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 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 krb5_error_code KRB5_CALLCONV
107 krb5_init_context_profile(profile_t profile, krb5_flags flags,
108 krb5_context *context_out)
110 krb5_context ctx = 0;
111 krb5_error_code retval;
113 krb5_int32 now, now_usec;
119 /* Verify some assumptions. If the assumptions hold and the
120 compiler is optimizing, this should result in no code being
121 executed. If we're guessing "unsigned long long" instead
122 of using uint64_t, the possibility does exist that we're
126 assert(sizeof(i64) == 8);
127 i64 = 0, i64--, i64 >>= 62;
129 i64 = 1, i64 <<= 31, i64 <<= 31, i64 <<= 1;
135 retval = krb5int_initialize_library();
139 #if (defined(_WIN32))
141 * Load the krbcc32.dll if necessary. We do this here so that
142 * we know to use API: later on during initialization.
143 * The context being NULL is ok.
145 krb5_win_ccdll_load(ctx);
148 * krb5_vercheck() is defined in win_glue.c, and this is
149 * where we handle the timebomb and version server checks.
151 retval = krb5_vercheck();
158 ctx = calloc(1, sizeof(struct _krb5_context));
161 ctx->magic = KV5M_CONTEXT;
163 ctx->profile_secure = (flags & KRB5_INIT_CONTEXT_SECURE) != 0;
165 if ((retval = krb5_os_init_context(ctx, profile, flags)) != 0)
168 retval = profile_get_boolean(ctx->profile, KRB5_CONF_LIBDEFAULTS,
169 KRB5_CONF_ALLOW_WEAK_CRYPTO, NULL, 0, &tmp);
172 ctx->allow_weak_crypto = tmp;
174 retval = profile_get_boolean(ctx->profile, KRB5_CONF_LIBDEFAULTS,
175 KRB5_CONF_IGNORE_ACCEPTOR_HOSTNAME, NULL, 0,
179 ctx->ignore_acceptor_hostname = tmp;
181 /* initialize the prng (not well, but passable) */
182 if ((retval = krb5_c_random_os_entropy( ctx, 0, NULL)) !=0)
184 if ((retval = krb5_crypto_us_timeofday(&seed_data.now, &seed_data.now_usec)))
186 seed_data.pid = getpid ();
187 seed.length = sizeof(seed_data);
188 seed.data = (char *) &seed_data;
189 if ((retval = krb5_c_random_add_entropy(ctx, KRB5_C_RANDSOURCE_TIMING, &seed)))
192 ctx->default_realm = 0;
193 profile_get_integer(ctx->profile, KRB5_CONF_LIBDEFAULTS, KRB5_CONF_CLOCKSKEW,
195 ctx->clockskew = tmp;
198 /* Default ticket lifetime is currently not supported */
199 profile_get_integer(ctx->profile, KRB5_CONF_LIBDEFAULTS, "tkt_lifetime",
200 0, 10 * 60 * 60, &tmp);
201 ctx->tkt_lifetime = tmp;
204 /* DCE 1.1 and below only support CKSUMTYPE_RSA_MD4 (2) */
205 /* DCE add kdc_req_checksum_type = 2 to krb5.conf */
206 profile_get_integer(ctx->profile, KRB5_CONF_LIBDEFAULTS,
207 KRB5_CONF_KDC_REQ_CHECKSUM_TYPE, 0, CKSUMTYPE_RSA_MD5,
209 ctx->kdc_req_sumtype = tmp;
211 profile_get_integer(ctx->profile, KRB5_CONF_LIBDEFAULTS,
212 KRB5_CONF_AP_REQ_CHECKSUM_TYPE, 0, 0,
214 ctx->default_ap_req_sumtype = tmp;
216 profile_get_integer(ctx->profile, KRB5_CONF_LIBDEFAULTS,
217 KRB5_CONF_SAFE_CHECKSUM_TYPE, 0,
218 CKSUMTYPE_RSA_MD5_DES, &tmp);
219 ctx->default_safe_sumtype = tmp;
221 profile_get_integer(ctx->profile, KRB5_CONF_LIBDEFAULTS,
222 KRB5_CONF_KDC_DEFAULT_OPTIONS, 0,
223 KDC_OPT_RENEWABLE_OK, &tmp);
224 ctx->kdc_default_options = tmp;
225 #define DEFAULT_KDC_TIMESYNC 1
226 profile_get_integer(ctx->profile, KRB5_CONF_LIBDEFAULTS,
227 KRB5_CONF_KDC_TIMESYNC, 0, DEFAULT_KDC_TIMESYNC,
229 ctx->library_options = tmp ? KRB5_LIBOPT_SYNC_KDCTIME : 0;
231 retval = profile_get_string(ctx->profile, KRB5_CONF_LIBDEFAULTS,
232 KRB5_CONF_PLUGIN_BASE_DIR, 0,
233 DEFAULT_PLUGIN_BASE_DIR,
234 &ctx->plugin_base_dir);
239 * We use a default file credentials cache of 3. See
240 * lib/krb5/krb/ccache/file/fcc.h for a description of the
241 * credentials cache types.
243 * Note: DCE 1.0.3a only supports a cache type of 1
244 * DCE 1.1 supports a cache type of 2.
246 #define DEFAULT_CCACHE_TYPE 4
247 profile_get_integer(ctx->profile, KRB5_CONF_LIBDEFAULTS, KRB5_CONF_CCACHE_TYPE,
248 0, DEFAULT_CCACHE_TYPE, &tmp);
249 ctx->fcc_default_format = tmp + 0x0500;
250 ctx->prompt_types = 0;
251 ctx->use_conf_ktypes = 0;
252 ctx->udp_pref_limit = -1;
253 ctx->trace_callback = NULL;
254 #ifndef DISABLE_TRACING
255 if (!ctx->profile_secure)
256 krb5int_init_trace(ctx);
262 krb5_free_context(ctx);
267 krb5_free_context(krb5_context ctx)
271 krb5_os_free_context(ctx);
273 free(ctx->in_tkt_etypes);
274 ctx->in_tkt_etypes = NULL;
275 free(ctx->tgs_etypes);
276 ctx->tgs_etypes = NULL;
277 free(ctx->default_realm);
278 ctx->default_realm = 0;
279 if (ctx->ser_ctx_count && ctx->ser_ctx) {
284 krb5_clear_error_message(ctx);
286 #ifndef DISABLE_TRACING
287 if (ctx->trace_callback)
288 ctx->trace_callback(ctx, NULL, ctx->trace_callback_data);
291 k5_ccselect_free_context(ctx);
292 k5_plugin_free_context(ctx);
293 free(ctx->plugin_base_dir);
300 * Set the desired default ktypes, making sure they are valid.
302 static krb5_error_code
303 set_default_etype_var(krb5_context context, const krb5_enctype *etypes,
306 krb5_error_code code;
311 /* Empty list passed in. */
314 code = krb5int_copy_etypes(etypes, &list);
318 /* Filter list in place to exclude invalid and (optionally) weak
320 for (src = dst = 0; list[src]; src++) {
321 if (!krb5_c_valid_enctype(list[src]))
323 if (!context->allow_weak_crypto
324 && krb5int_c_weak_enctype(list[src]))
326 list[dst++] = list[src];
328 list[dst] = 0; /* Zero-terminate. */
331 return KRB5_CONFIG_ETYPE_NOSUPP;
343 krb5_set_default_in_tkt_ktypes(krb5_context context,
344 const krb5_enctype *etypes)
346 return set_default_etype_var(context, etypes, &context->in_tkt_etypes);
349 krb5_error_code KRB5_CALLCONV
350 krb5_set_default_tgs_enctypes(krb5_context context, const krb5_enctype *etypes)
352 return set_default_etype_var(context, etypes, &context->tgs_etypes);
355 /* Old name for above function. */
357 krb5_set_default_tgs_ktypes(krb5_context context, const krb5_enctype *etypes)
359 return set_default_etype_var(context, etypes, &context->tgs_etypes);
363 * Add etype to, or remove etype from, the zero-terminated list *list_ptr,
364 * reallocating if the list size changes. Filter out weak enctypes if
365 * allow_weak is false. If memory allocation fails, set *list_ptr to NULL and
366 * do nothing for subsequent operations.
369 mod_list(krb5_enctype etype, krb5_boolean add, krb5_boolean allow_weak,
370 krb5_enctype **list_ptr)
373 krb5_enctype *list = *list_ptr;
375 /* Stop now if a previous allocation failed or the enctype is filtered. */
376 if (list == NULL || (!allow_weak && krb5int_c_weak_enctype(etype)))
379 /* Count entries; do nothing if etype is a duplicate. */
380 for (i = 0; list[i] != 0; i++) {
381 if (list[i] == etype)
384 /* Make room for the new entry and add it. */
385 list = realloc(list, (i + 2) * sizeof(krb5_enctype));
391 /* Look for etype in the list. */
392 for (i = 0; list[i] != 0; i++) {
393 if (list[i] != etype)
395 /* Perform removal. */
396 for (; list[i + 1] != 0; i++)
397 list[i] = list[i + 1];
399 list = realloc(list, (i + 1) * sizeof(krb5_enctype));
403 /* Update *list_ptr, freeing the old value if realloc failed. */
410 * Set *result to a zero-terminated list of enctypes resulting from
411 * parsing profstr. profstr may be modified during parsing.
414 krb5int_parse_enctype_list(krb5_context context, const char *profkey,
415 char *profstr, krb5_enctype *default_list,
416 krb5_enctype **result)
418 char *token, *delim = " \t\r\n,", *save = NULL;
419 krb5_boolean sel, weak = context->allow_weak_crypto;
420 krb5_enctype etype, *list;
425 /* Set up an empty list. Allocation failure is detected at the end. */
426 list = malloc(sizeof(krb5_enctype));
430 /* Walk through the words in profstr. */
431 for (token = strtok_r(profstr, delim, &save); token;
432 token = strtok_r(NULL, delim, &save)) {
433 /* Determine if we are adding or removing enctypes. */
435 if (*token == '+' || *token == '-')
436 sel = (*token++ == '+');
438 if (strcasecmp(token, "DEFAULT") == 0) {
439 /* Set all enctypes in the default list. */
440 for (i = 0; default_list[i]; i++)
441 mod_list(default_list[i], sel, weak, &list);
442 } else if (strcasecmp(token, "des") == 0) {
443 mod_list(ENCTYPE_DES_CBC_CRC, sel, weak, &list);
444 mod_list(ENCTYPE_DES_CBC_MD5, sel, weak, &list);
445 mod_list(ENCTYPE_DES_CBC_MD4, sel, weak, &list);
446 } else if (strcasecmp(token, "des3") == 0) {
447 mod_list(ENCTYPE_DES3_CBC_SHA1, sel, weak, &list);
448 } else if (strcasecmp(token, "aes") == 0) {
449 mod_list(ENCTYPE_AES256_CTS_HMAC_SHA1_96, sel, weak, &list);
450 mod_list(ENCTYPE_AES128_CTS_HMAC_SHA1_96, sel, weak, &list);
451 } else if (strcasecmp(token, "rc4") == 0) {
452 mod_list(ENCTYPE_ARCFOUR_HMAC, sel, weak, &list);
454 } else if (strcasecmp(token, "camellia") == 0) {
455 mod_list(ENCTYPE_CAMELLIA256_CTS_CMAC, sel, weak, &list);
456 mod_list(ENCTYPE_CAMELLIA128_CTS_CMAC, sel, weak, &list);
458 } else if (krb5_string_to_enctype(token, &etype) == 0) {
459 /* Set a specific enctype. */
460 mod_list(etype, sel, weak, &list);
462 TRACE_ENCTYPE_LIST_UNKNOWN(context, profkey, token);
473 * Set *etypes_ptr to a zero-terminated list of enctypes. ctx_list
474 * (containing application-specified enctypes) is used if non-NULL;
475 * otherwise the libdefaults profile string specified by profkey is
476 * used. default_list is the default enctype list to be used while
477 * parsing profile strings, and is also used if the profile string is
480 static krb5_error_code
481 get_profile_etype_list(krb5_context context, krb5_enctype **etypes_ptr,
482 char *profkey, krb5_enctype *ctx_list,
483 krb5_enctype *default_list)
485 krb5_enctype *etypes;
486 krb5_error_code code;
492 /* Use application defaults. */
493 code = krb5int_copy_etypes(ctx_list, &etypes);
497 /* Parse profile setting, or "DEFAULT" if not specified. */
498 code = profile_get_string(context->profile, KRB5_CONF_LIBDEFAULTS,
499 profkey, NULL, "DEFAULT", &profstr);
502 code = krb5int_parse_enctype_list(context, profkey, profstr,
503 default_list, &etypes);
504 profile_release_string(profstr);
509 if (etypes[0] == 0) {
511 return KRB5_CONFIG_ETYPE_NOSUPP;
514 *etypes_ptr = etypes;
519 krb5_get_default_in_tkt_ktypes(krb5_context context, krb5_enctype **ktypes)
521 return get_profile_etype_list(context, ktypes,
522 KRB5_CONF_DEFAULT_TKT_ENCTYPES,
523 context->in_tkt_etypes,
524 default_enctype_list);
529 krb5_free_ktypes (krb5_context context, krb5_enctype *val)
536 krb5_get_tgs_ktypes(krb5_context context, krb5_const_principal princ, krb5_enctype **ktypes)
538 if (context->use_conf_ktypes)
539 /* This one is set *only* by reading the config file; it's not
540 set by the application. */
541 return get_profile_etype_list(context, ktypes,
542 KRB5_CONF_DEFAULT_TKT_ENCTYPES, NULL,
543 default_enctype_list);
545 return get_profile_etype_list(context, ktypes,
546 KRB5_CONF_DEFAULT_TGS_ENCTYPES,
548 default_enctype_list);
551 krb5_error_code KRB5_CALLCONV
552 krb5_get_permitted_enctypes(krb5_context context, krb5_enctype **ktypes)
554 return get_profile_etype_list(context, ktypes,
555 KRB5_CONF_PERMITTED_ENCTYPES,
556 context->tgs_etypes, default_enctype_list);
560 krb5_is_permitted_enctype(krb5_context context, krb5_enctype etype)
562 krb5_enctype *list, *ptr;
565 if (krb5_get_permitted_enctypes(context, &list))
571 for (ptr = list; *ptr; ptr++)
575 krb5_free_ktypes (context, list);
580 /* The same as krb5_is_permitted_enctype, but verifies multiple etype's
581 * Returns 0 is either the list of the permitted enc types is not available
582 * or all requested etypes are not permitted. Otherwise returns 1.
586 krb5_is_permitted_enctype_ext ( krb5_context context,
587 krb5_etypes_permitted *etypes)
589 krb5_enctype *list, *ptr;
590 krb5_boolean ret = 0;
593 if (krb5_get_permitted_enctypes(context, &list))
596 for ( i=0; i< etypes->etype_count; i++ )
598 for (ptr = list; *ptr; ptr++)
600 if (*ptr == etypes->etype[i])
602 etypes->etype_ok[i] = TRUE;
607 krb5_free_ktypes (context, list);