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