From: Vincent JARDIN Date: Mon, 21 Oct 2019 21:20:37 +0000 (+0200) Subject: Fix C_GetSlotList() when length is 0 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1ede9b8d33c4bc9a4194ffca22ac6d7351f6bcf5;p=p11-kit Fix C_GetSlotList() when length is 0 Let's add a support for cases when the buffer != NULL but the length is 0. According to Oasis, buffer = NULL and length = 0 means a query of the length so the subsequent calls with a buffer != NULL should fill buffer when length is long enough. If not, according to Oasis, one should get a CKR_BUFFER_TOO_SMALL. This current fix is for IN_ULONG_BUFFER(), same should be applied for IN_BYTE_BUFFER() and for IN_ATTRIBUTE_BUFFER(). Include a test_no_slots() Fix: issue #257 Suggested-by: Daiki Ueno --- diff --git a/p11-kit/rpc-client.c b/p11-kit/rpc-client.c index e202e37..7d7c281 100644 --- a/p11-kit/rpc-client.c +++ b/p11-kit/rpc-client.c @@ -582,7 +582,7 @@ proto_read_sesssion_info (p11_rpc_message *msg, #define IN_ULONG_BUFFER(arr, len) \ if (len == NULL) \ { _ret = CKR_ARGUMENTS_BAD; goto _cleanup; } \ - if (!p11_rpc_message_write_ulong_buffer (&_msg, arr ? *len : 0)) \ + if (!p11_rpc_message_write_ulong_buffer (&_msg, arr, len)) \ { _ret = CKR_HOST_MEMORY; goto _cleanup; } #define IN_ULONG_ARRAY(arr, len) \ diff --git a/p11-kit/rpc-message.c b/p11-kit/rpc-message.c index 672d1c7..95bf6ce 100644 --- a/p11-kit/rpc-message.c +++ b/p11-kit/rpc-message.c @@ -372,14 +372,16 @@ p11_rpc_message_write_byte_array (p11_rpc_message *msg, bool p11_rpc_message_write_ulong_buffer (p11_rpc_message *msg, - CK_ULONG count) + CK_ULONG_PTR array, + CK_ULONG_PTR n_array) { assert (msg != NULL); assert (msg->output != NULL); /* Make sure this is in the right order */ assert (!msg->signature || p11_rpc_message_verify_part (msg, "fu")); - p11_rpc_buffer_add_uint32 (msg->output, count); + p11_rpc_buffer_add_byte (msg->output, array ? 0 : 1); + p11_rpc_buffer_add_uint32 (msg->output, *n_array); return !p11_buffer_failed (msg->output); } diff --git a/p11-kit/rpc-message.h b/p11-kit/rpc-message.h index 989bbc0..9e1fe0f 100644 --- a/p11-kit/rpc-message.h +++ b/p11-kit/rpc-message.h @@ -286,7 +286,8 @@ bool p11_rpc_message_write_byte_array (p11_rpc_message *msg, CK_ULONG num); bool p11_rpc_message_write_ulong_buffer (p11_rpc_message *msg, - CK_ULONG count); + CK_ULONG_PTR array, + CK_ULONG_PTR n_array); bool p11_rpc_message_write_ulong_array (p11_rpc_message *msg, CK_ULONG_PTR arr, diff --git a/p11-kit/rpc-server.c b/p11-kit/rpc-server.c index 846ee94..37c2c54 100644 --- a/p11-kit/rpc-server.c +++ b/p11-kit/rpc-server.c @@ -166,6 +166,7 @@ proto_read_ulong_buffer (p11_rpc_message *msg, CK_ULONG *n_buffer) { uint32_t length; + uint8_t buffer_is_null; assert (msg != NULL); assert (buffer != NULL); @@ -175,6 +176,8 @@ proto_read_ulong_buffer (p11_rpc_message *msg, /* Check that we're supposed to be reading this at this point */ assert (!msg->signature || p11_rpc_message_verify_part (msg, "fu")); + if (!p11_rpc_buffer_get_byte (msg->input, &msg->parsed, &buffer_is_null)) + return PARSE_ERROR; /* The number of ulongs there's room for on the other end */ if (!p11_rpc_buffer_get_uint32 (msg->input, &msg->parsed, &length)) return PARSE_ERROR; @@ -182,8 +185,8 @@ proto_read_ulong_buffer (p11_rpc_message *msg, *n_buffer = length; *buffer = NULL; - /* If set to zero, then they just want the length */ - if (length == 0) + /* If buffer is NULL, the caller just wants the length */ + if (buffer_is_null) return CKR_OK; *buffer = p11_rpc_message_alloc_extra (msg, length * sizeof (CK_ULONG)); diff --git a/p11-kit/test-server.c b/p11-kit/test-server.c index a1fbcb7..a820f15 100644 --- a/p11-kit/test-server.c +++ b/p11-kit/test-server.c @@ -264,6 +264,36 @@ test_open_session_write_protected (void *unused) p11_kit_module_release (module); } +static void +test_no_slots (void *unused) +{ + CK_FUNCTION_LIST_PTR module; + CK_SLOT_ID slots[32]; + CK_ULONG count; + CK_RV rv; + + module = p11_kit_module_load (P11_MODULE_PATH "/p11-kit-client" SHLEXT, 0); + assert (module != NULL); + + rv = p11_kit_module_initialize (module); + assert (rv == CKR_OK); + + count = 0; + rv = module->C_GetSlotList (CK_TRUE, NULL, &count); + assert (rv == CKR_OK); + assert_num_eq (0, count); + + count = 0; + rv = module->C_GetSlotList (CK_TRUE, slots, &count); + assert (rv == CKR_OK); + assert_num_eq (0, count); + + rv = p11_kit_module_finalize (module); + assert (rv == CKR_OK); + + p11_kit_module_release (module); +} + int main (int argc, char *argv[]) @@ -283,6 +313,11 @@ main (int argc, "pkcs11:?write-protected=yes", 1 }; + struct fixture with_no_slots = { + P11_MODULE_PATH "/mock-eight" SHLEXT, + "pkcs11:", + 0 + }; p11_library_init (); mock_module_init (); @@ -296,6 +331,7 @@ main (int argc, p11_testx (test_initialize, (void *)&without_provider, "/server/all/initialize"); p11_testx (test_initialize_no_address, (void *)&without_provider, "/server/all/initialize-no-address"); p11_testx (test_open_session, (void *)&without_provider, "/server/all/open-session"); + p11_testx (test_no_slots, (void *)&with_no_slots, "/server/no-slots"); return p11_test_run (argc, argv); }