add gsseap error table
[mech_eap.git] / util_exts.c
index 0cdeed0..ccc86ec 100644 (file)
 #include "gssapiP_eap.h"
 
 static OM_uint32
+encodeExtensions(OM_uint32 *minor,
+                 gss_buffer_set_t extensions,
+                 OM_uint32 *types,
+                 gss_buffer_t buffer);
+
+static OM_uint32
+decodeExtensions(OM_uint32 *minor,
+                 const gss_buffer_t buffer,
+                 gss_buffer_set_t *pExtensions,
+                 OM_uint32 **pTypes);
+
+/*
+ * Initiator extensions
+ */
+static OM_uint32
 makeGssChannelBindings(OM_uint32 *minor,
                        gss_cred_id_t cred,
                        gss_ctx_id_t ctx,
@@ -98,6 +113,9 @@ eapGssInitExtensions[] = {
     },
 };
 
+/*
+ * Acceptor extensions
+ */
 static OM_uint32
 makeReauthCreds(OM_uint32 *minor,
                 gss_cred_id_t cred,
@@ -125,11 +143,13 @@ verifyReauthCreds(OM_uint32 *minor,
                   gss_channel_bindings_t chanBindings,
                   gss_buffer_t inputToken)
 {
+    OM_uint32 major = GSS_S_UNAVAILABLE;
+
 #ifdef GSSEAP_ENABLE_REAUTH
-    return gssEapStoreReauthCreds(minor, ctx, cred, inputToken);
-#else
-    return GSS_S_UNAVAILABLE;
+    major = gssEapStoreReauthCreds(minor, ctx, cred, inputToken);
 #endif
+
+    return major;
 }
 
 static struct gss_eap_extension_provider
@@ -143,6 +163,178 @@ eapGssAcceptExtensions[] = {
     },
 };
 
