10Sstevel@tonic-gate /*
2*7934SMark.Phalan@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
30Sstevel@tonic-gate * Use is subject to license terms.
40Sstevel@tonic-gate */
50Sstevel@tonic-gate
60Sstevel@tonic-gate
70Sstevel@tonic-gate /*
80Sstevel@tonic-gate * clients/kinit/kinit.c
90Sstevel@tonic-gate *
100Sstevel@tonic-gate * Copyright 1990 by the Massachusetts Institute of Technology.
110Sstevel@tonic-gate * All Rights Reserved.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * Export of this software from the United States of America may
140Sstevel@tonic-gate * require a specific license from the United States Government.
150Sstevel@tonic-gate * It is the responsibility of any person or organization contemplating
160Sstevel@tonic-gate * export to obtain such a license before exporting.
170Sstevel@tonic-gate *
180Sstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
190Sstevel@tonic-gate * distribute this software and its documentation for any purpose and
200Sstevel@tonic-gate * without fee is hereby granted, provided that the above copyright
210Sstevel@tonic-gate * notice appear in all copies and that both that copyright notice and
220Sstevel@tonic-gate * this permission notice appear in supporting documentation, and that
230Sstevel@tonic-gate * the name of M.I.T. not be used in advertising or publicity pertaining
240Sstevel@tonic-gate * to distribution of the software without specific, written prior
250Sstevel@tonic-gate * permission. Furthermore if you modify this software you must label
260Sstevel@tonic-gate * your software as modified software and not distribute it in such a
270Sstevel@tonic-gate * fashion that it might be confused with the original M.I.T. software.
280Sstevel@tonic-gate * M.I.T. makes no representations about the suitability of
290Sstevel@tonic-gate * this software for any purpose. It is provided "as is" without express
300Sstevel@tonic-gate * or implied warranty.
310Sstevel@tonic-gate *
320Sstevel@tonic-gate *
330Sstevel@tonic-gate * Initialize a credentials cache.
340Sstevel@tonic-gate */
350Sstevel@tonic-gate #include <k5-int.h>
360Sstevel@tonic-gate #include <profile/prof_int.h>
370Sstevel@tonic-gate #include <com_err.h>
380Sstevel@tonic-gate #include <libintl.h>
390Sstevel@tonic-gate
400Sstevel@tonic-gate #include <krb5.h>
410Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
420Sstevel@tonic-gate #include <kerberosIV/krb.h>
430Sstevel@tonic-gate #define HAVE_KRB524
440Sstevel@tonic-gate #else
450Sstevel@tonic-gate #undef HAVE_KRB524
46*7934SMark.Phalan@Sun.COM #endif
470Sstevel@tonic-gate #include <string.h>
480Sstevel@tonic-gate #include <stdio.h>
490Sstevel@tonic-gate #include <time.h>
50*7934SMark.Phalan@Sun.COM #include <errno.h>
51*7934SMark.Phalan@Sun.COM #include <com_err.h>
520Sstevel@tonic-gate #include <netdb.h>
530Sstevel@tonic-gate #include <locale.h>
540Sstevel@tonic-gate
550Sstevel@tonic-gate #ifdef GETOPT_LONG
560Sstevel@tonic-gate #include <getopt.h>
57*7934SMark.Phalan@Sun.COM #else
580Sstevel@tonic-gate #ifdef HAVE_UNISTD_H
590Sstevel@tonic-gate #include <unistd.h>
60*7934SMark.Phalan@Sun.COM #ifdef sun
61*7934SMark.Phalan@Sun.COM /* SunOS4 unistd didn't declare these; okay to make unconditional? */
62*7934SMark.Phalan@Sun.COM extern int optind;
63*7934SMark.Phalan@Sun.COM extern char *optarg;
64*7934SMark.Phalan@Sun.COM #endif /* sun */
65*7934SMark.Phalan@Sun.COM #else
660Sstevel@tonic-gate extern int optind;
670Sstevel@tonic-gate extern char *optarg;
680Sstevel@tonic-gate extern int getopt();
690Sstevel@tonic-gate #endif /* HAVE_UNISTD_H */
700Sstevel@tonic-gate #endif /* GETOPT_LONG */
710Sstevel@tonic-gate
720Sstevel@tonic-gate #ifndef _WIN32
730Sstevel@tonic-gate #define GET_PROGNAME(x) (strrchr((x), '/') ? strrchr((x), '/')+1 : (x))
74*7934SMark.Phalan@Sun.COM #else
750Sstevel@tonic-gate #define GET_PROGNAME(x) max(max(strrchr((x), '/'), strrchr((x), '\\')) + 1,(x))
76*7934SMark.Phalan@Sun.COM #endif
770Sstevel@tonic-gate
780Sstevel@tonic-gate #ifdef HAVE_PWD_H
790Sstevel@tonic-gate #include <pwd.h>
802881Smp153739 static
get_name_from_os()810Sstevel@tonic-gate char * get_name_from_os()
820Sstevel@tonic-gate {
830Sstevel@tonic-gate struct passwd *pw;
842881Smp153739 if ((pw = getpwuid((int) getuid())))
850Sstevel@tonic-gate return pw->pw_name;
860Sstevel@tonic-gate return 0;
870Sstevel@tonic-gate }
880Sstevel@tonic-gate #else /* HAVE_PWD_H */
890Sstevel@tonic-gate #ifdef _WIN32
902881Smp153739 static
get_name_from_os()910Sstevel@tonic-gate char * get_name_from_os()
920Sstevel@tonic-gate {
930Sstevel@tonic-gate static char name[1024];
940Sstevel@tonic-gate DWORD name_size = sizeof(name);
950Sstevel@tonic-gate if (GetUserName(name, &name_size)) {
960Sstevel@tonic-gate name[sizeof(name)-1] = 0; /* Just to be extra safe */
970Sstevel@tonic-gate return name;
980Sstevel@tonic-gate } else {
990Sstevel@tonic-gate return 0;
1000Sstevel@tonic-gate }
1010Sstevel@tonic-gate }
1020Sstevel@tonic-gate #else /* _WIN32 */
1032881Smp153739 static
get_name_from_os()1040Sstevel@tonic-gate char * get_name_from_os()
1050Sstevel@tonic-gate {
1060Sstevel@tonic-gate return 0;
1070Sstevel@tonic-gate }
1080Sstevel@tonic-gate #endif /* _WIN32 */
1090Sstevel@tonic-gate #endif /* HAVE_PWD_H */
1100Sstevel@tonic-gate
1110Sstevel@tonic-gate static char* progname_v5 = 0;
1120Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
1130Sstevel@tonic-gate static char* progname_v4 = 0;
1140Sstevel@tonic-gate static char* progname_v524 = 0;
115*7934SMark.Phalan@Sun.COM #endif
1160Sstevel@tonic-gate #include <locale.h>
1170Sstevel@tonic-gate
1180Sstevel@tonic-gate static int got_k5 = 0;
1190Sstevel@tonic-gate static int got_k4 = 0;
1200Sstevel@tonic-gate
1210Sstevel@tonic-gate static int default_k5 = 1;
1220Sstevel@tonic-gate #if defined(KRB5_KRB4_COMPAT) && defined(KINIT_DEFAULT_BOTH)
1230Sstevel@tonic-gate static int default_k4 = 1;
124*7934SMark.Phalan@Sun.COM #else
1250Sstevel@tonic-gate static int default_k4 = 0;
126*7934SMark.Phalan@Sun.COM #endif
1270Sstevel@tonic-gate
1280Sstevel@tonic-gate static int authed_k5 = 0;
1290Sstevel@tonic-gate static int authed_k4 = 0;
1300Sstevel@tonic-gate
1312881Smp153739 #define KRB4_BACKUP_DEFAULT_LIFE_SECS 24*60*60 /* 1 day */
1320Sstevel@tonic-gate #define ROOT_UNAME "root"
1330Sstevel@tonic-gate
1340Sstevel@tonic-gate typedef enum { INIT_PW, INIT_KT, RENEW, VALIDATE } action_type;
1350Sstevel@tonic-gate
1360Sstevel@tonic-gate struct k_opts
1370Sstevel@tonic-gate {
1380Sstevel@tonic-gate /* in seconds */
1390Sstevel@tonic-gate krb5_deltat starttime;
1400Sstevel@tonic-gate krb5_deltat lifetime;
1410Sstevel@tonic-gate krb5_deltat rlife;
1420Sstevel@tonic-gate
1430Sstevel@tonic-gate int forwardable;
1440Sstevel@tonic-gate int proxiable;
1450Sstevel@tonic-gate int addresses;
1460Sstevel@tonic-gate
1470Sstevel@tonic-gate int not_forwardable;
1480Sstevel@tonic-gate int not_proxiable;
1490Sstevel@tonic-gate int no_addresses;
1500Sstevel@tonic-gate
1510Sstevel@tonic-gate int verbose;
1520Sstevel@tonic-gate
1530Sstevel@tonic-gate char* principal_name;
1540Sstevel@tonic-gate char* service_name;
1550Sstevel@tonic-gate char* keytab_name;
1560Sstevel@tonic-gate char* k5_cache_name;
1570Sstevel@tonic-gate char* k4_cache_name;
1580Sstevel@tonic-gate
1590Sstevel@tonic-gate action_type action;
160*7934SMark.Phalan@Sun.COM
161*7934SMark.Phalan@Sun.COM int num_pa_opts;
162*7934SMark.Phalan@Sun.COM krb5_gic_opt_pa_data *pa_opts;
1630Sstevel@tonic-gate };
1640Sstevel@tonic-gate
1650Sstevel@tonic-gate int forwardable_flag = 0;
1660Sstevel@tonic-gate int renewable_flag = 0;
1670Sstevel@tonic-gate int proxiable_flag = 0;
1680Sstevel@tonic-gate int no_address_flag = 0;
1690Sstevel@tonic-gate profile_options_boolean config_option[] = {
1700Sstevel@tonic-gate { "forwardable", &forwardable_flag, 0 },
1710Sstevel@tonic-gate { "renewable", &renewable_flag, 0 },
1720Sstevel@tonic-gate { "proxiable", &proxiable_flag, 0 },
1730Sstevel@tonic-gate { "no_addresses", &no_address_flag, 0 },
1740Sstevel@tonic-gate { NULL, NULL, 0 }
1750Sstevel@tonic-gate };
1760Sstevel@tonic-gate
1770Sstevel@tonic-gate char *renew_timeval=NULL;
1780Sstevel@tonic-gate char *life_timeval=NULL;
1790Sstevel@tonic-gate int lifetime_specified;
1800Sstevel@tonic-gate int renewtime_specified;
1810Sstevel@tonic-gate profile_option_strings config_times[] = {
1820Sstevel@tonic-gate { "max_life", &life_timeval, 0 },
1830Sstevel@tonic-gate { "max_renewable_life", &renew_timeval, 0 },
1840Sstevel@tonic-gate { NULL, NULL, 0 }
1850Sstevel@tonic-gate };
1860Sstevel@tonic-gate
1870Sstevel@tonic-gate struct k5_data
1880Sstevel@tonic-gate {
1890Sstevel@tonic-gate krb5_context ctx;
1900Sstevel@tonic-gate krb5_ccache cc;
1910Sstevel@tonic-gate krb5_principal me;
1920Sstevel@tonic-gate char* name;
1930Sstevel@tonic-gate };
1940Sstevel@tonic-gate
1950Sstevel@tonic-gate struct k4_data
1960Sstevel@tonic-gate {
1970Sstevel@tonic-gate krb5_deltat lifetime;
1980Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
1990Sstevel@tonic-gate char aname[ANAME_SZ + 1];
2000Sstevel@tonic-gate char inst[INST_SZ + 1];
2010Sstevel@tonic-gate char realm[REALM_SZ + 1];
2020Sstevel@tonic-gate char name[ANAME_SZ + 1 + INST_SZ + 1 + REALM_SZ + 1];
203*7934SMark.Phalan@Sun.COM #endif
2040Sstevel@tonic-gate };
2050Sstevel@tonic-gate
2060Sstevel@tonic-gate char *realmdef[] = { "realms", NULL, "kinit", NULL };
2070Sstevel@tonic-gate char *appdef[] = { "appdefaults", "kinit", NULL };
2080Sstevel@tonic-gate
2090Sstevel@tonic-gate #define krb_realm (*(realmdef + 1))
2100Sstevel@tonic-gate
2110Sstevel@tonic-gate #define lifetime_specified config_times[0].found
2120Sstevel@tonic-gate #define renewtime_specified config_times[1].found
2130Sstevel@tonic-gate
2140Sstevel@tonic-gate /*
2150Sstevel@tonic-gate * Try no preauthentication first; then try the encrypted timestamp
2160Sstevel@tonic-gate */
2170Sstevel@tonic-gate krb5_preauthtype * preauth = NULL;
2180Sstevel@tonic-gate krb5_preauthtype preauth_list[2] = { 0, -1 };
2190Sstevel@tonic-gate
220*7934SMark.Phalan@Sun.COM static void _kwarnd_add_warning(char *, char *, time_t);
221*7934SMark.Phalan@Sun.COM static void _kwarnd_del_warning(char *, char *);
2220Sstevel@tonic-gate
2230Sstevel@tonic-gate #ifdef GETOPT_LONG
2240Sstevel@tonic-gate /* if struct[2] == NULL, then long_getopt acts as if the short flag
2250Sstevel@tonic-gate struct[3] was specified. If struct[2] != NULL, then struct[3] is
2260Sstevel@tonic-gate stored in *(struct[2]), the array index which was specified is
2270Sstevel@tonic-gate stored in *index, and long_getopt() returns 0. */
2280Sstevel@tonic-gate
2290Sstevel@tonic-gate struct option long_options[] = {
2300Sstevel@tonic-gate { "noforwardable", 0, NULL, 'F' },
2310Sstevel@tonic-gate { "noproxiable", 0, NULL, 'P' },
2320Sstevel@tonic-gate { "addresses", 0, NULL, 'a'},
2330Sstevel@tonic-gate { "forwardable", 0, NULL, 'f' },
2340Sstevel@tonic-gate { "proxiable", 0, NULL, 'p' },
2350Sstevel@tonic-gate { "noaddresses", 0, NULL, 'A' },
2360Sstevel@tonic-gate { NULL, 0, NULL, 0 }
2370Sstevel@tonic-gate };
2380Sstevel@tonic-gate
2390Sstevel@tonic-gate #define GETOPT(argc, argv, str) getopt_long(argc, argv, str, long_options, 0)
240*7934SMark.Phalan@Sun.COM #else
2410Sstevel@tonic-gate #define GETOPT(argc, argv, str) getopt(argc, argv, str)
242*7934SMark.Phalan@Sun.COM #endif
2430Sstevel@tonic-gate
2442881Smp153739 static void
usage(progname)2452881Smp153739 usage(progname)
246*7934SMark.Phalan@Sun.COM char *progname;
2470Sstevel@tonic-gate {
2480Sstevel@tonic-gate #define USAGE_BREAK "\n\t"
2492881Smp153739
2500Sstevel@tonic-gate #ifdef GETOPT_LONG
2510Sstevel@tonic-gate #define USAGE_LONG_FORWARDABLE " | --forwardable | --noforwardable"
2520Sstevel@tonic-gate #define USAGE_LONG_PROXIABLE " | --proxiable | --noproxiable"
2530Sstevel@tonic-gate #define USAGE_LONG_ADDRESSES " | --addresses | --noaddresses"
2540Sstevel@tonic-gate #define USAGE_BREAK_LONG USAGE_BREAK
255*7934SMark.Phalan@Sun.COM #else
2560Sstevel@tonic-gate #define USAGE_LONG_FORWARDABLE ""
2570Sstevel@tonic-gate #define USAGE_LONG_PROXIABLE ""
2580Sstevel@tonic-gate #define USAGE_LONG_ADDRESSES ""
2590Sstevel@tonic-gate #define USAGE_BREAK_LONG ""
260*7934SMark.Phalan@Sun.COM #endif
2610Sstevel@tonic-gate
2620Sstevel@tonic-gate fprintf(stderr, "%s : %s [-V] "
2630Sstevel@tonic-gate "[-l lifetime] [-s start_time] "
2640Sstevel@tonic-gate USAGE_BREAK
2650Sstevel@tonic-gate "[-r renewable_life] "
2660Sstevel@tonic-gate "[-f | -F" USAGE_LONG_FORWARDABLE "] "
2670Sstevel@tonic-gate USAGE_BREAK_LONG
2680Sstevel@tonic-gate "[-p | -P" USAGE_LONG_PROXIABLE "] "
2690Sstevel@tonic-gate USAGE_BREAK_LONG
2702881Smp153739 "[-a | -A" USAGE_LONG_ADDRESSES "] "
2710Sstevel@tonic-gate USAGE_BREAK
2720Sstevel@tonic-gate "[-v] [-R] "
2730Sstevel@tonic-gate "[-k [-t keytab_file]] "
274*7934SMark.Phalan@Sun.COM "[-c cachename] "
2750Sstevel@tonic-gate USAGE_BREAK
276*7934SMark.Phalan@Sun.COM "[-S service_name]"
277*7934SMark.Phalan@Sun.COM "[-X <attribute>[=<value>]] [principal]"
2780Sstevel@tonic-gate "\n\n",
2790Sstevel@tonic-gate gettext("Usage"), progname);
2800Sstevel@tonic-gate
2810Sstevel@tonic-gate #define KRB_AVAIL_STRING(x) ((x)?gettext("available"):gettext("not available"))
2820Sstevel@tonic-gate
2830Sstevel@tonic-gate #define OPTTYPE_KRB5 "5"
2840Sstevel@tonic-gate #define OPTTYPE_KRB4 "4"
2850Sstevel@tonic-gate #define OPTTYPE_EITHER "Either 4 or 5"
2860Sstevel@tonic-gate #ifdef HAVE_KRB524
2870Sstevel@tonic-gate #define OPTTYPE_BOTH "5, or both 5 and 4"
2880Sstevel@tonic-gate #else
2890Sstevel@tonic-gate #define OPTTYPE_BOTH "5"
2900Sstevel@tonic-gate #endif
2910Sstevel@tonic-gate
2920Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
2930Sstevel@tonic-gate #define USAGE_OPT_FMT "%s%-50s%s\n"
2942881Smp153739 #define ULINE(indent, col1, col2) \
2952881Smp153739 fprintf(stderr, USAGE_OPT_FMT, indent, col1, col2)
2960Sstevel@tonic-gate #else
2970Sstevel@tonic-gate #define USAGE_OPT_FMT "%s%s\n"
2982881Smp153739 #define ULINE(indent, col1, col2) \
2992881Smp153739 fprintf(stderr, USAGE_OPT_FMT, indent, col1)
3000Sstevel@tonic-gate #endif
3010Sstevel@tonic-gate
3020Sstevel@tonic-gate ULINE(" ", "options:", "valid with Kerberos:");
3030Sstevel@tonic-gate fprintf(stderr, "\t-5 Kerberos 5 (%s)\n", KRB_AVAIL_STRING(got_k5));
3040Sstevel@tonic-gate fprintf(stderr, "\t-4 Kerberos 4 (%s)\n", KRB_AVAIL_STRING(got_k4));
3050Sstevel@tonic-gate fprintf(stderr, "\t (Default behavior is to try %s%s%s%s)\n",
3060Sstevel@tonic-gate default_k5?"Kerberos 5":"",
3070Sstevel@tonic-gate (default_k5 && default_k4)?gettext(" and "):"",
3080Sstevel@tonic-gate default_k4?"Kerberos 4":"",
3090Sstevel@tonic-gate (!default_k5 && !default_k4)?gettext("neither"):"");
3100Sstevel@tonic-gate ULINE("\t", gettext("-V verbose"), OPTTYPE_EITHER);
3110Sstevel@tonic-gate ULINE("\t", gettext("-l lifetime"), OPTTYPE_EITHER);
3120Sstevel@tonic-gate ULINE("\t", gettext("-s start time"), OPTTYPE_KRB5);
3130Sstevel@tonic-gate ULINE("\t", gettext("-r renewable lifetime"), OPTTYPE_KRB5);
3140Sstevel@tonic-gate ULINE("\t", gettext("-f forwardable"), OPTTYPE_KRB5);
3150Sstevel@tonic-gate ULINE("\t", gettext("-F not forwardable"), OPTTYPE_KRB5);
3160Sstevel@tonic-gate ULINE("\t", gettext("-p proxiable"), OPTTYPE_KRB5);
3170Sstevel@tonic-gate ULINE("\t", gettext("-P not proxiable"), OPTTYPE_KRB5);
3180Sstevel@tonic-gate ULINE("\t", gettext("-A do not include addresses"), OPTTYPE_KRB5);
3192881Smp153739 ULINE("\t", gettext("-a include addresses"), OPTTYPE_KRB5);
3200Sstevel@tonic-gate ULINE("\t", gettext("-v validate"), OPTTYPE_KRB5);
3210Sstevel@tonic-gate ULINE("\t", gettext("-R renew"), OPTTYPE_BOTH);
3220Sstevel@tonic-gate ULINE("\t", gettext("-k use keytab"), OPTTYPE_BOTH);
3230Sstevel@tonic-gate ULINE("\t", gettext("-t filename of keytab to use"), OPTTYPE_BOTH);
3240Sstevel@tonic-gate ULINE("\t", gettext("-c Kerberos 5 cache name"), OPTTYPE_KRB5);
3250Sstevel@tonic-gate /* This options is not yet available: */
3260Sstevel@tonic-gate /* ULINE("\t", "-C Kerberos 4 cache name", OPTTYPE_KRB4); */
3270Sstevel@tonic-gate ULINE("\t", gettext("-S service"), OPTTYPE_BOTH);
328*7934SMark.Phalan@Sun.COM ULINE("\t", gettext("-X <attribute>[=<value>]"), OPTTYPE_KRB5);
3290Sstevel@tonic-gate exit(2);
3300Sstevel@tonic-gate }
3310Sstevel@tonic-gate
332*7934SMark.Phalan@Sun.COM static krb5_context errctx;
extended_com_err_fn(const char * myprog,errcode_t code,const char * fmt,va_list args)333*7934SMark.Phalan@Sun.COM static void extended_com_err_fn (const char *myprog, errcode_t code,
334*7934SMark.Phalan@Sun.COM const char *fmt, va_list args)
335*7934SMark.Phalan@Sun.COM {
336*7934SMark.Phalan@Sun.COM const char *emsg;
337*7934SMark.Phalan@Sun.COM emsg = krb5_get_error_message (errctx, code);
338*7934SMark.Phalan@Sun.COM fprintf (stderr, "%s: %s ", myprog, emsg);
339*7934SMark.Phalan@Sun.COM krb5_free_error_message (errctx, emsg);
340*7934SMark.Phalan@Sun.COM vfprintf (stderr, fmt, args);
341*7934SMark.Phalan@Sun.COM fprintf (stderr, "\n");
342*7934SMark.Phalan@Sun.COM }
343*7934SMark.Phalan@Sun.COM
344*7934SMark.Phalan@Sun.COM static int
add_preauth_opt(struct k_opts * opts,char * av)345*7934SMark.Phalan@Sun.COM add_preauth_opt(struct k_opts *opts, char *av)
346*7934SMark.Phalan@Sun.COM {
347*7934SMark.Phalan@Sun.COM char *sep, *v;
348*7934SMark.Phalan@Sun.COM krb5_gic_opt_pa_data *p, *x;
349*7934SMark.Phalan@Sun.COM
350*7934SMark.Phalan@Sun.COM if (opts->num_pa_opts == 0) {
351*7934SMark.Phalan@Sun.COM opts->pa_opts = malloc(sizeof(krb5_gic_opt_pa_data));
352*7934SMark.Phalan@Sun.COM if (opts->pa_opts == NULL)
353*7934SMark.Phalan@Sun.COM return ENOMEM;
354*7934SMark.Phalan@Sun.COM } else {
355*7934SMark.Phalan@Sun.COM size_t newsize = (opts->num_pa_opts + 1) * sizeof(krb5_gic_opt_pa_data);
356*7934SMark.Phalan@Sun.COM x = realloc(opts->pa_opts, newsize);
357*7934SMark.Phalan@Sun.COM if (x == NULL)
358*7934SMark.Phalan@Sun.COM return ENOMEM;
359*7934SMark.Phalan@Sun.COM opts->pa_opts = x;
360*7934SMark.Phalan@Sun.COM }
361*7934SMark.Phalan@Sun.COM p = &opts->pa_opts[opts->num_pa_opts];
362*7934SMark.Phalan@Sun.COM sep = strchr(av, '=');
363*7934SMark.Phalan@Sun.COM if (sep) {
364*7934SMark.Phalan@Sun.COM *sep = '\0';
365*7934SMark.Phalan@Sun.COM v = ++sep;
366*7934SMark.Phalan@Sun.COM p->value = v;
367*7934SMark.Phalan@Sun.COM } else {
368*7934SMark.Phalan@Sun.COM p->value = "yes";
369*7934SMark.Phalan@Sun.COM }
370*7934SMark.Phalan@Sun.COM p->attr = av;
371*7934SMark.Phalan@Sun.COM opts->num_pa_opts++;
372*7934SMark.Phalan@Sun.COM return 0;
373*7934SMark.Phalan@Sun.COM }
374*7934SMark.Phalan@Sun.COM
3752881Smp153739 static char *
parse_options(argc,argv,opts,progname)3762881Smp153739 parse_options(argc, argv, opts, progname)
3770Sstevel@tonic-gate int argc;
3780Sstevel@tonic-gate char **argv;
3790Sstevel@tonic-gate struct k_opts* opts;
3802881Smp153739 char *progname;
3810Sstevel@tonic-gate {
3820Sstevel@tonic-gate krb5_error_code code;
3830Sstevel@tonic-gate int errflg = 0;
3840Sstevel@tonic-gate int use_k4 = 0;
3850Sstevel@tonic-gate int use_k5 = 0;
3860Sstevel@tonic-gate int i;
3870Sstevel@tonic-gate
388*7934SMark.Phalan@Sun.COM while ((i = GETOPT(argc, argv, "r:fpFP54aAVl:s:c:kt:RS:vX:"))
3890Sstevel@tonic-gate != -1) {
3900Sstevel@tonic-gate switch (i) {
3910Sstevel@tonic-gate case 'V':
3920Sstevel@tonic-gate opts->verbose = 1;
3930Sstevel@tonic-gate break;
3940Sstevel@tonic-gate case 'l':
3950Sstevel@tonic-gate /* Lifetime */
3960Sstevel@tonic-gate code = krb5_string_to_deltat(optarg, &opts->lifetime);
3970Sstevel@tonic-gate if (code != 0 || opts->lifetime == 0) {
3980Sstevel@tonic-gate fprintf(stderr, gettext("Bad lifetime value %s\n"), optarg);
3990Sstevel@tonic-gate errflg++;
4000Sstevel@tonic-gate }
4010Sstevel@tonic-gate break;
4020Sstevel@tonic-gate case 'r':
4030Sstevel@tonic-gate /* Renewable Time */
4040Sstevel@tonic-gate code = krb5_string_to_deltat(optarg, &opts->rlife);
4050Sstevel@tonic-gate if (code != 0 || opts->rlife == 0) {
4060Sstevel@tonic-gate fprintf(stderr, gettext("Bad lifetime value %s\n"), optarg);
4070Sstevel@tonic-gate errflg++;
4080Sstevel@tonic-gate }
4090Sstevel@tonic-gate break;
4100Sstevel@tonic-gate case 'f':
4110Sstevel@tonic-gate opts->forwardable = 1;
4120Sstevel@tonic-gate break;
4130Sstevel@tonic-gate case 'F':
4140Sstevel@tonic-gate opts->not_forwardable = 1;
4150Sstevel@tonic-gate break;
4160Sstevel@tonic-gate case 'p':
4170Sstevel@tonic-gate opts->proxiable = 1;
4180Sstevel@tonic-gate break;
4190Sstevel@tonic-gate case 'P':
4200Sstevel@tonic-gate opts->not_proxiable = 1;
4210Sstevel@tonic-gate break;
4220Sstevel@tonic-gate case 'a':
4230Sstevel@tonic-gate /* Note: This is supported only with GETOPT_LONG */
4240Sstevel@tonic-gate opts->addresses = 1;
4250Sstevel@tonic-gate break;
4260Sstevel@tonic-gate case 'A':
4270Sstevel@tonic-gate opts->no_addresses = 1;
4280Sstevel@tonic-gate break;
4290Sstevel@tonic-gate case 's':
4300Sstevel@tonic-gate code = krb5_string_to_deltat(optarg, &opts->starttime);
4310Sstevel@tonic-gate if (code != 0 || opts->starttime == 0) {
4320Sstevel@tonic-gate krb5_timestamp abs_starttime;
4330Sstevel@tonic-gate
4340Sstevel@tonic-gate code = krb5_string_to_timestamp(optarg, &abs_starttime);
4350Sstevel@tonic-gate if (code != 0 || abs_starttime == 0) {
4360Sstevel@tonic-gate fprintf(stderr, gettext("Bad start time value %s\n"), optarg);
4370Sstevel@tonic-gate errflg++;
4380Sstevel@tonic-gate } else {
4390Sstevel@tonic-gate opts->starttime = abs_starttime - time(0);
4400Sstevel@tonic-gate }
4410Sstevel@tonic-gate }
4420Sstevel@tonic-gate break;
4430Sstevel@tonic-gate case 'S':
4440Sstevel@tonic-gate opts->service_name = optarg;
4450Sstevel@tonic-gate break;
4460Sstevel@tonic-gate case 'k':
4470Sstevel@tonic-gate opts->action = INIT_KT;
4480Sstevel@tonic-gate break;
4490Sstevel@tonic-gate case 't':
4500Sstevel@tonic-gate if (opts->keytab_name)
4510Sstevel@tonic-gate {
4520Sstevel@tonic-gate fprintf(stderr, gettext("Only one -t option allowed.\n"));
4530Sstevel@tonic-gate errflg++;
4540Sstevel@tonic-gate } else {
4550Sstevel@tonic-gate opts->keytab_name = optarg;
4560Sstevel@tonic-gate }
4570Sstevel@tonic-gate break;
4580Sstevel@tonic-gate case 'R':
4590Sstevel@tonic-gate opts->action = RENEW;
4600Sstevel@tonic-gate break;
4610Sstevel@tonic-gate case 'v':
4620Sstevel@tonic-gate opts->action = VALIDATE;
4630Sstevel@tonic-gate break;
4640Sstevel@tonic-gate case 'c':
4650Sstevel@tonic-gate if (opts->k5_cache_name)
4660Sstevel@tonic-gate {
4670Sstevel@tonic-gate fprintf(stderr, gettext("Only one -c option allowed\n"));
4680Sstevel@tonic-gate errflg++;
4690Sstevel@tonic-gate } else {
4700Sstevel@tonic-gate opts->k5_cache_name = optarg;
4710Sstevel@tonic-gate }
4720Sstevel@tonic-gate break;
473*7934SMark.Phalan@Sun.COM case 'X':
474*7934SMark.Phalan@Sun.COM code = add_preauth_opt(opts, optarg);
475*7934SMark.Phalan@Sun.COM if (code)
476*7934SMark.Phalan@Sun.COM {
477*7934SMark.Phalan@Sun.COM com_err(progname, code, "while adding preauth option");
478*7934SMark.Phalan@Sun.COM errflg++;
479*7934SMark.Phalan@Sun.COM }
480*7934SMark.Phalan@Sun.COM break;
4810Sstevel@tonic-gate #if 0
4820Sstevel@tonic-gate /*
4830Sstevel@tonic-gate A little more work is needed before we can enable this
4840Sstevel@tonic-gate option.
4850Sstevel@tonic-gate */
4860Sstevel@tonic-gate case 'C':
4870Sstevel@tonic-gate if (opts->k4_cache_name)
4880Sstevel@tonic-gate {
4890Sstevel@tonic-gate fprintf(stderr, "Only one -C option allowed\n");
4900Sstevel@tonic-gate errflg++;
4910Sstevel@tonic-gate } else {
4920Sstevel@tonic-gate opts->k4_cache_name = optarg;
4930Sstevel@tonic-gate }
4940Sstevel@tonic-gate break;
4950Sstevel@tonic-gate #endif
4960Sstevel@tonic-gate case '4':
4970Sstevel@tonic-gate if (!got_k4)
4980Sstevel@tonic-gate {
4990Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
5000Sstevel@tonic-gate fprintf(stderr, "Kerberos 4 support could not be loaded\n");
5010Sstevel@tonic-gate #else
5020Sstevel@tonic-gate fprintf(stderr, gettext("This was not built with Kerberos 4 support\n"));
5030Sstevel@tonic-gate #endif
5040Sstevel@tonic-gate exit(3);
5050Sstevel@tonic-gate }
5060Sstevel@tonic-gate use_k4 = 1;
5070Sstevel@tonic-gate break;
5080Sstevel@tonic-gate case '5':
5090Sstevel@tonic-gate if (!got_k5)
5100Sstevel@tonic-gate {
5110Sstevel@tonic-gate fprintf(stderr, gettext("Kerberos 5 support could not be loaded\n"));
5120Sstevel@tonic-gate exit(3);
5130Sstevel@tonic-gate }
5140Sstevel@tonic-gate use_k5 = 1;
5150Sstevel@tonic-gate break;
5160Sstevel@tonic-gate default:
5170Sstevel@tonic-gate errflg++;
5180Sstevel@tonic-gate break;
5190Sstevel@tonic-gate }
5200Sstevel@tonic-gate }
5210Sstevel@tonic-gate
5220Sstevel@tonic-gate if (opts->forwardable && opts->not_forwardable)
5230Sstevel@tonic-gate {
5240Sstevel@tonic-gate fprintf(stderr, gettext("Only one of -f and -F allowed\n"));
5250Sstevel@tonic-gate errflg++;
5260Sstevel@tonic-gate }
5270Sstevel@tonic-gate if (opts->proxiable && opts->not_proxiable)
5280Sstevel@tonic-gate {
5290Sstevel@tonic-gate fprintf(stderr, gettext("Only one of -p and -P allowed\n"));
5300Sstevel@tonic-gate errflg++;
5310Sstevel@tonic-gate }
5320Sstevel@tonic-gate if (opts->addresses && opts->no_addresses)
5330Sstevel@tonic-gate {
5340Sstevel@tonic-gate fprintf(stderr, gettext("Only one of -a and -A allowed\n"));
5350Sstevel@tonic-gate errflg++;
5360Sstevel@tonic-gate }
5370Sstevel@tonic-gate
5380Sstevel@tonic-gate if (argc - optind > 1) {
5390Sstevel@tonic-gate fprintf(stderr, gettext("Extra arguments (starting with \"%s\").\n"),
5400Sstevel@tonic-gate argv[optind+1]);
5410Sstevel@tonic-gate errflg++;
5420Sstevel@tonic-gate }
5430Sstevel@tonic-gate
5440Sstevel@tonic-gate /* At this point, if errorless, we know we only have one option
5450Sstevel@tonic-gate selection */
5460Sstevel@tonic-gate if (!use_k5 && !use_k4) {
5470Sstevel@tonic-gate use_k5 = default_k5;
5480Sstevel@tonic-gate use_k4 = default_k4;
5490Sstevel@tonic-gate }
5500Sstevel@tonic-gate
5510Sstevel@tonic-gate /* Now, we encode the OPTTYPE stuff here... */
5520Sstevel@tonic-gate if (!use_k5 &&
5530Sstevel@tonic-gate (opts->starttime || opts->rlife || opts->forwardable ||
5540Sstevel@tonic-gate opts->proxiable || opts->addresses || opts->not_forwardable ||
5550Sstevel@tonic-gate opts->not_proxiable || opts->no_addresses ||
5560Sstevel@tonic-gate (opts->action == VALIDATE) || opts->k5_cache_name))
5570Sstevel@tonic-gate {
5580Sstevel@tonic-gate fprintf(stderr, gettext("Specified option that requires Kerberos 5\n"));
5590Sstevel@tonic-gate errflg++;
5600Sstevel@tonic-gate }
5610Sstevel@tonic-gate if (!use_k4 &&
5620Sstevel@tonic-gate opts->k4_cache_name)
5630Sstevel@tonic-gate {
5640Sstevel@tonic-gate fprintf(stderr, gettext("Specified option that require Kerberos 4\n"));
5650Sstevel@tonic-gate errflg++;
5660Sstevel@tonic-gate }
5670Sstevel@tonic-gate if (
5680Sstevel@tonic-gate #ifdef HAVE_KRB524
5690Sstevel@tonic-gate !use_k5
5700Sstevel@tonic-gate #else
5710Sstevel@tonic-gate use_k4
5720Sstevel@tonic-gate #endif
5730Sstevel@tonic-gate && (opts->service_name || opts->keytab_name ||
5740Sstevel@tonic-gate (opts->action == INIT_KT) || (opts->action == RENEW))
5750Sstevel@tonic-gate )
5760Sstevel@tonic-gate {
5770Sstevel@tonic-gate fprintf(stderr, gettext("Specified option that requires Kerberos 5\n"));
5780Sstevel@tonic-gate errflg++;
5790Sstevel@tonic-gate }
5800Sstevel@tonic-gate
5810Sstevel@tonic-gate if (errflg) {
5822881Smp153739 usage(progname);
5830Sstevel@tonic-gate }
5840Sstevel@tonic-gate
5850Sstevel@tonic-gate got_k5 = got_k5 && use_k5;
5860Sstevel@tonic-gate got_k4 = got_k4 && use_k4;
5870Sstevel@tonic-gate
5880Sstevel@tonic-gate opts->principal_name = (optind == argc-1) ? argv[optind] : 0;
5890Sstevel@tonic-gate return opts->principal_name;
5900Sstevel@tonic-gate }
5910Sstevel@tonic-gate
5922881Smp153739 static int
k5_begin(opts,k5,k4)5930Sstevel@tonic-gate k5_begin(opts, k5, k4)
5940Sstevel@tonic-gate struct k_opts* opts;
5950Sstevel@tonic-gate struct k5_data* k5;
5960Sstevel@tonic-gate struct k4_data* k4;
5970Sstevel@tonic-gate {
5980Sstevel@tonic-gate char* progname = progname_v5;
5990Sstevel@tonic-gate krb5_error_code code = 0;
6000Sstevel@tonic-gate
6010Sstevel@tonic-gate if (!got_k5)
6020Sstevel@tonic-gate return 0;
6030Sstevel@tonic-gate
6042881Smp153739 code = krb5_init_context(&k5->ctx);
6052881Smp153739 if (code) {
6060Sstevel@tonic-gate com_err(progname, code, gettext("while initializing Kerberos 5 library"));
6070Sstevel@tonic-gate return 0;
6080Sstevel@tonic-gate }
609*7934SMark.Phalan@Sun.COM errctx = k5->ctx;
6100Sstevel@tonic-gate if (opts->k5_cache_name)
6110Sstevel@tonic-gate {
6120Sstevel@tonic-gate code = krb5_cc_resolve(k5->ctx, opts->k5_cache_name, &k5->cc);
6130Sstevel@tonic-gate if (code != 0) {
6140Sstevel@tonic-gate com_err(progname, code, gettext("resolving ccache %s"),
6150Sstevel@tonic-gate opts->k5_cache_name);
6160Sstevel@tonic-gate return 0;
6170Sstevel@tonic-gate }
6180Sstevel@tonic-gate }
6190Sstevel@tonic-gate else
6200Sstevel@tonic-gate {
6210Sstevel@tonic-gate if ((code = krb5_cc_default(k5->ctx, &k5->cc))) {
6220Sstevel@tonic-gate com_err(progname, code, gettext("while getting default ccache"));
6230Sstevel@tonic-gate return 0;
6240Sstevel@tonic-gate }
6250Sstevel@tonic-gate }
6260Sstevel@tonic-gate
6270Sstevel@tonic-gate if (opts->principal_name)
6280Sstevel@tonic-gate {
6290Sstevel@tonic-gate /* Use specified name */
6300Sstevel@tonic-gate if ((code = krb5_parse_name(k5->ctx, opts->principal_name,
6310Sstevel@tonic-gate &k5->me))) {
6320Sstevel@tonic-gate com_err(progname, code, gettext("when parsing name %s"),
6330Sstevel@tonic-gate opts->principal_name);
6340Sstevel@tonic-gate return 0;
6350Sstevel@tonic-gate }
6360Sstevel@tonic-gate }
6370Sstevel@tonic-gate else
6380Sstevel@tonic-gate {
6390Sstevel@tonic-gate /* No principal name specified */
6400Sstevel@tonic-gate if (opts->action == INIT_KT) {
6410Sstevel@tonic-gate /* Use the default host/service name */
6422881Smp153739 code = krb5_sname_to_principal(k5->ctx, NULL, NULL,
6432881Smp153739 KRB5_NT_SRV_HST, &k5->me);
6442881Smp153739 if (code) {
6452881Smp153739 com_err(progname, code, gettext(
6462881Smp153739 "when creating default server principal name"));
6472881Smp153739 return 0;
6482881Smp153739 }
6490Sstevel@tonic-gate } else {
6502881Smp153739 /* Get default principal from cache if one exists */
6512881Smp153739 code = krb5_cc_get_principal(k5->ctx, k5->cc,
6522881Smp153739 &k5->me);
6532881Smp153739 if (code)
6542881Smp153739 {
6552881Smp153739 char *name = get_name_from_os();
6562881Smp153739 if (!name)
6572881Smp153739 {
6582881Smp153739 fprintf(stderr, gettext("Unable to identify user\n"));
6592881Smp153739 return 0;
6602881Smp153739 }
6610Sstevel@tonic-gate /* use strcmp to ensure only "root" is matched */
6620Sstevel@tonic-gate if (strcmp(name, ROOT_UNAME) == 0)
6630Sstevel@tonic-gate {
6640Sstevel@tonic-gate if (code = krb5_sname_to_principal(k5->ctx, NULL, ROOT_UNAME,
6650Sstevel@tonic-gate KRB5_NT_SRV_HST, &k5->me)) {
6660Sstevel@tonic-gate com_err(progname, code, gettext(
6670Sstevel@tonic-gate "when creating default server principal name"));
6680Sstevel@tonic-gate return 0;
6690Sstevel@tonic-gate }
6702881Smp153739 } else
6712881Smp153739 if ((code = krb5_parse_name(k5->ctx, name,
6722881Smp153739 &k5->me)))
6732881Smp153739 {
6742881Smp153739 com_err(progname, code, gettext("when parsing name %s"),
6752881Smp153739 name);
6762881Smp153739 return 0;
6770Sstevel@tonic-gate }
6782881Smp153739 }
6792881Smp153739 }
6800Sstevel@tonic-gate }
6812881Smp153739
6822881Smp153739 code = krb5_unparse_name(k5->ctx, k5->me, &k5->name);
6832881Smp153739 if (code) {
6840Sstevel@tonic-gate com_err(progname, code, gettext("when unparsing name"));
6850Sstevel@tonic-gate return 0;
6860Sstevel@tonic-gate }
6870Sstevel@tonic-gate opts->principal_name = k5->name;
6880Sstevel@tonic-gate
6890Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
6900Sstevel@tonic-gate if (got_k4)
6910Sstevel@tonic-gate {
6920Sstevel@tonic-gate /* Translate to a Kerberos 4 principal */
6930Sstevel@tonic-gate code = krb5_524_conv_principal(k5->ctx, k5->me,
6940Sstevel@tonic-gate k4->aname, k4->inst, k4->realm);
6950Sstevel@tonic-gate if (code) {
6960Sstevel@tonic-gate k4->aname[0] = 0;
6970Sstevel@tonic-gate k4->inst[0] = 0;
6980Sstevel@tonic-gate k4->realm[0] = 0;
6990Sstevel@tonic-gate }
7000Sstevel@tonic-gate }
7010Sstevel@tonic-gate #endif
7020Sstevel@tonic-gate return 1;
7030Sstevel@tonic-gate }
7040Sstevel@tonic-gate
7052881Smp153739 static void
k5_end(k5)7060Sstevel@tonic-gate k5_end(k5)
7070Sstevel@tonic-gate struct k5_data* k5;
7080Sstevel@tonic-gate {
7090Sstevel@tonic-gate if (k5->name)
7100Sstevel@tonic-gate krb5_free_unparsed_name(k5->ctx, k5->name);
7110Sstevel@tonic-gate if (k5->me)
7120Sstevel@tonic-gate krb5_free_principal(k5->ctx, k5->me);
7130Sstevel@tonic-gate if (k5->cc)
7140Sstevel@tonic-gate krb5_cc_close(k5->ctx, k5->cc);
7150Sstevel@tonic-gate if (k5->ctx)
7160Sstevel@tonic-gate krb5_free_context(k5->ctx);
717*7934SMark.Phalan@Sun.COM errctx = NULL;
7180Sstevel@tonic-gate memset(k5, 0, sizeof(*k5));
7190Sstevel@tonic-gate }
7200Sstevel@tonic-gate
7212881Smp153739 static int
k4_begin(opts,k4)7220Sstevel@tonic-gate k4_begin(opts, k4)
7230Sstevel@tonic-gate struct k_opts* opts;
7240Sstevel@tonic-gate struct k4_data* k4;
7250Sstevel@tonic-gate {
7260Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
7270Sstevel@tonic-gate char* progname = progname_v4;
7280Sstevel@tonic-gate int k_errno = 0;
7290Sstevel@tonic-gate #endif
7300Sstevel@tonic-gate
7310Sstevel@tonic-gate if (!got_k4)
7320Sstevel@tonic-gate return 0;
7330Sstevel@tonic-gate
7340Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
7350Sstevel@tonic-gate if (k4->aname[0])
7360Sstevel@tonic-gate goto skip;
7370Sstevel@tonic-gate
7380Sstevel@tonic-gate if (opts->principal_name)
7390Sstevel@tonic-gate {
7400Sstevel@tonic-gate /* Use specified name */
7412881Smp153739 k_errno = kname_parse(k4->aname, k4->inst, k4->realm,
7422881Smp153739 opts->principal_name);
7432881Smp153739 if (k_errno)
7440Sstevel@tonic-gate {
7450Sstevel@tonic-gate fprintf(stderr, "%s: %s\n", progname,
7460Sstevel@tonic-gate krb_get_err_text(k_errno));
7470Sstevel@tonic-gate return 0;
7480Sstevel@tonic-gate }
7490Sstevel@tonic-gate } else {
7500Sstevel@tonic-gate /* No principal name specified */
7510Sstevel@tonic-gate if (opts->action == INIT_KT) {
7520Sstevel@tonic-gate /* Use the default host/service name */
7530Sstevel@tonic-gate /* XXX - need to add this functionality */
7540Sstevel@tonic-gate fprintf(stderr, "%s: Kerberos 4 srvtab support is not "
7550Sstevel@tonic-gate "implemented\n", progname);
7560Sstevel@tonic-gate return 0;
7570Sstevel@tonic-gate } else {
7580Sstevel@tonic-gate /* Get default principal from cache if one exists */
7592881Smp153739 k_errno = krb_get_tf_fullname(tkt_string(), k4->aname,
7602881Smp153739 k4->inst, k4->realm);
7612881Smp153739 if (k_errno)
7620Sstevel@tonic-gate {
7630Sstevel@tonic-gate char *name = get_name_from_os();
7640Sstevel@tonic-gate if (!name)
7650Sstevel@tonic-gate {
7660Sstevel@tonic-gate fprintf(stderr, "Unable to identify user\n");
7670Sstevel@tonic-gate return 0;
7680Sstevel@tonic-gate }
7692881Smp153739 k_errno = kname_parse(k4->aname, k4->inst, k4->realm,
7702881Smp153739 name);
7712881Smp153739 if (k_errno)
7720Sstevel@tonic-gate {
7730Sstevel@tonic-gate fprintf(stderr, "%s: %s\n", progname,
7740Sstevel@tonic-gate krb_get_err_text(k_errno));
7750Sstevel@tonic-gate return 0;
7760Sstevel@tonic-gate }
7770Sstevel@tonic-gate }
7780Sstevel@tonic-gate }
7790Sstevel@tonic-gate }
7800Sstevel@tonic-gate
7810Sstevel@tonic-gate if (!k4->realm[0])
7820Sstevel@tonic-gate krb_get_lrealm(k4->realm, 1);
7830Sstevel@tonic-gate
7840Sstevel@tonic-gate if (k4->inst[0])
7850Sstevel@tonic-gate sprintf(k4->name, "%s.%s@%s", k4->aname, k4->inst, k4->realm);
7860Sstevel@tonic-gate else
7870Sstevel@tonic-gate sprintf(k4->name, "%s@%s", k4->aname, k4->realm);
7880Sstevel@tonic-gate opts->principal_name = k4->name;
7890Sstevel@tonic-gate
7900Sstevel@tonic-gate skip:
7910Sstevel@tonic-gate if (k4->aname[0] && !k_isname(k4->aname))
7920Sstevel@tonic-gate {
7930Sstevel@tonic-gate fprintf(stderr, "%s: bad Kerberos 4 name format\n", progname);
7940Sstevel@tonic-gate return 0;
7950Sstevel@tonic-gate }
7960Sstevel@tonic-gate
7970Sstevel@tonic-gate if (k4->inst[0] && !k_isinst(k4->inst))
7980Sstevel@tonic-gate {
7990Sstevel@tonic-gate fprintf(stderr, "%s: bad Kerberos 4 instance format\n", progname);
8000Sstevel@tonic-gate return 0;
8010Sstevel@tonic-gate }
8020Sstevel@tonic-gate
8030Sstevel@tonic-gate if (k4->realm[0] && !k_isrealm(k4->realm))
8040Sstevel@tonic-gate {
8050Sstevel@tonic-gate fprintf(stderr, "%s: bad Kerberos 4 realm format\n", progname);
8060Sstevel@tonic-gate return 0;
8070Sstevel@tonic-gate }
8080Sstevel@tonic-gate #endif /* KRB5_KRB4_COMPAT */
8090Sstevel@tonic-gate return 1;
8100Sstevel@tonic-gate }
8110Sstevel@tonic-gate
8122881Smp153739 static void
k4_end(k4)8130Sstevel@tonic-gate k4_end(k4)
8140Sstevel@tonic-gate struct k4_data* k4;
8150Sstevel@tonic-gate {
8160Sstevel@tonic-gate memset(k4, 0, sizeof(*k4));
8170Sstevel@tonic-gate }
8180Sstevel@tonic-gate
8190Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
8200Sstevel@tonic-gate static char stash_password[1024];
8210Sstevel@tonic-gate static int got_password = 0;
8220Sstevel@tonic-gate #endif /* KRB5_KRB4_COMPAT */
8230Sstevel@tonic-gate
8242881Smp153739 static krb5_error_code
8250Sstevel@tonic-gate KRB5_CALLCONV
kinit_prompter(krb5_context ctx,void * data,const char * name,const char * banner,int num_prompts,krb5_prompt prompts[])8260Sstevel@tonic-gate kinit_prompter(
8270Sstevel@tonic-gate krb5_context ctx,
8280Sstevel@tonic-gate void *data,
8290Sstevel@tonic-gate const char *name,
8300Sstevel@tonic-gate const char *banner,
8310Sstevel@tonic-gate int num_prompts,
8320Sstevel@tonic-gate krb5_prompt prompts[]
8330Sstevel@tonic-gate )
8340Sstevel@tonic-gate {
8350Sstevel@tonic-gate int i;
8360Sstevel@tonic-gate krb5_prompt_type *types;
8370Sstevel@tonic-gate krb5_error_code rc =
8380Sstevel@tonic-gate krb5_prompter_posix(ctx, data, name, banner, num_prompts, prompts);
8390Sstevel@tonic-gate if (!rc && (types = krb5_get_prompt_types(ctx)))
8400Sstevel@tonic-gate for (i = 0; i < num_prompts; i++)
8410Sstevel@tonic-gate if ((types[i] == KRB5_PROMPT_TYPE_PASSWORD) ||
8420Sstevel@tonic-gate (types[i] == KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN))
8430Sstevel@tonic-gate {
8440Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
8450Sstevel@tonic-gate strncpy(stash_password, prompts[i].reply->data,
8460Sstevel@tonic-gate sizeof(stash_password));
8470Sstevel@tonic-gate got_password = 1;
8480Sstevel@tonic-gate #endif
8490Sstevel@tonic-gate }
8500Sstevel@tonic-gate return rc;
8510Sstevel@tonic-gate }
8520Sstevel@tonic-gate
8532881Smp153739 static int
k5_kinit(opts,k5)8540Sstevel@tonic-gate k5_kinit(opts, k5)
8550Sstevel@tonic-gate struct k_opts* opts;
8560Sstevel@tonic-gate struct k5_data* k5;
8570Sstevel@tonic-gate {
8580Sstevel@tonic-gate char* progname = progname_v5;
8590Sstevel@tonic-gate int notix = 1;
8600Sstevel@tonic-gate krb5_keytab keytab = 0;
8610Sstevel@tonic-gate krb5_creds my_creds;
8620Sstevel@tonic-gate krb5_error_code code = 0;
863*7934SMark.Phalan@Sun.COM krb5_get_init_creds_opt *options = NULL;
864*7934SMark.Phalan@Sun.COM int i;
8650Sstevel@tonic-gate krb5_timestamp now;
8660Sstevel@tonic-gate krb5_deltat lifetime = 0, rlife = 0, krb5_max_duration;
8670Sstevel@tonic-gate
8680Sstevel@tonic-gate if (!got_k5)
8690Sstevel@tonic-gate return 0;
8700Sstevel@tonic-gate
871*7934SMark.Phalan@Sun.COM code = krb5_get_init_creds_opt_alloc(k5->ctx, &options);
872*7934SMark.Phalan@Sun.COM if (code)
873*7934SMark.Phalan@Sun.COM goto cleanup;
8740Sstevel@tonic-gate memset(&my_creds, 0, sizeof(my_creds));
8750Sstevel@tonic-gate
8760Sstevel@tonic-gate /*
8770Sstevel@tonic-gate * Solaris Kerberos: added support for max_life and max_renewable_life
8780Sstevel@tonic-gate * which should be removed in the next minor release. See PSARC 2003/545
8790Sstevel@tonic-gate * for more info.
8800Sstevel@tonic-gate *
8810Sstevel@tonic-gate * Also, check krb5.conf for proxiable/forwardable/renewable/no_address
8820Sstevel@tonic-gate * parameter values.
8830Sstevel@tonic-gate */
8840Sstevel@tonic-gate /* If either tkt life or renew life weren't set earlier take common steps to
8850Sstevel@tonic-gate * get the krb5.conf parameter values.
8860Sstevel@tonic-gate */
8870Sstevel@tonic-gate
8880Sstevel@tonic-gate if ((code = krb5_timeofday(k5->ctx, &now))) {
8890Sstevel@tonic-gate com_err(progname, code, gettext("while getting time of day"));
8900Sstevel@tonic-gate exit(1);
8910Sstevel@tonic-gate }
8920Sstevel@tonic-gate krb5_max_duration = KRB5_KDB_EXPIRATION - now - 60*60;
8930Sstevel@tonic-gate
8940Sstevel@tonic-gate if (opts->lifetime == 0 || opts->rlife == 0) {
8950Sstevel@tonic-gate
8960Sstevel@tonic-gate krb_realm = krb5_princ_realm(k5->ctx, k5->me)->data;
8970Sstevel@tonic-gate /* realm params take precedence */
8980Sstevel@tonic-gate profile_get_options_string(k5->ctx->profile, realmdef, config_times);
8990Sstevel@tonic-gate profile_get_options_string(k5->ctx->profile, appdef, config_times);
9000Sstevel@tonic-gate
9010Sstevel@tonic-gate /* if the input opts doesn't have lifetime set and the krb5.conf
9020Sstevel@tonic-gate * parameter has been set, use that.
9030Sstevel@tonic-gate */
9040Sstevel@tonic-gate if (opts->lifetime == 0 && life_timeval != NULL) {
9050Sstevel@tonic-gate code = krb5_string_to_deltat(life_timeval, &lifetime);
9060Sstevel@tonic-gate if (code != 0 || lifetime == 0 || lifetime > krb5_max_duration) {
9070Sstevel@tonic-gate fprintf(stderr, gettext("Bad max_life "
9080Sstevel@tonic-gate "value in Kerberos config file %s\n"),
9090Sstevel@tonic-gate life_timeval);
9100Sstevel@tonic-gate exit(1);
9110Sstevel@tonic-gate }
9120Sstevel@tonic-gate opts->lifetime = lifetime;
9130Sstevel@tonic-gate }
9140Sstevel@tonic-gate if (opts->rlife == 0 && renew_timeval != NULL) {
9150Sstevel@tonic-gate code = krb5_string_to_deltat(renew_timeval, &rlife);
9160Sstevel@tonic-gate if (code != 0 || rlife == 0 || rlife > krb5_max_duration) {
9170Sstevel@tonic-gate fprintf(stderr, gettext("Bad max_renewable_life "
9180Sstevel@tonic-gate "value in Kerberos config file %s\n"),
9190Sstevel@tonic-gate renew_timeval);
9200Sstevel@tonic-gate exit(1);
9210Sstevel@tonic-gate }
9220Sstevel@tonic-gate opts->rlife = rlife;
9230Sstevel@tonic-gate }
9240Sstevel@tonic-gate }
9250Sstevel@tonic-gate
9260Sstevel@tonic-gate /*
9270Sstevel@tonic-gate * If lifetime is not set on the cmdline or in the krb5.conf
9280Sstevel@tonic-gate * file, default to max.
9290Sstevel@tonic-gate */
9300Sstevel@tonic-gate if (opts->lifetime == 0)
9310Sstevel@tonic-gate opts->lifetime = krb5_max_duration;
9320Sstevel@tonic-gate
9330Sstevel@tonic-gate
9340Sstevel@tonic-gate profile_get_options_boolean(k5->ctx->profile,
9350Sstevel@tonic-gate realmdef, config_option);
9360Sstevel@tonic-gate profile_get_options_boolean(k5->ctx->profile,
9370Sstevel@tonic-gate appdef, config_option);
9380Sstevel@tonic-gate
9390Sstevel@tonic-gate
9400Sstevel@tonic-gate /* cmdline opts take precedence over krb5.conf file values */
9410Sstevel@tonic-gate if (!opts->not_proxiable && proxiable_flag) {
942*7934SMark.Phalan@Sun.COM krb5_get_init_creds_opt_set_proxiable(options, 1);
9430Sstevel@tonic-gate }
9440Sstevel@tonic-gate if (!opts->not_forwardable && forwardable_flag) {
945*7934SMark.Phalan@Sun.COM krb5_get_init_creds_opt_set_forwardable(options, 1);
9460Sstevel@tonic-gate }
9470Sstevel@tonic-gate if (renewable_flag) {
9480Sstevel@tonic-gate /*
9490Sstevel@tonic-gate * If this flag is set in krb5.conf, but rlife is 0, then
9500Sstevel@tonic-gate * set it to the max (and let the KDC sort it out).
9510Sstevel@tonic-gate */
9520Sstevel@tonic-gate opts->rlife = opts->rlife ? opts->rlife : krb5_max_duration;
9530Sstevel@tonic-gate }
9540Sstevel@tonic-gate if (no_address_flag) {
9550Sstevel@tonic-gate /* cmdline opts will overwrite this below if needbe */
956*7934SMark.Phalan@Sun.COM krb5_get_init_creds_opt_set_address_list(options, NULL);
9570Sstevel@tonic-gate }
9580Sstevel@tonic-gate
9590Sstevel@tonic-gate
9600Sstevel@tonic-gate /*
9610Sstevel@tonic-gate From this point on, we can goto cleanup because my_creds is
9620Sstevel@tonic-gate initialized.
9630Sstevel@tonic-gate */
9640Sstevel@tonic-gate
9650Sstevel@tonic-gate if (opts->lifetime)
966*7934SMark.Phalan@Sun.COM krb5_get_init_creds_opt_set_tkt_life(options, opts->lifetime);
9670Sstevel@tonic-gate if (opts->rlife)
968*7934SMark.Phalan@Sun.COM krb5_get_init_creds_opt_set_renew_life(options, opts->rlife);
9690Sstevel@tonic-gate if (opts->forwardable)
970*7934SMark.Phalan@Sun.COM krb5_get_init_creds_opt_set_forwardable(options, 1);
9710Sstevel@tonic-gate if (opts->not_forwardable)
972*7934SMark.Phalan@Sun.COM krb5_get_init_creds_opt_set_forwardable(options, 0);
9730Sstevel@tonic-gate if (opts->proxiable)
974*7934SMark.Phalan@Sun.COM krb5_get_init_creds_opt_set_proxiable(options, 1);
9750Sstevel@tonic-gate if (opts->not_proxiable)
976*7934SMark.Phalan@Sun.COM krb5_get_init_creds_opt_set_proxiable(options, 0);
9770Sstevel@tonic-gate if (opts->addresses)
9780Sstevel@tonic-gate {
9790Sstevel@tonic-gate krb5_address **addresses = NULL;
9800Sstevel@tonic-gate code = krb5_os_localaddr(k5->ctx, &addresses);
9810Sstevel@tonic-gate if (code != 0) {
9820Sstevel@tonic-gate com_err(progname, code, gettext("getting local addresses"));
9830Sstevel@tonic-gate goto cleanup;
9840Sstevel@tonic-gate }
985*7934SMark.Phalan@Sun.COM krb5_get_init_creds_opt_set_address_list(options, addresses);
9860Sstevel@tonic-gate }
9870Sstevel@tonic-gate if (opts->no_addresses)
988*7934SMark.Phalan@Sun.COM krb5_get_init_creds_opt_set_address_list(options, NULL);
9890Sstevel@tonic-gate
9900Sstevel@tonic-gate if ((opts->action == INIT_KT) && opts->keytab_name)
9910Sstevel@tonic-gate {
9920Sstevel@tonic-gate code = krb5_kt_resolve(k5->ctx, opts->keytab_name, &keytab);
9930Sstevel@tonic-gate if (code != 0) {
9940Sstevel@tonic-gate com_err(progname, code, gettext("resolving keytab %s"),
9950Sstevel@tonic-gate opts->keytab_name);
9960Sstevel@tonic-gate goto cleanup;
9970Sstevel@tonic-gate }
9980Sstevel@tonic-gate }
9990Sstevel@tonic-gate
1000*7934SMark.Phalan@Sun.COM for (i = 0; i < opts->num_pa_opts; i++) {
1001*7934SMark.Phalan@Sun.COM code = krb5_get_init_creds_opt_set_pa(k5->ctx, options,
1002*7934SMark.Phalan@Sun.COM opts->pa_opts[i].attr,
1003*7934SMark.Phalan@Sun.COM opts->pa_opts[i].value);
1004*7934SMark.Phalan@Sun.COM if (code != 0) {
1005*7934SMark.Phalan@Sun.COM com_err(progname, code, "while setting '%s'='%s'",
1006*7934SMark.Phalan@Sun.COM opts->pa_opts[i].attr, opts->pa_opts[i].value);
1007*7934SMark.Phalan@Sun.COM goto cleanup;
1008*7934SMark.Phalan@Sun.COM }
1009*7934SMark.Phalan@Sun.COM }
1010*7934SMark.Phalan@Sun.COM
10110Sstevel@tonic-gate switch (opts->action) {
10120Sstevel@tonic-gate case INIT_PW:
10130Sstevel@tonic-gate code = krb5_get_init_creds_password(k5->ctx, &my_creds, k5->me,
10140Sstevel@tonic-gate 0, kinit_prompter, 0,
10150Sstevel@tonic-gate opts->starttime,
10160Sstevel@tonic-gate opts->service_name,
1017*7934SMark.Phalan@Sun.COM options);
10180Sstevel@tonic-gate break;
10190Sstevel@tonic-gate case INIT_KT:
10200Sstevel@tonic-gate code = krb5_get_init_creds_keytab(k5->ctx, &my_creds, k5->me,
10210Sstevel@tonic-gate keytab,
10220Sstevel@tonic-gate opts->starttime,
10230Sstevel@tonic-gate opts->service_name,
1024*7934SMark.Phalan@Sun.COM options);
10250Sstevel@tonic-gate break;
10260Sstevel@tonic-gate case VALIDATE:
10270Sstevel@tonic-gate code = krb5_get_validated_creds(k5->ctx, &my_creds, k5->me, k5->cc,
10280Sstevel@tonic-gate opts->service_name);
10290Sstevel@tonic-gate break;
10300Sstevel@tonic-gate case RENEW:
10310Sstevel@tonic-gate code = krb5_get_renewed_creds(k5->ctx, &my_creds, k5->me, k5->cc,
10320Sstevel@tonic-gate opts->service_name);
10330Sstevel@tonic-gate break;
10340Sstevel@tonic-gate }
10350Sstevel@tonic-gate
10360Sstevel@tonic-gate if (code) {
10370Sstevel@tonic-gate char *doing = 0;
10380Sstevel@tonic-gate switch (opts->action) {
10390Sstevel@tonic-gate case INIT_PW:
10400Sstevel@tonic-gate case INIT_KT:
10410Sstevel@tonic-gate doing = gettext("getting initial credentials");
10420Sstevel@tonic-gate break;
10430Sstevel@tonic-gate case VALIDATE:
10440Sstevel@tonic-gate doing = gettext("validating credentials");
10450Sstevel@tonic-gate break;
10460Sstevel@tonic-gate case RENEW:
10470Sstevel@tonic-gate doing = gettext("renewing credentials");
10480Sstevel@tonic-gate break;
10490Sstevel@tonic-gate }
10500Sstevel@tonic-gate
10510Sstevel@tonic-gate /* If got code == KRB5_AP_ERR_V4_REPLY && got_k4, we should
10520Sstevel@tonic-gate let the user know that maybe he/she wants -4. */
10530Sstevel@tonic-gate if (code == KRB5KRB_AP_ERR_V4_REPLY && got_k4)
10540Sstevel@tonic-gate com_err(progname, code, "while %s\n"
10550Sstevel@tonic-gate "The KDC doesn't support v5. "
10560Sstevel@tonic-gate "You may want the -4 option in the future",
10570Sstevel@tonic-gate doing);
10580Sstevel@tonic-gate else if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY)
10590Sstevel@tonic-gate fprintf(stderr, gettext("%s: Password incorrect while %s\n"), progname,
10600Sstevel@tonic-gate doing);
10610Sstevel@tonic-gate else
10620Sstevel@tonic-gate com_err(progname, code, gettext("while %s"), doing);
10630Sstevel@tonic-gate goto cleanup;
10640Sstevel@tonic-gate }
10650Sstevel@tonic-gate
10660Sstevel@tonic-gate if (!opts->lifetime) {
10670Sstevel@tonic-gate /* We need to figure out what lifetime to use for Kerberos 4. */
10680Sstevel@tonic-gate opts->lifetime = my_creds.times.endtime - my_creds.times.authtime;
10690Sstevel@tonic-gate }
10700Sstevel@tonic-gate
10712881Smp153739 code = krb5_cc_initialize(k5->ctx, k5->cc, k5->me);
10722881Smp153739 if (code) {
10730Sstevel@tonic-gate com_err(progname, code, gettext("when initializing cache %s"),
10740Sstevel@tonic-gate opts->k5_cache_name?opts->k5_cache_name:"");
10750Sstevel@tonic-gate goto cleanup;
10760Sstevel@tonic-gate }
10770Sstevel@tonic-gate
10782881Smp153739 code = krb5_cc_store_cred(k5->ctx, k5->cc, &my_creds);
10792881Smp153739 if (code) {
10800Sstevel@tonic-gate com_err(progname, code, gettext("while storing credentials"));
10810Sstevel@tonic-gate goto cleanup;
10820Sstevel@tonic-gate }
10830Sstevel@tonic-gate
10840Sstevel@tonic-gate if (opts->action == RENEW) {
1085*7934SMark.Phalan@Sun.COM _kwarnd_del_warning(progname, opts->principal_name);
1086*7934SMark.Phalan@Sun.COM _kwarnd_add_warning(progname, opts->principal_name, my_creds.times.endtime);
10870Sstevel@tonic-gate } else if ((opts->action == INIT_KT) || (opts->action == INIT_PW)) {
1088*7934SMark.Phalan@Sun.COM _kwarnd_add_warning(progname, opts->principal_name, my_creds.times.endtime);
10890Sstevel@tonic-gate }
10900Sstevel@tonic-gate
10910Sstevel@tonic-gate notix = 0;
10920Sstevel@tonic-gate
10930Sstevel@tonic-gate cleanup:
1094*7934SMark.Phalan@Sun.COM if (options)
1095*7934SMark.Phalan@Sun.COM krb5_get_init_creds_opt_free(k5->ctx, options);
10960Sstevel@tonic-gate if (my_creds.client == k5->me) {
10970Sstevel@tonic-gate my_creds.client = 0;
10980Sstevel@tonic-gate }
1099*7934SMark.Phalan@Sun.COM if (opts->pa_opts) {
1100*7934SMark.Phalan@Sun.COM free(opts->pa_opts);
1101*7934SMark.Phalan@Sun.COM opts->pa_opts = NULL;
1102*7934SMark.Phalan@Sun.COM opts->num_pa_opts = 0;
1103*7934SMark.Phalan@Sun.COM }
11040Sstevel@tonic-gate krb5_free_cred_contents(k5->ctx, &my_creds);
11050Sstevel@tonic-gate if (keytab)
11060Sstevel@tonic-gate krb5_kt_close(k5->ctx, keytab);
11070Sstevel@tonic-gate return notix?0:1;
11080Sstevel@tonic-gate }
11090Sstevel@tonic-gate
11102881Smp153739 static int
k4_kinit(opts,k4,ctx)11110Sstevel@tonic-gate k4_kinit(opts, k4, ctx)
11120Sstevel@tonic-gate struct k_opts* opts;
11130Sstevel@tonic-gate struct k4_data* k4;
11140Sstevel@tonic-gate krb5_context ctx;
11150Sstevel@tonic-gate {
11160Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
11170Sstevel@tonic-gate char* progname = progname_v4;
11180Sstevel@tonic-gate int k_errno = 0;
11190Sstevel@tonic-gate #endif
11200Sstevel@tonic-gate
11210Sstevel@tonic-gate if (!got_k4)
11220Sstevel@tonic-gate return 0;
11230Sstevel@tonic-gate
11240Sstevel@tonic-gate if (opts->starttime)
11250Sstevel@tonic-gate return 0;
11260Sstevel@tonic-gate
11270Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
11280Sstevel@tonic-gate if (!k4->lifetime)
11290Sstevel@tonic-gate k4->lifetime = opts->lifetime;
11300Sstevel@tonic-gate if (!k4->lifetime)
11310Sstevel@tonic-gate k4->lifetime = KRB4_BACKUP_DEFAULT_LIFE_SECS;
11320Sstevel@tonic-gate
11332881Smp153739 k4->lifetime = krb_time_to_life(0, k4->lifetime);
11340Sstevel@tonic-gate
11350Sstevel@tonic-gate switch (opts->action)
11360Sstevel@tonic-gate {
11370Sstevel@tonic-gate case INIT_PW:
11380Sstevel@tonic-gate if (!got_password) {
11392881Smp153739 unsigned int pwsize = sizeof(stash_password);
11400Sstevel@tonic-gate krb5_error_code code;
11410Sstevel@tonic-gate char prompt[1024];
11420Sstevel@tonic-gate
11430Sstevel@tonic-gate sprintf(prompt, gettext("Password for %s: "), opts->principal_name);
11440Sstevel@tonic-gate stash_password[0] = 0;
11450Sstevel@tonic-gate /*
11460Sstevel@tonic-gate Note: krb5_read_password does not actually look at the
11470Sstevel@tonic-gate context, so we're ok even if we don't have a context. If
11480Sstevel@tonic-gate we cannot dynamically load krb5, we can substitute any
11490Sstevel@tonic-gate decent read password function instead of the krb5 one.
11500Sstevel@tonic-gate */
11510Sstevel@tonic-gate code = krb5_read_password(ctx, prompt, 0, stash_password, &pwsize);
11520Sstevel@tonic-gate if (code || pwsize == 0)
11530Sstevel@tonic-gate {
11540Sstevel@tonic-gate fprintf(stderr, gettext("Error while reading password for '%s'\n"),
11550Sstevel@tonic-gate opts->principal_name);
11560Sstevel@tonic-gate memset(stash_password, 0, sizeof(stash_password));
11570Sstevel@tonic-gate return 0;
11580Sstevel@tonic-gate }
11590Sstevel@tonic-gate got_password = 1;
11600Sstevel@tonic-gate }
11610Sstevel@tonic-gate k_errno = krb_get_pw_in_tkt(k4->aname, k4->inst, k4->realm, "krbtgt",
11620Sstevel@tonic-gate k4->realm, k4->lifetime, stash_password);
11630Sstevel@tonic-gate
11640Sstevel@tonic-gate if (k_errno) {
11650Sstevel@tonic-gate fprintf(stderr, "%s: %s\n", progname,
11660Sstevel@tonic-gate krb_get_err_text(k_errno));
11670Sstevel@tonic-gate if (authed_k5)
11682881Smp153739 fprintf(stderr, gettext("Maybe your KDC does not support v4. "
11690Sstevel@tonic-gate "Try the -5 option next time.\n"));
11700Sstevel@tonic-gate return 0;
11710Sstevel@tonic-gate }
11720Sstevel@tonic-gate return 1;
11730Sstevel@tonic-gate #ifndef HAVE_KRB524
11740Sstevel@tonic-gate case INIT_KT:
11750Sstevel@tonic-gate fprintf(stderr, gettext("%s: srvtabs are not supported\n"), progname);
11760Sstevel@tonic-gate return 0;
11770Sstevel@tonic-gate case RENEW:
11780Sstevel@tonic-gate fprintf(stderr, gettext("%s: renewal of krb4 tickets is not supported\n"),
11790Sstevel@tonic-gate progname);
11800Sstevel@tonic-gate return 0;
11812881Smp153739 #else
11822881Smp153739 /* These cases are handled by the 524 code - this prevents the compiler
11832881Smp153739 warnings of not using all the enumerated types.
11842881Smp153739 */
11852881Smp153739 case INIT_KT:
11862881Smp153739 case RENEW:
11872881Smp153739 case VALIDATE:
11882881Smp153739 return 0;
11890Sstevel@tonic-gate #endif
11900Sstevel@tonic-gate }
11910Sstevel@tonic-gate #endif
11920Sstevel@tonic-gate return 0;
11930Sstevel@tonic-gate }
11940Sstevel@tonic-gate
11952881Smp153739 static char*
getvprogname(v,progname)11962881Smp153739 getvprogname(v, progname)
11972881Smp153739 char *v, *progname;
11980Sstevel@tonic-gate {
11992881Smp153739 unsigned int len = strlen(progname) + 2 + strlen(v) + 2;
12000Sstevel@tonic-gate char *ret = malloc(len);
12010Sstevel@tonic-gate if (ret)
12020Sstevel@tonic-gate sprintf(ret, "%s(v%s)", progname, v);
12030Sstevel@tonic-gate else
12040Sstevel@tonic-gate ret = progname;
12050Sstevel@tonic-gate return ret;
12060Sstevel@tonic-gate }
12070Sstevel@tonic-gate
12080Sstevel@tonic-gate #ifdef HAVE_KRB524
12090Sstevel@tonic-gate /* Convert krb5 tickets to krb4. */
try_convert524(k5)12102881Smp153739 static int try_convert524(k5)
12110Sstevel@tonic-gate struct k5_data* k5;
12120Sstevel@tonic-gate {
12130Sstevel@tonic-gate char * progname = progname_v524;
12140Sstevel@tonic-gate krb5_error_code code = 0;
12150Sstevel@tonic-gate int icode = 0;
12160Sstevel@tonic-gate krb5_principal kpcserver = 0;
12170Sstevel@tonic-gate krb5_creds *v5creds = 0;
12180Sstevel@tonic-gate krb5_creds increds;
12190Sstevel@tonic-gate CREDENTIALS v4creds;
12200Sstevel@tonic-gate
12210Sstevel@tonic-gate if (!got_k4 || !got_k5)
12220Sstevel@tonic-gate return 0;
12230Sstevel@tonic-gate
12240Sstevel@tonic-gate memset((char *) &increds, 0, sizeof(increds));
12250Sstevel@tonic-gate /*
12260Sstevel@tonic-gate From this point on, we can goto cleanup because increds is
12270Sstevel@tonic-gate initialized.
12280Sstevel@tonic-gate */
12290Sstevel@tonic-gate
12300Sstevel@tonic-gate if ((code = krb5_build_principal(k5->ctx,
12310Sstevel@tonic-gate &kpcserver,
12320Sstevel@tonic-gate krb5_princ_realm(k5->ctx, k5->me)->length,
12330Sstevel@tonic-gate krb5_princ_realm(k5->ctx, k5->me)->data,
12340Sstevel@tonic-gate "krbtgt",
12350Sstevel@tonic-gate krb5_princ_realm(k5->ctx, k5->me)->data,
12360Sstevel@tonic-gate NULL))) {
12370Sstevel@tonic-gate com_err(progname, code, gettext(
12380Sstevel@tonic-gate "while creating service principal name"));
12390Sstevel@tonic-gate goto cleanup;
12400Sstevel@tonic-gate }
12410Sstevel@tonic-gate
12420Sstevel@tonic-gate increds.client = k5->me;
12430Sstevel@tonic-gate increds.server = kpcserver;
12440Sstevel@tonic-gate /* Prevent duplicate free calls. */
12450Sstevel@tonic-gate kpcserver = 0;
12460Sstevel@tonic-gate
12470Sstevel@tonic-gate increds.times.endtime = 0;
12480Sstevel@tonic-gate increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
12490Sstevel@tonic-gate if ((code = krb5_get_credentials(k5->ctx, 0,
12500Sstevel@tonic-gate k5->cc,
12510Sstevel@tonic-gate &increds,
12520Sstevel@tonic-gate &v5creds))) {
12530Sstevel@tonic-gate com_err(progname, code,
12540Sstevel@tonic-gate gettext("getting V5 credentials"));
12550Sstevel@tonic-gate goto cleanup;
12560Sstevel@tonic-gate }
12570Sstevel@tonic-gate if ((icode = krb524_convert_creds_kdc(k5->ctx,
12580Sstevel@tonic-gate v5creds,
12590Sstevel@tonic-gate &v4creds))) {
12600Sstevel@tonic-gate com_err(progname, icode,
12610Sstevel@tonic-gate gettext("converting to V4 credentials"));
12620Sstevel@tonic-gate goto cleanup;
12630Sstevel@tonic-gate }
12640Sstevel@tonic-gate /* this is stolen from the v4 kinit */
12650Sstevel@tonic-gate /* initialize ticket cache */
12660Sstevel@tonic-gate if ((icode = in_tkt(v4creds.pname, v4creds.pinst)
12670Sstevel@tonic-gate != KSUCCESS)) {
12680Sstevel@tonic-gate com_err(progname, icode, gettext(
12690Sstevel@tonic-gate "trying to create the V4 ticket file"));
12700Sstevel@tonic-gate goto cleanup;
12710Sstevel@tonic-gate }
12720Sstevel@tonic-gate /* stash ticket, session key, etc. for future use */
12730Sstevel@tonic-gate if ((icode = krb_save_credentials(v4creds.service,
12740Sstevel@tonic-gate v4creds.instance,
12750Sstevel@tonic-gate v4creds.realm,
12760Sstevel@tonic-gate v4creds.session,
12770Sstevel@tonic-gate v4creds.lifetime,
12780Sstevel@tonic-gate v4creds.kvno,
12790Sstevel@tonic-gate &(v4creds.ticket_st),
12800Sstevel@tonic-gate v4creds.issue_date))) {
12810Sstevel@tonic-gate com_err(progname, icode, gettext(
12820Sstevel@tonic-gate "trying to save the V4 ticket"));
12830Sstevel@tonic-gate goto cleanup;
12840Sstevel@tonic-gate }
12850Sstevel@tonic-gate
12860Sstevel@tonic-gate cleanup:
12870Sstevel@tonic-gate memset(&v4creds, 0, sizeof(v4creds));
12880Sstevel@tonic-gate if (v5creds)
12890Sstevel@tonic-gate krb5_free_creds(k5->ctx, v5creds);
12900Sstevel@tonic-gate increds.client = 0;
12910Sstevel@tonic-gate krb5_free_cred_contents(k5->ctx, &increds);
12920Sstevel@tonic-gate if (kpcserver)
12930Sstevel@tonic-gate krb5_free_principal(k5->ctx, kpcserver);
12940Sstevel@tonic-gate return !(code || icode);
12950Sstevel@tonic-gate }
12960Sstevel@tonic-gate #endif /* HAVE_KRB524 */
12970Sstevel@tonic-gate
12980Sstevel@tonic-gate int
main(argc,argv)12990Sstevel@tonic-gate main(argc, argv)
13000Sstevel@tonic-gate int argc;
13010Sstevel@tonic-gate char **argv;
13020Sstevel@tonic-gate {
13030Sstevel@tonic-gate struct k_opts opts;
13040Sstevel@tonic-gate struct k5_data k5;
13050Sstevel@tonic-gate struct k4_data k4;
1306*7934SMark.Phalan@Sun.COM char *progname;
13070Sstevel@tonic-gate
13080Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
13090Sstevel@tonic-gate
13100Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
13110Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST"
13120Sstevel@tonic-gate #endif
13130Sstevel@tonic-gate
13140Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
13150Sstevel@tonic-gate
13160Sstevel@tonic-gate progname = GET_PROGNAME(argv[0]);
13172881Smp153739 progname_v5 = getvprogname("5", progname);
13180Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
13192881Smp153739 progname_v4 = getvprogname("4", progname);
13202881Smp153739 progname_v524 = getvprogname("524", progname);
13210Sstevel@tonic-gate #endif
13220Sstevel@tonic-gate
13230Sstevel@tonic-gate /* Ensure we can be driven from a pipe */
13240Sstevel@tonic-gate if(!isatty(fileno(stdin)))
13250Sstevel@tonic-gate setvbuf(stdin, 0, _IONBF, 0);
13260Sstevel@tonic-gate if(!isatty(fileno(stdout)))
13270Sstevel@tonic-gate setvbuf(stdout, 0, _IONBF, 0);
13280Sstevel@tonic-gate if(!isatty(fileno(stderr)))
13290Sstevel@tonic-gate setvbuf(stderr, 0, _IONBF, 0);
13300Sstevel@tonic-gate
13310Sstevel@tonic-gate /*
13320Sstevel@tonic-gate This is where we would put in code to dynamically load Kerberos
13330Sstevel@tonic-gate libraries. Currenlty, we just get them implicitly.
13340Sstevel@tonic-gate */
13350Sstevel@tonic-gate got_k5 = 1;
13360Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
13370Sstevel@tonic-gate got_k4 = 1;
13380Sstevel@tonic-gate #endif
13390Sstevel@tonic-gate
13400Sstevel@tonic-gate memset(&opts, 0, sizeof(opts));
13410Sstevel@tonic-gate opts.action = INIT_PW;
13420Sstevel@tonic-gate
13430Sstevel@tonic-gate memset(&k5, 0, sizeof(k5));
13440Sstevel@tonic-gate memset(&k4, 0, sizeof(k4));
13450Sstevel@tonic-gate
1346*7934SMark.Phalan@Sun.COM set_com_err_hook (extended_com_err_fn);
1347*7934SMark.Phalan@Sun.COM
13482881Smp153739 parse_options(argc, argv, &opts, progname);
13490Sstevel@tonic-gate
13500Sstevel@tonic-gate got_k5 = k5_begin(&opts, &k5, &k4);
13510Sstevel@tonic-gate got_k4 = k4_begin(&opts, &k4);
13520Sstevel@tonic-gate
13530Sstevel@tonic-gate authed_k5 = k5_kinit(&opts, &k5);
13540Sstevel@tonic-gate #ifdef HAVE_KRB524
13550Sstevel@tonic-gate if (authed_k5)
13560Sstevel@tonic-gate authed_k4 = try_convert524(&k5);
13570Sstevel@tonic-gate #endif
13580Sstevel@tonic-gate if (!authed_k4)
13590Sstevel@tonic-gate authed_k4 = k4_kinit(&opts, &k4, k5.ctx);
13600Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
13610Sstevel@tonic-gate memset(stash_password, 0, sizeof(stash_password));
13620Sstevel@tonic-gate #endif
13630Sstevel@tonic-gate
13640Sstevel@tonic-gate if (authed_k5 && opts.verbose)
13650Sstevel@tonic-gate fprintf(stderr, gettext("Authenticated to Kerberos v5\n"));
13660Sstevel@tonic-gate if (authed_k4 && opts.verbose)
13670Sstevel@tonic-gate fprintf(stderr, gettext("Authenticated to Kerberos v4\n"));
13680Sstevel@tonic-gate
13690Sstevel@tonic-gate k5_end(&k5);
13700Sstevel@tonic-gate k4_end(&k4);
13710Sstevel@tonic-gate
13722881Smp153739 if ((got_k5 && !authed_k5) || (got_k4 && !authed_k4) ||
13732881Smp153739 (!got_k5 && !got_k4))
13740Sstevel@tonic-gate exit(1);
13750Sstevel@tonic-gate return 0;
13760Sstevel@tonic-gate }
13770Sstevel@tonic-gate
13780Sstevel@tonic-gate static void
_kwarnd_add_warning(char * progname,char * me,time_t endtime)1379*7934SMark.Phalan@Sun.COM _kwarnd_add_warning(char *progname, char *me, time_t endtime)
13800Sstevel@tonic-gate {
13810Sstevel@tonic-gate if (kwarn_add_warning(me, endtime) != 0)
13820Sstevel@tonic-gate fprintf(stderr, gettext(
13830Sstevel@tonic-gate "%s: no ktkt_warnd warning possible\n"), progname);
13840Sstevel@tonic-gate return;
13850Sstevel@tonic-gate }
13860Sstevel@tonic-gate
13870Sstevel@tonic-gate
13880Sstevel@tonic-gate static void
_kwarnd_del_warning(char * progname,char * me)1389*7934SMark.Phalan@Sun.COM _kwarnd_del_warning(char *progname, char *me)
13900Sstevel@tonic-gate {
13910Sstevel@tonic-gate if (kwarn_del_warning(me) != 0)
13920Sstevel@tonic-gate fprintf(stderr, gettext(
13930Sstevel@tonic-gate "%s: unable to delete ktkt_warnd message for %s\n"),
13940Sstevel@tonic-gate progname, me);
13950Sstevel@tonic-gate return;
13960Sstevel@tonic-gate }
1397