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