From 65cd447a61efa852da2c0e7db25f385c2436e236 Mon Sep 17 00:00:00 2001 From: Martin Kraft Date: Mon, 30 Jul 2018 14:59:08 -0400 Subject: MM-11301: Validates listen address config value. (#9138) * MM-11301: Validates listen address config value. * MM-11301: Adds some invalid port test cases. * MM-11301: Accept domain names. * MM-11301: Fix for max port. --- model/config.go | 13 ++++++++++++- model/config_test.go | 42 ++++++++++++++++++++++++++++++++++++++++ model/utils.go | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+), 1 deletion(-) (limited to 'model') diff --git a/model/config.go b/model/config.go index 1d0f40901..aa7900279 100644 --- a/model/config.go +++ b/model/config.go @@ -6,9 +6,12 @@ package model import ( "encoding/json" "io" + "math" + "net" "net/http" "net/url" "regexp" + "strconv" "strings" "time" ) @@ -2352,7 +2355,15 @@ func (ss *ServiceSettings) isValid() *AppError { } } - if len(*ss.ListenAddress) == 0 { + host, port, err := net.SplitHostPort(*ss.ListenAddress) + var isValidHost bool + if host == "" { + isValidHost = true + } else { + isValidHost = (net.ParseIP(host) != nil) || IsDomainName(host) + } + portInt, err := strconv.Atoi(port) + if err != nil || !isValidHost || portInt < 0 || portInt > math.MaxUint16 { return NewAppError("Config.IsValid", "model.config.is_valid.listen_address.app_error", nil, "", http.StatusBadRequest) } diff --git a/model/config_test.go b/model/config_test.go index 848f4327e..179bab8e2 100644 --- a/model/config_test.go +++ b/model/config_test.go @@ -519,3 +519,45 @@ func TestDisplaySettingsIsValidCustomUrlSchemes(t *testing.T) { }) } } + +func TestListenAddressIsValidated(t *testing.T) { + + testValues := map[string]bool{ + ":8065": true, + ":9917": true, + "0.0.0.0:9917": true, + "[2001:db8::68]:9918": true, + "[::1]:8065": true, + "localhost:8065": true, + "test.com:8065": true, + ":0": true, + ":33147": true, + "123:8065": false, + "[::1]:99999": false, + "[::1]:-1": false, + "[::1]:8065a": false, + "0.0.0:9917": false, + "0.0.0.0:9917/": false, + "0..0.0:9917/": false, + "0.0.0222.0:9917/": false, + "http://0.0.0.0:9917/": false, + "http://0.0.0.0:9917": false, + "8065": false, + "[2001:db8::68]": false, + } + + for key, expected := range testValues { + ss := &ServiceSettings{ + ListenAddress: NewString(key), + } + ss.SetDefaults() + if expected { + require.Nil(t, ss.isValid(), fmt.Sprintf("Got an error from '%v'.", key)) + } else { + err := ss.isValid() + require.NotNil(t, err, fmt.Sprintf("Expected '%v' to throw an error.", key)) + require.Equal(t, "model.config.is_valid.listen_address.app_error", err.Message) + } + } + +} diff --git a/model/utils.go b/model/utils.go index 9f8ef90e1..892f8c278 100644 --- a/model/utils.go +++ b/model/utils.go @@ -536,3 +536,57 @@ func checkNowhereNil(t *testing.T, name string, value interface{}) bool { return true } } + +// Copied from https://golang.org/src/net/dnsclient.go#L119 +func IsDomainName(s string) bool { + // See RFC 1035, RFC 3696. + // Presentation format has dots before every label except the first, and the + // terminal empty label is optional here because we assume fully-qualified + // (absolute) input. We must therefore reserve space for the first and last + // labels' length octets in wire format, where they are necessary and the + // maximum total length is 255. + // So our _effective_ maximum is 253, but 254 is not rejected if the last + // character is a dot. + l := len(s) + if l == 0 || l > 254 || l == 254 && s[l-1] != '.' { + return false + } + + last := byte('.') + ok := false // Ok once we've seen a letter. + partlen := 0 + for i := 0; i < len(s); i++ { + c := s[i] + switch { + default: + return false + case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '_': + ok = true + partlen++ + case '0' <= c && c <= '9': + // fine + partlen++ + case c == '-': + // Byte before dash cannot be dot. + if last == '.' { + return false + } + partlen++ + case c == '.': + // Byte before dot cannot be dot, dash. + if last == '.' || last == '-' { + return false + } + if partlen > 63 || partlen == 0 { + return false + } + partlen = 0 + } + last = c + } + if last == '-' || partlen > 63 { + return false + } + + return ok +} -- cgit v1.2.3-1-g7c22