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