diff options
author | Greg Hudson <ghudson@mit.edu> | 2013-08-05 15:57:29 -0400 |
---|---|---|
committer | Greg Hudson <ghudson@mit.edu> | 2013-08-15 12:39:57 -0400 |
commit | db21244a069e581a392dff5b320e758e06a28e4d (patch) | |
tree | 7a99f0700c983da998571a7ab4bf845020a304be /src/lib | |
parent | d61fbd85467c71c9bfb185e0e675e1619972bd0b (diff) | |
download | krb5-db21244a069e581a392dff5b320e758e06a28e4d.tar.gz krb5-db21244a069e581a392dff5b320e758e06a28e4d.tar.xz krb5-db21244a069e581a392dff5b320e758e06a28e4d.zip |
Use hostrealm interface for realm mapping
Reimplement krb5_get_host_realm, krb5_get_fallback_host_realm, and
krb5_get_default_realm in terms of the hostrealm interface. Three
built-in modules (dns, domain, and profile) implement the current
behavior.
ticket: 7687
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/krb5/krb/init_ctx.c | 1 | ||||
-rw-r--r-- | src/lib/krb5/libkrb5.exports | 1 | ||||
-rw-r--r-- | src/lib/krb5/os/Makefile.in | 15 | ||||
-rw-r--r-- | src/lib/krb5/os/def_realm.c | 190 | ||||
-rw-r--r-- | src/lib/krb5/os/deps | 79 | ||||
-rw-r--r-- | src/lib/krb5/os/hostrealm.c | 401 | ||||
-rw-r--r-- | src/lib/krb5/os/hostrealm_dns.c | 143 | ||||
-rw-r--r-- | src/lib/krb5/os/hostrealm_domain.c | 128 | ||||
-rw-r--r-- | src/lib/krb5/os/hostrealm_profile.c | 117 | ||||
-rw-r--r-- | src/lib/krb5/os/hst_realm.c | 255 | ||||
-rw-r--r-- | src/lib/krb5/os/os-proto.h | 12 |
11 files changed, 875 insertions, 467 deletions
diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c index 39b6853cba..3f4aad4fd6 100644 --- a/src/lib/krb5/krb/init_ctx.c +++ b/src/lib/krb5/krb/init_ctx.c @@ -310,6 +310,7 @@ krb5_free_context(krb5_context ctx) #endif k5_ccselect_free_context(ctx); + k5_hostrealm_free_context(ctx); k5_localauth_free_context(ctx); k5_plugin_free_context(ctx); free(ctx->plugin_base_dir); diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports index 665db7fa6d..59d698a821 100644 --- a/src/lib/krb5/libkrb5.exports +++ b/src/lib/krb5/libkrb5.exports @@ -115,6 +115,7 @@ k5_free_otp_tokeninfo k5_free_pa_otp_challenge k5_free_pa_otp_req k5_free_serverlist +k5_hostrealm_free_context k5_init_trace k5_kt_get_principal k5_localauth_free_context diff --git a/src/lib/krb5/os/Makefile.in b/src/lib/krb5/os/Makefile.in index 0353a8476a..769f234711 100644 --- a/src/lib/krb5/os/Makefile.in +++ b/src/lib/krb5/os/Makefile.in @@ -11,7 +11,6 @@ LOCALINCLUDES=-I$(top_srcdir)/util/profile STLIBOBJS= \ accessor.o \ c_ustime.o \ - def_realm.o \ ccdefname.o \ changepw.o \ dnsglue.o \ @@ -22,6 +21,10 @@ STLIBOBJS= \ genaddrs.o \ gen_rname.o \ hostaddr.o \ + hostrealm.o \ + hostrealm_dns.o \ + hostrealm_domain.o \ + hostrealm_profile.o \ hst_realm.o \ init_os_ctx.o \ krbfileio.o \ @@ -55,7 +58,6 @@ STLIBOBJS= \ OBJS= \ $(OUTPRE)accessor.$(OBJEXT) \ $(OUTPRE)c_ustime.$(OBJEXT) \ - $(OUTPRE)def_realm.$(OBJEXT) \ $(OUTPRE)ccdefname.$(OBJEXT) \ $(OUTPRE)changepw.$(OBJEXT) \ $(OUTPRE)dnsglue.$(OBJEXT) \ @@ -66,6 +68,10 @@ OBJS= \ $(OUTPRE)genaddrs.$(OBJEXT) \ $(OUTPRE)gen_rname.$(OBJEXT) \ $(OUTPRE)hostaddr.$(OBJEXT) \ + $(OUTPRE)hostrealm.$(OBJEXT) \ + $(OUTPRE)hostrealm_dns.$(OBJEXT) \ + $(OUTPRE)hostrealm_domain.$(OBJEXT) \ + $(OUTPRE)hostrealm_profile.$(OBJEXT) \ $(OUTPRE)hst_realm.$(OBJEXT) \ $(OUTPRE)init_os_ctx.$(OBJEXT) \ $(OUTPRE)krbfileio.$(OBJEXT) \ @@ -99,7 +105,6 @@ OBJS= \ SRCS= \ $(srcdir)/accessor.c \ $(srcdir)/c_ustime.c \ - $(srcdir)/def_realm.c \ $(srcdir)/ccdefname.c \ $(srcdir)/changepw.c \ $(srcdir)/dnsglue.c \ @@ -110,6 +115,10 @@ SRCS= \ $(srcdir)/genaddrs.c \ $(srcdir)/gen_rname.c \ $(srcdir)/hostaddr.c \ + $(srcdir)/hostrealm.c \ + $(srcdir)/hostrealm_dns.c \ + $(srcdir)/hostrealm_domain.c \ + $(srcdir)/hostrealm_profile.c \ $(srcdir)/hst_realm.c \ $(srcdir)/init_os_ctx.c \ $(srcdir)/krbfileio.c \ diff --git a/src/lib/krb5/os/def_realm.c b/src/lib/krb5/os/def_realm.c deleted file mode 100644 index 81ad6f2ff9..0000000000 --- a/src/lib/krb5/os/def_realm.c +++ /dev/null @@ -1,190 +0,0 @@ -/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* lib/krb5/os/def_realm.c */ -/* - * Copyright 1990,1991,2009 by the Massachusetts Institute of Technology. - * All Rights Reserved. - * - * Export of this software from the United States of America may - * require a specific license from the United States Government. - * It is the responsibility of any person or organization contemplating - * export to obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of M.I.T. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. Furthermore if you modify this software you must label - * your software as modified software and not distribute it in such a - * fashion that it might be confused with the original M.I.T. software. - * 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_get_default_realm(), krb5_set_default_realm(), - * krb5_free_default_realm() functions. - */ - -#include "k5-int.h" -#include "os-proto.h" -#include <stdio.h> - -#ifdef KRB5_DNS_LOOKUP -#ifdef WSHELPER -#include <wshelper.h> -#else /* WSHELPER */ -#ifdef HAVE_NETINET_IN_H -#include <netinet/in.h> -#endif -#include <arpa/inet.h> -#include <arpa/nameser.h> -#include <resolv.h> -#include <netdb.h> -#endif /* WSHELPER */ - -/* for old Unixes and friends ... */ -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 64 -#endif - -#define MAX_DNS_NAMELEN (15*(MAXHOSTNAMELEN + 1)+1) - -#endif /* KRB5_DNS_LOOKUP */ - -/* - * Retrieves the default realm to be used if no user-specified realm is - * available. [e.g. to interpret a user-typed principal name with the - * realm omitted for convenience] - * - * returns system errors, NOT_ENOUGH_SPACE, KV5M_CONTEXT - */ - -/* - * Implementation: the default realm is stored in a configuration file, - * named by krb5_config_file; the first token in this file is taken as - * the default local realm name. - */ - -krb5_error_code KRB5_CALLCONV -krb5_get_default_realm(krb5_context context, char **lrealm) -{ - char *realm = 0; - krb5_error_code retval; - - if (!context || (context->magic != KV5M_CONTEXT)) - return KV5M_CONTEXT; - - if (!context->default_realm) { - /* - * XXX should try to figure out a reasonable default based - * on the host's DNS domain. - */ - context->default_realm = 0; - if (context->profile != 0) { - retval = profile_get_string(context->profile, KRB5_CONF_LIBDEFAULTS, - KRB5_CONF_DEFAULT_REALM, 0, 0, - &realm); - - if (!retval && realm) { - context->default_realm = strdup(realm); - if (!context->default_realm) { - profile_release_string(realm); - return ENOMEM; - } - profile_release_string(realm); - } - } -#ifndef KRB5_DNS_LOOKUP - else - return KRB5_CONFIG_CANTOPEN; -#else /* KRB5_DNS_LOOKUP */ - if (context->default_realm == 0) { - int use_dns = _krb5_use_dns_realm(context); - if ( use_dns ) { - /* - * Since this didn't appear in our config file, try looking - * it up via DNS. Look for a TXT records of the form: - * - * _kerberos.<localhost> - * _kerberos.<domainname> - * _kerberos.<searchlist> - * - */ - char localhost[MAX_DNS_NAMELEN+1]; - char * p; - - krb5int_get_fq_local_hostname (localhost, sizeof(localhost)); - - if ( localhost[0] ) { - p = localhost; - do { - retval = k5_try_realm_txt_rr(context, "_kerberos", p, - &context->default_realm); - p = strchr(p,'.'); - if (p) - p++; - } while (retval && p && p[0]); - - if (retval) - retval = k5_try_realm_txt_rr(context, "_kerberos", "", - &context->default_realm); - } else { - retval = k5_try_realm_txt_rr(context, "_kerberos", "", - &context->default_realm); - } - if (retval) { - return(KRB5_CONFIG_NODEFREALM); - } - } - } -#endif /* KRB5_DNS_LOOKUP */ - } - - if (context->default_realm == 0) - return(KRB5_CONFIG_NODEFREALM); - if (context->default_realm[0] == 0) { - free (context->default_realm); - context->default_realm = 0; - return KRB5_CONFIG_NODEFREALM; - } - - realm = context->default_realm; - - if (!(*lrealm = strdup(realm))) - return ENOMEM; - return(0); -} - -krb5_error_code KRB5_CALLCONV -krb5_set_default_realm(krb5_context context, const char *lrealm) -{ - if (!context || (context->magic != KV5M_CONTEXT)) - return KV5M_CONTEXT; - - if (context->default_realm) { - free(context->default_realm); - context->default_realm = 0; - } - - /* Allow the user to clear the default realm setting by passing in - NULL */ - if (!lrealm) return 0; - - context->default_realm = strdup(lrealm); - - if (!context->default_realm) - return ENOMEM; - - return(0); - -} - -void KRB5_CALLCONV -krb5_free_default_realm(krb5_context context, char *lrealm) -{ - free (lrealm); -} diff --git a/src/lib/krb5/os/deps b/src/lib/krb5/os/deps index 63caf75c28..0b53b97d2c 100644 --- a/src/lib/krb5/os/deps +++ b/src/lib/krb5/os/deps @@ -24,28 +24,18 @@ c_ustime.so c_ustime.po $(OUTPRE)c_ustime.$(OBJEXT): \ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ c_ustime.c -def_realm.so def_realm.po $(OUTPRE)def_realm.$(OBJEXT): \ - $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ - $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ - $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ - $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ - $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ - $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ - $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ - $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/locate_plugin.h \ - $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ - $(top_srcdir)/include/socket-utils.h def_realm.c os-proto.h ccdefname.so ccdefname.po $(OUTPRE)ccdefname.$(OBJEXT): \ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ - $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ - $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ - $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ - $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ - $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ - $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/locate_plugin.h \ - $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ - $(top_srcdir)/include/socket-utils.h ccdefname.c os-proto.h + $(COM_ERR_DEPS) $(srcdir)/../ccache/cc-int.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ccdefname.c os-proto.h changepw.so changepw.po $(OUTPRE)changepw.$(OBJEXT): \ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ @@ -149,6 +139,54 @@ hostaddr.so hostaddr.po $(OUTPRE)hostaddr.$(OBJEXT): \ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/locate_plugin.h \ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ $(top_srcdir)/include/socket-utils.h hostaddr.c os-proto.h +hostrealm.so hostrealm.po $(OUTPRE)hostrealm.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/hostrealm_plugin.h \ + $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + hostrealm.c os-proto.h +hostrealm_dns.so hostrealm_dns.po $(OUTPRE)hostrealm_dns.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/hostrealm_plugin.h \ + $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + dnsglue.h hostrealm_dns.c os-proto.h +hostrealm_domain.so hostrealm_domain.po $(OUTPRE)hostrealm_domain.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/hostrealm_plugin.h \ + $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + hostrealm_domain.c os-proto.h +hostrealm_profile.so hostrealm_profile.po $(OUTPRE)hostrealm_profile.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/hostrealm_plugin.h \ + $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + hostrealm_profile.c os-proto.h hst_realm.so hst_realm.po $(OUTPRE)hst_realm.$(OBJEXT): \ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ @@ -160,8 +198,7 @@ hst_realm.so hst_realm.po $(OUTPRE)hst_realm.$(OBJEXT): \ $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/locate_plugin.h \ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ - $(top_srcdir)/include/socket-utils.h dnsglue.h hst_realm.c \ - os-proto.h + $(top_srcdir)/include/socket-utils.h hst_realm.c os-proto.h init_os_ctx.so init_os_ctx.po $(OUTPRE)init_os_ctx.$(OBJEXT): \ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ diff --git a/src/lib/krb5/os/hostrealm.c b/src/lib/krb5/os/hostrealm.c new file mode 100644 index 0000000000..87f8ffb3cc --- /dev/null +++ b/src/lib/krb5/os/hostrealm.c @@ -0,0 +1,401 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/os/hostrealm.c - realm-of-host and default-realm APIs */ +/* + * Copyright (C) 2013 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "k5-int.h" +#include "os-proto.h" +#include <krb5/hostrealm_plugin.h> +#include <ctype.h> + +struct hostrealm_module_handle { + struct krb5_hostrealm_vtable_st vt; + krb5_hostrealm_moddata data; +}; + +/* Release a list of hostrealm module handles. */ +static void +free_handles(krb5_context context, struct hostrealm_module_handle **handles) +{ + struct hostrealm_module_handle *h, **hp; + + if (handles == NULL) + return; + for (hp = handles; *hp != NULL; hp++) { + h = *hp; + if (h->vt.fini != NULL) + h->vt.fini(context, h->data); + free(h); + } + free(handles); +} + +/* Get the registered hostrealm modules including all built-in modules, in the + * proper order. */ +static krb5_error_code +get_modules(krb5_context context, krb5_plugin_initvt_fn **modules_out) +{ + krb5_error_code ret; + const int intf = PLUGIN_INTERFACE_HOSTREALM; + + *modules_out = NULL; + + /* Register built-in modules. */ + ret = k5_plugin_register(context, intf, "profile", + hostrealm_profile_initvt); + if (ret) + return ret; + ret = k5_plugin_register(context, intf, "dns", hostrealm_dns_initvt); + if (ret) + return ret; + ret = k5_plugin_register(context, intf, "domain", hostrealm_domain_initvt); + if (ret) + return ret; + + return k5_plugin_load_all(context, intf, modules_out); +} + +/* Initialize context->hostrealm_handles with a list of module handles. */ +static krb5_error_code +load_hostrealm_modules(krb5_context context) +{ + krb5_error_code ret; + struct hostrealm_module_handle **list = NULL, *handle; + krb5_plugin_initvt_fn *modules = NULL, *mod; + size_t count; + + ret = get_modules(context, &modules); + if (ret != 0) + goto cleanup; + + /* Allocate a large enough list of handles. */ + for (count = 0; modules[count] != NULL; count++); + list = k5alloc((count + 1) * sizeof(*list), &ret); + if (list == NULL) + goto cleanup; + + /* Initialize each module, ignoring ones that fail. */ + count = 0; + for (mod = modules; *mod != NULL; mod++) { + handle = k5alloc(sizeof(*handle), &ret); + if (handle == NULL) + goto cleanup; + ret = (*mod)(context, 1, 1, (krb5_plugin_vtable)&handle->vt); + if (ret != 0) { + TRACE_HOSTREALM_VTINIT_FAIL(context, ret); + free(handle); + continue; + } + + handle->data = NULL; + if (handle->vt.init != NULL) { + ret = handle->vt.init(context, &handle->data); + if (ret != 0) { + TRACE_HOSTREALM_INIT_FAIL(context, handle->vt.name, ret); + free(handle); + continue; + } + } + list[count++] = handle; + list[count] = NULL; + } + list[count] = NULL; + + ret = 0; + context->hostrealm_handles = list; + list = NULL; + +cleanup: + k5_plugin_free_modules(context, modules); + free_handles(context, list); + return ret; +} + +/* Invoke a module's host_realm method, if it has one. */ +static krb5_error_code +host_realm(krb5_context context, struct hostrealm_module_handle *h, + const char *host, char ***realms_out) +{ + if (h->vt.host_realm == NULL) + return KRB5_PLUGIN_NO_HANDLE; + return h->vt.host_realm(context, h->data, host, realms_out); +} + +/* Invoke a module's fallback_realm method, if it has one. */ +static krb5_error_code +fallback_realm(krb5_context context, struct hostrealm_module_handle *h, + const char *host, char ***realms_out) +{ + if (h->vt.fallback_realm == NULL) + return KRB5_PLUGIN_NO_HANDLE; + return h->vt.fallback_realm(context, h->data, host, realms_out); +} + +/* Invoke a module's default_realm method, if it has one. */ +static krb5_error_code +default_realm(krb5_context context, struct hostrealm_module_handle *h, + char ***realms_out) +{ + if (h->vt.default_realm == NULL) + return KRB5_PLUGIN_NO_HANDLE; + return h->vt.default_realm(context, h->data, realms_out); +} + +/* Invoke a module's free_list method. */ +static void +free_list(krb5_context context, struct hostrealm_module_handle *h, + char **list) +{ + h->vt.free_list(context, h->data, list); +} + +/* Copy a null-terminated list of strings. */ +static krb5_error_code +copy_list(char **in, char ***out) +{ + size_t count, i; + char **list; + + *out = NULL; + for (count = 0; in[count] != NULL; count++); + list = calloc(count + 1, sizeof(*list)); + if (list == NULL) + return ENOMEM; + for (i = 0; i < count; i++) { + list[i] = strdup(in[i]); + if (list[i] == NULL) { + krb5_free_host_realm(NULL, list); + return ENOMEM; + } + } + *out = list; + return 0; +} + +/* Construct a one-element realm list containing a copy of realm. */ +krb5_error_code +k5_make_realmlist(const char *realm, char ***realms_out) +{ + char **realms; + + *realms_out = NULL; + realms = calloc(2, sizeof(*realms)); + if (realms == NULL) + return ENOMEM; + realms[0] = strdup(realm); + if (realms[0] == NULL) { + free(realms); + return ENOMEM; + } + *realms_out = realms; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_get_host_realm(krb5_context context, const char *host, char ***realms_out) +{ + krb5_error_code ret; + struct hostrealm_module_handle **hp; + char **realms, cleanname[1024]; + + *realms_out = NULL; + + if (context->hostrealm_handles == NULL) { + ret = load_hostrealm_modules(context); + if (ret) + return ret; + } + + ret = k5_clean_hostname(context, host, cleanname, sizeof(cleanname)); + if (ret) + return ret; + + /* Give each module a chance to determine the host's realms. */ + for (hp = context->hostrealm_handles; *hp != NULL; hp++) { + ret = host_realm(context, *hp, cleanname, &realms); + if (ret == 0) { + ret = copy_list(realms, realms_out); + free_list(context, *hp, realms); + return ret; + } else if (ret != KRB5_PLUGIN_NO_HANDLE) { + return ret; + } + } + + /* Return a list containing the "referral realm" (an empty realm), as a + * cue to try referrals. */ + return k5_make_realmlist(KRB5_REFERRAL_REALM, realms_out); +} + +krb5_error_code KRB5_CALLCONV +krb5_get_fallback_host_realm(krb5_context context, krb5_data *hdata, + char ***realms_out) +{ + krb5_error_code ret; + struct hostrealm_module_handle **hp; + char **realms, *defrealm, *host, cleanname[1024]; + + *realms_out = NULL; + + /* Convert hdata into a string and clean it. */ + host = k5memdup0(hdata->data, hdata->length, &ret); + if (host == NULL) + return ret; + ret = k5_clean_hostname(context, host, cleanname, sizeof(cleanname)); + free(host); + if (ret) + return ret; + + if (context->hostrealm_handles == NULL) { + ret = load_hostrealm_modules(context); + if (ret) + return ret; + } + + /* Give each module a chance to determine the fallback realms. */ + for (hp = context->hostrealm_handles; *hp != NULL; hp++) { + ret = fallback_realm(context, *hp, cleanname, &realms); + if (ret == 0) { + ret = copy_list(realms, realms_out); + free_list(context, *hp, realms); + return ret; + } else if (ret != KRB5_PLUGIN_NO_HANDLE) { + return ret; + } + } + + /* Return a list containing the default realm. */ + ret = krb5_get_default_realm(context, &defrealm); + if (ret) + return ret; + ret = k5_make_realmlist(defrealm, realms_out); + krb5_free_default_realm(context, defrealm); + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_free_host_realm(krb5_context context, char *const *list) +{ + char *const *p; + + for (p = list; p != NULL && *p != NULL; p++) + free(*p); + free((char **)list); + return 0; +} + +/* Get the system default realm using hostrealm modules. */ +static krb5_error_code +get_default_realm(krb5_context context, char **realm_out) +{ + krb5_error_code ret; + struct hostrealm_module_handle **hp; + char **realms; + + *realm_out = NULL; + if (context->hostrealm_handles == NULL) { + ret = load_hostrealm_modules(context); + if (ret) + return ret; + } + + /* Give each module a chance to determine the default realm. */ + for (hp = context->hostrealm_handles; *hp != NULL; hp++) { + ret = default_realm(context, *hp, &realms); + if (ret == 0) { + if (*realms == NULL) { + ret = KRB5_CONFIG_NODEFREALM; + } else { + *realm_out = strdup(realms[0]); + if (*realm_out == NULL) + ret = ENOMEM; + } + free_list(context, *hp, realms); + return ret; + } else if (ret != KRB5_PLUGIN_NO_HANDLE) { + return ret; + } + } + + return KRB5_CONFIG_NODEFREALM; +} + +krb5_error_code KRB5_CALLCONV +krb5_get_default_realm(krb5_context context, char **realm_out) +{ + krb5_error_code ret; + + *realm_out = NULL; + + if (context == NULL || context->magic != KV5M_CONTEXT) + return KV5M_CONTEXT; + + if (context->default_realm == NULL) { + ret = get_default_realm(context, &context->default_realm); + if (ret) + return ret; + } + *realm_out = strdup(context->default_realm); + return (*realm_out == NULL) ? ENOMEM : 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_set_default_realm(krb5_context context, const char *realm) +{ + if (context == NULL || context->magic != KV5M_CONTEXT) + return KV5M_CONTEXT; + + if (context->default_realm != NULL) { + free(context->default_realm); + context->default_realm = NULL; + } + + /* Allow the caller to clear the default realm setting by passing NULL. */ + if (realm != NULL) { + context->default_realm = strdup(realm); + if (context->default_realm == NULL) + return ENOMEM; + } + + return 0; +} + +void KRB5_CALLCONV +krb5_free_default_realm(krb5_context context, char *realm) +{ + free(realm); +} + +void +k5_hostrealm_free_context(krb5_context context) +{ + free_handles(context, context->hostrealm_handles); + context->hostrealm_handles = NULL; +} diff --git a/src/lib/krb5/os/hostrealm_dns.c b/src/lib/krb5/os/hostrealm_dns.c new file mode 100644 index 0000000000..7f017a856c --- /dev/null +++ b/src/lib/krb5/os/hostrealm_dns.c @@ -0,0 +1,143 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/os/hostream_dns.c - dns hostrealm module */ +/* + * Copyright (C) 1990,1991,2002,2008,2009,2013 by the Massachusetts Institute + * of Technology. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file implements the built-in dns module for the hostrealm interface, + * which uses TXT records in the DNS to determine the default realm or the + * fallback realm of a host. + */ + +#include "k5-int.h" +#include "os-proto.h" +#include <krb5/hostrealm_plugin.h> + +#ifdef KRB5_DNS_LOOKUP +#include "dnsglue.h" + +/* Try a _kerberos TXT lookup for fqdn and each parent domain; return the + * resulting realm (caller must free) or NULL. */ +static char * +txt_lookup(krb5_context context, const char *fqdn) +{ + char *realm; + + while (fqdn != NULL && *fqdn != '\0') { + if (k5_try_realm_txt_rr(context, "_kerberos", fqdn, &realm) == 0) + return realm; + fqdn = strchr(fqdn, '.'); + if (fqdn != NULL) + fqdn++; + } + return NULL; +} + +static krb5_error_code +dns_fallback_realm(krb5_context context, krb5_hostrealm_moddata data, + const char *host, char ***realms_out) +{ + krb5_error_code ret; + char *realm; + + *realms_out = NULL; + if (!_krb5_use_dns_realm(context) || k5_is_numeric_address(host)) + return KRB5_PLUGIN_NO_HANDLE; + + /* Try a TXT record lookup for each component of host. */ + realm = txt_lookup(context, host); + if (realm == NULL) + return KRB5_PLUGIN_NO_HANDLE; + ret = k5_make_realmlist(realm, realms_out); + free(realm); + return ret; +} + +static krb5_error_code +dns_default_realm(krb5_context context, krb5_hostrealm_moddata data, + char ***realms_out) +{ + krb5_error_code ret; + char localhost[MAXDNAME + 1], *realm; + + *realms_out = NULL; + if (!_krb5_use_dns_realm(context)) + return KRB5_PLUGIN_NO_HANDLE; + + ret = krb5int_get_fq_local_hostname(localhost, sizeof(localhost)); + if (ret) + return ret; + + /* If we don't find a TXT record for localhost or any parent, look for a + * global record. */ + realm = txt_lookup(context, localhost); + if (realm == NULL) + (void)k5_try_realm_txt_rr(context, "_kerberos", NULL, &realm); + + if (realm == NULL) + return KRB5_PLUGIN_NO_HANDLE; + ret = k5_make_realmlist(realm, realms_out); + free(realm); + return ret; +} + +static void +dns_free_realmlist(krb5_context context, krb5_hostrealm_moddata data, + char **list) +{ + krb5_free_host_realm(context, list); +} + +krb5_error_code +hostrealm_dns_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_hostrealm_vtable vt = (krb5_hostrealm_vtable)vtable; + + vt->name = "dns"; + vt->fallback_realm = dns_fallback_realm; + vt->default_realm = dns_default_realm; + vt->free_list = dns_free_realmlist; + return 0; +} + +#else /* KRB5_DNS_LOOKUP */ + +krb5_error_code +hostrealm_dns_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_hostrealm_vtable vt = (krb5_hostrealm_vtable)vtable; + + vt->name = "dns"; + return 0; +} + +#endif /* KRB5_DNS_LOOKUP */ diff --git a/src/lib/krb5/os/hostrealm_domain.c b/src/lib/krb5/os/hostrealm_domain.c new file mode 100644 index 0000000000..dc9cc59b59 --- /dev/null +++ b/src/lib/krb5/os/hostrealm_domain.c @@ -0,0 +1,128 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/os/hostream_domain.c - domain hostrealm module */ +/* + * Copyright (C) 1990,1991,2002,2008,2009,2013 by the Massachusetts Institute + * of Technology. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file implements the built-in domain module for the hostrealm interface, + * which uses domain-based heuristics to determine the fallback realm of a + * host. + */ + +#include "k5-int.h" +#include "os-proto.h" +#include <krb5/hostrealm_plugin.h> +#include <ctype.h> + +static krb5_error_code +domain_fallback_realm(krb5_context context, krb5_hostrealm_moddata data, + const char *host, char ***realms_out) +{ + krb5_error_code ret; + struct serverlist slist; + krb5_data drealm; + char *uhost = NULL, *p; + const char *suffix, *dot; + int limit; + + *realms_out = NULL; + + /* These heuristics don't apply to address literals. */ + if (k5_is_numeric_address(host)) + return KRB5_PLUGIN_NO_HANDLE; + + /* Make an uppercase copy of host. */ + uhost = strdup(host); + if (uhost == NULL) + return ENOMEM; + for (p = uhost; *p != '\0'; p++) { + if (islower((unsigned char)*p)) + *p = toupper((unsigned char)*p); + } + + /* + * Try searching domain suffixes as realms. This heuristic is turned off + * by default. If DNS lookups for KDCs are enabled (as they are by + * default), an attacker could control which domain component is used as + * the realm for a host. + * + * A realm_try_domains value of -1 (the default) means not to search at + * all, a value of 0 means to try only the full domain itself, 1 means to + * also try the parent domain, etc.. We will stop searching when we reach + * a suffix with only one label. + */ + ret = profile_get_integer(context->profile, KRB5_CONF_LIBDEFAULTS, + KRB5_CONF_REALM_TRY_DOMAINS, 0, -1, &limit); + if (ret) + return ret; + suffix = uhost; + while (limit-- >= 0 && (dot = strchr(suffix, '.')) != NULL) { + drealm = string2data((char *)suffix); + if (k5_locate_kdc(context, &drealm, &slist, FALSE, SOCK_DGRAM) == 0) { + k5_free_serverlist(&slist); + ret = k5_make_realmlist(suffix, realms_out); + goto cleanup; + } + suffix = dot + 1; + } + + /* + * If that didn't succeed, use the upper-cased parent domain of the + * hostname, regardless of whether we can actually look it up as a realm. + */ + dot = strchr(uhost, '.'); + if (dot != NULL) + ret = k5_make_realmlist(dot + 1, realms_out); + else + ret = KRB5_PLUGIN_NO_HANDLE; + +cleanup: + free(uhost); + return ret; +} + +static void +domain_free_realmlist(krb5_context context, krb5_hostrealm_moddata data, + char **list) +{ + krb5_free_host_realm(context, list); +} + +krb5_error_code +hostrealm_domain_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_hostrealm_vtable vt = (krb5_hostrealm_vtable)vtable; + + vt->name = "domain"; + vt->fallback_realm = domain_fallback_realm; + vt->free_list = domain_free_realmlist; + return 0; +} diff --git a/src/lib/krb5/os/hostrealm_profile.c b/src/lib/krb5/os/hostrealm_profile.c new file mode 100644 index 0000000000..6b99c05bbe --- /dev/null +++ b/src/lib/krb5/os/hostrealm_profile.c @@ -0,0 +1,117 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/os/hostream_profile.c - profile hostrealm module */ +/* + * Copyright (C) 1990,1991,2002,2008,2009,2013 by the Massachusetts Institute + * of Technology. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file implements the built-in profile module for the hostrealm + * interface, which uses profile configuration to determine the local default + * realm or the authoritative realm of a host. + */ + +#include "k5-int.h" +#include "os-proto.h" +#include <krb5/hostrealm_plugin.h> + +/* + * Search progressively shorter suffixes of host in the [domain_realms] section + * of the profile to find the realm. For example, given a host a.b.c, try to + * match a.b.c, then .b.c, then b.c, then .c, then c. If we don't find a + * match, return success but set *realm_out to NULL. + */ +static krb5_error_code +profile_host_realm(krb5_context context, krb5_hostrealm_moddata data, + const char *host, char ***realms_out) +{ + krb5_error_code ret; + const char *p; + char *prof_realm; + + *realms_out = NULL; + + /* Don't look up IP addresses in [domain_realms]. */ + if (k5_is_numeric_address(host)) + return KRB5_PLUGIN_NO_HANDLE; + + /* Look for the host and each suffix in the [domain_realms] section. */ + for (p = host; p != NULL; p = (*p == '.') ? p + 1 : strchr(p, '.')) { + ret = profile_get_string(context->profile, KRB5_CONF_DOMAIN_REALM, p, + NULL, NULL, &prof_realm); + if (ret) + return ret; + if (prof_realm != NULL) { + ret = k5_make_realmlist(prof_realm, realms_out); + profile_release_string(prof_realm); + return ret; + } + } + return KRB5_PLUGIN_NO_HANDLE; +} + +/* Look up the default_realm variable in the [libdefaults] section of the + * profile. */ +static krb5_error_code +profile_default_realm(krb5_context context, krb5_hostrealm_moddata data, + char ***realms_out) +{ + krb5_error_code ret; + char *prof_realm; + + *realms_out = NULL; + ret = profile_get_string(context->profile, KRB5_CONF_LIBDEFAULTS, + KRB5_CONF_DEFAULT_REALM, NULL, NULL, &prof_realm); + if (ret) + return ret; + if (prof_realm == NULL) + return KRB5_PLUGIN_NO_HANDLE; + ret = k5_make_realmlist(prof_realm, realms_out); + profile_release_string(prof_realm); + return ret; +} + +static void +profile_free_realmlist(krb5_context context, krb5_hostrealm_moddata data, + char **list) +{ + krb5_free_host_realm(context, list); +} + +krb5_error_code +hostrealm_profile_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_hostrealm_vtable vt = (krb5_hostrealm_vtable)vtable; + + vt->name = "profile"; + vt->host_realm = profile_host_realm; + vt->default_realm = profile_default_realm; + vt->free_list = profile_free_realmlist; + return 0; +} diff --git a/src/lib/krb5/os/hst_realm.c b/src/lib/krb5/os/hst_realm.c index 0c1579b689..7cb7c5f619 100644 --- a/src/lib/krb5/os/hst_realm.c +++ b/src/lib/krb5/os/hst_realm.c @@ -34,14 +34,6 @@ #include "fake-addrinfo.h" -#ifdef KRB5_DNS_LOOKUP -#include "dnsglue.h" -#else -#ifndef MAXDNAME -#define MAXDNAME (16 * MAXHOSTNAMELEN) -#endif /* MAXDNAME */ -#endif /* KRB5_DNS_LOOKUP */ - #if defined(_WIN32) && !defined(__CYGWIN32__) #ifndef EAFNOSUPPORT #define EAFNOSUPPORT WSAEAFNOSUPPORT @@ -117,8 +109,8 @@ krb5int_get_fq_local_hostname(char *buf, size_t bufsize) } /* Return true if name appears to be an IPv4 or IPv6 address. */ -static krb5_boolean -is_numeric_address(const char *name) +krb5_boolean +k5_is_numeric_address(const char *name) { int ndots = 0; const char *p; @@ -141,236 +133,6 @@ is_numeric_address(const char *name) return FALSE; } -/* - * Search progressively shorter suffixes of host in the [domain_realms] section - * of the profile to find the realm. For example, given a host a.b.c, try to - * match a.b.c, then .b.c, then b.c, then .c, then c. If we don't find a - * match, return success but set *realm_out to NULL. - */ -static krb5_error_code -search_domain_realm(krb5_context context, const char *host, char **realm_out) -{ - krb5_error_code ret; - const char *p; - char *prof_realm; - - *realm_out = NULL; - for (p = host; p != NULL; p = (*p == '.') ? p + 1 : strchr(p, '.')) { - ret = profile_get_string(context->profile, KRB5_CONF_DOMAIN_REALM, p, - NULL, NULL, &prof_realm); - if (ret) - return ret; - if (prof_realm != NULL) { - *realm_out = strdup(prof_realm); - profile_release_string(prof_realm); - if (*realm_out == NULL) - return ENOMEM; - return 0; - } - } - return 0; -} - -krb5_error_code KRB5_CALLCONV -krb5_get_host_realm(krb5_context context, const char *host, char ***realmsp) -{ - char **retrealms, *realm = NULL; - krb5_error_code ret; - char cleanname[MAXDNAME + 1]; - - *realmsp = NULL; - - ret = k5_clean_hostname(context, host, cleanname, sizeof(cleanname)); - if (ret) - return ret; - - /* Search the [domain_realm] profile section unless the hostname looks like - * an IP address. */ - if (!is_numeric_address(cleanname)) - ret = search_domain_realm(context, cleanname, &realm); - - /* If we didn't find a match, return the referral realm. */ - if (realm == NULL) { - realm = strdup(KRB5_REFERRAL_REALM); - if (realm == NULL) - return ENOMEM; - } - - retrealms = calloc(2, sizeof(*retrealms)); - if (retrealms == NULL) { - free(realm); - return ENOMEM; - } - - retrealms[0] = realm; - retrealms[1] = 0; - - TRACE_GET_HOST_REALM_RETURN(context, host, realm); - *realmsp = retrealms; - return 0; -} - -/* - * Walk through the components of a domain. At each stage determine if a KDC - * can be located for that domain. Return a realm corresponding to the - * upper-cased domain name for which a KDC was found or NULL if no KDC was - * found. Stop searching after limit labels have been removed from the domain - * (-1 means don't search at all, 0 means try only the full domain itself, 1 - * means also try the parent domain, etc.) or when we reach a parent with only - * one label. - */ -static krb5_error_code -domain_heuristic(krb5_context context, const char *domain, char **realm, - int limit) -{ - krb5_error_code ret = 0, r; - struct serverlist slist; - krb5_data drealm; - char *p = NULL, *fqdn, *dot; - - *realm = NULL; - if (limit < 0) - return 0; - - memset(&drealm, 0, sizeof(drealm)); - fqdn = strdup(domain); - if (fqdn == NULL) { - ret = ENOMEM; - goto cleanup; - } - - /* Upper case the domain (for use as a realm). */ - for (p = fqdn; *p != '\0'; p++) { - if (islower((unsigned char)*p)) - *p = toupper((unsigned char)*p); - } - - /* Search up to limit parents, as long as we have multiple labels. */ - p = fqdn; - while (limit-- >= 0 && (dot = strchr(p, '.')) != NULL) { - /* Find a KDC based on this part of the domain name. */ - drealm = string2data(p); - r = k5_locate_kdc(context, &drealm, &slist, FALSE, SOCK_DGRAM); - if (r == 0) { - k5_free_serverlist(&slist); - *realm = strdup(p); - if (*realm == NULL) { - ret = ENOMEM; - goto cleanup; - } - break; - } - - p = dot + 1; - } - -cleanup: - free(fqdn); - return ret; -} - -/* - * Determine the fallback realm. Used by krb5_get_credentials after referral - * processing has failed, to look at TXT records or make a DNS-based - * assumption. - */ -krb5_error_code KRB5_CALLCONV -krb5_get_fallback_host_realm(krb5_context context, krb5_data *hdata, - char ***realmsp) -{ - char **retrealms, *p, *realm = NULL, *host, cleanname[MAXDNAME + 1]; - krb5_error_code ret; - int limit; - errcode_t code; - krb5_boolean is_numeric; - - *realmsp = NULL; - - /* Convert hdata into a string and clean it up. */ - host = k5memdup0(hdata->data, hdata->length, &ret); - if (host == NULL) - return ret; - ret = k5_clean_hostname(context, host, cleanname, sizeof(cleanname)); - free(host); - if (ret) - return ret; - is_numeric = is_numeric_address(cleanname); - - /* - * Try looking up a _kerberos.<hostname> TXT record in DNS. This heuristic - * is turned off by default since, in the absence of secure DNS, it can - * allow an attacker to control the realm used for a host. - */ -#ifdef KRB5_DNS_LOOKUP - if (_krb5_use_dns_realm(context) && !is_numeric) { - p = cleanname; - do { - ret = k5_try_realm_txt_rr(context, "_kerberos", p, &realm); - p = strchr(p, '.'); - if (p != NULL) - p++; - } while (ret && p != NULL && *p != '\0'); - } -#endif /* KRB5_DNS_LOOKUP */ - - /* - * Next try searching the domain components as realms. This heuristic is - * also turned off by default. If DNS lookups for KDCs are enabled (as - * they are by default), an attacker could control which domain component - * is used as the realm for a host. - */ - if (realm == NULL && !is_numeric) { - code = profile_get_integer(context->profile, KRB5_CONF_LIBDEFAULTS, - KRB5_CONF_REALM_TRY_DOMAINS, 0, -1, &limit); - if (code == 0) { - ret = domain_heuristic(context, cleanname, &realm, limit); - if (ret) - return ret; - } - } - - /* - * The next fallback--and the first one to apply with default - * configuration--is to use the upper-cased parent domain of the hostname, - * regardless of whether we can actually look it up as a realm. - */ - if (realm == NULL && !is_numeric) { - p = strchr(cleanname, '.'); - if (p) { - realm = strdup(p + 1); - if (realm == NULL) - return ENOMEM; - for (p = realm; *p != '\0'; p++) { - if (islower((unsigned char)*p)) - *p = toupper((unsigned char)*p); - } - } - } - - /* - * The final fallback--used when the fully-qualified hostname has only one - * component--is to use the local default realm. - */ - if (realm == NULL) { - ret = krb5_get_default_realm(context, &realm); - if (ret) - return ret; - } - - retrealms = calloc(2, sizeof(*retrealms)); - if (retrealms == NULL) { - free(realm); - return ENOMEM; - } - - retrealms[0] = realm; - retrealms[1] = 0; - - TRACE_GET_FALLBACK_HOST_REALM_RETURN(context, host, realm); - *realmsp = retrealms; - return 0; -} - /* Common code for krb5_get_host_realm and krb5_get_fallback_host_realm * to do basic sanity checks on supplied hostname. */ krb5_error_code @@ -404,16 +166,3 @@ k5_clean_hostname(krb5_context context, const char *host, char *cleanname, return 0; } - -krb5_error_code KRB5_CALLCONV -krb5_free_host_realm(krb5_context context, char *const *realmlist) -{ - char *const *p; - - if (realmlist == NULL) - return 0; - for (p = realmlist; *p; p++) - free(*p); - free((char **)realmlist); - return 0; -} diff --git a/src/lib/krb5/os/os-proto.h b/src/lib/krb5/os/os-proto.h index e2891a1e0e..c6b730f81b 100644 --- a/src/lib/krb5/os/os-proto.h +++ b/src/lib/krb5/os/os-proto.h @@ -133,6 +133,8 @@ krb5_error_code k5_time_with_offset(krb5_timestamp offset, krb5_int32 *usec_out); void k5_set_prompt_types(krb5_context, krb5_prompt_type *); krb5_error_code k5_clean_hostname(krb5_context, const char *, char *, size_t); +krb5_boolean k5_is_numeric_address(const char *name); +krb5_error_code k5_make_realmlist(const char *realm, char ***realms_out); krb5_error_code k5_kt_client_default_name(krb5_context context, char **name_out); krb5_error_code k5_write_messages(krb5_context, krb5_pointer, krb5_data *, @@ -146,6 +148,16 @@ extern unsigned int krb5_max_skdc_timeout; extern unsigned int krb5_skdc_timeout_shift; extern unsigned int krb5_skdc_timeout_1; +void k5_hostrealm_free_context(krb5_context); +krb5_error_code hostrealm_profile_initvt(krb5_context context, int maj_ver, + int min_ver, + krb5_plugin_vtable vtable); +krb5_error_code hostrealm_dns_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable); +krb5_error_code hostrealm_domain_initvt(krb5_context context, int maj_ver, + int min_ver, + krb5_plugin_vtable vtable); + void k5_localauth_free_context(krb5_context); krb5_error_code localauth_names_initvt(krb5_context context, int maj_ver, int min_ver, krb5_plugin_vtable vtable); |