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 81075 : _kdc_fix_time(time_t **t)
58 : {
59 81075 : if(*t == NULL){
60 0 : ALLOC(*t);
61 0 : **t = MAX_TIME;
62 : }
63 81075 : if(**t == 0) **t = MAX_TIME; /* fix for old clients */
64 81075 : }
65 :
66 : static int
67 46574 : realloc_method_data(METHOD_DATA *md)
68 : {
69 1743 : PA_DATA *pa;
70 46574 : pa = realloc(md->val, (md->len + 1) * sizeof(*md->val));
71 46574 : if(pa == NULL)
72 0 : return ENOMEM;
73 46574 : md->val = pa;
74 46574 : md->len++;
75 46574 : 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 29690 : set_salt_padata(krb5_context context,
86 : krb5_kdc_configuration *config,
87 : METHOD_DATA *md, Key *key)
88 : {
89 29690 : if (!key->salt)
90 1218 : return 0;
91 :
92 28460 : return get_pa_etype_info2(context, config, md, key, TRUE);
93 : }
94 :
95 : const PA_DATA*
96 501719 : _kdc_find_padata(const KDC_REQ *req, int *start, int type)
97 : {
98 501719 : if (req->padata == NULL)
99 5778 : return NULL;
100 :
101 993275 : while((size_t)*start < req->padata->len){
102 693025 : (*start)++;
103 693025 : if(req->padata->val[*start - 1].padata_type == (unsigned)type)
104 195691 : return &req->padata->val[*start - 1];
105 : }
106 289329 : 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 18114 : is_default_salt_p(const krb5_salt *default_salt, const Key *key)
133 : {
134 18114 : if (key->salt == NULL)
135 990 : return TRUE;
136 17121 : if (default_salt->salttype != key->salt->type)
137 0 : return FALSE;
138 17121 : if (krb5_data_cmp(&default_salt->saltvalue, &key->salt->salt) != 0)
139 4205 : return FALSE;
140 12437 : 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 18114 : is_good_salt_p(const krb5_salt *default_salt, const Key *key)
154 : {
155 18114 : if (key->key.keytype == KRB5_ENCTYPE_DES_CBC_CRC)
156 0 : return is_default_salt_p(default_salt, key);
157 :
158 17529 : return TRUE;
159 : }
160 :
161 : krb5_boolean
162 29995 : _kdc_is_anon_request(const KDC_REQ *req)
163 : {
164 29995 : 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 58716 : return b->kdc_options.request_anonymous ||
174 29891 : (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 18116 : _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 18116 : krb5_boolean is_preauth = flags & KFE_IS_PREAUTH;
201 18116 : 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 18116 : krb5_enctype enctype = ETYPE_NULL;
207 585 : const krb5_enctype *p;
208 18116 : Key *key = NULL;
209 585 : size_t i, k, m;
210 :
211 18116 : if (is_preauth && (flags & KFE_USE_CLIENT) &&
212 18116 : r->client->flags.synthetic)
213 0 : return KRB5KDC_ERR_ETYPE_NOSUPP;
214 :
215 18116 : if ((flags & KFE_USE_CLIENT) && !r->client->flags.synthetic) {
216 18116 : princ = r->client;
217 18116 : request_princ = r->client_princ;
218 : } else {
219 0 : princ = r->server;
220 0 : request_princ = r->server->principal;
221 : }
222 :
223 18701 : use_strongest_session_key =
224 18116 : is_preauth ? r->config->preauth_use_strongest_session_key
225 18116 : : (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 18116 : ret = krb5_get_pw_salt(r->context, request_princ, &def_salt);
230 18116 : if (ret)
231 0 : return ret;
232 :
233 18116 : 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 18116 : 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 18116 : p = krb5_kerberos_enctypes(r->context);
264 18116 : for (i = 0;
265 41636 : p[i] != ETYPE_NULL && enctype == ETYPE_NULL;
266 23520 : i++) {
267 23520 : 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 57018 : for (k = 0; k < len && enctype == ETYPE_NULL; k++) {
273 :
274 33498 : if (p[i] != etypes[k])
275 14147 : continue;
276 :
277 19351 : 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 19351 : key = NULL;
290 19351 : 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 19936 : while (hdb_next_enctype2key(r->context, princ, NULL,
312 37465 : p[i], &key) == 0) {
313 18114 : if (key->key.keyvalue.length == 0) {
314 0 : ret = KRB5KDC_ERR_NULL_KEY;
315 0 : continue;
316 : }
317 18114 : enctype = p[i];
318 18114 : ret = 0;
319 35643 : if (is_preauth && ret_key != NULL &&
320 19299 : !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 18116 : 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 18116 : if (ret == 0) {
375 18114 : if (ret_enctype != NULL)
376 0 : *ret_enctype = enctype;
377 18114 : if (ret_key != NULL)
378 18114 : *ret_key = key;
379 18114 : if (ret_default_salt != NULL)
380 18114 : *ret_default_salt = is_default_salt_p(&def_salt, key);
381 : }
382 :
383 18116 : krb5_free_salt (r->context, def_salt);
384 18116 : 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 96855 : _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 96855 : 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 105535 : for (i = 0; i < len; ++i) {
406 : size_t j;
407 :
408 : /* Check that the server also supports the etype. */
409 123278 : for (j = 0; j < princ->session_etypes->len; ++j) {
410 114538 : if (princ->session_etypes->val[j] == etypes[i]) {
411 96572 : *ret_enctype = etypes[i];
412 96572 : return 0;
413 : }
414 : }
415 : }
416 :
417 223 : return KRB5KDC_ERR_ETYPE_NOSUPP;
418 : }
419 :
420 : krb5_error_code
421 41607 : _kdc_make_anonymous_principalname (PrincipalName *pn)
422 : {
423 41607 : pn->name_type = KRB5_NT_WELLKNOWN;
424 41607 : pn->name_string.len = 2;
425 41607 : pn->name_string.val = calloc(2, sizeof(*pn->name_string.val));
426 41607 : if (pn->name_string.val == NULL)
427 0 : goto failed;
428 :
429 41607 : pn->name_string.val[0] = strdup(KRB5_WELLKNOWN_NAME);
430 41607 : if (pn->name_string.val[0] == NULL)
431 0 : goto failed;
432 :
433 41607 : pn->name_string.val[1] = strdup(KRB5_ANON_NAME);
434 41607 : if (pn->name_string.val[1] == NULL)
435 0 : goto failed;
436 :
437 39949 : 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 180545 : _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 180545 : va_start(ap, fmt);
456 180545 : s = kdc_log_msg_va(r->context, r->config, level, fmt, ap);
457 180545 : if(s) free(s);
458 180545 : va_end(ap);
459 180545 : }
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 30100 : _kdc_set_e_text(astgs_request_t r, const char *fmt, ...)
478 : __attribute__ ((__format__ (__printf__, 2, 3)))
479 : {
480 1170 : va_list ap;
481 30100 : char *e_text = NULL;
482 1170 : int vasprintf_ret;
483 :
484 30100 : va_start(ap, fmt);
485 30100 : vasprintf_ret = vasprintf(&e_text, fmt, ap);
486 30100 : va_end(ap);
487 :
488 30100 : 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 30100 : 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 30100 : r->e_text = e_text;
504 30100 : r->e_text_buf = e_text;
505 30100 : kdc_log(r->context, r->config, 4, "%s", e_text);
506 : }
507 :
508 : void
509 77898 : _kdc_log_timestamp(astgs_request_t r, const char *type,
510 : KerberosTime authtime, KerberosTime *starttime,
511 : KerberosTime endtime, KerberosTime *renew_till)
512 : {
513 77898 : krb5_kdc_configuration *config = r->config;
514 2828 : char authtime_str[100], starttime_str[100],
515 : endtime_str[100], renewtime_str[100];
516 :
517 77898 : if (authtime)
518 77898 : kdc_audit_setkv_number((kdc_request_t)r, "auth", authtime);
519 77898 : if (starttime && *starttime)
520 48172 : kdc_audit_setkv_number((kdc_request_t)r, "start", *starttime);
521 77898 : if (endtime)
522 77898 : kdc_audit_setkv_number((kdc_request_t)r, "end", endtime);
523 77898 : if (renew_till && *renew_till)
524 6781 : kdc_audit_setkv_number((kdc_request_t)r, "renew", *renew_till);
525 :
526 77898 : krb5_format_time(r->context, authtime,
527 : authtime_str, sizeof(authtime_str), TRUE);
528 77898 : if (starttime)
529 48172 : krb5_format_time(r->context, *starttime,
530 : starttime_str, sizeof(starttime_str), TRUE);
531 : else
532 29726 : strlcpy(starttime_str, "unset", sizeof(starttime_str));
533 77898 : krb5_format_time(r->context, endtime,
534 : endtime_str, sizeof(endtime_str), TRUE);
535 77898 : if (renew_till)
536 6781 : krb5_format_time(r->context, *renew_till,
537 : renewtime_str, sizeof(renewtime_str), TRUE);
538 : else
539 71117 : strlcpy(renewtime_str, "unset", sizeof(renewtime_str));
540 :
541 77898 : 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 77898 : }
545 :
546 : /*
547 : *
548 : */
549 :
550 : #ifdef PKINIT
551 :
552 : static krb5_error_code
553 57 : pa_pkinit_validate(astgs_request_t r, const PA_DATA *pa)
554 : {
555 57 : pk_client_params *pkp = NULL;
556 57 : char *client_cert = NULL;
557 0 : krb5_error_code ret;
558 :
559 57 : ret = _kdc_pk_rd_padata(r, pa, &pkp);
560 57 : 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 55 : ret = _kdc_pk_validate_freshness_token(r, pkp);
573 55 : if (ret) {
574 12 : _kdc_r_log(r, 4, "Failed to validate freshness token");
575 12 : goto out;
576 : }
577 :
578 43 : ret = _kdc_pk_check_client(r, pkp, &client_cert);
579 43 : if (client_cert)
580 41 : kdc_audit_addkv((kdc_request_t)r, 0, KDC_REQUEST_KV_PKINIT_CLIENT_CERT,
581 : "%s", client_cert);
582 43 : 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 41 : r->pa_endtime = _kdc_pk_endtime(pkp);
591 41 : if (!r->client->flags.synthetic)
592 41 : r->pa_max_life = _kdc_pk_max_life(pkp);
593 :
594 41 : _kdc_r_log(r, 4, "PKINIT pre-authentication succeeded -- %s using %s",
595 : r->cname, client_cert);
596 :
597 41 : ret = _kdc_pk_mk_pa_reply(r, pkp);
598 41 : if (ret) {
599 0 : _kdc_set_e_text(r, "Failed to build PK-INIT reply");
600 0 : goto out;
601 : }
602 41 : ret = _kdc_add_initial_verified_cas(r->context, r->config,
603 : pkp, &r->et);
604 :
605 41 : 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 41 : r->ek.nonce = _kdc_pk_nonce(pkp);
613 :
614 57 : out:
615 57 : if (pkp)
616 55 : _kdc_pk_free_client_param(r->context, pkp);
617 57 : free(client_cert);
618 :
619 57 : 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 160 : 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 160 : unsigned int invalidKeys = 0;
706 0 : krb5_error_code ret;
707 160 : const Keys *keys = NULL;
708 0 : unsigned int i;
709 :
710 160 : if (KDCchallengekey)
711 160 : krb5_keyblock_zero(KDCchallengekey);
712 160 : if (used_key)
713 160 : *used_key = NULL;
714 :
715 160 : keys = hdb_kvno2keys(r->context, r->client, kvno);
716 160 : if (keys == NULL) {
717 0 : return KRB5KDC_ERR_ETYPE_NOSUPP;
718 : }
719 :
720 166 : for (i = 0; i < keys->len; i++) {
721 164 : struct Key *k = &keys->val[i];
722 0 : krb5_crypto challengecrypto, longtermcrypto;
723 0 : krb5_keyblock client_challengekey;
724 :
725 164 : ret = krb5_crypto_init(r->context, &k->key, 0, &longtermcrypto);
726 164 : if (ret)
727 6 : continue;
728 :
729 164 : ret = krb5_crypto_fx_cf2(r->context, r->armor_crypto, longtermcrypto,
730 : pepper1client, pepper2, aenctype,
731 : &client_challengekey);
732 164 : if (ret) {
733 0 : krb5_crypto_destroy(r->context, longtermcrypto);
734 0 : continue;
735 : }
736 :
737 164 : ret = krb5_crypto_init(r->context, &client_challengekey, 0,
738 : &challengecrypto);
739 164 : krb5_free_keyblock_contents(r->context, &client_challengekey);
740 164 : if (ret) {
741 0 : krb5_crypto_destroy(r->context, longtermcrypto);
742 0 : continue;
743 : }
744 :
745 164 : ret = _krb5_validate_pa_enc_challenge(r->context,
746 : challengecrypto,
747 : KRB5_KU_ENC_CHALLENGE_CLIENT,
748 : enc_data,
749 164 : r->cname);
750 164 : krb5_crypto_destroy(r->context, challengecrypto);
751 164 : 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 157 : if (pepper1kdc == NULL) {
781 : /* The caller is not interessted in details */
782 0 : return 0;
783 : }
784 :
785 157 : heim_assert(KDCchallengekey != NULL,
786 : "KDCchallengekey pointer required with pepper1kdc");
787 157 : 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 157 : ret = krb5_crypto_fx_cf2(r->context, r->armor_crypto, longtermcrypto,
796 : pepper1kdc, pepper2, aenctype,
797 : KDCchallengekey);
798 157 : krb5_crypto_destroy(r->context, longtermcrypto);
799 157 : if (ret)
800 0 : return ret;
801 :
802 157 : *used_key = k;
803 157 : 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 160 : pa_enc_chal_validate(astgs_request_t r, const PA_DATA *pa)
814 : {
815 160 : 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 160 : struct Key *k = NULL;
822 0 : size_t size;
823 :
824 160 : heim_assert(r->armor_crypto != NULL, "ENC-CHAL called for non FAST");
825 :
826 160 : 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 160 : 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 160 : ret = decode_EncryptedData(pa->padata_value.data,
842 160 : pa->padata_value.length,
843 : &enc_data,
844 : &size);
845 160 : 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 160 : pepper1client.data = "clientchallengearmor";
853 160 : pepper1client.length = strlen(pepper1client.data);
854 160 : pepper1kdc.data = "kdcchallengearmor";
855 160 : pepper1kdc.length = strlen(pepper1kdc.data);
856 160 : pepper2.data = "challengelongterm";
857 160 : pepper2.length = strlen(pepper2.data);
858 :
859 160 : krb5_crypto_getenctype(r->context, r->armor_crypto, &aenctype);
860 :
861 160 : kdc_log(r->context, r->config, 5, "FAST armor enctype is: %d", (int)aenctype);
862 :
863 160 : ret = pa_enc_chal_decrypt_kvno(r, aenctype,
864 : &pepper1client,
865 : &pepper1kdc,
866 : &pepper2,
867 : kvno,
868 : &enc_data,
869 : &KDCchallengekey,
870 : &k);
871 160 : 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 160 : 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 159 : 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 157 : free_EncryptedData(&enc_data);
966 157 : if (ret == 0) {
967 0 : krb5_crypto challengecrypto;
968 157 : char *estr = NULL;
969 157 : char *astr = NULL;
970 157 : char *kstr = NULL;
971 :
972 157 : ret = krb5_crypto_init(r->context, &KDCchallengekey, 0, &challengecrypto);
973 157 : krb5_free_keyblock_contents(r->context, &KDCchallengekey);
974 157 : if (ret)
975 0 : return ret;
976 :
977 157 : ret = _krb5_make_pa_enc_challenge(r->context, challengecrypto,
978 : KRB5_KU_ENC_CHALLENGE_KDC,
979 : r->rep.padata);
980 157 : krb5_crypto_destroy(r->context, challengecrypto);
981 157 : if (ret)
982 0 : return ret;
983 :
984 157 : ret = set_salt_padata(r->context, r->config, r->rep.padata, k);
985 157 : 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 157 : krb5_free_keyblock_contents(r->context, &r->reply_key);
993 157 : ret = krb5_copy_keyblock_contents(r->context, &k->key, &r->reply_key);
994 157 : if (ret)
995 0 : return ret;
996 :
997 157 : if (krb5_enctype_to_string(r->context, (int)aenctype, &astr))
998 0 : astr = NULL;
999 157 : if (krb5_enctype_to_string(r->context, enc_data.etype, &estr))
1000 0 : estr = NULL;
1001 157 : if (krb5_enctype_to_string(r->context, k->key.keytype, &kstr))
1002 0 : kstr = NULL;
1003 471 : _kdc_r_log(r, 4, "ENC-CHAL Pre-authentication succeeded -- %s "
1004 : "using armor=%s enc=%s key=%s",
1005 : r->cname,
1006 157 : astr ? astr : "unknown enctype",
1007 157 : estr ? estr : "unknown enctype",
1008 157 : kstr ? kstr : "unknown enctype");
1009 157 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
1010 : KDC_AUTH_EVENT_VALIDATED_LONG_TERM_KEY);
1011 157 : kdc_audit_setkv_number((kdc_request_t)r,
1012 : KDC_REQUEST_KV_PA_SUCCEEDED_KVNO,
1013 : kvno);
1014 157 : return 0;
1015 : }
1016 :
1017 0 : return ret;
1018 : }
1019 :
1020 : static krb5_error_code
1021 30104 : 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 30104 : Key *pa_key = NULL;
1030 30104 : const Keys *keys = NULL;
1031 :
1032 30104 : if (_pa_key)
1033 29856 : *_pa_key = NULL;
1034 :
1035 30104 : krb5_data_zero(ts_data);
1036 :
1037 30104 : keys = hdb_kvno2keys(r->context, r->client, kvno);
1038 30104 : if (keys == NULL) {
1039 158 : return KRB5KDC_ERR_ETYPE_NOSUPP;
1040 : }
1041 31116 : ret = hdb_enctype2key(r->context, r->client, keys,
1042 29946 : enc_data->etype, &pa_key);
1043 29946 : if(ret){
1044 5 : return KRB5KDC_ERR_ETYPE_NOSUPP;
1045 : }
1046 :
1047 29941 : try_next_key:
1048 29941 : ret = krb5_crypto_init(r->context, &pa_key->key, 0, &crypto);
1049 29941 : 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 29941 : ret = krb5_decrypt_EncryptedData(r->context,
1057 : crypto,
1058 : KRB5_KU_PA_ENC_TIMESTAMP,
1059 : enc_data,
1060 : ts_data);
1061 29941 : krb5_crypto_destroy(r->context, crypto);
1062 : /*
1063 : * Since the user might have several keys with the same
1064 : * enctype but with diffrent salting, we need to try all
1065 : * the keys with the same enctype.
1066 : */
1067 29941 : if (ret) {
1068 329 : ret = hdb_next_enctype2key(r->context, r->client, keys,
1069 329 : enc_data->etype, &pa_key);
1070 329 : if (ret == 0)
1071 0 : goto try_next_key;
1072 :
1073 329 : return KRB5KDC_ERR_PREAUTH_FAILED;
1074 : }
1075 :
1076 29612 : if (_pa_key)
1077 29542 : *_pa_key = pa_key;
1078 28442 : return 0;
1079 : }
1080 :
1081 : static krb5_error_code
1082 29857 : pa_enc_ts_validate(astgs_request_t r, const PA_DATA *pa)
1083 : {
1084 29857 : 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 29857 : 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 29856 : } 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 29856 : 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 31026 : ret = decode_EncryptedData(pa->padata_value.data,
1115 29856 : pa->padata_value.length,
1116 : &enc_data,
1117 : &len);
1118 29856 : 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 29856 : ret = pa_enc_ts_decrypt_kvno(r, kvno, &enc_data, &ts_data, &pa_key);
1126 29856 : 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 :
1147 29851 : if (ret == KRB5KDC_ERR_PREAUTH_FAILED) {
1148 0 : krb5_error_code ret2;
1149 309 : const char *msg = krb5_get_error_message(r->context, ret);
1150 309 : krb5_error_code hret = ret;
1151 0 : int hi;
1152 :
1153 309 : kdc_audit_setkv_number((kdc_request_t)r,
1154 : KDC_REQUEST_KV_PA_FAILED_KVNO,
1155 : kvno);
1156 :
1157 : /*
1158 : * Check if old and older keys are
1159 : * able to decrypt.
1160 : */
1161 329 : for (hi = 1; hi < 3; hi++) {
1162 0 : krb5_kvno hkvno;
1163 :
1164 322 : if (hi >= kvno) {
1165 74 : break;
1166 : }
1167 :
1168 248 : hkvno = kvno - hi;
1169 248 : hret = pa_enc_ts_decrypt_kvno(r, hkvno,
1170 : &enc_data,
1171 : &ts_data,
1172 : NULL); /* pa_key */
1173 248 : if (hret == 0) {
1174 70 : krb5_data_free(&ts_data);
1175 70 : kdc_audit_setkv_number((kdc_request_t)r,
1176 : KDC_REQUEST_KV_PA_HISTORIC_KVNO,
1177 : hkvno);
1178 70 : break;
1179 : }
1180 178 : if (hret == KRB5KDC_ERR_ETYPE_NOSUPP) {
1181 158 : break;
1182 : }
1183 : }
1184 :
1185 309 : ret2 = krb5_enctype_to_string(r->context, enc_data.etype, &str);
1186 309 : if (ret2)
1187 0 : str = NULL;
1188 309 : _kdc_r_log(r, 2, "Failed to decrypt PA-DATA -- %s "
1189 : "(enctype %s) error %s",
1190 309 : r->cname, str ? str : "unknown enctype", msg);
1191 309 : krb5_xfree(str);
1192 309 : krb5_free_error_message(r->context, msg);
1193 309 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_PA_ETYPE,
1194 309 : enc_data.etype);
1195 309 : if (hret == 0)
1196 70 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
1197 : KDC_AUTH_EVENT_HISTORIC_LONG_TERM_KEY);
1198 : else
1199 239 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
1200 : KDC_AUTH_EVENT_WRONG_LONG_TERM_KEY);
1201 :
1202 309 : free_EncryptedData(&enc_data);
1203 :
1204 309 : ret = KRB5KDC_ERR_PREAUTH_FAILED;
1205 309 : goto out;
1206 : }
1207 29542 : free_EncryptedData(&enc_data);
1208 29542 : ret = decode_PA_ENC_TS_ENC(ts_data.data,
1209 : ts_data.length,
1210 : &p,
1211 : &len);
1212 29542 : krb5_data_free(&ts_data);
1213 29542 : if(ret){
1214 0 : ret = KRB5KDC_ERR_PREAUTH_FAILED;
1215 0 : _kdc_r_log(r, 4, "Failed to decode PA-ENC-TS-ENC -- %s",
1216 : r->cname);
1217 0 : goto out;
1218 : }
1219 29542 : if (labs(kdc_time - p.patimestamp) > r->context->max_skew) {
1220 0 : char client_time[100];
1221 :
1222 9 : krb5_format_time(r->context, p.patimestamp,
1223 : client_time, sizeof(client_time), TRUE);
1224 :
1225 9 : ret = KRB5KRB_AP_ERR_SKEW;
1226 9 : _kdc_r_log(r, 4, "Too large time skew, "
1227 : "client time %s is out by %u > %u seconds -- %s",
1228 : client_time,
1229 9 : (unsigned)labs(kdc_time - p.patimestamp),
1230 9 : r->context->max_skew,
1231 : r->cname);
1232 9 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
1233 : KDC_AUTH_EVENT_CLIENT_TIME_SKEW);
1234 :
1235 : /*
1236 : * The following is needed to make windows clients to
1237 : * retry using the timestamp in the error message, if
1238 : * there is a e_text, they become unhappy.
1239 : */
1240 9 : r->e_text = NULL;
1241 9 : free_PA_ENC_TS_ENC(&p);
1242 9 : goto out;
1243 : }
1244 29533 : free_PA_ENC_TS_ENC(&p);
1245 :
1246 29533 : ret = set_salt_padata(r->context, r->config, r->rep.padata, pa_key);
1247 29521 : if (ret == 0)
1248 29533 : ret = krb5_copy_keyblock_contents(r->context, &pa_key->key, &r->reply_key);
1249 29533 : if (ret)
1250 0 : return ret;
1251 :
1252 29533 : ret = krb5_enctype_to_string(r->context, pa_key->key.keytype, &str);
1253 29533 : if (ret)
1254 0 : str = NULL;
1255 29533 : _kdc_r_log(r, 4, "ENC-TS Pre-authentication succeeded -- %s using %s",
1256 29533 : r->cname, str ? str : "unknown enctype");
1257 29533 : krb5_xfree(str);
1258 29533 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_PA_ETYPE,
1259 29533 : pa_key->key.keytype);
1260 29533 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
1261 : KDC_AUTH_EVENT_VALIDATED_LONG_TERM_KEY);
1262 29533 : kdc_audit_setkv_number((kdc_request_t)r,
1263 : KDC_REQUEST_KV_PA_SUCCEEDED_KVNO,
1264 : kvno);
1265 :
1266 29533 : ret = 0;
1267 :
1268 28686 : out:
1269 :
1270 28686 : return ret;
1271 : }
1272 :
1273 : #ifdef PKINIT
1274 :
1275 : static krb5_error_code
1276 4 : make_freshness_token(astgs_request_t r, const Key *krbtgt_key, unsigned krbtgt_kvno)
1277 : {
1278 4 : krb5_error_code ret = 0;
1279 4 : const struct timeval current_kdc_time = krb5_kdc_get_time();
1280 4 : int usec = current_kdc_time.tv_usec;
1281 4 : const PA_ENC_TS_ENC ts_enc = {
1282 4 : .patimestamp = current_kdc_time.tv_sec,
1283 : .pausec = &usec,
1284 : };
1285 4 : unsigned char *encoded_ts_enc = NULL;
1286 0 : size_t ts_enc_size;
1287 4 : size_t ts_enc_len = 0;
1288 0 : EncryptedData encdata;
1289 0 : krb5_crypto crypto;
1290 4 : unsigned char *token = NULL;
1291 0 : size_t token_size;
1292 4 : size_t token_len = 0;
1293 0 : size_t token_alloc_size;
1294 :
1295 4 : ASN1_MALLOC_ENCODE(PA_ENC_TS_ENC,
1296 : encoded_ts_enc,
1297 : ts_enc_size,
1298 : &ts_enc,
1299 : &ts_enc_len,
1300 : ret);
1301 4 : if (ret)
1302 0 : return ret;
1303 4 : if (ts_enc_size != ts_enc_len)
1304 0 : krb5_abortx(r->context, "internal error in ASN.1 encoder");
1305 :
1306 4 : ret = krb5_crypto_init(r->context, &krbtgt_key->key, 0, &crypto);
1307 4 : if (ret) {
1308 0 : free(encoded_ts_enc);
1309 0 : return ret;
1310 : }
1311 :
1312 4 : ret = krb5_encrypt_EncryptedData(r->context,
1313 : crypto,
1314 : KRB5_KU_AS_FRESHNESS,
1315 : encoded_ts_enc,
1316 : ts_enc_len,
1317 : krbtgt_kvno,
1318 : &encdata);
1319 4 : free(encoded_ts_enc);
1320 4 : krb5_crypto_destroy(r->context, crypto);
1321 4 : if (ret)
1322 0 : return ret;
1323 :
1324 4 : token_size = length_EncryptedData(&encdata);
1325 4 : token_alloc_size = token_size + 2; /* Account for the two leading zero bytes. */
1326 4 : token = calloc(1, token_alloc_size);
1327 4 : if (token == NULL) {
1328 0 : free_EncryptedData(&encdata);
1329 0 : return ENOMEM;
1330 : }
1331 :
1332 4 : ret = encode_EncryptedData(token + token_alloc_size - 1,
1333 : token_size,
1334 : &encdata,
1335 : &token_len);
1336 4 : free_EncryptedData(&encdata);
1337 4 : if (ret) {
1338 0 : free(token);
1339 0 : return ret;
1340 : }
1341 4 : if (token_size != token_len)
1342 0 : krb5_abortx(r->context, "internal error in ASN.1 encoder");
1343 :
1344 4 : ret = krb5_padata_add(r->context,
1345 : r->rep.padata,
1346 : KRB5_PADATA_AS_FRESHNESS,
1347 : token,
1348 : token_alloc_size);
1349 4 : if (ret)
1350 0 : free(token);
1351 4 : return ret;
1352 : }
1353 :
1354 : #endif /* PKINIT */
1355 :
1356 : static krb5_error_code
1357 17773 : send_freshness_token(astgs_request_t r, const Key *krbtgt_key, unsigned krbtgt_kvno)
1358 : {
1359 17773 : krb5_error_code ret = 0;
1360 : #ifdef PKINIT
1361 17773 : int idx = 0;
1362 17773 : const PA_DATA *freshness_padata = NULL;
1363 :
1364 17773 : freshness_padata = _kdc_find_padata(&r->req,
1365 : &idx,
1366 : KRB5_PADATA_AS_FRESHNESS);
1367 17773 : if (freshness_padata == NULL) {
1368 17184 : return 0;
1369 : }
1370 :
1371 4 : ret = make_freshness_token(r, krbtgt_key, krbtgt_kvno);
1372 : #endif /* PKINIT */
1373 4 : return ret;
1374 : }
1375 :
1376 : struct kdc_patypes {
1377 : int type;
1378 : const char *name;
1379 : unsigned int flags;
1380 : #define PA_ANNOUNCE 1
1381 : #define PA_REQ_FAST 2 /* only use inside fast */
1382 : #define PA_SYNTHETIC_OK 4
1383 : #define PA_REPLACE_REPLY_KEY 8 /* PA mech replaces reply key */
1384 : #define PA_USES_LONG_TERM_KEY 16 /* PA mech uses client's long-term key */
1385 : #define PA_USES_FAST_COOKIE 32 /* Multi-step PA mech maintains state in PA-FX-COOKIE */
1386 : krb5_error_code (*validate)(astgs_request_t, const PA_DATA *pa);
1387 : krb5_error_code (*finalize_pac)(astgs_request_t r);
1388 : void (*cleanup)(astgs_request_t r);
1389 : };
1390 :
1391 : static const struct kdc_patypes pat[] = {
1392 : #ifdef PKINIT
1393 : {
1394 : KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)",
1395 : PA_ANNOUNCE | PA_SYNTHETIC_OK | PA_REPLACE_REPLY_KEY,
1396 : pa_pkinit_validate, NULL, NULL
1397 : },
1398 : {
1399 : KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", PA_ANNOUNCE | PA_REPLACE_REPLY_KEY,
1400 : pa_pkinit_validate, NULL, NULL
1401 : },
1402 : {
1403 : KRB5_PADATA_PKINIT_KX, "Anonymous PK-INIT", PA_ANNOUNCE,
1404 : NULL, NULL, NULL
1405 : },
1406 : #else
1407 : { KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)", 0, NULL , NULL, NULL },
1408 : { KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", 0, NULL, NULL, NULL },
1409 : { KRB5_PADATA_PKINIT_KX, "Anonymous PK-INIT", 0, NULL, NULL, NULL },
1410 : #endif
1411 : { KRB5_PADATA_PA_PK_OCSP_RESPONSE , "OCSP", 0, NULL, NULL, NULL },
1412 : {
1413 : KRB5_PADATA_ENC_TIMESTAMP , "ENC-TS",
1414 : PA_ANNOUNCE | PA_USES_LONG_TERM_KEY,
1415 : pa_enc_ts_validate, NULL, NULL
1416 : },
1417 : {
1418 : KRB5_PADATA_ENCRYPTED_CHALLENGE , "ENC-CHAL",
1419 : PA_ANNOUNCE | PA_USES_LONG_TERM_KEY | PA_REQ_FAST,
1420 : pa_enc_chal_validate, NULL, NULL
1421 : },
1422 : { KRB5_PADATA_REQ_ENC_PA_REP , "REQ-ENC-PA-REP", 0, NULL, NULL, NULL },
1423 : { KRB5_PADATA_FX_FAST, "FX-FAST", PA_ANNOUNCE, NULL, NULL, NULL },
1424 : { KRB5_PADATA_FX_ERROR, "FX-ERROR", 0, NULL, NULL, NULL },
1425 : { KRB5_PADATA_FX_COOKIE, "FX-COOKIE", 0, NULL, NULL, NULL },
1426 : {
1427 : KRB5_PADATA_GSS , "GSS",
1428 : PA_ANNOUNCE | PA_SYNTHETIC_OK | PA_REPLACE_REPLY_KEY | PA_USES_FAST_COOKIE,
1429 : pa_gss_validate, pa_gss_finalize_pac, NULL
1430 : },
1431 : };
1432 :
1433 : static void
1434 45059 : log_patypes(astgs_request_t r, METHOD_DATA *padata)
1435 : {
1436 45059 : krb5_kdc_configuration *config = r->config;
1437 45059 : struct rk_strpool *p = NULL;
1438 1755 : char *str;
1439 1755 : size_t n, m;
1440 :
1441 118649 : for (n = 0; n < padata->len; n++) {
1442 468931 : for (m = 0; m < sizeof(pat) / sizeof(pat[0]); m++) {
1443 466133 : if (padata->val[n].padata_type == pat[m].type) {
1444 70792 : p = rk_strpoolprintf(p, "%s", pat[m].name);
1445 70792 : break;
1446 : }
1447 : }
1448 73590 : if (m == sizeof(pat) / sizeof(pat[0]))
1449 2798 : p = rk_strpoolprintf(p, "%d", padata->val[n].padata_type);
1450 73590 : if (p && n + 1 < padata->len)
1451 28531 : p = rk_strpoolprintf(p, ", ");
1452 73590 : if (p == NULL) {
1453 0 : kdc_log(r->context, config, 1, "out of memory");
1454 0 : return;
1455 : }
1456 : }
1457 45059 : if (p == NULL)
1458 0 : p = rk_strpoolprintf(p, "none");
1459 :
1460 45059 : str = rk_strpoolcollect(p);
1461 45059 : kdc_log(r->context, config, 4, "Client sent patypes: %s", str);
1462 45059 : kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE,
1463 : "client-pa", "%s", str);
1464 45059 : free(str);
1465 : }
1466 :
1467 : static krb5_boolean
1468 59451 : pa_used_flag_isset(astgs_request_t r, unsigned int flag)
1469 : {
1470 59451 : if (r->pa_used == NULL)
1471 0 : return FALSE;
1472 :
1473 59451 : return (r->pa_used->flags & flag) == flag;
1474 : }
1475 :
1476 : /*
1477 : *
1478 : */
1479 :
1480 : krb5_error_code
1481 77898 : _kdc_encode_reply(krb5_context context,
1482 : krb5_kdc_configuration *config,
1483 : astgs_request_t r, uint32_t nonce,
1484 : krb5_enctype etype,
1485 : int skvno, const EncryptionKey *skey,
1486 : int ckvno,
1487 : int rk_is_subkey,
1488 : krb5_data *reply)
1489 : {
1490 2828 : unsigned char *buf;
1491 2828 : size_t buf_size;
1492 77898 : size_t len = 0;
1493 2828 : krb5_error_code ret;
1494 2828 : krb5_crypto crypto;
1495 77898 : KDC_REP *rep = &r->rep;
1496 77898 : EncTicketPart *et = &r->et;
1497 77898 : EncKDCRepPart *ek = &r->ek;
1498 :
1499 77898 : heim_assert(rep->padata != NULL, "reply padata uninitialized");
1500 :
1501 77898 : ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret);
1502 77898 : if(ret) {
1503 0 : const char *msg = krb5_get_error_message(context, ret);
1504 0 : kdc_log(context, config, 4, "Failed to encode ticket: %s", msg);
1505 0 : krb5_free_error_message(context, msg);
1506 0 : return ret;
1507 : }
1508 77898 : if(buf_size != len)
1509 0 : krb5_abortx(context, "Internal error in ASN.1 encoder");
1510 :
1511 77898 : ret = krb5_crypto_init(context, skey, etype, &crypto);
1512 77898 : if (ret) {
1513 0 : const char *msg = krb5_get_error_message(context, ret);
1514 0 : kdc_log(context, config, 4, "krb5_crypto_init failed: %s", msg);
1515 0 : krb5_free_error_message(context, msg);
1516 0 : free(buf);
1517 0 : return ret;
1518 : }
1519 :
1520 77898 : ret = krb5_encrypt_EncryptedData(context,
1521 : crypto,
1522 : KRB5_KU_TICKET,
1523 : buf,
1524 : len,
1525 : skvno,
1526 : &rep->ticket.enc_part);
1527 77898 : free(buf);
1528 77898 : krb5_crypto_destroy(context, crypto);
1529 77898 : if(ret) {
1530 0 : const char *msg = krb5_get_error_message(context, ret);
1531 0 : kdc_log(context, config, 4, "Failed to encrypt data: %s", msg);
1532 0 : krb5_free_error_message(context, msg);
1533 0 : return ret;
1534 : }
1535 :
1536 77898 : if (r && r->armor_crypto) {
1537 1658 : KrbFastFinished finished;
1538 1658 : krb5_data data;
1539 :
1540 42002 : kdc_log(context, config, 4, "FAST armor protection");
1541 :
1542 42002 : memset(&finished, 0, sizeof(finished));
1543 42002 : krb5_data_zero(&data);
1544 :
1545 42002 : finished.timestamp = kdc_time;
1546 42002 : finished.usec = 0;
1547 42002 : finished.crealm = et->crealm;
1548 42002 : finished.cname = et->cname;
1549 :
1550 42002 : ASN1_MALLOC_ENCODE(Ticket, data.data, data.length,
1551 : &rep->ticket, &len, ret);
1552 42002 : if (ret)
1553 0 : return ret;
1554 42002 : if (data.length != len)
1555 0 : krb5_abortx(context, "internal asn.1 error");
1556 :
1557 42002 : ret = krb5_create_checksum(context, r->armor_crypto,
1558 : KRB5_KU_FAST_FINISHED, 0,
1559 : data.data, data.length,
1560 : &finished.ticket_checksum);
1561 42002 : krb5_data_free(&data);
1562 42002 : if (ret)
1563 0 : return ret;
1564 :
1565 42002 : ret = _kdc_fast_mk_response(context, r->armor_crypto,
1566 : rep->padata, &r->strengthen_key, &finished,
1567 : nonce, &data);
1568 42002 : free_Checksum(&finished.ticket_checksum);
1569 42002 : if (ret)
1570 0 : return ret;
1571 :
1572 42002 : free_METHOD_DATA(r->rep.padata);
1573 :
1574 42002 : ret = krb5_padata_add(context, rep->padata,
1575 : KRB5_PADATA_FX_FAST,
1576 : data.data, data.length);
1577 42002 : if (ret)
1578 0 : return ret;
1579 :
1580 : /*
1581 : * Hide client name for privacy reasons
1582 : */
1583 42002 : if (r->fast.flags.requested_hidden_names) {
1584 41607 : Realm anon_realm = KRB5_ANON_REALM;
1585 :
1586 41607 : free_Realm(&rep->crealm);
1587 41607 : ret = copy_Realm(&anon_realm, &rep->crealm);
1588 41607 : if (ret == 0) {
1589 41607 : free_PrincipalName(&rep->cname);
1590 41607 : ret = _kdc_make_anonymous_principalname(&rep->cname);
1591 : }
1592 41607 : if (ret)
1593 0 : return ret;
1594 : }
1595 : }
1596 :
1597 77898 : if (rep->padata->len == 0) {
1598 7557 : free_METHOD_DATA(rep->padata);
1599 7557 : free(rep->padata);
1600 7557 : rep->padata = NULL;
1601 : }
1602 :
1603 77898 : if(rep->msg_type == krb_as_rep && !config->encode_as_rep_as_tgs_rep)
1604 29726 : ASN1_MALLOC_ENCODE(EncASRepPart, buf, buf_size, ek, &len, ret);
1605 : else
1606 48172 : ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret);
1607 77898 : if(ret) {
1608 0 : const char *msg = krb5_get_error_message(context, ret);
1609 0 : kdc_log(context, config, 4, "Failed to encode KDC-REP: %s", msg);
1610 0 : krb5_free_error_message(context, msg);
1611 0 : return ret;
1612 : }
1613 77898 : if(buf_size != len) {
1614 0 : free(buf);
1615 0 : kdc_log(context, config, 4, "Internal error in ASN.1 encoder");
1616 0 : _kdc_set_e_text(r, "KDC internal error");
1617 0 : return KRB5KRB_ERR_GENERIC;
1618 : }
1619 77898 : ret = krb5_crypto_init(context, &r->reply_key, 0, &crypto);
1620 77898 : if (ret) {
1621 0 : const char *msg = krb5_get_error_message(context, ret);
1622 0 : free(buf);
1623 0 : kdc_log(context, config, 4, "krb5_crypto_init failed: %s", msg);
1624 0 : krb5_free_error_message(context, msg);
1625 0 : return ret;
1626 : }
1627 77898 : if(rep->msg_type == krb_as_rep) {
1628 29726 : ret = krb5_encrypt_EncryptedData(context,
1629 : crypto,
1630 : KRB5_KU_AS_REP_ENC_PART,
1631 : buf,
1632 : len,
1633 : ckvno,
1634 : &rep->enc_part);
1635 29726 : free(buf);
1636 29726 : if (ret == 0)
1637 29726 : ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret);
1638 : } else {
1639 48172 : ret = krb5_encrypt_EncryptedData(context,
1640 : crypto,
1641 : rk_is_subkey ?
1642 : KRB5_KU_TGS_REP_ENC_PART_SUB_KEY :
1643 : KRB5_KU_TGS_REP_ENC_PART_SESSION,
1644 : buf,
1645 : len,
1646 : ckvno,
1647 : &rep->enc_part);
1648 48172 : free(buf);
1649 48172 : if (ret == 0)
1650 48172 : ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret);
1651 : }
1652 77898 : krb5_crypto_destroy(context, crypto);
1653 77898 : if(ret) {
1654 0 : const char *msg = krb5_get_error_message(context, ret);
1655 0 : kdc_log(context, config, 4, "Failed to encode KDC-REP: %s", msg);
1656 0 : krb5_free_error_message(context, msg);
1657 0 : return ret;
1658 : }
1659 77898 : if(buf_size != len) {
1660 0 : free(buf);
1661 0 : kdc_log(context, config, 4, "Internal error in ASN.1 encoder");
1662 0 : _kdc_set_e_text(r, "KDC internal error");
1663 0 : return KRB5KRB_ERR_GENERIC;
1664 : }
1665 77898 : reply->data = buf;
1666 77898 : reply->length = buf_size;
1667 77898 : return 0;
1668 : }
1669 :
1670 : /*
1671 : *
1672 : */
1673 :
1674 : static krb5_error_code
1675 620 : get_pa_etype_info(krb5_context context,
1676 : krb5_kdc_configuration *config,
1677 : METHOD_DATA *md, Key *ckey,
1678 : krb5_boolean include_salt)
1679 : {
1680 620 : krb5_error_code ret = 0;
1681 0 : ETYPE_INFO_ENTRY eie; /* do not free this one */
1682 0 : ETYPE_INFO ei;
1683 0 : PA_DATA pa;
1684 0 : size_t len;
1685 :
1686 : /*
1687 : * Code moved here from what used to be make_etype_info_entry() because
1688 : * using the ASN.1 compiler-generated SEQUENCE OF add functions makes that
1689 : * old function's body and this one's small and clean.
1690 : *
1691 : * The following comment blocks were there:
1692 : *
1693 : * According to `the specs', we can't send a salt if we have AFS3 salted
1694 : * key, but that requires that you *know* what cell you are using (e.g by
1695 : * assuming that the cell is the same as the realm in lower case)
1696 : *
1697 : * We shouldn't sent salttype since it is incompatible with the
1698 : * specification and it breaks windows clients. The afs salting problem
1699 : * is solved by using KRB5-PADATA-AFS3-SALT implemented in Heimdal 0.7 and
1700 : * later.
1701 : *
1702 : * We return no salt type at all, as that should indicate the default salt
1703 : * type and make everybody happy. some systems (like w2k) dislike being
1704 : * told the salt type here.
1705 : */
1706 :
1707 620 : pa.padata_type = KRB5_PADATA_ETYPE_INFO;
1708 620 : pa.padata_value.data = NULL;
1709 620 : pa.padata_value.length = 0;
1710 620 : ei.len = 0;
1711 620 : ei.val = NULL;
1712 620 : eie.etype = ckey->key.keytype;
1713 620 : eie.salttype = NULL;
1714 620 : eie.salt = NULL;
1715 620 : if (include_salt && ckey->salt)
1716 0 : eie.salt = &ckey->salt->salt;
1717 620 : ret = add_ETYPE_INFO(&ei, &eie);
1718 620 : if (ret == 0)
1719 620 : ASN1_MALLOC_ENCODE(ETYPE_INFO, pa.padata_value.data, pa.padata_value.length,
1720 : &ei, &len, ret);
1721 620 : if (ret == 0)
1722 620 : add_METHOD_DATA(md, &pa);
1723 620 : free_ETYPE_INFO(&ei);
1724 620 : free_PA_DATA(&pa);
1725 620 : return ret;
1726 : }
1727 :
1728 : /*
1729 : *
1730 : */
1731 :
1732 : extern const int _krb5_AES_SHA1_string_to_default_iterator;
1733 : extern const int _krb5_AES_SHA2_string_to_default_iterator;
1734 :
1735 : static krb5_error_code
1736 45593 : make_s2kparams(int value, size_t len, krb5_data **ps2kparams)
1737 : {
1738 1740 : krb5_data *s2kparams;
1739 1740 : krb5_error_code ret;
1740 :
1741 45593 : ALLOC(s2kparams);
1742 45593 : if (s2kparams == NULL)
1743 0 : return ENOMEM;
1744 45593 : ret = krb5_data_alloc(s2kparams, len);
1745 45593 : if (ret) {
1746 0 : free(s2kparams);
1747 0 : return ret;
1748 : }
1749 45593 : _krb5_put_int(s2kparams->data, value, len);
1750 45593 : *ps2kparams = s2kparams;
1751 45593 : return 0;
1752 : }
1753 :
1754 : static krb5_error_code
1755 46574 : make_etype_info2_entry(ETYPE_INFO2_ENTRY *ent,
1756 : Key *key,
1757 : krb5_boolean include_salt)
1758 : {
1759 1743 : krb5_error_code ret;
1760 :
1761 46574 : ent->etype = key->key.keytype;
1762 46574 : if (key->salt && include_salt) {
1763 45581 : ALLOC(ent->salt);
1764 45581 : if (ent->salt == NULL)
1765 0 : return ENOMEM;
1766 45581 : *ent->salt = malloc(key->salt->salt.length + 1);
1767 45581 : if (*ent->salt == NULL) {
1768 0 : free(ent->salt);
1769 0 : ent->salt = NULL;
1770 0 : return ENOMEM;
1771 : }
1772 45581 : memcpy(*ent->salt, key->salt->salt.data, key->salt->salt.length);
1773 45581 : (*ent->salt)[key->salt->salt.length] = '\0';
1774 : } else
1775 993 : ent->salt = NULL;
1776 :
1777 46574 : ent->s2kparams = NULL;
1778 :
1779 46574 : switch (key->key.keytype) {
1780 45593 : case ETYPE_AES128_CTS_HMAC_SHA1_96:
1781 : case ETYPE_AES256_CTS_HMAC_SHA1_96:
1782 45593 : ret = make_s2kparams(_krb5_AES_SHA1_string_to_default_iterator,
1783 45593 : 4, &ent->s2kparams);
1784 45593 : break;
1785 0 : case KRB5_ENCTYPE_AES128_CTS_HMAC_SHA256_128:
1786 : case KRB5_ENCTYPE_AES256_CTS_HMAC_SHA384_192:
1787 0 : ret = make_s2kparams(_krb5_AES_SHA2_string_to_default_iterator,
1788 0 : 4, &ent->s2kparams);
1789 0 : break;
1790 0 : case ETYPE_DES_CBC_CRC:
1791 : case ETYPE_DES_CBC_MD4:
1792 : case ETYPE_DES_CBC_MD5:
1793 : /* Check if this was a AFS3 salted key */
1794 0 : if(key->salt && key->salt->type == hdb_afs3_salt)
1795 0 : ret = make_s2kparams(1, 1, &ent->s2kparams);
1796 : else
1797 0 : ret = 0;
1798 0 : break;
1799 978 : default:
1800 978 : ret = 0;
1801 978 : break;
1802 : }
1803 44831 : return ret;
1804 : }
1805 :
1806 : /*
1807 : * Return an ETYPE-INFO2. Enctypes are storted the same way as in the
1808 : * database (client supported enctypes first, then the unsupported
1809 : * enctypes).
1810 : */
1811 :
1812 : static krb5_error_code
1813 46574 : get_pa_etype_info2(krb5_context context,
1814 : krb5_kdc_configuration *config,
1815 : METHOD_DATA *md, Key *ckey,
1816 : krb5_boolean include_salt)
1817 : {
1818 46574 : krb5_error_code ret = 0;
1819 1743 : ETYPE_INFO2 pa;
1820 1743 : unsigned char *buf;
1821 1743 : size_t len;
1822 :
1823 46574 : pa.len = 1;
1824 46574 : pa.val = calloc(1, sizeof(pa.val[0]));
1825 46574 : if(pa.val == NULL)
1826 0 : return ENOMEM;
1827 :
1828 46574 : ret = make_etype_info2_entry(&pa.val[0], ckey, include_salt);
1829 46574 : if (ret) {
1830 0 : free_ETYPE_INFO2(&pa);
1831 0 : return ret;
1832 : }
1833 :
1834 46574 : ASN1_MALLOC_ENCODE(ETYPE_INFO2, buf, len, &pa, &len, ret);
1835 46574 : free_ETYPE_INFO2(&pa);
1836 46574 : if(ret)
1837 0 : return ret;
1838 46574 : ret = realloc_method_data(md);
1839 46574 : if(ret) {
1840 0 : free(buf);
1841 0 : return ret;
1842 : }
1843 46574 : md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO2;
1844 46574 : md->val[md->len - 1].padata_value.length = len;
1845 46574 : md->val[md->len - 1].padata_value.data = buf;
1846 46574 : return 0;
1847 : }
1848 :
1849 : /*
1850 : * Return 0 if the client has only older enctypes, this is for
1851 : * determining if the server should send ETYPE_INFO2 or not.
1852 : */
1853 :
1854 : static int
1855 18114 : newer_enctype_present(krb5_context context,
1856 : struct KDC_REQ_BODY_etype *etype_list)
1857 : {
1858 585 : size_t i;
1859 :
1860 19591 : for (i = 0; i < etype_list->len; i++) {
1861 18971 : if (!krb5_is_enctype_old(context, etype_list->val[i]))
1862 16909 : return 1;
1863 : }
1864 620 : return 0;
1865 : }
1866 :
1867 : static krb5_error_code
1868 18114 : get_pa_etype_info_both(krb5_context context,
1869 : krb5_kdc_configuration *config,
1870 : struct KDC_REQ_BODY_etype *etype_list,
1871 : METHOD_DATA *md, Key *ckey,
1872 : krb5_boolean include_salt)
1873 : {
1874 585 : krb5_error_code ret;
1875 :
1876 : /*
1877 : * Windows 2019 (and earlier versions) always sends the salt
1878 : * and Samba has testsuites that check this behaviour, so a
1879 : * Samba AD DC will set this flag to match the AS-REP packet
1880 : * more closely.
1881 : */
1882 18114 : if (config->force_include_pa_etype_salt)
1883 18114 : include_salt = TRUE;
1884 :
1885 : /*
1886 : * RFC4120 requires:
1887 : * When the AS server is to include pre-authentication data in a
1888 : * KRB-ERROR or in an AS-REP, it MUST use PA-ETYPE-INFO2, not
1889 : * PA-ETYPE-INFO, if the etype field of the client's AS-REQ lists
1890 : * at least one "newer" encryption type. Otherwise (when the etype
1891 : * field of the client's AS-REQ does not list any "newer" encryption
1892 : * types), it MUST send both PA-ETYPE-INFO2 and PA-ETYPE-INFO (both
1893 : * with an entry for each enctype). A "newer" enctype is any enctype
1894 : * first officially specified concurrently with or subsequent to the
1895 : * issue of this RFC. The enctypes DES, 3DES, or RC4 and any defined
1896 : * in [RFC1510] are not "newer" enctypes.
1897 : *
1898 : * It goes on to state:
1899 : * The preferred ordering of the "hint" pre-authentication data that
1900 : * affect client key selection is: ETYPE-INFO2, followed by ETYPE-INFO,
1901 : * followed by PW-SALT. As noted in Section 3.1.3, a KDC MUST NOT send
1902 : * ETYPE-INFO or PW-SALT when the client's AS-REQ includes at least one
1903 : * "newer" etype.
1904 : */
1905 :
1906 18114 : ret = get_pa_etype_info2(context, config, md, ckey, include_salt);
1907 18114 : if (ret)
1908 0 : return ret;
1909 :
1910 18114 : if (!newer_enctype_present(context, etype_list))
1911 620 : ret = get_pa_etype_info(context, config, md, ckey, include_salt);
1912 :
1913 17529 : return ret;
1914 : }
1915 :
1916 : /*
1917 : *
1918 : */
1919 :
1920 : void
1921 77898 : _log_astgs_req(astgs_request_t r, krb5_enctype setype)
1922 : {
1923 77898 : const KDC_REQ_BODY *b = &r->req.req_body;
1924 77898 : krb5_enctype cetype = r->reply_key.keytype;
1925 2828 : krb5_error_code ret;
1926 2828 : struct rk_strpool *p;
1927 77898 : struct rk_strpool *s = NULL;
1928 2828 : char *str;
1929 2828 : char *cet;
1930 2828 : char *set;
1931 2828 : size_t i;
1932 :
1933 : /*
1934 : * we are collecting ``p'' and ``s''. The former is a textual
1935 : * representation of the enctypes as strings which will be used
1936 : * for debugging. The latter is a terse comma separated list of
1937 : * the %d's of the enctypes to emit into our audit trail to
1938 : * conserve space in the logs.
1939 : */
1940 :
1941 77898 : p = rk_strpoolprintf(NULL, "%s", "Client supported enctypes: ");
1942 :
1943 505734 : for (i = 0; i < b->etype.len; i++) {
1944 425008 : ret = krb5_enctype_to_string(r->context, b->etype.val[i], &str);
1945 425008 : if (ret == 0) {
1946 424986 : p = rk_strpoolprintf(p, "%s", str);
1947 424986 : free(str);
1948 : } else
1949 22 : p = rk_strpoolprintf(p, "%d", b->etype.val[i]);
1950 425008 : if (p == NULL) {
1951 0 : rk_strpoolfree(s);
1952 0 : _kdc_r_log(r, 4, "out of memory");
1953 0 : return;
1954 : }
1955 425008 : s = rk_strpoolprintf(s, "%d", b->etype.val[i]);
1956 425008 : if (i + 1 < b->etype.len) {
1957 347110 : p = rk_strpoolprintf(p, ", ");
1958 347110 : s = rk_strpoolprintf(s, ",");
1959 : }
1960 : }
1961 77898 : if (p == NULL)
1962 0 : p = rk_strpoolprintf(p, "no encryption types");
1963 :
1964 77898 : str = rk_strpoolcollect(s);
1965 77898 : if (str)
1966 77898 : kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE, "etypes", "%s",
1967 : str);
1968 77898 : free(str);
1969 :
1970 77898 : ret = krb5_enctype_to_string(r->context, cetype, &cet);
1971 77898 : if(ret == 0) {
1972 77898 : ret = krb5_enctype_to_string(r->context, setype, &set);
1973 77898 : if (ret == 0) {
1974 77898 : p = rk_strpoolprintf(p, ", using %s/%s", cet, set);
1975 77898 : free(set);
1976 : }
1977 77898 : free(cet);
1978 : }
1979 77898 : if (ret != 0)
1980 0 : p = rk_strpoolprintf(p, ", using enctypes %d/%d",
1981 : cetype, setype);
1982 :
1983 77898 : str = rk_strpoolcollect(p);
1984 77898 : if (str)
1985 77898 : _kdc_r_log(r, 4, "%s", str);
1986 77898 : free(str);
1987 :
1988 77898 : kdc_audit_addkv((kdc_request_t)r, 0, "etype", "%d/%d", cetype, setype);
1989 :
1990 : {
1991 2828 : char fixedstr[128];
1992 2828 : int result;
1993 :
1994 77898 : result = unparse_flags(KDCOptions2int(b->kdc_options), asn1_KDCOptions_units(),
1995 : fixedstr, sizeof(fixedstr));
1996 77898 : if (result > 0) {
1997 72565 : _kdc_r_log(r, 4, "Requested flags: %s", fixedstr);
1998 72565 : kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE,
1999 : "flags", "%s", fixedstr);
2000 : }
2001 : }
2002 : }
2003 :
2004 : /*
2005 : * verify the flags on `client' and `server', returning 0
2006 : * if they are OK and generating an error messages and returning
2007 : * and error code otherwise.
2008 : */
2009 :
2010 : KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL
2011 98025 : kdc_check_flags(astgs_request_t r,
2012 : krb5_boolean is_as_req,
2013 : hdb_entry *client,
2014 : hdb_entry *server)
2015 : {
2016 98025 : if (client != NULL) {
2017 : /* check client */
2018 97975 : if (client->flags.locked_out) {
2019 0 : kdc_audit_addreason((kdc_request_t)r, "Client is locked out");
2020 0 : return KRB5KDC_ERR_CLIENT_REVOKED;
2021 : }
2022 :
2023 97975 : if (client->flags.invalid) {
2024 0 : kdc_audit_addreason((kdc_request_t)r,
2025 : "Client has invalid bit set");
2026 0 : return KRB5KDC_ERR_POLICY;
2027 : }
2028 :
2029 97975 : if (!client->flags.client) {
2030 0 : kdc_audit_addreason((kdc_request_t)r,
2031 : "Principal may not act as client");
2032 0 : return KRB5KDC_ERR_POLICY;
2033 : }
2034 :
2035 97975 : if (client->valid_start && *client->valid_start > kdc_time) {
2036 0 : char starttime_str[100];
2037 0 : krb5_format_time(r->context, *client->valid_start,
2038 : starttime_str, sizeof(starttime_str), TRUE);
2039 0 : kdc_audit_addreason((kdc_request_t)r, "Client not yet valid "
2040 : "until %s", starttime_str);
2041 0 : return KRB5KDC_ERR_CLIENT_NOTYET;
2042 : }
2043 :
2044 97975 : if (client->valid_end && *client->valid_end < kdc_time) {
2045 0 : char endtime_str[100];
2046 0 : krb5_format_time(r->context, *client->valid_end,
2047 : endtime_str, sizeof(endtime_str), TRUE);
2048 0 : kdc_audit_addreason((kdc_request_t)r, "Client expired at %s",
2049 : endtime_str);
2050 0 : return KRB5KDC_ERR_NAME_EXP;
2051 : }
2052 :
2053 97975 : if (client->flags.require_pwchange &&
2054 0 : (server == NULL || !server->flags.change_pw))
2055 0 : return KRB5KDC_ERR_KEY_EXPIRED;
2056 :
2057 97975 : if (client->pw_end && *client->pw_end < kdc_time
2058 16 : && (server == NULL || !server->flags.change_pw)) {
2059 0 : char pwend_str[100];
2060 0 : krb5_format_time(r->context, *client->pw_end,
2061 : pwend_str, sizeof(pwend_str), TRUE);
2062 0 : kdc_audit_addreason((kdc_request_t)r, "Client's key has expired "
2063 : "at %s", pwend_str);
2064 0 : return KRB5KDC_ERR_KEY_EXPIRED;
2065 : }
2066 : }
2067 :
2068 : /* check server */
2069 :
2070 98025 : if (server != NULL) {
2071 97205 : if (server->flags.locked_out) {
2072 0 : kdc_audit_addreason((kdc_request_t)r, "Server locked out");
2073 0 : return KRB5KDC_ERR_SERVICE_REVOKED;
2074 : }
2075 97205 : if (server->flags.invalid) {
2076 0 : kdc_audit_addreason((kdc_request_t)r,
2077 : "Server has invalid flag set");
2078 0 : return KRB5KDC_ERR_POLICY;
2079 : }
2080 97205 : if (!server->flags.server) {
2081 0 : kdc_audit_addreason((kdc_request_t)r,
2082 : "Principal may not act as server");
2083 0 : return KRB5KDC_ERR_POLICY;
2084 : }
2085 :
2086 97205 : if (!is_as_req && server->flags.initial) {
2087 0 : kdc_audit_addreason((kdc_request_t)r,
2088 : "AS-REQ is required for server");
2089 0 : return KRB5KDC_ERR_POLICY;
2090 : }
2091 :
2092 97205 : if (server->valid_start && *server->valid_start > kdc_time) {
2093 0 : char starttime_str[100];
2094 0 : krb5_format_time(r->context, *server->valid_start,
2095 : starttime_str, sizeof(starttime_str), TRUE);
2096 0 : kdc_audit_addreason((kdc_request_t)r, "Server not yet valid "
2097 : "until %s", starttime_str);
2098 0 : return KRB5KDC_ERR_SERVICE_NOTYET;
2099 : }
2100 :
2101 97205 : if (server->valid_end && *server->valid_end < kdc_time) {
2102 0 : char endtime_str[100];
2103 0 : krb5_format_time(r->context, *server->valid_end,
2104 : endtime_str, sizeof(endtime_str), TRUE);
2105 0 : kdc_audit_addreason((kdc_request_t)r, "Server expired at %s",
2106 : endtime_str);
2107 0 : return KRB5KDC_ERR_SERVICE_EXP;
2108 : }
2109 :
2110 97205 : if (server->pw_end && *server->pw_end < kdc_time) {
2111 0 : char pwend_str[100];
2112 0 : krb5_format_time(r->context, *server->pw_end,
2113 : pwend_str, sizeof(pwend_str), TRUE);
2114 0 : kdc_audit_addreason((kdc_request_t)r, "Server's key has expired "
2115 : "at %s", pwend_str);
2116 0 : return KRB5KDC_ERR_KEY_EXPIRED;
2117 : }
2118 : }
2119 94612 : return 0;
2120 : }
2121 :
2122 : /*
2123 : * Return TRUE if `from' is part of `addresses' taking into consideration
2124 : * the configuration variables that tells us how strict we should be about
2125 : * these checks
2126 : */
2127 :
2128 : krb5_boolean
2129 77901 : _kdc_check_addresses(astgs_request_t r, HostAddresses *addresses,
2130 : const struct sockaddr *from)
2131 : {
2132 77901 : krb5_kdc_configuration *config = r->config;
2133 2828 : krb5_error_code ret;
2134 2828 : krb5_address addr;
2135 2828 : krb5_boolean result;
2136 77901 : krb5_boolean only_netbios = TRUE;
2137 2828 : size_t i;
2138 :
2139 77901 : if (!config->check_ticket_addresses && !config->warn_ticket_addresses)
2140 0 : return TRUE;
2141 :
2142 : /*
2143 : * Fields of HostAddresses type are always OPTIONAL and should be non-
2144 : * empty, but we check for empty just in case as our compiler doesn't
2145 : * support size constraints on SEQUENCE OF.
2146 : */
2147 77901 : if (addresses == NULL || addresses->len == 0)
2148 77783 : return config->allow_null_ticket_addresses;
2149 :
2150 236 : for (i = 0; i < addresses->len; ++i) {
2151 118 : if (addresses->val[i].addr_type != KRB5_ADDRESS_NETBIOS) {
2152 0 : only_netbios = FALSE;
2153 : }
2154 : }
2155 :
2156 : /* Windows sends it's netbios name, which I can only assume is
2157 : * used for the 'allowed workstations' check. This is painful,
2158 : * but we still want to check IP addresses if they happen to be
2159 : * present.
2160 : */
2161 :
2162 118 : if(only_netbios)
2163 118 : return config->allow_null_ticket_addresses;
2164 :
2165 0 : ret = krb5_sockaddr2address (r->context, from, &addr);
2166 0 : if(ret)
2167 0 : return FALSE;
2168 :
2169 0 : result = krb5_address_search(r->context, &addr, addresses);
2170 0 : krb5_free_address (r->context, &addr);
2171 0 : return result;
2172 : }
2173 :
2174 : /*
2175 : *
2176 : */
2177 : krb5_error_code
2178 0 : _kdc_check_anon_policy(astgs_request_t r)
2179 : {
2180 0 : if (!r->config->allow_anonymous) {
2181 0 : kdc_audit_addreason((kdc_request_t)r,
2182 : "Anonymous tickets denied by local policy");
2183 0 : return KRB5KDC_ERR_POLICY;
2184 : }
2185 :
2186 0 : return 0;
2187 : }
2188 :
2189 : /*
2190 : * Determine whether the client requested a PAC be included
2191 : * or excluded explictly, or whether it doesn't care.
2192 : */
2193 :
2194 : static uint64_t
2195 29726 : get_pac_attributes(krb5_context context, KDC_REQ *req)
2196 : {
2197 1170 : krb5_error_code ret;
2198 1170 : PA_PAC_REQUEST pacreq;
2199 1170 : const PA_DATA *pa;
2200 29726 : int i = 0;
2201 1170 : uint32_t pac_attributes;
2202 :
2203 29726 : pa = _kdc_find_padata(req, &i, KRB5_PADATA_PA_PAC_REQUEST);
2204 29726 : if (pa == NULL)
2205 27837 : return KRB5_PAC_WAS_GIVEN_IMPLICITLY;
2206 :
2207 719 : ret = decode_PA_PAC_REQUEST(pa->padata_value.data,
2208 719 : pa->padata_value.length,
2209 : &pacreq,
2210 : NULL);
2211 719 : if (ret)
2212 0 : return KRB5_PAC_WAS_GIVEN_IMPLICITLY;
2213 :
2214 719 : pac_attributes = pacreq.include_pac ? KRB5_PAC_WAS_REQUESTED : 0;
2215 719 : free_PA_PAC_REQUEST(&pacreq);
2216 719 : return pac_attributes;
2217 : }
2218 :
2219 : /*
2220 : *
2221 : */
2222 :
2223 : static krb5_error_code
2224 29726 : generate_pac(astgs_request_t r, const Key *skey, const Key *tkey,
2225 : krb5_boolean is_tgs)
2226 : {
2227 1170 : krb5_error_code ret;
2228 1170 : krb5_data data;
2229 1170 : uint16_t rodc_id;
2230 1170 : krb5_principal client;
2231 29726 : krb5_const_principal canon_princ = NULL;
2232 :
2233 29726 : r->pac_attributes = get_pac_attributes(r->context, &r->req);
2234 29726 : kdc_audit_setkv_number((kdc_request_t)r, "pac_attributes",
2235 28556 : r->pac_attributes);
2236 :
2237 29726 : if (!is_tgs && !(r->pac_attributes & (KRB5_PAC_WAS_REQUESTED | KRB5_PAC_WAS_GIVEN_IMPLICITLY)))
2238 1 : return 0;
2239 :
2240 : /*
2241 : * When a PA mech does not use the client's long-term key, the PAC
2242 : * may include the client's long-term key (encrypted in the reply key)
2243 : * for use by other shared secret authentication protocols, e.g. NTLM.
2244 : * Validate a PA mech was actually used before doing this.
2245 : */
2246 :
2247 29725 : ret = _kdc_pac_generate(r,
2248 : r->client,
2249 : r->server,
2250 29725 : r->pa_used && !pa_used_flag_isset(r, PA_USES_LONG_TERM_KEY)
2251 : ? &r->reply_key : NULL,
2252 : r->pac_attributes,
2253 : &r->pac);
2254 29725 : if (ret) {
2255 0 : _kdc_r_log(r, 4, "PAC generation failed for -- %s",
2256 : r->cname);
2257 0 : return ret;
2258 : }
2259 29725 : if (r->pac == NULL)
2260 0 : return 0;
2261 :
2262 29725 : rodc_id = r->server->kvno >> 16;
2263 :
2264 : /* libkrb5 expects ticket and PAC client names to match */
2265 29725 : ret = _krb5_principalname2krb5_principal(r->context, &client,
2266 : r->et.cname, r->et.crealm);
2267 29725 : if (ret)
2268 0 : return ret;
2269 :
2270 : /*
2271 : * Include the canonical name of the principal in the authorization
2272 : * data, if the realms match (if they don't, then the KDC could
2273 : * impersonate any realm. Windows always canonicalizes the realm,
2274 : * but Heimdal permits aliases between realms.)
2275 : */
2276 29725 : if (krb5_realm_compare(r->context, client, r->canon_client_princ)) {
2277 29725 : char *cpn = NULL;
2278 :
2279 29725 : canon_princ = r->canon_client_princ;
2280 :
2281 29725 : (void) krb5_unparse_name(r->context, canon_princ, &cpn);
2282 29725 : kdc_audit_addkv((kdc_request_t)r, 0, "canon_client_name", "%s",
2283 29725 : cpn ? cpn : "<unknown>");
2284 29725 : krb5_xfree(cpn);
2285 : }
2286 :
2287 29725 : if (r->pa_used && r->pa_used->finalize_pac) {
2288 0 : ret = r->pa_used->finalize_pac(r);
2289 0 : if (ret)
2290 0 : return ret;
2291 : }
2292 :
2293 29725 : ret = _krb5_pac_sign(r->context,
2294 : r->pac,
2295 : r->et.authtime,
2296 : client,
2297 29725 : &skey->key, /* Server key */
2298 29725 : &tkey->key, /* TGS key */
2299 : rodc_id,
2300 : NULL, /* UPN */
2301 : canon_princ,
2302 : FALSE, /* add_full_sig */
2303 : is_tgs ? &r->pac_attributes : NULL,
2304 : &data);
2305 29725 : krb5_free_principal(r->context, client);
2306 29725 : krb5_pac_free(r->context, r->pac);
2307 29725 : r->pac = NULL;
2308 29725 : if (ret) {
2309 0 : _kdc_r_log(r, 4, "PAC signing failed for -- %s",
2310 : r->cname);
2311 0 : return ret;
2312 : }
2313 :
2314 29725 : ret = _kdc_tkt_insert_pac(r->context, &r->et, &data);
2315 29725 : krb5_data_free(&data);
2316 :
2317 29725 : return ret;
2318 : }
2319 :
2320 : /*
2321 : *
2322 : */
2323 :
2324 : krb5_boolean
2325 124195 : _kdc_is_anonymous(krb5_context context, krb5_const_principal principal)
2326 : {
2327 124195 : return krb5_principal_is_anonymous(context, principal, KRB5_ANON_MATCH_ANY);
2328 : }
2329 :
2330 : /*
2331 : * Returns TRUE if principal is the unauthenticated anonymous identity,
2332 : * i.e. WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS. Unfortunately due to
2333 : * backwards compatibility logic in krb5_principal_is_anonymous() we
2334 : * have to use our own implementation.
2335 : */
2336 :
2337 : krb5_boolean
2338 43531 : _kdc_is_anonymous_pkinit(krb5_context context, krb5_const_principal principal)
2339 : {
2340 43531 : return _kdc_is_anonymous(context, principal) &&
2341 0 : strcmp(principal->realm, KRB5_ANON_REALM) == 0;
2342 : }
2343 :
2344 : static int
2345 17773 : require_preauth_p(astgs_request_t r)
2346 : {
2347 17773 : return r->config->require_preauth
2348 0 : || r->client->flags.require_preauth
2349 17188 : || r->server->flags.require_preauth;
2350 : }
2351 :
2352 :
2353 : /*
2354 : *
2355 : */
2356 :
2357 : static krb5_error_code
2358 26219 : add_enc_pa_rep(astgs_request_t r)
2359 : {
2360 1170 : krb5_error_code ret;
2361 1170 : krb5_crypto crypto;
2362 1170 : Checksum checksum;
2363 1170 : krb5_data cdata;
2364 1170 : size_t len;
2365 :
2366 26219 : ret = krb5_crypto_init(r->context, &r->reply_key, 0, &crypto);
2367 26219 : if (ret)
2368 0 : return ret;
2369 :
2370 26219 : ret = krb5_create_checksum(r->context, crypto,
2371 : KRB5_KU_AS_REQ, 0,
2372 : r->request.data, r->request.length,
2373 : &checksum);
2374 26219 : krb5_crypto_destroy(r->context, crypto);
2375 26219 : if (ret)
2376 0 : return ret;
2377 :
2378 26219 : ASN1_MALLOC_ENCODE(Checksum, cdata.data, cdata.length,
2379 : &checksum, &len, ret);
2380 26219 : free_Checksum(&checksum);
2381 26219 : if (ret)
2382 0 : return ret;
2383 26219 : heim_assert(cdata.length == len, "ASN.1 internal error");
2384 :
2385 26219 : if (r->ek.encrypted_pa_data == NULL) {
2386 26219 : ALLOC(r->ek.encrypted_pa_data);
2387 26219 : if (r->ek.encrypted_pa_data == NULL)
2388 0 : return ENOMEM;
2389 : }
2390 26219 : ret = krb5_padata_add(r->context, r->ek.encrypted_pa_data,
2391 : KRB5_PADATA_REQ_ENC_PA_REP, cdata.data, cdata.length);
2392 26219 : if (ret)
2393 0 : return ret;
2394 :
2395 26219 : if (!r->config->enable_fast)
2396 915 : return 0;
2397 :
2398 25304 : return krb5_padata_add(r->context, r->ek.encrypted_pa_data,
2399 : KRB5_PADATA_FX_FAST, NULL, 0);
2400 : }
2401 :
2402 : /*
2403 : * Add an authorization data element indicating that a synthetic
2404 : * principal was used, so that the TGS does not accidentally
2405 : * synthesize a non-synthetic principal that has since been deleted.
2406 : */
2407 : static krb5_error_code
2408 0 : add_synthetic_princ_ad(astgs_request_t r)
2409 : {
2410 0 : krb5_data data;
2411 :
2412 0 : krb5_data_zero(&data);
2413 :
2414 0 : return _kdc_tkt_add_if_relevant_ad(r->context, &r->et,
2415 : KRB5_AUTHDATA_SYNTHETIC_PRINC_USED,
2416 : &data);
2417 : }
2418 :
2419 : static krb5_error_code
2420 5102 : get_local_tgs(krb5_context context,
2421 : krb5_kdc_configuration *config,
2422 : krb5_const_realm realm,
2423 : HDB **krbtgtdb,
2424 : hdb_entry **krbtgt)
2425 : {
2426 0 : krb5_error_code ret;
2427 0 : krb5_principal tgs_name;
2428 :
2429 5102 : *krbtgtdb = NULL;
2430 5102 : *krbtgt = NULL;
2431 :
2432 5102 : ret = krb5_make_principal(context,
2433 : &tgs_name,
2434 : realm,
2435 : KRB5_TGS_NAME,
2436 : realm,
2437 : NULL);
2438 5102 : if (ret == 0)
2439 5102 : ret = _kdc_db_fetch(context, config, tgs_name,
2440 : HDB_F_GET_KRBTGT, NULL, krbtgtdb, krbtgt);
2441 :
2442 5102 : krb5_free_principal(context, tgs_name);
2443 5102 : return ret;
2444 : }
2445 :
2446 : /*
2447 : *
2448 : */
2449 :
2450 : krb5_error_code
2451 50836 : _kdc_as_rep(astgs_request_t r)
2452 : {
2453 50836 : krb5_kdc_configuration *config = r->config;
2454 50836 : KDC_REQ *req = &r->req;
2455 50836 : const char *from = r->from;
2456 50836 : KDC_REQ_BODY *b = NULL;
2457 50836 : KDC_REP *rep = &r->rep;
2458 1755 : KDCOptions f;
2459 1755 : krb5_enctype setype;
2460 50836 : krb5_error_code ret = 0;
2461 1755 : Key *skey;
2462 50836 : int found_pa = 0;
2463 50836 : int i, flags = HDB_F_FOR_AS_REQ;
2464 1755 : const PA_DATA *pa;
2465 1755 : krb5_boolean is_tgs;
2466 1755 : const char *msg;
2467 1755 : Key *krbtgt_key;
2468 1755 : unsigned krbtgt_kvno;
2469 :
2470 50836 : memset(rep, 0, sizeof(*rep));
2471 :
2472 50836 : ALLOC(rep->padata);
2473 50836 : if (rep->padata == NULL) {
2474 0 : ret = ENOMEM;
2475 0 : krb5_set_error_message(r->context, ret, N_("malloc: out of memory", ""));
2476 0 : goto out;
2477 : }
2478 :
2479 : /*
2480 : * Look for FAST armor and unwrap
2481 : */
2482 50836 : ret = _kdc_fast_unwrap_request(r, NULL, NULL);
2483 50836 : if (ret) {
2484 8 : _kdc_r_log(r, 1, "FAST unwrap request from %s failed: %d", from, ret);
2485 8 : goto out;
2486 : }
2487 :
2488 : /* Validate armor TGT, and initialize the armor client and PAC */
2489 50828 : if (r->armor_ticket) {
2490 462 : ret = _kdc_fast_check_armor_pac(r, HDB_F_FOR_AS_REQ);
2491 462 : if (ret)
2492 4 : goto out;
2493 : }
2494 :
2495 50824 : b = &req->req_body;
2496 50824 : f = b->kdc_options;
2497 :
2498 50824 : if (f.canonicalize)
2499 47063 : flags |= HDB_F_CANON;
2500 :
2501 50824 : if (b->sname == NULL) {
2502 3 : ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
2503 3 : _kdc_set_e_text(r, "No server in request");
2504 3 : goto out;
2505 : }
2506 :
2507 50821 : ret = _krb5_principalname2krb5_principal(r->context, &r->server_princ,
2508 49066 : *(b->sname), b->realm);
2509 50821 : if (!ret)
2510 50821 : ret = krb5_unparse_name(r->context, r->server_princ, &r->sname);
2511 50821 : if (ret) {
2512 0 : kdc_log(r->context, config, 2,
2513 : "AS_REQ malformed server name from %s", from);
2514 0 : goto out;
2515 : }
2516 :
2517 50821 : if (b->cname == NULL) {
2518 0 : ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
2519 0 : _kdc_set_e_text(r, "No client in request");
2520 0 : goto out;
2521 : }
2522 :
2523 50821 : ret = _krb5_principalname2krb5_principal(r->context, &r->client_princ,
2524 49066 : *(b->cname), b->realm);
2525 50821 : if (!ret)
2526 50821 : ret = krb5_unparse_name(r->context, r->client_princ, &r->cname);
2527 50821 : if (ret) {
2528 0 : kdc_log(r->context, config, 2,
2529 : "AS-REQ malformed client name from %s", from);
2530 0 : goto out;
2531 : }
2532 :
2533 50821 : kdc_log(r->context, config, 4, "AS-REQ %s from %s for %s",
2534 : r->cname, r->from, r->sname);
2535 :
2536 50821 : is_tgs = krb5_principal_is_krbtgt(r->context, r->server_princ);
2537 :
2538 50925 : if (_kdc_is_anonymous(r->context, r->client_princ) &&
2539 104 : !_kdc_is_anon_request(req)) {
2540 0 : kdc_log(r->context, config, 2, "Anonymous client w/o anonymous flag");
2541 0 : ret = KRB5KDC_ERR_BADOPTION;
2542 0 : goto out;
2543 : }
2544 :
2545 52576 : ret = _kdc_db_fetch(r->context, config, r->client_princ,
2546 50821 : HDB_F_GET_CLIENT | HDB_F_SYNTHETIC_OK | flags, NULL,
2547 : &r->clientdb, &r->client);
2548 50821 : switch (ret) {
2549 46704 : case 0: /* Success */
2550 48459 : break;
2551 1627 : case HDB_ERR_NOT_FOUND_HERE:
2552 1627 : kdc_log(r->context, config, 5, "client %s does not have secrets at this KDC, need to proxy",
2553 : r->cname);
2554 1627 : goto out;
2555 286 : case HDB_ERR_WRONG_REALM: {
2556 286 : char *fixed_client_name = NULL;
2557 :
2558 286 : ret = krb5_unparse_name(r->context, r->client->principal,
2559 : &fixed_client_name);
2560 286 : if (ret) {
2561 0 : goto out;
2562 : }
2563 :
2564 286 : kdc_log(r->context, config, 4, "WRONG_REALM - %s -> %s",
2565 : r->cname, fixed_client_name);
2566 286 : free(fixed_client_name);
2567 :
2568 286 : r->e_text = NULL;
2569 286 : ret = _kdc_fast_mk_error(r, r->rep.padata, r->armor_crypto,
2570 286 : &req->req_body,
2571 286 : r->error_code = KRB5_KDC_ERR_WRONG_REALM,
2572 286 : r->client->principal, r->server_princ,
2573 286 : NULL, NULL, r->reply);
2574 286 : goto out;
2575 : }
2576 449 : default:
2577 : {
2578 449 : msg = krb5_get_error_message(r->context, ret);
2579 449 : kdc_log(r->context, config, 4, "UNKNOWN -- %s: %s", r->cname, msg);
2580 449 : krb5_free_error_message(r->context, msg);
2581 449 : ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
2582 449 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
2583 : KDC_AUTH_EVENT_CLIENT_UNKNOWN);
2584 449 : goto out;
2585 : }
2586 : }
2587 :
2588 48459 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
2589 : KDC_AUTH_EVENT_CLIENT_FOUND);
2590 :
2591 98673 : ret = _kdc_db_fetch(r->context, config, r->server_princ,
2592 48459 : HDB_F_GET_SERVER | HDB_F_DELAY_NEW_KEYS |
2593 48459 : flags | (is_tgs ? HDB_F_GET_KRBTGT : 0),
2594 : NULL, &r->serverdb, &r->server);
2595 48459 : switch (ret) {
2596 46702 : case 0: /* Success */
2597 48457 : break;
2598 0 : case HDB_ERR_NOT_FOUND_HERE:
2599 0 : kdc_log(r->context, config, 5, "target %s does not have secrets at this KDC, need to proxy",
2600 : r->sname);
2601 0 : goto out;
2602 2 : default:
2603 2 : msg = krb5_get_error_message(r->context, ret);
2604 2 : kdc_log(r->context, config, 4, "UNKNOWN -- %s: %s", r->sname, msg);
2605 2 : krb5_free_error_message(r->context, msg);
2606 2 : ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
2607 2 : goto out;
2608 : }
2609 :
2610 48457 : ret = _kdc_check_access(r);
2611 48457 : if(ret)
2612 302 : goto out;
2613 :
2614 : /*
2615 : * This has to be here (not later), because we need to have r->sessionetype
2616 : * set prior to calling pa_pkinit_validate(), which in turn calls
2617 : * _kdc_pk_mk_pa_reply(), during padata validation.
2618 : */
2619 :
2620 : /*
2621 : * Select an enctype for the to-be-issued ticket's session key using the
2622 : * intersection of the client's requested enctypes and the server's (like a
2623 : * root krbtgt, but not necessarily) etypes from its HDB entry.
2624 : */
2625 49910 : ret = _kdc_find_session_etype(r, b->etype.val, b->etype.len,
2626 48155 : r->server, &r->sessionetype);
2627 48155 : if (ret) {
2628 170 : kdc_log(r->context, config, 4,
2629 : "Client (%s) from %s has no common enctypes with KDC "
2630 : "to use for the session key",
2631 : r->cname, from);
2632 170 : goto out;
2633 : }
2634 :
2635 : /*
2636 : * Select the best encryption type for the KDC without regard to
2637 : * the client since the client never needs to read that data.
2638 : */
2639 :
2640 49740 : ret = _kdc_get_preferred_key(r->context, config,
2641 47985 : r->server, r->sname,
2642 : &setype, &skey);
2643 47985 : if(ret)
2644 138 : goto out;
2645 :
2646 : /* If server is not krbtgt, fetch local krbtgt key for signing authdata */
2647 47847 : if (is_tgs) {
2648 42745 : krbtgt_key = skey;
2649 42745 : krbtgt_kvno = r->server->kvno;
2650 : } else {
2651 5102 : ret = get_local_tgs(r->context, config, r->server_princ->realm,
2652 : &r->krbtgtdb, &r->krbtgt);
2653 5102 : if (ret)
2654 0 : goto out;
2655 :
2656 5102 : ret = _kdc_get_preferred_key(r->context, config, r->krbtgt,
2657 5102 : r->server_princ->realm,
2658 : NULL, &krbtgt_key);
2659 5102 : if (ret)
2660 0 : goto out;
2661 :
2662 5102 : krbtgt_kvno = r->server->kvno;
2663 : }
2664 :
2665 : /*
2666 : * Pre-auth processing
2667 : */
2668 :
2669 47847 : if(req->padata){
2670 1755 : unsigned int n;
2671 :
2672 45059 : log_patypes(r, req->padata);
2673 :
2674 : /* Check if preauth matching */
2675 :
2676 361612 : for (n = 0; !found_pa && n < sizeof(pat) / sizeof(pat[0]); n++) {
2677 315141 : if (pat[n].validate == NULL)
2678 149944 : continue;
2679 165197 : if (r->armor_crypto == NULL && (pat[n].flags & PA_REQ_FAST))
2680 14951 : continue;
2681 150246 : if (!r->config->enable_fast_cookie && (pat[n].flags & PA_USES_FAST_COOKIE))
2682 14985 : continue;
2683 :
2684 135261 : kdc_log(r->context, config, 5,
2685 135261 : "Looking for %s pa-data -- %s", pat[n].name, r->cname);
2686 135261 : i = 0;
2687 135261 : pa = _kdc_find_padata(req, &i, pat[n].type);
2688 135261 : if (pa) {
2689 30074 : if (r->client->flags.synthetic &&
2690 0 : !(pat[n].flags & PA_SYNTHETIC_OK)) {
2691 0 : kdc_log(r->context, config, 4, "UNKNOWN -- %s", r->cname);
2692 0 : ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
2693 0 : goto out;
2694 : }
2695 30074 : kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_VIS, "pa", "%s",
2696 28904 : pat[n].name);
2697 30074 : ret = pat[n].validate(r, pa);
2698 30074 : if (ret != 0) {
2699 0 : krb5_error_code ret2;
2700 343 : Key *ckey = NULL;
2701 0 : krb5_boolean default_salt;
2702 :
2703 686 : if (ret != KRB5_KDC_ERR_MORE_PREAUTH_DATA_REQUIRED &&
2704 343 : !kdc_audit_getkv((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT))
2705 0 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
2706 : KDC_AUTH_EVENT_PREAUTH_FAILED);
2707 :
2708 : /*
2709 : * If there is a client key, send ETYPE_INFO{,2}
2710 : */
2711 343 : if (!r->client->flags.locked_out) {
2712 343 : ret2 = _kdc_find_etype(r, KFE_IS_PREAUTH|KFE_USE_CLIENT,
2713 343 : b->etype.val, b->etype.len,
2714 : NULL, &ckey, &default_salt);
2715 343 : if (ret2 == 0) {
2716 341 : ret2 = get_pa_etype_info_both(r->context, config, &b->etype,
2717 : r->rep.padata, ckey, !default_salt);
2718 341 : if (ret2 != 0)
2719 0 : ret = ret2;
2720 : }
2721 : }
2722 343 : goto out;
2723 : }
2724 29731 : if (!kdc_audit_getkv((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT))
2725 0 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
2726 : KDC_AUTH_EVENT_PREAUTH_SUCCEEDED);
2727 29731 : kdc_log(r->context, config, 4,
2728 : "%s pre-authentication succeeded -- %s",
2729 28561 : pat[n].name, r->cname);
2730 29731 : found_pa = 1;
2731 29731 : r->pa_used = &pat[n];
2732 29731 : r->et.flags.pre_authent = 1;
2733 : }
2734 : }
2735 : }
2736 :
2737 47504 : if (found_pa == 0) {
2738 17773 : Key *ckey = NULL;
2739 585 : size_t n;
2740 585 : krb5_boolean default_salt;
2741 :
2742 17773 : if (r->client->flags.synthetic) {
2743 0 : kdc_log(r->context, config, 4, "UNKNOWN -- %s", r->cname);
2744 0 : ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
2745 17188 : goto out;
2746 : }
2747 :
2748 213276 : for (n = 0; n < sizeof(pat) / sizeof(pat[0]); n++) {
2749 195503 : if ((pat[n].flags & PA_ANNOUNCE) == 0)
2750 71092 : continue;
2751 :
2752 124411 : if (!r->armor_crypto && (pat[n].flags & PA_REQ_FAST))
2753 17739 : continue;
2754 106672 : if (pat[n].type == KRB5_PADATA_PKINIT_KX && !r->config->allow_anonymous)
2755 17773 : continue;
2756 88899 : if (pat[n].type == KRB5_PADATA_ENC_TIMESTAMP) {
2757 17773 : if (r->armor_crypto && !r->config->enable_armored_pa_enc_timestamp)
2758 34 : continue;
2759 17739 : if (!r->armor_crypto && !r->config->enable_unarmored_pa_enc_timestamp)
2760 0 : continue;
2761 : }
2762 88865 : if (pat[n].type == KRB5_PADATA_FX_FAST && !r->config->enable_fast)
2763 758 : continue;
2764 88107 : if (pat[n].type == KRB5_PADATA_GSS && !r->config->enable_gss_preauth)
2765 17773 : continue;
2766 70334 : if (!r->config->enable_fast_cookie && (pat[n].flags & PA_USES_FAST_COOKIE))
2767 0 : continue;
2768 :
2769 70334 : ret = krb5_padata_add(r->context, r->rep.padata,
2770 67994 : pat[n].type, NULL, 0);
2771 70334 : if (ret)
2772 0 : goto out;
2773 : }
2774 :
2775 : /*
2776 : * If there is a client key, send ETYPE_INFO{,2}
2777 : */
2778 18358 : ret = _kdc_find_etype(r, KFE_IS_PREAUTH|KFE_USE_CLIENT,
2779 17773 : b->etype.val, b->etype.len,
2780 : NULL, &ckey, &default_salt);
2781 17773 : if (ret == 0) {
2782 17773 : ret = get_pa_etype_info_both(r->context, config, &b->etype,
2783 : r->rep.padata, ckey, !default_salt);
2784 17773 : if (ret)
2785 0 : goto out;
2786 : }
2787 :
2788 : /*
2789 : * If the client indicated support for PKINIT Freshness, send back a
2790 : * freshness token.
2791 : */
2792 17773 : ret = send_freshness_token(r, krbtgt_key, krbtgt_kvno);
2793 17773 : if (ret)
2794 0 : goto out;
2795 :
2796 : /*
2797 : * send requre preauth is its required or anon is requested,
2798 : * anon is today only allowed via preauth mechanisms.
2799 : */
2800 17773 : if (require_preauth_p(r) || _kdc_is_anon_request(&r->req)) {
2801 17773 : ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
2802 17773 : _kdc_set_e_text(r, "Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ");
2803 17773 : goto out;
2804 : }
2805 :
2806 0 : if (ckey == NULL) {
2807 0 : ret = KRB5KDC_ERR_CLIENT_NOTYET;
2808 0 : _kdc_set_e_text(r, "Doesn't have a client key available");
2809 0 : goto out;
2810 : }
2811 0 : krb5_free_keyblock_contents(r->context, &r->reply_key);
2812 0 : ret = krb5_copy_keyblock_contents(r->context, &ckey->key, &r->reply_key);
2813 0 : if (ret)
2814 0 : goto out;
2815 : }
2816 :
2817 29731 : r->canon_client_princ = r->client->principal;
2818 :
2819 29731 : if (_kdc_is_anon_request(&r->req)) {
2820 0 : ret = _kdc_check_anon_policy(r);
2821 0 : if (ret) {
2822 0 : _kdc_set_e_text(r, "Anonymous ticket requests are disabled");
2823 0 : goto out;
2824 : }
2825 :
2826 0 : r->et.flags.anonymous = 1;
2827 : }
2828 :
2829 29731 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
2830 : KDC_AUTH_EVENT_CLIENT_AUTHORIZED);
2831 :
2832 29731 : if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey) {
2833 0 : ret = KRB5KDC_ERR_BADOPTION;
2834 0 : _kdc_set_e_text(r, "Bad KDC options");
2835 0 : goto out;
2836 : }
2837 :
2838 : /*
2839 : * Build reply
2840 : */
2841 29731 : rep->pvno = 5;
2842 29731 : rep->msg_type = krb_as_rep;
2843 :
2844 59462 : if (!config->historical_anon_realm &&
2845 29731 : _kdc_is_anonymous(r->context, r->client_princ)) {
2846 0 : Realm anon_realm = KRB5_ANON_REALM;
2847 0 : ret = copy_Realm(&anon_realm, &rep->crealm);
2848 29731 : } else if (f.canonicalize || r->client->flags.force_canonicalize)
2849 29731 : ret = copy_Realm(&r->canon_client_princ->realm, &rep->crealm);
2850 : else
2851 0 : ret = copy_Realm(&r->client_princ->realm, &rep->crealm);
2852 29731 : if (ret)
2853 0 : goto out;
2854 29731 : if (r->et.flags.anonymous)
2855 0 : ret = _kdc_make_anonymous_principalname(&rep->cname);
2856 29731 : else if (f.canonicalize || r->client->flags.force_canonicalize)
2857 29731 : ret = _krb5_principal2principalname(&rep->cname, r->canon_client_princ);
2858 : else
2859 0 : ret = _krb5_principal2principalname(&rep->cname, r->client_princ);
2860 29731 : if (ret)
2861 0 : goto out;
2862 :
2863 29731 : rep->ticket.tkt_vno = 5;
2864 29731 : if (f.canonicalize || r->server->flags.force_canonicalize)
2865 29725 : ret = copy_Realm(&r->server->principal->realm, &rep->ticket.realm);
2866 : else
2867 6 : ret = copy_Realm(&r->server_princ->realm, &rep->ticket.realm);
2868 29731 : if (ret)
2869 0 : goto out;
2870 29731 : if (f.canonicalize || r->server->flags.force_canonicalize)
2871 29725 : _krb5_principal2principalname(&rep->ticket.sname,
2872 29725 : r->server->principal);
2873 : else
2874 6 : _krb5_principal2principalname(&rep->ticket.sname,
2875 6 : r->server_princ);
2876 : /* java 1.6 expects the name to be the same type, lets allow that
2877 : * uncomplicated name-types, when f.canonicalize is not set (to
2878 : * match Windows Server 1709). */
2879 : #define CNT(sp,t) (((sp)->sname->name_type) == KRB5_NT_##t)
2880 29731 : if (!f.canonicalize
2881 1423 : && (CNT(b, UNKNOWN) || CNT(b, PRINCIPAL) || CNT(b, SRV_INST) || CNT(b, SRV_HST) || CNT(b, SRV_XHST))) {
2882 1391 : rep->ticket.sname.name_type = b->sname->name_type;
2883 : }
2884 : #undef CNT
2885 :
2886 29731 : r->et.flags.initial = 1;
2887 29731 : if(r->client->flags.forwardable && r->server->flags.forwardable)
2888 29698 : r->et.flags.forwardable = f.forwardable;
2889 29731 : if(r->client->flags.proxiable && r->server->flags.proxiable)
2890 29692 : r->et.flags.proxiable = f.proxiable;
2891 39 : else if (f.proxiable) {
2892 4 : _kdc_set_e_text(r, "Ticket may not be proxiable");
2893 4 : ret = KRB5KDC_ERR_POLICY;
2894 4 : goto out;
2895 : }
2896 29727 : if(r->client->flags.postdate && r->server->flags.postdate)
2897 0 : r->et.flags.may_postdate = f.allow_postdate;
2898 29727 : else if (f.allow_postdate){
2899 0 : _kdc_set_e_text(r, "Ticket may not be postdateable");
2900 0 : ret = KRB5KDC_ERR_POLICY;
2901 0 : goto out;
2902 : }
2903 :
2904 29727 : if (b->addresses)
2905 98 : kdc_audit_addaddrs((kdc_request_t)r, b->addresses, "reqaddrs");
2906 :
2907 : /* check for valid set of addresses */
2908 29727 : if (!_kdc_check_addresses(r, b->addresses, r->addr)) {
2909 0 : if (r->config->warn_ticket_addresses) {
2910 0 : kdc_audit_setkv_bool((kdc_request_t)r, "wrongaddr", TRUE);
2911 : } else {
2912 0 : _kdc_set_e_text(r, "Request from wrong address");
2913 0 : ret = KRB5KRB_AP_ERR_BADADDR;
2914 0 : goto out;
2915 : }
2916 : }
2917 :
2918 29727 : ret = copy_PrincipalName(&rep->cname, &r->et.cname);
2919 29727 : if (ret)
2920 0 : goto out;
2921 29727 : ret = copy_Realm(&rep->crealm, &r->et.crealm);
2922 29727 : if (ret)
2923 0 : goto out;
2924 :
2925 : {
2926 1170 : time_t start;
2927 1170 : time_t t;
2928 :
2929 29727 : start = r->et.authtime = kdc_time;
2930 :
2931 29727 : if(f.postdated && req->req_body.from){
2932 0 : ALLOC(r->et.starttime);
2933 0 : start = *r->et.starttime = *req->req_body.from;
2934 0 : r->et.flags.invalid = 1;
2935 0 : r->et.flags.postdated = 1; /* XXX ??? */
2936 : }
2937 29727 : _kdc_fix_time(&b->till);
2938 29727 : t = *b->till;
2939 :
2940 : /* be careful not to overflow */
2941 :
2942 : /*
2943 : * Pre-auth can override r->client->max_life if configured.
2944 : *
2945 : * See pre-auth methods, specifically PKINIT, which can get or derive
2946 : * this from the client's certificate.
2947 : */
2948 29727 : if (r->pa_max_life > 0)
2949 0 : t = rk_time_add(start, min(rk_time_sub(t, start), r->pa_max_life));
2950 29727 : else if (r->client->max_life)
2951 29727 : t = rk_time_add(start, min(rk_time_sub(t, start),
2952 : *r->client->max_life));
2953 :
2954 29727 : if (r->server->max_life)
2955 29721 : t = rk_time_add(start, min(rk_time_sub(t, start),
2956 : *r->server->max_life));
2957 :
2958 : /* Pre-auth can bound endtime as well */
2959 29727 : if (r->pa_endtime > 0)
2960 41 : t = rk_time_add(start, min(rk_time_sub(t, start), r->pa_endtime));
2961 : #if 0
2962 : t = min(t, rk_time_add(start, realm->max_life));
2963 : #endif
2964 29727 : r->et.endtime = t;
2965 :
2966 29727 : if (start > r->et.endtime) {
2967 1 : _kdc_set_e_text(r, "Requested effective lifetime is negative or too short");
2968 1 : ret = KRB5KDC_ERR_NEVER_VALID;
2969 1 : goto out;
2970 : }
2971 :
2972 29726 : if(f.renewable_ok && r->et.endtime < *b->till){
2973 2 : f.renewable = 1;
2974 2 : if(b->rtime == NULL){
2975 2 : ALLOC(b->rtime);
2976 2 : *b->rtime = 0;
2977 : }
2978 2 : if(*b->rtime < *b->till)
2979 2 : *b->rtime = *b->till;
2980 : }
2981 29726 : if(f.renewable && b->rtime){
2982 3607 : t = *b->rtime;
2983 3607 : if(t == 0)
2984 14 : t = MAX_TIME;
2985 3607 : if(r->client->max_renew)
2986 3607 : t = rk_time_add(start, min(rk_time_sub(t, start),
2987 : *r->client->max_renew));
2988 3607 : if(r->server->max_renew)
2989 3607 : t = rk_time_add(start, min(rk_time_sub(t, start),
2990 : *r->server->max_renew));
2991 : #if 0
2992 : t = min(t, rk_time_add(start, realm->max_renew));
2993 : #endif
2994 3607 : ALLOC(r->et.renew_till);
2995 3607 : *r->et.renew_till = t;
2996 3607 : r->et.flags.renewable = 1;
2997 : }
2998 : }
2999 :
3000 29726 : if(b->addresses){
3001 98 : ALLOC(r->et.caddr);
3002 98 : copy_HostAddresses(b->addresses, r->et.caddr);
3003 : }
3004 :
3005 29726 : r->et.transited.tr_type = domain_X500_Compress;
3006 29726 : krb5_data_zero(&r->et.transited.contents);
3007 :
3008 : /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
3009 : * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
3010 : * incapable of correctly decoding SEQUENCE OF's of zero length.
3011 : *
3012 : * To fix this, always send at least one no-op last_req
3013 : *
3014 : * If there's a pw_end or valid_end we will use that,
3015 : * otherwise just a dummy lr.
3016 : */
3017 29726 : r->ek.last_req.val = malloc(2 * sizeof(*r->ek.last_req.val));
3018 29726 : if (r->ek.last_req.val == NULL) {
3019 0 : ret = ENOMEM;
3020 0 : goto out;
3021 : }
3022 29726 : r->ek.last_req.len = 0;
3023 29726 : if (r->client->pw_end
3024 26255 : && (config->kdc_warn_pwexpire == 0
3025 0 : || kdc_time + config->kdc_warn_pwexpire >= *r->client->pw_end)) {
3026 26255 : r->ek.last_req.val[r->ek.last_req.len].lr_type = LR_PW_EXPTIME;
3027 26255 : r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->pw_end;
3028 26255 : ++r->ek.last_req.len;
3029 : }
3030 29726 : if (r->client->valid_end) {
3031 0 : r->ek.last_req.val[r->ek.last_req.len].lr_type = LR_ACCT_EXPTIME;
3032 0 : r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->valid_end;
3033 0 : ++r->ek.last_req.len;
3034 : }
3035 29726 : if (r->ek.last_req.len == 0) {
3036 3471 : r->ek.last_req.val[r->ek.last_req.len].lr_type = LR_NONE;
3037 3471 : r->ek.last_req.val[r->ek.last_req.len].lr_value = 0;
3038 3471 : ++r->ek.last_req.len;
3039 : }
3040 : /* Set the nonce if it’s not already set. */
3041 29726 : if (!r->ek.nonce) {
3042 29687 : r->ek.nonce = b->nonce;
3043 : }
3044 29726 : if (r->client->valid_end || r->client->pw_end) {
3045 26255 : ALLOC(r->ek.key_expiration);
3046 26255 : if (r->client->valid_end) {
3047 0 : if (r->client->pw_end)
3048 0 : *r->ek.key_expiration = min(*r->client->valid_end,
3049 : *r->client->pw_end);
3050 : else
3051 0 : *r->ek.key_expiration = *r->client->valid_end;
3052 : } else
3053 26255 : *r->ek.key_expiration = *r->client->pw_end;
3054 : } else
3055 3471 : r->ek.key_expiration = NULL;
3056 29726 : r->ek.flags = r->et.flags;
3057 29726 : r->ek.authtime = r->et.authtime;
3058 29726 : if (r->et.starttime) {
3059 0 : ALLOC(r->ek.starttime);
3060 0 : *r->ek.starttime = *r->et.starttime;
3061 : }
3062 29726 : r->ek.endtime = r->et.endtime;
3063 29726 : if (r->et.renew_till) {
3064 3607 : ALLOC(r->ek.renew_till);
3065 3607 : *r->ek.renew_till = *r->et.renew_till;
3066 : }
3067 29726 : ret = copy_Realm(&rep->ticket.realm, &r->ek.srealm);
3068 29726 : if (ret)
3069 0 : goto out;
3070 29726 : ret = copy_PrincipalName(&rep->ticket.sname, &r->ek.sname);
3071 29726 : if (ret)
3072 0 : goto out;
3073 29726 : if(r->et.caddr){
3074 98 : ALLOC(r->ek.caddr);
3075 98 : copy_HostAddresses(r->et.caddr, r->ek.caddr);
3076 : }
3077 :
3078 : /*
3079 : * Check session and reply keys
3080 : */
3081 :
3082 29726 : if (r->session_key.keytype == ETYPE_NULL) {
3083 29685 : ret = krb5_generate_random_keyblock(r->context, r->sessionetype, &r->session_key);
3084 29685 : if (ret)
3085 0 : goto out;
3086 : }
3087 :
3088 29726 : if (r->reply_key.keytype == ETYPE_NULL) {
3089 0 : _kdc_set_e_text(r, "Client has no reply key");
3090 0 : ret = KRB5KDC_ERR_CLIENT_NOTYET;
3091 0 : goto out;
3092 : }
3093 :
3094 29726 : ret = copy_EncryptionKey(&r->session_key, &r->et.key);
3095 29726 : if (ret)
3096 0 : goto out;
3097 :
3098 29726 : ret = copy_EncryptionKey(&r->session_key, &r->ek.key);
3099 29726 : if (ret)
3100 0 : goto out;
3101 :
3102 : /* Add the PAC */
3103 29726 : if (!r->et.flags.anonymous) {
3104 29726 : ret = generate_pac(r, skey, krbtgt_key, is_tgs);
3105 29726 : if (ret)
3106 0 : goto out;
3107 : }
3108 :
3109 29726 : if (r->client->flags.synthetic) {
3110 0 : ret = add_synthetic_princ_ad(r);
3111 0 : if (ret)
3112 0 : goto out;
3113 : }
3114 :
3115 29726 : _kdc_log_timestamp(r, "AS-REQ", r->et.authtime,
3116 : r->et.starttime, r->et.endtime,
3117 : r->et.renew_till);
3118 :
3119 29726 : _log_astgs_req(r, setype);
3120 :
3121 : /*
3122 : * We always say we support FAST/enc-pa-rep
3123 : */
3124 :
3125 29726 : r->et.flags.enc_pa_rep = r->ek.flags.enc_pa_rep = 1;
3126 :
3127 : /*
3128 : * update reply-key with strengthen-key
3129 : */
3130 :
3131 29726 : ret = _kdc_fast_strengthen_reply_key(r);
3132 29726 : if (ret)
3133 0 : goto out;
3134 :
3135 : /*
3136 : * Add REQ_ENC_PA_REP if client supports it
3137 : */
3138 :
3139 29726 : i = 0;
3140 29726 : pa = _kdc_find_padata(req, &i, KRB5_PADATA_REQ_ENC_PA_REP);
3141 29726 : if (pa) {
3142 :
3143 26219 : ret = add_enc_pa_rep(r);
3144 26219 : if (ret) {
3145 0 : msg = krb5_get_error_message(r->context, ret);
3146 0 : _kdc_r_log(r, 4, "add_enc_pa_rep failed: %s: %d", msg, ret);
3147 0 : krb5_free_error_message(r->context, msg);
3148 0 : goto out;
3149 : }
3150 : }
3151 :
3152 : /*
3153 : * Last chance for plugins to update reply
3154 : */
3155 29726 : ret = _kdc_finalize_reply(r);
3156 29726 : if (ret)
3157 0 : goto out;
3158 :
3159 : /*
3160 : * Don't send kvno from client entry if the pre-authentication
3161 : * mechanism replaced the reply key.
3162 : */
3163 :
3164 34406 : ret = _kdc_encode_reply(r->context, config,
3165 29726 : r, req->req_body.nonce, setype,
3166 29726 : r->server->kvno, &skey->key,
3167 29685 : pa_used_flag_isset(r, PA_REPLACE_REPLY_KEY) ? 0 : r->client->kvno,
3168 29726 : 0, r->reply);
3169 29726 : if (ret)
3170 0 : goto out;
3171 :
3172 : /*
3173 : * Check if message is too large
3174 : */
3175 29726 : if (r->datagram_reply && r->reply->length > config->max_datagram_reply_length) {
3176 12312 : krb5_data_free(r->reply);
3177 12312 : ret = KRB5KRB_ERR_RESPONSE_TOO_BIG;
3178 12312 : _kdc_set_e_text(r, "Reply packet too large");
3179 : }
3180 :
3181 17414 : out:
3182 50836 : if (ret) {
3183 : /* Overwrite ‘error_code’ only if we have an actual error. */
3184 33136 : r->error_code = ret;
3185 : }
3186 : {
3187 50836 : krb5_error_code ret2 = _kdc_audit_request(r);
3188 50836 : if (ret2) {
3189 21 : krb5_data_free(r->reply);
3190 21 : ret = ret2;
3191 : }
3192 : }
3193 :
3194 : /*
3195 : * In case of a non proxy error, build an error message.
3196 : */
3197 50836 : if (ret != 0 && ret != HDB_ERR_NOT_FOUND_HERE && r->reply->length == 0) {
3198 31489 : kdc_log(r->context, config, 5, "as-req: sending error: %d to client", ret);
3199 32659 : ret = _kdc_fast_mk_error(r,
3200 : r->rep.padata,
3201 : r->armor_crypto,
3202 31489 : &req->req_body,
3203 31489 : r->error_code ? r->error_code : ret,
3204 : r->client_princ,
3205 : r->server_princ,
3206 : NULL, NULL,
3207 31489 : r->reply);
3208 : }
3209 :
3210 50836 : if (r->pa_used && r->pa_used->cleanup)
3211 0 : r->pa_used->cleanup(r);
3212 :
3213 50836 : free_AS_REP(&r->rep);
3214 50836 : free_EncTicketPart(&r->et);
3215 50836 : free_EncKDCRepPart(&r->ek);
3216 50836 : _kdc_free_fast_state(&r->fast);
3217 :
3218 50836 : if (r->client_princ) {
3219 50821 : krb5_free_principal(r->context, r->client_princ);
3220 50821 : r->client_princ = NULL;
3221 : }
3222 50836 : if (r->server_princ){
3223 50821 : krb5_free_principal(r->context, r->server_princ);
3224 50821 : r->server_princ = NULL;
3225 : }
3226 50836 : if (r->client)
3227 48745 : _kdc_free_ent(r->context, r->clientdb, r->client);
3228 50836 : if (r->server)
3229 48457 : _kdc_free_ent(r->context, r->serverdb, r->server);
3230 50836 : if (r->krbtgt)
3231 5102 : _kdc_free_ent(r->context, r->krbtgtdb, r->krbtgt);
3232 50836 : if (r->armor_crypto) {
3233 463 : krb5_crypto_destroy(r->context, r->armor_crypto);
3234 463 : r->armor_crypto = NULL;
3235 : }
3236 50836 : if (r->armor_ticket)
3237 463 : krb5_free_ticket(r->context, r->armor_ticket);
3238 50836 : if (r->armor_server)
3239 463 : _kdc_free_ent(r->context, r->armor_serverdb, r->armor_server);
3240 50836 : krb5_free_keyblock_contents(r->context, &r->reply_key);
3241 50836 : krb5_free_keyblock_contents(r->context, &r->enc_ad_key);
3242 50836 : krb5_free_keyblock_contents(r->context, &r->session_key);
3243 50836 : krb5_free_keyblock_contents(r->context, &r->strengthen_key);
3244 50836 : krb5_pac_free(r->context, r->pac);
3245 :
3246 50836 : return ret;
3247 : }
|