* init_ctx.c (init_common): Initialize udp_pref_limit field
[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 #if TARGET_OS_MAC
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 #if TARGET_OS_MAC
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
225         ctx->udp_pref_limit = -1;
226         *context = ctx;
227         return 0;
228
229 cleanup:
230         krb5_free_context(ctx);
231         return retval;
232 }
233
234 void KRB5_CALLCONV
235 krb5_free_context(ctx)
236         krb5_context    ctx;
237 {
238      krb5_free_ets(ctx);
239      krb5_os_free_context(ctx);
240
241      if (ctx->in_tkt_ktypes) {
242           free(ctx->in_tkt_ktypes);
243           ctx->in_tkt_ktypes = 0;
244      }
245
246      if (ctx->tgs_ktypes) {
247           free(ctx->tgs_ktypes);
248           ctx->tgs_ktypes = 0;
249      }
250
251      if (ctx->default_realm) {
252           free(ctx->default_realm);
253           ctx->default_realm = 0;
254      }
255
256      if (ctx->ser_ctx_count && ctx->ser_ctx) {
257           free(ctx->ser_ctx);
258           ctx->ser_ctx = 0;
259      }
260
261      ctx->magic = 0;
262      free(ctx);
263 }
264
265 /*
266  * Set the desired default ktypes, making sure they are valid.
267  */
268 krb5_error_code
269 krb5_set_default_in_tkt_ktypes(context, ktypes)
270         krb5_context context;
271         const krb5_enctype *ktypes;
272 {
273     krb5_enctype * new_ktypes;
274     int i;
275
276     if (ktypes) {
277         for (i = 0; ktypes[i]; i++) {
278             if (!krb5_c_valid_enctype(ktypes[i])) 
279                 return KRB5_PROG_ETYPE_NOSUPP;
280         }
281
282         /* Now copy the default ktypes into the context pointer */
283         if ((new_ktypes = (krb5_enctype *)malloc(sizeof(krb5_enctype) * i)))
284             memcpy(new_ktypes, ktypes, sizeof(krb5_enctype) * i);
285         else
286             return ENOMEM;
287
288     } else {
289         i = 0;
290         new_ktypes = 0;
291     }
292
293     if (context->in_tkt_ktypes) 
294         free(context->in_tkt_ktypes);
295     context->in_tkt_ktypes = new_ktypes;
296     context->in_tkt_ktype_count = i;
297     return 0;
298 }
299
300 static krb5_error_code
301 get_profile_etype_list(context, ktypes, profstr, ctx_count, ctx_list)
302      krb5_context context;
303      krb5_enctype **ktypes;
304      char *profstr;
305      int ctx_count;
306      krb5_enctype *ctx_list;
307 {
308     krb5_enctype *old_ktypes;
309
310     if (ctx_count) {
311         /* application-set defaults */
312         if ((old_ktypes = 
313              (krb5_enctype *)malloc(sizeof(krb5_enctype) *
314                                     (ctx_count + 1)))) {
315             memcpy(old_ktypes, ctx_list, sizeof(krb5_enctype) * ctx_count);
316             old_ktypes[ctx_count] = 0;
317         } else {
318             return ENOMEM;
319         }
320     } else {
321         /*
322            XXX - For now, we only support libdefaults
323            Perhaps this should be extended to allow for per-host / per-realm
324            session key types.
325          */
326
327         char *retval;
328         char *sp, *ep;
329         int i, j, count;
330         krb5_error_code code;
331
332         code = profile_get_string(context->profile, "libdefaults", profstr,
333                                   NULL, DEFAULT_ETYPE_LIST, &retval);
334         if (code)
335             return code;
336
337         count = 0;
338         sp = retval;
339         while (*sp) {
340             for (ep = sp; *ep && (*ep != ',') && !isspace((int) (*ep)); ep++)
341                 ;
342             if (*ep) {
343                 *ep++ = '\0';
344                 while (isspace((int) (*ep)) || *ep == ',')
345                     *ep++ = '\0';
346             }
347             count++;
348             sp = ep;
349         }
350         
351         if ((old_ktypes =
352              (krb5_enctype *)malloc(sizeof(krb5_enctype) * (count + 1))) ==
353             (krb5_enctype *) NULL)
354             return ENOMEM;
355         
356         sp = retval;
357         j = 0;
358         i = 1;
359         while (1) {
360             if (! krb5_string_to_enctype(sp, &old_ktypes[j]))
361                 j++;
362
363             if (i++ >= count)
364                 break;
365
366             /* skip to next token */
367             while (*sp) sp++;
368             while (! *sp) sp++;
369         }
370
371         old_ktypes[j] = (krb5_enctype) 0;
372         profile_release_string(retval);
373     }
374
375     if (old_ktypes[0] == 0) {
376         free (old_ktypes);
377         *ktypes = 0;
378         return KRB5_CONFIG_ETYPE_NOSUPP;
379     }
380
381     *ktypes = old_ktypes;
382     return 0;
383 }
384
385 krb5_error_code
386 krb5_get_default_in_tkt_ktypes(context, ktypes)
387     krb5_context context;
388     krb5_enctype **ktypes;
389 {
390     return(get_profile_etype_list(context, ktypes, "default_tkt_enctypes",
391                                   context->in_tkt_ktype_count,
392                                   context->in_tkt_ktypes));
393 }
394
395 krb5_error_code KRB5_CALLCONV
396 krb5_set_default_tgs_enctypes (context, ktypes)
397         krb5_context context;
398         const krb5_enctype *ktypes;
399 {
400     krb5_enctype * new_ktypes;
401     int i;
402
403     if (ktypes) {
404         for (i = 0; ktypes[i]; i++) {
405             if (!krb5_c_valid_enctype(ktypes[i])) 
406                 return KRB5_PROG_ETYPE_NOSUPP;
407         }
408
409         /* Now copy the default ktypes into the context pointer */
410         if ((new_ktypes = (krb5_enctype *)malloc(sizeof(krb5_enctype) * i)))
411             memcpy(new_ktypes, ktypes, sizeof(krb5_enctype) * i);
412         else
413             return ENOMEM;
414
415     } else {
416         i = 0;
417         new_ktypes = (krb5_enctype *)NULL;
418     }
419
420     if (context->tgs_ktypes) 
421         krb5_free_ktypes(context, context->tgs_ktypes);
422     context->tgs_ktypes = new_ktypes;
423     context->tgs_ktype_count = i;
424     return 0;
425 }
426
427 krb5_error_code krb5_set_default_tgs_ktypes
428 (krb5_context context, const krb5_enctype *etypes)
429 {
430   return (krb5_set_default_tgs_enctypes (context, etypes));
431 }
432
433
434 void
435 KRB5_CALLCONV
436 krb5_free_ktypes (context, val)
437      krb5_context context;
438      krb5_enctype *val;
439 {
440     free (val);
441 }
442
443 krb5_error_code
444 KRB5_CALLCONV
445 krb5_get_tgs_ktypes(context, princ, ktypes)
446     krb5_context context;
447     krb5_const_principal princ;
448     krb5_enctype **ktypes;
449 {
450     return(get_profile_etype_list(context, ktypes, "default_tgs_enctypes",
451                                   context->tgs_ktype_count,
452                                   context->tgs_ktypes));
453 }
454
455 krb5_error_code
456 krb5_get_permitted_enctypes(context, ktypes)
457     krb5_context context;
458     krb5_enctype **ktypes;
459 {
460     return(get_profile_etype_list(context, ktypes, "permitted_enctypes",
461                                   context->tgs_ktype_count,
462                                   context->tgs_ktypes));
463 }
464
465 krb5_boolean
466 krb5_is_permitted_enctype(context, etype)
467      krb5_context context;
468      krb5_enctype etype;
469 {
470     krb5_enctype *list, *ptr;
471     krb5_boolean ret;
472
473     if (krb5_get_permitted_enctypes(context, &list))
474         return(0);
475
476     
477     ret = 0;
478
479     for (ptr = list; *ptr; ptr++)
480         if (*ptr == etype)
481             ret = 1;
482
483     krb5_free_ktypes (context, list);
484
485     return(ret);
486 }