]> granicus.if.org Git - p11-kit/commitdiff
trust: Make each configured path its own token
authorStef Walter <stefw@gnome.org>
Wed, 6 Mar 2013 18:16:09 +0000 (19:16 +0100)
committerStef Walter <stefw@gnome.org>
Fri, 15 Mar 2013 16:25:17 +0000 (17:25 +0100)
 * Each source directory or file configured into the module or passed
   in as an initialization argument becomes its own token.
   Previously there was one token that contained certificates from
   all the configured paths.
 * These tokens are clearly labeled in the token info as
   to the directory or file that they represent.
 * Update PKCS#11 module logic to deal with multiple tokens, validate
   the slot ids and so on.
 * The order in which the paths are configured will become the
   order of trust priority. This is the same order in which they
   are listed through 'p11-kit list-modules' and C_GetSlotList.
 * Update the frob-token internal tool to only play with one path
 * Adjust tests where necessary to reflect the new state of things
   and add tests for modified trust module code

https://bugs.freedesktop.org/show_bug.cgi?id=61499

trust/module.c
trust/tests/frob-token.c
trust/tests/test-module.c
trust/tests/test-session.c
trust/tests/test-token.c
trust/token.c
trust/token.h

index 5ac018e5c24a4c64838af55591811ff4ec2a948f..a39c204ab9988210507f83df5d347c51d960d386 100644 (file)
 
 #define CRYPTOKI_EXPORTS
 
+#include "array.h"
 #include "attrs.h"
 #define P11_DEBUG_FLAG P11_DEBUG_TRUST
 #include "debug.h"
 #include "dict.h"
 #include "library.h"
 #include "module.h"
+#include "parser.h"
 #include "pkcs11.h"
 #include "session.h"
 #include "token.h"
 
 #define MANUFACTURER_ID         "PKCS#11 Kit                     "
 #define LIBRARY_DESCRIPTION     "PKCS#11 Kit Trust Module        "
-#define SLOT_DESCRIPTION        "System Certificates, Trust Anchors, and Black Lists             "
 #define TOKEN_LABEL             "System Trust Anchors and Policy "
 #define TOKEN_MODEL             "PKCS#11 Kit      "
 #define TOKEN_SERIAL_NUMBER     "1                "
 
-/* Arbitrary non-zero and non-one choice */
-#define SYSTEM_SLOT_ID   18UL
+/* Initial slot id: non-zero and non-one */
+#define BASE_SLOT_ID   18UL
 
 static struct _Shared {
        p11_dict *sessions;
-       p11_token *token;
+       p11_array *tokens;
        char *paths;
 } gl = { NULL, NULL };
 
@@ -103,6 +104,80 @@ lookup_session (CK_SESSION_HANDLE handle,
        return CKR_OK;
 }
 
+static CK_RV
+lookup_slot_inlock (CK_SLOT_ID id,
+                    p11_token **token)
+{
+       /*
+        * These are invalid inputs, that well behaved callers should
+        * not produce, so have them fail precondations
+        */
+
+       return_val_if_fail (gl.tokens != NULL,
+                           CKR_CRYPTOKI_NOT_INITIALIZED);
+
+       return_val_if_fail (id >= BASE_SLOT_ID && id - BASE_SLOT_ID < gl.tokens->num,
+                           CKR_SLOT_ID_INVALID);
+
+       if (token)
+               *token = gl.tokens->elem[id - BASE_SLOT_ID];
+       return CKR_OK;
+}
+
+static bool
+check_slot (CK_SLOT_ID id)
+{
+       bool ret;
+
+       p11_lock ();
+       ret = lookup_slot_inlock (id, NULL) == CKR_OK;
+       p11_unlock ();
+
+       return ret;
+}
+
+static bool
+create_tokens_inlock (p11_array *tokens,
+                      const char *paths)
+{
+       p11_token *token;
+       p11_token *check;
+       CK_SLOT_ID slot;
+       const char *path;
+       char *remaining;
+       char *pos;
+
+       p11_debug ("using paths: %s", paths);
+
+       remaining = strdup (paths);
+       return_val_if_fail (remaining != NULL, false);
+
+       while (remaining) {
+               path = remaining;
+               pos = strchr (remaining, ':');
+               if (pos == NULL) {
+                       remaining = NULL;
+               } else {
+                       pos[0] = '\0';
+                       remaining = pos + 1;
+               }
+
+               if (path[0] != '\0') {
+                       slot = BASE_SLOT_ID + tokens->num;
+                       token = p11_token_new (slot, path);
+                       return_val_if_fail (token != NULL, false);
+
+                       if (!p11_array_push (tokens, token))
+                               return_val_if_reached (false);
+
+                       assert (lookup_slot_inlock (slot, &check) == CKR_OK && check == token);
+               }
+       }
+
+       free (remaining);
+       return true;
+}
+
 static void
 parse_argument (char *arg)
 {
@@ -220,8 +295,8 @@ sys_C_Finalize (CK_VOID_PTR reserved)
                                p11_dict_free (gl.sessions);
                                gl.sessions = NULL;
 
-                               p11_token_free (gl.token);
-                               gl.token = NULL;
+                               p11_array_free (gl.tokens);
+                               gl.tokens = NULL;
 
                                rv = CKR_OK;
                        }
