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