check gssEapRadiusAddAttr(REALM_NAME) return code
[mech_eap.git] / mech_eap / init_sec_context.c
index 6cb4be0..4e8e550 100644 (file)
@@ -170,10 +170,20 @@ peerSetConfigBlob(void *ctx GSSEAP_UNUSED,
 }
 
 static const struct wpa_config_blob *
-peerGetConfigBlob(void *ctx GSSEAP_UNUSED,
-                  const char *name GSSEAP_UNUSED)
+peerGetConfigBlob(void *ctx,
+                  const char *name)
 {
-    return NULL;
+    gss_ctx_id_t gssCtx = (gss_ctx_id_t)ctx;
+    size_t index;
+
+    if (strcmp(name, "client-cert") == 0)
+        index = CONFIG_BLOB_CLIENT_CERT;
+    else if (strcmp(name, "private-key") == 0)
+        index = CONFIG_BLOB_PRIVATE_KEY;
+    else
+        return NULL;
+
+    return &gssCtx->initiatorCtx.configBlobs[index];
 }
 
 static void
@@ -202,8 +212,6 @@ extern int wpa_debug_level;
 #define CHBIND_SERVICE_SPECIFIC_FLAG    0x04
 #define CHBIND_REALM_NAME_FLAG          0x08
 
-extern void TestFunc();
-
 static OM_uint32
 peerInitEapChannelBinding(OM_uint32 *minor, gss_ctx_id_t ctx)
 {
@@ -266,6 +274,9 @@ peerInitEapChannelBinding(OM_uint32 *minor, gss_ctx_id_t ctx)
         major = gssEapRadiusAddAttr(minor, &buf,
                                     PW_GSS_ACCEPTOR_REALM_NAME,
                                     0, &nameBuf);
+        if (GSS_ERROR(major))
+            goto cleanup;
+
         chbindReqFlags |= CHBIND_REALM_NAME_FLAG;
     }
 
@@ -284,7 +295,7 @@ peerInitEapChannelBinding(OM_uint32 *minor, gss_ctx_id_t ctx)
     *minor = 0;
 
 cleanup:
-    krbFreeUnparsedName(krbContext, &nameBuf);
+    /*namebuf is freed when used and may be left with a unowned pointer*/
     wpabuf_free(buf);
 
     return major;
@@ -305,6 +316,8 @@ peerProcessChbindResponse(void *context, int code, int nsid,
     if (nsid != CHBIND_NSID_RADIUS)
         return;
 
+    if (data == NULL)
+        return;
     msg = radius_parser_start(data, len);
     if (msg == NULL)
         return;
@@ -342,6 +355,7 @@ peerConfigInit(OM_uint32 *minor, gss_ctx_id_t ctx)
     OM_uint32 major;
     krb5_context krbContext;
     struct eap_peer_config *eapPeerConfig = &ctx->initiatorCtx.eapPeerConfig;
+    struct wpa_config_blob *configBlobs = ctx->initiatorCtx.configBlobs;
     gss_buffer_desc identity = GSS_C_EMPTY_BUFFER;
     gss_buffer_desc realm = GSS_C_EMPTY_BUFFER;
     gss_cred_id_t cred = ctx->cred;
@@ -392,8 +406,10 @@ peerConfigInit(OM_uint32 *minor, gss_ctx_id_t ctx)
     eapPeerConfig->anonymous_identity_len = 1 + realm.length;
 
     /* password */
-    eapPeerConfig->password = (unsigned char *)cred->password.value;
-    eapPeerConfig->password_len = cred->password.length;
+    if ((cred->flags & CRED_FLAG_CERTIFICATE) == 0) {
+        eapPeerConfig->password = (unsigned char *)cred->password.value;
+        eapPeerConfig->password_len = cred->password.length;
+    }
 
     /* certs */
     eapPeerConfig->ca_cert = (unsigned char *)cred->caCertificate.value;
@@ -420,6 +436,26 @@ peerConfigInit(OM_uint32 *minor, gss_ctx_id_t ctx)
         eapPeerConfig->chbind_config = NULL;
         eapPeerConfig->chbind_config_len = 0;
     }
+    if (cred->flags & CRED_FLAG_CERTIFICATE) {
+        /*
+         * CRED_FLAG_CONFIG_BLOB is an internal flag which will be used in the
+         * future to directly pass certificate and private key data to the
+         * EAP implementation, rather than an indirected string pointer.
+         */
+        if (cred->flags & CRED_FLAG_CONFIG_BLOB) {
+            eapPeerConfig->client_cert = (unsigned char *)"blob://client-cert";
+            configBlobs[CONFIG_BLOB_CLIENT_CERT].data = cred->clientCertificate.value;
+            configBlobs[CONFIG_BLOB_CLIENT_CERT].len  = cred->clientCertificate.length;
+
+            eapPeerConfig->client_cert = (unsigned char *)"blob://private-key";
+            configBlobs[CONFIG_BLOB_PRIVATE_KEY].data = cred->clientCertificate.value;
+            configBlobs[CONFIG_BLOB_PRIVATE_KEY].len  = cred->privateKey.length;
+        } else {
+            eapPeerConfig->client_cert = (unsigned char *)cred->clientCertificate.value;
+            eapPeerConfig->private_key = (unsigned char *)cred->privateKey.value;
+        }
+        eapPeerConfig->private_key_passwd = (unsigned char *)cred->password.value;
+    }
 
     *minor = 0;
     return GSS_S_COMPLETE;
@@ -931,6 +967,11 @@ eapGssSmInitGssFlags(OM_uint32 *minor,
     unsigned char wireFlags[4];
     gss_buffer_desc flagsBuf;
 
+    /*
+     * As a temporary measure, force mutual authentication until channel binding is
+     * more widely deployed.
+     */
+    ctx->gssFlags |= GSS_C_MUTUAL_FLAG;
     store_uint32_be(ctx->gssFlags & GSSEAP_WIRE_FLAGS_MASK, wireFlags);
 
     flagsBuf.length = sizeof(wireFlags);