From 4bd95702dd1e81f383ee67c14945620d30247908 Mon Sep 17 00:00:00 2001 From: Dan Peterson Date: Wed, 23 Nov 2016 11:35:17 -0700 Subject: [PATCH] net: expand nss myhostname fallback detection Expand myhostname fallback detection to properly detect the local hostname in addition to other supported special names and suffixes. Fixes #17967 Change-Id: I1fe141fd9838b25886c08b6f2fd325e58be60457 Reviewed-on: https://go-review.googlesource.com/33550 Reviewed-by: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Gobot Gobot --- src/net/conf.go | 24 +++++++-- src/net/conf_test.go | 114 ++++++++++++++++++++++++++----------------- src/net/parse.go | 22 ++++++--- 3 files changed, 101 insertions(+), 59 deletions(-) diff --git a/src/net/conf.go b/src/net/conf.go index 41e62d5689..c10aafe63a 100644 --- a/src/net/conf.go +++ b/src/net/conf.go @@ -179,8 +179,6 @@ func (c *conf) hostLookupOrder(hostname string) (ret hostLookupOrder) { } } - hasDot := byteIndex(hostname, '.') != -1 - // Canonicalize the hostname by removing any trailing dot. if stringsHasSuffix(hostname, ".") { hostname = hostname[:len(hostname)-1] @@ -220,10 +218,14 @@ func (c *conf) hostLookupOrder(hostname string) (ret hostLookupOrder) { var first string for _, src := range srcs { if src.source == "myhostname" { - if hostname == "" || hasDot { - continue + if isLocalhost(hostname) || isGateway(hostname) { + return fallbackOrder } - return fallbackOrder + hn, err := getHostname() + if err != nil || stringsEqualFold(hostname, hn) { + return fallbackOrder + } + continue } if src.source == "files" || src.source == "dns" { if !src.standardCriteria() { @@ -306,3 +308,15 @@ func goDebugNetDNS() (dnsMode string, debugLevel int) { parsePart(goDebug) return } + +// isLocalhost reports whether h should be considered a "localhost" +// name for the myhostname NSS module. +func isLocalhost(h string) bool { + return stringsEqualFold(h, "localhost") || stringsEqualFold(h, "localhost.localdomain") || stringsHasSuffixFold(h, ".localhost") || stringsHasSuffixFold(h, ".localhost.localdomain") +} + +// isGateway reports whether h should be considered a "gateway" +// name for the myhostname NSS module. +func isGateway(h string) bool { + return stringsEqualFold(h, "gateway") +} diff --git a/src/net/conf_test.go b/src/net/conf_test.go index ec8814b845..17d03f4b5f 100644 --- a/src/net/conf_test.go +++ b/src/net/conf_test.go @@ -13,8 +13,9 @@ import ( ) type nssHostTest struct { - host string - want hostLookupOrder + host string + localhost string + want hostLookupOrder } func nssStr(s string) *nssConf { return parseNSSConf(strings.NewReader(s)) } @@ -42,8 +43,8 @@ func TestConfHostLookupOrder(t *testing.T) { resolv: defaultResolvConf, }, hostTests: []nssHostTest{ - {"foo.local", hostLookupCgo}, - {"google.com", hostLookupCgo}, + {"foo.local", "myhostname", hostLookupCgo}, + {"google.com", "myhostname", hostLookupCgo}, }, }, { @@ -54,7 +55,7 @@ func TestConfHostLookupOrder(t *testing.T) { resolv: defaultResolvConf, }, hostTests: []nssHostTest{ - {"x.com", hostLookupDNSFiles}, + {"x.com", "myhostname", hostLookupDNSFiles}, }, }, { @@ -65,7 +66,7 @@ func TestConfHostLookupOrder(t *testing.T) { resolv: defaultResolvConf, }, hostTests: []nssHostTest{ - {"x.com", hostLookupFilesDNS}, + {"x.com", "myhostname", hostLookupFilesDNS}, }, }, { @@ -75,11 +76,11 @@ func TestConfHostLookupOrder(t *testing.T) { resolv: defaultResolvConf, }, hostTests: []nssHostTest{ - {"foo.local", hostLookupCgo}, - {"foo.local.", hostLookupCgo}, - {"foo.LOCAL", hostLookupCgo}, - {"foo.LOCAL.", hostLookupCgo}, - {"google.com", hostLookupFilesDNS}, + {"foo.local", "myhostname", hostLookupCgo}, + {"foo.local.", "myhostname", hostLookupCgo}, + {"foo.LOCAL", "myhostname", hostLookupCgo}, + {"foo.LOCAL.", "myhostname", hostLookupCgo}, + {"google.com", "myhostname", hostLookupFilesDNS}, }, }, { @@ -89,7 +90,7 @@ func TestConfHostLookupOrder(t *testing.T) { nss: nssStr("foo: bar"), resolv: defaultResolvConf, }, - hostTests: []nssHostTest{{"google.com", hostLookupFilesDNS}}, + hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupFilesDNS}}, }, // On OpenBSD, no resolv.conf means no DNS. { @@ -98,7 +99,7 @@ func TestConfHostLookupOrder(t *testing.T) { goos: "openbsd", resolv: defaultResolvConf, }, - hostTests: []nssHostTest{{"google.com", hostLookupFiles}}, + hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupFiles}}, }, { name: "solaris_no_nsswitch", @@ -107,7 +108,7 @@ func TestConfHostLookupOrder(t *testing.T) { nss: &nssConf{err: os.ErrNotExist}, resolv: defaultResolvConf, }, - hostTests: []nssHostTest{{"google.com", hostLookupCgo}}, + hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupCgo}}, }, { name: "openbsd_lookup_bind_file", @@ -116,8 +117,8 @@ func TestConfHostLookupOrder(t *testing.T) { resolv: &dnsConfig{lookup: []string{"bind", "file"}}, }, hostTests: []nssHostTest{ - {"google.com", hostLookupDNSFiles}, - {"foo.local", hostLookupDNSFiles}, + {"google.com", "myhostname", hostLookupDNSFiles}, + {"foo.local", "myhostname", hostLookupDNSFiles}, }, }, { @@ -126,7 +127,7 @@ func TestConfHostLookupOrder(t *testing.T) { goos: "openbsd", resolv: &dnsConfig{lookup: []string{"file", "bind"}}, }, - hostTests: []nssHostTest{{"google.com", hostLookupFilesDNS}}, + hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupFilesDNS}}, }, { name: "openbsd_lookup_bind", @@ -134,7 +135,7 @@ func TestConfHostLookupOrder(t *testing.T) { goos: "openbsd", resolv: &dnsConfig{lookup: []string{"bind"}}, }, - hostTests: []nssHostTest{{"google.com", hostLookupDNS}}, + hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupDNS}}, }, { name: "openbsd_lookup_file", @@ -142,7 +143,7 @@ func TestConfHostLookupOrder(t *testing.T) { goos: "openbsd", resolv: &dnsConfig{lookup: []string{"file"}}, }, - hostTests: []nssHostTest{{"google.com", hostLookupFiles}}, + hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupFiles}}, }, { name: "openbsd_lookup_yp", @@ -150,7 +151,7 @@ func TestConfHostLookupOrder(t *testing.T) { goos: "openbsd", resolv: &dnsConfig{lookup: []string{"file", "bind", "yp"}}, }, - hostTests: []nssHostTest{{"google.com", hostLookupCgo}}, + hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupCgo}}, }, { name: "openbsd_lookup_two", @@ -158,7 +159,7 @@ func TestConfHostLookupOrder(t *testing.T) { goos: "openbsd", resolv: &dnsConfig{lookup: []string{"file", "foo"}}, }, - hostTests: []nssHostTest{{"google.com", hostLookupCgo}}, + hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupCgo}}, }, { name: "openbsd_lookup_empty", @@ -166,7 +167,7 @@ func TestConfHostLookupOrder(t *testing.T) { goos: "openbsd", resolv: &dnsConfig{lookup: nil}, }, - hostTests: []nssHostTest{{"google.com", hostLookupDNSFiles}}, + hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupDNSFiles}}, }, // glibc lacking an nsswitch.conf, per // http://www.gnu.org/software/libc/manual/html_node/Notes-on-NSS-Configuration-File.html @@ -177,7 +178,7 @@ func TestConfHostLookupOrder(t *testing.T) { nss: &nssConf{err: os.ErrNotExist}, resolv: defaultResolvConf, }, - hostTests: []nssHostTest{{"google.com", hostLookupDNSFiles}}, + hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupDNSFiles}}, }, { name: "files_mdns_dns", @@ -186,8 +187,8 @@ func TestConfHostLookupOrder(t *testing.T) { resolv: defaultResolvConf, }, hostTests: []nssHostTest{ - {"x.com", hostLookupFilesDNS}, - {"x.local", hostLookupCgo}, + {"x.com", "myhostname", hostLookupFilesDNS}, + {"x.local", "myhostname", hostLookupCgo}, }, }, { @@ -197,9 +198,9 @@ func TestConfHostLookupOrder(t *testing.T) { resolv: defaultResolvConf, }, hostTests: []nssHostTest{ - {"x.com", hostLookupDNS}, - {"x\\.com", hostLookupCgo}, // punt on weird glibc escape - {"foo.com%en0", hostLookupCgo}, // and IPv6 zones + {"x.com", "myhostname", hostLookupDNS}, + {"x\\.com", "myhostname", hostLookupCgo}, // punt on weird glibc escape + {"foo.com%en0", "myhostname", hostLookupCgo}, // and IPv6 zones }, }, { @@ -210,8 +211,8 @@ func TestConfHostLookupOrder(t *testing.T) { hasMDNSAllow: true, }, hostTests: []nssHostTest{ - {"x.com", hostLookupCgo}, - {"x.local", hostLookupCgo}, + {"x.com", "myhostname", hostLookupCgo}, + {"x.local", "myhostname", hostLookupCgo}, }, }, { @@ -221,9 +222,9 @@ func TestConfHostLookupOrder(t *testing.T) { resolv: defaultResolvConf, }, hostTests: []nssHostTest{ - {"x.com", hostLookupFilesDNS}, - {"x", hostLookupFilesDNS}, - {"x.local", hostLookupCgo}, + {"x.com", "myhostname", hostLookupFilesDNS}, + {"x", "myhostname", hostLookupFilesDNS}, + {"x.local", "myhostname", hostLookupCgo}, }, }, { @@ -233,9 +234,9 @@ func TestConfHostLookupOrder(t *testing.T) { resolv: defaultResolvConf, }, hostTests: []nssHostTest{ - {"x.com", hostLookupDNSFiles}, - {"x", hostLookupDNSFiles}, - {"x.local", hostLookupCgo}, + {"x.com", "myhostname", hostLookupDNSFiles}, + {"x", "myhostname", hostLookupDNSFiles}, + {"x.local", "myhostname", hostLookupCgo}, }, }, { @@ -245,7 +246,7 @@ func TestConfHostLookupOrder(t *testing.T) { resolv: defaultResolvConf, }, hostTests: []nssHostTest{ - {"x.com", hostLookupCgo}, + {"x.com", "myhostname", hostLookupCgo}, }, }, { @@ -255,9 +256,23 @@ func TestConfHostLookupOrder(t *testing.T) { resolv: defaultResolvConf, }, hostTests: []nssHostTest{ - {"x.com", hostLookupFilesDNS}, - {"somehostname", hostLookupCgo}, - {"", hostLookupFilesDNS}, // Issue 13623 + {"x.com", "myhostname", hostLookupFilesDNS}, + {"myhostname", "myhostname", hostLookupCgo}, + {"myHostname", "myhostname", hostLookupCgo}, + {"myhostname.dot", "myhostname.dot", hostLookupCgo}, + {"myHostname.dot", "myhostname.dot", hostLookupCgo}, + {"gateway", "myhostname", hostLookupCgo}, + {"Gateway", "myhostname", hostLookupCgo}, + {"localhost", "myhostname", hostLookupCgo}, + {"Localhost", "myhostname", hostLookupCgo}, + {"anything.localhost", "myhostname", hostLookupCgo}, + {"Anything.localhost", "myhostname", hostLookupCgo}, + {"localhost.localdomain", "myhostname", hostLookupCgo}, + {"Localhost.Localdomain", "myhostname", hostLookupCgo}, + {"anything.localhost.localdomain", "myhostname", hostLookupCgo}, + {"Anything.Localhost.Localdomain", "myhostname", hostLookupCgo}, + {"somehostname", "myhostname", hostLookupFilesDNS}, + {"", "myhostname", hostLookupFilesDNS}, // Issue 13623 }, }, { @@ -267,8 +282,9 @@ func TestConfHostLookupOrder(t *testing.T) { resolv: defaultResolvConf, }, hostTests: []nssHostTest{ - {"x.com", hostLookupFilesDNS}, - {"somehostname", hostLookupCgo}, + {"x.com", "myhostname", hostLookupFilesDNS}, + {"somehostname", "myhostname", hostLookupFilesDNS}, + {"myhostname", "myhostname", hostLookupCgo}, }, }, // Debian Squeeze is just "dns,files", but lists all @@ -282,8 +298,8 @@ func TestConfHostLookupOrder(t *testing.T) { resolv: defaultResolvConf, }, hostTests: []nssHostTest{ - {"x.com", hostLookupDNSFiles}, - {"somehostname", hostLookupDNSFiles}, + {"x.com", "myhostname", hostLookupDNSFiles}, + {"somehostname", "myhostname", hostLookupDNSFiles}, }, }, { @@ -292,7 +308,7 @@ func TestConfHostLookupOrder(t *testing.T) { nss: nssStr("foo: bar"), resolv: &dnsConfig{servers: defaultNS, ndots: 1, timeout: 5, attempts: 2, unknownOpt: true}, }, - hostTests: []nssHostTest{{"google.com", hostLookupCgo}}, + hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupCgo}}, }, // Android should always use cgo. { @@ -303,12 +319,18 @@ func TestConfHostLookupOrder(t *testing.T) { resolv: defaultResolvConf, }, hostTests: []nssHostTest{ - {"x.com", hostLookupCgo}, + {"x.com", "myhostname", hostLookupCgo}, }, }, } + + origGetHostname := getHostname + defer func() { getHostname = origGetHostname }() + for _, tt := range tests { for _, ht := range tt.hostTests { + getHostname = func() (string, error) { return ht.localhost, nil } + gotOrder := tt.c.hostLookupOrder(ht.host) if gotOrder != ht.want { t.Errorf("%s: hostLookupOrder(%q) = %v; want %v", tt.name, ht.host, gotOrder, ht.want) diff --git a/src/net/parse.go b/src/net/parse.go index d615eb2b56..58269849ce 100644 --- a/src/net/parse.go +++ b/src/net/parse.go @@ -334,22 +334,28 @@ func stringsHasSuffix(s, suffix string) bool { // stringsHasSuffixFold reports whether s ends in suffix, // ASCII-case-insensitively. func stringsHasSuffixFold(s, suffix string) bool { - if len(suffix) > len(s) { + return len(s) >= len(suffix) && stringsEqualFold(s[len(s)-len(suffix):], suffix) +} + +// stringsHasPrefix is strings.HasPrefix. It reports whether s begins with prefix. +func stringsHasPrefix(s, prefix string) bool { + return len(s) >= len(prefix) && s[:len(prefix)] == prefix +} + +// stringsEqualFold is strings.EqualFold, ASCII only. It reports whether s and t +// are equal, ASCII-case-insensitively. +func stringsEqualFold(s, t string) bool { + if len(s) != len(t) { return false } - for i := 0; i < len(suffix); i++ { - if lowerASCII(suffix[i]) != lowerASCII(s[len(s)-len(suffix)+i]) { + for i := 0; i < len(s); i++ { + if lowerASCII(s[i]) != lowerASCII(t[i]) { return false } } return true } -// stringsHasPrefix is strings.HasPrefix. It reports whether s begins with prefix. -func stringsHasPrefix(s, prefix string) bool { - return len(s) >= len(prefix) && s[:len(prefix)] == prefix -} - func readFull(r io.Reader) (all []byte, err error) { buf := make([]byte, 1024) for { -- 2.50.0