From ac0bf6a4f4c07643472cb09d9915a21936f25943 Mon Sep 17 00:00:00 2001 From: Elijah Swift Date: Thu, 29 Feb 2024 16:56:22 -0500 Subject: [PATCH] Make changes to pass handle in python Make changes to pass handle in python Signed-off-by: Elijah Swift --- pyracf/common/irrsmo00.c | 35 ++++++------ pyracf/common/irrsmo00.py | 26 +++++++-- tests/common/test_irrsmo00_interface.py | 71 +++++++++++++++---------- 3 files changed, 84 insertions(+), 48 deletions(-) diff --git a/pyracf/common/irrsmo00.c b/pyracf/common/irrsmo00.c index ba31b1a..275a2ce 100644 --- a/pyracf/common/irrsmo00.c +++ b/pyracf/common/irrsmo00.c @@ -20,52 +20,56 @@ static PyObject *call_irrsmo00(PyObject *self, PyObject *args, PyObject *kwargs) const unsigned int request_xml_length; const unsigned int result_buffer_size; const unsigned int irrsmo00_options; + const char request_handle[64] = {0}; const char *running_userid; const uint8_t running_userid_length; static char *kwlist[] = { "request_xml", - "request_xml_length", + "request_xml_len", "result_buffer_size", "irrsmo00_options", + "handle", "running_userid", - "running_userid_length", + "running_userid_len", NULL}; if ( !PyArg_ParseTupleAndKeywords( args, kwargs, - "y|IIIyb", + "yIII|w*yb", kwlist, &request_xml, &request_xml_length, &result_buffer_size, &irrsmo00_options, + &request_handle, &running_userid, &running_userid_length)) { return NULL; } + PyObject * full_result; char work_area[1024]; - char req_handle[64] = {0}; running_userid_t running_userid_struct = {running_userid_length, {0}}; unsigned int alet = 0; unsigned int acee = 0; - unsigned char result_buffer[result_buffer_size]; + unsigned char * result_buffer = malloc(result_buffer_size); memset(result_buffer, 0, result_buffer_size); unsigned int saf_rc = 0; unsigned int racf_rc = 0; unsigned int racf_rsn = 0; + unsigned int result_len = result_buffer_size; unsigned int num_parms = 17; - unsigned int fn = 1; + unsigned int fn = 1; strncpy( running_userid_struct.running_userid, running_userid, running_userid_struct.running_userid_length); - + IRRSMO64( work_area, alet, @@ -79,12 +83,13 @@ static PyObject *call_irrsmo00(PyObject *self, PyObject *args, PyObject *kwargs) irrsmo00_options, request_xml_length, request_xml, - req_handle, + request_handle, running_userid_struct, acee, - result_buffer_size, + &result_len, result_buffer); + // https://docs.python.org/3/c-api/arg.html#c.Py_BuildValue // // According to the Python 3 C API documentation: @@ -122,12 +127,10 @@ static PyObject *call_irrsmo00(PyObject *self, PyObject *args, PyObject *kwargs) // Py_BuildValue() will return a Tuple. return Py_BuildValue( - "y#BBB", - result_buffer, - result_buffer_size, - saf_rc, - racf_rc, - racf_rsn); + "{s:y#,s:[B,B,B],s:w*}", + "resultBuffer", result_buffer, result_len, + "returnCodes", saf_rc, racf_rc, racf_rsn, + "handle", request_handle); } static char call_irrsmo00_docs[] = @@ -138,7 +141,7 @@ static char call_irrsmo00_docs[] = " irrsmo00_options: uint,\n" " running_userid: bytes,\n" " running_userid_length: uint,\n" - ") -> List[bytes,int,int,int]:\n" + ") -> Dict{ resultBuffers: List[bytes], returnCodes: List[int,int,int] }:\n" "# Returns an XML result string and return and reason " "codes from the IRRSMO00 RACF Callable Service.\n"; diff --git a/pyracf/common/irrsmo00.py b/pyracf/common/irrsmo00.py index 58198f4..afc3535 100644 --- a/pyracf/common/irrsmo00.py +++ b/pyracf/common/irrsmo00.py @@ -61,18 +61,34 @@ def call_racf( running_userid = run_as_userid.encode("cp1047") result = call_irrsmo00( request_xml=request_xml, - request_xml_length=len(request_xml), + request_xml_len=len(request_xml), result_buffer_size=self.__result_buffer_size, irrsmo00_options=irrsmo00_options, running_userid=running_userid, - running_userid_length=len(running_userid), + running_userid_len=len(running_userid), ) + if ( + (result["returnCodes"][0] == 8) + and (result["returnCodes"][1] == 4000) + and (result["returnCodes"][2] < 100000000) + ): + print(result) + result = call_irrsmo00( + request_xml=request_xml, + request_xml_len=len(request_xml), + result_buffer_size=result["returnCodes"][2], + irrsmo00_options=irrsmo00_options, + running_userid=running_userid, + running_userid_len=len(running_userid), + handle=result["handle"], + ) + print(result) # Preserve raw result XML just in case we need to create a dump. # If the decoded result XML cannot be parsed with the XML parser, # a dump may need to be taken to aid in problem determination. - self.__raw_result_xml = result[0] + self.__raw_result_xml = result["resultBuffer"] # Replace any null bytes in the result XML with spaces. - result_xml = self.__null_byte_fix(result[0]) + result_xml = self.__null_byte_fix(self.__raw_result_xml) # 'irrsmo00.c' returns a raw unmodified bytes object containing a copy # of the exact contents of the result xml buffer that the IRRSMO00 # callable service populates. @@ -88,5 +104,5 @@ def call_racf( # service was unable to process the request. in this case, would should # only return the return and reasons codes for error handling downstream. if result_xml_length == 0: - return list(result[1:4]) + return result["returnCodes"] return result_xml[:result_xml_length].decode("cp1047") diff --git a/tests/common/test_irrsmo00_interface.py b/tests/common/test_irrsmo00_interface.py index ccdd039..f1da958 100644 --- a/tests/common/test_irrsmo00_interface.py +++ b/tests/common/test_irrsmo00_interface.py @@ -56,7 +56,10 @@ def test_irrsmo00_null_byte_fix( 0, 0, 0, 0, 0, 0, ]) # fmt: on - call_irrsmo00_wrapper_mock.return_value = [xml_containing_null_bytes, 0, 0, 0] + call_irrsmo00_wrapper_mock.return_value = { + "resultBuffer": xml_containing_null_bytes, + "returnCodes": [0, 0, 0], + } self.assertEqual( self.irrsmo00.call_racf(b""), self.good_xml.decode("cp1047")[: self.good_xml_null_terminator_index], @@ -67,12 +70,10 @@ def test_irrsmo00_empty_result( call_irrsmo00_wrapper_mock: Mock, ): # Simulate failure due to incomplete 'IRR.IRRSMO00.PRECHECK' setup - call_irrsmo00_wrapper_mock.return_value = [ - bytes([0 for i in range(256)]), - 8, - 200, - 16, - ] + call_irrsmo00_wrapper_mock.return_value = { + "resultBuffer": bytes([0 for i in range(256)]), + "returnCodes": [8, 200, 16], + } self.assertEqual(self.irrsmo00.call_racf(b""), [8, 200, 16]) def test_irrsmo00_result_buffer_full_failure( @@ -80,7 +81,10 @@ def test_irrsmo00_result_buffer_full_failure( call_irrsmo00_wrapper_mock: Mock, ): # Simulate scenario where result buffer is too small. - call_irrsmo00_wrapper_mock.return_value = [self.good_xml[:32], 8, 4000, 32] + call_irrsmo00_wrapper_mock.return_value = { + "resultBuffer": self.good_xml[:32], + "returnCodes": [8, 4000, 100000000], + } self.assertEqual( self.irrsmo00.call_racf(b""), self.good_xml.decode("cp1047")[:32] ) @@ -90,19 +94,20 @@ def test_irrsmo00_result_buffer_full_success( call_irrsmo00_wrapper_mock: Mock, ): # Simulate scenario where result buffer is exactly the right size. - call_irrsmo00_wrapper_mock.return_value = [ - self.good_xml[: self.good_xml_null_terminator_index], - 0, - 0, - 0, - ] + call_irrsmo00_wrapper_mock.return_value = { + "resultBuffer": self.good_xml[: self.good_xml_null_terminator_index], + "returnCodes": [0, 0, 0], + } self.assertEqual( self.irrsmo00.call_racf(b""), self.good_xml.decode("cp1047")[: self.good_xml_null_terminator_index], ) def test_irrsmo00_normal_result(self, call_irrsmo00_wrapper_mock: Mock): - call_irrsmo00_wrapper_mock.return_value = [self.good_xml, 0, 0, 0] + call_irrsmo00_wrapper_mock.return_value = { + "resultBuffer": self.good_xml, + "returnCodes": [0, 0, 0], + } self.assertEqual( self.irrsmo00.call_racf(b""), self.good_xml.decode("cp1047")[: self.good_xml_null_terminator_index], @@ -112,52 +117,64 @@ def test_irrsmo00_normal_result(self, call_irrsmo00_wrapper_mock: Mock): # Test IRRSMO00 Argument Construction # ============================================================================ def test_irrsmo00_minimum_arguments(self, call_irrsmo00_wrapper_mock: Mock): - call_irrsmo00_wrapper_mock.return_value = [self.good_xml, 0, 0, 0] + call_irrsmo00_wrapper_mock.return_value = { + "resultBuffer": self.good_xml, + "returnCodes": [0, 0, 0], + } self.irrsmo00.call_racf(b"some bytes") call_irrsmo00_wrapper_mock.assert_called_with( request_xml=b"some bytes", - request_xml_length=10, + request_xml_len=10, result_buffer_size=16384, irrsmo00_options=13, running_userid=b"", - running_userid_length=0, + running_userid_len=0, ) def test_irrsmo00_with_precheck_set_to_true(self, call_irrsmo00_wrapper_mock: Mock): - call_irrsmo00_wrapper_mock.return_value = [self.good_xml, 0, 0, 0] + call_irrsmo00_wrapper_mock.return_value = { + "resultBuffer": self.good_xml, + "returnCodes": [0, 0, 0], + } self.irrsmo00.call_racf(b"some bytes", precheck=True) call_irrsmo00_wrapper_mock.assert_called_with( request_xml=b"some bytes", - request_xml_length=10, + request_xml_len=10, result_buffer_size=16384, irrsmo00_options=15, running_userid=b"", - running_userid_length=0, + running_userid_len=0, ) def test_irrsmo00_with_run_as_userid_set(self, call_irrsmo00_wrapper_mock: Mock): - call_irrsmo00_wrapper_mock.return_value = [self.good_xml, 0, 0, 0] + call_irrsmo00_wrapper_mock.return_value = { + "resultBuffer": self.good_xml, + "returnCodes": [0, 0, 0], + } self.irrsmo00.call_racf(b"some bytes", run_as_userid="KRABS") call_irrsmo00_wrapper_mock.assert_called_with( request_xml=b"some bytes", - request_xml_length=10, + request_xml_len=10, result_buffer_size=16384, irrsmo00_options=13, running_userid=b"\xd2\xd9\xc1\xc2\xe2", - running_userid_length=5, + running_userid_len=5, ) def test_irrsmo00_with_custom_result_buffer_size( self, call_irrsmo00_wrapper_mock: Mock ): - call_irrsmo00_wrapper_mock.return_value = [self.good_xml, 0, 0, 0] + call_irrsmo00_wrapper_mock.return_value = { + "resultBuffer": self.good_xml, + "returnCodes": [0, 0, 0], + } irrsmo00 = IRRSMO00(result_buffer_size=32768) irrsmo00.call_racf(b"some bytes") call_irrsmo00_wrapper_mock.assert_called_with( request_xml=b"some bytes", - request_xml_length=10, + request_xml_len=10, result_buffer_size=32768, irrsmo00_options=13, running_userid=b"", - running_userid_length=0, + running_userid_len=0, )