build the trunk on Windows (again)
[krb5.git] / src / lib / krb5 / krb / init_ctx.c
index 24d30e9af93f65b58e998a9ede1493622b6e23c9..b80fd50fa170409ef0b116da5709b0dab9165a3d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * lib/krb5/krb/init_ctx.c
  *
- * Copyright 1994,1999,2000, 2002  by the Massachusetts Institute of Technology.
+ * Copyright 1994,1999,2000, 2002, 2003  by the Massachusetts Institute of Technology.
  * All Rights Reserved.
  *
  * Export of this software from the United States of America may
@@ -56,7 +56,7 @@
 #include <ctype.h>
 #include "brand.c"
 /* There has to be a better way for windows... */
-#if defined(unix) 
+#if defined(unix) || TARGET_OS_MAC
 #include "../krb5_libinit.h"
 #endif
 
    them.  This'll be fixed, but for better compatibility, let's prefer
    des-crc for now.  */
 #define DEFAULT_ETYPE_LIST     \
+       "aes256-cts-hmac-sha1-96 " \
+       "aes128-cts-hmac-sha1-96 " \
        "des3-cbc-sha1 arcfour-hmac-md5 " \
        "des-cbc-crc des-cbc-md5 des-cbc-md4 "
 
+/* Not included:
+       "aes128-cts-hmac-sha1-96 " \
+ */
+
 #if (defined(_WIN32))
 extern krb5_error_code krb5_vercheck();
 extern void krb5_win_ccdll_load(krb5_context context);
 #endif
 
-static krb5_error_code init_common (krb5_context *, krb5_boolean);
+static krb5_error_code init_common (krb5_context *, krb5_boolean, krb5_boolean);
 
 krb5_error_code KRB5_CALLCONV
-krb5_init_context(context)
-       krb5_context *context;
+krb5_init_context(krb5_context *context)
 {
 
-       return init_common (context, FALSE);
+       return init_common (context, FALSE, FALSE);
 }
 
 krb5_error_code KRB5_CALLCONV
-krb5_init_secure_context(context)
-       krb5_context *context;
+krb5_init_secure_context(krb5_context *context)
 {
 
         /* This is to make gcc -Wall happy */
         if(0) krb5_brand[0] = krb5_brand[0];
-       return init_common (context, TRUE);
+       return init_common (context, TRUE, FALSE);
+}
+
+krb5_error_code
+krb5int_init_context_kdc(krb5_context *context)
+{
+    return init_common (context, FALSE, TRUE);
 }
 
 static krb5_error_code
-init_common (context, secure)
-       krb5_context *context;
-       krb5_boolean secure;
+init_common (krb5_context *context, krb5_boolean secure, krb5_boolean kdc)
 {
        krb5_context ctx = 0;
        krb5_error_code retval;
@@ -107,8 +115,25 @@ init_common (context, secure)
        krb5_data seed;
        int tmp;
 
-       /* Initialize error tables */
-       krb5_init_ets(ctx);
+       /* Verify some assumptions.  If the assumptions hold and the
+          compiler is optimizing, this should result in no code being
+          executed.  If we're guessing "unsigned long long" instead
+          of using uint64_t, the possibility does exist that we're
+          wrong.  */
+       {
+           krb5_ui_8 i64;
+           assert(sizeof(i64) == 8);
+           i64 = 0, i64--, i64 >>= 62;
+           assert(i64 == 3);
+           i64 = 1, i64 <<= 31, i64 <<= 31, i64 <<= 1;
+           assert(i64 != 0);
+           i64 <<= 1;
+           assert(i64 == 0);
+       }
+
+       retval = krb5int_initialize_library();
+       if (retval)
+           return retval;
 
 #if (defined(_WIN32))
        /* 
@@ -125,8 +150,6 @@ init_common (context, secure)
        retval = krb5_vercheck();
        if (retval)
                return retval;
-#else /* assume UNIX for now */
-       krb5int_initialize_library ();
 #endif
 
        *context = 0;
@@ -146,7 +169,7 @@ init_common (context, secure)
        if ((retval = krb5_set_default_tgs_ktypes(ctx, NULL)))
                goto cleanup;
 
-       if ((retval = krb5_os_init_context(ctx)))
+       if ((retval = krb5_os_init_context(ctx, kdc)))
                goto cleanup;
 
        /* initialize the prng (not well, but passable) */
@@ -193,11 +216,7 @@ init_common (context, secure)
                            "kdc_default_options", 0,
                            KDC_OPT_RENEWABLE_OK, &tmp);
        ctx->kdc_default_options = tmp;
