krb5 commit: Improve type safety of SPNEGO helper functions
Greg Hudson
ghudson at mit.edu
Mon Jan 11 11:51:41 EST 2016
https://github.com/krb5/krb5/commit/28db863bd8a0a6e76be65acdd7c35afd3503827c
commit 28db863bd8a0a6e76be65acdd7c35afd3503827c
Author: Greg Hudson <ghudson at mit.edu>
Date: Wed Jan 6 11:31:07 2016 -0500
Improve type safety of SPNEGO helper functions
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.
src/lib/gssapi/spnego/spnego_mech.c | 162 +++++++++++++++++------------------
1 files changed, 77 insertions(+), 85 deletions(-)
diff --git a/src/lib/gssapi/spnego/spnego_mech.c b/src/lib/gssapi/spnego/spnego_mech.c
index c7de261..110b886 100644
--- a/src/lib/gssapi/spnego/spnego_mech.c
+++ b/src/lib/gssapi/spnego/spnego_mech.c
@@ -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
@@ -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 *);
@@ -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:
@@ -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;
@@ -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;
@@ -666,16 +666,15 @@ cleanup:
* 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;
@@ -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)) {
@@ -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,
@@ -1233,17 +1232,19 @@ errout:
}
/*
- * 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;
@@ -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);
@@ -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;
@@ -1294,19 +1292,20 @@ cleanup:
}
/*
- * 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;
@@ -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;
@@ -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);
@@ -1382,7 +1376,7 @@ cleanup:
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,
@@ -1390,11 +1384,9 @@ acc_ctx_cont(OM_uint32 *minstat,
{
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;
@@ -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 ||
@@ -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;
@@ -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
More information about the cvs-krb5
mailing list