summaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2013-08-05 15:57:29 -0400
committerGreg Hudson <ghudson@mit.edu>2013-08-15 12:39:57 -0400
commitdb21244a069e581a392dff5b320e758e06a28e4d (patch)
tree7a99f0700c983da998571a7ab4bf845020a304be /src/lib
parentd61fbd85467c71c9bfb185e0e675e1619972bd0b (diff)
downloadkrb5-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.c1
-rw-r--r--src/lib/krb5/libkrb5.exports1
-rw-r--r--src/lib/krb5/os/Makefile.in15
-rw-r--r--src/lib/krb5/os/def_realm.c190
-rw-r--r--src/lib/krb5/os/deps79
-rw-r--r--src/lib/krb5/os/hostrealm.c401
-rw-r--r--src/lib/krb5/os/hostrealm_dns.c143
-rw-r--r--src/lib/krb5/os/hostrealm_domain.c128
-rw-r--r--src/lib/krb5/os/hostrealm_profile.c117
-rw-r--r--src/lib/krb5/os/hst_realm.c255
-rw-r--r--src/lib/krb5/os/os-proto.h12
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);