From 1440ab035ba04550ddbbfbff1ee9b5571e3d95db Mon Sep 17 00:00:00 2001 From: Marc Horowitz Date: Fri, 30 Oct 1998 02:56:35 +0000 Subject: pull up 3des implementation from the marc-3des branch git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@11001 dc483132-0cff-0310-8789-dd5450dbe970 --- src/clients/kinit/kinit.c | 536 +++++++++++++++++++--------------------------- 1 file changed, 219 insertions(+), 317 deletions(-) (limited to 'src/clients/kinit/kinit.c') diff --git a/src/clients/kinit/kinit.c b/src/clients/kinit/kinit.c index 6f7b840..f02db2e 100644 --- a/src/clients/kinit/kinit.c +++ b/src/clients/kinit/kinit.c @@ -24,43 +24,64 @@ * Initialize a credentials cache. */ -#include "k5-int.h" +#include +#include +#include + +#ifdef GETOPT_LONG +#include "getopt.h" +#else +#include +#endif #include "com_err.h" -#include "adm_proto.h" -#include #ifdef HAVE_PWD_H #include -#endif -#define KRB5_DEFAULT_OPTIONS 0 -#define KRB5_DEFAULT_LIFE 60*60*10 /* 10 hours */ - -extern int optind; -extern char *optarg; +void get_name_from_passwd_file(program_name, kcontext, me) + char * program_name; + krb5_context kcontext; + krb5_principal * me; +{ + struct passwd *pw; + krb5_error_code code; + if (pw = getpwuid((int) getuid())) { + if ((code = krb5_parse_name(kcontext, pw->pw_name, me))) { + com_err (program_name, code, "when parsing name %s", pw->pw_name); + exit(1); + } + } else { + fprintf(stderr, "Unable to identify user from password file\n"); + exit(1); + } +} +#else /* HAVE_PWD_H */ +void get_name_from_passwd_file(kcontext, me) + krb5_context kcontext; + krb5_principal * me; +{ + fprintf(stderr, "Unable to identify user\n"); + exit(1); +} +#endif /* HAVE_PWD_H */ -krb5_data tgtname = { - 0, - KRB5_TGS_NAME_SIZE, - KRB5_TGS_NAME +#ifdef GETOPT_LONG +/* if struct[2] == NULL, then long_getopt acts as if the short flag + struct[3] was specified. If struct[2] != NULL, then struct[3] is + stored in *(struct[2]), the array index which was specified is + stored in *index, and long_getopt() returns 0. */ + +struct option long_options[] = { + { "noforwardable", 0, NULL, 'f'+0200 }, + { "noproxiable", 0, NULL, 'p'+0200 }, + { "addresses", 0, NULL, 'A'+0200}, + { "forwardable", 0, NULL, 'f' }, + { "proxiable", 0, NULL, 'p' }, + { "noaddresses", 0, NULL, 'A'}, + { "version", 0, NULL, 0x01 }, + { NULL, 0, NULL, 0 } }; - -/* Internal prototypes */ -static krb5_error_code krb5_validate_tgt - KRB5_PROTOTYPE((krb5_context, krb5_ccache, - krb5_principal, krb5_data *)); -static krb5_error_code krb5_renew_tgt - KRB5_PROTOTYPE((krb5_context, krb5_ccache, - krb5_principal, krb5_data *)); -static krb5_error_code krb5_tgt_gen - KRB5_PROTOTYPE((krb5_context, krb5_ccache, - krb5_principal, krb5_data *, int opt)); - -/* - * Try no preauthentication first; then try the encrypted timestamp - */ -krb5_preauthtype * preauth = NULL; -krb5_preauthtype preauth_list[2] = { 0, -1 }; +#endif int main(argc, argv) @@ -68,114 +89,147 @@ main(argc, argv) char **argv; { krb5_context kcontext; + krb5_principal me = NULL; + krb5_deltat start_time = 0; + krb5_address **addresses = NULL; + krb5_get_init_creds_opt opts; + char *service_name = NULL; + krb5_keytab keytab = NULL; + char *cache_name; krb5_ccache ccache = NULL; - char *cache_name = NULL; /* -f option */ - char *keytab_name = NULL; /* -t option */ - char *service_name = NULL; /* -s option */ - krb5_deltat lifetime = KRB5_DEFAULT_LIFE; /* -l option */ - krb5_timestamp starttime = 0; - krb5_deltat rlife = 0; - int options = KRB5_DEFAULT_OPTIONS; - int option; - int errflg = 0; - krb5_error_code code; - krb5_principal me; - krb5_principal server; + enum { INIT_PW, INIT_KT, RENEW, VALIDATE} action; + int errflg = 0, idx, i; krb5_creds my_creds; - krb5_timestamp now; - krb5_address *null_addr = (krb5_address *)0; - krb5_address **addrs = (krb5_address **)0; - int use_keytab = 0; /* -k option */ - krb5_keytab keytab = NULL; - struct passwd *pw = 0; - int pwsize; - char password[255], *client_name, prompt[1024]; + krb5_error_code code; - code = krb5_init_context(&kcontext); - if (code) { - com_err(argv[0], code, "while initializing krb5"); - exit(1); - } + /* Ensure we can be driven from a pipe */ + if(!isatty(fileno(stdin))) + setvbuf(stdin, 0, _IONBF, 0); + if(!isatty(fileno(stdout))) + setvbuf(stdout, 0, _IONBF, 0); + if(!isatty(fileno(stderr))) + setvbuf(stderr, 0, _IONBF, 0); - if ((code = krb5_timeofday(kcontext, &now))) { - com_err(argv[0], code, "while getting time of day"); + if (code = krb5_init_context(&kcontext)) { + com_err(argv[0], code, "while initializing kerberos library"); exit(1); } + krb5_get_init_creds_opt_init(&opts); + + action = INIT_PW; + if (strrchr(argv[0], '/')) argv[0] = strrchr(argv[0], '/')+1; - while ((option = getopt(argc, argv, "r:Rfpl:s:c:kt:vS:")) != -1) { - switch (option) { - case 'r': - options |= KDC_OPT_RENEWABLE; - code = krb5_string_to_deltat(optarg, &rlife); - if (code != 0 || rlife == 0) { - fprintf(stderr, "Bad lifetime value %s\n", optarg); - errflg++; + while ( +#ifdef GETOPT_LONG + (i = getopt_long(argc, argv, "r:fpAl:s:c:kt:RS:v", + long_options, &idx)) != -1 +#else + (i = getopt(argc, argv, "r:fpAl:s:c:kt:RS:v")) != -1 +#endif + ) { + switch (i) { +#ifdef GETOPT_LONG + case 1: /* Print the version */ + printf("%s\n", krb5_version); + exit(0); +#endif + case 'l': + { + krb5_deltat lifetime; + code = krb5_string_to_deltat(optarg, &lifetime); + if (code != 0 || lifetime == 0) { + fprintf(stderr, "Bad lifetime value %s\n", optarg); + errflg++; + } + krb5_get_init_creds_opt_set_tkt_life(&opts, lifetime); } break; - case 'R': - /* renew the ticket */ - options |= KDC_OPT_RENEW; + case 'r': + { + krb5_deltat rlife; + + code = krb5_string_to_deltat(optarg, &rlife); + if (code != 0 || rlife == 0) { + fprintf(stderr, "Bad lifetime value %s\n", optarg); + errflg++; + } + krb5_get_init_creds_opt_set_renew_life(&opts, rlife); + } break; - case 'v': - /* validate the ticket */ - options |= KDC_OPT_VALIDATE; + case 'f': + krb5_get_init_creds_opt_set_forwardable(&opts, 1); break; - case 'S': - service_name = optarg; +#ifdef GETOPT_LONG + case 'f'+0200: + krb5_get_init_creds_opt_set_forwardable(&opts, 0); break; +#endif case 'p': - options |= KDC_OPT_PROXIABLE; + krb5_get_init_creds_opt_set_proxiable(&opts, 1); break; - case 'f': - options |= KDC_OPT_FORWARDABLE; +#ifdef GETOPT_LONG + case 'p'+0200: + krb5_get_init_creds_opt_set_proxiable(&opts, 0); break; -#ifndef NO_KEYTAB - case 'k': - use_keytab = 1; +#endif + case 'A': + krb5_get_init_creds_opt_set_address_list(&opts, NULL); break; - case 't': - if (keytab == NULL) { - keytab_name = optarg; +#ifdef GETOPT_LONG + case 'A'+0200: + krb5_os_localaddr(kcontext, &addresses); + krb5_get_init_creds_opt_set_address_list(&opts, addresses); + break; +#endif + case 's': + code = krb5_string_to_deltat(optarg, &start_time); + if (code != 0 || start_time == 0) { + krb5_timestamp abs_starttime; + krb5_timestamp now; + + code = krb5_string_to_timestamp(optarg, &abs_starttime); + if (code != 0 || abs_starttime == 0) { + fprintf(stderr, "Bad start time value %s\n", optarg); + errflg++; + } else { + if ((code = krb5_timeofday(kcontext, &now))) { + com_err(argv[0], code, + "while getting time of day"); + exit(1); + } - code = krb5_kt_resolve(kcontext, keytab_name, &keytab); + start_time = abs_starttime - now; + } + } + break; + case 'S': + service_name = optarg; + break; + case 'k': + action = INIT_KT; + break; + case 't': + if (keytab == NULL) { + code = krb5_kt_resolve(kcontext, optarg, &keytab); if (code != 0) { - com_err(argv[0], code, "resolving keytab %s", - keytab_name); - errflg++; + com_err(argv[0], code, "resolving keytab %s", optarg); + errflg++; } } else { fprintf(stderr, "Only one -t option allowed.\n"); errflg++; } break; -#endif - case 'l': - code = krb5_string_to_deltat(optarg, &lifetime); - if (code != 0 || lifetime == 0) { - fprintf(stderr, "Bad lifetime value %s\n", optarg); - errflg++; - } + case 'R': + action = RENEW; break; - case 's': - code = krb5_string_to_timestamp(optarg, &starttime); - if (code != 0 || starttime == 0) { - krb5_deltat ktmp; - code = krb5_string_to_deltat(optarg, &ktmp); - if (code == 0 && ktmp != 0) { - starttime = now + ktmp; - options |= KDC_OPT_POSTDATED; - } else { - fprintf(stderr, "Bad postdate start time value %s\n", optarg); - errflg++; - } - } else { - options |= KDC_OPT_POSTDATED; - } + case 'v': + action = VALIDATE; break; - case 'c': + case 'c': if (ccache == NULL) { cache_name = optarg; @@ -190,7 +244,6 @@ main(argc, argv) errflg++; } break; - case '?': default: errflg++; break; @@ -204,7 +257,11 @@ main(argc, argv) } if (errflg) { - fprintf(stderr, "Usage: %s [-r time] [-R] [-s time] [-v] [-puf] [-l lifetime] [-c cachename] [-k] [-t keytab] [-S target_service] [principal]\n", argv[0]); +#ifdef GETOPT_LONG + fprintf(stderr, "Usage: %s [--version] [-l lifetime] [-r renewable_life] [-f | --forwardable | --noforwardable] [-p | --proxiable | --noproxiable] [-A | --noaddresses | --addresses] [-s start_time] [-S target_service] [-k [-t keytab_file]] [-R] [-v] [-c cachename] [principal]\n", argv[0]); +#else + fprintf(stderr, "Usage: %s [-l lifetime] [-r renewable_life] [-f] [-p] [-A] [-s start_time] [-S target_service] [-k [-t keytab_file]] [-R] [-v] [-c cachename] [principal]\n", argv[0]); +#endif exit(2); } @@ -215,147 +272,51 @@ main(argc, argv) } } - if (optind != argc-1) { /* No principal name specified */ -#ifndef NO_KEYTAB - if (use_keytab) { - /* Use the default host/service name */ - code = krb5_sname_to_principal(kcontext, NULL, NULL, - KRB5_NT_SRV_HST, &me); - if (code) { - com_err(argv[0], code, - "when creating default server principal name"); - exit(1); - } - } else -#endif - { - /* Get default principal from cache if one exists */ - code = krb5_cc_get_principal(kcontext, ccache, &me); - if (code) { -#ifdef HAVE_PWD_H - /* Else search passwd file for client */ - pw = getpwuid((int) getuid()); - if (pw) { - if ((code = krb5_parse_name(kcontext,pw->pw_name, - &me))) { - com_err (argv[0], code, "when parsing name %s", - pw->pw_name); - exit(1); - } - } else { - fprintf(stderr, - "Unable to identify user from password file\n"); - exit(1); - } -#else /* HAVE_PWD_H */ - fprintf(stderr, "Unable to identify user\n"); - exit(1); -#endif /* HAVE_PWD_H */ - } - } - } /* Use specified name */ - else if ((code = krb5_parse_name (kcontext, argv[optind], &me))) { - com_err (argv[0], code, "when parsing name %s",argv[optind]); - exit(1); - } - - if ((code = krb5_unparse_name(kcontext, me, &client_name))) { - com_err (argv[0], code, "when unparsing name"); - exit(1); - } - - memset((char *)&my_creds, 0, sizeof(my_creds)); - - my_creds.client = me; - - if (service_name == NULL) { - if((code = krb5_build_principal_ext(kcontext, &server, - krb5_princ_realm(kcontext, me)->length, - krb5_princ_realm(kcontext, me)->data, - tgtname.length, tgtname.data, - krb5_princ_realm(kcontext, me)->length, - krb5_princ_realm(kcontext, me)->data, - 0))) { - com_err(argv[0], code, "while building server name"); - exit(1); - } - } else { - if ((code = krb5_parse_name(kcontext, service_name, &server))) { - com_err(argv[0], code, "while parsing service name %s", - service_name); - exit(1); - } - } - - my_creds.server = server; - - if (options & KDC_OPT_POSTDATED) { - my_creds.times.starttime = starttime; - my_creds.times.endtime = starttime + lifetime; + if (optind == argc-1) { + /* Use specified name */ + if ((code = krb5_parse_name (kcontext, argv[optind], &me))) { + com_err (argv[0], code, "when parsing name %s",argv[optind]); + exit(1); + } } else { - my_creds.times.starttime = 0; /* start timer when request - gets to KDC */ - my_creds.times.endtime = now + lifetime; - } - if (options & KDC_OPT_RENEWABLE) { - my_creds.times.renew_till = now + rlife; - } else - my_creds.times.renew_till = 0; - - if (options & KDC_OPT_VALIDATE) { - /* don't use get_in_tkt, just use mk_req... */ - krb5_data outbuf; - - code = krb5_validate_tgt(kcontext, ccache, server, &outbuf); - if (code) { - com_err (argv[0], code, "validating tgt"); - exit(1); + /* No principal name specified */ + if (action == INIT_KT) { + /* Use the default host/service name */ + if (code = krb5_sname_to_principal(kcontext, NULL, NULL, + KRB5_NT_SRV_HST, &me)) { + com_err(argv[0], code, + "when creating default server principal name"); + exit(1); + } + } else { + /* Get default principal from cache if one exists */ + if (code = krb5_cc_get_principal(kcontext, ccache, &me)) + get_name_from_passwd_file(argv[0], kcontext, &me); } - /* should be done... */ - exit(0); } - - if (options & KDC_OPT_RENEW) { - /* don't use get_in_tkt, just use mk_req... */ - krb5_data outbuf; - - code = krb5_renew_tgt(kcontext, ccache, server, &outbuf); - if (code) { - com_err (argv[0], code, "renewing tgt"); - exit(1); - } - /* should be done... */ - exit(0); + + switch (action) { + case INIT_PW: + code = krb5_get_init_creds_password(kcontext, &my_creds, me, NULL, + krb5_prompter_posix, NULL, + start_time, service_name, + &opts); + break; + case INIT_KT: + code = krb5_get_init_creds_keytab(kcontext, &my_creds, me, keytab, + start_time, service_name, + &opts); + break; + case VALIDATE: + code = krb5_get_validated_creds(kcontext, &my_creds, me, ccache, + service_name); + break; + case RENEW: + code = krb5_get_renewed_creds(kcontext, &my_creds, me, ccache, + service_name); + break; } -#ifndef NO_KEYTAB - if (!use_keytab) -#endif - { - (void) sprintf(prompt, "Password for %.*s: ", - sizeof(prompt)-32, (char *) client_name); - - pwsize = sizeof(password); - code = krb5_read_password(kcontext, prompt, 0, password, &pwsize); - if (code || pwsize == 0) { - fprintf(stderr, "Error while reading password for '%s'\n", - client_name); - memset(password, 0, sizeof(password)); - exit(1); - } - - code = krb5_get_in_tkt_with_password(kcontext, options, addrs, - NULL, preauth, password, 0, - &my_creds, 0); - memset(password, 0, sizeof(password)); -#ifndef NO_KEYTAB - } else { - code = krb5_get_in_tkt_with_keytab(kcontext, options, addrs, - NULL, preauth, keytab, 0, - &my_creds, 0); -#endif - } - if (code) { if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) fprintf (stderr, "%s: Password incorrect\n", argv[0]); @@ -364,86 +325,27 @@ main(argc, argv) exit(1); } - code = krb5_cc_initialize (kcontext, ccache, me); - if (code != 0) { + if (code = krb5_cc_initialize(kcontext, ccache, me)) { com_err (argv[0], code, "when initializing cache %s", cache_name?cache_name:""); exit(1); } - code = krb5_cc_store_cred(kcontext, ccache, &my_creds); - if (code) { + if (code = krb5_cc_store_cred(kcontext, ccache, &my_creds)) { com_err (argv[0], code, "while storing credentials"); exit(1); } - /* my_creds is pointing at server */ - krb5_free_principal(kcontext, server); + if (me) + krb5_free_principal(kcontext, me); + if (keytab) + krb5_kt_close(kcontext, keytab); + if (ccache) + krb5_cc_close(kcontext, ccache); + if (addresses) + krb5_free_addresses(kcontext, addresses); krb5_free_context(kcontext); - + exit(0); } - -#define VALIDATE 0 -#define RENEW 1 - -/* stripped down version of krb5_mk_req */ -static krb5_error_code krb5_validate_tgt(context, ccache, server, outbuf) - krb5_context context; - krb5_ccache ccache; - krb5_principal server; /* tgtname */ - krb5_data *outbuf; -{ - return krb5_tgt_gen(context, ccache, server, outbuf, VALIDATE); -} - -/* stripped down version of krb5_mk_req */ -static krb5_error_code krb5_renew_tgt(context, ccache, server, outbuf) - krb5_context context; - krb5_ccache ccache; - krb5_principal server; /* tgtname */ - krb5_data *outbuf; -{ - return krb5_tgt_gen(context, ccache, server, outbuf, RENEW); -} - - -/* stripped down version of krb5_mk_req */ -static krb5_error_code krb5_tgt_gen(context, ccache, server, outbuf, opt) - krb5_context context; - krb5_ccache ccache; - krb5_principal server; /* tgtname */ - krb5_data *outbuf; - int opt; -{ - krb5_error_code retval; - krb5_creds * credsp; - krb5_creds creds; - - /* obtain ticket & session key */ - memset((char *)&creds, 0, sizeof(creds)); - if ((retval = krb5_copy_principal(context, server, &creds.server))) - goto cleanup; - - if ((retval = krb5_cc_get_principal(context, ccache, &creds.client))) - goto cleanup_creds; - - if(opt == VALIDATE) { - if ((retval = krb5_get_credentials_validate(context, 0, - ccache, &creds, &credsp))) - goto cleanup_creds; - } else { - if ((retval = krb5_get_credentials_renew(context, 0, - ccache, &creds, &credsp))) - goto cleanup_creds; - } - - /* we don't actually need to do the mk_req, just get the creds. */ -cleanup_creds: - krb5_free_cred_contents(context, &creds); - -cleanup: - - return retval; -} -- cgit v1.1