]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Default dns_canonicalize_hostname to "fallback"
authorGreg Hudson <ghudson@mit.edu>
Wed, 27 May 2020 22:48:35 +0000 (18:48 -0400)
committerGreg Hudson <ghudson@mit.edu>
Fri, 29 May 2020 21:49:36 +0000 (17:49 -0400)
This change should mitigate some of the pain caused by the rdns=true
default (generally associated with unwanted PTR records that cannot
easily be changed), with a minimum of fallout.

Update the documentation and tests accordingly.  In test environments,
disable qualify_shortname and use the uncanonicalized system hostname
(lowercased) to match the initial sn2princ result.

ticket: 8911 (new)

13 files changed:
doc/admin/appl_servers.rst
doc/admin/conf_files/krb5_conf.rst
doc/admin/princ_dns.rst
src/kadmin/testing/proto/krb5.conf.proto
src/kadmin/testing/scripts/env-setup.shin
src/kadmin/testing/scripts/init_db
src/kadmin/testing/scripts/start_servers
src/kadmin/testing/scripts/start_servers_local
src/lib/kadm5/unit-test/api.current/init-v2.exp
src/lib/krb5/krb/init_ctx.c
src/tests/dejagnu/config/default.exp
src/tests/t_sn2princ.py
src/util/k5test.py

index 5232db9af0ca2175c7ae445d3a3e5aa2a256eca4..afdf30297c3b3fe62ac68b64af0a8f0254e4cdd9 100644 (file)
@@ -115,14 +115,12 @@ Getting DNS information correct
 -------------------------------
 
 Several aspects of Kerberos rely on name service.  When a hostname is
-used to name a service, the Kerberos library canonicalizes the
-hostname using forward and reverse name resolution.  (The reverse name
-resolution step can be turned off using the **rdns** variable in
-:ref:`libdefaults`.)  The result of this canonicalization must match
-the principal entry in the host's keytab, or authentication will fail.
-
-Each host's canonical name must be the fully-qualified host name
-(including the domain), and each host's IP address must
+used to name a service, clients may canonicalize the hostname using
+forward and possibly reverse name resolution.  The result of this
+canonicalization must match the principal entry in the host's keytab,
+or authentication will fail.  To work with all client canonicalization
+configurations, each host's canonical name must be the fully-qualified
+host name (including the domain), and each host's IP address must
 reverse-resolve to the canonical name.
 
 Configuration of hostnames varies by operating system.  On the
index 1d8ffc1e4650d0ae245f22692bbdc2430b515a58..7f2879640ce4ed0e0633896519f29bfa6ca3b20d 100644 (file)
@@ -188,11 +188,10 @@ The libdefaults section may contain any of the following relations:
     hostnames for use in service principal names.  Setting this flag
     to false can improve security by reducing reliance on DNS, but
     means that short hostnames will not be canonicalized to
-    fully-qualified hostnames.  The default value is true.
-
-    If this option is set to ``fallback`` (new in release 1.18), DNS
-    canonicalization will only be performed the server hostname is not
-    found with the original name when requesting credentials.
+    fully-qualified hostnames.  If this option is set to ``fallback`` (new
+    in release 1.18), DNS canonicalization will only be performed the
+    server hostname is not found with the original name when
+    requesting credentials.  The default value is ``fallback``.
 
 **dns_lookup_kdc**
     Indicate whether DNS SRV records should be used to locate the KDCs
index e1d823f279272e4929885e25ec9a7a99f131eee0..32a269afc939906dee528964659556223672f3a5 100644 (file)
@@ -31,27 +31,35 @@ based on rotating ``CNAME`` records in DNS.
 Service principal canonicalization
 ----------------------------------
 
