From e544eaa09354773e246d7fe1b223ddac2bd06c08 Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Wed, 12 May 2010 20:49:11 +0000 Subject: [PATCH] Reimplement krb5_get_in_tkt_with_skey in terms of krb5_get_init_creds, similar to how the password and keytab equivalents were done. Eliminate krb5_get_in_tkt. It's been very hard to use since we made krb5_kdc_rep_decrypt_proc private (in krb5 1.7 the prototype was taken out of krb5.h altogether), and it's unlikely that anything would have used it directly in the first place. Remove and/or simplify a lot of code depended on by krb_get_in_tkt, including all of preauth.c. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@24012 dc483132-0cff-0310-8789-dd5450dbe970 --- src/include/k5-int.h | 17 - src/include/krb5/krb5.hin | 11 - src/lib/krb5/krb/Makefile.in | 3 - src/lib/krb5/krb/get_in_tkt.c | 538 +------------------------------- src/lib/krb5/krb/in_tkt_sky.c | 84 ++--- src/lib/krb5/krb/preauth.c | 567 ---------------------------------- src/lib/krb5/libkrb5.exports | 3 - 7 files changed, 53 insertions(+), 1170 deletions(-) delete mode 100644 src/lib/krb5/krb/preauth.c diff --git a/src/include/k5-int.h b/src/include/k5-int.h index fc39acdc7..184549ce0 100644 --- a/src/include/k5-int.h +++ b/src/include/k5-int.h @@ -1082,23 +1082,6 @@ typedef struct _krb5_preauth_ops { krb5_preauth_process_proc process; } krb5_preauth_ops; -krb5_error_code -krb5_obtain_padata(krb5_context, krb5_pa_data **, - krb5_error_code (*)(krb5_context, const krb5_enctype, - krb5_data *, krb5_const_pointer, - krb5_keyblock **), - krb5_const_pointer, krb5_creds *, krb5_kdc_req *); - -krb5_error_code -krb5_process_padata(krb5_context, krb5_kdc_req *, krb5_kdc_rep *, - krb5_error_code (*)(krb5_context, const krb5_enctype, - krb5_data *, krb5_const_pointer, - krb5_keyblock **), - krb5_const_pointer, - krb5_error_code (*)(krb5_context, const krb5_keyblock *, - krb5_const_pointer, krb5_kdc_rep *), - krb5_keyblock **, krb5_creds *, krb5_int32 *); - krb5_pa_data * krb5int_find_pa_data(krb5_context, krb5_pa_data *const *, krb5_preauthtype); /* Does not return a copy; original padata sequence responsible for freeing*/ diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin index 1c89f9e92..18097f236 100644 --- a/src/include/krb5/krb5.hin +++ b/src/include/krb5/krb5.hin @@ -1949,17 +1949,6 @@ krb5_error_code KRB5_CALLCONV krb5_get_profile(krb5_context, struct _profile_t * /* profile_t */ *); #if KRB5_DEPRECATED -KRB5_ATTR_DEPRECATED krb5_error_code KRB5_CALLCONV -krb5_get_in_tkt(krb5_context, krb5_flags, krb5_address *const *, - krb5_enctype *, krb5_preauthtype *, - krb5_error_code (*)(krb5_context, krb5_enctype, krb5_data *, - krb5_const_pointer, krb5_keyblock **), - krb5_const_pointer, - krb5_error_code (*)(krb5_context, const krb5_keyblock *, - krb5_const_pointer, krb5_kdc_rep * ), - krb5_const_pointer, krb5_creds *, krb5_ccache, - krb5_kdc_rep **); - KRB5_ATTR_DEPRECATED krb5_error_code KRB5_CALLCONV krb5_get_in_tkt_with_password(krb5_context, krb5_flags, krb5_address *const *, krb5_enctype *, krb5_preauthtype *, const char *, diff --git a/src/lib/krb5/krb/Makefile.in b/src/lib/krb5/krb/Makefile.in index 4384c5e55..ba9903209 100644 --- a/src/lib/krb5/krb/Makefile.in +++ b/src/lib/krb5/krb/Makefile.in @@ -75,7 +75,6 @@ STLIBOBJS= \ pac_sign.o \ parse.o \ pr_to_salt.o \ - preauth.o \ preauth2.o \ gic_opt_set_pa.o \ princ_comp.o \ @@ -174,7 +173,6 @@ OBJS= $(OUTPRE)addr_comp.$(OBJEXT) \ $(OUTPRE)pac_sign.$(OBJEXT) \ $(OUTPRE)parse.$(OBJEXT) \ $(OUTPRE)pr_to_salt.$(OBJEXT) \ - $(OUTPRE)preauth.$(OBJEXT) \ $(OUTPRE)preauth2.$(OBJEXT) \ $(OUTPRE)gic_opt_set_pa.$(OBJEXT) \ $(OUTPRE)princ_comp.$(OBJEXT) \ @@ -274,7 +272,6 @@ SRCS= $(srcdir)/addr_comp.c \ $(srcdir)/pac_sign.c \ $(srcdir)/parse.c \ $(srcdir)/pr_to_salt.c \ - $(srcdir)/preauth.c \ $(srcdir)/preauth2.c \ $(srcdir)/gic_opt_set_pa.c \ $(srcdir)/princ_comp.c \ diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c index 2b98e45d0..e97984f50 100644 --- a/src/lib/krb5/krb/get_in_tkt.c +++ b/src/lib/krb5/krb/get_in_tkt.c @@ -25,7 +25,6 @@ * or implied warranty. * * - * krb5_get_in_tkt() */ #include @@ -45,48 +44,8 @@ #endif #endif /* APPLE_PKINIT */ -/* - All-purpose initial ticket routine, usually called via - krb5_get_in_tkt_with_password or krb5_get_in_tkt_with_skey. - - Attempts to get an initial ticket for creds->client to use server - creds->server, (realm is taken from creds->client), with options - options, and using creds->times.starttime, creds->times.endtime, - creds->times.renew_till as from, till, and rtime. - creds->times.renew_till is ignored unless the RENEWABLE option is requested. - - key_proc is called to fill in the key to be used for decryption. - keyseed is passed on to key_proc. - - decrypt_proc is called to perform the decryption of the response (the - encrypted part is in dec_rep->enc_part; the decrypted part should be - allocated and filled into dec_rep->enc_part2 - arg is passed on to decrypt_proc. - - If addrs is non-NULL, it is used for the addresses requested. If it is - null, the system standard addresses are used. - - A succesful call will place the ticket in the credentials cache ccache - and fill in creds with the ticket information used/returned.. - - returns system errors, encryption errors - -*/ - - /* some typedef's for the function args to make things look a bit cleaner */ -typedef krb5_error_code (*git_key_proc) (krb5_context, - krb5_enctype, - krb5_data *, - krb5_const_pointer, - krb5_keyblock **); - -typedef krb5_error_code (*git_decrypt_proc) (krb5_context, - const krb5_keyblock *, - krb5_const_pointer, - krb5_kdc_rep * ); - static krb5_error_code make_preauth_list (krb5_context, krb5_preauthtype *, int, krb5_pa_data ***); @@ -112,175 +71,14 @@ krb5int_addint32 (krb5_int32 x, krb5_int32 y) return x + y; } -#if APPLE_PKINIT -/* - * Common code to generate krb5_kdc_req.nonce. Like the original MIT code this - * just uses krb5_timeofday(); it should use a PRNG. Even more unfortunately this - * value is used interchangeably with an explicit now_time throughout this module... - */ -static krb5_error_code -gen_nonce(krb5_context context, - krb5_int32 *nonce) -{ - krb5_int32 time_now; - krb5_error_code retval = krb5_timeofday(context, &time_now); - if(retval) { - return retval; - } - *nonce = time_now; - return 0; -} -#endif /* APPLE_PKINIT */ - -/* - * This function sends a request to the KDC, and gets back a response; - * the response is parsed into ret_err_reply or ret_as_reply if the - * reponse is a KRB_ERROR or a KRB_AS_REP packet. If it is some other - * unexpected response, an error is returned. - */ static krb5_error_code -send_as_request(krb5_context context, - krb5_data *packet, const krb5_data *realm, - krb5_error ** ret_err_reply, - krb5_kdc_rep ** ret_as_reply, - int *use_master) +decrypt_as_reply(krb5_context context, krb5_kdc_req *request, + krb5_kdc_rep *as_reply, krb5_keyblock *key) { - krb5_kdc_rep *as_reply = 0; - krb5_error_code retval; - krb5_data reply; - char k4_version; /* same type as *(krb5_data::data) */ - int tcp_only = 0; - - reply.data = 0; - - /* set the nonce if the caller expects us to do it */ - - k4_version = packet->data[0]; -send_again: - retval = krb5_sendto_kdc(context, packet, - realm, - &reply, use_master, tcp_only); -#if APPLE_PKINIT - inTktDebug("krb5_sendto_kdc returned %d\n", (int)retval); -#endif /* APPLE_PKINIT */ - - if (retval) - goto cleanup; - - /* now decode the reply...could be error or as_rep */ - if (krb5_is_krb_error(&reply)) { - krb5_error *err_reply; - - if ((retval = decode_krb5_error(&reply, &err_reply))) - /* some other error code--??? */ - goto cleanup; - - if (ret_err_reply) { - if (err_reply->error == KRB_ERR_RESPONSE_TOO_BIG - && tcp_only == 0) { - tcp_only = 1; - krb5_free_error(context, err_reply); - free(reply.data); - reply.data = 0; - goto send_again; - } - *ret_err_reply = err_reply; - } else - krb5_free_error(context, err_reply); - goto cleanup; - } - - /* - * Check to make sure it isn't a V4 reply. - */ - if (!krb5_is_as_rep(&reply)) { -/* these are in as well but it isn't worth including. */ -#define V4_KRB_PROT_VERSION 4 -#define V4_AUTH_MSG_ERR_REPLY (5<<1) - /* check here for V4 reply */ - unsigned int t_switch; - - /* From v4 g_in_tkt.c: This used to be - switch (pkt_msg_type(rpkt) & ~1) { - but SCO 3.2v4 cc compiled that incorrectly. */ - t_switch = reply.data[1]; - t_switch &= ~1; - - if (t_switch == V4_AUTH_MSG_ERR_REPLY - && (reply.data[0] == V4_KRB_PROT_VERSION - || reply.data[0] == k4_version)) { - retval = KRB5KRB_AP_ERR_V4_REPLY; - } else { - retval = KRB5KRB_AP_ERR_MSG_TYPE; - } - goto cleanup; - } - - /* It must be a KRB_AS_REP message, or an bad returned packet */ - if ((retval = decode_krb5_as_rep(&reply, &as_reply))) - /* some other error code ??? */ - goto cleanup; - - if (as_reply->msg_type != KRB5_AS_REP) { - retval = KRB5KRB_AP_ERR_MSG_TYPE; - krb5_free_kdc_rep(context, as_reply); - goto cleanup; - } - - if (ret_as_reply) - *ret_as_reply = as_reply; - else - krb5_free_kdc_rep(context, as_reply); - -cleanup: - if (reply.data) - free(reply.data); - return retval; -} - -static krb5_error_code -decrypt_as_reply(krb5_context context, - krb5_kdc_req *request, - krb5_kdc_rep *as_reply, - git_key_proc key_proc, - krb5_const_pointer keyseed, - krb5_keyblock * key, - git_decrypt_proc decrypt_proc, - krb5_const_pointer decryptarg) -{ - krb5_error_code retval; - krb5_keyblock * decrypt_key = 0; - krb5_data salt; - if (as_reply->enc_part2) return 0; - if (key) - decrypt_key = key; - else { - /* - * Use salt corresponding to the client principal supplied by - * the KDC, which may differ from the requested principal if - * canonicalization is in effect. We will check - * as_reply->client later in verify_as_reply. - */ - if ((retval = krb5_principal2salt(context, as_reply->client, &salt))) - return(retval); - - retval = (*key_proc)(context, as_reply->enc_part.enctype, - &salt, keyseed, &decrypt_key); - free(salt.data); - if (retval) - goto cleanup; - } - - if ((retval = (*decrypt_proc)(context, decrypt_key, decryptarg, as_reply))) - goto cleanup; - -cleanup: - if (!key && decrypt_key) - krb5_free_keyblock(context, decrypt_key); - return (retval); + return krb5_kdc_rep_decrypt_proc(context, key, NULL, as_reply); } /** @@ -561,63 +359,6 @@ make_preauth_list(krb5_context context, } #define MAX_IN_TKT_LOOPS 16 -static const krb5_enctype get_in_tkt_enctypes[] = { - ENCTYPE_DES3_CBC_SHA1, - ENCTYPE_ARCFOUR_HMAC, - ENCTYPE_DES_CBC_MD5, - ENCTYPE_DES_CBC_MD4, - ENCTYPE_DES_CBC_CRC, - 0 -}; - -static krb5_error_code -rewrite_server_realm(krb5_context context, - krb5_const_principal old_server, - const krb5_data *realm, - krb5_boolean tgs, - krb5_principal *server) -{ - krb5_error_code retval; - - assert(*server == NULL); - - retval = krb5_copy_principal(context, old_server, server); - if (retval) - return retval; - - krb5_free_data_contents(context, &(*server)->realm); - (*server)->realm.data = NULL; - - retval = krb5int_copy_data_contents(context, realm, &(*server)->realm); - if (retval) - goto cleanup; - - if (tgs) { - krb5_free_data_contents(context, &(*server)->data[1]); - (*server)->data[1].data = NULL; - - retval = krb5int_copy_data_contents(context, realm, &(*server)->data[1]); - if (retval) - goto cleanup; - } - -cleanup: - if (retval) { - krb5_free_principal(context, *server); - *server = NULL; - } - - return retval; -} - -static inline int -tgt_is_local_realm(krb5_creds *tgt) -{ - return (tgt->server->length == 2 - && data_eq_string(tgt->server->data[0], KRB5_TGS_NAME) - && data_eq(tgt->server->data[1], tgt->client->realm) - && data_eq(tgt->server->realm, tgt->client->realm)); -} static krb5_error_code request_enc_pa_rep(krb5_pa_data ***padptr) @@ -643,271 +384,6 @@ request_enc_pa_rep(krb5_pa_data ***padptr) return 0; } -krb5_error_code KRB5_CALLCONV -krb5_get_in_tkt(krb5_context context, - krb5_flags options, - krb5_address * const * addrs, - krb5_enctype * ktypes, - krb5_preauthtype * ptypes, - git_key_proc key_proc, - krb5_const_pointer keyseed, - git_decrypt_proc decrypt_proc, - krb5_const_pointer decryptarg, - krb5_creds * creds, - krb5_ccache ccache, - krb5_kdc_rep ** ret_as_reply) -{ - krb5_error_code retval; - krb5_timestamp time_now; - krb5_keyblock * decrypt_key = 0; - krb5_kdc_req request; - krb5_data *encoded_request; - krb5_error * err_reply; - krb5_kdc_rep * as_reply = 0; - krb5_pa_data ** preauth_to_use = 0; - int loopcount = 0; - krb5_int32 do_more = 0; - int canon_flag; - int use_master = 0; - int referral_count = 0; - krb5_principal_data referred_client; - krb5_principal referred_server = NULL; - krb5_boolean is_tgt_req; - -#if APPLE_PKINIT - inTktDebug("krb5_get_in_tkt top\n"); -#endif /* APPLE_PKINIT */ - - if (! krb5_realm_compare(context, creds->client, creds->server)) - return KRB5_IN_TKT_REALM_MISMATCH; - - if (ret_as_reply) - *ret_as_reply = 0; - - referred_client = *(creds->client); - referred_client.realm.data = NULL; - referred_client.realm.length = 0; - - /* per referrals draft, enterprise principals imply canonicalization */ - canon_flag = ((options & KDC_OPT_CANONICALIZE) != 0) || - creds->client->type == KRB5_NT_ENTERPRISE_PRINCIPAL; - - /* - * Set up the basic request structure - */ - request.magic = KV5M_KDC_REQ; - request.msg_type = KRB5_AS_REQ; - request.addresses = 0; - request.ktype = 0; - request.padata = 0; - if (addrs) - request.addresses = (krb5_address **) addrs; - else - if ((retval = krb5_os_localaddr(context, &request.addresses))) - goto cleanup; - request.kdc_options = options; - request.client = creds->client; - request.server = creds->server; - request.nonce = 0; - request.from = creds->times.starttime; - request.till = creds->times.endtime; - request.rtime = creds->times.renew_till; -#if APPLE_PKINIT - retval = gen_nonce(context, (krb5_int32 *)&time_now); - if(retval) { - goto cleanup; - } - request.nonce = time_now; -#endif /* APPLE_PKINIT */ - - retval = krb5int_copy_etypes(get_in_tkt_enctypes, &request.ktype); - request.nktypes = krb5int_count_etypes(request.ktype); - if (ktypes) { - int i, req, next = 0; - for (req = 0; ktypes[req]; req++) { - if (ktypes[req] == request.ktype[next]) { - next++; - continue; - } - for (i = next + 1; i < request.nktypes; i++) - if (ktypes[req] == request.ktype[i]) { - /* Found the enctype we want, but not in the - position we want. Move it, but keep the old - one from the desired slot around in case it's - later in our requested-ktypes list. */ - krb5_enctype t; - t = request.ktype[next]; - request.ktype[next] = request.ktype[i]; - request.ktype[i] = t; - next++; - break; - } - /* If we didn't find it, don't do anything special, just - drop it. */ - } - request.ktype[next] = 0; - request.nktypes = next; - } - request.authorization_data.ciphertext.length = 0; - request.authorization_data.ciphertext.data = 0; - request.unenc_authdata = 0; - request.second_ticket = 0; - - /* - * If a list of preauth types are passed in, convert it to a - * preauth_to_use list. - */ - if (ptypes) { - retval = make_preauth_list(context, ptypes, -1, &preauth_to_use); - if (retval) - goto cleanup; - } - - is_tgt_req = tgt_is_local_realm(creds); - - while (1) { - if (loopcount++ > MAX_IN_TKT_LOOPS) { - retval = KRB5_GET_IN_TKT_LOOP; - goto cleanup; - } - -#if APPLE_PKINIT - inTktDebug("krb5_get_in_tkt calling krb5_obtain_padata\n"); -#endif /* APPLE_PKINIT */ - if ((retval = krb5_obtain_padata(context, preauth_to_use, key_proc, - keyseed, creds, &request)) != 0) - goto cleanup; - if (preauth_to_use) - krb5_free_pa_data(context, preauth_to_use); - preauth_to_use = 0; - - err_reply = 0; - as_reply = 0; - - if ((retval = krb5_timeofday(context, &time_now))) - goto cleanup; - - /* - * XXX we know they are the same size... and we should do - * something better than just the current time - */ - request.nonce = (krb5_int32) time_now; - - if ((retval = encode_krb5_as_req(&request, &encoded_request)) != 0) - goto cleanup; - retval = send_as_request(context, encoded_request, - krb5_princ_realm(context, request.client), &err_reply, - &as_reply, &use_master); - krb5_free_data(context, encoded_request); - if (retval != 0) - goto cleanup; - - if (err_reply) { - if (err_reply->error == KDC_ERR_PREAUTH_REQUIRED && - err_reply->e_data.length > 0) { - retval = decode_krb5_padata_sequence(&err_reply->e_data, - &preauth_to_use); - krb5_free_error(context, err_reply); - if (retval) - goto cleanup; - retval = sort_krb5_padata_sequence(context, - &request.server->realm, - preauth_to_use); - if (retval) - goto cleanup; - continue; - } else if (canon_flag && err_reply->error == KDC_ERR_WRONG_REALM) { - if (++referral_count > KRB5_REFERRAL_MAXHOPS || - err_reply->client == NULL || - err_reply->client->realm.length == 0) { - retval = KRB5KDC_ERR_WRONG_REALM; - krb5_free_error(context, err_reply); - goto cleanup; - } - /* Rewrite request.client with realm from error reply */ - if (referred_client.realm.data) { - krb5_free_data_contents(context, &referred_client.realm); - referred_client.realm.data = NULL; - } - retval = krb5int_copy_data_contents(context, - &err_reply->client->realm, - &referred_client.realm); - krb5_free_error(context, err_reply); - if (retval) - goto cleanup; - request.client = &referred_client; - - if (referred_server != NULL) { - krb5_free_principal(context, referred_server); - referred_server = NULL; - } - - retval = rewrite_server_realm(context, - creds->server, - &referred_client.realm, - is_tgt_req, - &referred_server); - if (retval) - goto cleanup; - request.server = referred_server; - - continue; - } else { - retval = (krb5_error_code) err_reply->error - + ERROR_TABLE_BASE_krb5; - krb5_free_error(context, err_reply); - goto cleanup; - } - } else if (!as_reply) { - retval = KRB5KRB_AP_ERR_MSG_TYPE; - goto cleanup; - } - if ((retval = krb5_process_padata(context, &request, as_reply, - key_proc, keyseed, decrypt_proc, - &decrypt_key, creds, - &do_more)) != 0) - goto cleanup; - - if (!do_more) - break; - } - - if ((retval = decrypt_as_reply(context, &request, as_reply, key_proc, - keyseed, decrypt_key, decrypt_proc, - decryptarg))) - goto cleanup; - - if ((retval = verify_as_reply(context, time_now, &request, as_reply))) - goto cleanup; - - if ((retval = stash_as_reply(context, time_now, &request, as_reply, - creds, ccache))) - goto cleanup; - -cleanup: - if (request.ktype) - free(request.ktype); - if (!addrs && request.addresses) - krb5_free_addresses(context, request.addresses); - if (request.padata) - krb5_free_pa_data(context, request.padata); - if (preauth_to_use) - krb5_free_pa_data(context, preauth_to_use); - if (decrypt_key) - krb5_free_keyblock(context, decrypt_key); - if (as_reply) { - if (ret_as_reply) - *ret_as_reply = as_reply; - else - krb5_free_kdc_rep(context, as_reply); - } - if (referred_client.realm.data) - krb5_free_data_contents(context, &referred_client.realm); - if (referred_server) - krb5_free_principal(context, referred_server); - return (retval); -} - /* Sort a pa_data sequence so that types named in the "preferred_preauth_types" * libdefaults entry are listed before any others. */ static krb5_error_code @@ -1904,9 +1380,7 @@ init_creds_step_reply(krb5_context context, &encrypting_key); if (code != 0) goto cleanup; - code = decrypt_as_reply(context, NULL, ctx->reply, NULL, NULL, - &encrypting_key, krb5_kdc_rep_decrypt_proc, - NULL); + code = decrypt_as_reply(context, NULL, ctx->reply, &encrypting_key); } else code = -1; @@ -1925,9 +1399,7 @@ init_creds_step_reply(krb5_context context, if (code != 0) goto cleanup; - code = decrypt_as_reply(context, NULL, ctx->reply, NULL, NULL, - &encrypting_key, krb5_kdc_rep_decrypt_proc, - NULL); + code = decrypt_as_reply(context, NULL, ctx->reply, &encrypting_key); if (code != 0) goto cleanup; } diff --git a/src/lib/krb5/krb/in_tkt_sky.c b/src/lib/krb5/krb/in_tkt_sky.c index 01c8905f8..f2888e5d4 100644 --- a/src/lib/krb5/krb/in_tkt_sky.c +++ b/src/lib/krb5/krb/in_tkt_sky.c @@ -31,39 +31,21 @@ #include "k5-int.h" -struct skey_keyproc_arg { - const krb5_keyblock *key; - krb5_principal client; /* it's a pointer, really! */ -}; - -/* - * Key-generator for in_tkt_skey, below. - * "keyseed" is actually a krb5_keyblock *, or NULL if we should fetch - * from system area. - */ +/* A krb5_gic_get_as_key_fct shim for copying a caller-provided keyblock into + * the AS keyblock. */ static krb5_error_code -skey_keyproc(krb5_context context, krb5_enctype type, krb5_data *salt, - krb5_const_pointer keyseed, krb5_keyblock **key) +get_as_key_skey(krb5_context context, krb5_principal client, + krb5_enctype etype, krb5_prompter_fct prompter, + void *prompter_data, krb5_data *salt, krb5_data *params, + krb5_keyblock *as_key, void *gak_data) { - krb5_keyblock *realkey; - krb5_error_code retval; - const krb5_keyblock * keyblock; - - keyblock = (const krb5_keyblock *)keyseed; - - if (!krb5_c_valid_enctype(type)) - return KRB5_PROG_ETYPE_NOSUPP; - - if ((retval = krb5_copy_keyblock(context, keyblock, &realkey))) - return retval; - - if (realkey->enctype != type) { - krb5_free_keyblock(context, realkey); - return KRB5_PROG_ETYPE_NOSUPP; - } + const krb5_keyblock *key = gak_data; - *key = realkey; - return 0; + if (!krb5_c_valid_enctype(etype)) + return(KRB5_PROG_ETYPE_NOSUPP); + if (as_key->length) + krb5_free_keyblock_contents(context, as_key); + return krb5int_c_copy_keyblock_contents(context, key, as_key); } /* @@ -94,15 +76,45 @@ krb5_get_in_tkt_with_skey(krb5_context context, krb5_flags options, const krb5_keyblock *key, krb5_ccache ccache, krb5_creds *creds, krb5_kdc_rep **ret_as_reply) { - if (key) - return krb5_get_in_tkt(context, options, addrs, ktypes, pre_auth_types, - skey_keyproc, (krb5_const_pointer)key, - krb5_kdc_rep_decrypt_proc, 0, creds, - ccache, ret_as_reply); + krb5_error_code retval; + char *server; + krb5_principal server_princ, client_princ; + int use_master = 0; + krb5_get_init_creds_opt *opts = NULL; + #ifndef LEAN_CLIENT - else + if (key == NULL) { return krb5_get_in_tkt_with_keytab(context, options, addrs, ktypes, pre_auth_types, NULL, ccache, creds, ret_as_reply); + } #endif /* LEAN_CLIENT */ + + retval = krb5int_populate_gic_opt(context, &opts, options, addrs, ktypes, + pre_auth_types, creds); + if (retval) + return retval; + retval = krb5_unparse_name(context, creds->server, &server); + if (retval) { + krb5_get_init_creds_opt_free(context, opts); + return retval; + } + server_princ = creds->server; + client_princ = creds->client; + retval = krb5int_get_init_creds(context, creds, creds->client, + krb5_prompter_posix, NULL, 0, server, opts, + get_as_key_skey, (void *) key, &use_master, + ret_as_reply); + krb5_free_unparsed_name(context, server); + krb5_get_init_creds_opt_free(context, opts); + if (retval) + return retval; + krb5_free_principal( context, creds->server); + krb5_free_principal( context, creds->client); + creds->client = client_princ; + creds->server = server_princ; + /* store it in the ccache! */ + if (ccache) + retval = krb5_cc_store_cred(context, ccache, creds); + return retval; } diff --git a/src/lib/krb5/krb/preauth.c b/src/lib/krb5/krb/preauth.c deleted file mode 100644 index 51c941733..000000000 --- a/src/lib/krb5/krb/preauth.c +++ /dev/null @@ -1,567 +0,0 @@ -/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - * Copyright 1995 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. - * - */ - -/* - * This file contains routines for establishing, verifying, and any other - * necessary functions, for utilizing the pre-authentication field of the - * kerberos kdc request, with various hardware/software verification devices. - */ - -#include "k5-int.h" -#include -#include - -/* some typedefs for the function args to make things look a bit cleaner */ - -typedef krb5_error_code (*git_key_proc)( - krb5_context, - const krb5_enctype, - krb5_data *, - krb5_const_pointer, - krb5_keyblock **); - -typedef krb5_error_code (*git_decrypt_proc)( - krb5_context, - const krb5_keyblock *, - krb5_const_pointer, - krb5_kdc_rep *); - -static krb5_error_code obtain_enc_ts_padata( - krb5_context, - krb5_pa_data *, - krb5_etype_info, - krb5_keyblock *, - git_key_proc, - krb5_const_pointer, - krb5_creds *, - krb5_kdc_req *, - krb5_pa_data **); - -static krb5_error_code process_pw_salt( - krb5_context, - krb5_pa_data *, - krb5_kdc_req *, - krb5_kdc_rep *, - git_key_proc, - krb5_const_pointer, - git_decrypt_proc, - krb5_keyblock **, - krb5_creds *, - krb5_int32 *, - krb5_int32 *); - -static krb5_error_code obtain_sam_padata( - krb5_context, - krb5_pa_data *, - krb5_etype_info, - krb5_keyblock *, - git_key_proc, - krb5_const_pointer, - krb5_creds *, - krb5_kdc_req *, - krb5_pa_data **); - -static const krb5_preauth_ops preauth_systems[] = { - { - KV5M_PREAUTH_OPS, - KRB5_PADATA_ENC_TIMESTAMP, - 0, - obtain_enc_ts_padata, - 0, - }, - { - KV5M_PREAUTH_OPS, - KRB5_PADATA_PW_SALT, - 0, - 0, - process_pw_salt, - }, - { - KV5M_PREAUTH_OPS, - KRB5_PADATA_AFS3_SALT, - 0, - 0, - process_pw_salt, - }, - { - KV5M_PREAUTH_OPS, - KRB5_PADATA_SAM_CHALLENGE, - 0, - obtain_sam_padata, - 0, - }, - { KV5M_PREAUTH_OPS, -1 } -}; - -static krb5_error_code -find_pa_system(krb5_preauthtype type, const krb5_preauth_ops **Preauth_proc); - -krb5_error_code krb5_obtain_padata(krb5_context context, krb5_pa_data **preauth_to_use, git_key_proc key_proc, krb5_const_pointer key_seed, krb5_creds *creds, krb5_kdc_req *request) -{ - krb5_error_code retval; - krb5_etype_info etype_info = 0; - krb5_pa_data ** pa; - krb5_pa_data ** send_pa_list; - krb5_pa_data ** send_pa; - const krb5_preauth_ops *ops; - krb5_keyblock * def_enc_key = 0; - krb5_enctype enctype; - krb5_data salt; - krb5_data scratch; - int size; - int f_salt = 0; - - if (preauth_to_use == NULL) - return 0; - - for (pa = preauth_to_use, size=0; *pa; pa++, size++) { - if ((*pa)->pa_type == KRB5_PADATA_ETYPE_INFO) { - /* XXX use the first one. Is there another way to disambiguate? */ - if (etype_info) - continue; - - scratch.length = (*pa)->length; - scratch.data = (char *) (*pa)->contents; - retval = decode_krb5_etype_info(&scratch, &etype_info); - if (retval) - return retval; - if (etype_info[0] == NULL) { - krb5_free_etype_info(context, etype_info); - etype_info = NULL; - } - } - } - - if ((send_pa_list = malloc((size+1) * sizeof(krb5_pa_data *))) == NULL) - return ENOMEM; - - send_pa = send_pa_list; - *send_pa = 0; - - enctype = request->ktype[0]; - salt.data = 0; - salt.length = SALT_TYPE_NO_LENGTH; - if (etype_info) { - enctype = etype_info[0]->etype; - salt.data = (char *) etype_info[0]->salt; - if(etype_info[0]->length == KRB5_ETYPE_NO_SALT) - salt.length = SALT_TYPE_NO_LENGTH; /* XXX */ - else - salt.length = etype_info[0]->length; - } - if (salt.length == SALT_TYPE_NO_LENGTH) { - /* - * This will set the salt length - */ - if ((retval = krb5_principal2salt(context, request->client, &salt))) - goto cleanup; - f_salt = 1; - } - - if ((retval = (*key_proc)(context, enctype, &salt, key_seed, - &def_enc_key))) - goto cleanup; - - - for (pa = preauth_to_use; *pa; pa++) { - if (find_pa_system((*pa)->pa_type, &ops)) - continue; - - if (ops->obtain == 0) - continue; - - retval = ((ops)->obtain)(context, *pa, etype_info, def_enc_key, - key_proc, key_seed, creds, - request, send_pa); - if (retval) - goto cleanup; - - if (*send_pa) - send_pa++; - *send_pa = 0; - } - - retval = 0; - - if (send_pa_list[0]) { - request->padata = send_pa_list; - send_pa_list = 0; - } - -cleanup: - if (etype_info) - krb5_free_etype_info(context, etype_info); - if (f_salt) - free(salt.data); - if (send_pa_list) - krb5_free_pa_data(context, send_pa_list); - if (def_enc_key) - krb5_free_keyblock(context, def_enc_key); - return retval; - -} - -krb5_error_code -krb5_process_padata(krb5_context context, krb5_kdc_req *request, krb5_kdc_rep *as_reply, git_key_proc key_proc, krb5_const_pointer keyseed, git_decrypt_proc decrypt_proc, krb5_keyblock **decrypt_key, krb5_creds *creds, krb5_int32 *do_more) -{ - krb5_error_code retval = 0; - const krb5_preauth_ops * ops; - krb5_pa_data ** pa; - krb5_int32 done = 0; - - *do_more = 0; /* By default, we don't need to repeat... */ - if (as_reply->padata == 0) - return 0; - - for (pa = as_reply->padata; *pa; pa++) { - if (find_pa_system((*pa)->pa_type, &ops)) - continue; - - if (ops->process == 0) - continue; - - retval = ((ops)->process)(context, *pa, request, as_reply, - key_proc, keyseed, decrypt_proc, - decrypt_key, creds, do_more, &done); - if (retval) - goto cleanup; - if (done) - break; - } - -cleanup: - return retval; -} - -/* - * This routine is the "obtain" function for the ENC_TIMESTAMP - * preauthentication type. It take the current time and encrypts it - * in the user's key. - */ -static krb5_error_code -obtain_enc_ts_padata(krb5_context context, krb5_pa_data *in_padata, krb5_etype_info etype_info, krb5_keyblock *def_enc_key, git_key_proc key_proc, krb5_const_pointer key_seed, krb5_creds *creds, krb5_kdc_req *request, krb5_pa_data **out_padata) -{ - krb5_pa_enc_ts pa_enc; - krb5_error_code retval; - krb5_data * scratch; - krb5_enc_data enc_data; - krb5_pa_data * pa; - - retval = krb5_us_timeofday(context, &pa_enc.patimestamp, &pa_enc.pausec); - if (retval) - return retval; - - if ((retval = encode_krb5_pa_enc_ts(&pa_enc, &scratch)) != 0) - return retval; - - enc_data.ciphertext.data = 0; - - if ((retval = krb5_encrypt_helper(context, def_enc_key, - KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS, - scratch, &enc_data))) - goto cleanup; - - krb5_free_data(context, scratch); - scratch = 0; - - if ((retval = encode_krb5_enc_data(&enc_data, &scratch)) != 0) - goto cleanup; - - if ((pa = malloc(sizeof(krb5_pa_data))) == NULL) { - retval = ENOMEM; - goto cleanup; - } - - pa->magic = KV5M_PA_DATA; - pa->pa_type = KRB5_PADATA_ENC_TIMESTAMP; - pa->length = scratch->length; - pa->contents = (krb5_octet *) scratch->data; - - *out_padata = pa; - - free(scratch); - scratch = 0; - - retval = 0; - -cleanup: - if (scratch) - krb5_free_data(context, scratch); - if (enc_data.ciphertext.data) - free(enc_data.ciphertext.data); - return retval; -} - -static krb5_error_code -process_pw_salt(krb5_context context, krb5_pa_data *padata, krb5_kdc_req *request, krb5_kdc_rep *as_reply, git_key_proc key_proc, krb5_const_pointer keyseed, git_decrypt_proc decrypt_proc, krb5_keyblock **decrypt_key, krb5_creds *creds, krb5_int32 *do_more, krb5_int32 *done) -{ - krb5_error_code retval; - krb5_data salt; - - if (*decrypt_key != 0) - return 0; - - salt.data = (char *) padata->contents; - salt.length = - (padata->pa_type == KRB5_PADATA_AFS3_SALT)?(SALT_TYPE_AFS_LENGTH):(padata->length); - - if ((retval = (*key_proc)(context, as_reply->enc_part.enctype, - &salt, keyseed, decrypt_key))) { - *decrypt_key = 0; - return retval; - } - - return 0; -} - -static krb5_error_code -find_pa_system(krb5_preauthtype type, const krb5_preauth_ops **preauth) -{ - const krb5_preauth_ops *ap = preauth_systems; - - while ((ap->type != -1) && (ap->type != type)) - ap++; - if (ap->type == -1) - return(KRB5_PREAUTH_BAD_TYPE); - *preauth = ap; - return 0; -} - - -extern const char *krb5_default_pwd_prompt1; - -static krb5_error_code -sam_get_pass_from_user(krb5_context context, krb5_etype_info etype_info, git_key_proc key_proc, krb5_const_pointer key_seed, krb5_kdc_req *request, krb5_keyblock **new_enc_key, const char *prompt) -{ - krb5_enctype enctype; - krb5_error_code retval; - const char *oldprompt; - - /* enctype = request->ktype[0]; */ - enctype = ENCTYPE_DES_CBC_MD5; -/* hack with this first! */ - oldprompt = krb5_default_pwd_prompt1; - krb5_default_pwd_prompt1 = prompt; - { - krb5_data newpw; - newpw.data = 0; newpw.length = 0; - /* we don't keep the new password, just the key... */ - retval = (*key_proc)(context, enctype, 0, - (krb5_const_pointer)&newpw, new_enc_key); - free(newpw.data); - } - krb5_default_pwd_prompt1 = oldprompt; - return retval; -} -static -char *handle_sam_labels(krb5_sam_challenge *sc) -{ - char *label = sc->sam_challenge_label.data; - unsigned int label_len = sc->sam_challenge_label.length; - char *prompt = sc->sam_response_prompt.data; - unsigned int prompt_len = sc->sam_response_prompt.length; - char *challenge = sc->sam_challenge.data; - unsigned int challenge_len = sc->sam_challenge.length; - struct k5buf buf; - - if (sc->sam_cksum.length == 0) { - /* or invalid -- but lets just handle presence now XXX */ - switch (sc->sam_type) { - case PA_SAM_TYPE_ENIGMA: /* Enigma Logic */ - label = "Challenge for Enigma Logic mechanism"; - break; - case PA_SAM_TYPE_DIGI_PATH: /* Digital Pathways */ - case PA_SAM_TYPE_DIGI_PATH_HEX: /* Digital Pathways */ - label = "Challenge for Digital Pathways mechanism"; - break; - case PA_SAM_TYPE_ACTIVCARD_DEC: /* Digital Pathways */ - case PA_SAM_TYPE_ACTIVCARD_HEX: /* Digital Pathways */ - label = "Challenge for Activcard mechanism"; - break; - case PA_SAM_TYPE_SKEY_K0: /* S/key where KDC has key 0 */ - label = "Challenge for Enhanced S/Key mechanism"; - break; - case PA_SAM_TYPE_SKEY: /* Traditional S/Key */ - label = "Challenge for Traditional S/Key mechanism"; - break; - case PA_SAM_TYPE_SECURID: /* Security Dynamics */ - label = "Challenge for Security Dynamics mechanism"; - break; - case PA_SAM_TYPE_SECURID_PREDICT: /* predictive Security Dynamics */ - label = "Challenge for Security Dynamics mechanism"; - break; - } - prompt = "Passcode"; - label_len = strlen(label); - prompt_len = strlen(prompt); - } - - /* example: - Challenge for Digital Pathways mechanism: [134591] - Passcode: - */ - krb5int_buf_init_dynamic(&buf); - if (challenge_len) { - krb5int_buf_add_len(&buf, label, label_len); - krb5int_buf_add(&buf, ": ["); - krb5int_buf_add_len(&buf, challenge, challenge_len); - krb5int_buf_add(&buf, "]\n"); - } - krb5int_buf_add_len(&buf, prompt, prompt_len); - krb5int_buf_add(&buf, ": "); - return krb5int_buf_data(&buf); -} - -/* - * This routine is the "obtain" function for the SAM_CHALLENGE - * preauthentication type. It presents the challenge... - */ -static krb5_error_code -obtain_sam_padata(krb5_context context, krb5_pa_data *in_padata, krb5_etype_info etype_info, krb5_keyblock *def_enc_key, git_key_proc key_proc, krb5_const_pointer key_seed, krb5_creds *creds, krb5_kdc_req *request, krb5_pa_data **out_padata) -{ - krb5_error_code retval; - krb5_data * scratch = 0; - krb5_data tmpsam; - krb5_pa_data * pa; - krb5_sam_challenge *sam_challenge = 0; - krb5_sam_response sam_response; - /* these two get encrypted and stuffed in to sam_response */ - krb5_enc_sam_response_enc enc_sam_response_enc; - krb5_keyblock * sam_use_key = 0; - char *prompt = 0, *passcode = 0; - - sam_response.sam_enc_nonce_or_ts.ciphertext.data = 0; - - tmpsam.length = in_padata->length; - tmpsam.data = (char *) in_padata->contents; - retval = decode_krb5_sam_challenge(&tmpsam, &sam_challenge); - if (retval) - return retval; - - if (sam_challenge->sam_flags & KRB5_SAM_MUST_PK_ENCRYPT_SAD) { - retval = KRB5_SAM_UNSUPPORTED; - goto cleanup; - } - - enc_sam_response_enc.sam_nonce = sam_challenge->sam_nonce; - if (!sam_challenge->sam_nonce) { - retval = krb5_us_timeofday(context, - &enc_sam_response_enc.sam_timestamp, - &enc_sam_response_enc.sam_usec); - if (retval) - goto cleanup; - sam_response.sam_patimestamp = enc_sam_response_enc.sam_timestamp; - } - if (sam_challenge->sam_flags & KRB5_SAM_SEND_ENCRYPTED_SAD) { - /* encrypt passcode in key by stuffing it here */ - unsigned int pcsize = 256; - passcode = malloc(pcsize + 1); - if (passcode == NULL) { - retval = ENOMEM; - goto cleanup; - } - prompt = handle_sam_labels(sam_challenge); - if (prompt == NULL) { - retval = ENOMEM; - goto cleanup; - } - retval = krb5_read_password(context, prompt, 0, passcode, &pcsize); - if (retval) - goto cleanup; - enc_sam_response_enc.sam_sad.data = passcode; - enc_sam_response_enc.sam_sad.length = pcsize; - } else if (sam_challenge->sam_flags & KRB5_SAM_USE_SAD_AS_KEY) { - prompt = handle_sam_labels(sam_challenge); - if (prompt == NULL) { - retval = ENOMEM; - goto cleanup; - } - retval = sam_get_pass_from_user(context, etype_info, key_proc, - key_seed, request, &sam_use_key, - prompt); - if (retval) - goto cleanup; - enc_sam_response_enc.sam_sad.length = 0; - } else { - /* what *was* it? */ - retval = KRB5_SAM_UNSUPPORTED; - goto cleanup; - } - - /* so at this point, either sam_use_key is generated from the passcode - * or enc_sam_response_enc.sam_sad is set to it, and we use - * def_enc_key instead. */ - /* encode the encoded part of the response */ - if ((retval = encode_krb5_enc_sam_response_enc(&enc_sam_response_enc, - &scratch)) != 0) - goto cleanup; - - if ((retval = krb5_encrypt_helper(context, - sam_use_key?sam_use_key:def_enc_key, - 0, scratch, - &sam_response.sam_enc_nonce_or_ts))) - goto cleanup; - - krb5_free_data(context, scratch); - scratch = 0; - - /* sam_enc_key is reserved for future use */ - sam_response.sam_enc_key.ciphertext.length = 0; - - /* copy things from the challenge */ - sam_response.sam_nonce = sam_challenge->sam_nonce; - sam_response.sam_flags = sam_challenge->sam_flags; - sam_response.sam_track_id = sam_challenge->sam_track_id; - sam_response.sam_type = sam_challenge->sam_type; - sam_response.magic = KV5M_SAM_RESPONSE; - - if ((retval = encode_krb5_sam_response(&sam_response, &scratch)) != 0) - goto cleanup; - - if ((pa = malloc(sizeof(krb5_pa_data))) == NULL) { - retval = ENOMEM; - goto cleanup; - } - - pa->magic = KV5M_PA_DATA; - pa->pa_type = KRB5_PADATA_SAM_RESPONSE; - pa->length = scratch->length; - pa->contents = (krb5_octet *) scratch->data; - free(scratch); - scratch = NULL; - - *out_padata = pa; - - retval = 0; - -cleanup: - krb5_free_data(context, scratch); - krb5_free_sam_challenge(context, sam_challenge); - free(prompt); - free(passcode); - free(sam_response.sam_enc_nonce_or_ts.ciphertext.data); - return retval; -} diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports index 5c517c89c..4065bea8e 100644 --- a/src/lib/krb5/libkrb5.exports +++ b/src/lib/krb5/libkrb5.exports @@ -331,7 +331,6 @@ krb5_get_default_realm krb5_get_error_message krb5_get_fallback_host_realm krb5_get_host_realm -krb5_get_in_tkt krb5_get_in_tkt_with_keytab krb5_get_in_tkt_with_password krb5_get_in_tkt_with_skey @@ -428,7 +427,6 @@ krb5_mk_req_extended krb5_mk_safe krb5_net_read krb5_net_write -krb5_obtain_padata krb5_os_free_context krb5_os_hostaddr krb5_os_init_context @@ -448,7 +446,6 @@ krb5_principal2salt_norealm krb5_principal_compare krb5_principal_compare_any_realm krb5_principal_compare_flags -krb5_process_padata krb5_prompter_posix krb5_rc_close krb5_rc_default -- 2.26.2