@@ -284,9 +359,11 @@ sys_C_Initialize (CK_VOID_PTR init_args)
                                                    p11_dict_ulongptr_equal,
                                                    NULL, p11_session_free);
 
-                       gl.token = p11_token_new (gl.paths ? gl.paths : TRUST_PATHS);
+                       gl.tokens = p11_array_new ((p11_destroyer)p11_token_free);
+                       if (gl.tokens && !create_tokens_inlock (gl.tokens, gl.paths ? gl.paths : TRUST_PATHS))
+                               gl.tokens = NULL;
 
-                       if (gl.sessions == NULL || gl.token == NULL) {
+                       if (gl.sessions == NULL || gl.tokens == NULL) {
                                warn_if_reached ();
                                rv = CKR_GENERAL_ERROR;
                        }
@@ -351,6 +428,7 @@ sys_C_GetSlotList (CK_BBOOL token_present,
                    CK_ULONG_PTR count)
 {
        CK_RV rv = CKR_OK;
+       int i;
 
        return_val_if_fail (count != NULL, CKR_ARGUMENTS_BAD);
 
@@ -367,16 +445,17 @@ sys_C_GetSlotList (CK_BBOOL token_present,
                /* already failed */
 
        } else if (!slot_list) {
-               *count = 1;
+               *count = gl.tokens->num;
                rv = CKR_OK;
 
-       } else if (*count < 1) {
-               *count = 1;
+       } else if (*count < gl.tokens->num) {
+               *count = gl.tokens->num;
                rv = CKR_BUFFER_TOO_SMALL;
 
        } else {
-               slot_list[0] = SYSTEM_SLOT_ID;
-               *count = 1;
+               for (i = 0; i < gl.tokens->num; i++)
+                       slot_list[i] = BASE_SLOT_ID + i;
+               *count = gl.tokens->num;
                rv = CKR_OK;
        }
 
@@ -390,19 +469,16 @@ sys_C_GetSlotInfo (CK_SLOT_ID id,
                    CK_SLOT_INFO_PTR info)
 {
        CK_RV rv = CKR_OK;
+       p11_token *token;
+       const char *path;
+       size_t length;
 
-       return_val_if_fail (id == SYSTEM_SLOT_ID, CKR_SLOT_ID_INVALID);
        return_val_if_fail (info != NULL, CKR_ARGUMENTS_BAD);
 
        p11_debug ("in");
-
        p11_lock ();
 
-               if (!gl.sessions)
-                       rv = CKR_CRYPTOKI_NOT_INITIALIZED;
-
-       p11_unlock ();
-
+       rv = lookup_slot_inlock (id, &token);
        if (rv == CKR_OK) {
                memset (info, 0, sizeof (*info));
                info->firmwareVersion.major = 0;
@@ -411,9 +487,17 @@ sys_C_GetSlotInfo (CK_SLOT_ID id,
                info->hardwareVersion.minor = 0;
                info->flags = CKF_TOKEN_PRESENT;
                strncpy ((char*)info->manufacturerID, MANUFACTURER_ID, 32);
-               strncpy ((char*)info->slotDescription, SLOT_DESCRIPTION, 64);
+
+               /* If too long, copy the first 64 characters into buffer */
+               path = p11_token_get_path (token);
+               length = strlen (path);
+               if (length > sizeof (info->slotDescription))
+                       length = sizeof (info->slotDescription);
+               memset (info->slotDescription, ' ', sizeof (info->slotDescription));
+               memcpy (info->slotDescription, path, length);
        }
 
+       p11_unlock ();
        p11_debug ("out: 0x%lx", rv);
 
        return rv;
@@ -424,19 +508,17 @@ sys_C_GetTokenInfo (CK_SLOT_ID id,
                     CK_TOKEN_INFO_PTR info)
 {
        CK_RV rv = CKR_OK;
+       p11_token *token;
+       const char *path;
+       size_t length;
 
-       return_val_if_fail (id == SYSTEM_SLOT_ID, CKR_SLOT_ID_INVALID);
        return_val_if_fail (info != NULL, CKR_ARGUMENTS_BAD);
 
        p11_debug ("in");
 
        p11_lock ();
 
-               if (!gl.sessions)
-                       rv = CKR_CRYPTOKI_NOT_INITIALIZED;
-
-       p11_unlock ();
-
+       rv = lookup_slot_inlock (id, &token);
        if (rv == CKR_OK) {
                memset (info, 0, sizeof (*info));
                info->firmwareVersion.major = 0;
@@ -445,7 +527,6 @@ sys_C_GetTokenInfo (CK_SLOT_ID id,
                info->hardwareVersion.minor = 0;
                info->flags = CKF_TOKEN_INITIALIZED | CKF_WRITE_PROTECTED;
                strncpy ((char*)info->manufacturerID, MANUFACTURER_ID, 32);
-               strncpy ((char*)info->label, TOKEN_LABEL, 32);
                strncpy ((char*)info->model, TOKEN_MODEL, 16);
                strncpy ((char*)info->serialNumber, TOKEN_SERIAL_NUMBER, 16);
                info->ulMaxSessionCount = CK_EFFECTIVELY_INFINITE;
@@ -458,8 +539,17 @@ sys_C_GetTokenInfo (CK_SLOT_ID id,
                info->ulFreePublicMemory = CK_UNAVAILABLE_INFORMATION;
                info->ulTotalPrivateMemory = CK_UNAVAILABLE_INFORMATION;
                info->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION;
+
+               /* If too long, copy the last 32 characters into buffer */
+               path = basename (p11_token_get_path (token));
+               length = strlen (path);
+               if (length > sizeof (info->label))
+                       length = sizeof (info->label);
+               memset (info->label, ' ', sizeof (info->label));
+               memcpy (info->label, path, length);
        }
 
+       p11_unlock ();
        p11_debug ("out: 0x%lx", rv);
 
        return rv;
@@ -487,8 +577,8 @@ sys_C_GetMechanismInfo (CK_SLOT_ID id,
                         CK_MECHANISM_TYPE type,
                         CK_MECHANISM_INFO_PTR info)
 {
-       return_val_if_fail (id == SYSTEM_SLOT_ID, CKR_SLOT_ID_INVALID);
        return_val_if_fail (info != NULL, CKR_ARGUMENTS_BAD);
+       return_val_if_fail (check_slot (id), CKR_SLOT_ID_INVALID);
        return_val_if_reached (CKR_MECHANISM_INVALID);
 }
 
@@ -498,7 +588,7 @@ sys_C_InitToken (CK_SLOT_ID id,
                  CK_ULONG pin_len,
                  CK_UTF8CHAR_PTR label)
 {
-       return_val_if_fail (id == SYSTEM_SLOT_ID, CKR_SLOT_ID_INVALID);
+       return_val_if_fail (check_slot (id), CKR_SLOT_ID_INVALID);
        return_val_if_reached (CKR_TOKEN_WRITE_PROTECTED);
 }
 
@@ -519,17 +609,19 @@ sys_C_OpenSession (CK_SLOT_ID id,
                    CK_SESSION_HANDLE_PTR handle)
 {
        p11_session *session;
+       p11_token *token;
        CK_RV rv = CKR_OK;
 
-       return_val_if_fail (id == SYSTEM_SLOT_ID, CKR_SLOT_ID_INVALID);
+       return_val_if_fail (check_slot (id), CKR_SLOT_ID_INVALID);
        return_val_if_fail (handle != NULL, CKR_ARGUMENTS_BAD);
 
        p11_debug ("in");
 
        p11_lock ();
 
-               if (!gl.sessions) {
-                       rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+               rv = lookup_slot_inlock (id, &token);
+               if (rv != CKR_OK) {
+                       /* fail below */;
 
                } else if (!(flags & CKF_SERIAL_SESSION)) {
                        rv = CKR_SESSION_PARALLEL_NOT_SUPPORTED;
@@ -538,7 +630,7 @@ sys_C_OpenSession (CK_SLOT_ID id,
                        rv = CKR_TOKEN_WRITE_PROTECTED;
 
                } else {
-                       session = p11_session_new (gl.token);
+                       session = p11_session_new (token);
                        if (p11_dict_set (gl.sessions, &session->handle, session)) {
                                rv = CKR_OK;
                                *handle = session->handle;
@@ -585,20 +677,23 @@ sys_C_CloseSession (CK_SESSION_HANDLE handle)
 static CK_RV
 sys_C_CloseAllSessions (CK_SLOT_ID id)
 {
-       CK_RV rv = CKR_OK;
-
-       return_val_if_fail (id == SYSTEM_SLOT_ID, CKR_SLOT_ID_INVALID);
+       CK_SESSION_HANDLE *handle;
+       p11_session *session;
+       p11_token *token;
+       p11_dictiter iter;
+       CK_RV rv;
 
        p11_debug ("in");
 
        p11_lock ();
 
-               if (!gl.sessions) {
-                       rv = CKR_CRYPTOKI_NOT_INITIALIZED;
-
-               } else {
-                       p11_dict_clear (gl.sessions);
-                       rv = CKR_OK;
+               rv = lookup_slot_inlock (id, &token);
+               if (rv == CKR_OK) {
+                       p11_dict_iterate (gl.sessions, &iter);
+                       while (p11_dict_next (&iter, (void **)&handle, (void **)&session)) {
+                               if (session->token == token)
+                                       p11_dict_remove (gl.sessions, handle);
+                       }
                }
 
        p11_unlock ();
@@ -624,6 +719,7 @@ static CK_RV
 sys_C_GetSessionInfo (CK_SESSION_HANDLE handle,
                       CK_SESSION_INFO_PTR info)
 {
+       p11_session *session;
        CK_RV rv;
 
        return_val_if_fail (info != NULL, CKR_ARGUMENTS_BAD);
@@ -632,17 +728,17 @@ sys_C_GetSessionInfo (CK_SESSION_HANDLE handle,
 
        p11_lock ();
 
-               rv = lookup_session (handle, NULL);
+               rv = lookup_session (handle, &session);
+               if (rv == CKR_OK) {
+                       info->flags = CKF_SERIAL_SESSION;
+                       info->state = CKS_RO_PUBLIC_SESSION;
+                       info->slotID = p11_token_get_slot (session->token);
+                       info->ulDeviceError = 0;
+               }
+
 
        p11_unlock ();
 
-       if (rv == CKR_OK) {
-               info->flags = CKF_SERIAL_SESSION;
-               info->slotID = SYSTEM_SLOT_ID;
-               info->state = CKS_RO_PUBLIC_SESSION;
-               info->ulDeviceError = 0;
-       }
-
        p11_debug ("out: 0x%lx", rv);
 
        return rv;
@@ -951,11 +1047,11 @@ sys_C_FindObjectsInit (CK_SESSION_HANDLE handle,
                /* Refresh from disk if this session hasn't yet */
                if (rv == CKR_OK && want_token_objects && !session->loaded) {
                        session->loaded = CK_TRUE;
-                       p11_token_load (gl.token);
+                       p11_token_load (session->token);
                }
 
                if (rv == CKR_OK) {
-                       objects = p11_token_objects (gl.token);
+                       objects = p11_token_objects (session->token);
 
                        find = calloc (1, sizeof (FindObjects));
                        warn_if_fail (find != NULL);
index 23856cf473591f6d84b20d4e712116d177432f8d..976fb2bfc84c615f7e8beed84708716fb0d8e5c1 100644 (file)
@@ -48,11 +48,11 @@ main (int argc,
        int count;
 
        if (argc != 2) {
-               fprintf (stderr, "usage: frob-token anchor:paths\n");
+               fprintf (stderr, "usage: frob-token path\n");
                return 2;
        }
 
-       token = p11_token_new (argv[1]);
+       token = p11_token_new (1, argv[1]);
        count = p11_token_load (token);
 
        printf ("%d files loaded\n", count);
index 52fbe039f926008f423553c30c5b3359b1743f3e..d811f1d685b40405d1924fea48e7bab3314e0248 100644 (file)
 #include "test-data.h"
 #include "token.h"
 
+#include <assert.h>
+
+/*
+ * This is the number of input paths. Should match the
+ * paths below near :
+ *
+ * paths='%s'
+ */
+#define NUM_SLOTS 3
+
 struct {
        CK_FUNCTION_LIST *module;
-       CK_SLOT_ID slot;
-       CK_SESSION_HANDLE session;
+       CK_SLOT_ID slots[NUM_SLOTS];
 } test;
 
 static void
@@ -71,7 +80,7 @@ setup (CuTest *cu)
        CuAssertTrue (cu, rv == CKR_OK);
 
        memset (&args, 0, sizeof (args));
-       paths = SRCDIR "/input:" SRCDIR "/files/cacert-ca.der";
+       paths = SRCDIR "/input:" SRCDIR "/files/cacert-ca.der:" SRCDIR "/files/testing-server.der";
        if (asprintf (&arguments, "paths='%s'", paths) < 0)
                CuAssertTrue (cu, false && "not reached");
        args.pReserved = arguments;
@@ -82,13 +91,10 @@ setup (CuTest *cu)
 
        free (arguments);
 
-       count = 1;
-       rv = test.module->C_GetSlotList (CK_TRUE, &test.slot, &count);
-       CuAssertTrue (cu, rv == CKR_OK);
-       CuAssertTrue (cu, count == 1);
-
-       rv = test.module->C_OpenSession (test.slot, CKF_SERIAL_SESSION, NULL, NULL, &test.session);
+       count = NUM_SLOTS;
+       rv = test.module->C_GetSlotList (CK_TRUE, test.slots, &count);
        CuAssertTrue (cu, rv == CKR_OK);
+       CuAssertTrue (cu, count == NUM_SLOTS);
 }
 
 static void
@@ -96,38 +102,238 @@ teardown (CuTest *cu)
 {
        CK_RV rv;
 
-       rv = test.module->C_CloseSession (test.session);
-       CuAssertTrue (cu, rv == CKR_OK);
-
        rv = test.module->C_Finalize (NULL);
        CuAssertTrue (cu, rv == CKR_OK);
 
        memset (&test, 0, sizeof (test));
 }
 
+static void
+test_get_slot_list (CuTest *cu)
+{
+       CK_SLOT_ID slots[NUM_SLOTS];
+       CK_ULONG count;
+       CK_RV rv;
+       int i;
+
+       setup (cu);
+
+       rv = test.module->C_GetSlotList (TRUE, NULL, &count);
+       CuAssertIntEquals (cu, CKR_OK, rv);
+       CuAssertIntEquals (cu, NUM_SLOTS, count);
+
+       count = 1;
+       rv = test.module->C_GetSlotList (TRUE, slots, &count);
+       CuAssertIntEquals (cu, CKR_BUFFER_TOO_SMALL, rv);
+       CuAssertIntEquals (cu, NUM_SLOTS, count);
+
+       count = NUM_SLOTS;
+       memset (slots, 0, sizeof (slots));
+       rv = test.module->C_GetSlotList (TRUE, slots, &count);
+       CuAssertIntEquals (cu, CKR_OK, rv);
+       CuAssertIntEquals (cu, NUM_SLOTS, count);
+
+       for (i = 0; i < NUM_SLOTS; i++)
+               CuAssertTrue (cu, slots[i] != 0);
+
+       teardown (cu);
+}
+
+static void
+test_get_slot_info (CuTest *cu)
+{
+       CK_SLOT_ID slots[NUM_SLOTS];
+       CK_SLOT_INFO info;
+       char description[64];
+       CK_ULONG count;
+       CK_RV rv;
+       int i;
+
+       /* These are the paths passed in in setup() */
+       const char *paths[] = {
+               SRCDIR "/input",
+               SRCDIR "/files/cacert-ca.der",
+               SRCDIR "/files/testing-server.der"
+       };
+
+       setup (cu);
+
+       count = NUM_SLOTS;
+       rv = test.module->C_GetSlotList (TRUE, slots, &count);
+       CuAssertIntEquals (cu, CKR_OK, rv);
+       CuAssertIntEquals (cu, NUM_SLOTS, count);
+
+       for (i = 0; i < NUM_SLOTS; i++) {
+               rv = test.module->C_GetSlotInfo (slots[i], &info);
+               CuAssertIntEquals (cu, CKR_OK, rv);
+
+               memset (description, ' ', sizeof (description));
+               assert (strlen (paths[i]) <= sizeof (description));
+               memcpy (description, paths[i], strlen (paths[i]));
+               CuAssertTrue (cu, memcmp (info.slotDescription, description, sizeof (description)) == 0);
+       }
+
+       teardown (cu);
+}
+
+static void
+test_get_token_info (CuTest *cu)
+{
+       CK_SLOT_ID slots[NUM_SLOTS];
+       CK_TOKEN_INFO info;
+       char label[32];
+       CK_ULONG count;
+       CK_RV rv;
+       int i;
+
+       /* These are the paths passed in in setup() */
+       const char *labels[] = {
+               "input",
+               "cacert-ca.der",
+               "testing-server.der"
+       };
+
+       setup (cu);
+
+       count = NUM_SLOTS;
+       rv = test.module->C_GetSlotList (TRUE, slots, &count);
+       CuAssertIntEquals (cu, CKR_OK, rv);
+       CuAssertIntEquals (cu, NUM_SLOTS, count);
+
+       for (i = 0; i < NUM_SLOTS; i++) {
+               rv = test.module->C_GetTokenInfo (slots[i], &info);
+               CuAssertIntEquals (cu, CKR_OK, rv);
+
+               memset (label, ' ', sizeof (label));
+               memcpy (label, labels[i], strlen (labels[i]));
+               CuAssertTrue (cu, memcmp (info.label, label, sizeof (label)) == 0);
+       }
+
+       teardown (cu);
+}
+
+static void
+test_get_session_info (CuTest *cu)
+{
+       CK_SLOT_ID slots[NUM_SLOTS];
+       CK_SESSION_HANDLE sessions[NUM_SLOTS];
+       CK_SESSION_INFO info;
+       CK_ULONG count;
+       CK_RV rv;
+       int i;
+
+       setup (cu);
+
+       count = NUM_SLOTS;
+       rv = test.module->C_GetSlotList (TRUE, slots, &count);
+       CuAssertIntEquals (cu, CKR_OK, rv);
+       CuAssertIntEquals (cu, NUM_SLOTS, count);
+
+       /* Open two sessions with each token */
+       for (i = 0; i < NUM_SLOTS; i++) {
+               rv = test.module->C_OpenSession (slots[i], CKF_SERIAL_SESSION, NULL, NULL, &sessions[i]);
+               CuAssertIntEquals (cu, CKR_OK, rv);
+
+               rv = test.module->C_GetSessionInfo (sessions[i], &info);
+               CuAssertIntEquals (cu, CKR_OK, rv);
+
+               CuAssertIntEquals (cu, slots[i], info.slotID);
+               CuAssertIntEquals (cu, CKF_SERIAL_SESSION, info.flags);
+       }
+
+       teardown (cu);
+}
+
+static void
+test_close_all_sessions (CuTest *cu)
+{
+       CK_SLOT_ID slots[NUM_SLOTS];
+       CK_SESSION_HANDLE sessions[NUM_SLOTS][2];
+       CK_SESSION_INFO info;
+       CK_ULONG count;
+       CK_RV rv;
+       int i;
+
+       setup (cu);
+
+       count = NUM_SLOTS;
+       rv = test.module->C_GetSlotList (TRUE, slots, &count);
+       CuAssertIntEquals (cu, CKR_OK, rv);
+       CuAssertIntEquals (cu, NUM_SLOTS, count);
+
+       /* Open two sessions with each token */
+       for (i = 0; i < NUM_SLOTS; i++) {
+               rv = test.module->C_OpenSession (slots[i], CKF_SERIAL_SESSION, NULL, NULL, &sessions[i][0]);
+               CuAssertIntEquals (cu, CKR_OK, rv);
+
+               rv = test.module->C_GetSessionInfo (sessions[i][0], &info);
+               CuAssertIntEquals (cu, CKR_OK, rv);
+
+               rv = test.module->C_OpenSession (slots[i], CKF_SERIAL_SESSION, NULL, NULL, &sessions[i][1]);
+               CuAssertIntEquals (cu, CKR_OK, rv);
+
+               rv = test.module->C_GetSessionInfo (sessions[i][0], &info);
+               CuAssertIntEquals (cu, CKR_OK, rv);
+       }
+
+       /* Close all the sessions on the first token */
+       rv = test.module->C_CloseAllSessions (slots[0]);
+       CuAssertIntEquals (cu, CKR_OK, rv);
+
+       /* Those sessions should be closed */
+       rv = test.module->C_GetSessionInfo (sessions[0][0], &info);
+       CuAssertIntEquals (cu, CKR_SESSION_HANDLE_INVALID, rv);
+       rv = test.module->C_GetSessionInfo (sessions[0][1], &info);
+       CuAssertIntEquals (cu, CKR_SESSION_HANDLE_INVALID, rv);
+
+       /* Other sessions should still be open */
+       for (i = 1; i < NUM_SLOTS; i++) {
+               rv = test.module->C_GetSessionInfo (sessions[i][0], &info);
+               CuAssertIntEquals (cu, CKR_OK, rv);
+               rv = test.module->C_GetSessionInfo (sessions[i][0], &info);
+               CuAssertIntEquals (cu, CKR_OK, rv);
+       }
+
+       teardown (cu);
+}
+
 static CK_ULONG
 find_objects (CuTest *cu,
               CK_ATTRIBUTE *match,
+              CK_OBJECT_HANDLE *sessions,
               CK_OBJECT_HANDLE *objects,
-              CK_ULONG num_objects)
+              CK_ULONG max_objects)
 {
+       CK_SESSION_HANDLE session;
        CK_RV rv;
+       CK_ULONG found;
        CK_ULONG count;
+       int i, j;
 
-       count = p11_attrs_count (match);
+       found = 0;
+       for (i = 0; i < NUM_SLOTS; i++) {
+               rv = test.module->C_OpenSession (test.slots[i], CKF_SERIAL_SESSION, NULL, NULL, &session);
+               CuAssertTrue (cu, rv == CKR_OK);
 
-       rv = test.module->C_FindObjectsInit (test.session, match, count);
-       CuAssertTrue (cu, rv == CKR_OK);
-       rv = test.module->C_FindObjects (test.session, objects, num_objects, &num_objects);
-       CuAssertTrue (cu, rv == CKR_OK);
-       rv = test.module->C_FindObjectsFinal (test.session);
-       CuAssertTrue (cu, rv == CKR_OK);
+               rv = test.module->C_FindObjectsInit (session, match, p11_attrs_count (match));
+               CuAssertTrue (cu, rv == CKR_OK);
+               rv = test.module->C_FindObjects (session, objects + found, max_objects - found, &count);
+               CuAssertTrue (cu, rv == CKR_OK);
+               rv = test.module->C_FindObjectsFinal (session);
+               CuAssertTrue (cu, rv == CKR_OK);
 
-       return num_objects;
+               for (j = found ; j < found + count; j++)
+                       sessions[j] = session;
+               found += count;
+       }
+
+       assert (found < max_objects);
+       return found;
 }
 
 static void
 check_trust_object_equiv (CuTest *cu,
+                          CK_SESSION_HANDLE session,
                           CK_OBJECT_HANDLE trust,
                           CK_ATTRIBUTE *cert)
 {
@@ -150,7 +356,7 @@ check_trust_object_equiv (CuTest *cu,
                { CKA_INVALID, },
        };
 
-       rv = test.module->C_GetAttributeValue (test.session, trust, equiv, 6);
+       rv = test.module->C_GetAttributeValue (session, trust, equiv, 6);
        CuAssertTrue (cu, rv == CKR_OK);
 
        test_check_attrs (cu, equiv, cert);
@@ -158,6 +364,7 @@ check_trust_object_equiv (CuTest *cu,
 
 static void
 check_trust_object_hashes (CuTest *cu,
+                           CK_SESSION_HANDLE session,
                            CK_OBJECT_HANDLE trust,
                            CK_ATTRIBUTE *cert)
 {
@@ -173,7 +380,7 @@ check_trust_object_hashes (CuTest *cu,
                { CKA_INVALID, },
        };
 
-       rv = test.module->C_GetAttributeValue (test.session, trust, hashes, 2);
+       rv = test.module->C_GetAttributeValue (session, trust, hashes, 2);
        CuAssertTrue (cu, rv == CKR_OK);
 
        value = p11_attrs_find (cert, CKA_VALUE);
@@ -193,6 +400,7 @@ check_has_trust_object (CuTest *cu,
        CK_OBJECT_CLASS trust_object = CKO_NSS_TRUST;
        CK_ATTRIBUTE klass = { CKA_CLASS, &trust_object, sizeof (trust_object) };
        CK_OBJECT_HANDLE objects[2];
+       CK_SESSION_HANDLE sessions[2];
        CK_ATTRIBUTE *match;
        CK_ATTRIBUTE *attr;
        CK_ULONG count;
@@ -201,15 +409,16 @@ check_has_trust_object (CuTest *cu,
        CuAssertPtrNotNull (cu, attr);
 
        match = p11_attrs_build (NULL, &klass, attr, NULL);
-       count = find_objects (cu, match, objects, 2);
+       count = find_objects (cu, match, sessions, objects, 2);
        CuAssertIntEquals (cu, 1, count);
 
-       check_trust_object_equiv (cu, objects[0], cert);
-       check_trust_object_hashes (cu, objects[0], cert);
+       check_trust_object_equiv (cu, sessions[0], objects[0], cert);
+       check_trust_object_hashes (cu, sessions[0], objects[0], cert);
 }
 
 static void
 check_certificate (CuTest *cu,
+                   CK_SESSION_HANDLE session,
                    CK_OBJECT_HANDLE handle)
 {
        unsigned char label[4096]= { 0, };
@@ -249,7 +458,7 @@ check_certificate (CuTest *cu,
        };
 
        /* Note that we don't pass the CKA_INVALID attribute in */
-       rv = test.module->C_GetAttributeValue (test.session, handle, attrs, 15);
+       rv = test.module->C_GetAttributeValue (session, handle, attrs, 15);
        CuAssertTrue (cu, rv == CKR_OK);
 
        /* If this is the cacert3 certificate, check its values */
@@ -270,7 +479,7 @@ check_certificate (CuTest *cu,
                test_check_cacert3_ca (cu, attrs, NULL);
 
                /* Get anchor specific attributes */
-               rv = test.module->C_GetAttributeValue (test.session, handle, anchor, 1);
+               rv = test.module->C_GetAttributeValue (session, handle, anchor, 1);
                CuAssertTrue (cu, rv == CKR_OK);
 
                /* It lives in the trusted directory */
@@ -295,16 +504,17 @@ test_find_certificates (CuTest *cu)
        };
 
        CK_OBJECT_HANDLE objects[16];
+       CK_SESSION_HANDLE sessions[16];
        CK_ULONG count;
        CK_ULONG i;
 
        setup (cu);
 
-       count = find_objects (cu, match, objects, 16);
-       CuAssertIntEquals (cu, 6, count);
+       count = find_objects (cu, match, sessions, objects, 16);
+       CuAssertIntEquals (cu, 7, count);
 
        for (i = 0; i < count; i++)
-               check_certificate (cu, objects[i]);
+               check_certificate (cu, sessions[i], objects[i]);
 
        teardown (cu);
 }
@@ -325,12 +535,14 @@ test_find_builtin (CuTest *cu)
        };
 
        CK_OBJECT_HANDLE objects[16];
+       CK_SESSION_HANDLE sessions[16];
        CK_ULONG count;
 
        setup (cu);
 
-       count = find_objects (cu, match, objects, 16);
-       CuAssertIntEquals (cu, 1, count);
+       /* One per token */
+       count = find_objects (cu, match, sessions, objects, 16);
+       CuAssertIntEquals (cu, NUM_SLOTS, count);
 
        teardown (cu);
 }
@@ -346,6 +558,11 @@ main (void)
        p11_library_init ();
        p11_debug_init ();
 
+       SUITE_ADD_TEST (suite, test_get_slot_list);
+       SUITE_ADD_TEST (suite, test_get_slot_info);
+       SUITE_ADD_TEST (suite, test_get_token_info);
+       SUITE_ADD_TEST (suite, test_get_session_info);
+       SUITE_ADD_TEST (suite, test_close_all_sessions);
        SUITE_ADD_TEST (suite, test_find_certificates);
        SUITE_ADD_TEST (suite, test_find_builtin);
 
index e9031f23e5f78302d194ffe224d134278eb77df9..6183e7c5930741835340eb306b6bea53ddd78816 100644 (file)
@@ -53,7 +53,7 @@ struct {
 static void
 setup (CuTest *cu)
 {
-       test.token = p11_token_new ("");
+       test.token = p11_token_new (1, "/nonexistant");
        CuAssertPtrNotNull (cu, test.token);
 
        test.session = p11_session_new (test.token);
index c56640661193a6ec13ba99e8826845f3926a7ef3..96f7a6c2d71783559710dda93695e98da78179cc 100644 (file)
@@ -51,9 +51,10 @@ struct {
 } test;
 
 static void
-setup (CuTest *cu)
+setup (CuTest *cu,
+       const char *path)
 {
-       test.token = p11_token_new (SRCDIR "/input:" SRCDIR "/files/self-server.der:" SRCDIR "/files/cacert-ca.der");
+       test.token = p11_token_new (333, path);
        CuAssertPtrNotNull (cu, test.token);
 }
 
@@ -70,10 +71,10 @@ test_token_load (CuTest *cu)
        p11_dict *objects;
        int count;
 
-       setup (cu);
+       setup (cu, SRCDIR "/input");
 
        count = p11_token_load (test.token);
-       CuAssertIntEquals (cu, 7, count);
+       CuAssertIntEquals (cu, 6, count);
 
        /* A certificate and trust object for each parsed object + builtin */
        objects = p11_token_objects (test.token);
@@ -183,7 +184,7 @@ test_token_flags (CuTest *cu)
                { CKA_INVALID },
        };
 
-       setup (cu);
+       setup (cu, SRCDIR "/input");
 
        if (p11_token_load (test.token) < 0)
                CuFail (cu, "should not be reached");
@@ -197,6 +198,26 @@ test_token_flags (CuTest *cu)
        teardown (cu);
 }
 
+static void
+test_token_path (CuTest *cu)
+{
+       setup (cu, "/wheee");
+
+       CuAssertStrEquals (cu, "/wheee", p11_token_get_path (test.token));
+
+       teardown (cu);
+}
+
+static void
+test_token_slot (CuTest *cu)
+{
+       setup (cu, "/unneeded");
+
+       CuAssertIntEquals (cu, 333, p11_token_get_slot (test.token));
+
+       teardown (cu);
+}
+
 int
 main (void)
 {
@@ -211,6 +232,8 @@ main (void)
 
        SUITE_ADD_TEST (suite, test_token_load);
        SUITE_ADD_TEST (suite, test_token_flags);
+       SUITE_ADD_TEST (suite, test_token_path);
+       SUITE_ADD_TEST (suite, test_token_slot);
 
        CuSuiteRun (suite);
        CuSuiteSummary (suite, output);
index f96d86590da11772fcfb3e09ec4214f1ef92b2d0..39bca042c750f5f66ccfcdcb5d86c8cf4f0fcd67 100644 (file)
@@ -59,7 +59,8 @@
 struct _p11_token {
        p11_parser *parser;
        p11_dict *objects;
-       const char *paths;
+       const char *path;
+       CK_SLOT_ID slot;
        int loaded;
 };
 
@@ -208,43 +209,6 @@ loader_load_path (p11_token *token,
        }
 }
 
-static int
-loader_load_paths (p11_token *token,
-                   const char *paths)
-{
-       const char *pos;
-       int total = 0;
-       char *path;
-       int ret;
-
-       p11_debug ("loading paths: %s", paths);
-
-       while (paths) {
-               pos = strchr (paths, ':');
-               if (pos == NULL) {
-                       path = strdup (paths);
-                       paths = NULL;
-               } else {
-                       path = strndup (paths, pos - paths);
-                       paths = pos + 1;
-               }
-
-               return_val_if_fail (path != NULL, -1);
-
-               if (path[0] != '\0') {
-                       /* We don't expect this to fail except for in strange circumstances */
-                       ret = loader_load_path (token, path);
-                       if (ret < 0)
-                               return_val_if_reached (-1);
-                       total += ret;
-               }
-
-               free (path);
-       }
-
-       return total;
-}
-
 static int
 load_builtin_objects (p11_token *token)
 {
@@ -425,7 +389,7 @@ p11_token_load (p11_token *token)
 
        builtins = load_builtin_objects (token);
 
-       count = loader_load_paths (token, token->paths);
+       count = loader_load_path (token, token->path);
        return_val_if_fail (count >= 0, count);
 
        return count + builtins;
@@ -449,7 +413,8 @@ p11_token_free (p11_token *token)
 }
 
 p11_token *
-p11_token_new (const char *paths)
+p11_token_new (CK_SLOT_ID slot,
+               const char *path)
 {
        p11_token *token;
 
@@ -464,8 +429,25 @@ p11_token_new (const char *paths)
                                       free, p11_attrs_free);
        return_val_if_fail (token->objects != NULL, NULL);
 
-       token->paths = paths;
+       token->path = strdup (path);
+       return_val_if_fail (token->path != NULL, NULL);
+
+       token->slot = slot;
        token->loaded = 0;
 
        return token;
 }
+
+const char *
+p11_token_get_path (p11_token *token)
+{
+       return_val_if_fail (token != NULL, NULL);
+       return token->path;
+}
+
+CK_SLOT_ID
+p11_token_get_slot (p11_token *token)
+{
+       return_val_if_fail (token != NULL, 0);
+       return token->slot;
+}
index 0c53d32b2a0360a60a1d6350b14f6e401736a66c..599e98228c0413694f12aaeaae24e949dfae3c12 100644 (file)
 #define P11_TOKEN_H_
 
 #include "dict.h"
+#include "pkcs11.h"
 
 typedef struct _p11_token p11_token;
 
-p11_token *     p11_token_new         (const char *paths);
+p11_token *     p11_token_new         (CK_SLOT_ID slot,
+                                       const char *path);
 
 void            p11_token_free        (p11_token *token);
 
@@ -47,4 +49,8 @@ int             p11_token_load        (p11_token *token);
 
 p11_dict *      p11_token_objects     (p11_token *token);
 
+const char *    p11_token_get_path    (p11_token *token);
+
+CK_SLOT_ID      p11_token_get_slot    (p11_token *token);
+
 #endif /* P11_TOKEN_H_ */