1*159d09a2SMark Phalan /*
2*159d09a2SMark Phalan  * COPYRIGHT (C) 2006,2007
3*159d09a2SMark Phalan  * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
4*159d09a2SMark Phalan  * ALL RIGHTS RESERVED
5*159d09a2SMark Phalan  *
6*159d09a2SMark Phalan  * Permission is granted to use, copy, create derivative works
7*159d09a2SMark Phalan  * and redistribute this software and such derivative works
8*159d09a2SMark Phalan  * for any purpose, so long as the name of The University of
9*159d09a2SMark Phalan  * Michigan is not used in any advertising or publicity
10*159d09a2SMark Phalan  * pertaining to the use of distribution of this software
11*159d09a2SMark Phalan  * without specific, written prior authorization.  If the
12*159d09a2SMark Phalan  * above copyright notice or any other identification of the
13*159d09a2SMark Phalan  * University of Michigan is included in any copy of any
14*159d09a2SMark Phalan  * portion of this software, then the disclaimer below must
15*159d09a2SMark Phalan  * also be included.
16*159d09a2SMark Phalan  *
17*159d09a2SMark Phalan  * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
18*159d09a2SMark Phalan  * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
19*159d09a2SMark Phalan  * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
20*159d09a2SMark Phalan  * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
21*159d09a2SMark Phalan  * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
22*159d09a2SMark Phalan  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
23*159d09a2SMark Phalan  * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
24*159d09a2SMark Phalan  * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
25*159d09a2SMark Phalan  * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
26*159d09a2SMark Phalan  * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
27*159d09a2SMark Phalan  * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
28*159d09a2SMark Phalan  * SUCH DAMAGES.
29*159d09a2SMark Phalan  */
30*159d09a2SMark Phalan 
31*159d09a2SMark Phalan #include <stdio.h>
32*159d09a2SMark Phalan #include <stdlib.h>
33*159d09a2SMark Phalan #include <errno.h>
34*159d09a2SMark Phalan #include <string.h>
35*159d09a2SMark Phalan 
36*159d09a2SMark Phalan #include "k5-int.h"
37*159d09a2SMark Phalan #include "pkinit.h"
38*159d09a2SMark Phalan 
39*159d09a2SMark Phalan /*
40*159d09a2SMark Phalan  * Routines for handling profile [config file] options
41*159d09a2SMark Phalan  */
42*159d09a2SMark Phalan 
43*159d09a2SMark Phalan /* Forward prototypes */
44*159d09a2SMark Phalan static int _krb5_conf_boolean(const char *s);
45*159d09a2SMark Phalan 
46*159d09a2SMark Phalan /*
47*159d09a2SMark Phalan  * XXX
48*159d09a2SMark Phalan  * The following is duplicated verbatim from src/lib/krb5/krb/get_in_tkt.c,
49*159d09a2SMark Phalan  * which is duplicated from somewhere else. :-/
50*159d09a2SMark Phalan  * XXX
51*159d09a2SMark Phalan  */
52*159d09a2SMark Phalan static const char *const conf_yes[] = {
53*159d09a2SMark Phalan     "y", "yes", "true", "t", "1", "on",
54*159d09a2SMark Phalan     0,
55*159d09a2SMark Phalan };
56*159d09a2SMark Phalan 
57*159d09a2SMark Phalan static const char *const conf_no[] = {
58*159d09a2SMark Phalan     "n", "no", "false", "nil", "0", "off",
59*159d09a2SMark Phalan     0,
60*159d09a2SMark Phalan };
61*159d09a2SMark Phalan 
62*159d09a2SMark Phalan static int
_krb5_conf_boolean(const char * s)63*159d09a2SMark Phalan _krb5_conf_boolean(const char *s)
64*159d09a2SMark Phalan {
65*159d09a2SMark Phalan     const char *const *p;
66*159d09a2SMark Phalan 
67*159d09a2SMark Phalan     for(p=conf_yes; *p; p++) {
68*159d09a2SMark Phalan 	if (strcasecmp(*p,s) == 0)
69*159d09a2SMark Phalan 	    return 1;
70*159d09a2SMark Phalan     }
71*159d09a2SMark Phalan 
72*159d09a2SMark Phalan     for(p=conf_no; *p; p++) {
73*159d09a2SMark Phalan 	if (strcasecmp(*p,s) == 0)
74*159d09a2SMark Phalan 	    return 0;
75*159d09a2SMark Phalan     }
76*159d09a2SMark Phalan 
77*159d09a2SMark Phalan     /* Default to "no" */
78*159d09a2SMark Phalan     return 0;
79*159d09a2SMark Phalan }
80*159d09a2SMark Phalan 
81*159d09a2SMark Phalan /*
82*159d09a2SMark Phalan  * XXX
83*159d09a2SMark Phalan  * End duplicated code from src/lib/krb5/krb/get_in_tkt.c
84*159d09a2SMark Phalan  * XXX
85*159d09a2SMark Phalan  */
86*159d09a2SMark Phalan 
87*159d09a2SMark Phalan /*
88*159d09a2SMark Phalan  * The following are based on krb5_libdefault_* functions in
89*159d09a2SMark Phalan  * src/lib/krb5/krb/get_in_tkt.c
90*159d09a2SMark Phalan  * N.B.  This assumes that context->default_realm has
91*159d09a2SMark Phalan  * already been established.
92*159d09a2SMark Phalan  */
93*159d09a2SMark Phalan krb5_error_code
pkinit_kdcdefault_strings(krb5_context context,const char * realmname,const char * option,char *** ret_value)94*159d09a2SMark Phalan pkinit_kdcdefault_strings(krb5_context context, const char *realmname,
95*159d09a2SMark Phalan 			  const char *option, char ***ret_value)
96*159d09a2SMark Phalan {
97*159d09a2SMark Phalan     profile_t profile = NULL;
98*159d09a2SMark Phalan     const char *names[5];
99*159d09a2SMark Phalan     char **values = NULL;
100*159d09a2SMark Phalan     krb5_error_code retval;
101*159d09a2SMark Phalan 
102*159d09a2SMark Phalan     if (context == NULL)
103*159d09a2SMark Phalan 	return KV5M_CONTEXT;
104*159d09a2SMark Phalan 
105*159d09a2SMark Phalan     profile = context->profile;
106*159d09a2SMark Phalan 
107*159d09a2SMark Phalan     if (realmname != NULL) {
108*159d09a2SMark Phalan 	/*
109*159d09a2SMark Phalan 	 * Try number one:
110*159d09a2SMark Phalan 	 *
111*159d09a2SMark Phalan 	 * [realms]
112*159d09a2SMark Phalan 	 *	    REALM = {
113*159d09a2SMark Phalan 	 *		option = <value>
114*159d09a2SMark Phalan 	 *	    }
115*159d09a2SMark Phalan 	 */
116*159d09a2SMark Phalan 
117*159d09a2SMark Phalan 	names[0] = "realms";
118*159d09a2SMark Phalan 	names[1] = realmname;
119*159d09a2SMark Phalan 	names[2] = option;
120*159d09a2SMark Phalan 	names[3] = 0;
121*159d09a2SMark Phalan 	retval = profile_get_values(profile, names, &values);
122*159d09a2SMark Phalan 	if (retval == 0 && values != NULL)
123*159d09a2SMark Phalan 	    goto goodbye;
124*159d09a2SMark Phalan     }
125*159d09a2SMark Phalan 
126*159d09a2SMark Phalan     /*
127*159d09a2SMark Phalan      * Try number two:
128*159d09a2SMark Phalan      *
129*159d09a2SMark Phalan      * [kdcdefaults]
130*159d09a2SMark Phalan      *	    option = <value>
131*159d09a2SMark Phalan      */
132*159d09a2SMark Phalan 
133*159d09a2SMark Phalan     names[0] = "kdcdefaults";
134*159d09a2SMark Phalan     names[1] = option;
135*159d09a2SMark Phalan     names[2] = 0;
136*159d09a2SMark Phalan     retval = profile_get_values(profile, names, &values);
137*159d09a2SMark Phalan     if (retval == 0 && values != NULL)
138*159d09a2SMark Phalan 	goto goodbye;
139*159d09a2SMark Phalan 
140*159d09a2SMark Phalan goodbye:
141*159d09a2SMark Phalan     if (values == NULL)
142*159d09a2SMark Phalan 	retval = ENOENT;
143*159d09a2SMark Phalan 
144*159d09a2SMark Phalan     *ret_value = values;
145*159d09a2SMark Phalan 
146*159d09a2SMark Phalan     return retval;
147*159d09a2SMark Phalan 
148*159d09a2SMark Phalan }
149*159d09a2SMark Phalan 
150*159d09a2SMark Phalan krb5_error_code
pkinit_kdcdefault_string(krb5_context context,const char * realmname,const char * option,char ** ret_value)151*159d09a2SMark Phalan pkinit_kdcdefault_string(krb5_context context, const char *realmname,
152*159d09a2SMark Phalan 			 const char *option, char **ret_value)
153*159d09a2SMark Phalan {
154*159d09a2SMark Phalan     krb5_error_code retval;
155*159d09a2SMark Phalan     char **values = NULL;
156*159d09a2SMark Phalan 
157*159d09a2SMark Phalan     retval = pkinit_kdcdefault_strings(context, realmname, option, &values);
158*159d09a2SMark Phalan     if (retval)
159*159d09a2SMark Phalan 	return retval;
160*159d09a2SMark Phalan 
161*159d09a2SMark Phalan     if (values[0] == NULL) {
162*159d09a2SMark Phalan 	retval = ENOENT;
163*159d09a2SMark Phalan     } else {
164*159d09a2SMark Phalan 	*ret_value = malloc(strlen(values[0]) + 1);
165*159d09a2SMark Phalan 	/* Solaris Kerberos */
166*159d09a2SMark Phalan 	if (*ret_value == NULL) {
167*159d09a2SMark Phalan 	    pkiDebug(error_message(ENOMEM));
168*159d09a2SMark Phalan 	    retval = ENOMEM;
169*159d09a2SMark Phalan 	}
170*159d09a2SMark Phalan 	else /* Solaris Kerberos */
171*159d09a2SMark Phalan 	    (void) strlcpy(*ret_value, values[0], strlen(values[0]) + 1);
172*159d09a2SMark Phalan     }
173*159d09a2SMark Phalan 
174*159d09a2SMark Phalan     profile_free_list(values);
175*159d09a2SMark Phalan     return retval;
176*159d09a2SMark Phalan }
177*159d09a2SMark Phalan 
178*159d09a2SMark Phalan krb5_error_code
pkinit_kdcdefault_boolean(krb5_context context,const char * realmname,const char * option,int default_value,int * ret_value)179*159d09a2SMark Phalan pkinit_kdcdefault_boolean(krb5_context context, const char *realmname,
180*159d09a2SMark Phalan 			  const char *option, int default_value, int *ret_value)
181*159d09a2SMark Phalan {
182*159d09a2SMark Phalan     char *string = NULL;
183*159d09a2SMark Phalan     krb5_error_code retval;
184*159d09a2SMark Phalan 
185*159d09a2SMark Phalan     retval = pkinit_kdcdefault_string(context, realmname, option, &string);
186*159d09a2SMark Phalan 
187*159d09a2SMark Phalan     if (retval == 0) {
188*159d09a2SMark Phalan 	*ret_value = _krb5_conf_boolean(string);
189*159d09a2SMark Phalan 	free(string);
190*159d09a2SMark Phalan     } else
191*159d09a2SMark Phalan 	*ret_value = default_value;
192*159d09a2SMark Phalan 
193*159d09a2SMark Phalan     return 0;
194*159d09a2SMark Phalan }
195*159d09a2SMark Phalan 
196*159d09a2SMark Phalan krb5_error_code
pkinit_kdcdefault_integer(krb5_context context,const char * realmname,const char * option,int default_value,int * ret_value)197*159d09a2SMark Phalan pkinit_kdcdefault_integer(krb5_context context, const char *realmname,
198*159d09a2SMark Phalan 			  const char *option, int default_value, int *ret_value)
199*159d09a2SMark Phalan {
200*159d09a2SMark Phalan     char *string = NULL;
201*159d09a2SMark Phalan     krb5_error_code retval;
202*159d09a2SMark Phalan 
203*159d09a2SMark Phalan     retval = pkinit_kdcdefault_string(context, realmname, option, &string);
204*159d09a2SMark Phalan 
205*159d09a2SMark Phalan     if (retval == 0) {
206*159d09a2SMark Phalan 	char *endptr;
207*159d09a2SMark Phalan 	long l;
208*159d09a2SMark Phalan 	l = strtol(string, &endptr, 0);
209*159d09a2SMark Phalan 	if (endptr == string)
210*159d09a2SMark Phalan 	    *ret_value = default_value;
211*159d09a2SMark Phalan 	else
212*159d09a2SMark Phalan 	    *ret_value = l;
213*159d09a2SMark Phalan 	free(string);
214*159d09a2SMark Phalan     } else
215*159d09a2SMark Phalan 	*ret_value = default_value;
216*159d09a2SMark Phalan 
217*159d09a2SMark Phalan     return 0;
218*159d09a2SMark Phalan }
219*159d09a2SMark Phalan 
220*159d09a2SMark Phalan 
221*159d09a2SMark Phalan /*
222*159d09a2SMark Phalan  * krb5_libdefault_string() is defined as static in
223*159d09a2SMark Phalan  * src/lib/krb5/krb/get_in_tkt.c.  Create local versions of
224*159d09a2SMark Phalan  * krb5_libdefault_* functions here.  We need a libdefaults_strings()
225*159d09a2SMark Phalan  * function which is not currently supported there anyway.  Also,
226*159d09a2SMark Phalan  * add the ability to supply a default value for the boolean and
227*159d09a2SMark Phalan  * integer functions.
228*159d09a2SMark Phalan  */
229*159d09a2SMark Phalan 
230*159d09a2SMark Phalan krb5_error_code
pkinit_libdefault_strings(krb5_context context,const krb5_data * realm,const char * option,char *** ret_value)231*159d09a2SMark Phalan pkinit_libdefault_strings(krb5_context context, const krb5_data *realm,
232*159d09a2SMark Phalan 			  const char *option, char ***ret_value)
233*159d09a2SMark Phalan {
234*159d09a2SMark Phalan     profile_t profile;
235*159d09a2SMark Phalan     const char *names[5];
236*159d09a2SMark Phalan     char **values = NULL;
237*159d09a2SMark Phalan     krb5_error_code retval;
238*159d09a2SMark Phalan     char realmstr[1024];
239*159d09a2SMark Phalan 
240*159d09a2SMark Phalan     if (realm != NULL && realm->length > sizeof(realmstr)-1)
241*159d09a2SMark Phalan 	return EINVAL;
242*159d09a2SMark Phalan 
243*159d09a2SMark Phalan     if (realm != NULL) {
244*159d09a2SMark Phalan 	/* Solaris Kerberos */
245*159d09a2SMark Phalan 	(void) strlcpy(realmstr, realm->data, realm->length + 1);
246*159d09a2SMark Phalan 	realmstr[realm->length] = '\0';
247*159d09a2SMark Phalan     }
248*159d09a2SMark Phalan 
249*159d09a2SMark Phalan     if (!context || (context->magic != KV5M_CONTEXT))
250*159d09a2SMark Phalan 	return KV5M_CONTEXT;
251*159d09a2SMark Phalan 
252*159d09a2SMark Phalan     profile = context->profile;
253*159d09a2SMark Phalan 
254*159d09a2SMark Phalan 
255*159d09a2SMark Phalan     if (realm != NULL) {
256*159d09a2SMark Phalan 	/*
257*159d09a2SMark Phalan 	 * Try number one:
258*159d09a2SMark Phalan 	 *
259*159d09a2SMark Phalan 	 * [libdefaults]
260*159d09a2SMark Phalan 	 *	  REALM = {
261*159d09a2SMark Phalan 	 *		  option = <value>
262*159d09a2SMark Phalan 	 *	  }
263*159d09a2SMark Phalan 	 */
264*159d09a2SMark Phalan 
265*159d09a2SMark Phalan 	names[0] = "libdefaults";
266*159d09a2SMark Phalan 	names[1] = realmstr;
267*159d09a2SMark Phalan 	names[2] = option;
268*159d09a2SMark Phalan 	names[3] = 0;
269*159d09a2SMark Phalan 	retval = profile_get_values(profile, names, &values);
270*159d09a2SMark Phalan 	if (retval == 0 && values != NULL && values[0] != NULL)
271*159d09a2SMark Phalan 	    goto goodbye;
272*159d09a2SMark Phalan 
273*159d09a2SMark Phalan 	/*
274*159d09a2SMark Phalan 	 * Try number two:
275*159d09a2SMark Phalan 	 *
276*159d09a2SMark Phalan 	 * [realms]
277*159d09a2SMark Phalan 	 *	REALM = {
278*159d09a2SMark Phalan 	 *		option = <value>
279*159d09a2SMark Phalan 	 *	}
280*159d09a2SMark Phalan 	 */
281*159d09a2SMark Phalan 
282*159d09a2SMark Phalan 	names[0] = "realms";
283*159d09a2SMark Phalan 	names[1] = realmstr;
284*159d09a2SMark Phalan 	names[2] = option;
285*159d09a2SMark Phalan 	names[3] = 0;
286*159d09a2SMark Phalan 	retval = profile_get_values(profile, names, &values);
287*159d09a2SMark Phalan 	if (retval == 0 && values != NULL && values[0] != NULL)
288*159d09a2SMark Phalan 	    goto goodbye;
289*159d09a2SMark Phalan     }
290*159d09a2SMark Phalan 
291*159d09a2SMark Phalan     /*
292*159d09a2SMark Phalan      * Try number three:
293*159d09a2SMark Phalan      *
294*159d09a2SMark Phalan      * [libdefaults]
295*159d09a2SMark Phalan      *	      option = <value>
296*159d09a2SMark Phalan      */
297*159d09a2SMark Phalan 
298*159d09a2SMark Phalan     names[0] = "libdefaults";
299*159d09a2SMark Phalan     names[1] = option;
300*159d09a2SMark Phalan     names[2] = 0;
301*159d09a2SMark Phalan     retval = profile_get_values(profile, names, &values);
302*159d09a2SMark Phalan     if (retval == 0 && values != NULL && values[0] != NULL)
303*159d09a2SMark Phalan 	goto goodbye;
304*159d09a2SMark Phalan 
305*159d09a2SMark Phalan goodbye:
306*159d09a2SMark Phalan     if (values == NULL)
307*159d09a2SMark Phalan 	return ENOENT;
308*159d09a2SMark Phalan 
309*159d09a2SMark Phalan     *ret_value = values;
310*159d09a2SMark Phalan 
311*159d09a2SMark Phalan     return retval;
312*159d09a2SMark Phalan }
313*159d09a2SMark Phalan 
314*159d09a2SMark Phalan krb5_error_code
pkinit_libdefault_string(krb5_context context,const krb5_data * realm,const char * option,char ** ret_value)315*159d09a2SMark Phalan pkinit_libdefault_string(krb5_context context, const krb5_data *realm,
316*159d09a2SMark Phalan 			 const char *option, char **ret_value)
317*159d09a2SMark Phalan {
318*159d09a2SMark Phalan     krb5_error_code retval;
319*159d09a2SMark Phalan     char **values = NULL;
320*159d09a2SMark Phalan 
321*159d09a2SMark Phalan     retval = pkinit_libdefault_strings(context, realm, option, &values);
322*159d09a2SMark Phalan     if (retval)
323*159d09a2SMark Phalan 	return retval;
324*159d09a2SMark Phalan 
325*159d09a2SMark Phalan     if (values[0] == NULL) {
326*159d09a2SMark Phalan 	retval = ENOENT;
327*159d09a2SMark Phalan     } else {
328*159d09a2SMark Phalan 	*ret_value = malloc(strlen(values[0]) + 1);
329*159d09a2SMark Phalan 	if (*ret_value == NULL)
330*159d09a2SMark Phalan 	    retval = ENOMEM;
331*159d09a2SMark Phalan 	else /* Solaris Kerberos */
332*159d09a2SMark Phalan 	    (void) strlcpy(*ret_value, values[0], strlen(values[0]) + 1);
333*159d09a2SMark Phalan     }
334*159d09a2SMark Phalan 
335*159d09a2SMark Phalan     profile_free_list(values);
336*159d09a2SMark Phalan     return retval;
337*159d09a2SMark Phalan }
338*159d09a2SMark Phalan 
339*159d09a2SMark Phalan krb5_error_code
pkinit_libdefault_boolean(krb5_context context,const krb5_data * realm,const char * option,int default_value,int * ret_value)340*159d09a2SMark Phalan pkinit_libdefault_boolean(krb5_context context, const krb5_data *realm,
341*159d09a2SMark Phalan 			  const char *option, int default_value,
342*159d09a2SMark Phalan 			  int *ret_value)
343*159d09a2SMark Phalan {
344*159d09a2SMark Phalan     char *string = NULL;
345*159d09a2SMark Phalan     krb5_error_code retval;
346*159d09a2SMark Phalan 
347*159d09a2SMark Phalan     retval = pkinit_libdefault_string(context, realm, option, &string);
348*159d09a2SMark Phalan 
349*159d09a2SMark Phalan    if (retval == 0) {
350*159d09a2SMark Phalan 	*ret_value = _krb5_conf_boolean(string);
351*159d09a2SMark Phalan 	free(string);
352*159d09a2SMark Phalan     } else
353*159d09a2SMark Phalan 	*ret_value = default_value;
354*159d09a2SMark Phalan 
355*159d09a2SMark Phalan     return 0;
356*159d09a2SMark Phalan }
357*159d09a2SMark Phalan 
358*159d09a2SMark Phalan krb5_error_code
pkinit_libdefault_integer(krb5_context context,const krb5_data * realm,const char * option,int default_value,int * ret_value)359*159d09a2SMark Phalan pkinit_libdefault_integer(krb5_context context, const krb5_data *realm,
360*159d09a2SMark Phalan 			  const char *option, int default_value,
361*159d09a2SMark Phalan 			  int *ret_value)
362*159d09a2SMark Phalan {
363*159d09a2SMark Phalan     char *string = NULL;
364*159d09a2SMark Phalan     krb5_error_code retval;
365*159d09a2SMark Phalan 
366*159d09a2SMark Phalan     retval = pkinit_libdefault_string(context, realm, option, &string);
367*159d09a2SMark Phalan 
368*159d09a2SMark Phalan     if (retval == 0) {
369*159d09a2SMark Phalan 	char *endptr;
370*159d09a2SMark Phalan 	long l;
371*159d09a2SMark Phalan 	l = strtol(string, &endptr, 0);
372*159d09a2SMark Phalan 	if (endptr == string)
373*159d09a2SMark Phalan 	    *ret_value = default_value;
374*159d09a2SMark Phalan 	else
375*159d09a2SMark Phalan 	    *ret_value = l;
376*159d09a2SMark Phalan 	free(string);
377*159d09a2SMark Phalan     }
378*159d09a2SMark Phalan 
379*159d09a2SMark Phalan     return retval;
380*159d09a2SMark Phalan }
381