pull up r23742 from trunk
authorTom Yu <tlyu@mit.edu>
Tue, 23 Feb 2010 00:25:58 +0000 (00:25 +0000)
committerTom Yu <tlyu@mit.edu>
Tue, 23 Feb 2010 00:25:58 +0000 (00:25 +0000)
 ------------------------------------------------------------------------
 r23742 | ghudson | 2010-02-21 23:52:30 -0500 (Sun, 21 Feb 2010) | 24 lines

 ticket: 6603
 target_version: 1.8
 tags: pullup

 Fix two unrelated problems in SPNEGO which don't crop up with the krb5
 mechanism.

 1. The third call to spnego_init_accept_context uses faulty logic to
 determine if the exchange is complete, preventing a third mech token
 from being sent to the acceptor if no MIC exchange is required.
 Follow the logic used in the second call (in init_ctx_nego), which is
 correct.

 2. If the acceptor selects a mech other than the optimistic mech, it
 sets sc->mic_reqd to 1 whether or not the selected mech supports MICs
 (which isn't known until the mech completes).  Most code outside of
 handle_mic checks sc->mic_reqd along with (sc->ctx_flags &
 GSS_C_INTEG_FLAG), but the code in acc_ctx_call_acc neglected to do
 so, so it could improperly delegate responsibility for deciding when
 the negotiation was finished to handle_mic--which never gets called if
 (sc->ctx_flags & GSS_C_INTEG_FLAG) is false.  Fix acc_ctx_call_acc to
 check sc->ctx_flags so that mechs which don't support integrity
 protection can complete if they are selected non-optimistically.

ticket: 6603
version_fixed: 1.8
status: resolved

git-svn-id: svn://anonsvn.mit.edu/krb5/branches/krb5-1-8@23748 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/gssapi/spnego/spnego_mech.c

index 60fadd5e5ba84d6fd22096a455747c09f5abcc2d..cb286bc5cc1de80d4f10103c9233a8c46db400d6 100644 (file)
@@ -448,8 +448,9 @@ create_spnego_ctx(void)
 }
 
 /*
- * Both initiator and acceptor call here to verify and/or create
- * mechListMIC, and to consistency-check the MIC state.
+ * Both initiator and acceptor call here to verify and/or create mechListMIC,
+ * and to consistency-check the MIC state.  handle_mic is invoked only if the
+ * negotiated mech has completed and supports MICs.
  */
 static OM_uint32
 handle_mic(OM_uint32 *minor_status, gss_buffer_t mic_in,
@@ -658,18 +659,20 @@ init_ctx_cont(OM_uint32 *minor_status, gss_ctx_id_t *ctx, gss_buffer_t buf,
                                    supportedMech, responseToken,
                                    mechListMIC,
                                    negState, tokflag);
-       } else if (!sc->mech_complete &&
-                  *responseToken == GSS_C_NO_BUFFER) {
-               /*
-                * mech not finished and mech token missing
-                */
+       } else if ((!sc->mech_complete && *responseToken == GSS_C_NO_BUFFER) ||
+                  (sc->mech_complete && *responseToken != GSS_C_NO_BUFFER)) {
+               /* Missing or spurious token from acceptor. */
                ret = GSS_S_DEFECTIVE_TOKEN;
-       } else if (sc->mic_reqd &&
-                  (sc->ctx_flags & GSS_C_INTEG_FLAG)) {
+       } else if (!sc->mech_complete ||
+                  (sc->mic_reqd &&
+                   (sc->ctx_flags & GSS_C_INTEG_FLAG))) {
+               /* Not obviously done; we may decide we're done later in
+                * init_ctx_call_init or handle_mic. */
                *negState = ACCEPT_INCOMPLETE;
                *tokflag = CONT_TOKEN_SEND;
                ret = GSS_S_CONTINUE_NEEDED;
        } else {
+               /* mech finished on last pass and no MIC required, so done. */
                *negState = ACCEPT_COMPLETE;
                *tokflag = NO_TOKEN_SEND;
                ret = GSS_S_COMPLETE;
@@ -1535,10 +1538,13 @@ acc_ctx_call_acc(OM_uint32 *minor_status, spnego_gss_ctx_id_t sc,
                if (ret_flags != NULL)
                        *ret_flags = sc->ctx_flags;
 
-               if (!sc->mic_reqd) {
+               if (!sc->mic_reqd ||
+                   !(sc->ctx_flags & GSS_C_INTEG_FLAG)) {
+                       /* No MIC exchange required, so we're done. */
                        *negState = ACCEPT_COMPLETE;
                        ret = GSS_S_COMPLETE;
                } else {
+                       /* handle_mic will decide if we're done. */
                        ret = GSS_S_CONTINUE_NEEDED;
                }
        } else if (ret != GSS_S_CONTINUE_NEEDED) {