]> granicus.if.org Git - p11-kit/commitdiff
Add p11_kit_load_initialize_module() function.
authorStef Walter <stefw@collabora.co.uk>
Fri, 27 May 2011 14:07:15 +0000 (16:07 +0200)
committerStef Walter <stefw@collabora.co.uk>
Fri, 27 May 2011 14:07:15 +0000 (16:07 +0200)
 * This function will load a module from a file path, and then
   initialize it.

doc/p11-kit-sections.txt
p11-kit/modules.c
p11-kit/p11-kit.h

index 10435b2f86afe928fb8cedf7402b5b8e000508c7..c7b15960591a14f482fb5d99f83db05c58198ae0 100644 (file)
@@ -36,6 +36,7 @@ p11_kit_registered_module_to_name
 p11_kit_registered_name_to_module
 p11_kit_registered_option
 p11_kit_initialize_module
+p11_kit_load_initialize_module
 p11_kit_finalize_module
 </SECTION>
 
index 7fe507393630dd588c043c1cb103ffa1b69e3b68..e155889713a58f86a6623b20142cd3a00359a95c 100644 (file)
  */
 
 typedef struct _Module {
+       CK_FUNCTION_LIST_PTR funcs;
+       int ref_count;
+
+       /* Registered modules */
        char *name;
        hash_t *config;
+
+       /* Loaded modules */
        void *dl_module;
-       CK_FUNCTION_LIST_PTR funcs;
-       int ref_count;
-       int initialize_count;
+       int dlopen_count;
+
+       /* Initialized modules */
        CK_C_INITIALIZE_ARGS init_args;
+       int initialize_count;
 } Module;
 
 /*
@@ -305,11 +312,79 @@ alloc_module_unlocked (void)
 }
 
 static CK_RV
-load_module_from_config_unlocked (const char *configfile, const char *name)
+dlopen_and_get_function_list (Module *mod, const char *path)
+{
+       CK_C_GetFunctionList gfl;
+       CK_RV rv;
+
+       assert (mod);
+       assert (path);
+
+       mod->dl_module = dlopen (path, RTLD_LOCAL | RTLD_NOW);
+       if (mod->dl_module == NULL) {
+               warning ("couldn't load module: %s: %s", path, dlerror ());
+               return CKR_GENERAL_ERROR;
+       }
+
+       mod->dlopen_count++;
+
+       gfl = dlsym (mod->dl_module, "C_GetFunctionList");
+       if (!gfl) {
+               warning ("couldn't find C_GetFunctionList entry point in module: %s: %s",
+                        path, dlerror ());
+               return CKR_GENERAL_ERROR;
+       }
+
+       rv = gfl (&mod->funcs);
+       if (rv != CKR_OK) {
+               warning ("call to C_GetFunctiontList failed in module: %s: %s",
+                        path, p11_kit_strerror (rv));
+               return rv;
+       }
+
+       return CKR_OK;
+}
+
+static CK_RV
+load_module_from_file_unlocked (const char *path, Module **result)
+{
+       Module *mod;
+       Module *prev;
+       CK_RV rv;
+
+       mod = alloc_module_unlocked ();
+       if (!mod)
+               return CKR_HOST_MEMORY;
+
+       rv = dlopen_and_get_function_list (mod, path);
+       if (rv != CKR_OK) {
+               free_module_unlocked (mod);
+               return rv;
+       }
+
+       /* Do we have a previous one like this, if so ignore load */
+       prev = hash_get (gl.modules, mod->funcs);
+
+       if (prev != NULL) {
+               free_module_unlocked (mod);
+               mod = prev;
+
+       } else if (!hash_set (gl.modules, mod->funcs, mod)) {
+               free_module_unlocked (mod);
+               return CKR_HOST_MEMORY;
+       }
+
+       if (result)
+               *result= mod;
+       return CKR_OK;
+}
+
+static CK_RV
+load_module_from_config_unlocked (const char *configfile, const char *name,
+                                  Module **result)
 {
        Module *mod, *prev;
        const char *path;
-       CK_C_GetFunctionList gfl;
        CK_RV rv;
 
        assert (configfile);
@@ -339,25 +414,8 @@ load_module_from_config_unlocked (const char *configfile, const char *name)
                return CKR_GENERAL_ERROR;
        }
 
