From 79c34ed3d829ee9e3fa64aa5b3b90b4e37514cf7 Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Mon, 4 Apr 2011 23:06:09 +0000 Subject: [PATCH] More sensical mech selection for gss_acquire_cred/accept_sec_context If a caller passes an empty mech set to gss_acquire_cred, get a cred for all mechs instead of just the krb5 mech, as we don't know what mechanism the cred is going to be used with (particularly in the acceptor case). As a related fix, if a caller passes a credential to gss_accept_sec_context and it does not contain a mech-specific cred for the token's mech, error out instead of using the default cred with the token's mechanism. ticket: 6894 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@24840 dc483132-0cff-0310-8789-dd5450dbe970 --- .../gssapi/mechglue/g_accept_sec_context.c | 15 ++-- src/lib/gssapi/mechglue/g_acquire_cred.c | 78 ++++++++----------- 2 files changed, 44 insertions(+), 49 deletions(-) diff --git a/src/lib/gssapi/mechglue/g_accept_sec_context.c b/src/lib/gssapi/mechglue/g_accept_sec_context.c index 8714f3fb7..8e0b7c5a0 100644 --- a/src/lib/gssapi/mechglue/g_accept_sec_context.c +++ b/src/lib/gssapi/mechglue/g_accept_sec_context.c @@ -115,7 +115,6 @@ gss_cred_id_t * d_cred; OM_uint32 status, temp_status, temp_minor_status; OM_uint32 temp_ret_flags = 0; gss_union_ctx_id_t union_ctx_id; - gss_union_cred_t union_cred; gss_cred_id_t input_cred_handle = GSS_C_NO_CREDENTIAL; gss_cred_id_t tmp_d_cred = GSS_C_NO_CREDENTIAL; gss_name_t internal_name = GSS_C_NO_NAME; @@ -181,11 +180,17 @@ gss_cred_id_t * d_cred; /* * get the appropriate cred handle from the union cred struct. - * defaults to GSS_C_NO_CREDENTIAL if there is no cred, which will - * use the default credential. */ - union_cred = (gss_union_cred_t) verifier_cred_handle; - input_cred_handle = gssint_get_mechanism_cred(union_cred, token_mech_type); + if (verifier_cred_handle != GSS_C_NO_CREDENTIAL) { + input_cred_handle = + gssint_get_mechanism_cred((gss_union_cred_t)verifier_cred_handle, + token_mech_type); + if (input_cred_handle == GSS_C_NO_CREDENTIAL) { + /* verifier credential specified but no acceptor credential found */ + status = GSS_S_NO_CRED; + goto error_out; + } + } /* * now select the approprate underlying mechanism routine and diff --git a/src/lib/gssapi/mechglue/g_acquire_cred.c b/src/lib/gssapi/mechglue/g_acquire_cred.c index 6dfc65f7b..71bbf9e21 100644 --- a/src/lib/gssapi/mechglue/g_acquire_cred.c +++ b/src/lib/gssapi/mechglue/g_acquire_cred.c @@ -103,14 +103,11 @@ gss_OID_set * actual_mechs; OM_uint32 * time_rec; { - OM_uint32 major = GSS_S_FAILURE; + OM_uint32 major = GSS_S_FAILURE, tmpMinor; OM_uint32 initTimeOut, acceptTimeOut, outTime = GSS_C_INDEFINITE; - gss_OID_set_desc default_OID_set; - gss_OID_set mechs; - gss_OID_desc default_OID; - gss_mechanism mech; + gss_OID_set mechs = GSS_C_NO_OID_SET; unsigned int i; - gss_union_cred_t creds; + gss_union_cred_t creds = NULL; major = val_acq_cred_args(minor_status, desired_name, @@ -121,44 +118,37 @@ OM_uint32 * time_rec; actual_mechs, time_rec); if (major != GSS_S_COMPLETE) - return (major); - - /* Initial value needed below. */ - major = GSS_S_FAILURE; + goto cleanup; /* - * if desired_mechs equals GSS_C_NULL_OID_SET, then pick an - * appropriate default. We use the first mechanism in the - * mechansim list as the default. This set is created with - * statics thus needs not be freed + * if desired_mechs equals GSS_C_NULL_OID_SET, then try to + * acquire credentials for all mechanisms. */ - if(desired_mechs == GSS_C_NULL_OID_SET) { - mech = gssint_get_mechanism(NULL); - if (mech == NULL) - return (GSS_S_BAD_MECH); - - mechs = &default_OID_set; - default_OID_set.count = 1; - default_OID_set.elements = &default_OID; - default_OID.length = mech->mech_type.length; - default_OID.elements = mech->mech_type.elements; + if (desired_mechs == GSS_C_NULL_OID_SET) { + major = gss_indicate_mechs(minor_status, &mechs); + if (major != GSS_S_COMPLETE) + goto cleanup; } else mechs = desired_mechs; - if (mechs->count == 0) - return (GSS_S_BAD_MECH); + if (mechs->count == 0) { + major = GSS_S_BAD_MECH; + goto cleanup; + } /* allocate the output credential structure */ - creds = (gss_union_cred_t)malloc(sizeof (gss_union_cred_desc)); - if (creds == NULL) - return (GSS_S_FAILURE); + creds = (gss_union_cred_t)calloc(1, sizeof (gss_union_cred_desc)); + if (creds == NULL) { + major = GSS_S_FAILURE; + *minor_status = ENOMEM; + goto cleanup; + } - /* initialize to 0s */ - (void) memset(creds, 0, sizeof (gss_union_cred_desc)); + creds->count = 0; creds->loopback = creds; /* for each requested mech attempt to obtain a credential */ - for (i = 0; i < mechs->count; i++) { + for (i = 0, major = GSS_S_UNAVAILABLE; i < mechs->count; i++) { major = gss_add_cred(minor_status, (gss_cred_id_t)creds, desired_name, &mechs->elements[i], @@ -188,10 +178,8 @@ OM_uint32 * time_rec; } /* for */ /* ensure that we have at least one credential element */ - if (creds->count < 1) { - free(creds); - return (major); - } + if (creds->count < 1) + goto cleanup; /* * fill in output parameters @@ -204,20 +192,22 @@ OM_uint32 * time_rec; oids.elements = creds->mechs_array; major = generic_gss_copy_oid_set(minor_status, &oids, actual_mechs); - if (GSS_ERROR(major)) { - (void) gss_release_cred(minor_status, - (gss_cred_id_t *)&creds); - return (major); - } + if (GSS_ERROR(major)) + goto cleanup; } if (time_rec) *time_rec = outTime; - - creds->loopback = creds; *output_cred_handle = (gss_cred_id_t)creds; - return (GSS_S_COMPLETE); + +cleanup: + if (GSS_ERROR(major)) + gss_release_cred(&tmpMinor, (gss_cred_id_t *)&creds); + if (desired_mechs == GSS_C_NO_OID_SET) + generic_gss_release_oid_set(&tmpMinor, &mechs); + + return (major); } static OM_uint32 -- 2.26.2