diff options
author | Greg Hudson <ghudson@mit.edu> | 2009-09-13 02:52:23 +0000 |
---|---|---|
committer | Greg Hudson <ghudson@mit.edu> | 2009-09-13 02:52:23 +0000 |
commit | 0e39f8a3ad915eeb0131fb4a87b0fef304101cfd (patch) | |
tree | 6c6d7fd4b23f4724156300b5505433b13cfe9fb6 /src/lib/gssapi/mechglue | |
parent | f89b62fe9fd7b0cb10d7e2ff542fb18c1b56d35d (diff) | |
download | krb5-0e39f8a3ad915eeb0131fb4a87b0fef304101cfd.tar.gz krb5-0e39f8a3ad915eeb0131fb4a87b0fef304101cfd.tar.xz krb5-0e39f8a3ad915eeb0131fb4a87b0fef304101cfd.zip |
Implement s4u extensions
Merge Luke's users/lhoward/s4u branch to trunk. Implements S4U2Self
and S4U2Proxy extensions.
ticket: 6563
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@22736 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/lib/gssapi/mechglue')
-rw-r--r-- | src/lib/gssapi/mechglue/Makefile.in | 3 | ||||
-rw-r--r-- | src/lib/gssapi/mechglue/g_accept_sec_context.c | 185 | ||||
-rw-r--r-- | src/lib/gssapi/mechglue/g_acquire_cred.c | 70 | ||||
-rw-r--r-- | src/lib/gssapi/mechglue/g_acquire_cred_imp_name.c | 549 | ||||
-rw-r--r-- | src/lib/gssapi/mechglue/g_glue.c | 16 | ||||
-rw-r--r-- | src/lib/gssapi/mechglue/g_initialize.c | 3 | ||||
-rw-r--r-- | src/lib/gssapi/mechglue/g_set_context_option.c | 4 | ||||
-rw-r--r-- | src/lib/gssapi/mechglue/mglueP.h | 31 |
8 files changed, 707 insertions, 154 deletions
diff --git a/src/lib/gssapi/mechglue/Makefile.in b/src/lib/gssapi/mechglue/Makefile.in index 927b3755ca..18e89f19dc 100644 --- a/src/lib/gssapi/mechglue/Makefile.in +++ b/src/lib/gssapi/mechglue/Makefile.in @@ -14,6 +14,7 @@ DEFS=-D_GSS_STATIC_LINK=1 SRCS = \ $(srcdir)/g_accept_sec_context.c \ $(srcdir)/g_acquire_cred.c \ + $(srcdir)/g_acquire_cred_imp_name.c \ $(srcdir)/g_buffer_set.c \ $(srcdir)/g_canon_name.c \ $(srcdir)/g_compare_name.c \ @@ -58,6 +59,7 @@ SRCS = \ OBJS = \ $(OUTPRE)g_accept_sec_context.$(OBJEXT) \ $(OUTPRE)g_acquire_cred.$(OBJEXT) \ + $(OUTPRE)g_acquire_cred_imp_name.$(OBJEXT) \ $(OUTPRE)g_buffer_set.$(OBJEXT) \ $(OUTPRE)g_canon_name.$(OBJEXT) \ $(OUTPRE)g_compare_name.$(OBJEXT) \ @@ -102,6 +104,7 @@ OBJS = \ STLIBOBJS = \ g_accept_sec_context.o \ g_acquire_cred.o \ + g_acquire_cred_imp_name.o \ g_buffer_set.o \ g_canon_name.o \ g_compare_name.o \ diff --git a/src/lib/gssapi/mechglue/g_accept_sec_context.c b/src/lib/gssapi/mechglue/g_accept_sec_context.c index fa703d34d2..dc43915935 100644 --- a/src/lib/gssapi/mechglue/g_accept_sec_context.c +++ b/src/lib/gssapi/mechglue/g_accept_sec_context.c @@ -121,6 +121,7 @@ gss_cred_id_t * d_cred; gss_name_t tmp_src_name = GSS_C_NO_NAME; gss_OID_desc token_mech_type_desc; gss_OID token_mech_type = &token_mech_type_desc; + gss_OID actual_mech = GSS_C_NO_OID; gss_mechanism mech; status = val_acc_sec_ctx_args(minor_status, @@ -198,8 +199,8 @@ gss_cred_id_t * d_cred; input_cred_handle, input_token_buffer, input_chan_bindings, - &internal_name, - mech_type, + src_name ? &internal_name : NULL, + &actual_mech, output_token, &temp_ret_flags, time_rec, @@ -222,110 +223,120 @@ gss_cred_id_t * d_cred; * then call gss_import_name() to create * the union name struct cast to src_name */ - if (internal_name != NULL) { - temp_status = gssint_convert_name_to_union_name( - &temp_minor_status, mech, - internal_name, &tmp_src_name); - if (temp_status != GSS_S_COMPLETE) { - *minor_status = temp_minor_status; - map_error(minor_status, mech); - if (output_token->length) - (void) gss_release_buffer(&temp_minor_status, - output_token); - if (internal_name != GSS_C_NO_NAME) - mech->gss_release_name( - &temp_minor_status, - &internal_name); - return (temp_status); - } - if (src_name != NULL) { + if (src_name != NULL) { + if (internal_name != GSS_C_NO_NAME) { + /* consumes internal_name regardless of success */ + temp_status = gssint_convert_name_to_union_name( + &temp_minor_status, mech, + internal_name, &tmp_src_name); + if (temp_status != GSS_S_COMPLETE) { + *minor_status = temp_minor_status; + map_error(minor_status, mech); + if (output_token->length) + (void) gss_release_buffer(&temp_minor_status, + output_token); + return (temp_status); + } *src_name = tmp_src_name; - } - } else if (src_name != NULL) { - *src_name = GSS_C_NO_NAME; + } else + *src_name = GSS_C_NO_NAME; } +#define g_OID_prefix_equal(o1, o2) \ + (((o1)->length >= (o2)->length) && \ + (memcmp((o1)->elements, (o2)->elements, (o2)->length) == 0)) + /* Ensure we're returning correct creds format */ if ((temp_ret_flags & GSS_C_DELEG_FLAG) && tmp_d_cred != GSS_C_NO_CREDENTIAL) { - gss_union_cred_t d_u_cred = NULL; - - d_u_cred = malloc(sizeof (gss_union_cred_desc)); - if (d_u_cred == NULL) { - status = GSS_S_FAILURE; - goto error_out; - } - (void) memset(d_u_cred, 0, - sizeof (gss_union_cred_desc)); - - d_u_cred->count = 1; + if (actual_mech != GSS_C_NO_OID && + !g_OID_prefix_equal(actual_mech, token_mech_type)) { + *d_cred = tmp_d_cred; /* unwrapped pseudo-mech */ + } else { + gss_union_cred_t d_u_cred = NULL; - status = generic_gss_copy_oid(&temp_minor_status, - token_mech_type, - &d_u_cred->mechs_array); + d_u_cred = malloc(sizeof (gss_union_cred_desc)); + if (d_u_cred == NULL) { + status = GSS_S_FAILURE; + goto error_out; + } + (void) memset(d_u_cred, 0, sizeof (gss_union_cred_desc)); - if (status != GSS_S_COMPLETE) { - free(d_u_cred); - goto error_out; - } + d_u_cred->count = 1; - d_u_cred->cred_array = malloc(sizeof (gss_cred_id_t)); - if (d_u_cred->cred_array != NULL) { - d_u_cred->cred_array[0] = tmp_d_cred; - } else { - free(d_u_cred); - status = GSS_S_FAILURE; - goto error_out; - } + status = generic_gss_copy_oid(&temp_minor_status, + token_mech_type, + &d_u_cred->mechs_array); - internal_name = GSS_C_NO_NAME; + if (status != GSS_S_COMPLETE) { + free(d_u_cred); + goto error_out; + } - d_u_cred->auxinfo.creation_time = time(0); - d_u_cred->auxinfo.time_rec = 0; - d_u_cred->loopback = d_u_cred; + d_u_cred->cred_array = malloc(sizeof(gss_cred_id_t)); + if (d_u_cred->cred_array != NULL) { + d_u_cred->cred_array[0] = tmp_d_cred; + } else { + free(d_u_cred); + status = GSS_S_FAILURE; + goto error_out; + } - if (mech->gss_inquire_cred) { - status = mech->gss_inquire_cred(minor_status, - tmp_d_cred, - &internal_name, - &d_u_cred->auxinfo.time_rec, - &d_u_cred->auxinfo.cred_usage, - NULL); - if (status != GSS_S_COMPLETE) - map_error(minor_status, mech); - } + d_u_cred->auxinfo.creation_time = time(0); + d_u_cred->auxinfo.time_rec = 0; + d_u_cred->loopback = d_u_cred; + + internal_name = GSS_C_NO_NAME; + + if (mech->gss_inquire_cred) { + status = mech->gss_inquire_cred(minor_status, + tmp_d_cred, + &internal_name, + &d_u_cred->auxinfo.time_rec, + &d_u_cred->auxinfo.cred_usage, + NULL); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } - if (internal_name != NULL) { - temp_status = gssint_convert_name_to_union_name( - &temp_minor_status, mech, - internal_name, &tmp_src_name); - if (temp_status != GSS_S_COMPLETE) { - *minor_status = temp_minor_status; - map_error(minor_status, mech); - if (output_token->length) - (void) gss_release_buffer( + if (internal_name != GSS_C_NO_NAME) { + /* consumes internal_name regardless of success */ + temp_status = gssint_convert_name_to_union_name( + &temp_minor_status, mech, + internal_name, &tmp_src_name); + if (temp_status != GSS_S_COMPLETE) { + *minor_status = temp_minor_status; + map_error(minor_status, mech); + if (output_token->length) + (void) gss_release_buffer( + &temp_minor_status, + output_token); + (void) gss_release_oid(&temp_minor_status, + &actual_mech); + free(d_u_cred->cred_array); + free(d_u_cred); + return (temp_status); + } + + if (tmp_src_name != GSS_C_NO_NAME) { + status = gss_display_name( &temp_minor_status, - output_token); - free(d_u_cred->cred_array); - free(d_u_cred); - return (temp_status); + tmp_src_name, + &d_u_cred->auxinfo.name, + &d_u_cred->auxinfo.name_type); + (void) gss_release_name(&temp_minor_status, + &tmp_src_name); + } } - } - if (tmp_src_name != NULL) { - status = gss_display_name( - &temp_minor_status, - tmp_src_name, - &d_u_cred->auxinfo.name, - &d_u_cred->auxinfo.name_type); + *d_cred = (gss_cred_id_t)d_u_cred; } - - *d_cred = (gss_cred_id_t)d_u_cred; } - if (src_name == NULL && tmp_src_name != NULL) - (void) gss_release_name(&temp_minor_status, - &tmp_src_name); + if (mech_type != NULL) + *mech_type = actual_mech; + else + (void) gss_release_oid(&temp_minor_status, &actual_mech); if (ret_flags != NULL) *ret_flags = temp_ret_flags; return (status); diff --git a/src/lib/gssapi/mechglue/g_acquire_cred.c b/src/lib/gssapi/mechglue/g_acquire_cred.c index fada9e8872..6dfc65f7b2 100644 --- a/src/lib/gssapi/mechglue/g_acquire_cred.c +++ b/src/lib/gssapi/mechglue/g_acquire_cred.c @@ -2,7 +2,7 @@ /* * Copyright 1996 by Sun Microsystems, Inc. - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appears in all copies and @@ -12,7 +12,7 @@ * without specific, written prior permission. Sun Microsystems makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. - * + * * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR @@ -35,42 +35,6 @@ #include <errno.h> #include <time.h> -static gss_OID_set -create_actual_mechs(mechs_array, count) - const gss_OID mechs_array; - int count; -{ - gss_OID_set actual_mechs; - int i; - OM_uint32 minor; - - actual_mechs = (gss_OID_set) malloc(sizeof(gss_OID_set_desc)); - if (!actual_mechs) - return NULL; - - actual_mechs->elements = (gss_OID) - malloc(sizeof (gss_OID_desc) * count); - if (!actual_mechs->elements) { - free(actual_mechs); - return NULL; - } - - actual_mechs->count = 0; - - for (i = 0; i < count; i++) { - actual_mechs->elements[i].elements = (void *) - malloc(mechs_array[i].length); - if (actual_mechs->elements[i].elements == NULL) { - (void) gss_release_oid_set(&minor, &actual_mechs); - return (NULL); - } - g_OID_copy(&actual_mechs->elements[i], &mechs_array[i]); - actual_mechs->count++; - } - - return actual_mechs; -} - static OM_uint32 val_acq_cred_args( OM_uint32 *minor_status, @@ -172,7 +136,7 @@ OM_uint32 * time_rec; 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; @@ -234,12 +198,16 @@ OM_uint32 * time_rec; * setup the actual mechs output parameter */ if (actual_mechs != NULL) { - if ((*actual_mechs = create_actual_mechs(creds->mechs_array, - creds->count)) == NULL) { + gss_OID_set_desc oids; + + oids.count = creds->count; + 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); - *minor_status = 0; - return (GSS_S_FAILURE); + return (major); } } @@ -312,7 +280,7 @@ OM_uint32 KRB5_CALLCONV gss_add_cred(minor_status, input_cred_handle, desired_name, desired_mech, cred_usage, initiator_time_req, acceptor_time_req, - output_cred_handle, actual_mechs, + output_cred_handle, actual_mechs, initiator_time_rec, acceptor_time_rec) OM_uint32 *minor_status; gss_cred_id_t input_cred_handle; @@ -434,7 +402,7 @@ gss_add_cred(minor_status, input_cred_handle, status = mech->gss_display_name(&temp_minor_status, internal_name, &union_cred->auxinfo.name, &union_cred->auxinfo.name_type); - + if (status != GSS_S_COMPLETE) goto errout; } @@ -475,10 +443,14 @@ gss_add_cred(minor_status, input_cred_handle, g_OID_copy(&new_mechs_array[union_cred->count], &mech->mech_type); - if (actual_mechs) { - *actual_mechs = create_actual_mechs(new_mechs_array, - union_cred->count + 1); - if (*actual_mechs == NULL) { + if (actual_mechs != NULL) { + gss_OID_set_desc oids; + + oids.count = union_cred->count + 1; + oids.elements = new_mechs_array; + + status = generic_gss_copy_oid_set(minor_status, &oids, actual_mechs); + if (GSS_ERROR(status)) { free(new_mechs_array[union_cred->count].elements); goto errout; } diff --git a/src/lib/gssapi/mechglue/g_acquire_cred_imp_name.c b/src/lib/gssapi/mechglue/g_acquire_cred_imp_name.c new file mode 100644 index 0000000000..9ba6a1faa7 --- /dev/null +++ b/src/lib/gssapi/mechglue/g_acquire_cred_imp_name.c @@ -0,0 +1,549 @@ +/* #pragma ident "@(#)g_acquire_cred.c 1.22 04/02/23 SMI" */ + +/* + * Copyright 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine for gss_acquire_cred_impersonate_name + */ + +#include "mglueP.h" +#include <stdio.h> +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#include <string.h> +#include <errno.h> +#include <time.h> + +static OM_uint32 +val_acq_cred_impersonate_name_args( + OM_uint32 *minor_status, + const gss_cred_id_t impersonator_cred_handle, + const gss_name_t desired_name, + OM_uint32 time_req, + gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec) +{ + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 0; + + if (output_cred_handle != NULL) + *output_cred_handle = GSS_C_NO_CREDENTIAL; + + if (actual_mechs != NULL) + *actual_mechs = GSS_C_NULL_OID_SET; + + if (time_rec != NULL) + *time_rec = 0; + + /* Validate arguments. */ + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (impersonator_cred_handle == GSS_C_NO_CREDENTIAL) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CRED); + + if (desired_name == GSS_C_NO_NAME) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME); + + if (output_cred_handle == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (cred_usage != GSS_C_ACCEPT + && cred_usage != GSS_C_INITIATE + && cred_usage != GSS_C_BOTH) { + if (minor_status) { + *minor_status = EINVAL; + map_errcode(minor_status); + } + return GSS_S_FAILURE; + } + + return (GSS_S_COMPLETE); +} + + +OM_uint32 KRB5_CALLCONV +gss_acquire_cred_impersonate_name(OM_uint32 *minor_status, + const gss_cred_id_t impersonator_cred_handle, + const gss_name_t desired_name, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec) +{ + OM_uint32 major = GSS_S_FAILURE; + 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; + unsigned int i; + gss_union_cred_t creds; + + major = val_acq_cred_impersonate_name_args(minor_status, + impersonator_cred_handle, + desired_name, + time_req, + desired_mechs, + cred_usage, + output_cred_handle, + actual_mechs, + time_rec); + if (major != GSS_S_COMPLETE) + return (major); + + /* Initial value needed below. */ + major = GSS_S_FAILURE; + + /* + * 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 == 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; + } else + mechs = desired_mechs; + + if (mechs->count == 0) + return (GSS_S_BAD_MECH); + + /* allocate the output credential structure */ + creds = (gss_union_cred_t)malloc(sizeof (gss_union_cred_desc)); + if (creds == NULL) + return (GSS_S_FAILURE); + + /* initialize to 0s */ + (void) memset(creds, 0, sizeof (gss_union_cred_desc)); + creds->loopback = creds; + + /* for each requested mech attempt to obtain a credential */ + for (i = 0; i < mechs->count; i++) { + major = gss_add_cred_impersonate_name(minor_status, + (gss_cred_id_t)creds, + impersonator_cred_handle, + desired_name, + &mechs->elements[i], + cred_usage, + time_req, + time_req, NULL, + NULL, + &initTimeOut, + &acceptTimeOut); + if (major == GSS_S_COMPLETE) { + /* update the credential's time */ + if (cred_usage == GSS_C_ACCEPT) { + if (outTime > acceptTimeOut) + outTime = acceptTimeOut; + } else if (cred_usage == GSS_C_INITIATE) { + if (outTime > initTimeOut) + outTime = initTimeOut; + } else { + /* + * time_rec is the lesser of the + * init/accept times + */ + if (initTimeOut > acceptTimeOut) + outTime = (outTime > acceptTimeOut) ? + acceptTimeOut : outTime; + else + outTime = (outTime > initTimeOut) ? + initTimeOut : outTime; + } + } + } /* for */ + + /* ensure that we have at least one credential element */ + if (creds->count < 1) { + free(creds); + return (major); + } + + /* + * fill in output parameters + * setup the actual mechs output parameter + */ + if (actual_mechs != NULL) { + gss_OID_set_desc oids; + + oids.count = creds->count; + 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 (time_rec) + *time_rec = outTime; + + + creds->loopback = creds; + *output_cred_handle = (gss_cred_id_t)creds; + return (GSS_S_COMPLETE); +} + +static OM_uint32 +val_add_cred_impersonate_name_args( + OM_uint32 *minor_status, + gss_cred_id_t input_cred_handle, + const gss_cred_id_t impersonator_cred_handle, + gss_name_t desired_name, + gss_OID desired_mech, + gss_cred_usage_t cred_usage, + OM_uint32 initiator_time_req, + OM_uint32 acceptor_time_req, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *initiator_time_rec, + OM_uint32 *acceptor_time_rec) +{ + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 0; + + if (output_cred_handle != NULL) + *output_cred_handle = GSS_C_NO_CREDENTIAL; + + if (actual_mechs != NULL) + *actual_mechs = GSS_C_NO_OID_SET; + + if (acceptor_time_rec != NULL) + *acceptor_time_rec = 0; + + if (initiator_time_rec != NULL) + *initiator_time_rec = 0; + + /* Validate arguments. */ + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (impersonator_cred_handle == GSS_C_NO_CREDENTIAL) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CRED); + + if (desired_name == GSS_C_NO_NAME) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME); + + if (input_cred_handle == GSS_C_NO_CREDENTIAL && + output_cred_handle == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CRED); + + if (cred_usage != GSS_C_ACCEPT + && cred_usage != GSS_C_INITIATE + && cred_usage != GSS_C_BOTH) { + if (minor_status) { + *minor_status = EINVAL; + map_errcode(minor_status); + } + return GSS_S_FAILURE; + } + + return (GSS_S_COMPLETE); +} + + +/* V2 KRB5_CALLCONV */ +OM_uint32 KRB5_CALLCONV +gss_add_cred_impersonate_name(OM_uint32 *minor_status, + gss_cred_id_t input_cred_handle, + const gss_cred_id_t impersonator_cred_handle, + const gss_name_t desired_name, + const gss_OID desired_mech, + gss_cred_usage_t cred_usage, + OM_uint32 initiator_time_req, + OM_uint32 acceptor_time_req, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *initiator_time_rec, + OM_uint32 *acceptor_time_rec) +{ + OM_uint32 status, temp_minor_status; + OM_uint32 time_req, time_rec; + gss_union_name_t union_name; + gss_union_cred_t new_union_cred, union_cred; + gss_cred_id_t mech_impersonator_cred; + gss_name_t internal_name = GSS_C_NO_NAME; + gss_name_t allocated_name = GSS_C_NO_NAME; + gss_mechanism mech; + gss_cred_id_t cred = NULL; + gss_OID new_mechs_array = NULL; + gss_cred_id_t * new_cred_array = NULL; + + status = val_add_cred_impersonate_name_args(minor_status, + input_cred_handle, + impersonator_cred_handle, + desired_name, + desired_mech, + cred_usage, + initiator_time_req, + acceptor_time_req, + output_cred_handle, + actual_mechs, + initiator_time_rec, + acceptor_time_rec); + if (status != GSS_S_COMPLETE) + return (status); + + mech = gssint_get_mechanism(desired_mech); + if (!mech) + return GSS_S_BAD_MECH; + else if (!mech->gss_acquire_cred) + return (GSS_S_UNAVAILABLE); + + if (input_cred_handle == GSS_C_NO_CREDENTIAL) { + union_cred = malloc(sizeof (gss_union_cred_desc)); + if (union_cred == NULL) + return (GSS_S_FAILURE); + + (void) memset(union_cred, 0, sizeof (gss_union_cred_desc)); + + /* for default credentials we will use GSS_C_NO_NAME */ + internal_name = GSS_C_NO_NAME; + } else { + union_cred = (gss_union_cred_t)input_cred_handle; + if (gssint_get_mechanism_cred(union_cred, desired_mech) != + GSS_C_NO_CREDENTIAL) + return (GSS_S_DUPLICATE_ELEMENT); + } + + mech_impersonator_cred = + gssint_get_mechanism_cred((gss_union_cred_t)impersonator_cred_handle, + desired_mech); + if (mech_impersonator_cred == GSS_C_NO_CREDENTIAL) + return (GSS_S_NO_CRED); + + /* may need to create a mechanism specific name */ + union_name = (gss_union_name_t)desired_name; + if (union_name->mech_type && + g_OID_equal(union_name->mech_type, + &mech->mech_type)) + internal_name = union_name->mech_name; + else { + if (gssint_import_internal_name(minor_status, + &mech->mech_type, union_name, + &allocated_name) != GSS_S_COMPLETE) + return (GSS_S_BAD_NAME); + internal_name = allocated_name; + } + + if (cred_usage == GSS_C_ACCEPT) + time_req = acceptor_time_req; + else if (cred_usage == GSS_C_INITIATE) + time_req = initiator_time_req; + else if (cred_usage == GSS_C_BOTH) + time_req = (acceptor_time_req > initiator_time_req) ? + acceptor_time_req : initiator_time_req; + else + time_req = 0; + + status = mech->gss_acquire_cred_impersonate_name(minor_status, + mech_impersonator_cred, + internal_name, + time_req, + GSS_C_NULL_OID_SET, + cred_usage, + &cred, + NULL, + &time_rec); + if (status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + goto errout; + } + + /* may need to set credential auxinfo strucutre */ + if (union_cred->auxinfo.creation_time == 0) { + union_cred->auxinfo.creation_time = time(NULL); + union_cred->auxinfo.time_rec = time_rec; + union_cred->auxinfo.cred_usage = cred_usage; + + /* + * we must set the name; if name is not supplied + * we must do inquire cred to get it + */ + if (internal_name == NULL) { + if (mech->gss_inquire_cred == NULL || + ((status = mech->gss_inquire_cred( + &temp_minor_status, cred, + &allocated_name, NULL, NULL, + NULL)) != GSS_S_COMPLETE)) + goto errout; + internal_name = allocated_name; + } + + if (internal_name != GSS_C_NO_NAME) { + status = mech->gss_display_name(&temp_minor_status, internal_name, + &union_cred->auxinfo.name, + &union_cred->auxinfo.name_type); + + if (status != GSS_S_COMPLETE) + goto errout; + } + } + + /* now add the new credential elements */ + new_mechs_array = (gss_OID) + malloc(sizeof (gss_OID_desc) * (union_cred->count+1)); + + new_cred_array = (gss_cred_id_t *) + malloc(sizeof (gss_cred_id_t) * (union_cred->count+1)); + + if (!new_mechs_array || !new_cred_array) { + status = GSS_S_FAILURE; + goto errout; + } + + if (acceptor_time_rec) + if (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH) + *acceptor_time_rec = time_rec; + if (initiator_time_rec) + if (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH) + *initiator_time_rec = time_rec; + + /* + * OK, expand the mechanism array and the credential array + */ + (void) memcpy(new_mechs_array, union_cred->mechs_array, + sizeof (gss_OID_desc) * union_cred->count); + (void) memcpy(new_cred_array, union_cred->cred_array, + sizeof (gss_cred_id_t) * union_cred->count); + + new_cred_array[union_cred->count] = cred; + if ((new_mechs_array[union_cred->count].elements = + malloc(mech->mech_type.length)) == NULL) + goto errout; + + g_OID_copy(&new_mechs_array[union_cred->count], + &mech->mech_type); + + if (actual_mechs != NULL) { + gss_OID_set_desc oids; + + oids.count = union_cred->count + 1; + oids.elements = new_mechs_array; + + status = generic_gss_copy_oid_set(minor_status, &oids, actual_mechs); + if (GSS_ERROR(status)) { + free(new_mechs_array[union_cred->count].elements); + goto errout; + } + } + + if (output_cred_handle == NULL) { + free(union_cred->mechs_array); + free(union_cred->cred_array); + new_union_cred = union_cred; + } else { + new_union_cred = malloc(sizeof (gss_union_cred_desc)); + if (new_union_cred == NULL) { + free(new_mechs_array[union_cred->count].elements); + goto errout; + } + *new_union_cred = *union_cred; + *output_cred_handle = (gss_cred_id_t)new_union_cred; + } + + new_union_cred->mechs_array = new_mechs_array; + new_union_cred->cred_array = new_cred_array; + new_union_cred->count++; + new_union_cred->loopback = new_union_cred; + + /* We're done with the internal name. Free it if we allocated it. */ + + if (allocated_name) + (void) gssint_release_internal_name(&temp_minor_status, + &mech->mech_type, + &allocated_name); + + return (GSS_S_COMPLETE); + +errout: + if (new_mechs_array) + free(new_mechs_array); + if (new_cred_array) + free(new_cred_array); + + if (cred != NULL && mech->gss_release_cred) + mech->gss_release_cred(&temp_minor_status, &cred); + + if (allocated_name) + (void) gssint_release_internal_name(&temp_minor_status, + &mech->mech_type, + &allocated_name); + + if (input_cred_handle == GSS_C_NO_CREDENTIAL && union_cred) { + if (union_cred->auxinfo.name.value) + free(union_cred->auxinfo.name.value); + free(union_cred); + } + + return (status); +} diff --git a/src/lib/gssapi/mechglue/g_glue.c b/src/lib/gssapi/mechglue/g_glue.c index 5a8ea54b1e..4d35819c58 100644 --- a/src/lib/gssapi/mechglue/g_glue.c +++ b/src/lib/gssapi/mechglue/g_glue.c @@ -611,25 +611,9 @@ gssint_get_mechanism_cred(union_cred, mech_type) if (union_cred == GSS_C_NO_CREDENTIAL) return GSS_C_NO_CREDENTIAL; - /* SPNEGO mechanism will again call into GSSAPI */ - if (g_OID_equal(&gss_spnego_mechanism_oid_desc, mech_type)) - return (gss_cred_id_t)union_cred; - for (i=0; i < union_cred->count; i++) { if (g_OID_equal(mech_type, &union_cred->mechs_array[i])) return union_cred->cred_array[i]; - - /* for SPNEGO, check the next-lower set of creds */ - if (g_OID_equal(&gss_spnego_mechanism_oid_desc, &union_cred->mechs_array[i])) { - gss_union_cred_t candidate_cred; - gss_cred_id_t sub_cred; - - candidate_cred = (gss_union_cred_t)union_cred->cred_array[i]; - sub_cred = gssint_get_mechanism_cred(candidate_cred, mech_type); - - if(sub_cred != GSS_C_NO_CREDENTIAL) - return sub_cred; - } } return GSS_C_NO_CREDENTIAL; } diff --git a/src/lib/gssapi/mechglue/g_initialize.c b/src/lib/gssapi/mechglue/g_initialize.c index 85fbe63219..e34b7bf0a7 100644 --- a/src/lib/gssapi/mechglue/g_initialize.c +++ b/src/lib/gssapi/mechglue/g_initialize.c @@ -761,6 +761,9 @@ build_dynamicMech(void *dl, const gss_OID mech_type) GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_unwrap_iov); GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_wrap_iov_length); GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_complete_auth_token); + /* New for 1.8 */ + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_acquire_cred_impersonate_name); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_add_cred_impersonate_name); assert(mech_type != GSS_C_NO_OID); diff --git a/src/lib/gssapi/mechglue/g_set_context_option.c b/src/lib/gssapi/mechglue/g_set_context_option.c index 17d9e3bace..b35b36ad54 100644 --- a/src/lib/gssapi/mechglue/g_set_context_option.c +++ b/src/lib/gssapi/mechglue/g_set_context_option.c @@ -70,8 +70,8 @@ gss_set_sec_context_option (OM_uint32 *minor_status, } status = mech->gss_set_sec_context_option(minor_status, - ctx ? &internal_ctx : - &ctx->internal_ctx_id, + ctx ? &ctx->internal_ctx_id : + &internal_ctx, desired_object, value); if (status == GSS_S_COMPLETE) { diff --git a/src/lib/gssapi/mechglue/mglueP.h b/src/lib/gssapi/mechglue/mglueP.h index 001636146e..46bfb94636 100644 --- a/src/lib/gssapi/mechglue/mglueP.h +++ b/src/lib/gssapi/mechglue/mglueP.h @@ -473,6 +473,37 @@ typedef struct gss_config { gss_buffer_t /* input_message_buffer */ ); + /* New for 1.8 */ + + OM_uint32 (*gss_acquire_cred_impersonate_name) + ( + OM_uint32 *, /* minor_status */ + const gss_cred_id_t, /* impersonator_cred_handle */ + const gss_name_t, /* desired_name */ + OM_uint32, /* time_req */ + const gss_OID_set, /* desired_mechs */ + gss_cred_usage_t, /* cred_usage */ + gss_cred_id_t *, /* output_cred_handle */ + gss_OID_set *, /* actual_mechs */ + OM_uint32 * /* time_rec */ + /* */); + + OM_uint32 (*gss_add_cred_impersonate_name) + ( + OM_uint32 *, /* minor_status */ + gss_cred_id_t, /* input_cred_handle */ + const gss_cred_id_t, /* impersonator_cred_handle */ + const gss_name_t, /* desired_name */ + const gss_OID, /* desired_mech */ + gss_cred_usage_t, /* cred_usage */ + OM_uint32, /* initiator_time_req */ + OM_uint32, /* acceptor_time_req */ + gss_cred_id_t *, /* output_cred_handle */ + gss_OID_set *, /* actual_mechs */ + OM_uint32 *, /* initiator_time_rec */ + OM_uint32 * /* acceptor_time_rec */ + /* */); + } *gss_mechanism; /* This structure MUST NOT be used by any code outside libgss */ |