-       mod->dl_module = dlopen (path, RTLD_LOCAL | RTLD_NOW);
-       if (mod->dl_module == NULL) {
-               warning ("couldn't load module: %s: %s", path, dlerror ());
-               free_module_unlocked (mod);
-               return CKR_GENERAL_ERROR;
-       }
-
-       gfl = dlsym (mod->dl_module, "C_GetFunctionList");
-       if (!gfl) {
-               warning ("couldn't find C_GetFunctionList entry point in module: %s: %s",
-                        path, dlerror ());
-               free_module_unlocked (mod);
-               return CKR_GENERAL_ERROR;
-       }
-
-       rv = gfl (&mod->funcs);
+       rv = dlopen_and_get_function_list (mod, path);
        if (rv != CKR_OK) {
-               warning ("call to C_GetFunctiontList failed in module: %s: %s",
-                        path, p11_kit_strerror (rv));
                free_module_unlocked (mod);
                return rv;
        }
@@ -392,6 +450,8 @@ load_module_from_config_unlocked (const char *configfile, const char *name)
                return CKR_HOST_MEMORY;
        }
 
+       if (result)
+               *result = mod;
        return CKR_OK;
 }
 
@@ -442,7 +502,7 @@ load_modules_from_config_unlocked (const char *directory)
                if (is_dir)
                        rv = CKR_OK;
                else
-                       rv = load_module_from_config_unlocked (path, dp->d_name);
+                       rv = load_module_from_config_unlocked (path, dp->d_name, NULL);
 
                free (path);
 
@@ -1193,3 +1253,62 @@ p11_kit_finalize_module (CK_FUNCTION_LIST_PTR module)
        debug ("out: %lu", rv);
        return rv;
 }
+
+/**
+ * p11_kit_load_initialize_module:
+ * @module_path: full file path of module library
+ * @module: location to place loaded module pointer
+ *
+ * Load an arbitrary PKCS\#11 module from a dynamic library file, and
+ * initialize it. Normally using the p11_kit_initialize_registered() function
+ * is preferred.
+ *
+ * Using this function to load and initialize modules allows coordination between
+ * multiple users of the same module in a single process. The caller should not
+ * call the module's <code>C_Initialize</code> method. This function will call
+ * <code>C_Initialize</code> as necessary.
+ *
+ * If a module has already been loaded, then use of this function is unnecesasry.
+ * Instead use the p11_kit_initialize_module() function to initialize it.
+ *
+ * Subsequent calls to this function for the same module will result in an
+ * initialization count being incremented for the module. It is safe (although
+ * usually unnecessary) to use this function on registered modules.
+ *
+ * The module must be finalized with p11_kit_finalize_module() instead of
+ * calling its <code>C_Finalize</code> method directly.
+ *
+ * This function does not accept a <code>CK_C_INITIALIZE_ARGS</code> argument.
+ * Custom initialization arguments cannot be supported when multiple consumers
+ * load the same module.
+ *
+ * Returns: CKR_OK if the initialization was successful.
+ */
+CK_RV
+p11_kit_load_initialize_module (const char *module_path,
+                                CK_FUNCTION_LIST_PTR_PTR module)
+{
+       Module *mod;
+       CK_RV rv = CKR_OK;
+
+       /* WARNING: This function must be reentrant for the same arguments */
+       debug ("in");
+
+       _p11_lock ();
+
+               rv = init_globals_unlocked ();
+               if (rv == CKR_OK) {
+
+                       rv = load_module_from_file_unlocked (module_path, &mod);
+                       if (rv == CKR_OK) {
+
+                               /* WARNING: Reentrancy can occur here */
+                               rv = initialize_module_unlocked_reentrant (mod);
+                       }
+               }
+
+       _p11_unlock ();
+
+       debug ("out: %lu", rv);
+       return rv;
+}
index fe36b1c9cd504e5641e8faefc9b7b89346c89794..8807058b127c305f69b0d45f39f314d5d1c8d155 100644 (file)
@@ -67,6 +67,9 @@ CK_RV                    p11_kit_initialize_module         (CK_FUNCTION_LIST_PTR
 
 CK_RV                    p11_kit_finalize_module           (CK_FUNCTION_LIST_PTR module);
 
+CK_RV                    p11_kit_load_initialize_module    (const char *module_path,
+                                                            CK_FUNCTION_LIST_PTR_PTR module);
+
 const char*              p11_kit_strerror                  (CK_RV rv);
 
 #ifdef __cplusplus