1192468Ssam/* $NetBSD: context.c,v 1.8 2023/09/11 15:12:12 christos Exp $ */ 2192468Ssam 3192468Ssam/* 4192468Ssam * Copyright (c) 1997 - 2010 Kungliga Tekniska H��gskolan 5192468Ssam * (Royal Institute of Technology, Stockholm, Sweden). 6192468Ssam * All rights reserved. 7192468Ssam * 8192468Ssam * Portions Copyright (c) 2009 Apple Inc. All rights reserved. 9192468Ssam * 10192468Ssam * Redistribution and use in source and binary forms, with or without 11192468Ssam * modification, are permitted provided that the following conditions 12192468Ssam * are met: 13192468Ssam * 14192468Ssam * 1. Redistributions of source code must retain the above copyright 15192468Ssam * notice, this list of conditions and the following disclaimer. 16192468Ssam * 17192468Ssam * 2. Redistributions in binary form must reproduce the above copyright 18192468Ssam * notice, this list of conditions and the following disclaimer in the 19192468Ssam * documentation and/or other materials provided with the distribution. 20192468Ssam * 21192468Ssam * 3. Neither the name of the Institute nor the names of its contributors 22192468Ssam * may be used to endorse or promote products derived from this software 23192468Ssam * without specific prior written permission. 24192468Ssam * 25192468Ssam * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 26192468Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27192468Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28192468Ssam * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 29192468Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30192468Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31192468Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32192468Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33192468Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34192468Ssam * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35192468Ssam * SUCH DAMAGE. 36192468Ssam */ 37192468Ssam 38192468Ssam#include "krb5_locl.h" 39192468Ssam#include <assert.h> 40192468Ssam#include <krb5/com_err.h> 41192468Ssam#if OPENSSL_VERSION_NUMBER >= 0x30000000UL 42192468Ssam#include <openssl/provider.h> 43192468Ssam#endif 44192468Ssam 45192468Ssam#define INIT_FIELD(C, T, E, D, F) \ 46192468Ssam (C)->E = krb5_config_get_ ## T ## _default ((C), NULL, (D), \ 47192468Ssam "libdefaults", F, NULL) 48192468Ssam 49192468Ssam#define INIT_FLAG(C, O, V, D, F) \ 50237214Sadrian do { \ 51192468Ssam if (krb5_config_get_bool_default((C), NULL, (D),"libdefaults", F, NULL)) { \ 52192468Ssam (C)->O |= V; \ 53192468Ssam } \ 54192468Ssam } while(0) 55192468Ssam 56192468Ssamstatic krb5_error_code 57237214Sadriancopy_enctypes(krb5_context context, 58237214Sadrian const krb5_enctype *in, 59237214Sadrian krb5_enctype **out); 60237214Sadrian 61237214Sadrian/* 62237214Sadrian * Set the list of etypes `ret_etypes' from the configuration variable 63237214Sadrian * `name' 64237214Sadrian */ 65237214Sadrian 66237214Sadrianstatic krb5_error_code 67237214Sadrianset_etypes (krb5_context context, 68192468Ssam const char *name, 69192468Ssam krb5_enctype **ret_enctypes) 70192468Ssam{ 71192468Ssam char **etypes_str; 72192468Ssam krb5_enctype *etypes = NULL; 73192468Ssam 74192468Ssam etypes_str = krb5_config_get_strings(context, NULL, "libdefaults", 75192468Ssam name, NULL); 76192468Ssam if(etypes_str){ 77237214Sadrian int i, j, k; 78192468Ssam for(i = 0; etypes_str[i]; i++); 79237214Sadrian etypes = malloc((i+1) * sizeof(*etypes)); 80192468Ssam if (etypes == NULL) { 81232705Sadrian krb5_config_free_strings (etypes_str); 82192468Ssam return krb5_enomem(context); 83192468Ssam } 84192468Ssam for(j = 0, k = 0; j < i; j++) { 85192468Ssam krb5_enctype e; 86192468Ssam if(krb5_string_to_enctype(context, etypes_str[j], &e) != 0) 87192468Ssam continue; 88192468Ssam if (krb5_enctype_valid(context, e) != 0) 89192468Ssam continue; 90192468Ssam etypes[k++] = e; 91192468Ssam } 92192468Ssam etypes[k] = ETYPE_NULL; 93237214Sadrian krb5_config_free_strings(etypes_str); 94192468Ssam } 95237214Sadrian *ret_enctypes = etypes; 96192468Ssam return 0; 97232705Sadrian} 98192468Ssam 99192468Ssam/* 100192468Ssam * read variables from the configuration file and set in `context' 101192468Ssam */ 102192468Ssam 103192468Ssamstatic krb5_error_code 104192468Ssaminit_context_from_config_file(krb5_context context) 105192468Ssam{ 106192468Ssam krb5_error_code ret; 107192468Ssam const char * tmp; 108192468Ssam char **s; 109192468Ssam krb5_enctype *tmptypes = NULL; 110192468Ssam 111192468Ssam INIT_FIELD(context, time, max_skew, 5 * 60, "clockskew"); 112192468Ssam INIT_FIELD(context, time, kdc_timeout, 30, "kdc_timeout"); 113192468Ssam INIT_FIELD(context, time, host_timeout, 3, "host_timeout"); 114192468Ssam INIT_FIELD(context, int, max_retries, 3, "max_retries"); 115192468Ssam 116192765Ssam INIT_FIELD(context, string, http_proxy, NULL, "http_proxy"); 117192765Ssam 118192765Ssam ret = krb5_config_get_bool_default(context, NULL, FALSE, 119192765Ssam "libdefaults", 120192765Ssam "allow_weak_crypto", NULL); 121192765Ssam if (ret) { 122192468Ssam krb5_enctype_enable(context, ETYPE_DES_CBC_CRC); 123192468Ssam krb5_enctype_enable(context, ETYPE_DES_CBC_MD4); 124192468Ssam krb5_enctype_enable(context, ETYPE_DES_CBC_MD5); 125192468Ssam krb5_enctype_enable(context, ETYPE_DES_CBC_NONE); 126192468Ssam krb5_enctype_enable(context, ETYPE_DES_CFB64_NONE); 127192468Ssam krb5_enctype_enable(context, ETYPE_DES_PCBC_NONE); 128192468Ssam } 129192468Ssam 130192468Ssam ret = set_etypes (context, "default_etypes", &tmptypes); 131192468Ssam if(ret) 132192468Ssam return ret; 133192468Ssam free(context->etypes); 134192468Ssam context->etypes = tmptypes; 135192468Ssam 136192468Ssam /* The etypes member may change during the lifetime 137192468Ssam * of the context. To be able to reset it to 138192468Ssam * config value, we keep another copy. 139192468Ssam */ 140192468Ssam free(context->cfg_etypes); 141192468Ssam context->cfg_etypes = NULL; 142192468Ssam if (tmptypes) { 143192468Ssam ret = copy_enctypes(context, tmptypes, &context->cfg_etypes); 144192468Ssam if (ret) 145192468Ssam return ret; 146192468Ssam } 147192468Ssam 148192468Ssam ret = set_etypes (context, "default_etypes_des", &tmptypes); 149192468Ssam if(ret) 150192468Ssam return ret; 151192468Ssam free(context->etypes_des); 152192468Ssam context->etypes_des = tmptypes; 153192468Ssam 154192468Ssam ret = set_etypes (context, "default_as_etypes", &tmptypes); 155192468Ssam if(ret) 156192468Ssam return ret; 157192468Ssam free(context->as_etypes); 158192468Ssam context->as_etypes = tmptypes; 159192468Ssam 160192468Ssam ret = set_etypes (context, "default_tgs_etypes", &tmptypes); 161192468Ssam if(ret) 162192468Ssam return ret; 163192468Ssam free(context->tgs_etypes); 164192468Ssam context->tgs_etypes = tmptypes; 165192468Ssam 166192468Ssam ret = set_etypes (context, "permitted_enctypes", &tmptypes); 167193760Ssam if(ret) 168192468Ssam return ret; 169193760Ssam free(context->permitted_enctypes); 170192468Ssam context->permitted_enctypes = tmptypes; 171192468Ssam 172192468Ssam INIT_FIELD(context, string, default_keytab, 173192468Ssam KEYTAB_DEFAULT, "default_keytab_name"); 174192468Ssam 175193760Ssam INIT_FIELD(context, string, default_keytab_modify, 176192468Ssam NULL, "default_keytab_modify_name"); 177193760Ssam 178192468Ssam INIT_FIELD(context, string, time_fmt, 179192468Ssam "%Y-%m-%dT%H:%M:%S", "time_format"); 180192468Ssam 181192468Ssam INIT_FIELD(context, string, date_fmt, 182192468Ssam "%Y-%m-%d", "date_format"); 183193292Ssam 184193292Ssam INIT_FIELD(context, bool, log_utc, 185193292Ssam FALSE, "log_utc"); 186193292Ssam 187193292Ssam 188193292Ssam 189193292Ssam /* init dns-proxy slime */ 190193292Ssam tmp = krb5_config_get_string(context, NULL, "libdefaults", 191193292Ssam "dns_proxy", NULL); 192193292Ssam if(tmp) 193193292Ssam roken_gethostby_setup(context->http_proxy, tmp); 194193292Ssam krb5_free_host_realm (context, context->default_realms); 195193292Ssam context->default_realms = NULL; 196193292Ssam 197193292Ssam { 198193292Ssam krb5_addresses addresses; 199193292Ssam char **adr, **a; 200193292Ssam 201193292Ssam krb5_set_extra_addresses(context, NULL); 202193292Ssam adr = krb5_config_get_strings(context, NULL, 203192468Ssam "libdefaults", 204192468Ssam "extra_addresses", 205192468Ssam NULL); 206192468Ssam memset(&addresses, 0, sizeof(addresses)); 207192468Ssam for(a = adr; a && *a; a++) { 208193292Ssam ret = krb5_parse_address(context, *a, &addresses); 209193292Ssam if (ret == 0) { 210193292Ssam krb5_add_extra_addresses(context, &addresses); 211193292Ssam krb5_free_addresses(context, &addresses); 212193292Ssam } 213193292Ssam } 214193292Ssam krb5_config_free_strings(adr); 215193292Ssam 216193292Ssam krb5_set_ignore_addresses(context, NULL); 217193292Ssam adr = krb5_config_get_strings(context, NULL, 218193292Ssam "libdefaults", 219193292Ssam "ignore_addresses", 220193292Ssam NULL); 221193292Ssam memset(&addresses, 0, sizeof(addresses)); 222192468Ssam for(a = adr; a && *a; a++) { 223192468Ssam ret = krb5_parse_address(context, *a, &addresses); 224192468Ssam if (ret == 0) { 225192468Ssam krb5_add_ignore_addresses(context, &addresses); 226192468Ssam krb5_free_addresses(context, &addresses); 227192468Ssam } 228192468Ssam } 229192468Ssam krb5_config_free_strings(adr); 230193292Ssam } 231193292Ssam 232193292Ssam INIT_FIELD(context, bool, scan_interfaces, TRUE, "scan_interfaces"); 233193292Ssam INIT_FIELD(context, int, fcache_vno, 0, "fcache_version"); 234193292Ssam /* prefer dns_lookup_kdc over srv_lookup. */ 235193292Ssam INIT_FIELD(context, bool, srv_lookup, TRUE, "srv_lookup"); 236193292Ssam INIT_FIELD(context, bool, srv_lookup, context->srv_lookup, "dns_lookup_kdc"); 237193292Ssam INIT_FIELD(context, int, large_msg_size, 1400, "large_message_size"); 238193292Ssam INIT_FIELD(context, int, max_msg_size, 1000 * 1024, "maximum_message_size"); 239193292Ssam INIT_FLAG(context, flags, KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME, TRUE, "dns_canonicalize_hostname"); 240193292Ssam INIT_FLAG(context, flags, KRB5_CTX_F_CHECK_PAC, TRUE, "check_pac"); 241193292Ssam 242193292Ssam if (context->default_cc_name) 243193292Ssam free(context->default_cc_name); 244193292Ssam context->default_cc_name = NULL; 245193292Ssam context->default_cc_name_set = 0; 246192468Ssam 247192468Ssam s = krb5_config_get_strings(context, NULL, "logging", "krb5", NULL); 248192468Ssam if(s) { 249192468Ssam char **p; 250192468Ssam 251192468Ssam if (context->debug_dest) 252192468Ssam krb5_closelog(context, context->debug_dest); 253192468Ssam 254192468Ssam krb5_initlog(context, "libkrb5", &context->debug_dest); 255192468Ssam for(p = s; *p; p++) 256192468Ssam krb5_addlog_dest(context, context->debug_dest, *p); 257192468Ssam krb5_config_free_strings(s); 258192468Ssam } 259192468Ssam 260192468Ssam tmp = krb5_config_get_string(context, NULL, "libdefaults", 261192468Ssam "check-rd-req-server", NULL); 262193292Ssam if (tmp == NULL && !issuid()) 263193292Ssam tmp = getenv("KRB5_CHECK_RD_REQ_SERVER"); 264192468Ssam if(tmp) { 265192468Ssam if (strcasecmp(tmp, "ignore") == 0) 266192468Ssam context->flags |= KRB5_CTX_F_RD_REQ_IGNORE; 267192468Ssam } 268192468Ssam ret = krb5_config_get_bool_default(context, NULL, TRUE, 269192468Ssam "libdefaults", 270192468Ssam "fcache_strict_checking", NULL); 271192468Ssam if (ret) 272192468Ssam context->flags |= KRB5_CTX_F_FCACHE_STRICT_CHECKING; 273192468Ssam 274237214Sadrian return 0; 275237214Sadrian} 276192468Ssam 277192468Ssamstatic krb5_error_code 278192468Ssamcc_ops_register(krb5_context context) 279192468Ssam{ 280192468Ssam context->cc_ops = NULL; 281192468Ssam context->num_cc_ops = 0; 282192468Ssam 283192468Ssam#ifndef KCM_IS_API_CACHE 284192468Ssam krb5_cc_register(context, &krb5_acc_ops, TRUE); 285192468Ssam#endif 286192468Ssam krb5_cc_register(context, &krb5_fcc_ops, TRUE); 287192468Ssam krb5_cc_register(context, &krb5_dcc_ops, TRUE); 288192468Ssam krb5_cc_register(context, &krb5_mcc_ops, TRUE); 289192468Ssam#ifdef HAVE_SCC 290192468Ssam krb5_cc_register(context, &krb5_scc_ops, TRUE); 291192468Ssam#endif 292192468Ssam#ifdef HAVE_KCM 293192468Ssam#ifdef KCM_IS_API_CACHE 294192468Ssam krb5_cc_register(context, &krb5_akcm_ops, TRUE); 295192468Ssam#endif 296192468Ssam krb5_cc_register(context, &krb5_kcm_ops, TRUE); 297192468Ssam#endif 298192468Ssam _krb5_load_ccache_plugins(context); 299192468Ssam return 0; 300192468Ssam} 301192468Ssam 302192468Ssamstatic krb5_error_code 303192468Ssamcc_ops_copy(krb5_context context, const krb5_context src_context) 304192468Ssam{ 305192468Ssam const krb5_cc_ops **cc_ops; 306192468Ssam 307192468Ssam context->cc_ops = NULL; 308192468Ssam context->num_cc_ops = 0; 309192468Ssam 310192468Ssam if (src_context->num_cc_ops == 0) 311192468Ssam return 0; 312192468Ssam 313192468Ssam cc_ops = malloc(sizeof(cc_ops[0]) * src_context->num_cc_ops); 314192468Ssam if (cc_ops == NULL) { 315192468Ssam krb5_set_error_message(context, KRB5_CC_NOMEM, 316192468Ssam N_("malloc: out of memory", "")); 317192468Ssam return KRB5_CC_NOMEM; 318192468Ssam } 319192468Ssam 320192468Ssam memcpy(rk_UNCONST(cc_ops), src_context->cc_ops, 321192468Ssam sizeof(cc_ops[0]) * src_context->num_cc_ops); 322192468Ssam context->cc_ops = cc_ops; 323192468Ssam context->num_cc_ops = src_context->num_cc_ops; 324192468Ssam 325192468Ssam return 0; 326192468Ssam} 327192468Ssam 328192468Ssamstatic krb5_error_code 329192468Ssamkt_ops_register(krb5_context context) 330192468Ssam{ 331192468Ssam context->num_kt_types = 0; 332192468Ssam context->kt_types = NULL; 333192468Ssam 334192468Ssam krb5_kt_register (context, &krb5_fkt_ops); 335192468Ssam krb5_kt_register (context, &krb5_wrfkt_ops); 336192468Ssam krb5_kt_register (context, &krb5_javakt_ops); 337192468Ssam krb5_kt_register (context, &krb5_mkt_ops); 338192468Ssam#ifndef HEIMDAL_SMALLER 339192468Ssam krb5_kt_register (context, &krb5_akf_ops); 340229952Sadrian#endif 341229952Sadrian krb5_kt_register (context, &krb5_any_ops); 342229952Sadrian return 0; 343229952Sadrian} 344192468Ssam 345192468Ssamstatic krb5_error_code 346192468Ssamkt_ops_copy(krb5_context context, const krb5_context src_context) 347192468Ssam{ 348192468Ssam context->num_kt_types = 0; 349237214Sadrian context->kt_types = NULL; 350237214Sadrian 351192468Ssam if (src_context->num_kt_types == 0) 352192468Ssam return 0; 353192468Ssam 354192468Ssam context->kt_types = malloc(sizeof(context->kt_types[0]) * src_context->num_kt_types); 355192468Ssam if (context->kt_types == NULL) 356192468Ssam return krb5_enomem(context); 357192468Ssam 358192468Ssam context->num_kt_types = src_context->num_kt_types; 359192468Ssam memcpy(context->kt_types, src_context->kt_types, 360192468Ssam sizeof(context->kt_types[0]) * src_context->num_kt_types); 361192468Ssam 362192468Ssam return 0; 363192468Ssam} 364192468Ssam 365192468Ssamstatic const char *sysplugin_dirs[] = { 366192468Ssam#ifdef _WIN32 367192468Ssam "$ORIGIN", 368192468Ssam#else 369192468Ssam "$ORIGIN/../lib/plugin/krb5", 370192468Ssam#endif 371192468Ssam#ifdef __APPLE__ 372192468Ssam LIBDIR "/plugin/krb5", 373192468Ssam#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