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