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