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 memset((char *)&dns_realm, 0, sizeof (dns_realm)); 414 #endif /* KRB5_DNS_LOOKUP */ 415 416 memset((char *) ¶ms, 0, sizeof(params)); 417 memset((char *) &empty_params, 0, sizeof(empty_params)); 418 419 if (params_in == NULL) params_in = &empty_params; 420 421 if (params_in->mask & KADM5_CONFIG_REALM) { 422 lrealm = params.realm = strdup(params_in->realm); 423 if (params.realm) 424 params.mask |= KADM5_CONFIG_REALM; 425 } else { 426 kret = krb5_get_default_realm(context, &lrealm); 427 if (kret) 428 goto cleanup; 429 params.realm = lrealm; 430 params.mask |= KADM5_CONFIG_REALM; 431 } 432 if (params_in->mask & KADM5_CONFIG_PROFILE) { 433 filename = params.profile = strdup(params_in->profile); 434 if (params.profile) 435 params.mask |= KADM5_CONFIG_PROFILE; 436 envname = NULL; 437 } else { 438 /* 439 * XXX These defaults should to work on both client and 440 * server. kadm5_get_config_params can be implemented as a 441 * wrapper function in each library that provides correct 442 * defaults for NULL values. 443 */ 444 filename = (kdcprofile) ? kdcprofile : DEFAULT_KDC_PROFILE; 445 envname = (kdcenv) ? kdcenv : KDC_PROFILE_ENV; 446 if (context->profile_secure == TRUE) envname = 0; 447 } 448 449 kret = krb5_aprof_init(filename, envname, &aprofile); 450 if (kret) 451 goto cleanup; 452 453 /* Initialize realm parameters */ 454 hierarchy[0] = "realms"; 455 hierarchy[1] = lrealm; 456 hierarchy[3] = (char *) NULL; 457 458 #ifdef KRB5_DNS_LOOKUP 459 /* 460 * Initialize realm info for (possible) DNS lookups. 461 */ 462 dns_realm.data = strdup(lrealm); 463 dns_realm.length = strlen(lrealm); 464 dns_realm.magic = 0; 465 #endif /* KRB5_DNS_LOOKUP */ 466 467 /* Get the value for the admin server */ 468 hierarchy[2] = "admin_server"; 469 if (params_in->mask & KADM5_CONFIG_ADMIN_SERVER) { 470 params.admin_server = strdup(params_in->admin_server); 471 if (params.admin_server) 472 params.mask |= KADM5_CONFIG_ADMIN_SERVER; 473 } else if (aprofile && 474 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { 475 params.admin_server = svalue; 476 params.mask |= KADM5_CONFIG_ADMIN_SERVER; 477 } 478 #ifdef KRB5_DNS_LOOKUP 479 else if (strcmp(envname, "KRB5_CONFIG") == 0) { 480 /* 481 * Solaris Kerberos: only do DNS lookup for admin_server if this 482 * is a krb5.conf type of config file. Note, the filename may 483 * not be /etc/krb5/krb5.conf so we assume that the KRB5_CONFIG 484 * envname string will consistently indicate the type of config 485 * file. 486 */ 487 dnsret = krb5_get_servername(context, &dns_realm, 488 "_kerberos-adm", "_udp", 489 dns_host, &dns_portno); 490 if (dnsret == 0) { 491 params.admin_server = strdup(dns_host); 492 if (params.admin_server) 493 params.mask |= KADM5_CONFIG_ADMIN_SERVER; 494 params.kadmind_port = dns_portno; 495 params.mask |= KADM5_CONFIG_KADMIND_PORT; 496 } 497 } 498 #endif /* KRB5_DNS_LOOKUP */ 499 500 if ((params.mask & KADM5_CONFIG_ADMIN_SERVER) && dnsret) { 501 char *p; 502 p = strchr(params.admin_server, ':'); 503 if (p) { 504 params.kadmind_port = atoi(p+1); 505 params.mask |= KADM5_CONFIG_KADMIND_PORT; 506 *p = '\0'; 507 } 508 } 509 510 /* Get the value for the database */ 511 hierarchy[2] = "database_name"; 512 if (params_in->mask & KADM5_CONFIG_DBNAME) { 513 params.dbname = strdup(params_in->dbname); 514 if (params.dbname) 515 params.mask |= KADM5_CONFIG_DBNAME; 516 } else if (aprofile && 517 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { 518 params.dbname = svalue; 519 params.mask |= KADM5_CONFIG_DBNAME; 520 } else { 521 params.dbname = strdup(DEFAULT_KDB_FILE); 522 if (params.dbname) 523 params.mask |= KADM5_CONFIG_DBNAME; 524 } 525 526 /* 527 * admin database name and lockfile are now always derived from dbname 528 */ 529 if (params.mask & KADM5_CONFIG_DBNAME) { 530 params.admin_dbname = (char *) malloc(strlen(params.dbname) + 7); 531 if (params.admin_dbname) { 532 sprintf(params.admin_dbname, "%s.kadm5", params.dbname); 533 params.mask |= KADM5_CONFIG_ADBNAME; 534 } 535 } 536 537 if (params.mask & KADM5_CONFIG_ADBNAME) { 538 params.admin_lockfile = (char *) malloc(strlen(params.admin_dbname) 539 + 6); 540 if (params.admin_lockfile) { 541 sprintf(params.admin_lockfile, "%s.lock", params.admin_dbname); 542 params.mask |= KADM5_CONFIG_ADB_LOCKFILE; 543 } 544 } 545 546 /* Get the value for the admin (policy) database lock file*/ 547 hierarchy[2] = "admin_keytab"; 548 if (params_in->mask & KADM5_CONFIG_ADMIN_KEYTAB) { 549 params.admin_keytab = strdup(params_in->admin_keytab); 550 if (params.admin_keytab) 551 params.mask |= KADM5_CONFIG_ADMIN_KEYTAB; 552 } else if (aprofile && 553 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { 554 params.mask |= KADM5_CONFIG_ADMIN_KEYTAB; 555 params.admin_keytab = svalue; 556 } else if ((params.admin_keytab = (char *) getenv("KRB5_KTNAME"))) { 557 params.admin_keytab = strdup(params.admin_keytab); 558 if (params.admin_keytab) 559 params.mask |= KADM5_CONFIG_ADMIN_KEYTAB; 560 } else { 561 params.admin_keytab = strdup(DEFAULT_KADM5_KEYTAB); 562 if (params.admin_keytab) 563 params.mask |= KADM5_CONFIG_ADMIN_KEYTAB; 564 } 565 566 /* Get the name of the acl file */ 567 hierarchy[2] = "acl_file"; 568 if (params_in->mask & KADM5_CONFIG_ACL_FILE) { 569 params.acl_file = strdup(params_in->acl_file); 570 if (params.acl_file) 571 params.mask |= KADM5_CONFIG_ACL_FILE; 572 } else if (aprofile && 573 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { 574 params.mask |= KADM5_CONFIG_ACL_FILE; 575 params.acl_file = svalue; 576 } else { 577 params.acl_file = strdup(DEFAULT_KADM5_ACL_FILE); 578 if (params.acl_file) 579 params.mask |= KADM5_CONFIG_ACL_FILE; 580 } 581 582 /* Get the name of the dict file */ 583 hierarchy[2] = "dict_file"; 584 if (params_in->mask & KADM5_CONFIG_DICT_FILE) { 585 params.dict_file = strdup(params_in->dict_file); 586 if (params.dict_file) 587 params.mask |= KADM5_CONFIG_DICT_FILE; 588 } else if (aprofile && 589 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { 590 params.mask |= KADM5_CONFIG_DICT_FILE; 591 params.dict_file = svalue; 592 } 593 594 /* Get the value for the kadmind port */ 595 if (! (params.mask & KADM5_CONFIG_KADMIND_PORT)) { 596 hierarchy[2] = "kadmind_port"; 597 if (params_in->mask & KADM5_CONFIG_KADMIND_PORT) { 598 params.mask |= KADM5_CONFIG_KADMIND_PORT; 599 params.kadmind_port = params_in->kadmind_port; 600 } else if (aprofile && 601 !krb5_aprof_get_int32(aprofile, hierarchy, TRUE, 602 &ivalue)) { 603 params.kadmind_port = ivalue; 604 params.mask |= KADM5_CONFIG_KADMIND_PORT; 605 } else { 606 params.kadmind_port = DEFAULT_KADM5_PORT; 607 params.mask |= KADM5_CONFIG_KADMIND_PORT; 608 } 609 } 610 611 /* Get the value for the kpasswd port */ 612 if (! (params.mask & KADM5_CONFIG_KPASSWD_PORT)) { 613 hierarchy[2] = "kpasswd_port"; 614 if (params_in->mask & KADM5_CONFIG_KPASSWD_PORT) { 615 params.mask |= KADM5_CONFIG_KPASSWD_PORT; 616 params.kpasswd_port = params_in->kpasswd_port; 617 } else if (aprofile && 618 !krb5_aprof_get_int32(aprofile, hierarchy, TRUE, 619 &ivalue)) { 620 params.kpasswd_port = ivalue; 621 params.mask |= KADM5_CONFIG_KPASSWD_PORT; 622 } else { 623 params.kpasswd_port = DEFAULT_KPASSWD_PORT; 624 params.mask |= KADM5_CONFIG_KPASSWD_PORT; 625 } 626 } 627 628 /* Get the value for the master key name */ 629 hierarchy[2] = "master_key_name"; 630 if (params_in->mask & KADM5_CONFIG_MKEY_NAME) { 631 params.mkey_name = strdup(params_in->mkey_name); 632 if (params.mkey_name) 633 params.mask |= KADM5_CONFIG_MKEY_NAME; 634 } else if (aprofile && 635 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { 636 params.mask |= KADM5_CONFIG_MKEY_NAME; 637 params.mkey_name = svalue; 638 } 639 640 /* Get the value for the master key type */ 641 hierarchy[2] = "master_key_type"; 642 if (params_in->mask & KADM5_CONFIG_ENCTYPE) { 643 params.mask |= KADM5_CONFIG_ENCTYPE; 644 params.enctype = params_in->enctype; 645 } else if (aprofile && 646 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { 647 if (!krb5_string_to_enctype(svalue, ¶ms.enctype)) { 648 params.mask |= KADM5_CONFIG_ENCTYPE; 649 krb5_xfree(svalue); 650 } 651 } else { 652 params.mask |= KADM5_CONFIG_ENCTYPE; 653 params.enctype = DEFAULT_KDC_ENCTYPE; 654 } 655 656 /* Get the value for mkey_from_kbd */ 657 if (params_in->mask & KADM5_CONFIG_MKEY_FROM_KBD) { 658 params.mask |= KADM5_CONFIG_MKEY_FROM_KBD; 659 params.mkey_from_kbd = params_in->mkey_from_kbd; 660 } 661 662 /* Get the value for the stashfile */ 663 hierarchy[2] = "key_stash_file"; 664 if (params_in->mask & KADM5_CONFIG_STASH_FILE) { 665 params.stash_file = strdup(params_in->stash_file); 666 if (params.stash_file) 667 params.mask |= KADM5_CONFIG_STASH_FILE; 668 } else if (aprofile && 669 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { 670 params.mask |= KADM5_CONFIG_STASH_FILE; 671 params.stash_file = svalue; 672 } 673 674 /* 675 * Get the value for maximum ticket lifetime. 676 * See SEAM documentation or the Bug ID 4184504 677 * We have changed the logic so that the entries are 678 * created in the database with the maximum duration 679 * for life and renew life KRB5_INT32_MAX 680 * However this wil get negotiated down when 681 * as or tgs request is processed by KDC. 682 */ 683 hierarchy[2] = "max_life"; 684 if (params_in->mask & KADM5_CONFIG_MAX_LIFE) { 685 params.mask |= KADM5_CONFIG_MAX_LIFE; 686 params.max_life = params_in->max_life; 687 } else { 688 params.max_life = KRB5_INT32_MAX; 689 params.mask |= KADM5_CONFIG_MAX_LIFE; 690 } 691 692 /* Get the value for maximum renewable ticket lifetime. */ 693 hierarchy[2] = "max_renewable_life"; 694 if (params_in->mask & KADM5_CONFIG_MAX_RLIFE) { 695 params.mask |= KADM5_CONFIG_MAX_RLIFE; 696 params.max_rlife = params_in->max_rlife; 697 } else { 698 params.max_rlife = KRB5_INT32_MAX; 699 params.mask |= KADM5_CONFIG_MAX_RLIFE; 700 } 701 702 /* Get the value for the default principal expiration */ 703 hierarchy[2] = "default_principal_expiration"; 704 if (params_in->mask & KADM5_CONFIG_EXPIRATION) { 705 params.mask |= KADM5_CONFIG_EXPIRATION; 706 params.expiration = params_in->expiration; 707 } else if (aprofile && 708 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { 709 if (!krb5_string_to_timestamp(svalue, ¶ms.expiration)) { 710 params.mask |= KADM5_CONFIG_EXPIRATION; 711 krb5_xfree(svalue); 712 } 713 } else { 714 params.mask |= KADM5_CONFIG_EXPIRATION; 715 params.expiration = 0; 716 } 717 718 /* Get the value for the default principal flags */ 719 hierarchy[2] = "default_principal_flags"; 720 if (params_in->mask & KADM5_CONFIG_FLAGS) { 721 params.mask |= KADM5_CONFIG_FLAGS; 722 params.flags = params_in->flags; 723 } else if (aprofile && 724 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { 725 char *sp, *ep, *tp; 726 727 sp = svalue; 728 params.flags = 0; 729 while (sp) { 730 if ((ep = strchr(sp, (int) ',')) || 731 (ep = strchr(sp, (int) ' ')) || 732 (ep = strchr(sp, (int) '\t'))) { 733 /* Fill in trailing whitespace of sp */ 734 tp = ep - 1; 735 while (isspace((int) *tp) && (tp > sp)) { 736 *tp = '\0'; 737 tp--; 738 } 739 *ep = '\0'; 740 ep++; 741 /* Skip over trailing whitespace of ep */ 742 while (isspace((int) *ep) && (*ep)) ep++; 743 } 744 /* Convert this flag */ 745 if (krb5_string_to_flags(sp, 746 "+", 747 "-", 748 ¶ms.flags)) 749 break; 750 sp = ep; 751 } 752 if (!sp) 753 params.mask |= KADM5_CONFIG_FLAGS; 754 krb5_xfree(svalue); 755 } else { 756 params.mask |= KADM5_CONFIG_FLAGS; 757 params.flags = KRB5_KDB_DEF_FLAGS; 758 } 759 760 /* Get the value for the supported enctype/salttype matrix */ 761 hierarchy[2] = "supported_enctypes"; 762 if (params_in->mask & KADM5_CONFIG_ENCTYPES) { 763 params.mask |= KADM5_CONFIG_ENCTYPES; 764 if (params_in->num_keysalts > 0) { 765 params.keysalts = malloc(params_in->num_keysalts * 766 sizeof (*params.keysalts)); 767 if (params.keysalts == NULL) { 768 kret = ENOMEM; 769 goto cleanup; 770 } 771 (void) memcpy(params.keysalts, params_in->keysalts, 772 (params_in->num_keysalts * 773 sizeof (*params.keysalts))); 774 params.num_keysalts = params_in->num_keysalts; 775 } 776 } else { 777 svalue = NULL; 778 if (aprofile) 779 krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue); 780 if (svalue == NULL) 781 svalue = strdup(DEFAULT_ENCTYPE_LIST); 782 783 params.keysalts = NULL; 784 params.num_keysalts = 0; 785 krb5_string_to_keysalts(svalue, 786 ", \t",/* Tuple separators */ 787 ":.-", /* Key/salt separators */ 788 0, /* No duplicates */ 789 ¶ms.keysalts, 790 ¶ms.num_keysalts); 791 if (params.num_keysalts) 792 params.mask |= KADM5_CONFIG_ENCTYPES; 793 794 if (svalue) 795 krb5_xfree(svalue); 796 } 797 798 hierarchy[2] = "kpasswd_server"; 799 if (params_in->mask & KADM5_CONFIG_KPASSWD_SERVER) { 800 params.mask |= KADM5_CONFIG_KPASSWD_SERVER; 801 params.kpasswd_server = strdup(params_in->kpasswd_server); 802 } else { 803 svalue = NULL; 804 805 if (aprofile) 806 krb5_aprof_get_string(aprofile, hierarchy, 807 TRUE, &svalue); 808 if (svalue == NULL) { 809 #ifdef KRB5_DNS_LOOKUP 810 if (strcmp(envname, "KRB5_CONFIG") == 0) { 811 /* 812 * Solaris Kerberos: only do DNS lookup for 813 * kpasswd_server if this is a krb5.conf type of 814 * config file. Note, the filename may not be 815 * /etc/krb5/krb5.conf so we assume that the 816 * KRB5_CONFIG envname string will consistently 817 * indicate the type of config file. 818 */ 819 dnsret = krb5_get_servername(context, 820 &dns_realm, "_kpasswd", "_udp", 821 dns_host, &dns_portno); 822 823 if (dnsret == 0) { 824 params.kpasswd_server = 825 strdup(dns_host); 826 if (params.kpasswd_server) { 827 params.mask |= 828 KADM5_CONFIG_KPASSWD_SERVER; 829 } 830 params.kpasswd_port = dns_portno; 831 params.mask |= 832 KADM5_CONFIG_KPASSWD_PORT; 833 } 834 } 835 #endif /* KRB5_DNS_LOOKUP */ 836 837 /* 838 * If a unique 'kpasswd_server' is not specified, 839 * use the normal 'admin_server'. 840 */ 841 if ((params.mask & KADM5_CONFIG_ADMIN_SERVER) && 842 dnsret) { 843 params.kpasswd_server = 844 strdup(params.admin_server); 845 params.mask |= KADM5_CONFIG_KPASSWD_SERVER; 846 } 847 } else { 848 char *p; 849 params.kpasswd_server = svalue; 850 params.mask |= KADM5_CONFIG_KPASSWD_SERVER; 851 852 if ((p = strchr(params.kpasswd_server, ':'))) { 853 params.kpasswd_port = atoi(p+1); 854 params.mask |= KADM5_CONFIG_KPASSWD_PORT; 855 *p = '\0'; 856 } 857 } 858 } 859 860 hierarchy[2] = "kpasswd_protocol"; 861 862 /* default to current RPCSEC_GSS protocol */ 863 params.kpasswd_protocol = KRB5_CHGPWD_RPCSEC; 864 params.mask |= KADM5_CONFIG_KPASSWD_PROTOCOL; 865 866 if (params_in->mask & KADM5_CONFIG_KPASSWD_PROTOCOL) { 867 params.mask |= KADM5_CONFIG_KPASSWD_PROTOCOL; 868 params.kpasswd_protocol = params_in->kpasswd_protocol; 869 } else { 870 svalue = NULL; 871 872 if (aprofile) 873 krb5_aprof_get_string(aprofile, hierarchy, 874 TRUE, &svalue); 875 if (svalue != NULL) { 876 if (strcasecmp(svalue, "RPCSEC_GSS") == 0) { 877 params.kpasswd_protocol = KRB5_CHGPWD_RPCSEC; 878 params.mask |= KADM5_CONFIG_KPASSWD_PROTOCOL; 879 } else if (strcasecmp(svalue, "SET_CHANGE") == 0) { 880 params.kpasswd_protocol = 881 KRB5_CHGPWD_CHANGEPW_V2; 882 params.mask |= KADM5_CONFIG_KPASSWD_PROTOCOL; 883 } 884 } 885 if (svalue) 886 krb5_xfree(svalue); 887 } 888 889 /* 890 * If the kpasswd_port is not yet defined, define it now. 891 */ 892 if (! (params.mask & KADM5_CONFIG_KPASSWD_PORT)) { 893 if (params_in->mask & KADM5_CONFIG_KPASSWD_PORT) 894 params.kpasswd_port = params_in->kpasswd_port; 895 /* 896 * If kpasswd_port is not explicitly defined, 897 * determine the port to use based on the protocol. 898 * The alternative protocol uses a different port 899 * than the standard admind port. 900 */ 901 else if (params.kpasswd_protocol == KRB5_CHGPWD_RPCSEC) { 902 params.kpasswd_port = DEFAULT_KADM5_PORT; 903 } else { 904 /* 905 * When using the Horowitz/IETF protocol for 906 * password changing, the default port is 464 907 * (officially recognized by IANA). 908 */ 909 params.kpasswd_port = DEFAULT_KPASSWD_PORT; 910 } 911 params.mask |= KADM5_CONFIG_KPASSWD_PORT; 912 } 913 914 hierarchy[2] = "sunw_dbprop_enable"; 915 916 params.iprop_enabled = FALSE; 917 params.mask |= KADM5_CONFIG_IPROP_ENABLED; 918 919 if (params_in->mask & KADM5_CONFIG_IPROP_ENABLED) { 920 params.mask |= KADM5_CONFIG_IPROP_ENABLED; 921 params.iprop_enabled = params_in->iprop_enabled; 922 } else { 923 if (aprofile && !krb5_aprof_get_string(aprofile, hierarchy, 924 TRUE, &svalue)) { 925 if (strncasecmp(svalue, "Y", 1) == 0) 926 params.iprop_enabled = TRUE; 927 if (strncasecmp(svalue, "true", 4) == 0) 928 params.iprop_enabled = TRUE; 929 params.mask |= KADM5_CONFIG_IPROP_ENABLED; 930 krb5_xfree(svalue); 931 } 932 } 933 934 hierarchy[2] = "sunw_dbprop_master_ulogsize"; 935 936 params.iprop_ulogsize = DEF_ULOGENTRIES; 937 params.mask |= KADM5_CONFIG_ULOG_SIZE; 938 939 if (params_in->mask & KADM5_CONFIG_ULOG_SIZE) { 940 params.mask |= KADM5_CONFIG_ULOG_SIZE; 941 params.iprop_ulogsize = params_in->iprop_ulogsize; 942 } else { 943 if (aprofile && !krb5_aprof_get_int32(aprofile, hierarchy, 944 TRUE, &ivalue)) { 945 if (ivalue > MAX_ULOGENTRIES) 946 params.iprop_ulogsize = MAX_ULOGENTRIES; 947 else if (ivalue <= 0) 948 params.iprop_ulogsize = DEF_ULOGENTRIES; 949 else 950 params.iprop_ulogsize = ivalue; 951 params.mask |= KADM5_CONFIG_ULOG_SIZE; 952 } 953 } 954 955 hierarchy[2] = "sunw_dbprop_slave_poll"; 956 957 params.iprop_polltime = "2m"; 958 params.mask |= KADM5_CONFIG_POLL_TIME; 959 960 if (params_in->mask & KADM5_CONFIG_POLL_TIME) { 961 params.iprop_polltime = strdup(params_in->iprop_polltime); 962 if (params.iprop_polltime) 963 params.mask |= KADM5_CONFIG_POLL_TIME; 964 } else { 965 if (aprofile && !krb5_aprof_get_string(aprofile, hierarchy, 966 TRUE, &svalue)) { 967 params.iprop_polltime = strdup(svalue); 968 params.mask |= KADM5_CONFIG_POLL_TIME; 969 krb5_xfree(svalue); 970 } 971 } 972 973 *params_out = params; 974 975 cleanup: 976 if (aprofile) 977 krb5_aprof_finish(aprofile); 978 if (kret) { 979 kadm5_free_config_params(context, ¶ms); 980 params_out->mask = 0; 981 } 982 #ifdef KRB5_DNS_LOOKUP 983 if (dns_realm.data) 984 free(dns_realm.data); 985 #endif /* KRB5_DNS_LOOKUP */ 986 987 return(kret); 988 } 989 /* 990 * kadm5_free_config_params() - Free data allocated by above. 991 */ 992 /*ARGSUSED*/ 993 krb5_error_code 994 kadm5_free_config_params(context, params) 995 krb5_context context; 996 kadm5_config_params *params; 997 { 998 if (params) { 999 if (params->profile) { 1000 krb5_xfree(params->profile); 1001 params->profile = NULL; 1002 } 1003 if (params->dbname) { 1004 krb5_xfree(params->dbname); 1005 params->dbname = NULL; 1006 } 1007 if (params->mkey_name) { 1008 krb5_xfree(params->mkey_name); 1009 params->mkey_name = NULL; 1010 } 1011 if (params->stash_file) { 1012 krb5_xfree(params->stash_file); 1013 params->stash_file = NULL; 1014 } 1015 if (params->keysalts) { 1016 krb5_xfree(params->keysalts); 1017 params->keysalts = NULL; 1018 params->num_keysalts = 0; 1019 } 1020 if (params->admin_keytab) { 1021 free(params->admin_keytab); 1022 params->admin_keytab = NULL; 1023 } 1024 if (params->dict_file) { 1025 free(params->dict_file); 1026 params->dict_file = NULL; 1027 } 1028 if (params->acl_file) { 1029 free(params->acl_file); 1030 params->acl_file = NULL; 1031 } 1032 if (params->realm) { 1033 free(params->realm); 1034 params->realm = NULL; 1035 } 1036 if (params->admin_dbname) { 1037 free(params->admin_dbname); 1038 params->admin_dbname = NULL; 1039 } 1040 if (params->admin_lockfile) { 1041 free(params->admin_lockfile); 1042 params->admin_lockfile = NULL; 1043 } 1044 if (params->admin_server) { 1045 free(params->admin_server); 1046 params->admin_server = NULL; 1047 } 1048 if (params->kpasswd_server) { 1049 free(params->kpasswd_server); 1050 params->kpasswd_server = NULL; 1051 } 1052 } 1053 return (0); 1054 } 1055 1056 krb5_error_code 1057 kadm5_get_admin_service_name(krb5_context ctx, 1058 char *realm_in, 1059 char *admin_name, 1060 size_t maxlen) 1061 { 1062 krb5_error_code ret; 1063 kadm5_config_params params_in, params_out; 1064 struct hostent *hp; 1065 1066 memset(¶ms_in, 0, sizeof(params_in)); 1067 memset(¶ms_out, 0, sizeof(params_out)); 1068 1069 params_in.mask |= KADM5_CONFIG_REALM; 1070 params_in.realm = realm_in; 1071 ret = kadm5_get_config_params(ctx, DEFAULT_PROFILE_PATH, 1072 "KRB5_CONFIG", ¶ms_in, ¶ms_out); 1073 if (ret) 1074 return ret; 1075 1076 if (!(params_out.mask & KADM5_CONFIG_ADMIN_SERVER)) { 1077 ret = KADM5_MISSING_KRB5_CONF_PARAMS; 1078 goto err_params; 1079 } 1080 1081 hp = gethostbyname(params_out.admin_server); 1082 if (hp == NULL) { 1083 ret = errno; 1084 goto err_params; 1085 } 1086 if (strlen(hp->h_name) + sizeof("kadmin/") > maxlen) { 1087 ret = ENOMEM; 1088 goto err_params; 1089 } 1090 sprintf(admin_name, "kadmin/%s", hp->h_name); 1091 1092 err_params: 1093 kadm5_free_config_params(ctx, ¶ms_out); 1094 return ret; 1095 } 1096 1097 /*********************************************************************** 1098 * This is the old krb5_realm_read_params, which I mutated into 1099 * kadm5_get_config_params but which old code (kdb5_* and krb5kdc) 1100 * still uses. 1101 ***********************************************************************/ 1102 1103 /* 1104 * krb5_read_realm_params() - Read per-realm parameters from KDC 1105 * alternate profile. 1106 */ 1107 krb5_error_code 1108 krb5_read_realm_params(kcontext, realm, kdcprofile, kdcenv, rparamp) 1109 krb5_context kcontext; 1110 char *realm; 1111 char *kdcprofile; 1112 char *kdcenv; 1113 krb5_realm_params **rparamp; 1114 { 1115 char *filename; 1116 char *envname; 1117 char *lrealm; 1118 krb5_pointer aprofile = 0; 1119 krb5_realm_params *rparams; 1120 const char *hierarchy[4]; 1121 char *svalue; 1122 krb5_int32 ivalue; 1123 krb5_boolean bvalue; 1124 krb5_deltat dtvalue; 1125 1126 krb5_error_code kret; 1127 1128 filename = (kdcprofile) ? kdcprofile : DEFAULT_KDC_PROFILE; 1129 envname = (kdcenv) ? kdcenv : KDC_PROFILE_ENV; 1130 1131 if (kcontext->profile_secure == TRUE) envname = 0; 1132 1133 rparams = (krb5_realm_params *) NULL; 1134 if (realm) 1135 lrealm = strdup(realm); 1136 else { 1137 kret = krb5_get_default_realm(kcontext, &lrealm); 1138 if (kret) 1139 goto cleanup; 1140 } 1141 1142 kret = krb5_aprof_init(filename, envname, &aprofile); 1143 if (kret) 1144 goto cleanup; 1145 1146 rparams = (krb5_realm_params *) malloc(sizeof(krb5_realm_params)); 1147 if (rparams == 0) { 1148 kret = ENOMEM; 1149 goto cleanup; 1150 } 1151 1152 /* Initialize realm parameters */ 1153 memset((char *) rparams, 0, sizeof(krb5_realm_params)); 1154 1155 /* Get the value for the database */ 1156 hierarchy[0] = "realms"; 1157 hierarchy[1] = lrealm; 1158 hierarchy[2] = "database_name"; 1159 hierarchy[3] = (char *) NULL; 1160 if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) 1161 rparams->realm_dbname = svalue; 1162 1163 /* Get the value for the KDC port list */ 1164 hierarchy[2] = "kdc_ports"; 1165 if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) 1166 rparams->realm_kdc_ports = svalue; 1167 hierarchy[2] = "kdc_tcp_ports"; 1168 if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) 1169 rparams->realm_kdc_tcp_ports = svalue; 1170 1171 /* Get the name of the acl file */ 1172 hierarchy[2] = "acl_file"; 1173 if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) 1174 rparams->realm_acl_file = svalue; 1175 1176 /* Get the value for the kadmind port */ 1177 hierarchy[2] = "kadmind_port"; 1178 if (!krb5_aprof_get_int32(aprofile, hierarchy, TRUE, &ivalue)) { 1179 rparams->realm_kadmind_port = ivalue; 1180 rparams->realm_kadmind_port_valid = 1; 1181 } 1182 1183 /* Get the value for the master key name */ 1184 hierarchy[2] = "master_key_name"; 1185 if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) 1186 rparams->realm_mkey_name = svalue; 1187 1188 /* Get the value for the master key type */ 1189 hierarchy[2] = "master_key_type"; 1190 if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { 1191 if (!krb5_string_to_enctype(svalue, &rparams->realm_enctype)) 1192 rparams->realm_enctype_valid = 1; 1193 krb5_xfree(svalue); 1194 } 1195 1196 /* Get the value for the stashfile */ 1197 hierarchy[2] = "key_stash_file"; 1198 if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) 1199 rparams->realm_stash_file = svalue; 1200 1201 /* Get the value for maximum ticket lifetime. */ 1202 hierarchy[2] = "max_life"; 1203 if (!krb5_aprof_get_deltat(aprofile, hierarchy, TRUE, &dtvalue)) { 1204 rparams->realm_max_life = dtvalue; 1205 rparams->realm_max_life_valid = 1; 1206 } 1207 1208 /* Get the value for maximum renewable ticket lifetime. */ 1209 hierarchy[2] = "max_renewable_life"; 1210 if (!krb5_aprof_get_deltat(aprofile, hierarchy, TRUE, &dtvalue)) { 1211 rparams->realm_max_rlife = dtvalue; 1212 rparams->realm_max_rlife_valid = 1; 1213 } 1214 1215 /* Get the value for the default principal expiration */ 1216 hierarchy[2] = "default_principal_expiration"; 1217 if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { 1218 if (!krb5_string_to_timestamp(svalue, 1219 &rparams->realm_expiration)) 1220 rparams->realm_expiration_valid = 1; 1221 krb5_xfree(svalue); 1222 } 1223 1224 hierarchy[2] = "reject_bad_transit"; 1225 if (!krb5_aprof_get_boolean(aprofile, hierarchy, TRUE, &bvalue)) { 1226 rparams->realm_reject_bad_transit = bvalue; 1227 rparams->realm_reject_bad_transit_valid = 1; 1228 } 1229 1230 /* Get the value for the default principal flags */ 1231 hierarchy[2] = "default_principal_flags"; 1232 if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { 1233 char *sp, *ep, *tp; 1234 1235 sp = svalue; 1236 rparams->realm_flags = 0; 1237 while (sp) { 1238 if ((ep = strchr(sp, (int) ',')) || 1239 (ep = strchr(sp, (int) ' ')) || 1240 (ep = strchr(sp, (int) '\t'))) { 1241 /* Fill in trailing whitespace of sp */ 1242 tp = ep - 1; 1243 while (isspace((int) *tp) && (tp < sp)) { 1244 *tp = '\0'; 1245 tp--; 1246 } 1247 *ep = '\0'; 1248 ep++; 1249 /* Skip over trailing whitespace of ep */ 1250 while (isspace((int) *ep) && (*ep)) ep++; 1251 } 1252 /* Convert this flag */ 1253 if (krb5_string_to_flags(sp, 1254 "+", 1255 "-", 1256 &rparams->realm_flags)) 1257 break; 1258 sp = ep; 1259 } 1260 if (!sp) 1261 rparams->realm_flags_valid = 1; 1262 krb5_xfree(svalue); 1263 } 1264 1265 /* Get the value for the supported enctype/salttype matrix */ 1266 /* 1267 * SUNWresync121 1268 * Solaris kerberos: updated this code to support default values for 1269 * the supported_enctypes. 1270 */ 1271 hierarchy[2] = "supported_enctypes"; 1272 svalue = NULL; 1273 krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue); 1274 1275 /* 1276 * Set the default value if supported_enctypes was not explicitly 1277 * set in the kdc.conf. 1278 */ 1279 if (svalue == NULL) { 1280 svalue = strdup(DEFAULT_ENCTYPE_LIST); 1281 } 1282 if (svalue != NULL) { 1283 krb5_string_to_keysalts(svalue, 1284 ", \t", /* Tuple separators */ 1285 ":.-", /* Key/salt separators */ 1286 0, /* No duplicates */ 1287 &rparams->realm_keysalts, 1288 &rparams->realm_num_keysalts); 1289 krb5_xfree(svalue); 1290 svalue = NULL; 1291 } 1292 cleanup: 1293 if (aprofile) 1294 krb5_aprof_finish(aprofile); 1295 if (lrealm) 1296 free(lrealm); 1297 if (kret) { 1298 if (rparams) 1299 krb5_free_realm_params(kcontext, rparams); 1300 rparams = 0; 1301 } 1302 *rparamp = rparams; 1303 return(kret); 1304 } 1305 1306 /* 1307 * krb5_free_realm_params() - Free data allocated by above. 1308 */ 1309 krb5_error_code 1310 krb5_free_realm_params(kcontext, rparams) 1311 krb5_context kcontext; 1312 krb5_realm_params *rparams; 1313 { 1314 if (rparams) { 1315 if (rparams->realm_profile) 1316 krb5_xfree(rparams->realm_profile); 1317 if (rparams->realm_dbname) 1318 krb5_xfree(rparams->realm_dbname); 1319 if (rparams->realm_mkey_name) 1320 krb5_xfree(rparams->realm_mkey_name); 1321 if (rparams->realm_stash_file) 1322 krb5_xfree(rparams->realm_stash_file); 1323 if (rparams->realm_keysalts) 1324 krb5_xfree(rparams->realm_keysalts); 1325 if (rparams->realm_kdc_ports) 1326 krb5_xfree(rparams->realm_kdc_ports); 1327 if (rparams->realm_kdc_tcp_ports) 1328 krb5_xfree(rparams->realm_kdc_tcp_ports); 1329 if (rparams->realm_acl_file) 1330 krb5_xfree(rparams->realm_acl_file); 1331 krb5_xfree(rparams); 1332 } 1333 return(0); 1334 } 1335 1336