xref: /titanic_53/usr/src/cmd/krb5/kinit/kinit.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
3*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
4*7c478bd9Sstevel@tonic-gate  */
5*7c478bd9Sstevel@tonic-gate 
6*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
7*7c478bd9Sstevel@tonic-gate 
8*7c478bd9Sstevel@tonic-gate /*
9*7c478bd9Sstevel@tonic-gate  * clients/kinit/kinit.c
10*7c478bd9Sstevel@tonic-gate  *
11*7c478bd9Sstevel@tonic-gate  * Copyright 1990 by the Massachusetts Institute of Technology.
12*7c478bd9Sstevel@tonic-gate  * All Rights Reserved.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may
15*7c478bd9Sstevel@tonic-gate  *   require a specific license from the United States Government.
16*7c478bd9Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
17*7c478bd9Sstevel@tonic-gate  *   export to obtain such a license before exporting.
18*7c478bd9Sstevel@tonic-gate  *
19*7c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
20*7c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
21*7c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
22*7c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
23*7c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
24*7c478bd9Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
25*7c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
26*7c478bd9Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
27*7c478bd9Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
28*7c478bd9Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
29*7c478bd9Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
30*7c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
31*7c478bd9Sstevel@tonic-gate  * or implied warranty.
32*7c478bd9Sstevel@tonic-gate  *
33*7c478bd9Sstevel@tonic-gate  *
34*7c478bd9Sstevel@tonic-gate  * Initialize a credentials cache.
35*7c478bd9Sstevel@tonic-gate  */
36*7c478bd9Sstevel@tonic-gate #include <k5-int.h>
37*7c478bd9Sstevel@tonic-gate #include <profile/prof_int.h>
38*7c478bd9Sstevel@tonic-gate #include <com_err.h>
39*7c478bd9Sstevel@tonic-gate #include <libintl.h>
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate #include <krb5.h>
42*7c478bd9Sstevel@tonic-gate 
43*7c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
44*7c478bd9Sstevel@tonic-gate #include <kerberosIV/krb.h>
45*7c478bd9Sstevel@tonic-gate #define HAVE_KRB524
46*7c478bd9Sstevel@tonic-gate #else
47*7c478bd9Sstevel@tonic-gate #undef HAVE_KRB524
48*7c478bd9Sstevel@tonic-gate #endif /* KRB5_KRB4_COMPAT */
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate #include <string.h>
51*7c478bd9Sstevel@tonic-gate #include <stdio.h>
52*7c478bd9Sstevel@tonic-gate #include <time.h>
53*7c478bd9Sstevel@tonic-gate #include <netdb.h>
54*7c478bd9Sstevel@tonic-gate #include <locale.h>
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate #ifdef GETOPT_LONG
57*7c478bd9Sstevel@tonic-gate #include <getopt.h>
58*7c478bd9Sstevel@tonic-gate #else /* GETOPT_LONG */
59*7c478bd9Sstevel@tonic-gate #ifdef HAVE_UNISTD_H
60*7c478bd9Sstevel@tonic-gate #include <unistd.h>
61*7c478bd9Sstevel@tonic-gate #else /* HAVE_UNISTD_H */
62*7c478bd9Sstevel@tonic-gate extern int optind;
63*7c478bd9Sstevel@tonic-gate extern char *optarg;
64*7c478bd9Sstevel@tonic-gate extern int getopt();
65*7c478bd9Sstevel@tonic-gate #endif /* HAVE_UNISTD_H */
66*7c478bd9Sstevel@tonic-gate #endif /* GETOPT_LONG */
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate #ifndef _WIN32
69*7c478bd9Sstevel@tonic-gate #define GET_PROGNAME(x) (strrchr((x), '/') ? strrchr((x), '/')+1 : (x))
70*7c478bd9Sstevel@tonic-gate #else /* _WIN32 */
71*7c478bd9Sstevel@tonic-gate #define GET_PROGNAME(x) max(max(strrchr((x), '/'), strrchr((x), '\\')) + 1,(x))
72*7c478bd9Sstevel@tonic-gate #endif /* _WIN32 */
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate #ifdef HAVE_PWD_H
75*7c478bd9Sstevel@tonic-gate #include <pwd.h>
76*7c478bd9Sstevel@tonic-gate char * get_name_from_os()
77*7c478bd9Sstevel@tonic-gate {
78*7c478bd9Sstevel@tonic-gate     struct passwd *pw;
79*7c478bd9Sstevel@tonic-gate     if (pw = getpwuid((int) getuid()))
80*7c478bd9Sstevel@tonic-gate 	return pw->pw_name;
81*7c478bd9Sstevel@tonic-gate     return 0;
82*7c478bd9Sstevel@tonic-gate }
83*7c478bd9Sstevel@tonic-gate #else /* HAVE_PWD_H */
84*7c478bd9Sstevel@tonic-gate #ifdef _WIN32
85*7c478bd9Sstevel@tonic-gate char * get_name_from_os()
86*7c478bd9Sstevel@tonic-gate {
87*7c478bd9Sstevel@tonic-gate     static char name[1024];
88*7c478bd9Sstevel@tonic-gate     DWORD name_size = sizeof(name);
89*7c478bd9Sstevel@tonic-gate     if (GetUserName(name, &name_size)) {
90*7c478bd9Sstevel@tonic-gate 	name[sizeof(name)-1] = 0; /* Just to be extra safe */
91*7c478bd9Sstevel@tonic-gate 	return name;
92*7c478bd9Sstevel@tonic-gate     } else {
93*7c478bd9Sstevel@tonic-gate 	return 0;
94*7c478bd9Sstevel@tonic-gate     }
95*7c478bd9Sstevel@tonic-gate }
96*7c478bd9Sstevel@tonic-gate #else /* _WIN32 */
97*7c478bd9Sstevel@tonic-gate char * get_name_from_os()
98*7c478bd9Sstevel@tonic-gate {
99*7c478bd9Sstevel@tonic-gate     return 0;
100*7c478bd9Sstevel@tonic-gate }
101*7c478bd9Sstevel@tonic-gate #endif /* _WIN32 */
102*7c478bd9Sstevel@tonic-gate #endif /* HAVE_PWD_H */
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate static char *progname;
105*7c478bd9Sstevel@tonic-gate 
106*7c478bd9Sstevel@tonic-gate static char* progname_v5 = 0;
107*7c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
108*7c478bd9Sstevel@tonic-gate static char* progname_v4 = 0;
109*7c478bd9Sstevel@tonic-gate static char* progname_v524 = 0;
110*7c478bd9Sstevel@tonic-gate #endif /* KRB5_KRB4_COMPAT */
111*7c478bd9Sstevel@tonic-gate #include <locale.h>
112*7c478bd9Sstevel@tonic-gate 
113*7c478bd9Sstevel@tonic-gate static int got_k5 = 0;
114*7c478bd9Sstevel@tonic-gate static int got_k4 = 0;
115*7c478bd9Sstevel@tonic-gate 
116*7c478bd9Sstevel@tonic-gate static int default_k5 = 1;
117*7c478bd9Sstevel@tonic-gate #if defined(KRB5_KRB4_COMPAT) && defined(KINIT_DEFAULT_BOTH)
118*7c478bd9Sstevel@tonic-gate static int default_k4 = 1;
119*7c478bd9Sstevel@tonic-gate #else /* KRB5_KRB4_COMPAT && KINIT_DEFAULT_BOTH */
120*7c478bd9Sstevel@tonic-gate static int default_k4 = 0;
121*7c478bd9Sstevel@tonic-gate #endif /* KRB5_KRB4_COMPAT && KINIT_DEFAULT_BOTH */
122*7c478bd9Sstevel@tonic-gate 
123*7c478bd9Sstevel@tonic-gate static int authed_k5 = 0;
124*7c478bd9Sstevel@tonic-gate static int authed_k4 = 0;
125*7c478bd9Sstevel@tonic-gate 
126*7c478bd9Sstevel@tonic-gate #define KRB4_BACKUP_DEFAULT_LIFE_SECS 10*60*60 /* 10 hours */
127*7c478bd9Sstevel@tonic-gate #define	ROOT_UNAME	"root"
128*7c478bd9Sstevel@tonic-gate 
129*7c478bd9Sstevel@tonic-gate typedef enum { INIT_PW, INIT_KT, RENEW, VALIDATE } action_type;
130*7c478bd9Sstevel@tonic-gate 
131*7c478bd9Sstevel@tonic-gate struct k_opts
132*7c478bd9Sstevel@tonic-gate {
133*7c478bd9Sstevel@tonic-gate     /* in seconds */
134*7c478bd9Sstevel@tonic-gate     krb5_deltat starttime;
135*7c478bd9Sstevel@tonic-gate     krb5_deltat lifetime;
136*7c478bd9Sstevel@tonic-gate     krb5_deltat rlife;
137*7c478bd9Sstevel@tonic-gate 
138*7c478bd9Sstevel@tonic-gate     int forwardable;
139*7c478bd9Sstevel@tonic-gate     int proxiable;
140*7c478bd9Sstevel@tonic-gate     int addresses;
141*7c478bd9Sstevel@tonic-gate 
142*7c478bd9Sstevel@tonic-gate     int not_forwardable;
143*7c478bd9Sstevel@tonic-gate     int not_proxiable;
144*7c478bd9Sstevel@tonic-gate     int no_addresses;
145*7c478bd9Sstevel@tonic-gate 
146*7c478bd9Sstevel@tonic-gate     int verbose;
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate     char* principal_name;
149*7c478bd9Sstevel@tonic-gate     char* service_name;
150*7c478bd9Sstevel@tonic-gate     char* keytab_name;
151*7c478bd9Sstevel@tonic-gate     char* k5_cache_name;
152*7c478bd9Sstevel@tonic-gate     char* k4_cache_name;
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate     action_type action;
155*7c478bd9Sstevel@tonic-gate };
156*7c478bd9Sstevel@tonic-gate 
157*7c478bd9Sstevel@tonic-gate int	forwardable_flag = 0;
158*7c478bd9Sstevel@tonic-gate int	renewable_flag = 0;
159*7c478bd9Sstevel@tonic-gate int	proxiable_flag = 0;
160*7c478bd9Sstevel@tonic-gate int	no_address_flag = 0;
161*7c478bd9Sstevel@tonic-gate profile_options_boolean	config_option[] = {
162*7c478bd9Sstevel@tonic-gate 	{ "forwardable",	&forwardable_flag,	0 },
163*7c478bd9Sstevel@tonic-gate 	{ "renewable",		&renewable_flag,	0 },
164*7c478bd9Sstevel@tonic-gate 	{ "proxiable",		&proxiable_flag,	0 },
165*7c478bd9Sstevel@tonic-gate 	{ "no_addresses",	&no_address_flag,	0 },
166*7c478bd9Sstevel@tonic-gate 	{ NULL,			NULL,			0 }
167*7c478bd9Sstevel@tonic-gate };
168*7c478bd9Sstevel@tonic-gate 
169*7c478bd9Sstevel@tonic-gate char	*renew_timeval=NULL;
170*7c478bd9Sstevel@tonic-gate char	*life_timeval=NULL;
171*7c478bd9Sstevel@tonic-gate int	lifetime_specified;
172*7c478bd9Sstevel@tonic-gate int	renewtime_specified;
173*7c478bd9Sstevel@tonic-gate profile_option_strings	config_times[] = {
174*7c478bd9Sstevel@tonic-gate 	{ "max_life",		&life_timeval,	0 },
175*7c478bd9Sstevel@tonic-gate 	{ "max_renewable_life",	&renew_timeval,	0 },
176*7c478bd9Sstevel@tonic-gate 	{ NULL,			NULL,		0 }
177*7c478bd9Sstevel@tonic-gate };
178*7c478bd9Sstevel@tonic-gate 
179*7c478bd9Sstevel@tonic-gate struct k5_data
180*7c478bd9Sstevel@tonic-gate {
181*7c478bd9Sstevel@tonic-gate     krb5_context ctx;
182*7c478bd9Sstevel@tonic-gate     krb5_ccache cc;
183*7c478bd9Sstevel@tonic-gate     krb5_principal me;
184*7c478bd9Sstevel@tonic-gate     char* name;
185*7c478bd9Sstevel@tonic-gate };
186*7c478bd9Sstevel@tonic-gate 
187*7c478bd9Sstevel@tonic-gate struct k4_data
188*7c478bd9Sstevel@tonic-gate {
189*7c478bd9Sstevel@tonic-gate     krb5_deltat lifetime;
190*7c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
191*7c478bd9Sstevel@tonic-gate     char aname[ANAME_SZ + 1];
192*7c478bd9Sstevel@tonic-gate     char inst[INST_SZ + 1];
193*7c478bd9Sstevel@tonic-gate     char realm[REALM_SZ + 1];
194*7c478bd9Sstevel@tonic-gate     char name[ANAME_SZ + 1 + INST_SZ + 1 + REALM_SZ + 1];
195*7c478bd9Sstevel@tonic-gate #endif /*KRB5_KRB4_COMPAT */
196*7c478bd9Sstevel@tonic-gate };
197*7c478bd9Sstevel@tonic-gate 
198*7c478bd9Sstevel@tonic-gate char	*realmdef[] = { "realms", NULL, "kinit", NULL };
199*7c478bd9Sstevel@tonic-gate char	*appdef[] = { "appdefaults", "kinit", NULL };
200*7c478bd9Sstevel@tonic-gate 
201*7c478bd9Sstevel@tonic-gate #define	krb_realm		(*(realmdef + 1))
202*7c478bd9Sstevel@tonic-gate 
203*7c478bd9Sstevel@tonic-gate #define	lifetime_specified	config_times[0].found
204*7c478bd9Sstevel@tonic-gate #define	renewtime_specified	config_times[1].found
205*7c478bd9Sstevel@tonic-gate 
206*7c478bd9Sstevel@tonic-gate /*
207*7c478bd9Sstevel@tonic-gate  * Try no preauthentication first; then try the encrypted timestamp
208*7c478bd9Sstevel@tonic-gate  */
209*7c478bd9Sstevel@tonic-gate krb5_preauthtype * preauth = NULL;
210*7c478bd9Sstevel@tonic-gate krb5_preauthtype preauth_list[2] = { 0, -1 };
211*7c478bd9Sstevel@tonic-gate 
212*7c478bd9Sstevel@tonic-gate static void _kwarnd_add_warning(char *, time_t);
213*7c478bd9Sstevel@tonic-gate static void _kwarnd_del_warning(char *);
214*7c478bd9Sstevel@tonic-gate 
215*7c478bd9Sstevel@tonic-gate #ifdef GETOPT_LONG
216*7c478bd9Sstevel@tonic-gate /* if struct[2] == NULL, then long_getopt acts as if the short flag
217*7c478bd9Sstevel@tonic-gate    struct[3] was specified.  If struct[2] != NULL, then struct[3] is
218*7c478bd9Sstevel@tonic-gate    stored in *(struct[2]), the array index which was specified is
219*7c478bd9Sstevel@tonic-gate    stored in *index, and long_getopt() returns 0. */
220*7c478bd9Sstevel@tonic-gate 
221*7c478bd9Sstevel@tonic-gate struct option long_options[] = {
222*7c478bd9Sstevel@tonic-gate     { "noforwardable", 0, NULL, 'F' },
223*7c478bd9Sstevel@tonic-gate     { "noproxiable", 0, NULL, 'P' },
224*7c478bd9Sstevel@tonic-gate     { "addresses", 0, NULL, 'a'},
225*7c478bd9Sstevel@tonic-gate     { "forwardable", 0, NULL, 'f' },
226*7c478bd9Sstevel@tonic-gate     { "proxiable", 0, NULL, 'p' },
227*7c478bd9Sstevel@tonic-gate     { "noaddresses", 0, NULL, 'A' },
228*7c478bd9Sstevel@tonic-gate     { NULL, 0, NULL, 0 }
229*7c478bd9Sstevel@tonic-gate };
230*7c478bd9Sstevel@tonic-gate 
231*7c478bd9Sstevel@tonic-gate #define GETOPT(argc, argv, str) getopt_long(argc, argv, str, long_options, 0)
232*7c478bd9Sstevel@tonic-gate #else /* GETOPT_LONG */
233*7c478bd9Sstevel@tonic-gate #define GETOPT(argc, argv, str) getopt(argc, argv, str)
234*7c478bd9Sstevel@tonic-gate #endif /* GETOPT_LONG */
235*7c478bd9Sstevel@tonic-gate 
236*7c478bd9Sstevel@tonic-gate /* Save the program name for the error messages */
237*7c478bd9Sstevel@tonic-gate static char *progname;
238*7c478bd9Sstevel@tonic-gate 
239*7c478bd9Sstevel@tonic-gate void
240*7c478bd9Sstevel@tonic-gate usage(void)
241*7c478bd9Sstevel@tonic-gate {
242*7c478bd9Sstevel@tonic-gate #define USAGE_BREAK "\n\t"
243*7c478bd9Sstevel@tonic-gate #ifdef GETOPT_LONG
244*7c478bd9Sstevel@tonic-gate #define USAGE_LONG_FORWARDABLE " | --forwardable | --noforwardable"
245*7c478bd9Sstevel@tonic-gate #define USAGE_LONG_PROXIABLE   " | --proxiable | --noproxiable"
246*7c478bd9Sstevel@tonic-gate #define USAGE_LONG_ADDRESSES   " | --addresses | --noaddresses"
247*7c478bd9Sstevel@tonic-gate #define USAGE_BREAK_LONG       USAGE_BREAK
248*7c478bd9Sstevel@tonic-gate #else /* GETOPT_LONG */
249*7c478bd9Sstevel@tonic-gate #define USAGE_LONG_FORWARDABLE ""
250*7c478bd9Sstevel@tonic-gate #define USAGE_LONG_PROXIABLE   ""
251*7c478bd9Sstevel@tonic-gate #define USAGE_LONG_ADDRESSES   ""
252*7c478bd9Sstevel@tonic-gate #define USAGE_BREAK_LONG       ""
253*7c478bd9Sstevel@tonic-gate #endif /* GETOPT_LONG */
254*7c478bd9Sstevel@tonic-gate 
255*7c478bd9Sstevel@tonic-gate     fprintf(stderr, "%s : %s  [-V] "
256*7c478bd9Sstevel@tonic-gate 	    "[-l lifetime] [-s start_time] "
257*7c478bd9Sstevel@tonic-gate 	    USAGE_BREAK
258*7c478bd9Sstevel@tonic-gate 	    "[-r renewable_life] "
259*7c478bd9Sstevel@tonic-gate 	    "[-f | -F" USAGE_LONG_FORWARDABLE "] "
260*7c478bd9Sstevel@tonic-gate 	    USAGE_BREAK_LONG
261*7c478bd9Sstevel@tonic-gate 	    "[-p | -P" USAGE_LONG_PROXIABLE "] "
262*7c478bd9Sstevel@tonic-gate 	    USAGE_BREAK_LONG
263*7c478bd9Sstevel@tonic-gate 	    "[-A" USAGE_LONG_ADDRESSES "] "
264*7c478bd9Sstevel@tonic-gate 	    USAGE_BREAK
265*7c478bd9Sstevel@tonic-gate 	    "[-v] [-R] "
266*7c478bd9Sstevel@tonic-gate 	    "[-k [-t keytab_file]] "
267*7c478bd9Sstevel@tonic-gate 	    USAGE_BREAK
268*7c478bd9Sstevel@tonic-gate 	    "[-c cachename] "
269*7c478bd9Sstevel@tonic-gate 	    "[-S service_name] [principal]"
270*7c478bd9Sstevel@tonic-gate 	    "\n\n",
271*7c478bd9Sstevel@tonic-gate 	    gettext("Usage"), progname);
272*7c478bd9Sstevel@tonic-gate 
273*7c478bd9Sstevel@tonic-gate #define KRB_AVAIL_STRING(x) ((x)?gettext("available"):gettext("not available"))
274*7c478bd9Sstevel@tonic-gate 
275*7c478bd9Sstevel@tonic-gate #define OPTTYPE_KRB5   "5"
276*7c478bd9Sstevel@tonic-gate #define OPTTYPE_KRB4   "4"
277*7c478bd9Sstevel@tonic-gate #define OPTTYPE_EITHER "Either 4 or 5"
278*7c478bd9Sstevel@tonic-gate #ifdef HAVE_KRB524
279*7c478bd9Sstevel@tonic-gate #define OPTTYPE_BOTH "5, or both 5 and 4"
280*7c478bd9Sstevel@tonic-gate #else
281*7c478bd9Sstevel@tonic-gate #define OPTTYPE_BOTH "5"
282*7c478bd9Sstevel@tonic-gate #endif
283*7c478bd9Sstevel@tonic-gate 
284*7c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
285*7c478bd9Sstevel@tonic-gate #define USAGE_OPT_FMT "%s%-50s%s\n"
286*7c478bd9Sstevel@tonic-gate #else
287*7c478bd9Sstevel@tonic-gate #define USAGE_OPT_FMT "%s%s\n"
288*7c478bd9Sstevel@tonic-gate #endif
289*7c478bd9Sstevel@tonic-gate 
290*7c478bd9Sstevel@tonic-gate #define ULINE(indent, col1, col2) \
291*7c478bd9Sstevel@tonic-gate fprintf(stderr, USAGE_OPT_FMT, indent, col1, col2)
292*7c478bd9Sstevel@tonic-gate 
293*7c478bd9Sstevel@tonic-gate     ULINE("    ", "options:", "valid with Kerberos:");
294*7c478bd9Sstevel@tonic-gate     fprintf(stderr, "\t-5 Kerberos 5 (%s)\n", KRB_AVAIL_STRING(got_k5));
295*7c478bd9Sstevel@tonic-gate     fprintf(stderr, "\t-4 Kerberos 4 (%s)\n", KRB_AVAIL_STRING(got_k4));
296*7c478bd9Sstevel@tonic-gate     fprintf(stderr, "\t   (Default behavior is to try %s%s%s%s)\n",
297*7c478bd9Sstevel@tonic-gate 	    default_k5?"Kerberos 5":"",
298*7c478bd9Sstevel@tonic-gate 	    (default_k5 && default_k4)?gettext(" and "):"",
299*7c478bd9Sstevel@tonic-gate 	    default_k4?"Kerberos 4":"",
300*7c478bd9Sstevel@tonic-gate 	    (!default_k5 && !default_k4)?gettext("neither"):"");
301*7c478bd9Sstevel@tonic-gate     ULINE("\t", gettext("-V verbose"),                   OPTTYPE_EITHER);
302*7c478bd9Sstevel@tonic-gate     ULINE("\t", gettext("-l lifetime"),                  OPTTYPE_EITHER);
303*7c478bd9Sstevel@tonic-gate     ULINE("\t", gettext("-s start time"),                OPTTYPE_KRB5);
304*7c478bd9Sstevel@tonic-gate     ULINE("\t", gettext("-r renewable lifetime"),        OPTTYPE_KRB5);
305*7c478bd9Sstevel@tonic-gate     ULINE("\t", gettext("-f forwardable"),               OPTTYPE_KRB5);
306*7c478bd9Sstevel@tonic-gate     ULINE("\t", gettext("-F not forwardable"),           OPTTYPE_KRB5);
307*7c478bd9Sstevel@tonic-gate     ULINE("\t", gettext("-p proxiable"),                 OPTTYPE_KRB5);
308*7c478bd9Sstevel@tonic-gate     ULINE("\t", gettext("-P not proxiable"),             OPTTYPE_KRB5);
309*7c478bd9Sstevel@tonic-gate     ULINE("\t", gettext("-A do not include addresses"),  OPTTYPE_KRB5);
310*7c478bd9Sstevel@tonic-gate     ULINE("\t", gettext("-v validate"),                  OPTTYPE_KRB5);
311*7c478bd9Sstevel@tonic-gate     ULINE("\t", gettext("-R renew"),                     OPTTYPE_BOTH);
312*7c478bd9Sstevel@tonic-gate     ULINE("\t", gettext("-k use keytab"),                OPTTYPE_BOTH);
313*7c478bd9Sstevel@tonic-gate     ULINE("\t", gettext("-t filename of keytab to use"), OPTTYPE_BOTH);
314*7c478bd9Sstevel@tonic-gate     ULINE("\t", gettext("-c Kerberos 5 cache name"),     OPTTYPE_KRB5);
315*7c478bd9Sstevel@tonic-gate     /* This options is not yet available: */
316*7c478bd9Sstevel@tonic-gate     /* ULINE("\t", "-C Kerberos 4 cache name",     OPTTYPE_KRB4); */
317*7c478bd9Sstevel@tonic-gate     ULINE("\t", gettext("-S service"),                   OPTTYPE_BOTH);
318*7c478bd9Sstevel@tonic-gate     exit(2);
319*7c478bd9Sstevel@tonic-gate }
320*7c478bd9Sstevel@tonic-gate 
321*7c478bd9Sstevel@tonic-gate char *
322*7c478bd9Sstevel@tonic-gate parse_options(argc, argv, opts)
323*7c478bd9Sstevel@tonic-gate     int argc;
324*7c478bd9Sstevel@tonic-gate     char **argv;
325*7c478bd9Sstevel@tonic-gate     struct k_opts* opts;
326*7c478bd9Sstevel@tonic-gate {
327*7c478bd9Sstevel@tonic-gate     krb5_error_code code;
328*7c478bd9Sstevel@tonic-gate     int errflg = 0;
329*7c478bd9Sstevel@tonic-gate     int use_k4 = 0;
330*7c478bd9Sstevel@tonic-gate     int use_k5 = 0;
331*7c478bd9Sstevel@tonic-gate     int i;
332*7c478bd9Sstevel@tonic-gate 
333*7c478bd9Sstevel@tonic-gate     while ((i = GETOPT(argc, argv, "r:fpFP54AVl:s:c:kt:RS:v"))
334*7c478bd9Sstevel@tonic-gate 	   != -1) {
335*7c478bd9Sstevel@tonic-gate 	switch (i) {
336*7c478bd9Sstevel@tonic-gate 	case 'V':
337*7c478bd9Sstevel@tonic-gate 	    opts->verbose = 1;
338*7c478bd9Sstevel@tonic-gate 	    break;
339*7c478bd9Sstevel@tonic-gate 	case 'l':
340*7c478bd9Sstevel@tonic-gate 	    /* Lifetime */
341*7c478bd9Sstevel@tonic-gate 	    code = krb5_string_to_deltat(optarg, &opts->lifetime);
342*7c478bd9Sstevel@tonic-gate 	    if (code != 0 || opts->lifetime == 0) {
343*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, gettext("Bad lifetime value %s\n"), optarg);
344*7c478bd9Sstevel@tonic-gate 		errflg++;
345*7c478bd9Sstevel@tonic-gate 	    }
346*7c478bd9Sstevel@tonic-gate 	    break;
347*7c478bd9Sstevel@tonic-gate 	case 'r':
348*7c478bd9Sstevel@tonic-gate 	    /* Renewable Time */
349*7c478bd9Sstevel@tonic-gate 	    code = krb5_string_to_deltat(optarg, &opts->rlife);
350*7c478bd9Sstevel@tonic-gate 	    if (code != 0 || opts->rlife == 0) {
351*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, gettext("Bad lifetime value %s\n"), optarg);
352*7c478bd9Sstevel@tonic-gate 		errflg++;
353*7c478bd9Sstevel@tonic-gate 	    }
354*7c478bd9Sstevel@tonic-gate 	    break;
355*7c478bd9Sstevel@tonic-gate 	case 'f':
356*7c478bd9Sstevel@tonic-gate 	    opts->forwardable = 1;
357*7c478bd9Sstevel@tonic-gate 	    break;
358*7c478bd9Sstevel@tonic-gate 	case 'F':
359*7c478bd9Sstevel@tonic-gate 	    opts->not_forwardable = 1;
360*7c478bd9Sstevel@tonic-gate 	    break;
361*7c478bd9Sstevel@tonic-gate 	case 'p':
362*7c478bd9Sstevel@tonic-gate 	    opts->proxiable = 1;
363*7c478bd9Sstevel@tonic-gate 	    break;
364*7c478bd9Sstevel@tonic-gate 	case 'P':
365*7c478bd9Sstevel@tonic-gate 	    opts->not_proxiable = 1;
366*7c478bd9Sstevel@tonic-gate 	    break;
367*7c478bd9Sstevel@tonic-gate 	case 'a':
368*7c478bd9Sstevel@tonic-gate 	    /* Note: This is supported only with GETOPT_LONG */
369*7c478bd9Sstevel@tonic-gate 	    opts->addresses = 1;
370*7c478bd9Sstevel@tonic-gate 	    break;
371*7c478bd9Sstevel@tonic-gate 	case 'A':
372*7c478bd9Sstevel@tonic-gate 	    opts->no_addresses = 1;
373*7c478bd9Sstevel@tonic-gate 	    break;
374*7c478bd9Sstevel@tonic-gate        	case 's':
375*7c478bd9Sstevel@tonic-gate 	    code = krb5_string_to_deltat(optarg, &opts->starttime);
376*7c478bd9Sstevel@tonic-gate 	    if (code != 0 || opts->starttime == 0) {
377*7c478bd9Sstevel@tonic-gate 		krb5_timestamp abs_starttime;
378*7c478bd9Sstevel@tonic-gate 
379*7c478bd9Sstevel@tonic-gate 		code = krb5_string_to_timestamp(optarg, &abs_starttime);
380*7c478bd9Sstevel@tonic-gate 		if (code != 0 || abs_starttime == 0) {
381*7c478bd9Sstevel@tonic-gate 		    fprintf(stderr, gettext("Bad start time value %s\n"), optarg);
382*7c478bd9Sstevel@tonic-gate 		    errflg++;
383*7c478bd9Sstevel@tonic-gate 		} else {
384*7c478bd9Sstevel@tonic-gate 		    opts->starttime = abs_starttime - time(0);
385*7c478bd9Sstevel@tonic-gate 		}
386*7c478bd9Sstevel@tonic-gate 	    }
387*7c478bd9Sstevel@tonic-gate 	    break;
388*7c478bd9Sstevel@tonic-gate 	case 'S':
389*7c478bd9Sstevel@tonic-gate 	    opts->service_name = optarg;
390*7c478bd9Sstevel@tonic-gate 	    break;
391*7c478bd9Sstevel@tonic-gate 	case 'k':
392*7c478bd9Sstevel@tonic-gate 	    opts->action = INIT_KT;
393*7c478bd9Sstevel@tonic-gate 	    break;
394*7c478bd9Sstevel@tonic-gate 	case 't':
395*7c478bd9Sstevel@tonic-gate 	    if (opts->keytab_name)
396*7c478bd9Sstevel@tonic-gate 	    {
397*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, gettext("Only one -t option allowed.\n"));
398*7c478bd9Sstevel@tonic-gate 		errflg++;
399*7c478bd9Sstevel@tonic-gate 	    } else {
400*7c478bd9Sstevel@tonic-gate 		opts->keytab_name = optarg;
401*7c478bd9Sstevel@tonic-gate 	    }
402*7c478bd9Sstevel@tonic-gate 	    break;
403*7c478bd9Sstevel@tonic-gate 	case 'R':
404*7c478bd9Sstevel@tonic-gate 	    opts->action = RENEW;
405*7c478bd9Sstevel@tonic-gate 	    break;
406*7c478bd9Sstevel@tonic-gate 	case 'v':
407*7c478bd9Sstevel@tonic-gate 	    opts->action = VALIDATE;
408*7c478bd9Sstevel@tonic-gate 	    break;
409*7c478bd9Sstevel@tonic-gate        	case 'c':
410*7c478bd9Sstevel@tonic-gate 	    if (opts->k5_cache_name)
411*7c478bd9Sstevel@tonic-gate 	    {
412*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, gettext("Only one -c option allowed\n"));
413*7c478bd9Sstevel@tonic-gate 		errflg++;
414*7c478bd9Sstevel@tonic-gate 	    } else {
415*7c478bd9Sstevel@tonic-gate 		opts->k5_cache_name = optarg;
416*7c478bd9Sstevel@tonic-gate 	    }
417*7c478bd9Sstevel@tonic-gate 	    break;
418*7c478bd9Sstevel@tonic-gate #if 0
419*7c478bd9Sstevel@tonic-gate 	    /*
420*7c478bd9Sstevel@tonic-gate 	      A little more work is needed before we can enable this
421*7c478bd9Sstevel@tonic-gate 	      option.
422*7c478bd9Sstevel@tonic-gate 	    */
423*7c478bd9Sstevel@tonic-gate 	case 'C':
424*7c478bd9Sstevel@tonic-gate 	    if (opts->k4_cache_name)
425*7c478bd9Sstevel@tonic-gate 	    {
426*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "Only one -C option allowed\n");
427*7c478bd9Sstevel@tonic-gate 		errflg++;
428*7c478bd9Sstevel@tonic-gate 	    } else {
429*7c478bd9Sstevel@tonic-gate 		opts->k4_cache_name = optarg;
430*7c478bd9Sstevel@tonic-gate 	    }
431*7c478bd9Sstevel@tonic-gate 	    break;
432*7c478bd9Sstevel@tonic-gate #endif
433*7c478bd9Sstevel@tonic-gate 	case '4':
434*7c478bd9Sstevel@tonic-gate 	    if (!got_k4)
435*7c478bd9Sstevel@tonic-gate 	    {
436*7c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
437*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "Kerberos 4 support could not be loaded\n");
438*7c478bd9Sstevel@tonic-gate #else
439*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, gettext("This was not built with Kerberos 4 support\n"));
440*7c478bd9Sstevel@tonic-gate #endif
441*7c478bd9Sstevel@tonic-gate 		exit(3);
442*7c478bd9Sstevel@tonic-gate 	    }
443*7c478bd9Sstevel@tonic-gate 	    use_k4 = 1;
444*7c478bd9Sstevel@tonic-gate 	    break;
445*7c478bd9Sstevel@tonic-gate 	case '5':
446*7c478bd9Sstevel@tonic-gate 	    if (!got_k5)
447*7c478bd9Sstevel@tonic-gate 	    {
448*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, gettext("Kerberos 5 support could not be loaded\n"));
449*7c478bd9Sstevel@tonic-gate 		exit(3);
450*7c478bd9Sstevel@tonic-gate 	    }
451*7c478bd9Sstevel@tonic-gate 	    use_k5 = 1;
452*7c478bd9Sstevel@tonic-gate 	    break;
453*7c478bd9Sstevel@tonic-gate 	default:
454*7c478bd9Sstevel@tonic-gate 	    errflg++;
455*7c478bd9Sstevel@tonic-gate 	    break;
456*7c478bd9Sstevel@tonic-gate 	}
457*7c478bd9Sstevel@tonic-gate     }
458*7c478bd9Sstevel@tonic-gate 
459*7c478bd9Sstevel@tonic-gate     if (opts->forwardable && opts->not_forwardable)
460*7c478bd9Sstevel@tonic-gate     {
461*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, gettext("Only one of -f and -F allowed\n"));
462*7c478bd9Sstevel@tonic-gate 	errflg++;
463*7c478bd9Sstevel@tonic-gate     }
464*7c478bd9Sstevel@tonic-gate     if (opts->proxiable && opts->not_proxiable)
465*7c478bd9Sstevel@tonic-gate     {
466*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, gettext("Only one of -p and -P allowed\n"));
467*7c478bd9Sstevel@tonic-gate 	errflg++;
468*7c478bd9Sstevel@tonic-gate     }
469*7c478bd9Sstevel@tonic-gate     if (opts->addresses && opts->no_addresses)
470*7c478bd9Sstevel@tonic-gate     {
471*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, gettext("Only one of -a and -A allowed\n"));
472*7c478bd9Sstevel@tonic-gate 	errflg++;
473*7c478bd9Sstevel@tonic-gate     }
474*7c478bd9Sstevel@tonic-gate 
475*7c478bd9Sstevel@tonic-gate     if (argc - optind > 1) {
476*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, gettext("Extra arguments (starting with \"%s\").\n"),
477*7c478bd9Sstevel@tonic-gate 		argv[optind+1]);
478*7c478bd9Sstevel@tonic-gate 	errflg++;
479*7c478bd9Sstevel@tonic-gate     }
480*7c478bd9Sstevel@tonic-gate 
481*7c478bd9Sstevel@tonic-gate     /* At this point, if errorless, we know we only have one option
482*7c478bd9Sstevel@tonic-gate        selection */
483*7c478bd9Sstevel@tonic-gate     if (!use_k5 && !use_k4) {
484*7c478bd9Sstevel@tonic-gate 	use_k5 = default_k5;
485*7c478bd9Sstevel@tonic-gate 	use_k4 = default_k4;
486*7c478bd9Sstevel@tonic-gate     }
487*7c478bd9Sstevel@tonic-gate 
488*7c478bd9Sstevel@tonic-gate     /* Now, we encode the OPTTYPE stuff here... */
489*7c478bd9Sstevel@tonic-gate     if (!use_k5 &&
490*7c478bd9Sstevel@tonic-gate 	(opts->starttime || opts->rlife || opts->forwardable ||
491*7c478bd9Sstevel@tonic-gate 	 opts->proxiable || opts->addresses || opts->not_forwardable ||
492*7c478bd9Sstevel@tonic-gate 	 opts->not_proxiable || opts->no_addresses ||
493*7c478bd9Sstevel@tonic-gate 	 (opts->action == VALIDATE) || opts->k5_cache_name))
494*7c478bd9Sstevel@tonic-gate     {
495*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, gettext("Specified option that requires Kerberos 5\n"));
496*7c478bd9Sstevel@tonic-gate 	errflg++;
497*7c478bd9Sstevel@tonic-gate     }
498*7c478bd9Sstevel@tonic-gate     if (!use_k4 &&
499*7c478bd9Sstevel@tonic-gate 	opts->k4_cache_name)
500*7c478bd9Sstevel@tonic-gate     {
501*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, gettext("Specified option that require Kerberos 4\n"));
502*7c478bd9Sstevel@tonic-gate 	errflg++;
503*7c478bd9Sstevel@tonic-gate     }
504*7c478bd9Sstevel@tonic-gate     if (
505*7c478bd9Sstevel@tonic-gate #ifdef HAVE_KRB524
506*7c478bd9Sstevel@tonic-gate 	!use_k5
507*7c478bd9Sstevel@tonic-gate #else
508*7c478bd9Sstevel@tonic-gate 	use_k4
509*7c478bd9Sstevel@tonic-gate #endif
510*7c478bd9Sstevel@tonic-gate 	&& (opts->service_name || opts->keytab_name ||
511*7c478bd9Sstevel@tonic-gate 	    (opts->action == INIT_KT) || (opts->action == RENEW))
512*7c478bd9Sstevel@tonic-gate 	)
513*7c478bd9Sstevel@tonic-gate     {
514*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, gettext("Specified option that requires Kerberos 5\n"));
515*7c478bd9Sstevel@tonic-gate 	errflg++;
516*7c478bd9Sstevel@tonic-gate     }
517*7c478bd9Sstevel@tonic-gate 
518*7c478bd9Sstevel@tonic-gate     if (errflg) {
519*7c478bd9Sstevel@tonic-gate 	usage();
520*7c478bd9Sstevel@tonic-gate     }
521*7c478bd9Sstevel@tonic-gate 
522*7c478bd9Sstevel@tonic-gate     got_k5 = got_k5 && use_k5;
523*7c478bd9Sstevel@tonic-gate     got_k4 = got_k4 && use_k4;
524*7c478bd9Sstevel@tonic-gate 
525*7c478bd9Sstevel@tonic-gate     opts->principal_name = (optind == argc-1) ? argv[optind] : 0;
526*7c478bd9Sstevel@tonic-gate     return opts->principal_name;
527*7c478bd9Sstevel@tonic-gate }
528*7c478bd9Sstevel@tonic-gate 
529*7c478bd9Sstevel@tonic-gate int
530*7c478bd9Sstevel@tonic-gate k5_begin(opts, k5, k4)
531*7c478bd9Sstevel@tonic-gate     struct k_opts* opts;
532*7c478bd9Sstevel@tonic-gate struct k5_data* k5;
533*7c478bd9Sstevel@tonic-gate struct k4_data* k4;
534*7c478bd9Sstevel@tonic-gate {
535*7c478bd9Sstevel@tonic-gate     char* progname = progname_v5;
536*7c478bd9Sstevel@tonic-gate     krb5_error_code code = 0;
537*7c478bd9Sstevel@tonic-gate     char* cp;
538*7c478bd9Sstevel@tonic-gate 
539*7c478bd9Sstevel@tonic-gate     if (!got_k5)
540*7c478bd9Sstevel@tonic-gate 	return 0;
541*7c478bd9Sstevel@tonic-gate 
542*7c478bd9Sstevel@tonic-gate     if (code = krb5_init_context(&k5->ctx)) {
543*7c478bd9Sstevel@tonic-gate 	com_err(progname, code, gettext("while initializing Kerberos 5 library"));
544*7c478bd9Sstevel@tonic-gate 	return 0;
545*7c478bd9Sstevel@tonic-gate     }
546*7c478bd9Sstevel@tonic-gate     if (opts->k5_cache_name)
547*7c478bd9Sstevel@tonic-gate     {
548*7c478bd9Sstevel@tonic-gate 	code = krb5_cc_resolve(k5->ctx, opts->k5_cache_name, &k5->cc);
549*7c478bd9Sstevel@tonic-gate 	if (code != 0) {
550*7c478bd9Sstevel@tonic-gate 	    com_err(progname, code, gettext("resolving ccache %s"),
551*7c478bd9Sstevel@tonic-gate 		    opts->k5_cache_name);
552*7c478bd9Sstevel@tonic-gate 	    return 0;
553*7c478bd9Sstevel@tonic-gate 	}
554*7c478bd9Sstevel@tonic-gate     }
555*7c478bd9Sstevel@tonic-gate     else
556*7c478bd9Sstevel@tonic-gate     {
557*7c478bd9Sstevel@tonic-gate 	if ((code = krb5_cc_default(k5->ctx, &k5->cc))) {
558*7c478bd9Sstevel@tonic-gate 	    com_err(progname, code, gettext("while getting default ccache"));
559*7c478bd9Sstevel@tonic-gate 	    return 0;
560*7c478bd9Sstevel@tonic-gate 	}
561*7c478bd9Sstevel@tonic-gate     }
562*7c478bd9Sstevel@tonic-gate 
563*7c478bd9Sstevel@tonic-gate     if (opts->principal_name)
564*7c478bd9Sstevel@tonic-gate     {
565*7c478bd9Sstevel@tonic-gate 	/* Use specified name */
566*7c478bd9Sstevel@tonic-gate 	if ((code = krb5_parse_name(k5->ctx, opts->principal_name,
567*7c478bd9Sstevel@tonic-gate 				    &k5->me))) {
568*7c478bd9Sstevel@tonic-gate 	    com_err(progname, code, gettext("when parsing name %s"),
569*7c478bd9Sstevel@tonic-gate 		    opts->principal_name);
570*7c478bd9Sstevel@tonic-gate 	    return 0;
571*7c478bd9Sstevel@tonic-gate 	}
572*7c478bd9Sstevel@tonic-gate     }
573*7c478bd9Sstevel@tonic-gate     else
574*7c478bd9Sstevel@tonic-gate     {
575*7c478bd9Sstevel@tonic-gate 	/* No principal name specified */
576*7c478bd9Sstevel@tonic-gate 	if (opts->action == INIT_KT) {
577*7c478bd9Sstevel@tonic-gate 	    /* Use the default host/service name */
578*7c478bd9Sstevel@tonic-gate 	    if (code = krb5_sname_to_principal(k5->ctx, NULL, NULL,
579*7c478bd9Sstevel@tonic-gate 					       KRB5_NT_SRV_HST, &k5->me)) {
580*7c478bd9Sstevel@tonic-gate 		com_err(progname, code, gettext(
581*7c478bd9Sstevel@tonic-gate 			"when creating default server principal name"));
582*7c478bd9Sstevel@tonic-gate 		return 0;
583*7c478bd9Sstevel@tonic-gate 	    }
584*7c478bd9Sstevel@tonic-gate 	} else {
585*7c478bd9Sstevel@tonic-gate 	/* Get default principal from cache if one exists */
586*7c478bd9Sstevel@tonic-gate             if (code = krb5_cc_get_principal(k5->ctx, k5->cc, &k5->me)) {
587*7c478bd9Sstevel@tonic-gate                 char *name = get_name_from_os();
588*7c478bd9Sstevel@tonic-gate                 if (!name)
589*7c478bd9Sstevel@tonic-gate                 {
590*7c478bd9Sstevel@tonic-gate                     fprintf(stderr, gettext("Unable to identify user\n"));
591*7c478bd9Sstevel@tonic-gate                     return 0;
592*7c478bd9Sstevel@tonic-gate                 }
593*7c478bd9Sstevel@tonic-gate                 /* use strcmp to ensure only "root" is matched */
594*7c478bd9Sstevel@tonic-gate                 if (strcmp(name, ROOT_UNAME) == 0)
595*7c478bd9Sstevel@tonic-gate                 {
596*7c478bd9Sstevel@tonic-gate                 	if (code = krb5_sname_to_principal(k5->ctx, NULL, ROOT_UNAME,
597*7c478bd9Sstevel@tonic-gate 				    KRB5_NT_SRV_HST, &k5->me)) {
598*7c478bd9Sstevel@tonic-gate 			    com_err(progname, code, gettext(
599*7c478bd9Sstevel@tonic-gate 				"when creating default server principal name"));
600*7c478bd9Sstevel@tonic-gate                                 return 0;
601*7c478bd9Sstevel@tonic-gate                         }
602*7c478bd9Sstevel@tonic-gate                 } else if (code = krb5_parse_name(k5->ctx, name, &k5->me)) {
603*7c478bd9Sstevel@tonic-gate 			com_err(progname, code, gettext("when parsing name %s"),
604*7c478bd9Sstevel@tonic-gate 				name);
605*7c478bd9Sstevel@tonic-gate 			return 0;
606*7c478bd9Sstevel@tonic-gate 		}
607*7c478bd9Sstevel@tonic-gate             }
608*7c478bd9Sstevel@tonic-gate         }
609*7c478bd9Sstevel@tonic-gate     }
610*7c478bd9Sstevel@tonic-gate     if (code = krb5_unparse_name(k5->ctx, k5->me, &k5->name)) {
611*7c478bd9Sstevel@tonic-gate 	com_err(progname, code, gettext("when unparsing name"));
612*7c478bd9Sstevel@tonic-gate 	return 0;
613*7c478bd9Sstevel@tonic-gate     }
614*7c478bd9Sstevel@tonic-gate     opts->principal_name = k5->name;
615*7c478bd9Sstevel@tonic-gate 
616*7c478bd9Sstevel@tonic-gate 
617*7c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
618*7c478bd9Sstevel@tonic-gate     if (got_k4)
619*7c478bd9Sstevel@tonic-gate     {
620*7c478bd9Sstevel@tonic-gate 	/* Translate to a Kerberos 4 principal */
621*7c478bd9Sstevel@tonic-gate 	code = krb5_524_conv_principal(k5->ctx, k5->me,
622*7c478bd9Sstevel@tonic-gate 				       k4->aname, k4->inst, k4->realm);
623*7c478bd9Sstevel@tonic-gate 	if (code) {
624*7c478bd9Sstevel@tonic-gate 	    k4->aname[0] = 0;
625*7c478bd9Sstevel@tonic-gate 	    k4->inst[0] = 0;
626*7c478bd9Sstevel@tonic-gate 	    k4->realm[0] = 0;
627*7c478bd9Sstevel@tonic-gate 	}
628*7c478bd9Sstevel@tonic-gate     }
629*7c478bd9Sstevel@tonic-gate #endif
630*7c478bd9Sstevel@tonic-gate     return 1;
631*7c478bd9Sstevel@tonic-gate }
632*7c478bd9Sstevel@tonic-gate 
633*7c478bd9Sstevel@tonic-gate void
634*7c478bd9Sstevel@tonic-gate k5_end(k5)
635*7c478bd9Sstevel@tonic-gate     struct k5_data* k5;
636*7c478bd9Sstevel@tonic-gate {
637*7c478bd9Sstevel@tonic-gate     if (k5->name)
638*7c478bd9Sstevel@tonic-gate 	krb5_free_unparsed_name(k5->ctx, k5->name);
639*7c478bd9Sstevel@tonic-gate     if (k5->me)
640*7c478bd9Sstevel@tonic-gate 	krb5_free_principal(k5->ctx, k5->me);
641*7c478bd9Sstevel@tonic-gate     if (k5->cc)
642*7c478bd9Sstevel@tonic-gate 	krb5_cc_close(k5->ctx, k5->cc);
643*7c478bd9Sstevel@tonic-gate     if (k5->ctx)
644*7c478bd9Sstevel@tonic-gate 	krb5_free_context(k5->ctx);
645*7c478bd9Sstevel@tonic-gate     memset(k5, 0, sizeof(*k5));
646*7c478bd9Sstevel@tonic-gate }
647*7c478bd9Sstevel@tonic-gate 
648*7c478bd9Sstevel@tonic-gate int
649*7c478bd9Sstevel@tonic-gate k4_begin(opts, k4)
650*7c478bd9Sstevel@tonic-gate     struct k_opts* opts;
651*7c478bd9Sstevel@tonic-gate     struct k4_data* k4;
652*7c478bd9Sstevel@tonic-gate {
653*7c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
654*7c478bd9Sstevel@tonic-gate     char* progname = progname_v4;
655*7c478bd9Sstevel@tonic-gate     int k_errno = 0;
656*7c478bd9Sstevel@tonic-gate #endif
657*7c478bd9Sstevel@tonic-gate 
658*7c478bd9Sstevel@tonic-gate     if (!got_k4)
659*7c478bd9Sstevel@tonic-gate 	return 0;
660*7c478bd9Sstevel@tonic-gate 
661*7c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
662*7c478bd9Sstevel@tonic-gate     if (k4->aname[0])
663*7c478bd9Sstevel@tonic-gate 	goto skip;
664*7c478bd9Sstevel@tonic-gate 
665*7c478bd9Sstevel@tonic-gate     if (opts->principal_name)
666*7c478bd9Sstevel@tonic-gate     {
667*7c478bd9Sstevel@tonic-gate 	/* Use specified name */
668*7c478bd9Sstevel@tonic-gate 	if (k_errno = kname_parse(k4->aname, k4->inst, k4->realm,
669*7c478bd9Sstevel@tonic-gate 				  opts->principal_name))
670*7c478bd9Sstevel@tonic-gate 	{
671*7c478bd9Sstevel@tonic-gate 	    fprintf(stderr, "%s: %s\n", progname,
672*7c478bd9Sstevel@tonic-gate 		    krb_get_err_text(k_errno));
673*7c478bd9Sstevel@tonic-gate 	    return 0;
674*7c478bd9Sstevel@tonic-gate 	}
675*7c478bd9Sstevel@tonic-gate     } else {
676*7c478bd9Sstevel@tonic-gate 	/* No principal name specified */
677*7c478bd9Sstevel@tonic-gate 	if (opts->action == INIT_KT) {
678*7c478bd9Sstevel@tonic-gate 	    /* Use the default host/service name */
679*7c478bd9Sstevel@tonic-gate 	    /* XXX - need to add this functionality */
680*7c478bd9Sstevel@tonic-gate 	    fprintf(stderr, "%s: Kerberos 4 srvtab support is not "
681*7c478bd9Sstevel@tonic-gate 		    "implemented\n", progname);
682*7c478bd9Sstevel@tonic-gate 	    return 0;
683*7c478bd9Sstevel@tonic-gate 	} else {
684*7c478bd9Sstevel@tonic-gate 	    /* Get default principal from cache if one exists */
685*7c478bd9Sstevel@tonic-gate 	    if (k_errno = krb_get_tf_fullname(tkt_string(), k4->aname,
686*7c478bd9Sstevel@tonic-gate 					      k4->inst, k4->realm))
687*7c478bd9Sstevel@tonic-gate 	    {
688*7c478bd9Sstevel@tonic-gate 		char *name = get_name_from_os();
689*7c478bd9Sstevel@tonic-gate 		if (!name)
690*7c478bd9Sstevel@tonic-gate 		{
691*7c478bd9Sstevel@tonic-gate 		    fprintf(stderr, "Unable to identify user\n");
692*7c478bd9Sstevel@tonic-gate 		    return 0;
693*7c478bd9Sstevel@tonic-gate 		}
694*7c478bd9Sstevel@tonic-gate 		if (k_errno = kname_parse(k4->aname, k4->inst, k4->realm,
695*7c478bd9Sstevel@tonic-gate 					  name))
696*7c478bd9Sstevel@tonic-gate 		{
697*7c478bd9Sstevel@tonic-gate 		    fprintf(stderr, "%s: %s\n", progname,
698*7c478bd9Sstevel@tonic-gate 			    krb_get_err_text(k_errno));
699*7c478bd9Sstevel@tonic-gate 		    return 0;
700*7c478bd9Sstevel@tonic-gate 		}
701*7c478bd9Sstevel@tonic-gate 	    }
702*7c478bd9Sstevel@tonic-gate 	}
703*7c478bd9Sstevel@tonic-gate     }
704*7c478bd9Sstevel@tonic-gate 
705*7c478bd9Sstevel@tonic-gate     if (!k4->realm[0])
706*7c478bd9Sstevel@tonic-gate 	krb_get_lrealm(k4->realm, 1);
707*7c478bd9Sstevel@tonic-gate 
708*7c478bd9Sstevel@tonic-gate     if (k4->inst[0])
709*7c478bd9Sstevel@tonic-gate 	sprintf(k4->name, "%s.%s@%s", k4->aname, k4->inst, k4->realm);
710*7c478bd9Sstevel@tonic-gate     else
711*7c478bd9Sstevel@tonic-gate 	sprintf(k4->name, "%s@%s", k4->aname, k4->realm);
712*7c478bd9Sstevel@tonic-gate     opts->principal_name = k4->name;
713*7c478bd9Sstevel@tonic-gate 
714*7c478bd9Sstevel@tonic-gate  skip:
715*7c478bd9Sstevel@tonic-gate     if (k4->aname[0] && !k_isname(k4->aname))
716*7c478bd9Sstevel@tonic-gate     {
717*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "%s: bad Kerberos 4 name format\n", progname);
718*7c478bd9Sstevel@tonic-gate 	return 0;
719*7c478bd9Sstevel@tonic-gate     }
720*7c478bd9Sstevel@tonic-gate 
721*7c478bd9Sstevel@tonic-gate     if (k4->inst[0] && !k_isinst(k4->inst))
722*7c478bd9Sstevel@tonic-gate     {
723*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "%s: bad Kerberos 4 instance format\n", progname);
724*7c478bd9Sstevel@tonic-gate 	return 0;
725*7c478bd9Sstevel@tonic-gate     }
726*7c478bd9Sstevel@tonic-gate 
727*7c478bd9Sstevel@tonic-gate     if (k4->realm[0] && !k_isrealm(k4->realm))
728*7c478bd9Sstevel@tonic-gate     {
729*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "%s: bad Kerberos 4 realm format\n", progname);
730*7c478bd9Sstevel@tonic-gate 	return 0;
731*7c478bd9Sstevel@tonic-gate     }
732*7c478bd9Sstevel@tonic-gate #endif /* KRB5_KRB4_COMPAT */
733*7c478bd9Sstevel@tonic-gate     return 1;
734*7c478bd9Sstevel@tonic-gate }
735*7c478bd9Sstevel@tonic-gate 
736*7c478bd9Sstevel@tonic-gate void
737*7c478bd9Sstevel@tonic-gate k4_end(k4)
738*7c478bd9Sstevel@tonic-gate     struct k4_data* k4;
739*7c478bd9Sstevel@tonic-gate {
740*7c478bd9Sstevel@tonic-gate     memset(k4, 0, sizeof(*k4));
741*7c478bd9Sstevel@tonic-gate }
742*7c478bd9Sstevel@tonic-gate 
743*7c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
744*7c478bd9Sstevel@tonic-gate static char stash_password[1024];
745*7c478bd9Sstevel@tonic-gate static int got_password = 0;
746*7c478bd9Sstevel@tonic-gate #endif /* KRB5_KRB4_COMPAT */
747*7c478bd9Sstevel@tonic-gate 
748*7c478bd9Sstevel@tonic-gate krb5_error_code
749*7c478bd9Sstevel@tonic-gate KRB5_CALLCONV
750*7c478bd9Sstevel@tonic-gate kinit_prompter(
751*7c478bd9Sstevel@tonic-gate     krb5_context ctx,
752*7c478bd9Sstevel@tonic-gate     void *data,
753*7c478bd9Sstevel@tonic-gate     const char *name,
754*7c478bd9Sstevel@tonic-gate     const char *banner,
755*7c478bd9Sstevel@tonic-gate     int num_prompts,
756*7c478bd9Sstevel@tonic-gate     krb5_prompt prompts[]
757*7c478bd9Sstevel@tonic-gate     )
758*7c478bd9Sstevel@tonic-gate {
759*7c478bd9Sstevel@tonic-gate     int i;
760*7c478bd9Sstevel@tonic-gate     krb5_prompt_type *types;
761*7c478bd9Sstevel@tonic-gate     krb5_error_code rc =
762*7c478bd9Sstevel@tonic-gate 	krb5_prompter_posix(ctx, data, name, banner, num_prompts, prompts);
763*7c478bd9Sstevel@tonic-gate     if (!rc && (types = krb5_get_prompt_types(ctx)))
764*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < num_prompts; i++)
765*7c478bd9Sstevel@tonic-gate 	    if ((types[i] == KRB5_PROMPT_TYPE_PASSWORD) ||
766*7c478bd9Sstevel@tonic-gate 		(types[i] == KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN))
767*7c478bd9Sstevel@tonic-gate 	    {
768*7c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
769*7c478bd9Sstevel@tonic-gate 		strncpy(stash_password, prompts[i].reply->data,
770*7c478bd9Sstevel@tonic-gate 			sizeof(stash_password));
771*7c478bd9Sstevel@tonic-gate 		got_password = 1;
772*7c478bd9Sstevel@tonic-gate #endif
773*7c478bd9Sstevel@tonic-gate 	    }
774*7c478bd9Sstevel@tonic-gate 
775*7c478bd9Sstevel@tonic-gate     return rc;
776*7c478bd9Sstevel@tonic-gate }
777*7c478bd9Sstevel@tonic-gate 
778*7c478bd9Sstevel@tonic-gate int
779*7c478bd9Sstevel@tonic-gate k5_kinit(opts, k5)
780*7c478bd9Sstevel@tonic-gate     struct k_opts* opts;
781*7c478bd9Sstevel@tonic-gate     struct k5_data* k5;
782*7c478bd9Sstevel@tonic-gate {
783*7c478bd9Sstevel@tonic-gate     char* progname = progname_v5;
784*7c478bd9Sstevel@tonic-gate     int notix = 1;
785*7c478bd9Sstevel@tonic-gate     krb5_keytab keytab = 0;
786*7c478bd9Sstevel@tonic-gate     krb5_creds my_creds;
787*7c478bd9Sstevel@tonic-gate     krb5_error_code code = 0;
788*7c478bd9Sstevel@tonic-gate     krb5_get_init_creds_opt options;
789*7c478bd9Sstevel@tonic-gate     krb5_timestamp now;
790*7c478bd9Sstevel@tonic-gate     krb5_deltat lifetime = 0, rlife = 0, krb5_max_duration;
791*7c478bd9Sstevel@tonic-gate 
792*7c478bd9Sstevel@tonic-gate     if (!got_k5)
793*7c478bd9Sstevel@tonic-gate 	return 0;
794*7c478bd9Sstevel@tonic-gate 
795*7c478bd9Sstevel@tonic-gate     krb5_get_init_creds_opt_init(&options);
796*7c478bd9Sstevel@tonic-gate     memset(&my_creds, 0, sizeof(my_creds));
797*7c478bd9Sstevel@tonic-gate 
798*7c478bd9Sstevel@tonic-gate     /*
799*7c478bd9Sstevel@tonic-gate      * Solaris Kerberos: added support for max_life and max_renewable_life
800*7c478bd9Sstevel@tonic-gate      * which should be removed in the next minor release.  See PSARC 2003/545
801*7c478bd9Sstevel@tonic-gate      * for more info.
802*7c478bd9Sstevel@tonic-gate      *
803*7c478bd9Sstevel@tonic-gate      * Also, check krb5.conf for proxiable/forwardable/renewable/no_address
804*7c478bd9Sstevel@tonic-gate      * parameter values.
805*7c478bd9Sstevel@tonic-gate      */
806*7c478bd9Sstevel@tonic-gate     /* If either tkt life or renew life weren't set earlier take common steps to
807*7c478bd9Sstevel@tonic-gate      * get the krb5.conf parameter values.
808*7c478bd9Sstevel@tonic-gate      */
809*7c478bd9Sstevel@tonic-gate 
810*7c478bd9Sstevel@tonic-gate     if ((code = krb5_timeofday(k5->ctx, &now))) {
811*7c478bd9Sstevel@tonic-gate 	    com_err(progname, code, gettext("while getting time of day"));
812*7c478bd9Sstevel@tonic-gate 	    exit(1);
813*7c478bd9Sstevel@tonic-gate     }
814*7c478bd9Sstevel@tonic-gate     krb5_max_duration = KRB5_KDB_EXPIRATION - now - 60*60;
815*7c478bd9Sstevel@tonic-gate 
816*7c478bd9Sstevel@tonic-gate     if (opts->lifetime == 0 || opts->rlife == 0) {
817*7c478bd9Sstevel@tonic-gate 
818*7c478bd9Sstevel@tonic-gate 	krb_realm = krb5_princ_realm(k5->ctx, k5->me)->data;
819*7c478bd9Sstevel@tonic-gate 	/* realm params take precedence */
820*7c478bd9Sstevel@tonic-gate 	profile_get_options_string(k5->ctx->profile, realmdef, config_times);
821*7c478bd9Sstevel@tonic-gate 	profile_get_options_string(k5->ctx->profile, appdef, config_times);
822*7c478bd9Sstevel@tonic-gate 
823*7c478bd9Sstevel@tonic-gate 	/* if the input opts doesn't have lifetime set and the krb5.conf
824*7c478bd9Sstevel@tonic-gate 	 * parameter has been set, use that.
825*7c478bd9Sstevel@tonic-gate 	 */
826*7c478bd9Sstevel@tonic-gate 	if (opts->lifetime == 0 && life_timeval != NULL) {
827*7c478bd9Sstevel@tonic-gate 	    code = krb5_string_to_deltat(life_timeval, &lifetime);
828*7c478bd9Sstevel@tonic-gate 	    if (code != 0 || lifetime == 0 || lifetime > krb5_max_duration) {
829*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, gettext("Bad max_life "
830*7c478bd9Sstevel@tonic-gate 			    "value in Kerberos config file %s\n"),
831*7c478bd9Sstevel@tonic-gate 			life_timeval);
832*7c478bd9Sstevel@tonic-gate 		exit(1);
833*7c478bd9Sstevel@tonic-gate 	    }
834*7c478bd9Sstevel@tonic-gate 	    opts->lifetime = lifetime;
835*7c478bd9Sstevel@tonic-gate 	}
836*7c478bd9Sstevel@tonic-gate 	if (opts->rlife == 0 && renew_timeval != NULL) {
837*7c478bd9Sstevel@tonic-gate 	    code = krb5_string_to_deltat(renew_timeval, &rlife);
838*7c478bd9Sstevel@tonic-gate 	    if (code != 0 || rlife == 0 || rlife > krb5_max_duration) {
839*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, gettext("Bad max_renewable_life "
840*7c478bd9Sstevel@tonic-gate 			    "value in Kerberos config file %s\n"),
841*7c478bd9Sstevel@tonic-gate 			renew_timeval);
842*7c478bd9Sstevel@tonic-gate 		exit(1);
843*7c478bd9Sstevel@tonic-gate 	    }
844*7c478bd9Sstevel@tonic-gate 	    opts->rlife = rlife;
845*7c478bd9Sstevel@tonic-gate 	}
846*7c478bd9Sstevel@tonic-gate     }
847*7c478bd9Sstevel@tonic-gate 
848*7c478bd9Sstevel@tonic-gate     /*
849*7c478bd9Sstevel@tonic-gate      * If lifetime is not set on the cmdline or in the krb5.conf
850*7c478bd9Sstevel@tonic-gate      * file, default to max.
851*7c478bd9Sstevel@tonic-gate      */
852*7c478bd9Sstevel@tonic-gate     if (opts->lifetime == 0)
853*7c478bd9Sstevel@tonic-gate 	    opts->lifetime = krb5_max_duration;
854*7c478bd9Sstevel@tonic-gate 
855*7c478bd9Sstevel@tonic-gate 
856*7c478bd9Sstevel@tonic-gate     profile_get_options_boolean(k5->ctx->profile,
857*7c478bd9Sstevel@tonic-gate 				realmdef, config_option);
858*7c478bd9Sstevel@tonic-gate     profile_get_options_boolean(k5->ctx->profile,
859*7c478bd9Sstevel@tonic-gate 				appdef, config_option);
860*7c478bd9Sstevel@tonic-gate 
861*7c478bd9Sstevel@tonic-gate 
862*7c478bd9Sstevel@tonic-gate     /* cmdline opts take precedence over krb5.conf file values */
863*7c478bd9Sstevel@tonic-gate     if (!opts->not_proxiable && proxiable_flag) {
864*7c478bd9Sstevel@tonic-gate 	    krb5_get_init_creds_opt_set_proxiable(&options, 1);
865*7c478bd9Sstevel@tonic-gate     }
866*7c478bd9Sstevel@tonic-gate     if (!opts->not_forwardable && forwardable_flag) {
867*7c478bd9Sstevel@tonic-gate 	    krb5_get_init_creds_opt_set_forwardable(&options, 1);
868*7c478bd9Sstevel@tonic-gate     }
869*7c478bd9Sstevel@tonic-gate     if (renewable_flag) {
870*7c478bd9Sstevel@tonic-gate 	    /*
871*7c478bd9Sstevel@tonic-gate 	     * If this flag is set in krb5.conf, but rlife is 0, then
872*7c478bd9Sstevel@tonic-gate 	     * set it to the max (and let the KDC sort it out).
873*7c478bd9Sstevel@tonic-gate 	     */
874*7c478bd9Sstevel@tonic-gate 	    opts->rlife = opts->rlife ? opts->rlife : krb5_max_duration;
875*7c478bd9Sstevel@tonic-gate     }
876*7c478bd9Sstevel@tonic-gate     if (no_address_flag) {
877*7c478bd9Sstevel@tonic-gate 	    /* cmdline opts will overwrite this below if needbe */
878*7c478bd9Sstevel@tonic-gate 	    krb5_get_init_creds_opt_set_address_list(&options, NULL);
879*7c478bd9Sstevel@tonic-gate     }
880*7c478bd9Sstevel@tonic-gate 
881*7c478bd9Sstevel@tonic-gate 
882*7c478bd9Sstevel@tonic-gate     /*
883*7c478bd9Sstevel@tonic-gate       From this point on, we can goto cleanup because my_creds is
884*7c478bd9Sstevel@tonic-gate       initialized.
885*7c478bd9Sstevel@tonic-gate     */
886*7c478bd9Sstevel@tonic-gate 
887*7c478bd9Sstevel@tonic-gate     if (opts->lifetime)
888*7c478bd9Sstevel@tonic-gate 	krb5_get_init_creds_opt_set_tkt_life(&options, opts->lifetime);
889*7c478bd9Sstevel@tonic-gate     if (opts->rlife)
890*7c478bd9Sstevel@tonic-gate 	krb5_get_init_creds_opt_set_renew_life(&options, opts->rlife);
891*7c478bd9Sstevel@tonic-gate     if (opts->forwardable)
892*7c478bd9Sstevel@tonic-gate 	krb5_get_init_creds_opt_set_forwardable(&options, 1);
893*7c478bd9Sstevel@tonic-gate     if (opts->not_forwardable)
894*7c478bd9Sstevel@tonic-gate 	krb5_get_init_creds_opt_set_forwardable(&options, 0);
895*7c478bd9Sstevel@tonic-gate     if (opts->proxiable)
896*7c478bd9Sstevel@tonic-gate 	krb5_get_init_creds_opt_set_proxiable(&options, 1);
897*7c478bd9Sstevel@tonic-gate     if (opts->not_proxiable)
898*7c478bd9Sstevel@tonic-gate 	krb5_get_init_creds_opt_set_proxiable(&options, 0);
899*7c478bd9Sstevel@tonic-gate     if (opts->addresses)
900*7c478bd9Sstevel@tonic-gate     {
901*7c478bd9Sstevel@tonic-gate 	krb5_address **addresses = NULL;
902*7c478bd9Sstevel@tonic-gate 	code = krb5_os_localaddr(k5->ctx, &addresses);
903*7c478bd9Sstevel@tonic-gate 	if (code != 0) {
904*7c478bd9Sstevel@tonic-gate 	    com_err(progname, code, gettext("getting local addresses"));
905*7c478bd9Sstevel@tonic-gate 	    goto cleanup;
906*7c478bd9Sstevel@tonic-gate 	}
907*7c478bd9Sstevel@tonic-gate 	krb5_get_init_creds_opt_set_address_list(&options, addresses);
908*7c478bd9Sstevel@tonic-gate 	krb5_free_addresses(k5->ctx, addresses);
909*7c478bd9Sstevel@tonic-gate     }
910*7c478bd9Sstevel@tonic-gate     if (opts->no_addresses)
911*7c478bd9Sstevel@tonic-gate 	krb5_get_init_creds_opt_set_address_list(&options, NULL);
912*7c478bd9Sstevel@tonic-gate 
913*7c478bd9Sstevel@tonic-gate     if ((opts->action == INIT_KT) && opts->keytab_name)
914*7c478bd9Sstevel@tonic-gate     {
915*7c478bd9Sstevel@tonic-gate 	code = krb5_kt_resolve(k5->ctx, opts->keytab_name, &keytab);
916*7c478bd9Sstevel@tonic-gate 	if (code != 0) {
917*7c478bd9Sstevel@tonic-gate 	    com_err(progname, code, gettext("resolving keytab %s"),
918*7c478bd9Sstevel@tonic-gate 		    opts->keytab_name);
919*7c478bd9Sstevel@tonic-gate 	    goto cleanup;
920*7c478bd9Sstevel@tonic-gate 	}
921*7c478bd9Sstevel@tonic-gate     }
922*7c478bd9Sstevel@tonic-gate 
923*7c478bd9Sstevel@tonic-gate 
924*7c478bd9Sstevel@tonic-gate 
925*7c478bd9Sstevel@tonic-gate     switch (opts->action) {
926*7c478bd9Sstevel@tonic-gate     case INIT_PW:
927*7c478bd9Sstevel@tonic-gate 	code = krb5_get_init_creds_password(k5->ctx, &my_creds, k5->me,
928*7c478bd9Sstevel@tonic-gate 					    0, kinit_prompter, 0,
929*7c478bd9Sstevel@tonic-gate 					    opts->starttime,
930*7c478bd9Sstevel@tonic-gate 					    opts->service_name,
931*7c478bd9Sstevel@tonic-gate 					    &options);
932*7c478bd9Sstevel@tonic-gate 	break;
933*7c478bd9Sstevel@tonic-gate     case INIT_KT:
934*7c478bd9Sstevel@tonic-gate 	code = krb5_get_init_creds_keytab(k5->ctx, &my_creds, k5->me,
935*7c478bd9Sstevel@tonic-gate 					  keytab,
936*7c478bd9Sstevel@tonic-gate 					  opts->starttime,
937*7c478bd9Sstevel@tonic-gate 					  opts->service_name,
938*7c478bd9Sstevel@tonic-gate 					  &options);
939*7c478bd9Sstevel@tonic-gate 	break;
940*7c478bd9Sstevel@tonic-gate     case VALIDATE:
941*7c478bd9Sstevel@tonic-gate 	code = krb5_get_validated_creds(k5->ctx, &my_creds, k5->me, k5->cc,
942*7c478bd9Sstevel@tonic-gate 					opts->service_name);
943*7c478bd9Sstevel@tonic-gate 	break;
944*7c478bd9Sstevel@tonic-gate     case RENEW:
945*7c478bd9Sstevel@tonic-gate 	code = krb5_get_renewed_creds(k5->ctx, &my_creds, k5->me, k5->cc,
946*7c478bd9Sstevel@tonic-gate 				      opts->service_name);
947*7c478bd9Sstevel@tonic-gate 	break;
948*7c478bd9Sstevel@tonic-gate     }
949*7c478bd9Sstevel@tonic-gate 
950*7c478bd9Sstevel@tonic-gate     if (code) {
951*7c478bd9Sstevel@tonic-gate 	char *doing = 0;
952*7c478bd9Sstevel@tonic-gate 	switch (opts->action) {
953*7c478bd9Sstevel@tonic-gate 	case INIT_PW:
954*7c478bd9Sstevel@tonic-gate 	case INIT_KT:
955*7c478bd9Sstevel@tonic-gate 	    doing = gettext("getting initial credentials");
956*7c478bd9Sstevel@tonic-gate 	    break;
957*7c478bd9Sstevel@tonic-gate 	case VALIDATE:
958*7c478bd9Sstevel@tonic-gate 	    doing = gettext("validating credentials");
959*7c478bd9Sstevel@tonic-gate 	    break;
960*7c478bd9Sstevel@tonic-gate 	case RENEW:
961*7c478bd9Sstevel@tonic-gate 	    doing = gettext("renewing credentials");
962*7c478bd9Sstevel@tonic-gate 	    break;
963*7c478bd9Sstevel@tonic-gate 	}
964*7c478bd9Sstevel@tonic-gate 
965*7c478bd9Sstevel@tonic-gate 	/* If got code == KRB5_AP_ERR_V4_REPLY && got_k4, we should
966*7c478bd9Sstevel@tonic-gate 	   let the user know that maybe he/she wants -4. */
967*7c478bd9Sstevel@tonic-gate 	if (code == KRB5KRB_AP_ERR_V4_REPLY && got_k4)
968*7c478bd9Sstevel@tonic-gate 	    com_err(progname, code, "while %s\n"
969*7c478bd9Sstevel@tonic-gate 		    "The KDC doesn't support v5.  "
970*7c478bd9Sstevel@tonic-gate 		    "You may want the -4 option in the future",
971*7c478bd9Sstevel@tonic-gate 		    doing);
972*7c478bd9Sstevel@tonic-gate 	else if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY)
973*7c478bd9Sstevel@tonic-gate 	    fprintf(stderr, gettext("%s: Password incorrect while %s\n"), progname,
974*7c478bd9Sstevel@tonic-gate 		    doing);
975*7c478bd9Sstevel@tonic-gate 	else
976*7c478bd9Sstevel@tonic-gate 	    com_err(progname, code, gettext("while %s"), doing);
977*7c478bd9Sstevel@tonic-gate 	goto cleanup;
978*7c478bd9Sstevel@tonic-gate     }
979*7c478bd9Sstevel@tonic-gate 
980*7c478bd9Sstevel@tonic-gate     if (!opts->lifetime) {
981*7c478bd9Sstevel@tonic-gate 	/* We need to figure out what lifetime to use for Kerberos 4. */
982*7c478bd9Sstevel@tonic-gate 	opts->lifetime = my_creds.times.endtime - my_creds.times.authtime;
983*7c478bd9Sstevel@tonic-gate     }
984*7c478bd9Sstevel@tonic-gate 
985*7c478bd9Sstevel@tonic-gate     if (code = krb5_cc_initialize(k5->ctx, k5->cc, k5->me)) {
986*7c478bd9Sstevel@tonic-gate 	com_err(progname, code, gettext("when initializing cache %s"),
987*7c478bd9Sstevel@tonic-gate 		opts->k5_cache_name?opts->k5_cache_name:"");
988*7c478bd9Sstevel@tonic-gate 	goto cleanup;
989*7c478bd9Sstevel@tonic-gate     }
990*7c478bd9Sstevel@tonic-gate 
991*7c478bd9Sstevel@tonic-gate     if (code = krb5_cc_store_cred(k5->ctx, k5->cc, &my_creds)) {
992*7c478bd9Sstevel@tonic-gate 	com_err(progname, code, gettext("while storing credentials"));
993*7c478bd9Sstevel@tonic-gate 	goto cleanup;
994*7c478bd9Sstevel@tonic-gate     }
995*7c478bd9Sstevel@tonic-gate 
996*7c478bd9Sstevel@tonic-gate     if (opts->action == RENEW) {
997*7c478bd9Sstevel@tonic-gate         _kwarnd_del_warning(opts->principal_name);
998*7c478bd9Sstevel@tonic-gate         _kwarnd_add_warning(opts->principal_name, my_creds.times.endtime);
999*7c478bd9Sstevel@tonic-gate     } else if ((opts->action == INIT_KT) || (opts->action == INIT_PW)) {
1000*7c478bd9Sstevel@tonic-gate         _kwarnd_add_warning(opts->principal_name, my_creds.times.endtime);
1001*7c478bd9Sstevel@tonic-gate     }
1002*7c478bd9Sstevel@tonic-gate 
1003*7c478bd9Sstevel@tonic-gate     notix = 0;
1004*7c478bd9Sstevel@tonic-gate 
1005*7c478bd9Sstevel@tonic-gate  cleanup:
1006*7c478bd9Sstevel@tonic-gate     if (my_creds.client == k5->me) {
1007*7c478bd9Sstevel@tonic-gate 	my_creds.client = 0;
1008*7c478bd9Sstevel@tonic-gate     }
1009*7c478bd9Sstevel@tonic-gate     krb5_free_cred_contents(k5->ctx, &my_creds);
1010*7c478bd9Sstevel@tonic-gate     if (keytab)
1011*7c478bd9Sstevel@tonic-gate 	krb5_kt_close(k5->ctx, keytab);
1012*7c478bd9Sstevel@tonic-gate     return notix?0:1;
1013*7c478bd9Sstevel@tonic-gate }
1014*7c478bd9Sstevel@tonic-gate 
1015*7c478bd9Sstevel@tonic-gate int
1016*7c478bd9Sstevel@tonic-gate k4_kinit(opts, k4, ctx)
1017*7c478bd9Sstevel@tonic-gate     struct k_opts* opts;
1018*7c478bd9Sstevel@tonic-gate     struct k4_data* k4;
1019*7c478bd9Sstevel@tonic-gate     krb5_context ctx;
1020*7c478bd9Sstevel@tonic-gate {
1021*7c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
1022*7c478bd9Sstevel@tonic-gate     char* progname = progname_v4;
1023*7c478bd9Sstevel@tonic-gate     int k_errno = 0;
1024*7c478bd9Sstevel@tonic-gate #endif
1025*7c478bd9Sstevel@tonic-gate 
1026*7c478bd9Sstevel@tonic-gate     if (!got_k4)
1027*7c478bd9Sstevel@tonic-gate 	return 0;
1028*7c478bd9Sstevel@tonic-gate 
1029*7c478bd9Sstevel@tonic-gate     if (opts->starttime)
1030*7c478bd9Sstevel@tonic-gate 	return 0;
1031*7c478bd9Sstevel@tonic-gate 
1032*7c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
1033*7c478bd9Sstevel@tonic-gate     if (!k4->lifetime)
1034*7c478bd9Sstevel@tonic-gate 	k4->lifetime = opts->lifetime;
1035*7c478bd9Sstevel@tonic-gate     if (!k4->lifetime)
1036*7c478bd9Sstevel@tonic-gate 	k4->lifetime = KRB4_BACKUP_DEFAULT_LIFE_SECS;
1037*7c478bd9Sstevel@tonic-gate 
1038*7c478bd9Sstevel@tonic-gate     k4->lifetime /= (5 * 60);
1039*7c478bd9Sstevel@tonic-gate     if (k4->lifetime < 1)
1040*7c478bd9Sstevel@tonic-gate 	k4->lifetime = 1;
1041*7c478bd9Sstevel@tonic-gate     if (k4->lifetime > 255)
1042*7c478bd9Sstevel@tonic-gate 	k4->lifetime = 255;
1043*7c478bd9Sstevel@tonic-gate 
1044*7c478bd9Sstevel@tonic-gate     switch (opts->action)
1045*7c478bd9Sstevel@tonic-gate     {
1046*7c478bd9Sstevel@tonic-gate     case INIT_PW:
1047*7c478bd9Sstevel@tonic-gate 	if (!got_password) {
1048*7c478bd9Sstevel@tonic-gate 	    int pwsize = sizeof(stash_password);
1049*7c478bd9Sstevel@tonic-gate 	    krb5_error_code code;
1050*7c478bd9Sstevel@tonic-gate 	    char prompt[1024];
1051*7c478bd9Sstevel@tonic-gate 
1052*7c478bd9Sstevel@tonic-gate 	    sprintf(prompt, gettext("Password for %s: "), opts->principal_name);
1053*7c478bd9Sstevel@tonic-gate 	    stash_password[0] = 0;
1054*7c478bd9Sstevel@tonic-gate 	    /*
1055*7c478bd9Sstevel@tonic-gate 	      Note: krb5_read_password does not actually look at the
1056*7c478bd9Sstevel@tonic-gate 	      context, so we're ok even if we don't have a context.  If
1057*7c478bd9Sstevel@tonic-gate 	      we cannot dynamically load krb5, we can substitute any
1058*7c478bd9Sstevel@tonic-gate 	      decent read password function instead of the krb5 one.
1059*7c478bd9Sstevel@tonic-gate 	    */
1060*7c478bd9Sstevel@tonic-gate 	    code = krb5_read_password(ctx, prompt, 0, stash_password, &pwsize);
1061*7c478bd9Sstevel@tonic-gate 	    if (code || pwsize == 0)
1062*7c478bd9Sstevel@tonic-gate 	    {
1063*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, gettext("Error while reading password for '%s'\n"),
1064*7c478bd9Sstevel@tonic-gate 			opts->principal_name);
1065*7c478bd9Sstevel@tonic-gate 		memset(stash_password, 0, sizeof(stash_password));
1066*7c478bd9Sstevel@tonic-gate 		return 0;
1067*7c478bd9Sstevel@tonic-gate 	    }
1068*7c478bd9Sstevel@tonic-gate 	    got_password = 1;
1069*7c478bd9Sstevel@tonic-gate 	}
1070*7c478bd9Sstevel@tonic-gate 	k_errno = krb_get_pw_in_tkt(k4->aname, k4->inst, k4->realm, "krbtgt",
1071*7c478bd9Sstevel@tonic-gate 				    k4->realm, k4->lifetime, stash_password);
1072*7c478bd9Sstevel@tonic-gate 
1073*7c478bd9Sstevel@tonic-gate 	if (k_errno) {
1074*7c478bd9Sstevel@tonic-gate 	    fprintf(stderr, "%s: %s\n", progname,
1075*7c478bd9Sstevel@tonic-gate 		    krb_get_err_text(k_errno));
1076*7c478bd9Sstevel@tonic-gate 	    if (authed_k5)
1077*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, gettext("Maybe your KDC does not support v4.  "
1078*7c478bd9Sstevel@tonic-gate 			"Try the -5 option next time.\n"));
1079*7c478bd9Sstevel@tonic-gate 	    return 0;
1080*7c478bd9Sstevel@tonic-gate 	}
1081*7c478bd9Sstevel@tonic-gate 	return 1;
1082*7c478bd9Sstevel@tonic-gate #ifndef HAVE_KRB524
1083*7c478bd9Sstevel@tonic-gate     case INIT_KT:
1084*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, gettext("%s: srvtabs are not supported\n"), progname);
1085*7c478bd9Sstevel@tonic-gate 	return 0;
1086*7c478bd9Sstevel@tonic-gate     case RENEW:
1087*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, gettext("%s: renewal of krb4 tickets is not supported\n"),
1088*7c478bd9Sstevel@tonic-gate 		progname);
1089*7c478bd9Sstevel@tonic-gate 	return 0;
1090*7c478bd9Sstevel@tonic-gate #endif
1091*7c478bd9Sstevel@tonic-gate     }
1092*7c478bd9Sstevel@tonic-gate #endif
1093*7c478bd9Sstevel@tonic-gate     return 0;
1094*7c478bd9Sstevel@tonic-gate }
1095*7c478bd9Sstevel@tonic-gate 
1096*7c478bd9Sstevel@tonic-gate char*
1097*7c478bd9Sstevel@tonic-gate getvprogname(v)
1098*7c478bd9Sstevel@tonic-gate     char *v;
1099*7c478bd9Sstevel@tonic-gate {
1100*7c478bd9Sstevel@tonic-gate     int len = strlen(progname) + 2 + strlen(v) + 2;
1101*7c478bd9Sstevel@tonic-gate     char *ret = malloc(len);
1102*7c478bd9Sstevel@tonic-gate     if (ret)
1103*7c478bd9Sstevel@tonic-gate 	sprintf(ret, "%s(v%s)", progname, v);
1104*7c478bd9Sstevel@tonic-gate     else
1105*7c478bd9Sstevel@tonic-gate 	ret = progname;
1106*7c478bd9Sstevel@tonic-gate     return ret;
1107*7c478bd9Sstevel@tonic-gate }
1108*7c478bd9Sstevel@tonic-gate 
1109*7c478bd9Sstevel@tonic-gate #ifdef HAVE_KRB524
1110*7c478bd9Sstevel@tonic-gate /* Convert krb5 tickets to krb4. */
1111*7c478bd9Sstevel@tonic-gate int try_convert524(k5)
1112*7c478bd9Sstevel@tonic-gate     struct k5_data* k5;
1113*7c478bd9Sstevel@tonic-gate {
1114*7c478bd9Sstevel@tonic-gate     char * progname = progname_v524;
1115*7c478bd9Sstevel@tonic-gate     krb5_error_code code = 0;
1116*7c478bd9Sstevel@tonic-gate     int icode = 0;
1117*7c478bd9Sstevel@tonic-gate     krb5_principal kpcserver = 0;
1118*7c478bd9Sstevel@tonic-gate     krb5_creds *v5creds = 0;
1119*7c478bd9Sstevel@tonic-gate     krb5_creds increds;
1120*7c478bd9Sstevel@tonic-gate     CREDENTIALS v4creds;
1121*7c478bd9Sstevel@tonic-gate 
1122*7c478bd9Sstevel@tonic-gate     if (!got_k4 || !got_k5)
1123*7c478bd9Sstevel@tonic-gate 	return 0;
1124*7c478bd9Sstevel@tonic-gate 
1125*7c478bd9Sstevel@tonic-gate     memset((char *) &increds, 0, sizeof(increds));
1126*7c478bd9Sstevel@tonic-gate     /*
1127*7c478bd9Sstevel@tonic-gate       From this point on, we can goto cleanup because increds is
1128*7c478bd9Sstevel@tonic-gate       initialized.
1129*7c478bd9Sstevel@tonic-gate     */
1130*7c478bd9Sstevel@tonic-gate 
1131*7c478bd9Sstevel@tonic-gate     /* or do this directly with krb524_convert_creds_kdc */
1132*7c478bd9Sstevel@tonic-gate     krb524_init_ets(k5->ctx);
1133*7c478bd9Sstevel@tonic-gate 
1134*7c478bd9Sstevel@tonic-gate     if ((code = krb5_build_principal(k5->ctx,
1135*7c478bd9Sstevel@tonic-gate 				     &kpcserver,
1136*7c478bd9Sstevel@tonic-gate 				     krb5_princ_realm(k5->ctx, k5->me)->length,
1137*7c478bd9Sstevel@tonic-gate 				     krb5_princ_realm(k5->ctx, k5->me)->data,
1138*7c478bd9Sstevel@tonic-gate 				     "krbtgt",
1139*7c478bd9Sstevel@tonic-gate 				     krb5_princ_realm(k5->ctx, k5->me)->data,
1140*7c478bd9Sstevel@tonic-gate 				     NULL))) {
1141*7c478bd9Sstevel@tonic-gate 	com_err(progname, code, gettext(
1142*7c478bd9Sstevel@tonic-gate 		"while creating service principal name"));
1143*7c478bd9Sstevel@tonic-gate 	goto cleanup;
1144*7c478bd9Sstevel@tonic-gate     }
1145*7c478bd9Sstevel@tonic-gate 
1146*7c478bd9Sstevel@tonic-gate     increds.client = k5->me;
1147*7c478bd9Sstevel@tonic-gate     increds.server = kpcserver;
1148*7c478bd9Sstevel@tonic-gate     /* Prevent duplicate free calls.  */
1149*7c478bd9Sstevel@tonic-gate     kpcserver = 0;
1150*7c478bd9Sstevel@tonic-gate 
1151*7c478bd9Sstevel@tonic-gate     increds.times.endtime = 0;
1152*7c478bd9Sstevel@tonic-gate     increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
1153*7c478bd9Sstevel@tonic-gate     if ((code = krb5_get_credentials(k5->ctx, 0,
1154*7c478bd9Sstevel@tonic-gate 				     k5->cc,
1155*7c478bd9Sstevel@tonic-gate 				     &increds,
1156*7c478bd9Sstevel@tonic-gate 				     &v5creds))) {
1157*7c478bd9Sstevel@tonic-gate 	com_err(progname, code,
1158*7c478bd9Sstevel@tonic-gate 		gettext("getting V5 credentials"));
1159*7c478bd9Sstevel@tonic-gate 	goto cleanup;
1160*7c478bd9Sstevel@tonic-gate     }
1161*7c478bd9Sstevel@tonic-gate     if ((icode = krb524_convert_creds_kdc(k5->ctx,
1162*7c478bd9Sstevel@tonic-gate 					  v5creds,
1163*7c478bd9Sstevel@tonic-gate 					  &v4creds))) {
1164*7c478bd9Sstevel@tonic-gate 	com_err(progname, icode,
1165*7c478bd9Sstevel@tonic-gate 		gettext("converting to V4 credentials"));
1166*7c478bd9Sstevel@tonic-gate 	goto cleanup;
1167*7c478bd9Sstevel@tonic-gate     }
1168*7c478bd9Sstevel@tonic-gate     /* this is stolen from the v4 kinit */
1169*7c478bd9Sstevel@tonic-gate     /* initialize ticket cache */
1170*7c478bd9Sstevel@tonic-gate     if ((icode = in_tkt(v4creds.pname, v4creds.pinst)
1171*7c478bd9Sstevel@tonic-gate 	 != KSUCCESS)) {
1172*7c478bd9Sstevel@tonic-gate 	com_err(progname, icode, gettext(
1173*7c478bd9Sstevel@tonic-gate 		"trying to create the V4 ticket file"));
1174*7c478bd9Sstevel@tonic-gate 	goto cleanup;
1175*7c478bd9Sstevel@tonic-gate     }
1176*7c478bd9Sstevel@tonic-gate     /* stash ticket, session key, etc. for future use */
1177*7c478bd9Sstevel@tonic-gate     if ((icode = krb_save_credentials(v4creds.service,
1178*7c478bd9Sstevel@tonic-gate 				      v4creds.instance,
1179*7c478bd9Sstevel@tonic-gate 				      v4creds.realm,
1180*7c478bd9Sstevel@tonic-gate 				      v4creds.session,
1181*7c478bd9Sstevel@tonic-gate 				      v4creds.lifetime,
1182*7c478bd9Sstevel@tonic-gate 				      v4creds.kvno,
1183*7c478bd9Sstevel@tonic-gate 				      &(v4creds.ticket_st),
1184*7c478bd9Sstevel@tonic-gate 				      v4creds.issue_date))) {
1185*7c478bd9Sstevel@tonic-gate 	com_err(progname, icode, gettext(
1186*7c478bd9Sstevel@tonic-gate 		"trying to save the V4 ticket"));
1187*7c478bd9Sstevel@tonic-gate 	goto cleanup;
1188*7c478bd9Sstevel@tonic-gate     }
1189*7c478bd9Sstevel@tonic-gate 
1190*7c478bd9Sstevel@tonic-gate  cleanup:
1191*7c478bd9Sstevel@tonic-gate     memset(&v4creds, 0, sizeof(v4creds));
1192*7c478bd9Sstevel@tonic-gate     if (v5creds)
1193*7c478bd9Sstevel@tonic-gate 	krb5_free_creds(k5->ctx, v5creds);
1194*7c478bd9Sstevel@tonic-gate     increds.client = 0;
1195*7c478bd9Sstevel@tonic-gate     krb5_free_cred_contents(k5->ctx, &increds);
1196*7c478bd9Sstevel@tonic-gate     if (kpcserver)
1197*7c478bd9Sstevel@tonic-gate 	krb5_free_principal(k5->ctx, kpcserver);
1198*7c478bd9Sstevel@tonic-gate     return !(code || icode);
1199*7c478bd9Sstevel@tonic-gate }
1200*7c478bd9Sstevel@tonic-gate #endif /* HAVE_KRB524 */
1201*7c478bd9Sstevel@tonic-gate 
1202*7c478bd9Sstevel@tonic-gate int
1203*7c478bd9Sstevel@tonic-gate main(argc, argv)
1204*7c478bd9Sstevel@tonic-gate     int argc;
1205*7c478bd9Sstevel@tonic-gate     char **argv;
1206*7c478bd9Sstevel@tonic-gate {
1207*7c478bd9Sstevel@tonic-gate     struct k_opts opts;
1208*7c478bd9Sstevel@tonic-gate     struct k5_data k5;
1209*7c478bd9Sstevel@tonic-gate     struct k4_data k4;
1210*7c478bd9Sstevel@tonic-gate 
1211*7c478bd9Sstevel@tonic-gate     (void) setlocale(LC_ALL, "");
1212*7c478bd9Sstevel@tonic-gate 
1213*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
1214*7c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN	"SYS_TEST"
1215*7c478bd9Sstevel@tonic-gate #endif
1216*7c478bd9Sstevel@tonic-gate 
1217*7c478bd9Sstevel@tonic-gate     (void) textdomain(TEXT_DOMAIN);
1218*7c478bd9Sstevel@tonic-gate 
1219*7c478bd9Sstevel@tonic-gate     progname = GET_PROGNAME(argv[0]);
1220*7c478bd9Sstevel@tonic-gate     progname_v5 = getvprogname("5");
1221*7c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
1222*7c478bd9Sstevel@tonic-gate     progname_v4 = getvprogname("4");
1223*7c478bd9Sstevel@tonic-gate     progname_v524 = getvprogname("524");
1224*7c478bd9Sstevel@tonic-gate #endif
1225*7c478bd9Sstevel@tonic-gate 
1226*7c478bd9Sstevel@tonic-gate     /* Ensure we can be driven from a pipe */
1227*7c478bd9Sstevel@tonic-gate     if(!isatty(fileno(stdin)))
1228*7c478bd9Sstevel@tonic-gate 	setvbuf(stdin, 0, _IONBF, 0);
1229*7c478bd9Sstevel@tonic-gate     if(!isatty(fileno(stdout)))
1230*7c478bd9Sstevel@tonic-gate 	setvbuf(stdout, 0, _IONBF, 0);
1231*7c478bd9Sstevel@tonic-gate     if(!isatty(fileno(stderr)))
1232*7c478bd9Sstevel@tonic-gate 	setvbuf(stderr, 0, _IONBF, 0);
1233*7c478bd9Sstevel@tonic-gate 
1234*7c478bd9Sstevel@tonic-gate     /*
1235*7c478bd9Sstevel@tonic-gate       This is where we would put in code to dynamically load Kerberos
1236*7c478bd9Sstevel@tonic-gate       libraries.  Currenlty, we just get them implicitly.
1237*7c478bd9Sstevel@tonic-gate     */
1238*7c478bd9Sstevel@tonic-gate     got_k5 = 1;
1239*7c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
1240*7c478bd9Sstevel@tonic-gate     got_k4 = 1;
1241*7c478bd9Sstevel@tonic-gate #endif
1242*7c478bd9Sstevel@tonic-gate 
1243*7c478bd9Sstevel@tonic-gate     memset(&opts, 0, sizeof(opts));
1244*7c478bd9Sstevel@tonic-gate     opts.action = INIT_PW;
1245*7c478bd9Sstevel@tonic-gate 
1246*7c478bd9Sstevel@tonic-gate     memset(&k5, 0, sizeof(k5));
1247*7c478bd9Sstevel@tonic-gate     memset(&k4, 0, sizeof(k4));
1248*7c478bd9Sstevel@tonic-gate 
1249*7c478bd9Sstevel@tonic-gate     parse_options(argc, argv, &opts);
1250*7c478bd9Sstevel@tonic-gate 
1251*7c478bd9Sstevel@tonic-gate     got_k5 = k5_begin(&opts, &k5, &k4);
1252*7c478bd9Sstevel@tonic-gate     got_k4 = k4_begin(&opts, &k4);
1253*7c478bd9Sstevel@tonic-gate 
1254*7c478bd9Sstevel@tonic-gate     authed_k5 = k5_kinit(&opts, &k5);
1255*7c478bd9Sstevel@tonic-gate #ifdef HAVE_KRB524
1256*7c478bd9Sstevel@tonic-gate     if (authed_k5)
1257*7c478bd9Sstevel@tonic-gate 	authed_k4 = try_convert524(&k5);
1258*7c478bd9Sstevel@tonic-gate #endif
1259*7c478bd9Sstevel@tonic-gate     if (!authed_k4)
1260*7c478bd9Sstevel@tonic-gate 	authed_k4 = k4_kinit(&opts, &k4, k5.ctx);
1261*7c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT
1262*7c478bd9Sstevel@tonic-gate     memset(stash_password, 0, sizeof(stash_password));
1263*7c478bd9Sstevel@tonic-gate #endif
1264*7c478bd9Sstevel@tonic-gate 
1265*7c478bd9Sstevel@tonic-gate     if (authed_k5 && opts.verbose)
1266*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, gettext("Authenticated to Kerberos v5\n"));
1267*7c478bd9Sstevel@tonic-gate     if (authed_k4 && opts.verbose)
1268*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, gettext("Authenticated to Kerberos v4\n"));
1269*7c478bd9Sstevel@tonic-gate 
1270*7c478bd9Sstevel@tonic-gate     k5_end(&k5);
1271*7c478bd9Sstevel@tonic-gate     k4_end(&k4);
1272*7c478bd9Sstevel@tonic-gate 
1273*7c478bd9Sstevel@tonic-gate     if ((got_k5 && !authed_k5) || (got_k4 && !authed_k4))
1274*7c478bd9Sstevel@tonic-gate 	exit(1);
1275*7c478bd9Sstevel@tonic-gate     return 0;
1276*7c478bd9Sstevel@tonic-gate }
1277*7c478bd9Sstevel@tonic-gate 
1278*7c478bd9Sstevel@tonic-gate static void
1279*7c478bd9Sstevel@tonic-gate _kwarnd_add_warning(char *me, time_t endtime)
1280*7c478bd9Sstevel@tonic-gate {
1281*7c478bd9Sstevel@tonic-gate     if (kwarn_add_warning(me, endtime) != 0)
1282*7c478bd9Sstevel@tonic-gate         fprintf(stderr, gettext(
1283*7c478bd9Sstevel@tonic-gate             "%s:  no ktkt_warnd warning possible\n"), progname);
1284*7c478bd9Sstevel@tonic-gate     return;
1285*7c478bd9Sstevel@tonic-gate }
1286*7c478bd9Sstevel@tonic-gate 
1287*7c478bd9Sstevel@tonic-gate 
1288*7c478bd9Sstevel@tonic-gate static void
1289*7c478bd9Sstevel@tonic-gate _kwarnd_del_warning(char *me)
1290*7c478bd9Sstevel@tonic-gate {
1291*7c478bd9Sstevel@tonic-gate     if (kwarn_del_warning(me) != 0)
1292*7c478bd9Sstevel@tonic-gate         fprintf(stderr, gettext(
1293*7c478bd9Sstevel@tonic-gate             "%s:  unable to delete ktkt_warnd message for %s\n"),
1294*7c478bd9Sstevel@tonic-gate             progname, me);
1295*7c478bd9Sstevel@tonic-gate     return;
1296*7c478bd9Sstevel@tonic-gate }
1297