Get simple EAP case working
authorLuke Howard <lukeh@padl.com>
Thu, 9 Sep 2010 15:55:20 +0000 (17:55 +0200)
committerLuke Howard <lukeh@padl.com>
Thu, 9 Sep 2010 15:55:20 +0000 (17:55 +0200)
mech_eap/accept_sec_context.c
mech_eap/display_name.c
mech_eap/gssapiP_eap.h
mech_eap/init_sec_context.c
mech_eap/mech_eap.exports
mech_eap/unwrap_iov.c
mech_eap/util_context.c
mech_eap/util_krb.c
mech_eap/util_token.c
mech_eap/verify_mic.c
mech_eap/wrap_iov.c

index e254ade..332a6c8 100644 (file)
@@ -214,8 +214,7 @@ serverGetEapReqIdText(void *ctx,
 #endif
 
 static OM_uint32
-serverDeriveKey(OM_uint32 *minor,
-                gss_ctx_id_t ctx)
+completeAccept(OM_uint32 *minor, gss_ctx_id_t ctx)
 {
     OM_uint32 major;
     krb5_context krbContext;
@@ -245,6 +244,11 @@ serverDeriveKey(OM_uint32 *minor,
         ctx->gssFlags &= ~(GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG);
     }
 
+    sequenceInit(&ctx->seqState, ctx->recvSeq,
+                 ((ctx->gssFlags & GSS_C_REPLAY_FLAG) != 0),
+                 ((ctx->gssFlags & GSS_C_SEQUENCE_FLAG) != 0),
+                 TRUE);
+
     return GSS_S_COMPLETE;
 }
 
@@ -256,26 +260,24 @@ eapGssSmAcceptAuthenticate(OM_uint32 *minor,
                            gss_channel_bindings_t chanBindings,
                            gss_buffer_t outputToken)
 {
-    OM_uint32 major, tmpMinor, tmpMajor;
+    OM_uint32 major;
+    OM_uint32 tmpMinor, tmpMajor;
     int code;
     struct wpabuf respData;
-    struct eap_config *config = (struct eap_config *)&ctx->acceptorCtx.eapConfig;
     static struct eapol_callbacks cb = { serverGetEapUser, serverGetEapReqIdText };
 
-    wpabuf_set(&respData, inputToken->value, inputToken->length);
-    ctx->acceptorCtx.eapPolInterface->eapRespData = &respData;
-    ctx->acceptorCtx.eapPolInterface->eapResp = TRUE;
-
     if (ctx->acceptorCtx.eap == NULL) {
-        /* initial context token */
-        config->eap_server = 1;
-        config->ssl_ctx = ctx->acceptorCtx.tlsContext;
+        struct eap_config eapConfig;
 
         major = initTls(minor, ctx);
         if (GSS_ERROR(major))
             goto cleanup;
 
-        ctx->acceptorCtx.eap = eap_server_sm_init(ctx, &cb, config);
+        memset(&eapConfig, 0, sizeof(eapConfig));
+        eapConfig.eap_server = 1;
+        eapConfig.ssl_ctx = ctx->acceptorCtx.tlsContext;
+
+        ctx->acceptorCtx.eap = eap_server_sm_init(ctx, &cb, &eapConfig);
         if (ctx->acceptorCtx.eap == NULL) {
             major = GSS_S_FAILURE;
             goto cleanup;
@@ -286,12 +288,18 @@ eapGssSmAcceptAuthenticate(OM_uint32 *minor,
         ctx->acceptorCtx.eapPolInterface->eapRestart = TRUE;
     }
 
-    if (ctx->acceptorName == GSS_C_NO_NAME && cred->name != GSS_C_NO_NAME) {
+    if (ctx->acceptorName == GSS_C_NO_NAME &&
+        cred != GSS_C_NO_CREDENTIAL &&
+        cred->name != GSS_C_NO_NAME) {
         major = gss_duplicate_name(minor, cred->name, &ctx->acceptorName);
         if (GSS_ERROR(major))
             goto cleanup;
     }
 
+    wpabuf_set(&respData, inputToken->value, inputToken->length);
+    ctx->acceptorCtx.eapPolInterface->eapRespData = &respData;
+    ctx->acceptorCtx.eapPolInterface->eapResp = TRUE;
+
     code = eap_server_sm_step(ctx->acceptorCtx.eap);
 
     if (ctx->acceptorCtx.eapPolInterface->eapReq) {
@@ -300,13 +308,9 @@ eapGssSmAcceptAuthenticate(OM_uint32 *minor,
     }
 
     if (ctx->acceptorCtx.eapPolInterface->eapSuccess) {
-        major = serverDeriveKey(minor, ctx);
-        if (GSS_ERROR(major))
-            goto cleanup;
-
         ctx->acceptorCtx.eapPolInterface->eapSuccess = 0;
         ctx->state = EAP_STATE_ESTABLISHED;
-        major = GSS_S_COMPLETE;
+        major = completeAccept(minor, ctx);
     } else if (ctx->acceptorCtx.eapPolInterface->eapFail) {
         ctx->acceptorCtx.eapPolInterface->eapFail = 0;
         major = GSS_S_FAILURE;
@@ -323,11 +327,14 @@ eapGssSmAcceptAuthenticate(OM_uint32 *minor,
         tmpMajor = duplicateBuffer(&tmpMinor, &buf, outputToken);
         if (GSS_ERROR(tmpMajor)) {
             major = tmpMajor;
+            *minor = tmpMinor;
             goto cleanup;
         }
     }
 
 cleanup:
+    ctx->acceptorCtx.eapPolInterface->eapRespData = NULL;
+
     return major;
 }
 
@@ -374,7 +381,8 @@ gss_accept_sec_context(OM_uint32 *minor,
                        OM_uint32 *time_rec,
                        gss_cred_id_t *delegated_cred_handle)
 {
-    OM_uint32 major, tmpMinor;
+    OM_uint32 major;
+    OM_uint32 tmpMajor, tmpMinor;
     gss_ctx_id_t ctx = *context_handle;
     struct eap_gss_acceptor_sm *sm = NULL;
     gss_buffer_desc innerInputToken, innerOutputToken;
@@ -423,28 +431,34 @@ gss_accept_sec_context(OM_uint32 *minor,
             goto cleanup;
     } while (major == GSS_S_CONTINUE_NEEDED && innerOutputToken.length == 0);
 
-    if (src_name != NULL && ctx->initiatorName != GSS_C_NO_NAME) {
-        major = gss_duplicate_name(minor, ctx->initiatorName, src_name);
-        if (GSS_ERROR(major))
-            goto cleanup;
-    }
     if (mech_type != NULL) {
         if (!gssEapInternalizeOid(ctx->mechanismUsed, mech_type))
             duplicateOid(&tmpMinor, ctx->mechanismUsed, mech_type);
     }
     if (innerOutputToken.length != 0) {
-        major = gssEapMakeToken(minor, ctx, &innerOutputToken,
-                                sm->outputTokenType, output_token);
-        if (GSS_ERROR(major))
+        tmpMajor = gssEapMakeToken(&tmpMinor, ctx, &innerOutputToken,
+                                   sm->outputTokenType, output_token);
+        if (GSS_ERROR(tmpMajor)) {
+            major = tmpMajor;
+            *minor = tmpMinor;
             goto cleanup;
+        }
     }
     if (ret_flags != NULL)
         *ret_flags = ctx->gssFlags;
-    if (time_rec != NULL)
-        gss_context_time(&tmpMinor, ctx, time_rec);
     if (delegated_cred_handle != NULL)
         *delegated_cred_handle = GSS_C_NO_CREDENTIAL;
 
+    if (major == GSS_S_COMPLETE) {
+        if (src_name != NULL && ctx->initiatorName != GSS_C_NO_NAME) {
+            major = gss_duplicate_name(&tmpMinor, ctx->initiatorName, src_name);
+            if (GSS_ERROR(major))
+                goto cleanup;
+        }
+        if (time_rec != NULL)
+            gss_context_time(&tmpMinor, ctx, time_rec);
+    }
+
     assert(ctx->state == EAP_STATE_ESTABLISHED || major == GSS_S_CONTINUE_NEEDED);
 
 cleanup:
index 96e1613..9ef4314 100644 (file)
@@ -65,7 +65,8 @@ gss_display_name(OM_uint32 *minor,
 
     krb5_free_unparsed_name(krbContext, krbName);
 
-    *output_name_type = GSS_EAP_NT_PRINCIPAL_NAME;
+    if (output_name_type != NULL)
+        *output_name_type = GSS_EAP_NT_PRINCIPAL_NAME;
 
     return GSS_S_COMPLETE;
 }
index 2369f47..0c19b91 100644 (file)
@@ -49,6 +49,7 @@
 /* EAP includes */
 #include <common.h>
 #include <eap_peer/eap.h>
+#include <eap_peer/eap_i.h>
 #include <eap_peer/eap_config.h>
 #include <crypto/tls.h>                     /* XXX testing implementation only */
 #include <wpabuf.h>
@@ -117,7 +118,6 @@ enum eap_gss_state {
 struct eap_gss_initiator_ctx {
     unsigned int idleWhile;
     struct eap_peer_config eapPeerConfig;
-    struct eap_config eapConfig;
     struct eap_sm *eap;
     struct wpabuf reqData;
 };
@@ -126,7 +126,6 @@ struct eap_gss_acceptor_ctx {
     struct eap_eapol_interface *eapPolInterface;
     void *tlsContext;
     struct eap_sm *eap;
-    struct eap_config eapConfig; /* XXX */
 };
 
 struct gss_ctx_id_struct {
index 119eb4f..48784dd 100644 (file)
@@ -68,6 +68,7 @@ policyVariableToFlag(enum eapol_bool_var variable)
     }
 
     return flag;
+        
 }
 
 static struct eap_peer_config *
@@ -183,6 +184,8 @@ static struct eapol_callbacks gssEapPolicyCallbacks = {
     peerNotifyPending,
 };
 
+extern int wpa_debug_level;
+
 static OM_uint32
 peerConfigInit(OM_uint32 *minor,
                gss_cred_id_t cred,
@@ -197,6 +200,8 @@ peerConfigInit(OM_uint32 *minor,
     GSSEAP_KRB_INIT(&krbContext);
 
     if (loadConfig) {
+        eapPeerConfig->fragment_size = 1024;
+        wpa_debug_level = 0;
     }
 
     code = krb5_unparse_name(krbContext, cred->name->krbPrincipal, &identity);
@@ -228,8 +233,8 @@ peerConfigFree(OM_uint32 *minor,
 }
 
 static OM_uint32
-peerDeriveKey(OM_uint32 *minor,
-              gss_ctx_id_t ctx)
+completeInit(OM_uint32 *minor,
+             gss_ctx_id_t ctx)
 {
     OM_uint32 major;
     const unsigned char *key;
@@ -260,6 +265,11 @@ peerDeriveKey(OM_uint32 *minor,
         ctx->gssFlags &= ~(GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG);
     }
 
+    sequenceInit(&ctx->seqState, ctx->recvSeq,
+                 ((ctx->gssFlags & GSS_C_REPLAY_FLAG) != 0),
+                 ((ctx->gssFlags & GSS_C_SEQUENCE_FLAG) != 0),
+                 TRUE);
+
     return GSS_S_COMPLETE;
 }
 
@@ -275,9 +285,11 @@ eapGssSmInitAuthenticate(OM_uint32 *minor,
                          gss_buffer_t inputToken,
                          gss_buffer_t outputToken)
 {
-    OM_uint32 major, tmpMinor;
+    OM_uint32 major;
+    OM_uint32 tmpMajor, tmpMinor;
     time_t now;
     int initialContextToken = 0, code;
+    struct wpabuf *resp = NULL;
 
     initialContextToken = (inputToken == GSS_C_NO_BUFFER ||
                            inputToken->length == 0);
@@ -287,12 +299,15 @@ eapGssSmInitAuthenticate(OM_uint32 *minor,
         goto cleanup;
 
     if (initialContextToken) {
+        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,
                                                  ctx,
-                                                 &ctx->initiatorCtx.eapConfig);
+                                                 &eapConfig);
 
         time(&now);
         if (timeReq == 0 || timeReq == GSS_C_INDEFINITE)
@@ -318,46 +333,49 @@ eapGssSmInitAuthenticate(OM_uint32 *minor,
         }
         if (GSS_ERROR(major))
             goto cleanup;
+
+        resp = eap_sm_buildIdentity(ctx->initiatorCtx.eap, 0, 0);
+        major = GSS_S_CONTINUE_NEEDED;
+        goto cleanup;
+    } else {
+        ctx->flags |= CTX_FLAG_EAP_REQ; /* we have a Request from the acceptor */
     }
 
     wpabuf_set(&ctx->initiatorCtx.reqData,
                inputToken->value, inputToken->length);
 
-    code = eap_peer_sm_step(ctx->initiatorCtx.eap);
+    major = GSS_S_CONTINUE_NEEDED;
 
+    code = eap_peer_sm_step(ctx->initiatorCtx.eap);
     if (ctx->flags & CTX_FLAG_EAP_RESP) {
-        struct wpabuf *resp;
-        gss_buffer_desc buf;
-
         ctx->flags &= ~(CTX_FLAG_EAP_RESP);
 
         resp = eap_get_eapRespData(ctx->initiatorCtx.eap);
-
-        if (resp != NULL) {
-            buf.length = wpabuf_len(resp);
-            buf.value = (void *)wpabuf_head(resp);
-
-            major = duplicateBuffer(minor, &buf, outputToken);
-            if (GSS_ERROR(major))
-                goto cleanup;
-
-            major = GSS_S_CONTINUE_NEEDED;
-        }
-    }
-
-    if (ctx->flags & CTX_FLAG_EAP_SUCCESS) {
-        major = peerDeriveKey(minor, ctx);
-        if (GSS_ERROR(major))
-            goto cleanup;
-
+    } else if (ctx->flags & CTX_FLAG_EAP_SUCCESS) {
+        major = completeInit(minor, ctx);
         ctx->flags &= ~(CTX_FLAG_EAP_SUCCESS);
         ctx->state = EAP_STATE_ESTABLISHED;
-        major = GSS_S_COMPLETE;
     } else if ((ctx->flags & CTX_FLAG_EAP_FAIL) || code == 0) {
         major = GSS_S_FAILURE;
     }
 
 cleanup:
+    if (resp != NULL) {
+        OM_uint32 tmpMajor;
+        gss_buffer_desc buf;
+
+        assert(major == GSS_S_CONTINUE_NEEDED);
+
+        buf.length = wpabuf_len(resp);
+        buf.value = (void *)wpabuf_head(resp);
+
+        tmpMajor = duplicateBuffer(&tmpMinor, &buf, outputToken);
+        if (GSS_ERROR(tmpMajor)) {
+            major = tmpMajor;
+            *minor = tmpMinor;
+        }
+    }
+
     wpabuf_set(&ctx->initiatorCtx.reqData, NULL, 0);
     peerConfigFree(&tmpMinor, ctx);
 
@@ -462,7 +480,8 @@ gss_init_sec_context(OM_uint32 *minor,
                      OM_uint32 *ret_flags,
                      OM_uint32 *time_rec)
 {
-    OM_uint32 major, tmpMinor;
+    OM_uint32 major;
+    OM_uint32 tmpMajor, tmpMinor;
     gss_ctx_id_t ctx = *context_handle;
     struct eap_gss_initiator_sm *sm = NULL;
     gss_buffer_desc innerInputToken, innerOutputToken;
@@ -531,10 +550,13 @@ gss_init_sec_context(OM_uint32 *minor,
             duplicateOid(&tmpMinor, ctx->mechanismUsed, actual_mech_type);
     }
     if (innerOutputToken.length != 0) {
-        major = gssEapMakeToken(minor, ctx, &innerOutputToken,
-                                sm->outputTokenType, output_token);
-        if (GSS_ERROR(major))
+        tmpMajor = gssEapMakeToken(&tmpMinor, ctx, &innerOutputToken,
+                                   sm->outputTokenType, output_token);
+        if (GSS_ERROR(tmpMajor)) {
+            major = tmpMajor;
+            *minor = tmpMinor;
             goto cleanup;
+        }
     }
     if (ret_flags != NULL)
         *ret_flags = ctx->gssFlags;
index f097029..ad4dc24 100644 (file)
@@ -8,8 +8,10 @@ gss_context_time
 gss_delete_sec_context
 gss_display_name
 gss_display_name_ext
+gss_display_status
 gss_duplicate_name
 gss_export_name
+gss_export_name_composite
 gss_export_sec_context
 gss_get_mic
 gss_get_name_attribute
@@ -19,17 +21,20 @@ gss_indicate_mechs
 gss_init_sec_context
 gss_inquire_context
 gss_inquire_cred
-gss_inquire_name
+gss_inquire_cred_by_oid
 gss_inquire_mechs_for_name
+gss_inquire_name
 gss_inquire_names_for_mech
+gss_inquire_sec_context_by_oid
 gss_map_name_to_any
 gss_process_context_token
 gss_pseudo_random
 gss_release_any_name_mapping
 gss_release_cred
-gss_internal_release_oid
 gss_release_name
+gss_internal_release_oid
 gss_set_name_attribute
+gss_set_sec_context_option
 gss_store_cred
 gss_unwrap
 gss_unwrap_iov
index 6ed4caf..d10f71c 100644 (file)
@@ -80,7 +80,6 @@ unwrapToken(OM_uint32 *minor,
     size_t dataLen, assocDataLen;
     uint64_t seqnum;
     int valid = 0;
-    krb5_cksumtype cksumtype;
     int conf_flag = 0;
     krb5_context krbContext;
 
@@ -201,7 +200,7 @@ unwrapToken(OM_uint32 *minor,
             store_uint16_be(0, ptr + 4);
             store_uint16_be(0, ptr + 6);
 
-            code = gssEapVerify(krbContext, cksumtype, rrc,
+            code = gssEapVerify(krbContext, 0, rrc,
                                 &ctx->rfc3961Key, keyUsage,
                                 iov, iov_count, &valid);
             if (code != 0 || valid == FALSE) {
@@ -220,7 +219,7 @@ unwrapToken(OM_uint32 *minor,
             goto defective;
         seqnum = load_uint64_be(ptr + 8);
 
-        code = gssEapVerify(krbContext, cksumtype, 0,
+        code = gssEapVerify(krbContext, 0, 0,
                             &ctx->rfc3961Key, keyUsage,
                             iov, iov_count, &valid);
         if (code != 0 || valid == FALSE) {
index 6352319..eff975c 100644 (file)
@@ -110,7 +110,7 @@ gssEapReleaseContext(OM_uint32 *minor,
     gssEapReleaseName(&tmpMinor, &ctx->initiatorName);
     gssEapReleaseName(&tmpMinor, &ctx->acceptorName);
     gss_release_oid(&tmpMinor, &ctx->mechanismUsed);
-    sequenceFree(ctx->seqState);
+    sequenceFree(&ctx->seqState);
 
     GSSEAP_MUTEX_DESTROY(&ctx->mutex);
 
@@ -171,7 +171,7 @@ gssEapVerifyToken(OM_uint32 *minor,
     if (GSS_ERROR(major))
         return major;
 
-    if (ctx->mechanismUsed != GSS_C_NO_OID) {
+    if (ctx->mechanismUsed == GSS_C_NO_OID) {
         if (!gssEapIsConcreteMechanismOid(oid))
             return GSS_S_BAD_MECH;
 
index 35e2395..dd52890 100644 (file)
@@ -108,7 +108,12 @@ gssEapDeriveRFC3961Key(OM_uint32 *minor,
     if (code != 0)
         goto cleanup;
 
-    data.length = keyLength;
+    if (keyLength < keybytes) {
+        code = KRB5_BAD_MSIZE;
+        goto cleanup;
+    }
+
+    data.length = keybytes;
     data.data = (char *)key;
 
     kd.contents = GSSEAP_MALLOC(keylength);
@@ -131,7 +136,11 @@ gssEapDeriveRFC3961Key(OM_uint32 *minor,
     if (code != 0)
         goto cleanup;
 
-    prf.length = prflength;
+    if (prflength < keybytes) {
+        code = KRB5_CRYPTO_INTERNAL;
+        goto cleanup;
+    }
+    prf.length = keybytes;
     prf.data = GSSEAP_MALLOC(prflength);
     if (data.data == NULL) {
         code = ENOMEM;
index e089690..c331945 100644 (file)
@@ -208,7 +208,7 @@ verifyTokenHeader(gss_OID mech,
     gss_OID_desc toid;
     ssize_t toksize = (ssize_t)toksize_in;
 
-    if (toksize -= 1 < 0)
+    if ((toksize -= 1) < 0)
         return ERANGE;
 
     if (*buf++ != 0x60)
@@ -221,18 +221,18 @@ verifyTokenHeader(gss_OID mech,
     if (seqsize != toksize)
         return ERANGE;
 
-    if (toksize -= 1 < 0)
+    if ((toksize -= 1) < 0)
         return ERANGE;
 
     if (*buf++ != 0x06)
         return EINVAL;
 
-    if (toksize -= 1 < 0)
+    if ((toksize -= 1) < 0)
         return ERANGE;
 
     toid.length = *buf++;
 
-    if (toksize -= toid.length < 0)
+    if ((toksize -= toid.length) < 0)
         return ERANGE;
 
     toid.elements = buf;
@@ -247,7 +247,7 @@ verifyTokenHeader(gss_OID mech,
     }
 
     if (tok_type != TOK_TYPE_NONE) {
-        if (toksize -= 2 < 0)
+        if ((toksize -= 2) < 0)
             return EINVAL;
 
         if ((*buf++ != ((tok_type >> 8) & 0xff)) ||
index ee19b01..2d72307 100644 (file)
@@ -39,15 +39,25 @@ gss_verify_mic(OM_uint32 *minor,
                gss_buffer_t message_token,
                gss_qop_t *qop_state)
 {
-    gss_iov_buffer_desc iov[2];
+    gss_iov_buffer_desc iov[3];
     int conf_state;
 
+    if (message_token->length < 16) {
+        *minor = KRB5_BAD_MSIZE;
+        return GSS_S_BAD_SIG;
+    }
+
     iov[0].type = GSS_IOV_BUFFER_TYPE_DATA;
     iov[0].buffer = *message_buffer;
 
     iov[1].type = GSS_IOV_BUFFER_TYPE_HEADER;
-    iov[1].buffer = *message_token;
+    iov[1].buffer.length = 16;
+    iov[1].buffer.value = message_token->value;
+
+    iov[2].type = GSS_IOV_BUFFER_TYPE_TRAILER;
+    iov[2].buffer.length = message_token->length - 16;
+    iov[2].buffer.value = (unsigned char *)message_token->value + 16;
 
     return gssEapUnwrapOrVerifyMIC(minor, ctx, &conf_state, qop_state,
-                                   iov, 2, TOK_TYPE_MIC);
+                                   iov, 3, TOK_TYPE_MIC);
 }
index f9681fa..6f53365 100644 (file)
@@ -295,10 +295,7 @@ cleanup:
 
     *minor = code;
 
-    if (code == 0)
-        return GSS_S_FAILURE;
-    else
-        return GSS_S_COMPLETE;
+    return (code == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE;
 }
 
 OM_uint32