]> granicus.if.org Git - p11-kit/commitdiff
proxy: Support C_WaitForSlotEvent() if CKF_DONT_BLOCK is specified
authorDaiki Ueno <dueno@redhat.com>
Thu, 16 May 2019 14:52:37 +0000 (16:52 +0200)
committerDaiki Ueno <ueno@gnu.org>
Tue, 21 May 2019 06:07:12 +0000 (08:07 +0200)
While fully implementing C_WaitForSlotEvent() would require a separate
thread to monitor events, it is straightforward to implement the
function if the CKF_DONT_BLOCK flag is given.

Suggested by David Ward.

p11-kit/Makefile.am
p11-kit/mock-module-ep7.c [new file with mode: 0644]
p11-kit/proxy.c
p11-kit/test-proxy.c

index 0155f7c58a742b582c46d6ce0927b1ed8bb3f920..09a068ef479127e49bcaa8e4baa40f7f06aff8ae 100644 (file)
@@ -409,7 +409,8 @@ check_LTLIBRARIES += \
        mock-four.la \
        mock-five.la \
        mock-seven.la \
-       mock-eight.la
+       mock-eight.la \
+       mock-nine.la
 
 mock_one_la_SOURCES = p11-kit/mock-module-ep.c
 mock_one_la_LIBADD = libp11-test.la libp11-common.la
@@ -448,6 +449,10 @@ mock_eight_la_SOURCES = p11-kit/mock-module-ep6.c
 mock_eight_la_LDFLAGS = $(mock_one_la_LDFLAGS)
 mock_eight_la_LIBADD = $(mock_one_la_LIBADD)
 
+mock_nine_la_SOURCES = p11-kit/mock-module-ep7.c
+mock_nine_la_LDFLAGS = $(mock_one_la_LDFLAGS)
+mock_nine_la_LIBADD = $(mock_one_la_LIBADD)
+
 EXTRA_DIST += \
        p11-kit/fixtures \
        p11-kit/test-mock.c \
diff --git a/p11-kit/mock-module-ep7.c b/p11-kit/mock-module-ep7.c
new file mode 100644 (file)
index 0000000..51fad06
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2012 Stefan Walter
+ * Copyright (c) 2019 Red Hat, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *     * Redistributions of source code must retain the above
+ *       copyright notice, this list of conditions and the
+ *       following disclaimer.
+ *     * Redistributions in binary form must reproduce the
+ *       above copyright notice, this list of conditions and
+ *       the following disclaimer in the documentation and/or
+ *       other materials provided with the distribution.
+ *     * The names of contributors to this software may not be
+ *       used to endorse or promote products derived from this
+ *       software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Author: Stef Walter <stef@thewalter.net>, Daiki Ueno
+ */
+
+#include "config.h"
+
+#define CRYPTOKI_EXPORTS 1
+#include "pkcs11.h"
+
+#include "mock.h"
+#include "test.h"
+
+static CK_RV
+override_wait_for_slot_event (CK_FLAGS flags,
+                             CK_SLOT_ID_PTR slot,
+                             CK_VOID_PTR reserved)
+{
+       if (flags & CKF_DONT_BLOCK) {
+               *slot = MOCK_SLOT_ONE_ID;
+               return CKR_OK;
+       }
+
+       return mock_C_WaitForSlotEvent(flags, slot, reserved);
+}
+
+#ifdef OS_WIN32
+__declspec(dllexport)
+#endif
+CK_RV
+C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list)
+{
+       mock_module_init ();
+       mock_module.C_GetFunctionList = C_GetFunctionList;
+       if (list == NULL)
+               return CKR_ARGUMENTS_BAD;
+       mock_module.C_WaitForSlotEvent = override_wait_for_slot_event;
+       *list = &mock_module;
+       return CKR_OK;
+}
index ae8831863880cdacc19ca55b1de61fe368012078..a9c7055d7033f99196df44c349ac71bd2f8faaa5 100644 (file)
@@ -604,7 +604,40 @@ proxy_C_WaitForSlotEvent (CK_X_FUNCTION_LIST *self,
                           CK_SLOT_ID_PTR slot,
                           CK_VOID_PTR reserved)
 {
-       return CKR_FUNCTION_NOT_SUPPORTED;
+       State *state = (State *)self;
+       Proxy *py = state->px;
+       CK_FUNCTION_LIST_PTR *f;
+       CK_FUNCTION_LIST_PTR funcs;
+       CK_SLOT_ID real_slot;
+       unsigned int i;
+       CK_RV rv = CKR_NO_EVENT;
+
+       /* Only the non-blocking case is supported. */
+       if ((flags & CKF_DONT_BLOCK) == 0)
+               return CKR_FUNCTION_NOT_SUPPORTED;
+
+       p11_lock ();
+
+       for (f = py->inited; *f; ++f) {
+               funcs = *f;
+               assert (funcs != NULL);
+
+               rv = (funcs->C_WaitForSlotEvent) (flags, &real_slot, reserved);
+               if (rv == CKR_NO_EVENT)
+                       continue;
+               if (rv != CKR_OK)
+                       break;
+               for (i = 0; i < py->n_mappings; i++)
+                       if (py->mappings[i].funcs == funcs &&
+                           py->mappings[i].real_slot == real_slot) {
+                               *slot = py->mappings[i].wrap_slot;
+                               break;
+                       }
+       }
+
+       p11_unlock ();
+
+       return rv;
 }
 
 static CK_RV
