diff options
| author | Greg Hudson <ghudson@mit.edu> | 2009-10-09 18:29:34 +0000 |
|---|---|---|
| committer | Greg Hudson <ghudson@mit.edu> | 2009-10-09 18:29:34 +0000 |
| commit | 17ffdd0e93271072369e479f440ddf85e020580a (patch) | |
| tree | cdaf4944a478128a1d53d854063a7d809b7c6aae /src/lib/gssapi | |
| parent | 6ad74ac369b09df7d29ca8e09b0af946b4819523 (diff) | |
| download | krb5-17ffdd0e93271072369e479f440ddf85e020580a.tar.gz krb5-17ffdd0e93271072369e479f440ddf85e020580a.tar.xz krb5-17ffdd0e93271072369e479f440ddf85e020580a.zip | |
Implement GSS naming extensions and authdata verification
Merge Luke's users/lhoward/authdata branch to trunk. Implements GSS naming
extensions and verification of authorization data.
ticket: 6572
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@22875 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/lib/gssapi')
43 files changed, 2369 insertions, 251 deletions
diff --git a/src/lib/gssapi/generic/gssapi_ext.h b/src/lib/gssapi/generic/gssapi_ext.h index ce115639b..12216775a 100644 --- a/src/lib/gssapi/generic/gssapi_ext.h +++ b/src/lib/gssapi/generic/gssapi_ext.h @@ -254,7 +254,6 @@ OM_uint32 KRB5_CALLCONV gss_release_iov_buffer gss_iov_buffer_desc *, /* iov */ int); /* iov_count */ - /* * Protocol transition */ @@ -285,6 +284,80 @@ gss_add_cred_impersonate_name( OM_uint32 *, /* initiator_time_rec */ OM_uint32 *); /* acceptor_time_rec */ +/* + * Naming extensions + */ +OM_uint32 KRB5_CALLCONV 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_CALLCONV 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_CALLCONV 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_CALLCONV 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_CALLCONV gss_delete_name_attribute +( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + gss_buffer_t /* attr */ +); + +OM_uint32 KRB5_CALLCONV gss_export_name_composite +( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + gss_buffer_t /* exp_composite_name */ +); + +typedef struct gss_any *gss_any_t; + +OM_uint32 KRB5_CALLCONV 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_CALLCONV gss_release_any_name_mapping +( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + gss_buffer_t, /* type_id */ + gss_any_t * /* input */ +); + #ifdef __cplusplus } #endif 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); diff --git a/src/lib/gssapi/libgssapi_krb5.exports b/src/lib/gssapi/libgssapi_krb5.exports index d641fc65b..60754df7a 100644 --- a/src/lib/gssapi/libgssapi_krb5.exports +++ b/src/lib/gssapi/libgssapi_krb5.exports @@ -20,13 +20,17 @@ gss_complete_auth_token gss_context_time gss_create_empty_buffer_set gss_create_empty_oid_set +gss_delete_name_attribute gss_delete_sec_context gss_display_name +gss_display_name_ext gss_display_status gss_duplicate_name gss_export_name +gss_export_name_composite gss_export_sec_context gss_get_mic +gss_get_name_attribute gss_import_name gss_import_sec_context gss_indicate_mechs @@ -49,6 +53,7 @@ gss_krb5int_make_seal_token_v3 gss_krb5int_unseal_token_v3 gsskrb5_extract_authtime_from_sec_context gsskrb5_extract_authz_data_from_sec_context +gss_map_name_to_any gss_mech_krb5 gss_mech_krb5_old gss_mech_set_krb5 @@ -64,6 +69,7 @@ gss_nt_string_uid_name gss_nt_user_name gss_oid_to_str gss_process_context_token +gss_release_any_name_mapping gss_release_buffer_set gss_release_buffer gss_release_cred @@ -72,6 +78,7 @@ gss_release_name gss_release_oid gss_release_oid_set gss_seal +gss_set_name_attribute gss_set_sec_context_option gss_sign gss_str_to_oid @@ -92,3 +99,4 @@ gssspi_mech_invoke krb5_gss_dbg_client_expcreds krb5_gss_register_acceptor_identity krb5_gss_use_kdc_context +gss_inquire_name diff --git a/src/lib/gssapi/mechglue/Makefile.in b/src/lib/gssapi/mechglue/Makefile.in index 18e89f19d..61972ab75 100644 --- a/src/lib/gssapi/mechglue/Makefile.in +++ b/src/lib/gssapi/mechglue/Makefile.in @@ -21,11 +21,15 @@ SRCS = \ $(srcdir)/g_complete_auth_token.c \ $(srcdir)/g_context_time.c \ $(srcdir)/g_delete_sec_context.c \ + $(srcdir)/g_del_name_attr.c \ $(srcdir)/g_dsp_name.c \ + $(srcdir)/g_dsp_name_ext.c \ $(srcdir)/g_dsp_status.c \ $(srcdir)/g_dup_name.c \ $(srcdir)/g_exp_sec_context.c \ $(srcdir)/g_export_name.c \ + $(srcdir)/g_export_name_comp.c \ + $(srcdir)/g_get_name_attr.c \ $(srcdir)/g_glue.c \ $(srcdir)/g_imp_name.c \ $(srcdir)/g_imp_sec_context.c \ @@ -35,7 +39,9 @@ SRCS = \ $(srcdir)/g_inq_context_oid.c \ $(srcdir)/g_inq_cred.c \ $(srcdir)/g_inq_cred_oid.c \ + $(srcdir)/g_inq_name.c \ $(srcdir)/g_inq_names.c \ + $(srcdir)/g_map_name_to_any.c \ $(srcdir)/g_mech_invoke.c \ $(srcdir)/g_mechname.c \ $(srcdir)/g_oid_ops.c \ @@ -43,10 +49,12 @@ SRCS = \ $(srcdir)/g_rel_buffer.c \ $(srcdir)/g_rel_cred.c \ $(srcdir)/g_rel_name.c \ + $(srcdir)/g_rel_name_mapping.c \ $(srcdir)/g_rel_oid_set.c \ $(srcdir)/g_seal.c \ $(srcdir)/g_set_context_option.c \ $(srcdir)/g_set_cred_option.c \ + $(srcdir)/g_set_name_attr.c \ $(srcdir)/g_sign.c \ $(srcdir)/g_store_cred.c \ $(srcdir)/g_unseal.c \ @@ -66,11 +74,15 @@ OBJS = \ $(OUTPRE)g_complete_auth_token.$(OBJEXT) \ $(OUTPRE)g_context_time.$(OBJEXT) \ $(OUTPRE)g_delete_sec_context.$(OBJEXT) \ + $(OUTPRE)g_del_name_attr.$(OBJEXT) \ $(OUTPRE)g_dsp_name.$(OBJEXT) \ + $(OUTPRE)g_dsp_name_ext.$(OBJEXT) \ $(OUTPRE)g_dsp_status.$(OBJEXT) \ $(OUTPRE)g_dup_name.$(OBJEXT) \ $(OUTPRE)g_exp_sec_context.$(OBJEXT) \ $(OUTPRE)g_export_name.$(OBJEXT) \ + $(OUTPRE)g_export_name_comp.$(OBJEXT) \ + $(OUTPRE)g_get_name_attr.$(OBJEXT) \ $(OUTPRE)g_glue.$(OBJEXT) \ $(OUTPRE)g_imp_name.$(OBJEXT) \ $(OUTPRE)g_imp_sec_context.$(OBJEXT) \ @@ -80,7 +92,9 @@ OBJS = \ $(OUTPRE)g_inq_context_oid.$(OBJEXT) \ $(OUTPRE)g_inq_cred.$(OBJEXT) \ $(OUTPRE)g_inq_cred_oid.$(OBJEXT) \ + $(OUTPRE)g_inq_name.$(OBJEXT) \ $(OUTPRE)g_inq_names.$(OBJEXT) \ + $(OUTPRE)g_map_name_to_any.$(OBJEXT) \ $(OUTPRE)g_mech_invoke.$(OBJEXT) \ $(OUTPRE)g_mechname.$(OBJEXT) \ $(OUTPRE)g_oid_ops.$(OBJEXT) \ @@ -88,10 +102,12 @@ OBJS = \ $(OUTPRE)g_rel_buffer.$(OBJEXT) \ $(OUTPRE)g_rel_cred.$(OBJEXT) \ $(OUTPRE)g_rel_name.$(OBJEXT) \ + $(OUTPRE)g_rel_name_mapping.$(OBJEXT) \ $(OUTPRE)g_rel_oid_set.$(OBJEXT) \ $(OUTPRE)g_seal.$(OBJEXT) \ $(OUTPRE)g_set_context_option.$(OBJEXT) \ $(OUTPRE)g_set_cred_option.$(OBJEXT) \ + $(OUTPRE)g_set_name_attr.$(OBJEXT) \ $(OUTPRE)g_sign.$(OBJEXT) \ $(OUTPRE)g_store_cred.$(OBJEXT) \ $(OUTPRE)g_unseal.$(OBJEXT) \ @@ -111,11 +127,15 @@ STLIBOBJS = \ g_complete_auth_token.o \ g_context_time.o \ g_delete_sec_context.o \ + g_del_name_attr.o \ g_dsp_name.o \ + g_dsp_name_ext.o \ g_dsp_status.o \ g_dup_name.o \ g_exp_sec_context.o \ g_export_name.o \ + g_export_name_comp.o \ + g_get_name_attr.o \ g_glue.o \ g_imp_name.o \ g_imp_sec_context.o \ @@ -125,7 +145,9 @@ STLIBOBJS = \ g_inq_context_oid.o \ g_inq_cred.o \ g_inq_cred_oid.o \ + g_inq_name.o \ g_inq_names.o \ + g_map_name_to_any.o \ g_mech_invoke.o \ g_mechname.o \ g_oid_ops.o \ @@ -133,10 +155,12 @@ STLIBOBJS = \ g_rel_buffer.o \ g_rel_cred.o \ g_rel_name.o \ + g_rel_name_mapping.o \ g_rel_oid_set.o \ g_seal.o \ g_set_context_option.o \ g_set_cred_option.o \ + g_set_name_attr.o \ g_sign.o \ g_store_cred.o \ g_unseal.o \ diff --git a/src/lib/gssapi/mechglue/g_del_name_attr.c b/src/lib/gssapi/mechglue/g_del_name_attr.c new file mode 100644 index 000000000..4c5064217 --- /dev/null +++ b/src/lib/gssapi/mechglue/g_del_name_attr.c @@ -0,0 +1,70 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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. + * + */ + +/* + * glue routine for gss_delete_name_attribute + */ + +#include "mglueP.h" + +OM_uint32 KRB5_CALLCONV +gss_delete_name_attribute(OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t attr) +{ + OM_uint32 status; + gss_union_name_t union_name; + gss_mechanism mech; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + if (name == GSS_C_NO_NAME) + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME; + + *minor_status = 0; + + union_name = (gss_union_name_t)name; + + if (union_name->mech_type == GSS_C_NO_OID) + return GSS_S_UNAVAILABLE; + + mech = gssint_get_mechanism(name->mech_type); + if (mech == NULL) + return GSS_S_BAD_NAME; + + if (mech->gss_delete_name_attribute == NULL) + return GSS_S_UNAVAILABLE; + + status = (*mech->gss_delete_name_attribute)(minor_status, + union_name->mech_name, + attr); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + + return status; +} + diff --git a/src/lib/gssapi/mechglue/g_dsp_name.c b/src/lib/gssapi/mechglue/g_dsp_name.c index 7efd583f8..2540f21c0 100644 --- a/src/lib/gssapi/mechglue/g_dsp_name.c +++ b/src/lib/gssapi/mechglue/g_dsp_name.c @@ -1,8 +1,7 @@ /* #pragma ident "@(#)g_dsp_name.c 1.13 04/02/23 SMI" */ - /* * Copyright 1996 by Sun Microsystems, Inc. - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appears in all copies and @@ -12,7 +11,7 @@ * without specific, written prior permission. Sun Microsystems makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. - * + * * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR @@ -102,7 +101,7 @@ gss_OID * output_name_type; output_name_buffer, output_name_type)); } - + /* * copy the value of the external_name component of the union * name into the output_name_buffer and point the output_name_type diff --git a/src/lib/gssapi/mechglue/g_dsp_name_ext.c b/src/lib/gssapi/mechglue/g_dsp_name_ext.c new file mode 100644 index 000000000..14326a30f --- /dev/null +++ b/src/lib/gssapi/mechglue/g_dsp_name_ext.c @@ -0,0 +1,131 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine for gss_display_name_ext() + * + */ + +#include "mglueP.h" +#include <stdio.h> +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#include <string.h> + +static OM_uint32 +val_dsp_name_ext_args( + OM_uint32 *minor_status, + gss_name_t input_name, + gss_OID display_as_name_type, + gss_buffer_t output_name_buffer) +{ + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 0; + + if (output_name_buffer != GSS_C_NO_BUFFER) { + output_name_buffer->length = 0; + output_name_buffer->value = NULL; + } + + /* Validate arguments. */ + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + if (output_name_buffer == GSS_C_NO_BUFFER) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + if (input_name == GSS_C_NO_NAME) + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME; + + if (display_as_name_type == GSS_C_NO_OID) + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAMETYPE; + + return GSS_S_COMPLETE; +} + + +OM_uint32 KRB5_CALLCONV +gss_display_name_ext (OM_uint32 *minor_status, + gss_name_t input_name, + gss_OID display_as_name_type, + gss_buffer_t output_name_buffer) +{ + OM_uint32 status; + gss_union_name_t union_name; + gss_mechanism mech; + + status = val_dsp_name_ext_args(minor_status, + input_name, + display_as_name_type, + output_name_buffer); + if (status != GSS_S_COMPLETE) + return status; + + union_name = (gss_union_name_t) input_name; + + if (union_name->mech_type) { + mech = gssint_get_mechanism(union_name->mech_type); + if (mech == NULL) + status = GSS_S_BAD_NAME; + else if (mech->gss_display_name_ext == NULL) { + if (mech->gss_display_name != NULL && + g_OID_equal(display_as_name_type, union_name->name_type)) { + status = (*mech->gss_display_name)(minor_status, + union_name->mech_name, + output_name_buffer, + NULL); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else + status = GSS_S_UNAVAILABLE; + } else { + status = (*mech->gss_display_name_ext)(minor_status, + union_name->mech_name, + display_as_name_type, + output_name_buffer); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } + return status; + } + + if (!g_OID_equal(display_as_name_type, union_name->name_type)) + return GSS_S_UNAVAILABLE; + + if ((output_name_buffer->value = + malloc(union_name->external_name->length + 1)) == NULL) { + return GSS_S_FAILURE; + } + output_name_buffer->length = union_name->external_name->length; + (void) memcpy(output_name_buffer->value, + union_name->external_name->value, + union_name->external_name->length); + ((char *)output_name_buffer->value)[output_name_buffer->length] = '\0'; + + return GSS_S_COMPLETE; +} diff --git a/src/lib/gssapi/mechglue/g_export_name_comp.c b/src/lib/gssapi/mechglue/g_export_name_comp.c new file mode 100644 index 000000000..24eaf247e --- /dev/null +++ b/src/lib/gssapi/mechglue/g_export_name_comp.c @@ -0,0 +1,73 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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. + * + */ + +/* + * glue routine for gss_export_name_composite + */ + +#include "mglueP.h" + +OM_uint32 KRB5_CALLCONV +gss_export_name_composite(OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t exp_composite_name) +{ + OM_uint32 status; + gss_union_name_t union_name; + gss_mechanism mech; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + if (name == GSS_C_NO_NAME) + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME; + + if (exp_composite_name == GSS_C_NO_BUFFER) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *minor_status = 0; + + union_name = (gss_union_name_t)name; + + if (union_name->mech_type == GSS_C_NO_OID) + return GSS_S_UNAVAILABLE; + + mech = gssint_get_mechanism(name->mech_type); + if (mech == NULL) + return GSS_S_BAD_NAME; + + if (mech->gss_export_name_composite == NULL) + return GSS_S_UNAVAILABLE; + + status = (*mech->gss_export_name_composite)(minor_status, + union_name->mech_name, + exp_composite_name); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + + return status; +} + diff --git a/src/lib/gssapi/mechglue/g_get_name_attr.c b/src/lib/gssapi/mechglue/g_get_name_attr.c new file mode 100644 index 000000000..66238f0aa --- /dev/null +++ b/src/lib/gssapi/mechglue/g_get_name_attr.c @@ -0,0 +1,89 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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. + * + */ + +/* + * glue routine for gss_get_name_attribute + */ + +#include "mglueP.h" + +OM_uint32 KRB5_CALLCONV +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 status; + gss_union_name_t union_name; + gss_mechanism mech; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + if (name == GSS_C_NO_NAME) + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME; + if (attr == GSS_C_NO_BUFFER) + return GSS_S_CALL_INACCESSIBLE_READ; + if (more == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + if (authenticated != NULL) + *authenticated = 0; + if (complete != NULL) + *complete = 0; + + *minor_status = 0; + + union_name = (gss_union_name_t)name; + + if (union_name->mech_type == GSS_C_NO_OID) + return GSS_S_UNAVAILABLE; + + mech = gssint_get_mechanism(name->mech_type); + if (mech == NULL) + return GSS_S_BAD_NAME; + + if (mech->gss_get_name_attribute == NULL) + return GSS_S_UNAVAILABLE; + + status = (*mech->gss_get_name_attribute)(minor_status, + union_name->mech_name, + attr, + authenticated, + complete, + value, + display_value, + more); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + + return status; +} + diff --git a/src/lib/gssapi/mechglue/g_glue.c b/src/lib/gssapi/mechglue/g_glue.c index 4d35819c5..711c58fd8 100644 --- a/src/lib/gssapi/mechglue/g_glue.c +++ b/src/lib/gssapi/mechglue/g_glue.c @@ -288,7 +288,46 @@ OM_uint32 gssint_get_mech_type(OID, token) * Internal routines to get and release an internal mechanism name */ -#include "mglueP.h" +#if 0 +static OM_uint32 +import_internal_name_composite(OM_uint32 *minor_status, + gss_mechanism mech, + gss_union_name_t union_name, + gss_name_t *internal_name) +{ + OM_uint32 status, tmp; + gss_mechanism name_mech; + gss_buffer_desc composite_name; + + if (mech->gss_import_name == NULL) + return (GSS_S_UNAVAILABLE); + + name_mech = gssint_get_mechanism(union_name->mech_type); + if (name_mech == NULL) + return (GSS_S_BAD_MECH); + + if (name_mech->gss_export_name_composite == NULL) + return (GSS_S_UNAVAILABLE); + + composite_name.length = 0; + composite_name.value = NULL; + + status = (*name_mech->gss_export_name_composite)(minor_status, + union_name->mech_name, + &composite_name); + if (GSS_ERROR(status)) + return (status); + + status = (*mech->gss_import_name)(minor_status, + &composite_name, + gss_nt_exported_name, + internal_name); + + gss_release_buffer(&tmp, &composite_name); + + return (status); +} +#endif OM_uint32 gssint_import_internal_name (minor_status, mech_type, union_name, internal_name) @@ -301,22 +340,32 @@ gss_name_t *internal_name; gss_mechanism mech; mech = gssint_get_mechanism (mech_type); - if (mech) { - if (mech->gss_import_name) { - status = mech->gss_import_name ( - minor_status, - union_name->external_name, - union_name->name_type, - internal_name); - if (status != GSS_S_COMPLETE) - map_error(minor_status, mech); - } else - status = GSS_S_UNAVAILABLE; + if (mech == NULL) + return (GSS_S_BAD_MECH); - return (status); +#if 0 + /* Try composite name, it will preserve any extended attributes */ + if (union_name->mech_type && union_name->mech_name) { + status = import_internal_name_composite(minor_status, + mech, + union_name, + internal_name); + if (status == GSS_S_COMPLETE) + return (GSS_S_COMPLETE); } +#endif - return (GSS_S_BAD_MECH); + if (mech->gss_import_name == NULL) + return (GSS_S_UNAVAILABLE); + + status = mech->gss_import_name(minor_status, + union_name->external_name, + union_name->name_type, + internal_name); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + + return (status); } OM_uint32 gssint_export_internal_name(minor_status, mech_type, diff --git a/src/lib/gssapi/mechglue/g_imp_name.c b/src/lib/gssapi/mechglue/g_imp_name.c index c4767bf3e..6137b9825 100644 --- a/src/lib/gssapi/mechglue/g_imp_name.c +++ b/src/lib/gssapi/mechglue/g_imp_name.c @@ -176,7 +176,6 @@ allocation_failure: /* * GSS export name constants */ -static const char *expNameTokId = "\x04\x01"; static const unsigned int expNameTokIdLen = 2; static const unsigned int mechOidLenLen = 2; static const unsigned int nameTypeLenLen = 2; @@ -201,7 +200,9 @@ importExportName(minor, unionName) return (GSS_S_DEFECTIVE_TOKEN); buf = (unsigned char *)expName.value; - if (memcmp(expNameTokId, buf, expNameTokIdLen) != 0) + if (buf[0] != 0x04) + return (GSS_S_DEFECTIVE_TOKEN); + if (buf[1] != 0x01 && buf[1] != 0x02) return (GSS_S_DEFECTIVE_TOKEN); buf += expNameTokIdLen; diff --git a/src/lib/gssapi/mechglue/g_initialize.c b/src/lib/gssapi/mechglue/g_initialize.c index e34b7bf0a..41aa6821b 100644 --- a/src/lib/gssapi/mechglue/g_initialize.c +++ b/src/lib/gssapi/mechglue/g_initialize.c @@ -761,9 +761,18 @@ build_dynamicMech(void *dl, const gss_OID mech_type) GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_unwrap_iov); GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_wrap_iov_length); GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_complete_auth_token); - /* New for 1.8 */ + /* Services4User (introduced in 1.8) */ GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_acquire_cred_impersonate_name); GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_add_cred_impersonate_name); + /* Naming extensions (introduced in 1.8) */ + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_display_name_ext); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_inquire_name); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_get_name_attribute); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_set_name_attribute); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_delete_name_attribute); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_export_name_composite); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_map_name_to_any); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_release_any_name_mapping); assert(mech_type != GSS_C_NO_OID); diff --git a/src/lib/gssapi/mechglue/g_inq_context_oid.c b/src/lib/gssapi/mechglue/g_inq_context_oid.c index 50bfcb561..379ec419c 100644 --- a/src/lib/gssapi/mechglue/g_inq_context_oid.c +++ b/src/lib/gssapi/mechglue/g_inq_context_oid.c @@ -62,11 +62,11 @@ gss_inquire_sec_context_by_oid (OM_uint32 *minor_status, if (status != GSS_S_COMPLETE) map_error(minor_status, mech); } else - status = GSS_S_BAD_MECH; + status = GSS_S_UNAVAILABLE; return status; } - return GSS_S_NO_CONTEXT; + return GSS_S_BAD_MECH; } diff --git a/src/lib/gssapi/mechglue/g_inq_cred_oid.c b/src/lib/gssapi/mechglue/g_inq_cred_oid.c index 34056f6bd..c2cc27d33 100644 --- a/src/lib/gssapi/mechglue/g_inq_cred_oid.c +++ b/src/lib/gssapi/mechglue/g_inq_cred_oid.c @@ -93,15 +93,19 @@ gss_inquire_cred_by_oid(OM_uint32 *minor_status, return status; } - status = GSS_S_BAD_MECH; + status = GSS_S_UNAVAILABLE; for (i = 0; i < union_cred->count; i++) { mech = gssint_get_mechanism(&union_cred->mechs_array[i]); - if (mech == NULL) - continue; + if (mech == NULL) { + status = GSS_S_BAD_MECH; + break; + } - if (mech->gss_inquire_cred_by_oid == NULL) + if (mech->gss_inquire_cred_by_oid == NULL) { + status = GSS_S_UNAVAILABLE; continue; + } status = (mech->gss_inquire_cred_by_oid)(minor_status, union_cred->cred_array[i], diff --git a/src/lib/gssapi/mechglue/g_inq_name.c b/src/lib/gssapi/mechglue/g_inq_name.c new file mode 100644 index 000000000..260ef20c6 --- /dev/null +++ b/src/lib/gssapi/mechglue/g_inq_name.c @@ -0,0 +1,101 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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. + * + */ + +/* + * glue routine for gss_inquire_name + */ + +#include "mglueP.h" + +OM_uint32 KRB5_CALLCONV +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 status, tmp; + gss_union_name_t union_name; + gss_mechanism mech; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + if (name == GSS_C_NO_NAME) + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME; + + if (MN_mech != NULL) + *MN_mech = GSS_C_NO_OID; + + if (attrs != NULL) + *attrs = GSS_C_NO_BUFFER_SET; + + *minor_status = 0; + union_name = (gss_union_name_t)name; + + if (union_name->mech_type == GSS_C_NO_OID) { + /* We don't yet support non-mechanism attributes */ + if (name_is_MN != NULL) + name_is_MN = 0; + *minor_status = 0; + return GSS_S_COMPLETE; + } + + if (name_is_MN != NULL) + *name_is_MN = 1; + + if (MN_mech != NULL) { + status = generic_gss_copy_oid(minor_status, + union_name->mech_type, + MN_mech); + if (GSS_ERROR(status)) + return status; + } + + mech = gssint_get_mechanism(name->mech_type); + if (mech == NULL) { + gss_release_oid(&tmp, MN_mech); + return GSS_S_BAD_NAME; + } + + if (mech->gss_inquire_name == NULL) { + gss_release_oid(&tmp, MN_mech); + return GSS_S_UNAVAILABLE; + } + + status = (*mech->gss_inquire_name)(minor_status, + union_name->mech_name, + NULL, + NULL, + attrs); + if (status != GSS_S_COMPLETE) { + generic_gss_release_oid(&tmp, MN_mech); + map_error(minor_status, mech); + } + + return status; +} + diff --git a/src/lib/gssapi/mechglue/g_map_name_to_any.c b/src/lib/gssapi/mechglue/g_map_name_to_any.c new file mode 100644 index 000000000..b0fa2be64 --- /dev/null +++ b/src/lib/gssapi/mechglue/g_map_name_to_any.c @@ -0,0 +1,80 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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. + * + */ + +/* + * glue routine for gss_map_name_to_any + */ + +#include "mglueP.h" + +OM_uint32 KRB5_CALLCONV +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 status; + gss_union_name_t union_name; + gss_mechanism mech; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + if (name == GSS_C_NO_NAME) + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME; + + if (type_id == GSS_C_NO_BUFFER) + return GSS_S_CALL_INACCESSIBLE_READ; + + if (output == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *minor_status = 0; + + union_name = (gss_union_name_t)name; + + if (union_name->mech_type == GSS_C_NO_OID) + return GSS_S_UNAVAILABLE; + + mech = gssint_get_mechanism(name->mech_type); + if (mech == NULL) + return GSS_S_BAD_NAME; + + if (mech->gss_map_name_to_any == NULL) + return GSS_S_UNAVAILABLE; + + status = (*mech->gss_map_name_to_any)(minor_status, + union_name->mech_name, + authenticated, + type_id, + output); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + + return status; +} + diff --git a/src/lib/gssapi/mechglue/g_rel_name_mapping.c b/src/lib/gssapi/mechglue/g_rel_name_mapping.c new file mode 100644 index 000000000..b9159a115 --- /dev/null +++ b/src/lib/gssapi/mechglue/g_rel_name_mapping.c @@ -0,0 +1,78 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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. + * + */ + +/* + * glue routine for gss_release_any_name_mapping + */ + +#include "mglueP.h" + +OM_uint32 KRB5_CALLCONV +gss_release_any_name_mapping(OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t type_id, + gss_any_t *input) +{ + OM_uint32 status; + gss_union_name_t union_name; + gss_mechanism mech; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + if (name == GSS_C_NO_NAME) + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME; + + if (type_id == GSS_C_NO_BUFFER) + return GSS_S_CALL_INACCESSIBLE_READ; + + if (input == NULL) + return GSS_S_CALL_INACCESSIBLE_READ; + + *minor_status = 0; + + union_name = (gss_union_name_t)name; + + if (union_name->mech_type == GSS_C_NO_OID) + return GSS_S_UNAVAILABLE; + + mech = gssint_get_mechanism(name->mech_type); + if (mech == NULL) + return GSS_S_BAD_NAME; + + if (mech->gss_release_any_name_mapping == NULL) + return GSS_S_UNAVAILABLE; + + status = (*mech->gss_release_any_name_mapping)(minor_status, + union_name->mech_name, + type_id, + input); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + + return status; +} + diff --git a/src/lib/gssapi/mechglue/g_set_context_option.c b/src/lib/gssapi/mechglue/g_set_context_option.c index 8f3abbc5d..2f4ba36ae 100644 --- a/src/lib/gssapi/mechglue/g_set_context_option.c +++ b/src/lib/gssapi/mechglue/g_set_context_option.c @@ -65,9 +65,10 @@ gss_set_sec_context_option (OM_uint32 *minor_status, mech = gssint_get_mechanism (ctx->mech_type); } - if (mech == NULL || mech->gss_set_sec_context_option == NULL) { + if (mech == NULL) return GSS_S_BAD_MECH; - } + if (mech->gss_set_sec_context_option == NULL) + return GSS_S_UNAVAILABLE; status = mech->gss_set_sec_context_option(minor_status, ctx ? &ctx->internal_ctx_id : diff --git a/src/lib/gssapi/mechglue/g_set_cred_option.c b/src/lib/gssapi/mechglue/g_set_cred_option.c index 84d18cdf8..bac8c5b50 100644 --- a/src/lib/gssapi/mechglue/g_set_cred_option.c +++ b/src/lib/gssapi/mechglue/g_set_cred_option.c @@ -56,15 +56,19 @@ gssspi_set_cred_option(OM_uint32 *minor_status, union_cred = (gss_union_cred_t) cred_handle; - status = GSS_S_BAD_MECH; + status = GSS_S_UNAVAILABLE; for (i = 0; i < union_cred->count; i++) { mech = gssint_get_mechanism(&union_cred->mechs_array[i]); - if (mech == NULL) - continue; + if (mech == NULL) { + status = GSS_S_BAD_MECH; + break; + } - if (mech->gssspi_set_cred_option == NULL) + if (mech->gssspi_set_cred_option == NULL) { + status = GSS_S_UNAVAILABLE; continue; + } status = (mech->gssspi_set_cred_option)(minor_status, union_cred->cred_array[i], diff --git a/src/lib/gssapi/mechglue/g_set_name_attr.c b/src/lib/gssapi/mechglue/g_set_name_attr.c new file mode 100644 index 000000000..14df2319d --- /dev/null +++ b/src/lib/gssapi/mechglue/g_set_name_attr.c @@ -0,0 +1,74 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * 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. + * + */ + +/* + * glue routine for gss_set_name_attribute + */ + +#include "mglueP.h" + +OM_uint32 KRB5_CALLCONV +gss_set_name_attribute(OM_uint32 *minor_status, + gss_name_t name, + int complete, + gss_buffer_t attr, + gss_buffer_t value) +{ + OM_uint32 status; + gss_union_name_t union_name; + gss_mechanism mech; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + if (name == GSS_C_NO_NAME) + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME; + + *minor_status = 0; + + union_name = (gss_union_name_t)name; + + if (union_name->mech_type == GSS_C_NO_OID) + return GSS_S_UNAVAILABLE; + + mech = gssint_get_mechanism(name->mech_type); + if (mech == NULL) + return GSS_S_BAD_NAME; + + if (mech->gss_set_name_attribute == NULL) + return GSS_S_UNAVAILABLE; + + status = (*mech->gss_set_name_attribute)(minor_status, + union_name->mech_name, + complete, + attr, + value); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + + return status; +} + diff --git a/src/lib/gssapi/mechglue/mglueP.h b/src/lib/gssapi/mechglue/mglueP.h index 46bfb9463..177db62cc 100644 --- a/src/lib/gssapi/mechglue/mglueP.h +++ b/src/lib/gssapi/mechglue/mglueP.h @@ -504,6 +504,75 @@ typedef struct gss_config { OM_uint32 * /* acceptor_time_rec */ /* */); + OM_uint32 (*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 (*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 (*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 (*gss_set_name_attribute) + ( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + int, /* complete */ + gss_buffer_t, /* attr */ + gss_buffer_t /* value */ + /* */); + + OM_uint32 (*gss_delete_name_attribute) + ( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + gss_buffer_t /* attr */ + /* */); + + OM_uint32 (*gss_export_name_composite) + ( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + gss_buffer_t /* exp_composite_name */ + /* */); + + OM_uint32 (*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 (*gss_release_any_name_mapping) + ( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + gss_buffer_t, /* type_id */ + gss_any_t * /* input */ + /* */); + } *gss_mechanism; /* This structure MUST NOT be used by any code outside libgss */ diff --git a/src/lib/gssapi/spnego/gssapiP_spnego.h b/src/lib/gssapi/spnego/gssapiP_spnego.h index 5e6cd5a0c..43b004931 100644 --- a/src/lib/gssapi/spnego/gssapiP_spnego.h +++ b/src/lib/gssapi/spnego/gssapiP_spnego.h @@ -442,6 +442,83 @@ spnego_gss_acquire_cred_impersonate_name( gss_OID_set *, /* actual_mechs */ OM_uint32 *); /* time_rec */ +OM_uint32 +spnego_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 +spnego_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 +spnego_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 +spnego_gss_set_name_attribute +( + OM_uint32 *minor_status, + gss_name_t name, + int complete, + gss_buffer_t attr, + gss_buffer_t value +); + +OM_uint32 +spnego_gss_delete_name_attribute +( + OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t attr +); + +OM_uint32 +spnego_gss_export_name_composite +( + OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t exp_composite_name +); + +OM_uint32 +spnego_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 +spnego_gss_release_any_name_mapping +( + OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t type_id, + gss_any_t *input +); + #ifdef __cplusplus } #endif diff --git a/src/lib/gssapi/spnego/spnego_mech.c b/src/lib/gssapi/spnego/spnego_mech.c index 14b65f751..999a5e3e8 100644 --- a/src/lib/gssapi/spnego/spnego_mech.c +++ b/src/lib/gssapi/spnego/spnego_mech.c @@ -260,6 +260,14 @@ static struct gss_config spnego_mechanism = spnego_gss_complete_auth_token, spnego_gss_acquire_cred_impersonate_name, NULL, /* gss_add_cred_impersonate_name */ + spnego_gss_display_name_ext, + spnego_gss_inquire_name, + spnego_gss_get_name_attribute, + spnego_gss_set_name_attribute, + spnego_gss_delete_name_attribute, + spnego_gss_export_name_composite, + spnego_gss_map_name_to_any, + spnego_gss_release_any_name_mapping, }; #ifdef _GSS_STATIC_LINK @@ -2354,6 +2362,129 @@ spnego_gss_acquire_cred_impersonate_name(OM_uint32 *minor_status, return (status); } +OM_uint32 +spnego_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 ret; + ret = gss_display_name_ext(minor_status, + name, + display_as_name_type, + display_name); + return (ret); +} + + +OM_uint32 +spnego_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 ret; + ret = gss_inquire_name(minor_status, + name, + name_is_MN, + MN_mech, + attrs); + return (ret); +} + +OM_uint32 +spnego_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 ret; + ret = gss_get_name_attribute(minor_status, + name, + attr, + authenticated, + complete, + value, + display_value, + more); + return (ret); +} + +OM_uint32 +spnego_gss_set_name_attribute(OM_uint32 *minor_status, + gss_name_t name, + int complete, + gss_buffer_t attr, + gss_buffer_t value) +{ + OM_uint32 ret; + ret = gss_set_name_attribute(minor_status, + name, + complete, + attr, + value); + return (ret); +} + +OM_uint32 +spnego_gss_delete_name_attribute(OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t attr) +{ + OM_uint32 ret; + ret = gss_delete_name_attribute(minor_status, + name, + attr); + return (ret); +} + +OM_uint32 +spnego_gss_export_name_composite(OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t exp_composite_name) +{ + OM_uint32 ret; + ret = gss_export_name_composite(minor_status, + name, + exp_composite_name); + return (ret); +} + +OM_uint32 +spnego_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 ret; + ret = gss_map_name_to_any(minor_status, + name, + authenticated, + type_id, + output); + return (ret); +} + +OM_uint32 +spnego_gss_release_any_name_mapping(OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t type_id, + gss_any_t *input) +{ + OM_uint32 ret; + ret = gss_release_any_name_mapping(minor_status, + name, + type_id, + input); + return (ret); +} + /* * We will release everything but the ctx_handle so that it * can be passed back to init/accept context. This routine should |
