summaryrefslogtreecommitdiff
path: root/p11-kit
diff options
context:
space:
mode:
Diffstat (limited to 'p11-kit')
-rw-r--r--p11-kit/Makefile.am1
-rw-r--r--p11-kit/compat.c114
-rw-r--r--p11-kit/compat.h143
-rw-r--r--p11-kit/conf.c64
-rw-r--r--p11-kit/debug.c31
-rw-r--r--p11-kit/debug.h2
-rw-r--r--p11-kit/modules.c104
-rw-r--r--p11-kit/private.h40
-rw-r--r--p11-kit/proxy.c7
-rw-r--r--p11-kit/util.c188
10 files changed, 563 insertions, 131 deletions
diff --git a/p11-kit/Makefile.am b/p11-kit/Makefile.am
index 3b838b3..72623b3 100644
--- a/p11-kit/Makefile.am
+++ b/p11-kit/Makefile.am
@@ -20,6 +20,7 @@ inc_HEADERS = \
MODULE_SRCS = \
util.c util.h \
+ compat.c compat.h \
conf.c conf.h \
debug.c debug.h \
hashmap.c hashmap.h \
diff --git a/p11-kit/compat.c b/p11-kit/compat.c
new file mode 100644
index 0000000..5fe8a84
--- /dev/null
+++ b/p11-kit/compat.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2011 Collabora Ltd.
+ *
+ * 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 <stefw@collabora.co.uk>
+ */
+
+#include "config.h"
+
+#include "compat.h"
+#include "private.h"
+
+#include <assert.h>
+
+#ifdef OS_UNIX
+
+void
+mutex_init (mutex_t *mutex)
+{
+ pthread_mutexattr_t attr;
+ int ret;
+
+ pthread_mutexattr_init (&attr);
+ pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
+ ret = pthread_mutex_init (mutex, &attr);
+ assert (ret == 0);
+ pthread_mutexattr_destroy (&attr);
+}
+
+#endif /* OS_UNIX */
+
+#ifdef OS_WIN32
+
+const char *
+module_error (void)
+{
+ DWORD code = GetLastError();
+ p11_local *local;
+ LPVOID msg_buf;
+
+ local = _p11_library_get_thread_local ();
+
+ FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, code,
+ MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPSTR)&msg_buf, 0, NULL);
+
+ if (local->last_error)
+ LocalFree (local->last_error);
+ local->last_error = msg_buf;
+
+ return msg_buf;
+}
+
+int
+thread_create (thread_t *thread,
+ thread_routine routine,
+ void *arg)
+{
+ assert (thread);
+
+ *thread = CreateThread (NULL, 0,
+ (LPTHREAD_START_ROUTINE)routine,
+ arg, 0, NULL);
+
+ if (*thread == NULL)
+ return GetLastError ();
+
+ return 0;
+}
+
+int
+thread_join (thread_t thread)
+{
+ DWORD res;
+
+ res = WaitForSingleObject (thread, INFINITE);
+ if (res == WAIT_FAILED)
+ return GetLastError ();
+
+ CloseHandle (thread);
+ return 0;
+}
+
+#endif /* OS_WIN32 */
diff --git a/p11-kit/compat.h b/p11-kit/compat.h
new file mode 100644
index 0000000..4972b19
--- /dev/null
+++ b/p11-kit/compat.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2011 Collabora Ltd.
+ *
+ * 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 <stefw@collabora.co.uk>
+ */
+
+#ifndef __COMPAT_H__
+#define __COMPAT_H__
+
+#include "config.h"
+
+/* -----------------------------------------------------------------------------
+ * WIN32
+ */
+
+#ifdef OS_WIN32
+
+#define _WIN32_WINNT 0x500
+#define _WIN32_IE 0x400
+#define WIN32_LEAN_AND_MEAN 1
+#include <windows.h>
+
+/* Oh ... my ... god */
+#undef CreateMutex
+
+typedef CRITICAL_SECTION mutex_t;
+
+typedef HANDLE thread_t;
+
+#define mutex_init(m) \
+ (InitializeCriticalSection (m))
+#define mutex_lock(m) \
+ (EnterCriticalSection (m))
+#define mutex_unlock(m) \
+ (LeaveCriticalSection (m))
+#define mutex_uninit(m) \
+ (DeleteCriticalSection (m))
+
+typedef void * (*thread_routine) (void *arg);
+
+int thread_create (thread_t *thread, thread_routine, void *arg);
+
+int thread_join (thread_t thread);
+
+#define thread_self() \
+ (GetCurrentThread ())
+
+typedef HMODULE dl_module_t;
+
+#define module_open(f) \
+ (LoadLibrary (f))
+#define module_close(d) \
+ (FreeLibrary (d))
+#define module_symbol(d, s) \
+ ((void *)GetProcAddress ((d), (s)))
+
+const char * module_error (void);
+
+#define sleep_ms(ms) \
+ (Sleep (ms))
+
+#endif /* OS_WIN32 */
+
+/* ----------------------------------------------------------------------------
+ * UNIX
+ */
+
+#ifdef OS_UNIX
+
+#include <pthread.h>
+#include <dlfcn.h>
+#include <time.h>
+
+typedef pthread_mutex_t mutex_t;
+
+void mutex_init (mutex_t *mutex);
+
+#define mutex_lock(m) \
+ (pthread_mutex_lock (m))
+#define mutex_unlock(m) \
+ (pthread_mutex_unlock (m))
+#define mutex_uninit(m) \
+ (pthread_mutex_destroy(m))
+
+typedef pthread_t thread_t;
+
+typedef void * (*thread_routine) (void *arg);
+
+#define thread_create(t, r, a) \
+ (pthread_create ((t), NULL, (r), (a)))
+#define thread_join(t) \
+ (pthread_join ((t), NULL))
+#define thread_self(m) \
+ (pthread_self ())
+
+typedef void * dl_module_t;
+
+#define module_open(f) \
+ (dlopen ((f), RTLD_LOCAL | RTLD_NOW))
+#define module_close(d) \
+ (dlclose(d))
+#define module_error() \
+ (dlerror ())
+#define module_symbol(d, s) \
+ (dlsym ((d), (s)))
+
+#define sleep_ms(ms) \
+ do { int _ms = (ms); \
+ struct timespec _ts = { _ms / 1000, (_ms % 1000) * 1000 * 1000 }; \
+ nanosleep (&_ts, NULL); \
+ } while(0)
+
+#endif /* OS_UNIX */
+
+#endif /* __COMPAT_H__ */
diff --git a/p11-kit/conf.c b/p11-kit/conf.c
index 1e2d880..b05c8aa 100644
--- a/p11-kit/conf.c
+++ b/p11-kit/conf.c
@@ -37,6 +37,7 @@
#include "config.h"
+#include "compat.h"
#include "conf.h"
#define DEBUG_FLAG DEBUG_CONF
#include "debug.h"
@@ -50,13 +51,20 @@
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
-#include <pwd.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#ifdef OS_UNIX
+#include <pwd.h>
+#endif
+
+#ifdef OS_WIN32
+#include <shlobj.h>
+#endif
+
static void
strcln (char* data, char ch)
{
@@ -327,31 +335,47 @@ _p11_conf_parse_file (const char* filename, int flags)
return map;
}
-static char*
+static char *
expand_user_path (const char *path)
{
const char *env;
- struct passwd *pwd;
- int error = 0;
- if (path[0] == '~' && path[1] == '/') {
- env = getenv ("HOME");
- if (env && env[0]) {
- return strconcat (env, path + 1, NULL);
- } else {
- pwd = getpwuid (getuid ());
- if (!pwd) {
- error = errno;
- _p11_message ("couldn't lookup home directory for user %d: %s",
- getuid (), strerror (errno));
- errno = error;
- return NULL;
- }
- return strconcat (pwd->pw_dir, path + 1, NULL);
+ if (path[0] != '~' || path[1] != '/')
+ return strdup (path);
+
+ path += 1;
+ env = getenv ("HOME");
+ if (env && env[0]) {
+ return strconcat (env, path, NULL);
+
+ } else {
+#ifdef OS_UNIX
+ struct passwd *pwd;
+ int error = 0;
+
+ pwd = getpwuid (getuid ());
+ if (!pwd) {
+ error = errno;
+ _p11_message ("couldn't lookup home directory for user %d: %s",
+ getuid (), strerror (errno));
+ errno = error;
+ return NULL;
}
- }
- return strdup (path);
+ return strconcat (pwd->pw_dir, path, NULL);
+
+#else /* OS_WIN32 */
+ char directory[MAX_PATH + 1];
+
+ if (!SHGetSpecialFolderPathA (NULL, directory, CSIDL_PROFILE, TRUE)) {
+ _p11_message ("couldn't lookup home directory for user");
+ errno = ENOTDIR;
+ return NULL;
+ }
+
+ return strconcat (directory, path, NULL);
+#endif /* OS_WIN32 */
+ }
}
static int
diff --git a/p11-kit/debug.c b/p11-kit/debug.c
index e4b39f0..5766dae 100644
--- a/p11-kit/debug.c
+++ b/p11-kit/debug.c
@@ -36,9 +36,10 @@
#include "config.h"
+#include "compat.h"
#include "debug.h"
-#include <pthread.h>
+#include <assert.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
@@ -58,10 +59,11 @@ static struct DebugKey debug_keys[] = {
{ 0, }
};
-pthread_mutex_t debug_mutex = PTHREAD_MUTEX_INITIALIZER;
+static int debug_inited = 0;
+static mutex_t debug_mutex;
/* global variable exported in debug.h */
-int debug_current_flags = ~0;
+int debug_current_flags;
static int
parse_environ_flags (void)
@@ -109,22 +111,21 @@ parse_environ_flags (void)
}
void
+debug_init (void)
+{
+ debug_current_flags = parse_environ_flags ();
+ mutex_init (&debug_mutex);
+ debug_inited = 1;
+}
+
+void
debug_message (int flag, const char *format, ...)
{
- static int initialized_flags = 0;
char buffer[512];
va_list args;
- pthread_mutex_lock (&debug_mutex);
-
- /*
- * This is not thread-safe, but it's not really the end of the
- * world if it happens more than once.
- */
- if (!initialized_flags) {
- initialized_flags = 1;
- debug_current_flags = parse_environ_flags ();
- }
+ assert (debug_inited);
+ mutex_lock (&debug_mutex);
if (flag & debug_current_flags) {
va_start (args, format);
@@ -134,5 +135,5 @@ debug_message (int flag, const char *format, ...)
fprintf (stderr, "(p11-kit:%d) %s\n", getpid(), buffer);
}
- pthread_mutex_unlock (&debug_mutex);
+ mutex_unlock (&debug_mutex);
}
diff --git a/p11-kit/debug.h b/p11-kit/debug.h
index 2d6a226..b8490dd 100644
--- a/p11-kit/debug.h
+++ b/p11-kit/debug.h
@@ -45,6 +45,8 @@ typedef enum {
extern int debug_current_flags;
+void debug_init (void);
+
void debug_message (int flag,
const char *format,
...);
diff --git a/p11-kit/modules.c b/p11-kit/modules.c
index 1394532..34926a4 100644
--- a/p11-kit/modules.c
+++ b/p11-kit/modules.c
@@ -48,10 +48,8 @@
#include <assert.h>
#include <dirent.h>
-#include <dlfcn.h>
#include <errno.h>
#include <limits.h>
-#include <pthread.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
@@ -105,23 +103,15 @@ typedef struct _Module {
hashmap *config;
/* Loaded modules */
- void *dl_module;
+ dl_module_t dl_module;
/* Initialization, mutex must be held */
- pthread_mutex_t initialize_mutex;
+ mutex_t initialize_mutex;
int initialize_called;
- pthread_t initialize_thread;
+ thread_t initialize_thread;
} Module;
/*
- * This is the mutex that protects the global data of this library
- * and the pkcs11 proxy module. Note that we *never* call into our
- * underlying pkcs11 modules while holding this mutex. Therefore it
- * doesn't have to be recursive and we can keep things simple.
- */
-pthread_mutex_t _p11_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-/*
* Shared data between threads, protected by the mutex, a structure so
* we can audit thread safety easier.
*/
@@ -137,20 +127,15 @@ static struct _Shared {
static CK_RV
create_mutex (CK_VOID_PTR_PTR mut)
{
- pthread_mutex_t *pmutex;
- int err;
+ mutex_t *pmutex;
if (mut == NULL)
return CKR_ARGUMENTS_BAD;
- pmutex = malloc (sizeof (pthread_mutex_t));
+ pmutex = malloc (sizeof (mutex_t));
if (!pmutex)
return CKR_HOST_MEMORY;
- err = pthread_mutex_init (pmutex, NULL);
- if (err == ENOMEM)
- return CKR_HOST_MEMORY;
- else if (err != 0)
- return CKR_GENERAL_ERROR;
+ mutex_init (pmutex);
*mut = pmutex;
return CKR_OK;
}
@@ -158,17 +143,12 @@ create_mutex (CK_VOID_PTR_PTR mut)
static CK_RV
destroy_mutex (CK_VOID_PTR mut)
{
- pthread_mutex_t *pmutex = mut;
- int err;
+ mutex_t *pmutex = mut;
if (mut == NULL)
return CKR_MUTEX_BAD;
- err = pthread_mutex_destroy (pmutex);
- if (err == EINVAL)
- return CKR_MUTEX_BAD;
- else if (err != 0)
- return CKR_GENERAL_ERROR;
+ mutex_uninit (pmutex);
free (pmutex);
return CKR_OK;
}
@@ -176,36 +156,24 @@ destroy_mutex (CK_VOID_PTR mut)
static CK_RV
lock_mutex (CK_VOID_PTR mut)
{
- pthread_mutex_t *pmutex = mut;
- int err;
+ mutex_t *pmutex = mut;
if (mut == NULL)
return CKR_MUTEX_BAD;
- err = pthread_mutex_lock (pmutex);
- if (err == EINVAL)
- return CKR_MUTEX_BAD;
- else if (err != 0)
- return CKR_GENERAL_ERROR;
+ mutex_lock (pmutex);
return CKR_OK;
}
static CK_RV
unlock_mutex (CK_VOID_PTR mut)
{
- pthread_mutex_t *pmutex = mut;
- int err;
+ mutex_t *pmutex = mut;
if (mut == NULL)
return CKR_MUTEX_BAD;
- err = pthread_mutex_unlock (pmutex);
- if (err == EINVAL)
- return CKR_MUTEX_BAD;
- else if (err == EPERM)
- return CKR_MUTEX_NOT_LOCKED;
- else if (err != 0)
- return CKR_GENERAL_ERROR;
+ mutex_unlock (pmutex);
return CKR_OK;
}
@@ -224,9 +192,9 @@ free_module_unlocked (void *data)
assert (mod->ref_count == 0);
if (mod->dl_module)
- dlclose (mod->dl_module);
+ module_close (mod->dl_module);
- pthread_mutex_destroy (&mod->initialize_mutex);
+ mutex_uninit (&mod->initialize_mutex);
hash_free (mod->config);
free (mod->name);
free (mod);
@@ -246,7 +214,7 @@ alloc_module_unlocked (void)
mod->init_args.LockMutex = lock_mutex;
mod->init_args.UnlockMutex = unlock_mutex;
mod->init_args.flags = CKF_OS_LOCKING_OK;
- pthread_mutex_init (&mod->initialize_mutex, NULL);
+ mutex_init (&mod->initialize_mutex);
return mod;
}
@@ -294,16 +262,16 @@ dlopen_and_get_function_list (Module *mod, const char *path)
assert (mod);
assert (path);
- mod->dl_module = dlopen (path, RTLD_LOCAL | RTLD_NOW);
+ mod->dl_module = module_open (path);
if (mod->dl_module == NULL) {
- _p11_message ("couldn't load module: %s: %s", path, dlerror ());
+ _p11_message ("couldn't load module: %s: %s", path, module_error ());
return CKR_GENERAL_ERROR;
}
- gfl = dlsym (mod->dl_module, "C_GetFunctionList");
+ gfl = module_symbol (mod->dl_module, "C_GetFunctionList");
if (!gfl) {
_p11_message ("couldn't find C_GetFunctionList entry point in module: %s: %s",
- path, dlerror ());
+ path, module_error ());
return CKR_GENERAL_ERROR;
}
@@ -515,10 +483,10 @@ static CK_RV
initialize_module_unlocked_reentrant (Module *mod)
{
CK_RV rv = CKR_OK;
- pthread_t self;
+ thread_t self;
assert (mod);
- self = pthread_self ();
+ self = thread_self ();
if (mod->initialize_thread == self) {
_p11_message ("p11-kit initialization called recursively");
@@ -533,7 +501,7 @@ initialize_module_unlocked_reentrant (Module *mod)
mod->initialize_thread = self;
/* Change over to the module specific mutex */
- pthread_mutex_lock (&mod->initialize_mutex);
+ mutex_lock (&mod->initialize_mutex);
_p11_unlock ();
if (!mod->initialize_called) {
@@ -554,7 +522,7 @@ initialize_module_unlocked_reentrant (Module *mod)
rv = CKR_OK;
}
- pthread_mutex_unlock (&mod->initialize_mutex);
+ mutex_unlock (&mod->initialize_mutex);
_p11_lock ();
/* Don't claim reference if failed */
@@ -565,6 +533,8 @@ initialize_module_unlocked_reentrant (Module *mod)
return rv;
}
+#ifdef OS_UNIX
+
static void
reinitialize_after_fork (void)
{
@@ -593,6 +563,8 @@ reinitialize_after_fork (void)
_p11_kit_proxy_after_fork ();
}
+#endif /* OS_UNIX */
+
static CK_RV
init_globals_unlocked (void)
{
@@ -607,7 +579,9 @@ init_globals_unlocked (void)
if (once)
return CKR_OK;
+#ifdef OS_UNIX
pthread_atfork (NULL, NULL, reinitialize_after_fork);
+#endif
once = 1;
return CKR_OK;
@@ -654,7 +628,7 @@ finalize_module_unlocked_reentrant (Module *mod)
*/
++mod->ref_count;
- pthread_mutex_lock (&mod->initialize_mutex);
+ mutex_lock (&mod->initialize_mutex);
_p11_unlock ();
if (mod->initialize_called) {
@@ -665,7 +639,7 @@ finalize_module_unlocked_reentrant (Module *mod)
mod->initialize_called = 0;
}
- pthread_mutex_unlock (&mod->initialize_mutex);
+ mutex_unlock (&mod->initialize_mutex);
_p11_lock ();
/* Match the increment above */
@@ -748,6 +722,8 @@ p11_kit_initialize_registered (void)
/* WARNING: This function must be reentrant */
debug ("in");
+ _p11_library_init_once ();
+
_p11_lock ();
_p11_kit_clear_message ();
@@ -833,6 +809,8 @@ p11_kit_finalize_registered (void)
/* WARNING: This function must be reentrant */
debug ("in");
+ _p11_library_init_once ();
+
_p11_lock ();
_p11_kit_clear_message ();
@@ -886,6 +864,8 @@ p11_kit_registered_modules (void)
{
CK_FUNCTION_LIST_PTR_PTR result;
+ _p11_library_init_once ();
+
_p11_lock ();
_p11_kit_clear_message ();
@@ -916,6 +896,8 @@ p11_kit_registered_module_to_name (CK_FUNCTION_LIST_PTR module)
Module *mod;
char *name = NULL;
+ _p11_library_init_once ();
+
_p11_lock ();
_p11_kit_clear_message ();
@@ -980,6 +962,8 @@ p11_kit_registered_option (CK_FUNCTION_LIST_PTR module, const char *field)
char *option = NULL;
hashmap *config = NULL;
+ _p11_library_init_once ();
+
_p11_lock ();
_p11_kit_clear_message ();
@@ -1044,6 +1028,8 @@ p11_kit_initialize_module (CK_FUNCTION_LIST_PTR module)
/* WARNING: This function must be reentrant for the same arguments */
debug ("in");
+ _p11_library_init_once ();
+
_p11_lock ();
_p11_kit_clear_message ();
@@ -1127,6 +1113,8 @@ p11_kit_finalize_module (CK_FUNCTION_LIST_PTR module)
/* WARNING: This function must be reentrant for the same arguments */
debug ("in");
+ _p11_library_init_once ();
+
_p11_lock ();
_p11_kit_clear_message ();
@@ -1191,6 +1179,8 @@ p11_kit_load_initialize_module (const char *module_path,
/* WARNING: This function must be reentrant for the same arguments */
debug ("in: %s", module_path);
+ _p11_library_init_once ();
+
_p11_lock ();
_p11_kit_clear_message ();
diff --git a/p11-kit/private.h b/p11-kit/private.h
index b5a8653..a8f46c5 100644
--- a/p11-kit/private.h
+++ b/p11-kit/private.h
@@ -36,15 +36,45 @@
#define __P11_KIT_PRIVATE_H__
#include "pkcs11.h"
-#include "pthread.h"
+#include "compat.h"
-extern pthread_mutex_t _p11_mutex;
+extern mutex_t _p11_mutex;
-#define _p11_lock() pthread_mutex_lock (&_p11_mutex);
+#define P11_MAX_MESSAGE 512
-#define _p11_unlock() pthread_mutex_unlock (&_p11_mutex);
+typedef struct {
+ char message[P11_MAX_MESSAGE];
+#ifdef OS_WIN32
+ void *last_error;
+#endif
+} p11_local;
-void _p11_message (const char* msg, ...);
+#define _p11_lock() mutex_lock (&_p11_mutex);
+
+#define _p11_unlock() mutex_unlock (&_p11_mutex);
+
+void _p11_message (const char* msg, ...);
+
+p11_local * _p11_library_get_thread_local (void);
+
+#ifdef OS_WIN32
+
+/* No implementation, because done by DllMain */
+#define _p11_library_init_once()
+
+#else /* !OS_WIN32 */
+
+extern pthread_once_t _p11_once;
+
+#define _p11_library_init_once() \
+ pthread_once (&_p11_once, _p11_library_init);
+
+#endif /* !OS_WIN32 */
+
+
+void _p11_library_init (void);
+
+void _p11_library_uninit (void);
CK_FUNCTION_LIST_PTR_PTR _p11_kit_registered_modules_unlocked (void);
diff --git a/p11-kit/proxy.c b/p11-kit/proxy.c
index 0f0fc42..ebb1309 100644
--- a/p11-kit/proxy.c
+++ b/p11-kit/proxy.c
@@ -38,6 +38,7 @@
#define DEBUG_FLAG DEBUG_PROXY
#include "debug.h"
#include "hashmap.h"
+#define CRYPTOKI_EXPORTS
#include "pkcs11.h"
#include "p11-kit.h"
#include "private.h"
@@ -46,7 +47,6 @@
#include <sys/types.h>
#include <assert.h>
#include <errno.h>
-#include <pthread.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdlib.h>
@@ -1389,8 +1389,13 @@ static CK_FUNCTION_LIST proxy_function_list = {
proxy_C_WaitForSlotEvent
};
+#ifdef OS_WIN32
+__declspec(dllexport)
+#endif
+
CK_RV
C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list)
{
+ _p11_library_init_once ();
return proxy_C_GetFunctionList (list);
}
diff --git a/p11-kit/util.c b/p11-kit/util.c
index fdf434b..eab0b13 100644
--- a/p11-kit/util.c
+++ b/p11-kit/util.c
@@ -36,6 +36,7 @@
#include "config.h"
+#include "debug.h"
#include "p11-kit.h"
#include "private.h"
#include "util.h"
@@ -46,6 +47,18 @@
#include <stdio.h>
#include <string.h>
+/*
+ * This is the mutex that protects the global data of this library
+ * and the pkcs11 proxy module. Note that we *never* call into our
+ * underlying pkcs11 modules while holding this mutex. Therefore it
+ * doesn't have to be recursive and we can keep things simple.
+ */
+mutex_t _p11_mutex;
+
+#ifdef OS_UNIX
+pthread_once_t _p11_once;
+#endif
+
/**
* SECTION:p11-kit-future
* @title: Future
@@ -56,9 +69,6 @@
* MACRO. See the p11-kit.h header for more details.
*/
-#define MAX_MESSAGE 512
-static pthread_once_t key_once = PTHREAD_ONCE_INIT;
-static pthread_key_t message_buffer_key = 0;
static int print_messages = 1;
void*
@@ -143,44 +153,34 @@ p11_kit_space_strdup (const unsigned char *string, size_t max_length)
}
static void
-create_message_buffer_key (void)
-{
- pthread_key_create (&message_buffer_key, free);
-}
-
-static void
store_message_buffer (const char* msg, size_t length)
{
- char *thread_buf;
+ p11_local *local;
- if (length > MAX_MESSAGE - 1)
- length = MAX_MESSAGE - 1;
+ if (length > P11_MAX_MESSAGE - 1)
+ length = P11_MAX_MESSAGE - 1;
- pthread_once (&key_once, create_message_buffer_key);
- thread_buf = pthread_getspecific (message_buffer_key);
- if (!thread_buf) {
- thread_buf = malloc (MAX_MESSAGE);
- pthread_setspecific (message_buffer_key, thread_buf);
+ local = _p11_library_get_thread_local ();
+ if (local != NULL) {
+ memcpy (local->message, msg, length);
+ local->message[length] = 0;
}
-
- memcpy (thread_buf, msg, length);
- thread_buf[length] = 0;
}
void
_p11_message (const char* msg, ...)
{
- char buffer[MAX_MESSAGE];
+ char buffer[P11_MAX_MESSAGE];
va_list va;
size_t length;
va_start (va, msg);
- length = vsnprintf (buffer, MAX_MESSAGE - 1, msg, va);
+ length = vsnprintf (buffer, P11_MAX_MESSAGE - 1, msg, va);
va_end (va);
/* Was it truncated? */
- if (length > MAX_MESSAGE - 1)
- length = MAX_MESSAGE - 1;
+ if (length > P11_MAX_MESSAGE - 1)
+ length = P11_MAX_MESSAGE - 1;
buffer[length] = 0;
/* If printing is not disabled, just print out */
@@ -220,20 +220,18 @@ p11_kit_be_quiet (void)
const char*
p11_kit_message (void)
{
- char *thread_buf;
- pthread_once (&key_once, create_message_buffer_key);
- thread_buf = pthread_getspecific (message_buffer_key);
- return thread_buf && thread_buf[0] ? thread_buf : NULL;
+ p11_local *local;
+ local = _p11_library_get_thread_local ();
+ return local && local->message[0] ? local->message : NULL;
}
void
_p11_kit_clear_message (void)
{
- char *thread_buf;
- pthread_once (&key_once, create_message_buffer_key);
- thread_buf = pthread_getspecific (message_buffer_key);
- if (thread_buf != NULL)
- thread_buf[0] = 0;
+ p11_local *local;
+ local = _p11_library_get_thread_local ();
+ if (local != NULL)
+ local->message[0] = 0;
}
void
@@ -246,3 +244,127 @@ _p11_kit_default_message (CK_RV rv)
store_message_buffer (msg, strlen (msg));
}
}
+
+#ifdef OS_UNIX
+
+static pthread_key_t thread_local = 0;
+
+p11_local *
+_p11_library_get_thread_local (void)
+{
+ p11_local *local;
+
+ _p11_library_init_once ();
+
+ local = pthread_getspecific (thread_local);
+ if (local == NULL) {
+ local = calloc (1, sizeof (p11_local));
+ pthread_setspecific (thread_local, local);
+ }
+
+ return local;
+}
+
+void
+_p11_library_init (void)
+{
+ debug_init ();
+ mutex_init (&_p11_mutex);
+ pthread_key_create (&thread_local, free);
+}
+
+void
+_p11_library_uninit (void)
+{
+ pthread_key_delete (thread_local);
+ mutex_uninit (&_p11_mutex);
+}
+
+#endif /* OS_UNIX */
+
+#ifdef OS_WIN32
+
+static DWORD thread_local = TLS_OUT_OF_INDEXES;
+
+BOOL WINAPI DllMain (HINSTANCE, DWORD, LPVOID);
+
+p11_local *
+_p11_library_get_thread_local (void)
+{
+ LPVOID data;
+
+ if (thread_local == TLS_OUT_OF_INDEXES)
+ return NULL;
+
+ data = TlsGetValue (thread_local);
+ if (data == NULL) {
+ data = LocalAlloc (LPTR, sizeof (p11_local));
+ TlsSetValue (thread_local, data);
+ }
+
+ return (p11_local *)data;
+}
+
+void
+_p11_library_init (void)
+{
+ debug_init ();
+ mutex_init (&_p11_mutex);
+ thread_local = TlsAlloc ();
+}
+
+static void
+free_tls_value (LPVOID data)
+{
+ p11_local *local = data;
+ if (local->last_error)
+ LocalFree (local->last_error);
+ LocalFree (data);
+}
+
+void
+_p11_library_uninit (void)
+{
+ LPVOID data;
+
+ if (thread_local != TLS_OUT_OF_INDEXES) {
+ data = TlsGetValue (thread_local);
+ free_tls_value (data);
+ TlsFree (thread_local);
+ }
+ mutex_uninit (&_p11_mutex);
+}
+
+BOOL WINAPI
+DllMain (HINSTANCE instance,
+ DWORD reason,
+ LPVOID reserved)
+{
+ LPVOID data;
+
+ switch (reason) {
+ case DLL_PROCESS_ATTACH:
+ _p11_library_init ();
+ if (thread_local == TLS_OUT_OF_INDEXES)
+ return FALSE;
+ break;
+
+ case DLL_THREAD_DETACH:
+ if (thread_local != TLS_OUT_OF_INDEXES) {
+ data = TlsGetValue (thread_local);
+ free_tls_value (data);
+ }
+ break;
+
+ case DLL_PROCESS_DETACH:
+ _p11_library_uninit ();
+ break;
+
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+#endif /* OS_WIN32 */