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 56117 : _kdc_fix_time(time_t **t)
58 : {
59 56117 : if(*t == NULL){
60 0 : ALLOC(*t);
61 0 : **t = MAX_TIME;
62 : }
63 56117 : if(**t == 0) **t = MAX_TIME; /* fix for old clients */
64 56117 : }
65 :
66 : static int
67 28880 : realloc_method_data(METHOD_DATA *md)
68 : {
69 : PA_DATA *pa;
70 28880 : pa = realloc(md->val, (md->len + 1) * sizeof(*md->val));
71 28880 : if(pa == NULL)
72 0 : return ENOMEM;
73 28880 : md->val = pa;
74 28880 : md->len++;
75 28880 : 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 18413 : set_salt_padata(krb5_context context,
86 : krb5_kdc_configuration *config,
87 : METHOD_DATA *md, Key *key)
88 : {
89 18413 : if (!key->salt)
90 1139 : return 0;
91 :
92 17274 : return get_pa_etype_info2(context, config, md, key, TRUE);
93 : }
94 :
95 : const PA_DATA*
96 406032 : _kdc_find_padata(const KDC_REQ *req, int *start, int type)
97 : {
98 406032 : if (req->padata == NULL)
99 2678 : return NULL;
100 :
101 1191735 : while((size_t)*start < req->padata->len){
102 524739 : (*start)++;
103 524739 : if(req->padata->val[*start - 1].padata_type == (unsigned)type)
104 139712 : return &req->padata->val[*start - 1];
105 : }
106 263642 : 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 11606 : is_default_salt_p(const krb5_salt *default_salt, const Key *key)
133 : {
134 11606 : if (key->salt == NULL)
135 905 : return TRUE;
136 10701 : if (default_salt->salttype != key->salt->type)
137 0 : return FALSE;
138 10701 : if (krb5_data_cmp(&default_salt->saltvalue, &key->salt->salt) != 0)
139 3043 : return FALSE;
140 7658 : 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 11606 : is_good_salt_p(const krb5_salt *default_salt, const Key *key)
154 : {
155 11606 : if (key->key.keytype == KRB5_ENCTYPE_DES_CBC_CRC)
156 0 : return is_default_salt_p(default_salt, key);
157 :
158 11606 : return TRUE;
159 : }
160 :
161 : krb5_boolean
162 18487 : _kdc_is_anon_request(const KDC_REQ *req)
163 : {
164 18487 : 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 36974 : return b->kdc_options.request_anonymous ||
174 18410 : (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 11606 : _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 : krb5_boolean use_strongest_session_key;
200 11606 : krb5_boolean is_preauth = flags & KFE_IS_PREAUTH;
201 11606 : krb5_boolean is_tgs = flags & KFE_IS_TGS;
202 : hdb_entry *princ;
203 : krb5_principal request_princ;
204 : krb5_error_code ret;
205 : krb5_salt def_salt;
206 11606 : krb5_enctype enctype = ETYPE_NULL;
207 : const krb5_enctype *p;
208 11606 : Key *key = NULL;
209 : size_t i, k, m;
210 :
211 23212 : if (is_preauth && (flags & KFE_USE_CLIENT) &&
212 11606 : r->client->flags.synthetic)
213 0 : return KRB5KDC_ERR_ETYPE_NOSUPP;
214 :
215 11606 : if ((flags & KFE_USE_CLIENT) && !r->client->flags.synthetic) {
216 11606 : princ = r->client;
217 11606 : request_princ = r->client_princ;
218 : } else {
219 0 : princ = r->server;
220 0 : request_princ = r->server->principal;
221 : }
222 :
223 11606 : use_strongest_session_key =
224 11606 : is_preauth ? r->config->preauth_use_strongest_session_key
225 23212 : : (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 11606 : ret = krb5_get_pw_salt(r->context, request_princ, &def_salt);
230 11606 : if (ret)
231 0 : return ret;
232 :
233 11606 : 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 11606 : 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 11606 : p = krb5_kerberos_enctypes(r->context);
264 39618 : for (i = 0;
265 55119 : p[i] != ETYPE_NULL && enctype == ETYPE_NULL;
266 16406 : i++) {
267 16406 : 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 41975 : for (k = 0; k < len && enctype == ETYPE_NULL; k++) {
273 :
274 25569 : if (p[i] != etypes[k])
275 12740 : continue;
276 :
277 12829 : 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 12829 : key = NULL;
290 12829 : 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 37264 : while (hdb_next_enctype2key(r->context, princ, NULL,
312 24435 : p[i], &key) == 0) {
313 11606 : if (key->key.keyvalue.length == 0) {
314 0 : ret = KRB5KDC_ERR_NULL_KEY;
315 0 : continue;
316 : }
317 11606 : enctype = p[i];
318 11606 : ret = 0;
319 23212 : if (is_preauth && ret_key != NULL &&
320 11606 : !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 11606 : 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 11606 : if (ret == 0) {
375 11606 : if (ret_enctype != NULL)
376 0 : *ret_enctype = enctype;
377 11606 : if (ret_key != NULL)
378 11606 : *ret_key = key;
379 11606 : if (ret_default_salt != NULL)
380 11606 : *ret_default_salt = is_default_salt_p(&def_salt, key);
381 : }
382 :
383 11606 : krb5_free_salt (r->context, def_salt);
384 11606 : 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 66206 : _kdc_find_session_etype(astgs_request_t r,
393 : krb5_enctype *etypes, size_t len,
394 : const hdb_entry *princ,
395 : krb5_enctype *ret_enctype)
396 : {
397 : size_t i;
398 :
399 66206 : if (princ->session_etypes == NULL) {
400 : /* The principal must have session etypes available. */
401 0 : return KRB5KDC_ERR_ETYPE_NOSUPP;
402 : }
403 :
404 : /* Loop over the client's specified etypes. */
405 74306 : for (i = 0; i < len; ++i) {
406 : size_t j;
407 :
408 : /* Check that the server also supports the etype. */
409 88433 : for (j = 0; j < princ->session_etypes->len; ++j) {
410 80333 : if (princ->session_etypes->val[j] == etypes[i]) {
411 66087 : *ret_enctype = etypes[i];
412 66087 : return 0;
413 : }
414 : }
415 : }
416 :
417 119 : return KRB5KDC_ERR_ETYPE_NOSUPP;
418 : }
419 :
420 : krb5_error_code
421 30931 : _kdc_make_anonymous_principalname (PrincipalName *pn)
422 : {
423 30931 : pn->name_type = KRB5_NT_WELLKNOWN;
424 30931 : pn->name_string.len = 2;
425 30931 : pn->name_string.val = calloc(2, sizeof(*pn->name_string.val));
426 30931 : if (pn->name_string.val == NULL)
427 0 : goto failed;
428 :
429 30931 : pn->name_string.val[0] = strdup(KRB5_WELLKNOWN_NAME);
430 30931 : if (pn->name_string.val[0] == NULL)
431 0 : goto failed;
432 :
433 30931 : pn->name_string.val[1] = strdup(KRB5_ANON_NAME);
434 30931 : if (pn->name_string.val[1] == NULL)
435 0 : goto failed;
436 :
437 30931 : 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 122045 : _kdc_r_log(astgs_request_t r, int level, const char *fmt, ...)
451 : __attribute__ ((__format__ (__printf__, 3, 4)))
452 : {
453 : va_list ap;
454 : char *s;
455 122045 : va_start(ap, fmt);
456 122045 : s = kdc_log_msg_va(r->context, r->config, level, fmt, ap);
457 122045 : if(s) free(s);
458 122045 : va_end(ap);
459 122045 : }
460 :
461 : void
462 0 : _kdc_set_const_e_text(astgs_request_t r, const char *e_text)
463 : {
464 : /* We should never see this */
465 0 : 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 0 : r->e_text = e_text;
473 0 : kdc_log(r->context, r->config, 4, "%s", e_text);
474 : }
475 :
476 : void
477 19032 : _kdc_set_e_text(astgs_request_t r, const char *fmt, ...)
478 : __attribute__ ((__format__ (__printf__, 2, 3)))
479 : {
480 : va_list ap;
481 19032 : char *e_text = NULL;
482 : int vasprintf_ret;
483 :
484 19032 : va_start(ap, fmt);
485 19032 : vasprintf_ret = vasprintf(&e_text, fmt, ap);
486 19032 : va_end(ap);
487 :
488 19032 : 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 19032 : 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 19032 : r->e_text = e_text;
504 19032 : r->e_text_buf = e_text;
505 19032 : kdc_log(r->context, r->config, 4, "%s", e_text);
506 : }
507 :
508 : void
509 54055 : _kdc_log_timestamp(astgs_request_t r, const char *type,
510 : KerberosTime authtime, KerberosTime *starttime,
511 : KerberosTime endtime, KerberosTime *renew_till)
512 : {
513 54055 : krb5_kdc_configuration *config = r->config;
514 : char authtime_str[100], starttime_str[100],
515 : endtime_str[100], renewtime_str[100];
516 :
517 54055 : if (authtime)
518 54055 : kdc_audit_setkv_number((kdc_request_t)r, "auth", authtime);
519 54055 : if (starttime && *starttime)
520 35728 : kdc_audit_setkv_number((kdc_request_t)r, "start", *starttime);
521 54055 : if (endtime)
522 54055 : kdc_audit_setkv_number((kdc_request_t)r, "end", endtime);
523 54055 : if (renew_till && *renew_till)
524 3950 : kdc_audit_setkv_number((kdc_request_t)r, "renew", *renew_till);
525 :
526 54055 : krb5_format_time(r->context, authtime,
527 : authtime_str, sizeof(authtime_str), TRUE);
528 54055 : if (starttime)
529 35728 : krb5_format_time(r->context, *starttime,
530 : starttime_str, sizeof(starttime_str), TRUE);
531 : else
532 18327 : strlcpy(starttime_str, "unset", sizeof(starttime_str));
533 54055 : krb5_format_time(r->context, endtime,
534 : endtime_str, sizeof(endtime_str), TRUE);
535 54055 : if (renew_till)
536 3950 : krb5_format_time(r->context, *renew_till,
537 : renewtime_str, sizeof(renewtime_str), TRUE);
538 : else
539 50105 : strlcpy(renewtime_str, "unset", sizeof(renewtime_str));
540 :
541 54055 : 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 54055 : }
545 :
546 : /*
547 : *
548 : */
549 :
550 : #ifdef PKINIT
551 :
552 : static krb5_error_code
553 0 : pa_pkinit_validate(astgs_request_t r, const PA_DATA *pa)
554 : {
555 0 : pk_client_params *pkp = NULL;
556 0 : char *client_cert = NULL;
557 : krb5_error_code ret;
558 :
559 0 : ret = _kdc_pk_rd_padata(r, pa, &pkp);
560 0 : if (ret || pkp == NULL) {
561 0 : ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
562 0 : _kdc_r_log(r, 4, "Failed to decode PKINIT PA-DATA -- %s",
563 : r->cname);
564 0 : goto out;
565 : }
566 :
567 0 : ret = _kdc_pk_check_client(r, pkp, &client_cert);
568 0 : if (client_cert)
569 0 : kdc_audit_addkv((kdc_request_t)r, 0, KDC_REQUEST_KV_PKINIT_CLIENT_CERT,
570 : "%s", client_cert);
571 0 : if (ret) {
572 0 : _kdc_set_e_text(r, "PKINIT certificate not allowed to "
573 : "impersonate principal");
574 0 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
575 : KDC_AUTH_EVENT_CLIENT_NAME_UNAUTHORIZED);
576 0 : goto out;
577 : }
578 :
579 0 : r->pa_endtime = _kdc_pk_endtime(pkp);
580 0 : if (!r->client->flags.synthetic)
581 0 : r->pa_max_life = _kdc_pk_max_life(pkp);
582 :
583 0 : _kdc_r_log(r, 4, "PKINIT pre-authentication succeeded -- %s using %s",
584 : r->cname, client_cert);
585 :
586 0 : ret = _kdc_pk_mk_pa_reply(r, pkp);
587 0 : if (ret) {
588 0 : _kdc_set_e_text(r, "Failed to build PK-INIT reply");
589 0 : goto out;
590 : }
591 0 : ret = _kdc_add_initial_verified_cas(r->context, r->config,
592 : pkp, &r->et);
593 :
594 0 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
595 : KDC_AUTH_EVENT_PREAUTH_SUCCEEDED);
596 :
597 0 : out:
598 0 : if (pkp)
599 0 : _kdc_pk_free_client_param(r->context, pkp);
600 0 : free(client_cert);
601 :
602 0 : return ret;
603 : }
604 :
605 : #endif /* PKINIT */
606 :
607 : static krb5_error_code
608 0 : pa_gss_validate(astgs_request_t r, const PA_DATA *pa)
609 : {
610 0 : gss_client_params *gcp = NULL;
611 0 : char *client_name = NULL;
612 : krb5_error_code ret;
613 0 : int open = 0;
614 :
615 0 : ret = _kdc_gss_rd_padata(r, pa, &gcp, &open);
616 0 : if (ret && gcp == NULL)
617 0 : return ret;
618 :
619 0 : if (open) {
620 0 : ret = _kdc_gss_check_client(r, gcp, &client_name);
621 0 : if (client_name)
622 0 : kdc_audit_addkv((kdc_request_t)r, 0, KDC_REQUEST_KV_GSS_INITIATOR,
623 : "%s", client_name);
624 0 : if (ret) {
625 0 : _kdc_set_e_text(r, "GSS-API client not allowed to "
626 : "impersonate principal");
627 0 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
628 : KDC_AUTH_EVENT_CLIENT_NAME_UNAUTHORIZED);
629 0 : goto out;
630 : }
631 :
632 0 : r->pa_endtime = _kdc_gss_endtime(r, gcp);
633 :
634 0 : _kdc_r_log(r, 4, "GSS pre-authentication succeeded -- %s using %s",
635 : r->cname, client_name);
636 0 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
637 : KDC_AUTH_EVENT_PREAUTH_SUCCEEDED);
638 :
639 0 : ret = _kdc_gss_mk_composite_name_ad(r, gcp);
640 0 : if (ret) {
641 0 : _kdc_set_e_text(r, "Failed to build GSS authorization data");
642 0 : goto out;
643 : }
644 : }
645 :
646 0 : ret = _kdc_gss_mk_pa_reply(r, gcp);
647 0 : if (ret) {
648 0 : if (ret != KRB5_KDC_ERR_MORE_PREAUTH_DATA_REQUIRED)
649 0 : _kdc_set_e_text(r, "Failed to build GSS pre-authentication reply");
650 0 : goto out;
651 : }
652 :
653 0 : ret = kdc_request_set_attribute((kdc_request_t)r,
654 0 : HSTR("org.h5l.pa-gss-client-params"), gcp);
655 0 : if (ret)
656 0 : goto out;
657 :
658 0 : out:
659 0 : kdc_object_release(gcp);
660 0 : free(client_name);
661 :
662 0 : return ret;
663 : }
664 :
665 : static krb5_error_code
666 0 : pa_gss_finalize_pac(astgs_request_t r)
667 : {
668 : gss_client_params *gcp;
669 :
670 0 : gcp = kdc_request_get_attribute((kdc_request_t)r, HSTR("org.h5l.pa-gss-client-params"));
671 :
672 0 : heim_assert(gcp != NULL, "invalid GSS-API client params");
673 :
674 0 : return _kdc_gss_finalize_pac(r, gcp);
675 : }
676 :
677 : static krb5_error_code
678 1 : pa_enc_chal_validate(astgs_request_t r, const PA_DATA *pa)
679 : {
680 : krb5_data pepper1, pepper2;
681 1 : int invalidPassword = 0;
682 : EncryptedData enc_data;
683 : krb5_enctype aenctype;
684 : krb5_error_code ret;
685 : struct Key *k;
686 : size_t size;
687 : int i;
688 :
689 1 : heim_assert(r->armor_crypto != NULL, "ENC-CHAL called for non FAST");
690 :
691 1 : if (_kdc_is_anon_request(&r->req)) {
692 0 : ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
693 0 : kdc_log(r->context, r->config, 4, "ENC-CHALL doesn't support anon");
694 0 : return ret;
695 : }
696 :
697 1 : if (r->client->flags.locked_out) {
698 0 : ret = KRB5KDC_ERR_CLIENT_REVOKED;
699 0 : kdc_log(r->context, r->config, 0,
700 : "Client (%s) is locked out", r->cname);
701 0 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
702 : KDC_AUTH_EVENT_CLIENT_LOCKED_OUT);
703 0 : return ret;
704 : }
705 :
706 1 : ret = decode_EncryptedData(pa->padata_value.data,
707 : pa->padata_value.length,
708 : &enc_data,
709 : &size);
710 1 : if (ret) {
711 0 : ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
712 0 : _kdc_r_log(r, 4, "Failed to decode PA-DATA -- %s",
713 : r->cname);
714 0 : return ret;
715 : }
716 :
717 1 : pepper1.data = "clientchallengearmor";
718 1 : pepper1.length = strlen(pepper1.data);
719 1 : pepper2.data = "challengelongterm";
720 1 : pepper2.length = strlen(pepper2.data);
721 :
722 1 : krb5_crypto_getenctype(r->context, r->armor_crypto, &aenctype);
723 :
724 1 : kdc_log(r->context, r->config, 5, "FAST armor enctype is: %d", (int)aenctype);
725 :
726 2 : for (i = 0; i < r->client->keys.len; i++) {
727 : krb5_crypto challengecrypto, longtermcrypto;
728 : krb5_keyblock challengekey;
729 :
730 1 : k = &r->client->keys.val[i];
731 :
732 1 : ret = krb5_crypto_init(r->context, &k->key, 0, &longtermcrypto);
733 1 : if (ret)
734 0 : continue;
735 :
736 1 : ret = krb5_crypto_fx_cf2(r->context, r->armor_crypto, longtermcrypto,
737 : &pepper1, &pepper2, aenctype,
738 : &challengekey);
739 1 : if (ret) {
740 0 : krb5_crypto_destroy(r->context, longtermcrypto);
741 0 : continue;
742 : }
743 :
744 1 : ret = krb5_crypto_init(r->context, &challengekey, 0,
745 : &challengecrypto);
746 1 : krb5_free_keyblock_contents(r->context, &challengekey);
747 1 : if (ret) {
748 0 : krb5_crypto_destroy(r->context, longtermcrypto);
749 0 : continue;
750 : }
751 :
752 1 : ret = _krb5_validate_pa_enc_challenge(r->context,
753 : challengecrypto,
754 : KRB5_KU_ENC_CHALLENGE_CLIENT,
755 : &enc_data,
756 1 : r->cname);
757 1 : krb5_crypto_destroy(r->context, challengecrypto);
758 1 : if (ret) {
759 : const char *msg;
760 : krb5_error_code ret2;
761 0 : char *str = NULL;
762 :
763 0 : krb5_crypto_destroy(r->context, longtermcrypto);
764 :
765 0 : invalidPassword = (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY);
766 0 : if (!invalidPassword) {
767 0 : goto out;
768 : }
769 :
770 0 : ret2 = krb5_enctype_to_string(r->context, k->key.keytype, &str);
771 0 : if (ret2)
772 0 : str = NULL;
773 0 : msg = krb5_get_error_message(r->context, ret);
774 0 : _kdc_r_log(r, 2, "Failed to decrypt ENC-CHAL -- %s "
775 : "(enctype %s) error %s",
776 0 : r->cname, str ? str : "unknown enctype", msg);
777 0 : krb5_free_error_message(r->context, msg);
778 0 : free(str);
779 :
780 0 : continue;
781 : }
782 :
783 : /*
784 : * Found a key that the client used, lets pick that as the reply key
785 : */
786 :
787 1 : krb5_free_keyblock_contents(r->context, &r->reply_key);
788 1 : ret = krb5_copy_keyblock_contents(r->context, &k->key, &r->reply_key);
789 1 : if (ret) {
790 0 : krb5_crypto_destroy(r->context, longtermcrypto);
791 0 : goto out;
792 : }
793 :
794 1 : krb5_free_keyblock_contents(r->context, &challengekey);
795 :
796 : /*
797 : * Provide KDC authentication to the client, uses a different
798 : * challenge key (different pepper).
799 : */
800 :
801 1 : pepper1.data = "kdcchallengearmor";
802 1 : pepper1.length = strlen(pepper1.data);
803 :
804 1 : ret = krb5_crypto_fx_cf2(r->context, r->armor_crypto, longtermcrypto,
805 : &pepper1, &pepper2, aenctype,
806 : &challengekey);
807 1 : krb5_crypto_destroy(r->context, longtermcrypto);
808 1 : if (ret)
809 0 : goto out;
810 :
811 1 : ret = krb5_crypto_init(r->context, &challengekey, 0, &challengecrypto);
812 1 : krb5_free_keyblock_contents(r->context, &challengekey);
813 1 : if (ret)
814 0 : goto out;
815 :
816 1 : ret = _krb5_make_pa_enc_challenge(r->context, challengecrypto,
817 : KRB5_KU_ENC_CHALLENGE_KDC,
818 : r->rep.padata);
819 1 : krb5_crypto_destroy(r->context, challengecrypto);
820 1 : if (ret)
821 0 : goto out;
822 :
823 1 : if (ret == 0)
824 1 : ret = set_salt_padata(r->context, r->config,
825 : r->rep.padata, k);
826 :
827 : /*
828 : * Success
829 : */
830 1 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
831 : KDC_AUTH_EVENT_VALIDATED_LONG_TERM_KEY);
832 1 : goto out;
833 : }
834 :
835 0 : if (invalidPassword) {
836 0 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
837 : KDC_AUTH_EVENT_WRONG_LONG_TERM_KEY);
838 0 : ret = KRB5KDC_ERR_PREAUTH_FAILED;
839 : } else {
840 0 : ret = KRB5KDC_ERR_ETYPE_NOSUPP;
841 : }
842 1 : out:
843 1 : free_EncryptedData(&enc_data);
844 :
845 1 : return ret;
846 : }
847 :
848 : static krb5_error_code
849 18720 : pa_enc_ts_validate(astgs_request_t r, const PA_DATA *pa)
850 : {
851 : EncryptedData enc_data;
852 : krb5_error_code ret;
853 : krb5_crypto crypto;
854 : krb5_data ts_data;
855 : PA_ENC_TS_ENC p;
856 : size_t len;
857 : Key *pa_key;
858 : char *str;
859 :
860 18720 : if (r->armor_crypto && !r->config->enable_armored_pa_enc_timestamp) {
861 0 : ret = KRB5KDC_ERR_POLICY;
862 0 : kdc_log(r->context, r->config, 0,
863 : "Armored encrypted timestamp pre-authentication is disabled");
864 0 : return ret;
865 18720 : } else if (!r->armor_crypto && !r->config->enable_unarmored_pa_enc_timestamp) {
866 0 : ret = KRB5KDC_ERR_POLICY;
867 0 : kdc_log(r->context, r->config, 0,
868 : "Unarmored encrypted timestamp pre-authentication is disabled");
869 0 : return ret;
870 : }
871 :
872 18720 : if (r->client->flags.locked_out) {
873 26 : ret = KRB5KDC_ERR_CLIENT_REVOKED;
874 26 : kdc_log(r->context, r->config, 0,
875 : "Client (%s) is locked out", r->cname);
876 26 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
877 : KDC_AUTH_EVENT_CLIENT_LOCKED_OUT);
878 26 : return ret;
879 : }
880 :
881 18694 : ret = decode_EncryptedData(pa->padata_value.data,
882 : pa->padata_value.length,
883 : &enc_data,
884 : &len);
885 18694 : if (ret) {
886 0 : ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
887 0 : _kdc_r_log(r, 4, "Failed to decode PA-DATA -- %s",
888 : r->cname);
889 0 : goto out;
890 : }
891 :
892 18694 : ret = hdb_enctype2key(r->context, r->client, NULL,
893 : enc_data.etype, &pa_key);
894 18694 : if(ret){
895 : char *estr;
896 0 : _kdc_set_e_text(r, "No key matching entype");
897 0 : ret = KRB5KDC_ERR_ETYPE_NOSUPP;
898 0 : if(krb5_enctype_to_string(r->context, enc_data.etype, &estr))
899 0 : estr = NULL;
900 0 : if(estr == NULL)
901 0 : _kdc_r_log(r, 4,
902 : "No client key matching pa-data (%d) -- %s",
903 0 : enc_data.etype, r->cname);
904 : else
905 0 : _kdc_r_log(r, 4,
906 : "No client key matching pa-data (%s) -- %s",
907 : estr, r->cname);
908 0 : free(estr);
909 0 : free_EncryptedData(&enc_data);
910 0 : goto out;
911 : }
912 :
913 18694 : try_next_key:
914 18694 : ret = krb5_crypto_init(r->context, &pa_key->key, 0, &crypto);
915 18694 : if (ret) {
916 0 : const char *msg = krb5_get_error_message(r->context, ret);
917 0 : _kdc_r_log(r, 4, "krb5_crypto_init failed: %s", msg);
918 0 : krb5_free_error_message(r->context, msg);
919 0 : free_EncryptedData(&enc_data);
920 0 : goto out;
921 : }
922 :
923 18694 : ret = krb5_decrypt_EncryptedData (r->context,
924 : crypto,
925 : KRB5_KU_PA_ENC_TIMESTAMP,
926 : &enc_data,
927 : &ts_data);
928 18694 : krb5_crypto_destroy(r->context, crypto);
929 : /*
930 : * Since the user might have several keys with the same
931 : * enctype but with diffrent salting, we need to try all
932 : * the keys with the same enctype.
933 : */
934 18694 : if(ret){
935 : krb5_error_code ret2;
936 274 : const char *msg = krb5_get_error_message(r->context, ret);
937 :
938 274 : ret2 = krb5_enctype_to_string(r->context,
939 274 : pa_key->key.keytype, &str);
940 274 : if (ret2)
941 0 : str = NULL;
942 274 : _kdc_r_log(r, 2, "Failed to decrypt PA-DATA -- %s "
943 : "(enctype %s) error %s",
944 274 : r->cname, str ? str : "unknown enctype", msg);
945 274 : krb5_xfree(str);
946 274 : krb5_free_error_message(r->context, msg);
947 274 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_PA_ETYPE,
948 274 : pa_key->key.keytype);
949 274 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
950 : KDC_AUTH_EVENT_WRONG_LONG_TERM_KEY);
951 274 : if(hdb_next_enctype2key(r->context, r->client, NULL,
952 : enc_data.etype, &pa_key) == 0)
953 0 : goto try_next_key;
954 :
955 274 : free_EncryptedData(&enc_data);
956 :
957 274 : ret = KRB5KDC_ERR_PREAUTH_FAILED;
958 274 : goto out;
959 : }
960 18420 : free_EncryptedData(&enc_data);
961 18420 : ret = decode_PA_ENC_TS_ENC(ts_data.data,
962 : ts_data.length,
963 : &p,
964 : &len);
965 18420 : krb5_data_free(&ts_data);
966 18420 : if(ret){
967 0 : ret = KRB5KDC_ERR_PREAUTH_FAILED;
968 0 : _kdc_r_log(r, 4, "Failed to decode PA-ENC-TS_ENC -- %s",
969 : r->cname);
970 0 : goto out;
971 : }
972 18420 : if (labs(kdc_time - p.patimestamp) > r->context->max_skew) {
973 : char client_time[100];
974 :
975 8 : krb5_format_time(r->context, p.patimestamp,
976 : client_time, sizeof(client_time), TRUE);
977 :
978 8 : ret = KRB5KRB_AP_ERR_SKEW;
979 24 : _kdc_r_log(r, 4, "Too large time skew, "
980 : "client time %s is out by %u > %u seconds -- %s",
981 : client_time,
982 8 : (unsigned)labs(kdc_time - p.patimestamp),
983 8 : r->context->max_skew,
984 : r->cname);
985 8 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
986 : KDC_AUTH_EVENT_CLIENT_TIME_SKEW);
987 :
988 : /*
989 : * The following is needed to make windows clients to
990 : * retry using the timestamp in the error message, if
991 : * there is a e_text, they become unhappy.
992 : */
993 8 : r->e_text = NULL;
994 8 : free_PA_ENC_TS_ENC(&p);
995 8 : goto out;
996 : }
997 18412 : free_PA_ENC_TS_ENC(&p);
998 :
999 18412 : ret = set_salt_padata(r->context, r->config,
1000 : r->rep.padata, pa_key);
1001 18412 : if (ret == 0)
1002 18412 : ret = krb5_copy_keyblock_contents(r->context, &pa_key->key, &r->reply_key);
1003 18412 : if (ret)
1004 0 : return ret;
1005 :
1006 18412 : ret = krb5_enctype_to_string(r->context, pa_key->key.keytype, &str);
1007 18412 : if (ret)
1008 0 : str = NULL;
1009 18412 : _kdc_r_log(r, 4, "ENC-TS Pre-authentication succeeded -- %s using %s",
1010 18412 : r->cname, str ? str : "unknown enctype");
1011 18412 : krb5_xfree(str);
1012 18412 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_PA_ETYPE,
1013 18412 : pa_key->key.keytype);
1014 18412 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
1015 : KDC_AUTH_EVENT_VALIDATED_LONG_TERM_KEY);
1016 :
1017 18412 : ret = 0;
1018 :
1019 18694 : out:
1020 :
1021 18694 : return ret;
1022 : }
1023 :
1024 : struct kdc_patypes {
1025 : int type;
1026 : char *name;
1027 : unsigned int flags;
1028 : #define PA_ANNOUNCE 1
1029 : #define PA_REQ_FAST 2 /* only use inside fast */
1030 : #define PA_SYNTHETIC_OK 4
1031 : #define PA_REPLACE_REPLY_KEY 8 /* PA mech replaces reply key */
1032 : #define PA_USES_LONG_TERM_KEY 16 /* PA mech uses client's long-term key */
1033 : krb5_error_code (*validate)(astgs_request_t, const PA_DATA *pa);
1034 : krb5_error_code (*finalize_pac)(astgs_request_t r);
1035 : void (*cleanup)(astgs_request_t r);
1036 : };
1037 :
1038 : static const struct kdc_patypes pat[] = {
1039 : #ifdef PKINIT
1040 : {
1041 : KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)",
1042 : PA_ANNOUNCE | PA_SYNTHETIC_OK | PA_REPLACE_REPLY_KEY,
1043 : pa_pkinit_validate, NULL, NULL
1044 : },
1045 : {
1046 : KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", PA_ANNOUNCE | PA_REPLACE_REPLY_KEY,
1047 : pa_pkinit_validate, NULL, NULL
1048 : },
1049 : {
1050 : KRB5_PADATA_PKINIT_KX, "Anonymous PK-INIT", PA_ANNOUNCE,
1051 : NULL, NULL, NULL
1052 : },
1053 : #else
1054 : { KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)", 0, NULL , NULL, NULL },
1055 : { KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", 0, NULL, NULL, NULL },
1056 : { KRB5_PADATA_PKINIT_KX, "Anonymous PK-INIT", 0, NULL, NULL, NULL },
1057 : #endif
1058 : { KRB5_PADATA_PA_PK_OCSP_RESPONSE , "OCSP", 0, NULL, NULL, NULL },
1059 : {
1060 : KRB5_PADATA_ENC_TIMESTAMP , "ENC-TS",
1061 : PA_ANNOUNCE | PA_USES_LONG_TERM_KEY,
1062 : pa_enc_ts_validate, NULL, NULL
1063 : },
1064 : {
1065 : KRB5_PADATA_ENCRYPTED_CHALLENGE , "ENC-CHAL",
1066 : PA_ANNOUNCE | PA_USES_LONG_TERM_KEY | PA_REQ_FAST,
1067 : pa_enc_chal_validate, NULL, NULL
1068 : },
1069 : { KRB5_PADATA_REQ_ENC_PA_REP , "REQ-ENC-PA-REP", 0, NULL, NULL, NULL },
1070 : { KRB5_PADATA_FX_FAST, "FX-FAST", PA_ANNOUNCE, NULL, NULL, NULL },
1071 : { KRB5_PADATA_FX_ERROR, "FX-ERROR", 0, NULL, NULL, NULL },
1072 : { KRB5_PADATA_FX_COOKIE, "FX-COOKIE", 0, NULL, NULL, NULL },
1073 : {
1074 : KRB5_PADATA_GSS , "GSS",
1075 : PA_ANNOUNCE | PA_SYNTHETIC_OK | PA_REPLACE_REPLY_KEY,
1076 : pa_gss_validate, pa_gss_finalize_pac, NULL
1077 : },
1078 : };
1079 :
1080 : static void
1081 28654 : log_patypes(astgs_request_t r, METHOD_DATA *padata)
1082 : {
1083 28654 : krb5_kdc_configuration *config = r->config;
1084 28654 : struct rk_strpool *p = NULL;
1085 : char *str;
1086 : size_t n, m;
1087 :
1088 75538 : for (n = 0; n < padata->len; n++) {
1089 296845 : for (m = 0; m < sizeof(pat) / sizeof(pat[0]); m++) {
1090 295626 : if (padata->val[n].padata_type == pat[m].type) {
1091 45665 : p = rk_strpoolprintf(p, "%s", pat[m].name);
1092 45665 : break;
1093 : }
1094 : }
1095 46884 : if (m == sizeof(pat) / sizeof(pat[0]))
1096 1219 : p = rk_strpoolprintf(p, "%d", padata->val[n].padata_type);
1097 46884 : if (p && n + 1 < padata->len)
1098 18230 : p = rk_strpoolprintf(p, ", ");
1099 46884 : if (p == NULL) {
1100 0 : kdc_log(r->context, config, 1, "out of memory");
1101 0 : return;
1102 : }
1103 : }
1104 28654 : if (p == NULL)
1105 0 : p = rk_strpoolprintf(p, "none");
1106 :
1107 28654 : str = rk_strpoolcollect(p);
1108 28654 : kdc_log(r->context, config, 4, "Client sent patypes: %s", str);
1109 28654 : kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE,
1110 : "client-pa", "%s", str);
1111 28654 : free(str);
1112 : }
1113 :
1114 : static krb5_boolean
1115 36654 : pa_used_flag_isset(astgs_request_t r, unsigned int flag)
1116 : {
1117 36654 : if (r->pa_used == NULL)
1118 0 : return FALSE;
1119 :
1120 36654 : return (r->pa_used->flags & flag) == flag;
1121 : }
1122 :
1123 : /*
1124 : *
1125 : */
1126 :
1127 : krb5_error_code
1128 54055 : _kdc_encode_reply(krb5_context context,
1129 : krb5_kdc_configuration *config,
1130 : astgs_request_t r, uint32_t nonce,
1131 : krb5_enctype etype,
1132 : int skvno, const EncryptionKey *skey,
1133 : int ckvno,
1134 : int rk_is_subkey,
1135 : krb5_data *reply)
1136 : {
1137 : unsigned char *buf;
1138 : size_t buf_size;
1139 54055 : size_t len = 0;
1140 : krb5_error_code ret;
1141 : krb5_crypto crypto;
1142 54055 : KDC_REP *rep = &r->rep;
1143 54055 : EncTicketPart *et = &r->et;
1144 54055 : EncKDCRepPart *ek = &r->ek;
1145 :
1146 54055 : heim_assert(rep->padata != NULL, "reply padata uninitialized");
1147 :
1148 54055 : ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret);
1149 54055 : if(ret) {
1150 0 : const char *msg = krb5_get_error_message(context, ret);
1151 0 : kdc_log(context, config, 4, "Failed to encode ticket: %s", msg);
1152 0 : krb5_free_error_message(context, msg);
1153 0 : return ret;
1154 : }
1155 54055 : if(buf_size != len)
1156 0 : krb5_abortx(context, "Internal error in ASN.1 encoder");
1157 :
1158 54055 : ret = krb5_crypto_init(context, skey, etype, &crypto);
1159 54055 : if (ret) {
1160 0 : const char *msg = krb5_get_error_message(context, ret);
1161 0 : kdc_log(context, config, 4, "krb5_crypto_init failed: %s", msg);
1162 0 : krb5_free_error_message(context, msg);
1163 0 : free(buf);
1164 0 : return ret;
1165 : }
1166 :
1167 54055 : ret = krb5_encrypt_EncryptedData(context,
1168 : crypto,
1169 : KRB5_KU_TICKET,
1170 : buf,
1171 : len,
1172 : skvno,
1173 : &rep->ticket.enc_part);
1174 54055 : free(buf);
1175 54055 : krb5_crypto_destroy(context, crypto);
1176 54055 : if(ret) {
1177 0 : const char *msg = krb5_get_error_message(context, ret);
1178 0 : kdc_log(context, config, 4, "Failed to encrypt data: %s", msg);
1179 0 : krb5_free_error_message(context, msg);
1180 0 : return ret;
1181 : }
1182 :
1183 54055 : if (r && r->armor_crypto) {
1184 : KrbFastFinished finished;
1185 : krb5_data data;
1186 :
1187 30932 : kdc_log(context, config, 4, "FAST armor protection");
1188 :
1189 30932 : memset(&finished, 0, sizeof(finished));
1190 30932 : krb5_data_zero(&data);
1191 :
1192 30932 : finished.timestamp = kdc_time;
1193 30932 : finished.usec = 0;
1194 30932 : finished.crealm = et->crealm;
1195 30932 : finished.cname = et->cname;
1196 :
1197 30932 : ASN1_MALLOC_ENCODE(Ticket, data.data, data.length,
1198 : &rep->ticket, &len, ret);
1199 30932 : if (ret)
1200 0 : return ret;
1201 30932 : if (data.length != len)
1202 0 : krb5_abortx(context, "internal asn.1 error");
1203 :
1204 30932 : ret = krb5_create_checksum(context, r->armor_crypto,
1205 : KRB5_KU_FAST_FINISHED, 0,
1206 : data.data, data.length,
1207 : &finished.ticket_checksum);
1208 30932 : krb5_data_free(&data);
1209 30932 : if (ret)
1210 0 : return ret;
1211 :
1212 30932 : ret = _kdc_fast_mk_response(context, r->armor_crypto,
1213 : rep->padata, &r->strengthen_key, &finished,
1214 : nonce, &data);
1215 30932 : free_Checksum(&finished.ticket_checksum);
1216 30932 : if (ret)
1217 0 : return ret;
1218 :
1219 30932 : free_METHOD_DATA(r->rep.padata);
1220 :
1221 30932 : ret = krb5_padata_add(context, rep->padata,
1222 : KRB5_PADATA_FX_FAST,
1223 : data.data, data.length);
1224 30932 : if (ret)
1225 0 : return ret;
1226 :
1227 : /*
1228 : * Hide client name for privacy reasons
1229 : */
1230 30932 : if (r->fast.flags.requested_hidden_names) {
1231 30931 : Realm anon_realm = KRB5_ANON_REALM;
1232 :
1233 30931 : free_Realm(&rep->crealm);
1234 30931 : ret = copy_Realm(&anon_realm, &rep->crealm);
1235 30931 : if (ret == 0) {
1236 30931 : free_PrincipalName(&rep->cname);
1237 30931 : ret = _kdc_make_anonymous_principalname(&rep->cname);
1238 : }
1239 30931 : if (ret)
1240 0 : return ret;
1241 : }
1242 : }
1243 :
1244 54055 : if (rep->padata->len == 0) {
1245 5929 : free_METHOD_DATA(rep->padata);
1246 5929 : free(rep->padata);
1247 5929 : rep->padata = NULL;
1248 : }
1249 :
1250 54055 : if(rep->msg_type == krb_as_rep && !config->encode_as_rep_as_tgs_rep)
1251 18327 : ASN1_MALLOC_ENCODE(EncASRepPart, buf, buf_size, ek, &len, ret);
1252 : else
1253 35728 : ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret);
1254 54055 : if(ret) {
1255 0 : const char *msg = krb5_get_error_message(context, ret);
1256 0 : kdc_log(context, config, 4, "Failed to encode KDC-REP: %s", msg);
1257 0 : krb5_free_error_message(context, msg);
1258 0 : return ret;
1259 : }
1260 54055 : if(buf_size != len) {
1261 0 : free(buf);
1262 0 : kdc_log(context, config, 4, "Internal error in ASN.1 encoder");
1263 0 : _kdc_set_e_text(r, "KDC internal error");
1264 0 : return KRB5KRB_ERR_GENERIC;
1265 : }
1266 54055 : ret = krb5_crypto_init(context, &r->reply_key, 0, &crypto);
1267 54055 : if (ret) {
1268 0 : const char *msg = krb5_get_error_message(context, ret);
1269 0 : free(buf);
1270 0 : kdc_log(context, config, 4, "krb5_crypto_init failed: %s", msg);
1271 0 : krb5_free_error_message(context, msg);
1272 0 : return ret;
1273 : }
1274 54055 : if(rep->msg_type == krb_as_rep) {
1275 18327 : ret = krb5_encrypt_EncryptedData(context,
1276 : crypto,
1277 : KRB5_KU_AS_REP_ENC_PART,
1278 : buf,
1279 : len,
1280 : ckvno,
1281 : &rep->enc_part);
1282 18327 : free(buf);
1283 18327 : if (ret == 0)
1284 18327 : ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret);
1285 : } else {
1286 35728 : ret = krb5_encrypt_EncryptedData(context,
1287 : crypto,
1288 : rk_is_subkey ?
1289 : KRB5_KU_TGS_REP_ENC_PART_SUB_KEY :
1290 : KRB5_KU_TGS_REP_ENC_PART_SESSION,
1291 : buf,
1292 : len,
1293 : ckvno,
1294 : &rep->enc_part);
1295 35728 : free(buf);
1296 35728 : if (ret == 0)
1297 35728 : ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret);
1298 : }
1299 54055 : krb5_crypto_destroy(context, crypto);
1300 54055 : if(ret) {
1301 0 : const char *msg = krb5_get_error_message(context, ret);
1302 0 : kdc_log(context, config, 4, "Failed to encode KDC-REP: %s", msg);
1303 0 : krb5_free_error_message(context, msg);
1304 0 : return ret;
1305 : }
1306 54055 : if(buf_size != len) {
1307 0 : free(buf);
1308 0 : kdc_log(context, config, 4, "Internal error in ASN.1 encoder");
1309 0 : _kdc_set_e_text(r, "KDC internal error");
1310 0 : return KRB5KRB_ERR_GENERIC;
1311 : }
1312 54055 : reply->data = buf;
1313 54055 : reply->length = buf_size;
1314 54055 : return 0;
1315 : }
1316 :
1317 : /*
1318 : *
1319 : */
1320 :
1321 : static krb5_error_code
1322 536 : get_pa_etype_info(krb5_context context,
1323 : krb5_kdc_configuration *config,
1324 : METHOD_DATA *md, Key *ckey,
1325 : krb5_boolean include_salt)
1326 : {
1327 536 : krb5_error_code ret = 0;
1328 : ETYPE_INFO_ENTRY eie; /* do not free this one */
1329 : ETYPE_INFO ei;
1330 : PA_DATA pa;
1331 : size_t len;
1332 :
1333 : /*
1334 : * Code moved here from what used to be make_etype_info_entry() because
1335 : * using the ASN.1 compiler-generated SEQUENCE OF add functions makes that
1336 : * old function's body and this one's small and clean.
1337 : *
1338 : * The following comment blocks were there:
1339 : *
1340 : * According to `the specs', we can't send a salt if we have AFS3 salted
1341 : * key, but that requires that you *know* what cell you are using (e.g by
1342 : * assuming that the cell is the same as the realm in lower case)
1343 : *
1344 : * We shouldn't sent salttype since it is incompatible with the
1345 : * specification and it breaks windows clients. The afs salting problem
1346 : * is solved by using KRB5-PADATA-AFS3-SALT implemented in Heimdal 0.7 and
1347 : * later.
1348 : *
1349 : * We return no salt type at all, as that should indicate the default salt
1350 : * type and make everybody happy. some systems (like w2k) dislike being
1351 : * told the salt type here.
1352 : */
1353 :
1354 536 : pa.padata_type = KRB5_PADATA_ETYPE_INFO;
1355 536 : pa.padata_value.data = NULL;
1356 536 : pa.padata_value.length = 0;
1357 536 : ei.len = 0;
1358 536 : ei.val = NULL;
1359 536 : eie.etype = ckey->key.keytype;
1360 536 : eie.salttype = NULL;
1361 536 : eie.salt = NULL;
1362 536 : if (include_salt && ckey->salt)
1363 0 : eie.salt = &ckey->salt->salt;
1364 536 : ret = add_ETYPE_INFO(&ei, &eie);
1365 536 : if (ret == 0)
1366 536 : ASN1_MALLOC_ENCODE(ETYPE_INFO, pa.padata_value.data, pa.padata_value.length,
1367 : &ei, &len, ret);
1368 536 : if (ret == 0)
1369 536 : add_METHOD_DATA(md, &pa);
1370 536 : free_ETYPE_INFO(&ei);
1371 536 : free_PA_DATA(&pa);
1372 536 : return ret;
1373 : }
1374 :
1375 : /*
1376 : *
1377 : */
1378 :
1379 : extern int _krb5_AES_SHA1_string_to_default_iterator;
1380 : extern int _krb5_AES_SHA2_string_to_default_iterator;
1381 :
1382 : static krb5_error_code
1383 27975 : make_s2kparams(int value, size_t len, krb5_data **ps2kparams)
1384 : {
1385 : krb5_data *s2kparams;
1386 : krb5_error_code ret;
1387 :
1388 27975 : ALLOC(s2kparams);
1389 27975 : if (s2kparams == NULL)
1390 0 : return ENOMEM;
1391 27975 : ret = krb5_data_alloc(s2kparams, len);
1392 27975 : if (ret) {
1393 0 : free(s2kparams);
1394 0 : return ret;
1395 : }
1396 27975 : _krb5_put_int(s2kparams->data, value, len);
1397 27975 : *ps2kparams = s2kparams;
1398 27975 : return 0;
1399 : }
1400 :
1401 : static krb5_error_code
1402 28880 : make_etype_info2_entry(ETYPE_INFO2_ENTRY *ent,
1403 : Key *key,
1404 : krb5_boolean include_salt)
1405 : {
1406 : krb5_error_code ret;
1407 :
1408 28880 : ent->etype = key->key.keytype;
1409 28880 : if (key->salt && include_salt) {
1410 27975 : ALLOC(ent->salt);
1411 27975 : if (ent->salt == NULL)
1412 0 : return ENOMEM;
1413 27975 : *ent->salt = malloc(key->salt->salt.length + 1);
1414 27975 : if (*ent->salt == NULL) {
1415 0 : free(ent->salt);
1416 0 : ent->salt = NULL;
1417 0 : return ENOMEM;
1418 : }
1419 27975 : memcpy(*ent->salt, key->salt->salt.data, key->salt->salt.length);
1420 27975 : (*ent->salt)[key->salt->salt.length] = '\0';
1421 : } else
1422 905 : ent->salt = NULL;
1423 :
1424 28880 : ent->s2kparams = NULL;
1425 :
1426 28880 : switch (key->key.keytype) {
1427 27975 : case ETYPE_AES128_CTS_HMAC_SHA1_96:
1428 : case ETYPE_AES256_CTS_HMAC_SHA1_96:
1429 27975 : ret = make_s2kparams(_krb5_AES_SHA1_string_to_default_iterator,
1430 27975 : 4, &ent->s2kparams);
1431 27975 : break;
1432 0 : case KRB5_ENCTYPE_AES128_CTS_HMAC_SHA256_128:
1433 : case KRB5_ENCTYPE_AES256_CTS_HMAC_SHA384_192:
1434 0 : ret = make_s2kparams(_krb5_AES_SHA2_string_to_default_iterator,
1435 0 : 4, &ent->s2kparams);
1436 0 : break;
1437 0 : case ETYPE_DES_CBC_CRC:
1438 : case ETYPE_DES_CBC_MD4:
1439 : case ETYPE_DES_CBC_MD5:
1440 : /* Check if this was a AFS3 salted key */
1441 0 : if(key->salt && key->salt->type == hdb_afs3_salt)
1442 0 : ret = make_s2kparams(1, 1, &ent->s2kparams);
1443 : else
1444 0 : ret = 0;
1445 0 : break;
1446 905 : default:
1447 905 : ret = 0;
1448 905 : break;
1449 : }
1450 28880 : return ret;
1451 : }
1452 :
1453 : /*
1454 : * Return an ETYPE-INFO2. Enctypes are storted the same way as in the
1455 : * database (client supported enctypes first, then the unsupported
1456 : * enctypes).
1457 : */
1458 :
1459 : static krb5_error_code
1460 28880 : get_pa_etype_info2(krb5_context context,
1461 : krb5_kdc_configuration *config,
1462 : METHOD_DATA *md, Key *ckey,
1463 : krb5_boolean include_salt)
1464 : {
1465 28880 : krb5_error_code ret = 0;
1466 : ETYPE_INFO2 pa;
1467 : unsigned char *buf;
1468 : size_t len;
1469 :
1470 28880 : pa.len = 1;
1471 28880 : pa.val = calloc(1, sizeof(pa.val[0]));
1472 28880 : if(pa.val == NULL)
1473 0 : return ENOMEM;
1474 :
1475 28880 : ret = make_etype_info2_entry(&pa.val[0], ckey, include_salt);
1476 28880 : if (ret) {
1477 0 : free_ETYPE_INFO2(&pa);
1478 0 : return ret;
1479 : }
1480 :
1481 28880 : ASN1_MALLOC_ENCODE(ETYPE_INFO2, buf, len, &pa, &len, ret);
1482 28880 : free_ETYPE_INFO2(&pa);
1483 28880 : if(ret)
1484 0 : return ret;
1485 28880 : ret = realloc_method_data(md);
1486 28880 : if(ret) {
1487 0 : free(buf);
1488 0 : return ret;
1489 : }
1490 28880 : md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO2;
1491 28880 : md->val[md->len - 1].padata_value.length = len;
1492 28880 : md->val[md->len - 1].padata_value.data = buf;
1493 28880 : return 0;
1494 : }
1495 :
1496 : /*
1497 : * Return 0 if the client have only older enctypes, this is for
1498 : * determining if the server should send ETYPE_INFO2 or not.
1499 : */
1500 :
1501 : static int
1502 11606 : newer_enctype_present(krb5_context context,
1503 : struct KDC_REQ_BODY_etype *etype_list)
1504 : {
1505 : size_t i;
1506 :
1507 12706 : for (i = 0; i < etype_list->len; i++) {
1508 12170 : if (!krb5_is_enctype_old(context, etype_list->val[i]))
1509 11070 : return 1;
1510 : }
1511 536 : return 0;
1512 : }
1513 :
1514 : static krb5_error_code
1515 11606 : get_pa_etype_info_both(krb5_context context,
1516 : krb5_kdc_configuration *config,
1517 : struct KDC_REQ_BODY_etype *etype_list,
1518 : METHOD_DATA *md, Key *ckey,
1519 : krb5_boolean include_salt)
1520 : {
1521 : krb5_error_code ret;
1522 :
1523 : /*
1524 : * Windows 2019 (and earlier versions) always sends the salt
1525 : * and Samba has testsuites that check this behaviour, so a
1526 : * Samba AD DC will set this flag to match the AS-REP packet
1527 : * more closely.
1528 : */
1529 11606 : if (config->force_include_pa_etype_salt)
1530 11606 : include_salt = TRUE;
1531 :
1532 : /*
1533 : * RFC4120 requires:
1534 : * When the AS server is to include pre-authentication data in a
1535 : * KRB-ERROR or in an AS-REP, it MUST use PA-ETYPE-INFO2, not
1536 : * PA-ETYPE-INFO, if the etype field of the client's AS-REQ lists
1537 : * at least one "newer" encryption type. Otherwise (when the etype
1538 : * field of the client's AS-REQ does not list any "newer" encryption
1539 : * types), it MUST send both PA-ETYPE-INFO2 and PA-ETYPE-INFO (both
1540 : * with an entry for each enctype). A "newer" enctype is any enctype
1541 : * first officially specified concurrently with or subsequent to the
1542 : * issue of this RFC. The enctypes DES, 3DES, or RC4 and any defined
1543 : * in [RFC1510] are not "newer" enctypes.
1544 : *
1545 : * It goes on to state:
1546 : * The preferred ordering of the "hint" pre-authentication data that
1547 : * affect client key selection is: ETYPE-INFO2, followed by ETYPE-INFO,
1548 : * followed by PW-SALT. As noted in Section 3.1.3, a KDC MUST NOT send
1549 : * ETYPE-INFO or PW-SALT when the client's AS-REQ includes at least one
1550 : * "newer" etype.
1551 : */
1552 :
1553 11606 : ret = get_pa_etype_info2(context, config, md, ckey, include_salt);
1554 11606 : if (ret)
1555 0 : return ret;
1556 :
1557 11606 : if (!newer_enctype_present(context, etype_list))
1558 536 : ret = get_pa_etype_info(context, config, md, ckey, include_salt);
1559 :
1560 11606 : return ret;
1561 : }
1562 :
1563 : /*
1564 : *
1565 : */
1566 :
1567 : void
1568 54055 : _log_astgs_req(astgs_request_t r, krb5_enctype setype)
1569 : {
1570 54055 : const KDC_REQ_BODY *b = &r->req.req_body;
1571 54055 : krb5_enctype cetype = r->reply_key.keytype;
1572 : krb5_error_code ret;
1573 : struct rk_strpool *p;
1574 54055 : struct rk_strpool *s = NULL;
1575 : char *str;
1576 : char *cet;
1577 : char *set;
1578 : size_t i;
1579 :
1580 : /*
1581 : * we are collecting ``p'' and ``s''. The former is a textual
1582 : * representation of the enctypes as strings which will be used
1583 : * for debugging. The latter is a terse comma separated list of
1584 : * the %d's of the enctypes to emit into our audit trail to
1585 : * conserve space in the logs.
1586 : */
1587 :
1588 54055 : p = rk_strpoolprintf(NULL, "%s", "Client supported enctypes: ");
1589 :
1590 351575 : for (i = 0; i < b->etype.len; i++) {
1591 297520 : ret = krb5_enctype_to_string(r->context, b->etype.val[i], &str);
1592 297520 : if (ret == 0) {
1593 297514 : p = rk_strpoolprintf(p, "%s", str);
1594 297514 : free(str);
1595 : } else
1596 6 : p = rk_strpoolprintf(p, "%d", b->etype.val[i]);
1597 297520 : if (p == NULL) {
1598 0 : rk_strpoolfree(s);
1599 0 : _kdc_r_log(r, 4, "out of memory");
1600 0 : return;
1601 : }
1602 297520 : s = rk_strpoolprintf(s, "%d", b->etype.val[i]);
1603 297520 : if (i + 1 < b->etype.len) {
1604 243465 : p = rk_strpoolprintf(p, ", ");
1605 243465 : s = rk_strpoolprintf(s, ",");
1606 : }
1607 : }
1608 54055 : if (p == NULL)
1609 0 : p = rk_strpoolprintf(p, "no encryption types");
1610 :
1611 54055 : str = rk_strpoolcollect(s);
1612 54055 : if (str)
1613 54055 : kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE, "etypes", "%s",
1614 : str);
1615 54055 : free(str);
1616 :
1617 54055 : ret = krb5_enctype_to_string(r->context, cetype, &cet);
1618 54055 : if(ret == 0) {
1619 54055 : ret = krb5_enctype_to_string(r->context, setype, &set);
1620 54055 : if (ret == 0) {
1621 54055 : p = rk_strpoolprintf(p, ", using %s/%s", cet, set);
1622 54055 : free(set);
1623 : }
1624 54055 : free(cet);
1625 : }
1626 54055 : if (ret != 0)
1627 0 : p = rk_strpoolprintf(p, ", using enctypes %d/%d",
1628 : cetype, setype);
1629 :
1630 54055 : str = rk_strpoolcollect(p);
1631 54055 : if (str)
1632 54055 : _kdc_r_log(r, 4, "%s", str);
1633 54055 : free(str);
1634 :
1635 54055 : kdc_audit_addkv((kdc_request_t)r, 0, "etype", "%d/%d", cetype, setype);
1636 :
1637 : {
1638 : char fixedstr[128];
1639 : int result;
1640 :
1641 54055 : result = unparse_flags(KDCOptions2int(b->kdc_options), asn1_KDCOptions_units(),
1642 : fixedstr, sizeof(fixedstr));
1643 54055 : if (result > 0) {
1644 49296 : _kdc_r_log(r, 4, "Requested flags: %s", fixedstr);
1645 49296 : kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE,
1646 : "flags", "%s", fixedstr);
1647 : }
1648 : }
1649 : }
1650 :
1651 : /*
1652 : * verify the flags on `client' and `server', returning 0
1653 : * if they are OK and generating an error messages and returning
1654 : * and error code otherwise.
1655 : */
1656 :
1657 : KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL
1658 55019 : kdc_check_flags(astgs_request_t r,
1659 : krb5_boolean is_as_req,
1660 : hdb_entry *client,
1661 : hdb_entry *server)
1662 : {
1663 55019 : if (client != NULL) {
1664 : /* check client */
1665 54970 : if (client->flags.locked_out) {
1666 0 : kdc_audit_addreason((kdc_request_t)r, "Client is locked out");
1667 0 : return KRB5KDC_ERR_CLIENT_REVOKED;
1668 : }
1669 :
1670 54970 : if (client->flags.invalid) {
1671 0 : kdc_audit_addreason((kdc_request_t)r,
1672 : "Client has invalid bit set");
1673 0 : return KRB5KDC_ERR_POLICY;
1674 : }
1675 :
1676 54970 : if (!client->flags.client) {
1677 0 : kdc_audit_addreason((kdc_request_t)r,
1678 : "Principal may not act as client");
1679 0 : return KRB5KDC_ERR_POLICY;
1680 : }
1681 :
1682 54970 : if (client->valid_start && *client->valid_start > kdc_time) {
1683 : char starttime_str[100];
1684 0 : krb5_format_time(r->context, *client->valid_start,
1685 : starttime_str, sizeof(starttime_str), TRUE);
1686 0 : kdc_audit_addreason((kdc_request_t)r, "Client not yet valid "
1687 : "until %s", starttime_str);
1688 0 : return KRB5KDC_ERR_CLIENT_NOTYET;
1689 : }
1690 :
1691 54970 : if (client->valid_end && *client->valid_end < kdc_time) {
1692 : char endtime_str[100];
1693 0 : krb5_format_time(r->context, *client->valid_end,
1694 : endtime_str, sizeof(endtime_str), TRUE);
1695 0 : kdc_audit_addreason((kdc_request_t)r, "Client expired at %s",
1696 : endtime_str);
1697 0 : return KRB5KDC_ERR_NAME_EXP;
1698 : }
1699 :
1700 54970 : if (client->flags.require_pwchange &&
1701 0 : (server == NULL || !server->flags.change_pw))
1702 0 : return KRB5KDC_ERR_KEY_EXPIRED;
1703 :
1704 54970 : if (client->pw_end && *client->pw_end < kdc_time
1705 8 : && (server == NULL || !server->flags.change_pw)) {
1706 : char pwend_str[100];
1707 0 : krb5_format_time(r->context, *client->pw_end,
1708 : pwend_str, sizeof(pwend_str), TRUE);
1709 0 : kdc_audit_addreason((kdc_request_t)r, "Client's key has expired "
1710 : "at %s", pwend_str);
1711 0 : return KRB5KDC_ERR_KEY_EXPIRED;
1712 : }
1713 : }
1714 :
1715 : /* check server */
1716 :
1717 55019 : if (server != NULL) {
1718 55019 : if (server->flags.locked_out) {
1719 0 : kdc_audit_addreason((kdc_request_t)r, "Server locked out");
1720 0 : return KRB5KDC_ERR_SERVICE_REVOKED;
1721 : }
1722 55019 : if (server->flags.invalid) {
1723 0 : kdc_audit_addreason((kdc_request_t)r,
1724 : "Server has invalid flag set");
1725 0 : return KRB5KDC_ERR_POLICY;
1726 : }
1727 55019 : if (!server->flags.server) {
1728 0 : kdc_audit_addreason((kdc_request_t)r,
1729 : "Principal may not act as server");
1730 0 : return KRB5KDC_ERR_POLICY;
1731 : }
1732 :
1733 55019 : if (!is_as_req && server->flags.initial) {
1734 0 : kdc_audit_addreason((kdc_request_t)r,
1735 : "AS-REQ is required for server");
1736 0 : return KRB5KDC_ERR_POLICY;
1737 : }
1738 :
1739 55019 : if (server->valid_start && *server->valid_start > kdc_time) {
1740 : char starttime_str[100];
1741 0 : krb5_format_time(r->context, *server->valid_start,
1742 : starttime_str, sizeof(starttime_str), TRUE);
1743 0 : kdc_audit_addreason((kdc_request_t)r, "Server not yet valid "
1744 : "until %s", starttime_str);
1745 0 : return KRB5KDC_ERR_SERVICE_NOTYET;
1746 : }
1747 :
1748 55019 : if (server->valid_end && *server->valid_end < kdc_time) {
1749 : char endtime_str[100];
1750 0 : krb5_format_time(r->context, *server->valid_end,
1751 : endtime_str, sizeof(endtime_str), TRUE);
1752 0 : kdc_audit_addreason((kdc_request_t)r, "Server expired at %s",
1753 : endtime_str);
1754 0 : return KRB5KDC_ERR_SERVICE_EXP;
1755 : }
1756 :
1757 55019 : if (server->pw_end && *server->pw_end < kdc_time) {
1758 : char pwend_str[100];
1759 0 : krb5_format_time(r->context, *server->pw_end,
1760 : pwend_str, sizeof(pwend_str), TRUE);
1761 0 : kdc_audit_addreason((kdc_request_t)r, "Server's key has expired "
1762 : "at %s", pwend_str);
1763 0 : return KRB5KDC_ERR_KEY_EXPIRED;
1764 : }
1765 : }
1766 55019 : return 0;
1767 : }
1768 :
1769 : /*
1770 : * Return TRUE if `from' is part of `addresses' taking into consideration
1771 : * the configuration variables that tells us how strict we should be about
1772 : * these checks
1773 : */
1774 :
1775 : krb5_boolean
1776 54208 : _kdc_check_addresses(astgs_request_t r, HostAddresses *addresses,
1777 : const struct sockaddr *from)
1778 : {
1779 54208 : krb5_kdc_configuration *config = r->config;
1780 : krb5_error_code ret;
1781 : krb5_address addr;
1782 : krb5_boolean result;
1783 54208 : krb5_boolean only_netbios = TRUE;
1784 : size_t i;
1785 :
1786 54208 : if (!config->check_ticket_addresses && !config->warn_ticket_addresses)
1787 0 : return TRUE;
1788 :
1789 : /*
1790 : * Fields of HostAddresses type are always OPTIONAL and should be non-
1791 : * empty, but we check for empty just in case as our compiler doesn't
1792 : * support size constraints on SEQUENCE OF.
1793 : */
1794 54208 : if (addresses == NULL || addresses->len == 0)
1795 54100 : return config->allow_null_ticket_addresses;
1796 :
1797 216 : for (i = 0; i < addresses->len; ++i) {
1798 108 : if (addresses->val[i].addr_type != KRB5_ADDRESS_NETBIOS) {
1799 0 : only_netbios = FALSE;
1800 : }
1801 : }
1802 :
1803 : /* Windows sends it's netbios name, which I can only assume is
1804 : * used for the 'allowed workstations' check. This is painful,
1805 : * but we still want to check IP addresses if they happen to be
1806 : * present.
1807 : */
1808 :
1809 108 : if(only_netbios)
1810 108 : return config->allow_null_ticket_addresses;
1811 :
1812 0 : ret = krb5_sockaddr2address (r->context, from, &addr);
1813 0 : if(ret)
1814 0 : return FALSE;
1815 :
1816 0 : result = krb5_address_search(r->context, &addr, addresses);
1817 0 : krb5_free_address (r->context, &addr);
1818 0 : return result;
1819 : }
1820 :
1821 : /*
1822 : *
1823 : */
1824 : krb5_error_code
1825 0 : _kdc_check_anon_policy(astgs_request_t r)
1826 : {
1827 0 : if (!r->config->allow_anonymous) {
1828 0 : kdc_audit_addreason((kdc_request_t)r,
1829 : "Anonymous tickets denied by local policy");
1830 0 : return KRB5KDC_ERR_POLICY;
1831 : }
1832 :
1833 0 : return 0;
1834 : }
1835 :
1836 : /*
1837 : * Determine whether the client requested a PAC be included
1838 : * or excluded explictly, or whether it doesn't care.
1839 : */
1840 :
1841 : static uint64_t
1842 18327 : get_pac_attributes(krb5_context context, KDC_REQ *req)
1843 : {
1844 : krb5_error_code ret;
1845 : PA_PAC_REQUEST pacreq;
1846 : const PA_DATA *pa;
1847 18327 : int i = 0;
1848 : uint32_t pac_attributes;
1849 :
1850 18327 : pa = _kdc_find_padata(req, &i, KRB5_PADATA_PA_PAC_REQUEST);
1851 18327 : if (pa == NULL)
1852 17923 : return KRB5_PAC_WAS_GIVEN_IMPLICITLY;
1853 :
1854 404 : ret = decode_PA_PAC_REQUEST(pa->padata_value.data,
1855 : pa->padata_value.length,
1856 : &pacreq,
1857 : NULL);
1858 404 : if (ret)
1859 0 : return KRB5_PAC_WAS_GIVEN_IMPLICITLY;
1860 :
1861 404 : pac_attributes = pacreq.include_pac ? KRB5_PAC_WAS_REQUESTED : 0;
1862 404 : free_PA_PAC_REQUEST(&pacreq);
1863 404 : return pac_attributes;
1864 : }
1865 :
1866 : /*
1867 : *
1868 : */
1869 :
1870 : static krb5_error_code
1871 18327 : generate_pac(astgs_request_t r, const Key *skey, const Key *tkey,
1872 : krb5_boolean is_tgs)
1873 : {
1874 : krb5_error_code ret;
1875 : krb5_data data;
1876 : uint16_t rodc_id;
1877 : krb5_principal client;
1878 18327 : krb5_const_principal canon_princ = NULL;
1879 :
1880 18327 : r->pac_attributes = get_pac_attributes(r->context, &r->req);
1881 18327 : kdc_audit_setkv_number((kdc_request_t)r, "pac_attributes",
1882 18327 : r->pac_attributes);
1883 :
1884 18327 : if (!is_tgs && !(r->pac_attributes & (KRB5_PAC_WAS_REQUESTED | KRB5_PAC_WAS_GIVEN_IMPLICITLY)))
1885 0 : return 0;
1886 :
1887 : /*
1888 : * When a PA mech does not use the client's long-term key, the PAC
1889 : * may include the client's long-term key (encrypted in the reply key)
1890 : * for use by other shared secret authentication protocols, e.g. NTLM.
1891 : * Validate a PA mech was actually used before doing this.
1892 : */
1893 :
1894 36654 : ret = _kdc_pac_generate(r,
1895 : r->client,
1896 : r->server,
1897 36654 : r->pa_used && !pa_used_flag_isset(r, PA_USES_LONG_TERM_KEY)
1898 : ? &r->reply_key : NULL,
1899 : r->pac_attributes,
1900 : &r->pac);
1901 18327 : if (ret) {
1902 0 : _kdc_r_log(r, 4, "PAC generation failed for -- %s",
1903 : r->cname);
1904 0 : return ret;
1905 : }
1906 18327 : if (r->pac == NULL)
1907 0 : return 0;
1908 :
1909 18327 : rodc_id = r->server->kvno >> 16;
1910 :
1911 : /* libkrb5 expects ticket and PAC client names to match */
1912 18327 : ret = _krb5_principalname2krb5_principal(r->context, &client,
1913 : r->et.cname, r->et.crealm);
1914 18327 : if (ret)
1915 0 : return ret;
1916 :
1917 : /*
1918 : * Include the canonical name of the principal in the authorization
1919 : * data, if the realms match (if they don't, then the KDC could
1920 : * impersonate any realm. Windows always canonicalizes the realm,
1921 : * but Heimdal permits aliases between realms.)
1922 : */
1923 18327 : if (krb5_realm_compare(r->context, client, r->canon_client_princ)) {
1924 18327 : char *cpn = NULL;
1925 :
1926 18327 : canon_princ = r->canon_client_princ;
1927 :
1928 18327 : (void) krb5_unparse_name(r->context, canon_princ, &cpn);
1929 18327 : kdc_audit_addkv((kdc_request_t)r, 0, "canon_client_name", "%s",
1930 18327 : cpn ? cpn : "<unknown>");
1931 18327 : krb5_xfree(cpn);
1932 : }
1933 :
1934 18327 : if (r->pa_used && r->pa_used->finalize_pac) {
1935 0 : ret = r->pa_used->finalize_pac(r);
1936 0 : if (ret)
1937 0 : return ret;
1938 : }
1939 :
1940 36654 : ret = _krb5_pac_sign(r->context,
1941 : r->pac,
1942 : r->et.authtime,
1943 : client,
1944 18327 : &skey->key, /* Server key */
1945 18327 : &tkey->key, /* TGS key */
1946 : rodc_id,
1947 : NULL, /* UPN */
1948 : canon_princ,
1949 : false, /* add_full_sig */
1950 : is_tgs ? &r->pac_attributes : NULL,
1951 : &data);
1952 18327 : krb5_free_principal(r->context, client);
1953 18327 : krb5_pac_free(r->context, r->pac);
1954 18327 : r->pac = NULL;
1955 18327 : if (ret) {
1956 0 : _kdc_r_log(r, 4, "PAC signing failed for -- %s",
1957 : r->cname);
1958 0 : return ret;
1959 : }
1960 :
1961 18327 : ret = _kdc_tkt_insert_pac(r->context, &r->et, &data);
1962 18327 : krb5_data_free(&data);
1963 :
1964 18327 : return ret;
1965 : }
1966 :
1967 : /*
1968 : *
1969 : */
1970 :
1971 : krb5_boolean
1972 82910 : _kdc_is_anonymous(krb5_context context, krb5_const_principal principal)
1973 : {
1974 82910 : return krb5_principal_is_anonymous(context, principal, KRB5_ANON_MATCH_ANY);
1975 : }
1976 :
1977 : /*
1978 : * Returns TRUE if principal is the unauthenticated anonymous identity,
1979 : * i.e. WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS. Unfortunately due to
1980 : * backwards compatibility logic in krb5_principal_is_anonymous() we
1981 : * have to use our own implementation.
1982 : */
1983 :
1984 : krb5_boolean
1985 32155 : _kdc_is_anonymous_pkinit(krb5_context context, krb5_const_principal principal)
1986 : {
1987 32155 : return _kdc_is_anonymous(context, principal) &&
1988 0 : strcmp(principal->realm, KRB5_ANON_REALM) == 0;
1989 : }
1990 :
1991 : static int
1992 11298 : require_preauth_p(astgs_request_t r)
1993 : {
1994 11298 : return r->config->require_preauth
1995 0 : || r->client->flags.require_preauth
1996 11298 : || r->server->flags.require_preauth;
1997 : }
1998 :
1999 :
2000 : /*
2001 : *
2002 : */
2003 :
2004 : static krb5_error_code
2005 17041 : add_enc_pa_rep(astgs_request_t r)
2006 : {
2007 : krb5_error_code ret;
2008 : krb5_crypto crypto;
2009 : Checksum checksum;
2010 : krb5_data cdata;
2011 : size_t len;
2012 :
2013 17041 : ret = krb5_crypto_init(r->context, &r->reply_key, 0, &crypto);
2014 17041 : if (ret)
2015 0 : return ret;
2016 :
2017 17041 : ret = krb5_create_checksum(r->context, crypto,
2018 : KRB5_KU_AS_REQ, 0,
2019 : r->request.data, r->request.length,
2020 : &checksum);
2021 17041 : krb5_crypto_destroy(r->context, crypto);
2022 17041 : if (ret)
2023 0 : return ret;
2024 :
2025 17041 : ASN1_MALLOC_ENCODE(Checksum, cdata.data, cdata.length,
2026 : &checksum, &len, ret);
2027 17041 : free_Checksum(&checksum);
2028 17041 : if (ret)
2029 0 : return ret;
2030 17041 : heim_assert(cdata.length == len, "ASN.1 internal error");
2031 :
2032 17041 : if (r->ek.encrypted_pa_data == NULL) {
2033 17041 : ALLOC(r->ek.encrypted_pa_data);
2034 17041 : if (r->ek.encrypted_pa_data == NULL)
2035 0 : return ENOMEM;
2036 : }
2037 17041 : ret = krb5_padata_add(r->context, r->ek.encrypted_pa_data,
2038 : KRB5_PADATA_REQ_ENC_PA_REP, cdata.data, cdata.length);
2039 17041 : if (ret)
2040 0 : return ret;
2041 :
2042 17041 : return krb5_padata_add(r->context, r->ek.encrypted_pa_data,
2043 : KRB5_PADATA_FX_FAST, NULL, 0);
2044 : }
2045 :
2046 : /*
2047 : * Add an authorization data element indicating that a synthetic
2048 : * principal was used, so that the TGS does not accidentally
2049 : * synthesize a non-synthetic principal that has since been deleted.
2050 : */
2051 : static krb5_error_code
2052 0 : add_synthetic_princ_ad(astgs_request_t r)
2053 : {
2054 : krb5_data data;
2055 :
2056 0 : krb5_data_zero(&data);
2057 :
2058 0 : return _kdc_tkt_add_if_relevant_ad(r->context, &r->et,
2059 : KRB5_AUTHDATA_SYNTHETIC_PRINC_USED,
2060 : &data);
2061 : }
2062 :
2063 : static krb5_error_code
2064 1186 : get_local_tgs(krb5_context context,
2065 : krb5_kdc_configuration *config,
2066 : krb5_const_realm realm,
2067 : HDB **krbtgtdb,
2068 : hdb_entry **krbtgt)
2069 : {
2070 : krb5_error_code ret;
2071 : krb5_principal tgs_name;
2072 :
2073 1186 : *krbtgtdb = NULL;
2074 1186 : *krbtgt = NULL;
2075 :
2076 1186 : ret = krb5_make_principal(context,
2077 : &tgs_name,
2078 : realm,
2079 : KRB5_TGS_NAME,
2080 : realm,
2081 : NULL);
2082 1186 : if (ret)
2083 0 : return ret;
2084 :
2085 1186 : ret = _kdc_db_fetch(context, config, tgs_name,
2086 : HDB_F_GET_KRBTGT, NULL, krbtgtdb, krbtgt);
2087 1186 : krb5_free_principal(context, tgs_name);
2088 :
2089 1186 : return ret;
2090 : }
2091 :
2092 : /*
2093 : *
2094 : */
2095 :
2096 : krb5_error_code
2097 32428 : _kdc_as_rep(astgs_request_t r)
2098 : {
2099 32428 : krb5_kdc_configuration *config = r->config;
2100 32428 : KDC_REQ *req = &r->req;
2101 32428 : const char *from = r->from;
2102 32428 : KDC_REQ_BODY *b = NULL;
2103 32428 : KDC_REP *rep = &r->rep;
2104 : KDCOptions f;
2105 : krb5_enctype setype;
2106 32428 : krb5_error_code ret = 0;
2107 : Key *skey;
2108 32428 : int found_pa = 0;
2109 32428 : int i, flags = HDB_F_FOR_AS_REQ;
2110 : const PA_DATA *pa;
2111 : krb5_boolean is_tgs;
2112 : const char *msg;
2113 : Key *krbtgt_key;
2114 :
2115 32428 : memset(rep, 0, sizeof(*rep));
2116 :
2117 32428 : ALLOC(rep->padata);
2118 32428 : if (rep->padata == NULL) {
2119 0 : ret = ENOMEM;
2120 0 : krb5_set_error_message(r->context, ret, N_("malloc: out of memory", ""));
2121 0 : goto out;
2122 : }
2123 :
2124 : /*
2125 : * Look for FAST armor and unwrap
2126 : */
2127 32428 : ret = _kdc_fast_unwrap_request(r, NULL, NULL);
2128 32428 : if (ret) {
2129 0 : _kdc_r_log(r, 1, "FAST unwrap request from %s failed: %d", from, ret);
2130 0 : goto out;
2131 : }
2132 :
2133 32428 : b = &req->req_body;
2134 32428 : f = b->kdc_options;
2135 :
2136 32428 : if (f.canonicalize)
2137 29879 : flags |= HDB_F_CANON;
2138 :
2139 32428 : if (b->sname == NULL) {
2140 0 : ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
2141 0 : _kdc_set_e_text(r, "No server in request");
2142 0 : goto out;
2143 : }
2144 :
2145 64856 : ret = _krb5_principalname2krb5_principal(r->context, &r->server_princ,
2146 32428 : *(b->sname), b->realm);
2147 32428 : if (!ret)
2148 32428 : ret = krb5_unparse_name(r->context, r->server_princ, &r->sname);
2149 32428 : if (ret) {
2150 0 : kdc_log(r->context, config, 2,
2151 : "AS_REQ malformed server name from %s", from);
2152 0 : goto out;
2153 : }
2154 :
2155 32428 : if (b->cname == NULL) {
2156 0 : ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
2157 0 : _kdc_set_e_text(r, "No client in request");
2158 0 : goto out;
2159 : }
2160 :
2161 64856 : ret = _krb5_principalname2krb5_principal(r->context, &r->client_princ,
2162 32428 : *(b->cname), b->realm);
2163 32428 : if (!ret)
2164 32428 : ret = krb5_unparse_name(r->context, r->client_princ, &r->cname);
2165 32428 : if (ret) {
2166 0 : kdc_log(r->context, config, 2,
2167 : "AS-REQ malformed client name from %s", from);
2168 0 : goto out;
2169 : }
2170 :
2171 32428 : kdc_log(r->context, config, 4, "AS-REQ %s from %s for %s",
2172 : r->cname, r->from, r->sname);
2173 :
2174 32428 : is_tgs = krb5_principal_is_krbtgt(r->context, r->server_princ);
2175 :
2176 32505 : if (_kdc_is_anonymous(r->context, r->client_princ) &&
2177 77 : !_kdc_is_anon_request(req)) {
2178 0 : kdc_log(r->context, config, 2, "Anonymous client w/o anonymous flag");
2179 0 : ret = KRB5KDC_ERR_BADOPTION;
2180 0 : goto out;
2181 : }
2182 :
2183 64856 : ret = _kdc_db_fetch(r->context, config, r->client_princ,
2184 32428 : HDB_F_GET_CLIENT | HDB_F_SYNTHETIC_OK | flags, NULL,
2185 : &r->clientdb, &r->client);
2186 32428 : switch (ret) {
2187 30105 : case 0: /* Success */
2188 30105 : break;
2189 1627 : case HDB_ERR_NOT_FOUND_HERE:
2190 1627 : kdc_log(r->context, config, 5, "client %s does not have secrets at this KDC, need to proxy",
2191 : r->cname);
2192 1627 : goto out;
2193 283 : case HDB_ERR_WRONG_REALM: {
2194 283 : char *fixed_client_name = NULL;
2195 :
2196 283 : ret = krb5_unparse_name(r->context, r->client->principal,
2197 : &fixed_client_name);
2198 283 : if (ret) {
2199 0 : goto out;
2200 : }
2201 :
2202 283 : kdc_log(r->context, config, 4, "WRONG_REALM - %s -> %s",
2203 : r->cname, fixed_client_name);
2204 283 : free(fixed_client_name);
2205 :
2206 283 : r->e_text = NULL;
2207 849 : ret = _kdc_fast_mk_error(r, r->rep.padata, r->armor_crypto,
2208 283 : &req->req_body,
2209 283 : r->error_code = KRB5_KDC_ERR_WRONG_REALM,
2210 283 : r->client->principal, r->server_princ,
2211 283 : NULL, NULL, r->reply);
2212 283 : goto out;
2213 : }
2214 413 : default:
2215 : {
2216 413 : msg = krb5_get_error_message(r->context, ret);
2217 413 : kdc_log(r->context, config, 4, "UNKNOWN -- %s: %s", r->cname, msg);
2218 413 : krb5_free_error_message(r->context, msg);
2219 413 : ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
2220 413 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
2221 : KDC_AUTH_EVENT_CLIENT_UNKNOWN);
2222 413 : goto out;
2223 : }
2224 : }
2225 60210 : ret = _kdc_db_fetch(r->context, config, r->server_princ,
2226 30105 : HDB_F_GET_SERVER | HDB_F_DELAY_NEW_KEYS |
2227 30105 : flags | (is_tgs ? HDB_F_GET_KRBTGT : 0),
2228 : NULL, &r->serverdb, &r->server);
2229 30105 : switch (ret) {
2230 30103 : case 0: /* Success */
2231 30103 : break;
2232 0 : case HDB_ERR_NOT_FOUND_HERE:
2233 0 : kdc_log(r->context, config, 5, "target %s does not have secrets at this KDC, need to proxy",
2234 : r->sname);
2235 0 : goto out;
2236 2 : default:
2237 2 : msg = krb5_get_error_message(r->context, ret);
2238 2 : kdc_log(r->context, config, 4, "UNKNOWN -- %s: %s", r->sname, msg);
2239 2 : krb5_free_error_message(r->context, msg);
2240 2 : ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
2241 2 : goto out;
2242 : }
2243 :
2244 : /*
2245 : * This has to be here (not later), because we need to have r->sessionetype
2246 : * set prior to calling pa_pkinit_validate(), which in turn calls
2247 : * _kdc_pk_mk_pa_reply(), during padata validation.
2248 : */
2249 :
2250 : /*
2251 : * Select an enctype for the to-be-issued ticket's session key using the
2252 : * intersection of the client's requested enctypes and the server's (like a
2253 : * root krbtgt, but not necessarily) etypes from its HDB entry.
2254 : */
2255 60206 : ret = _kdc_find_session_etype(r, b->etype.val, b->etype.len,
2256 30103 : r->server, &r->sessionetype);
2257 30103 : if (ret) {
2258 84 : kdc_log(r->context, config, 4,
2259 : "Client (%s) from %s has no common enctypes with KDC "
2260 : "to use for the session key",
2261 : r->cname, from);
2262 84 : goto out;
2263 : }
2264 :
2265 : /*
2266 : * Pre-auth processing
2267 : */
2268 :
2269 30019 : if(req->padata){
2270 : unsigned int n;
2271 :
2272 28654 : log_patypes(r, req->padata);
2273 :
2274 : /* Check if preauth matching */
2275 :
2276 231215 : for (n = 0; !found_pa && n < sizeof(pat) / sizeof(pat[0]); n++) {
2277 202869 : if (pat[n].validate == NULL)
2278 97040 : continue;
2279 105829 : if (r->armor_crypto == NULL && (pat[n].flags & PA_REQ_FAST))
2280 9932 : continue;
2281 :
2282 95897 : kdc_log(r->context, config, 5,
2283 : "Looking for %s pa-data -- %s", pat[n].name, r->cname);
2284 95897 : i = 0;
2285 95897 : pa = _kdc_find_padata(req, &i, pat[n].type);
2286 95897 : if (pa) {
2287 18721 : if (r->client->flags.synthetic &&
2288 0 : !(pat[n].flags & PA_SYNTHETIC_OK)) {
2289 0 : kdc_log(r->context, config, 4, "UNKNOWN -- %s", r->cname);
2290 0 : ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
2291 0 : goto out;
2292 : }
2293 18721 : kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_VIS, "pa", "%s",
2294 : pat[n].name);
2295 18721 : ret = pat[n].validate(r, pa);
2296 18721 : if (ret != 0) {
2297 : krb5_error_code ret2;
2298 308 : Key *ckey = NULL;
2299 : krb5_boolean default_salt;
2300 :
2301 616 : if (ret != KRB5_KDC_ERR_MORE_PREAUTH_DATA_REQUIRED &&
2302 308 : !kdc_audit_getkv((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT))
2303 0 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
2304 : KDC_AUTH_EVENT_PREAUTH_FAILED);
2305 :
2306 : /*
2307 : * If there is a client key, send ETYPE_INFO{,2}
2308 : */
2309 616 : ret2 = _kdc_find_etype(r, KFE_IS_PREAUTH|KFE_USE_CLIENT,
2310 308 : b->etype.val, b->etype.len,
2311 : NULL, &ckey, &default_salt);
2312 308 : if (ret2 == 0) {
2313 308 : ret2 = get_pa_etype_info_both(r->context, config, &b->etype,
2314 : r->rep.padata, ckey, !default_salt);
2315 308 : if (ret2 != 0)
2316 0 : ret = ret2;
2317 : }
2318 308 : goto out;
2319 : }
2320 18413 : if (!kdc_audit_getkv((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT))
2321 0 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
2322 : KDC_AUTH_EVENT_PREAUTH_SUCCEEDED);
2323 18413 : kdc_log(r->context, config, 4,
2324 : "%s pre-authentication succeeded -- %s",
2325 : pat[n].name, r->cname);
2326 18413 : found_pa = 1;
2327 18413 : r->pa_used = &pat[n];
2328 18413 : r->et.flags.pre_authent = 1;
2329 : }
2330 : }
2331 : }
2332 :
2333 29711 : if (found_pa == 0) {
2334 11298 : Key *ckey = NULL;
2335 : size_t n;
2336 : krb5_boolean default_salt;
2337 :
2338 11298 : if (r->client->flags.synthetic) {
2339 0 : kdc_log(r->context, config, 4, "UNKNOWN -- %s", r->cname);
2340 0 : ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
2341 11298 : goto out;
2342 : }
2343 :
2344 135576 : for (n = 0; n < sizeof(pat) / sizeof(pat[0]); n++) {
2345 124278 : if ((pat[n].flags & PA_ANNOUNCE) == 0)
2346 45192 : continue;
2347 :
2348 79086 : if (!r->armor_crypto && (pat[n].flags & PA_REQ_FAST))
2349 11297 : continue;
2350 67789 : if (pat[n].type == KRB5_PADATA_ENC_TIMESTAMP) {
2351 11298 : if (r->armor_crypto && !r->config->enable_armored_pa_enc_timestamp)
2352 1 : continue;
2353 11297 : if (!r->armor_crypto && !r->config->enable_unarmored_pa_enc_timestamp)
2354 0 : continue;
2355 : }
2356 :
2357 67788 : ret = krb5_padata_add(r->context, r->rep.padata,
2358 : pat[n].type, NULL, 0);
2359 67788 : if (ret)
2360 0 : goto out;
2361 : }
2362 :
2363 : /*
2364 : * If there is a client key, send ETYPE_INFO{,2}
2365 : */
2366 22596 : ret = _kdc_find_etype(r, KFE_IS_PREAUTH|KFE_USE_CLIENT,
2367 11298 : b->etype.val, b->etype.len,
2368 : NULL, &ckey, &default_salt);
2369 11298 : if (ret == 0) {
2370 11298 : ret = get_pa_etype_info_both(r->context, config, &b->etype,
2371 : r->rep.padata, ckey, !default_salt);
2372 11298 : if (ret)
2373 0 : goto out;
2374 : }
2375 :
2376 : /*
2377 : * send requre preauth is its required or anon is requested,
2378 : * anon is today only allowed via preauth mechanisms.
2379 : */
2380 11298 : if (require_preauth_p(r) || _kdc_is_anon_request(&r->req)) {
2381 11298 : ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
2382 11298 : _kdc_set_e_text(r, "Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ");
2383 11298 : goto out;
2384 : }
2385 :
2386 0 : if (ckey == NULL) {
2387 0 : ret = KRB5KDC_ERR_CLIENT_NOTYET;
2388 0 : _kdc_set_e_text(r, "Doesn't have a client key available");
2389 0 : goto out;
2390 : }
2391 0 : krb5_free_keyblock_contents(r->context, &r->reply_key);
2392 0 : ret = krb5_copy_keyblock_contents(r->context, &ckey->key, &r->reply_key);
2393 0 : if (ret)
2394 0 : goto out;
2395 : }
2396 :
2397 18413 : r->canon_client_princ = r->client->principal;
2398 :
2399 : /*
2400 : * Verify flags after the user been required to prove its identity
2401 : * with in a preauth mech.
2402 : */
2403 :
2404 18413 : ret = _kdc_check_access(r);
2405 18413 : if(ret)
2406 4 : goto out;
2407 :
2408 18409 : if (_kdc_is_anon_request(&r->req)) {
2409 0 : ret = _kdc_check_anon_policy(r);
2410 0 : if (ret) {
2411 0 : _kdc_set_e_text(r, "Anonymous ticket requests are disabled");
2412 0 : goto out;
2413 : }
2414 :
2415 0 : r->et.flags.anonymous = 1;
2416 : }
2417 :
2418 18409 : kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
2419 : KDC_AUTH_EVENT_CLIENT_AUTHORIZED);
2420 :
2421 : /*
2422 : * Select the best encryption type for the KDC with out regard to
2423 : * the client since the client never needs to read that data.
2424 : */
2425 :
2426 18409 : ret = _kdc_get_preferred_key(r->context, config,
2427 18409 : r->server, r->sname,
2428 : &setype, &skey);
2429 18409 : if(ret)
2430 82 : goto out;
2431 :
2432 : /* If server is not krbtgt, fetch local krbtgt key for signing authdata */
2433 18327 : if (is_tgs) {
2434 17141 : krbtgt_key = skey;
2435 : } else {
2436 1186 : ret = get_local_tgs(r->context, config, r->server_princ->realm,
2437 : &r->krbtgtdb, &r->krbtgt);
2438 1186 : if (ret)
2439 0 : goto out;
2440 :
2441 1186 : ret = _kdc_get_preferred_key(r->context, config, r->krbtgt,
2442 1186 : r->server_princ->realm,
2443 : NULL, &krbtgt_key);
2444 1186 : if (ret)
2445 0 : goto out;
2446 : }
2447 :
2448 18327 : if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey) {
2449 0 : ret = KRB5KDC_ERR_BADOPTION;
2450 0 : _kdc_set_e_text(r, "Bad KDC options");
2451 0 : goto out;
2452 : }
2453 :
2454 : /*
2455 : * Build reply
2456 : */
2457 18327 : rep->pvno = 5;
2458 18327 : rep->msg_type = krb_as_rep;
2459 :
2460 36654 : if (!config->historical_anon_realm &&
2461 18327 : _kdc_is_anonymous(r->context, r->client_princ)) {
2462 0 : Realm anon_realm = KRB5_ANON_REALM;
2463 0 : ret = copy_Realm(&anon_realm, &rep->crealm);
2464 18327 : } else if (f.canonicalize || r->client->flags.force_canonicalize)
2465 18327 : ret = copy_Realm(&r->canon_client_princ->realm, &rep->crealm);
2466 : else
2467 0 : ret = copy_Realm(&r->client_princ->realm, &rep->crealm);
2468 18327 : if (ret)
2469 0 : goto out;
2470 18327 : if (r->et.flags.anonymous)
2471 0 : ret = _kdc_make_anonymous_principalname(&rep->cname);
2472 18327 : else if (f.canonicalize || r->client->flags.force_canonicalize)
2473 18327 : ret = _krb5_principal2principalname(&rep->cname, r->canon_client_princ);
2474 : else
2475 0 : ret = _krb5_principal2principalname(&rep->cname, r->client_princ);
2476 18327 : if (ret)
2477 0 : goto out;
2478 :
2479 18327 : rep->ticket.tkt_vno = 5;
2480 18327 : if (f.canonicalize || r->server->flags.force_canonicalize)
2481 18321 : ret = copy_Realm(&r->server->principal->realm, &rep->ticket.realm);
2482 : else
2483 6 : ret = copy_Realm(&r->server_princ->realm, &rep->ticket.realm);
2484 18327 : if (ret)
2485 0 : goto out;
2486 18327 : if (f.canonicalize || r->server->flags.force_canonicalize)
2487 18321 : _krb5_principal2principalname(&rep->ticket.sname,
2488 18321 : r->server->principal);
2489 : else
2490 6 : _krb5_principal2principalname(&rep->ticket.sname,
2491 6 : r->server_princ);
2492 : /* java 1.6 expects the name to be the same type, lets allow that
2493 : * uncomplicated name-types, when f.canonicalize is not set (to
2494 : * match Windows Server 1709). */
2495 : #define CNT(sp,t) (((sp)->sname->name_type) == KRB5_NT_##t)
2496 18327 : if (!f.canonicalize
2497 848 : && (CNT(b, UNKNOWN) || CNT(b, PRINCIPAL) || CNT(b, SRV_INST) || CNT(b, SRV_HST) || CNT(b, SRV_XHST))) {
2498 848 : rep->ticket.sname.name_type = b->sname->name_type;
2499 : }
2500 : #undef CNT
2501 :
2502 18327 : r->et.flags.initial = 1;
2503 18327 : if(r->client->flags.forwardable && r->server->flags.forwardable)
2504 18327 : r->et.flags.forwardable = f.forwardable;
2505 18327 : if(r->client->flags.proxiable && r->server->flags.proxiable)
2506 18321 : r->et.flags.proxiable = f.proxiable;
2507 6 : else if (f.proxiable) {
2508 0 : _kdc_set_e_text(r, "Ticket may not be proxiable");
2509 0 : ret = KRB5KDC_ERR_POLICY;
2510 0 : goto out;
2511 : }
2512 18327 : if(r->client->flags.postdate && r->server->flags.postdate)
2513 0 : r->et.flags.may_postdate = f.allow_postdate;
2514 18327 : else if (f.allow_postdate){
2515 0 : _kdc_set_e_text(r, "Ticket may not be postdate");
2516 0 : ret = KRB5KDC_ERR_POLICY;
2517 0 : goto out;
2518 : }
2519 :
2520 18327 : if (b->addresses)
2521 90 : kdc_audit_addaddrs((kdc_request_t)r, b->addresses, "reqaddrs");
2522 :
2523 : /* check for valid set of addresses */
2524 18327 : if (!_kdc_check_addresses(r, b->addresses, r->addr)) {
2525 0 : if (r->config->warn_ticket_addresses) {
2526 0 : kdc_audit_setkv_bool((kdc_request_t)r, "wrongaddr", TRUE);
2527 : } else {
2528 0 : _kdc_set_e_text(r, "Request from wrong address");
2529 0 : ret = KRB5KRB_AP_ERR_BADADDR;
2530 0 : goto out;
2531 : }
2532 : }
2533 :
2534 18327 : ret = copy_PrincipalName(&rep->cname, &r->et.cname);
2535 18327 : if (ret)
2536 0 : goto out;
2537 18327 : ret = copy_Realm(&rep->crealm, &r->et.crealm);
2538 18327 : if (ret)
2539 0 : goto out;
2540 :
2541 : {
2542 : time_t start;
2543 : time_t t;
2544 :
2545 18327 : start = r->et.authtime = kdc_time;
2546 :
2547 18327 : if(f.postdated && req->req_body.from){
2548 0 : ALLOC(r->et.starttime);
2549 0 : start = *r->et.starttime = *req->req_body.from;
2550 0 : r->et.flags.invalid = 1;
2551 0 : r->et.flags.postdated = 1; /* XXX ??? */
2552 : }
2553 18327 : _kdc_fix_time(&b->till);
2554 18327 : t = *b->till;
2555 :
2556 : /* be careful not overflowing */
2557 :
2558 : /*
2559 : * Pre-auth can override r->client->max_life if configured.
2560 : *
2561 : * See pre-auth methods, specifically PKINIT, which can get or derive
2562 : * this from the client's certificate.
2563 : */
2564 18327 : if (r->pa_max_life > 0)
2565 0 : t = rk_time_add(start, min(rk_time_sub(t, start), r->pa_max_life));
2566 18327 : else if (r->client->max_life && *r->client->max_life)
2567 18327 : t = rk_time_add(start, min(rk_time_sub(t, start),
2568 : *r->client->max_life));
2569 :
2570 18327 : if (r->server->max_life && *r->server->max_life)
2571 18321 : t = rk_time_add(start, min(rk_time_sub(t, start),
2572 : *r->server->max_life));
2573 :
2574 : /* Pre-auth can bound endtime as well */
2575 18327 : if (r->pa_endtime > 0)
2576 0 : t = rk_time_add(start, min(rk_time_sub(t, start), r->pa_endtime));
2577 : #if 0
2578 : t = min(t, rk_time_add(start, realm->max_life));
2579 : #endif
2580 18327 : r->et.endtime = t;
2581 18327 : if(f.renewable_ok && r->et.endtime < *b->till){
2582 1 : f.renewable = 1;
2583 1 : if(b->rtime == NULL){
2584 1 : ALLOC(b->rtime);
2585 1 : *b->rtime = 0;
2586 : }
2587 1 : if(*b->rtime < *b->till)
2588 1 : *b->rtime = *b->till;
2589 : }
2590 18327 : if(f.renewable && b->rtime){
2591 2041 : t = *b->rtime;
2592 2041 : if(t == 0)
2593 0 : t = MAX_TIME;
2594 2041 : if(r->client->max_renew && *r->client->max_renew)
2595 2041 : t = rk_time_add(start, min(rk_time_sub(t, start),
2596 : *r->client->max_renew));
2597 2041 : if(r->server->max_renew && *r->server->max_renew)
2598 2041 : t = rk_time_add(start, min(rk_time_sub(t, start),
2599 : *r->server->max_renew));
2600 : #if 0
2601 : t = min(t, rk_time_add(start, realm->max_renew));
2602 : #endif
2603 2041 : ALLOC(r->et.renew_till);
2604 2041 : *r->et.renew_till = t;
2605 2041 : r->et.flags.renewable = 1;
2606 : }
2607 : }
2608 :
2609 18327 : if(b->addresses){
2610 90 : ALLOC(r->et.caddr);
2611 90 : copy_HostAddresses(b->addresses, r->et.caddr);
2612 : }
2613 :
2614 18327 : r->et.transited.tr_type = domain_X500_Compress;
2615 18327 : krb5_data_zero(&r->et.transited.contents);
2616 :
2617 : /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
2618 : * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
2619 : * incapable of correctly decoding SEQUENCE OF's of zero length.
2620 : *
2621 : * To fix this, always send at least one no-op last_req
2622 : *
2623 : * If there's a pw_end or valid_end we will use that,
2624 : * otherwise just a dummy lr.
2625 : */
2626 18327 : r->ek.last_req.val = malloc(2 * sizeof(*r->ek.last_req.val));
2627 18327 : if (r->ek.last_req.val == NULL) {
2628 0 : ret = ENOMEM;
2629 0 : goto out;
2630 : }
2631 18327 : r->ek.last_req.len = 0;
2632 18327 : if (r->client->pw_end
2633 16221 : && (config->kdc_warn_pwexpire == 0
2634 0 : || kdc_time + config->kdc_warn_pwexpire >= *r->client->pw_end)) {
2635 16221 : r->ek.last_req.val[r->ek.last_req.len].lr_type = LR_PW_EXPTIME;
2636 16221 : r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->pw_end;
2637 16221 : ++r->ek.last_req.len;
2638 : }
2639 18327 : if (r->client->valid_end) {
2640 0 : r->ek.last_req.val[r->ek.last_req.len].lr_type = LR_ACCT_EXPTIME;
2641 0 : r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->valid_end;
2642 0 : ++r->ek.last_req.len;
2643 : }
2644 18327 : if (r->ek.last_req.len == 0) {
2645 2106 : r->ek.last_req.val[r->ek.last_req.len].lr_type = LR_NONE;
2646 2106 : r->ek.last_req.val[r->ek.last_req.len].lr_value = 0;
2647 2106 : ++r->ek.last_req.len;
2648 : }
2649 18327 : r->ek.nonce = b->nonce;
2650 18327 : if (r->client->valid_end || r->client->pw_end) {
2651 16221 : ALLOC(r->ek.key_expiration);
2652 32442 : if (r->client->valid_end) {
2653 0 : if (r->client->pw_end)
2654 0 : *r->ek.key_expiration = min(*r->client->valid_end,
2655 : *r->client->pw_end);
2656 : else
2657 0 : *r->ek.key_expiration = *r->client->valid_end;
2658 : } else
2659 16221 : *r->ek.key_expiration = *r->client->pw_end;
2660 : } else
2661 2106 : r->ek.key_expiration = NULL;
2662 18327 : r->ek.flags = r->et.flags;
2663 18327 : r->ek.authtime = r->et.authtime;
2664 18327 : if (r->et.starttime) {
2665 0 : ALLOC(r->ek.starttime);
2666 0 : *r->ek.starttime = *r->et.starttime;
2667 : }
2668 18327 : r->ek.endtime = r->et.endtime;
2669 18327 : if (r->et.renew_till) {
2670 2041 : ALLOC(r->ek.renew_till);
2671 2041 : *r->ek.renew_till = *r->et.renew_till;
2672 : }
2673 18327 : ret = copy_Realm(&rep->ticket.realm, &r->ek.srealm);
2674 18327 : if (ret)
2675 0 : goto out;
2676 18327 : ret = copy_PrincipalName(&rep->ticket.sname, &r->ek.sname);
2677 18327 : if (ret)
2678 0 : goto out;
2679 18327 : if(r->et.caddr){
2680 90 : ALLOC(r->ek.caddr);
2681 90 : copy_HostAddresses(r->et.caddr, r->ek.caddr);
2682 : }
2683 :
2684 : /*
2685 : * Check and session and reply keys
2686 : */
2687 :
2688 18327 : if (r->session_key.keytype == ETYPE_NULL) {
2689 18327 : ret = krb5_generate_random_keyblock(r->context, r->sessionetype, &r->session_key);
2690 18327 : if (ret)
2691 0 : goto out;
2692 : }
2693 :
2694 18327 : if (r->reply_key.keytype == ETYPE_NULL) {
2695 0 : _kdc_set_e_text(r, "Client have no reply key");
2696 0 : ret = KRB5KDC_ERR_CLIENT_NOTYET;
2697 0 : goto out;
2698 : }
2699 :
2700 18327 : ret = copy_EncryptionKey(&r->session_key, &r->et.key);
2701 18327 : if (ret)
2702 0 : goto out;
2703 :
2704 18327 : ret = copy_EncryptionKey(&r->session_key, &r->ek.key);
2705 18327 : if (ret)
2706 0 : goto out;
2707 :
2708 : /* Add the PAC */
2709 18327 : if (!r->et.flags.anonymous) {
2710 18327 : ret = generate_pac(r, skey, krbtgt_key, is_tgs);
2711 18327 : if (ret)
2712 0 : goto out;
2713 : }
2714 :
2715 18327 : if (r->client->flags.synthetic) {
2716 0 : ret = add_synthetic_princ_ad(r);
2717 0 : if (ret)
2718 0 : goto out;
2719 : }
2720 :
2721 18327 : _kdc_log_timestamp(r, "AS-REQ", r->et.authtime,
2722 : r->et.starttime, r->et.endtime,
2723 : r->et.renew_till);
2724 :
2725 18327 : _log_astgs_req(r, setype);
2726 :
2727 : /*
2728 : * We always say we support FAST/enc-pa-rep
2729 : */
2730 :
2731 18327 : r->et.flags.enc_pa_rep = r->ek.flags.enc_pa_rep = 1;
2732 :
2733 : /*
2734 : * update reply-key with strengthen-key
2735 : */
2736 :
2737 18327 : ret = _kdc_fast_strengthen_reply_key(r);
2738 18327 : if (ret)
2739 0 : goto out;
2740 :
2741 : /*
2742 : * Add REQ_ENC_PA_REP if client supports it
2743 : */
2744 :
2745 18327 : i = 0;
2746 18327 : pa = _kdc_find_padata(req, &i, KRB5_PADATA_REQ_ENC_PA_REP);
2747 18327 : if (pa) {
2748 :
2749 17041 : ret = add_enc_pa_rep(r);
2750 17041 : if (ret) {
2751 0 : msg = krb5_get_error_message(r->context, ret);
2752 0 : _kdc_r_log(r, 4, "add_enc_pa_rep failed: %s: %d", msg, ret);
2753 0 : krb5_free_error_message(r->context, msg);
2754 0 : goto out;
2755 : }
2756 : }
2757 :
2758 : /*
2759 : * Last chance for plugins to update reply
2760 : */
2761 18327 : ret = _kdc_finalize_reply(r);
2762 18327 : if (ret)
2763 0 : goto out;
2764 :
2765 : /*
2766 : * Don't send kvno from client entry if the pre-authentication
2767 : * mechanism replaced the reply key.
2768 : */
2769 :
2770 73308 : ret = _kdc_encode_reply(r->context, config,
2771 18327 : r, req->req_body.nonce, setype,
2772 18327 : r->server->kvno, &skey->key,
2773 36654 : pa_used_flag_isset(r, PA_REPLACE_REPLY_KEY) ? 0 : r->client->kvno,
2774 18327 : 0, r->reply);
2775 18327 : if (ret)
2776 0 : goto out;
2777 :
2778 : /*
2779 : * Check if message too large
2780 : */
2781 26061 : if (r->datagram_reply && r->reply->length > config->max_datagram_reply_length) {
2782 7734 : krb5_data_free(r->reply);
2783 7734 : ret = KRB5KRB_ERR_RESPONSE_TOO_BIG;
2784 7734 : _kdc_set_e_text(r, "Reply packet too large");
2785 : }
2786 :
2787 43021 : out:
2788 32428 : r->error_code = ret;
2789 : {
2790 32428 : krb5_error_code ret2 = _kdc_audit_request(r);
2791 32428 : if (ret2) {
2792 26 : krb5_data_free(r->reply);
2793 26 : ret = ret2;
2794 : }
2795 : }
2796 :
2797 : /*
2798 : * In case of a non proxy error, build an error message.
2799 : */
2800 32428 : if (ret != 0 && ret != HDB_ERR_NOT_FOUND_HERE && r->reply->length == 0) {
2801 19899 : kdc_log(r->context, config, 5, "as-req: sending error: %d to client", ret);
2802 39798 : ret = _kdc_fast_mk_error(r,
2803 : r->rep.padata,
2804 : r->armor_crypto,
2805 19899 : &req->req_body,
2806 : r->error_code,
2807 : r->client_princ,
2808 : r->server_princ,
2809 : NULL, NULL,
2810 19899 : r->reply);
2811 : }
2812 :
2813 32428 : if (r->pa_used && r->pa_used->cleanup)
2814 0 : r->pa_used->cleanup(r);
2815 :
2816 32428 : free_AS_REP(&r->rep);
2817 32428 : free_EncTicketPart(&r->et);
2818 32428 : free_EncKDCRepPart(&r->ek);
2819 32428 : _kdc_free_fast_state(&r->fast);
2820 :
2821 32428 : if (r->client_princ) {
2822 32428 : krb5_free_principal(r->context, r->client_princ);
2823 32428 : r->client_princ = NULL;
2824 : }
2825 32428 : if (r->server_princ){
2826 32428 : krb5_free_principal(r->context, r->server_princ);
2827 32428 : r->server_princ = NULL;
2828 : }
2829 32428 : if (r->client)
2830 30388 : _kdc_free_ent(r->context, r->clientdb, r->client);
2831 32428 : if (r->server)
2832 30103 : _kdc_free_ent(r->context, r->serverdb, r->server);
2833 32428 : if (r->krbtgt)
2834 1186 : _kdc_free_ent(r->context, r->krbtgtdb, r->krbtgt);
2835 32428 : if (r->armor_crypto) {
2836 2 : krb5_crypto_destroy(r->context, r->armor_crypto);
2837 2 : r->armor_crypto = NULL;
2838 : }
2839 32428 : if (r->armor_ticket)
2840 2 : krb5_free_ticket(r->context, r->armor_ticket);
2841 32428 : if (r->armor_server)
2842 2 : _kdc_free_ent(r->context, r->armor_serverdb, r->armor_server);
2843 32428 : krb5_free_keyblock_contents(r->context, &r->reply_key);
2844 32428 : krb5_free_keyblock_contents(r->context, &r->session_key);
2845 32428 : krb5_free_keyblock_contents(r->context, &r->strengthen_key);
2846 32428 : krb5_pac_free(r->context, r->pac);
2847 :
2848 32428 : return ret;
2849 : }
|