Skip to content

Commit

Permalink
Improve type safety of SPNEGO helper functions
Browse files Browse the repository at this point in the history
Modify init_ctx_new(), init_ctx_cont(), acc_ctx_hints(),
acc_ctx_new(), and acc_ctx_cont() to operate on SPNEGO context handles
rather than generic GSS context handles.  For the functions which
create a new context, move the context parameter to the end and follow
the usual practices for output parameters.  Adjust stage 1 flow
control in spnego_gss_accept_sec_context() to allow acc_ctx_new() to
always be a context constructor.
  • Loading branch information
greghudson committed Jan 11, 2016
1 parent 159dbbd commit 28db863
Showing 1 changed file with 77 additions and 85 deletions.
162 changes: 77 additions & 85 deletions src/lib/gssapi/spnego/spnego_mech.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,14 @@ handle_mic(OM_uint32 *, gss_buffer_t, int, spnego_gss_ctx_id_t,
gss_buffer_t *, OM_uint32 *, send_token_flag *);

static OM_uint32
init_ctx_new(OM_uint32 *, spnego_gss_cred_id_t, gss_ctx_id_t *,
send_token_flag *);
init_ctx_new(OM_uint32 *, spnego_gss_cred_id_t, send_token_flag *,
spnego_gss_ctx_id_t *);
static OM_uint32
init_ctx_nego(OM_uint32 *, spnego_gss_ctx_id_t, OM_uint32, gss_OID,
gss_buffer_t *, gss_buffer_t *,
OM_uint32 *, send_token_flag *);
static OM_uint32
init_ctx_cont(OM_uint32 *, gss_ctx_id_t *, gss_buffer_t,
init_ctx_cont(OM_uint32 *, spnego_gss_ctx_id_t, gss_buffer_t,
gss_buffer_t *, gss_buffer_t *,
OM_uint32 *, send_token_flag *);
static OM_uint32
Expand All @@ -136,13 +136,12 @@ init_ctx_call_init(OM_uint32 *, spnego_gss_ctx_id_t, spnego_gss_cred_id_t,
OM_uint32 *, send_token_flag *);

static OM_uint32
acc_ctx_new(OM_uint32 *, gss_buffer_t, gss_ctx_id_t *,
spnego_gss_cred_id_t, gss_buffer_t *,
gss_buffer_t *, OM_uint32 *, send_token_flag *);
acc_ctx_new(OM_uint32 *, gss_buffer_t, spnego_gss_cred_id_t, gss_buffer_t *,
gss_buffer_t *, OM_uint32 *, send_token_flag *,
spnego_gss_ctx_id_t *);
static OM_uint32
acc_ctx_cont(OM_uint32 *, gss_buffer_t, gss_ctx_id_t *,
gss_buffer_t *, gss_buffer_t *,
OM_uint32 *, send_token_flag *);
acc_ctx_cont(OM_uint32 *, gss_buffer_t, spnego_gss_ctx_id_t, gss_buffer_t *,
gss_buffer_t *, OM_uint32 *, send_token_flag *);
static OM_uint32
acc_ctx_vfy_oid(OM_uint32 *, spnego_gss_ctx_id_t, gss_OID,
OM_uint32 *, send_token_flag *);
Expand Down Expand Up @@ -193,8 +192,8 @@ const gss_OID_set_desc * const gss_mech_set_spnego = spnego_oidsets+0;
static int make_NegHints(OM_uint32 *, gss_buffer_t *);
static int put_neg_hints(unsigned char **, gss_buffer_t, unsigned int);
static OM_uint32
acc_ctx_hints(OM_uint32 *, gss_ctx_id_t *, spnego_gss_cred_id_t,
gss_buffer_t *, OM_uint32 *, send_token_flag *);
acc_ctx_hints(OM_uint32 *, spnego_gss_cred_id_t, gss_buffer_t *, OM_uint32 *,
send_token_flag *, spnego_gss_ctx_id_t *);

/*
* The Mech OID for SPNEGO:
Expand Down Expand Up @@ -620,18 +619,19 @@ process_mic(OM_uint32 *minor_status, gss_buffer_t mic_in,
return GSS_S_COMPLETE;
}

/*
* Initial call to spnego_gss_init_sec_context().
*/
/* Create a new SPNEGO context handle for the initial call to
* spnego_gss_init_sec_context(). */
static OM_uint32
init_ctx_new(OM_uint32 *minor_status,
spnego_gss_cred_id_t spcred,
gss_ctx_id_t *ctx,
send_token_flag *tokflag)
send_token_flag *tokflag,
spnego_gss_ctx_id_t *sc_out)
{
OM_uint32 ret;
spnego_gss_ctx_id_t sc = NULL;

*sc_out = NULL;

sc = create_spnego_ctx(1);
if (sc == NULL)
return GSS_S_FAILURE;
Expand All @@ -651,7 +651,7 @@ init_ctx_new(OM_uint32 *minor_status,
}

sc->ctx_handle = GSS_C_NO_CONTEXT;
*ctx = (gss_ctx_id_t)sc;
*sc_out = sc;
sc = NULL;
*tokflag = INIT_TOKEN_SEND;
ret = GSS_S_CONTINUE_NEEDED;
Expand All @@ -666,16 +666,15 @@ init_ctx_new(OM_uint32 *minor_status,
* to decode reply and update state.
*/
static OM_uint32
init_ctx_cont(OM_uint32 *minor_status, gss_ctx_id_t *ctx, gss_buffer_t buf,
gss_buffer_t *responseToken, gss_buffer_t *mechListMIC,
OM_uint32 *negState, send_token_flag *tokflag)
init_ctx_cont(OM_uint32 *minor_status, spnego_gss_ctx_id_t sc,
gss_buffer_t buf, gss_buffer_t *responseToken,
gss_buffer_t *mechListMIC, OM_uint32 *negState,
send_token_flag *tokflag)
{
OM_uint32 ret, tmpmin, acc_negState;
unsigned char *ptr;
spnego_gss_ctx_id_t sc;
gss_OID supportedMech = GSS_C_NO_OID;

sc = (spnego_gss_ctx_id_t)*ctx;
*negState = REJECT;
*tokflag = ERROR_TOKEN_SEND;

Expand Down Expand Up @@ -1034,13 +1033,14 @@ spnego_gss_init_sec_context(
spcred = (spnego_gss_cred_id_t)claimant_cred_handle;
spnego_ctx = (spnego_gss_ctx_id_t)*context_handle;
if (spnego_ctx == NULL) {
ret = init_ctx_new(minor_status, spcred,
context_handle, &send_token);
ret = init_ctx_new(minor_status, spcred, &send_token,
&spnego_ctx);
if (ret != GSS_S_CONTINUE_NEEDED) {
goto cleanup;
}
*context_handle = (gss_ctx_id_t)spnego_ctx;
} else {
ret = init_ctx_cont(minor_status, context_handle,
ret = init_ctx_cont(minor_status, spnego_ctx,
input_token, &mechtok_in,
&mechListMIC_in, &negState, &send_token);
if (HARD_ERROR(ret)) {
Expand All @@ -1050,7 +1050,6 @@ spnego_gss_init_sec_context(

/* 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(
minor_status, spnego_ctx, spcred,
Expand Down Expand Up @@ -1233,17 +1232,19 @@ make_NegHints(OM_uint32 *minor_status, gss_buffer_t *outbuf)
}

/*
* Support the Microsoft NegHints extension to SPNEGO for compatibility with
* some versions of Samba. See:
* http://msdn.microsoft.com/en-us/library/cc247039(PROT.10).aspx
* Create a new SPNEGO context handle for the initial call to
* spnego_gss_accept_sec_context() when the request is empty. For empty
* requests, we implement the Microsoft NegHints extension to SPNEGO for
* compatibility with some versions of Samba. See:
* http://msdn.microsoft.com/en-us/library/cc247039(PROT.10).aspx
*/
static OM_uint32
acc_ctx_hints(OM_uint32 *minor_status,
gss_ctx_id_t *ctx,
spnego_gss_cred_id_t spcred,
gss_buffer_t *mechListMIC,
OM_uint32 *negState,
send_token_flag *return_token)
send_token_flag *return_token,
spnego_gss_ctx_id_t *sc_out)
{
OM_uint32 tmpmin, ret;
gss_OID_set supported_mechSet;
Expand All @@ -1254,10 +1255,7 @@ acc_ctx_hints(OM_uint32 *minor_status,
*return_token = NO_TOKEN_SEND;
*negState = REJECT;
*minor_status = 0;

/* A hint request must be the first token received. */
if (*ctx != GSS_C_NO_CONTEXT)
return GSS_S_DEFECTIVE_TOKEN;
*sc_out = NULL;

ret = get_negotiable_mechs(minor_status, spcred, GSS_C_ACCEPT,
&supported_mechSet);
Expand All @@ -1282,7 +1280,7 @@ acc_ctx_hints(OM_uint32 *minor_status,
*negState = ACCEPT_INCOMPLETE;
*return_token = INIT_TOKEN_SEND;
sc->firstpass = 1;
*ctx = (gss_ctx_id_t)sc;
*sc_out = sc;
sc = NULL;
ret = GSS_S_COMPLETE;

Expand All @@ -1294,19 +1292,20 @@ acc_ctx_hints(OM_uint32 *minor_status,
}

/*
* Set negState to REJECT if the token is defective, else
* ACCEPT_INCOMPLETE or REQUEST_MIC, depending on whether initiator's
* preferred mechanism is supported.
* Create a new SPNEGO context handle for the initial call to
* spnego_gss_accept_sec_context(). Set negState to REJECT if the token is
* defective, else ACCEPT_INCOMPLETE or REQUEST_MIC, depending on whether
* the initiator's preferred mechanism is supported.
*/
static OM_uint32
acc_ctx_new(OM_uint32 *minor_status,
gss_buffer_t buf,
gss_ctx_id_t *ctx,
spnego_gss_cred_id_t spcred,
gss_buffer_t *mechToken,
gss_buffer_t *mechListMIC,
OM_uint32 *negState,
send_token_flag *return_token)
send_token_flag *return_token,
spnego_gss_ctx_id_t *sc_out)
{
OM_uint32 tmpmin, ret, req_flags;
gss_OID_set supported_mechSet, mechTypes;
Expand Down Expand Up @@ -1345,12 +1344,7 @@ acc_ctx_new(OM_uint32 *minor_status,
ret = GSS_S_BAD_MECH;
goto cleanup;
}
sc = (spnego_gss_ctx_id_t)*ctx;
if (sc != NULL) {
gss_release_buffer(&tmpmin, &sc->DER_mechTypes);
assert(mech_wanted != GSS_C_NO_OID);
} else
sc = create_spnego_ctx(0);
sc = create_spnego_ctx(0);
if (sc == NULL) {
ret = GSS_S_FAILURE;
*return_token = NO_TOKEN_SEND;
Expand All @@ -1368,7 +1362,7 @@ acc_ctx_new(OM_uint32 *minor_status,

*return_token = INIT_TOKEN_SEND;
sc->firstpass = 1;
*ctx = (gss_ctx_id_t)sc;
*sc_out = sc;
ret = GSS_S_COMPLETE;
cleanup:
gss_release_oid_set(&tmpmin, &mechTypes);
Expand All @@ -1382,19 +1376,17 @@ acc_ctx_new(OM_uint32 *minor_status,
static OM_uint32
acc_ctx_cont(OM_uint32 *minstat,
gss_buffer_t buf,
gss_ctx_id_t *ctx,
spnego_gss_ctx_id_t sc,
gss_buffer_t *responseToken,
gss_buffer_t *mechListMIC,
OM_uint32 *negState,
send_token_flag *return_token)
{
OM_uint32 ret, tmpmin;
gss_OID supportedMech;
spnego_gss_ctx_id_t sc;
unsigned int len;
unsigned char *ptr, *bufstart;

sc = (spnego_gss_ctx_id_t)*ctx;
ret = GSS_S_DEFECTIVE_TOKEN;
*negState = REJECT;
*minstat = 0;
Expand Down Expand Up @@ -1630,6 +1622,16 @@ spnego_gss_accept_sec_context(
output_token->length = 0;
output_token->value = NULL;
}
if (src_name != NULL)
*src_name = GSS_C_NO_NAME;
if (mech_type != NULL)
*mech_type = GSS_C_NO_OID;
if (time_rec != NULL)
*time_rec = 0;
if (ret_flags != NULL)
*ret_flags = 0;
if (delegated_cred_handle != NULL)
*delegated_cred_handle = GSS_C_NO_CREDENTIAL;

if (minor_status == NULL ||
output_token == GSS_C_NO_BUFFER ||
Expand All @@ -1642,43 +1644,34 @@ spnego_gss_accept_sec_context(
/* 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)
*mech_type = GSS_C_NO_OID;
if (time_rec != NULL)
*time_rec = 0;
if (ret_flags != NULL)
*ret_flags = 0;
if (delegated_cred_handle != NULL)
*delegated_cred_handle = GSS_C_NO_CREDENTIAL;
if (input_token->length == 0) {
ret = acc_ctx_hints(minor_status,
context_handle, spcred,
&mic_out,
&negState,
&return_token);
if (ret != GSS_S_COMPLETE)
goto cleanup;
sendTokenInit = 1;
ret = GSS_S_CONTINUE_NEEDED;
} else {
/* Can set negState to REQUEST_MIC */
ret = acc_ctx_new(minor_status, input_token,
context_handle, spcred,
&mechtok_in, &mic_in,
&negState, &return_token);
if (ret != GSS_S_COMPLETE)
goto cleanup;
ret = GSS_S_CONTINUE_NEEDED;
if (sc == NULL && input_token->length == 0) {
/* Process a request for NegHints. */
ret = acc_ctx_hints(minor_status, spcred, &mic_out, &negState,
&return_token, &sc);
if (ret != GSS_S_COMPLETE)
goto cleanup;
*context_handle = (gss_ctx_id_t)sc;
sendTokenInit = 1;
ret = GSS_S_CONTINUE_NEEDED;
} else if (sc == NULL || sc->internal_mech == GSS_C_NO_OID) {
if (sc != NULL) {
/* Discard the context from the NegHints request. */
release_spnego_ctx(&sc);
*context_handle = GSS_C_NO_CONTEXT;
}
/* Process an initial token; can set negState to
* REQUEST_MIC. */
ret = acc_ctx_new(minor_status, input_token, spcred,
&mechtok_in, &mic_in, &negState,
&return_token, &sc);
if (ret != GSS_S_COMPLETE)
goto cleanup;
*context_handle = (gss_ctx_id_t)sc;
ret = GSS_S_CONTINUE_NEEDED;
} else {
/* Process a response token. Can set negState to
* ACCEPT_INCOMPLETE. */
ret = acc_ctx_cont(minor_status, input_token,
context_handle, &mechtok_in,
ret = acc_ctx_cont(minor_status, input_token, sc, &mechtok_in,
&mic_in, &negState, &return_token);
if (ret != GSS_S_COMPLETE)
goto cleanup;
Expand All @@ -1687,7 +1680,6 @@ spnego_gss_accept_sec_context(

/* 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
* present in input_token. If neither is present, whether
Expand Down

0 comments on commit 28db863

Please sign in to comment.