Merge TLD code from Windows port, after cleanup
authorLuke Howard <lukeh@padl.com>
Tue, 13 Sep 2011 05:02:41 +0000 (15:02 +1000)
committerLuke Howard <lukeh@padl.com>
Tue, 13 Sep 2011 05:02:41 +0000 (15:02 +1000)
mech_eap/Makefile.am
mech_eap/display_status.c
mech_eap/util.h
mech_eap/util_krb.c
mech_eap/util_tld.c [new file with mode: 0644]

index 86b575e..13fc3dd 100644 (file)
@@ -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                                  \
index 78738ff..e826b19 100644 (file)
 
 #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;
index 905916b..6fd31d7 100644 (file)
@@ -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
index 88ad6dd..779c812 100644 (file)
 
 #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/mech_eap/util_tld.c b/mech_eap/util_tld.c
new file mode 100644 (file)
index 0000000..38e6a10
--- /dev/null
@@ -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 */