make state transition explicit rather than side-effect of GSS status code
authorLuke Howard <lukeh@padl.com>
Tue, 8 Mar 2011 02:50:46 +0000 (13:50 +1100)
committerLuke Howard <lukeh@padl.com>
Tue, 8 Mar 2011 13:38:41 +0000 (00:38 +1100)
accept_sec_context.c
gssapiP_eap.h
init_sec_context.c
util_sm.c

index 6d65647..d9e232e 100644 (file)
@@ -48,7 +48,8 @@ eapGssSmAcceptGssReauth(OM_uint32 *minor,
                         OM_uint32 timeReq __attribute__((__unused__)),
                         gss_channel_bindings_t chanBindings,
                         gss_buffer_t inputToken,
-                        gss_buffer_t outputToken);
+                        gss_buffer_t outputToken,
+                        int *transitionState);
 #endif
 
 /*
@@ -137,7 +138,8 @@ eapGssSmAcceptIdentity(OM_uint32 *minor,
                        OM_uint32 timeReq __attribute__((__unused__)),
                        gss_channel_bindings_t chanBindings __attribute__((__unused__)),
                        gss_buffer_t inputToken,
-                       gss_buffer_t outputToken)
+                       gss_buffer_t outputToken,
+                       int *transitionState)
 {
     OM_uint32 major;
     struct wpabuf *reqData;
@@ -178,7 +180,9 @@ eapGssSmAcceptIdentity(OM_uint32 *minor,
     wpabuf_free(reqData);
 
     *minor = 0;
-    return GSS_S_COMPLETE; /* advance state */
+    *transitionState = 1;
+
+    return GSS_S_CONTINUE_NEEDED;
 }
 
 /*
@@ -425,7 +429,8 @@ eapGssSmAcceptAuthenticate(OM_uint32 *minor,
                            OM_uint32 timeReq __attribute__((__unused__)),
                            gss_channel_bindings_t chanBindings,
                            gss_buffer_t inputToken,
-                           gss_buffer_t outputToken)
+                           gss_buffer_t outputToken,
+                           int *transitionState)
 {
     OM_uint32 major, tmpMinor;
     struct rs_connection *rconn;
@@ -522,8 +527,6 @@ eapGssSmAcceptAuthenticate(OM_uint32 *minor,
                                    &ctx->acceptorCtx.state, TRUE);
         if (GSS_ERROR(major) && *minor != GSSEAP_NO_SUCH_ATTR)
             goto cleanup;
-
-        major = GSS_S_CONTINUE_NEEDED;
     } else {
         ctx->acceptorCtx.vps = frresp->vps;
         frresp->vps = NULL;
@@ -535,9 +538,12 @@ eapGssSmAcceptAuthenticate(OM_uint32 *minor,
         if (GSS_ERROR(major))
             goto cleanup;
 
-        major = GSS_S_COMPLETE; /* advance state */
+        *transitionState = 1;
     }
 
+    major = GSS_S_CONTINUE_NEEDED;
+    *minor = 0;
+
 cleanup:
     if (request != NULL)
         rs_request_destroy(request);
