gss_init_sec_context() and gss_accept_sec_context() both output a token and
either create or modify a security context. There are some additional outputs:
actual_mech_type, ret_flags, and time_rec for gss_init_sec_context(), and
src_name, mech_type, ret_flags, time_rec, and delegated_cred_handle for
gss_accept_sec_context(). RFC 2744 sections 5.1 and 5.19 define some rules for
how these parameters should be set when GSS_S_CONTINUE_NEEDED is returned.
Although the mechglue initializes most output parameters, it does not do so for
ret_flags and time_rec. This is a separate bug, which impacts the following
SPNEGO misbehaviors; if SPNEGO does not set these output parameters, the
caller's value will remain unchanged.
The current SPNEGO implementation has the following bugs related to the
additional output parameters:
* gss_init_sec_context() only sets ret_flags if the underlying mech is called
and returns GSS_S_COMPLETE, or if SPNEGO itself will return GSS_S_COMPLETE.
gss_accept_sec_context() initializes ret_flags to 0, and only sets ret_flags to
another value if the underlying mech is called and returns GSS_S_COMPLETE;
ret_flags could remain as 0 on SPNEGO's final return from
gss_accept_sec_context(), if the MIC exchange forces an extra round trip.
* gss_init_sec_context() and gss_accept_sec_context() do not filter out
PROT_READY from ret_flags as required by RFC 4178.
* gss_init_sec_context() and gss_accept_sec_context() pass time_rec directly to
the underlying mech. gss_accept_sec_context() initializes time_rec to 0 but
gss_init_sec_context() does not. Neither function will set time_rec to a
meaningful value if the underlying mech is not called on the final SPNEGO call
due to the MIC exchange. Note that time_rec is relative to the current time; if
SPNEGO records time_rec from the underlying mech at one step and reports it to
the caller at a later step, the time differential between steps could render
that value inaccurate. SPNEGO could either adjust the value by the
differential, or call gss_context_time() on the underlying context.
* gss_accept_sec_context() initializes mech_type to GSS_C_NO_OID and passes it
directly to the underlying mech. If the underlying mech is not called on the
final step, mech_type will remain as GSS_C_NO_OID.
* gss_accept_sec_context() initializes delegated_cred_handle to
GSS_C_NO_CREDENTIAL and passes it directly to the underlying mech. SPNEGO could
report a delegated cred to the caller too early (before the MIC exchange) and
not on the final call.
* gss_accept_sec_context() could leak a value of src_name (recorded as
sc->internal_name) if the underlying mech reports it twice. RFC 2744 doesn't
explicitly prohibit this, although it seems like it should be unusual.