Index: Makefile.in ================================================================== --- Makefile.in +++ Makefile.in @@ -48,11 +48,11 @@ rm -f libcackey_g.a $(AR) rc libcackey_g.a cackey_g.o -$(RANLIB) libcackey_g.a libcackey_wrap.@SHOBJEXT@: libcackey_wrap.o - $(CC) $(SHOBJFLAGS) $(SHOBJLDFLAGS) -o libcackey_wrap.@SHOBJEXT@ libcackey_wrap.o + $(CC) $(SHOBJFLAGS) $(SHOBJLDFLAGS) -o libcackey_wrap.@SHOBJEXT@ libcackey_wrap.o -ldl -@WEAKENSYMS@ "libcackey_wrap.@SHOBJEXT@" -@REMOVESYMS@ "libcackey_wrap.@SHOBJEXT@" libcackey_wrap.o: libcackey_wrap.c $(CC) $(SHOBJFLAGS) -o libcackey_wrap.o -c libcackey_wrap.c Index: build/libcackey_wrap.c.in ================================================================== --- build/libcackey_wrap.c.in +++ build/libcackey_wrap.c.in @@ -1,13 +1,13 @@ #define _GNU_SOURCE #include #include "config.h" -#include #include #include +#include #define CK_PTR * #define CK_DEFINE_FUNCTION(returnType, name) returnType name #define CK_DECLARE_FUNCTION(returnType, name) returnType name #define CK_DECLARE_FUNCTION_POINTER(returnType, name) returnType (* name) @@ -15,12 +15,83 @@ #ifndef NULL_PTR # define NULL_PTR 0 #endif #include "./pkcs11/pkcs11.h" + +#ifndef CACKEY_LIBRARY_FILE +#define CACKEY_LIBRARY_FILE "libcackey_g.so" +#endif + +void abort(void); +void free(void *ptr); static void *libcackey_wrap_handle = NULL_PTR; + +typedef enum { + LIBCACKEY_WRAP_MUTEX_UNINIT = 0, + LIBCACKEY_WRAP_MUTEX_INIT, + LIBCACKEY_WRAP_MUTEX_UNLOCKED, + LIBCACKEY_WRAP_MUTEX_LOCKED, +} libcackey_wrap_mutexes_states_t; +static libcackey_wrap_mutexes_states_t libcackey_wrap_mutexes[16] = {LIBCACKEY_WRAP_MUTEX_UNINIT}; + +typedef libcackey_wrap_mutexes_states_t *pthread_mutex_t; +typedef int pthread_mutexattr_t; + +int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr) { + libcackey_wrap_mutexes_states_t *mutex_; + int idx; + + for (idx = 0; idx < (sizeof(libcackey_wrap_mutexes) / sizeof(libcackey_wrap_mutexes[0])); idx++) { + if (libcackey_wrap_mutexes[idx] == LIBCACKEY_WRAP_MUTEX_UNINIT) { + libcackey_wrap_mutexes[idx] = LIBCACKEY_WRAP_MUTEX_INIT; + mutex_ = &libcackey_wrap_mutexes[idx]; + break; + } + } + + if (!mutex_) { + return(1); + } + + *mutex = mutex_; + + return(0); +} + +int pthread_mutex_destroy(pthread_mutex_t *mutex) { + **mutex = LIBCACKEY_WRAP_MUTEX_UNINIT; + + return(0); +} + +int pthread_mutex_lock(pthread_mutex_t *mutex) { + struct timespec sleeptime; + + while (**mutex == LIBCACKEY_WRAP_MUTEX_LOCKED) { + sleeptime.tv_sec = 0; + sleeptime.tv_nsec = 1000000; + nanosleep(&sleeptime, NULL); +fprintf(stderr, "mutex %p is locked\n", mutex); fflush(stderr); + /* Do nothing */ + } + +fprintf(stderr, "locking mutex %p\n", mutex); fflush(stderr); + **mutex = LIBCACKEY_WRAP_MUTEX_LOCKED; +fprintf(stderr, "locked mutex %p\n", mutex); fflush(stderr); + + return(CKR_OK); +} + +int pthread_mutex_unlock(pthread_mutex_t *mutex) { +fprintf(stderr, "unlocking mutex %p\n", mutex); fflush(stderr); + **mutex = LIBCACKEY_WRAP_MUTEX_UNLOCKED; +fprintf(stderr, "unlocked mutex %p\n", mutex); fflush(stderr); + + return(CKR_OK); +} static void libcackey_wrap_init(void) { Dl_info libinfo; int dladdr_ret; char *library, *libraryDir, *libraryDirLastSlash; @@ -55,13 +126,14 @@ return; } *libraryDirLastSlash = '\0'; - asprintf(&library, "%s/libcackey.so", libraryDir); + asprintf(&library, "%s/" CACKEY_LIBRARY_FILE, libraryDir); libcackey_wrap_handle = dlmopen(LM_ID_NEWLM, library, RTLD_LOCAL | RTLD_NOW); + libcackey_wrap_handle = dlmopen(LM_ID_NEWLM, , RTLD_LOCAL | RTLD_NOW); if (!libcackey_wrap_handle) { fprintf(stderr, "Unable to load \"%s\": %s\n", library, dlerror()); abort(); @@ -69,7 +141,19 @@ return; } free(library); + return; +} + +static void libcackey_wrap_fini(void) { + if (!libcackey_wrap_handle) { + return; + } + + dlclose(libcackey_wrap_handle); + + libcackey_wrap_handle = NULL_PTR; + return; } Index: build/make-libcackey_wrap ================================================================== --- build/make-libcackey_wrap +++ build/make-libcackey_wrap @@ -2,12 +2,28 @@ cd "$(dirname "${BASH_SOURCE[0]}")" || exit 1 cat libcackey_wrap.c.in +functionList=() +while IFS='' read -r line; do + function="$(echo "${line}" | cut -f 2 -d , | cut -f 1 -d ')' | sed 's@ *@@g')" + + if [ "${function}" = 'C_LoginMutexArg' ]; then + continue + fi + + functionList=("${functionList[@]}" "${function}") +done < <(grep '^CK_DEFINE_FUNCTION' ../cackey.c) + grep '^CK_DEFINE_FUNCTION' ../cackey.c | while IFS='' read -r line; do function="$(echo "${line}" | cut -f 2 -d , | cut -f 1 -d ')' | sed 's@ *@@g')" + + if [ "${function}" = 'C_LoginMutexArg' ]; then + continue + fi + args="$(echo "${line}" | cut -f 3 -d '(' | cut -f 1 -d ')' | tr ',' $'\n' | sed 's@^ *@@')" argNames=() while read argType argName; do argNames=("${argNames[@]}" "${argName}") done <<<"${args}" @@ -19,13 +35,43 @@ argNamesList="$(echo "${argNamesList}" | cut -c 3-)" echo '' echo "${line}" echo $'\t'"CK_RV (*func)($(echo "${args}" | tr $'\n' ',' | sed 's@,*$@@;s@,@, @g'));" + case "${function}" in + C_Finalize) + echo $'\t''CK_RV retval;' + ;; + C_GetFunctionList) + echo $'\t''CK_RV retval;' + echo $'\t''CK_FUNCTION_LIST_PTR pFunctionList;' + ;; + esac + echo '' echo $'\t''libcackey_wrap_init();' + echo '' echo $'\t'"func = dlsym(libcackey_wrap_handle, \"${function}\");" echo '' - echo $'\t'"return(func($argNamesList));" + if [ "${function}" = 'C_Finalize' ]; then + echo $'\t'"retval = func($argNamesList);" + echo '' + echo $'\t''libcackey_wrap_fini();' + echo '' + echo $'\t''return(retval);' + elif [ "${function}" = 'C_GetFunctionList' ]; then + echo $'\t'"retval = func($argNamesList);" + echo '' + echo $'\t''if (retval == CKR_OK) {' + echo $'\t\t''pFunctionList = *ppFunctionList;' + for function in "${functionList[@]}"; do + echo $'\t\t'"pFunctionList->${function} = ${function};" + done + echo $'\t''}' + echo '' + echo $'\t''return(retval);' + else + echo $'\t'"return(func($argNamesList));" + fi echo '}' done Index: test.c ================================================================== --- test.c +++ test.c @@ -555,13 +555,13 @@ } printf("\n"); } } - chk_rv = C_OpenSession(slots[0], CKF_SERIAL_SESSION, NULL, NULL, &hSession); + chk_rv = C_OpenSession(slots[1], CKF_SERIAL_SESSION, NULL, NULL, &hSession); if (chk_rv == CKR_OK) { - chk_rv = C_GetTokenInfo(slots[0], &tokenInfo); + chk_rv = C_GetTokenInfo(slots[1], &tokenInfo); if (chk_rv != CKR_OK) { return(1); } if ((tokenInfo.flags & CKF_LOGIN_REQUIRED) == CKF_LOGIN_REQUIRED && (tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) == 0) {