Add error token type
authorLuke Howard <lukeh@padl.com>
Tue, 12 Oct 2010 00:16:56 +0000 (01:16 +0100)
committerLuke Howard <lukeh@padl.com>
Tue, 12 Oct 2010 00:16:56 +0000 (01:16 +0100)
accept_sec_context.c
gssapiP_eap.h
gsseap_err.et
init_sec_context.c
util.h

index b8446d3..86327eb 100644 (file)
@@ -463,6 +463,24 @@ eapGssSmAcceptEstablished(OM_uint32 *minor,
     return GSS_S_BAD_STATUS;
 }
 
+static OM_uint32
+makeErrorToken(OM_uint32 *minor,
+               OM_uint32 majorStatus,
+               OM_uint32 minorStatus,
+               gss_buffer_t outputToken)
+{
+    unsigned char errorData[8];
+    gss_buffer_desc errorBuffer;
+
+    store_uint32_be(majorStatus, &errorData[0]);
+    store_uint32_be(minorStatus, &errorData[4]);
+
+    errorBuffer.length = sizeof(errorData);
+    errorBuffer.value = errorData;
+
+    return duplicateBuffer(minor, &errorBuffer, outputToken);
+}
+
 static struct gss_eap_acceptor_sm {
     enum gss_eap_token_type inputTokenType;
     enum gss_eap_token_type outputTokenType;
@@ -473,13 +491,14 @@ static struct gss_eap_acceptor_sm {
                               gss_channel_bindings_t,
                               gss_buffer_t);
 } eapGssAcceptorSm[] = {
-    { TOK_TYPE_EAP_RESP,    TOK_TYPE_EAP_REQ,    eapGssSmAcceptIdentity           },
-    { TOK_TYPE_EAP_RESP,    TOK_TYPE_EAP_REQ,    eapGssSmAcceptAuthenticate       },
-    { TOK_TYPE_EXT_REQ,     TOK_TYPE_NONE,       eapGssSmAcceptExtensionsReq      },
-    { TOK_TYPE_NONE,        TOK_TYPE_EXT_RESP,   eapGssSmAcceptExtensionsResp     },
-    { TOK_TYPE_NONE,        TOK_TYPE_NONE,       eapGssSmAcceptEstablished        },
+    { TOK_TYPE_EAP_RESP,    TOK_TYPE_EAP_REQ,       eapGssSmAcceptIdentity           },
+    { TOK_TYPE_EAP_RESP,    TOK_TYPE_EAP_REQ,       eapGssSmAcceptAuthenticate       },
+    { TOK_TYPE_EXT_REQ,     TOK_TYPE_NONE,          eapGssSmAcceptExtensionsReq      },
+    { TOK_TYPE_NONE,        TOK_TYPE_EXT_RESP,      eapGssSmAcceptExtensionsResp     },
+    { TOK_TYPE_NONE,        TOK_TYPE_NONE,          eapGssSmAcceptEstablished        },
+    { TOK_TYPE_NONE,        TOK_TYPE_CONTEXT_ERR,   NULL                             },
 #ifdef GSSEAP_ENABLE_REAUTH
-    { TOK_TYPE_GSS_REAUTH,  TOK_TYPE_GSS_REAUTH, eapGssSmAcceptGssReauth          },
+    { TOK_TYPE_GSS_REAUTH,  TOK_TYPE_GSS_REAUTH,    eapGssSmAcceptGssReauth          },
 #endif
 };
 
@@ -575,23 +594,23 @@ gss_accept_sec_context(OM_uint32 *minor,
                                    &innerInputToken,
                                    input_chan_bindings,
                                    &innerOutputToken);
-        if (GSS_ERROR(major))
-            goto cleanup;
+        if (GSS_ERROR(major)) {
+            /* Generate an error token */
+            tmpMajor = makeErrorToken(&tmpMinor, major, *minor, &innerOutputToken);
+            if (GSS_ERROR(tmpMajor)) {
+                major = tmpMajor;
+                goto cleanup;
+            }
+
+            sm = &eapGssAcceptorSm[EAP_STATE_ERROR];
+            goto send_token;
+        }
     } while (major == GSS_S_CONTINUE_NEEDED && innerOutputToken.length == 0);
 
     if (mech_type != NULL) {
         if (!gssEapInternalizeOid(ctx->mechanismUsed, mech_type))
             duplicateOid(&tmpMinor, ctx->mechanismUsed, mech_type);
     }
