1*0a6a1f1dSLionel Sambuc /* $NetBSD: init_creds_pw.c,v 1.1.1.2 2014/04/24 12:45:50 pettai Exp $ */
2ebfedea0SLionel Sambuc
3ebfedea0SLionel Sambuc /*
4ebfedea0SLionel Sambuc * Copyright (c) 1997 - 2008 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 "krb5_locl.h"
39ebfedea0SLionel Sambuc
40ebfedea0SLionel Sambuc typedef struct krb5_get_init_creds_ctx {
41ebfedea0SLionel Sambuc KDCOptions flags;
42ebfedea0SLionel Sambuc krb5_creds cred;
43ebfedea0SLionel Sambuc krb5_addresses *addrs;
44ebfedea0SLionel Sambuc krb5_enctype *etypes;
45ebfedea0SLionel Sambuc krb5_preauthtype *pre_auth_types;
46ebfedea0SLionel Sambuc char *in_tkt_service;
47ebfedea0SLionel Sambuc unsigned nonce;
48ebfedea0SLionel Sambuc unsigned pk_nonce;
49ebfedea0SLionel Sambuc
50ebfedea0SLionel Sambuc krb5_data req_buffer;
51ebfedea0SLionel Sambuc AS_REQ as_req;
52ebfedea0SLionel Sambuc int pa_counter;
53ebfedea0SLionel Sambuc
54ebfedea0SLionel Sambuc /* password and keytab_data is freed on completion */
55ebfedea0SLionel Sambuc char *password;
56ebfedea0SLionel Sambuc krb5_keytab_key_proc_args *keytab_data;
57ebfedea0SLionel Sambuc
58ebfedea0SLionel Sambuc krb5_pointer *keyseed;
59ebfedea0SLionel Sambuc krb5_s2k_proc keyproc;
60ebfedea0SLionel Sambuc
61ebfedea0SLionel Sambuc krb5_get_init_creds_tristate req_pac;
62ebfedea0SLionel Sambuc
63ebfedea0SLionel Sambuc krb5_pk_init_ctx pk_init_ctx;
64ebfedea0SLionel Sambuc int ic_flags;
65ebfedea0SLionel Sambuc
66ebfedea0SLionel Sambuc int used_pa_types;
67ebfedea0SLionel Sambuc #define USED_PKINIT 1
68ebfedea0SLionel Sambuc #define USED_PKINIT_W2K 2
69ebfedea0SLionel Sambuc #define USED_ENC_TS_GUESS 4
70ebfedea0SLionel Sambuc #define USED_ENC_TS_INFO 8
71ebfedea0SLionel Sambuc
72ebfedea0SLionel Sambuc METHOD_DATA md;
73ebfedea0SLionel Sambuc KRB_ERROR error;
74ebfedea0SLionel Sambuc AS_REP as_rep;
75ebfedea0SLionel Sambuc EncKDCRepPart enc_part;
76ebfedea0SLionel Sambuc
77ebfedea0SLionel Sambuc krb5_prompter_fct prompter;
78ebfedea0SLionel Sambuc void *prompter_data;
79ebfedea0SLionel Sambuc
80ebfedea0SLionel Sambuc struct pa_info_data *ppaid;
81ebfedea0SLionel Sambuc
82ebfedea0SLionel Sambuc } krb5_get_init_creds_ctx;
83ebfedea0SLionel Sambuc
84ebfedea0SLionel Sambuc
85ebfedea0SLionel Sambuc struct pa_info_data {
86ebfedea0SLionel Sambuc krb5_enctype etype;
87ebfedea0SLionel Sambuc krb5_salt salt;
88ebfedea0SLionel Sambuc krb5_data *s2kparams;
89ebfedea0SLionel Sambuc };
90ebfedea0SLionel Sambuc
91ebfedea0SLionel Sambuc static void
free_paid(krb5_context context,struct pa_info_data * ppaid)92ebfedea0SLionel Sambuc free_paid(krb5_context context, struct pa_info_data *ppaid)
93ebfedea0SLionel Sambuc {
94ebfedea0SLionel Sambuc krb5_free_salt(context, ppaid->salt);
95ebfedea0SLionel Sambuc if (ppaid->s2kparams)
96ebfedea0SLionel Sambuc krb5_free_data(context, ppaid->s2kparams);
97ebfedea0SLionel Sambuc }
98ebfedea0SLionel Sambuc
99ebfedea0SLionel Sambuc static krb5_error_code KRB5_CALLCONV
default_s2k_func(krb5_context context,krb5_enctype type,krb5_const_pointer keyseed,krb5_salt salt,krb5_data * s2kparms,krb5_keyblock ** key)100ebfedea0SLionel Sambuc default_s2k_func(krb5_context context, krb5_enctype type,
101ebfedea0SLionel Sambuc krb5_const_pointer keyseed,
102ebfedea0SLionel Sambuc krb5_salt salt, krb5_data *s2kparms,
103ebfedea0SLionel Sambuc krb5_keyblock **key)
104ebfedea0SLionel Sambuc {
105ebfedea0SLionel Sambuc krb5_error_code ret;
106ebfedea0SLionel Sambuc krb5_data password;
107ebfedea0SLionel Sambuc krb5_data opaque;
108ebfedea0SLionel Sambuc
109ebfedea0SLionel Sambuc _krb5_debug(context, 5, "krb5_get_init_creds: using default_s2k_func");
110ebfedea0SLionel Sambuc
111ebfedea0SLionel Sambuc password.data = rk_UNCONST(keyseed);
112ebfedea0SLionel Sambuc password.length = strlen(keyseed);
113ebfedea0SLionel Sambuc if (s2kparms)
114ebfedea0SLionel Sambuc opaque = *s2kparms;
115ebfedea0SLionel Sambuc else
116ebfedea0SLionel Sambuc krb5_data_zero(&opaque);
117ebfedea0SLionel Sambuc
118ebfedea0SLionel Sambuc *key = malloc(sizeof(**key));
119ebfedea0SLionel Sambuc if (*key == NULL)
120ebfedea0SLionel Sambuc return ENOMEM;
121ebfedea0SLionel Sambuc ret = krb5_string_to_key_data_salt_opaque(context, type, password,
122ebfedea0SLionel Sambuc salt, opaque, *key);
123ebfedea0SLionel Sambuc if (ret) {
124ebfedea0SLionel Sambuc free(*key);
125ebfedea0SLionel Sambuc *key = NULL;
126ebfedea0SLionel Sambuc }
127ebfedea0SLionel Sambuc return ret;
128ebfedea0SLionel Sambuc }
129ebfedea0SLionel Sambuc
130ebfedea0SLionel Sambuc static void
free_init_creds_ctx(krb5_context context,krb5_init_creds_context ctx)131ebfedea0SLionel Sambuc free_init_creds_ctx(krb5_context context, krb5_init_creds_context ctx)
132ebfedea0SLionel Sambuc {
133ebfedea0SLionel Sambuc if (ctx->etypes)
134ebfedea0SLionel Sambuc free(ctx->etypes);
135ebfedea0SLionel Sambuc if (ctx->pre_auth_types)
136ebfedea0SLionel Sambuc free (ctx->pre_auth_types);
137ebfedea0SLionel Sambuc if (ctx->in_tkt_service)
138ebfedea0SLionel Sambuc free(ctx->in_tkt_service);
139ebfedea0SLionel Sambuc if (ctx->keytab_data)
140ebfedea0SLionel Sambuc free(ctx->keytab_data);
141ebfedea0SLionel Sambuc if (ctx->password) {
142ebfedea0SLionel Sambuc memset(ctx->password, 0, strlen(ctx->password));
143ebfedea0SLionel Sambuc free(ctx->password);
144ebfedea0SLionel Sambuc }
145ebfedea0SLionel Sambuc krb5_data_free(&ctx->req_buffer);
146ebfedea0SLionel Sambuc krb5_free_cred_contents(context, &ctx->cred);
147ebfedea0SLionel Sambuc free_METHOD_DATA(&ctx->md);
148ebfedea0SLionel Sambuc free_AS_REP(&ctx->as_rep);
149ebfedea0SLionel Sambuc free_EncKDCRepPart(&ctx->enc_part);
150ebfedea0SLionel Sambuc free_KRB_ERROR(&ctx->error);
151ebfedea0SLionel Sambuc free_AS_REQ(&ctx->as_req);
152ebfedea0SLionel Sambuc if (ctx->ppaid) {
153ebfedea0SLionel Sambuc free_paid(context, ctx->ppaid);
154ebfedea0SLionel Sambuc free(ctx->ppaid);
155ebfedea0SLionel Sambuc }
156ebfedea0SLionel Sambuc memset(ctx, 0, sizeof(*ctx));
157ebfedea0SLionel Sambuc }
158ebfedea0SLionel Sambuc
159ebfedea0SLionel Sambuc static int
get_config_time(krb5_context context,const char * realm,const char * name,int def)160ebfedea0SLionel Sambuc get_config_time (krb5_context context,
161ebfedea0SLionel Sambuc const char *realm,
162ebfedea0SLionel Sambuc const char *name,
163ebfedea0SLionel Sambuc int def)
164ebfedea0SLionel Sambuc {
165ebfedea0SLionel Sambuc int ret;
166ebfedea0SLionel Sambuc
167ebfedea0SLionel Sambuc ret = krb5_config_get_time (context, NULL,
168ebfedea0SLionel Sambuc "realms",
169ebfedea0SLionel Sambuc realm,
170ebfedea0SLionel Sambuc name,
171ebfedea0SLionel Sambuc NULL);
172ebfedea0SLionel Sambuc if (ret >= 0)
173ebfedea0SLionel Sambuc return ret;
174ebfedea0SLionel Sambuc ret = krb5_config_get_time (context, NULL,
175ebfedea0SLionel Sambuc "libdefaults",
176ebfedea0SLionel Sambuc name,
177ebfedea0SLionel Sambuc NULL);
178ebfedea0SLionel Sambuc if (ret >= 0)
179ebfedea0SLionel Sambuc return ret;
180ebfedea0SLionel Sambuc return def;
181ebfedea0SLionel Sambuc }
182ebfedea0SLionel Sambuc
183ebfedea0SLionel Sambuc static krb5_error_code
init_cred(krb5_context context,krb5_creds * cred,krb5_principal client,krb5_deltat start_time,krb5_get_init_creds_opt * options)184ebfedea0SLionel Sambuc init_cred (krb5_context context,
185ebfedea0SLionel Sambuc krb5_creds *cred,
186ebfedea0SLionel Sambuc krb5_principal client,
187ebfedea0SLionel Sambuc krb5_deltat start_time,
188ebfedea0SLionel Sambuc krb5_get_init_creds_opt *options)
189ebfedea0SLionel Sambuc {
190ebfedea0SLionel Sambuc krb5_error_code ret;
191ebfedea0SLionel Sambuc int tmp;
192ebfedea0SLionel Sambuc krb5_timestamp now;
193ebfedea0SLionel Sambuc
194ebfedea0SLionel Sambuc krb5_timeofday (context, &now);
195ebfedea0SLionel Sambuc
196ebfedea0SLionel Sambuc memset (cred, 0, sizeof(*cred));
197ebfedea0SLionel Sambuc
198ebfedea0SLionel Sambuc if (client)
199ebfedea0SLionel Sambuc krb5_copy_principal(context, client, &cred->client);
200ebfedea0SLionel Sambuc else {
201ebfedea0SLionel Sambuc ret = krb5_get_default_principal (context,
202ebfedea0SLionel Sambuc &cred->client);
203ebfedea0SLionel Sambuc if (ret)
204ebfedea0SLionel Sambuc goto out;
205ebfedea0SLionel Sambuc }
206ebfedea0SLionel Sambuc
207ebfedea0SLionel Sambuc if (start_time)
208ebfedea0SLionel Sambuc cred->times.starttime = now + start_time;
209ebfedea0SLionel Sambuc
210ebfedea0SLionel Sambuc if (options->flags & KRB5_GET_INIT_CREDS_OPT_TKT_LIFE)
211ebfedea0SLionel Sambuc tmp = options->tkt_life;
212ebfedea0SLionel Sambuc else
213ebfedea0SLionel Sambuc tmp = 10 * 60 * 60;
214ebfedea0SLionel Sambuc cred->times.endtime = now + tmp;
215ebfedea0SLionel Sambuc
216ebfedea0SLionel Sambuc if ((options->flags & KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE) &&
217ebfedea0SLionel Sambuc options->renew_life > 0) {
218ebfedea0SLionel Sambuc cred->times.renew_till = now + options->renew_life;
219ebfedea0SLionel Sambuc }
220ebfedea0SLionel Sambuc
221ebfedea0SLionel Sambuc return 0;
222ebfedea0SLionel Sambuc
223ebfedea0SLionel Sambuc out:
224ebfedea0SLionel Sambuc krb5_free_cred_contents (context, cred);
225ebfedea0SLionel Sambuc return ret;
226ebfedea0SLionel Sambuc }
227ebfedea0SLionel Sambuc
228ebfedea0SLionel Sambuc /*
229ebfedea0SLionel Sambuc * Print a message (str) to the user about the expiration in `lr'
230ebfedea0SLionel Sambuc */
231ebfedea0SLionel Sambuc
232ebfedea0SLionel Sambuc static void
report_expiration(krb5_context context,krb5_prompter_fct prompter,krb5_data * data,const char * str,time_t now)233ebfedea0SLionel Sambuc report_expiration (krb5_context context,
234ebfedea0SLionel Sambuc krb5_prompter_fct prompter,
235ebfedea0SLionel Sambuc krb5_data *data,
236ebfedea0SLionel Sambuc const char *str,
237ebfedea0SLionel Sambuc time_t now)
238ebfedea0SLionel Sambuc {
239ebfedea0SLionel Sambuc char *p = NULL;
240ebfedea0SLionel Sambuc
241ebfedea0SLionel Sambuc if (asprintf(&p, "%s%s", str, ctime(&now)) < 0 || p == NULL)
242ebfedea0SLionel Sambuc return;
243ebfedea0SLionel Sambuc (*prompter)(context, data, NULL, p, 0, NULL);
244ebfedea0SLionel Sambuc free(p);
245ebfedea0SLionel Sambuc }
246ebfedea0SLionel Sambuc
247ebfedea0SLionel Sambuc /*
248ebfedea0SLionel Sambuc * Check the context, and in the case there is a expiration warning,
249ebfedea0SLionel Sambuc * use the prompter to print the warning.
250ebfedea0SLionel Sambuc *
251ebfedea0SLionel Sambuc * @param context A Kerberos 5 context.
252ebfedea0SLionel Sambuc * @param options An GIC options structure
253ebfedea0SLionel Sambuc * @param ctx The krb5_init_creds_context check for expiration.
254ebfedea0SLionel Sambuc */
255ebfedea0SLionel Sambuc
256ebfedea0SLionel Sambuc static krb5_error_code
process_last_request(krb5_context context,krb5_get_init_creds_opt * options,krb5_init_creds_context ctx)257ebfedea0SLionel Sambuc process_last_request(krb5_context context,
258ebfedea0SLionel Sambuc krb5_get_init_creds_opt *options,
259ebfedea0SLionel Sambuc krb5_init_creds_context ctx)
260ebfedea0SLionel Sambuc {
261ebfedea0SLionel Sambuc krb5_const_realm realm;
262ebfedea0SLionel Sambuc LastReq *lr;
263ebfedea0SLionel Sambuc krb5_boolean reported = FALSE;
264ebfedea0SLionel Sambuc krb5_timestamp sec;
265ebfedea0SLionel Sambuc time_t t;
266ebfedea0SLionel Sambuc size_t i;
267ebfedea0SLionel Sambuc
268ebfedea0SLionel Sambuc /*
269ebfedea0SLionel Sambuc * First check if there is a API consumer.
270ebfedea0SLionel Sambuc */
271ebfedea0SLionel Sambuc
272ebfedea0SLionel Sambuc realm = krb5_principal_get_realm (context, ctx->cred.client);
273ebfedea0SLionel Sambuc lr = &ctx->enc_part.last_req;
274ebfedea0SLionel Sambuc
275ebfedea0SLionel Sambuc if (options && options->opt_private && options->opt_private->lr.func) {
276ebfedea0SLionel Sambuc krb5_last_req_entry **lre;
277ebfedea0SLionel Sambuc
278ebfedea0SLionel Sambuc lre = calloc(lr->len + 1, sizeof(**lre));
279ebfedea0SLionel Sambuc if (lre == NULL) {
280ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM,
281ebfedea0SLionel Sambuc N_("malloc: out of memory", ""));
282ebfedea0SLionel Sambuc return ENOMEM;
283ebfedea0SLionel Sambuc }
284ebfedea0SLionel Sambuc for (i = 0; i < lr->len; i++) {
285ebfedea0SLionel Sambuc lre[i] = calloc(1, sizeof(*lre[i]));
286ebfedea0SLionel Sambuc if (lre[i] == NULL)
287ebfedea0SLionel Sambuc break;
288ebfedea0SLionel Sambuc lre[i]->lr_type = lr->val[i].lr_type;
289ebfedea0SLionel Sambuc lre[i]->value = lr->val[i].lr_value;
290ebfedea0SLionel Sambuc }
291ebfedea0SLionel Sambuc
292ebfedea0SLionel Sambuc (*options->opt_private->lr.func)(context, lre,
293ebfedea0SLionel Sambuc options->opt_private->lr.ctx);
294ebfedea0SLionel Sambuc
295ebfedea0SLionel Sambuc for (i = 0; i < lr->len; i++)
296ebfedea0SLionel Sambuc free(lre[i]);
297ebfedea0SLionel Sambuc free(lre);
298ebfedea0SLionel Sambuc }
299ebfedea0SLionel Sambuc
300ebfedea0SLionel Sambuc /*
301ebfedea0SLionel Sambuc * Now check if we should prompt the user
302ebfedea0SLionel Sambuc */
303ebfedea0SLionel Sambuc
304ebfedea0SLionel Sambuc if (ctx->prompter == NULL)
305ebfedea0SLionel Sambuc return 0;
306ebfedea0SLionel Sambuc
307ebfedea0SLionel Sambuc krb5_timeofday (context, &sec);
308ebfedea0SLionel Sambuc
309ebfedea0SLionel Sambuc t = sec + get_config_time (context,
310ebfedea0SLionel Sambuc realm,
311ebfedea0SLionel Sambuc "warn_pwexpire",
312ebfedea0SLionel Sambuc 7 * 24 * 60 * 60);
313ebfedea0SLionel Sambuc
314ebfedea0SLionel Sambuc for (i = 0; i < lr->len; ++i) {
315ebfedea0SLionel Sambuc if (lr->val[i].lr_value <= t) {
316ebfedea0SLionel Sambuc switch (abs(lr->val[i].lr_type)) {
317ebfedea0SLionel Sambuc case LR_PW_EXPTIME :
318ebfedea0SLionel Sambuc report_expiration(context, ctx->prompter,
319ebfedea0SLionel Sambuc ctx->prompter_data,
320ebfedea0SLionel Sambuc "Your password will expire at ",
321ebfedea0SLionel Sambuc lr->val[i].lr_value);
322ebfedea0SLionel Sambuc reported = TRUE;
323ebfedea0SLionel Sambuc break;
324ebfedea0SLionel Sambuc case LR_ACCT_EXPTIME :
325ebfedea0SLionel Sambuc report_expiration(context, ctx->prompter,
326ebfedea0SLionel Sambuc ctx->prompter_data,
327ebfedea0SLionel Sambuc "Your account will expire at ",
328ebfedea0SLionel Sambuc lr->val[i].lr_value);
329ebfedea0SLionel Sambuc reported = TRUE;
330ebfedea0SLionel Sambuc break;
331ebfedea0SLionel Sambuc }
332ebfedea0SLionel Sambuc }
333ebfedea0SLionel Sambuc }
334ebfedea0SLionel Sambuc
335ebfedea0SLionel Sambuc if (!reported
336ebfedea0SLionel Sambuc && ctx->enc_part.key_expiration
337ebfedea0SLionel Sambuc && *ctx->enc_part.key_expiration <= t) {
338ebfedea0SLionel Sambuc report_expiration(context, ctx->prompter,
339ebfedea0SLionel Sambuc ctx->prompter_data,
340ebfedea0SLionel Sambuc "Your password/account will expire at ",
341ebfedea0SLionel Sambuc *ctx->enc_part.key_expiration);
342ebfedea0SLionel Sambuc }
343ebfedea0SLionel Sambuc return 0;
344ebfedea0SLionel Sambuc }
345ebfedea0SLionel Sambuc
346ebfedea0SLionel Sambuc static krb5_addresses no_addrs = { 0, NULL };
347ebfedea0SLionel Sambuc
348ebfedea0SLionel Sambuc static krb5_error_code
get_init_creds_common(krb5_context context,krb5_principal client,krb5_deltat start_time,krb5_get_init_creds_opt * options,krb5_init_creds_context ctx)349ebfedea0SLionel Sambuc get_init_creds_common(krb5_context context,
350ebfedea0SLionel Sambuc krb5_principal client,
351ebfedea0SLionel Sambuc krb5_deltat start_time,
352ebfedea0SLionel Sambuc krb5_get_init_creds_opt *options,
353ebfedea0SLionel Sambuc krb5_init_creds_context ctx)
354ebfedea0SLionel Sambuc {
355ebfedea0SLionel Sambuc krb5_get_init_creds_opt *default_opt = NULL;
356ebfedea0SLionel Sambuc krb5_error_code ret;
357ebfedea0SLionel Sambuc krb5_enctype *etypes;
358ebfedea0SLionel Sambuc krb5_preauthtype *pre_auth_types;
359ebfedea0SLionel Sambuc
360ebfedea0SLionel Sambuc memset(ctx, 0, sizeof(*ctx));
361ebfedea0SLionel Sambuc
362ebfedea0SLionel Sambuc if (options == NULL) {
363ebfedea0SLionel Sambuc const char *realm = krb5_principal_get_realm(context, client);
364ebfedea0SLionel Sambuc
365ebfedea0SLionel Sambuc krb5_get_init_creds_opt_alloc (context, &default_opt);
366ebfedea0SLionel Sambuc options = default_opt;
367ebfedea0SLionel Sambuc krb5_get_init_creds_opt_set_default_flags(context, NULL, realm, options);
368ebfedea0SLionel Sambuc }
369ebfedea0SLionel Sambuc
370ebfedea0SLionel Sambuc if (options->opt_private) {
371ebfedea0SLionel Sambuc if (options->opt_private->password) {
372ebfedea0SLionel Sambuc ret = krb5_init_creds_set_password(context, ctx,
373ebfedea0SLionel Sambuc options->opt_private->password);
374ebfedea0SLionel Sambuc if (ret)
375ebfedea0SLionel Sambuc goto out;
376ebfedea0SLionel Sambuc }
377ebfedea0SLionel Sambuc
378ebfedea0SLionel Sambuc ctx->keyproc = options->opt_private->key_proc;
379ebfedea0SLionel Sambuc ctx->req_pac = options->opt_private->req_pac;
380ebfedea0SLionel Sambuc ctx->pk_init_ctx = options->opt_private->pk_init_ctx;
381ebfedea0SLionel Sambuc ctx->ic_flags = options->opt_private->flags;
382ebfedea0SLionel Sambuc } else
383ebfedea0SLionel Sambuc ctx->req_pac = KRB5_INIT_CREDS_TRISTATE_UNSET;
384ebfedea0SLionel Sambuc
385ebfedea0SLionel Sambuc if (ctx->keyproc == NULL)
386ebfedea0SLionel Sambuc ctx->keyproc = default_s2k_func;
387ebfedea0SLionel Sambuc
388ebfedea0SLionel Sambuc /* Enterprise name implicitly turns on canonicalize */
389ebfedea0SLionel Sambuc if ((ctx->ic_flags & KRB5_INIT_CREDS_CANONICALIZE) ||
390ebfedea0SLionel Sambuc krb5_principal_get_type(context, client) == KRB5_NT_ENTERPRISE_PRINCIPAL)
391ebfedea0SLionel Sambuc ctx->flags.canonicalize = 1;
392ebfedea0SLionel Sambuc
393ebfedea0SLionel Sambuc ctx->pre_auth_types = NULL;
394ebfedea0SLionel Sambuc ctx->addrs = NULL;
395ebfedea0SLionel Sambuc ctx->etypes = NULL;
396ebfedea0SLionel Sambuc ctx->pre_auth_types = NULL;
397ebfedea0SLionel Sambuc
398ebfedea0SLionel Sambuc ret = init_cred(context, &ctx->cred, client, start_time, options);
399ebfedea0SLionel Sambuc if (ret) {
400ebfedea0SLionel Sambuc if (default_opt)
401ebfedea0SLionel Sambuc krb5_get_init_creds_opt_free(context, default_opt);
402ebfedea0SLionel Sambuc return ret;
403ebfedea0SLionel Sambuc }
404ebfedea0SLionel Sambuc
405ebfedea0SLionel Sambuc ret = krb5_init_creds_set_service(context, ctx, NULL);
406ebfedea0SLionel Sambuc if (ret)
407ebfedea0SLionel Sambuc goto out;
408ebfedea0SLionel Sambuc
409ebfedea0SLionel Sambuc if (options->flags & KRB5_GET_INIT_CREDS_OPT_FORWARDABLE)
410ebfedea0SLionel Sambuc ctx->flags.forwardable = options->forwardable;
411ebfedea0SLionel Sambuc
412ebfedea0SLionel Sambuc if (options->flags & KRB5_GET_INIT_CREDS_OPT_PROXIABLE)
413ebfedea0SLionel Sambuc ctx->flags.proxiable = options->proxiable;
414ebfedea0SLionel Sambuc
415ebfedea0SLionel Sambuc if (start_time)
416ebfedea0SLionel Sambuc ctx->flags.postdated = 1;
417ebfedea0SLionel Sambuc if (ctx->cred.times.renew_till)
418ebfedea0SLionel Sambuc ctx->flags.renewable = 1;
419ebfedea0SLionel Sambuc if (options->flags & KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST) {
420ebfedea0SLionel Sambuc ctx->addrs = options->address_list;
421ebfedea0SLionel Sambuc } else if (options->opt_private) {
422ebfedea0SLionel Sambuc switch (options->opt_private->addressless) {
423ebfedea0SLionel Sambuc case KRB5_INIT_CREDS_TRISTATE_UNSET:
424ebfedea0SLionel Sambuc #if KRB5_ADDRESSLESS_DEFAULT == TRUE
425ebfedea0SLionel Sambuc ctx->addrs = &no_addrs;
426ebfedea0SLionel Sambuc #else
427ebfedea0SLionel Sambuc ctx->addrs = NULL;
428ebfedea0SLionel Sambuc #endif
429ebfedea0SLionel Sambuc break;
430ebfedea0SLionel Sambuc case KRB5_INIT_CREDS_TRISTATE_FALSE:
431ebfedea0SLionel Sambuc ctx->addrs = NULL;
432ebfedea0SLionel Sambuc break;
433ebfedea0SLionel Sambuc case KRB5_INIT_CREDS_TRISTATE_TRUE:
434ebfedea0SLionel Sambuc ctx->addrs = &no_addrs;
435ebfedea0SLionel Sambuc break;
436ebfedea0SLionel Sambuc }
437ebfedea0SLionel Sambuc }
438ebfedea0SLionel Sambuc if (options->flags & KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST) {
439ebfedea0SLionel Sambuc if (ctx->etypes)
440ebfedea0SLionel Sambuc free(ctx->etypes);
441ebfedea0SLionel Sambuc
442ebfedea0SLionel Sambuc etypes = malloc((options->etype_list_length + 1)
443ebfedea0SLionel Sambuc * sizeof(krb5_enctype));
444ebfedea0SLionel Sambuc if (etypes == NULL) {
445ebfedea0SLionel Sambuc ret = ENOMEM;
446ebfedea0SLionel Sambuc krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
447ebfedea0SLionel Sambuc goto out;
448ebfedea0SLionel Sambuc }
449ebfedea0SLionel Sambuc memcpy (etypes, options->etype_list,
450ebfedea0SLionel Sambuc options->etype_list_length * sizeof(krb5_enctype));
451ebfedea0SLionel Sambuc etypes[options->etype_list_length] = ETYPE_NULL;
452ebfedea0SLionel Sambuc ctx->etypes = etypes;
453ebfedea0SLionel Sambuc }
454ebfedea0SLionel Sambuc if (options->flags & KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST) {
455ebfedea0SLionel Sambuc pre_auth_types = malloc((options->preauth_list_length + 1)
456ebfedea0SLionel Sambuc * sizeof(krb5_preauthtype));
457ebfedea0SLionel Sambuc if (pre_auth_types == NULL) {
458ebfedea0SLionel Sambuc ret = ENOMEM;
459ebfedea0SLionel Sambuc krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
460ebfedea0SLionel Sambuc goto out;
461ebfedea0SLionel Sambuc }
462ebfedea0SLionel Sambuc memcpy (pre_auth_types, options->preauth_list,
463ebfedea0SLionel Sambuc options->preauth_list_length * sizeof(krb5_preauthtype));
464ebfedea0SLionel Sambuc pre_auth_types[options->preauth_list_length] = KRB5_PADATA_NONE;
465ebfedea0SLionel Sambuc ctx->pre_auth_types = pre_auth_types;
466ebfedea0SLionel Sambuc }
467ebfedea0SLionel Sambuc if (options->flags & KRB5_GET_INIT_CREDS_OPT_ANONYMOUS)
468ebfedea0SLionel Sambuc ctx->flags.request_anonymous = options->anonymous;
469ebfedea0SLionel Sambuc if (default_opt)
470ebfedea0SLionel Sambuc krb5_get_init_creds_opt_free(context, default_opt);
471ebfedea0SLionel Sambuc return 0;
472ebfedea0SLionel Sambuc out:
473ebfedea0SLionel Sambuc if (default_opt)
474ebfedea0SLionel Sambuc krb5_get_init_creds_opt_free(context, default_opt);
475ebfedea0SLionel Sambuc return ret;
476ebfedea0SLionel Sambuc }
477ebfedea0SLionel Sambuc
478ebfedea0SLionel Sambuc static krb5_error_code
change_password(krb5_context context,krb5_principal client,const char * password,char * newpw,size_t newpw_sz,krb5_prompter_fct prompter,void * data,krb5_get_init_creds_opt * old_options)479ebfedea0SLionel Sambuc change_password (krb5_context context,
480ebfedea0SLionel Sambuc krb5_principal client,
481ebfedea0SLionel Sambuc const char *password,
482ebfedea0SLionel Sambuc char *newpw,
483ebfedea0SLionel Sambuc size_t newpw_sz,
484ebfedea0SLionel Sambuc krb5_prompter_fct prompter,
485ebfedea0SLionel Sambuc void *data,
486ebfedea0SLionel Sambuc krb5_get_init_creds_opt *old_options)
487ebfedea0SLionel Sambuc {
488ebfedea0SLionel Sambuc krb5_prompt prompts[2];
489ebfedea0SLionel Sambuc krb5_error_code ret;
490ebfedea0SLionel Sambuc krb5_creds cpw_cred;
491ebfedea0SLionel Sambuc char buf1[BUFSIZ], buf2[BUFSIZ];
492ebfedea0SLionel Sambuc krb5_data password_data[2];
493ebfedea0SLionel Sambuc int result_code;
494ebfedea0SLionel Sambuc krb5_data result_code_string;
495ebfedea0SLionel Sambuc krb5_data result_string;
496ebfedea0SLionel Sambuc char *p;
497ebfedea0SLionel Sambuc krb5_get_init_creds_opt *options;
498ebfedea0SLionel Sambuc
499ebfedea0SLionel Sambuc memset (&cpw_cred, 0, sizeof(cpw_cred));
500ebfedea0SLionel Sambuc
501ebfedea0SLionel Sambuc ret = krb5_get_init_creds_opt_alloc(context, &options);
502ebfedea0SLionel Sambuc if (ret)
503ebfedea0SLionel Sambuc return ret;
504ebfedea0SLionel Sambuc krb5_get_init_creds_opt_set_tkt_life (options, 60);
505ebfedea0SLionel Sambuc krb5_get_init_creds_opt_set_forwardable (options, FALSE);
506ebfedea0SLionel Sambuc krb5_get_init_creds_opt_set_proxiable (options, FALSE);
507ebfedea0SLionel Sambuc if (old_options && old_options->flags & KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST)
508ebfedea0SLionel Sambuc krb5_get_init_creds_opt_set_preauth_list (options,
509ebfedea0SLionel Sambuc old_options->preauth_list,
510ebfedea0SLionel Sambuc old_options->preauth_list_length);
511ebfedea0SLionel Sambuc
512ebfedea0SLionel Sambuc krb5_data_zero (&result_code_string);
513ebfedea0SLionel Sambuc krb5_data_zero (&result_string);
514ebfedea0SLionel Sambuc
515ebfedea0SLionel Sambuc ret = krb5_get_init_creds_password (context,
516ebfedea0SLionel Sambuc &cpw_cred,
517ebfedea0SLionel Sambuc client,
518ebfedea0SLionel Sambuc password,
519ebfedea0SLionel Sambuc prompter,
520ebfedea0SLionel Sambuc data,
521ebfedea0SLionel Sambuc 0,
522ebfedea0SLionel Sambuc "kadmin/changepw",
523ebfedea0SLionel Sambuc options);
524ebfedea0SLionel Sambuc krb5_get_init_creds_opt_free(context, options);
525ebfedea0SLionel Sambuc if (ret)
526ebfedea0SLionel Sambuc goto out;
527ebfedea0SLionel Sambuc
528ebfedea0SLionel Sambuc for(;;) {
529ebfedea0SLionel Sambuc password_data[0].data = buf1;
530ebfedea0SLionel Sambuc password_data[0].length = sizeof(buf1);
531ebfedea0SLionel Sambuc
532ebfedea0SLionel Sambuc prompts[0].hidden = 1;
533ebfedea0SLionel Sambuc prompts[0].prompt = "New password: ";
534ebfedea0SLionel Sambuc prompts[0].reply = &password_data[0];
535ebfedea0SLionel Sambuc prompts[0].type = KRB5_PROMPT_TYPE_NEW_PASSWORD;
536ebfedea0SLionel Sambuc
537ebfedea0SLionel Sambuc password_data[1].data = buf2;
538ebfedea0SLionel Sambuc password_data[1].length = sizeof(buf2);
539ebfedea0SLionel Sambuc
540ebfedea0SLionel Sambuc prompts[1].hidden = 1;
541ebfedea0SLionel Sambuc prompts[1].prompt = "Repeat new password: ";
542ebfedea0SLionel Sambuc prompts[1].reply = &password_data[1];
543ebfedea0SLionel Sambuc prompts[1].type = KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN;
544ebfedea0SLionel Sambuc
545ebfedea0SLionel Sambuc ret = (*prompter) (context, data, NULL, "Changing password",
546ebfedea0SLionel Sambuc 2, prompts);
547ebfedea0SLionel Sambuc if (ret) {
548ebfedea0SLionel Sambuc memset (buf1, 0, sizeof(buf1));
549ebfedea0SLionel Sambuc memset (buf2, 0, sizeof(buf2));
550ebfedea0SLionel Sambuc goto out;
551ebfedea0SLionel Sambuc }
552ebfedea0SLionel Sambuc
553ebfedea0SLionel Sambuc if (strcmp (buf1, buf2) == 0)
554ebfedea0SLionel Sambuc break;
555ebfedea0SLionel Sambuc memset (buf1, 0, sizeof(buf1));
556ebfedea0SLionel Sambuc memset (buf2, 0, sizeof(buf2));
557ebfedea0SLionel Sambuc }
558ebfedea0SLionel Sambuc
559ebfedea0SLionel Sambuc ret = krb5_set_password (context,
560ebfedea0SLionel Sambuc &cpw_cred,
561ebfedea0SLionel Sambuc buf1,
562ebfedea0SLionel Sambuc client,
563ebfedea0SLionel Sambuc &result_code,
564ebfedea0SLionel Sambuc &result_code_string,
565ebfedea0SLionel Sambuc &result_string);
566ebfedea0SLionel Sambuc if (ret)
567ebfedea0SLionel Sambuc goto out;
568ebfedea0SLionel Sambuc if (asprintf(&p, "%s: %.*s\n",
569ebfedea0SLionel Sambuc result_code ? "Error" : "Success",
570ebfedea0SLionel Sambuc (int)result_string.length,
571ebfedea0SLionel Sambuc result_string.length > 0 ? (char*)result_string.data : "") < 0)
572ebfedea0SLionel Sambuc {
573ebfedea0SLionel Sambuc ret = ENOMEM;
574ebfedea0SLionel Sambuc goto out;
575ebfedea0SLionel Sambuc }
576ebfedea0SLionel Sambuc
577ebfedea0SLionel Sambuc /* return the result */
578ebfedea0SLionel Sambuc (*prompter) (context, data, NULL, p, 0, NULL);
579ebfedea0SLionel Sambuc
580ebfedea0SLionel Sambuc free (p);
581ebfedea0SLionel Sambuc if (result_code == 0) {
582ebfedea0SLionel Sambuc strlcpy (newpw, buf1, newpw_sz);
583ebfedea0SLionel Sambuc ret = 0;
584ebfedea0SLionel Sambuc } else {
585ebfedea0SLionel Sambuc ret = ENOTTY;
586ebfedea0SLionel Sambuc krb5_set_error_message(context, ret,
587ebfedea0SLionel Sambuc N_("failed changing password", ""));
588ebfedea0SLionel Sambuc }
589ebfedea0SLionel Sambuc
590ebfedea0SLionel Sambuc out:
591ebfedea0SLionel Sambuc memset (buf1, 0, sizeof(buf1));
592ebfedea0SLionel Sambuc memset (buf2, 0, sizeof(buf2));
593ebfedea0SLionel Sambuc krb5_data_free (&result_string);
594ebfedea0SLionel Sambuc krb5_data_free (&result_code_string);
595ebfedea0SLionel Sambuc krb5_free_cred_contents (context, &cpw_cred);
596ebfedea0SLionel Sambuc return ret;
597ebfedea0SLionel Sambuc }
598ebfedea0SLionel Sambuc
599ebfedea0SLionel Sambuc
600ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_keyblock_key_proc(krb5_context context,krb5_keytype type,krb5_data * salt,krb5_const_pointer keyseed,krb5_keyblock ** key)601ebfedea0SLionel Sambuc krb5_keyblock_key_proc (krb5_context context,
602ebfedea0SLionel Sambuc krb5_keytype type,
603ebfedea0SLionel Sambuc krb5_data *salt,
604ebfedea0SLionel Sambuc krb5_const_pointer keyseed,
605ebfedea0SLionel Sambuc krb5_keyblock **key)
606ebfedea0SLionel Sambuc {
607ebfedea0SLionel Sambuc return krb5_copy_keyblock (context, keyseed, key);
608ebfedea0SLionel Sambuc }
609ebfedea0SLionel Sambuc
610ebfedea0SLionel Sambuc /*
611ebfedea0SLionel Sambuc *
612ebfedea0SLionel Sambuc */
613ebfedea0SLionel Sambuc
614ebfedea0SLionel Sambuc static krb5_error_code
init_as_req(krb5_context context,KDCOptions opts,const krb5_creds * creds,const krb5_addresses * addrs,const krb5_enctype * etypes,AS_REQ * a)615ebfedea0SLionel Sambuc init_as_req (krb5_context context,
616ebfedea0SLionel Sambuc KDCOptions opts,
617ebfedea0SLionel Sambuc const krb5_creds *creds,
618ebfedea0SLionel Sambuc const krb5_addresses *addrs,
619ebfedea0SLionel Sambuc const krb5_enctype *etypes,
620ebfedea0SLionel Sambuc AS_REQ *a)
621ebfedea0SLionel Sambuc {
622ebfedea0SLionel Sambuc krb5_error_code ret;
623ebfedea0SLionel Sambuc
624ebfedea0SLionel Sambuc memset(a, 0, sizeof(*a));
625ebfedea0SLionel Sambuc
626ebfedea0SLionel Sambuc a->pvno = 5;
627ebfedea0SLionel Sambuc a->msg_type = krb_as_req;
628ebfedea0SLionel Sambuc a->req_body.kdc_options = opts;
629ebfedea0SLionel Sambuc a->req_body.cname = malloc(sizeof(*a->req_body.cname));
630ebfedea0SLionel Sambuc if (a->req_body.cname == NULL) {
631ebfedea0SLionel Sambuc ret = ENOMEM;
632ebfedea0SLionel Sambuc krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
633ebfedea0SLionel Sambuc goto fail;
634ebfedea0SLionel Sambuc }
635ebfedea0SLionel Sambuc a->req_body.sname = malloc(sizeof(*a->req_body.sname));
636ebfedea0SLionel Sambuc if (a->req_body.sname == NULL) {
637ebfedea0SLionel Sambuc ret = ENOMEM;
638ebfedea0SLionel Sambuc krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
639ebfedea0SLionel Sambuc goto fail;
640ebfedea0SLionel Sambuc }
641ebfedea0SLionel Sambuc
642ebfedea0SLionel Sambuc ret = _krb5_principal2principalname (a->req_body.cname, creds->client);
643ebfedea0SLionel Sambuc if (ret)
644ebfedea0SLionel Sambuc goto fail;
645ebfedea0SLionel Sambuc ret = copy_Realm(&creds->client->realm, &a->req_body.realm);
646ebfedea0SLionel Sambuc if (ret)
647ebfedea0SLionel Sambuc goto fail;
648ebfedea0SLionel Sambuc
649ebfedea0SLionel Sambuc ret = _krb5_principal2principalname (a->req_body.sname, creds->server);
650ebfedea0SLionel Sambuc if (ret)
651ebfedea0SLionel Sambuc goto fail;
652ebfedea0SLionel Sambuc
653ebfedea0SLionel Sambuc if(creds->times.starttime) {
654ebfedea0SLionel Sambuc a->req_body.from = malloc(sizeof(*a->req_body.from));
655ebfedea0SLionel Sambuc if (a->req_body.from == NULL) {
656ebfedea0SLionel Sambuc ret = ENOMEM;
657ebfedea0SLionel Sambuc krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
658ebfedea0SLionel Sambuc goto fail;
659ebfedea0SLionel Sambuc }
660ebfedea0SLionel Sambuc *a->req_body.from = creds->times.starttime;
661ebfedea0SLionel Sambuc }
662ebfedea0SLionel Sambuc if(creds->times.endtime){
663ebfedea0SLionel Sambuc ALLOC(a->req_body.till, 1);
664ebfedea0SLionel Sambuc *a->req_body.till = creds->times.endtime;
665ebfedea0SLionel Sambuc }
666ebfedea0SLionel Sambuc if(creds->times.renew_till){
667ebfedea0SLionel Sambuc a->req_body.rtime = malloc(sizeof(*a->req_body.rtime));
668ebfedea0SLionel Sambuc if (a->req_body.rtime == NULL) {
669ebfedea0SLionel Sambuc ret = ENOMEM;
670ebfedea0SLionel Sambuc krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
671ebfedea0SLionel Sambuc goto fail;
672ebfedea0SLionel Sambuc }
673ebfedea0SLionel Sambuc *a->req_body.rtime = creds->times.renew_till;
674ebfedea0SLionel Sambuc }
675ebfedea0SLionel Sambuc a->req_body.nonce = 0;
676*0a6a1f1dSLionel Sambuc ret = _krb5_init_etype(context,
677*0a6a1f1dSLionel Sambuc KRB5_PDU_AS_REQUEST,
678ebfedea0SLionel Sambuc &a->req_body.etype.len,
679ebfedea0SLionel Sambuc &a->req_body.etype.val,
680ebfedea0SLionel Sambuc etypes);
681ebfedea0SLionel Sambuc if (ret)
682ebfedea0SLionel Sambuc goto fail;
683ebfedea0SLionel Sambuc
684ebfedea0SLionel Sambuc /*
685ebfedea0SLionel Sambuc * This means no addresses
686ebfedea0SLionel Sambuc */
687ebfedea0SLionel Sambuc
688ebfedea0SLionel Sambuc if (addrs && addrs->len == 0) {
689ebfedea0SLionel Sambuc a->req_body.addresses = NULL;
690ebfedea0SLionel Sambuc } else {
691ebfedea0SLionel Sambuc a->req_body.addresses = malloc(sizeof(*a->req_body.addresses));
692ebfedea0SLionel Sambuc if (a->req_body.addresses == NULL) {
693ebfedea0SLionel Sambuc ret = ENOMEM;
694ebfedea0SLionel Sambuc krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
695ebfedea0SLionel Sambuc goto fail;
696ebfedea0SLionel Sambuc }
697ebfedea0SLionel Sambuc
698ebfedea0SLionel Sambuc if (addrs)
699ebfedea0SLionel Sambuc ret = krb5_copy_addresses(context, addrs, a->req_body.addresses);
700ebfedea0SLionel Sambuc else {
701ebfedea0SLionel Sambuc ret = krb5_get_all_client_addrs (context, a->req_body.addresses);
702ebfedea0SLionel Sambuc if(ret == 0 && a->req_body.addresses->len == 0) {
703ebfedea0SLionel Sambuc free(a->req_body.addresses);
704ebfedea0SLionel Sambuc a->req_body.addresses = NULL;
705ebfedea0SLionel Sambuc }
706ebfedea0SLionel Sambuc }
707ebfedea0SLionel Sambuc if (ret)
708ebfedea0SLionel Sambuc goto fail;
709ebfedea0SLionel Sambuc }
710ebfedea0SLionel Sambuc
711ebfedea0SLionel Sambuc a->req_body.enc_authorization_data = NULL;
712ebfedea0SLionel Sambuc a->req_body.additional_tickets = NULL;
713ebfedea0SLionel Sambuc
714ebfedea0SLionel Sambuc a->padata = NULL;
715ebfedea0SLionel Sambuc
716ebfedea0SLionel Sambuc return 0;
717ebfedea0SLionel Sambuc fail:
718ebfedea0SLionel Sambuc free_AS_REQ(a);
719ebfedea0SLionel Sambuc memset(a, 0, sizeof(*a));
720ebfedea0SLionel Sambuc return ret;
721ebfedea0SLionel Sambuc }
722ebfedea0SLionel Sambuc
723ebfedea0SLionel Sambuc
724ebfedea0SLionel Sambuc static krb5_error_code
set_paid(struct pa_info_data * paid,krb5_context context,krb5_enctype etype,krb5_salttype salttype,void * salt_string,size_t salt_len,krb5_data * s2kparams)725ebfedea0SLionel Sambuc set_paid(struct pa_info_data *paid, krb5_context context,
726ebfedea0SLionel Sambuc krb5_enctype etype,
727ebfedea0SLionel Sambuc krb5_salttype salttype, void *salt_string, size_t salt_len,
728ebfedea0SLionel Sambuc krb5_data *s2kparams)
729ebfedea0SLionel Sambuc {
730ebfedea0SLionel Sambuc paid->etype = etype;
731ebfedea0SLionel Sambuc paid->salt.salttype = salttype;
732ebfedea0SLionel Sambuc paid->salt.saltvalue.data = malloc(salt_len + 1);
733ebfedea0SLionel Sambuc if (paid->salt.saltvalue.data == NULL) {
734ebfedea0SLionel Sambuc krb5_clear_error_message(context);
735ebfedea0SLionel Sambuc return ENOMEM;
736ebfedea0SLionel Sambuc }
737ebfedea0SLionel Sambuc memcpy(paid->salt.saltvalue.data, salt_string, salt_len);
738ebfedea0SLionel Sambuc ((char *)paid->salt.saltvalue.data)[salt_len] = '\0';
739ebfedea0SLionel Sambuc paid->salt.saltvalue.length = salt_len;
740ebfedea0SLionel Sambuc if (s2kparams) {
741ebfedea0SLionel Sambuc krb5_error_code ret;
742ebfedea0SLionel Sambuc
743ebfedea0SLionel Sambuc ret = krb5_copy_data(context, s2kparams, &paid->s2kparams);
744ebfedea0SLionel Sambuc if (ret) {
745ebfedea0SLionel Sambuc krb5_clear_error_message(context);
746ebfedea0SLionel Sambuc krb5_free_salt(context, paid->salt);
747ebfedea0SLionel Sambuc return ret;
748ebfedea0SLionel Sambuc }
749ebfedea0SLionel Sambuc } else
750ebfedea0SLionel Sambuc paid->s2kparams = NULL;
751ebfedea0SLionel Sambuc
752ebfedea0SLionel Sambuc return 0;
753ebfedea0SLionel Sambuc }
754ebfedea0SLionel Sambuc
755ebfedea0SLionel Sambuc static struct pa_info_data *
pa_etype_info2(krb5_context context,const krb5_principal client,const AS_REQ * asreq,struct pa_info_data * paid,heim_octet_string * data)756ebfedea0SLionel Sambuc pa_etype_info2(krb5_context context,
757ebfedea0SLionel Sambuc const krb5_principal client,
758ebfedea0SLionel Sambuc const AS_REQ *asreq,
759ebfedea0SLionel Sambuc struct pa_info_data *paid,
760ebfedea0SLionel Sambuc heim_octet_string *data)
761ebfedea0SLionel Sambuc {
762ebfedea0SLionel Sambuc krb5_error_code ret;
763ebfedea0SLionel Sambuc ETYPE_INFO2 e;
764ebfedea0SLionel Sambuc size_t sz;
765*0a6a1f1dSLionel Sambuc size_t i, j;
766ebfedea0SLionel Sambuc
767ebfedea0SLionel Sambuc memset(&e, 0, sizeof(e));
768ebfedea0SLionel Sambuc ret = decode_ETYPE_INFO2(data->data, data->length, &e, &sz);
769ebfedea0SLionel Sambuc if (ret)
770ebfedea0SLionel Sambuc goto out;
771ebfedea0SLionel Sambuc if (e.len == 0)
772ebfedea0SLionel Sambuc goto out;
773ebfedea0SLionel Sambuc for (j = 0; j < asreq->req_body.etype.len; j++) {
774ebfedea0SLionel Sambuc for (i = 0; i < e.len; i++) {
775ebfedea0SLionel Sambuc if (asreq->req_body.etype.val[j] == e.val[i].etype) {
776ebfedea0SLionel Sambuc krb5_salt salt;
777ebfedea0SLionel Sambuc if (e.val[i].salt == NULL)
778ebfedea0SLionel Sambuc ret = krb5_get_pw_salt(context, client, &salt);
779ebfedea0SLionel Sambuc else {
780ebfedea0SLionel Sambuc salt.saltvalue.data = *e.val[i].salt;
781ebfedea0SLionel Sambuc salt.saltvalue.length = strlen(*e.val[i].salt);
782ebfedea0SLionel Sambuc ret = 0;
783ebfedea0SLionel Sambuc }
784ebfedea0SLionel Sambuc if (ret == 0)
785ebfedea0SLionel Sambuc ret = set_paid(paid, context, e.val[i].etype,
786ebfedea0SLionel Sambuc KRB5_PW_SALT,
787ebfedea0SLionel Sambuc salt.saltvalue.data,
788ebfedea0SLionel Sambuc salt.saltvalue.length,
789ebfedea0SLionel Sambuc e.val[i].s2kparams);
790ebfedea0SLionel Sambuc if (e.val[i].salt == NULL)
791ebfedea0SLionel Sambuc krb5_free_salt(context, salt);
792ebfedea0SLionel Sambuc if (ret == 0) {
793ebfedea0SLionel Sambuc free_ETYPE_INFO2(&e);
794ebfedea0SLionel Sambuc return paid;
795ebfedea0SLionel Sambuc }
796ebfedea0SLionel Sambuc }
797ebfedea0SLionel Sambuc }
798ebfedea0SLionel Sambuc }
799ebfedea0SLionel Sambuc out:
800ebfedea0SLionel Sambuc free_ETYPE_INFO2(&e);
801ebfedea0SLionel Sambuc return NULL;
802ebfedea0SLionel Sambuc }
803ebfedea0SLionel Sambuc
804ebfedea0SLionel Sambuc static struct pa_info_data *
pa_etype_info(krb5_context context,const krb5_principal client,const AS_REQ * asreq,struct pa_info_data * paid,heim_octet_string * data)805ebfedea0SLionel Sambuc pa_etype_info(krb5_context context,
806ebfedea0SLionel Sambuc const krb5_principal client,
807ebfedea0SLionel Sambuc const AS_REQ *asreq,
808ebfedea0SLionel Sambuc struct pa_info_data *paid,
809ebfedea0SLionel Sambuc heim_octet_string *data)
810ebfedea0SLionel Sambuc {
811ebfedea0SLionel Sambuc krb5_error_code ret;
812ebfedea0SLionel Sambuc ETYPE_INFO e;
813ebfedea0SLionel Sambuc size_t sz;
814*0a6a1f1dSLionel Sambuc size_t i, j;
815ebfedea0SLionel Sambuc
816ebfedea0SLionel Sambuc memset(&e, 0, sizeof(e));
817ebfedea0SLionel Sambuc ret = decode_ETYPE_INFO(data->data, data->length, &e, &sz);
818ebfedea0SLionel Sambuc if (ret)
819ebfedea0SLionel Sambuc goto out;
820ebfedea0SLionel Sambuc if (e.len == 0)
821ebfedea0SLionel Sambuc goto out;
822ebfedea0SLionel Sambuc for (j = 0; j < asreq->req_body.etype.len; j++) {
823ebfedea0SLionel Sambuc for (i = 0; i < e.len; i++) {
824ebfedea0SLionel Sambuc if (asreq->req_body.etype.val[j] == e.val[i].etype) {
825ebfedea0SLionel Sambuc krb5_salt salt;
826ebfedea0SLionel Sambuc salt.salttype = KRB5_PW_SALT;
827ebfedea0SLionel Sambuc if (e.val[i].salt == NULL)
828ebfedea0SLionel Sambuc ret = krb5_get_pw_salt(context, client, &salt);
829ebfedea0SLionel Sambuc else {
830ebfedea0SLionel Sambuc salt.saltvalue = *e.val[i].salt;
831ebfedea0SLionel Sambuc ret = 0;
832ebfedea0SLionel Sambuc }
833ebfedea0SLionel Sambuc if (e.val[i].salttype)
834ebfedea0SLionel Sambuc salt.salttype = *e.val[i].salttype;
835ebfedea0SLionel Sambuc if (ret == 0) {
836ebfedea0SLionel Sambuc ret = set_paid(paid, context, e.val[i].etype,
837ebfedea0SLionel Sambuc salt.salttype,
838ebfedea0SLionel Sambuc salt.saltvalue.data,
839ebfedea0SLionel Sambuc salt.saltvalue.length,
840ebfedea0SLionel Sambuc NULL);
841ebfedea0SLionel Sambuc if (e.val[i].salt == NULL)
842ebfedea0SLionel Sambuc krb5_free_salt(context, salt);
843ebfedea0SLionel Sambuc }
844ebfedea0SLionel Sambuc if (ret == 0) {
845ebfedea0SLionel Sambuc free_ETYPE_INFO(&e);
846ebfedea0SLionel Sambuc return paid;
847ebfedea0SLionel Sambuc }
848ebfedea0SLionel Sambuc }
849ebfedea0SLionel Sambuc }
850ebfedea0SLionel Sambuc }
851ebfedea0SLionel Sambuc out:
852ebfedea0SLionel Sambuc free_ETYPE_INFO(&e);
853ebfedea0SLionel Sambuc return NULL;
854ebfedea0SLionel Sambuc }
855ebfedea0SLionel Sambuc
856ebfedea0SLionel Sambuc static struct pa_info_data *
pa_pw_or_afs3_salt(krb5_context context,const krb5_principal client,const AS_REQ * asreq,struct pa_info_data * paid,heim_octet_string * data)857ebfedea0SLionel Sambuc pa_pw_or_afs3_salt(krb5_context context,
858ebfedea0SLionel Sambuc const krb5_principal client,
859ebfedea0SLionel Sambuc const AS_REQ *asreq,
860ebfedea0SLionel Sambuc struct pa_info_data *paid,
861ebfedea0SLionel Sambuc heim_octet_string *data)
862ebfedea0SLionel Sambuc {
863ebfedea0SLionel Sambuc krb5_error_code ret;
864ebfedea0SLionel Sambuc if (paid->etype == ENCTYPE_NULL)
865ebfedea0SLionel Sambuc return NULL;
866ebfedea0SLionel Sambuc ret = set_paid(paid, context,
867ebfedea0SLionel Sambuc paid->etype,
868ebfedea0SLionel Sambuc paid->salt.salttype,
869ebfedea0SLionel Sambuc data->data,
870ebfedea0SLionel Sambuc data->length,
871ebfedea0SLionel Sambuc NULL);
872ebfedea0SLionel Sambuc if (ret)
873ebfedea0SLionel Sambuc return NULL;
874ebfedea0SLionel Sambuc return paid;
875ebfedea0SLionel Sambuc }
876ebfedea0SLionel Sambuc
877ebfedea0SLionel Sambuc
878ebfedea0SLionel Sambuc struct pa_info {
879ebfedea0SLionel Sambuc krb5_preauthtype type;
880ebfedea0SLionel Sambuc struct pa_info_data *(*salt_info)(krb5_context,
881ebfedea0SLionel Sambuc const krb5_principal,
882ebfedea0SLionel Sambuc const AS_REQ *,
883ebfedea0SLionel Sambuc struct pa_info_data *,
884ebfedea0SLionel Sambuc heim_octet_string *);
885ebfedea0SLionel Sambuc };
886ebfedea0SLionel Sambuc
887ebfedea0SLionel Sambuc static struct pa_info pa_prefs[] = {
888ebfedea0SLionel Sambuc { KRB5_PADATA_ETYPE_INFO2, pa_etype_info2 },
889ebfedea0SLionel Sambuc { KRB5_PADATA_ETYPE_INFO, pa_etype_info },
890ebfedea0SLionel Sambuc { KRB5_PADATA_PW_SALT, pa_pw_or_afs3_salt },
891ebfedea0SLionel Sambuc { KRB5_PADATA_AFS3_SALT, pa_pw_or_afs3_salt }
892ebfedea0SLionel Sambuc };
893ebfedea0SLionel Sambuc
894ebfedea0SLionel Sambuc static PA_DATA *
find_pa_data(const METHOD_DATA * md,unsigned type)895*0a6a1f1dSLionel Sambuc find_pa_data(const METHOD_DATA *md, unsigned type)
896ebfedea0SLionel Sambuc {
897*0a6a1f1dSLionel Sambuc size_t i;
898ebfedea0SLionel Sambuc if (md == NULL)
899ebfedea0SLionel Sambuc return NULL;
900ebfedea0SLionel Sambuc for (i = 0; i < md->len; i++)
901ebfedea0SLionel Sambuc if (md->val[i].padata_type == type)
902ebfedea0SLionel Sambuc return &md->val[i];
903ebfedea0SLionel Sambuc return NULL;
904ebfedea0SLionel Sambuc }
905ebfedea0SLionel Sambuc
906ebfedea0SLionel Sambuc static struct pa_info_data *
process_pa_info(krb5_context context,const krb5_principal client,const AS_REQ * asreq,struct pa_info_data * paid,METHOD_DATA * md)907ebfedea0SLionel Sambuc process_pa_info(krb5_context context,
908ebfedea0SLionel Sambuc const krb5_principal client,
909ebfedea0SLionel Sambuc const AS_REQ *asreq,
910ebfedea0SLionel Sambuc struct pa_info_data *paid,
911ebfedea0SLionel Sambuc METHOD_DATA *md)
912ebfedea0SLionel Sambuc {
913ebfedea0SLionel Sambuc struct pa_info_data *p = NULL;
914*0a6a1f1dSLionel Sambuc size_t i;
915ebfedea0SLionel Sambuc
916ebfedea0SLionel Sambuc for (i = 0; p == NULL && i < sizeof(pa_prefs)/sizeof(pa_prefs[0]); i++) {
917ebfedea0SLionel Sambuc PA_DATA *pa = find_pa_data(md, pa_prefs[i].type);
918ebfedea0SLionel Sambuc if (pa == NULL)
919ebfedea0SLionel Sambuc continue;
920*0a6a1f1dSLionel Sambuc paid->salt.salttype = (krb5_salttype)pa_prefs[i].type;
921ebfedea0SLionel Sambuc p = (*pa_prefs[i].salt_info)(context, client, asreq,
922ebfedea0SLionel Sambuc paid, &pa->padata_value);
923ebfedea0SLionel Sambuc }
924ebfedea0SLionel Sambuc return p;
925ebfedea0SLionel Sambuc }
926ebfedea0SLionel Sambuc
927ebfedea0SLionel Sambuc static krb5_error_code
make_pa_enc_timestamp(krb5_context context,METHOD_DATA * md,krb5_enctype etype,krb5_keyblock * key)928ebfedea0SLionel Sambuc make_pa_enc_timestamp(krb5_context context, METHOD_DATA *md,
929ebfedea0SLionel Sambuc krb5_enctype etype, krb5_keyblock *key)
930ebfedea0SLionel Sambuc {
931ebfedea0SLionel Sambuc PA_ENC_TS_ENC p;
932ebfedea0SLionel Sambuc unsigned char *buf;
933ebfedea0SLionel Sambuc size_t buf_size;
934*0a6a1f1dSLionel Sambuc size_t len = 0;
935ebfedea0SLionel Sambuc EncryptedData encdata;
936ebfedea0SLionel Sambuc krb5_error_code ret;
937ebfedea0SLionel Sambuc int32_t usec;
938ebfedea0SLionel Sambuc int usec2;
939ebfedea0SLionel Sambuc krb5_crypto crypto;
940ebfedea0SLionel Sambuc
941ebfedea0SLionel Sambuc krb5_us_timeofday (context, &p.patimestamp, &usec);
942ebfedea0SLionel Sambuc usec2 = usec;
943ebfedea0SLionel Sambuc p.pausec = &usec2;
944ebfedea0SLionel Sambuc
945ebfedea0SLionel Sambuc ASN1_MALLOC_ENCODE(PA_ENC_TS_ENC, buf, buf_size, &p, &len, ret);
946ebfedea0SLionel Sambuc if (ret)
947ebfedea0SLionel Sambuc return ret;
948ebfedea0SLionel Sambuc if(buf_size != len)
949ebfedea0SLionel Sambuc krb5_abortx(context, "internal error in ASN.1 encoder");
950ebfedea0SLionel Sambuc
951ebfedea0SLionel Sambuc ret = krb5_crypto_init(context, key, 0, &crypto);
952ebfedea0SLionel Sambuc if (ret) {
953ebfedea0SLionel Sambuc free(buf);
954ebfedea0SLionel Sambuc return ret;
955ebfedea0SLionel Sambuc }
956ebfedea0SLionel Sambuc ret = krb5_encrypt_EncryptedData(context,
957ebfedea0SLionel Sambuc crypto,
958ebfedea0SLionel Sambuc KRB5_KU_PA_ENC_TIMESTAMP,
959ebfedea0SLionel Sambuc buf,
960ebfedea0SLionel Sambuc len,
961ebfedea0SLionel Sambuc 0,
962ebfedea0SLionel Sambuc &encdata);
963ebfedea0SLionel Sambuc free(buf);
964ebfedea0SLionel Sambuc krb5_crypto_destroy(context, crypto);
965ebfedea0SLionel Sambuc if (ret)
966ebfedea0SLionel Sambuc return ret;
967ebfedea0SLionel Sambuc
968ebfedea0SLionel Sambuc ASN1_MALLOC_ENCODE(EncryptedData, buf, buf_size, &encdata, &len, ret);
969ebfedea0SLionel Sambuc free_EncryptedData(&encdata);
970ebfedea0SLionel Sambuc if (ret)
971ebfedea0SLionel Sambuc return ret;
972ebfedea0SLionel Sambuc if(buf_size != len)
973ebfedea0SLionel Sambuc krb5_abortx(context, "internal error in ASN.1 encoder");
974ebfedea0SLionel Sambuc
975ebfedea0SLionel Sambuc ret = krb5_padata_add(context, md, KRB5_PADATA_ENC_TIMESTAMP, buf, len);
976ebfedea0SLionel Sambuc if (ret)
977ebfedea0SLionel Sambuc free(buf);
978ebfedea0SLionel Sambuc return ret;
979ebfedea0SLionel Sambuc }
980ebfedea0SLionel Sambuc
981ebfedea0SLionel Sambuc static krb5_error_code
add_enc_ts_padata(krb5_context context,METHOD_DATA * md,krb5_principal client,krb5_s2k_proc keyproc,krb5_const_pointer keyseed,krb5_enctype * enctypes,unsigned netypes,krb5_salt * salt,krb5_data * s2kparams)982ebfedea0SLionel Sambuc add_enc_ts_padata(krb5_context context,
983ebfedea0SLionel Sambuc METHOD_DATA *md,
984ebfedea0SLionel Sambuc krb5_principal client,
985ebfedea0SLionel Sambuc krb5_s2k_proc keyproc,
986ebfedea0SLionel Sambuc krb5_const_pointer keyseed,
987ebfedea0SLionel Sambuc krb5_enctype *enctypes,
988ebfedea0SLionel Sambuc unsigned netypes,
989ebfedea0SLionel Sambuc krb5_salt *salt,
990ebfedea0SLionel Sambuc krb5_data *s2kparams)
991ebfedea0SLionel Sambuc {
992ebfedea0SLionel Sambuc krb5_error_code ret;
993ebfedea0SLionel Sambuc krb5_salt salt2;
994ebfedea0SLionel Sambuc krb5_enctype *ep;
995*0a6a1f1dSLionel Sambuc size_t i;
996ebfedea0SLionel Sambuc
997ebfedea0SLionel Sambuc if(salt == NULL) {
998ebfedea0SLionel Sambuc /* default to standard salt */
999ebfedea0SLionel Sambuc ret = krb5_get_pw_salt (context, client, &salt2);
1000ebfedea0SLionel Sambuc if (ret)
1001ebfedea0SLionel Sambuc return ret;
1002ebfedea0SLionel Sambuc salt = &salt2;
1003ebfedea0SLionel Sambuc }
1004ebfedea0SLionel Sambuc if (!enctypes) {
1005ebfedea0SLionel Sambuc enctypes = context->etypes;
1006ebfedea0SLionel Sambuc netypes = 0;
1007ebfedea0SLionel Sambuc for (ep = enctypes; *ep != ETYPE_NULL; ep++)
1008ebfedea0SLionel Sambuc netypes++;
1009ebfedea0SLionel Sambuc }
1010ebfedea0SLionel Sambuc
1011ebfedea0SLionel Sambuc for (i = 0; i < netypes; ++i) {
1012ebfedea0SLionel Sambuc krb5_keyblock *key;
1013ebfedea0SLionel Sambuc
1014ebfedea0SLionel Sambuc _krb5_debug(context, 5, "krb5_get_init_creds: using ENC-TS with enctype %d", enctypes[i]);
1015ebfedea0SLionel Sambuc
1016ebfedea0SLionel Sambuc ret = (*keyproc)(context, enctypes[i], keyseed,
1017ebfedea0SLionel Sambuc *salt, s2kparams, &key);
1018ebfedea0SLionel Sambuc if (ret)
1019ebfedea0SLionel Sambuc continue;
1020ebfedea0SLionel Sambuc ret = make_pa_enc_timestamp (context, md, enctypes[i], key);
1021ebfedea0SLionel Sambuc krb5_free_keyblock (context, key);
1022ebfedea0SLionel Sambuc if (ret)
1023ebfedea0SLionel Sambuc return ret;
1024ebfedea0SLionel Sambuc }
1025ebfedea0SLionel Sambuc if(salt == &salt2)
1026ebfedea0SLionel Sambuc krb5_free_salt(context, salt2);
1027ebfedea0SLionel Sambuc return 0;
1028ebfedea0SLionel Sambuc }
1029ebfedea0SLionel Sambuc
1030ebfedea0SLionel Sambuc static krb5_error_code
pa_data_to_md_ts_enc(krb5_context context,const AS_REQ * a,const krb5_principal client,krb5_get_init_creds_ctx * ctx,struct pa_info_data * ppaid,METHOD_DATA * md)1031ebfedea0SLionel Sambuc pa_data_to_md_ts_enc(krb5_context context,
1032ebfedea0SLionel Sambuc const AS_REQ *a,
1033ebfedea0SLionel Sambuc const krb5_principal client,
1034ebfedea0SLionel Sambuc krb5_get_init_creds_ctx *ctx,
1035ebfedea0SLionel Sambuc struct pa_info_data *ppaid,
1036ebfedea0SLionel Sambuc METHOD_DATA *md)
1037ebfedea0SLionel Sambuc {
1038ebfedea0SLionel Sambuc if (ctx->keyproc == NULL || ctx->keyseed == NULL)
1039ebfedea0SLionel Sambuc return 0;
1040ebfedea0SLionel Sambuc
1041ebfedea0SLionel Sambuc if (ppaid) {
1042ebfedea0SLionel Sambuc add_enc_ts_padata(context, md, client,
1043ebfedea0SLionel Sambuc ctx->keyproc, ctx->keyseed,
1044ebfedea0SLionel Sambuc &ppaid->etype, 1,
1045ebfedea0SLionel Sambuc &ppaid->salt, ppaid->s2kparams);
1046ebfedea0SLionel Sambuc } else {
1047ebfedea0SLionel Sambuc krb5_salt salt;
1048ebfedea0SLionel Sambuc
1049ebfedea0SLionel Sambuc _krb5_debug(context, 5, "krb5_get_init_creds: pa-info not found, guessing salt");
1050ebfedea0SLionel Sambuc
1051ebfedea0SLionel Sambuc /* make a v5 salted pa-data */
1052ebfedea0SLionel Sambuc add_enc_ts_padata(context, md, client,
1053ebfedea0SLionel Sambuc ctx->keyproc, ctx->keyseed,
1054ebfedea0SLionel Sambuc a->req_body.etype.val, a->req_body.etype.len,
1055ebfedea0SLionel Sambuc NULL, NULL);
1056ebfedea0SLionel Sambuc
1057ebfedea0SLionel Sambuc /* make a v4 salted pa-data */
1058ebfedea0SLionel Sambuc salt.salttype = KRB5_PW_SALT;
1059ebfedea0SLionel Sambuc krb5_data_zero(&salt.saltvalue);
1060ebfedea0SLionel Sambuc add_enc_ts_padata(context, md, client,
1061ebfedea0SLionel Sambuc ctx->keyproc, ctx->keyseed,
1062ebfedea0SLionel Sambuc a->req_body.etype.val, a->req_body.etype.len,
1063ebfedea0SLionel Sambuc &salt, NULL);
1064ebfedea0SLionel Sambuc }
1065ebfedea0SLionel Sambuc return 0;
1066ebfedea0SLionel Sambuc }
1067ebfedea0SLionel Sambuc
1068ebfedea0SLionel Sambuc static krb5_error_code
pa_data_to_key_plain(krb5_context context,const krb5_principal client,krb5_get_init_creds_ctx * ctx,krb5_salt salt,krb5_data * s2kparams,krb5_enctype etype,krb5_keyblock ** key)1069ebfedea0SLionel Sambuc pa_data_to_key_plain(krb5_context context,
1070ebfedea0SLionel Sambuc const krb5_principal client,
1071ebfedea0SLionel Sambuc krb5_get_init_creds_ctx *ctx,
1072ebfedea0SLionel Sambuc krb5_salt salt,
1073ebfedea0SLionel Sambuc krb5_data *s2kparams,
1074ebfedea0SLionel Sambuc krb5_enctype etype,
1075ebfedea0SLionel Sambuc krb5_keyblock **key)
1076ebfedea0SLionel Sambuc {
1077ebfedea0SLionel Sambuc krb5_error_code ret;
1078ebfedea0SLionel Sambuc
1079ebfedea0SLionel Sambuc ret = (*ctx->keyproc)(context, etype, ctx->keyseed,
1080ebfedea0SLionel Sambuc salt, s2kparams, key);
1081ebfedea0SLionel Sambuc return ret;
1082ebfedea0SLionel Sambuc }
1083ebfedea0SLionel Sambuc
1084ebfedea0SLionel Sambuc
1085ebfedea0SLionel Sambuc static krb5_error_code
pa_data_to_md_pkinit(krb5_context context,const AS_REQ * a,const krb5_principal client,int win2k,krb5_get_init_creds_ctx * ctx,METHOD_DATA * md)1086ebfedea0SLionel Sambuc pa_data_to_md_pkinit(krb5_context context,
1087ebfedea0SLionel Sambuc const AS_REQ *a,
1088ebfedea0SLionel Sambuc const krb5_principal client,
1089ebfedea0SLionel Sambuc int win2k,
1090ebfedea0SLionel Sambuc krb5_get_init_creds_ctx *ctx,
1091ebfedea0SLionel Sambuc METHOD_DATA *md)
1092ebfedea0SLionel Sambuc {
1093ebfedea0SLionel Sambuc if (ctx->pk_init_ctx == NULL)
1094ebfedea0SLionel Sambuc return 0;
1095ebfedea0SLionel Sambuc #ifdef PKINIT
1096ebfedea0SLionel Sambuc return _krb5_pk_mk_padata(context,
1097ebfedea0SLionel Sambuc ctx->pk_init_ctx,
1098ebfedea0SLionel Sambuc ctx->ic_flags,
1099ebfedea0SLionel Sambuc win2k,
1100ebfedea0SLionel Sambuc &a->req_body,
1101ebfedea0SLionel Sambuc ctx->pk_nonce,
1102ebfedea0SLionel Sambuc md);
1103ebfedea0SLionel Sambuc #else
1104ebfedea0SLionel Sambuc krb5_set_error_message(context, EINVAL,
1105ebfedea0SLionel Sambuc N_("no support for PKINIT compiled in", ""));
1106ebfedea0SLionel Sambuc return EINVAL;
1107ebfedea0SLionel Sambuc #endif
1108ebfedea0SLionel Sambuc }
1109ebfedea0SLionel Sambuc
1110ebfedea0SLionel Sambuc static krb5_error_code
pa_data_add_pac_request(krb5_context context,krb5_get_init_creds_ctx * ctx,METHOD_DATA * md)1111ebfedea0SLionel Sambuc pa_data_add_pac_request(krb5_context context,
1112ebfedea0SLionel Sambuc krb5_get_init_creds_ctx *ctx,
1113ebfedea0SLionel Sambuc METHOD_DATA *md)
1114ebfedea0SLionel Sambuc {
1115*0a6a1f1dSLionel Sambuc size_t len = 0, length;
1116ebfedea0SLionel Sambuc krb5_error_code ret;
1117ebfedea0SLionel Sambuc PA_PAC_REQUEST req;
1118ebfedea0SLionel Sambuc void *buf;
1119ebfedea0SLionel Sambuc
1120ebfedea0SLionel Sambuc switch (ctx->req_pac) {
1121ebfedea0SLionel Sambuc case KRB5_INIT_CREDS_TRISTATE_UNSET:
1122ebfedea0SLionel Sambuc return 0; /* don't bother */
1123ebfedea0SLionel Sambuc case KRB5_INIT_CREDS_TRISTATE_TRUE:
1124ebfedea0SLionel Sambuc req.include_pac = 1;
1125ebfedea0SLionel Sambuc break;
1126ebfedea0SLionel Sambuc case KRB5_INIT_CREDS_TRISTATE_FALSE:
1127ebfedea0SLionel Sambuc req.include_pac = 0;
1128ebfedea0SLionel Sambuc }
1129ebfedea0SLionel Sambuc
1130ebfedea0SLionel Sambuc ASN1_MALLOC_ENCODE(PA_PAC_REQUEST, buf, length,
1131ebfedea0SLionel Sambuc &req, &len, ret);
1132ebfedea0SLionel Sambuc if (ret)
1133ebfedea0SLionel Sambuc return ret;
1134ebfedea0SLionel Sambuc if(len != length)
1135ebfedea0SLionel Sambuc krb5_abortx(context, "internal error in ASN.1 encoder");
1136ebfedea0SLionel Sambuc
1137ebfedea0SLionel Sambuc ret = krb5_padata_add(context, md, KRB5_PADATA_PA_PAC_REQUEST, buf, len);
1138ebfedea0SLionel Sambuc if (ret)
1139ebfedea0SLionel Sambuc free(buf);
1140ebfedea0SLionel Sambuc
1141ebfedea0SLionel Sambuc return 0;
1142ebfedea0SLionel Sambuc }
1143ebfedea0SLionel Sambuc
1144ebfedea0SLionel Sambuc /*
1145ebfedea0SLionel Sambuc * Assumes caller always will free `out_md', even on error.
1146ebfedea0SLionel Sambuc */
1147ebfedea0SLionel Sambuc
1148ebfedea0SLionel Sambuc static krb5_error_code
process_pa_data_to_md(krb5_context context,const krb5_creds * creds,const AS_REQ * a,krb5_get_init_creds_ctx * ctx,METHOD_DATA * in_md,METHOD_DATA ** out_md,krb5_prompter_fct prompter,void * prompter_data)1149ebfedea0SLionel Sambuc process_pa_data_to_md(krb5_context context,
1150ebfedea0SLionel Sambuc const krb5_creds *creds,
1151ebfedea0SLionel Sambuc const AS_REQ *a,
1152ebfedea0SLionel Sambuc krb5_get_init_creds_ctx *ctx,
1153ebfedea0SLionel Sambuc METHOD_DATA *in_md,
1154ebfedea0SLionel Sambuc METHOD_DATA **out_md,
1155ebfedea0SLionel Sambuc krb5_prompter_fct prompter,
1156ebfedea0SLionel Sambuc void *prompter_data)
1157ebfedea0SLionel Sambuc {
1158ebfedea0SLionel Sambuc krb5_error_code ret;
1159ebfedea0SLionel Sambuc
1160ebfedea0SLionel Sambuc ALLOC(*out_md, 1);
1161ebfedea0SLionel Sambuc if (*out_md == NULL) {
1162ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1163ebfedea0SLionel Sambuc return ENOMEM;
1164ebfedea0SLionel Sambuc }
1165ebfedea0SLionel Sambuc (*out_md)->len = 0;
1166ebfedea0SLionel Sambuc (*out_md)->val = NULL;
1167ebfedea0SLionel Sambuc
1168ebfedea0SLionel Sambuc if (_krb5_have_debug(context, 5)) {
1169ebfedea0SLionel Sambuc unsigned i;
1170ebfedea0SLionel Sambuc _krb5_debug(context, 5, "KDC send %d patypes", in_md->len);
1171ebfedea0SLionel Sambuc for (i = 0; i < in_md->len; i++)
1172ebfedea0SLionel Sambuc _krb5_debug(context, 5, "KDC send PA-DATA type: %d", in_md->val[i].padata_type);
1173ebfedea0SLionel Sambuc }
1174ebfedea0SLionel Sambuc
1175ebfedea0SLionel Sambuc /*
1176ebfedea0SLionel Sambuc * Make sure we don't sent both ENC-TS and PK-INIT pa data, no
1177ebfedea0SLionel Sambuc * need to expose our password protecting our PKCS12 key.
1178ebfedea0SLionel Sambuc */
1179ebfedea0SLionel Sambuc
1180ebfedea0SLionel Sambuc if (ctx->pk_init_ctx) {
1181ebfedea0SLionel Sambuc
1182ebfedea0SLionel Sambuc _krb5_debug(context, 5, "krb5_get_init_creds: "
1183ebfedea0SLionel Sambuc "prepareing PKINIT padata (%s)",
1184ebfedea0SLionel Sambuc (ctx->used_pa_types & USED_PKINIT_W2K) ? "win2k" : "ietf");
1185ebfedea0SLionel Sambuc
1186ebfedea0SLionel Sambuc if (ctx->used_pa_types & USED_PKINIT_W2K) {
1187ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_GET_IN_TKT_LOOP,
1188ebfedea0SLionel Sambuc "Already tried pkinit, looping");
1189ebfedea0SLionel Sambuc return KRB5_GET_IN_TKT_LOOP;
1190ebfedea0SLionel Sambuc }
1191ebfedea0SLionel Sambuc
1192ebfedea0SLionel Sambuc ret = pa_data_to_md_pkinit(context, a, creds->client,
1193ebfedea0SLionel Sambuc (ctx->used_pa_types & USED_PKINIT),
1194ebfedea0SLionel Sambuc ctx, *out_md);
1195ebfedea0SLionel Sambuc if (ret)
1196ebfedea0SLionel Sambuc return ret;
1197ebfedea0SLionel Sambuc
1198ebfedea0SLionel Sambuc if (ctx->used_pa_types & USED_PKINIT)
1199ebfedea0SLionel Sambuc ctx->used_pa_types |= USED_PKINIT_W2K;
1200ebfedea0SLionel Sambuc else
1201ebfedea0SLionel Sambuc ctx->used_pa_types |= USED_PKINIT;
1202ebfedea0SLionel Sambuc
1203ebfedea0SLionel Sambuc } else if (in_md->len != 0) {
1204ebfedea0SLionel Sambuc struct pa_info_data *paid, *ppaid;
1205ebfedea0SLionel Sambuc unsigned flag;
1206ebfedea0SLionel Sambuc
1207ebfedea0SLionel Sambuc paid = calloc(1, sizeof(*paid));
1208ebfedea0SLionel Sambuc
1209ebfedea0SLionel Sambuc paid->etype = ENCTYPE_NULL;
1210ebfedea0SLionel Sambuc ppaid = process_pa_info(context, creds->client, a, paid, in_md);
1211ebfedea0SLionel Sambuc
1212ebfedea0SLionel Sambuc if (ppaid)
1213ebfedea0SLionel Sambuc flag = USED_ENC_TS_INFO;
1214ebfedea0SLionel Sambuc else
1215ebfedea0SLionel Sambuc flag = USED_ENC_TS_GUESS;
1216ebfedea0SLionel Sambuc
1217ebfedea0SLionel Sambuc if (ctx->used_pa_types & flag) {
1218ebfedea0SLionel Sambuc if (ppaid)
1219ebfedea0SLionel Sambuc free_paid(context, ppaid);
1220ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_GET_IN_TKT_LOOP,
1221ebfedea0SLionel Sambuc "Already tried ENC-TS-%s, looping",
1222ebfedea0SLionel Sambuc flag == USED_ENC_TS_INFO ? "info" : "guess");
1223ebfedea0SLionel Sambuc return KRB5_GET_IN_TKT_LOOP;
1224ebfedea0SLionel Sambuc }
1225ebfedea0SLionel Sambuc
1226ebfedea0SLionel Sambuc pa_data_to_md_ts_enc(context, a, creds->client, ctx, ppaid, *out_md);
1227ebfedea0SLionel Sambuc
1228ebfedea0SLionel Sambuc ctx->used_pa_types |= flag;
1229ebfedea0SLionel Sambuc
1230ebfedea0SLionel Sambuc if (ppaid) {
1231ebfedea0SLionel Sambuc if (ctx->ppaid) {
1232ebfedea0SLionel Sambuc free_paid(context, ctx->ppaid);
1233ebfedea0SLionel Sambuc free(ctx->ppaid);
1234ebfedea0SLionel Sambuc }
1235ebfedea0SLionel Sambuc ctx->ppaid = ppaid;
1236ebfedea0SLionel Sambuc } else
1237ebfedea0SLionel Sambuc free(paid);
1238ebfedea0SLionel Sambuc }
1239ebfedea0SLionel Sambuc
1240ebfedea0SLionel Sambuc pa_data_add_pac_request(context, ctx, *out_md);
1241ebfedea0SLionel Sambuc
1242ebfedea0SLionel Sambuc if ((*out_md)->len == 0) {
1243ebfedea0SLionel Sambuc free(*out_md);
1244ebfedea0SLionel Sambuc *out_md = NULL;
1245ebfedea0SLionel Sambuc }
1246ebfedea0SLionel Sambuc
1247ebfedea0SLionel Sambuc return 0;
1248ebfedea0SLionel Sambuc }
1249ebfedea0SLionel Sambuc
1250ebfedea0SLionel Sambuc static krb5_error_code
process_pa_data_to_key(krb5_context context,krb5_get_init_creds_ctx * ctx,krb5_creds * creds,AS_REQ * a,AS_REP * rep,const krb5_krbhst_info * hi,krb5_keyblock ** key)1251ebfedea0SLionel Sambuc process_pa_data_to_key(krb5_context context,
1252ebfedea0SLionel Sambuc krb5_get_init_creds_ctx *ctx,
1253ebfedea0SLionel Sambuc krb5_creds *creds,
1254ebfedea0SLionel Sambuc AS_REQ *a,
1255ebfedea0SLionel Sambuc AS_REP *rep,
1256ebfedea0SLionel Sambuc const krb5_krbhst_info *hi,
1257ebfedea0SLionel Sambuc krb5_keyblock **key)
1258ebfedea0SLionel Sambuc {
1259ebfedea0SLionel Sambuc struct pa_info_data paid, *ppaid = NULL;
1260ebfedea0SLionel Sambuc krb5_error_code ret;
1261ebfedea0SLionel Sambuc krb5_enctype etype;
1262ebfedea0SLionel Sambuc PA_DATA *pa;
1263ebfedea0SLionel Sambuc
1264ebfedea0SLionel Sambuc memset(&paid, 0, sizeof(paid));
1265ebfedea0SLionel Sambuc
1266ebfedea0SLionel Sambuc etype = rep->enc_part.etype;
1267ebfedea0SLionel Sambuc
1268ebfedea0SLionel Sambuc if (rep->padata) {
1269ebfedea0SLionel Sambuc paid.etype = etype;
1270ebfedea0SLionel Sambuc ppaid = process_pa_info(context, creds->client, a, &paid,
1271ebfedea0SLionel Sambuc rep->padata);
1272ebfedea0SLionel Sambuc }
1273ebfedea0SLionel Sambuc if (ppaid == NULL)
1274ebfedea0SLionel Sambuc ppaid = ctx->ppaid;
1275ebfedea0SLionel Sambuc if (ppaid == NULL) {
1276ebfedea0SLionel Sambuc ret = krb5_get_pw_salt (context, creds->client, &paid.salt);
1277ebfedea0SLionel Sambuc if (ret)
1278ebfedea0SLionel Sambuc return ret;
1279ebfedea0SLionel Sambuc paid.etype = etype;
1280ebfedea0SLionel Sambuc paid.s2kparams = NULL;
1281ebfedea0SLionel Sambuc ppaid = &paid;
1282ebfedea0SLionel Sambuc }
1283ebfedea0SLionel Sambuc
1284ebfedea0SLionel Sambuc pa = NULL;
1285ebfedea0SLionel Sambuc if (rep->padata) {
1286ebfedea0SLionel Sambuc int idx = 0;
1287ebfedea0SLionel Sambuc pa = krb5_find_padata(rep->padata->val,
1288ebfedea0SLionel Sambuc rep->padata->len,
1289ebfedea0SLionel Sambuc KRB5_PADATA_PK_AS_REP,
1290ebfedea0SLionel Sambuc &idx);
1291ebfedea0SLionel Sambuc if (pa == NULL) {
1292ebfedea0SLionel Sambuc idx = 0;
1293ebfedea0SLionel Sambuc pa = krb5_find_padata(rep->padata->val,
1294ebfedea0SLionel Sambuc rep->padata->len,
1295ebfedea0SLionel Sambuc KRB5_PADATA_PK_AS_REP_19,
1296ebfedea0SLionel Sambuc &idx);
1297ebfedea0SLionel Sambuc }
1298ebfedea0SLionel Sambuc }
1299ebfedea0SLionel Sambuc if (pa && ctx->pk_init_ctx) {
1300ebfedea0SLionel Sambuc #ifdef PKINIT
1301ebfedea0SLionel Sambuc _krb5_debug(context, 5, "krb5_get_init_creds: using PKINIT");
1302ebfedea0SLionel Sambuc
1303ebfedea0SLionel Sambuc ret = _krb5_pk_rd_pa_reply(context,
1304ebfedea0SLionel Sambuc a->req_body.realm,
1305ebfedea0SLionel Sambuc ctx->pk_init_ctx,
1306ebfedea0SLionel Sambuc etype,
1307ebfedea0SLionel Sambuc hi,
1308ebfedea0SLionel Sambuc ctx->pk_nonce,
1309ebfedea0SLionel Sambuc &ctx->req_buffer,
1310ebfedea0SLionel Sambuc pa,
1311ebfedea0SLionel Sambuc key);
1312ebfedea0SLionel Sambuc #else
1313ebfedea0SLionel Sambuc ret = EINVAL;
1314ebfedea0SLionel Sambuc krb5_set_error_message(context, ret, N_("no support for PKINIT compiled in", ""));
1315ebfedea0SLionel Sambuc #endif
1316ebfedea0SLionel Sambuc } else if (ctx->keyseed) {
1317ebfedea0SLionel Sambuc _krb5_debug(context, 5, "krb5_get_init_creds: using keyproc");
1318ebfedea0SLionel Sambuc ret = pa_data_to_key_plain(context, creds->client, ctx,
1319ebfedea0SLionel Sambuc ppaid->salt, ppaid->s2kparams, etype, key);
1320ebfedea0SLionel Sambuc } else {
1321ebfedea0SLionel Sambuc ret = EINVAL;
1322ebfedea0SLionel Sambuc krb5_set_error_message(context, ret, N_("No usable pa data type", ""));
1323ebfedea0SLionel Sambuc }
1324ebfedea0SLionel Sambuc
1325ebfedea0SLionel Sambuc free_paid(context, &paid);
1326ebfedea0SLionel Sambuc return ret;
1327ebfedea0SLionel Sambuc }
1328ebfedea0SLionel Sambuc
1329ebfedea0SLionel Sambuc /**
1330ebfedea0SLionel Sambuc * Start a new context to get a new initial credential.
1331ebfedea0SLionel Sambuc *
1332ebfedea0SLionel Sambuc * @param context A Kerberos 5 context.
1333ebfedea0SLionel Sambuc * @param client The Kerberos principal to get the credential for, if
1334ebfedea0SLionel Sambuc * NULL is given, the default principal is used as determined by
1335ebfedea0SLionel Sambuc * krb5_get_default_principal().
1336ebfedea0SLionel Sambuc * @param prompter
1337ebfedea0SLionel Sambuc * @param prompter_data
1338ebfedea0SLionel Sambuc * @param start_time the time the ticket should start to be valid or 0 for now.
1339ebfedea0SLionel Sambuc * @param options a options structure, can be NULL for default options.
1340ebfedea0SLionel Sambuc * @param rctx A new allocated free with krb5_init_creds_free().
1341ebfedea0SLionel Sambuc *
1342ebfedea0SLionel Sambuc * @return 0 for success or an Kerberos 5 error code, see krb5_get_error_message().
1343ebfedea0SLionel Sambuc *
1344ebfedea0SLionel Sambuc * @ingroup krb5_credential
1345ebfedea0SLionel Sambuc */
1346ebfedea0SLionel Sambuc
1347ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_init_creds_init(krb5_context context,krb5_principal client,krb5_prompter_fct prompter,void * prompter_data,krb5_deltat start_time,krb5_get_init_creds_opt * options,krb5_init_creds_context * rctx)1348ebfedea0SLionel Sambuc krb5_init_creds_init(krb5_context context,
1349ebfedea0SLionel Sambuc krb5_principal client,
1350ebfedea0SLionel Sambuc krb5_prompter_fct prompter,
1351ebfedea0SLionel Sambuc void *prompter_data,
1352ebfedea0SLionel Sambuc krb5_deltat start_time,
1353ebfedea0SLionel Sambuc krb5_get_init_creds_opt *options,
1354ebfedea0SLionel Sambuc krb5_init_creds_context *rctx)
1355ebfedea0SLionel Sambuc {
1356ebfedea0SLionel Sambuc krb5_init_creds_context ctx;
1357ebfedea0SLionel Sambuc krb5_error_code ret;
1358ebfedea0SLionel Sambuc
1359ebfedea0SLionel Sambuc *rctx = NULL;
1360ebfedea0SLionel Sambuc
1361ebfedea0SLionel Sambuc ctx = calloc(1, sizeof(*ctx));
1362ebfedea0SLionel Sambuc if (ctx == NULL) {
1363ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1364ebfedea0SLionel Sambuc return ENOMEM;
1365ebfedea0SLionel Sambuc }
1366ebfedea0SLionel Sambuc
1367ebfedea0SLionel Sambuc ret = get_init_creds_common(context, client, start_time, options, ctx);
1368ebfedea0SLionel Sambuc if (ret) {
1369ebfedea0SLionel Sambuc free(ctx);
1370ebfedea0SLionel Sambuc return ret;
1371ebfedea0SLionel Sambuc }
1372ebfedea0SLionel Sambuc
1373ebfedea0SLionel Sambuc /* Set a new nonce. */
1374ebfedea0SLionel Sambuc krb5_generate_random_block (&ctx->nonce, sizeof(ctx->nonce));
1375ebfedea0SLionel Sambuc ctx->nonce &= 0x7fffffff;
1376ebfedea0SLionel Sambuc /* XXX these just needs to be the same when using Windows PK-INIT */
1377ebfedea0SLionel Sambuc ctx->pk_nonce = ctx->nonce;
1378ebfedea0SLionel Sambuc
1379ebfedea0SLionel Sambuc ctx->prompter = prompter;
1380ebfedea0SLionel Sambuc ctx->prompter_data = prompter_data;
1381ebfedea0SLionel Sambuc
1382ebfedea0SLionel Sambuc *rctx = ctx;
1383ebfedea0SLionel Sambuc
1384ebfedea0SLionel Sambuc return ret;
1385ebfedea0SLionel Sambuc }
1386ebfedea0SLionel Sambuc
1387ebfedea0SLionel Sambuc /**
1388ebfedea0SLionel Sambuc * Sets the service that the is requested. This call is only neede for
1389ebfedea0SLionel Sambuc * special initial tickets, by default the a krbtgt is fetched in the default realm.
1390ebfedea0SLionel Sambuc *
1391ebfedea0SLionel Sambuc * @param context a Kerberos 5 context.
1392ebfedea0SLionel Sambuc * @param ctx a krb5_init_creds_context context.
1393ebfedea0SLionel Sambuc * @param service the service given as a string, for example
1394ebfedea0SLionel Sambuc * "kadmind/admin". If NULL, the default krbtgt in the clients
1395ebfedea0SLionel Sambuc * realm is set.
1396ebfedea0SLionel Sambuc *
1397ebfedea0SLionel Sambuc * @return 0 for success, or an Kerberos 5 error code, see krb5_get_error_message().
1398ebfedea0SLionel Sambuc * @ingroup krb5_credential
1399ebfedea0SLionel Sambuc */
1400ebfedea0SLionel Sambuc
1401ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_init_creds_set_service(krb5_context context,krb5_init_creds_context ctx,const char * service)1402ebfedea0SLionel Sambuc krb5_init_creds_set_service(krb5_context context,
1403ebfedea0SLionel Sambuc krb5_init_creds_context ctx,
1404ebfedea0SLionel Sambuc const char *service)
1405ebfedea0SLionel Sambuc {
1406ebfedea0SLionel Sambuc krb5_const_realm client_realm;
1407ebfedea0SLionel Sambuc krb5_principal principal;
1408ebfedea0SLionel Sambuc krb5_error_code ret;
1409ebfedea0SLionel Sambuc
1410ebfedea0SLionel Sambuc client_realm = krb5_principal_get_realm (context, ctx->cred.client);
1411ebfedea0SLionel Sambuc
1412ebfedea0SLionel Sambuc if (service) {
1413ebfedea0SLionel Sambuc ret = krb5_parse_name (context, service, &principal);
1414ebfedea0SLionel Sambuc if (ret)
1415ebfedea0SLionel Sambuc return ret;
1416ebfedea0SLionel Sambuc krb5_principal_set_realm (context, principal, client_realm);
1417ebfedea0SLionel Sambuc } else {
1418ebfedea0SLionel Sambuc ret = krb5_make_principal(context, &principal,
1419ebfedea0SLionel Sambuc client_realm, KRB5_TGS_NAME, client_realm,
1420ebfedea0SLionel Sambuc NULL);
1421ebfedea0SLionel Sambuc if (ret)
1422ebfedea0SLionel Sambuc return ret;
1423ebfedea0SLionel Sambuc }
1424ebfedea0SLionel Sambuc
1425ebfedea0SLionel Sambuc /*
1426ebfedea0SLionel Sambuc * This is for Windows RODC that are picky about what name type
1427ebfedea0SLionel Sambuc * the server principal have, and the really strange part is that
1428ebfedea0SLionel Sambuc * they are picky about the AS-REQ name type and not the TGS-REQ
1429ebfedea0SLionel Sambuc * later. Oh well.
1430ebfedea0SLionel Sambuc */
1431ebfedea0SLionel Sambuc
1432ebfedea0SLionel Sambuc if (krb5_principal_is_krbtgt(context, principal))
1433ebfedea0SLionel Sambuc krb5_principal_set_type(context, principal, KRB5_NT_SRV_INST);
1434ebfedea0SLionel Sambuc
1435ebfedea0SLionel Sambuc krb5_free_principal(context, ctx->cred.server);
1436ebfedea0SLionel Sambuc ctx->cred.server = principal;
1437ebfedea0SLionel Sambuc
1438ebfedea0SLionel Sambuc return 0;
1439ebfedea0SLionel Sambuc }
1440ebfedea0SLionel Sambuc
1441ebfedea0SLionel Sambuc /**
1442ebfedea0SLionel Sambuc * Sets the password that will use for the request.
1443ebfedea0SLionel Sambuc *
1444ebfedea0SLionel Sambuc * @param context a Kerberos 5 context.
1445ebfedea0SLionel Sambuc * @param ctx ctx krb5_init_creds_context context.
1446ebfedea0SLionel Sambuc * @param password the password to use.
1447ebfedea0SLionel Sambuc *
1448ebfedea0SLionel Sambuc * @return 0 for success, or an Kerberos 5 error code, see krb5_get_error_message().
1449ebfedea0SLionel Sambuc * @ingroup krb5_credential
1450ebfedea0SLionel Sambuc */
1451ebfedea0SLionel Sambuc
1452ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_init_creds_set_password(krb5_context context,krb5_init_creds_context ctx,const char * password)1453ebfedea0SLionel Sambuc krb5_init_creds_set_password(krb5_context context,
1454ebfedea0SLionel Sambuc krb5_init_creds_context ctx,
1455ebfedea0SLionel Sambuc const char *password)
1456ebfedea0SLionel Sambuc {
1457ebfedea0SLionel Sambuc if (ctx->password) {
1458ebfedea0SLionel Sambuc memset(ctx->password, 0, strlen(ctx->password));
1459ebfedea0SLionel Sambuc free(ctx->password);
1460ebfedea0SLionel Sambuc }
1461ebfedea0SLionel Sambuc if (password) {
1462ebfedea0SLionel Sambuc ctx->password = strdup(password);
1463ebfedea0SLionel Sambuc if (ctx->password == NULL) {
1464ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1465ebfedea0SLionel Sambuc return ENOMEM;
1466ebfedea0SLionel Sambuc }
1467ebfedea0SLionel Sambuc ctx->keyseed = (void *) ctx->password;
1468ebfedea0SLionel Sambuc } else {
1469ebfedea0SLionel Sambuc ctx->keyseed = NULL;
1470ebfedea0SLionel Sambuc ctx->password = NULL;
1471ebfedea0SLionel Sambuc }
1472ebfedea0SLionel Sambuc
1473ebfedea0SLionel Sambuc return 0;
1474ebfedea0SLionel Sambuc }
1475ebfedea0SLionel Sambuc
1476ebfedea0SLionel Sambuc static krb5_error_code KRB5_CALLCONV
keytab_key_proc(krb5_context context,krb5_enctype enctype,krb5_const_pointer keyseed,krb5_salt salt,krb5_data * s2kparms,krb5_keyblock ** key)1477ebfedea0SLionel Sambuc keytab_key_proc(krb5_context context, krb5_enctype enctype,
1478ebfedea0SLionel Sambuc krb5_const_pointer keyseed,
1479ebfedea0SLionel Sambuc krb5_salt salt, krb5_data *s2kparms,
1480ebfedea0SLionel Sambuc krb5_keyblock **key)
1481ebfedea0SLionel Sambuc {
1482ebfedea0SLionel Sambuc krb5_keytab_key_proc_args *args = rk_UNCONST(keyseed);
1483ebfedea0SLionel Sambuc krb5_keytab keytab = args->keytab;
1484ebfedea0SLionel Sambuc krb5_principal principal = args->principal;
1485ebfedea0SLionel Sambuc krb5_error_code ret;
1486ebfedea0SLionel Sambuc krb5_keytab real_keytab;
1487ebfedea0SLionel Sambuc krb5_keytab_entry entry;
1488ebfedea0SLionel Sambuc
1489ebfedea0SLionel Sambuc if(keytab == NULL)
1490ebfedea0SLionel Sambuc krb5_kt_default(context, &real_keytab);
1491ebfedea0SLionel Sambuc else
1492ebfedea0SLionel Sambuc real_keytab = keytab;
1493ebfedea0SLionel Sambuc
1494ebfedea0SLionel Sambuc ret = krb5_kt_get_entry (context, real_keytab, principal,
1495ebfedea0SLionel Sambuc 0, enctype, &entry);
1496ebfedea0SLionel Sambuc
1497ebfedea0SLionel Sambuc if (keytab == NULL)
1498ebfedea0SLionel Sambuc krb5_kt_close (context, real_keytab);
1499ebfedea0SLionel Sambuc
1500ebfedea0SLionel Sambuc if (ret)
1501ebfedea0SLionel Sambuc return ret;
1502ebfedea0SLionel Sambuc
1503ebfedea0SLionel Sambuc ret = krb5_copy_keyblock (context, &entry.keyblock, key);
1504ebfedea0SLionel Sambuc krb5_kt_free_entry(context, &entry);
1505ebfedea0SLionel Sambuc return ret;
1506ebfedea0SLionel Sambuc }
1507ebfedea0SLionel Sambuc
1508ebfedea0SLionel Sambuc
1509ebfedea0SLionel Sambuc /**
1510ebfedea0SLionel Sambuc * Set the keytab to use for authentication.
1511ebfedea0SLionel Sambuc *
1512ebfedea0SLionel Sambuc * @param context a Kerberos 5 context.
1513ebfedea0SLionel Sambuc * @param ctx ctx krb5_init_creds_context context.
1514ebfedea0SLionel Sambuc * @param keytab the keytab to read the key from.
1515ebfedea0SLionel Sambuc *
1516ebfedea0SLionel Sambuc * @return 0 for success, or an Kerberos 5 error code, see krb5_get_error_message().
1517ebfedea0SLionel Sambuc * @ingroup krb5_credential
1518ebfedea0SLionel Sambuc */
1519ebfedea0SLionel Sambuc
1520ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_init_creds_set_keytab(krb5_context context,krb5_init_creds_context ctx,krb5_keytab keytab)1521ebfedea0SLionel Sambuc krb5_init_creds_set_keytab(krb5_context context,
1522ebfedea0SLionel Sambuc krb5_init_creds_context ctx,
1523ebfedea0SLionel Sambuc krb5_keytab keytab)
1524ebfedea0SLionel Sambuc {
1525ebfedea0SLionel Sambuc krb5_keytab_key_proc_args *a;
1526ebfedea0SLionel Sambuc krb5_keytab_entry entry;
1527ebfedea0SLionel Sambuc krb5_kt_cursor cursor;
1528ebfedea0SLionel Sambuc krb5_enctype *etypes = NULL;
1529ebfedea0SLionel Sambuc krb5_error_code ret;
1530ebfedea0SLionel Sambuc size_t netypes = 0;
1531ebfedea0SLionel Sambuc int kvno = 0;
1532ebfedea0SLionel Sambuc
1533ebfedea0SLionel Sambuc a = malloc(sizeof(*a));
1534ebfedea0SLionel Sambuc if (a == NULL) {
1535ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM,
1536ebfedea0SLionel Sambuc N_("malloc: out of memory", ""));
1537ebfedea0SLionel Sambuc return ENOMEM;
1538ebfedea0SLionel Sambuc }
1539ebfedea0SLionel Sambuc
1540ebfedea0SLionel Sambuc a->principal = ctx->cred.client;
1541ebfedea0SLionel Sambuc a->keytab = keytab;
1542ebfedea0SLionel Sambuc
1543ebfedea0SLionel Sambuc ctx->keytab_data = a;
1544ebfedea0SLionel Sambuc ctx->keyseed = (void *)a;
1545ebfedea0SLionel Sambuc ctx->keyproc = keytab_key_proc;
1546ebfedea0SLionel Sambuc
1547ebfedea0SLionel Sambuc /*
1548ebfedea0SLionel Sambuc * We need to the KDC what enctypes we support for this keytab,
1549ebfedea0SLionel Sambuc * esp if the keytab is really a password based entry, then the
1550ebfedea0SLionel Sambuc * KDC might have more enctypes in the database then what we have
1551ebfedea0SLionel Sambuc * in the keytab.
1552ebfedea0SLionel Sambuc */
1553ebfedea0SLionel Sambuc
1554ebfedea0SLionel Sambuc ret = krb5_kt_start_seq_get(context, keytab, &cursor);
1555ebfedea0SLionel Sambuc if(ret)
1556ebfedea0SLionel Sambuc goto out;
1557ebfedea0SLionel Sambuc
1558ebfedea0SLionel Sambuc while(krb5_kt_next_entry(context, keytab, &entry, &cursor) == 0){
1559ebfedea0SLionel Sambuc void *ptr;
1560ebfedea0SLionel Sambuc
1561ebfedea0SLionel Sambuc if (!krb5_principal_compare(context, entry.principal, ctx->cred.client))
1562ebfedea0SLionel Sambuc goto next;
1563ebfedea0SLionel Sambuc
1564ebfedea0SLionel Sambuc /* check if we ahve this kvno already */
1565ebfedea0SLionel Sambuc if (entry.vno > kvno) {
1566ebfedea0SLionel Sambuc /* remove old list of etype */
1567ebfedea0SLionel Sambuc if (etypes)
1568ebfedea0SLionel Sambuc free(etypes);
1569ebfedea0SLionel Sambuc etypes = NULL;
1570ebfedea0SLionel Sambuc netypes = 0;
1571ebfedea0SLionel Sambuc kvno = entry.vno;
1572ebfedea0SLionel Sambuc } else if (entry.vno != kvno)
1573ebfedea0SLionel Sambuc goto next;
1574ebfedea0SLionel Sambuc
1575ebfedea0SLionel Sambuc /* check if enctype is supported */
1576ebfedea0SLionel Sambuc if (krb5_enctype_valid(context, entry.keyblock.keytype) != 0)
1577ebfedea0SLionel Sambuc goto next;
1578ebfedea0SLionel Sambuc
1579ebfedea0SLionel Sambuc /* add enctype to supported list */
1580ebfedea0SLionel Sambuc ptr = realloc(etypes, sizeof(etypes[0]) * (netypes + 2));
1581ebfedea0SLionel Sambuc if (ptr == NULL)
1582ebfedea0SLionel Sambuc goto next;
1583ebfedea0SLionel Sambuc
1584ebfedea0SLionel Sambuc etypes = ptr;
1585ebfedea0SLionel Sambuc etypes[netypes] = entry.keyblock.keytype;
1586ebfedea0SLionel Sambuc etypes[netypes + 1] = ETYPE_NULL;
1587ebfedea0SLionel Sambuc netypes++;
1588ebfedea0SLionel Sambuc next:
1589ebfedea0SLionel Sambuc krb5_kt_free_entry(context, &entry);
1590ebfedea0SLionel Sambuc }
1591ebfedea0SLionel Sambuc krb5_kt_end_seq_get(context, keytab, &cursor);
1592ebfedea0SLionel Sambuc
1593ebfedea0SLionel Sambuc if (etypes) {
1594ebfedea0SLionel Sambuc if (ctx->etypes)
1595ebfedea0SLionel Sambuc free(ctx->etypes);
1596ebfedea0SLionel Sambuc ctx->etypes = etypes;
1597ebfedea0SLionel Sambuc }
1598ebfedea0SLionel Sambuc
1599ebfedea0SLionel Sambuc out:
1600ebfedea0SLionel Sambuc return 0;
1601ebfedea0SLionel Sambuc }
1602ebfedea0SLionel Sambuc
1603ebfedea0SLionel Sambuc static krb5_error_code KRB5_CALLCONV
keyblock_key_proc(krb5_context context,krb5_enctype enctype,krb5_const_pointer keyseed,krb5_salt salt,krb5_data * s2kparms,krb5_keyblock ** key)1604ebfedea0SLionel Sambuc keyblock_key_proc(krb5_context context, krb5_enctype enctype,
1605ebfedea0SLionel Sambuc krb5_const_pointer keyseed,
1606ebfedea0SLionel Sambuc krb5_salt salt, krb5_data *s2kparms,
1607ebfedea0SLionel Sambuc krb5_keyblock **key)
1608ebfedea0SLionel Sambuc {
1609ebfedea0SLionel Sambuc return krb5_copy_keyblock (context, keyseed, key);
1610ebfedea0SLionel Sambuc }
1611ebfedea0SLionel Sambuc
1612ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_init_creds_set_keyblock(krb5_context context,krb5_init_creds_context ctx,krb5_keyblock * keyblock)1613ebfedea0SLionel Sambuc krb5_init_creds_set_keyblock(krb5_context context,
1614ebfedea0SLionel Sambuc krb5_init_creds_context ctx,
1615ebfedea0SLionel Sambuc krb5_keyblock *keyblock)
1616ebfedea0SLionel Sambuc {
1617ebfedea0SLionel Sambuc ctx->keyseed = (void *)keyblock;
1618ebfedea0SLionel Sambuc ctx->keyproc = keyblock_key_proc;
1619ebfedea0SLionel Sambuc
1620ebfedea0SLionel Sambuc return 0;
1621ebfedea0SLionel Sambuc }
1622ebfedea0SLionel Sambuc
1623ebfedea0SLionel Sambuc /**
1624ebfedea0SLionel Sambuc * The core loop if krb5_get_init_creds() function family. Create the
1625ebfedea0SLionel Sambuc * packets and have the caller send them off to the KDC.
1626ebfedea0SLionel Sambuc *
1627ebfedea0SLionel Sambuc * If the caller want all work been done for them, use
1628ebfedea0SLionel Sambuc * krb5_init_creds_get() instead.
1629ebfedea0SLionel Sambuc *
1630ebfedea0SLionel Sambuc * @param context a Kerberos 5 context.
1631ebfedea0SLionel Sambuc * @param ctx ctx krb5_init_creds_context context.
1632ebfedea0SLionel Sambuc * @param in input data from KDC, first round it should be reset by krb5_data_zer().
1633ebfedea0SLionel Sambuc * @param out reply to KDC.
1634ebfedea0SLionel Sambuc * @param hostinfo KDC address info, first round it can be NULL.
1635ebfedea0SLionel Sambuc * @param flags status of the round, if
1636ebfedea0SLionel Sambuc * KRB5_INIT_CREDS_STEP_FLAG_CONTINUE is set, continue one more round.
1637ebfedea0SLionel Sambuc *
1638ebfedea0SLionel Sambuc * @return 0 for success, or an Kerberos 5 error code, see
1639ebfedea0SLionel Sambuc * krb5_get_error_message().
1640ebfedea0SLionel Sambuc *
1641ebfedea0SLionel Sambuc * @ingroup krb5_credential
1642ebfedea0SLionel Sambuc */
1643ebfedea0SLionel Sambuc
1644ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_init_creds_step(krb5_context context,krb5_init_creds_context ctx,krb5_data * in,krb5_data * out,krb5_krbhst_info * hostinfo,unsigned int * flags)1645ebfedea0SLionel Sambuc krb5_init_creds_step(krb5_context context,
1646ebfedea0SLionel Sambuc krb5_init_creds_context ctx,
1647ebfedea0SLionel Sambuc krb5_data *in,
1648ebfedea0SLionel Sambuc krb5_data *out,
1649ebfedea0SLionel Sambuc krb5_krbhst_info *hostinfo,
1650ebfedea0SLionel Sambuc unsigned int *flags)
1651ebfedea0SLionel Sambuc {
1652ebfedea0SLionel Sambuc krb5_error_code ret;
1653*0a6a1f1dSLionel Sambuc size_t len = 0;
1654ebfedea0SLionel Sambuc size_t size;
1655ebfedea0SLionel Sambuc
1656ebfedea0SLionel Sambuc krb5_data_zero(out);
1657ebfedea0SLionel Sambuc
1658ebfedea0SLionel Sambuc if (ctx->as_req.req_body.cname == NULL) {
1659ebfedea0SLionel Sambuc ret = init_as_req(context, ctx->flags, &ctx->cred,
1660ebfedea0SLionel Sambuc ctx->addrs, ctx->etypes, &ctx->as_req);
1661ebfedea0SLionel Sambuc if (ret) {
1662ebfedea0SLionel Sambuc free_init_creds_ctx(context, ctx);
1663ebfedea0SLionel Sambuc return ret;
1664ebfedea0SLionel Sambuc }
1665ebfedea0SLionel Sambuc }
1666ebfedea0SLionel Sambuc
1667ebfedea0SLionel Sambuc #define MAX_PA_COUNTER 10
1668ebfedea0SLionel Sambuc if (ctx->pa_counter > MAX_PA_COUNTER) {
1669ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_GET_IN_TKT_LOOP,
1670ebfedea0SLionel Sambuc N_("Looping %d times while getting "
1671ebfedea0SLionel Sambuc "initial credentials", ""),
1672ebfedea0SLionel Sambuc ctx->pa_counter);
1673ebfedea0SLionel Sambuc return KRB5_GET_IN_TKT_LOOP;
1674ebfedea0SLionel Sambuc }
1675ebfedea0SLionel Sambuc ctx->pa_counter++;
1676ebfedea0SLionel Sambuc
1677ebfedea0SLionel Sambuc _krb5_debug(context, 5, "krb5_get_init_creds: loop %d", ctx->pa_counter);
1678ebfedea0SLionel Sambuc
1679ebfedea0SLionel Sambuc /* Lets process the input packet */
1680ebfedea0SLionel Sambuc if (in && in->length) {
1681ebfedea0SLionel Sambuc krb5_kdc_rep rep;
1682ebfedea0SLionel Sambuc
1683ebfedea0SLionel Sambuc memset(&rep, 0, sizeof(rep));
1684ebfedea0SLionel Sambuc
1685ebfedea0SLionel Sambuc _krb5_debug(context, 5, "krb5_get_init_creds: processing input");
1686ebfedea0SLionel Sambuc
1687ebfedea0SLionel Sambuc ret = decode_AS_REP(in->data, in->length, &rep.kdc_rep, &size);
1688ebfedea0SLionel Sambuc if (ret == 0) {
1689ebfedea0SLionel Sambuc krb5_keyblock *key = NULL;
1690ebfedea0SLionel Sambuc unsigned eflags = EXTRACT_TICKET_AS_REQ | EXTRACT_TICKET_TIMESYNC;
1691ebfedea0SLionel Sambuc
1692ebfedea0SLionel Sambuc if (ctx->flags.canonicalize) {
1693ebfedea0SLionel Sambuc eflags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH;
1694ebfedea0SLionel Sambuc eflags |= EXTRACT_TICKET_MATCH_REALM;
1695ebfedea0SLionel Sambuc }
1696ebfedea0SLionel Sambuc if (ctx->ic_flags & KRB5_INIT_CREDS_NO_C_CANON_CHECK)
1697ebfedea0SLionel Sambuc eflags |= EXTRACT_TICKET_ALLOW_CNAME_MISMATCH;
1698ebfedea0SLionel Sambuc
1699ebfedea0SLionel Sambuc ret = process_pa_data_to_key(context, ctx, &ctx->cred,
1700ebfedea0SLionel Sambuc &ctx->as_req, &rep.kdc_rep, hostinfo, &key);
1701ebfedea0SLionel Sambuc if (ret) {
1702ebfedea0SLionel Sambuc free_AS_REP(&rep.kdc_rep);
1703ebfedea0SLionel Sambuc goto out;
1704ebfedea0SLionel Sambuc }
1705ebfedea0SLionel Sambuc
1706ebfedea0SLionel Sambuc _krb5_debug(context, 5, "krb5_get_init_creds: extracting ticket");
1707ebfedea0SLionel Sambuc
1708ebfedea0SLionel Sambuc ret = _krb5_extract_ticket(context,
1709ebfedea0SLionel Sambuc &rep,
1710ebfedea0SLionel Sambuc &ctx->cred,
1711ebfedea0SLionel Sambuc key,
1712ebfedea0SLionel Sambuc NULL,
1713ebfedea0SLionel Sambuc KRB5_KU_AS_REP_ENC_PART,
1714ebfedea0SLionel Sambuc NULL,
1715ebfedea0SLionel Sambuc ctx->nonce,
1716ebfedea0SLionel Sambuc eflags,
1717ebfedea0SLionel Sambuc NULL,
1718ebfedea0SLionel Sambuc NULL);
1719ebfedea0SLionel Sambuc krb5_free_keyblock(context, key);
1720ebfedea0SLionel Sambuc
1721ebfedea0SLionel Sambuc *flags = 0;
1722ebfedea0SLionel Sambuc
1723ebfedea0SLionel Sambuc if (ret == 0)
1724ebfedea0SLionel Sambuc ret = copy_EncKDCRepPart(&rep.enc_part, &ctx->enc_part);
1725ebfedea0SLionel Sambuc
1726ebfedea0SLionel Sambuc free_AS_REP(&rep.kdc_rep);
1727ebfedea0SLionel Sambuc free_EncASRepPart(&rep.enc_part);
1728ebfedea0SLionel Sambuc
1729ebfedea0SLionel Sambuc return ret;
1730ebfedea0SLionel Sambuc
1731ebfedea0SLionel Sambuc } else {
1732ebfedea0SLionel Sambuc /* let's try to parse it as a KRB-ERROR */
1733ebfedea0SLionel Sambuc
1734ebfedea0SLionel Sambuc _krb5_debug(context, 5, "krb5_get_init_creds: got an error");
1735ebfedea0SLionel Sambuc
1736ebfedea0SLionel Sambuc free_KRB_ERROR(&ctx->error);
1737ebfedea0SLionel Sambuc
1738ebfedea0SLionel Sambuc ret = krb5_rd_error(context, in, &ctx->error);
1739ebfedea0SLionel Sambuc if(ret && in->length && ((char*)in->data)[0] == 4)
1740ebfedea0SLionel Sambuc ret = KRB5KRB_AP_ERR_V4_REPLY;
1741ebfedea0SLionel Sambuc if (ret) {
1742ebfedea0SLionel Sambuc _krb5_debug(context, 5, "krb5_get_init_creds: failed to read error");
1743ebfedea0SLionel Sambuc goto out;
1744ebfedea0SLionel Sambuc }
1745ebfedea0SLionel Sambuc
1746ebfedea0SLionel Sambuc ret = krb5_error_from_rd_error(context, &ctx->error, &ctx->cred);
1747ebfedea0SLionel Sambuc
1748ebfedea0SLionel Sambuc _krb5_debug(context, 5, "krb5_get_init_creds: KRB-ERROR %d", ret);
1749ebfedea0SLionel Sambuc
1750ebfedea0SLionel Sambuc /*
1751ebfedea0SLionel Sambuc * If no preauth was set and KDC requires it, give it one
1752ebfedea0SLionel Sambuc * more try.
1753ebfedea0SLionel Sambuc */
1754ebfedea0SLionel Sambuc
1755ebfedea0SLionel Sambuc if (ret == KRB5KDC_ERR_PREAUTH_REQUIRED) {
1756ebfedea0SLionel Sambuc
1757ebfedea0SLionel Sambuc free_METHOD_DATA(&ctx->md);
1758ebfedea0SLionel Sambuc memset(&ctx->md, 0, sizeof(ctx->md));
1759ebfedea0SLionel Sambuc
1760ebfedea0SLionel Sambuc if (ctx->error.e_data) {
1761ebfedea0SLionel Sambuc ret = decode_METHOD_DATA(ctx->error.e_data->data,
1762ebfedea0SLionel Sambuc ctx->error.e_data->length,
1763ebfedea0SLionel Sambuc &ctx->md,
1764ebfedea0SLionel Sambuc NULL);
1765ebfedea0SLionel Sambuc if (ret)
1766ebfedea0SLionel Sambuc krb5_set_error_message(context, ret,
1767ebfedea0SLionel Sambuc N_("Failed to decode METHOD-DATA", ""));
1768ebfedea0SLionel Sambuc } else {
1769ebfedea0SLionel Sambuc krb5_set_error_message(context, ret,
1770ebfedea0SLionel Sambuc N_("Preauth required but no preauth "
1771ebfedea0SLionel Sambuc "options send by KDC", ""));
1772ebfedea0SLionel Sambuc }
1773ebfedea0SLionel Sambuc } else if (ret == KRB5KRB_AP_ERR_SKEW && context->kdc_sec_offset == 0) {
1774ebfedea0SLionel Sambuc /*
1775ebfedea0SLionel Sambuc * Try adapt to timeskrew when we are using pre-auth, and
1776ebfedea0SLionel Sambuc * if there was a time skew, try again.
1777ebfedea0SLionel Sambuc */
1778ebfedea0SLionel Sambuc krb5_set_real_time(context, ctx->error.stime, -1);
1779ebfedea0SLionel Sambuc if (context->kdc_sec_offset)
1780ebfedea0SLionel Sambuc ret = 0;
1781ebfedea0SLionel Sambuc
1782ebfedea0SLionel Sambuc _krb5_debug(context, 10, "init_creds: err skew updateing kdc offset to %d",
1783ebfedea0SLionel Sambuc context->kdc_sec_offset);
1784ebfedea0SLionel Sambuc
1785ebfedea0SLionel Sambuc ctx->used_pa_types = 0;
1786ebfedea0SLionel Sambuc
1787ebfedea0SLionel Sambuc } else if (ret == KRB5_KDC_ERR_WRONG_REALM && ctx->flags.canonicalize) {
1788ebfedea0SLionel Sambuc /* client referal to a new realm */
1789ebfedea0SLionel Sambuc
1790ebfedea0SLionel Sambuc if (ctx->error.crealm == NULL) {
1791ebfedea0SLionel Sambuc krb5_set_error_message(context, ret,
1792ebfedea0SLionel Sambuc N_("Got a client referral, not but no realm", ""));
1793ebfedea0SLionel Sambuc goto out;
1794ebfedea0SLionel Sambuc }
1795ebfedea0SLionel Sambuc _krb5_debug(context, 5,
1796ebfedea0SLionel Sambuc "krb5_get_init_creds: got referal to realm %s",
1797ebfedea0SLionel Sambuc *ctx->error.crealm);
1798ebfedea0SLionel Sambuc
1799ebfedea0SLionel Sambuc ret = krb5_principal_set_realm(context,
1800ebfedea0SLionel Sambuc ctx->cred.client,
1801ebfedea0SLionel Sambuc *ctx->error.crealm);
1802ebfedea0SLionel Sambuc
1803ebfedea0SLionel Sambuc ctx->used_pa_types = 0;
1804ebfedea0SLionel Sambuc }
1805ebfedea0SLionel Sambuc if (ret)
1806ebfedea0SLionel Sambuc goto out;
1807ebfedea0SLionel Sambuc }
1808ebfedea0SLionel Sambuc }
1809ebfedea0SLionel Sambuc
1810ebfedea0SLionel Sambuc if (ctx->as_req.padata) {
1811ebfedea0SLionel Sambuc free_METHOD_DATA(ctx->as_req.padata);
1812ebfedea0SLionel Sambuc free(ctx->as_req.padata);
1813ebfedea0SLionel Sambuc ctx->as_req.padata = NULL;
1814ebfedea0SLionel Sambuc }
1815ebfedea0SLionel Sambuc
1816ebfedea0SLionel Sambuc /* Set a new nonce. */
1817ebfedea0SLionel Sambuc ctx->as_req.req_body.nonce = ctx->nonce;
1818ebfedea0SLionel Sambuc
1819ebfedea0SLionel Sambuc /* fill_in_md_data */
1820ebfedea0SLionel Sambuc ret = process_pa_data_to_md(context, &ctx->cred, &ctx->as_req, ctx,
1821ebfedea0SLionel Sambuc &ctx->md, &ctx->as_req.padata,
1822ebfedea0SLionel Sambuc ctx->prompter, ctx->prompter_data);
1823ebfedea0SLionel Sambuc if (ret)
1824ebfedea0SLionel Sambuc goto out;
1825ebfedea0SLionel Sambuc
1826ebfedea0SLionel Sambuc krb5_data_free(&ctx->req_buffer);
1827ebfedea0SLionel Sambuc
1828ebfedea0SLionel Sambuc ASN1_MALLOC_ENCODE(AS_REQ,
1829ebfedea0SLionel Sambuc ctx->req_buffer.data, ctx->req_buffer.length,
1830ebfedea0SLionel Sambuc &ctx->as_req, &len, ret);
1831ebfedea0SLionel Sambuc if (ret)
1832ebfedea0SLionel Sambuc goto out;
1833ebfedea0SLionel Sambuc if(len != ctx->req_buffer.length)
1834ebfedea0SLionel Sambuc krb5_abortx(context, "internal error in ASN.1 encoder");
1835ebfedea0SLionel Sambuc
1836ebfedea0SLionel Sambuc out->data = ctx->req_buffer.data;
1837ebfedea0SLionel Sambuc out->length = ctx->req_buffer.length;
1838ebfedea0SLionel Sambuc
1839ebfedea0SLionel Sambuc *flags = KRB5_INIT_CREDS_STEP_FLAG_CONTINUE;
1840ebfedea0SLionel Sambuc
1841ebfedea0SLionel Sambuc return 0;
1842ebfedea0SLionel Sambuc out:
1843ebfedea0SLionel Sambuc return ret;
1844ebfedea0SLionel Sambuc }
1845ebfedea0SLionel Sambuc
1846ebfedea0SLionel Sambuc /**
1847ebfedea0SLionel Sambuc * Extract the newly acquired credentials from krb5_init_creds_context
1848ebfedea0SLionel Sambuc * context.
1849ebfedea0SLionel Sambuc *
1850ebfedea0SLionel Sambuc * @param context A Kerberos 5 context.
1851ebfedea0SLionel Sambuc * @param ctx
1852ebfedea0SLionel Sambuc * @param cred credentials, free with krb5_free_cred_contents().
1853ebfedea0SLionel Sambuc *
1854ebfedea0SLionel Sambuc * @return 0 for sucess or An Kerberos error code, see krb5_get_error_message().
1855ebfedea0SLionel Sambuc */
1856ebfedea0SLionel Sambuc
1857ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_init_creds_get_creds(krb5_context context,krb5_init_creds_context ctx,krb5_creds * cred)1858ebfedea0SLionel Sambuc krb5_init_creds_get_creds(krb5_context context,
1859ebfedea0SLionel Sambuc krb5_init_creds_context ctx,
1860ebfedea0SLionel Sambuc krb5_creds *cred)
1861ebfedea0SLionel Sambuc {
1862ebfedea0SLionel Sambuc return krb5_copy_creds_contents(context, &ctx->cred, cred);
1863ebfedea0SLionel Sambuc }
1864ebfedea0SLionel Sambuc
1865ebfedea0SLionel Sambuc /**
1866ebfedea0SLionel Sambuc * Get the last error from the transaction.
1867ebfedea0SLionel Sambuc *
1868ebfedea0SLionel Sambuc * @return Returns 0 or an error code
1869ebfedea0SLionel Sambuc *
1870ebfedea0SLionel Sambuc * @ingroup krb5_credential
1871ebfedea0SLionel Sambuc */
1872ebfedea0SLionel Sambuc
1873ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_init_creds_get_error(krb5_context context,krb5_init_creds_context ctx,KRB_ERROR * error)1874ebfedea0SLionel Sambuc krb5_init_creds_get_error(krb5_context context,
1875ebfedea0SLionel Sambuc krb5_init_creds_context ctx,
1876ebfedea0SLionel Sambuc KRB_ERROR *error)
1877ebfedea0SLionel Sambuc {
1878ebfedea0SLionel Sambuc krb5_error_code ret;
1879ebfedea0SLionel Sambuc
1880ebfedea0SLionel Sambuc ret = copy_KRB_ERROR(&ctx->error, error);
1881ebfedea0SLionel Sambuc if (ret)
1882ebfedea0SLionel Sambuc krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
1883ebfedea0SLionel Sambuc
1884ebfedea0SLionel Sambuc return ret;
1885ebfedea0SLionel Sambuc }
1886ebfedea0SLionel Sambuc
1887ebfedea0SLionel Sambuc /**
1888ebfedea0SLionel Sambuc * Free the krb5_init_creds_context allocated by krb5_init_creds_init().
1889ebfedea0SLionel Sambuc *
1890ebfedea0SLionel Sambuc * @param context A Kerberos 5 context.
1891ebfedea0SLionel Sambuc * @param ctx The krb5_init_creds_context to free.
1892ebfedea0SLionel Sambuc *
1893ebfedea0SLionel Sambuc * @ingroup krb5_credential
1894ebfedea0SLionel Sambuc */
1895ebfedea0SLionel Sambuc
1896ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION void KRB5_LIB_CALL
krb5_init_creds_free(krb5_context context,krb5_init_creds_context ctx)1897ebfedea0SLionel Sambuc krb5_init_creds_free(krb5_context context,
1898ebfedea0SLionel Sambuc krb5_init_creds_context ctx)
1899ebfedea0SLionel Sambuc {
1900ebfedea0SLionel Sambuc free_init_creds_ctx(context, ctx);
1901ebfedea0SLionel Sambuc free(ctx);
1902ebfedea0SLionel Sambuc }
1903ebfedea0SLionel Sambuc
1904ebfedea0SLionel Sambuc /**
1905ebfedea0SLionel Sambuc * Get new credentials as setup by the krb5_init_creds_context.
1906ebfedea0SLionel Sambuc *
1907ebfedea0SLionel Sambuc * @param context A Kerberos 5 context.
1908ebfedea0SLionel Sambuc * @param ctx The krb5_init_creds_context to process.
1909ebfedea0SLionel Sambuc *
1910ebfedea0SLionel Sambuc * @ingroup krb5_credential
1911ebfedea0SLionel Sambuc */
1912ebfedea0SLionel Sambuc
1913ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_init_creds_get(krb5_context context,krb5_init_creds_context ctx)1914ebfedea0SLionel Sambuc krb5_init_creds_get(krb5_context context, krb5_init_creds_context ctx)
1915ebfedea0SLionel Sambuc {
1916ebfedea0SLionel Sambuc krb5_sendto_ctx stctx = NULL;
1917ebfedea0SLionel Sambuc krb5_krbhst_info *hostinfo = NULL;
1918ebfedea0SLionel Sambuc krb5_error_code ret;
1919ebfedea0SLionel Sambuc krb5_data in, out;
1920ebfedea0SLionel Sambuc unsigned int flags = 0;
1921ebfedea0SLionel Sambuc
1922ebfedea0SLionel Sambuc krb5_data_zero(&in);
1923ebfedea0SLionel Sambuc krb5_data_zero(&out);
1924ebfedea0SLionel Sambuc
1925ebfedea0SLionel Sambuc ret = krb5_sendto_ctx_alloc(context, &stctx);
1926ebfedea0SLionel Sambuc if (ret)
1927ebfedea0SLionel Sambuc goto out;
1928ebfedea0SLionel Sambuc krb5_sendto_ctx_set_func(stctx, _krb5_kdc_retry, NULL);
1929ebfedea0SLionel Sambuc
1930ebfedea0SLionel Sambuc while (1) {
1931ebfedea0SLionel Sambuc flags = 0;
1932ebfedea0SLionel Sambuc ret = krb5_init_creds_step(context, ctx, &in, &out, hostinfo, &flags);
1933ebfedea0SLionel Sambuc krb5_data_free(&in);
1934ebfedea0SLionel Sambuc if (ret)
1935ebfedea0SLionel Sambuc goto out;
1936ebfedea0SLionel Sambuc
1937ebfedea0SLionel Sambuc if ((flags & 1) == 0)
1938ebfedea0SLionel Sambuc break;
1939ebfedea0SLionel Sambuc
1940ebfedea0SLionel Sambuc ret = krb5_sendto_context (context, stctx, &out,
1941ebfedea0SLionel Sambuc ctx->cred.client->realm, &in);
1942ebfedea0SLionel Sambuc if (ret)
1943ebfedea0SLionel Sambuc goto out;
1944ebfedea0SLionel Sambuc
1945ebfedea0SLionel Sambuc }
1946ebfedea0SLionel Sambuc
1947ebfedea0SLionel Sambuc out:
1948ebfedea0SLionel Sambuc if (stctx)
1949ebfedea0SLionel Sambuc krb5_sendto_ctx_free(context, stctx);
1950ebfedea0SLionel Sambuc
1951ebfedea0SLionel Sambuc return ret;
1952ebfedea0SLionel Sambuc }
1953ebfedea0SLionel Sambuc
1954ebfedea0SLionel Sambuc /**
1955ebfedea0SLionel Sambuc * Get new credentials using password.
1956ebfedea0SLionel Sambuc *
1957ebfedea0SLionel Sambuc * @ingroup krb5_credential
1958ebfedea0SLionel Sambuc */
1959ebfedea0SLionel Sambuc
1960ebfedea0SLionel Sambuc
1961ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_get_init_creds_password(krb5_context context,krb5_creds * creds,krb5_principal client,const char * password,krb5_prompter_fct prompter,void * data,krb5_deltat start_time,const char * in_tkt_service,krb5_get_init_creds_opt * options)1962ebfedea0SLionel Sambuc krb5_get_init_creds_password(krb5_context context,
1963ebfedea0SLionel Sambuc krb5_creds *creds,
1964ebfedea0SLionel Sambuc krb5_principal client,
1965ebfedea0SLionel Sambuc const char *password,
1966ebfedea0SLionel Sambuc krb5_prompter_fct prompter,
1967ebfedea0SLionel Sambuc void *data,
1968ebfedea0SLionel Sambuc krb5_deltat start_time,
1969ebfedea0SLionel Sambuc const char *in_tkt_service,
1970ebfedea0SLionel Sambuc krb5_get_init_creds_opt *options)
1971ebfedea0SLionel Sambuc {
1972ebfedea0SLionel Sambuc krb5_init_creds_context ctx;
1973ebfedea0SLionel Sambuc char buf[BUFSIZ];
1974ebfedea0SLionel Sambuc krb5_error_code ret;
1975ebfedea0SLionel Sambuc int chpw = 0;
1976ebfedea0SLionel Sambuc
1977ebfedea0SLionel Sambuc again:
1978ebfedea0SLionel Sambuc ret = krb5_init_creds_init(context, client, prompter, data, start_time, options, &ctx);
1979ebfedea0SLionel Sambuc if (ret)
1980ebfedea0SLionel Sambuc goto out;
1981ebfedea0SLionel Sambuc
1982ebfedea0SLionel Sambuc ret = krb5_init_creds_set_service(context, ctx, in_tkt_service);
1983ebfedea0SLionel Sambuc if (ret)
1984ebfedea0SLionel Sambuc goto out;
1985ebfedea0SLionel Sambuc
1986ebfedea0SLionel Sambuc if (prompter != NULL && ctx->password == NULL && password == NULL) {
1987ebfedea0SLionel Sambuc krb5_prompt prompt;
1988ebfedea0SLionel Sambuc krb5_data password_data;
1989ebfedea0SLionel Sambuc char *p, *q;
1990ebfedea0SLionel Sambuc
1991ebfedea0SLionel Sambuc krb5_unparse_name (context, client, &p);
1992ebfedea0SLionel Sambuc asprintf (&q, "%s's Password: ", p);
1993ebfedea0SLionel Sambuc free (p);
1994ebfedea0SLionel Sambuc prompt.prompt = q;
1995ebfedea0SLionel Sambuc password_data.data = buf;
1996ebfedea0SLionel Sambuc password_data.length = sizeof(buf);
1997ebfedea0SLionel Sambuc prompt.hidden = 1;
1998ebfedea0SLionel Sambuc prompt.reply = &password_data;
1999ebfedea0SLionel Sambuc prompt.type = KRB5_PROMPT_TYPE_PASSWORD;
2000ebfedea0SLionel Sambuc
2001ebfedea0SLionel Sambuc ret = (*prompter) (context, data, NULL, NULL, 1, &prompt);
2002ebfedea0SLionel Sambuc free (q);
2003ebfedea0SLionel Sambuc if (ret) {
2004ebfedea0SLionel Sambuc memset (buf, 0, sizeof(buf));
2005ebfedea0SLionel Sambuc ret = KRB5_LIBOS_PWDINTR;
2006ebfedea0SLionel Sambuc krb5_clear_error_message (context);
2007ebfedea0SLionel Sambuc goto out;
2008ebfedea0SLionel Sambuc }
2009ebfedea0SLionel Sambuc password = password_data.data;
2010ebfedea0SLionel Sambuc }
2011ebfedea0SLionel Sambuc
2012ebfedea0SLionel Sambuc if (password) {
2013ebfedea0SLionel Sambuc ret = krb5_init_creds_set_password(context, ctx, password);
2014ebfedea0SLionel Sambuc if (ret)
2015ebfedea0SLionel Sambuc goto out;
2016ebfedea0SLionel Sambuc }
2017ebfedea0SLionel Sambuc
2018ebfedea0SLionel Sambuc ret = krb5_init_creds_get(context, ctx);
2019ebfedea0SLionel Sambuc
2020ebfedea0SLionel Sambuc if (ret == 0)
2021ebfedea0SLionel Sambuc process_last_request(context, options, ctx);
2022ebfedea0SLionel Sambuc
2023ebfedea0SLionel Sambuc
2024ebfedea0SLionel Sambuc if (ret == KRB5KDC_ERR_KEY_EXPIRED && chpw == 0) {
2025ebfedea0SLionel Sambuc char buf2[1024];
2026ebfedea0SLionel Sambuc
2027ebfedea0SLionel Sambuc /* try to avoid recursion */
2028ebfedea0SLionel Sambuc if (in_tkt_service != NULL && strcmp(in_tkt_service, "kadmin/changepw") == 0)
2029ebfedea0SLionel Sambuc goto out;
2030ebfedea0SLionel Sambuc
2031ebfedea0SLionel Sambuc /* don't try to change password where then where none */
2032ebfedea0SLionel Sambuc if (prompter == NULL)
2033ebfedea0SLionel Sambuc goto out;
2034ebfedea0SLionel Sambuc
2035ebfedea0SLionel Sambuc ret = change_password (context,
2036ebfedea0SLionel Sambuc client,
2037ebfedea0SLionel Sambuc ctx->password,
2038ebfedea0SLionel Sambuc buf2,
2039ebfedea0SLionel Sambuc sizeof(buf),
2040ebfedea0SLionel Sambuc prompter,
2041ebfedea0SLionel Sambuc data,
2042ebfedea0SLionel Sambuc options);
2043ebfedea0SLionel Sambuc if (ret)
2044ebfedea0SLionel Sambuc goto out;
2045ebfedea0SLionel Sambuc chpw = 1;
2046ebfedea0SLionel Sambuc krb5_init_creds_free(context, ctx);
2047ebfedea0SLionel Sambuc goto again;
2048ebfedea0SLionel Sambuc }
2049ebfedea0SLionel Sambuc
2050ebfedea0SLionel Sambuc out:
2051ebfedea0SLionel Sambuc if (ret == 0)
2052ebfedea0SLionel Sambuc krb5_init_creds_get_creds(context, ctx, creds);
2053ebfedea0SLionel Sambuc
2054ebfedea0SLionel Sambuc if (ctx)
2055ebfedea0SLionel Sambuc krb5_init_creds_free(context, ctx);
2056ebfedea0SLionel Sambuc
2057ebfedea0SLionel Sambuc memset(buf, 0, sizeof(buf));
2058ebfedea0SLionel Sambuc return ret;
2059ebfedea0SLionel Sambuc }
2060ebfedea0SLionel Sambuc
2061ebfedea0SLionel Sambuc /**
2062ebfedea0SLionel Sambuc * Get new credentials using keyblock.
2063ebfedea0SLionel Sambuc *
2064ebfedea0SLionel Sambuc * @ingroup krb5_credential
2065ebfedea0SLionel Sambuc */
2066ebfedea0SLionel Sambuc
2067ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_get_init_creds_keyblock(krb5_context context,krb5_creds * creds,krb5_principal client,krb5_keyblock * keyblock,krb5_deltat start_time,const char * in_tkt_service,krb5_get_init_creds_opt * options)2068ebfedea0SLionel Sambuc krb5_get_init_creds_keyblock(krb5_context context,
2069ebfedea0SLionel Sambuc krb5_creds *creds,
2070ebfedea0SLionel Sambuc krb5_principal client,
2071ebfedea0SLionel Sambuc krb5_keyblock *keyblock,
2072ebfedea0SLionel Sambuc krb5_deltat start_time,
2073ebfedea0SLionel Sambuc const char *in_tkt_service,
2074ebfedea0SLionel Sambuc krb5_get_init_creds_opt *options)
2075ebfedea0SLionel Sambuc {
2076ebfedea0SLionel Sambuc krb5_init_creds_context ctx;
2077ebfedea0SLionel Sambuc krb5_error_code ret;
2078ebfedea0SLionel Sambuc
2079ebfedea0SLionel Sambuc memset(creds, 0, sizeof(*creds));
2080ebfedea0SLionel Sambuc
2081ebfedea0SLionel Sambuc ret = krb5_init_creds_init(context, client, NULL, NULL, start_time, options, &ctx);
2082ebfedea0SLionel Sambuc if (ret)
2083ebfedea0SLionel Sambuc goto out;
2084ebfedea0SLionel Sambuc
2085ebfedea0SLionel Sambuc ret = krb5_init_creds_set_service(context, ctx, in_tkt_service);
2086ebfedea0SLionel Sambuc if (ret)
2087ebfedea0SLionel Sambuc goto out;
2088ebfedea0SLionel Sambuc
2089ebfedea0SLionel Sambuc ret = krb5_init_creds_set_keyblock(context, ctx, keyblock);
2090ebfedea0SLionel Sambuc if (ret)
2091ebfedea0SLionel Sambuc goto out;
2092ebfedea0SLionel Sambuc
2093ebfedea0SLionel Sambuc ret = krb5_init_creds_get(context, ctx);
2094ebfedea0SLionel Sambuc
2095ebfedea0SLionel Sambuc if (ret == 0)
2096ebfedea0SLionel Sambuc process_last_request(context, options, ctx);
2097ebfedea0SLionel Sambuc
2098ebfedea0SLionel Sambuc out:
2099ebfedea0SLionel Sambuc if (ret == 0)
2100ebfedea0SLionel Sambuc krb5_init_creds_get_creds(context, ctx, creds);
2101ebfedea0SLionel Sambuc
2102ebfedea0SLionel Sambuc if (ctx)
2103ebfedea0SLionel Sambuc krb5_init_creds_free(context, ctx);
2104ebfedea0SLionel Sambuc
2105ebfedea0SLionel Sambuc return ret;
2106ebfedea0SLionel Sambuc }
2107ebfedea0SLionel Sambuc
2108ebfedea0SLionel Sambuc /**
2109ebfedea0SLionel Sambuc * Get new credentials using keytab.
2110ebfedea0SLionel Sambuc *
2111ebfedea0SLionel Sambuc * @ingroup krb5_credential
2112ebfedea0SLionel Sambuc */
2113ebfedea0SLionel Sambuc
2114ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_get_init_creds_keytab(krb5_context context,krb5_creds * creds,krb5_principal client,krb5_keytab keytab,krb5_deltat start_time,const char * in_tkt_service,krb5_get_init_creds_opt * options)2115ebfedea0SLionel Sambuc krb5_get_init_creds_keytab(krb5_context context,
2116ebfedea0SLionel Sambuc krb5_creds *creds,
2117ebfedea0SLionel Sambuc krb5_principal client,
2118ebfedea0SLionel Sambuc krb5_keytab keytab,
2119ebfedea0SLionel Sambuc krb5_deltat start_time,
2120ebfedea0SLionel Sambuc const char *in_tkt_service,
2121ebfedea0SLionel Sambuc krb5_get_init_creds_opt *options)
2122ebfedea0SLionel Sambuc {
2123ebfedea0SLionel Sambuc krb5_init_creds_context ctx;
2124ebfedea0SLionel Sambuc krb5_error_code ret;
2125ebfedea0SLionel Sambuc
2126ebfedea0SLionel Sambuc memset(creds, 0, sizeof(*creds));
2127ebfedea0SLionel Sambuc
2128ebfedea0SLionel Sambuc ret = krb5_init_creds_init(context, client, NULL, NULL, start_time, options, &ctx);
2129ebfedea0SLionel Sambuc if (ret)
2130ebfedea0SLionel Sambuc goto out;
2131ebfedea0SLionel Sambuc
2132ebfedea0SLionel Sambuc ret = krb5_init_creds_set_service(context, ctx, in_tkt_service);
2133ebfedea0SLionel Sambuc if (ret)
2134ebfedea0SLionel Sambuc goto out;
2135ebfedea0SLionel Sambuc
2136ebfedea0SLionel Sambuc ret = krb5_init_creds_set_keytab(context, ctx, keytab);
2137ebfedea0SLionel Sambuc if (ret)
2138ebfedea0SLionel Sambuc goto out;
2139ebfedea0SLionel Sambuc
2140ebfedea0SLionel Sambuc ret = krb5_init_creds_get(context, ctx);
2141ebfedea0SLionel Sambuc if (ret == 0)
2142ebfedea0SLionel Sambuc process_last_request(context, options, ctx);
2143ebfedea0SLionel Sambuc
2144ebfedea0SLionel Sambuc out:
2145ebfedea0SLionel Sambuc if (ret == 0)
2146ebfedea0SLionel Sambuc krb5_init_creds_get_creds(context, ctx, creds);
2147ebfedea0SLionel Sambuc
2148ebfedea0SLionel Sambuc if (ctx)
2149ebfedea0SLionel Sambuc krb5_init_creds_free(context, ctx);
2150ebfedea0SLionel Sambuc
2151ebfedea0SLionel Sambuc return ret;
2152ebfedea0SLionel Sambuc }
2153