xref: /illumos-gate/usr/src/lib/krb5/kadm5/alt_prof.c (revision 20a7641f9918de8574b8b3b47dbe35c4bfc78df1)
1 /*
2  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 
7 /*
8  * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
9  *
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.
15  *
16  *	For further information, read the top-level Openvision
17  *	copyright which is contained in the top-level MIT Kerberos
18  *	copyright.
19  *
20  * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
21  *
22  */
23 
24 
25 /*
26  * lib/kadm/alt_prof.c
27  *
28  * Copyright 1995,2001 by the Massachusetts Institute of Technology.
29  * All Rights Reserved.
30  *
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.
35  *
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.
49  *
50  */
51 
52 /*
53  * alt_prof.c - Implement alternate profile file handling.
54  */
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>
62 
63 krb5_error_code kadm5_free_config_params();
64 
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"
73 
74 static krb5_key_salt_tuple *copy_key_salt_tuple(ksalt, len)
75 krb5_key_salt_tuple *ksalt;
76 krb5_int32 len;
77 {
78     krb5_key_salt_tuple *knew;
79 
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;
84     }
85     return 0;
86 }
87 
88 /*
89  * krb5_aprof_init()	- Initialize alternate profile context.
90  *
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.
95  *
96  * Returns:
97  *	error codes from profile_init()
98  */
99 krb5_error_code
100 krb5_aprof_init(fname, envname, acontextp)
101     char		*fname;
102     char		*envname;
103     krb5_pointer	*acontextp;
104 {
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;
112 
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;
132     }
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]);
142 	}
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;
151 }
152 
153 /*
154  * krb5_aprof_getvals()	- Get values from alternate profile.
155  *
156  * Parameters:
157  *	acontext	- opaque context for alternate profile.
158  *	hierarchy	- hierarchy of value to retrieve.
159  *	retdata		- Returned data values.
160  *
161  * Returns:
162  * 	error codes from profile_get_values()
163  */
164 krb5_error_code
165 krb5_aprof_getvals(acontext, hierarchy, retdata)
166     krb5_pointer	acontext;
167     const char		**hierarchy;
168     char		***retdata;
169 {
170     return(profile_get_values((profile_t) acontext,
171 			      hierarchy,
172 			      retdata));
173 }
174 
175 /*
176  * krb5_aprof_get_boolean()
177  *
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
184  */
185 
186 static krb5_error_code
187 string_to_boolean (const char *string, krb5_boolean *out)
188 {
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;
192 
193     for (i = 0; i < sizeof(yes)/sizeof(yes[0]); i++)
194 	if (!strcasecmp(string, yes[i])) {
195 	    *out = 1;
196 	    return 0;
197 	}
198     for (i = 0; i < sizeof(no)/sizeof(no[0]); i++)
199 	if (!strcasecmp(string, no[i])) {
200 	    *out = 0;
201 	    return 0;
202 	}
203     return PROF_BAD_BOOLEAN;
204 }
205 
206 krb5_error_code
207 krb5_aprof_get_boolean(krb5_pointer acontext, const char **hierarchy,
208 		       int uselast, krb5_boolean *retdata)
209 {
210     krb5_error_code kret;
211     char **values;
212     char *valp;
213     int idx;
214     krb5_boolean val;
215 
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--;
224     }
225     valp = values[idx];
226     kret = string_to_boolean (valp, &val);
227     if (kret)
228 	return kret;
229     *retdata = val;
230     return 0;
231 }
232 
233 /*
234  * krb5_aprof_get_deltat()	- Get a delta time value from the alternate
235  *				  profile.
236  *
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.
243  *
244  * Returns:
245  * 	error codes from profile_get_values()
246  *	error codes from krb5_string_to_deltat()
247  */
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;
254 {
255     krb5_error_code	kret;
256     char		**values;
257     char		*valp;
258     int			idx;
259 
260     if (!(kret = krb5_aprof_getvals(acontext, hierarchy, &values))) {
261 	idx = 0;
262 	if (uselast) {
263 	    for (idx=0; values[idx]; idx++);
264 	    idx--;
265 	}
266 	valp = values[idx];
267 	kret = krb5_string_to_deltat(valp, deltatp);
268 
269 	/* Free the string storage */
270 	for (idx=0; values[idx]; idx++)
271 	    krb5_xfree(values[idx]);
272 	krb5_xfree(values);
273     }
274     return(kret);
275 }
276 
277 /*
278  * krb5_aprof_get_string()	- Get a string value from the alternate
279  *				  profile.
280  *
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.
287  *
288  * Returns:
289  * 	error codes from profile_get_values()
290  */
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;
297 {
298     krb5_error_code	kret;
299     char		**values;
300     int			idx, i;
301 
302     if (!(kret = krb5_aprof_getvals(acontext, hierarchy, &values))) {
303 	idx = 0;
304 	if (uselast) {
305 	    for (idx=0; values[idx]; idx++);
306 	    idx--;
307 	}
308 
309 	*stringp = values[idx];
310 
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);
316     }
317     return(kret);
318 }
319 
320 /*
321  * krb5_aprof_get_int32()	- Get a 32-bit integer value from the alternate
322  *				  profile.
323  *
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.
330  *
331  * Returns:
332  * 	error codes from profile_get_values()
333  *	EINVAL			- value is not an integer
334  */
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;
341 {
342     krb5_error_code	kret;
343     char		**values;
344     int			idx;
345 
346     if (!(kret = krb5_aprof_getvals(acontext, hierarchy, &values))) {
347 	idx = 0;
348 	if (uselast) {
349 	    for (idx=0; values[idx]; idx++);
350 	    idx--;
351 	}
352 
353 	if (sscanf(values[idx], "%d", intp) != 1)
354 	    kret = EINVAL;
355 
356 	/* Free the string storage */
357 	for (idx=0; values[idx]; idx++)
358 	    krb5_xfree(values[idx]);
359 	krb5_xfree(values);
360     }
361     return(kret);
362 }
363 
364 /*
365  * krb5_aprof_finish()	- Finish alternate profile context.
366  *
367  * Parameter:
368  *	acontext	- opaque context for alternate profile.
369  *
370  * Returns:
371  *	0 on success, something else on failure.
372  */
373 krb5_error_code
374 krb5_aprof_finish(acontext)
375     krb5_pointer	acontext;
376 {
377     profile_release(acontext);
378     return(0);
379 }
380 
381 /*
382  * Function: kadm5_get_config_params
383  *
384  * Purpose: Merge configuration parameters provided by the caller with
385  * values specified in configuration files and with default values.
386  *
387  * Arguments:
388  *
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
396  *
397  * Effects:
398  *
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.
404  *
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.
408  */
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;
414 {
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;
423 
424     krb5_error_code	kret = 0;
425     krb5_error_code dnsret = 1;
426 
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 */
433 
434     memset((char *) &params, 0, sizeof(params));
435     memset((char *) &empty_params, 0, sizeof(empty_params));
436 
437     if (params_in == NULL) params_in = &empty_params;
438 
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;
449     }
450     /*
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.
455      */
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";
462     }
463     if (context->profile_secure == TRUE) envname = 0;
464 
465     kret = krb5_aprof_init(filename, envname, &aprofile);
466     if (kret)
467 	    goto cleanup;
468 
469     /* Initialize realm parameters */
470     hierarchy[0] = "realms";
471     hierarchy[1] = lrealm;
472     hierarchy[3] = (char *) NULL;
473 
474 #ifdef KRB5_DNS_LOOKUP
475 	/*
476 	 * Initialize realm info for (possible) DNS lookups.
477 	 */
478 	dns_realm.data = strdup(lrealm);
479 	dns_realm.length = strlen(lrealm);
480 	dns_realm.magic = 0;
481 #endif /* KRB5_DNS_LOOKUP */
482 
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;
493     }
494 #ifdef KRB5_DNS_LOOKUP
495 	else if (strcmp(envname, "KRB5_CONFIG") == 0) {
496 		/*
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.
502 		 */
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;
512 		}
513 	}
514 #endif /* KRB5_DNS_LOOKUP */
515 
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';
523 	 }
524     }
525 
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;
540     }
541 
542     /*
543      * admin database name and lockfile are now always derived from dbname
544      */
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;
550 	 }
551     }
552 
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;
559 	 }
560     }
561 
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;
580     }
581 
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;
596     }
597 
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;
608     }
609 
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;
624 	 }
625     }
626 
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;
641 	}
642     }
643 
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;
654     }
655 
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);
666 	 }
667     } else {
668 	 params.mask |= KADM5_CONFIG_ENCTYPE;
669 	 params.enctype = DEFAULT_KDC_ENCTYPE;
670     }
671 
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;
676     }
677 
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;
688     }
689 
690 	/*
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.
699 	 */
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;
707     }
708 
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;
717     }
718 
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);
729 	 }
730     } else {
731 	 params.mask |= KADM5_CONFIG_EXPIRATION;
732 	 params.expiration = 0;
733     }
734 
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;
743 
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--;
755 		   }
756 		   *ep = '\0';
757 		   ep++;
758 		   /* Skip over trailing whitespace of ep */
759 		   while (isspace((int) *ep) && (*ep)) ep++;
760 	      }
761 	      /* Convert this flag */
762 	      if (krb5_string_to_flags(sp,
763 				       "+",
764 				       "-",
765 				       &params.flags))
766 		   break;
767 	      sp = ep;
768 	 }
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;
775     }
776 
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;
787 		    }
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;
792 	 }
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);
799 
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;
810 
811 	 if (svalue)
812 	      krb5_xfree(svalue);
813     }
814 
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;
821 
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) {
828 				/*
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.
835 				 */
836 				dnsret = krb5_get_servername(context,
837 				    &dns_realm, "_kpasswd", "_udp",
838 				    dns_host, &dns_portno);
839 
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;
846 					}
847 					params.kpasswd_port = dns_portno;
848 					params.mask |=
849 					    KADM5_CONFIG_KPASSWD_PORT;
850 				}
851 			}
852 #endif /* KRB5_DNS_LOOKUP */
853 
854 			/*
855 			 * If a unique 'kpasswd_server' is not specified,
856 			 * use the normal 'admin_server'.
857 			 */
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;
863 			}
864 		} else {
865 			char *p;
866 			params.kpasswd_server = svalue;
867 			params.mask |= KADM5_CONFIG_KPASSWD_SERVER;
868 
869 			if ((p = strchr(params.kpasswd_server, ':'))) {
870 				params.kpasswd_port = atoi(p+1);
871 				params.mask |= KADM5_CONFIG_KPASSWD_PORT;
872 				*p = '\0';
873 			}
874 		}
875 	}
876 
877 	hierarchy[2] = "kpasswd_protocol";
878 
879 	/* default to current RPCSEC_GSS protocol */
880 	params.kpasswd_protocol = KRB5_CHGPWD_RPCSEC;
881 	params.mask |= KADM5_CONFIG_KPASSWD_PROTOCOL;
882 
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;
888 
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;
900 			}
901 		}
902 		if (svalue)
903 			krb5_xfree(svalue);
904 	}
905 
906 	/*
907 	 * If the kpasswd_port is not yet defined, define it now.
908 	 */
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;
912 		/*
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.
917 		 */
918 		else if (params.kpasswd_protocol == KRB5_CHGPWD_RPCSEC) {
919 			params.kpasswd_port = DEFAULT_KADM5_PORT;
920 		} else {
921 			/*
922 			 * When using the Horowitz/IETF protocol for
923 			 * password changing, the default port is 464
924 			 * (officially recognized by IANA).
925 			 */
926 			params.kpasswd_port = DEFAULT_KPASSWD_PORT;
927 		}
928 		params.mask |= KADM5_CONFIG_KPASSWD_PORT;
929 	}
930 
931 	hierarchy[2] = "sunw_dbprop_enable";
932 
933 	params.iprop_enabled = FALSE;
934 	params.mask |= KADM5_CONFIG_IPROP_ENABLED;
935 
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);
948 		}
949 	}
950 
951 	hierarchy[2] = "sunw_dbprop_master_ulogsize";
952 
953 	params.iprop_ulogsize = DEF_ULOGENTRIES;
954 	params.mask |= KADM5_CONFIG_ULOG_SIZE;
955 
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;
969 		}
970 	}
971 
972 	hierarchy[2] = "sunw_dbprop_slave_poll";
973 
974 	params.iprop_polltime = strdup("2m");
975 	if (params.iprop_polltime)
976 		params.mask |= KADM5_CONFIG_POLL_TIME;
977 
978 	if (params_in->mask & KADM5_CONFIG_POLL_TIME) {
979 		if (params.iprop_polltime)
980 			free(params.iprop_polltime);
981 		params.iprop_polltime = strdup(params_in->iprop_polltime);
982 		if (params.iprop_polltime)
983 			params.mask |= KADM5_CONFIG_POLL_TIME;
984 	} else {
985 		if (aprofile && !krb5_aprof_get_string(aprofile, hierarchy,
986 		    TRUE, &svalue)) {
987 			if (params.iprop_polltime)
988 				free(params.iprop_polltime);
989 			params.iprop_polltime = strdup(svalue);
990 			params.mask |= KADM5_CONFIG_POLL_TIME;
991 			krb5_xfree(svalue);
992 		}
993 	}
994 
995 	*params_out = params;
996 
997 cleanup:
998     if (aprofile)
999 	krb5_aprof_finish(aprofile);
1000     if (kret) {
1001 	 kadm5_free_config_params(context, &params);
1002 	 params_out->mask = 0;
1003     }
1004 #ifdef KRB5_DNS_LOOKUP
1005 	if (dns_realm.data)
1006 		free(dns_realm.data);
1007 #endif /* KRB5_DNS_LOOKUP */
1008 
1009     return(kret);
1010 }
1011 /*
1012  * kadm5_free_config_params()	- Free data allocated by above.
1013  */
1014 /*ARGSUSED*/
1015 krb5_error_code
1016 kadm5_free_config_params(context, params)
1017     krb5_context	context;
1018     kadm5_config_params	*params;
1019 {
1020     if (params) {
1021 	if (params->dbname) {
1022 		krb5_xfree(params->dbname);
1023 		params->dbname = NULL;
1024 	}
1025 	if (params->mkey_name) {
1026 		krb5_xfree(params->mkey_name);
1027 		params->mkey_name = NULL;
1028 	}
1029 	if (params->stash_file) {
1030 		krb5_xfree(params->stash_file);
1031 		params->stash_file = NULL;
1032 	}
1033 	if (params->keysalts) {
1034 		krb5_xfree(params->keysalts);
1035 		params->keysalts = NULL;
1036 		params->num_keysalts = 0;
1037 	}
1038 	if (params->admin_keytab) {
1039 		free(params->admin_keytab);
1040 		params->admin_keytab = NULL;
1041 	}
1042 	if (params->dict_file) {
1043 		free(params->dict_file);
1044 		params->dict_file = NULL;
1045 	}
1046 	if (params->acl_file) {
1047 		free(params->acl_file);
1048 		params->acl_file = NULL;
1049 	}
1050 	if (params->realm) {
1051 		free(params->realm);
1052 		params->realm = NULL;
1053 	}
1054 	if (params->admin_dbname) {
1055 		free(params->admin_dbname);
1056 		params->admin_dbname = NULL;
1057 	}
1058 	if (params->admin_lockfile) {
1059 		free(params->admin_lockfile);
1060 		params->admin_lockfile = NULL;
1061 	}
1062 	if (params->admin_server) {
1063 		free(params->admin_server);
1064 		params->admin_server = NULL;
1065 	}
1066 	if (params->kpasswd_server) {
1067 		free(params->kpasswd_server);
1068 		params->kpasswd_server = NULL;
1069 	}
1070 	if (params->iprop_polltime) {
1071 		free(params->iprop_polltime);
1072 		params->iprop_polltime = NULL;
1073 	}
1074 	}
1075 	return (0);
1076 }
1077 
1078 krb5_error_code
1079 kadm5_get_admin_service_name(krb5_context ctx,
1080 			     char *realm_in,
1081 			     char *admin_name,
1082 			     size_t maxlen)
1083 {
1084     krb5_error_code ret;
1085     kadm5_config_params params_in, params_out;
1086     struct hostent *hp;
1087 
1088     memset(&params_in, 0, sizeof(params_in));
1089     memset(&params_out, 0, sizeof(params_out));
1090 
1091     params_in.mask |= KADM5_CONFIG_REALM;
1092     params_in.realm = realm_in;
1093     ret = kadm5_get_config_params(ctx, 0, &params_in, &params_out);
1094     if (ret)
1095 	return ret;
1096 
1097     if (!(params_out.mask & KADM5_CONFIG_ADMIN_SERVER)) {
1098 	ret = KADM5_MISSING_KRB5_CONF_PARAMS;
1099 	goto err_params;
1100     }
1101 
1102     hp = gethostbyname(params_out.admin_server);
1103     if (hp == NULL) {
1104 	ret = errno;
1105 	goto err_params;
1106     }
1107     if (strlen(hp->h_name) + sizeof("kadmin/") > maxlen) {
1108 	ret = ENOMEM;
1109 	goto err_params;
1110     }
1111     sprintf(admin_name, "kadmin/%s", hp->h_name);
1112 
1113 err_params:
1114     kadm5_free_config_params(ctx, &params_out);
1115     return ret;
1116 }
1117 
1118 /***********************************************************************
1119  * This is the old krb5_realm_read_params, which I mutated into
1120  * kadm5_get_config_params but which old code (kdb5_* and krb5kdc)
1121  * still uses.
1122  ***********************************************************************/
1123 
1124 /*
1125  * krb5_read_realm_params()	- Read per-realm parameters from KDC
1126  *				  alternate profile.
1127  */
1128 krb5_error_code
1129 krb5_read_realm_params(kcontext, realm, rparamp)
1130     krb5_context	kcontext;
1131     char		*realm;
1132     krb5_realm_params	**rparamp;
1133 {
1134     char		*filename;
1135     char		*envname;
1136     char		*lrealm;
1137     krb5_pointer	aprofile = 0;
1138     krb5_realm_params	*rparams;
1139     const char		*hierarchy[4];
1140     char		*svalue;
1141     krb5_int32		ivalue;
1142     krb5_boolean	bvalue;
1143     krb5_deltat		dtvalue;
1144 
1145     char		*kdcprofile = 0;
1146     char		*kdcenv = 0;
1147 
1148     krb5_error_code	kret;
1149 
1150     filename = (kdcprofile) ? kdcprofile : DEFAULT_KDC_PROFILE;
1151     envname = (kdcenv) ? kdcenv : KDC_PROFILE_ENV;
1152 
1153     if (kcontext->profile_secure == TRUE) envname = 0;
1154 
1155     rparams = (krb5_realm_params *) NULL;
1156     if (realm)
1157 	lrealm = strdup(realm);
1158     else {
1159 	kret = krb5_get_default_realm(kcontext, &lrealm);
1160 	if (kret)
1161 	    goto cleanup;
1162     }
1163 
1164     kret = krb5_aprof_init(filename, envname, &aprofile);
1165     if (kret)
1166 	goto cleanup;
1167 
1168     rparams = (krb5_realm_params *) malloc(sizeof(krb5_realm_params));
1169     if (rparams == 0) {
1170 	kret = ENOMEM;
1171 	goto cleanup;
1172     }
1173 
1174     /* Initialize realm parameters */
1175     memset((char *) rparams, 0, sizeof(krb5_realm_params));
1176 
1177     /* Get the value for the database */
1178     hierarchy[0] = "realms";
1179     hierarchy[1] = lrealm;
1180     hierarchy[2] = "database_name";
1181     hierarchy[3] = (char *) NULL;
1182     if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue))
1183 	rparams->realm_dbname = svalue;
1184 
1185     /* Get the value for the KDC port list */
1186     hierarchy[2] = "kdc_ports";
1187     if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue))
1188 	rparams->realm_kdc_ports = svalue;
1189     hierarchy[2] = "kdc_tcp_ports";
1190     if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue))
1191 	rparams->realm_kdc_tcp_ports = svalue;
1192 
1193     /* Get the name of the acl file */
1194     hierarchy[2] = "acl_file";
1195     if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue))
1196 	rparams->realm_acl_file = svalue;
1197 
1198     /* Get the value for the kadmind port */
1199     hierarchy[2] = "kadmind_port";
1200     if (!krb5_aprof_get_int32(aprofile, hierarchy, TRUE, &ivalue)) {
1201 	rparams->realm_kadmind_port = ivalue;
1202 	rparams->realm_kadmind_port_valid = 1;
1203     }
1204 
1205     /* Get the value for the master key name */
1206     hierarchy[2] = "master_key_name";
1207     if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue))
1208 	rparams->realm_mkey_name = svalue;
1209 
1210     /* Get the value for the master key type */
1211     hierarchy[2] = "master_key_type";
1212     if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
1213 	if (!krb5_string_to_enctype(svalue, &rparams->realm_enctype))
1214 	    rparams->realm_enctype_valid = 1;
1215 	krb5_xfree(svalue);
1216     }
1217 
1218     /* Get the value for the stashfile */
1219     hierarchy[2] = "key_stash_file";
1220     if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue))
1221 	rparams->realm_stash_file = svalue;
1222 
1223     /* Get the value for maximum ticket lifetime. */
1224     hierarchy[2] = "max_life";
1225     if (!krb5_aprof_get_deltat(aprofile, hierarchy, TRUE, &dtvalue)) {
1226 	rparams->realm_max_life = dtvalue;
1227 	rparams->realm_max_life_valid = 1;
1228     }
1229 
1230     /* Get the value for maximum renewable ticket lifetime. */
1231     hierarchy[2] = "max_renewable_life";
1232     if (!krb5_aprof_get_deltat(aprofile, hierarchy, TRUE, &dtvalue)) {
1233 	rparams->realm_max_rlife = dtvalue;
1234 	rparams->realm_max_rlife_valid = 1;
1235     }
1236 
1237     /* Get the value for the default principal expiration */
1238     hierarchy[2] = "default_principal_expiration";
1239     if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
1240 	if (!krb5_string_to_timestamp(svalue,
1241 				      &rparams->realm_expiration))
1242 	    rparams->realm_expiration_valid = 1;
1243 	krb5_xfree(svalue);
1244     }
1245 
1246     hierarchy[2] = "reject_bad_transit";
1247     if (!krb5_aprof_get_boolean(aprofile, hierarchy, TRUE, &bvalue)) {
1248 	rparams->realm_reject_bad_transit = bvalue;
1249 	rparams->realm_reject_bad_transit_valid = 1;
1250     }
1251 
1252     /* Get the value for the default principal flags */
1253     hierarchy[2] = "default_principal_flags";
1254     if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
1255 	char *sp, *ep, *tp;
1256 
1257 	sp = svalue;
1258 	rparams->realm_flags = 0;
1259 	while (sp) {
1260 	    if ((ep = strchr(sp, (int) ',')) ||
1261 		(ep = strchr(sp, (int) ' ')) ||
1262 		(ep = strchr(sp, (int) '\t'))) {
1263 		/* Fill in trailing whitespace of sp */
1264 		tp = ep - 1;
1265 		while (isspace((int) *tp) && (tp < sp)) {
1266 		    *tp = '\0';
1267 		    tp--;
1268 		}
1269 		*ep = '\0';
1270 		ep++;
1271 		/* Skip over trailing whitespace of ep */
1272 		while (isspace((int) *ep) && (*ep)) ep++;
1273 	    }
1274 	    /* Convert this flag */
1275 	    if (krb5_string_to_flags(sp,
1276 				     "+",
1277 				     "-",
1278 				     &rparams->realm_flags))
1279 		break;
1280 	    sp = ep;
1281 	}
1282 	if (!sp)
1283 	    rparams->realm_flags_valid = 1;
1284 	krb5_xfree(svalue);
1285     }
1286 
1287 	/* Get the value for the supported enctype/salttype matrix */
1288 	/*
1289 	 * SUNWresync121
1290 	 * Solaris kerberos: updated this code to support default values for
1291 	 * the supported_enctypes.
1292 	 */
1293 	hierarchy[2] = "supported_enctypes";
1294 	svalue = NULL;
1295 	krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue);
1296 
1297 	/*
1298 	 * Set the default value if supported_enctypes was not explicitly
1299 	 * set in the kdc.conf.
1300 	 */
1301 	if (svalue == NULL) {
1302 	    svalue = strdup(DEFAULT_ENCTYPE_LIST);
1303 	}
1304 	if (svalue != NULL) {
1305 	    krb5_string_to_keysalts(svalue,
1306 				    ", \t",	/* Tuple separators	*/
1307 				    ":.-",	/* Key/salt separators	*/
1308 				    0,	/* No duplicates	*/
1309 				    &rparams->realm_keysalts,
1310 				    &rparams->realm_num_keysalts);
1311 	    krb5_xfree(svalue);
1312 	    svalue = NULL;
1313 	}
1314 cleanup:
1315     if (aprofile)
1316 	krb5_aprof_finish(aprofile);
1317     if (lrealm)
1318 	free(lrealm);
1319     if (kret) {
1320 	if (rparams)
1321 	    krb5_free_realm_params(kcontext, rparams);
1322 	rparams = 0;
1323     }
1324     *rparamp = rparams;
1325     return(kret);
1326 }
1327 
1328 /*
1329  * krb5_free_realm_params()	- Free data allocated by above.
1330  */
1331 krb5_error_code
1332 krb5_free_realm_params(kcontext, rparams)
1333     krb5_context	kcontext;
1334     krb5_realm_params	*rparams;
1335 {
1336     if (rparams) {
1337 	if (rparams->realm_profile)
1338 	    krb5_xfree(rparams->realm_profile);
1339 	if (rparams->realm_dbname)
1340 	    krb5_xfree(rparams->realm_dbname);
1341 	if (rparams->realm_mkey_name)
1342 	    krb5_xfree(rparams->realm_mkey_name);
1343 	if (rparams->realm_stash_file)
1344 	    krb5_xfree(rparams->realm_stash_file);
1345 	if (rparams->realm_keysalts)
1346 	    krb5_xfree(rparams->realm_keysalts);
1347 	if (rparams->realm_kdc_ports)
1348 	    krb5_xfree(rparams->realm_kdc_ports);
1349 	if (rparams->realm_kdc_tcp_ports)
1350 	    krb5_xfree(rparams->realm_kdc_tcp_ports);
1351 	if (rparams->realm_acl_file)
1352 	    krb5_xfree(rparams->realm_acl_file);
1353 	krb5_xfree(rparams);
1354     }
1355     return(0);
1356 }
1357 
1358