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