-#if TARGET_OS_MAC
 #define DEFAULT_KDC_TIMESYNC 1
-#else
-#define DEFAULT_KDC_TIMESYNC 0
-#endif
        profile_get_integer(ctx->profile, "libdefaults",
                            "kdc_timesync", 0, DEFAULT_KDC_TIMESYNC,
                            &tmp);
@@ -211,16 +230,13 @@ init_common (context, secure)
         * Note: DCE 1.0.3a only supports a cache type of 1
         *      DCE 1.1 supports a cache type of 2.
         */
-#if TARGET_OS_MAC
 #define DEFAULT_CCACHE_TYPE 4
-#else
-#define DEFAULT_CCACHE_TYPE 3
-#endif
        profile_get_integer(ctx->profile, "libdefaults", "ccache_type",
                            0, DEFAULT_CCACHE_TYPE, &tmp);
        ctx->fcc_default_format = tmp + 0x0500;
        ctx->scc_default_format = tmp + 0x0500;
        ctx->prompt_types = 0;
+       ctx->use_conf_ktypes = 0;
 
        ctx->udp_pref_limit = -1;
        *context = ctx;
@@ -232,10 +248,8 @@ cleanup:
 }
 
 void KRB5_CALLCONV
-krb5_free_context(ctx)
-       krb5_context    ctx;
+krb5_free_context(krb5_context ctx)
 {
-     krb5_free_ets(ctx);
      krb5_os_free_context(ctx);
 
      if (ctx->in_tkt_ktypes) {
@@ -258,6 +272,8 @@ krb5_free_context(ctx)
          ctx->ser_ctx = 0;
      }
 
+     krb5_clear_error_message(ctx);
+
      ctx->magic = 0;
      free(ctx);
 }
@@ -266,9 +282,7 @@ krb5_free_context(ctx)
  * Set the desired default ktypes, making sure they are valid.
  */
 krb5_error_code
-krb5_set_default_in_tkt_ktypes(context, ktypes)
-       krb5_context context;
-       const krb5_enctype *ktypes;
+krb5_set_default_in_tkt_ktypes(krb5_context context, const krb5_enctype *ktypes)
 {
     krb5_enctype * new_ktypes;
     int i;
@@ -298,12 +312,8 @@ krb5_set_default_in_tkt_ktypes(context, ktypes)
 }
 
 static krb5_error_code
-get_profile_etype_list(context, ktypes, profstr, ctx_count, ctx_list)
-     krb5_context context;
-     krb5_enctype **ktypes;
-     char *profstr;
-     int ctx_count;
-     krb5_enctype *ctx_list;
+get_profile_etype_list(krb5_context context, krb5_enctype **ktypes, char *profstr,
+                      unsigned int ctx_count, krb5_enctype *ctx_list)
 {
     krb5_enctype *old_ktypes;
 
@@ -383,9 +393,7 @@ get_profile_etype_list(context, ktypes, profstr, ctx_count, ctx_list)
 }
 
 krb5_error_code
