xref: /freebsd/crypto/krb5/src/lib/krb5/krb/init_ctx.c (revision f1c4c3daccbaf3820f0e2224de53df12fc952fcc)
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  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 "os-proto.h"
55 #include <ctype.h>
56 #include "brand.c"
57 #include "../krb5_libinit.h"
58 
59 static krb5_enctype default_enctype_list[] = {
60     ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96,
61     ENCTYPE_AES256_CTS_HMAC_SHA384_192, ENCTYPE_AES128_CTS_HMAC_SHA256_128,
62     ENCTYPE_DES3_CBC_SHA1,
63     ENCTYPE_ARCFOUR_HMAC,
64     ENCTYPE_CAMELLIA128_CTS_CMAC, ENCTYPE_CAMELLIA256_CTS_CMAC,
65     0
66 };
67 
68 #if (defined(_WIN32))
69 extern krb5_error_code krb5_vercheck(void);
70 extern void krb5_win_ccdll_load(krb5_context context);
71 #endif
72 
73 #define DEFAULT_CLOCKSKEW  300 /* 5 min */
74 
75 static krb5_error_code
get_integer(krb5_context ctx,const char * name,int def_val,int * int_out)76 get_integer(krb5_context ctx, const char *name, int def_val, int *int_out)
77 {
78     krb5_error_code retval;
79 
80     retval = profile_get_integer(ctx->profile, KRB5_CONF_LIBDEFAULTS,
81                                  name, NULL, def_val, int_out);
82     if (retval)
83         TRACE_PROFILE_ERR(ctx, name, KRB5_CONF_LIBDEFAULTS, retval);
84     return retval;
85 }
86 
87 static krb5_error_code
get_boolean(krb5_context ctx,const char * name,int def_val,int * boolean_out)88 get_boolean(krb5_context ctx, const char *name, int def_val, int *boolean_out)
89 {
90     krb5_error_code retval;
91 
92     retval = profile_get_boolean(ctx->profile, KRB5_CONF_LIBDEFAULTS,
93                                  name, NULL, def_val, boolean_out);
94     if (retval)
95         TRACE_PROFILE_ERR(ctx, name, KRB5_CONF_LIBDEFAULTS, retval);
96     return retval;
97 }
98 
99 static krb5_error_code
get_tristate(krb5_context ctx,const char * name,const char * third_option,int third_option_val,int def_val,int * val_out)100 get_tristate(krb5_context ctx, const char *name, const char *third_option,
101              int third_option_val, int def_val, int *val_out)
102 {
103     krb5_error_code retval;
104     char *str;
105     int match;
106 
107     retval = profile_get_boolean(ctx->profile, KRB5_CONF_LIBDEFAULTS, name,
108                                  NULL, def_val, val_out);
109     if (retval != PROF_BAD_BOOLEAN)
110         return retval;
111     retval = profile_get_string(ctx->profile, KRB5_CONF_LIBDEFAULTS, name,
112                                 NULL, NULL, &str);
113     if (retval)
114         return retval;
115     match = (strcasecmp(third_option, str) == 0);
116     free(str);
117     if (!match)
118         return EINVAL;
119     *val_out = third_option_val;
120     return 0;
121 }
122 
123 krb5_error_code KRB5_CALLCONV
krb5_init_context(krb5_context * context)124 krb5_init_context(krb5_context *context)
125 {
126     /*
127      * This is rather silly, but should improve our chances of
128      * retaining the krb5_brand array in the final linked library,
129      * better than a static variable that's unreferenced after
130      * optimization, or even a non-static symbol that's not exported
131      * from the library nor referenced from anywhere else in the
132      * library.
133      *
134      * If someday we grow an API to actually return the string, we can
135      * get rid of this silliness.
136      */
137     int my_zero = (krb5_brand[0] == 0);
138 
139     return krb5_init_context_profile(NULL, my_zero, context);
140 }
141 
142 krb5_error_code KRB5_CALLCONV
krb5_init_secure_context(krb5_context * context)143 krb5_init_secure_context(krb5_context *context)
144 {
145     return krb5_init_context_profile(NULL, KRB5_INIT_CONTEXT_SECURE, context);
146 }
147 
148 krb5_error_code
krb5int_init_context_kdc(krb5_context * context)149 krb5int_init_context_kdc(krb5_context *context)
150 {
151     return krb5_init_context_profile(NULL, KRB5_INIT_CONTEXT_KDC, context);
152 }
153 
154 krb5_error_code KRB5_CALLCONV
krb5_init_context_profile(profile_t profile,krb5_flags flags,krb5_context * context_out)155 krb5_init_context_profile(profile_t profile, krb5_flags flags,
156                           krb5_context *context_out)
157 {
158     krb5_context ctx = 0;
159     krb5_error_code retval;
160     int tmp;
161     char *plugin_dir = NULL, *timeout_str = NULL;
162 
163     /* Verify some assumptions.  If the assumptions hold and the
164        compiler is optimizing, this should result in no code being
165        executed.  If we're guessing "unsigned long long" instead
166        of using uint64_t, the possibility does exist that we're
167        wrong.  */
168     {
169         uint64_t i64;
170         assert(sizeof(i64) == 8);
171         i64 = 0, i64--, i64 >>= 62;
172         assert(i64 == 3);
173         i64 = 1, i64 <<= 31, i64 <<= 31, i64 <<= 1;
174         assert(i64 != 0);
175         i64 <<= 1;
176         assert(i64 == 0);
177     }
178 
179     retval = krb5int_initialize_library();
180     if (retval)
181         return retval;
182 
183 #if (defined(_WIN32))
184     /*
185      * Load the krbcc32.dll if necessary.  We do this here so that
186      * we know to use API: later on during initialization.
187      * The context being NULL is ok.
188      */
189     krb5_win_ccdll_load(ctx);
190 
191     /*
192      * krb5_vercheck() is defined in win_glue.c, and this is
193      * where we handle the timebomb and version server checks.
194      */
195     retval = krb5_vercheck();
196     if (retval)
197         return retval;
198 #endif
199 
200     *context_out = NULL;
201 
202     ctx = calloc(1, sizeof(struct _krb5_context));
203     if (!ctx)
204         return ENOMEM;
205     ctx->magic = KV5M_CONTEXT;
206 
207     ctx->profile_secure = (flags & KRB5_INIT_CONTEXT_SECURE) != 0;
208 
209     retval = k5_os_init_context(ctx, profile, flags);
210     if (retval)
211         goto cleanup;
212 
213     ctx->trace_callback = NULL;
214 #ifndef DISABLE_TRACING
215     if (!ctx->profile_secure)
216         k5_init_trace(ctx);
217 #endif
218 
219     retval = get_boolean(ctx, KRB5_CONF_ALLOW_WEAK_CRYPTO, 0, &tmp);
220     if (retval)
221         goto cleanup;
222     ctx->allow_weak_crypto = tmp;
223 
224     retval = get_boolean(ctx, KRB5_CONF_ALLOW_DES3, 0, &tmp);
225     if (retval)
226         goto cleanup;
227     ctx->allow_des3 = tmp;
228 
229     retval = get_boolean(ctx, KRB5_CONF_ALLOW_RC4, 0, &tmp);
230     if (retval)
231         goto cleanup;
232     ctx->allow_rc4 = tmp;
233 
234     retval = get_boolean(ctx, KRB5_CONF_IGNORE_ACCEPTOR_HOSTNAME, 0, &tmp);
235     if (retval)
236         goto cleanup;
237     ctx->ignore_acceptor_hostname = tmp;
238 
239     retval = get_boolean(ctx, KRB5_CONF_ENFORCE_OK_AS_DELEGATE, 0, &tmp);
240     if (retval)
241         goto cleanup;
242     ctx->enforce_ok_as_delegate = tmp;
243 
244     retval = get_tristate(ctx, KRB5_CONF_DNS_CANONICALIZE_HOSTNAME, "fallback",
245                           CANONHOST_FALLBACK, 1, &tmp);
246     if (retval)
247         goto cleanup;
248     ctx->dns_canonicalize_hostname = tmp;
249 
250     ctx->default_realm = 0;
251     get_integer(ctx, KRB5_CONF_CLOCKSKEW, DEFAULT_CLOCKSKEW, &tmp);
252     ctx->clockskew = tmp;
253 
254     retval = profile_get_string(ctx->profile, KRB5_CONF_LIBDEFAULTS,
255                                 KRB5_CONF_REQUEST_TIMEOUT, NULL, NULL,
256                                 &timeout_str);
257     if (retval)
258         goto cleanup;
259     if (timeout_str != NULL) {
260         retval = krb5_string_to_deltat(timeout_str, &ctx->req_timeout);
261         if (retval)
262             goto cleanup;
263     }
264 
265     get_integer(ctx, KRB5_CONF_KDC_DEFAULT_OPTIONS, KDC_OPT_RENEWABLE_OK,
266                 &tmp);
267     ctx->kdc_default_options = tmp;
268 #define DEFAULT_KDC_TIMESYNC 1
269     get_integer(ctx, KRB5_CONF_KDC_TIMESYNC, DEFAULT_KDC_TIMESYNC, &tmp);
270     ctx->library_options = tmp ? KRB5_LIBOPT_SYNC_KDCTIME : 0;
271 
272     retval = profile_get_string(ctx->profile, KRB5_CONF_LIBDEFAULTS,
273                                 KRB5_CONF_PLUGIN_BASE_DIR, 0,
274                                 DEFAULT_PLUGIN_BASE_DIR, &plugin_dir);
275     if (!retval)
276         retval = k5_expand_path_tokens(ctx, plugin_dir, &ctx->plugin_base_dir);
277     if (retval) {
278         TRACE_PROFILE_ERR(ctx, KRB5_CONF_PLUGIN_BASE_DIR,
279                           KRB5_CONF_LIBDEFAULTS, retval);
280         goto cleanup;
281     }
282 
283     /*
284      * We use a default file credentials cache of 3.  See
285      * lib/krb5/krb/ccache/file/fcc.h for a description of the
286      * credentials cache types.
287      *
288      * Note: DCE 1.0.3a only supports a cache type of 1
289      *      DCE 1.1 supports a cache type of 2.
290      */
291 #define DEFAULT_CCACHE_TYPE 4
292     get_integer(ctx, KRB5_CONF_CCACHE_TYPE, DEFAULT_CCACHE_TYPE, &tmp);
293     ctx->fcc_default_format = tmp + 0x0500;
294     ctx->prompt_types = 0;
295     ctx->use_conf_ktypes = 0;
296     ctx->udp_pref_limit = -1;
297 
298     /* It's OK if this fails */
299     (void)profile_get_string(ctx->profile, KRB5_CONF_LIBDEFAULTS,
300                              KRB5_CONF_ERR_FMT, NULL, NULL, &ctx->err_fmt);
301     *context_out = ctx;
302     ctx = NULL;
303 
304 cleanup:
305     profile_release_string(plugin_dir);
306     profile_release_string(timeout_str);
307     krb5_free_context(ctx);
308     return retval;
309 }
310 
311 void KRB5_CALLCONV
krb5_free_context(krb5_context ctx)312 krb5_free_context(krb5_context ctx)
313 {
314     if (ctx == NULL)
315         return;
316     k5_os_free_context(ctx);
317 
318     free(ctx->tgs_etypes);
319     ctx->tgs_etypes = NULL;
320     free(ctx->default_realm);
321     ctx->default_realm = 0;
322 
323     krb5_clear_error_message(ctx);
324     free(ctx->err_fmt);
325 
326 #ifndef DISABLE_TRACING
327     if (ctx->trace_callback)
328         ctx->trace_callback(ctx, NULL, ctx->trace_callback_data);
329 #endif
330 
331     k5_ccselect_free_context(ctx);
332     k5_hostrealm_free_context(ctx);
333     k5_localauth_free_context(ctx);
334     k5_plugin_free_context(ctx);
335     free(ctx->plugin_base_dir);
336     free(ctx->tls);
337 
338     ctx->magic = 0;
339     free(ctx);
340 }
341 
342 /*
343  * Set the desired default ktypes, making sure they are valid.
344  */
345 krb5_error_code KRB5_CALLCONV
krb5_set_default_tgs_enctypes(krb5_context context,const krb5_enctype * etypes)346 krb5_set_default_tgs_enctypes(krb5_context context, const krb5_enctype *etypes)
347 {
348     krb5_error_code code;
349     krb5_enctype *list;
350     size_t src, dst;
351 
352     if (etypes) {
353         /* Empty list passed in. */
354         if (etypes[0] == 0)
355             return EINVAL;
356         code = k5_copy_etypes(etypes, &list);
357         if (code)
358             return code;
359 
360         /* Filter list in place to exclude invalid and (optionally) weak
361          * enctypes. */
362         for (src = dst = 0; list[src]; src++) {
363             if (!krb5_c_valid_enctype(list[src]))
364                 continue;
365             if (!context->allow_weak_crypto
366                 && krb5int_c_weak_enctype(list[src]))
367                 continue;
368             list[dst++] = list[src];
369         }
370         list[dst] = 0;          /* Zero-terminate. */
371         if (dst == 0) {
372             free(list);
373             return KRB5_CONFIG_ETYPE_NOSUPP;
374         }
375     } else {
376         list = NULL;
377     }
378 
379     free(context->tgs_etypes);
380     context->tgs_etypes = list;
381     return 0;
382 }
383 
384 /* Old name for above function.  This is not a public API, but Samba (as of
385  * 2021-02-12) uses this name if it finds it in the library. */
386 krb5_error_code
387 krb5_set_default_tgs_ktypes(krb5_context context, const krb5_enctype *etypes);
388 
389 krb5_error_code
krb5_set_default_tgs_ktypes(krb5_context context,const krb5_enctype * etypes)390 krb5_set_default_tgs_ktypes(krb5_context context, const krb5_enctype *etypes)
391 {
392     return krb5_set_default_tgs_enctypes(context, etypes);
393 }
394 
395 /*
396  * Add etype to, or remove etype from, the zero-terminated list *list_ptr,
397  * reallocating if the list size changes.  Filter out weak enctypes if
398  * allow_weak is false.  If memory allocation fails, set *list_ptr to NULL and
399  * do nothing for subsequent operations.
400  */
401 static void
mod_list(krb5_enctype etype,krb5_boolean add,krb5_boolean allow_weak,krb5_enctype ** list_ptr)402 mod_list(krb5_enctype etype, krb5_boolean add, krb5_boolean allow_weak,
403          krb5_enctype **list_ptr)
404 {
405     size_t i;
406     krb5_enctype *list = *list_ptr;
407 
408     /* Stop now if a previous allocation failed or the enctype is filtered. */
409     if (list == NULL || (!allow_weak && krb5int_c_weak_enctype(etype)))
410         return;
411     if (add) {
412         /* Count entries; do nothing if etype is a duplicate. */
413         for (i = 0; list[i] != 0; i++) {
414             if (list[i] == etype)
415                 return;
416         }
417         /* Make room for the new entry and add it. */
418         list = realloc(list, (i + 2) * sizeof(krb5_enctype));
419         if (list != NULL) {
420             list[i] = etype;
421             list[i + 1] = 0;
422         }
423     } else {
424         /* Look for etype in the list. */
425         for (i = 0; list[i] != 0; i++) {
426             if (list[i] != etype)
427                 continue;
428             /* Perform removal. */
429             for (; list[i + 1] != 0; i++)
430                 list[i] = list[i + 1];
431             list[i] = 0;
432             list = realloc(list, (i + 1) * sizeof(krb5_enctype));
433             break;
434         }
435     }
436     /* Update *list_ptr, freeing the old value if realloc failed. */
437     if (list == NULL)
438         free(*list_ptr);
439     *list_ptr = list;
440 }
441 
442 /*
443  * Set *result to a zero-terminated list of enctypes resulting from
444  * parsing profstr.  profstr may be modified during parsing.
445  */
446 krb5_error_code
krb5int_parse_enctype_list(krb5_context context,const char * profkey,char * profstr,krb5_enctype * default_list,krb5_enctype ** result)447 krb5int_parse_enctype_list(krb5_context context, const char *profkey,
448                            char *profstr, krb5_enctype *default_list,
449                            krb5_enctype **result)
450 {
451     char *token, *delim = " \t\r\n,", *save = NULL;
452     krb5_boolean sel, weak = context->allow_weak_crypto;
453     krb5_enctype etype, *list;
454     unsigned int i;
455 
456     *result = NULL;
457 
458     /* Set up an empty list.  Allocation failure is detected at the end. */
459     list = malloc(sizeof(krb5_enctype));
460     if (list != NULL)
461         list[0] = 0;
462 
463     /* Walk through the words in profstr. */
464     for (token = strtok_r(profstr, delim, &save); token;
465          token = strtok_r(NULL, delim, &save)) {
466         /* Determine if we are adding or removing enctypes. */
467         sel = TRUE;
468         if (*token == '+' || *token == '-')
469             sel = (*token++ == '+');
470 
471         if (strcasecmp(token, "DEFAULT") == 0) {
472             /* Set all enctypes in the default list. */
473             for (i = 0; default_list[i]; i++)
474                 mod_list(default_list[i], sel, weak, &list);
475         } else if (strcasecmp(token, "des3") == 0) {
476             mod_list(ENCTYPE_DES3_CBC_SHA1, sel, weak, &list);
477         } else if (strcasecmp(token, "aes") == 0) {
478             mod_list(ENCTYPE_AES256_CTS_HMAC_SHA1_96, sel, weak, &list);
479             mod_list(ENCTYPE_AES128_CTS_HMAC_SHA1_96, sel, weak, &list);
480             mod_list(ENCTYPE_AES256_CTS_HMAC_SHA384_192, sel, weak, &list);
481             mod_list(ENCTYPE_AES128_CTS_HMAC_SHA256_128, sel, weak, &list);
482         } else if (strcasecmp(token, "rc4") == 0) {
483             mod_list(ENCTYPE_ARCFOUR_HMAC, sel, weak, &list);
484         } else if (strcasecmp(token, "camellia") == 0) {
485             mod_list(ENCTYPE_CAMELLIA256_CTS_CMAC, sel, weak, &list);
486             mod_list(ENCTYPE_CAMELLIA128_CTS_CMAC, sel, weak, &list);
487         } else if (krb5_string_to_enctype(token, &etype) == 0) {
488             /* Set a specific enctype. */
489             mod_list(etype, sel, weak, &list);
490         } else {
491             TRACE_ENCTYPE_LIST_UNKNOWN(context, profkey, token);
492         }
493     }
494 
495     if (list == NULL)
496         return ENOMEM;
497     if (list[0] == ENCTYPE_NULL) {
498         free(list);
499         return KRB5_CONFIG_ETYPE_NOSUPP;
500     }
501     *result = list;
502     return 0;
503 }
504 
505 krb5_error_code
krb5_get_default_in_tkt_ktypes(krb5_context context,krb5_enctype ** ktypes)506 krb5_get_default_in_tkt_ktypes(krb5_context context, krb5_enctype **ktypes)
507 {
508     krb5_error_code ret;
509     char *profstr = NULL;
510     const char *profkey;
511 
512     *ktypes = NULL;
513 
514     profkey = KRB5_CONF_DEFAULT_TKT_ENCTYPES;
515     ret = profile_get_string(context->profile, KRB5_CONF_LIBDEFAULTS,
516                              profkey, NULL, NULL, &profstr);
517     if (ret)
518         return ret;
519     if (profstr == NULL) {
520         profkey = KRB5_CONF_PERMITTED_ENCTYPES;
521         ret = profile_get_string(context->profile, KRB5_CONF_LIBDEFAULTS,
522                                  profkey, NULL, "DEFAULT", &profstr);
523         if (ret)
524             return ret;
525     }
526 
527     ret = krb5int_parse_enctype_list(context, profkey, profstr,
528                                      default_enctype_list, ktypes);
529     profile_release_string(profstr);
530     return ret;
531 }
532 
533 void
534 KRB5_CALLCONV
krb5_free_enctypes(krb5_context context,krb5_enctype * val)535 krb5_free_enctypes(krb5_context context, krb5_enctype *val)
536 {
537     free (val);
538 }
539 
540 krb5_error_code KRB5_CALLCONV
krb5_get_tgs_ktypes(krb5_context context,krb5_const_principal princ,krb5_enctype ** ktypes)541 krb5_get_tgs_ktypes(krb5_context context, krb5_const_principal princ,
542                     krb5_enctype **ktypes)
543 {
544     krb5_error_code ret;
545     char *profstr = NULL;
546     const char *profkey;
547 
548     *ktypes = NULL;
549 
550     /* Use only profile configuration when use_conf_ktypes is set. */
551     if (!context->use_conf_ktypes && context->tgs_etypes != NULL)
552         return k5_copy_etypes(context->tgs_etypes, ktypes);
553 
554     profkey = KRB5_CONF_DEFAULT_TGS_ENCTYPES;
555     ret = profile_get_string(context->profile, KRB5_CONF_LIBDEFAULTS,
556                              profkey, NULL, NULL, &profstr);
557     if (ret)
558         return ret;
559     if (profstr == NULL) {
560         profkey = KRB5_CONF_PERMITTED_ENCTYPES;
561         ret = profile_get_string(context->profile, KRB5_CONF_LIBDEFAULTS,
562                                  profkey, NULL, "DEFAULT", &profstr);
563         if (ret)
564             return ret;
565     }
566 
567     ret = krb5int_parse_enctype_list(context, profkey, profstr,
568                                      default_enctype_list, ktypes);
569     profile_release_string(profstr);
570     return ret;
571 }
572 
573 krb5_error_code KRB5_CALLCONV
krb5_get_permitted_enctypes(krb5_context context,krb5_enctype ** ktypes)574 krb5_get_permitted_enctypes(krb5_context context, krb5_enctype **ktypes)
575 {
576     krb5_error_code ret;
577     char *profstr = NULL;
578     const char *profkey;
579 
580     *ktypes = NULL;
581 
582     if (context->tgs_etypes != NULL)
583         return k5_copy_etypes(context->tgs_etypes, ktypes);
584 
585     profkey = KRB5_CONF_PERMITTED_ENCTYPES;
586     ret = profile_get_string(context->profile, KRB5_CONF_LIBDEFAULTS,
587                              profkey, NULL, "DEFAULT", &profstr);
588     if (ret)
589         return ret;
590 
591     ret = krb5int_parse_enctype_list(context, profkey, profstr,
592                                      default_enctype_list, ktypes);
593     profile_release_string(profstr);
594     return ret;
595 }
596 
597 krb5_boolean
krb5_is_permitted_enctype(krb5_context context,krb5_enctype etype)598 krb5_is_permitted_enctype(krb5_context context, krb5_enctype etype)
599 {
600     krb5_enctype *list;
601     krb5_boolean ret;
602 
603     if (krb5_get_permitted_enctypes(context, &list))
604         return FALSE;
605     ret = k5_etypes_contains(list, etype);
606     krb5_free_enctypes(context, list);
607     return ret;
608 }
609