root/source4/heimdal/lib/krb5/context.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. set_etypes
  2. copy_etypes
  3. init_context_from_config_file
  4. cc_ops_register
  5. kt_ops_register
  6. krb5_init_context
  7. krb5_copy_context
  8. krb5_free_context
  9. krb5_set_config_files
  10. add_file
  11. krb5_prepend_config_files
  12. krb5_prepend_config_files_default
  13. krb5_get_default_config_files
  14. krb5_free_config_files
  15. krb5_kerberos_enctypes
  16. default_etypes
  17. krb5_set_default_in_tkt_etypes
  18. krb5_get_default_in_tkt_etypes
  19. krb5_get_err_text
  20. krb5_init_ets
  21. krb5_set_use_admin_kdc
  22. krb5_get_use_admin_kdc
  23. krb5_add_extra_addresses
  24. krb5_set_extra_addresses
  25. krb5_get_extra_addresses
  26. krb5_add_ignore_addresses
  27. krb5_set_ignore_addresses
  28. krb5_get_ignore_addresses
  29. krb5_set_fcache_version
  30. krb5_get_fcache_version
  31. krb5_is_thread_safe
  32. krb5_set_dns_canonicalize_hostname
  33. krb5_get_dns_canonicalize_hostname
  34. krb5_get_kdc_sec_offset
  35. krb5_set_kdc_sec_offset
  36. krb5_get_max_time_skew
  37. krb5_set_max_time_skew

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

/* [<][>][^][v][top][bottom][index][help] */