xref: /minix3/crypto/external/bsd/heimdal/dist/kuser/kinit.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: kinit.c,v 1.1.1.2 2014/04/24 12:45:28 pettai Exp $	*/
2ebfedea0SLionel Sambuc 
3ebfedea0SLionel Sambuc /*
4ebfedea0SLionel Sambuc  * Copyright (c) 1997-2007 Kungliga Tekniska Högskolan
5ebfedea0SLionel Sambuc  * (Royal Institute of Technology, Stockholm, Sweden).
6ebfedea0SLionel Sambuc  * All rights reserved.
7ebfedea0SLionel Sambuc  *
8ebfedea0SLionel Sambuc  * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
9ebfedea0SLionel Sambuc  *
10ebfedea0SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
11ebfedea0SLionel Sambuc  * modification, are permitted provided that the following conditions
12ebfedea0SLionel Sambuc  * are met:
13ebfedea0SLionel Sambuc  *
14ebfedea0SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
15ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
16ebfedea0SLionel Sambuc  *
17ebfedea0SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
18ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in the
19ebfedea0SLionel Sambuc  *    documentation and/or other materials provided with the distribution.
20ebfedea0SLionel Sambuc  *
21ebfedea0SLionel Sambuc  * 3. Neither the name of the Institute nor the names of its contributors
22ebfedea0SLionel Sambuc  *    may be used to endorse or promote products derived from this software
23ebfedea0SLionel Sambuc  *    without specific prior written permission.
24ebfedea0SLionel Sambuc  *
25ebfedea0SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
26ebfedea0SLionel Sambuc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27ebfedea0SLionel Sambuc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28ebfedea0SLionel Sambuc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
29ebfedea0SLionel Sambuc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30ebfedea0SLionel Sambuc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31ebfedea0SLionel Sambuc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32ebfedea0SLionel Sambuc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33ebfedea0SLionel Sambuc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34ebfedea0SLionel Sambuc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35ebfedea0SLionel Sambuc  * SUCH DAMAGE.
36ebfedea0SLionel Sambuc  */
37ebfedea0SLionel Sambuc 
38ebfedea0SLionel Sambuc #include "kuser_locl.h"
39ebfedea0SLionel Sambuc 
40ebfedea0SLionel Sambuc #ifdef __APPLE__
41ebfedea0SLionel Sambuc #include <Security/Security.h>
42ebfedea0SLionel Sambuc #endif
43ebfedea0SLionel Sambuc 
44ebfedea0SLionel Sambuc #ifndef NO_NTLM
45ebfedea0SLionel Sambuc #include <krb5/heimntlm.h>
46ebfedea0SLionel Sambuc #endif
47ebfedea0SLionel Sambuc 
48ebfedea0SLionel Sambuc int forwardable_flag	= -1;
49ebfedea0SLionel Sambuc int proxiable_flag	= -1;
50ebfedea0SLionel Sambuc int renewable_flag	= -1;
51ebfedea0SLionel Sambuc int renew_flag		= 0;
52ebfedea0SLionel Sambuc int pac_flag		= -1;
53ebfedea0SLionel Sambuc int validate_flag	= 0;
54ebfedea0SLionel Sambuc int version_flag	= 0;
55ebfedea0SLionel Sambuc int help_flag		= 0;
56ebfedea0SLionel Sambuc int addrs_flag		= -1;
57ebfedea0SLionel Sambuc struct getarg_strings extra_addresses;
58ebfedea0SLionel Sambuc int anonymous_flag	= 0;
59ebfedea0SLionel Sambuc char *lifetime 		= NULL;
60ebfedea0SLionel Sambuc char *renew_life	= NULL;
61ebfedea0SLionel Sambuc char *server_str	= NULL;
62ebfedea0SLionel Sambuc char *cred_cache	= NULL;
63ebfedea0SLionel Sambuc char *start_str		= NULL;
64ebfedea0SLionel Sambuc static int switch_cache_flags = 1;
65ebfedea0SLionel Sambuc struct getarg_strings etype_str;
66ebfedea0SLionel Sambuc int use_keytab		= 0;
67ebfedea0SLionel Sambuc char *keytab_str	= NULL;
68ebfedea0SLionel Sambuc int do_afslog		= -1;
69ebfedea0SLionel Sambuc int fcache_version;
70ebfedea0SLionel Sambuc char *password_file	= NULL;
71ebfedea0SLionel Sambuc char *pk_user_id	= NULL;
72ebfedea0SLionel Sambuc int pk_enterprise_flag = 0;
73ebfedea0SLionel Sambuc struct hx509_certs_data *ent_user_id = NULL;
74ebfedea0SLionel Sambuc char *pk_x509_anchors	= NULL;
75ebfedea0SLionel Sambuc int pk_use_enckey	= 0;
76ebfedea0SLionel Sambuc static int canonicalize_flag = 0;
77ebfedea0SLionel Sambuc static int enterprise_flag = 0;
78ebfedea0SLionel Sambuc static int ok_as_delegate_flag = 0;
79ebfedea0SLionel Sambuc static int use_referrals_flag = 0;
80ebfedea0SLionel Sambuc static int windows_flag = 0;
81ebfedea0SLionel Sambuc #ifndef NO_NTLM
82ebfedea0SLionel Sambuc static char *ntlm_domain;
83ebfedea0SLionel Sambuc #endif
84ebfedea0SLionel Sambuc 
85ebfedea0SLionel Sambuc 
86ebfedea0SLionel Sambuc static struct getargs args[] = {
87ebfedea0SLionel Sambuc     /*
88ebfedea0SLionel Sambuc      * used by MIT
89ebfedea0SLionel Sambuc      * a: ~A
90ebfedea0SLionel Sambuc      * V: verbose
91ebfedea0SLionel Sambuc      * F: ~f
92ebfedea0SLionel Sambuc      * P: ~p
93ebfedea0SLionel Sambuc      * C: v4 cache name?
94ebfedea0SLionel Sambuc      * 5:
95ebfedea0SLionel Sambuc      *
96ebfedea0SLionel Sambuc      * old flags
97ebfedea0SLionel Sambuc      * 4:
98ebfedea0SLionel Sambuc      * 9:
99ebfedea0SLionel Sambuc      */
100ebfedea0SLionel Sambuc     { "afslog", 	0  , arg_flag, &do_afslog,
101*0a6a1f1dSLionel Sambuc       NP_("obtain afs tokens", ""), NULL },
102ebfedea0SLionel Sambuc 
103ebfedea0SLionel Sambuc     { "cache", 		'c', arg_string, &cred_cache,
104ebfedea0SLionel Sambuc       NP_("credentials cache", ""), "cachename" },
105ebfedea0SLionel Sambuc 
106ebfedea0SLionel Sambuc     { "forwardable",	0, arg_negative_flag, &forwardable_flag,
107*0a6a1f1dSLionel Sambuc       NP_("get tickets not forwardable", ""), NULL },
108ebfedea0SLionel Sambuc 
109ebfedea0SLionel Sambuc     { NULL,		'f', arg_flag, &forwardable_flag,
110*0a6a1f1dSLionel Sambuc       NP_("get forwardable tickets", ""), NULL },
111ebfedea0SLionel Sambuc 
112ebfedea0SLionel Sambuc     { "keytab",         't', arg_string, &keytab_str,
113ebfedea0SLionel Sambuc       NP_("keytab to use", ""), "keytabname" },
114ebfedea0SLionel Sambuc 
115ebfedea0SLionel Sambuc     { "lifetime",	'l', arg_string, &lifetime,
116ebfedea0SLionel Sambuc       NP_("lifetime of tickets", ""), "time" },
117ebfedea0SLionel Sambuc 
118ebfedea0SLionel Sambuc     { "proxiable",	'p', arg_flag, &proxiable_flag,
119*0a6a1f1dSLionel Sambuc       NP_("get proxiable tickets", ""), NULL },
120ebfedea0SLionel Sambuc 
121ebfedea0SLionel Sambuc     { "renew",          'R', arg_flag, &renew_flag,
122*0a6a1f1dSLionel Sambuc       NP_("renew TGT", ""), NULL },
123ebfedea0SLionel Sambuc 
124ebfedea0SLionel Sambuc     { "renewable",	0,   arg_flag, &renewable_flag,
125*0a6a1f1dSLionel Sambuc       NP_("get renewable tickets", ""), NULL },
126ebfedea0SLionel Sambuc 
127ebfedea0SLionel Sambuc     { "renewable-life",	'r', arg_string, &renew_life,
128ebfedea0SLionel Sambuc       NP_("renewable lifetime of tickets", ""), "time" },
129ebfedea0SLionel Sambuc 
130ebfedea0SLionel Sambuc     { "server", 	'S', arg_string, &server_str,
131ebfedea0SLionel Sambuc       NP_("server to get ticket for", ""), "principal" },
132ebfedea0SLionel Sambuc 
133ebfedea0SLionel Sambuc     { "start-time",	's', arg_string, &start_str,
134ebfedea0SLionel Sambuc       NP_("when ticket gets valid", ""), "time" },
135ebfedea0SLionel Sambuc 
136ebfedea0SLionel Sambuc     { "use-keytab",     'k', arg_flag, &use_keytab,
137*0a6a1f1dSLionel Sambuc       NP_("get key from keytab", ""), NULL },
138ebfedea0SLionel Sambuc 
139ebfedea0SLionel Sambuc     { "validate",	'v', arg_flag, &validate_flag,
140*0a6a1f1dSLionel Sambuc       NP_("validate TGT", ""), NULL },
141ebfedea0SLionel Sambuc 
142ebfedea0SLionel Sambuc     { "enctypes",	'e', arg_strings, &etype_str,
143ebfedea0SLionel Sambuc       NP_("encryption types to use", ""), "enctypes" },
144ebfedea0SLionel Sambuc 
145ebfedea0SLionel Sambuc     { "fcache-version", 0,   arg_integer, &fcache_version,
146*0a6a1f1dSLionel Sambuc       NP_("file cache version to create", ""), NULL },
147ebfedea0SLionel Sambuc 
148ebfedea0SLionel Sambuc     { "addresses",	'A',   arg_negative_flag,	&addrs_flag,
149*0a6a1f1dSLionel Sambuc       NP_("request a ticket with no addresses", ""), NULL },
150ebfedea0SLionel Sambuc 
151ebfedea0SLionel Sambuc     { "extra-addresses",'a', arg_strings,	&extra_addresses,
152ebfedea0SLionel Sambuc       NP_("include these extra addresses", ""), "addresses" },
153ebfedea0SLionel Sambuc 
154ebfedea0SLionel Sambuc     { "anonymous",	0,   arg_flag,	&anonymous_flag,
155*0a6a1f1dSLionel Sambuc       NP_("request an anonymous ticket", ""), NULL },
156ebfedea0SLionel Sambuc 
157ebfedea0SLionel Sambuc     { "request-pac",	0,   arg_flag,	&pac_flag,
158*0a6a1f1dSLionel Sambuc       NP_("request a Windows PAC", ""), NULL },
159ebfedea0SLionel Sambuc 
160ebfedea0SLionel Sambuc     { "password-file",	0,   arg_string, &password_file,
161*0a6a1f1dSLionel Sambuc       NP_("read the password from a file", ""), NULL },
162ebfedea0SLionel Sambuc 
163ebfedea0SLionel Sambuc     { "canonicalize",0,   arg_flag, &canonicalize_flag,
164*0a6a1f1dSLionel Sambuc       NP_("canonicalize client principal", ""), NULL },
165ebfedea0SLionel Sambuc 
166ebfedea0SLionel Sambuc     { "enterprise",0,   arg_flag, &enterprise_flag,
167*0a6a1f1dSLionel Sambuc       NP_("parse principal as a KRB5-NT-ENTERPRISE name", ""), NULL },
168ebfedea0SLionel Sambuc #ifdef PKINIT
169ebfedea0SLionel Sambuc     { "pk-enterprise",	0,	arg_flag,	&pk_enterprise_flag,
170*0a6a1f1dSLionel Sambuc       NP_("use enterprise name from certificate", ""), NULL },
171ebfedea0SLionel Sambuc 
172ebfedea0SLionel Sambuc     { "pk-user",	'C',	arg_string,	&pk_user_id,
173ebfedea0SLionel Sambuc       NP_("principal's public/private/certificate identifier", ""), "id" },
174ebfedea0SLionel Sambuc 
175ebfedea0SLionel Sambuc     { "x509-anchors",	'D',  arg_string, &pk_x509_anchors,
176ebfedea0SLionel Sambuc       NP_("directory with CA certificates", ""), "directory" },
177ebfedea0SLionel Sambuc 
178ebfedea0SLionel Sambuc     { "pk-use-enckey",	0,  arg_flag, &pk_use_enckey,
179*0a6a1f1dSLionel Sambuc       NP_("Use RSA encrypted reply (instead of DH)", ""), NULL },
180ebfedea0SLionel Sambuc #endif
181ebfedea0SLionel Sambuc #ifndef NO_NTLM
182ebfedea0SLionel Sambuc     { "ntlm-domain",	0,  arg_string, &ntlm_domain,
183ebfedea0SLionel Sambuc       NP_("NTLM domain", ""), "domain" },
184ebfedea0SLionel Sambuc #endif
185ebfedea0SLionel Sambuc 
186ebfedea0SLionel Sambuc     { "change-default",  0,  arg_negative_flag, &switch_cache_flags,
187*0a6a1f1dSLionel Sambuc       NP_("switch the default cache to the new credentials cache", ""), NULL },
188ebfedea0SLionel Sambuc 
189ebfedea0SLionel Sambuc     { "ok-as-delegate",	0,  arg_flag, &ok_as_delegate_flag,
190*0a6a1f1dSLionel Sambuc       NP_("honor ok-as-delegate on tickets", ""), NULL },
191ebfedea0SLionel Sambuc 
192ebfedea0SLionel Sambuc     { "use-referrals",	0,  arg_flag, &use_referrals_flag,
193*0a6a1f1dSLionel Sambuc       NP_("only use referrals, no dns canalisation", ""), NULL },
194ebfedea0SLionel Sambuc 
195ebfedea0SLionel Sambuc     { "windows",	0,  arg_flag, &windows_flag,
196*0a6a1f1dSLionel Sambuc       NP_("get windows behavior", ""), NULL },
197ebfedea0SLionel Sambuc 
198*0a6a1f1dSLionel Sambuc     { "version", 	0,   arg_flag, &version_flag, NULL, NULL },
199*0a6a1f1dSLionel Sambuc     { "help",		0,   arg_flag, &help_flag, NULL, NULL }
200ebfedea0SLionel Sambuc };
201ebfedea0SLionel Sambuc 
202ebfedea0SLionel Sambuc static void
usage(int ret)203ebfedea0SLionel Sambuc usage (int ret)
204ebfedea0SLionel Sambuc {
205ebfedea0SLionel Sambuc     arg_printusage_i18n (args,
206ebfedea0SLionel Sambuc 			 sizeof(args)/sizeof(*args),
207ebfedea0SLionel Sambuc 			 N_("Usage: ", ""),
208ebfedea0SLionel Sambuc 			 NULL,
209ebfedea0SLionel Sambuc 			 "[principal [command]]",
210ebfedea0SLionel Sambuc 			 getarg_i18n);
211ebfedea0SLionel Sambuc     exit (ret);
212ebfedea0SLionel Sambuc }
213ebfedea0SLionel Sambuc 
214ebfedea0SLionel Sambuc static krb5_error_code
get_server(krb5_context context,krb5_principal client,const char * server,krb5_principal * princ)215ebfedea0SLionel Sambuc get_server(krb5_context context,
216ebfedea0SLionel Sambuc 	   krb5_principal client,
217ebfedea0SLionel Sambuc 	   const char *server,
218ebfedea0SLionel Sambuc 	   krb5_principal *princ)
219ebfedea0SLionel Sambuc {
220ebfedea0SLionel Sambuc     krb5_const_realm realm;
221ebfedea0SLionel Sambuc     if(server)
222ebfedea0SLionel Sambuc 	return krb5_parse_name(context, server, princ);
223ebfedea0SLionel Sambuc 
224ebfedea0SLionel Sambuc     realm = krb5_principal_get_realm(context, client);
225ebfedea0SLionel Sambuc     return krb5_make_principal(context, princ, realm,
226ebfedea0SLionel Sambuc 			       KRB5_TGS_NAME, realm, NULL);
227ebfedea0SLionel Sambuc }
228ebfedea0SLionel Sambuc 
229ebfedea0SLionel Sambuc static int
renew_validate(krb5_context context,int renew,int validate,krb5_ccache cache,const char * server,krb5_deltat life)230ebfedea0SLionel Sambuc renew_validate(krb5_context context,
231ebfedea0SLionel Sambuc 	       int renew,
232ebfedea0SLionel Sambuc 	       int validate,
233ebfedea0SLionel Sambuc 	       krb5_ccache cache,
234ebfedea0SLionel Sambuc 	       const char *server,
235ebfedea0SLionel Sambuc 	       krb5_deltat life)
236ebfedea0SLionel Sambuc {
237ebfedea0SLionel Sambuc     krb5_error_code ret;
238ebfedea0SLionel Sambuc     krb5_creds in, *out = NULL;
239ebfedea0SLionel Sambuc     krb5_kdc_flags flags;
240ebfedea0SLionel Sambuc 
241ebfedea0SLionel Sambuc     memset(&in, 0, sizeof(in));
242ebfedea0SLionel Sambuc 
243ebfedea0SLionel Sambuc     ret = krb5_cc_get_principal(context, cache, &in.client);
244ebfedea0SLionel Sambuc     if(ret) {
245ebfedea0SLionel Sambuc 	krb5_warn(context, ret, "krb5_cc_get_principal");
246ebfedea0SLionel Sambuc 	return ret;
247ebfedea0SLionel Sambuc     }
248ebfedea0SLionel Sambuc     ret = get_server(context, in.client, server, &in.server);
249ebfedea0SLionel Sambuc     if(ret) {
250ebfedea0SLionel Sambuc 	krb5_warn(context, ret, "get_server");
251ebfedea0SLionel Sambuc 	goto out;
252ebfedea0SLionel Sambuc     }
253ebfedea0SLionel Sambuc 
254ebfedea0SLionel Sambuc     if (renew) {
255ebfedea0SLionel Sambuc 	/*
256ebfedea0SLionel Sambuc 	 * no need to check the error here, it's only to be
257ebfedea0SLionel Sambuc 	 * friendly to the user
258ebfedea0SLionel Sambuc 	 */
259ebfedea0SLionel Sambuc 	krb5_get_credentials(context, KRB5_GC_CACHED, cache, &in, &out);
260ebfedea0SLionel Sambuc     }
261ebfedea0SLionel Sambuc 
262ebfedea0SLionel Sambuc     flags.i = 0;
263ebfedea0SLionel Sambuc     flags.b.renewable         = flags.b.renew = renew;
264ebfedea0SLionel Sambuc     flags.b.validate          = validate;
265ebfedea0SLionel Sambuc 
266ebfedea0SLionel Sambuc     if (forwardable_flag != -1)
267ebfedea0SLionel Sambuc 	flags.b.forwardable       = forwardable_flag;
268ebfedea0SLionel Sambuc     else if (out)
269ebfedea0SLionel Sambuc 	flags.b.forwardable 	  = out->flags.b.forwardable;
270ebfedea0SLionel Sambuc 
271ebfedea0SLionel Sambuc     if (proxiable_flag != -1)
272ebfedea0SLionel Sambuc 	flags.b.proxiable         = proxiable_flag;
273ebfedea0SLionel Sambuc     else if (out)
274ebfedea0SLionel Sambuc 	flags.b.proxiable 	  = out->flags.b.proxiable;
275ebfedea0SLionel Sambuc 
276ebfedea0SLionel Sambuc     if (anonymous_flag)
277ebfedea0SLionel Sambuc 	flags.b.request_anonymous = anonymous_flag;
278ebfedea0SLionel Sambuc     if(life)
279ebfedea0SLionel Sambuc 	in.times.endtime = time(NULL) + life;
280ebfedea0SLionel Sambuc 
281ebfedea0SLionel Sambuc     if (out) {
282ebfedea0SLionel Sambuc 	krb5_free_creds (context, out);
283ebfedea0SLionel Sambuc 	out = NULL;
284ebfedea0SLionel Sambuc     }
285ebfedea0SLionel Sambuc 
286ebfedea0SLionel Sambuc 
287ebfedea0SLionel Sambuc     ret = krb5_get_kdc_cred(context,
288ebfedea0SLionel Sambuc 			    cache,
289ebfedea0SLionel Sambuc 			    flags,
290ebfedea0SLionel Sambuc 			    NULL,
291ebfedea0SLionel Sambuc 			    NULL,
292ebfedea0SLionel Sambuc 			    &in,
293ebfedea0SLionel Sambuc 			    &out);
294ebfedea0SLionel Sambuc     if(ret) {
295ebfedea0SLionel Sambuc 	krb5_warn(context, ret, "krb5_get_kdc_cred");
296ebfedea0SLionel Sambuc 	goto out;
297ebfedea0SLionel Sambuc     }
298ebfedea0SLionel Sambuc     ret = krb5_cc_initialize(context, cache, in.client);
299ebfedea0SLionel Sambuc     if(ret) {
300ebfedea0SLionel Sambuc 	krb5_free_creds (context, out);
301ebfedea0SLionel Sambuc 	krb5_warn(context, ret, "krb5_cc_initialize");
302ebfedea0SLionel Sambuc 	goto out;
303ebfedea0SLionel Sambuc     }
304ebfedea0SLionel Sambuc     ret = krb5_cc_store_cred(context, cache, out);
305ebfedea0SLionel Sambuc 
306ebfedea0SLionel Sambuc     if(ret == 0 && server == NULL) {
307ebfedea0SLionel Sambuc 	/* only do this if it's a general renew-my-tgt request */
308ebfedea0SLionel Sambuc #ifndef NO_AFS
309ebfedea0SLionel Sambuc 	if(do_afslog && k_hasafs())
310ebfedea0SLionel Sambuc 	    krb5_afslog(context, cache, NULL, NULL);
311ebfedea0SLionel Sambuc #endif
312ebfedea0SLionel Sambuc     }
313ebfedea0SLionel Sambuc 
314ebfedea0SLionel Sambuc     krb5_free_creds (context, out);
315ebfedea0SLionel Sambuc     if(ret) {
316ebfedea0SLionel Sambuc 	krb5_warn(context, ret, "krb5_cc_store_cred");
317ebfedea0SLionel Sambuc 	goto out;
318ebfedea0SLionel Sambuc     }
319ebfedea0SLionel Sambuc out:
320ebfedea0SLionel Sambuc     krb5_free_cred_contents(context, &in);
321ebfedea0SLionel Sambuc     return ret;
322ebfedea0SLionel Sambuc }
323ebfedea0SLionel Sambuc 
324ebfedea0SLionel Sambuc #ifndef NO_NTLM
325ebfedea0SLionel Sambuc 
326ebfedea0SLionel Sambuc static krb5_error_code
store_ntlmkey(krb5_context context,krb5_ccache id,const char * domain,struct ntlm_buf * buf)327ebfedea0SLionel Sambuc store_ntlmkey(krb5_context context, krb5_ccache id,
328ebfedea0SLionel Sambuc 	      const char *domain, struct ntlm_buf *buf)
329ebfedea0SLionel Sambuc {
330ebfedea0SLionel Sambuc     krb5_error_code ret;
331ebfedea0SLionel Sambuc     krb5_data data;
332ebfedea0SLionel Sambuc     char *name;
333ebfedea0SLionel Sambuc 
334ebfedea0SLionel Sambuc     asprintf(&name, "ntlm-key-%s", domain);
335ebfedea0SLionel Sambuc     if (name == NULL) {
336ebfedea0SLionel Sambuc 	krb5_clear_error_message(context);
337ebfedea0SLionel Sambuc 	return ENOMEM;
338ebfedea0SLionel Sambuc     }
339ebfedea0SLionel Sambuc 
340ebfedea0SLionel Sambuc     data.length = buf->length;
341ebfedea0SLionel Sambuc     data.data = buf->data;
342ebfedea0SLionel Sambuc 
343ebfedea0SLionel Sambuc     ret = krb5_cc_set_config(context, id, NULL, name, &data);
344ebfedea0SLionel Sambuc     free(name);
345ebfedea0SLionel Sambuc     return ret;
346ebfedea0SLionel Sambuc }
347ebfedea0SLionel Sambuc #endif
348ebfedea0SLionel Sambuc 
349ebfedea0SLionel Sambuc static krb5_error_code
get_new_tickets(krb5_context context,krb5_principal principal,krb5_ccache ccache,krb5_deltat ticket_life,int interactive)350ebfedea0SLionel Sambuc get_new_tickets(krb5_context context,
351ebfedea0SLionel Sambuc 		krb5_principal principal,
352ebfedea0SLionel Sambuc 		krb5_ccache ccache,
353ebfedea0SLionel Sambuc 		krb5_deltat ticket_life,
354ebfedea0SLionel Sambuc 		int interactive)
355ebfedea0SLionel Sambuc {
356ebfedea0SLionel Sambuc     krb5_error_code ret;
357ebfedea0SLionel Sambuc     krb5_get_init_creds_opt *opt;
358ebfedea0SLionel Sambuc     krb5_creds cred;
359ebfedea0SLionel Sambuc     char passwd[256];
360ebfedea0SLionel Sambuc     krb5_deltat start_time = 0;
361ebfedea0SLionel Sambuc     krb5_deltat renew = 0;
362*0a6a1f1dSLionel Sambuc     const char *renewstr = NULL;
363ebfedea0SLionel Sambuc     krb5_enctype *enctype = NULL;
364ebfedea0SLionel Sambuc     krb5_ccache tempccache;
365ebfedea0SLionel Sambuc #ifndef NO_NTLM
366ebfedea0SLionel Sambuc     struct ntlm_buf ntlmkey;
367ebfedea0SLionel Sambuc     memset(&ntlmkey, 0, sizeof(ntlmkey));
368ebfedea0SLionel Sambuc #endif
369ebfedea0SLionel Sambuc     passwd[0] = '\0';
370ebfedea0SLionel Sambuc 
371ebfedea0SLionel Sambuc     if (password_file) {
372ebfedea0SLionel Sambuc 	FILE *f;
373ebfedea0SLionel Sambuc 
374ebfedea0SLionel Sambuc 	if (strcasecmp("STDIN", password_file) == 0)
375ebfedea0SLionel Sambuc 	    f = stdin;
376ebfedea0SLionel Sambuc 	else
377ebfedea0SLionel Sambuc 	    f = fopen(password_file, "r");
378ebfedea0SLionel Sambuc 	if (f == NULL)
379ebfedea0SLionel Sambuc 	    krb5_errx(context, 1, "Failed to open the password file %s",
380ebfedea0SLionel Sambuc 		      password_file);
381ebfedea0SLionel Sambuc 
382ebfedea0SLionel Sambuc 	if (fgets(passwd, sizeof(passwd), f) == NULL)
383ebfedea0SLionel Sambuc 	    krb5_errx(context, 1,
384ebfedea0SLionel Sambuc 		      N_("Failed to read password from file %s", ""),
385ebfedea0SLionel Sambuc 		      password_file);
386ebfedea0SLionel Sambuc 	if (f != stdin)
387ebfedea0SLionel Sambuc 	    fclose(f);
388ebfedea0SLionel Sambuc 	passwd[strcspn(passwd, "\n")] = '\0';
389ebfedea0SLionel Sambuc     }
390ebfedea0SLionel Sambuc 
391ebfedea0SLionel Sambuc #ifdef __APPLE__
392ebfedea0SLionel Sambuc     if (passwd[0] == '\0') {
393ebfedea0SLionel Sambuc 	const char *realm;
394ebfedea0SLionel Sambuc 	OSStatus osret;
395ebfedea0SLionel Sambuc 	UInt32 length;
396ebfedea0SLionel Sambuc 	void *buffer;
397ebfedea0SLionel Sambuc 	char *name;
398ebfedea0SLionel Sambuc 
399ebfedea0SLionel Sambuc 	realm = krb5_principal_get_realm(context, principal);
400ebfedea0SLionel Sambuc 
401ebfedea0SLionel Sambuc 	ret = krb5_unparse_name_flags(context, principal,
402ebfedea0SLionel Sambuc 				      KRB5_PRINCIPAL_UNPARSE_NO_REALM, &name);
403ebfedea0SLionel Sambuc 	if (ret)
404ebfedea0SLionel Sambuc 	    goto nopassword;
405ebfedea0SLionel Sambuc 
406ebfedea0SLionel Sambuc 	osret = SecKeychainFindGenericPassword(NULL, strlen(realm), realm,
407ebfedea0SLionel Sambuc 					       strlen(name), name,
408ebfedea0SLionel Sambuc 					       &length, &buffer, NULL);
409ebfedea0SLionel Sambuc 	free(name);
410ebfedea0SLionel Sambuc 	if (osret == noErr && length < sizeof(passwd) - 1) {
411ebfedea0SLionel Sambuc 	    memcpy(passwd, buffer, length);
412ebfedea0SLionel Sambuc 	    passwd[length] = '\0';
413ebfedea0SLionel Sambuc 	}
414ebfedea0SLionel Sambuc     nopassword:
415ebfedea0SLionel Sambuc 	do { } while(0);
416ebfedea0SLionel Sambuc     }
417ebfedea0SLionel Sambuc #endif
418ebfedea0SLionel Sambuc 
419ebfedea0SLionel Sambuc     memset(&cred, 0, sizeof(cred));
420ebfedea0SLionel Sambuc 
421ebfedea0SLionel Sambuc     ret = krb5_get_init_creds_opt_alloc (context, &opt);
422ebfedea0SLionel Sambuc     if (ret)
423ebfedea0SLionel Sambuc 	krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc");
424ebfedea0SLionel Sambuc 
425ebfedea0SLionel Sambuc     krb5_get_init_creds_opt_set_default_flags(context, "kinit",
426ebfedea0SLionel Sambuc 	krb5_principal_get_realm(context, principal), opt);
427ebfedea0SLionel Sambuc 
428ebfedea0SLionel Sambuc     if(forwardable_flag != -1)
429ebfedea0SLionel Sambuc 	krb5_get_init_creds_opt_set_forwardable (opt, forwardable_flag);
430ebfedea0SLionel Sambuc     if(proxiable_flag != -1)
431ebfedea0SLionel Sambuc 	krb5_get_init_creds_opt_set_proxiable (opt, proxiable_flag);
432ebfedea0SLionel Sambuc     if(anonymous_flag)
433ebfedea0SLionel Sambuc 	krb5_get_init_creds_opt_set_anonymous (opt, anonymous_flag);
434ebfedea0SLionel Sambuc     if (pac_flag != -1)
435ebfedea0SLionel Sambuc 	krb5_get_init_creds_opt_set_pac_request(context, opt,
436ebfedea0SLionel Sambuc 						pac_flag ? TRUE : FALSE);
437ebfedea0SLionel Sambuc     if (canonicalize_flag)
438ebfedea0SLionel Sambuc 	krb5_get_init_creds_opt_set_canonicalize(context, opt, TRUE);
439*0a6a1f1dSLionel Sambuc     if (pk_enterprise_flag || enterprise_flag || canonicalize_flag || windows_flag)
440ebfedea0SLionel Sambuc 	krb5_get_init_creds_opt_set_win2k(context, opt, TRUE);
441ebfedea0SLionel Sambuc     if (pk_user_id || ent_user_id || anonymous_flag) {
442ebfedea0SLionel Sambuc 	ret = krb5_get_init_creds_opt_set_pkinit(context, opt,
443ebfedea0SLionel Sambuc 						 principal,
444ebfedea0SLionel Sambuc 						 pk_user_id,
445ebfedea0SLionel Sambuc 						 pk_x509_anchors,
446ebfedea0SLionel Sambuc 						 NULL,
447ebfedea0SLionel Sambuc 						 NULL,
448ebfedea0SLionel Sambuc 						 pk_use_enckey ? 2 : 0 |
449ebfedea0SLionel Sambuc 						 anonymous_flag ? 4 : 0,
450ebfedea0SLionel Sambuc 						 krb5_prompter_posix,
451ebfedea0SLionel Sambuc 						 NULL,
452ebfedea0SLionel Sambuc 						 passwd);
453ebfedea0SLionel Sambuc 	if (ret)
454ebfedea0SLionel Sambuc 	    krb5_err(context, 1, ret, "krb5_get_init_creds_opt_set_pkinit");
455ebfedea0SLionel Sambuc 	if (ent_user_id)
456ebfedea0SLionel Sambuc 	    krb5_get_init_creds_opt_set_pkinit_user_certs(context, opt, ent_user_id);
457ebfedea0SLionel Sambuc     }
458ebfedea0SLionel Sambuc 
459ebfedea0SLionel Sambuc     if (addrs_flag != -1)
460ebfedea0SLionel Sambuc 	krb5_get_init_creds_opt_set_addressless(context, opt,
461ebfedea0SLionel Sambuc 						addrs_flag ? FALSE : TRUE);
462ebfedea0SLionel Sambuc 
463ebfedea0SLionel Sambuc     if (renew_life == NULL && renewable_flag)
464ebfedea0SLionel Sambuc 	renewstr = "1 month";
465ebfedea0SLionel Sambuc     if (renew_life)
466ebfedea0SLionel Sambuc 	renewstr = renew_life;
467ebfedea0SLionel Sambuc     if (renewstr) {
468ebfedea0SLionel Sambuc 	renew = parse_time (renewstr, "s");
469ebfedea0SLionel Sambuc 	if (renew < 0)
470ebfedea0SLionel Sambuc 	    errx (1, "unparsable time: %s", renewstr);
471ebfedea0SLionel Sambuc 
472ebfedea0SLionel Sambuc 	krb5_get_init_creds_opt_set_renew_life (opt, renew);
473ebfedea0SLionel Sambuc     }
474ebfedea0SLionel Sambuc 
475ebfedea0SLionel Sambuc     if(ticket_life != 0)
476ebfedea0SLionel Sambuc 	krb5_get_init_creds_opt_set_tkt_life (opt, ticket_life);
477ebfedea0SLionel Sambuc 
478ebfedea0SLionel Sambuc     if(start_str) {
479ebfedea0SLionel Sambuc 	int tmp = parse_time (start_str, "s");
480ebfedea0SLionel Sambuc 	if (tmp < 0)
481ebfedea0SLionel Sambuc 	    errx (1, N_("unparsable time: %s", ""), start_str);
482ebfedea0SLionel Sambuc 
483ebfedea0SLionel Sambuc 	start_time = tmp;
484ebfedea0SLionel Sambuc     }
485ebfedea0SLionel Sambuc 
486ebfedea0SLionel Sambuc     if(etype_str.num_strings) {
487ebfedea0SLionel Sambuc 	int i;
488ebfedea0SLionel Sambuc 
489ebfedea0SLionel Sambuc 	enctype = malloc(etype_str.num_strings * sizeof(*enctype));
490ebfedea0SLionel Sambuc 	if(enctype == NULL)
491ebfedea0SLionel Sambuc 	    errx(1, "out of memory");
492ebfedea0SLionel Sambuc 	for(i = 0; i < etype_str.num_strings; i++) {
493ebfedea0SLionel Sambuc 	    ret = krb5_string_to_enctype(context,
494ebfedea0SLionel Sambuc 					 etype_str.strings[i],
495ebfedea0SLionel Sambuc 					 &enctype[i]);
496ebfedea0SLionel Sambuc 	    if(ret)
497ebfedea0SLionel Sambuc 		errx(1, "unrecognized enctype: %s", etype_str.strings[i]);
498ebfedea0SLionel Sambuc 	}
499ebfedea0SLionel Sambuc 	krb5_get_init_creds_opt_set_etype_list(opt, enctype,
500ebfedea0SLionel Sambuc 					       etype_str.num_strings);
501ebfedea0SLionel Sambuc     }
502ebfedea0SLionel Sambuc 
503ebfedea0SLionel Sambuc     if(use_keytab || keytab_str) {
504ebfedea0SLionel Sambuc 	krb5_keytab kt;
505ebfedea0SLionel Sambuc 	if(keytab_str)
506ebfedea0SLionel Sambuc 	    ret = krb5_kt_resolve(context, keytab_str, &kt);
507ebfedea0SLionel Sambuc 	else
508ebfedea0SLionel Sambuc 	    ret = krb5_kt_default(context, &kt);
509ebfedea0SLionel Sambuc 	if (ret)
510ebfedea0SLionel Sambuc 	    krb5_err (context, 1, ret, "resolving keytab");
511ebfedea0SLionel Sambuc 	ret = krb5_get_init_creds_keytab (context,
512ebfedea0SLionel Sambuc 					  &cred,
513ebfedea0SLionel Sambuc 					  principal,
514ebfedea0SLionel Sambuc 					  kt,
515ebfedea0SLionel Sambuc 					  start_time,
516ebfedea0SLionel Sambuc 					  server_str,
517ebfedea0SLionel Sambuc 					  opt);
518ebfedea0SLionel Sambuc 	krb5_kt_close(context, kt);
519ebfedea0SLionel Sambuc     } else if (pk_user_id || ent_user_id || anonymous_flag) {
520ebfedea0SLionel Sambuc 	ret = krb5_get_init_creds_password (context,
521ebfedea0SLionel Sambuc 					    &cred,
522ebfedea0SLionel Sambuc 					    principal,
523ebfedea0SLionel Sambuc 					    passwd,
524ebfedea0SLionel Sambuc 					    krb5_prompter_posix,
525ebfedea0SLionel Sambuc 					    NULL,
526ebfedea0SLionel Sambuc 					    start_time,
527ebfedea0SLionel Sambuc 					    server_str,
528ebfedea0SLionel Sambuc 					    opt);
529ebfedea0SLionel Sambuc     } else if (!interactive) {
530ebfedea0SLionel Sambuc 	krb5_warnx(context, "Not interactive, failed to get initial ticket");
531ebfedea0SLionel Sambuc 	krb5_get_init_creds_opt_free(context, opt);
532ebfedea0SLionel Sambuc 	return 0;
533ebfedea0SLionel Sambuc     } else {
534ebfedea0SLionel Sambuc 
535ebfedea0SLionel Sambuc 	if (passwd[0] == '\0') {
536ebfedea0SLionel Sambuc 	    char *p, *prompt;
537ebfedea0SLionel Sambuc 
538ebfedea0SLionel Sambuc 	    krb5_unparse_name (context, principal, &p);
539ebfedea0SLionel Sambuc 	    asprintf (&prompt, N_("%s's Password: ", ""), p);
540ebfedea0SLionel Sambuc 	    free (p);
541ebfedea0SLionel Sambuc 
542ebfedea0SLionel Sambuc 	    if (UI_UTIL_read_pw_string(passwd, sizeof(passwd)-1, prompt, 0)){
543ebfedea0SLionel Sambuc 		memset(passwd, 0, sizeof(passwd));
544ebfedea0SLionel Sambuc 		exit(1);
545ebfedea0SLionel Sambuc 	    }
546ebfedea0SLionel Sambuc 	    free (prompt);
547ebfedea0SLionel Sambuc 	}
548ebfedea0SLionel Sambuc 
549ebfedea0SLionel Sambuc 
550ebfedea0SLionel Sambuc 	ret = krb5_get_init_creds_password (context,
551ebfedea0SLionel Sambuc 					    &cred,
552ebfedea0SLionel Sambuc 					    principal,
553ebfedea0SLionel Sambuc 					    passwd,
554ebfedea0SLionel Sambuc 					    krb5_prompter_posix,
555ebfedea0SLionel Sambuc 					    NULL,
556ebfedea0SLionel Sambuc 					    start_time,
557ebfedea0SLionel Sambuc 					    server_str,
558ebfedea0SLionel Sambuc 					    opt);
559ebfedea0SLionel Sambuc     }
560ebfedea0SLionel Sambuc     krb5_get_init_creds_opt_free(context, opt);
561ebfedea0SLionel Sambuc #ifndef NO_NTLM
562ebfedea0SLionel Sambuc     if (ntlm_domain && passwd[0])
563ebfedea0SLionel Sambuc 	heim_ntlm_nt_key(passwd, &ntlmkey);
564ebfedea0SLionel Sambuc #endif
565ebfedea0SLionel Sambuc     memset(passwd, 0, sizeof(passwd));
566ebfedea0SLionel Sambuc 
567ebfedea0SLionel Sambuc     switch(ret){
568ebfedea0SLionel Sambuc     case 0:
569ebfedea0SLionel Sambuc 	break;
570ebfedea0SLionel Sambuc     case KRB5_LIBOS_PWDINTR: /* don't print anything if it was just C-c:ed */
571ebfedea0SLionel Sambuc 	exit(1);
572ebfedea0SLionel Sambuc     case KRB5KRB_AP_ERR_BAD_INTEGRITY:
573ebfedea0SLionel Sambuc     case KRB5KRB_AP_ERR_MODIFIED:
574ebfedea0SLionel Sambuc     case KRB5KDC_ERR_PREAUTH_FAILED:
575ebfedea0SLionel Sambuc 	krb5_errx(context, 1, N_("Password incorrect", ""));
576ebfedea0SLionel Sambuc 	break;
577ebfedea0SLionel Sambuc     case KRB5KRB_AP_ERR_V4_REPLY:
578ebfedea0SLionel Sambuc 	krb5_errx(context, 1, N_("Looks like a Kerberos 4 reply", ""));
579ebfedea0SLionel Sambuc 	break;
580ebfedea0SLionel Sambuc     default:
581ebfedea0SLionel Sambuc 	krb5_err(context, 1, ret, "krb5_get_init_creds");
582ebfedea0SLionel Sambuc     }
583ebfedea0SLionel Sambuc 
584ebfedea0SLionel Sambuc     if(ticket_life != 0) {
585ebfedea0SLionel Sambuc 	if(abs(cred.times.endtime - cred.times.starttime - ticket_life) > 30) {
586ebfedea0SLionel Sambuc 	    char life[64];
587ebfedea0SLionel Sambuc 	    unparse_time_approx(cred.times.endtime - cred.times.starttime,
588ebfedea0SLionel Sambuc 				life, sizeof(life));
589ebfedea0SLionel Sambuc 	    krb5_warnx(context, N_("NOTICE: ticket lifetime is %s", ""), life);
590ebfedea0SLionel Sambuc 	}
591ebfedea0SLionel Sambuc     }
592ebfedea0SLionel Sambuc     if(renew_life) {
593ebfedea0SLionel Sambuc 	if(abs(cred.times.renew_till - cred.times.starttime - renew) > 30) {
594ebfedea0SLionel Sambuc 	    char life[64];
595ebfedea0SLionel Sambuc 	    unparse_time_approx(cred.times.renew_till - cred.times.starttime,
596ebfedea0SLionel Sambuc 				life, sizeof(life));
597ebfedea0SLionel Sambuc 	    krb5_warnx(context,
598ebfedea0SLionel Sambuc 		       N_("NOTICE: ticket renewable lifetime is %s", ""),
599ebfedea0SLionel Sambuc 		       life);
600ebfedea0SLionel Sambuc 	}
601ebfedea0SLionel Sambuc     }
602ebfedea0SLionel Sambuc 
603ebfedea0SLionel Sambuc     ret = krb5_cc_new_unique(context, krb5_cc_get_type(context, ccache),
604ebfedea0SLionel Sambuc 			     NULL, &tempccache);
605ebfedea0SLionel Sambuc     if (ret)
606ebfedea0SLionel Sambuc 	krb5_err (context, 1, ret, "krb5_cc_new_unique");
607ebfedea0SLionel Sambuc 
608ebfedea0SLionel Sambuc     ret = krb5_cc_initialize (context, tempccache, cred.client);
609ebfedea0SLionel Sambuc     if (ret)
610ebfedea0SLionel Sambuc 	krb5_err (context, 1, ret, "krb5_cc_initialize");
611ebfedea0SLionel Sambuc 
612ebfedea0SLionel Sambuc     ret = krb5_cc_store_cred (context, tempccache, &cred);
613ebfedea0SLionel Sambuc     if (ret)
614ebfedea0SLionel Sambuc 	krb5_err (context, 1, ret, "krb5_cc_store_cred");
615ebfedea0SLionel Sambuc 
616ebfedea0SLionel Sambuc     krb5_free_cred_contents (context, &cred);
617ebfedea0SLionel Sambuc 
618ebfedea0SLionel Sambuc     ret = krb5_cc_move(context, tempccache, ccache);
619ebfedea0SLionel Sambuc     if (ret)
620ebfedea0SLionel Sambuc 	krb5_err (context, 1, ret, "krb5_cc_move");
621ebfedea0SLionel Sambuc 
622ebfedea0SLionel Sambuc     if (switch_cache_flags)
623ebfedea0SLionel Sambuc 	krb5_cc_switch(context, ccache);
624ebfedea0SLionel Sambuc 
625ebfedea0SLionel Sambuc #ifndef NO_NTLM
626ebfedea0SLionel Sambuc     if (ntlm_domain && ntlmkey.data)
627ebfedea0SLionel Sambuc 	store_ntlmkey(context, ccache, ntlm_domain, &ntlmkey);
628ebfedea0SLionel Sambuc #endif
629ebfedea0SLionel Sambuc 
630ebfedea0SLionel Sambuc     if (ok_as_delegate_flag || windows_flag || use_referrals_flag) {
631ebfedea0SLionel Sambuc 	unsigned char d = 0;
632ebfedea0SLionel Sambuc 	krb5_data data;
633ebfedea0SLionel Sambuc 
634ebfedea0SLionel Sambuc 	if (ok_as_delegate_flag || windows_flag)
635ebfedea0SLionel Sambuc 	    d |= 1;
636ebfedea0SLionel Sambuc 	if (use_referrals_flag || windows_flag)
637ebfedea0SLionel Sambuc 	    d |= 2;
638ebfedea0SLionel Sambuc 
639ebfedea0SLionel Sambuc 	data.length = 1;
640ebfedea0SLionel Sambuc 	data.data = &d;
641ebfedea0SLionel Sambuc 
642ebfedea0SLionel Sambuc 	krb5_cc_set_config(context, ccache, NULL, "realm-config", &data);
643ebfedea0SLionel Sambuc     }
644ebfedea0SLionel Sambuc 
645ebfedea0SLionel Sambuc 
646ebfedea0SLionel Sambuc     if (enctype)
647ebfedea0SLionel Sambuc 	free(enctype);
648ebfedea0SLionel Sambuc 
649ebfedea0SLionel Sambuc     return 0;
650ebfedea0SLionel Sambuc }
651ebfedea0SLionel Sambuc 
652ebfedea0SLionel Sambuc static time_t
ticket_lifetime(krb5_context context,krb5_ccache cache,krb5_principal client,const char * server)653ebfedea0SLionel Sambuc ticket_lifetime(krb5_context context, krb5_ccache cache,
654ebfedea0SLionel Sambuc 		krb5_principal client, const char *server)
655ebfedea0SLionel Sambuc {
656ebfedea0SLionel Sambuc     krb5_creds in_cred, *cred;
657ebfedea0SLionel Sambuc     krb5_error_code ret;
658ebfedea0SLionel Sambuc     time_t timeout;
659ebfedea0SLionel Sambuc 
660ebfedea0SLionel Sambuc     memset(&in_cred, 0, sizeof(in_cred));
661ebfedea0SLionel Sambuc 
662ebfedea0SLionel Sambuc     ret = krb5_cc_get_principal(context, cache, &in_cred.client);
663ebfedea0SLionel Sambuc     if(ret) {
664ebfedea0SLionel Sambuc 	krb5_warn(context, ret, "krb5_cc_get_principal");
665ebfedea0SLionel Sambuc 	return 0;
666ebfedea0SLionel Sambuc     }
667ebfedea0SLionel Sambuc     ret = get_server(context, in_cred.client, server, &in_cred.server);
668ebfedea0SLionel Sambuc     if(ret) {
669ebfedea0SLionel Sambuc 	krb5_free_principal(context, in_cred.client);
670ebfedea0SLionel Sambuc 	krb5_warn(context, ret, "get_server");
671ebfedea0SLionel Sambuc 	return 0;
672ebfedea0SLionel Sambuc     }
673ebfedea0SLionel Sambuc 
674ebfedea0SLionel Sambuc     ret = krb5_get_credentials(context, KRB5_GC_CACHED,
675ebfedea0SLionel Sambuc 			       cache, &in_cred, &cred);
676ebfedea0SLionel Sambuc     krb5_free_principal(context, in_cred.client);
677ebfedea0SLionel Sambuc     krb5_free_principal(context, in_cred.server);
678ebfedea0SLionel Sambuc     if(ret) {
679ebfedea0SLionel Sambuc 	krb5_warn(context, ret, "krb5_get_credentials");
680ebfedea0SLionel Sambuc 	return 0;
681ebfedea0SLionel Sambuc     }
682ebfedea0SLionel Sambuc     timeout = cred->times.endtime - cred->times.starttime;
683ebfedea0SLionel Sambuc     if (timeout < 0)
684ebfedea0SLionel Sambuc 	timeout = 0;
685ebfedea0SLionel Sambuc     krb5_free_creds(context, cred);
686ebfedea0SLionel Sambuc     return timeout;
687ebfedea0SLionel Sambuc }
688ebfedea0SLionel Sambuc 
689ebfedea0SLionel Sambuc struct renew_ctx {
690ebfedea0SLionel Sambuc     krb5_context context;
691ebfedea0SLionel Sambuc     krb5_ccache  ccache;
692ebfedea0SLionel Sambuc     krb5_principal principal;
693ebfedea0SLionel Sambuc     krb5_deltat ticket_life;
694ebfedea0SLionel Sambuc };
695ebfedea0SLionel Sambuc 
696ebfedea0SLionel Sambuc static time_t
renew_func(void * ptr)697ebfedea0SLionel Sambuc renew_func(void *ptr)
698ebfedea0SLionel Sambuc {
699ebfedea0SLionel Sambuc     struct renew_ctx *ctx = ptr;
700ebfedea0SLionel Sambuc     krb5_error_code ret;
701ebfedea0SLionel Sambuc     time_t expire;
702ebfedea0SLionel Sambuc     int new_tickets = 0;
703ebfedea0SLionel Sambuc 
704ebfedea0SLionel Sambuc     if (renewable_flag) {
705ebfedea0SLionel Sambuc 	ret = renew_validate(ctx->context, renewable_flag, validate_flag,
706ebfedea0SLionel Sambuc 			     ctx->ccache, server_str, ctx->ticket_life);
707ebfedea0SLionel Sambuc 	if (ret)
708ebfedea0SLionel Sambuc 	    new_tickets = 1;
709ebfedea0SLionel Sambuc     } else
710ebfedea0SLionel Sambuc 	new_tickets = 1;
711ebfedea0SLionel Sambuc 
712ebfedea0SLionel Sambuc     if (new_tickets)
713ebfedea0SLionel Sambuc 	get_new_tickets(ctx->context, ctx->principal,
714ebfedea0SLionel Sambuc 			ctx->ccache, ctx->ticket_life, 0);
715ebfedea0SLionel Sambuc 
716ebfedea0SLionel Sambuc #ifndef NO_AFS
717ebfedea0SLionel Sambuc     if(do_afslog && k_hasafs())
718ebfedea0SLionel Sambuc 	krb5_afslog(ctx->context, ctx->ccache, NULL, NULL);
719ebfedea0SLionel Sambuc #endif
720ebfedea0SLionel Sambuc 
721ebfedea0SLionel Sambuc     expire = ticket_lifetime(ctx->context, ctx->ccache, ctx->principal,
722ebfedea0SLionel Sambuc 			     server_str) / 2;
723ebfedea0SLionel Sambuc     return expire + 1;
724ebfedea0SLionel Sambuc }
725ebfedea0SLionel Sambuc 
726ebfedea0SLionel Sambuc int
main(int argc,char ** argv)727ebfedea0SLionel Sambuc main (int argc, char **argv)
728ebfedea0SLionel Sambuc {
729ebfedea0SLionel Sambuc     krb5_error_code ret;
730ebfedea0SLionel Sambuc     krb5_context context;
731ebfedea0SLionel Sambuc     krb5_ccache  ccache;
732ebfedea0SLionel Sambuc     krb5_principal principal;
733ebfedea0SLionel Sambuc     int optidx = 0;
734ebfedea0SLionel Sambuc     krb5_deltat ticket_life = 0;
735ebfedea0SLionel Sambuc     int parseflags = 0;
736ebfedea0SLionel Sambuc 
737ebfedea0SLionel Sambuc     setprogname (argv[0]);
738ebfedea0SLionel Sambuc 
739ebfedea0SLionel Sambuc     setlocale (LC_ALL, "");
740ebfedea0SLionel Sambuc     bindtextdomain ("heimdal_kuser", HEIMDAL_LOCALEDIR);
741ebfedea0SLionel Sambuc     textdomain("heimdal_kuser");
742ebfedea0SLionel Sambuc 
743ebfedea0SLionel Sambuc     ret = krb5_init_context (&context);
744ebfedea0SLionel Sambuc     if (ret == KRB5_CONFIG_BADFORMAT)
745ebfedea0SLionel Sambuc 	errx (1, "krb5_init_context failed to parse configuration file");
746ebfedea0SLionel Sambuc     else if (ret)
747ebfedea0SLionel Sambuc 	errx(1, "krb5_init_context failed: %d", ret);
748ebfedea0SLionel Sambuc 
749ebfedea0SLionel Sambuc     if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
750ebfedea0SLionel Sambuc 	usage(1);
751ebfedea0SLionel Sambuc 
752ebfedea0SLionel Sambuc     if (help_flag)
753ebfedea0SLionel Sambuc 	usage (0);
754ebfedea0SLionel Sambuc 
755ebfedea0SLionel Sambuc     if(version_flag) {
756ebfedea0SLionel Sambuc 	print_version(NULL);
757ebfedea0SLionel Sambuc 	exit(0);
758ebfedea0SLionel Sambuc     }
759ebfedea0SLionel Sambuc 
760ebfedea0SLionel Sambuc     argc -= optidx;
761ebfedea0SLionel Sambuc     argv += optidx;
762ebfedea0SLionel Sambuc 
763ebfedea0SLionel Sambuc     if (canonicalize_flag || enterprise_flag)
764ebfedea0SLionel Sambuc 	parseflags |= KRB5_PRINCIPAL_PARSE_ENTERPRISE;
765ebfedea0SLionel Sambuc 
766ebfedea0SLionel Sambuc     if (pk_enterprise_flag) {
767ebfedea0SLionel Sambuc 	ret = krb5_pk_enterprise_cert(context, pk_user_id,
768ebfedea0SLionel Sambuc 				      argv[0], &principal,
769ebfedea0SLionel Sambuc 				      &ent_user_id);
770ebfedea0SLionel Sambuc 	if (ret)
771ebfedea0SLionel Sambuc 	    krb5_err(context, 1, ret, "krb5_pk_enterprise_certs");
772ebfedea0SLionel Sambuc 
773ebfedea0SLionel Sambuc 	pk_user_id = NULL;
774ebfedea0SLionel Sambuc 
775ebfedea0SLionel Sambuc     } else if (anonymous_flag) {
776ebfedea0SLionel Sambuc 
777ebfedea0SLionel Sambuc 	ret = krb5_make_principal(context, &principal, argv[0],
778ebfedea0SLionel Sambuc 				  KRB5_WELLKNOWN_NAME, KRB5_ANON_NAME,
779ebfedea0SLionel Sambuc 				  NULL);
780ebfedea0SLionel Sambuc 	if (ret)
781ebfedea0SLionel Sambuc 	    krb5_err(context, 1, ret, "krb5_make_principal");
782ebfedea0SLionel Sambuc 	krb5_principal_set_type(context, principal, KRB5_NT_WELLKNOWN);
783ebfedea0SLionel Sambuc 
784ebfedea0SLionel Sambuc     } else {
785ebfedea0SLionel Sambuc 	if (argv[0]) {
786ebfedea0SLionel Sambuc 	    ret = krb5_parse_name_flags (context, argv[0], parseflags,
787ebfedea0SLionel Sambuc 					 &principal);
788ebfedea0SLionel Sambuc 	    if (ret)
789ebfedea0SLionel Sambuc 		krb5_err (context, 1, ret, "krb5_parse_name");
790ebfedea0SLionel Sambuc 	} else {
791ebfedea0SLionel Sambuc 	    ret = krb5_get_default_principal (context, &principal);
792ebfedea0SLionel Sambuc 	    if (ret)
793ebfedea0SLionel Sambuc 		krb5_err (context, 1, ret, "krb5_get_default_principal");
794ebfedea0SLionel Sambuc 	}
795ebfedea0SLionel Sambuc     }
796ebfedea0SLionel Sambuc 
797ebfedea0SLionel Sambuc     if(fcache_version)
798ebfedea0SLionel Sambuc 	krb5_set_fcache_version(context, fcache_version);
799ebfedea0SLionel Sambuc 
800ebfedea0SLionel Sambuc     if(renewable_flag == -1)
801ebfedea0SLionel Sambuc 	/* this seems somewhat pointless, but whatever */
802ebfedea0SLionel Sambuc 	krb5_appdefault_boolean(context, "kinit",
803ebfedea0SLionel Sambuc 				krb5_principal_get_realm(context, principal),
804ebfedea0SLionel Sambuc 				"renewable", FALSE, &renewable_flag);
805ebfedea0SLionel Sambuc     if(do_afslog == -1)
806ebfedea0SLionel Sambuc 	krb5_appdefault_boolean(context, "kinit",
807ebfedea0SLionel Sambuc 				krb5_principal_get_realm(context, principal),
808ebfedea0SLionel Sambuc 				"afslog", TRUE, &do_afslog);
809ebfedea0SLionel Sambuc 
810ebfedea0SLionel Sambuc     if(cred_cache)
811ebfedea0SLionel Sambuc 	ret = krb5_cc_resolve(context, cred_cache, &ccache);
812ebfedea0SLionel Sambuc     else {
813ebfedea0SLionel Sambuc 	if(argc > 1) {
814ebfedea0SLionel Sambuc 	    char s[1024];
815ebfedea0SLionel Sambuc 	    ret = krb5_cc_new_unique(context, NULL, NULL, &ccache);
816ebfedea0SLionel Sambuc 	    if(ret)
817ebfedea0SLionel Sambuc 		krb5_err(context, 1, ret, "creating cred cache");
818ebfedea0SLionel Sambuc 	    snprintf(s, sizeof(s), "%s:%s",
819ebfedea0SLionel Sambuc 		     krb5_cc_get_type(context, ccache),
820ebfedea0SLionel Sambuc 		     krb5_cc_get_name(context, ccache));
821ebfedea0SLionel Sambuc 	    setenv("KRB5CCNAME", s, 1);
822ebfedea0SLionel Sambuc 	} else {
823ebfedea0SLionel Sambuc 	    ret = krb5_cc_cache_match(context, principal, &ccache);
824ebfedea0SLionel Sambuc 	    if (ret) {
825ebfedea0SLionel Sambuc 		const char *type;
826ebfedea0SLionel Sambuc 		ret = krb5_cc_default (context, &ccache);
827ebfedea0SLionel Sambuc 		if (ret)
828ebfedea0SLionel Sambuc 		    krb5_err (context, 1, ret, N_("resolving credentials cache", ""));
829ebfedea0SLionel Sambuc 
830ebfedea0SLionel Sambuc 		/*
831ebfedea0SLionel Sambuc 		 * Check if the type support switching, and we do,
832ebfedea0SLionel Sambuc 		 * then do that instead over overwriting the current
833ebfedea0SLionel Sambuc 		 * default credential
834ebfedea0SLionel Sambuc 		 */
835ebfedea0SLionel Sambuc 		type = krb5_cc_get_type(context, ccache);
836ebfedea0SLionel Sambuc 		if (krb5_cc_support_switch(context, type)) {
837ebfedea0SLionel Sambuc 		    krb5_cc_close(context, ccache);
838ebfedea0SLionel Sambuc 		    ret = krb5_cc_new_unique(context, type, NULL, &ccache);
839ebfedea0SLionel Sambuc 		}
840ebfedea0SLionel Sambuc 	    }
841ebfedea0SLionel Sambuc 	}
842ebfedea0SLionel Sambuc     }
843ebfedea0SLionel Sambuc     if (ret)
844ebfedea0SLionel Sambuc 	krb5_err (context, 1, ret, N_("resolving credentials cache", ""));
845ebfedea0SLionel Sambuc 
846ebfedea0SLionel Sambuc #ifndef NO_AFS
847ebfedea0SLionel Sambuc     if(argc > 1 && k_hasafs ())
848ebfedea0SLionel Sambuc 	k_setpag();
849ebfedea0SLionel Sambuc #endif
850ebfedea0SLionel Sambuc 
851ebfedea0SLionel Sambuc     if (lifetime) {
852ebfedea0SLionel Sambuc 	int tmp = parse_time (lifetime, "s");
853ebfedea0SLionel Sambuc 	if (tmp < 0)
854ebfedea0SLionel Sambuc 	    errx (1, N_("unparsable time: %s", ""), lifetime);
855ebfedea0SLionel Sambuc 
856ebfedea0SLionel Sambuc 	ticket_life = tmp;
857ebfedea0SLionel Sambuc     }
858ebfedea0SLionel Sambuc 
859ebfedea0SLionel Sambuc     if(addrs_flag == 0 && extra_addresses.num_strings > 0)
860ebfedea0SLionel Sambuc 	krb5_errx(context, 1,
861ebfedea0SLionel Sambuc 		  N_("specifying both extra addresses and "
862ebfedea0SLionel Sambuc 		     "no addresses makes no sense", ""));
863ebfedea0SLionel Sambuc     {
864ebfedea0SLionel Sambuc 	int i;
865ebfedea0SLionel Sambuc 	krb5_addresses addresses;
866ebfedea0SLionel Sambuc 	memset(&addresses, 0, sizeof(addresses));
867ebfedea0SLionel Sambuc 	for(i = 0; i < extra_addresses.num_strings; i++) {
868ebfedea0SLionel Sambuc 	    ret = krb5_parse_address(context, extra_addresses.strings[i],
869ebfedea0SLionel Sambuc 				     &addresses);
870ebfedea0SLionel Sambuc 	    if (ret == 0) {
871ebfedea0SLionel Sambuc 		krb5_add_extra_addresses(context, &addresses);
872ebfedea0SLionel Sambuc 		krb5_free_addresses(context, &addresses);
873ebfedea0SLionel Sambuc 	    }
874ebfedea0SLionel Sambuc 	}
875ebfedea0SLionel Sambuc 	free_getarg_strings(&extra_addresses);
876ebfedea0SLionel Sambuc     }
877ebfedea0SLionel Sambuc 
878ebfedea0SLionel Sambuc     if(renew_flag || validate_flag) {
879ebfedea0SLionel Sambuc 	ret = renew_validate(context, renew_flag, validate_flag,
880ebfedea0SLionel Sambuc 			     ccache, server_str, ticket_life);
881ebfedea0SLionel Sambuc 	exit(ret != 0);
882ebfedea0SLionel Sambuc     }
883ebfedea0SLionel Sambuc 
884ebfedea0SLionel Sambuc     get_new_tickets(context, principal, ccache, ticket_life, 1);
885ebfedea0SLionel Sambuc 
886ebfedea0SLionel Sambuc #ifndef NO_AFS
887ebfedea0SLionel Sambuc     if(do_afslog && k_hasafs())
888ebfedea0SLionel Sambuc 	krb5_afslog(context, ccache, NULL, NULL);
889ebfedea0SLionel Sambuc #endif
890ebfedea0SLionel Sambuc     if(argc > 1) {
891ebfedea0SLionel Sambuc 	struct renew_ctx ctx;
892ebfedea0SLionel Sambuc 	time_t timeout;
893ebfedea0SLionel Sambuc 
894ebfedea0SLionel Sambuc 	timeout = ticket_lifetime(context, ccache, principal, server_str) / 2;
895ebfedea0SLionel Sambuc 
896ebfedea0SLionel Sambuc 	ctx.context = context;
897ebfedea0SLionel Sambuc 	ctx.ccache = ccache;
898ebfedea0SLionel Sambuc 	ctx.principal = principal;
899ebfedea0SLionel Sambuc 	ctx.ticket_life = ticket_life;
900ebfedea0SLionel Sambuc 
901ebfedea0SLionel Sambuc 	ret = simple_execvp_timed(argv[1], argv+1,
902ebfedea0SLionel Sambuc 				  renew_func, &ctx, timeout);
903ebfedea0SLionel Sambuc #define EX_NOEXEC	126
904ebfedea0SLionel Sambuc #define EX_NOTFOUND	127
905ebfedea0SLionel Sambuc 	if(ret == EX_NOEXEC)
906ebfedea0SLionel Sambuc 	    krb5_warnx(context, N_("permission denied: %s", ""), argv[1]);
907ebfedea0SLionel Sambuc 	else if(ret == EX_NOTFOUND)
908ebfedea0SLionel Sambuc 	    krb5_warnx(context, N_("command not found: %s", ""), argv[1]);
909ebfedea0SLionel Sambuc 
910ebfedea0SLionel Sambuc 	krb5_cc_destroy(context, ccache);
911ebfedea0SLionel Sambuc #ifndef NO_AFS
912ebfedea0SLionel Sambuc 	if(k_hasafs())
913ebfedea0SLionel Sambuc 	    k_unlog();
914ebfedea0SLionel Sambuc #endif
915ebfedea0SLionel Sambuc     } else {
916ebfedea0SLionel Sambuc 	krb5_cc_close (context, ccache);
917ebfedea0SLionel Sambuc 	ret = 0;
918ebfedea0SLionel Sambuc     }
919ebfedea0SLionel Sambuc     krb5_free_principal(context, principal);
920ebfedea0SLionel Sambuc     krb5_free_context (context);
921ebfedea0SLionel Sambuc     return ret;
922ebfedea0SLionel Sambuc }
923