1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/krb5/krb/init_ctx.c */
4 * Copyright 1994,1999,2000, 2002, 2003, 2007, 2008, 2009,2012 by the Massachusetts Institute of Technology.
7 * Export of this software from the United States of America may
8 * require a specific license from the United States Government.
9 * It is the responsibility of any person or organization contemplating
10 * export to obtain such a license before exporting.
12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13 * distribute this software and its documentation for any purpose and
14 * without fee is hereby granted, provided that the above copyright
15 * notice appear in all copies and that both that copyright notice and
16 * this permission notice appear in supporting documentation, and that
17 * the name of M.I.T. not be used in advertising or publicity pertaining
18 * to distribution of the software without specific, written prior
19 * permission. Furthermore if you modify this software you must label
20 * your software as modified software and not distribute it in such a
21 * fashion that it might be confused with the original M.I.T. software.
22 * M.I.T. makes no representations about the suitability of
23 * this software for any purpose. It is provided "as is" without express
24 * or implied warranty.
27 * Copyright (C) 1998 by the FundsXpress, INC.
29 * All rights reserved.
31 * Export of this software from the United States of America may require
32 * a specific license from the United States Government. It is the
33 * responsibility of any person or organization contemplating export to
34 * obtain such a license before exporting.
36 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
37 * distribute this software and its documentation for any purpose and
38 * without fee is hereby granted, provided that the above copyright
39 * notice appear in all copies and that both that copyright notice and
40 * this permission notice appear in supporting documentation, and that
41 * the name of FundsXpress. not be used in advertising or publicity pertaining
42 * to distribution of the software without specific, written prior
43 * permission. FundsXpress makes no representations about the suitability of
44 * this software for any purpose. It is provided "as is" without express
45 * or implied warranty.
47 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
48 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
49 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
53 #include "int-proto.h"
56 #include "../krb5_libinit.h"
58 /* The des-mdX entries are last for now, because it's easy to
59 configure KDCs to issue TGTs with des-mdX keys and then not accept
60 them. This'll be fixed, but for better compatibility, let's prefer
62 static krb5_enctype default_enctype_list[] = {
63 ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96,
64 ENCTYPE_DES3_CBC_SHA1,
66 ENCTYPE_DES_CBC_CRC, ENCTYPE_DES_CBC_MD5, ENCTYPE_DES_CBC_MD4,
71 extern krb5_error_code krb5_vercheck();
72 extern void krb5_win_ccdll_load(krb5_context context);
75 krb5_error_code KRB5_CALLCONV
76 krb5_init_context(krb5_context *context)
79 * This is rather silly, but should improve our chances of
80 * retaining the krb5_brand array in the final linked library,
81 * better than a static variable that's unreferenced after
82 * optimization, or even a non-static symbol that's not exported
83 * from the library nor referenced from anywhere else in the
86 * If someday we grow an API to actually return the string, we can
87 * get rid of this silliness.
89 int my_zero = (krb5_brand[0] == 0);
91 return krb5_init_context_profile(NULL, my_zero, context);
94 krb5_error_code KRB5_CALLCONV
95 krb5_init_secure_context(krb5_context *context)
97 return krb5_init_context_profile(NULL, KRB5_INIT_CONTEXT_SECURE, context);
101 krb5int_init_context_kdc(krb5_context *context)
103 return krb5_init_context_profile(NULL, KRB5_INIT_CONTEXT_KDC, context);
106 #define DEFAULT_KDC_TIMESYNC 1
107 #define DEFAULT_CCACHE_TYPE 4
108 #define DEFAULT_CLOCKSKEW 5*60
110 static krb5_error_code
111 init_context(profile_t profile, krb5_context *context, krb5_flags flags);
112 static krb5_error_code
113 process_config(krb5_context *context);
115 krb5_error_code KRB5_CALLCONV
116 krb5_init_context_profile(profile_t profile, krb5_flags flags,
117 krb5_context *context_out)
119 krb5_error_code retval = 0;
121 /* Init context with defaults */
122 retval = init_context(profile, context_out, flags);
124 if (!retval && (*context_out)->profile != NULL)
125 retval = process_config(context_out);
130 static krb5_error_code
131 init_context(profile_t profile, krb5_context *context, krb5_flags flags)
133 krb5_context ctx = 0;
134 krb5_error_code retval;
136 krb5_int32 now, now_usec;
141 /* Verify some assumptions. If the assumptions hold and the
142 compiler is optimizing, this should result in no code being
143 executed. If we're guessing "unsigned long long" instead
144 of using uint64_t, the possibility does exist that we're
148 assert(sizeof(i64) == 8);
149 i64 = 0, i64--, i64 >>= 62;
151 i64 = 1, i64 <<= 31, i64 <<= 31, i64 <<= 1;
157 retval = krb5int_initialize_library();
161 #if (defined(_WIN32))
163 * Load the krbcc32.dll if necessary. We do this here so that
164 * we know to use API: later on during initialization.
165 * The context being NULL is ok.
167 krb5_win_ccdll_load(ctx);
170 * krb5_vercheck() is defined in win_glue.c, and this is
171 * where we handle the timebomb and version server checks.
173 retval = krb5_vercheck();
180 ctx = calloc(1, sizeof(struct _krb5_context));
183 ctx->magic = KV5M_CONTEXT;
185 ctx->profile_secure = (flags & KRB5_INIT_CONTEXT_SECURE) != 0;
187 if ((retval = krb5_os_init_context(ctx, profile, flags)) != 0)
190 /* initialize the prng (not well, but passable) */
191 if ((retval = krb5_c_random_os_entropy( ctx, 0, NULL)) != 0)
193 if ((retval = krb5_crypto_us_timeofday(&seed_data.now, &seed_data.now_usec)))
195 seed_data.pid = getpid ();
196 seed.length = sizeof(seed_data);
197 seed.data = (char *) &seed_data;
198 if ((retval = krb5_c_random_add_entropy(ctx, KRB5_C_RANDSOURCE_TIMING, &seed)))
202 /* Default ticket lifetime is currently not supported */
203 profile_get_integer(ctx->profile, KRB5_CONF_LIBDEFAULTS, "tkt_lifetime",
204 0, 10 * 60 * 60, &tmp);
205 ctx->tkt_lifetime = tmp;
208 ctx->prompt_types = 0;
209 ctx->use_conf_ktypes = 0;
210 ctx->udp_pref_limit = -1;
211 ctx->trace_callback = NULL;
212 ctx->ignore_acceptor_hostname = FALSE;
213 ctx->allow_weak_crypto = FALSE;
214 ctx->kdc_req_sumtype = CKSUMTYPE_RSA_MD5;
215 ctx->default_ap_req_sumtype = 0;
216 ctx->default_safe_sumtype = CKSUMTYPE_RSA_MD5_DES;
217 ctx->kdc_default_options = KDC_OPT_RENEWABLE_OK;
218 ctx->library_options = DEFAULT_KDC_TIMESYNC;
219 ctx->fcc_default_format = DEFAULT_CCACHE_TYPE + 0x0500;
220 ctx->clockskew = DEFAULT_CLOCKSKEW;
222 ctx->plugin_base_dir = strdup(DEFAULT_PLUGIN_BASE_DIR);
223 if (ctx->plugin_base_dir == NULL) {
228 #ifndef DISABLE_TRACING
229 if (!ctx->profile_secure)
230 krb5int_init_trace(ctx);
237 krb5_free_context(ctx);
241 static krb5_error_code
242 process_config(krb5_context *context)
244 krb5_error_code retval = 0;
245 const char *names[4];
248 krb5_context ctx = *context;
250 names[0] = KRB5_CONF_LIBDEFAULTS;
251 names[2] = names[3] = 0;
253 /* allow_weak_crypto */
254 names[1] = KRB5_CONF_ALLOW_WEAK_CRYPTO;
255 retval = profile_get_boolean_nodef(ctx->profile, names, &tmp);
257 ctx->allow_weak_crypto = tmp;
258 else if (retval != PROF_NO_SECTION && retval != PROF_NO_RELATION)
261 /* ignore_acceptor_hostname */
262 names[1] = KRB5_CONF_IGNORE_ACCEPTOR_HOSTNAME;
263 retval = profile_get_boolean_nodef(ctx->profile, names, &tmp);
265 ctx->ignore_acceptor_hostname = tmp;
266 else if (retval != PROF_NO_SECTION && retval != PROF_NO_RELATION)
270 names[1] = KRB5_CONF_CLOCKSKEW;
271 retval = profile_get_integer_nodef(ctx->profile, names, &tmp);
273 ctx->clockskew = tmp;
274 else if (retval != PROF_NO_SECTION && retval != PROF_NO_RELATION)
277 /* DCE 1.1 and below only support CKSUMTYPE_RSA_MD4 (2) */
278 /* DCE add kdc_req_checksum_type = 2 to krb5.conf */
279 /* kdc_req_sumtype */
280 names[1] = KRB5_CONF_KDC_REQ_CHECKSUM_TYPE;
281 retval = profile_get_integer_nodef(ctx->profile, names, &tmp);
283 ctx->kdc_req_sumtype = tmp;
284 else if (retval != PROF_NO_SECTION && retval != PROF_NO_RELATION)
287 /* default_ap_req_sumtype */
288 names[1] = KRB5_CONF_AP_REQ_CHECKSUM_TYPE;
289 retval = profile_get_integer_nodef(ctx->profile, names, &tmp);
291 ctx->default_ap_req_sumtype = tmp;
292 else if (retval != PROF_NO_SECTION && retval != PROF_NO_RELATION)
295 /* default_safe_sumtype */
296 names[1] = KRB5_CONF_SAFE_CHECKSUM_TYPE;
297 retval = profile_get_integer_nodef(ctx->profile, names, &tmp);
299 ctx->default_safe_sumtype = tmp;
300 else if (retval != PROF_NO_SECTION && retval != PROF_NO_RELATION)
303 /* kdc_default_options */
304 names[1] = KRB5_CONF_KDC_DEFAULT_OPTIONS;
305 retval = profile_get_integer_nodef(ctx->profile, names, &tmp);
307 ctx->kdc_default_options = tmp;
308 else if (retval != PROF_NO_SECTION && retval != PROF_NO_RELATION)
311 /* library_options */
312 names[1] = KRB5_CONF_KDC_TIMESYNC;
313 retval = profile_get_integer_nodef(ctx->profile, names, &tmp);
315 ctx->library_options = tmp ? KRB5_LIBOPT_SYNC_KDCTIME : 0;
316 else if (retval != PROF_NO_SECTION && retval != PROF_NO_RELATION)
319 /* plugin_base_dir */
320 names[1] = KRB5_CONF_PLUGIN_BASE_DIR;
321 retval = profile_get_string_nodef(ctx->profile, names, &s_tmp);
323 if (ctx->plugin_base_dir)
324 free(ctx->plugin_base_dir);
325 ctx->plugin_base_dir = strdup(s_tmp);
328 } else if (retval != PROF_NO_SECTION && retval != PROF_NO_RELATION)
331 /* fcc_default_format */
333 * We use a default file credentials cache of 3. See
334 * lib/krb5/krb/ccache/file/fcc.h for a description of the
335 * credentials cache types.
337 * Note: DCE 1.0.3a only supports a cache type of 1
338 * DCE 1.1 supports a cache type of 2.
340 names[1] = KRB5_CONF_CCACHE_TYPE;
341 retval = profile_get_integer_nodef(ctx->profile, names, &tmp);
343 ctx->fcc_default_format = tmp + 0x0500;
344 else if (retval != PROF_NO_SECTION && retval != PROF_NO_RELATION)
350 TRACE_PROFILE_ERR(ctx, names[1], names[0], retval);
351 krb5_free_context(*context);
356 krb5_free_context(krb5_context ctx)
360 krb5_os_free_context(ctx);
362 free(ctx->in_tkt_etypes);
363 ctx->in_tkt_etypes = NULL;
364 free(ctx->tgs_etypes);
365 ctx->tgs_etypes = NULL;
366 free(ctx->default_realm);
367 ctx->default_realm = 0;
368 if (ctx->ser_ctx_count && ctx->ser_ctx) {
373 krb5_clear_error_message(ctx);
375 #ifndef DISABLE_TRACING
376 if (ctx->trace_callback)
377 ctx->trace_callback(ctx, NULL, ctx->trace_callback_data);
380 k5_ccselect_free_context(ctx);
381 k5_plugin_free_context(ctx);
382 free(ctx->plugin_base_dir);
389 * Set the desired default ktypes, making sure they are valid.
391 static krb5_error_code
392 set_default_etype_var(krb5_context context, const krb5_enctype *etypes,
395 krb5_error_code code;
400 /* Empty list passed in. */
403 code = krb5int_copy_etypes(etypes, &list);
407 /* Filter list in place to exclude invalid and (optionally) weak
409 for (src = dst = 0; list[src]; src++) {
410 if (!krb5_c_valid_enctype(list[src]))
412 if (!context->allow_weak_crypto
413 && krb5int_c_weak_enctype(list[src]))
415 list[dst++] = list[src];
417 list[dst] = 0; /* Zero-terminate. */
420 return KRB5_CONFIG_ETYPE_NOSUPP;
432 krb5_set_default_in_tkt_ktypes(krb5_context context,
433 const krb5_enctype *etypes)
435 return set_default_etype_var(context, etypes, &context->in_tkt_etypes);
438 krb5_error_code KRB5_CALLCONV
439 krb5_set_default_tgs_enctypes(krb5_context context, const krb5_enctype *etypes)
441 return set_default_etype_var(context, etypes, &context->tgs_etypes);
444 /* Old name for above function. */
446 krb5_set_default_tgs_ktypes(krb5_context context, const krb5_enctype *etypes)
448 return set_default_etype_var(context, etypes, &context->tgs_etypes);
452 * Add etype to, or remove etype from, the zero-terminated list *list_ptr,
453 * reallocating if the list size changes. Filter out weak enctypes if
454 * allow_weak is false. If memory allocation fails, set *list_ptr to NULL and
455 * do nothing for subsequent operations.
458 mod_list(krb5_enctype etype, krb5_boolean add, krb5_boolean allow_weak,
459 krb5_enctype **list_ptr)
462 krb5_enctype *list = *list_ptr;
464 /* Stop now if a previous allocation failed or the enctype is filtered. */
465 if (list == NULL || (!allow_weak && krb5int_c_weak_enctype(etype)))
468 /* Count entries; do nothing if etype is a duplicate. */
469 for (i = 0; list[i] != 0; i++) {
470 if (list[i] == etype)
473 /* Make room for the new entry and add it. */
474 list = realloc(list, (i + 2) * sizeof(krb5_enctype));
480 /* Look for etype in the list. */
481 for (i = 0; list[i] != 0; i++) {
482 if (list[i] != etype)
484 /* Perform removal. */
485 for (; list[i + 1] != 0; i++)
486 list[i] = list[i + 1];
488 list = realloc(list, (i + 1) * sizeof(krb5_enctype));
492 /* Update *list_ptr, freeing the old value if realloc failed. */
499 * Set *result to a zero-terminated list of enctypes resulting from
500 * parsing profstr. profstr may be modified during parsing.
503 krb5int_parse_enctype_list(krb5_context context, const char *profkey,
504 char *profstr, krb5_enctype *default_list,
505 krb5_enctype **result)
507 char *token, *delim = " \t\r\n,", *save = NULL;
508 krb5_boolean sel, weak = context->allow_weak_crypto;
509 krb5_enctype etype, *list;
514 /* Set up an empty list. Allocation failure is detected at the end. */
515 list = malloc(sizeof(krb5_enctype));
519 /* Walk through the words in profstr. */
520 for (token = strtok_r(profstr, delim, &save); token;
521 token = strtok_r(NULL, delim, &save)) {
522 /* Determine if we are adding or removing enctypes. */
524 if (*token == '+' || *token == '-')
525 sel = (*token++ == '+');
527 if (strcasecmp(token, "DEFAULT") == 0) {
528 /* Set all enctypes in the default list. */
529 for (i = 0; default_list[i]; i++)
530 mod_list(default_list[i], sel, weak, &list);
531 } else if (strcasecmp(token, "des") == 0) {
532 mod_list(ENCTYPE_DES_CBC_CRC, sel, weak, &list);
533 mod_list(ENCTYPE_DES_CBC_MD5, sel, weak, &list);
534 mod_list(ENCTYPE_DES_CBC_MD4, sel, weak, &list);
535 } else if (strcasecmp(token, "des3") == 0) {
536 mod_list(ENCTYPE_DES3_CBC_SHA1, sel, weak, &list);
537 } else if (strcasecmp(token, "aes") == 0) {
538 mod_list(ENCTYPE_AES256_CTS_HMAC_SHA1_96, sel, weak, &list);
539 mod_list(ENCTYPE_AES128_CTS_HMAC_SHA1_96, sel, weak, &list);
540 } else if (strcasecmp(token, "rc4") == 0) {
541 mod_list(ENCTYPE_ARCFOUR_HMAC, sel, weak, &list);
543 } else if (strcasecmp(token, "camellia") == 0) {
544 mod_list(ENCTYPE_CAMELLIA256_CTS_CMAC, sel, weak, &list);
545 mod_list(ENCTYPE_CAMELLIA128_CTS_CMAC, sel, weak, &list);
547 } else if (krb5_string_to_enctype(token, &etype) == 0) {
548 /* Set a specific enctype. */
549 mod_list(etype, sel, weak, &list);
551 TRACE_ENCTYPE_LIST_UNKNOWN(context, profkey, token);
562 * Set *etypes_ptr to a zero-terminated list of enctypes. ctx_list
563 * (containing application-specified enctypes) is used if non-NULL;
564 * otherwise the libdefaults profile string specified by profkey is
565 * used. default_list is the default enctype list to be used while
566 * parsing profile strings, and is also used if the profile string is
569 static krb5_error_code
570 get_profile_etype_list(krb5_context context, krb5_enctype **etypes_ptr,
571 char *profkey, krb5_enctype *ctx_list,
572 krb5_enctype *default_list)
574 krb5_enctype *etypes;
575 krb5_error_code code;
581 /* Use application defaults. */
582 code = krb5int_copy_etypes(ctx_list, &etypes);
586 /* Parse profile setting, or "DEFAULT" if not specified. */
587 code = profile_get_string(context->profile, KRB5_CONF_LIBDEFAULTS,
588 profkey, NULL, "DEFAULT", &profstr);
591 code = krb5int_parse_enctype_list(context, profkey, profstr,
592 default_list, &etypes);
593 profile_release_string(profstr);
598 if (etypes[0] == 0) {
600 return KRB5_CONFIG_ETYPE_NOSUPP;
603 *etypes_ptr = etypes;
608 krb5_get_default_in_tkt_ktypes(krb5_context context, krb5_enctype **ktypes)
610 return get_profile_etype_list(context, ktypes,
611 KRB5_CONF_DEFAULT_TKT_ENCTYPES,
612 context->in_tkt_etypes,
613 default_enctype_list);
618 krb5_free_ktypes (krb5_context context, krb5_enctype *val)
625 krb5_get_tgs_ktypes(krb5_context context, krb5_const_principal princ, krb5_enctype **ktypes)
627 if (context->use_conf_ktypes)
628 /* This one is set *only* by reading the config file; it's not
629 set by the application. */
630 return get_profile_etype_list(context, ktypes,
631 KRB5_CONF_DEFAULT_TKT_ENCTYPES, NULL,
632 default_enctype_list);
634 return get_profile_etype_list(context, ktypes,
635 KRB5_CONF_DEFAULT_TGS_ENCTYPES,
637 default_enctype_list);
640 krb5_error_code KRB5_CALLCONV
641 krb5_get_permitted_enctypes(krb5_context context, krb5_enctype **ktypes)
643 return get_profile_etype_list(context, ktypes,
644 KRB5_CONF_PERMITTED_ENCTYPES,
645 context->tgs_etypes, default_enctype_list);
649 krb5_is_permitted_enctype(krb5_context context, krb5_enctype etype)
651 krb5_enctype *list, *ptr;
654 if (krb5_get_permitted_enctypes(context, &list))
659 for (ptr = list; *ptr; ptr++)
663 krb5_free_ktypes (context, list);
668 /* The same as krb5_is_permitted_enctype, but verifies multiple etype's
669 * Returns 0 is either the list of the permitted enc types is not available
670 * or all requested etypes are not permitted. Otherwise returns 1.
674 krb5_is_permitted_enctype_ext ( krb5_context context,
675 krb5_etypes_permitted *etypes)
677 krb5_enctype *list, *ptr;
678 krb5_boolean ret = 0;
681 if (krb5_get_permitted_enctypes(context, &list))
684 for ( i=0; i< etypes->etype_count; i++ )
686 for (ptr = list; *ptr; ptr++)
688 if (*ptr == etypes->etype[i])
690 etypes->etype_ok[i] = TRUE;
695 krb5_free_ktypes (context, list);