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