-MIT Kerberos clients currently always do forward resolution (looking
-up the IPv4 and possibly IPv6 addresses using ``getaddrinfo()``) of
-the hostname part of a host-based service principal to canonicalize
-the hostname.  They obtain the "canonical" name of the host when doing
-so.  By default, MIT Kerberos clients will also then do reverse DNS
-resolution (looking up the hostname associated with the IPv4 or IPv6
-address using ``getnameinfo()``) of the hostname.  Using the
-:ref:`krb5.conf(5)` setting::
+In the MIT krb5 client library, canonicalization of host-based service
+principals is controlled by the **dns_canonicalize_hostname**,
+**rnds**, and **qualify_shortname** variables in :ref:`libdefaults`.
+
+If **dns_canonicalize_hostname** is set to ``true`` (the default value
+before release 1.19), the client performs forward resolution by
+looking up the IPv4 and/or IPv6 addresses of the hostname using
+``getaddrinfo()``.  This process will typically add a domain suffix to
+the hostname if needed, and follow CNAME records in the DNS.  If
+**rdns** is also set to ``true`` (the default), the client will then
+perform a reverse lookup of the first returned Internet address using
+``getnameinfo()``, finding the name associated with the PTR record.
+
+If **dns_canonicalize_hostname** is set to ``false``, the hostname is
+not canonicalized using DNS.  If the hostname has only one component
+(i.e. it contains no "." characters), the host's primary DNS search
+domain will be appended, if there is one.  The **qualify_shortname**
+variable can be used to override or disable this suffix.
+
+If **dns_canonicalize_hostname** is set to ``fallback`` (the default
+value in release 1.19 and later), the hostname is initially treated
+according to the rules for ``dns_canonicalize_hostname=false``.  If a
+ticket request fails because the service principal is unknown, it the
+hostname will be canonicalized according to the rules for
+``dns_canonicalize_hostname=true`` and the request will be retried.
+
+In all cases, the hostname is converted to lowercase, and any trailing
+dot is removed.
 
-    [libdefaults]
-        rdns = false
-
-will disable reverse DNS lookup on clients.  The default setting is
-"true".
-
-Operating system bugs may prevent a setting of ``rdns = false`` from
-disabling reverse DNS lookup.  Some versions of GNU libc have a bug in
-``getaddrinfo()`` that cause them to look up ``PTR`` records even when
-not required.  MIT Kerberos releases krb5-1.10.2 and newer have a
-workaround for this problem, as does the krb5-1.9.x series as of
-release krb5-1.9.4.
 
 
 Reverse DNS mismatches
index e710852d456cc8a46fd1640541f03a49dbb537e5..c0af716a57512f4672d5165596612be6a0a03616 100644 (file)
@@ -2,19 +2,19 @@
        default_realm = __REALM__
        default_keytab_name = FILE:__K5ROOT__/keytab
        dns_fallback = no
+       qualify_shortname = ""
        plugin_base_dir = __PLUGIN_DIR__
        allow_weak_crypto = true
 
 [realms]
        __REALM__ = {
-               kdc = __KDCHOST__:1750
-               admin_server = __KDCHOST__:1751
+               kdc = __HOSTNAME__:1750
+               admin_server = __HOSTNAME__:1751
                database_module = foobar_db2_module_blah
        }
 
 [domain_realm]
-       __LOCALHOST__ = __REALM__
-       __KDCHOST__ = __REALM__
+       __HOSTNAME__ = __REALM__
 
 [logging]
        admin_server = FILE:__K5ROOT__/syslog
index 969c5340cd99de44670b137c5dda9a4a29e8e73f..88f8ad1aa891e32a05935a9f4485eb05cb2f4fff 100755 (executable)
@@ -71,8 +71,8 @@ BSDDB_DUMP=$TESTDIR/util/bsddb_dump; export BSDDB_DUMP
 CLNTTCL=$TESTDIR/util/kadm5_clnt_tcl; export CLNTTCL
 SRVTCL=$TESTDIR/util/kadm5_srv_tcl; export SRVTCL
 
-QUALNAME=`$BUILDTOP/tests/resolve/resolve -q | tr '[A-Z]' '[a-z]'`
-export QUALNAME
+HOSTNAME=`hostname | tr '[A-Z]' '[a-z]'`
+export HOSTNAME
 
 KRB5_CONFIG=$K5ROOT/krb5.conf; export KRB5_CONFIG
 KRB5_KDC_PROFILE=$K5ROOT/kdc.conf; export KRB5_KDC_PROFILE
index e65826c9635dc2201ee6ac036b82cd81cbf4e6ab..216f62793324322cad544d4101b8151d85f8c44e 100755 (executable)
@@ -79,8 +79,7 @@ fi
 # done
 
 sed -e "s/__REALM__/$REALM/g" -e "s#__K5ROOT__#$K5ROOT#g" \
