Use stored identity if cached identity matches
authorLuke Howard <lukeh@padl.com>
Fri, 18 Mar 2011 13:13:18 +0000 (00:13 +1100)
committerLuke Howard <lukeh@padl.com>
Fri, 18 Mar 2011 13:13:18 +0000 (00:13 +1100)
compare_name.c
util.h
util_cred.c
util_name.c

index 9621908..1da4d98 100644 (file)
@@ -42,20 +42,5 @@ gss_compare_name(OM_uint32 *minor,
                  gss_name_t name2,
                  int *name_equal)
 {
-    krb5_context krbContext;
-
-    *minor = 0;
-
-    if (name1 == GSS_C_NO_NAME && name2 == GSS_C_NO_NAME) {
-        *name_equal = 1;
-    } else if (name1 != GSS_C_NO_NAME && name2 != GSS_C_NO_NAME) {
-        GSSEAP_KRB_INIT(&krbContext);
-
-        /* krbPrincipal is immutable, so lock not required */
-        *name_equal = krb5_principal_compare(krbContext,
-                                             name1->krbPrincipal,
-                                             name2->krbPrincipal);
-    }
-
-    return GSS_S_COMPLETE;
+    return gssEapCompareName(minor, name1, name2, name_equal);
 }
diff --git a/util.h b/util.h
index 8fac347..90256ca 100644 (file)
--- a/util.h
+++ b/util.h
@@ -491,6 +491,12 @@ gssEapDisplayName(OM_uint32 *minor,
                   gss_buffer_t output_name_buffer,
                   gss_OID *output_name_type);
 
