cleanup radius code a bit
authorLuke Howard <lukeh@padl.com>
Mon, 20 Sep 2010 22:04:10 +0000 (00:04 +0200)
committerLuke Howard <lukeh@padl.com>
Mon, 20 Sep 2010 22:04:10 +0000 (00:04 +0200)
mech_eap/accept_sec_context.c
mech_eap/export_sec_context.c
mech_eap/gssapiP_eap.h
mech_eap/util_context.c
mech_eap/util_radius.h

index af35d56..01a07bc 100644 (file)
@@ -54,14 +54,16 @@ acceptReady(OM_uint32 *minor, gss_ctx_id_t ctx)
     if (vp != NULL) {
         nameBuf.length = vp->lvalue;
         nameBuf.value = vp->strvalue;
-    } else {
+    } else if (ctx->initiatorName == GSS_C_NO_NAME) {
         ctx->gssFlags |= GSS_C_ANON_FLAG;
     }
 
-    major = gssEapImportName(minor, &nameBuf, GSS_C_NT_USER_NAME,
-                             &ctx->initiatorName);
-    if (GSS_ERROR(major))
-        return major;
+    if (nameBuf.length != 0 || ctx->initiatorName == GSS_C_NO_NAME) {
+        major = gssEapImportName(minor, &nameBuf, GSS_C_NT_USER_NAME,
+                                 &ctx->initiatorName);
+        if (GSS_ERROR(major))
+            return major;
+    }
 
     vp = rc_avpair_get(ctx->acceptorCtx.avps, PW_MSCHAP2_SUCCESS, 0);
     if (ctx->encryptionType != ENCTYPE_NULL && vp != NULL) {
@@ -108,10 +110,10 @@ eapGssSmAcceptIdentity(OM_uint32 *minor,
     OM_uint32 major;
     rc_handle *rh;
     union {
-        struct eap_hdr eap;
+        struct eap_hdr pdu;
         unsigned char data[5];
-    } pdu;
-    gss_buffer_desc pduBuffer;
+    } pkt;
+    gss_buffer_desc pktBuffer;
     char *config = RC_CONFIG_FILE;
 
     if (inputToken != GSS_C_NO_BUFFER && inputToken->length != 0)
@@ -141,15 +143,15 @@ eapGssSmAcceptIdentity(OM_uint32 *minor,
             return major;
     }
 
-    pdu.eap.code = EAP_CODE_REQUEST;
-    pdu.eap.identifier = 0;
-    pdu.eap.length = htons(sizeof(pdu.data));
-    pdu.data[4] = EAP_TYPE_IDENTITY;
+    pkt.pdu.code = EAP_CODE_REQUEST;
+    pkt.pdu.identifier = 0;
+    pkt.pdu.length = htons(sizeof(pkt.data));
+    pkt.data[4] = EAP_TYPE_IDENTITY;
 
-    pduBuffer.length = sizeof(pdu.data);
-    pduBuffer.value = pdu.data;
+    pktBuffer.length = sizeof(pkt.data);
+    pktBuffer.value = pkt.data;
 
-    major = duplicateBuffer(minor, &pduBuffer, outputToken);
+    major = duplicateBuffer(minor, &pktBuffer, outputToken);
     if (GSS_ERROR(major))
         return major;
 
@@ -159,6 +161,33 @@ eapGssSmAcceptIdentity(OM_uint32 *minor,
 }
 
 static OM_uint32
+importInitiatorIdentity(OM_uint32 *minor,
+                        gss_ctx_id_t ctx,
+                        gss_buffer_t inputToken,
+                        gss_buffer_t nameBuf)
+{
+    OM_uint32 major, tmpMinor;
+    struct eap_hdr *pdu = (struct eap_hdr *)inputToken->value;
+    unsigned char *pos = (unsigned char *)(pdu + 1);
+    gss_name_t name;
+
+    assert(pdu->code == EAP_CODE_RESPONSE);
+    assert(pos[0] == EAP_TYPE_IDENTITY);
+
+    nameBuf->value = pos + 1;
+    nameBuf->length = inputToken->length - sizeof(*pdu) - 1;
+
+    major = gssEapImportName(minor, nameBuf, GSS_C_NT_USER_NAME, &name);
+    if (GSS_ERROR(major))
+        return major;
+
+    gssEapReleaseName(&tmpMinor, &ctx->initiatorName);
+    ctx->initiatorName = name;
+
+    return GSS_S_COMPLETE;
+}
+
+static OM_uint32
 eapGssSmAcceptAuthenticate(OM_uint32 *minor,
                            gss_ctx_id_t ctx,
                            gss_cred_id_t cred,
@@ -166,25 +195,44 @@ eapGssSmAcceptAuthenticate(OM_uint32 *minor,
                            gss_channel_bindings_t chanBindings,
                            gss_buffer_t outputToken)
 {
-    OM_uint32 major;
-    OM_uint32 service = PW_AUTHENTICATE_ONLY;
+    OM_uint32 major, tmpMinor;
     int code;
     VALUE_PAIR *send = NULL;
     VALUE_PAIR *received = NULL;
     rc_handle *rh = ctx->acceptorCtx.radHandle;
     char msgBuffer[4096];
+    struct eap_hdr *pdu;
+    unsigned char *pos;
+    gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER;
 
-    if (rc_avpair_add(rh, &send, PW_EAP_MESSAGE,
-                      inputToken->value, inputToken->length, 0) == NULL) {
-        *minor = ENOMEM;
-        major = GSS_S_FAILURE;
-        goto cleanup;
+    pdu = (struct eap_hdr *)inputToken->value;
+    pos = (unsigned char *)(pdu + 1);
+
+    if (inputToken->length > sizeof(*pdu) &&
+        pdu->code == EAP_CODE_RESPONSE &&
+        pos[0] == EAP_TYPE_IDENTITY) {
+        major = importInitiatorIdentity(minor, ctx, inputToken, &nameBuf);
+        if (GSS_ERROR(major))
+            goto cleanup;
+
+        major = addRadiusAttributeFromBuffer(minor, rh, &send,
+                                             PW_USER_NAME, &nameBuf);
+        if (GSS_ERROR(major))
+            goto cleanup;
     }
 
-    if (rc_avpair_add(rh, &send, PW_SERVICE_TYPE, &service, -1, 0) == NULL) {
-        *minor = ENOMEM;
-        major = GSS_S_FAILURE;
+    major = addRadiusAttributeFromBuffer(minor, rh, &send, PW_EAP_MESSAGE,
+                                         inputToken);
+    if (GSS_ERROR(major))
         goto cleanup;
+
+    if (ctx->acceptorCtx.lastStatus == PW_ACCESS_CHALLENGE) {
+        major = addRadiusAttributeFromBuffer(minor, rh, &send, PW_STATE,
+                                             &ctx->acceptorCtx.state);
+        if (GSS_ERROR(major))
+            goto cleanup;
+
+        gss_release_buffer(&tmpMinor, &ctx->acceptorCtx.state);
     }
 
     code = rc_auth(rh, 0, send, &received, msgBuffer);
@@ -194,20 +242,21 @@ eapGssSmAcceptAuthenticate(OM_uint32 *minor,
         goto cleanup;
     }
 
-    if (code == OK_RC || code == PW_ACCESS_CHALLENGE) {
-        VALUE_PAIR *eapResponse;
-        gss_buffer_desc eapBuf = GSS_C_EMPTY_BUFFER;
-
-        eapResponse = rc_avpair_get(received, PW_EAP_MESSAGE, 0);
-        if (eapResponse != NULL) {
-            eapBuf.length = eapResponse->lvalue;
-            eapBuf.value = eapResponse->strvalue;
-        }
+    ctx->acceptorCtx.lastStatus = code;
 
-        major = duplicateBuffer(minor, &eapBuf, outputToken);
+    if (code == OK_RC || code == PW_ACCESS_CHALLENGE) {
+        major = getBufferFromRadiusAttributes(minor, received, PW_EAP_MESSAGE,
+                                              outputToken);
         if (GSS_ERROR(major))
             goto cleanup;
 
+        if (code == PW_ACCESS_CHALLENGE) {
+            major = getBufferFromRadiusAttributes(minor, received, PW_STATE,
+                                                  &ctx->acceptorCtx.state);
+            if (GSS_ERROR(major))
+                goto cleanup;
+        }
+
         major = GSS_S_CONTINUE_NEEDED;
     } else {
         major = GSS_S_FAILURE;
index 50d4f5c..2387dd6 100644 (file)
@@ -37,13 +37,7 @@ gssEapExportPartialContext(OM_uint32 *minor,
                            gss_ctx_id_t ctx,
                            gss_buffer_t token)
 {
-    token->length = 0;
-    token->value = NULL;
-
-    /*
-     * The format of this token awaits definition by libradius.
-     */
-    return GSS_S_COMPLETE;
+    return duplicateBuffer(minor, &ctx->acceptorCtx.state, token);
 }
 
 static OM_uint32
index 0b2e64e..45be196 100644 (file)
@@ -44,7 +44,6 @@
 #include <gssapi/gssapi.h>
 #include <gssapi/gssapi_ext.h>
 #include "gssapi_eap.h"
-#include "util.h"
 
 /* Kerberos includes */
 #include <krb5.h>
@@ -69,6 +68,8 @@ typedef struct value_pair VALUE_PAIR;
 #include <freeradius/radius.h>
 #endif
 
+#include "util.h"
+
 /* These name flags are informative and not actually used by anything yet */
 #define NAME_FLAG_NAI                       0x00000001
 #define NAME_FLAG_SERVICE                   0x00000002
@@ -135,7 +136,9 @@ struct gss_eap_initiator_ctx {
 
 struct gss_eap_acceptor_ctx {
     rc_handle *radHandle;
+    int lastStatus;
     VALUE_PAIR *avps;
+    gss_buffer_desc state;
 };
 
 struct gss_ctx_id_struct {
index 5d2a55d..6d3b937 100644 (file)
@@ -82,10 +82,14 @@ releaseInitiatorContext(struct gss_eap_initiator_ctx *ctx)
 static void
 releaseAcceptorContext(struct gss_eap_acceptor_ctx *ctx)
 {
+    OM_uint32 tmpMinor;
+
     if (ctx->avps != NULL)
         rc_avpair_free(ctx->avps);
     if (ctx->radHandle != NULL)
         rc_config_free(ctx->radHandle);
+
+    gss_release_buffer(&tmpMinor, &ctx->state);
 }
 
 OM_uint32
index 75984c6..1da66f2 100644 (file)
@@ -90,6 +90,41 @@ private:
 extern "C" {
 #endif
 
+#ifndef __cplusplus
+static inline OM_uint32
+addRadiusAttributeFromBuffer(OM_uint32 *minor,
+                             rc_handle *rh,
+                             VALUE_PAIR **vp,
+                             int type,
+                             gss_buffer_t buffer)
+{
+    if (rc_avpair_add(rh, vp, type, buffer->value, buffer->length, 0) == NULL) {
+        *minor = ENOMEM;
+        return GSS_S_FAILURE;
+    }
+
+    return GSS_S_COMPLETE;
+}
+
+static inline OM_uint32
+getBufferFromRadiusAttributes(OM_uint32 *minor,
+                              VALUE_PAIR *vps,
+                              int type,
+                              gss_buffer_t buffer)
+{
+    VALUE_PAIR *vp;
+    gss_buffer_desc tmp = GSS_C_EMPTY_BUFFER;
+
+    vp = rc_avpair_get(vps, type, 0);
+    if (vp != NULL) {
+        tmp.length = vp->lvalue;
+        tmp.value = vp->strvalue;
+    }
+
+    return duplicateBuffer(minor, &tmp, buffer);
+}
+#endif
+
 OM_uint32 gssEapRadiusAttrProviderInit(OM_uint32 *minor);
 OM_uint32 gssEapRadiusAttrProviderFinalize(OM_uint32 *minor);