summaryrefslogtreecommitdiffstats
path: root/src/lib/gssapi/mechglue
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2009-09-13 02:52:23 +0000
committerGreg Hudson <ghudson@mit.edu>2009-09-13 02:52:23 +0000
commit0e39f8a3ad915eeb0131fb4a87b0fef304101cfd (patch)
tree6c6d7fd4b23f4724156300b5505433b13cfe9fb6 /src/lib/gssapi/mechglue
parentf89b62fe9fd7b0cb10d7e2ff542fb18c1b56d35d (diff)
downloadkrb5-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.in3
-rw-r--r--src/lib/gssapi/mechglue/g_accept_sec_context.c185
-rw-r--r--src/lib/gssapi/mechglue/g_acquire_cred.c70
-rw-r--r--src/lib/gssapi/mechglue/g_acquire_cred_imp_name.c549
-rw-r--r--src/lib/gssapi/mechglue/g_glue.c16
-rw-r--r--src/lib/gssapi/mechglue/g_initialize.c3
-rw-r--r--src/lib/gssapi/mechglue/g_set_context_option.c4
-rw-r--r--src/lib/gssapi/mechglue/mglueP.h31
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 */