1bfc032a1SShawn Emery /*
2bfc032a1SShawn Emery  * CDDL HEADER START
3bfc032a1SShawn Emery  *
4bfc032a1SShawn Emery  * The contents of this file are subject to the terms of the
5bfc032a1SShawn Emery  * Common Development and Distribution License (the "License").
6bfc032a1SShawn Emery  * You may not use this file except in compliance with the License.
7bfc032a1SShawn Emery  *
8bfc032a1SShawn Emery  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9bfc032a1SShawn Emery  * or http://www.opensolaris.org/os/licensing.
10bfc032a1SShawn Emery  * See the License for the specific language governing permissions
11bfc032a1SShawn Emery  * and limitations under the License.
12bfc032a1SShawn Emery  *
13bfc032a1SShawn Emery  * When distributing Covered Code, include this CDDL HEADER in each
14bfc032a1SShawn Emery  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15bfc032a1SShawn Emery  * If applicable, add the following below this CDDL HEADER, with the
16bfc032a1SShawn Emery  * fields enclosed by brackets "[]" replaced with your own identifying
17bfc032a1SShawn Emery  * information: Portions Copyright [yyyy] [name of copyright owner]
18bfc032a1SShawn Emery  *
19bfc032a1SShawn Emery  * CDDL HEADER END
20bfc032a1SShawn Emery  */
21bfc032a1SShawn Emery 
22bfc032a1SShawn Emery /*
23bfc032a1SShawn Emery  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24bfc032a1SShawn Emery  */
25bfc032a1SShawn Emery 
26bfc032a1SShawn Emery /*
27bfc032a1SShawn Emery  * prof_solaris.c:
28bfc032a1SShawn Emery  * Abstracted contract private interfaces for configuring krb5.conf(4).
29bfc032a1SShawn Emery  */
30bfc032a1SShawn Emery 
31bfc032a1SShawn Emery #include <ctype.h>
32bfc032a1SShawn Emery #include "prof_int.h"
33bfc032a1SShawn Emery #include "k5-int.h"
34bfc032a1SShawn Emery 
35bfc032a1SShawn Emery errcode_t
36bfc032a1SShawn Emery __profile_iter_name_value(profile_t profile, char *section, char *key,
37bfc032a1SShawn Emery 	char ***retvals)
38bfc032a1SShawn Emery {
39bfc032a1SShawn Emery 	const char	*hierarchy[4];
40bfc032a1SShawn Emery 	errcode_t	code, code2;
41bfc032a1SShawn Emery 	char		*name = NULL, *value = NULL, **ret_values = NULL;
42bfc032a1SShawn Emery 	void		*state = NULL;
43bfc032a1SShawn Emery 	struct profile_string_list values;
44bfc032a1SShawn Emery 	boolean_t	found = FALSE;
45bfc032a1SShawn Emery 
46bfc032a1SShawn Emery 	hierarchy[0] = section;
47bfc032a1SShawn Emery 	hierarchy[1] = NULL;
48bfc032a1SShawn Emery 
49bfc032a1SShawn Emery 	if (code = init_list(&values))
50bfc032a1SShawn Emery 		return (code);
51bfc032a1SShawn Emery 
52bfc032a1SShawn Emery 	code = profile_iterator_create(profile, hierarchy,
53bfc032a1SShawn Emery 	    PROFILE_ITER_LIST_SECTION, &state);
54bfc032a1SShawn Emery 	while (code == 0) {
55bfc032a1SShawn Emery 		code = profile_iterator(&state, &name, &value);
56bfc032a1SShawn Emery 		if (code == 0 && name != NULL) {
57bfc032a1SShawn Emery 			if ((key == NULL) || (strcmp(value, key) == 0)) {
58bfc032a1SShawn Emery 				code2 = add_to_list(&values, name);
59bfc032a1SShawn Emery 				if (code2 != 0) {
60bfc032a1SShawn Emery 					end_list(&values, &ret_values);
61bfc032a1SShawn Emery 					profile_free_list(ret_values);
62bfc032a1SShawn Emery 					code2 = code;
63bfc032a1SShawn Emery 					goto cleanup;
64bfc032a1SShawn Emery 				}
65bfc032a1SShawn Emery 				found = TRUE;
66bfc032a1SShawn Emery 			}
67bfc032a1SShawn Emery 		}
68bfc032a1SShawn Emery 		if (name != NULL) {
69bfc032a1SShawn Emery 			profile_release_string(name);
70bfc032a1SShawn Emery 			name = NULL;
71bfc032a1SShawn Emery 		}
72bfc032a1SShawn Emery 		if (value != NULL) {
73bfc032a1SShawn Emery 			profile_release_string(value);
74bfc032a1SShawn Emery 			value = NULL;
75bfc032a1SShawn Emery 		}
76bfc032a1SShawn Emery 	}
77bfc032a1SShawn Emery 	code = 0;
78bfc032a1SShawn Emery 	if (found == TRUE)
79bfc032a1SShawn Emery 		end_list(&values, &ret_values);
80bfc032a1SShawn Emery 
81bfc032a1SShawn Emery cleanup:
82bfc032a1SShawn Emery 
83bfc032a1SShawn Emery 	if (state != NULL)
84bfc032a1SShawn Emery 		profile_iterator_free(&state);
85bfc032a1SShawn Emery 	if (name != NULL)
86bfc032a1SShawn Emery 		profile_release_string(name);
87bfc032a1SShawn Emery 	if (value != NULL)
88bfc032a1SShawn Emery 		profile_release_string(value);
89bfc032a1SShawn Emery 
90bfc032a1SShawn Emery 	*retvals = ret_values;
91bfc032a1SShawn Emery 
92bfc032a1SShawn Emery 	return (code);
93bfc032a1SShawn Emery }
94bfc032a1SShawn Emery 
95bfc032a1SShawn Emery errcode_t
96bfc032a1SShawn Emery __profile_get_domain_realm(profile_t profile, char *realm, char ***domains)
97bfc032a1SShawn Emery {
98bfc032a1SShawn Emery 	if (profile == NULL || realm == NULL || domains == NULL)
99bfc032a1SShawn Emery 		return (EINVAL);
100bfc032a1SShawn Emery 
101bfc032a1SShawn Emery 	return (__profile_iter_name_value(profile, "domain_realm", realm,
102bfc032a1SShawn Emery 	    domains));
103bfc032a1SShawn Emery }
104bfc032a1SShawn Emery 
105bfc032a1SShawn Emery errcode_t
106bfc032a1SShawn Emery __profile_set_appdefaults(profile_t profile)
107bfc032a1SShawn Emery {
108bfc032a1SShawn Emery 	const char	*hierarchy[4];
109bfc032a1SShawn Emery 	errcode_t	code;
110bfc032a1SShawn Emery 
111bfc032a1SShawn Emery 	if (profile == NULL)
112bfc032a1SShawn Emery 		return (EINVAL);
113bfc032a1SShawn Emery 
114bfc032a1SShawn Emery 	hierarchy[0] = "appdefaults";
115bfc032a1SShawn Emery 	hierarchy[1] = "kinit";
116bfc032a1SShawn Emery 	hierarchy[3] = NULL;
117bfc032a1SShawn Emery 
118bfc032a1SShawn Emery 	hierarchy[2] = "renewable";
119bfc032a1SShawn Emery 
120bfc032a1SShawn Emery 	/*
121bfc032a1SShawn Emery 	 * Not fatal if this fails, continue on.
122bfc032a1SShawn Emery 	 */
123bfc032a1SShawn Emery 	(void) profile_clear_relation(profile, hierarchy);
124bfc032a1SShawn Emery 
125bfc032a1SShawn Emery 	code = profile_add_relation(profile, hierarchy, "true");
126bfc032a1SShawn Emery 	if (code != 0)
127bfc032a1SShawn Emery 		return (code);
128bfc032a1SShawn Emery 
129bfc032a1SShawn Emery 	hierarchy[2] = "forwardable";
130bfc032a1SShawn Emery 
131bfc032a1SShawn Emery 	(void) profile_clear_relation(profile, hierarchy);
132bfc032a1SShawn Emery 
133bfc032a1SShawn Emery 	code = profile_add_relation(profile, hierarchy, "true");
134bfc032a1SShawn Emery 
135bfc032a1SShawn Emery 	return (code);
136bfc032a1SShawn Emery }
137bfc032a1SShawn Emery 
138bfc032a1SShawn Emery errcode_t
139bfc032a1SShawn Emery __profile_set_logging(profile_t profile)
140bfc032a1SShawn Emery {
141bfc032a1SShawn Emery 	const char	*hierarchy[4];
142bfc032a1SShawn Emery 	errcode_t	code;
143bfc032a1SShawn Emery 
144bfc032a1SShawn Emery 	if (profile == NULL)
145bfc032a1SShawn Emery 		return (EINVAL);
146bfc032a1SShawn Emery 
147bfc032a1SShawn Emery 	hierarchy[0] = "logging";
148bfc032a1SShawn Emery 	hierarchy[2] = NULL;
149bfc032a1SShawn Emery 	hierarchy[3] = NULL;
150bfc032a1SShawn Emery 
151bfc032a1SShawn Emery 	hierarchy[1] = "default";
152bfc032a1SShawn Emery 
153bfc032a1SShawn Emery 	/*
154bfc032a1SShawn Emery 	 * Not fatal if this fails, continue on.
155bfc032a1SShawn Emery 	 */
156bfc032a1SShawn Emery 	(void) profile_clear_relation(profile, hierarchy);
157bfc032a1SShawn Emery 
158bfc032a1SShawn Emery 	code = profile_add_relation(profile, hierarchy,
159bfc032a1SShawn Emery 	    "FILE:/var/krb5/kdc.log");
160bfc032a1SShawn Emery 	if (code != 0)
161bfc032a1SShawn Emery 		return (code);
162bfc032a1SShawn Emery 
163bfc032a1SShawn Emery 	hierarchy[1] = "kdc";
164bfc032a1SShawn Emery 
165bfc032a1SShawn Emery 	(void) profile_clear_relation(profile, hierarchy);
166bfc032a1SShawn Emery 
167bfc032a1SShawn Emery 	code = profile_add_relation(profile, hierarchy,
168bfc032a1SShawn Emery 	    "FILE:/var/krb5/kdc.log");
169bfc032a1SShawn Emery 	if (code != 0)
170bfc032a1SShawn Emery 		return (code);
171bfc032a1SShawn Emery 
172bfc032a1SShawn Emery 	hierarchy[1] = "kdc_rotate";
173bfc032a1SShawn Emery 
174bfc032a1SShawn Emery 	hierarchy[2] = "period";
175bfc032a1SShawn Emery 
176bfc032a1SShawn Emery 	(void) profile_clear_relation(profile, hierarchy);
177bfc032a1SShawn Emery 
178bfc032a1SShawn Emery 	code = profile_add_relation(profile, hierarchy, "1d");
179bfc032a1SShawn Emery 	if (code != 0)
180bfc032a1SShawn Emery 		return (code);
181bfc032a1SShawn Emery 
182bfc032a1SShawn Emery 	hierarchy[2] = "versions";
183bfc032a1SShawn Emery 
184bfc032a1SShawn Emery 	(void) profile_clear_relation(profile, hierarchy);
185bfc032a1SShawn Emery 
186bfc032a1SShawn Emery 	code = profile_add_relation(profile, hierarchy, "10");
187bfc032a1SShawn Emery 
188bfc032a1SShawn Emery 	return (code);
189bfc032a1SShawn Emery }
190bfc032a1SShawn Emery 
191bfc032a1SShawn Emery errcode_t
192bfc032a1SShawn Emery __profile_set_libdefaults(profile_t profile, char *realm)
193bfc032a1SShawn Emery {
194bfc032a1SShawn Emery 	const char	*hierarchy[4];
195bfc032a1SShawn Emery 	errcode_t	code;
196bfc032a1SShawn Emery 
197bfc032a1SShawn Emery 	if (profile == NULL || realm == NULL)
198bfc032a1SShawn Emery 		return (EINVAL);
199bfc032a1SShawn Emery 
200bfc032a1SShawn Emery 	hierarchy[0] = "libdefaults";
201bfc032a1SShawn Emery 	hierarchy[1] = "default_realm";
202bfc032a1SShawn Emery 	hierarchy[2] = NULL;
203bfc032a1SShawn Emery 
204bfc032a1SShawn Emery 	/*
205bfc032a1SShawn Emery 	 * Not fatal if this fails, continue on.
206bfc032a1SShawn Emery 	 */
207bfc032a1SShawn Emery 	(void) profile_clear_relation(profile, hierarchy);
208bfc032a1SShawn Emery 
209bfc032a1SShawn Emery 	code = profile_add_relation(profile, hierarchy, realm);
210bfc032a1SShawn Emery 
211bfc032a1SShawn Emery 	return (code);
212bfc032a1SShawn Emery }
213bfc032a1SShawn Emery 
214bfc032a1SShawn Emery errcode_t
215bfc032a1SShawn Emery __profile_set_kdc(profile_t profile, char *realm, char *kdc,
216bfc032a1SShawn Emery 	boolean_t overwrite)
217bfc032a1SShawn Emery {
218bfc032a1SShawn Emery 	const char	*hierarchy[4];
219bfc032a1SShawn Emery 	errcode_t	code;
220bfc032a1SShawn Emery 
221bfc032a1SShawn Emery 	if (profile == NULL || realm == NULL || kdc == NULL)
222bfc032a1SShawn Emery 		return (EINVAL);
223bfc032a1SShawn Emery 
224bfc032a1SShawn Emery 	hierarchy[0] = "realms";
225bfc032a1SShawn Emery 	hierarchy[1] = realm;
226bfc032a1SShawn Emery 	hierarchy[3] = NULL;
227bfc032a1SShawn Emery 
228bfc032a1SShawn Emery 	hierarchy[2] = "kdc";
229bfc032a1SShawn Emery 
230bfc032a1SShawn Emery 	if (overwrite == TRUE) {
231bfc032a1SShawn Emery 		/*
232bfc032a1SShawn Emery 		 * Not fatal if this fails, continue on.
233bfc032a1SShawn Emery 		 */
234bfc032a1SShawn Emery 		(void) profile_clear_relation(profile, hierarchy);
235bfc032a1SShawn Emery 	}
236bfc032a1SShawn Emery 
237bfc032a1SShawn Emery 	code = profile_add_relation(profile, hierarchy, kdc);
238bfc032a1SShawn Emery 
239bfc032a1SShawn Emery 	return (code);
240bfc032a1SShawn Emery }
241bfc032a1SShawn Emery 
242bfc032a1SShawn Emery /*
243bfc032a1SShawn Emery  * errcode_t __profile_release(profile_t profile)
244bfc032a1SShawn Emery  *
245bfc032a1SShawn Emery  * where profile was the pointer passed back by __profile_init
246bfc032a1SShawn Emery  * Note: used to commit the associated profile to the backing store
247bfc032a1SShawn Emery  * (e.g. file) and free profile memory
248bfc032a1SShawn Emery  * Note: that this function returns an error code which profile_release
249bfc032a1SShawn Emery  * does not.  With the error code, the application can determine if they
250bfc032a1SShawn Emery  * need to free the resulting profile information in memory
251bfc032a1SShawn Emery  */
252bfc032a1SShawn Emery errcode_t
253bfc032a1SShawn Emery __profile_release(profile_t profile)
254bfc032a1SShawn Emery {
255bfc032a1SShawn Emery 	prf_file_t	p, next;
256bfc032a1SShawn Emery 	errcode_t	code;
257bfc032a1SShawn Emery 
258bfc032a1SShawn Emery 	if (profile == NULL || profile->magic != PROF_MAGIC_PROFILE)
259bfc032a1SShawn Emery 		return (EINVAL);
260bfc032a1SShawn Emery 
261bfc032a1SShawn Emery 	for (p = profile->first_file; p; p = next) {
262bfc032a1SShawn Emery 		next = p->next;
263bfc032a1SShawn Emery 		if ((code = profile_close_file(p)) != 0)
264bfc032a1SShawn Emery 			return (code);
265bfc032a1SShawn Emery 	}
266bfc032a1SShawn Emery 	profile->magic = 0;
267bfc032a1SShawn Emery 	free(profile);
268bfc032a1SShawn Emery 
269bfc032a1SShawn Emery 	return (0);
270bfc032a1SShawn Emery }
271bfc032a1SShawn Emery 
272bfc032a1SShawn Emery /*
273bfc032a1SShawn Emery  * void __profile_abandon(profile_t profile)
274bfc032a1SShawn Emery  *
275bfc032a1SShawn Emery  * where profile was the pointer passed back by __profile_init
276bfc032a1SShawn Emery  * Note: used to free any profile information in memory.  Typically can
277bfc032a1SShawn Emery  * be used in conjunction with __profile_release upon error
278bfc032a1SShawn Emery  */
279bfc032a1SShawn Emery void
280bfc032a1SShawn Emery __profile_abandon(profile_t profile)
281bfc032a1SShawn Emery {
282bfc032a1SShawn Emery 	profile_abandon(profile);
283bfc032a1SShawn Emery }
284bfc032a1SShawn Emery 
285bfc032a1SShawn Emery /*
286bfc032a1SShawn Emery  * errcode_t __profile_add_domain_mapping(profile_t profile, char *domain,
287bfc032a1SShawn Emery  *	char *realm)
288bfc032a1SShawn Emery  *
289bfc032a1SShawn Emery  * where profile was the pointer passed back by __profile_init
290bfc032a1SShawn Emery  * where domain is the domain name of the associated realm name
291bfc032a1SShawn Emery  * where realm is the corresponding realm name for the domain
292bfc032a1SShawn Emery  */
293bfc032a1SShawn Emery errcode_t
294bfc032a1SShawn Emery __profile_add_domain_mapping(profile_t profile, char *domain, char *realm)
295bfc032a1SShawn Emery {
296bfc032a1SShawn Emery 	const char	*hierarchy[4];
297bfc032a1SShawn Emery 	errcode_t	code = 0;
298bfc032a1SShawn Emery 
299bfc032a1SShawn Emery 	if (profile == NULL || domain == NULL || realm == NULL)
300bfc032a1SShawn Emery 		return (EINVAL);
301bfc032a1SShawn Emery 
302bfc032a1SShawn Emery 	hierarchy[0] = "domain_realm";
303bfc032a1SShawn Emery 	hierarchy[1] = domain;
304bfc032a1SShawn Emery 	hierarchy[2] = NULL;
305bfc032a1SShawn Emery 
306bfc032a1SShawn Emery 	/*
307bfc032a1SShawn Emery 	 * Not fatal if relation can't be cleared, continue on.
308bfc032a1SShawn Emery 	 */
309bfc032a1SShawn Emery 	(void) profile_clear_relation(profile, hierarchy);
310bfc032a1SShawn Emery 
311bfc032a1SShawn Emery 	code = profile_add_relation(profile, hierarchy, realm);
312bfc032a1SShawn Emery 
313bfc032a1SShawn Emery 	return (code);
314bfc032a1SShawn Emery }
315bfc032a1SShawn Emery 
316bfc032a1SShawn Emery /*
317bfc032a1SShawn Emery  * errcode_t __profile_remove_domain_mapping(profile_t profile,	char *realm)
318bfc032a1SShawn Emery  *
319bfc032a1SShawn Emery  * where profile was the pointer passed back by __profile_init
320bfc032a1SShawn Emery  * where domain is the domain name of the associated realm name
321bfc032a1SShawn Emery  * where realm is the corresponding realm name for the domain
322bfc032a1SShawn Emery  * Note: for the remove function, all matching domain - realm mappings
323bfc032a1SShawn Emery  * will be removed for realm
324bfc032a1SShawn Emery  */
325bfc032a1SShawn Emery errcode_t
326bfc032a1SShawn Emery __profile_remove_domain_mapping(profile_t profile, char *realm)
327bfc032a1SShawn Emery {
328bfc032a1SShawn Emery 	const char	*hierarchy[4];
329bfc032a1SShawn Emery 	errcode_t	code;
330bfc032a1SShawn Emery 	char		**domains = NULL, **domain = NULL;
331bfc032a1SShawn Emery 
332bfc032a1SShawn Emery 	if (profile == NULL || realm == NULL)
333bfc032a1SShawn Emery 		return (EINVAL);
334bfc032a1SShawn Emery 
335bfc032a1SShawn Emery 	hierarchy[0] = "domain_realm";
336bfc032a1SShawn Emery 	hierarchy[1] = NULL;
337bfc032a1SShawn Emery 	hierarchy[2] = NULL;
338bfc032a1SShawn Emery 
339bfc032a1SShawn Emery 	code = __profile_get_domain_realm(profile, realm, &domains);
340bfc032a1SShawn Emery 	if (code == 0 && domains != NULL) {
341bfc032a1SShawn Emery 		for (domain = domains; *domain; domain++) {
342bfc032a1SShawn Emery 			hierarchy[1] = *domain;
343bfc032a1SShawn Emery 			code = profile_clear_relation(profile, hierarchy);
344bfc032a1SShawn Emery 			if (code != 0)
345bfc032a1SShawn Emery 				goto error;
346bfc032a1SShawn Emery 		}
347bfc032a1SShawn Emery 	}
348bfc032a1SShawn Emery 
349bfc032a1SShawn Emery error:
350bfc032a1SShawn Emery 	if (domains != NULL)
351bfc032a1SShawn Emery 		profile_free_list(domains);
352bfc032a1SShawn Emery 
353bfc032a1SShawn Emery 	return (code);
354bfc032a1SShawn Emery }
355bfc032a1SShawn Emery 
356bfc032a1SShawn Emery /*
357bfc032a1SShawn Emery  * errcode_t __profile_get_realm_entry(profile_t profile, char *realm,
358bfc032a1SShawn Emery  *	char *name, char ***ret_value)
359bfc032a1SShawn Emery  *
360bfc032a1SShawn Emery  * where profile was the pointer passed back by __profile_init
361bfc032a1SShawn Emery  * where realm is the target realm for lookup
362bfc032a1SShawn Emery  * where name is the name in the realm section requested
363bfc032a1SShawn Emery  * where value is a string array of any matching values assigned to name.
364bfc032a1SShawn Emery  * The array is terminated with a NULL pointer.
365bfc032a1SShawn Emery  * Note: if no name has been configured and a profile does exist
366bfc032a1SShawn Emery  * then value is set to NULL
367bfc032a1SShawn Emery  */
368bfc032a1SShawn Emery errcode_t
369bfc032a1SShawn Emery __profile_get_realm_entry(profile_t profile, char *realm, char *name,
370bfc032a1SShawn Emery 	char ***ret_value)
371bfc032a1SShawn Emery {
372bfc032a1SShawn Emery 	const char	*hierarchy[4];
373bfc032a1SShawn Emery 	errcode_t	code;
374bfc032a1SShawn Emery 	char		**values = NULL;
375bfc032a1SShawn Emery 
376bfc032a1SShawn Emery 	if (profile == NULL || realm == NULL || name == NULL ||
377bfc032a1SShawn Emery 	    ret_value == NULL)
378bfc032a1SShawn Emery 		return (EINVAL);
379bfc032a1SShawn Emery 
380bfc032a1SShawn Emery 	hierarchy[0] = "realms";
381bfc032a1SShawn Emery 	hierarchy[1] = realm;
382bfc032a1SShawn Emery 	hierarchy[2] = name;
383bfc032a1SShawn Emery 	hierarchy[3] = NULL;
384bfc032a1SShawn Emery 
385bfc032a1SShawn Emery 	code = profile_get_values(profile, hierarchy, &values);
386bfc032a1SShawn Emery 	if (code == 0 && values != NULL)
387bfc032a1SShawn Emery 		*ret_value = values;
388bfc032a1SShawn Emery 
389938d11f4SShawn Emery 	if (code == PROF_NO_RELATION)
390938d11f4SShawn Emery 		code = 0;
391bfc032a1SShawn Emery 
392bfc032a1SShawn Emery 	return (code);
393bfc032a1SShawn Emery }
394bfc032a1SShawn Emery 
395bfc032a1SShawn Emery /*
396bfc032a1SShawn Emery  * errcode_t __profile_add_realm_entry(profile_t profile, char *realm,
397bfc032a1SShawn Emery  *	char *name, char **value)
398bfc032a1SShawn Emery  *
399bfc032a1SShawn Emery  * where profile was the pointer passed back by __profile_init
400bfc032a1SShawn Emery  * where realm is the target realm for the name-value pair
401bfc032a1SShawn Emery  * where name is the name in the realm subsection to add
402bfc032a1SShawn Emery  * where value is a string array values to assigned to name.  The array is
403bfc032a1SShawn Emery  * terminated with a NULL pointer.
404bfc032a1SShawn Emery  * Note: if the realm subsection does no exist then an error is returned
405bfc032a1SShawn Emery  * Note: if the name already exists the set is overwritten with the values
406bfc032a1SShawn Emery  * passed
407bfc032a1SShawn Emery  */
408bfc032a1SShawn Emery errcode_t
409bfc032a1SShawn Emery __profile_add_realm_entry(profile_t profile, char *realm, char *name,
410bfc032a1SShawn Emery 	char **values)
411bfc032a1SShawn Emery {
412bfc032a1SShawn Emery 	const char	*hierarchy[4];
413bfc032a1SShawn Emery 	errcode_t	code;
414bfc032a1SShawn Emery 	char		**tvalue = NULL;
415bfc032a1SShawn Emery 
416bfc032a1SShawn Emery 	if (profile == NULL || realm == NULL || name == NULL || values == NULL)
417bfc032a1SShawn Emery 		return (EINVAL);
418bfc032a1SShawn Emery 
419bfc032a1SShawn Emery 	hierarchy[0] = "realms";
420bfc032a1SShawn Emery 	hierarchy[1] = realm;
421bfc032a1SShawn Emery 	hierarchy[2] = name;
422bfc032a1SShawn Emery 	hierarchy[3] = NULL;
423bfc032a1SShawn Emery 
424bfc032a1SShawn Emery 	/*
425bfc032a1SShawn Emery 	 * Not fatal if this fails, continue on.
426bfc032a1SShawn Emery 	 */
427bfc032a1SShawn Emery 	(void) profile_clear_relation(profile, hierarchy);
428bfc032a1SShawn Emery 
429bfc032a1SShawn Emery 	for (tvalue = values; *tvalue; tvalue++) {
430bfc032a1SShawn Emery 
431bfc032a1SShawn Emery 		code = profile_add_relation(profile, hierarchy, *tvalue);
432bfc032a1SShawn Emery 		if (code != 0)
433bfc032a1SShawn Emery 			return (code);
434bfc032a1SShawn Emery 	}
435bfc032a1SShawn Emery 
436bfc032a1SShawn Emery 	return (0);
437bfc032a1SShawn Emery }
438bfc032a1SShawn Emery 
439bfc032a1SShawn Emery /*
440bfc032a1SShawn Emery  * errcode_t __profile_get_default_realm(profile_t profile, char **realm)
441bfc032a1SShawn Emery  *
442bfc032a1SShawn Emery  * where profile was the pointer passed back by __profile_init
443bfc032a1SShawn Emery  * where realm is the default_realm configured for the system
444bfc032a1SShawn Emery  * Note: if no default_realm has been configured and a profile does exist
445bfc032a1SShawn Emery  * then realm is set to NULL
446bfc032a1SShawn Emery  */
447bfc032a1SShawn Emery errcode_t
448bfc032a1SShawn Emery __profile_get_default_realm(profile_t profile, char **realm)
449bfc032a1SShawn Emery {
450bfc032a1SShawn Emery 	errcode_t	code;
451bfc032a1SShawn Emery 	char		*value = NULL;
452bfc032a1SShawn Emery 
453bfc032a1SShawn Emery 	if (profile == NULL || realm == NULL)
454bfc032a1SShawn Emery 		return (EINVAL);
455bfc032a1SShawn Emery 
456bfc032a1SShawn Emery 	code = profile_get_string(profile, "libdefaults", "default_realm", 0, 0,
457bfc032a1SShawn Emery 	    &value);
458bfc032a1SShawn Emery 	if (code == 0 && value != NULL)
459bfc032a1SShawn Emery 		*realm = value;
460bfc032a1SShawn Emery 
461938d11f4SShawn Emery 	if (code == PROF_NO_RELATION)
462938d11f4SShawn Emery 		code = 0;
463bfc032a1SShawn Emery 
464bfc032a1SShawn Emery 	return (code);
465bfc032a1SShawn Emery }
466bfc032a1SShawn Emery 
467bfc032a1SShawn Emery /*
468bfc032a1SShawn Emery  * errcode_t __profile_get_realms(profile_t profile, char ***realms)
469bfc032a1SShawn Emery  *
470bfc032a1SShawn Emery  * where profile was the pointer passed back by __profile_init
471bfc032a1SShawn Emery  * where realms is a string array of realm names currently configured.
472bfc032a1SShawn Emery  * The array is terminated with a NULL pointer.
473bfc032a1SShawn Emery  * Note: if no realms have been configured and a profile does exist then
474bfc032a1SShawn Emery  * realms is set to NULL
475bfc032a1SShawn Emery  */
476bfc032a1SShawn Emery errcode_t
477bfc032a1SShawn Emery __profile_get_realms(profile_t profile, char ***realms)
478bfc032a1SShawn Emery {
479bfc032a1SShawn Emery 
480bfc032a1SShawn Emery 	if (profile == NULL || realms == NULL)
481bfc032a1SShawn Emery 		return (EINVAL);
482bfc032a1SShawn Emery 
483bfc032a1SShawn Emery 	return (__profile_iter_name_value(profile, "realms", NULL, realms));
484bfc032a1SShawn Emery }
485bfc032a1SShawn Emery 
486bfc032a1SShawn Emery /*
487bfc032a1SShawn Emery  * errcode_t __profile_add_realm(profile_t profile, char *realm,
488bfc032a1SShawn Emery  *	char *master, char **kdcs, boolean_t set_change, boolean_t
489bfc032a1SShawn Emery  *	default_realm)
490bfc032a1SShawn Emery  *
491bfc032a1SShawn Emery  * where profile was the pointer passed back by __profile_init
492bfc032a1SShawn Emery  * where realm is the realm name associated with the configuration
493bfc032a1SShawn Emery  * where master is the server that is assigned to admin_server
494bfc032a1SShawn Emery  * where kdcs is a string array of KDCs used to populate the kdc set.
495bfc032a1SShawn Emery  * The array is terminated with a NULL pointer.
496bfc032a1SShawn Emery  * where set_change, if set, will use the SET_CHANGE protocol for password
497bfc032a1SShawn Emery  * modifications.  RPCSEC_GSS is set by default
498bfc032a1SShawn Emery  * where default_realm, if set, will assign the realm to default_realm
499bfc032a1SShawn Emery  * Note: the ordering of kdcs is determined by the server's position in the
500bfc032a1SShawn Emery  * array
501bfc032a1SShawn Emery  * Note: kdcs must be assigned a value, even if it is the same value as the
502bfc032a1SShawn Emery  * master.
503bfc032a1SShawn Emery  */
504bfc032a1SShawn Emery errcode_t
505bfc032a1SShawn Emery __profile_add_realm(profile_t profile, char *realm, char *master, char **kdcs,
506bfc032a1SShawn Emery 	boolean_t set_change, boolean_t default_realm)
507bfc032a1SShawn Emery {
508bfc032a1SShawn Emery 	const char	*hierarchy[4];
509bfc032a1SShawn Emery 	errcode_t	code;
510bfc032a1SShawn Emery 	boolean_t	ow = TRUE;
511bfc032a1SShawn Emery 	char		**tkdcs;
512bfc032a1SShawn Emery 
513bfc032a1SShawn Emery 	if (profile == NULL || realm == NULL || master == NULL || kdcs == NULL)
514bfc032a1SShawn Emery 		return (EINVAL);
515bfc032a1SShawn Emery 
516bfc032a1SShawn Emery 	/*
517bfc032a1SShawn Emery 	 * Sets the default realm to realm if default_realm flag is set.
518bfc032a1SShawn Emery 	 */
519bfc032a1SShawn Emery 	if (default_realm == TRUE) {
520bfc032a1SShawn Emery 		if (code = __profile_set_libdefaults(profile, realm))
521bfc032a1SShawn Emery 			return (code);
522bfc032a1SShawn Emery 	}
523bfc032a1SShawn Emery 
524bfc032a1SShawn Emery 	hierarchy[0] = "realms";
525bfc032a1SShawn Emery 	hierarchy[1] = realm;
526bfc032a1SShawn Emery 	hierarchy[3] = NULL;
527bfc032a1SShawn Emery 
528bfc032a1SShawn Emery 	hierarchy[2] = "admin_server";
529bfc032a1SShawn Emery 
530bfc032a1SShawn Emery 	/*
531bfc032a1SShawn Emery 	 * Not fatal if this fails, therefore return code is not checked.
532bfc032a1SShawn Emery 	 */
533bfc032a1SShawn Emery 	(void) profile_clear_relation(profile, hierarchy);
534bfc032a1SShawn Emery 
535bfc032a1SShawn Emery 	if (code = profile_add_relation(profile, hierarchy, master))
536bfc032a1SShawn Emery 		return (code);
537bfc032a1SShawn Emery 
538bfc032a1SShawn Emery 	/*
539bfc032a1SShawn Emery 	 * If not set then defaults to undefined, which defaults to RPCSEC_GSS.
540bfc032a1SShawn Emery 	 */
541bfc032a1SShawn Emery 	if (set_change == TRUE) {
542bfc032a1SShawn Emery 		hierarchy[2] = "kpasswd_protocol";
543bfc032a1SShawn Emery 
544bfc032a1SShawn Emery 		(void) profile_clear_relation(profile, hierarchy);
545bfc032a1SShawn Emery 
546bfc032a1SShawn Emery 		code = profile_add_relation(profile, hierarchy, "SET_CHANGE");
547bfc032a1SShawn Emery 		if (code != 0)
548bfc032a1SShawn Emery 			return (code);
549bfc032a1SShawn Emery 	}
550bfc032a1SShawn Emery 
551bfc032a1SShawn Emery 	for (tkdcs = kdcs; *tkdcs; tkdcs++) {
552bfc032a1SShawn Emery 		if (code = __profile_set_kdc(profile, realm, *tkdcs, ow))
553bfc032a1SShawn Emery 			return (code);
554bfc032a1SShawn Emery 		ow = FALSE;
555bfc032a1SShawn Emery 	}
556bfc032a1SShawn Emery 
557bfc032a1SShawn Emery 	code = __profile_set_logging(profile);
558bfc032a1SShawn Emery 	if (code != 0)
559bfc032a1SShawn Emery 		return (code);
560bfc032a1SShawn Emery 
561bfc032a1SShawn Emery 	code = __profile_set_appdefaults(profile);
562bfc032a1SShawn Emery 
563bfc032a1SShawn Emery 	return (code);
564bfc032a1SShawn Emery }
565bfc032a1SShawn Emery 
566bfc032a1SShawn Emery /*
567bfc032a1SShawn Emery  * errcode_t __profile_remove_xrealm_mapping(profile_t profile, char *realm)
568bfc032a1SShawn Emery  *
569bfc032a1SShawn Emery  * where profile was the pointer passed back by __profile_init
570bfc032a1SShawn Emery  * where source is the source realm for the capath
571bfc032a1SShawn Emery  * where target is the target realm for the capath
572bfc032a1SShawn Emery  * where inter is the intermediate realm between the source and target
573bfc032a1SShawn Emery  * realms.  If the source and target share x-realm keys then this set to "."
574bfc032a1SShawn Emery  * Note: for the remove function, all associated source, target, and
575bfc032a1SShawn Emery  * intermediate entries will be removed matching the realm name
576bfc032a1SShawn Emery  */
577bfc032a1SShawn Emery errcode_t
578bfc032a1SShawn Emery __profile_remove_xrealm_mapping(profile_t profile, char *realm)
579bfc032a1SShawn Emery {
580bfc032a1SShawn Emery 	const char	*hierarchy[4];
581bfc032a1SShawn Emery 	errcode_t	code, code2, code3;
582bfc032a1SShawn Emery 	void		*state = NULL, *state2 = NULL;
583bfc032a1SShawn Emery 	char		*source = NULL, *dummy_val = NULL, *target = NULL;
584bfc032a1SShawn Emery 	char		*inter = NULL;
585bfc032a1SShawn Emery 
586bfc032a1SShawn Emery 	if (profile == NULL || realm == NULL)
587bfc032a1SShawn Emery 		return (EINVAL);
588bfc032a1SShawn Emery 
589bfc032a1SShawn Emery 	hierarchy[0] = "capaths";
590bfc032a1SShawn Emery 	hierarchy[1] = realm;
591bfc032a1SShawn Emery 	hierarchy[2] = NULL;
592bfc032a1SShawn Emery 	hierarchy[3] = NULL;
593bfc032a1SShawn Emery 
594bfc032a1SShawn Emery 	/*
595bfc032a1SShawn Emery 	 * Not fatal if this fails, continue on.
596bfc032a1SShawn Emery 	 */
597bfc032a1SShawn Emery 	code = profile_rename_section(profile, hierarchy, NULL);
598bfc032a1SShawn Emery 
599bfc032a1SShawn Emery 	hierarchy[1] = NULL;
600bfc032a1SShawn Emery 	code = profile_iterator_create(profile, hierarchy,
601bfc032a1SShawn Emery 	    PROFILE_ITER_LIST_SECTION, &state);
602bfc032a1SShawn Emery 	while (code == 0) {
603bfc032a1SShawn Emery 		code = profile_iterator(&state, &source, &dummy_val);
604bfc032a1SShawn Emery 		if (code == 0 && source != NULL) {
605bfc032a1SShawn Emery 			hierarchy[1] = source;
606bfc032a1SShawn Emery 			code2 = profile_iterator_create(profile, hierarchy,
607bfc032a1SShawn Emery 			    PROFILE_ITER_LIST_SECTION, &state2);
608bfc032a1SShawn Emery 			while (code2 == 0) {
609bfc032a1SShawn Emery 				code2 = profile_iterator(&state2, &target,
610bfc032a1SShawn Emery 				    &inter);
611bfc032a1SShawn Emery 				if (code2 == 0 && target != NULL &&
612bfc032a1SShawn Emery 				    inter != NULL) {
613bfc032a1SShawn Emery 					if (strcmp(realm, target) == 0 ||
614bfc032a1SShawn Emery 					    strcmp(realm, inter) == 0) {
615bfc032a1SShawn Emery 						hierarchy[2] = target;
616bfc032a1SShawn Emery 						code3 =
617bfc032a1SShawn Emery 						    profile_clear_relation(
618bfc032a1SShawn Emery 						    profile, hierarchy);
619bfc032a1SShawn Emery 						if (code3 != 0) {
620bfc032a1SShawn Emery 							code = code3;
621bfc032a1SShawn Emery 							goto error;
622bfc032a1SShawn Emery 						}
623bfc032a1SShawn Emery 					}
624bfc032a1SShawn Emery 				}
625bfc032a1SShawn Emery 				if (target != NULL) {
626bfc032a1SShawn Emery 					profile_release_string(target);
627bfc032a1SShawn Emery 					target = NULL;
628bfc032a1SShawn Emery 				}
629bfc032a1SShawn Emery 				if (inter != NULL) {
630bfc032a1SShawn Emery 					profile_release_string(inter);
631bfc032a1SShawn Emery 					inter = NULL;
632bfc032a1SShawn Emery 				}
633bfc032a1SShawn Emery 			}
634bfc032a1SShawn Emery 		}
635bfc032a1SShawn Emery 		if (source != NULL) {
636bfc032a1SShawn Emery 			profile_release_string(source);
637bfc032a1SShawn Emery 			source = NULL;
638bfc032a1SShawn Emery 		}
639bfc032a1SShawn Emery 		if (dummy_val != NULL) {
640bfc032a1SShawn Emery 			profile_release_string(dummy_val);
641bfc032a1SShawn Emery 			dummy_val = NULL;
642bfc032a1SShawn Emery 		}
643bfc032a1SShawn Emery 	}
644bfc032a1SShawn Emery 	code = 0;
645bfc032a1SShawn Emery 
646bfc032a1SShawn Emery error:
647bfc032a1SShawn Emery 	if (state != NULL)
648bfc032a1SShawn Emery 		profile_iterator_free(&state);
649bfc032a1SShawn Emery 	if (state2 != NULL)
650bfc032a1SShawn Emery 		profile_iterator_free(&state2);
651bfc032a1SShawn Emery 	if (target != NULL)
652bfc032a1SShawn Emery 		profile_release_string(target);
653bfc032a1SShawn Emery 	if (inter != NULL)
654bfc032a1SShawn Emery 		profile_release_string(inter);
655bfc032a1SShawn Emery 	if (source != NULL)
656bfc032a1SShawn Emery 		profile_release_string(source);
657bfc032a1SShawn Emery 	if (dummy_val != NULL)
658bfc032a1SShawn Emery 		profile_release_string(dummy_val);
659bfc032a1SShawn Emery 
660bfc032a1SShawn Emery 	return (code);
661bfc032a1SShawn Emery }
662bfc032a1SShawn Emery 
663bfc032a1SShawn Emery /*
664bfc032a1SShawn Emery  * errcode_t __profile_remove_realm(profile_t profile, char *realm)
665bfc032a1SShawn Emery  *
666bfc032a1SShawn Emery  * where profile was the pointer passed back by __profile_init
667bfc032a1SShawn Emery  * where realm is the target realm for removal
668bfc032a1SShawn Emery  * Note: the function removes the matching realm in the realms section,
669bfc032a1SShawn Emery  * the default_realm, relevant domain_realm mappings with the realm name,
670bfc032a1SShawn Emery  * and matching capaths source realm subsection.
671bfc032a1SShawn Emery  */
672bfc032a1SShawn Emery errcode_t
673bfc032a1SShawn Emery __profile_remove_realm(profile_t profile, char *realm)
674bfc032a1SShawn Emery {
675bfc032a1SShawn Emery 	const char	*hierarchy[4];
676bfc032a1SShawn Emery 	errcode_t	code;
677938d11f4SShawn Emery 	char		*drealm = NULL;
678bfc032a1SShawn Emery 
679bfc032a1SShawn Emery 	if (profile == NULL || realm == NULL)
680bfc032a1SShawn Emery 		return (EINVAL);
681bfc032a1SShawn Emery 
682bfc032a1SShawn Emery 	/*
683bfc032a1SShawn Emery 	 * Remove the default realm.
684bfc032a1SShawn Emery 	 */
685bfc032a1SShawn Emery 	hierarchy[0] = "libdefaults";
686bfc032a1SShawn Emery 	hierarchy[1] = "default_realm";
687bfc032a1SShawn Emery 	hierarchy[2] = NULL;
688bfc032a1SShawn Emery 
689bfc032a1SShawn Emery 	code = __profile_get_default_realm(profile, &drealm);
690bfc032a1SShawn Emery 	if (code != 0)
691bfc032a1SShawn Emery 		return (code);
692bfc032a1SShawn Emery 	else if (drealm != NULL) {
693bfc032a1SShawn Emery 		if (strcmp(drealm, realm) == 0) {
694bfc032a1SShawn Emery 			code = profile_clear_relation(profile, hierarchy);
695938d11f4SShawn Emery 			if (code != 0) {
696938d11f4SShawn Emery 				free(drealm);
697bfc032a1SShawn Emery 				return (code);
698938d11f4SShawn Emery 			}
699bfc032a1SShawn Emery 		}
700bfc032a1SShawn Emery 		free(drealm);
701bfc032a1SShawn Emery 	}
702bfc032a1SShawn Emery 
703bfc032a1SShawn Emery 	hierarchy[0] = "realms";
704bfc032a1SShawn Emery 	hierarchy[1] = realm;
705bfc032a1SShawn Emery 	hierarchy[2] = NULL;
706bfc032a1SShawn Emery 
707bfc032a1SShawn Emery 	code = profile_rename_section(profile, hierarchy, NULL);
708bfc032a1SShawn Emery 	if (code != 0)
709bfc032a1SShawn Emery 		return (code);
710bfc032a1SShawn Emery 
711bfc032a1SShawn Emery 	code = __profile_remove_domain_mapping(profile, realm);
712bfc032a1SShawn Emery 	if (code != 0)
713bfc032a1SShawn Emery 		return (code);
714bfc032a1SShawn Emery 
715bfc032a1SShawn Emery 	code = __profile_remove_xrealm_mapping(profile, realm);
716bfc032a1SShawn Emery 	if (code != 0)
717bfc032a1SShawn Emery 		return (code);
718bfc032a1SShawn Emery 
719bfc032a1SShawn Emery 	/*
720bfc032a1SShawn Emery 	 * Not fatal even if realm wasn't available to remove.
721bfc032a1SShawn Emery 	 */
722bfc032a1SShawn Emery 	return (0);
723bfc032a1SShawn Emery }
724bfc032a1SShawn Emery 
725bfc032a1SShawn Emery /*
726bfc032a1SShawn Emery  * errcode_t __profile_add_xrealm_mapping(profile_t profile, char *source,
727bfc032a1SShawn Emery  *	char *target, char *inter)
728bfc032a1SShawn Emery  *
729bfc032a1SShawn Emery  * where profile was the pointer passed back by __profile_init
730bfc032a1SShawn Emery  * where source is the source realm for the capath
731bfc032a1SShawn Emery  * where target is the target realm for the capath
732bfc032a1SShawn Emery  * where inter is the intermediate realm between the source and target
733bfc032a1SShawn Emery  * realms.  If the source and target share x-realm keys then this set to "."
734bfc032a1SShawn Emery  * Note: if the section does not exist one will be created
735bfc032a1SShawn Emery  */
736bfc032a1SShawn Emery errcode_t
737bfc032a1SShawn Emery __profile_add_xrealm_mapping(profile_t profile, char *source, char *target,
738bfc032a1SShawn Emery 	char *inter)
739bfc032a1SShawn Emery {
740bfc032a1SShawn Emery 	const char	*hierarchy[4];
741bfc032a1SShawn Emery 	errcode_t	code;
742bfc032a1SShawn Emery 
743bfc032a1SShawn Emery 	if (profile == NULL || source == NULL || target == NULL ||
744bfc032a1SShawn Emery 	    inter == NULL)
745bfc032a1SShawn Emery 		return (EINVAL);
746bfc032a1SShawn Emery 
747bfc032a1SShawn Emery 	hierarchy[0] = "capaths";
748bfc032a1SShawn Emery 	hierarchy[1] = source;
749bfc032a1SShawn Emery 	hierarchy[2] = target;
750bfc032a1SShawn Emery 	hierarchy[3] = NULL;
751bfc032a1SShawn Emery 
752bfc032a1SShawn Emery 	/*
753bfc032a1SShawn Emery 	 * Not fatal if this fails, continue on.
754bfc032a1SShawn Emery 	 */
755bfc032a1SShawn Emery 	(void) profile_clear_relation(profile, hierarchy);
756bfc032a1SShawn Emery 
757bfc032a1SShawn Emery 	code = profile_add_relation(profile, hierarchy, inter);
758bfc032a1SShawn Emery 
759bfc032a1SShawn Emery 	return (code);
760bfc032a1SShawn Emery }
761bfc032a1SShawn Emery 
762bfc032a1SShawn Emery /*
763bfc032a1SShawn Emery  * errcode_t __profile_validate(profile_t profile, int *val_err, char **val)
764bfc032a1SShawn Emery  *
765bfc032a1SShawn Emery  * where profile was the pointer passed back by __profile_init
766bfc032a1SShawn Emery  * where val_err is a function specific error code of the following values:
767bfc032a1SShawn Emery  *	0 No errors detected in profile
768bfc032a1SShawn Emery  *	1 default realm is in lower-case (val returns realm)
769bfc032a1SShawn Emery  *	2 realm in realms section is in lower-case (val returns realm)
770bfc032a1SShawn Emery  *	3 default realm is not found in realms section
771bfc032a1SShawn Emery  *		(val returns realm not found)
772bfc032a1SShawn Emery  *	4 default realm does not exist
773bfc032a1SShawn Emery  *	5 no realm found in realms section
774bfc032a1SShawn Emery  *	6 no domain realm mapping entry found corresponding to a realm
775bfc032a1SShawn Emery  *		in the realms section (val returns realm name)
776bfc032a1SShawn Emery  *	7 kdc relation-value does not exist in realm
777bfc032a1SShawn Emery  *		(val returns realm name)
778bfc032a1SShawn Emery  *	8 admin_server relation-value does not exist in realm
779bfc032a1SShawn Emery  *		(val returns realm name)
780bfc032a1SShawn Emery  * where val is the associated errant value, associated with val_err.  This
781bfc032a1SShawn Emery  * value is returned as is from the profile
782bfc032a1SShawn Emery  * Note: function infers the following:
783bfc032a1SShawn Emery  *	1. REALM should be in upper-case
784bfc032a1SShawn Emery  *	2. all required entries are present
785bfc032a1SShawn Emery  *	3. all relations are defined between default realm, realm, and
786bfc032a1SShawn Emery  *		domain - realm mappings
787938d11f4SShawn Emery  *
788938d11f4SShawn Emery  * Note: The return value of this function is based on the error code returned
789938d11f4SShawn Emery  * by the framework/mechanism.  The function could return zero with the
790938d11f4SShawn Emery  * validation error code set to non-zero if the profile is invalid in any way.
791938d11f4SShawn Emery  *
792bfc032a1SShawn Emery  * Caution: This function could return false positives on valid
793bfc032a1SShawn Emery  * configurations and should only be used by the CIFS team for
794bfc032a1SShawn Emery  * specific purposes.
795bfc032a1SShawn Emery  */
796bfc032a1SShawn Emery errcode_t
797bfc032a1SShawn Emery __profile_validate(profile_t profile, int *val_err, char **val)
798bfc032a1SShawn Emery {
799bfc032a1SShawn Emery 	errcode_t	code;
800*940daf74SToomas Soome 	int		c;
801bfc032a1SShawn Emery 	boolean_t	found = FALSE;
802bfc032a1SShawn Emery 	char		*default_realm = NULL, **realms = NULL, *tr = NULL;
803bfc032a1SShawn Emery 	char		**trealms = NULL, **domains = NULL, **ret_vals = NULL;
804bfc032a1SShawn Emery 
805bfc032a1SShawn Emery 	if (profile == NULL || val_err == NULL || val == NULL)
806bfc032a1SShawn Emery 		return (EINVAL);
807bfc032a1SShawn Emery 
808bfc032a1SShawn Emery 	*val_err = 0;
809bfc032a1SShawn Emery 	*val = NULL;
810bfc032a1SShawn Emery 
811bfc032a1SShawn Emery 	code = __profile_get_default_realm(profile, &default_realm);
812bfc032a1SShawn Emery 	if (code == 0 && default_realm != NULL) {
813bfc032a1SShawn Emery 		tr = default_realm;
814bfc032a1SShawn Emery 
815*940daf74SToomas Soome 		while ((c = *tr++) != 0) {
816bfc032a1SShawn Emery 			if (islower(c)) {
817bfc032a1SShawn Emery 				*val_err = 1;
818bfc032a1SShawn Emery 				*val = strdup(default_realm);
819bfc032a1SShawn Emery 				if (*val == NULL)
820bfc032a1SShawn Emery 					code = ENOMEM;
821bfc032a1SShawn Emery 				goto cleanup;
822bfc032a1SShawn Emery 			}
823bfc032a1SShawn Emery 		}
824bfc032a1SShawn Emery 	} else if (code == 0 && default_realm == NULL) {
825bfc032a1SShawn Emery 		*val_err = 4;
826bfc032a1SShawn Emery 		goto cleanup;
827bfc032a1SShawn Emery 	} else
828bfc032a1SShawn Emery 		goto cleanup;
829bfc032a1SShawn Emery 
830bfc032a1SShawn Emery 	code = __profile_get_realms(profile, &realms);
831bfc032a1SShawn Emery 	if (code == 0 && realms != NULL) {
832bfc032a1SShawn Emery 		for (trealms = realms; *trealms; trealms++) {
833bfc032a1SShawn Emery 
834bfc032a1SShawn Emery 			tr = *trealms;
835*940daf74SToomas Soome 			while ((c = *tr++) != 0) {
836bfc032a1SShawn Emery 				if (islower(c)) {
837bfc032a1SShawn Emery 					*val_err = 2;
838bfc032a1SShawn Emery 					*val = strdup(*trealms);
839bfc032a1SShawn Emery 					if (*val == NULL)
840bfc032a1SShawn Emery 						code = ENOMEM;
841bfc032a1SShawn Emery 					goto cleanup;
842bfc032a1SShawn Emery 				}
843bfc032a1SShawn Emery 			}
844bfc032a1SShawn Emery 
845bfc032a1SShawn Emery 			if (strcmp(default_realm, *trealms) == 0)
846bfc032a1SShawn Emery 				found = TRUE;
847bfc032a1SShawn Emery 
848bfc032a1SShawn Emery 			code = __profile_get_domain_realm(profile, *trealms,
849bfc032a1SShawn Emery 			    &domains);
850bfc032a1SShawn Emery 			if (code == 0 && domains != NULL) {
851bfc032a1SShawn Emery 				profile_free_list(domains);
852bfc032a1SShawn Emery 				domains = NULL;
853bfc032a1SShawn Emery 			} else if (code == 0 && domains == NULL) {
854bfc032a1SShawn Emery 				*val_err = 6;
855bfc032a1SShawn Emery 				*val = strdup(*trealms);
856bfc032a1SShawn Emery 				if (*val == NULL)
857bfc032a1SShawn Emery 					code = ENOMEM;
858bfc032a1SShawn Emery 				goto cleanup;
859bfc032a1SShawn Emery 			} else
860bfc032a1SShawn Emery 				goto cleanup;
861bfc032a1SShawn Emery 
862bfc032a1SShawn Emery 			code = __profile_get_realm_entry(profile, *trealms,
863bfc032a1SShawn Emery 			    "kdc", &ret_vals);
864bfc032a1SShawn Emery 			if (code == 0 && ret_vals != NULL) {
865bfc032a1SShawn Emery 				profile_free_list(ret_vals);
866bfc032a1SShawn Emery 				ret_vals = NULL;
867bfc032a1SShawn Emery 			} else if (code == 0 && ret_vals == NULL) {
868bfc032a1SShawn Emery 				*val_err = 7;
869bfc032a1SShawn Emery 				*val = strdup(*trealms);
870bfc032a1SShawn Emery 				if (*val == NULL)
871bfc032a1SShawn Emery 					code = ENOMEM;
872bfc032a1SShawn Emery 				goto cleanup;
873bfc032a1SShawn Emery 			} else
874bfc032a1SShawn Emery 				goto cleanup;
875bfc032a1SShawn Emery 
876bfc032a1SShawn Emery 			code = __profile_get_realm_entry(profile, *trealms,
877bfc032a1SShawn Emery 			    "admin_server", &ret_vals);
878bfc032a1SShawn Emery 			if (code == 0 && ret_vals != NULL) {
879bfc032a1SShawn Emery 				profile_free_list(ret_vals);
880bfc032a1SShawn Emery 				ret_vals = NULL;
881bfc032a1SShawn Emery 			} else if (code == 0 && ret_vals == NULL) {
882bfc032a1SShawn Emery 				*val_err = 8;
883bfc032a1SShawn Emery 				*val = strdup(*trealms);
884bfc032a1SShawn Emery 				if (*val == NULL)
885bfc032a1SShawn Emery 					code = ENOMEM;
886bfc032a1SShawn Emery 				goto cleanup;
887bfc032a1SShawn Emery 			} else
888bfc032a1SShawn Emery 				goto cleanup;
889bfc032a1SShawn Emery 		}
890bfc032a1SShawn Emery 
891bfc032a1SShawn Emery 		if (found == FALSE) {
892bfc032a1SShawn Emery 			*val_err = 3;
893bfc032a1SShawn Emery 			*val = strdup(default_realm);
894bfc032a1SShawn Emery 			if (*val == NULL)
895bfc032a1SShawn Emery 				code = ENOMEM;
896bfc032a1SShawn Emery 			goto cleanup;
897bfc032a1SShawn Emery 		}
898bfc032a1SShawn Emery 	} else if (code == 0 && realms == NULL)
899bfc032a1SShawn Emery 		*val_err = 5;
900bfc032a1SShawn Emery 
901bfc032a1SShawn Emery cleanup:
902bfc032a1SShawn Emery 
903bfc032a1SShawn Emery 	if (realms != NULL)
904bfc032a1SShawn Emery 		profile_free_list(realms);
905bfc032a1SShawn Emery 	if (ret_vals != NULL)
906bfc032a1SShawn Emery 		profile_free_list(ret_vals);
907bfc032a1SShawn Emery 	if (default_realm != NULL)
908bfc032a1SShawn Emery 		profile_release_string(default_realm);
909bfc032a1SShawn Emery 	if (domains != NULL)
910bfc032a1SShawn Emery 		profile_free_list(domains);
911bfc032a1SShawn Emery 
912bfc032a1SShawn Emery 	return (code);
913bfc032a1SShawn Emery }
914bfc032a1SShawn Emery 
915bfc032a1SShawn Emery /*
916bfc032a1SShawn Emery  * errcode_t __profile_init(char *filename, profile_t *profile)
917bfc032a1SShawn Emery  *
918bfc032a1SShawn Emery  * where filename is the specified profile location.  If filename is NULL
919bfc032a1SShawn Emery  * then function uses the system default name, /etc/krb5/krb5.conf
920bfc032a1SShawn Emery  * where profile is pointer passed to caller upon success
921bfc032a1SShawn Emery  * Note: if the file does not exist then one will be created
922bfc032a1SShawn Emery  * Note: if the file does exist then any existing profile information will
923bfc032a1SShawn Emery  * be in profile
924bfc032a1SShawn Emery  * Note: profile_release() should be used by the caller to free profile
925bfc032a1SShawn Emery  */
926bfc032a1SShawn Emery errcode_t
927bfc032a1SShawn Emery __profile_init(char *filename, profile_t *profile)
928bfc032a1SShawn Emery {
929bfc032a1SShawn Emery 	profile_filespec_t	*filenames = NULL;
930bfc032a1SShawn Emery 	krb5_error_code		ret = 0;
931bfc032a1SShawn Emery 	errcode_t		code = 0;
932bfc032a1SShawn Emery 	int			err = 0, fd;
933bfc032a1SShawn Emery 	mode_t			mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
934bfc032a1SShawn Emery 
935bfc032a1SShawn Emery 	if (profile == NULL)
936bfc032a1SShawn Emery 		return (EINVAL);
937bfc032a1SShawn Emery 
938bfc032a1SShawn Emery 	if (filename != NULL) {
939bfc032a1SShawn Emery 		filenames = malloc(2 * sizeof (char *));
940bfc032a1SShawn Emery 		if (filenames == NULL)
941bfc032a1SShawn Emery 			return (ENOMEM);
942bfc032a1SShawn Emery 		filenames[0] = strdup(filename);
943bfc032a1SShawn Emery 		if (filenames[0] == NULL) {
944bfc032a1SShawn Emery 			free(filenames);
945bfc032a1SShawn Emery 			return (ENOMEM);
946bfc032a1SShawn Emery 		}
947bfc032a1SShawn Emery 		filenames[1] = NULL;
948bfc032a1SShawn Emery 	} else {
949bfc032a1SShawn Emery 		ret = krb5_get_default_config_files(&filenames);
950bfc032a1SShawn Emery 		if (ret != 0)
951bfc032a1SShawn Emery 			return (ret);
952bfc032a1SShawn Emery 	}
953bfc032a1SShawn Emery