OpenKMIP / PyKMIP

A Python implementation of the KMIP specification.
Apache License 2.0
263 stars 132 forks source link

query_server_information fails on SafeNet server #100

Closed wew036 closed 8 years ago

wew036 commented 9 years ago

I got the following problem when calling this command on SafeNet. This happened only on the QUERY_SERVERINFORMATION command, but worked on other QUERY* commands. Does it mean SafeNet sent 24 extra bytes?

Traceback (most recent call last): File "query.py", line 114, in username=opts.username, password=opts.password) File "query.py", line 59, in query result = client.query(query_functions=query_functions) File "/media/Data/wenguangw/work/encryption/pykmip/kmip/services/kmip_client.py", line 355, in query response = self._send_and_receive_message(request) File "/media/Data/wenguangw/work/encryption/pykmip/kmip/services/kmip_client.py", line 838, in _send_and_receive_message response.read(data) File "/media/Data/wenguangw/work/encryption/pykmip/kmip/core/messages/messages.py", line 387, in read batch_item.read(istream) File "/media/Data/wenguangw/work/encryption/pykmip/kmip/core/messages/messages.py", line 296, in read self.response_payload.read(tstream) File "/media/Data/wenguangw/work/encryption/pykmip/kmip/core/messages/payloads/query.py", line 225, in read self.is_oversized(tstream) File "/media/Data/wenguangw/work/encryption/pykmip/kmip/core/primitives.py", line 47, in is_oversized raise errors.StreamNotEmptyError(Base.name, extra) kmip.core.errors.StreamNotEmptyError: Invalid length used to read Base, bytes remaining: 24

If I comment out the error checking which raised the exception, I got this:

2015-10-10 09:54:51,993 - main - INFO - query() result status: ResultStatus.SUCCESS 2015-10-10 09:54:51,993 - main - INFO - number of operations supported: 0 2015-10-10 09:54:51,994 - main - INFO - number of object types supported: 0 2015-10-10 09:54:51,994 - main - INFO - vendor identification: None 2015-10-10 09:54:51,994 - main - INFO - server information: 541000070000000e4b657953656375726520313530760000541001070000000d4b4e554357374b4358594432450000005410020700000006382e312e30200000 2015-10-10 09:54:51,994 - main - INFO - number of application namespaces supported: 0 2015-10-10 09:54:51,994 - main - INFO - number of extensions supported: 0

The weird server information can be converted to (using http://www.rapidtables.com/convert/number/hex-to-ascii.htm):

TKeySecure 150vT KNUCW7KCXYD2ET8.1.0

In what way might the SafeNet server be violating the KMIP protocol? Is there an easy way to work around this from PyKMIP?

PeterHamilton commented 9 years ago

Hi wew036, thanks for filing this issue. From the stacktrace you posted, it does look like the server is sending back too much data (the 24 extra bytes mentioned). By other QUERY_* commands, you're referring to making specific Query requests for other information, like the set of supported operations or KMIP object types, correct? And those requests work properly? If the answer to both of those questions is YES, than it does look like the encoding for just the server information data is being sent incorrectly.

The only way for me to be sure is to look at the encoding (the response bytes) actually received by the client. You can enable debug logging by changing the INFO values in kmip/logconfig.ini to DEBUG. Debug logging should display the bytes sent and received by the client to the CLI.

If you're ok with sending me the encoding, I only need the portion starting with the following byte sequence: 42000f. That starts the actual Query operation response, which will include the server information encoding. I should be able to figure out what extra data the server is sending and, ultimately, whether or not this is a bug with PyKMIP or with the server data.

wew036 commented 9 years ago

Yes, by QUERY_* commands, I mean the QUERY_OPERATIONS, QUERY_OBJECTS, QUERY_APPLICATION_NAMESPACES, QUERY_EXTENSION_LIST, QUERY_EXTENSION_MAP commands in kmip/demos/units/query.py. I tried them one-by-one, and they all work except the QUERY_SERVER_INFORMATION.

There is no byte sequence 42000f, but here are the closest match:

2015-10-10 16:15:03,901 - kmip.services.kmip_protocol - DEBUG - KMIPProtocol.write: 42007801000000b84200770100000080420069010000002042006a0200000004000000010000000042006b0200000004000000010000000042000c01000000404200230100000038420024050000000400000001000000004200250100000020420099070000000474657374000000004200a10700000008746535743132332142000d0200000004000000010000000042000f010000002842005c05000000040000001800000000420079010000001042007405000000040000000300000000 2015-10-10 16:15:03,906 - kmip.services.kmip_protocol - DEBUG - KMIPProtocol.read: 42007b01000000e042007a0100000048420069010000002042006a0200000004000000010000000042006b020000000400000001000000004200920900000008000000005621734642000d0200000004000000010000000042000f010000008842005c0500000004000000180000000042007f0500000004000000000000000042007c01000000604200880100000040541000070000000e4b657953656375726520313530760000541001070000000d4b4e554357374b4358594432450000005410020700000006382e312e3020000042009d070000000d536166654e65742c20496e632e000000

PeterHamilton commented 9 years ago

Ok, I've figured out what's going wrong here. The SafeNet server is sending back two pieces of information when you make a QUERY_SERVER_INFORMATION request: the server information string itself (which you listed above in your initial post) and a vendor identification string (which turns out here to just be: SafeNet, Inc.). This is expected behavior. For this case, both pieces of data are encoded in UTF-8, which is also expected. (Note: there's a minor issue with how the server information string itself is encoded but it isn't causing the error we're dealing with here).

This is the real issue. The KMIP spec dictates that the vendor identification string should be encoded before the server information data in the response payload, but SafeNet is encoding it after the server information data. The PyKMIP client strictly follows the spec and checks for vendor identification data before checking for server information data. As a result, the client reaches the 24 bytes of vendor identification data after decoding the server information and sees it as extra, unexpected information associated with the server information data block and breaks.

TL;DR This is a problem with the SafeNet appliance not strictly following the KMIP spec when encoding the server information and vendor identification data in the response payload for a QUERY_SERVER_INFORMATION request.