-       -e "s/__KDCHOST__/$QUALNAME/g" \
-       -e "s/__LOCALHOST__/$QUALNAME/g" \
+       -e "s/__HOSTNAME__/$HOSTNAME/g" \
        -e "s#__MODDIR__#$MODDIR#g" \
        < $STESTDIR/proto/krb5.conf.proto > $K5ROOT/krb5.conf
 sed -e "s/__REALM__/$REALM/g" -e "s#__K5ROOT__#$K5ROOT#g" \
index f23df06828f8347dde5d288284f5a59c78fceedf..05519e4ee1fc51c3eb26d48109ffc3529e197377 100755 (executable)
@@ -36,8 +36,7 @@ if [ $local = 0 ]; then
 
        # Fix up the local krb5.conf to point to the remote 
        sed -e "s/__REALM__/$REALM/g" -e "s#__K5ROOT__#$K5ROOT#g" \
-               -e "s/__KDCHOST__/$hostname/g" \
-               -e "s/__LOCALHOST__/$QUALNAME/g" \
+               -e "s/__HOSTNAME__/$HOSTNAME/g" \
                -e "s#__MODDIR__#$TOP/../plugins/kdb#g"\
                -e "s#__PLUGIN_DIR__#$TOP/../plugins#g"\
                < $STESTDIR/proto/krb5.conf.proto > $K5ROOT/krb5.conf
