some work on fast reauth
[mech_eap.orig] / init_sec_context.c
index dd90745..173f234 100644 (file)
@@ -234,25 +234,37 @@ initReady(OM_uint32 *minor, gss_ctx_id_t ctx)
     OM_uint32 major;
     const unsigned char *key;
     size_t keyLength;
+    krb5_enctype encryptionType;
+    int gotKey = 0;
 
     /* Cache encryption type derived from selected mechanism OID */
-    major = gssEapOidToEnctype(minor, ctx->mechanismUsed, &ctx->encryptionType);
+    major = gssEapOidToEnctype(minor, ctx->mechanismUsed, &encryptionType);
     if (GSS_ERROR(major))
         return major;
 
-    if (ctx->encryptionType != ENCTYPE_NULL &&
+    if (encryptionType != ENCTYPE_NULL &&
         eap_key_available(ctx->initiatorCtx.eap)) {
         key = eap_get_eapKeyData(ctx->initiatorCtx.eap, &keyLength);
 
-        major = gssEapDeriveRfc3961Key(minor, key, keyLength,
-                                       ctx->encryptionType, &ctx->rfc3961Key);
-        if (GSS_ERROR(major))
-            return major;
+        if (keyLength >= EAP_EMSK_LEN) {
+            major = gssEapDeriveRfc3961Key(minor,
+                                           &key[EAP_EMSK_LEN / 2],
+                                           EAP_EMSK_LEN / 2,
+                                           encryptionType,
+                                           &ctx->rfc3961Key);
+               if (GSS_ERROR(major))
+                   return major;
+
+            major = rfc3961ChecksumTypeForKey(minor, &ctx->rfc3961Key,
+                                              &ctx->checksumType);
+            if (GSS_ERROR(major))
+                return major;
+            gotKey++;
+        }
+    }
 
-        major = rfc3961ChecksumTypeForKey(minor, &ctx->rfc3961Key,
-                                           &ctx->checksumType);
-        if (GSS_ERROR(major))
-            return major;
+    if (gotKey) {
+        ctx->encryptionType = encryptionType;
     } else {
         /*
          * draft-howlett-eap-gss says that integrity/confidentialty should
@@ -274,8 +286,6 @@ initReady(OM_uint32 *minor, gss_ctx_id_t ctx)
     return GSS_S_COMPLETE;
 }
 
-static gss_buffer_desc emptyBuffer = GSS_C_EMPTY_BUFFER;
-
 static OM_uint32
 eapGssSmInitIdentity(OM_uint32 *minor,
                      gss_cred_id_t cred,
@@ -288,9 +298,9 @@ eapGssSmInitIdentity(OM_uint32 *minor,
                      gss_buffer_t inputToken,
                      gss_buffer_t outputToken)
 {
-    int initialContextToken;
     time_t now;
     OM_uint32 major;
+    int initialContextToken;
 
     initialContextToken = (inputToken == GSS_C_NO_BUFFER ||
                            inputToken->length == 0);
@@ -303,11 +313,11 @@ eapGssSmInitIdentity(OM_uint32 *minor,
     else
         ctx->expiryTime = now + timeReq;
 
-    major = gss_duplicate_name(minor, cred->name, &ctx->initiatorName);
+    major = gssEapDuplicateName(minor, cred->name, &ctx->initiatorName);
     if (GSS_ERROR(major))
         return major;
 
-    major = gss_duplicate_name(minor, target, &ctx->acceptorName);
+    major = gssEapDuplicateName(minor, target, &ctx->acceptorName);
     if (GSS_ERROR(major))
         return major;
 
@@ -326,15 +336,13 @@ eapGssSmInitIdentity(OM_uint32 *minor,
     if (!gssEapCredAvailable(cred, ctx->mechanismUsed))
         return GSS_S_BAD_MECH;
 
-    major = duplicateBuffer(minor, &emptyBuffer, outputToken);
-    if (GSS_ERROR(major))
-        return major;
-
     ctx->state = EAP_STATE_AUTHENTICATE;
 
     return GSS_S_CONTINUE_NEEDED;
 }
 
+static struct wpabuf emptyWpaBuffer;
+
 static OM_uint32
 eapGssSmInitAuthenticate(OM_uint32 *minor,
                          gss_cred_id_t cred,
@@ -351,6 +359,10 @@ eapGssSmInitAuthenticate(OM_uint32 *minor,
     OM_uint32 tmpMinor;
     int code;
     struct wpabuf *resp = NULL;
+    int initialContextToken;
+
+    initialContextToken = (inputToken == GSS_C_NO_BUFFER ||
+                           inputToken->length == 0);
 
     major = peerConfigInit(minor, cred, ctx);
     if (GSS_ERROR(major))
@@ -360,7 +372,6 @@ eapGssSmInitAuthenticate(OM_uint32 *minor,
         struct eap_config eapConfig;
 
         memset(&eapConfig, 0, sizeof(eapConfig));
-        ctx->flags |= CTX_FLAG_EAP_PORT_ENABLED;
 
         ctx->initiatorCtx.eap = eap_peer_sm_init(ctx,
                                                  &gssEapPolicyCallbacks,
@@ -370,6 +381,8 @@ eapGssSmInitAuthenticate(OM_uint32 *minor,
             major = GSS_S_FAILURE;
             goto cleanup;
         }
+
+        ctx->flags |= CTX_FLAG_EAP_RESTART | CTX_FLAG_EAP_PORT_ENABLED;
     }
 
     ctx->flags |= CTX_FLAG_EAP_REQ; /* we have a Request from the acceptor */
@@ -381,12 +394,9 @@ eapGssSmInitAuthenticate(OM_uint32 *minor,
 
     code = eap_peer_sm_step(ctx->initiatorCtx.eap);
     if (ctx->flags & CTX_FLAG_EAP_RESP) {
-
         ctx->flags &= ~(CTX_FLAG_EAP_RESP);
 
         resp = eap_get_eapRespData(ctx->initiatorCtx.eap);
-        if (resp != NULL) {
-        }
     } else if (ctx->flags & CTX_FLAG_EAP_SUCCESS) {
         major = initReady(minor, ctx);
         if (GSS_ERROR(major))
@@ -397,8 +407,11 @@ eapGssSmInitAuthenticate(OM_uint32 *minor,
         ctx->state = EAP_STATE_GSS_CHANNEL_BINDINGS;
     } else if (ctx->flags & CTX_FLAG_EAP_FAIL) {
         major = GSS_S_DEFECTIVE_CREDENTIAL;
-    } else if (code == 0) {
-        major = GSS_S_FAILURE;
+    } else if (code == 0 && initialContextToken) {
+        resp = &emptyWpaBuffer;
+        major = GSS_S_CONTINUE_NEEDED;
+    } else {
+        major = GSS_S_DEFECTIVE_TOKEN;
     }
 
 cleanup:
@@ -477,6 +490,23 @@ cleanup:
 }
 
 static OM_uint32
+eapGssSmInitKrbCred(OM_uint32 *minor,
+                    gss_cred_id_t cred,
+                    gss_ctx_id_t ctx,
+                    gss_name_t target,
+                    gss_OID mech,
+                    OM_uint32 reqFlags,
+                    OM_uint32 timeReq,
+                    gss_channel_bindings_t chanBindings,
+                    gss_buffer_t inputToken,
+                    gss_buffer_t outputToken)
+{
+    /* Called with already established context */
+    *minor = EINVAL;
+    return GSS_S_BAD_STATUS;
+}
+
+static OM_uint32
 eapGssSmInitEstablished(OM_uint32 *minor,
                         gss_cred_id_t cred,
                         gss_ctx_id_t ctx,
@@ -510,6 +540,7 @@ static struct gss_eap_initiator_sm {
     { TOK_TYPE_NONE,    TOK_TYPE_EAP_RESP,  eapGssSmInitIdentity            },
     { TOK_TYPE_EAP_REQ, TOK_TYPE_EAP_RESP,  eapGssSmInitAuthenticate        },
     { TOK_TYPE_NONE,    TOK_TYPE_GSS_CB,    eapGssSmInitGssChannelBindings  },
+    { TOK_TYPE_KRB_CRED,TOK_TYPE_NONE,      eapGssSmInitKrbCred             },
     { TOK_TYPE_NONE,    TOK_TYPE_NONE,      eapGssSmInitEstablished         },
 };
 
@@ -609,7 +640,7 @@ gss_init_sec_context(OM_uint32 *minor,
     if (ret_flags != NULL)
         *ret_flags = ctx->gssFlags;
     if (time_rec != NULL)
-        gss_context_time(&tmpMinor, ctx, time_rec);
+        gssEapContextTime(&tmpMinor, ctx, time_rec);
 
     assert(ctx->state == EAP_STATE_ESTABLISHED || major == GSS_S_CONTINUE_NEEDED);