-krb5_get_default_in_tkt_ktypes(context, ktypes)
-    krb5_context context;
-    krb5_enctype **ktypes;
+krb5_get_default_in_tkt_ktypes(krb5_context context, krb5_enctype **ktypes)
 {
     return(get_profile_etype_list(context, ktypes, "default_tkt_enctypes",
                                  context->in_tkt_ktype_count,
@@ -393,9 +401,7 @@ krb5_get_default_in_tkt_ktypes(context, ktypes)
 }
 
 krb5_error_code KRB5_CALLCONV
-krb5_set_default_tgs_enctypes (context, ktypes)
-       krb5_context context;
-       const krb5_enctype *ktypes;
+krb5_set_default_tgs_enctypes (krb5_context context, const krb5_enctype *ktypes)
 {
     krb5_enctype * new_ktypes;
     int i;
@@ -433,29 +439,28 @@ krb5_error_code krb5_set_default_tgs_ktypes
 
 void
 KRB5_CALLCONV
-krb5_free_ktypes (context, val)
-     krb5_context context;
-     krb5_enctype *val;
+krb5_free_ktypes (krb5_context context, krb5_enctype *val)
 {
     free (val);
 }
 
 krb5_error_code
 KRB5_CALLCONV
-krb5_get_tgs_ktypes(context, princ, ktypes)
-    krb5_context context;
-    krb5_const_principal princ;
-    krb5_enctype **ktypes;
+krb5_get_tgs_ktypes(krb5_context context, krb5_const_principal princ, krb5_enctype **ktypes)
 {
-    return(get_profile_etype_list(context, ktypes, "default_tgs_enctypes",
-                                 context->tgs_ktype_count,
-                                 context->tgs_ktypes));
+    if (context->use_conf_ktypes)
+       /* This one is set *only* by reading the config file; it's not
+          set by the application.  */
+       return(get_profile_etype_list(context, ktypes, "default_tgs_enctypes",
+                                     0, NULL));
+    else
+       return(get_profile_etype_list(context, ktypes, "default_tgs_enctypes",
+                                     context->tgs_ktype_count,
+                                     context->tgs_ktypes));
 }
 
-krb5_error_code
-krb5_get_permitted_enctypes(context, ktypes)
-    krb5_context context;
-    krb5_enctype **ktypes;
+krb5_error_code KRB5_CALLCONV
+krb5_get_permitted_enctypes(krb5_context context, krb5_enctype **ktypes)
 {
     return(get_profile_etype_list(context, ktypes, "permitted_enctypes",
                                  context->tgs_ktype_count,
@@ -463,9 +468,7 @@ krb5_get_permitted_enctypes(context, ktypes)
 }
 
 krb5_boolean
-krb5_is_permitted_enctype(context, etype)
-     krb5_context context;
-     krb5_enctype etype;
+krb5_is_permitted_enctype(krb5_context context, krb5_enctype etype)
 {
     krb5_enctype *list, *ptr;
     krb5_boolean ret;
@@ -484,3 +487,93 @@ krb5_is_permitted_enctype(context, etype)
 
     return(ret);
 }
+
+static krb5_error_code
+copy_ktypes(krb5_context ctx,
+           unsigned int nktypes,
+           krb5_enctype *oldktypes,
+           krb5_enctype **newktypes)
+{
+    unsigned int i;
+
+    *newktypes = NULL;
+    if (!nktypes)
+       return 0;
+
+    *newktypes = malloc(nktypes * sizeof(krb5_enctype));
+    if (*newktypes == NULL)
+       return ENOMEM;
+    for (i = 0; i < nktypes; i++)
+       (*newktypes)[i] = oldktypes[i];
+    return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_copy_context(krb5_context ctx, krb5_context *nctx_out)
+{
+    krb5_error_code ret;
+    krb5_context nctx;
+
+    *nctx_out = NULL;
+    if (ctx == NULL)
+       return EINVAL;          /* XXX */
+
+    nctx = malloc(sizeof(*nctx));
+    if (nctx == NULL)
+       return ENOMEM;
+
+    *nctx = *ctx;
+
+    nctx->in_tkt_ktypes = NULL;
+    nctx->in_tkt_ktype_count = 0;
+    nctx->tgs_ktypes = NULL;
+    nctx->tgs_ktype_count = 0;
+    nctx->default_realm = NULL;
+    nctx->profile = NULL;
+    nctx->db_context = NULL;
+    nctx->ser_ctx_count = 0;
+    nctx->ser_ctx = NULL;
+    nctx->prompt_types = NULL;
+    nctx->os_context->default_ccname = NULL;
+
+    memset(&nctx->preauth_plugins, 0, sizeof(nctx->preauth_plugins));
+    nctx->preauth_context = NULL;
+
+    memset(&nctx->libkrb5_plugins, 0, sizeof(nctx->libkrb5_plugins));
+    nctx->vtbl = NULL;
+    nctx->locate_fptrs = NULL;
+
+    memset(&nctx->err, 0, sizeof(nctx->err));
+
+    ret = copy_ktypes(nctx, ctx->in_tkt_ktype_count,
+                     ctx->in_tkt_ktypes, &nctx->in_tkt_ktypes);
+    if (ret)
+       goto errout;
+    nctx->in_tkt_ktype_count = ctx->in_tkt_ktype_count;
+
+    ret = copy_ktypes(nctx, ctx->tgs_ktype_count,
+                     ctx->tgs_ktypes, &nctx->in_tkt_ktypes);
+    if (ret)
+       goto errout;
+    nctx->tgs_ktype_count = ctx->tgs_ktype_count;
+
+    if (ctx->os_context->default_ccname != NULL) {
+       nctx->os_context->default_ccname =
+           strdup(ctx->os_context->default_ccname);
+       if (nctx->os_context->default_ccname == NULL) {
+           ret = ENOMEM;
+           goto errout;
+       }
+    }
+    ret = krb5_get_profile(ctx, &nctx->profile);
+    if (ret)
+       goto errout;
+
+errout:
+    if (ret) {
+       krb5_free_context(nctx);
+    } else {
+       *nctx_out = nctx;
+    }
+    return ret;
+}