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*/
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 *,
pac_sign.o \
parse.o \
pr_to_salt.o \
- preauth.o \
preauth2.o \
gic_opt_set_pa.o \
princ_comp.o \
$(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) \
$(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 \
* or implied warranty.
*
*
- * krb5_get_in_tkt()
*/
#include <string.h>
#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 ***);
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 <kerberosIV/prot.h> 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);
}
/**
}
#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)
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
&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;
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;
}
#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);
}
/*
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;
}
+++ /dev/null
-/* -*- 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 <stdio.h>
-#include <time.h>
-
-/* 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;
-}
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
krb5_mk_safe
krb5_net_read
krb5_net_write
-krb5_obtain_padata
krb5_os_free_context
krb5_os_hostaddr
krb5_os_init_context
krb5_principal_compare
krb5_principal_compare_any_realm
krb5_principal_compare_flags
-krb5_process_padata
krb5_prompter_posix
krb5_rc_close
krb5_rc_default