1 /* $NetBSD: keys.c,v 1.4 2017/01/28 21:31:48 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1997 - 2011 Kungliga Tekniska Högskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include "hdb_locl.h" 37 38 struct hx509_certs_data; 39 struct krb5_pk_identity; 40 struct krb5_pk_cert; 41 struct ContentInfo; 42 struct AlgorithmIdentifier; 43 struct _krb5_krb_auth_data; 44 typedef struct krb5_pk_init_ctx_data *krb5_pk_init_ctx; 45 struct krb5_dh_moduli; 46 struct _krb5_key_data; 47 struct _krb5_encryption_type; 48 struct _krb5_key_type; 49 #include <krb5/pkinit_asn1.h> 50 #include <krb5/krb5-private.h> 51 #include <krb5/base64.h> 52 53 /* 54 * free all the memory used by (len, keys) 55 */ 56 57 void 58 hdb_free_keys(krb5_context context, int len, Key *keys) 59 { 60 size_t i; 61 62 for (i = 0; i < len; i++) { 63 free(keys[i].mkvno); 64 keys[i].mkvno = NULL; 65 if (keys[i].salt != NULL) { 66 free_Salt(keys[i].salt); 67 free(keys[i].salt); 68 keys[i].salt = NULL; 69 } 70 krb5_free_keyblock_contents(context, &keys[i].key); 71 } 72 free (keys); 73 } 74 75 /* 76 * for each entry in `default_keys' try to parse it as a sequence 77 * of etype:salttype:salt, syntax of this if something like: 78 * [(des|des3|etype):](pw-salt|afs3)[:string], if etype is omitted it 79 * means all etypes, and if string is omitted is means the default 80 * string (for that principal). Additional special values: 81 * v5 == pw-salt, and 82 * v4 == des:pw-salt: 83 * afs or afs3 == des:afs3-salt 84 */ 85 86 static const krb5_enctype des_etypes[] = { 87 KRB5_ENCTYPE_DES_CBC_MD5, 88 KRB5_ENCTYPE_DES_CBC_MD4, 89 KRB5_ENCTYPE_DES_CBC_CRC 90 }; 91 92 static const krb5_enctype all_etypes[] = { 93 KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96, 94 KRB5_ENCTYPE_DES3_CBC_SHA1, 95 KRB5_ENCTYPE_ARCFOUR_HMAC_MD5 96 }; 97 98 static krb5_error_code 99 parse_key_set(krb5_context context, const char *key, 100 krb5_enctype **ret_enctypes, size_t *ret_num_enctypes, 101 krb5_salt *salt, krb5_principal principal) 102 { 103 const char *p; 104 char buf[3][256]; 105 int num_buf = 0; 106 int i, num_enctypes = 0; 107 krb5_enctype e; 108 const krb5_enctype *enctypes = NULL; 109 krb5_error_code ret; 110 111 p = key; 112 113 *ret_enctypes = NULL; 114 *ret_num_enctypes = 0; 115 116 /* split p in a list of :-separated strings */ 117 for(num_buf = 0; num_buf < 3; num_buf++) 118 if(strsep_copy(&p, ":", buf[num_buf], sizeof(buf[num_buf])) == -1) 119 break; 120 121 salt->saltvalue.data = NULL; 122 salt->saltvalue.length = 0; 123 124 for(i = 0; i < num_buf; i++) { 125 if(enctypes == NULL && num_buf > 1) { 126 /* this might be a etype specifier */ 127 /* XXX there should be a string_to_etypes handling 128 special cases like `des' and `all' */ 129 if(strcmp(buf[i], "des") == 0) { 130 enctypes = des_etypes; 131 num_enctypes = sizeof(des_etypes)/sizeof(des_etypes[0]); 132 } else if(strcmp(buf[i], "des3") == 0) { 133 e = KRB5_ENCTYPE_DES3_CBC_SHA1; 134 enctypes = &e; 135 num_enctypes = 1; 136 } else { 137 ret = krb5_string_to_enctype(context, buf[i], &e); 138 if (ret == 0) { 139 enctypes = &e; 140 num_enctypes = 1; 141 } else 142 return ret; 143 } 144 continue; 145 } 146 if(salt->salttype == 0) { 147 /* interpret string as a salt specifier, if no etype 148 is set, this sets default values */ 149 /* XXX should perhaps use string_to_salttype, but that 150 interface sucks */ 151 if(strcmp(buf[i], "pw-salt") == 0) { 152 if(enctypes == NULL) { 153 enctypes = all_etypes; 154 num_enctypes = sizeof(all_etypes)/sizeof(all_etypes[0]); 155 } 156 salt->salttype = KRB5_PW_SALT; 157 } else if(strcmp(buf[i], "afs3-salt") == 0) { 158 if(enctypes == NULL) { 159 enctypes = des_etypes; 160 num_enctypes = sizeof(des_etypes)/sizeof(des_etypes[0]); 161 } 162 salt->salttype = KRB5_AFS3_SALT; 163 } 164 continue; 165 } 166 167 if (salt->saltvalue.data != NULL) 168 free(salt->saltvalue.data); 169 /* if there is a final string, use it as the string to 170 salt with, this is mostly useful with null salt for 171 v4 compat, and a cell name for afs compat */ 172 salt->saltvalue.data = strdup(buf[i]); 173 if (salt->saltvalue.data == NULL) 174 return krb5_enomem(context); 175 salt->saltvalue.length = strlen(buf[i]); 176 } 177 178 if(enctypes == NULL || salt->salttype == 0) { 179 krb5_free_salt(context, *salt); 180 krb5_set_error_message(context, EINVAL, "bad value for default_keys `%s'", key); 181 return EINVAL; 182 } 183 184 /* if no salt was specified make up default salt */ 185 if(salt->saltvalue.data == NULL) { 186 if(salt->salttype == KRB5_PW_SALT) { 187 ret = krb5_get_pw_salt(context, principal, salt); 188 if (ret) 189 return ret; 190 } else if(salt->salttype == KRB5_AFS3_SALT) { 191 krb5_const_realm realm = krb5_principal_get_realm(context, principal); 192 salt->saltvalue.data = strdup(realm); 193 if(salt->saltvalue.data == NULL) { 194 krb5_set_error_message(context, ENOMEM, 195 "out of memory while " 196 "parsing salt specifiers"); 197 return ENOMEM; 198 } 199 strlwr(salt->saltvalue.data); 200 salt->saltvalue.length = strlen(realm); 201 } 202 } 203 204 *ret_enctypes = malloc(sizeof(enctypes[0]) * num_enctypes); 205 if (*ret_enctypes == NULL) { 206 krb5_free_salt(context, *salt); 207 krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 208 return ENOMEM; 209 } 210 memcpy(*ret_enctypes, enctypes, sizeof(enctypes[0]) * num_enctypes); 211 *ret_num_enctypes = num_enctypes; 212 213 return 0; 214 } 215 216 /** 217 * This function prunes an HDB entry's keys that are too old to have been used 218 * to mint still valid tickets (based on the entry's maximum ticket lifetime). 219 * 220 * @param context Context 221 * @param entry HDB entry 222 */ 223 krb5_error_code 224 hdb_prune_keys(krb5_context context, hdb_entry *entry) 225 { 226 HDB_extension *ext; 227 HDB_Ext_KeySet *keys; 228 size_t nelem; 229 230 ext = hdb_find_extension(entry, choice_HDB_extension_data_hist_keys); 231 if (ext == NULL) 232 return 0; 233 keys = &ext->data.u.hist_keys; 234 nelem = keys->len; 235 236 /* Optionally drop key history for keys older than now - max_life */ 237 if (entry->max_life != NULL && nelem > 0 238 && krb5_config_get_bool_default(context, NULL, FALSE, 239 "kadmin", "prune-key-history", NULL)) { 240 hdb_keyset *elem; 241 time_t ceiling = time(NULL) - *entry->max_life; 242 time_t keep_time = 0; 243 size_t i; 244 245 /* 246 * Compute most recent key timestamp that predates the current time 247 * by at least the entry's maximum ticket lifetime. 248 */ 249 for (i = 0; i < nelem; ++i) { 250 elem = &keys->val[i]; 251 if (elem->set_time && *elem->set_time < ceiling 252 && (keep_time == 0 || *elem->set_time > keep_time)) 253 keep_time = *elem->set_time; 254 } 255 256 /* Drop obsolete entries */ 257 if (keep_time) { 258 for (i = 0; i < nelem; /* see below */) { 259 elem = &keys->val[i]; 260 if (elem->set_time && *elem->set_time < keep_time) { 261 remove_HDB_Ext_KeySet(keys, i); 262 /* 263 * Removing the i'th element shifts the tail down, continue 264 * at same index with reduced upper bound. 265 */ 266 --nelem; 267 continue; 268 } 269 ++i; 270 } 271 } 272 } 273 274 return 0; 275 } 276 277 /** 278 * This function adds an HDB entry's current keyset to the entry's key 279 * history. The current keyset is left alone; the caller is responsible 280 * for freeing it. 281 * 282 * @param context Context 283 * @param entry HDB entry 284 */ 285 krb5_error_code 286 hdb_add_current_keys_to_history(krb5_context context, hdb_entry *entry) 287 { 288 krb5_boolean replace = FALSE; 289 krb5_error_code ret; 290 HDB_extension *ext; 291 HDB_Ext_KeySet *keys; 292 hdb_keyset newkeyset; 293 time_t newtime; 294 295 if (entry->keys.len == 0) 296 return 0; /* nothing to do */ 297 298 ext = hdb_find_extension(entry, choice_HDB_extension_data_hist_keys); 299 if (ext == NULL) { 300 replace = TRUE; 301 ext = calloc(1, sizeof (*ext)); 302 if (ext == NULL) 303 return krb5_enomem(context); 304 305 ext->data.element = choice_HDB_extension_data_hist_keys; 306 } 307 keys = &ext->data.u.hist_keys; 308 309 ext->mandatory = FALSE; 310 311 /* 312 * Copy in newest old keyset 313 */ 314 ret = hdb_entry_get_pw_change_time(entry, &newtime); 315 if (ret) 316 goto out; 317 318 memset(&newkeyset, 0, sizeof(newkeyset)); 319 newkeyset.keys = entry->keys; 320 newkeyset.kvno = entry->kvno; 321 newkeyset.set_time = &newtime; 322 323 ret = add_HDB_Ext_KeySet(keys, &newkeyset); 324 if (ret) 325 goto out; 326 327 if (replace) { 328 /* hdb_replace_extension() deep-copies ext; what a waste */ 329 ret = hdb_replace_extension(context, entry, ext); 330 if (ret) 331 goto out; 332 } 333 334 ret = hdb_prune_keys(context, entry); 335 if (ret) 336 goto out; 337 338 out: 339 if (replace && ext) { 340 free_HDB_extension(ext); 341 free(ext); 342 } 343 return ret; 344 } 345 346 /** 347 * This function adds a key to an HDB entry's key history. 348 * 349 * @param context Context 350 * @param entry HDB entry 351 * @param kvno Key version number of the key to add to the history 352 * @param key The Key to add 353 */ 354 krb5_error_code 355 hdb_add_history_key(krb5_context context, hdb_entry *entry, krb5_kvno kvno, Key *key) 356 { 357 size_t i; 358 hdb_keyset keyset; 359 HDB_Ext_KeySet *hist_keys; 360 HDB_extension ext; 361 HDB_extension *extp; 362 krb5_error_code ret; 363 364 memset(&keyset, 0, sizeof (keyset)); 365 memset(&ext, 0, sizeof (ext)); 366 367 extp = hdb_find_extension(entry, choice_HDB_extension_data_hist_keys); 368 if (extp == NULL) { 369 ext.data.element = choice_HDB_extension_data_hist_keys; 370 extp = &ext; 371 } 372 373 extp->mandatory = FALSE; 374 hist_keys = &extp->data.u.hist_keys; 375 376 for (i = 0; i < hist_keys->len; i++) { 377 if (hist_keys->val[i].kvno == kvno) { 378 ret = add_Keys(&hist_keys->val[i].keys, key); 379 goto out; 380 } 381 } 382 383 keyset.kvno = kvno; 384 ret = add_Keys(&keyset.keys, key); 385 if (ret) 386 goto out; 387 ret = add_HDB_Ext_KeySet(hist_keys, &keyset); 388 if (ret) 389 goto out; 390 if (extp == &ext) { 391 ret = hdb_replace_extension(context, entry, &ext); 392 if (ret) 393 goto out; 394 } 395 396 out: 397 free_hdb_keyset(&keyset); 398 free_HDB_extension(&ext); 399 return ret; 400 } 401 402 403 /** 404 * This function changes an hdb_entry's kvno, swapping the current key 405 * set with a historical keyset. If no historical keys are found then 406 * an error is returned (the caller can still set entry->kvno directly). 407 * 408 * @param context krb5_context 409 * @param new_kvno New kvno for the entry 410 * @param entry hdb_entry to modify 411 */ 412 krb5_error_code 413 hdb_change_kvno(krb5_context context, krb5_kvno new_kvno, hdb_entry *entry) 414 { 415 HDB_extension ext; 416 HDB_extension *extp; 417 hdb_keyset keyset; 418 HDB_Ext_KeySet *hist_keys; 419 size_t i; 420 int found = 0; 421 krb5_error_code ret; 422 423 if (entry->kvno == new_kvno) 424 return 0; 425 426 extp = hdb_find_extension(entry, choice_HDB_extension_data_hist_keys); 427 if (extp == NULL) { 428 memset(&ext, 0, sizeof (ext)); 429 ext.data.element = choice_HDB_extension_data_hist_keys; 430 extp = &ext; 431 } 432 433 memset(&keyset, 0, sizeof (keyset)); 434 hist_keys = &extp->data.u.hist_keys; 435 for (i = 0; i < hist_keys->len; i++) { 436 if (hist_keys->val[i].kvno == new_kvno) { 437 found = 1; 438 ret = copy_hdb_keyset(&hist_keys->val[i], &keyset); 439 if (ret) 440 goto out; 441 ret = remove_HDB_Ext_KeySet(hist_keys, i); 442 if (ret) 443 goto out; 444 break; 445 } 446 } 447 448 if (!found) 449 return HDB_ERR_KVNO_NOT_FOUND; 450 451 ret = hdb_add_current_keys_to_history(context, entry); 452 if (ret) 453 goto out; 454 455 /* Note: we do nothing with keyset.set_time */ 456 entry->kvno = new_kvno; 457 entry->keys = keyset.keys; /* shortcut */ 458 memset(&keyset.keys, 0, sizeof (keyset.keys)); 459 460 out: 461 free_hdb_keyset(&keyset); 462 return ret; 463 } 464 465 466 static krb5_error_code 467 add_enctype_to_key_set(Key **key_set, size_t *nkeyset, 468 krb5_enctype enctype, krb5_salt *salt) 469 { 470 krb5_error_code ret; 471 Key key, *tmp; 472 473 memset(&key, 0, sizeof(key)); 474 475 tmp = realloc(*key_set, (*nkeyset + 1) * sizeof((*key_set)[0])); 476 if (tmp == NULL) 477 return ENOMEM; 478 479 *key_set = tmp; 480 481 key.key.keytype = enctype; 482 key.key.keyvalue.length = 0; 483 key.key.keyvalue.data = NULL; 484 485 if (salt) { 486 key.salt = calloc(1, sizeof(*key.salt)); 487 if (key.salt == NULL) { 488 free_Key(&key); 489 return ENOMEM; 490 } 491 492 key.salt->type = salt->salttype; 493 krb5_data_zero (&key.salt->salt); 494 495 ret = krb5_data_copy(&key.salt->salt, 496 salt->saltvalue.data, 497 salt->saltvalue.length); 498 if (ret) { 499 free_Key(&key); 500 return ret; 501 } 502 } else 503 key.salt = NULL; 504 505 (*key_set)[*nkeyset] = key; 506 507 *nkeyset += 1; 508 509 return 0; 510 } 511 512 513 static 514 krb5_error_code 515 ks_tuple2str(krb5_context context, int n_ks_tuple, 516 krb5_key_salt_tuple *ks_tuple, char ***ks_tuple_strs) 517 { 518 size_t i; 519 char **ksnames; 520 krb5_error_code rc = KRB5_PROG_ETYPE_NOSUPP; 521 522 *ks_tuple_strs = NULL; 523 if (n_ks_tuple < 1) 524 return 0; 525 526 if ((ksnames = calloc(n_ks_tuple + 1, sizeof (*ksnames))) == NULL) 527 return (errno); 528 529 for (i = 0; i < n_ks_tuple; i++) { 530 char *ename, *sname; 531 532 if (krb5_enctype_to_string(context, ks_tuple[i].ks_enctype, &ename)) 533 goto out; 534 if (krb5_salttype_to_string(context, ks_tuple[i].ks_enctype, 535 ks_tuple[i].ks_salttype, &sname)) { 536 free(ename); 537 goto out; 538 } 539 540 if (asprintf(&ksnames[i], "%s:%s", ename, sname) == -1) { 541 rc = errno; 542 free(ename); 543 free(sname); 544 goto out; 545 } 546 free(ename); 547 free(sname); 548 } 549 550 ksnames[i] = NULL; 551 *ks_tuple_strs = ksnames; 552 return 0; 553 554 out: 555 for (i = 0; i < n_ks_tuple; i++) 556 free(ksnames[i]); 557 free(ksnames); 558 return (rc); 559 } 560 561 /* 562 * 563 */ 564 565 static char ** 566 glob_rules_keys(krb5_context context, krb5_const_principal principal) 567 { 568 const krb5_config_binding *list; 569 krb5_principal pattern; 570 krb5_error_code ret; 571 572 list = krb5_config_get_list(context, NULL, "kadmin", 573 "default_key_rules", NULL); 574 if (list == NULL) 575 return NULL; 576 577 while (list) { 578 if (list->type == krb5_config_string) { 579 ret = krb5_parse_name(context, list->name, &pattern); 580 if (ret == 0) { 581 ret = krb5_principal_match(context, principal, pattern); 582 krb5_free_principal(context, pattern); 583 if (ret) { 584 return krb5_config_get_strings(context, list, 585 list->name, NULL); 586 } 587 } 588 } 589 list = list->next; 590 } 591 return NULL; 592 } 593 594 /* 595 * NIST guidance in Section 5.1 of [SP800-132] requires that a portion 596 * of the salt of at least 128 bits shall be randomly generated. 597 */ 598 static krb5_error_code 599 add_random_to_salt(krb5_context context, krb5_salt *in, krb5_salt *out) 600 { 601 krb5_error_code ret; 602 char *p; 603 unsigned char random[16]; 604 char *s; 605 int slen; 606 607 krb5_generate_random_block(random, sizeof(random)); 608 609 slen = rk_base64_encode(random, sizeof(random), &s); 610 if (slen < 0) 611 return ENOMEM; 612 613 ret = krb5_data_alloc(&out->saltvalue, slen + in->saltvalue.length); 614 if (ret) { 615 free(s); 616 return ret; 617 } 618 619 p = out->saltvalue.data; 620 memcpy(p, s, slen); 621 memcpy(&p[slen], in->saltvalue.data, in->saltvalue.length); 622 623 out->salttype = in->salttype; 624 free(s); 625 626 return 0; 627 } 628 629 /* 630 * Generate the `key_set' from the [kadmin]default_keys statement. If 631 * `no_salt' is set, salt is not important (and will not be set) since 632 * it's random keys that is going to be created. 633 */ 634 635 krb5_error_code 636 hdb_generate_key_set(krb5_context context, krb5_principal principal, 637 krb5_key_salt_tuple *ks_tuple, int n_ks_tuple, 638 Key **ret_key_set, size_t *nkeyset, int no_salt) 639 { 640 char **ktypes = NULL; 641 char **kp; 642 krb5_error_code ret; 643 Key *k, *key_set; 644 size_t i, j; 645 char **ks_tuple_strs; 646 char **config_ktypes = NULL; 647 static const char *default_keytypes[] = { 648 "aes256-cts-hmac-sha1-96:pw-salt", 649 "des3-cbc-sha1:pw-salt", 650 "arcfour-hmac-md5:pw-salt", 651 NULL 652 }; 653 654 if ((ret = ks_tuple2str(context, n_ks_tuple, ks_tuple, &ks_tuple_strs))) 655 return ret; 656 657 ktypes = ks_tuple_strs; 658 if (ktypes == NULL) { 659 ktypes = glob_rules_keys(context, principal); 660 } 661 if (ktypes == NULL) { 662 config_ktypes = krb5_config_get_strings(context, NULL, "kadmin", 663 "default_keys", NULL); 664 ktypes = config_ktypes; 665 } 666 if (ktypes == NULL) 667 ktypes = (char **)(intptr_t)default_keytypes; 668 669 *ret_key_set = key_set = NULL; 670 *nkeyset = 0; 671 672 for(kp = ktypes; kp && *kp; kp++) { 673 const char *p; 674 krb5_salt salt; 675 krb5_enctype *enctypes; 676 size_t num_enctypes; 677 678 p = *kp; 679 /* check alias */ 680 if(strcmp(p, "v5") == 0) 681 p = "pw-salt"; 682 else if(strcmp(p, "v4") == 0) 683 p = "des:pw-salt:"; 684 else if(strcmp(p, "afs") == 0 || strcmp(p, "afs3") == 0) 685 p = "des:afs3-salt"; 686 else if (strcmp(p, "arcfour-hmac-md5") == 0) 687 p = "arcfour-hmac-md5:pw-salt"; 688 689 memset(&salt, 0, sizeof(salt)); 690 691 ret = parse_key_set(context, p, 692 &enctypes, &num_enctypes, &salt, principal); 693 if (ret) { 694 krb5_warn(context, ret, "bad value for default_keys `%s'", *kp); 695 ret = 0; 696 krb5_free_salt(context, salt); 697 continue; 698 } 699 700 for (i = 0; i < num_enctypes; i++) { 701 krb5_salt *saltp = no_salt ? NULL : &salt; 702 krb5_salt rsalt; 703 704 /* find duplicates */ 705 for (j = 0; j < *nkeyset; j++) { 706 707 k = &key_set[j]; 708 709 if (k->key.keytype == enctypes[i]) { 710 if (no_salt) 711 break; 712 if (k->salt == NULL && salt.salttype == KRB5_PW_SALT) 713 break; 714 if (k->salt->type == salt.salttype && 715 k->salt->salt.length == salt.saltvalue.length && 716 memcmp(k->salt->salt.data, salt.saltvalue.data, 717 salt.saltvalue.length) == 0) 718 break; 719 } 720 } 721 /* not a duplicate, lets add it */ 722 if (j < *nkeyset) 723 continue; 724 725 memset(&rsalt, 0, sizeof(rsalt)); 726 727 /* prepend salt with randomness if required */ 728 if (!no_salt && 729 _krb5_enctype_requires_random_salt(context, enctypes[i])) { 730 saltp = &rsalt; 731 ret = add_random_to_salt(context, &salt, &rsalt); 732 } 733 734 if (ret == 0) 735 ret = add_enctype_to_key_set(&key_set, nkeyset, enctypes[i], 736 saltp); 737 krb5_free_salt(context, rsalt); 738 739 if (ret) { 740 free(enctypes); 741 krb5_free_salt(context, salt); 742 goto out; 743 } 744 } 745 free(enctypes); 746 krb5_free_salt(context, salt); 747 } 748 749 *ret_key_set = key_set; 750 751 out: 752 if (config_ktypes != NULL) 753 krb5_config_free_strings(config_ktypes); 754 755 for(kp = ks_tuple_strs; kp && *kp; kp++) 756 free(*kp); 757 free(ks_tuple_strs); 758 759 if (ret) { 760 krb5_warn(context, ret, 761 "failed to parse the [kadmin]default_keys values"); 762 763 for (i = 0; i < *nkeyset; i++) 764 free_Key(&key_set[i]); 765 free(key_set); 766 } else if (*nkeyset == 0) { 767 krb5_warnx(context, 768 "failed to parse any of the [kadmin]default_keys values"); 769 ret = EINVAL; /* XXX */ 770 } 771 772 return ret; 773 } 774 775 776 krb5_error_code 777 hdb_generate_key_set_password(krb5_context context, 778 krb5_principal principal, 779 const char *password, 780 krb5_key_salt_tuple *ks_tuple, int n_ks_tuple, 781 Key **keys, size_t *num_keys) 782 { 783 krb5_error_code ret; 784 size_t i; 785 786 ret = hdb_generate_key_set(context, principal, ks_tuple, n_ks_tuple, 787 keys, num_keys, 0); 788 if (ret) 789 return ret; 790 791 for (i = 0; i < (*num_keys); i++) { 792 krb5_salt salt; 793 Key *key = &(*keys)[i]; 794 795 salt.salttype = key->salt->type; 796 salt.saltvalue.length = key->salt->salt.length; 797 salt.saltvalue.data = key->salt->salt.data; 798 799 ret = krb5_string_to_key_salt (context, 800 key->key.keytype, 801 password, 802 salt, 803 &key->key); 804 if(ret) 805 break; 806 } 807 808 if(ret) { 809 hdb_free_keys (context, *num_keys, *keys); 810 return ret; 811 } 812 return ret; 813 } 814