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