New KRB5_NO_TICKET_STORE env var
[heimdal.git] / lib / krb5 / context.c
blob34d83013c20c124ea65857afec17033fecc98877
1 /*
2 * Copyright (c) 1997 - 2010 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the Institute nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
36 #include "krb5_locl.h"
37 #include <assert.h>
38 #include <com_err.h>
40 #define INIT_FIELD(C, T, E, D, F) \
41 (C)->E = krb5_config_get_ ## T ## _default ((C), NULL, (D), \
42 "libdefaults", F, NULL)
44 #define INIT_FLAG(C, O, V, D, F) \
45 do { \
46 if (krb5_config_get_bool_default((C), NULL, (D),"libdefaults", F, NULL)) { \
47 (C)->O |= V; \
48 } \
49 } while(0)
51 static krb5_error_code
52 copy_enctypes(krb5_context context,
53 const krb5_enctype *in,
54 krb5_enctype **out);
57 * Set the list of etypes `ret_etypes' from the configuration variable
58 * `name'
61 static krb5_error_code
62 set_etypes (krb5_context context,
63 const char *name,
64 krb5_enctype **ret_enctypes)
66 char **etypes_str;
67 krb5_enctype *etypes = NULL;
69 etypes_str = krb5_config_get_strings(context, NULL, "libdefaults",
70 name, NULL);
71 if(etypes_str){
72 int i, j, k;
73 for(i = 0; etypes_str[i]; i++);
74 etypes = malloc((i+1) * sizeof(*etypes));
75 if (etypes == NULL) {
76 krb5_config_free_strings (etypes_str);
77 return krb5_enomem(context);
79 for(j = 0, k = 0; j < i; j++) {
80 krb5_enctype e;
81 if(krb5_string_to_enctype(context, etypes_str[j], &e) != 0)
82 continue;
83 if (krb5_enctype_valid(context, e) != 0)
84 continue;
85 etypes[k++] = e;
87 etypes[k] = ETYPE_NULL;
88 krb5_config_free_strings(etypes_str);
90 *ret_enctypes = etypes;
91 return 0;
95 * read variables from the configuration file and set in `context'
98 static krb5_error_code
99 init_context_from_config_file(krb5_context context)
101 krb5_error_code ret;
102 const char * tmp;
103 char **s;
104 krb5_enctype *tmptypes;
106 INIT_FIELD(context, time, max_skew, 5 * 60, "clockskew");
107 INIT_FIELD(context, time, kdc_timeout, 30, "kdc_timeout");
108 INIT_FIELD(context, time, host_timeout, 3, "host_timeout");
109 INIT_FIELD(context, int, max_retries, 3, "max_retries");
111 INIT_FIELD(context, string, http_proxy, NULL, "http_proxy");
113 ret = krb5_config_get_bool_default(context, NULL, FALSE,
114 "libdefaults",
115 "allow_weak_crypto", NULL);
116 if (ret) {
117 krb5_enctype_enable(context, ETYPE_DES_CBC_CRC);
118 krb5_enctype_enable(context, ETYPE_DES_CBC_MD4);
119 krb5_enctype_enable(context, ETYPE_DES_CBC_MD5);
120 krb5_enctype_enable(context, ETYPE_DES_CBC_NONE);
121 krb5_enctype_enable(context, ETYPE_DES_CFB64_NONE);
122 krb5_enctype_enable(context, ETYPE_DES_PCBC_NONE);
125 ret = set_etypes (context, "default_etypes", &tmptypes);
126 if(ret)
127 return ret;
128 free(context->etypes);
129 context->etypes = tmptypes;
131 /* The etypes member may change during the lifetime
132 * of the context. To be able to reset it to
133 * config value, we keep another copy.
135 free(context->cfg_etypes);
136 context->cfg_etypes = NULL;
137 if (tmptypes) {
138 ret = copy_enctypes(context, tmptypes, &context->cfg_etypes);
139 if (ret)
140 return ret;
143 ret = set_etypes (context, "default_etypes_des", &tmptypes);
144 if(ret)
145 return ret;
146 free(context->etypes_des);
147 context->etypes_des = tmptypes;
149 ret = set_etypes (context, "default_as_etypes", &tmptypes);
150 if(ret)
151 return ret;
152 free(context->as_etypes);
153 context->as_etypes = tmptypes;
155 ret = set_etypes (context, "default_tgs_etypes", &tmptypes);
156 if(ret)
157 return ret;
158 free(context->tgs_etypes);
159 context->tgs_etypes = tmptypes;
161 ret = set_etypes (context, "permitted_enctypes", &tmptypes);
162 if(ret)
163 return ret;
164 free(context->permitted_enctypes);
165 context->permitted_enctypes = tmptypes;
167 INIT_FIELD(context, string, default_keytab,
168 KEYTAB_DEFAULT, "default_keytab_name");
170 INIT_FIELD(context, string, default_keytab_modify,
171 NULL, "default_keytab_modify_name");
173 INIT_FIELD(context, string, time_fmt,
174 "%Y-%m-%dT%H:%M:%S", "time_format");
176 INIT_FIELD(context, string, date_fmt,
177 "%Y-%m-%d", "date_format");
179 INIT_FIELD(context, bool, log_utc,
180 FALSE, "log_utc");
182 context->no_ticket_store =
183 getenv("KRB5_NO_TICKET_STORE") != NULL;
185 /* init dns-proxy slime */
186 tmp = krb5_config_get_string(context, NULL, "libdefaults",
187 "dns_proxy", NULL);
188 if(tmp)
189 roken_gethostby_setup(context->http_proxy, tmp);
190 krb5_free_host_realm (context, context->default_realms);
191 context->default_realms = NULL;
194 krb5_addresses addresses;
195 char **adr, **a;
197 krb5_set_extra_addresses(context, NULL);
198 adr = krb5_config_get_strings(context, NULL,
199 "libdefaults",
200 "extra_addresses",
201 NULL);
202 memset(&addresses, 0, sizeof(addresses));
203 for(a = adr; a && *a; a++) {
204 ret = krb5_parse_address(context, *a, &addresses);
205 if (ret == 0) {
206 krb5_add_extra_addresses(context, &addresses);
207 krb5_free_addresses(context, &addresses);
210 krb5_config_free_strings(adr);
212 krb5_set_ignore_addresses(context, NULL);
213 adr = krb5_config_get_strings(context, NULL,
214 "libdefaults",
215 "ignore_addresses",
216 NULL);
217 memset(&addresses, 0, sizeof(addresses));
218 for(a = adr; a && *a; a++) {
219 ret = krb5_parse_address(context, *a, &addresses);
220 if (ret == 0) {
221 krb5_add_ignore_addresses(context, &addresses);
222 krb5_free_addresses(context, &addresses);
225 krb5_config_free_strings(adr);
228 INIT_FIELD(context, bool, scan_interfaces, TRUE, "scan_interfaces");
229 INIT_FIELD(context, int, fcache_vno, 0, "fcache_version");
230 /* prefer dns_lookup_kdc over srv_lookup. */
231 INIT_FIELD(context, bool, srv_lookup, TRUE, "srv_lookup");
232 INIT_FIELD(context, bool, srv_lookup, context->srv_lookup, "dns_lookup_kdc");
233 INIT_FIELD(context, int, large_msg_size, 1400, "large_message_size");
234 INIT_FIELD(context, int, max_msg_size, 1000 * 1024, "maximum_message_size");
235 INIT_FLAG(context, flags, KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME, TRUE, "dns_canonicalize_hostname");
236 INIT_FLAG(context, flags, KRB5_CTX_F_CHECK_PAC, TRUE, "check_pac");
238 if (context->default_cc_name)
239 free(context->default_cc_name);
240 context->default_cc_name = NULL;
241 context->default_cc_name_set = 0;
243 s = krb5_config_get_strings(context, NULL, "logging", "krb5", NULL);
244 if(s) {
245 char **p;
247 if (context->debug_dest)
248 krb5_closelog(context, context->debug_dest);
250 krb5_initlog(context, "libkrb5", &context->debug_dest);
251 for(p = s; *p; p++)
252 krb5_addlog_dest(context, context->debug_dest, *p);
253 krb5_config_free_strings(s);
256 tmp = krb5_config_get_string(context, NULL, "libdefaults",
257 "check-rd-req-server", NULL);
258 if (tmp == NULL)
259 tmp = secure_getenv("KRB5_CHECK_RD_REQ_SERVER");
260 if(tmp) {
261 if (strcasecmp(tmp, "ignore") == 0)
262 context->flags |= KRB5_CTX_F_RD_REQ_IGNORE;
264 ret = krb5_config_get_bool_default(context, NULL, TRUE,
265 "libdefaults",
266 "fcache_strict_checking", NULL);
267 if (ret)
268 context->flags |= KRB5_CTX_F_FCACHE_STRICT_CHECKING;
270 return 0;
273 static krb5_error_code
274 cc_ops_register(krb5_context context)
276 context->cc_ops = NULL;
277 context->num_cc_ops = 0;
279 #ifndef KCM_IS_API_CACHE
280 krb5_cc_register(context, &krb5_acc_ops, TRUE);
281 #endif
282 krb5_cc_register(context, &krb5_fcc_ops, TRUE);
283 krb5_cc_register(context, &krb5_dcc_ops, TRUE);
284 krb5_cc_register(context, &krb5_mcc_ops, TRUE);
285 #ifdef HAVE_SCC
286 krb5_cc_register(context, &krb5_scc_ops, TRUE);
287 #endif
288 #ifdef HAVE_KCM
289 #ifdef KCM_IS_API_CACHE
290 krb5_cc_register(context, &krb5_akcm_ops, TRUE);
291 #endif
292 krb5_cc_register(context, &krb5_kcm_ops, TRUE);
293 #endif
294 _krb5_load_ccache_plugins(context);
295 return 0;
298 static krb5_error_code
299 cc_ops_copy(krb5_context context, const krb5_context src_context)
301 const krb5_cc_ops **cc_ops;
303 context->cc_ops = NULL;
304 context->num_cc_ops = 0;
306 if (src_context->num_cc_ops == 0)
307 return 0;
309 cc_ops = malloc(sizeof(cc_ops[0]) * src_context->num_cc_ops);
310 if (cc_ops == NULL) {
311 krb5_set_error_message(context, KRB5_CC_NOMEM,
312 N_("malloc: out of memory", ""));
313 return KRB5_CC_NOMEM;
316 memcpy(rk_UNCONST(cc_ops), src_context->cc_ops,
317 sizeof(cc_ops[0]) * src_context->num_cc_ops);
318 context->cc_ops = cc_ops;
319 context->num_cc_ops = src_context->num_cc_ops;
321 return 0;
324 static krb5_error_code
325 kt_ops_register(krb5_context context)
327 context->num_kt_types = 0;
328 context->kt_types = NULL;
330 krb5_kt_register (context, &krb5_fkt_ops);
331 krb5_kt_register (context, &krb5_wrfkt_ops);
332 krb5_kt_register (context, &krb5_javakt_ops);
333 krb5_kt_register (context, &krb5_mkt_ops);
334 #ifndef HEIMDAL_SMALLER
335 krb5_kt_register (context, &krb5_akf_ops);
336 #endif
337 krb5_kt_register (context, &krb5_any_ops);
338 return 0;
341 static krb5_error_code
342 kt_ops_copy(krb5_context context, const krb5_context src_context)
344 context->num_kt_types = 0;
345 context->kt_types = NULL;
347 if (src_context->num_kt_types == 0)
348 return 0;
350 context->kt_types = malloc(sizeof(context->kt_types[0]) * src_context->num_kt_types);
351 if (context->kt_types == NULL)
352 return krb5_enomem(context);
354 context->num_kt_types = src_context->num_kt_types;
355 memcpy(context->kt_types, src_context->kt_types,
356 sizeof(context->kt_types[0]) * src_context->num_kt_types);
358 return 0;
361 static const char *sysplugin_dirs[] = {
362 #ifdef _WIN32
363 "$ORIGIN",
364 #else
365 "$ORIGIN/../lib/plugin/krb5",
366 #endif
367 #ifdef __APPLE__
368 LIBDIR "/plugin/krb5",
369 #ifdef HEIM_PLUGINS_SEARCH_SYSTEM
370 "/Library/KerberosPlugins/KerberosFrameworkPlugins",
371 "/System/Library/KerberosPlugins/KerberosFrameworkPlugins",
372 #endif
373 #endif
374 NULL
377 static void
378 init_context_once(void *ctx)
380 krb5_context context = ctx;
381 char **dirs;
383 #ifdef _WIN32
384 dirs = rk_UNCONST(sysplugin_dirs);
385 #else
386 dirs = krb5_config_get_strings(context, NULL, "libdefaults",
387 "plugin_dir", NULL);
388 if (dirs == NULL)
389 dirs = rk_UNCONST(sysplugin_dirs);
390 #endif
392 _krb5_load_plugins(context, "krb5", (const char **)dirs);
394 if (dirs != rk_UNCONST(sysplugin_dirs))
395 krb5_config_free_strings(dirs);
397 bindtextdomain(HEIMDAL_TEXTDOMAIN, HEIMDAL_LOCALEDIR);
402 * Initializes the context structure and reads the configuration file
403 * /etc/krb5.conf. The structure should be freed by calling
404 * krb5_free_context() when it is no longer being used.
406 * @param context pointer to returned context
408 * @return Returns 0 to indicate success. Otherwise an errno code is
409 * returned. Failure means either that something bad happened during
410 * initialization (typically ENOMEM) or that Kerberos should not be
411 * used ENXIO. If the function returns HEIM_ERR_RANDOM_OFFLINE, the
412 * random source is not available and later Kerberos calls might fail.
414 * @ingroup krb5
417 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
418 krb5_init_context(krb5_context *context)
420 static heim_base_once_t init_context = HEIM_BASE_ONCE_INIT;
421 krb5_context p;
422 krb5_error_code ret;
423 char **files;
424 uint8_t rnd;
426 *context = NULL;
429 * krb5_init_context() will get one random byte to make sure our
430 * random is alive. Assumption is that once the non blocking
431 * source allows us to pull bytes, its all seeded and allows us to
432 * pull more bytes.
434 * Most Kerberos users calls krb5_init_context(), so this is
435 * useful point where we can do the checking.
437 ret = krb5_generate_random(&rnd, sizeof(rnd));
438 if (ret)
439 return ret;
441 p = calloc(1, sizeof(*p));
442 if(!p)
443 return ENOMEM;
445 HEIMDAL_MUTEX_init(&p->mutex);
447 p->flags |= KRB5_CTX_F_HOMEDIR_ACCESS;
449 ret = krb5_get_default_config_files(&files);
450 if(ret)
451 goto out;
452 ret = krb5_set_config_files(p, files);
453 krb5_free_config_files(files);
454 if(ret)
455 goto out;
457 /* done enough to load plugins */
458 heim_base_once_f(&init_context, p, init_context_once);
460 /* init error tables */
461 krb5_init_ets(p);
462 cc_ops_register(p);
463 kt_ops_register(p);
465 #ifdef PKINIT
466 ret = hx509_context_init(&p->hx509ctx);
467 if (ret)
468 goto out;
469 #endif
470 if (rk_SOCK_INIT())
471 p->flags |= KRB5_CTX_F_SOCKETS_INITIALIZED;
473 out:
474 if(ret) {
475 krb5_free_context(p);
476 p = NULL;
478 *context = p;
479 return ret;
482 #ifndef HEIMDAL_SMALLER
484 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
485 krb5_get_permitted_enctypes(krb5_context context,
486 krb5_enctype **etypes)
488 return krb5_get_default_in_tkt_etypes(context, KRB5_PDU_NONE, etypes);
495 static krb5_error_code
496 copy_etypes (krb5_context context,
497 krb5_enctype *enctypes,
498 krb5_enctype **ret_enctypes)
500 unsigned int i;
502 for (i = 0; enctypes[i]; i++)
504 i++;
506 *ret_enctypes = malloc(sizeof(enctypes[0]) * i);
507 if (*ret_enctypes == NULL)
508 return krb5_enomem(context);
509 memcpy(*ret_enctypes, enctypes, sizeof(enctypes[0]) * i);
510 return 0;
514 * Make a copy for the Kerberos 5 context, the new krb5_context shoud
515 * be freed with krb5_free_context().
517 * @param context the Kerberos context to copy
518 * @param out the copy of the Kerberos, set to NULL error.
520 * @return Returns 0 to indicate success. Otherwise an kerberos et
521 * error code is returned, see krb5_get_error_message().
523 * @ingroup krb5
526 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
527 krb5_copy_context(krb5_context context, krb5_context *out)
529 krb5_error_code ret;
530 krb5_context p;
532 *out = NULL;
534 p = calloc(1, sizeof(*p));
535 if (p == NULL)
536 return krb5_enomem(context);
538 HEIMDAL_MUTEX_init(&p->mutex);
540 if (context->default_cc_name)
541 p->default_cc_name = strdup(context->default_cc_name);
542 if (context->default_cc_name_env)
543 p->default_cc_name_env = strdup(context->default_cc_name_env);
545 if (context->etypes) {
546 ret = copy_etypes(context, context->etypes, &p->etypes);
547 if (ret)
548 goto out;
550 if (context->cfg_etypes) {
551 ret = copy_etypes(context, context->cfg_etypes, &p->cfg_etypes);
552 if (ret)
553 goto out;
555 if (context->etypes_des) {
556 ret = copy_etypes(context, context->etypes_des, &p->etypes_des);
557 if (ret)
558 goto out;
561 if (context->default_realms) {
562 ret = krb5_copy_host_realm(context,
563 context->default_realms, &p->default_realms);
564 if (ret)
565 goto out;
568 ret = _krb5_config_copy(context, context->cf, &p->cf);
569 if (ret)
570 goto out;
572 /* XXX should copy */
573 krb5_init_ets(p);
575 cc_ops_copy(p, context);
576 kt_ops_copy(p, context);
578 #if 0 /* XXX */
579 if(context->warn_dest != NULL)
581 if(context->debug_dest != NULL)
583 #endif
585 ret = krb5_set_extra_addresses(p, context->extra_addresses);
586 if (ret)
587 goto out;
588 ret = krb5_set_extra_addresses(p, context->ignore_addresses);
589 if (ret)
590 goto out;
592 ret = _krb5_copy_send_to_kdc_func(p, context);
593 if (ret)
594 goto out;
596 *out = p;
598 return 0;
600 out:
601 krb5_free_context(p);
602 return ret;
605 #endif
608 * Frees the krb5_context allocated by krb5_init_context().
610 * @param context context to be freed.
612 * @ingroup krb5
615 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
616 krb5_free_context(krb5_context context)
618 _krb5_free_name_canon_rules(context, context->name_canon_rules);
619 if (context->default_cc_name)
620 free(context->default_cc_name);
621 if (context->default_cc_name_env)
622 free(context->default_cc_name_env);
623 free(context->etypes);
624 free(context->cfg_etypes);
625 free(context->etypes_des);
626 krb5_free_host_realm (context, context->default_realms);
627 krb5_config_file_free (context, context->cf);
628 free_error_table (context->et_list);
629 free(rk_UNCONST(context->cc_ops));
630 free(context->kt_types);
631 krb5_clear_error_message(context);
632 if(context->warn_dest != NULL)
633 krb5_closelog(context, context->warn_dest);
634 if(context->debug_dest != NULL)
635 krb5_closelog(context, context->debug_dest);
636 krb5_set_extra_addresses(context, NULL);
637 krb5_set_ignore_addresses(context, NULL);
638 krb5_set_send_to_kdc_func(context, NULL, NULL);
640 #ifdef PKINIT
641 if (context->hx509ctx)
642 hx509_context_free(&context->hx509ctx);
643 #endif
645 HEIMDAL_MUTEX_destroy(&context->mutex);
646 if (context->flags & KRB5_CTX_F_SOCKETS_INITIALIZED) {
647 rk_SOCK_EXIT();
650 memset(context, 0, sizeof(*context));
651 free(context);
655 * Reinit the context from a new set of filenames.
657 * @param context context to add configuration too.
658 * @param filenames array of filenames, end of list is indicated with a NULL filename.
660 * @return Returns 0 to indicate success. Otherwise an kerberos et
661 * error code is returned, see krb5_get_error_message().
663 * @ingroup krb5
666 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
667 krb5_set_config_files(krb5_context context, char **filenames)
669 krb5_error_code ret;
670 krb5_config_binding *tmp = NULL;
671 while(filenames != NULL && *filenames != NULL && **filenames != '\0') {
672 ret = krb5_config_parse_file_multi(context, *filenames, &tmp);
673 if (ret != 0 && ret != ENOENT && ret != EACCES && ret != EPERM
674 && ret != KRB5_CONFIG_BADFORMAT) {
675 krb5_config_file_free(context, tmp);
676 return ret;
678 filenames++;
680 #if 0
681 /* with this enabled and if there are no config files, Kerberos is
682 considererd disabled */
683 if(tmp == NULL)
684 return ENXIO;
685 #endif
687 #ifdef _WIN32
688 _krb5_load_config_from_registry(context, &tmp);
689 #endif
691 krb5_config_file_free(context, context->cf);
692 context->cf = tmp;
693 ret = init_context_from_config_file(context);
694 return ret;
697 static krb5_error_code
698 add_file(char ***pfilenames, int *len, char *file)
700 char **pp = *pfilenames;
701 int i;
703 for(i = 0; i < *len; i++) {
704 if(strcmp(pp[i], file) == 0) {
705 free(file);
706 return 0;
710 pp = realloc(*pfilenames, (*len + 2) * sizeof(*pp));
711 if (pp == NULL) {
712 free(file);
713 return ENOMEM;
716 pp[*len] = file;
717 pp[*len + 1] = NULL;
718 *pfilenames = pp;
719 *len += 1;
720 return 0;
724 * `pq' isn't free, it's up the the caller
727 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
728 krb5_prepend_config_files(const char *filelist, char **pq, char ***ret_pp)
730 krb5_error_code ret;
731 const char *p, *q;
732 char **pp;
733 int len;
734 char *fn;
736 pp = NULL;
738 len = 0;
739 p = filelist;
740 while(1) {
741 ssize_t l;
742 q = p;
743 l = strsep_copy(&q, PATH_SEP, NULL, 0);
744 if(l == -1)
745 break;
746 fn = malloc(l + 1);
747 if(fn == NULL) {
748 krb5_free_config_files(pp);
749 return ENOMEM;
751 (void)strsep_copy(&p, PATH_SEP, fn, l + 1);
752 ret = add_file(&pp, &len, fn);
753 if (ret) {
754 krb5_free_config_files(pp);
755 return ret;
759 if (pq != NULL) {
760 int i;
762 for (i = 0; pq[i] != NULL; i++) {
763 fn = strdup(pq[i]);
764 if (fn == NULL) {
765 krb5_free_config_files(pp);
766 return ENOMEM;
768 ret = add_file(&pp, &len, fn);
769 if (ret) {
770 krb5_free_config_files(pp);
771 return ret;
776 *ret_pp = pp;
777 return 0;
781 * Prepend the filename to the global configuration list.
783 * @param filelist a filename to add to the default list of filename
784 * @param pfilenames return array of filenames, should be freed with krb5_free_config_files().
786 * @return Returns 0 to indicate success. Otherwise an kerberos et
787 * error code is returned, see krb5_get_error_message().
789 * @ingroup krb5
792 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
793 krb5_prepend_config_files_default(const char *filelist, char ***pfilenames)
795 krb5_error_code ret;
796 char **defpp, **pp = NULL;
798 ret = krb5_get_default_config_files(&defpp);
799 if (ret)
800 return ret;
802 ret = krb5_prepend_config_files(filelist, defpp, &pp);
803 krb5_free_config_files(defpp);
804 if (ret) {
805 return ret;
807 *pfilenames = pp;
808 return 0;
811 #ifdef _WIN32
814 * Checks the registry for configuration file location
816 * Kerberos for Windows and other legacy Kerberos applications expect
817 * to find the configuration file location in the
818 * SOFTWARE\MIT\Kerberos registry key under the value "config".
820 KRB5_LIB_FUNCTION char * KRB5_LIB_CALL
821 _krb5_get_default_config_config_files_from_registry()
823 static const char * KeyName = "Software\\MIT\\Kerberos";
824 char *config_file = NULL;
825 LONG rcode;
826 HKEY key;
828 rcode = RegOpenKeyEx(HKEY_CURRENT_USER, KeyName, 0, KEY_READ, &key);
829 if (rcode == ERROR_SUCCESS) {
830 config_file = _krb5_parse_reg_value_as_multi_string(NULL, key, "config",
831 REG_NONE, 0, PATH_SEP);
832 RegCloseKey(key);
835 if (config_file)
836 return config_file;
838 rcode = RegOpenKeyEx(HKEY_LOCAL_MACHINE, KeyName, 0, KEY_READ, &key);
839 if (rcode == ERROR_SUCCESS) {
840 config_file = _krb5_parse_reg_value_as_multi_string(NULL, key, "config",
841 REG_NONE, 0, PATH_SEP);
842 RegCloseKey(key);
845 return config_file;
848 #endif
851 * Get the global configuration list.
853 * @param pfilenames return array of filenames, should be freed with krb5_free_config_files().
855 * @return Returns 0 to indicate success. Otherwise an kerberos et
856 * error code is returned, see krb5_get_error_message().
858 * @ingroup krb5
861 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
862 krb5_get_default_config_files(char ***pfilenames)
864 const char *files = NULL;
866 if (pfilenames == NULL)
867 return EINVAL;
868 files = secure_getenv("KRB5_CONFIG");
870 #ifdef _WIN32
871 if (files == NULL) {
872 char * reg_files;
873 reg_files = _krb5_get_default_config_config_files_from_registry();
874 if (reg_files != NULL) {
875 krb5_error_code code;
877 code = krb5_prepend_config_files(reg_files, NULL, pfilenames);
878 free(reg_files);
880 return code;
883 #endif
885 if (files == NULL)
886 files = krb5_config_file;
888 return krb5_prepend_config_files(files, NULL, pfilenames);
892 * Free a list of configuration files.
894 * @param filenames list, terminated with a NULL pointer, to be
895 * freed. NULL is an valid argument.
897 * @return Returns 0 to indicate success. Otherwise an kerberos et
898 * error code is returned, see krb5_get_error_message().
900 * @ingroup krb5
903 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
904 krb5_free_config_files(char **filenames)
906 char **p;
907 for(p = filenames; p && *p != NULL; p++)
908 free(*p);
909 free(filenames);
913 * Returns the list of Kerberos encryption types sorted in order of
914 * most preferred to least preferred encryption type. Note that some
915 * encryption types might be disabled, so you need to check with
916 * krb5_enctype_valid() before using the encryption type.
918 * @return list of enctypes, terminated with ETYPE_NULL. Its a static
919 * array completed into the Kerberos library so the content doesn't
920 * need to be freed.
922 * @ingroup krb5
925 KRB5_LIB_FUNCTION const krb5_enctype * KRB5_LIB_CALL
926 krb5_kerberos_enctypes(krb5_context context)
928 static const krb5_enctype p[] = {
929 ETYPE_AES256_CTS_HMAC_SHA1_96,
930 ETYPE_AES128_CTS_HMAC_SHA1_96,
931 ETYPE_AES256_CTS_HMAC_SHA384_192,
932 ETYPE_AES128_CTS_HMAC_SHA256_128,
933 ETYPE_DES3_CBC_SHA1,
934 ETYPE_ARCFOUR_HMAC_MD5,
935 ETYPE_NULL
938 static const krb5_enctype weak[] = {
939 ETYPE_AES256_CTS_HMAC_SHA1_96,
940 ETYPE_AES128_CTS_HMAC_SHA1_96,
941 ETYPE_AES256_CTS_HMAC_SHA384_192,
942 ETYPE_AES128_CTS_HMAC_SHA256_128,
943 ETYPE_DES3_CBC_SHA1,
944 ETYPE_DES3_CBC_MD5,
945 ETYPE_ARCFOUR_HMAC_MD5,
946 ETYPE_DES_CBC_MD5,
947 ETYPE_DES_CBC_MD4,
948 ETYPE_DES_CBC_CRC,
949 ETYPE_NULL
953 * if the list of enctypes enabled by "allow_weak_crypto"
954 * are valid, then return the former default enctype list
955 * that contained the weak entries.
957 if (krb5_enctype_valid(context, ETYPE_DES_CBC_CRC) == 0 &&
958 krb5_enctype_valid(context, ETYPE_DES_CBC_MD4) == 0 &&
959 krb5_enctype_valid(context, ETYPE_DES_CBC_MD5) == 0 &&
960 krb5_enctype_valid(context, ETYPE_DES_CBC_NONE) == 0 &&
961 krb5_enctype_valid(context, ETYPE_DES_CFB64_NONE) == 0 &&
962 krb5_enctype_valid(context, ETYPE_DES_PCBC_NONE) == 0)
963 return weak;
965 return p;
972 static krb5_error_code
973 copy_enctypes(krb5_context context,
974 const krb5_enctype *in,
975 krb5_enctype **out)
977 krb5_enctype *p = NULL;
978 size_t m, n;
980 for (n = 0; in[n]; n++)
982 n++;
983 ALLOC(p, n);
984 if(p == NULL)
985 return krb5_enomem(context);
986 for (n = 0, m = 0; in[n]; n++) {
987 if (krb5_enctype_valid(context, in[n]) != 0)
988 continue;
989 p[m++] = in[n];
991 p[m] = KRB5_ENCTYPE_NULL;
992 if (m == 0) {
993 free(p);
994 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
995 N_("no valid enctype set", ""));
996 return KRB5_PROG_ETYPE_NOSUPP;
998 *out = p;
999 return 0;
1004 * set `etype' to a malloced list of the default enctypes
1007 static krb5_error_code
1008 default_etypes(krb5_context context, krb5_enctype **etype)
1010 const krb5_enctype *p = krb5_kerberos_enctypes(context);
1011 return copy_enctypes(context, p, etype);
1015 * Set the default encryption types that will be use in communcation
1016 * with the KDC, clients and servers.
1018 * @param context Kerberos 5 context.
1019 * @param etypes Encryption types, array terminated with ETYPE_NULL (0).
1020 * A value of NULL resets the encryption types to the defaults set in the
1021 * configuration file.
1023 * @return Returns 0 to indicate success. Otherwise an kerberos et
1024 * error code is returned, see krb5_get_error_message().
1026 * @ingroup krb5
1029 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1030 krb5_set_default_in_tkt_etypes(krb5_context context,
1031 const krb5_enctype *etypes)
1033 krb5_error_code ret;
1034 krb5_enctype *p = NULL;
1036 if(!etypes) {
1037 etypes = context->cfg_etypes;
1040 if(etypes) {
1041 ret = copy_enctypes(context, etypes, &p);
1042 if (ret)
1043 return ret;
1045 if(context->etypes)
1046 free(context->etypes);
1047 context->etypes = p;
1048 return 0;
1052 * Get the default encryption types that will be use in communcation
1053 * with the KDC, clients and servers.
1055 * @param context Kerberos 5 context.
1056 * @param pdu_type request type (AS, TGS or none)
1057 * @param etypes Encryption types, array terminated with
1058 * ETYPE_NULL(0), caller should free array with krb5_xfree():
1060 * @return Returns 0 to indicate success. Otherwise an kerberos et
1061 * error code is returned, see krb5_get_error_message().
1063 * @ingroup krb5
1066 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1067 krb5_get_default_in_tkt_etypes(krb5_context context,
1068 krb5_pdu pdu_type,
1069 krb5_enctype **etypes)
1071 krb5_enctype *enctypes = NULL;
1072 krb5_error_code ret;
1073 krb5_enctype *p;
1075 heim_assert(pdu_type == KRB5_PDU_AS_REQUEST ||
1076 pdu_type == KRB5_PDU_TGS_REQUEST ||
1077 pdu_type == KRB5_PDU_NONE, "unexpected pdu type");
1079 if (pdu_type == KRB5_PDU_AS_REQUEST && context->as_etypes != NULL)
1080 enctypes = context->as_etypes;
1081 else if (pdu_type == KRB5_PDU_TGS_REQUEST && context->tgs_etypes != NULL)
1082 enctypes = context->tgs_etypes;
1083 else if (context->etypes != NULL)
1084 enctypes = context->etypes;
1086 if (enctypes != NULL) {
1087 ret = copy_enctypes(context, enctypes, &p);
1088 if (ret)
1089 return ret;
1090 } else {
1091 ret = default_etypes(context, &p);
1092 if (ret)
1093 return ret;
1095 *etypes = p;
1096 return 0;
1100 * Init the built-in ets in the Kerberos library.
1102 * @param context kerberos context to add the ets too
1104 * @ingroup krb5
1107 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
1108 krb5_init_ets(krb5_context context)
1110 if(context->et_list == NULL){
1111 krb5_add_et_list(context, initialize_krb5_error_table_r);
1112 krb5_add_et_list(context, initialize_asn1_error_table_r);
1113 krb5_add_et_list(context, initialize_heim_error_table_r);
1115 krb5_add_et_list(context, initialize_k524_error_table_r);
1117 #ifdef COM_ERR_BINDDOMAIN_krb5
1118 bindtextdomain(COM_ERR_BINDDOMAIN_krb5, HEIMDAL_LOCALEDIR);
1119 bindtextdomain(COM_ERR_BINDDOMAIN_asn1, HEIMDAL_LOCALEDIR);
1120 bindtextdomain(COM_ERR_BINDDOMAIN_heim, HEIMDAL_LOCALEDIR);
1121 bindtextdomain(COM_ERR_BINDDOMAIN_k524, HEIMDAL_LOCALEDIR);
1122 #endif
1124 #ifdef PKINIT
1125 krb5_add_et_list(context, initialize_hx_error_table_r);
1126 #ifdef COM_ERR_BINDDOMAIN_hx
1127 bindtextdomain(COM_ERR_BINDDOMAIN_hx, HEIMDAL_LOCALEDIR);
1128 #endif
1129 #endif
1134 * Make the kerberos library default to the admin KDC.
1136 * @param context Kerberos 5 context.
1137 * @param flag boolean flag to select if the use the admin KDC or not.
1139 * @ingroup krb5
1142 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
1143 krb5_set_use_admin_kdc (krb5_context context, krb5_boolean flag)
1145 context->use_admin_kdc = flag;
1149 * Make the kerberos library default to the admin KDC.
1151 * @param context Kerberos 5 context.
1153 * @return boolean flag to telling the context will use admin KDC as the default KDC.
1155 * @ingroup krb5
1158 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
1159 krb5_get_use_admin_kdc (krb5_context context)
1161 return context->use_admin_kdc;
1165 * Add extra address to the address list that the library will add to
1166 * the client's address list when communicating with the KDC.
1168 * @param context Kerberos 5 context.
1169 * @param addresses addreses to add
1171 * @return Returns 0 to indicate success. Otherwise an kerberos et
1172 * error code is returned, see krb5_get_error_message().
1174 * @ingroup krb5
1177 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1178 krb5_add_extra_addresses(krb5_context context, krb5_addresses *addresses)
1181 if(context->extra_addresses)
1182 return krb5_append_addresses(context,
1183 context->extra_addresses, addresses);
1184 else
1185 return krb5_set_extra_addresses(context, addresses);
1189 * Set extra address to the address list that the library will add to
1190 * the client's address list when communicating with the KDC.
1192 * @param context Kerberos 5 context.
1193 * @param addresses addreses to set
1195 * @return Returns 0 to indicate success. Otherwise an kerberos et
1196 * error code is returned, see krb5_get_error_message().
1198 * @ingroup krb5
1201 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1202 krb5_set_extra_addresses(krb5_context context, const krb5_addresses *addresses)
1204 if(context->extra_addresses)
1205 krb5_free_addresses(context, context->extra_addresses);
1207 if(addresses == NULL) {
1208 if(context->extra_addresses != NULL) {
1209 free(context->extra_addresses);
1210 context->extra_addresses = NULL;
1212 return 0;
1214 if(context->extra_addresses == NULL) {
1215 context->extra_addresses = malloc(sizeof(*context->extra_addresses));
1216 if (context->extra_addresses == NULL)
1217 return krb5_enomem(context);
1219 return krb5_copy_addresses(context, addresses, context->extra_addresses);
1223 * Get extra address to the address list that the library will add to
1224 * the client's address list when communicating with the KDC.
1226 * @param context Kerberos 5 context.
1227 * @param addresses addreses to set
1229 * @return Returns 0 to indicate success. Otherwise an kerberos et
1230 * error code is returned, see krb5_get_error_message().
1232 * @ingroup krb5
1235 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1236 krb5_get_extra_addresses(krb5_context context, krb5_addresses *addresses)
1238 if(context->extra_addresses == NULL) {
1239 memset(addresses, 0, sizeof(*addresses));
1240 return 0;
1242 return krb5_copy_addresses(context,context->extra_addresses, addresses);
1246 * Add extra addresses to ignore when fetching addresses from the
1247 * underlaying operating system.
1249 * @param context Kerberos 5 context.
1250 * @param addresses addreses to ignore
1252 * @return Returns 0 to indicate success. Otherwise an kerberos et
1253 * error code is returned, see krb5_get_error_message().
1255 * @ingroup krb5
1258 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1259 krb5_add_ignore_addresses(krb5_context context, krb5_addresses *addresses)
1262 if(context->ignore_addresses)
1263 return krb5_append_addresses(context,
1264 context->ignore_addresses, addresses);
1265 else
1266 return krb5_set_ignore_addresses(context, addresses);
1270 * Set extra addresses to ignore when fetching addresses from the
1271 * underlaying operating system.
1273 * @param context Kerberos 5 context.
1274 * @param addresses addreses to ignore
1276 * @return Returns 0 to indicate success. Otherwise an kerberos et
1277 * error code is returned, see krb5_get_error_message().
1279 * @ingroup krb5
1282 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1283 krb5_set_ignore_addresses(krb5_context context, const krb5_addresses *addresses)
1285 if(context->ignore_addresses)
1286 krb5_free_addresses(context, context->ignore_addresses);
1287 if(addresses == NULL) {
1288 if(context->ignore_addresses != NULL) {
1289 free(context->ignore_addresses);
1290 context->ignore_addresses = NULL;
1292 return 0;
1294 if(context->ignore_addresses == NULL) {
1295 context->ignore_addresses = malloc(sizeof(*context->ignore_addresses));
1296 if (context->ignore_addresses == NULL)
1297 return krb5_enomem(context);
1299 return krb5_copy_addresses(context, addresses, context->ignore_addresses);
1303 * Get extra addresses to ignore when fetching addresses from the
1304 * underlaying operating system.
1306 * @param context Kerberos 5 context.
1307 * @param addresses list addreses ignored
1309 * @return Returns 0 to indicate success. Otherwise an kerberos et
1310 * error code is returned, see krb5_get_error_message().
1312 * @ingroup krb5
1315 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1316 krb5_get_ignore_addresses(krb5_context context, krb5_addresses *addresses)
1318 if(context->ignore_addresses == NULL) {
1319 memset(addresses, 0, sizeof(*addresses));
1320 return 0;
1322 return krb5_copy_addresses(context, context->ignore_addresses, addresses);
1326 * Set version of fcache that the library should use.
1328 * @param context Kerberos 5 context.
1329 * @param version version number.
1331 * @return Returns 0 to indicate success. Otherwise an kerberos et
1332 * error code is returned, see krb5_get_error_message().
1334 * @ingroup krb5
1337 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1338 krb5_set_fcache_version(krb5_context context, int version)
1340 context->fcache_vno = version;
1341 return 0;
1345 * Get version of fcache that the library should use.
1347 * @param context Kerberos 5 context.
1348 * @param version version number.
1350 * @return Returns 0 to indicate success. Otherwise an kerberos et
1351 * error code is returned, see krb5_get_error_message().
1353 * @ingroup krb5
1356 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1357 krb5_get_fcache_version(krb5_context context, int *version)
1359 *version = context->fcache_vno;
1360 return 0;
1364 * Runtime check if the Kerberos library was complied with thread support.
1366 * @return TRUE if the library was compiled with thread support, FALSE if not.
1368 * @ingroup krb5
1372 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
1373 krb5_is_thread_safe(void)
1375 #ifdef ENABLE_PTHREAD_SUPPORT
1376 return TRUE;
1377 #else
1378 return FALSE;
1379 #endif
1383 * Set if the library should use DNS to canonicalize hostnames.
1385 * @param context Kerberos 5 context.
1386 * @param flag if its dns canonicalizion is used or not.
1388 * @ingroup krb5
1391 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
1392 krb5_set_dns_canonicalize_hostname (krb5_context context, krb5_boolean flag)
1394 if (flag)
1395 context->flags |= KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME;
1396 else
1397 context->flags &= ~KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME;
1401 * Get if the library uses DNS to canonicalize hostnames.
1403 * @param context Kerberos 5 context.
1405 * @return return non zero if the library uses DNS to canonicalize hostnames.
1407 * @ingroup krb5
1410 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
1411 krb5_get_dns_canonicalize_hostname (krb5_context context)
1413 return (context->flags & KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME) ? 1 : 0;
1417 * Get current offset in time to the KDC.
1419 * @param context Kerberos 5 context.
1420 * @param sec seconds part of offset.
1421 * @param usec micro seconds part of offset.
1423 * @return returns zero
1425 * @ingroup krb5
1428 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1429 krb5_get_kdc_sec_offset (krb5_context context, int32_t *sec, int32_t *usec)
1431 if (sec)
1432 *sec = context->kdc_sec_offset;
1433 if (usec)
1434 *usec = context->kdc_usec_offset;
1435 return 0;
1439 * Set current offset in time to the KDC.
1441 * @param context Kerberos 5 context.
1442 * @param sec seconds part of offset.
1443 * @param usec micro seconds part of offset.
1445 * @return returns zero
1447 * @ingroup krb5
1450 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1451 krb5_set_kdc_sec_offset (krb5_context context, int32_t sec, int32_t usec)
1453 context->kdc_sec_offset = sec;
1454 if (usec >= 0)
1455 context->kdc_usec_offset = usec;
1456 return 0;
1460 * Get max time skew allowed.
1462 * @param context Kerberos 5 context.
1464 * @return timeskew in seconds.
1466 * @ingroup krb5
1469 KRB5_LIB_FUNCTION time_t KRB5_LIB_CALL
1470 krb5_get_max_time_skew (krb5_context context)
1472 return context->max_skew;
1476 * Set max time skew allowed.
1478 * @param context Kerberos 5 context.
1479 * @param t timeskew in seconds.
1481 * @ingroup krb5
1484 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
1485 krb5_set_max_time_skew (krb5_context context, time_t t)
1487 context->max_skew = t;
1491 * Init encryption types in len, val with etypes.
1493 * @param context Kerberos 5 context.
1494 * @param pdu_type type of pdu
1495 * @param len output length of val.
1496 * @param val output array of enctypes.
1497 * @param etypes etypes to set val and len to, if NULL, use default enctypes.
1499 * @return Returns 0 to indicate success. Otherwise an kerberos et
1500 * error code is returned, see krb5_get_error_message().
1502 * @ingroup krb5
1505 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1506 _krb5_init_etype(krb5_context context,
1507 krb5_pdu pdu_type,
1508 unsigned *len,
1509 krb5_enctype **val,
1510 const krb5_enctype *etypes)
1512 krb5_error_code ret;
1514 if (etypes == NULL)
1515 ret = krb5_get_default_in_tkt_etypes(context, pdu_type, val);
1516 else
1517 ret = copy_enctypes(context, etypes, val);
1518 if (ret)
1519 return ret;
1521 if (len) {
1522 *len = 0;
1523 while ((*val)[*len] != KRB5_ENCTYPE_NULL)
1524 (*len)++;
1526 return 0;
1530 * Allow homedir accces
1533 static HEIMDAL_MUTEX homedir_mutex = HEIMDAL_MUTEX_INITIALIZER;
1534 static krb5_boolean allow_homedir = TRUE;
1536 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
1537 _krb5_homedir_access(krb5_context context)
1539 krb5_boolean allow;
1541 if (context && (context->flags & KRB5_CTX_F_HOMEDIR_ACCESS) == 0)
1542 return FALSE;
1544 HEIMDAL_MUTEX_lock(&homedir_mutex);
1545 allow = allow_homedir;
1546 HEIMDAL_MUTEX_unlock(&homedir_mutex);
1547 return allow;
1551 * Enable and disable home directory access on either the global state
1552 * or the krb5_context state. By calling krb5_set_home_dir_access()
1553 * with context set to NULL, the global state is configured otherwise
1554 * the state for the krb5_context is modified.
1556 * For home directory access to be allowed, both the global state and
1557 * the krb5_context state have to be allowed.
1559 * @param context a Kerberos 5 context or NULL
1560 * @param allow allow if TRUE home directory
1561 * @return the old value
1563 * @ingroup krb5
1566 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
1567 krb5_set_home_dir_access(krb5_context context, krb5_boolean allow)
1569 krb5_boolean old;
1570 if (context) {
1571 old = (context->flags & KRB5_CTX_F_HOMEDIR_ACCESS) ? TRUE : FALSE;
1572 if (allow)
1573 context->flags |= KRB5_CTX_F_HOMEDIR_ACCESS;
1574 else
1575 context->flags &= ~KRB5_CTX_F_HOMEDIR_ACCESS;
1576 } else {
1577 HEIMDAL_MUTEX_lock(&homedir_mutex);
1578 old = allow_homedir;
1579 allow_homedir = allow;
1580 HEIMDAL_MUTEX_unlock(&homedir_mutex);
1583 return old;