-    if (innerOutputToken.value != NULL) {
-        tmpMajor = gssEapMakeToken(&tmpMinor, ctx, &innerOutputToken,
-                                   sm->outputTokenType, output_token);
-        if (GSS_ERROR(tmpMajor)) {
-            major = tmpMajor;
-            *minor = tmpMinor;
-            goto cleanup;
-        }
-    }
     if (ret_flags != NULL)
         *ret_flags = ctx->gssFlags;
     if (delegated_cred_handle != NULL)
@@ -609,6 +628,17 @@ gss_accept_sec_context(OM_uint32 *minor,
 
     assert(ctx->state == EAP_STATE_ESTABLISHED || major == GSS_S_CONTINUE_NEEDED);
 
+send_token:
+    if (innerOutputToken.value != NULL) {
+        tmpMajor = gssEapMakeToken(&tmpMinor, ctx, &innerOutputToken,
+                                   sm->outputTokenType, output_token);
+        if (GSS_ERROR(tmpMajor)) {
+            major = tmpMajor;
+            *minor = tmpMinor;
+            goto cleanup;
+        }
+    }
+
 cleanup:
     if (cred != GSS_C_NO_CREDENTIAL)
         GSSEAP_MUTEX_UNLOCK(&cred->mutex);
index de45508..d5e9da4 100644 (file)
@@ -130,6 +130,7 @@ enum gss_eap_state {
     EAP_STATE_EXTENSIONS_REQ,
     EAP_STATE_EXTENSIONS_RESP,
     EAP_STATE_ESTABLISHED,
+    EAP_STATE_ERROR,
 #ifdef GSSEAP_ENABLE_REAUTH
     EAP_STATE_KRB_REAUTH_GSS
 #endif
index 99f89f9..0e4a359 100644 (file)
@@ -62,5 +62,6 @@ error_code GSSEAP_BAD_CONTEXT_TOKEN,        "Context token is malformed or corru
 error_code GSSEAP_MISSING_IOV,              "IOV is missing required buffer"
 error_code GSSEAP_BAD_STREAM_IOV,           "Stream IOV can only contain a single data buffer"
 error_code GSSEAP_BAD_PRF_KEY,              "PRF key usage type is unknown"
+error_code GSSEAP_BAD_ERROR_TOKEN,          "Error token is malformed or corrupt"
 
 end
index f7eda20..56f41de 100644 (file)
@@ -562,6 +562,39 @@ eapGssSmInitEstablished(OM_uint32 *minor,
     return GSS_S_BAD_STATUS;
 }
 
+static OM_uint32
+eapGssSmInitError(OM_uint32 *minor,
+                  gss_cred_id_t cred,
+                  gss_ctx_id_t ctx,
+                  gss_name_t target,
+                  gss_OID mech,
+                  OM_uint32 reqFlags,
+                  OM_uint32 timeReq,
+                  gss_channel_bindings_t chanBindings,
+                  gss_buffer_t inputToken,
+                  gss_buffer_t outputToken)
+{
+    OM_uint32 major;
+    unsigned char *p;
+
+    if (inputToken->length < 8) {
+        *minor = GSSEAP_WRONG_SIZE;
+        return GSS_S_DEFECTIVE_TOKEN;
+    }
+
+    p = (unsigned char *)inputToken->value;
+
+    major = load_uint32_be(&p[0]);
+    *minor = load_uint32_be(&p[4]);
+
+    if (!GSS_ERROR(major)) {
+        *minor = GSSEAP_BAD_ERROR_TOKEN;
+        major = GSS_S_FAILURE;
+    }
+
+    return major;
+}
+
 static struct gss_eap_initiator_sm {
     enum gss_eap_token_type inputTokenType;
     enum gss_eap_token_type outputTokenType;
@@ -576,13 +609,14 @@ static struct gss_eap_initiator_sm {
                               gss_buffer_t,
                               gss_buffer_t);
 } eapGssInitiatorSm[] = {
-    { TOK_TYPE_NONE,    TOK_TYPE_EAP_RESP,      eapGssSmInitIdentity            },
-    { TOK_TYPE_EAP_REQ, TOK_TYPE_EAP_RESP,      eapGssSmInitAuthenticate        },
-    { TOK_TYPE_NONE,    TOK_TYPE_EXT_REQ,       eapGssSmInitExtensionsReq       },
-    { TOK_TYPE_EXT_RESP,TOK_TYPE_NONE,          eapGssSmInitExtensionsResp      },
-    { TOK_TYPE_NONE,    TOK_TYPE_NONE,          eapGssSmInitEstablished         },
+    { TOK_TYPE_NONE,        TOK_TYPE_EAP_RESP,      eapGssSmInitIdentity            },
+    { TOK_TYPE_EAP_REQ,     TOK_TYPE_EAP_RESP,      eapGssSmInitAuthenticate        },
+    { TOK_TYPE_NONE,        TOK_TYPE_EXT_REQ,       eapGssSmInitExtensionsReq       },
+    { TOK_TYPE_EXT_RESP,    TOK_TYPE_NONE,          eapGssSmInitExtensionsResp      },
+    { TOK_TYPE_NONE,        TOK_TYPE_NONE,          eapGssSmInitEstablished         },
+    { TOK_TYPE_CONTEXT_ERR, TOK_TYPE_NONE,          eapGssSmInitError               },
 #ifdef GSSEAP_ENABLE_REAUTH
-    { TOK_TYPE_GSS_REAUTH, TOK_TYPE_GSS_REAUTH, eapGssSmInitGssReauth           },
+    { TOK_TYPE_GSS_REAUTH,  TOK_TYPE_GSS_REAUTH,    eapGssSmInitGssReauth           },
 #endif
 };
 
@@ -673,7 +707,9 @@ gss_init_sec_context(OM_uint32 *minor,
         if (GSS_ERROR(major))
             goto cleanup;
 
-        if (tokType != sm->inputTokenType) {
+        if (tokType == TOK_TYPE_CONTEXT_ERR) {
+            ctx->state = EAP_STATE_ERROR;
+        } else if (tokType != sm->inputTokenType) {
             *minor = GSSEAP_WRONG_TOK_ID;
             major = GSS_S_DEFECTIVE_TOKEN;
             goto cleanup;
diff --git a/util.h b/util.h
index 3494aab..33d4482 100644 (file)
--- a/util.h
+++ b/util.h
@@ -84,13 +84,14 @@ enum gss_eap_token_type {
     TOK_TYPE_MIC                     = 0x0404,  /* RFC 4121 MIC token */
     TOK_TYPE_WRAP                    = 0x0504,  /* RFC 4121 wrap token */
     TOK_TYPE_EXPORT_NAME             = 0x0401,  /* RFC 2743 exported name */
-    TOK_TYPE_EXPORT_NAME_COMPOSITE   = 0x0402,  /* draft-ietf-kitten-gss-naming */
+    TOK_TYPE_EXPORT_NAME_COMPOSITE   = 0x0402,  /* exported composite name */
     TOK_TYPE_DELETE_CONTEXT          = 0x0405,  /* RFC 2743 delete context */
-    TOK_TYPE_EAP_RESP                = 0x0601,  /* draft-howlett-eap-gss */
-    TOK_TYPE_EAP_REQ                 = 0x0602,  /* draft-howlett-eap-gss */
-    TOK_TYPE_EXT_REQ                 = 0x0603,  /* draft-howlett-eap-gss */
-    TOK_TYPE_EXT_RESP                = 0x0604,  /* to be specified */
-    TOK_TYPE_GSS_REAUTH              = 0x0605,  /* to be specified */
+    TOK_TYPE_EAP_RESP                = 0x0601,  /* EAP response */
+    TOK_TYPE_EAP_REQ                 = 0x0602,  /* EAP request */
+    TOK_TYPE_EXT_REQ                 = 0x0603,  /* GSS EAP extensions request */
+    TOK_TYPE_EXT_RESP                = 0x0604,  /* GSS EAP extensions response */
+    TOK_TYPE_GSS_REAUTH              = 0x0605,  /* GSS EAP fast reauthentication token */
+    TOK_TYPE_CONTEXT_ERR             = 0x0606,  /* context error */
 };
 
 #define EAP_EXPORT_CONTEXT_V1           1