aboutsummaryrefslogtreecommitdiffstats
path: root/lib/krb5/context.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/krb5/context.c')
-rw-r--r--lib/krb5/context.c206
1 files changed, 137 insertions, 69 deletions
diff --git a/lib/krb5/context.c b/lib/krb5/context.c
index 99bf1b419b0a..5660f7f36b9b 100644
--- a/lib/krb5/context.c
+++ b/lib/krb5/context.c
@@ -48,6 +48,11 @@
} \
} while(0)
+static krb5_error_code
+copy_enctypes(krb5_context context,
+ const krb5_enctype *in,
+ krb5_enctype **out);
+
/*
* Set the list of etypes `ret_etypes' from the configuration variable
* `name'
@@ -69,8 +74,7 @@ set_etypes (krb5_context context,
etypes = malloc((i+1) * sizeof(*etypes));
if (etypes == NULL) {
krb5_config_free_strings (etypes_str);
- krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
- return ENOMEM;
+ return krb5_enomem(context);
}
for(j = 0, k = 0; j < i; j++) {
krb5_enctype e;
@@ -100,7 +104,8 @@ init_context_from_config_file(krb5_context context)
krb5_enctype *tmptypes;
INIT_FIELD(context, time, max_skew, 5 * 60, "clockskew");
- INIT_FIELD(context, time, kdc_timeout, 3, "kdc_timeout");
+ INIT_FIELD(context, time, kdc_timeout, 30, "kdc_timeout");
+ INIT_FIELD(context, time, host_timeout, 3, "host_timeout");
INIT_FIELD(context, int, max_retries, 3, "max_retries");
INIT_FIELD(context, string, http_proxy, NULL, "http_proxy");
@@ -123,6 +128,18 @@ init_context_from_config_file(krb5_context context)
free(context->etypes);
context->etypes = tmptypes;
+ /* The etypes member may change during the lifetime
+ * of the context. To be able to reset it to
+ * config value, we keep another copy.
+ */
+ free(context->cfg_etypes);
+ context->cfg_etypes = NULL;
+ if (tmptypes) {
+ ret = copy_enctypes(context, tmptypes, &context->cfg_etypes);
+ if (ret)
+ return ret;
+ }
+
ret = set_etypes (context, "default_etypes_des", &tmptypes);
if(ret)
return ret;
@@ -147,15 +164,8 @@ init_context_from_config_file(krb5_context context)
free(context->permitted_enctypes);
context->permitted_enctypes = tmptypes;
- /* default keytab name */
- tmp = NULL;
- if(!issuid())
- tmp = getenv("KRB5_KTNAME");
- if(tmp != NULL)
- context->default_keytab = tmp;
- else
- INIT_FIELD(context, string, default_keytab,
- KEYTAB_DEFAULT, "default_keytab_name");
+ INIT_FIELD(context, string, default_keytab,
+ KEYTAB_DEFAULT, "default_keytab_name");
INIT_FIELD(context, string, default_keytab_modify,
NULL, "default_keytab_modify_name");
@@ -220,14 +230,22 @@ init_context_from_config_file(krb5_context context)
INIT_FIELD(context, bool, srv_lookup, TRUE, "srv_lookup");
INIT_FIELD(context, bool, srv_lookup, context->srv_lookup, "dns_lookup_kdc");
INIT_FIELD(context, int, large_msg_size, 1400, "large_message_size");
+ INIT_FIELD(context, int, max_msg_size, 1000 * 1024, "maximum_message_size");
INIT_FLAG(context, flags, KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME, TRUE, "dns_canonicalize_hostname");
INIT_FLAG(context, flags, KRB5_CTX_F_CHECK_PAC, TRUE, "check_pac");
+
+ if (context->default_cc_name)
+ free(context->default_cc_name);
context->default_cc_name = NULL;
context->default_cc_name_set = 0;
s = krb5_config_get_strings(context, NULL, "logging", "krb5", NULL);
if(s) {
char **p;
+
+ if (context->debug_dest)
+ krb5_closelog(context, context->debug_dest);
+
krb5_initlog(context, "libkrb5", &context->debug_dest);
for(p = s; *p; p++)
krb5_addlog_dest(context, context->debug_dest, *p);
@@ -242,6 +260,11 @@ init_context_from_config_file(krb5_context context)
if (strcasecmp(tmp, "ignore") == 0)
context->flags |= KRB5_CTX_F_RD_REQ_IGNORE;
}
+ ret = krb5_config_get_bool_default(context, NULL, TRUE,
+ "libdefaults",
+ "fcache_strict_checking", NULL);
+ if (ret)
+ context->flags |= KRB5_CTX_F_FCACHE_STRICT_CHECKING;
return 0;
}
@@ -256,6 +279,7 @@ cc_ops_register(krb5_context context)
krb5_cc_register(context, &krb5_acc_ops, TRUE);
#endif
krb5_cc_register(context, &krb5_fcc_ops, TRUE);
+ krb5_cc_register(context, &krb5_dcc_ops, TRUE);
krb5_cc_register(context, &krb5_mcc_ops, TRUE);
#ifdef HAVE_SCC
krb5_cc_register(context, &krb5_scc_ops, TRUE);
@@ -323,11 +347,8 @@ kt_ops_copy(krb5_context context, const krb5_context src_context)
return 0;
context->kt_types = malloc(sizeof(context->kt_types[0]) * src_context->num_kt_types);
- if (context->kt_types == NULL) {
- krb5_set_error_message(context, ENOMEM,
- N_("malloc: out of memory", ""));
- return ENOMEM;
- }
+ if (context->kt_types == NULL)
+ return krb5_enomem(context);
context->num_kt_types = src_context->num_kt_types;
memcpy(context->kt_types, src_context->kt_types,
@@ -337,11 +358,18 @@ kt_ops_copy(krb5_context context, const krb5_context src_context)
}
static const char *sysplugin_dirs[] = {
- LIBDIR "/plugin/krb5",
+#ifdef _WIN32
+ "$ORIGIN",
+#else
+ "$ORIGIN/../lib/plugin/krb5",
+#endif
#ifdef __APPLE__
+ LIBDIR "/plugin/krb5",
+#ifdef HEIM_PLUGINS_SEARCH_SYSTEM
"/Library/KerberosPlugins/KerberosFrameworkPlugins",
"/System/Library/KerberosPlugins/KerberosFrameworkPlugins",
#endif
+#endif
NULL
};
@@ -349,8 +377,21 @@ static void
init_context_once(void *ctx)
{
krb5_context context = ctx;
+ char **dirs;
- _krb5_load_plugins(context, "krb5", sysplugin_dirs);
+#ifdef _WIN32
+ dirs = rk_UNCONST(sysplugin_dirs);
+#else
+ dirs = krb5_config_get_strings(context, NULL, "libdefaults",
+ "plugin_dir", NULL);
+ if (dirs == NULL)
+ dirs = rk_UNCONST(sysplugin_dirs);
+#endif
+
+ _krb5_load_plugins(context, "krb5", (const char **)dirs);
+
+ if (dirs != rk_UNCONST(sysplugin_dirs))
+ krb5_config_free_strings(dirs);
bindtextdomain(HEIMDAL_TEXTDOMAIN, HEIMDAL_LOCALEDIR);
}
@@ -366,7 +407,8 @@ init_context_once(void *ctx)
* @return Returns 0 to indicate success. Otherwise an errno code is
* returned. Failure means either that something bad happened during
* initialization (typically ENOMEM) or that Kerberos should not be
- * used ENXIO.
+ * used ENXIO. If the function returns HEIM_ERR_RANDOM_OFFLINE, the
+ * random source is not available and later Kerberos calls might fail.
*
* @ingroup krb5
*/
@@ -378,19 +420,28 @@ krb5_init_context(krb5_context *context)
krb5_context p;
krb5_error_code ret;
char **files;
+ uint8_t rnd;
*context = NULL;
+ /**
+ * krb5_init_context() will get one random byte to make sure our
+ * random is alive. Assumption is that once the non blocking
+ * source allows us to pull bytes, its all seeded and allows us to
+ * pull more bytes.
+ *
+ * Most Kerberos users calls krb5_init_context(), so this is
+ * useful point where we can do the checking.
+ */
+ ret = krb5_generate_random(&rnd, sizeof(rnd));
+ if (ret)
+ return ret;
+
p = calloc(1, sizeof(*p));
if(!p)
return ENOMEM;
- p->mutex = malloc(sizeof(HEIMDAL_MUTEX));
- if (p->mutex == NULL) {
- free(p);
- return ENOMEM;
- }
- HEIMDAL_MUTEX_init(p->mutex);
+ HEIMDAL_MUTEX_init(&p->mutex);
p->flags |= KRB5_CTX_F_HOMEDIR_ACCESS;
@@ -402,6 +453,9 @@ krb5_init_context(krb5_context *context)
if(ret)
goto out;
+ /* done enough to load plugins */
+ heim_base_once_f(&init_context, p, init_context_once);
+
/* init error tables */
krb5_init_ets(p);
cc_ops_register(p);
@@ -419,8 +473,6 @@ out:
if(ret) {
krb5_free_context(p);
p = NULL;
- } else {
- heim_base_once_f(&init_context, p, init_context_once);
}
*context = p;
return ret;
@@ -450,13 +502,10 @@ copy_etypes (krb5_context context,
;
i++;
- *ret_enctypes = malloc(sizeof(ret_enctypes[0]) * i);
- if (*ret_enctypes == NULL) {
- krb5_set_error_message(context, ENOMEM,
- N_("malloc: out of memory", ""));
- return ENOMEM;
- }
- memcpy(*ret_enctypes, enctypes, sizeof(ret_enctypes[0]) * i);
+ *ret_enctypes = malloc(sizeof(enctypes[0]) * i);
+ if (*ret_enctypes == NULL)
+ return krb5_enomem(context);
+ memcpy(*ret_enctypes, enctypes, sizeof(enctypes[0]) * i);
return 0;
}
@@ -482,19 +531,10 @@ krb5_copy_context(krb5_context context, krb5_context *out)
*out = NULL;
p = calloc(1, sizeof(*p));
- if (p == NULL) {
- krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
- return ENOMEM;
- }
-
- p->mutex = malloc(sizeof(HEIMDAL_MUTEX));
- if (p->mutex == NULL) {
- krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
- free(p);
- return ENOMEM;
- }
- HEIMDAL_MUTEX_init(p->mutex);
+ if (p == NULL)
+ return krb5_enomem(context);
+ HEIMDAL_MUTEX_init(&p->mutex);
if (context->default_cc_name)
p->default_cc_name = strdup(context->default_cc_name);
@@ -506,6 +546,11 @@ krb5_copy_context(krb5_context context, krb5_context *out)
if (ret)
goto out;
}
+ if (context->cfg_etypes) {
+ ret = copy_etypes(context, context->cfg_etypes, &p->cfg_etypes);
+ if (ret)
+ goto out;
+ }
if (context->etypes_des) {
ret = copy_etypes(context, context->etypes_des, &p->etypes_des);
if (ret)
@@ -569,11 +614,13 @@ krb5_copy_context(krb5_context context, krb5_context *out)
KRB5_LIB_FUNCTION void KRB5_LIB_CALL
krb5_free_context(krb5_context context)
{
+ _krb5_free_name_canon_rules(context, context->name_canon_rules);
if (context->default_cc_name)
free(context->default_cc_name);
if (context->default_cc_name_env)
free(context->default_cc_name_env);
free(context->etypes);
+ free(context->cfg_etypes);
free(context->etypes_des);
krb5_free_host_realm (context, context->default_realms);
krb5_config_file_free (context, context->cf);
@@ -594,8 +641,7 @@ krb5_free_context(krb5_context context)
hx509_context_free(&context->hx509ctx);
#endif
- HEIMDAL_MUTEX_destroy(context->mutex);
- free(context->mutex);
+ HEIMDAL_MUTEX_destroy(&context->mutex);
if (context->flags & KRB5_CTX_F_SOCKETS_INITIALIZED) {
rk_SOCK_EXIT();
}
@@ -623,7 +669,8 @@ krb5_set_config_files(krb5_context context, char **filenames)
krb5_config_binding *tmp = NULL;
while(filenames != NULL && *filenames != NULL && **filenames != '\0') {
ret = krb5_config_parse_file_multi(context, *filenames, &tmp);
- if(ret != 0 && ret != ENOENT && ret != EACCES && ret != EPERM) {
+ if (ret != 0 && ret != ENOENT && ret != EACCES && ret != EPERM
+ && ret != KRB5_CONFIG_BADFORMAT) {
krb5_config_file_free(context, tmp);
return ret;
}
@@ -769,7 +816,7 @@ krb5_prepend_config_files_default(const char *filelist, char ***pfilenames)
* to find the configuration file location in the
* SOFTWARE\MIT\Kerberos registry key under the value "config".
*/
-char *
+KRB5_LIB_FUNCTION char * KRB5_LIB_CALL
_krb5_get_default_config_config_files_from_registry()
{
static const char * KeyName = "Software\\MIT\\Kerberos";
@@ -881,6 +928,18 @@ krb5_kerberos_enctypes(krb5_context context)
static const krb5_enctype p[] = {
ETYPE_AES256_CTS_HMAC_SHA1_96,
ETYPE_AES128_CTS_HMAC_SHA1_96,
+ ETYPE_AES256_CTS_HMAC_SHA384_192,
+ ETYPE_AES128_CTS_HMAC_SHA256_128,
+ ETYPE_DES3_CBC_SHA1,
+ ETYPE_ARCFOUR_HMAC_MD5,
+ ETYPE_NULL
+ };
+
+ static const krb5_enctype weak[] = {
+ ETYPE_AES256_CTS_HMAC_SHA1_96,
+ ETYPE_AES128_CTS_HMAC_SHA1_96,
+ ETYPE_AES256_CTS_HMAC_SHA384_192,
+ ETYPE_AES128_CTS_HMAC_SHA256_128,
ETYPE_DES3_CBC_SHA1,
ETYPE_DES3_CBC_MD5,
ETYPE_ARCFOUR_HMAC_MD5,
@@ -889,6 +948,20 @@ krb5_kerberos_enctypes(krb5_context context)
ETYPE_DES_CBC_CRC,
ETYPE_NULL
};
+
+ /*
+ * if the list of enctypes enabled by "allow_weak_crypto"
+ * are valid, then return the former default enctype list
+ * that contained the weak entries.
+ */
+ if (krb5_enctype_valid(context, ETYPE_DES_CBC_CRC) == 0 &&
+ krb5_enctype_valid(context, ETYPE_DES_CBC_MD4) == 0 &&
+ krb5_enctype_valid(context, ETYPE_DES_CBC_MD5) == 0 &&
+ krb5_enctype_valid(context, ETYPE_DES_CBC_NONE) == 0 &&
+ krb5_enctype_valid(context, ETYPE_DES_CFB64_NONE) == 0 &&
+ krb5_enctype_valid(context, ETYPE_DES_PCBC_NONE) == 0)
+ return weak;
+
return p;
}
@@ -944,6 +1017,8 @@ default_etypes(krb5_context context, krb5_enctype **etype)
*
* @param context Kerberos 5 context.
* @param etypes Encryption types, array terminated with ETYPE_NULL (0).
+ * A value of NULL resets the encryption types to the defaults set in the
+ * configuration file.
*
* @return Returns 0 to indicate success. Otherwise an kerberos et
* error code is returned, see krb5_get_error_message().
@@ -958,6 +1033,10 @@ krb5_set_default_in_tkt_etypes(krb5_context context,
krb5_error_code ret;
krb5_enctype *p = NULL;
+ if(!etypes) {
+ etypes = context->cfg_etypes;
+ }
+
if(etypes) {
ret = copy_enctypes(context, etypes, &p);
if (ret)
@@ -974,6 +1053,7 @@ krb5_set_default_in_tkt_etypes(krb5_context context,
* with the KDC, clients and servers.
*
* @param context Kerberos 5 context.
+ * @param pdu_type request type (AS, TGS or none)
* @param etypes Encryption types, array terminated with
* ETYPE_NULL(0), caller should free array with krb5_xfree():
*
@@ -994,7 +1074,7 @@ krb5_get_default_in_tkt_etypes(krb5_context context,
heim_assert(pdu_type == KRB5_PDU_AS_REQUEST ||
pdu_type == KRB5_PDU_TGS_REQUEST ||
- pdu_type == KRB5_PDU_NONE, "pdu contant not as expected");
+ pdu_type == KRB5_PDU_NONE, "unexpected pdu type");
if (pdu_type == KRB5_PDU_AS_REQUEST && context->as_etypes != NULL)
enctypes = context->as_etypes;
@@ -1133,10 +1213,8 @@ krb5_set_extra_addresses(krb5_context context, const krb5_addresses *addresses)
}
if(context->extra_addresses == NULL) {
context->extra_addresses = malloc(sizeof(*context->extra_addresses));
- if(context->extra_addresses == NULL) {
- krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
- return ENOMEM;
- }
+ if (context->extra_addresses == NULL)
+ return krb5_enomem(context);
}
return krb5_copy_addresses(context, addresses, context->extra_addresses);
}
@@ -1215,10 +1293,8 @@ krb5_set_ignore_addresses(krb5_context context, const krb5_addresses *addresses)
}
if(context->ignore_addresses == NULL) {
context->ignore_addresses = malloc(sizeof(*context->ignore_addresses));
- if(context->ignore_addresses == NULL) {
- krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
- return ENOMEM;
- }
+ if (context->ignore_addresses == NULL)
+ return krb5_enomem(context);
}
return krb5_copy_addresses(context, addresses, context->ignore_addresses);
}
@@ -1457,17 +1533,11 @@ _krb5_init_etype(krb5_context context,
static HEIMDAL_MUTEX homedir_mutex = HEIMDAL_MUTEX_INITIALIZER;
static krb5_boolean allow_homedir = TRUE;
-krb5_boolean
+KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
_krb5_homedir_access(krb5_context context)
{
krb5_boolean allow;
-#ifdef HAVE_GETEUID
- /* is never allowed for root */
- if (geteuid() == 0)
- return FALSE;
-#endif
-
if (context && (context->flags & KRB5_CTX_F_HOMEDIR_ACCESS) == 0)
return FALSE;
@@ -1486,8 +1556,6 @@ _krb5_homedir_access(krb5_context context)
* For home directory access to be allowed, both the global state and
* the krb5_context state have to be allowed.
*
- * Administrator (root user), never uses the home directory.
- *
* @param context a Kerberos 5 context or NULL
* @param allow allow if TRUE home directory
* @return the old value