Fix trace logging initialization
[krb5.git] / src / lib / krb5 / krb / init_ctx.c
index c5c29ca3ec37c2ddc15626805483cdca2a5f9043..fdc9218f84e49c6a0d0d23ce4e2a1bfa2a0a088f 100644 (file)
@@ -1,7 +1,6 @@
 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/krb5/krb/init_ctx.c */
 /*
- * lib/krb5/krb/init_ctx.c
- *
  * Copyright 1994,1999,2000, 2002, 2003, 2007, 2008, 2009  by the Massachusetts Institute of Technology.
  * All Rights Reserved.
  *
  * M.I.T. makes no representations about the suitability of
  * this software for any purpose.  It is provided "as is" without express
  * or implied warranty.
- *
- * krb5_init_contex()
  */
-
 /*
  * Copyright (C) 1998 by the FundsXpress, INC.
  *
  */
 
 #include "k5-int.h"
-#include "prof_int.h"        /* XXX for profile_copy, not public yet */
+#include "int-proto.h"
 #include <ctype.h>
 #include "brand.c"
-/* There has to be a better way for windows... */
-#if defined(unix) || TARGET_OS_MAC
 #include "../krb5_libinit.h"
-#endif
 
 /* The des-mdX entries are last for now, because it's easy to
    configure KDCs to issue TGTs with des-mdX keys and then not accept
@@ -79,32 +72,66 @@ 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, krb5_boolean);
+#define DEFAULT_CLOCKSKEW  300 /* 5 min */
+
+static krb5_error_code
+get_integer(krb5_context ctx, const char *name, int def_val, int *int_out)
+{
+    krb5_error_code retval;
+
+    retval = profile_get_integer(ctx->profile, KRB5_CONF_LIBDEFAULTS,
+                                 name, NULL, def_val, int_out);
+    if (retval)
+        TRACE_PROFILE_ERR(ctx, name, KRB5_CONF_LIBDEFAULTS, retval);
+    return retval;
+}
+
+static krb5_error_code
+get_boolean(krb5_context ctx, const char *name, int def_val, int *boolean_out)
+{
+    krb5_error_code retval;
+
+    retval = profile_get_boolean(ctx->profile, KRB5_CONF_LIBDEFAULTS,
+                                 name, NULL, def_val, boolean_out);
+    if (retval)
+        TRACE_PROFILE_ERR(ctx, name, KRB5_CONF_LIBDEFAULTS, retval);
+    return retval;
+}
 
 krb5_error_code KRB5_CALLCONV
 krb5_init_context(krb5_context *context)
 {
+    /*
+     * This is rather silly, but should improve our chances of
+     * retaining the krb5_brand array in the final linked library,
+     * better than a static variable that's unreferenced after
+     * optimization, or even a non-static symbol that's not exported
+     * from the library nor referenced from anywhere else in the
+     * library.
+     *
+     * If someday we grow an API to actually return the string, we can
+     * get rid of this silliness.
+     */
+    int my_zero = (krb5_brand[0] == 0);
 
-    return init_common (context, FALSE, FALSE);
+    return krb5_init_context_profile(NULL, my_zero, context);
 }
 
 krb5_error_code KRB5_CALLCONV
 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, FALSE);
+    return krb5_init_context_profile(NULL, KRB5_INIT_CONTEXT_SECURE, context);
 }
 
 krb5_error_code
 krb5int_init_context_kdc(krb5_context *context)
 {
-    return init_common (context, FALSE, TRUE);
+    return krb5_init_context_profile(NULL, KRB5_INIT_CONTEXT_KDC, context);
 }
 