+OM_uint32
+makeExtensions(OM_uint32 *minor,
+               gss_cred_id_t cred,
+               gss_ctx_id_t ctx,
+               const struct gss_eap_extension_provider *exts,
+               size_t nexts,
+               gss_channel_bindings_t chanBindings,
+               gss_buffer_t buffer)
+{
+    OM_uint32 major, tmpMinor;
+    size_t i, j;
+    gss_buffer_set_t extensions = GSS_C_NO_BUFFER_SET;
+    OM_uint32 *types;
+
+    assert(buffer != GSS_C_NO_BUFFER);
+
+    buffer->length = 0;
+    buffer->value = NULL;
+
+    types = GSSEAP_CALLOC(nexts, sizeof(OM_uint32));
+    if (types == NULL) {
+        *minor = ENOMEM;
+        major = GSS_S_FAILURE;
+        goto cleanup;
+    }
+
+    for (i = 0, j = 0; i < nexts; i++) {
+        const struct gss_eap_extension_provider *ext = &exts[i];
+        gss_buffer_desc extension = GSS_C_EMPTY_BUFFER;
+
+        types[j] = ext->type;
+        if (ext->critical)
+            types[j] |= EXT_FLAG_CRITICAL;
+
+        major = ext->make(minor, cred, ctx, chanBindings, &extension);
+        if (GSS_ERROR(major)) {
+            if (ext->critical)
+                goto cleanup;
+            else
+                continue;
+        }
+
+        major = gss_add_buffer_set_member(minor, &extension, &extensions);
+        if (GSS_ERROR(major))
+            goto cleanup;
+
+        j++;
+    }
+
+    assert(j == (extensions == GSS_C_NO_BUFFER_SET ? 0 : extensions->count));
+
+    major = encodeExtensions(minor, extensions, types, buffer);
+    if (GSS_ERROR(major))
+        goto cleanup;
+
+cleanup:
+    gss_release_buffer_set(&tmpMinor, &extensions);
+    if (types != NULL)
+        GSSEAP_FREE(types);
+
+    return major;
+}
+
+OM_uint32
+gssEapMakeExtensions(OM_uint32 *minor,
+                     gss_cred_id_t cred,
+                     gss_ctx_id_t ctx,
+                     gss_channel_bindings_t chanBindings,
+                     gss_buffer_t buffer)
+{
+    size_t nexts;
+    const struct gss_eap_extension_provider *exts;
+
+    if (CTX_IS_INITIATOR(ctx)) {
+        exts = eapGssInitExtensions;
+        nexts = sizeof(eapGssInitExtensions) / sizeof(eapGssInitExtensions[0]);
+    } else {
+        exts = eapGssAcceptExtensions;
+        nexts = sizeof(eapGssAcceptExtensions) / sizeof(eapGssAcceptExtensions[0]);
+    }
+
+    return makeExtensions(minor, cred, ctx, exts, nexts, chanBindings, buffer);
+}
+
+static OM_uint32
+verifyExtensions(OM_uint32 *minor,
+                 gss_cred_id_t cred,
+                 gss_ctx_id_t ctx,
+                 const struct gss_eap_extension_provider *exts,
+                 size_t nexts,
+                 gss_channel_bindings_t chanBindings,
+                 const gss_buffer_t buffer)
+{
+    OM_uint32 major, tmpMinor;
+    gss_buffer_set_t extensions = GSS_C_NO_BUFFER_SET;
+    OM_uint32 *types = NULL;
+    size_t i;
+
+    major = decodeExtensions(minor, buffer, &extensions, &types);
+    if (GSS_ERROR(major))
+        goto cleanup;
+
+    for (i = 0; i < nexts; i++) {
+        const struct gss_eap_extension_provider *ext = &exts[i];
+        gss_buffer_t extension = GSS_C_NO_BUFFER;
+        size_t j;
+
+        for (j = 0; j < extensions->count; j++) {
+            if ((types[j] & EXT_TYPE_MASK) == ext->type) {
+                extension = &extensions->elements[j];
+                break;
+            }
+        }
+
+        if (extension != GSS_C_NO_BUFFER) {
+            /* Process extension and mark as verified */
+            major = ext->verify(minor, cred, ctx, chanBindings,
+                                &extensions->elements[j]);
+            if (GSS_ERROR(major))
+                goto cleanup;
+
+            types[j] |= EXT_FLAG_VERIFIED;
+        } else if (ext->required) {
+            /* Required extension missing */
+            *minor = GSSEAP_MISSING_REQUIRED_EXT;
+            major = GSS_S_UNAVAILABLE;
+            goto cleanup;
+        }
+    }
+
+    /* Check we processed all critical extensions */
+    for (i = 0; i < extensions->count; i++) {
+        if ((types[i] & EXT_FLAG_CRITICAL) &&
+            (types[i] & EXT_FLAG_VERIFIED) == 0) {
+            *minor = GSSEAP_CRIT_EXT_UNAVAILABLE;
+            major = GSS_S_UNAVAILABLE;
+            goto cleanup;
+        }
+    }
+
+    *minor = 0;
+    major = GSS_S_COMPLETE;
+
+cleanup:
+    gss_release_buffer_set(&tmpMinor, &extensions);
+    if (types != NULL)
+        GSSEAP_FREE(types);
+
+    return major;
+}
+
+OM_uint32
+gssEapVerifyExtensions(OM_uint32 *minor,
+                       gss_cred_id_t cred,
+                       gss_ctx_id_t ctx,
+                       gss_channel_bindings_t chanBindings,
+                       const gss_buffer_t buffer)
+{
+    size_t nexts;
+    const struct gss_eap_extension_provider *exts;
+
+    if (CTX_IS_INITIATOR(ctx)) {
+        exts = eapGssAcceptExtensions;
+        nexts = sizeof(eapGssAcceptExtensions) / sizeof(eapGssAcceptExtensions[0]);
+    } else {
+        exts = eapGssInitExtensions;
+        nexts = sizeof(eapGssInitExtensions) / sizeof(eapGssInitExtensions[0]);
+    }
+
+    return verifyExtensions(minor, cred, ctx, exts, nexts, chanBindings, buffer);
+}
+
 static OM_uint32
 encodeExtensions(OM_uint32 *minor,
                  gss_buffer_set_t extensions,
@@ -280,153 +472,3 @@ cleanup:
 
     return major;
 }
