Merge illumos-gate
[unleashed/lotheac.git] / usr / src / lib / krb5 / kadm5 / alt_prof.c
blob64359824d51c8cbed1be7037488597223040a1fc
1 /*
2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
7 /*
8 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
10 * Openvision retains the copyright to derivative works of
11 * this source code. Do *NOT* create a derivative of this
12 * source code before consulting with your legal department.
13 * Do *NOT* integrate *ANY* of this source code into another
14 * product before consulting with your legal department.
16 * For further information, read the top-level Openvision
17 * copyright which is contained in the top-level MIT Kerberos
18 * copyright.
20 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
26 * lib/kadm/alt_prof.c
28 * Copyright 1995,2001 by the Massachusetts Institute of Technology.
29 * All Rights Reserved.
31 * Export of this software from the United States of America may
32 * require a specific license from the United States Government.
33 * It is the responsibility of any person or organization contemplating
34 * export to obtain such a license before exporting.
36 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
37 * distribute this software and its documentation for any purpose and
38 * without fee is hereby granted, provided that the above copyright
39 * notice appear in all copies and that both that copyright notice and
40 * this permission notice appear in supporting documentation, and that
41 * the name of M.I.T. not be used in advertising or publicity pertaining
42 * to distribution of the software without specific, written prior
43 * permission. Furthermore if you modify this software you must label
44 * your software as modified software and not distribute it in such a
45 * fashion that it might be confused with the original M.I.T. software.
46 * M.I.T. makes no representations about the suitability of
47 * this software for any purpose. It is provided "as is" without express
48 * or implied warranty.
53 * alt_prof.c - Implement alternate profile file handling.
55 #include "k5-int.h"
56 #include <kadm5/admin.h>
57 #include "adm_proto.h"
58 #include <stdio.h>
59 #include <ctype.h>
60 #include <os-proto.h>
61 #include <kdb/kdb_log.h>
63 krb5_error_code kadm5_free_config_params();
65 #define DEFAULT_ENCTYPE_LIST \
66 "aes256-cts-hmac-sha1-96:normal " \
67 "aes128-cts-hmac-sha1-96:normal " \
68 "des3-cbc-hmac-sha1-kd:normal " \
69 "arcfour-hmac-md5:normal " \
70 "arcfour-hmac-md5-exp:normal " \
71 "des-cbc-md5:normal " \
72 "des-cbc-crc:normal"
74 static krb5_key_salt_tuple *copy_key_salt_tuple(ksalt, len)
75 krb5_key_salt_tuple *ksalt;
76 krb5_int32 len;
78 krb5_key_salt_tuple *knew;
80 if((knew = (krb5_key_salt_tuple *)
81 malloc((len ) * sizeof(krb5_key_salt_tuple)))) {
82 memcpy(knew, ksalt, len * sizeof(krb5_key_salt_tuple));
83 return knew;
85 return 0;
89 * krb5_aprof_init() - Initialize alternate profile context.
91 * Parameters:
92 * fname - default file name of the profile.
93 * envname - environment variable name which can override fname.
94 * acontextp - Pointer to opaque context for alternate profile.
96 * Returns:
97 * error codes from profile_init()
99 krb5_error_code
100 krb5_aprof_init(fname, envname, acontextp)
101 char *fname;
102 char *envname;
103 krb5_pointer *acontextp;
105 krb5_error_code kret;
106 profile_t profile;
107 const char *kdc_config;
108 size_t krb5_config_len, kdc_config_len;
109 char *profile_path;
110 char **filenames;
111 int i;
113 kret = krb5_get_default_config_files (&filenames);
114 if (kret)
115 return kret;
116 krb5_config_len = 0;
117 for (i = 0; filenames[i] != NULL; i++)
118 krb5_config_len += strlen(filenames[i]) + 1;
119 if (i > 0)
120 krb5_config_len--;
121 if (envname == NULL
122 || (kdc_config = getenv(envname)) == NULL)
123 kdc_config = fname;
124 if (kdc_config == NULL)
125 kdc_config_len = 0;
126 else
127 kdc_config_len = strlen(kdc_config);
128 profile_path = malloc(2 + krb5_config_len + kdc_config_len);
129 if (profile_path == NULL) {
130 krb5_free_config_files(filenames);
131 return errno;
133 if (kdc_config_len)
134 strcpy(profile_path, kdc_config);
135 else
136 profile_path[0] = 0;
137 if (krb5_config_len)
138 for (i = 0; filenames[i] != NULL; i++) {
139 if (kdc_config_len || i)
140 strcat(profile_path, ":");
141 strcat(profile_path, filenames[i]);
143 krb5_free_config_files(filenames);
144 profile = (profile_t) NULL;
145 kret = profile_init_path(profile_path, &profile);
146 free(profile_path);
147 if (kret)
148 return kret;
149 *acontextp = profile;
150 return 0;
154 * krb5_aprof_getvals() - Get values from alternate profile.
156 * Parameters:
157 * acontext - opaque context for alternate profile.
158 * hierarchy - hierarchy of value to retrieve.
159 * retdata - Returned data values.
161 * Returns:
162 * error codes from profile_get_values()
164 krb5_error_code
165 krb5_aprof_getvals(acontext, hierarchy, retdata)
166 krb5_pointer acontext;
167 const char **hierarchy;
168 char ***retdata;
170 return(profile_get_values((profile_t) acontext,
171 hierarchy,
172 retdata));
176 * krb5_aprof_get_boolean()
178 * Parameters:
179 * acontext - opaque context for alternate profile
180 * hierarchy - hierarchy of value to retrieve
181 * retdata - Returned data value
182 * Returns:
183 * error codes
186 static krb5_error_code
187 string_to_boolean (const char *string, krb5_boolean *out)
189 static const char *const yes[] = { "y", "yes", "true", "t", "1", "on" };
190 static const char *const no[] = { "n", "no", "false", "f", "nil", "0", "off" };
191 int i;
193 for (i = 0; i < sizeof(yes)/sizeof(yes[0]); i++)
194 if (!strcasecmp(string, yes[i])) {
195 *out = 1;
196 return 0;
198 for (i = 0; i < sizeof(no)/sizeof(no[0]); i++)
199 if (!strcasecmp(string, no[i])) {
200 *out = 0;
201 return 0;
203 return PROF_BAD_BOOLEAN;
206 krb5_error_code
207 krb5_aprof_get_boolean(krb5_pointer acontext, const char **hierarchy,
208 int uselast, krb5_boolean *retdata)
210 krb5_error_code kret;
211 char **values;
212 char *valp;
213 int idx;
214 krb5_boolean val;
216 kret = krb5_aprof_getvals (acontext, hierarchy, &values);
217 if (kret)
218 return kret;
219 idx = 0;
220 if (uselast) {
221 while (values[idx])
222 idx++;
223 idx--;
225 valp = values[idx];
226 kret = string_to_boolean (valp, &val);
227 if (kret)
228 return kret;
229 *retdata = val;
230 return 0;
234 * krb5_aprof_get_deltat() - Get a delta time value from the alternate
235 * profile.
237 * Parameters:
238 * acontext - opaque context for alternate profile.
239 * hierarchy - hierarchy of value to retrieve.
240 * uselast - if true, use last value, otherwise use
241 * first value found.
242 * deltatp - returned delta time value.
244 * Returns:
245 * error codes from profile_get_values()
246 * error codes from krb5_string_to_deltat()
248 krb5_error_code
249 krb5_aprof_get_deltat(acontext, hierarchy, uselast, deltatp)
250 krb5_pointer acontext;
251 const char **hierarchy;
252 krb5_boolean uselast;
253 krb5_deltat *deltatp;
255 krb5_error_code kret;
256 char **values;
257 char *valp;
258 int idx;
260 if (!(kret = krb5_aprof_getvals(acontext, hierarchy, &values))) {
261 idx = 0;
262 if (uselast) {
263 for (idx=0; values[idx]; idx++);
264 idx--;
266 valp = values[idx];
267 kret = krb5_string_to_deltat(valp, deltatp);
269 /* Free the string storage */
270 for (idx=0; values[idx]; idx++)
271 krb5_xfree(values[idx]);
272 krb5_xfree(values);
274 return(kret);
278 * krb5_aprof_get_string() - Get a string value from the alternate
279 * profile.
281 * Parameters:
282 * acontext - opaque context for alternate profile.
283 * hierarchy - hierarchy of value to retrieve.
284 * uselast - if true, use last value, otherwise use
285 * first value found.
286 * stringp - returned string value.
288 * Returns:
289 * error codes from profile_get_values()
291 krb5_error_code
292 krb5_aprof_get_string(acontext, hierarchy, uselast, stringp)
293 krb5_pointer acontext;
294 const char **hierarchy;
295 krb5_boolean uselast;
296 char **stringp;
298 krb5_error_code kret;
299 char **values;
300 int idx, i;
302 if (!(kret = krb5_aprof_getvals(acontext, hierarchy, &values))) {
303 idx = 0;
304 if (uselast) {
305 for (idx=0; values[idx]; idx++);
306 idx--;
309 *stringp = values[idx];
311 /* Free the string storage */
312 for (i=0; values[i]; i++)
313 if (i != idx)
314 krb5_xfree(values[i]);
315 krb5_xfree(values);
317 return(kret);
321 * krb5_aprof_get_int32() - Get a 32-bit integer value from the alternate
322 * profile.
324 * Parameters:
325 * acontext - opaque context for alternate profile.
326 * hierarchy - hierarchy of value to retrieve.
327 * uselast - if true, use last value, otherwise use
328 * first value found.
329 * intp - returned 32-bit integer value.
331 * Returns:
332 * error codes from profile_get_values()
333 * EINVAL - value is not an integer
335 krb5_error_code
336 krb5_aprof_get_int32(acontext, hierarchy, uselast, intp)
337 krb5_pointer acontext;
338 const char **hierarchy;
339 krb5_boolean uselast;
340 krb5_int32 *intp;
342 krb5_error_code kret;
343 char **values;
344 int idx;
346 if (!(kret = krb5_aprof_getvals(acontext, hierarchy, &values))) {
347 idx = 0;
348 if (uselast) {
349 for (idx=0; values[idx]; idx++);
350 idx--;
353 if (sscanf(values[idx], "%d", intp) != 1)
354 kret = EINVAL;
356 /* Free the string storage */
357 for (idx=0; values[idx]; idx++)
358 krb5_xfree(values[idx]);
359 krb5_xfree(values);
361 return(kret);
365 * krb5_aprof_finish() - Finish alternate profile context.
367 * Parameter:
368 * acontext - opaque context for alternate profile.
370 * Returns:
371 * 0 on success, something else on failure.
373 krb5_error_code
374 krb5_aprof_finish(acontext)
375 krb5_pointer acontext;
377 profile_release(acontext);
378 return(0);
382 * Function: kadm5_get_config_params
384 * Purpose: Merge configuration parameters provided by the caller with
385 * values specified in configuration files and with default values.
387 * Arguments:
389 * context (r) krb5_context to use
390 * profile (r) profile file to use
391 * envname (r) envname that contains a profile name to
392 * override profile
393 * params_in (r) params structure containing user-supplied
394 * values, or NULL
395 * params_out (w) params structure to be filled in
397 * Effects:
399 * The fields and mask of params_out are filled in with values
400 * obtained from params_in, the specified profile, and default
401 * values. Only and all fields specified in params_out->mask are
402 * set. The context of params_out must be freed with
403 * kadm5_free_config_params.
405 * params_in and params_out may be the same pointer. However, all pointers
406 * in params_in for which the mask is set will be re-assigned to newly copied
407 * versions, overwriting the old pointer value.
409 krb5_error_code kadm5_get_config_params(context, use_kdc_config,
410 params_in, params_out)
411 krb5_context context;
412 int use_kdc_config;
413 kadm5_config_params *params_in, *params_out;
415 char *filename;
416 char *envname;
417 char *lrealm;
418 krb5_pointer aprofile = 0;
419 const char *hierarchy[4];
420 char *svalue;
421 krb5_int32 ivalue;
422 kadm5_config_params params, empty_params;
424 krb5_error_code kret = 0;
425 krb5_error_code dnsret = 1;
427 #ifdef KRB5_DNS_LOOKUP
428 char dns_host[MAX_DNS_NAMELEN];
429 unsigned short dns_portno;
430 krb5_data dns_realm;
431 memset((char *)&dns_realm, 0, sizeof (dns_realm));
432 #endif /* KRB5_DNS_LOOKUP */
434 memset((char *) &params, 0, sizeof(params));
435 memset((char *) &empty_params, 0, sizeof(empty_params));
437 if (params_in == NULL) params_in = &empty_params;
439 if (params_in->mask & KADM5_CONFIG_REALM) {
440 lrealm = params.realm = strdup(params_in->realm);
441 if (params.realm)
442 params.mask |= KADM5_CONFIG_REALM;
443 } else {
444 kret = krb5_get_default_realm(context, &lrealm);
445 if (kret)
446 goto cleanup;
447 params.realm = lrealm;
448 params.mask |= KADM5_CONFIG_REALM;
451 * XXX These defaults should to work on both client and
452 * server. kadm5_get_config_params can be implemented as a
453 * wrapper function in each library that provides correct
454 * defaults for NULL values.
456 if (use_kdc_config) {
457 filename = DEFAULT_KDC_PROFILE;
458 envname = KDC_PROFILE_ENV;
459 } else {
460 filename = DEFAULT_PROFILE_PATH;
461 envname = "KRB5_CONFIG";
463 if (context->profile_secure == TRUE) envname = 0;
465 kret = krb5_aprof_init(filename, envname, &aprofile);
466 if (kret)
467 goto cleanup;
469 /* Initialize realm parameters */
470 hierarchy[0] = "realms";
471 hierarchy[1] = lrealm;
472 hierarchy[3] = (char *) NULL;
474 #ifdef KRB5_DNS_LOOKUP
476 * Initialize realm info for (possible) DNS lookups.
478 dns_realm.data = strdup(lrealm);
479 dns_realm.length = strlen(lrealm);
480 dns_realm.magic = 0;
481 #endif /* KRB5_DNS_LOOKUP */
483 /* Get the value for the admin server */
484 hierarchy[2] = "admin_server";
485 if (params_in->mask & KADM5_CONFIG_ADMIN_SERVER) {
486 params.admin_server = strdup(params_in->admin_server);
487 if (params.admin_server)
488 params.mask |= KADM5_CONFIG_ADMIN_SERVER;
489 } else if (aprofile &&
490 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
491 params.admin_server = svalue;
492 params.mask |= KADM5_CONFIG_ADMIN_SERVER;
494 #ifdef KRB5_DNS_LOOKUP
495 else if (strcmp(envname, "KRB5_CONFIG") == 0) {
497 * Solaris Kerberos: only do DNS lookup for admin_server if this
498 * is a krb5.conf type of config file. Note, the filename may
499 * not be /etc/krb5/krb5.conf so we assume that the KRB5_CONFIG
500 * envname string will consistently indicate the type of config
501 * file.
503 dnsret = krb5_get_servername(context, &dns_realm,
504 "_kerberos-adm", "_udp",
505 dns_host, &dns_portno);
506 if (dnsret == 0) {
507 params.admin_server = strdup(dns_host);
508 if (params.admin_server)
509 params.mask |= KADM5_CONFIG_ADMIN_SERVER;
510 params.kadmind_port = dns_portno;
511 params.mask |= KADM5_CONFIG_KADMIND_PORT;
514 #endif /* KRB5_DNS_LOOKUP */
516 if ((params.mask & KADM5_CONFIG_ADMIN_SERVER) && dnsret) {
517 char *p;
518 p = strchr(params.admin_server, ':');
519 if (p) {
520 params.kadmind_port = atoi(p+1);
521 params.mask |= KADM5_CONFIG_KADMIND_PORT;
522 *p = '\0';
526 /* Get the value for the database */
527 hierarchy[2] = "database_name";
528 if (params_in->mask & KADM5_CONFIG_DBNAME) {
529 params.dbname = strdup(params_in->dbname);
530 if (params.dbname)
531 params.mask |= KADM5_CONFIG_DBNAME;
532 } else if (aprofile &&
533 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
534 params.dbname = svalue;
535 params.mask |= KADM5_CONFIG_DBNAME;
536 } else {
537 params.dbname = strdup(DEFAULT_KDB_FILE);
538 if (params.dbname)
539 params.mask |= KADM5_CONFIG_DBNAME;
543 * admin database name and lockfile are now always derived from dbname
545 if (params.mask & KADM5_CONFIG_DBNAME) {
546 params.admin_dbname = (char *) malloc(strlen(params.dbname) + 7);
547 if (params.admin_dbname) {
548 sprintf(params.admin_dbname, "%s.kadm5", params.dbname);
549 params.mask |= KADM5_CONFIG_ADBNAME;
553 if (params.mask & KADM5_CONFIG_ADBNAME) {
554 params.admin_lockfile = (char *) malloc(strlen(params.admin_dbname)
555 + 6);
556 if (params.admin_lockfile) {
557 sprintf(params.admin_lockfile, "%s.lock", params.admin_dbname);
558 params.mask |= KADM5_CONFIG_ADB_LOCKFILE;
562 /* Get the value for the admin (policy) database lock file*/
563 hierarchy[2] = "admin_keytab";
564 if (params_in->mask & KADM5_CONFIG_ADMIN_KEYTAB) {
565 params.admin_keytab = strdup(params_in->admin_keytab);
566 if (params.admin_keytab)
567 params.mask |= KADM5_CONFIG_ADMIN_KEYTAB;
568 } else if (aprofile &&
569 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
570 params.mask |= KADM5_CONFIG_ADMIN_KEYTAB;
571 params.admin_keytab = svalue;
572 } else if ((params.admin_keytab = (char *) getenv("KRB5_KTNAME"))) {
573 params.admin_keytab = strdup(params.admin_keytab);
574 if (params.admin_keytab)
575 params.mask |= KADM5_CONFIG_ADMIN_KEYTAB;
576 } else {
577 params.admin_keytab = strdup(DEFAULT_KADM5_KEYTAB);
578 if (params.admin_keytab)
579 params.mask |= KADM5_CONFIG_ADMIN_KEYTAB;
582 /* Get the name of the acl file */
583 hierarchy[2] = "acl_file";
584 if (params_in->mask & KADM5_CONFIG_ACL_FILE) {
585 params.acl_file = strdup(params_in->acl_file);
586 if (params.acl_file)
587 params.mask |= KADM5_CONFIG_ACL_FILE;
588 } else if (aprofile &&
589 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
590 params.mask |= KADM5_CONFIG_ACL_FILE;
591 params.acl_file = svalue;
592 } else {
593 params.acl_file = strdup(DEFAULT_KADM5_ACL_FILE);
594 if (params.acl_file)
595 params.mask |= KADM5_CONFIG_ACL_FILE;
598 /* Get the name of the dict file */
599 hierarchy[2] = "dict_file";
600 if (params_in->mask & KADM5_CONFIG_DICT_FILE) {
601 params.dict_file = strdup(params_in->dict_file);
602 if (params.dict_file)
603 params.mask |= KADM5_CONFIG_DICT_FILE;
604 } else if (aprofile &&
605 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
606 params.mask |= KADM5_CONFIG_DICT_FILE;
607 params.dict_file = svalue;
610 /* Get the value for the kadmind port */
611 if (! (params.mask & KADM5_CONFIG_KADMIND_PORT)) {
612 hierarchy[2] = "kadmind_port";
613 if (params_in->mask & KADM5_CONFIG_KADMIND_PORT) {
614 params.mask |= KADM5_CONFIG_KADMIND_PORT;
615 params.kadmind_port = params_in->kadmind_port;
616 } else if (aprofile &&
617 !krb5_aprof_get_int32(aprofile, hierarchy, TRUE,
618 &ivalue)) {
619 params.kadmind_port = ivalue;
620 params.mask |= KADM5_CONFIG_KADMIND_PORT;
621 } else {
622 params.kadmind_port = DEFAULT_KADM5_PORT;
623 params.mask |= KADM5_CONFIG_KADMIND_PORT;
627 /* Get the value for the kpasswd port */
628 if (! (params.mask & KADM5_CONFIG_KPASSWD_PORT)) {
629 hierarchy[2] = "kpasswd_port";
630 if (params_in->mask & KADM5_CONFIG_KPASSWD_PORT) {
631 params.mask |= KADM5_CONFIG_KPASSWD_PORT;
632 params.kpasswd_port = params_in->kpasswd_port;
633 } else if (aprofile &&
634 !krb5_aprof_get_int32(aprofile, hierarchy, TRUE,
635 &ivalue)) {
636 params.kpasswd_port = ivalue;
637 params.mask |= KADM5_CONFIG_KPASSWD_PORT;
638 } else {
639 params.kpasswd_port = DEFAULT_KPASSWD_PORT;
640 params.mask |= KADM5_CONFIG_KPASSWD_PORT;
644 /* Get the value for the master key name */
645 hierarchy[2] = "master_key_name";
646 if (params_in->mask & KADM5_CONFIG_MKEY_NAME) {
647 params.mkey_name = strdup(params_in->mkey_name);
648 if (params.mkey_name)
649 params.mask |= KADM5_CONFIG_MKEY_NAME;
650 } else if (aprofile &&
651 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
652 params.mask |= KADM5_CONFIG_MKEY_NAME;
653 params.mkey_name = svalue;
656 /* Get the value for the master key type */
657 hierarchy[2] = "master_key_type";
658 if (params_in->mask & KADM5_CONFIG_ENCTYPE) {
659 params.mask |= KADM5_CONFIG_ENCTYPE;
660 params.enctype = params_in->enctype;
661 } else if (aprofile &&
662 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
663 if (!krb5_string_to_enctype(svalue, &params.enctype)) {
664 params.mask |= KADM5_CONFIG_ENCTYPE;
665 krb5_xfree(svalue);
667 } else {
668 params.mask |= KADM5_CONFIG_ENCTYPE;
669 params.enctype = DEFAULT_KDC_ENCTYPE;
672 /* Get the value for mkey_from_kbd */
673 if (params_in->mask & KADM5_CONFIG_MKEY_FROM_KBD) {
674 params.mask |= KADM5_CONFIG_MKEY_FROM_KBD;
675 params.mkey_from_kbd = params_in->mkey_from_kbd;
678 /* Get the value for the stashfile */
679 hierarchy[2] = "key_stash_file";
680 if (params_in->mask & KADM5_CONFIG_STASH_FILE) {
681 params.stash_file = strdup(params_in->stash_file);
682 if (params.stash_file)
683 params.mask |= KADM5_CONFIG_STASH_FILE;
684 } else if (aprofile &&
685 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
686 params.mask |= KADM5_CONFIG_STASH_FILE;
687 params.stash_file = svalue;
691 * Solaris Kerberos
692 * Get the value for maximum ticket lifetime.
693 * See SEAM documentation or the Bug ID 4184504
694 * We have changed the logic so that the entries are
695 * created in the database with the maximum duration
696 * for life and renew life KRB5_INT32_MAX
697 * However this wil get negotiated down when
698 * as or tgs request is processed by KDC.
700 hierarchy[2] = "max_life";
701 if (params_in->mask & KADM5_CONFIG_MAX_LIFE) {
702 params.mask |= KADM5_CONFIG_MAX_LIFE;
703 params.max_life = params_in->max_life;
704 } else {
705 params.max_life = KRB5_INT32_MAX;
706 params.mask |= KADM5_CONFIG_MAX_LIFE;
709 /* Get the value for maximum renewable ticket lifetime. */
710 hierarchy[2] = "max_renewable_life";
711 if (params_in->mask & KADM5_CONFIG_MAX_RLIFE) {
712 params.mask |= KADM5_CONFIG_MAX_RLIFE;
713 params.max_rlife = params_in->max_rlife;
714 } else {
715 params.max_rlife = KRB5_INT32_MAX;
716 params.mask |= KADM5_CONFIG_MAX_RLIFE;
719 /* Get the value for the default principal expiration */
720 hierarchy[2] = "default_principal_expiration";
721 if (params_in->mask & KADM5_CONFIG_EXPIRATION) {
722 params.mask |= KADM5_CONFIG_EXPIRATION;
723 params.expiration = params_in->expiration;
724 } else if (aprofile &&
725 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
726 if (!krb5_string_to_timestamp(svalue, &params.expiration)) {
727 params.mask |= KADM5_CONFIG_EXPIRATION;
728 krb5_xfree(svalue);
730 } else {
731 params.mask |= KADM5_CONFIG_EXPIRATION;
732 params.expiration = 0;
735 /* Get the value for the default principal flags */
736 hierarchy[2] = "default_principal_flags";
737 if (params_in->mask & KADM5_CONFIG_FLAGS) {
738 params.mask |= KADM5_CONFIG_FLAGS;
739 params.flags = params_in->flags;
740 } else if (aprofile &&
741 !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
742 char *sp, *ep, *tp;
744 sp = svalue;
745 params.flags = 0;
746 while (sp) {
747 if ((ep = strchr(sp, (int) ',')) ||
748 (ep = strchr(sp, (int) ' ')) ||
749 (ep = strchr(sp, (int) '\t'))) {
750 /* Fill in trailing whitespace of sp */
751 tp = ep - 1;
752 while (isspace((int) *tp) && (tp > sp)) {
753 *tp = '\0';
754 tp--;
756 *ep = '\0';
757 ep++;
758 /* Skip over trailing whitespace of ep */
759 while (isspace((int) *ep) && (*ep)) ep++;
761 /* Convert this flag */
762 if (krb5_string_to_flags(sp,
763 "+",
764 "-",
765 &params.flags))
766 break;
767 sp = ep;
769 if (!sp)
770 params.mask |= KADM5_CONFIG_FLAGS;
771 krb5_xfree(svalue);
772 } else {
773 params.mask |= KADM5_CONFIG_FLAGS;
774 params.flags = KRB5_KDB_DEF_FLAGS;
777 /* Get the value for the supported enctype/salttype matrix */
778 hierarchy[2] = "supported_enctypes";
779 if (params_in->mask & KADM5_CONFIG_ENCTYPES) {
780 params.mask |= KADM5_CONFIG_ENCTYPES;
781 if (params_in->num_keysalts > 0) {
782 params.keysalts = malloc(params_in->num_keysalts *
783 sizeof (*params.keysalts));
784 if (params.keysalts == NULL) {
785 kret = ENOMEM;
786 goto cleanup;
788 (void) memcpy(params.keysalts, params_in->keysalts,
789 (params_in->num_keysalts *
790 sizeof (*params.keysalts)));
791 params.num_keysalts = params_in->num_keysalts;
793 } else {
794 svalue = NULL;
795 if (aprofile)
796 krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue);
797 if (svalue == NULL)
798 svalue = strdup(DEFAULT_ENCTYPE_LIST);
800 params.keysalts = NULL;
801 params.num_keysalts = 0;
802 krb5_string_to_keysalts(svalue,
803 ", \t",/* Tuple separators */
804 ":.-", /* Key/salt separators */
805 0, /* No duplicates */
806 &params.keysalts,
807 &params.num_keysalts);
808 if (params.num_keysalts)
809 params.mask |= KADM5_CONFIG_ENCTYPES;
811 if (svalue)
812 krb5_xfree(svalue);
815 hierarchy[2] = "kpasswd_server";
816 if (params_in->mask & KADM5_CONFIG_KPASSWD_SERVER) {
817 params.mask |= KADM5_CONFIG_KPASSWD_SERVER;
818 params.kpasswd_server = strdup(params_in->kpasswd_server);
819 } else {
820 svalue = NULL;
822 if (aprofile)
823 krb5_aprof_get_string(aprofile, hierarchy,
824 TRUE, &svalue);
825 if (svalue == NULL) {
826 #ifdef KRB5_DNS_LOOKUP
827 if (strcmp(envname, "KRB5_CONFIG") == 0) {
829 * Solaris Kerberos: only do DNS lookup for
830 * kpasswd_server if this is a krb5.conf type of
831 * config file. Note, the filename may not be
832 * /etc/krb5/krb5.conf so we assume that the
833 * KRB5_CONFIG envname string will consistently
834 * indicate the type of config file.
836 dnsret = krb5_get_servername(context,
837 &dns_realm, "_kpasswd", "_udp",
838 dns_host, &dns_portno);
840 if (dnsret == 0) {
841 params.kpasswd_server =
842 strdup(dns_host);
843 if (params.kpasswd_server) {
844 params.mask |=
845 KADM5_CONFIG_KPASSWD_SERVER;
847 params.kpasswd_port = dns_portno;
848 params.mask |=
849 KADM5_CONFIG_KPASSWD_PORT;
852 #endif /* KRB5_DNS_LOOKUP */
855 * If a unique 'kpasswd_server' is not specified,
856 * use the normal 'admin_server'.
858 if ((params.mask & KADM5_CONFIG_ADMIN_SERVER) &&
859 dnsret) {
860 params.kpasswd_server =
861 strdup(params.admin_server);
862 params.mask |= KADM5_CONFIG_KPASSWD_SERVER;
864 } else {
865 char *p;
866 params.kpasswd_server = svalue;
867 params.mask |= KADM5_CONFIG_KPASSWD_SERVER;
869 if ((p = strchr(params.kpasswd_server, ':'))) {
870 params.kpasswd_port = atoi(p+1);
871 params.mask |= KADM5_CONFIG_KPASSWD_PORT;
872 *p = '\0';
877 hierarchy[2] = "kpasswd_protocol";
879 /* default to current RPCSEC_GSS protocol */
880 params.kpasswd_protocol = KRB5_CHGPWD_RPCSEC;
881 params.mask |= KADM5_CONFIG_KPASSWD_PROTOCOL;
883 if (params_in->mask & KADM5_CONFIG_KPASSWD_PROTOCOL) {
884 params.mask |= KADM5_CONFIG_KPASSWD_PROTOCOL;
885 params.kpasswd_protocol = params_in->kpasswd_protocol;
886 } else {
887 svalue = NULL;
889 if (aprofile)
890 krb5_aprof_get_string(aprofile, hierarchy,
891 TRUE, &svalue);
892 if (svalue != NULL) {
893 if (strcasecmp(svalue, "RPCSEC_GSS") == 0) {
894 params.kpasswd_protocol = KRB5_CHGPWD_RPCSEC;
895 params.mask |= KADM5_CONFIG_KPASSWD_PROTOCOL;
896 } else if (strcasecmp(svalue, "SET_CHANGE") == 0) {
897 params.kpasswd_protocol =
898 KRB5_CHGPWD_CHANGEPW_V2;
899 params.mask |= KADM5_CONFIG_KPASSWD_PROTOCOL;
902 if (svalue)
903 krb5_xfree(svalue);
907 * If the kpasswd_port is not yet defined, define it now.
909 if (! (params.mask & KADM5_CONFIG_KPASSWD_PORT)) {
910 if (params_in->mask & KADM5_CONFIG_KPASSWD_PORT)
911 params.kpasswd_port = params_in->kpasswd_port;
913 * If kpasswd_port is not explicitly defined,
914 * determine the port to use based on the protocol.
915 * The alternative protocol uses a different port
916 * than the standard admind port.
918 else if (params.kpasswd_protocol == KRB5_CHGPWD_RPCSEC) {
919 params.kpasswd_port = DEFAULT_KADM5_PORT;
920 } else {
922 * When using the Horowitz/IETF protocol for
923 * password changing, the default port is 464
924 * (officially recognized by IANA).
926 params.kpasswd_port = DEFAULT_KPASSWD_PORT;
928 params.mask |= KADM5_CONFIG_KPASSWD_PORT;
931 hierarchy[2] = "sunw_dbprop_enable";
933 params.iprop_enabled = FALSE;
934 params.mask |= KADM5_CONFIG_IPROP_ENABLED;
936 if (params_in->mask & KADM5_CONFIG_IPROP_ENABLED) {
937 params.mask |= KADM5_CONFIG_IPROP_ENABLED;
938 params.iprop_enabled = params_in->iprop_enabled;
939 } else {
940 if (aprofile && !krb5_aprof_get_string(aprofile, hierarchy,
941 TRUE, &svalue)) {
942 if (strncasecmp(svalue, "Y", 1) == 0)
943 params.iprop_enabled = TRUE;
944 if (strncasecmp(svalue, "true", 4) == 0)
945 params.iprop_enabled = TRUE;
946 params.mask |= KADM5_CONFIG_IPROP_ENABLED;
947 krb5_xfree(svalue);
951 hierarchy[2] = "sunw_dbprop_master_ulogsize";
953 params.iprop_ulogsize = DEF_ULOGENTRIES;
954 params.mask |= KADM5_CONFIG_ULOG_SIZE;
956 if (params_in->mask & KADM5_CONFIG_ULOG_SIZE) {
957 params.mask |= KADM5_CONFIG_ULOG_SIZE;
958 params.iprop_ulogsize = params_in->iprop_ulogsize;
959 } else {
960 if (aprofile && !krb5_aprof_get_int32(aprofile, hierarchy,
961 TRUE, &ivalue)) {
962 if (ivalue > MAX_ULOGENTRIES)
963 params.iprop_ulogsize = MAX_ULOGENTRIES;
964 else if (ivalue <= 0)
965 params.iprop_ulogsize = DEF_ULOGENTRIES;
966 else
967 params.iprop_ulogsize = ivalue;
968 params.mask |= KADM5_CONFIG_ULOG_SIZE;
972 hierarchy[2] = "sunw_dbprop_slave_poll";
974 params.iprop_polltime = strdup("2m");
975 if (params.iprop_polltime)
976 params.mask |= KADM5_CONFIG_POLL_TIME;
978 if (params_in->mask & KADM5_CONFIG_POLL_TIME) {
979 free(params.iprop_polltime);
980 params.iprop_polltime = strdup(params_in->iprop_polltime);
981 if (params.iprop_polltime)
982 params.mask |= KADM5_CONFIG_POLL_TIME;
983 } else {
984 if (aprofile && !krb5_aprof_get_string(aprofile, hierarchy,
985 TRUE, &svalue)) {
986 free(params.iprop_polltime);
987 params.iprop_polltime = strdup(svalue);
988 params.mask |= KADM5_CONFIG_POLL_TIME;
989 krb5_xfree(svalue);
993 *params_out = params;
995 cleanup:
996 if (aprofile)
997 krb5_aprof_finish(aprofile);
998 if (kret) {
999 kadm5_free_config_params(context, &params);
1000 params_out->mask = 0;
1002 #ifdef KRB5_DNS_LOOKUP
1003 free(dns_realm.data);
1004 #endif /* KRB5_DNS_LOOKUP */
1006 return(kret);
1009 * kadm5_free_config_params() - Free data allocated by above.
1011 /*ARGSUSED*/
1012 krb5_error_code
1013 kadm5_free_config_params(context, params)
1014 krb5_context context;
1015 kadm5_config_params *params;
1017 if (params) {
1018 if (params->dbname) {
1019 krb5_xfree(params->dbname);
1020 params->dbname = NULL;
1022 if (params->mkey_name) {
1023 krb5_xfree(params->mkey_name);
1024 params->mkey_name = NULL;
1026 if (params->stash_file) {
1027 krb5_xfree(params->stash_file);
1028 params->stash_file = NULL;
1030 if (params->keysalts) {
1031 krb5_xfree(params->keysalts);
1032 params->keysalts = NULL;
1033 params->num_keysalts = 0;
1035 if (params->admin_keytab) {
1036 free(params->admin_keytab);
1037 params->admin_keytab = NULL;
1039 if (params->dict_file) {
1040 free(params->dict_file);
1041 params->dict_file = NULL;
1043 if (params->acl_file) {
1044 free(params->acl_file);
1045 params->acl_file = NULL;
1047 if (params->realm) {
1048 free(params->realm);
1049 params->realm = NULL;
1051 if (params->admin_dbname) {
1052 free(params->admin_dbname);
1053 params->admin_dbname = NULL;
1055 if (params->admin_lockfile) {
1056 free(params->admin_lockfile);
1057 params->admin_lockfile = NULL;
1059 if (params->admin_server) {
1060 free(params->admin_server);
1061 params->admin_server = NULL;
1063 if (params->kpasswd_server) {
1064 free(params->kpasswd_server);
1065 params->kpasswd_server = NULL;
1067 if (params->iprop_polltime) {
1068 free(params->iprop_polltime);
1069 params->iprop_polltime = NULL;
1072 return (0);
1075 krb5_error_code
1076 kadm5_get_admin_service_name(krb5_context ctx,
1077 char *realm_in,
1078 char *admin_name,
1079 size_t maxlen)
1081 krb5_error_code ret;
1082 kadm5_config_params params_in, params_out;
1083 struct hostent *hp;
1085 memset(&params_in, 0, sizeof(params_in));
1086 memset(&params_out, 0, sizeof(params_out));
1088 params_in.mask |= KADM5_CONFIG_REALM;
1089 params_in.realm = realm_in;
1090 ret = kadm5_get_config_params(ctx, 0, &params_in, &params_out);
1091 if (ret)
1092 return ret;
1094 if (!(params_out.mask & KADM5_CONFIG_ADMIN_SERVER)) {
1095 ret = KADM5_MISSING_KRB5_CONF_PARAMS;
1096 goto err_params;
1099 hp = gethostbyname(params_out.admin_server);
1100 if (hp == NULL) {
1101 ret = errno;
1102 goto err_params;
1104 if (strlen(hp->h_name) + sizeof("kadmin/") > maxlen) {
1105 ret = ENOMEM;
1106 goto err_params;
1108 sprintf(admin_name, "kadmin/%s", hp->h_name);
1110 err_params:
1111 kadm5_free_config_params(ctx, &params_out);
1112 return ret;
1115 /***********************************************************************
1116 * This is the old krb5_realm_read_params, which I mutated into
1117 * kadm5_get_config_params but which old code (kdb5_* and krb5kdc)
1118 * still uses.
1119 ***********************************************************************/
1122 * krb5_read_realm_params() - Read per-realm parameters from KDC
1123 * alternate profile.
1125 krb5_error_code
1126 krb5_read_realm_params(kcontext, realm, rparamp)
1127 krb5_context kcontext;
1128 char *realm;
1129 krb5_realm_params **rparamp;
1131 char *filename;
1132 char *envname;
1133 char *lrealm;
1134 krb5_pointer aprofile = 0;
1135 krb5_realm_params *rparams;
1136 const char *hierarchy[4];
1137 char *svalue;
1138 krb5_int32 ivalue;
1139 krb5_boolean bvalue;
1140 krb5_deltat dtvalue;
1142 char *kdcprofile = 0;
1143 char *kdcenv = 0;
1145 krb5_error_code kret;
1147 filename = (kdcprofile) ? kdcprofile : DEFAULT_KDC_PROFILE;
1148 envname = (kdcenv) ? kdcenv : KDC_PROFILE_ENV;
1150 if (kcontext->profile_secure == TRUE) envname = 0;
1152 rparams = (krb5_realm_params *) NULL;
1153 if (realm)
1154 lrealm = strdup(realm);
1155 else {
1156 kret = krb5_get_default_realm(kcontext, &lrealm);
1157 if (kret)
1158 goto cleanup;
1161 kret = krb5_aprof_init(filename, envname, &aprofile);
1162 if (kret)
1163 goto cleanup;
1165 rparams = (krb5_realm_params *) malloc(sizeof(krb5_realm_params));
1166 if (rparams == 0) {
1167 kret = ENOMEM;
1168 goto cleanup;
1171 /* Initialize realm parameters */
1172 memset((char *) rparams, 0, sizeof(krb5_realm_params));
1174 /* Get the value for the database */
1175 hierarchy[0] = "realms";
1176 hierarchy[1] = lrealm;
1177 hierarchy[2] = "database_name";
1178 hierarchy[3] = (char *) NULL;
1179 if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue))
1180 rparams->realm_dbname = svalue;
1182 /* Get the value for the KDC port list */
1183 hierarchy[2] = "kdc_ports";
1184 if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue))
1185 rparams->realm_kdc_ports = svalue;
1186 hierarchy[2] = "kdc_tcp_ports";
1187 if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue))
1188 rparams->realm_kdc_tcp_ports = svalue;
1190 /* Get the name of the acl file */
1191 hierarchy[2] = "acl_file";
1192 if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue))
1193 rparams->realm_acl_file = svalue;
1195 /* Get the value for the kadmind port */
1196 hierarchy[2] = "kadmind_port";
1197 if (!krb5_aprof_get_int32(aprofile, hierarchy, TRUE, &ivalue)) {
1198 rparams->realm_kadmind_port = ivalue;
1199 rparams->realm_kadmind_port_valid = 1;
1202 /* Get the value for the master key name */
1203 hierarchy[2] = "master_key_name";
1204 if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue))
1205 rparams->realm_mkey_name = svalue;
1207 /* Get the value for the master key type */
1208 hierarchy[2] = "master_key_type";
1209 if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
1210 if (!krb5_string_to_enctype(svalue, &rparams->realm_enctype))
1211 rparams->realm_enctype_valid = 1;
1212 krb5_xfree(svalue);
1215 /* Get the value for the stashfile */
1216 hierarchy[2] = "key_stash_file";
1217 if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue))
1218 rparams->realm_stash_file = svalue;
1220 /* Get the value for maximum ticket lifetime. */
1221 hierarchy[2] = "max_life";
1222 if (!krb5_aprof_get_deltat(aprofile, hierarchy, TRUE, &dtvalue)) {
1223 rparams->realm_max_life = dtvalue;
1224 rparams->realm_max_life_valid = 1;
1227 /* Get the value for maximum renewable ticket lifetime. */
1228 hierarchy[2] = "max_renewable_life";
1229 if (!krb5_aprof_get_deltat(aprofile, hierarchy, TRUE, &dtvalue)) {
1230 rparams->realm_max_rlife = dtvalue;
1231 rparams->realm_max_rlife_valid = 1;
1234 /* Get the value for the default principal expiration */
1235 hierarchy[2] = "default_principal_expiration";
1236 if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
1237 if (!krb5_string_to_timestamp(svalue,
1238 &rparams->realm_expiration))
1239 rparams->realm_expiration_valid = 1;
1240 krb5_xfree(svalue);
1243 hierarchy[2] = "reject_bad_transit";
1244 if (!krb5_aprof_get_boolean(aprofile, hierarchy, TRUE, &bvalue)) {
1245 rparams->realm_reject_bad_transit = bvalue;
1246 rparams->realm_reject_bad_transit_valid = 1;
1249 /* Get the value for the default principal flags */
1250 hierarchy[2] = "default_principal_flags";
1251 if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
1252 char *sp, *ep, *tp;
1254 sp = svalue;
1255 rparams->realm_flags = 0;
1256 while (sp) {
1257 if ((ep = strchr(sp, (int) ',')) ||
1258 (ep = strchr(sp, (int) ' ')) ||
1259 (ep = strchr(sp, (int) '\t'))) {
1260 /* Fill in trailing whitespace of sp */
1261 tp = ep - 1;
1262 while (isspace((int) *tp) && (tp < sp)) {
1263 *tp = '\0';
1264 tp--;
1266 *ep = '\0';
1267 ep++;
1268 /* Skip over trailing whitespace of ep */
1269 while (isspace((int) *ep) && (*ep)) ep++;
1271 /* Convert this flag */
1272 if (krb5_string_to_flags(sp,
1273 "+",
1274 "-",
1275 &rparams->realm_flags))
1276 break;
1277 sp = ep;
1279 if (!sp)
1280 rparams->realm_flags_valid = 1;
1281 krb5_xfree(svalue);
1284 /* Get the value for the supported enctype/salttype matrix */
1286 * SUNWresync121
1287 * Solaris kerberos: updated this code to support default values for
1288 * the supported_enctypes.
1290 hierarchy[2] = "supported_enctypes";
1291 svalue = NULL;
1292 krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue);
1295 * Set the default value if supported_enctypes was not explicitly
1296 * set in the kdc.conf.
1298 if (svalue == NULL) {
1299 svalue = strdup(DEFAULT_ENCTYPE_LIST);
1301 if (svalue != NULL) {
1302 krb5_string_to_keysalts(svalue,
1303 ", \t", /* Tuple separators */
1304 ":.-", /* Key/salt separators */
1305 0, /* No duplicates */
1306 &rparams->realm_keysalts,
1307 &rparams->realm_num_keysalts);
1308 krb5_xfree(svalue);
1309 svalue = NULL;
1311 cleanup:
1312 if (aprofile)
1313 krb5_aprof_finish(aprofile);
1314 free(lrealm);
1315 if (kret) {
1316 if (rparams)
1317 krb5_free_realm_params(kcontext, rparams);
1318 rparams = 0;
1320 *rparamp = rparams;
1321 return(kret);
1325 * krb5_free_realm_params() - Free data allocated by above.
1327 krb5_error_code
1328 krb5_free_realm_params(kcontext, rparams)
1329 krb5_context kcontext;
1330 krb5_realm_params *rparams;
1332 if (rparams) {
1333 if (rparams->realm_profile)
1334 krb5_xfree(rparams->realm_profile);
1335 if (rparams->realm_dbname)
1336 krb5_xfree(rparams->realm_dbname);
1337 if (rparams->realm_mkey_name)
1338 krb5_xfree(rparams->realm_mkey_name);
1339 if (rparams->realm_stash_file)
1340 krb5_xfree(rparams->realm_stash_file);
1341 if (rparams->realm_keysalts)
1342 krb5_xfree(rparams->realm_keysalts);
1343 if (rparams->realm_kdc_ports)
1344 krb5_xfree(rparams->realm_kdc_ports);
1345 if (rparams->realm_kdc_tcp_ports)
1346 krb5_xfree(rparams->realm_kdc_tcp_ports);
1347 if (rparams->realm_acl_file)
1348 krb5_xfree(rparams->realm_acl_file);
1349 krb5_xfree(rparams);
1351 return(0);