1 /* $NetBSD: krb5tgs.c,v 1.3 2019/12/15 22:50:46 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1997-2008 Kungliga Tekniska Högskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include "kdc_locl.h" 37 38 /* 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_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, 106 krb5_kdc_configuration *config, 107 hdb_entry_ex *krbtgt, 108 krb5_enctype enctype, 109 krb5_const_principal client, 110 krb5_const_principal server, 111 krb5_principals principals, 112 EncTicketPart *tkt) 113 { 114 krb5_error_code ret; 115 KRB5SignedPath sp; 116 krb5_data data; 117 krb5_crypto crypto = NULL; 118 size_t size = 0; 119 120 if (server && principals) { 121 ret = add_Principals(principals, server); 122 if (ret) 123 return ret; 124 } 125 126 { 127 KRB5SignedPathData spd; 128 129 spd.client = rk_UNCONST(client); 130 spd.authtime = tkt->authtime; 131 spd.delegated = principals; 132 spd.method_data = NULL; 133 134 ASN1_MALLOC_ENCODE(KRB5SignedPathData, data.data, data.length, 135 &spd, &size, ret); 136 if (ret) 137 return ret; 138 if (data.length != size) 139 krb5_abortx(context, "internal asn.1 encoder error"); 140 } 141 142 { 143 Key *key; 144 ret = hdb_enctype2key(context, &krbtgt->entry, NULL, enctype, &key); 145 if (ret == 0) 146 ret = krb5_crypto_init(context, &key->key, 0, &crypto); 147 if (ret) { 148 free(data.data); 149 return ret; 150 } 151 } 152 153 /* 154 * Fill in KRB5SignedPath 155 */ 156 157 sp.etype = enctype; 158 sp.delegated = principals; 159 sp.method_data = NULL; 160 161 ret = krb5_create_checksum(context, crypto, KRB5_KU_KRB5SIGNEDPATH, 0, 162 data.data, data.length, &sp.cksum); 163 krb5_crypto_destroy(context, crypto); 164 free(data.data); 165 if (ret) 166 return ret; 167 168 ASN1_MALLOC_ENCODE(KRB5SignedPath, data.data, data.length, &sp, &size, ret); 169 free_Checksum(&sp.cksum); 170 if (ret) 171 return ret; 172 if (data.length != size) 173 krb5_abortx(context, "internal asn.1 encoder error"); 174 175 176 /* 177 * Add IF-RELEVANT(KRB5SignedPath) to the last slot in 178 * authorization data field. 179 */ 180 181 ret = _kdc_tkt_add_if_relevant_ad(context, tkt, 182 KRB5_AUTHDATA_SIGNTICKET, &data); 183 krb5_data_free(&data); 184 185 return ret; 186 } 187 188 static krb5_error_code 189 check_KRB5SignedPath(krb5_context context, 190 krb5_kdc_configuration *config, 191 hdb_entry_ex *krbtgt, 192 krb5_principal cp, 193 EncTicketPart *tkt, 194 krb5_principals *delegated, 195 int *signedpath) 196 { 197 krb5_error_code ret; 198 krb5_data data; 199 krb5_crypto crypto = NULL; 200 201 if (delegated) 202 *delegated = NULL; 203 204 ret = find_KRB5SignedPath(context, tkt->authorization_data, &data); 205 if (ret == 0) { 206 KRB5SignedPathData spd; 207 KRB5SignedPath sp; 208 size_t size = 0; 209 210 ret = decode_KRB5SignedPath(data.data, data.length, &sp, NULL); 211 krb5_data_free(&data); 212 if (ret) 213 return ret; 214 215 spd.client = cp; 216 spd.authtime = tkt->authtime; 217 spd.delegated = sp.delegated; 218 spd.method_data = sp.method_data; 219 220 ASN1_MALLOC_ENCODE(KRB5SignedPathData, data.data, data.length, 221 &spd, &size, ret); 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, NULL, /* XXX use correct kvno! */ 232 sp.etype, &key); 233 if (ret == 0) 234 ret = krb5_crypto_init(context, &key->key, 0, &crypto); 235 if (ret) { 236 free(data.data); 237 free_KRB5SignedPath(&sp); 238 return ret; 239 } 240 } 241 ret = krb5_verify_checksum(context, crypto, KRB5_KU_KRB5SIGNEDPATH, 242 data.data, data.length, 243 &sp.cksum); 244 krb5_crypto_destroy(context, crypto); 245 free(data.data); 246 if (ret) { 247 free_KRB5SignedPath(&sp); 248 kdc_log(context, config, 5, 249 "KRB5SignedPath not signed correctly, not marking as signed"); 250 return 0; 251 } 252 253 if (delegated && sp.delegated) { 254 255 *delegated = malloc(sizeof(*sp.delegated)); 256 if (*delegated == NULL) { 257 free_KRB5SignedPath(&sp); 258 return ENOMEM; 259 } 260 261 ret = copy_Principals(*delegated, sp.delegated); 262 if (ret) { 263 free_KRB5SignedPath(&sp); 264 free(*delegated); 265 *delegated = NULL; 266 return ret; 267 } 268 } 269 free_KRB5SignedPath(&sp); 270 271 *signedpath = 1; 272 } 273 274 return 0; 275 } 276 277 /* 278 * 279 */ 280 281 static krb5_error_code 282 check_PAC(krb5_context context, 283 krb5_kdc_configuration *config, 284 const krb5_principal client_principal, 285 const krb5_principal delegated_proxy_principal, 286 hdb_entry_ex *client, 287 hdb_entry_ex *server, 288 hdb_entry_ex *krbtgt, 289 const EncryptionKey *server_check_key, 290 const EncryptionKey *server_sign_key, 291 const EncryptionKey *krbtgt_sign_key, 292 EncTicketPart *tkt, 293 krb5_data *rspac, 294 int *signedpath) 295 { 296 AuthorizationData *ad = tkt->authorization_data; 297 unsigned i, j; 298 krb5_error_code ret; 299 300 if (ad == NULL || ad->len == 0) 301 return 0; 302 303 for (i = 0; i < ad->len; i++) { 304 AuthorizationData child; 305 306 if (ad->val[i].ad_type != KRB5_AUTHDATA_IF_RELEVANT) 307 continue; 308 309 ret = decode_AuthorizationData(ad->val[i].ad_data.data, 310 ad->val[i].ad_data.length, 311 &child, 312 NULL); 313 if (ret) { 314 krb5_set_error_message(context, ret, "Failed to decode " 315 "IF_RELEVANT with %d", ret); 316 return ret; 317 } 318 for (j = 0; j < child.len; j++) { 319 320 if (child.val[j].ad_type == KRB5_AUTHDATA_WIN2K_PAC) { 321 int signed_pac = 0; 322 krb5_pac pac; 323 324 /* Found PAC */ 325 ret = krb5_pac_parse(context, 326 child.val[j].ad_data.data, 327 child.val[j].ad_data.length, 328 &pac); 329 free_AuthorizationData(&child); 330 if (ret) 331 return ret; 332 333 ret = krb5_pac_verify(context, pac, tkt->authtime, 334 client_principal, 335 server_check_key, NULL); 336 if (ret) { 337 krb5_pac_free(context, pac); 338 return ret; 339 } 340 341 ret = _kdc_pac_verify(context, client_principal, 342 delegated_proxy_principal, 343 client, server, krbtgt, &pac, &signed_pac); 344 if (ret) { 345 krb5_pac_free(context, pac); 346 return ret; 347 } 348 349 /* 350 * Only re-sign PAC if we could verify it with the PAC 351 * function. The no-verify case happens when we get in 352 * a PAC from cross realm from a Windows domain and 353 * that there is no PAC verification function. 354 */ 355 if (signed_pac) { 356 *signedpath = 1; 357 ret = _krb5_pac_sign(context, pac, tkt->authtime, 358 client_principal, 359 server_sign_key, krbtgt_sign_key, rspac); 360 } 361 krb5_pac_free(context, pac); 362 363 return ret; 364 } 365 } 366 free_AuthorizationData(&child); 367 } 368 return 0; 369 } 370 371 static krb5_boolean 372 is_anon_tgs_request_p(const KDC_REQ_BODY *b, 373 const EncTicketPart *tgt) 374 { 375 KDCOptions f = b->kdc_options; 376 377 /* 378 * Versions of Heimdal from 1.0 to 7.6, inclusive, send both the 379 * request-anonymous and cname-in-addl-tkt flags for constrained 380 * delegation requests. A true anonymous TGS request will only 381 * have the request-anonymous flag set. (A corollary of this is 382 * that it is not possible to support anonymous constrained 383 * delegation requests, although they would be of limited utility.) 384 */ 385 return tgt->flags.anonymous || 386 (f.request_anonymous && !f.cname_in_addl_tkt && !b->additional_tickets); 387 } 388 389 /* 390 * 391 */ 392 393 static krb5_error_code 394 check_tgs_flags(krb5_context context, 395 krb5_kdc_configuration *config, 396 KDC_REQ_BODY *b, 397 krb5_const_principal tgt_name, 398 const EncTicketPart *tgt, 399 EncTicketPart *et) 400 { 401 KDCOptions f = b->kdc_options; 402 403 if(f.validate){ 404 if(!tgt->flags.invalid || tgt->starttime == NULL){ 405 kdc_log(context, config, 0, 406 "Bad request to validate ticket"); 407 return KRB5KDC_ERR_BADOPTION; 408 } 409 if(*tgt->starttime > kdc_time){ 410 kdc_log(context, config, 0, 411 "Early request to validate ticket"); 412 return KRB5KRB_AP_ERR_TKT_NYV; 413 } 414 /* XXX tkt = tgt */ 415 et->flags.invalid = 0; 416 }else if(tgt->flags.invalid){ 417 kdc_log(context, config, 0, 418 "Ticket-granting ticket has INVALID flag set"); 419 return KRB5KRB_AP_ERR_TKT_INVALID; 420 } 421 422 if(f.forwardable){ 423 if(!tgt->flags.forwardable){ 424 kdc_log(context, config, 0, 425 "Bad request for forwardable ticket"); 426 return KRB5KDC_ERR_BADOPTION; 427 } 428 et->flags.forwardable = 1; 429 } 430 if(f.forwarded){ 431 if(!tgt->flags.forwardable){ 432 kdc_log(context, config, 0, 433 "Request to forward non-forwardable ticket"); 434 return KRB5KDC_ERR_BADOPTION; 435 } 436 et->flags.forwarded = 1; 437 et->caddr = b->addresses; 438 } 439 if(tgt->flags.forwarded) 440 et->flags.forwarded = 1; 441 442 if(f.proxiable){ 443 if(!tgt->flags.proxiable){ 444 kdc_log(context, config, 0, 445 "Bad request for proxiable ticket"); 446 return KRB5KDC_ERR_BADOPTION; 447 } 448 et->flags.proxiable = 1; 449 } 450 if(f.proxy){ 451 if(!tgt->flags.proxiable){ 452 kdc_log(context, config, 0, 453 "Request to proxy non-proxiable ticket"); 454 return KRB5KDC_ERR_BADOPTION; 455 } 456 et->flags.proxy = 1; 457 et->caddr = b->addresses; 458 } 459 if(tgt->flags.proxy) 460 et->flags.proxy = 1; 461 462 if(f.allow_postdate){ 463 if(!tgt->flags.may_postdate){ 464 kdc_log(context, config, 0, 465 "Bad request for post-datable ticket"); 466 return KRB5KDC_ERR_BADOPTION; 467 } 468 et->flags.may_postdate = 1; 469 } 470 if(f.postdated){ 471 if(!tgt->flags.may_postdate){ 472 kdc_log(context, config, 0, 473 "Bad request for postdated ticket"); 474 return KRB5KDC_ERR_BADOPTION; 475 } 476 if(b->from) 477 *et->starttime = *b->from; 478 et->flags.postdated = 1; 479 et->flags.invalid = 1; 480 }else if(b->from && *b->from > kdc_time + context->max_skew){ 481 kdc_log(context, config, 0, "Ticket cannot be postdated"); 482 return KRB5KDC_ERR_CANNOT_POSTDATE; 483 } 484 485 if(f.renewable){ 486 if(!tgt->flags.renewable || tgt->renew_till == NULL){ 487 kdc_log(context, config, 0, 488 "Bad request for renewable ticket"); 489 return KRB5KDC_ERR_BADOPTION; 490 } 491 et->flags.renewable = 1; 492 ALLOC(et->renew_till); 493 _kdc_fix_time(&b->rtime); 494 *et->renew_till = *b->rtime; 495 } 496 if(f.renew){ 497 time_t old_life; 498 if(!tgt->flags.renewable || tgt->renew_till == NULL){ 499 kdc_log(context, config, 0, 500 "Request to renew non-renewable ticket"); 501 return KRB5KDC_ERR_BADOPTION; 502 } 503 old_life = tgt->endtime; 504 if(tgt->starttime) 505 old_life -= *tgt->starttime; 506 else 507 old_life -= tgt->authtime; 508 et->endtime = *et->starttime + old_life; 509 if (et->renew_till != NULL) 510 et->endtime = min(*et->renew_till, et->endtime); 511 } 512 513 /* 514 * RFC 8062 section 3 defines an anonymous ticket as one containing 515 * the anonymous principal and the anonymous ticket flag. 516 */ 517 if (tgt->flags.anonymous && 518 !_kdc_is_anonymous(context, tgt_name)) { 519 kdc_log(context, config, 0, 520 "Anonymous ticket flag set without anonymous principal"); 521 return KRB5KDC_ERR_BADOPTION; 522 } 523 524 /* 525 * RFC 8062 section 4.2 states that if the TGT is anonymous, the 526 * anonymous KDC option SHOULD be set, but it is not required. 527 * Treat an anonymous TGT as if the anonymous flag was set. 528 */ 529 if (is_anon_tgs_request_p(b, tgt)) 530 et->flags.anonymous = 1; 531 532 return 0; 533 } 534 535 /* 536 * Determine if constrained delegation is allowed from this client to this server 537 */ 538 539 static krb5_error_code 540 check_constrained_delegation(krb5_context context, 541 krb5_kdc_configuration *config, 542 HDB *clientdb, 543 hdb_entry_ex *client, 544 hdb_entry_ex *server, 545 krb5_const_principal target) 546 { 547 const HDB_Ext_Constrained_delegation_acl *acl; 548 krb5_error_code ret; 549 size_t i; 550 551 /* 552 * constrained_delegation (S4U2Proxy) only works within 553 * the same realm. We use the already canonicalized version 554 * of the principals here, while "target" is the principal 555 * provided by the client. 556 */ 557 if(!krb5_realm_compare(context, client->entry.principal, server->entry.principal)) { 558 ret = KRB5KDC_ERR_BADOPTION; 559 kdc_log(context, config, 0, 560 "Bad request for constrained delegation"); 561 return ret; 562 } 563 564 if (clientdb->hdb_check_constrained_delegation) { 565 ret = clientdb->hdb_check_constrained_delegation(context, clientdb, client, target); 566 if (ret == 0) 567 return 0; 568 } else { 569 /* if client delegates to itself, that ok */ 570 if (krb5_principal_compare(context, client->entry.principal, server->entry.principal) == TRUE) 571 return 0; 572 573 ret = hdb_entry_get_ConstrainedDelegACL(&client->entry, &acl); 574 if (ret) { 575 krb5_clear_error_message(context); 576 return ret; 577 } 578 579 if (acl) { 580 for (i = 0; i < acl->len; i++) { 581 if (krb5_principal_compare(context, target, &acl->val[i]) == TRUE) 582 return 0; 583 } 584 } 585 ret = KRB5KDC_ERR_BADOPTION; 586 } 587 kdc_log(context, config, 0, 588 "Bad request for constrained delegation"); 589 return ret; 590 } 591 592 /* 593 * Determine if s4u2self is allowed from this client to this server 594 * 595 * For example, regardless of the principal being impersonated, if the 596 * 'client' and 'server' are the same, then it's safe. 597 */ 598 599 static krb5_error_code 600 check_s4u2self(krb5_context context, 601 krb5_kdc_configuration *config, 602 HDB *clientdb, 603 hdb_entry_ex *client, 604 krb5_const_principal server) 605 { 606 krb5_error_code ret; 607 608 /* if client does a s4u2self to itself, that ok */ 609 if (krb5_principal_compare(context, client->entry.principal, server) == TRUE) 610 return 0; 611 612 if (clientdb->hdb_check_s4u2self) { 613 ret = clientdb->hdb_check_s4u2self(context, clientdb, client, server); 614 if (ret == 0) 615 return 0; 616 } else { 617 ret = KRB5KDC_ERR_BADOPTION; 618 } 619 return ret; 620 } 621 622 /* 623 * 624 */ 625 626 static krb5_error_code 627 verify_flags (krb5_context context, 628 krb5_kdc_configuration *config, 629 const EncTicketPart *et, 630 const char *pstr) 631 { 632 if(et->endtime < kdc_time){ 633 kdc_log(context, config, 0, "Ticket expired (%s)", pstr); 634 return KRB5KRB_AP_ERR_TKT_EXPIRED; 635 } 636 if(et->flags.invalid){ 637 kdc_log(context, config, 0, "Ticket not valid (%s)", pstr); 638 return KRB5KRB_AP_ERR_TKT_NYV; 639 } 640 return 0; 641 } 642 643 /* 644 * 645 */ 646 647 static krb5_error_code 648 fix_transited_encoding(krb5_context context, 649 krb5_kdc_configuration *config, 650 krb5_boolean check_policy, 651 const TransitedEncoding *tr, 652 EncTicketPart *et, 653 const char *client_realm, 654 const char *server_realm, 655 const char *tgt_realm) 656 { 657 krb5_error_code ret = 0; 658 char **realms, **tmp; 659 unsigned int num_realms; 660 size_t i; 661 662 switch (tr->tr_type) { 663 case DOMAIN_X500_COMPRESS: 664 break; 665 case 0: 666 /* 667 * Allow empty content of type 0 because that is was Microsoft 668 * generates in their TGT. 669 */ 670 if (tr->contents.length == 0) 671 break; 672 kdc_log(context, config, 0, 673 "Transited type 0 with non empty content"); 674 return KRB5KDC_ERR_TRTYPE_NOSUPP; 675 default: 676 kdc_log(context, config, 0, 677 "Unknown transited type: %u", tr->tr_type); 678 return KRB5KDC_ERR_TRTYPE_NOSUPP; 679 } 680 681 ret = krb5_domain_x500_decode(context, 682 tr->contents, 683 &realms, 684 &num_realms, 685 client_realm, 686 server_realm); 687 if(ret){ 688 krb5_warn(context, ret, 689 "Decoding transited encoding"); 690 return ret; 691 } 692 693 /* 694 * If the realm of the presented tgt is neither the client nor the server 695 * realm, it is a transit realm and must be added to transited set. 696 */ 697 if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)) { 698 if (num_realms + 1 > UINT_MAX/sizeof(*realms)) { 699 ret = ERANGE; 700 goto free_realms; 701 } 702 tmp = realloc(realms, (num_realms + 1) * sizeof(*realms)); 703 if(tmp == NULL){ 704 ret = ENOMEM; 705 goto free_realms; 706 } 707 realms = tmp; 708 realms[num_realms] = strdup(tgt_realm); 709 if(realms[num_realms] == NULL){ 710 ret = ENOMEM; 711 goto free_realms; 712 } 713 num_realms++; 714 } 715 if(num_realms == 0) { 716 if(strcmp(client_realm, server_realm)) 717 kdc_log(context, config, 0, 718 "cross-realm %s -> %s", client_realm, server_realm); 719 } else { 720 size_t l = 0; 721 char *rs; 722 for(i = 0; i < num_realms; i++) 723 l += strlen(realms[i]) + 2; 724 rs = malloc(l); 725 if(rs != NULL) { 726 *rs = '\0'; 727 for(i = 0; i < num_realms; i++) { 728 if(i > 0) 729 strlcat(rs, ", ", l); 730 strlcat(rs, realms[i], l); 731 } 732 kdc_log(context, config, 0, 733 "cross-realm %s -> %s via [%s]", 734 client_realm, server_realm, rs); 735 free(rs); 736 } 737 } 738 if(check_policy) { 739 ret = krb5_check_transited(context, client_realm, 740 server_realm, 741 realms, num_realms, NULL); 742 if(ret) { 743 krb5_warn(context, ret, "cross-realm %s -> %s", 744 client_realm, server_realm); 745 goto free_realms; 746 } 747 et->flags.transited_policy_checked = 1; 748 } 749 et->transited.tr_type = DOMAIN_X500_COMPRESS; 750 ret = krb5_domain_x500_encode(realms, num_realms, &et->transited.contents); 751 if(ret) 752 krb5_warn(context, ret, "Encoding transited encoding"); 753 free_realms: 754 for(i = 0; i < num_realms; i++) 755 free(realms[i]); 756 free(realms); 757 return ret; 758 } 759 760 761 static krb5_error_code 762 tgs_make_reply(krb5_context context, 763 krb5_kdc_configuration *config, 764 KDC_REQ_BODY *b, 765 krb5_const_principal tgt_name, 766 const EncTicketPart *tgt, 767 const krb5_keyblock *replykey, 768 int rk_is_subkey, 769 const EncryptionKey *serverkey, 770 const krb5_keyblock *sessionkey, 771 krb5_kvno kvno, 772 AuthorizationData *auth_data, 773 hdb_entry_ex *server, 774 krb5_principal server_principal, 775 const char *server_name, 776 hdb_entry_ex *client, 777 krb5_principal client_principal, 778 const char *tgt_realm, 779 hdb_entry_ex *krbtgt, 780 krb5_enctype krbtgt_etype, 781 krb5_principals spp, 782 const krb5_data *rspac, 783 const METHOD_DATA *enc_pa_data, 784 const char **e_text, 785 krb5_data *reply) 786 { 787 KDC_REP rep; 788 EncKDCRepPart ek; 789 EncTicketPart et; 790 KDCOptions f = b->kdc_options; 791 krb5_error_code ret; 792 int is_weak = 0; 793 794 memset(&rep, 0, sizeof(rep)); 795 memset(&et, 0, sizeof(et)); 796 memset(&ek, 0, sizeof(ek)); 797 798 rep.pvno = 5; 799 rep.msg_type = krb_tgs_rep; 800 801 et.authtime = tgt->authtime; 802 _kdc_fix_time(&b->till); 803 et.endtime = min(tgt->endtime, *b->till); 804 ALLOC(et.starttime); 805 *et.starttime = kdc_time; 806 807 ret = check_tgs_flags(context, config, b, tgt_name, tgt, &et); 808 if(ret) 809 goto out; 810 811 /* We should check the transited encoding if: 812 1) the request doesn't ask not to be checked 813 2) globally enforcing a check 814 3) principal requires checking 815 4) we allow non-check per-principal, but principal isn't marked as allowing this 816 5) we don't globally allow this 817 */ 818 819 #define GLOBAL_FORCE_TRANSITED_CHECK \ 820 (config->trpolicy == TRPOLICY_ALWAYS_CHECK) 821 #define GLOBAL_ALLOW_PER_PRINCIPAL \ 822 (config->trpolicy == TRPOLICY_ALLOW_PER_PRINCIPAL) 823 #define GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK \ 824 (config->trpolicy == TRPOLICY_ALWAYS_HONOUR_REQUEST) 825 826 /* these will consult the database in future release */ 827 #define PRINCIPAL_FORCE_TRANSITED_CHECK(P) 0 828 #define PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(P) 0 829 830 ret = fix_transited_encoding(context, config, 831 !f.disable_transited_check || 832 GLOBAL_FORCE_TRANSITED_CHECK || 833 PRINCIPAL_FORCE_TRANSITED_CHECK(server) || 834 !((GLOBAL_ALLOW_PER_PRINCIPAL && 835 PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(server)) || 836 GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK), 837 &tgt->transited, &et, 838 krb5_principal_get_realm(context, client_principal), 839 krb5_principal_get_realm(context, server->entry.principal), 840 tgt_realm); 841 if(ret) 842 goto out; 843 844 ret = copy_Realm(&server_principal->realm, &rep.ticket.realm); 845 if (ret) 846 goto out; 847 _krb5_principal2principalname(&rep.ticket.sname, server_principal); 848 ret = copy_Realm(&tgt_name->realm, &rep.crealm); 849 if (ret) 850 goto out; 851 852 /* 853 * RFC 8062 states "if the ticket in the TGS request is an anonymous 854 * one, the client and client realm are copied from that ticket". So 855 * whilst the TGT flag check below is superfluous, it is included in 856 * order to follow the specification to its letter. 857 */ 858 if (et.flags.anonymous && !tgt->flags.anonymous) 859 _kdc_make_anonymous_principalname(&rep.cname); 860 else 861 ret = copy_PrincipalName(&tgt_name->name, &rep.cname); 862 if (ret) 863 goto out; 864 rep.ticket.tkt_vno = 5; 865 866 ek.caddr = et.caddr; 867 868 { 869 time_t life; 870 life = et.endtime - *et.starttime; 871 if(client && client->entry.max_life) 872 life = min(life, *client->entry.max_life); 873 if(server->entry.max_life) 874 life = min(life, *server->entry.max_life); 875 et.endtime = *et.starttime + life; 876 } 877 if(f.renewable_ok && tgt->flags.renewable && 878 et.renew_till == NULL && et.endtime < *b->till && 879 tgt->renew_till != NULL) 880 { 881 et.flags.renewable = 1; 882 ALLOC(et.renew_till); 883 *et.renew_till = *b->till; 884 } 885 if(et.renew_till){ 886 time_t renew; 887 renew = *et.renew_till - *et.starttime; 888 if(client && client->entry.max_renew) 889 renew = min(renew, *client->entry.max_renew); 890 if(server->entry.max_renew) 891 renew = min(renew, *server->entry.max_renew); 892 *et.renew_till = *et.starttime + renew; 893 } 894 895 if(et.renew_till){ 896 *et.renew_till = min(*et.renew_till, *tgt->renew_till); 897 *et.starttime = min(*et.starttime, *et.renew_till); 898 et.endtime = min(et.endtime, *et.renew_till); 899 } 900 901 *et.starttime = min(*et.starttime, et.endtime); 902 903 if(*et.starttime == et.endtime){ 904 ret = KRB5KDC_ERR_NEVER_VALID; 905 goto out; 906 } 907 if(et.renew_till && et.endtime == *et.renew_till){ 908 free(et.renew_till); 909 et.renew_till = NULL; 910 et.flags.renewable = 0; 911 } 912 913 et.flags.pre_authent = tgt->flags.pre_authent; 914 et.flags.hw_authent = tgt->flags.hw_authent; 915 et.flags.ok_as_delegate = server->entry.flags.ok_as_delegate; 916 917 /* 918 * For anonymous tickets, we should filter out positive authorization data 919 * that could reveal the client's identity, and return a policy error for 920 * restrictive authorization data. Policy for unknown authorization types 921 * is implementation dependent. 922 */ 923 if (rspac->length && !et.flags.anonymous) { 924 /* 925 * No not need to filter out the any PAC from the 926 * auth_data since it's signed by the KDC. 927 */ 928 ret = _kdc_tkt_add_if_relevant_ad(context, &et, 929 KRB5_AUTHDATA_WIN2K_PAC, rspac); 930 if (ret) 931 goto out; 932 } 933 934 if (auth_data) { 935 unsigned int i = 0; 936 937 /* XXX check authdata */ 938 939 if (et.authorization_data == NULL) { 940 et.authorization_data = calloc(1, sizeof(*et.authorization_data)); 941 if (et.authorization_data == NULL) { 942 ret = ENOMEM; 943 krb5_set_error_message(context, ret, "malloc: out of memory"); 944 goto out; 945 } 946 } 947 for(i = 0; i < auth_data->len ; i++) { 948 ret = add_AuthorizationData(et.authorization_data, &auth_data->val[i]); 949 if (ret) { 950 krb5_set_error_message(context, ret, "malloc: out of memory"); 951 goto out; 952 } 953 } 954 955 /* Filter out type KRB5SignedPath */ 956 ret = find_KRB5SignedPath(context, et.authorization_data, NULL); 957 if (ret == 0) { 958 if (et.authorization_data->len == 1) { 959 free_AuthorizationData(et.authorization_data); 960 free(et.authorization_data); 961 et.authorization_data = NULL; 962 } else { 963 AuthorizationData *ad = et.authorization_data; 964 free_AuthorizationDataElement(&ad->val[ad->len - 1]); 965 ad->len--; 966 } 967 } 968 } 969 970 ret = krb5_copy_keyblock_contents(context, sessionkey, &et.key); 971 if (ret) 972 goto out; 973 et.crealm = rep.crealm; 974 et.cname = rep.cname; 975 976 ek.key = et.key; 977 /* MIT must have at least one last_req */ 978 ek.last_req.val = calloc(1, sizeof(*ek.last_req.val)); 979 if (ek.last_req.val == NULL) { 980 ret = ENOMEM; 981 goto out; 982 } 983 ek.last_req.len = 1; /* set after alloc to avoid null deref on cleanup */ 984 ek.nonce = b->nonce; 985 ek.flags = et.flags; 986 ek.authtime = et.authtime; 987 ek.starttime = et.starttime; 988 ek.endtime = et.endtime; 989 ek.renew_till = et.renew_till; 990 ek.srealm = rep.ticket.realm; 991 ek.sname = rep.ticket.sname; 992 993 _kdc_log_timestamp(context, config, "TGS-REQ", et.authtime, et.starttime, 994 et.endtime, et.renew_till); 995 996 /* Don't sign cross realm tickets, they can't be checked anyway */ 997 { 998 char *r = get_krbtgt_realm(&ek.sname); 999 1000 if (r == NULL || strcmp(r, ek.srealm) == 0) { 1001 ret = _kdc_add_KRB5SignedPath(context, 1002 config, 1003 krbtgt, 1004 krbtgt_etype, 1005 client_principal, 1006 NULL, 1007 spp, 1008 &et); 1009 if (ret) 1010 goto out; 1011 } 1012 } 1013 1014 if (enc_pa_data->len) { 1015 rep.padata = calloc(1, sizeof(*rep.padata)); 1016 if (rep.padata == NULL) { 1017 ret = ENOMEM; 1018 goto out; 1019 } 1020 ret = copy_METHOD_DATA(enc_pa_data, rep.padata); 1021 if (ret) 1022 goto out; 1023 } 1024 1025 if (krb5_enctype_valid(context, serverkey->keytype) != 0 1026 && _kdc_is_weak_exception(server->entry.principal, serverkey->keytype)) 1027 { 1028 krb5_enctype_enable(context, serverkey->keytype); 1029 is_weak = 1; 1030 } 1031 1032 1033 /* It is somewhat unclear where the etype in the following 1034 encryption should come from. What we have is a session 1035 key in the passed tgt, and a list of preferred etypes 1036 *for the new ticket*. Should we pick the best possible 1037 etype, given the keytype in the tgt, or should we look 1038 at the etype list here as well? What if the tgt 1039 session key is DES3 and we want a ticket with a (say) 1040 CAST session key. Should the DES3 etype be added to the 1041 etype list, even if we don't want a session key with 1042 DES3? */ 1043 ret = _kdc_encode_reply(context, config, NULL, 0, 1044 &rep, &et, &ek, serverkey->keytype, 1045 kvno, 1046 serverkey, 0, replykey, rk_is_subkey, 1047 e_text, reply); 1048 if (is_weak) 1049 krb5_enctype_disable(context, serverkey->keytype); 1050 1051 out: 1052 free_TGS_REP(&rep); 1053 free_TransitedEncoding(&et.transited); 1054 if(et.starttime) 1055 free(et.starttime); 1056 if(et.renew_till) 1057 free(et.renew_till); 1058 if(et.authorization_data) { 1059 free_AuthorizationData(et.authorization_data); 1060 free(et.authorization_data); 1061 } 1062 free_LastReq(&ek.last_req); 1063 memset(et.key.keyvalue.data, 0, et.key.keyvalue.length); 1064 free_EncryptionKey(&et.key); 1065 return ret; 1066 } 1067 1068 static krb5_error_code 1069 tgs_check_authenticator(krb5_context context, 1070 krb5_kdc_configuration *config, 1071 krb5_auth_context ac, 1072 KDC_REQ_BODY *b, 1073 const char **e_text, 1074 krb5_keyblock *key) 1075 { 1076 krb5_authenticator auth; 1077 size_t len = 0; 1078 unsigned char *buf; 1079 size_t buf_size; 1080 krb5_error_code ret; 1081 krb5_crypto crypto; 1082 1083 krb5_auth_con_getauthenticator(context, ac, &auth); 1084 if(auth->cksum == NULL){ 1085 kdc_log(context, config, 0, "No authenticator in request"); 1086 ret = KRB5KRB_AP_ERR_INAPP_CKSUM; 1087 goto out; 1088 } 1089 /* 1090 * according to RFC1510 it doesn't need to be keyed, 1091 * but according to the latest draft it needs to. 1092 */ 1093 if ( 1094 #if 0 1095 !krb5_checksum_is_keyed(context, auth->cksum->cksumtype) 1096 || 1097 #endif 1098 !krb5_checksum_is_collision_proof(context, auth->cksum->cksumtype)) { 1099 kdc_log(context, config, 0, "Bad checksum type in authenticator: %d", 1100 auth->cksum->cksumtype); 1101 ret = KRB5KRB_AP_ERR_INAPP_CKSUM; 1102 goto out; 1103 } 1104 1105 /* XXX should not re-encode this */ 1106 ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, b, &len, ret); 1107 if(ret){ 1108 const char *msg = krb5_get_error_message(context, ret); 1109 kdc_log(context, config, 0, "Failed to encode KDC-REQ-BODY: %s", msg); 1110 krb5_free_error_message(context, msg); 1111 goto out; 1112 } 1113 if(buf_size != len) { 1114 free(buf); 1115 kdc_log(context, config, 0, "Internal error in ASN.1 encoder"); 1116 *e_text = "KDC internal error"; 1117 ret = KRB5KRB_ERR_GENERIC; 1118 goto out; 1119 } 1120 ret = krb5_crypto_init(context, key, 0, &crypto); 1121 if (ret) { 1122 const char *msg = krb5_get_error_message(context, ret); 1123 free(buf); 1124 kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg); 1125 krb5_free_error_message(context, msg); 1126 goto out; 1127 } 1128 ret = krb5_verify_checksum(context, 1129 crypto, 1130 KRB5_KU_TGS_REQ_AUTH_CKSUM, 1131 buf, 1132 len, 1133 auth->cksum); 1134 free(buf); 1135 krb5_crypto_destroy(context, crypto); 1136 if(ret){ 1137 const char *msg = krb5_get_error_message(context, ret); 1138 kdc_log(context, config, 0, 1139 "Failed to verify authenticator checksum: %s", msg); 1140 krb5_free_error_message(context, msg); 1141 } 1142 out: 1143 free_Authenticator(auth); 1144 free(auth); 1145 return ret; 1146 } 1147 1148 static krb5_boolean 1149 need_referral(krb5_context context, krb5_kdc_configuration *config, 1150 const KDCOptions * const options, krb5_principal server, 1151 krb5_realm **realms) 1152 { 1153 const char *name; 1154 1155 if(!options->canonicalize && server->name.name_type != KRB5_NT_SRV_INST) 1156 return FALSE; 1157 1158 if (server->name.name_string.len == 1) 1159 name = server->name.name_string.val[0]; 1160 else if (server->name.name_string.len == 3) { 1161 /* 1162 This is used to give referrals for the 1163 E3514235-4B06-11D1-AB04-00C04FC2DCD2/NTDSGUID/DNSDOMAIN 1164 SPN form, which is used for inter-domain communication in AD 1165 */ 1166 name = server->name.name_string.val[2]; 1167 kdc_log(context, config, 0, "Giving 3 part referral for %s", name); 1168 *realms = malloc(sizeof(char *)*2); 1169 if (*realms == NULL) { 1170 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 1171 return FALSE; 1172 } 1173 (*realms)[0] = strdup(name); 1174 (*realms)[1] = NULL; 1175 return TRUE; 1176 } else if (server->name.name_string.len > 1) 1177 name = server->name.name_string.val[1]; 1178 else 1179 return FALSE; 1180 1181 kdc_log(context, config, 0, "Searching referral for %s", name); 1182 1183 return _krb5_get_host_realm_int(context, name, FALSE, realms) == 0; 1184 } 1185 1186 static krb5_error_code 1187 tgs_parse_request(krb5_context context, 1188 krb5_kdc_configuration *config, 1189 KDC_REQ_BODY *b, 1190 const PA_DATA *tgs_req, 1191 hdb_entry_ex **krbtgt, 1192 krb5_enctype *krbtgt_etype, 1193 krb5_ticket **ticket, 1194 const char **e_text, 1195 const char *from, 1196 const struct sockaddr *from_addr, 1197 time_t **csec, 1198 int **cusec, 1199 AuthorizationData **auth_data, 1200 krb5_keyblock **replykey, 1201 int *rk_is_subkey) 1202 { 1203 static char failed[] = "<unparse_name failed>"; 1204 krb5_ap_req ap_req; 1205 krb5_error_code ret; 1206 krb5_principal princ; 1207 krb5_auth_context ac = NULL; 1208 krb5_flags ap_req_options; 1209 krb5_flags verify_ap_req_flags; 1210 krb5_crypto crypto; 1211 krb5uint32 krbtgt_kvno; /* kvno used for the PA-TGS-REQ AP-REQ Ticket */ 1212 krb5uint32 krbtgt_kvno_try; 1213 int kvno_search_tries = 4; /* number of kvnos to try when tkt_vno == 0 */ 1214 const Keys *krbtgt_keys;/* keyset for TGT tkt_vno */ 1215 Key *tkey; 1216 krb5_keyblock *subkey = NULL; 1217 unsigned usage; 1218 1219 *auth_data = NULL; 1220 *csec = NULL; 1221 *cusec = NULL; 1222 *replykey = NULL; 1223 1224 memset(&ap_req, 0, sizeof(ap_req)); 1225 ret = krb5_decode_ap_req(context, &tgs_req->padata_value, &ap_req); 1226 if(ret){ 1227 const char *msg = krb5_get_error_message(context, ret); 1228 kdc_log(context, config, 0, "Failed to decode AP-REQ: %s", msg); 1229 krb5_free_error_message(context, msg); 1230 goto out; 1231 } 1232 1233 if(!get_krbtgt_realm(&ap_req.ticket.sname)){ 1234 /* XXX check for ticket.sname == req.sname */ 1235 kdc_log(context, config, 0, "PA-DATA is not a ticket-granting ticket"); 1236 ret = KRB5KDC_ERR_POLICY; /* ? */ 1237 goto out; 1238 } 1239 1240 _krb5_principalname2krb5_principal(context, 1241 &princ, 1242 ap_req.ticket.sname, 1243 ap_req.ticket.realm); 1244 1245 krbtgt_kvno = ap_req.ticket.enc_part.kvno ? *ap_req.ticket.enc_part.kvno : 0; 1246 ret = _kdc_db_fetch(context, config, princ, HDB_F_GET_KRBTGT, 1247 &krbtgt_kvno, NULL, krbtgt); 1248 1249 if (ret == HDB_ERR_NOT_FOUND_HERE) { 1250 /* XXX Factor out this unparsing of the same princ all over */ 1251 char *p; 1252 ret = krb5_unparse_name(context, princ, &p); 1253 if (ret != 0) 1254 p = failed; 1255 krb5_free_principal(context, princ); 1256 kdc_log(context, config, 5, 1257 "Ticket-granting ticket account %s does not have secrets at " 1258 "this KDC, need to proxy", p); 1259 if (ret == 0) 1260 free(p); 1261 ret = HDB_ERR_NOT_FOUND_HERE; 1262 goto out; 1263 } else if (ret == HDB_ERR_KVNO_NOT_FOUND) { 1264 char *p; 1265 ret = krb5_unparse_name(context, princ, &p); 1266 if (ret != 0) 1267 p = failed; 1268 krb5_free_principal(context, princ); 1269 kdc_log(context, config, 5, 1270 "Ticket-granting ticket account %s does not have keys for " 1271 "kvno %d at this KDC", p, krbtgt_kvno); 1272 if (ret == 0) 1273 free(p); 1274 ret = HDB_ERR_KVNO_NOT_FOUND; 1275 goto out; 1276 } else if (ret == HDB_ERR_NO_MKEY) { 1277 char *p; 1278 ret = krb5_unparse_name(context, princ, &p); 1279 if (ret != 0) 1280 p = failed; 1281 krb5_free_principal(context, princ); 1282 kdc_log(context, config, 5, 1283 "Missing master key for decrypting keys for ticket-granting " 1284 "ticket account %s with kvno %d at this KDC", p, krbtgt_kvno); 1285 if (ret == 0) 1286 free(p); 1287 ret = HDB_ERR_KVNO_NOT_FOUND; 1288 goto out; 1289 } else if (ret) { 1290 const char *msg = krb5_get_error_message(context, ret); 1291 char *p; 1292 ret = krb5_unparse_name(context, princ, &p); 1293 if (ret != 0) 1294 p = failed; 1295 krb5_free_principal(context, princ); 1296 kdc_log(context, config, 0, 1297 "Ticket-granting ticket not found in database: %s", msg); 1298 krb5_free_error_message(context, msg); 1299 if (ret == 0) 1300 free(p); 1301 ret = KRB5KRB_AP_ERR_NOT_US; 1302 goto out; 1303 } 1304 1305 krbtgt_kvno_try = krbtgt_kvno ? krbtgt_kvno : (*krbtgt)->entry.kvno; 1306 *krbtgt_etype = ap_req.ticket.enc_part.etype; 1307 1308 next_kvno: 1309 krbtgt_keys = hdb_kvno2keys(context, &(*krbtgt)->entry, krbtgt_kvno_try); 1310 ret = hdb_enctype2key(context, &(*krbtgt)->entry, krbtgt_keys, 1311 ap_req.ticket.enc_part.etype, &tkey); 1312 if (ret && krbtgt_kvno == 0 && kvno_search_tries > 0) { 1313 kvno_search_tries--; 1314 krbtgt_kvno_try--; 1315 goto next_kvno; 1316 } else if (ret) { 1317 char *str = NULL, *p = NULL; 1318 1319 krb5_enctype_to_string(context, ap_req.ticket.enc_part.etype, &str); 1320 krb5_unparse_name(context, princ, &p); 1321 kdc_log(context, config, 0, 1322 "No server key with enctype %s found for %s", 1323 str ? str : "<unknown enctype>", 1324 p ? p : "<unparse_name failed>"); 1325 free(str); 1326 free(p); 1327 ret = KRB5KRB_AP_ERR_BADKEYVER; 1328 goto out; 1329 } 1330 1331 if (b->kdc_options.validate) 1332 verify_ap_req_flags = KRB5_VERIFY_AP_REQ_IGNORE_INVALID; 1333 else 1334 verify_ap_req_flags = 0; 1335 1336 ret = krb5_verify_ap_req2(context, 1337 &ac, 1338 &ap_req, 1339 princ, 1340 &tkey->key, 1341 verify_ap_req_flags, 1342 &ap_req_options, 1343 ticket, 1344 KRB5_KU_TGS_REQ_AUTH); 1345 if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY && kvno_search_tries > 0) { 1346 kvno_search_tries--; 1347 krbtgt_kvno_try--; 1348 goto next_kvno; 1349 } 1350 1351 krb5_free_principal(context, princ); 1352 if(ret) { 1353 const char *msg = krb5_get_error_message(context, ret); 1354 kdc_log(context, config, 0, "Failed to verify AP-REQ: %s", msg); 1355 krb5_free_error_message(context, msg); 1356 goto out; 1357 } 1358 1359 { 1360 krb5_authenticator auth; 1361 1362 ret = krb5_auth_con_getauthenticator(context, ac, &auth); 1363 if (ret == 0) { 1364 *csec = malloc(sizeof(**csec)); 1365 if (*csec == NULL) { 1366 krb5_free_authenticator(context, &auth); 1367 kdc_log(context, config, 0, "malloc failed"); 1368 goto out; 1369 } 1370 **csec = auth->ctime; 1371 *cusec = malloc(sizeof(**cusec)); 1372 if (*cusec == NULL) { 1373 krb5_free_authenticator(context, &auth); 1374 kdc_log(context, config, 0, "malloc failed"); 1375 goto out; 1376 } 1377 **cusec = auth->cusec; 1378 krb5_free_authenticator(context, &auth); 1379 } 1380 } 1381 1382 ret = tgs_check_authenticator(context, config, 1383 ac, b, e_text, &(*ticket)->ticket.key); 1384 if (ret) { 1385 krb5_auth_con_free(context, ac); 1386 goto out; 1387 } 1388 1389 usage = KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY; 1390 *rk_is_subkey = 1; 1391 1392 ret = krb5_auth_con_getremotesubkey(context, ac, &subkey); 1393 if(ret){ 1394 const char *msg = krb5_get_error_message(context, ret); 1395 krb5_auth_con_free(context, ac); 1396 kdc_log(context, config, 0, "Failed to get remote subkey: %s", msg); 1397 krb5_free_error_message(context, msg); 1398 goto out; 1399 } 1400 if(subkey == NULL){ 1401 usage = KRB5_KU_TGS_REQ_AUTH_DAT_SESSION; 1402 *rk_is_subkey = 0; 1403 1404 ret = krb5_auth_con_getkey(context, ac, &subkey); 1405 if(ret) { 1406 const char *msg = krb5_get_error_message(context, ret); 1407 krb5_auth_con_free(context, ac); 1408 kdc_log(context, config, 0, "Failed to get session key: %s", msg); 1409 krb5_free_error_message(context, msg); 1410 goto out; 1411 } 1412 } 1413 if(subkey == NULL){ 1414 krb5_auth_con_free(context, ac); 1415 kdc_log(context, config, 0, 1416 "Failed to get key for enc-authorization-data"); 1417 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */ 1418 goto out; 1419 } 1420 1421 *replykey = subkey; 1422 1423 if (b->enc_authorization_data) { 1424 krb5_data ad; 1425 1426 ret = krb5_crypto_init(context, subkey, 0, &crypto); 1427 if (ret) { 1428 const char *msg = krb5_get_error_message(context, ret); 1429 krb5_auth_con_free(context, ac); 1430 kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg); 1431 krb5_free_error_message(context, msg); 1432 goto out; 1433 } 1434 ret = krb5_decrypt_EncryptedData (context, 1435 crypto, 1436 usage, 1437 b->enc_authorization_data, 1438 &ad); 1439 krb5_crypto_destroy(context, crypto); 1440 if(ret){ 1441 krb5_auth_con_free(context, ac); 1442 kdc_log(context, config, 0, 1443 "Failed to decrypt enc-authorization-data"); 1444 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */ 1445 goto out; 1446 } 1447 ALLOC(*auth_data); 1448 if (*auth_data == NULL) { 1449 krb5_auth_con_free(context, ac); 1450 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */ 1451 goto out; 1452 } 1453 ret = decode_AuthorizationData(ad.data, ad.length, *auth_data, NULL); 1454 if(ret){ 1455 krb5_auth_con_free(context, ac); 1456 free(*auth_data); 1457 *auth_data = NULL; 1458 kdc_log(context, config, 0, "Failed to decode authorization data"); 1459 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */ 1460 goto out; 1461 } 1462 } 1463 1464 krb5_auth_con_free(context, ac); 1465 1466 out: 1467 free_AP_REQ(&ap_req); 1468 1469 return ret; 1470 } 1471 1472 static krb5_error_code 1473 build_server_referral(krb5_context context, 1474 krb5_kdc_configuration *config, 1475 krb5_crypto session, 1476 krb5_const_realm referred_realm, 1477 const PrincipalName *true_principal_name, 1478 const PrincipalName *requested_principal, 1479 krb5_data *outdata) 1480 { 1481 PA_ServerReferralData ref; 1482 krb5_error_code ret; 1483 EncryptedData ed; 1484 krb5_data data; 1485 size_t size = 0; 1486 1487 memset(&ref, 0, sizeof(ref)); 1488 1489 if (referred_realm) { 1490 ALLOC(ref.referred_realm); 1491 if (ref.referred_realm == NULL) 1492 goto eout; 1493 *ref.referred_realm = strdup(referred_realm); 1494 if (*ref.referred_realm == NULL) 1495 goto eout; 1496 } 1497 if (true_principal_name) { 1498 ALLOC(ref.true_principal_name); 1499 if (ref.true_principal_name == NULL) 1500 goto eout; 1501 ret = copy_PrincipalName(true_principal_name, ref.true_principal_name); 1502 if (ret) 1503 goto eout; 1504 } 1505 if (requested_principal) { 1506 ALLOC(ref.requested_principal_name); 1507 if (ref.requested_principal_name == NULL) 1508 goto eout; 1509 ret = copy_PrincipalName(requested_principal, 1510 ref.requested_principal_name); 1511 if (ret) 1512 goto eout; 1513 } 1514 1515 ASN1_MALLOC_ENCODE(PA_ServerReferralData, 1516 data.data, data.length, 1517 &ref, &size, ret); 1518 free_PA_ServerReferralData(&ref); 1519 if (ret) 1520 return ret; 1521 if (data.length != size) 1522 krb5_abortx(context, "internal asn.1 encoder error"); 1523 1524 ret = krb5_encrypt_EncryptedData(context, session, 1525 KRB5_KU_PA_SERVER_REFERRAL, 1526 data.data, data.length, 1527 0 /* kvno */, &ed); 1528 free(data.data); 1529 if (ret) 1530 return ret; 1531 1532 ASN1_MALLOC_ENCODE(EncryptedData, 1533 outdata->data, outdata->length, 1534 &ed, &size, ret); 1535 free_EncryptedData(&ed); 1536 if (ret) 1537 return ret; 1538 if (outdata->length != size) 1539 krb5_abortx(context, "internal asn.1 encoder error"); 1540 1541 return 0; 1542 eout: 1543 free_PA_ServerReferralData(&ref); 1544 krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 1545 return ENOMEM; 1546 } 1547 1548 static krb5_error_code 1549 tgs_build_reply(krb5_context context, 1550 krb5_kdc_configuration *config, 1551 KDC_REQ *req, 1552 KDC_REQ_BODY *b, 1553 hdb_entry_ex *krbtgt, 1554 krb5_enctype krbtgt_etype, 1555 const krb5_keyblock *replykey, 1556 int rk_is_subkey, 1557 krb5_ticket *ticket, 1558 krb5_data *reply, 1559 const char *from, 1560 const char **e_text, 1561 AuthorizationData **auth_data, 1562 const struct sockaddr *from_addr) 1563 { 1564 krb5_error_code ret, ret2; 1565 krb5_principal cp = NULL, sp = NULL, rsp = NULL, tp = NULL, dp = NULL; 1566 krb5_principal krbtgt_out_principal = NULL; 1567 char *spn = NULL, *cpn = NULL, *tpn = NULL, *dpn = NULL, *krbtgt_out_n = NULL; 1568 hdb_entry_ex *server = NULL, *client = NULL, *s4u2self_impersonated_client = NULL; 1569 HDB *clientdb, *s4u2self_impersonated_clientdb; 1570 krb5_realm ref_realm = NULL; 1571 EncTicketPart *tgt = &ticket->ticket; 1572 krb5_principals spp = NULL; 1573 const EncryptionKey *ekey; 1574 krb5_keyblock sessionkey; 1575 krb5_kvno kvno; 1576 krb5_data rspac; 1577 const char *tgt_realm = /* Realm of TGT issuer */ 1578 krb5_principal_get_realm(context, krbtgt->entry.principal); 1579 const char *our_realm = /* Realm of this KDC */ 1580 krb5_principal_get_comp_string(context, krbtgt->entry.principal, 1); 1581 char **capath = NULL; 1582 size_t num_capath = 0; 1583 1584 hdb_entry_ex *krbtgt_out = NULL; 1585 1586 METHOD_DATA enc_pa_data; 1587 1588 PrincipalName *s; 1589 Realm r; 1590 EncTicketPart adtkt; 1591 char opt_str[128]; 1592 int signedpath = 0; 1593 1594 Key *tkey_check; 1595 Key *tkey_sign; 1596 int flags = HDB_F_FOR_TGS_REQ; 1597 1598 memset(&sessionkey, 0, sizeof(sessionkey)); 1599 memset(&adtkt, 0, sizeof(adtkt)); 1600 krb5_data_zero(&rspac); 1601 memset(&enc_pa_data, 0, sizeof(enc_pa_data)); 1602 1603 s = b->sname; 1604 r = b->realm; 1605 1606 /* 1607 * Always to do CANON, see comment below about returned server principal (rsp). 1608 */ 1609 flags |= HDB_F_CANON; 1610 1611 if(b->kdc_options.enc_tkt_in_skey){ 1612 Ticket *t; 1613 hdb_entry_ex *uu; 1614 krb5_principal p; 1615 Key *uukey; 1616 krb5uint32 second_kvno = 0; 1617 krb5uint32 *kvno_ptr = NULL; 1618 1619 if(b->additional_tickets == NULL || 1620 b->additional_tickets->len == 0){ 1621 ret = KRB5KDC_ERR_BADOPTION; /* ? */ 1622 kdc_log(context, config, 0, 1623 "No second ticket present in request"); 1624 goto out; 1625 } 1626 t = &b->additional_tickets->val[0]; 1627 if(!get_krbtgt_realm(&t->sname)){ 1628 kdc_log(context, config, 0, 1629 "Additional ticket is not a ticket-granting ticket"); 1630 ret = KRB5KDC_ERR_POLICY; 1631 goto out; 1632 } 1633 _krb5_principalname2krb5_principal(context, &p, t->sname, t->realm); 1634 if(t->enc_part.kvno){ 1635 second_kvno = *t->enc_part.kvno; 1636 kvno_ptr = &second_kvno; 1637 } 1638 ret = _kdc_db_fetch(context, config, p, 1639 HDB_F_GET_KRBTGT, kvno_ptr, 1640 NULL, &uu); 1641 krb5_free_principal(context, p); 1642 if(ret){ 1643 if (ret == HDB_ERR_NOENTRY) 1644 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; 1645 goto out; 1646 } 1647 ret = hdb_enctype2key(context, &uu->entry, NULL, 1648 t->enc_part.etype, &uukey); 1649 if(ret){ 1650 _kdc_free_ent(context, uu); 1651 ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */ 1652 goto out; 1653 } 1654 ret = krb5_decrypt_ticket(context, t, &uukey->key, &adtkt, 0); 1655 _kdc_free_ent(context, uu); 1656 if(ret) 1657 goto out; 1658 1659 ret = verify_flags(context, config, &adtkt, spn); 1660 if (ret) 1661 goto out; 1662 1663 s = &adtkt.cname; 1664 r = adtkt.crealm; 1665 } 1666 1667 _krb5_principalname2krb5_principal(context, &sp, *s, r); 1668 ret = krb5_unparse_name(context, sp, &spn); 1669 if (ret) 1670 goto out; 1671 _krb5_principalname2krb5_principal(context, &cp, tgt->cname, tgt->crealm); 1672 ret = krb5_unparse_name(context, cp, &cpn); 1673 if (ret) 1674 goto out; 1675 unparse_flags (KDCOptions2int(b->kdc_options), 1676 asn1_KDCOptions_units(), 1677 opt_str, sizeof(opt_str)); 1678 if(*opt_str) 1679 kdc_log(context, config, 0, 1680 "TGS-REQ %s from %s for %s [%s]", 1681 cpn, from, spn, opt_str); 1682 else 1683 kdc_log(context, config, 0, 1684 "TGS-REQ %s from %s for %s", cpn, from, spn); 1685 1686 /* 1687 * Fetch server 1688 */ 1689 1690 server_lookup: 1691 ret = _kdc_db_fetch(context, config, sp, HDB_F_GET_SERVER | flags, 1692 NULL, NULL, &server); 1693 1694 if (ret == HDB_ERR_NOT_FOUND_HERE) { 1695 kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy", sp); 1696 goto out; 1697 } else if (ret == HDB_ERR_WRONG_REALM) { 1698 free(ref_realm); 1699 ref_realm = strdup(server->entry.principal->realm); 1700 if (ref_realm == NULL) { 1701 ret = krb5_enomem(context); 1702 goto out; 1703 } 1704 1705 kdc_log(context, config, 5, 1706 "Returning a referral to realm %s for " 1707 "server %s.", 1708 ref_realm, spn); 1709 krb5_free_principal(context, sp); 1710 sp = NULL; 1711 ret = krb5_make_principal(context, &sp, r, KRB5_TGS_NAME, 1712 ref_realm, NULL); 1713 if (ret) 1714 goto out; 1715 free(spn); 1716 spn = NULL; 1717 ret = krb5_unparse_name(context, sp, &spn); 1718 if (ret) 1719 goto out; 1720 1721 goto server_lookup; 1722 } else if (ret) { 1723 const char *new_rlm, *msg; 1724 Realm req_rlm; 1725 krb5_realm *realms; 1726 1727 if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) { 1728 if (capath == NULL) { 1729 /* With referalls, hierarchical capaths are always enabled */ 1730 ret2 = _krb5_find_capath(context, tgt->crealm, our_realm, 1731 req_rlm, TRUE, &capath, &num_capath); 1732 if (ret2) { 1733 ret = ret2; 1734 goto out; 1735 } 1736 } 1737 new_rlm = num_capath > 0 ? capath[--num_capath] : NULL; 1738 if (new_rlm) { 1739 kdc_log(context, config, 5, "krbtgt from %s via %s for " 1740 "realm %s not found, trying %s", tgt->crealm, 1741 our_realm, req_rlm, new_rlm); 1742 1743 free(ref_realm); 1744 ref_realm = strdup(new_rlm); 1745 if (ref_realm == NULL) { 1746 ret = krb5_enomem(context); 1747 goto out; 1748 } 1749 1750 krb5_free_principal(context, sp); 1751 sp = NULL; 1752 krb5_make_principal(context, &sp, r, 1753 KRB5_TGS_NAME, ref_realm, NULL); 1754 free(spn); 1755 spn = NULL; 1756 ret = krb5_unparse_name(context, sp, &spn); 1757 if (ret) 1758 goto out; 1759 goto server_lookup; 1760 } 1761 } else if (need_referral(context, config, &b->kdc_options, sp, &realms)) { 1762 if (strcmp(realms[0], sp->realm) != 0) { 1763 kdc_log(context, config, 5, 1764 "Returning a referral to realm %s for " 1765 "server %s that was not found", 1766 realms[0], spn); 1767 krb5_free_principal(context, sp); 1768 sp = NULL; 1769 krb5_make_principal(context, &sp, r, KRB5_TGS_NAME, 1770 realms[0], NULL); 1771 free(spn); 1772 spn = NULL; 1773 ret = krb5_unparse_name(context, sp, &spn); 1774 if (ret) { 1775 krb5_free_host_realm(context, realms); 1776 goto out; 1777 } 1778 1779 free(ref_realm); 1780 ref_realm = strdup(realms[0]); 1781 1782 krb5_free_host_realm(context, realms); 1783 goto server_lookup; 1784 } 1785 krb5_free_host_realm(context, realms); 1786 } 1787 msg = krb5_get_error_message(context, ret); 1788 kdc_log(context, config, 0, 1789 "Server not found in database: %s: %s", spn, msg); 1790 krb5_free_error_message(context, msg); 1791 if (ret == HDB_ERR_NOENTRY) 1792 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; 1793 goto out; 1794 } 1795 1796 /* the name returned to the client depend on what was asked for, 1797 * return canonical name if kdc_options.canonicalize was set, the 1798 * client wants the true name of the principal, if not it just 1799 * wants the name its asked for. 1800 */ 1801 1802 if (b->kdc_options.canonicalize) 1803 rsp = server->entry.principal; 1804 else 1805 rsp = sp; 1806 1807 1808 /* 1809 * Select enctype, return key and kvno. 1810 */ 1811 1812 { 1813 krb5_enctype etype; 1814 1815 if(b->kdc_options.enc_tkt_in_skey) { 1816 size_t i; 1817 ekey = &adtkt.key; 1818 for(i = 0; i < b->etype.len; i++) 1819 if (b->etype.val[i] == adtkt.key.keytype) 1820 break; 1821 if(i == b->etype.len) { 1822 kdc_log(context, config, 0, 1823 "Addition ticket have not matching etypes"); 1824 krb5_clear_error_message(context); 1825 ret = KRB5KDC_ERR_ETYPE_NOSUPP; 1826 goto out; 1827 } 1828 etype = b->etype.val[i]; 1829 kvno = 0; 1830 } else { 1831 Key *skey; 1832 1833 ret = _kdc_find_etype(context, 1834 krb5_principal_is_krbtgt(context, sp) ? 1835 config->tgt_use_strongest_session_key : 1836 config->svc_use_strongest_session_key, FALSE, 1837 server, b->etype.val, b->etype.len, &etype, 1838 NULL); 1839 if(ret) { 1840 kdc_log(context, config, 0, 1841 "Server (%s) has no support for etypes", spn); 1842 goto out; 1843 } 1844 ret = _kdc_get_preferred_key(context, config, server, spn, 1845 NULL, &skey); 1846 if(ret) { 1847 kdc_log(context, config, 0, 1848 "Server (%s) has no supported etypes", spn); 1849 goto out; 1850 } 1851 ekey = &skey->key; 1852 kvno = server->entry.kvno; 1853 } 1854 1855 ret = krb5_generate_random_keyblock(context, etype, &sessionkey); 1856 if (ret) 1857 goto out; 1858 } 1859 1860 /* 1861 * Check that service is in the same realm as the krbtgt. If it's 1862 * not the same, it's someone that is using a uni-directional trust 1863 * backward. 1864 */ 1865 1866 /* 1867 * Validate authoriation data 1868 */ 1869 1870 ret = hdb_enctype2key(context, &krbtgt->entry, NULL, /* XXX use the right kvno! */ 1871 krbtgt_etype, &tkey_check); 1872 if(ret) { 1873 kdc_log(context, config, 0, 1874 "Failed to find key for krbtgt PAC check"); 1875 goto out; 1876 } 1877 1878 /* 1879 * Now refetch the primary krbtgt, and get the current kvno (the 1880 * sign check may have been on an old kvno, and the server may 1881 * have been an incoming trust) 1882 */ 1883 1884 ret = krb5_make_principal(context, 1885 &krbtgt_out_principal, 1886 our_realm, 1887 KRB5_TGS_NAME, 1888 our_realm, 1889 NULL); 1890 if (ret) { 1891 kdc_log(context, config, 0, 1892 "Failed to make krbtgt principal name object for " 1893 "authz-data signatures"); 1894 goto out; 1895 } 1896 ret = krb5_unparse_name(context, krbtgt_out_principal, &krbtgt_out_n); 1897 if (ret) { 1898 kdc_log(context, config, 0, 1899 "Failed to make krbtgt principal name object for " 1900 "authz-data signatures"); 1901 goto out; 1902 } 1903 1904 ret = _kdc_db_fetch(context, config, krbtgt_out_principal, 1905 HDB_F_GET_KRBTGT, NULL, NULL, &krbtgt_out); 1906 if (ret) { 1907 char *ktpn = NULL; 1908 ret = krb5_unparse_name(context, krbtgt->entry.principal, &ktpn); 1909 kdc_log(context, config, 0, 1910 "No such principal %s (needed for authz-data signature keys) " 1911 "while processing TGS-REQ for service %s with krbtg %s", 1912 krbtgt_out_n, spn, (ret == 0) ? ktpn : "<unknown>"); 1913 free(ktpn); 1914 ret = KRB5KRB_AP_ERR_NOT_US; 1915 goto out; 1916 } 1917 1918 /* 1919 * The first realm is the realm of the service, the second is 1920 * krbtgt/<this>/@REALM component of the krbtgt DN the request was 1921 * encrypted to. The redirection via the krbtgt_out entry allows 1922 * the DB to possibly correct the case of the realm (Samba4 does 1923 * this) before the strcmp() 1924 */ 1925 if (strcmp(krb5_principal_get_realm(context, server->entry.principal), 1926 krb5_principal_get_realm(context, krbtgt_out->entry.principal)) != 0) { 1927 char *ktpn; 1928 ret = krb5_unparse_name(context, krbtgt_out->entry.principal, &ktpn); 1929 kdc_log(context, config, 0, 1930 "Request with wrong krbtgt: %s", 1931 (ret == 0) ? ktpn : "<unknown>"); 1932 if(ret == 0) 1933 free(ktpn); 1934 ret = KRB5KRB_AP_ERR_NOT_US; 1935 goto out; 1936 } 1937 1938 ret = _kdc_get_preferred_key(context, config, krbtgt_out, krbtgt_out_n, 1939 NULL, &tkey_sign); 1940 if (ret) { 1941 kdc_log(context, config, 0, 1942 "Failed to find key for krbtgt PAC signature"); 1943 goto out; 1944 } 1945 ret = hdb_enctype2key(context, &krbtgt_out->entry, NULL, 1946 tkey_sign->key.keytype, &tkey_sign); 1947 if(ret) { 1948 kdc_log(context, config, 0, 1949 "Failed to find key for krbtgt PAC signature"); 1950 goto out; 1951 } 1952 1953 ret = _kdc_db_fetch(context, config, cp, HDB_F_GET_CLIENT | flags, 1954 NULL, &clientdb, &client); 1955 if(ret == HDB_ERR_NOT_FOUND_HERE) { 1956 /* This is OK, we are just trying to find out if they have 1957 * been disabled or deleted in the meantime, missing secrets 1958 * is OK */ 1959 } else if(ret){ 1960 const char *krbtgt_realm, *msg; 1961 1962 /* 1963 * If the client belongs to the same realm as our krbtgt, it 1964 * should exist in the local database. 1965 * 1966 */ 1967 1968 krbtgt_realm = krb5_principal_get_realm(context, krbtgt_out->entry.principal); 1969 1970 if(strcmp(krb5_principal_get_realm(context, cp), krbtgt_realm) == 0) { 1971 if (ret == HDB_ERR_NOENTRY) 1972 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; 1973 kdc_log(context, config, 1, "Client no longer in database: %s", 1974 cpn); 1975 goto out; 1976 } 1977 1978 msg = krb5_get_error_message(context, ret); 1979 kdc_log(context, config, 1, "Client not found in database: %s", msg); 1980 krb5_free_error_message(context, msg); 1981 } 1982 1983 ret = check_PAC(context, config, cp, NULL, 1984 client, server, krbtgt, 1985 &tkey_check->key, 1986 ekey, &tkey_sign->key, 1987 tgt, &rspac, &signedpath); 1988 if (ret) { 1989 const char *msg = krb5_get_error_message(context, ret); 1990 kdc_log(context, config, 0, 1991 "Verify PAC failed for %s (%s) from %s with %s", 1992 spn, cpn, from, msg); 1993 krb5_free_error_message(context, msg); 1994 goto out; 1995 } 1996 1997 /* also check the krbtgt for signature */ 1998 ret = check_KRB5SignedPath(context, 1999 config, 2000 krbtgt, 2001 cp, 2002 tgt, 2003 &spp, 2004 &signedpath); 2005 if (ret) { 2006 const char *msg = krb5_get_error_message(context, ret); 2007 kdc_log(context, config, 0, 2008 "KRB5SignedPath check failed for %s (%s) from %s with %s", 2009 spn, cpn, from, msg); 2010 krb5_free_error_message(context, msg); 2011 goto out; 2012 } 2013 2014 /* 2015 * Process request 2016 */ 2017 2018 /* by default the tgt principal matches the client principal */ 2019 tp = cp; 2020 tpn = cpn; 2021 2022 if (client) { 2023 const PA_DATA *sdata; 2024 int i = 0; 2025 2026 sdata = _kdc_find_padata(req, &i, KRB5_PADATA_FOR_USER); 2027 if (sdata) { 2028 krb5_crypto crypto; 2029 krb5_data datack; 2030 PA_S4U2Self self; 2031 const char *str; 2032 2033 ret = decode_PA_S4U2Self(sdata->padata_value.data, 2034 sdata->padata_value.length, 2035 &self, NULL); 2036 if (ret) { 2037 kdc_log(context, config, 0, "Failed to decode PA-S4U2Self"); 2038 goto out; 2039 } 2040 2041 if (!krb5_checksum_is_keyed(context, self.cksum.cksumtype)) { 2042 free_PA_S4U2Self(&self); 2043 kdc_log(context, config, 0, "Reject PA-S4U2Self with unkeyed checksum"); 2044 ret = KRB5KRB_AP_ERR_INAPP_CKSUM; 2045 goto out; 2046 } 2047 2048 ret = _krb5_s4u2self_to_checksumdata(context, &self, &datack); 2049 if (ret) 2050 goto out; 2051 2052 ret = krb5_crypto_init(context, &tgt->key, 0, &crypto); 2053 if (ret) { 2054 const char *msg = krb5_get_error_message(context, ret); 2055 free_PA_S4U2Self(&self); 2056 krb5_data_free(&datack); 2057 kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg); 2058 krb5_free_error_message(context, msg); 2059 goto out; 2060 } 2061 2062 /* Allow HMAC_MD5 checksum with any key type */ 2063 if (self.cksum.cksumtype == CKSUMTYPE_HMAC_MD5) { 2064 unsigned char csdata[16]; 2065 Checksum cs; 2066 2067 cs.checksum.length = sizeof(csdata); 2068 cs.checksum.data = &csdata; 2069 2070 ret = _krb5_HMAC_MD5_checksum(context, &crypto->key, 2071 datack.data, datack.length, 2072 KRB5_KU_OTHER_CKSUM, &cs); 2073 if (ret == 0 && 2074 krb5_data_ct_cmp(&cs.checksum, &self.cksum.checksum) != 0) 2075 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; 2076 } 2077 else { 2078 ret = krb5_verify_checksum(context, 2079 crypto, 2080 KRB5_KU_OTHER_CKSUM, 2081 datack.data, 2082 datack.length, 2083 &self.cksum); 2084 } 2085 krb5_data_free(&datack); 2086 krb5_crypto_destroy(context, crypto); 2087 if (ret) { 2088 const char *msg = krb5_get_error_message(context, ret); 2089 free_PA_S4U2Self(&self); 2090 kdc_log(context, config, 0, 2091 "krb5_verify_checksum failed for S4U2Self: %s", msg); 2092 krb5_free_error_message(context, msg); 2093 goto out; 2094 } 2095 2096 ret = _krb5_principalname2krb5_principal(context, 2097 &tp, 2098 self.name, 2099 self.realm); 2100 free_PA_S4U2Self(&self); 2101 if (ret) 2102 goto out; 2103 2104 ret = krb5_unparse_name(context, tp, &tpn); 2105 if (ret) 2106 goto out; 2107 2108 /* If we were about to put a PAC into the ticket, we better fix it to be the right PAC */ 2109 if(rspac.data) { 2110 krb5_pac p = NULL; 2111 krb5_data_free(&rspac); 2112 ret = _kdc_db_fetch(context, config, tp, HDB_F_GET_CLIENT | flags, 2113 NULL, &s4u2self_impersonated_clientdb, &s4u2self_impersonated_client); 2114 if (ret) { 2115 const char *msg; 2116 2117 /* 2118 * If the client belongs to the same realm as our krbtgt, it 2119 * should exist in the local database. 2120 * 2121 */ 2122 2123 if (ret == HDB_ERR_NOENTRY) 2124 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; 2125 msg = krb5_get_error_message(context, ret); 2126 kdc_log(context, config, 1, 2127 "S2U4Self principal to impersonate %s not found in database: %s", 2128 tpn, msg); 2129 krb5_free_error_message(context, msg); 2130 goto out; 2131 } 2132 ret = _kdc_pac_generate(context, s4u2self_impersonated_client, &p); 2133 if (ret) { 2134 kdc_log(context, config, 0, "PAC generation failed for -- %s", 2135 tpn); 2136 goto out; 2137 } 2138 if (p != NULL) { 2139 ret = _krb5_pac_sign(context, p, ticket->ticket.authtime, 2140 s4u2self_impersonated_client->entry.principal, 2141 ekey, &tkey_sign->key, 2142 &rspac); 2143 krb5_pac_free(context, p); 2144 if (ret) { 2145 kdc_log(context, config, 0, "PAC signing failed for -- %s", 2146 tpn); 2147 goto out; 2148 } 2149 } 2150 } 2151 2152 /* 2153 * Check that service doing the impersonating is 2154 * requesting a ticket to it-self. 2155 */ 2156 ret = check_s4u2self(context, config, clientdb, client, sp); 2157 if (ret) { 2158 kdc_log(context, config, 0, "S4U2Self: %s is not allowed " 2159 "to impersonate to service " 2160 "(tried for user %s to service %s)", 2161 cpn, tpn, spn); 2162 goto out; 2163 } 2164 2165 /* 2166 * If the service isn't trusted for authentication to 2167 * delegation, remove the forward flag. 2168 */ 2169 2170 if (client->entry.flags.trusted_for_delegation) { 2171 str = "[forwardable]"; 2172 } else { 2173 b->kdc_options.forwardable = 0; 2174 str = ""; 2175 } 2176 kdc_log(context, config, 0, "s4u2self %s impersonating %s to " 2177 "service %s %s", cpn, tpn, spn, str); 2178 } 2179 } 2180 2181 /* 2182 * Constrained delegation 2183 */ 2184 2185 if (client != NULL 2186 && b->additional_tickets != NULL 2187 && b->additional_tickets->len != 0 2188 && b->kdc_options.cname_in_addl_tkt 2189 && b->kdc_options.enc_tkt_in_skey == 0) 2190 { 2191 int ad_signedpath = 0; 2192 Key *clientkey; 2193 Ticket *t; 2194 2195 /* 2196 * Require that the KDC have issued the service's krbtgt (not 2197 * self-issued ticket with kimpersonate(1). 2198 */ 2199 if (!signedpath) { 2200 ret = KRB5KDC_ERR_BADOPTION; 2201 kdc_log(context, config, 0, 2202 "Constrained delegation done on service ticket %s/%s", 2203 cpn, spn); 2204 goto out; 2205 } 2206 2207 t = &b->additional_tickets->val[0]; 2208 2209 ret = hdb_enctype2key(context, &client->entry, 2210 hdb_kvno2keys(context, &client->entry, 2211 t->enc_part.kvno ? * t->enc_part.kvno : 0), 2212 t->enc_part.etype, &clientkey); 2213 if(ret){ 2214 ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */ 2215 goto out; 2216 } 2217 2218 ret = krb5_decrypt_ticket(context, t, &clientkey->key, &adtkt, 0); 2219 if (ret) { 2220 kdc_log(context, config, 0, 2221 "failed to decrypt ticket for " 2222 "constrained delegation from %s to %s ", cpn, spn); 2223 goto out; 2224 } 2225 2226 ret = _krb5_principalname2krb5_principal(context, 2227 &tp, 2228 adtkt.cname, 2229 adtkt.crealm); 2230 if (ret) 2231 goto out; 2232 2233 ret = krb5_unparse_name(context, tp, &tpn); 2234 if (ret) 2235 goto out; 2236 2237 ret = _krb5_principalname2krb5_principal(context, 2238 &dp, 2239 t->sname, 2240 t->realm); 2241 if (ret) 2242 goto out; 2243 2244 ret = krb5_unparse_name(context, dp, &dpn); 2245 if (ret) 2246 goto out; 2247 2248 /* check that ticket is valid */ 2249 if (adtkt.flags.forwardable == 0) { 2250 kdc_log(context, config, 0, 2251 "Missing forwardable flag on ticket for " 2252 "constrained delegation from %s (%s) as %s to %s ", 2253 cpn, dpn, tpn, spn); 2254 ret = KRB5KDC_ERR_BADOPTION; 2255 goto out; 2256 } 2257 2258 ret = check_constrained_delegation(context, config, clientdb, 2259 client, server, sp); 2260 if (ret) { 2261 kdc_log(context, config, 0, 2262 "constrained delegation from %s (%s) as %s to %s not allowed", 2263 cpn, dpn, tpn, spn); 2264 goto out; 2265 } 2266 2267 ret = verify_flags(context, config, &adtkt, tpn); 2268 if (ret) { 2269 goto out; 2270 } 2271 2272 krb5_data_free(&rspac); 2273 2274 /* 2275 * generate the PAC for the user. 2276 * 2277 * TODO: pass in t->sname and t->realm and build 2278 * a S4U_DELEGATION_INFO blob to the PAC. 2279 */ 2280 ret = check_PAC(context, config, tp, dp, 2281 client, server, krbtgt, 2282 &clientkey->key, 2283 ekey, &tkey_sign->key, 2284 &adtkt, &rspac, &ad_signedpath); 2285 if (ret) { 2286 const char *msg = krb5_get_error_message(context, ret); 2287 kdc_log(context, config, 0, 2288 "Verify delegated PAC failed to %s for client" 2289 "%s (%s) as %s from %s with %s", 2290 spn, cpn, dpn, tpn, from, msg); 2291 krb5_free_error_message(context, msg); 2292 goto out; 2293 } 2294 2295 /* 2296 * Check that the KDC issued the user's ticket. 2297 */ 2298 ret = check_KRB5SignedPath(context, 2299 config, 2300 krbtgt, 2301 cp, 2302 &adtkt, 2303 NULL, 2304 &ad_signedpath); 2305 if (ret) { 2306 const char *msg = krb5_get_error_message(context, ret); 2307 kdc_log(context, config, 0, 2308 "KRB5SignedPath check from service %s failed " 2309 "for delegation to %s for client %s (%s)" 2310 "from %s failed with %s", 2311 spn, tpn, dpn, cpn, from, msg); 2312 krb5_free_error_message(context, msg); 2313 goto out; 2314 } 2315 2316 if (!ad_signedpath) { 2317 ret = KRB5KDC_ERR_BADOPTION; 2318 kdc_log(context, config, 0, 2319 "Ticket not signed with PAC nor SignedPath service %s failed " 2320 "for delegation to %s for client %s (%s)" 2321 "from %s", 2322 spn, tpn, dpn, cpn, from); 2323 goto out; 2324 } 2325 2326 kdc_log(context, config, 0, "constrained delegation for %s " 2327 "from %s (%s) to %s", tpn, cpn, dpn, spn); 2328 } 2329 2330 /* 2331 * Check flags 2332 */ 2333 2334 ret = kdc_check_flags(context, config, 2335 client, cpn, 2336 server, spn, 2337 FALSE); 2338 if(ret) 2339 goto out; 2340 2341 if((b->kdc_options.validate || b->kdc_options.renew) && 2342 !krb5_principal_compare(context, 2343 krbtgt->entry.principal, 2344 server->entry.principal)){ 2345 kdc_log(context, config, 0, "Inconsistent request."); 2346 ret = KRB5KDC_ERR_SERVER_NOMATCH; 2347 goto out; 2348 } 2349 2350 /* check for valid set of addresses */ 2351 if(!_kdc_check_addresses(context, config, tgt->caddr, from_addr)) { 2352 ret = KRB5KRB_AP_ERR_BADADDR; 2353 kdc_log(context, config, 0, "Request from wrong address"); 2354 goto out; 2355 } 2356 2357 /* check local and per-principal anonymous ticket issuance policy */ 2358 if (is_anon_tgs_request_p(b, tgt)) { 2359 ret = _kdc_check_anon_policy(context, config, client, server); 2360 if (ret) 2361 goto out; 2362 } 2363 2364 /* 2365 * If this is an referral, add server referral data to the 2366 * auth_data reply . 2367 */ 2368 if (ref_realm) { 2369 PA_DATA pa; 2370 krb5_crypto crypto; 2371 2372 kdc_log(context, config, 0, 2373 "Adding server referral to %s", ref_realm); 2374 2375 ret = krb5_crypto_init(context, &sessionkey, 0, &crypto); 2376 if (ret) 2377 goto out; 2378 2379 ret = build_server_referral(context, config, crypto, ref_realm, 2380 NULL, s, &pa.padata_value); 2381 krb5_crypto_destroy(context, crypto); 2382 if (ret) { 2383 kdc_log(context, config, 0, 2384 "Failed building server referral"); 2385 goto out; 2386 } 2387 pa.padata_type = KRB5_PADATA_SERVER_REFERRAL; 2388 2389 ret = add_METHOD_DATA(&enc_pa_data, &pa); 2390 krb5_data_free(&pa.padata_value); 2391 if (ret) { 2392 kdc_log(context, config, 0, 2393 "Add server referral METHOD-DATA failed"); 2394 goto out; 2395 } 2396 } 2397 2398 /* 2399 * 2400 */ 2401 2402 ret = tgs_make_reply(context, 2403 config, 2404 b, 2405 tp, 2406 tgt, 2407 replykey, 2408 rk_is_subkey, 2409 ekey, 2410 &sessionkey, 2411 kvno, 2412 *auth_data, 2413 server, 2414 rsp, 2415 spn, 2416 client, 2417 cp, 2418 tgt_realm, 2419 krbtgt_out, 2420 tkey_sign->key.keytype, 2421 spp, 2422 &rspac, 2423 &enc_pa_data, 2424 e_text, 2425 reply); 2426 2427 out: 2428 if (tpn != cpn) 2429 free(tpn); 2430 free(spn); 2431 free(cpn); 2432 free(dpn); 2433 free(krbtgt_out_n); 2434 _krb5_free_capath(context, capath); 2435 2436 krb5_data_free(&rspac); 2437 krb5_free_keyblock_contents(context, &sessionkey); 2438 if(krbtgt_out) 2439 _kdc_free_ent(context, krbtgt_out); 2440 if(server) 2441 _kdc_free_ent(context, server); 2442 if(client) 2443 _kdc_free_ent(context, client); 2444 if(s4u2self_impersonated_client) 2445 _kdc_free_ent(context, s4u2self_impersonated_client); 2446 2447 if (tp && tp != cp) 2448 krb5_free_principal(context, tp); 2449 krb5_free_principal(context, cp); 2450 krb5_free_principal(context, dp); 2451 krb5_free_principal(context, sp); 2452 krb5_free_principal(context, krbtgt_out_principal); 2453 free(ref_realm); 2454 free_METHOD_DATA(&enc_pa_data); 2455 2456 free_EncTicketPart(&adtkt); 2457 2458 return ret; 2459 } 2460 2461 /* 2462 * 2463 */ 2464 2465 krb5_error_code 2466 _kdc_tgs_rep(krb5_context context, 2467 krb5_kdc_configuration *config, 2468 KDC_REQ *req, 2469 krb5_data *data, 2470 const char *from, 2471 struct sockaddr *from_addr, 2472 int datagram_reply) 2473 { 2474 AuthorizationData *auth_data = NULL; 2475 krb5_error_code ret; 2476 int i = 0; 2477 const PA_DATA *tgs_req; 2478 2479 hdb_entry_ex *krbtgt = NULL; 2480 krb5_ticket *ticket = NULL; 2481 const char *e_text = NULL; 2482 krb5_enctype krbtgt_etype = ETYPE_NULL; 2483 2484 krb5_keyblock *replykey = NULL; 2485 int rk_is_subkey = 0; 2486 time_t *csec = NULL; 2487 int *cusec = NULL; 2488 2489 if(req->padata == NULL){ 2490 ret = KRB5KDC_ERR_PREAUTH_REQUIRED; /* XXX ??? */ 2491 kdc_log(context, config, 0, 2492 "TGS-REQ from %s without PA-DATA", from); 2493 goto out; 2494 } 2495 2496 tgs_req = _kdc_find_padata(req, &i, KRB5_PADATA_TGS_REQ); 2497 2498 if(tgs_req == NULL){ 2499 ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP; 2500 2501 kdc_log(context, config, 0, 2502 "TGS-REQ from %s without PA-TGS-REQ", from); 2503 goto out; 2504 } 2505 ret = tgs_parse_request(context, config, 2506 &req->req_body, tgs_req, 2507 &krbtgt, 2508 &krbtgt_etype, 2509 &ticket, 2510 &e_text, 2511 from, from_addr, 2512 &csec, &cusec, 2513 &auth_data, 2514 &replykey, 2515 &rk_is_subkey); 2516 if (ret == HDB_ERR_NOT_FOUND_HERE) { 2517 /* kdc_log() is called in tgs_parse_request() */ 2518 goto out; 2519 } 2520 if (ret) { 2521 kdc_log(context, config, 0, 2522 "Failed parsing TGS-REQ from %s", from); 2523 goto out; 2524 } 2525 2526 { 2527 const PA_DATA *pa = _kdc_find_padata(req, &i, KRB5_PADATA_FX_FAST); 2528 if (pa) 2529 kdc_log(context, config, 10, "Got TGS FAST request"); 2530 } 2531 2532 2533 ret = tgs_build_reply(context, 2534 config, 2535 req, 2536 &req->req_body, 2537 krbtgt, 2538 krbtgt_etype, 2539 replykey, 2540 rk_is_subkey, 2541 ticket, 2542 data, 2543 from, 2544 &e_text, 2545 &auth_data, 2546 from_addr); 2547 if (ret) { 2548 kdc_log(context, config, 0, 2549 "Failed building TGS-REP to %s", from); 2550 goto out; 2551 } 2552 2553 /* */ 2554 if (datagram_reply && data->length > config->max_datagram_reply_length) { 2555 krb5_data_free(data); 2556 ret = KRB5KRB_ERR_RESPONSE_TOO_BIG; 2557 e_text = "Reply packet too large"; 2558 } 2559 2560 out: 2561 if (replykey) 2562 krb5_free_keyblock(context, replykey); 2563 2564 if(ret && ret != HDB_ERR_NOT_FOUND_HERE && data->data == NULL){ 2565 /* XXX add fast wrapping on the error */ 2566 METHOD_DATA error_method = { 0, NULL }; 2567 2568 2569 kdc_log(context, config, 10, "tgs-req: sending error: %d to client", ret); 2570 ret = _kdc_fast_mk_error(context, NULL, 2571 &error_method, 2572 NULL, 2573 NULL, 2574 ret, NULL, 2575 NULL, 2576 NULL, NULL, 2577 csec, cusec, 2578 data); 2579 free_METHOD_DATA(&error_method); 2580 } 2581 free(csec); 2582 free(cusec); 2583 if (ticket) 2584 krb5_free_ticket(context, ticket); 2585 if(krbtgt) 2586 _kdc_free_ent(context, krbtgt); 2587 2588 if (auth_data) { 2589 free_AuthorizationData(auth_data); 2590 free(auth_data); 2591 } 2592 2593 return ret; 2594 } 2595