call krb5_c_ versions of enctype/cksumtype checking routines
[krb5.git] / src / lib / krb5 / krb / init_ctx.c
1 /*
2  * lib/krb5/krb/init_ctx.c
3  *
4  * Copyright 1994,1999,2000, 2002  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 arcfour-hmac-md5 " \
69         "des-cbc-crc des-cbc-md5 des-cbc-md4 "
70
71 #if (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_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_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(_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_c_random_os_entropy( ctx, 0, NULL)) !=0)
154           goto cleanup;
155         if ((retval = krb5_crypto_us_timeofday(&seed_data.now, &seed_data.now_usec)))
156                 goto cleanup;
157         seed_data.pid = getpid ();
158         seed.length = sizeof(seed_data);
159         seed.data = (char *) &seed_data;
160         if ((retval = krb5_c_random_add_entropy(ctx, KRB5_C_RANDSOURCE_TIMING, &seed)))
161                 goto cleanup;
162
163         ctx->default_realm = 0;
164         profile_get_integer(ctx->profile, "libdefaults", "clockskew",
165                             0, 5 * 60, &tmp);
166         ctx->clockskew = tmp;
167
168 #if 0
169         /* Default ticket lifetime is currently not supported */
170         profile_get_integer(ctx->profile, "libdefaults", "tkt_lifetime",
171                             0, 10 * 60 * 60, &tmp);
172         ctx->tkt_lifetime = tmp;
173 #endif
174
175         /* DCE 1.1 and below only support CKSUMTYPE_RSA_MD4 (2)  */
176         /* DCE add kdc_req_checksum_type = 2 to krb5.conf */
177         profile_get_integer(ctx->profile, "libdefaults",
178                             "kdc_req_checksum_type", 0, CKSUMTYPE_RSA_MD5, 
179                             &tmp);
180         ctx->kdc_req_sumtype = tmp;
181
182         profile_get_integer(ctx->profile, "libdefaults",
183                             "ap_req_checksum_type", 0, CKSUMTYPE_RSA_MD5,
184                             &tmp);
185         ctx->default_ap_req_sumtype = tmp;
186
187         profile_get_integer(ctx->profile, "libdefaults",
188                             "safe_checksum_type", 0,
189                             CKSUMTYPE_RSA_MD5_DES, &tmp);
190         ctx->default_safe_sumtype = tmp;
191
192         profile_get_integer(ctx->profile, "libdefaults",
193                             "kdc_default_options", 0,
194                             KDC_OPT_RENEWABLE_OK, &tmp);
195         ctx->kdc_default_options = tmp;
196 #ifdef macintosh
197 #define DEFAULT_KDC_TIMESYNC 1
198 #else
199 #define DEFAULT_KDC_TIMESYNC 0
200 #endif
201         profile_get_integer(ctx->profile, "libdefaults",
202                             "kdc_timesync", 0, DEFAULT_KDC_TIMESYNC,
203                             &tmp);
204         ctx->library_options = tmp ? KRB5_LIBOPT_SYNC_KDCTIME : 0;
205
206         /*
207          * We use a default file credentials cache of 3.  See
208          * lib/krb5/krb/ccache/file/fcc.h for a description of the
209          * credentials cache types.
210          *
211          * Note: DCE 1.0.3a only supports a cache type of 1
212          *      DCE 1.1 supports a cache type of 2.
213          */
214 #ifdef macintosh
215 #define DEFAULT_CCACHE_TYPE 4
216 #else
217 #define DEFAULT_CCACHE_TYPE 3
218 #endif
219         profile_get_integer(ctx->profile, "libdefaults", "ccache_type",
220                             0, DEFAULT_CCACHE_TYPE, &tmp);
221         ctx->fcc_default_format = tmp + 0x0500;
222         ctx->scc_default_format = tmp + 0x0500;
223         ctx->prompt_types = 0;
224         *context = ctx;
225         return 0;
226
227 cleanup:
228         krb5_free_context(ctx);
229         return retval;
230 }
231
232 void KRB5_CALLCONV
233 krb5_free_context(ctx)
234         krb5_context    ctx;
235 {
236      krb5_free_ets(ctx);
237      krb5_os_free_context(ctx);
238
239      if (ctx->in_tkt_ktypes) {
240           free(ctx->in_tkt_ktypes);
241           ctx->in_tkt_ktypes = 0;
242      }
243
244      if (ctx->tgs_ktypes) {
245           free(ctx->tgs_ktypes);
246           ctx->tgs_ktypes = 0;
247      }
248
249      if (ctx->default_realm) {
250           free(ctx->default_realm);
251           ctx->default_realm = 0;
252      }
253
254      if (ctx->ser_ctx_count && ctx->ser_ctx) {
255           free(ctx->ser_ctx);
256           ctx->ser_ctx = 0;
257      }
258
259      ctx->magic = 0;
260      free(ctx);
261 }
262
263 /*
264  * Set the desired default ktypes, making sure they are valid.
265  */
266 krb5_error_code
267 krb5_set_default_in_tkt_ktypes(context, ktypes)
268         krb5_context context;
269         const krb5_enctype *ktypes;
270 {
271     krb5_enctype * new_ktypes;
272     int i;
273
274     if (ktypes) {
275         for (i = 0; ktypes[i]; i++) {
276             if (!krb5_c_valid_enctype(ktypes[i])) 
277                 return KRB5_PROG_ETYPE_NOSUPP;
278         }
279
280         /* Now copy the default ktypes into the context pointer */
281         if ((new_ktypes = (krb5_enctype *)malloc(sizeof(krb5_enctype) * i)))
282             memcpy(new_ktypes, ktypes, sizeof(krb5_enctype) * i);
283         else
284             return ENOMEM;
285
286     } else {
287         i = 0;
288         new_ktypes = 0;
289     }
290
291     if (context->in_tkt_ktypes) 
292         free(context->in_tkt_ktypes);
293     context->in_tkt_ktypes = new_ktypes;
294     context->in_tkt_ktype_count = i;
295     return 0;
296 }
297
298 static krb5_error_code
299 get_profile_etype_list(context, ktypes, profstr, ctx_count, ctx_list)
300      krb5_context context;
301      krb5_enctype **ktypes;
302      char *profstr;
303      int ctx_count;
304      krb5_enctype *ctx_list;
305 {
306     krb5_enctype *old_ktypes;
307
308     if (ctx_count) {
309         /* application-set defaults */
310         if ((old_ktypes = 
311              (krb5_enctype *)malloc(sizeof(krb5_enctype) *
312                                     (ctx_count + 1)))) {
313             memcpy(old_ktypes, ctx_list, sizeof(krb5_enctype) * ctx_count);
314             old_ktypes[ctx_count] = 0;
315         } else {
316             return ENOMEM;
317         }
318     } else {
319         /*
320            XXX - For now, we only support libdefaults
321            Perhaps this should be extended to allow for per-host / per-realm
322            session key types.
323          */
324
325         char *retval;
326         char *sp, *ep;
327         int i, j, count;
328         krb5_error_code code;
329
330         code = profile_get_string(context->profile, "libdefaults", profstr,
331                                   NULL, DEFAULT_ETYPE_LIST, &retval);
332         if (code)
333             return code;
334
335         count = 0;
336         sp = retval;
337         while (*sp) {
338             for (ep = sp; *ep && (*ep != ',') && !isspace((int) (*ep)); ep++)
339                 ;
340             if (*ep) {
341                 *ep++ = '\0';
342                 while (isspace((int) (*ep)) || *ep == ',')
343                     *ep++ = '\0';
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 KRB5_CALLCONV
394 krb5_set_default_tgs_enctypes (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 (!krb5_c_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 krb5_error_code krb5_set_default_tgs_ktypes
426 (krb5_context context, const krb5_enctype *etypes)
427 {
428   return (krb5_set_default_tgs_enctypes (context, etypes));
429 }
430
431
432 void
433 KRB5_CALLCONV
434 krb5_free_ktypes (context, val)
435      krb5_context context;
436      krb5_enctype *val;
437 {
438     free (val);
439 }
440
441 krb5_error_code
442 KRB5_CALLCONV
443 krb5_get_tgs_ktypes(context, princ, ktypes)
444     krb5_context context;
445     krb5_const_principal princ;
446     krb5_enctype **ktypes;
447 {
448     return(get_profile_etype_list(context, ktypes, "default_tgs_enctypes",
449                                   context->tgs_ktype_count,
450                                   context->tgs_ktypes));
451 }
452
453 krb5_error_code
454 krb5_get_permitted_enctypes(context, ktypes)
455     krb5_context context;
456     krb5_enctype **ktypes;
457 {
458     return(get_profile_etype_list(context, ktypes, "permitted_enctypes",
459                                   context->tgs_ktype_count,
460                                   context->tgs_ktypes));
461 }
462
463 krb5_boolean
464 krb5_is_permitted_enctype(context, etype)
465      krb5_context context;
466      krb5_enctype etype;
467 {
468     krb5_enctype *list, *ptr;
469     krb5_boolean ret;
470
471     if (krb5_get_permitted_enctypes(context, &list))
472         return(0);
473
474     
475     ret = 0;
476
477     for (ptr = list; *ptr; ptr++)
478         if (*ptr == etype)
479             ret = 1;
480
481     krb5_free_ktypes (context, list);
482
483     return(ret);
484 }