xref: /freebsd/crypto/heimdal/lib/krb5/context.c (revision 5e9cd1ae3e10592ed70e7575551cba1bbab04d84)
1 /*
2  * Copyright (c) 1997 - 2000 Kungliga Tekniska H�gskolan
3  * (Royal Institute of Technology, Stockholm, Sweden).
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the Institute nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #include "krb5_locl.h"
35 
36 RCSID("$Id: context.c,v 1.59 2000/12/15 17:11:51 joda Exp $");
37 
38 #define INIT_FIELD(C, T, E, D, F)					\
39     (C)->E = krb5_config_get_ ## T ## _default ((C), NULL, (D), 	\
40 						"libdefaults", F, NULL)
41 
42 /*
43  * Set the list of etypes `ret_etypes' from the configuration variable
44  * `name'
45  */
46 
47 static krb5_error_code
48 set_etypes (krb5_context context,
49 	    const char *name,
50 	    krb5_enctype **ret_enctypes)
51 {
52     char **etypes_str;
53     krb5_enctype *etypes;
54 
55     etypes_str = krb5_config_get_strings(context, NULL, "libdefaults",
56 					 name, NULL);
57     if(etypes_str){
58 	int i, j, k;
59 	for(i = 0; etypes_str[i]; i++);
60 	etypes = malloc((i+1) * sizeof(*etypes));
61 	if (etypes == NULL) {
62 	    krb5_config_free_strings (etypes_str);
63 	    return ENOMEM;
64 	}
65 	for(j = 0, k = 0; j < i; j++) {
66 	    if(krb5_string_to_enctype(context, etypes_str[j], &etypes[k]) == 0)
67 		k++;
68 	}
69 	etypes[k] = ETYPE_NULL;
70 	krb5_config_free_strings(etypes_str);
71 	*ret_enctypes = etypes;
72     }
73     return 0;
74 }
75 
76 /*
77  * read variables from the configuration file and set in `context'
78  */
79 
80 static krb5_error_code
81 init_context_from_config_file(krb5_context context)
82 {
83     const char * tmp;
84     INIT_FIELD(context, time, max_skew, 5 * 60, "clockskew");
85     INIT_FIELD(context, time, kdc_timeout, 3, "kdc_timeout");
86     INIT_FIELD(context, int, max_retries, 3, "max_retries");
87 
88     INIT_FIELD(context, string, http_proxy, NULL, "http_proxy");
89 
90     set_etypes (context, "default_etypes", &context->etypes);
91     set_etypes (context, "default_etypes_des", &context->etypes_des);
92 
93     /* default keytab name */
94     INIT_FIELD(context, string, default_keytab,
95 	       KEYTAB_DEFAULT, "default_keytab_name");
96 
97     INIT_FIELD(context, string, time_fmt,
98 	       "%Y-%m-%dT%H:%M:%S", "time_format");
99 
100     INIT_FIELD(context, string, date_fmt,
101 	       "%Y-%m-%d", "date_format");
102 
103     INIT_FIELD(context, bool, log_utc,
104 	       FALSE, "log_utc");
105 
106 
107 
108     /* init dns-proxy slime */
109     tmp = krb5_config_get_string(context, NULL, "libdefaults",
110 				 "dns_proxy", NULL);
111     if(tmp)
112 	roken_gethostby_setup(context->http_proxy, tmp);
113     context->default_realms = NULL;
114 
115     {
116 	krb5_addresses addresses;
117 	char **adr, **a;
118 	adr = krb5_config_get_strings(context, NULL,
119 				      "libdefaults",
120 				      "extra_addresses",
121 				      NULL);
122 	memset(&addresses, 0, sizeof(addresses));
123 	for(a = adr; a && *a; a++) {
124 	    krb5_parse_address(context, *a, &addresses);
125 	    krb5_add_extra_addresses(context, &addresses);
126 	    krb5_free_addresses(context, &addresses);
127 	}
128 	krb5_config_free_strings(adr);
129     }
130 
131     INIT_FIELD(context, bool, scan_interfaces, TRUE, "scan_interfaces");
132     INIT_FIELD(context, bool, srv_lookup, TRUE, "srv_lookup");
133     INIT_FIELD(context, bool, srv_try_txt, FALSE, "srv_try_txt");
134     INIT_FIELD(context, int, fcache_vno, 0, "fcache_version");
135 
136     context->cc_ops       = NULL;
137     context->num_cc_ops	  = 0;
138     krb5_cc_register(context, &krb5_fcc_ops, TRUE);
139     krb5_cc_register(context, &krb5_mcc_ops, TRUE);
140 
141     context->num_kt_types = 0;
142     context->kt_types     = NULL;
143     krb5_kt_register (context, &krb5_fkt_ops);
144     krb5_kt_register (context, &krb5_mkt_ops);
145     krb5_kt_register (context, &krb5_akf_ops);
146     krb5_kt_register (context, &krb4_fkt_ops);
147     return 0;
148 }
149 
150 krb5_error_code
151 krb5_init_context(krb5_context *context)
152 {
153     krb5_context p;
154     const char *config_file = NULL;
155     krb5_config_section *tmp_cf;
156     krb5_error_code ret;
157 
158     ALLOC(p, 1);
159     if(!p)
160 	return ENOMEM;
161     memset(p, 0, sizeof(krb5_context_data));
162 
163     /* init error tables */
164     krb5_init_ets(p);
165 
166     if(!issuid())
167 	config_file = getenv("KRB5_CONFIG");
168     if (config_file == NULL)
169 	config_file = krb5_config_file;
170 
171     ret = krb5_config_parse_file (config_file, &tmp_cf);
172 
173     if (ret == 0)
174 	p->cf = tmp_cf;
175 #if 0
176     else
177 	krb5_warnx (p, "Unable to parse config file %s.  Ignoring.",
178 		    config_file); /* XXX */
179 #endif
180 
181     ret = init_context_from_config_file(p);
182     if(ret) {
183 	krb5_free_context(p);
184 	return ret;
185     }
186 
187     *context = p;
188     return 0;
189 }
190 
191 void
192 krb5_free_context(krb5_context context)
193 {
194   int i;
195 
196   free(context->etypes);
197   free(context->etypes_des);
198   krb5_free_host_realm (context, context->default_realms);
199   krb5_config_file_free (context, context->cf);
200   free_error_table (context->et_list);
201   for(i = 0; i < context->num_cc_ops; ++i)
202     free(context->cc_ops[i].prefix);
203   free(context->cc_ops);
204   free(context->kt_types);
205   free(context);
206 }
207 
208 /*
209  * set `etype' to a malloced list of the default enctypes
210  */
211 
212 static krb5_error_code
213 default_etypes(krb5_enctype **etype)
214 {
215     krb5_enctype p[] = {
216 	ETYPE_DES3_CBC_SHA1,
217 	ETYPE_DES3_CBC_MD5,
218 	ETYPE_ARCFOUR_HMAC_MD5,
219 	ETYPE_DES_CBC_MD5,
220 	ETYPE_DES_CBC_MD4,
221 	ETYPE_DES_CBC_CRC,
222 	ETYPE_NULL
223     };
224     *etype = malloc(sizeof(p));
225     if(*etype == NULL)
226 	return ENOMEM;
227     memcpy(*etype, p, sizeof(p));
228     return 0;
229 }
230 
231 krb5_error_code
232 krb5_set_default_in_tkt_etypes(krb5_context context,
233 			       const krb5_enctype *etypes)
234 {
235     int i;
236     krb5_enctype *p = NULL;
237 
238     if(etypes) {
239 	i = 0;
240 	while(etypes[i])
241 	    if(!krb5_enctype_valid(context, etypes[i++]))
242 		return KRB5_PROG_ETYPE_NOSUPP;
243 	++i;
244 	ALLOC(p, i);
245 	if(!p)
246 	    return ENOMEM;
247 	memmove(p, etypes, i * sizeof(krb5_enctype));
248     }
249     if(context->etypes)
250 	free(context->etypes);
251     context->etypes = p;
252     return 0;
253 }
254 
255 
256 krb5_error_code
257 krb5_get_default_in_tkt_etypes(krb5_context context,
258 			       krb5_enctype **etypes)
259 {
260   krb5_enctype *p;
261   int i;
262 
263   if(context->etypes) {
264     for(i = 0; context->etypes[i]; i++);
265     ++i;
266     ALLOC(p, i);
267     if(!p)
268       return ENOMEM;
269     memmove(p, context->etypes, i * sizeof(krb5_enctype));
270   } else
271     if(default_etypes(&p))
272       return ENOMEM;
273   *etypes = p;
274   return 0;
275 }
276 
277 const char *
278 krb5_get_err_text(krb5_context context, krb5_error_code code)
279 {
280     const char *p = com_right(context->et_list, code);
281     if(p == NULL)
282 	p = strerror(code);
283     return p;
284 }
285 
286 void
287 krb5_init_ets(krb5_context context)
288 {
289     if(context->et_list == NULL){
290 	initialize_krb5_error_table_r(&context->et_list);
291 	initialize_asn1_error_table_r(&context->et_list);
292 	initialize_heim_error_table_r(&context->et_list);
293     }
294 }
295 
296 void
297 krb5_set_use_admin_kdc (krb5_context context, krb5_boolean flag)
298 {
299     context->use_admin_kdc = flag;
300 }
301 
302 krb5_boolean
303 krb5_get_use_admin_kdc (krb5_context context)
304 {
305     return context->use_admin_kdc;
306 }
307 
308 krb5_error_code
309 krb5_add_extra_addresses(krb5_context context, krb5_addresses *addresses)
310 {
311 
312     if(context->extra_addresses)
313 	return krb5_append_addresses(context,
314 				     context->extra_addresses, addresses);
315     else
316 	return krb5_set_extra_addresses(context, addresses);
317 }
318 
319 krb5_error_code
320 krb5_set_extra_addresses(krb5_context context, const krb5_addresses *addresses)
321 {
322     if(context->extra_addresses) {
323 	krb5_free_addresses(context, context->extra_addresses);
324 	free(context->extra_addresses);
325     }
326     if(context->extra_addresses == NULL) {
327 	context->extra_addresses = malloc(sizeof(*context->extra_addresses));
328 	if(context->extra_addresses == NULL)
329 	    return ENOMEM;
330     }
331     return krb5_copy_addresses(context, addresses, context->extra_addresses);
332 }
333 
334 krb5_error_code
335 krb5_get_extra_addresses(krb5_context context, krb5_addresses *addresses)
336 {
337     if(context->extra_addresses == NULL) {
338 	memset(addresses, 0, sizeof(*addresses));
339 	return 0;
340     }
341     return copy_HostAddresses(context->extra_addresses, addresses);
342 }
343 
344 krb5_error_code
345 krb5_set_fcache_version(krb5_context context, int version)
346 {
347     context->fcache_vno = version;
348     return 0;
349 }
350 
351 krb5_error_code
352 krb5_get_fcache_version(krb5_context context, int *version)
353 {
354     *version = context->fcache_vno;
355     return 0;
356 }
357