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