-static krb5_error_code
-init_common (krb5_context *context, krb5_boolean secure, krb5_boolean kdc)
+krb5_error_code KRB5_CALLCONV
+krb5_init_context_profile(profile_t profile, krb5_flags flags,
+                          krb5_context *context_out)
 {
     krb5_context ctx = 0;
     krb5_error_code retval;
@@ -152,30 +179,33 @@ init_common (krb5_context *context, krb5_boolean secure, krb5_boolean kdc)
         return retval;
 #endif
 
-    *context = 0;
+    *context_out = NULL;
 
     ctx = calloc(1, sizeof(struct _krb5_context));
     if (!ctx)
         return ENOMEM;
     ctx->magic = KV5M_CONTEXT;
 
-    ctx->profile_secure = secure;
+    ctx->profile_secure = (flags & KRB5_INIT_CONTEXT_SECURE) != 0;
 
-    /* Set the default encryption types, possible defined in krb5/conf */
-    if ((retval = krb5_set_default_in_tkt_ktypes(ctx, NULL)))
+    if ((retval = krb5_os_init_context(ctx, profile, flags)) != 0)
         goto cleanup;
 
-    if ((retval = krb5_set_default_tgs_ktypes(ctx, NULL)))
-        goto cleanup;
+    ctx->trace_callback = NULL;
+#ifndef DISABLE_TRACING
+    if (!ctx->profile_secure)
+        krb5int_init_trace(ctx);
+#endif
 
-    if ((retval = krb5_os_init_context(ctx, kdc)))
+    retval = get_boolean(ctx, KRB5_CONF_ALLOW_WEAK_CRYPTO, 0, &tmp);
+    if (retval)
         goto cleanup;
+    ctx->allow_weak_crypto = tmp;
 
-    retval = profile_get_boolean(ctx->profile, KRB5_CONF_LIBDEFAULTS,
-                                 KRB5_CONF_ALLOW_WEAK_CRYPTO, NULL, 1, &tmp);
+    retval = get_boolean(ctx, KRB5_CONF_IGNORE_ACCEPTOR_HOSTNAME, 0, &tmp);
     if (retval)
         goto cleanup;
-    ctx->allow_weak_crypto = tmp;
+    ctx->ignore_acceptor_hostname = tmp;
 
     /* initialize the prng (not well, but passable) */
     if ((retval = krb5_c_random_os_entropy( ctx, 0, NULL)) !=0)
@@ -189,8 +219,7 @@ init_common (krb5_context *context, krb5_boolean secure, krb5_boolean kdc)
         goto cleanup;
 
     ctx->default_realm = 0;
-    profile_get_integer(ctx->profile, KRB5_CONF_LIBDEFAULTS, KRB5_CONF_CLOCKSKEW,
-                        0, 5 * 60, &tmp);
+    get_integer(ctx, KRB5_CONF_CLOCKSKEW, DEFAULT_CLOCKSKEW, &tmp);
     ctx->clockskew = tmp;
 
 #if 0
@@ -202,31 +231,34 @@ init_common (krb5_context *context, krb5_boolean secure, krb5_boolean kdc)
 
     /* DCE 1.1 and below only support CKSUMTYPE_RSA_MD4 (2)  */
     /* DCE add kdc_req_checksum_type = 2 to krb5.conf */
-    profile_get_integer(ctx->profile, KRB5_CONF_LIBDEFAULTS,
-                        KRB5_CONF_KDC_REQ_CHECKSUM_TYPE, 0, CKSUMTYPE_RSA_MD5,
-                        &tmp);
+    get_integer(ctx, KRB5_CONF_KDC_REQ_CHECKSUM_TYPE, CKSUMTYPE_RSA_MD5,
+                &tmp);
     ctx->kdc_req_sumtype = tmp;
 
-    profile_get_integer(ctx->profile, KRB5_CONF_LIBDEFAULTS,
-                        KRB5_CONF_AP_REQ_CHECKSUM_TYPE, 0, 0,
-                        &tmp);
+    get_integer(ctx, KRB5_CONF_AP_REQ_CHECKSUM_TYPE, 0, &tmp);
     ctx->default_ap_req_sumtype = tmp;
 
-    profile_get_integer(ctx->profile, KRB5_CONF_LIBDEFAULTS,
-                        KRB5_CONF_SAFE_CHECKSUM_TYPE, 0,
-                        CKSUMTYPE_RSA_MD5_DES, &tmp);
+    get_integer(ctx, KRB5_CONF_SAFE_CHECKSUM_TYPE, CKSUMTYPE_RSA_MD5_DES,
+                &tmp);
     ctx->default_safe_sumtype = tmp;
 
-    profile_get_integer(ctx->profile, KRB5_CONF_LIBDEFAULTS,
-                        KRB5_CONF_KDC_DEFAULT_OPTIONS, 0,
-                        KDC_OPT_RENEWABLE_OK, &tmp);
+    get_integer(ctx, KRB5_CONF_KDC_DEFAULT_OPTIONS, KDC_OPT_RENEWABLE_OK,
+                &tmp);
     ctx->kdc_default_options = tmp;
 #define DEFAULT_KDC_TIMESYNC 1
-    profile_get_integer(ctx->profile, KRB5_CONF_LIBDEFAULTS,
-                        KRB5_CONF_KDC_TIMESYNC, 0, DEFAULT_KDC_TIMESYNC,
-                        &tmp);
+    get_integer(ctx, KRB5_CONF_KDC_TIMESYNC, DEFAULT_KDC_TIMESYNC, &tmp);
     ctx->library_options = tmp ? KRB5_LIBOPT_SYNC_KDCTIME : 0;
 
+    retval = profile_get_string(ctx->profile, KRB5_CONF_LIBDEFAULTS,
+                                KRB5_CONF_PLUGIN_BASE_DIR, 0,
+                                DEFAULT_PLUGIN_BASE_DIR,
+                                &ctx->plugin_base_dir);
+    if (retval) {
+        TRACE_PROFILE_ERR(ctx, KRB5_CONF_PLUGIN_BASE_DIR,
+                          KRB5_CONF_LIBDEFAULTS, retval);
+        goto cleanup;
+    }
+
     /*
      * We use a default file credentials cache of 3.  See
      * lib/krb5/krb/ccache/file/fcc.h for a description of the
@@ -236,14 +268,12 @@ init_common (krb5_context *context, krb5_boolean secure, krb5_boolean kdc)
      *      DCE 1.1 supports a cache type of 2.
      */
 #define DEFAULT_CCACHE_TYPE 4
-    profile_get_integer(ctx->profile, KRB5_CONF_LIBDEFAULTS, KRB5_CONF_CCACHE_TYPE,
-                        0, DEFAULT_CCACHE_TYPE, &tmp);
+    get_integer(ctx, KRB5_CONF_CCACHE_TYPE, DEFAULT_CCACHE_TYPE, &tmp);
     ctx->fcc_default_format = tmp + 0x0500;
     ctx->prompt_types = 0;
     ctx->use_conf_ktypes = 0;
-
     ctx->udp_pref_limit = -1;
-    *context = ctx;
+    *context_out = ctx;
     return 0;
 
 cleanup:
@@ -271,26 +301,17 @@ krb5_free_context(krb5_context ctx)
 
     krb5_clear_error_message(ctx);
 
-    ctx->magic = 0;
-    free(ctx);
-}
+#ifndef DISABLE_TRACING
+    if (ctx->trace_callback)
+        ctx->trace_callback(ctx, NULL, ctx->trace_callback_data);
+#endif
 
