summaryrefslogtreecommitdiffstats
path: root/src/lib/gssapi/krb5
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/gssapi/krb5')
-rw-r--r--src/lib/gssapi/krb5/Makefile.in3
-rw-r--r--src/lib/gssapi/krb5/accept_sec_context.c57
-rw-r--r--src/lib/gssapi/krb5/acquire_cred.c87
-rw-r--r--src/lib/gssapi/krb5/add_cred.c39
-rw-r--r--src/lib/gssapi/krb5/compare_name.c5
-rw-r--r--src/lib/gssapi/krb5/delete_sec_context.c4
-rw-r--r--src/lib/gssapi/krb5/disp_name.c3
-rw-r--r--src/lib/gssapi/krb5/duplicate_name.c15
-rw-r--r--src/lib/gssapi/krb5/export_name.c2
-rw-r--r--src/lib/gssapi/krb5/gssapiP_krb5.h93
-rw-r--r--src/lib/gssapi/krb5/gssapi_krb5.c8
-rw-r--r--src/lib/gssapi/krb5/import_name.c106
-rw-r--r--src/lib/gssapi/krb5/init_sec_context.c61
-rw-r--r--src/lib/gssapi/krb5/inq_context.c34
-rw-r--r--src/lib/gssapi/krb5/inq_cred.c20
-rw-r--r--src/lib/gssapi/krb5/naming_exts.c722
-rw-r--r--src/lib/gssapi/krb5/rel_cred.c4
-rw-r--r--src/lib/gssapi/krb5/rel_name.c5
-rw-r--r--src/lib/gssapi/krb5/s4u_gss_glue.c46
-rw-r--r--src/lib/gssapi/krb5/ser_sctx.c91
-rw-r--r--src/lib/gssapi/krb5/val_cred.c2
21 files changed, 1190 insertions, 217 deletions
diff --git a/src/lib/gssapi/krb5/Makefile.in b/src/lib/gssapi/krb5/Makefile.in
index 645b91b11..b84efa176 100644
--- a/src/lib/gssapi/krb5/Makefile.in
+++ b/src/lib/gssapi/krb5/Makefile.in
@@ -69,6 +69,7 @@ SRCS = \
$(srcdir)/k5unsealiov.c \
$(srcdir)/krb5_gss_glue.c \
$(srcdir)/lucid_context.c \
+ $(srcdir)/naming_exts.c \
$(srcdir)/process_context_token.c \
$(srcdir)/rel_cred.c \
$(srcdir)/rel_oid.c \
@@ -120,6 +121,7 @@ OBJS = \
$(OUTPRE)k5unsealiov.$(OBJEXT) \
$(OUTPRE)krb5_gss_glue.$(OBJEXT) \
$(OUTPRE)lucid_context.$(OBJEXT) \
+ $(OUTPRE)naming_exts.$(OBJEXT) \
$(OUTPRE)process_context_token.$(OBJEXT) \
$(OUTPRE)rel_cred.$(OBJEXT) \
$(OUTPRE)rel_oid.$(OBJEXT) \
@@ -174,6 +176,7 @@ STLIBOBJS = \
k5unsealiov.o \
krb5_gss_glue.o \
lucid_context.o \
+ naming_exts.o \
process_context_token.o \
rel_cred.o \
rel_oid.o \
diff --git a/src/lib/gssapi/krb5/accept_sec_context.c b/src/lib/gssapi/krb5/accept_sec_context.c
index d340db7e7..934302cff 100644
--- a/src/lib/gssapi/krb5/accept_sec_context.c
+++ b/src/lib/gssapi/krb5/accept_sec_context.c
@@ -243,7 +243,7 @@ rd_and_store_for_creds(context, auth_context, inbuf, out_cred)
/* copy the client principle into it... */
if ((retval =
- krb5_copy_principal(context, creds[0]->client, &(cred->princ)))) {
+ kg_init_name(context, creds[0]->client, NULL, 0, &cred->name))) {
k5_mutex_destroy(&cred->lock);
retval = ENOMEM; /* out of memory? */
xfree(cred); /* clean up memory on failure */
@@ -252,7 +252,7 @@ rd_and_store_for_creds(context, auth_context, inbuf, out_cred)
}
cred->usage = GSS_C_INITIATE; /* we can't accept with this */
- /* cred->princ already set */
+ /* cred->name already set */
cred->prerfc_mech = 1; /* this cred will work with all three mechs */
cred->rfc_mech = 1;
cred->keytab = NULL; /* no keytab associated with this... */
@@ -307,7 +307,7 @@ kg_accept_dce(minor_status, context_handle, verifier_cred_handle,
krb5_error_code code;
krb5_gss_ctx_id_rec *ctx = 0;
krb5_timestamp now;
- krb5_principal name = NULL;
+ krb5_gss_name_t name = NULL;
krb5_ui_4 nonce = 0;
krb5_data ap_rep;
OM_uint32 major_status = GSS_S_FAILURE;
@@ -350,13 +350,8 @@ kg_accept_dce(minor_status, context_handle, verifier_cred_handle,
ctx->established = 1;
if (src_name) {
- if ((code = krb5_copy_principal(ctx->k5_context, ctx->there, &name))) {
- major_status = GSS_S_FAILURE;
- goto fail;
- }
- /* intern the src_name */
- if (! kg_save_name((gss_name_t) name)) {
- code = G_VALIDATE_FAILED;
+ if ((code = kg_duplicate_name(ctx->k5_context, ctx->there,
+ KG_INIT_NAME_INTERN, &name))) {
major_status = GSS_S_FAILURE;
goto fail;
}
@@ -420,7 +415,7 @@ kg_accept_krb5(minor_status, context_handle,
krb5_address addr, *paddr;
krb5_authenticator *authdat = 0;
krb5_checksum reqcksum;
- krb5_principal name = NULL;
+ krb5_gss_name_t name = NULL;
krb5_ui_4 gss_flags = 0;
int decode_req_message = 0;
krb5_gss_ctx_id_rec *ctx = NULL;
@@ -442,6 +437,7 @@ kg_accept_krb5(minor_status, context_handle,
int no_encap = 0;
krb5_flags ap_req_options = 0;
krb5_enctype negotiated_etype;
+ krb5_authdata_context ad_context = NULL;
code = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION);
if (code) {
@@ -587,8 +583,11 @@ kg_accept_krb5(minor_status, context_handle,
goto fail;
}
- if ((code = krb5_rd_req(context, &auth_context, &ap_req, cred->princ,
- cred->keytab, &ap_req_options, &ticket))) {
+ if ((code = krb5_rd_req(context, &auth_context, &ap_req,
+ cred->name ? cred->name->princ : NULL,
+ cred->keytab,
+ &ap_req_options,
+ &ticket))) {
major_status = GSS_S_FAILURE;
goto fail;
}
@@ -865,15 +864,23 @@ kg_accept_krb5(minor_status, context_handle,
major_status = GSS_S_FAILURE;
goto fail;
}
- if ((code = krb5_copy_principal(context, ticket->server, &ctx->here))) {
+ if ((code = kg_init_name(context, ticket->server, NULL, 0, &ctx->here))) {
major_status = GSS_S_FAILURE;
goto fail;
}
-
- if ((code = krb5_copy_principal(context, authdat->client, &ctx->there))) {
+ if ((code = krb5_auth_con_get_authdata_context(context, auth_context,
+ &ad_context))) {
major_status = GSS_S_FAILURE;
goto fail;
}
+ if ((code = kg_init_name(context, authdat->client,
+ ad_context, KG_INIT_NAME_NO_COPY, &ctx->there))) {
+ major_status = GSS_S_FAILURE;
+ goto fail;
+ }
+ /* Now owned by ctx->there */
+ authdat->client = NULL;
+ krb5_auth_con_set_authdata_context(context, auth_context, NULL);
if ((code = krb5_auth_con_getrecvsubkey(context, auth_context,
&ctx->subkey))) {
@@ -1092,13 +1099,8 @@ kg_accept_krb5(minor_status, context_handle,
/* set the return arguments */
if (src_name) {
- if ((code = krb5_copy_principal(context, ctx->there, &name))) {
- major_status = GSS_S_FAILURE;
- goto fail;
- }
- /* intern the src_name */
- if (! kg_save_name((gss_name_t) name)) {
- code = G_VALIDATE_FAILED;
+ if ((code = kg_duplicate_name(context, ctx->there,
+ KG_INIT_NAME_INTERN, &name))) {
major_status = GSS_S_FAILURE;
goto fail;
}
@@ -1163,15 +1165,14 @@ fail:
if (deleg_cred) { /* free memory associated with the deleg credential */
if (deleg_cred->ccache)
(void)krb5_cc_close(context, deleg_cred->ccache);
- if (deleg_cred->princ)
- krb5_free_principal(context, deleg_cred->princ);
+ if (deleg_cred->name)
+ kg_release_name(context, 0, &deleg_cred->name);
xfree(deleg_cred);
}
if (token.value)
xfree(token.value);
if (name) {
- (void) kg_delete_name((gss_name_t) name);
- krb5_free_principal(context, name);
+ (void) kg_release_name(context, 0, &name);
}
*minor_status = code;
@@ -1212,7 +1213,7 @@ fail:
krb_error_data.error = code;
(void) krb5_us_timeofday(context, &krb_error_data.stime,
&krb_error_data.susec);
- krb_error_data.server = cred->princ;
+ krb_error_data.server = cred->name ? cred->name->princ : NULL;
code = krb5_mk_error(context, &krb_error_data, &scratch);
if (code)
diff --git a/src/lib/gssapi/krb5/acquire_cred.c b/src/lib/gssapi/krb5/acquire_cred.c
index 4427ed763..8f8cf1e2c 100644
--- a/src/lib/gssapi/krb5/acquire_cred.c
+++ b/src/lib/gssapi/krb5/acquire_cred.c
@@ -131,18 +131,18 @@ gss_krb5int_register_acceptor_identity(OM_uint32 *minor_status,
}
/* get credentials corresponding to a key in the krb5 keytab.
- If the default name is requested, return the name in output_princ.
- If output_princ is non-NULL, the caller will use or free it, regardless
+ If the default name is requested, return the name in output_name.
+ If output_name is non-NULL, the caller will use or free it, regardless
of the return value.
If successful, set the keytab-specific fields in cred
*/
static OM_uint32
-acquire_accept_cred(context, minor_status, desired_name, output_princ, cred)
+acquire_accept_cred(context, minor_status, desired_name, output_name, cred)
krb5_context context;
OM_uint32 *minor_status;
- gss_name_t desired_name;
- krb5_principal *output_princ;
+ krb5_gss_name_t desired_name;
+ krb5_gss_name_t *output_name;
krb5_gss_cred_id_rec *cred;
{
krb5_error_code code;
@@ -150,7 +150,7 @@ acquire_accept_cred(context, minor_status, desired_name, output_princ, cred)
krb5_keytab kt;
krb5_keytab_entry entry;
- *output_princ = NULL;
+ *output_name = NULL;
cred->keytab = NULL;
/* open the default keytab */
@@ -178,8 +178,8 @@ acquire_accept_cred(context, minor_status, desired_name, output_princ, cred)
return(GSS_S_CRED_UNAVAIL);
}
- if (desired_name != GSS_C_NO_NAME) {
- princ = (krb5_principal) desired_name;
+ if (desired_name != NULL) {
+ princ = desired_name->princ;
if ((code = krb5_kt_get_entry(context, kt, princ, 0, 0, &entry))) {
(void) krb5_kt_close(context, kt);
if (code == KRB5_KT_NOTFOUND) {
@@ -212,18 +212,18 @@ acquire_accept_cred(context, minor_status, desired_name, output_princ, cred)
#endif /* LEAN_CLIENT */
/* get credentials corresponding to the default credential cache.
- If the default name is requested, return the name in output_princ.
- If output_princ is non-NULL, the caller will use or free it, regardless
+ If the default name is requested, return the name in output_name.
+ If output_name is non-NULL, the caller will use or free it, regardless
of the return value.
If successful, set the ccache-specific fields in cred.
*/
static OM_uint32
-acquire_init_cred(context, minor_status, desired_name, output_princ, cred)
+acquire_init_cred(context, minor_status, desired_name, output_name, cred)
krb5_context context;
OM_uint32 *minor_status;
- gss_name_t desired_name;
- krb5_principal *output_princ;
+ krb5_gss_name_t desired_name;
+ krb5_gss_name_t *output_name;
krb5_gss_cred_id_rec *cred;
{
krb5_error_code code;
@@ -255,11 +255,10 @@ acquire_init_cred(context, minor_status, desired_name, output_princ, cred)
kim_ccache kimccache = NULL;
kim_identity identity = NULL;
kim_credential_state state;
- krb5_principal desired_princ = (krb5_principal) desired_name;
err = kim_identity_create_from_krb5_principal (&identity,
context,
- desired_princ);
+ desired_name->princ);
if (!err) {
err = kim_ccache_create_from_client_identity (&kimccache, identity);
@@ -307,7 +306,7 @@ acquire_init_cred(context, minor_status, desired_name, output_princ, cred)
if ( pLeash_AcquireInitialTicketsIfNeeded ) {
char ccname[256]="";
- pLeash_AcquireInitialTicketsIfNeeded(context, (krb5_principal) desired_name, ccname, sizeof(ccname));
+ pLeash_AcquireInitialTicketsIfNeeded(context, desired_name->princ, ccname, sizeof(ccname));
if (!ccname[0]) {
*minor_status = KRB5_CC_NOTFOUND;
return(GSS_S_CRED_UNAVAIL);
@@ -354,17 +353,24 @@ acquire_init_cred(context, minor_status, desired_name, output_princ, cred)
return(GSS_S_FAILURE);
}
- if (desired_name != (gss_name_t) NULL) {
- if (! krb5_principal_compare(context, princ, (krb5_principal) desired_name)) {
+ if (desired_name != (krb5_gss_name_t)NULL) {
+ if (! krb5_principal_compare(context, princ, desired_name->princ)) {
(void)krb5_free_principal(context, princ);
(void)krb5_cc_close(context, ccache);
*minor_status = KG_CCACHE_NOMATCH;
return(GSS_S_CRED_UNAVAIL);
}
(void)krb5_free_principal(context, princ);
- princ = (krb5_principal) desired_name;
+ princ = desired_name->princ;
} else {
- *output_princ = princ;
+ if ((code = kg_init_name(context, princ, NULL,
+ KG_INIT_NAME_NO_COPY | KG_INIT_NAME_INTERN,
+ output_name))) {
+ (void)krb5_free_principal(context, princ);
+ (void)krb5_cc_close(context, ccache);
+ *minor_status = code;
+ return(GSS_S_FAILURE);
+ }
}
/* iterate over the ccache, find the tgt */
@@ -489,7 +495,7 @@ krb5_gss_acquire_cred(minor_status, desired_name, time_req,
/* validate the name */
/*SUPPRESS 29*/
- if ((desired_name != (gss_name_t) NULL) &&
+ if ((desired_name != GSS_C_NO_NAME) &&
(! kg_validate_name(desired_name))) {
*minor_status = (OM_uint32) G_VALIDATE_FAILED;
krb5_free_context(context);
@@ -531,7 +537,7 @@ krb5_gss_acquire_cred(minor_status, desired_name, time_req,
memset(cred, 0, sizeof(krb5_gss_cred_id_rec));
cred->usage = cred_usage;
- cred->princ = NULL;
+ cred->name = NULL;
cred->prerfc_mech = (req_old != 0);
cred->rfc_mech = (req_new != 0);
@@ -561,15 +567,15 @@ krb5_gss_acquire_cred(minor_status, desired_name, time_req,
}
/* if requested, acquire credentials for accepting */
- /* this will fill in cred->princ if the desired_name is not specified */
+ /* this will fill in cred->name if the desired_name is not specified */
#ifndef LEAN_CLIENT
if ((cred_usage == GSS_C_ACCEPT) ||
(cred_usage == GSS_C_BOTH))
if ((ret = acquire_accept_cred(context, minor_status, desired_name,
- &(cred->princ), cred))
+ &(cred->name), cred))
!= GSS_S_COMPLETE) {
- if (cred->princ)
- krb5_free_principal(context, cred->princ);
+ if (cred->name)
+ kg_release_name(context, 0, &cred->name);
k5_mutex_destroy(&cred->lock);
xfree(cred);
/* minor_status set by acquire_accept_cred() */
@@ -580,22 +586,22 @@ krb5_gss_acquire_cred(minor_status, desired_name, time_req,
#endif /* LEAN_CLIENT */
/* if requested, acquire credentials for initiation */
- /* this will fill in cred->princ if it wasn't set above, and
+ /* this will fill in cred->name if it wasn't set above, and
the desired_name is not specified */
if ((cred_usage == GSS_C_INITIATE) ||
(cred_usage == GSS_C_BOTH))
if ((ret =
acquire_init_cred(context, minor_status,
- cred->princ?(gss_name_t)cred->princ:desired_name,
- &(cred->princ), cred))
+ cred->name?cred->name:(krb5_gss_name_t)desired_name,
+ &cred->name, cred))
!= GSS_S_COMPLETE) {
#ifndef LEAN_CLIENT
if (cred->keytab)
krb5_kt_close(context, cred->keytab);
#endif /* LEAN_CLIENT */
- if (cred->princ)
- krb5_free_principal(context, cred->princ);
+ if (cred->name)
+ kg_release_name(context, 0, &cred->name);
k5_mutex_destroy(&cred->lock);
xfree(cred);
/* minor_status set by acquire_init_cred() */
@@ -606,9 +612,10 @@ krb5_gss_acquire_cred(minor_status, desired_name, time_req,
/* if the princ wasn't filled in already, fill it in now */
- if (!cred->princ && (desired_name != GSS_C_NO_NAME))
- if ((code = krb5_copy_principal(context, (krb5_principal) desired_name,
- &(cred->princ)))) {
+ if (!cred->name && (desired_name != GSS_C_NO_NAME))
+ if ((code = kg_duplicate_name(context,
+ (krb5_gss_name_t)desired_name,
+ 0, &cred->name))) {
if (cred->ccache)
(void)krb5_cc_close(context, cred->ccache);
#ifndef LEAN_CLIENT
@@ -640,8 +647,8 @@ krb5_gss_acquire_cred(minor_status, desired_name, time_req,
if (cred->keytab)
(void)krb5_kt_close(context, cred->keytab);
#endif /* LEAN_CLIENT */
- if (cred->princ)
- krb5_free_principal(context, cred->princ);
+ if (cred->name)
+ kg_release_name(context, 0, &cred->name);
k5_mutex_destroy(&cred->lock);
xfree(cred);
*minor_status = code;
@@ -673,8 +680,8 @@ krb5_gss_acquire_cred(minor_status, desired_name, time_req,
if (cred->keytab)
(void)krb5_kt_close(context, cred->keytab);
#endif /* LEAN_CLIENT */
- if (cred->princ)
- krb5_free_principal(context, cred->princ);
+ if (cred->name)
+ kg_release_name(context, 0, &cred->name);
k5_mutex_destroy(&cred->lock);
xfree(cred);
/* *minor_status set above */
@@ -694,8 +701,8 @@ krb5_gss_acquire_cred(minor_status, desired_name, time_req,
if (cred->keytab)
(void)krb5_kt_close(context, cred->keytab);
#endif /* LEAN_CLIENT */
- if (cred->princ)
- krb5_free_principal(context, cred->princ);
+ if (cred->name)
+ kg_release_name(context, 0, &cred->name);
k5_mutex_destroy(&cred->lock);
xfree(cred);
*minor_status = (OM_uint32) G_VALIDATE_FAILED;
diff --git a/src/lib/gssapi/krb5/add_cred.c b/src/lib/gssapi/krb5/add_cred.c
index 3652f918b..cb14a5c9b 100644
--- a/src/lib/gssapi/krb5/add_cred.c
+++ b/src/lib/gssapi/krb5/add_cred.c
@@ -170,8 +170,7 @@ krb5_gss_add_cred(minor_status, input_cred_handle,
/* make sure the desired_name is the same as the existing one */
if (desired_name &&
- !krb5_principal_compare(context, (krb5_principal) desired_name,
- cred->princ)) {
+ !kg_compare_name(context, (krb5_gss_name_t)desired_name, cred->name)) {
*minor_status = 0;
krb5_free_context(context);
return(GSS_S_BAD_NAME);
@@ -200,8 +199,8 @@ krb5_gss_add_cred(minor_status, input_cred_handle,
new_cred->rfc_mech = cred->rfc_mech;
new_cred->tgt_expire = cred->tgt_expire;
- if (cred->princ)
- code = krb5_copy_principal(context, cred->princ, &new_cred->princ);
+ if (cred->name)
+ code = kg_duplicate_name(context, cred->name, 0, &new_cred->name);
if (code) {
xfree(new_cred);
@@ -214,8 +213,8 @@ krb5_gss_add_cred(minor_status, input_cred_handle,
if (cred->keytab) {
kttype = krb5_kt_get_type(context, cred->keytab);
if ((strlen(kttype)+2) > sizeof(ktboth)) {
- if (new_cred->princ)
- krb5_free_principal(context, new_cred->princ);
+ if (new_cred->name)
+ kg_release_name(context, 0, &new_cred->name);
xfree(new_cred);
*minor_status = ENOMEM;
@@ -231,8 +230,8 @@ krb5_gss_add_cred(minor_status, input_cred_handle,
ktboth+strlen(ktboth),
sizeof(ktboth)-strlen(ktboth));
if (code) {
- if(new_cred->princ)
- krb5_free_principal(context, new_cred->princ);
+ if(new_cred->name)
+ kg_release_name(context, 0, &new_cred->name);
xfree(new_cred);
*minor_status = code;
@@ -243,8 +242,8 @@ krb5_gss_add_cred(minor_status, input_cred_handle,
code = krb5_kt_resolve(context, ktboth, &new_cred->keytab);
if (code) {
- if (new_cred->princ)
- krb5_free_principal(context, new_cred->princ);
+ if (new_cred->name)
+ kg_release_name(context, 0, &new_cred->name);
xfree(new_cred);
*minor_status = code;
@@ -261,15 +260,17 @@ krb5_gss_add_cred(minor_status, input_cred_handle,
if (cred->rcache) {
/* Open the replay cache for this principal. */
+ assert(cred->name->princ != NULL);
+
if ((code = krb5_get_server_rcache(context,
- krb5_princ_component(context, cred->princ, 0),
+ krb5_princ_component(context, cred->name->princ, 0),
&new_cred->rcache))) {
#ifndef LEAN_CLIENT
if (new_cred->keytab)
krb5_kt_close(context, new_cred->keytab);
#endif /* LEAN_CLIENT */
- if (new_cred->princ)
- krb5_free_principal(context, new_cred->princ);
+ if (new_cred->name)
+ kg_release_name(context, 0, &new_cred->name);
xfree(new_cred);
*minor_status = code;
@@ -292,8 +293,8 @@ krb5_gss_add_cred(minor_status, input_cred_handle,
if (new_cred->keytab)
krb5_kt_close(context, new_cred->keytab);
#endif /* LEAN_CLIENT */
- if (new_cred->princ)
- krb5_free_principal(context, new_cred->princ);
+ if (new_cred->name)
+ kg_release_name(context, 0, &new_cred->name);
xfree(new_cred);
krb5_free_context(context);
@@ -314,8 +315,8 @@ krb5_gss_add_cred(minor_status, input_cred_handle,
if (new_cred->keytab)
krb5_kt_close(context, new_cred->keytab);
#endif /* LEAN_CLIENT */
- if (new_cred->princ)
- krb5_free_principal(context, new_cred->princ);
+ if (new_cred->name)
+ kg_release_name(context, 0, &new_cred->name);
xfree(new_cred);
*minor_status = code;
@@ -338,8 +339,8 @@ krb5_gss_add_cred(minor_status, input_cred_handle,
if (new_cred->keytab)
krb5_kt_close(context, new_cred->keytab);
#endif /* LEAN_CLIENT */
- if (new_cred->princ)
- krb5_free_principal(context, new_cred->princ);
+ if (new_cred->name)
+ kg_release_name(context, 0, &new_cred->name);
xfree(new_cred);
krb5_free_context(context);
diff --git a/src/lib/gssapi/krb5/compare_name.c b/src/lib/gssapi/krb5/compare_name.c
index e456ed50a..1e106da92 100644
--- a/src/lib/gssapi/krb5/compare_name.c
+++ b/src/lib/gssapi/krb5/compare_name.c
@@ -54,8 +54,9 @@ krb5_gss_compare_name(minor_status, name1, name2, name_equal)
}
*minor_status = 0;
- *name_equal = krb5_principal_compare(context, (krb5_principal) name1,
- (krb5_principal) name2);
+ *name_equal = kg_compare_name(context,
+ (krb5_gss_name_t)name1,
+ (krb5_gss_name_t)name2);
krb5_free_context(context);
return(GSS_S_COMPLETE);
}
diff --git a/src/lib/gssapi/krb5/delete_sec_context.c b/src/lib/gssapi/krb5/delete_sec_context.c
index 33e0e313e..e2da3dc98 100644
--- a/src/lib/gssapi/krb5/delete_sec_context.c
+++ b/src/lib/gssapi/krb5/delete_sec_context.c
@@ -88,9 +88,9 @@ krb5_gss_delete_sec_context(minor_status, context_handle, output_token)
krb5_free_keyblock(context, ctx->seq);
if (ctx->here)
- krb5_free_principal(context, ctx->here);
+ kg_release_name(context, 0, &ctx->here);
if (ctx->there)
- krb5_free_principal(context, ctx->there);
+ kg_release_name(context, 0, &ctx->there);
if (ctx->subkey)
krb5_free_keyblock(context, ctx->subkey);
if (ctx->acceptor_subkey)
diff --git a/src/lib/gssapi/krb5/disp_name.c b/src/lib/gssapi/krb5/disp_name.c
index d6bf0f7ba..676dc4d6b 100644
--- a/src/lib/gssapi/krb5/disp_name.c
+++ b/src/lib/gssapi/krb5/disp_name.c
@@ -51,7 +51,8 @@ krb5_gss_display_name(minor_status, input_name, output_name_buffer,
}
if ((code = krb5_unparse_name(context,
- (krb5_principal) input_name, &str))) {
+ ((krb5_gss_name_t) input_name)->princ,
+ &str))) {
*minor_status = code;
save_error_info(*minor_status, context);
krb5_free_context(context);
diff --git a/src/lib/gssapi/krb5/duplicate_name.c b/src/lib/gssapi/krb5/duplicate_name.c
index add3a2ed0..678349324 100644
--- a/src/lib/gssapi/krb5/duplicate_name.c
+++ b/src/lib/gssapi/krb5/duplicate_name.c
@@ -34,7 +34,7 @@ OM_uint32 krb5_gss_duplicate_name(OM_uint32 *minor_status,
{
krb5_context context;
krb5_error_code code;
- krb5_principal princ, outprinc;
+ krb5_gss_name_t princ, outprinc;
if (minor_status)
*minor_status = 0;
@@ -53,23 +53,16 @@ OM_uint32 krb5_gss_duplicate_name(OM_uint32 *minor_status,
return(GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME);
}
- princ = (krb5_principal)input_name;
- if ((code = krb5_copy_principal(context, princ, &outprinc))) {
+ princ = (krb5_gss_name_t)input_name;
+ if ((code = kg_duplicate_name(context, princ, KG_INIT_NAME_INTERN, &outprinc))) {
*minor_status = code;
save_error_info(*minor_status, context);
krb5_free_context(context);
return(GSS_S_FAILURE);
}
-
- if (! kg_save_name((gss_name_t) outprinc)) {
- krb5_free_principal(context, outprinc);
- krb5_free_context(context);
- *minor_status = (OM_uint32) G_VALIDATE_FAILED;
- return(GSS_S_FAILURE);
- }
-
krb5_free_context(context);
*dest_name = (gss_name_t) outprinc;
+ assert(kg_validate_name(*dest_name));
return(GSS_S_COMPLETE);
}
diff --git a/src/lib/gssapi/krb5/export_name.c b/src/lib/gssapi/krb5/export_name.c
index 46664e5a0..67d9ce0b2 100644
--- a/src/lib/gssapi/krb5/export_name.c
+++ b/src/lib/gssapi/krb5/export_name.c
@@ -58,7 +58,7 @@ OM_uint32 krb5_gss_export_name(OM_uint32 *minor_status,
return(GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME);
}
- if ((code = krb5_unparse_name(context, (krb5_principal) input_name,
+ if ((code = krb5_unparse_name(context, ((krb5_gss_name_t) input_name)->princ,
&str))) {
if (minor_status)
*minor_status = code;
diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h
index 48da87807..e05c5bc81 100644
--- a/src/lib/gssapi/krb5/gssapiP_krb5.h
+++ b/src/lib/gssapi/krb5/gssapiP_krb5.h
@@ -153,7 +153,11 @@ enum qop {
/** internal types **/
-typedef krb5_principal krb5_gss_name_t;
+typedef struct _krb5_gss_name_rec {
+ krb5_principal princ; /* immutable */
+ k5_mutex_t lock; /* protects ad_context only for now */
+ krb5_authdata_context ad_context;
+} krb5_gss_name_rec, *krb5_gss_name_t;
typedef struct _krb5_gss_cred_id_rec {
/* protect against simultaneous accesses */
@@ -161,7 +165,7 @@ typedef struct _krb5_gss_cred_id_rec {
/* name/type of credential */
gss_cred_usage_t usage;
- krb5_principal princ; /* this is not interned as a gss_name_t */
+ krb5_gss_name_t name;
unsigned int prerfc_mech : 1;
unsigned int rfc_mech : 1;
unsigned int proxy_cred : 1;
@@ -184,8 +188,8 @@ typedef struct _krb5_gss_ctx_id_rec {
unsigned int seed_init : 1; /* XXX tested but never actually set */
OM_uint32 gss_flags;
unsigned char seed[16];
- krb5_principal here;
- krb5_principal there;
+ krb5_gss_name_t here;
+ krb5_gss_name_t there;
krb5_keyblock *subkey; /*One of two potential keys to use with RFC
* 4121 packets; this key must always be set.*/
int signalg;
@@ -825,6 +829,86 @@ OM_uint32 gss_krb5int_unseal_token_v3(krb5_context *contextptr,
int gss_krb5int_rotate_left (void *ptr, size_t bufsiz, size_t rc);
+/* naming_exts.c */
+#define KG_INIT_NAME_INTERN 0x1
+#define KG_INIT_NAME_NO_COPY 0x2
+
+krb5_error_code
+kg_init_name(krb5_context context,
+ krb5_principal principal,
+ krb5_authdata_context ad_context,
+ krb5_flags flags,
+ krb5_gss_name_t *name);
+
+krb5_error_code
+kg_release_name(krb5_context context,
+ krb5_flags flags,
+ krb5_gss_name_t *name);
+
+krb5_error_code
+kg_duplicate_name(krb5_context context,
+ const krb5_gss_name_t src,
+ krb5_flags flags,
+ krb5_gss_name_t *dst);
+
+krb5_boolean
+kg_compare_name(krb5_context context,
+ krb5_gss_name_t name1,
+ krb5_gss_name_t name2);
+
+OM_uint32
+krb5_gss_display_name_ext(OM_uint32 *minor_status,
+ gss_name_t name,
+ gss_OID display_as_name_type,
+ gss_buffer_t display_name);
+
+OM_uint32
+krb5_gss_inquire_name(OM_uint32 *minor_status,
+ gss_name_t name,
+ int *name_is_MN,
+ gss_OID *MN_mech,
+ gss_buffer_set_t *attrs);
+
+OM_uint32
+krb5_gss_get_name_attribute(OM_uint32 *minor_status,
+ gss_name_t name,
+ gss_buffer_t attr,
+ int *authenticated,
+ int *complete,
+ gss_buffer_t value,
+ gss_buffer_t display_value,
+ int *more);
+
+OM_uint32
+krb5_gss_set_name_attribute(OM_uint32 *minor_status,
+ gss_name_t name,
+ int complete,
+ gss_buffer_t attr,
+ gss_buffer_t value);
+
+OM_uint32
+krb5_gss_delete_name_attribute(OM_uint32 *minor_status,
+ gss_name_t name,
+ gss_buffer_t attr);
+
+OM_uint32
+krb5_gss_export_name_composite(OM_uint32 *minor_status,
+ gss_name_t name,
+ gss_buffer_t exp_composite_name);
+
+OM_uint32
+krb5_gss_map_name_to_any(OM_uint32 *minor_status,
+ gss_name_t name,
+ int authenticated,
+ gss_buffer_t type_id,
+ gss_any_t *output);
+
+OM_uint32
+krb5_gss_release_any_name_mapping(OM_uint32 *minor_status,
+ gss_name_t name,
+ gss_buffer_t type_id,
+ gss_any_t *input);
+
/* s4u_gss_glue.c */
OM_uint32
kg_compose_deleg_cred(OM_uint32 *minor_status,
@@ -837,7 +921,6 @@ kg_compose_deleg_cred(OM_uint32 *minor_status,
OM_uint32 *time_rec,
krb5_context context);
-
/*
* These take unglued krb5-mech-specific contexts.
*/
diff --git a/src/lib/gssapi/krb5/gssapi_krb5.c b/src/lib/gssapi/krb5/gssapi_krb5.c
index 3c1c6b8cb..351bead8a 100644
--- a/src/lib/gssapi/krb5/gssapi_krb5.c
+++ b/src/lib/gssapi/krb5/gssapi_krb5.c
@@ -681,6 +681,14 @@ static struct gss_config krb5_mechanism = {
NULL, /* complete_auth_token */
krb5_gss_acquire_cred_impersonate_name,
NULL, /* krb5_gss_add_cred_impersonate_name */
+ NULL, /* display_name_ext */
+ krb5_gss_inquire_name,
+ krb5_gss_get_name_attribute,
+ krb5_gss_set_name_attribute,
+ krb5_gss_delete_name_attribute,
+ krb5_gss_export_name_composite,
+ krb5_gss_map_name_to_any,
+ krb5_gss_release_any_name_mapping,
};
diff --git a/src/lib/gssapi/krb5/import_name.c b/src/lib/gssapi/krb5/import_name.c
index 6879c766f..b33619583 100644
--- a/src/lib/gssapi/krb5/import_name.c
+++ b/src/lib/gssapi/krb5/import_name.c
@@ -45,6 +45,39 @@
* GSS_S_FAILURE if memory allocation fails
*/
+/*
+ * Import serialized authdata context
+ */
+static krb5_error_code
+import_name_composite(krb5_context context,
+ unsigned char *enc_data, size_t enc_length,
+ krb5_authdata_context *pad_context)
+{
+ krb5_authdata_context ad_context;
+ krb5_error_code code;
+ krb5_data data;
+
+ code = krb5_authdata_context_init(context, &ad_context);
+ if (code != 0)
+ return code;
+
+ data.data = (char *)enc_data;
+ data.length = enc_length;
+
+ code = krb5_authdata_import_attributes(context,
+ ad_context,
+ AD_USAGE_MASK,
+ &data);
+ if (code != 0) {
+ krb5_authdata_context_free(context, ad_context);
+ return code;
+ }
+
+ *pad_context = ad_context;
+
+ return 0;
+}
+
OM_uint32
krb5_gss_import_name(minor_status, input_name_buffer,
input_name_type, output_name)
@@ -54,13 +87,16 @@ krb5_gss_import_name(minor_status, input_name_buffer,
gss_name_t *output_name;
{
krb5_context context;
- krb5_principal princ;
+ krb5_principal princ = NULL;
krb5_error_code code;
- char *stringrep, *tmp, *tmp2, *cp;
- OM_uint32 length;
+ unsigned char *cp, *end;
+ char *tmp, *stringrep, *tmp2;
+ ssize_t length;
#ifndef NO_PASSWORD
struct passwd *pw;
#endif
+ int has_ad = 0;
+ krb5_authdata_context ad_context = NULL;
code = krb5_gss_init_context(&context);
if (code) {
@@ -81,7 +117,7 @@ krb5_gss_import_name(minor_status, input_name_buffer,
char *service, *host;
if ((tmp =
- (char *) xmalloc(input_name_buffer->length + 1)) == NULL) {
+ xmalloc(input_name_buffer->length + 1)) == NULL) {
*minor_status = ENOMEM;
krb5_free_context(context);
return(GSS_S_FAILURE);
@@ -155,28 +191,49 @@ krb5_gss_import_name(minor_status, input_name_buffer,
goto do_getpwuid;
#endif
} else if (g_OID_equal(input_name_type, gss_nt_exported_name)) {
- cp = tmp;
+#define BOUNDS_CHECK(cp, end, n) do { if ((end) - (cp) < (n)) goto fail_name; } while (0)
+ cp = (unsigned char *)tmp;
+ end = cp + input_name_buffer->length;
+
+ BOUNDS_CHECK(cp, end, 2);
if (*cp++ != 0x04)
goto fail_name;
- if (*cp++ != 0x01)
+ switch (*cp++) {
+ case 0x01:
+ break;
+ case 0x02:
+ has_ad++;
+ break;
+ default:
goto fail_name;
+ }
+
+ BOUNDS_CHECK(cp, end, 2);
if (*cp++ != 0x00)
goto fail_name;
length = *cp++;
- if (length != gss_mech_krb5->length+2)
+ if (length != (ssize_t)gss_mech_krb5->length+2)
goto fail_name;
+
+ BOUNDS_CHECK(cp, end, 2);
if (*cp++ != 0x06)
goto fail_name;
length = *cp++;
- if (length != gss_mech_krb5->length)
+ if (length != (ssize_t)gss_mech_krb5->length)
goto fail_name;
+
+ BOUNDS_CHECK(cp, end, length);
if (memcmp(cp, gss_mech_krb5->elements, length) != 0)
goto fail_name;
cp += length;
+
+ BOUNDS_CHECK(cp, end, 4);
length = *cp++;
length = (length << 8) | *cp++;
length = (length << 8) | *cp++;
length = (length << 8) | *cp++;
+
+ BOUNDS_CHECK(cp, end, length);
tmp2 = malloc(length+1);
if (tmp2 == NULL) {
xfree(tmp);
@@ -184,10 +241,27 @@ krb5_gss_import_name(minor_status, input_name_buffer,
krb5_free_context(context);
return GSS_S_FAILURE;
}
- strncpy(tmp2, cp, length);
+ strncpy(tmp2, (char *)cp, length);
tmp2[length] = 0;
-
stringrep = tmp2;
+ cp += length;
+
+ if (has_ad) {
+ BOUNDS_CHECK(cp, end, 4);
+ length = *cp++;
+ length = (length << 8) | *cp++;
+ length = (length << 8) | *cp++;
+ length = (length << 8) | *cp++;
+
+ BOUNDS_CHECK(cp, end, length);
+ code = import_name_composite(context,
+ cp, length,
+ &ad_context);
+ if (code != 0)
+ goto fail_name;
+ cp += length;
+ }
+ assert(cp == end);
} else {
xfree(tmp);
krb5_free_context(context);
@@ -218,16 +292,21 @@ krb5_gss_import_name(minor_status, input_name_buffer,
if (code) {
*minor_status = (OM_uint32) code;
save_error_info(*minor_status, context);
+ krb5_authdata_context_free(context, ad_context);
krb5_free_context(context);
return(GSS_S_BAD_NAME);
}
/* save the name in the validation database */
-
- if (! kg_save_name((gss_name_t) princ)) {
+ code = kg_init_name(context, princ, ad_context,
+ KG_INIT_NAME_INTERN | KG_INIT_NAME_NO_COPY,
+ (krb5_gss_name_t *)output_name);
+ if (code != 0) {
+ *minor_status = (OM_uint32) code;
+ save_error_info(*minor_status, context);
krb5_free_principal(context, princ);
+ krb5_authdata_context_free(context, ad_context);
krb5_free_context(context);
- *minor_status = (OM_uint32) G_VALIDATE_FAILED;
return(GSS_S_FAILURE);
}
@@ -235,6 +314,5 @@ krb5_gss_import_name(minor_status, input_name_buffer,
/* return it */
- *output_name = (gss_name_t) princ;
return(GSS_S_COMPLETE);
}
diff --git a/src/lib/gssapi/krb5/init_sec_context.c b/src/lib/gssapi/krb5/init_sec_context.c
index 0bb4fde02..62e7d6ed7 100644
--- a/src/lib/gssapi/krb5/init_sec_context.c
+++ b/src/lib/gssapi/krb5/init_sec_context.c
@@ -122,7 +122,7 @@ static krb5_error_code get_credentials(context, cred, server, now,
endtime, out_creds)
krb5_context context;
krb5_gss_cred_id_t cred;
- krb5_principal server;
+ krb5_gss_name_t server;
krb5_timestamp now;
krb5_timestamp endtime;
krb5_creds **out_creds;
@@ -137,6 +137,8 @@ static krb5_error_code get_credentials(context, cred, server, now,
memset(&evidence_creds, 0, sizeof(krb5_creds));
in_creds.client = in_creds.server = NULL;
+ assert(cred->name != NULL);
+
if ((code = krb5_cc_get_principal(context, cred->ccache, &cc_princ)))
goto cleanup;
@@ -146,7 +148,7 @@ static krb5_error_code get_credentials(context, cred, server, now,
* we can just use the S4U2Self or evidence ticket directly).
*/
if (cred->proxy_cred &&
- !krb5_principal_compare(context, cc_princ, server)) {
+ !krb5_principal_compare(context, cc_princ, server->princ)) {
krb5_creds mcreds;
flags |= KRB5_GC_CANONICALIZE |
@@ -158,10 +160,11 @@ static krb5_error_code get_credentials(context, cred, server, now,
mcreds.magic = KV5M_CREDS;
mcreds.times.endtime = cred->tgt_expire;
mcreds.server = cc_princ;
- mcreds.client = cred->princ;
+ mcreds.client = cred->name->princ;
code = krb5_cc_retrieve_cred(context, cred->ccache,
- KRB5_TC_MATCH_TIMES, &mcreds,
+ KRB5_TC_MATCH_TIMES | KRB5_TC_MATCH_AUTHDATA,
+ &mcreds,
&evidence_creds);
if (code)
goto cleanup;
@@ -171,11 +174,26 @@ static krb5_error_code get_credentials(context, cred, server, now,
in_creds.client = cc_princ;
in_creds.second_ticket = evidence_creds.ticket;
} else {
- in_creds.client = cred->princ;
+ in_creds.client = cred->name->princ;
}
- in_creds.server = server;
+ in_creds.server = server->princ;
in_creds.times.endtime = endtime;
+ in_creds.authdata = NULL;
+ in_creds.keyblock.enctype = 0;
+
+ /*
+ * cred->name is immutable, so there is no need to acquire
+ * cred->name->lock.
+ */
+ if (cred->name->ad_context != NULL) {
+ code = krb5_authdata_export_authdata(context,
+ cred->name->ad_context,
+ AD_USAGE_TGS_REQ,
+ &in_creds.authdata);
+ if (code != 0)
+ goto cleanup;
+ }
code = krb5_get_credentials(context, flags, cred->ccache,
&in_creds, out_creds);
@@ -183,7 +201,7 @@ static krb5_error_code get_credentials(context, cred, server, now,
goto cleanup;
if (flags & KRB5_GC_CONSTRAINED_DELEGATION) {
- if (!krb5_principal_compare(context, cred->princ,
+ if (!krb5_principal_compare(context, cred->name->princ,
(*out_creds)->client)) {
/* server did not support constrained delegation */
code = KRB5_KDCREP_MODIFIED;
@@ -203,8 +221,8 @@ static krb5_error_code get_credentials(context, cred, server, now,
}
cleanup:
- if (cc_princ)
- krb5_free_principal(context, cc_princ);
+ krb5_free_authdata(context, in_creds.authdata);
+ krb5_free_principal(context, cc_princ);
krb5_free_cred_contents(context, &evidence_creds);
return code;
@@ -242,8 +260,10 @@ make_gss_checksum (krb5_context context, krb5_auth_context auth_context,
krb5_auth_con_setflags(context, auth_context,
con_flags & ~KRB5_AUTH_CONTEXT_DO_TIME);
+ assert(data->cred->name != NULL);
+
code = krb5_fwd_tgt_creds(context, auth_context, 0,
- data->cred->princ, data->ctx->there,
+ data->cred->name->princ, data->ctx->there->princ,
data->cred->ccache, 1,
&credmsg);
@@ -318,11 +338,13 @@ make_gss_checksum (krb5_context context, krb5_auth_context auth_context,
}
static krb5_error_code
-make_ap_req_v1(context, ctx, cred, k_cred, chan_bindings, mech_type, token)
+make_ap_req_v1(context, ctx, cred, k_cred, ad_context,
+ chan_bindings, mech_type, token)
krb5_context context;
krb5_gss_ctx_id_rec *ctx;
krb5_gss_cred_id_t cred;
krb5_creds *k_cred;
+ krb5_authdata_context ad_context;
gss_channel_bindings_t chan_bindings;
gss_OID mech_type;
gss_buffer_t token;
@@ -375,8 +397,10 @@ make_ap_req_v1(context, ctx, cred, k_cred, chan_bindings, mech_type, token)
if (ctx->gss_flags & GSS_C_MUTUAL_FLAG)
mk_req_flags |= AP_OPTS_MUTUAL_REQUIRED | AP_OPTS_ETYPE_NEGOTIATION;
+ krb5_auth_con_set_authdata_context(context, ctx->auth_context, ad_context);
code = krb5_mk_req_extended(context, &ctx->auth_context, mk_req_flags,
checksum_data, k_cred, &ap_req);
+ krb5_auth_con_set_authdata_context(context, ctx->auth_context, NULL);
krb5_free_data_contents(context, &cksum_struct.checksum_data);
if (code)
goto cleanup;
@@ -526,11 +550,10 @@ kg_new_connection(
ctx->krb_times.endtime = now + time_req;
}
- if ((code = krb5_copy_principal(context, cred->princ, &ctx->here)))
+ if ((code = kg_duplicate_name(context, cred->name, 0, &ctx->here)))
goto fail;
- if ((code = krb5_copy_principal(context, (krb5_principal) target_name,
- &ctx->there)))
+ if ((code = kg_duplicate_name(context, (krb5_gss_name_t)target_name, 0, &ctx->there)))
goto fail;
code = get_credentials(context, cred, ctx->there, now,
@@ -566,7 +589,8 @@ kg_new_connection(
/* gsskrb5 v1 */
krb5_int32 seq_temp;
if ((code = make_ap_req_v1(context, ctx,
- cred, k_cred, input_chan_bindings,
+ cred, k_cred, ctx->here->ad_context,
+ input_chan_bindings,
mech_type, &token))) {
if ((code == KRB5_FCC_NOFILE) || (code == KRB5_CC_NOTFOUND) ||
(code == KG_EMPTY_CCACHE))
@@ -640,9 +664,9 @@ fail:
if (ctx_free->auth_context)
krb5_auth_con_free(context, ctx_free->auth_context);
if (ctx_free->here)
- krb5_free_principal(context, ctx_free->here);
+ kg_release_name(context, 0, &ctx_free->here);
if (ctx_free->there)
- krb5_free_principal(context, ctx_free->there);
+ kg_release_name(context, 0, &ctx_free->there);
if (ctx_free->subkey)
krb5_free_keyblock(context, ctx_free->subkey);
xfree(ctx_free);
@@ -709,8 +733,7 @@ mutual_auth(
goto fail;
}
- if (! krb5_principal_compare(context, ctx->there,
- (krb5_principal) target_name)) {
+ if (! kg_compare_name(context, ctx->there, (krb5_gss_name_t)target_name)) {
(void)krb5_gss_delete_sec_context(minor_status,
context_handle, NULL);
code = 0;
diff --git a/src/lib/gssapi/krb5/inq_context.c b/src/lib/gssapi/krb5/inq_context.c
index f3e44cdf5..fbc389245 100644
--- a/src/lib/gssapi/krb5/inq_context.c
+++ b/src/lib/gssapi/krb5/inq_context.c
@@ -94,7 +94,7 @@ krb5_gss_inquire_context(minor_status, context_handle, initiator_name,
krb5_context context;
krb5_error_code code;
krb5_gss_ctx_id_rec *ctx;
- krb5_principal initiator, acceptor;
+ krb5_gss_name_t initiator, acceptor;
krb5_timestamp now;
krb5_deltat lifetime;
@@ -130,38 +130,28 @@ krb5_gss_inquire_context(minor_status, context_handle, initiator_name,
lifetime = 0;
if (initiator_name) {
- if ((code = krb5_copy_principal(context,
- ctx->initiate?ctx->here:ctx->there,
- &initiator))) {
+ if ((code = kg_duplicate_name(context,
+ ctx->initiate?ctx->here:ctx->there,
+ KG_INIT_NAME_INTERN,
+ &initiator))) {
*minor_status = code;
save_error_info(*minor_status, context);
return(GSS_S_FAILURE);
}
- if (! kg_save_name((gss_name_t) initiator)) {
- krb5_free_principal(context, initiator);
- *minor_status = (OM_uint32) G_VALIDATE_FAILED;
- return(GSS_S_FAILURE);
- }
}
if (acceptor_name) {
- if ((code = krb5_copy_principal(context,
- ctx->initiate?ctx->there:ctx->here,
- &acceptor))) {
- if (initiator) krb5_free_principal(context, initiator);
+ if ((code = kg_duplicate_name(context,
+ ctx->initiate?ctx->there:ctx->here,
+ KG_INIT_NAME_INTERN,
+ &acceptor))) {
+ if (initiator)
+ kg_release_name(context, KG_INIT_NAME_INTERN,
+ &initiator);
*minor_status = code;
save_error_info(*minor_status, context);
return(GSS_S_FAILURE);
}
- if (! kg_save_name((gss_name_t) acceptor)) {
- krb5_free_principal(context, acceptor);
- if (initiator) {
- kg_delete_name((gss_name_t) initiator);
- krb5_free_principal(context, initiator);
- }
- *minor_status = (OM_uint32) G_VALIDATE_FAILED;
- return(GSS_S_FAILURE);
- }
}
if (initiator_name)
diff --git a/src/lib/gssapi/krb5/inq_cred.c b/src/lib/gssapi/krb5/inq_cred.c
index 8560135ab..5c358eb9f 100644
--- a/src/lib/gssapi/krb5/inq_cred.c
+++ b/src/lib/gssapi/krb5/inq_cred.c
@@ -88,7 +88,7 @@ krb5_gss_inquire_cred(minor_status, cred_handle, name, lifetime_ret,
krb5_error_code code;
krb5_timestamp now;
krb5_deltat lifetime;
- krb5_principal ret_name;
+ krb5_gss_name_t ret_name;
gss_OID_set mechs;
OM_uint32 ret;
@@ -145,8 +145,9 @@ krb5_gss_inquire_cred(minor_status, cred_handle, name, lifetime_ret,
lifetime = GSS_C_INDEFINITE;
if (name) {
- if (cred->princ &&
- (code = krb5_copy_principal(context, cred->princ, &ret_name))) {
+ if (cred->name &&
+ (code = kg_duplicate_name(context, cred->name,
+ KG_INIT_NAME_INTERN, &ret_name))) {
k5_mutex_unlock(&cred->lock);
*minor_status = code;
save_error_info(*minor_status, context);
@@ -168,24 +169,13 @@ krb5_gss_inquire_cred(minor_status, cred_handle, name, lifetime_ret,
&mechs)))) {
k5_mutex_unlock(&cred->lock);
if (ret_name)
- krb5_free_principal(context, ret_name);
+ kg_release_name(context, KG_INIT_NAME_INTERN, &ret_name);
/* *minor_status set above */
goto fail;
}
}
if (name) {
- if (ret_name != NULL && ! kg_save_name((gss_name_t) ret_name)) {
- k5_mutex_unlock(&cred->lock);
- if (cred_handle == GSS_C_NO_CREDENTIAL)
- krb5_gss_release_cred(minor_status, (gss_cred_id_t *)&cred);
-
- (void) generic_gss_release_oid_set(minor_status, &mechs);
- krb5_free_principal(context, ret_name);
- *minor_status = (OM_uint32) G_VALIDATE_FAILED;
- krb5_free_context(context);
- return(GSS_S_FAILURE);
- }
if (ret_name != NULL)
*name = (gss_name_t) ret_name;
else
diff --git a/src/lib/gssapi/krb5/naming_exts.c b/src/lib/gssapi/krb5/naming_exts.c
new file mode 100644
index 000000000..14b9b006d
--- /dev/null
+++ b/src/lib/gssapi/krb5/naming_exts.c
@@ -0,0 +1,722 @@
+/* -*- mode: c; indent-tabs-mode: nil -*- */
+/*
+ * lib/gssapi/krb5/naming_exts.c
+ *
+ * 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.
+ *
+ *
+ */
+
+#include <assert.h>
+#include "k5-int.h" /* for zap() */
+#include "gssapiP_krb5.h"
+#include <stdarg.h>
+
+krb5_error_code
+kg_init_name(krb5_context context,
+ krb5_principal principal,
+ krb5_authdata_context ad_context,
+ krb5_flags flags,
+ krb5_gss_name_t *ret_name)
+{
+ krb5_error_code code;
+ krb5_gss_name_t name;
+
+ *ret_name = NULL;
+
+ assert(principal != NULL);
+
+ if (principal == NULL)
+ return EINVAL;
+
+ name = xmalloc(sizeof(krb5_gss_name_rec));
+ if (name == NULL)
+ return ENOMEM;
+
+ memset(name, 0, sizeof(krb5_gss_name_rec));
+
+ code = k5_mutex_init(&name->lock);
+ if (code != 0)
+ goto cleanup;
+
+ if ((flags & KG_INIT_NAME_NO_COPY) == 0) {
+ code = krb5_copy_principal(context, principal, &name->princ);
+ if (code != 0)
+ goto cleanup;
+
+ if (ad_context != NULL) {
+ code = krb5_authdata_context_copy(context,
+ ad_context,
+ &name->ad_context);
+ if (code != 0)
+ goto cleanup;
+ }
+ } else {
+ name->princ = principal;
+ name->ad_context = ad_context;
+ }
+
+ if ((flags & KG_INIT_NAME_INTERN) &&
+ !kg_save_name((gss_name_t)name)) {
+ code = G_VALIDATE_FAILED;
+ goto cleanup;
+ }
+
+ *ret_name = name;
+
+cleanup:
+ if (code != 0)
+ kg_release_name(context, 0, &name);
+
+ return code;
+}
+
+krb5_error_code
+kg_release_name(krb5_context context,
+ krb5_flags flags,
+ krb5_gss_name_t *name)
+{
+ if (*name != NULL) {
+ if (flags & KG_INIT_NAME_INTERN)
+ kg_delete_name((gss_name_t)*name);
+ krb5_free_principal(context, (*name)->princ);
+ krb5_authdata_context_free(context, (*name)->ad_context);
+ k5_mutex_destroy(&(*name)->lock);
+ free(*name);
+ *name = NULL;
+ }
+
+ return 0;
+}
+
+krb5_error_code
+kg_duplicate_name(krb5_context context,
+ const krb5_gss_name_t src,
+ krb5_flags flags,
+ krb5_gss_name_t *dst)
+{
+ krb5_error_code code;
+
+ code = k5_mutex_lock(&src->lock);
+ if (code != 0)
+ return code;
+
+ code = kg_init_name(context, src->princ,
+ src->ad_context, flags, dst);
+
+ k5_mutex_unlock(&src->lock);
+
+ return code;
+}
+
+
+krb5_boolean
+kg_compare_name(krb5_context context,
+ krb5_gss_name_t name1,
+ krb5_gss_name_t name2)
+{
+ return krb5_principal_compare(context, name1->princ, name2->princ);
+}
+
+static OM_uint32
+kg_map_name_error(OM_uint32 *minor_status, krb5_error_code code)
+{
+ OM_uint32 major_status;
+
+ switch (code) {
+ case 0:
+ major_status = GSS_S_COMPLETE;
+ break;
+ case ENOENT:
+ case EPERM:
+ major_status = GSS_S_UNAVAILABLE;
+ break;
+ default:
+ major_status = GSS_S_FAILURE;
+ break;
+ }
+
+ *minor_status = code;
+
+ return major_status;
+}
+
+/* Owns data on success */
+static krb5_error_code
+kg_data_list_to_buffer_set_nocopy(krb5_data **pdata,
+ gss_buffer_set_t *buffer_set)
+{
+ gss_buffer_set_t set;
+ OM_uint32 minor_status;
+ unsigned int i;
+ krb5_data *data;
+
+ data = *pdata;
+
+ if (data == NULL) {
+ if (buffer_set != NULL)
+ *buffer_set = GSS_C_NO_BUFFER_SET;
+ return 0;
+ } else if (buffer_set == NULL)
+ return EINVAL;
+
+ if (GSS_ERROR(gss_create_empty_buffer_set(&minor_status,
+ &set))) {
+ assert(minor_status != 0);
+ return minor_status;
+ }
+
+ for (i = 0; data[i].data != NULL; i++)
+ ;
+
+ set->count = i;
+ set->elements = calloc(i, sizeof(gss_buffer_desc));
+ if (set->elements == NULL) {
+ gss_release_buffer_set(&minor_status, &set);
+ return ENOMEM;
+ }
+
+ for (i = 0; i < set->count; i++) {
+ set->elements[i].length = data[i].length;
+ set->elements[i].value = data[i].data;
+ }
+
+ free(data);
+ *pdata = NULL;
+
+ *buffer_set = set;
+
+ return 0;
+}
+
+OM_uint32
+krb5_gss_inquire_name(OM_uint32 *minor_status,
+ gss_name_t name,
+ int *name_is_MN,
+ gss_OID *MN_mech,
+ gss_buffer_set_t *attrs)
+{
+ krb5_context context;
+ krb5_error_code code;
+ krb5_gss_name_t kname;
+ krb5_data *kattrs = NULL;
+
+ if (minor_status != NULL)
+ *minor_status = 0;
+
+ if (attrs != NULL)
+ *attrs = GSS_C_NO_BUFFER_SET;
+
+ code = krb5_gss_init_context(&context);
+ if (code != 0) {
+ *minor_status = code;
+ return GSS_S_FAILURE;
+ }
+
+ if (!kg_validate_name(name)) {
+ *minor_status = (OM_uint32)G_VALIDATE_FAILED;
+ krb5_free_context(context);
+ return GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME;
+ }
+
+ kname = (krb5_gss_name_t)name;
+
+ code = k5_mutex_lock(&kname->lock);
+ if (code != 0) {
+ *minor_status = code;
+ return GSS_S_FAILURE;
+ }
+
+ if (kname->ad_context == NULL) {
+ code = krb5_authdata_context_init(context, &kname->ad_context);
+ if (code != 0)
+ goto cleanup;
+ }
+
+ code = krb5_authdata_get_attribute_types(context,
+ kname->ad_context,
+ &kattrs);
+ if (code != 0)
+ goto cleanup;
+
+ code = kg_data_list_to_buffer_set_nocopy(&kattrs, attrs);
+ if (code != 0)
+ goto cleanup;
+
+cleanup:
+ k5_mutex_unlock(&kname->lock);
+ krb5int_free_data_list(context, kattrs);
+
+ krb5_free_context(context);
+
+ return kg_map_name_error(minor_status, code);
+}
+
+OM_uint32
+krb5_gss_get_name_attribute(OM_uint32 *minor_status,
+ gss_name_t name,
+ gss_buffer_t attr,
+ int *authenticated,
+ int *complete,
+ gss_buffer_t value,
+ gss_buffer_t display_value,
+ int *more)
+{
+ krb5_context context;
+ krb5_error_code code;
+ krb5_gss_name_t kname;
+ krb5_data kattr;
+ krb5_boolean kauthenticated;
+ krb5_boolean kcomplete;
+ krb5_data kvalue;
+ krb5_data kdisplay_value;
+
+ if (minor_status != NULL)
+ *minor_status = 0;
+
+ code = krb5_gss_init_context(&context);
+ if (code != 0) {
+ *minor_status = code;
+ return GSS_S_FAILURE;
+ }
+
+ if (!kg_validate_name(name)) {
+ *minor_status = (OM_uint32)G_VALIDATE_FAILED;
+ krb5_free_context(context);
+ return GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME;
+ }
+
+ kname = (krb5_gss_name_t)name;
+
+ code = k5_mutex_lock(&kname->lock);
+ if (code != 0) {
+ *minor_status = code;
+ krb5_free_context(context);
+ return GSS_S_FAILURE;
+ }
+
+ if (kname->ad_context == NULL) {
+ code = krb5_authdata_context_init(context, &kname->ad_context);
+ if (code != 0) {
+ *minor_status = code;
+ k5_mutex_unlock(&kname->lock);
+ krb5_free_context(context);
+ return GSS_S_UNAVAILABLE;
+ }
+ }
+
+ kattr.data = (char *)attr->value;
+ kattr.length = attr->length;
+
+ kauthenticated = FALSE;
+ kcomplete = FALSE;
+
+ code = krb5_authdata_get_attribute(context,
+ kname->ad_context,
+ &kattr,
+ &kauthenticated,
+ &kcomplete,
+ value ? &kvalue : NULL,
+ display_value ? &kdisplay_value : NULL,
+ more);
+ if (code == 0) {
+ if (value != NULL) {
+ value->value = kvalue.data;
+ value->length = kvalue.length;
+ }
+
+ if (authenticated != NULL)
+ *authenticated = kauthenticated;
+ if (complete != NULL)
+ *complete = kcomplete;
+
+ if (display_value != NULL) {
+ display_value->value = kdisplay_value.data;
+ display_value->length = kdisplay_value.length;
+ }
+ }
+
+ k5_mutex_unlock(&kname->lock);
+ krb5_free_context(context);
+
+ return kg_map_name_error(minor_status, code);
+}
+
+OM_uint32
+krb5_gss_set_name_attribute(OM_uint32 *minor_status,
+ gss_name_t name,
+ int complete,
+ gss_buffer_t attr,
+ gss_buffer_t value)
+{
+ krb5_context context;
+ krb5_error_code code;
+ krb5_gss_name_t kname;
+ krb5_data kattr;
+ krb5_data kvalue;
+
+ if (minor_status != NULL)
+ *minor_status = 0;
+
+ code = krb5_gss_init_context(&context);
+ if (code != 0) {
+ *minor_status = code;
+ return GSS_S_FAILURE;
+ }
+
+ if (!kg_validate_name(name)) {
+ *minor_status = (OM_uint32)G_VALIDATE_FAILED;
+ krb5_free_context(context);
+ return GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME;
+ }
+
+ kname = (krb5_gss_name_t)name;
+
+ code = k5_mutex_lock(&kname->lock);
+ if (code != 0) {
+ *minor_status = code;
+ return GSS_S_FAILURE;
+ }
+
+ if (kname->ad_context == NULL) {
+ code = krb5_authdata_context_init(context, &kname->ad_context);
+ if (code != 0) {
+ *minor_status = code;
+ k5_mutex_unlock(&kname->lock);
+ krb5_free_context(context);
+ return GSS_S_UNAVAILABLE;
+ }
+ }
+
+ kattr.data = (char *)attr->value;
+ kattr.length = attr->length;
+
+ kvalue.data = (char *)value->value;
+ kvalue.length = value->length;
+
+ code = krb5_authdata_set_attribute(context,
+ kname->ad_context,
+ complete,
+ &kattr,
+ &kvalue);
+
+ k5_mutex_unlock(&kname->lock);
+ krb5_free_context(context);
+
+ return kg_map_name_error(minor_status, code);
+}
+
+OM_uint32
+krb5_gss_delete_name_attribute(OM_uint32 *minor_status,
+ gss_name_t name,
+ gss_buffer_t attr)
+{
+ krb5_context context;
+ krb5_error_code code;
+ krb5_gss_name_t kname;
+ krb5_data kattr;
+
+ if (minor_status != NULL)
+ *minor_status = 0;
+
+ code = krb5_gss_init_context(&context);
+ if (code != 0) {
+ *minor_status = code;
+ return GSS_S_FAILURE;
+ }
+
+ if (!kg_validate_name(name)) {
+ *minor_status = (OM_uint32)G_VALIDATE_FAILED;
+ krb5_free_context(context);
+ return GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME;
+ }
+
+ kname = (krb5_gss_name_t)name;
+
+ code = k5_mutex_lock(&kname->lock);
+ if (code != 0) {
+ *minor_status = code;
+ return GSS_S_FAILURE;
+ }
+
+ if (kname->ad_context == NULL) {
+ code = krb5_authdata_context_init(context, &kname->ad_context);
+ if (code != 0) {
+ *minor_status = code;
+ k5_mutex_unlock(&kname->lock);
+ krb5_free_context(context);
+ return GSS_S_UNAVAILABLE;
+ }
+ }
+
+ kattr.data = (char *)attr->value;
+ kattr.length = attr->length;
+
+ code = krb5_authdata_delete_attribute(context,
+ kname->ad_context,
+ &kattr);
+
+ k5_mutex_unlock(&kname->lock);
+ krb5_free_context(context);
+
+ return kg_map_name_error(minor_status, code);
+}
+
+OM_uint32
+krb5_gss_map_name_to_any(OM_uint32 *minor_status,
+ gss_name_t name,
+ int authenticated,
+ gss_buffer_t type_id,
+ gss_any_t *output)
+{
+ krb5_context context;
+ krb5_error_code code;
+ krb5_gss_name_t kname;
+ char *kmodule;
+
+ if (minor_status != NULL)
+ *minor_status = 0;
+
+ code = krb5_gss_init_context(&context);
+ if (code != 0) {
+ *minor_status = code;
+ return GSS_S_FAILURE;
+ }
+
+ if (!kg_validate_name(name)) {
+ *minor_status = (OM_uint32)G_VALIDATE_FAILED;
+ krb5_free_context(context);
+ return GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME;
+ }
+
+ kname = (krb5_gss_name_t)name;
+
+ code = k5_mutex_lock(&kname->lock);
+ if (code != 0) {
+ *minor_status = code;
+ return GSS_S_FAILURE;
+ }
+
+ if (kname->ad_context == NULL) {
+ code = krb5_authdata_context_init(context, &kname->ad_context);
+ if (code != 0) {
+ *minor_status = code;
+ k5_mutex_unlock(&kname->lock);
+ krb5_free_context(context);
+ return GSS_S_UNAVAILABLE;
+ }
+ }
+
+ kmodule = (char *)type_id->value;
+ if (kmodule[type_id->length] != '\0') {
+ k5_mutex_unlock(&kname->lock);
+ krb5_free_context(context);
+ return GSS_S_UNAVAILABLE;
+ }
+
+ code = krb5_authdata_export_internal(context,
+ kname->ad_context,
+ authenticated,
+ kmodule,
+ (void **)output);
+
+ k5_mutex_unlock(&kname->lock);
+ krb5_free_context(context);
+
+ return kg_map_name_error(minor_status, code);
+}
+
+OM_uint32
+krb5_gss_release_any_name_mapping(OM_uint32 *minor_status,
+ gss_name_t name,
+ gss_buffer_t type_id,
+ gss_any_t *input)
+{
+ krb5_context context;
+ krb5_error_code code;
+ krb5_gss_name_t kname;
+ char *kmodule;
+
+ if (minor_status != NULL)
+ *minor_status = 0;
+
+ code = krb5_gss_init_context(&context);
+ if (code != 0) {
+ *minor_status = code;
+ return GSS_S_FAILURE;
+ }
+
+ if (!kg_validate_name(name)) {
+ *minor_status = (OM_uint32)G_VALIDATE_FAILED;
+ krb5_free_context(context);
+ return GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME;
+ }
+
+ kname = (krb5_gss_name_t)name;
+
+ code = k5_mutex_lock(&kname->lock);
+ if (code != 0) {
+ *minor_status = code;
+ return GSS_S_FAILURE;
+ }
+
+ if (kname->ad_context == NULL) {
+ code = krb5_authdata_context_init(context, &kname->ad_context);
+ if (code != 0) {
+ *minor_status = code;
+ k5_mutex_unlock(&kname->lock);
+ krb5_free_context(context);
+ return GSS_S_UNAVAILABLE;
+ }
+ }
+
+ kmodule = (char *)type_id->value;
+ if (kmodule[type_id->length] != '\0') {
+ k5_mutex_unlock(&kname->lock);
+ krb5_free_context(context);
+ return GSS_S_UNAVAILABLE;
+ }
+
+ code = krb5_authdata_free_internal(context,
+ kname->ad_context,
+ kmodule,
+ *input);
+ if (code == 0)
+ *input = NULL;
+
+ k5_mutex_unlock(&kname->lock);
+ krb5_free_context(context);
+
+ return kg_map_name_error(minor_status, code);
+
+}
+
+OM_uint32
+krb5_gss_export_name_composite(OM_uint32 *minor_status,
+ gss_name_t name,
+ gss_buffer_t exp_composite_name)
+{
+ krb5_context context;
+ krb5_error_code code;
+ krb5_gss_name_t kname;
+ krb5_data *attrs = NULL;
+ char *princstr = NULL;
+ unsigned char *cp;
+ size_t princlen;
+
+ if (minor_status != NULL)
+ *minor_status = 0;
+
+ code = krb5_gss_init_context(&context);
+ if (code != 0) {
+ *minor_status = code;
+ return GSS_S_FAILURE;
+ }
+
+ if (!kg_validate_name(name)) {
+ *minor_status = (OM_uint32)G_VALIDATE_FAILED;
+ krb5_free_context(context);
+ return GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME;
+ }
+
+ kname = (krb5_gss_name_t)name;
+
+ code = k5_mutex_lock(&kname->lock);
+ if (code != 0) {
+ *minor_status = code;
+ return GSS_S_FAILURE;
+ }
+
+ code = krb5_unparse_name(context, kname->princ, &princstr);
+ if (code != 0)
+ goto cleanup;
+
+ princlen = strlen(princstr);
+
+ if (kname->ad_context != NULL) {
+ code = krb5_authdata_export_attributes(context,
+ kname->ad_context,
+ AD_USAGE_MASK,
+ &attrs);
+ if (code != 0)
+ goto cleanup;
+ }
+
+ /* 04 02 OID Name AuthData */
+
+ exp_composite_name->length = 10 + gss_mech_krb5->length + princlen;
+ if (attrs != NULL)
+ exp_composite_name->length += 4 + attrs->length;
+ exp_composite_name->value = malloc(exp_composite_name->length);
+ if (exp_composite_name->value == NULL) {
+ code = ENOMEM;
+ goto cleanup;
+ }
+
+ cp = exp_composite_name->value;
+
+ /* Note: we assume the OID will be less than 128 bytes... */
+ *cp++ = 0x04;
+ if (attrs != NULL)
+ *cp++ = 0x02;
+ else
+ *cp++ = 0x01;
+
+ store_16_be(gss_mech_krb5->length + 2, cp);
+ cp += 2;
+ *cp++ = 0x06;
+ *cp++ = (gss_mech_krb5->length) & 0xFF;
+ memcpy(cp, gss_mech_krb5->elements, gss_mech_krb5->length);
+ cp += gss_mech_krb5->length;
+
+ store_32_be(princlen, cp);
+ cp += 4;
+ memcpy(cp, princstr, princlen);
+ cp += princlen;
+
+ if (attrs != NULL) {
+ store_32_be(attrs->length, cp);
+ cp += 4;
+ memcpy(cp, attrs->data, attrs->length);
+ cp += attrs->length;
+ }
+
+cleanup:
+ krb5_free_unparsed_name(context, princstr);
+ krb5_free_data(context, attrs);
+ k5_mutex_unlock(&kname->lock);
+ krb5_free_context(context);
+
+ return kg_map_name_error(minor_status, code);
+}
+
+#if 0
+OM_uint32
+krb5_gss_display_name_ext(OM_uint32 *minor_status,
+ gss_name_t name,
+ gss_OID display_as_name_type,
+ gss_buffer_t display_name)
+{
+}
+#endif
+
diff --git a/src/lib/gssapi/krb5/rel_cred.c b/src/lib/gssapi/krb5/rel_cred.c
index 833054326..b6b25887e 100644
--- a/src/lib/gssapi/krb5/rel_cred.c
+++ b/src/lib/gssapi/krb5/rel_cred.c
@@ -71,8 +71,8 @@ krb5_gss_release_cred(minor_status, cred_handle)
code3 = krb5_rc_close(context, cred->rcache);
else
code3 = 0;
- if (cred->princ)
- krb5_free_principal(context, cred->princ);
+ if (cred->name)
+ kg_release_name(context, 0, &cred->name);
if (cred->req_enctypes)
free(cred->req_enctypes);
diff --git a/src/lib/gssapi/krb5/rel_name.c b/src/lib/gssapi/krb5/rel_name.c
index 49d194448..5490b8a50 100644
--- a/src/lib/gssapi/krb5/rel_name.c
+++ b/src/lib/gssapi/krb5/rel_name.c
@@ -43,9 +43,8 @@ krb5_gss_release_name(minor_status, input_name)
return(GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME);
}
- (void)kg_delete_name(*input_name);
-
- krb5_free_principal(context, (krb5_principal) *input_name);
+ kg_release_name(context, KG_INIT_NAME_INTERN,
+ (krb5_gss_name_t *)input_name);
krb5_free_context(context);
*input_name = (gss_name_t) NULL;
diff --git a/src/lib/gssapi/krb5/s4u_gss_glue.c b/src/lib/gssapi/krb5/s4u_gss_glue.c
index 8e2d690b1..cae45039c 100644
--- a/src/lib/gssapi/krb5/s4u_gss_glue.c
+++ b/src/lib/gssapi/krb5/s4u_gss_glue.c
@@ -109,7 +109,7 @@ kg_is_initiator_cred(krb5_gss_cred_id_t cred)
static OM_uint32
kg_impersonate_name(OM_uint32 *minor_status,
const krb5_gss_cred_id_t impersonator_cred,
- const krb5_principal user,
+ const krb5_gss_name_t user,
OM_uint32 time_req,
const gss_OID_set desired_mechs,
krb5_gss_cred_id_t *output_cred,
@@ -124,18 +124,39 @@ kg_impersonate_name(OM_uint32 *minor_status,
memset(&in_creds, 0, sizeof(in_creds));
memset(&out_creds, 0, sizeof(out_creds));
- in_creds.client = user;
- in_creds.server = impersonator_cred->princ;
+ in_creds.client = user->princ;
+ in_creds.server = impersonator_cred->name->princ;
if (impersonator_cred->req_enctypes != NULL)
in_creds.keyblock.enctype = impersonator_cred->req_enctypes[0];
+ code = k5_mutex_lock(&user->lock);
+ if (code != 0) {
+ *minor_status = code;
+ return GSS_S_FAILURE;
+ }
+
+ if (user->ad_context != NULL) {
+ code = krb5_authdata_export_authdata(context,
+ user->ad_context,
+ AD_USAGE_TGS_REQ,
+ &in_creds.authdata);
+ if (code != 0) {
+ k5_mutex_unlock(&user->lock);
+ *minor_status = code;
+ return GSS_S_FAILURE;
+ }
+ }
+
+ k5_mutex_unlock(&user->lock);
+
code = krb5_get_credentials_for_user(context,
KRB5_GC_CANONICALIZE | KRB5_GC_NO_STORE,
impersonator_cred->ccache,
&in_creds,
NULL, &out_creds);
if (code != 0) {
+ krb5_free_authdata(context, in_creds.authdata);
*minor_status = code;
return GSS_S_FAILURE;
}
@@ -150,6 +171,7 @@ kg_impersonate_name(OM_uint32 *minor_status,
time_rec,
context);
+ krb5_free_authdata(context, in_creds.authdata);
krb5_free_creds(context, out_creds);
return major_status;
@@ -207,7 +229,7 @@ krb5_gss_acquire_cred_impersonate_name(OM_uint32 *minor_status,
major_status = kg_impersonate_name(minor_status,
(krb5_gss_cred_id_t)impersonator_cred_handle,
- (krb5_principal)desired_name,
+ (krb5_gss_name_t)desired_name,
time_req,
desired_mechs,
&cred,
@@ -242,12 +264,14 @@ kg_compose_deleg_cred(OM_uint32 *minor_status,
k5_mutex_assert_locked(&impersonator_cred->lock);
if (!kg_is_initiator_cred(impersonator_cred) ||
- impersonator_cred->princ == NULL ||
+ impersonator_cred->name == NULL ||
impersonator_cred->proxy_cred) {
code = G_BAD_USAGE;
goto cleanup;
}
+ assert(impersonator_cred->name->princ != NULL);
+
assert(subject_creds != NULL);
assert(subject_creds->client != NULL);
@@ -277,7 +301,7 @@ kg_compose_deleg_cred(OM_uint32 *minor_status,
cred->tgt_expire = impersonator_cred->tgt_expire;
- code = krb5_copy_principal(context, subject_creds->client, &cred->princ);
+ code = kg_init_name(context, subject_creds->client, NULL, 0, &cred->name);
if (code != 0)
goto cleanup;
@@ -286,8 +310,8 @@ kg_compose_deleg_cred(OM_uint32 *minor_status,
goto cleanup;
code = krb5_cc_initialize(context, cred->ccache,
- cred->proxy_cred ? impersonator_cred->princ :
- (krb5_principal)subject_creds->client);
+ cred->proxy_cred ? impersonator_cred->name->princ :
+ subject_creds->client);
if (code != 0)
goto cleanup;
@@ -334,10 +358,8 @@ cleanup:
if (GSS_ERROR(major_status) && cred != NULL) {
k5_mutex_destroy(&cred->lock);
- if (cred->ccache != NULL)
- krb5_cc_destroy(context, cred->ccache);
- if (cred->princ != NULL)
- krb5_free_principal(context, cred->princ);
+ krb5_cc_destroy(context, cred->ccache);
+ kg_release_name(context, 0, &cred->name);
xfree(cred);
}
diff --git a/src/lib/gssapi/krb5/ser_sctx.c b/src/lib/gssapi/krb5/ser_sctx.c
index 60ea9058c..9b55a6507 100644
--- a/src/lib/gssapi/krb5/ser_sctx.c
+++ b/src/lib/gssapi/krb5/ser_sctx.c
@@ -292,13 +292,13 @@ kg_ctx_size(kcontext, arg, sizep)
if (!kret && ctx->here)
kret = krb5_size_opaque(kcontext,
KV5M_PRINCIPAL,
- (krb5_pointer) ctx->here,
+ (krb5_pointer) ctx->here->princ,
&required);
if (!kret && ctx->there)
kret = krb5_size_opaque(kcontext,
KV5M_PRINCIPAL,
- (krb5_pointer) ctx->there,
+ (krb5_pointer) ctx->there->princ,
&required);
if (!kret && ctx->subkey)
@@ -352,7 +352,18 @@ kg_ctx_size(kcontext, arg, sizep)
&required);
}
}
- if (!kret)
+ if (!kret) {
+ krb5_gss_name_t initiator_name;
+
+ initiator_name = ctx->initiate ? ctx->here : ctx->there;
+
+ if (initiator_name) {
+ kret = krb5_size_opaque(kcontext,
+ KV5M_AUTHDATA_CONTEXT,
+ initiator_name->ad_context,
+ &required);
+ }
+ }
*sizep += required;
}
return(kret);
@@ -437,13 +448,13 @@ kg_ctx_externalize(kcontext, arg, buffer, lenremain)
if (!kret && ctx->here)
kret = krb5_externalize_opaque(kcontext,
KV5M_PRINCIPAL,
- (krb5_pointer) ctx->here,
+ (krb5_pointer) ctx->here->princ,
&bp, &remain);
if (!kret && ctx->there)
kret = krb5_externalize_opaque(kcontext,
KV5M_PRINCIPAL,
- (krb5_pointer) ctx->there,
+ (krb5_pointer) ctx->there->princ,
&bp, &remain);
if (!kret && ctx->subkey)
@@ -517,6 +528,20 @@ kg_ctx_externalize(kcontext, arg, buffer, lenremain)
&remain);
}
}
+ /* authdata context */
+ if (!kret) {
+ krb5_gss_name_t initiator_name;
+
+ initiator_name = ctx->initiate ? ctx->here : ctx->there;
+
+ if (initiator_name) {
+ kret = krb5_externalize_opaque(kcontext,
+ KV5M_AUTHDATA_CONTEXT,
+ initiator_name->ad_context,
+ &bp,
+ &remain);
+ }
+ }
/* trailer */
if (!kret)
kret = krb5_ser_pack_int32(KG_CONTEXT, &bp, &remain);
@@ -545,6 +570,7 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain)
krb5_octet *bp;
size_t remain;
krb5int_access kaccess;
+ krb5_principal princ;
kret = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION);
if (kret)
@@ -553,6 +579,7 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain)
bp = *buffer;
remain = *lenremain;
kret = EINVAL;
+ princ = NULL;
/* Read our magic number */
if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
ibuf = 0;
@@ -618,19 +645,28 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain)
kret = 0;
}
/* Now get substructure data */
- if ((kret = krb5_internalize_opaque(kcontext,
- KV5M_PRINCIPAL,
- (krb5_pointer *) &ctx->here,
- &bp, &remain))) {
- if (kret == EINVAL)
- kret = 0;
- }
- if (!kret &&
- (kret = krb5_internalize_opaque(kcontext,
- KV5M_PRINCIPAL,
- (krb5_pointer *) &ctx->there,
- &bp, &remain))) {
- if (kret == EINVAL)
+ kret = krb5_internalize_opaque(kcontext,
+ KV5M_PRINCIPAL,
+ (krb5_pointer *) &princ,
+ &bp, &remain);
+ if (kret == 0) {
+ kret = kg_init_name(kcontext, princ, NULL,
+ KG_INIT_NAME_NO_COPY, &ctx->here);
+ if (kret)
+ krb5_free_principal(kcontext, princ);
+ } else if (kret == EINVAL)
+ kret = 0;
+ if (!kret) {
+ kret = krb5_internalize_opaque(kcontext,
+ KV5M_PRINCIPAL,
+ (krb5_pointer *) &princ,
+ &bp, &remain);
+ if (kret == 0) {
+ kret = kg_init_name(kcontext, princ, NULL,
+ KG_INIT_NAME_NO_COPY, &ctx->there);
+ if (kret)
+ krb5_free_principal(kcontext, princ);
+ } else if (kret == EINVAL)
kret = 0;
}
if (!kret &&
@@ -718,6 +754,21 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain)
}
}
}
+ /* authdata context */
+ if (!kret) {
+ krb5_gss_name_t initiator_name;
+
+ initiator_name = ctx->initiate ? ctx->here : ctx->there;
+ if (initiator_name == NULL) {
+ kret = EINVAL;
+ } else {
+ kret = krb5_internalize_opaque(kcontext,
+ KV5M_AUTHDATA_CONTEXT,
+ (krb5_pointer *)&initiator_name->ad_context,
+ &bp,
+ &remain);
+ }
+ }
/* Get trailer */
if (!kret)
kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
@@ -736,9 +787,9 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain)
if (ctx->subkey)
krb5_free_keyblock(kcontext, ctx->subkey);
if (ctx->there)
- krb5_free_principal(kcontext, ctx->there);
+ kg_release_name(kcontext, 0, &ctx->there);
if (ctx->here)
- krb5_free_principal(kcontext, ctx->here);
+ kg_release_name(kcontext, 0, &ctx->here);
xfree(ctx);
}
}
diff --git a/src/lib/gssapi/krb5/val_cred.c b/src/lib/gssapi/krb5/val_cred.c
index 43b1f695d..747d8222e 100644
--- a/src/lib/gssapi/krb5/val_cred.c
+++ b/src/lib/gssapi/krb5/val_cred.c
@@ -59,7 +59,7 @@ krb5_gss_validate_cred_1(OM_uint32 *minor_status, gss_cred_id_t cred_handle,
return(GSS_S_DEFECTIVE_CREDENTIAL);
}
if (!cred->proxy_cred &&
- !krb5_principal_compare(context, princ, cred->princ)) {
+ !krb5_principal_compare(context, princ, cred->name->princ)) {
k5_mutex_unlock(&cred->lock);
*minor_status = KG_CCACHE_NOMATCH;
return(GSS_S_DEFECTIVE_CREDENTIAL);