Explain the current SPNEGO initiator/acceptor design in comments. No
authorGreg Hudson <ghudson@mit.edu>
Mon, 22 Feb 2010 16:10:05 +0000 (16:10 +0000)
committerGreg Hudson <ghudson@mit.edu>
Mon, 22 Feb 2010 16:10:05 +0000 (16:10 +0000)
code changes.

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@23743 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/gssapi/spnego/spnego_mech.c

index daabf63572791bef13c929b3fcef326119b8ffec..f7fcb5e5588a7a6d542760dbe116c4eee302931a 100644 (file)
@@ -29,7 +29,7 @@
  *
  * A module that implements the spnego security mechanism.
  * It is used to negotiate the security mechanism between
- * peers using the GSS-API.
+ * peers using the GSS-API.  SPNEGO is specified in RFC 4178.
  *
  */
 /*
@@ -336,6 +336,8 @@ spnego_gss_acquire_cred(OM_uint32 *minor_status,
        if (time_rec)
                *time_rec = 0;
 
+       /* We will obtain a mechglue credential and wrap it in a
+        * spnego_gss_cred_id_rec structure.  Allocate the wrapper. */
        spcred = malloc(sizeof(spnego_gss_cred_id_rec));
        if (spcred == NULL) {
                *minor_status = ENOMEM;
@@ -892,14 +894,6 @@ spnego_gss_init_sec_context(
                        OM_uint32 *ret_flags,
                        OM_uint32 *time_rec)
 {
-       /*
-        * send_token is used to indicate in later steps
-        * what type of token, if any should be sent or processed.
-        * NO_TOKEN_SEND = no token should be sent
-        * INIT_TOKEN_SEND = initial token will be sent
-        * CONT_TOKEN_SEND = continuing tokens to be sent
-        * CHECK_MIC = no token to be sent, but have a MIC to check.
-        */
        send_token_flag send_token = NO_TOKEN_SEND;
        OM_uint32 tmpmin, ret, negState;
        gss_buffer_t mechtok_in, mechListMIC_in, mechListMIC_out;
@@ -913,6 +907,29 @@ spnego_gss_init_sec_context(
        mechtok_in = mechListMIC_out = mechListMIC_in = GSS_C_NO_BUFFER;
        negState = REJECT;
 
+       /*
+        * This function works in three steps:
+        *
+        *   1. Perform mechanism negotiation.
+        *   2. Invoke the negotiated or optimistic mech's gss_init_sec_context
+        *      function and examine the results.
+        *   3. Process or generate MICs if necessary.
+        *
+        * The three steps share responsibility for determining when the
+        * exchange is complete.  If the selected mech completed in a previous
+        * call and no MIC exchange is expected, then step 1 will decide.  If
+        * the selected mech completes in this call and no MIC exchange is
+        * expected, then step 2 will decide.  If a MIC exchange is expected,
+        * then step 3 will decide.  If an error occurs in any step, the
+        * exchange will be aborted, possibly with an error token.
+        *
+        * negState determines the state of the negotiation, and is
+        * communicated to the acceptor if a continuing token is sent.
+        * send_token is used to indicate what type of token, if any, should be
+        * generated.
+        */
+
+       /* Validate arguments. */
        if (minor_status != NULL)
                *minor_status = 0;
        if (output_token != GSS_C_NO_BUFFER) {
@@ -927,6 +944,7 @@ spnego_gss_init_sec_context(
        if (actual_mech != NULL)
                *actual_mech = GSS_C_NO_OID;
 
+       /* Step 1: perform mechanism negotiation. */
        spcred = (spnego_gss_cred_id_t)claimant_cred_handle;
        if (*context_handle == GSS_C_NO_CONTEXT) {
                ret = init_ctx_new(minor_status, spcred,
@@ -942,6 +960,9 @@ spnego_gss_init_sec_context(
                        goto cleanup;
                }
        }
+
+       /* Step 2: invoke the selected or optimistic mechanism's
+        * gss_init_sec_context function, if it didn't complete previously. */
        spnego_ctx = (spnego_gss_ctx_id_t)*context_handle;
        if (!spnego_ctx->mech_complete) {
                ret = init_ctx_call_init(
@@ -952,7 +973,9 @@ spnego_gss_init_sec_context(
                        ret_flags, time_rec,
                        &negState, &send_token);
        }
-       /* create mic/check mic */
+
+       /* Step 3: process or generate the MIC, if the negotiated mech is
+        * complete and supports MICs. */
        if (!HARD_ERROR(ret) && spnego_ctx->mech_complete &&
            (spnego_ctx->ctx_flags & GSS_C_INTEG_FLAG)) {
 
@@ -1574,6 +1597,29 @@ spnego_gss_accept_sec_context(
 
        mechtok_in = mic_in = mic_out = GSS_C_NO_BUFFER;
 
+       /*
+        * This function works in three steps:
+        *
+        *   1. Perform mechanism negotiation.
+        *   2. Invoke the negotiated mech's gss_accept_sec_context function
+        *      and examine the results.
+        *   3. Process or generate MICs if necessary.
+        *
+        * Step one determines whether the negotiation requires a MIC exchange,
+        * while steps two and three share responsibility for determining when
+        * the exchange is complete.  If the selected mech completes in this
+        * call and no MIC exchange is expected, then step 2 will decide.  If a
+        * MIC exchange is expected, then step 3 will decide.  If an error
+        * occurs in any step, the exchange will be aborted, possibly with an
+        * error token.
+        *
+        * negState determines the state of the negotiation, and is
+        * communicated to the acceptor if a continuing token is sent.
+        * return_token is used to indicate what type of token, if any, should
+        * be generated.
+        */
+
+       /* Validate arguments. */
        if (minor_status != NULL)
                *minor_status = 0;
        if (output_token != GSS_C_NO_BUFFER) {
@@ -1589,9 +1635,11 @@ spnego_gss_accept_sec_context(
        if (input_token == GSS_C_NO_BUFFER)
                return GSS_S_CALL_INACCESSIBLE_READ;
 
+       /* Step 1: Perform mechanism negotiation. */
        sc = (spnego_gss_ctx_id_t)*context_handle;
        spcred = (spnego_gss_cred_id_t)verifier_cred_handle;
        if (sc == NULL || sc->internal_mech == GSS_C_NO_OID) {
+               /* Process an initial token or request for NegHints. */
                if (src_name != NULL)
                        *src_name = GSS_C_NO_NAME;
                if (mech_type != NULL)
@@ -1623,7 +1671,8 @@ spnego_gss_accept_sec_context(
                        ret = GSS_S_CONTINUE_NEEDED;
                }
        } else {
-               /* Can set negState to ACCEPT_INCOMPLETE */
+               /* Process a response token.  Can set negState to
+                * ACCEPT_INCOMPLETE. */
                ret = acc_ctx_cont(minor_status, input_token,
                                   context_handle, &mechtok_in,
                                   &mic_in, &negState, &return_token);
@@ -1631,6 +1680,9 @@ spnego_gss_accept_sec_context(
                        goto cleanup;
                ret = GSS_S_CONTINUE_NEEDED;
        }
+
+       /* Step 2: invoke the negotiated mechanism's gss_accept_sec_context
+        * function. */
        sc = (spnego_gss_ctx_id_t)*context_handle;
        /*
         * Handle mechtok_in and mic_in only if they are
@@ -1649,6 +1701,9 @@ spnego_gss_accept_sec_context(
        } else if (negState == REQUEST_MIC) {
                mechstat = GSS_S_CONTINUE_NEEDED;
        }
+
+       /* Step 3: process or generate the MIC, if the negotiated mech is
+        * complete and supports MICs. */
        if (!HARD_ERROR(ret) && sc->mech_complete &&
            (sc->ctx_flags & GSS_C_INTEG_FLAG)) {