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 82785 : _kdc_fix_time(time_t **t)
58 : {
59 82785 : if(*t == NULL){
60 0 : ALLOC(*t);
61 0 : **t = MAX_TIME;
62 : }
63 82785 : if(**t == 0) **t = MAX_TIME; /* fix for old clients */
64 82785 : }
65 :
66 : static int
67 47637 : realloc_method_data(METHOD_DATA *md)
68 : {
69 1743 : PA_DATA *pa;
70 47637 : pa = realloc(md->val, (md->len + 1) * sizeof(*md->val));
71 47637 : if(pa == NULL)
72 0 : return ENOMEM;
73 47637 : md->val = pa;
74 47637 : md->len++;
75 47637 : 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 30265 : set_salt_padata(krb5_context context,
86 : krb5_kdc_configuration *config,
87 : METHOD_DATA *md, Key *key)
88 : {
89 30265 : if (!key->salt)
90 1220 : return 0;
91 :
92 29033 : return get_pa_etype_info2(context, config, md, key, TRUE);
93 : }
94 :
95 : const PA_DATA*
96 513991 : _kdc_find_padata(const KDC_REQ *req, int *start, int type)
97 : {
98 513991 : if (req->padata == NULL)
99 5782 : return NULL;
100 :
101 1018787 : while((size_t)*start < req->padata->len){
102 711377 : (*start)++;
103 711377 : if(req->padata->val[*start - 1].padata_type == (unsigned)type)
104 200799 : return &req->padata->val[*start - 1];
105 : }
106 296489 : 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 18604 : is_default_salt_p(const krb5_salt *default_salt, const Key *key)
133 : {
134 18604 : if (key->salt == NULL)
135 991 : return TRUE;
136 17610 : if (default_salt->salttype != key->salt->type)
137 0 : return FALSE;
138 17610 : if (krb5_data_cmp(&default_salt->saltvalue, &key->salt->salt) != 0)
139 4500 : return FALSE;
140 12631 : 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 18604 : is_good_salt_p(const krb5_salt *default_salt, const Key *key)
154 : {
155 18604 : if (key->key.keytype == KRB5_ENCTYPE_DES_CBC_CRC)
156 0 : return is_default_salt_p(default_salt, key);
157 :
158 18019 : return TRUE;
159 : }
160 :
161 : krb5_boolean
162 30580 : _kdc_is_anon_request(const KDC_REQ *req)
163 : {
164 30580 : 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 59886 : return b->kdc_options.request_anonymous ||
174 30476 : (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 18606 : _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 585 : krb5_boolean use_strongest_session_key;
200 18606 : krb5_boolean is_preauth = flags & KFE_IS_PREAUTH;
201 18606 : krb5_boolean is_tgs = flags & KFE_IS_TGS;
202 585 : hdb_entry *princ;
203 585 : krb5_principal request_princ;
204 585 : krb5_error_code ret;
205 585 : krb5_salt def_salt;
206 18606 : krb5_enctype enctype = ETYPE_NULL;
207 585 : const krb5_enctype *p;
208 18606 : Key *key = NULL;
209 585 : size_t i, k, m;
210 :
211 18606 : if (is_preauth && (flags & KFE_USE_CLIENT) &&
212 18606 : r->client->flags.synthetic)
213 0 : return KRB5KDC_ERR_ETYPE_NOSUPP;
214 :
215 18606 : if ((flags & KFE_USE_CLIENT) && !r->client->flags.synthetic) {
216 18606 : princ = r->client;
217 18606 : request_princ = r->client_princ;
218 : } else {
219 0 : princ = r->server;
220 0 : request_princ = r->server->principal;
221 : }
222 :
223 19191 : use_strongest_session_key =
224 18606 : is_preauth ? r->config->preauth_use_strongest_session_key
225 18606 : : (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 18606 : ret = krb5_get_pw_salt(r->context, request_princ, &def_salt);
230 18606 : if (ret)
231 0 : return ret;
232 :
233 18606 : 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 18606 : 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 18606 : p = krb5_kerberos_enctypes(r->context);
264 18606 : for (i = 0;
265 42616 : p[i] != ETYPE_NULL && enctype == ETYPE_NULL;
266 24010 : i++) {
267 24010 : 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 57998 : for (k = 0; k < len && enctype == ETYPE_NULL; k++) {
273 :
274 33988 : if (p[i] != etypes[k])
275 14147 : continue;
276 :
277 19841 : 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 19841 : key = NULL;
290 19841 : 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 20426 : while (hdb_next_enctype2key(r->context, princ, NULL,
312 38445 : p[i], &key) == 0) {
313 18604 : if (key->key.keyvalue.length == 0) {
314 0 : ret = KRB5KDC_ERR_NULL_KEY;
315 0 : continue;
316 : }
317 18604 : enctype = p[i];
318 18604 : ret = 0;
319 36623 : if (is_preauth && ret_key != NULL &&
320 19789 : !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 18606 : 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 18606 : if (ret == 0) {
375 18604 : if (ret_enctype != NULL)
376 0 : *ret_enctype = enctype;
377 18604 : if (ret_key != NULL)
378 18604 : *ret_key = key;
379 18604 : if (ret_default_salt != NULL)
380 18604 : *ret_default_salt = is_default_salt_p(&def_salt, key);
381 : }
382 :
383 18606 : krb5_free_salt (r->context, def_salt);
384 18606 : 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 99049 : _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 3413 : size_t i;
398 :
399 99049 : 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 107729 : for (i = 0; i < len; ++i) {
406 : size_t j;
407 :
408 : /* Check that the server also supports the etype. */
409 125472 : for (j = 0; j < princ->session_etypes->len; ++j) {
410 116732 : if (princ->session_etypes->val[j] == etypes[i]) {
411 98766 : *ret_enctype = etypes[i];
412 98766 : return 0;
413 : }
414 : }
415 : }
416 :
417 223 : return KRB5KDC_ERR_ETYPE_NOSUPP;
418 : }
419 :
420 : krb5_error_code
421 42732 : _kdc_make_anonymous_principalname (PrincipalName *pn)
422 : {
423 42732 : pn->name_type = KRB5_NT_WELLKNOWN;
424 42732 : pn->name_string.len = 2;
425 42732 : pn->name_string.val = calloc(2, sizeof(*pn->name_string.val));
426 42732 : if (pn->name_string.val == NULL)
427 0 : goto failed;
428 :
429 42732 : pn->name_string.val[0] = strdup(KRB5_WELLKNOWN_NAME);
430 42732 : if (pn->name_string.val[0] == NULL)
431 0 : goto failed;
432 :
433 42732 : pn->name_string.val[1] = strdup(KRB5_ANON_NAME);
434 42732 : if (pn->name_string.val[1] == NULL)
435 0 : goto failed;
436 :
437 41074 : 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 184323 : _kdc_r_log(astgs_request_t r, int level, const char *fmt, ...)
451 : __attribute__ ((__format__ (__printf__, 3, 4)))
452 : {
453 6826 : va_list ap;
454 6826 : char *s;
455 184323 : va_start(ap, fmt);
456 184323 : s = kdc_log_msg_va(r->context, r->config, level, fmt, ap);
457 184323 : if(s) free(s);
458 184323 : va_end(ap);
459 184323 : }
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 30750 : _kdc_set_e_text(astgs_request_t r, const char *fmt, ...)
478 : __attribute__ ((__format__ (__printf__, 2, 3)))
479 : {
480 1170 : va_list ap;
481 30750 : char *e_text = NULL;
482 1170 : int vasprintf_ret;
483 :
484 30750 : va_start(ap, fmt);
485 30750 : vasprintf_ret = vasprintf(&e_text, fmt, ap);
486 30750 : va_end(ap);
487 :
488 30750 : 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 30750 : 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 30750 : r->e_text = e_text;
504 30750 : r->e_text_buf = e_text;
505 30750 : kdc_log(r->context, r->config, 4, "%s", e_text);
506 : }
507 :
508 : void
509 79598 : _kdc_log_timestamp(astgs_request_t r, const char *type,
510 : KerberosTime authtime, KerberosTime *starttime,
511 : KerberosTime endtime, KerberosTime *renew_till)
512 : {
513 79598 : krb5_kdc_configuration *config = r->config;
514 2828 : char authtime_str[100], starttime_str[100],
515 : endtime_str[100], renewtime_str[100];
516 :
517 79598 : if (authtime)
518 79598 : kdc_audit_setkv_number((kdc_request_t)r, "auth", authtime);
519 79598 : if (starttime && *starttime)
520 49297 : kdc_audit_setkv_number((kdc_request_t)r, "start", *starttime);
521 79598 : if (endtime)
522 79598 : kdc_audit_setkv_number((kdc_request_t)r, "end", endtime);
523 79598 : if (renew_till && *renew_till)
524 6793 : kdc_audit_setkv_number((kdc_request_t)r, "renew", *renew_till);
525 :
526 79598 : krb5_format_time(r->context, authtime,
527 : authtime_str, sizeof(authtime_str), TRUE);
528 79598 : if (starttime)
529 49297 : krb5_format_time(r->context, *starttime,
530 : starttime_str, sizeof(starttime_str), TRUE);
531 : else
532 30301 : strlcpy(starttime_str, "unset", sizeof(starttime_str));
533 79598 : krb5_format_time(r->context, endtime,
534 : endtime_str, sizeof(endtime_str), TRUE);
535 79598 : if (renew_till)
536 6793 : krb5_format_time(r->context, *renew_till,
537 : renewtime_str, sizeof(renewtime_str), TRUE);
538 : else
539 72805 : strlcpy(renewtime_str, "unset", sizeof(renewtime_str));
540 :
541 79598 : 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 79598 : }
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 30819 : 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 1170 : krb5_error_code ret;
1028 1170 : krb5_crypto crypto;
1029 30819 : Key *pa_key = NULL;
1030 30819 : const Keys *keys = NULL;
1031 :
1032 30819 : if (_pa_key)
1033 30511 : *_pa_key = NULL;
1034 :
1035 30819 : krb5_data_zero(ts_data);
1036 :
1037 30819 : keys = hdb_kvno2keys(r->context, r->client, kvno);
1038 30819 : if (keys == NULL) {
1039 158 : return KRB5KDC_ERR_ETYPE_NOSUPP;
1040 : }
1041 31831 : ret = hdb_enctype2key(r->context, r->client, keys,
1042 30661 : enc_data->etype, &pa_key);
1043 30661 : if(ret){
1044 5 : return KRB5KDC_ERR_ETYPE_NOSUPP;
1045 : }
1046 :
1047 30656 : try_next_key:
1048 30656 : ret = krb5_crypto_init(r->context, &pa_key->key, 0, &crypto);
1049 30656 : 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 30656 : ret = krb5_decrypt_EncryptedData(r->context,
1057 : crypto,
1058 : KRB5_KU_PA_ENC_TIMESTAMP,
1059 : enc_data,
1060 : ts_data);
1061 30656 : 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 30656 : if (ret) {
1068 415 : ret = hdb_next_enctype2key(r->context, r->client, keys,
1069 415 : enc_data->etype, &pa_key);
1070 415 : if (ret == 0)
1071 0 : goto try_next_key;
1072 :
1073 415 : return KRB5KDC_ERR_PREAUTH_FAILED;
1074 : }
1075 :
1076 30241 : if (_pa_key)
1077 30111 : *_pa_key = pa_key;
1078 29071 : return 0;
1079 : }
1080 :
1081 : static krb5_error_code
1082 30512 : pa_enc_ts_validate(astgs_request_t r, const PA_DATA *pa)
1083 : {
1084 30512 : krb5_kvno kvno = r->client->kvno;
1085 1170 : EncryptedData enc_data;
1086 1170 : krb5_error_code ret;
1087 1170 : krb5_data ts_data;
1088 1170 : PA_ENC_TS_ENC p;
1089 1170 : size_t len;
1090 1170 : Key *pa_key;
1091 1170 : char *str;
1092 :
1093 30512 : 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 30511 : } 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 30511 : 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 31681 : ret = decode_EncryptedData(pa->padata_value.data,
1115 30511 : pa->padata_value.length,
1116 : &enc_data,
1117 : &len);
1118 30511 : 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 30511 : ret = pa_enc_ts_decrypt_kvno(r, kvno, &enc_data, &ts_data, &pa_key);
1126 30511 : 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 30506 : if (ret == KRB5KDC_ERR_PREAUTH_FAILED) {
1147 0 : krb5_error_code ret2;
1148 395 : const char *msg = krb5_get_error_message(r->context, ret);
1149 395 : krb5_error_code hret = ret;
1150 0 : int hi;
1151 :
1152 395 : 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 415 : for (hi = 1; hi < 3; hi++) {
1161 0 : krb5_kvno hkvno;
1162 :
1163 408 : if (hi >= kvno) {
1164 100 : 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 395 : ret2 = krb5_enctype_to_string(r->context, enc_data.etype, &str);
1185 395 : if (ret2)
1186 0 : str = NULL;
1187 395 : _kdc_r_log(r, 2, "Failed to decrypt PA-DATA -- %s "
1188 : "(enctype %s) error %s",
1189 395 : r->cname, str ? str : "unknown enctype", msg);
1190 395 : krb5_xfree(str);
1191 395 : krb5_free_error_message(r->context, msg);
1192 395 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_PA_ETYPE,
1193 395 : enc_data.etype);
1194 395 : 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 265 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
1199 : KDC_AUTH_EVENT_WRONG_LONG_TERM_KEY);
1200 :
1201 395 : free_EncryptedData(&enc_data);
1202 :
1203 395 : ret = KRB5KDC_ERR_PREAUTH_FAILED;
1204 395 : goto out;
1205 : }
1206 30111 : free_EncryptedData(&enc_data);
1207 30111 : ret = decode_PA_ENC_TS_ENC(ts_data.data,
1208 : ts_data.length,
1209 : &p,
1210 : &len);
1211 30111 : krb5_data_free(&ts_data);
1212 30111 : 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 30111 : 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 30102 : free_PA_ENC_TS_ENC(&p);
1244 :
1245 30102 : ret = set_salt_padata(r->context, r->config, r->rep.padata, pa_key);
1246 30090 : if (ret == 0)
1247 30102 : ret = krb5_copy_keyblock_contents(r->context, &pa_key->key, &r->reply_key);
1248 30102 : if (ret)
1249 0 : return ret;
1250 :
1251 30102 : ret = krb5_enctype_to_string(r->context, pa_key->key.keytype, &str);
1252 30102 : if (ret)
1253 0 : str = NULL;
1254 30102 : _kdc_r_log(r, 4, "ENC-TS Pre-authentication succeeded -- %s using %s",
1255 30102 : r->cname, str ? str : "unknown enctype");
1256 30102 : krb5_xfree(str);
1257 30102 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_PA_ETYPE,
1258 30102 : pa_key->key.keytype);
1259 30102 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
1260 : KDC_AUTH_EVENT_VALIDATED_LONG_TERM_KEY);
1261 30102 : kdc_audit_setkv_number((kdc_request_t)r,
1262 : KDC_REQUEST_KV_PA_SUCCEEDED_KVNO,
1263 : kvno);
1264 :
1265 30102 : ret = 0;
1266 :
1267 29341 : out:
1268 :
1269 29341 : 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 18177 : send_freshness_token(astgs_request_t r, const Key *krbtgt_key, unsigned krbtgt_kvno)
1357 : {
1358 18177 : krb5_error_code ret = 0;
1359 : #ifdef PKINIT
1360 18177 : int idx = 0;
1361 18177 : const PA_DATA *freshness_padata = NULL;
1362 :
1363 18177 : freshness_padata = _kdc_find_padata(&r->req,
1364 : &idx,
1365 : KRB5_PADATA_AS_FRESHNESS);
1366 18177 : if (freshness_padata == NULL) {
1367 17588 : 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 : krb5_error_code (*validate)(astgs_request_t, const PA_DATA *pa);
1386 : krb5_error_code (*finalize_pac)(astgs_request_t r);
1387 : void (*cleanup)(astgs_request_t r);
1388 : };
1389 :
1390 : static const struct kdc_patypes pat[] = {
1391 : #ifdef PKINIT
1392 : {
1393 : KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)",
1394 : PA_ANNOUNCE | PA_SYNTHETIC_OK | PA_REPLACE_REPLY_KEY,
1395 : pa_pkinit_validate, NULL, NULL
1396 : },
1397 : {
1398 : KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", PA_ANNOUNCE | PA_REPLACE_REPLY_KEY,
1399 : pa_pkinit_validate, NULL, NULL
1400 : },
1401 : {
1402 : KRB5_PADATA_PKINIT_KX, "Anonymous PK-INIT", PA_ANNOUNCE,
1403 : NULL, NULL, NULL
1404 : },
1405 : #else
1406 : { KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)", 0, NULL , NULL, NULL },
1407 : { KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", 0, NULL, NULL, NULL },
1408 : { KRB5_PADATA_PKINIT_KX, "Anonymous PK-INIT", 0, NULL, NULL, NULL },
1409 : #endif
1410 : { KRB5_PADATA_PA_PK_OCSP_RESPONSE , "OCSP", 0, NULL, NULL, NULL },
1411 : {
1412 : KRB5_PADATA_ENC_TIMESTAMP , "ENC-TS",
1413 : PA_ANNOUNCE | PA_USES_LONG_TERM_KEY,
1414 : pa_enc_ts_validate, NULL, NULL
1415 : },
1416 : {
1417 : KRB5_PADATA_ENCRYPTED_CHALLENGE , "ENC-CHAL",
1418 : PA_ANNOUNCE | PA_USES_LONG_TERM_KEY | PA_REQ_FAST,
1419 : pa_enc_chal_validate, NULL, NULL
1420 : },
1421 : { KRB5_PADATA_REQ_ENC_PA_REP , "REQ-ENC-PA-REP", 0, NULL, NULL, NULL },
1422 : { KRB5_PADATA_FX_FAST, "FX-FAST", PA_ANNOUNCE, NULL, NULL, NULL },
1423 : { KRB5_PADATA_FX_ERROR, "FX-ERROR", 0, NULL, NULL, NULL },
1424 : { KRB5_PADATA_FX_COOKIE, "FX-COOKIE", 0, NULL, NULL, NULL },
1425 : {
1426 : KRB5_PADATA_GSS , "GSS",
1427 : PA_ANNOUNCE | PA_SYNTHETIC_OK | PA_REPLACE_REPLY_KEY | PA_USES_FAST_COOKIE,
1428 : pa_gss_validate, pa_gss_finalize_pac, NULL
1429 : },
1430 : };
1431 :
1432 : static void
1433 46126 : log_patypes(astgs_request_t r, METHOD_DATA *padata)
1434 : {
1435 46126 : krb5_kdc_configuration *config = r->config;
1436 46126 : struct rk_strpool *p = NULL;
1437 1755 : char *str;
1438 1755 : size_t n, m;
1439 :
1440 121750 : for (n = 0; n < padata->len; n++) {
1441 483424 : for (m = 0; m < sizeof(pat) / sizeof(pat[0]); m++) {
1442 480307 : if (padata->val[n].padata_type == pat[m].type) {
1443 72507 : p = rk_strpoolprintf(p, "%s", pat[m].name);
1444 72507 : break;
1445 : }
1446 : }
1447 75624 : if (m == sizeof(pat) / sizeof(pat[0]))
1448 3117 : p = rk_strpoolprintf(p, "%d", padata->val[n].padata_type);
1449 75624 : if (p && n + 1 < padata->len)
1450 29498 : p = rk_strpoolprintf(p, ", ");
1451 75624 : if (p == NULL) {
1452 0 : kdc_log(r->context, config, 1, "out of memory");
1453 0 : return;
1454 : }
1455 : }
1456 46126 : if (p == NULL)
1457 0 : p = rk_strpoolprintf(p, "none");
1458 :
1459 46126 : str = rk_strpoolcollect(p);
1460 46126 : kdc_log(r->context, config, 4, "Client sent patypes: %s", str);
1461 46126 : kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE,
1462 : "client-pa", "%s", str);
1463 46126 : free(str);
1464 : }
1465 :
1466 : static krb5_boolean
1467 60605 : pa_used_flag_isset(astgs_request_t r, unsigned int flag)
1468 : {
1469 60605 : if (r->pa_used == NULL)
1470 0 : return FALSE;
1471 :
1472 60605 : return (r->pa_used->flags & flag) == flag;
1473 : }
1474 :
1475 : /*
1476 : *
1477 : */
1478 :
1479 : krb5_error_code
1480 79598 : _kdc_encode_reply(krb5_context context,
1481 : krb5_kdc_configuration *config,
1482 : astgs_request_t r, uint32_t nonce,
1483 : krb5_enctype etype,
1484 : int skvno, const EncryptionKey *skey,
1485 : int ckvno,
1486 : int rk_is_subkey,
1487 : krb5_data *reply)
1488 : {
1489 2828 : unsigned char *buf;
1490 2828 : size_t buf_size;
1491 79598 : size_t len = 0;
1492 2828 : krb5_error_code ret;
1493 2828 : krb5_crypto crypto;
1494 79598 : KDC_REP *rep = &r->rep;
1495 79598 : EncTicketPart *et = &r->et;
1496 79598 : EncKDCRepPart *ek = &r->ek;
1497 :
1498 79598 : heim_assert(rep->padata != NULL, "reply padata uninitialized");
1499 :
1500 79598 : ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret);
1501 79598 : if(ret) {
1502 0 : const char *msg = krb5_get_error_message(context, ret);
1503 0 : kdc_log(context, config, 4, "Failed to encode ticket: %s", msg);
1504 0 : krb5_free_error_message(context, msg);
1505 0 : return ret;
1506 : }
1507 79598 : if(buf_size != len)
1508 0 : krb5_abortx(context, "Internal error in ASN.1 encoder");
1509 :
1510 79598 : ret = krb5_crypto_init(context, skey, etype, &crypto);
1511 79598 : if (ret) {
1512 0 : const char *msg = krb5_get_error_message(context, ret);
1513 0 : kdc_log(context, config, 4, "krb5_crypto_init failed: %s", msg);
1514 0 : krb5_free_error_message(context, msg);
1515 0 : free(buf);
1516 0 : return ret;
1517 : }
1518 :
1519 79598 : ret = krb5_encrypt_EncryptedData(context,
1520 : crypto,
1521 : KRB5_KU_TICKET,
1522 : buf,
1523 : len,
1524 : skvno,
1525 : &rep->ticket.enc_part);
1526 79598 : free(buf);
1527 79598 : krb5_crypto_destroy(context, crypto);
1528 79598 : if(ret) {
1529 0 : const char *msg = krb5_get_error_message(context, ret);
1530 0 : kdc_log(context, config, 4, "Failed to encrypt data: %s", msg);
1531 0 : krb5_free_error_message(context, msg);
1532 0 : return ret;
1533 : }
1534 :
1535 79598 : if (r && r->armor_crypto) {
1536 1658 : KrbFastFinished finished;
1537 1658 : krb5_data data;
1538 :
1539 43130 : kdc_log(context, config, 4, "FAST armor protection");
1540 :
1541 43130 : memset(&finished, 0, sizeof(finished));
1542 43130 : krb5_data_zero(&data);
1543 :
1544 43130 : finished.timestamp = kdc_time;
1545 43130 : finished.usec = 0;
1546 43130 : finished.crealm = et->crealm;
1547 43130 : finished.cname = et->cname;
1548 :
1549 43130 : ASN1_MALLOC_ENCODE(Ticket, data.data, data.length,
1550 : &rep->ticket, &len, ret);
1551 43130 : if (ret)
1552 0 : return ret;
1553 43130 : if (data.length != len)
1554 0 : krb5_abortx(context, "internal asn.1 error");
1555 :
1556 43130 : ret = krb5_create_checksum(context, r->armor_crypto,
1557 : KRB5_KU_FAST_FINISHED, 0,
1558 : data.data, data.length,
1559 : &finished.ticket_checksum);
1560 43130 : krb5_data_free(&data);
1561 43130 : if (ret)
1562 0 : return ret;
1563 :
1564 43130 : ret = _kdc_fast_mk_response(context, r->armor_crypto,
1565 : rep->padata, &r->strengthen_key, &finished,
1566 : nonce, &data);
1567 43130 : free_Checksum(&finished.ticket_checksum);
1568 43130 : if (ret)
1569 0 : return ret;
1570 :
1571 43130 : free_METHOD_DATA(r->rep.padata);
1572 :
1573 43130 : ret = krb5_padata_add(context, rep->padata,
1574 : KRB5_PADATA_FX_FAST,
1575 : data.data, data.length);
1576 43130 : if (ret)
1577 0 : return ret;
1578 :
1579 : /*
1580 : * Hide client name for privacy reasons
1581 : */
1582 43130 : if (r->fast.flags.requested_hidden_names) {
1583 42732 : Realm anon_realm = KRB5_ANON_REALM;
1584 :
1585 42732 : free_Realm(&rep->crealm);
1586 42732 : ret = copy_Realm(&anon_realm, &rep->crealm);
1587 42732 : if (ret == 0) {
1588 42732 : free_PrincipalName(&rep->cname);
1589 42732 : ret = _kdc_make_anonymous_principalname(&rep->cname);
1590 : }
1591 42732 : if (ret)
1592 0 : return ret;
1593 : }
1594 : }
1595 :
1596 79598 : if (rep->padata->len == 0) {
1597 7559 : free_METHOD_DATA(rep->padata);
1598 7559 : free(rep->padata);
1599 7559 : rep->padata = NULL;
1600 : }
1601 :
1602 79598 : if(rep->msg_type == krb_as_rep && !config->encode_as_rep_as_tgs_rep)
1603 30301 : ASN1_MALLOC_ENCODE(EncASRepPart, buf, buf_size, ek, &len, ret);
1604 : else
1605 49297 : ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret);
1606 79598 : if(ret) {
1607 0 : const char *msg = krb5_get_error_message(context, ret);
1608 0 : kdc_log(context, config, 4, "Failed to encode KDC-REP: %s", msg);
1609 0 : krb5_free_error_message(context, msg);
1610 0 : return ret;
1611 : }
1612 79598 : if(buf_size != len) {
1613 0 : free(buf);
1614 0 : kdc_log(context, config, 4, "Internal error in ASN.1 encoder");
1615 0 : _kdc_set_e_text(r, "KDC internal error");
1616 0 : return KRB5KRB_ERR_GENERIC;
1617 : }
1618 79598 : ret = krb5_crypto_init(context, &r->reply_key, 0, &crypto);
1619 79598 : if (ret) {
1620 0 : const char *msg = krb5_get_error_message(context, ret);
1621 0 : free(buf);
1622 0 : kdc_log(context, config, 4, "krb5_crypto_init failed: %s", msg);
1623 0 : krb5_free_error_message(context, msg);
1624 0 : return ret;
1625 : }
1626 79598 : if(rep->msg_type == krb_as_rep) {
1627 30301 : ret = krb5_encrypt_EncryptedData(context,
1628 : crypto,
1629 : KRB5_KU_AS_REP_ENC_PART,
1630 : buf,
1631 : len,
1632 : ckvno,
1633 : &rep->enc_part);
1634 30301 : free(buf);
1635 30301 : if (ret == 0)
1636 30301 : ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret);
1637 : } else {
1638 49297 : ret = krb5_encrypt_EncryptedData(context,
1639 : crypto,
1640 : rk_is_subkey ?
1641 : KRB5_KU_TGS_REP_ENC_PART_SUB_KEY :
1642 : KRB5_KU_TGS_REP_ENC_PART_SESSION,
1643 : buf,
1644 : len,
1645 : ckvno,
1646 : &rep->enc_part);
1647 49297 : free(buf);
1648 49297 : if (ret == 0)
1649 49297 : ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret);
1650 : }
1651 79598 : krb5_crypto_destroy(context, crypto);
1652 79598 : if(ret) {
1653 0 : const char *msg = krb5_get_error_message(context, ret);
1654 0 : kdc_log(context, config, 4, "Failed to encode KDC-REP: %s", msg);
1655 0 : krb5_free_error_message(context, msg);
1656 0 : return ret;
1657 : }
1658 79598 : if(buf_size != len) {
1659 0 : free(buf);
1660 0 : kdc_log(context, config, 4, "Internal error in ASN.1 encoder");
1661 0 : _kdc_set_e_text(r, "KDC internal error");
1662 0 : return KRB5KRB_ERR_GENERIC;
1663 : }
1664 79598 : reply->data = buf;
1665 79598 : reply->length = buf_size;
1666 79598 : return 0;
1667 : }
1668 :
1669 : /*
1670 : *
1671 : */
1672 :
1673 : static krb5_error_code
1674 620 : get_pa_etype_info(krb5_context context,
1675 : krb5_kdc_configuration *config,
1676 : METHOD_DATA *md, Key *ckey,
1677 : krb5_boolean include_salt)
1678 : {
1679 620 : krb5_error_code ret = 0;
1680 0 : ETYPE_INFO_ENTRY eie; /* do not free this one */
1681 0 : ETYPE_INFO ei;
1682 0 : PA_DATA pa;
1683 0 : size_t len;
1684 :
1685 : /*
1686 : * Code moved here from what used to be make_etype_info_entry() because
1687 : * using the ASN.1 compiler-generated SEQUENCE OF add functions makes that
1688 : * old function's body and this one's small and clean.
1689 : *
1690 : * The following comment blocks were there:
1691 : *
1692 : * According to `the specs', we can't send a salt if we have AFS3 salted
1693 : * key, but that requires that you *know* what cell you are using (e.g by
1694 : * assuming that the cell is the same as the realm in lower case)
1695 : *
1696 : * We shouldn't sent salttype since it is incompatible with the
1697 : * specification and it breaks windows clients. The afs salting problem
1698 : * is solved by using KRB5-PADATA-AFS3-SALT implemented in Heimdal 0.7 and
1699 : * later.
1700 : *
1701 : * We return no salt type at all, as that should indicate the default salt
1702 : * type and make everybody happy. some systems (like w2k) dislike being
1703 : * told the salt type here.
1704 : */
1705 :
1706 620 : pa.padata_type = KRB5_PADATA_ETYPE_INFO;
1707 620 : pa.padata_value.data = NULL;
1708 620 : pa.padata_value.length = 0;
1709 620 : ei.len = 0;
1710 620 : ei.val = NULL;
1711 620 : eie.etype = ckey->key.keytype;
1712 620 : eie.salttype = NULL;
1713 620 : eie.salt = NULL;
1714 620 : if (include_salt && ckey->salt)
1715 0 : eie.salt = &ckey->salt->salt;
1716 620 : ret = add_ETYPE_INFO(&ei, &eie);
1717 620 : if (ret == 0)
1718 620 : ASN1_MALLOC_ENCODE(ETYPE_INFO, pa.padata_value.data, pa.padata_value.length,
1719 : &ei, &len, ret);
1720 620 : if (ret == 0)
1721 620 : add_METHOD_DATA(md, &pa);
1722 620 : free_ETYPE_INFO(&ei);
1723 620 : free_PA_DATA(&pa);
1724 620 : return ret;
1725 : }
1726 :
1727 : /*
1728 : *
1729 : */
1730 :
1731 : extern const int _krb5_AES_SHA1_string_to_default_iterator;
1732 : extern const int _krb5_AES_SHA2_string_to_default_iterator;
1733 :
1734 : static krb5_error_code
1735 46656 : make_s2kparams(int value, size_t len, krb5_data **ps2kparams)
1736 : {
1737 1740 : krb5_data *s2kparams;
1738 1740 : krb5_error_code ret;
1739 :
1740 46656 : ALLOC(s2kparams);
1741 46656 : if (s2kparams == NULL)
1742 0 : return ENOMEM;
1743 46656 : ret = krb5_data_alloc(s2kparams, len);
1744 46656 : if (ret) {
1745 0 : free(s2kparams);
1746 0 : return ret;
1747 : }
1748 46656 : _krb5_put_int(s2kparams->data, value, len);
1749 46656 : *ps2kparams = s2kparams;
1750 46656 : return 0;
1751 : }
1752 :
1753 : static krb5_error_code
1754 47637 : make_etype_info2_entry(ETYPE_INFO2_ENTRY *ent,
1755 : Key *key,
1756 : krb5_boolean include_salt)
1757 : {
1758 1743 : krb5_error_code ret;
1759 :
1760 47637 : ent->etype = key->key.keytype;
1761 47637 : if (key->salt && include_salt) {
1762 46643 : ALLOC(ent->salt);
1763 46643 : if (ent->salt == NULL)
1764 0 : return ENOMEM;
1765 46643 : *ent->salt = malloc(key->salt->salt.length + 1);
1766 46643 : if (*ent->salt == NULL) {
1767 0 : free(ent->salt);
1768 0 : ent->salt = NULL;
1769 0 : return ENOMEM;
1770 : }
1771 46643 : memcpy(*ent->salt, key->salt->salt.data, key->salt->salt.length);
1772 46643 : (*ent->salt)[key->salt->salt.length] = '\0';
1773 : } else
1774 994 : ent->salt = NULL;
1775 :
1776 47637 : ent->s2kparams = NULL;
1777 :
1778 47637 : switch (key->key.keytype) {
1779 46656 : case ETYPE_AES128_CTS_HMAC_SHA1_96:
1780 : case ETYPE_AES256_CTS_HMAC_SHA1_96:
1781 46656 : ret = make_s2kparams(_krb5_AES_SHA1_string_to_default_iterator,
1782 46656 : 4, &ent->s2kparams);
1783 46656 : break;
1784 0 : case KRB5_ENCTYPE_AES128_CTS_HMAC_SHA256_128:
1785 : case KRB5_ENCTYPE_AES256_CTS_HMAC_SHA384_192:
1786 0 : ret = make_s2kparams(_krb5_AES_SHA2_string_to_default_iterator,
1787 0 : 4, &ent->s2kparams);
1788 0 : break;
1789 0 : case ETYPE_DES_CBC_CRC:
1790 : case ETYPE_DES_CBC_MD4:
1791 : case ETYPE_DES_CBC_MD5:
1792 : /* Check if this was a AFS3 salted key */
1793 0 : if(key->salt && key->salt->type == hdb_afs3_salt)
1794 0 : ret = make_s2kparams(1, 1, &ent->s2kparams);
1795 : else
1796 0 : ret = 0;
1797 0 : break;
1798 978 : default:
1799 978 : ret = 0;
1800 978 : break;
1801 : }
1802 45894 : return ret;
1803 : }
1804 :
1805 : /*
1806 : * Return an ETYPE-INFO2. Enctypes are storted the same way as in the
1807 : * database (client supported enctypes first, then the unsupported
1808 : * enctypes).
1809 : */
1810 :
1811 : static krb5_error_code
1812 47637 : get_pa_etype_info2(krb5_context context,
1813 : krb5_kdc_configuration *config,
1814 : METHOD_DATA *md, Key *ckey,
1815 : krb5_boolean include_salt)
1816 : {
1817 47637 : krb5_error_code ret = 0;
1818 1743 : ETYPE_INFO2 pa;
1819 1743 : unsigned char *buf;
1820 1743 : size_t len;
1821 :
1822 47637 : pa.len = 1;
1823 47637 : pa.val = calloc(1, sizeof(pa.val[0]));
1824 47637 : if(pa.val == NULL)
1825 0 : return ENOMEM;
1826 :
1827 47637 : ret = make_etype_info2_entry(&pa.val[0], ckey, include_salt);
1828 47637 : if (ret) {
1829 0 : free_ETYPE_INFO2(&pa);
1830 0 : return ret;
1831 : }
1832 :
1833 47637 : ASN1_MALLOC_ENCODE(ETYPE_INFO2, buf, len, &pa, &len, ret);
1834 47637 : free_ETYPE_INFO2(&pa);
1835 47637 : if(ret)
1836 0 : return ret;
1837 47637 : ret = realloc_method_data(md);
1838 47637 : if(ret) {
1839 0 : free(buf);
1840 0 : return ret;
1841 : }
1842 47637 : md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO2;
1843 47637 : md->val[md->len - 1].padata_value.length = len;
1844 47637 : md->val[md->len - 1].padata_value.data = buf;
1845 47637 : return 0;
1846 : }
1847 :
1848 : /*
1849 : * Return 0 if the client has only older enctypes, this is for
1850 : * determining if the server should send ETYPE_INFO2 or not.
1851 : */
1852 :
1853 : static int
1854 18604 : newer_enctype_present(krb5_context context,
1855 : struct KDC_REQ_BODY_etype *etype_list)
1856 : {
1857 585 : size_t i;
1858 :
1859 20081 : for (i = 0; i < etype_list->len; i++) {
1860 19461 : if (!krb5_is_enctype_old(context, etype_list->val[i]))
1861 17399 : return 1;
1862 : }
1863 620 : return 0;
1864 : }
1865 :
1866 : static krb5_error_code
1867 18604 : get_pa_etype_info_both(krb5_context context,
1868 : krb5_kdc_configuration *config,
1869 : struct KDC_REQ_BODY_etype *etype_list,
1870 : METHOD_DATA *md, Key *ckey,
1871 : krb5_boolean include_salt)
1872 : {
1873 585 : krb5_error_code ret;
1874 :
1875 : /*
1876 : * Windows 2019 (and earlier versions) always sends the salt
1877 : * and Samba has testsuites that check this behaviour, so a
1878 : * Samba AD DC will set this flag to match the AS-REP packet
1879 : * more closely.
1880 : */
1881 18604 : if (config->force_include_pa_etype_salt)
1882 18604 : include_salt = TRUE;
1883 :
1884 : /*
1885 : * RFC4120 requires:
1886 : * When the AS server is to include pre-authentication data in a
1887 : * KRB-ERROR or in an AS-REP, it MUST use PA-ETYPE-INFO2, not
1888 : * PA-ETYPE-INFO, if the etype field of the client's AS-REQ lists
1889 : * at least one "newer" encryption type. Otherwise (when the etype
1890 : * field of the client's AS-REQ does not list any "newer" encryption
1891 : * types), it MUST send both PA-ETYPE-INFO2 and PA-ETYPE-INFO (both
1892 : * with an entry for each enctype). A "newer" enctype is any enctype
1893 : * first officially specified concurrently with or subsequent to the
1894 : * issue of this RFC. The enctypes DES, 3DES, or RC4 and any defined
1895 : * in [RFC1510] are not "newer" enctypes.
1896 : *
1897 : * It goes on to state:
1898 : * The preferred ordering of the "hint" pre-authentication data that
1899 : * affect client key selection is: ETYPE-INFO2, followed by ETYPE-INFO,
1900 : * followed by PW-SALT. As noted in Section 3.1.3, a KDC MUST NOT send
1901 : * ETYPE-INFO or PW-SALT when the client's AS-REQ includes at least one
1902 : * "newer" etype.
1903 : */
1904 :
1905 18604 : ret = get_pa_etype_info2(context, config, md, ckey, include_salt);
1906 18604 : if (ret)
1907 0 : return ret;
1908 :
1909 18604 : if (!newer_enctype_present(context, etype_list))
1910 620 : ret = get_pa_etype_info(context, config, md, ckey, include_salt);
1911 :
1912 18019 : return ret;
1913 : }
1914 :
1915 : /*
1916 : *
1917 : */
1918 :
1919 : void
1920 79598 : _log_astgs_req(astgs_request_t r, krb5_enctype setype)
1921 : {
1922 79598 : const KDC_REQ_BODY *b = &r->req.req_body;
1923 79598 : krb5_enctype cetype = r->reply_key.keytype;
1924 2828 : krb5_error_code ret;
1925 2828 : struct rk_strpool *p;
1926 79598 : struct rk_strpool *s = NULL;
1927 2828 : char *str;
1928 2828 : char *cet;
1929 2828 : char *set;
1930 2828 : size_t i;
1931 :
1932 : /*
1933 : * we are collecting ``p'' and ``s''. The former is a textual
1934 : * representation of the enctypes as strings which will be used
1935 : * for debugging. The latter is a terse comma separated list of
1936 : * the %d's of the enctypes to emit into our audit trail to
1937 : * conserve space in the logs.
1938 : */
1939 :
1940 79598 : p = rk_strpoolprintf(NULL, "%s", "Client supported enctypes: ");
1941 :
1942 517551 : for (i = 0; i < b->etype.len; i++) {
1943 435125 : ret = krb5_enctype_to_string(r->context, b->etype.val[i], &str);
1944 435125 : if (ret == 0) {
1945 435099 : p = rk_strpoolprintf(p, "%s", str);
1946 435099 : free(str);
1947 : } else
1948 26 : p = rk_strpoolprintf(p, "%d", b->etype.val[i]);
1949 435125 : if (p == NULL) {
1950 0 : rk_strpoolfree(s);
1951 0 : _kdc_r_log(r, 4, "out of memory");
1952 0 : return;
1953 : }
1954 435125 : s = rk_strpoolprintf(s, "%d", b->etype.val[i]);
1955 435125 : if (i + 1 < b->etype.len) {
1956 355527 : p = rk_strpoolprintf(p, ", ");
1957 355527 : s = rk_strpoolprintf(s, ",");
1958 : }
1959 : }
1960 79598 : if (p == NULL)
1961 0 : p = rk_strpoolprintf(p, "no encryption types");
1962 :
1963 79598 : str = rk_strpoolcollect(s);
1964 79598 : if (str)
1965 79598 : kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE, "etypes", "%s",
1966 : str);
1967 79598 : free(str);
1968 :
1969 79598 : ret = krb5_enctype_to_string(r->context, cetype, &cet);
1970 79598 : if(ret == 0) {
1971 79598 : ret = krb5_enctype_to_string(r->context, setype, &set);
1972 79598 : if (ret == 0) {
1973 79598 : p = rk_strpoolprintf(p, ", using %s/%s", cet, set);
1974 79598 : free(set);
1975 : }
1976 79598 : free(cet);
1977 : }
1978 79598 : if (ret != 0)
1979 0 : p = rk_strpoolprintf(p, ", using enctypes %d/%d",
1980 : cetype, setype);
1981 :
1982 79598 : str = rk_strpoolcollect(p);
1983 79598 : if (str)
1984 79598 : _kdc_r_log(r, 4, "%s", str);
1985 79598 : free(str);
1986 :
1987 79598 : kdc_audit_addkv((kdc_request_t)r, 0, "etype", "%d/%d", cetype, setype);
1988 :
1989 : {
1990 2828 : char fixedstr[128];
1991 2828 : int result;
1992 :
1993 79598 : result = unparse_flags(KDCOptions2int(b->kdc_options), asn1_KDCOptions_units(),
1994 : fixedstr, sizeof(fixedstr));
1995 79598 : if (result > 0) {
1996 73974 : _kdc_r_log(r, 4, "Requested flags: %s", fixedstr);
1997 73974 : kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE,
1998 : "flags", "%s", fixedstr);
1999 : }
2000 : }
2001 : }
2002 :
2003 : /*
2004 : * verify the flags on `client' and `server', returning 0
2005 : * if they are OK and generating an error messages and returning
2006 : * and error code otherwise.
2007 : */
2008 :
2009 : KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL
2010 100225 : kdc_check_flags(astgs_request_t r,
2011 : krb5_boolean is_as_req,
2012 : hdb_entry *client,
2013 : hdb_entry *server)
2014 : {
2015 100225 : if (client != NULL) {
2016 : /* check client */
2017 100173 : if (client->flags.locked_out) {
2018 0 : kdc_audit_addreason((kdc_request_t)r, "Client is locked out");
2019 0 : return KRB5KDC_ERR_CLIENT_REVOKED;
2020 : }
2021 :
2022 100173 : if (client->flags.invalid) {
2023 0 : kdc_audit_addreason((kdc_request_t)r,
2024 : "Client has invalid bit set");
2025 0 : return KRB5KDC_ERR_POLICY;
2026 : }
2027 :
2028 100173 : if (!client->flags.client) {
2029 0 : kdc_audit_addreason((kdc_request_t)r,
2030 : "Principal may not act as client");
2031 0 : return KRB5KDC_ERR_POLICY;
2032 : }
2033 :
2034 100173 : if (client->valid_start && *client->valid_start > kdc_time) {
2035 0 : char starttime_str[100];
2036 0 : krb5_format_time(r->context, *client->valid_start,
2037 : starttime_str, sizeof(starttime_str), TRUE);
2038 0 : kdc_audit_addreason((kdc_request_t)r, "Client not yet valid "
2039 : "until %s", starttime_str);
2040 0 : return KRB5KDC_ERR_CLIENT_NOTYET;
2041 : }
2042 :
2043 100173 : if (client->valid_end && *client->valid_end < kdc_time) {
2044 0 : char endtime_str[100];
2045 0 : krb5_format_time(r->context, *client->valid_end,
2046 : endtime_str, sizeof(endtime_str), TRUE);
2047 0 : kdc_audit_addreason((kdc_request_t)r, "Client expired at %s",
2048 : endtime_str);
2049 0 : return KRB5KDC_ERR_NAME_EXP;
2050 : }
2051 :
2052 100173 : if (client->flags.require_pwchange &&
2053 0 : (server == NULL || !server->flags.change_pw))
2054 0 : return KRB5KDC_ERR_KEY_EXPIRED;
2055 :
2056 100173 : if (client->pw_end && *client->pw_end < kdc_time
2057 16 : && (server == NULL || !server->flags.change_pw)) {
2058 0 : char pwend_str[100];
2059 0 : krb5_format_time(r->context, *client->pw_end,
2060 : pwend_str, sizeof(pwend_str), TRUE);
2061 0 : kdc_audit_addreason((kdc_request_t)r, "Client's key has expired "
2062 : "at %s", pwend_str);
2063 0 : return KRB5KDC_ERR_KEY_EXPIRED;
2064 : }
2065 : }
2066 :
2067 : /* check server */
2068 :
2069 100225 : if (server != NULL) {
2070 99399 : if (server->flags.locked_out) {
2071 0 : kdc_audit_addreason((kdc_request_t)r, "Server locked out");
2072 0 : return KRB5KDC_ERR_SERVICE_REVOKED;
2073 : }
2074 99399 : if (server->flags.invalid) {
2075 0 : kdc_audit_addreason((kdc_request_t)r,
2076 : "Server has invalid flag set");
2077 0 : return KRB5KDC_ERR_POLICY;
2078 : }
2079 99399 : if (!server->flags.server) {
2080 0 : kdc_audit_addreason((kdc_request_t)r,
2081 : "Principal may not act as server");
2082 0 : return KRB5KDC_ERR_POLICY;
2083 : }
2084 :
2085 99399 : if (!is_as_req && server->flags.initial) {
2086 0 : kdc_audit_addreason((kdc_request_t)r,
2087 : "AS-REQ is required for server");
2088 0 : return KRB5KDC_ERR_POLICY;
2089 : }
2090 :
2091 99399 : if (server->valid_start && *server->valid_start > kdc_time) {
2092 0 : char starttime_str[100];
2093 0 : krb5_format_time(r->context, *server->valid_start,
2094 : starttime_str, sizeof(starttime_str), TRUE);
2095 0 : kdc_audit_addreason((kdc_request_t)r, "Server not yet valid "
2096 : "until %s", starttime_str);
2097 0 : return KRB5KDC_ERR_SERVICE_NOTYET;
2098 : }
2099 :
2100 99399 : if (server->valid_end && *server->valid_end < kdc_time) {
2101 0 : char endtime_str[100];
2102 0 : krb5_format_time(r->context, *server->valid_end,
2103 : endtime_str, sizeof(endtime_str), TRUE);
2104 0 : kdc_audit_addreason((kdc_request_t)r, "Server expired at %s",
2105 : endtime_str);
2106 0 : return KRB5KDC_ERR_SERVICE_EXP;
2107 : }
2108 :
2109 99399 : if (server->pw_end && *server->pw_end < kdc_time) {
2110 0 : char pwend_str[100];
2111 0 : krb5_format_time(r->context, *server->pw_end,
2112 : pwend_str, sizeof(pwend_str), TRUE);
2113 0 : kdc_audit_addreason((kdc_request_t)r, "Server's key has expired "
2114 : "at %s", pwend_str);
2115 0 : return KRB5KDC_ERR_KEY_EXPIRED;
2116 : }
2117 : }
2118 96812 : return 0;
2119 : }
2120 :
2121 : /*
2122 : * Return TRUE if `from' is part of `addresses' taking into consideration
2123 : * the configuration variables that tells us how strict we should be about
2124 : * these checks
2125 : */
2126 :
2127 : krb5_boolean
2128 79605 : _kdc_check_addresses(astgs_request_t r, HostAddresses *addresses,
2129 : const struct sockaddr *from)
2130 : {
2131 79605 : krb5_kdc_configuration *config = r->config;
2132 2828 : krb5_error_code ret;
2133 2828 : krb5_address addr;
2134 2828 : krb5_boolean result;
2135 79605 : krb5_boolean only_netbios = TRUE;
2136 2828 : size_t i;
2137 :
2138 79605 : if (!config->check_ticket_addresses && !config->warn_ticket_addresses)
2139 0 : return TRUE;
2140 :
2141 : /*
2142 : * Fields of HostAddresses type are always OPTIONAL and should be non-
2143 : * empty, but we check for empty just in case as our compiler doesn't
2144 : * support size constraints on SEQUENCE OF.
2145 : */
2146 79605 : if (addresses == NULL || addresses->len == 0)
2147 79487 : return config->allow_null_ticket_addresses;
2148 :
2149 236 : for (i = 0; i < addresses->len; ++i) {
2150 118 : if (addresses->val[i].addr_type != KRB5_ADDRESS_NETBIOS) {
2151 0 : only_netbios = FALSE;
2152 : }
2153 : }
2154 :
2155 : /* Windows sends it's netbios name, which I can only assume is
2156 : * used for the 'allowed workstations' check. This is painful,
2157 : * but we still want to check IP addresses if they happen to be
2158 : * present.
2159 : */
2160 :
2161 118 : if(only_netbios)
2162 118 : return config->allow_null_ticket_addresses;
2163 :
2164 0 : ret = krb5_sockaddr2address (r->context, from, &addr);
2165 0 : if(ret)
2166 0 : return FALSE;
2167 :
2168 0 : result = krb5_address_search(r->context, &addr, addresses);
2169 0 : krb5_free_address (r->context, &addr);
2170 0 : return result;
2171 : }
2172 :
2173 : /*
2174 : *
2175 : */
2176 : krb5_error_code
2177 0 : _kdc_check_anon_policy(astgs_request_t r)
2178 : {
2179 0 : if (!r->config->allow_anonymous) {
2180 0 : kdc_audit_addreason((kdc_request_t)r,
2181 : "Anonymous tickets denied by local policy");
2182 0 : return KRB5KDC_ERR_POLICY;
2183 : }
2184 :
2185 0 : return 0;
2186 : }
2187 :
2188 : /*
2189 : * Determine whether the client requested a PAC be included
2190 : * or excluded explictly, or whether it doesn't care.
2191 : */
2192 :
2193 : static uint64_t
2194 30305 : get_pac_attributes(krb5_context context, KDC_REQ *req)
2195 : {
2196 1170 : krb5_error_code ret;
2197 1170 : PA_PAC_REQUEST pacreq;
2198 1170 : const PA_DATA *pa;
2199 30305 : int i = 0;
2200 1170 : uint32_t pac_attributes;
2201 :
2202 30305 : pa = _kdc_find_padata(req, &i, KRB5_PADATA_PA_PAC_REQUEST);
2203 30305 : if (pa == NULL)
2204 28344 : return KRB5_PAC_WAS_GIVEN_IMPLICITLY;
2205 :
2206 791 : ret = decode_PA_PAC_REQUEST(pa->padata_value.data,
2207 791 : pa->padata_value.length,
2208 : &pacreq,
2209 : NULL);
2210 791 : if (ret)
2211 0 : return KRB5_PAC_WAS_GIVEN_IMPLICITLY;
2212 :
2213 791 : pac_attributes = pacreq.include_pac ? KRB5_PAC_WAS_REQUESTED : 0;
2214 791 : free_PA_PAC_REQUEST(&pacreq);
2215 791 : return pac_attributes;
2216 : }
2217 :
2218 : /*
2219 : *
2220 : */
2221 :
2222 : static krb5_error_code
2223 30305 : generate_pac(astgs_request_t r, const Key *skey, const Key *tkey,
2224 : krb5_boolean is_tgs)
2225 : {
2226 1170 : krb5_error_code ret;
2227 1170 : krb5_data data;
2228 1170 : uint16_t rodc_id;
2229 1170 : krb5_principal client;
2230 30305 : krb5_const_principal canon_princ = NULL;
2231 :
2232 30305 : r->pac_attributes = get_pac_attributes(r->context, &r->req);
2233 30305 : kdc_audit_setkv_number((kdc_request_t)r, "pac_attributes",
2234 29135 : r->pac_attributes);
2235 :
2236 30305 : 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 30304 : ret = _kdc_pac_generate(r,
2247 : r->client,
2248 : r->server,
2249 30304 : 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 30304 : if (ret) {
2254 4 : _kdc_r_log(r, 4, "PAC generation failed for -- %s",
2255 : r->cname);
2256 4 : return ret;
2257 : }
2258 30300 : if (r->pac == NULL)
2259 0 : return 0;
2260 :
2261 30300 : rodc_id = r->server->kvno >> 16;
2262 :
2263 : /* libkrb5 expects ticket and PAC client names to match */
2264 30300 : ret = _krb5_principalname2krb5_principal(r->context, &client,
2265 : r->et.cname, r->et.crealm);
2266 30300 : 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 30300 : if (krb5_realm_compare(r->context, client, r->canon_client_princ)) {
2276 30300 : char *cpn = NULL;
2277 :
2278 30300 : canon_princ = r->canon_client_princ;
2279 :
2280 30300 : (void) krb5_unparse_name(r->context, canon_princ, &cpn);
2281 30300 : kdc_audit_addkv((kdc_request_t)r, 0, "canon_client_name", "%s",
2282 30300 : cpn ? cpn : "<unknown>");
2283 30300 : krb5_xfree(cpn);
2284 : }
2285 :
2286 30300 : 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 30300 : ret = _krb5_pac_sign(r->context,
2293 : r->pac,
2294 : r->et.authtime,
2295 : client,
2296 30300 : &skey->key, /* Server key */
2297 30300 : &tkey->key, /* TGS key */
2298 : rodc_id,
2299 : NULL, /* UPN */
2300 : canon_princ,
2301 : FALSE, /* add_full_sig */
2302 : is_tgs ? &r->pac_attributes : NULL,
2303 : &data);
2304 30300 : krb5_free_principal(r->context, client);
2305 30300 : krb5_pac_free(r->context, r->pac);
2306 30300 : r->pac = NULL;
2307 30300 : if (ret) {
2308 0 : _kdc_r_log(r, 4, "PAC signing failed for -- %s",
2309 : r->cname);
2310 0 : return ret;
2311 : }
2312 :
2313 30300 : ret = _kdc_tkt_insert_pac(r->context, &r->et, &data);
2314 30300 : krb5_data_free(&data);
2315 :
2316 30300 : return ret;
2317 : }
2318 :
2319 : /*
2320 : *
2321 : */
2322 :
2323 : krb5_boolean
2324 127379 : _kdc_is_anonymous(krb5_context context, krb5_const_principal principal)
2325 : {
2326 127379 : return krb5_principal_is_anonymous(context, principal, KRB5_ANON_MATCH_ANY);
2327 : }
2328 :
2329 : /*
2330 : * Returns TRUE if principal is the unauthenticated anonymous identity,
2331 : * i.e. WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS. Unfortunately due to
2332 : * backwards compatibility logic in krb5_principal_is_anonymous() we
2333 : * have to use our own implementation.
2334 : */
2335 :
2336 : krb5_boolean
2337 44804 : _kdc_is_anonymous_pkinit(krb5_context context, krb5_const_principal principal)
2338 : {
2339 44804 : return _kdc_is_anonymous(context, principal) &&
2340 0 : strcmp(principal->realm, KRB5_ANON_REALM) == 0;
2341 : }
2342 :
2343 : static int
2344 18177 : require_preauth_p(astgs_request_t r)
2345 : {
2346 18177 : return r->config->require_preauth
2347 0 : || r->client->flags.require_preauth
2348 17592 : || r->server->flags.require_preauth;
2349 : }
2350 :
2351 :
2352 : /*
2353 : *
2354 : */
2355 :
2356 : static krb5_error_code
2357 26783 : add_enc_pa_rep(astgs_request_t r)
2358 : {
2359 1170 : krb5_error_code ret;
2360 1170 : krb5_crypto crypto;
2361 1170 : Checksum checksum;
2362 1170 : krb5_data cdata;
2363 1170 : size_t len;
2364 :
2365 26783 : ret = krb5_crypto_init(r->context, &r->reply_key, 0, &crypto);
2366 26783 : if (ret)
2367 0 : return ret;
2368 :
2369 26783 : ret = krb5_create_checksum(r->context, crypto,
2370 : KRB5_KU_AS_REQ, 0,
2371 : r->request.data, r->request.length,
2372 : &checksum);
2373 26783 : krb5_crypto_destroy(r->context, crypto);
2374 26783 : if (ret)
2375 0 : return ret;
2376 :
2377 26783 : ASN1_MALLOC_ENCODE(Checksum, cdata.data, cdata.length,
2378 : &checksum, &len, ret);
2379 26783 : free_Checksum(&checksum);
2380 26783 : if (ret)
2381 0 : return ret;
2382 26783 : heim_assert(cdata.length == len, "ASN.1 internal error");
2383 :
2384 26783 : if (r->ek.encrypted_pa_data == NULL) {
2385 26783 : ALLOC(r->ek.encrypted_pa_data);
2386 26783 : if (r->ek.encrypted_pa_data == NULL)
2387 0 : return ENOMEM;
2388 : }
2389 26783 : ret = krb5_padata_add(r->context, r->ek.encrypted_pa_data,
2390 : KRB5_PADATA_REQ_ENC_PA_REP, cdata.data, cdata.length);
2391 26783 : if (ret)
2392 0 : return ret;
2393 :
2394 26783 : if (!r->config->enable_fast)
2395 915 : return 0;
2396 :
2397 25868 : return krb5_padata_add(r->context, r->ek.encrypted_pa_data,
2398 : KRB5_PADATA_FX_FAST, NULL, 0);
2399 : }
2400 :
2401 : /*
2402 : * Add an authorization data element indicating that a synthetic
2403 : * principal was used, so that the TGS does not accidentally
2404 : * synthesize a non-synthetic principal that has since been deleted.
2405 : */
2406 : static krb5_error_code
2407 0 : add_synthetic_princ_ad(astgs_request_t r)
2408 : {
2409 0 : krb5_data data;
2410 :
2411 0 : krb5_data_zero(&data);
2412 :
2413 0 : return _kdc_tkt_add_if_relevant_ad(r->context, &r->et,
2414 : KRB5_AUTHDATA_SYNTHETIC_PRINC_USED,
2415 : &data);
2416 : }
2417 :
2418 : static krb5_error_code
2419 5114 : get_local_tgs(krb5_context context,
2420 : krb5_kdc_configuration *config,
2421 : krb5_const_realm realm,
2422 : HDB **krbtgtdb,
2423 : hdb_entry **krbtgt)
2424 : {
2425 0 : krb5_error_code ret;
2426 0 : krb5_principal tgs_name;
2427 :
2428 5114 : *krbtgtdb = NULL;
2429 5114 : *krbtgt = NULL;
2430 :
2431 5114 : ret = krb5_make_principal(context,
2432 : &tgs_name,
2433 : realm,
2434 : KRB5_TGS_NAME,
2435 : realm,
2436 : NULL);
2437 5114 : if (ret == 0)
2438 5114 : ret = _kdc_db_fetch(context, config, tgs_name,
2439 : HDB_F_GET_KRBTGT, NULL, krbtgtdb, krbtgt);
2440 :
2441 5114 : krb5_free_principal(context, tgs_name);
2442 5114 : return ret;
2443 : }
2444 :
2445 : /*
2446 : *
2447 : */
2448 :
2449 : krb5_error_code
2450 52160 : _kdc_as_rep(astgs_request_t r)
2451 : {
2452 52160 : krb5_kdc_configuration *config = r->config;
2453 52160 : KDC_REQ *req = &r->req;
2454 52160 : const char *from = r->from;
2455 52160 : KDC_REQ_BODY *b = NULL;
2456 52160 : KDC_REP *rep = &r->rep;
2457 1755 : KDCOptions f;
2458 1755 : krb5_enctype setype;
2459 52160 : krb5_error_code ret = 0;
2460 1755 : Key *skey;
2461 52160 : int found_pa = 0;
2462 52160 : int i, flags = HDB_F_FOR_AS_REQ;
2463 1755 : const PA_DATA *pa;
2464 1755 : krb5_boolean is_tgs;
2465 1755 : const char *msg;
2466 1755 : Key *krbtgt_key;
2467 1755 : unsigned krbtgt_kvno;
2468 :
2469 52160 : memset(rep, 0, sizeof(*rep));
2470 :
2471 52160 : ALLOC(rep->padata);
2472 52160 : if (rep->padata == NULL) {
2473 0 : ret = ENOMEM;
2474 0 : krb5_set_error_message(r->context, ret, N_("malloc: out of memory", ""));
2475 0 : goto out;
2476 : }
2477 :
2478 : /*
2479 : * Look for FAST armor and unwrap
2480 : */
2481 52160 : ret = _kdc_fast_unwrap_request(r, NULL, NULL);
2482 52160 : if (ret) {
2483 8 : _kdc_r_log(r, 1, "FAST unwrap request from %s failed: %d", from, ret);
2484 8 : goto out;
2485 : }
2486 :
2487 : /* Validate armor TGT, and initialize the armor client and PAC */
2488 52152 : if (r->armor_ticket) {
2489 468 : ret = _kdc_fast_check_armor_pac(r, HDB_F_FOR_AS_REQ);
2490 468 : if (ret)
2491 4 : goto out;
2492 : }
2493 :
2494 52148 : b = &req->req_body;
2495 52148 : f = b->kdc_options;
2496 :
2497 52148 : if (f.canonicalize)
2498 48069 : flags |= HDB_F_CANON;
2499 :
2500 52148 : if (b->sname == NULL) {
2501 3 : ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
2502 3 : _kdc_set_e_text(r, "No server in request");
2503 3 : goto out;
2504 : }
2505 :
2506 52145 : ret = _krb5_principalname2krb5_principal(r->context, &r->server_princ,
2507 50390 : *(b->sname), b->realm);
2508 52145 : if (!ret)
2509 52145 : ret = krb5_unparse_name(r->context, r->server_princ, &r->sname);
2510 52145 : if (ret) {
2511 0 : kdc_log(r->context, config, 2,
2512 : "AS_REQ malformed server name from %s", from);
2513 0 : goto out;
2514 : }
2515 :
2516 52145 : if (b->cname == NULL) {
2517 0 : ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
2518 0 : _kdc_set_e_text(r, "No client in request");
2519 0 : goto out;
2520 : }
2521 :
2522 52145 : ret = _krb5_principalname2krb5_principal(r->context, &r->client_princ,
2523 50390 : *(b->cname), b->realm);
2524 52145 : if (!ret)
2525 52145 : ret = krb5_unparse_name(r->context, r->client_princ, &r->cname);
2526 52145 : if (ret) {
2527 0 : kdc_log(r->context, config, 2,
2528 : "AS-REQ malformed client name from %s", from);
2529 0 : goto out;
2530 : }
2531 :
2532 52145 : kdc_log(r->context, config, 4, "AS-REQ %s from %s for %s",
2533 : r->cname, r->from, r->sname);
2534 :
2535 52145 : is_tgs = krb5_principal_is_krbtgt(r->context, r->server_princ);
2536 :
2537 52249 : if (_kdc_is_anonymous(r->context, r->client_princ) &&
2538 104 : !_kdc_is_anon_request(req)) {
2539 0 : kdc_log(r->context, config, 2, "Anonymous client w/o anonymous flag");
2540 0 : ret = KRB5KDC_ERR_BADOPTION;
2541 0 : goto out;
2542 : }
2543 :
2544 53900 : ret = _kdc_db_fetch(r->context, config, r->client_princ,
2545 52145 : HDB_F_GET_CLIENT | HDB_F_SYNTHETIC_OK | flags, NULL,
2546 : &r->clientdb, &r->client);
2547 52145 : switch (ret) {
2548 47776 : case 0: /* Success */
2549 49531 : break;
2550 1627 : case HDB_ERR_NOT_FOUND_HERE:
2551 1627 : kdc_log(r->context, config, 5, "client %s does not have secrets at this KDC, need to proxy",
2552 : r->cname);
2553 1627 : goto out;
2554 538 : case HDB_ERR_WRONG_REALM: {
2555 538 : char *fixed_client_name = NULL;
2556 :
2557 538 : ret = krb5_unparse_name(r->context, r->client->principal,
2558 : &fixed_client_name);
2559 538 : if (ret) {
2560 0 : goto out;
2561 : }
2562 :
2563 538 : kdc_log(r->context, config, 4, "WRONG_REALM - %s -> %s",
2564 : r->cname, fixed_client_name);
2565 538 : free(fixed_client_name);
2566 :
2567 538 : r->e_text = NULL;
2568 538 : ret = _kdc_fast_mk_error(r, r->rep.padata, r->armor_crypto,
2569 538 : &req->req_body,
2570 538 : r->error_code = KRB5_KDC_ERR_WRONG_REALM,
2571 538 : r->client->principal, r->server_princ,
2572 538 : NULL, NULL, r->reply);
2573 538 : goto out;
2574 : }
2575 449 : default:
2576 : {
2577 449 : msg = krb5_get_error_message(r->context, ret);
2578 449 : kdc_log(r->context, config, 4, "UNKNOWN -- %s: %s", r->cname, msg);
2579 449 : krb5_free_error_message(r->context, msg);
2580 449 : ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
2581 449 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
2582 : KDC_AUTH_EVENT_CLIENT_UNKNOWN);
2583 449 : goto out;
2584 : }
2585 : }
2586 :
2587 49531 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
2588 : KDC_AUTH_EVENT_CLIENT_FOUND);
2589 :
2590 100817 : ret = _kdc_db_fetch(r->context, config, r->server_princ,
2591 49531 : HDB_F_GET_SERVER | HDB_F_DELAY_NEW_KEYS |
2592 49531 : flags | (is_tgs ? HDB_F_GET_KRBTGT : 0),
2593 : NULL, &r->serverdb, &r->server);
2594 49531 : switch (ret) {
2595 47774 : case 0: /* Success */
2596 49529 : break;
2597 0 : case HDB_ERR_NOT_FOUND_HERE:
2598 0 : kdc_log(r->context, config, 5, "target %s does not have secrets at this KDC, need to proxy",
2599 : r->sname);
2600 0 : goto out;
2601 2 : default:
2602 2 : msg = krb5_get_error_message(r->context, ret);
2603 2 : kdc_log(r->context, config, 4, "UNKNOWN -- %s: %s", r->sname, msg);
2604 2 : krb5_free_error_message(r->context, msg);
2605 2 : ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
2606 2 : goto out;
2607 : }
2608 :
2609 49529 : ret = _kdc_check_access(r);
2610 49529 : if(ret)
2611 305 : goto out;
2612 :
2613 : /*
2614 : * This has to be here (not later), because we need to have r->sessionetype
2615 : * set prior to calling pa_pkinit_validate(), which in turn calls
2616 : * _kdc_pk_mk_pa_reply(), during padata validation.
2617 : */
2618 :
2619 : /*
2620 : * Select an enctype for the to-be-issued ticket's session key using the
2621 : * intersection of the client's requested enctypes and the server's (like a
2622 : * root krbtgt, but not necessarily) etypes from its HDB entry.
2623 : */
2624 50979 : ret = _kdc_find_session_etype(r, b->etype.val, b->etype.len,
2625 49224 : r->server, &r->sessionetype);
2626 49224 : if (ret) {
2627 170 : kdc_log(r->context, config, 4,
2628 : "Client (%s) from %s has no common enctypes with KDC "
2629 : "to use for the session key",
2630 : r->cname, from);
2631 170 : goto out;
2632 : }
2633 :
2634 : /*
2635 : * Select the best encryption type for the KDC without regard to
2636 : * the client since the client never needs to read that data.
2637 : */
2638 :
2639 50809 : ret = _kdc_get_preferred_key(r->context, config,
2640 49054 : r->server, r->sname,
2641 : &setype, &skey);
2642 49054 : if(ret)
2643 138 : goto out;
2644 :
2645 : /* If server is not krbtgt, fetch local krbtgt key for signing authdata */
2646 48916 : if (is_tgs) {
2647 43802 : krbtgt_key = skey;
2648 43802 : krbtgt_kvno = r->server->kvno;
2649 : } else {
2650 5114 : ret = get_local_tgs(r->context, config, r->server_princ->realm,
2651 : &r->krbtgtdb, &r->krbtgt);
2652 5114 : if (ret)
2653 0 : goto out;
2654 :
2655 5114 : ret = _kdc_get_preferred_key(r->context, config, r->krbtgt,
2656 5114 : r->server_princ->realm,
2657 : NULL, &krbtgt_key);
2658 5114 : if (ret)
2659 0 : goto out;
2660 :
2661 5114 : krbtgt_kvno = r->server->kvno;
2662 : }
2663 :
2664 : /*
2665 : * Pre-auth processing
2666 : */
2667 :
2668 48916 : if(req->padata){
2669 1755 : unsigned int n;
2670 :
2671 46126 : log_patypes(r, req->padata);
2672 :
2673 : /* Check if preauth matching */
2674 :
2675 370330 : for (n = 0; !found_pa && n < sizeof(pat) / sizeof(pat[0]); n++) {
2676 322878 : if (pat[n].validate == NULL)
2677 153678 : continue;
2678 169200 : if (r->armor_crypto == NULL && (pat[n].flags & PA_REQ_FAST))
2679 15353 : continue;
2680 153847 : if (!r->config->enable_fast_cookie && (pat[n].flags & PA_USES_FAST_COOKIE))
2681 15387 : continue;
2682 :
2683 138460 : kdc_log(r->context, config, 5,
2684 138460 : "Looking for %s pa-data -- %s", pat[n].name, r->cname);
2685 138460 : i = 0;
2686 138460 : pa = _kdc_find_padata(req, &i, pat[n].type);
2687 138460 : if (pa) {
2688 30739 : if (r->client->flags.synthetic &&
2689 0 : !(pat[n].flags & PA_SYNTHETIC_OK)) {
2690 0 : kdc_log(r->context, config, 4, "UNKNOWN -- %s", r->cname);
2691 0 : ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
2692 0 : goto out;
2693 : }
2694 30739 : kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_VIS, "pa", "%s",
2695 29569 : pat[n].name);
2696 30739 : ret = pat[n].validate(r, pa);
2697 30739 : if (ret != 0) {
2698 0 : krb5_error_code ret2;
2699 429 : Key *ckey = NULL;
2700 0 : krb5_boolean default_salt;
2701 :
2702 858 : if (ret != KRB5_KDC_ERR_MORE_PREAUTH_DATA_REQUIRED &&
2703 429 : !kdc_audit_getkv((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT))
2704 0 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
2705 : KDC_AUTH_EVENT_PREAUTH_FAILED);
2706 :
2707 : /*
2708 : * If there is a client key, send ETYPE_INFO{,2}
2709 : */
2710 429 : if (!r->client->flags.locked_out) {
2711 429 : ret2 = _kdc_find_etype(r, KFE_IS_PREAUTH|KFE_USE_CLIENT,
2712 429 : b->etype.val, b->etype.len,
2713 : NULL, &ckey, &default_salt);
2714 429 : if (ret2 == 0) {
2715 427 : ret2 = get_pa_etype_info_both(r->context, config, &b->etype,
2716 : r->rep.padata, ckey, !default_salt);
2717 427 : if (ret2 != 0)
2718 0 : ret = ret2;
2719 : }
2720 : }
2721 429 : goto out;
2722 : }
2723 30310 : if (!kdc_audit_getkv((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT))
2724 0 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
2725 : KDC_AUTH_EVENT_PREAUTH_SUCCEEDED);
2726 30310 : kdc_log(r->context, config, 4,
2727 : "%s pre-authentication succeeded -- %s",
2728 29140 : pat[n].name, r->cname);
2729 30310 : found_pa = 1;
2730 30310 : r->pa_used = &pat[n];
2731 30310 : r->et.flags.pre_authent = 1;
2732 : }
2733 : }
2734 : }
2735 :
2736 48487 : if (found_pa == 0) {
2737 18177 : Key *ckey = NULL;
2738 585 : size_t n;
2739 585 : krb5_boolean default_salt;
2740 :
2741 18177 : if (r->client->flags.synthetic) {
2742 0 : kdc_log(r->context, config, 4, "UNKNOWN -- %s", r->cname);
2743 0 : ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
2744 17592 : goto out;
2745 : }
2746 :
2747 218124 : for (n = 0; n < sizeof(pat) / sizeof(pat[0]); n++) {
2748 199947 : if ((pat[n].flags & PA_ANNOUNCE) == 0)
2749 72708 : continue;
2750 :
2751 127239 : if (!r->armor_crypto && (pat[n].flags & PA_REQ_FAST))
2752 18143 : continue;
2753 109096 : if (pat[n].type == KRB5_PADATA_PKINIT_KX && !r->config->allow_anonymous)
2754 18177 : continue;
2755 90919 : if (pat[n].type == KRB5_PADATA_ENC_TIMESTAMP) {
2756 18177 : if (r->armor_crypto && !r->config->enable_armored_pa_enc_timestamp)
2757 34 : continue;
2758 18143 : if (!r->armor_crypto && !r->config->enable_unarmored_pa_enc_timestamp)
2759 0 : continue;
2760 : }
2761 90885 : if (pat[n].type == KRB5_PADATA_FX_FAST && !r->config->enable_fast)
2762 758 : continue;
2763 90127 : if (pat[n].type == KRB5_PADATA_GSS && !r->config->enable_gss_preauth)
2764 18177 : continue;
2765 71950 : if (!r->config->enable_fast_cookie && (pat[n].flags & PA_USES_FAST_COOKIE))
2766 0 : continue;
2767 :
2768 71950 : ret = krb5_padata_add(r->context, r->rep.padata,
2769 69610 : pat[n].type, NULL, 0);
2770 71950 : if (ret)
2771 0 : goto out;
2772 : }
2773 :
2774 : /*
2775 : * If there is a client key, send ETYPE_INFO{,2}
2776 : */
2777 18762 : ret = _kdc_find_etype(r, KFE_IS_PREAUTH|KFE_USE_CLIENT,
2778 18177 : b->etype.val, b->etype.len,
2779 : NULL, &ckey, &default_salt);
2780 18177 : if (ret == 0) {
2781 18177 : ret = get_pa_etype_info_both(r->context, config, &b->etype,
2782 : r->rep.padata, ckey, !default_salt);
2783 18177 : if (ret)
2784 0 : goto out;
2785 : }
2786 :
2787 : /*
2788 : * If the client indicated support for PKINIT Freshness, send back a
2789 : * freshness token.
2790 : */
2791 18177 : ret = send_freshness_token(r, krbtgt_key, krbtgt_kvno);
2792 18177 : if (ret)
2793 0 : goto out;
2794 :
2795 : /*
2796 : * send requre preauth is its required or anon is requested,
2797 : * anon is today only allowed via preauth mechanisms.
2798 : */
2799 18177 : if (require_preauth_p(r) || _kdc_is_anon_request(&r->req)) {
2800 18177 : ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
2801 18177 : _kdc_set_e_text(r, "Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ");
2802 18177 : goto out;
2803 : }
2804 :
2805 0 : if (ckey == NULL) {
2806 0 : ret = KRB5KDC_ERR_CLIENT_NOTYET;
2807 0 : _kdc_set_e_text(r, "Doesn't have a client key available");
2808 0 : goto out;
2809 : }
2810 0 : krb5_free_keyblock_contents(r->context, &r->reply_key);
2811 0 : ret = krb5_copy_keyblock_contents(r->context, &ckey->key, &r->reply_key);
2812 0 : if (ret)
2813 0 : goto out;
2814 : }
2815 :
2816 30310 : r->canon_client_princ = r->client->principal;
2817 :
2818 30310 : if (_kdc_is_anon_request(&r->req)) {
2819 0 : ret = _kdc_check_anon_policy(r);
2820 0 : if (ret) {
2821 0 : _kdc_set_e_text(r, "Anonymous ticket requests are disabled");
2822 0 : goto out;
2823 : }
2824 :
2825 0 : r->et.flags.anonymous = 1;
2826 : }
2827 :
2828 30310 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
2829 : KDC_AUTH_EVENT_CLIENT_AUTHORIZED);
2830 :
2831 30310 : if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey) {
2832 0 : ret = KRB5KDC_ERR_BADOPTION;
2833 0 : _kdc_set_e_text(r, "Bad KDC options");
2834 0 : goto out;
2835 : }
2836 :
2837 : /*
2838 : * Build reply
2839 : */
2840 30310 : rep->pvno = 5;
2841 30310 : rep->msg_type = krb_as_rep;
2842 :
2843 60620 : if (!config->historical_anon_realm &&
2844 30310 : _kdc_is_anonymous(r->context, r->client_princ)) {
2845 0 : Realm anon_realm = KRB5_ANON_REALM;
2846 0 : ret = copy_Realm(&anon_realm, &rep->crealm);
2847 30310 : } else if (f.canonicalize || r->client->flags.force_canonicalize)
2848 30310 : ret = copy_Realm(&r->canon_client_princ->realm, &rep->crealm);
2849 : else
2850 0 : ret = copy_Realm(&r->client_princ->realm, &rep->crealm);
2851 30310 : if (ret)
2852 0 : goto out;
2853 30310 : if (r->et.flags.anonymous)
2854 0 : ret = _kdc_make_anonymous_principalname(&rep->cname);
2855 30310 : else if (f.canonicalize || r->client->flags.force_canonicalize)
2856 30310 : ret = _krb5_principal2principalname(&rep->cname, r->canon_client_princ);
2857 : else
2858 0 : ret = _krb5_principal2principalname(&rep->cname, r->client_princ);
2859 30310 : if (ret)
2860 0 : goto out;
2861 :
2862 30310 : rep->ticket.tkt_vno = 5;
2863 30310 : if (f.canonicalize || r->server->flags.force_canonicalize)
2864 30304 : ret = copy_Realm(&r->server->principal->realm, &rep->ticket.realm);
2865 : else
2866 6 : ret = copy_Realm(&r->server_princ->realm, &rep->ticket.realm);
2867 30310 : if (ret)
2868 0 : goto out;
2869 30310 : if (f.canonicalize || r->server->flags.force_canonicalize)
2870 30304 : _krb5_principal2principalname(&rep->ticket.sname,
2871 30304 : r->server->principal);
2872 : else
2873 6 : _krb5_principal2principalname(&rep->ticket.sname,
2874 6 : r->server_princ);
2875 : /* java 1.6 expects the name to be the same type, lets allow that
2876 : * uncomplicated name-types, when f.canonicalize is not set (to
2877 : * match Windows Server 1709). */
2878 : #define CNT(sp,t) (((sp)->sname->name_type) == KRB5_NT_##t)
2879 30310 : if (!f.canonicalize
2880 1501 : && (CNT(b, UNKNOWN) || CNT(b, PRINCIPAL) || CNT(b, SRV_INST) || CNT(b, SRV_HST) || CNT(b, SRV_XHST))) {
2881 1469 : rep->ticket.sname.name_type = b->sname->name_type;
2882 : }
2883 : #undef CNT
2884 :
2885 30310 : r->et.flags.initial = 1;
2886 30310 : if(r->client->flags.forwardable && r->server->flags.forwardable)
2887 30277 : r->et.flags.forwardable = f.forwardable;
2888 30310 : if(r->client->flags.proxiable && r->server->flags.proxiable)
2889 30271 : r->et.flags.proxiable = f.proxiable;
2890 39 : else if (f.proxiable) {
2891 4 : _kdc_set_e_text(r, "Ticket may not be proxiable");
2892 4 : ret = KRB5KDC_ERR_POLICY;
2893 4 : goto out;
2894 : }
2895 30306 : if(r->client->flags.postdate && r->server->flags.postdate)
2896 0 : r->et.flags.may_postdate = f.allow_postdate;
2897 30306 : else if (f.allow_postdate){
2898 0 : _kdc_set_e_text(r, "Ticket may not be postdateable");
2899 0 : ret = KRB5KDC_ERR_POLICY;
2900 0 : goto out;
2901 : }
2902 :
2903 30306 : if (b->addresses)
2904 98 : kdc_audit_addaddrs((kdc_request_t)r, b->addresses, "reqaddrs");
2905 :
2906 : /* check for valid set of addresses */
2907 30306 : if (!_kdc_check_addresses(r, b->addresses, r->addr)) {
2908 0 : if (r->config->warn_ticket_addresses) {
2909 0 : kdc_audit_setkv_bool((kdc_request_t)r, "wrongaddr", TRUE);
2910 : } else {
2911 0 : _kdc_set_e_text(r, "Request from wrong address");
2912 0 : ret = KRB5KRB_AP_ERR_BADADDR;
2913 0 : goto out;
2914 : }
2915 : }
2916 :
2917 30306 : ret = copy_PrincipalName(&rep->cname, &r->et.cname);
2918 30306 : if (ret)
2919 0 : goto out;
2920 30306 : ret = copy_Realm(&rep->crealm, &r->et.crealm);
2921 30306 : if (ret)
2922 0 : goto out;
2923 :
2924 : {
2925 1170 : time_t start;
2926 1170 : time_t t;
2927 :
2928 30306 : start = r->et.authtime = kdc_time;
2929 :
2930 30306 : if(f.postdated && req->req_body.from){
2931 0 : ALLOC(r->et.starttime);
2932 0 : start = *r->et.starttime = *req->req_body.from;
2933 0 : r->et.flags.invalid = 1;
2934 0 : r->et.flags.postdated = 1; /* XXX ??? */
2935 : }
2936 30306 : _kdc_fix_time(&b->till);
2937 30306 : t = *b->till;
2938 :
2939 : /* be careful not to overflow */
2940 :
2941 : /*
2942 : * Pre-auth can override r->client->max_life if configured.
2943 : *
2944 : * See pre-auth methods, specifically PKINIT, which can get or derive
2945 : * this from the client's certificate.
2946 : */
2947 30306 : if (r->pa_max_life > 0)
2948 0 : t = rk_time_add(start, min(rk_time_sub(t, start), r->pa_max_life));
2949 30306 : else if (r->client->max_life)
2950 30306 : t = rk_time_add(start, min(rk_time_sub(t, start),
2951 : *r->client->max_life));
2952 :
2953 30306 : if (r->server->max_life)
2954 30300 : t = rk_time_add(start, min(rk_time_sub(t, start),
2955 : *r->server->max_life));
2956 :
2957 : /* Pre-auth can bound endtime as well */
2958 30306 : if (r->pa_endtime > 0)
2959 45 : t = rk_time_add(start, min(rk_time_sub(t, start), r->pa_endtime));
2960 : #if 0
2961 : t = min(t, rk_time_add(start, realm->max_life));
2962 : #endif
2963 30306 : r->et.endtime = t;
2964 :
2965 30306 : if (start > r->et.endtime) {
2966 1 : _kdc_set_e_text(r, "Requested effective lifetime is negative or too short");
2967 1 : ret = KRB5KDC_ERR_NEVER_VALID;
2968 1 : goto out;
2969 : }
2970 :
2971 30305 : if(f.renewable_ok && r->et.endtime < *b->till){
2972 2 : f.renewable = 1;
2973 2 : if(b->rtime == NULL){
2974 2 : ALLOC(b->rtime);
2975 2 : *b->rtime = 0;
2976 : }
2977 2 : if(*b->rtime < *b->till)
2978 2 : *b->rtime = *b->till;
2979 : }
2980 30305 : if(f.renewable && b->rtime){
2981 3613 : t = *b->rtime;
2982 3613 : if(t == 0)
2983 14 : t = MAX_TIME;
2984 3613 : if(r->client->max_renew)
2985 3613 : t = rk_time_add(start, min(rk_time_sub(t, start),
2986 : *r->client->max_renew));
2987 3613 : if(r->server->max_renew)
2988 3613 : t = rk_time_add(start, min(rk_time_sub(t, start),
2989 : *r->server->max_renew));
2990 : #if 0
2991 : t = min(t, rk_time_add(start, realm->max_renew));
2992 : #endif
2993 3613 : ALLOC(r->et.renew_till);
2994 3613 : *r->et.renew_till = t;
2995 3613 : r->et.flags.renewable = 1;
2996 : }
2997 : }
2998 :
2999 30305 : if(b->addresses){
3000 98 : ALLOC(r->et.caddr);
3001 98 : copy_HostAddresses(b->addresses, r->et.caddr);
3002 : }
3003 :
3004 30305 : r->et.transited.tr_type = domain_X500_Compress;
3005 30305 : krb5_data_zero(&r->et.transited.contents);
3006 :
3007 : /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
3008 : * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
3009 : * incapable of correctly decoding SEQUENCE OF's of zero length.
3010 : *
3011 : * To fix this, always send at least one no-op last_req
3012 : *
3013 : * If there's a pw_end or valid_end we will use that,
3014 : * otherwise just a dummy lr.
3015 : */
3016 30305 : r->ek.last_req.val = malloc(2 * sizeof(*r->ek.last_req.val));
3017 30305 : if (r->ek.last_req.val == NULL) {
3018 0 : ret = ENOMEM;
3019 0 : goto out;
3020 : }
3021 30305 : r->ek.last_req.len = 0;
3022 30305 : if (r->client->pw_end
3023 26625 : && (config->kdc_warn_pwexpire == 0
3024 0 : || kdc_time + config->kdc_warn_pwexpire >= *r->client->pw_end)) {
3025 26625 : r->ek.last_req.val[r->ek.last_req.len].lr_type = LR_PW_EXPTIME;
3026 26625 : r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->pw_end;
3027 26625 : ++r->ek.last_req.len;
3028 : }
3029 30305 : if (r->client->valid_end) {
3030 0 : r->ek.last_req.val[r->ek.last_req.len].lr_type = LR_ACCT_EXPTIME;
3031 0 : r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->valid_end;
3032 0 : ++r->ek.last_req.len;
3033 : }
3034 30305 : if (r->ek.last_req.len == 0) {
3035 3680 : r->ek.last_req.val[r->ek.last_req.len].lr_type = LR_NONE;
3036 3680 : r->ek.last_req.val[r->ek.last_req.len].lr_value = 0;
3037 3680 : ++r->ek.last_req.len;
3038 : }
3039 : /* Set the nonce if it’s not already set. */
3040 30305 : if (!r->ek.nonce) {
3041 30262 : r->ek.nonce = b->nonce;
3042 : }
3043 30305 : if (r->client->valid_end || r->client->pw_end) {
3044 26625 : ALLOC(r->ek.key_expiration);
3045 26625 : if (r->client->valid_end) {
3046 0 : if (r->client->pw_end)
3047 0 : *r->ek.key_expiration = min(*r->client->valid_end,
3048 : *r->client->pw_end);
3049 : else
3050 0 : *r->ek.key_expiration = *r->client->valid_end;
3051 : } else
3052 26625 : *r->ek.key_expiration = *r->client->pw_end;
3053 : } else
3054 3680 : r->ek.key_expiration = NULL;
3055 30305 : r->ek.flags = r->et.flags;
3056 30305 : r->ek.authtime = r->et.authtime;
3057 30305 : if (r->et.starttime) {
3058 0 : ALLOC(r->ek.starttime);
3059 0 : *r->ek.starttime = *r->et.starttime;
3060 : }
3061 30305 : r->ek.endtime = r->et.endtime;
3062 30305 : if (r->et.renew_till) {
3063 3613 : ALLOC(r->ek.renew_till);
3064 3613 : *r->ek.renew_till = *r->et.renew_till;
3065 : }
3066 30305 : ret = copy_Realm(&rep->ticket.realm, &r->ek.srealm);
3067 30305 : if (ret)
3068 0 : goto out;
3069 30305 : ret = copy_PrincipalName(&rep->ticket.sname, &r->ek.sname);
3070 30305 : if (ret)
3071 0 : goto out;
3072 30305 : if(r->et.caddr){
3073 98 : ALLOC(r->ek.caddr);
3074 98 : copy_HostAddresses(r->et.caddr, r->ek.caddr);
3075 : }
3076 :
3077 : /*
3078 : * Check session and reply keys
3079 : */
3080 :
3081 30305 : if (r->session_key.keytype == ETYPE_NULL) {
3082 30260 : ret = krb5_generate_random_keyblock(r->context, r->sessionetype, &r->session_key);
3083 30260 : if (ret)
3084 0 : goto out;
3085 : }
3086 :
3087 30305 : if (r->reply_key.keytype == ETYPE_NULL) {
3088 0 : _kdc_set_e_text(r, "Client has no reply key");
3089 0 : ret = KRB5KDC_ERR_CLIENT_NOTYET;
3090 0 : goto out;
3091 : }
3092 :
3093 30305 : ret = copy_EncryptionKey(&r->session_key, &r->et.key);
3094 30305 : if (ret)
3095 0 : goto out;
3096 :
3097 30305 : ret = copy_EncryptionKey(&r->session_key, &r->ek.key);
3098 30305 : if (ret)
3099 0 : goto out;
3100 :
3101 : /* Add the PAC */
3102 30305 : if (!r->et.flags.anonymous) {
3103 30305 : ret = generate_pac(r, skey, krbtgt_key, is_tgs);
3104 30305 : if (ret)
3105 4 : goto out;
3106 : }
3107 :
3108 30301 : if (r->client->flags.synthetic) {
3109 0 : ret = add_synthetic_princ_ad(r);
3110 0 : if (ret)
3111 0 : goto out;
3112 : }
3113 :
3114 30301 : _kdc_log_timestamp(r, "AS-REQ", r->et.authtime,
3115 : r->et.starttime, r->et.endtime,
3116 : r->et.renew_till);
3117 :
3118 30301 : _log_astgs_req(r, setype);
3119 :
3120 : /*
3121 : * We always say we support FAST/enc-pa-rep
3122 : */
3123 :
3124 30301 : r->et.flags.enc_pa_rep = r->ek.flags.enc_pa_rep = 1;
3125 :
3126 : /*
3127 : * update reply-key with strengthen-key
3128 : */
3129 :
3130 30301 : ret = _kdc_fast_strengthen_reply_key(r);
3131 30301 : if (ret)
3132 0 : goto out;
3133 :
3134 : /*
3135 : * Add REQ_ENC_PA_REP if client supports it
3136 : */
3137 :
3138 30301 : i = 0;
3139 30301 : pa = _kdc_find_padata(req, &i, KRB5_PADATA_REQ_ENC_PA_REP);
3140 30301 : if (pa) {
3141 :
3142 26783 : ret = add_enc_pa_rep(r);
3143 26783 : if (ret) {
3144 0 : msg = krb5_get_error_message(r->context, ret);
3145 0 : _kdc_r_log(r, 4, "add_enc_pa_rep failed: %s: %d", msg, ret);
3146 0 : krb5_free_error_message(r->context, msg);
3147 0 : goto out;
3148 : }
3149 : }
3150 :
3151 : /*
3152 : * Last chance for plugins to update reply
3153 : */
3154 30301 : ret = _kdc_finalize_reply(r);
3155 30301 : if (ret)
3156 0 : goto out;
3157 :
3158 : /*
3159 : * Don't send kvno from client entry if the pre-authentication
3160 : * mechanism replaced the reply key.
3161 : */
3162 :
3163 34981 : ret = _kdc_encode_reply(r->context, config,
3164 30301 : r, req->req_body.nonce, setype,
3165 30301 : r->server->kvno, &skey->key,
3166 30256 : pa_used_flag_isset(r, PA_REPLACE_REPLY_KEY) ? 0 : r->client->kvno,
3167 30301 : 0, r->reply);
3168 30301 : if (ret)
3169 0 : goto out;
3170 :
3171 : /*
3172 : * Check if message is too large
3173 : */
3174 30301 : if (r->datagram_reply && r->reply->length > config->max_datagram_reply_length) {
3175 12558 : krb5_data_free(r->reply);
3176 12558 : ret = KRB5KRB_ERR_RESPONSE_TOO_BIG;
3177 12558 : _kdc_set_e_text(r, "Reply packet too large");
3178 : }
3179 :
3180 17743 : out:
3181 52160 : if (ret) {
3182 : /* Overwrite ‘error_code’ only if we have an actual error. */
3183 33879 : r->error_code = ret;
3184 : }
3185 : {
3186 52160 : krb5_error_code ret2 = _kdc_audit_request(r);
3187 52160 : if (ret2) {
3188 22 : krb5_data_free(r->reply);
3189 22 : ret = ret2;
3190 : }
3191 : }
3192 :
3193 : /*
3194 : * In case of a non proxy error, build an error message.
3195 : */
3196 52160 : if (ret != 0 && ret != HDB_ERR_NOT_FOUND_HERE && r->reply->length == 0) {
3197 32232 : kdc_log(r->context, config, 5, "as-req: sending error: %d to client", ret);
3198 33402 : ret = _kdc_fast_mk_error(r,
3199 : r->rep.padata,
3200 : r->armor_crypto,
3201 32232 : &req->req_body,
3202 32232 : r->error_code ? r->error_code : ret,
3203 : r->client_princ,
3204 : r->server_princ,
3205 : NULL, NULL,
3206 32232 : r->reply);
3207 : }
3208 :
3209 52160 : if (r->pa_used && r->pa_used->cleanup)
3210 0 : r->pa_used->cleanup(r);
3211 :
3212 52160 : free_AS_REP(&r->rep);
3213 52160 : free_EncTicketPart(&r->et);
3214 52160 : free_EncKDCRepPart(&r->ek);
3215 52160 : _kdc_free_fast_state(&r->fast);
3216 :
3217 52160 : if (r->client_princ) {
3218 52145 : krb5_free_principal(r->context, r->client_princ);
3219 52145 : r->client_princ = NULL;
3220 : }
3221 52160 : if (r->server_princ){
3222 52145 : krb5_free_principal(r->context, r->server_princ);
3223 52145 : r->server_princ = NULL;
3224 : }
3225 52160 : if (r->client)
3226 50069 : _kdc_free_ent(r->context, r->clientdb, r->client);
3227 52160 : if (r->server)
3228 49529 : _kdc_free_ent(r->context, r->serverdb, r->server);
3229 52160 : if (r->krbtgt)
3230 5114 : _kdc_free_ent(r->context, r->krbtgtdb, r->krbtgt);
3231 52160 : if (r->armor_crypto) {
3232 469 : krb5_crypto_destroy(r->context, r->armor_crypto);
3233 469 : r->armor_crypto = NULL;
3234 : }
3235 52160 : if (r->armor_ticket)
3236 469 : krb5_free_ticket(r->context, r->armor_ticket);
3237 52160 : if (r->armor_server)
3238 469 : _kdc_free_ent(r->context, r->armor_serverdb, r->armor_server);
3239 52160 : krb5_free_keyblock_contents(r->context, &r->reply_key);
3240 52160 : krb5_free_keyblock_contents(r->context, &r->enc_ad_key);
3241 52160 : krb5_free_keyblock_contents(r->context, &r->session_key);
3242 52160 : krb5_free_keyblock_contents(r->context, &r->strengthen_key);
3243 52160 : krb5_pac_free(r->context, r->pac);
3244 :
3245 52160 : return ret;
3246 : }
|