]> git.ipfire.org Git - thirdparty/samba.git/blame - third_party/heimdal/kdc/kerberos5.c
third_party/heimdal: Import lorikeet-heimdal-202405090452 (commit 49c8e97b7221db53355...
[thirdparty/samba.git] / third_party / heimdal / kdc / kerberos5.c
CommitLineData
954c0172 1/*
2b29b718
SM
2 * Copyright (c) 1997-2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
954c0172 5 *
2b29b718
SM
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
954c0172 9 *
2b29b718
SM
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
954c0172 12 *
2b29b718
SM
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
954c0172 16 *
2b29b718
SM
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
954c0172 20 *
2b29b718
SM
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
954c0172
HIU
32 */
33
34#include "kdc_locl.h"
954c0172 35
51569b31
JS
36#ifdef TIME_T_SIGNED
37#if SIZEOF_TIME_T == 4
38#define MAX_TIME ((time_t)INT32_MAX)
39#elif SIZEOF_TIME_T == 8
40#define MAX_TIME ((time_t)INT64_MAX)
41#else
42#error "Unexpected sizeof(time_t)"
43#endif
44#else
45
46#if SIZEOF_TIME_T == 4
47#define MAX_TIME ((time_t)UINT32_MAX)
48#else
49#define MAX_TIME ((time_t)UINT64_MAX)
50#endif
51#endif
954c0172 52
40b65c84
SM
53#undef __attribute__
54#define __attribute__(X)
55
3c1e780e
AB
56void
57_kdc_fix_time(time_t **t)
954c0172
HIU
58{
59 if(*t == NULL){
60 ALLOC(*t);
61 **t = MAX_TIME;
62 }
63 if(**t == 0) **t = MAX_TIME; /* fix for old clients */
64}
65
66static int
67realloc_method_data(METHOD_DATA *md)
68{
69 PA_DATA *pa;
70 pa = realloc(md->val, (md->len + 1) * sizeof(*md->val));
71 if(pa == NULL)
72 return ENOMEM;
73 md->val = pa;
74 md->len++;
75 return 0;
76}
77
40b65c84
SM
78static krb5_error_code
79get_pa_etype_info2(krb5_context context,
80 krb5_kdc_configuration *config,
81 METHOD_DATA *md, Key *ckey,
82 krb5_boolean include_salt);
83
84static krb5_error_code
85set_salt_padata(krb5_context context,
86 krb5_kdc_configuration *config,
87 METHOD_DATA *md, Key *key)
954c0172 88{
51569b31
JS
89 if (!key->salt)
90 return 0;
40b65c84 91
51569b31 92 return get_pa_etype_info2(context, config, md, key, TRUE);
954c0172
HIU
93}
94
91adebe7
AB
95const PA_DATA*
96_kdc_find_padata(const KDC_REQ *req, int *start, int type)
954c0172 97{
91adebe7
AB
98 if (req->padata == NULL)
99 return NULL;
100
255e3e18 101 while((size_t)*start < req->padata->len){
954c0172 102 (*start)++;
255e3e18 103 if(req->padata->val[*start - 1].padata_type == (unsigned)type)
954c0172
HIU
104 return &req->padata->val[*start - 1];
105 }
106 return NULL;
107}
108
243321b4
SM
109/*
110 * This is a hack to allow predefined weak services, like afs to
111 * still use weak types
112 */
113
114krb5_boolean
9b261c00 115_kdc_is_weak_exception(krb5_principal principal, krb5_enctype etype)
243321b4
SM
116{
117 if (principal->name.name_string.len > 0 &&
118 strcmp(principal->name.name_string.val[0], "afs") == 0 &&
51569b31
JS
119 (etype == ETYPE_DES_CBC_CRC
120 || etype == ETYPE_DES_CBC_MD4
121 || etype == ETYPE_DES_CBC_MD5))
243321b4
SM
122 return TRUE;
123 return FALSE;
124}
125
126
b39330c4
AB
127/*
128 * Detect if `key' is the using the the precomputed `default_salt'.
129 */
130
131static krb5_boolean
132is_default_salt_p(const krb5_salt *default_salt, const Key *key)
133{
134 if (key->salt == NULL)
135 return TRUE;
136 if (default_salt->salttype != key->salt->type)
137 return FALSE;
51569b31 138 if (krb5_data_cmp(&default_salt->saltvalue, &key->salt->salt) != 0)
b39330c4
AB
139 return FALSE;
140 return TRUE;
141}
142
40b65c84
SM
143/*
144 * Detect if `key' is the using the the precomputed `default_salt'
145 * (for des-cbc-crc) or any salt otherwise.
146 *
147 * This is for avoiding Kerberos v4 (yes really) keys in AS-REQ as
148 * that salt is strange, and a buggy client will try to use the
149 * principal as the salt and not the returned value.
150 */
151
152static krb5_boolean
153is_good_salt_p(const krb5_salt *default_salt, const Key *key)
154{
51569b31
JS
155 if (key->key.keytype == KRB5_ENCTYPE_DES_CBC_CRC)
156 return is_default_salt_p(default_salt, key);
40b65c84 157
51569b31
JS
158 return TRUE;
159}
40b65c84
SM
160
161krb5_boolean
162_kdc_is_anon_request(const KDC_REQ *req)
163{
164 const KDC_REQ_BODY *b = &req->req_body;
165
166 /*
167 * Versions of Heimdal from 0.9rc1 through 1.50 use bit 14 instead
168 * of 16 for request_anonymous, as indicated in the anonymous draft
169 * prior to version 11. Bit 14 is assigned to S4U2Proxy, but S4U2Proxy
170 * requests are only sent to the TGS and, in any case, would have an
171 * additional ticket present.
172 */
173 return b->kdc_options.request_anonymous ||
174 (b->kdc_options.cname_in_addl_tkt && !b->additional_tickets);
175}
176
954c0172
HIU
177/*
178 * return the first appropriate key of `princ' in `ret_key'. Look for
179 * all the etypes in (`etypes', `len'), stopping as soon as we find
40b65c84
SM
180 * one, but preferring one that has default salt.
181 *
182 * XXX This function does way way too much. Split it up!
183 *
184 * XXX `etypes' and `len' are always `b->etype.val' and `b->etype.len' -- the
185 * etype list from the KDC-REQ-BODY, which is available here as
186 * `r->req->req_body', so we could just stop having it passed in.
187 *
188 * XXX Picking an enctype(s) for PA-ETYPE-INFO* is rather different than
189 * picking an enctype for a ticket's session key. The former is what we do
190 * here when `(flags & KFE_IS_PREAUTH)', the latter otherwise.
954c0172
HIU
191 */
192
3c1e780e 193krb5_error_code
40b65c84 194_kdc_find_etype(astgs_request_t r, uint32_t flags,
2b29b718 195 krb5_enctype *etypes, unsigned len,
40b65c84
SM
196 krb5_enctype *ret_enctype, Key **ret_key,
197 krb5_boolean *ret_default_salt)
954c0172 198{
40b65c84
SM
199 krb5_boolean use_strongest_session_key;
200 krb5_boolean is_preauth = flags & KFE_IS_PREAUTH;
201 krb5_boolean is_tgs = flags & KFE_IS_TGS;
51569b31 202 hdb_entry *princ;
40b65c84 203 krb5_principal request_princ;
255e3e18 204 krb5_error_code ret;
b39330c4 205 krb5_salt def_salt;
51569b31 206 krb5_enctype enctype = ETYPE_NULL;
40b65c84
SM
207 const krb5_enctype *p;
208 Key *key = NULL;
209 size_t i, k, m;
210
211 if (is_preauth && (flags & KFE_USE_CLIENT) &&
51569b31 212 r->client->flags.synthetic)
40b65c84
SM
213 return KRB5KDC_ERR_ETYPE_NOSUPP;
214
51569b31 215 if ((flags & KFE_USE_CLIENT) && !r->client->flags.synthetic) {
40b65c84
SM
216 princ = r->client;
217 request_princ = r->client_princ;
218 } else {
219 princ = r->server;
51569b31 220 request_princ = r->server->principal;
40b65c84
SM
221 }
222
223 use_strongest_session_key =
224 is_preauth ? r->config->preauth_use_strongest_session_key
225 : (is_tgs ? r->config->tgt_use_strongest_session_key :
226 r->config->svc_use_strongest_session_key);
b39330c4 227
255e3e18 228 /* We'll want to avoid keys with v4 salted keys in the pre-auth case... */
40b65c84 229 ret = krb5_get_pw_salt(r->context, request_princ, &def_salt);
255e3e18
SM
230 if (ret)
231 return ret;
954c0172 232
255e3e18 233 ret = KRB5KDC_ERR_ETYPE_NOSUPP;
954c0172 234
40b65c84
SM
235 /*
236 * Pick an enctype that is in the intersection of:
237 *
238 * - permitted_enctypes (local policy)
239 * - requested enctypes (KDC-REQ-BODY's etype list)
240 * - the client's long-term keys' enctypes
241 * OR
242 * the server's configured etype list
243 *
244 * There are two sub-cases:
245 *
246 * - use local enctype preference (local policy)
247 * - use the client's preference list
248 */
954c0172 249
40b65c84 250 if (use_strongest_session_key) {
255e3e18
SM
251 /*
252 * Pick the strongest key that the KDC, target service, and
253 * client all support, using the local cryptosystem enctype
254 * list in strongest-to-weakest order to drive the search.
255 *
256 * This is not what RFC4120 says to do, but it encourages
257 * adoption of stronger enctypes. This doesn't play well with
258 * clients that have multiple Kerberos client implementations
40b65c84 259 * with different supported enctype lists sharing the same ccache.
255e3e18
SM
260 */
261
262 /* drive the search with local supported enctypes list */
40b65c84
SM
263 p = krb5_kerberos_enctypes(r->context);
264 for (i = 0;
51569b31 265 p[i] != ETYPE_NULL && enctype == ETYPE_NULL;
40b65c84
SM
266 i++) {
267 if (krb5_enctype_valid(r->context, p[i]) != 0 &&
51569b31 268 !_kdc_is_weak_exception(princ->principal, p[i]))
954c0172 269 continue;
255e3e18
SM
270
271 /* check that the client supports it too */
51569b31 272 for (k = 0; k < len && enctype == ETYPE_NULL; k++) {
40b65c84
SM
273
274 if (p[i] != etypes[k])
255e3e18 275 continue;
40b65c84
SM
276
277 if (!is_preauth && (flags & KFE_USE_CLIENT)) {
278 /*
279 * It suffices that the client says it supports this
280 * enctype in its KDC-REQ-BODY's etype list, which is what
281 * `etypes' is here.
282 */
f33f73f8 283 enctype = p[i];
40b65c84
SM
284 ret = 0;
285 break;
286 }
287
288 /* check target princ support */
289 key = NULL;
51569b31 290 if (!is_preauth && !(flags & KFE_USE_CLIENT) && princ->etypes) {
40b65c84
SM
291 /*
292 * Use the etypes list from the server's HDB entry instead
293 * of deriving it from its long-term keys. This allows an
294 * entry to have just one long-term key but record support
295 * for multiple enctypes.
296 */
51569b31
JS
297 for (m = 0; m < princ->etypes->len; m++) {
298 if (p[i] == princ->etypes->val[m]) {
f33f73f8 299 enctype = p[i];
40b65c84
SM
300 ret = 0;
301 break;
302 }
303 }
304 } else {
305 /*
306 * Use the entry's long-term keys as the source of its
307 * supported enctypes, either because we're making
308 * PA-ETYPE-INFO* or because we're selecting a session key
309 * enctype.
310 */
51569b31 311 while (hdb_next_enctype2key(r->context, princ, NULL,
40b65c84
SM
312 p[i], &key) == 0) {
313 if (key->key.keyvalue.length == 0) {
314 ret = KRB5KDC_ERR_NULL_KEY;
315 continue;
316 }
317 enctype = p[i];
318 ret = 0;
319 if (is_preauth && ret_key != NULL &&
320 !is_good_salt_p(&def_salt, key))
321 continue;
322 }
323 }
954c0172 324 }
255e3e18 325 }
255e3e18
SM
326 } else {
327 /*
328 * Pick the first key from the client's enctype list that is
329 * supported by the cryptosystem and by the given principal.
330 *
331 * RFC4120 says we SHOULD pick the first _strong_ key from the
332 * client's list... not the first key... If the admin disallows
333 * weak enctypes in krb5.conf and selects this key selection
334 * algorithm, then we get exactly what RFC4120 says.
335 */
40b65c84 336 for(i = 0; ret != 0 && i < len; i++) {
255e3e18 337
40b65c84 338 if (krb5_enctype_valid(r->context, etypes[i]) != 0 &&
51569b31 339 !_kdc_is_weak_exception(princ->principal, etypes[i]))
255e3e18
SM
340 continue;
341
40b65c84
SM
342 key = NULL;
343 while (ret != 0 &&
51569b31 344 hdb_next_enctype2key(r->context, princ, NULL,
40b65c84 345 etypes[i], &key) == 0) {
255e3e18
SM
346 if (key->key.keyvalue.length == 0) {
347 ret = KRB5KDC_ERR_NULL_KEY;
348 continue;
349 }
40b65c84 350 enctype = etypes[i];
255e3e18 351 ret = 0;
40b65c84
SM
352 if (is_preauth && ret_key != NULL &&
353 !is_good_salt_p(&def_salt, key))
354 continue;
b39330c4 355 }
954c0172
HIU
356 }
357 }
255e3e18 358
51569b31 359 if (ret == 0 && enctype == ETYPE_NULL) {
40b65c84
SM
360 /*
361 * if the service principal is one for which there is a known 1DES
362 * exception and no other enctype matches both the client request and
363 * the service key list, provide a DES-CBC-CRC key.
364 */
365 if (ret_key == NULL &&
51569b31 366 _kdc_is_weak_exception(princ->principal, ETYPE_DES_CBC_CRC)) {
40b65c84
SM
367 ret = 0;
368 enctype = ETYPE_DES_CBC_CRC;
369 } else {
370 ret = KRB5KDC_ERR_ETYPE_NOSUPP;
371 }
372 }
373
374 if (ret == 0) {
375 if (ret_enctype != NULL)
376 *ret_enctype = enctype;
377 if (ret_key != NULL)
378 *ret_key = key;
379 if (ret_default_salt != NULL)
380 *ret_default_salt = is_default_salt_p(&def_salt, key);
381 }
382
383 krb5_free_salt (r->context, def_salt);
954c0172
HIU
384 return ret;
385}
386
975e43fc
AB
387/*
388 * The principal's session_etypes must be sorted in order of strength, with
389 * preferred etype first.
390*/
391krb5_error_code
392_kdc_find_session_etype(astgs_request_t r,
393 krb5_enctype *etypes, size_t len,
394 const hdb_entry *princ,
395 krb5_enctype *ret_enctype)
396{
397 size_t i;
398
399 if (princ->session_etypes == NULL) {
400 /* The principal must have session etypes available. */
401 return KRB5KDC_ERR_ETYPE_NOSUPP;
402 }
403
404 /* Loop over the client's specified etypes. */
405 for (i = 0; i < len; ++i) {
406 size_t j;
407
408 /* Check that the server also supports the etype. */
409 for (j = 0; j < princ->session_etypes->len; ++j) {
410 if (princ->session_etypes->val[j] == etypes[i]) {
411 *ret_enctype = etypes[i];
412 return 0;
413 }
414 }
415 }
416
417 return KRB5KDC_ERR_ETYPE_NOSUPP;
418}
419
3c1e780e
AB
420krb5_error_code
421_kdc_make_anonymous_principalname (PrincipalName *pn)
954c0172 422{
40b65c84
SM
423 pn->name_type = KRB5_NT_WELLKNOWN;
424 pn->name_string.len = 2;
425 pn->name_string.val = calloc(2, sizeof(*pn->name_string.val));
954c0172 426 if (pn->name_string.val == NULL)
40b65c84
SM
427 goto failed;
428
429 pn->name_string.val[0] = strdup(KRB5_WELLKNOWN_NAME);
430 if (pn->name_string.val[0] == NULL)
431 goto failed;
432
433 pn->name_string.val[1] = strdup(KRB5_ANON_NAME);
434 if (pn->name_string.val[1] == NULL)
435 goto failed;
436
954c0172 437 return 0;
40b65c84
SM
438
439failed:
440 free_PrincipalName(pn);
441
442 pn->name_type = KRB5_NT_UNKNOWN;
443 pn->name_string.len = 0;
444 pn->name_string.val = NULL;
445
446 return ENOMEM;
447}
448
449static void
450_kdc_r_log(astgs_request_t r, int level, const char *fmt, ...)
451 __attribute__ ((__format__ (__printf__, 3, 4)))
452{
453 va_list ap;
454 char *s;
455 va_start(ap, fmt);
456 s = kdc_log_msg_va(r->context, r->config, level, fmt, ap);
457 if(s) free(s);
458 va_end(ap);
954c0172
HIU
459}
460
3c1e780e 461void
40b65c84
SM
462_kdc_set_const_e_text(astgs_request_t r, const char *e_text)
463{
464 /* We should never see this */
465 if (r->e_text) {
466 kdc_log(r->context, r->config, 1,
467 "trying to replace e-text \"%s\" with \"%s\"\n",
468 r->e_text, e_text);
469 return;
470 }
471
472 r->e_text = e_text;
473 kdc_log(r->context, r->config, 4, "%s", e_text);
474}
475
476void
477_kdc_set_e_text(astgs_request_t r, const char *fmt, ...)
478 __attribute__ ((__format__ (__printf__, 2, 3)))
479{
480 va_list ap;
481 char *e_text = NULL;
482 int vasprintf_ret;
483
484 va_start(ap, fmt);
485 vasprintf_ret = vasprintf(&e_text, fmt, ap);
486 va_end(ap);
487
488 if (vasprintf_ret < 0 || !e_text) {
489 /* not much else to do... */
490 kdc_log(r->context, r->config, 1,
491 "Could not set e_text: %s (out of memory)", fmt);
492 return;
493 }
494
495 /* We should never see this */
496 if (r->e_text) {
497 kdc_log(r->context, r->config, 1, "trying to replace e-text: %s\n",
498 e_text);
499 free(e_text);
500 return;
501 }
502
503 r->e_text = e_text;
504 r->e_text_buf = e_text;
505 kdc_log(r->context, r->config, 4, "%s", e_text);
506}
507
508void
509_kdc_log_timestamp(astgs_request_t r, const char *type,
2b29b718 510 KerberosTime authtime, KerberosTime *starttime,
3c1e780e 511 KerberosTime endtime, KerberosTime *renew_till)
954c0172 512{
40b65c84 513 krb5_kdc_configuration *config = r->config;
2b29b718 514 char authtime_str[100], starttime_str[100],
55f5453b 515 endtime_str[100], renewtime_str[100];
2b29b718 516
40b65c84 517 if (authtime)
51569b31 518 kdc_audit_setkv_number((kdc_request_t)r, "auth", authtime);
40b65c84 519 if (starttime && *starttime)
51569b31 520 kdc_audit_setkv_number((kdc_request_t)r, "start", *starttime);
40b65c84 521 if (endtime)
51569b31 522 kdc_audit_setkv_number((kdc_request_t)r, "end", endtime);
40b65c84 523 if (renew_till && *renew_till)
51569b31 524 kdc_audit_setkv_number((kdc_request_t)r, "renew", *renew_till);
40b65c84
SM
525
526 krb5_format_time(r->context, authtime,
2b29b718 527 authtime_str, sizeof(authtime_str), TRUE);
954c0172 528 if (starttime)
40b65c84 529 krb5_format_time(r->context, *starttime,
2b29b718 530 starttime_str, sizeof(starttime_str), TRUE);
954c0172 531 else
c0e8144c 532 strlcpy(starttime_str, "unset", sizeof(starttime_str));
40b65c84 533 krb5_format_time(r->context, endtime,
2b29b718 534 endtime_str, sizeof(endtime_str), TRUE);
954c0172 535 if (renew_till)
40b65c84 536 krb5_format_time(r->context, *renew_till,
2b29b718 537 renewtime_str, sizeof(renewtime_str), TRUE);
954c0172 538 else
c0e8144c 539 strlcpy(renewtime_str, "unset", sizeof(renewtime_str));
2b29b718 540
40b65c84 541 kdc_log(r->context, config, 4,
1f2f4708 542 "%s authtime: %s starttime: %s endtime: %s renew till: %s",
c0e8144c 543 type, authtime_str, starttime_str, endtime_str, renewtime_str);
954c0172
HIU
544}
545
40b65c84
SM
546/*
547 *
548 */
549
550#ifdef PKINIT
551
552static krb5_error_code
51569b31 553pa_pkinit_validate(astgs_request_t r, const PA_DATA *pa)
40b65c84
SM
554{
555 pk_client_params *pkp = NULL;
556 char *client_cert = NULL;
557 krb5_error_code ret;
558
559 ret = _kdc_pk_rd_padata(r, pa, &pkp);
560 if (ret || pkp == NULL) {
81058c60
JS
561 if (ret == HX509_CERT_REVOKED) {
562 ret = KRB5_KDC_ERR_CLIENT_NOT_TRUSTED;
563 } else {
564 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
565 }
40b65c84
SM
566 _kdc_r_log(r, 4, "Failed to decode PKINIT PA-DATA -- %s",
567 r->cname);
40b65c84
SM
568 goto out;
569 }
570
a25f549e
JS
571 /* Validate the freshness token. */
572 ret = _kdc_pk_validate_freshness_token(r, pkp);
573 if (ret) {
574 _kdc_r_log(r, 4, "Failed to validate freshness token");
575 goto out;
576 }
577
40b65c84 578 ret = _kdc_pk_check_client(r, pkp, &client_cert);
51569b31
JS
579 if (client_cert)
580 kdc_audit_addkv((kdc_request_t)r, 0, KDC_REQUEST_KV_PKINIT_CLIENT_CERT,
581 "%s", client_cert);
40b65c84
SM
582 if (ret) {
583 _kdc_set_e_text(r, "PKINIT certificate not allowed to "
584 "impersonate principal");
51569b31
JS
585 kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
586 KDC_AUTH_EVENT_CLIENT_NAME_UNAUTHORIZED);
40b65c84
SM
587 goto out;
588 }
40b65c84
SM
589
590 r->pa_endtime = _kdc_pk_endtime(pkp);
51569b31 591 if (!r->client->flags.synthetic)
40b65c84
SM
592 r->pa_max_life = _kdc_pk_max_life(pkp);
593
594 _kdc_r_log(r, 4, "PKINIT pre-authentication succeeded -- %s using %s",
595 r->cname, client_cert);
596
597 ret = _kdc_pk_mk_pa_reply(r, pkp);
598 if (ret) {
599 _kdc_set_e_text(r, "Failed to build PK-INIT reply");
600 goto out;
601 }
602 ret = _kdc_add_initial_verified_cas(r->context, r->config,
603 pkp, &r->et);
604
51569b31
JS
605 kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
606 KDC_AUTH_EVENT_PREAUTH_SUCCEEDED);
607
a25f549e
JS
608 /*
609 * Match Windows by preferring the authenticator nonce over the one in the
610 * request body.
611 */
612 r->ek.nonce = _kdc_pk_nonce(pkp);
613
40b65c84
SM
614 out:
615 if (pkp)
616 _kdc_pk_free_client_param(r->context, pkp);
51569b31 617 free(client_cert);
40b65c84
SM
618
619 return ret;
620}
621
622#endif /* PKINIT */
623
624static krb5_error_code
51569b31 625pa_gss_validate(astgs_request_t r, const PA_DATA *pa)
40b65c84
SM
626{
627 gss_client_params *gcp = NULL;
628 char *client_name = NULL;
629 krb5_error_code ret;
630 int open = 0;
631
632 ret = _kdc_gss_rd_padata(r, pa, &gcp, &open);
633 if (ret && gcp == NULL)
634 return ret;
635
636 if (open) {
637 ret = _kdc_gss_check_client(r, gcp, &client_name);
51569b31
JS
638 if (client_name)
639 kdc_audit_addkv((kdc_request_t)r, 0, KDC_REQUEST_KV_GSS_INITIATOR,
640 "%s", client_name);
40b65c84
SM
641 if (ret) {
642 _kdc_set_e_text(r, "GSS-API client not allowed to "
643 "impersonate principal");
51569b31
JS
644 kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
645 KDC_AUTH_EVENT_CLIENT_NAME_UNAUTHORIZED);
40b65c84
SM
646 goto out;
647 }
40b65c84
SM
648
649 r->pa_endtime = _kdc_gss_endtime(r, gcp);
650
651 _kdc_r_log(r, 4, "GSS pre-authentication succeeded -- %s using %s",
652 r->cname, client_name);
51569b31
JS
653 kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
654 KDC_AUTH_EVENT_PREAUTH_SUCCEEDED);
40b65c84
SM
655
656 ret = _kdc_gss_mk_composite_name_ad(r, gcp);
657 if (ret) {
658 _kdc_set_e_text(r, "Failed to build GSS authorization data");
659 goto out;
660 }
661 }
662
663 ret = _kdc_gss_mk_pa_reply(r, gcp);
664 if (ret) {
665 if (ret != KRB5_KDC_ERR_MORE_PREAUTH_DATA_REQUIRED)
666 _kdc_set_e_text(r, "Failed to build GSS pre-authentication reply");
40b65c84
SM
667 goto out;
668 }
669
51569b31
JS
670 ret = kdc_request_set_attribute((kdc_request_t)r,
671 HSTR("org.h5l.pa-gss-client-params"), gcp);
672 if (ret)
673 goto out;
40b65c84
SM
674
675out:
51569b31
JS
676 kdc_object_release(gcp);
677 free(client_name);
40b65c84
SM
678
679 return ret;
680}
681
682static krb5_error_code
683pa_gss_finalize_pac(astgs_request_t r)
684{
51569b31
JS
685 gss_client_params *gcp;
686
687 gcp = kdc_request_get_attribute((kdc_request_t)r, HSTR("org.h5l.pa-gss-client-params"));
40b65c84
SM
688
689 heim_assert(gcp != NULL, "invalid GSS-API client params");
690
691 return _kdc_gss_finalize_pac(r, gcp);
692}
693
40b65c84 694static krb5_error_code
75ec66c7
SM
695pa_enc_chal_decrypt_kvno(astgs_request_t r,
696 krb5_enctype aenctype,
697 krb5_data *pepper1client,
698 krb5_data *pepper1kdc,
699 krb5_data *pepper2,
700 krb5_kvno kvno,
701 EncryptedData *enc_data,
702 krb5_keyblock *KDCchallengekey,
703 struct Key **used_key)
40b65c84 704{
75ec66c7 705 unsigned int invalidKeys = 0;
40b65c84 706 krb5_error_code ret;
75ec66c7
SM
707 const Keys *keys = NULL;
708 unsigned int i;
40b65c84 709
75ec66c7
SM
710 if (KDCchallengekey)
711 krb5_keyblock_zero(KDCchallengekey);
712 if (used_key)
713 *used_key = NULL;
40b65c84 714
75ec66c7
SM
715 keys = hdb_kvno2keys(r->context, r->client, kvno);
716 if (keys == NULL) {
717 return KRB5KDC_ERR_ETYPE_NOSUPP;
40b65c84
SM
718 }
719
75ec66c7
SM
720 for (i = 0; i < keys->len; i++) {
721 struct Key *k = &keys->val[i];
40b65c84 722 krb5_crypto challengecrypto, longtermcrypto;
75ec66c7 723 krb5_keyblock client_challengekey;
40b65c84 724
40b65c84
SM
725 ret = krb5_crypto_init(r->context, &k->key, 0, &longtermcrypto);
726 if (ret)
727 continue;
75ec66c7 728
40b65c84 729 ret = krb5_crypto_fx_cf2(r->context, r->armor_crypto, longtermcrypto,
75ec66c7
SM
730 pepper1client, pepper2, aenctype,
731 &client_challengekey);
40b65c84
SM
732 if (ret) {
733 krb5_crypto_destroy(r->context, longtermcrypto);
734 continue;
735 }
75ec66c7
SM
736
737 ret = krb5_crypto_init(r->context, &client_challengekey, 0,
40b65c84 738 &challengecrypto);
75ec66c7 739 krb5_free_keyblock_contents(r->context, &client_challengekey);
40b65c84
SM
740 if (ret) {
741 krb5_crypto_destroy(r->context, longtermcrypto);
742 continue;
743 }
744
745 ret = _krb5_validate_pa_enc_challenge(r->context,
746 challengecrypto,
747 KRB5_KU_ENC_CHALLENGE_CLIENT,
75ec66c7 748 enc_data,
40b65c84
SM
749 r->cname);
750 krb5_crypto_destroy(r->context, challengecrypto);
751 if (ret) {
752 const char *msg;
753 krb5_error_code ret2;
754 char *str = NULL;
755
756 krb5_crypto_destroy(r->context, longtermcrypto);
757
75ec66c7
SM
758 if (ret != KRB5KRB_AP_ERR_BAD_INTEGRITY)
759 return ret;
760
761 invalidKeys += 1;
762
763 if (pepper1kdc == NULL)
764 /* The caller is not interessted in details */
765 continue;
40b65c84
SM
766
767 ret2 = krb5_enctype_to_string(r->context, k->key.keytype, &str);
768 if (ret2)
769 str = NULL;
770 msg = krb5_get_error_message(r->context, ret);
771 _kdc_r_log(r, 2, "Failed to decrypt ENC-CHAL -- %s "
772 "(enctype %s) error %s",
773 r->cname, str ? str : "unknown enctype", msg);
774 krb5_free_error_message(r->context, msg);
775 free(str);
776
777 continue;
778 }
40b65c84 779
75ec66c7
SM
780 if (pepper1kdc == NULL) {
781 /* The caller is not interessted in details */
782 return 0;
40b65c84
SM
783 }
784
75ec66c7
SM
785 heim_assert(KDCchallengekey != NULL,
786 "KDCchallengekey pointer required with pepper1kdc");
787 heim_assert(used_key != NULL,
788 "used_key pointer required with pepper1kdc");
40b65c84
SM
789
790 /*
791 * Provide KDC authentication to the client, uses a different
792 * challenge key (different pepper).
793 */
794
40b65c84 795 ret = krb5_crypto_fx_cf2(r->context, r->armor_crypto, longtermcrypto,
75ec66c7
SM
796 pepper1kdc, pepper2, aenctype,
797 KDCchallengekey);
40b65c84
SM
798 krb5_crypto_destroy(r->context, longtermcrypto);
799 if (ret)
75ec66c7
SM
800 return ret;
801
802 *used_key = k;
803 return 0;
804 }
805
806 if (invalidKeys == 0)
807 return KRB5KDC_ERR_ETYPE_NOSUPP;
808
809 return KRB5KDC_ERR_PREAUTH_FAILED;
810}
811
812static krb5_error_code
813pa_enc_chal_validate(astgs_request_t r, const PA_DATA *pa)
814{
815 krb5_kvno kvno = r->client->kvno;
816 krb5_data pepper1client, pepper1kdc, pepper2;
817 EncryptedData enc_data;
818 krb5_enctype aenctype;
819 krb5_error_code ret;
820 krb5_keyblock KDCchallengekey;
821 struct Key *k = NULL;
822 size_t size;
823
824 heim_assert(r->armor_crypto != NULL, "ENC-CHAL called for non FAST");
825
826 if (_kdc_is_anon_request(&r->req)) {
827 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
828 kdc_log(r->context, r->config, 4, "ENC-CHAL doesn't support anon");
829 return ret;
830 }
831
832 if (r->client->flags.locked_out) {
833 ret = KRB5KDC_ERR_CLIENT_REVOKED;
834 kdc_log(r->context, r->config, 0,
835 "Client (%s) is locked out", r->cname);
836 kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
837 KDC_AUTH_EVENT_CLIENT_LOCKED_OUT);
838 return ret;
839 }
840
841 ret = decode_EncryptedData(pa->padata_value.data,
842 pa->padata_value.length,
843 &enc_data,
844 &size);
845 if (ret) {
846 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
847 _kdc_r_log(r, 4, "Failed to decode PA-DATA -- %s",
848 r->cname);
849 return ret;
850 }
851
852 pepper1client.data = "clientchallengearmor";
853 pepper1client.length = strlen(pepper1client.data);
854 pepper1kdc.data = "kdcchallengearmor";
855 pepper1kdc.length = strlen(pepper1kdc.data);
856 pepper2.data = "challengelongterm";
857 pepper2.length = strlen(pepper2.data);
858
859 krb5_crypto_getenctype(r->context, r->armor_crypto, &aenctype);
860
861 kdc_log(r->context, r->config, 5, "FAST armor enctype is: %d", (int)aenctype);
862
863 ret = pa_enc_chal_decrypt_kvno(r, aenctype,
864 &pepper1client,
865 &pepper1kdc,
866 &pepper2,
867 kvno,
868 &enc_data,
869 &KDCchallengekey,
870 &k);
871 if (ret == KRB5KDC_ERR_ETYPE_NOSUPP) {
872 char *estr;
873 _kdc_set_e_text(r, "No key matching entype");
874 if(krb5_enctype_to_string(r->context, enc_data.etype, &estr))
875 estr = NULL;
876 if(estr == NULL)
877 _kdc_r_log(r, 4,
878 "No client key matching ENC-CHAL (%d) -- %s",
879 enc_data.etype, r->cname);
880 else
881 _kdc_r_log(r, 4,
882 "No client key matching ENC-CHAL (%s) -- %s",
883 estr, r->cname);
884 free(estr);
885 free_EncryptedData(&enc_data);
886 kdc_audit_setkv_number((kdc_request_t)r,
887 KDC_REQUEST_KV_PA_FAILED_KVNO,
888 kvno);
889 return ret;
890 }
891 if (ret == KRB5KRB_AP_ERR_SKEW) {
892 /*
893 * Logging happens inside of
894 * _krb5_validate_pa_enc_challenge()
895 * via pa_enc_chal_decrypt_kvno()
896 */
897
898 free_EncryptedData(&enc_data);
899 kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
900 KDC_AUTH_EVENT_CLIENT_TIME_SKEW);
901
902 /*
903 * The following is needed to make windows clients to
904 * retry using the timestamp in the error message, if
905 * there is a e_text, they become unhappy.
906 */
907 r->e_text = NULL;
908 return ret;
909 }
910 if (ret == KRB5KDC_ERR_PREAUTH_FAILED) {
911 krb5_error_code hret = ret;
912 int hi;
913
914 /*
915 * Logging happens inside of
916 * via pa_enc_chal_decrypt_kvno()
917 */
918
919 kdc_audit_setkv_number((kdc_request_t)r,
920 KDC_REQUEST_KV_PA_FAILED_KVNO,
921 kvno);
922
923 /*
924 * Check if old and older keys are
925 * able to decrypt.
926 */
927 for (hi = 1; hi < 3; hi++) {
928 krb5_kvno hkvno;
929
930 if (hi >= kvno) {
931 break;
932 }
933
934 hkvno = kvno - hi;
935 hret = pa_enc_chal_decrypt_kvno(r, aenctype,
936 &pepper1client,
937 NULL, /* pepper1kdc */
938 &pepper2,
939 hkvno,
940 &enc_data,
941 NULL, /* KDCchallengekey */
942 NULL); /* used_key */
943 if (hret == 0) {
944 kdc_audit_setkv_number((kdc_request_t)r,
945 KDC_REQUEST_KV_PA_HISTORIC_KVNO,
946 hkvno);
947 break;
948 }
949 if (hret == KRB5KDC_ERR_ETYPE_NOSUPP) {
950 break;
951 }
952 }
40b65c84 953
75ec66c7
SM
954 free_EncryptedData(&enc_data);
955
956 if (hret == 0)
957 kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
958 KDC_AUTH_EVENT_HISTORIC_LONG_TERM_KEY);
959 else
960 kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
961 KDC_AUTH_EVENT_WRONG_LONG_TERM_KEY);
962
963 return ret;
964 }
965 free_EncryptedData(&enc_data);
966 if (ret == 0) {
967 krb5_crypto challengecrypto;
968 char *estr = NULL;
969 char *astr = NULL;
970 char *kstr = NULL;
971
972 ret = krb5_crypto_init(r->context, &KDCchallengekey, 0, &challengecrypto);
973 krb5_free_keyblock_contents(r->context, &KDCchallengekey);
40b65c84 974 if (ret)
75ec66c7 975 return ret;
40b65c84
SM
976
977 ret = _krb5_make_pa_enc_challenge(r->context, challengecrypto,
978 KRB5_KU_ENC_CHALLENGE_KDC,
979 r->rep.padata);
980 krb5_crypto_destroy(r->context, challengecrypto);
981 if (ret)
75ec66c7
SM
982 return ret;
983
984 ret = set_salt_padata(r->context, r->config, r->rep.padata, k);
985 if (ret)
986 return ret;
40b65c84
SM
987
988 /*
75ec66c7 989 * Found a key that the client used, lets pick that as the reply key
40b65c84 990 */
75ec66c7
SM
991
992 krb5_free_keyblock_contents(r->context, &r->reply_key);
993 ret = krb5_copy_keyblock_contents(r->context, &k->key, &r->reply_key);
994 if (ret)
995 return ret;
996
997 if (krb5_enctype_to_string(r->context, (int)aenctype, &astr))
998 astr = NULL;
999 if (krb5_enctype_to_string(r->context, enc_data.etype, &estr))
1000 estr = NULL;
1001 if (krb5_enctype_to_string(r->context, k->key.keytype, &kstr))
1002 kstr = NULL;
1003 _kdc_r_log(r, 4, "ENC-CHAL Pre-authentication succeeded -- %s "
1004 "using armor=%s enc=%s key=%s",
1005 r->cname,
1006 astr ? astr : "unknown enctype",
1007 estr ? estr : "unknown enctype",
1008 kstr ? kstr : "unknown enctype");
51569b31
JS
1009 kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
1010 KDC_AUTH_EVENT_VALIDATED_LONG_TERM_KEY);
75ec66c7
SM
1011 kdc_audit_setkv_number((kdc_request_t)r,
1012 KDC_REQUEST_KV_PA_SUCCEEDED_KVNO,
1013 kvno);
1014 return 0;
40b65c84
SM
1015 }
1016
75ec66c7
SM
1017 return ret;
1018}
1019
1020static krb5_error_code
1021pa_enc_ts_decrypt_kvno(astgs_request_t r,
1022 krb5_kvno kvno,
1023 const EncryptedData *enc_data,
1024 krb5_data *ts_data,
1025 Key **_pa_key)
1026{
1027 krb5_error_code ret;
1028 krb5_crypto crypto;
1029 Key *pa_key = NULL;
1030 const Keys *keys = NULL;
1031
1032 if (_pa_key)
1033 *_pa_key = NULL;
1034
1035 krb5_data_zero(ts_data);
1036
1037 keys = hdb_kvno2keys(r->context, r->client, kvno);
1038 if (keys == NULL) {
1039 return KRB5KDC_ERR_ETYPE_NOSUPP;
1040 }
1041 ret = hdb_enctype2key(r->context, r->client, keys,
1042 enc_data->etype, &pa_key);
1043 if(ret){
1044 return KRB5KDC_ERR_ETYPE_NOSUPP;
40b65c84 1045 }
40b65c84 1046
75ec66c7
SM
1047 try_next_key:
1048 ret = krb5_crypto_init(r->context, &pa_key->key, 0, &crypto);
1049 if (ret) {
1050 const char *msg = krb5_get_error_message(r->context, ret);
1051 _kdc_r_log(r, 4, "krb5_crypto_init failed: %s", msg);
1052 krb5_free_error_message(r->context, msg);
1053 return ret;
1054 }
1055
1056 ret = krb5_decrypt_EncryptedData(r->context,
1057 crypto,
1058 KRB5_KU_PA_ENC_TIMESTAMP,
1059 enc_data,
1060 ts_data);
1061 krb5_crypto_destroy(r->context, crypto);
1062 /*
1063 * Since the user might have several keys with the same
f1a83798 1064 * enctype but with different salting, we need to try all
75ec66c7
SM
1065 * the keys with the same enctype.
1066 */
1067 if (ret) {
1068 ret = hdb_next_enctype2key(r->context, r->client, keys,
1069 enc_data->etype, &pa_key);
1070 if (ret == 0)
1071 goto try_next_key;
1072
1073 return KRB5KDC_ERR_PREAUTH_FAILED;
1074 }
1075
1076 if (_pa_key)
1077 *_pa_key = pa_key;
1078 return 0;
40b65c84
SM
1079}
1080
1081static krb5_error_code
51569b31 1082pa_enc_ts_validate(astgs_request_t r, const PA_DATA *pa)
40b65c84 1083{
75ec66c7 1084 krb5_kvno kvno = r->client->kvno;
40b65c84
SM
1085 EncryptedData enc_data;
1086 krb5_error_code ret;
40b65c84
SM
1087 krb5_data ts_data;
1088 PA_ENC_TS_ENC p;
1089 size_t len;
1090 Key *pa_key;
c33f6b2c 1091 char *str;
255e3e18 1092
40b65c84
SM
1093 if (r->armor_crypto && !r->config->enable_armored_pa_enc_timestamp) {
1094 ret = KRB5KDC_ERR_POLICY;
1095 kdc_log(r->context, r->config, 0,
1096 "Armored encrypted timestamp pre-authentication is disabled");
1097 return ret;
1098 } else if (!r->armor_crypto && !r->config->enable_unarmored_pa_enc_timestamp) {
1099 ret = KRB5KDC_ERR_POLICY;
1100 kdc_log(r->context, r->config, 0,
1101 "Unarmored encrypted timestamp pre-authentication is disabled");
1102 return ret;
1103 }
1104
51569b31 1105 if (r->client->flags.locked_out) {
40b65c84
SM
1106 ret = KRB5KDC_ERR_CLIENT_REVOKED;
1107 kdc_log(r->context, r->config, 0,
1108 "Client (%s) is locked out", r->cname);
51569b31
JS
1109 kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
1110 KDC_AUTH_EVENT_CLIENT_LOCKED_OUT);
40b65c84
SM
1111 return ret;
1112 }
1113
1114 ret = decode_EncryptedData(pa->padata_value.data,
1115 pa->padata_value.length,
1116 &enc_data,
1117 &len);
1118 if (ret) {
1119 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1120 _kdc_r_log(r, 4, "Failed to decode PA-DATA -- %s",
1121 r->cname);
1122 goto out;
1123 }
1124
75ec66c7
SM
1125 ret = pa_enc_ts_decrypt_kvno(r, kvno, &enc_data, &ts_data, &pa_key);
1126 if (ret == KRB5KDC_ERR_ETYPE_NOSUPP) {
40b65c84 1127 char *estr;
b12a33e2 1128 _kdc_set_e_text(r, "No key matching enctype");
40b65c84
SM
1129 if(krb5_enctype_to_string(r->context, enc_data.etype, &estr))
1130 estr = NULL;
1131 if(estr == NULL)
1132 _kdc_r_log(r, 4,
1133 "No client key matching pa-data (%d) -- %s",
1134 enc_data.etype, r->cname);
1135 else
1136 _kdc_r_log(r, 4,
1137 "No client key matching pa-data (%s) -- %s",
1138 estr, r->cname);
1139 free(estr);
1140 free_EncryptedData(&enc_data);
75ec66c7
SM
1141 kdc_audit_setkv_number((kdc_request_t)r,
1142 KDC_REQUEST_KV_PA_FAILED_KVNO,
1143 kvno);
40b65c84
SM
1144 goto out;
1145 }
75ec66c7 1146 if (ret == KRB5KDC_ERR_PREAUTH_FAILED) {
40b65c84
SM
1147 krb5_error_code ret2;
1148 const char *msg = krb5_get_error_message(r->context, ret);
75ec66c7
SM
1149 krb5_error_code hret = ret;
1150 int hi;
1151
1152 kdc_audit_setkv_number((kdc_request_t)r,
1153 KDC_REQUEST_KV_PA_FAILED_KVNO,
1154 kvno);
40b65c84 1155
75ec66c7
SM
1156 /*
1157 * Check if old and older keys are
1158 * able to decrypt.
1159 */
1160 for (hi = 1; hi < 3; hi++) {
1161 krb5_kvno hkvno;
1162
1163 if (hi >= kvno) {
1164 break;
1165 }
1166
1167 hkvno = kvno - hi;
1168 hret = pa_enc_ts_decrypt_kvno(r, hkvno,
1169 &enc_data,
1170 &ts_data,
1171 NULL); /* pa_key */
1172 if (hret == 0) {
1173 krb5_data_free(&ts_data);
1174 kdc_audit_setkv_number((kdc_request_t)r,
1175 KDC_REQUEST_KV_PA_HISTORIC_KVNO,
1176 hkvno);
1177 break;
1178 }
1179 if (hret == KRB5KDC_ERR_ETYPE_NOSUPP) {
1180 break;
1181 }
1182 }
1183
1184 ret2 = krb5_enctype_to_string(r->context, enc_data.etype, &str);
40b65c84
SM
1185 if (ret2)
1186 str = NULL;
1187 _kdc_r_log(r, 2, "Failed to decrypt PA-DATA -- %s "
1188 "(enctype %s) error %s",
1189 r->cname, str ? str : "unknown enctype", msg);
51569b31 1190 krb5_xfree(str);
40b65c84 1191 krb5_free_error_message(r->context, msg);
51569b31 1192 kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_PA_ETYPE,
75ec66c7
SM
1193 enc_data.etype);
1194 if (hret == 0)
1195 kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
1196 KDC_AUTH_EVENT_HISTORIC_LONG_TERM_KEY);
1197 else
1198 kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
1199 KDC_AUTH_EVENT_WRONG_LONG_TERM_KEY);
40b65c84
SM
1200
1201 free_EncryptedData(&enc_data);
1202
1203 ret = KRB5KDC_ERR_PREAUTH_FAILED;
1204 goto out;
1205 }
1206 free_EncryptedData(&enc_data);
40b65c84
SM
1207 ret = decode_PA_ENC_TS_ENC(ts_data.data,
1208 ts_data.length,
1209 &p,
1210 &len);
1211 krb5_data_free(&ts_data);
1212 if(ret){
1213 ret = KRB5KDC_ERR_PREAUTH_FAILED;
b12a33e2 1214 _kdc_r_log(r, 4, "Failed to decode PA-ENC-TS-ENC -- %s",
40b65c84
SM
1215 r->cname);
1216 goto out;
1217 }
1218 if (labs(kdc_time - p.patimestamp) > r->context->max_skew) {
1219 char client_time[100];
1220
1221 krb5_format_time(r->context, p.patimestamp,
1222 client_time, sizeof(client_time), TRUE);
1223
1224 ret = KRB5KRB_AP_ERR_SKEW;
1225 _kdc_r_log(r, 4, "Too large time skew, "
1226 "client time %s is out by %u > %u seconds -- %s",
1227 client_time,
1228 (unsigned)labs(kdc_time - p.patimestamp),
1229 r->context->max_skew,
1230 r->cname);
51569b31
JS
1231 kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
1232 KDC_AUTH_EVENT_CLIENT_TIME_SKEW);
40b65c84
SM
1233
1234 /*
1235 * The following is needed to make windows clients to
1236 * retry using the timestamp in the error message, if
1237 * there is a e_text, they become unhappy.
1238 */
1239 r->e_text = NULL;
1240 free_PA_ENC_TS_ENC(&p);
1241 goto out;
1242 }
1243 free_PA_ENC_TS_ENC(&p);
1244
75ec66c7 1245 ret = set_salt_padata(r->context, r->config, r->rep.padata, pa_key);
51569b31
JS
1246 if (ret == 0)
1247 ret = krb5_copy_keyblock_contents(r->context, &pa_key->key, &r->reply_key);
40b65c84
SM
1248 if (ret)
1249 return ret;
1250
1251 ret = krb5_enctype_to_string(r->context, pa_key->key.keytype, &str);
1252 if (ret)
1253 str = NULL;
1254 _kdc_r_log(r, 4, "ENC-TS Pre-authentication succeeded -- %s using %s",
1255 r->cname, str ? str : "unknown enctype");
51569b31
JS
1256 krb5_xfree(str);
1257 kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_PA_ETYPE,
1258 pa_key->key.keytype);
1259 kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
1260 KDC_AUTH_EVENT_VALIDATED_LONG_TERM_KEY);
75ec66c7
SM
1261 kdc_audit_setkv_number((kdc_request_t)r,
1262 KDC_REQUEST_KV_PA_SUCCEEDED_KVNO,
1263 kvno);
40b65c84
SM
1264
1265 ret = 0;
1266
1267 out:
1268
1269 return ret;
1270}
1271
a25f549e
JS
1272#ifdef PKINIT
1273
1274static krb5_error_code
1275make_freshness_token(astgs_request_t r, const Key *krbtgt_key, unsigned krbtgt_kvno)
1276{
1277 krb5_error_code ret = 0;
1278 const struct timeval current_kdc_time = krb5_kdc_get_time();
1279 int usec = current_kdc_time.tv_usec;
1280 const PA_ENC_TS_ENC ts_enc = {
1281 .patimestamp = current_kdc_time.tv_sec,
1282 .pausec = &usec,
1283 };
1284 unsigned char *encoded_ts_enc = NULL;
1285 size_t ts_enc_size;
1286 size_t ts_enc_len = 0;
1287 EncryptedData encdata;
1288 krb5_crypto crypto;
1289 unsigned char *token = NULL;
1290 size_t token_size;
1291 size_t token_len = 0;
1292 size_t token_alloc_size;
1293
1294 ASN1_MALLOC_ENCODE(PA_ENC_TS_ENC,
1295 encoded_ts_enc,
1296 ts_enc_size,
1297 &ts_enc,
1298 &ts_enc_len,
1299 ret);
1300 if (ret)
1301 return ret;
1302 if (ts_enc_size != ts_enc_len)
1303 krb5_abortx(r->context, "internal error in ASN.1 encoder");
1304
1305 ret = krb5_crypto_init(r->context, &krbtgt_key->key, 0, &crypto);
1306 if (ret) {
1307 free(encoded_ts_enc);
1308 return ret;
1309 }
1310
1311 ret = krb5_encrypt_EncryptedData(r->context,
1312 crypto,
1313 KRB5_KU_AS_FRESHNESS,
1314 encoded_ts_enc,
1315 ts_enc_len,
1316 krbtgt_kvno,
1317 &encdata);
1318 free(encoded_ts_enc);
1319 krb5_crypto_destroy(r->context, crypto);
1320 if (ret)
1321 return ret;
1322
1323 token_size = length_EncryptedData(&encdata);
1324 token_alloc_size = token_size + 2; /* Account for the two leading zero bytes. */
1325 token = calloc(1, token_alloc_size);
1326 if (token == NULL) {
1327 free_EncryptedData(&encdata);
1328 return ENOMEM;
1329 }
1330
1331 ret = encode_EncryptedData(token + token_alloc_size - 1,
1332 token_size,
1333 &encdata,
1334 &token_len);
1335 free_EncryptedData(&encdata);
1336 if (ret) {
1337 free(token);
1338 return ret;
1339 }
1340 if (token_size != token_len)
1341 krb5_abortx(r->context, "internal error in ASN.1 encoder");
1342
1343 ret = krb5_padata_add(r->context,
1344 r->rep.padata,
1345 KRB5_PADATA_AS_FRESHNESS,
1346 token,
1347 token_alloc_size);
1348 if (ret)
1349 free(token);
1350 return ret;
1351}
1352
1353#endif /* PKINIT */
1354
1355static krb5_error_code
1356send_freshness_token(astgs_request_t r, const Key *krbtgt_key, unsigned krbtgt_kvno)
1357{
1358 krb5_error_code ret = 0;
1359#ifdef PKINIT
1360 int idx = 0;
1361 const PA_DATA *freshness_padata = NULL;
1362
1363 freshness_padata = _kdc_find_padata(&r->req,
1364 &idx,
1365 KRB5_PADATA_AS_FRESHNESS);
1366 if (freshness_padata == NULL) {
1367 return 0;
1368 }
1369
1370 ret = make_freshness_token(r, krbtgt_key, krbtgt_kvno);
1371#endif /* PKINIT */
1372 return ret;
1373}
1374
40b65c84
SM
1375struct kdc_patypes {
1376 int type;
95c02a97 1377 const char *name;
40b65c84
SM
1378 unsigned int flags;
1379#define PA_ANNOUNCE 1
1380#define PA_REQ_FAST 2 /* only use inside fast */
1381#define PA_SYNTHETIC_OK 4
1382#define PA_REPLACE_REPLY_KEY 8 /* PA mech replaces reply key */
1383#define PA_USES_LONG_TERM_KEY 16 /* PA mech uses client's long-term key */
fc474042 1384#define PA_USES_FAST_COOKIE 32 /* Multi-step PA mech maintains state in PA-FX-COOKIE */
09bcd48f 1385#define PA_HARDWARE_AUTH 64 /* PA mech uses hardware authentication */
51569b31 1386 krb5_error_code (*validate)(astgs_request_t, const PA_DATA *pa);
40b65c84
SM
1387 krb5_error_code (*finalize_pac)(astgs_request_t r);
1388 void (*cleanup)(astgs_request_t r);
1389};
1390
1391static const struct kdc_patypes pat[] = {
1392#ifdef PKINIT
1393 {
1394 KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)",
09bcd48f 1395 PA_ANNOUNCE | PA_SYNTHETIC_OK | PA_REPLACE_REPLY_KEY | PA_HARDWARE_AUTH,
40b65c84
SM
1396 pa_pkinit_validate, NULL, NULL
1397 },
1398 {
09bcd48f 1399 KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", PA_ANNOUNCE | PA_REPLACE_REPLY_KEY | PA_HARDWARE_AUTH,
40b65c84
SM
1400 pa_pkinit_validate, NULL, NULL
1401 },
1402 {
1403 KRB5_PADATA_PKINIT_KX, "Anonymous PK-INIT", PA_ANNOUNCE,
1404 NULL, NULL, NULL
1405 },
1406#else
1407 { KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)", 0, NULL , NULL, NULL },
1408 { KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", 0, NULL, NULL, NULL },
1409 { KRB5_PADATA_PKINIT_KX, "Anonymous PK-INIT", 0, NULL, NULL, NULL },
1410#endif
1411 { KRB5_PADATA_PA_PK_OCSP_RESPONSE , "OCSP", 0, NULL, NULL, NULL },
1412 {
1413 KRB5_PADATA_ENC_TIMESTAMP , "ENC-TS",
1414 PA_ANNOUNCE | PA_USES_LONG_TERM_KEY,
1415 pa_enc_ts_validate, NULL, NULL
1416 },
1417 {
1418 KRB5_PADATA_ENCRYPTED_CHALLENGE , "ENC-CHAL",
1419 PA_ANNOUNCE | PA_USES_LONG_TERM_KEY | PA_REQ_FAST,
1420 pa_enc_chal_validate, NULL, NULL
1421 },
1422 { KRB5_PADATA_REQ_ENC_PA_REP , "REQ-ENC-PA-REP", 0, NULL, NULL, NULL },
1423 { KRB5_PADATA_FX_FAST, "FX-FAST", PA_ANNOUNCE, NULL, NULL, NULL },
1424 { KRB5_PADATA_FX_ERROR, "FX-ERROR", 0, NULL, NULL, NULL },
1425 { KRB5_PADATA_FX_COOKIE, "FX-COOKIE", 0, NULL, NULL, NULL },
1426 {
1427 KRB5_PADATA_GSS , "GSS",
fc474042 1428 PA_ANNOUNCE | PA_SYNTHETIC_OK | PA_REPLACE_REPLY_KEY | PA_USES_FAST_COOKIE,
51569b31 1429 pa_gss_validate, pa_gss_finalize_pac, NULL
40b65c84
SM
1430 },
1431};
1432
1433static void
1434log_patypes(astgs_request_t r, METHOD_DATA *padata)
1435{
1436 krb5_kdc_configuration *config = r->config;
1437 struct rk_strpool *p = NULL;
1438 char *str;
1439 size_t n, m;
1440
1441 for (n = 0; n < padata->len; n++) {
1442 for (m = 0; m < sizeof(pat) / sizeof(pat[0]); m++) {
1443 if (padata->val[n].padata_type == pat[m].type) {
1444 p = rk_strpoolprintf(p, "%s", pat[m].name);
1445 break;
1446 }
c33f6b2c 1447 }
40b65c84
SM
1448 if (m == sizeof(pat) / sizeof(pat[0]))
1449 p = rk_strpoolprintf(p, "%d", padata->val[n].padata_type);
1450 if (p && n + 1 < padata->len)
c33f6b2c
AB
1451 p = rk_strpoolprintf(p, ", ");
1452 if (p == NULL) {
40b65c84 1453 kdc_log(r->context, config, 1, "out of memory");
c33f6b2c
AB
1454 return;
1455 }
1456 }
835926c8
AB
1457 if (p == NULL)
1458 p = rk_strpoolprintf(p, "none");
255e3e18 1459
c33f6b2c 1460 str = rk_strpoolcollect(p);
40b65c84 1461 kdc_log(r->context, config, 4, "Client sent patypes: %s", str);
51569b31
JS
1462 kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE,
1463 "client-pa", "%s", str);
c33f6b2c
AB
1464 free(str);
1465}
1466
40b65c84
SM
1467static krb5_boolean
1468pa_used_flag_isset(astgs_request_t r, unsigned int flag)
1469{
1470 if (r->pa_used == NULL)
1471 return FALSE;
1472
1473 return (r->pa_used->flags & flag) == flag;
1474}
1475
c33f6b2c
AB
1476/*
1477 *
1478 */
1479
3c1e780e
AB
1480krb5_error_code
1481_kdc_encode_reply(krb5_context context,
1482 krb5_kdc_configuration *config,
40b65c84 1483 astgs_request_t r, uint32_t nonce,
2b29b718 1484 krb5_enctype etype,
3c1e780e 1485 int skvno, const EncryptionKey *skey,
40b65c84 1486 int ckvno,
4f8ba5ad 1487 int rk_is_subkey,
3c1e780e 1488 krb5_data *reply)
954c0172
HIU
1489{
1490 unsigned char *buf;
1491 size_t buf_size;
255e3e18 1492 size_t len = 0;
954c0172
HIU
1493 krb5_error_code ret;
1494 krb5_crypto crypto;
40b65c84
SM
1495 KDC_REP *rep = &r->rep;
1496 EncTicketPart *et = &r->et;
1497 EncKDCRepPart *ek = &r->ek;
1498
1499 heim_assert(rep->padata != NULL, "reply padata uninitialized");
954c0172
HIU
1500
1501 ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret);
1502 if(ret) {
4f8ba5ad 1503 const char *msg = krb5_get_error_message(context, ret);
40b65c84 1504 kdc_log(context, config, 4, "Failed to encode ticket: %s", msg);
4f8ba5ad 1505 krb5_free_error_message(context, msg);
954c0172
HIU
1506 return ret;
1507 }
40b65c84
SM
1508 if(buf_size != len)
1509 krb5_abortx(context, "Internal error in ASN.1 encoder");
954c0172
HIU
1510
1511 ret = krb5_crypto_init(context, skey, etype, &crypto);
1512 if (ret) {
40b65c84
SM
1513 const char *msg = krb5_get_error_message(context, ret);
1514 kdc_log(context, config, 4, "krb5_crypto_init failed: %s", msg);
4f8ba5ad 1515 krb5_free_error_message(context, msg);
40b65c84 1516 free(buf);
954c0172
HIU
1517 return ret;
1518 }
1519
2b29b718 1520 ret = krb5_encrypt_EncryptedData(context,
954c0172
HIU
1521 crypto,
1522 KRB5_KU_TICKET,
1523 buf,
1524 len,
1525 skvno,
1526 &rep->ticket.enc_part);
1527 free(buf);
1528 krb5_crypto_destroy(context, crypto);
1529 if(ret) {
4f8ba5ad 1530 const char *msg = krb5_get_error_message(context, ret);
40b65c84 1531 kdc_log(context, config, 4, "Failed to encrypt data: %s", msg);
4f8ba5ad 1532 krb5_free_error_message(context, msg);
954c0172
HIU
1533 return ret;
1534 }
2b29b718 1535
40b65c84
SM
1536 if (r && r->armor_crypto) {
1537 KrbFastFinished finished;
1538 krb5_data data;
1539
1540 kdc_log(context, config, 4, "FAST armor protection");
1541
1542 memset(&finished, 0, sizeof(finished));
1543 krb5_data_zero(&data);
1544
1545 finished.timestamp = kdc_time;
1546 finished.usec = 0;
1547 finished.crealm = et->crealm;
1548 finished.cname = et->cname;
1549
1550 ASN1_MALLOC_ENCODE(Ticket, data.data, data.length,
1551 &rep->ticket, &len, ret);
1552 if (ret)
1553 return ret;
1554 if (data.length != len)
1555 krb5_abortx(context, "internal asn.1 error");
1556
1557 ret = krb5_create_checksum(context, r->armor_crypto,
1558 KRB5_KU_FAST_FINISHED, 0,
1559 data.data, data.length,
1560 &finished.ticket_checksum);
1561 krb5_data_free(&data);
1562 if (ret)
1563 return ret;
1564
1565 ret = _kdc_fast_mk_response(context, r->armor_crypto,
1566 rep->padata, &r->strengthen_key, &finished,
1567 nonce, &data);
1568 free_Checksum(&finished.ticket_checksum);
1569 if (ret)
1570 return ret;
1571
1572 free_METHOD_DATA(r->rep.padata);
1573
1574 ret = krb5_padata_add(context, rep->padata,
1575 KRB5_PADATA_FX_FAST,
1576 data.data, data.length);
1577 if (ret)
1578 return ret;
1579
1580 /*
1581 * Hide client name for privacy reasons
1582 */
1583 if (r->fast.flags.requested_hidden_names) {
1584 Realm anon_realm = KRB5_ANON_REALM;
1585
1586 free_Realm(&rep->crealm);
1587 ret = copy_Realm(&anon_realm, &rep->crealm);
1588 if (ret == 0) {
1589 free_PrincipalName(&rep->cname);
1590 ret = _kdc_make_anonymous_principalname(&rep->cname);
1591 }
1592 if (ret)
1593 return ret;
1594 }
1595 }
1596
1597 if (rep->padata->len == 0) {
1598 free_METHOD_DATA(rep->padata);
1599 free(rep->padata);
1600 rep->padata = NULL;
1601 }
1602
954c0172
HIU
1603 if(rep->msg_type == krb_as_rep && !config->encode_as_rep_as_tgs_rep)
1604 ASN1_MALLOC_ENCODE(EncASRepPart, buf, buf_size, ek, &len, ret);
1605 else
1606 ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret);
1607 if(ret) {
4f8ba5ad 1608 const char *msg = krb5_get_error_message(context, ret);
40b65c84 1609 kdc_log(context, config, 4, "Failed to encode KDC-REP: %s", msg);
4f8ba5ad 1610 krb5_free_error_message(context, msg);
954c0172
HIU
1611 return ret;
1612 }
1613 if(buf_size != len) {
1614 free(buf);
40b65c84
SM
1615 kdc_log(context, config, 4, "Internal error in ASN.1 encoder");
1616 _kdc_set_e_text(r, "KDC internal error");
954c0172
HIU
1617 return KRB5KRB_ERR_GENERIC;
1618 }
40b65c84 1619 ret = krb5_crypto_init(context, &r->reply_key, 0, &crypto);
954c0172 1620 if (ret) {
4f8ba5ad 1621 const char *msg = krb5_get_error_message(context, ret);
954c0172 1622 free(buf);
40b65c84 1623 kdc_log(context, config, 4, "krb5_crypto_init failed: %s", msg);
4f8ba5ad 1624 krb5_free_error_message(context, msg);
954c0172
HIU
1625 return ret;
1626 }
1627 if(rep->msg_type == krb_as_rep) {
51569b31
JS
1628 ret = krb5_encrypt_EncryptedData(context,
1629 crypto,
1630 KRB5_KU_AS_REP_ENC_PART,
1631 buf,
1632 len,
1633 ckvno,
1634 &rep->enc_part);
1635 free(buf);
1636 if (ret == 0)
1637 ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret);
954c0172 1638 } else {
51569b31
JS
1639 ret = krb5_encrypt_EncryptedData(context,
1640 crypto,
1641 rk_is_subkey ?
1642 KRB5_KU_TGS_REP_ENC_PART_SUB_KEY :
1643 KRB5_KU_TGS_REP_ENC_PART_SESSION,
1644 buf,
1645 len,
1646 ckvno,
1647 &rep->enc_part);
1648 free(buf);
1649 if (ret == 0)
1650 ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret);
954c0172
HIU
1651 }
1652 krb5_crypto_destroy(context, crypto);
1653 if(ret) {
4f8ba5ad 1654 const char *msg = krb5_get_error_message(context, ret);
40b65c84 1655 kdc_log(context, config, 4, "Failed to encode KDC-REP: %s", msg);
4f8ba5ad 1656 krb5_free_error_message(context, msg);
954c0172
HIU
1657 return ret;
1658 }
1659 if(buf_size != len) {
1660 free(buf);
40b65c84
SM
1661 kdc_log(context, config, 4, "Internal error in ASN.1 encoder");
1662 _kdc_set_e_text(r, "KDC internal error");
954c0172
HIU
1663 return KRB5KRB_ERR_GENERIC;
1664 }
1665 reply->data = buf;
1666 reply->length = buf_size;
1667 return 0;
1668}
1669
b39330c4
AB
1670/*
1671 *
1672 */
1673
954c0172 1674static krb5_error_code
2b29b718 1675get_pa_etype_info(krb5_context context,
954c0172 1676 krb5_kdc_configuration *config,
40b65c84
SM
1677 METHOD_DATA *md, Key *ckey,
1678 krb5_boolean include_salt)
954c0172
HIU
1679{
1680 krb5_error_code ret = 0;
51569b31
JS
1681 ETYPE_INFO_ENTRY eie; /* do not free this one */
1682 ETYPE_INFO ei;
1683 PA_DATA pa;
954c0172 1684 size_t len;
2b29b718 1685
51569b31
JS
1686 /*
1687 * Code moved here from what used to be make_etype_info_entry() because
1688 * using the ASN.1 compiler-generated SEQUENCE OF add functions makes that
1689 * old function's body and this one's small and clean.
1690 *
1691 * The following comment blocks were there:
1692 *
1693 * According to `the specs', we can't send a salt if we have AFS3 salted
1694 * key, but that requires that you *know* what cell you are using (e.g by
1695 * assuming that the cell is the same as the realm in lower case)
1696 *
1697 * We shouldn't sent salttype since it is incompatible with the
1698 * specification and it breaks windows clients. The afs salting problem
1699 * is solved by using KRB5-PADATA-AFS3-SALT implemented in Heimdal 0.7 and
1700 * later.
1701 *
1702 * We return no salt type at all, as that should indicate the default salt
1703 * type and make everybody happy. some systems (like w2k) dislike being
1704 * told the salt type here.
1705 */
954c0172 1706
51569b31
JS
1707 pa.padata_type = KRB5_PADATA_ETYPE_INFO;
1708 pa.padata_value.data = NULL;
1709 pa.padata_value.length = 0;
1710 ei.len = 0;
1711 ei.val = NULL;
1712 eie.etype = ckey->key.keytype;
1713 eie.salttype = NULL;
1714 eie.salt = NULL;
1715 if (include_salt && ckey->salt)
1716 eie.salt = &ckey->salt->salt;
1717 ret = add_ETYPE_INFO(&ei, &eie);
1718 if (ret == 0)
1719 ASN1_MALLOC_ENCODE(ETYPE_INFO, pa.padata_value.data, pa.padata_value.length,
1720 &ei, &len, ret);
1721 if (ret == 0)
1722 add_METHOD_DATA(md, &pa);
1723 free_ETYPE_INFO(&ei);
1724 free_PA_DATA(&pa);
1725 return ret;
954c0172
HIU
1726}
1727
1728/*
1729 *
1730 */
1731
a25f549e
JS
1732extern const int _krb5_AES_SHA1_string_to_default_iterator;
1733extern const int _krb5_AES_SHA2_string_to_default_iterator;
954c0172
HIU
1734
1735static krb5_error_code
40b65c84 1736make_s2kparams(int value, size_t len, krb5_data **ps2kparams)
954c0172 1737{
40b65c84
SM
1738 krb5_data *s2kparams;
1739 krb5_error_code ret;
1740
1741 ALLOC(s2kparams);
1742 if (s2kparams == NULL)
1743 return ENOMEM;
1744 ret = krb5_data_alloc(s2kparams, len);
1745 if (ret) {
1746 free(s2kparams);
1747 return ret;
1748 }
1749 _krb5_put_int(s2kparams->data, value, len);
1750 *ps2kparams = s2kparams;
1751 return 0;
1752}
1753
1754static krb5_error_code
1755make_etype_info2_entry(ETYPE_INFO2_ENTRY *ent,
1756 Key *key,
1757 krb5_boolean include_salt)
1758{
1759 krb5_error_code ret;
1760
954c0172 1761 ent->etype = key->key.keytype;
40b65c84 1762 if (key->salt && include_salt) {
954c0172
HIU
1763 ALLOC(ent->salt);
1764 if (ent->salt == NULL)
1765 return ENOMEM;
1766 *ent->salt = malloc(key->salt->salt.length + 1);
1767 if (*ent->salt == NULL) {
1768 free(ent->salt);
1769 ent->salt = NULL;
1770 return ENOMEM;
1771 }
1772 memcpy(*ent->salt, key->salt->salt.data, key->salt->salt.length);
1773 (*ent->salt)[key->salt->salt.length] = '\0';
1774 } else
1775 ent->salt = NULL;
1776
1777 ent->s2kparams = NULL;
1778
1779 switch (key->key.keytype) {
c44efdaa
AB
1780 case ETYPE_AES128_CTS_HMAC_SHA1_96:
1781 case ETYPE_AES256_CTS_HMAC_SHA1_96:
40b65c84
SM
1782 ret = make_s2kparams(_krb5_AES_SHA1_string_to_default_iterator,
1783 4, &ent->s2kparams);
1784 break;
1785 case KRB5_ENCTYPE_AES128_CTS_HMAC_SHA256_128:
1786 case KRB5_ENCTYPE_AES256_CTS_HMAC_SHA384_192:
1787 ret = make_s2kparams(_krb5_AES_SHA2_string_to_default_iterator,
1788 4, &ent->s2kparams);
954c0172 1789 break;
c44efdaa
AB
1790 case ETYPE_DES_CBC_CRC:
1791 case ETYPE_DES_CBC_MD4:
1792 case ETYPE_DES_CBC_MD5:
1793 /* Check if this was a AFS3 salted key */
40b65c84
SM
1794 if(key->salt && key->salt->type == hdb_afs3_salt)
1795 ret = make_s2kparams(1, 1, &ent->s2kparams);
1796 else
1797 ret = 0;
c44efdaa 1798 break;
954c0172 1799 default:
40b65c84 1800 ret = 0;
954c0172
HIU
1801 break;
1802 }
40b65c84 1803 return ret;
954c0172
HIU
1804}
1805
1806/*
b39330c4
AB
1807 * Return an ETYPE-INFO2. Enctypes are storted the same way as in the
1808 * database (client supported enctypes first, then the unsupported
1809 * enctypes).
954c0172
HIU
1810 */
1811
1812static krb5_error_code
2b29b718 1813get_pa_etype_info2(krb5_context context,
954c0172 1814 krb5_kdc_configuration *config,
40b65c84
SM
1815 METHOD_DATA *md, Key *ckey,
1816 krb5_boolean include_salt)
954c0172
HIU
1817{
1818 krb5_error_code ret = 0;
954c0172
HIU
1819 ETYPE_INFO2 pa;
1820 unsigned char *buf;
1821 size_t len;
1822
9b261c00
AB
1823 pa.len = 1;
1824 pa.val = calloc(1, sizeof(pa.val[0]));
954c0172
HIU
1825 if(pa.val == NULL)
1826 return ENOMEM;
2b29b718 1827
40b65c84 1828 ret = make_etype_info2_entry(&pa.val[0], ckey, include_salt);
9b261c00
AB
1829 if (ret) {
1830 free_ETYPE_INFO2(&pa);
1831 return ret;
954c0172
HIU
1832 }
1833
1834 ASN1_MALLOC_ENCODE(ETYPE_INFO2, buf, len, &pa, &len, ret);
1835 free_ETYPE_INFO2(&pa);
1836 if(ret)
1837 return ret;
1838 ret = realloc_method_data(md);
1839 if(ret) {
1840 free(buf);
1841 return ret;
1842 }
1843 md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO2;
1844 md->val[md->len - 1].padata_value.length = len;
1845 md->val[md->len - 1].padata_value.data = buf;
1846 return 0;
1847}
1848
40b65c84 1849/*
b12a33e2 1850 * Return 0 if the client has only older enctypes, this is for
40b65c84
SM
1851 * determining if the server should send ETYPE_INFO2 or not.
1852 */
1853
1854static int
1855newer_enctype_present(krb5_context context,
1856 struct KDC_REQ_BODY_etype *etype_list)
1857{
1858 size_t i;
1859
1860 for (i = 0; i < etype_list->len; i++) {
1861 if (!krb5_is_enctype_old(context, etype_list->val[i]))
1862 return 1;
1863 }
1864 return 0;
1865}
1866
1867static krb5_error_code
1868get_pa_etype_info_both(krb5_context context,
1869 krb5_kdc_configuration *config,
1870 struct KDC_REQ_BODY_etype *etype_list,
1871 METHOD_DATA *md, Key *ckey,
1872 krb5_boolean include_salt)
1873{
1874 krb5_error_code ret;
1875
1876 /*
1877 * Windows 2019 (and earlier versions) always sends the salt
1878 * and Samba has testsuites that check this behaviour, so a
1879 * Samba AD DC will set this flag to match the AS-REP packet
1880 * more closely.
1881 */
1882 if (config->force_include_pa_etype_salt)
1883 include_salt = TRUE;
1884
1885 /*
1886 * RFC4120 requires:
1887 * When the AS server is to include pre-authentication data in a
1888 * KRB-ERROR or in an AS-REP, it MUST use PA-ETYPE-INFO2, not
1889 * PA-ETYPE-INFO, if the etype field of the client's AS-REQ lists
1890 * at least one "newer" encryption type. Otherwise (when the etype
1891 * field of the client's AS-REQ does not list any "newer" encryption
1892 * types), it MUST send both PA-ETYPE-INFO2 and PA-ETYPE-INFO (both
1893 * with an entry for each enctype). A "newer" enctype is any enctype
1894 * first officially specified concurrently with or subsequent to the
1895 * issue of this RFC. The enctypes DES, 3DES, or RC4 and any defined
1896 * in [RFC1510] are not "newer" enctypes.
1897 *
1898 * It goes on to state:
1899 * The preferred ordering of the "hint" pre-authentication data that
1900 * affect client key selection is: ETYPE-INFO2, followed by ETYPE-INFO,
1901 * followed by PW-SALT. As noted in Section 3.1.3, a KDC MUST NOT send
1902 * ETYPE-INFO or PW-SALT when the client's AS-REQ includes at least one
1903 * "newer" etype.
1904 */
1905
1906 ret = get_pa_etype_info2(context, config, md, ckey, include_salt);
1907 if (ret)
1908 return ret;
1909
1910 if (!newer_enctype_present(context, etype_list))
1911 ret = get_pa_etype_info(context, config, md, ckey, include_salt);
1912
1913 return ret;
1914}
1915
f7242f64
AB
1916/*
1917 *
1918 */
1919
40b65c84
SM
1920void
1921_log_astgs_req(astgs_request_t r, krb5_enctype setype)
f7242f64 1922{
40b65c84
SM
1923 const KDC_REQ_BODY *b = &r->req.req_body;
1924 krb5_enctype cetype = r->reply_key.keytype;
f7242f64 1925 krb5_error_code ret;
9b261c00 1926 struct rk_strpool *p;
40b65c84 1927 struct rk_strpool *s = NULL;
f7242f64 1928 char *str;
40b65c84
SM
1929 char *cet;
1930 char *set;
255e3e18 1931 size_t i;
2b29b718 1932
40b65c84
SM
1933 /*
1934 * we are collecting ``p'' and ``s''. The former is a textual
1935 * representation of the enctypes as strings which will be used
1936 * for debugging. The latter is a terse comma separated list of
1937 * the %d's of the enctypes to emit into our audit trail to
1938 * conserve space in the logs.
1939 */
1940
9b261c00
AB
1941 p = rk_strpoolprintf(NULL, "%s", "Client supported enctypes: ");
1942
f7242f64 1943 for (i = 0; i < b->etype.len; i++) {
40b65c84 1944 ret = krb5_enctype_to_string(r->context, b->etype.val[i], &str);
f7242f64
AB
1945 if (ret == 0) {
1946 p = rk_strpoolprintf(p, "%s", str);
1947 free(str);
1948 } else
1949 p = rk_strpoolprintf(p, "%d", b->etype.val[i]);
f7242f64 1950 if (p == NULL) {
40b65c84
SM
1951 rk_strpoolfree(s);
1952 _kdc_r_log(r, 4, "out of memory");
f7242f64
AB
1953 return;
1954 }
40b65c84
SM
1955 s = rk_strpoolprintf(s, "%d", b->etype.val[i]);
1956 if (i + 1 < b->etype.len) {
1957 p = rk_strpoolprintf(p, ", ");
1958 s = rk_strpoolprintf(s, ",");
1959 }
f7242f64
AB
1960 }
1961 if (p == NULL)
1962 p = rk_strpoolprintf(p, "no encryption types");
2b29b718 1963
40b65c84
SM
1964 str = rk_strpoolcollect(s);
1965 if (str)
51569b31
JS
1966 kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE, "etypes", "%s",
1967 str);
40b65c84 1968 free(str);
f7242f64 1969
40b65c84
SM
1970 ret = krb5_enctype_to_string(r->context, cetype, &cet);
1971 if(ret == 0) {
1972 ret = krb5_enctype_to_string(r->context, setype, &set);
1973 if (ret == 0) {
1974 p = rk_strpoolprintf(p, ", using %s/%s", cet, set);
1975 free(set);
f7242f64 1976 }
40b65c84 1977 free(cet);
f7242f64 1978 }
40b65c84
SM
1979 if (ret != 0)
1980 p = rk_strpoolprintf(p, ", using enctypes %d/%d",
1981 cetype, setype);
2b29b718 1982
9b261c00 1983 str = rk_strpoolcollect(p);
40b65c84
SM
1984 if (str)
1985 _kdc_r_log(r, 4, "%s", str);
9b261c00
AB
1986 free(str);
1987
51569b31 1988 kdc_audit_addkv((kdc_request_t)r, 0, "etype", "%d/%d", cetype, setype);
40b65c84 1989
f7242f64 1990 {
91adebe7 1991 char fixedstr[128];
40b65c84
SM
1992 int result;
1993
1994 result = unparse_flags(KDCOptions2int(b->kdc_options), asn1_KDCOptions_units(),
1995 fixedstr, sizeof(fixedstr));
1996 if (result > 0) {
1997 _kdc_r_log(r, 4, "Requested flags: %s", fixedstr);
51569b31
JS
1998 kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE,
1999 "flags", "%s", fixedstr);
40b65c84 2000 }
f7242f64
AB
2001 }
2002}
2003
954c0172
HIU
2004/*
2005 * verify the flags on `client' and `server', returning 0
2006 * if they are OK and generating an error messages and returning
2007 * and error code otherwise.
2008 */
2009
51569b31 2010KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL
40b65c84
SM
2011kdc_check_flags(astgs_request_t r,
2012 krb5_boolean is_as_req,
51569b31
JS
2013 hdb_entry *client,
2014 hdb_entry *server)
954c0172 2015{
51569b31 2016 if (client != NULL) {
954c0172 2017 /* check client */
e2532553 2018 if (client->flags.locked_out) {
51569b31 2019 kdc_audit_addreason((kdc_request_t)r, "Client is locked out");
580a705b 2020 return KRB5KDC_ERR_CLIENT_REVOKED;
e2532553
AB
2021 }
2022
954c0172 2023 if (client->flags.invalid) {
51569b31
JS
2024 kdc_audit_addreason((kdc_request_t)r,
2025 "Client has invalid bit set");
954c0172
HIU
2026 return KRB5KDC_ERR_POLICY;
2027 }
255e3e18 2028
40b65c84 2029 if (!client->flags.client) {
51569b31
JS
2030 kdc_audit_addreason((kdc_request_t)r,
2031 "Principal may not act as client");
954c0172
HIU
2032 return KRB5KDC_ERR_POLICY;
2033 }
255e3e18 2034
954c0172 2035 if (client->valid_start && *client->valid_start > kdc_time) {
30d164d9 2036 char starttime_str[100];
40b65c84 2037 krb5_format_time(r->context, *client->valid_start,
2b29b718 2038 starttime_str, sizeof(starttime_str), TRUE);
51569b31
JS
2039 kdc_audit_addreason((kdc_request_t)r, "Client not yet valid "
2040 "until %s", starttime_str);
954c0172
HIU
2041 return KRB5KDC_ERR_CLIENT_NOTYET;
2042 }
255e3e18 2043
954c0172 2044 if (client->valid_end && *client->valid_end < kdc_time) {
30d164d9 2045 char endtime_str[100];
40b65c84 2046 krb5_format_time(r->context, *client->valid_end,
2b29b718 2047 endtime_str, sizeof(endtime_str), TRUE);
51569b31
JS
2048 kdc_audit_addreason((kdc_request_t)r, "Client expired at %s",
2049 endtime_str);
40b65c84 2050 return KRB5KDC_ERR_NAME_EXP;
954c0172 2051 }
255e3e18 2052
40b65c84 2053 if (client->flags.require_pwchange &&
51569b31 2054 (server == NULL || !server->flags.change_pw))
40b65c84
SM
2055 return KRB5KDC_ERR_KEY_EXPIRED;
2056
2b29b718 2057 if (client->pw_end && *client->pw_end < kdc_time
51569b31 2058 && (server == NULL || !server->flags.change_pw)) {
30d164d9 2059 char pwend_str[100];
40b65c84 2060 krb5_format_time(r->context, *client->pw_end,
2b29b718 2061 pwend_str, sizeof(pwend_str), TRUE);
51569b31
JS
2062 kdc_audit_addreason((kdc_request_t)r, "Client's key has expired "
2063 "at %s", pwend_str);
954c0172
HIU
2064 return KRB5KDC_ERR_KEY_EXPIRED;
2065 }
2066 }
2067
2068 /* check server */
2b29b718 2069
51569b31 2070 if (server != NULL) {
e2532553 2071 if (server->flags.locked_out) {
51569b31 2072 kdc_audit_addreason((kdc_request_t)r, "Server locked out");
40b65c84 2073 return KRB5KDC_ERR_SERVICE_REVOKED;
e2532553 2074 }
954c0172 2075 if (server->flags.invalid) {
51569b31
JS
2076 kdc_audit_addreason((kdc_request_t)r,
2077 "Server has invalid flag set");
954c0172
HIU
2078 return KRB5KDC_ERR_POLICY;
2079 }
40b65c84 2080 if (!server->flags.server) {
51569b31
JS
2081 kdc_audit_addreason((kdc_request_t)r,
2082 "Principal may not act as server");
954c0172
HIU
2083 return KRB5KDC_ERR_POLICY;
2084 }
2085
40b65c84 2086 if (!is_as_req && server->flags.initial) {
51569b31
JS
2087 kdc_audit_addreason((kdc_request_t)r,
2088 "AS-REQ is required for server");
954c0172
HIU
2089 return KRB5KDC_ERR_POLICY;
2090 }
2091
2092 if (server->valid_start && *server->valid_start > kdc_time) {
30d164d9 2093 char starttime_str[100];
40b65c84 2094 krb5_format_time(r->context, *server->valid_start,
2b29b718 2095 starttime_str, sizeof(starttime_str), TRUE);
51569b31
JS
2096 kdc_audit_addreason((kdc_request_t)r, "Server not yet valid "
2097 "until %s", starttime_str);
954c0172
HIU
2098 return KRB5KDC_ERR_SERVICE_NOTYET;
2099 }
2100
2101 if (server->valid_end && *server->valid_end < kdc_time) {
30d164d9 2102 char endtime_str[100];
40b65c84 2103 krb5_format_time(r->context, *server->valid_end,
2b29b718 2104 endtime_str, sizeof(endtime_str), TRUE);
51569b31
JS
2105 kdc_audit_addreason((kdc_request_t)r, "Server expired at %s",
2106 endtime_str);
954c0172
HIU
2107 return KRB5KDC_ERR_SERVICE_EXP;
2108 }
2109
2110 if (server->pw_end && *server->pw_end < kdc_time) {
30d164d9 2111 char pwend_str[100];
40b65c84 2112 krb5_format_time(r->context, *server->pw_end,
2b29b718 2113 pwend_str, sizeof(pwend_str), TRUE);
51569b31
JS
2114 kdc_audit_addreason((kdc_request_t)r, "Server's key has expired "
2115 "at %s", pwend_str);
954c0172
HIU
2116 return KRB5KDC_ERR_KEY_EXPIRED;
2117 }
2118 }
2119 return 0;
2120}
2121
2122/*
2123 * Return TRUE if `from' is part of `addresses' taking into consideration
2124 * the configuration variables that tells us how strict we should be about
2125 * these checks
2126 */
2127
3c1e780e 2128krb5_boolean
40b65c84
SM
2129_kdc_check_addresses(astgs_request_t r, HostAddresses *addresses,
2130 const struct sockaddr *from)
954c0172 2131{
40b65c84 2132 krb5_kdc_configuration *config = r->config;
954c0172
HIU
2133 krb5_error_code ret;
2134 krb5_address addr;
2135 krb5_boolean result;
ef9ec958 2136 krb5_boolean only_netbios = TRUE;
255e3e18 2137 size_t i;
2b29b718 2138
40b65c84 2139 if (!config->check_ticket_addresses && !config->warn_ticket_addresses)
954c0172
HIU
2140 return TRUE;
2141
40b65c84
SM
2142 /*
2143 * Fields of HostAddresses type are always OPTIONAL and should be non-
2144 * empty, but we check for empty just in case as our compiler doesn't
2145 * support size constraints on SEQUENCE OF.
2146 */
2147 if (addresses == NULL || addresses->len == 0)
ef9ec958 2148 return config->allow_null_ticket_addresses;
2b29b718 2149
ef9ec958 2150 for (i = 0; i < addresses->len; ++i) {
c33f6b2c
AB
2151 if (addresses->val[i].addr_type != KRB5_ADDRESS_NETBIOS) {
2152 only_netbios = FALSE;
2153 }
ef9ec958
AB
2154 }
2155
2156 /* Windows sends it's netbios name, which I can only assume is
c33f6b2c
AB
2157 * used for the 'allowed workstations' check. This is painful,
2158 * but we still want to check IP addresses if they happen to be
2159 * present.
2160 */
ef9ec958
AB
2161
2162 if(only_netbios)
954c0172 2163 return config->allow_null_ticket_addresses;
c33f6b2c 2164
40b65c84 2165 ret = krb5_sockaddr2address (r->context, from, &addr);
954c0172
HIU
2166 if(ret)
2167 return FALSE;
2168
40b65c84
SM
2169 result = krb5_address_search(r->context, &addr, addresses);
2170 krb5_free_address (r->context, &addr);
954c0172
HIU
2171 return result;
2172}
2173
f7242f64
AB
2174/*
2175 *
2176 */
40b65c84
SM
2177krb5_error_code
2178_kdc_check_anon_policy(astgs_request_t r)
2179{
2180 if (!r->config->allow_anonymous) {
51569b31
JS
2181 kdc_audit_addreason((kdc_request_t)r,
2182 "Anonymous tickets denied by local policy");
40b65c84
SM
2183 return KRB5KDC_ERR_POLICY;
2184 }
2185
2186 return 0;
2187}
2188
2189/*
2190 * Determine whether the client requested a PAC be included
2191 * or excluded explictly, or whether it doesn't care.
2192 */
f7242f64 2193
40b65c84
SM
2194static uint64_t
2195get_pac_attributes(krb5_context context, KDC_REQ *req)
f7242f64
AB
2196{
2197 krb5_error_code ret;
2198 PA_PAC_REQUEST pacreq;
91adebe7 2199 const PA_DATA *pa;
f7242f64 2200 int i = 0;
40b65c84 2201 uint32_t pac_attributes;
2f9245f2 2202
f7242f64
AB
2203 pa = _kdc_find_padata(req, &i, KRB5_PADATA_PA_PAC_REQUEST);
2204 if (pa == NULL)
40b65c84 2205 return KRB5_PAC_WAS_GIVEN_IMPLICITLY;
f7242f64
AB
2206
2207 ret = decode_PA_PAC_REQUEST(pa->padata_value.data,
2208 pa->padata_value.length,
2209 &pacreq,
2210 NULL);
2211 if (ret)
40b65c84
SM
2212 return KRB5_PAC_WAS_GIVEN_IMPLICITLY;
2213
2214 pac_attributes = pacreq.include_pac ? KRB5_PAC_WAS_REQUESTED : 0;
2215 free_PA_PAC_REQUEST(&pacreq);
2216 return pac_attributes;
2217}
2218
2219/*
2220 *
2221 */
2222
2223static krb5_error_code
2224generate_pac(astgs_request_t r, const Key *skey, const Key *tkey,
2225 krb5_boolean is_tgs)
2226{
2227 krb5_error_code ret;
40b65c84
SM
2228 uint16_t rodc_id;
2229 krb5_principal client;
2230 krb5_const_principal canon_princ = NULL;
2231
2232 r->pac_attributes = get_pac_attributes(r->context, &r->req);
51569b31
JS
2233 kdc_audit_setkv_number((kdc_request_t)r, "pac_attributes",
2234 r->pac_attributes);
40b65c84
SM
2235
2236 if (!is_tgs && !(r->pac_attributes & (KRB5_PAC_WAS_REQUESTED | KRB5_PAC_WAS_GIVEN_IMPLICITLY)))
2237 return 0;
2238
2239 /*
2240 * When a PA mech does not use the client's long-term key, the PAC
2241 * may include the client's long-term key (encrypted in the reply key)
2242 * for use by other shared secret authentication protocols, e.g. NTLM.
2243 * Validate a PA mech was actually used before doing this.
2244 */
2245
f33f73f8 2246 ret = _kdc_pac_generate(r,
40b65c84
SM
2247 r->client,
2248 r->server,
2249 r->pa_used && !pa_used_flag_isset(r, PA_USES_LONG_TERM_KEY)
2250 ? &r->reply_key : NULL,
2251 r->pac_attributes,
2252 &r->pac);
2253 if (ret) {
2254 _kdc_r_log(r, 4, "PAC generation failed for -- %s",
2255 r->cname);
2256 return ret;
2257 }
2258 if (r->pac == NULL)
2259 return 0;
2260
51569b31 2261 rodc_id = r->server->kvno >> 16;
40b65c84
SM
2262
2263 /* libkrb5 expects ticket and PAC client names to match */
2264 ret = _krb5_principalname2krb5_principal(r->context, &client,
2265 r->et.cname, r->et.crealm);
2266 if (ret)
2267 return ret;
2268
2269 /*
2270 * Include the canonical name of the principal in the authorization
2271 * data, if the realms match (if they don't, then the KDC could
2272 * impersonate any realm. Windows always canonicalizes the realm,
2273 * but Heimdal permits aliases between realms.)
2274 */
51569b31 2275 if (krb5_realm_compare(r->context, client, r->canon_client_princ)) {
40b65c84
SM
2276 char *cpn = NULL;
2277
51569b31 2278 canon_princ = r->canon_client_princ;
40b65c84 2279
51569b31
JS
2280 (void) krb5_unparse_name(r->context, canon_princ, &cpn);
2281 kdc_audit_addkv((kdc_request_t)r, 0, "canon_client_name", "%s",
2282 cpn ? cpn : "<unknown>");
40b65c84
SM
2283 krb5_xfree(cpn);
2284 }
2285
2286 if (r->pa_used && r->pa_used->finalize_pac) {
2287 ret = r->pa_used->finalize_pac(r);
2288 if (ret)
2289 return ret;
2290 }
2291
09bcd48f
JS
2292 ret = _krb5_kdc_pac_sign_ticket(r->context,
2293 r->pac,
2294 client,
2295 &skey->key, /* Server key */
2296 &tkey->key, /* TGS key */
2297 rodc_id,
2298 NULL, /* UPN */
2299 canon_princ,
2300 !is_tgs, /* add_ticket_sig */
2301 !is_tgs, /* add_full_sig */
2302 &r->et,
2303 is_tgs ? &r->pac_attributes : NULL);
40b65c84
SM
2304 krb5_free_principal(r->context, client);
2305 krb5_pac_free(r->context, r->pac);
2306 r->pac = NULL;
2307 if (ret) {
2308 _kdc_r_log(r, 4, "PAC signing failed for -- %s",
2309 r->cname);
2310 return ret;
2311 }
40b65c84
SM
2312
2313 return ret;
2314}
2315
2316/*
2317 *
2318 */
2319
2320krb5_boolean
2321_kdc_is_anonymous(krb5_context context, krb5_const_principal principal)
2322{
2323 return krb5_principal_is_anonymous(context, principal, KRB5_ANON_MATCH_ANY);
2324}
2325
2326/*
2327 * Returns TRUE if principal is the unauthenticated anonymous identity,
2328 * i.e. WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS. Unfortunately due to
2329 * backwards compatibility logic in krb5_principal_is_anonymous() we
2330 * have to use our own implementation.
2331 */
2332
2333krb5_boolean
2334_kdc_is_anonymous_pkinit(krb5_context context, krb5_const_principal principal)
2335{
2336 return _kdc_is_anonymous(context, principal) &&
2337 strcmp(principal->realm, KRB5_ANON_REALM) == 0;
2338}
2339
2340static int
2341require_preauth_p(astgs_request_t r)
2342{
2343 return r->config->require_preauth
51569b31
JS
2344 || r->client->flags.require_preauth
2345 || r->server->flags.require_preauth;
40b65c84
SM
2346}
2347
2348
2349/*
2350 *
2351 */
2352
2353static krb5_error_code
2354add_enc_pa_rep(astgs_request_t r)
2355{
2356 krb5_error_code ret;
2357 krb5_crypto crypto;
2358 Checksum checksum;
2359 krb5_data cdata;
2360 size_t len;
2361
2362 ret = krb5_crypto_init(r->context, &r->reply_key, 0, &crypto);
2363 if (ret)
2364 return ret;
2365
2366 ret = krb5_create_checksum(r->context, crypto,
2367 KRB5_KU_AS_REQ, 0,
2368 r->request.data, r->request.length,
2369 &checksum);
2370 krb5_crypto_destroy(r->context, crypto);
2371 if (ret)
2372 return ret;
2373
2374 ASN1_MALLOC_ENCODE(Checksum, cdata.data, cdata.length,
2375 &checksum, &len, ret);
2376 free_Checksum(&checksum);
2377 if (ret)
2378 return ret;
2379 heim_assert(cdata.length == len, "ASN.1 internal error");
2380
2381 if (r->ek.encrypted_pa_data == NULL) {
2382 ALLOC(r->ek.encrypted_pa_data);
2383 if (r->ek.encrypted_pa_data == NULL)
2384 return ENOMEM;
2f9245f2 2385 }
40b65c84
SM
2386 ret = krb5_padata_add(r->context, r->ek.encrypted_pa_data,
2387 KRB5_PADATA_REQ_ENC_PA_REP, cdata.data, cdata.length);
2388 if (ret)
2389 return ret;
75ec66c7
SM
2390
2391 if (!r->config->enable_fast)
2392 return 0;
2393
40b65c84
SM
2394 return krb5_padata_add(r->context, r->ek.encrypted_pa_data,
2395 KRB5_PADATA_FX_FAST, NULL, 0);
f7242f64
AB
2396}
2397
40b65c84
SM
2398/*
2399 * Add an authorization data element indicating that a synthetic
2400 * principal was used, so that the TGS does not accidentally
2401 * synthesize a non-synthetic principal that has since been deleted.
2402 */
2403static krb5_error_code
2404add_synthetic_princ_ad(astgs_request_t r)
9b261c00 2405{
40b65c84
SM
2406 krb5_data data;
2407
2408 krb5_data_zero(&data);
2409
2410 return _kdc_tkt_add_if_relevant_ad(r->context, &r->et,
2411 KRB5_AUTHDATA_SYNTHETIC_PRINC_USED,
2412 &data);
9b261c00
AB
2413}
2414
91e684f5
LH
2415static krb5_error_code
2416get_local_tgs(krb5_context context,
2417 krb5_kdc_configuration *config,
2418 krb5_const_realm realm,
51569b31
JS
2419 HDB **krbtgtdb,
2420 hdb_entry **krbtgt)
91e684f5
LH
2421{
2422 krb5_error_code ret;
2423 krb5_principal tgs_name;
2424
51569b31 2425 *krbtgtdb = NULL;
91e684f5
LH
2426 *krbtgt = NULL;
2427
2428 ret = krb5_make_principal(context,
2429 &tgs_name,
2430 realm,
2431 KRB5_TGS_NAME,
2432 realm,
2433 NULL);
a87aae52
JS
2434 if (ret == 0)
2435 ret = _kdc_db_fetch(context, config, tgs_name,
2436 HDB_F_GET_KRBTGT, NULL, krbtgtdb, krbtgt);
91e684f5 2437
91e684f5 2438 krb5_free_principal(context, tgs_name);
91e684f5
LH
2439 return ret;
2440}
2441
f7242f64
AB
2442/*
2443 *
2444 */
2445
954c0172 2446krb5_error_code
40b65c84 2447_kdc_as_rep(astgs_request_t r)
954c0172 2448{
40b65c84
SM
2449 krb5_kdc_configuration *config = r->config;
2450 KDC_REQ *req = &r->req;
2451 const char *from = r->from;
2452 KDC_REQ_BODY *b = NULL;
2453 KDC_REP *rep = &r->rep;
2454 KDCOptions f;
2455 krb5_enctype setype;
954c0172 2456 krb5_error_code ret = 0;
40b65c84
SM
2457 Key *skey;
2458 int found_pa = 0;
2459 int i, flags = HDB_F_FOR_AS_REQ;
2460 const PA_DATA *pa;
db30b71f 2461 krb5_boolean is_tgs;
40b65c84 2462 const char *msg;
40b65c84 2463 Key *krbtgt_key;
a25f549e 2464 unsigned krbtgt_kvno;
40b65c84
SM
2465
2466 memset(rep, 0, sizeof(*rep));
954c0172 2467
40b65c84
SM
2468 ALLOC(rep->padata);
2469 if (rep->padata == NULL) {
2470 ret = ENOMEM;
2471 krb5_set_error_message(r->context, ret, N_("malloc: out of memory", ""));
2472 goto out;
2473 }
2474
2475 /*
2476 * Look for FAST armor and unwrap
2477 */
2478 ret = _kdc_fast_unwrap_request(r, NULL, NULL);
2479 if (ret) {
2480 _kdc_r_log(r, 1, "FAST unwrap request from %s failed: %d", from, ret);
2481 goto out;
2482 }
91adebe7 2483
95c02a97
JS
2484 /* Validate armor TGT, and initialize the armor client and PAC */
2485 if (r->armor_ticket) {
2486 ret = _kdc_fast_check_armor_pac(r, HDB_F_FOR_AS_REQ);
2487 if (ret)
2488 goto out;
2489 }
2490
40b65c84
SM
2491 b = &req->req_body;
2492 f = b->kdc_options;
89eaef02 2493
91adebe7
AB
2494 if (f.canonicalize)
2495 flags |= HDB_F_CANON;
954c0172 2496
40b65c84 2497 if (b->sname == NULL) {
b0f4455e 2498 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
40b65c84
SM
2499 _kdc_set_e_text(r, "No server in request");
2500 goto out;
954c0172 2501 }
40b65c84
SM
2502
2503 ret = _krb5_principalname2krb5_principal(r->context, &r->server_princ,
2504 *(b->sname), b->realm);
2505 if (!ret)
2506 ret = krb5_unparse_name(r->context, r->server_princ, &r->sname);
954c0172 2507 if (ret) {
40b65c84
SM
2508 kdc_log(r->context, config, 2,
2509 "AS_REQ malformed server name from %s", from);
954c0172
HIU
2510 goto out;
2511 }
9b261c00 2512
40b65c84
SM
2513 if (b->cname == NULL) {
2514 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
2515 _kdc_set_e_text(r, "No client in request");
2516 goto out;
954c0172 2517 }
40b65c84
SM
2518
2519 ret = _krb5_principalname2krb5_principal(r->context, &r->client_princ,
2520 *(b->cname), b->realm);
2521 if (!ret)
2522 ret = krb5_unparse_name(r->context, r->client_princ, &r->cname);
954c0172 2523 if (ret) {
40b65c84 2524 kdc_log(r->context, config, 2,
3c1e780e 2525 "AS-REQ malformed client name from %s", from);
954c0172
HIU
2526 goto out;
2527 }
2528
40b65c84
SM
2529 kdc_log(r->context, config, 4, "AS-REQ %s from %s for %s",
2530 r->cname, r->from, r->sname);
954c0172 2531
40b65c84 2532 is_tgs = krb5_principal_is_krbtgt(r->context, r->server_princ);
9b261c00 2533
40b65c84
SM
2534 if (_kdc_is_anonymous(r->context, r->client_princ) &&
2535 !_kdc_is_anon_request(req)) {
2536 kdc_log(r->context, config, 2, "Anonymous client w/o anonymous flag");
2537 ret = KRB5KDC_ERR_BADOPTION;
9b261c00
AB
2538 goto out;
2539 }
2540
40b65c84
SM
2541 ret = _kdc_db_fetch(r->context, config, r->client_princ,
2542 HDB_F_GET_CLIENT | HDB_F_SYNTHETIC_OK | flags, NULL,
2543 &r->clientdb, &r->client);
2544 switch (ret) {
2545 case 0: /* Success */
2546 break;
2547 case HDB_ERR_NOT_FOUND_HERE:
2548 kdc_log(r->context, config, 5, "client %s does not have secrets at this KDC, need to proxy",
2549 r->cname);
aa1c32cc 2550 goto out;
40b65c84 2551 case HDB_ERR_WRONG_REALM: {
2d988002
SM
2552 char *fixed_client_name = NULL;
2553
51569b31 2554 ret = krb5_unparse_name(r->context, r->client->principal,
2d988002
SM
2555 &fixed_client_name);
2556 if (ret) {
2557 goto out;
2558 }
2559
40b65c84
SM
2560 kdc_log(r->context, config, 4, "WRONG_REALM - %s -> %s",
2561 r->cname, fixed_client_name);
2d988002
SM
2562 free(fixed_client_name);
2563
40b65c84
SM
2564 r->e_text = NULL;
2565 ret = _kdc_fast_mk_error(r, r->rep.padata, r->armor_crypto,
2566 &req->req_body,
51569b31
JS
2567 r->error_code = KRB5_KDC_ERR_WRONG_REALM,
2568 r->client->principal, r->server_princ,
40b65c84 2569 NULL, NULL, r->reply);
2d988002 2570 goto out;
40b65c84
SM
2571 }
2572 default:
2573 {
40b65c84
SM
2574 msg = krb5_get_error_message(r->context, ret);
2575 kdc_log(r->context, config, 4, "UNKNOWN -- %s: %s", r->cname, msg);
2576 krb5_free_error_message(r->context, msg);
954c0172 2577 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
51569b31
JS
2578 kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
2579 KDC_AUTH_EVENT_CLIENT_UNKNOWN);
954c0172
HIU
2580 goto out;
2581 }
40b65c84 2582 }
95c02a97
JS
2583
2584 kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
2585 KDC_AUTH_EVENT_CLIENT_FOUND);
2586
40b65c84
SM
2587 ret = _kdc_db_fetch(r->context, config, r->server_princ,
2588 HDB_F_GET_SERVER | HDB_F_DELAY_NEW_KEYS |
2589 flags | (is_tgs ? HDB_F_GET_KRBTGT : 0),
51569b31 2590 NULL, &r->serverdb, &r->server);
40b65c84
SM
2591 switch (ret) {
2592 case 0: /* Success */
2593 break;
2594 case HDB_ERR_NOT_FOUND_HERE:
2595 kdc_log(r->context, config, 5, "target %s does not have secrets at this KDC, need to proxy",
2596 r->sname);
aa1c32cc 2597 goto out;
40b65c84
SM
2598 default:
2599 msg = krb5_get_error_message(r->context, ret);
2600 kdc_log(r->context, config, 4, "UNKNOWN -- %s: %s", r->sname, msg);
2601 krb5_free_error_message(r->context, msg);
954c0172
HIU
2602 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
2603 goto out;
2604 }
2605
95c02a97
JS
2606 ret = _kdc_check_access(r);
2607 if(ret)
2608 goto out;
2609
975e43fc
AB
2610 /*
2611 * This has to be here (not later), because we need to have r->sessionetype
2612 * set prior to calling pa_pkinit_validate(), which in turn calls
2613 * _kdc_pk_mk_pa_reply(), during padata validation.
2614 */
2615
9b261c00 2616 /*
40b65c84
SM
2617 * Select an enctype for the to-be-issued ticket's session key using the
2618 * intersection of the client's requested enctypes and the server's (like a
2619 * root krbtgt, but not necessarily) etypes from its HDB entry.
255e3e18 2620 */
975e43fc
AB
2621 ret = _kdc_find_session_etype(r, b->etype.val, b->etype.len,
2622 r->server, &r->sessionetype);
255e3e18 2623 if (ret) {
40b65c84 2624 kdc_log(r->context, config, 4,
255e3e18
SM
2625 "Client (%s) from %s has no common enctypes with KDC "
2626 "to use for the session key",
40b65c84 2627 r->cname, from);
255e3e18
SM
2628 goto out;
2629 }
954c0172 2630
a25f549e
JS
2631 /*
2632 * Select the best encryption type for the KDC without regard to
2633 * the client since the client never needs to read that data.
2634 */
2635
2636 ret = _kdc_get_preferred_key(r->context, config,
2637 r->server, r->sname,
2638 &setype, &skey);
2639 if(ret)
2640 goto out;
2641
2642 /* If server is not krbtgt, fetch local krbtgt key for signing authdata */
2643 if (is_tgs) {
2644 krbtgt_key = skey;
2645 krbtgt_kvno = r->server->kvno;
2646 } else {
2647 ret = get_local_tgs(r->context, config, r->server_princ->realm,
2648 &r->krbtgtdb, &r->krbtgt);
2649 if (ret)
2650 goto out;
2651
2652 ret = _kdc_get_preferred_key(r->context, config, r->krbtgt,
2653 r->server_princ->realm,
2654 NULL, &krbtgt_key);
2655 if (ret)
2656 goto out;
2657
2658 krbtgt_kvno = r->server->kvno;
2659 }
2660
9b261c00
AB
2661 /*
2662 * Pre-auth processing
2663 */
954c0172
HIU
2664
2665 if(req->padata){
40b65c84 2666 unsigned int n;
954c0172 2667
40b65c84 2668 log_patypes(r, req->padata);
c33f6b2c 2669
40b65c84 2670 /* Check if preauth matching */
954c0172 2671
40b65c84
SM
2672 for (n = 0; !found_pa && n < sizeof(pat) / sizeof(pat[0]); n++) {
2673 if (pat[n].validate == NULL)
2674 continue;
2675 if (r->armor_crypto == NULL && (pat[n].flags & PA_REQ_FAST))
2676 continue;
fc474042
JS
2677 if (!r->config->enable_fast_cookie && (pat[n].flags & PA_USES_FAST_COOKIE))
2678 continue;
954c0172 2679
40b65c84
SM
2680 kdc_log(r->context, config, 5,
2681 "Looking for %s pa-data -- %s", pat[n].name, r->cname);
954c0172 2682 i = 0;
40b65c84
SM
2683 pa = _kdc_find_padata(req, &i, pat[n].type);
2684 if (pa) {
51569b31 2685 if (r->client->flags.synthetic &&
40b65c84
SM
2686 !(pat[n].flags & PA_SYNTHETIC_OK)) {
2687 kdc_log(r->context, config, 4, "UNKNOWN -- %s", r->cname);
51569b31 2688 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
40b65c84
SM
2689 goto out;
2690 }
09bcd48f
JS
2691 if (!(pat[n].flags & PA_HARDWARE_AUTH)) {
2692 ret = _kdc_hwauth_policy(r);
2693 if (ret) {
2694 kdc_log(r->context, config, 4, "Hardware authentication required for %s", r->cname);
2695 return ret;
2696 }
2697 }
51569b31
JS
2698 kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_VIS, "pa", "%s",
2699 pat[n].name);
2700 ret = pat[n].validate(r, pa);
40b65c84
SM
2701 if (ret != 0) {
2702 krb5_error_code ret2;
2703 Key *ckey = NULL;
2704 krb5_boolean default_salt;
2705
51569b31
JS
2706 if (ret != KRB5_KDC_ERR_MORE_PREAUTH_DATA_REQUIRED &&
2707 !kdc_audit_getkv((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT))
2708 kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
2709 KDC_AUTH_EVENT_PREAUTH_FAILED);
40b65c84
SM
2710
2711 /*
2712 * If there is a client key, send ETYPE_INFO{,2}
2713 */
90436389
JS
2714 if (!r->client->flags.locked_out) {
2715 ret2 = _kdc_find_etype(r, KFE_IS_PREAUTH|KFE_USE_CLIENT,
2716 b->etype.val, b->etype.len,
2717 NULL, &ckey, &default_salt);
2718 if (ret2 == 0) {
2719 ret2 = get_pa_etype_info_both(r->context, config, &b->etype,
2720 r->rep.padata, ckey, !default_salt);
2721 if (ret2 != 0)
2722 ret = ret2;
2723 }
40b65c84
SM
2724 }
2725 goto out;
2726 }
51569b31
JS
2727 if (!kdc_audit_getkv((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT))
2728 kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
2729 KDC_AUTH_EVENT_PREAUTH_SUCCEEDED);
40b65c84
SM
2730 kdc_log(r->context, config, 4,
2731 "%s pre-authentication succeeded -- %s",
2732 pat[n].name, r->cname);
2733 found_pa = 1;
2734 r->pa_used = &pat[n];
40b65c84 2735 r->et.flags.pre_authent = 1;
954c0172 2736 }
30bae409 2737 }
40b65c84 2738 }
30bae409 2739
40b65c84
SM
2740 if (found_pa == 0) {
2741 Key *ckey = NULL;
2742 size_t n;
2743 krb5_boolean default_salt;
255e3e18 2744
51569b31 2745 if (r->client->flags.synthetic) {
40b65c84 2746 kdc_log(r->context, config, 4, "UNKNOWN -- %s", r->cname);
51569b31 2747 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
40b65c84
SM
2748 goto out;
2749 }
e2532553 2750
40b65c84
SM
2751 for (n = 0; n < sizeof(pat) / sizeof(pat[0]); n++) {
2752 if ((pat[n].flags & PA_ANNOUNCE) == 0)
954c0172 2753 continue;
954c0172 2754
40b65c84 2755 if (!r->armor_crypto && (pat[n].flags & PA_REQ_FAST))
954c0172 2756 continue;
75ec66c7
SM
2757 if (pat[n].type == KRB5_PADATA_PKINIT_KX && !r->config->allow_anonymous)
2758 continue;
40b65c84
SM
2759 if (pat[n].type == KRB5_PADATA_ENC_TIMESTAMP) {
2760 if (r->armor_crypto && !r->config->enable_armored_pa_enc_timestamp)
2761 continue;
2762 if (!r->armor_crypto && !r->config->enable_unarmored_pa_enc_timestamp)
2763 continue;
954c0172 2764 }
75ec66c7
SM
2765 if (pat[n].type == KRB5_PADATA_FX_FAST && !r->config->enable_fast)
2766 continue;
2767 if (pat[n].type == KRB5_PADATA_GSS && !r->config->enable_gss_preauth)
2768 continue;
fc474042
JS
2769 if (!r->config->enable_fast_cookie && (pat[n].flags & PA_USES_FAST_COOKIE))
2770 continue;
954c0172 2771
40b65c84
SM
2772 ret = krb5_padata_add(r->context, r->rep.padata,
2773 pat[n].type, NULL, 0);
2774 if (ret)
954c0172 2775 goto out;
40b65c84 2776 }
89eaef02 2777
40b65c84
SM
2778 /*
2779 * If there is a client key, send ETYPE_INFO{,2}
2780 */
2781 ret = _kdc_find_etype(r, KFE_IS_PREAUTH|KFE_USE_CLIENT,
2782 b->etype.val, b->etype.len,
2783 NULL, &ckey, &default_salt);
2784 if (ret == 0) {
2785 ret = get_pa_etype_info_both(r->context, config, &b->etype,
2786 r->rep.padata, ckey, !default_salt);
c0e8144c 2787 if (ret)
9b261c00 2788 goto out;
9b261c00 2789 }
255e3e18 2790
a25f549e
JS
2791 /*
2792 * If the client indicated support for PKINIT Freshness, send back a
2793 * freshness token.
2794 */
2795 ret = send_freshness_token(r, krbtgt_key, krbtgt_kvno);
2796 if (ret)
2797 goto out;
2798
40b65c84
SM
2799 /*
2800 * send requre preauth is its required or anon is requested,
2801 * anon is today only allowed via preauth mechanisms.
2802 */
2803 if (require_preauth_p(r) || _kdc_is_anon_request(&r->req)) {
2804 ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
2805 _kdc_set_e_text(r, "Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ");
2806 goto out;
2807 }
544e1789 2808
40b65c84
SM
2809 if (ckey == NULL) {
2810 ret = KRB5KDC_ERR_CLIENT_NOTYET;
2811 _kdc_set_e_text(r, "Doesn't have a client key available");
2812 goto out;
2813 }
2814 krb5_free_keyblock_contents(r->context, &r->reply_key);
2815 ret = krb5_copy_keyblock_contents(r->context, &ckey->key, &r->reply_key);
2816 if (ret)
2817 goto out;
954c0172 2818 }
2b29b718 2819
51569b31
JS
2820 r->canon_client_princ = r->client->principal;
2821
40b65c84
SM
2822 if (_kdc_is_anon_request(&r->req)) {
2823 ret = _kdc_check_anon_policy(r);
2824 if (ret) {
2825 _kdc_set_e_text(r, "Anonymous ticket requests are disabled");
2826 goto out;
2827 }
2828
2829 r->et.flags.anonymous = 1;
2830 }
2831
51569b31
JS
2832 kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
2833 KDC_AUTH_EVENT_CLIENT_AUTHORIZED);
d202191f 2834
40b65c84 2835 if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey) {
954c0172 2836 ret = KRB5KDC_ERR_BADOPTION;
40b65c84 2837 _kdc_set_e_text(r, "Bad KDC options");
954c0172
HIU
2838 goto out;
2839 }
2b29b718 2840
40b65c84
SM
2841 /*
2842 * Build reply
2843 */
2844 rep->pvno = 5;
2845 rep->msg_type = krb_as_rep;
2846
2847 if (!config->historical_anon_realm &&
2848 _kdc_is_anonymous(r->context, r->client_princ)) {
2849 Realm anon_realm = KRB5_ANON_REALM;
2850 ret = copy_Realm(&anon_realm, &rep->crealm);
51569b31
JS
2851 } else if (f.canonicalize || r->client->flags.force_canonicalize)
2852 ret = copy_Realm(&r->canon_client_princ->realm, &rep->crealm);
40b65c84
SM
2853 else
2854 ret = copy_Realm(&r->client_princ->realm, &rep->crealm);
9b261c00
AB
2855 if (ret)
2856 goto out;
40b65c84
SM
2857 if (r->et.flags.anonymous)
2858 ret = _kdc_make_anonymous_principalname(&rep->cname);
51569b31
JS
2859 else if (f.canonicalize || r->client->flags.force_canonicalize)
2860 ret = _krb5_principal2principalname(&rep->cname, r->canon_client_princ);
40b65c84
SM
2861 else
2862 ret = _krb5_principal2principalname(&rep->cname, r->client_princ);
9b261c00
AB
2863 if (ret)
2864 goto out;
2865
40b65c84 2866 rep->ticket.tkt_vno = 5;
51569b31
JS
2867 if (f.canonicalize || r->server->flags.force_canonicalize)
2868 ret = copy_Realm(&r->server->principal->realm, &rep->ticket.realm);
40b65c84
SM
2869 else
2870 ret = copy_Realm(&r->server_princ->realm, &rep->ticket.realm);
2871 if (ret)
2872 goto out;
51569b31 2873 if (f.canonicalize || r->server->flags.force_canonicalize)
40b65c84 2874 _krb5_principal2principalname(&rep->ticket.sname,
51569b31 2875 r->server->principal);
40b65c84
SM
2876 else
2877 _krb5_principal2principalname(&rep->ticket.sname,
2878 r->server_princ);
b39330c4 2879 /* java 1.6 expects the name to be the same type, lets allow that
41473daf
AB
2880 * uncomplicated name-types, when f.canonicalize is not set (to
2881 * match Windows Server 1709). */
b39330c4 2882#define CNT(sp,t) (((sp)->sname->name_type) == KRB5_NT_##t)
41473daf
AB
2883 if (!f.canonicalize
2884 && (CNT(b, UNKNOWN) || CNT(b, PRINCIPAL) || CNT(b, SRV_INST) || CNT(b, SRV_HST) || CNT(b, SRV_XHST))) {
40b65c84 2885 rep->ticket.sname.name_type = b->sname->name_type;
41473daf 2886 }
b39330c4 2887#undef CNT
954c0172 2888
40b65c84 2889 r->et.flags.initial = 1;
51569b31 2890 if(r->client->flags.forwardable && r->server->flags.forwardable)
40b65c84 2891 r->et.flags.forwardable = f.forwardable;
51569b31 2892 if(r->client->flags.proxiable && r->server->flags.proxiable)
40b65c84 2893 r->et.flags.proxiable = f.proxiable;
954c0172 2894 else if (f.proxiable) {
40b65c84 2895 _kdc_set_e_text(r, "Ticket may not be proxiable");
954c0172 2896 ret = KRB5KDC_ERR_POLICY;
954c0172
HIU
2897 goto out;
2898 }
51569b31 2899 if(r->client->flags.postdate && r->server->flags.postdate)
40b65c84 2900 r->et.flags.may_postdate = f.allow_postdate;
954c0172 2901 else if (f.allow_postdate){
b12a33e2 2902 _kdc_set_e_text(r, "Ticket may not be postdateable");
954c0172 2903 ret = KRB5KDC_ERR_POLICY;
954c0172
HIU
2904 goto out;
2905 }
2906
40b65c84 2907 if (b->addresses)
51569b31 2908 kdc_audit_addaddrs((kdc_request_t)r, b->addresses, "reqaddrs");
40b65c84 2909
954c0172 2910 /* check for valid set of addresses */
40b65c84
SM
2911 if (!_kdc_check_addresses(r, b->addresses, r->addr)) {
2912 if (r->config->warn_ticket_addresses) {
51569b31 2913 kdc_audit_setkv_bool((kdc_request_t)r, "wrongaddr", TRUE);
40b65c84
SM
2914 } else {
2915 _kdc_set_e_text(r, "Request from wrong address");
2916 ret = KRB5KRB_AP_ERR_BADADDR;
2917 goto out;
2918 }
954c0172
HIU
2919 }
2920
40b65c84 2921 ret = copy_PrincipalName(&rep->cname, &r->et.cname);
9b261c00
AB
2922 if (ret)
2923 goto out;
40b65c84 2924 ret = copy_Realm(&rep->crealm, &r->et.crealm);
f7242f64
AB
2925 if (ret)
2926 goto out;
2b29b718 2927
954c0172
HIU
2928 {
2929 time_t start;
2930 time_t t;
40b65c84
SM
2931
2932 start = r->et.authtime = kdc_time;
2b29b718 2933
954c0172 2934 if(f.postdated && req->req_body.from){
40b65c84
SM
2935 ALLOC(r->et.starttime);
2936 start = *r->et.starttime = *req->req_body.from;
2937 r->et.flags.invalid = 1;
2938 r->et.flags.postdated = 1; /* XXX ??? */
954c0172 2939 }
3c1e780e 2940 _kdc_fix_time(&b->till);
954c0172
HIU
2941 t = *b->till;
2942
b12a33e2 2943 /* be careful not to overflow */
954c0172 2944
40b65c84 2945 /*
51569b31 2946 * Pre-auth can override r->client->max_life if configured.
40b65c84
SM
2947 *
2948 * See pre-auth methods, specifically PKINIT, which can get or derive
2949 * this from the client's certificate.
2950 */
2951 if (r->pa_max_life > 0)
51569b31 2952 t = rk_time_add(start, min(rk_time_sub(t, start), r->pa_max_life));
eeebd488 2953 else if (r->client->max_life)
51569b31
JS
2954 t = rk_time_add(start, min(rk_time_sub(t, start),
2955 *r->client->max_life));
40b65c84 2956
eeebd488 2957 if (r->server->max_life)
51569b31
JS
2958 t = rk_time_add(start, min(rk_time_sub(t, start),
2959 *r->server->max_life));
40b65c84
SM
2960
2961 /* Pre-auth can bound endtime as well */
2962 if (r->pa_endtime > 0)
51569b31 2963 t = rk_time_add(start, min(rk_time_sub(t, start), r->pa_endtime));
954c0172 2964#if 0
51569b31 2965 t = min(t, rk_time_add(start, realm->max_life));
954c0172 2966#endif
40b65c84 2967 r->et.endtime = t;
eeebd488
JS
2968
2969 if (start > r->et.endtime) {
2970 _kdc_set_e_text(r, "Requested effective lifetime is negative or too short");
2971 ret = KRB5KDC_ERR_NEVER_VALID;
2972 goto out;
2973 }
2974
40b65c84 2975 if(f.renewable_ok && r->et.endtime < *b->till){
954c0172
HIU
2976 f.renewable = 1;
2977 if(b->rtime == NULL){
2978 ALLOC(b->rtime);
2979 *b->rtime = 0;
2980 }
2981 if(*b->rtime < *b->till)
2982 *b->rtime = *b->till;
2983 }
2984 if(f.renewable && b->rtime){
2985 t = *b->rtime;
2986 if(t == 0)
2987 t = MAX_TIME;
eeebd488 2988 if(r->client->max_renew)
51569b31
JS
2989 t = rk_time_add(start, min(rk_time_sub(t, start),
2990 *r->client->max_renew));
eeebd488 2991 if(r->server->max_renew)
51569b31
JS
2992 t = rk_time_add(start, min(rk_time_sub(t, start),
2993 *r->server->max_renew));
954c0172 2994#if 0
51569b31 2995 t = min(t, rk_time_add(start, realm->max_renew));
954c0172 2996#endif
40b65c84
SM
2997 ALLOC(r->et.renew_till);
2998 *r->et.renew_till = t;
2999 r->et.flags.renewable = 1;
954c0172
HIU
3000 }
3001 }
3002
954c0172 3003 if(b->addresses){
40b65c84
SM
3004 ALLOC(r->et.caddr);
3005 copy_HostAddresses(b->addresses, r->et.caddr);
954c0172 3006 }
2b29b718 3007
40b65c84
SM
3008 r->et.transited.tr_type = domain_X500_Compress;
3009 krb5_data_zero(&r->et.transited.contents);
2b29b718 3010
954c0172
HIU
3011 /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
3012 * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
3013 * incapable of correctly decoding SEQUENCE OF's of zero length.
3014 *
3015 * To fix this, always send at least one no-op last_req
3016 *
3017 * If there's a pw_end or valid_end we will use that,
3018 * otherwise just a dummy lr.
3019 */
40b65c84
SM
3020 r->ek.last_req.val = malloc(2 * sizeof(*r->ek.last_req.val));
3021 if (r->ek.last_req.val == NULL) {
9e6b0c28
AB
3022 ret = ENOMEM;
3023 goto out;
3024 }
40b65c84 3025 r->ek.last_req.len = 0;
51569b31 3026 if (r->client->pw_end
954c0172 3027 && (config->kdc_warn_pwexpire == 0
51569b31 3028 || kdc_time + config->kdc_warn_pwexpire >= *r->client->pw_end)) {
40b65c84 3029 r->ek.last_req.val[r->ek.last_req.len].lr_type = LR_PW_EXPTIME;
51569b31 3030 r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->pw_end;
40b65c84
SM
3031 ++r->ek.last_req.len;
3032 }
51569b31 3033 if (r->client->valid_end) {
40b65c84 3034 r->ek.last_req.val[r->ek.last_req.len].lr_type = LR_ACCT_EXPTIME;
51569b31 3035 r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->valid_end;
40b65c84
SM
3036 ++r->ek.last_req.len;
3037 }
3038 if (r->ek.last_req.len == 0) {
3039 r->ek.last_req.val[r->ek.last_req.len].lr_type = LR_NONE;
3040 r->ek.last_req.val[r->ek.last_req.len].lr_value = 0;
3041 ++r->ek.last_req.len;
3042 }
a25f549e
JS
3043 /* Set the nonce if it’s not already set. */
3044 if (!r->ek.nonce) {
3045 r->ek.nonce = b->nonce;
3046 }
51569b31 3047 if (r->client->valid_end || r->client->pw_end) {
40b65c84 3048 ALLOC(r->ek.key_expiration);
51569b31
JS
3049 if (r->client->valid_end) {
3050 if (r->client->pw_end)
3051 *r->ek.key_expiration = min(*r->client->valid_end,
3052 *r->client->pw_end);
954c0172 3053 else
51569b31 3054 *r->ek.key_expiration = *r->client->valid_end;
954c0172 3055 } else
51569b31 3056 *r->ek.key_expiration = *r->client->pw_end;
954c0172 3057 } else
40b65c84
SM
3058 r->ek.key_expiration = NULL;
3059 r->ek.flags = r->et.flags;
3060 r->ek.authtime = r->et.authtime;
3061 if (r->et.starttime) {
3062 ALLOC(r->ek.starttime);
3063 *r->ek.starttime = *r->et.starttime;
954c0172 3064 }
40b65c84
SM
3065 r->ek.endtime = r->et.endtime;
3066 if (r->et.renew_till) {
3067 ALLOC(r->ek.renew_till);
3068 *r->ek.renew_till = *r->et.renew_till;
954c0172 3069 }
40b65c84
SM
3070 ret = copy_Realm(&rep->ticket.realm, &r->ek.srealm);
3071 if (ret)
3072 goto out;
3073 ret = copy_PrincipalName(&rep->ticket.sname, &r->ek.sname);
3074 if (ret)
3075 goto out;
3076 if(r->et.caddr){
3077 ALLOC(r->ek.caddr);
3078 copy_HostAddresses(r->et.caddr, r->ek.caddr);
954c0172
HIU
3079 }
3080
40b65c84 3081 /*
b12a33e2 3082 * Check session and reply keys
40b65c84 3083 */
533024be 3084
40b65c84
SM
3085 if (r->session_key.keytype == ETYPE_NULL) {
3086 ret = krb5_generate_random_keyblock(r->context, r->sessionetype, &r->session_key);
9b261c00
AB
3087 if (ret)
3088 goto out;
89eaef02
AB
3089 }
3090
40b65c84 3091 if (r->reply_key.keytype == ETYPE_NULL) {
b12a33e2 3092 _kdc_set_e_text(r, "Client has no reply key");
9b261c00
AB
3093 ret = KRB5KDC_ERR_CLIENT_NOTYET;
3094 goto out;
3095 }
3096
40b65c84 3097 ret = copy_EncryptionKey(&r->session_key, &r->et.key);
9b261c00
AB
3098 if (ret)
3099 goto out;
954c0172 3100
40b65c84
SM
3101 ret = copy_EncryptionKey(&r->session_key, &r->ek.key);
3102 if (ret)
3103 goto out;
954c0172 3104
51569b31 3105 if (r->client->flags.synthetic) {
40b65c84
SM
3106 ret = add_synthetic_princ_ad(r);
3107 if (ret)
f7242f64 3108 goto out;
918c7634
AB
3109 }
3110
40b65c84
SM
3111 _kdc_log_timestamp(r, "AS-REQ", r->et.authtime,
3112 r->et.starttime, r->et.endtime,
3113 r->et.renew_till);
3c1e780e 3114
40b65c84 3115 _log_astgs_req(r, setype);
89eaef02 3116
40b65c84
SM
3117 /*
3118 * We always say we support FAST/enc-pa-rep
3119 */
3c1e780e 3120
40b65c84 3121 r->et.flags.enc_pa_rep = r->ek.flags.enc_pa_rep = 1;
3c1e780e 3122
40b65c84
SM
3123 /*
3124 * update reply-key with strengthen-key
3125 */
f7242f64 3126
40b65c84
SM
3127 ret = _kdc_fast_strengthen_reply_key(r);
3128 if (ret)
3129 goto out;
978bc868 3130
40b65c84
SM
3131 /*
3132 * Add REQ_ENC_PA_REP if client supports it
3133 */
978bc868 3134
40b65c84
SM
3135 i = 0;
3136 pa = _kdc_find_padata(req, &i, KRB5_PADATA_REQ_ENC_PA_REP);
3137 if (pa) {
978bc868 3138
40b65c84 3139 ret = add_enc_pa_rep(r);
978bc868 3140 if (ret) {
40b65c84
SM
3141 msg = krb5_get_error_message(r->context, ret);
3142 _kdc_r_log(r, 4, "add_enc_pa_rep failed: %s: %d", msg, ret);
3143 krb5_free_error_message(r->context, msg);
3144 goto out;
978bc868 3145 }
40b65c84 3146 }
978bc868 3147
09bcd48f
JS
3148 /* Add the PAC */
3149 if (!r->et.flags.anonymous) {
3150 ret = generate_pac(r, skey, krbtgt_key, is_tgs);
3151 if (ret)
3152 goto out;
3153 }
3154
3155 /*
3156 * No more changes to the ticket (r->et) from this point on, lest
3157 * the checksums in the PAC be invalidated.
3158 */
3159
40b65c84
SM
3160 /*
3161 * Last chance for plugins to update reply
3162 */
3163 ret = _kdc_finalize_reply(r);
3164 if (ret)
3165 goto out;
978bc868 3166
40b65c84
SM
3167 /*
3168 * Don't send kvno from client entry if the pre-authentication
3169 * mechanism replaced the reply key.
3170 */
978bc868 3171
40b65c84
SM
3172 ret = _kdc_encode_reply(r->context, config,
3173 r, req->req_body.nonce, setype,
51569b31
JS
3174 r->server->kvno, &skey->key,
3175 pa_used_flag_isset(r, PA_REPLACE_REPLY_KEY) ? 0 : r->client->kvno,
40b65c84
SM
3176 0, r->reply);
3177 if (ret)
3178 goto out;
978bc868 3179
40b65c84 3180 /*
b12a33e2 3181 * Check if message is too large
40b65c84
SM
3182 */
3183 if (r->datagram_reply && r->reply->length > config->max_datagram_reply_length) {
3184 krb5_data_free(r->reply);
3185 ret = KRB5KRB_ERR_RESPONSE_TOO_BIG;
3186 _kdc_set_e_text(r, "Reply packet too large");
3187 }
978bc868 3188
40b65c84 3189out:
95c02a97
JS
3190 if (ret) {
3191 /* Overwrite ‘error_code’ only if we have an actual error. */
3192 r->error_code = ret;
3193 }
f33f73f8
SM
3194 {
3195 krb5_error_code ret2 = _kdc_audit_request(r);
3196 if (ret2) {
3197 krb5_data_free(r->reply);
3198 ret = ret2;
3199 }
3200 }
51569b31 3201
40b65c84
SM
3202 /*
3203 * In case of a non proxy error, build an error message.
3204 */
f33f73f8
SM
3205 if (ret != 0 && ret != HDB_ERR_NOT_FOUND_HERE && r->reply->length == 0) {
3206 kdc_log(r->context, config, 5, "as-req: sending error: %d to client", ret);
40b65c84
SM
3207 ret = _kdc_fast_mk_error(r,
3208 r->rep.padata,
3209 r->armor_crypto,
3210 &req->req_body,
95c02a97 3211 r->error_code ? r->error_code : ret,
40b65c84
SM
3212 r->client_princ,
3213 r->server_princ,
3214 NULL, NULL,
3215 r->reply);
f33f73f8 3216 }
40b65c84
SM
3217
3218 if (r->pa_used && r->pa_used->cleanup)
3219 r->pa_used->cleanup(r);
3220
3221 free_AS_REP(&r->rep);
3222 free_EncTicketPart(&r->et);
3223 free_EncKDCRepPart(&r->ek);
3224 _kdc_free_fast_state(&r->fast);
3225
3226 if (r->client_princ) {
3227 krb5_free_principal(r->context, r->client_princ);
3228 r->client_princ = NULL;
3229 }
3230 if (r->server_princ){
3231 krb5_free_principal(r->context, r->server_princ);
3232 r->server_princ = NULL;
3233 }
3234 if (r->client)
51569b31 3235 _kdc_free_ent(r->context, r->clientdb, r->client);
40b65c84 3236 if (r->server)
51569b31
JS
3237 _kdc_free_ent(r->context, r->serverdb, r->server);
3238 if (r->krbtgt)
3239 _kdc_free_ent(r->context, r->krbtgtdb, r->krbtgt);
40b65c84
SM
3240 if (r->armor_crypto) {
3241 krb5_crypto_destroy(r->context, r->armor_crypto);
3242 r->armor_crypto = NULL;
3243 }
3244 if (r->armor_ticket)
3245 krb5_free_ticket(r->context, r->armor_ticket);
3246 if (r->armor_server)
51569b31 3247 _kdc_free_ent(r->context, r->armor_serverdb, r->armor_server);
40b65c84 3248 krb5_free_keyblock_contents(r->context, &r->reply_key);
75ec66c7 3249 krb5_free_keyblock_contents(r->context, &r->enc_ad_key);
40b65c84
SM
3250 krb5_free_keyblock_contents(r->context, &r->session_key);
3251 krb5_free_keyblock_contents(r->context, &r->strengthen_key);
3252 krb5_pac_free(r->context, r->pac);
978bc868 3253
40b65c84 3254 return ret;
978bc868 3255}