1 /*
2  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 #pragma ident	"%Z%%M%	%I%	%E% SMI"
7 
8 /*
9  * appdefault - routines designed to be called from applications to
10  *		 handle the [appdefaults] profile section
11  */
12 #include <stdio.h>
13 #include <string.h>
14 #include <k5-int.h>
15 
16 
17 
18  /*xxx Duplicating this is annoying; try to work on a better way.*/
19 static const char *conf_yes[] = {
20 	"y", "yes", "true", "t", "1", "on",
21 	0,
22 };
23 
24 static const char *conf_no[] = {
25 	"n", "no", "false", "nil", "0", "off",
26 	0,
27 };
28 
29 static int conf_boolean(char *s)
30 {
31 	const char * const *p;
32 	for(p=conf_yes; *p; p++) {
33 		if (!strcasecmp(*p,s))
34 			return 1;
35 	}
36 	for(p=conf_no; *p; p++) {
37 		if (!strcasecmp(*p,s))
38 		return 0;
39 	}
40 	/* Default to "no" */
41 	return 0;
42 }
43 
44 static krb5_error_code appdefault_get(krb5_context context,
45 			const char *appname, const krb5_data *realm,
46 			const char *option, char **ret_value)
47 {
48         profile_t profile;
49         const char *names[5];
50 	char **nameval = NULL;
51 	krb5_error_code retval;
52 	const char * realmstr =  realm?realm->data:NULL;
53 
54 	    if (!context || (context->magic != KV5M_CONTEXT))
55 	    return KV5M_CONTEXT;
56 
57 	    profile = context->profile;
58 
59 	/*
60 	 * Try number one:
61 	 *
62 	 * [appdefaults]
63 	 *	app = {
64 	 *		SOME.REALM = {
65 	 *			option = <boolean>
66 	 *		}
67 	 *	}
68 	 */
69 
70 	names[0] = "appdefaults";
71 	names[1] = appname;
72 
73 	if (realmstr) {
74 		names[2] = realmstr;
75 		names[3] = option;
76 		names[4] = 0;
77 		retval = profile_get_values(profile, names, &nameval);
78 		if (retval == 0 && nameval && nameval[0]) {
79 			*ret_value = strdup(nameval[0]);
80 			goto goodbye;
81 		}
82 	}
83 
84 	/*
85 	 * Try number two:
86 	 *
87 	 * [appdefaults]
88 	 *	app = {
89 	 *		option = <boolean>
90 	 *      }
91 	 */
92 
93 	names[2] = option;
94 	names[3] = 0;
95 	retval = profile_get_values(profile, names, &nameval);
96 	if (retval == 0 && nameval && nameval[0]) {
97 		*ret_value = strdup(nameval[0]);
98 		goto goodbye;
99 	}
100 
101 	/*
102 	 * Try number three:
103 	 *
104 	 * [appdefaults]
105 	 *	realm = {
106 	 *		option = <boolean>
107 	 */
108 
109 	if (realmstr) {
110 		names[1] = realmstr;
111 		names[2] = option;
112 		names[3] = 0;
113 		retval = profile_get_values(profile, names, &nameval);
114 		if (retval == 0 && nameval && nameval[0]) {
115 			*ret_value = strdup(nameval[0]);
116 			goto goodbye;
117 		}
118 	}
119 
120 	/*
121 	 * Try number four:
122 	 *
123 	 * [appdefaults]
124 	 *	option = <boolean>
125 	 */
126 
127 	names[1] = option;
128 	names[2] = 0;
129 	retval = profile_get_values(profile, names, &nameval);
130 	if (retval == 0 && nameval && nameval[0]) {
131 		*ret_value = strdup(nameval[0]);
132 	} else {
133 		return retval;
134 	}
135 
136 goodbye:
137 	if (nameval) {
138 		char **cpp;
139 		for (cpp = nameval; *cpp; cpp++)
140 			free(*cpp);
141 		free(nameval);
142 	}
143 	return 0;
144 }
145 
146 void KRB5_CALLCONV
147 krb5_appdefault_boolean(krb5_context context,
148 		const char *appname, const krb5_data *realm,
149 		const char *option, int default_value,
150 		int *ret_value)
151 {
152 	char *string = NULL;
153 	krb5_error_code retval;
154 
155 	retval = appdefault_get(context, appname, realm, option, &string);
156 
157 	if (! retval && string) {
158 		*ret_value = conf_boolean(string);
159 		free(string);
160 	} else
161 		*ret_value = default_value;
162 }
163 
164 void KRB5_CALLCONV
165 krb5_appdefault_string(krb5_context context, const char *appname,
166 		const krb5_data *realm, const char *option,
167 		const char *default_value, char **ret_value)
168 {
169 	krb5_error_code retval;
170 	char *string;
171 
172 	retval = appdefault_get(context, appname, realm, option, &string);
173 
174 	if (! retval && string) {
175 		*ret_value = string;
176 	} else {
177 		*ret_value = strdup(default_value);
178 	}
179 }
180