xref: /onnv-gate/usr/src/lib/gss_mechs/mech_krb5/profile/prof_solaris.c (revision 13073:6b4a9cc90eaa)
112568SShawn.Emery@Sun.COM /*
212568SShawn.Emery@Sun.COM  * CDDL HEADER START
312568SShawn.Emery@Sun.COM  *
412568SShawn.Emery@Sun.COM  * The contents of this file are subject to the terms of the
512568SShawn.Emery@Sun.COM  * Common Development and Distribution License (the "License").
612568SShawn.Emery@Sun.COM  * You may not use this file except in compliance with the License.
712568SShawn.Emery@Sun.COM  *
812568SShawn.Emery@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
912568SShawn.Emery@Sun.COM  * or http://www.opensolaris.org/os/licensing.
1012568SShawn.Emery@Sun.COM  * See the License for the specific language governing permissions
1112568SShawn.Emery@Sun.COM  * and limitations under the License.
1212568SShawn.Emery@Sun.COM  *
1312568SShawn.Emery@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
1412568SShawn.Emery@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1512568SShawn.Emery@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
1612568SShawn.Emery@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
1712568SShawn.Emery@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
1812568SShawn.Emery@Sun.COM  *
1912568SShawn.Emery@Sun.COM  * CDDL HEADER END
2012568SShawn.Emery@Sun.COM  */
2112568SShawn.Emery@Sun.COM 
2212568SShawn.Emery@Sun.COM /*
2312568SShawn.Emery@Sun.COM  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
2412568SShawn.Emery@Sun.COM  */
2512568SShawn.Emery@Sun.COM 
2612568SShawn.Emery@Sun.COM /*
2712568SShawn.Emery@Sun.COM  * prof_solaris.c:
2812568SShawn.Emery@Sun.COM  * Abstracted contract private interfaces for configuring krb5.conf(4).
2912568SShawn.Emery@Sun.COM  */
3012568SShawn.Emery@Sun.COM 
3112568SShawn.Emery@Sun.COM #include <ctype.h>
3212568SShawn.Emery@Sun.COM #include "prof_int.h"
3312568SShawn.Emery@Sun.COM #include "k5-int.h"
3412568SShawn.Emery@Sun.COM 
3512568SShawn.Emery@Sun.COM errcode_t
__profile_iter_name_value(profile_t profile,char * section,char * key,char *** retvals)3612568SShawn.Emery@Sun.COM __profile_iter_name_value(profile_t profile, char *section, char *key,
3712568SShawn.Emery@Sun.COM 	char ***retvals)
3812568SShawn.Emery@Sun.COM {
3912568SShawn.Emery@Sun.COM 	const char	*hierarchy[4];
4012568SShawn.Emery@Sun.COM 	errcode_t	code, code2;
4112568SShawn.Emery@Sun.COM 	char		*name = NULL, *value = NULL, **ret_values = NULL;
4212568SShawn.Emery@Sun.COM 	void		*state = NULL;
4312568SShawn.Emery@Sun.COM 	struct profile_string_list values;
4412568SShawn.Emery@Sun.COM 	boolean_t	found = FALSE;
4512568SShawn.Emery@Sun.COM 
4612568SShawn.Emery@Sun.COM 	hierarchy[0] = section;
4712568SShawn.Emery@Sun.COM 	hierarchy[1] = NULL;
4812568SShawn.Emery@Sun.COM 
4912568SShawn.Emery@Sun.COM 	if (code = init_list(&values))
5012568SShawn.Emery@Sun.COM 		return (code);
5112568SShawn.Emery@Sun.COM 
5212568SShawn.Emery@Sun.COM 	code = profile_iterator_create(profile, hierarchy,
5312568SShawn.Emery@Sun.COM 	    PROFILE_ITER_LIST_SECTION, &state);
5412568SShawn.Emery@Sun.COM 	while (code == 0) {
5512568SShawn.Emery@Sun.COM 		code = profile_iterator(&state, &name, &value);
5612568SShawn.Emery@Sun.COM 		if (code == 0 && name != NULL) {
5712568SShawn.Emery@Sun.COM 			if ((key == NULL) || (strcmp(value, key) == 0)) {
5812568SShawn.Emery@Sun.COM 				code2 = add_to_list(&values, name);
5912568SShawn.Emery@Sun.COM 				if (code2 != 0) {
6012568SShawn.Emery@Sun.COM 					end_list(&values, &ret_values);
6112568SShawn.Emery@Sun.COM 					profile_free_list(ret_values);
6212568SShawn.Emery@Sun.COM 					code2 = code;
6312568SShawn.Emery@Sun.COM 					goto cleanup;
6412568SShawn.Emery@Sun.COM 				}
6512568SShawn.Emery@Sun.COM 				found = TRUE;
6612568SShawn.Emery@Sun.COM 			}
6712568SShawn.Emery@Sun.COM 		}
6812568SShawn.Emery@Sun.COM 		if (name != NULL) {
6912568SShawn.Emery@Sun.COM 			profile_release_string(name);
7012568SShawn.Emery@Sun.COM 			name = NULL;
7112568SShawn.Emery@Sun.COM 		}
7212568SShawn.Emery@Sun.COM 		if (value != NULL) {
7312568SShawn.Emery@Sun.COM 			profile_release_string(value);
7412568SShawn.Emery@Sun.COM 			value = NULL;
7512568SShawn.Emery@Sun.COM 		}
7612568SShawn.Emery@Sun.COM 	}
7712568SShawn.Emery@Sun.COM 	code = 0;
7812568SShawn.Emery@Sun.COM 	if (found == TRUE)
7912568SShawn.Emery@Sun.COM 		end_list(&values, &ret_values);
8012568SShawn.Emery@Sun.COM 
8112568SShawn.Emery@Sun.COM cleanup:
8212568SShawn.Emery@Sun.COM 
8312568SShawn.Emery@Sun.COM 	if (state != NULL)
8412568SShawn.Emery@Sun.COM 		profile_iterator_free(&state);
8512568SShawn.Emery@Sun.COM 	if (name != NULL)
8612568SShawn.Emery@Sun.COM 		profile_release_string(name);
8712568SShawn.Emery@Sun.COM 	if (value != NULL)
8812568SShawn.Emery@Sun.COM 		profile_release_string(value);
8912568SShawn.Emery@Sun.COM 
9012568SShawn.Emery@Sun.COM 	*retvals = ret_values;
9112568SShawn.Emery@Sun.COM 
9212568SShawn.Emery@Sun.COM 	return (code);
9312568SShawn.Emery@Sun.COM }
9412568SShawn.Emery@Sun.COM 
9512568SShawn.Emery@Sun.COM errcode_t
__profile_get_domain_realm(profile_t profile,char * realm,char *** domains)9612568SShawn.Emery@Sun.COM __profile_get_domain_realm(profile_t profile, char *realm, char ***domains)
9712568SShawn.Emery@Sun.COM {
9812568SShawn.Emery@Sun.COM 	if (profile == NULL || realm == NULL || domains == NULL)
9912568SShawn.Emery@Sun.COM 		return (EINVAL);
10012568SShawn.Emery@Sun.COM 
10112568SShawn.Emery@Sun.COM 	return (__profile_iter_name_value(profile, "domain_realm", realm,
10212568SShawn.Emery@Sun.COM 	    domains));
10312568SShawn.Emery@Sun.COM }
10412568SShawn.Emery@Sun.COM 
10512568SShawn.Emery@Sun.COM errcode_t
__profile_set_appdefaults(profile_t profile)10612568SShawn.Emery@Sun.COM __profile_set_appdefaults(profile_t profile)
10712568SShawn.Emery@Sun.COM {
10812568SShawn.Emery@Sun.COM 	const char	*hierarchy[4];
10912568SShawn.Emery@Sun.COM 	errcode_t	code;
11012568SShawn.Emery@Sun.COM 
11112568SShawn.Emery@Sun.COM 	if (profile == NULL)
11212568SShawn.Emery@Sun.COM 		return (EINVAL);
11312568SShawn.Emery@Sun.COM 
11412568SShawn.Emery@Sun.COM 	hierarchy[0] = "appdefaults";
11512568SShawn.Emery@Sun.COM 	hierarchy[1] = "kinit";
11612568SShawn.Emery@Sun.COM 	hierarchy[3] = NULL;
11712568SShawn.Emery@Sun.COM 
11812568SShawn.Emery@Sun.COM 	hierarchy[2] = "renewable";
11912568SShawn.Emery@Sun.COM 
12012568SShawn.Emery@Sun.COM 	/*
12112568SShawn.Emery@Sun.COM 	 * Not fatal if this fails, continue on.
12212568SShawn.Emery@Sun.COM 	 */
12312568SShawn.Emery@Sun.COM 	(void) profile_clear_relation(profile, hierarchy);
12412568SShawn.Emery@Sun.COM 
12512568SShawn.Emery@Sun.COM 	code = profile_add_relation(profile, hierarchy, "true");
12612568SShawn.Emery@Sun.COM 	if (code != 0)
12712568SShawn.Emery@Sun.COM 		return (code);
12812568SShawn.Emery@Sun.COM 
12912568SShawn.Emery@Sun.COM 	hierarchy[2] = "forwardable";
13012568SShawn.Emery@Sun.COM 
13112568SShawn.Emery@Sun.COM 	(void) profile_clear_relation(profile, hierarchy);
13212568SShawn.Emery@Sun.COM 
13312568SShawn.Emery@Sun.COM 	code = profile_add_relation(profile, hierarchy, "true");
13412568SShawn.Emery@Sun.COM 
13512568SShawn.Emery@Sun.COM 	return (code);
13612568SShawn.Emery@Sun.COM }
13712568SShawn.Emery@Sun.COM 
13812568SShawn.Emery@Sun.COM errcode_t
__profile_set_logging(profile_t profile)13912568SShawn.Emery@Sun.COM __profile_set_logging(profile_t profile)
14012568SShawn.Emery@Sun.COM {
14112568SShawn.Emery@Sun.COM 	const char	*hierarchy[4];
14212568SShawn.Emery@Sun.COM 	errcode_t	code;
14312568SShawn.Emery@Sun.COM 
14412568SShawn.Emery@Sun.COM 	if (profile == NULL)
14512568SShawn.Emery@Sun.COM 		return (EINVAL);
14612568SShawn.Emery@Sun.COM 
14712568SShawn.Emery@Sun.COM 	hierarchy[0] = "logging";
14812568SShawn.Emery@Sun.COM 	hierarchy[2] = NULL;
14912568SShawn.Emery@Sun.COM 	hierarchy[3] = NULL;
15012568SShawn.Emery@Sun.COM 
15112568SShawn.Emery@Sun.COM 	hierarchy[1] = "default";
15212568SShawn.Emery@Sun.COM 
15312568SShawn.Emery@Sun.COM 	/*
15412568SShawn.Emery@Sun.COM 	 * Not fatal if this fails, continue on.
15512568SShawn.Emery@Sun.COM 	 */
15612568SShawn.Emery@Sun.COM 	(void) profile_clear_relation(profile, hierarchy);
15712568SShawn.Emery@Sun.COM 
15812568SShawn.Emery@Sun.COM 	code = profile_add_relation(profile, hierarchy,
15912568SShawn.Emery@Sun.COM 	    "FILE:/var/krb5/kdc.log");
16012568SShawn.Emery@Sun.COM 	if (code != 0)
16112568SShawn.Emery@Sun.COM 		return (code);
16212568SShawn.Emery@Sun.COM 
16312568SShawn.Emery@Sun.COM 	hierarchy[1] = "kdc";
16412568SShawn.Emery@Sun.COM 
16512568SShawn.Emery@Sun.COM 	(void) profile_clear_relation(profile, hierarchy);
16612568SShawn.Emery@Sun.COM 
16712568SShawn.Emery@Sun.COM 	code = profile_add_relation(profile, hierarchy,
16812568SShawn.Emery@Sun.COM 	    "FILE:/var/krb5/kdc.log");
16912568SShawn.Emery@Sun.COM 	if (code != 0)
17012568SShawn.Emery@Sun.COM 		return (code);
17112568SShawn.Emery@Sun.COM 
17212568SShawn.Emery@Sun.COM 	hierarchy[1] = "kdc_rotate";
17312568SShawn.Emery@Sun.COM 
17412568SShawn.Emery@Sun.COM 	hierarchy[2] = "period";
17512568SShawn.Emery@Sun.COM 
17612568SShawn.Emery@Sun.COM 	(void) profile_clear_relation(profile, hierarchy);
17712568SShawn.Emery@Sun.COM 
17812568SShawn.Emery@Sun.COM 	code = profile_add_relation(profile, hierarchy, "1d");
17912568SShawn.Emery@Sun.COM 	if (code != 0)
18012568SShawn.Emery@Sun.COM 		return (code);
18112568SShawn.Emery@Sun.COM 
18212568SShawn.Emery@Sun.COM 	hierarchy[2] = "versions";
18312568SShawn.Emery@Sun.COM 
18412568SShawn.Emery@Sun.COM 	(void) profile_clear_relation(profile, hierarchy);
18512568SShawn.Emery@Sun.COM 
18612568SShawn.Emery@Sun.COM 	code = profile_add_relation(profile, hierarchy, "10");
18712568SShawn.Emery@Sun.COM 
18812568SShawn.Emery@Sun.COM 	return (code);
18912568SShawn.Emery@Sun.COM }
19012568SShawn.Emery@Sun.COM 
19112568SShawn.Emery@Sun.COM errcode_t
__profile_set_libdefaults(profile_t profile,char * realm)19212568SShawn.Emery@Sun.COM __profile_set_libdefaults(profile_t profile, char *realm)
19312568SShawn.Emery@Sun.COM {
19412568SShawn.Emery@Sun.COM 	const char	*hierarchy[4];
19512568SShawn.Emery@Sun.COM 	errcode_t	code;
19612568SShawn.Emery@Sun.COM 
19712568SShawn.Emery@Sun.COM 	if (profile == NULL || realm == NULL)
19812568SShawn.Emery@Sun.COM 		return (EINVAL);
19912568SShawn.Emery@Sun.COM 
20012568SShawn.Emery@Sun.COM 	hierarchy[0] = "libdefaults";
20112568SShawn.Emery@Sun.COM 	hierarchy[1] = "default_realm";
20212568SShawn.Emery@Sun.COM 	hierarchy[2] = NULL;
20312568SShawn.Emery@Sun.COM 
20412568SShawn.Emery@Sun.COM 	/*
20512568SShawn.Emery@Sun.COM 	 * Not fatal if this fails, continue on.
20612568SShawn.Emery@Sun.COM 	 */
20712568SShawn.Emery@Sun.COM 	(void) profile_clear_relation(profile, hierarchy);
20812568SShawn.Emery@Sun.COM 
20912568SShawn.Emery@Sun.COM 	code = profile_add_relation(profile, hierarchy, realm);
21012568SShawn.Emery@Sun.COM 
21112568SShawn.Emery@Sun.COM 	return (code);
21212568SShawn.Emery@Sun.COM }
21312568SShawn.Emery@Sun.COM 
21412568SShawn.Emery@Sun.COM errcode_t
__profile_set_kdc(profile_t profile,char * realm,char * kdc,boolean_t overwrite)21512568SShawn.Emery@Sun.COM __profile_set_kdc(profile_t profile, char *realm, char *kdc,
21612568SShawn.Emery@Sun.COM 	boolean_t overwrite)
21712568SShawn.Emery@Sun.COM {
21812568SShawn.Emery@Sun.COM 	const char	*hierarchy[4];
21912568SShawn.Emery@Sun.COM 	errcode_t	code;
22012568SShawn.Emery@Sun.COM 
22112568SShawn.Emery@Sun.COM 	if (profile == NULL || realm == NULL || kdc == NULL)
22212568SShawn.Emery@Sun.COM 		return (EINVAL);
22312568SShawn.Emery@Sun.COM 
22412568SShawn.Emery@Sun.COM 	hierarchy[0] = "realms";
22512568SShawn.Emery@Sun.COM 	hierarchy[1] = realm;
22612568SShawn.Emery@Sun.COM 	hierarchy[3] = NULL;
22712568SShawn.Emery@Sun.COM 
22812568SShawn.Emery@Sun.COM 	hierarchy[2] = "kdc";
22912568SShawn.Emery@Sun.COM 
23012568SShawn.Emery@Sun.COM 	if (overwrite == TRUE) {
23112568SShawn.Emery@Sun.COM 		/*
23212568SShawn.Emery@Sun.COM 		 * Not fatal if this fails, continue on.
23312568SShawn.Emery@Sun.COM 		 */
23412568SShawn.Emery@Sun.COM 		(void) profile_clear_relation(profile, hierarchy);
23512568SShawn.Emery@Sun.COM 	}
23612568SShawn.Emery@Sun.COM 
23712568SShawn.Emery@Sun.COM 	code = profile_add_relation(profile, hierarchy, kdc);
23812568SShawn.Emery@Sun.COM 
23912568SShawn.Emery@Sun.COM 	return (code);
24012568SShawn.Emery@Sun.COM }
24112568SShawn.Emery@Sun.COM 
24212568SShawn.Emery@Sun.COM /*
24312568SShawn.Emery@Sun.COM  * errcode_t __profile_release(profile_t profile)
24412568SShawn.Emery@Sun.COM  *
24512568SShawn.Emery@Sun.COM  * where profile was the pointer passed back by __profile_init
24612568SShawn.Emery@Sun.COM  * Note: used to commit the associated profile to the backing store
24712568SShawn.Emery@Sun.COM  * (e.g. file) and free profile memory
24812568SShawn.Emery@Sun.COM  * Note: that this function returns an error code which profile_release
24912568SShawn.Emery@Sun.COM  * does not.  With the error code, the application can determine if they
25012568SShawn.Emery@Sun.COM  * need to free the resulting profile information in memory
25112568SShawn.Emery@Sun.COM  */
25212568SShawn.Emery@Sun.COM errcode_t
__profile_release(profile_t profile)25312568SShawn.Emery@Sun.COM __profile_release(profile_t profile)
25412568SShawn.Emery@Sun.COM {
25512568SShawn.Emery@Sun.COM 	prf_file_t	p, next;
25612568SShawn.Emery@Sun.COM 	errcode_t	code;
25712568SShawn.Emery@Sun.COM 
25812568SShawn.Emery@Sun.COM 	if (profile == NULL || profile->magic != PROF_MAGIC_PROFILE)
25912568SShawn.Emery@Sun.COM 		return (EINVAL);
26012568SShawn.Emery@Sun.COM 
26112568SShawn.Emery@Sun.COM 	for (p = profile->first_file; p; p = next) {
26212568SShawn.Emery@Sun.COM 		next = p->next;
26312568SShawn.Emery@Sun.COM 		if ((code = profile_close_file(p)) != 0)
26412568SShawn.Emery@Sun.COM 			return (code);
26512568SShawn.Emery@Sun.COM 	}
26612568SShawn.Emery@Sun.COM 	profile->magic = 0;
26712568SShawn.Emery@Sun.COM 	free(profile);
26812568SShawn.Emery@Sun.COM 
26912568SShawn.Emery@Sun.COM 	return (0);
27012568SShawn.Emery@Sun.COM }
27112568SShawn.Emery@Sun.COM 
27212568SShawn.Emery@Sun.COM /*
27312568SShawn.Emery@Sun.COM  * void __profile_abandon(profile_t profile)
27412568SShawn.Emery@Sun.COM  *
27512568SShawn.Emery@Sun.COM  * where profile was the pointer passed back by __profile_init
27612568SShawn.Emery@Sun.COM  * Note: used to free any profile information in memory.  Typically can
27712568SShawn.Emery@Sun.COM  * be used in conjunction with __profile_release upon error
27812568SShawn.Emery@Sun.COM  */
27912568SShawn.Emery@Sun.COM void
__profile_abandon(profile_t profile)28012568SShawn.Emery@Sun.COM __profile_abandon(profile_t profile)
28112568SShawn.Emery@Sun.COM {
28212568SShawn.Emery@Sun.COM 	profile_abandon(profile);
28312568SShawn.Emery@Sun.COM }
28412568SShawn.Emery@Sun.COM 
28512568SShawn.Emery@Sun.COM /*
28612568SShawn.Emery@Sun.COM  * errcode_t __profile_add_domain_mapping(profile_t profile, char *domain,
28712568SShawn.Emery@Sun.COM  *	char *realm)
28812568SShawn.Emery@Sun.COM  *
28912568SShawn.Emery@Sun.COM  * where profile was the pointer passed back by __profile_init
29012568SShawn.Emery@Sun.COM  * where domain is the domain name of the associated realm name
29112568SShawn.Emery@Sun.COM  * where realm is the corresponding realm name for the domain
29212568SShawn.Emery@Sun.COM  */
29312568SShawn.Emery@Sun.COM errcode_t
__profile_add_domain_mapping(profile_t profile,char * domain,char * realm)29412568SShawn.Emery@Sun.COM __profile_add_domain_mapping(profile_t profile, char *domain, char *realm)
29512568SShawn.Emery@Sun.COM {
29612568SShawn.Emery@Sun.COM 	const char	*hierarchy[4];
29712568SShawn.Emery@Sun.COM 	errcode_t	code = 0;
29812568SShawn.Emery@Sun.COM 
29912568SShawn.Emery@Sun.COM 	if (profile == NULL || domain == NULL || realm == NULL)
30012568SShawn.Emery@Sun.COM 		return (EINVAL);
30112568SShawn.Emery@Sun.COM 
30212568SShawn.Emery@Sun.COM 	hierarchy[0] = "domain_realm";
30312568SShawn.Emery@Sun.COM 	hierarchy[1] = domain;
30412568SShawn.Emery@Sun.COM 	hierarchy[2] = NULL;
30512568SShawn.Emery@Sun.COM 
30612568SShawn.Emery@Sun.COM 	/*
30712568SShawn.Emery@Sun.COM 	 * Not fatal if relation can't be cleared, continue on.
30812568SShawn.Emery@Sun.COM 	 */
30912568SShawn.Emery@Sun.COM 	(void) profile_clear_relation(profile, hierarchy);
31012568SShawn.Emery@Sun.COM 
31112568SShawn.Emery@Sun.COM 	code = profile_add_relation(profile, hierarchy, realm);
31212568SShawn.Emery@Sun.COM 
31312568SShawn.Emery@Sun.COM 	return (code);
31412568SShawn.Emery@Sun.COM }
31512568SShawn.Emery@Sun.COM 
31612568SShawn.Emery@Sun.COM /*
31712568SShawn.Emery@Sun.COM  * errcode_t __profile_remove_domain_mapping(profile_t profile,	char *realm)
31812568SShawn.Emery@Sun.COM  *
31912568SShawn.Emery@Sun.COM  * where profile was the pointer passed back by __profile_init
32012568SShawn.Emery@Sun.COM  * where domain is the domain name of the associated realm name
32112568SShawn.Emery@Sun.COM  * where realm is the corresponding realm name for the domain
32212568SShawn.Emery@Sun.COM  * Note: for the remove function, all matching domain - realm mappings
32312568SShawn.Emery@Sun.COM  * will be removed for realm
32412568SShawn.Emery@Sun.COM  */
32512568SShawn.Emery@Sun.COM errcode_t
__profile_remove_domain_mapping(profile_t profile,char * realm)32612568SShawn.Emery@Sun.COM __profile_remove_domain_mapping(profile_t profile, char *realm)
32712568SShawn.Emery@Sun.COM {
32812568SShawn.Emery@Sun.COM 	const char	*hierarchy[4];
32912568SShawn.Emery@Sun.COM 	errcode_t	code;
33012568SShawn.Emery@Sun.COM 	char		**domains = NULL, **domain = NULL;
33112568SShawn.Emery@Sun.COM 
33212568SShawn.Emery@Sun.COM 	if (profile == NULL || realm == NULL)
33312568SShawn.Emery@Sun.COM 		return (EINVAL);
33412568SShawn.Emery@Sun.COM 
33512568SShawn.Emery@Sun.COM 	hierarchy[0] = "domain_realm";
33612568SShawn.Emery@Sun.COM 	hierarchy[1] = NULL;
33712568SShawn.Emery@Sun.COM 	hierarchy[2] = NULL;
33812568SShawn.Emery@Sun.COM 
33912568SShawn.Emery@Sun.COM 	code = __profile_get_domain_realm(profile, realm, &domains);
34012568SShawn.Emery@Sun.COM 	if (code == 0 && domains != NULL) {
34112568SShawn.Emery@Sun.COM 		for (domain = domains; *domain; domain++) {
34212568SShawn.Emery@Sun.COM 			hierarchy[1] = *domain;
34312568SShawn.Emery@Sun.COM 			code = profile_clear_relation(profile, hierarchy);
34412568SShawn.Emery@Sun.COM 			if (code != 0)
34512568SShawn.Emery@Sun.COM 				goto error;
34612568SShawn.Emery@Sun.COM 		}
34712568SShawn.Emery@Sun.COM 	}
34812568SShawn.Emery@Sun.COM 
34912568SShawn.Emery@Sun.COM error:
35012568SShawn.Emery@Sun.COM 	if (domains != NULL)
35112568SShawn.Emery@Sun.COM 		profile_free_list(domains);
35212568SShawn.Emery@Sun.COM 
35312568SShawn.Emery@Sun.COM 	return (code);
35412568SShawn.Emery@Sun.COM }
35512568SShawn.Emery@Sun.COM 
35612568SShawn.Emery@Sun.COM /*
35712568SShawn.Emery@Sun.COM  * errcode_t __profile_get_realm_entry(profile_t profile, char *realm,
35812568SShawn.Emery@Sun.COM  *	char *name, char ***ret_value)
35912568SShawn.Emery@Sun.COM  *
36012568SShawn.Emery@Sun.COM  * where profile was the pointer passed back by __profile_init
36112568SShawn.Emery@Sun.COM  * where realm is the target realm for lookup
36212568SShawn.Emery@Sun.COM  * where name is the name in the realm section requested
36312568SShawn.Emery@Sun.COM  * where value is a string array of any matching values assigned to name.
36412568SShawn.Emery@Sun.COM  * The array is terminated with a NULL pointer.
36512568SShawn.Emery@Sun.COM  * Note: if no name has been configured and a profile does exist
36612568SShawn.Emery@Sun.COM  * then value is set to NULL
36712568SShawn.Emery@Sun.COM  */
36812568SShawn.Emery@Sun.COM errcode_t
__profile_get_realm_entry(profile_t profile,char * realm,char * name,char *** ret_value)36912568SShawn.Emery@Sun.COM __profile_get_realm_entry(profile_t profile, char *realm, char *name,
37012568SShawn.Emery@Sun.COM 	char ***ret_value)
37112568SShawn.Emery@Sun.COM {
37212568SShawn.Emery@Sun.COM 	const char	*hierarchy[4];
37312568SShawn.Emery@Sun.COM 	errcode_t	code;
37412568SShawn.Emery@Sun.COM 	char		**values = NULL;
37512568SShawn.Emery@Sun.COM 
37612568SShawn.Emery@Sun.COM 	if (profile == NULL || realm == NULL || name == NULL ||
37712568SShawn.Emery@Sun.COM 	    ret_value == NULL)
37812568SShawn.Emery@Sun.COM 		return (EINVAL);
37912568SShawn.Emery@Sun.COM 
38012568SShawn.Emery@Sun.COM 	hierarchy[0] = "realms";
38112568SShawn.Emery@Sun.COM 	hierarchy[1] = realm;
38212568SShawn.Emery@Sun.COM 	hierarchy[2] = name;
38312568SShawn.Emery@Sun.COM 	hierarchy[3] = NULL;
38412568SShawn.Emery@Sun.COM 
38512568SShawn.Emery@Sun.COM 	code = profile_get_values(profile, hierarchy, &values);
38612568SShawn.Emery@Sun.COM 	if (code == 0 && values != NULL)
38712568SShawn.Emery@Sun.COM 		*ret_value = values;
38812568SShawn.Emery@Sun.COM 
389*13073SShawn.Emery@Sun.COM 	if (code == PROF_NO_RELATION)
390*13073SShawn.Emery@Sun.COM 		code = 0;
39112568SShawn.Emery@Sun.COM 
39212568SShawn.Emery@Sun.COM 	return (code);
39312568SShawn.Emery@Sun.COM }
39412568SShawn.Emery@Sun.COM 
39512568SShawn.Emery@Sun.COM /*
39612568SShawn.Emery@Sun.COM  * errcode_t __profile_add_realm_entry(profile_t profile, char *realm,
39712568SShawn.Emery@Sun.COM  *	char *name, char **value)
39812568SShawn.Emery@Sun.COM  *
39912568SShawn.Emery@Sun.COM  * where profile was the pointer passed back by __profile_init
40012568SShawn.Emery@Sun.COM  * where realm is the target realm for the name-value pair
40112568SShawn.Emery@Sun.COM  * where name is the name in the realm subsection to add
40212568SShawn.Emery@Sun.COM  * where value is a string array values to assigned to name.  The array is
40312568SShawn.Emery@Sun.COM  * terminated with a NULL pointer.
40412568SShawn.Emery@Sun.COM  * Note: if the realm subsection does no exist then an error is returned
40512568SShawn.Emery@Sun.COM  * Note: if the name already exists the set is overwritten with the values
40612568SShawn.Emery@Sun.COM  * passed
40712568SShawn.Emery@Sun.COM  */
40812568SShawn.Emery@Sun.COM errcode_t
__profile_add_realm_entry(profile_t profile,char * realm,char * name,char ** values)40912568SShawn.Emery@Sun.COM __profile_add_realm_entry(profile_t profile, char *realm, char *name,
41012568SShawn.Emery@Sun.COM 	char **values)
41112568SShawn.Emery@Sun.COM {
41212568SShawn.Emery@Sun.COM 	const char	*hierarchy[4];
41312568SShawn.Emery@Sun.COM 	errcode_t	code;
41412568SShawn.Emery@Sun.COM 	char		**tvalue = NULL;
41512568SShawn.Emery@Sun.COM 
41612568SShawn.Emery@Sun.COM 	if (profile == NULL || realm == NULL || name == NULL || values == NULL)
41712568SShawn.Emery@Sun.COM 		return (EINVAL);
41812568SShawn.Emery@Sun.COM 
41912568SShawn.Emery@Sun.COM 	hierarchy[0] = "realms";
42012568SShawn.Emery@Sun.COM 	hierarchy[1] = realm;
42112568SShawn.Emery@Sun.COM 	hierarchy[2] = name;
42212568SShawn.Emery@Sun.COM 	hierarchy[3] = NULL;
42312568SShawn.Emery@Sun.COM 
42412568SShawn.Emery@Sun.COM 	/*
42512568SShawn.Emery@Sun.COM 	 * Not fatal if this fails, continue on.
42612568SShawn.Emery@Sun.COM 	 */
42712568SShawn.Emery@Sun.COM 	(void) profile_clear_relation(profile, hierarchy);
42812568SShawn.Emery@Sun.COM 
42912568SShawn.Emery@Sun.COM 	for (tvalue = values; *tvalue; tvalue++) {
43012568SShawn.Emery@Sun.COM 
43112568SShawn.Emery@Sun.COM 		code = profile_add_relation(profile, hierarchy, *tvalue);
43212568SShawn.Emery@Sun.COM 		if (code != 0)
43312568SShawn.Emery@Sun.COM 			return (code);
43412568SShawn.Emery@Sun.COM 	}
43512568SShawn.Emery@Sun.COM 
43612568SShawn.Emery@Sun.COM 	return (0);
43712568SShawn.Emery@Sun.COM }
43812568SShawn.Emery@Sun.COM 
43912568SShawn.Emery@Sun.COM /*
44012568SShawn.Emery@Sun.COM  * errcode_t __profile_get_default_realm(profile_t profile, char **realm)
44112568SShawn.Emery@Sun.COM  *
44212568SShawn.Emery@Sun.COM  * where profile was the pointer passed back by __profile_init
44312568SShawn.Emery@Sun.COM  * where realm is the default_realm configured for the system
44412568SShawn.Emery@Sun.COM  * Note: if no default_realm has been configured and a profile does exist
44512568SShawn.Emery@Sun.COM  * then realm is set to NULL
44612568SShawn.Emery@Sun.COM  */
44712568SShawn.Emery@Sun.COM errcode_t
__profile_get_default_realm(profile_t profile,char ** realm)44812568SShawn.Emery@Sun.COM __profile_get_default_realm(profile_t profile, char **realm)
44912568SShawn.Emery@Sun.COM {
45012568SShawn.Emery@Sun.COM 	errcode_t	code;
45112568SShawn.Emery@Sun.COM 	char		*value = NULL;
45212568SShawn.Emery@Sun.COM 
45312568SShawn.Emery@Sun.COM 	if (profile == NULL || realm == NULL)
45412568SShawn.Emery@Sun.COM 		return (EINVAL);
45512568SShawn.Emery@Sun.COM 
45612568SShawn.Emery@Sun.COM 	code = profile_get_string(profile, "libdefaults", "default_realm", 0, 0,
45712568SShawn.Emery@Sun.COM 	    &value);
45812568SShawn.Emery@Sun.COM 	if (code == 0 && value != NULL)
45912568SShawn.Emery@Sun.COM 		*realm = value;
46012568SShawn.Emery@Sun.COM 
461*13073SShawn.Emery@Sun.COM 	if (code == PROF_NO_RELATION)
462*13073SShawn.Emery@Sun.COM 		code = 0;
46312568SShawn.Emery@Sun.COM 
46412568SShawn.Emery@Sun.COM 	return (code);
46512568SShawn.Emery@Sun.COM }
46612568SShawn.Emery@Sun.COM 
46712568SShawn.Emery@Sun.COM /*
46812568SShawn.Emery@Sun.COM  * errcode_t __profile_get_realms(profile_t profile, char ***realms)
46912568SShawn.Emery@Sun.COM  *
47012568SShawn.Emery@Sun.COM  * where profile was the pointer passed back by __profile_init
47112568SShawn.Emery@Sun.COM  * where realms is a string array of realm names currently configured.
47212568SShawn.Emery@Sun.COM  * The array is terminated with a NULL pointer.
47312568SShawn.Emery@Sun.COM  * Note: if no realms have been configured and a profile does exist then
47412568SShawn.Emery@Sun.COM  * realms is set to NULL
47512568SShawn.Emery@Sun.COM  */
47612568SShawn.Emery@Sun.COM errcode_t
__profile_get_realms(profile_t profile,char *** realms)47712568SShawn.Emery@Sun.COM __profile_get_realms(profile_t profile, char ***realms)
47812568SShawn.Emery@Sun.COM {
47912568SShawn.Emery@Sun.COM 
48012568SShawn.Emery@Sun.COM 	if (profile == NULL || realms == NULL)
48112568SShawn.Emery@Sun.COM 		return (EINVAL);
48212568SShawn.Emery@Sun.COM 
48312568SShawn.Emery@Sun.COM 	return (__profile_iter_name_value(profile, "realms", NULL, realms));
48412568SShawn.Emery@Sun.COM }
48512568SShawn.Emery@Sun.COM 
48612568SShawn.Emery@Sun.COM /*
48712568SShawn.Emery@Sun.COM  * errcode_t __profile_add_realm(profile_t profile, char *realm,
48812568SShawn.Emery@Sun.COM  *	char *master, char **kdcs, boolean_t set_change, boolean_t
48912568SShawn.Emery@Sun.COM  *	default_realm)
49012568SShawn.Emery@Sun.COM  *
49112568SShawn.Emery@Sun.COM  * where profile was the pointer passed back by __profile_init
49212568SShawn.Emery@Sun.COM  * where realm is the realm name associated with the configuration
49312568SShawn.Emery@Sun.COM  * where master is the server that is assigned to admin_server
49412568SShawn.Emery@Sun.COM  * where kdcs is a string array of KDCs used to populate the kdc set.
49512568SShawn.Emery@Sun.COM  * The array is terminated with a NULL pointer.
49612568SShawn.Emery@Sun.COM  * where set_change, if set, will use the SET_CHANGE protocol for password
49712568SShawn.Emery@Sun.COM  * modifications.  RPCSEC_GSS is set by default
49812568SShawn.Emery@Sun.COM  * where default_realm, if set, will assign the realm to default_realm
49912568SShawn.Emery@Sun.COM  * Note: the ordering of kdcs is determined by the server's position in the
50012568SShawn.Emery@Sun.COM  * array
50112568SShawn.Emery@Sun.COM  * Note: kdcs must be assigned a value, even if it is the same value as the
50212568SShawn.Emery@Sun.COM  * master.
50312568SShawn.Emery@Sun.COM  */
50412568SShawn.Emery@Sun.COM errcode_t
__profile_add_realm(profile_t profile,char * realm,char * master,char ** kdcs,boolean_t set_change,boolean_t default_realm)50512568SShawn.Emery@Sun.COM __profile_add_realm(profile_t profile, char *realm, char *master, char **kdcs,
50612568SShawn.Emery@Sun.COM 	boolean_t set_change, boolean_t default_realm)
50712568SShawn.Emery@Sun.COM {
50812568SShawn.Emery@Sun.COM 	const char	*hierarchy[4];
50912568SShawn.Emery@Sun.COM 	errcode_t	code;
51012568SShawn.Emery@Sun.COM 	boolean_t	ow = TRUE;
51112568SShawn.Emery@Sun.COM 	char		**tkdcs;
51212568SShawn.Emery@Sun.COM 
51312568SShawn.Emery@Sun.COM 	if (profile == NULL || realm == NULL || master == NULL || kdcs == NULL)
51412568SShawn.Emery@Sun.COM 		return (EINVAL);
51512568SShawn.Emery@Sun.COM 
51612568SShawn.Emery@Sun.COM 	/*
51712568SShawn.Emery@Sun.COM 	 * Sets the default realm to realm if default_realm flag is set.
51812568SShawn.Emery@Sun.COM 	 */
51912568SShawn.Emery@Sun.COM 	if (default_realm == TRUE) {
52012568SShawn.Emery@Sun.COM 		if (code = __profile_set_libdefaults(profile, realm))
52112568SShawn.Emery@Sun.COM 			return (code);
52212568SShawn.Emery@Sun.COM 	}
52312568SShawn.Emery@Sun.COM 
52412568SShawn.Emery@Sun.COM 	hierarchy[0] = "realms";
52512568SShawn.Emery@Sun.COM 	hierarchy[1] = realm;
52612568SShawn.Emery@Sun.COM 	hierarchy[3] = NULL;
52712568SShawn.Emery@Sun.COM 
52812568SShawn.Emery@Sun.COM 	hierarchy[2] = "admin_server";
52912568SShawn.Emery@Sun.COM 
53012568SShawn.Emery@Sun.COM 	/*
53112568SShawn.Emery@Sun.COM 	 * Not fatal if this fails, therefore return code is not checked.
53212568SShawn.Emery@Sun.COM 	 */
53312568SShawn.Emery@Sun.COM 	(void) profile_clear_relation(profile, hierarchy);
53412568SShawn.Emery@Sun.COM 
53512568SShawn.Emery@Sun.COM 	if (code = profile_add_relation(profile, hierarchy, master))
53612568SShawn.Emery@Sun.COM 		return (code);
53712568SShawn.Emery@Sun.COM 
53812568SShawn.Emery@Sun.COM 	/*
53912568SShawn.Emery@Sun.COM 	 * If not set then defaults to undefined, which defaults to RPCSEC_GSS.
54012568SShawn.Emery@Sun.COM 	 */
54112568SShawn.Emery@Sun.COM 	if (set_change == TRUE) {
54212568SShawn.Emery@Sun.COM 		hierarchy[2] = "kpasswd_protocol";
54312568SShawn.Emery@Sun.COM 
54412568SShawn.Emery@Sun.COM 		(void) profile_clear_relation(profile, hierarchy);
54512568SShawn.Emery@Sun.COM 
54612568SShawn.Emery@Sun.COM 		code = profile_add_relation(profile, hierarchy, "SET_CHANGE");
54712568SShawn.Emery@Sun.COM 		if (code != 0)
54812568SShawn.Emery@Sun.COM 			return (code);
54912568SShawn.Emery@Sun.COM 	}
55012568SShawn.Emery@Sun.COM 
55112568SShawn.Emery@Sun.COM 	for (tkdcs = kdcs; *tkdcs; tkdcs++) {
55212568SShawn.Emery@Sun.COM 		if (code = __profile_set_kdc(profile, realm, *tkdcs, ow))
55312568SShawn.Emery@Sun.COM 			return (code);
55412568SShawn.Emery@Sun.COM 		ow = FALSE;
55512568SShawn.Emery@Sun.COM 	}
55612568SShawn.Emery@Sun.COM 
55712568SShawn.Emery@Sun.COM 	code = __profile_set_logging(profile);
55812568SShawn.Emery@Sun.COM 	if (code != 0)
55912568SShawn.Emery@Sun.COM 		return (code);
56012568SShawn.Emery@Sun.COM 
56112568SShawn.Emery@Sun.COM 	code = __profile_set_appdefaults(profile);
56212568SShawn.Emery@Sun.COM 
56312568SShawn.Emery@Sun.COM 	return (code);
56412568SShawn.Emery@Sun.COM }
56512568SShawn.Emery@Sun.COM 
56612568SShawn.Emery@Sun.COM /*
56712568SShawn.Emery@Sun.COM  * errcode_t __profile_remove_xrealm_mapping(profile_t profile, char *realm)
56812568SShawn.Emery@Sun.COM  *
56912568SShawn.Emery@Sun.COM  * where profile was the pointer passed back by __profile_init
57012568SShawn.Emery@Sun.COM  * where source is the source realm for the capath
57112568SShawn.Emery@Sun.COM  * where target is the target realm for the capath
57212568SShawn.Emery@Sun.COM  * where inter is the intermediate realm between the source and target
57312568SShawn.Emery@Sun.COM  * realms.  If the source and target share x-realm keys then this set to "."
57412568SShawn.Emery@Sun.COM  * Note: for the remove function, all associated source, target, and
57512568SShawn.Emery@Sun.COM  * intermediate entries will be removed matching the realm name
57612568SShawn.Emery@Sun.COM  */
57712568SShawn.Emery@Sun.COM errcode_t
__profile_remove_xrealm_mapping(profile_t profile,char * realm)57812568SShawn.Emery@Sun.COM __profile_remove_xrealm_mapping(profile_t profile, char *realm)
57912568SShawn.Emery@Sun.COM {
58012568SShawn.Emery@Sun.COM 	const char	*hierarchy[4];
58112568SShawn.Emery@Sun.COM 	errcode_t	code, code2, code3;
58212568SShawn.Emery@Sun.COM 	void		*state = NULL, *state2 = NULL;
58312568SShawn.Emery@Sun.COM 	char		*source = NULL, *dummy_val = NULL, *target = NULL;
58412568SShawn.Emery@Sun.COM 	char		*inter = NULL;
58512568SShawn.Emery@Sun.COM 
58612568SShawn.Emery@Sun.COM 	if (profile == NULL || realm == NULL)
58712568SShawn.Emery@Sun.COM 		return (EINVAL);
58812568SShawn.Emery@Sun.COM 
58912568SShawn.Emery@Sun.COM 	hierarchy[0] = "capaths";
59012568SShawn.Emery@Sun.COM 	hierarchy[1] = realm;
59112568SShawn.Emery@Sun.COM 	hierarchy[2] = NULL;
59212568SShawn.Emery@Sun.COM 	hierarchy[3] = NULL;
59312568SShawn.Emery@Sun.COM 
59412568SShawn.Emery@Sun.COM 	/*
59512568SShawn.Emery@Sun.COM 	 * Not fatal if this fails, continue on.
59612568SShawn.Emery@Sun.COM 	 */
59712568SShawn.Emery@Sun.COM 	code = profile_rename_section(profile, hierarchy, NULL);
59812568SShawn.Emery@Sun.COM 
59912568SShawn.Emery@Sun.COM 	hierarchy[1] = NULL;
60012568SShawn.Emery@Sun.COM 	code = profile_iterator_create(profile, hierarchy,
60112568SShawn.Emery@Sun.COM 	    PROFILE_ITER_LIST_SECTION, &state);
60212568SShawn.Emery@Sun.COM 	while (code == 0) {
60312568SShawn.Emery@Sun.COM 		code = profile_iterator(&state, &source, &dummy_val);
60412568SShawn.Emery@Sun.COM 		if (code == 0 && source != NULL) {
60512568SShawn.Emery@Sun.COM 			hierarchy[1] = source;
60612568SShawn.Emery@Sun.COM 			code2 = profile_iterator_create(profile, hierarchy,
60712568SShawn.Emery@Sun.COM 			    PROFILE_ITER_LIST_SECTION, &state2);
60812568SShawn.Emery@Sun.COM 			while (code2 == 0) {
60912568SShawn.Emery@Sun.COM 				code2 = profile_iterator(&state2, &target,
61012568SShawn.Emery@Sun.COM 				    &inter);
61112568SShawn.Emery@Sun.COM 				if (code2 == 0 && target != NULL &&
61212568SShawn.Emery@Sun.COM 				    inter != NULL) {
61312568SShawn.Emery@Sun.COM 					if (strcmp(realm, target) == 0 ||
61412568SShawn.Emery@Sun.COM 					    strcmp(realm, inter) == 0) {
61512568SShawn.Emery@Sun.COM 						hierarchy[2] = target;
61612568SShawn.Emery@Sun.COM 						code3 =
61712568SShawn.Emery@Sun.COM 						    profile_clear_relation(
61812568SShawn.Emery@Sun.COM 						    profile, hierarchy);
61912568SShawn.Emery@Sun.COM 						if (code3 != 0) {
62012568SShawn.Emery@Sun.COM 							code = code3;
62112568SShawn.Emery@Sun.COM 							goto error;
62212568SShawn.Emery@Sun.COM 						}
62312568SShawn.Emery@Sun.COM 					}
62412568SShawn.Emery@Sun.COM 				}
62512568SShawn.Emery@Sun.COM 				if (target != NULL) {
62612568SShawn.Emery@Sun.COM 					profile_release_string(target);
62712568SShawn.Emery@Sun.COM 					target = NULL;
62812568SShawn.Emery@Sun.COM 				}
62912568SShawn.Emery@Sun.COM 				if (inter != NULL) {
63012568SShawn.Emery@Sun.COM 					profile_release_string(inter);
63112568SShawn.Emery@Sun.COM 					inter = NULL;
63212568SShawn.Emery@Sun.COM 				}
63312568SShawn.Emery@Sun.COM 			}
63412568SShawn.Emery@Sun.COM 		}
63512568SShawn.Emery@Sun.COM 		if (source != NULL) {
63612568SShawn.Emery@Sun.COM 			profile_release_string(source);
63712568SShawn.Emery@Sun.COM 			source = NULL;
63812568SShawn.Emery@Sun.COM 		}
63912568SShawn.Emery@Sun.COM 		if (dummy_val != NULL) {
64012568SShawn.Emery@Sun.COM 			profile_release_string(dummy_val);
64112568SShawn.Emery@Sun.COM 			dummy_val = NULL;
64212568SShawn.Emery@Sun.COM 		}
64312568SShawn.Emery@Sun.COM 	}
64412568SShawn.Emery@Sun.COM 	code = 0;
64512568SShawn.Emery@Sun.COM 
64612568SShawn.Emery@Sun.COM error:
64712568SShawn.Emery@Sun.COM 	if (state != NULL)
64812568SShawn.Emery@Sun.COM 		profile_iterator_free(&state);
64912568SShawn.Emery@Sun.COM 	if (state2 != NULL)
65012568SShawn.Emery@Sun.COM 		profile_iterator_free(&state2);
65112568SShawn.Emery@Sun.COM 	if (target != NULL)
65212568SShawn.Emery@Sun.COM 		profile_release_string(target);
65312568SShawn.Emery@Sun.COM 	if (inter != NULL)
65412568SShawn.Emery@Sun.COM 		profile_release_string(inter);
65512568SShawn.Emery@Sun.COM 	if (source != NULL)
65612568SShawn.Emery@Sun.COM 		profile_release_string(source);
65712568SShawn.Emery@Sun.COM 	if (dummy_val != NULL)
65812568SShawn.Emery@Sun.COM 		profile_release_string(dummy_val);
65912568SShawn.Emery@Sun.COM 
66012568SShawn.Emery@Sun.COM 	return (code);
66112568SShawn.Emery@Sun.COM }
66212568SShawn.Emery@Sun.COM 
66312568SShawn.Emery@Sun.COM /*
66412568SShawn.Emery@Sun.COM  * errcode_t __profile_remove_realm(profile_t profile, char *realm)
66512568SShawn.Emery@Sun.COM  *
66612568SShawn.Emery@Sun.COM  * where profile was the pointer passed back by __profile_init
66712568SShawn.Emery@Sun.COM  * where realm is the target realm for removal
66812568SShawn.Emery@Sun.COM  * Note: the function removes the matching realm in the realms section,
66912568SShawn.Emery@Sun.COM  * the default_realm, relevant domain_realm mappings with the realm name,
67012568SShawn.Emery@Sun.COM  * and matching capaths source realm subsection.
67112568SShawn.Emery@Sun.COM  */
67212568SShawn.Emery@Sun.COM errcode_t
__profile_remove_realm(profile_t profile,char * realm)67312568SShawn.Emery@Sun.COM __profile_remove_realm(profile_t profile, char *realm)
67412568SShawn.Emery@Sun.COM {
67512568SShawn.Emery@Sun.COM 	const char	*hierarchy[4];
67612568SShawn.Emery@Sun.COM 	errcode_t	code;
677*13073SShawn.Emery@Sun.COM 	char		*drealm = NULL;
67812568SShawn.Emery@Sun.COM 
67912568SShawn.Emery@Sun.COM 	if (profile == NULL || realm == NULL)
68012568SShawn.Emery@Sun.COM 		return (EINVAL);
68112568SShawn.Emery@Sun.COM 
68212568SShawn.Emery@Sun.COM 	/*
68312568SShawn.Emery@Sun.COM 	 * Remove the default realm.
68412568SShawn.Emery@Sun.COM 	 */
68512568SShawn.Emery@Sun.COM 	hierarchy[0] = "libdefaults";
68612568SShawn.Emery@Sun.COM 	hierarchy[1] = "default_realm";
68712568SShawn.Emery@Sun.COM 	hierarchy[2] = NULL;
68812568SShawn.Emery@Sun.COM 
68912568SShawn.Emery@Sun.COM 	code = __profile_get_default_realm(profile, &drealm);
69012568SShawn.Emery@Sun.COM 	if (code != 0)
69112568SShawn.Emery@Sun.COM 		return (code);
69212568SShawn.Emery@Sun.COM 	else if (drealm != NULL) {
69312568SShawn.Emery@Sun.COM 		if (strcmp(drealm, realm) == 0) {
69412568SShawn.Emery@Sun.COM 			code = profile_clear_relation(profile, hierarchy);
695*13073SShawn.Emery@Sun.COM 			if (code != 0) {
696*13073SShawn.Emery@Sun.COM 				free(drealm);
69712568SShawn.Emery@Sun.COM 				return (code);
698*13073SShawn.Emery@Sun.COM 			}
69912568SShawn.Emery@Sun.COM 		}
70012568SShawn.Emery@Sun.COM 		free(drealm);
70112568SShawn.Emery@Sun.COM 	}
70212568SShawn.Emery@Sun.COM 
70312568SShawn.Emery@Sun.COM 	hierarchy[0] = "realms";
70412568SShawn.Emery@Sun.COM 	hierarchy[1] = realm;
70512568SShawn.Emery@Sun.COM 	hierarchy[2] = NULL;
70612568SShawn.Emery@Sun.COM 
70712568SShawn.Emery@Sun.COM 	code = profile_rename_section(profile, hierarchy, NULL);
70812568SShawn.Emery@Sun.COM 	if (code != 0)
70912568SShawn.Emery@Sun.COM 		return (code);
71012568SShawn.Emery@Sun.COM 
71112568SShawn.Emery@Sun.COM 	code = __profile_remove_domain_mapping(profile, realm);
71212568SShawn.Emery@Sun.COM 	if (code != 0)
71312568SShawn.Emery@Sun.COM 		return (code);
71412568SShawn.Emery@Sun.COM 
71512568SShawn.Emery@Sun.COM 	code = __profile_remove_xrealm_mapping(profile, realm);
71612568SShawn.Emery@Sun.COM 	if (code != 0)
71712568SShawn.Emery@Sun.COM 		return (code);
71812568SShawn.Emery@Sun.COM 
71912568SShawn.Emery@Sun.COM 	/*
72012568SShawn.Emery@Sun.COM 	 * Not fatal even if realm wasn't available to remove.
72112568SShawn.Emery@Sun.COM 	 */
72212568SShawn.Emery@Sun.COM 	return (0);
72312568SShawn.Emery@Sun.COM }
72412568SShawn.Emery@Sun.COM 
72512568SShawn.Emery@Sun.COM /*
72612568SShawn.Emery@Sun.COM  * errcode_t __profile_add_xrealm_mapping(profile_t profile, char *source,
72712568SShawn.Emery@Sun.COM  *	char *target, char *inter)
72812568SShawn.Emery@Sun.COM  *
72912568SShawn.Emery@Sun.COM  * where profile was the pointer passed back by __profile_init
73012568SShawn.Emery@Sun.COM  * where source is the source realm for the capath
73112568SShawn.Emery@Sun.COM  * where target is the target realm for the capath
73212568SShawn.Emery@Sun.COM  * where inter is the intermediate realm between the source and target
73312568SShawn.Emery@Sun.COM  * realms.  If the source and target share x-realm keys then this set to "."
73412568SShawn.Emery@Sun.COM  * Note: if the section does not exist one will be created
73512568SShawn.Emery@Sun.COM  */
73612568SShawn.Emery@Sun.COM errcode_t
__profile_add_xrealm_mapping(profile_t profile,char * source,char * target,char * inter)73712568SShawn.Emery@Sun.COM __profile_add_xrealm_mapping(profile_t profile, char *source, char *target,
73812568SShawn.Emery@Sun.COM 	char *inter)
73912568SShawn.Emery@Sun.COM {
74012568SShawn.Emery@Sun.COM 	const char	*hierarchy[4];
74112568SShawn.Emery@Sun.COM 	errcode_t	code;
74212568SShawn.Emery@Sun.COM 
74312568SShawn.Emery@Sun.COM 	if (profile == NULL || source == NULL || target == NULL ||
74412568SShawn.Emery@Sun.COM 	    inter == NULL)
74512568SShawn.Emery@Sun.COM 		return (EINVAL);
74612568SShawn.Emery@Sun.COM 
74712568SShawn.Emery@Sun.COM 	hierarchy[0] = "capaths";
74812568SShawn.Emery@Sun.COM 	hierarchy[1] = source;
74912568SShawn.Emery@Sun.COM 	hierarchy[2] = target;
75012568SShawn.Emery@Sun.COM 	hierarchy[3] = NULL;
75112568SShawn.Emery@Sun.COM 
75212568SShawn.Emery@Sun.COM 	/*
75312568SShawn.Emery@Sun.COM 	 * Not fatal if this fails, continue on.
75412568SShawn.Emery@Sun.COM 	 */
75512568SShawn.Emery@Sun.COM 	(void) profile_clear_relation(profile, hierarchy);
75612568SShawn.Emery@Sun.COM 
75712568SShawn.Emery@Sun.COM 	code = profile_add_relation(profile, hierarchy, inter);
75812568SShawn.Emery@Sun.COM 
75912568SShawn.Emery@Sun.COM 	return (code);
76012568SShawn.Emery@Sun.COM }
76112568SShawn.Emery@Sun.COM 
76212568SShawn.Emery@Sun.COM /*
76312568SShawn.Emery@Sun.COM  * errcode_t __profile_validate(profile_t profile, int *val_err, char **val)
76412568SShawn.Emery@Sun.COM  *
76512568SShawn.Emery@Sun.COM  * where profile was the pointer passed back by __profile_init
76612568SShawn.Emery@Sun.COM  * where val_err is a function specific error code of the following values:
76712568SShawn.Emery@Sun.COM  *	0 No errors detected in profile
76812568SShawn.Emery@Sun.COM  *	1 default realm is in lower-case (val returns realm)
76912568SShawn.Emery@Sun.COM  *	2 realm in realms section is in lower-case (val returns realm)
77012568SShawn.Emery@Sun.COM  *	3 default realm is not found in realms section
77112568SShawn.Emery@Sun.COM  *		(val returns realm not found)
77212568SShawn.Emery@Sun.COM  *	4 default realm does not exist
77312568SShawn.Emery@Sun.COM  *	5 no realm found in realms section
77412568SShawn.Emery@Sun.COM  *	6 no domain realm mapping entry found corresponding to a realm
77512568SShawn.Emery@Sun.COM  *		in the realms section (val returns realm name)
77612568SShawn.Emery@Sun.COM  *	7 kdc relation-value does not exist in realm
77712568SShawn.Emery@Sun.COM  *		(val returns realm name)
77812568SShawn.Emery@Sun.COM  *	8 admin_server relation-value does not exist in realm
77912568SShawn.Emery@Sun.COM  *		(val returns realm name)
78012568SShawn.Emery@Sun.COM  * where val is the associated errant value, associated with val_err.  This
78112568SShawn.Emery@Sun.COM  * value is returned as is from the profile
78212568SShawn.Emery@Sun.COM  * Note: function infers the following:
78312568SShawn.Emery@Sun.COM  *	1. REALM should be in upper-case
78412568SShawn.Emery@Sun.COM  *	2. all required entries are present
78512568SShawn.Emery@Sun.COM  *	3. all relations are defined between default realm, realm, and
78612568SShawn.Emery@Sun.COM  *		domain - realm mappings
787*13073SShawn.Emery@Sun.COM  *
788*13073SShawn.Emery@Sun.COM  * Note: The return value of this function is based on the error code returned
789*13073SShawn.Emery@Sun.COM  * by the framework/mechanism.  The function could return zero with the
790*13073SShawn.Emery@Sun.COM  * validation error code set to non-zero if the profile is invalid in any way.
791*13073SShawn.Emery@Sun.COM  *
79212568SShawn.Emery@Sun.COM  * Caution: This function could return false positives on valid
79312568SShawn.Emery@Sun.COM  * configurations and should only be used by the CIFS team for
79412568SShawn.Emery@Sun.COM  * specific purposes.
79512568SShawn.Emery@Sun.COM  */
79612568SShawn.Emery@Sun.COM errcode_t
__profile_validate(profile_t profile,int * val_err,char ** val)79712568SShawn.Emery@Sun.COM __profile_validate(profile_t profile, int *val_err, char **val)
79812568SShawn.Emery@Sun.COM {
79912568SShawn.Emery@Sun.COM 	errcode_t	code;
80012568SShawn.Emery@Sun.COM 	register int	c;
80112568SShawn.Emery@Sun.COM 	boolean_t	found = FALSE;
80212568SShawn.Emery@Sun.COM 	char		*default_realm = NULL, **realms = NULL, *tr = NULL;
80312568SShawn.Emery@Sun.COM 	char		**trealms = NULL, **domains = NULL, **ret_vals = NULL;
80412568SShawn.Emery@Sun.COM 
80512568SShawn.Emery@Sun.COM 	if (profile == NULL || val_err == NULL || val == NULL)
80612568SShawn.Emery@Sun.COM 		return (EINVAL);
80712568SShawn.Emery@Sun.COM 
80812568SShawn.Emery@Sun.COM 	*val_err = 0;
80912568SShawn.Emery@Sun.COM 	*val = NULL;
81012568SShawn.Emery@Sun.COM 
81112568SShawn.Emery@Sun.COM 	code = __profile_get_default_realm(profile, &default_realm);
81212568SShawn.Emery@Sun.COM 	if (code == 0 && default_realm != NULL) {
81312568SShawn.Emery@Sun.COM 		tr = default_realm;
81412568SShawn.Emery@Sun.COM 
81512568SShawn.Emery@Sun.COM 		while ((c = *tr++) != NULL) {
81612568SShawn.Emery@Sun.COM 			if (islower(c)) {
81712568SShawn.Emery@Sun.COM 				*val_err = 1;
81812568SShawn.Emery@Sun.COM 				*val = strdup(default_realm);
81912568SShawn.Emery@Sun.COM 				if (*val == NULL)
82012568SShawn.Emery@Sun.COM 					code = ENOMEM;
82112568SShawn.Emery@Sun.COM 				goto cleanup;
82212568SShawn.Emery@Sun.COM 			}
82312568SShawn.Emery@Sun.COM 		}
82412568SShawn.Emery@Sun.COM 	} else if (code == 0 && default_realm == NULL) {
82512568SShawn.Emery@Sun.COM 		*val_err = 4;
82612568SShawn.Emery@Sun.COM 		goto cleanup;
82712568SShawn.Emery@Sun.COM 	} else
82812568SShawn.Emery@Sun.COM 		goto cleanup;
82912568SShawn.Emery@Sun.COM 
83012568SShawn.Emery@Sun.COM 	code = __profile_get_realms(profile, &realms);
83112568SShawn.Emery@Sun.COM 	if (code == 0 && realms != NULL) {
83212568SShawn.Emery@Sun.COM 		for (trealms = realms; *trealms; trealms++) {
83312568SShawn.Emery@Sun.COM 
83412568SShawn.Emery@Sun.COM 			tr = *trealms;
83512568SShawn.Emery@Sun.COM 			while ((c = *tr++) != NULL) {
83612568SShawn.Emery@Sun.COM 				if (islower(c)) {
83712568SShawn.Emery@Sun.COM 					*val_err = 2;
83812568SShawn.Emery@Sun.COM 					*val = strdup(*trealms);
83912568SShawn.Emery@Sun.COM 					if (*val == NULL)
84012568SShawn.Emery@Sun.COM 						code = ENOMEM;
84112568SShawn.Emery@Sun.COM 					goto cleanup;
84212568SShawn.Emery@Sun.COM 				}
84312568SShawn.Emery@Sun.COM 			}
84412568SShawn.Emery@Sun.COM 
84512568SShawn.Emery@Sun.COM 			if (strcmp(default_realm, *trealms) == 0)
84612568SShawn.Emery@Sun.COM 				found = TRUE;
84712568SShawn.Emery@Sun.COM 
84812568SShawn.Emery@Sun.COM 			code = __profile_get_domain_realm(profile, *trealms,
84912568SShawn.Emery@Sun.COM 			    &domains);
85012568SShawn.Emery@Sun.COM 			if (code == 0 && domains != NULL) {
85112568SShawn.Emery@Sun.COM 				profile_free_list(domains);
85212568SShawn.Emery@Sun.COM 				domains = NULL;
85312568SShawn.Emery@Sun.COM 			} else if (code == 0 && domains == NULL) {
85412568SShawn.Emery@Sun.COM 				*val_err = 6;
85512568SShawn.Emery@Sun.COM 				*val = strdup(*trealms);
85612568SShawn.Emery@Sun.COM 				if (*val == NULL)
85712568SShawn.Emery@Sun.COM 					code = ENOMEM;
85812568SShawn.Emery@Sun.COM 				goto cleanup;
85912568SShawn.Emery@Sun.COM 			} else
86012568SShawn.Emery@Sun.COM 				goto cleanup;
86112568SShawn.Emery@Sun.COM 
86212568SShawn.Emery@Sun.COM 			code = __profile_get_realm_entry(profile, *trealms,
86312568SShawn.Emery@Sun.COM 			    "kdc", &ret_vals);
86412568SShawn.Emery@Sun.COM 			if (code == 0 && ret_vals != NULL) {
86512568SShawn.Emery@Sun.COM 				profile_free_list(ret_vals);
86612568SShawn.Emery@Sun.COM 				ret_vals = NULL;
86712568SShawn.Emery@Sun.COM 			} else if (code == 0 && ret_vals == NULL) {
86812568SShawn.Emery@Sun.COM 				*val_err = 7;
86912568SShawn.Emery@Sun.COM 				*val = strdup(*trealms);
87012568SShawn.Emery@Sun.COM 				if (*val == NULL)
87112568SShawn.Emery@Sun.COM 					code = ENOMEM;
87212568SShawn.Emery@Sun.COM 				goto cleanup;
87312568SShawn.Emery@Sun.COM 			} else
87412568SShawn.Emery@Sun.COM 				goto cleanup;
87512568SShawn.Emery@Sun.COM 
87612568SShawn.Emery@Sun.COM 			code = __profile_get_realm_entry(profile, *trealms,
87712568SShawn.Emery@Sun.COM 			    "admin_server", &ret_vals);
87812568SShawn.Emery@Sun.COM 			if (code == 0 && ret_vals != NULL) {
87912568SShawn.Emery@Sun.COM 				profile_free_list(ret_vals);
88012568SShawn.Emery@Sun.COM 				ret_vals = NULL;
88112568SShawn.Emery@Sun.COM 			} else if (code == 0 && ret_vals == NULL) {
88212568SShawn.Emery@Sun.COM 				*val_err = 8;
88312568SShawn.Emery@Sun.COM 				*val = strdup(*trealms);
88412568SShawn.Emery@Sun.COM 				if (*val == NULL)
88512568SShawn.Emery@Sun.COM 					code = ENOMEM;
88612568SShawn.Emery@Sun.COM 				goto cleanup;
88712568SShawn.Emery@Sun.COM 			} else
88812568SShawn.Emery@Sun.COM 				goto cleanup;
88912568SShawn.Emery@Sun.COM 		}
89012568SShawn.Emery@Sun.COM 
89112568SShawn.Emery@Sun.COM 		if (found == FALSE) {
89212568SShawn.Emery@Sun.COM 			*val_err = 3;
89312568SShawn.Emery@Sun.COM 			*val = strdup(default_realm);
89412568SShawn.Emery@Sun.COM 			if (*val == NULL)
89512568SShawn.Emery@Sun.COM 				code = ENOMEM;
89612568SShawn.Emery@Sun.COM 			goto cleanup;
89712568SShawn.Emery@Sun.COM 		}
89812568SShawn.Emery@Sun.COM 	} else if (code == 0 && realms == NULL)
89912568SShawn.Emery@Sun.COM 		*val_err = 5;
90012568SShawn.Emery@Sun.COM 
90112568SShawn.Emery@Sun.COM cleanup:
90212568SShawn.Emery@Sun.COM 
90312568SShawn.Emery@Sun.COM 	if (realms != NULL)
90412568SShawn.Emery@Sun.COM 		profile_free_list(realms);
90512568SShawn.Emery@Sun.COM 	if (ret_vals != NULL)
90612568SShawn.Emery@Sun.COM 		profile_free_list(ret_vals);
90712568SShawn.Emery@Sun.COM 	if (default_realm != NULL)
90812568SShawn.Emery@Sun.COM 		profile_release_string(default_realm);
90912568SShawn.Emery@Sun.COM 	if (domains != NULL)
91012568SShawn.Emery@Sun.COM 		profile_free_list(domains);
91112568SShawn.Emery@Sun.COM 
91212568SShawn.Emery@Sun.COM 	return (code);
91312568SShawn.Emery@Sun.COM }
91412568SShawn.Emery@Sun.COM 
91512568SShawn.Emery@Sun.COM /*
91612568SShawn.Emery@Sun.COM  * errcode_t __profile_init(char *filename, profile_t *profile)
91712568SShawn.Emery@Sun.COM  *
91812568SShawn.Emery@Sun.COM  * where filename is the specified profile location.  If filename is NULL
91912568SShawn.Emery@Sun.COM  * then function uses the system default name, /etc/krb5/krb5.conf
92012568SShawn.Emery@Sun.COM  * where profile is pointer passed to caller upon success
92112568SShawn.Emery@Sun.COM  * Note: if the file does not exist then one will be created
92212568SShawn.Emery@Sun.COM  * Note: if the file does exist then any existing profile information will
92312568SShawn.Emery@Sun.COM  * be in profile
92412568SShawn.Emery@Sun.COM  * Note: profile_release() should be used by the caller to free profile
92512568SShawn.Emery@Sun.COM  */
92612568SShawn.Emery@Sun.COM errcode_t
__profile_init(char * filename,profile_t * profile)92712568SShawn.Emery@Sun.COM __profile_init(char *filename, profile_t *profile)
92812568SShawn.Emery@Sun.COM {
92912568SShawn.Emery@Sun.COM 	profile_filespec_t	*filenames = NULL;
93012568SShawn.Emery@Sun.COM 	krb5_error_code		ret = 0;
93112568SShawn.Emery@Sun.COM 	errcode_t		code = 0;
93212568SShawn.Emery@Sun.COM 	int			err = 0, fd;
93312568SShawn.Emery@Sun.COM 	mode_t			mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
93412568SShawn.Emery@Sun.COM 
93512568SShawn.Emery@Sun.COM 	if (profile == NULL)
93612568SShawn.Emery@Sun.COM 		return (EINVAL);
93712568SShawn.Emery@Sun.COM 
93812568SShawn.Emery@Sun.COM 	if (filename != NULL) {
93912568SShawn.Emery@Sun.COM 		filenames = malloc(2 * sizeof (char *));
94012568SShawn.Emery@Sun.COM 		if (filenames == NULL)
94112568SShawn.Emery@Sun.COM 			return (ENOMEM);
94212568SShawn.Emery@Sun.COM 		filenames[0] = strdup(filename);
94312568SShawn.Emery@Sun.COM 		if (filenames[0] == NULL) {
94412568SShawn.Emery@Sun.COM 			free(filenames);
94512568SShawn.Emery@Sun.COM 			return (ENOMEM);
94612568SShawn.Emery@Sun.COM 		}
94712568SShawn.Emery@Sun.COM 		filenames[1] = NULL;
94812568SShawn.Emery@Sun.COM 	} else {
94912568SShawn.Emery@Sun.COM 		ret = krb5_get_default_config_files(&filenames);
95012568SShawn.Emery@Sun.COM 		if (ret != 0)
95112568SShawn.Emery@Sun.COM 			return (ret);
95212568SShawn.Emery@Sun.COM 	}
95312568SShawn.Emery@Sun.COM 
95412568SShawn.Emery@Sun.COM 	/*
95512568SShawn.Emery@Sun.COM 	 * If file does not exist then create said file.
95612568SShawn.Emery@Sun.COM 	 */
95712568SShawn.Emery@Sun.COM 	fd = open(*filenames, O_RDWR|O_CREAT|O_NOFOLLOW|O_NOLINKS, mode);
95812568SShawn.Emery@Sun.COM 	if (fd < 0) {
95912568SShawn.Emery@Sun.COM 		err = errno;
96012568SShawn.Emery@Sun.COM 		krb5_free_config_files(filenames);
96112568SShawn.Emery@Sun.COM 		return (err);
96212568SShawn.Emery@Sun.COM 	} else
96312568SShawn.Emery@Sun.COM 		close(fd);
96412568SShawn.Emery@Sun.COM 
96512568SShawn.Emery@Sun.COM 	/*
96612568SShawn.Emery@Sun.COM 	 * Specify non-null for specific file (to load any existing profile)
96712568SShawn.Emery@Sun.COM 	 */
96812568SShawn.Emery@Sun.COM 	code = profile_init((const_profile_filespec_t *)filenames, profile);
96912568SShawn.Emery@Sun.COM 
97012568SShawn.Emery@Sun.COM 	krb5_free_config_files(filenames);
97112568SShawn.Emery@Sun.COM 
97212568SShawn.Emery@Sun.COM 	return (code);
97312568SShawn.Emery@Sun.COM }
974