From 0c7eaa3b6513902c897d582905a8077daefb73b3 Mon Sep 17 00:00:00 2001 From: Martin Gallo Date: Fri, 10 Jul 2026 13:57:27 -0300 Subject: [PATCH 1/2] Fixed Python3 bytes/str issue on HDB --- pysap/SAPHDB.py | 9 ++++--- tests/saphdb_test.py | 64 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 66 insertions(+), 7 deletions(-) diff --git a/pysap/SAPHDB.py b/pysap/SAPHDB.py index 72b94bd..eefbe34 100644 --- a/pysap/SAPHDB.py +++ b/pysap/SAPHDB.py @@ -1024,7 +1024,10 @@ def __init__(self, username, session_cookie): self.session_cookie = session_cookie def craft_authentication_request(self, value=None, connection=None): - return super(SAPHDBAuthSessionCookieMethod, self).craft_authentication_request(self.session_cookie + connection.client_id, + client_id = connection.client_id + if isinstance(self.session_cookie, bytes) and isinstance(client_id, str): + client_id = client_id.encode() + return super(SAPHDBAuthSessionCookieMethod, self).craft_authentication_request(self.session_cookie + client_id, connection) @@ -1213,7 +1216,7 @@ def process_connect_response(self, connect_reponse, connection=None): # * commtype: communication type ("\x07") # * session cookie: the SessionCookie established for the connection gss_token = SAPHDBPartAuthentication(self.session_cookie) - if gss_token.auth_fields[1].value == "\x07": + if gss_token.auth_fields[1].value in ("\x07", b"\x07"): self.session_cookie = gss_token.auth_fields[2].value else: self.session_cookie = None @@ -1348,7 +1351,7 @@ def recv(self): header_raw = self._stream_socket.ins.recv(32) header = SAPHDB(header_raw) # Then get the payload - payload = "" + payload = b"" if header.varpartlength > 0: payload = self._stream_socket.ins.recv(header.varpartlength) # And finally construct the whole packet with header plus payload diff --git a/tests/saphdb_test.py b/tests/saphdb_test.py index 6a89d53..a1a2c52 100755 --- a/tests/saphdb_test.py +++ b/tests/saphdb_test.py @@ -24,10 +24,10 @@ # External imports import pytest # Custom imports -from pysap.SAPHDB import SAPHDBConnection - - -pytestmark = pytest.mark.integration +from pysap.SAPHDB import (SAPHDB, SAPHDBAuthGSSMethod, + SAPHDBAuthSessionCookieMethod, SAPHDBConnection, + SAPHDBPart, SAPHDBPartAuthentication, + SAPHDBPartAuthenticationField, SAPHDBSegment) class SAPHDBServerTestHandler(BaseRequestHandler): @@ -38,6 +38,7 @@ def handle(self): self.request.send(b"\x00" * 8) +@pytest.mark.integration class PySAPHDBConnectionTest(unittest.TestCase): test_port = 30017 @@ -70,6 +71,61 @@ def test_saphdbconnection_initialize(self): self.stop_server() +class _FakeInputSocket(object): + def __init__(self, responses): + self.responses = list(responses) + + def recv(self, size): + return self.responses.pop(0) + + +class _FakeStreamSocket(object): + def __init__(self, responses): + self.ins = _FakeInputSocket(responses) + + +def test_saphdb_recv_accepts_zero_length_varpart(): + header = bytes(SAPHDB(varpartlength=0, noofsegm=0, segments=[])) + connection = SAPHDBConnection("127.0.0.1", 30015) + connection._stream_socket = _FakeStreamSocket([header]) + + packet = connection.recv() + + assert packet.varpartlength == 0 + assert packet.noofsegm == 0 + + +def test_session_cookie_auth_request_accepts_byte_cookie(): + connection = SAPHDBConnection("127.0.0.1", 30015, + pid="123", hostname="hana-client") + auth_method = SAPHDBAuthSessionCookieMethod("SYSTEM", b"cookie-") + + request = auth_method.craft_authentication_request(connection=connection) + auth_part = request.segments[0].parts[1].buffer[0] + + assert auth_part.auth_fields[2].value == b"cookie-123@hana-client" + + +def test_gss_connect_response_accepts_byte_session_cookie_marker(): + gss_cookie = SAPHDBPartAuthentication(auth_fields=[ + SAPHDBPartAuthenticationField(value=b"1.2.840.113554.1.2.2"), + SAPHDBPartAuthenticationField(value=b"\x07"), + SAPHDBPartAuthenticationField(value=b"session-cookie"), + ]) + auth_payload = SAPHDBPartAuthentication(auth_fields=[ + SAPHDBPartAuthenticationField(value=b"GSS"), + SAPHDBPartAuthenticationField(value=bytes(gss_cookie)), + ]) + connect_response = SAPHDB(segments=[SAPHDBSegment(segmentkind=2, parts=[ + SAPHDBPart(partkind=33, argumentcount=1, buffer=auth_payload), + ])]) + + auth_method = SAPHDBAuthGSSMethod("SYSTEM") + auth_method.process_connect_response(connect_response) + + assert auth_method.session_cookie == b"session-cookie" + + def suite(): loader = unittest.TestLoader() suite = unittest.TestSuite() From e7929820c36dedb1f871a56db0cc09047c2e842e Mon Sep 17 00:00:00 2001 From: Martin Gallo Date: Fri, 10 Jul 2026 14:02:30 -0300 Subject: [PATCH 2/2] Moved to a test class --- tests/saphdb_test.py | 63 ++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/tests/saphdb_test.py b/tests/saphdb_test.py index a1a2c52..60a9cca 100755 --- a/tests/saphdb_test.py +++ b/tests/saphdb_test.py @@ -84,52 +84,53 @@ def __init__(self, responses): self.ins = _FakeInputSocket(responses) -def test_saphdb_recv_accepts_zero_length_varpart(): - header = bytes(SAPHDB(varpartlength=0, noofsegm=0, segments=[])) - connection = SAPHDBConnection("127.0.0.1", 30015) - connection._stream_socket = _FakeStreamSocket([header]) +class PySAPHDBPython3Test(unittest.TestCase): - packet = connection.recv() + def test_saphdb_recv_accepts_zero_length_varpart(self): + header = bytes(SAPHDB(varpartlength=0, noofsegm=0, segments=[])) + connection = SAPHDBConnection("127.0.0.1", 30015) + connection._stream_socket = _FakeStreamSocket([header]) - assert packet.varpartlength == 0 - assert packet.noofsegm == 0 + packet = connection.recv() + self.assertEqual(packet.varpartlength, 0) + self.assertEqual(packet.noofsegm, 0) -def test_session_cookie_auth_request_accepts_byte_cookie(): - connection = SAPHDBConnection("127.0.0.1", 30015, - pid="123", hostname="hana-client") - auth_method = SAPHDBAuthSessionCookieMethod("SYSTEM", b"cookie-") + def test_session_cookie_auth_request_accepts_byte_cookie(self): + connection = SAPHDBConnection("127.0.0.1", 30015, + pid="123", hostname="hana-client") + auth_method = SAPHDBAuthSessionCookieMethod("SYSTEM", b"cookie-") - request = auth_method.craft_authentication_request(connection=connection) - auth_part = request.segments[0].parts[1].buffer[0] + request = auth_method.craft_authentication_request(connection=connection) + auth_part = request.segments[0].parts[1].buffer[0] - assert auth_part.auth_fields[2].value == b"cookie-123@hana-client" + self.assertEqual(auth_part.auth_fields[2].value, b"cookie-123@hana-client") + def test_gss_connect_response_accepts_byte_session_cookie_marker(self): + gss_cookie = SAPHDBPartAuthentication(auth_fields=[ + SAPHDBPartAuthenticationField(value=b"1.2.840.113554.1.2.2"), + SAPHDBPartAuthenticationField(value=b"\x07"), + SAPHDBPartAuthenticationField(value=b"session-cookie"), + ]) + auth_payload = SAPHDBPartAuthentication(auth_fields=[ + SAPHDBPartAuthenticationField(value=b"GSS"), + SAPHDBPartAuthenticationField(value=bytes(gss_cookie)), + ]) + connect_response = SAPHDB(segments=[SAPHDBSegment(segmentkind=2, parts=[ + SAPHDBPart(partkind=33, argumentcount=1, buffer=auth_payload), + ])]) -def test_gss_connect_response_accepts_byte_session_cookie_marker(): - gss_cookie = SAPHDBPartAuthentication(auth_fields=[ - SAPHDBPartAuthenticationField(value=b"1.2.840.113554.1.2.2"), - SAPHDBPartAuthenticationField(value=b"\x07"), - SAPHDBPartAuthenticationField(value=b"session-cookie"), - ]) - auth_payload = SAPHDBPartAuthentication(auth_fields=[ - SAPHDBPartAuthenticationField(value=b"GSS"), - SAPHDBPartAuthenticationField(value=bytes(gss_cookie)), - ]) - connect_response = SAPHDB(segments=[SAPHDBSegment(segmentkind=2, parts=[ - SAPHDBPart(partkind=33, argumentcount=1, buffer=auth_payload), - ])]) + auth_method = SAPHDBAuthGSSMethod("SYSTEM") + auth_method.process_connect_response(connect_response) - auth_method = SAPHDBAuthGSSMethod("SYSTEM") - auth_method.process_connect_response(connect_response) - - assert auth_method.session_cookie == b"session-cookie" + self.assertEqual(auth_method.session_cookie, b"session-cookie") def suite(): loader = unittest.TestLoader() suite = unittest.TestSuite() suite.addTest(loader.loadTestsFromTestCase(PySAPHDBConnectionTest)) + suite.addTest(loader.loadTestsFromTestCase(PySAPHDBPython3Test)) return suite