marshal server name in partial contexts
authorLuke Howard <lukeh@padl.com>
Mon, 4 Oct 2010 10:25:36 +0000 (12:25 +0200)
committerLuke Howard <lukeh@padl.com>
Mon, 4 Oct 2010 10:25:36 +0000 (12:25 +0200)
mech_eap/accept_sec_context.c
mech_eap/context_time.c
mech_eap/export_sec_context.c
mech_eap/gssapiP_eap.h
mech_eap/import_sec_context.c
mech_eap/inquire_context.c
mech_eap/util_context.c
mech_eap/util_radius.cpp
mech_eap/util_radius.h

index 8b98484..b977242 100644 (file)
@@ -130,12 +130,6 @@ eapGssSmAcceptIdentity(OM_uint32 *minor,
     if (inputToken != GSS_C_NO_BUFFER && inputToken->length != 0)
         return GSS_S_DEFECTIVE_TOKEN;
 
-    assert(ctx->acceptorCtx.radHandle == NULL);
-
-    major = gssEapRadiusAllocHandle(minor, cred, &ctx->acceptorCtx.radHandle);
-    if (GSS_ERROR(major))
-        return major;
-
     assert(ctx->acceptorName == GSS_C_NO_NAME);
 
     if (cred != GSS_C_NO_CREDENTIAL && cred->name != GSS_C_NO_NAME) {
@@ -170,6 +164,9 @@ setAcceptorIdentity(OM_uint32 *minor,
     gss_buffer_desc nameBuf;
     krb5_context krbContext = NULL;
     krb5_principal krbPrinc;
+    rc_handle *rh = ctx->acceptorCtx.radHandle;
+
+    assert(rh != NULL);
 
     /* Awaits further specification */
     if (ctx->acceptorName == GSS_C_NO_NAME)
@@ -186,7 +183,7 @@ setAcceptorIdentity(OM_uint32 *minor,
     /* Acceptor-Service-Name */
     krbDataToGssBuffer(krb5_princ_component(krbContext, krbPrinc, 0), &nameBuf);
 
-    major = addAvpFromBuffer(minor, ctx->acceptorCtx.radHandle, avps,
+    major = addAvpFromBuffer(minor, rh, avps,
                              VENDOR_ATTR_GSS_ACCEPTOR_SERVICE_NAME,
                              VENDOR_ID_UKERNA,
                              &nameBuf);
@@ -196,7 +193,7 @@ setAcceptorIdentity(OM_uint32 *minor,
     /* Acceptor-Host-Name */
     krbDataToGssBuffer(krb5_princ_component(krbContext, krbPrinc, 1), &nameBuf);
 
-    major = addAvpFromBuffer(minor, ctx->acceptorCtx.radHandle, avps,
+    major = addAvpFromBuffer(minor, rh, avps,
                              VENDOR_ATTR_GSS_ACCEPTOR_HOST_NAME,
                              VENDOR_ID_UKERNA,
                              &nameBuf);
@@ -219,7 +216,7 @@ setAcceptorIdentity(OM_uint32 *minor,
         nameBuf.value = ssi;
         nameBuf.length = strlen(ssi);
 
-        major = addAvpFromBuffer(minor, ctx->acceptorCtx.radHandle, avps,
+        major = addAvpFromBuffer(minor, rh, avps,
                                  VENDOR_ATTR_GSS_ACCEPTOR_SERVICE_SPECIFIC,
                                  VENDOR_ID_UKERNA,
                                  &nameBuf);
@@ -234,7 +231,7 @@ setAcceptorIdentity(OM_uint32 *minor,
     krbDataToGssBuffer(krb5_princ_realm(krbContext, krbPrinc), &nameBuf);
     if (nameBuf.length != 0) {
         /* Acceptor-Realm-Name */
-        major = addAvpFromBuffer(minor, ctx->acceptorCtx.radHandle, avps,
+        major = addAvpFromBuffer(minor, rh, avps,
                                  VENDOR_ATTR_GSS_ACCEPTOR_REALM_NAME,
                                  VENDOR_ID_UKERNA,
                                  &nameBuf);
@@ -254,15 +251,24 @@ eapGssSmAcceptAuthenticate(OM_uint32 *minor,
                            gss_buffer_t outputToken)
 {
     OM_uint32 major, tmpMinor;
+    rc_handle *rh;
     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 (ctx->acceptorCtx.radHandle == NULL) {
+        /* May be NULL from an imported partial context */
+        major = gssEapRadiusAllocHandle(minor, cred, ctx);
+        if (GSS_ERROR(major))
+            goto cleanup;
+    }
+
+    rh = ctx->acceptorCtx.radHandle;
+
     pdu = (struct eap_hdr *)inputToken->value;
     pos = (unsigned char *)(pdu + 1);
 
@@ -286,7 +292,7 @@ eapGssSmAcceptAuthenticate(OM_uint32 *minor,
     if (GSS_ERROR(major))
         goto cleanup;
 
-    if (ctx->acceptorCtx.lastStatus == CHALLENGE_RC) {
+    if (ctx->acceptorCtx.state.length != 0) {
         major = addAvpFromBuffer(minor, rh, &send, PW_STATE, 0,
                                  &ctx->acceptorCtx.state);
         if (GSS_ERROR(major))
@@ -315,8 +321,6 @@ eapGssSmAcceptAuthenticate(OM_uint32 *minor,
     if (GSS_ERROR(major))
         goto cleanup;
 
-    ctx->acceptorCtx.lastStatus = code;
-
     major = getBufferFromAvps(minor, received, PW_EAP_MESSAGE, 0,
                               outputToken, TRUE);
     if ((major == GSS_S_UNAVAILABLE && code != OK_RC) ||
index dd29312..b72836b 100644 (file)
@@ -37,7 +37,7 @@ gss_context_time(OM_uint32 *minor,
                  gss_ctx_id_t ctx,
                  OM_uint32 *time_rec)
 {
-    OM_uint32 major = GSS_S_NO_CONTEXT;
+    OM_uint32 major;
 
     if (ctx == GSS_C_NO_CONTEXT) {
         *minor = EINVAL;
@@ -48,10 +48,16 @@ gss_context_time(OM_uint32 *minor,
 
     GSSEAP_MUTEX_LOCK(&ctx->mutex);
 
-    if (CTX_IS_ESTABLISHED(ctx)) {
-        major = gssEapContextTime(minor, ctx, time_rec);
+    if (!CTX_IS_ESTABLISHED(ctx)) {
+        major = GSS_S_NO_CONTEXT;
+        goto cleanup;
     }
 
+    major = gssEapContextTime(minor, ctx, time_rec);
+    if (GSS_ERROR(major))
+        goto cleanup;
+
+cleanup:
     GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
 
     return major;
index d2b7123..001dd5b 100644 (file)
@@ -37,8 +37,49 @@ gssEapExportPartialContext(OM_uint32 *minor,
                            gss_ctx_id_t ctx,
                            gss_buffer_t token)
 {
-    /* XXX we also need to serialise the current server name */
-    return duplicateBuffer(minor, &ctx->acceptorCtx.state, token);
+    OM_uint32 major, tmpMinor;
+    size_t length, serverLen;
+    unsigned char *p;
+
+    if (ctx->acceptorCtx.radServer != NULL)
+        serverLen = strlen(ctx->acceptorCtx.radServer);
+    else
+        serverLen = 0;
+
+    length = 4 + serverLen + 4 + ctx->acceptorCtx.state.length;
+
+    token->value = GSSEAP_MALLOC(length);
+    if (token->value == NULL) {
+        *minor = ENOMEM;
+        major = GSS_S_FAILURE;
+        goto cleanup;
+    }
+    token->length = length;
+
+    p = (unsigned char *)token->value;
+
+    store_uint32_be(serverLen, p);
+    p += 4;
+    if (serverLen != 0) {
+        memcpy(p, ctx->acceptorCtx.radServer, serverLen);
+        p += serverLen;
+    }
+
+    store_uint32_be(ctx->acceptorCtx.state.length, p);
+    p += 4;
+    if (ctx->acceptorCtx.state.length != 0) {
+        memcpy(p, ctx->acceptorCtx.state.value,
+               ctx->acceptorCtx.state.length);
+        p += ctx->acceptorCtx.state.length;
+    }
+
+    assert(p == (unsigned char *)token->value + token->length);
+
+cleanup:
+    if (GSS_ERROR(major))
+        gss_release_buffer(&tmpMinor, token);
+
+    return major;
 }
 
 static OM_uint32
index c1a2d4f..757649b 100644 (file)
@@ -142,9 +142,9 @@ struct gss_eap_initiator_ctx {
 
 struct gss_eap_acceptor_ctx {
     rc_handle *radHandle;
-    int lastStatus;
-    VALUE_PAIR *avps;
+    char *radServer;
     gss_buffer_desc state;
+    VALUE_PAIR *avps;
 };
 
 struct gss_ctx_id_struct {
index 8297262..202be3d 100644 (file)
 
 #include "gssapiP_eap.h"
 
+#define UPDATE_REMAIN(n)    do {            \
+        p += (n);                           \
+        remain -= (n);                      \
+    } while (0)
+
+#define CHECK_REMAIN(n)     do {            \
+        if (remain < (n)) {                 \
+            *minor = ERANGE;                \
+            return GSS_S_DEFECTIVE_TOKEN;   \
+        }                                   \
+    } while (0)
+
 static OM_uint32
 gssEapImportPartialContext(OM_uint32 *minor,
                            unsigned char **pBuf,
@@ -42,28 +54,46 @@ gssEapImportPartialContext(OM_uint32 *minor,
     unsigned char *p = *pBuf;
     size_t remain = *pRemain;
     gss_buffer_desc buf;
+    size_t serverLen;
 
-    /* XXX we also need to deserialise the current server name */
+    /* Selected RADIUS server */
+    CHECK_REMAIN(4);
+    serverLen = load_uint32_be(p);
+    UPDATE_REMAIN(4);
 
-    if (remain < 4) {
-        *minor = ERANGE;
-        return GSS_S_DEFECTIVE_TOKEN;
+    if (serverLen != 0) {
+        CHECK_REMAIN(serverLen);
+
+        ctx->acceptorCtx.radServer = GSSEAP_MALLOC(serverLen + 1);
+        if (ctx->acceptorCtx.radServer == NULL) {
+            *minor = ENOMEM;
+            return GSS_S_FAILURE;
+        }
+        memcpy(ctx->acceptorCtx.radServer, p, serverLen);
+        ctx->acceptorCtx.radServer[serverLen] = '\0';
+
+        UPDATE_REMAIN(serverLen);
     }
+
+    /* RADIUS state blob */
+    CHECK_REMAIN(4);
     buf.length = load_uint32_be(p);
+    UPDATE_REMAIN(4);
 
-    if (remain < buf.length) {
-        *minor = ERANGE;
-        return GSS_S_DEFECTIVE_TOKEN;
+    if (buf.length != 0) {
+        CHECK_REMAIN(buf.length);
 
-    }
-    buf.value = &p[4];
+        buf.value = p;
 
-    major = duplicateBuffer(minor, &buf, &ctx->acceptorCtx.state);
-    if (GSS_ERROR(major))
-        return major;
+        major = duplicateBuffer(minor, &buf, &ctx->acceptorCtx.state);
+        if (GSS_ERROR(major))
+            return major;
+
+        UPDATE_REMAIN(buf.length);
+    }
 
-    *pBuf += 4 + buf.length;
-    *pRemain -= 4 + buf.length;
+    *pBuf = p;
+    *pRemain = remain;
 
     return GSS_S_COMPLETE;
 }
index 670f304..ab0e4d3 100644 (file)
@@ -46,7 +46,7 @@ gss_inquire_context(OM_uint32 *minor,
     OM_uint32 major, tmpMinor;
 
     if (ctx == GSS_C_NO_CONTEXT) {
-        *mionr = EINVAL;
+        *minor = EINVAL;
         return GSS_S_NO_CONTEXT;
     }
 
index 9c6916d..6b5f9df 100644 (file)
@@ -93,6 +93,8 @@ releaseAcceptorContext(struct gss_eap_acceptor_ctx *ctx)
         rc_config_free(ctx->radHandle);
 
     gss_release_buffer(&tmpMinor, &ctx->state);
+    if (ctx->radServer != NULL)
+        GSSEAP_FREE(ctx->radServer);
 }
 
 OM_uint32
index c13ecf0..0fe19ba 100644 (file)
@@ -37,11 +37,12 @@ static gss_buffer_desc radiusUrnPrefix = {
     (void *)"urn:x-radius:"
 };
 
-static bool
+static int
 radiusAllocHandle(const char *configFile,
                   rc_handle **pHandle)
 {
     rc_handle *rh;
+    int ret;
 
     *pHandle = NULL;
 
@@ -51,16 +52,17 @@ radiusAllocHandle(const char *configFile,
     rh = rc_read_config((char *)configFile);
     if (rh == NULL) {
         rc_config_free(rh);
-        return false;
+        return -1;
     }
 
-    if (rc_read_dictionary(rh, rc_conf_str(rh, (char *)"dictionary")) != 0) {
+    ret = rc_read_dictionary(rh, rc_conf_str(rh, (char *)"dictionary"));
+    if (ret != 0) {
         rc_config_free(rh);
-        return false;
+        return ret;
     }
 
     *pHandle = rh;
-    return true;
+    return 0;
 }
 
 VALUE_PAIR *
@@ -106,7 +108,7 @@ gss_eap_radius_attr_provider::allocRadHandle(const std::string &configFile)
 {
     m_configFile.assign(configFile);
 
-    return radiusAllocHandle(m_configFile.c_str(), &m_rh);
+    return (radiusAllocHandle(m_configFile.c_str(), &m_rh) == 0);
 }
 
 bool
@@ -513,18 +515,22 @@ gssEapRadiusAttrProviderFinalize(OM_uint32 *minor)
 OM_uint32
 gssEapRadiusAllocHandle(OM_uint32 *minor,
                         const gss_cred_id_t cred,
-                        rc_handle **pHandle)
+                        gss_ctx_id_t ctx)
 {
     const char *configFile = NULL;
 
-    *pHandle = NULL;
+    assert(ctx->acceptorCtx.radHandle == NULL);
 
     if (cred != GSS_C_NO_CREDENTIAL && cred->radiusConfigFile != NULL)
         configFile = cred->radiusConfigFile;
 
-    if (!radiusAllocHandle(configFile, pHandle))
+    if (radiusAllocHandle(configFile, &ctx->acceptorCtx.radHandle) != 0)
         return GSS_S_FAILURE;
 
+    /* XXX TODO allocate connection handle */
+
+    /* XXX TODO select based on acceptorCtx.radServer */
+
     return GSS_S_COMPLETE;
 }
 
index 518c846..a7bb03c 100644 (file)
@@ -134,7 +134,7 @@ OM_uint32 gssEapRadiusAttrProviderFinalize(OM_uint32 *minor);
 OM_uint32
 gssEapRadiusAllocHandle(OM_uint32 *minor,
                         const gss_cred_id_t cred,
-                        rc_handle **pHandle);
+                        gss_ctx_id_t ctx);
 
 #define RC_CONFIG_FILE      SYSCONFDIR "/radiusclient/radiusclient.conf"