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