1 /* $NetBSD: kerberos5.c,v 1.9 2023/06/19 21:41:41 christos Exp $ */
2
3 /*
4 * Copyright (c) 1997-2007 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * 3. Neither the name of the Institute nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 #include "kdc_locl.h"
37
38 #define MAX_TIME ((time_t)((1U << 31) - 1))
39
40 void
_kdc_fix_time(time_t ** t)41 _kdc_fix_time(time_t **t)
42 {
43 if(*t == NULL){
44 ALLOC(*t);
45 **t = MAX_TIME;
46 }
47 if(**t == 0) **t = MAX_TIME; /* fix for old clients */
48 }
49
50 static int
realloc_method_data(METHOD_DATA * md)51 realloc_method_data(METHOD_DATA *md)
52 {
53 PA_DATA *pa;
54 pa = realloc(md->val, (md->len + 1) * sizeof(*md->val));
55 if(pa == NULL)
56 return ENOMEM;
57 md->val = pa;
58 md->len++;
59 return 0;
60 }
61
62 static void
set_salt_padata(METHOD_DATA * md,Salt * salt)63 set_salt_padata(METHOD_DATA *md, Salt *salt)
64 {
65 if (salt) {
66 realloc_method_data(md);
67 md->val[md->len - 1].padata_type = salt->type;
68 der_copy_octet_string(&salt->salt,
69 &md->val[md->len - 1].padata_value);
70 }
71 }
72
73 const PA_DATA*
_kdc_find_padata(const KDC_REQ * req,int * start,int type)74 _kdc_find_padata(const KDC_REQ *req, int *start, int type)
75 {
76 if (req->padata == NULL)
77 return NULL;
78
79 while((size_t)*start < req->padata->len){
80 (*start)++;
81 if(req->padata->val[*start - 1].padata_type == (unsigned)type)
82 return &req->padata->val[*start - 1];
83 }
84 return NULL;
85 }
86
87 /*
88 * This is a hack to allow predefined weak services, like afs to
89 * still use weak types
90 */
91
92 krb5_boolean
_kdc_is_weak_exception(krb5_principal principal,krb5_enctype etype)93 _kdc_is_weak_exception(krb5_principal principal, krb5_enctype etype)
94 {
95 if (principal->name.name_string.len > 0 &&
96 strcmp(principal->name.name_string.val[0], "afs") == 0 &&
97 (etype == (krb5_enctype)ETYPE_DES_CBC_CRC
98 || etype == (krb5_enctype)ETYPE_DES_CBC_MD4
99 || etype == (krb5_enctype)ETYPE_DES_CBC_MD5))
100 return TRUE;
101 return FALSE;
102 }
103
104
105 /*
106 * Detect if `key' is the using the the precomputed `default_salt'.
107 */
108
109 static krb5_boolean
is_default_salt_p(const krb5_salt * default_salt,const Key * key)110 is_default_salt_p(const krb5_salt *default_salt, const Key *key)
111 {
112 if (key->salt == NULL)
113 return TRUE;
114 if (default_salt->salttype != key->salt->type)
115 return FALSE;
116 if (krb5_data_cmp(&default_salt->saltvalue, &key->salt->salt))
117 return FALSE;
118 return TRUE;
119 }
120
121 /*
122 * Detect if `key' is the using the the precomputed `default_salt'
123 * (for des-cbc-crc) or any salt otherwise.
124 *
125 * This is for avoiding Kerberos v4 (yes really) keys in AS-REQ as
126 * that salt is strange, and a buggy client will try to use the
127 * principal as the salt and not the returned value.
128 */
129
130 static krb5_boolean
is_good_salt_p(const krb5_salt * default_salt,const Key * key)131 is_good_salt_p(const krb5_salt *default_salt, const Key *key)
132 {
133 if (key->key.keytype == KRB5_ENCTYPE_DES_CBC_CRC)
134 return is_default_salt_p(default_salt, key);
135
136 return TRUE;
137 }
138
139 krb5_boolean
_kdc_is_anon_request(const KDC_REQ * req)140 _kdc_is_anon_request(const KDC_REQ *req)
141 {
142 const KDC_REQ_BODY *b = &req->req_body;
143
144 /*
145 * Versions of Heimdal from 0.9rc1 through 1.50 use bit 14 instead
146 * of 16 for request_anonymous, as indicated in the anonymous draft
147 * prior to version 11. Bit 14 is assigned to S4U2Proxy, but S4U2Proxy
148 * requests are only sent to the TGS and, in any case, would have an
149 * additional ticket present.
150 */
151 return b->kdc_options.request_anonymous ||
152 (b->kdc_options.cname_in_addl_tkt && !b->additional_tickets);
153 }
154
155 /*
156 * return the first appropriate key of `princ' in `ret_key'. Look for
157 * all the etypes in (`etypes', `len'), stopping as soon as we find
158 * one, but preferring one that has default salt.
159 */
160
161 krb5_error_code
_kdc_find_etype(krb5_context context,krb5_boolean use_strongest_session_key,krb5_boolean is_preauth,hdb_entry_ex * princ,krb5_enctype * etypes,unsigned len,krb5_enctype * ret_enctype,Key ** ret_key)162 _kdc_find_etype(krb5_context context, krb5_boolean use_strongest_session_key,
163 krb5_boolean is_preauth, hdb_entry_ex *princ,
164 krb5_enctype *etypes, unsigned len,
165 krb5_enctype *ret_enctype, Key **ret_key)
166 {
167 krb5_error_code ret;
168 krb5_salt def_salt;
169 krb5_enctype enctype = (krb5_enctype)ETYPE_NULL;
170 const krb5_enctype *p;
171 Key *key = NULL;
172 int i, k;
173
174 /* We'll want to avoid keys with v4 salted keys in the pre-auth case... */
175 ret = krb5_get_pw_salt(context, princ->entry.principal, &def_salt);
176 if (ret)
177 return ret;
178
179 ret = KRB5KDC_ERR_ETYPE_NOSUPP;
180
181 if (use_strongest_session_key) {
182
183 /*
184 * Pick the strongest key that the KDC, target service, and
185 * client all support, using the local cryptosystem enctype
186 * list in strongest-to-weakest order to drive the search.
187 *
188 * This is not what RFC4120 says to do, but it encourages
189 * adoption of stronger enctypes. This doesn't play well with
190 * clients that have multiple Kerberos client implementations
191 * available with different supported enctype lists.
192 */
193
194 /* drive the search with local supported enctypes list */
195 p = krb5_kerberos_enctypes(context);
196 for (i = 0;
197 p[i] != (krb5_enctype)ETYPE_NULL && enctype == (krb5_enctype)ETYPE_NULL;
198 i++) {
199 if (krb5_enctype_valid(context, p[i]) != 0 &&
200 !_kdc_is_weak_exception(princ->entry.principal, p[i]))
201 continue;
202
203 /* check that the client supports it too */
204 for (k = 0; k < len && enctype == (krb5_enctype)ETYPE_NULL; k++) {
205
206 if (p[i] != etypes[k])
207 continue;
208
209 /* check target princ support */
210 key = NULL;
211 while (hdb_next_enctype2key(context, &princ->entry, NULL,
212 p[i], &key) == 0) {
213 if (key->key.keyvalue.length == 0) {
214 ret = KRB5KDC_ERR_NULL_KEY;
215 continue;
216 }
217 enctype = p[i];
218 ret = 0;
219 if (is_preauth && ret_key != NULL &&
220 !is_good_salt_p(&def_salt, key))
221 continue;
222 }
223 }
224 }
225 } else {
226 /*
227 * Pick the first key from the client's enctype list that is
228 * supported by the cryptosystem and by the given principal.
229 *
230 * RFC4120 says we SHOULD pick the first _strong_ key from the
231 * client's list... not the first key... If the admin disallows
232 * weak enctypes in krb5.conf and selects this key selection
233 * algorithm, then we get exactly what RFC4120 says.
234 */
235 for(i = 0; ret != 0 && i < len; i++) {
236
237 if (krb5_enctype_valid(context, etypes[i]) != 0 &&
238 !_kdc_is_weak_exception(princ->entry.principal, etypes[i]))
239 continue;
240
241 key = NULL;
242 while (ret != 0 &&
243 hdb_next_enctype2key(context, &princ->entry, NULL,
244 etypes[i], &key) == 0) {
245 if (key->key.keyvalue.length == 0) {
246 ret = KRB5KDC_ERR_NULL_KEY;
247 continue;
248 }
249 enctype = etypes[i];
250 ret = 0;
251 if (is_preauth && ret_key != NULL &&
252 !is_good_salt_p(&def_salt, key))
253 continue;
254 }
255 }
256 }
257
258 if (enctype == (krb5_enctype)ETYPE_NULL) {
259 /*
260 * if the service principal is one for which there is a known 1DES
261 * exception and no other enctype matches both the client request and
262 * the service key list, provide a DES-CBC-CRC key.
263 */
264 if (ret_key == NULL &&
265 _kdc_is_weak_exception(princ->entry.principal, ETYPE_DES_CBC_CRC)) {
266 ret = 0;
267 enctype = ETYPE_DES_CBC_CRC;
268 } else {
269 ret = KRB5KDC_ERR_ETYPE_NOSUPP;
270 }
271 }
272
273 if (ret == 0) {
274 if (ret_enctype != NULL)
275 *ret_enctype = enctype;
276 if (ret_key != NULL)
277 *ret_key = key;
278 }
279
280 krb5_free_salt (context, def_salt);
281 return ret;
282 }
283
284 krb5_error_code
_kdc_make_anonymous_principalname(PrincipalName * pn)285 _kdc_make_anonymous_principalname (PrincipalName *pn)
286 {
287 pn->name_type = KRB5_NT_WELLKNOWN;
288 pn->name_string.len = 2;
289 pn->name_string.val = calloc(2, sizeof(*pn->name_string.val));
290 if (pn->name_string.val == NULL)
291 goto failed;
292
293 pn->name_string.val[0] = strdup(KRB5_WELLKNOWN_NAME);
294 if (pn->name_string.val[0] == NULL)
295 goto failed;
296
297 pn->name_string.val[1] = strdup(KRB5_ANON_NAME);
298 if (pn->name_string.val[1] == NULL)
299 goto failed;
300
301 return 0;
302
303 failed:
304 free_PrincipalName(pn);
305
306 pn->name_type = KRB5_NT_UNKNOWN;
307 pn->name_string.len = 0;
308 pn->name_string.val = NULL;
309
310 return ENOMEM;
311 }
312
313 static void
_kdc_r_log(kdc_request_t r,int level,const char * fmt,...)314 _kdc_r_log(kdc_request_t r, int level, const char *fmt, ...)
315 {
316 va_list ap;
317 char *s;
318 va_start(ap, fmt);
319 s = kdc_log_msg_va(r->context, r->config, level, fmt, ap);
320 if(s) free(s);
321 va_end(ap);
322 }
323
324 static void
_kdc_set_e_text(kdc_request_t r,const char * e_text)325 _kdc_set_e_text(kdc_request_t r, const char *e_text)
326 {
327 r->e_text = e_text;
328 kdc_log(r->context, r->config, 0, "%s", e_text);
329 }
330
331 void
_kdc_log_timestamp(krb5_context context,krb5_kdc_configuration * config,const char * type,KerberosTime authtime,KerberosTime * starttime,KerberosTime endtime,KerberosTime * renew_till)332 _kdc_log_timestamp(krb5_context context,
333 krb5_kdc_configuration *config,
334 const char *type,
335 KerberosTime authtime, KerberosTime *starttime,
336 KerberosTime endtime, KerberosTime *renew_till)
337 {
338 char authtime_str[100], starttime_str[100],
339 endtime_str[100], renewtime_str[100];
340
341 krb5_format_time(context, authtime,
342 authtime_str, sizeof(authtime_str), TRUE);
343 if (starttime)
344 krb5_format_time(context, *starttime,
345 starttime_str, sizeof(starttime_str), TRUE);
346 else
347 strlcpy(starttime_str, "unset", sizeof(starttime_str));
348 krb5_format_time(context, endtime,
349 endtime_str, sizeof(endtime_str), TRUE);
350 if (renew_till)
351 krb5_format_time(context, *renew_till,
352 renewtime_str, sizeof(renewtime_str), TRUE);
353 else
354 strlcpy(renewtime_str, "unset", sizeof(renewtime_str));
355
356 kdc_log(context, config, 5,
357 "%s authtime: %s starttime: %s endtime: %s renew till: %s",
358 type, authtime_str, starttime_str, endtime_str, renewtime_str);
359 }
360
361 /*
362 *
363 */
364
365 #ifdef PKINIT
366
367 static krb5_error_code
pa_pkinit_validate(kdc_request_t r,const PA_DATA * pa)368 pa_pkinit_validate(kdc_request_t r, const PA_DATA *pa)
369 {
370 pk_client_params *pkp = NULL;
371 char *client_cert = NULL;
372 krb5_error_code ret;
373
374 ret = _kdc_pk_rd_padata(r->context, r->config, &r->req, pa, r->client, &pkp);
375 if (ret || pkp == NULL) {
376 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
377 _kdc_r_log(r, 5, "Failed to decode PKINIT PA-DATA -- %s",
378 r->client_name);
379 goto out;
380 }
381
382 ret = _kdc_pk_check_client(r->context,
383 r->config,
384 r->clientdb,
385 r->client,
386 pkp,
387 &client_cert);
388 if (ret) {
389 _kdc_set_e_text(r, "PKINIT certificate not allowed to "
390 "impersonate principal");
391 goto out;
392 }
393
394 _kdc_r_log(r, 0, "PKINIT pre-authentication succeeded -- %s using %s",
395 r->client_name, client_cert);
396 free(client_cert);
397
398 ret = _kdc_pk_mk_pa_reply(r->context, r->config, pkp, r->client,
399 r->sessionetype, &r->req, &r->request,
400 &r->reply_key, &r->session_key, &r->outpadata);
401 if (ret) {
402 _kdc_set_e_text(r, "Failed to build PK-INIT reply");
403 goto out;
404 }
405 #if 0
406 ret = _kdc_add_inital_verified_cas(r->context, r->config,
407 pkp, &r->et);
408 #endif
409 out:
410 if (pkp)
411 _kdc_pk_free_client_param(r->context, pkp);
412
413 return ret;
414 }
415
416 #endif /* PKINIT */
417
418 /*
419 *
420 */
421
422 static krb5_error_code
make_pa_enc_challange(krb5_context context,METHOD_DATA * md,krb5_crypto crypto)423 make_pa_enc_challange(krb5_context context, METHOD_DATA *md,
424 krb5_crypto crypto)
425 {
426 PA_ENC_TS_ENC p;
427 unsigned char *buf;
428 size_t buf_size;
429 size_t len;
430 EncryptedData encdata;
431 krb5_error_code ret;
432 int32_t usec;
433 int usec2;
434
435 krb5_us_timeofday (context, &p.patimestamp, &usec);
436 usec2 = usec;
437 p.pausec = &usec2;
438
439 ASN1_MALLOC_ENCODE(PA_ENC_TS_ENC, buf, buf_size, &p, &len, ret);
440 if (ret)
441 return ret;
442 if(buf_size != len)
443 krb5_abortx(context, "internal error in ASN.1 encoder");
444
445 ret = krb5_encrypt_EncryptedData(context,
446 crypto,
447 KRB5_KU_ENC_CHALLENGE_KDC,
448 buf,
449 len,
450 0,
451 &encdata);
452 free(buf);
453 if (ret)
454 return ret;
455
456 ASN1_MALLOC_ENCODE(EncryptedData, buf, buf_size, &encdata, &len, ret);
457 free_EncryptedData(&encdata);
458 if (ret)
459 return ret;
460 if(buf_size != len)
461 krb5_abortx(context, "internal error in ASN.1 encoder");
462
463 ret = krb5_padata_add(context, md, KRB5_PADATA_ENCRYPTED_CHALLENGE, buf, len);
464 if (ret)
465 free(buf);
466 return ret;
467 }
468
469 static krb5_error_code
pa_enc_chal_validate(kdc_request_t r,const PA_DATA * pa)470 pa_enc_chal_validate(kdc_request_t r, const PA_DATA *pa)
471 {
472 krb5_data pepper1, pepper2, ts_data;
473 int invalidPassword = 0;
474 EncryptedData enc_data;
475 krb5_enctype aenctype;
476 krb5_error_code ret;
477 struct Key *k;
478 size_t size;
479 int i;
480
481 heim_assert(r->armor_crypto != NULL, "ENC-CHAL called for non FAST");
482
483 if (_kdc_is_anon_request(&r->req)) {
484 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
485 kdc_log(r->context, r->config, 0, "ENC-CHALL doesn't support anon");
486 return ret;
487 }
488
489 ret = decode_EncryptedData(pa->padata_value.data,
490 pa->padata_value.length,
491 &enc_data,
492 &size);
493 if (ret) {
494 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
495 _kdc_r_log(r, 5, "Failed to decode PA-DATA -- %s",
496 r->client_name);
497 return ret;
498 }
499
500 pepper1.data = "clientchallengearmor";
501 pepper1.length = strlen(pepper1.data);
502 pepper2.data = "challengelongterm";
503 pepper2.length = strlen(pepper2.data);
504
505 krb5_crypto_getenctype(r->context, r->armor_crypto, &aenctype);
506
507 for (i = 0; i < r->client->entry.keys.len; i++) {
508 krb5_crypto challangecrypto, longtermcrypto;
509 krb5_keyblock challangekey;
510 PA_ENC_TS_ENC p;
511
512 k = &r->client->entry.keys.val[i];
513
514 ret = krb5_crypto_init(r->context, &k->key, 0, &longtermcrypto);
515 if (ret)
516 continue;
517
518 ret = krb5_crypto_fx_cf2(r->context, r->armor_crypto, longtermcrypto,
519 &pepper1, &pepper2, aenctype,
520 &challangekey);
521 krb5_crypto_destroy(r->context, longtermcrypto);
522 if (ret)
523 continue;
524
525 ret = krb5_crypto_init(r->context, &challangekey, 0,
526 &challangecrypto);
527 if (ret)
528 continue;
529
530 ret = krb5_decrypt_EncryptedData(r->context, challangecrypto,
531 KRB5_KU_ENC_CHALLENGE_CLIENT,
532 &enc_data,
533 &ts_data);
534 if (ret) {
535 const char *msg = krb5_get_error_message(r->context, ret);
536 krb5_error_code ret2;
537 char *str = NULL;
538
539 invalidPassword = 1;
540
541 ret2 = krb5_enctype_to_string(r->context, k->key.keytype, &str);
542 if (ret2)
543 str = NULL;
544 _kdc_r_log(r, 5, "Failed to decrypt ENC-CHAL -- %s "
545 "(enctype %s) error %s",
546 r->client_name, str ? str : "unknown enctype", msg);
547 krb5_free_error_message(r->context, msg);
548 free(str);
549
550 continue;
551 }
552
553 ret = decode_PA_ENC_TS_ENC(ts_data.data,
554 ts_data.length,
555 &p,
556 &size);
557 krb5_data_free(&ts_data);
558 if(ret){
559 krb5_crypto_destroy(r->context, challangecrypto);
560 ret = KRB5KDC_ERR_PREAUTH_FAILED;
561 _kdc_r_log(r, 5, "Failed to decode PA-ENC-TS_ENC -- %s",
562 r->client_name);
563 continue;
564 }
565
566 if (labs(kdc_time - p.patimestamp) > r->context->max_skew) {
567 char client_time[100];
568
569 krb5_crypto_destroy(r->context, challangecrypto);
570
571 krb5_format_time(r->context, p.patimestamp,
572 client_time, sizeof(client_time), TRUE);
573
574 ret = KRB5KRB_AP_ERR_SKEW;
575 _kdc_r_log(r, 0, "Too large time skew, "
576 "client time %s is out by %u > %u seconds -- %s",
577 client_time,
578 (unsigned)labs(kdc_time - p.patimestamp),
579 r->context->max_skew,
580 r->client_name);
581
582 free_PA_ENC_TS_ENC(&p);
583 goto out;
584 }
585
586 free_PA_ENC_TS_ENC(&p);
587
588 ret = make_pa_enc_challange(r->context, &r->outpadata,
589 challangecrypto);
590 krb5_crypto_destroy(r->context, challangecrypto);
591 if (ret)
592 goto out;
593
594 set_salt_padata(&r->outpadata, k->salt);
595 krb5_free_keyblock_contents(r->context, &r->reply_key);
596 ret = krb5_copy_keyblock_contents(r->context, &k->key, &r->reply_key);
597 if (ret)
598 goto out;
599
600 /*
601 * Success
602 */
603 if (r->clientdb->hdb_auth_status)
604 r->clientdb->hdb_auth_status(r->context, r->clientdb, r->client,
605 HDB_AUTH_SUCCESS);
606 goto out;
607 }
608
609 if (invalidPassword && r->clientdb->hdb_auth_status) {
610 r->clientdb->hdb_auth_status(r->context, r->clientdb, r->client,
611 HDB_AUTH_WRONG_PASSWORD);
612 ret = KRB5KDC_ERR_PREAUTH_FAILED;
613 }
614 out:
615 free_EncryptedData(&enc_data);
616
617 return ret;
618 }
619
620 static krb5_error_code
pa_enc_ts_validate(kdc_request_t r,const PA_DATA * pa)621 pa_enc_ts_validate(kdc_request_t r, const PA_DATA *pa)
622 {
623 EncryptedData enc_data;
624 krb5_error_code ret;
625 krb5_crypto crypto;
626 krb5_data ts_data;
627 PA_ENC_TS_ENC p;
628 size_t len;
629 Key *pa_key;
630 char *str;
631
632 ret = decode_EncryptedData(pa->padata_value.data,
633 pa->padata_value.length,
634 &enc_data,
635 &len);
636 if (ret) {
637 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
638 _kdc_r_log(r, 5, "Failed to decode PA-DATA -- %s",
639 r->client_name);
640 goto out;
641 }
642
643 ret = hdb_enctype2key(r->context, &r->client->entry, NULL,
644 enc_data.etype, &pa_key);
645 if(ret){
646 char *estr;
647 _kdc_set_e_text(r, "No key matching entype");
648 ret = KRB5KDC_ERR_ETYPE_NOSUPP;
649 if(krb5_enctype_to_string(r->context, enc_data.etype, &estr))
650 estr = NULL;
651 if(estr == NULL)
652 _kdc_r_log(r, 5,
653 "No client key matching pa-data (%d) -- %s",
654 enc_data.etype, r->client_name);
655 else
656 _kdc_r_log(r, 5,
657 "No client key matching pa-data (%s) -- %s",
658 estr, r->client_name);
659 free(estr);
660 free_EncryptedData(&enc_data);
661 goto out;
662 }
663
664 try_next_key:
665 ret = krb5_crypto_init(r->context, &pa_key->key, 0, &crypto);
666 if (ret) {
667 const char *msg = krb5_get_error_message(r->context, ret);
668 _kdc_r_log(r, 0, "krb5_crypto_init failed: %s", msg);
669 krb5_free_error_message(r->context, msg);
670 free_EncryptedData(&enc_data);
671 goto out;
672 }
673
674 ret = krb5_decrypt_EncryptedData (r->context,
675 crypto,
676 KRB5_KU_PA_ENC_TIMESTAMP,
677 &enc_data,
678 &ts_data);
679 krb5_crypto_destroy(r->context, crypto);
680 /*
681 * Since the user might have several keys with the same
682 * enctype but with diffrent salting, we need to try all
683 * the keys with the same enctype.
684 */
685 if(ret){
686 krb5_error_code ret2;
687 const char *msg = krb5_get_error_message(r->context, ret);
688
689 ret2 = krb5_enctype_to_string(r->context,
690 pa_key->key.keytype, &str);
691 if (ret2)
692 str = NULL;
693 _kdc_r_log(r, 5, "Failed to decrypt PA-DATA -- %s "
694 "(enctype %s) error %s",
695 r->client_name, str ? str : "unknown enctype", msg);
696 krb5_free_error_message(r->context, msg);
697 free(str);
698
699 if(hdb_next_enctype2key(r->context, &r->client->entry, NULL,
700 enc_data.etype, &pa_key) == 0)
701 goto try_next_key;
702
703 free_EncryptedData(&enc_data);
704
705 if (r->clientdb->hdb_auth_status)
706 r->clientdb->hdb_auth_status(r->context, r->clientdb, r->client,
707 HDB_AUTH_WRONG_PASSWORD);
708
709 ret = KRB5KDC_ERR_PREAUTH_FAILED;
710 goto out;
711 }
712 free_EncryptedData(&enc_data);
713 ret = decode_PA_ENC_TS_ENC(ts_data.data,
714 ts_data.length,
715 &p,
716 &len);
717 krb5_data_free(&ts_data);
718 if(ret){
719 ret = KRB5KDC_ERR_PREAUTH_FAILED;
720 _kdc_r_log(r, 5, "Failed to decode PA-ENC-TS_ENC -- %s",
721 r->client_name);
722 goto out;
723 }
724 if (labs(kdc_time - p.patimestamp) > r->context->max_skew) {
725 char client_time[100];
726
727 krb5_format_time(r->context, p.patimestamp,
728 client_time, sizeof(client_time), TRUE);
729
730 ret = KRB5KRB_AP_ERR_SKEW;
731 _kdc_r_log(r, 0, "Too large time skew, "
732 "client time %s is out by %u > %u seconds -- %s",
733 client_time,
734 (unsigned)labs(kdc_time - p.patimestamp),
735 r->context->max_skew,
736 r->client_name);
737
738 /*
739 * The following is needed to make windows clients to
740 * retry using the timestamp in the error message, if
741 * there is a e_text, they become unhappy.
742 */
743 r->e_text = NULL;
744 free_PA_ENC_TS_ENC(&p);
745 goto out;
746 }
747 free_PA_ENC_TS_ENC(&p);
748
749 set_salt_padata(&r->outpadata, pa_key->salt);
750
751 ret = krb5_copy_keyblock_contents(r->context, &pa_key->key, &r->reply_key);
752 if (ret)
753 return ret;
754
755 ret = krb5_enctype_to_string(r->context, pa_key->key.keytype, &str);
756 if (ret)
757 str = NULL;
758 _kdc_r_log(r, 2, "ENC-TS Pre-authentication succeeded -- %s using %s",
759 r->client_name, str ? str : "unknown enctype");
760 free(str);
761
762 ret = 0;
763
764 out:
765
766 return ret;
767 }
768
769 struct kdc_patypes {
770 int type;
771 char *name;
772 unsigned int flags;
773 #define PA_ANNOUNCE 1
774 #define PA_REQ_FAST 2 /* only use inside fast */
775 krb5_error_code (*validate)(kdc_request_t, const PA_DATA *pa);
776 };
777
778 static const struct kdc_patypes pat[] = {
779 #ifdef PKINIT
780 {
781 KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)", PA_ANNOUNCE,
782 pa_pkinit_validate
783 },
784 {
785 KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", PA_ANNOUNCE,
786 pa_pkinit_validate
787 },
788 {
789 KRB5_PADATA_PKINIT_KX, "Anonymous PK-INIT", PA_ANNOUNCE,
790 NULL
791 },
792 #else
793 { KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)", 0, NULL },
794 { KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", 0, NULL },
795 { KRB5_PADATA_PKINIT_KX, "Anonymous PK-INIT", 0, NULL },
796 #endif
797 { KRB5_PADATA_PA_PK_OCSP_RESPONSE , "OCSP", 0, NULL },
798 {
799 KRB5_PADATA_ENC_TIMESTAMP , "ENC-TS",
800 PA_ANNOUNCE,
801 pa_enc_ts_validate
802 },
803 {
804 KRB5_PADATA_ENCRYPTED_CHALLENGE , "ENC-CHAL",
805 PA_ANNOUNCE | PA_REQ_FAST,
806 pa_enc_chal_validate
807 },
808 { KRB5_PADATA_REQ_ENC_PA_REP , "REQ-ENC-PA-REP", 0, NULL },
809 { KRB5_PADATA_FX_FAST, "FX-FAST", PA_ANNOUNCE, NULL },
810 { KRB5_PADATA_FX_ERROR, "FX-ERROR", 0, NULL },
811 { KRB5_PADATA_FX_COOKIE, "FX-COOKIE", 0, NULL }
812 };
813
814 static void
log_patypes(krb5_context context,krb5_kdc_configuration * config,METHOD_DATA * padata)815 log_patypes(krb5_context context,
816 krb5_kdc_configuration *config,
817 METHOD_DATA *padata)
818 {
819 struct rk_strpool *p = NULL;
820 char *str;
821 size_t n, m;
822
823 for (n = 0; n < padata->len; n++) {
824 for (m = 0; m < sizeof(pat) / sizeof(pat[0]); m++) {
825 if (padata->val[n].padata_type == pat[m].type) {
826 p = rk_strpoolprintf(p, "%s", pat[m].name);
827 break;
828 }
829 }
830 if (m == sizeof(pat) / sizeof(pat[0]))
831 p = rk_strpoolprintf(p, "%d", padata->val[n].padata_type);
832 if (p && n + 1 < padata->len)
833 p = rk_strpoolprintf(p, ", ");
834 if (p == NULL) {
835 kdc_log(context, config, 0, "out of memory");
836 return;
837 }
838 }
839 if (p == NULL)
840 p = rk_strpoolprintf(p, "none");
841
842 str = rk_strpoolcollect(p);
843 kdc_log(context, config, 0, "Client sent patypes: %s", str);
844 free(str);
845 }
846
847 /*
848 *
849 */
850
851 krb5_error_code
_kdc_encode_reply(krb5_context context,krb5_kdc_configuration * config,krb5_crypto armor_crypto,uint32_t nonce,KDC_REP * rep,EncTicketPart * et,EncKDCRepPart * ek,krb5_enctype etype,int skvno,const EncryptionKey * skey,int ckvno,const EncryptionKey * reply_key,int rk_is_subkey,const char ** e_text,krb5_data * reply)852 _kdc_encode_reply(krb5_context context,
853 krb5_kdc_configuration *config,
854 krb5_crypto armor_crypto, uint32_t nonce,
855 KDC_REP *rep, EncTicketPart *et, EncKDCRepPart *ek,
856 krb5_enctype etype,
857 int skvno, const EncryptionKey *skey,
858 int ckvno, const EncryptionKey *reply_key,
859 int rk_is_subkey,
860 const char **e_text,
861 krb5_data *reply)
862 {
863 unsigned char *buf;
864 size_t buf_size;
865 size_t len = 0;
866 krb5_error_code ret;
867 krb5_crypto crypto;
868
869 ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret);
870 if(ret) {
871 const char *msg = krb5_get_error_message(context, ret);
872 kdc_log(context, config, 0, "Failed to encode ticket: %s", msg);
873 krb5_free_error_message(context, msg);
874 return ret;
875 }
876 if(buf_size != len)
877 krb5_abortx(context, "Internal error in ASN.1 encoder");
878
879 ret = krb5_crypto_init(context, skey, etype, &crypto);
880 if (ret) {
881 const char *msg = krb5_get_error_message(context, ret);
882 kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
883 krb5_free_error_message(context, msg);
884 free(buf);
885 return ret;
886 }
887
888 ret = krb5_encrypt_EncryptedData(context,
889 crypto,
890 KRB5_KU_TICKET,
891 buf,
892 len,
893 skvno,
894 &rep->ticket.enc_part);
895 free(buf);
896 krb5_crypto_destroy(context, crypto);
897 if(ret) {
898 const char *msg = krb5_get_error_message(context, ret);
899 kdc_log(context, config, 0, "Failed to encrypt data: %s", msg);
900 krb5_free_error_message(context, msg);
901 return ret;
902 }
903
904 if (armor_crypto) {
905 krb5_data data;
906 krb5_keyblock *strengthen_key = NULL;
907 KrbFastFinished finished;
908
909 kdc_log(context, config, 0, "FAST armor protection");
910
911 memset(&finished, 0, sizeof(finished));
912 krb5_data_zero(&data);
913
914 finished.timestamp = kdc_time;
915 finished.usec = 0;
916 finished.crealm = et->crealm;
917 finished.cname = et->cname;
918
919 ASN1_MALLOC_ENCODE(Ticket, data.data, data.length,
920 &rep->ticket, &len, ret);
921 if (ret)
922 return ret;
923 if (data.length != len)
924 krb5_abortx(context, "internal asn.1 error");
925
926 ret = krb5_create_checksum(context, armor_crypto,
927 KRB5_KU_FAST_FINISHED, 0,
928 data.data, data.length,
929 &finished.ticket_checksum);
930 krb5_data_free(&data);
931 if (ret)
932 return ret;
933
934 ret = _kdc_fast_mk_response(context, armor_crypto,
935 rep->padata, strengthen_key, &finished,
936 nonce, &data);
937 free_Checksum(&finished.ticket_checksum);
938 if (ret)
939 return ret;
940
941 if (rep->padata) {
942 free_METHOD_DATA(rep->padata);
943 } else {
944 rep->padata = calloc(1, sizeof(*(rep->padata)));
945 if (rep->padata == NULL) {
946 krb5_data_free(&data);
947 return ENOMEM;
948 }
949 }
950
951 ret = krb5_padata_add(context, rep->padata,
952 KRB5_PADATA_FX_FAST,
953 data.data, data.length);
954 if (ret)
955 return ret;
956
957 /*
958 * Hide client name of privacy reasons
959 */
960 if (1 /* r->fast_options.hide_client_names */) {
961 rep->crealm[0] = '\0';
962 free_PrincipalName(&rep->cname);
963 rep->cname.name_type = 0;
964 }
965 }
966
967 if(rep->msg_type == krb_as_rep && !config->encode_as_rep_as_tgs_rep)
968 ASN1_MALLOC_ENCODE(EncASRepPart, buf, buf_size, ek, &len, ret);
969 else
970 ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret);
971 if(ret) {
972 const char *msg = krb5_get_error_message(context, ret);
973 kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", msg);
974 krb5_free_error_message(context, msg);
975 return ret;
976 }
977 if(buf_size != len) {
978 free(buf);
979 kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
980 *e_text = "KDC internal error";
981 return KRB5KRB_ERR_GENERIC;
982 }
983 ret = krb5_crypto_init(context, reply_key, 0, &crypto);
984 if (ret) {
985 const char *msg = krb5_get_error_message(context, ret);
986 free(buf);
987 kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
988 krb5_free_error_message(context, msg);
989 return ret;
990 }
991 if(rep->msg_type == krb_as_rep) {
992 krb5_encrypt_EncryptedData(context,
993 crypto,
994 KRB5_KU_AS_REP_ENC_PART,
995 buf,
996 len,
997 ckvno,
998 &rep->enc_part);
999 free(buf);
1000 ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret);
1001 } else {
1002 krb5_encrypt_EncryptedData(context,
1003 crypto,
1004 rk_is_subkey ? KRB5_KU_TGS_REP_ENC_PART_SUB_KEY : KRB5_KU_TGS_REP_ENC_PART_SESSION,
1005 buf,
1006 len,
1007 ckvno,
1008 &rep->enc_part);
1009 free(buf);
1010 ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret);
1011 }
1012 krb5_crypto_destroy(context, crypto);
1013 if(ret) {
1014 const char *msg = krb5_get_error_message(context, ret);
1015 kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", msg);
1016 krb5_free_error_message(context, msg);
1017 return ret;
1018 }
1019 if(buf_size != len) {
1020 free(buf);
1021 kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
1022 *e_text = "KDC internal error";
1023 return KRB5KRB_ERR_GENERIC;
1024 }
1025 reply->data = buf;
1026 reply->length = buf_size;
1027 return 0;
1028 }
1029
1030 /*
1031 * Return 1 if the client have only older enctypes, this is for
1032 * determining if the server should send ETYPE_INFO2 or not.
1033 */
1034
1035 static int
older_enctype(krb5_enctype enctype)1036 older_enctype(krb5_enctype enctype)
1037 {
1038 switch (enctype) {
1039 case ETYPE_DES_CBC_CRC:
1040 case ETYPE_DES_CBC_MD4:
1041 case ETYPE_DES_CBC_MD5:
1042 case ETYPE_DES3_CBC_SHA1:
1043 case ETYPE_ARCFOUR_HMAC_MD5:
1044 case ETYPE_ARCFOUR_HMAC_MD5_56:
1045 /*
1046 * The following three is "old" windows enctypes and is needed for
1047 * windows 2000 hosts.
1048 */
1049 case ETYPE_ARCFOUR_MD4:
1050 case ETYPE_ARCFOUR_HMAC_OLD:
1051 case ETYPE_ARCFOUR_HMAC_OLD_EXP:
1052 return 1;
1053 default:
1054 return 0;
1055 }
1056 }
1057
1058 /*
1059 *
1060 */
1061
1062 static krb5_error_code
make_etype_info_entry(krb5_context context,ETYPE_INFO_ENTRY * ent,Key * key)1063 make_etype_info_entry(krb5_context context, ETYPE_INFO_ENTRY *ent, Key *key)
1064 {
1065 ent->etype = key->key.keytype;
1066 if(key->salt){
1067 #if 0
1068 ALLOC(ent->salttype);
1069
1070 if(key->salt->type == hdb_pw_salt)
1071 *ent->salttype = 0; /* or 1? or NULL? */
1072 else if(key->salt->type == hdb_afs3_salt)
1073 *ent->salttype = 2;
1074 else {
1075 kdc_log(context, config, 0, "unknown salt-type: %d",
1076 key->salt->type);
1077 return KRB5KRB_ERR_GENERIC;
1078 }
1079 /* according to `the specs', we can't send a salt if
1080 we have AFS3 salted key, but that requires that you
1081 *know* what cell you are using (e.g by assuming
1082 that the cell is the same as the realm in lower
1083 case) */
1084 #elif 0
1085 ALLOC(ent->salttype);
1086 *ent->salttype = key->salt->type;
1087 #else
1088 /*
1089 * We shouldn't sent salttype since it is incompatible with the
1090 * specification and it breaks windows clients. The afs
1091 * salting problem is solved by using KRB5-PADATA-AFS3-SALT
1092 * implemented in Heimdal 0.7 and later.
1093 */
1094 ent->salttype = NULL;
1095 #endif
1096 krb5_copy_data(context, &key->salt->salt,
1097 &ent->salt);
1098 } else {
1099 /* we return no salt type at all, as that should indicate
1100 * the default salt type and make everybody happy. some
1101 * systems (like w2k) dislike being told the salt type
1102 * here. */
1103
1104 ent->salttype = NULL;
1105 ent->salt = NULL;
1106 }
1107 return 0;
1108 }
1109
1110 static krb5_error_code
get_pa_etype_info(krb5_context context,krb5_kdc_configuration * config,METHOD_DATA * md,Key * ckey)1111 get_pa_etype_info(krb5_context context,
1112 krb5_kdc_configuration *config,
1113 METHOD_DATA *md, Key *ckey)
1114 {
1115 krb5_error_code ret = 0;
1116 ETYPE_INFO pa;
1117 unsigned char *buf;
1118 size_t len;
1119
1120
1121 pa.len = 1;
1122 pa.val = calloc(1, sizeof(pa.val[0]));
1123 if(pa.val == NULL)
1124 return ENOMEM;
1125
1126 ret = make_etype_info_entry(context, &pa.val[0], ckey);
1127 if (ret) {
1128 free_ETYPE_INFO(&pa);
1129 return ret;
1130 }
1131
1132 ASN1_MALLOC_ENCODE(ETYPE_INFO, buf, len, &pa, &len, ret);
1133 free_ETYPE_INFO(&pa);
1134 if(ret)
1135 return ret;
1136 ret = realloc_method_data(md);
1137 if(ret) {
1138 free(buf);
1139 return ret;
1140 }
1141 md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO;
1142 md->val[md->len - 1].padata_value.length = len;
1143 md->val[md->len - 1].padata_value.data = buf;
1144 return 0;
1145 }
1146
1147 /*
1148 *
1149 */
1150
1151 extern int _krb5_AES_SHA1_string_to_default_iterator;
1152 extern int _krb5_AES_SHA2_string_to_default_iterator;
1153
1154 static krb5_error_code
make_s2kparams(int value,size_t len,krb5_data ** ps2kparams)1155 make_s2kparams(int value, size_t len, krb5_data **ps2kparams)
1156 {
1157 krb5_data *s2kparams;
1158 krb5_error_code ret;
1159
1160 ALLOC(s2kparams);
1161 if (s2kparams == NULL)
1162 return ENOMEM;
1163 ret = krb5_data_alloc(s2kparams, len);
1164 if (ret) {
1165 free(s2kparams);
1166 return ret;
1167 }
1168 _krb5_put_int(s2kparams->data, value, len);
1169 *ps2kparams = s2kparams;
1170 return 0;
1171 }
1172
1173 static krb5_error_code
make_etype_info2_entry(ETYPE_INFO2_ENTRY * ent,Key * key)1174 make_etype_info2_entry(ETYPE_INFO2_ENTRY *ent, Key *key)
1175 {
1176 krb5_error_code ret;
1177
1178 ent->etype = key->key.keytype;
1179 if(key->salt) {
1180 ALLOC(ent->salt);
1181 if (ent->salt == NULL)
1182 return ENOMEM;
1183 *ent->salt = malloc(key->salt->salt.length + 1);
1184 if (*ent->salt == NULL) {
1185 free(ent->salt);
1186 ent->salt = NULL;
1187 return ENOMEM;
1188 }
1189 memcpy(*ent->salt, key->salt->salt.data, key->salt->salt.length);
1190 (*ent->salt)[key->salt->salt.length] = '\0';
1191 } else
1192 ent->salt = NULL;
1193
1194 ent->s2kparams = NULL;
1195
1196 switch (key->key.keytype) {
1197 case ETYPE_AES128_CTS_HMAC_SHA1_96:
1198 case ETYPE_AES256_CTS_HMAC_SHA1_96:
1199 ret = make_s2kparams(_krb5_AES_SHA1_string_to_default_iterator,
1200 4, &ent->s2kparams);
1201 break;
1202 case KRB5_ENCTYPE_AES128_CTS_HMAC_SHA256_128:
1203 case KRB5_ENCTYPE_AES256_CTS_HMAC_SHA384_192:
1204 ret = make_s2kparams(_krb5_AES_SHA2_string_to_default_iterator,
1205 4, &ent->s2kparams);
1206 break;
1207 case ETYPE_DES_CBC_CRC:
1208 case ETYPE_DES_CBC_MD4:
1209 case ETYPE_DES_CBC_MD5:
1210 /* Check if this was a AFS3 salted key */
1211 if(key->salt && key->salt->type == hdb_afs3_salt)
1212 ret = make_s2kparams(1, 1, &ent->s2kparams);
1213 else
1214 ret = 0;
1215 break;
1216 default:
1217 ret = 0;
1218 break;
1219 }
1220 return ret;
1221 }
1222
1223 /*
1224 * Return an ETYPE-INFO2. Enctypes are storted the same way as in the
1225 * database (client supported enctypes first, then the unsupported
1226 * enctypes).
1227 */
1228
1229 static krb5_error_code
get_pa_etype_info2(krb5_context context,krb5_kdc_configuration * config,METHOD_DATA * md,Key * ckey)1230 get_pa_etype_info2(krb5_context context,
1231 krb5_kdc_configuration *config,
1232 METHOD_DATA *md, Key *ckey)
1233 {
1234 krb5_error_code ret = 0;
1235 ETYPE_INFO2 pa;
1236 unsigned char *buf;
1237 size_t len;
1238
1239 pa.len = 1;
1240 pa.val = calloc(1, sizeof(pa.val[0]));
1241 if(pa.val == NULL)
1242 return ENOMEM;
1243
1244 ret = make_etype_info2_entry(&pa.val[0], ckey);
1245 if (ret) {
1246 free_ETYPE_INFO2(&pa);
1247 return ret;
1248 }
1249
1250 ASN1_MALLOC_ENCODE(ETYPE_INFO2, buf, len, &pa, &len, ret);
1251 free_ETYPE_INFO2(&pa);
1252 if(ret)
1253 return ret;
1254 ret = realloc_method_data(md);
1255 if(ret) {
1256 free(buf);
1257 return ret;
1258 }
1259 md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO2;
1260 md->val[md->len - 1].padata_value.length = len;
1261 md->val[md->len - 1].padata_value.data = buf;
1262 return 0;
1263 }
1264
1265 /*
1266 *
1267 */
1268
1269 static void
log_as_req(krb5_context context,krb5_kdc_configuration * config,krb5_enctype cetype,krb5_enctype setype,const KDC_REQ_BODY * b)1270 log_as_req(krb5_context context,
1271 krb5_kdc_configuration *config,
1272 krb5_enctype cetype,
1273 krb5_enctype setype,
1274 const KDC_REQ_BODY *b)
1275 {
1276 krb5_error_code ret;
1277 struct rk_strpool *p;
1278 char *str;
1279 size_t i;
1280
1281 p = rk_strpoolprintf(NULL, "%s", "Client supported enctypes: ");
1282
1283 for (i = 0; i < b->etype.len; i++) {
1284 ret = krb5_enctype_to_string(context, b->etype.val[i], &str);
1285 if (ret == 0) {
1286 p = rk_strpoolprintf(p, "%s", str);
1287 free(str);
1288 } else
1289 p = rk_strpoolprintf(p, "%d", b->etype.val[i]);
1290 if (p && i + 1 < b->etype.len)
1291 p = rk_strpoolprintf(p, ", ");
1292 if (p == NULL) {
1293 kdc_log(context, config, 0, "out of memory");
1294 return;
1295 }
1296 }
1297 if (p == NULL)
1298 p = rk_strpoolprintf(p, "no encryption types");
1299
1300 {
1301 char *cet;
1302 char *set;
1303
1304 ret = krb5_enctype_to_string(context, cetype, &cet);
1305 if(ret == 0) {
1306 ret = krb5_enctype_to_string(context, setype, &set);
1307 if (ret == 0) {
1308 p = rk_strpoolprintf(p, ", using %s/%s", cet, set);
1309 free(set);
1310 }
1311 free(cet);
1312 }
1313 if (ret != 0)
1314 p = rk_strpoolprintf(p, ", using enctypes %d/%d",
1315 cetype, setype);
1316 }
1317
1318 str = rk_strpoolcollect(p);
1319 kdc_log(context, config, 0, "%s", str);
1320 free(str);
1321
1322 {
1323 char fixedstr[128];
1324 unparse_flags(KDCOptions2int(b->kdc_options), asn1_KDCOptions_units(),
1325 fixedstr, sizeof(fixedstr));
1326 if(*fixedstr)
1327 kdc_log(context, config, 0, "Requested flags: %s", fixedstr);
1328 }
1329 }
1330
1331 /*
1332 * verify the flags on `client' and `server', returning 0
1333 * if they are OK and generating an error messages and returning
1334 * and error code otherwise.
1335 */
1336
1337 krb5_error_code
kdc_check_flags(krb5_context context,krb5_kdc_configuration * config,hdb_entry_ex * client_ex,const char * client_name,hdb_entry_ex * server_ex,const char * server_name,krb5_boolean is_as_req)1338 kdc_check_flags(krb5_context context,
1339 krb5_kdc_configuration *config,
1340 hdb_entry_ex *client_ex, const char *client_name,
1341 hdb_entry_ex *server_ex, const char *server_name,
1342 krb5_boolean is_as_req)
1343 {
1344 if(client_ex != NULL) {
1345 hdb_entry *client = &client_ex->entry;
1346
1347 /* check client */
1348 if (client->flags.locked_out) {
1349 kdc_log(context, config, 0,
1350 "Client (%s) is locked out", client_name);
1351 return KRB5KDC_ERR_POLICY;
1352 }
1353
1354 if (client->flags.invalid) {
1355 kdc_log(context, config, 0,
1356 "Client (%s) has invalid bit set", client_name);
1357 return KRB5KDC_ERR_POLICY;
1358 }
1359
1360 if(!client->flags.client){
1361 kdc_log(context, config, 0,
1362 "Principal may not act as client -- %s", client_name);
1363 return KRB5KDC_ERR_POLICY;
1364 }
1365
1366 if (client->valid_start && *client->valid_start > kdc_time) {
1367 char starttime_str[100];
1368 krb5_format_time(context, *client->valid_start,
1369 starttime_str, sizeof(starttime_str), TRUE);
1370 kdc_log(context, config, 0,
1371 "Client not yet valid until %s -- %s",
1372 starttime_str, client_name);
1373 return KRB5KDC_ERR_CLIENT_NOTYET;
1374 }
1375
1376 if (client->valid_end && *client->valid_end < kdc_time) {
1377 char endtime_str[100];
1378 krb5_format_time(context, *client->valid_end,
1379 endtime_str, sizeof(endtime_str), TRUE);
1380 kdc_log(context, config, 0,
1381 "Client expired at %s -- %s",
1382 endtime_str, client_name);
1383 return KRB5KDC_ERR_NAME_EXP;
1384 }
1385
1386 if (client->flags.require_pwchange &&
1387 (server_ex == NULL || !server_ex->entry.flags.change_pw)) {
1388 kdc_log(context, config, 0,
1389 "Client's key must be changed -- %s", client_name);
1390 return KRB5KDC_ERR_KEY_EXPIRED;
1391 }
1392
1393 if (client->pw_end && *client->pw_end < kdc_time
1394 && (server_ex == NULL || !server_ex->entry.flags.change_pw)) {
1395 char pwend_str[100];
1396 krb5_format_time(context, *client->pw_end,
1397 pwend_str, sizeof(pwend_str), TRUE);
1398 kdc_log(context, config, 0,
1399 "Client's key has expired at %s -- %s",
1400 pwend_str, client_name);
1401 return KRB5KDC_ERR_KEY_EXPIRED;
1402 }
1403 }
1404
1405 /* check server */
1406
1407 if (server_ex != NULL) {
1408 hdb_entry *server = &server_ex->entry;
1409
1410 if (server->flags.locked_out) {
1411 kdc_log(context, config, 0,
1412 "Client server locked out -- %s", server_name);
1413 return KRB5KDC_ERR_POLICY;
1414 }
1415 if (server->flags.invalid) {
1416 kdc_log(context, config, 0,
1417 "Server has invalid flag set -- %s", server_name);
1418 return KRB5KDC_ERR_POLICY;
1419 }
1420
1421 if(!server->flags.server){
1422 kdc_log(context, config, 0,
1423 "Principal may not act as server -- %s", server_name);
1424 return KRB5KDC_ERR_POLICY;
1425 }
1426
1427 if(!is_as_req && server->flags.initial) {
1428 kdc_log(context, config, 0,
1429 "AS-REQ is required for server -- %s", server_name);
1430 return KRB5KDC_ERR_POLICY;
1431 }
1432
1433 if (server->valid_start && *server->valid_start > kdc_time) {
1434 char starttime_str[100];
1435 krb5_format_time(context, *server->valid_start,
1436 starttime_str, sizeof(starttime_str), TRUE);
1437 kdc_log(context, config, 0,
1438 "Server not yet valid until %s -- %s",
1439 starttime_str, server_name);
1440 return KRB5KDC_ERR_SERVICE_NOTYET;
1441 }
1442
1443 if (server->valid_end && *server->valid_end < kdc_time) {
1444 char endtime_str[100];
1445 krb5_format_time(context, *server->valid_end,
1446 endtime_str, sizeof(endtime_str), TRUE);
1447 kdc_log(context, config, 0,
1448 "Server expired at %s -- %s",
1449 endtime_str, server_name);
1450 return KRB5KDC_ERR_SERVICE_EXP;
1451 }
1452
1453 if (server->pw_end && *server->pw_end < kdc_time) {
1454 char pwend_str[100];
1455 krb5_format_time(context, *server->pw_end,
1456 pwend_str, sizeof(pwend_str), TRUE);
1457 kdc_log(context, config, 0,
1458 "Server's key has expired at -- %s",
1459 pwend_str, server_name);
1460 return KRB5KDC_ERR_KEY_EXPIRED;
1461 }
1462 }
1463 return 0;
1464 }
1465
1466 /*
1467 * Return TRUE if `from' is part of `addresses' taking into consideration
1468 * the configuration variables that tells us how strict we should be about
1469 * these checks
1470 */
1471
1472 krb5_boolean
_kdc_check_addresses(krb5_context context,krb5_kdc_configuration * config,HostAddresses * addresses,const struct sockaddr * from)1473 _kdc_check_addresses(krb5_context context,
1474 krb5_kdc_configuration *config,
1475 HostAddresses *addresses, const struct sockaddr *from)
1476 {
1477 krb5_error_code ret;
1478 krb5_address addr;
1479 krb5_boolean result;
1480 krb5_boolean only_netbios = TRUE;
1481 size_t i;
1482
1483 if(config->check_ticket_addresses == 0)
1484 return TRUE;
1485
1486 if(addresses == NULL)
1487 return config->allow_null_ticket_addresses;
1488
1489 for (i = 0; i < addresses->len; ++i) {
1490 if (addresses->val[i].addr_type != KRB5_ADDRESS_NETBIOS) {
1491 only_netbios = FALSE;
1492 }
1493 }
1494
1495 /* Windows sends it's netbios name, which I can only assume is
1496 * used for the 'allowed workstations' check. This is painful,
1497 * but we still want to check IP addresses if they happen to be
1498 * present.
1499 */
1500
1501 if(only_netbios)
1502 return config->allow_null_ticket_addresses;
1503
1504 ret = krb5_sockaddr2address (context, from, &addr);
1505 if(ret)
1506 return FALSE;
1507
1508 result = krb5_address_search(context, &addr, addresses);
1509 krb5_free_address (context, &addr);
1510 return result;
1511 }
1512
1513 /*
1514 *
1515 */
1516 krb5_error_code
_kdc_check_anon_policy(krb5_context context,krb5_kdc_configuration * config,hdb_entry_ex * client,hdb_entry_ex * server)1517 _kdc_check_anon_policy (krb5_context context,
1518 krb5_kdc_configuration *config,
1519 hdb_entry_ex *client,
1520 hdb_entry_ex *server)
1521 {
1522 if (!config->allow_anonymous){
1523 kdc_log(context, config, 0,
1524 "Request for anonymous ticket denied by local policy");
1525 return KRB5KDC_ERR_POLICY;
1526 }
1527
1528 return 0;
1529 }
1530
1531 /*
1532 *
1533 */
1534
1535 static krb5_boolean
send_pac_p(krb5_context context,KDC_REQ * req)1536 send_pac_p(krb5_context context, KDC_REQ *req)
1537 {
1538 krb5_error_code ret;
1539 PA_PAC_REQUEST pacreq;
1540 const PA_DATA *pa;
1541 int i = 0;
1542
1543 pa = _kdc_find_padata(req, &i, KRB5_PADATA_PA_PAC_REQUEST);
1544 if (pa == NULL)
1545 return TRUE;
1546
1547 ret = decode_PA_PAC_REQUEST(pa->padata_value.data,
1548 pa->padata_value.length,
1549 &pacreq,
1550 NULL);
1551 if (ret)
1552 return TRUE;
1553 i = pacreq.include_pac;
1554 free_PA_PAC_REQUEST(&pacreq);
1555 if (i == 0)
1556 return FALSE;
1557 return TRUE;
1558 }
1559
1560 /*
1561 *
1562 */
1563
1564 static krb5_error_code
generate_pac(kdc_request_t r,Key * skey)1565 generate_pac(kdc_request_t r, Key *skey)
1566 {
1567 krb5_error_code ret;
1568 krb5_pac p = NULL;
1569 krb5_data data;
1570
1571 ret = _kdc_pac_generate(r->context, r->client, &p);
1572 if (ret) {
1573 _kdc_r_log(r, 0, "PAC generation failed for -- %s",
1574 r->client_name);
1575 return ret;
1576 }
1577 if (p == NULL)
1578 return 0;
1579
1580 ret = _krb5_pac_sign(r->context, p, r->et.authtime,
1581 r->client->entry.principal,
1582 &skey->key, /* Server key */
1583 &skey->key, /* FIXME: should be krbtgt key */
1584 &data);
1585 krb5_pac_free(r->context, p);
1586 if (ret) {
1587 _kdc_r_log(r, 0, "PAC signing failed for -- %s",
1588 r->client_name);
1589 return ret;
1590 }
1591
1592 ret = _kdc_tkt_add_if_relevant_ad(r->context, &r->et,
1593 KRB5_AUTHDATA_WIN2K_PAC,
1594 &data);
1595 krb5_data_free(&data);
1596
1597 return ret;
1598 }
1599
1600 /*
1601 *
1602 */
1603
1604 krb5_boolean
_kdc_is_anonymous(krb5_context context,krb5_const_principal principal)1605 _kdc_is_anonymous(krb5_context context, krb5_const_principal principal)
1606 {
1607 return krb5_principal_is_anonymous(context, principal, KRB5_ANON_MATCH_ANY);
1608 }
1609
1610 static int
require_preauth_p(kdc_request_t r)1611 require_preauth_p(kdc_request_t r)
1612 {
1613 return r->config->require_preauth
1614 || r->client->entry.flags.require_preauth
1615 || r->server->entry.flags.require_preauth;
1616 }
1617
1618
1619 /*
1620 *
1621 */
1622
1623 static krb5_error_code
add_enc_pa_rep(kdc_request_t r)1624 add_enc_pa_rep(kdc_request_t r)
1625 {
1626 krb5_error_code ret;
1627 krb5_crypto crypto;
1628 Checksum checksum;
1629 krb5_data cdata;
1630 size_t len;
1631
1632 ret = krb5_crypto_init(r->context, &r->reply_key, 0, &crypto);
1633 if (ret)
1634 return ret;
1635
1636 ret = krb5_create_checksum(r->context, crypto,
1637 KRB5_KU_AS_REQ, 0,
1638 r->request.data, r->request.length,
1639 &checksum);
1640 krb5_crypto_destroy(r->context, crypto);
1641 if (ret)
1642 return ret;
1643
1644 ASN1_MALLOC_ENCODE(Checksum, cdata.data, cdata.length,
1645 &checksum, &len, ret);
1646 free_Checksum(&checksum);
1647 if (ret)
1648 return ret;
1649 heim_assert(cdata.length == len, "ASN.1 internal error");
1650
1651 if (r->ek.encrypted_pa_data == NULL) {
1652 ALLOC(r->ek.encrypted_pa_data);
1653 if (r->ek.encrypted_pa_data == NULL)
1654 return ENOMEM;
1655 }
1656 ret = krb5_padata_add(r->context, r->ek.encrypted_pa_data,
1657 KRB5_PADATA_REQ_ENC_PA_REP, cdata.data, cdata.length);
1658 if (ret)
1659 return ret;
1660
1661 return krb5_padata_add(r->context, r->ek.encrypted_pa_data,
1662 KRB5_PADATA_FX_FAST, NULL, 0);
1663 }
1664
1665 /*
1666 *
1667 */
1668
1669 krb5_error_code
_kdc_as_rep(kdc_request_t r,krb5_data * reply,const char * from,struct sockaddr * from_addr,int datagram_reply)1670 _kdc_as_rep(kdc_request_t r,
1671 krb5_data *reply,
1672 const char *from,
1673 struct sockaddr *from_addr,
1674 int datagram_reply)
1675 {
1676 krb5_context context = r->context;
1677 krb5_kdc_configuration *config = r->config;
1678 KDC_REQ *req = &r->req;
1679 KDC_REQ_BODY *b = NULL;
1680 AS_REP rep;
1681 KDCOptions f;
1682 krb5_enctype setype;
1683 krb5_error_code ret = 0;
1684 Key *skey;
1685 int found_pa = 0;
1686 int i, flags = HDB_F_FOR_AS_REQ;
1687 METHOD_DATA error_method;
1688 const PA_DATA *pa;
1689
1690 memset(&rep, 0, sizeof(rep));
1691 error_method.len = 0;
1692 error_method.val = NULL;
1693
1694 /*
1695 * Look for FAST armor and unwrap
1696 */
1697 ret = _kdc_fast_unwrap_request(r);
1698 if (ret) {
1699 _kdc_r_log(r, 0, "FAST unwrap request from %s failed: %d", from, ret);
1700 goto out;
1701 }
1702
1703 b = &req->req_body;
1704 f = b->kdc_options;
1705
1706 if (f.canonicalize)
1707 flags |= HDB_F_CANON;
1708
1709 if(b->sname == NULL){
1710 ret = KRB5KRB_ERR_GENERIC;
1711 _kdc_set_e_text(r, "No server in request");
1712 } else{
1713 ret = _krb5_principalname2krb5_principal (context,
1714 &r->server_princ,
1715 *(b->sname),
1716 b->realm);
1717 if (ret == 0)
1718 ret = krb5_unparse_name(context, r->server_princ, &r->server_name);
1719 }
1720 if (ret) {
1721 kdc_log(context, config, 0,
1722 "AS-REQ malformed server name from %s", from);
1723 goto out;
1724 }
1725 if(b->cname == NULL){
1726 ret = KRB5KRB_ERR_GENERIC;
1727 _kdc_set_e_text(r, "No client in request");
1728 } else {
1729 ret = _krb5_principalname2krb5_principal (context,
1730 &r->client_princ,
1731 *(b->cname),
1732 b->realm);
1733 if (ret)
1734 goto out;
1735
1736 ret = krb5_unparse_name(context, r->client_princ, &r->client_name);
1737 }
1738 if (ret) {
1739 kdc_log(context, config, 0,
1740 "AS-REQ malformed client name from %s", from);
1741 goto out;
1742 }
1743
1744 kdc_log(context, config, 0, "AS-REQ %s from %s for %s",
1745 r->client_name, from, r->server_name);
1746
1747 /*
1748 *
1749 */
1750
1751 if (_kdc_is_anonymous(context, r->client_princ) &&
1752 !_kdc_is_anon_request(&r->req)) {
1753 kdc_log(context, config, 0, "Anonymous client w/o anonymous flag");
1754 ret = KRB5KDC_ERR_BADOPTION;
1755 goto out;
1756 }
1757
1758 /*
1759 *
1760 */
1761
1762 ret = _kdc_db_fetch(context, config, r->client_princ,
1763 HDB_F_GET_CLIENT | flags, NULL,
1764 &r->clientdb, &r->client);
1765 if(ret == HDB_ERR_NOT_FOUND_HERE) {
1766 kdc_log(context, config, 5, "client %s does not have secrets at this KDC, need to proxy",
1767 r->client_name);
1768 goto out;
1769 } else if (ret == HDB_ERR_WRONG_REALM) {
1770 char *fixed_client_name = NULL;
1771
1772 ret = krb5_unparse_name(context, r->client->entry.principal,
1773 &fixed_client_name);
1774 if (ret) {
1775 goto out;
1776 }
1777
1778 kdc_log(context, config, 0, "WRONG_REALM - %s -> %s",
1779 r->client_name, fixed_client_name);
1780 free(fixed_client_name);
1781
1782 ret = _kdc_fast_mk_error(context, r,
1783 &error_method,
1784 r->armor_crypto,
1785 &req->req_body,
1786 KRB5_KDC_ERR_WRONG_REALM,
1787 NULL,
1788 r->server_princ,
1789 NULL,
1790 &r->client->entry.principal->realm,
1791 NULL, NULL,
1792 reply);
1793 goto out;
1794 } else if(ret){
1795 const char *msg = krb5_get_error_message(context, ret);
1796 kdc_log(context, config, 0, "UNKNOWN -- %s: %s", r->client_name, msg);
1797 krb5_free_error_message(context, msg);
1798 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
1799 goto out;
1800 }
1801 ret = _kdc_db_fetch(context, config, r->server_princ,
1802 HDB_F_GET_SERVER|HDB_F_GET_KRBTGT | flags,
1803 NULL, NULL, &r->server);
1804 if(ret == HDB_ERR_NOT_FOUND_HERE) {
1805 kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy",
1806 r->server_name);
1807 goto out;
1808 } else if(ret){
1809 const char *msg = krb5_get_error_message(context, ret);
1810 kdc_log(context, config, 0, "UNKNOWN -- %s: %s", r->server_name, msg);
1811 krb5_free_error_message(context, msg);
1812 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
1813 goto out;
1814 }
1815
1816 /*
1817 * Select a session enctype from the list of the crypto system
1818 * supported enctypes that is supported by the client and is one of
1819 * the enctype of the enctype of the service (likely krbtgt).
1820 *
1821 * The latter is used as a hint of what enctypes all KDC support,
1822 * to make sure a newer version of KDC won't generate a session
1823 * enctype that an older version of a KDC in the same realm can't
1824 * decrypt.
1825 */
1826
1827 ret = _kdc_find_etype(context,
1828 krb5_principal_is_krbtgt(context, r->server_princ) ?
1829 config->tgt_use_strongest_session_key :
1830 config->svc_use_strongest_session_key, FALSE,
1831 r->client, b->etype.val, b->etype.len, &r->sessionetype,
1832 NULL);
1833 if (ret) {
1834 kdc_log(context, config, 0,
1835 "Client (%s) from %s has no common enctypes with KDC "
1836 "to use for the session key",
1837 r->client_name, from);
1838 goto out;
1839 }
1840
1841 /*
1842 * Pre-auth processing
1843 */
1844
1845 if(req->padata){
1846 unsigned int n;
1847
1848 log_patypes(context, config, req->padata);
1849
1850 /* Check if preauth matching */
1851
1852 for (n = 0; !found_pa && n < sizeof(pat) / sizeof(pat[0]); n++) {
1853 if (pat[n].validate == NULL)
1854 continue;
1855 if (r->armor_crypto == NULL && (pat[n].flags & PA_REQ_FAST))
1856 continue;
1857
1858 kdc_log(context, config, 5,
1859 "Looking for %s pa-data -- %s", pat[n].name, r->client_name);
1860 i = 0;
1861 pa = _kdc_find_padata(req, &i, pat[n].type);
1862 if (pa) {
1863 ret = pat[n].validate(r, pa);
1864 if (ret != 0) {
1865 goto out;
1866 }
1867 kdc_log(context, config, 0,
1868 "%s pre-authentication succeeded -- %s",
1869 pat[n].name, r->client_name);
1870 found_pa = 1;
1871 r->et.flags.pre_authent = 1;
1872 }
1873 }
1874 }
1875
1876 if (found_pa == 0) {
1877 Key *ckey = NULL;
1878 size_t n;
1879
1880 for (n = 0; n < sizeof(pat) / sizeof(pat[0]); n++) {
1881 if ((pat[n].flags & PA_ANNOUNCE) == 0)
1882 continue;
1883 ret = krb5_padata_add(context, &error_method,
1884 pat[n].type, NULL, 0);
1885 if (ret)
1886 goto out;
1887 }
1888
1889 /*
1890 * If there is a client key, send ETYPE_INFO{,2}
1891 */
1892 ret = _kdc_find_etype(context,
1893 config->preauth_use_strongest_session_key, TRUE,
1894 r->client, b->etype.val, b->etype.len, NULL, &ckey);
1895 if (ret == 0) {
1896
1897 /*
1898 * RFC4120 requires:
1899 * - If the client only knows about old enctypes, then send
1900 * both info replies (we send 'info' first in the list).
1901 * - If the client is 'modern', because it knows about 'new'
1902 * enctype types, then only send the 'info2' reply.
1903 *
1904 * Before we send the full list of etype-info data, we pick
1905 * the client key we would have used anyway below, just pick
1906 * that instead.
1907 */
1908
1909 if (older_enctype(ckey->key.keytype)) {
1910 ret = get_pa_etype_info(context, config,
1911 &error_method, ckey);
1912 if (ret)
1913 goto out;
1914 }
1915 ret = get_pa_etype_info2(context, config,
1916 &error_method, ckey);
1917 if (ret)
1918 goto out;
1919 }
1920
1921 /*
1922 * send requre preauth is its required or anon is requested,
1923 * anon is today only allowed via preauth mechanisms.
1924 */
1925 if (require_preauth_p(r) || _kdc_is_anon_request(&r->req)) {
1926 ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
1927 _kdc_set_e_text(r, "Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ");
1928 goto out;
1929 }
1930
1931 if (ckey == NULL) {
1932 ret = KRB5KDC_ERR_CLIENT_NOTYET;
1933 _kdc_set_e_text(r, "Doesn't have a client key available");
1934 goto out;
1935 }
1936 krb5_free_keyblock_contents(r->context, &r->reply_key);
1937 ret = krb5_copy_keyblock_contents(r->context, &ckey->key, &r->reply_key);
1938 if (ret)
1939 goto out;
1940 }
1941
1942 if (r->clientdb->hdb_auth_status) {
1943 r->clientdb->hdb_auth_status(context, r->clientdb, r->client,
1944 HDB_AUTH_SUCCESS);
1945 }
1946
1947 /*
1948 * Verify flags after the user been required to prove its identity
1949 * with in a preauth mech.
1950 */
1951
1952 ret = _kdc_check_access(context, config, r->client, r->client_name,
1953 r->server, r->server_name,
1954 req, &error_method);
1955 if(ret)
1956 goto out;
1957
1958 if (_kdc_is_anon_request(&r->req)) {
1959 ret = _kdc_check_anon_policy(context, config, r->client, r->server);
1960 if (ret) {
1961 _kdc_set_e_text(r, "Anonymous ticket requests are disabled");
1962 goto out;
1963 }
1964
1965 r->et.flags.anonymous = 1;
1966 }
1967
1968 /*
1969 * Select the best encryption type for the KDC with out regard to
1970 * the client since the client never needs to read that data.
1971 */
1972
1973 ret = _kdc_get_preferred_key(context, config,
1974 r->server, r->server_name,
1975 &setype, &skey);
1976 if(ret)
1977 goto out;
1978
1979 if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey) {
1980 ret = KRB5KDC_ERR_BADOPTION;
1981 _kdc_set_e_text(r, "Bad KDC options");
1982 goto out;
1983 }
1984
1985 /*
1986 * Build reply
1987 */
1988
1989 rep.pvno = 5;
1990 rep.msg_type = krb_as_rep;
1991
1992 if (!config->historical_anon_realm &&
1993 _kdc_is_anonymous(context, r->client_princ)) {
1994 Realm anon_realm = KRB5_ANON_REALM;
1995 ret = copy_Realm(&anon_realm, &rep.crealm);
1996 } else
1997 ret = copy_Realm(&r->client->entry.principal->realm, &rep.crealm);
1998 if (ret)
1999 goto out;
2000 if (r->et.flags.anonymous)
2001 ret = _kdc_make_anonymous_principalname(&rep.cname);
2002 else
2003 ret = _krb5_principal2principalname(&rep.cname, r->client->entry.principal);
2004 if (ret)
2005 goto out;
2006
2007 rep.ticket.tkt_vno = 5;
2008 ret = copy_Realm(&r->server->entry.principal->realm, &rep.ticket.realm);
2009 if (ret)
2010 goto out;
2011 _krb5_principal2principalname(&rep.ticket.sname,
2012 r->server->entry.principal);
2013 /* java 1.6 expects the name to be the same type, lets allow that
2014 * uncomplicated name-types. */
2015 #define CNT(sp,t) (((sp)->sname->name_type) == KRB5_NT_##t)
2016 if (CNT(b, UNKNOWN) || CNT(b, PRINCIPAL) || CNT(b, SRV_INST) || CNT(b, SRV_HST) || CNT(b, SRV_XHST))
2017 rep.ticket.sname.name_type = b->sname->name_type;
2018 #undef CNT
2019
2020 r->et.flags.initial = 1;
2021 if(r->client->entry.flags.forwardable && r->server->entry.flags.forwardable)
2022 r->et.flags.forwardable = f.forwardable;
2023 else if (f.forwardable) {
2024 _kdc_set_e_text(r, "Ticket may not be forwardable");
2025 ret = KRB5KDC_ERR_POLICY;
2026 goto out;
2027 }
2028 if(r->client->entry.flags.proxiable && r->server->entry.flags.proxiable)
2029 r->et.flags.proxiable = f.proxiable;
2030 else if (f.proxiable) {
2031 _kdc_set_e_text(r, "Ticket may not be proxiable");
2032 ret = KRB5KDC_ERR_POLICY;
2033 goto out;
2034 }
2035 if(r->client->entry.flags.postdate && r->server->entry.flags.postdate)
2036 r->et.flags.may_postdate = f.allow_postdate;
2037 else if (f.allow_postdate){
2038 _kdc_set_e_text(r, "Ticket may not be postdate");
2039 ret = KRB5KDC_ERR_POLICY;
2040 goto out;
2041 }
2042
2043 /* check for valid set of addresses */
2044 if(!_kdc_check_addresses(context, config, b->addresses, from_addr)) {
2045 _kdc_set_e_text(r, "Bad address list in requested");
2046 ret = KRB5KRB_AP_ERR_BADADDR;
2047 goto out;
2048 }
2049
2050 ret = copy_PrincipalName(&rep.cname, &r->et.cname);
2051 if (ret)
2052 goto out;
2053 ret = copy_Realm(&rep.crealm, &r->et.crealm);
2054 if (ret)
2055 goto out;
2056
2057 {
2058 time_t start;
2059 time_t t;
2060
2061 start = r->et.authtime = kdc_time;
2062
2063 if(f.postdated && req->req_body.from){
2064 ALLOC(r->et.starttime);
2065 start = *r->et.starttime = *req->req_body.from;
2066 r->et.flags.invalid = 1;
2067 r->et.flags.postdated = 1; /* XXX ??? */
2068 }
2069 _kdc_fix_time(&b->till);
2070 t = *b->till;
2071
2072 /* be careful not overflowing */
2073
2074 if(r->client->entry.max_life)
2075 t = start + min(t - start, *r->client->entry.max_life);
2076 if(r->server->entry.max_life)
2077 t = start + min(t - start, *r->server->entry.max_life);
2078 #if 0
2079 t = min(t, start + realm->max_life);
2080 #endif
2081 r->et.endtime = t;
2082 if(f.renewable_ok && r->et.endtime < *b->till){
2083 f.renewable = 1;
2084 if(b->rtime == NULL){
2085 ALLOC(b->rtime);
2086 *b->rtime = 0;
2087 }
2088 if(*b->rtime < *b->till)
2089 *b->rtime = *b->till;
2090 }
2091 if(f.renewable && b->rtime){
2092 t = *b->rtime;
2093 if(t == 0)
2094 t = MAX_TIME;
2095 if(r->client->entry.max_renew)
2096 t = start + min(t - start, *r->client->entry.max_renew);
2097 if(r->server->entry.max_renew)
2098 t = start + min(t - start, *r->server->entry.max_renew);
2099 #if 0
2100 t = min(t, start + realm->max_renew);
2101 #endif
2102 ALLOC(r->et.renew_till);
2103 *r->et.renew_till = t;
2104 r->et.flags.renewable = 1;
2105 }
2106 }
2107
2108 if(b->addresses){
2109 ALLOC(r->et.caddr);
2110 copy_HostAddresses(b->addresses, r->et.caddr);
2111 }
2112
2113 r->et.transited.tr_type = DOMAIN_X500_COMPRESS;
2114 krb5_data_zero(&r->et.transited.contents);
2115
2116 /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
2117 * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
2118 * incapable of correctly decoding SEQUENCE OF's of zero length.
2119 *
2120 * To fix this, always send at least one no-op last_req
2121 *
2122 * If there's a pw_end or valid_end we will use that,
2123 * otherwise just a dummy lr.
2124 */
2125 r->ek.last_req.val = malloc(2 * sizeof(*r->ek.last_req.val));
2126 if (r->ek.last_req.val == NULL) {
2127 ret = ENOMEM;
2128 goto out;
2129 }
2130 r->ek.last_req.len = 0;
2131 if (r->client->entry.pw_end
2132 && (config->kdc_warn_pwexpire == 0
2133 || kdc_time + config->kdc_warn_pwexpire >= *r->client->entry.pw_end)) {
2134 r->ek.last_req.val[r->ek.last_req.len].lr_type = LR_PW_EXPTIME;
2135 r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->entry.pw_end;
2136 ++r->ek.last_req.len;
2137 }
2138 if (r->client->entry.valid_end) {
2139 r->ek.last_req.val[r->ek.last_req.len].lr_type = LR_ACCT_EXPTIME;
2140 r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->entry.valid_end;
2141 ++r->ek.last_req.len;
2142 }
2143 if (r->ek.last_req.len == 0) {
2144 r->ek.last_req.val[r->ek.last_req.len].lr_type = LR_NONE;
2145 r->ek.last_req.val[r->ek.last_req.len].lr_value = 0;
2146 ++r->ek.last_req.len;
2147 }
2148 r->ek.nonce = b->nonce;
2149 if (r->client->entry.valid_end || r->client->entry.pw_end) {
2150 ALLOC(r->ek.key_expiration);
2151 if (r->client->entry.valid_end) {
2152 if (r->client->entry.pw_end)
2153 *r->ek.key_expiration = min(*r->client->entry.valid_end,
2154 *r->client->entry.pw_end);
2155 else
2156 *r->ek.key_expiration = *r->client->entry.valid_end;
2157 } else
2158 *r->ek.key_expiration = *r->client->entry.pw_end;
2159 } else
2160 r->ek.key_expiration = NULL;
2161 r->ek.flags = r->et.flags;
2162 r->ek.authtime = r->et.authtime;
2163 if (r->et.starttime) {
2164 ALLOC(r->ek.starttime);
2165 *r->ek.starttime = *r->et.starttime;
2166 }
2167 r->ek.endtime = r->et.endtime;
2168 if (r->et.renew_till) {
2169 ALLOC(r->ek.renew_till);
2170 *r->ek.renew_till = *r->et.renew_till;
2171 }
2172 ret = copy_Realm(&rep.ticket.realm, &r->ek.srealm);
2173 if (ret)
2174 goto out;
2175 ret = copy_PrincipalName(&rep.ticket.sname, &r->ek.sname);
2176 if (ret)
2177 goto out;
2178 if(r->et.caddr){
2179 ALLOC(r->ek.caddr);
2180 copy_HostAddresses(r->et.caddr, r->ek.caddr);
2181 }
2182
2183 /*
2184 * Check and session and reply keys
2185 */
2186
2187 if (r->session_key.keytype == ETYPE_NULL) {
2188 ret = krb5_generate_random_keyblock(context, r->sessionetype, &r->session_key);
2189 if (ret)
2190 goto out;
2191 }
2192
2193 if (r->reply_key.keytype == ETYPE_NULL) {
2194 _kdc_set_e_text(r, "Client have no reply key");
2195 ret = KRB5KDC_ERR_CLIENT_NOTYET;
2196 goto out;
2197 }
2198
2199 ret = copy_EncryptionKey(&r->session_key, &r->et.key);
2200 if (ret)
2201 goto out;
2202
2203 ret = copy_EncryptionKey(&r->session_key, &r->ek.key);
2204 if (ret)
2205 goto out;
2206
2207 if (r->outpadata.len) {
2208
2209 ALLOC(rep.padata);
2210 if (rep.padata == NULL) {
2211 ret = ENOMEM;
2212 goto out;
2213 }
2214 ret = copy_METHOD_DATA(&r->outpadata, rep.padata);
2215 if (ret)
2216 goto out;
2217 }
2218
2219 /* Add the PAC */
2220 if (send_pac_p(context, req) && !r->et.flags.anonymous) {
2221 generate_pac(r, skey);
2222 }
2223
2224 _kdc_log_timestamp(context, config, "AS-REQ", r->et.authtime, r->et.starttime,
2225 r->et.endtime, r->et.renew_till);
2226
2227 {
2228 krb5_principal client_principal;
2229
2230 ret = _krb5_principalname2krb5_principal(context, &client_principal,
2231 rep.cname, rep.crealm);
2232 if (ret)
2233 goto out;
2234
2235 /* do this as the last thing since this signs the EncTicketPart */
2236 ret = _kdc_add_KRB5SignedPath(context,
2237 config,
2238 r->server,
2239 setype,
2240 client_principal,
2241 NULL,
2242 NULL,
2243 &r->et);
2244 krb5_free_principal(context, client_principal);
2245 if (ret)
2246 goto out;
2247 }
2248
2249 log_as_req(context, config, r->reply_key.keytype, setype, b);
2250
2251 /*
2252 * We always say we support FAST/enc-pa-rep
2253 */
2254
2255 r->et.flags.enc_pa_rep = r->ek.flags.enc_pa_rep = 1;
2256
2257 /*
2258 * Add REQ_ENC_PA_REP if client supports it
2259 */
2260
2261 i = 0;
2262 pa = _kdc_find_padata(req, &i, KRB5_PADATA_REQ_ENC_PA_REP);
2263 if (pa) {
2264
2265 ret = add_enc_pa_rep(r);
2266 if (ret) {
2267 const char *msg = krb5_get_error_message(r->context, ret);
2268 _kdc_r_log(r, 0, "add_enc_pa_rep failed: %s: %d", msg, ret);
2269 krb5_free_error_message(r->context, msg);
2270 goto out;
2271 }
2272 }
2273
2274 /*
2275 *
2276 */
2277
2278 ret = _kdc_encode_reply(context, config,
2279 r->armor_crypto, req->req_body.nonce,
2280 &rep, &r->et, &r->ek, setype, r->server->entry.kvno,
2281 &skey->key, r->client->entry.kvno,
2282 &r->reply_key, 0, &r->e_text, reply);
2283 if (ret)
2284 goto out;
2285
2286 /*
2287 * Check if message too large
2288 */
2289 if (datagram_reply && reply->length > config->max_datagram_reply_length) {
2290 krb5_data_free(reply);
2291 ret = KRB5KRB_ERR_RESPONSE_TOO_BIG;
2292 _kdc_set_e_text(r, "Reply packet too large");
2293 }
2294
2295 out:
2296 free_AS_REP(&rep);
2297
2298 /*
2299 * In case of a non proxy error, build an error message.
2300 */
2301 if (ret != 0 && ret != HDB_ERR_NOT_FOUND_HERE && reply->length == 0) {
2302 ret = _kdc_fast_mk_error(context, r,
2303 &error_method,
2304 r->armor_crypto,
2305 &req->req_body,
2306 ret, r->e_text,
2307 r->server_princ,
2308 r->client_princ ?
2309 &r->client_princ->name : NULL,
2310 r->client_princ ?
2311 &r->client_princ->realm : NULL,
2312 NULL, NULL,
2313 reply);
2314 if (ret)
2315 goto out2;
2316 }
2317 out2:
2318 free_EncTicketPart(&r->et);
2319 free_EncKDCRepPart(&r->ek);
2320 free_KDCFastState(&r->fast);
2321
2322 if (error_method.len)
2323 free_METHOD_DATA(&error_method);
2324 if (r->outpadata.len)
2325 free_METHOD_DATA(&r->outpadata);
2326 if (r->client_princ) {
2327 krb5_free_principal(context, r->client_princ);
2328 r->client_princ = NULL;
2329 }
2330 if (r->client_name) {
2331 free(r->client_name);
2332 r->client_name = NULL;
2333 }
2334 if (r->server_princ){
2335 krb5_free_principal(context, r->server_princ);
2336 r->server_princ = NULL;
2337 }
2338 if (r->server_name) {
2339 free(r->server_name);
2340 r->server_name = NULL;
2341 }
2342 if (r->client)
2343 _kdc_free_ent(context, r->client);
2344 if (r->server)
2345 _kdc_free_ent(context, r->server);
2346 if (r->armor_crypto) {
2347 krb5_crypto_destroy(r->context, r->armor_crypto);
2348 r->armor_crypto = NULL;
2349 }
2350 krb5_free_keyblock_contents(r->context, &r->reply_key);
2351 krb5_free_keyblock_contents(r->context, &r->session_key);
2352 return ret;
2353 }
2354
2355 /*
2356 * Add the AuthorizationData `data´ of `type´ to the last element in
2357 * the sequence of authorization_data in `tkt´ wrapped in an IF_RELEVANT
2358 */
2359
2360 krb5_error_code
_kdc_tkt_add_if_relevant_ad(krb5_context context,EncTicketPart * tkt,int type,const krb5_data * data)2361 _kdc_tkt_add_if_relevant_ad(krb5_context context,
2362 EncTicketPart *tkt,
2363 int type,
2364 const krb5_data *data)
2365 {
2366 krb5_error_code ret;
2367 size_t size = 0;
2368
2369 if (tkt->authorization_data == NULL) {
2370 tkt->authorization_data = calloc(1, sizeof(*tkt->authorization_data));
2371 if (tkt->authorization_data == NULL) {
2372 krb5_set_error_message(context, ENOMEM, "out of memory");
2373 return ENOMEM;
2374 }
2375 }
2376
2377 /* add the entry to the last element */
2378 {
2379 AuthorizationData ad = { 0, NULL };
2380 AuthorizationDataElement ade;
2381
2382 ade.ad_type = type;
2383 ade.ad_data = *data;
2384
2385 ret = add_AuthorizationData(&ad, &ade);
2386 if (ret) {
2387 krb5_set_error_message(context, ret, "add AuthorizationData failed");
2388 return ret;
2389 }
2390
2391 ade.ad_type = KRB5_AUTHDATA_IF_RELEVANT;
2392
2393 ASN1_MALLOC_ENCODE(AuthorizationData,
2394 ade.ad_data.data, ade.ad_data.length,
2395 &ad, &size, ret);
2396 free_AuthorizationData(&ad);
2397 if (ret) {
2398 krb5_set_error_message(context, ret, "ASN.1 encode of "
2399 "AuthorizationData failed");
2400 return ret;
2401 }
2402 if (ade.ad_data.length != size)
2403 krb5_abortx(context, "internal asn.1 encoder error");
2404
2405 ret = add_AuthorizationData(tkt->authorization_data, &ade);
2406 der_free_octet_string(&ade.ad_data);
2407 if (ret) {
2408 krb5_set_error_message(context, ret, "add AuthorizationData failed");
2409 return ret;
2410 }
2411 }
2412
2413 return 0;
2414 }
2415