1 /* $NetBSD: context.c,v 1.3 2013/11/14 05:04:24 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1997 - 2010 Kungliga Tekniska Högskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * All rights reserved. 7 * 8 * Portions Copyright (c) 2009 Apple Inc. All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 21 * 3. Neither the name of the Institute nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 */ 37 38 #include "krb5_locl.h" 39 #include <krb5/com_err.h> 40 41 #define INIT_FIELD(C, T, E, D, F) \ 42 (C)->E = krb5_config_get_ ## T ## _default ((C), NULL, (D), \ 43 "libdefaults", F, NULL) 44 45 #define INIT_FLAG(C, O, V, D, F) \ 46 do { \ 47 if (krb5_config_get_bool_default((C), NULL, (D),"libdefaults", F, NULL)) { \ 48 (C)->O |= V; \ 49 } \ 50 } while(0) 51 52 /* 53 * Set the list of etypes `ret_etypes' from the configuration variable 54 * `name' 55 */ 56 57 static krb5_error_code 58 set_etypes (krb5_context context, 59 const char *name, 60 krb5_enctype **ret_enctypes) 61 { 62 char **etypes_str; 63 krb5_enctype *etypes = NULL; 64 65 etypes_str = krb5_config_get_strings(context, NULL, "libdefaults", 66 name, NULL); 67 if(etypes_str){ 68 int i, j, k; 69 for(i = 0; etypes_str[i]; i++); 70 etypes = malloc((i+1) * sizeof(*etypes)); 71 if (etypes == NULL) { 72 krb5_config_free_strings (etypes_str); 73 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", "")); 74 return ENOMEM; 75 } 76 for(j = 0, k = 0; j < i; j++) { 77 krb5_enctype e; 78 if(krb5_string_to_enctype(context, etypes_str[j], &e) != 0) 79 continue; 80 if (krb5_enctype_valid(context, e) != 0) 81 continue; 82 etypes[k++] = e; 83 } 84 etypes[k] = ETYPE_NULL; 85 krb5_config_free_strings(etypes_str); 86 } 87 *ret_enctypes = etypes; 88 return 0; 89 } 90 91 /* 92 * read variables from the configuration file and set in `context' 93 */ 94 95 static krb5_error_code 96 init_context_from_config_file(krb5_context context) 97 { 98 krb5_error_code ret; 99 const char * tmp; 100 char **s; 101 krb5_enctype *tmptypes; 102 103 INIT_FIELD(context, time, max_skew, 5 * 60, "clockskew"); 104 INIT_FIELD(context, time, kdc_timeout, 3, "kdc_timeout"); 105 INIT_FIELD(context, int, max_retries, 3, "max_retries"); 106 107 INIT_FIELD(context, string, http_proxy, NULL, "http_proxy"); 108 109 ret = krb5_config_get_bool_default(context, NULL, FALSE, 110 "libdefaults", 111 "allow_weak_crypto", NULL); 112 if (ret) { 113 krb5_enctype_enable(context, ETYPE_DES_CBC_CRC); 114 krb5_enctype_enable(context, ETYPE_DES_CBC_MD4); 115 krb5_enctype_enable(context, ETYPE_DES_CBC_MD5); 116 krb5_enctype_enable(context, ETYPE_DES_CBC_NONE); 117 krb5_enctype_enable(context, ETYPE_DES_CFB64_NONE); 118 krb5_enctype_enable(context, ETYPE_DES_PCBC_NONE); 119 } 120 121 ret = set_etypes (context, "default_etypes", &tmptypes); 122 if(ret) 123 return ret; 124 free(context->etypes); 125 context->etypes = tmptypes; 126 127 ret = set_etypes (context, "default_etypes_des", &tmptypes); 128 if(ret) 129 return ret; 130 free(context->etypes_des); 131 context->etypes_des = tmptypes; 132 133 /* default keytab name */ 134 tmp = NULL; 135 if(!issuid()) 136 tmp = getenv("KRB5_KTNAME"); 137 if(tmp != NULL) 138 context->default_keytab = tmp; 139 else 140 INIT_FIELD(context, string, default_keytab, 141 KEYTAB_DEFAULT, "default_keytab_name"); 142 143 INIT_FIELD(context, string, default_keytab_modify, 144 NULL, "default_keytab_modify_name"); 145 146 INIT_FIELD(context, string, time_fmt, 147 "%Y-%m-%dT%H:%M:%S", "time_format"); 148 149 INIT_FIELD(context, string, date_fmt, 150 "%Y-%m-%d", "date_format"); 151 152 INIT_FIELD(context, bool, log_utc, 153 FALSE, "log_utc"); 154 155 156 157 /* init dns-proxy slime */ 158 tmp = krb5_config_get_string(context, NULL, "libdefaults", 159 "dns_proxy", NULL); 160 if(tmp) 161 roken_gethostby_setup(context->http_proxy, tmp); 162 krb5_free_host_realm (context, context->default_realms); 163 context->default_realms = NULL; 164 165 { 166 krb5_addresses addresses; 167 char **adr, **a; 168 169 krb5_set_extra_addresses(context, NULL); 170 adr = krb5_config_get_strings(context, NULL, 171 "libdefaults", 172 "extra_addresses", 173 NULL); 174 memset(&addresses, 0, sizeof(addresses)); 175 for(a = adr; a && *a; a++) { 176 ret = krb5_parse_address(context, *a, &addresses); 177 if (ret == 0) { 178 krb5_add_extra_addresses(context, &addresses); 179 krb5_free_addresses(context, &addresses); 180 } 181 } 182 krb5_config_free_strings(adr); 183 184 krb5_set_ignore_addresses(context, NULL); 185 adr = krb5_config_get_strings(context, NULL, 186 "libdefaults", 187 "ignore_addresses", 188 NULL); 189 memset(&addresses, 0, sizeof(addresses)); 190 for(a = adr; a && *a; a++) { 191 ret = krb5_parse_address(context, *a, &addresses); 192 if (ret == 0) { 193 krb5_add_ignore_addresses(context, &addresses); 194 krb5_free_addresses(context, &addresses); 195 } 196 } 197 krb5_config_free_strings(adr); 198 } 199 200 INIT_FIELD(context, bool, scan_interfaces, TRUE, "scan_interfaces"); 201 INIT_FIELD(context, int, fcache_vno, 0, "fcache_version"); 202 /* prefer dns_lookup_kdc over srv_lookup. */ 203 INIT_FIELD(context, bool, srv_lookup, TRUE, "srv_lookup"); 204 INIT_FIELD(context, bool, srv_lookup, context->srv_lookup, "dns_lookup_kdc"); 205 INIT_FIELD(context, int, large_msg_size, 1400, "large_message_size"); 206 INIT_FLAG(context, flags, KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME, TRUE, "dns_canonicalize_hostname"); 207 INIT_FLAG(context, flags, KRB5_CTX_F_CHECK_PAC, TRUE, "check_pac"); 208 context->default_cc_name = NULL; 209 context->default_cc_name_set = 0; 210 211 s = krb5_config_get_strings(context, NULL, "logging", "krb5", NULL); 212 if(s) { 213 char **p; 214 krb5_initlog(context, "libkrb5", &context->debug_dest); 215 for(p = s; *p; p++) 216 krb5_addlog_dest(context, context->debug_dest, *p); 217 krb5_config_free_strings(s); 218 } 219 220 tmp = krb5_config_get_string(context, NULL, "libdefaults", 221 "check-rd-req-server", NULL); 222 if (tmp == NULL && !issuid()) 223 tmp = getenv("KRB5_CHECK_RD_REQ_SERVER"); 224 if(tmp) { 225 if (strcasecmp(tmp, "ignore") == 0) 226 context->flags |= KRB5_CTX_F_RD_REQ_IGNORE; 227 } 228 229 return 0; 230 } 231 232 static krb5_error_code 233 cc_ops_register(krb5_context context) 234 { 235 context->cc_ops = NULL; 236 context->num_cc_ops = 0; 237 238 #ifndef KCM_IS_API_CACHE 239 krb5_cc_register(context, &krb5_acc_ops, TRUE); 240 #endif 241 krb5_cc_register(context, &krb5_fcc_ops, TRUE); 242 krb5_cc_register(context, &krb5_mcc_ops, TRUE); 243 #ifdef HAVE_SCC 244 krb5_cc_register(context, &krb5_scc_ops, TRUE); 245 #endif 246 #ifdef HAVE_KCM 247 #ifdef KCM_IS_API_CACHE 248 krb5_cc_register(context, &krb5_akcm_ops, TRUE); 249 #endif 250 krb5_cc_register(context, &krb5_kcm_ops, TRUE); 251 #endif 252 _krb5_load_ccache_plugins(context); 253 return 0; 254 } 255 256 static krb5_error_code 257 cc_ops_copy(krb5_context context, const krb5_context src_context) 258 { 259 const krb5_cc_ops **cc_ops; 260 261 context->cc_ops = NULL; 262 context->num_cc_ops = 0; 263 264 if (src_context->num_cc_ops == 0) 265 return 0; 266 267 cc_ops = malloc(sizeof(cc_ops[0]) * src_context->num_cc_ops); 268 if (cc_ops == NULL) { 269 krb5_set_error_message(context, KRB5_CC_NOMEM, 270 N_("malloc: out of memory", "")); 271 return KRB5_CC_NOMEM; 272 } 273 274 memcpy(rk_UNCONST(cc_ops), src_context->cc_ops, 275 sizeof(cc_ops[0]) * src_context->num_cc_ops); 276 context->cc_ops = cc_ops; 277 context->num_cc_ops = src_context->num_cc_ops; 278 279 return 0; 280 } 281 282 static krb5_error_code 283 kt_ops_register(krb5_context context) 284 { 285 context->num_kt_types = 0; 286 context->kt_types = NULL; 287 288 krb5_kt_register (context, &krb5_fkt_ops); 289 krb5_kt_register (context, &krb5_wrfkt_ops); 290 krb5_kt_register (context, &krb5_javakt_ops); 291 krb5_kt_register (context, &krb5_mkt_ops); 292 #ifndef HEIMDAL_SMALLER 293 krb5_kt_register (context, &krb5_akf_ops); 294 #endif 295 krb5_kt_register (context, &krb5_any_ops); 296 return 0; 297 } 298 299 static krb5_error_code 300 kt_ops_copy(krb5_context context, const krb5_context src_context) 301 { 302 context->num_kt_types = 0; 303 context->kt_types = NULL; 304 305 if (src_context->num_kt_types == 0) 306 return 0; 307 308 context->kt_types = malloc(sizeof(context->kt_types[0]) * src_context->num_kt_types); 309 if (context->kt_types == NULL) { 310 krb5_set_error_message(context, ENOMEM, 311 N_("malloc: out of memory", "")); 312 return ENOMEM; 313 } 314 315 context->num_kt_types = src_context->num_kt_types; 316 memcpy(context->kt_types, src_context->kt_types, 317 sizeof(context->kt_types[0]) * src_context->num_kt_types); 318 319 return 0; 320 } 321 322 static const char *sysplugin_dirs[] = { 323 LIBDIR "/plugin/krb5", 324 #ifdef __APPLE__ 325 "/Library/KerberosPlugins/KerberosFrameworkPlugins", 326 "/System/Library/KerberosPlugins/KerberosFrameworkPlugins", 327 #endif 328 NULL 329 }; 330 331 static void 332 init_context_once(void *ctx) 333 { 334 krb5_context context = ctx; 335 336 _krb5_load_plugins(context, "krb5", sysplugin_dirs); 337 338 bindtextdomain(HEIMDAL_TEXTDOMAIN, HEIMDAL_LOCALEDIR); 339 } 340 341 342 /** 343 * Initializes the context structure and reads the configuration file 344 * /etc/krb5.conf. The structure should be freed by calling 345 * krb5_free_context() when it is no longer being used. 346 * 347 * @param context pointer to returned context 348 * 349 * @return Returns 0 to indicate success. Otherwise an errno code is 350 * returned. Failure means either that something bad happened during 351 * initialization (typically ENOMEM) or that Kerberos should not be 352 * used ENXIO. 353 * 354 * @ingroup krb5 355 */ 356 357 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 358 krb5_init_context(krb5_context *context) 359 { 360 static heim_base_once_t init_context = HEIM_BASE_ONCE_INIT; 361 krb5_context p; 362 krb5_error_code ret; 363 char **files; 364 365 *context = NULL; 366 367 p = calloc(1, sizeof(*p)); 368 if(!p) 369 return ENOMEM; 370 371 p->mutex = malloc(sizeof(HEIMDAL_MUTEX)); 372 if (p->mutex == NULL) { 373 free(p); 374 return ENOMEM; 375 } 376 HEIMDAL_MUTEX_init(p->mutex); 377 378 p->flags |= KRB5_CTX_F_HOMEDIR_ACCESS; 379 380 ret = krb5_get_default_config_files(&files); 381 if(ret) 382 goto out; 383 ret = krb5_set_config_files(p, files); 384 krb5_free_config_files(files); 385 if(ret) 386 goto out; 387 388 /* init error tables */ 389 krb5_init_ets(p); 390 cc_ops_register(p); 391 kt_ops_register(p); 392 393 #ifdef PKINIT 394 ret = hx509_context_init(&p->hx509ctx); 395 if (ret) 396 goto out; 397 #endif 398 if (rk_SOCK_INIT()) 399 p->flags |= KRB5_CTX_F_SOCKETS_INITIALIZED; 400 401 out: 402 if(ret) { 403 krb5_free_context(p); 404 p = NULL; 405 } else { 406 heim_base_once_f(&init_context, p, init_context_once); 407 } 408 *context = p; 409 return ret; 410 } 411 412 #ifndef HEIMDAL_SMALLER 413 414 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 415 krb5_get_permitted_enctypes(krb5_context context, 416 krb5_enctype **etypes) 417 { 418 return krb5_get_default_in_tkt_etypes(context, etypes); 419 } 420 421 /* 422 * 423 */ 424 425 static krb5_error_code 426 copy_etypes (krb5_context context, 427 krb5_enctype *enctypes, 428 krb5_enctype **ret_enctypes) 429 { 430 unsigned int i; 431 432 for (i = 0; enctypes[i]; i++) 433 ; 434 i++; 435 436 *ret_enctypes = malloc(sizeof(**ret_enctypes) * i); 437 if (*ret_enctypes == NULL) { 438 krb5_set_error_message(context, ENOMEM, 439 N_("malloc: out of memory", "")); 440 return ENOMEM; 441 } 442 memcpy(*ret_enctypes, enctypes, sizeof(**ret_enctypes) * i); 443 return 0; 444 } 445 446 /** 447 * Make a copy for the Kerberos 5 context, the new krb5_context shoud 448 * be freed with krb5_free_context(). 449 * 450 * @param context the Kerberos context to copy 451 * @param out the copy of the Kerberos, set to NULL error. 452 * 453 * @return Returns 0 to indicate success. Otherwise an kerberos et 454 * error code is returned, see krb5_get_error_message(). 455 * 456 * @ingroup krb5 457 */ 458 459 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 460 krb5_copy_context(krb5_context context, krb5_context *out) 461 { 462 krb5_error_code ret; 463 krb5_context p; 464 465 *out = NULL; 466 467 p = calloc(1, sizeof(*p)); 468 if (p == NULL) { 469 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 470 return ENOMEM; 471 } 472 473 p->mutex = malloc(sizeof(HEIMDAL_MUTEX)); 474 if (p->mutex == NULL) { 475 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 476 free(p); 477 return ENOMEM; 478 } 479 HEIMDAL_MUTEX_init(p->mutex); 480 481 482 if (context->default_cc_name) 483 p->default_cc_name = strdup(context->default_cc_name); 484 if (context->default_cc_name_env) 485 p->default_cc_name_env = strdup(context->default_cc_name_env); 486 487 if (context->etypes) { 488 ret = copy_etypes(context, context->etypes, &p->etypes); 489 if (ret) 490 goto out; 491 } 492 if (context->etypes_des) { 493 ret = copy_etypes(context, context->etypes_des, &p->etypes_des); 494 if (ret) 495 goto out; 496 } 497 498 if (context->default_realms) { 499 ret = krb5_copy_host_realm(context, 500 context->default_realms, &p->default_realms); 501 if (ret) 502 goto out; 503 } 504 505 ret = _krb5_config_copy(context, context->cf, &p->cf); 506 if (ret) 507 goto out; 508 509 /* XXX should copy */ 510 krb5_init_ets(p); 511 512 cc_ops_copy(p, context); 513 kt_ops_copy(p, context); 514 515 #if 0 /* XXX */ 516 if(context->warn_dest != NULL) 517 ; 518 if(context->debug_dest != NULL) 519 ; 520 #endif 521 522 ret = krb5_set_extra_addresses(p, context->extra_addresses); 523 if (ret) 524 goto out; 525 ret = krb5_set_extra_addresses(p, context->ignore_addresses); 526 if (ret) 527 goto out; 528 529 ret = _krb5_copy_send_to_kdc_func(p, context); 530 if (ret) 531 goto out; 532 533 *out = p; 534 535 return 0; 536 537 out: 538 krb5_free_context(p); 539 return ret; 540 } 541 542 #endif 543 544 /** 545 * Frees the krb5_context allocated by krb5_init_context(). 546 * 547 * @param context context to be freed. 548 * 549 * @ingroup krb5 550 */ 551 552 KRB5_LIB_FUNCTION void KRB5_LIB_CALL 553 krb5_free_context(krb5_context context) 554 { 555 if (context->default_cc_name) 556 free(context->default_cc_name); 557 if (context->default_cc_name_env) 558 free(context->default_cc_name_env); 559 free(context->etypes); 560 free(context->etypes_des); 561 krb5_free_host_realm (context, context->default_realms); 562 krb5_config_file_free (context, context->cf); 563 free_error_table (context->et_list); 564 free(rk_UNCONST(context->cc_ops)); 565 free(context->kt_types); 566 krb5_clear_error_message(context); 567 if(context->warn_dest != NULL) 568 krb5_closelog(context, context->warn_dest); 569 if(context->debug_dest != NULL) 570 krb5_closelog(context, context->debug_dest); 571 krb5_set_extra_addresses(context, NULL); 572 krb5_set_ignore_addresses(context, NULL); 573 krb5_set_send_to_kdc_func(context, NULL, NULL); 574 575 #ifdef PKINIT 576 if (context->hx509ctx) 577 hx509_context_free(&context->hx509ctx); 578 #endif 579 580 HEIMDAL_MUTEX_destroy(context->mutex); 581 free(context->mutex); 582 if (context->flags & KRB5_CTX_F_SOCKETS_INITIALIZED) { 583 rk_SOCK_EXIT(); 584 } 585 586 memset(context, 0, sizeof(*context)); 587 free(context); 588 } 589 590 /** 591 * Reinit the context from a new set of filenames. 592 * 593 * @param context context to add configuration too. 594 * @param filenames array of filenames, end of list is indicated with a NULL filename. 595 * 596 * @return Returns 0 to indicate success. Otherwise an kerberos et 597 * error code is returned, see krb5_get_error_message(). 598 * 599 * @ingroup krb5 600 */ 601 602 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 603 krb5_set_config_files(krb5_context context, char **filenames) 604 { 605 krb5_error_code ret; 606 krb5_config_binding *tmp = NULL; 607 while(filenames != NULL && *filenames != NULL && **filenames != '\0') { 608 ret = krb5_config_parse_file_multi(context, *filenames, &tmp); 609 if(ret != 0 && ret != ENOENT && ret != EACCES && ret != EPERM) { 610 krb5_config_file_free(context, tmp); 611 return ret; 612 } 613 filenames++; 614 } 615 #if 1 616 /* with this enabled and if there are no config files, Kerberos is 617 considererd disabled */ 618 if(tmp == NULL) 619 return ENXIO; 620 #endif 621 622 #ifdef _WIN32 623 _krb5_load_config_from_registry(context, &tmp); 624 #endif 625 626 krb5_config_file_free(context, context->cf); 627 context->cf = tmp; 628 ret = init_context_from_config_file(context); 629 return ret; 630 } 631 632 static krb5_error_code 633 add_file(char ***pfilenames, int *len, char *file) 634 { 635 char **pp = *pfilenames; 636 int i; 637 638 for(i = 0; i < *len; i++) { 639 if(strcmp(pp[i], file) == 0) { 640 free(file); 641 return 0; 642 } 643 } 644 645 pp = realloc(*pfilenames, (*len + 2) * sizeof(*pp)); 646 if (pp == NULL) { 647 free(file); 648 return ENOMEM; 649 } 650 651 pp[*len] = file; 652 pp[*len + 1] = NULL; 653 *pfilenames = pp; 654 *len += 1; 655 return 0; 656 } 657 658 /* 659 * `pq' isn't free, it's up the the caller 660 */ 661 662 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 663 krb5_prepend_config_files(const char *filelist, char **pq, char ***ret_pp) 664 { 665 krb5_error_code ret; 666 const char *p, *q; 667 char **pp; 668 int len; 669 char *fn; 670 671 pp = NULL; 672 673 len = 0; 674 p = filelist; 675 while(1) { 676 ssize_t l; 677 q = p; 678 l = strsep_copy(&q, PATH_SEP, NULL, 0); 679 if(l == -1) 680 break; 681 fn = malloc(l + 1); 682 if(fn == NULL) { 683 krb5_free_config_files(pp); 684 return ENOMEM; 685 } 686 (void)strsep_copy(&p, PATH_SEP, fn, l + 1); 687 ret = add_file(&pp, &len, fn); 688 if (ret) { 689 krb5_free_config_files(pp); 690 return ret; 691 } 692 } 693 694 if (pq != NULL) { 695 int i; 696 697 for (i = 0; pq[i] != NULL; i++) { 698 fn = strdup(pq[i]); 699 if (fn == NULL) { 700 krb5_free_config_files(pp); 701 return ENOMEM; 702 } 703 ret = add_file(&pp, &len, fn); 704 if (ret) { 705 krb5_free_config_files(pp); 706 return ret; 707 } 708 } 709 } 710 711 *ret_pp = pp; 712 return 0; 713 } 714 715 /** 716 * Prepend the filename to the global configuration list. 717 * 718 * @param filelist a filename to add to the default list of filename 719 * @param pfilenames return array of filenames, should be freed with krb5_free_config_files(). 720 * 721 * @return Returns 0 to indicate success. Otherwise an kerberos et 722 * error code is returned, see krb5_get_error_message(). 723 * 724 * @ingroup krb5 725 */ 726 727 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 728 krb5_prepend_config_files_default(const char *filelist, char ***pfilenames) 729 { 730 krb5_error_code ret; 731 char **defpp, **pp = NULL; 732 733 ret = krb5_get_default_config_files(&defpp); 734 if (ret) 735 return ret; 736 737 ret = krb5_prepend_config_files(filelist, defpp, &pp); 738 krb5_free_config_files(defpp); 739 if (ret) { 740 return ret; 741 } 742 *pfilenames = pp; 743 return 0; 744 } 745 746 #ifdef _WIN32 747 748 /** 749 * Checks the registry for configuration file location 750 * 751 * Kerberos for Windows and other legacy Kerberos applications expect 752 * to find the configuration file location in the 753 * SOFTWARE\MIT\Kerberos registry key under the value "config". 754 */ 755 char * 756 _krb5_get_default_config_config_files_from_registry() 757 { 758 static const char * KeyName = "Software\\MIT\\Kerberos"; 759 char *config_file = NULL; 760 LONG rcode; 761 HKEY key; 762 763 rcode = RegOpenKeyEx(HKEY_CURRENT_USER, KeyName, 0, KEY_READ, &key); 764 if (rcode == ERROR_SUCCESS) { 765 config_file = _krb5_parse_reg_value_as_multi_string(NULL, key, "config", 766 REG_NONE, 0, PATH_SEP); 767 RegCloseKey(key); 768 } 769 770 if (config_file) 771 return config_file; 772 773 rcode = RegOpenKeyEx(HKEY_LOCAL_MACHINE, KeyName, 0, KEY_READ, &key); 774 if (rcode == ERROR_SUCCESS) { 775 config_file = _krb5_parse_reg_value_as_multi_string(NULL, key, "config", 776 REG_NONE, 0, PATH_SEP); 777 RegCloseKey(key); 778 } 779 780 return config_file; 781 } 782 783 #endif 784 785 /** 786 * Get the global configuration list. 787 * 788 * @param pfilenames return array of filenames, should be freed with krb5_free_config_files(). 789 * 790 * @return Returns 0 to indicate success. Otherwise an kerberos et 791 * error code is returned, see krb5_get_error_message(). 792 * 793 * @ingroup krb5 794 */ 795 796 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 797 krb5_get_default_config_files(char ***pfilenames) 798 { 799 const char *files = NULL; 800 801 if (pfilenames == NULL) 802 return EINVAL; 803 if(!issuid()) 804 files = getenv("KRB5_CONFIG"); 805 806 #ifdef _WIN32 807 if (files == NULL) { 808 char * reg_files; 809 reg_files = _krb5_get_default_config_config_files_from_registry(); 810 if (reg_files != NULL) { 811 krb5_error_code code; 812 813 code = krb5_prepend_config_files(reg_files, NULL, pfilenames); 814 free(reg_files); 815 816 return code; 817 } 818 } 819 #endif 820 821 if (files == NULL) 822 files = krb5_config_file; 823 824 return krb5_prepend_config_files(files, NULL, pfilenames); 825 } 826 827 /** 828 * Free a list of configuration files. 829 * 830 * @param filenames list, terminated with a NULL pointer, to be 831 * freed. NULL is an valid argument. 832 * 833 * @return Returns 0 to indicate success. Otherwise an kerberos et 834 * error code is returned, see krb5_get_error_message(). 835 * 836 * @ingroup krb5 837 */ 838 839 KRB5_LIB_FUNCTION void KRB5_LIB_CALL 840 krb5_free_config_files(char **filenames) 841 { 842 char **p; 843 for(p = filenames; p && *p != NULL; p++) 844 free(*p); 845 free(filenames); 846 } 847 848 /** 849 * Returns the list of Kerberos encryption types sorted in order of 850 * most preferred to least preferred encryption type. Note that some 851 * encryption types might be disabled, so you need to check with 852 * krb5_enctype_valid() before using the encryption type. 853 * 854 * @return list of enctypes, terminated with ETYPE_NULL. Its a static 855 * array completed into the Kerberos library so the content doesn't 856 * need to be freed. 857 * 858 * @ingroup krb5 859 */ 860 861 KRB5_LIB_FUNCTION const krb5_enctype * KRB5_LIB_CALL 862 krb5_kerberos_enctypes(krb5_context context) 863 { 864 static const krb5_enctype p[] = { 865 ETYPE_AES256_CTS_HMAC_SHA1_96, 866 ETYPE_AES128_CTS_HMAC_SHA1_96, 867 ETYPE_DES3_CBC_SHA1, 868 ETYPE_DES3_CBC_MD5, 869 ETYPE_ARCFOUR_HMAC_MD5, 870 ETYPE_DES_CBC_MD5, 871 ETYPE_DES_CBC_MD4, 872 ETYPE_DES_CBC_CRC, 873 ETYPE_NULL 874 }; 875 return p; 876 } 877 878 /* 879 * set `etype' to a malloced list of the default enctypes 880 */ 881 882 static krb5_error_code 883 default_etypes(krb5_context context, krb5_enctype **etype) 884 { 885 const krb5_enctype *p; 886 krb5_enctype *e = NULL, *ep; 887 int i, n = 0; 888 889 p = krb5_kerberos_enctypes(context); 890 891 for (i = 0; p[i] != ETYPE_NULL; i++) { 892 if (krb5_enctype_valid(context, p[i]) != 0) 893 continue; 894 ep = realloc(e, (n + 2) * sizeof(*e)); 895 if (ep == NULL) { 896 free(e); 897 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", "")); 898 return ENOMEM; 899 } 900 e = ep; 901 e[n] = p[i]; 902 e[n + 1] = ETYPE_NULL; 903 n++; 904 } 905 *etype = e; 906 return 0; 907 } 908 909 /** 910 * Set the default encryption types that will be use in communcation 911 * with the KDC, clients and servers. 912 * 913 * @param context Kerberos 5 context. 914 * @param etypes Encryption types, array terminated with ETYPE_NULL (0). 915 * 916 * @return Returns 0 to indicate success. Otherwise an kerberos et 917 * error code is returned, see krb5_get_error_message(). 918 * 919 * @ingroup krb5 920 */ 921 922 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 923 krb5_set_default_in_tkt_etypes(krb5_context context, 924 const krb5_enctype *etypes) 925 { 926 krb5_error_code ret; 927 krb5_enctype *p = NULL; 928 unsigned int n, m; 929 930 if(etypes) { 931 for (n = 0; etypes[n]; n++) 932 ; 933 n++; 934 ALLOC(p, n); 935 if(!p) { 936 krb5_set_error_message (context, ENOMEM, 937 N_("malloc: out of memory", "")); 938 return ENOMEM; 939 } 940 for (n = 0, m = 0; etypes[n]; n++) { 941 ret = krb5_enctype_valid(context, etypes[n]); 942 if (ret) 943 continue; 944 p[m++] = etypes[n]; 945 } 946 p[m] = ETYPE_NULL; 947 if (m == 0) { 948 free(p); 949 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, 950 N_("no valid enctype set", "")); 951 return KRB5_PROG_ETYPE_NOSUPP; 952 } 953 } 954 if(context->etypes) 955 free(context->etypes); 956 context->etypes = p; 957 return 0; 958 } 959 960 /** 961 * Get the default encryption types that will be use in communcation 962 * with the KDC, clients and servers. 963 * 964 * @param context Kerberos 5 context. 965 * @param etypes Encryption types, array terminated with 966 * ETYPE_NULL(0), caller should free array with krb5_xfree(): 967 * 968 * @return Returns 0 to indicate success. Otherwise an kerberos et 969 * error code is returned, see krb5_get_error_message(). 970 * 971 * @ingroup krb5 972 */ 973 974 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 975 krb5_get_default_in_tkt_etypes(krb5_context context, 976 krb5_enctype **etypes) 977 { 978 krb5_enctype *p; 979 int i; 980 krb5_error_code ret; 981 982 if(context->etypes) { 983 for(i = 0; context->etypes[i]; i++); 984 ++i; 985 ALLOC(p, i); 986 if(!p) { 987 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", "")); 988 return ENOMEM; 989 } 990 memmove(p, context->etypes, i * sizeof(krb5_enctype)); 991 } else { 992 ret = default_etypes(context, &p); 993 if (ret) 994 return ret; 995 } 996 *etypes = p; 997 return 0; 998 } 999 1000 /** 1001 * Init the built-in ets in the Kerberos library. 1002 * 1003 * @param context kerberos context to add the ets too 1004 * 1005 * @ingroup krb5 1006 */ 1007 1008 KRB5_LIB_FUNCTION void KRB5_LIB_CALL 1009 krb5_init_ets(krb5_context context) 1010 { 1011 if(context->et_list == NULL){ 1012 krb5_add_et_list(context, initialize_krb5_error_table_r); 1013 krb5_add_et_list(context, initialize_asn1_error_table_r); 1014 krb5_add_et_list(context, initialize_heim_error_table_r); 1015 1016 krb5_add_et_list(context, initialize_k524_error_table_r); 1017 1018 #ifdef COM_ERR_BINDDOMAIN_krb5 1019 bindtextdomain(COM_ERR_BINDDOMAIN_krb5, HEIMDAL_LOCALEDIR); 1020 bindtextdomain(COM_ERR_BINDDOMAIN_asn1, HEIMDAL_LOCALEDIR); 1021 bindtextdomain(COM_ERR_BINDDOMAIN_heim, HEIMDAL_LOCALEDIR); 1022 bindtextdomain(COM_ERR_BINDDOMAIN_k524, HEIMDAL_LOCALEDIR); 1023 #endif 1024 1025 #ifdef PKINIT 1026 krb5_add_et_list(context, initialize_hx_error_table_r); 1027 #ifdef COM_ERR_BINDDOMAIN_hx 1028 bindtextdomain(COM_ERR_BINDDOMAIN_hx, HEIMDAL_LOCALEDIR); 1029 #endif 1030 #endif 1031 } 1032 } 1033 1034 /** 1035 * Make the kerberos library default to the admin KDC. 1036 * 1037 * @param context Kerberos 5 context. 1038 * @param flag boolean flag to select if the use the admin KDC or not. 1039 * 1040 * @ingroup krb5 1041 */ 1042 1043 KRB5_LIB_FUNCTION void KRB5_LIB_CALL 1044 krb5_set_use_admin_kdc (krb5_context context, krb5_boolean flag) 1045 { 1046 context->use_admin_kdc = flag; 1047 } 1048 1049 /** 1050 * Make the kerberos library default to the admin KDC. 1051 * 1052 * @param context Kerberos 5 context. 1053 * 1054 * @return boolean flag to telling the context will use admin KDC as the default KDC. 1055 * 1056 * @ingroup krb5 1057 */ 1058 1059 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL 1060 krb5_get_use_admin_kdc (krb5_context context) 1061 { 1062 return context->use_admin_kdc; 1063 } 1064 1065 /** 1066 * Add extra address to the address list that the library will add to 1067 * the client's address list when communicating with the KDC. 1068 * 1069 * @param context Kerberos 5 context. 1070 * @param addresses addreses to add 1071 * 1072 * @return Returns 0 to indicate success. Otherwise an kerberos et 1073 * error code is returned, see krb5_get_error_message(). 1074 * 1075 * @ingroup krb5 1076 */ 1077 1078 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1079 krb5_add_extra_addresses(krb5_context context, krb5_addresses *addresses) 1080 { 1081 1082 if(context->extra_addresses) 1083 return krb5_append_addresses(context, 1084 context->extra_addresses, addresses); 1085 else 1086 return krb5_set_extra_addresses(context, addresses); 1087 } 1088 1089 /** 1090 * Set extra address to the address list that the library will add to 1091 * the client's address list when communicating with the KDC. 1092 * 1093 * @param context Kerberos 5 context. 1094 * @param addresses addreses to set 1095 * 1096 * @return Returns 0 to indicate success. Otherwise an kerberos et 1097 * error code is returned, see krb5_get_error_message(). 1098 * 1099 * @ingroup krb5 1100 */ 1101 1102 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1103 krb5_set_extra_addresses(krb5_context context, const krb5_addresses *addresses) 1104 { 1105 if(context->extra_addresses) 1106 krb5_free_addresses(context, context->extra_addresses); 1107 1108 if(addresses == NULL) { 1109 if(context->extra_addresses != NULL) { 1110 free(context->extra_addresses); 1111 context->extra_addresses = NULL; 1112 } 1113 return 0; 1114 } 1115 if(context->extra_addresses == NULL) { 1116 context->extra_addresses = malloc(sizeof(*context->extra_addresses)); 1117 if(context->extra_addresses == NULL) { 1118 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", "")); 1119 return ENOMEM; 1120 } 1121 } 1122 return krb5_copy_addresses(context, addresses, context->extra_addresses); 1123 } 1124 1125 /** 1126 * Get extra address to the address list that the library will add to 1127 * the client's address list when communicating with the KDC. 1128 * 1129 * @param context Kerberos 5 context. 1130 * @param addresses addreses to set 1131 * 1132 * @return Returns 0 to indicate success. Otherwise an kerberos et 1133 * error code is returned, see krb5_get_error_message(). 1134 * 1135 * @ingroup krb5 1136 */ 1137 1138 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1139 krb5_get_extra_addresses(krb5_context context, krb5_addresses *addresses) 1140 { 1141 if(context->extra_addresses == NULL) { 1142 memset(addresses, 0, sizeof(*addresses)); 1143 return 0; 1144 } 1145 return krb5_copy_addresses(context,context->extra_addresses, addresses); 1146 } 1147 1148 /** 1149 * Add extra addresses to ignore when fetching addresses from the 1150 * underlaying operating system. 1151 * 1152 * @param context Kerberos 5 context. 1153 * @param addresses addreses to ignore 1154 * 1155 * @return Returns 0 to indicate success. Otherwise an kerberos et 1156 * error code is returned, see krb5_get_error_message(). 1157 * 1158 * @ingroup krb5 1159 */ 1160 1161 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1162 krb5_add_ignore_addresses(krb5_context context, krb5_addresses *addresses) 1163 { 1164 1165 if(context->ignore_addresses) 1166 return krb5_append_addresses(context, 1167 context->ignore_addresses, addresses); 1168 else 1169 return krb5_set_ignore_addresses(context, addresses); 1170 } 1171 1172 /** 1173 * Set extra addresses to ignore when fetching addresses from the 1174 * underlaying operating system. 1175 * 1176 * @param context Kerberos 5 context. 1177 * @param addresses addreses to ignore 1178 * 1179 * @return Returns 0 to indicate success. Otherwise an kerberos et 1180 * error code is returned, see krb5_get_error_message(). 1181 * 1182 * @ingroup krb5 1183 */ 1184 1185 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1186 krb5_set_ignore_addresses(krb5_context context, const krb5_addresses *addresses) 1187 { 1188 if(context->ignore_addresses) 1189 krb5_free_addresses(context, context->ignore_addresses); 1190 if(addresses == NULL) { 1191 if(context->ignore_addresses != NULL) { 1192 free(context->ignore_addresses); 1193 context->ignore_addresses = NULL; 1194 } 1195 return 0; 1196 } 1197 if(context->ignore_addresses == NULL) { 1198 context->ignore_addresses = malloc(sizeof(*context->ignore_addresses)); 1199 if(context->ignore_addresses == NULL) { 1200 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", "")); 1201 return ENOMEM; 1202 } 1203 } 1204 return krb5_copy_addresses(context, addresses, context->ignore_addresses); 1205 } 1206 1207 /** 1208 * Get extra addresses to ignore when fetching addresses from the 1209 * underlaying operating system. 1210 * 1211 * @param context Kerberos 5 context. 1212 * @param addresses list addreses ignored 1213 * 1214 * @return Returns 0 to indicate success. Otherwise an kerberos et 1215 * error code is returned, see krb5_get_error_message(). 1216 * 1217 * @ingroup krb5 1218 */ 1219 1220 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1221 krb5_get_ignore_addresses(krb5_context context, krb5_addresses *addresses) 1222 { 1223 if(context->ignore_addresses == NULL) { 1224 memset(addresses, 0, sizeof(*addresses)); 1225 return 0; 1226 } 1227 return krb5_copy_addresses(context, context->ignore_addresses, addresses); 1228 } 1229 1230 /** 1231 * Set version of fcache that the library should use. 1232 * 1233 * @param context Kerberos 5 context. 1234 * @param version version number. 1235 * 1236 * @return Returns 0 to indicate success. Otherwise an kerberos et 1237 * error code is returned, see krb5_get_error_message(). 1238 * 1239 * @ingroup krb5 1240 */ 1241 1242 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1243 krb5_set_fcache_version(krb5_context context, int version) 1244 { 1245 context->fcache_vno = version; 1246 return 0; 1247 } 1248 1249 /** 1250 * Get version of fcache that the library should use. 1251 * 1252 * @param context Kerberos 5 context. 1253 * @param version version number. 1254 * 1255 * @return Returns 0 to indicate success. Otherwise an kerberos et 1256 * error code is returned, see krb5_get_error_message(). 1257 * 1258 * @ingroup krb5 1259 */ 1260 1261 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1262 krb5_get_fcache_version(krb5_context context, int *version) 1263 { 1264 *version = context->fcache_vno; 1265 return 0; 1266 } 1267 1268 /** 1269 * Runtime check if the Kerberos library was complied with thread support. 1270 * 1271 * @return TRUE if the library was compiled with thread support, FALSE if not. 1272 * 1273 * @ingroup krb5 1274 */ 1275 1276 1277 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL 1278 krb5_is_thread_safe(void) 1279 { 1280 #ifdef ENABLE_PTHREAD_SUPPORT 1281 return TRUE; 1282 #else 1283 return FALSE; 1284 #endif 1285 } 1286 1287 /** 1288 * Set if the library should use DNS to canonicalize hostnames. 1289 * 1290 * @param context Kerberos 5 context. 1291 * @param flag if its dns canonicalizion is used or not. 1292 * 1293 * @ingroup krb5 1294 */ 1295 1296 KRB5_LIB_FUNCTION void KRB5_LIB_CALL 1297 krb5_set_dns_canonicalize_hostname (krb5_context context, krb5_boolean flag) 1298 { 1299 if (flag) 1300 context->flags |= KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME; 1301 else 1302 context->flags &= ~KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME; 1303 } 1304 1305 /** 1306 * Get if the library uses DNS to canonicalize hostnames. 1307 * 1308 * @param context Kerberos 5 context. 1309 * 1310 * @return return non zero if the library uses DNS to canonicalize hostnames. 1311 * 1312 * @ingroup krb5 1313 */ 1314 1315 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL 1316 krb5_get_dns_canonicalize_hostname (krb5_context context) 1317 { 1318 return (context->flags & KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME) ? 1 : 0; 1319 } 1320 1321 /** 1322 * Get current offset in time to the KDC. 1323 * 1324 * @param context Kerberos 5 context. 1325 * @param sec seconds part of offset. 1326 * @param usec micro seconds part of offset. 1327 * 1328 * @return returns zero 1329 * 1330 * @ingroup krb5 1331 */ 1332 1333 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1334 krb5_get_kdc_sec_offset (krb5_context context, int32_t *sec, int32_t *usec) 1335 { 1336 if (sec) 1337 *sec = context->kdc_sec_offset; 1338 if (usec) 1339 *usec = context->kdc_usec_offset; 1340 return 0; 1341 } 1342 1343 /** 1344 * Set current offset in time to the KDC. 1345 * 1346 * @param context Kerberos 5 context. 1347 * @param sec seconds part of offset. 1348 * @param usec micro seconds part of offset. 1349 * 1350 * @return returns zero 1351 * 1352 * @ingroup krb5 1353 */ 1354 1355 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1356 krb5_set_kdc_sec_offset (krb5_context context, int32_t sec, int32_t usec) 1357 { 1358 context->kdc_sec_offset = sec; 1359 if (usec >= 0) 1360 context->kdc_usec_offset = usec; 1361 return 0; 1362 } 1363 1364 /** 1365 * Get max time skew allowed. 1366 * 1367 * @param context Kerberos 5 context. 1368 * 1369 * @return timeskew in seconds. 1370 * 1371 * @ingroup krb5 1372 */ 1373 1374 KRB5_LIB_FUNCTION time_t KRB5_LIB_CALL 1375 krb5_get_max_time_skew (krb5_context context) 1376 { 1377 return context->max_skew; 1378 } 1379 1380 /** 1381 * Set max time skew allowed. 1382 * 1383 * @param context Kerberos 5 context. 1384 * @param t timeskew in seconds. 1385 * 1386 * @ingroup krb5 1387 */ 1388 1389 KRB5_LIB_FUNCTION void KRB5_LIB_CALL 1390 krb5_set_max_time_skew (krb5_context context, time_t t) 1391 { 1392 context->max_skew = t; 1393 } 1394 1395 /** 1396 * Init encryption types in len, val with etypes. 1397 * 1398 * @param context Kerberos 5 context. 1399 * @param len output length of val. 1400 * @param val output array of enctypes. 1401 * @param etypes etypes to set val and len to, if NULL, use default enctypes. 1402 1403 * @return Returns 0 to indicate success. Otherwise an kerberos et 1404 * error code is returned, see krb5_get_error_message(). 1405 * 1406 * @ingroup krb5 1407 */ 1408 1409 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1410 krb5_init_etype (krb5_context context, 1411 unsigned *len, 1412 krb5_enctype **val, 1413 const krb5_enctype *etypes) 1414 { 1415 unsigned int i; 1416 krb5_error_code ret; 1417 krb5_enctype *tmp = NULL; 1418 1419 ret = 0; 1420 if (etypes == NULL) { 1421 ret = krb5_get_default_in_tkt_etypes(context, &tmp); 1422 if (ret) 1423 return ret; 1424 etypes = tmp; 1425 } 1426 1427 for (i = 0; etypes[i]; ++i) 1428 ; 1429 *len = i; 1430 *val = malloc(i * sizeof(**val)); 1431 if (i != 0 && *val == NULL) { 1432 ret = ENOMEM; 1433 krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); 1434 goto cleanup; 1435 } 1436 memmove (*val, 1437 etypes, 1438 i * sizeof(*tmp)); 1439 cleanup: 1440 if (tmp != NULL) 1441 free (tmp); 1442 return ret; 1443 } 1444 1445 /* 1446 * Allow homedir accces 1447 */ 1448 1449 static HEIMDAL_MUTEX homedir_mutex = HEIMDAL_MUTEX_INITIALIZER; 1450 static krb5_boolean allow_homedir = TRUE; 1451 1452 krb5_boolean 1453 _krb5_homedir_access(krb5_context context) 1454 { 1455 krb5_boolean allow; 1456 1457 #ifdef HAVE_GETEUID 1458 /* is never allowed for root */ 1459 if (geteuid() == 0) 1460 return FALSE; 1461 #endif 1462 1463 if (context && (context->flags & KRB5_CTX_F_HOMEDIR_ACCESS) == 0) 1464 return FALSE; 1465 1466 HEIMDAL_MUTEX_lock(&homedir_mutex); 1467 allow = allow_homedir; 1468 HEIMDAL_MUTEX_unlock(&homedir_mutex); 1469 return allow; 1470 } 1471 1472 /** 1473 * Enable and disable home directory access on either the global state 1474 * or the krb5_context state. By calling krb5_set_home_dir_access() 1475 * with context set to NULL, the global state is configured otherwise 1476 * the state for the krb5_context is modified. 1477 * 1478 * For home directory access to be allowed, both the global state and 1479 * the krb5_context state have to be allowed. 1480 * 1481 * Administrator (root user), never uses the home directory. 1482 * 1483 * @param context a Kerberos 5 context or NULL 1484 * @param allow allow if TRUE home directory 1485 * @return the old value 1486 * 1487 * @ingroup krb5 1488 */ 1489 1490 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL 1491 krb5_set_home_dir_access(krb5_context context, krb5_boolean allow) 1492 { 1493 krb5_boolean old; 1494 if (context) { 1495 old = (context->flags & KRB5_CTX_F_HOMEDIR_ACCESS) ? TRUE : FALSE; 1496 if (allow) 1497 context->flags |= KRB5_CTX_F_HOMEDIR_ACCESS; 1498 else 1499 context->flags &= ~KRB5_CTX_F_HOMEDIR_ACCESS; 1500 } else { 1501 HEIMDAL_MUTEX_lock(&homedir_mutex); 1502 old = allow_homedir; 1503 allow_homedir = allow; 1504 HEIMDAL_MUTEX_unlock(&homedir_mutex); 1505 } 1506 1507 return old; 1508 } 1509