-/* Copy the zero-terminated enctype list old_list into *new_list. */
-static krb5_error_code
-copy_enctypes(krb5_context context, const krb5_enctype *old_list,
-              krb5_enctype **new_list)
-{
-    unsigned int count;
-    krb5_enctype *list;
+    k5_ccselect_free_context(ctx);
+    k5_plugin_free_context(ctx);
+    free(ctx->plugin_base_dir);
 
-    *new_list = NULL;
-    for (count = 0; old_list[count]; count++);
-    list = malloc(sizeof(krb5_enctype) * (count + 1));
-    if (list == NULL)
-        return ENOMEM;
-    memcpy(list, old_list, sizeof(krb5_enctype) * (count + 1));
-    *new_list = list;
-    return 0;
+    ctx->magic = 0;
+    free(ctx);
 }
 
 /*
@@ -302,19 +323,31 @@ set_default_etype_var(krb5_context context, const krb5_enctype *etypes,
 {
     krb5_error_code code;
     krb5_enctype *list;
-    int i;
+    size_t src, dst;
 
     if (etypes) {
-        for (i = 0; etypes[i]; i++) {
-            if (!krb5_c_valid_enctype(etypes[i]))
-                return KRB5_PROG_ETYPE_NOSUPP;
-            if (!context->allow_weak_crypto && krb5int_c_weak_enctype(etypes[i]))
-                return KRB5_PROG_ETYPE_NOSUPP;
-        }
-
-        code = copy_enctypes(context, etypes, &list);
+        /* Empty list passed in. */
+        if (etypes[0] == 0)
+            return EINVAL;
+        code = krb5int_copy_etypes(etypes, &list);
         if (code)
             return code;
