3cbf99e5b8a7dd32335aa7e81fbc59e159077d31
[krb5.git] / src / lib / krb5 / krb / init_ctx.c
1 /*
2  * lib/krb5/krb/init_ctx.c
3  *
4  * Copyright 1994,1999,2000, 2002, 2003  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  * krb5_init_contex()
27  */
28
29 /*
30  * Copyright (C) 1998 by the FundsXpress, INC.
31  * 
32  * All rights reserved.
33  * 
34  * Export of this software from the United States of America may require
35  * a specific license from the United States Government.  It is the
36  * responsibility of any person or organization contemplating export to
37  * obtain such a license before exporting.
38  * 
39  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
40  * distribute this software and its documentation for any purpose and
41  * without fee is hereby granted, provided that the above copyright
42  * notice appear in all copies and that both that copyright notice and
43  * this permission notice appear in supporting documentation, and that
44  * the name of FundsXpress. not be used in advertising or publicity pertaining
45  * to distribution of the software without specific, written prior
46  * permission.  FundsXpress makes no representations about the suitability of
47  * this software for any purpose.  It is provided "as is" without express
48  * or implied warranty.
49  * 
50  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
51  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
52  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
53  */
54
55 #include "k5-int.h"
56 #include <ctype.h>
57 #include "brand.c"
58 /* There has to be a better way for windows... */
59 #if defined(unix) || TARGET_OS_MAC
60 #include "../krb5_libinit.h"
61 #endif
62
63 /* The des-mdX entries are last for now, because it's easy to
64    configure KDCs to issue TGTs with des-mdX keys and then not accept
65    them.  This'll be fixed, but for better compatibility, let's prefer
66    des-crc for now.  */
67 #define DEFAULT_ETYPE_LIST      \
68         "aes256-cts-hmac-sha1-96 " \
69         "aes128-cts-hmac-sha1-96 " \
70         "des3-cbc-sha1 arcfour-hmac-md5 " \
71         "des-cbc-crc des-cbc-md5 des-cbc-md4 "
72
73 /* Not included:
74         "aes128-cts-hmac-sha1-96 " \
75  */
76
77 #if (defined(_WIN32))
78 extern krb5_error_code krb5_vercheck();
79 extern void krb5_win_ccdll_load(krb5_context context);
80 #endif
81
82 static krb5_error_code init_common (krb5_context *, krb5_boolean);
83
84 krb5_error_code KRB5_CALLCONV
85 krb5_init_context(krb5_context *context)
86 {
87
88         return init_common (context, FALSE);
89 }
90
91 krb5_error_code KRB5_CALLCONV
92 krb5_init_secure_context(krb5_context *context)
93 {
94
95         /* This is to make gcc -Wall happy */
96         if(0) krb5_brand[0] = krb5_brand[0];
97         return init_common (context, TRUE);
98 }
99
100 static krb5_error_code
101 init_common (krb5_context *context, krb5_boolean secure)
102 {
103         krb5_context ctx = 0;
104         krb5_error_code retval;
105         struct {
106             krb5_int32 now, now_usec;
107             long pid;
108         } seed_data;
109         krb5_data seed;
110         int tmp;
111
112         /* Verify some assumptions.  If the assumptions hold and the
113            compiler is optimizing, this should result in no code being
114            executed.  If we're guessing "unsigned long long" instead
115            of using uint64_t, the possibility does exist that we're
116            wrong.  */
117         {
118             krb5_ui_8 i64;
119             assert(sizeof(i64) == 8);
120             i64 = 0, i64--, i64 >>= 62;
121             assert(i64 == 3);
122             i64 = 1, i64 <<= 31, i64 <<= 31, i64 <<= 1;
123             assert(i64 != 0);
124             i64 <<= 1;
125             assert(i64 == 0);
126         }
127
128         retval = krb5int_initialize_library();
129         if (retval)
130             return retval;
131
132 #if (defined(_WIN32))
133         /* 
134          * Load the krbcc32.dll if necessary.  We do this here so that
135          * we know to use API: later on during initialization.
136          * The context being NULL is ok.
137          */
138         krb5_win_ccdll_load(ctx);
139
140         /*
141          * krb5_vercheck() is defined in win_glue.c, and this is
142          * where we handle the timebomb and version server checks.
143          */
144         retval = krb5_vercheck();
145         if (retval)
146                 return retval;
147 #endif
148
149         *context = 0;
150
151         ctx = malloc(sizeof(struct _krb5_context));
152         if (!ctx)
153                 return ENOMEM;
154         memset(ctx, 0, sizeof(struct _krb5_context));
155         ctx->magic = KV5M_CONTEXT;
156
157         ctx->profile_secure = secure;
158
159         /* Set the default encryption types, possible defined in krb5/conf */
160         if ((retval = krb5_set_default_in_tkt_ktypes(ctx, NULL)))
161                 goto cleanup;
162
163         if ((retval = krb5_set_default_tgs_ktypes(ctx, NULL)))
164                 goto cleanup;
165
166         ctx->conf_tgs_ktypes = calloc(ctx->tgs_ktype_count, sizeof(krb5_enctype));
167         if (ctx->conf_tgs_ktypes == NULL && ctx->tgs_ktype_count != 0)
168             goto cleanup;
169         memcpy(ctx->conf_tgs_ktypes, ctx->tgs_ktypes,
170                sizeof(krb5_enctype) * ctx->tgs_ktype_count);
171         ctx->conf_tgs_ktypes_count = ctx->tgs_ktype_count;
172
173         if ((retval = krb5_os_init_context(ctx)))
174                 goto cleanup;
175
176         /* initialize the prng (not well, but passable) */
177         if ((retval = krb5_c_random_os_entropy( ctx, 0, NULL)) !=0)
178           goto cleanup;
179         if ((retval = krb5_crypto_us_timeofday(&seed_data.now, &seed_data.now_usec)))
180                 goto cleanup;
181         seed_data.pid = getpid ();
182         seed.length = sizeof(seed_data);
183         seed.data = (char *) &seed_data;
184         if ((retval = krb5_c_random_add_entropy(ctx, KRB5_C_RANDSOURCE_TIMING, &seed)))
185                 goto cleanup;
186
187         ctx->default_realm = 0;
188         profile_get_integer(ctx->profile, "libdefaults", "clockskew",
189                             0, 5 * 60, &tmp);
190         ctx->clockskew = tmp;
191
192 #if 0
193         /* Default ticket lifetime is currently not supported */
194         profile_get_integer(ctx->profile, "libdefaults", "tkt_lifetime",
195                             0, 10 * 60 * 60, &tmp);
196         ctx->tkt_lifetime = tmp;
197 #endif
198
199         /* DCE 1.1 and below only support CKSUMTYPE_RSA_MD4 (2)  */
200         /* DCE add kdc_req_checksum_type = 2 to krb5.conf */
201         profile_get_integer(ctx->profile, "libdefaults",
202                             "kdc_req_checksum_type", 0, CKSUMTYPE_RSA_MD5, 
203                             &tmp);
204         ctx->kdc_req_sumtype = tmp;
205
206         profile_get_integer(ctx->profile, "libdefaults",
207                             "ap_req_checksum_type", 0, CKSUMTYPE_RSA_MD5,
208                             &tmp);
209         ctx->default_ap_req_sumtype = tmp;
210
211         profile_get_integer(ctx->profile, "libdefaults",
212                             "safe_checksum_type", 0,
213                             CKSUMTYPE_RSA_MD5_DES, &tmp);
214         ctx->default_safe_sumtype = tmp;
215
216         profile_get_integer(ctx->profile, "libdefaults",
217                             "kdc_default_options", 0,
218                             KDC_OPT_RENEWABLE_OK, &tmp);
219         ctx->kdc_default_options = tmp;
220 #define DEFAULT_KDC_TIMESYNC 1
221         profile_get_integer(ctx->profile, "libdefaults",
222                             "kdc_timesync", 0, DEFAULT_KDC_TIMESYNC,
223                             &tmp);
224         ctx->library_options = tmp ? KRB5_LIBOPT_SYNC_KDCTIME : 0;
225
226         /*
227          * We use a default file credentials cache of 3.  See
228          * lib/krb5/krb/ccache/file/fcc.h for a description of the
229          * credentials cache types.
230          *
231          * Note: DCE 1.0.3a only supports a cache type of 1
232          *      DCE 1.1 supports a cache type of 2.
233          */
234 #define DEFAULT_CCACHE_TYPE 4
235         profile_get_integer(ctx->profile, "libdefaults", "ccache_type",
236                             0, DEFAULT_CCACHE_TYPE, &tmp);
237         ctx->fcc_default_format = tmp + 0x0500;
238         ctx->scc_default_format = tmp + 0x0500;
239         ctx->prompt_types = 0;
240         ctx->use_conf_ktypes = 0;
241
242         ctx->udp_pref_limit = -1;
243         *context = ctx;
244         return 0;
245
246 cleanup:
247         krb5_free_context(ctx);
248         return retval;
249 }
250
251 void KRB5_CALLCONV
252 krb5_free_context(krb5_context ctx)
253 {
254      krb5_os_free_context(ctx);
255
256      if (ctx->in_tkt_ktypes) {
257           free(ctx->in_tkt_ktypes);
258           ctx->in_tkt_ktypes = 0;
259      }
260
261      if (ctx->tgs_ktypes) {
262           free(ctx->tgs_ktypes);
263           ctx->tgs_ktypes = 0;
264      }
265
266      if (ctx->conf_tgs_ktypes) {
267          free(ctx->conf_tgs_ktypes);
268          ctx->conf_tgs_ktypes = 0;
269      }
270
271      if (ctx->default_realm) {
272           free(ctx->default_realm);
273           ctx->default_realm = 0;
274      }
275
276      if (ctx->ser_ctx_count && ctx->ser_ctx) {
277           free(ctx->ser_ctx);
278           ctx->ser_ctx = 0;
279      }
280
281      ctx->magic = 0;
282      free(ctx);
283 }
284
285 /*
286  * Set the desired default ktypes, making sure they are valid.
287  */
288 krb5_error_code
289 krb5_set_default_in_tkt_ktypes(krb5_context context, const krb5_enctype *ktypes)
290 {
291     krb5_enctype * new_ktypes;
292     int i;
293
294     if (ktypes) {
295         for (i = 0; ktypes[i]; i++) {
296             if (!krb5_c_valid_enctype(ktypes[i])) 
297                 return KRB5_PROG_ETYPE_NOSUPP;
298         }
299
300         /* Now copy the default ktypes into the context pointer */
301         if ((new_ktypes = (krb5_enctype *)malloc(sizeof(krb5_enctype) * i)))
302             memcpy(new_ktypes, ktypes, sizeof(krb5_enctype) * i);
303         else
304             return ENOMEM;
305
306     } else {
307         i = 0;
308         new_ktypes = 0;
309     }
310
311     if (context->in_tkt_ktypes) 
312         free(context->in_tkt_ktypes);
313     context->in_tkt_ktypes = new_ktypes;
314     context->in_tkt_ktype_count = i;
315     return 0;
316 }
317
318 static krb5_error_code
319 get_profile_etype_list(krb5_context context, krb5_enctype **ktypes, char *profstr,
320                        int ctx_count, krb5_enctype *ctx_list)
321 {
322     krb5_enctype *old_ktypes;
323
324     if (ctx_count) {
325         /* application-set defaults */
326         if ((old_ktypes = 
327              (krb5_enctype *)malloc(sizeof(krb5_enctype) *
328                                     (ctx_count + 1)))) {
329             memcpy(old_ktypes, ctx_list, sizeof(krb5_enctype) * ctx_count);
330             old_ktypes[ctx_count] = 0;
331         } else {
332             return ENOMEM;
333         }
334     } else {
335         /*
336            XXX - For now, we only support libdefaults
337            Perhaps this should be extended to allow for per-host / per-realm
338            session key types.
339          */
340
341         char *retval;
342         char *sp, *ep;
343         int i, j, count;
344         krb5_error_code code;
345
346         code = profile_get_string(context->profile, "libdefaults", profstr,
347                                   NULL, DEFAULT_ETYPE_LIST, &retval);
348         if (code)
349             return code;
350
351         count = 0;
352         sp = retval;
353         while (*sp) {
354             for (ep = sp; *ep && (*ep != ',') && !isspace((int) (*ep)); ep++)
355                 ;
356             if (*ep) {
357                 *ep++ = '\0';
358                 while (isspace((int) (*ep)) || *ep == ',')
359                     *ep++ = '\0';
360             }
361             count++;
362             sp = ep;
363         }
364         
365         if ((old_ktypes =
366              (krb5_enctype *)malloc(sizeof(krb5_enctype) * (count + 1))) ==
367             (krb5_enctype *) NULL)
368             return ENOMEM;
369         
370         sp = retval;
371         j = 0;
372         i = 1;
373         while (1) {
374             if (! krb5_string_to_enctype(sp, &old_ktypes[j]))
375                 j++;
376
377             if (i++ >= count)
378                 break;
379
380             /* skip to next token */
381             while (*sp) sp++;
382             while (! *sp) sp++;
383         }
384
385         old_ktypes[j] = (krb5_enctype) 0;
386         profile_release_string(retval);
387     }
388
389     if (old_ktypes[0] == 0) {
390         free (old_ktypes);
391         *ktypes = 0;
392         return KRB5_CONFIG_ETYPE_NOSUPP;
393     }
394
395     *ktypes = old_ktypes;
396     return 0;
397 }
398
399 krb5_error_code
400 krb5_get_default_in_tkt_ktypes(krb5_context context, krb5_enctype **ktypes)
401 {
402     return(get_profile_etype_list(context, ktypes, "default_tkt_enctypes",
403                                   context->in_tkt_ktype_count,
404                                   context->in_tkt_ktypes));
405 }
406
407 krb5_error_code KRB5_CALLCONV
408 krb5_set_default_tgs_enctypes (krb5_context context, const krb5_enctype *ktypes)
409 {
410     krb5_enctype * new_ktypes;
411     int i;
412
413     if (ktypes) {
414         for (i = 0; ktypes[i]; i++) {
415             if (!krb5_c_valid_enctype(ktypes[i])) 
416                 return KRB5_PROG_ETYPE_NOSUPP;
417         }
418
419         /* Now copy the default ktypes into the context pointer */
420         if ((new_ktypes = (krb5_enctype *)malloc(sizeof(krb5_enctype) * i)))
421             memcpy(new_ktypes, ktypes, sizeof(krb5_enctype) * i);
422         else
423             return ENOMEM;
424
425     } else {
426         i = 0;
427         new_ktypes = (krb5_enctype *)NULL;
428     }
429
430     if (context->tgs_ktypes) 
431         krb5_free_ktypes(context, context->tgs_ktypes);
432     context->tgs_ktypes = new_ktypes;
433     context->tgs_ktype_count = i;
434     return 0;
435 }
436
437 krb5_error_code krb5_set_default_tgs_ktypes
438 (krb5_context context, const krb5_enctype *etypes)
439 {
440   return (krb5_set_default_tgs_enctypes (context, etypes));
441 }
442
443
444 void
445 KRB5_CALLCONV
446 krb5_free_ktypes (krb5_context context, krb5_enctype *val)
447 {
448     free (val);
449 }
450
451 krb5_error_code
452 KRB5_CALLCONV
453 krb5_get_tgs_ktypes(krb5_context context, krb5_const_principal princ, krb5_enctype **ktypes)
454 {
455     if (context->use_conf_ktypes)
456         /* This one is set *only* by reading the config file; it's not
457            set by the application.  */
458         return(get_profile_etype_list(context, ktypes, "default_tgs_enctypes",
459                                       context->conf_tgs_ktypes_count,
460                                       context->conf_tgs_ktypes));
461     else
462         return(get_profile_etype_list(context, ktypes, "default_tgs_enctypes",
463                                       context->tgs_ktype_count,
464                                       context->tgs_ktypes));
465 }
466
467 krb5_error_code KRB5_CALLCONV
468 krb5_get_permitted_enctypes(krb5_context context, krb5_enctype **ktypes)
469 {
470     return(get_profile_etype_list(context, ktypes, "permitted_enctypes",
471                                   context->tgs_ktype_count,
472                                   context->tgs_ktypes));
473 }
474
475 krb5_boolean
476 krb5_is_permitted_enctype(krb5_context context, krb5_enctype etype)
477 {
478     krb5_enctype *list, *ptr;
479     krb5_boolean ret;
480
481     if (krb5_get_permitted_enctypes(context, &list))
482         return(0);
483
484     
485     ret = 0;
486
487     for (ptr = list; *ptr; ptr++)
488         if (*ptr == etype)
489             ret = 1;
490
491     krb5_free_ktypes (context, list);
492
493     return(ret);
494 }