1 /* 2 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 #pragma ident "%Z%%M% %I% %E% SMI" 7 8 /* 9 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING 10 * 11 * Openvision retains the copyright to derivative works of 12 * this source code. Do *NOT* create a derivative of this 13 * source code before consulting with your legal department. 14 * Do *NOT* integrate *ANY* of this source code into another 15 * product before consulting with your legal department. 16 * 17 * For further information, read the top-level Openvision 18 * copyright which is contained in the top-level MIT Kerberos 19 * copyright. 20 * 21 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING 22 * 23 */ 24 25 26 /* 27 * lib/kadm/alt_prof.c 28 * 29 * Copyright 1995 by the Massachusetts Institute of Technology. 30 * All Rights Reserved. 31 * 32 * Export of this software from the United States of America may 33 * require a specific license from the United States Government. 34 * It is the responsibility of any person or organization contemplating 35 * export to obtain such a license before exporting. 36 * 37 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 38 * distribute this software and its documentation for any purpose and 39 * without fee is hereby granted, provided that the above copyright 40 * notice appear in all copies and that both that copyright notice and 41 * this permission notice appear in supporting documentation, and that 42 * the name of M.I.T. not be used in advertising or publicity pertaining 43 * to distribution of the software without specific, written prior 44 * permission. M.I.T. makes no representations about the suitability of 45 * this software for any purpose. It is provided "as is" without express 46 * or implied warranty. 47 * 48 */ 49 50 /* 51 * alt_prof.c - Implement alternate profile file handling. 52 */ 53 #include <k5-int.h> 54 #include <kadm5/admin.h> 55 #include <adm_proto.h> 56 #include <stdio.h> 57 #include <ctype.h> 58 #include <os-proto.h> 59 #include <kdb/kdb_log.h> 60 61 krb5_error_code kadm5_free_config_params(); 62 63 #define DEFAULT_ENCTYPE_LIST \ 64 "aes256-cts-hmac-sha1-96:normal " \ 65 "aes128-cts-hmac-sha1-96:normal " \ 66 "des3-cbc-hmac-sha1-kd:normal " \ 67 "arcfour-hmac-md5:normal " \ 68 "des-cbc-md5:normal " \ 69 "des-cbc-crc:normal" 70 71 /* 72 * krb5_aprof_init() - Initialize alternate profile context. 73 * 74 * Parameters: 75 * fname - default file name of the profile. 76 * envname - environment variable name which can override fname. 77 * acontextp - Pointer to opaque context for alternate profile. 78 * 79 * Returns: 80 * error codes from profile_init() 81 */ 82 krb5_error_code 83 krb5_aprof_init(fname, envname, acontextp) 84 char *fname; 85 char *envname; 86 krb5_pointer *acontextp; 87 { 88 krb5_error_code kret; 89 const char *namelist[2]; 90 profile_t profile; 91 92 namelist[1] = (char *)NULL; 93 profile = (profile_t)NULL; 94 if (envname) { 95 if ((namelist[0] = getenv(envname))) { 96 kret = profile_init(namelist, &profile); 97 if (kret) 98 return (kret); 99 *acontextp = (krb5_pointer) profile; 100 return (0); 101 } 102 } 103 profile = (profile_t)NULL; 104 if (fname) { 105 kret = profile_init_path(fname, &profile); 106 if (kret == ENOENT) { 107 profile = 0; 108 } else if (kret) 109 return (kret); 110 *acontextp = (krb5_pointer) profile; 111 return (0); 112 } 113 return (0); 114 } 115 116 /* 117 * krb5_aprof_getvals() - Get values from alternate profile. 118 * 119 * Parameters: 120 * acontext - opaque context for alternate profile. 121 * hierarchy - hierarchy of value to retrieve. 122 * retdata - Returned data values. 123 * 124 * Returns: 125 * error codes from profile_get_values() 126 */ 127 krb5_error_code 128 krb5_aprof_getvals(acontext, hierarchy, retdata) 129 krb5_pointer acontext; 130 const char **hierarchy; 131 char ***retdata; 132 { 133 return (profile_get_values((profile_t)acontext, 134 hierarchy, 135 retdata)); 136 } 137 138 /* 139 * krb5_aprof_get_deltat() - Get a delta time value from the alternate 140 * profile. 141 * 142 * Parameters: 143 * acontext - opaque context for alternate profile. 144 * hierarchy - hierarchy of value to retrieve. 145 * uselast - if true, use last value, otherwise use 146 * first value found. 147 * deltatp - returned delta time value. 148 * 149 * Returns: 150 * error codes from profile_get_values() 151 * error codes from krb5_string_to_deltat() 152 */ 153 krb5_error_code 154 krb5_aprof_get_deltat(acontext, hierarchy, uselast, deltatp) 155 krb5_pointer acontext; 156 const char **hierarchy; 157 krb5_boolean uselast; 158 krb5_deltat *deltatp; 159 { 160 krb5_error_code kret; 161 char **values; 162 char *valp; 163 int index; 164 165 if (!(kret = krb5_aprof_getvals(acontext, hierarchy, &values))) { 166 index = 0; 167 if (uselast) { 168 for (index = 0; values[index]; index++); 169 index--; 170 } 171 valp = values[index]; 172 kret = krb5_string_to_deltat(valp, deltatp); 173 174 /* Free the string storage */ 175 for (index = 0; values[index]; index++) 176 krb5_xfree(values[index]); 177 krb5_xfree(values); 178 } 179 return (kret); 180 } 181 182 /* 183 * krb5_aprof_get_string() - Get a string value from the alternate 184 * profile. 185 * 186 * Parameters: 187 * acontext - opaque context for alternate profile. 188 * hierarchy - hierarchy of value to retrieve. 189 * uselast - if true, use last value, otherwise use 190 * first value found. 191 * stringp - returned string value. 192 * 193 * Returns: 194 * error codes from profile_get_values() 195 */ 196 krb5_error_code 197 krb5_aprof_get_string(acontext, hierarchy, uselast, stringp) 198 krb5_pointer acontext; 199 const char **hierarchy; 200 krb5_boolean uselast; 201 char **stringp; 202 { 203 krb5_error_code kret; 204 char **values; 205 int index, i; 206 207 if (!(kret = krb5_aprof_getvals(acontext, hierarchy, &values))) { 208 index = 0; 209 if (uselast) { 210 for (index = 0; values[index]; index++); 211 index--; 212 } 213 214 *stringp = values[index]; 215 216 /* Free the string storage */ 217 for (i = 0; values[i]; i++) 218 if (i != index) 219 krb5_xfree(values[i]); 220 krb5_xfree(values); 221 } 222 return (kret); 223 } 224 225 /* 226 * krb5_aprof_get_int32() - Get a 32-bit integer value from the alternate 227 * profile. 228 * 229 * Parameters: 230 * acontext - opaque context for alternate profile. 231 * hierarchy - hierarchy of value to retrieve. 232 * uselast - if true, use last value, otherwise use 233 * first value found. 234 * intp - returned 32-bit integer value. 235 * 236 * Returns: 237 * error codes from profile_get_values() 238 * EINVAL - value is not an integer 239 */ 240 krb5_error_code 241 krb5_aprof_get_int32(acontext, hierarchy, uselast, intp) 242 krb5_pointer acontext; 243 const char **hierarchy; 244 krb5_boolean uselast; 245 krb5_int32 *intp; 246 { 247 krb5_error_code kret; 248 char **values; 249 int index; 250 251 if (!(kret = krb5_aprof_getvals(acontext, hierarchy, &values))) { 252 index = 0; 253 if (uselast) { 254 for (index = 0; values[index]; index++); 255 index--; 256 } 257 258 if (sscanf(values[index], "%d", intp) != 1) 259 kret = EINVAL; 260 261 /* Free the string storage */ 262 for (index = 0; values[index]; index++) 263 krb5_xfree(values[index]); 264 krb5_xfree(values); 265 } 266 return (kret); 267 } 268 269 /* 270 * krb5_aprof_finish() - Finish alternate profile context. 271 * 272 * Parameter: 273 * acontext - opaque context for alternate profile. 274 * 275 * Returns: 276 * 0 on success, something else on failure. 277 */ 278 krb5_error_code 279 krb5_aprof_finish(acontext) 280 krb5_pointer acontext; 281 { 282 profile_release(acontext); 283 return (0); 284 } 285 286 /* 287 * Function: kadm5_get_config_params 288 * 289 * Purpose: Merge configuration parameters provided by the caller with 290 * values specified in configuration files and with default values. 291 * 292 * Arguments: 293 * 294 * context(r) krb5_context to use 295 * profile(r) profile file to use 296 * envname(r) envname that contains a profile name to 297 * override profile 298 * params_in(r) params structure containing user-supplied 299 * values, or NULL 300 * params_out(w) params structure to be filled in 301 * 302 * Effects: 303 * 304 * The fields and mask of params_out are filled in with values 305 * obtained from params_in, the specified profile, and default 306 * values. Only and all fields specified in params_out->mask are 307 * set. The context of params_out must be freed with 308 * kadm5_free_config_params. 309 * 310 * params_in and params_out may be the same pointer. However, all pointers 311 * in params_in for which the mask is set will be re-assigned to newly copied 312 * versions, overwriting the old pointer value. 313 */ 314 krb5_error_code kadm5_get_config_params(context, kdcprofile, kdcenv, 315 params_in, params_out) 316 krb5_context context; 317 char *kdcprofile; 318 char *kdcenv; 319 kadm5_config_params *params_in, *params_out; 320 { 321 char *filename; 322 char *envname; 323 char *lrealm; 324 krb5_pointer aprofile = 0; 325 const char *hierarchy[4]; 326 char *svalue; 327 krb5_int32 ivalue; 328 kadm5_config_params params, empty_params; 329 330 krb5_error_code kret = 0; 331 krb5_error_code dnsret = 1; 332 333 #ifdef KRB5_DNS_LOOKUP 334 char dns_host[MAX_DNS_NAMELEN]; 335 unsigned short dns_portno; 336 krb5_data dns_realm; 337 #endif /* KRB5_DNS_LOOKUP */ 338 339 memset((char *)¶ms, 0, sizeof (params)); 340 memset((char *)&empty_params, 0, sizeof (empty_params)); 341 342 if (params_in == NULL) params_in = &empty_params; 343 344 if (params_in->mask & KADM5_CONFIG_REALM) { 345 lrealm = params.realm = strdup(params_in->realm); 346 if (params.realm) 347 params.mask |= KADM5_CONFIG_REALM; 348 } else { 349 kret = krb5_get_default_realm(context, &lrealm); 350 if (kret) 351 goto cleanup; 352 params.realm = lrealm; 353 params.mask |= KADM5_CONFIG_REALM; 354 } 355 if (params_in->mask & KADM5_CONFIG_PROFILE) { 356 filename = params.profile = strdup(params_in->profile); 357 if (params.profile) 358 params.mask |= KADM5_CONFIG_PROFILE; 359 envname = NULL; 360 } else { 361 /* 362 * XXX These defaults should to work on both client and 363 * server. kadm5_get_config_params can be implemented as a 364 * wrapper function in each library that provides correct 365 * defaults for NULL values. 366 */ 367 filename = (kdcprofile) ? kdcprofile : DEFAULT_KDC_PROFILE; 368 envname = (kdcenv) ? kdcenv : KDC_PROFILE_ENV; 369 if (context->profile_secure == TRUE) envname = 0; 370 } 371 372 kret = krb5_aprof_init(filename, envname, &aprofile); 373 if (kret) 374 goto cleanup; 375 376 /* Initialize realm parameters */ 377 hierarchy[0] = "realms"; 378 hierarchy[1] = lrealm; 379 hierarchy[3] = (char *)NULL; 380 381 #ifdef KRB5_DNS_LOOKUP 382 /* 383 * Initialize realm info for (possible) DNS lookups. 384 */ 385 dns_realm.data = strdup(lrealm); 386 dns_realm.length = strlen(lrealm); 387 dns_realm.magic = 0; 388 #endif /* KRB5_DNS_LOOKUP */ 389 390 /* Get the value for the admin server */ 391 hierarchy[2] = "admin_server"; 392 if (params_in->mask & KADM5_CONFIG_ADMIN_SERVER) { 393 params.admin_server = strdup(params_in->admin_server); 394 if (params.admin_server) 395 params.mask |= KADM5_CONFIG_ADMIN_SERVER; 396 } else if (aprofile && 397 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { 398 params.admin_server = svalue; 399 params.mask |= KADM5_CONFIG_ADMIN_SERVER; 400 } 401 #ifdef KRB5_DNS_LOOKUP 402 else if (strcmp(envname, "KRB5_CONFIG") == 0) { 403 /* 404 * Solaris Kerberos: only do DNS lookup for admin_server if this 405 * is a krb5.conf type of config file. Note, the filename may 406 * not be /etc/krb5/krb5.conf so we assume that the KRB5_CONFIG 407 * envname string will consistently indicate the type of config 408 * file. 409 */ 410 dnsret = krb5_get_servername(context, &dns_realm, 411 "_kerberos-adm", "_udp", 412 dns_host, &dns_portno); 413 if (dnsret == 0) { 414 params.admin_server = strdup(dns_host); 415 if (params.admin_server) 416 params.mask |= KADM5_CONFIG_ADMIN_SERVER; 417 params.kadmind_port = dns_portno; 418 params.mask |= KADM5_CONFIG_KADMIND_PORT; 419 } 420 } 421 #endif /* KRB5_DNS_LOOKUP */ 422 423 if ((params.mask & KADM5_CONFIG_ADMIN_SERVER) && dnsret) { 424 char *p; 425 if (p = strchr(params.admin_server, ':')) { 426 params.kadmind_port = atoi(p+1); 427 params.mask |= KADM5_CONFIG_KADMIND_PORT; 428 *p = '\0'; 429 } 430 } 431 432 /* Get the value for the database */ 433 hierarchy[2] = "database_name"; 434 if (params_in->mask & KADM5_CONFIG_DBNAME) { 435 params.dbname = strdup(params_in->dbname); 436 if (params.dbname) 437 params.mask |= KADM5_CONFIG_DBNAME; 438 } else if (aprofile && 439 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { 440 params.dbname = svalue; 441 params.mask |= KADM5_CONFIG_DBNAME; 442 } else { 443 params.dbname = strdup(DEFAULT_KDB_FILE); 444 if (params.dbname) 445 params.mask |= KADM5_CONFIG_DBNAME; 446 } 447 448 /* 449 * admin database name and lockfile are now always derived from dbname 450 */ 451 if (params.mask & KADM5_CONFIG_DBNAME) { 452 params.admin_dbname = (char *)malloc(strlen(params.dbname) 453 + 7); 454 if (params.admin_dbname) { 455 sprintf(params.admin_dbname, "%s.kadm5", 456 params.dbname); 457 params.mask |= KADM5_CONFIG_ADBNAME; 458 } 459 } 460 461 if (params.mask & KADM5_CONFIG_ADBNAME) { 462 params.admin_lockfile = 463 (char *)malloc(strlen(params.admin_dbname)+ 6); 464 if (params.admin_lockfile) { 465 sprintf(params.admin_lockfile, "%s.lock", 466 params.admin_dbname); 467 params.mask |= KADM5_CONFIG_ADB_LOCKFILE; 468 } 469 } 470 471 /* Get the value for the admin(policy) database lock file */ 472 hierarchy[2] = "admin_keytab"; 473 if (params_in->mask & KADM5_CONFIG_ADMIN_KEYTAB) { 474 params.admin_keytab = strdup(params_in->admin_keytab); 475 if (params.admin_keytab) 476 params.mask |= KADM5_CONFIG_ADMIN_KEYTAB; 477 } else if (aprofile && 478 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { 479 params.mask |= KADM5_CONFIG_ADMIN_KEYTAB; 480 params.admin_keytab = svalue; 481 } else if (params.admin_keytab = (char *)getenv("KRB5_KTNAME")) { 482 params.admin_keytab = strdup(params.admin_keytab); 483 if (params.admin_keytab) 484 params.mask |= KADM5_CONFIG_ADMIN_KEYTAB; 485 } else { 486 params.admin_keytab = strdup(DEFAULT_KADM5_KEYTAB); 487 if (params.admin_keytab) 488 params.mask |= KADM5_CONFIG_ADMIN_KEYTAB; 489 } 490 491 /* Get the name of the acl file */ 492 hierarchy[2] = "acl_file"; 493 if (params_in->mask & KADM5_CONFIG_ACL_FILE) { 494 params.acl_file = strdup(params_in->acl_file); 495 if (params.acl_file) 496 params.mask |= KADM5_CONFIG_ACL_FILE; 497 } else if (aprofile && 498 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { 499 params.mask |= KADM5_CONFIG_ACL_FILE; 500 params.acl_file = svalue; 501 } else { 502 params.acl_file = strdup(DEFAULT_KADM5_ACL_FILE); 503 if (params.acl_file) 504 params.mask |= KADM5_CONFIG_ACL_FILE; 505 } 506 507 /* Get the name of the dict file */ 508 hierarchy[2] = "dict_file"; 509 if (params_in->mask & KADM5_CONFIG_DICT_FILE) { 510 params.dict_file = strdup(params_in->dict_file); 511 if (params.dict_file) 512 params.mask |= KADM5_CONFIG_DICT_FILE; 513 } else if (aprofile && 514 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { 515 params.mask |= KADM5_CONFIG_DICT_FILE; 516 params.dict_file = svalue; 517 } 518 519 /* Get the value for the kadmind port */ 520 if (! (params.mask & KADM5_CONFIG_KADMIND_PORT)) { 521 hierarchy[2] = "kadmind_port"; 522 if (params_in->mask & KADM5_CONFIG_KADMIND_PORT) { 523 params.mask |= KADM5_CONFIG_KADMIND_PORT; 524 params.kadmind_port = params_in->kadmind_port; 525 } else if (aprofile && 526 !krb5_aprof_get_int32(aprofile, hierarchy, TRUE, 527 &ivalue)) { 528 params.kadmind_port = ivalue; 529 params.mask |= KADM5_CONFIG_KADMIND_PORT; 530 } else { 531 params.kadmind_port = DEFAULT_KADM5_PORT; 532 params.mask |= KADM5_CONFIG_KADMIND_PORT; 533 } 534 } 535 536 /* Get the value for the master key name */ 537 hierarchy[2] = "master_key_name"; 538 if (params_in->mask & KADM5_CONFIG_MKEY_NAME) { 539 params.mkey_name = strdup(params_in->mkey_name); 540 if (params.mkey_name) 541 params.mask |= KADM5_CONFIG_MKEY_NAME; 542 } else if (aprofile && 543 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { 544 params.mask |= KADM5_CONFIG_MKEY_NAME; 545 params.mkey_name = svalue; 546 } 547 548 /* Get the value for the master key type */ 549 hierarchy[2] = "master_key_type"; 550 if (params_in->mask & KADM5_CONFIG_ENCTYPE) { 551 params.mask |= KADM5_CONFIG_ENCTYPE; 552 params.enctype = params_in->enctype; 553 } else if (aprofile && 554 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { 555 if (!krb5_string_to_enctype(svalue, ¶ms.enctype)) { 556 params.mask |= KADM5_CONFIG_ENCTYPE; 557 krb5_xfree(svalue); 558 } 559 } else { 560 params.mask |= KADM5_CONFIG_ENCTYPE; 561 params.enctype = DEFAULT_KDC_ENCTYPE; 562 } 563 564 /* Get the value for mkey_from_kbd */ 565 if (params_in->mask & KADM5_CONFIG_MKEY_FROM_KBD) { 566 params.mask |= KADM5_CONFIG_MKEY_FROM_KBD; 567 params.mkey_from_kbd = params_in->mkey_from_kbd; 568 } 569 570 /* Get the value for the stashfile */ 571 hierarchy[2] = "key_stash_file"; 572 if (params_in->mask & KADM5_CONFIG_STASH_FILE) { 573 params.stash_file = strdup(params_in->stash_file); 574 if (params.stash_file) 575 params.mask |= KADM5_CONFIG_STASH_FILE; 576 } else if (aprofile && 577 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { 578 params.mask |= KADM5_CONFIG_STASH_FILE; 579 params.stash_file = svalue; 580 } 581 582 /* 583 * Get the value for maximum ticket lifetime. 584 * See SEAM documentation or the Bug ID 4184504 585 * We have changed the logic so that the entries are 586 * created in the database with the maximum duration 587 * for life and renew life KRB5_INT32_MAX 588 * However this wil get negotiated down when 589 * as or tgs request is processed by KDC. 590 */ 591 hierarchy[2] = "max_life"; 592 if (params_in->mask & KADM5_CONFIG_MAX_LIFE) { 593 params.mask |= KADM5_CONFIG_MAX_LIFE; 594 params.max_life = params_in->max_life; 595 } else { 596 params.mask |= KADM5_CONFIG_MAX_LIFE; 597 params.max_life = KRB5_INT32_MAX; 598 } 599 600 /* Get the value for maximum renewable ticket lifetime. */ 601 hierarchy[2] = "max_renewable_life"; 602 if (params_in->mask & KADM5_CONFIG_MAX_RLIFE) { 603 params.mask |= KADM5_CONFIG_MAX_RLIFE; 604 params.max_rlife = params_in->max_rlife; 605 } else { 606 params.mask |= KADM5_CONFIG_MAX_RLIFE; 607 params.max_rlife = KRB5_INT32_MAX; 608 } 609 610 /* Get the value for the default principal expiration */ 611 hierarchy[2] = "default_principal_expiration"; 612 if (params_in->mask & KADM5_CONFIG_EXPIRATION) { 613 params.mask |= KADM5_CONFIG_EXPIRATION; 614 params.expiration = params_in->expiration; 615 } else if (aprofile && 616 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { 617 if (!krb5_string_to_timestamp(svalue, ¶ms.expiration)) { 618 params.mask |= KADM5_CONFIG_EXPIRATION; 619 krb5_xfree(svalue); 620 } 621 } else { 622 params.mask |= KADM5_CONFIG_EXPIRATION; 623 params.expiration = 0; 624 } 625 626 /* Get the value for the default principal flags */ 627 hierarchy[2] = "default_principal_flags"; 628 if (params_in->mask & KADM5_CONFIG_FLAGS) { 629 params.mask |= KADM5_CONFIG_FLAGS; 630 params.flags = params_in->flags; 631 } else if (aprofile && 632 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { 633 char *sp, *ep, *tp; 634 635 sp = svalue; 636 params.flags = 0; 637 while (sp) { 638 if ((ep = strchr(sp, (int)',')) || 639 (ep = strchr(sp, (int)' ')) || 640 (ep = strchr(sp, (int)'\t'))) { 641 /* Fill in trailing whitespace of sp */ 642 tp = ep - 1; 643 while (isspace(*tp) && (tp < sp)) { 644 *tp = '\0'; 645 tp--; 646 } 647 *ep = '\0'; 648 ep++; 649 /* Skip over trailing whitespace of ep */ 650 while (isspace(*ep) && (*ep)) ep++; 651 } 652 /* Convert this flag */ 653 if (krb5_string_to_flags(sp, 654 "+", 655 "-", 656 ¶ms.flags)) 657 break; 658 sp = ep; 659 } 660 if (!sp) 661 params.mask |= KADM5_CONFIG_FLAGS; 662 krb5_xfree(svalue); 663 } else { 664 params.mask |= KADM5_CONFIG_FLAGS; 665 params.flags = KRB5_KDB_DEF_FLAGS; 666 } 667 668 /* Get the value for the supported enctype/salttype matrix */ 669 hierarchy[2] = "supported_enctypes"; 670 if (params_in->mask & KADM5_CONFIG_ENCTYPES) { 671 params.mask |= KADM5_CONFIG_ENCTYPES; 672 if (params_in->num_keysalts > 0) { 673 params.keysalts = malloc(params_in->num_keysalts * 674 sizeof (*params.keysalts)); 675 if (params.keysalts == NULL) { 676 kret = ENOMEM; 677 goto cleanup; 678 } 679 (void) memcpy(params.keysalts, params_in->keysalts, 680 (params_in->num_keysalts * 681 sizeof (*params.keysalts))); 682 params.num_keysalts = params_in->num_keysalts; 683 } 684 } else { 685 svalue = NULL; 686 if (aprofile) 687 krb5_aprof_get_string(aprofile, hierarchy, 688 TRUE, &svalue); 689 if (svalue == NULL) 690 svalue = strdup(DEFAULT_ENCTYPE_LIST); 691 692 params.keysalts = NULL; 693 params.num_keysalts = 0; 694 krb5_string_to_keysalts(svalue, 695 ", \t", /* Tuple separators */ 696 ":.-", /* Key/salt separators */ 697 0, /* No duplicates */ 698 ¶ms.keysalts, 699 ¶ms.num_keysalts); 700 if (params.num_keysalts) 701 params.mask |= KADM5_CONFIG_ENCTYPES; 702 703 if (svalue) 704 krb5_xfree(svalue); 705 } 706 707 hierarchy[2] = "kpasswd_server"; 708 if (params_in->mask & KADM5_CONFIG_KPASSWD_SERVER) { 709 params.mask |= KADM5_CONFIG_KPASSWD_SERVER; 710 params.kpasswd_server = strdup(params_in->kpasswd_server); 711 } else { 712 svalue = NULL; 713 714 if (aprofile) 715 krb5_aprof_get_string(aprofile, hierarchy, 716 TRUE, &svalue); 717 if (svalue == NULL) { 718 #ifdef KRB5_DNS_LOOKUP 719 if (strcmp(envname, "KRB5_CONFIG") == 0) { 720 /* 721 * Solaris Kerberos: only do DNS lookup for 722 * kpasswd_server if this is a krb5.conf type of 723 * config file. Note, the filename may not be 724 * /etc/krb5/krb5.conf so we assume that the 725 * KRB5_CONFIG envname string will consistently 726 * indicate the type of config file. 727 */ 728 dnsret = krb5_get_servername(context, 729 &dns_realm, "_kpasswd", "_udp", 730 dns_host, &dns_portno); 731 732 if (dnsret == 0) { 733 params.kpasswd_server = 734 strdup(dns_host); 735 if (params.kpasswd_server) { 736 params.mask |= 737 KADM5_CONFIG_KPASSWD_SERVER; 738 } 739 params.kpasswd_port = dns_portno; 740 params.mask |= 741 KADM5_CONFIG_KPASSWD_PORT; 742 } 743 } 744 #endif /* KRB5_DNS_LOOKUP */ 745 746 /* 747 * If a unique 'kpasswd_server' is not specified, 748 * use the normal 'admin_server'. 749 */ 750 if ((params.mask & KADM5_CONFIG_ADMIN_SERVER) && 751 dnsret) { 752 params.kpasswd_server = 753 strdup(params.admin_server); 754 params.mask |= KADM5_CONFIG_KPASSWD_SERVER; 755 } 756 } else { 757 char *p; 758 params.kpasswd_server = svalue; 759 params.mask |= KADM5_CONFIG_KPASSWD_SERVER; 760 761 if ((p = strchr(params.kpasswd_server, ':'))) { 762 params.kpasswd_port = atoi(p+1); 763 params.mask |= KADM5_CONFIG_KPASSWD_PORT; 764 *p = '\0'; 765 } 766 } 767 } 768 769 hierarchy[2] = "kpasswd_protocol"; 770 771 /* default to current RPCSEC_GSS protocol */ 772 params.kpasswd_protocol = KRB5_CHGPWD_RPCSEC; 773 params.mask |= KADM5_CONFIG_KPASSWD_PROTOCOL; 774 775 if (params_in->mask & KADM5_CONFIG_KPASSWD_PROTOCOL) { 776 params.mask |= KADM5_CONFIG_KPASSWD_PROTOCOL; 777 params.kpasswd_protocol = params_in->kpasswd_protocol; 778 } else { 779 svalue = NULL; 780 781 if (aprofile) 782 krb5_aprof_get_string(aprofile, hierarchy, 783 TRUE, &svalue); 784 if (svalue != NULL) { 785 if (strcasecmp(svalue, "RPCSEC_GSS") == 0) { 786 params.kpasswd_protocol = KRB5_CHGPWD_RPCSEC; 787 params.mask |= KADM5_CONFIG_KPASSWD_PROTOCOL; 788 } else if (strcasecmp(svalue, "SET_CHANGE") == 0) { 789 params.kpasswd_protocol = 790 KRB5_CHGPWD_CHANGEPW_V2; 791 params.mask |= KADM5_CONFIG_KPASSWD_PROTOCOL; 792 } 793 } 794 if (svalue) 795 krb5_xfree(svalue); 796 } 797 798 /* 799 * If the kpasswd_port is not yet defined, define it now. 800 */ 801 if (! (params.mask & KADM5_CONFIG_KPASSWD_PORT)) { 802 if (params_in->mask & KADM5_CONFIG_KPASSWD_PORT) 803 params.kpasswd_port = params_in->kpasswd_port; 804 /* 805 * If kpasswd_port is not explicitly defined, 806 * determine the port to use based on the protocol. 807 * The alternative protocol uses a different port 808 * than the standard admind port. 809 */ 810 else if (params.kpasswd_protocol == KRB5_CHGPWD_RPCSEC) { 811 params.kpasswd_port = DEFAULT_KADM5_PORT; 812 } else { 813 /* 814 * When using the Horowitz/IETF protocol for 815 * password changing, the default port is 464 816 * (officially recognized by IANA). 817 */ 818 params.kpasswd_port = DEFAULT_KPASSWD_PORT; 819 } 820 params.mask |= KADM5_CONFIG_KPASSWD_PORT; 821 } 822 823 hierarchy[2] = "sunw_dbprop_enable"; 824 825 params.iprop_enabled = FALSE; 826 params.mask |= KADM5_CONFIG_IPROP_ENABLED; 827 828 if (params_in->mask & KADM5_CONFIG_IPROP_ENABLED) { 829 params.mask |= KADM5_CONFIG_IPROP_ENABLED; 830 params.iprop_enabled = params_in->iprop_enabled; 831 } else { 832 if (aprofile && !krb5_aprof_get_string(aprofile, hierarchy, 833 TRUE, &svalue)) { 834 if (strncasecmp(svalue, "Y", 1) == 0) 835 params.iprop_enabled = TRUE; 836 if (strncasecmp(svalue, "true", 4) == 0) 837 params.iprop_enabled = TRUE; 838 params.mask |= KADM5_CONFIG_IPROP_ENABLED; 839 krb5_xfree(svalue); 840 } 841 } 842 843 hierarchy[2] = "sunw_dbprop_master_ulogsize"; 844 845 params.iprop_ulogsize = DEF_ULOGENTRIES; 846 params.mask |= KADM5_CONFIG_ULOG_SIZE; 847 848 if (params_in->mask & KADM5_CONFIG_ULOG_SIZE) { 849 params.mask |= KADM5_CONFIG_ULOG_SIZE; 850 params.iprop_ulogsize = params_in->iprop_ulogsize; 851 } else { 852 if (aprofile && !krb5_aprof_get_int32(aprofile, hierarchy, 853 TRUE, &ivalue)) { 854 if (ivalue > MAX_ULOGENTRIES) 855 params.iprop_ulogsize = MAX_ULOGENTRIES; 856 else if (ivalue <= 0) 857 params.iprop_ulogsize = DEF_ULOGENTRIES; 858 else 859 params.iprop_ulogsize = ivalue; 860 params.mask |= KADM5_CONFIG_ULOG_SIZE; 861 } 862 } 863 864 hierarchy[2] = "sunw_dbprop_slave_poll"; 865 866 params.iprop_polltime = "2m"; 867 params.mask |= KADM5_CONFIG_POLL_TIME; 868 869 if (params_in->mask & KADM5_CONFIG_POLL_TIME) { 870 params.iprop_polltime = strdup(params_in->iprop_polltime); 871 if (params.iprop_polltime) 872 params.mask |= KADM5_CONFIG_POLL_TIME; 873 } else { 874 if (aprofile && !krb5_aprof_get_string(aprofile, hierarchy, 875 TRUE, &svalue)) { 876 params.iprop_polltime = strdup(svalue); 877 params.mask |= KADM5_CONFIG_POLL_TIME; 878 krb5_xfree(svalue); 879 } 880 } 881 882 *params_out = params; 883 884 cleanup: 885 if (aprofile) 886 krb5_aprof_finish(aprofile); 887 if (kret) { 888 (void) kadm5_free_config_params(context, ¶ms); 889 params_out->mask = 0; 890 } 891 #ifdef KRB5_DNS_LOOKUP 892 if (dns_realm.data) 893 free(dns_realm.data); 894 #endif /* KRB5_DNS_LOOKUP */ 895 896 return (kret); 897 } 898 /* 899 * kadm5_free_config_params() - Free data allocated by above. 900 */ 901 /*ARGSUSED*/ 902 krb5_error_code 903 kadm5_free_config_params(context, params) 904 krb5_context context; 905 kadm5_config_params *params; 906 { 907 if (params) { 908 if (params->profile) { 909 krb5_xfree(params->profile); 910 params->profile = NULL; 911 } 912 if (params->dbname) { 913 krb5_xfree(params->dbname); 914 params->dbname = NULL; 915 } 916 if (params->mkey_name) { 917 krb5_xfree(params->mkey_name); 918 params->mkey_name = NULL; 919 } 920 if (params->stash_file) { 921 krb5_xfree(params->stash_file); 922 params->stash_file = NULL; 923 } 924 if (params->keysalts) { 925 krb5_xfree(params->keysalts); 926 params->keysalts = NULL; 927 params->num_keysalts = 0; 928 } 929 if (params->admin_keytab) { 930 free(params->admin_keytab); 931 params->admin_keytab = NULL; 932 } 933 if (params->dict_file) { 934 free(params->dict_file); 935 params->dict_file = NULL; 936 } 937 if (params->acl_file) { 938 free(params->acl_file); 939 params->acl_file = NULL; 940 } 941 if (params->realm) { 942 free(params->realm); 943 params->realm = NULL; 944 } 945 if (params->admin_dbname) { 946 free(params->admin_dbname); 947 params->admin_dbname = NULL; 948 } 949 if (params->admin_lockfile) { 950 free(params->admin_lockfile); 951 params->admin_lockfile = NULL; 952 } 953 if (params->admin_server) { 954 free(params->admin_server); 955 params->admin_server = NULL; 956 } 957 if (params->kpasswd_server) { 958 free(params->kpasswd_server); 959 params->kpasswd_server = NULL; 960 } 961 } 962 return (0); 963 } 964 965 /* 966 * This is the old krb5_realm_read_params, which I mutated into 967 * kadm5_get_config_params but which old code(kdb5_* and krb5kdc) 968 * still uses. 969 */ 970 971 /* 972 * krb5_read_realm_params() - Read per-realm parameters from KDC 973 * alternate profile. 974 */ 975 krb5_error_code 976 krb5_read_realm_params(kcontext, realm, kdcprofile, kdcenv, rparamp) 977 krb5_context kcontext; 978 char *realm; 979 char *kdcprofile; 980 char *kdcenv; 981 krb5_realm_params **rparamp; 982 { 983 char *filename; 984 char *envname; 985 char *lrealm; 986 krb5_pointer aprofile = 0; 987 krb5_realm_params *rparams; 988 const char *hierarchy[4]; 989 char *svalue; 990 krb5_int32 ivalue; 991 krb5_deltat dtvalue; 992 993 krb5_error_code kret; 994 995 filename = (kdcprofile) ? kdcprofile : DEFAULT_KDC_PROFILE; 996 envname = (kdcenv) ? kdcenv : KDC_PROFILE_ENV; 997 998 if (kcontext->profile_secure == TRUE) envname = 0; 999 1000 rparams = (krb5_realm_params *) NULL; 1001 if (realm) 1002 lrealm = strdup(realm); 1003 else { 1004 kret = krb5_get_default_realm(kcontext, &lrealm); 1005 if (kret) 1006 goto cleanup; 1007 } 1008 1009 kret = krb5_aprof_init(filename, envname, &aprofile); 1010 if (kret) 1011 goto cleanup; 1012 1013 rparams = (krb5_realm_params *) malloc(sizeof (krb5_realm_params)); 1014 if (rparams == 0) { 1015 kret = ENOMEM; 1016 goto cleanup; 1017 } 1018 1019 /* Initialize realm parameters */ 1020 memset((char *)rparams, 0, sizeof (krb5_realm_params)); 1021 1022 /* Get the value for the database */ 1023 hierarchy[0] = "realms"; 1024 hierarchy[1] = lrealm; 1025 hierarchy[2] = "database_name"; 1026 hierarchy[3] = (char *)NULL; 1027 if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) 1028 rparams->realm_dbname = svalue; 1029 1030 /* Get the value for the KDC port list */ 1031 hierarchy[2] = "kdc_ports"; 1032 if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) 1033 rparams->realm_kdc_ports = svalue; 1034 hierarchy[2] = "kdc_tcp_ports"; 1035 if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) 1036 rparams->realm_kdc_tcp_ports = svalue; 1037 1038 /* Get the name of the acl file */ 1039 hierarchy[2] = "acl_file"; 1040 if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) 1041 rparams->realm_acl_file = svalue; 1042 1043 /* Get the value for the kadmind port */ 1044 hierarchy[2] = "kadmind_port"; 1045 if (!krb5_aprof_get_int32(aprofile, hierarchy, TRUE, &ivalue)) { 1046 rparams->realm_kadmind_port = ivalue; 1047 rparams->realm_kadmind_port_valid = 1; 1048 } 1049 1050 /* Get the value for the master key name */ 1051 hierarchy[2] = "master_key_name"; 1052 if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) 1053 rparams->realm_mkey_name = svalue; 1054 1055 /* Get the value for the master key type */ 1056 hierarchy[2] = "master_key_type"; 1057 if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { 1058 if (!krb5_string_to_enctype(svalue, &rparams->realm_enctype)) 1059 rparams->realm_enctype_valid = 1; 1060 krb5_xfree(svalue); 1061 } 1062 1063 /* Get the value for the stashfile */ 1064 hierarchy[2] = "key_stash_file"; 1065 if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) 1066 rparams->realm_stash_file = svalue; 1067 1068 /* Get the value for maximum ticket lifetime. */ 1069 hierarchy[2] = "max_life"; 1070 if (!krb5_aprof_get_deltat(aprofile, hierarchy, TRUE, &dtvalue)) { 1071 rparams->realm_max_life = dtvalue; 1072 rparams->realm_max_life_valid = 1; 1073 } 1074 1075 /* Get the value for maximum renewable ticket lifetime. */ 1076 hierarchy[2] = "max_renewable_life"; 1077 if (!krb5_aprof_get_deltat(aprofile, hierarchy, TRUE, &dtvalue)) { 1078 rparams->realm_max_rlife = dtvalue; 1079 rparams->realm_max_rlife_valid = 1; 1080 } 1081 1082 /* Get the value for the default principal expiration */ 1083 hierarchy[2] = "default_principal_expiration"; 1084 if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { 1085 if (!krb5_string_to_timestamp(svalue, 1086 &rparams->realm_expiration)) 1087 rparams->realm_expiration_valid = 1; 1088 krb5_xfree(svalue); 1089 } 1090 1091 /* Get the value for the default principal flags */ 1092 hierarchy[2] = "default_principal_flags"; 1093 if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { 1094 char *sp, *ep, *tp; 1095 1096 sp = svalue; 1097 rparams->realm_flags = 0; 1098 while (sp) { 1099 if ((ep = strchr(sp, (int)',')) || 1100 (ep = strchr(sp, (int)' ')) || 1101 (ep = strchr(sp, (int)'\t'))) { 1102 /* Fill in trailing whitespace of sp */ 1103 tp = ep - 1; 1104 while (isspace(*tp) && (tp < sp)) { 1105 *tp = '\0'; 1106 tp--; 1107 } 1108 *ep = '\0'; 1109 ep++; 1110 /* Skip over trailing whitespace of ep */ 1111 while (isspace(*ep) && (*ep)) ep++; 1112 } 1113 /* Convert this flag */ 1114 if (krb5_string_to_flags(sp, 1115 "+", 1116 "-", 1117 &rparams->realm_flags)) 1118 break; 1119 sp = ep; 1120 } 1121 if (!sp) 1122 rparams->realm_flags_valid = 1; 1123 krb5_xfree(svalue); 1124 } 1125 1126 /* Get the value for the supported enctype/salttype matrix */ 1127 /* 1128 * SUNWresync121 1129 * Solaris kerberos: updated this code to support default values for 1130 * the supported_enctypes. 1131 */ 1132 hierarchy[2] = "supported_enctypes"; 1133 svalue = NULL; 1134 krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue); 1135 1136 /* 1137 * Set the default value if supported_enctypes was not explicitly 1138 * set in the kdc.conf. 1139 */ 1140 if (svalue == NULL) { 1141 svalue = strdup(DEFAULT_ENCTYPE_LIST); 1142 } 1143 if (svalue != NULL) { 1144 krb5_string_to_keysalts(svalue, 1145 ", \t", /* Tuple separators */ 1146 ":.-", /* Key/salt separators */ 1147 0, /* No duplicates */ 1148 &rparams->realm_keysalts, 1149 &rparams->realm_num_keysalts); 1150 krb5_xfree(svalue); 1151 svalue = NULL; 1152 } 1153 1154 cleanup: 1155 if (aprofile) 1156 krb5_aprof_finish(aprofile); 1157 if (lrealm) 1158 free(lrealm); 1159 if (kret) { 1160 if (rparams) 1161 krb5_free_realm_params(kcontext, rparams); 1162 rparams = 0; 1163 } 1164 *rparamp = rparams; 1165 return (kret); 1166 } 1167 1168 /* 1169 * krb5_free_realm_params() - Free data allocated by above. 1170 */ 1171 /*ARGSUSED*/ 1172 krb5_error_code 1173 krb5_free_realm_params(kcontext, rparams) 1174 krb5_context kcontext; 1175 krb5_realm_params *rparams; 1176 { 1177 if (rparams) { 1178 if (rparams->realm_profile) 1179 krb5_xfree(rparams->realm_profile); 1180 if (rparams->realm_dbname) 1181 krb5_xfree(rparams->realm_dbname); 1182 if (rparams->realm_mkey_name) 1183 krb5_xfree(rparams->realm_mkey_name); 1184 if (rparams->realm_stash_file) 1185 krb5_xfree(rparams->realm_stash_file); 1186 if (rparams->realm_keysalts) 1187 krb5_xfree(rparams->realm_keysalts); 1188 if (rparams->realm_kdc_ports) 1189 krb5_xfree(rparams->realm_kdc_ports); 1190 krb5_xfree(rparams); 1191 } 1192 return (0); 1193 } 1194