1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 /* lib/kadm5/alt_prof.c */ 3 /* 4 * Copyright 1995,2001,2008,2009 by the Massachusetts Institute of Technology. 5 * All Rights Reserved. 6 * 7 * Export of this software from the United States of America may 8 * require a specific license from the United States Government. 9 * It is the responsibility of any person or organization contemplating 10 * export to obtain such a license before exporting. 11 * 12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 13 * distribute this software and its documentation for any purpose and 14 * without fee is hereby granted, provided that the above copyright 15 * notice appear in all copies and that both that copyright notice and 16 * this permission notice appear in supporting documentation, and that 17 * the name of M.I.T. not be used in advertising or publicity pertaining 18 * to distribution of the software without specific, written prior 19 * permission. Furthermore if you modify this software you must label 20 * your software as modified software and not distribute it in such a 21 * fashion that it might be confused with the original M.I.T. software. 22 * M.I.T. makes no representations about the suitability of 23 * this software for any purpose. It is provided "as is" without express 24 * or implied warranty. 25 */ 26 /* 27 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 31 /* Implement alternate profile file handling. */ 32 #include "k5-int.h" 33 #include "fake-addrinfo.h" 34 #include <kadm5/admin.h> 35 #include "adm_proto.h" 36 #include <stdio.h> 37 #include <ctype.h> 38 #include <kdb_log.h> 39 40 static krb5_key_salt_tuple * 41 copy_key_salt_tuple(krb5_key_salt_tuple *ksalt, krb5_int32 len) 42 { 43 krb5_key_salt_tuple *knew; 44 45 knew = calloc(len, sizeof(krb5_key_salt_tuple)); 46 if (knew == NULL) 47 return NULL; 48 memcpy(knew, ksalt, len * sizeof(krb5_key_salt_tuple)); 49 return knew; 50 } 51 52 /* 53 * krb5_aprof_getvals() - Get values from alternate profile. 54 * 55 * Parameters: 56 * acontext - opaque context for alternate profile. 57 * hierarchy - hierarchy of value to retrieve. 58 * retdata - Returned data values. 59 * 60 * Returns: 61 * error codes from profile_get_values() 62 */ 63 krb5_error_code 64 krb5_aprof_getvals(krb5_pointer acontext, const char **hierarchy, 65 char ***retdata) 66 { 67 return profile_get_values(acontext, hierarchy, retdata); 68 } 69 70 /* 71 * krb5_aprof_get_boolean() 72 * 73 * Parameters: 74 * acontext - opaque context for alternate profile 75 * hierarchy - hierarchy of value to retrieve 76 * retdata - Returned data value 77 * Returns: 78 * error codes 79 */ 80 81 static krb5_error_code 82 string_to_boolean(const char *string, krb5_boolean *out) 83 { 84 static const char *const yes[] = { "y", "yes", "true", "t", "1", "on" }; 85 static const char *const no[] = { "n", "no", "false", "f", "nil", "0", 86 "off" }; 87 unsigned int i; 88 89 for (i = 0; i < sizeof(yes) / sizeof(yes[0]); i++) { 90 if (!strcasecmp(string, yes[i])) { 91 *out = TRUE; 92 return 0; 93 } 94 } 95 for (i = 0; i < sizeof(no) / sizeof(no[0]); i++) { 96 if (!strcasecmp(string, no[i])) { 97 *out = FALSE; 98 return 0; 99 } 100 } 101 return PROF_BAD_BOOLEAN; 102 } 103 104 krb5_error_code 105 krb5_aprof_get_boolean(krb5_pointer acontext, const char **hierarchy, 106 int uselast, krb5_boolean *retdata) 107 { 108 krb5_error_code ret; 109 char **values, *valp; 110 int idx; 111 krb5_boolean val; 112 113 ret = krb5_aprof_getvals(acontext, hierarchy, &values); 114 if (ret) 115 return ret; 116 idx = 0; 117 if (uselast) { 118 while (values[idx] != NULL) 119 idx++; 120 idx--; 121 } 122 valp = values[idx]; 123 ret = string_to_boolean(valp, &val); 124 profile_free_list(values); 125 if (ret) 126 return ret; 127 *retdata = val; 128 return 0; 129 } 130 131 /* 132 * krb5_aprof_get_deltat() - Get a delta time value from the alternate 133 * profile. 134 * 135 * Parameters: 136 * acontext - opaque context for alternate profile. 137 * hierarchy - hierarchy of value to retrieve. 138 * uselast - if true, use last value, otherwise use first 139 * value found. 140 * deltatp - returned delta time value. 141 * 142 * Returns: 143 * error codes from profile_get_values() 144 * error codes from krb5_string_to_deltat() 145 */ 146 krb5_error_code 147 krb5_aprof_get_deltat(krb5_pointer acontext, const char **hierarchy, 148 krb5_boolean uselast, krb5_deltat *deltatp) 149 { 150 krb5_error_code ret; 151 char **values, *valp; 152 int idx; 153 154 ret = krb5_aprof_getvals(acontext, hierarchy, &values); 155 if (ret) 156 return ret; 157 158 idx = 0; 159 if (uselast) { 160 for (idx = 0; values[idx] != NULL; idx++); 161 idx--; 162 } 163 valp = values[idx]; 164 165 ret = krb5_string_to_deltat(valp, deltatp); 166 profile_free_list(values); 167 return ret; 168 } 169 170 /* 171 * krb5_aprof_get_string() - Get a string value from the alternate profile. 172 * 173 * Parameters: 174 * acontext - opaque context for alternate profile. 175 * hierarchy - hierarchy of value to retrieve. 176 * uselast - if true, use last value, otherwise use first 177 * value found. 178 * stringp - returned string value. 179 * 180 * Returns: 181 * error codes from profile_get_values() 182 */ 183 krb5_error_code 184 krb5_aprof_get_string(krb5_pointer acontext, const char **hierarchy, 185 krb5_boolean uselast, char **stringp) 186 { 187 krb5_error_code ret; 188 char **values; 189 int lastidx; 190 191 ret = krb5_aprof_getvals(acontext, hierarchy, &values); 192 if (ret) 193 return ret; 194 195 for (lastidx = 0; values[lastidx] != NULL; lastidx++); 196 lastidx--; 197 198 /* Excise the entry we want from the null-terminated list, 199 * and free up the rest. */ 200 if (uselast) { 201 *stringp = values[lastidx]; 202 values[lastidx] = NULL; 203 } else { 204 *stringp = values[0]; 205 values[0] = values[lastidx]; 206 values[lastidx] = NULL; 207 } 208 209 profile_free_list(values); 210 return 0; 211 } 212 213 /* 214 * krb5_aprof_get_string_all() - When the attr identified by "hierarchy" is 215 * specified multiple times, concatenate all of 216 * its string values from the alternate profile, 217 * separated with spaces. 218 * 219 * Parameters: 220 * acontext - opaque context for alternate profile. 221 * hierarchy - hierarchy of value to retrieve. 222 * stringp - Returned string value. 223 * 224 * Returns: 225 * error codes from profile_get_values() or ENOMEM 226 * Caller is responsible for deallocating stringp buffer 227 */ 228 krb5_error_code 229 krb5_aprof_get_string_all(krb5_pointer acontext, const char **hierarchy, 230 char **stringp) 231 { 232 krb5_error_code ret; 233 char **values; 234 int idx = 0; 235 size_t buf_size = 0; 236 237 ret = krb5_aprof_getvals(acontext, hierarchy, &values); 238 if (ret) 239 return ret; 240 241 buf_size = strlen(values[0]) + 3; 242 for (idx = 1; values[idx] != NULL; idx++) 243 buf_size += strlen(values[idx]) + 3; 244 245 *stringp = calloc(1, buf_size); 246 if (*stringp == NULL) { 247 profile_free_list(values); 248 return ENOMEM; 249 } 250 strlcpy(*stringp, values[0], buf_size); 251 for (idx = 1; values[idx] != NULL; idx++) { 252 strlcat(*stringp, " ", buf_size); 253 strlcat(*stringp, values[idx], buf_size); 254 } 255 256 profile_free_list(values); 257 return 0; 258 } 259 260 261 /* 262 * krb5_aprof_get_int32() - Get a 32-bit integer value from the alternate 263 * profile. 264 * 265 * Parameters: 266 * acontext - opaque context for alternate profile. 267 * hierarchy - hierarchy of value to retrieve. 268 * uselast - if true, use last value, otherwise use first 269 * value found. 270 * intp - returned 32-bit integer value. 271 * 272 * Returns: 273 * error codes from profile_get_values() 274 * EINVAL - value is not an integer 275 */ 276 krb5_error_code 277 krb5_aprof_get_int32(krb5_pointer acontext, const char **hierarchy, 278 krb5_boolean uselast, krb5_int32 *intp) 279 { 280 krb5_error_code ret; 281 char **values; 282 int idx; 283 284 ret = krb5_aprof_getvals(acontext, hierarchy, &values); 285 if (ret) 286 return ret; 287 288 idx = 0; 289 if (uselast) { 290 for (idx = 0; values[idx] != NULL; idx++); 291 idx--; 292 } 293 294 if (sscanf(values[idx], "%d", intp) != 1) 295 ret = EINVAL; 296 297 profile_free_list(values); 298 return ret; 299 } 300 301 /* 302 * Returns nonzero if it found something to copy; the caller may still need to 303 * check the output field or mask to see if the copy (allocation) was 304 * successful. Returns zero if nothing was found to copy, and thus the caller 305 * may want to apply some default heuristic. If the default action is just to 306 * use a fixed, compiled-in string, supply it as the default value here and 307 * ignore the return value. 308 */ 309 static int 310 get_string_param(char **param_out, char *param_in, long *mask_out, 311 long mask_in, long mask_bit, krb5_pointer aprofile, 312 const char **hierarchy, const char *config_name, 313 const char *default_value) 314 { 315 char *svalue; 316 317 hierarchy[2] = config_name; 318 if (mask_in & mask_bit) { 319 *param_out = strdup(param_in); 320 if (*param_out) 321 *mask_out |= mask_bit; 322 return 1; 323 } else if (aprofile != NULL && 324 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { 325 *param_out = svalue; 326 *mask_out |= mask_bit; 327 return 1; 328 } else if (default_value) { 329 *param_out = strdup(default_value); 330 if (*param_out) 331 *mask_out |= mask_bit; 332 return 1; 333 } else { 334 return 0; 335 } 336 } 337 /* 338 * Similar, for (host-order) port number, if not already set in the output 339 * field; default_value == 0 means no default. 340 */ 341 static void 342 get_port_param(int *param_out, int param_in, long *mask_out, long mask_in, 343 long mask_bit, krb5_pointer aprofile, const char **hierarchy, 344 const char *config_name, int default_value) 345 { 346 krb5_int32 ivalue; 347 348 if (*mask_out & mask_bit) 349 return; 350 hierarchy[2] = config_name; 351 if (mask_in & mask_bit) { 352 *mask_out |= mask_bit; 353 *param_out = param_in; 354 } else if (aprofile != NULL && 355 !krb5_aprof_get_int32(aprofile, hierarchy, TRUE, &ivalue)) { 356 *param_out = ivalue; 357 *mask_out |= mask_bit; 358 } else if (default_value) { 359 *param_out = default_value; 360 *mask_out |= mask_bit; 361 } 362 } 363 364 /* 365 * Similar, for delta_t; default is required. 366 */ 367 static void 368 get_deltat_param(krb5_deltat *param_out, krb5_deltat param_in, long *mask_out, 369 long mask_in, long mask_bit, krb5_pointer aprofile, 370 const char **hierarchy, const char *config_name, 371 krb5_deltat default_value) 372 { 373 krb5_deltat dtvalue; 374 375 hierarchy[2] = config_name; 376 if (mask_in & mask_bit) { 377 *mask_out |= mask_bit; 378 *param_out = param_in; 379 } else if (aprofile && 380 !krb5_aprof_get_deltat(aprofile, hierarchy, TRUE, &dtvalue)) { 381 *param_out = dtvalue; 382 *mask_out |= mask_bit; 383 } else { 384 *param_out = default_value; 385 *mask_out |= mask_bit; 386 } 387 } 388 389 /* 390 * Parse out the port number from an admin_server setting. Modify server to 391 * contain just the hostname or address. If a port is given, set *port, and 392 * set the appropriate bit in *mask. 393 */ 394 static void 395 parse_admin_server_port(char *server, int *port, long *mask) 396 { 397 char *end, *portstr; 398 399 /* Allow the name or addr to be enclosed in brackets, for IPv6 addrs. */ 400 if (*server == '[' && (end = strchr(server + 1, ']')) != NULL) { 401 portstr = (*(end + 1) == ':') ? end + 2 : NULL; 402 /* Shift the bracketed name or address back into server. */ 403 memmove(server, server + 1, end - (server + 1)); 404 *(end - 1) = '\0'; 405 } else { 406 /* Terminate the name at the colon, if any. */ 407 end = server + strcspn(server, ":"); 408 portstr = (*end == ':') ? end + 1 : NULL; 409 *end = '\0'; 410 } 411 412 /* If we found a port string, parse it and set the appropriate bit. */ 413 if (portstr) { 414 *port = atoi(portstr); 415 *mask |= KADM5_CONFIG_KADMIND_PORT; 416 } 417 } 418 419 /* 420 * Function: kadm5_get_config_params 421 * 422 * Purpose: Merge configuration parameters provided by the caller with values 423 * specified in configuration files and with default values. 424 * 425 * Arguments: 426 * 427 * context (r) krb5_context to use 428 * profile (r) profile file to use 429 * envname (r) envname that contains a profile name to 430 * override profile 431 * params_in (r) params structure containing user-supplied 432 * values, or NULL 433 * params_out (w) params structure to be filled in 434 * 435 * Effects: 436 * 437 * The fields and mask of params_out are filled in with values obtained from 438 * params_in, the specified profile, and default values. Only and all fields 439 * specified in params_out->mask are set. The context of params_out must be 440 * freed with kadm5_free_config_params. 441 * 442 * params_in and params_out may be the same pointer. However, all pointers in 443 * params_in for which the mask is set will be re-assigned to newly copied 444 * versions, overwriting the old pointer value. 445 */ 446 krb5_error_code kadm5_get_config_params(krb5_context context, 447 int use_kdc_config, 448 kadm5_config_params *params_in, 449 kadm5_config_params *params_out) 450 { 451 char *lrealm, *svalue, *sp, *ep, *tp; 452 krb5_pointer aprofile = context->profile; 453 const char *hierarchy[4]; 454 krb5_int32 ivalue; 455 kadm5_config_params params, empty_params; 456 krb5_boolean bvalue; 457 krb5_error_code ret = 0; 458 459 memset(¶ms, 0, sizeof(params)); 460 memset(&empty_params, 0, sizeof(empty_params)); 461 462 if (params_in == NULL) 463 params_in = &empty_params; 464 465 if (params_in->mask & KADM5_CONFIG_REALM) { 466 lrealm = params.realm = strdup(params_in->realm); 467 if (params.realm == NULL) { 468 ret = ENOMEM; 469 goto cleanup; 470 } 471 params.mask |= KADM5_CONFIG_REALM; 472 } else { 473 ret = krb5_get_default_realm(context, &lrealm); 474 if (ret) 475 goto cleanup; 476 params.realm = lrealm; 477 params.mask |= KADM5_CONFIG_REALM; 478 } 479 480 if (params_in->mask & KADM5_CONFIG_KVNO) { 481 params.kvno = params_in->kvno; 482 params.mask |= KADM5_CONFIG_KVNO; 483 } 484 485 /* Initialize realm parameters. */ 486 hierarchy[0] = KRB5_CONF_REALMS; 487 hierarchy[1] = lrealm; 488 hierarchy[3] = NULL; 489 490 #define GET_STRING_PARAM(FIELD, BIT, CONFTAG, DEFAULT) \ 491 get_string_param(¶ms.FIELD, params_in->FIELD, \ 492 ¶ms.mask, params_in->mask, BIT, \ 493 aprofile, hierarchy, CONFTAG, DEFAULT) 494 495 /* Get the value for the admin server. */ 496 GET_STRING_PARAM(admin_server, KADM5_CONFIG_ADMIN_SERVER, 497 KRB5_CONF_ADMIN_SERVER, NULL); 498 499 if (params.mask & KADM5_CONFIG_ADMIN_SERVER) { 500 parse_admin_server_port(params.admin_server, ¶ms.kadmind_port, 501 ¶ms.mask); 502 } 503 504 /* Get the value for the database. */ 505 GET_STRING_PARAM(dbname, KADM5_CONFIG_DBNAME, KRB5_CONF_DATABASE_NAME, 506 DEFAULT_KDB_FILE); 507 508 /* Get the name of the acl file. */ 509 GET_STRING_PARAM(acl_file, KADM5_CONFIG_ACL_FILE, KRB5_CONF_ACL_FILE, 510 DEFAULT_KADM5_ACL_FILE); 511 512 /* Get the name of the dict file. */ 513 GET_STRING_PARAM(dict_file, KADM5_CONFIG_DICT_FILE, KRB5_CONF_DICT_FILE, 514 NULL); 515 516 /* Get the kadmind listen addresses. */ 517 GET_STRING_PARAM(kadmind_listen, KADM5_CONFIG_KADMIND_LISTEN, 518 KRB5_CONF_KADMIND_LISTEN, NULL); 519 GET_STRING_PARAM(kpasswd_listen, KADM5_CONFIG_KPASSWD_LISTEN, 520 KRB5_CONF_KPASSWD_LISTEN, NULL); 521 GET_STRING_PARAM(iprop_listen, KADM5_CONFIG_IPROP_LISTEN, 522 KRB5_CONF_IPROP_LISTEN, NULL); 523 524 #define GET_PORT_PARAM(FIELD, BIT, CONFTAG, DEFAULT) \ 525 get_port_param(¶ms.FIELD, params_in->FIELD, \ 526 ¶ms.mask, params_in->mask, BIT, \ 527 aprofile, hierarchy, CONFTAG, DEFAULT) 528 529 /* Get the value for the kadmind port. */ 530 GET_PORT_PARAM(kadmind_port, KADM5_CONFIG_KADMIND_PORT, 531 KRB5_CONF_KADMIND_PORT, DEFAULT_KADM5_PORT); 532 533 /* Get the value for the kpasswd port. */ 534 GET_PORT_PARAM(kpasswd_port, KADM5_CONFIG_KPASSWD_PORT, 535 KRB5_CONF_KPASSWD_PORT, DEFAULT_KPASSWD_PORT); 536 537 /* Get the value for the master key name. */ 538 GET_STRING_PARAM(mkey_name, KADM5_CONFIG_MKEY_NAME, 539 KRB5_CONF_MASTER_KEY_NAME, NULL); 540 541 /* Get the value for the master key type. */ 542 hierarchy[2] = KRB5_CONF_MASTER_KEY_TYPE; 543 if (params_in->mask & KADM5_CONFIG_ENCTYPE) { 544 params.mask |= KADM5_CONFIG_ENCTYPE; 545 params.enctype = params_in->enctype; 546 } else if (aprofile != NULL && 547 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { 548 if (!krb5_string_to_enctype(svalue, ¶ms.enctype)) { 549 params.mask |= KADM5_CONFIG_ENCTYPE; 550 free(svalue); 551 } 552 } else { 553 params.mask |= KADM5_CONFIG_ENCTYPE; 554 params.enctype = DEFAULT_KDC_ENCTYPE; 555 } 556 557 /* Get the value for mkey_from_kbd. */ 558 if (params_in->mask & KADM5_CONFIG_MKEY_FROM_KBD) { 559 params.mask |= KADM5_CONFIG_MKEY_FROM_KBD; 560 params.mkey_from_kbd = params_in->mkey_from_kbd; 561 } 562 563 /* Get the value for the stashfile. */ 564 GET_STRING_PARAM(stash_file, KADM5_CONFIG_STASH_FILE, 565 KRB5_CONF_KEY_STASH_FILE, NULL); 566 567 /* Get the value for maximum ticket lifetime. */ 568 #define GET_DELTAT_PARAM(FIELD, BIT, CONFTAG, DEFAULT) \ 569 get_deltat_param(¶ms.FIELD, params_in->FIELD, \ 570 ¶ms.mask, params_in->mask, BIT, \ 571 aprofile, hierarchy, CONFTAG, DEFAULT) 572 573 GET_DELTAT_PARAM(max_life, KADM5_CONFIG_MAX_LIFE, KRB5_CONF_MAX_LIFE, 574 24 * 60 * 60); /* 1 day */ 575 576 /* Get the value for maximum renewable ticket lifetime. */ 577 GET_DELTAT_PARAM(max_rlife, KADM5_CONFIG_MAX_RLIFE, 578 KRB5_CONF_MAX_RENEWABLE_LIFE, 0); 579 580 /* Get the value for the default principal expiration */ 581 hierarchy[2] = KRB5_CONF_DEFAULT_PRINCIPAL_EXPIRATION; 582 if (params_in->mask & KADM5_CONFIG_EXPIRATION) { 583 params.mask |= KADM5_CONFIG_EXPIRATION; 584 params.expiration = params_in->expiration; 585 } else if (aprofile && 586 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { 587 if (!krb5_string_to_timestamp(svalue, ¶ms.expiration)) { 588 params.mask |= KADM5_CONFIG_EXPIRATION; 589 free(svalue); 590 } 591 } else { 592 params.mask |= KADM5_CONFIG_EXPIRATION; 593 params.expiration = 0; 594 } 595 596 /* Get the value for the default principal flags */ 597 hierarchy[2] = KRB5_CONF_DEFAULT_PRINCIPAL_FLAGS; 598 if (params_in->mask & KADM5_CONFIG_FLAGS) { 599 params.mask |= KADM5_CONFIG_FLAGS; 600 params.flags = params_in->flags; 601 } else if (aprofile != NULL && 602 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { 603 sp = svalue; 604 params.flags = 0; 605 while (sp != NULL) { 606 if ((ep = strchr(sp, ',')) != NULL || 607 (ep = strchr(sp, ' ')) != NULL || 608 (ep = strchr(sp, '\t')) != NULL) { 609 /* Fill in trailing whitespace of sp. */ 610 tp = ep - 1; 611 while (isspace((unsigned char)*tp) && tp > sp) { 612 *tp = '\0'; 613 tp--; 614 } 615 *ep = '\0'; 616 ep++; 617 /* Skip over trailing whitespace of ep. */ 618 while (isspace((unsigned char)*ep) && *ep != '\0') 619 ep++; 620 } 621 /* Convert this flag. */ 622 if (krb5_flagspec_to_mask(sp, ¶ms.flags, ¶ms.flags)) 623 break; 624 sp = ep; 625 } 626 if (sp == NULL) 627 params.mask |= KADM5_CONFIG_FLAGS; 628 free(svalue); 629 } else { 630 params.mask |= KADM5_CONFIG_FLAGS; 631 params.flags = KRB5_KDB_DEF_FLAGS; 632 } 633 634 /* Get the value for the supported enctype/salttype matrix. */ 635 hierarchy[2] = KRB5_CONF_SUPPORTED_ENCTYPES; 636 if (params_in->mask & KADM5_CONFIG_ENCTYPES) { 637 if (params_in->keysalts) { 638 params.keysalts = copy_key_salt_tuple(params_in->keysalts, 639 params_in->num_keysalts); 640 if (params.keysalts) { 641 params.mask |= KADM5_CONFIG_ENCTYPES; 642 params.num_keysalts = params_in->num_keysalts; 643 } 644 } else { 645 params.mask |= KADM5_CONFIG_ENCTYPES; 646 params.keysalts = NULL; 647 params.num_keysalts = params_in->num_keysalts; 648 } 649 } else { 650 svalue = NULL; 651 if (aprofile != NULL) 652 krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue); 653 if (svalue == NULL) 654 svalue = strdup(KRB5_DEFAULT_SUPPORTED_ENCTYPES); 655 if (svalue == NULL) { 656 ret = ENOMEM; 657 goto cleanup; 658 } 659 660 params.keysalts = NULL; 661 params.num_keysalts = 0; 662 krb5_string_to_keysalts(svalue, 663 NULL, /* Tuple separators */ 664 NULL, /* Key/salt separators */ 665 0, /* No duplicates */ 666 ¶ms.keysalts, 667 ¶ms.num_keysalts); 668 if (params.num_keysalts) 669 params.mask |= KADM5_CONFIG_ENCTYPES; 670 671 free(svalue); 672 } 673 674 hierarchy[2] = KRB5_CONF_IPROP_ENABLE; 675 676 params.iprop_enabled = FALSE; 677 params.mask |= KADM5_CONFIG_IPROP_ENABLED; 678 679 if (params_in->mask & KADM5_CONFIG_IPROP_ENABLED) { 680 params.mask |= KADM5_CONFIG_IPROP_ENABLED; 681 params.iprop_enabled = params_in->iprop_enabled; 682 } else { 683 if (aprofile && 684 !krb5_aprof_get_boolean(aprofile, hierarchy, TRUE, &bvalue)) { 685 params.iprop_enabled = bvalue; 686 params.mask |= KADM5_CONFIG_IPROP_ENABLED; 687 } 688 } 689 690 if (!GET_STRING_PARAM(iprop_logfile, KADM5_CONFIG_IPROP_LOGFILE, 691 KRB5_CONF_IPROP_LOGFILE, NULL)) { 692 if (params.mask & KADM5_CONFIG_DBNAME) { 693 if (asprintf(¶ms.iprop_logfile, "%s.ulog", 694 params.dbname) >= 0) 695 params.mask |= KADM5_CONFIG_IPROP_LOGFILE; 696 } 697 } 698 699 GET_PORT_PARAM(iprop_port, KADM5_CONFIG_IPROP_PORT, KRB5_CONF_IPROP_PORT, 700 0); 701 702 /* 5 min for large KDBs */ 703 GET_DELTAT_PARAM(iprop_resync_timeout, KADM5_CONFIG_IPROP_RESYNC_TIMEOUT, 704 KRB5_CONF_IPROP_RESYNC_TIMEOUT, 60 * 5); 705 706 if (params_in->mask & KADM5_CONFIG_ULOG_SIZE) { 707 params.mask |= KADM5_CONFIG_ULOG_SIZE; 708 params.iprop_ulogsize = params_in->iprop_ulogsize; 709 } else { 710 params.iprop_ulogsize = 0; 711 hierarchy[2] = KRB5_CONF_IPROP_ULOGSIZE; 712 if (aprofile != NULL && 713 !krb5_aprof_get_int32(aprofile, hierarchy, TRUE, &ivalue) && 714 ivalue > 0) 715 params.iprop_ulogsize = ivalue; 716 hierarchy[2] = KRB5_CONF_IPROP_MASTER_ULOGSIZE; 717 if (params.iprop_ulogsize == 0 && aprofile != NULL && 718 !krb5_aprof_get_int32(aprofile, hierarchy, TRUE, &ivalue) && 719 ivalue > 0) 720 params.iprop_ulogsize = ivalue; 721 if (params.iprop_ulogsize == 0) 722 params.iprop_ulogsize = DEF_ULOGENTRIES; 723 } 724 params.mask |= KADM5_CONFIG_ULOG_SIZE; 725 726 GET_DELTAT_PARAM(iprop_poll_time, KADM5_CONFIG_POLL_TIME, 727 KRB5_CONF_IPROP_REPLICA_POLL, -1); 728 if (params.iprop_poll_time == -1) { 729 GET_DELTAT_PARAM(iprop_poll_time, KADM5_CONFIG_POLL_TIME, 730 KRB5_CONF_IPROP_SLAVE_POLL, 2 * 60); 731 } 732 733 *params_out = params; 734 735 cleanup: 736 if (ret) { 737 kadm5_free_config_params(context, ¶ms); 738 params_out->mask = 0; 739 } 740 return ret; 741 } 742 743 /* 744 * kadm5_free_config_params() - Free data allocated by above. 745 */ 746 krb5_error_code 747 kadm5_free_config_params(krb5_context context, kadm5_config_params *params) 748 { 749 if (params == NULL) 750 return 0; 751 free(params->dbname); 752 free(params->mkey_name); 753 free(params->stash_file); 754 free(params->keysalts); 755 free(params->admin_server); 756 free(params->dict_file); 757 free(params->acl_file); 758 free(params->realm); 759 free(params->iprop_logfile); 760 return 0; 761 } 762 763 krb5_error_code 764 kadm5_get_admin_service_name(krb5_context ctx, char *realm_in, 765 char *admin_name, size_t maxlen) 766 { 767 krb5_error_code ret; 768 kadm5_config_params params_in, params_out; 769 char *canonhost = NULL; 770 771 memset(¶ms_in, 0, sizeof(params_in)); 772 memset(¶ms_out, 0, sizeof(params_out)); 773 774 params_in.mask |= KADM5_CONFIG_REALM; 775 params_in.realm = realm_in; 776 ret = kadm5_get_config_params(ctx, 0, ¶ms_in, ¶ms_out); 777 if (ret) 778 return ret; 779 780 if (!(params_out.mask & KADM5_CONFIG_ADMIN_SERVER)) { 781 ret = KADM5_MISSING_KRB5_CONF_PARAMS; 782 goto err_params; 783 } 784 785 ret = krb5_expand_hostname(ctx, params_out.admin_server, &canonhost); 786 if (ret) 787 goto err_params; 788 789 if (strlen(canonhost) + sizeof("kadmin/") > maxlen) { 790 ret = ENOMEM; 791 goto err_params; 792 } 793 snprintf(admin_name, maxlen, "kadmin/%s", canonhost); 794 795 err_params: 796 krb5_free_string(ctx, canonhost); 797 kadm5_free_config_params(ctx, ¶ms_out); 798 return ret; 799 } 800