1/* 2 * Copyright (c) 1997-2007 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Portions Copyright (c) 2009 Apple Inc. 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((size_t)*start < req->padata->len){ 80 (*start)++; 81 if(req->padata->val[*start - 1].padata_type == (unsigned)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, krb5_boolean use_strongest_session_key, 129 krb5_boolean is_preauth, hdb_entry_ex *princ, 130 krb5_enctype *etypes, unsigned len, 131 krb5_enctype *ret_enctype, Key **ret_key) 132{ 133 krb5_error_code ret; 134 krb5_salt def_salt; 135 krb5_enctype enctype = ETYPE_NULL; 136 Key *key; 137 int i; 138 139 /* We'll want to avoid keys with v4 salted keys in the pre-auth case... */ 140 ret = krb5_get_pw_salt(context, princ->entry.principal, &def_salt); 141 if (ret) 142 return ret; 143 144 ret = KRB5KDC_ERR_ETYPE_NOSUPP; 145 146 if (use_strongest_session_key) { 147 const krb5_enctype *p; 148 krb5_enctype clientbest = ETYPE_NULL; 149 int j; 150 151 /* 152 * Pick the strongest key that the KDC, target service, and 153 * client all support, using the local cryptosystem enctype 154 * list in strongest-to-weakest order to drive the search. 155 * 156 * This is not what RFC4120 says to do, but it encourages 157 * adoption of stronger enctypes. This doesn't play well with 158 * clients that have multiple Kerberos client implementations 159 * available with different supported enctype lists. 160 */ 161 162 /* drive the search with local supported enctypes list */ 163 p = krb5_kerberos_enctypes(context); 164 for (i = 0; p[i] != ETYPE_NULL && enctype == ETYPE_NULL; i++) { 165 if (krb5_enctype_valid(context, p[i]) != 0) 166 continue; 167 168 /* check that the client supports it too */ 169 for (j = 0; j < len && enctype == ETYPE_NULL; j++) { 170 if (p[i] != etypes[j]) 171 continue; 172 /* save best of union of { client, crypto system } */ 173 if (clientbest == ETYPE_NULL) 174 clientbest = p[i]; 175 /* check target princ support */ 176 ret = hdb_enctype2key(context, &princ->entry, p[i], &key); 177 if (ret) 178 continue; 179 if (is_preauth && !is_default_salt_p(&def_salt, key)) 180 continue; 181 enctype = p[i]; 182 } 183 } 184 if (clientbest != ETYPE_NULL && enctype == ETYPE_NULL) 185 enctype = clientbest; 186 else if (enctype == ETYPE_NULL) 187 ret = KRB5KDC_ERR_ETYPE_NOSUPP; 188 if (ret == 0 && ret_enctype != NULL) 189 *ret_enctype = enctype; 190 if (ret == 0 && ret_key != NULL) 191 *ret_key = key; 192 } else { 193 /* 194 * Pick the first key from the client's enctype list that is 195 * supported by the cryptosystem and by the given principal. 196 * 197 * RFC4120 says we SHOULD pick the first _strong_ key from the 198 * client's list... not the first key... If the admin disallows 199 * weak enctypes in krb5.conf and selects this key selection 200 * algorithm, then we get exactly what RFC4120 says. 201 */ 202 for(key = NULL, i = 0; ret != 0 && i < len; i++, key = NULL) { 203 204 if (krb5_enctype_valid(context, etypes[i]) != 0 && 205 !_kdc_is_weak_exception(princ->entry.principal, etypes[i])) 206 continue; 207 208 while (hdb_next_enctype2key(context, &princ->entry, etypes[i], &key) == 0) { 209 if (key->key.keyvalue.length == 0) { 210 ret = KRB5KDC_ERR_NULL_KEY; 211 continue; 212 } 213 if (ret_key != NULL) 214 *ret_key = key; 215 if (ret_enctype != NULL) 216 *ret_enctype = etypes[i]; 217 ret = 0; 218 if (is_preauth && is_default_salt_p(&def_salt, key)) 219 goto out; 220 } 221 } 222 } 223 224out: 225 krb5_free_salt (context, def_salt); 226 return ret; 227} 228 229krb5_error_code 230_kdc_make_anonymous_principalname (PrincipalName *pn) 231{ 232 pn->name_type = KRB5_NT_PRINCIPAL; 233 pn->name_string.len = 1; 234 pn->name_string.val = malloc(sizeof(*pn->name_string.val)); 235 if (pn->name_string.val == NULL) 236 return ENOMEM; 237 pn->name_string.val[0] = strdup("anonymous"); 238 if (pn->name_string.val[0] == NULL) { 239 free(pn->name_string.val); 240 pn->name_string.val = NULL; 241 return ENOMEM; 242 } 243 return 0; 244} 245 246static void 247_kdc_r_log(kdc_request_t r, int level, const char *fmt, ...) 248{ 249 va_list ap; 250 char *s; 251 va_start(ap, fmt); 252 s = kdc_log_msg_va(r->context, r->config, level, fmt, ap); 253 if(s) free(s); 254 va_end(ap); 255} 256 257static void 258_kdc_set_e_text(kdc_request_t r, const char *e_text) 259{ 260 r->e_text = e_text; 261 kdc_log(r->context, r->config, 0, "%s", e_text); 262} 263 264void 265_kdc_log_timestamp(krb5_context context, 266 krb5_kdc_configuration *config, 267 const char *type, 268 KerberosTime authtime, KerberosTime *starttime, 269 KerberosTime endtime, KerberosTime *renew_till) 270{ 271 char authtime_str[100], starttime_str[100], 272 endtime_str[100], renewtime_str[100]; 273 274 krb5_format_time(context, authtime, 275 authtime_str, sizeof(authtime_str), TRUE); 276 if (starttime) 277 krb5_format_time(context, *starttime, 278 starttime_str, sizeof(starttime_str), TRUE); 279 else 280 strlcpy(starttime_str, "unset", sizeof(starttime_str)); 281 krb5_format_time(context, endtime, 282 endtime_str, sizeof(endtime_str), TRUE); 283 if (renew_till) 284 krb5_format_time(context, *renew_till, 285 renewtime_str, sizeof(renewtime_str), TRUE); 286 else 287 strlcpy(renewtime_str, "unset", sizeof(renewtime_str)); 288 289 kdc_log(context, config, 5, 290 "%s authtime: %s starttime: %s endtime: %s renew till: %s", 291 type, authtime_str, starttime_str, endtime_str, renewtime_str); 292} 293 294/* 295 * 296 */ 297 298#ifdef PKINIT 299 300static krb5_error_code 301pa_pkinit_validate(kdc_request_t r, const PA_DATA *pa) 302{ 303 pk_client_params *pkp = NULL; 304 char *client_cert = NULL; 305 krb5_error_code ret; 306 307 ret = _kdc_pk_rd_padata(r->context, r->config, &r->req, pa, r->client, &pkp); 308 if (ret || pkp == NULL) { 309 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; 310 _kdc_r_log(r, 5, "Failed to decode PKINIT PA-DATA -- %s", 311 r->client_name); 312 goto out; 313 } 314 315 ret = _kdc_pk_check_client(r->context, 316 r->config, 317 r->clientdb, 318 r->client, 319 NULL, /* pku2u params */ 320 pkp, 321 &client_cert); 322 if (ret) { 323 _kdc_set_e_text(r, "PKINIT certificate not allowed to " 324 "impersonate principal"); 325 goto out; 326 } 327 328 _kdc_r_log(r, 0, "PKINIT pre-authentication succeeded -- %s using %s", 329 r->client_name, client_cert); 330 free(client_cert); 331 332 ret = _kdc_pk_mk_pa_reply(r->context, r->config, pkp, r->client, 333 r->sessionetype, &r->req, &r->request, 334 &r->reply_key, &r->session_key, &r->outpadata); 335 if (ret) { 336 _kdc_set_e_text(r, "Failed to build PK-INIT reply"); 337 goto out; 338 } 339#if 0 340 ret = _kdc_add_inital_verified_cas(r->context, r->config, 341 pkp, &r->et); 342#endif 343 out: 344 if (pkp) 345 _kdc_pk_free_client_param(r->context, pkp); 346 347 return ret; 348} 349 350#endif /* PKINIT */ 351 352/* 353 * 354 */ 355 356static krb5_error_code 357make_pa_enc_challange(krb5_context context, METHOD_DATA *md, 358 krb5_crypto crypto) 359{ 360 PA_ENC_TS_ENC p; 361 unsigned char *buf; 362 size_t buf_size; 363 size_t len; 364 EncryptedData encdata; 365 krb5_error_code ret; 366 int32_t usec; 367 int usec2; 368 369 krb5_us_timeofday (context, &p.patimestamp, &usec); 370 usec2 = usec; 371 p.pausec = &usec2; 372 373 ASN1_MALLOC_ENCODE(PA_ENC_TS_ENC, buf, buf_size, &p, &len, ret); 374 if (ret) 375 return ret; 376 if(buf_size != len) 377 krb5_abortx(context, "internal error in ASN.1 encoder"); 378 379 ret = krb5_encrypt_EncryptedData(context, 380 crypto, 381 KRB5_KU_ENC_CHALLENGE_KDC, 382 buf, 383 len, 384 0, 385 &encdata); 386 free(buf); 387 if (ret) 388 return ret; 389 390 ASN1_MALLOC_ENCODE(EncryptedData, buf, buf_size, &encdata, &len, ret); 391 free_EncryptedData(&encdata); 392 if (ret) 393 return ret; 394 if(buf_size != len) 395 krb5_abortx(context, "internal error in ASN.1 encoder"); 396 397 ret = krb5_padata_add(context, md, KRB5_PADATA_ENCRYPTED_CHALLENGE, buf, len); 398 if (ret) 399 free(buf); 400 return ret; 401} 402 403static krb5_error_code 404pa_enc_chal_validate(kdc_request_t r, const PA_DATA *pa) 405{ 406 krb5_data pepper1, pepper2, ts_data; 407 KDC_REQ_BODY *b = &r->req.req_body; 408 EncryptedData enc_data; 409 krb5_enctype aenctype; 410 krb5_error_code ret; 411 struct Key *k; 412 size_t size; 413 int i; 414 415 heim_assert(r->armor_crypto != NULL, "ENC-CHAL called for non FAST"); 416 417 if (b->kdc_options.request_anonymous) { 418 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; 419 kdc_log(r->context, r->config, 0, "ENC-CHALL doesn't support anon"); 420 return ret; 421 } 422 423 ret = decode_EncryptedData(pa->padata_value.data, 424 pa->padata_value.length, 425 &enc_data, 426 &size); 427 if (ret) { 428 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; 429 _kdc_r_log(r, 5, "Failed to decode PA-DATA -- %s", 430 r->client_name); 431 return ret; 432 } 433 434 pepper1.data = "clientchallengearmor"; 435 pepper1.length = strlen(pepper1.data); 436 pepper2.data = "challengelongterm"; 437 pepper2.length = strlen(pepper2.data); 438 439 krb5_crypto_getenctype(r->context, r->armor_crypto, &aenctype); 440 441 for (i = 0; i < r->client->entry.keys.len; i++) { 442 krb5_crypto challangecrypto, longtermcrypto; 443 krb5_keyblock challangekey; 444 PA_ENC_TS_ENC p; 445 446 k = &r->client->entry.keys.val[i]; 447 448 ret = krb5_crypto_init(r->context, &k->key, 0, &longtermcrypto); 449 if (ret) 450 continue; 451 452 ret = krb5_crypto_fx_cf2(r->context, r->armor_crypto, longtermcrypto, 453 &pepper1, &pepper2, aenctype, 454 &challangekey); 455 krb5_crypto_destroy(r->context, longtermcrypto); 456 if (ret) 457 continue; 458 459 ret = krb5_crypto_init(r->context, &challangekey, 0, 460 &challangecrypto); 461 if (ret) 462 continue; 463 464 ret = krb5_decrypt_EncryptedData(r->context, challangecrypto, 465 KRB5_KU_ENC_CHALLENGE_CLIENT, 466 &enc_data, 467 &ts_data); 468 if (ret) 469 continue; 470 471 ret = decode_PA_ENC_TS_ENC(ts_data.data, 472 ts_data.length, 473 &p, 474 &size); 475 krb5_data_free(&ts_data); 476 if(ret){ 477 krb5_crypto_destroy(r->context, challangecrypto); 478 ret = KRB5KDC_ERR_PREAUTH_FAILED; 479 _kdc_r_log(r, 5, "Failed to decode PA-ENC-TS_ENC -- %s", 480 r->client_name); 481 continue; 482 } 483 484 if (krb5_time_abs(kdc_time, p.patimestamp) > r->context->max_skew) { 485 char client_time[100]; 486 487 krb5_crypto_destroy(r->context, challangecrypto); 488 489 krb5_format_time(r->context, p.patimestamp, 490 client_time, sizeof(client_time), TRUE); 491 492 ret = KRB5KRB_AP_ERR_SKEW; 493 _kdc_r_log(r, 0, "Too large time skew, " 494 "client time %s is out by %u > %u seconds -- %s", 495 client_time, 496 (unsigned)krb5_time_abs(kdc_time, p.patimestamp), 497 r->context->max_skew, 498 r->client_name); 499 500 free_PA_ENC_TS_ENC(&p); 501 goto out; 502 } 503 504 free_PA_ENC_TS_ENC(&p); 505 506 ret = make_pa_enc_challange(r->context, &r->outpadata, 507 challangecrypto); 508 krb5_crypto_destroy(r->context, challangecrypto); 509 if (ret) 510 goto out; 511 512 set_salt_padata(&r->outpadata, k->salt); 513 krb5_free_keyblock_contents(r->context, &r->reply_key); 514 ret = krb5_copy_keyblock_contents(r->context, &k->key, &r->reply_key); 515 ret = 0; 516 break; 517 } 518 if (i < r->client->entry.keys.len) 519 ret = KRB5KDC_ERR_PREAUTH_FAILED; 520 out: 521 free_EncryptedData(&enc_data); 522 523 return ret; 524} 525 526static krb5_error_code 527pa_enc_ts_validate(kdc_request_t r, const PA_DATA *pa) 528{ 529 EncryptedData enc_data; 530 krb5_error_code ret; 531 krb5_crypto crypto; 532 krb5_data ts_data; 533 PA_ENC_TS_ENC p; 534 size_t len; 535 Key *pa_key; 536 char *str; 537 538 if (r->req.req_body.kdc_options.request_anonymous) { 539 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; 540 _kdc_set_e_text(r, "ENC-TS doesn't support anon"); 541 goto out; 542 } 543 544 ret = decode_EncryptedData(pa->padata_value.data, 545 pa->padata_value.length, 546 &enc_data, 547 &len); 548 if (ret) { 549 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; 550 _kdc_r_log(r, 5, "Failed to decode PA-DATA -- %s", 551 r->client_name); 552 goto out; 553 } 554 555 ret = hdb_enctype2key(r->context, &r->client->entry, 556 enc_data.etype, &pa_key); 557 if(ret){ 558 char *estr; 559 _kdc_set_e_text(r, "No key matching entype"); 560 ret = KRB5KDC_ERR_ETYPE_NOSUPP; 561 if(krb5_enctype_to_string(r->context, enc_data.etype, &estr)) 562 estr = NULL; 563 if(estr == NULL) 564 _kdc_r_log(r, 5, 565 "No client key matching pa-data (%d) -- %s", 566 enc_data.etype, r->client_name); 567 else 568 _kdc_r_log(r, 5, 569 "No client key matching pa-data (%s) -- %s", 570 estr, r->client_name); 571 free(estr); 572 free_EncryptedData(&enc_data); 573 goto out; 574 } 575 576 try_next_key: 577 ret = krb5_crypto_init(r->context, &pa_key->key, 0, &crypto); 578 if (ret) { 579 const char *msg = krb5_get_error_message(r->context, ret); 580 _kdc_r_log(r, 0, "krb5_crypto_init failed: %s", msg); 581 krb5_free_error_message(r->context, msg); 582 free_EncryptedData(&enc_data); 583 goto out; 584 } 585 586 ret = krb5_decrypt_EncryptedData (r->context, 587 crypto, 588 KRB5_KU_PA_ENC_TIMESTAMP, 589 &enc_data, 590 &ts_data); 591 krb5_crypto_destroy(r->context, crypto); 592 /* 593 * Since the user might have several keys with the same 594 * enctype but with diffrent salting, we need to try all 595 * the keys with the same enctype. 596 */ 597 if(ret){ 598 krb5_error_code ret2; 599 const char *msg = krb5_get_error_message(r->context, ret); 600 601 ret2 = krb5_enctype_to_string(r->context, 602 pa_key->key.keytype, &str); 603 if (ret2) 604 str = NULL; 605 _kdc_r_log(r, 5, "Failed to decrypt PA-DATA -- %s " 606 "(enctype %s) error %s", 607 r->client_name, str ? str : "unknown enctype", msg); 608 krb5_free_error_message(r->context, msg); 609 free(str); 610 611 if(hdb_next_enctype2key(r->context, &r->client->entry, 612 enc_data.etype, &pa_key) == 0) 613 goto try_next_key; 614 615 free_EncryptedData(&enc_data); 616 617 if (r->clientdb->hdb_auth_status) 618 r->clientdb->hdb_auth_status(r->context, r->clientdb, r->client, 619 HDB_AUTH_WRONG_PASSWORD); 620 621 ret = KRB5KDC_ERR_PREAUTH_FAILED; 622 goto out; 623 } 624 free_EncryptedData(&enc_data); 625 ret = decode_PA_ENC_TS_ENC(ts_data.data, 626 ts_data.length, 627 &p, 628 &len); 629 krb5_data_free(&ts_data); 630 if(ret){ 631 ret = KRB5KDC_ERR_PREAUTH_FAILED; 632 _kdc_r_log(r, 5, "Failed to decode PA-ENC-TS_ENC -- %s", 633 r->client_name); 634 goto out; 635 } 636 if (krb5_time_abs(kdc_time, p.patimestamp) > r->context->max_skew) { 637 char client_time[100]; 638 639 krb5_format_time(r->context, p.patimestamp, 640 client_time, sizeof(client_time), TRUE); 641 642 ret = KRB5KRB_AP_ERR_SKEW; 643 _kdc_r_log(r, 0, "Too large time skew, " 644 "client time %s is out by %u > %u seconds -- %s", 645 client_time, 646 (unsigned)krb5_time_abs(kdc_time, p.patimestamp), 647 r->context->max_skew, 648 r->client_name); 649 650 /* 651 * The following is needed to make windows clients to 652 * retry using the timestamp in the error message, if 653 * there is a e_text, they become unhappy. 654 */ 655 r->e_text = NULL; 656 free_PA_ENC_TS_ENC(&p); 657 goto out; 658 } 659 free_PA_ENC_TS_ENC(&p); 660 661 set_salt_padata(&r->outpadata, pa_key->salt); 662 663 ret = krb5_copy_keyblock_contents(r->context, &pa_key->key, &r->reply_key); 664 if (ret) 665 return ret; 666 667 ret = krb5_enctype_to_string(r->context, pa_key->key.keytype, &str); 668 if (ret) 669 str = NULL; 670 _kdc_r_log(r, 2, "ENC-TS Pre-authentication succeeded -- %s using %s", 671 r->client_name, str ? str : "unknown enctype"); 672 free(str); 673 674 ret = 0; 675 676 out: 677 678 return ret; 679} 680 681struct kdc_patypes { 682 int type; 683 char *name; 684 unsigned int flags; 685#define PA_ANNOUNCE 1 686#define PA_REQ_FAST 2 /* only use inside fast */ 687 krb5_error_code (*validate)(kdc_request_t, const PA_DATA *pa); 688}; 689 690static const struct kdc_patypes pat[] = { 691#ifdef PKINIT 692 { 693 KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)", PA_ANNOUNCE, 694 pa_pkinit_validate 695 }, 696 { 697 KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", PA_ANNOUNCE, 698 pa_pkinit_validate 699 }, 700#else 701 { KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)", 0, NULL }, 702 { KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", 0, NULL }, 703#endif 704 { KRB5_PADATA_PA_PK_OCSP_RESPONSE , "OCSP", 0, NULL }, 705 { 706 KRB5_PADATA_ENC_TIMESTAMP , "ENC-TS", 707 PA_ANNOUNCE, 708 pa_enc_ts_validate 709 }, 710 { 711 KRB5_PADATA_ENCRYPTED_CHALLENGE , "ENC-CHAL", 712 PA_ANNOUNCE | PA_REQ_FAST, 713 pa_enc_chal_validate 714 }, 715 { KRB5_PADATA_REQ_ENC_PA_REP , "REQ-ENC-PA-REP", 0, NULL }, 716 { KRB5_PADATA_FX_FAST, "FX-FAST", PA_ANNOUNCE, NULL }, 717 { KRB5_PADATA_FX_ERROR, "FX-ERROR", 0, NULL }, 718 { KRB5_PADATA_FX_COOKIE, "FX-COOKIE", 0, NULL } 719}; 720 721static void 722log_patypes(krb5_context context, 723 krb5_kdc_configuration *config, 724 METHOD_DATA *padata) 725{ 726 struct rk_strpool *p = NULL; 727 char *str; 728 size_t n, m; 729 730 for (n = 0; n < padata->len; n++) { 731 for (m = 0; m < sizeof(pat) / sizeof(pat[0]); m++) { 732 if (padata->val[n].padata_type == pat[m].type) { 733 p = rk_strpoolprintf(p, "%s", pat[m].name); 734 break; 735 } 736 } 737 if (m == sizeof(pat) / sizeof(pat[0])) 738 p = rk_strpoolprintf(p, "%d", padata->val[n].padata_type); 739 if (p && n + 1 < padata->len) 740 p = rk_strpoolprintf(p, ", "); 741 if (p == NULL) { 742 kdc_log(context, config, 0, "out of memory"); 743 return; 744 } 745 } 746 if (p == NULL) 747 p = rk_strpoolprintf(p, "none"); 748 749 str = rk_strpoolcollect(p); 750 kdc_log(context, config, 0, "Client sent patypes: %s", str); 751 free(str); 752} 753 754/* 755 * 756 */ 757 758krb5_error_code 759_kdc_encode_reply(krb5_context context, 760 krb5_kdc_configuration *config, 761 krb5_crypto armor_crypto, uint32_t nonce, 762 KDC_REP *rep, EncTicketPart *et, EncKDCRepPart *ek, 763 krb5_enctype etype, 764 int skvno, const EncryptionKey *skey, 765 int ckvno, const EncryptionKey *reply_key, 766 int rk_is_subkey, 767 const char **e_text, 768 krb5_data *reply) 769{ 770 unsigned char *buf; 771 size_t buf_size; 772 size_t len = 0; 773 krb5_error_code ret; 774 krb5_crypto crypto; 775 776 ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret); 777 if(ret) { 778 const char *msg = krb5_get_error_message(context, ret); 779 kdc_log(context, config, 0, "Failed to encode ticket: %s", msg); 780 krb5_free_error_message(context, msg); 781 return ret; 782 } 783 if(buf_size != len) 784 krb5_abortx(context, "Internal error in ASN.1 encoder"); 785 786 ret = krb5_crypto_init(context, skey, etype, &crypto); 787 if (ret) { 788 const char *msg = krb5_get_error_message(context, ret); 789 kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg); 790 krb5_free_error_message(context, msg); 791 return ret; 792 } 793 794 ret = krb5_encrypt_EncryptedData(context, 795 crypto, 796 KRB5_KU_TICKET, 797 buf, 798 len, 799 skvno, 800 &rep->ticket.enc_part); 801 free(buf); 802 krb5_crypto_destroy(context, crypto); 803 if(ret) { 804 const char *msg = krb5_get_error_message(context, ret); 805 kdc_log(context, config, 0, "Failed to encrypt data: %s", msg); 806 krb5_free_error_message(context, msg); 807 return ret; 808 } 809 810 if (armor_crypto) { 811 krb5_data data; 812 krb5_keyblock *strengthen_key = NULL; 813 KrbFastFinished finished; 814 815 kdc_log(context, config, 0, "FAST armor protection"); 816 817 memset(&finished, 0, sizeof(finished)); 818 krb5_data_zero(&data); 819 820 finished.timestamp = kdc_time; 821 finished.usec = 0; 822 finished.crealm = et->crealm; 823 finished.cname = et->cname; 824 825 ASN1_MALLOC_ENCODE(Ticket, data.data, data.length, 826 &rep->ticket, &len, ret); 827 if (ret) 828 return ret; 829 if (data.length != len) 830 krb5_abortx(context, "internal asn.1 error"); 831 832 ret = krb5_create_checksum(context, armor_crypto, 833 KRB5_KU_FAST_FINISHED, 0, 834 data.data, data.length, 835 &finished.ticket_checksum); 836 krb5_data_free(&data); 837 if (ret) 838 return ret; 839 840 ret = _kdc_fast_mk_response(context, armor_crypto, 841 rep->padata, strengthen_key, &finished, 842 nonce, &data); 843 free_Checksum(&finished.ticket_checksum); 844 if (ret) 845 return ret; 846 847 if (rep->padata) { 848 free_METHOD_DATA(rep->padata); 849 } else { 850 rep->padata = calloc(1, sizeof(*(rep->padata))); 851 if (rep->padata == NULL) { 852 krb5_data_free(&data); 853 return ENOMEM; 854 } 855 } 856 857 ret = krb5_padata_add(context, rep->padata, 858 KRB5_PADATA_FX_FAST, 859 data.data, data.length); 860 if (ret) 861 return ret; 862 863 /* 864 * Hide client name of privacy reasons 865 */ 866 if (1 /* r->fast_options.hide_client_names */) { 867 rep->crealm[0] = '\0'; 868 free_PrincipalName(&rep->cname); 869 rep->cname.name_type = 0; 870 } 871 } 872 873 if(rep->msg_type == krb_as_rep && !config->encode_as_rep_as_tgs_rep) 874 ASN1_MALLOC_ENCODE(EncASRepPart, buf, buf_size, ek, &len, ret); 875 else 876 ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret); 877 if(ret) { 878 const char *msg = krb5_get_error_message(context, ret); 879 kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", msg); 880 krb5_free_error_message(context, msg); 881 return ret; 882 } 883 if(buf_size != len) { 884 free(buf); 885 kdc_log(context, config, 0, "Internal error in ASN.1 encoder"); 886 *e_text = "KDC internal error"; 887 return KRB5KRB_ERR_GENERIC; 888 } 889 ret = krb5_crypto_init(context, reply_key, 0, &crypto); 890 if (ret) { 891 const char *msg = krb5_get_error_message(context, ret); 892 free(buf); 893 kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg); 894 krb5_free_error_message(context, msg); 895 return ret; 896 } 897 if(rep->msg_type == krb_as_rep) { 898 krb5_encrypt_EncryptedData(context, 899 crypto, 900 KRB5_KU_AS_REP_ENC_PART, 901 buf, 902 len, 903 ckvno, 904 &rep->enc_part); 905 free(buf); 906 ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret); 907 } else { 908 krb5_encrypt_EncryptedData(context, 909 crypto, 910 rk_is_subkey ? KRB5_KU_TGS_REP_ENC_PART_SUB_KEY : KRB5_KU_TGS_REP_ENC_PART_SESSION, 911 buf, 912 len, 913 ckvno, 914 &rep->enc_part); 915 free(buf); 916 ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret); 917 } 918 krb5_crypto_destroy(context, crypto); 919 if(ret) { 920 const char *msg = krb5_get_error_message(context, ret); 921 kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", msg); 922 krb5_free_error_message(context, msg); 923 return ret; 924 } 925 if(buf_size != len) { 926 free(buf); 927 kdc_log(context, config, 0, "Internal error in ASN.1 encoder"); 928 *e_text = "KDC internal error"; 929 return KRB5KRB_ERR_GENERIC; 930 } 931 reply->data = buf; 932 reply->length = buf_size; 933 return 0; 934} 935 936/* 937 * Return 1 if the client have only older enctypes, this is for 938 * determining if the server should send ETYPE_INFO2 or not. 939 */ 940 941static int 942older_enctype(krb5_enctype enctype) 943{ 944 switch (enctype) { 945 case ETYPE_DES_CBC_CRC: 946 case ETYPE_DES_CBC_MD4: 947 case ETYPE_DES_CBC_MD5: 948 case ETYPE_DES3_CBC_SHA1: 949 case ETYPE_ARCFOUR_HMAC_MD5: 950 case ETYPE_ARCFOUR_HMAC_MD5_56: 951 /* 952 * The following three is "old" windows enctypes and is needed for 953 * windows 2000 hosts. 954 */ 955 case ETYPE_ARCFOUR_MD4: 956 case ETYPE_ARCFOUR_HMAC_OLD: 957 case ETYPE_ARCFOUR_HMAC_OLD_EXP: 958 return 1; 959 default: 960 return 0; 961 } 962} 963 964/* 965 * 966 */ 967 968static krb5_error_code 969make_etype_info_entry(krb5_context context, ETYPE_INFO_ENTRY *ent, Key *key) 970{ 971 ent->etype = key->key.keytype; 972 if(key->salt){ 973#if 0 974 ALLOC(ent->salttype); 975 976 if(key->salt->type == hdb_pw_salt) 977 *ent->salttype = 0; /* or 1? or NULL? */ 978 else if(key->salt->type == hdb_afs3_salt) 979 *ent->salttype = 2; 980 else { 981 kdc_log(context, config, 0, "unknown salt-type: %d", 982 key->salt->type); 983 return KRB5KRB_ERR_GENERIC; 984 } 985 /* according to `the specs', we can't send a salt if 986 we have AFS3 salted key, but that requires that you 987 *know* what cell you are using (e.g by assuming 988 that the cell is the same as the realm in lower 989 case) */ 990#elif 0 991 ALLOC(ent->salttype); 992 *ent->salttype = key->salt->type; 993#else 994 /* 995 * We shouldn't sent salttype since it is incompatible with the 996 * specification and it breaks windows clients. The afs 997 * salting problem is solved by using KRB5-PADATA-AFS3-SALT 998 * implemented in Heimdal 0.7 and later. 999 */ 1000 ent->salttype = NULL; 1001#endif 1002 krb5_copy_data(context, &key->salt->salt, 1003 &ent->salt); 1004 } else { 1005 /* we return no salt type at all, as that should indicate 1006 * the default salt type and make everybody happy. some 1007 * systems (like w2k) dislike being told the salt type 1008 * here. */ 1009 1010 ent->salttype = NULL; 1011 ent->salt = NULL; 1012 } 1013 return 0; 1014} 1015 1016static krb5_error_code 1017get_pa_etype_info(krb5_context context, 1018 krb5_kdc_configuration *config, 1019 METHOD_DATA *md, Key *ckey) 1020{ 1021 krb5_error_code ret = 0; 1022 ETYPE_INFO pa; 1023 unsigned char *buf; 1024 size_t len; 1025 1026 1027 pa.len = 1; 1028 pa.val = calloc(1, sizeof(pa.val[0])); 1029 if(pa.val == NULL) 1030 return ENOMEM; 1031 1032 ret = make_etype_info_entry(context, &pa.val[0], ckey); 1033 if (ret) { 1034 free_ETYPE_INFO(&pa); 1035 return ret; 1036 } 1037 1038 ASN1_MALLOC_ENCODE(ETYPE_INFO, buf, len, &pa, &len, ret); 1039 free_ETYPE_INFO(&pa); 1040 if(ret) 1041 return ret; 1042 ret = realloc_method_data(md); 1043 if(ret) { 1044 free(buf); 1045 return ret; 1046 } 1047 md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO; 1048 md->val[md->len - 1].padata_value.length = len; 1049 md->val[md->len - 1].padata_value.data = buf; 1050 return 0; 1051} 1052 1053/* 1054 * 1055 */ 1056 1057extern int _krb5_AES_string_to_default_iterator; 1058 1059static krb5_error_code 1060make_etype_info2_entry(ETYPE_INFO2_ENTRY *ent, Key *key) 1061{ 1062 ent->etype = key->key.keytype; 1063 if(key->salt) { 1064 ALLOC(ent->salt); 1065 if (ent->salt == NULL) 1066 return ENOMEM; 1067 *ent->salt = malloc(key->salt->salt.length + 1); 1068 if (*ent->salt == NULL) { 1069 free(ent->salt); 1070 ent->salt = NULL; 1071 return ENOMEM; 1072 } 1073 memcpy(*ent->salt, key->salt->salt.data, key->salt->salt.length); 1074 (*ent->salt)[key->salt->salt.length] = '\0'; 1075 } else 1076 ent->salt = NULL; 1077 1078 ent->s2kparams = NULL; 1079 1080 switch (key->key.keytype) { 1081 case ETYPE_AES128_CTS_HMAC_SHA1_96: 1082 case ETYPE_AES256_CTS_HMAC_SHA1_96: 1083 ALLOC(ent->s2kparams); 1084 if (ent->s2kparams == NULL) 1085 return ENOMEM; 1086 ent->s2kparams->length = 4; 1087 ent->s2kparams->data = malloc(ent->s2kparams->length); 1088 if (ent->s2kparams->data == NULL) { 1089 free(ent->s2kparams); 1090 ent->s2kparams = NULL; 1091 return ENOMEM; 1092 } 1093 _krb5_put_int(ent->s2kparams->data, 1094 _krb5_AES_string_to_default_iterator, 1095 ent->s2kparams->length); 1096 break; 1097 case ETYPE_DES_CBC_CRC: 1098 case ETYPE_DES_CBC_MD4: 1099 case ETYPE_DES_CBC_MD5: 1100 /* Check if this was a AFS3 salted key */ 1101 if(key->salt && key->salt->type == hdb_afs3_salt){ 1102 ALLOC(ent->s2kparams); 1103 if (ent->s2kparams == NULL) 1104 return ENOMEM; 1105 ent->s2kparams->length = 1; 1106 ent->s2kparams->data = malloc(ent->s2kparams->length); 1107 if (ent->s2kparams->data == NULL) { 1108 free(ent->s2kparams); 1109 ent->s2kparams = NULL; 1110 return ENOMEM; 1111 } 1112 _krb5_put_int(ent->s2kparams->data, 1113 1, 1114 ent->s2kparams->length); 1115 } 1116 break; 1117 default: 1118 break; 1119 } 1120 return 0; 1121} 1122 1123/* 1124 * Return an ETYPE-INFO2. Enctypes are storted the same way as in the 1125 * database (client supported enctypes first, then the unsupported 1126 * enctypes). 1127 */ 1128 1129static krb5_error_code 1130get_pa_etype_info2(krb5_context context, 1131 krb5_kdc_configuration *config, 1132 METHOD_DATA *md, Key *ckey) 1133{ 1134 krb5_error_code ret = 0; 1135 ETYPE_INFO2 pa; 1136 unsigned char *buf; 1137 size_t len; 1138 1139 pa.len = 1; 1140 pa.val = calloc(1, sizeof(pa.val[0])); 1141 if(pa.val == NULL) 1142 return ENOMEM; 1143 1144 ret = make_etype_info2_entry(&pa.val[0], ckey); 1145 if (ret) { 1146 free_ETYPE_INFO2(&pa); 1147 return ret; 1148 } 1149 1150 ASN1_MALLOC_ENCODE(ETYPE_INFO2, buf, len, &pa, &len, ret); 1151 free_ETYPE_INFO2(&pa); 1152 if(ret) 1153 return ret; 1154 ret = realloc_method_data(md); 1155 if(ret) { 1156 free(buf); 1157 return ret; 1158 } 1159 md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO2; 1160 md->val[md->len - 1].padata_value.length = len; 1161 md->val[md->len - 1].padata_value.data = buf; 1162 return 0; 1163} 1164 1165/* 1166 * 1167 */ 1168 1169static void 1170log_as_req(krb5_context context, 1171 krb5_kdc_configuration *config, 1172 krb5_enctype cetype, 1173 krb5_enctype setype, 1174 const KDC_REQ_BODY *b) 1175{ 1176 krb5_error_code ret; 1177 struct rk_strpool *p; 1178 char *str; 1179 size_t i; 1180 1181 p = rk_strpoolprintf(NULL, "%s", "Client supported enctypes: "); 1182 1183 for (i = 0; i < b->etype.len; i++) { 1184 ret = krb5_enctype_to_string(context, b->etype.val[i], &str); 1185 if (ret == 0) { 1186 p = rk_strpoolprintf(p, "%s", str); 1187 free(str); 1188 } else 1189 p = rk_strpoolprintf(p, "%d", b->etype.val[i]); 1190 if (p && i + 1 < b->etype.len) 1191 p = rk_strpoolprintf(p, ", "); 1192 if (p == NULL) { 1193 kdc_log(context, config, 0, "out of memory"); 1194 return; 1195 } 1196 } 1197 if (p == NULL) 1198 p = rk_strpoolprintf(p, "no encryption types"); 1199 1200 { 1201 char *cet; 1202 char *set; 1203 1204 ret = krb5_enctype_to_string(context, cetype, &cet); 1205 if(ret == 0) { 1206 ret = krb5_enctype_to_string(context, setype, &set); 1207 if (ret == 0) { 1208 p = rk_strpoolprintf(p, ", using %s/%s", cet, set); 1209 free(set); 1210 } 1211 free(cet); 1212 } 1213 if (ret != 0) 1214 p = rk_strpoolprintf(p, ", using enctypes %d/%d", 1215 cetype, setype); 1216 } 1217 1218 str = rk_strpoolcollect(p); 1219 kdc_log(context, config, 0, "%s", str); 1220 free(str); 1221 1222 { 1223 char fixedstr[128]; 1224 unparse_flags(KDCOptions2int(b->kdc_options), asn1_KDCOptions_units(), 1225 fixedstr, sizeof(fixedstr)); 1226 if(*fixedstr) 1227 kdc_log(context, config, 0, "Requested flags: %s", fixedstr); 1228 } 1229} 1230 1231/* 1232 * verify the flags on `client' and `server', returning 0 1233 * if they are OK and generating an error messages and returning 1234 * and error code otherwise. 1235 */ 1236 1237krb5_error_code 1238kdc_check_flags(krb5_context context, 1239 krb5_kdc_configuration *config, 1240 hdb_entry_ex *client_ex, const char *client_name, 1241 hdb_entry_ex *server_ex, const char *server_name, 1242 krb5_boolean is_as_req) 1243{ 1244 if(client_ex != NULL) { 1245 hdb_entry *client = &client_ex->entry; 1246 1247 /* check client */ 1248 if (client->flags.locked_out) { 1249 kdc_log(context, config, 0, 1250 "Client (%s) is locked out", client_name); 1251 return KRB5KDC_ERR_POLICY; 1252 } 1253 1254 if (client->flags.invalid) { 1255 kdc_log(context, config, 0, 1256 "Client (%s) has invalid bit set", client_name); 1257 return KRB5KDC_ERR_POLICY; 1258 } 1259 1260 if(!client->flags.client){ 1261 kdc_log(context, config, 0, 1262 "Principal may not act as client -- %s", client_name); 1263 return KRB5KDC_ERR_POLICY; 1264 } 1265 1266 if (client->valid_start && *client->valid_start > kdc_time) { 1267 char starttime_str[100]; 1268 krb5_format_time(context, *client->valid_start, 1269 starttime_str, sizeof(starttime_str), TRUE); 1270 kdc_log(context, config, 0, 1271 "Client not yet valid until %s -- %s", 1272 starttime_str, client_name); 1273 return KRB5KDC_ERR_CLIENT_NOTYET; 1274 } 1275 1276 if (client->valid_end && *client->valid_end < kdc_time) { 1277 char endtime_str[100]; 1278 krb5_format_time(context, *client->valid_end, 1279 endtime_str, sizeof(endtime_str), TRUE); 1280 kdc_log(context, config, 0, 1281 "Client expired at %s -- %s", 1282 endtime_str, client_name); 1283 return KRB5KDC_ERR_NAME_EXP; 1284 } 1285 1286 if (client->pw_end && *client->pw_end < kdc_time 1287 && (server_ex == NULL || !server_ex->entry.flags.change_pw)) { 1288 char pwend_str[100]; 1289 krb5_format_time(context, *client->pw_end, 1290 pwend_str, sizeof(pwend_str), TRUE); 1291 kdc_log(context, config, 0, 1292 "Client's key has expired at %s -- %s", 1293 pwend_str, client_name); 1294 return KRB5KDC_ERR_KEY_EXPIRED; 1295 } 1296 } 1297 1298 /* check server */ 1299 1300 if (server_ex != NULL) { 1301 hdb_entry *server = &server_ex->entry; 1302 1303 if (server->flags.locked_out) { 1304 kdc_log(context, config, 0, 1305 "Client server locked out -- %s", server_name); 1306 return KRB5KDC_ERR_POLICY; 1307 } 1308 if (server->flags.invalid) { 1309 kdc_log(context, config, 0, 1310 "Server has invalid flag set -- %s", server_name); 1311 return KRB5KDC_ERR_POLICY; 1312 } 1313 1314 if(!server->flags.server){ 1315 kdc_log(context, config, 0, 1316 "Principal may not act as server -- %s", server_name); 1317 return KRB5KDC_ERR_POLICY; 1318 } 1319 1320 if(!is_as_req && server->flags.initial) { 1321 kdc_log(context, config, 0, 1322 "AS-REQ is required for server -- %s", server_name); 1323 return KRB5KDC_ERR_POLICY; 1324 } 1325 1326 if (server->valid_start && *server->valid_start > kdc_time) { 1327 char starttime_str[100]; 1328 krb5_format_time(context, *server->valid_start, 1329 starttime_str, sizeof(starttime_str), TRUE); 1330 kdc_log(context, config, 0, 1331 "Server not yet valid until %s -- %s", 1332 starttime_str, server_name); 1333 return KRB5KDC_ERR_SERVICE_NOTYET; 1334 } 1335 1336 if (server->valid_end && *server->valid_end < kdc_time) { 1337 char endtime_str[100]; 1338 krb5_format_time(context, *server->valid_end, 1339 endtime_str, sizeof(endtime_str), TRUE); 1340 kdc_log(context, config, 0, 1341 "Server expired at %s -- %s", 1342 endtime_str, server_name); 1343 return KRB5KDC_ERR_SERVICE_EXP; 1344 } 1345 1346 if (server->pw_end && *server->pw_end < kdc_time) { 1347 char pwend_str[100]; 1348 krb5_format_time(context, *server->pw_end, 1349 pwend_str, sizeof(pwend_str), TRUE); 1350 kdc_log(context, config, 0, 1351 "Server's key has expired at -- %s", 1352 pwend_str, server_name); 1353 return KRB5KDC_ERR_KEY_EXPIRED; 1354 } 1355 } 1356 return 0; 1357} 1358 1359/* 1360 * Return TRUE if `from' is part of `addresses' taking into consideration 1361 * the configuration variables that tells us how strict we should be about 1362 * these checks 1363 */ 1364 1365krb5_boolean 1366_kdc_check_addresses(krb5_context context, 1367 krb5_kdc_configuration *config, 1368 HostAddresses *addresses, const struct sockaddr *from) 1369{ 1370 krb5_error_code ret; 1371 krb5_address addr; 1372 krb5_boolean result; 1373 krb5_boolean only_netbios = TRUE; 1374 size_t i; 1375 1376 if(config->check_ticket_addresses == 0) 1377 return TRUE; 1378 1379 if(addresses == NULL) 1380 return config->allow_null_ticket_addresses; 1381 1382 for (i = 0; i < addresses->len; ++i) { 1383 if (addresses->val[i].addr_type != KRB5_ADDRESS_NETBIOS) { 1384 only_netbios = FALSE; 1385 } 1386 } 1387 1388 /* Windows sends it's netbios name, which I can only assume is 1389 * used for the 'allowed workstations' check. This is painful, 1390 * but we still want to check IP addresses if they happen to be 1391 * present. 1392 */ 1393 1394 if(only_netbios) 1395 return config->allow_null_ticket_addresses; 1396 1397 ret = krb5_sockaddr2address (context, from, &addr); 1398 if(ret) 1399 return FALSE; 1400 1401 result = krb5_address_search(context, &addr, addresses); 1402 krb5_free_address (context, &addr); 1403 return result; 1404} 1405 1406/* 1407 * 1408 */ 1409 1410static krb5_boolean 1411send_pac_p(krb5_context context, KDC_REQ *req) 1412{ 1413 krb5_error_code ret; 1414 PA_PAC_REQUEST pacreq; 1415 const PA_DATA *pa; 1416 int i = 0; 1417 1418 pa = _kdc_find_padata(req, &i, KRB5_PADATA_PA_PAC_REQUEST); 1419 if (pa == NULL) 1420 return TRUE; 1421 1422 ret = decode_PA_PAC_REQUEST(pa->padata_value.data, 1423 pa->padata_value.length, 1424 &pacreq, 1425 NULL); 1426 if (ret) 1427 return TRUE; 1428 i = pacreq.include_pac; 1429 free_PA_PAC_REQUEST(&pacreq); 1430 if (i == 0) 1431 return FALSE; 1432 return TRUE; 1433} 1434 1435/* 1436 * 1437 */ 1438 1439static krb5_error_code 1440generate_pac(kdc_request_t r, Key *skey) 1441{ 1442 krb5_error_code ret; 1443 krb5_pac p = NULL; 1444 krb5_data data; 1445 1446 ret = _kdc_pac_generate(r->context, r->client, &p); 1447 if (ret) { 1448 _kdc_r_log(r, 0, "PAC generation failed for -- %s", 1449 r->client_name); 1450 return ret; 1451 } 1452 if (p == NULL) 1453 return 0; 1454 1455 ret = _krb5_pac_sign(r->context, p, r->et.authtime, 1456 r->client->entry.principal, 1457 &skey->key, /* Server key */ 1458 &skey->key, /* FIXME: should be krbtgt key */ 1459 &data); 1460 krb5_pac_free(r->context, p); 1461 if (ret) { 1462 _kdc_r_log(r, 0, "PAC signing failed for -- %s", 1463 r->client_name); 1464 return ret; 1465 } 1466 1467 ret = _kdc_tkt_add_if_relevant_ad(r->context, &r->et, 1468 KRB5_AUTHDATA_WIN2K_PAC, 1469 &data); 1470 krb5_data_free(&data); 1471 1472 return ret; 1473} 1474 1475/* 1476 * 1477 */ 1478 1479krb5_boolean 1480_kdc_is_anonymous(krb5_context context, krb5_principal principal) 1481{ 1482 if (principal->name.name_type != KRB5_NT_WELLKNOWN || 1483 principal->name.name_string.len != 2 || 1484 strcmp(principal->name.name_string.val[0], KRB5_WELLKNOWN_NAME) != 0 || 1485 strcmp(principal->name.name_string.val[1], KRB5_ANON_NAME) != 0) 1486 return 0; 1487 return 1; 1488} 1489 1490static int 1491require_preauth_p(kdc_request_t r) 1492{ 1493 return r->config->require_preauth 1494 || r->client->entry.flags.require_preauth 1495 || r->server->entry.flags.require_preauth; 1496} 1497 1498 1499/* 1500 * 1501 */ 1502 1503static krb5_error_code 1504add_enc_pa_rep(kdc_request_t r) 1505{ 1506 krb5_error_code ret; 1507 krb5_crypto crypto; 1508 Checksum checksum; 1509 krb5_data cdata; 1510 size_t len; 1511 1512 ret = krb5_crypto_init(r->context, &r->reply_key, 0, &crypto); 1513 if (ret) 1514 return ret; 1515 1516 ret = krb5_create_checksum(r->context, crypto, 1517 KRB5_KU_AS_REQ, 0, 1518 r->request.data, r->request.length, 1519 &checksum); 1520 krb5_crypto_destroy(r->context, crypto); 1521 if (ret) 1522 return ret; 1523 1524 ASN1_MALLOC_ENCODE(Checksum, cdata.data, cdata.length, 1525 &checksum, &len, ret); 1526 free_Checksum(&checksum); 1527 if (ret) 1528 return ret; 1529 heim_assert(cdata.length == len, "ASN.1 internal error"); 1530 1531 if (r->ek.encrypted_pa_data == NULL) { 1532 ALLOC(r->ek.encrypted_pa_data); 1533 if (r->ek.encrypted_pa_data == NULL) 1534 return ENOMEM; 1535 } 1536 ret = krb5_padata_add(r->context, r->ek.encrypted_pa_data, 1537 KRB5_PADATA_REQ_ENC_PA_REP, cdata.data, cdata.length); 1538 if (ret) 1539 return ret; 1540 1541 return krb5_padata_add(r->context, r->ek.encrypted_pa_data, 1542 KRB5_PADATA_FX_FAST, NULL, 0); 1543} 1544 1545/* 1546 * 1547 */ 1548 1549krb5_error_code 1550_kdc_as_rep(kdc_request_t r, 1551 krb5_data *reply, 1552 const char *from, 1553 struct sockaddr *from_addr, 1554 size_t max_reply_size) 1555{ 1556 krb5_context context = r->context; 1557 krb5_kdc_configuration *config = r->config; 1558 KDC_REQ *req = &r->req; 1559 KDC_REQ_BODY *b = NULL; 1560 AS_REP rep; 1561 KDCOptions f; 1562 krb5_enctype setype; 1563 krb5_error_code ret = 0; 1564 Key *ckey, *skey; 1565 int found_pa = 0; 1566 int i, flags = HDB_F_FOR_AS_REQ; 1567 METHOD_DATA error_method; 1568#ifdef PKINIT 1569 InitiatorNameAssertion pku2u; 1570 memset(&pku2u, 0, sizeof(pku2u)); 1571#endif 1572 1573 1574 memset(&rep, 0, sizeof(rep)); 1575 error_method.len = 0; 1576 error_method.val = NULL; 1577 1578 /* 1579 * Look for FAST armor and unwrap 1580 */ 1581 ret = _kdc_fast_unwrap_request(r); 1582 if (ret) { 1583 _kdc_r_log(r, 0, "FAST unwrap request from %s failed: %d", from, ret); 1584 goto out; 1585 } 1586 1587 b = &req->req_body; 1588 f = b->kdc_options; 1589 1590 if (f.canonicalize) 1591 flags |= HDB_F_CANON; 1592 1593 if(b->sname == NULL){ 1594 ret = KRB5KRB_ERR_GENERIC; 1595 _kdc_set_e_text(r, "No server in request"); 1596 } else{ 1597 ret = _krb5_principalname2krb5_principal (context, 1598 &r->server_princ, 1599 *(b->sname), 1600 b->realm); 1601 if (ret == 0) 1602 ret = krb5_unparse_name(context, r->server_princ, &r->server_name); 1603 } 1604 if (ret) { 1605 kdc_log(context, config, 0, 1606 "AS-REQ malformed server name from %s", from); 1607 goto out; 1608 } 1609 1610 /* 1611 * Now find the client's name, first lets check if its a PKU2U 1612 * name, that means 1613 */ 1614 1615 if(b->cname == NULL){ 1616 ret = KRB5KRB_ERR_GENERIC; 1617 _kdc_set_e_text(r, "No client in request"); 1618 goto out; 1619 } 1620 1621#ifdef PKINIT 1622 if (strcmp(b->realm, KRB5_PKU2U_REALM_NAME) == 0) { 1623 const PA_DATA *papk; 1624 size_t len, size; 1625 void *buf; 1626 char *str; 1627 1628 i = 0; 1629 papk = _kdc_find_padata(req, &i, KRB5_PADATA_PKU2U_NAME); 1630 if (papk) { 1631 ret = decode_InitiatorNameAssertion(papk->padata_value.data, 1632 papk->padata_value.length, 1633 &pku2u, &len); 1634 if (ret) { 1635 kdc_log(context, config, 0, 1636 "AS-REQ InitiatorNameAssertion malformed %s", from); 1637 goto out; 1638 } 1639 if (pku2u.initiatorName) { 1640 if (pku2u.initiatorName->element != choice_InitiatorName_nameNotInCert) { 1641 kdc_log(context, config, 0, "PKU2U not nameNotInCert"); 1642 ret = KRB5KRB_ERR_GENERIC; 1643 goto out; 1644 } 1645 ASN1_MALLOC_ENCODE(GeneralName, buf, len, 1646 &pku2u.initiatorName->u.nameNotInCert, 1647 &size, ret); 1648 if (ret) { 1649 ret = KRB5KRB_ERR_GENERIC; 1650 goto out; 1651 } 1652 if (size != len) 1653 krb5_abortx(context, "internal asn.1 error"); 1654 1655 ret = base64_encode(buf, (int)len, &str); 1656 free(buf); 1657 if (ret < 0) { 1658 ret = KRB5KRB_ERR_GENERIC; 1659 goto out; 1660 } 1661 1662 ret = krb5_make_principal(context, &r->client_princ, 1663 KRB5_PKU2U_REALM_NAME, str, NULL); 1664 free(str); 1665 if (ret) { 1666 ret = KRB5KRB_ERR_GENERIC; 1667 goto out; 1668 } 1669 krb5_principal_set_type(context, r->client_princ, 1670 KRB5_NT_X509_GENERAL_NAME); 1671 } 1672 } 1673 } 1674#endif 1675 /* 1676 * if not found in pku2u name, lets got for the traditional way 1677 */ 1678 if (r->client_princ == NULL) { 1679 ret = _krb5_principalname2krb5_principal (context, 1680 &r->client_princ, 1681 *(b->cname), 1682 b->realm); 1683 if (ret) { 1684 kdc_log(context, config, 0, 1685 "AS-REQ malformed client name from %s", from); 1686 goto out; 1687 } 1688 } 1689 1690 /* 1691 * If its a LKDC referrals 1692 */ 1693 if (f.canonicalize && strncmp(b->realm, KRB5_LKDC_REALM_NAME, strlen(KRB5_LKDC_REALM_NAME) - 1) == 0) { 1694 kdc_log(context, config, 0, 1695 "Got a canonicalize request for a LKDC realm from %s", from); 1696 1697 if (config->lkdc_realm) { 1698 ret = KRB5_KDC_ERR_WRONG_REALM; 1699 krb5_principal_set_realm(context, r->client_princ, config->lkdc_realm); 1700 _kdc_set_e_text(r, "LKDC referral to the real LKDC realm name"); 1701 } else { 1702 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; 1703 _kdc_set_e_text(r, "Asked for LKDC, but there is none"); 1704 } 1705 goto out; 1706 } 1707 1708 ret = krb5_unparse_name(context, r->client_princ, &r->client_name); 1709 if (ret) { 1710 kdc_log(context, config, 0, 1711 "AS-REQ client not printable %s", from); 1712 goto out; 1713 } 1714 1715 kdc_log(context, config, 0, "AS-REQ %s from %s for %s", 1716 r->client_name, from, r->server_name); 1717 1718 /* 1719 * 1720 */ 1721 1722 if (_kdc_is_anonymous(context, r->client_princ)) { 1723 if (!b->kdc_options.request_anonymous) { 1724 kdc_log(context, config, 0, "Anonymous ticket w/o anonymous flag"); 1725 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; 1726 goto out; 1727 } 1728 } else if (b->kdc_options.request_anonymous) { 1729 kdc_log(context, config, 0, 1730 "Request for a anonymous ticket with non " 1731 "anonymous client name: %s", r->client_name); 1732 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; 1733 goto out; 1734 } 1735 1736 /* 1737 * 1738 */ 1739 1740 ret = _kdc_db_fetch(context, config, r->client_princ, 1741 HDB_F_GET_CLIENT | flags, NULL, 1742 &r->clientdb, &r->client); 1743 if(ret == HDB_ERR_NOT_FOUND_HERE) { 1744 kdc_log(context, config, 5, "client %s does not have secrets at this KDC, need to proxy", 1745 r->client_name); 1746 goto out; 1747 } else if(ret){ 1748 const char *msg = krb5_get_error_message(context, ret); 1749 kdc_log(context, config, 0, "UNKNOWN -- %s: %s", r->client_name, msg); 1750 krb5_free_error_message(context, msg); 1751 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; 1752 goto out; 1753 } 1754 1755 1756 if (krb5_principal_compare(context, r->client_princ, r->client->entry.principal) == FALSE) { 1757 char *str; 1758 ret = krb5_unparse_name(context, r->client->entry.principal, &str); 1759 if (ret) { 1760 kdc_log(context, config, 0, 1761 "AS-REQ client not printable %s", from); 1762 goto out; 1763 } 1764 kdc_log(context, config, 0, 1765 "AS-REQ remapping client from %s to %s", r->client_name, str); 1766 free(r->client_name); 1767 r->client_name = str; 1768 } 1769 1770 kdc_log(context, config, 0, "AS-REQ %s from %s for %s", 1771 r->client_name, from, r->server_name); 1772 1773 ret = _kdc_db_fetch(context, config, r->server_princ, 1774 HDB_F_GET_SERVER|HDB_F_GET_KRBTGT | flags, 1775 NULL, NULL, &r->server); 1776 if(ret == HDB_ERR_NOT_FOUND_HERE) { 1777 kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy", 1778 r->server_name); 1779 goto out; 1780 } else if(ret){ 1781 const char *msg = krb5_get_error_message(context, ret); 1782 kdc_log(context, config, 0, "UNKNOWN -- %s: %s", r->server_name, msg); 1783 krb5_free_error_message(context, msg); 1784 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; 1785 goto out; 1786 } 1787 1788 /* 1789 * Select a session enctype from the list of the crypto system 1790 * supported enctypes that is supported by the client and is one of 1791 * the enctype of the enctype of the service (likely krbtgt). 1792 * 1793 * The latter is used as a hint of what enctypes all KDC support, 1794 * to make sure a newer version of KDC won't generate a session 1795 * enctype that an older version of a KDC in the same realm can't 1796 * decrypt. 1797 */ 1798 1799 ret = _kdc_find_etype(context, config->as_use_strongest_session_key, FALSE, 1800 r->client, b->etype.val, b->etype.len, &r->sessionetype, 1801 NULL); 1802 if (ret) { 1803 kdc_log(context, config, 0, 1804 "Client (%s) from %s has no common enctypes with KDC " 1805 "to use for the session key", 1806 r->client_name, from); 1807 goto out; 1808 } 1809 1810 /* 1811 * Pre-auth processing 1812 */ 1813 1814 if(req->padata){ 1815 const PA_DATA *pa; 1816 unsigned int n; 1817 1818 log_patypes(context, config, req->padata); 1819 1820 /* Check if preauth matching */ 1821 1822 for (n = 0; !found_pa && n < sizeof(pat) / sizeof(pat[0]); n++) { 1823 if (pat[n].validate == NULL) 1824 continue; 1825 if (r->armor_crypto == NULL && (pat[n].flags & PA_REQ_FAST)) 1826 continue; 1827 1828 kdc_log(context, config, 5, 1829 "Looking for %s pa-data -- %s", pat[n].name, r->client_name); 1830 i = 0; 1831 pa = _kdc_find_padata(req, &i, pat[n].type); 1832 if (pa) { 1833 ret = pat[n].validate(r, pa); 1834 if (ret == 0) { 1835 kdc_log(context, config, 0, 1836 "%s pre-authentication succeeded -- %s", 1837 pat[n].name, r->client_name); 1838 found_pa = 1; 1839 r->et.flags.pre_authent = 1; 1840 } 1841 } 1842 } 1843 } 1844 1845 if (found_pa == 0 && (require_preauth_p(r) || b->kdc_options.request_anonymous)) { 1846 size_t n; 1847 1848 for (n = 0; n < sizeof(pat) / sizeof(pat[0]); n++) { 1849 if ((pat[n].flags & PA_ANNOUNCE) == 0) 1850 continue; 1851 ret = krb5_padata_add(context, &error_method, 1852 pat[n].type, NULL, 0); 1853 if (ret) 1854 goto out; 1855 } 1856 1857 /* 1858 * If there is a client key, send ETYPE_INFO{,2} 1859 */ 1860 ret = _kdc_find_etype(context, 1861 config->preauth_use_strongest_session_key, TRUE, 1862 r->client, b->etype.val, b->etype.len, NULL, &ckey); 1863 if (ret == 0) { 1864 1865 /* 1866 * RFC4120 requires: 1867 * - If the client only knows about old enctypes, then send 1868 * both info replies (we send 'info' first in the list). 1869 * - If the client is 'modern', because it knows about 'new' 1870 * enctype types, then only send the 'info2' reply. 1871 * 1872 * Before we send the full list of etype-info data, we pick 1873 * the client key we would have used anyway below, just pick 1874 * that instead. 1875 */ 1876 1877 if (older_enctype(ckey->key.keytype)) { 1878 ret = get_pa_etype_info(context, config, 1879 &error_method, ckey); 1880 if (ret) 1881 goto out; 1882 } 1883 ret = get_pa_etype_info2(context, config, 1884 &error_method, ckey); 1885 if (ret) 1886 goto out; 1887 } 1888 1889 ret = KRB5KDC_ERR_PREAUTH_REQUIRED; 1890 _kdc_set_e_text(r, "Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ"); 1891 goto out; 1892 } 1893 1894 /* 1895 * Verify flags after the user been required to prove its identity 1896 * with in a preauth mech. 1897 */ 1898 1899 ret = _kdc_check_access(context, config, r->client, r->client_name, 1900 r->server, r->server_name, 1901 req, &error_method); 1902 if(ret) 1903 goto out; 1904 1905 /* 1906 * Select the best encryption type for the KDC with out regard to 1907 * the client since the client never needs to read that data. 1908 */ 1909 1910 ret = _kdc_get_preferred_key(context, config, 1911 r->server, r->server_name, 1912 &setype, &skey); 1913 if(ret) 1914 goto out; 1915 1916 if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey 1917 || (f.request_anonymous && !config->allow_anonymous)) { 1918 ret = KRB5KDC_ERR_BADOPTION; 1919 _kdc_set_e_text(r, "Bad KDC options"); 1920 goto out; 1921 } 1922 1923 /* 1924 * Let backend know that authentication have passed and failure 1925 * counts can be reset. 1926 */ 1927 1928 if (r->clientdb->hdb_auth_status) 1929 r->clientdb->hdb_auth_status(context, r->clientdb, r->client, 1930 HDB_AUTH_SUCCESS); 1931 1932 /* 1933 * Build reply 1934 */ 1935 1936 rep.pvno = 5; 1937 rep.msg_type = krb_as_rep; 1938 1939 ret = copy_Realm(&r->client->entry.principal->realm, &rep.crealm); 1940 if (ret) 1941 goto out; 1942 ret = _krb5_principal2principalname(&rep.cname, r->client->entry.principal); 1943 if (ret) 1944 goto out; 1945 1946 rep.ticket.tkt_vno = 5; 1947 copy_Realm(&r->server->entry.principal->realm, &rep.ticket.realm); 1948 _krb5_principal2principalname(&rep.ticket.sname, 1949 r->server->entry.principal); 1950 /* java 1.6 expects the name to be the same type, lets allow that 1951 * uncomplicated name-types. */ 1952#define CNT(sp,t) (((sp)->sname->name_type) == KRB5_NT_##t) 1953 if (CNT(b, UNKNOWN) || CNT(b, PRINCIPAL) || CNT(b, SRV_INST) || CNT(b, SRV_HST) || CNT(b, SRV_XHST)) 1954 rep.ticket.sname.name_type = b->sname->name_type; 1955#undef CNT 1956 1957 r->et.flags.initial = 1; 1958 if(r->client->entry.flags.forwardable && r->server->entry.flags.forwardable) 1959 r->et.flags.forwardable = f.forwardable; 1960 else if (f.forwardable) { 1961 _kdc_set_e_text(r, "Ticket may not be forwardable"); 1962 ret = KRB5KDC_ERR_POLICY; 1963 goto out; 1964 } 1965 if(r->client->entry.flags.proxiable && r->server->entry.flags.proxiable) 1966 r->et.flags.proxiable = f.proxiable; 1967 else if (f.proxiable) { 1968 _kdc_set_e_text(r, "Ticket may not be proxiable"); 1969 ret = KRB5KDC_ERR_POLICY; 1970 goto out; 1971 } 1972 if(r->client->entry.flags.postdate && r->server->entry.flags.postdate) 1973 r->et.flags.may_postdate = f.allow_postdate; 1974 else if (f.allow_postdate){ 1975 _kdc_set_e_text(r, "Ticket may not be postdate"); 1976 ret = KRB5KDC_ERR_POLICY; 1977 goto out; 1978 } 1979 1980 /* check for valid set of addresses */ 1981 if(!_kdc_check_addresses(context, config, b->addresses, from_addr)) { 1982 _kdc_set_e_text(r, "Bad address list in requested"); 1983 ret = KRB5KRB_AP_ERR_BADADDR; 1984 goto out; 1985 } 1986 1987 ret = copy_PrincipalName(&rep.cname, &r->et.cname); 1988 if (ret) 1989 goto out; 1990 ret = copy_Realm(&rep.crealm, &r->et.crealm); 1991 if (ret) 1992 goto out; 1993 1994 { 1995 time_t start; 1996 time_t t; 1997 1998 start = r->et.authtime = kdc_time; 1999 2000 if(f.postdated && req->req_body.from){ 2001 ALLOC(r->et.starttime); 2002 start = *r->et.starttime = *req->req_body.from; 2003 r->et.flags.invalid = 1; 2004 r->et.flags.postdated = 1; /* XXX ??? */ 2005 } 2006 _kdc_fix_time(&b->till); 2007 t = *b->till; 2008 2009 /* be careful not overflowing */ 2010 2011 if(r->client->entry.max_life) 2012 t = start + min(t - start, *r->client->entry.max_life); 2013 if(r->server->entry.max_life) 2014 t = start + min(t - start, *r->server->entry.max_life); 2015#if 0 2016 t = min(t, start + realm->max_life); 2017#endif 2018 r->et.endtime = t; 2019 if(f.renewable_ok && r->et.endtime < *b->till){ 2020 f.renewable = 1; 2021 if(b->rtime == NULL){ 2022 ALLOC(b->rtime); 2023 *b->rtime = 0; 2024 } 2025 if(*b->rtime < *b->till) 2026 *b->rtime = *b->till; 2027 } 2028 if(f.renewable && b->rtime){ 2029 t = *b->rtime; 2030 if(t == 0) 2031 t = MAX_TIME; 2032 if(r->client->entry.max_renew) 2033 t = start + min(t - start, *r->client->entry.max_renew); 2034 if(r->server->entry.max_renew) 2035 t = start + min(t - start, *r->server->entry.max_renew); 2036#if 0 2037 t = min(t, start + realm->max_renew); 2038#endif 2039 ALLOC(r->et.renew_till); 2040 *r->et.renew_till = t; 2041 r->et.flags.renewable = 1; 2042 } 2043 } 2044 2045 if (f.request_anonymous) 2046 r->et.flags.anonymous = 1; 2047 2048 if(b->addresses){ 2049 ALLOC(r->et.caddr); 2050 copy_HostAddresses(b->addresses, r->et.caddr); 2051 } 2052 2053 r->et.transited.tr_type = DOMAIN_X500_COMPRESS; 2054 krb5_data_zero(&r->et.transited.contents); 2055 2056 /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded 2057 * as 0 and as 0x80 (meaning indefinite length) apart, and is thus 2058 * incapable of correctly decoding SEQUENCE OF's of zero length. 2059 * 2060 * To fix this, always send at least one no-op last_req 2061 * 2062 * If there's a pw_end or valid_end we will use that, 2063 * otherwise just a dummy lr. 2064 */ 2065 r->ek.last_req.val = malloc(2 * sizeof(*r->ek.last_req.val)); 2066 if (r->ek.last_req.val == NULL) { 2067 ret = ENOMEM; 2068 goto out; 2069 } 2070 r->ek.last_req.len = 0; 2071 if (r->client->entry.pw_end 2072 && (config->kdc_warn_pwexpire == 0 2073 || kdc_time + config->kdc_warn_pwexpire >= *r->client->entry.pw_end)) { 2074 r->ek.last_req.val[r->ek.last_req.len].lr_type = LR_PW_EXPTIME; 2075 r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->entry.pw_end; 2076 ++r->ek.last_req.len; 2077 } 2078 if (r->client->entry.valid_end) { 2079 r->ek.last_req.val[r->ek.last_req.len].lr_type = LR_ACCT_EXPTIME; 2080 r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->entry.valid_end; 2081 ++r->ek.last_req.len; 2082 } 2083 if (r->ek.last_req.len == 0) { 2084 r->ek.last_req.val[r->ek.last_req.len].lr_type = LR_NONE; 2085 r->ek.last_req.val[r->ek.last_req.len].lr_value = 0; 2086 ++r->ek.last_req.len; 2087 } 2088 r->ek.nonce = b->nonce; 2089 if (r->client->entry.valid_end || r->client->entry.pw_end) { 2090 ALLOC(r->ek.key_expiration); 2091 if (r->client->entry.valid_end) { 2092 if (r->client->entry.pw_end) 2093 *r->ek.key_expiration = min(*r->client->entry.valid_end, 2094 *r->client->entry.pw_end); 2095 else 2096 *r->ek.key_expiration = *r->client->entry.valid_end; 2097 } else 2098 *r->ek.key_expiration = *r->client->entry.pw_end; 2099 } else 2100 r->ek.key_expiration = NULL; 2101 r->ek.flags = r->et.flags; 2102 r->ek.authtime = r->et.authtime; 2103 if (r->et.starttime) { 2104 ALLOC(r->ek.starttime); 2105 *r->ek.starttime = *r->et.starttime; 2106 } 2107 r->ek.endtime = r->et.endtime; 2108 if (r->et.renew_till) { 2109 ALLOC(r->ek.renew_till); 2110 *r->ek.renew_till = *r->et.renew_till; 2111 } 2112 copy_Realm(&rep.ticket.realm, &r->ek.srealm); 2113 copy_PrincipalName(&rep.ticket.sname, &r->ek.sname); 2114 if(r->et.caddr){ 2115 ALLOC(r->ek.caddr); 2116 copy_HostAddresses(r->et.caddr, r->ek.caddr); 2117 } 2118 2119 /* 2120 * Check and session and reply keys 2121 */ 2122 2123 if (r->session_key.keytype == ETYPE_NULL) { 2124 ret = krb5_generate_random_keyblock(context, r->sessionetype, &r->session_key); 2125 if (ret) 2126 goto out; 2127 } 2128 2129 if (r->reply_key.keytype == ETYPE_NULL) { 2130 _kdc_set_e_text(r, "Client have no reply key"); 2131 ret = KRB5KDC_ERR_CLIENT_NOTYET; 2132 goto out; 2133 } 2134 2135 ret = copy_EncryptionKey(&r->session_key, &r->et.key); 2136 if (ret) 2137 goto out; 2138 2139 ret = copy_EncryptionKey(&r->session_key, &r->ek.key); 2140 if (ret) 2141 goto out; 2142 2143 /* 2144 * Add signing of alias referral 2145 */ 2146 2147 if (f.canonicalize) { 2148 PA_ClientCanonicalized canon; 2149 krb5_data data; 2150 PA_DATA pa; 2151 krb5_crypto cryptox; 2152 size_t len = 0; 2153 2154 memset(&canon, 0, sizeof(canon)); 2155 2156 canon.names.requested_name = *b->cname; 2157 canon.names.mapped_name = r->client->entry.principal->name; 2158 2159 ASN1_MALLOC_ENCODE(PA_ClientCanonicalizedNames, data.data, data.length, 2160 &canon.names, &len, ret); 2161 if (ret) 2162 goto out; 2163 if (data.length != len) 2164 krb5_abortx(context, "internal asn.1 error"); 2165 2166 /* sign using "returned session key" */ 2167 ret = krb5_crypto_init(context, &r->et.key, 0, &cryptox); 2168 if (ret) { 2169 free(data.data); 2170 goto out; 2171 } 2172 2173 ret = krb5_create_checksum(context, cryptox, 2174 KRB5_KU_CANONICALIZED_NAMES, 0, 2175 data.data, data.length, 2176 &canon.canon_checksum); 2177 free(data.data); 2178 krb5_crypto_destroy(context, cryptox); 2179 if (ret) 2180 goto out; 2181 2182 ASN1_MALLOC_ENCODE(PA_ClientCanonicalized, data.data, data.length, 2183 &canon, &len, ret); 2184 free_Checksum(&canon.canon_checksum); 2185 if (ret) 2186 goto out; 2187 if (data.length != len) 2188 krb5_abortx(context, "internal asn.1 error"); 2189 2190 pa.padata_type = KRB5_PADATA_CLIENT_CANONICALIZED; 2191 pa.padata_value = data; 2192 ret = add_METHOD_DATA(&r->outpadata, &pa); 2193 free(data.data); 2194 if (ret) 2195 goto out; 2196 } 2197 2198 if (r->outpadata.len) { 2199 2200 ALLOC(rep.padata); 2201 if (rep.padata == NULL) { 2202 ret = ENOMEM; 2203 goto out; 2204 } 2205 ret = copy_METHOD_DATA(&r->outpadata, rep.padata); 2206 if (ret) 2207 goto out; 2208 } 2209 2210 /* Add the PAC */ 2211 if (send_pac_p(context, req)) { 2212 generate_pac(r, skey); 2213 } 2214 2215 _kdc_log_timestamp(context, config, "AS-REQ", r->et.authtime, r->et.starttime, 2216 r->et.endtime, r->et.renew_till); 2217 2218 /* do this as the last thing since this signs the EncTicketPart */ 2219 ret = _kdc_add_KRB5SignedPath(context, 2220 config, 2221 r->server, 2222 setype, 2223 r->client->entry.principal, 2224 NULL, 2225 NULL, 2226 &r->et); 2227 if (ret) 2228 goto out; 2229 2230 log_as_req(context, config, r->reply_key.keytype, setype, b); 2231 2232 /* 2233 * We always say we support FAST/enc-pa-rep 2234 */ 2235 2236 r->et.flags.enc_pa_rep = r->ek.flags.enc_pa_rep = 1; 2237 2238 /* 2239 * Add REQ_ENC_PA_REP if client supports it 2240 */ 2241 2242 { 2243 const PA_DATA *pa; 2244 i = 0; 2245 2246 pa = _kdc_find_padata(req, &i, KRB5_PADATA_REQ_ENC_PA_REP); 2247 if (pa) { 2248 ret = add_enc_pa_rep(r); 2249 if (ret) { 2250 const char *msg = krb5_get_error_message(r->context, ret); 2251 _kdc_r_log(r, 0, "add_enc_pa_rep failed: %s: %d", msg, ret); 2252 krb5_free_error_message(r->context, msg); 2253 goto out; 2254 } 2255 } 2256 } 2257 2258 /* 2259 * 2260 */ 2261 2262 ret = _kdc_encode_reply(context, config, 2263 r->armor_crypto, req->req_body.nonce, 2264 &rep, &r->et, &r->ek, setype, r->server->entry.kvno, 2265 &skey->key, r->client->entry.kvno, 2266 &r->reply_key, 0, &r->e_text, reply); 2267 if (ret) 2268 goto out; 2269 2270 /* 2271 * Check if message too large 2272 */ 2273 if (max_reply_size && reply->length > config->max_datagram_reply_length) { 2274 krb5_data_free(reply); 2275 ret = KRB5KRB_ERR_RESPONSE_TOO_BIG; 2276 _kdc_set_e_text(r, "Reply packet too large"); 2277 } 2278 2279out: 2280 free_AS_REP(&rep); 2281 2282 /* 2283 * In case of a non proxy error, build an error message. 2284 */ 2285 if(ret != 0 && ret != HDB_ERR_NOT_FOUND_HERE) { 2286 ret = _kdc_fast_mk_error(context, r, 2287 &error_method, 2288 r->armor_crypto, 2289 &req->req_body, 2290 ret, r->e_text, 2291 r->client_princ, r->server_princ, 2292 NULL, NULL, 2293 reply); 2294 if (ret) 2295 goto out2; 2296 } 2297 2298out2: 2299#ifdef PKINIT 2300 free_InitiatorNameAssertion(&pku2u); 2301#endif 2302 free_EncTicketPart(&r->et); 2303 free_EncKDCRepPart(&r->ek); 2304 free_KDCFastState(&r->fast); 2305 2306 if (error_method.len) 2307 free_METHOD_DATA(&error_method); 2308 if (r->outpadata.len) 2309 free_METHOD_DATA(&r->outpadata); 2310 if (r->client_princ) { 2311 krb5_free_principal(context, r->client_princ); 2312 r->client_princ = NULL; 2313 } 2314 if (r->client_name) { 2315 free(r->client_name); 2316 r->client_name = NULL; 2317 } 2318 if (r->server_princ){ 2319 krb5_free_principal(context, r->server_princ); 2320 r->server_princ = NULL; 2321 } 2322 if (r->server_name) { 2323 free(r->server_name); 2324 r->server_name = NULL; 2325 } 2326 if (r->client) 2327 _kdc_free_ent(context, r->client); 2328 if (r->server) 2329 _kdc_free_ent(context, r->server); 2330 if (r->armor_crypto) { 2331 krb5_crypto_destroy(r->context, r->armor_crypto); 2332 r->armor_crypto = NULL; 2333 } 2334 krb5_free_keyblock_contents(r->context, &r->reply_key); 2335 krb5_free_keyblock_contents(r->context, &r->session_key); 2336 2337 return ret; 2338} 2339 2340/* 2341 * Add the AuthorizationData `data´ of `type´ to the last element in 2342 * the sequence of authorization_data in `tkt´ wrapped in an IF_RELEVANT 2343 */ 2344 2345krb5_error_code 2346_kdc_tkt_add_if_relevant_ad(krb5_context context, 2347 EncTicketPart *tkt, 2348 int type, 2349 const krb5_data *data) 2350{ 2351 krb5_error_code ret; 2352 size_t size = 0; 2353 2354 if (tkt->authorization_data == NULL) { 2355 tkt->authorization_data = calloc(1, sizeof(*tkt->authorization_data)); 2356 if (tkt->authorization_data == NULL) { 2357 krb5_set_error_message(context, ENOMEM, "out of memory"); 2358 return ENOMEM; 2359 } 2360 } 2361 2362 /* add the entry to the last element */ 2363 { 2364 AuthorizationData ad = { 0, NULL }; 2365 AuthorizationDataElement ade; 2366 2367 ade.ad_type = type; 2368 ade.ad_data = *data; 2369 2370 ret = add_AuthorizationData(&ad, &ade); 2371 if (ret) { 2372 krb5_set_error_message(context, ret, "add AuthorizationData failed"); 2373 return ret; 2374 } 2375 2376 ade.ad_type = KRB5_AUTHDATA_IF_RELEVANT; 2377 2378 ASN1_MALLOC_ENCODE(AuthorizationData, 2379 ade.ad_data.data, ade.ad_data.length, 2380 &ad, &size, ret); 2381 free_AuthorizationData(&ad); 2382 if (ret) { 2383 krb5_set_error_message(context, ret, "ASN.1 encode of " 2384 "AuthorizationData failed"); 2385 return ret; 2386 } 2387 if (ade.ad_data.length != size) 2388 krb5_abortx(context, "internal asn.1 encoder error"); 2389 2390 ret = add_AuthorizationData(tkt->authorization_data, &ade); 2391 der_free_octet_string(&ade.ad_data); 2392 if (ret) { 2393 krb5_set_error_message(context, ret, "add AuthorizationData failed"); 2394 return ret; 2395 } 2396 } 2397 2398 return 0; 2399} 2400