cleanup key derivation on acceptor
authorLuke Howard <lukeh@padl.com>
Tue, 21 Sep 2010 10:38:54 +0000 (12:38 +0200)
committerLuke Howard <lukeh@padl.com>
Tue, 21 Sep 2010 10:38:54 +0000 (12:38 +0200)
accept_sec_context.c
init_sec_context.c
util_krb.c
util_radius.h

index ad6a698..42c29c2 100644 (file)
@@ -65,7 +65,9 @@ acceptReady(OM_uint32 *minor, gss_ctx_id_t ctx, gss_cred_id_t cred)
 
     ctx->initiatorName->attrCtx = gssEapCreateAttrContext(cred, ctx);
 
-    vp = rc_avpair_get(ctx->acceptorCtx.avps, 16, 311);
+    vp = rc_avpair_get(ctx->acceptorCtx.avps,
+                       RADIUS_VENDOR_ATTR_MS_MPPE_SEND_KEY,
+                       RADIUS_VENDOR_ID_MICROSOFT);
     if (ctx->encryptionType != ENCTYPE_NULL && vp != NULL) {
         major = gssEapDeriveRfc3961Key(minor,
                                        (unsigned char *)vp->strvalue,
index 8fdd55d..050f335 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
@@ -260,7 +272,6 @@ initReady(OM_uint32 *minor, gss_ctx_id_t ctx)
          * material it seems confusing to the caller to advertise this.
          */
         ctx->gssFlags &= ~(GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG);
-        ctx->encryptionType = ENCTYPE_NULL;
     }
 
     major = sequenceInit(minor,
index 3607ec5..48c79a4 100644 (file)
@@ -95,6 +95,8 @@ gssEapDeriveRfc3961Key(OM_uint32 *minor,
     unsigned char constant[4 + sizeof("rfc4121-gss-eap") - 1], *p;
     ssize_t i, remain;
 
+    assert(encryptionType != ENCTYPE_NULL);
+
     memset(pKey, 0, sizeof(*pKey));
 
     GSSEAP_KRB_INIT(&krbContext);
@@ -105,6 +107,9 @@ gssEapDeriveRfc3961Key(OM_uint32 *minor,
     t.data = NULL;
     t.length = 0;
 
+    prfOut.data = NULL;
+    prfOut.length = 0;
+
     code = krb5_c_keylengths(krbContext, encryptionType,
                              &randomLength, &keyLength);
     if (code != 0)
index b8a85d8..acc2283 100644 (file)
@@ -129,6 +129,13 @@ gssEapRadiusAllocHandle(OM_uint32 *minor,
 
 #define RC_CONFIG_FILE      SYSCONFDIR "/radiusclient/radiusclient.conf"
 
+/* RFC 2548 - Microsoft Vendor-specific RADIUS Attributes */
+#define RADIUS_VENDOR_ID_MICROSOFT 311
+
+enum { RADIUS_VENDOR_ATTR_MS_MPPE_SEND_KEY = 16,
+       RADIUS_VENDOR_ATTR_MS_MPPE_RECV_KEY = 17
+};
+
 #ifdef __cplusplus
 }
 #endif