xref: /freebsd/crypto/heimdal/lib/krb5/context.c (revision 5521ff5a4d1929056e7ffc982fac3341ca54df7c)
1 /*
2  * Copyright (c) 1997 - 2001 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.64 2001/05/16 22:24:42 assar 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 	    krb5_set_error_string (context, "malloc: out of memory");
64 	    return ENOMEM;
65 	}
66 	for(j = 0, k = 0; j < i; j++) {
67 	    if(krb5_string_to_enctype(context, etypes_str[j], &etypes[k]) == 0)
68 		k++;
69 	}
70 	etypes[k] = ETYPE_NULL;
71 	krb5_config_free_strings(etypes_str);
72 	*ret_enctypes = etypes;
73     }
74     return 0;
75 }
76 
77 /*
78  * read variables from the configuration file and set in `context'
79  */
80 
81 static krb5_error_code
82 init_context_from_config_file(krb5_context context)
83 {
84     const char * tmp;
85     INIT_FIELD(context, time, max_skew, 5 * 60, "clockskew");
86     INIT_FIELD(context, time, kdc_timeout, 3, "kdc_timeout");
87     INIT_FIELD(context, int, max_retries, 3, "max_retries");
88 
89     INIT_FIELD(context, string, http_proxy, NULL, "http_proxy");
90 
91     set_etypes (context, "default_etypes", &context->etypes);
92     set_etypes (context, "default_etypes_des", &context->etypes_des);
93 
94     /* default keytab name */
95     INIT_FIELD(context, string, default_keytab,
96 	       KEYTAB_DEFAULT, "default_keytab_name");
97 
98     INIT_FIELD(context, string, default_keytab_modify,
99 	       KEYTAB_DEFAULT_MODIFY, "default_keytab_modify_name");
100 
101     INIT_FIELD(context, string, time_fmt,
102 	       "%Y-%m-%dT%H:%M:%S", "time_format");
103 
104     INIT_FIELD(context, string, date_fmt,
105 	       "%Y-%m-%d", "date_format");
106 
107     INIT_FIELD(context, bool, log_utc,
108 	       FALSE, "log_utc");
109 
110 
111 
112     /* init dns-proxy slime */
113     tmp = krb5_config_get_string(context, NULL, "libdefaults",
114 				 "dns_proxy", NULL);
115     if(tmp)
116 	roken_gethostby_setup(context->http_proxy, tmp);
117     context->default_realms = NULL;
118 
119     {
120 	krb5_addresses addresses;
121 	char **adr, **a;
122 	adr = krb5_config_get_strings(context, NULL,
123 				      "libdefaults",
124 				      "extra_addresses",
125 				      NULL);
126 	memset(&addresses, 0, sizeof(addresses));
127 	for(a = adr; a && *a; a++) {
128 	    krb5_parse_address(context, *a, &addresses);
129 	    krb5_add_extra_addresses(context, &addresses);
130 	    krb5_free_addresses(context, &addresses);
131 	}
132 	krb5_config_free_strings(adr);
133     }
134 
135     INIT_FIELD(context, bool, scan_interfaces, TRUE, "scan_interfaces");
136     INIT_FIELD(context, bool, srv_lookup, TRUE, "srv_lookup");
137     INIT_FIELD(context, bool, srv_try_txt, FALSE, "srv_try_txt");
138     INIT_FIELD(context, int, fcache_vno, 0, "fcache_version");
139 
140     context->cc_ops       = NULL;
141     context->num_cc_ops	  = 0;
142     krb5_cc_register(context, &krb5_fcc_ops, TRUE);
143     krb5_cc_register(context, &krb5_mcc_ops, TRUE);
144 
145     context->num_kt_types = 0;
146     context->kt_types     = NULL;
147     krb5_kt_register (context, &krb5_fkt_ops);
148     krb5_kt_register (context, &krb5_mkt_ops);
149     krb5_kt_register (context, &krb5_akf_ops);
150     krb5_kt_register (context, &krb4_fkt_ops);
151     krb5_kt_register (context, &krb5_srvtab_fkt_ops);
152     krb5_kt_register (context, &krb5_any_ops);
153     return 0;
154 }
155 
156 krb5_error_code
157 krb5_init_context(krb5_context *context)
158 {
159     krb5_context p;
160     const char *config_file = NULL;
161     krb5_config_section *tmp_cf;
162     krb5_error_code ret;
163 
164     ALLOC(p, 1);
165     if(!p)
166 	return ENOMEM;
167     memset(p, 0, sizeof(krb5_context_data));
168 
169     /* init error tables */
170     krb5_init_ets(p);
171 
172     if(!issuid())
173 	config_file = getenv("KRB5_CONFIG");
174     if (config_file == NULL)
175 	config_file = krb5_config_file;
176 
177     ret = krb5_config_parse_file (p, config_file, &tmp_cf);
178 
179     if (ret == 0)
180 	p->cf = tmp_cf;
181 #if 0
182     else
183 	krb5_warnx (p, "Unable to parse config file %s.  Ignoring.",
184 		    config_file); /* XXX */
185 #endif
186 
187     ret = init_context_from_config_file(p);
188     if(ret) {
189 	krb5_free_context(p);
190 	return ret;
191     }
192 
193     *context = p;
194     return 0;
195 }
196 
197 void
198 krb5_free_context(krb5_context context)
199 {
200   int i;
201 
202   free(context->etypes);
203   free(context->etypes_des);
204   krb5_free_host_realm (context, context->default_realms);
205   krb5_config_file_free (context, context->cf);
206   free_error_table (context->et_list);
207   for(i = 0; i < context->num_cc_ops; ++i)
208     free(context->cc_ops[i].prefix);
209   free(context->cc_ops);
210   free(context->kt_types);
211   free(context);
212 }
213 
214 /*
215  * set `etype' to a malloced list of the default enctypes
216  */
217 
218 static krb5_error_code
219 default_etypes(krb5_context context, krb5_enctype **etype)
220 {
221     krb5_enctype p[] = {
222 	ETYPE_DES3_CBC_SHA1,
223 	ETYPE_DES3_CBC_MD5,
224 	ETYPE_ARCFOUR_HMAC_MD5,
225 	ETYPE_DES_CBC_MD5,
226 	ETYPE_DES_CBC_MD4,
227 	ETYPE_DES_CBC_CRC,
228 	ETYPE_NULL
229     };
230 
231     *etype = malloc(sizeof(p));
232     if(*etype == NULL) {
233 	krb5_set_error_string (context, "malloc: out of memory");
234 	return ENOMEM;
235     }
236     memcpy(*etype, p, sizeof(p));
237     return 0;
238 }
239 
240 krb5_error_code
241 krb5_set_default_in_tkt_etypes(krb5_context context,
242 			       const krb5_enctype *etypes)
243 {
244     int i;
245     krb5_enctype *p = NULL;
246 
247     if(etypes) {
248 	for (i = 0; etypes[i]; ++i)
249 	    if(!krb5_enctype_valid(context, etypes[i])) {
250 		krb5_set_error_string(context, "enctype %d not supported",
251 				      etypes[i]);
252 		return KRB5_PROG_ETYPE_NOSUPP;
253 	    }
254 	++i;
255 	ALLOC(p, i);
256 	if(!p) {
257 	    krb5_set_error_string (context, "malloc: out of memory");
258 	    return ENOMEM;
259 	}
260 	memmove(p, etypes, i * sizeof(krb5_enctype));
261     }
262     if(context->etypes)
263 	free(context->etypes);
264     context->etypes = p;
265     return 0;
266 }
267 
268 
269 krb5_error_code
270 krb5_get_default_in_tkt_etypes(krb5_context context,
271 			       krb5_enctype **etypes)
272 {
273   krb5_enctype *p;
274   int i;
275   krb5_error_code ret;
276 
277   if(context->etypes) {
278     for(i = 0; context->etypes[i]; i++);
279     ++i;
280     ALLOC(p, i);
281     if(!p) {
282       krb5_set_error_string (context, "malloc: out of memory");
283       return ENOMEM;
284     }
285     memmove(p, context->etypes, i * sizeof(krb5_enctype));
286   } else {
287     ret = default_etypes(context, &p);
288     if (ret)
289       return ret;
290   }
291   *etypes = p;
292   return 0;
293 }
294 
295 const char *
296 krb5_get_err_text(krb5_context context, krb5_error_code code)
297 {
298     const char *p = com_right(context->et_list, code);
299     if(p == NULL)
300 	p = strerror(code);
301     return p;
302 }
303 
304 void
305 krb5_init_ets(krb5_context context)
306 {
307     if(context->et_list == NULL){
308 	krb5_add_et_list(context, initialize_krb5_error_table_r);
309 	krb5_add_et_list(context, initialize_asn1_error_table_r);
310 	krb5_add_et_list(context, initialize_heim_error_table_r);
311     }
312 }
313 
314 void
315 krb5_set_use_admin_kdc (krb5_context context, krb5_boolean flag)
316 {
317     context->use_admin_kdc = flag;
318 }
319 
320 krb5_boolean
321 krb5_get_use_admin_kdc (krb5_context context)
322 {
323     return context->use_admin_kdc;
324 }
325 
326 krb5_error_code
327 krb5_add_extra_addresses(krb5_context context, krb5_addresses *addresses)
328 {
329 
330     if(context->extra_addresses)
331 	return krb5_append_addresses(context,
332 				     context->extra_addresses, addresses);
333     else
334 	return krb5_set_extra_addresses(context, addresses);
335 }
336 
337 krb5_error_code
338 krb5_set_extra_addresses(krb5_context context, const krb5_addresses *addresses)
339 {
340     if(context->extra_addresses) {
341 	krb5_free_addresses(context, context->extra_addresses);
342 	free(context->extra_addresses);
343     }
344     if(context->extra_addresses == NULL) {
345 	context->extra_addresses = malloc(sizeof(*context->extra_addresses));
346 	if(context->extra_addresses == NULL) {
347 	    krb5_set_error_string (context, "malloc: out of memory");
348 	    return ENOMEM;
349 	}
350     }
351     return krb5_copy_addresses(context, addresses, context->extra_addresses);
352 }
353 
354 krb5_error_code
355 krb5_get_extra_addresses(krb5_context context, krb5_addresses *addresses)
356 {
357     if(context->extra_addresses == NULL) {
358 	memset(addresses, 0, sizeof(*addresses));
359 	return 0;
360     }
361     return copy_HostAddresses(context->extra_addresses, addresses);
362 }
363 
364 krb5_error_code
365 krb5_set_fcache_version(krb5_context context, int version)
366 {
367     context->fcache_vno = version;
368     return 0;
369 }
370 
371 krb5_error_code
372 krb5_get_fcache_version(krb5_context context, int *version)
373 {
374     *version = context->fcache_vno;
375     return 0;
376 }
377