xref: /freebsd/crypto/heimdal/kuser/kinit.c (revision 1c43270ada91f3473174c2bf81fba64963b7e4ac)
1b528cefcSMark Murray /*
28373020dSJacques Vidrine  * Copyright (c) 1997-2002 Kungliga Tekniska H�gskolan
3b528cefcSMark Murray  * (Royal Institute of Technology, Stockholm, Sweden).
4b528cefcSMark Murray  * All rights reserved.
5b528cefcSMark Murray  *
6b528cefcSMark Murray  * Redistribution and use in source and binary forms, with or without
7b528cefcSMark Murray  * modification, are permitted provided that the following conditions
8b528cefcSMark Murray  * are met:
9b528cefcSMark Murray  *
10b528cefcSMark Murray  * 1. Redistributions of source code must retain the above copyright
11b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer.
12b528cefcSMark Murray  *
13b528cefcSMark Murray  * 2. Redistributions in binary form must reproduce the above copyright
14b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer in the
15b528cefcSMark Murray  *    documentation and/or other materials provided with the distribution.
16b528cefcSMark Murray  *
17b528cefcSMark Murray  * 3. Neither the name of the Institute nor the names of its contributors
18b528cefcSMark Murray  *    may be used to endorse or promote products derived from this software
19b528cefcSMark Murray  *    without specific prior written permission.
20b528cefcSMark Murray  *
21b528cefcSMark Murray  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22b528cefcSMark Murray  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23b528cefcSMark Murray  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24b528cefcSMark Murray  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25b528cefcSMark Murray  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26b528cefcSMark Murray  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27b528cefcSMark Murray  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28b528cefcSMark Murray  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29b528cefcSMark Murray  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30b528cefcSMark Murray  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31b528cefcSMark Murray  * SUCH DAMAGE.
32b528cefcSMark Murray  */
33b528cefcSMark Murray 
34b528cefcSMark Murray #include "kuser_locl.h"
351c43270aSJacques Vidrine RCSID("$Id: kinit.c,v 1.90.4.4 2004/01/13 10:13:55 lha Exp $");
365e9cd1aeSAssar Westerlund 
375e9cd1aeSAssar Westerlund int forwardable_flag	= -1;
385e9cd1aeSAssar Westerlund int proxiable_flag	= -1;
395e9cd1aeSAssar Westerlund int renewable_flag	= -1;
40b528cefcSMark Murray int renew_flag		= 0;
41b528cefcSMark Murray int validate_flag	= 0;
42b528cefcSMark Murray int version_flag	= 0;
43b528cefcSMark Murray int help_flag		= 0;
4413e3f4d6SMark Murray int addrs_flag		= 1;
458373020dSJacques Vidrine struct getarg_strings extra_addresses;
465e9cd1aeSAssar Westerlund int anonymous_flag	= 0;
47b528cefcSMark Murray char *lifetime 		= NULL;
48b528cefcSMark Murray char *renew_life	= NULL;
49b528cefcSMark Murray char *server		= NULL;
50b528cefcSMark Murray char *cred_cache	= NULL;
51b528cefcSMark Murray char *start_str		= NULL;
52b528cefcSMark Murray struct getarg_strings etype_str;
53b528cefcSMark Murray int use_keytab		= 0;
54b528cefcSMark Murray char *keytab_str	= NULL;
55bbd80c28SJacques Vidrine int do_afslog		= -1;
56b528cefcSMark Murray #ifdef KRB4
574137ff4cSJacques Vidrine int get_v4_tgt		= -1;
584137ff4cSJacques Vidrine int convert_524;
59b528cefcSMark Murray #endif
60b528cefcSMark Murray int fcache_version;
61b528cefcSMark Murray 
625e9cd1aeSAssar Westerlund static struct getargs args[] = {
63b528cefcSMark Murray #ifdef KRB4
64b528cefcSMark Murray     { "524init", 	'4', arg_flag, &get_v4_tgt,
65b528cefcSMark Murray       "obtain version 4 TGT" },
66b528cefcSMark Murray 
674137ff4cSJacques Vidrine     { "524convert", 	'9', arg_flag, &convert_524,
684137ff4cSJacques Vidrine       "only convert ticket to version 4" },
69bbd80c28SJacques Vidrine #endif
70b528cefcSMark Murray     { "afslog", 	0  , arg_flag, &do_afslog,
71b528cefcSMark Murray       "obtain afs tokens"  },
72bbd80c28SJacques Vidrine 
73b528cefcSMark Murray     { "cache", 		'c', arg_string, &cred_cache,
74b528cefcSMark Murray       "credentials cache", "cachename" },
75b528cefcSMark Murray 
765e9cd1aeSAssar Westerlund     { "forwardable",	'f', arg_flag, &forwardable_flag,
77b528cefcSMark Murray       "get forwardable tickets"},
78b528cefcSMark Murray 
79b528cefcSMark Murray     { "keytab",         't', arg_string, &keytab_str,
80b528cefcSMark Murray       "keytab to use", "keytabname" },
81b528cefcSMark Murray 
82b528cefcSMark Murray     { "lifetime",	'l', arg_string, &lifetime,
835e9cd1aeSAssar Westerlund       "lifetime of tickets", "time"},
84b528cefcSMark Murray 
855e9cd1aeSAssar Westerlund     { "proxiable",	'p', arg_flag, &proxiable_flag,
86b528cefcSMark Murray       "get proxiable tickets" },
87b528cefcSMark Murray 
88b528cefcSMark Murray     { "renew",          'R', arg_flag, &renew_flag,
89b528cefcSMark Murray       "renew TGT" },
90b528cefcSMark Murray 
915e9cd1aeSAssar Westerlund     { "renewable",	0,   arg_flag, &renewable_flag,
92b528cefcSMark Murray       "get renewable tickets" },
93b528cefcSMark Murray 
94b528cefcSMark Murray     { "renewable-life",	'r', arg_string, &renew_life,
955e9cd1aeSAssar Westerlund       "renewable lifetime of tickets", "time" },
96b528cefcSMark Murray 
97b528cefcSMark Murray     { "server", 	'S', arg_string, &server,
98b528cefcSMark Murray       "server to get ticket for", "principal" },
99b528cefcSMark Murray 
100b528cefcSMark Murray     { "start-time",	's', arg_string, &start_str,
1015e9cd1aeSAssar Westerlund       "when ticket gets valid", "time" },
102b528cefcSMark Murray 
103b528cefcSMark Murray     { "use-keytab",     'k', arg_flag, &use_keytab,
104b528cefcSMark Murray       "get key from keytab" },
105b528cefcSMark Murray 
106b528cefcSMark Murray     { "validate",	'v', arg_flag, &validate_flag,
107b528cefcSMark Murray       "validate TGT" },
108b528cefcSMark Murray 
109b528cefcSMark Murray     { "enctypes",	'e', arg_strings, &etype_str,
1105e9cd1aeSAssar Westerlund       "encryption types to use", "enctypes" },
111b528cefcSMark Murray 
112b528cefcSMark Murray     { "fcache-version", 0,   arg_integer, &fcache_version,
113b528cefcSMark Murray       "file cache version to create" },
114b528cefcSMark Murray 
11513e3f4d6SMark Murray     { "addresses",	0,   arg_negative_flag,	&addrs_flag,
116b528cefcSMark Murray       "request a ticket with no addresses" },
117b528cefcSMark Murray 
1188373020dSJacques Vidrine     { "extra-addresses",'a', arg_strings,	&extra_addresses,
1198373020dSJacques Vidrine       "include these extra addresses", "addresses" },
1208373020dSJacques Vidrine 
1215e9cd1aeSAssar Westerlund     { "anonymous",	0,   arg_flag,	&anonymous_flag,
1225e9cd1aeSAssar Westerlund       "request an anonymous ticket" },
1235e9cd1aeSAssar Westerlund 
124b528cefcSMark Murray     { "version", 	0,   arg_flag, &version_flag },
125b528cefcSMark Murray     { "help",		0,   arg_flag, &help_flag }
126b528cefcSMark Murray };
127b528cefcSMark Murray 
128b528cefcSMark Murray static void
129b528cefcSMark Murray usage (int ret)
130b528cefcSMark Murray {
131b528cefcSMark Murray     arg_printusage (args,
132b528cefcSMark Murray 		    sizeof(args)/sizeof(*args),
133b528cefcSMark Murray 		    NULL,
134adb0ddaeSAssar Westerlund 		    "[principal [command]]");
135b528cefcSMark Murray     exit (ret);
136b528cefcSMark Murray }
137b528cefcSMark Murray 
1384137ff4cSJacques Vidrine #ifdef KRB4
1394137ff4cSJacques Vidrine /* for when the KDC tells us it's a v4 one, we try to talk that */
1404137ff4cSJacques Vidrine 
1414137ff4cSJacques Vidrine static int
1424137ff4cSJacques Vidrine key_to_key(const char *user,
1434137ff4cSJacques Vidrine 	   char *instance,
1444137ff4cSJacques Vidrine 	   const char *realm,
1454137ff4cSJacques Vidrine 	   const void *arg,
1464137ff4cSJacques Vidrine 	   des_cblock *key)
1474137ff4cSJacques Vidrine {
1484137ff4cSJacques Vidrine     memcpy(key, arg, sizeof(des_cblock));
1494137ff4cSJacques Vidrine     return 0;
1504137ff4cSJacques Vidrine }
1514137ff4cSJacques Vidrine 
1524137ff4cSJacques Vidrine static int
1534137ff4cSJacques Vidrine do_v4_fallback (krb5_context context,
1544137ff4cSJacques Vidrine 		const krb5_principal principal,
1554137ff4cSJacques Vidrine 		int lifetime,
1564137ff4cSJacques Vidrine 		int use_srvtab, const char *srvtab_str,
1574137ff4cSJacques Vidrine 		const char *passwd)
1584137ff4cSJacques Vidrine {
1594137ff4cSJacques Vidrine     int ret;
1604137ff4cSJacques Vidrine     krb_principal princ;
1614137ff4cSJacques Vidrine     des_cblock key;
1624137ff4cSJacques Vidrine     krb5_error_code kret;
1634137ff4cSJacques Vidrine 
1644137ff4cSJacques Vidrine     if (lifetime == 0)
1654137ff4cSJacques Vidrine 	lifetime = DEFAULT_TKT_LIFE;
1664137ff4cSJacques Vidrine     else
1674137ff4cSJacques Vidrine 	lifetime = krb_time_to_life (0, lifetime);
1684137ff4cSJacques Vidrine 
1694137ff4cSJacques Vidrine     kret = krb5_524_conv_principal (context, principal,
1704137ff4cSJacques Vidrine 				    princ.name,
1714137ff4cSJacques Vidrine 				    princ.instance,
1724137ff4cSJacques Vidrine 				    princ.realm);
1734137ff4cSJacques Vidrine     if (kret) {
1744137ff4cSJacques Vidrine 	krb5_warn (context, kret, "krb5_524_conv_principal");
1754137ff4cSJacques Vidrine 	return 1;
1764137ff4cSJacques Vidrine     }
1774137ff4cSJacques Vidrine 
1784137ff4cSJacques Vidrine     if (use_srvtab || srvtab_str) {
1794137ff4cSJacques Vidrine 	if (srvtab_str == NULL)
1804137ff4cSJacques Vidrine 	    srvtab_str = KEYFILE;
1814137ff4cSJacques Vidrine 
1824137ff4cSJacques Vidrine 	ret = read_service_key (princ.name, princ.instance, princ.realm,
1834137ff4cSJacques Vidrine 				0, srvtab_str, (char *)&key);
1844137ff4cSJacques Vidrine 	if (ret) {
1854137ff4cSJacques Vidrine 	    warnx ("read_service_key %s: %s", srvtab_str,
1864137ff4cSJacques Vidrine 		   krb_get_err_text (ret));
1874137ff4cSJacques Vidrine 	    return 1;
1884137ff4cSJacques Vidrine 	}
1894137ff4cSJacques Vidrine 	ret = krb_get_in_tkt (princ.name, princ.instance, princ.realm,
1904137ff4cSJacques Vidrine 			      KRB_TICKET_GRANTING_TICKET, princ.realm,
1914137ff4cSJacques Vidrine 			      lifetime, key_to_key, NULL, key);
1924137ff4cSJacques Vidrine     } else {
1938373020dSJacques Vidrine 	ret = krb_get_pw_in_tkt(princ.name, princ.instance, princ.realm,
1944137ff4cSJacques Vidrine 				KRB_TICKET_GRANTING_TICKET, princ.realm,
1958373020dSJacques Vidrine 				lifetime, passwd);
1964137ff4cSJacques Vidrine     }
1974137ff4cSJacques Vidrine     memset (key, 0, sizeof(key));
1984137ff4cSJacques Vidrine     if (ret) {
1994137ff4cSJacques Vidrine 	warnx ("%s", krb_get_err_text(ret));
2004137ff4cSJacques Vidrine 	return 1;
2014137ff4cSJacques Vidrine     }
2024137ff4cSJacques Vidrine     if (do_afslog && k_hasafs()) {
2034137ff4cSJacques Vidrine 	if ((ret = krb_afslog(NULL, NULL)) != 0 && ret != KDC_PR_UNKNOWN) {
2044137ff4cSJacques Vidrine 	    if(ret > 0)
2054137ff4cSJacques Vidrine 		warnx ("%s", krb_get_err_text(ret));
2064137ff4cSJacques Vidrine 	    else
2074137ff4cSJacques Vidrine 		warnx ("failed to store AFS token");
2084137ff4cSJacques Vidrine 	}
2094137ff4cSJacques Vidrine     }
2104137ff4cSJacques Vidrine     return 0;
2114137ff4cSJacques Vidrine }
2124137ff4cSJacques Vidrine 
2134137ff4cSJacques Vidrine 
2144137ff4cSJacques Vidrine /*
2154137ff4cSJacques Vidrine  * the special version of get_default_principal that takes v4 into account
2164137ff4cSJacques Vidrine  */
2174137ff4cSJacques Vidrine 
2184137ff4cSJacques Vidrine static krb5_error_code
2194137ff4cSJacques Vidrine kinit_get_default_principal (krb5_context context,
2204137ff4cSJacques Vidrine 			     krb5_principal *princ)
2214137ff4cSJacques Vidrine {
2224137ff4cSJacques Vidrine     krb5_error_code ret;
2234137ff4cSJacques Vidrine     krb5_ccache id;
2244137ff4cSJacques Vidrine     krb_principal v4_princ;
2254137ff4cSJacques Vidrine     int kret;
2264137ff4cSJacques Vidrine 
2274137ff4cSJacques Vidrine     ret = krb5_cc_default (context, &id);
2284137ff4cSJacques Vidrine     if (ret == 0) {
2294137ff4cSJacques Vidrine 	ret = krb5_cc_get_principal (context, id, princ);
2304137ff4cSJacques Vidrine 	krb5_cc_close (context, id);
2314137ff4cSJacques Vidrine 	if (ret == 0)
2324137ff4cSJacques Vidrine 	    return 0;
2334137ff4cSJacques Vidrine     }
2344137ff4cSJacques Vidrine 
2354137ff4cSJacques Vidrine     kret = krb_get_tf_fullname (tkt_string(),
2364137ff4cSJacques Vidrine 				v4_princ.name,
2374137ff4cSJacques Vidrine 				v4_princ.instance,
2384137ff4cSJacques Vidrine 				v4_princ.realm);
2394137ff4cSJacques Vidrine     if (kret == KSUCCESS) {
2404137ff4cSJacques Vidrine 	ret = krb5_425_conv_principal (context,
2414137ff4cSJacques Vidrine 				       v4_princ.name,
2424137ff4cSJacques Vidrine 				       v4_princ.instance,
2434137ff4cSJacques Vidrine 				       v4_princ.realm,
2444137ff4cSJacques Vidrine 				       princ);
2454137ff4cSJacques Vidrine 	if (ret == 0)
2464137ff4cSJacques Vidrine 	    return 0;
2474137ff4cSJacques Vidrine     }
2484137ff4cSJacques Vidrine     return krb5_get_default_principal (context, princ);
2494137ff4cSJacques Vidrine }
2504137ff4cSJacques Vidrine 
2514137ff4cSJacques Vidrine #else /* !KRB4 */
2524137ff4cSJacques Vidrine 
2534137ff4cSJacques Vidrine static krb5_error_code
2544137ff4cSJacques Vidrine kinit_get_default_principal (krb5_context context,
2554137ff4cSJacques Vidrine 			     krb5_principal *princ)
2564137ff4cSJacques Vidrine {
2574137ff4cSJacques Vidrine     return krb5_get_default_principal (context, princ);
2584137ff4cSJacques Vidrine }
2594137ff4cSJacques Vidrine 
2604137ff4cSJacques Vidrine #endif /* !KRB4 */
2614137ff4cSJacques Vidrine 
2624137ff4cSJacques Vidrine static krb5_error_code
2634137ff4cSJacques Vidrine get_server(krb5_context context,
2644137ff4cSJacques Vidrine 	   krb5_principal client,
2654137ff4cSJacques Vidrine 	   const char *server,
2664137ff4cSJacques Vidrine 	   krb5_principal *princ)
2674137ff4cSJacques Vidrine {
2684137ff4cSJacques Vidrine     krb5_realm *client_realm;
2694137ff4cSJacques Vidrine     if(server)
2704137ff4cSJacques Vidrine 	return krb5_parse_name(context, server, princ);
2714137ff4cSJacques Vidrine 
2724137ff4cSJacques Vidrine     client_realm = krb5_princ_realm (context, client);
2734137ff4cSJacques Vidrine     return krb5_make_principal(context, princ, *client_realm,
2744137ff4cSJacques Vidrine 			       KRB5_TGS_NAME, *client_realm, NULL);
2754137ff4cSJacques Vidrine }
2764137ff4cSJacques Vidrine 
2774137ff4cSJacques Vidrine #ifdef KRB4
2784137ff4cSJacques Vidrine static krb5_error_code
2794137ff4cSJacques Vidrine do_524init(krb5_context context, krb5_ccache ccache,
2804137ff4cSJacques Vidrine 	   krb5_creds *creds, const char *server)
2814137ff4cSJacques Vidrine {
2824137ff4cSJacques Vidrine     krb5_error_code ret;
2834137ff4cSJacques Vidrine     CREDENTIALS c;
2844137ff4cSJacques Vidrine     krb5_creds in_creds, *real_creds;
2854137ff4cSJacques Vidrine 
2864137ff4cSJacques Vidrine     if(creds != NULL)
2874137ff4cSJacques Vidrine 	real_creds = creds;
2884137ff4cSJacques Vidrine     else {
2894137ff4cSJacques Vidrine 	krb5_principal client;
2904137ff4cSJacques Vidrine 	krb5_cc_get_principal(context, ccache, &client);
2914137ff4cSJacques Vidrine 	memset(&in_creds, 0, sizeof(in_creds));
2924137ff4cSJacques Vidrine 	ret = get_server(context, client, server, &in_creds.server);
2931c43270aSJacques Vidrine 	if(ret) {
2940cadf2f4SJacques Vidrine 	    krb5_free_principal(context, client);
2954137ff4cSJacques Vidrine 	    return ret;
2961c43270aSJacques Vidrine 	}
2971c43270aSJacques Vidrine 	in_creds.client = client;
2984137ff4cSJacques Vidrine 	ret = krb5_get_credentials(context, 0, ccache, &in_creds, &real_creds);
2991c43270aSJacques Vidrine 	krb5_free_principal(context, client);
3000cadf2f4SJacques Vidrine 	krb5_free_principal(context, in_creds.server);
3014137ff4cSJacques Vidrine 	if(ret)
3024137ff4cSJacques Vidrine 	    return ret;
3034137ff4cSJacques Vidrine     }
3044137ff4cSJacques Vidrine     ret = krb524_convert_creds_kdc_ccache(context, ccache, real_creds, &c);
3054137ff4cSJacques Vidrine     if(ret)
3064137ff4cSJacques Vidrine 	krb5_warn(context, ret, "converting creds");
3074137ff4cSJacques Vidrine     else {
3084137ff4cSJacques Vidrine 	int tret = tf_setup(&c, c.pname, c.pinst);
3094137ff4cSJacques Vidrine 	if(tret)
3104137ff4cSJacques Vidrine 	    krb5_warnx(context, "saving v4 creds: %s", krb_get_err_text(tret));
3114137ff4cSJacques Vidrine     }
3124137ff4cSJacques Vidrine 
3134137ff4cSJacques Vidrine     if(creds == NULL)
3144137ff4cSJacques Vidrine 	krb5_free_creds(context, real_creds);
3154137ff4cSJacques Vidrine     memset(&c, 0, sizeof(c));
3164137ff4cSJacques Vidrine 
3174137ff4cSJacques Vidrine     return ret;
3184137ff4cSJacques Vidrine }
3194137ff4cSJacques Vidrine #endif
3204137ff4cSJacques Vidrine 
321b528cefcSMark Murray static int
322b528cefcSMark Murray renew_validate(krb5_context context,
323b528cefcSMark Murray 	       int renew,
324b528cefcSMark Murray 	       int validate,
325b528cefcSMark Murray 	       krb5_ccache cache,
326b528cefcSMark Murray 	       const char *server,
327b528cefcSMark Murray 	       krb5_deltat life)
328b528cefcSMark Murray {
329b528cefcSMark Murray     krb5_error_code ret;
330b528cefcSMark Murray     krb5_creds in, *out;
331b528cefcSMark Murray     krb5_kdc_flags flags;
332b528cefcSMark Murray 
333b528cefcSMark Murray     memset(&in, 0, sizeof(in));
334b528cefcSMark Murray 
335b528cefcSMark Murray     ret = krb5_cc_get_principal(context, cache, &in.client);
336b528cefcSMark Murray     if(ret) {
337b528cefcSMark Murray 	krb5_warn(context, ret, "krb5_cc_get_principal");
338b528cefcSMark Murray 	return ret;
339b528cefcSMark Murray     }
3404137ff4cSJacques Vidrine     ret = get_server(context, in.client, server, &in.server);
341b528cefcSMark Murray     if(ret) {
3424137ff4cSJacques Vidrine 	krb5_warn(context, ret, "get_server");
343b528cefcSMark Murray 	goto out;
344b528cefcSMark Murray     }
345b528cefcSMark Murray     flags.i = 0;
346b528cefcSMark Murray     flags.b.renewable         = flags.b.renew = renew;
347b528cefcSMark Murray     flags.b.validate          = validate;
348adb0ddaeSAssar Westerlund     if (forwardable_flag != -1)
3495e9cd1aeSAssar Westerlund 	flags.b.forwardable       = forwardable_flag;
350adb0ddaeSAssar Westerlund     if (proxiable_flag != -1)
3515e9cd1aeSAssar Westerlund 	flags.b.proxiable         = proxiable_flag;
352adb0ddaeSAssar Westerlund     if (anonymous_flag != -1)
3535e9cd1aeSAssar Westerlund 	flags.b.request_anonymous = anonymous_flag;
354b528cefcSMark Murray     if(life)
355b528cefcSMark Murray 	in.times.endtime = time(NULL) + life;
356b528cefcSMark Murray 
357b528cefcSMark Murray     ret = krb5_get_kdc_cred(context,
358b528cefcSMark Murray 			    cache,
359b528cefcSMark Murray 			    flags,
360b528cefcSMark Murray 			    NULL,
361b528cefcSMark Murray 			    NULL,
362b528cefcSMark Murray 			    &in,
363b528cefcSMark Murray 			    &out);
364b528cefcSMark Murray     if(ret) {
365b528cefcSMark Murray 	krb5_warn(context, ret, "krb5_get_kdc_cred");
366b528cefcSMark Murray 	goto out;
367b528cefcSMark Murray     }
368b528cefcSMark Murray     ret = krb5_cc_initialize(context, cache, in.client);
369b528cefcSMark Murray     if(ret) {
370b528cefcSMark Murray 	krb5_free_creds (context, out);
371b528cefcSMark Murray 	krb5_warn(context, ret, "krb5_cc_initialize");
372b528cefcSMark Murray 	goto out;
373b528cefcSMark Murray     }
374b528cefcSMark Murray     ret = krb5_cc_store_cred(context, cache, out);
3754137ff4cSJacques Vidrine 
3764137ff4cSJacques Vidrine     if(ret == 0 && server == NULL) {
377bbd80c28SJacques Vidrine #ifdef KRB4
3784137ff4cSJacques Vidrine 	/* only do this if it's a general renew-my-tgt request */
3794137ff4cSJacques Vidrine 	if(get_v4_tgt)
3804137ff4cSJacques Vidrine 	    do_524init(context, cache, out, NULL);
381bbd80c28SJacques Vidrine #endif
3824137ff4cSJacques Vidrine 	if(do_afslog && k_hasafs())
3834137ff4cSJacques Vidrine 	    krb5_afslog(context, cache, NULL, NULL);
3844137ff4cSJacques Vidrine     }
3854137ff4cSJacques Vidrine 
386b528cefcSMark Murray     krb5_free_creds (context, out);
387b528cefcSMark Murray     if(ret) {
388b528cefcSMark Murray 	krb5_warn(context, ret, "krb5_cc_store_cred");
389b528cefcSMark Murray 	goto out;
390b528cefcSMark Murray     }
391b528cefcSMark Murray out:
392b528cefcSMark Murray     krb5_free_creds_contents(context, &in);
393b528cefcSMark Murray     return ret;
394b528cefcSMark Murray }
395b528cefcSMark Murray 
3964137ff4cSJacques Vidrine static krb5_error_code
3974137ff4cSJacques Vidrine get_new_tickets(krb5_context context,
3984137ff4cSJacques Vidrine 		krb5_principal principal,
3994137ff4cSJacques Vidrine 		krb5_ccache ccache,
4004137ff4cSJacques Vidrine 		krb5_deltat ticket_life)
401b528cefcSMark Murray {
402b528cefcSMark Murray     krb5_error_code ret;
403b528cefcSMark Murray     krb5_get_init_creds_opt opt;
404b528cefcSMark Murray     krb5_addresses no_addrs;
4054137ff4cSJacques Vidrine     krb5_creds cred;
4065e9cd1aeSAssar Westerlund     char passwd[256];
4074137ff4cSJacques Vidrine     krb5_deltat start_time = 0;
4088373020dSJacques Vidrine     krb5_deltat renew = 0;
409b528cefcSMark Murray 
410b528cefcSMark Murray     memset(&cred, 0, sizeof(cred));
411b528cefcSMark Murray 
412b528cefcSMark Murray     krb5_get_init_creds_opt_init (&opt);
413b528cefcSMark Murray 
4145e9cd1aeSAssar Westerlund     krb5_get_init_creds_opt_set_default_flags(context, "kinit",
4155e9cd1aeSAssar Westerlund 					      /* XXX */principal->realm, &opt);
4165e9cd1aeSAssar Westerlund 
4175e9cd1aeSAssar Westerlund     if(forwardable_flag != -1)
4185e9cd1aeSAssar Westerlund 	krb5_get_init_creds_opt_set_forwardable (&opt, forwardable_flag);
4195e9cd1aeSAssar Westerlund     if(proxiable_flag != -1)
4205e9cd1aeSAssar Westerlund 	krb5_get_init_creds_opt_set_proxiable (&opt, proxiable_flag);
4215e9cd1aeSAssar Westerlund     if(anonymous_flag != -1)
4225e9cd1aeSAssar Westerlund 	krb5_get_init_creds_opt_set_anonymous (&opt, anonymous_flag);
423b528cefcSMark Murray 
42413e3f4d6SMark Murray     if (!addrs_flag) {
425b528cefcSMark Murray 	no_addrs.len = 0;
426b528cefcSMark Murray 	no_addrs.val = NULL;
427b528cefcSMark Murray 
428b528cefcSMark Murray 	krb5_get_init_creds_opt_set_address_list (&opt, &no_addrs);
429b528cefcSMark Murray     }
430b528cefcSMark Murray 
4311c43270aSJacques Vidrine     if (renew_life == NULL && renewable_flag)
4321c43270aSJacques Vidrine 	renew_life = "1 month";
433b528cefcSMark Murray     if(renew_life) {
4348373020dSJacques Vidrine 	renew = parse_time (renew_life, "s");
4358373020dSJacques Vidrine 	if (renew < 0)
436b528cefcSMark Murray 	    errx (1, "unparsable time: %s", renew_life);
437b528cefcSMark Murray 
4388373020dSJacques Vidrine 	krb5_get_init_creds_opt_set_renew_life (&opt, renew);
4391c43270aSJacques Vidrine     }
4408373020dSJacques Vidrine 
441b528cefcSMark Murray     if(ticket_life != 0)
442b528cefcSMark Murray 	krb5_get_init_creds_opt_set_tkt_life (&opt, ticket_life);
443b528cefcSMark Murray 
444b528cefcSMark Murray     if(start_str) {
445b528cefcSMark Murray 	int tmp = parse_time (start_str, "s");
446b528cefcSMark Murray 	if (tmp < 0)
447b528cefcSMark Murray 	    errx (1, "unparsable time: %s", start_str);
448b528cefcSMark Murray 
449b528cefcSMark Murray 	start_time = tmp;
450b528cefcSMark Murray     }
451b528cefcSMark Murray 
452b528cefcSMark Murray     if(etype_str.num_strings) {
453b528cefcSMark Murray 	krb5_enctype *enctype = NULL;
454b528cefcSMark Murray 	int i;
455b528cefcSMark Murray 	enctype = malloc(etype_str.num_strings * sizeof(*enctype));
456b528cefcSMark Murray 	if(enctype == NULL)
457b528cefcSMark Murray 	    errx(1, "out of memory");
458b528cefcSMark Murray 	for(i = 0; i < etype_str.num_strings; i++) {
459b528cefcSMark Murray 	    ret = krb5_string_to_enctype(context,
460b528cefcSMark Murray 					 etype_str.strings[i],
461b528cefcSMark Murray 					 &enctype[i]);
462b528cefcSMark Murray 	    if(ret)
463b528cefcSMark Murray 		errx(1, "unrecognized enctype: %s", etype_str.strings[i]);
464b528cefcSMark Murray 	}
465b528cefcSMark Murray 	krb5_get_init_creds_opt_set_etype_list(&opt, enctype,
466b528cefcSMark Murray 					       etype_str.num_strings);
467b528cefcSMark Murray     }
468b528cefcSMark Murray 
469b528cefcSMark Murray     if(use_keytab || keytab_str) {
470b528cefcSMark Murray 	krb5_keytab kt;
471b528cefcSMark Murray 	if(keytab_str)
472b528cefcSMark Murray 	    ret = krb5_kt_resolve(context, keytab_str, &kt);
473b528cefcSMark Murray 	else
474b528cefcSMark Murray 	    ret = krb5_kt_default(context, &kt);
475b528cefcSMark Murray 	if (ret)
476b528cefcSMark Murray 	    krb5_err (context, 1, ret, "resolving keytab");
477b528cefcSMark Murray 	ret = krb5_get_init_creds_keytab (context,
478b528cefcSMark Murray 					  &cred,
479b528cefcSMark Murray 					  principal,
480b528cefcSMark Murray 					  kt,
481b528cefcSMark Murray 					  start_time,
482b528cefcSMark Murray 					  server,
483b528cefcSMark Murray 					  &opt);
484b528cefcSMark Murray 	krb5_kt_close(context, kt);
4855e9cd1aeSAssar Westerlund     } else {
4865e9cd1aeSAssar Westerlund 	char *p, *prompt;
4875e9cd1aeSAssar Westerlund 
4885e9cd1aeSAssar Westerlund 	krb5_unparse_name (context, principal, &p);
4895e9cd1aeSAssar Westerlund 	asprintf (&prompt, "%s's Password: ", p);
4905e9cd1aeSAssar Westerlund 	free (p);
4915e9cd1aeSAssar Westerlund 
4925e9cd1aeSAssar Westerlund 	if (des_read_pw_string(passwd, sizeof(passwd)-1, prompt, 0)){
4935e9cd1aeSAssar Westerlund 	    memset(passwd, 0, sizeof(passwd));
4945e9cd1aeSAssar Westerlund 	    exit(1);
4955e9cd1aeSAssar Westerlund 	}
4965e9cd1aeSAssar Westerlund 
4975e9cd1aeSAssar Westerlund 	free (prompt);
4985e9cd1aeSAssar Westerlund 
499b528cefcSMark Murray 	ret = krb5_get_init_creds_password (context,
500b528cefcSMark Murray 					    &cred,
501b528cefcSMark Murray 					    principal,
5025e9cd1aeSAssar Westerlund 					    passwd,
503b528cefcSMark Murray 					    krb5_prompter_posix,
504b528cefcSMark Murray 					    NULL,
505b528cefcSMark Murray 					    start_time,
506b528cefcSMark Murray 					    server,
507b528cefcSMark Murray 					    &opt);
5085e9cd1aeSAssar Westerlund     }
5095e9cd1aeSAssar Westerlund #ifdef KRB4
5105e9cd1aeSAssar Westerlund     if (ret == KRB5KRB_AP_ERR_V4_REPLY || ret == KRB5_KDC_UNREACH) {
5115e9cd1aeSAssar Westerlund 	int exit_val;
5125e9cd1aeSAssar Westerlund 
5135e9cd1aeSAssar Westerlund 	exit_val = do_v4_fallback (context, principal, ticket_life,
5144137ff4cSJacques Vidrine 				   use_keytab, keytab_str, passwd);
5154137ff4cSJacques Vidrine 	get_v4_tgt = 0;
5164137ff4cSJacques Vidrine 	do_afslog  = 0;
5175e9cd1aeSAssar Westerlund 	memset(passwd, 0, sizeof(passwd));
5184137ff4cSJacques Vidrine 	if (exit_val == 0 || ret == KRB5KRB_AP_ERR_V4_REPLY)
5195e9cd1aeSAssar Westerlund 	    return exit_val;
5205e9cd1aeSAssar Westerlund     }
5215e9cd1aeSAssar Westerlund #endif
5225e9cd1aeSAssar Westerlund     memset(passwd, 0, sizeof(passwd));
5235e9cd1aeSAssar Westerlund 
524b528cefcSMark Murray     switch(ret){
525b528cefcSMark Murray     case 0:
526b528cefcSMark Murray 	break;
527b528cefcSMark Murray     case KRB5_LIBOS_PWDINTR: /* don't print anything if it was just C-c:ed */
528b528cefcSMark Murray 	exit(1);
529b528cefcSMark Murray     case KRB5KRB_AP_ERR_BAD_INTEGRITY:
530b528cefcSMark Murray     case KRB5KRB_AP_ERR_MODIFIED:
531b528cefcSMark Murray 	krb5_errx(context, 1, "Password incorrect");
532b528cefcSMark Murray 	break;
533b528cefcSMark Murray     default:
534b528cefcSMark Murray 	krb5_err(context, 1, ret, "krb5_get_init_creds");
535b528cefcSMark Murray     }
536b528cefcSMark Murray 
5378373020dSJacques Vidrine     if(ticket_life != 0) {
5388373020dSJacques Vidrine 	if(abs(cred.times.endtime - cred.times.starttime - ticket_life) > 30) {
5398373020dSJacques Vidrine 	    char life[32];
5408373020dSJacques Vidrine 	    unparse_time(cred.times.endtime - cred.times.starttime,
5418373020dSJacques Vidrine 			 life, sizeof(life));
5428373020dSJacques Vidrine 	    krb5_warnx(context, "NOTICE: ticket lifetime is %s", life);
5438373020dSJacques Vidrine 	}
5448373020dSJacques Vidrine     }
5458373020dSJacques Vidrine     if(renew != 0) {
5468373020dSJacques Vidrine 	if(abs(cred.times.renew_till - cred.times.starttime - renew) > 30) {
5478373020dSJacques Vidrine 	    char life[32];
5488373020dSJacques Vidrine 	    unparse_time(cred.times.renew_till - cred.times.starttime,
5498373020dSJacques Vidrine 			 life, sizeof(life));
5508373020dSJacques Vidrine 	    krb5_warnx(context, "NOTICE: ticket renewable lifetime is %s",
5518373020dSJacques Vidrine 		       life);
5528373020dSJacques Vidrine 	}
5538373020dSJacques Vidrine     }
5548373020dSJacques Vidrine 
555b528cefcSMark Murray     ret = krb5_cc_initialize (context, ccache, cred.client);
556b528cefcSMark Murray     if (ret)
557b528cefcSMark Murray 	krb5_err (context, 1, ret, "krb5_cc_initialize");
558b528cefcSMark Murray 
559b528cefcSMark Murray     ret = krb5_cc_store_cred (context, ccache, &cred);
560b528cefcSMark Murray     if (ret)
561b528cefcSMark Murray 	krb5_err (context, 1, ret, "krb5_cc_store_cred");
562b528cefcSMark Murray 
5634137ff4cSJacques Vidrine     krb5_free_creds_contents (context, &cred);
5644137ff4cSJacques Vidrine 
5654137ff4cSJacques Vidrine     return 0;
566b528cefcSMark Murray }
5674137ff4cSJacques Vidrine 
5684137ff4cSJacques Vidrine int
5694137ff4cSJacques Vidrine main (int argc, char **argv)
5704137ff4cSJacques Vidrine {
5714137ff4cSJacques Vidrine     krb5_error_code ret;
5724137ff4cSJacques Vidrine     krb5_context context;
5734137ff4cSJacques Vidrine     krb5_ccache  ccache;
5744137ff4cSJacques Vidrine     krb5_principal principal;
5754137ff4cSJacques Vidrine     int optind = 0;
5764137ff4cSJacques Vidrine     krb5_deltat ticket_life = 0;
5774137ff4cSJacques Vidrine 
5784137ff4cSJacques Vidrine     setprogname (argv[0]);
5794137ff4cSJacques Vidrine 
5804137ff4cSJacques Vidrine     ret = krb5_init_context (&context);
5814137ff4cSJacques Vidrine     if (ret)
5824137ff4cSJacques Vidrine 	errx(1, "krb5_init_context failed: %d", ret);
5834137ff4cSJacques Vidrine 
5844137ff4cSJacques Vidrine     if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind))
5854137ff4cSJacques Vidrine 	usage(1);
5864137ff4cSJacques Vidrine 
5874137ff4cSJacques Vidrine     if (help_flag)
5884137ff4cSJacques Vidrine 	usage (0);
5894137ff4cSJacques Vidrine 
5904137ff4cSJacques Vidrine     if(version_flag) {
5914137ff4cSJacques Vidrine 	print_version(NULL);
5924137ff4cSJacques Vidrine 	exit(0);
5934137ff4cSJacques Vidrine     }
5944137ff4cSJacques Vidrine 
5954137ff4cSJacques Vidrine     argc -= optind;
5964137ff4cSJacques Vidrine     argv += optind;
5974137ff4cSJacques Vidrine 
5984137ff4cSJacques Vidrine     if (argv[0]) {
5994137ff4cSJacques Vidrine 	ret = krb5_parse_name (context, argv[0], &principal);
6004137ff4cSJacques Vidrine 	if (ret)
6014137ff4cSJacques Vidrine 	    krb5_err (context, 1, ret, "krb5_parse_name");
6024137ff4cSJacques Vidrine     } else {
6034137ff4cSJacques Vidrine 	ret = kinit_get_default_principal (context, &principal);
6044137ff4cSJacques Vidrine 	if (ret)
6054137ff4cSJacques Vidrine 	    krb5_err (context, 1, ret, "krb5_get_default_principal");
6064137ff4cSJacques Vidrine     }
6074137ff4cSJacques Vidrine 
6084137ff4cSJacques Vidrine     if(fcache_version)
6094137ff4cSJacques Vidrine 	krb5_set_fcache_version(context, fcache_version);
6104137ff4cSJacques Vidrine 
6114137ff4cSJacques Vidrine     if(cred_cache)
6124137ff4cSJacques Vidrine 	ret = krb5_cc_resolve(context, cred_cache, &ccache);
6134137ff4cSJacques Vidrine     else {
6144137ff4cSJacques Vidrine 	if(argc > 1) {
6154137ff4cSJacques Vidrine 	    char s[1024];
6164137ff4cSJacques Vidrine 	    ret = krb5_cc_gen_new(context, &krb5_fcc_ops, &ccache);
6174137ff4cSJacques Vidrine 	    if(ret)
6184137ff4cSJacques Vidrine 		krb5_err(context, 1, ret, "creating cred cache");
6194137ff4cSJacques Vidrine 	    snprintf(s, sizeof(s), "%s:%s",
6204137ff4cSJacques Vidrine 		     krb5_cc_get_type(context, ccache),
6214137ff4cSJacques Vidrine 		     krb5_cc_get_name(context, ccache));
6224137ff4cSJacques Vidrine 	    setenv("KRB5CCNAME", s, 1);
6234137ff4cSJacques Vidrine #ifdef KRB4
6244137ff4cSJacques Vidrine 	    {
6254137ff4cSJacques Vidrine 		int fd;
6264137ff4cSJacques Vidrine 		snprintf(s, sizeof(s), "%s_XXXXXX", TKT_ROOT);
6274137ff4cSJacques Vidrine 		if((fd = mkstemp(s)) >= 0) {
6284137ff4cSJacques Vidrine 		    close(fd);
6294137ff4cSJacques Vidrine 		    setenv("KRBTKFILE", s, 1);
6304137ff4cSJacques Vidrine 		    if (k_hasafs ())
6314137ff4cSJacques Vidrine 			k_setpag();
6324137ff4cSJacques Vidrine 		}
6334137ff4cSJacques Vidrine 	    }
6344137ff4cSJacques Vidrine #endif
6354137ff4cSJacques Vidrine 	} else
6364137ff4cSJacques Vidrine 	    ret = krb5_cc_default (context, &ccache);
6374137ff4cSJacques Vidrine     }
6384137ff4cSJacques Vidrine     if (ret)
6394137ff4cSJacques Vidrine 	krb5_err (context, 1, ret, "resolving credentials cache");
6404137ff4cSJacques Vidrine 
6414137ff4cSJacques Vidrine     if (lifetime) {
6424137ff4cSJacques Vidrine 	int tmp = parse_time (lifetime, "s");
6434137ff4cSJacques Vidrine 	if (tmp < 0)
6444137ff4cSJacques Vidrine 	    errx (1, "unparsable time: %s", lifetime);
6454137ff4cSJacques Vidrine 
6464137ff4cSJacques Vidrine 	ticket_life = tmp;
6474137ff4cSJacques Vidrine     }
6484137ff4cSJacques Vidrine #ifdef KRB4
6494137ff4cSJacques Vidrine     if(get_v4_tgt == -1)
6504137ff4cSJacques Vidrine 	krb5_appdefault_boolean(context, "kinit",
6514137ff4cSJacques Vidrine 				krb5_principal_get_realm(context, principal),
6524137ff4cSJacques Vidrine 				"krb4_get_tickets", TRUE, &get_v4_tgt);
653bbd80c28SJacques Vidrine #endif
6544137ff4cSJacques Vidrine     if(do_afslog == -1)
6554137ff4cSJacques Vidrine 	krb5_appdefault_boolean(context, "kinit",
6564137ff4cSJacques Vidrine 				krb5_principal_get_realm(context, principal),
6574137ff4cSJacques Vidrine 				"afslog", TRUE, &do_afslog);
6584137ff4cSJacques Vidrine 
6598373020dSJacques Vidrine     if(!addrs_flag && extra_addresses.num_strings > 0)
6608373020dSJacques Vidrine 	krb5_errx(context, 1, "specifying both extra addresses and "
6618373020dSJacques Vidrine 		  "no addresses makes no sense");
6628373020dSJacques Vidrine     {
6638373020dSJacques Vidrine 	int i;
6648373020dSJacques Vidrine 	krb5_addresses addresses;
6658373020dSJacques Vidrine 	memset(&addresses, 0, sizeof(addresses));
6668373020dSJacques Vidrine 	for(i = 0; i < extra_addresses.num_strings; i++) {
6678373020dSJacques Vidrine 	    ret = krb5_parse_address(context, extra_addresses.strings[i],
6688373020dSJacques Vidrine 				     &addresses);
6698373020dSJacques Vidrine 	    if (ret == 0) {
6708373020dSJacques Vidrine 		krb5_add_extra_addresses(context, &addresses);
6718373020dSJacques Vidrine 		krb5_free_addresses(context, &addresses);
6728373020dSJacques Vidrine 	    }
6738373020dSJacques Vidrine 	}
6748373020dSJacques Vidrine 	free_getarg_strings(&extra_addresses);
6758373020dSJacques Vidrine     }
6768373020dSJacques Vidrine 
6774137ff4cSJacques Vidrine 
6784137ff4cSJacques Vidrine     if(renew_flag || validate_flag) {
6794137ff4cSJacques Vidrine 	ret = renew_validate(context, renew_flag, validate_flag,
6804137ff4cSJacques Vidrine 			     ccache, server, ticket_life);
6814137ff4cSJacques Vidrine 	exit(ret != 0);
6824137ff4cSJacques Vidrine     }
6834137ff4cSJacques Vidrine 
6844137ff4cSJacques Vidrine #ifdef KRB4
6854137ff4cSJacques Vidrine     if(!convert_524)
6864137ff4cSJacques Vidrine #endif
6874137ff4cSJacques Vidrine 	get_new_tickets(context, principal, ccache, ticket_life);
6884137ff4cSJacques Vidrine 
6894137ff4cSJacques Vidrine #ifdef KRB4
6904137ff4cSJacques Vidrine     if(get_v4_tgt)
6914137ff4cSJacques Vidrine 	do_524init(context, ccache, NULL, server);
692bbd80c28SJacques Vidrine #endif
693b528cefcSMark Murray     if(do_afslog && k_hasafs())
694b528cefcSMark Murray 	krb5_afslog(context, ccache, NULL, NULL);
695adb0ddaeSAssar Westerlund     if(argc > 1) {
6961c43270aSJacques Vidrine 	ret = simple_execvp(argv[1], argv+1);
697adb0ddaeSAssar Westerlund 	krb5_cc_destroy(context, ccache);
698adb0ddaeSAssar Westerlund #ifdef KRB4
699adb0ddaeSAssar Westerlund 	dest_tkt();
700bbd80c28SJacques Vidrine #endif
701adb0ddaeSAssar Westerlund 	if(k_hasafs())
702adb0ddaeSAssar Westerlund 	    k_unlog();
7031c43270aSJacques Vidrine     } else {
704b528cefcSMark Murray 	krb5_cc_close (context, ccache);
7051c43270aSJacques Vidrine 	ret = 0;
7061c43270aSJacques Vidrine     }
7074137ff4cSJacques Vidrine     krb5_free_principal(context, principal);
708b528cefcSMark Murray     krb5_free_context (context);
7091c43270aSJacques Vidrine     return ret;
710b528cefcSMark Murray }
711