Line data Source code
1 : /*
2 : * Copyright (c) 1997-2007 Kungliga Tekniska Högskolan
3 : * (Royal Institute of Technology, Stockholm, Sweden).
4 : * All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions
8 : * are met:
9 : *
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : *
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.
16 : *
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.
20 : *
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.
32 : */
33 :
34 : #include "kdc_locl.h"
35 :
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
52 :
53 : #undef __attribute__
54 : #define __attribute__(X)
55 :
56 : void
57 82146 : _kdc_fix_time(time_t **t)
58 : {
59 82146 : if(*t == NULL){
60 0 : ALLOC(*t);
61 0 : **t = MAX_TIME;
62 : }
63 82146 : if(**t == 0) **t = MAX_TIME; /* fix for old clients */
64 82146 : }
65 :
66 : static int
67 46636 : realloc_method_data(METHOD_DATA *md)
68 : {
69 1764 : PA_DATA *pa;
70 46636 : pa = realloc(md->val, (md->len + 1) * sizeof(*md->val));
71 46636 : if(pa == NULL)
72 0 : return ENOMEM;
73 46636 : md->val = pa;
74 46636 : md->len++;
75 46636 : return 0;
76 : }
77 :
78 : static krb5_error_code
79 : get_pa_etype_info2(krb5_context context,
80 : krb5_kdc_configuration *config,
81 : METHOD_DATA *md, Key *ckey,
82 : krb5_boolean include_salt);
83 :
84 : static krb5_error_code
85 29620 : set_salt_padata(krb5_context context,
86 : krb5_kdc_configuration *config,
87 : METHOD_DATA *md, Key *key)
88 : {
89 29620 : if (!key->salt)
90 1254 : return 0;
91 :
92 28354 : return get_pa_etype_info2(context, config, md, key, TRUE);
93 : }
94 :
95 : const PA_DATA*
96 508573 : _kdc_find_padata(const KDC_REQ *req, int *start, int type)
97 : {
98 508573 : if (req->padata == NULL)
99 5782 : return NULL;
100 :
101 1005909 : while((size_t)*start < req->padata->len){
102 702699 : (*start)++;
103 702699 : if(req->padata->val[*start - 1].padata_type == (unsigned)type)
104 199581 : return &req->padata->val[*start - 1];
105 : }
106 292170 : return NULL;
107 : }
108 :
109 : /*
110 : * This is a hack to allow predefined weak services, like afs to
111 : * still use weak types
112 : */
113 :
114 : krb5_boolean
115 0 : _kdc_is_weak_exception(krb5_principal principal, krb5_enctype etype)
116 : {
117 0 : if (principal->name.name_string.len > 0 &&
118 0 : strcmp(principal->name.name_string.val[0], "afs") == 0 &&
119 : (etype == ETYPE_DES_CBC_CRC
120 0 : || etype == ETYPE_DES_CBC_MD4
121 0 : || etype == ETYPE_DES_CBC_MD5))
122 0 : return TRUE;
123 0 : return FALSE;
124 : }
125 :
126 :
127 : /*
128 : * Detect if `key' is the using the the precomputed `default_salt'.
129 : */
130 :
131 : static krb5_boolean
132 18282 : is_default_salt_p(const krb5_salt *default_salt, const Key *key)
133 : {
134 18282 : if (key->salt == NULL)
135 1001 : return TRUE;
136 17278 : if (default_salt->salttype != key->salt->type)
137 0 : return FALSE;
138 17278 : if (krb5_data_cmp(&default_salt->saltvalue, &key->salt->salt) != 0)
139 4364 : return FALSE;
140 12428 : return TRUE;
141 : }
142 :
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 :
152 : static krb5_boolean
153 18282 : is_good_salt_p(const krb5_salt *default_salt, const Key *key)
154 : {
155 18282 : if (key->key.keytype == KRB5_ENCTYPE_DES_CBC_CRC)
156 0 : return is_default_salt_p(default_salt, key);
157 :
158 17690 : return TRUE;
159 : }
160 :
161 : krb5_boolean
162 29935 : _kdc_is_anon_request(const KDC_REQ *req)
163 : {
164 29935 : 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 58582 : return b->kdc_options.request_anonymous ||
174 29831 : (b->kdc_options.cname_in_addl_tkt && !b->additional_tickets);
175 : }
176 :
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
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.
191 : */
192 :
193 : krb5_error_code
194 18284 : _kdc_find_etype(astgs_request_t r, uint32_t flags,
195 : krb5_enctype *etypes, unsigned len,
196 : krb5_enctype *ret_enctype, Key **ret_key,
197 : krb5_boolean *ret_default_salt)
198 : {
199 592 : krb5_boolean use_strongest_session_key;
200 18284 : krb5_boolean is_preauth = flags & KFE_IS_PREAUTH;
201 18284 : krb5_boolean is_tgs = flags & KFE_IS_TGS;
202 592 : hdb_entry *princ;
203 592 : krb5_principal request_princ;
204 592 : krb5_error_code ret;
205 592 : krb5_salt def_salt;
206 18284 : krb5_enctype enctype = ETYPE_NULL;
207 592 : const krb5_enctype *p;
208 18284 : Key *key = NULL;
209 592 : size_t i, k, m;
210 :
211 18284 : if (is_preauth && (flags & KFE_USE_CLIENT) &&
212 18284 : r->client->flags.synthetic)
213 0 : return KRB5KDC_ERR_ETYPE_NOSUPP;
214 :
215 18284 : if ((flags & KFE_USE_CLIENT) && !r->client->flags.synthetic) {
216 18284 : princ = r->client;
217 18284 : request_princ = r->client_princ;
218 : } else {
219 0 : princ = r->server;
220 0 : request_princ = r->server->principal;
221 : }
222 :
223 18876 : use_strongest_session_key =
224 18284 : is_preauth ? r->config->preauth_use_strongest_session_key
225 18284 : : (is_tgs ? r->config->tgt_use_strongest_session_key :
226 0 : r->config->svc_use_strongest_session_key);
227 :
228 : /* We'll want to avoid keys with v4 salted keys in the pre-auth case... */
229 18284 : ret = krb5_get_pw_salt(r->context, request_princ, &def_salt);
230 18284 : if (ret)
231 0 : return ret;
232 :
233 18284 : ret = KRB5KDC_ERR_ETYPE_NOSUPP;
234 :
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 : */
249 :
250 18284 : if (use_strongest_session_key) {
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
259 : * with different supported enctype lists sharing the same ccache.
260 : */
261 :
262 : /* drive the search with local supported enctypes list */
263 18284 : p = krb5_kerberos_enctypes(r->context);
264 18284 : for (i = 0;
265 42057 : p[i] != ETYPE_NULL && enctype == ETYPE_NULL;
266 23773 : i++) {
267 23773 : if (krb5_enctype_valid(r->context, p[i]) != 0 &&
268 0 : !_kdc_is_weak_exception(princ->principal, p[i]))
269 0 : continue;
270 :
271 : /* check that the client supports it too */
272 58130 : for (k = 0; k < len && enctype == ETYPE_NULL; k++) {
273 :
274 34357 : if (p[i] != etypes[k])
275 14737 : continue;
276 :
277 19620 : 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 : */
283 0 : enctype = p[i];
284 0 : ret = 0;
285 0 : break;
286 : }
287 :
288 : /* check target princ support */
289 19620 : key = NULL;
290 19620 : if (!is_preauth && !(flags & KFE_USE_CLIENT) && princ->etypes) {
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 : */
297 0 : for (m = 0; m < princ->etypes->len; m++) {
298 0 : if (p[i] == princ->etypes->val[m]) {
299 0 : enctype = p[i];
300 0 : ret = 0;
301 0 : 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 : */
311 20212 : while (hdb_next_enctype2key(r->context, princ, NULL,
312 37902 : p[i], &key) == 0) {
313 18282 : if (key->key.keyvalue.length == 0) {
314 0 : ret = KRB5KDC_ERR_NULL_KEY;
315 0 : continue;
316 : }
317 18282 : enctype = p[i];
318 18282 : ret = 0;
319 35972 : if (is_preauth && ret_key != NULL &&
320 19481 : !is_good_salt_p(&def_salt, key))
321 0 : continue;
322 : }
323 : }
324 : }
325 : }
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 : */
336 0 : for(i = 0; ret != 0 && i < len; i++) {
337 :
338 0 : if (krb5_enctype_valid(r->context, etypes[i]) != 0 &&
339 0 : !_kdc_is_weak_exception(princ->principal, etypes[i]))
340 0 : continue;
341 :
342 0 : key = NULL;
343 0 : while (ret != 0 &&
344 0 : hdb_next_enctype2key(r->context, princ, NULL,
345 0 : etypes[i], &key) == 0) {
346 0 : if (key->key.keyvalue.length == 0) {
347 0 : ret = KRB5KDC_ERR_NULL_KEY;
348 0 : continue;
349 : }
350 0 : enctype = etypes[i];
351 0 : ret = 0;
352 0 : if (is_preauth && ret_key != NULL &&
353 0 : !is_good_salt_p(&def_salt, key))
354 0 : continue;
355 : }
356 : }
357 : }
358 :
359 18284 : if (ret == 0 && enctype == ETYPE_NULL) {
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 0 : if (ret_key == NULL &&
366 0 : _kdc_is_weak_exception(princ->principal, ETYPE_DES_CBC_CRC)) {
367 0 : ret = 0;
368 0 : enctype = ETYPE_DES_CBC_CRC;
369 : } else {
370 0 : ret = KRB5KDC_ERR_ETYPE_NOSUPP;
371 : }
372 : }
373 :
374 18284 : if (ret == 0) {
375 18282 : if (ret_enctype != NULL)
376 0 : *ret_enctype = enctype;
377 18282 : if (ret_key != NULL)
378 18282 : *ret_key = key;
379 18282 : if (ret_default_salt != NULL)
380 18282 : *ret_default_salt = is_default_salt_p(&def_salt, key);
381 : }
382 :
383 18284 : krb5_free_salt (r->context, def_salt);
384 18284 : return ret;
385 : }
386 :
387 : /*
388 : * The principal's session_etypes must be sorted in order of strength, with
389 : * preferred etype first.
390 : */
391 : krb5_error_code
392 98097 : _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 3448 : size_t i;
398 :
399 98097 : if (princ->session_etypes == NULL) {
400 : /* The principal must have session etypes available. */
401 60 : return KRB5KDC_ERR_ETYPE_NOSUPP;
402 : }
403 :
404 : /* Loop over the client's specified etypes. */
405 107064 : for (i = 0; i < len; ++i) {
406 : size_t j;
407 :
408 : /* Check that the server also supports the etype. */
409 125088 : for (j = 0; j < princ->session_etypes->len; ++j) {
410 116061 : if (princ->session_etypes->val[j] == etypes[i]) {
411 97814 : *ret_enctype = etypes[i];
412 97814 : return 0;
413 : }
414 : }
415 : }
416 :
417 223 : return KRB5KDC_ERR_ETYPE_NOSUPP;
418 : }
419 :
420 : krb5_error_code
421 42761 : _kdc_make_anonymous_principalname (PrincipalName *pn)
422 : {
423 42761 : pn->name_type = KRB5_NT_WELLKNOWN;
424 42761 : pn->name_string.len = 2;
425 42761 : pn->name_string.val = calloc(2, sizeof(*pn->name_string.val));
426 42761 : if (pn->name_string.val == NULL)
427 0 : goto failed;
428 :
429 42761 : pn->name_string.val[0] = strdup(KRB5_WELLKNOWN_NAME);
430 42761 : if (pn->name_string.val[0] == NULL)
431 0 : goto failed;
432 :
433 42761 : pn->name_string.val[1] = strdup(KRB5_ANON_NAME);
434 42761 : if (pn->name_string.val[1] == NULL)
435 0 : goto failed;
436 :
437 41089 : return 0;
438 :
439 0 : failed:
440 0 : free_PrincipalName(pn);
441 :
442 0 : pn->name_type = KRB5_NT_UNKNOWN;
443 0 : pn->name_string.len = 0;
444 0 : pn->name_string.val = NULL;
445 :
446 0 : return ENOMEM;
447 : }
448 :
449 : static void
450 182406 : _kdc_r_log(astgs_request_t r, int level, const char *fmt, ...)
451 : __attribute__ ((__format__ (__printf__, 3, 4)))
452 : {
453 6896 : va_list ap;
454 6896 : char *s;
455 182406 : va_start(ap, fmt);
456 182406 : s = kdc_log_msg_va(r->context, r->config, level, fmt, ap);
457 182406 : if(s) free(s);
458 182406 : va_end(ap);
459 182406 : }
460 :
461 : void
462 4 : _kdc_set_const_e_text(astgs_request_t r, const char *e_text)
463 : {
464 : /* We should never see this */
465 4 : if (r->e_text) {
466 0 : kdc_log(r->context, r->config, 1,
467 : "trying to replace e-text \"%s\" with \"%s\"\n",
468 : r->e_text, e_text);
469 0 : return;
470 : }
471 :
472 4 : r->e_text = e_text;
473 4 : kdc_log(r->context, r->config, 4, "%s", e_text);
474 : }
475 :
476 : void
477 30108 : _kdc_set_e_text(astgs_request_t r, const char *fmt, ...)
478 : __attribute__ ((__format__ (__printf__, 2, 3)))
479 : {
480 1184 : va_list ap;
481 30108 : char *e_text = NULL;
482 1184 : int vasprintf_ret;
483 :
484 30108 : va_start(ap, fmt);
485 30108 : vasprintf_ret = vasprintf(&e_text, fmt, ap);
486 30108 : va_end(ap);
487 :
488 30108 : if (vasprintf_ret < 0 || !e_text) {
489 : /* not much else to do... */
490 0 : kdc_log(r->context, r->config, 1,
491 : "Could not set e_text: %s (out of memory)", fmt);
492 0 : return;
493 : }
494 :
495 : /* We should never see this */
496 30108 : if (r->e_text) {
497 0 : kdc_log(r->context, r->config, 1, "trying to replace e-text: %s\n",
498 : e_text);
499 0 : free(e_text);
500 0 : return;
501 : }
502 :
503 30108 : r->e_text = e_text;
504 30108 : r->e_text_buf = e_text;
505 30108 : kdc_log(r->context, r->config, 4, "%s", e_text);
506 : }
507 :
508 : void
509 78965 : _kdc_log_timestamp(astgs_request_t r, const char *type,
510 : KerberosTime authtime, KerberosTime *starttime,
511 : KerberosTime endtime, KerberosTime *renew_till)
512 : {
513 78965 : krb5_kdc_configuration *config = r->config;
514 2856 : char authtime_str[100], starttime_str[100],
515 : endtime_str[100], renewtime_str[100];
516 :
517 78965 : if (authtime)
518 78965 : kdc_audit_setkv_number((kdc_request_t)r, "auth", authtime);
519 78965 : if (starttime && *starttime)
520 49305 : kdc_audit_setkv_number((kdc_request_t)r, "start", *starttime);
521 78965 : if (endtime)
522 78965 : kdc_audit_setkv_number((kdc_request_t)r, "end", endtime);
523 78965 : if (renew_till && *renew_till)
524 6263 : kdc_audit_setkv_number((kdc_request_t)r, "renew", *renew_till);
525 :
526 78965 : krb5_format_time(r->context, authtime,
527 : authtime_str, sizeof(authtime_str), TRUE);
528 78965 : if (starttime)
529 49305 : krb5_format_time(r->context, *starttime,
530 : starttime_str, sizeof(starttime_str), TRUE);
531 : else
532 29660 : strlcpy(starttime_str, "unset", sizeof(starttime_str));
533 78965 : krb5_format_time(r->context, endtime,
534 : endtime_str, sizeof(endtime_str), TRUE);
535 78965 : if (renew_till)
536 6263 : krb5_format_time(r->context, *renew_till,
537 : renewtime_str, sizeof(renewtime_str), TRUE);
538 : else
539 72702 : strlcpy(renewtime_str, "unset", sizeof(renewtime_str));
540 :
541 78965 : kdc_log(r->context, config, 4,
542 : "%s authtime: %s starttime: %s endtime: %s renew till: %s",
543 : type, authtime_str, starttime_str, endtime_str, renewtime_str);
544 78965 : }
545 :
546 : /*
547 : *
548 : */
549 :
550 : #ifdef PKINIT
551 :
552 : static krb5_error_code
553 61 : pa_pkinit_validate(astgs_request_t r, const PA_DATA *pa)
554 : {
555 61 : pk_client_params *pkp = NULL;
556 61 : char *client_cert = NULL;
557 0 : krb5_error_code ret;
558 :
559 61 : ret = _kdc_pk_rd_padata(r, pa, &pkp);
560 61 : if (ret || pkp == NULL) {
561 2 : if (ret == HX509_CERT_REVOKED) {
562 2 : ret = KRB5_KDC_ERR_CLIENT_NOT_TRUSTED;
563 : } else {
564 0 : ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
565 : }
566 2 : _kdc_r_log(r, 4, "Failed to decode PKINIT PA-DATA -- %s",
567 : r->cname);
568 2 : goto out;
569 : }
570 :
571 : /* Validate the freshness token. */
572 59 : ret = _kdc_pk_validate_freshness_token(r, pkp);
573 59 : if (ret) {
574 12 : _kdc_r_log(r, 4, "Failed to validate freshness token");
575 12 : goto out;
576 : }
577 :
578 47 : ret = _kdc_pk_check_client(r, pkp, &client_cert);
579 47 : if (client_cert)
580 45 : kdc_audit_addkv((kdc_request_t)r, 0, KDC_REQUEST_KV_PKINIT_CLIENT_CERT,
581 : "%s", client_cert);
582 47 : if (ret) {
583 2 : _kdc_set_e_text(r, "PKINIT certificate not allowed to "
584 : "impersonate principal");
585 2 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
586 : KDC_AUTH_EVENT_CLIENT_NAME_UNAUTHORIZED);
587 2 : goto out;
588 : }
589 :
590 45 : r->pa_endtime = _kdc_pk_endtime(pkp);
591 45 : if (!r->client->flags.synthetic)
592 45 : r->pa_max_life = _kdc_pk_max_life(pkp);
593 :
594 45 : _kdc_r_log(r, 4, "PKINIT pre-authentication succeeded -- %s using %s",
595 : r->cname, client_cert);
596 :
597 45 : ret = _kdc_pk_mk_pa_reply(r, pkp);
598 45 : if (ret) {
599 0 : _kdc_set_e_text(r, "Failed to build PK-INIT reply");
600 0 : goto out;
601 : }
602 45 : ret = _kdc_add_initial_verified_cas(r->context, r->config,
603 : pkp, &r->et);
604 :
605 45 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
606 : KDC_AUTH_EVENT_PREAUTH_SUCCEEDED);
607 :
608 : /*
609 : * Match Windows by preferring the authenticator nonce over the one in the
610 : * request body.
611 : */
612 45 : r->ek.nonce = _kdc_pk_nonce(pkp);
613 :
614 61 : out:
615 61 : if (pkp)
616 59 : _kdc_pk_free_client_param(r->context, pkp);
617 61 : free(client_cert);
618 :
619 61 : return ret;
620 : }
621 :
622 : #endif /* PKINIT */
623 :
624 : static krb5_error_code
625 0 : pa_gss_validate(astgs_request_t r, const PA_DATA *pa)
626 : {
627 0 : gss_client_params *gcp = NULL;
628 0 : char *client_name = NULL;
629 0 : krb5_error_code ret;
630 0 : int open = 0;
631 :
632 0 : ret = _kdc_gss_rd_padata(r, pa, &gcp, &open);
633 0 : if (ret && gcp == NULL)
634 0 : return ret;
635 :
636 0 : if (open) {
637 0 : ret = _kdc_gss_check_client(r, gcp, &client_name);
638 0 : if (client_name)
639 0 : kdc_audit_addkv((kdc_request_t)r, 0, KDC_REQUEST_KV_GSS_INITIATOR,
640 : "%s", client_name);
641 0 : if (ret) {
642 0 : _kdc_set_e_text(r, "GSS-API client not allowed to "
643 : "impersonate principal");
644 0 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
645 : KDC_AUTH_EVENT_CLIENT_NAME_UNAUTHORIZED);
646 0 : goto out;
647 : }
648 :
649 0 : r->pa_endtime = _kdc_gss_endtime(r, gcp);
650 :
651 0 : _kdc_r_log(r, 4, "GSS pre-authentication succeeded -- %s using %s",
652 : r->cname, client_name);
653 0 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
654 : KDC_AUTH_EVENT_PREAUTH_SUCCEEDED);
655 :
656 0 : ret = _kdc_gss_mk_composite_name_ad(r, gcp);
657 0 : if (ret) {
658 0 : _kdc_set_e_text(r, "Failed to build GSS authorization data");
659 0 : goto out;
660 : }
661 : }
662 :
663 0 : ret = _kdc_gss_mk_pa_reply(r, gcp);
664 0 : if (ret) {
665 0 : if (ret != KRB5_KDC_ERR_MORE_PREAUTH_DATA_REQUIRED)
666 0 : _kdc_set_e_text(r, "Failed to build GSS pre-authentication reply");
667 0 : goto out;
668 : }
669 :
670 0 : ret = kdc_request_set_attribute((kdc_request_t)r,
671 0 : HSTR("org.h5l.pa-gss-client-params"), gcp);
672 0 : if (ret)
673 0 : goto out;
674 :
675 0 : out:
676 0 : kdc_object_release(gcp);
677 0 : free(client_name);
678 :
679 0 : return ret;
680 : }
681 :
682 : static krb5_error_code
683 0 : pa_gss_finalize_pac(astgs_request_t r)
684 : {
685 0 : gss_client_params *gcp;
686 :
687 0 : gcp = kdc_request_get_attribute((kdc_request_t)r, HSTR("org.h5l.pa-gss-client-params"));
688 :
689 0 : heim_assert(gcp != NULL, "invalid GSS-API client params");
690 :
691 0 : return _kdc_gss_finalize_pac(r, gcp);
692 : }
693 :
694 : static krb5_error_code
695 166 : pa_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)
704 : {
705 166 : unsigned int invalidKeys = 0;
706 0 : krb5_error_code ret;
707 166 : const Keys *keys = NULL;
708 0 : unsigned int i;
709 :
710 166 : if (KDCchallengekey)
711 166 : krb5_keyblock_zero(KDCchallengekey);
712 166 : if (used_key)
713 166 : *used_key = NULL;
714 :
715 166 : keys = hdb_kvno2keys(r->context, r->client, kvno);
716 166 : if (keys == NULL) {
717 0 : return KRB5KDC_ERR_ETYPE_NOSUPP;
718 : }
719 :
720 172 : for (i = 0; i < keys->len; i++) {
721 170 : struct Key *k = &keys->val[i];
722 0 : krb5_crypto challengecrypto, longtermcrypto;
723 0 : krb5_keyblock client_challengekey;
724 :
725 170 : ret = krb5_crypto_init(r->context, &k->key, 0, &longtermcrypto);
726 170 : if (ret)
727 6 : continue;
728 :
729 170 : ret = krb5_crypto_fx_cf2(r->context, r->armor_crypto, longtermcrypto,
730 : pepper1client, pepper2, aenctype,
731 : &client_challengekey);
732 170 : if (ret) {
733 0 : krb5_crypto_destroy(r->context, longtermcrypto);
734 0 : continue;
735 : }
736 :
737 170 : ret = krb5_crypto_init(r->context, &client_challengekey, 0,
738 : &challengecrypto);
739 170 : krb5_free_keyblock_contents(r->context, &client_challengekey);
740 170 : if (ret) {
741 0 : krb5_crypto_destroy(r->context, longtermcrypto);
742 0 : continue;
743 : }
744 :
745 170 : ret = _krb5_validate_pa_enc_challenge(r->context,
746 : challengecrypto,
747 : KRB5_KU_ENC_CHALLENGE_CLIENT,
748 : enc_data,
749 170 : r->cname);
750 170 : krb5_crypto_destroy(r->context, challengecrypto);
751 170 : if (ret) {
752 0 : const char *msg;
753 0 : krb5_error_code ret2;
754 7 : char *str = NULL;
755 :
756 7 : krb5_crypto_destroy(r->context, longtermcrypto);
757 :
758 7 : if (ret != KRB5KRB_AP_ERR_BAD_INTEGRITY)
759 1 : return ret;
760 :
761 6 : invalidKeys += 1;
762 :
763 6 : if (pepper1kdc == NULL)
764 : /* The caller is not interessted in details */
765 6 : continue;
766 :
767 6 : ret2 = krb5_enctype_to_string(r->context, k->key.keytype, &str);
768 6 : if (ret2)
769 0 : str = NULL;
770 6 : msg = krb5_get_error_message(r->context, ret);
771 6 : _kdc_r_log(r, 2, "Failed to decrypt ENC-CHAL -- %s "
772 : "(enctype %s) error %s",
773 6 : r->cname, str ? str : "unknown enctype", msg);
774 6 : krb5_free_error_message(r->context, msg);
775 6 : free(str);
776 :
777 6 : continue;
778 : }
779 :
780 163 : if (pepper1kdc == NULL) {
781 : /* The caller is not interessted in details */
782 0 : return 0;
783 : }
784 :
785 163 : heim_assert(KDCchallengekey != NULL,
786 : "KDCchallengekey pointer required with pepper1kdc");
787 163 : heim_assert(used_key != NULL,
788 : "used_key pointer required with pepper1kdc");
789 :
790 : /*
791 : * Provide KDC authentication to the client, uses a different
792 : * challenge key (different pepper).
793 : */
794 :
795 163 : ret = krb5_crypto_fx_cf2(r->context, r->armor_crypto, longtermcrypto,
796 : pepper1kdc, pepper2, aenctype,
797 : KDCchallengekey);
798 163 : krb5_crypto_destroy(r->context, longtermcrypto);
799 163 : if (ret)
800 0 : return ret;
801 :
802 163 : *used_key = k;
803 163 : return 0;
804 : }
805 :
806 2 : if (invalidKeys == 0)
807 0 : return KRB5KDC_ERR_ETYPE_NOSUPP;
808 :
809 2 : return KRB5KDC_ERR_PREAUTH_FAILED;
810 : }
811 :
812 : static krb5_error_code
813 166 : pa_enc_chal_validate(astgs_request_t r, const PA_DATA *pa)
814 : {
815 166 : krb5_kvno kvno = r->client->kvno;
816 0 : krb5_data pepper1client, pepper1kdc, pepper2;
817 0 : EncryptedData enc_data;
818 0 : krb5_enctype aenctype;
819 0 : krb5_error_code ret;
820 0 : krb5_keyblock KDCchallengekey;
821 166 : struct Key *k = NULL;
822 0 : size_t size;
823 :
824 166 : heim_assert(r->armor_crypto != NULL, "ENC-CHAL called for non FAST");
825 :
826 166 : if (_kdc_is_anon_request(&r->req)) {
827 0 : ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
828 0 : kdc_log(r->context, r->config, 4, "ENC-CHAL doesn't support anon");
829 0 : return ret;
830 : }
831 :
832 166 : if (r->client->flags.locked_out) {
833 0 : ret = KRB5KDC_ERR_CLIENT_REVOKED;
834 0 : kdc_log(r->context, r->config, 0,
835 : "Client (%s) is locked out", r->cname);
836 0 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
837 : KDC_AUTH_EVENT_CLIENT_LOCKED_OUT);
838 0 : return ret;
839 : }
840 :
841 166 : ret = decode_EncryptedData(pa->padata_value.data,
842 166 : pa->padata_value.length,
843 : &enc_data,
844 : &size);
845 166 : if (ret) {
846 0 : ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
847 0 : _kdc_r_log(r, 4, "Failed to decode PA-DATA -- %s",
848 : r->cname);
849 0 : return ret;
850 : }
851 :
852 166 : pepper1client.data = "clientchallengearmor";
853 166 : pepper1client.length = strlen(pepper1client.data);
854 166 : pepper1kdc.data = "kdcchallengearmor";
855 166 : pepper1kdc.length = strlen(pepper1kdc.data);
856 166 : pepper2.data = "challengelongterm";
857 166 : pepper2.length = strlen(pepper2.data);
858 :
859 166 : krb5_crypto_getenctype(r->context, r->armor_crypto, &aenctype);
860 :
861 166 : kdc_log(r->context, r->config, 5, "FAST armor enctype is: %d", (int)aenctype);
862 :
863 166 : ret = pa_enc_chal_decrypt_kvno(r, aenctype,
864 : &pepper1client,
865 : &pepper1kdc,
866 : &pepper2,
867 : kvno,
868 : &enc_data,
869 : &KDCchallengekey,
870 : &k);
871 166 : if (ret == KRB5KDC_ERR_ETYPE_NOSUPP) {
872 0 : char *estr;
873 0 : _kdc_set_e_text(r, "No key matching entype");
874 0 : if(krb5_enctype_to_string(r->context, enc_data.etype, &estr))
875 0 : estr = NULL;
876 0 : if(estr == NULL)
877 0 : _kdc_r_log(r, 4,
878 : "No client key matching ENC-CHAL (%d) -- %s",
879 0 : enc_data.etype, r->cname);
880 : else
881 0 : _kdc_r_log(r, 4,
882 : "No client key matching ENC-CHAL (%s) -- %s",
883 : estr, r->cname);
884 0 : free(estr);
885 0 : free_EncryptedData(&enc_data);
886 0 : kdc_audit_setkv_number((kdc_request_t)r,
887 : KDC_REQUEST_KV_PA_FAILED_KVNO,
888 : kvno);
889 0 : return ret;
890 : }
891 166 : 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 1 : free_EncryptedData(&enc_data);
899 1 : 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 1 : r->e_text = NULL;
908 1 : return ret;
909 : }
910 165 : if (ret == KRB5KDC_ERR_PREAUTH_FAILED) {
911 2 : krb5_error_code hret = ret;
912 0 : int hi;
913 :
914 : /*
915 : * Logging happens inside of
916 : * via pa_enc_chal_decrypt_kvno()
917 : */
918 :
919 2 : 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 2 : for (hi = 1; hi < 3; hi++) {
928 0 : krb5_kvno hkvno;
929 :
930 2 : if (hi >= kvno) {
931 2 : break;
932 : }
933 :
934 0 : hkvno = kvno - hi;
935 0 : 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 0 : if (hret == 0) {
944 0 : kdc_audit_setkv_number((kdc_request_t)r,
945 : KDC_REQUEST_KV_PA_HISTORIC_KVNO,
946 : hkvno);
947 0 : break;
948 : }
949 0 : if (hret == KRB5KDC_ERR_ETYPE_NOSUPP) {
950 0 : break;
951 : }
952 : }
953 :
954 2 : free_EncryptedData(&enc_data);
955 :
956 2 : if (hret == 0)
957 0 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
958 : KDC_AUTH_EVENT_HISTORIC_LONG_TERM_KEY);
959 : else
960 2 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
961 : KDC_AUTH_EVENT_WRONG_LONG_TERM_KEY);
962 :
963 2 : return ret;
964 : }
965 163 : free_EncryptedData(&enc_data);
966 163 : if (ret == 0) {
967 0 : krb5_crypto challengecrypto;
968 163 : char *estr = NULL;
969 163 : char *astr = NULL;
970 163 : char *kstr = NULL;
971 :
972 163 : ret = krb5_crypto_init(r->context, &KDCchallengekey, 0, &challengecrypto);
973 163 : krb5_free_keyblock_contents(r->context, &KDCchallengekey);
974 163 : if (ret)
975 0 : return ret;
976 :
977 163 : ret = _krb5_make_pa_enc_challenge(r->context, challengecrypto,
978 : KRB5_KU_ENC_CHALLENGE_KDC,
979 : r->rep.padata);
980 163 : krb5_crypto_destroy(r->context, challengecrypto);
981 163 : if (ret)
982 0 : return ret;
983 :
984 163 : ret = set_salt_padata(r->context, r->config, r->rep.padata, k);
985 163 : if (ret)
986 0 : return ret;
987 :
988 : /*
989 : * Found a key that the client used, lets pick that as the reply key
990 : */
991 :
992 163 : krb5_free_keyblock_contents(r->context, &r->reply_key);
993 163 : ret = krb5_copy_keyblock_contents(r->context, &k->key, &r->reply_key);
994 163 : if (ret)
995 0 : return ret;
996 :
997 163 : if (krb5_enctype_to_string(r->context, (int)aenctype, &astr))
998 0 : astr = NULL;
999 163 : if (krb5_enctype_to_string(r->context, enc_data.etype, &estr))
1000 0 : estr = NULL;
1001 163 : if (krb5_enctype_to_string(r->context, k->key.keytype, &kstr))
1002 0 : kstr = NULL;
1003 489 : _kdc_r_log(r, 4, "ENC-CHAL Pre-authentication succeeded -- %s "
1004 : "using armor=%s enc=%s key=%s",
1005 : r->cname,
1006 163 : astr ? astr : "unknown enctype",
1007 163 : estr ? estr : "unknown enctype",
1008 163 : kstr ? kstr : "unknown enctype");
1009 163 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
1010 : KDC_AUTH_EVENT_VALIDATED_LONG_TERM_KEY);
1011 163 : kdc_audit_setkv_number((kdc_request_t)r,
1012 : KDC_REQUEST_KV_PA_SUCCEEDED_KVNO,
1013 : kvno);
1014 163 : return 0;
1015 : }
1016 :
1017 0 : return ret;
1018 : }
1019 :
1020 : static krb5_error_code
1021 30171 : pa_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 1184 : krb5_error_code ret;
1028 1184 : krb5_crypto crypto;
1029 30171 : Key *pa_key = NULL;
1030 30171 : const Keys *keys = NULL;
1031 :
1032 30171 : if (_pa_key)
1033 29863 : *_pa_key = NULL;
1034 :
1035 30171 : krb5_data_zero(ts_data);
1036 :
1037 30171 : keys = hdb_kvno2keys(r->context, r->client, kvno);
1038 30171 : if (keys == NULL) {
1039 158 : return KRB5KDC_ERR_ETYPE_NOSUPP;
1040 : }
1041 31197 : ret = hdb_enctype2key(r->context, r->client, keys,
1042 30013 : enc_data->etype, &pa_key);
1043 30013 : if(ret){
1044 5 : return KRB5KDC_ERR_ETYPE_NOSUPP;
1045 : }
1046 :
1047 30008 : try_next_key:
1048 30008 : ret = krb5_crypto_init(r->context, &pa_key->key, 0, &crypto);
1049 30008 : if (ret) {
1050 0 : const char *msg = krb5_get_error_message(r->context, ret);
1051 0 : _kdc_r_log(r, 4, "krb5_crypto_init failed: %s", msg);
1052 0 : krb5_free_error_message(r->context, msg);
1053 0 : return ret;
1054 : }
1055 :
1056 30008 : ret = krb5_decrypt_EncryptedData(r->context,
1057 : crypto,
1058 : KRB5_KU_PA_ENC_TIMESTAMP,
1059 : enc_data,
1060 : ts_data);
1061 30008 : krb5_crypto_destroy(r->context, crypto);
1062 : /*
1063 : * Since the user might have several keys with the same
1064 : * enctype but with different salting, we need to try all
1065 : * the keys with the same enctype.
1066 : */
1067 30008 : if (ret) {
1068 412 : ret = hdb_next_enctype2key(r->context, r->client, keys,
1069 412 : enc_data->etype, &pa_key);
1070 412 : if (ret == 0)
1071 0 : goto try_next_key;
1072 :
1073 412 : return KRB5KDC_ERR_PREAUTH_FAILED;
1074 : }
1075 :
1076 29596 : if (_pa_key)
1077 29466 : *_pa_key = pa_key;
1078 28412 : return 0;
1079 : }
1080 :
1081 : static krb5_error_code
1082 29864 : pa_enc_ts_validate(astgs_request_t r, const PA_DATA *pa)
1083 : {
1084 29864 : krb5_kvno kvno = r->client->kvno;
1085 1184 : EncryptedData enc_data;
1086 1184 : krb5_error_code ret;
1087 1184 : krb5_data ts_data;
1088 1184 : PA_ENC_TS_ENC p;
1089 1184 : size_t len;
1090 1184 : Key *pa_key;
1091 1184 : char *str;
1092 :
1093 29864 : if (r->armor_crypto && !r->config->enable_armored_pa_enc_timestamp) {
1094 1 : ret = KRB5KDC_ERR_POLICY;
1095 1 : kdc_log(r->context, r->config, 0,
1096 : "Armored encrypted timestamp pre-authentication is disabled");
1097 1 : return ret;
1098 29863 : } else if (!r->armor_crypto && !r->config->enable_unarmored_pa_enc_timestamp) {
1099 0 : ret = KRB5KDC_ERR_POLICY;
1100 0 : kdc_log(r->context, r->config, 0,
1101 : "Unarmored encrypted timestamp pre-authentication is disabled");
1102 0 : return ret;
1103 : }
1104 :
1105 29863 : if (r->client->flags.locked_out) {
1106 0 : ret = KRB5KDC_ERR_CLIENT_REVOKED;
1107 0 : kdc_log(r->context, r->config, 0,
1108 : "Client (%s) is locked out", r->cname);
1109 0 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
1110 : KDC_AUTH_EVENT_CLIENT_LOCKED_OUT);
1111 0 : return ret;
1112 : }
1113 :
1114 31047 : ret = decode_EncryptedData(pa->padata_value.data,
1115 29863 : pa->padata_value.length,
1116 : &enc_data,
1117 : &len);
1118 29863 : if (ret) {
1119 0 : ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1120 0 : _kdc_r_log(r, 4, "Failed to decode PA-DATA -- %s",
1121 : r->cname);
1122 0 : goto out;
1123 : }
1124 :
1125 29863 : ret = pa_enc_ts_decrypt_kvno(r, kvno, &enc_data, &ts_data, &pa_key);
1126 29863 : if (ret == KRB5KDC_ERR_ETYPE_NOSUPP) {
1127 0 : char *estr;
1128 5 : _kdc_set_e_text(r, "No key matching enctype");
1129 5 : if(krb5_enctype_to_string(r->context, enc_data.etype, &estr))
1130 0 : estr = NULL;
1131 5 : if(estr == NULL)
1132 0 : _kdc_r_log(r, 4,
1133 : "No client key matching pa-data (%d) -- %s",
1134 0 : enc_data.etype, r->cname);
1135 : else
1136 5 : _kdc_r_log(r, 4,
1137 : "No client key matching pa-data (%s) -- %s",
1138 : estr, r->cname);
1139 5 : free(estr);
1140 5 : free_EncryptedData(&enc_data);
1141 5 : kdc_audit_setkv_number((kdc_request_t)r,
1142 : KDC_REQUEST_KV_PA_FAILED_KVNO,
1143 : kvno);
1144 5 : goto out;
1145 : }
1146 29858 : if (ret == KRB5KDC_ERR_PREAUTH_FAILED) {
1147 0 : krb5_error_code ret2;
1148 392 : const char *msg = krb5_get_error_message(r->context, ret);
1149 392 : krb5_error_code hret = ret;
1150 0 : int hi;
1151 :
1152 392 : kdc_audit_setkv_number((kdc_request_t)r,
1153 : KDC_REQUEST_KV_PA_FAILED_KVNO,
1154 : kvno);
1155 :
1156 : /*
1157 : * Check if old and older keys are
1158 : * able to decrypt.
1159 : */
1160 412 : for (hi = 1; hi < 3; hi++) {
1161 0 : krb5_kvno hkvno;
1162 :
1163 405 : if (hi >= kvno) {
1164 97 : break;
1165 : }
1166 :
1167 308 : hkvno = kvno - hi;
1168 308 : hret = pa_enc_ts_decrypt_kvno(r, hkvno,
1169 : &enc_data,
1170 : &ts_data,
1171 : NULL); /* pa_key */
1172 308 : if (hret == 0) {
1173 130 : krb5_data_free(&ts_data);
1174 130 : kdc_audit_setkv_number((kdc_request_t)r,
1175 : KDC_REQUEST_KV_PA_HISTORIC_KVNO,
1176 : hkvno);
1177 130 : break;
1178 : }
1179 178 : if (hret == KRB5KDC_ERR_ETYPE_NOSUPP) {
1180 158 : break;
1181 : }
1182 : }
1183 :
1184 392 : ret2 = krb5_enctype_to_string(r->context, enc_data.etype, &str);
1185 392 : if (ret2)
1186 0 : str = NULL;
1187 392 : _kdc_r_log(r, 2, "Failed to decrypt PA-DATA -- %s "
1188 : "(enctype %s) error %s",
1189 392 : r->cname, str ? str : "unknown enctype", msg);
1190 392 : krb5_xfree(str);
1191 392 : krb5_free_error_message(r->context, msg);
1192 392 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_PA_ETYPE,
1193 392 : enc_data.etype);
1194 392 : if (hret == 0)
1195 130 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
1196 : KDC_AUTH_EVENT_HISTORIC_LONG_TERM_KEY);
1197 : else
1198 262 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
1199 : KDC_AUTH_EVENT_WRONG_LONG_TERM_KEY);
1200 :
1201 392 : free_EncryptedData(&enc_data);
1202 :
1203 392 : ret = KRB5KDC_ERR_PREAUTH_FAILED;
1204 392 : goto out;
1205 : }
1206 29466 : free_EncryptedData(&enc_data);
1207 29466 : ret = decode_PA_ENC_TS_ENC(ts_data.data,
1208 : ts_data.length,
1209 : &p,
1210 : &len);
1211 29466 : krb5_data_free(&ts_data);
1212 29466 : if(ret){
1213 0 : ret = KRB5KDC_ERR_PREAUTH_FAILED;
1214 0 : _kdc_r_log(r, 4, "Failed to decode PA-ENC-TS-ENC -- %s",
1215 : r->cname);
1216 0 : goto out;
1217 : }
1218 29466 : if (labs(kdc_time - p.patimestamp) > r->context->max_skew) {
1219 0 : char client_time[100];
1220 :
1221 9 : krb5_format_time(r->context, p.patimestamp,
1222 : client_time, sizeof(client_time), TRUE);
1223 :
1224 9 : ret = KRB5KRB_AP_ERR_SKEW;
1225 9 : _kdc_r_log(r, 4, "Too large time skew, "
1226 : "client time %s is out by %u > %u seconds -- %s",
1227 : client_time,
1228 9 : (unsigned)labs(kdc_time - p.patimestamp),
1229 9 : r->context->max_skew,
1230 : r->cname);
1231 9 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
1232 : KDC_AUTH_EVENT_CLIENT_TIME_SKEW);
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 9 : r->e_text = NULL;
1240 9 : free_PA_ENC_TS_ENC(&p);
1241 9 : goto out;
1242 : }
1243 29457 : free_PA_ENC_TS_ENC(&p);
1244 :
1245 29457 : ret = set_salt_padata(r->context, r->config, r->rep.padata, pa_key);
1246 29445 : if (ret == 0)
1247 29457 : ret = krb5_copy_keyblock_contents(r->context, &pa_key->key, &r->reply_key);
1248 29457 : if (ret)
1249 0 : return ret;
1250 :
1251 29457 : ret = krb5_enctype_to_string(r->context, pa_key->key.keytype, &str);
1252 29457 : if (ret)
1253 0 : str = NULL;
1254 29457 : _kdc_r_log(r, 4, "ENC-TS Pre-authentication succeeded -- %s using %s",
1255 29457 : r->cname, str ? str : "unknown enctype");
1256 29457 : krb5_xfree(str);
1257 29457 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_PA_ETYPE,
1258 29457 : pa_key->key.keytype);
1259 29457 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
1260 : KDC_AUTH_EVENT_VALIDATED_LONG_TERM_KEY);
1261 29457 : kdc_audit_setkv_number((kdc_request_t)r,
1262 : KDC_REQUEST_KV_PA_SUCCEEDED_KVNO,
1263 : kvno);
1264 :
1265 29457 : ret = 0;
1266 :
1267 28679 : out:
1268 :
1269 28679 : return ret;
1270 : }
1271 :
1272 : #ifdef PKINIT
1273 :
1274 : static krb5_error_code
1275 4 : make_freshness_token(astgs_request_t r, const Key *krbtgt_key, unsigned krbtgt_kvno)
1276 : {
1277 4 : krb5_error_code ret = 0;
1278 4 : const struct timeval current_kdc_time = krb5_kdc_get_time();
1279 4 : int usec = current_kdc_time.tv_usec;
1280 4 : const PA_ENC_TS_ENC ts_enc = {
1281 4 : .patimestamp = current_kdc_time.tv_sec,
1282 : .pausec = &usec,
1283 : };
1284 4 : unsigned char *encoded_ts_enc = NULL;
1285 0 : size_t ts_enc_size;
1286 4 : size_t ts_enc_len = 0;
1287 0 : EncryptedData encdata;
1288 0 : krb5_crypto crypto;
1289 4 : unsigned char *token = NULL;
1290 0 : size_t token_size;
1291 4 : size_t token_len = 0;
1292 0 : size_t token_alloc_size;
1293 :
1294 4 : 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 4 : if (ret)
1301 0 : return ret;
1302 4 : if (ts_enc_size != ts_enc_len)
1303 0 : krb5_abortx(r->context, "internal error in ASN.1 encoder");
1304 :
1305 4 : ret = krb5_crypto_init(r->context, &krbtgt_key->key, 0, &crypto);
1306 4 : if (ret) {
1307 0 : free(encoded_ts_enc);
1308 0 : return ret;
1309 : }
1310 :
1311 4 : 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 4 : free(encoded_ts_enc);
1319 4 : krb5_crypto_destroy(r->context, crypto);
1320 4 : if (ret)
1321 0 : return ret;
1322 :
1323 4 : token_size = length_EncryptedData(&encdata);
1324 4 : token_alloc_size = token_size + 2; /* Account for the two leading zero bytes. */
1325 4 : token = calloc(1, token_alloc_size);
1326 4 : if (token == NULL) {
1327 0 : free_EncryptedData(&encdata);
1328 0 : return ENOMEM;
1329 : }
1330 :
1331 4 : ret = encode_EncryptedData(token + token_alloc_size - 1,
1332 : token_size,
1333 : &encdata,
1334 : &token_len);
1335 4 : free_EncryptedData(&encdata);
1336 4 : if (ret) {
1337 0 : free(token);
1338 0 : return ret;
1339 : }
1340 4 : if (token_size != token_len)
1341 0 : krb5_abortx(r->context, "internal error in ASN.1 encoder");
1342 :
1343 4 : ret = krb5_padata_add(r->context,
1344 : r->rep.padata,
1345 : KRB5_PADATA_AS_FRESHNESS,
1346 : token,
1347 : token_alloc_size);
1348 4 : if (ret)
1349 0 : free(token);
1350 4 : return ret;
1351 : }
1352 :
1353 : #endif /* PKINIT */
1354 :
1355 : static krb5_error_code
1356 17858 : send_freshness_token(astgs_request_t r, const Key *krbtgt_key, unsigned krbtgt_kvno)
1357 : {
1358 17858 : krb5_error_code ret = 0;
1359 : #ifdef PKINIT
1360 17858 : int idx = 0;
1361 17858 : const PA_DATA *freshness_padata = NULL;
1362 :
1363 17858 : freshness_padata = _kdc_find_padata(&r->req,
1364 : &idx,
1365 : KRB5_PADATA_AS_FRESHNESS);
1366 17858 : if (freshness_padata == NULL) {
1367 17262 : return 0;
1368 : }
1369 :
1370 4 : ret = make_freshness_token(r, krbtgt_key, krbtgt_kvno);
1371 : #endif /* PKINIT */
1372 4 : return ret;
1373 : }
1374 :
1375 : struct kdc_patypes {
1376 : int type;
1377 : const char *name;
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 */
1384 : #define PA_USES_FAST_COOKIE 32 /* Multi-step PA mech maintains state in PA-FX-COOKIE */
1385 : #define PA_HARDWARE_AUTH 64 /* PA mech uses hardware authentication */
1386 : krb5_error_code (*validate)(astgs_request_t, const PA_DATA *pa);
1387 : krb5_error_code (*finalize_pac)(astgs_request_t r);
1388 : void (*cleanup)(astgs_request_t r);
1389 : };
1390 :
1391 : static const struct kdc_patypes pat[] = {
1392 : #ifdef PKINIT
1393 : {
1394 : KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)",
1395 : PA_ANNOUNCE | PA_SYNTHETIC_OK | PA_REPLACE_REPLY_KEY | PA_HARDWARE_AUTH,
1396 : pa_pkinit_validate, NULL, NULL
1397 : },
1398 : {
1399 : KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", PA_ANNOUNCE | PA_REPLACE_REPLY_KEY | PA_HARDWARE_AUTH,
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",
1428 : PA_ANNOUNCE | PA_SYNTHETIC_OK | PA_REPLACE_REPLY_KEY | PA_USES_FAST_COOKIE,
1429 : pa_gss_validate, pa_gss_finalize_pac, NULL
1430 : },
1431 : };
1432 :
1433 : static void
1434 45166 : log_patypes(astgs_request_t r, METHOD_DATA *padata)
1435 : {
1436 45166 : krb5_kdc_configuration *config = r->config;
1437 45166 : struct rk_strpool *p = NULL;
1438 1776 : char *str;
1439 1776 : size_t n, m;
1440 :
1441 119188 : for (n = 0; n < padata->len; n++) {
1442 473492 : for (m = 0; m < sizeof(pat) / sizeof(pat[0]); m++) {
1443 470375 : if (padata->val[n].padata_type == pat[m].type) {
1444 70905 : p = rk_strpoolprintf(p, "%s", pat[m].name);
1445 70905 : break;
1446 : }
1447 : }
1448 74022 : if (m == sizeof(pat) / sizeof(pat[0]))
1449 3117 : p = rk_strpoolprintf(p, "%d", padata->val[n].padata_type);
1450 74022 : if (p && n + 1 < padata->len)
1451 28856 : p = rk_strpoolprintf(p, ", ");
1452 74022 : if (p == NULL) {
1453 0 : kdc_log(r->context, config, 1, "out of memory");
1454 0 : return;
1455 : }
1456 : }
1457 45166 : if (p == NULL)
1458 0 : p = rk_strpoolprintf(p, "none");
1459 :
1460 45166 : str = rk_strpoolcollect(p);
1461 45166 : kdc_log(r->context, config, 4, "Client sent patypes: %s", str);
1462 45166 : kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE,
1463 : "client-pa", "%s", str);
1464 45166 : free(str);
1465 : }
1466 :
1467 : static krb5_boolean
1468 59315 : pa_used_flag_isset(astgs_request_t r, unsigned int flag)
1469 : {
1470 59315 : if (r->pa_used == NULL)
1471 0 : return FALSE;
1472 :
1473 59315 : return (r->pa_used->flags & flag) == flag;
1474 : }
1475 :
1476 : /*
1477 : *
1478 : */
1479 :
1480 : krb5_error_code
1481 78961 : _kdc_encode_reply(krb5_context context,
1482 : krb5_kdc_configuration *config,
1483 : astgs_request_t r, uint32_t nonce,
1484 : krb5_enctype etype,
1485 : int skvno, const EncryptionKey *skey,
1486 : int ckvno,
1487 : int rk_is_subkey,
1488 : krb5_data *reply)
1489 : {
1490 2856 : unsigned char *buf;
1491 2856 : size_t buf_size;
1492 78961 : size_t len = 0;
1493 2856 : krb5_error_code ret;
1494 2856 : krb5_crypto crypto;
1495 78961 : KDC_REP *rep = &r->rep;
1496 78961 : EncTicketPart *et = &r->et;
1497 78961 : EncKDCRepPart *ek = &r->ek;
1498 :
1499 78961 : heim_assert(rep->padata != NULL, "reply padata uninitialized");
1500 :
1501 78961 : ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret);
1502 78961 : if(ret) {
1503 0 : const char *msg = krb5_get_error_message(context, ret);
1504 0 : kdc_log(context, config, 4, "Failed to encode ticket: %s", msg);
1505 0 : krb5_free_error_message(context, msg);
1506 0 : return ret;
1507 : }
1508 78961 : if(buf_size != len)
1509 0 : krb5_abortx(context, "Internal error in ASN.1 encoder");
1510 :
1511 78961 : ret = krb5_crypto_init(context, skey, etype, &crypto);
1512 78961 : if (ret) {
1513 0 : const char *msg = krb5_get_error_message(context, ret);
1514 0 : kdc_log(context, config, 4, "krb5_crypto_init failed: %s", msg);
1515 0 : krb5_free_error_message(context, msg);
1516 0 : free(buf);
1517 0 : return ret;
1518 : }
1519 :
1520 78961 : ret = krb5_encrypt_EncryptedData(context,
1521 : crypto,
1522 : KRB5_KU_TICKET,
1523 : buf,
1524 : len,
1525 : skvno,
1526 : &rep->ticket.enc_part);
1527 78961 : free(buf);
1528 78961 : krb5_crypto_destroy(context, crypto);
1529 78961 : if(ret) {
1530 0 : const char *msg = krb5_get_error_message(context, ret);
1531 0 : kdc_log(context, config, 4, "Failed to encrypt data: %s", msg);
1532 0 : krb5_free_error_message(context, msg);
1533 0 : return ret;
1534 : }
1535 :
1536 78961 : if (r && r->armor_crypto) {
1537 1672 : KrbFastFinished finished;
1538 1672 : krb5_data data;
1539 :
1540 43159 : kdc_log(context, config, 4, "FAST armor protection");
1541 :
1542 43159 : memset(&finished, 0, sizeof(finished));
1543 43159 : krb5_data_zero(&data);
1544 :
1545 43159 : finished.timestamp = kdc_time;
1546 43159 : finished.usec = 0;
1547 43159 : finished.crealm = et->crealm;
1548 43159 : finished.cname = et->cname;
1549 :
1550 43159 : ASN1_MALLOC_ENCODE(Ticket, data.data, data.length,
1551 : &rep->ticket, &len, ret);
1552 43159 : if (ret)
1553 0 : return ret;
1554 43159 : if (data.length != len)
1555 0 : krb5_abortx(context, "internal asn.1 error");
1556 :
1557 43159 : ret = krb5_create_checksum(context, r->armor_crypto,
1558 : KRB5_KU_FAST_FINISHED, 0,
1559 : data.data, data.length,
1560 : &finished.ticket_checksum);
1561 43159 : krb5_data_free(&data);
1562 43159 : if (ret)
1563 0 : return ret;
1564 :
1565 43159 : ret = _kdc_fast_mk_response(context, r->armor_crypto,
1566 : rep->padata, &r->strengthen_key, &finished,
1567 : nonce, &data);
1568 43159 : free_Checksum(&finished.ticket_checksum);
1569 43159 : if (ret)
1570 0 : return ret;
1571 :
1572 43159 : free_METHOD_DATA(r->rep.padata);
1573 :
1574 43159 : ret = krb5_padata_add(context, rep->padata,
1575 : KRB5_PADATA_FX_FAST,
1576 : data.data, data.length);
1577 43159 : if (ret)
1578 0 : return ret;
1579 :
1580 : /*
1581 : * Hide client name for privacy reasons
1582 : */
1583 43159 : if (r->fast.flags.requested_hidden_names) {
1584 42761 : Realm anon_realm = KRB5_ANON_REALM;
1585 :
1586 42761 : free_Realm(&rep->crealm);
1587 42761 : ret = copy_Realm(&anon_realm, &rep->crealm);
1588 42761 : if (ret == 0) {
1589 42761 : free_PrincipalName(&rep->cname);
1590 42761 : ret = _kdc_make_anonymous_principalname(&rep->cname);
1591 : }
1592 42761 : if (ret)
1593 0 : return ret;
1594 : }
1595 : }
1596 :
1597 78961 : if (rep->padata->len == 0) {
1598 7572 : free_METHOD_DATA(rep->padata);
1599 7572 : free(rep->padata);
1600 7572 : rep->padata = NULL;
1601 : }
1602 :
1603 78961 : if(rep->msg_type == krb_as_rep && !config->encode_as_rep_as_tgs_rep)
1604 29656 : ASN1_MALLOC_ENCODE(EncASRepPart, buf, buf_size, ek, &len, ret);
1605 : else
1606 49305 : ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret);
1607 78961 : if(ret) {
1608 0 : const char *msg = krb5_get_error_message(context, ret);
1609 0 : kdc_log(context, config, 4, "Failed to encode KDC-REP: %s", msg);
1610 0 : krb5_free_error_message(context, msg);
1611 0 : return ret;
1612 : }
1613 78961 : if(buf_size != len) {
1614 0 : free(buf);
1615 0 : kdc_log(context, config, 4, "Internal error in ASN.1 encoder");
1616 0 : _kdc_set_e_text(r, "KDC internal error");
1617 0 : return KRB5KRB_ERR_GENERIC;
1618 : }
1619 78961 : ret = krb5_crypto_init(context, &r->reply_key, 0, &crypto);
1620 78961 : if (ret) {
1621 0 : const char *msg = krb5_get_error_message(context, ret);
1622 0 : free(buf);
1623 0 : kdc_log(context, config, 4, "krb5_crypto_init failed: %s", msg);
1624 0 : krb5_free_error_message(context, msg);
1625 0 : return ret;
1626 : }
1627 78961 : if(rep->msg_type == krb_as_rep) {
1628 29656 : 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 29656 : free(buf);
1636 29656 : if (ret == 0)
1637 29656 : ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret);
1638 : } else {
1639 49305 : 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 49305 : free(buf);
1649 49305 : if (ret == 0)
1650 49305 : ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret);
1651 : }
1652 78961 : krb5_crypto_destroy(context, crypto);
1653 78961 : if(ret) {
1654 0 : const char *msg = krb5_get_error_message(context, ret);
1655 0 : kdc_log(context, config, 4, "Failed to encode KDC-REP: %s", msg);
1656 0 : krb5_free_error_message(context, msg);
1657 0 : return ret;
1658 : }
1659 78961 : if(buf_size != len) {
1660 0 : free(buf);
1661 0 : kdc_log(context, config, 4, "Internal error in ASN.1 encoder");
1662 0 : _kdc_set_e_text(r, "KDC internal error");
1663 0 : return KRB5KRB_ERR_GENERIC;
1664 : }
1665 78961 : reply->data = buf;
1666 78961 : reply->length = buf_size;
1667 78961 : return 0;
1668 : }
1669 :
1670 : /*
1671 : *
1672 : */
1673 :
1674 : static krb5_error_code
1675 618 : get_pa_etype_info(krb5_context context,
1676 : krb5_kdc_configuration *config,
1677 : METHOD_DATA *md, Key *ckey,
1678 : krb5_boolean include_salt)
1679 : {
1680 618 : krb5_error_code ret = 0;
1681 0 : ETYPE_INFO_ENTRY eie; /* do not free this one */
1682 0 : ETYPE_INFO ei;
1683 0 : PA_DATA pa;
1684 0 : size_t len;
1685 :
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 : */
1706 :
1707 618 : pa.padata_type = KRB5_PADATA_ETYPE_INFO;
1708 618 : pa.padata_value.data = NULL;
1709 618 : pa.padata_value.length = 0;
1710 618 : ei.len = 0;
1711 618 : ei.val = NULL;
1712 618 : eie.etype = ckey->key.keytype;
1713 618 : eie.salttype = NULL;
1714 618 : eie.salt = NULL;
1715 618 : if (include_salt && ckey->salt)
1716 0 : eie.salt = &ckey->salt->salt;
1717 618 : ret = add_ETYPE_INFO(&ei, &eie);
1718 618 : if (ret == 0)
1719 618 : ASN1_MALLOC_ENCODE(ETYPE_INFO, pa.padata_value.data, pa.padata_value.length,
1720 : &ei, &len, ret);
1721 618 : if (ret == 0)
1722 618 : add_METHOD_DATA(md, &pa);
1723 618 : free_ETYPE_INFO(&ei);
1724 618 : free_PA_DATA(&pa);
1725 618 : return ret;
1726 : }
1727 :
1728 : /*
1729 : *
1730 : */
1731 :
1732 : extern const int _krb5_AES_SHA1_string_to_default_iterator;
1733 : extern const int _krb5_AES_SHA2_string_to_default_iterator;
1734 :
1735 : static krb5_error_code
1736 45638 : make_s2kparams(int value, size_t len, krb5_data **ps2kparams)
1737 : {
1738 1761 : krb5_data *s2kparams;
1739 1761 : krb5_error_code ret;
1740 :
1741 45638 : ALLOC(s2kparams);
1742 45638 : if (s2kparams == NULL)
1743 0 : return ENOMEM;
1744 45638 : ret = krb5_data_alloc(s2kparams, len);
1745 45638 : if (ret) {
1746 0 : free(s2kparams);
1747 0 : return ret;
1748 : }
1749 45638 : _krb5_put_int(s2kparams->data, value, len);
1750 45638 : *ps2kparams = s2kparams;
1751 45638 : return 0;
1752 : }
1753 :
1754 : static krb5_error_code
1755 46636 : make_etype_info2_entry(ETYPE_INFO2_ENTRY *ent,
1756 : Key *key,
1757 : krb5_boolean include_salt)
1758 : {
1759 1764 : krb5_error_code ret;
1760 :
1761 46636 : ent->etype = key->key.keytype;
1762 46636 : if (key->salt && include_salt) {
1763 45632 : ALLOC(ent->salt);
1764 45632 : if (ent->salt == NULL)
1765 0 : return ENOMEM;
1766 45632 : *ent->salt = malloc(key->salt->salt.length + 1);
1767 45632 : if (*ent->salt == NULL) {
1768 0 : free(ent->salt);
1769 0 : ent->salt = NULL;
1770 0 : return ENOMEM;
1771 : }
1772 45632 : memcpy(*ent->salt, key->salt->salt.data, key->salt->salt.length);
1773 45632 : (*ent->salt)[key->salt->salt.length] = '\0';
1774 : } else
1775 1004 : ent->salt = NULL;
1776 :
1777 46636 : ent->s2kparams = NULL;
1778 :
1779 46636 : switch (key->key.keytype) {
1780 45638 : case ETYPE_AES128_CTS_HMAC_SHA1_96:
1781 : case ETYPE_AES256_CTS_HMAC_SHA1_96:
1782 45638 : ret = make_s2kparams(_krb5_AES_SHA1_string_to_default_iterator,
1783 45638 : 4, &ent->s2kparams);
1784 45638 : break;
1785 0 : case KRB5_ENCTYPE_AES128_CTS_HMAC_SHA256_128:
1786 : case KRB5_ENCTYPE_AES256_CTS_HMAC_SHA384_192:
1787 0 : ret = make_s2kparams(_krb5_AES_SHA2_string_to_default_iterator,
1788 0 : 4, &ent->s2kparams);
1789 0 : break;
1790 0 : 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 */
1794 0 : if(key->salt && key->salt->type == hdb_afs3_salt)
1795 0 : ret = make_s2kparams(1, 1, &ent->s2kparams);
1796 : else
1797 0 : ret = 0;
1798 0 : break;
1799 995 : default:
1800 995 : ret = 0;
1801 995 : break;
1802 : }
1803 44872 : return ret;
1804 : }
1805 :
1806 : /*
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).
1810 : */
1811 :
1812 : static krb5_error_code
1813 46636 : get_pa_etype_info2(krb5_context context,
1814 : krb5_kdc_configuration *config,
1815 : METHOD_DATA *md, Key *ckey,
1816 : krb5_boolean include_salt)
1817 : {
1818 46636 : krb5_error_code ret = 0;
1819 1764 : ETYPE_INFO2 pa;
1820 1764 : unsigned char *buf;
1821 1764 : size_t len;
1822 :
1823 46636 : pa.len = 1;
1824 46636 : pa.val = calloc(1, sizeof(pa.val[0]));
1825 46636 : if(pa.val == NULL)
1826 0 : return ENOMEM;
1827 :
1828 46636 : ret = make_etype_info2_entry(&pa.val[0], ckey, include_salt);
1829 46636 : if (ret) {
1830 0 : free_ETYPE_INFO2(&pa);
1831 0 : return ret;
1832 : }
1833 :
1834 46636 : ASN1_MALLOC_ENCODE(ETYPE_INFO2, buf, len, &pa, &len, ret);
1835 46636 : free_ETYPE_INFO2(&pa);
1836 46636 : if(ret)
1837 0 : return ret;
1838 46636 : ret = realloc_method_data(md);
1839 46636 : if(ret) {
1840 0 : free(buf);
1841 0 : return ret;
1842 : }
1843 46636 : md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO2;
1844 46636 : md->val[md->len - 1].padata_value.length = len;
1845 46636 : md->val[md->len - 1].padata_value.data = buf;
1846 46636 : return 0;
1847 : }
1848 :
1849 : /*
1850 : * Return 0 if the client has only older enctypes, this is for
1851 : * determining if the server should send ETYPE_INFO2 or not.
1852 : */
1853 :
1854 : static int
1855 18282 : newer_enctype_present(krb5_context context,
1856 : struct KDC_REQ_BODY_etype *etype_list)
1857 : {
1858 592 : size_t i;
1859 :
1860 19757 : for (i = 0; i < etype_list->len; i++) {
1861 19139 : if (!krb5_is_enctype_old(context, etype_list->val[i]))
1862 17072 : return 1;
1863 : }
1864 618 : return 0;
1865 : }
1866 :
1867 : static krb5_error_code
1868 18282 : get_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 592 : 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 18282 : if (config->force_include_pa_etype_salt)
1883 18282 : 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 18282 : ret = get_pa_etype_info2(context, config, md, ckey, include_salt);
1907 18282 : if (ret)
1908 0 : return ret;
1909 :
1910 18282 : if (!newer_enctype_present(context, etype_list))
1911 618 : ret = get_pa_etype_info(context, config, md, ckey, include_salt);
1912 :
1913 17690 : return ret;
1914 : }
1915 :
1916 : /*
1917 : *
1918 : */
1919 :
1920 : void
1921 78965 : _log_astgs_req(astgs_request_t r, krb5_enctype setype)
1922 : {
1923 78965 : const KDC_REQ_BODY *b = &r->req.req_body;
1924 78965 : krb5_enctype cetype = r->reply_key.keytype;
1925 2856 : krb5_error_code ret;
1926 2856 : struct rk_strpool *p;
1927 78965 : struct rk_strpool *s = NULL;
1928 2856 : char *str;
1929 2856 : char *cet;
1930 2856 : char *set;
1931 2856 : size_t i;
1932 :
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 :
1941 78965 : p = rk_strpoolprintf(NULL, "%s", "Client supported enctypes: ");
1942 :
1943 513388 : for (i = 0; i < b->etype.len; i++) {
1944 431567 : ret = krb5_enctype_to_string(r->context, b->etype.val[i], &str);
1945 431567 : if (ret == 0) {
1946 431541 : p = rk_strpoolprintf(p, "%s", str);
1947 431541 : free(str);
1948 : } else
1949 26 : p = rk_strpoolprintf(p, "%d", b->etype.val[i]);
1950 431567 : if (p == NULL) {
1951 0 : rk_strpoolfree(s);
1952 0 : _kdc_r_log(r, 4, "out of memory");
1953 0 : return;
1954 : }
1955 431567 : s = rk_strpoolprintf(s, "%d", b->etype.val[i]);
1956 431567 : if (i + 1 < b->etype.len) {
1957 352602 : p = rk_strpoolprintf(p, ", ");
1958 352602 : s = rk_strpoolprintf(s, ",");
1959 : }
1960 : }
1961 78965 : if (p == NULL)
1962 0 : p = rk_strpoolprintf(p, "no encryption types");
1963 :
1964 78965 : str = rk_strpoolcollect(s);
1965 78965 : if (str)
1966 78965 : kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE, "etypes", "%s",
1967 : str);
1968 78965 : free(str);
1969 :
1970 78965 : ret = krb5_enctype_to_string(r->context, cetype, &cet);
1971 78965 : if(ret == 0) {
1972 78965 : ret = krb5_enctype_to_string(r->context, setype, &set);
1973 78965 : if (ret == 0) {
1974 78965 : p = rk_strpoolprintf(p, ", using %s/%s", cet, set);
1975 78965 : free(set);
1976 : }
1977 78965 : free(cet);
1978 : }
1979 78965 : if (ret != 0)
1980 0 : p = rk_strpoolprintf(p, ", using enctypes %d/%d",
1981 : cetype, setype);
1982 :
1983 78965 : str = rk_strpoolcollect(p);
1984 78965 : if (str)
1985 78965 : _kdc_r_log(r, 4, "%s", str);
1986 78965 : free(str);
1987 :
1988 78965 : kdc_audit_addkv((kdc_request_t)r, 0, "etype", "%d/%d", cetype, setype);
1989 :
1990 : {
1991 2856 : char fixedstr[128];
1992 2856 : int result;
1993 :
1994 78965 : result = unparse_flags(KDCOptions2int(b->kdc_options), asn1_KDCOptions_units(),
1995 : fixedstr, sizeof(fixedstr));
1996 78965 : if (result > 0) {
1997 73338 : _kdc_r_log(r, 4, "Requested flags: %s", fixedstr);
1998 73338 : kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE,
1999 : "flags", "%s", fixedstr);
2000 : }
2001 : }
2002 : }
2003 :
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 :
2010 : KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL
2011 99273 : kdc_check_flags(astgs_request_t r,
2012 : krb5_boolean is_as_req,
2013 : hdb_entry *client,
2014 : hdb_entry *server)
2015 : {
2016 99273 : if (client != NULL) {
2017 : /* check client */
2018 99213 : if (client->flags.locked_out) {
2019 0 : kdc_audit_addreason((kdc_request_t)r, "Client is locked out");
2020 0 : return KRB5KDC_ERR_CLIENT_REVOKED;
2021 : }
2022 :
2023 99213 : if (client->flags.invalid) {
2024 0 : kdc_audit_addreason((kdc_request_t)r,
2025 : "Client has invalid bit set");
2026 0 : return KRB5KDC_ERR_POLICY;
2027 : }
2028 :
2029 99213 : if (!client->flags.client) {
2030 0 : kdc_audit_addreason((kdc_request_t)r,
2031 : "Principal may not act as client");
2032 0 : return KRB5KDC_ERR_POLICY;
2033 : }
2034 :
2035 99213 : if (client->valid_start && *client->valid_start > kdc_time) {
2036 0 : char starttime_str[100];
2037 0 : krb5_format_time(r->context, *client->valid_start,
2038 : starttime_str, sizeof(starttime_str), TRUE);
2039 0 : kdc_audit_addreason((kdc_request_t)r, "Client not yet valid "
2040 : "until %s", starttime_str);
2041 0 : return KRB5KDC_ERR_CLIENT_NOTYET;
2042 : }
2043 :
2044 99213 : if (client->valid_end && *client->valid_end < kdc_time) {
2045 0 : char endtime_str[100];
2046 0 : krb5_format_time(r->context, *client->valid_end,
2047 : endtime_str, sizeof(endtime_str), TRUE);
2048 0 : kdc_audit_addreason((kdc_request_t)r, "Client expired at %s",
2049 : endtime_str);
2050 0 : return KRB5KDC_ERR_NAME_EXP;
2051 : }
2052 :
2053 99213 : if (client->flags.require_pwchange &&
2054 0 : (server == NULL || !server->flags.change_pw))
2055 0 : return KRB5KDC_ERR_KEY_EXPIRED;
2056 :
2057 99213 : if (client->pw_end && *client->pw_end < kdc_time
2058 16 : && (server == NULL || !server->flags.change_pw)) {
2059 0 : char pwend_str[100];
2060 0 : krb5_format_time(r->context, *client->pw_end,
2061 : pwend_str, sizeof(pwend_str), TRUE);
2062 0 : kdc_audit_addreason((kdc_request_t)r, "Client's key has expired "
2063 : "at %s", pwend_str);
2064 0 : return KRB5KDC_ERR_KEY_EXPIRED;
2065 : }
2066 : }
2067 :
2068 : /* check server */
2069 :
2070 99273 : if (server != NULL) {
2071 98447 : if (server->flags.locked_out) {
2072 0 : kdc_audit_addreason((kdc_request_t)r, "Server locked out");
2073 0 : return KRB5KDC_ERR_SERVICE_REVOKED;
2074 : }
2075 98447 : if (server->flags.invalid) {
2076 0 : kdc_audit_addreason((kdc_request_t)r,
2077 : "Server has invalid flag set");
2078 0 : return KRB5KDC_ERR_POLICY;
2079 : }
2080 98447 : if (!server->flags.server) {
2081 0 : kdc_audit_addreason((kdc_request_t)r,
2082 : "Principal may not act as server");
2083 0 : return KRB5KDC_ERR_POLICY;
2084 : }
2085 :
2086 98447 : if (!is_as_req && server->flags.initial) {
2087 0 : kdc_audit_addreason((kdc_request_t)r,
2088 : "AS-REQ is required for server");
2089 0 : return KRB5KDC_ERR_POLICY;
2090 : }
2091 :
2092 98447 : if (server->valid_start && *server->valid_start > kdc_time) {
2093 0 : char starttime_str[100];
2094 0 : krb5_format_time(r->context, *server->valid_start,
2095 : starttime_str, sizeof(starttime_str), TRUE);
2096 0 : kdc_audit_addreason((kdc_request_t)r, "Server not yet valid "
2097 : "until %s", starttime_str);
2098 0 : return KRB5KDC_ERR_SERVICE_NOTYET;
2099 : }
2100 :
2101 98447 : if (server->valid_end && *server->valid_end < kdc_time) {
2102 0 : char endtime_str[100];
2103 0 : krb5_format_time(r->context, *server->valid_end,
2104 : endtime_str, sizeof(endtime_str), TRUE);
2105 0 : kdc_audit_addreason((kdc_request_t)r, "Server expired at %s",
2106 : endtime_str);
2107 0 : return KRB5KDC_ERR_SERVICE_EXP;
2108 : }
2109 :
2110 98447 : if (server->pw_end && *server->pw_end < kdc_time) {
2111 0 : char pwend_str[100];
2112 0 : krb5_format_time(r->context, *server->pw_end,
2113 : pwend_str, sizeof(pwend_str), TRUE);
2114 0 : kdc_audit_addreason((kdc_request_t)r, "Server's key has expired "
2115 : "at %s", pwend_str);
2116 0 : return KRB5KDC_ERR_KEY_EXPIRED;
2117 : }
2118 : }
2119 95825 : 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 :
2128 : krb5_boolean
2129 78968 : _kdc_check_addresses(astgs_request_t r, HostAddresses *addresses,
2130 : const struct sockaddr *from)
2131 : {
2132 78968 : krb5_kdc_configuration *config = r->config;
2133 2856 : krb5_error_code ret;
2134 2856 : krb5_address addr;
2135 2856 : krb5_boolean result;
2136 78968 : krb5_boolean only_netbios = TRUE;
2137 2856 : size_t i;
2138 :
2139 78968 : if (!config->check_ticket_addresses && !config->warn_ticket_addresses)
2140 0 : return TRUE;
2141 :
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 78968 : if (addresses == NULL || addresses->len == 0)
2148 78850 : return config->allow_null_ticket_addresses;
2149 :
2150 236 : for (i = 0; i < addresses->len; ++i) {
2151 118 : if (addresses->val[i].addr_type != KRB5_ADDRESS_NETBIOS) {
2152 0 : only_netbios = FALSE;
2153 : }
2154 : }
2155 :
2156 : /* Windows sends it's netbios name, which I can only assume is
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 : */
2161 :
2162 118 : if(only_netbios)
2163 118 : return config->allow_null_ticket_addresses;
2164 :
2165 0 : ret = krb5_sockaddr2address (r->context, from, &addr);
2166 0 : if(ret)
2167 0 : return FALSE;
2168 :
2169 0 : result = krb5_address_search(r->context, &addr, addresses);
2170 0 : krb5_free_address (r->context, &addr);
2171 0 : return result;
2172 : }
2173 :
2174 : /*
2175 : *
2176 : */
2177 : krb5_error_code
2178 0 : _kdc_check_anon_policy(astgs_request_t r)
2179 : {
2180 0 : if (!r->config->allow_anonymous) {
2181 0 : kdc_audit_addreason((kdc_request_t)r,
2182 : "Anonymous tickets denied by local policy");
2183 0 : return KRB5KDC_ERR_POLICY;
2184 : }
2185 :
2186 0 : 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 : */
2193 :
2194 : static uint64_t
2195 29660 : get_pac_attributes(krb5_context context, KDC_REQ *req)
2196 : {
2197 1184 : krb5_error_code ret;
2198 1184 : PA_PAC_REQUEST pacreq;
2199 1184 : const PA_DATA *pa;
2200 29660 : int i = 0;
2201 1184 : uint32_t pac_attributes;
2202 :
2203 29660 : pa = _kdc_find_padata(req, &i, KRB5_PADATA_PA_PAC_REQUEST);
2204 29660 : if (pa == NULL)
2205 27685 : return KRB5_PAC_WAS_GIVEN_IMPLICITLY;
2206 :
2207 791 : ret = decode_PA_PAC_REQUEST(pa->padata_value.data,
2208 791 : pa->padata_value.length,
2209 : &pacreq,
2210 : NULL);
2211 791 : if (ret)
2212 0 : return KRB5_PAC_WAS_GIVEN_IMPLICITLY;
2213 :
2214 791 : pac_attributes = pacreq.include_pac ? KRB5_PAC_WAS_REQUESTED : 0;
2215 791 : free_PA_PAC_REQUEST(&pacreq);
2216 791 : return pac_attributes;
2217 : }
2218 :
2219 : /*
2220 : *
2221 : */
2222 :
2223 : static krb5_error_code
2224 29660 : generate_pac(astgs_request_t r, const Key *skey, const Key *tkey,
2225 : krb5_boolean is_tgs)
2226 : {
2227 1184 : krb5_error_code ret;
2228 1184 : uint16_t rodc_id;
2229 1184 : krb5_principal client;
2230 29660 : krb5_const_principal canon_princ = NULL;
2231 :
2232 29660 : r->pac_attributes = get_pac_attributes(r->context, &r->req);
2233 29660 : kdc_audit_setkv_number((kdc_request_t)r, "pac_attributes",
2234 28476 : r->pac_attributes);
2235 :
2236 29660 : if (!is_tgs && !(r->pac_attributes & (KRB5_PAC_WAS_REQUESTED | KRB5_PAC_WAS_GIVEN_IMPLICITLY)))
2237 1 : 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 :
2246 29659 : ret = _kdc_pac_generate(r,
2247 : r->client,
2248 : r->server,
2249 29659 : 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 29659 : if (ret) {
2254 4 : _kdc_r_log(r, 4, "PAC generation failed for -- %s",
2255 : r->cname);
2256 4 : return ret;
2257 : }
2258 29655 : if (r->pac == NULL)
2259 0 : return 0;
2260 :
2261 29655 : rodc_id = r->server->kvno >> 16;
2262 :
2263 : /* libkrb5 expects ticket and PAC client names to match */
2264 29655 : ret = _krb5_principalname2krb5_principal(r->context, &client,
2265 : r->et.cname, r->et.crealm);
2266 29655 : if (ret)
2267 0 : 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 : */
2275 29655 : if (krb5_realm_compare(r->context, client, r->canon_client_princ)) {
2276 29655 : char *cpn = NULL;
2277 :
2278 29655 : canon_princ = r->canon_client_princ;
2279 :
2280 29655 : (void) krb5_unparse_name(r->context, canon_princ, &cpn);
2281 29655 : kdc_audit_addkv((kdc_request_t)r, 0, "canon_client_name", "%s",
2282 29655 : cpn ? cpn : "<unknown>");
2283 29655 : krb5_xfree(cpn);
2284 : }
2285 :
2286 29655 : if (r->pa_used && r->pa_used->finalize_pac) {
2287 0 : ret = r->pa_used->finalize_pac(r);
2288 0 : if (ret)
2289 0 : return ret;
2290 : }
2291 :
2292 29655 : ret = _krb5_kdc_pac_sign_ticket(r->context,
2293 : r->pac,
2294 : client,
2295 29655 : &skey->key, /* Server key */
2296 29655 : &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);
2304 29655 : krb5_free_principal(r->context, client);
2305 29655 : krb5_pac_free(r->context, r->pac);
2306 29655 : r->pac = NULL;
2307 29655 : if (ret) {
2308 0 : _kdc_r_log(r, 4, "PAC signing failed for -- %s",
2309 : r->cname);
2310 0 : return ret;
2311 : }
2312 :
2313 28471 : return ret;
2314 : }
2315 :
2316 : /*
2317 : *
2318 : */
2319 :
2320 : krb5_boolean
2321 125804 : _kdc_is_anonymous(krb5_context context, krb5_const_principal principal)
2322 : {
2323 125804 : 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 :
2333 : krb5_boolean
2334 44834 : _kdc_is_anonymous_pkinit(krb5_context context, krb5_const_principal principal)
2335 : {
2336 44834 : return _kdc_is_anonymous(context, principal) &&
2337 0 : strcmp(principal->realm, KRB5_ANON_REALM) == 0;
2338 : }
2339 :
2340 : static int
2341 17858 : require_preauth_p(astgs_request_t r)
2342 : {
2343 17858 : return r->config->require_preauth
2344 0 : || r->client->flags.require_preauth
2345 17266 : || r->server->flags.require_preauth;
2346 : }
2347 :
2348 :
2349 : /*
2350 : *
2351 : */
2352 :
2353 : static krb5_error_code
2354 26137 : add_enc_pa_rep(astgs_request_t r)
2355 : {
2356 1184 : krb5_error_code ret;
2357 1184 : krb5_crypto crypto;
2358 1184 : Checksum checksum;
2359 1184 : krb5_data cdata;
2360 1184 : size_t len;
2361 :
2362 26137 : ret = krb5_crypto_init(r->context, &r->reply_key, 0, &crypto);
2363 26137 : if (ret)
2364 0 : return ret;
2365 :
2366 26137 : ret = krb5_create_checksum(r->context, crypto,
2367 : KRB5_KU_AS_REQ, 0,
2368 : r->request.data, r->request.length,
2369 : &checksum);
2370 26137 : krb5_crypto_destroy(r->context, crypto);
2371 26137 : if (ret)
2372 0 : return ret;
2373 :
2374 26137 : ASN1_MALLOC_ENCODE(Checksum, cdata.data, cdata.length,
2375 : &checksum, &len, ret);
2376 26137 : free_Checksum(&checksum);
2377 26137 : if (ret)
2378 0 : return ret;
2379 26137 : heim_assert(cdata.length == len, "ASN.1 internal error");
2380 :
2381 26137 : if (r->ek.encrypted_pa_data == NULL) {
2382 26137 : ALLOC(r->ek.encrypted_pa_data);
2383 26137 : if (r->ek.encrypted_pa_data == NULL)
2384 0 : return ENOMEM;
2385 : }
2386 26137 : ret = krb5_padata_add(r->context, r->ek.encrypted_pa_data,
2387 : KRB5_PADATA_REQ_ENC_PA_REP, cdata.data, cdata.length);
2388 26137 : if (ret)
2389 0 : return ret;
2390 :
2391 26137 : if (!r->config->enable_fast)
2392 949 : return 0;
2393 :
2394 25188 : return krb5_padata_add(r->context, r->ek.encrypted_pa_data,
2395 : KRB5_PADATA_FX_FAST, NULL, 0);
2396 : }
2397 :
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 : */
2403 : static krb5_error_code
2404 0 : add_synthetic_princ_ad(astgs_request_t r)
2405 : {
2406 0 : krb5_data data;
2407 :
2408 0 : krb5_data_zero(&data);
2409 :
2410 0 : return _kdc_tkt_add_if_relevant_ad(r->context, &r->et,
2411 : KRB5_AUTHDATA_SYNTHETIC_PRINC_USED,
2412 : &data);
2413 : }
2414 :
2415 : static krb5_error_code
2416 5115 : get_local_tgs(krb5_context context,
2417 : krb5_kdc_configuration *config,
2418 : krb5_const_realm realm,
2419 : HDB **krbtgtdb,
2420 : hdb_entry **krbtgt)
2421 : {
2422 0 : krb5_error_code ret;
2423 0 : krb5_principal tgs_name;
2424 :
2425 5115 : *krbtgtdb = NULL;
2426 5115 : *krbtgt = NULL;
2427 :
2428 5115 : ret = krb5_make_principal(context,
2429 : &tgs_name,
2430 : realm,
2431 : KRB5_TGS_NAME,
2432 : realm,
2433 : NULL);
2434 5115 : if (ret == 0)
2435 5115 : ret = _kdc_db_fetch(context, config, tgs_name,
2436 : HDB_F_GET_KRBTGT, NULL, krbtgtdb, krbtgt);
2437 :
2438 5115 : krb5_free_principal(context, tgs_name);
2439 5115 : return ret;
2440 : }
2441 :
2442 : /*
2443 : *
2444 : */
2445 :
2446 : krb5_error_code
2447 51200 : _kdc_as_rep(astgs_request_t r)
2448 : {
2449 51200 : krb5_kdc_configuration *config = r->config;
2450 51200 : KDC_REQ *req = &r->req;
2451 51200 : const char *from = r->from;
2452 51200 : KDC_REQ_BODY *b = NULL;
2453 51200 : KDC_REP *rep = &r->rep;
2454 1776 : KDCOptions f;
2455 1776 : krb5_enctype setype;
2456 51200 : krb5_error_code ret = 0;
2457 1776 : Key *skey;
2458 51200 : int found_pa = 0;
2459 51200 : int i, flags = HDB_F_FOR_AS_REQ;
2460 1776 : const PA_DATA *pa;
2461 1776 : krb5_boolean is_tgs;
2462 1776 : const char *msg;
2463 1776 : Key *krbtgt_key;
2464 1776 : unsigned krbtgt_kvno;
2465 :
2466 51200 : memset(rep, 0, sizeof(*rep));
2467 :
2468 51200 : ALLOC(rep->padata);
2469 51200 : if (rep->padata == NULL) {
2470 0 : ret = ENOMEM;
2471 0 : krb5_set_error_message(r->context, ret, N_("malloc: out of memory", ""));
2472 0 : goto out;
2473 : }
2474 :
2475 : /*
2476 : * Look for FAST armor and unwrap
2477 : */
2478 51200 : ret = _kdc_fast_unwrap_request(r, NULL, NULL);
2479 51200 : if (ret) {
2480 8 : _kdc_r_log(r, 1, "FAST unwrap request from %s failed: %d", from, ret);
2481 8 : goto out;
2482 : }
2483 :
2484 : /* Validate armor TGT, and initialize the armor client and PAC */
2485 51192 : if (r->armor_ticket) {
2486 468 : ret = _kdc_fast_check_armor_pac(r, HDB_F_FOR_AS_REQ);
2487 468 : if (ret)
2488 4 : goto out;
2489 : }
2490 :
2491 51188 : b = &req->req_body;
2492 51188 : f = b->kdc_options;
2493 :
2494 51188 : if (f.canonicalize)
2495 47109 : flags |= HDB_F_CANON;
2496 :
2497 51188 : if (b->sname == NULL) {
2498 3 : ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
2499 3 : _kdc_set_e_text(r, "No server in request");
2500 3 : goto out;
2501 : }
2502 :
2503 51185 : ret = _krb5_principalname2krb5_principal(r->context, &r->server_princ,
2504 49409 : *(b->sname), b->realm);
2505 51185 : if (!ret)
2506 51185 : ret = krb5_unparse_name(r->context, r->server_princ, &r->sname);
2507 51185 : if (ret) {
2508 0 : kdc_log(r->context, config, 2,
2509 : "AS_REQ malformed server name from %s", from);
2510 0 : goto out;
2511 : }
2512 :
2513 51185 : if (b->cname == NULL) {
2514 0 : ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
2515 0 : _kdc_set_e_text(r, "No client in request");
2516 0 : goto out;
2517 : }
2518 :
2519 51185 : ret = _krb5_principalname2krb5_principal(r->context, &r->client_princ,
2520 49409 : *(b->cname), b->realm);
2521 51185 : if (!ret)
2522 51185 : ret = krb5_unparse_name(r->context, r->client_princ, &r->cname);
2523 51185 : if (ret) {
2524 0 : kdc_log(r->context, config, 2,
2525 : "AS-REQ malformed client name from %s", from);
2526 0 : goto out;
2527 : }
2528 :
2529 51185 : kdc_log(r->context, config, 4, "AS-REQ %s from %s for %s",
2530 : r->cname, r->from, r->sname);
2531 :
2532 51185 : is_tgs = krb5_principal_is_krbtgt(r->context, r->server_princ);
2533 :
2534 51289 : if (_kdc_is_anonymous(r->context, r->client_princ) &&
2535 104 : !_kdc_is_anon_request(req)) {
2536 0 : kdc_log(r->context, config, 2, "Anonymous client w/o anonymous flag");
2537 0 : ret = KRB5KDC_ERR_BADOPTION;
2538 0 : goto out;
2539 : }
2540 :
2541 52961 : ret = _kdc_db_fetch(r->context, config, r->client_princ,
2542 51185 : HDB_F_GET_CLIENT | HDB_F_SYNTHETIC_OK | flags, NULL,
2543 : &r->clientdb, &r->client);
2544 51185 : switch (ret) {
2545 46795 : case 0: /* Success */
2546 48571 : break;
2547 1627 : case HDB_ERR_NOT_FOUND_HERE:
2548 1627 : kdc_log(r->context, config, 5, "client %s does not have secrets at this KDC, need to proxy",
2549 : r->cname);
2550 1627 : goto out;
2551 538 : case HDB_ERR_WRONG_REALM: {
2552 538 : char *fixed_client_name = NULL;
2553 :
2554 538 : ret = krb5_unparse_name(r->context, r->client->principal,
2555 : &fixed_client_name);
2556 538 : if (ret) {
2557 0 : goto out;
2558 : }
2559 :
2560 538 : kdc_log(r->context, config, 4, "WRONG_REALM - %s -> %s",
2561 : r->cname, fixed_client_name);
2562 538 : free(fixed_client_name);
2563 :
2564 538 : r->e_text = NULL;
2565 538 : ret = _kdc_fast_mk_error(r, r->rep.padata, r->armor_crypto,
2566 538 : &req->req_body,
2567 538 : r->error_code = KRB5_KDC_ERR_WRONG_REALM,
2568 538 : r->client->principal, r->server_princ,
2569 538 : NULL, NULL, r->reply);
2570 538 : goto out;
2571 : }
2572 449 : default:
2573 : {
2574 449 : msg = krb5_get_error_message(r->context, ret);
2575 449 : kdc_log(r->context, config, 4, "UNKNOWN -- %s: %s", r->cname, msg);
2576 449 : krb5_free_error_message(r->context, msg);
2577 449 : ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
2578 449 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
2579 : KDC_AUTH_EVENT_CLIENT_UNKNOWN);
2580 449 : goto out;
2581 : }
2582 : }
2583 :
2584 48571 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
2585 : KDC_AUTH_EVENT_CLIENT_FOUND);
2586 :
2587 98918 : ret = _kdc_db_fetch(r->context, config, r->server_princ,
2588 48571 : HDB_F_GET_SERVER | HDB_F_DELAY_NEW_KEYS |
2589 48571 : flags | (is_tgs ? HDB_F_GET_KRBTGT : 0),
2590 : NULL, &r->serverdb, &r->server);
2591 48571 : switch (ret) {
2592 46793 : case 0: /* Success */
2593 48569 : break;
2594 0 : case HDB_ERR_NOT_FOUND_HERE:
2595 0 : kdc_log(r->context, config, 5, "target %s does not have secrets at this KDC, need to proxy",
2596 : r->sname);
2597 0 : goto out;
2598 2 : default:
2599 2 : msg = krb5_get_error_message(r->context, ret);
2600 2 : kdc_log(r->context, config, 4, "UNKNOWN -- %s: %s", r->sname, msg);
2601 2 : krb5_free_error_message(r->context, msg);
2602 2 : ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
2603 2 : goto out;
2604 : }
2605 :
2606 48569 : ret = _kdc_check_access(r);
2607 48569 : if(ret)
2608 305 : goto out;
2609 :
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 :
2616 : /*
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.
2620 : */
2621 50040 : ret = _kdc_find_session_etype(r, b->etype.val, b->etype.len,
2622 48264 : r->server, &r->sessionetype);
2623 48264 : if (ret) {
2624 170 : kdc_log(r->context, config, 4,
2625 : "Client (%s) from %s has no common enctypes with KDC "
2626 : "to use for the session key",
2627 : r->cname, from);
2628 170 : goto out;
2629 : }
2630 :
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 49870 : ret = _kdc_get_preferred_key(r->context, config,
2637 48094 : r->server, r->sname,
2638 : &setype, &skey);
2639 48094 : if(ret)
2640 138 : goto out;
2641 :
2642 : /* If server is not krbtgt, fetch local krbtgt key for signing authdata */
2643 47956 : if (is_tgs) {
2644 42841 : krbtgt_key = skey;
2645 42841 : krbtgt_kvno = r->server->kvno;
2646 : } else {
2647 5115 : ret = get_local_tgs(r->context, config, r->server_princ->realm,
2648 : &r->krbtgtdb, &r->krbtgt);
2649 5115 : if (ret)
2650 0 : goto out;
2651 :
2652 5115 : ret = _kdc_get_preferred_key(r->context, config, r->krbtgt,
2653 5115 : r->server_princ->realm,
2654 : NULL, &krbtgt_key);
2655 5115 : if (ret)
2656 0 : goto out;
2657 :
2658 5115 : krbtgt_kvno = r->server->kvno;
2659 : }
2660 :
2661 : /*
2662 : * Pre-auth processing
2663 : */
2664 :
2665 47956 : if(req->padata){
2666 1776 : unsigned int n;
2667 :
2668 45166 : log_patypes(r, req->padata);
2669 :
2670 : /* Check if preauth matching */
2671 :
2672 362673 : for (n = 0; !found_pa && n < sizeof(pat) / sizeof(pat[0]); n++) {
2673 316164 : if (pat[n].validate == NULL)
2674 150482 : continue;
2675 165682 : if (r->armor_crypto == NULL && (pat[n].flags & PA_REQ_FAST))
2676 15034 : continue;
2677 150648 : if (!r->config->enable_fast_cookie && (pat[n].flags & PA_USES_FAST_COOKIE))
2678 15068 : continue;
2679 :
2680 135580 : kdc_log(r->context, config, 5,
2681 135580 : "Looking for %s pa-data -- %s", pat[n].name, r->cname);
2682 135580 : i = 0;
2683 135580 : pa = _kdc_find_padata(req, &i, pat[n].type);
2684 135580 : if (pa) {
2685 30098 : if (r->client->flags.synthetic &&
2686 0 : !(pat[n].flags & PA_SYNTHETIC_OK)) {
2687 0 : kdc_log(r->context, config, 4, "UNKNOWN -- %s", r->cname);
2688 0 : ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
2689 0 : goto out;
2690 : }
2691 30098 : if (!(pat[n].flags & PA_HARDWARE_AUTH)) {
2692 30037 : ret = _kdc_hwauth_policy(r);
2693 30037 : if (ret) {
2694 7 : kdc_log(r->context, config, 4, "Hardware authentication required for %s", r->cname);
2695 7 : goto out;
2696 : }
2697 : }
2698 30091 : kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_VIS, "pa", "%s",
2699 28907 : pat[n].name);
2700 30091 : ret = pat[n].validate(r, pa);
2701 30091 : if (ret != 0) {
2702 0 : krb5_error_code ret2;
2703 426 : Key *ckey = NULL;
2704 0 : krb5_boolean default_salt;
2705 :
2706 852 : if (ret != KRB5_KDC_ERR_MORE_PREAUTH_DATA_REQUIRED &&
2707 426 : !kdc_audit_getkv((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT))
2708 0 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
2709 : KDC_AUTH_EVENT_PREAUTH_FAILED);
2710 :
2711 : /*
2712 : * If there is a client key, send ETYPE_INFO{,2}
2713 : */
2714 426 : if (!r->client->flags.locked_out) {
2715 426 : ret2 = _kdc_find_etype(r, KFE_IS_PREAUTH|KFE_USE_CLIENT,
2716 426 : b->etype.val, b->etype.len,
2717 : NULL, &ckey, &default_salt);
2718 426 : if (ret2 == 0) {
2719 424 : ret2 = get_pa_etype_info_both(r->context, config, &b->etype,
2720 : r->rep.padata, ckey, !default_salt);
2721 424 : if (ret2 != 0)
2722 0 : ret = ret2;
2723 : }
2724 : }
2725 426 : goto out;
2726 : }
2727 29665 : if (!kdc_audit_getkv((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT))
2728 0 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
2729 : KDC_AUTH_EVENT_PREAUTH_SUCCEEDED);
2730 29665 : kdc_log(r->context, config, 4,
2731 : "%s pre-authentication succeeded -- %s",
2732 28481 : pat[n].name, r->cname);
2733 29665 : found_pa = 1;
2734 29665 : r->pa_used = &pat[n];
2735 29665 : r->et.flags.pre_authent = 1;
2736 : }
2737 : }
2738 : }
2739 :
2740 47523 : if (found_pa == 0) {
2741 17858 : Key *ckey = NULL;
2742 592 : size_t n;
2743 592 : krb5_boolean default_salt;
2744 :
2745 17858 : if (r->client->flags.synthetic) {
2746 0 : kdc_log(r->context, config, 4, "UNKNOWN -- %s", r->cname);
2747 0 : ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
2748 17266 : goto out;
2749 : }
2750 :
2751 214296 : for (n = 0; n < sizeof(pat) / sizeof(pat[0]); n++) {
2752 196438 : if ((pat[n].flags & PA_ANNOUNCE) == 0)
2753 71432 : continue;
2754 :
2755 125006 : if (!r->armor_crypto && (pat[n].flags & PA_REQ_FAST))
2756 17824 : continue;
2757 107182 : if (pat[n].type == KRB5_PADATA_PKINIT_KX && !r->config->allow_anonymous)
2758 17858 : continue;
2759 89324 : if (pat[n].type == KRB5_PADATA_ENC_TIMESTAMP) {
2760 17858 : if (r->armor_crypto && !r->config->enable_armored_pa_enc_timestamp)
2761 34 : continue;
2762 17824 : if (!r->armor_crypto && !r->config->enable_unarmored_pa_enc_timestamp)
2763 0 : continue;
2764 : }
2765 89290 : if (pat[n].type == KRB5_PADATA_FX_FAST && !r->config->enable_fast)
2766 775 : continue;
2767 88515 : if (pat[n].type == KRB5_PADATA_GSS && !r->config->enable_gss_preauth)
2768 17858 : continue;
2769 70657 : if (!r->config->enable_fast_cookie && (pat[n].flags & PA_USES_FAST_COOKIE))
2770 0 : continue;
2771 :
2772 70657 : ret = krb5_padata_add(r->context, r->rep.padata,
2773 68289 : pat[n].type, NULL, 0);
2774 70657 : if (ret)
2775 0 : goto out;
2776 : }
2777 :
2778 : /*
2779 : * If there is a client key, send ETYPE_INFO{,2}
2780 : */
2781 18450 : ret = _kdc_find_etype(r, KFE_IS_PREAUTH|KFE_USE_CLIENT,
2782 17858 : b->etype.val, b->etype.len,
2783 : NULL, &ckey, &default_salt);
2784 17858 : if (ret == 0) {
2785 17858 : ret = get_pa_etype_info_both(r->context, config, &b->etype,
2786 : r->rep.padata, ckey, !default_salt);
2787 17858 : if (ret)
2788 0 : goto out;
2789 : }
2790 :
2791 : /*
2792 : * If the client indicated support for PKINIT Freshness, send back a
2793 : * freshness token.
2794 : */
2795 17858 : ret = send_freshness_token(r, krbtgt_key, krbtgt_kvno);
2796 17858 : if (ret)
2797 0 : goto out;
2798 :
2799 : /*
2800 : * send requre preauth is its required or anon is requested,
2801 : * anon is today only allowed via preauth mechanisms.
2802 : */
2803 17858 : if (require_preauth_p(r) || _kdc_is_anon_request(&r->req)) {
2804 17858 : ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
2805 17858 : _kdc_set_e_text(r, "Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ");
2806 17858 : goto out;
2807 : }
2808 :
2809 0 : if (ckey == NULL) {
2810 0 : ret = KRB5KDC_ERR_CLIENT_NOTYET;
2811 0 : _kdc_set_e_text(r, "Doesn't have a client key available");
2812 0 : goto out;
2813 : }
2814 0 : krb5_free_keyblock_contents(r->context, &r->reply_key);
2815 0 : ret = krb5_copy_keyblock_contents(r->context, &ckey->key, &r->reply_key);
2816 0 : if (ret)
2817 0 : goto out;
2818 : }
2819 :
2820 29665 : r->canon_client_princ = r->client->principal;
2821 :
2822 29665 : if (_kdc_is_anon_request(&r->req)) {
2823 0 : ret = _kdc_check_anon_policy(r);
2824 0 : if (ret) {
2825 0 : _kdc_set_e_text(r, "Anonymous ticket requests are disabled");
2826 0 : goto out;
2827 : }
2828 :
2829 0 : r->et.flags.anonymous = 1;
2830 : }
2831 :
2832 29665 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
2833 : KDC_AUTH_EVENT_CLIENT_AUTHORIZED);
2834 :
2835 29665 : if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey) {
2836 0 : ret = KRB5KDC_ERR_BADOPTION;
2837 0 : _kdc_set_e_text(r, "Bad KDC options");
2838 0 : goto out;
2839 : }
2840 :
2841 : /*
2842 : * Build reply
2843 : */
2844 29665 : rep->pvno = 5;
2845 29665 : rep->msg_type = krb_as_rep;
2846 :
2847 59330 : if (!config->historical_anon_realm &&
2848 29665 : _kdc_is_anonymous(r->context, r->client_princ)) {
2849 0 : Realm anon_realm = KRB5_ANON_REALM;
2850 0 : ret = copy_Realm(&anon_realm, &rep->crealm);
2851 29665 : } else if (f.canonicalize || r->client->flags.force_canonicalize)
2852 29665 : ret = copy_Realm(&r->canon_client_princ->realm, &rep->crealm);
2853 : else
2854 0 : ret = copy_Realm(&r->client_princ->realm, &rep->crealm);
2855 29665 : if (ret)
2856 0 : goto out;
2857 29665 : if (r->et.flags.anonymous)
2858 0 : ret = _kdc_make_anonymous_principalname(&rep->cname);
2859 29665 : else if (f.canonicalize || r->client->flags.force_canonicalize)
2860 29665 : ret = _krb5_principal2principalname(&rep->cname, r->canon_client_princ);
2861 : else
2862 0 : ret = _krb5_principal2principalname(&rep->cname, r->client_princ);
2863 29665 : if (ret)
2864 0 : goto out;
2865 :
2866 29665 : rep->ticket.tkt_vno = 5;
2867 29665 : if (f.canonicalize || r->server->flags.force_canonicalize)
2868 29659 : ret = copy_Realm(&r->server->principal->realm, &rep->ticket.realm);
2869 : else
2870 6 : ret = copy_Realm(&r->server_princ->realm, &rep->ticket.realm);
2871 29665 : if (ret)
2872 0 : goto out;
2873 29665 : if (f.canonicalize || r->server->flags.force_canonicalize)
2874 29659 : _krb5_principal2principalname(&rep->ticket.sname,
2875 29659 : r->server->principal);
2876 : else
2877 6 : _krb5_principal2principalname(&rep->ticket.sname,
2878 6 : r->server_princ);
2879 : /* java 1.6 expects the name to be the same type, lets allow that
2880 : * uncomplicated name-types, when f.canonicalize is not set (to
2881 : * match Windows Server 1709). */
2882 : #define CNT(sp,t) (((sp)->sname->name_type) == KRB5_NT_##t)
2883 29665 : if (!f.canonicalize
2884 1501 : && (CNT(b, UNKNOWN) || CNT(b, PRINCIPAL) || CNT(b, SRV_INST) || CNT(b, SRV_HST) || CNT(b, SRV_XHST))) {
2885 1469 : rep->ticket.sname.name_type = b->sname->name_type;
2886 : }
2887 : #undef CNT
2888 :
2889 29665 : r->et.flags.initial = 1;
2890 29665 : if(r->client->flags.forwardable && r->server->flags.forwardable)
2891 29632 : r->et.flags.forwardable = f.forwardable;
2892 29665 : if(r->client->flags.proxiable && r->server->flags.proxiable)
2893 29626 : r->et.flags.proxiable = f.proxiable;
2894 39 : else if (f.proxiable) {
2895 4 : _kdc_set_e_text(r, "Ticket may not be proxiable");
2896 4 : ret = KRB5KDC_ERR_POLICY;
2897 4 : goto out;
2898 : }
2899 29661 : if(r->client->flags.postdate && r->server->flags.postdate)
2900 0 : r->et.flags.may_postdate = f.allow_postdate;
2901 29661 : else if (f.allow_postdate){
2902 0 : _kdc_set_e_text(r, "Ticket may not be postdateable");
2903 0 : ret = KRB5KDC_ERR_POLICY;
2904 0 : goto out;
2905 : }
2906 :
2907 29661 : if (b->addresses)
2908 98 : kdc_audit_addaddrs((kdc_request_t)r, b->addresses, "reqaddrs");
2909 :
2910 : /* check for valid set of addresses */
2911 29661 : if (!_kdc_check_addresses(r, b->addresses, r->addr)) {
2912 0 : if (r->config->warn_ticket_addresses) {
2913 0 : kdc_audit_setkv_bool((kdc_request_t)r, "wrongaddr", TRUE);
2914 : } else {
2915 0 : _kdc_set_e_text(r, "Request from wrong address");
2916 0 : ret = KRB5KRB_AP_ERR_BADADDR;
2917 0 : goto out;
2918 : }
2919 : }
2920 :
2921 29661 : ret = copy_PrincipalName(&rep->cname, &r->et.cname);
2922 29661 : if (ret)
2923 0 : goto out;
2924 29661 : ret = copy_Realm(&rep->crealm, &r->et.crealm);
2925 29661 : if (ret)
2926 0 : goto out;
2927 :
2928 : {
2929 1184 : time_t start;
2930 1184 : time_t t;
2931 :
2932 29661 : start = r->et.authtime = kdc_time;
2933 :
2934 29661 : if(f.postdated && req->req_body.from){
2935 0 : ALLOC(r->et.starttime);
2936 0 : start = *r->et.starttime = *req->req_body.from;
2937 0 : r->et.flags.invalid = 1;
2938 0 : r->et.flags.postdated = 1; /* XXX ??? */
2939 : }
2940 29661 : _kdc_fix_time(&b->till);
2941 29661 : t = *b->till;
2942 :
2943 : /* be careful not to overflow */
2944 :
2945 : /*
2946 : * Pre-auth can override r->client->max_life if configured.
2947 : *
2948 : * See pre-auth methods, specifically PKINIT, which can get or derive
2949 : * this from the client's certificate.
2950 : */
2951 29661 : if (r->pa_max_life > 0)
2952 0 : t = rk_time_add(start, min(rk_time_sub(t, start), r->pa_max_life));
2953 29661 : else if (r->client->max_life)
2954 29661 : t = rk_time_add(start, min(rk_time_sub(t, start),
2955 : *r->client->max_life));
2956 :
2957 29661 : if (r->server->max_life)
2958 29655 : t = rk_time_add(start, min(rk_time_sub(t, start),
2959 : *r->server->max_life));
2960 :
2961 : /* Pre-auth can bound endtime as well */
2962 29661 : if (r->pa_endtime > 0)
2963 45 : t = rk_time_add(start, min(rk_time_sub(t, start), r->pa_endtime));
2964 : #if 0
2965 : t = min(t, rk_time_add(start, realm->max_life));
2966 : #endif
2967 29661 : r->et.endtime = t;
2968 :
2969 29661 : if (start > r->et.endtime) {
2970 1 : _kdc_set_e_text(r, "Requested effective lifetime is negative or too short");
2971 1 : ret = KRB5KDC_ERR_NEVER_VALID;
2972 1 : goto out;
2973 : }
2974 :
2975 29660 : if(f.renewable_ok && r->et.endtime < *b->till){
2976 2 : f.renewable = 1;
2977 2 : if(b->rtime == NULL){
2978 2 : ALLOC(b->rtime);
2979 2 : *b->rtime = 0;
2980 : }
2981 2 : if(*b->rtime < *b->till)
2982 2 : *b->rtime = *b->till;
2983 : }
2984 29660 : if(f.renewable && b->rtime){
2985 3085 : t = *b->rtime;
2986 3085 : if(t == 0)
2987 14 : t = MAX_TIME;
2988 3085 : if(r->client->max_renew)
2989 3085 : t = rk_time_add(start, min(rk_time_sub(t, start),
2990 : *r->client->max_renew));
2991 3085 : if(r->server->max_renew)
2992 3085 : t = rk_time_add(start, min(rk_time_sub(t, start),
2993 : *r->server->max_renew));
2994 : #if 0
2995 : t = min(t, rk_time_add(start, realm->max_renew));
2996 : #endif
2997 3085 : ALLOC(r->et.renew_till);
2998 3085 : *r->et.renew_till = t;
2999 3085 : r->et.flags.renewable = 1;
3000 : }
3001 : }
3002 :
3003 29660 : if(b->addresses){
3004 98 : ALLOC(r->et.caddr);
3005 98 : copy_HostAddresses(b->addresses, r->et.caddr);
3006 : }
3007 :
3008 29660 : r->et.transited.tr_type = domain_X500_Compress;
3009 29660 : krb5_data_zero(&r->et.transited.contents);
3010 :
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 : */
3020 29660 : r->ek.last_req.val = malloc(2 * sizeof(*r->ek.last_req.val));
3021 29660 : if (r->ek.last_req.val == NULL) {
3022 0 : ret = ENOMEM;
3023 0 : goto out;
3024 : }
3025 29660 : r->ek.last_req.len = 0;
3026 29660 : if (r->client->pw_end
3027 26173 : && (config->kdc_warn_pwexpire == 0
3028 0 : || kdc_time + config->kdc_warn_pwexpire >= *r->client->pw_end)) {
3029 26173 : r->ek.last_req.val[r->ek.last_req.len].lr_type = LR_PW_EXPTIME;
3030 26173 : r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->pw_end;
3031 26173 : ++r->ek.last_req.len;
3032 : }
3033 29660 : if (r->client->valid_end) {
3034 0 : r->ek.last_req.val[r->ek.last_req.len].lr_type = LR_ACCT_EXPTIME;
3035 0 : r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->valid_end;
3036 0 : ++r->ek.last_req.len;
3037 : }
3038 29660 : if (r->ek.last_req.len == 0) {
3039 3487 : r->ek.last_req.val[r->ek.last_req.len].lr_type = LR_NONE;
3040 3487 : r->ek.last_req.val[r->ek.last_req.len].lr_value = 0;
3041 3487 : ++r->ek.last_req.len;
3042 : }
3043 : /* Set the nonce if it’s not already set. */
3044 29660 : if (!r->ek.nonce) {
3045 29617 : r->ek.nonce = b->nonce;
3046 : }
3047 29660 : if (r->client->valid_end || r->client->pw_end) {
3048 26173 : ALLOC(r->ek.key_expiration);
3049 26173 : if (r->client->valid_end) {
3050 0 : if (r->client->pw_end)
3051 0 : *r->ek.key_expiration = min(*r->client->valid_end,
3052 : *r->client->pw_end);
3053 : else
3054 0 : *r->ek.key_expiration = *r->client->valid_end;
3055 : } else
3056 26173 : *r->ek.key_expiration = *r->client->pw_end;
3057 : } else
3058 3487 : r->ek.key_expiration = NULL;
3059 29660 : r->ek.flags = r->et.flags;
3060 29660 : r->ek.authtime = r->et.authtime;
3061 29660 : if (r->et.starttime) {
3062 0 : ALLOC(r->ek.starttime);
3063 0 : *r->ek.starttime = *r->et.starttime;
3064 : }
3065 29660 : r->ek.endtime = r->et.endtime;
3066 29660 : if (r->et.renew_till) {
3067 3085 : ALLOC(r->ek.renew_till);
3068 3085 : *r->ek.renew_till = *r->et.renew_till;
3069 : }
3070 29660 : ret = copy_Realm(&rep->ticket.realm, &r->ek.srealm);
3071 29660 : if (ret)
3072 0 : goto out;
3073 29660 : ret = copy_PrincipalName(&rep->ticket.sname, &r->ek.sname);
3074 29660 : if (ret)
3075 0 : goto out;
3076 29660 : if(r->et.caddr){
3077 98 : ALLOC(r->ek.caddr);
3078 98 : copy_HostAddresses(r->et.caddr, r->ek.caddr);
3079 : }
3080 :
3081 : /*
3082 : * Check session and reply keys
3083 : */
3084 :
3085 29660 : if (r->session_key.keytype == ETYPE_NULL) {
3086 29615 : ret = krb5_generate_random_keyblock(r->context, r->sessionetype, &r->session_key);
3087 29615 : if (ret)
3088 0 : goto out;
3089 : }
3090 :
3091 29660 : if (r->reply_key.keytype == ETYPE_NULL) {
3092 0 : _kdc_set_e_text(r, "Client has no reply key");
3093 0 : ret = KRB5KDC_ERR_CLIENT_NOTYET;
3094 0 : goto out;
3095 : }
3096 :
3097 29660 : ret = copy_EncryptionKey(&r->session_key, &r->et.key);
3098 29660 : if (ret)
3099 0 : goto out;
3100 :
3101 29660 : ret = copy_EncryptionKey(&r->session_key, &r->ek.key);
3102 29660 : if (ret)
3103 0 : goto out;
3104 :
3105 29660 : if (r->client->flags.synthetic) {
3106 0 : ret = add_synthetic_princ_ad(r);
3107 0 : if (ret)
3108 0 : goto out;
3109 : }
3110 :
3111 29660 : _kdc_log_timestamp(r, "AS-REQ", r->et.authtime,
3112 : r->et.starttime, r->et.endtime,
3113 : r->et.renew_till);
3114 :
3115 29660 : _log_astgs_req(r, setype);
3116 :
3117 : /*
3118 : * We always say we support FAST/enc-pa-rep
3119 : */
3120 :
3121 29660 : r->et.flags.enc_pa_rep = r->ek.flags.enc_pa_rep = 1;
3122 :
3123 : /*
3124 : * update reply-key with strengthen-key
3125 : */
3126 :
3127 29660 : ret = _kdc_fast_strengthen_reply_key(r);
3128 29660 : if (ret)
3129 0 : goto out;
3130 :
3131 : /*
3132 : * Add REQ_ENC_PA_REP if client supports it
3133 : */
3134 :
3135 29660 : i = 0;
3136 29660 : pa = _kdc_find_padata(req, &i, KRB5_PADATA_REQ_ENC_PA_REP);
3137 29660 : if (pa) {
3138 :
3139 26137 : ret = add_enc_pa_rep(r);
3140 26137 : if (ret) {
3141 0 : msg = krb5_get_error_message(r->context, ret);
3142 0 : _kdc_r_log(r, 4, "add_enc_pa_rep failed: %s: %d", msg, ret);
3143 0 : krb5_free_error_message(r->context, msg);
3144 0 : goto out;
3145 : }
3146 : }
3147 :
3148 : /* Add the PAC */
3149 29660 : if (!r->et.flags.anonymous) {
3150 29660 : ret = generate_pac(r, skey, krbtgt_key, is_tgs);
3151 29660 : if (ret)
3152 4 : 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 :
3160 : /*
3161 : * Last chance for plugins to update reply
3162 : */
3163 29656 : ret = _kdc_finalize_reply(r);
3164 29656 : if (ret)
3165 0 : goto out;
3166 :
3167 : /*
3168 : * Don't send kvno from client entry if the pre-authentication
3169 : * mechanism replaced the reply key.
3170 : */
3171 :
3172 34392 : ret = _kdc_encode_reply(r->context, config,
3173 29656 : r, req->req_body.nonce, setype,
3174 29656 : r->server->kvno, &skey->key,
3175 29611 : pa_used_flag_isset(r, PA_REPLACE_REPLY_KEY) ? 0 : r->client->kvno,
3176 29656 : 0, r->reply);
3177 29656 : if (ret)
3178 0 : goto out;
3179 :
3180 : /*
3181 : * Check if message is too large
3182 : */
3183 29656 : if (r->datagram_reply && r->reply->length > config->max_datagram_reply_length) {
3184 12235 : krb5_data_free(r->reply);
3185 12235 : ret = KRB5KRB_ERR_RESPONSE_TOO_BIG;
3186 12235 : _kdc_set_e_text(r, "Reply packet too large");
3187 : }
3188 :
3189 17421 : out:
3190 51200 : if (ret) {
3191 : /* Overwrite ‘error_code’ only if we have an actual error. */
3192 33241 : r->error_code = ret;
3193 : }
3194 : {
3195 51200 : krb5_error_code ret2 = _kdc_audit_request(r);
3196 51200 : if (ret2) {
3197 22 : krb5_data_free(r->reply);
3198 22 : ret = ret2;
3199 : }
3200 : }
3201 :
3202 : /*
3203 : * In case of a non proxy error, build an error message.
3204 : */
3205 51200 : if (ret != 0 && ret != HDB_ERR_NOT_FOUND_HERE && r->reply->length == 0) {
3206 31594 : kdc_log(r->context, config, 5, "as-req: sending error: %d to client", ret);
3207 32778 : ret = _kdc_fast_mk_error(r,
3208 : r->rep.padata,
3209 : r->armor_crypto,
3210 31594 : &req->req_body,
3211 31594 : r->error_code ? r->error_code : ret,
3212 : r->client_princ,
3213 : r->server_princ,
3214 : NULL, NULL,
3215 31594 : r->reply);
3216 : }
3217 :
3218 51200 : if (r->pa_used && r->pa_used->cleanup)
3219 0 : r->pa_used->cleanup(r);
3220 :
3221 51200 : free_AS_REP(&r->rep);
3222 51200 : free_EncTicketPart(&r->et);
3223 51200 : free_EncKDCRepPart(&r->ek);
3224 51200 : _kdc_free_fast_state(&r->fast);
3225 :
3226 51200 : if (r->client_princ) {
3227 51185 : krb5_free_principal(r->context, r->client_princ);
3228 51185 : r->client_princ = NULL;
3229 : }
3230 51200 : if (r->server_princ){
3231 51185 : krb5_free_principal(r->context, r->server_princ);
3232 51185 : r->server_princ = NULL;
3233 : }
3234 51200 : if (r->client)
3235 49109 : _kdc_free_ent(r->context, r->clientdb, r->client);
3236 51200 : if (r->server)
3237 48569 : _kdc_free_ent(r->context, r->serverdb, r->server);
3238 51200 : if (r->krbtgt)
3239 5115 : _kdc_free_ent(r->context, r->krbtgtdb, r->krbtgt);
3240 51200 : if (r->armor_crypto) {
3241 469 : krb5_crypto_destroy(r->context, r->armor_crypto);
3242 469 : r->armor_crypto = NULL;
3243 : }
3244 51200 : if (r->armor_ticket)
3245 469 : krb5_free_ticket(r->context, r->armor_ticket);
3246 51200 : if (r->armor_server)
3247 469 : _kdc_free_ent(r->context, r->armor_serverdb, r->armor_server);
3248 51200 : krb5_free_keyblock_contents(r->context, &r->reply_key);
3249 51200 : krb5_free_keyblock_contents(r->context, &r->enc_ad_key);
3250 51200 : krb5_free_keyblock_contents(r->context, &r->session_key);
3251 51200 : krb5_free_keyblock_contents(r->context, &r->strengthen_key);
3252 51200 : krb5_pac_free(r->context, r->pac);
3253 :
3254 51200 : return ret;
3255 : }
|