+OM_uint32
+gssEapCompareName(OM_uint32 *minor,
+                  gss_name_t name1,
+                  gss_name_t name2,
+                  int *name_equal);
+
 /* util_oid.c */
 OM_uint32
 composeOid(OM_uint32 *minor_status,
index 1a18911..8c4ce55 100644 (file)
@@ -202,7 +202,10 @@ gssEapAcquireCred(OM_uint32 *minor,
 {
     OM_uint32 major, tmpMinor;
     gss_cred_id_t cred;
+    gss_buffer_desc defaultIdentity = GSS_C_EMPTY_BUFFER;
+    gss_name_t defaultIdentityName = GSS_C_NO_NAME;
     gss_buffer_desc defaultCreds = GSS_C_EMPTY_BUFFER;
+    gss_OID nameMech = GSS_C_NO_OID;
 
     /* XXX TODO validate with changed set_cred_option API */
     *pCred = GSS_C_NO_CREDENTIAL;
@@ -228,6 +231,29 @@ gssEapAcquireCred(OM_uint32 *minor,
         break;
     }
 
+    major = gssEapValidateMechs(minor, desiredMechs);
+    if (GSS_ERROR(major))
+        goto cleanup;
+
+    major = duplicateOidSet(minor, desiredMechs, &cred->mechanisms);
+    if (GSS_ERROR(major))
+        goto cleanup;
+
+    if (cred->mechanisms != GSS_C_NO_OID_SET &&
+        cred->mechanisms->count == 1)
+        nameMech = &cred->mechanisms->elements[0];
+
+    if (cred->flags & CRED_FLAG_INITIATE) {
+        major = readDefaultIdentityAndCreds(minor, &defaultIdentity, &defaultCreds);
+        if (GSS_ERROR(major))
+            goto cleanup;
+
+        major = gssEapImportName(minor, &defaultIdentity, GSS_C_NT_USER_NAME,
+                                 nameMech, &defaultIdentityName);
+        if (GSS_ERROR(major))
+            goto cleanup;
+    }
+
     if (desiredName != GSS_C_NO_NAME) {
         GSSEAP_MUTEX_LOCK(&desiredName->mutex);
 
@@ -238,12 +264,22 @@ gssEapAcquireCred(OM_uint32 *minor,
         }
 
         GSSEAP_MUTEX_UNLOCK(&desiredName->mutex);
-    } else {
-        gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER;
-        gss_OID nameType = GSS_C_NO_OID;
-        char serviceName[5 + MAXHOSTNAMELEN];
 
+        if (defaultIdentityName != GSS_C_NO_NAME) {
+            int nameEqual;
+
+            major = gssEapCompareName(minor, desiredName,
+                                      defaultIdentityName, &nameEqual);
+            if (GSS_ERROR(major))
+                goto cleanup;
+            else if (nameEqual)
+                cred->flags |= CRED_FLAG_DEFAULT_IDENTITY;
+        }
+    } else {
         if (cred->flags & CRED_FLAG_ACCEPT) {
+            gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER;
+            char serviceName[5 + MAXHOSTNAMELEN];
+
             /* default host-based service is host@localhost */
             memcpy(serviceName, "host@", 5);
             if (gethostname(&serviceName[5], MAXHOSTNAMELEN) != 0) {
@@ -255,33 +291,19 @@ gssEapAcquireCred(OM_uint32 *minor,
             nameBuf.value = serviceName;
             nameBuf.length = strlen((char *)nameBuf.value);
 
-            nameType = GSS_C_NT_HOSTBASED_SERVICE;
-        } else if (cred->flags & CRED_FLAG_INITIATE) {
-            major = readDefaultIdentityAndCreds(minor, &nameBuf, &defaultCreds);
-            if (GSS_ERROR(major))
-                goto cleanup;
-
-            nameType = GSS_C_NT_USER_NAME;
-        }
-
-        if (nameBuf.length != 0) {
-            gss_OID mech = GSS_C_NO_OID;
-
-            if (cred->mechanisms != GSS_C_NO_OID_SET &&
-                cred->mechanisms->count == 1)
-                mech = &cred->mechanisms->elements[0];
-
-            major = gssEapImportName(minor, &nameBuf, nameType, mech, &cred->name);
+            major = gssEapImportName(minor, &nameBuf, GSS_C_NT_HOSTBASED_SERVICE,
+                                     nameMech, &cred->name);
             if (GSS_ERROR(major))
                 goto cleanup;
+        } else if (cred->flags & CRED_FLAG_INITIATE) {
+            cred->name = defaultIdentityName;
+            defaultIdentityName = GSS_C_NO_NAME;
         }
-
-        if (nameBuf.value != serviceName)
-            gss_release_buffer(&tmpMinor, &nameBuf);
-
         cred->flags |= CRED_FLAG_DEFAULT_IDENTITY;
     }
 
+    assert(cred->name != GSS_C_NO_NAME);
+
     if (password != GSS_C_NO_BUFFER) {
         major = duplicateBuffer(minor, password, &cred->password);
         if (GSS_ERROR(major))
@@ -309,14 +331,6 @@ gssEapAcquireCred(OM_uint32 *minor,
         goto cleanup;
     }
 
-    major = gssEapValidateMechs(minor, desiredMechs);
-    if (GSS_ERROR(major))
-        goto cleanup;
-
-    major = duplicateOidSet(minor, desiredMechs, &cred->mechanisms);
-    if (GSS_ERROR(major))
-        goto cleanup;
-
     if (pActualMechs != NULL) {
         major = duplicateOidSet(minor, cred->mechanisms, pActualMechs);
         if (GSS_ERROR(major))
@@ -334,6 +348,8 @@ gssEapAcquireCred(OM_uint32 *minor,
 cleanup:
     if (GSS_ERROR(major))
         gssEapReleaseCred(&tmpMinor, &cred);
+    gssEapReleaseName(&tmpMinor, &defaultIdentityName);
+    gss_release_buffer(&tmpMinor, &defaultIdentity);
     if (defaultCreds.value != NULL) {
         memset(defaultCreds.value, 0, defaultCreds.length);
         gss_release_buffer(&tmpMinor, &defaultCreds);
index 3112f88..144d26e 100644 (file)
@@ -738,3 +738,27 @@ gssEapDisplayName(OM_uint32 *minor,
 
     return GSS_S_COMPLETE;
 }
+
+OM_uint32
+gssEapCompareName(OM_uint32 *minor,
+                  gss_name_t name1,
+                  gss_name_t name2,
+                  int *name_equal)
+{
+    krb5_context krbContext;
+
+    *minor = 0;
+
+    if (name1 == GSS_C_NO_NAME && name2 == GSS_C_NO_NAME) {
+        *name_equal = 1;
+    } else if (name1 != GSS_C_NO_NAME && name2 != GSS_C_NO_NAME) {
+        GSSEAP_KRB_INIT(&krbContext);
+
+        /* krbPrincipal is immutable, so lock not required */
+        *name_equal = krb5_principal_compare(krbContext,
+                                             name1->krbPrincipal,
+                                             name2->krbPrincipal);
+    }
+
+    return GSS_S_COMPLETE;
+}