index 998ef9164d72ae2e8f3c1389fe49e2591e9a1563..858e88031ea204eae1cf386562a07fc29dabc8a2 100755 (executable)
@@ -79,7 +79,7 @@ cat - > /tmp/start_servers_local$$ <<\EOF
 if { [catch {
        source $env(STOP)/testing/tcl/util.t
        set r $env(REALM)
-       set q $env(QUALNAME)
+       set q $env(HOSTNAME)
        puts stdout [kadm5_init $env(SRVTCL) mrroot null \
                [config_params {KADM5_CONFIG_REALM} $r] \
                $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 server_handle]
index 7a353d4e9ce247a149e894dd0b9f387dde65e0fb..47764c2129a22455a026a75685cbf1f11fc5b71c 100644 (file)
@@ -3,18 +3,14 @@ load_lib lib.t
 api_exit
 api_start
 
-if ![info exists RESOLVE] {
-    set RESOLVE [findfile $objdir/../../../tests/resolve/resolve]
-}
 proc get_hostname { } {
-    global RESOLVE
     global hostname
 
     if {[info exists hostname]} {
        return 1
     }
 
-    catch "exec $RESOLVE -q >myname" exec_output
+    catch "exec hostname >myname" exec_output
     if ![string match "" $exec_output] {
        send_log "$exec_output\n"
        verbose $exec_output
index be31eb31e01c2a236967dcfe7e91405a83ceab25..21d5cb1ca58c71bd370acce5fbe36392b27716c7 100644 (file)
@@ -238,7 +238,7 @@ krb5_init_context_profile(profile_t profile, krb5_flags flags,
     ctx->enforce_ok_as_delegate = tmp;
 
     retval = get_tristate(ctx, KRB5_CONF_DNS_CANONICALIZE_HOSTNAME, "fallback",
-                          CANONHOST_FALLBACK, 1, &tmp);
+                          CANONHOST_FALLBACK, CANONHOST_FALLBACK, &tmp);
     if (retval)
         goto cleanup;
     ctx->dns_canonicalize_hostname = tmp;
index f5536c6dd281ba9de8e7077f2bbfa04ff3bc7e96..619fcce48ff216e938ddcc5ee997fb1fd3ae2d51 100644 (file)
@@ -303,7 +303,6 @@ foreach i {
     {KTUTIL $objdir/../../kadmin/ktutil/ktutil}
     {KLIST $objdir/../../clients/klist/klist}
     {KDESTROY $objdir/../../clients/kdestroy/kdestroy}
-    {RESOLVE $objdir/../resolve/resolve}
     {T_INETD $objdir/t_inetd}
     {KPROPLOG $objdir/../../kprop/kproplog}
     {KPASSWD $objdir/../../clients/kpasswd/kpasswd}
@@ -497,7 +496,6 @@ proc setup_runtime_env { } {
 # 0 on failure.
 
 proc get_hostname { } {
-    global RESOLVE
     global hostname
     global tmppwd
 
@@ -507,7 +505,7 @@ proc get_hostname { } {
 
     envstack_push
     setup_runtime_env
-    catch "exec $RESOLVE -q >$tmppwd/hostname" exec_output
+    catch "exec hostname >$tmppwd/hostname" exec_output
     envstack_pop
     if ![string match "" $exec_output] {
        verbose -log $exec_output
@@ -745,6 +743,7 @@ proc setup_krb5_conf { {type client} } {
        puts $conffile "\[libdefaults\]"
        puts $conffile "        default_realm = $REALMNAME"
        puts $conffile "        dns_lookup_kdc = false"
+       puts $conffile "        qualify_shortname = \"\""
        if [info exists allow_weak_crypto($type)] {
            puts $conffile "    allow_weak_crypto = $allow_weak_crypto($type)"
        } else {
index f1b21c521dc153d2450bfd2bf677af3f9ac1e1d8..ca94af4e10fffaad16ee59ed281a953704890b20 100755 (executable)
@@ -2,7 +2,8 @@ from k5test import *
 
 offline = (len(args) > 0 and args[0] != "no")
 
-conf = {'domain_realm': {'kerberos.org': 'R1',
+conf = {'libdefaults': {'dns_canonicalize_hostname': 'true'},
+        'domain_realm': {'kerberos.org': 'R1',
                          'example.com': 'R2',
                          'mit.edu': 'R3'}}
 no_rdns_conf = {'libdefaults': {'rdns': 'false'}}
@@ -28,7 +29,7 @@ def testbase(host, nametype, princhost, princrealm, env=None):
         fail('Expected %s, got %s' % (expected, out))
 
 def test(host, princhost, princrealm):
-    # Test with the host-based name type in the default environment.
+    # Test with the host-based name type with canonicalization enabled.
     testbase(host, 'srv-hst', princhost, princrealm)
 
 def testnc(host, princhost, princrealm):
index 442a4e4f7313a1ff6408e73b64787f70187286b5..e58c9fd8a81186d6e169ce325dd3366badd9fdf4 100644 (file)
@@ -193,7 +193,10 @@ Scripts may use the following functions and variables:
 
 * plugins: The plugin directory in the build tree (absolute path).
 
-* hostname: This machine's fully-qualified domain name.
+* hostname: The local hostname as it will initially appear in
+  krb5_sname_to_principal() results.  (Shortname qualification is
+  turned off in the test environment to make this value easy to
+  discover from Python.)
 
 * null_input: A file opened to read /dev/null.
 
@@ -525,23 +528,6 @@ def _find_srctop():
     return os.path.abspath(root)
 
 
-# Return the local hostname as it will be canonicalized by
-# krb5_sname_to_principal.  We can't simply use socket.getfqdn()
-# because it explicitly prefers results containing periods and
-# krb5_sname_to_principal doesn't care.
-def _get_hostname():
-    hostname = socket.gethostname()
-    try:
-        ai = socket.getaddrinfo(hostname, None, 0, 0, 0, socket.AI_CANONNAME)
-    except socket.gaierror as e:
-        fail('Local hostname "%s" does not resolve: %s.' % (hostname, e[1]))
-    (family, socktype, proto, canonname, sockaddr) = ai[0]
-    try:
-        name = socket.getnameinfo(sockaddr, socket.NI_NAMEREQD)
-    except socket.gaierror:
-        return canonname.lower()
-    return name[0].lower()
-
 # Parse command line arguments, setting global option variables.  Also
 # sets the global variable args to the positional arguments, which may
 # be used by the test script.
@@ -1263,6 +1249,7 @@ _default_krb5_conf = {
     'libdefaults': {
         'default_realm': '$realm',
         'dns_lookup_kdc': 'false',
+        'qualify_shortname': '',
         'plugin_base_dir': '$plugins'},
     'realms': {'$realm': {
             'kdc': '$hostname:$port0',
@@ -1363,7 +1350,7 @@ buildtop = _find_buildtop()
 srctop = _find_srctop()
 plugins = os.path.join(buildtop, 'plugins')
 runenv = _import_runenv()
-hostname = _get_hostname()
+hostname = socket.gethostname().lower()
 null_input = open(os.devnull, 'r')
 
 # A DB pass is a tuple of: name, kdc_conf.