Added a new trace logging message TRACE_PROFILE_ERR to improve the diagnostics of...
[krb5.git] / src / lib / krb5 / krb / init_ctx.c
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/krb5/krb/init_ctx.c */
3 /*
4  * Copyright 1994,1999,2000, 2002, 2003, 2007, 2008, 2009,2012 by the Massachusetts Institute of Technology.
5  * All Rights Reserved.
6  *
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.
11  *
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.
25  */
26 /*
27  * Copyright (C) 1998 by the FundsXpress, INC.
28  *
29  * All rights reserved.
30  *
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.
35  *
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.
46  *
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.
50  */
51
52 #include "k5-int.h"
53 #include "int-proto.h"
54 #include <ctype.h>
55 #include "brand.c"
56 #include "../krb5_libinit.h"
57
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
61    des-crc for now.  */
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,
65     ENCTYPE_ARCFOUR_HMAC,
66     ENCTYPE_DES_CBC_CRC, ENCTYPE_DES_CBC_MD5, ENCTYPE_DES_CBC_MD4,
67     0
68 };
69
70 #if (defined(_WIN32))
71 extern krb5_error_code krb5_vercheck();
72 extern void krb5_win_ccdll_load(krb5_context context);
73 #endif
74
75 krb5_error_code KRB5_CALLCONV
76 krb5_init_context(krb5_context *context)
77 {
78     /*
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
84      * library.
85      *
86      * If someday we grow an API to actually return the string, we can
87      * get rid of this silliness.
88      */
89     int my_zero = (krb5_brand[0] == 0);
90
91     return krb5_init_context_profile(NULL, my_zero, context);
92 }
93
94 krb5_error_code KRB5_CALLCONV
95 krb5_init_secure_context(krb5_context *context)
96 {
97     return krb5_init_context_profile(NULL, KRB5_INIT_CONTEXT_SECURE, context);
98 }
99
100 krb5_error_code
101 krb5int_init_context_kdc(krb5_context *context)
102 {
103     return krb5_init_context_profile(NULL, KRB5_INIT_CONTEXT_KDC, context);
104 }
105
106 #define DEFAULT_KDC_TIMESYNC 1
107 #define DEFAULT_CCACHE_TYPE  4
108 #define DEFAULT_CLOCKSKEW    5*60
109
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);
114
115 krb5_error_code KRB5_CALLCONV
116 krb5_init_context_profile(profile_t profile, krb5_flags flags,
117                           krb5_context *context_out)
118 {
119     krb5_error_code retval = 0;
120
121     /* Init context with defaults */
122     retval = init_context(profile, context_out, flags);
123
124     if (!retval && (*context_out)->profile != NULL)
125        retval =  process_config(context_out);
126
127     return retval;
128 }
129
130 static krb5_error_code
131 init_context(profile_t profile, krb5_context *context, krb5_flags flags)
132 {
133     krb5_context ctx = 0;
134     krb5_error_code retval;
135     struct {
136         krb5_int32 now, now_usec;
137         long pid;
138     } seed_data;
139     krb5_data seed;
140
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
145        wrong.  */
146     {
147         krb5_ui_8 i64;
148         assert(sizeof(i64) == 8);
149         i64 = 0, i64--, i64 >>= 62;
150         assert(i64 == 3);
151         i64 = 1, i64 <<= 31, i64 <<= 31, i64 <<= 1;
152         assert(i64 != 0);
153         i64 <<= 1;
154         assert(i64 == 0);
155     }
156
157     retval = krb5int_initialize_library();
158     if (retval)
159         return retval;
160
161 #if (defined(_WIN32))
162     /*
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.
166      */
167     krb5_win_ccdll_load(ctx);
168
169     /*
170      * krb5_vercheck() is defined in win_glue.c, and this is
171      * where we handle the timebomb and version server checks.
172      */
173     retval = krb5_vercheck();
174     if (retval)
175         return retval;
176 #endif
177
178     *context = NULL;
179
180     ctx = calloc(1, sizeof(struct _krb5_context));
181     if (!ctx)
182         return ENOMEM;
183     ctx->magic = KV5M_CONTEXT;
184
185     ctx->profile_secure = (flags & KRB5_INIT_CONTEXT_SECURE) != 0;
186
187     if ((retval = krb5_os_init_context(ctx, profile, flags)) != 0)
188         goto cleanup;
189
190     /* initialize the prng (not well, but passable) */
191     if ((retval = krb5_c_random_os_entropy( ctx, 0, NULL)) != 0)
192         goto cleanup;
193     if ((retval = krb5_crypto_us_timeofday(&seed_data.now, &seed_data.now_usec)))
194         goto cleanup;
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)))
199         goto cleanup;
200
201 #if 0
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;
206 #endif
207
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;
221
222     ctx->plugin_base_dir = strdup(DEFAULT_PLUGIN_BASE_DIR);
223     if (ctx->plugin_base_dir == NULL) {
224         retval = ENOMEM;
225         goto cleanup;
226     }
227
228 #ifndef DISABLE_TRACING
229     if (!ctx->profile_secure)
230         krb5int_init_trace(ctx);
231 #endif
232
233     *context = ctx;
234     return 0;
235
236 cleanup:
237     krb5_free_context(ctx);
238     return retval;
239 }
240
241 static krb5_error_code
242 process_config(krb5_context *context)
243 {
244     krb5_error_code retval = 0;
245     const char      *names[4];
246     int tmp;
247     char * s_tmp = NULL;
248     krb5_context ctx = *context;
249
250     names[0] = KRB5_CONF_LIBDEFAULTS;
251     names[2] = names[3] = 0;
252
253     /* allow_weak_crypto */
254     names[1] = KRB5_CONF_ALLOW_WEAK_CRYPTO;
255     retval = profile_get_boolean_nodef(ctx->profile, names, &tmp);
256     if (!retval)
257         ctx->allow_weak_crypto = tmp;
258     else if (retval != PROF_NO_SECTION && retval != PROF_NO_RELATION)
259         goto cleanup;
260
261     /* ignore_acceptor_hostname */
262     names[1] = KRB5_CONF_IGNORE_ACCEPTOR_HOSTNAME;
263     retval = profile_get_boolean_nodef(ctx->profile, names, &tmp);
264     if (!retval)
265         ctx->ignore_acceptor_hostname = tmp;
266     else if (retval != PROF_NO_SECTION && retval != PROF_NO_RELATION)
267         goto cleanup;
268
269     /* clockskew */
270     names[1] = KRB5_CONF_CLOCKSKEW;
271     retval = profile_get_integer_nodef(ctx->profile, names, &tmp);
272     if (!retval)
273         ctx->clockskew = tmp;
274     else if (retval != PROF_NO_SECTION && retval != PROF_NO_RELATION)
275         goto cleanup;
276
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);
282     if (!retval)
283         ctx->kdc_req_sumtype = tmp;
284     else if (retval != PROF_NO_SECTION && retval != PROF_NO_RELATION)
285         goto cleanup;
286
287     /* default_ap_req_sumtype */
288     names[1] = KRB5_CONF_AP_REQ_CHECKSUM_TYPE;
289     retval = profile_get_integer_nodef(ctx->profile, names, &tmp);
290     if (!retval)
291         ctx->default_ap_req_sumtype = tmp;
292     else if (retval != PROF_NO_SECTION && retval != PROF_NO_RELATION)
293         goto cleanup;
294
295     /* default_safe_sumtype */
296     names[1] = KRB5_CONF_SAFE_CHECKSUM_TYPE;
297     retval = profile_get_integer_nodef(ctx->profile, names, &tmp);
298     if (!retval)
299         ctx->default_safe_sumtype = tmp;
300     else if (retval != PROF_NO_SECTION && retval != PROF_NO_RELATION)
301         goto cleanup;
302
303     /* kdc_default_options */
304     names[1] = KRB5_CONF_KDC_DEFAULT_OPTIONS;
305     retval = profile_get_integer_nodef(ctx->profile, names, &tmp);
306     if (!retval)
307         ctx->kdc_default_options = tmp;
308     else if (retval != PROF_NO_SECTION && retval != PROF_NO_RELATION)
309         goto cleanup;
310
311     /* library_options */
312     names[1] = KRB5_CONF_KDC_TIMESYNC;
313     retval = profile_get_integer_nodef(ctx->profile, names, &tmp);
314     if (!retval)
315         ctx->library_options = tmp ? KRB5_LIBOPT_SYNC_KDCTIME : 0;
316     else if (retval != PROF_NO_SECTION && retval != PROF_NO_RELATION)
317         goto cleanup;
318
319     /* plugin_base_dir */
320     names[1] = KRB5_CONF_PLUGIN_BASE_DIR;
321     retval = profile_get_string_nodef(ctx->profile, names, &s_tmp);
322     if (!retval) {
323         if (ctx->plugin_base_dir)
324             free(ctx->plugin_base_dir);
325         ctx->plugin_base_dir = strdup(s_tmp);
326         free(s_tmp);
327         s_tmp = NULL;
328     } else if (retval != PROF_NO_SECTION && retval != PROF_NO_RELATION)
329         goto cleanup;
330
331     /* fcc_default_format */
332     /*
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.
336      *
337      * Note: DCE 1.0.3a only supports a cache type of 1
338      *      DCE 1.1 supports a cache type of 2.
339      */
340     names[1] = KRB5_CONF_CCACHE_TYPE;
341     retval = profile_get_integer_nodef(ctx->profile, names, &tmp);
342     if (!retval)
343         ctx->fcc_default_format = tmp + 0x0500;
344     else if (retval != PROF_NO_SECTION && retval != PROF_NO_RELATION)
345         goto cleanup;
346
347     return 0;
348
349 cleanup:
350     TRACE_PROFILE_ERR(ctx, names[1], names[0], retval);
351     krb5_free_context(*context);
352     return retval;
353 }
354
355 void KRB5_CALLCONV
356 krb5_free_context(krb5_context ctx)
357 {
358     if (ctx == NULL)
359         return;
360     krb5_os_free_context(ctx);
361
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) {
369         free(ctx->ser_ctx);
370         ctx->ser_ctx = 0;
371     }
372
373     krb5_clear_error_message(ctx);
374
375 #ifndef DISABLE_TRACING
376     if (ctx->trace_callback)
377         ctx->trace_callback(ctx, NULL, ctx->trace_callback_data);
378 #endif
379
380     k5_ccselect_free_context(ctx);
381     k5_plugin_free_context(ctx);
382     free(ctx->plugin_base_dir);
383
384     ctx->magic = 0;
385     free(ctx);
386 }
387
388 /*
389  * Set the desired default ktypes, making sure they are valid.
390  */
391 static krb5_error_code
392 set_default_etype_var(krb5_context context, const krb5_enctype *etypes,
393                       krb5_enctype **var)
394 {
395     krb5_error_code code;
396     krb5_enctype *list;
397     size_t src, dst;
398
399     if (etypes) {
400         /* Empty list passed in. */
401         if (etypes[0] == 0)
402             return EINVAL;
403         code = krb5int_copy_etypes(etypes, &list);
404         if (code)
405             return code;
406
407         /* Filter list in place to exclude invalid and (optionally) weak
408          * enctypes. */
409         for (src = dst = 0; list[src]; src++) {
410             if (!krb5_c_valid_enctype(list[src]))
411                 continue;
412             if (!context->allow_weak_crypto
413                 && krb5int_c_weak_enctype(list[src]))
414                 continue;
415             list[dst++] = list[src];
416         }
417         list[dst] = 0;          /* Zero-terminate. */
418         if (dst == 0) {
419             free(list);
420             return KRB5_CONFIG_ETYPE_NOSUPP;
421         }
422     } else {
423         list = NULL;
424     }
425
426     free(*var);
427     *var = list;
428     return 0;
429 }
430
431 krb5_error_code
432 krb5_set_default_in_tkt_ktypes(krb5_context context,
433                                const krb5_enctype *etypes)
434 {
435     return set_default_etype_var(context, etypes, &context->in_tkt_etypes);
436 }
437
438 krb5_error_code KRB5_CALLCONV
439 krb5_set_default_tgs_enctypes(krb5_context context, const krb5_enctype *etypes)
440 {
441     return set_default_etype_var(context, etypes, &context->tgs_etypes);
442 }
443
444 /* Old name for above function. */
445 krb5_error_code
446 krb5_set_default_tgs_ktypes(krb5_context context, const krb5_enctype *etypes)
447 {
448     return set_default_etype_var(context, etypes, &context->tgs_etypes);
449 }
450
451 /*
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.
456  */
457 static void
458 mod_list(krb5_enctype etype, krb5_boolean add, krb5_boolean allow_weak,
459          krb5_enctype **list_ptr)
460 {
461     size_t i;
462     krb5_enctype *list = *list_ptr;
463
464     /* Stop now if a previous allocation failed or the enctype is filtered. */
465     if (list == NULL || (!allow_weak && krb5int_c_weak_enctype(etype)))
466         return;
467     if (add) {
468         /* Count entries; do nothing if etype is a duplicate. */
469         for (i = 0; list[i] != 0; i++) {
470             if (list[i] == etype)
471                 return;
472         }
473         /* Make room for the new entry and add it. */
474         list = realloc(list, (i + 2) * sizeof(krb5_enctype));
475         if (list != NULL) {
476             list[i] = etype;
477             list[i + 1] = 0;
478         }
479     } else {
480         /* Look for etype in the list. */
481         for (i = 0; list[i] != 0; i++) {
482             if (list[i] != etype)
483                 continue;
484             /* Perform removal. */
485             for (; list[i + 1] != 0; i++)
486                 list[i] = list[i + 1];
487             list[i] = 0;
488             list = realloc(list, (i + 1) * sizeof(krb5_enctype));
489             break;
490         }
491     }
492     /* Update *list_ptr, freeing the old value if realloc failed. */
493     if (list == NULL)
494         free(*list_ptr);
495     *list_ptr = list;
496 }
497
498 /*
499  * Set *result to a zero-terminated list of enctypes resulting from
500  * parsing profstr.  profstr may be modified during parsing.
501  */
502 krb5_error_code
503 krb5int_parse_enctype_list(krb5_context context, const char *profkey,
504                            char *profstr, krb5_enctype *default_list,
505                            krb5_enctype **result)
506 {
507     char *token, *delim = " \t\r\n,", *save = NULL;
508     krb5_boolean sel, weak = context->allow_weak_crypto;
509     krb5_enctype etype, *list;
510     unsigned int i;
511
512     *result = NULL;
513
514     /* Set up an empty list.  Allocation failure is detected at the end. */
515     list = malloc(sizeof(krb5_enctype));
516     if (list != NULL)
517         list[0] = 0;
518
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. */
523         sel = TRUE;
524         if (*token == '+' || *token == '-')
525             sel = (*token++ == '+');
526
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);
542 #ifdef CAMELLIA
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);
546 #endif
547         } else if (krb5_string_to_enctype(token, &etype) == 0) {
548             /* Set a specific enctype. */
549             mod_list(etype, sel, weak, &list);
550         } else {
551             TRACE_ENCTYPE_LIST_UNKNOWN(context, profkey, token);
552         }
553     }
554
555     if (list == NULL)
556         return ENOMEM;
557     *result = list;
558     return 0;
559 }
560
561 /*
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
567  * not set.
568  */
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)
573 {
574     krb5_enctype *etypes;
575     krb5_error_code code;
576     char *profstr;
577
578     *etypes_ptr = NULL;
579
580     if (ctx_list) {
581         /* Use application defaults. */
582         code = krb5int_copy_etypes(ctx_list, &etypes);
583         if (code)
584             return code;
585     } else {
586         /* Parse profile setting, or "DEFAULT" if not specified. */
587         code = profile_get_string(context->profile, KRB5_CONF_LIBDEFAULTS,
588                                   profkey, NULL, "DEFAULT", &profstr);
589         if (code)
590             return code;
591         code = krb5int_parse_enctype_list(context, profkey, profstr,
592                                           default_list, &etypes);
593         profile_release_string(profstr);
594         if (code)
595             return code;
596     }
597
598     if (etypes[0] == 0) {
599         free(etypes);
600         return KRB5_CONFIG_ETYPE_NOSUPP;
601     }
602
603     *etypes_ptr = etypes;
604     return 0;
605 }
606
607 krb5_error_code
608 krb5_get_default_in_tkt_ktypes(krb5_context context, krb5_enctype **ktypes)
609 {
610     return get_profile_etype_list(context, ktypes,
611                                   KRB5_CONF_DEFAULT_TKT_ENCTYPES,
612                                   context->in_tkt_etypes,
613                                   default_enctype_list);
614 }
615
616 void
617 KRB5_CALLCONV
618 krb5_free_ktypes (krb5_context context, krb5_enctype *val)
619 {
620     free (val);
621 }
622
623 krb5_error_code
624 KRB5_CALLCONV
625 krb5_get_tgs_ktypes(krb5_context context, krb5_const_principal princ, krb5_enctype **ktypes)
626 {
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);
633     else
634         return get_profile_etype_list(context, ktypes,
635                                       KRB5_CONF_DEFAULT_TGS_ENCTYPES,
636                                       context->tgs_etypes,
637                                       default_enctype_list);
638 }
639
640 krb5_error_code KRB5_CALLCONV
641 krb5_get_permitted_enctypes(krb5_context context, krb5_enctype **ktypes)
642 {
643     return get_profile_etype_list(context, ktypes,
644                                   KRB5_CONF_PERMITTED_ENCTYPES,
645                                   context->tgs_etypes, default_enctype_list);
646 }
647
648 krb5_boolean
649 krb5_is_permitted_enctype(krb5_context context, krb5_enctype etype)
650 {
651     krb5_enctype *list, *ptr;
652     krb5_boolean ret;
653
654     if (krb5_get_permitted_enctypes(context, &list))
655         return(0);
656
657     ret = 0;
658
659     for (ptr = list; *ptr; ptr++)
660         if (*ptr == etype)
661             ret = 1;
662
663     krb5_free_ktypes (context, list);
664
665     return(ret);
666 }
667
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.
671  */
672
673 krb5_boolean
674 krb5_is_permitted_enctype_ext ( krb5_context context,
675                                 krb5_etypes_permitted *etypes)
676 {
677     krb5_enctype *list, *ptr;
678     krb5_boolean ret = 0;
679     int i = 0;
680
681     if (krb5_get_permitted_enctypes(context, &list))
682         return(0);
683
684     for ( i=0; i< etypes->etype_count; i++ )
685     {
686         for (ptr = list; *ptr; ptr++)
687         {
688             if (*ptr == etypes->etype[i])
689             {
690                 etypes->etype_ok[i] =  TRUE;
691                 ret = 1;
692             }
693         }
694     }
695     krb5_free_ktypes (context, list);
696
697     return(ret);
698 }