* Makefile.in (t_walk_rtree, t_kerb): Do not link against kdb libraries
[krb5.git] / src / lib / krb5 / krb / init_ctx.c
1 /*
2  * lib/krb5/krb/init_ctx.c
3  *
4  * Copyright 1994,1999,2000 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) 
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         "des3-cbc-sha1 " \
69         "des-cbc-crc des-cbc-md5 des-cbc-md4 "
70
71 #if (defined(_MSDOS) || defined(_WIN32))
72 extern krb5_error_code krb5_vercheck();
73 extern void krb5_win_ccdll_load(krb5_context context);
74 #endif
75
76 static krb5_error_code init_common (krb5_context *, krb5_boolean);
77
78 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
79 krb5_init_context(context)
80         krb5_context *context;
81 {
82
83         return init_common (context, FALSE);
84 }
85
86 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
87 krb5_init_secure_context(context)
88         krb5_context *context;
89 {
90
91         /* This is to make gcc -Wall happy */
92         if(0) krb5_brand[0] = krb5_brand[0];
93         return init_common (context, TRUE);
94 }
95
96 static krb5_error_code
97 init_common (context, secure)
98         krb5_context *context;
99         krb5_boolean secure;
100 {
101         krb5_context ctx = 0;
102         krb5_error_code retval;
103         struct {
104             krb5_int32 now, now_usec;
105             long pid;
106         } seed_data;
107         krb5_data seed;
108         int tmp;
109
110         /* Initialize error tables */
111         krb5_init_ets(ctx);
112
113 #if (defined(_MSDOS) || defined(_WIN32))
114         /* 
115          * Load the krbcc32.dll if necessary.  We do this here so that
116          * we know to use API: later on during initialization.
117          * The context being NULL is ok.
118          */
119         krb5_win_ccdll_load(ctx);
120
121         /*
122          * krb5_vercheck() is defined in win_glue.c, and this is
123          * where we handle the timebomb and version server checks.
124          */
125         retval = krb5_vercheck();
126         if (retval)
127                 return retval;
128 #else /* assume UNIX for now */
129         krb5int_initialize_library ();
130 #endif
131
132         *context = 0;
133
134         ctx = malloc(sizeof(struct _krb5_context));
135         if (!ctx)
136                 return ENOMEM;
137         memset(ctx, 0, sizeof(struct _krb5_context));
138         ctx->magic = KV5M_CONTEXT;
139
140         ctx->profile_secure = secure;
141
142         /* Set the default encryption types, possible defined in krb5/conf */
143         if ((retval = krb5_set_default_in_tkt_ktypes(ctx, NULL)))
144                 goto cleanup;
145
146         if ((retval = krb5_set_default_tgs_ktypes(ctx, NULL)))
147                 goto cleanup;
148
149         if ((retval = krb5_os_init_context(ctx)))
150                 goto cleanup;
151
152         /* initialize the prng (not well, but passable) */
153         if ((retval = krb5_crypto_us_timeofday(&seed_data.now, &seed_data.now_usec)))
154                 goto cleanup;
155         seed_data.pid = getpid ();
156         seed.length = sizeof(seed_data);
157         seed.data = (char *) &seed_data;
158         if ((retval = krb5_c_random_seed(ctx, &seed)))
159                 goto cleanup;
160
161         ctx->default_realm = 0;
162         profile_get_integer(ctx->profile, "libdefaults", "clockskew",
163                             0, 5 * 60, &tmp);
164         ctx->clockskew = tmp;
165
166 #if 0
167         /* Default ticket lifetime is currently not supported */
168         profile_get_integer(ctx->profile, "libdefaults", "tkt_lifetime",
169                             0, 10 * 60 * 60, &tmp);
170         ctx->tkt_lifetime = tmp;
171 #endif
172
173         /* DCE 1.1 and below only support CKSUMTYPE_RSA_MD4 (2)  */
174         /* DCE add kdc_req_checksum_type = 2 to krb5.conf */
175         profile_get_integer(ctx->profile, "libdefaults",
176                             "kdc_req_checksum_type", 0, CKSUMTYPE_RSA_MD5, 
177                             &tmp);
178         ctx->kdc_req_sumtype = tmp;
179
180         profile_get_integer(ctx->profile, "libdefaults",
181                             "ap_req_checksum_type", 0, CKSUMTYPE_RSA_MD5,
182                             &tmp);
183         ctx->default_ap_req_sumtype = tmp;
184
185         profile_get_integer(ctx->profile, "libdefaults",
186                             "safe_checksum_type", 0,
187                             CKSUMTYPE_RSA_MD5_DES, &tmp);
188         ctx->default_safe_sumtype = tmp;
189
190         profile_get_integer(ctx->profile, "libdefaults",
191                             "kdc_default_options", 0,
192                             KDC_OPT_RENEWABLE_OK, &tmp);
193         ctx->kdc_default_options = KDC_OPT_RENEWABLE_OK;
194 #ifdef macintosh
195 #define DEFAULT_KDC_TIMESYNC 1
196 #else
197 #define DEFAULT_KDC_TIMESYNC 0
198 #endif
199         profile_get_integer(ctx->profile, "libdefaults",
200                             "kdc_timesync", 0, DEFAULT_KDC_TIMESYNC,
201                             &tmp);
202         ctx->library_options = tmp ? KRB5_LIBOPT_SYNC_KDCTIME : 0;
203
204         /*
205          * We use a default file credentials cache of 3.  See
206          * lib/krb5/krb/ccache/file/fcc.h for a description of the
207          * credentials cache types.
208          *
209          * Note: DCE 1.0.3a only supports a cache type of 1
210          *      DCE 1.1 supports a cache type of 2.
211          */
212 #ifdef macintosh
213 #define DEFAULT_CCACHE_TYPE 4
214 #else
215 #define DEFAULT_CCACHE_TYPE 3
216 #endif
217         profile_get_integer(ctx->profile, "libdefaults", "ccache_type",
218                             0, DEFAULT_CCACHE_TYPE, &tmp);
219         ctx->fcc_default_format = tmp + 0x0500;
220         ctx->scc_default_format = tmp + 0x0500;
221         ctx->prompt_types = 0;
222         *context = ctx;
223         return 0;
224
225 cleanup:
226         krb5_free_context(ctx);
227         return retval;
228 }
229
230 KRB5_DLLIMP void KRB5_CALLCONV
231 krb5_free_context(ctx)
232         krb5_context    ctx;
233 {
234      krb5_free_ets(ctx);
235      krb5_os_free_context(ctx);
236
237      if (ctx->in_tkt_ktypes) {
238           free(ctx->in_tkt_ktypes);
239           ctx->in_tkt_ktypes = 0;
240      }
241
242      if (ctx->tgs_ktypes) {
243           free(ctx->tgs_ktypes);
244           ctx->tgs_ktypes = 0;
245      }
246
247      if (ctx->default_realm) {
248           free(ctx->default_realm);
249           ctx->default_realm = 0;
250      }
251
252      if (ctx->ser_ctx_count && ctx->ser_ctx) {
253           free(ctx->ser_ctx);
254           ctx->ser_ctx = 0;
255      }
256
257      ctx->magic = 0;
258      free(ctx);
259 }
260
261 /*
262  * Set the desired default ktypes, making sure they are valid.
263  */
264 krb5_error_code
265 krb5_set_default_in_tkt_ktypes(context, ktypes)
266         krb5_context context;
267         const krb5_enctype *ktypes;
268 {
269     krb5_enctype * new_ktypes;
270     int i;
271
272     if (ktypes) {
273         for (i = 0; ktypes[i]; i++) {
274             if (!valid_enctype(ktypes[i])) 
275                 return KRB5_PROG_ETYPE_NOSUPP;
276         }
277
278         /* Now copy the default ktypes into the context pointer */
279         if ((new_ktypes = (krb5_enctype *)malloc(sizeof(krb5_enctype) * i)))
280             memcpy(new_ktypes, ktypes, sizeof(krb5_enctype) * i);
281         else
282             return ENOMEM;
283
284     } else {
285         i = 0;
286         new_ktypes = 0;
287     }
288
289     if (context->in_tkt_ktypes) 
290         free(context->in_tkt_ktypes);
291     context->in_tkt_ktypes = new_ktypes;
292     context->in_tkt_ktype_count = i;
293     return 0;
294 }
295
296 static krb5_error_code
297 get_profile_etype_list(context, ktypes, profstr, ctx_count, ctx_list)
298      krb5_context context;
299      krb5_enctype **ktypes;
300      char *profstr;
301      int ctx_count;
302      krb5_enctype FAR *ctx_list;
303 {
304     krb5_enctype *old_ktypes;
305
306     if (ctx_count) {
307         /* application-set defaults */
308         if ((old_ktypes = 
309              (krb5_enctype *)malloc(sizeof(krb5_enctype) *
310                                     (ctx_count + 1)))) {
311             memcpy(old_ktypes, ctx_list, sizeof(krb5_enctype) * ctx_count);
312             old_ktypes[ctx_count] = 0;
313         } else {
314             return ENOMEM;
315         }
316     } else {
317         /*
318            XXX - For now, we only support libdefaults
319            Perhaps this should be extended to allow for per-host / per-realm
320            session key types.
321          */
322
323         char *retval;
324         char *sp, *ep;
325         int i, j, count;
326         krb5_error_code code;
327
328         code = profile_get_string(context->profile, "libdefaults", profstr,
329                                   NULL, DEFAULT_ETYPE_LIST, &retval);
330         if (code)
331             return code;
332
333         count = 0;
334         sp = retval;
335         while (sp) {
336             for (ep = sp; *ep && (*ep != ',') && !isspace((int) (*ep)); ep++)
337                 ;
338             if (*ep) {
339                 *ep++ = '\0';
340                 while (isspace((int) (*ep)) || *ep == ',')
341                     *ep++ = '\0';
342             } else
343                 ep = (char *) NULL;
344
345             count++;
346             sp = ep;
347         }
348         
349         if ((old_ktypes =
350              (krb5_enctype *)malloc(sizeof(krb5_enctype) * (count + 1))) ==
351             (krb5_enctype *) NULL)
352             return ENOMEM;
353         
354         sp = retval;
355         j = 0;
356         i = 1;
357         while (1) {
358             if (! krb5_string_to_enctype(sp, &old_ktypes[j]))
359                 j++;
360
361             if (i++ >= count)
362                 break;
363
364             /* skip to next token */
365             while (*sp) sp++;
366             while (! *sp) sp++;
367         }
368
369         old_ktypes[j] = (krb5_enctype) 0;
370         profile_release_string(retval);
371     }
372
373     if (old_ktypes[0] == 0) {
374         free (old_ktypes);
375         *ktypes = 0;
376         return KRB5_CONFIG_ETYPE_NOSUPP;
377     }
378
379     *ktypes = old_ktypes;
380     return 0;
381 }
382
383 krb5_error_code
384 krb5_get_default_in_tkt_ktypes(context, ktypes)
385     krb5_context context;
386     krb5_enctype **ktypes;
387 {
388     return(get_profile_etype_list(context, ktypes, "default_tkt_enctypes",
389                                   context->in_tkt_ktype_count,
390                                   context->in_tkt_ktypes));
391 }
392
393 krb5_error_code
394 krb5_set_default_tgs_ktypes(context, ktypes)
395         krb5_context context;
396         const krb5_enctype *ktypes;
397 {
398     krb5_enctype * new_ktypes;
399     int i;
400
401     if (ktypes) {
402         for (i = 0; ktypes[i]; i++) {
403             if (!valid_enctype(ktypes[i])) 
404                 return KRB5_PROG_ETYPE_NOSUPP;
405         }
406
407         /* Now copy the default ktypes into the context pointer */
408         if ((new_ktypes = (krb5_enctype *)malloc(sizeof(krb5_enctype) * i)))
409             memcpy(new_ktypes, ktypes, sizeof(krb5_enctype) * i);
410         else
411             return ENOMEM;
412
413     } else {
414         i = 0;
415         new_ktypes = (krb5_enctype *)NULL;
416     }
417
418     if (context->tgs_ktypes) 
419         krb5_free_ktypes(context, context->tgs_ktypes);
420     context->tgs_ktypes = new_ktypes;
421     context->tgs_ktype_count = i;
422     return 0;
423 }
424
425 void
426 KRB5_CALLCONV
427 krb5_free_ktypes (context, val)
428      krb5_context context;
429      krb5_enctype FAR *val;
430 {
431     free (val);
432 }
433
434 krb5_error_code
435 KRB5_CALLCONV
436 krb5_get_tgs_ktypes(context, princ, ktypes)
437     krb5_context context;
438     krb5_const_principal princ;
439     krb5_enctype **ktypes;
440 {
441     return(get_profile_etype_list(context, ktypes, "default_tgs_enctypes",
442                                   context->tgs_ktype_count,
443                                   context->tgs_ktypes));
444 }
445
446 krb5_error_code
447 krb5_get_permitted_enctypes(context, ktypes)
448     krb5_context context;
449     krb5_enctype **ktypes;
450 {
451     return(get_profile_etype_list(context, ktypes, "permitted_enctypes",
452                                   context->tgs_ktype_count,
453                                   context->tgs_ktypes));
454 }
455
456 krb5_boolean
457 krb5_is_permitted_enctype(context, etype)
458      krb5_context context;
459      krb5_enctype etype;
460 {
461     krb5_enctype *list, *ptr;
462     krb5_boolean ret;
463
464     if (krb5_get_permitted_enctypes(context, &list))
465         return(0);
466
467     
468     ret = 0;
469
470     for (ptr = list; *ptr; ptr++)
471         if (*ptr == etype)
472             ret = 1;
473
474     krb5_free_ktypes (context, list);
475
476     return(ret);
477 }