155682Smarkm/*
2178825Sdfr * Copyright (c) 1997 - 2005 Kungliga Tekniska H�gskolan
355682Smarkm * (Royal Institute of Technology, Stockholm, Sweden).
455682Smarkm * All rights reserved.
555682Smarkm *
655682Smarkm * Redistribution and use in source and binary forms, with or without
755682Smarkm * modification, are permitted provided that the following conditions
855682Smarkm * are met:
955682Smarkm *
1055682Smarkm * 1. Redistributions of source code must retain the above copyright
1155682Smarkm *    notice, this list of conditions and the following disclaimer.
1255682Smarkm *
1355682Smarkm * 2. Redistributions in binary form must reproduce the above copyright
1455682Smarkm *    notice, this list of conditions and the following disclaimer in the
1555682Smarkm *    documentation and/or other materials provided with the distribution.
1655682Smarkm *
1755682Smarkm * 3. Neither the name of the Institute nor the names of its contributors
1855682Smarkm *    may be used to endorse or promote products derived from this software
1955682Smarkm *    without specific prior written permission.
2055682Smarkm *
2155682Smarkm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
2255682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2355682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2455682Smarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
2555682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2655682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2755682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2855682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2955682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3055682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3155682Smarkm * SUCH DAMAGE.
3255682Smarkm */
3355682Smarkm
3455682Smarkm#include "krb5_locl.h"
35102644Snectar#include <com_err.h>
3655682Smarkm
37178825SdfrRCSID("$Id: context.c 22293 2007-12-14 05:25:59Z lha $");
3855682Smarkm
3955682Smarkm#define INIT_FIELD(C, T, E, D, F)					\
4055682Smarkm    (C)->E = krb5_config_get_ ## T ## _default ((C), NULL, (D), 	\
4155682Smarkm						"libdefaults", F, NULL)
4255682Smarkm
43178825Sdfr#define INIT_FLAG(C, O, V, D, F)					\
44178825Sdfr    do {								\
45178825Sdfr	if (krb5_config_get_bool_default((C), NULL, (D),"libdefaults", F, NULL)) { \
46178825Sdfr	    (C)->O |= V;						\
47178825Sdfr        }								\
48178825Sdfr    } while(0)
49178825Sdfr
5055682Smarkm/*
5155682Smarkm * Set the list of etypes `ret_etypes' from the configuration variable
5255682Smarkm * `name'
5355682Smarkm */
5455682Smarkm
5555682Smarkmstatic krb5_error_code
5655682Smarkmset_etypes (krb5_context context,
5755682Smarkm	    const char *name,
5855682Smarkm	    krb5_enctype **ret_enctypes)
5955682Smarkm{
6055682Smarkm    char **etypes_str;
61102644Snectar    krb5_enctype *etypes = NULL;
6255682Smarkm
6355682Smarkm    etypes_str = krb5_config_get_strings(context, NULL, "libdefaults",
6455682Smarkm					 name, NULL);
6555682Smarkm    if(etypes_str){
6655682Smarkm	int i, j, k;
6755682Smarkm	for(i = 0; etypes_str[i]; i++);
6855682Smarkm	etypes = malloc((i+1) * sizeof(*etypes));
6955682Smarkm	if (etypes == NULL) {
7055682Smarkm	    krb5_config_free_strings (etypes_str);
7178527Sassar	    krb5_set_error_string (context, "malloc: out of memory");
7255682Smarkm	    return ENOMEM;
7355682Smarkm	}
7455682Smarkm	for(j = 0, k = 0; j < i; j++) {
75178825Sdfr	    krb5_enctype e;
76178825Sdfr	    if(krb5_string_to_enctype(context, etypes_str[j], &e) != 0)
77178825Sdfr		continue;
78178825Sdfr	    if (krb5_enctype_valid(context, e) != 0)
79178825Sdfr		continue;
80178825Sdfr	    etypes[k++] = e;
8155682Smarkm	}
8255682Smarkm	etypes[k] = ETYPE_NULL;
8355682Smarkm	krb5_config_free_strings(etypes_str);
84102644Snectar    }
85102644Snectar    *ret_enctypes = etypes;
8655682Smarkm    return 0;
8755682Smarkm}
8855682Smarkm
8955682Smarkm/*
9055682Smarkm * read variables from the configuration file and set in `context'
9155682Smarkm */
9255682Smarkm
9355682Smarkmstatic krb5_error_code
9455682Smarkminit_context_from_config_file(krb5_context context)
9555682Smarkm{
9690926Snectar    krb5_error_code ret;
9755682Smarkm    const char * tmp;
98102644Snectar    krb5_enctype *tmptypes;
9990926Snectar
10055682Smarkm    INIT_FIELD(context, time, max_skew, 5 * 60, "clockskew");
10155682Smarkm    INIT_FIELD(context, time, kdc_timeout, 3, "kdc_timeout");
10255682Smarkm    INIT_FIELD(context, int, max_retries, 3, "max_retries");
10355682Smarkm
10472445Sassar    INIT_FIELD(context, string, http_proxy, NULL, "http_proxy");
105102644Snectar
106102644Snectar    ret = set_etypes (context, "default_etypes", &tmptypes);
107102644Snectar    if(ret)
108102644Snectar	return ret;
109102644Snectar    free(context->etypes);
110102644Snectar    context->etypes = tmptypes;
111102644Snectar
112102644Snectar    ret = set_etypes (context, "default_etypes_des", &tmptypes);
113102644Snectar    if(ret)
114102644Snectar	return ret;
115102644Snectar    free(context->etypes_des);
116102644Snectar    context->etypes_des = tmptypes;
11755682Smarkm
11855682Smarkm    /* default keytab name */
119102644Snectar    tmp = NULL;
120102644Snectar    if(!issuid())
121102644Snectar	tmp = getenv("KRB5_KTNAME");
122102644Snectar    if(tmp != NULL)
123102644Snectar	context->default_keytab = tmp;
124102644Snectar    else
125102644Snectar	INIT_FIELD(context, string, default_keytab,
126102644Snectar		   KEYTAB_DEFAULT, "default_keytab_name");
12755682Smarkm
12878527Sassar    INIT_FIELD(context, string, default_keytab_modify,
12990926Snectar	       NULL, "default_keytab_modify_name");
13078527Sassar
13172445Sassar    INIT_FIELD(context, string, time_fmt,
13272445Sassar	       "%Y-%m-%dT%H:%M:%S", "time_format");
13355682Smarkm
13472445Sassar    INIT_FIELD(context, string, date_fmt,
13572445Sassar	       "%Y-%m-%d", "date_format");
13672445Sassar
13772445Sassar    INIT_FIELD(context, bool, log_utc,
13872445Sassar	       FALSE, "log_utc");
13972445Sassar
14072445Sassar
14172445Sassar
14255682Smarkm    /* init dns-proxy slime */
14355682Smarkm    tmp = krb5_config_get_string(context, NULL, "libdefaults",
14455682Smarkm				 "dns_proxy", NULL);
14555682Smarkm    if(tmp)
14655682Smarkm	roken_gethostby_setup(context->http_proxy, tmp);
147102644Snectar    krb5_free_host_realm (context, context->default_realms);
14855682Smarkm    context->default_realms = NULL;
14955682Smarkm
15055682Smarkm    {
15155682Smarkm	krb5_addresses addresses;
15255682Smarkm	char **adr, **a;
153102644Snectar
154102644Snectar	krb5_set_extra_addresses(context, NULL);
15555682Smarkm	adr = krb5_config_get_strings(context, NULL,
15655682Smarkm				      "libdefaults",
15755682Smarkm				      "extra_addresses",
15855682Smarkm				      NULL);
15955682Smarkm	memset(&addresses, 0, sizeof(addresses));
16055682Smarkm	for(a = adr; a && *a; a++) {
16190926Snectar	    ret = krb5_parse_address(context, *a, &addresses);
16290926Snectar	    if (ret == 0) {
16390926Snectar		krb5_add_extra_addresses(context, &addresses);
16490926Snectar		krb5_free_addresses(context, &addresses);
16590926Snectar	    }
16655682Smarkm	}
16755682Smarkm	krb5_config_free_strings(adr);
16890926Snectar
169102644Snectar	krb5_set_ignore_addresses(context, NULL);
17090926Snectar	adr = krb5_config_get_strings(context, NULL,
17190926Snectar				      "libdefaults",
17290926Snectar				      "ignore_addresses",
17390926Snectar				      NULL);
17490926Snectar	memset(&addresses, 0, sizeof(addresses));
17590926Snectar	for(a = adr; a && *a; a++) {
17690926Snectar	    ret = krb5_parse_address(context, *a, &addresses);
17790926Snectar	    if (ret == 0) {
17890926Snectar		krb5_add_ignore_addresses(context, &addresses);
17990926Snectar		krb5_free_addresses(context, &addresses);
18090926Snectar	    }
18190926Snectar	}
18290926Snectar	krb5_config_free_strings(adr);
18355682Smarkm    }
18455682Smarkm
18555682Smarkm    INIT_FIELD(context, bool, scan_interfaces, TRUE, "scan_interfaces");
18655682Smarkm    INIT_FIELD(context, int, fcache_vno, 0, "fcache_version");
187103423Snectar    /* prefer dns_lookup_kdc over srv_lookup. */
188103423Snectar    INIT_FIELD(context, bool, srv_lookup, TRUE, "srv_lookup");
189103423Snectar    INIT_FIELD(context, bool, srv_lookup, context->srv_lookup, "dns_lookup_kdc");
190178825Sdfr    INIT_FIELD(context, int, large_msg_size, 1400, "large_message_size");
191178825Sdfr    INIT_FLAG(context, flags, KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME, TRUE, "dns_canonicalize_hostname");
192178825Sdfr    INIT_FLAG(context, flags, KRB5_CTX_F_CHECK_PAC, TRUE, "check_pac");
193120945Snectar    context->default_cc_name = NULL;
194178825Sdfr    context->default_cc_name_set = 0;
19555682Smarkm    return 0;
19655682Smarkm}
19755682Smarkm
198178825Sdfr/**
199178825Sdfr * Initializes the context structure and reads the configuration file
200178825Sdfr * /etc/krb5.conf. The structure should be freed by calling
201178825Sdfr * krb5_free_context() when it is no longer being used.
202178825Sdfr *
203178825Sdfr * @param context pointer to returned context
204178825Sdfr *
205178825Sdfr * @return Returns 0 to indicate success.  Otherwise an errno code is
206178825Sdfr * returned.  Failure means either that something bad happened during
207178825Sdfr * initialization (typically ENOMEM) or that Kerberos should not be
208178825Sdfr * used ENXIO.
209178825Sdfr *
210178825Sdfr * @ingroup krb5
211178825Sdfr */
212178825Sdfr
213178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
21455682Smarkmkrb5_init_context(krb5_context *context)
21555682Smarkm{
21655682Smarkm    krb5_context p;
21755682Smarkm    krb5_error_code ret;
218102644Snectar    char **files;
21955682Smarkm
220178825Sdfr    *context = NULL;
221178825Sdfr
222102644Snectar    p = calloc(1, sizeof(*p));
22355682Smarkm    if(!p)
22455682Smarkm	return ENOMEM;
22555682Smarkm
226178825Sdfr    p->mutex = malloc(sizeof(HEIMDAL_MUTEX));
227178825Sdfr    if (p->mutex == NULL) {
228178825Sdfr	free(p);
229178825Sdfr	return ENOMEM;
230178825Sdfr    }
231178825Sdfr    HEIMDAL_MUTEX_init(p->mutex);
232178825Sdfr
233102644Snectar    ret = krb5_get_default_config_files(&files);
234102644Snectar    if(ret)
235102644Snectar	goto out;
236102644Snectar    ret = krb5_set_config_files(p, files);
237102644Snectar    krb5_free_config_files(files);
238102644Snectar    if(ret)
239102644Snectar	goto out;
240102644Snectar
24155682Smarkm    /* init error tables */
24255682Smarkm    krb5_init_ets(p);
24355682Smarkm
244102644Snectar    p->cc_ops = NULL;
245102644Snectar    p->num_cc_ops = 0;
246178825Sdfr    krb5_cc_register(p, &krb5_acc_ops, TRUE);
247102644Snectar    krb5_cc_register(p, &krb5_fcc_ops, TRUE);
248102644Snectar    krb5_cc_register(p, &krb5_mcc_ops, TRUE);
249178825Sdfr#ifdef HAVE_KCM
250178825Sdfr    krb5_cc_register(p, &krb5_kcm_ops, TRUE);
251178825Sdfr#endif
25255682Smarkm
253102644Snectar    p->num_kt_types = 0;
254102644Snectar    p->kt_types     = NULL;
255102644Snectar    krb5_kt_register (p, &krb5_fkt_ops);
256178825Sdfr    krb5_kt_register (p, &krb5_wrfkt_ops);
257178825Sdfr    krb5_kt_register (p, &krb5_javakt_ops);
258102644Snectar    krb5_kt_register (p, &krb5_mkt_ops);
259102644Snectar    krb5_kt_register (p, &krb5_akf_ops);
260102644Snectar    krb5_kt_register (p, &krb4_fkt_ops);
261102644Snectar    krb5_kt_register (p, &krb5_srvtab_fkt_ops);
262102644Snectar    krb5_kt_register (p, &krb5_any_ops);
26355682Smarkm
264102644Snectarout:
26572445Sassar    if(ret) {
26672445Sassar	krb5_free_context(p);
267102644Snectar	p = NULL;
26872445Sassar    }
26955682Smarkm    *context = p;
270102644Snectar    return ret;
27155682Smarkm}
27255682Smarkm
273178825Sdfr/**
274178825Sdfr * Frees the krb5_context allocated by krb5_init_context().
275178825Sdfr *
276178825Sdfr * @param context context to be freed.
277178825Sdfr *
278178825Sdfr *  @ingroup krb5
279178825Sdfr*/
280178825Sdfr
281178825Sdfrvoid KRB5_LIB_FUNCTION
28255682Smarkmkrb5_free_context(krb5_context context)
28355682Smarkm{
284120945Snectar    if (context->default_cc_name)
285120945Snectar	free(context->default_cc_name);
286178825Sdfr    if (context->default_cc_name_env)
287178825Sdfr	free(context->default_cc_name_env);
28890926Snectar    free(context->etypes);
28990926Snectar    free(context->etypes_des);
29090926Snectar    krb5_free_host_realm (context, context->default_realms);
29190926Snectar    krb5_config_file_free (context, context->cf);
29290926Snectar    free_error_table (context->et_list);
29390926Snectar    free(context->cc_ops);
29490926Snectar    free(context->kt_types);
29590926Snectar    krb5_clear_error_string(context);
29690926Snectar    if(context->warn_dest != NULL)
29790926Snectar	krb5_closelog(context, context->warn_dest);
29890926Snectar    krb5_set_extra_addresses(context, NULL);
29990926Snectar    krb5_set_ignore_addresses(context, NULL);
300178825Sdfr    krb5_set_send_to_kdc_func(context, NULL, NULL);
301178825Sdfr    if (context->mutex != NULL) {
302178825Sdfr	HEIMDAL_MUTEX_destroy(context->mutex);
303178825Sdfr	free(context->mutex);
304178825Sdfr    }
305178825Sdfr    memset(context, 0, sizeof(*context));
30690926Snectar    free(context);
30755682Smarkm}
30855682Smarkm
309178825Sdfr/**
310178825Sdfr * Reinit the context from a new set of filenames.
311178825Sdfr *
312178825Sdfr * @param context context to add configuration too.
313178825Sdfr * @param filenames array of filenames, end of list is indicated with a NULL filename.
314178825Sdfr *
315178825Sdfr * @return Returns 0 to indicate success.  Otherwise an kerberos et
316178825Sdfr * error code is returned, see krb5_get_error_message().
317178825Sdfr *
318178825Sdfr * @ingroup krb5
319178825Sdfr */
320178825Sdfr
321178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
322102644Snectarkrb5_set_config_files(krb5_context context, char **filenames)
323102644Snectar{
324102644Snectar    krb5_error_code ret;
325102644Snectar    krb5_config_binding *tmp = NULL;
326102644Snectar    while(filenames != NULL && *filenames != NULL && **filenames != '\0') {
327102644Snectar	ret = krb5_config_parse_file_multi(context, *filenames, &tmp);
328178825Sdfr	if(ret != 0 && ret != ENOENT && ret != EACCES) {
329102644Snectar	    krb5_config_file_free(context, tmp);
330102644Snectar	    return ret;
331102644Snectar	}
332102644Snectar	filenames++;
333102644Snectar    }
334102644Snectar#if 0
335102644Snectar    /* with this enabled and if there are no config files, Kerberos is
336102644Snectar       considererd disabled */
337102644Snectar    if(tmp == NULL)
338107207Snectar	return ENXIO;
339102644Snectar#endif
340102644Snectar    krb5_config_file_free(context, context->cf);
341102644Snectar    context->cf = tmp;
342102644Snectar    ret = init_context_from_config_file(context);
343102644Snectar    return ret;
344102644Snectar}
345102644Snectar
346178825Sdfrstatic krb5_error_code
347178825Sdfradd_file(char ***pfilenames, int *len, char *file)
348102644Snectar{
349178825Sdfr    char **pp = *pfilenames;
350178825Sdfr    int i;
351178825Sdfr
352178825Sdfr    for(i = 0; i < *len; i++) {
353178825Sdfr	if(strcmp(pp[i], file) == 0) {
354178825Sdfr	    free(file);
355178825Sdfr	    return 0;
356178825Sdfr	}
357178825Sdfr    }
358178825Sdfr
359178825Sdfr    pp = realloc(*pfilenames, (*len + 2) * sizeof(*pp));
360178825Sdfr    if (pp == NULL) {
361178825Sdfr	free(file);
362178825Sdfr	return ENOMEM;
363178825Sdfr    }
364178825Sdfr
365178825Sdfr    pp[*len] = file;
366178825Sdfr    pp[*len + 1] = NULL;
367178825Sdfr    *pfilenames = pp;
368178825Sdfr    *len += 1;
369178825Sdfr    return 0;
370178825Sdfr}
371178825Sdfr
372178825Sdfr/*
373178825Sdfr *  `pq' isn't free, it's up the the caller
374178825Sdfr */
375178825Sdfr
376178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
377178825Sdfrkrb5_prepend_config_files(const char *filelist, char **pq, char ***ret_pp)
378178825Sdfr{
379178825Sdfr    krb5_error_code ret;
380102644Snectar    const char *p, *q;
381102644Snectar    char **pp;
382178825Sdfr    int len;
383178825Sdfr    char *fn;
384102644Snectar
385178825Sdfr    pp = NULL;
386102644Snectar
387178825Sdfr    len = 0;
388178825Sdfr    p = filelist;
389102644Snectar    while(1) {
390102644Snectar	ssize_t l;
391102644Snectar	q = p;
392102644Snectar	l = strsep_copy(&q, ":", NULL, 0);
393102644Snectar	if(l == -1)
394102644Snectar	    break;
395178825Sdfr	fn = malloc(l + 1);
396178825Sdfr	if(fn == NULL) {
397102644Snectar	    krb5_free_config_files(pp);
398102644Snectar	    return ENOMEM;
399102644Snectar	}
400178825Sdfr	l = strsep_copy(&p, ":", fn, l + 1);
401178825Sdfr	ret = add_file(&pp, &len, fn);
402178825Sdfr	if (ret) {
403178825Sdfr	    krb5_free_config_files(pp);
404178825Sdfr	    return ret;
405178825Sdfr	}
406178825Sdfr    }
407178825Sdfr
408178825Sdfr    if (pq != NULL) {
409178825Sdfr	int i;
410178825Sdfr
411178825Sdfr	for (i = 0; pq[i] != NULL; i++) {
412178825Sdfr	    fn = strdup(pq[i]);
413178825Sdfr	    if (fn == NULL) {
414178825Sdfr		krb5_free_config_files(pp);
415178825Sdfr		return ENOMEM;
416102644Snectar	    }
417178825Sdfr	    ret = add_file(&pp, &len, fn);
418178825Sdfr	    if (ret) {
419178825Sdfr		krb5_free_config_files(pp);
420178825Sdfr		return ret;
421178825Sdfr	    }
422178825Sdfr	}
423102644Snectar    }
424178825Sdfr
425178825Sdfr    *ret_pp = pp;
426178825Sdfr    return 0;
427178825Sdfr}
428178825Sdfr
429178825Sdfr/**
430178825Sdfr * Prepend the filename to the global configuration list.
431178825Sdfr *
432178825Sdfr * @param filelist a filename to add to the default list of filename
433178825Sdfr * @param pfilenames return array of filenames, should be freed with krb5_free_config_files().
434178825Sdfr *
435178825Sdfr * @return Returns 0 to indicate success.  Otherwise an kerberos et
436178825Sdfr * error code is returned, see krb5_get_error_message().
437178825Sdfr *
438178825Sdfr * @ingroup krb5
439178825Sdfr */
440178825Sdfr
441178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
442178825Sdfrkrb5_prepend_config_files_default(const char *filelist, char ***pfilenames)
443178825Sdfr{
444178825Sdfr    krb5_error_code ret;
445178825Sdfr    char **defpp, **pp = NULL;
446178825Sdfr
447178825Sdfr    ret = krb5_get_default_config_files(&defpp);
448178825Sdfr    if (ret)
449178825Sdfr	return ret;
450178825Sdfr
451178825Sdfr    ret = krb5_prepend_config_files(filelist, defpp, &pp);
452178825Sdfr    krb5_free_config_files(defpp);
453178825Sdfr    if (ret) {
454178825Sdfr	return ret;
455178825Sdfr    }
456102644Snectar    *pfilenames = pp;
457102644Snectar    return 0;
458102644Snectar}
459102644Snectar
460178825Sdfr/**
461178825Sdfr * Get the global configuration list.
462178825Sdfr *
463178825Sdfr * @param pfilenames return array of filenames, should be freed with krb5_free_config_files().
464178825Sdfr *
465178825Sdfr * @return Returns 0 to indicate success.  Otherwise an kerberos et
466178825Sdfr * error code is returned, see krb5_get_error_message().
467178825Sdfr *
468178825Sdfr * @ingroup krb5
469178825Sdfr */
470178825Sdfr
471178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
472178825Sdfrkrb5_get_default_config_files(char ***pfilenames)
473178825Sdfr{
474178825Sdfr    const char *files = NULL;
475178825Sdfr
476178825Sdfr    if (pfilenames == NULL)
477178825Sdfr        return EINVAL;
478178825Sdfr    if(!issuid())
479178825Sdfr	files = getenv("KRB5_CONFIG");
480178825Sdfr    if (files == NULL)
481178825Sdfr	files = krb5_config_file;
482178825Sdfr
483178825Sdfr    return krb5_prepend_config_files(files, NULL, pfilenames);
484178825Sdfr}
485178825Sdfr
486178825Sdfr/**
487178825Sdfr * Free a list of configuration files.
488178825Sdfr *
489178825Sdfr * @param filenames list to be freed.
490178825Sdfr *
491178825Sdfr * @return Returns 0 to indicate success. Otherwise an kerberos et
492178825Sdfr * error code is returned, see krb5_get_error_message().
493178825Sdfr *
494178825Sdfr * @ingroup krb5
495178825Sdfr */
496178825Sdfr
497178825Sdfrvoid KRB5_LIB_FUNCTION
498102644Snectarkrb5_free_config_files(char **filenames)
499102644Snectar{
500102644Snectar    char **p;
501102644Snectar    for(p = filenames; *p != NULL; p++)
502102644Snectar	free(*p);
503102644Snectar    free(filenames);
504102644Snectar}
505102644Snectar
506178825Sdfr/**
507178825Sdfr * Returns the list of Kerberos encryption types sorted in order of
508178825Sdfr * most preferred to least preferred encryption type.  Note that some
509178825Sdfr * encryption types might be disabled, so you need to check with
510178825Sdfr * krb5_enctype_valid() before using the encryption type.
511178825Sdfr *
512178825Sdfr * @return list of enctypes, terminated with ETYPE_NULL. Its a static
513178825Sdfr * array completed into the Kerberos library so the content doesn't
514178825Sdfr * need to be freed.
515178825Sdfr *
516178825Sdfr * @ingroup krb5
51772445Sassar */
51872445Sassar
519178825Sdfrconst krb5_enctype * KRB5_LIB_FUNCTION
520178825Sdfrkrb5_kerberos_enctypes(krb5_context context)
52155682Smarkm{
522178825Sdfr    static const krb5_enctype p[] = {
523178825Sdfr	ETYPE_AES256_CTS_HMAC_SHA1_96,
524178825Sdfr	ETYPE_AES128_CTS_HMAC_SHA1_96,
52555682Smarkm	ETYPE_DES3_CBC_SHA1,
52655682Smarkm	ETYPE_DES3_CBC_MD5,
52772445Sassar	ETYPE_ARCFOUR_HMAC_MD5,
52855682Smarkm	ETYPE_DES_CBC_MD5,
52955682Smarkm	ETYPE_DES_CBC_MD4,
53055682Smarkm	ETYPE_DES_CBC_CRC,
53155682Smarkm	ETYPE_NULL
53255682Smarkm    };
533178825Sdfr    return p;
534178825Sdfr}
53578527Sassar
536178825Sdfr/*
537178825Sdfr * set `etype' to a malloced list of the default enctypes
538178825Sdfr */
539178825Sdfr
540178825Sdfrstatic krb5_error_code
541178825Sdfrdefault_etypes(krb5_context context, krb5_enctype **etype)
542178825Sdfr{
543178825Sdfr    const krb5_enctype *p;
544178825Sdfr    krb5_enctype *e = NULL, *ep;
545178825Sdfr    int i, n = 0;
546178825Sdfr
547178825Sdfr    p = krb5_kerberos_enctypes(context);
548178825Sdfr
549178825Sdfr    for (i = 0; p[i] != ETYPE_NULL; i++) {
550178825Sdfr	if (krb5_enctype_valid(context, p[i]) != 0)
551178825Sdfr	    continue;
552178825Sdfr	ep = realloc(e, (n + 2) * sizeof(*e));
553178825Sdfr	if (ep == NULL) {
554178825Sdfr	    free(e);
555178825Sdfr	    krb5_set_error_string (context, "malloc: out of memory");
556178825Sdfr	    return ENOMEM;
557178825Sdfr	}
558178825Sdfr	e = ep;
559178825Sdfr	e[n] = p[i];
560178825Sdfr	e[n + 1] = ETYPE_NULL;
561178825Sdfr	n++;
56278527Sassar    }
563178825Sdfr    *etype = e;
56455682Smarkm    return 0;
56555682Smarkm}
56655682Smarkm
567178825Sdfr/**
568178825Sdfr * Set the default encryption types that will be use in communcation
569178825Sdfr * with the KDC, clients and servers.
570178825Sdfr *
571178825Sdfr * @param context Kerberos 5 context.
572178825Sdfr * @param etypes Encryption types, array terminated with ETYPE_NULL (0).
573178825Sdfr *
574178825Sdfr * @return Returns 0 to indicate success. Otherwise an kerberos et
575178825Sdfr * error code is returned, see krb5_get_error_message().
576178825Sdfr *
577178825Sdfr * @ingroup krb5
578178825Sdfr */
579178825Sdfr
580178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
58155682Smarkmkrb5_set_default_in_tkt_etypes(krb5_context context,
58255682Smarkm			       const krb5_enctype *etypes)
58355682Smarkm{
584178825Sdfr    krb5_enctype *p = NULL;
58555682Smarkm    int i;
58655682Smarkm
58755682Smarkm    if(etypes) {
588178825Sdfr	for (i = 0; etypes[i]; ++i) {
589178825Sdfr	    krb5_error_code ret;
590178825Sdfr	    ret = krb5_enctype_valid(context, etypes[i]);
591178825Sdfr	    if (ret)
592178825Sdfr		return ret;
593178825Sdfr	}
59455682Smarkm	++i;
59555682Smarkm	ALLOC(p, i);
59678527Sassar	if(!p) {
59778527Sassar	    krb5_set_error_string (context, "malloc: out of memory");
59855682Smarkm	    return ENOMEM;
59978527Sassar	}
60055682Smarkm	memmove(p, etypes, i * sizeof(krb5_enctype));
60155682Smarkm    }
60255682Smarkm    if(context->etypes)
60355682Smarkm	free(context->etypes);
60455682Smarkm    context->etypes = p;
60555682Smarkm    return 0;
60655682Smarkm}
60755682Smarkm
608178825Sdfr/**
609178825Sdfr * Get the default encryption types that will be use in communcation
610178825Sdfr * with the KDC, clients and servers.
611178825Sdfr *
612178825Sdfr * @param context Kerberos 5 context.
613178825Sdfr * @param etypes Encryption types, array terminated with
614178825Sdfr * ETYPE_NULL(0), caller should free array with krb5_xfree():
615178825Sdfr *
616178825Sdfr * @return Returns 0 to indicate success. Otherwise an kerberos et
617178825Sdfr * error code is returned, see krb5_get_error_message().
618178825Sdfr *
619178825Sdfr * @ingroup krb5
620178825Sdfr */
62155682Smarkm
622178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
62355682Smarkmkrb5_get_default_in_tkt_etypes(krb5_context context,
62455682Smarkm			       krb5_enctype **etypes)
62555682Smarkm{
62655682Smarkm  krb5_enctype *p;
62755682Smarkm  int i;
62878527Sassar  krb5_error_code ret;
62955682Smarkm
63055682Smarkm  if(context->etypes) {
63155682Smarkm    for(i = 0; context->etypes[i]; i++);
63255682Smarkm    ++i;
63355682Smarkm    ALLOC(p, i);
63478527Sassar    if(!p) {
63578527Sassar      krb5_set_error_string (context, "malloc: out of memory");
63655682Smarkm      return ENOMEM;
63778527Sassar    }
63855682Smarkm    memmove(p, context->etypes, i * sizeof(krb5_enctype));
63978527Sassar  } else {
64078527Sassar    ret = default_etypes(context, &p);
64178527Sassar    if (ret)
64278527Sassar      return ret;
64378527Sassar  }
64455682Smarkm  *etypes = p;
64555682Smarkm  return 0;
64655682Smarkm}
64755682Smarkm
648178825Sdfr/**
649178825Sdfr * Return the error string for the error code. The caller must not
650178825Sdfr * free the string.
651178825Sdfr *
652178825Sdfr * @param context Kerberos 5 context.
653178825Sdfr * @param code Kerberos error code.
654178825Sdfr *
655178825Sdfr * @return the error message matching code
656178825Sdfr *
657178825Sdfr * @ingroup krb5
658178825Sdfr */
659178825Sdfr
660178825Sdfrconst char* KRB5_LIB_FUNCTION
66155682Smarkmkrb5_get_err_text(krb5_context context, krb5_error_code code)
66255682Smarkm{
66390926Snectar    const char *p = NULL;
66490926Snectar    if(context != NULL)
66590926Snectar	p = com_right(context->et_list, code);
66655682Smarkm    if(p == NULL)
66755682Smarkm	p = strerror(code);
668142403Snectar    if (p == NULL)
669142403Snectar	p = "Unknown error";
67055682Smarkm    return p;
67155682Smarkm}
67255682Smarkm
673178825Sdfr/**
674178825Sdfr * Init the built-in ets in the Kerberos library.
675178825Sdfr *
676178825Sdfr * @param context kerberos context to add the ets too
677178825Sdfr *
678178825Sdfr * @ingroup krb5
679178825Sdfr */
680178825Sdfr
681178825Sdfrvoid KRB5_LIB_FUNCTION
68255682Smarkmkrb5_init_ets(krb5_context context)
68355682Smarkm{
68455682Smarkm    if(context->et_list == NULL){
68578527Sassar	krb5_add_et_list(context, initialize_krb5_error_table_r);
68678527Sassar	krb5_add_et_list(context, initialize_asn1_error_table_r);
68778527Sassar	krb5_add_et_list(context, initialize_heim_error_table_r);
68890926Snectar	krb5_add_et_list(context, initialize_k524_error_table_r);
689178825Sdfr#ifdef PKINIT
690178825Sdfr	krb5_add_et_list(context, initialize_hx_error_table_r);
691178825Sdfr#endif
69255682Smarkm    }
69355682Smarkm}
69455682Smarkm
695178825Sdfr/**
696178825Sdfr * Make the kerberos library default to the admin KDC.
697178825Sdfr *
698178825Sdfr * @param context Kerberos 5 context.
699178825Sdfr * @param flag boolean flag to select if the use the admin KDC or not.
700178825Sdfr *
701178825Sdfr * @ingroup krb5
702178825Sdfr */
703178825Sdfr
704178825Sdfrvoid KRB5_LIB_FUNCTION
70555682Smarkmkrb5_set_use_admin_kdc (krb5_context context, krb5_boolean flag)
70655682Smarkm{
70755682Smarkm    context->use_admin_kdc = flag;
70855682Smarkm}
70955682Smarkm
710178825Sdfr/**
711178825Sdfr * Make the kerberos library default to the admin KDC.
712178825Sdfr *
713178825Sdfr * @param context Kerberos 5 context.
714178825Sdfr *
715178825Sdfr * @return boolean flag to telling the context will use admin KDC as the default KDC.
716178825Sdfr *
717178825Sdfr * @ingroup krb5
718178825Sdfr */
719178825Sdfr
720178825Sdfrkrb5_boolean KRB5_LIB_FUNCTION
72155682Smarkmkrb5_get_use_admin_kdc (krb5_context context)
72255682Smarkm{
72355682Smarkm    return context->use_admin_kdc;
72455682Smarkm}
72555682Smarkm
726178825Sdfr/**
727178825Sdfr * Add extra address to the address list that the library will add to
728178825Sdfr * the client's address list when communicating with the KDC.
729178825Sdfr *
730178825Sdfr * @param context Kerberos 5 context.
731178825Sdfr * @param addresses addreses to add
732178825Sdfr *
733178825Sdfr * @return Returns 0 to indicate success. Otherwise an kerberos et
734178825Sdfr * error code is returned, see krb5_get_error_message().
735178825Sdfr *
736178825Sdfr * @ingroup krb5
737178825Sdfr */
738178825Sdfr
739178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
74055682Smarkmkrb5_add_extra_addresses(krb5_context context, krb5_addresses *addresses)
74155682Smarkm{
74255682Smarkm
74355682Smarkm    if(context->extra_addresses)
74455682Smarkm	return krb5_append_addresses(context,
74555682Smarkm				     context->extra_addresses, addresses);
74655682Smarkm    else
74755682Smarkm	return krb5_set_extra_addresses(context, addresses);
74855682Smarkm}
74955682Smarkm
750178825Sdfr/**
751178825Sdfr * Set extra address to the address list that the library will add to
752178825Sdfr * the client's address list when communicating with the KDC.
753178825Sdfr *
754178825Sdfr * @param context Kerberos 5 context.
755178825Sdfr * @param addresses addreses to set
756178825Sdfr *
757178825Sdfr * @return Returns 0 to indicate success. Otherwise an kerberos et
758178825Sdfr * error code is returned, see krb5_get_error_message().
759178825Sdfr *
760178825Sdfr * @ingroup krb5
761178825Sdfr */
762178825Sdfr
763178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
76457419Smarkmkrb5_set_extra_addresses(krb5_context context, const krb5_addresses *addresses)
76555682Smarkm{
76690926Snectar    if(context->extra_addresses)
76755682Smarkm	krb5_free_addresses(context, context->extra_addresses);
76890926Snectar
76990926Snectar    if(addresses == NULL) {
77090926Snectar	if(context->extra_addresses != NULL) {
77190926Snectar	    free(context->extra_addresses);
77290926Snectar	    context->extra_addresses = NULL;
77390926Snectar	}
77490926Snectar	return 0;
77555682Smarkm    }
77655682Smarkm    if(context->extra_addresses == NULL) {
77755682Smarkm	context->extra_addresses = malloc(sizeof(*context->extra_addresses));
77878527Sassar	if(context->extra_addresses == NULL) {
77978527Sassar	    krb5_set_error_string (context, "malloc: out of memory");
78055682Smarkm	    return ENOMEM;
78178527Sassar	}
78255682Smarkm    }
78357419Smarkm    return krb5_copy_addresses(context, addresses, context->extra_addresses);
78455682Smarkm}
78555682Smarkm
786178825Sdfr/**
787178825Sdfr * Get extra address to the address list that the library will add to
788178825Sdfr * the client's address list when communicating with the KDC.
789178825Sdfr *
790178825Sdfr * @param context Kerberos 5 context.
791178825Sdfr * @param addresses addreses to set
792178825Sdfr *
793178825Sdfr * @return Returns 0 to indicate success. Otherwise an kerberos et
794178825Sdfr * error code is returned, see krb5_get_error_message().
795178825Sdfr *
796178825Sdfr * @ingroup krb5
797178825Sdfr */
798178825Sdfr
799178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
80055682Smarkmkrb5_get_extra_addresses(krb5_context context, krb5_addresses *addresses)
80155682Smarkm{
80255682Smarkm    if(context->extra_addresses == NULL) {
80355682Smarkm	memset(addresses, 0, sizeof(*addresses));
80455682Smarkm	return 0;
80555682Smarkm    }
80690926Snectar    return krb5_copy_addresses(context,context->extra_addresses, addresses);
80755682Smarkm}
80855682Smarkm
809178825Sdfr/**
810178825Sdfr * Add extra addresses to ignore when fetching addresses from the
811178825Sdfr * underlaying operating system.
812178825Sdfr *
813178825Sdfr * @param context Kerberos 5 context.
814178825Sdfr * @param addresses addreses to ignore
815178825Sdfr *
816178825Sdfr * @return Returns 0 to indicate success. Otherwise an kerberos et
817178825Sdfr * error code is returned, see krb5_get_error_message().
818178825Sdfr *
819178825Sdfr * @ingroup krb5
820178825Sdfr */
821178825Sdfr
822178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
82390926Snectarkrb5_add_ignore_addresses(krb5_context context, krb5_addresses *addresses)
82490926Snectar{
82590926Snectar
82690926Snectar    if(context->ignore_addresses)
82790926Snectar	return krb5_append_addresses(context,
82890926Snectar				     context->ignore_addresses, addresses);
82990926Snectar    else
83090926Snectar	return krb5_set_ignore_addresses(context, addresses);
83190926Snectar}
83290926Snectar
833178825Sdfr/**
834178825Sdfr * Set extra addresses to ignore when fetching addresses from the
835178825Sdfr * underlaying operating system.
836178825Sdfr *
837178825Sdfr * @param context Kerberos 5 context.
838178825Sdfr * @param addresses addreses to ignore
839178825Sdfr *
840178825Sdfr * @return Returns 0 to indicate success. Otherwise an kerberos et
841178825Sdfr * error code is returned, see krb5_get_error_message().
842178825Sdfr *
843178825Sdfr * @ingroup krb5
844178825Sdfr */
845178825Sdfr
846178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
84790926Snectarkrb5_set_ignore_addresses(krb5_context context, const krb5_addresses *addresses)
84890926Snectar{
84990926Snectar    if(context->ignore_addresses)
85090926Snectar	krb5_free_addresses(context, context->ignore_addresses);
85190926Snectar    if(addresses == NULL) {
85290926Snectar	if(context->ignore_addresses != NULL) {
85390926Snectar	    free(context->ignore_addresses);
85490926Snectar	    context->ignore_addresses = NULL;
85590926Snectar	}
85690926Snectar	return 0;
85790926Snectar    }
85890926Snectar    if(context->ignore_addresses == NULL) {
85990926Snectar	context->ignore_addresses = malloc(sizeof(*context->ignore_addresses));
86090926Snectar	if(context->ignore_addresses == NULL) {
86190926Snectar	    krb5_set_error_string (context, "malloc: out of memory");
86290926Snectar	    return ENOMEM;
86390926Snectar	}
86490926Snectar    }
86590926Snectar    return krb5_copy_addresses(context, addresses, context->ignore_addresses);
86690926Snectar}
86790926Snectar
868178825Sdfr/**
869178825Sdfr * Get extra addresses to ignore when fetching addresses from the
870178825Sdfr * underlaying operating system.
871178825Sdfr *
872178825Sdfr * @param context Kerberos 5 context.
873178825Sdfr * @param addresses list addreses ignored
874178825Sdfr *
875178825Sdfr * @return Returns 0 to indicate success. Otherwise an kerberos et
876178825Sdfr * error code is returned, see krb5_get_error_message().
877178825Sdfr *
878178825Sdfr * @ingroup krb5
879178825Sdfr */
880178825Sdfr
881178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
88290926Snectarkrb5_get_ignore_addresses(krb5_context context, krb5_addresses *addresses)
88390926Snectar{
88490926Snectar    if(context->ignore_addresses == NULL) {
88590926Snectar	memset(addresses, 0, sizeof(*addresses));
88690926Snectar	return 0;
88790926Snectar    }
88890926Snectar    return krb5_copy_addresses(context, context->ignore_addresses, addresses);
88990926Snectar}
89090926Snectar
891178825Sdfr/**
892178825Sdfr * Set version of fcache that the library should use.
893178825Sdfr *
894178825Sdfr * @param context Kerberos 5 context.
895178825Sdfr * @param version version number.
896178825Sdfr *
897178825Sdfr * @return Returns 0 to indicate success. Otherwise an kerberos et
898178825Sdfr * error code is returned, see krb5_get_error_message().
899178825Sdfr *
900178825Sdfr * @ingroup krb5
901178825Sdfr */
902178825Sdfr
903178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
90455682Smarkmkrb5_set_fcache_version(krb5_context context, int version)
90555682Smarkm{
90655682Smarkm    context->fcache_vno = version;
90755682Smarkm    return 0;
90855682Smarkm}
90955682Smarkm
910178825Sdfr/**
911178825Sdfr * Get version of fcache that the library should use.
912178825Sdfr *
913178825Sdfr * @param context Kerberos 5 context.
914178825Sdfr * @param version version number.
915178825Sdfr *
916178825Sdfr * @return Returns 0 to indicate success. Otherwise an kerberos et
917178825Sdfr * error code is returned, see krb5_get_error_message().
918178825Sdfr *
919178825Sdfr * @ingroup krb5
920178825Sdfr */
921178825Sdfr
922178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
92355682Smarkmkrb5_get_fcache_version(krb5_context context, int *version)
92455682Smarkm{
92555682Smarkm    *version = context->fcache_vno;
92655682Smarkm    return 0;
92755682Smarkm}
928178825Sdfr
929178825Sdfr/**
930178825Sdfr * Runtime check if the Kerberos library was complied with thread support.
931178825Sdfr *
932178825Sdfr * @return TRUE if the library was compiled with thread support, FALSE if not.
933178825Sdfr *
934178825Sdfr * @ingroup krb5
935178825Sdfr */
936178825Sdfr
937178825Sdfr
938178825Sdfrkrb5_boolean KRB5_LIB_FUNCTION
939178825Sdfrkrb5_is_thread_safe(void)
940178825Sdfr{
941178825Sdfr#ifdef ENABLE_PTHREAD_SUPPORT
942178825Sdfr    return TRUE;
943178825Sdfr#else
944178825Sdfr    return FALSE;
945178825Sdfr#endif
946178825Sdfr}
947178825Sdfr
948178825Sdfr/**
949178825Sdfr * Set if the library should use DNS to canonicalize hostnames.
950178825Sdfr *
951178825Sdfr * @param context Kerberos 5 context.
952178825Sdfr * @param flag if its dns canonicalizion is used or not.
953178825Sdfr *
954178825Sdfr * @ingroup krb5
955178825Sdfr */
956178825Sdfr
957178825Sdfrvoid KRB5_LIB_FUNCTION
958178825Sdfrkrb5_set_dns_canonicalize_hostname (krb5_context context, krb5_boolean flag)
959178825Sdfr{
960178825Sdfr    if (flag)
961178825Sdfr	context->flags |= KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME;
962178825Sdfr    else
963178825Sdfr	context->flags &= ~KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME;
964178825Sdfr}
965178825Sdfr
966178825Sdfr/**
967178825Sdfr * Get if the library uses DNS to canonicalize hostnames.
968178825Sdfr *
969178825Sdfr * @param context Kerberos 5 context.
970178825Sdfr *
971178825Sdfr * @return return non zero if the library uses DNS to canonicalize hostnames.
972178825Sdfr *
973178825Sdfr * @ingroup krb5
974178825Sdfr */
975178825Sdfr
976178825Sdfrkrb5_boolean KRB5_LIB_FUNCTION
977178825Sdfrkrb5_get_dns_canonicalize_hostname (krb5_context context)
978178825Sdfr{
979178825Sdfr    return (context->flags & KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME) ? 1 : 0;
980178825Sdfr}
981178825Sdfr
982178825Sdfr/**
983178825Sdfr * Get current offset in time to the KDC.
984178825Sdfr *
985178825Sdfr * @param context Kerberos 5 context.
986178825Sdfr * @param sec seconds part of offset.
987178825Sdfr * @param usec micro seconds part of offset.
988178825Sdfr *
989178825Sdfr * @return return non zero if the library uses DNS to canonicalize hostnames.
990178825Sdfr *
991178825Sdfr * @ingroup krb5
992178825Sdfr */
993178825Sdfr
994178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
995178825Sdfrkrb5_get_kdc_sec_offset (krb5_context context, int32_t *sec, int32_t *usec)
996178825Sdfr{
997178825Sdfr    if (sec)
998178825Sdfr	*sec = context->kdc_sec_offset;
999178825Sdfr    if (usec)
1000178825Sdfr	*usec = context->kdc_usec_offset;
1001178825Sdfr    return 0;
1002178825Sdfr}
1003178825Sdfr
1004178825Sdfr/**
1005178825Sdfr * Get max time skew allowed.
1006178825Sdfr *
1007178825Sdfr * @param context Kerberos 5 context.
1008178825Sdfr *
1009178825Sdfr * @return timeskew in seconds.
1010178825Sdfr *
1011178825Sdfr * @ingroup krb5
1012178825Sdfr */
1013178825Sdfr
1014178825Sdfrtime_t KRB5_LIB_FUNCTION
1015178825Sdfrkrb5_get_max_time_skew (krb5_context context)
1016178825Sdfr{
1017178825Sdfr    return context->max_skew;
1018178825Sdfr}
1019178825Sdfr
1020178825Sdfr/**
1021178825Sdfr * Set max time skew allowed.
1022178825Sdfr *
1023178825Sdfr * @param context Kerberos 5 context.
1024178825Sdfr * @param t timeskew in seconds.
1025178825Sdfr *
1026178825Sdfr * @ingroup krb5
1027178825Sdfr */
1028178825Sdfr
1029178825Sdfrvoid KRB5_LIB_FUNCTION
1030178825Sdfrkrb5_set_max_time_skew (krb5_context context, time_t t)
1031178825Sdfr{
1032178825Sdfr    context->max_skew = t;
1033178825Sdfr}
1034