From ecf20954105d5ac0b7a47bd4932c2dacc1a96e3e Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Tue, 13 Sep 2011 15:02:41 +1000 Subject: [PATCH] Merge TLD code from Windows port, after cleanup --- moonshot/mech_eap/Makefile.am | 1 + moonshot/mech_eap/display_status.c | 60 ++++++--------- moonshot/mech_eap/util.h | 17 +++++ moonshot/mech_eap/util_krb.c | 35 +++------ moonshot/mech_eap/util_tld.c | 152 +++++++++++++++++++++++++++++++++++++ 5 files changed, 206 insertions(+), 59 deletions(-) create mode 100644 moonshot/mech_eap/util_tld.c diff --git a/moonshot/mech_eap/Makefile.am b/moonshot/mech_eap/Makefile.am index 86b575e..13fc3dd 100644 --- a/moonshot/mech_eap/Makefile.am +++ b/moonshot/mech_eap/Makefile.am @@ -86,6 +86,7 @@ mech_eap_la_SOURCES = \ util_oid.c \ util_ordering.c \ util_sm.c \ + util_tld.c \ util_token.c \ verify_mic.c \ wrap.c \ diff --git a/moonshot/mech_eap/display_status.c b/moonshot/mech_eap/display_status.c index 78738ff..e826b19 100644 --- a/moonshot/mech_eap/display_status.c +++ b/moonshot/mech_eap/display_status.c @@ -36,33 +36,24 @@ #include "gssapiP_eap.h" -static GSSEAP_THREAD_ONCE gssEapStatusInfoKeyOnce = GSSEAP_ONCE_INITIALIZER; -static GSSEAP_THREAD_KEY gssEapStatusInfoKey; - struct gss_eap_status_info { OM_uint32 code; char *message; struct gss_eap_status_info *next; }; -static void -destroyStatusInfo(void *arg) +void +gssEapDestroyStatusInfo(struct gss_eap_status_info *p) { - struct gss_eap_status_info *p = arg, *next; + struct gss_eap_status_info *next; - for (p = arg; p != NULL; p = next) { + for (; p != NULL; p = next) { next = p->next; GSSEAP_FREE(p->message); GSSEAP_FREE(p); } } -static void -createStatusInfoKey(void) -{ - GSSEAP_KEY_CREATE(&gssEapStatusInfoKey, destroyStatusInfo); -} - /* * Associate a message with a mechanism (minor) status code. This function * takes ownership of the message regardless of success. The message must @@ -73,23 +64,23 @@ createStatusInfoKey(void) static void saveStatusInfoNoCopy(OM_uint32 minor, char *message) { - struct gss_eap_status_info **next = NULL, *p; - - GSSEAP_ONCE(&gssEapStatusInfoKeyOnce, createStatusInfoKey); - - p = GSSEAP_GETSPECIFIC(gssEapStatusInfoKey); - for (; p != NULL; p = p->next) { - if (p->code == minor) { - /* Set message in-place */ - if (p->message != NULL) - GSSEAP_FREE(p->message); - p->message = message; - return; + struct gss_eap_status_info **next = NULL, *p=NULL; + struct gss_eap_thread_local_data *tld = gssEapGetThreadLocalData(); + + if (tld != NULL) { + for (p = tld->statusInfo; p != NULL; p = p->next) { + if (p->code == minor) { + /* Set message in-place */ + if (p->message != NULL) + GSSEAP_FREE(p->message); + p->message = message; + return; + } + next = &p->next; } - next = &p->next; + p = GSSEAP_CALLOC(1, sizeof(*p)); } - p = GSSEAP_CALLOC(1, sizeof(*p)); if (p == NULL) { if (message != NULL) GSSEAP_FREE(message); @@ -102,21 +93,20 @@ saveStatusInfoNoCopy(OM_uint32 minor, char *message) if (next != NULL) *next = p; else - GSSEAP_SETSPECIFIC(gssEapStatusInfoKey, p); + tld->statusInfo = p; } static const char * getStatusInfo(OM_uint32 minor) { struct gss_eap_status_info *p; + struct gss_eap_thread_local_data *tld = gssEapGetThreadLocalData(); - GSSEAP_ONCE(&gssEapStatusInfoKeyOnce, createStatusInfoKey); - - for (p = GSSEAP_GETSPECIFIC(gssEapStatusInfoKey); - p != NULL; - p = p->next) { - if (p->code == minor) - return p->message; + if (tld != NULL) { + for (p = tld->statusInfo; p != NULL; p = p->next) { + if (p->code == minor) + return p->message; + } } return NULL; diff --git a/moonshot/mech_eap/util.h b/moonshot/mech_eap/util.h index 905916b..6fd31d7 100644 --- a/moonshot/mech_eap/util.h +++ b/moonshot/mech_eap/util.h @@ -956,6 +956,23 @@ gssBufferToKrbData(gss_buffer_t buffer, krb5_data *data) data->length = buffer->length; } +/* util_tld.c */ +struct gss_eap_status_info; + +struct gss_eap_thread_local_data { + krb5_context krbContext; + struct gss_eap_status_info *statusInfo; +}; + +struct gss_eap_thread_local_data * +gssEapGetThreadLocalData(void); + +void +gssEapDestroyStatusInfo(struct gss_eap_status_info *status); + +void +gssEapDestroyKrbContext(krb5_context context); + #ifdef __cplusplus } #endif diff --git a/moonshot/mech_eap/util_krb.c b/moonshot/mech_eap/util_krb.c index 88ad6dd..779c812 100644 --- a/moonshot/mech_eap/util_krb.c +++ b/moonshot/mech_eap/util_krb.c @@ -36,24 +36,13 @@ #include "gssapiP_eap.h" -static GSSEAP_THREAD_ONCE krbContextKeyOnce = GSSEAP_ONCE_INITIALIZER; -static GSSEAP_THREAD_KEY krbContextKey; - -static void -destroyKrbContext(void *arg) +void +gssEapDestroyKrbContext(krb5_context context) { - krb5_context context = (krb5_context)arg; - if (context != NULL) krb5_free_context(context); } -static void -createKrbContextKey(void) -{ - GSSEAP_KEY_CREATE(&krbContextKey, destroyKrbContext); -} - static krb5_error_code initKrbContext(krb5_context *pKrbContext) { @@ -91,19 +80,17 @@ cleanup: OM_uint32 gssEapKerberosInit(OM_uint32 *minor, krb5_context *context) { + struct gss_eap_thread_local_data *tld; + *minor = 0; - GSSEAP_ONCE(&krbContextKeyOnce, createKrbContextKey); - - *context = GSSEAP_GETSPECIFIC(krbContextKey); - if (*context == NULL) { - *minor = initKrbContext(context); - if (*minor == 0) { - if (GSSEAP_SETSPECIFIC(krbContextKey, *context) != 0) { - *minor = errno; - krb5_free_context(*context); - *context = NULL; - } + tld = gssEapGetThreadLocalData(); + if (tld != NULL) { + *context = tld->krbContext; + if (*context == NULL) { + *minor = initKrbContext(context); + if (*minor == 0) + tld->krbContext = *context; } } diff --git a/moonshot/mech_eap/util_tld.c b/moonshot/mech_eap/util_tld.c new file mode 100644 index 0000000..38e6a10 --- /dev/null +++ b/moonshot/mech_eap/util_tld.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2011, JANET(UK) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. 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. + * + * 3. Neither the name of JANET(UK) nor the names of its contributors + * may 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 HOLDER 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. + */ + +/* + * Thread local data abstraction. + */ + +#include "gssapiP_eap.h" + +/* Clean up thread-local data; called on thread detach */ +static void +destroyThreadLocalData(struct gss_eap_thread_local_data *tld) +{ + if (tld->statusInfo != NULL) + gssEapDestroyStatusInfo(tld->statusInfo); + if (tld->krbContext != NULL) + gssEapDestroyKrbContext(tld->krbContext); + GSSEAP_FREE(tld); +} + +#ifdef WIN32 + +/* + * This is the tls index returned by TlsAlloc() on process init. + * Each thread, on thread attach in DllMain(), allocates its thread-local + * data and uses this index with TlsSetValue() to store it. + * It can then subsequently be retrieved with TlsGetValue(). + */ +static DWORD tlsIndex; + +/* Access thread-local data */ +struct gss_eap_thread_local_data * +gssEapGetThreadLocalData(void) +{ + return TlsGetValue(tlsIndex); +} + +BOOL WINAPI +DllMain(HINSTANCE hDLL, /* DLL module handle */ + DWORD reason, /* reason called */ + LPVOID reserved) /* reserved */ +{ + struct gss_eap_thread_local_data *tlsData; + + switch (reason) { + case DLL_PROCESS_ATTACH: + /* Allocate a TLS index. */ + tlsIndex = TlsAlloc(); + if (tlsIndex == TLS_OUT_OF_INDEXES) + return FALSE; + /* No break: Initialize the index for first thread.*/ + case DLL_THREAD_ATTACH: + /* Initialize the TLS index for this thread. */ + tlsData = GSSEAP_CALLOC(1, sizeof(*tlsData)); + if (tlsData != NULL) + TlsSetValue(tlsIndex, tlsData); + break; + case DLL_THREAD_DETACH: + /* Release the allocated memory for this thread. */ + tlsData = TlsGetValue(tlsIndex); + if (tlsData != NULL) { + destroyThreadLocalData(tlsData); + TlsSetValue(tlsIndex, NULL); + } + break; + case DLL_PROCESS_DETACH: + /* Release the allocated memory for this thread. */ + tlsData = TlsGetValue(tlsIndex); + if (tlsData != NULL) + destroyThreadLocalData(tlsData); + /* Release the TLS index. */ + TlsFree(tlsIndex); + break; + default: + break; + } + + return TRUE; + UNREFERENCED_PARAMETER(hDLL); + UNREFERENCED_PARAMETER(reserved); +} + +#else /* WIN32 */ + +/* pthreads implementation */ + +static GSSEAP_THREAD_ONCE tldKeyOnce = GSSEAP_ONCE_INITIALIZER; +static GSSEAP_THREAD_KEY tldKey; + +static void +pthreadDestroyThreadLocalData(void *arg) +{ + struct gss_eap_thread_local_data* tld = arg; + + if (tld != NULL) + destroyThreadLocalData(tld); +} + +static void +createThreadLocalDataKey(void) +{ + GSSEAP_KEY_CREATE(&tldKey, pthreadDestroyThreadLocalData); +} + +struct gss_eap_thread_local_data * +gssEapGetThreadLocalData() +{ + struct gss_eap_thread_local_data *tld; + + GSSEAP_ONCE(&tldKeyOnce, createThreadLocalDataKey); + + tld = GSSEAP_GETSPECIFIC(tldKey); + if (tld == NULL) { + tld = GSSEAP_CALLOC(1, sizeof(*tld)); + if (tld == NULL) + return NULL; + + GSSEAP_SETSPECIFIC(tldKey, tld); + } + + return tld; +} +#endif /* WIN32 */ -- 2.1.4