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