diff options
Diffstat (limited to 'src/lib/gssapi/krb5')
-rw-r--r-- | src/lib/gssapi/krb5/Makefile.in | 3 | ||||
-rw-r--r-- | src/lib/gssapi/krb5/accept_sec_context.c | 57 | ||||
-rw-r--r-- | src/lib/gssapi/krb5/acquire_cred.c | 87 | ||||
-rw-r--r-- | src/lib/gssapi/krb5/add_cred.c | 39 | ||||
-rw-r--r-- | src/lib/gssapi/krb5/compare_name.c | 5 | ||||
-rw-r--r-- | src/lib/gssapi/krb5/delete_sec_context.c | 4 | ||||
-rw-r--r-- | src/lib/gssapi/krb5/disp_name.c | 3 | ||||
-rw-r--r-- | src/lib/gssapi/krb5/duplicate_name.c | 15 | ||||
-rw-r--r-- | src/lib/gssapi/krb5/export_name.c | 2 | ||||
-rw-r--r-- | src/lib/gssapi/krb5/gssapiP_krb5.h | 93 | ||||
-rw-r--r-- | src/lib/gssapi/krb5/gssapi_krb5.c | 8 | ||||
-rw-r--r-- | src/lib/gssapi/krb5/import_name.c | 106 | ||||
-rw-r--r-- | src/lib/gssapi/krb5/init_sec_context.c | 61 | ||||
-rw-r--r-- | src/lib/gssapi/krb5/inq_context.c | 34 | ||||
-rw-r--r-- | src/lib/gssapi/krb5/inq_cred.c | 20 | ||||
-rw-r--r-- | src/lib/gssapi/krb5/naming_exts.c | 722 | ||||
-rw-r--r-- | src/lib/gssapi/krb5/rel_cred.c | 4 | ||||
-rw-r--r-- | src/lib/gssapi/krb5/rel_name.c | 5 | ||||
-rw-r--r-- | src/lib/gssapi/krb5/s4u_gss_glue.c | 46 | ||||
-rw-r--r-- | src/lib/gssapi/krb5/ser_sctx.c | 91 | ||||
-rw-r--r-- | src/lib/gssapi/krb5/val_cred.c | 2 |
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); |