diff options
Diffstat (limited to 'crypto/heimdal/kuser/kinit.c')
-rw-r--r-- | crypto/heimdal/kuser/kinit.c | 633 |
1 files changed, 387 insertions, 246 deletions
diff --git a/crypto/heimdal/kuser/kinit.c b/crypto/heimdal/kuser/kinit.c index 4b8b24a..2676309 100644 --- a/crypto/heimdal/kuser/kinit.c +++ b/crypto/heimdal/kuser/kinit.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2002 Kungliga Tekniska Högskolan + * Copyright (c) 1997-2007 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -32,41 +32,60 @@ */ #include "kuser_locl.h" -RCSID("$Id: kinit.c,v 1.90.4.5 2004/06/21 08:17:06 lha Exp $"); +RCSID("$Id: kinit.c 22116 2007-12-03 21:22:58Z lha $"); + +#include "krb5-v4compat.h" + +#include "heimntlm.h" int forwardable_flag = -1; int proxiable_flag = -1; int renewable_flag = -1; int renew_flag = 0; +int pac_flag = -1; int validate_flag = 0; int version_flag = 0; int help_flag = 0; -int addrs_flag = 1; +int addrs_flag = -1; struct getarg_strings extra_addresses; int anonymous_flag = 0; char *lifetime = NULL; char *renew_life = NULL; -char *server = NULL; +char *server_str = NULL; char *cred_cache = NULL; char *start_str = NULL; struct getarg_strings etype_str; int use_keytab = 0; char *keytab_str = NULL; int do_afslog = -1; -#ifdef KRB4 int get_v4_tgt = -1; -int convert_524; -#endif +int convert_524 = 0; int fcache_version; +char *password_file = NULL; +char *pk_user_id = NULL; +char *pk_x509_anchors = NULL; +int pk_use_enckey = 0; +static int canonicalize_flag = 0; +static char *ntlm_domain; + +static char *krb4_cc_name; static struct getargs args[] = { -#ifdef KRB4 + /* + * used by MIT + * a: ~A + * V: verbose + * F: ~f + * P: ~p + * C: v4 cache name? + * 5: + */ { "524init", '4', arg_flag, &get_v4_tgt, "obtain version 4 TGT" }, - + { "524convert", '9', arg_flag, &convert_524, "only convert ticket to version 4" }, -#endif + { "afslog", 0 , arg_flag, &do_afslog, "obtain afs tokens" }, @@ -94,7 +113,7 @@ static struct getargs args[] = { { "renewable-life", 'r', arg_string, &renew_life, "renewable lifetime of tickets", "time" }, - { "server", 'S', arg_string, &server, + { "server", 'S', arg_string, &server_str, "server to get ticket for", "principal" }, { "start-time", 's', arg_string, &start_str, @@ -112,7 +131,7 @@ static struct getargs args[] = { { "fcache-version", 0, arg_integer, &fcache_version, "file cache version to create" }, - { "addresses", 0, arg_negative_flag, &addrs_flag, + { "addresses", 'A', arg_negative_flag, &addrs_flag, "request a ticket with no addresses" }, { "extra-addresses",'a', arg_strings, &extra_addresses, @@ -121,6 +140,27 @@ static struct getargs args[] = { { "anonymous", 0, arg_flag, &anonymous_flag, "request an anonymous ticket" }, + { "request-pac", 0, arg_flag, &pac_flag, + "request a Windows PAC" }, + + { "password-file", 0, arg_string, &password_file, + "read the password from a file" }, + + { "canonicalize",0, arg_flag, &canonicalize_flag, + "canonicalize client principal" }, +#ifdef PKINIT + { "pk-user", 'C', arg_string, &pk_user_id, + "principal's public/private/certificate identifier", "id" }, + + { "x509-anchors", 'D', arg_string, &pk_x509_anchors, + "directory with CA certificates", "directory" }, + + { "pk-use-enckey", 0, arg_flag, &pk_use_enckey, + "Use RSA encrypted reply (instead of DH)" }, +#endif + { "ntlm-domain", 0, arg_string, &ntlm_domain, + "NTLM domain", "domain" }, + { "version", 0, arg_flag, &version_flag }, { "help", 0, arg_flag, &help_flag } }; @@ -135,130 +175,6 @@ usage (int ret) exit (ret); } -#ifdef KRB4 -/* for when the KDC tells us it's a v4 one, we try to talk that */ - -static int -key_to_key(const char *user, - char *instance, - const char *realm, - const void *arg, - des_cblock *key) -{ - memcpy(key, arg, sizeof(des_cblock)); - return 0; -} - -static int -do_v4_fallback (krb5_context context, - const krb5_principal principal, - int lifetime, - int use_srvtab, const char *srvtab_str, - const char *passwd) -{ - int ret; - krb_principal princ; - des_cblock key; - krb5_error_code kret; - - if (lifetime == 0) - lifetime = DEFAULT_TKT_LIFE; - else - lifetime = krb_time_to_life (0, lifetime); - - kret = krb5_524_conv_principal (context, principal, - princ.name, - princ.instance, - princ.realm); - if (kret) { - krb5_warn (context, kret, "krb5_524_conv_principal"); - return 1; - } - - if (use_srvtab || srvtab_str) { - if (srvtab_str == NULL) - srvtab_str = KEYFILE; - - ret = read_service_key (princ.name, princ.instance, princ.realm, - 0, srvtab_str, (char *)&key); - if (ret) { - warnx ("read_service_key %s: %s", srvtab_str, - krb_get_err_text (ret)); - return 1; - } - ret = krb_get_in_tkt (princ.name, princ.instance, princ.realm, - KRB_TICKET_GRANTING_TICKET, princ.realm, - lifetime, key_to_key, NULL, key); - } else { - ret = krb_get_pw_in_tkt(princ.name, princ.instance, princ.realm, - KRB_TICKET_GRANTING_TICKET, princ.realm, - lifetime, passwd); - } - memset (key, 0, sizeof(key)); - if (ret) { - warnx ("%s", krb_get_err_text(ret)); - return 1; - } - if (do_afslog && k_hasafs()) { - if ((ret = krb_afslog(NULL, NULL)) != 0 && ret != KDC_PR_UNKNOWN) { - if(ret > 0) - warnx ("%s", krb_get_err_text(ret)); - else - warnx ("failed to store AFS token"); - } - } - return 0; -} - - -/* - * the special version of get_default_principal that takes v4 into account - */ - -static krb5_error_code -kinit_get_default_principal (krb5_context context, - krb5_principal *princ) -{ - krb5_error_code ret; - krb5_ccache id; - krb_principal v4_princ; - int kret; - - ret = krb5_cc_default (context, &id); - if (ret == 0) { - ret = krb5_cc_get_principal (context, id, princ); - krb5_cc_close (context, id); - if (ret == 0) - return 0; - } - - kret = krb_get_tf_fullname (tkt_string(), - v4_princ.name, - v4_princ.instance, - v4_princ.realm); - if (kret == KSUCCESS) { - ret = krb5_425_conv_principal (context, - v4_princ.name, - v4_princ.instance, - v4_princ.realm, - princ); - if (ret == 0) - return 0; - } - return krb5_get_default_principal (context, princ); -} - -#else /* !KRB4 */ - -static krb5_error_code -kinit_get_default_principal (krb5_context context, - krb5_principal *princ) -{ - return krb5_get_default_principal (context, princ); -} - -#endif /* !KRB4 */ - static krb5_error_code get_server(krb5_context context, krb5_principal client, @@ -274,13 +190,13 @@ get_server(krb5_context context, KRB5_TGS_NAME, *client_realm, NULL); } -#ifdef KRB4 static krb5_error_code do_524init(krb5_context context, krb5_ccache ccache, krb5_creds *creds, const char *server) { krb5_error_code ret; - CREDENTIALS c; + + struct credentials c; krb5_creds in_creds, *real_creds; if(creds != NULL) @@ -305,9 +221,9 @@ do_524init(krb5_context context, krb5_ccache ccache, if(ret) krb5_warn(context, ret, "converting creds"); else { - int tret = tf_setup(&c, c.pname, c.pinst); + krb5_error_code tret = _krb5_krb_tf_setup(context, &c, NULL, 0); if(tret) - krb5_warnx(context, "saving v4 creds: %s", krb_get_err_text(tret)); + krb5_warn(context, tret, "saving v4 creds"); } if(creds == NULL) @@ -316,7 +232,6 @@ do_524init(krb5_context context, krb5_ccache ccache, return ret; } -#endif static int renew_validate(krb5_context context, @@ -327,7 +242,7 @@ renew_validate(krb5_context context, krb5_deltat life) { krb5_error_code ret; - krb5_creds in, *out; + krb5_creds in, *out = NULL; krb5_kdc_flags flags; memset(&in, 0, sizeof(in)); @@ -342,18 +257,40 @@ renew_validate(krb5_context context, krb5_warn(context, ret, "get_server"); goto out; } + + if (renew) { + /* + * no need to check the error here, it's only to be + * friendly to the user + */ + krb5_get_credentials(context, KRB5_GC_CACHED, cache, &in, &out); + } + flags.i = 0; flags.b.renewable = flags.b.renew = renew; flags.b.validate = validate; + if (forwardable_flag != -1) flags.b.forwardable = forwardable_flag; + else if (out) + flags.b.forwardable = out->flags.b.forwardable; + if (proxiable_flag != -1) flags.b.proxiable = proxiable_flag; + else if (out) + flags.b.proxiable = out->flags.b.proxiable; + if (anonymous_flag != -1) flags.b.request_anonymous = anonymous_flag; if(life) in.times.endtime = time(NULL) + life; + if (out) { + krb5_free_creds (context, out); + out = NULL; + } + + ret = krb5_get_kdc_cred(context, cache, flags, @@ -374,11 +311,9 @@ renew_validate(krb5_context context, ret = krb5_cc_store_cred(context, cache, out); if(ret == 0 && server == NULL) { -#ifdef KRB4 /* only do this if it's a general renew-my-tgt request */ if(get_v4_tgt) do_524init(context, cache, out, NULL); -#endif if(do_afslog && k_hasafs()) krb5_afslog(context, cache, NULL, NULL); } @@ -389,57 +324,137 @@ renew_validate(krb5_context context, goto out; } out: - krb5_free_creds_contents(context, &in); + krb5_free_cred_contents(context, &in); return ret; } static krb5_error_code +store_ntlmkey(krb5_context context, krb5_ccache id, + const char *domain, krb5_const_principal client, + struct ntlm_buf *buf) +{ + krb5_error_code ret; + krb5_creds cred; + + memset(&cred, 0, sizeof(cred)); + + ret = krb5_make_principal(context, &cred.server, + krb5_principal_get_realm(context, client), + "@ntlm-key", domain, NULL); + if (ret) + goto out; + ret = krb5_copy_principal(context, client, &cred.client); + if (ret) + goto out; + + cred.times.authtime = time(NULL); + cred.times.endtime = time(NULL) + 3600 * 24 * 30; /* XXX */ + cred.session.keytype = ENCTYPE_ARCFOUR_HMAC_MD5; + ret = krb5_data_copy(&cred.session.keyvalue, buf->data, buf->length); + if (ret) + goto out; + + ret = krb5_cc_store_cred(context, id, &cred); + +out: + krb5_free_cred_contents (context, &cred); + return 0; +} + +static krb5_error_code get_new_tickets(krb5_context context, krb5_principal principal, krb5_ccache ccache, - krb5_deltat ticket_life) + krb5_deltat ticket_life, + int interactive) { krb5_error_code ret; - krb5_get_init_creds_opt opt; - krb5_addresses no_addrs; + krb5_get_init_creds_opt *opt; krb5_creds cred; char passwd[256]; krb5_deltat start_time = 0; krb5_deltat renew = 0; + char *renewstr = NULL; + krb5_enctype *enctype = NULL; + struct ntlm_buf ntlmkey; + krb5_ccache tempccache; + + memset(&ntlmkey, 0, sizeof(ntlmkey)); + passwd[0] = '\0'; + + if (password_file) { + FILE *f; + + if (strcasecmp("STDIN", password_file) == 0) + f = stdin; + else + f = fopen(password_file, "r"); + if (f == NULL) + krb5_errx(context, 1, "Failed to open the password file %s", + password_file); + + if (fgets(passwd, sizeof(passwd), f) == NULL) + krb5_errx(context, 1, + "Failed to read password from file %s", password_file); + if (f != stdin) + fclose(f); + passwd[strcspn(passwd, "\n")] = '\0'; + } + memset(&cred, 0, sizeof(cred)); - krb5_get_init_creds_opt_init (&opt); + ret = krb5_get_init_creds_opt_alloc (context, &opt); + if (ret) + krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc"); - krb5_get_init_creds_opt_set_default_flags(context, "kinit", - /* XXX */principal->realm, &opt); + krb5_get_init_creds_opt_set_default_flags(context, "kinit", + krb5_principal_get_realm(context, principal), opt); if(forwardable_flag != -1) - krb5_get_init_creds_opt_set_forwardable (&opt, forwardable_flag); + krb5_get_init_creds_opt_set_forwardable (opt, forwardable_flag); if(proxiable_flag != -1) - krb5_get_init_creds_opt_set_proxiable (&opt, proxiable_flag); + krb5_get_init_creds_opt_set_proxiable (opt, proxiable_flag); if(anonymous_flag != -1) - krb5_get_init_creds_opt_set_anonymous (&opt, anonymous_flag); - - if (!addrs_flag) { - no_addrs.len = 0; - no_addrs.val = NULL; - - krb5_get_init_creds_opt_set_address_list (&opt, &no_addrs); + krb5_get_init_creds_opt_set_anonymous (opt, anonymous_flag); + if (pac_flag != -1) + krb5_get_init_creds_opt_set_pac_request(context, opt, + pac_flag ? TRUE : FALSE); + if (canonicalize_flag) + krb5_get_init_creds_opt_set_canonicalize(context, opt, TRUE); + if (pk_user_id) { + ret = krb5_get_init_creds_opt_set_pkinit(context, opt, + principal, + pk_user_id, + pk_x509_anchors, + NULL, + NULL, + pk_use_enckey ? 2 : 0, + krb5_prompter_posix, + NULL, + passwd); + if (ret) + krb5_err(context, 1, ret, "krb5_get_init_creds_opt_set_pkinit"); } + if (addrs_flag != -1) + krb5_get_init_creds_opt_set_addressless(context, opt, + addrs_flag ? FALSE : TRUE); + if (renew_life == NULL && renewable_flag) - renew_life = "1 month"; - if(renew_life) { - renew = parse_time (renew_life, "s"); + renewstr = "1 month"; + if (renew_life) + renewstr = renew_life; + if (renewstr) { + renew = parse_time (renewstr, "s"); if (renew < 0) - errx (1, "unparsable time: %s", renew_life); - - krb5_get_init_creds_opt_set_renew_life (&opt, renew); + errx (1, "unparsable time: %s", renewstr); + + krb5_get_init_creds_opt_set_renew_life (opt, renew); } if(ticket_life != 0) - krb5_get_init_creds_opt_set_tkt_life (&opt, ticket_life); + krb5_get_init_creds_opt_set_tkt_life (opt, ticket_life); if(start_str) { int tmp = parse_time (start_str, "s"); @@ -450,8 +465,8 @@ get_new_tickets(krb5_context context, } if(etype_str.num_strings) { - krb5_enctype *enctype = NULL; int i; + enctype = malloc(etype_str.num_strings * sizeof(*enctype)); if(enctype == NULL) errx(1, "out of memory"); @@ -462,7 +477,7 @@ get_new_tickets(krb5_context context, if(ret) errx(1, "unrecognized enctype: %s", etype_str.strings[i]); } - krb5_get_init_creds_opt_set_etype_list(&opt, enctype, + krb5_get_init_creds_opt_set_etype_list(opt, enctype, etype_str.num_strings); } @@ -479,23 +494,40 @@ get_new_tickets(krb5_context context, principal, kt, start_time, - server, - &opt); + server_str, + opt); krb5_kt_close(context, kt); + } else if (pk_user_id) { + ret = krb5_get_init_creds_password (context, + &cred, + principal, + passwd, + krb5_prompter_posix, + NULL, + start_time, + server_str, + opt); + } else if (!interactive) { + krb5_warnx(context, "Not interactive, failed to get initial ticket"); + krb5_get_init_creds_opt_free(context, opt); + return 0; } else { - char *p, *prompt; - - krb5_unparse_name (context, principal, &p); - asprintf (&prompt, "%s's Password: ", p); - free (p); - if (des_read_pw_string(passwd, sizeof(passwd)-1, prompt, 0)){ - memset(passwd, 0, sizeof(passwd)); - exit(1); + if (passwd[0] == '\0') { + char *p, *prompt; + + krb5_unparse_name (context, principal, &p); + asprintf (&prompt, "%s's Password: ", p); + free (p); + + if (UI_UTIL_read_pw_string(passwd, sizeof(passwd)-1, prompt, 0)){ + memset(passwd, 0, sizeof(passwd)); + exit(1); + } + free (prompt); } - free (prompt); - + ret = krb5_get_init_creds_password (context, &cred, principal, @@ -503,22 +535,12 @@ get_new_tickets(krb5_context context, krb5_prompter_posix, NULL, start_time, - server, - &opt); + server_str, + opt); } -#ifdef KRB4 - if (ret == KRB5KRB_AP_ERR_V4_REPLY || ret == KRB5_KDC_UNREACH) { - int exit_val; - - exit_val = do_v4_fallback (context, principal, ticket_life, - use_keytab, keytab_str, passwd); - get_v4_tgt = 0; - do_afslog = 0; - memset(passwd, 0, sizeof(passwd)); - if (exit_val == 0 || ret == KRB5KRB_AP_ERR_V4_REPLY) - return exit_val; - } -#endif + krb5_get_init_creds_opt_free(context, opt); + if (ntlm_domain && passwd[0]) + heim_ntlm_nt_key(passwd, &ntlmkey); memset(passwd, 0, sizeof(passwd)); switch(ret){ @@ -528,43 +550,136 @@ get_new_tickets(krb5_context context, exit(1); case KRB5KRB_AP_ERR_BAD_INTEGRITY: case KRB5KRB_AP_ERR_MODIFIED: + case KRB5KDC_ERR_PREAUTH_FAILED: krb5_errx(context, 1, "Password incorrect"); break; + case KRB5KRB_AP_ERR_V4_REPLY: + krb5_errx(context, 1, "Looks like a Kerberos 4 reply"); + break; default: krb5_err(context, 1, ret, "krb5_get_init_creds"); } if(ticket_life != 0) { if(abs(cred.times.endtime - cred.times.starttime - ticket_life) > 30) { - char life[32]; - unparse_time(cred.times.endtime - cred.times.starttime, - life, sizeof(life)); + char life[64]; + unparse_time_approx(cred.times.endtime - cred.times.starttime, + life, sizeof(life)); krb5_warnx(context, "NOTICE: ticket lifetime is %s", life); } } - if(renew != 0) { + if(renew_life) { if(abs(cred.times.renew_till - cred.times.starttime - renew) > 30) { - char life[32]; - unparse_time(cred.times.renew_till - cred.times.starttime, - life, sizeof(life)); + char life[64]; + unparse_time_approx(cred.times.renew_till - cred.times.starttime, + life, sizeof(life)); krb5_warnx(context, "NOTICE: ticket renewable lifetime is %s", life); } } - ret = krb5_cc_initialize (context, ccache, cred.client); + ret = krb5_cc_new_unique(context, krb5_cc_get_type(context, ccache), + NULL, &tempccache); + if (ret) + krb5_err (context, 1, ret, "krb5_cc_new_unique"); + + ret = krb5_cc_initialize (context, tempccache, cred.client); if (ret) krb5_err (context, 1, ret, "krb5_cc_initialize"); - ret = krb5_cc_store_cred (context, ccache, &cred); + ret = krb5_cc_store_cred (context, tempccache, &cred); if (ret) krb5_err (context, 1, ret, "krb5_cc_store_cred"); - krb5_free_creds_contents (context, &cred); + krb5_free_cred_contents (context, &cred); + + ret = krb5_cc_move(context, tempccache, ccache); + if (ret) + krb5_err (context, 1, ret, "krb5_cc_move"); + + if (ntlm_domain && ntlmkey.data) + store_ntlmkey(context, ccache, ntlm_domain, principal, &ntlmkey); + + if (enctype) + free(enctype); return 0; } +static time_t +ticket_lifetime(krb5_context context, krb5_ccache cache, + krb5_principal client, const char *server) +{ + krb5_creds in_cred, *cred; + krb5_error_code ret; + time_t timeout; + + memset(&in_cred, 0, sizeof(in_cred)); + + ret = krb5_cc_get_principal(context, cache, &in_cred.client); + if(ret) { + krb5_warn(context, ret, "krb5_cc_get_principal"); + return 0; + } + ret = get_server(context, in_cred.client, server, &in_cred.server); + if(ret) { + krb5_free_principal(context, in_cred.client); + krb5_warn(context, ret, "get_server"); + return 0; + } + + ret = krb5_get_credentials(context, KRB5_GC_CACHED, + cache, &in_cred, &cred); + krb5_free_principal(context, in_cred.client); + krb5_free_principal(context, in_cred.server); + if(ret) { + krb5_warn(context, ret, "krb5_get_credentials"); + return 0; + } + timeout = cred->times.endtime - cred->times.starttime; + if (timeout < 0) + timeout = 0; + krb5_free_creds(context, cred); + return timeout; +} + +struct renew_ctx { + krb5_context context; + krb5_ccache ccache; + krb5_principal principal; + krb5_deltat ticket_life; +}; + +static time_t +renew_func(void *ptr) +{ + struct renew_ctx *ctx = ptr; + krb5_error_code ret; + time_t expire; + int new_tickets = 0; + + if (renewable_flag) { + ret = renew_validate(ctx->context, renewable_flag, validate_flag, + ctx->ccache, server_str, ctx->ticket_life); + if (ret) + new_tickets = 1; + } else + new_tickets = 1; + + if (new_tickets) + get_new_tickets(ctx->context, ctx->principal, + ctx->ccache, ctx->ticket_life, 0); + + if(get_v4_tgt || convert_524) + do_524init(ctx->context, ctx->ccache, NULL, server_str); + if(do_afslog && k_hasafs()) + krb5_afslog(ctx->context, ctx->ccache, NULL, NULL); + + expire = ticket_lifetime(ctx->context, ctx->ccache, ctx->principal, + server_str) / 2; + return expire + 1; +} + int main (int argc, char **argv) { @@ -572,16 +687,19 @@ main (int argc, char **argv) krb5_context context; krb5_ccache ccache; krb5_principal principal; - int optind = 0; + int optidx = 0; krb5_deltat ticket_life = 0; + int parseflags = 0; setprogname (argv[0]); ret = krb5_init_context (&context); - if (ret) + if (ret == KRB5_CONFIG_BADFORMAT) + errx (1, "krb5_init_context failed to parse configuration file"); + else if (ret) errx(1, "krb5_init_context failed: %d", ret); - if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind)) + if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) usage(1); if (help_flag) @@ -592,15 +710,18 @@ main (int argc, char **argv) exit(0); } - argc -= optind; - argv += optind; + argc -= optidx; + argv += optidx; + + if (canonicalize_flag) + parseflags |= KRB5_PRINCIPAL_PARSE_ENTERPRISE; if (argv[0]) { - ret = krb5_parse_name (context, argv[0], &principal); + ret = krb5_parse_name_flags (context, argv[0], parseflags, &principal); if (ret) krb5_err (context, 1, ret, "krb5_parse_name"); } else { - ret = kinit_get_default_principal (context, &principal); + ret = krb5_get_default_principal (context, &principal); if (ret) krb5_err (context, 1, ret, "krb5_get_default_principal"); } @@ -608,6 +729,20 @@ main (int argc, char **argv) if(fcache_version) krb5_set_fcache_version(context, fcache_version); + if(renewable_flag == -1) + /* this seems somewhat pointless, but whatever */ + krb5_appdefault_boolean(context, "kinit", + krb5_principal_get_realm(context, principal), + "renewable", FALSE, &renewable_flag); + if(get_v4_tgt == -1) + krb5_appdefault_boolean(context, "kinit", + krb5_principal_get_realm(context, principal), + "krb4_get_tickets", FALSE, &get_v4_tgt); + if(do_afslog == -1) + krb5_appdefault_boolean(context, "kinit", + krb5_principal_get_realm(context, principal), + "afslog", TRUE, &do_afslog); + if(cred_cache) ret = krb5_cc_resolve(context, cred_cache, &ccache); else { @@ -620,23 +755,28 @@ main (int argc, char **argv) krb5_cc_get_type(context, ccache), krb5_cc_get_name(context, ccache)); setenv("KRB5CCNAME", s, 1); -#ifdef KRB4 - { + if (get_v4_tgt) { int fd; - snprintf(s, sizeof(s), "%s_XXXXXX", TKT_ROOT); - if((fd = mkstemp(s)) >= 0) { + if (asprintf(&krb4_cc_name, "%s_XXXXXX", TKT_ROOT) < 0) + krb5_errx(context, 1, "out of memory"); + if((fd = mkstemp(krb4_cc_name)) >= 0) { close(fd); - setenv("KRBTKFILE", s, 1); + setenv("KRBTKFILE", krb4_cc_name, 1); + } else { + free(krb4_cc_name); + krb4_cc_name = NULL; } } -#endif - } else - ret = krb5_cc_default (context, &ccache); + } else { + ret = krb5_cc_cache_match(context, principal, NULL, &ccache); + if (ret) + ret = krb5_cc_default (context, &ccache); + } } if (ret) krb5_err (context, 1, ret, "resolving credentials cache"); - if (argc > 1 && k_hasafs ()) + if(argc > 1 && k_hasafs ()) k_setpag(); if (lifetime) { @@ -646,18 +786,8 @@ main (int argc, char **argv) ticket_life = tmp; } -#ifdef KRB4 - if(get_v4_tgt == -1) - krb5_appdefault_boolean(context, "kinit", - krb5_principal_get_realm(context, principal), - "krb4_get_tickets", TRUE, &get_v4_tgt); -#endif - if(do_afslog == -1) - krb5_appdefault_boolean(context, "kinit", - krb5_principal_get_realm(context, principal), - "afslog", TRUE, &do_afslog); - if(!addrs_flag && extra_addresses.num_strings > 0) + if(addrs_flag == 0 && extra_addresses.num_strings > 0) krb5_errx(context, 1, "specifying both extra addresses and " "no addresses makes no sense"); { @@ -675,30 +805,41 @@ main (int argc, char **argv) free_getarg_strings(&extra_addresses); } - if(renew_flag || validate_flag) { ret = renew_validate(context, renew_flag, validate_flag, - ccache, server, ticket_life); + ccache, server_str, ticket_life); exit(ret != 0); } -#ifdef KRB4 if(!convert_524) -#endif - get_new_tickets(context, principal, ccache, ticket_life); + get_new_tickets(context, principal, ccache, ticket_life, 1); -#ifdef KRB4 - if(get_v4_tgt) - do_524init(context, ccache, NULL, server); -#endif + if(get_v4_tgt || convert_524) + do_524init(context, ccache, NULL, server_str); if(do_afslog && k_hasafs()) krb5_afslog(context, ccache, NULL, NULL); if(argc > 1) { - ret = simple_execvp(argv[1], argv+1); + struct renew_ctx ctx; + time_t timeout; + + timeout = ticket_lifetime(context, ccache, principal, server_str) / 2; + + ctx.context = context; + ctx.ccache = ccache; + ctx.principal = principal; + ctx.ticket_life = ticket_life; + + ret = simple_execvp_timed(argv[1], argv+1, + renew_func, &ctx, timeout); +#define EX_NOEXEC 126 +#define EX_NOTFOUND 127 + if(ret == EX_NOEXEC) + krb5_warnx(context, "permission denied: %s", argv[1]); + else if(ret == EX_NOTFOUND) + krb5_warnx(context, "command not found: %s", argv[1]); + krb5_cc_destroy(context, ccache); -#ifdef KRB4 - dest_tkt(); -#endif + _krb5_krb_dest_tkt(context, krb4_cc_name); if(k_hasafs()) k_unlog(); } else { |