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