/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- get_krbtgt_realm
- find_KRB5SignedPath
- _kdc_add_KRB5SignedPath
- check_KRB5SignedPath
- check_PAC
- check_tgs_flags
- check_constrained_delegation
- verify_flags
- fix_transited_encoding
- tgs_make_reply
- tgs_check_authenticator
- find_rpath
- need_referral
- tgs_parse_request
- build_server_referral
- tgs_build_reply
- _kdc_tgs_rep
1 /*
2 * Copyright (c) 1997-2008 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 RCSID("$Id$");
37
38 /*
39 * return the realm of a krbtgt-ticket or NULL
40 */
41
42 static Realm
43 get_krbtgt_realm(const PrincipalName *p)
/* [<][>][^][v][top][bottom][index][help] */
44 {
45 if(p->name_string.len == 2
46 && strcmp(p->name_string.val[0], KRB5_TGS_NAME) == 0)
47 return p->name_string.val[1];
48 else
49 return NULL;
50 }
51
52 /*
53 * The KDC might add a signed path to the ticket authorization data
54 * field. This is to avoid server impersonating clients and the
55 * request constrained delegation.
56 *
57 * This is done by storing a KRB5_AUTHDATA_IF_RELEVANT with a single
58 * entry of type KRB5SignedPath.
59 */
60
61 static krb5_error_code
62 find_KRB5SignedPath(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
63 const AuthorizationData *ad,
64 krb5_data *data)
65 {
66 AuthorizationData child;
67 krb5_error_code ret;
68 int pos;
69
70 if (ad == NULL || ad->len == 0)
71 return KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
72
73 pos = ad->len - 1;
74
75 if (ad->val[pos].ad_type != KRB5_AUTHDATA_IF_RELEVANT)
76 return KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
77
78 ret = decode_AuthorizationData(ad->val[pos].ad_data.data,
79 ad->val[pos].ad_data.length,
80 &child,
81 NULL);
82 if (ret) {
83 krb5_set_error_message(context, ret, "Failed to decode "
84 "IF_RELEVANT with %d", ret);
85 return ret;
86 }
87
88 if (child.len != 1) {
89 free_AuthorizationData(&child);
90 return KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
91 }
92
93 if (child.val[0].ad_type != KRB5_AUTHDATA_SIGNTICKET) {
94 free_AuthorizationData(&child);
95 return KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
96 }
97
98 if (data)
99 ret = der_copy_octet_string(&child.val[0].ad_data, data);
100 free_AuthorizationData(&child);
101 return ret;
102 }
103
104 krb5_error_code
105 _kdc_add_KRB5SignedPath(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
106 krb5_kdc_configuration *config,
107 hdb_entry_ex *krbtgt,
108 krb5_enctype enctype,
109 krb5_const_principal server,
110 KRB5SignedPathPrincipals *principals,
111 EncTicketPart *tkt)
112 {
113 krb5_error_code ret;
114 KRB5SignedPath sp;
115 krb5_data data;
116 krb5_crypto crypto = NULL;
117 size_t size;
118
119 if (server && principals) {
120 ret = add_KRB5SignedPathPrincipals(principals, server);
121 if (ret)
122 return ret;
123 }
124
125 {
126 KRB5SignedPathData spd;
127
128 spd.encticket = *tkt;
129 spd.delegated = principals;
130
131 ASN1_MALLOC_ENCODE(KRB5SignedPathData, data.data, data.length,
132 &spd, &size, ret);
133 if (ret)
134 return ret;
135 if (data.length != size)
136 krb5_abortx(context, "internal asn.1 encoder error");
137 }
138
139 {
140 Key *key;
141 ret = hdb_enctype2key(context, &krbtgt->entry, enctype, &key);
142 if (ret == 0)
143 ret = krb5_crypto_init(context, &key->key, 0, &crypto);
144 if (ret) {
145 free(data.data);
146 return ret;
147 }
148 }
149
150 /*
151 * Fill in KRB5SignedPath
152 */
153
154 sp.etype = enctype;
155 sp.delegated = principals;
156
157 ret = krb5_create_checksum(context, crypto, KRB5_KU_KRB5SIGNEDPATH, 0,
158 data.data, data.length, &sp.cksum);
159 krb5_crypto_destroy(context, crypto);
160 free(data.data);
161 if (ret)
162 return ret;
163
164 ASN1_MALLOC_ENCODE(KRB5SignedPath, data.data, data.length, &sp, &size, ret);
165 free_Checksum(&sp.cksum);
166 if (ret)
167 return ret;
168 if (data.length != size)
169 krb5_abortx(context, "internal asn.1 encoder error");
170
171
172 /*
173 * Add IF-RELEVANT(KRB5SignedPath) to the last slot in
174 * authorization data field.
175 */
176
177 ret = _kdc_tkt_add_if_relevant_ad(context, tkt,
178 KRB5_AUTHDATA_SIGNTICKET, &data);
179 krb5_data_free(&data);
180
181 return ret;
182 }
183
184 static krb5_error_code
185 check_KRB5SignedPath(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
186 krb5_kdc_configuration *config,
187 hdb_entry_ex *krbtgt,
188 EncTicketPart *tkt,
189 KRB5SignedPathPrincipals **delegated,
190 int *signedpath)
191 {
192 krb5_error_code ret;
193 krb5_data data;
194 krb5_crypto crypto = NULL;
195
196 if (delegated)
197 *delegated = NULL;
198
199 ret = find_KRB5SignedPath(context, tkt->authorization_data, &data);
200 if (ret == 0) {
201 KRB5SignedPathData spd;
202 KRB5SignedPath sp;
203 AuthorizationData *ad;
204 size_t size;
205
206 ret = decode_KRB5SignedPath(data.data, data.length, &sp, NULL);
207 krb5_data_free(&data);
208 if (ret)
209 return ret;
210
211 spd.encticket = *tkt;
212 /* the KRB5SignedPath is the last entry */
213 ad = spd.encticket.authorization_data;
214 if (--ad->len == 0)
215 spd.encticket.authorization_data = NULL;
216 spd.delegated = sp.delegated;
217
218 ASN1_MALLOC_ENCODE(KRB5SignedPathData, data.data, data.length,
219 &spd, &size, ret);
220 ad->len++;
221 spd.encticket.authorization_data = ad;
222 if (ret) {
223 free_KRB5SignedPath(&sp);
224 return ret;
225 }
226 if (data.length != size)
227 krb5_abortx(context, "internal asn.1 encoder error");
228
229 {
230 Key *key;
231 ret = hdb_enctype2key(context, &krbtgt->entry, sp.etype, &key);
232 if (ret == 0)
233 ret = krb5_crypto_init(context, &key->key, 0, &crypto);
234 if (ret) {
235 free(data.data);
236 free_KRB5SignedPath(&sp);
237 return ret;
238 }
239 }
240 ret = krb5_verify_checksum(context, crypto, KRB5_KU_KRB5SIGNEDPATH,
241 data.data, data.length,
242 &sp.cksum);
243 krb5_crypto_destroy(context, crypto);
244 free(data.data);
245 if (ret) {
246 free_KRB5SignedPath(&sp);
247 return ret;
248 }
249
250 if (delegated && sp.delegated) {
251
252 *delegated = malloc(sizeof(*sp.delegated));
253 if (*delegated == NULL) {
254 free_KRB5SignedPath(&sp);
255 return ENOMEM;
256 }
257
258 ret = copy_KRB5SignedPathPrincipals(*delegated, sp.delegated);
259 if (ret) {
260 free_KRB5SignedPath(&sp);
261 free(*delegated);
262 *delegated = NULL;
263 return ret;
264 }
265 }
266 free_KRB5SignedPath(&sp);
267
268 *signedpath = 1;
269 }
270
271 return 0;
272 }
273
274 /*
275 *
276 */
277
278 static krb5_error_code
279 check_PAC(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
280 krb5_kdc_configuration *config,
281 const krb5_principal client_principal,
282 hdb_entry_ex *client,
283 hdb_entry_ex *server,
284 const EncryptionKey *server_key,
285 const EncryptionKey *krbtgt_key,
286 EncTicketPart *tkt,
287 krb5_data *rspac,
288 int *signedpath)
289 {
290 AuthorizationData *ad = tkt->authorization_data;
291 unsigned i, j;
292 krb5_error_code ret;
293
294 if (ad == NULL || ad->len == 0)
295 return 0;
296
297 for (i = 0; i < ad->len; i++) {
298 AuthorizationData child;
299
300 if (ad->val[i].ad_type != KRB5_AUTHDATA_IF_RELEVANT)
301 continue;
302
303 ret = decode_AuthorizationData(ad->val[i].ad_data.data,
304 ad->val[i].ad_data.length,
305 &child,
306 NULL);
307 if (ret) {
308 krb5_set_error_message(context, ret, "Failed to decode "
309 "IF_RELEVANT with %d", ret);
310 return ret;
311 }
312 for (j = 0; j < child.len; j++) {
313
314 if (child.val[j].ad_type == KRB5_AUTHDATA_WIN2K_PAC) {
315 krb5_pac pac;
316
317 /* Found PAC */
318 ret = krb5_pac_parse(context,
319 child.val[j].ad_data.data,
320 child.val[j].ad_data.length,
321 &pac);
322 free_AuthorizationData(&child);
323 if (ret)
324 return ret;
325
326 ret = krb5_pac_verify(context, pac, tkt->authtime,
327 client_principal,
328 krbtgt_key, NULL);
329 if (ret) {
330 krb5_pac_free(context, pac);
331 return ret;
332 }
333
334 ret = _kdc_pac_verify(context, client_principal,
335 client, server, &pac);
336 if (ret) {
337 krb5_pac_free(context, pac);
338 return ret;
339 }
340 *signedpath = 1;
341
342 ret = _krb5_pac_sign(context, pac, tkt->authtime,
343 client_principal,
344 server_key, krbtgt_key, rspac);
345
346 krb5_pac_free(context, pac);
347
348 return ret;
349 }
350 }
351 free_AuthorizationData(&child);
352 }
353 return 0;
354 }
355
356 /*
357 *
358 */
359
360 static krb5_error_code
361 check_tgs_flags(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
362 krb5_kdc_configuration *config,
363 KDC_REQ_BODY *b, const EncTicketPart *tgt, EncTicketPart *et)
364 {
365 KDCOptions f = b->kdc_options;
366
367 if(f.validate){
368 if(!tgt->flags.invalid || tgt->starttime == NULL){
369 kdc_log(context, config, 0,
370 "Bad request to validate ticket");
371 return KRB5KDC_ERR_BADOPTION;
372 }
373 if(*tgt->starttime > kdc_time){
374 kdc_log(context, config, 0,
375 "Early request to validate ticket");
376 return KRB5KRB_AP_ERR_TKT_NYV;
377 }
378 /* XXX tkt = tgt */
379 et->flags.invalid = 0;
380 }else if(tgt->flags.invalid){
381 kdc_log(context, config, 0,
382 "Ticket-granting ticket has INVALID flag set");
383 return KRB5KRB_AP_ERR_TKT_INVALID;
384 }
385
386 if(f.forwardable){
387 if(!tgt->flags.forwardable){
388 kdc_log(context, config, 0,
389 "Bad request for forwardable ticket");
390 return KRB5KDC_ERR_BADOPTION;
391 }
392 et->flags.forwardable = 1;
393 }
394 if(f.forwarded){
395 if(!tgt->flags.forwardable){
396 kdc_log(context, config, 0,
397 "Request to forward non-forwardable ticket");
398 return KRB5KDC_ERR_BADOPTION;
399 }
400 et->flags.forwarded = 1;
401 et->caddr = b->addresses;
402 }
403 if(tgt->flags.forwarded)
404 et->flags.forwarded = 1;
405
406 if(f.proxiable){
407 if(!tgt->flags.proxiable){
408 kdc_log(context, config, 0,
409 "Bad request for proxiable ticket");
410 return KRB5KDC_ERR_BADOPTION;
411 }
412 et->flags.proxiable = 1;
413 }
414 if(f.proxy){
415 if(!tgt->flags.proxiable){
416 kdc_log(context, config, 0,
417 "Request to proxy non-proxiable ticket");
418 return KRB5KDC_ERR_BADOPTION;
419 }
420 et->flags.proxy = 1;
421 et->caddr = b->addresses;
422 }
423 if(tgt->flags.proxy)
424 et->flags.proxy = 1;
425
426 if(f.allow_postdate){
427 if(!tgt->flags.may_postdate){
428 kdc_log(context, config, 0,
429 "Bad request for post-datable ticket");
430 return KRB5KDC_ERR_BADOPTION;
431 }
432 et->flags.may_postdate = 1;
433 }
434 if(f.postdated){
435 if(!tgt->flags.may_postdate){
436 kdc_log(context, config, 0,
437 "Bad request for postdated ticket");
438 return KRB5KDC_ERR_BADOPTION;
439 }
440 if(b->from)
441 *et->starttime = *b->from;
442 et->flags.postdated = 1;
443 et->flags.invalid = 1;
444 }else if(b->from && *b->from > kdc_time + context->max_skew){
445 kdc_log(context, config, 0, "Ticket cannot be postdated");
446 return KRB5KDC_ERR_CANNOT_POSTDATE;
447 }
448
449 if(f.renewable){
450 if(!tgt->flags.renewable){
451 kdc_log(context, config, 0,
452 "Bad request for renewable ticket");
453 return KRB5KDC_ERR_BADOPTION;
454 }
455 et->flags.renewable = 1;
456 ALLOC(et->renew_till);
457 _kdc_fix_time(&b->rtime);
458 *et->renew_till = *b->rtime;
459 }
460 if(f.renew){
461 time_t old_life;
462 if(!tgt->flags.renewable || tgt->renew_till == NULL){
463 kdc_log(context, config, 0,
464 "Request to renew non-renewable ticket");
465 return KRB5KDC_ERR_BADOPTION;
466 }
467 old_life = tgt->endtime;
468 if(tgt->starttime)
469 old_life -= *tgt->starttime;
470 else
471 old_life -= tgt->authtime;
472 et->endtime = *et->starttime + old_life;
473 if (et->renew_till != NULL)
474 et->endtime = min(*et->renew_till, et->endtime);
475 }
476
477 #if 0
478 /* checks for excess flags */
479 if(f.request_anonymous && !config->allow_anonymous){
480 kdc_log(context, config, 0,
481 "Request for anonymous ticket");
482 return KRB5KDC_ERR_BADOPTION;
483 }
484 #endif
485 return 0;
486 }
487
488 /*
489 *
490 */
491
492 static krb5_error_code
493 check_constrained_delegation(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
494 krb5_kdc_configuration *config,
495 hdb_entry_ex *client,
496 krb5_const_principal server)
497 {
498 const HDB_Ext_Constrained_delegation_acl *acl;
499 krb5_error_code ret;
500 int i;
501
502 ret = hdb_entry_get_ConstrainedDelegACL(&client->entry, &acl);
503 if (ret) {
504 krb5_clear_error_message(context);
505 return ret;
506 }
507
508 if (acl) {
509 for (i = 0; i < acl->len; i++) {
510 if (krb5_principal_compare(context, server, &acl->val[i]) == TRUE)
511 return 0;
512 }
513 }
514 kdc_log(context, config, 0,
515 "Bad request for constrained delegation");
516 return KRB5KDC_ERR_BADOPTION;
517 }
518
519 /*
520 *
521 */
522
523 static krb5_error_code
524 verify_flags (krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
525 krb5_kdc_configuration *config,
526 const EncTicketPart *et,
527 const char *pstr)
528 {
529 if(et->endtime < kdc_time){
530 kdc_log(context, config, 0, "Ticket expired (%s)", pstr);
531 return KRB5KRB_AP_ERR_TKT_EXPIRED;
532 }
533 if(et->flags.invalid){
534 kdc_log(context, config, 0, "Ticket not valid (%s)", pstr);
535 return KRB5KRB_AP_ERR_TKT_NYV;
536 }
537 return 0;
538 }
539
540 /*
541 *
542 */
543
544 static krb5_error_code
545 fix_transited_encoding(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
546 krb5_kdc_configuration *config,
547 krb5_boolean check_policy,
548 const TransitedEncoding *tr,
549 EncTicketPart *et,
550 const char *client_realm,
551 const char *server_realm,
552 const char *tgt_realm)
553 {
554 krb5_error_code ret = 0;
555 char **realms, **tmp;
556 unsigned int num_realms;
557 int i;
558
559 switch (tr->tr_type) {
560 case DOMAIN_X500_COMPRESS:
561 break;
562 case 0:
563 /*
564 * Allow empty content of type 0 because that is was Microsoft
565 * generates in their TGT.
566 */
567 if (tr->contents.length == 0)
568 break;
569 kdc_log(context, config, 0,
570 "Transited type 0 with non empty content");
571 return KRB5KDC_ERR_TRTYPE_NOSUPP;
572 default:
573 kdc_log(context, config, 0,
574 "Unknown transited type: %u", tr->tr_type);
575 return KRB5KDC_ERR_TRTYPE_NOSUPP;
576 }
577
578 ret = krb5_domain_x500_decode(context,
579 tr->contents,
580 &realms,
581 &num_realms,
582 client_realm,
583 server_realm);
584 if(ret){
585 krb5_warn(context, ret,
586 "Decoding transited encoding");
587 return ret;
588 }
589 if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)) {
590 /* not us, so add the previous realm to transited set */
591 if (num_realms + 1 > UINT_MAX/sizeof(*realms)) {
592 ret = ERANGE;
593 goto free_realms;
594 }
595 tmp = realloc(realms, (num_realms + 1) * sizeof(*realms));
596 if(tmp == NULL){
597 ret = ENOMEM;
598 goto free_realms;
599 }
600 realms = tmp;
601 realms[num_realms] = strdup(tgt_realm);
602 if(realms[num_realms] == NULL){
603 ret = ENOMEM;
604 goto free_realms;
605 }
606 num_realms++;
607 }
608 if(num_realms == 0) {
609 if(strcmp(client_realm, server_realm))
610 kdc_log(context, config, 0,
611 "cross-realm %s -> %s", client_realm, server_realm);
612 } else {
613 size_t l = 0;
614 char *rs;
615 for(i = 0; i < num_realms; i++)
616 l += strlen(realms[i]) + 2;
617 rs = malloc(l);
618 if(rs != NULL) {
619 *rs = '\0';
620 for(i = 0; i < num_realms; i++) {
621 if(i > 0)
622 strlcat(rs, ", ", l);
623 strlcat(rs, realms[i], l);
624 }
625 kdc_log(context, config, 0,
626 "cross-realm %s -> %s via [%s]",
627 client_realm, server_realm, rs);
628 free(rs);
629 }
630 }
631 if(check_policy) {
632 ret = krb5_check_transited(context, client_realm,
633 server_realm,
634 realms, num_realms, NULL);
635 if(ret) {
636 krb5_warn(context, ret, "cross-realm %s -> %s",
637 client_realm, server_realm);
638 goto free_realms;
639 }
640 et->flags.transited_policy_checked = 1;
641 }
642 et->transited.tr_type = DOMAIN_X500_COMPRESS;
643 ret = krb5_domain_x500_encode(realms, num_realms, &et->transited.contents);
644 if(ret)
645 krb5_warn(context, ret, "Encoding transited encoding");
646 free_realms:
647 for(i = 0; i < num_realms; i++)
648 free(realms[i]);
649 free(realms);
650 return ret;
651 }
652
653
654 static krb5_error_code
655 tgs_make_reply(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
656 krb5_kdc_configuration *config,
657 KDC_REQ_BODY *b,
658 krb5_const_principal tgt_name,
659 const EncTicketPart *tgt,
660 const EncryptionKey *serverkey,
661 const krb5_keyblock *sessionkey,
662 krb5_kvno kvno,
663 AuthorizationData *auth_data,
664 hdb_entry_ex *server,
665 krb5_principal server_principal,
666 const char *server_name,
667 hdb_entry_ex *client,
668 krb5_principal client_principal,
669 hdb_entry_ex *krbtgt,
670 krb5_enctype krbtgt_etype,
671 KRB5SignedPathPrincipals *spp,
672 const krb5_data *rspac,
673 const METHOD_DATA *enc_pa_data,
674 const char **e_text,
675 krb5_data *reply)
676 {
677 KDC_REP rep;
678 EncKDCRepPart ek;
679 EncTicketPart et;
680 KDCOptions f = b->kdc_options;
681 krb5_error_code ret;
682 int is_weak = 0;
683
684 memset(&rep, 0, sizeof(rep));
685 memset(&et, 0, sizeof(et));
686 memset(&ek, 0, sizeof(ek));
687
688 rep.pvno = 5;
689 rep.msg_type = krb_tgs_rep;
690
691 et.authtime = tgt->authtime;
692 _kdc_fix_time(&b->till);
693 et.endtime = min(tgt->endtime, *b->till);
694 ALLOC(et.starttime);
695 *et.starttime = kdc_time;
696
697 ret = check_tgs_flags(context, config, b, tgt, &et);
698 if(ret)
699 goto out;
700
701 /* We should check the transited encoding if:
702 1) the request doesn't ask not to be checked
703 2) globally enforcing a check
704 3) principal requires checking
705 4) we allow non-check per-principal, but principal isn't marked as allowing this
706 5) we don't globally allow this
707 */
708
709 #define GLOBAL_FORCE_TRANSITED_CHECK \
710 (config->trpolicy == TRPOLICY_ALWAYS_CHECK)
711 #define GLOBAL_ALLOW_PER_PRINCIPAL \
712 (config->trpolicy == TRPOLICY_ALLOW_PER_PRINCIPAL)
713 #define GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK \
714 (config->trpolicy == TRPOLICY_ALWAYS_HONOUR_REQUEST)
715
716 /* these will consult the database in future release */
717 #define PRINCIPAL_FORCE_TRANSITED_CHECK(P) 0
718 #define PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(P) 0
719
720 ret = fix_transited_encoding(context, config,
721 !f.disable_transited_check ||
722 GLOBAL_FORCE_TRANSITED_CHECK ||
723 PRINCIPAL_FORCE_TRANSITED_CHECK(server) ||
724 !((GLOBAL_ALLOW_PER_PRINCIPAL &&
725 PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(server)) ||
726 GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK),
727 &tgt->transited, &et,
728 *krb5_princ_realm(context, client_principal),
729 *krb5_princ_realm(context, server->entry.principal),
730 *krb5_princ_realm(context, krbtgt->entry.principal));
731 if(ret)
732 goto out;
733
734 copy_Realm(krb5_princ_realm(context, server_principal),
735 &rep.ticket.realm);
736 _krb5_principal2principalname(&rep.ticket.sname, server_principal);
737 copy_Realm(&tgt_name->realm, &rep.crealm);
738 /*
739 if (f.request_anonymous)
740 _kdc_make_anonymous_principalname (&rep.cname);
741 else */
742
743 copy_PrincipalName(&tgt_name->name, &rep.cname);
744 rep.ticket.tkt_vno = 5;
745
746 ek.caddr = et.caddr;
747 if(et.caddr == NULL)
748 et.caddr = tgt->caddr;
749
750 {
751 time_t life;
752 life = et.endtime - *et.starttime;
753 if(client && client->entry.max_life)
754 life = min(life, *client->entry.max_life);
755 if(server->entry.max_life)
756 life = min(life, *server->entry.max_life);
757 et.endtime = *et.starttime + life;
758 }
759 if(f.renewable_ok && tgt->flags.renewable &&
760 et.renew_till == NULL && et.endtime < *b->till){
761 et.flags.renewable = 1;
762 ALLOC(et.renew_till);
763 *et.renew_till = *b->till;
764 }
765 if(et.renew_till){
766 time_t renew;
767 renew = *et.renew_till - et.authtime;
768 if(client && client->entry.max_renew)
769 renew = min(renew, *client->entry.max_renew);
770 if(server->entry.max_renew)
771 renew = min(renew, *server->entry.max_renew);
772 *et.renew_till = et.authtime + renew;
773 }
774
775 if(et.renew_till){
776 *et.renew_till = min(*et.renew_till, *tgt->renew_till);
777 *et.starttime = min(*et.starttime, *et.renew_till);
778 et.endtime = min(et.endtime, *et.renew_till);
779 }
780
781 *et.starttime = min(*et.starttime, et.endtime);
782
783 if(*et.starttime == et.endtime){
784 ret = KRB5KDC_ERR_NEVER_VALID;
785 goto out;
786 }
787 if(et.renew_till && et.endtime == *et.renew_till){
788 free(et.renew_till);
789 et.renew_till = NULL;
790 et.flags.renewable = 0;
791 }
792
793 et.flags.pre_authent = tgt->flags.pre_authent;
794 et.flags.hw_authent = tgt->flags.hw_authent;
795 et.flags.anonymous = tgt->flags.anonymous;
796 et.flags.ok_as_delegate = server->entry.flags.ok_as_delegate;
797
798 if (auth_data) {
799 /* XXX Check enc-authorization-data */
800 et.authorization_data = calloc(1, sizeof(*et.authorization_data));
801 if (et.authorization_data == NULL) {
802 ret = ENOMEM;
803 goto out;
804 }
805 ret = copy_AuthorizationData(auth_data, et.authorization_data);
806 if (ret)
807 goto out;
808
809 /* Filter out type KRB5SignedPath */
810 ret = find_KRB5SignedPath(context, et.authorization_data, NULL);
811 if (ret == 0) {
812 if (et.authorization_data->len == 1) {
813 free_AuthorizationData(et.authorization_data);
814 free(et.authorization_data);
815 et.authorization_data = NULL;
816 } else {
817 AuthorizationData *ad = et.authorization_data;
818 free_AuthorizationDataElement(&ad->val[ad->len - 1]);
819 ad->len--;
820 }
821 }
822 }
823
824 if(rspac->length) {
825 /*
826 * No not need to filter out the any PAC from the
827 * auth_data since it's signed by the KDC.
828 */
829 ret = _kdc_tkt_add_if_relevant_ad(context, &et,
830 KRB5_AUTHDATA_WIN2K_PAC,
831 rspac);
832 if (ret)
833 goto out;
834 }
835
836 ret = krb5_copy_keyblock_contents(context, sessionkey, &et.key);
837 if (ret)
838 goto out;
839 et.crealm = tgt->crealm;
840 et.cname = tgt_name->name;
841
842 ek.key = et.key;
843 /* MIT must have at least one last_req */
844 ek.last_req.len = 1;
845 ek.last_req.val = calloc(1, sizeof(*ek.last_req.val));
846 if (ek.last_req.val == NULL) {
847 ret = ENOMEM;
848 goto out;
849 }
850 ek.nonce = b->nonce;
851 ek.flags = et.flags;
852 ek.authtime = et.authtime;
853 ek.starttime = et.starttime;
854 ek.endtime = et.endtime;
855 ek.renew_till = et.renew_till;
856 ek.srealm = rep.ticket.realm;
857 ek.sname = rep.ticket.sname;
858
859 _kdc_log_timestamp(context, config, "TGS-REQ", et.authtime, et.starttime,
860 et.endtime, et.renew_till);
861
862 /* Don't sign cross realm tickets, they can't be checked anyway */
863 {
864 char *r = get_krbtgt_realm(&ek.sname);
865
866 if (r == NULL || strcmp(r, ek.srealm) == 0) {
867 ret = _kdc_add_KRB5SignedPath(context,
868 config,
869 krbtgt,
870 krbtgt_etype,
871 NULL,
872 spp,
873 &et);
874 if (ret)
875 goto out;
876 }
877 }
878
879 if (enc_pa_data->len) {
880 rep.padata = calloc(1, sizeof(*rep.padata));
881 if (rep.padata == NULL) {
882 ret = ENOMEM;
883 goto out;
884 }
885 ret = copy_METHOD_DATA(enc_pa_data, rep.padata);
886 if (ret)
887 goto out;
888 }
889
890 if (krb5_enctype_valid(context, et.key.keytype) != 0
891 && _kdc_is_weak_expection(server->entry.principal, et.key.keytype))
892 {
893 krb5_enctype_enable(context, et.key.keytype);
894 is_weak = 1;
895 }
896
897
898 /* It is somewhat unclear where the etype in the following
899 encryption should come from. What we have is a session
900 key in the passed tgt, and a list of preferred etypes
901 *for the new ticket*. Should we pick the best possible
902 etype, given the keytype in the tgt, or should we look
903 at the etype list here as well? What if the tgt
904 session key is DES3 and we want a ticket with a (say)
905 CAST session key. Should the DES3 etype be added to the
906 etype list, even if we don't want a session key with
907 DES3? */
908 ret = _kdc_encode_reply(context, config,
909 &rep, &et, &ek, et.key.keytype,
910 kvno,
911 serverkey, 0, &tgt->key, e_text, reply);
912 if (is_weak)
913 krb5_enctype_disable(context, et.key.keytype);
914
915 out:
916 free_TGS_REP(&rep);
917 free_TransitedEncoding(&et.transited);
918 if(et.starttime)
919 free(et.starttime);
920 if(et.renew_till)
921 free(et.renew_till);
922 if(et.authorization_data) {
923 free_AuthorizationData(et.authorization_data);
924 free(et.authorization_data);
925 }
926 free_LastReq(&ek.last_req);
927 memset(et.key.keyvalue.data, 0, et.key.keyvalue.length);
928 free_EncryptionKey(&et.key);
929 return ret;
930 }
931
932 static krb5_error_code
933 tgs_check_authenticator(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
934 krb5_kdc_configuration *config,
935 krb5_auth_context ac,
936 KDC_REQ_BODY *b,
937 const char **e_text,
938 krb5_keyblock *key)
939 {
940 krb5_authenticator auth;
941 size_t len;
942 unsigned char *buf;
943 size_t buf_size;
944 krb5_error_code ret;
945 krb5_crypto crypto;
946
947 krb5_auth_con_getauthenticator(context, ac, &auth);
948 if(auth->cksum == NULL){
949 kdc_log(context, config, 0, "No authenticator in request");
950 ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
951 goto out;
952 }
953 /*
954 * according to RFC1510 it doesn't need to be keyed,
955 * but according to the latest draft it needs to.
956 */
957 if (
958 #if 0
959 !krb5_checksum_is_keyed(context, auth->cksum->cksumtype)
960 ||
961 #endif
962 !krb5_checksum_is_collision_proof(context, auth->cksum->cksumtype)) {
963 kdc_log(context, config, 0, "Bad checksum type in authenticator: %d",
964 auth->cksum->cksumtype);
965 ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
966 goto out;
967 }
968
969 /* XXX should not re-encode this */
970 ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, b, &len, ret);
971 if(ret){
972 kdc_log(context, config, 0, "Failed to encode KDC-REQ-BODY: %s",
973 krb5_get_err_text(context, ret));
974 goto out;
975 }
976 if(buf_size != len) {
977 free(buf);
978 kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
979 *e_text = "KDC internal error";
980 ret = KRB5KRB_ERR_GENERIC;
981 goto out;
982 }
983 ret = krb5_crypto_init(context, key, 0, &crypto);
984 if (ret) {
985 free(buf);
986 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
987 krb5_get_err_text(context, ret));
988 goto out;
989 }
990 ret = krb5_verify_checksum(context,
991 crypto,
992 KRB5_KU_TGS_REQ_AUTH_CKSUM,
993 buf,
994 len,
995 auth->cksum);
996 free(buf);
997 krb5_crypto_destroy(context, crypto);
998 if(ret){
999 kdc_log(context, config, 0,
1000 "Failed to verify authenticator checksum: %s",
1001 krb5_get_err_text(context, ret));
1002 }
1003 out:
1004 free_Authenticator(auth);
1005 free(auth);
1006 return ret;
1007 }
1008
1009 /*
1010 *
1011 */
1012
1013 static const char *
1014 find_rpath(krb5_context context, Realm crealm, Realm srealm)
/* [<][>][^][v][top][bottom][index][help] */
1015 {
1016 const char *new_realm = krb5_config_get_string(context,
1017 NULL,
1018 "capaths",
1019 crealm,
1020 srealm,
1021 NULL);
1022 return new_realm;
1023 }
1024
1025
1026 static krb5_boolean
1027 need_referral(krb5_context context, krb5_kdc_configuration *config,
/* [<][>][^][v][top][bottom][index][help] */
1028 const KDCOptions * const options, krb5_principal server,
1029 krb5_realm **realms)
1030 {
1031 const char *name;
1032
1033 if(!options->canonicalize && server->name.name_type != KRB5_NT_SRV_INST)
1034 return FALSE;
1035
1036 if (server->name.name_string.len == 1)
1037 name = server->name.name_string.val[0];
1038 if (server->name.name_string.len > 1)
1039 name = server->name.name_string.val[1];
1040 else
1041 return FALSE;
1042
1043 kdc_log(context, config, 0, "Searching referral for %s", name);
1044
1045 return _krb5_get_host_realm_int(context, name, FALSE, realms) == 0;
1046 }
1047
1048 static krb5_error_code
1049 tgs_parse_request(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1050 krb5_kdc_configuration *config,
1051 KDC_REQ_BODY *b,
1052 const PA_DATA *tgs_req,
1053 hdb_entry_ex **krbtgt,
1054 krb5_enctype *krbtgt_etype,
1055 krb5_ticket **ticket,
1056 const char **e_text,
1057 const char *from,
1058 const struct sockaddr *from_addr,
1059 time_t **csec,
1060 int **cusec,
1061 AuthorizationData **auth_data)
1062 {
1063 krb5_ap_req ap_req;
1064 krb5_error_code ret;
1065 krb5_principal princ;
1066 krb5_auth_context ac = NULL;
1067 krb5_flags ap_req_options;
1068 krb5_flags verify_ap_req_flags;
1069 krb5_crypto crypto;
1070 Key *tkey;
1071
1072 *auth_data = NULL;
1073 *csec = NULL;
1074 *cusec = NULL;
1075
1076 memset(&ap_req, 0, sizeof(ap_req));
1077 ret = krb5_decode_ap_req(context, &tgs_req->padata_value, &ap_req);
1078 if(ret){
1079 kdc_log(context, config, 0, "Failed to decode AP-REQ: %s",
1080 krb5_get_err_text(context, ret));
1081 goto out;
1082 }
1083
1084 if(!get_krbtgt_realm(&ap_req.ticket.sname)){
1085 /* XXX check for ticket.sname == req.sname */
1086 kdc_log(context, config, 0, "PA-DATA is not a ticket-granting ticket");
1087 ret = KRB5KDC_ERR_POLICY; /* ? */
1088 goto out;
1089 }
1090
1091 _krb5_principalname2krb5_principal(context,
1092 &princ,
1093 ap_req.ticket.sname,
1094 ap_req.ticket.realm);
1095
1096 ret = _kdc_db_fetch(context, config, princ, HDB_F_GET_KRBTGT, NULL, krbtgt);
1097
1098 if(ret) {
1099 char *p;
1100 ret = krb5_unparse_name(context, princ, &p);
1101 if (ret != 0)
1102 p = "<unparse_name failed>";
1103 krb5_free_principal(context, princ);
1104 kdc_log(context, config, 0,
1105 "Ticket-granting ticket not found in database: %s: %s",
1106 p, krb5_get_err_text(context, ret));
1107 if (ret == 0)
1108 free(p);
1109 ret = KRB5KRB_AP_ERR_NOT_US;
1110 goto out;
1111 }
1112
1113 if(ap_req.ticket.enc_part.kvno &&
1114 *ap_req.ticket.enc_part.kvno != (*krbtgt)->entry.kvno){
1115 char *p;
1116
1117 ret = krb5_unparse_name (context, princ, &p);
1118 krb5_free_principal(context, princ);
1119 if (ret != 0)
1120 p = "<unparse_name failed>";
1121 kdc_log(context, config, 0,
1122 "Ticket kvno = %d, DB kvno = %d (%s)",
1123 *ap_req.ticket.enc_part.kvno,
1124 (*krbtgt)->entry.kvno,
1125 p);
1126 if (ret == 0)
1127 free (p);
1128 ret = KRB5KRB_AP_ERR_BADKEYVER;
1129 goto out;
1130 }
1131
1132 *krbtgt_etype = ap_req.ticket.enc_part.etype;
1133
1134 ret = hdb_enctype2key(context, &(*krbtgt)->entry,
1135 ap_req.ticket.enc_part.etype, &tkey);
1136 if(ret){
1137 char *str = NULL, *p = NULL;
1138
1139 krb5_enctype_to_string(context, ap_req.ticket.enc_part.etype, &str);
1140 krb5_unparse_name(context, princ, &p);
1141 kdc_log(context, config, 0,
1142 "No server key with enctype %s found for %s",
1143 str ? str : "<unknown enctype>",
1144 p ? p : "<unparse_name failed>");
1145 free(str);
1146 free(p);
1147 ret = KRB5KRB_AP_ERR_BADKEYVER;
1148 goto out;
1149 }
1150
1151 if (b->kdc_options.validate)
1152 verify_ap_req_flags = KRB5_VERIFY_AP_REQ_IGNORE_INVALID;
1153 else
1154 verify_ap_req_flags = 0;
1155
1156 ret = krb5_verify_ap_req2(context,
1157 &ac,
1158 &ap_req,
1159 princ,
1160 &tkey->key,
1161 verify_ap_req_flags,
1162 &ap_req_options,
1163 ticket,
1164 KRB5_KU_TGS_REQ_AUTH);
1165
1166 krb5_free_principal(context, princ);
1167 if(ret) {
1168 kdc_log(context, config, 0, "Failed to verify AP-REQ: %s",
1169 krb5_get_err_text(context, ret));
1170 goto out;
1171 }
1172
1173 {
1174 krb5_authenticator auth;
1175
1176 ret = krb5_auth_con_getauthenticator(context, ac, &auth);
1177 if (ret == 0) {
1178 *csec = malloc(sizeof(**csec));
1179 if (*csec == NULL) {
1180 krb5_free_authenticator(context, &auth);
1181 kdc_log(context, config, 0, "malloc failed");
1182 goto out;
1183 }
1184 **csec = auth->ctime;
1185 *cusec = malloc(sizeof(**cusec));
1186 if (*cusec == NULL) {
1187 krb5_free_authenticator(context, &auth);
1188 kdc_log(context, config, 0, "malloc failed");
1189 goto out;
1190 }
1191 **cusec = auth->cusec;
1192 krb5_free_authenticator(context, &auth);
1193 }
1194 }
1195
1196 ret = tgs_check_authenticator(context, config,
1197 ac, b, e_text, &(*ticket)->ticket.key);
1198 if (ret) {
1199 krb5_auth_con_free(context, ac);
1200 goto out;
1201 }
1202
1203 if (b->enc_authorization_data) {
1204 unsigned usage = KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY;
1205 krb5_keyblock *subkey;
1206 krb5_data ad;
1207
1208 ret = krb5_auth_con_getremotesubkey(context,
1209 ac,
1210 &subkey);
1211 if(ret){
1212 krb5_auth_con_free(context, ac);
1213 kdc_log(context, config, 0, "Failed to get remote subkey: %s",
1214 krb5_get_err_text(context, ret));
1215 goto out;
1216 }
1217 if(subkey == NULL){
1218 usage = KRB5_KU_TGS_REQ_AUTH_DAT_SESSION;
1219 ret = krb5_auth_con_getkey(context, ac, &subkey);
1220 if(ret) {
1221 krb5_auth_con_free(context, ac);
1222 kdc_log(context, config, 0, "Failed to get session key: %s",
1223 krb5_get_err_text(context, ret));
1224 goto out;
1225 }
1226 }
1227 if(subkey == NULL){
1228 krb5_auth_con_free(context, ac);
1229 kdc_log(context, config, 0,
1230 "Failed to get key for enc-authorization-data");
1231 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1232 goto out;
1233 }
1234 ret = krb5_crypto_init(context, subkey, 0, &crypto);
1235 if (ret) {
1236 krb5_auth_con_free(context, ac);
1237 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
1238 krb5_get_err_text(context, ret));
1239 goto out;
1240 }
1241 ret = krb5_decrypt_EncryptedData (context,
1242 crypto,
1243 usage,
1244 b->enc_authorization_data,
1245 &ad);
1246 krb5_crypto_destroy(context, crypto);
1247 if(ret){
1248 krb5_auth_con_free(context, ac);
1249 kdc_log(context, config, 0,
1250 "Failed to decrypt enc-authorization-data");
1251 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1252 goto out;
1253 }
1254 krb5_free_keyblock(context, subkey);
1255 ALLOC(*auth_data);
1256 if (*auth_data == NULL) {
1257 krb5_auth_con_free(context, ac);
1258 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1259 goto out;
1260 }
1261 ret = decode_AuthorizationData(ad.data, ad.length, *auth_data, NULL);
1262 if(ret){
1263 krb5_auth_con_free(context, ac);
1264 free(*auth_data);
1265 *auth_data = NULL;
1266 kdc_log(context, config, 0, "Failed to decode authorization data");
1267 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1268 goto out;
1269 }
1270 }
1271
1272 krb5_auth_con_free(context, ac);
1273
1274 out:
1275 free_AP_REQ(&ap_req);
1276
1277 return ret;
1278 }
1279
1280 static krb5_error_code
1281 build_server_referral(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1282 krb5_kdc_configuration *config,
1283 krb5_crypto session,
1284 krb5_const_realm referred_realm,
1285 const PrincipalName *true_principal_name,
1286 const PrincipalName *requested_principal,
1287 krb5_data *outdata)
1288 {
1289 PA_ServerReferralData ref;
1290 krb5_error_code ret;
1291 EncryptedData ed;
1292 krb5_data data;
1293 size_t size;
1294
1295 memset(&ref, 0, sizeof(ref));
1296
1297 if (referred_realm) {
1298 ALLOC(ref.referred_realm);
1299 if (ref.referred_realm == NULL)
1300 goto eout;
1301 *ref.referred_realm = strdup(referred_realm);
1302 if (*ref.referred_realm == NULL)
1303 goto eout;
1304 }
1305 if (true_principal_name) {
1306 ALLOC(ref.true_principal_name);
1307 if (ref.true_principal_name == NULL)
1308 goto eout;
1309 ret = copy_PrincipalName(true_principal_name, ref.true_principal_name);
1310 if (ret)
1311 goto eout;
1312 }
1313 if (requested_principal) {
1314 ALLOC(ref.requested_principal_name);
1315 if (ref.requested_principal_name == NULL)
1316 goto eout;
1317 ret = copy_PrincipalName(requested_principal,
1318 ref.requested_principal_name);
1319 if (ret)
1320 goto eout;
1321 }
1322
1323 ASN1_MALLOC_ENCODE(PA_ServerReferralData,
1324 data.data, data.length,
1325 &ref, &size, ret);
1326 free_PA_ServerReferralData(&ref);
1327 if (ret)
1328 return ret;
1329 if (data.length != size)
1330 krb5_abortx(context, "internal asn.1 encoder error");
1331
1332 ret = krb5_encrypt_EncryptedData(context, session,
1333 KRB5_KU_PA_SERVER_REFERRAL,
1334 data.data, data.length,
1335 0 /* kvno */, &ed);
1336 free(data.data);
1337 if (ret)
1338 return ret;
1339
1340 ASN1_MALLOC_ENCODE(EncryptedData,
1341 outdata->data, outdata->length,
1342 &ed, &size, ret);
1343 free_EncryptedData(&ed);
1344 if (ret)
1345 return ret;
1346 if (outdata->length != size)
1347 krb5_abortx(context, "internal asn.1 encoder error");
1348
1349 return 0;
1350 eout:
1351 free_PA_ServerReferralData(&ref);
1352 krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
1353 return ENOMEM;
1354 }
1355
1356 static krb5_error_code
1357 tgs_build_reply(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1358 krb5_kdc_configuration *config,
1359 KDC_REQ *req,
1360 KDC_REQ_BODY *b,
1361 hdb_entry_ex *krbtgt,
1362 krb5_enctype krbtgt_etype,
1363 krb5_ticket *ticket,
1364 krb5_data *reply,
1365 const char *from,
1366 const char **e_text,
1367 AuthorizationData **auth_data,
1368 const struct sockaddr *from_addr,
1369 int datagram_reply)
1370 {
1371 krb5_error_code ret;
1372 krb5_principal cp = NULL, sp = NULL;
1373 krb5_principal client_principal = NULL;
1374 char *spn = NULL, *cpn = NULL;
1375 hdb_entry_ex *server = NULL, *client = NULL;
1376 krb5_realm ref_realm = NULL;
1377 EncTicketPart *tgt = &ticket->ticket;
1378 KRB5SignedPathPrincipals *spp = NULL;
1379 Key *tkey;
1380 const EncryptionKey *ekey;
1381 krb5_keyblock sessionkey;
1382 krb5_kvno kvno;
1383 krb5_data rspac;
1384 int cross_realm = 0;
1385
1386 METHOD_DATA enc_pa_data;
1387
1388 PrincipalName *s;
1389 Realm r;
1390 int nloop = 0;
1391 EncTicketPart adtkt;
1392 char opt_str[128];
1393 int signedpath = 0;
1394
1395 memset(&sessionkey, 0, sizeof(sessionkey));
1396 memset(&adtkt, 0, sizeof(adtkt));
1397 krb5_data_zero(&rspac);
1398 memset(&enc_pa_data, 0, sizeof(enc_pa_data));
1399
1400 s = b->sname;
1401 r = b->realm;
1402
1403 if(b->kdc_options.enc_tkt_in_skey){
1404 Ticket *t;
1405 hdb_entry_ex *uu;
1406 krb5_principal p;
1407 Key *uukey;
1408
1409 if(b->additional_tickets == NULL ||
1410 b->additional_tickets->len == 0){
1411 ret = KRB5KDC_ERR_BADOPTION; /* ? */
1412 kdc_log(context, config, 0,
1413 "No second ticket present in request");
1414 goto out;
1415 }
1416 t = &b->additional_tickets->val[0];
1417 if(!get_krbtgt_realm(&t->sname)){
1418 kdc_log(context, config, 0,
1419 "Additional ticket is not a ticket-granting ticket");
1420 ret = KRB5KDC_ERR_POLICY;
1421 goto out;
1422 }
1423 _krb5_principalname2krb5_principal(context, &p, t->sname, t->realm);
1424 ret = _kdc_db_fetch(context, config, p,
1425 HDB_F_GET_CLIENT|HDB_F_GET_SERVER,
1426 NULL, &uu);
1427 krb5_free_principal(context, p);
1428 if(ret){
1429 if (ret == HDB_ERR_NOENTRY)
1430 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
1431 goto out;
1432 }
1433 ret = hdb_enctype2key(context, &uu->entry,
1434 t->enc_part.etype, &uukey);
1435 if(ret){
1436 _kdc_free_ent(context, uu);
1437 ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
1438 goto out;
1439 }
1440 ret = krb5_decrypt_ticket(context, t, &uukey->key, &adtkt, 0);
1441 _kdc_free_ent(context, uu);
1442 if(ret)
1443 goto out;
1444
1445 ret = verify_flags(context, config, &adtkt, spn);
1446 if (ret)
1447 goto out;
1448
1449 s = &adtkt.cname;
1450 r = adtkt.crealm;
1451 }
1452
1453 _krb5_principalname2krb5_principal(context, &sp, *s, r);
1454 ret = krb5_unparse_name(context, sp, &spn);
1455 if (ret)
1456 goto out;
1457 _krb5_principalname2krb5_principal(context, &cp, tgt->cname, tgt->crealm);
1458 ret = krb5_unparse_name(context, cp, &cpn);
1459 if (ret)
1460 goto out;
1461 unparse_flags (KDCOptions2int(b->kdc_options),
1462 asn1_KDCOptions_units(),
1463 opt_str, sizeof(opt_str));
1464 if(*opt_str)
1465 kdc_log(context, config, 0,
1466 "TGS-REQ %s from %s for %s [%s]",
1467 cpn, from, spn, opt_str);
1468 else
1469 kdc_log(context, config, 0,
1470 "TGS-REQ %s from %s for %s", cpn, from, spn);
1471
1472 /*
1473 * Fetch server
1474 */
1475
1476 server_lookup:
1477 ret = _kdc_db_fetch(context, config, sp, HDB_F_GET_SERVER | HDB_F_CANON,
1478 NULL, &server);
1479
1480 if(ret){
1481 const char *new_rlm;
1482 Realm req_rlm;
1483 krb5_realm *realms;
1484
1485 if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) {
1486 if(nloop++ < 2) {
1487 new_rlm = find_rpath(context, tgt->crealm, req_rlm);
1488 if(new_rlm) {
1489 kdc_log(context, config, 5, "krbtgt for realm %s "
1490 "not found, trying %s",
1491 req_rlm, new_rlm);
1492 krb5_free_principal(context, sp);
1493 free(spn);
1494 krb5_make_principal(context, &sp, r,
1495 KRB5_TGS_NAME, new_rlm, NULL);
1496 ret = krb5_unparse_name(context, sp, &spn);
1497 if (ret)
1498 goto out;
1499
1500 if (ref_realm)
1501 free(ref_realm);
1502 ref_realm = strdup(new_rlm);
1503 goto server_lookup;
1504 }
1505 }
1506 } else if(need_referral(context, config, &b->kdc_options, sp, &realms)) {
1507 if (strcmp(realms[0], sp->realm) != 0) {
1508 kdc_log(context, config, 5,
1509 "Returning a referral to realm %s for "
1510 "server %s that was not found",
1511 realms[0], spn);
1512 krb5_free_principal(context, sp);
1513 free(spn);
1514 krb5_make_principal(context, &sp, r, KRB5_TGS_NAME,
1515 realms[0], NULL);
1516 ret = krb5_unparse_name(context, sp, &spn);
1517 if (ret)
1518 goto out;
1519
1520 if (ref_realm)
1521 free(ref_realm);
1522 ref_realm = strdup(realms[0]);
1523
1524 krb5_free_host_realm(context, realms);
1525 goto server_lookup;
1526 }
1527 krb5_free_host_realm(context, realms);
1528 }
1529 kdc_log(context, config, 0,
1530 "Server not found in database: %s: %s", spn,
1531 krb5_get_err_text(context, ret));
1532 if (ret == HDB_ERR_NOENTRY)
1533 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
1534 goto out;
1535 }
1536
1537 ret = _kdc_db_fetch(context, config, cp, HDB_F_GET_CLIENT | HDB_F_CANON,
1538 NULL, &client);
1539 if(ret) {
1540 const char *krbtgt_realm;
1541
1542 /*
1543 * If the client belongs to the same realm as our krbtgt, it
1544 * should exist in the local database.
1545 *
1546 */
1547
1548 krbtgt_realm =
1549 krb5_principal_get_comp_string(context,
1550 krbtgt->entry.principal, 1);
1551
1552 if(strcmp(krb5_principal_get_realm(context, cp), krbtgt_realm) == 0) {
1553 if (ret == HDB_ERR_NOENTRY)
1554 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
1555 kdc_log(context, config, 1, "Client no longer in database: %s",
1556 cpn);
1557 goto out;
1558 }
1559
1560 kdc_log(context, config, 1, "Client not found in database: %s: %s",
1561 cpn, krb5_get_err_text(context, ret));
1562
1563 cross_realm = 1;
1564 }
1565
1566 /*
1567 * Select enctype, return key and kvno.
1568 */
1569
1570 {
1571 krb5_enctype etype;
1572
1573 if(b->kdc_options.enc_tkt_in_skey) {
1574 int i;
1575 ekey = &adtkt.key;
1576 for(i = 0; i < b->etype.len; i++)
1577 if (b->etype.val[i] == adtkt.key.keytype)
1578 break;
1579 if(i == b->etype.len) {
1580 kdc_log(context, config, 0,
1581 "Addition ticket have not matching etypes", spp);
1582 krb5_clear_error_message(context);
1583 return KRB5KDC_ERR_ETYPE_NOSUPP;
1584 }
1585 etype = b->etype.val[i];
1586 kvno = 0;
1587 } else {
1588 Key *skey;
1589
1590 ret = _kdc_find_etype(context, server, b->etype.val, b->etype.len,
1591 &skey, &etype);
1592 if(ret) {
1593 kdc_log(context, config, 0,
1594 "Server (%s) has no support for etypes", spn);
1595 return ret;
1596 }
1597 ekey = &skey->key;
1598 kvno = server->entry.kvno;
1599 }
1600
1601 ret = krb5_generate_random_keyblock(context, etype, &sessionkey);
1602 if (ret)
1603 goto out;
1604 }
1605
1606 /*
1607 * Validate authoriation data
1608 */
1609
1610 /*
1611 * Check that service is in the same realm as the krbtgt. If it's
1612 * not the same, it's someone that is using a uni-directional trust
1613 * backward.
1614 */
1615
1616 if (strcmp(krb5_principal_get_realm(context, sp),
1617 krb5_principal_get_comp_string(context,
1618 krbtgt->entry.principal,
1619 1)) != 0) {
1620 char *tpn;
1621 ret = krb5_unparse_name(context, krbtgt->entry.principal, &tpn);
1622 kdc_log(context, config, 0,
1623 "Request with wrong krbtgt: %s",
1624 (ret == 0) ? tpn : "<unknown>");
1625 if(ret == 0)
1626 free(tpn);
1627 ret = KRB5KRB_AP_ERR_NOT_US;
1628 goto out;
1629 }
1630
1631 /* check PAC if there is one */
1632
1633 ret = hdb_enctype2key(context, &krbtgt->entry,
1634 krbtgt_etype, &tkey);
1635 if(ret) {
1636 kdc_log(context, config, 0,
1637 "Failed to find key for krbtgt PAC check");
1638 goto out;
1639 }
1640
1641 ret = check_PAC(context, config, cp,
1642 client, server, ekey, &tkey->key,
1643 tgt, &rspac, &signedpath);
1644 if (ret) {
1645 kdc_log(context, config, 0,
1646 "Verify PAC failed for %s (%s) from %s with %s",
1647 spn, cpn, from, krb5_get_err_text(context, ret));
1648 goto out;
1649 }
1650
1651 /* also check the krbtgt for signature */
1652 ret = check_KRB5SignedPath(context,
1653 config,
1654 krbtgt,
1655 tgt,
1656 &spp,
1657 &signedpath);
1658 if (ret) {
1659 kdc_log(context, config, 0,
1660 "KRB5SignedPath check failed for %s (%s) from %s with %s",
1661 spn, cpn, from, krb5_get_err_text(context, ret));
1662 goto out;
1663 }
1664
1665 /*
1666 * Process request
1667 */
1668
1669 client_principal = cp;
1670
1671 if (client) {
1672 const PA_DATA *sdata;
1673 int i = 0;
1674
1675 sdata = _kdc_find_padata(req, &i, KRB5_PADATA_S4U2SELF);
1676 if (sdata) {
1677 krb5_crypto crypto;
1678 krb5_data datack;
1679 PA_S4U2Self self;
1680 char *selfcpn = NULL;
1681 const char *str;
1682
1683 ret = decode_PA_S4U2Self(sdata->padata_value.data,
1684 sdata->padata_value.length,
1685 &self, NULL);
1686 if (ret) {
1687 kdc_log(context, config, 0, "Failed to decode PA-S4U2Self");
1688 goto out;
1689 }
1690
1691 ret = _krb5_s4u2self_to_checksumdata(context, &self, &datack);
1692 if (ret)
1693 goto out;
1694
1695 ret = krb5_crypto_init(context, &tgt->key, 0, &crypto);
1696 if (ret) {
1697 free_PA_S4U2Self(&self);
1698 krb5_data_free(&datack);
1699 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
1700 krb5_get_err_text(context, ret));
1701 goto out;
1702 }
1703
1704 ret = krb5_verify_checksum(context,
1705 crypto,
1706 KRB5_KU_OTHER_CKSUM,
1707 datack.data,
1708 datack.length,
1709 &self.cksum);
1710 krb5_data_free(&datack);
1711 krb5_crypto_destroy(context, crypto);
1712 if (ret) {
1713 free_PA_S4U2Self(&self);
1714 kdc_log(context, config, 0,
1715 "krb5_verify_checksum failed for S4U2Self: %s",
1716 krb5_get_err_text(context, ret));
1717 goto out;
1718 }
1719
1720 ret = _krb5_principalname2krb5_principal(context,
1721 &client_principal,
1722 self.name,
1723 self.realm);
1724 free_PA_S4U2Self(&self);
1725 if (ret)
1726 goto out;
1727
1728 ret = krb5_unparse_name(context, client_principal, &selfcpn);
1729 if (ret)
1730 goto out;
1731
1732 /*
1733 * Check that service doing the impersonating is
1734 * requesting a ticket to it-self.
1735 */
1736 if (krb5_principal_compare(context, cp, sp) != TRUE) {
1737 kdc_log(context, config, 0, "S4U2Self: %s is not allowed "
1738 "to impersonate some other user "
1739 "(tried for user %s to service %s)",
1740 cpn, selfcpn, spn);
1741 free(selfcpn);
1742 ret = KRB5KDC_ERR_BADOPTION; /* ? */
1743 goto out;
1744 }
1745
1746 /*
1747 * If the service isn't trusted for authentication to
1748 * delegation, remove the forward flag.
1749 */
1750
1751 if (client->entry.flags.trusted_for_delegation) {
1752 str = "[forwardable]";
1753 } else {
1754 b->kdc_options.forwardable = 0;
1755 str = "";
1756 }
1757 kdc_log(context, config, 0, "s4u2self %s impersonating %s to "
1758 "service %s %s", cpn, selfcpn, spn, str);
1759 free(selfcpn);
1760 }
1761 }
1762
1763 /*
1764 * Constrained delegation
1765 */
1766
1767 if (client != NULL
1768 && b->additional_tickets != NULL
1769 && b->additional_tickets->len != 0
1770 && b->kdc_options.enc_tkt_in_skey == 0)
1771 {
1772 int ad_signedpath = 0;
1773 Key *clientkey;
1774 Ticket *t;
1775 char *str;
1776
1777 /*
1778 * Require that the KDC have issued the service's krbtgt (not
1779 * self-issued ticket with kimpersonate(1).
1780 */
1781 if (!signedpath) {
1782 ret = KRB5KDC_ERR_BADOPTION;
1783 kdc_log(context, config, 0,
1784 "Constrained delegation done on service ticket %s/%s",
1785 cpn, spn);
1786 goto out;
1787 }
1788
1789 t = &b->additional_tickets->val[0];
1790
1791 ret = hdb_enctype2key(context, &client->entry,
1792 t->enc_part.etype, &clientkey);
1793 if(ret){
1794 ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
1795 goto out;
1796 }
1797
1798 ret = krb5_decrypt_ticket(context, t, &clientkey->key, &adtkt, 0);
1799 if (ret) {
1800 kdc_log(context, config, 0,
1801 "failed to decrypt ticket for "
1802 "constrained delegation from %s to %s ", spn, cpn);
1803 goto out;
1804 }
1805
1806 /* check that ticket is valid */
1807 if (adtkt.flags.forwardable == 0) {
1808 kdc_log(context, config, 0,
1809 "Missing forwardable flag on ticket for "
1810 "constrained delegation from %s to %s ", spn, cpn);
1811 ret = KRB5KDC_ERR_BADOPTION;
1812 goto out;
1813 }
1814
1815 ret = check_constrained_delegation(context, config, client, sp);
1816 if (ret) {
1817 kdc_log(context, config, 0,
1818 "constrained delegation from %s to %s not allowed",
1819 spn, cpn);
1820 goto out;
1821 }
1822
1823 ret = _krb5_principalname2krb5_principal(context,
1824 &client_principal,
1825 adtkt.cname,
1826 adtkt.crealm);
1827 if (ret)
1828 goto out;
1829
1830 ret = krb5_unparse_name(context, client_principal, &str);
1831 if (ret)
1832 goto out;
1833
1834 ret = verify_flags(context, config, &adtkt, str);
1835 if (ret) {
1836 free(str);
1837 goto out;
1838 }
1839
1840 /*
1841 * Check that the KDC issued the user's ticket.
1842 */
1843 ret = check_KRB5SignedPath(context,
1844 config,
1845 krbtgt,
1846 &adtkt,
1847 NULL,
1848 &ad_signedpath);
1849 if (ret == 0 && !ad_signedpath)
1850 ret = KRB5KDC_ERR_BADOPTION;
1851 if (ret) {
1852 kdc_log(context, config, 0,
1853 "KRB5SignedPath check from service %s failed "
1854 "for delegation to %s for client %s "
1855 "from %s failed with %s",
1856 spn, str, cpn, from, krb5_get_err_text(context, ret));
1857 free(str);
1858 goto out;
1859 }
1860
1861 kdc_log(context, config, 0, "constrained delegation for %s "
1862 "from %s to %s", str, cpn, spn);
1863 free(str);
1864 }
1865
1866 /*
1867 * Check flags
1868 */
1869
1870 ret = _kdc_check_flags(context, config,
1871 client, cpn,
1872 server, spn,
1873 FALSE);
1874 if(ret)
1875 goto out;
1876
1877 if((b->kdc_options.validate || b->kdc_options.renew) &&
1878 !krb5_principal_compare(context,
1879 krbtgt->entry.principal,
1880 server->entry.principal)){
1881 kdc_log(context, config, 0, "Inconsistent request.");
1882 ret = KRB5KDC_ERR_SERVER_NOMATCH;
1883 goto out;
1884 }
1885
1886 /* check for valid set of addresses */
1887 if(!_kdc_check_addresses(context, config, tgt->caddr, from_addr)) {
1888 ret = KRB5KRB_AP_ERR_BADADDR;
1889 kdc_log(context, config, 0, "Request from wrong address");
1890 goto out;
1891 }
1892
1893 /*
1894 * If this is an referral, add server referral data to the
1895 * auth_data reply .
1896 */
1897 if (ref_realm) {
1898 PA_DATA pa;
1899 krb5_crypto crypto;
1900
1901 kdc_log(context, config, 0,
1902 "Adding server referral to %s", ref_realm);
1903
1904 ret = krb5_crypto_init(context, &sessionkey, 0, &crypto);
1905 if (ret)
1906 goto out;
1907
1908 ret = build_server_referral(context, config, crypto, ref_realm,
1909 NULL, s, &pa.padata_value);
1910 krb5_crypto_destroy(context, crypto);
1911 if (ret) {
1912 kdc_log(context, config, 0,
1913 "Failed building server referral");
1914 goto out;
1915 }
1916 pa.padata_type = KRB5_PADATA_SERVER_REFERRAL;
1917
1918 ret = add_METHOD_DATA(&enc_pa_data, &pa);
1919 krb5_data_free(&pa.padata_value);
1920 if (ret) {
1921 kdc_log(context, config, 0,
1922 "Add server referral METHOD-DATA failed");
1923 goto out;
1924 }
1925 }
1926
1927 /*
1928 *
1929 */
1930
1931 ret = tgs_make_reply(context,
1932 config,
1933 b,
1934 client_principal,
1935 tgt,
1936 ekey,
1937 &sessionkey,
1938 kvno,
1939 *auth_data,
1940 server,
1941 sp,
1942 spn,
1943 client,
1944 cp,
1945 krbtgt,
1946 krbtgt_etype,
1947 spp,
1948 &rspac,
1949 &enc_pa_data,
1950 e_text,
1951 reply);
1952
1953 out:
1954 free(spn);
1955 free(cpn);
1956
1957 krb5_data_free(&rspac);
1958 krb5_free_keyblock_contents(context, &sessionkey);
1959 if(server)
1960 _kdc_free_ent(context, server);
1961 if(client)
1962 _kdc_free_ent(context, client);
1963
1964 if (client_principal && client_principal != cp)
1965 krb5_free_principal(context, client_principal);
1966 if (cp)
1967 krb5_free_principal(context, cp);
1968 if (sp)
1969 krb5_free_principal(context, sp);
1970 if (ref_realm)
1971 free(ref_realm);
1972 free_METHOD_DATA(&enc_pa_data);
1973
1974 free_EncTicketPart(&adtkt);
1975
1976 return ret;
1977 }
1978
1979 /*
1980 *
1981 */
1982
1983 krb5_error_code
1984 _kdc_tgs_rep(krb5_context context,
/* [<][>][^][v][top][bottom][index][help] */
1985 krb5_kdc_configuration *config,
1986 KDC_REQ *req,
1987 krb5_data *data,
1988 const char *from,
1989 struct sockaddr *from_addr,
1990 int datagram_reply)
1991 {
1992 AuthorizationData *auth_data = NULL;
1993 krb5_error_code ret;
1994 int i = 0;
1995 const PA_DATA *tgs_req;
1996
1997 hdb_entry_ex *krbtgt = NULL;
1998 krb5_ticket *ticket = NULL;
1999 const char *e_text = NULL;
2000 krb5_enctype krbtgt_etype = ETYPE_NULL;
2001
2002 time_t *csec = NULL;
2003 int *cusec = NULL;
2004
2005 if(req->padata == NULL){
2006 ret = KRB5KDC_ERR_PREAUTH_REQUIRED; /* XXX ??? */
2007 kdc_log(context, config, 0,
2008 "TGS-REQ from %s without PA-DATA", from);
2009 goto out;
2010 }
2011
2012 tgs_req = _kdc_find_padata(req, &i, KRB5_PADATA_TGS_REQ);
2013
2014 if(tgs_req == NULL){
2015 ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
2016
2017 kdc_log(context, config, 0,
2018 "TGS-REQ from %s without PA-TGS-REQ", from);
2019 goto out;
2020 }
2021 ret = tgs_parse_request(context, config,
2022 &req->req_body, tgs_req,
2023 &krbtgt,
2024 &krbtgt_etype,
2025 &ticket,
2026 &e_text,
2027 from, from_addr,
2028 &csec, &cusec,
2029 &auth_data);
2030 if (ret) {
2031 kdc_log(context, config, 0,
2032 "Failed parsing TGS-REQ from %s", from);
2033 goto out;
2034 }
2035
2036 ret = tgs_build_reply(context,
2037 config,
2038 req,
2039 &req->req_body,
2040 krbtgt,
2041 krbtgt_etype,
2042 ticket,
2043 data,
2044 from,
2045 &e_text,
2046 &auth_data,
2047 from_addr,
2048 datagram_reply);
2049 if (ret) {
2050 kdc_log(context, config, 0,
2051 "Failed building TGS-REP to %s", from);
2052 goto out;
2053 }
2054
2055 /* */
2056 if (datagram_reply && data->length > config->max_datagram_reply_length) {
2057 krb5_data_free(data);
2058 ret = KRB5KRB_ERR_RESPONSE_TOO_BIG;
2059 e_text = "Reply packet too large";
2060 }
2061
2062 out:
2063 if(ret && data->data == NULL){
2064 krb5_mk_error(context,
2065 ret,
2066 NULL,
2067 NULL,
2068 NULL,
2069 NULL,
2070 csec,
2071 cusec,
2072 data);
2073 }
2074 free(csec);
2075 free(cusec);
2076 if (ticket)
2077 krb5_free_ticket(context, ticket);
2078 if(krbtgt)
2079 _kdc_free_ent(context, krbtgt);
2080
2081 if (auth_data) {
2082 free_AuthorizationData(auth_data);
2083 free(auth_data);
2084 }
2085
2086 return 0;
2087 }