diff options
Diffstat (limited to 'crypto/heimdal/kuser/kinit.c')
-rw-r--r-- | crypto/heimdal/kuser/kinit.c | 265 |
1 files changed, 226 insertions, 39 deletions
diff --git a/crypto/heimdal/kuser/kinit.c b/crypto/heimdal/kuser/kinit.c index 35b493a..be2857c 100644 --- a/crypto/heimdal/kuser/kinit.c +++ b/crypto/heimdal/kuser/kinit.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2000 Kungliga Tekniska Högskolan + * Copyright (c) 1997-2001 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -32,16 +32,142 @@ */ #include "kuser_locl.h" -RCSID("$Id: kinit.c,v 1.60 2000/02/01 14:06:33 joda Exp $"); +RCSID("$Id: kinit.c,v 1.69 2001/01/05 16:32:55 joda Exp $"); -int forwardable = 0; -int proxiable = 0; -int renewable = 0; +#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, + char *passwd, size_t passwd_size) +{ + 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_tkt2(princ.name, princ.instance, princ.realm, + KRB_TICKET_GRANTING_TICKET, princ.realm, + lifetime, passwd, &key); + } + memset (passwd, 0, passwd_size); + memset (key, 0, sizeof(key)); + if (ret) { + warnx ("%s", krb_get_err_text(ret)); + return 1; + } + if (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 */ + +int forwardable_flag = -1; +int proxiable_flag = -1; +int renewable_flag = -1; int renew_flag = 0; int validate_flag = 0; int version_flag = 0; int help_flag = 0; int addrs_flag = 1; +int anonymous_flag = 0; char *lifetime = NULL; char *renew_life = NULL; char *server = NULL; @@ -56,7 +182,7 @@ extern int get_v4_tgt; #endif int fcache_version; -struct getargs args[] = { +static struct getargs args[] = { #ifdef KRB4 { "524init", '4', arg_flag, &get_v4_tgt, "obtain version 4 TGT" }, @@ -67,32 +193,32 @@ struct getargs args[] = { { "cache", 'c', arg_string, &cred_cache, "credentials cache", "cachename" }, - { "forwardable", 'f', arg_flag, &forwardable, + { "forwardable", 'f', arg_flag, &forwardable_flag, "get forwardable tickets"}, { "keytab", 't', arg_string, &keytab_str, "keytab to use", "keytabname" }, { "lifetime", 'l', arg_string, &lifetime, - "lifetime of tickets", "seconds"}, + "lifetime of tickets", "time"}, - { "proxiable", 'p', arg_flag, &proxiable, + { "proxiable", 'p', arg_flag, &proxiable_flag, "get proxiable tickets" }, { "renew", 'R', arg_flag, &renew_flag, "renew TGT" }, - { "renewable", 0, arg_flag, &renewable, + { "renewable", 0, arg_flag, &renewable_flag, "get renewable tickets" }, { "renewable-life", 'r', arg_string, &renew_life, - "renewable lifetime of tickets", "seconds" }, + "renewable lifetime of tickets", "time" }, { "server", 'S', arg_string, &server, "server to get ticket for", "principal" }, { "start-time", 's', arg_string, &start_str, - "when ticket gets valid", "seconds" }, + "when ticket gets valid", "time" }, { "use-keytab", 'k', arg_flag, &use_keytab, "get key from keytab" }, @@ -101,7 +227,7 @@ struct getargs args[] = { "validate TGT" }, { "enctypes", 'e', arg_strings, &etype_str, - "encryption type to use", "enctype" }, + "encryption types to use", "enctypes" }, { "fcache-version", 0, arg_integer, &fcache_version, "file cache version to create" }, @@ -109,6 +235,9 @@ struct getargs args[] = { { "addresses", 0, arg_negative_flag, &addrs_flag, "request a ticket with no addresses" }, + { "anonymous", 0, arg_flag, &anonymous_flag, + "request an anonymous ticket" }, + { "version", 0, arg_flag, &version_flag }, { "help", 0, arg_flag, &help_flag } }; @@ -159,10 +288,11 @@ renew_validate(krb5_context context, } } flags.i = 0; - flags.b.renewable = flags.b.renew = renew; - flags.b.validate = validate; - flags.b.forwardable = forwardable; - flags.b.proxiable = proxiable; + flags.b.renewable = flags.b.renew = renew; + flags.b.validate = validate; + flags.b.forwardable = forwardable_flag; + flags.b.proxiable = proxiable_flag; + flags.b.request_anonymous = anonymous_flag; if(life) in.times.endtime = time(NULL) + life; @@ -207,18 +337,22 @@ main (int argc, char **argv) krb5_deltat start_time = 0; krb5_deltat ticket_life = 0; krb5_addresses no_addrs; + char passwd[256]; set_progname (argv[0]); memset(&cred, 0, sizeof(cred)); ret = krb5_init_context (&context); if (ret) - errx(1, "krb5_init_context failed: %u", ret); + errx(1, "krb5_init_context failed: %d", ret); - forwardable = krb5_config_get_bool (context, NULL, - "libdefaults", - "forwardable", - NULL); + /* XXX no way to figure out if set without explict test */ + if(krb5_config_get_string(context, NULL, "libdefaults", + "forwardable", NULL)) + forwardable_flag = krb5_config_get_bool (context, NULL, + "libdefaults", + "forwardable", + NULL); #ifdef KRB4 get_v4_tgt = krb5_config_get_bool_default (context, NULL, @@ -239,6 +373,22 @@ main (int argc, char **argv) exit(0); } + argc -= optind; + argv += optind; + + if (argc > 1) + usage (1); + + if (argv[0]) { + ret = krb5_parse_name (context, argv[0], &principal); + if (ret) + krb5_err (context, 1, ret, "krb5_parse_name"); + } else { + ret = kinit_get_default_principal (context, &principal); + if (ret) + krb5_err (context, 1, ret, "krb5_get_default_principal"); + } + if(fcache_version) krb5_set_fcache_version(context, fcache_version); @@ -264,8 +414,15 @@ main (int argc, char **argv) krb5_get_init_creds_opt_init (&opt); - krb5_get_init_creds_opt_set_forwardable (&opt, forwardable); - krb5_get_init_creds_opt_set_proxiable (&opt, proxiable); + krb5_get_init_creds_opt_set_default_flags(context, "kinit", + /* XXX */principal->realm, &opt); + + if(forwardable_flag != -1) + krb5_get_init_creds_opt_set_forwardable (&opt, forwardable_flag); + if(proxiable_flag != -1) + 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; @@ -280,7 +437,7 @@ main (int argc, char **argv) errx (1, "unparsable time: %s", renew_life); krb5_get_init_creds_opt_set_renew_life (&opt, tmp); - } else if (renewable) + } else if (renewable_flag) krb5_get_init_creds_opt_set_renew_life (&opt, 1 << 30); if(ticket_life != 0) @@ -311,18 +468,16 @@ main (int argc, char **argv) etype_str.num_strings); } - argc -= optind; - argv += optind; - - if (argc > 1) - usage (1); - - if (argv[0]) { - ret = krb5_parse_name (context, argv[0], &principal); - if (ret) - krb5_err (context, 1, ret, "krb5_parse_name"); - } else - principal = NULL; +#ifdef KRB4 + get_v4_tgt = krb5_config_get_bool_default (context, + NULL, + get_v4_tgt, + "realms", + krb5_princ_realm(context, + principal), + "krb4_get_tickets", + NULL); +#endif if(use_keytab || keytab_str) { krb5_keytab kt; @@ -340,23 +495,55 @@ main (int argc, char **argv) server, &opt); krb5_kt_close(context, kt); - } else + } 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); + } + + free (prompt); + ret = krb5_get_init_creds_password (context, &cred, principal, - NULL, + passwd, krb5_prompter_posix, NULL, start_time, server, &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, sizeof(passwd)); + memset(passwd, 0, sizeof(passwd)); + if (exit_val == 0 || ret == KRB5KRB_AP_ERR_V4_REPLY) { + krb5_free_context (context); + return exit_val; + } + } +#endif + memset(passwd, 0, sizeof(passwd)); + switch(ret){ case 0: break; case KRB5_LIBOS_PWDINTR: /* don't print anything if it was just C-c:ed */ + memset(passwd, 0, sizeof(passwd)); exit(1); case KRB5KRB_AP_ERR_BAD_INTEGRITY: case KRB5KRB_AP_ERR_MODIFIED: + memset(passwd, 0, sizeof(passwd)); krb5_errx(context, 1, "Password incorrect"); break; default: |