@@ -1617,14 +1650,6 @@ proxy_C_GenerateRandom (CK_X_FUNCTION_LIST *self,
        return (map.funcs->C_GenerateRandom) (handle, random_data, random_len);
 }
 
-static CK_RV
-module_C_WaitForSlotEvent (CK_FLAGS flags,
-                           CK_SLOT_ID_PTR slot,
-                           CK_VOID_PTR reserved)
-{
-       return proxy_C_WaitForSlotEvent (&global.virt.funcs, flags, slot, reserved);
-}
-
 /* --------------------------------------------------------------------
  * MODULE ENTRY POINT
  */
@@ -1737,11 +1762,8 @@ C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list)
                }
        }
 
-       if (rv == CKR_OK) {
-               /* We use this as a check below */
-               module->C_WaitForSlotEvent = module_C_WaitForSlotEvent;
+       if (rv == CKR_OK)
                *list = module;
-       }
 
        if (loaded)
                p11_kit_modules_release (loaded);
@@ -1769,7 +1791,21 @@ p11_proxy_module_cleanup (void)
 bool
 p11_proxy_module_check (CK_FUNCTION_LIST_PTR module)
 {
-       return (module->C_WaitForSlotEvent == module_C_WaitForSlotEvent);
+       State *state;
+       bool ret = false;
+
+       if (!p11_virtual_is_wrapper (module))
+               return false;
+
+       p11_lock ();
+       for (state = all_instances; state != NULL; state = state->next)
+               if (state->wrapped == module) {
+                       ret = true;
+                       break;
+               }
+       p11_unlock ();
+
+       return ret;
 }
 
 CK_RV
index f61f37e188866423a2b6096d794f5ec2f6e09374..9a8f71deca9e8b87437253b8df774da01dae37f3 100644 (file)
@@ -234,6 +234,7 @@ teardown (void *unused)
 #define ENABLED "enable-in: test-proxy, p11-kit-proxy\n"
 #define DISABLED "disable-in: p11-kit-proxy\n"
 #define EIGHT_MODULE "module: mock-eight" SHLEXT "\n"
+#define NINE_MODULE "module: mock-nine" SHLEXT "\n"
 
 static CK_ULONG
 load_modules_and_count_slots (void)
@@ -343,6 +344,44 @@ test_slot_appear (void)
        p11_proxy_module_cleanup ();
 }
 
+static void
+test_slot_event (void)
+{
+       CK_FUNCTION_LIST_PTR proxy;
+       CK_SLOT_ID slot;
+       CK_SLOT_ID slots[32];
+       CK_ULONG count;
+       CK_RV rv;
+
+       p11_test_file_write (test.directory, "nine.module", NINE_MODULE, strlen (NINE_MODULE));
+
+       rv = C_GetFunctionList (&proxy);
+       assert (rv == CKR_OK);
+
+       assert (p11_proxy_module_check (proxy));
+
+       rv = proxy->C_Initialize (NULL);
+       assert (rv == CKR_OK);
+
+       rv = proxy->C_GetSlotList (CK_FALSE, slots, &count);
+       assert (rv == CKR_OK);
+       assert (count == 2);
+
+       slot = 0;
+       rv = proxy->C_WaitForSlotEvent (0, &slot, NULL);
+       assert_num_eq (rv, CKR_FUNCTION_NOT_SUPPORTED);
+       assert_num_eq (slot, 0);
+
+       rv = proxy->C_WaitForSlotEvent (CKF_DONT_BLOCK, &slot, NULL);
+       assert_num_eq (rv, CKR_OK);
+       assert_num_eq (slot, slots[0]);
+
+       rv = proxy->C_Finalize (NULL);
+       assert_num_eq (rv, CKR_OK);
+
+       p11_proxy_module_cleanup ();
+}
+
 static CK_FUNCTION_LIST_PTR
 setup_mock_module (CK_SESSION_HANDLE *session)
 {
@@ -430,6 +469,7 @@ main (int argc,
        p11_test (test_disable, "/proxy/disable");
        p11_test (test_no_slot, "/proxy/no-slot");
        p11_test (test_slot_appear, "/proxy/slot-appear");
+       p11_test (test_slot_event, "/proxy/slot-event");
 
        test_mock_add_tests ("/proxy");