-
-OM_uint32
-gssEapMakeExtensions(OM_uint32 *minor,
-                     gss_cred_id_t cred,
-                     gss_ctx_id_t ctx,
-                     gss_channel_bindings_t chanBindings,
-                     gss_buffer_t buffer)
-{
-    OM_uint32 major, tmpMinor;
-    size_t i, j, nexts;
-    gss_buffer_set_t extensions = GSS_C_NO_BUFFER_SET;
-    OM_uint32 *types;
-    const struct gss_eap_extension_provider *exts;
-
-    if (CTX_IS_INITIATOR(ctx)) {
-        exts = eapGssInitExtensions;
-        nexts = sizeof(eapGssInitExtensions) / sizeof(eapGssInitExtensions[0]);
-    } else {
-        exts = eapGssAcceptExtensions;
-        nexts = sizeof(eapGssAcceptExtensions) / sizeof(eapGssAcceptExtensions[0]);
-    }
-
-    assert(buffer != GSS_C_NO_BUFFER);
-
-    buffer->length = 0;
-    buffer->value = NULL;
-
-    types = GSSEAP_CALLOC(nexts, sizeof(OM_uint32));
-    if (types == NULL) {
-        *minor = ENOMEM;
-        major = GSS_S_FAILURE;
-        goto cleanup;
-    }
-
-    for (i = 0, j = 0; i < nexts; i++) {
-        const struct gss_eap_extension_provider *ext = &exts[i];
-        gss_buffer_desc extension = GSS_C_EMPTY_BUFFER;
-
-        types[j] = ext->type;
-        if (ext->critical)
-            types[j] |= EXT_FLAG_CRITICAL;
-
-        major = ext->make(minor, cred, ctx, chanBindings, &extension);
-        if (GSS_ERROR(major)) {
-            if (ext->critical)
-                goto cleanup;
-            else
-                continue;
-        }
-
-        major = gss_add_buffer_set_member(minor, &extension, &extensions);
-        if (GSS_ERROR(major))
-            goto cleanup;
-
-        j++;
-    }
-
-    assert(j == (extensions == GSS_C_NO_BUFFER_SET ? 0 : extensions->count));
-
-    major = encodeExtensions(minor, extensions, types, buffer);
-    if (GSS_ERROR(major))
-        goto cleanup;
-
-cleanup:
-    gss_release_buffer_set(&tmpMinor, &extensions);
-    if (types != NULL)
-        GSSEAP_FREE(types);
-
-    return major;
-}
-
-OM_uint32
-gssEapVerifyExtensions(OM_uint32 *minor,
-                       gss_cred_id_t cred,
-                       gss_ctx_id_t ctx,
-                       gss_channel_bindings_t chanBindings,
-                       const gss_buffer_t buffer)
-{
-    OM_uint32 major, tmpMinor;
-    gss_buffer_set_t extensions = GSS_C_NO_BUFFER_SET;
-    OM_uint32 *types = NULL;
-    size_t i, nexts;
-    const struct gss_eap_extension_provider *exts;
-
-    if (CTX_IS_INITIATOR(ctx)) {
-        exts = eapGssAcceptExtensions;
-        nexts = sizeof(eapGssAcceptExtensions) / sizeof(eapGssAcceptExtensions[0]);
-    } else {
-        exts = eapGssInitExtensions;
-        nexts = sizeof(eapGssInitExtensions) / sizeof(eapGssInitExtensions[0]);
-    }
-
-    major = decodeExtensions(minor, buffer, &extensions, &types);
-    if (GSS_ERROR(major))
-        goto cleanup;
-
-    for (i = 0; i < nexts; i++) {
-        const struct gss_eap_extension_provider *ext = &exts[i];
-        gss_buffer_t extension = GSS_C_NO_BUFFER;
-        size_t j;
-
-        for (j = 0; j < extensions->count; j++) {
-            if ((types[j] & EXT_TYPE_MASK) == ext->type) {
-                extension = &extensions->elements[j];
-                break;
-            }
-        }
-
-        if (extension != GSS_C_NO_BUFFER) {
-            /* Process extension and mark as verified */
-            major = ext->verify(minor, cred, ctx, chanBindings,
-                                &extensions->elements[j]);
-            if (GSS_ERROR(major))
-                goto cleanup;
-
-            types[j] |= EXT_FLAG_VERIFIED;
-        } else if (ext->required) {
-            /* Required extension missing */
-            *minor = ENOENT;
-            major = GSS_S_UNAVAILABLE;
-            gssEapSaveStatusInfo(*minor,
-                                 "Missing required GSS EAP extension %08x",
-                                 ext->type);
-            goto cleanup;
-        }
-    }
-
-    /* Check we processed all critical extensions */
-    for (i = 0; i < extensions->count; i++) {
-        if ((types[i] & EXT_FLAG_CRITICAL) &&
-            (types[i] & EXT_FLAG_VERIFIED) == 0) {
-            *minor = ENOSYS;
-            major = GSS_S_UNAVAILABLE;
-            gssEapSaveStatusInfo(*minor,
-                                 "Received unknown critical GSS EAP extension %08x",
-                                 (types[i] & EXT_TYPE_MASK));
-            goto cleanup;
-        }
-    }
-
-    *minor = 0;
-    major = GSS_S_COMPLETE;
-
-cleanup:
-    gss_release_buffer_set(&tmpMinor, &extensions);
-    if (types != NULL)
-        GSSEAP_FREE(types);
-
-    return major;
-}