+
+        /* Filter list in place to exclude invalid and (optionally) weak
+         * enctypes. */
+        for (src = dst = 0; list[src]; src++) {
+            if (!krb5_c_valid_enctype(list[src]))
+                continue;
+            if (!context->allow_weak_crypto
+                && krb5int_c_weak_enctype(list[src]))
+                continue;
+            list[dst++] = list[src];
+        }
+        list[dst] = 0;          /* Zero-terminate. */
+        if (dst == 0) {
+            free(list);
+            return KRB5_CONFIG_ETYPE_NOSUPP;
+        }
     } else {
         list = NULL;
     }
@@ -396,8 +429,9 @@ mod_list(krb5_enctype etype, krb5_boolean add, krb5_boolean allow_weak,
  * parsing profstr.  profstr may be modified during parsing.
  */
 krb5_error_code
-krb5int_parse_enctype_list(krb5_context context, char *profstr,
-                           krb5_enctype *default_list, krb5_enctype **result)
+krb5int_parse_enctype_list(krb5_context context, const char *profkey,
+                           char *profstr, krb5_enctype *default_list,
+                           krb5_enctype **result)
 {
     char *token, *delim = " \t\r\n,", *save = NULL;
     krb5_boolean sel, weak = context->allow_weak_crypto;
@@ -434,9 +468,16 @@ krb5int_parse_enctype_list(krb5_context context, char *profstr,
             mod_list(ENCTYPE_AES128_CTS_HMAC_SHA1_96, sel, weak, &list);
         } else if (strcasecmp(token, "rc4") == 0) {
             mod_list(ENCTYPE_ARCFOUR_HMAC, sel, weak, &list);
+#ifdef CAMELLIA
+        } else if (strcasecmp(token, "camellia") == 0) {
+            mod_list(ENCTYPE_CAMELLIA256_CTS_CMAC, sel, weak, &list);
+            mod_list(ENCTYPE_CAMELLIA128_CTS_CMAC, sel, weak, &list);
+#endif
         } else if (krb5_string_to_enctype(token, &etype) == 0) {
             /* Set a specific enctype. */
             mod_list(etype, sel, weak, &list);
+        } else {
+            TRACE_ENCTYPE_LIST_UNKNOWN(context, profkey, token);
         }
     }
 
@@ -467,7 +508,7 @@ get_profile_etype_list(krb5_context context, krb5_enctype **etypes_ptr,
 
     if (ctx_list) {
         /* Use application defaults. */
-        code = copy_enctypes(context, ctx_list, &etypes);
+        code = krb5int_copy_etypes(ctx_list, &etypes);
         if (code)
             return code;
     } else {
@@ -476,8 +517,8 @@ get_profile_etype_list(krb5_context context, krb5_enctype **etypes_ptr,
                                   profkey, NULL, "DEFAULT", &profstr);
         if (code)
             return code;
-        code = krb5int_parse_enctype_list(context, profstr, default_list,
-                                          &etypes);
+        code = krb5int_parse_enctype_list(context, profkey, profstr,
+                                          default_list, &etypes);
         profile_release_string(profstr);
         if (code)
             return code;
@@ -585,72 +626,3 @@ krb5_is_permitted_enctype_ext ( krb5_context context,
 
     return(ret);
 }
-
-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_etypes = NULL;
-    nctx->tgs_etypes = NULL;
-    nctx->default_realm = NULL;
-    nctx->profile = NULL;
-    nctx->dal_handle = 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_enctypes(nctx, ctx->in_tkt_etypes, &nctx->in_tkt_etypes);
-    if (ret)
-        goto errout;
-    ret = copy_enctypes(nctx, ctx->tgs_etypes, &nctx->tgs_etypes);
-    if (ret)
-        goto errout;
-
-    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;
-}
-
-krb5_error_code KRB5_CALLCONV
-krb5_get_profile (krb5_context ctx, profile_t *profile)
-{
-    return profile_copy (ctx->profile, profile);
-}