1 /* 2 * Copyright (c) 1997-2002 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: kerberos5.c,v 1.145 2003/04/15 11:07:39 lha Exp $"); 37 38 #define MAX_TIME ((time_t)((1U << 31) - 1)) 39 40 static void 41 fix_time(time_t **t) 42 { 43 if(*t == NULL){ 44 ALLOC(*t); 45 **t = MAX_TIME; 46 } 47 if(**t == 0) **t = MAX_TIME; /* fix for old clients */ 48 } 49 50 static void 51 set_salt_padata (METHOD_DATA **m, Salt *salt) 52 { 53 if (salt) { 54 ALLOC(*m); 55 (*m)->len = 1; 56 ALLOC((*m)->val); 57 (*m)->val->padata_type = salt->type; 58 copy_octet_string(&salt->salt, 59 &(*m)->val->padata_value); 60 } 61 } 62 63 static PA_DATA* 64 find_padata(KDC_REQ *req, int *start, int type) 65 { 66 while(*start < req->padata->len){ 67 (*start)++; 68 if(req->padata->val[*start - 1].padata_type == type) 69 return &req->padata->val[*start - 1]; 70 } 71 return NULL; 72 } 73 74 /* 75 * return the first appropriate key of `princ' in `ret_key'. Look for 76 * all the etypes in (`etypes', `len'), stopping as soon as we find 77 * one, but preferring one that has default salt 78 */ 79 80 static krb5_error_code 81 find_etype(hdb_entry *princ, krb5_enctype *etypes, unsigned len, 82 Key **ret_key, krb5_enctype *ret_etype) 83 { 84 int i; 85 krb5_error_code ret = KRB5KDC_ERR_ETYPE_NOSUPP; 86 87 for(i = 0; ret != 0 && i < len ; i++) { 88 Key *key = NULL; 89 90 while (hdb_next_enctype2key(context, princ, etypes[i], &key) == 0) { 91 if (key->key.keyvalue.length == 0) { 92 ret = KRB5KDC_ERR_NULL_KEY; 93 continue; 94 } 95 *ret_key = key; 96 *ret_etype = etypes[i]; 97 ret = 0; 98 if (key->salt == NULL) 99 return ret; 100 } 101 } 102 return ret; 103 } 104 105 static krb5_error_code 106 find_keys(hdb_entry *client, 107 hdb_entry *server, 108 Key **ckey, 109 krb5_enctype *cetype, 110 Key **skey, 111 krb5_enctype *setype, 112 krb5_enctype *etypes, 113 unsigned num_etypes) 114 { 115 krb5_error_code ret; 116 117 if(client){ 118 /* find client key */ 119 ret = find_etype(client, etypes, num_etypes, ckey, cetype); 120 if (ret) { 121 kdc_log(0, "Client has no support for etypes"); 122 return ret; 123 } 124 } 125 126 if(server){ 127 /* find server key */ 128 ret = find_etype(server, etypes, num_etypes, skey, setype); 129 if (ret) { 130 kdc_log(0, "Server has no support for etypes"); 131 return ret; 132 } 133 } 134 return 0; 135 } 136 137 static krb5_error_code 138 make_anonymous_principalname (PrincipalName *pn) 139 { 140 pn->name_type = KRB5_NT_PRINCIPAL; 141 pn->name_string.len = 1; 142 pn->name_string.val = malloc(sizeof(*pn->name_string.val)); 143 if (pn->name_string.val == NULL) 144 return ENOMEM; 145 pn->name_string.val[0] = strdup("anonymous"); 146 if (pn->name_string.val[0] == NULL) { 147 free(pn->name_string.val); 148 pn->name_string.val = NULL; 149 return ENOMEM; 150 } 151 return 0; 152 } 153 154 static krb5_error_code 155 encode_reply(KDC_REP *rep, EncTicketPart *et, EncKDCRepPart *ek, 156 krb5_enctype etype, 157 int skvno, EncryptionKey *skey, 158 int ckvno, EncryptionKey *ckey, 159 const char **e_text, 160 krb5_data *reply) 161 { 162 unsigned char *buf; 163 size_t buf_size; 164 size_t len; 165 krb5_error_code ret; 166 krb5_crypto crypto; 167 168 ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret); 169 if(ret) { 170 kdc_log(0, "Failed to encode ticket: %s", 171 krb5_get_err_text(context, ret)); 172 return ret; 173 } 174 if(buf_size != len) { 175 free(buf); 176 kdc_log(0, "Internal error in ASN.1 encoder"); 177 *e_text = "KDC internal error"; 178 return KRB5KRB_ERR_GENERIC; 179 } 180 181 ret = krb5_crypto_init(context, skey, etype, &crypto); 182 if (ret) { 183 free(buf); 184 kdc_log(0, "krb5_crypto_init failed: %s", 185 krb5_get_err_text(context, ret)); 186 return ret; 187 } 188 189 ret = krb5_encrypt_EncryptedData(context, 190 crypto, 191 KRB5_KU_TICKET, 192 buf, 193 len, 194 skvno, 195 &rep->ticket.enc_part); 196 free(buf); 197 krb5_crypto_destroy(context, crypto); 198 if(ret) { 199 kdc_log(0, "Failed to encrypt data: %s", 200 krb5_get_err_text(context, ret)); 201 return ret; 202 } 203 204 if(rep->msg_type == krb_as_rep && !encode_as_rep_as_tgs_rep) 205 ASN1_MALLOC_ENCODE(EncASRepPart, buf, buf_size, ek, &len, ret); 206 else 207 ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret); 208 if(ret) { 209 kdc_log(0, "Failed to encode KDC-REP: %s", 210 krb5_get_err_text(context, ret)); 211 return ret; 212 } 213 if(buf_size != len) { 214 free(buf); 215 kdc_log(0, "Internal error in ASN.1 encoder"); 216 *e_text = "KDC internal error"; 217 return KRB5KRB_ERR_GENERIC; 218 } 219 ret = krb5_crypto_init(context, ckey, 0, &crypto); 220 if (ret) { 221 free(buf); 222 kdc_log(0, "krb5_crypto_init failed: %s", 223 krb5_get_err_text(context, ret)); 224 return ret; 225 } 226 if(rep->msg_type == krb_as_rep) { 227 krb5_encrypt_EncryptedData(context, 228 crypto, 229 KRB5_KU_AS_REP_ENC_PART, 230 buf, 231 len, 232 ckvno, 233 &rep->enc_part); 234 free(buf); 235 ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret); 236 } else { 237 krb5_encrypt_EncryptedData(context, 238 crypto, 239 KRB5_KU_TGS_REP_ENC_PART_SESSION, 240 buf, 241 len, 242 ckvno, 243 &rep->enc_part); 244 free(buf); 245 ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret); 246 } 247 krb5_crypto_destroy(context, crypto); 248 if(ret) { 249 kdc_log(0, "Failed to encode KDC-REP: %s", 250 krb5_get_err_text(context, ret)); 251 return ret; 252 } 253 if(buf_size != len) { 254 free(buf); 255 kdc_log(0, "Internal error in ASN.1 encoder"); 256 *e_text = "KDC internal error"; 257 return KRB5KRB_ERR_GENERIC; 258 } 259 reply->data = buf; 260 reply->length = buf_size; 261 return 0; 262 } 263 264 static int 265 realloc_method_data(METHOD_DATA *md) 266 { 267 PA_DATA *pa; 268 pa = realloc(md->val, (md->len + 1) * sizeof(*md->val)); 269 if(pa == NULL) 270 return ENOMEM; 271 md->val = pa; 272 md->len++; 273 return 0; 274 } 275 276 static krb5_error_code 277 make_etype_info_entry(ETYPE_INFO_ENTRY *ent, Key *key) 278 { 279 ent->etype = key->key.keytype; 280 if(key->salt){ 281 ALLOC(ent->salttype); 282 #if 0 283 if(key->salt->type == hdb_pw_salt) 284 *ent->salttype = 0; /* or 1? or NULL? */ 285 else if(key->salt->type == hdb_afs3_salt) 286 *ent->salttype = 2; 287 else { 288 kdc_log(0, "unknown salt-type: %d", 289 key->salt->type); 290 return KRB5KRB_ERR_GENERIC; 291 } 292 /* according to `the specs', we can't send a salt if 293 we have AFS3 salted key, but that requires that you 294 *know* what cell you are using (e.g by assuming 295 that the cell is the same as the realm in lower 296 case) */ 297 #else 298 *ent->salttype = key->salt->type; 299 #endif 300 krb5_copy_data(context, &key->salt->salt, 301 &ent->salt); 302 } else { 303 /* we return no salt type at all, as that should indicate 304 * the default salt type and make everybody happy. some 305 * systems (like w2k) dislike being told the salt type 306 * here. */ 307 308 ent->salttype = NULL; 309 ent->salt = NULL; 310 } 311 return 0; 312 } 313 314 static krb5_error_code 315 get_pa_etype_info(METHOD_DATA *md, hdb_entry *client, 316 ENCTYPE *etypes, unsigned int etypes_len) 317 { 318 krb5_error_code ret = 0; 319 int i, j; 320 unsigned int n = 0; 321 ETYPE_INFO pa; 322 unsigned char *buf; 323 size_t len; 324 325 326 pa.len = client->keys.len; 327 if(pa.len > UINT_MAX/sizeof(*pa.val)) 328 return ERANGE; 329 pa.val = malloc(pa.len * sizeof(*pa.val)); 330 if(pa.val == NULL) 331 return ENOMEM; 332 333 for(j = 0; j < etypes_len; j++) { 334 for(i = 0; i < client->keys.len; i++) { 335 if(client->keys.val[i].key.keytype == etypes[j]) 336 if((ret = make_etype_info_entry(&pa.val[n++], 337 &client->keys.val[i])) != 0) { 338 free_ETYPE_INFO(&pa); 339 return ret; 340 } 341 } 342 } 343 for(i = 0; i < client->keys.len; i++) { 344 for(j = 0; j < etypes_len; j++) { 345 if(client->keys.val[i].key.keytype == etypes[j]) 346 goto skip; 347 } 348 if((ret = make_etype_info_entry(&pa.val[n++], 349 &client->keys.val[i])) != 0) { 350 free_ETYPE_INFO(&pa); 351 return ret; 352 } 353 skip:; 354 } 355 356 if(n != pa.len) { 357 char *name; 358 krb5_unparse_name(context, client->principal, &name); 359 kdc_log(0, "internal error in get_pa_etype_info(%s): %d != %d", 360 name, n, pa.len); 361 free(name); 362 pa.len = n; 363 } 364 365 ASN1_MALLOC_ENCODE(ETYPE_INFO, buf, len, &pa, &len, ret); 366 free_ETYPE_INFO(&pa); 367 if(ret) 368 return ret; 369 ret = realloc_method_data(md); 370 if(ret) { 371 free(buf); 372 return ret; 373 } 374 md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO; 375 md->val[md->len - 1].padata_value.length = len; 376 md->val[md->len - 1].padata_value.data = buf; 377 return 0; 378 } 379 380 /* 381 * verify the flags on `client' and `server', returning 0 382 * if they are OK and generating an error messages and returning 383 * and error code otherwise. 384 */ 385 386 krb5_error_code 387 check_flags(hdb_entry *client, const char *client_name, 388 hdb_entry *server, const char *server_name, 389 krb5_boolean is_as_req) 390 { 391 if(client != NULL) { 392 /* check client */ 393 if (client->flags.invalid) { 394 kdc_log(0, "Client (%s) has invalid bit set", client_name); 395 return KRB5KDC_ERR_POLICY; 396 } 397 398 if(!client->flags.client){ 399 kdc_log(0, "Principal may not act as client -- %s", 400 client_name); 401 return KRB5KDC_ERR_POLICY; 402 } 403 404 if (client->valid_start && *client->valid_start > kdc_time) { 405 kdc_log(0, "Client not yet valid -- %s", client_name); 406 return KRB5KDC_ERR_CLIENT_NOTYET; 407 } 408 409 if (client->valid_end && *client->valid_end < kdc_time) { 410 kdc_log(0, "Client expired -- %s", client_name); 411 return KRB5KDC_ERR_NAME_EXP; 412 } 413 414 if (client->pw_end && *client->pw_end < kdc_time 415 && !server->flags.change_pw) { 416 kdc_log(0, "Client's key has expired -- %s", client_name); 417 return KRB5KDC_ERR_KEY_EXPIRED; 418 } 419 } 420 421 /* check server */ 422 423 if (server != NULL) { 424 if (server->flags.invalid) { 425 kdc_log(0, "Server has invalid flag set -- %s", server_name); 426 return KRB5KDC_ERR_POLICY; 427 } 428 429 if(!server->flags.server){ 430 kdc_log(0, "Principal may not act as server -- %s", 431 server_name); 432 return KRB5KDC_ERR_POLICY; 433 } 434 435 if(!is_as_req && server->flags.initial) { 436 kdc_log(0, "AS-REQ is required for server -- %s", server_name); 437 return KRB5KDC_ERR_POLICY; 438 } 439 440 if (server->valid_start && *server->valid_start > kdc_time) { 441 kdc_log(0, "Server not yet valid -- %s", server_name); 442 return KRB5KDC_ERR_SERVICE_NOTYET; 443 } 444 445 if (server->valid_end && *server->valid_end < kdc_time) { 446 kdc_log(0, "Server expired -- %s", server_name); 447 return KRB5KDC_ERR_SERVICE_EXP; 448 } 449 450 if (server->pw_end && *server->pw_end < kdc_time) { 451 kdc_log(0, "Server's key has expired -- %s", server_name); 452 return KRB5KDC_ERR_KEY_EXPIRED; 453 } 454 } 455 return 0; 456 } 457 458 /* 459 * Return TRUE if `from' is part of `addresses' taking into consideration 460 * the configuration variables that tells us how strict we should be about 461 * these checks 462 */ 463 464 static krb5_boolean 465 check_addresses(HostAddresses *addresses, const struct sockaddr *from) 466 { 467 krb5_error_code ret; 468 krb5_address addr; 469 krb5_boolean result; 470 471 if(check_ticket_addresses == 0) 472 return TRUE; 473 474 if(addresses == NULL) 475 return allow_null_ticket_addresses; 476 477 ret = krb5_sockaddr2address (context, from, &addr); 478 if(ret) 479 return FALSE; 480 481 result = krb5_address_search(context, &addr, addresses); 482 krb5_free_address (context, &addr); 483 return result; 484 } 485 486 krb5_error_code 487 as_rep(KDC_REQ *req, 488 krb5_data *reply, 489 const char *from, 490 struct sockaddr *from_addr) 491 { 492 KDC_REQ_BODY *b = &req->req_body; 493 AS_REP rep; 494 KDCOptions f = b->kdc_options; 495 hdb_entry *client = NULL, *server = NULL; 496 krb5_enctype cetype, setype; 497 EncTicketPart et; 498 EncKDCRepPart ek; 499 krb5_principal client_princ, server_princ; 500 char *client_name, *server_name; 501 krb5_error_code ret = 0; 502 const char *e_text = NULL; 503 krb5_crypto crypto; 504 Key *ckey, *skey; 505 506 memset(&rep, 0, sizeof(rep)); 507 508 if(b->sname == NULL){ 509 server_name = "<unknown server>"; 510 ret = KRB5KRB_ERR_GENERIC; 511 e_text = "No server in request"; 512 } else{ 513 principalname2krb5_principal (&server_princ, *(b->sname), b->realm); 514 krb5_unparse_name(context, server_princ, &server_name); 515 } 516 517 if(b->cname == NULL){ 518 client_name = "<unknown client>"; 519 ret = KRB5KRB_ERR_GENERIC; 520 e_text = "No client in request"; 521 } else { 522 principalname2krb5_principal (&client_princ, *(b->cname), b->realm); 523 krb5_unparse_name(context, client_princ, &client_name); 524 } 525 kdc_log(0, "AS-REQ %s from %s for %s", 526 client_name, from, server_name); 527 528 if(ret) 529 goto out; 530 531 ret = db_fetch(client_princ, &client); 532 if(ret){ 533 kdc_log(0, "UNKNOWN -- %s: %s", client_name, 534 krb5_get_err_text(context, ret)); 535 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; 536 goto out; 537 } 538 539 ret = db_fetch(server_princ, &server); 540 if(ret){ 541 kdc_log(0, "UNKNOWN -- %s: %s", server_name, 542 krb5_get_err_text(context, ret)); 543 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; 544 goto out; 545 } 546 547 ret = check_flags(client, client_name, server, server_name, TRUE); 548 if(ret) 549 goto out; 550 551 memset(&et, 0, sizeof(et)); 552 memset(&ek, 0, sizeof(ek)); 553 554 if(req->padata){ 555 int i = 0; 556 PA_DATA *pa; 557 int found_pa = 0; 558 kdc_log(5, "Looking for pa-data -- %s", client_name); 559 while((pa = find_padata(req, &i, KRB5_PADATA_ENC_TIMESTAMP))){ 560 krb5_data ts_data; 561 PA_ENC_TS_ENC p; 562 time_t patime; 563 size_t len; 564 EncryptedData enc_data; 565 Key *pa_key; 566 567 found_pa = 1; 568 569 ret = decode_EncryptedData(pa->padata_value.data, 570 pa->padata_value.length, 571 &enc_data, 572 &len); 573 if (ret) { 574 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; 575 kdc_log(5, "Failed to decode PA-DATA -- %s", 576 client_name); 577 goto out; 578 } 579 580 ret = hdb_enctype2key(context, client, enc_data.etype, &pa_key); 581 if(ret){ 582 char *estr; 583 e_text = "No key matches pa-data"; 584 ret = KRB5KDC_ERR_PREAUTH_FAILED; 585 if(krb5_enctype_to_string(context, enc_data.etype, &estr)) 586 estr = NULL; 587 if(estr == NULL) 588 kdc_log(5, "No client key matching pa-data (%d) -- %s", 589 enc_data.etype, client_name); 590 else 591 kdc_log(5, "No client key matching pa-data (%s) -- %s", 592 estr, client_name); 593 free(estr); 594 595 free_EncryptedData(&enc_data); 596 continue; 597 } 598 599 try_next_key: 600 ret = krb5_crypto_init(context, &pa_key->key, 0, &crypto); 601 if (ret) { 602 kdc_log(0, "krb5_crypto_init failed: %s", 603 krb5_get_err_text(context, ret)); 604 free_EncryptedData(&enc_data); 605 continue; 606 } 607 608 ret = krb5_decrypt_EncryptedData (context, 609 crypto, 610 KRB5_KU_PA_ENC_TIMESTAMP, 611 &enc_data, 612 &ts_data); 613 krb5_crypto_destroy(context, crypto); 614 if(ret){ 615 if(hdb_next_enctype2key(context, client, 616 enc_data.etype, &pa_key) == 0) 617 goto try_next_key; 618 free_EncryptedData(&enc_data); 619 e_text = "Failed to decrypt PA-DATA"; 620 kdc_log (5, "Failed to decrypt PA-DATA -- %s", 621 client_name); 622 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; 623 continue; 624 } 625 free_EncryptedData(&enc_data); 626 ret = decode_PA_ENC_TS_ENC(ts_data.data, 627 ts_data.length, 628 &p, 629 &len); 630 krb5_data_free(&ts_data); 631 if(ret){ 632 e_text = "Failed to decode PA-ENC-TS-ENC"; 633 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; 634 kdc_log (5, "Failed to decode PA-ENC-TS_ENC -- %s", 635 client_name); 636 continue; 637 } 638 patime = p.patimestamp; 639 free_PA_ENC_TS_ENC(&p); 640 if (abs(kdc_time - p.patimestamp) > context->max_skew) { 641 ret = KRB5KDC_ERR_PREAUTH_FAILED; 642 e_text = "Too large time skew"; 643 kdc_log(0, "Too large time skew -- %s", client_name); 644 goto out; 645 } 646 et.flags.pre_authent = 1; 647 kdc_log(2, "Pre-authentication succeded -- %s", client_name); 648 break; 649 } 650 if(found_pa == 0 && require_preauth) 651 goto use_pa; 652 /* We come here if we found a pa-enc-timestamp, but if there 653 was some problem with it, other than too large skew */ 654 if(found_pa && et.flags.pre_authent == 0){ 655 kdc_log(0, "%s -- %s", e_text, client_name); 656 e_text = NULL; 657 goto out; 658 } 659 }else if (require_preauth 660 || client->flags.require_preauth 661 || server->flags.require_preauth) { 662 METHOD_DATA method_data; 663 PA_DATA *pa; 664 unsigned char *buf; 665 size_t len; 666 krb5_data foo_data; 667 668 use_pa: 669 method_data.len = 0; 670 method_data.val = NULL; 671 672 ret = realloc_method_data(&method_data); 673 pa = &method_data.val[method_data.len-1]; 674 pa->padata_type = KRB5_PADATA_ENC_TIMESTAMP; 675 pa->padata_value.length = 0; 676 pa->padata_value.data = NULL; 677 678 ret = get_pa_etype_info(&method_data, client, 679 b->etype.val, b->etype.len); /* XXX check ret */ 680 681 ASN1_MALLOC_ENCODE(METHOD_DATA, buf, len, &method_data, &len, ret); 682 free_METHOD_DATA(&method_data); 683 foo_data.data = buf; 684 foo_data.length = len; 685 686 ret = KRB5KDC_ERR_PREAUTH_REQUIRED; 687 krb5_mk_error(context, 688 ret, 689 "Need to use PA-ENC-TIMESTAMP", 690 &foo_data, 691 client_princ, 692 server_princ, 693 NULL, 694 NULL, 695 reply); 696 free(buf); 697 kdc_log(0, "No PA-ENC-TIMESTAMP -- %s", client_name); 698 ret = 0; 699 goto out2; 700 } 701 702 ret = find_keys(client, server, &ckey, &cetype, &skey, &setype, 703 b->etype.val, b->etype.len); 704 if(ret) { 705 kdc_log(0, "Server/client has no support for etypes"); 706 goto out; 707 } 708 709 { 710 char *cet; 711 char *set; 712 713 ret = krb5_enctype_to_string(context, cetype, &cet); 714 if(ret == 0) { 715 ret = krb5_enctype_to_string(context, setype, &set); 716 if (ret == 0) { 717 kdc_log(5, "Using %s/%s", cet, set); 718 free(set); 719 } 720 free(cet); 721 } 722 if (ret != 0) 723 kdc_log(5, "Using e-types %d/%d", cetype, setype); 724 } 725 726 { 727 char str[128]; 728 unparse_flags(KDCOptions2int(f), KDCOptions_units, str, sizeof(str)); 729 if(*str) 730 kdc_log(2, "Requested flags: %s", str); 731 } 732 733 734 if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey 735 || (f.request_anonymous && !allow_anonymous)) { 736 ret = KRB5KDC_ERR_BADOPTION; 737 kdc_log(0, "Bad KDC options -- %s", client_name); 738 goto out; 739 } 740 741 rep.pvno = 5; 742 rep.msg_type = krb_as_rep; 743 copy_Realm(&b->realm, &rep.crealm); 744 if (f.request_anonymous) 745 make_anonymous_principalname (&rep.cname); 746 else 747 copy_PrincipalName(b->cname, &rep.cname); 748 rep.ticket.tkt_vno = 5; 749 copy_Realm(&b->realm, &rep.ticket.realm); 750 copy_PrincipalName(b->sname, &rep.ticket.sname); 751 752 et.flags.initial = 1; 753 if(client->flags.forwardable && server->flags.forwardable) 754 et.flags.forwardable = f.forwardable; 755 else if (f.forwardable) { 756 ret = KRB5KDC_ERR_POLICY; 757 kdc_log(0, "Ticket may not be forwardable -- %s", client_name); 758 goto out; 759 } 760 if(client->flags.proxiable && server->flags.proxiable) 761 et.flags.proxiable = f.proxiable; 762 else if (f.proxiable) { 763 ret = KRB5KDC_ERR_POLICY; 764 kdc_log(0, "Ticket may not be proxiable -- %s", client_name); 765 goto out; 766 } 767 if(client->flags.postdate && server->flags.postdate) 768 et.flags.may_postdate = f.allow_postdate; 769 else if (f.allow_postdate){ 770 ret = KRB5KDC_ERR_POLICY; 771 kdc_log(0, "Ticket may not be postdatable -- %s", client_name); 772 goto out; 773 } 774 775 /* check for valid set of addresses */ 776 if(!check_addresses(b->addresses, from_addr)) { 777 ret = KRB5KRB_AP_ERR_BADADDR; 778 kdc_log(0, "Bad address list requested -- %s", client_name); 779 goto out; 780 } 781 782 krb5_generate_random_keyblock(context, setype, &et.key); 783 copy_PrincipalName(&rep.cname, &et.cname); 784 copy_Realm(&b->realm, &et.crealm); 785 786 { 787 time_t start; 788 time_t t; 789 790 start = et.authtime = kdc_time; 791 792 if(f.postdated && req->req_body.from){ 793 ALLOC(et.starttime); 794 start = *et.starttime = *req->req_body.from; 795 et.flags.invalid = 1; 796 et.flags.postdated = 1; /* XXX ??? */ 797 } 798 fix_time(&b->till); 799 t = *b->till; 800 801 /* be careful not overflowing */ 802 803 if(client->max_life) 804 t = start + min(t - start, *client->max_life); 805 if(server->max_life) 806 t = start + min(t - start, *server->max_life); 807 #if 0 808 t = min(t, start + realm->max_life); 809 #endif 810 et.endtime = t; 811 if(f.renewable_ok && et.endtime < *b->till){ 812 f.renewable = 1; 813 if(b->rtime == NULL){ 814 ALLOC(b->rtime); 815 *b->rtime = 0; 816 } 817 if(*b->rtime < *b->till) 818 *b->rtime = *b->till; 819 } 820 if(f.renewable && b->rtime){ 821 t = *b->rtime; 822 if(t == 0) 823 t = MAX_TIME; 824 if(client->max_renew) 825 t = start + min(t - start, *client->max_renew); 826 if(server->max_renew) 827 t = start + min(t - start, *server->max_renew); 828 #if 0 829 t = min(t, start + realm->max_renew); 830 #endif 831 ALLOC(et.renew_till); 832 *et.renew_till = t; 833 et.flags.renewable = 1; 834 } 835 } 836 837 if (f.request_anonymous) 838 et.flags.anonymous = 1; 839 840 if(b->addresses){ 841 ALLOC(et.caddr); 842 copy_HostAddresses(b->addresses, et.caddr); 843 } 844 845 { 846 krb5_data empty_string; 847 848 krb5_data_zero(&empty_string); 849 et.transited.tr_type = DOMAIN_X500_COMPRESS; 850 et.transited.contents = empty_string; 851 } 852 853 copy_EncryptionKey(&et.key, &ek.key); 854 855 /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded 856 * as 0 and as 0x80 (meaning indefinite length) apart, and is thus 857 * incapable of correctly decoding SEQUENCE OF's of zero length. 858 * 859 * To fix this, always send at least one no-op last_req 860 * 861 * If there's a pw_end or valid_end we will use that, 862 * otherwise just a dummy lr. 863 */ 864 ek.last_req.val = malloc(2 * sizeof(*ek.last_req.val)); 865 ek.last_req.len = 0; 866 if (client->pw_end 867 && (kdc_warn_pwexpire == 0 868 || kdc_time + kdc_warn_pwexpire <= *client->pw_end)) { 869 ek.last_req.val[ek.last_req.len].lr_type = LR_PW_EXPTIME; 870 ek.last_req.val[ek.last_req.len].lr_value = *client->pw_end; 871 ++ek.last_req.len; 872 } 873 if (client->valid_end) { 874 ek.last_req.val[ek.last_req.len].lr_type = LR_ACCT_EXPTIME; 875 ek.last_req.val[ek.last_req.len].lr_value = *client->valid_end; 876 ++ek.last_req.len; 877 } 878 if (ek.last_req.len == 0) { 879 ek.last_req.val[ek.last_req.len].lr_type = LR_NONE; 880 ek.last_req.val[ek.last_req.len].lr_value = 0; 881 ++ek.last_req.len; 882 } 883 ek.nonce = b->nonce; 884 if (client->valid_end || client->pw_end) { 885 ALLOC(ek.key_expiration); 886 if (client->valid_end) { 887 if (client->pw_end) 888 *ek.key_expiration = min(*client->valid_end, *client->pw_end); 889 else 890 *ek.key_expiration = *client->valid_end; 891 } else 892 *ek.key_expiration = *client->pw_end; 893 } else 894 ek.key_expiration = NULL; 895 ek.flags = et.flags; 896 ek.authtime = et.authtime; 897 if (et.starttime) { 898 ALLOC(ek.starttime); 899 *ek.starttime = *et.starttime; 900 } 901 ek.endtime = et.endtime; 902 if (et.renew_till) { 903 ALLOC(ek.renew_till); 904 *ek.renew_till = *et.renew_till; 905 } 906 copy_Realm(&rep.ticket.realm, &ek.srealm); 907 copy_PrincipalName(&rep.ticket.sname, &ek.sname); 908 if(et.caddr){ 909 ALLOC(ek.caddr); 910 copy_HostAddresses(et.caddr, ek.caddr); 911 } 912 913 set_salt_padata (&rep.padata, ckey->salt); 914 ret = encode_reply(&rep, &et, &ek, setype, server->kvno, &skey->key, 915 client->kvno, &ckey->key, &e_text, reply); 916 free_EncTicketPart(&et); 917 free_EncKDCRepPart(&ek); 918 out: 919 free_AS_REP(&rep); 920 if(ret){ 921 krb5_mk_error(context, 922 ret, 923 e_text, 924 NULL, 925 client_princ, 926 server_princ, 927 NULL, 928 NULL, 929 reply); 930 ret = 0; 931 } 932 out2: 933 krb5_free_principal(context, client_princ); 934 free(client_name); 935 krb5_free_principal(context, server_princ); 936 free(server_name); 937 if(client) 938 free_ent(client); 939 if(server) 940 free_ent(server); 941 return ret; 942 } 943 944 945 static krb5_error_code 946 check_tgs_flags(KDC_REQ_BODY *b, EncTicketPart *tgt, EncTicketPart *et) 947 { 948 KDCOptions f = b->kdc_options; 949 950 if(f.validate){ 951 if(!tgt->flags.invalid || tgt->starttime == NULL){ 952 kdc_log(0, "Bad request to validate ticket"); 953 return KRB5KDC_ERR_BADOPTION; 954 } 955 if(*tgt->starttime > kdc_time){ 956 kdc_log(0, "Early request to validate ticket"); 957 return KRB5KRB_AP_ERR_TKT_NYV; 958 } 959 /* XXX tkt = tgt */ 960 et->flags.invalid = 0; 961 }else if(tgt->flags.invalid){ 962 kdc_log(0, "Ticket-granting ticket has INVALID flag set"); 963 return KRB5KRB_AP_ERR_TKT_INVALID; 964 } 965 966 if(f.forwardable){ 967 if(!tgt->flags.forwardable){ 968 kdc_log(0, "Bad request for forwardable ticket"); 969 return KRB5KDC_ERR_BADOPTION; 970 } 971 et->flags.forwardable = 1; 972 } 973 if(f.forwarded){ 974 if(!tgt->flags.forwardable){ 975 kdc_log(0, "Request to forward non-forwardable ticket"); 976 return KRB5KDC_ERR_BADOPTION; 977 } 978 et->flags.forwarded = 1; 979 et->caddr = b->addresses; 980 } 981 if(tgt->flags.forwarded) 982 et->flags.forwarded = 1; 983 984 if(f.proxiable){ 985 if(!tgt->flags.proxiable){ 986 kdc_log(0, "Bad request for proxiable ticket"); 987 return KRB5KDC_ERR_BADOPTION; 988 } 989 et->flags.proxiable = 1; 990 } 991 if(f.proxy){ 992 if(!tgt->flags.proxiable){ 993 kdc_log(0, "Request to proxy non-proxiable ticket"); 994 return KRB5KDC_ERR_BADOPTION; 995 } 996 et->flags.proxy = 1; 997 et->caddr = b->addresses; 998 } 999 if(tgt->flags.proxy) 1000 et->flags.proxy = 1; 1001 1002 if(f.allow_postdate){ 1003 if(!tgt->flags.may_postdate){ 1004 kdc_log(0, "Bad request for post-datable ticket"); 1005 return KRB5KDC_ERR_BADOPTION; 1006 } 1007 et->flags.may_postdate = 1; 1008 } 1009 if(f.postdated){ 1010 if(!tgt->flags.may_postdate){ 1011 kdc_log(0, "Bad request for postdated ticket"); 1012 return KRB5KDC_ERR_BADOPTION; 1013 } 1014 if(b->from) 1015 *et->starttime = *b->from; 1016 et->flags.postdated = 1; 1017 et->flags.invalid = 1; 1018 }else if(b->from && *b->from > kdc_time + context->max_skew){ 1019 kdc_log(0, "Ticket cannot be postdated"); 1020 return KRB5KDC_ERR_CANNOT_POSTDATE; 1021 } 1022 1023 if(f.renewable){ 1024 if(!tgt->flags.renewable){ 1025 kdc_log(0, "Bad request for renewable ticket"); 1026 return KRB5KDC_ERR_BADOPTION; 1027 } 1028 et->flags.renewable = 1; 1029 ALLOC(et->renew_till); 1030 fix_time(&b->rtime); 1031 *et->renew_till = *b->rtime; 1032 } 1033 if(f.renew){ 1034 time_t old_life; 1035 if(!tgt->flags.renewable || tgt->renew_till == NULL){ 1036 kdc_log(0, "Request to renew non-renewable ticket"); 1037 return KRB5KDC_ERR_BADOPTION; 1038 } 1039 old_life = tgt->endtime; 1040 if(tgt->starttime) 1041 old_life -= *tgt->starttime; 1042 else 1043 old_life -= tgt->authtime; 1044 et->endtime = *et->starttime + old_life; 1045 if (et->renew_till != NULL) 1046 et->endtime = min(*et->renew_till, et->endtime); 1047 } 1048 1049 /* checks for excess flags */ 1050 if(f.request_anonymous && !allow_anonymous){ 1051 kdc_log(0, "Request for anonymous ticket"); 1052 return KRB5KDC_ERR_BADOPTION; 1053 } 1054 return 0; 1055 } 1056 1057 static krb5_error_code 1058 fix_transited_encoding(TransitedEncoding *tr, 1059 const char *client_realm, 1060 const char *server_realm, 1061 const char *tgt_realm) 1062 { 1063 krb5_error_code ret = 0; 1064 if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)){ 1065 char **realms = NULL, **tmp; 1066 int num_realms = 0; 1067 int i; 1068 if(tr->tr_type && tr->contents.length != 0) { 1069 if(tr->tr_type != DOMAIN_X500_COMPRESS){ 1070 kdc_log(0, "Unknown transited type: %u", 1071 tr->tr_type); 1072 return KRB5KDC_ERR_TRTYPE_NOSUPP; 1073 } 1074 ret = krb5_domain_x500_decode(context, 1075 tr->contents, 1076 &realms, 1077 &num_realms, 1078 client_realm, 1079 server_realm); 1080 if(ret){ 1081 krb5_warn(context, ret, "Decoding transited encoding"); 1082 return ret; 1083 } 1084 } 1085 if (num_realms < 0 || num_realms + 1 > UINT_MAX/sizeof(*realms)) { 1086 ret = ERANGE; 1087 goto free_realms; 1088 } 1089 tmp = realloc(realms, (num_realms + 1) * sizeof(*realms)); 1090 if(tmp == NULL){ 1091 ret = ENOMEM; 1092 goto free_realms; 1093 } 1094 realms = tmp; 1095 realms[num_realms] = strdup(tgt_realm); 1096 if(realms[num_realms] == NULL){ 1097 ret = ENOMEM; 1098 goto free_realms; 1099 } 1100 num_realms++; 1101 free_TransitedEncoding(tr); 1102 tr->tr_type = DOMAIN_X500_COMPRESS; 1103 ret = krb5_domain_x500_encode(realms, num_realms, &tr->contents); 1104 if(ret) 1105 krb5_warn(context, ret, "Encoding transited encoding"); 1106 free_realms: 1107 for(i = 0; i < num_realms; i++) 1108 free(realms[i]); 1109 free(realms); 1110 } 1111 return ret; 1112 } 1113 1114 1115 static krb5_error_code 1116 tgs_make_reply(KDC_REQ_BODY *b, 1117 EncTicketPart *tgt, 1118 EncTicketPart *adtkt, 1119 AuthorizationData *auth_data, 1120 hdb_entry *server, 1121 hdb_entry *client, 1122 krb5_principal client_principal, 1123 hdb_entry *krbtgt, 1124 krb5_enctype cetype, 1125 const char **e_text, 1126 krb5_data *reply) 1127 { 1128 KDC_REP rep; 1129 EncKDCRepPart ek; 1130 EncTicketPart et; 1131 KDCOptions f = b->kdc_options; 1132 krb5_error_code ret; 1133 krb5_enctype etype; 1134 Key *skey; 1135 EncryptionKey *ekey; 1136 1137 if(adtkt) { 1138 int i; 1139 krb5_keytype kt; 1140 ekey = &adtkt->key; 1141 for(i = 0; i < b->etype.len; i++){ 1142 ret = krb5_enctype_to_keytype(context, b->etype.val[i], &kt); 1143 if(ret) 1144 continue; 1145 if(adtkt->key.keytype == kt) 1146 break; 1147 } 1148 if(i == b->etype.len) 1149 return KRB5KDC_ERR_ETYPE_NOSUPP; 1150 etype = b->etype.val[i]; 1151 }else{ 1152 ret = find_keys(NULL, server, NULL, NULL, &skey, &etype, 1153 b->etype.val, b->etype.len); 1154 if(ret) { 1155 kdc_log(0, "Server has no support for etypes"); 1156 return ret; 1157 } 1158 ekey = &skey->key; 1159 } 1160 1161 memset(&rep, 0, sizeof(rep)); 1162 memset(&et, 0, sizeof(et)); 1163 memset(&ek, 0, sizeof(ek)); 1164 1165 rep.pvno = 5; 1166 rep.msg_type = krb_tgs_rep; 1167 1168 et.authtime = tgt->authtime; 1169 fix_time(&b->till); 1170 et.endtime = min(tgt->endtime, *b->till); 1171 ALLOC(et.starttime); 1172 *et.starttime = kdc_time; 1173 1174 ret = check_tgs_flags(b, tgt, &et); 1175 if(ret) 1176 goto out; 1177 1178 copy_TransitedEncoding(&tgt->transited, &et.transited); 1179 ret = fix_transited_encoding(&et.transited, 1180 *krb5_princ_realm(context, client_principal), 1181 *krb5_princ_realm(context, server->principal), 1182 *krb5_princ_realm(context, krbtgt->principal)); 1183 if(ret) 1184 goto out; 1185 1186 copy_Realm(krb5_princ_realm(context, server->principal), 1187 &rep.ticket.realm); 1188 krb5_principal2principalname(&rep.ticket.sname, server->principal); 1189 copy_Realm(&tgt->crealm, &rep.crealm); 1190 if (f.request_anonymous) 1191 make_anonymous_principalname (&tgt->cname); 1192 else 1193 copy_PrincipalName(&tgt->cname, &rep.cname); 1194 rep.ticket.tkt_vno = 5; 1195 1196 ek.caddr = et.caddr; 1197 if(et.caddr == NULL) 1198 et.caddr = tgt->caddr; 1199 1200 { 1201 time_t life; 1202 life = et.endtime - *et.starttime; 1203 if(client && client->max_life) 1204 life = min(life, *client->max_life); 1205 if(server->max_life) 1206 life = min(life, *server->max_life); 1207 et.endtime = *et.starttime + life; 1208 } 1209 if(f.renewable_ok && tgt->flags.renewable && 1210 et.renew_till == NULL && et.endtime < *b->till){ 1211 et.flags.renewable = 1; 1212 ALLOC(et.renew_till); 1213 *et.renew_till = *b->till; 1214 } 1215 if(et.renew_till){ 1216 time_t renew; 1217 renew = *et.renew_till - et.authtime; 1218 if(client && client->max_renew) 1219 renew = min(renew, *client->max_renew); 1220 if(server->max_renew) 1221 renew = min(renew, *server->max_renew); 1222 *et.renew_till = et.authtime + renew; 1223 } 1224 1225 if(et.renew_till){ 1226 *et.renew_till = min(*et.renew_till, *tgt->renew_till); 1227 *et.starttime = min(*et.starttime, *et.renew_till); 1228 et.endtime = min(et.endtime, *et.renew_till); 1229 } 1230 1231 *et.starttime = min(*et.starttime, et.endtime); 1232 1233 if(*et.starttime == et.endtime){ 1234 ret = KRB5KDC_ERR_NEVER_VALID; 1235 goto out; 1236 } 1237 if(et.renew_till && et.endtime == *et.renew_till){ 1238 free(et.renew_till); 1239 et.renew_till = NULL; 1240 et.flags.renewable = 0; 1241 } 1242 1243 et.flags.pre_authent = tgt->flags.pre_authent; 1244 et.flags.hw_authent = tgt->flags.hw_authent; 1245 et.flags.anonymous = tgt->flags.anonymous; 1246 1247 /* XXX Check enc-authorization-data */ 1248 et.authorization_data = auth_data; 1249 1250 krb5_generate_random_keyblock(context, etype, &et.key); 1251 et.crealm = tgt->crealm; 1252 et.cname = tgt->cname; 1253 1254 ek.key = et.key; 1255 /* MIT must have at least one last_req */ 1256 ek.last_req.len = 1; 1257 ek.last_req.val = calloc(1, sizeof(*ek.last_req.val)); 1258 ek.nonce = b->nonce; 1259 ek.flags = et.flags; 1260 ek.authtime = et.authtime; 1261 ek.starttime = et.starttime; 1262 ek.endtime = et.endtime; 1263 ek.renew_till = et.renew_till; 1264 ek.srealm = rep.ticket.realm; 1265 ek.sname = rep.ticket.sname; 1266 1267 /* It is somewhat unclear where the etype in the following 1268 encryption should come from. What we have is a session 1269 key in the passed tgt, and a list of preferred etypes 1270 *for the new ticket*. Should we pick the best possible 1271 etype, given the keytype in the tgt, or should we look 1272 at the etype list here as well? What if the tgt 1273 session key is DES3 and we want a ticket with a (say) 1274 CAST session key. Should the DES3 etype be added to the 1275 etype list, even if we don't want a session key with 1276 DES3? */ 1277 ret = encode_reply(&rep, &et, &ek, etype, adtkt ? 0 : server->kvno, ekey, 1278 0, &tgt->key, e_text, reply); 1279 out: 1280 free_TGS_REP(&rep); 1281 free_TransitedEncoding(&et.transited); 1282 if(et.starttime) 1283 free(et.starttime); 1284 if(et.renew_till) 1285 free(et.renew_till); 1286 free_LastReq(&ek.last_req); 1287 memset(et.key.keyvalue.data, 0, et.key.keyvalue.length); 1288 free_EncryptionKey(&et.key); 1289 return ret; 1290 } 1291 1292 static krb5_error_code 1293 tgs_check_authenticator(krb5_auth_context ac, 1294 KDC_REQ_BODY *b, 1295 const char **e_text, 1296 krb5_keyblock *key) 1297 { 1298 krb5_authenticator auth; 1299 size_t len; 1300 unsigned char *buf; 1301 size_t buf_size; 1302 krb5_error_code ret; 1303 krb5_crypto crypto; 1304 1305 krb5_auth_con_getauthenticator(context, ac, &auth); 1306 if(auth->cksum == NULL){ 1307 kdc_log(0, "No authenticator in request"); 1308 ret = KRB5KRB_AP_ERR_INAPP_CKSUM; 1309 goto out; 1310 } 1311 /* 1312 * according to RFC1510 it doesn't need to be keyed, 1313 * but according to the latest draft it needs to. 1314 */ 1315 if ( 1316 #if 0 1317 !krb5_checksum_is_keyed(context, auth->cksum->cksumtype) 1318 || 1319 #endif 1320 !krb5_checksum_is_collision_proof(context, auth->cksum->cksumtype)) { 1321 kdc_log(0, "Bad checksum type in authenticator: %d", 1322 auth->cksum->cksumtype); 1323 ret = KRB5KRB_AP_ERR_INAPP_CKSUM; 1324 goto out; 1325 } 1326 1327 /* XXX should not re-encode this */ 1328 ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, b, &len, ret); 1329 if(ret){ 1330 kdc_log(0, "Failed to encode KDC-REQ-BODY: %s", 1331 krb5_get_err_text(context, ret)); 1332 goto out; 1333 } 1334 if(buf_size != len) { 1335 free(buf); 1336 kdc_log(0, "Internal error in ASN.1 encoder"); 1337 *e_text = "KDC internal error"; 1338 ret = KRB5KRB_ERR_GENERIC; 1339 goto out; 1340 } 1341 ret = krb5_crypto_init(context, key, 0, &crypto); 1342 if (ret) { 1343 free(buf); 1344 kdc_log(0, "krb5_crypto_init failed: %s", 1345 krb5_get_err_text(context, ret)); 1346 goto out; 1347 } 1348 ret = krb5_verify_checksum(context, 1349 crypto, 1350 KRB5_KU_TGS_REQ_AUTH_CKSUM, 1351 buf, 1352 len, 1353 auth->cksum); 1354 free(buf); 1355 krb5_crypto_destroy(context, crypto); 1356 if(ret){ 1357 kdc_log(0, "Failed to verify checksum: %s", 1358 krb5_get_err_text(context, ret)); 1359 } 1360 out: 1361 free_Authenticator(auth); 1362 free(auth); 1363 return ret; 1364 } 1365 1366 /* 1367 * return the realm of a krbtgt-ticket or NULL 1368 */ 1369 1370 static Realm 1371 get_krbtgt_realm(const PrincipalName *p) 1372 { 1373 if(p->name_string.len == 2 1374 && strcmp(p->name_string.val[0], KRB5_TGS_NAME) == 0) 1375 return p->name_string.val[1]; 1376 else 1377 return NULL; 1378 } 1379 1380 static Realm 1381 find_rpath(Realm r) 1382 { 1383 const char *new_realm = krb5_config_get_string(context, 1384 NULL, 1385 "libdefaults", 1386 "capath", 1387 r, 1388 NULL); 1389 return (Realm)new_realm; 1390 } 1391 1392 1393 static krb5_boolean 1394 need_referral(krb5_principal server, krb5_realm **realms) 1395 { 1396 if(server->name.name_type != KRB5_NT_SRV_INST || 1397 server->name.name_string.len != 2) 1398 return FALSE; 1399 1400 return krb5_get_host_realm_int(context, server->name.name_string.val[1], 1401 FALSE, realms) == 0; 1402 } 1403 1404 static krb5_error_code 1405 tgs_rep2(KDC_REQ_BODY *b, 1406 PA_DATA *tgs_req, 1407 krb5_data *reply, 1408 const char *from, 1409 const struct sockaddr *from_addr, 1410 time_t **csec, 1411 int **cusec) 1412 { 1413 krb5_ap_req ap_req; 1414 krb5_error_code ret; 1415 krb5_principal princ; 1416 krb5_auth_context ac = NULL; 1417 krb5_ticket *ticket = NULL; 1418 krb5_flags ap_req_options; 1419 krb5_flags verify_ap_req_flags; 1420 const char *e_text = NULL; 1421 krb5_crypto crypto; 1422 1423 hdb_entry *krbtgt = NULL; 1424 EncTicketPart *tgt; 1425 Key *tkey; 1426 krb5_enctype cetype; 1427 krb5_principal cp = NULL; 1428 krb5_principal sp = NULL; 1429 AuthorizationData *auth_data = NULL; 1430 1431 *csec = NULL; 1432 *cusec = NULL; 1433 1434 memset(&ap_req, 0, sizeof(ap_req)); 1435 ret = krb5_decode_ap_req(context, &tgs_req->padata_value, &ap_req); 1436 if(ret){ 1437 kdc_log(0, "Failed to decode AP-REQ: %s", 1438 krb5_get_err_text(context, ret)); 1439 goto out2; 1440 } 1441 1442 if(!get_krbtgt_realm(&ap_req.ticket.sname)){ 1443 /* XXX check for ticket.sname == req.sname */ 1444 kdc_log(0, "PA-DATA is not a ticket-granting ticket"); 1445 ret = KRB5KDC_ERR_POLICY; /* ? */ 1446 goto out2; 1447 } 1448 1449 principalname2krb5_principal(&princ, 1450 ap_req.ticket.sname, 1451 ap_req.ticket.realm); 1452 1453 ret = db_fetch(princ, &krbtgt); 1454 1455 if(ret) { 1456 char *p; 1457 krb5_unparse_name(context, princ, &p); 1458 krb5_free_principal(context, princ); 1459 kdc_log(0, "Ticket-granting ticket not found in database: %s: %s", 1460 p, krb5_get_err_text(context, ret)); 1461 free(p); 1462 ret = KRB5KRB_AP_ERR_NOT_US; 1463 goto out2; 1464 } 1465 1466 if(ap_req.ticket.enc_part.kvno && 1467 *ap_req.ticket.enc_part.kvno != krbtgt->kvno){ 1468 char *p; 1469 1470 krb5_unparse_name (context, princ, &p); 1471 krb5_free_principal(context, princ); 1472 kdc_log(0, "Ticket kvno = %d, DB kvno = %d (%s)", 1473 *ap_req.ticket.enc_part.kvno, 1474 krbtgt->kvno, 1475 p); 1476 free (p); 1477 ret = KRB5KRB_AP_ERR_BADKEYVER; 1478 goto out2; 1479 } 1480 1481 ret = hdb_enctype2key(context, krbtgt, ap_req.ticket.enc_part.etype, &tkey); 1482 if(ret){ 1483 char *str; 1484 krb5_enctype_to_string(context, ap_req.ticket.enc_part.etype, &str); 1485 kdc_log(0, "No server key found for %s", str); 1486 free(str); 1487 ret = KRB5KRB_AP_ERR_BADKEYVER; 1488 goto out2; 1489 } 1490 1491 if (b->kdc_options.validate) 1492 verify_ap_req_flags = KRB5_VERIFY_AP_REQ_IGNORE_INVALID; 1493 else 1494 verify_ap_req_flags = 0; 1495 1496 ret = krb5_verify_ap_req2(context, 1497 &ac, 1498 &ap_req, 1499 princ, 1500 &tkey->key, 1501 verify_ap_req_flags, 1502 &ap_req_options, 1503 &ticket, 1504 KRB5_KU_TGS_REQ_AUTH); 1505 1506 krb5_free_principal(context, princ); 1507 if(ret) { 1508 kdc_log(0, "Failed to verify AP-REQ: %s", 1509 krb5_get_err_text(context, ret)); 1510 goto out2; 1511 } 1512 1513 { 1514 krb5_authenticator auth; 1515 1516 ret = krb5_auth_con_getauthenticator(context, ac, &auth); 1517 if (ret == 0) { 1518 *csec = malloc(sizeof(**csec)); 1519 if (*csec == NULL) { 1520 krb5_free_authenticator(context, &auth); 1521 kdc_log(0, "malloc failed"); 1522 goto out2; 1523 } 1524 **csec = auth->ctime; 1525 *cusec = malloc(sizeof(**cusec)); 1526 if (*cusec == NULL) { 1527 krb5_free_authenticator(context, &auth); 1528 kdc_log(0, "malloc failed"); 1529 goto out2; 1530 } 1531 **csec = auth->cusec; 1532 krb5_free_authenticator(context, &auth); 1533 } 1534 } 1535 1536 cetype = ap_req.authenticator.etype; 1537 1538 tgt = &ticket->ticket; 1539 1540 ret = tgs_check_authenticator(ac, b, &e_text, &tgt->key); 1541 1542 if (b->enc_authorization_data) { 1543 krb5_keyblock *subkey; 1544 krb5_data ad; 1545 ret = krb5_auth_con_getremotesubkey(context, 1546 ac, 1547 &subkey); 1548 if(ret){ 1549 krb5_auth_con_free(context, ac); 1550 kdc_log(0, "Failed to get remote subkey: %s", 1551 krb5_get_err_text(context, ret)); 1552 goto out2; 1553 } 1554 if(subkey == NULL){ 1555 ret = krb5_auth_con_getkey(context, ac, &subkey); 1556 if(ret) { 1557 krb5_auth_con_free(context, ac); 1558 kdc_log(0, "Failed to get session key: %s", 1559 krb5_get_err_text(context, ret)); 1560 goto out2; 1561 } 1562 } 1563 if(subkey == NULL){ 1564 krb5_auth_con_free(context, ac); 1565 kdc_log(0, "Failed to get key for enc-authorization-data"); 1566 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */ 1567 goto out2; 1568 } 1569 ret = krb5_crypto_init(context, subkey, 0, &crypto); 1570 if (ret) { 1571 krb5_auth_con_free(context, ac); 1572 kdc_log(0, "krb5_crypto_init failed: %s", 1573 krb5_get_err_text(context, ret)); 1574 goto out2; 1575 } 1576 ret = krb5_decrypt_EncryptedData (context, 1577 crypto, 1578 KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY, 1579 b->enc_authorization_data, 1580 &ad); 1581 krb5_crypto_destroy(context, crypto); 1582 if(ret){ 1583 krb5_auth_con_free(context, ac); 1584 kdc_log(0, "Failed to decrypt enc-authorization-data"); 1585 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */ 1586 goto out2; 1587 } 1588 krb5_free_keyblock(context, subkey); 1589 ALLOC(auth_data); 1590 ret = decode_AuthorizationData(ad.data, ad.length, auth_data, NULL); 1591 if(ret){ 1592 krb5_auth_con_free(context, ac); 1593 free(auth_data); 1594 auth_data = NULL; 1595 kdc_log(0, "Failed to decode authorization data"); 1596 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */ 1597 goto out2; 1598 } 1599 } 1600 1601 krb5_auth_con_free(context, ac); 1602 1603 if(ret){ 1604 kdc_log(0, "Failed to verify authenticator: %s", 1605 krb5_get_err_text(context, ret)); 1606 goto out2; 1607 } 1608 1609 { 1610 PrincipalName *s; 1611 Realm r; 1612 char *spn = NULL, *cpn = NULL; 1613 hdb_entry *server = NULL, *client = NULL; 1614 int loop = 0; 1615 EncTicketPart adtkt; 1616 char opt_str[128]; 1617 1618 s = b->sname; 1619 r = b->realm; 1620 if(b->kdc_options.enc_tkt_in_skey){ 1621 Ticket *t; 1622 hdb_entry *uu; 1623 krb5_principal p; 1624 Key *tkey; 1625 1626 if(b->additional_tickets == NULL || 1627 b->additional_tickets->len == 0){ 1628 ret = KRB5KDC_ERR_BADOPTION; /* ? */ 1629 kdc_log(0, "No second ticket present in request"); 1630 goto out; 1631 } 1632 t = &b->additional_tickets->val[0]; 1633 if(!get_krbtgt_realm(&t->sname)){ 1634 kdc_log(0, "Additional ticket is not a ticket-granting ticket"); 1635 ret = KRB5KDC_ERR_POLICY; 1636 goto out2; 1637 } 1638 principalname2krb5_principal(&p, t->sname, t->realm); 1639 ret = db_fetch(p, &uu); 1640 krb5_free_principal(context, p); 1641 if(ret){ 1642 if (ret == HDB_ERR_NOENTRY) 1643 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; 1644 goto out; 1645 } 1646 ret = hdb_enctype2key(context, uu, t->enc_part.etype, &tkey); 1647 if(ret){ 1648 ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */ 1649 goto out; 1650 } 1651 ret = krb5_decrypt_ticket(context, t, &tkey->key, &adtkt, 0); 1652 1653 if(ret) 1654 goto out; 1655 s = &adtkt.cname; 1656 r = adtkt.crealm; 1657 } 1658 1659 principalname2krb5_principal(&sp, *s, r); 1660 krb5_unparse_name(context, sp, &spn); 1661 principalname2krb5_principal(&cp, tgt->cname, tgt->crealm); 1662 krb5_unparse_name(context, cp, &cpn); 1663 unparse_flags (KDCOptions2int(b->kdc_options), KDCOptions_units, 1664 opt_str, sizeof(opt_str)); 1665 if(*opt_str) 1666 kdc_log(0, "TGS-REQ %s from %s for %s [%s]", 1667 cpn, from, spn, opt_str); 1668 else 1669 kdc_log(0, "TGS-REQ %s from %s for %s", cpn, from, spn); 1670 server_lookup: 1671 ret = db_fetch(sp, &server); 1672 1673 if(ret){ 1674 Realm req_rlm, new_rlm; 1675 krb5_realm *realms; 1676 1677 if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) { 1678 if(loop++ < 2) { 1679 new_rlm = find_rpath(req_rlm); 1680 if(new_rlm) { 1681 kdc_log(5, "krbtgt for realm %s not found, trying %s", 1682 req_rlm, new_rlm); 1683 krb5_free_principal(context, sp); 1684 free(spn); 1685 krb5_make_principal(context, &sp, r, 1686 KRB5_TGS_NAME, new_rlm, NULL); 1687 krb5_unparse_name(context, sp, &spn); 1688 goto server_lookup; 1689 } 1690 } 1691 } else if(need_referral(sp, &realms)) { 1692 if (strcmp(realms[0], sp->realm) != 0) { 1693 kdc_log(5, "returning a referral to realm %s for " 1694 "server %s that was not found", 1695 realms[0], spn); 1696 krb5_free_principal(context, sp); 1697 free(spn); 1698 krb5_make_principal(context, &sp, r, KRB5_TGS_NAME, 1699 realms[0], NULL); 1700 krb5_unparse_name(context, sp, &spn); 1701 krb5_free_host_realm(context, realms); 1702 goto server_lookup; 1703 } 1704 krb5_free_host_realm(context, realms); 1705 } 1706 kdc_log(0, "Server not found in database: %s: %s", spn, 1707 krb5_get_err_text(context, ret)); 1708 if (ret == HDB_ERR_NOENTRY) 1709 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; 1710 goto out; 1711 } 1712 1713 ret = db_fetch(cp, &client); 1714 if(ret) 1715 kdc_log(1, "Client not found in database: %s: %s", 1716 cpn, krb5_get_err_text(context, ret)); 1717 #if 0 1718 /* XXX check client only if same realm as krbtgt-instance */ 1719 if(ret){ 1720 kdc_log(0, "Client not found in database: %s: %s", 1721 cpn, krb5_get_err_text(context, ret)); 1722 if (ret == HDB_ERR_NOENTRY) 1723 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; 1724 goto out; 1725 } 1726 #endif 1727 1728 ret = check_flags(client, cpn, server, spn, FALSE); 1729 if(ret) 1730 goto out; 1731 1732 if((b->kdc_options.validate || b->kdc_options.renew) && 1733 !krb5_principal_compare(context, 1734 krbtgt->principal, 1735 server->principal)){ 1736 kdc_log(0, "Inconsistent request."); 1737 ret = KRB5KDC_ERR_SERVER_NOMATCH; 1738 goto out; 1739 } 1740 1741 /* check for valid set of addresses */ 1742 if(!check_addresses(tgt->caddr, from_addr)) { 1743 ret = KRB5KRB_AP_ERR_BADADDR; 1744 kdc_log(0, "Request from wrong address"); 1745 goto out; 1746 } 1747 1748 ret = tgs_make_reply(b, 1749 tgt, 1750 b->kdc_options.enc_tkt_in_skey ? &adtkt : NULL, 1751 auth_data, 1752 server, 1753 client, 1754 cp, 1755 krbtgt, 1756 cetype, 1757 &e_text, 1758 reply); 1759 1760 out: 1761 free(spn); 1762 free(cpn); 1763 1764 if(server) 1765 free_ent(server); 1766 if(client) 1767 free_ent(client); 1768 } 1769 out2: 1770 if(ret) { 1771 krb5_mk_error(context, 1772 ret, 1773 e_text, 1774 NULL, 1775 cp, 1776 sp, 1777 NULL, 1778 NULL, 1779 reply); 1780 free(*csec); 1781 free(*cusec); 1782 *csec = NULL; 1783 *cusec = NULL; 1784 } 1785 krb5_free_principal(context, cp); 1786 krb5_free_principal(context, sp); 1787 if (ticket) { 1788 krb5_free_ticket(context, ticket); 1789 free(ticket); 1790 } 1791 free_AP_REQ(&ap_req); 1792 if(auth_data){ 1793 free_AuthorizationData(auth_data); 1794 free(auth_data); 1795 } 1796 1797 if(krbtgt) 1798 free_ent(krbtgt); 1799 1800 return ret; 1801 } 1802 1803 1804 krb5_error_code 1805 tgs_rep(KDC_REQ *req, 1806 krb5_data *data, 1807 const char *from, 1808 struct sockaddr *from_addr) 1809 { 1810 krb5_error_code ret; 1811 int i = 0; 1812 PA_DATA *tgs_req = NULL; 1813 time_t *csec = NULL; 1814 int *cusec = NULL; 1815 1816 if(req->padata == NULL){ 1817 ret = KRB5KDC_ERR_PREAUTH_REQUIRED; /* XXX ??? */ 1818 kdc_log(0, "TGS-REQ from %s without PA-DATA", from); 1819 goto out; 1820 } 1821 1822 tgs_req = find_padata(req, &i, KRB5_PADATA_TGS_REQ); 1823 1824 if(tgs_req == NULL){ 1825 ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP; 1826 1827 kdc_log(0, "TGS-REQ from %s without PA-TGS-REQ", from); 1828 goto out; 1829 } 1830 ret = tgs_rep2(&req->req_body, tgs_req, data, from, from_addr, 1831 &csec, &cusec); 1832 out: 1833 if(ret && data->data == NULL){ 1834 krb5_mk_error(context, 1835 ret, 1836 NULL, 1837 NULL, 1838 NULL, 1839 NULL, 1840 csec, 1841 cusec, 1842 data); 1843 } 1844 free(csec); 1845 free(cusec); 1846 return 0; 1847 } 1848