diff options
author | Stef Walter <stefw@collabora.co.uk> | 2011-10-17 14:51:31 +0200 |
---|---|---|
committer | Stef Walter <stefw@collabora.co.uk> | 2011-10-17 15:32:41 +0200 |
commit | db92b76e3acb11e330309ebce071ec2e61400a71 (patch) | |
tree | cb11139880974ef8db53dd83a70de8f32d94cc09 /p11-kit | |
parent | b1d9fd5f88ade222fbd2206c7e11c5514c8b5634 (diff) |
Initial port to win32
* Tests do not all yet pass, at least not on wine
* Added abstraction of some non-portable functions in compat.h/c
* Build with an argument like this for win32 support:
./autogen.sh --host=i586-mingw32msvc
* This win32 port needs more work from interested parties
Diffstat (limited to 'p11-kit')
-rw-r--r-- | p11-kit/Makefile.am | 1 | ||||
-rw-r--r-- | p11-kit/compat.c | 114 | ||||
-rw-r--r-- | p11-kit/compat.h | 143 | ||||
-rw-r--r-- | p11-kit/conf.c | 64 | ||||
-rw-r--r-- | p11-kit/debug.c | 31 | ||||
-rw-r--r-- | p11-kit/debug.h | 2 | ||||
-rw-r--r-- | p11-kit/modules.c | 104 | ||||
-rw-r--r-- | p11-kit/private.h | 40 | ||||
-rw-r--r-- | p11-kit/proxy.c | 7 | ||||
-rw-r--r-- | p11-kit/util.c | 188 |
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 */ |