diff options
author | Greg Hudson <ghudson@mit.edu> | 2010-09-27 03:39:22 +0000 |
---|---|---|
committer | Greg Hudson <ghudson@mit.edu> | 2010-09-27 03:39:22 +0000 |
commit | e76d9a48c905e6db8ea9b7af4b843070756effaa (patch) | |
tree | 4de2b9144c91046489889161acf8131635faac27 /src/lib/gssapi/krb5/acquire_cred.c | |
parent | 19b34d5112cc13214f6a47962be89f199966a449 (diff) | |
download | krb5-e76d9a48c905e6db8ea9b7af4b843070756effaa.zip krb5-e76d9a48c905e6db8ea9b7af4b843070756effaa.tar.gz krb5-e76d9a48c905e6db8ea9b7af4b843070756effaa.tar.bz2 |
Add gss_krb5_import_cred
Add gss_krb5_import_cred from Heimdal; allows krb5 creds to be
acquired from a keytab or ccache into a GSSAPI credential without
using global process or thread variables.
Merged from the users/lhoward/import-cred branch.
ticket: 6785
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@24356 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/lib/gssapi/krb5/acquire_cred.c')
-rw-r--r-- | src/lib/gssapi/krb5/acquire_cred.c | 479 |
1 files changed, 289 insertions, 190 deletions
diff --git a/src/lib/gssapi/krb5/acquire_cred.c b/src/lib/gssapi/krb5/acquire_cred.c index bceab61..55214ce 100644 --- a/src/lib/gssapi/krb5/acquire_cred.c +++ b/src/lib/gssapi/krb5/acquire_cred.c @@ -1,6 +1,6 @@ /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* - * Copyright 2000, 2007, 2008 by the Massachusetts Institute of Technology. + * Copyright 2000, 2007-2010 by the Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may @@ -129,56 +129,55 @@ 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_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(krb5_context context, OM_uint32 *minor_status, - krb5_gss_name_t desired_name, - krb5_gss_name_t *output_name, + krb5_principal desired_princ, + krb5_keytab req_keytab, krb5_gss_cred_id_rec *cred) { krb5_error_code code; - krb5_principal princ; krb5_keytab kt; krb5_keytab_entry entry; - *output_name = NULL; - cred->keytab = NULL; + assert(cred->keytab == NULL); - /* open the default keytab */ + if (req_keytab != NULL) { + char ktname[BUFSIZ]; - code = gss_krb5int_initialize_library(); - if (code != 0) { - *minor_status = code; - return GSS_S_FAILURE; - } - code = k5_mutex_lock(&gssint_krb5_keytab_lock); - if (code) { - *minor_status = code; - return GSS_S_FAILURE; - } - if (krb5_gss_keytab != NULL) { - code = krb5_kt_resolve(context, krb5_gss_keytab, &kt); - k5_mutex_unlock(&gssint_krb5_keytab_lock); + /* Duplicate keytab handle */ + code = krb5_kt_get_name(context, req_keytab, ktname, sizeof(ktname)); + if (code) { + *minor_status = code; + return GSS_S_CRED_UNAVAIL; + } + code = krb5_kt_resolve(context, ktname, &kt); } else { - k5_mutex_unlock(&gssint_krb5_keytab_lock); - code = krb5_kt_default(context, &kt); + code = k5_mutex_lock(&gssint_krb5_keytab_lock); + if (code) { + *minor_status = code; + return GSS_S_FAILURE; + } + if (krb5_gss_keytab != NULL) { + code = krb5_kt_resolve(context, krb5_gss_keytab, &kt); + k5_mutex_unlock(&gssint_krb5_keytab_lock); + } else { + k5_mutex_unlock(&gssint_krb5_keytab_lock); + code = krb5_kt_default(context, &kt); + } } - if (code) { *minor_status = code; - return(GSS_S_CRED_UNAVAIL); + return GSS_S_CRED_UNAVAIL; } - 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 (desired_princ != NULL) { + code = krb5_kt_get_entry(context, kt, desired_princ, 0, 0, &entry); + if (code) { + krb5_kt_close(context, kt); if (code == KRB5_KT_NOTFOUND) { char *errstr = (char *)krb5_get_error_message(context, code); krb5_set_error_message(context, KG_KEYTAB_NOMATCH, "%s", errstr); @@ -186,46 +185,50 @@ acquire_accept_cred(krb5_context context, *minor_status = KG_KEYTAB_NOMATCH; } else *minor_status = code; - return(GSS_S_CRED_UNAVAIL); + return GSS_S_CRED_UNAVAIL; } krb5_kt_free_entry(context, &entry); - /* Open the replay cache for this principal. */ - if ((code = krb5_get_server_rcache(context, - krb5_princ_component(context, princ, 0), - &cred->rcache))) { + assert(cred->name == NULL); + code = kg_init_name(context, desired_princ, NULL, + KG_INIT_NAME_INTERN, &cred->name); + if (code) { *minor_status = code; - return(GSS_S_FAILURE); + return GSS_S_FAILURE; } + /* Open the replay cache for this principal. */ + code = krb5_get_server_rcache(context, + krb5_princ_component(context, desired_princ, 0), + &cred->rcache); + if (code) { + *minor_status = code; + return GSS_S_FAILURE; + } } -/* hooray. we made it */ - cred->keytab = kt; - return(GSS_S_COMPLETE); + return GSS_S_COMPLETE; } #endif /* LEAN_CLIENT */ /* get credentials corresponding to the default credential cache. - 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(krb5_context context, OM_uint32 *minor_status, - krb5_gss_name_t desired_name, - krb5_gss_name_t *output_name, + krb5_ccache req_ccache, + krb5_principal desired_princ, gss_buffer_t password, krb5_gss_cred_id_rec *cred) { krb5_error_code code; krb5_ccache ccache; - krb5_principal princ = NULL, tmp_princ; + krb5_principal ccache_princ = NULL, tmp_princ; + krb5_const_principal cred_princ = NULL; krb5_cc_cursor cur; krb5_creds creds; int got_endtime; @@ -237,16 +240,16 @@ acquire_init_cred(krb5_context context, /* load the GSS ccache name into the kg_context */ if (GSS_ERROR(kg_sync_ccache_name(context, minor_status))) - return(GSS_S_FAILURE); + return GSS_S_FAILURE; /* check to see if the caller provided a ccache name if so * we will just use that and not search the cache collection */ if (GSS_ERROR(kg_caller_provided_ccache_name (minor_status, &caller_provided_ccache_name))) { - return(GSS_S_FAILURE); + return GSS_S_FAILURE; } #if defined(USE_KIM) || defined(USE_LEASH) - if (desired_name && !caller_provided_ccache_name) { + if (desired_princ && !caller_provided_ccache_name && !req_ccache) { #if defined(USE_KIM) kim_error err = KIM_NO_ERROR; kim_ccache kimccache = NULL; @@ -255,7 +258,7 @@ acquire_init_cred(krb5_context context, err = kim_identity_create_from_krb5_principal (&identity, context, - desired_name->princ); + desired_princ); if (!err) { err = kim_ccache_create_from_client_identity (&kimccache, identity); @@ -289,7 +292,7 @@ acquire_init_cred(krb5_context context, if (err) { *minor_status = err; - return(GSS_S_CRED_UNAVAIL); + return GSS_S_CRED_UNAVAIL; } #elif defined(USE_LEASH) @@ -303,80 +306,99 @@ acquire_init_cred(krb5_context context, if ( pLeash_AcquireInitialTicketsIfNeeded ) { char ccname[256]=""; - pLeash_AcquireInitialTicketsIfNeeded(context, desired_name->princ, ccname, sizeof(ccname)); + pLeash_AcquireInitialTicketsIfNeeded(context, desired_princ, ccname, sizeof(ccname)); if (!ccname[0]) { *minor_status = KRB5_CC_NOTFOUND; - return(GSS_S_CRED_UNAVAIL); + return GSS_S_CRED_UNAVAIL; } if ((code = krb5_cc_resolve (context, ccname, &ccache))) { *minor_status = code; - return(GSS_S_CRED_UNAVAIL); + return GSS_S_CRED_UNAVAIL; } } else { /* leash dll not available, open the default credential cache */ if ((code = krb5int_cc_default(context, &ccache))) { *minor_status = code; - return(GSS_S_CRED_UNAVAIL); + return GSS_S_CRED_UNAVAIL; } } #endif /* USE_LEASH */ } else #endif /* USE_KIM || USE_LEASH */ { - /* open the default credential cache */ - - if ((code = krb5int_cc_default(context, &ccache))) { + if (req_ccache != NULL) { + /* Duplicate ccache handle */ + code = krb5_cc_dup(context, req_ccache, &ccache); + } else { + /* Open the default credential cache */ + code = krb5int_cc_default(context, &ccache); + } + if (code != 0) { *minor_status = code; - return(GSS_S_CRED_UNAVAIL); + return GSS_S_CRED_UNAVAIL; } } /* turn off OPENCLOSE mode while extensive frobbing is going on */ code = krb5_cc_set_flags(context, ccache, 0); if (code == KRB5_FCC_NOFILE && - password != GSS_C_NO_BUFFER && desired_name != NULL) { + password != GSS_C_NO_BUFFER && desired_princ != NULL) { /* We will get initial creds later. */ - code = krb5_cc_initialize(context, ccache, desired_name->princ); + code = krb5_cc_initialize(context, ccache, desired_princ); if (code == 0) code = krb5_cc_set_flags(context, ccache, 0); } if (code != 0) { - (void)krb5_cc_close(context, ccache); + krb5_cc_close(context, ccache); *minor_status = code; - return(GSS_S_CRED_UNAVAIL); + return GSS_S_CRED_UNAVAIL; } - /* get out the principal name and see if it matches */ - code = krb5_cc_get_principal(context, ccache, &princ); + /* + * Credentials cache principal must match either the acceptor principal + * name or the desired_princ argument (they may be the same). + */ + if (cred->name != NULL && desired_princ == NULL) + desired_princ = cred->name->princ; + + code = krb5_cc_get_principal(context, ccache, &ccache_princ); if (code != 0) { - (void)krb5_cc_close(context, ccache); + krb5_cc_close(context, ccache); *minor_status = code; - return(GSS_S_FAILURE); + return GSS_S_FAILURE; } - if (desired_name != NULL) { - if (!krb5_principal_compare(context, princ, desired_name->princ)) { - (void)krb5_free_principal(context, princ); - (void)krb5_cc_close(context, ccache); + if (desired_princ != NULL) { + if (!krb5_principal_compare(context, ccache_princ, desired_princ)) { + krb5_free_principal(context, ccache_princ); + krb5_cc_close(context, ccache); *minor_status = KG_CCACHE_NOMATCH; - return(GSS_S_CRED_UNAVAIL); + return GSS_S_CRED_UNAVAIL; } - (void)krb5_free_principal(context, princ); - princ = desired_name->princ; - } else { - if ((code = kg_init_name(context, princ, NULL, + } + + /* + * If we are acquiring initiator-only default credentials, then set + * cred->name to the credentials cache principal name. + */ + if (cred->name == NULL) { + if ((code = kg_init_name(context, ccache_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); + &cred->name))) { + krb5_free_principal(context, ccache_princ); + krb5_cc_close(context, ccache); *minor_status = code; - return(GSS_S_FAILURE); + return GSS_S_FAILURE; } - /* princ is now owned by output_name, it need not be freed here */ + } else { + krb5_free_principal(context, ccache_princ); } + assert(cred->name->princ != NULL); + cred_princ = cred->name->princ; + if (password != GSS_C_NO_BUFFER) { /* stash the password for later */ password_data.length = password->length; @@ -385,7 +407,7 @@ acquire_init_cred(krb5_context context, code = krb5int_copy_data_contents_add0(context, &password_data, &cred->password); if (code != 0) { - (void)krb5_cc_close(context, ccache); + krb5_cc_close(context, ccache); *minor_status = code; return GSS_S_FAILURE; } @@ -393,7 +415,7 @@ acquire_init_cred(krb5_context context, /* restore the OPENCLOSE flag */ code = krb5_cc_set_flags(context, ccache, KRB5_TC_OPENCLOSE); if (code != 0) { - (void)krb5_cc_close(context, ccache); + krb5_cc_close(context, ccache); *minor_status = code; return GSS_S_FAILURE; } @@ -405,9 +427,9 @@ acquire_init_cred(krb5_context context, /* iterate over the ccache, find the tgt */ if ((code = krb5_cc_start_seq_get(context, ccache, &cur))) { - (void)krb5_cc_close(context, ccache); + krb5_cc_close(context, ccache); *minor_status = code; - return(GSS_S_FAILURE); + return GSS_S_FAILURE; } /* this is hairy. If there's a tgt for the principal's local realm @@ -417,16 +439,16 @@ acquire_init_cred(krb5_context context, got_endtime = 0; code = krb5_build_principal_ext(context, &tmp_princ, - krb5_princ_realm(context, princ)->length, - krb5_princ_realm(context, princ)->data, + krb5_princ_realm(context, cred_princ)->length, + krb5_princ_realm(context, cred_princ)->data, KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME, - krb5_princ_realm(context, princ)->length, - krb5_princ_realm(context, princ)->data, + krb5_princ_realm(context, cred_princ)->length, + krb5_princ_realm(context, cred_princ)->data, 0); if (code) { - (void)krb5_cc_close(context, ccache); + krb5_cc_close(context, ccache); *minor_status = code; - return(GSS_S_FAILURE); + return GSS_S_FAILURE; } while (!(code = krb5_cc_next_cred(context, ccache, &cur, &creds))) { if (krb5_principal_compare(context, tmp_princ, creds.server)) { @@ -447,27 +469,27 @@ acquire_init_cred(krb5_context context, if (code && code != KRB5_CC_END) { /* this means some error occurred reading the ccache */ - (void)krb5_cc_end_seq_get(context, ccache, &cur); - (void)krb5_cc_close(context, ccache); + krb5_cc_end_seq_get(context, ccache, &cur); + krb5_cc_close(context, ccache); *minor_status = code; - return(GSS_S_FAILURE); + return GSS_S_FAILURE; } else if (! got_endtime) { /* this means the ccache was entirely empty */ - (void)krb5_cc_end_seq_get(context, ccache, &cur); - (void)krb5_cc_close(context, ccache); + krb5_cc_end_seq_get(context, ccache, &cur); + krb5_cc_close(context, ccache); *minor_status = KG_EMPTY_CCACHE; - return(GSS_S_FAILURE); + return GSS_S_FAILURE; } else { /* this means that we found an endtime to use. */ if ((code = krb5_cc_end_seq_get(context, ccache, &cur))) { - (void)krb5_cc_close(context, ccache); + krb5_cc_close(context, ccache); *minor_status = code; - return(GSS_S_FAILURE); + return GSS_S_FAILURE; } if ((code = krb5_cc_set_flags(context, ccache, KRB5_TC_OPENCLOSE))) { - (void)krb5_cc_close(context, ccache); + krb5_cc_close(context, ccache); *minor_status = code; - return(GSS_S_FAILURE); + return GSS_S_FAILURE; } } @@ -475,26 +497,37 @@ acquire_init_cred(krb5_context context, cred->ccache = ccache; /* minor_status is set while we are iterating over the ccache */ - return(GSS_S_COMPLETE); + return GSS_S_COMPLETE; } -/*ARGSUSED*/ -static OM_uint32 -acquire_cred(minor_status, desired_name, password, time_req, - cred_usage, output_cred_handle, time_rec, req_iakerb) - OM_uint32 *minor_status; - const gss_name_t desired_name; - const gss_buffer_t password; +struct acquire_cred_args { + gss_name_t desired_name; + gss_buffer_t password; OM_uint32 time_req; + gss_OID_set desired_mechs; gss_cred_usage_t cred_usage; - gss_cred_id_t *output_cred_handle; - OM_uint32 *time_rec; - int req_iakerb; + krb5_keytab keytab; + krb5_ccache ccache; + int iakerb; +}; + +/*ARGSUSED*/ +static OM_uint32 +acquire_cred(OM_uint32 *minor_status, + const struct acquire_cred_args *args, + gss_cred_id_t *output_cred_handle, + OM_uint32 *time_rec) { krb5_context context = NULL; krb5_gss_cred_id_t cred = NULL; OM_uint32 ret; krb5_error_code code = 0; + krb5_principal desired_princ = NULL; + + /* make sure all outputs are valid */ + *output_cred_handle = GSS_C_NO_CREDENTIAL; + if (time_rec) + *time_rec = 0; code = gss_krb5int_initialize_library(); if (code) @@ -504,31 +537,15 @@ acquire_cred(minor_status, desired_name, password, time_req, if (code) goto krb_error_out; - /* make sure all outputs are valid */ - - *output_cred_handle = NULL; - if (time_rec) - *time_rec = 0; - - /* validate the name */ - - /*SUPPRESS 29*/ - if ((desired_name != GSS_C_NO_NAME) && - (! kg_validate_name(desired_name))) { - code = G_VALIDATE_FAILED; - goto krb_error_out; - } - /* create the gss cred structure */ cred = k5alloc(sizeof(krb5_gss_cred_id_rec), &code); - if (code != 0) + if (cred == NULL) goto krb_error_out; - cred->usage = cred_usage; + cred->usage = args->cred_usage; cred->name = NULL; - cred->iakerb_mech = req_iakerb; - cred->default_identity = (desired_name == GSS_C_NO_NAME); - + cred->iakerb_mech = args->iakerb; + cred->default_identity = (args->desired_name == GSS_C_NO_NAME); #ifndef LEAN_CLIENT cred->keytab = NULL; #endif /* LEAN_CLIENT */ @@ -538,59 +555,50 @@ acquire_cred(minor_status, desired_name, password, time_req, if (code) goto krb_error_out; - /* Note that we don't need to lock this GSSAPI credential record - here, because no other thread can gain access to it until we - return it. */ - - if ((cred_usage != GSS_C_INITIATE) && - (cred_usage != GSS_C_ACCEPT) && - (cred_usage != GSS_C_BOTH)) { + switch (args->cred_usage) { + case GSS_C_INITIATE: + case GSS_C_ACCEPT: + case GSS_C_BOTH: + break; + default: ret = GSS_S_FAILURE; *minor_status = (OM_uint32) G_BAD_USAGE; goto error_out; } - /* if requested, acquire credentials for accepting */ - /* this will fill in cred->name if the desired_name is not specified */ + if (args->desired_name != GSS_C_NO_NAME) + desired_princ = ((krb5_gss_name_t)args->desired_name)->princ; + #ifndef LEAN_CLIENT - if ((cred_usage == GSS_C_ACCEPT) || - (cred_usage == GSS_C_BOTH)) - if ((ret = acquire_accept_cred(context, minor_status, - (krb5_gss_name_t)desired_name, - &cred->name, cred)) - != GSS_S_COMPLETE) { + /* + * If requested, acquire credentials for accepting. This will fill + * in cred->name if desired_princ is specified. + */ + if (args->cred_usage == GSS_C_ACCEPT || args->cred_usage == GSS_C_BOTH) { + ret = acquire_accept_cred(context, minor_status, + desired_princ, + args->keytab, cred); + if (ret != GSS_S_COMPLETE) goto error_out; - } + } #endif /* LEAN_CLIENT */ - /* if requested, acquire credentials for initiation */ - /* 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) { - ret = acquire_init_cred(context, minor_status, - cred->name ? - cred->name : (krb5_gss_name_t)desired_name, - &cred->name, password, cred); + /* + * If requested, acquire credentials for initiation. This will fill + * in cred->name if it wasn't set above. + */ + if (args->cred_usage == GSS_C_INITIATE || args->cred_usage == GSS_C_BOTH) { + ret = acquire_init_cred(context, minor_status, args->ccache, + desired_princ, args->password, cred); if (ret != GSS_S_COMPLETE) goto error_out; } - /* if the princ wasn't filled in already, fill it in now */ - - if (!cred->name && (desired_name != GSS_C_NO_NAME)) { - code = kg_duplicate_name(context, - (krb5_gss_name_t)desired_name, - 0, &cred->name); - if (code != 0) - goto krb_error_out; - } + assert(cred->default_identity || cred->name != NULL); /*** at this point, the cred structure has been completely created */ - /* compute time_rec */ - - if (cred_usage == GSS_C_ACCEPT) { + if (args->cred_usage == GSS_C_ACCEPT) { if (time_rec) *time_rec = GSS_C_INDEFINITE; } else { @@ -604,20 +612,16 @@ acquire_cred(minor_status, desired_name, password, time_req, *time_rec = (cred->tgt_expire > now) ? (cred->tgt_expire - now) : 0; } - /* intern the credential handle */ - - if (! kg_save_cred_id((gss_cred_id_t) cred)) { + if (!kg_save_cred_id((gss_cred_id_t)cred)) { ret = GSS_S_FAILURE; goto error_out; } - /* return success */ - *minor_status = 0; *output_cred_handle = (gss_cred_id_t) cred; krb5_free_context(context); - return(GSS_S_COMPLETE); + return GSS_S_COMPLETE; krb_error_out: *minor_status = code; @@ -626,10 +630,10 @@ krb_error_out: error_out: if (cred != NULL) { if (cred->ccache) - (void)krb5_cc_close(context, cred->ccache); + krb5_cc_close(context, cred->ccache); #ifndef LEAN_CLIENT if (cred->keytab) - (void)krb5_kt_close(context, cred->keytab); + krb5_kt_close(context, cred->keytab); #endif /* LEAN_CLIENT */ if (cred->name) kg_release_name(context, 0, &cred->name); @@ -643,7 +647,7 @@ error_out: OM_uint32 gss_krb5int_set_cred_rcache(OM_uint32 *minor_status, - gss_cred_id_t cred_handle, + gss_cred_id_t *cred_handle, const gss_OID desired_oid, const gss_buffer_t value) { @@ -659,10 +663,7 @@ gss_krb5int_set_cred_rcache(OM_uint32 *minor_status, rcache = (krb5_rcache)value->value; - if (cred_handle == GSS_C_NO_CREDENTIAL) - return GSS_S_NO_CRED; - - cred = (krb5_gss_cred_id_t)cred_handle; + cred = (krb5_gss_cred_id_t)*cred_handle; code = krb5_gss_init_context(&context); if (code) { @@ -704,8 +705,21 @@ krb5_gss_acquire_cred(minor_status, desired_name, time_req, gss_OID_set *actual_mechs; OM_uint32 *time_rec; { - return acquire_cred(minor_status, desired_name, GSS_C_NO_BUFFER, - time_req, cred_usage, output_cred_handle, time_rec, 0); + struct acquire_cred_args args; + + if (desired_name && !kg_validate_name(desired_name)) { + *minor_status = G_VALIDATE_FAILED; + return GSS_S_FAILURE; + } + + memset(&args, 0, sizeof(args)); + args.desired_name = desired_name; + args.time_req = time_req; + args.desired_mechs = desired_mechs; + args.cred_usage = cred_usage; + args.iakerb = 0; + + return acquire_cred(minor_status, &args, output_cred_handle, time_rec); } OM_uint32 @@ -721,8 +735,21 @@ iakerb_gss_acquire_cred(minor_status, desired_name, time_req, gss_OID_set *actual_mechs; OM_uint32 *time_rec; { - return acquire_cred(minor_status, desired_name, GSS_C_NO_BUFFER, - time_req, cred_usage, output_cred_handle, time_rec, 1); + struct acquire_cred_args args; + + if (desired_name && !kg_validate_name(desired_name)) { + *minor_status = G_VALIDATE_FAILED; + return GSS_S_FAILURE; + } + + memset(&args, 0, sizeof(args)); + args.desired_name = desired_name; + args.time_req = time_req; + args.desired_mechs = desired_mechs; + args.cred_usage = cred_usage; + args.iakerb = 1; + + return acquire_cred(minor_status, &args, output_cred_handle, time_rec); } OM_uint32 @@ -736,8 +763,22 @@ krb5_gss_acquire_cred_with_password(OM_uint32 *minor_status, gss_OID_set *actual_mechs, OM_uint32 *time_rec) { - return acquire_cred(minor_status, desired_name, password, - time_req, cred_usage, output_cred_handle, time_rec, 0); + struct acquire_cred_args args; + + if (desired_name && !kg_validate_name(desired_name)) { + *minor_status = G_VALIDATE_FAILED; + return GSS_S_FAILURE; + } + + memset(&args, 0, sizeof(args)); + args.desired_name = desired_name; + args.password = password; + args.time_req = time_req; + args.desired_mechs = desired_mechs; + args.cred_usage = cred_usage; + args.iakerb = 0; + + return acquire_cred(minor_status, &args, output_cred_handle, time_rec); } OM_uint32 @@ -751,6 +792,64 @@ iakerb_gss_acquire_cred_with_password(OM_uint32 *minor_status, gss_OID_set *actual_mechs, OM_uint32 *time_rec) { - return acquire_cred(minor_status, desired_name, password, - time_req, cred_usage, output_cred_handle, time_rec, 1); + struct acquire_cred_args args; + + if (desired_name && !kg_validate_name(desired_name)) { + *minor_status = G_VALIDATE_FAILED; + return GSS_S_FAILURE; + } + + memset(&args, 0, sizeof(args)); + args.desired_name = desired_name; + args.password = password; + args.time_req = time_req; + args.desired_mechs = desired_mechs; + args.cred_usage = cred_usage; + args.iakerb = 1; + + return acquire_cred(minor_status, &args, output_cred_handle, time_rec); +} + +OM_uint32 +gss_krb5int_import_cred(OM_uint32 *minor_status, + gss_cred_id_t *cred_handle, + const gss_OID desired_oid, + const gss_buffer_t value) +{ + struct krb5_gss_import_cred_req *req; + struct acquire_cred_args args; + krb5_gss_name_rec name; + OM_uint32 time_rec; + + assert(value->length == sizeof(*req)); + + if (value->length != sizeof(*req)) + return GSS_S_FAILURE; + + req = (struct krb5_gss_import_cred_req *)value->value; + + memset(&args, 0, sizeof(args)); + + if (req->keytab_principal) { + memset(&name, 0, sizeof(name)); + name.princ = req->keytab_principal; + args.desired_name = (gss_name_t)&name; + } + + args.ccache = req->id; + args.keytab = req->keytab; + + if (req->id && req->keytab) + args.cred_usage = GSS_C_BOTH; + else if (req->id) + args.cred_usage = GSS_C_INITIATE; + else if (req->keytab) + args.cred_usage = GSS_C_ACCEPT; + else { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + return acquire_cred(minor_status, &args, cred_handle, &time_rec); } + |