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