@@ -557,7 +563,8 @@ eapGssSmAcceptGssChannelBindings(OM_uint32 *minor,
                                  OM_uint32 timeReq __attribute__((__unused__)),
                                  gss_channel_bindings_t chanBindings,
                                  gss_buffer_t inputToken,
-                                 gss_buffer_t outputToken)
+                                 gss_buffer_t outputToken,
+                                 int *transitionState)
 {
     OM_uint32 major, tmpMinor;
     gss_iov_buffer_desc iov[2];
@@ -578,9 +585,6 @@ eapGssSmAcceptGssChannelBindings(OM_uint32 *minor,
         !bufferEqual(&iov[0].buffer, &chanBindings->application_data)) {
         major = GSS_S_BAD_BINDINGS;
         *minor = GSSEAP_BINDINGS_MISMATCH;
-    } else {
-        major = GSS_S_CONTINUE_NEEDED; /* process additional extensions */
-        *minor = 0;
     }
 
     gss_release_buffer(&tmpMinor, &iov[0].buffer);
@@ -599,7 +603,8 @@ eapGssSmAcceptReauthCreds(OM_uint32 *minor,
                           OM_uint32 timeReq __attribute__((__unused__)),
                           gss_channel_bindings_t chanBindings __attribute__((__unused__)),
                           gss_buffer_t inputToken,
-                          gss_buffer_t outputToken)
+                          gss_buffer_t outputToken,
+                          int *transitionState)
 {
     OM_uint32 major;
 
@@ -611,8 +616,7 @@ eapGssSmAcceptReauthCreds(OM_uint32 *minor,
     if (GSS_ERROR(major))
         return major;
 
-    *minor = 0;
-    return GSS_S_CONTINUE_NEEDED; /* process additional extensions */
+    return major;
 }
 #endif
 
@@ -626,10 +630,12 @@ eapGssSmAcceptNegoExtFinished(OM_uint32 *minor,
                               OM_uint32 timeReq __attribute__((__unused__)),
                               gss_channel_bindings_t chanBindings __attribute__((__unused__)),
                               gss_buffer_t inputToken,
-                              gss_buffer_t outputToken)
+                              gss_buffer_t outputToken,
+                              int *transitionState)
 {
     *minor = 0;
-    return GSS_S_COMPLETE; /* advance state */
+    *transitionState = 1;
+    return GSS_S_COMPLETE;
 }
 
 static struct gss_eap_sm eapGssAcceptorSm[] = {
@@ -667,6 +673,7 @@ static struct gss_eap_sm eapGssAcceptorSm[] = {
         1, /* required */
         eapGssSmAcceptGssChannelBindings,
     },
+#ifdef GSSEAP_ENABLE_REAUTH
     {
         ITOK_TYPE_NONE,
         ITOK_TYPE_REAUTH_CREDS,
@@ -675,6 +682,7 @@ static struct gss_eap_sm eapGssAcceptorSm[] = {
         0, /* required */
         eapGssSmAcceptReauthCreds,
     },
+#endif
     {
         ITOK_TYPE_NONE,
         ITOK_TYPE_NONE,
@@ -835,7 +843,8 @@ eapGssSmAcceptGssReauth(OM_uint32 *minor,
                         OM_uint32 timeReq __attribute__((__unused__)),
                         gss_channel_bindings_t chanBindings,
                         gss_buffer_t inputToken,
-                        gss_buffer_t outputToken)
+                        gss_buffer_t outputToken,
+                        int *transitionState)
 {
     OM_uint32 major, tmpMinor;
     gss_name_t krbInitiator = GSS_C_NO_NAME;
@@ -864,6 +873,7 @@ eapGssSmAcceptGssReauth(OM_uint32 *minor,
     if (major == GSS_S_COMPLETE) {
         major = acceptReadyKrb(minor, ctx, cred,
                                krbInitiator, mech, timeRec);
+        *transitionState = 1;
     }
 
     ctx->gssFlags = gssFlags;
index bcfdf03..884ed86 100644 (file)
@@ -166,7 +166,8 @@ struct gss_eap_sm {
                               OM_uint32,
                               gss_channel_bindings_t,
                               gss_buffer_t,
-                              gss_buffer_t);
+                              gss_buffer_t,
+                              int *);
 };
 
 #define CTX_IS_ESTABLISHED(ctx)             ((ctx)->state == GSSEAP_STATE_ESTABLISHED)
index f55aec9..56bbd6c 100644 (file)
@@ -391,7 +391,8 @@ eapGssSmInitError(OM_uint32 *minor,
                   OM_uint32 timeReq,
                   gss_channel_bindings_t chanBindings,
                   gss_buffer_t inputToken,
-                  gss_buffer_t outputToken)
+                  gss_buffer_t outputToken,
+                  int *transitionState)
 {
     OM_uint32 major;
     unsigned char *p;
@@ -427,7 +428,8 @@ eapGssSmInitGssReauth(OM_uint32 *minor,
                       OM_uint32 timeReq,
                       gss_channel_bindings_t chanBindings,
                       gss_buffer_t inputToken,
-                      gss_buffer_t outputToken)
+                      gss_buffer_t outputToken,
+                      int *transitionState)
 {
     OM_uint32 major, tmpMinor;
     gss_name_t mechTarget = GSS_C_NO_NAME;
@@ -480,10 +482,10 @@ eapGssSmInitGssReauth(OM_uint32 *minor,
         if (GSS_ERROR(major))
             goto cleanup;
         ctx->state = GSSEAP_STATE_NEGO_EXT; /* skip */
-    } else {
-        major = GSS_S_COMPLETE; /* advance state */
     }
 
+    *transitionState = 1;
+
 cleanup:
     gssReleaseName(&tmpMinor, &mechTarget);
 
@@ -501,7 +503,8 @@ eapGssSmInitIdentity(OM_uint32 *minor,
                      OM_uint32 timeReq,
                      gss_channel_bindings_t chanBindings,
                      gss_buffer_t inputToken,
-                     gss_buffer_t outputToken)
+                     gss_buffer_t outputToken,
+                     int *transitionState)
 {
     OM_uint32 major;
     int initialContextToken;
@@ -524,7 +527,9 @@ eapGssSmInitIdentity(OM_uint32 *minor,
     outputToken->value = NULL;
 
     *minor = 0;
-    return GSS_S_COMPLETE; /* advance state */
+    *transitionState = 1;
+
+    return GSS_S_COMPLETE;
 }
 
 static struct wpabuf emptyWpaBuffer;
@@ -539,7 +544,8 @@ eapGssSmInitAuthenticate(OM_uint32 *minor,
                          OM_uint32 timeReq,
                          gss_channel_bindings_t chanBindings,
                          gss_buffer_t inputToken,
-                         gss_buffer_t outputToken)
+                         gss_buffer_t outputToken,
+                         int *transitionState)
 {
     OM_uint32 major;
     OM_uint32 tmpMinor;
@@ -576,6 +582,8 @@ eapGssSmInitAuthenticate(OM_uint32 *minor,
 
     ctx->flags |= CTX_FLAG_EAP_REQ; /* we have a Request from the acceptor */
 
+    major = GSS_S_CONTINUE_NEEDED;
+
     wpabuf_set(&ctx->initiatorCtx.reqData,
                inputToken->value, inputToken->length);
 
@@ -584,19 +592,18 @@ eapGssSmInitAuthenticate(OM_uint32 *minor,
         ctx->flags &= ~(CTX_FLAG_EAP_RESP);
 
         resp = eap_get_eapRespData(ctx->initiatorCtx.eap);
-        major = GSS_S_CONTINUE_NEEDED;
     } else if (ctx->flags & CTX_FLAG_EAP_SUCCESS) {
         major = initReady(minor, ctx, reqFlags);
         if (GSS_ERROR(major))
             goto cleanup;
 
         ctx->flags &= ~(CTX_FLAG_EAP_SUCCESS);
-        major = GSS_S_COMPLETE; /* advance state */
+        *transitionState = 1;
     } else if (ctx->flags & CTX_FLAG_EAP_FAIL) {
         major = GSS_S_DEFECTIVE_CREDENTIAL;
         *minor = GSSEAP_PEER_AUTH_FAILURE;
     } else if (code == 0 && initialContextToken) {
-        major = GSS_S_CONTINUE_NEEDED;
+        /* */
     } else {
         major = GSS_S_DEFECTIVE_TOKEN;
         *minor = GSSEAP_PEER_BAD_MESSAGE;
@@ -635,7 +642,8 @@ eapGssSmInitGssChannelBindings(OM_uint32 *minor,
                                OM_uint32 timeReq,
                                gss_channel_bindings_t chanBindings,
                                gss_buffer_t inputToken,
-                               gss_buffer_t outputToken)
+                               gss_buffer_t outputToken,
+                               int *transitionState)
 {
     OM_uint32 major;
     gss_buffer_desc buffer = GSS_C_EMPTY_BUFFER;
@@ -665,7 +673,8 @@ eapGssSmInitReauthCreds(OM_uint32 *minor,
                         OM_uint32 timeReq,
                         gss_channel_bindings_t chanBindings,
                         gss_buffer_t inputToken,
-                        gss_buffer_t outputToken)
+                        gss_buffer_t outputToken,
+                        int *transitionState)
 {
     OM_uint32 major;
 
@@ -688,10 +697,12 @@ eapGssSmInitNegoExtFinished(OM_uint32 *minor,
                             OM_uint32 timeReq,
                             gss_channel_bindings_t chanBindings,
                             gss_buffer_t inputToken,
-                            gss_buffer_t outputToken)
+                            gss_buffer_t outputToken,
+                            int *transitionState)
 {
     *minor = 0;
-    return GSS_S_COMPLETE; /* advance state */
+    *transitionState = 1;
+    return GSS_S_COMPLETE;
 }
 
 static struct gss_eap_sm eapGssInitiatorSm[] = {
@@ -713,7 +724,6 @@ static struct gss_eap_sm eapGssInitiatorSm[] = {
         eapGssSmInitGssReauth,
     },
 #endif
-    /* first-leg extensions go here, they should return GSS_S_CONTINUE_NEEDED */
     {
         ITOK_TYPE_NONE,
         ITOK_TYPE_NONE,
index 9c2ae38..71783e2 100644 (file)
--- a/util_sm.c
+++ b/util_sm.c
@@ -161,6 +161,8 @@ gssEapSmStep(OM_uint32 *minor,
      * is reached.
      */
     do {
+        int transitionState = 0;
+
         major = GSS_S_COMPLETE;
 
         for (i = 0; i < smCount; i++) {
@@ -200,7 +202,7 @@ gssEapSmStep(OM_uint32 *minor,
             if (processToken) {
                 major = smp->processToken(minor, cred, ctx, target, mech, reqFlags,
                                          timeReq, chanBindings, innerInputToken,
-                                         &innerOutputToken);
+                                         &innerOutputToken, &transitionState);
                 if (GSS_ERROR(major))
                     break;
 
@@ -215,7 +217,7 @@ gssEapSmStep(OM_uint32 *minor,
                         outputTokenTypes[innerOutputTokens->count] |= ITOK_FLAG_CRITICAL;
                     innerOutputTokens->count++;
                 }
-                if (major == GSS_S_COMPLETE)
+                if (transitionState)
                     break;
             } else if (smp->required && smp->inputTokenType != ITOK_TYPE_NONE) {
                 major = GSS_S_DEFECTIVE_TOKEN;
@@ -224,15 +226,15 @@ gssEapSmStep(OM_uint32 *minor,
             }
         }
 
-        if (major != GSS_S_COMPLETE)
-            break; /* GSS_S_CONTINUE_NEEDED or error */
+        if (GSS_ERROR(major) || !transitionState)
+            break;
 
         assert(ctx->state < GSSEAP_STATE_ESTABLISHED);
 
         ctx->state = GSSEAP_STATE_NEXT(ctx->state);
 
         if (innerOutputTokens->count != 0) {
-            major = GSS_S_CONTINUE_NEEDED;
+            assert(major == GSS_S_CONTINUE_NEEDED);
             break; /* send any tokens if we have them */
         }
     } while (ctx->state != GSSEAP_STATE_ESTABLISHED);