浏览代码

cmd/stdiscosrv: Be more picky about allowed addresses (fixes #5151) (#5153)

Filter out ludicrous stuff both from explicitly announced addresses and
potential automatic replacements.
Jakob Borg 7 年之前
父节点
当前提交
e384c822b6
共有 2 个文件被更改,包括 79 次插入0 次删除
  1. 14 0
      cmd/stdiscosrv/apisrv.go
  2. 65 0
      cmd/stdiscosrv/apisrv_test.go

+ 14 - 0
cmd/stdiscosrv/apisrv.go

@@ -335,7 +335,21 @@ func fixupAddresses(remote net.IP, addresses []string) []string {
 		}
 
 		ip := net.ParseIP(host)
+
+		// Some classes of IP are no-go.
+		if ip.IsLoopback() || ip.IsMulticast() {
+			continue
+		}
+
 		if host == "" || ip.IsUnspecified() {
+			// Replace the unspecified IP with the request source.
+
+			// ... unless the request source is the loopback address or
+			// multicast/unspecified (can't happen, really).
+			if remote.IsLoopback() || remote.IsMulticast() || remote.IsUnspecified() {
+				continue
+			}
+
 			// Do not use IPv6 remote address if requested scheme is ...4
 			// (i.e., tcp4, etc.)
 			if strings.HasSuffix(uri.Scheme, "4") && remote.To4() == nil {

+ 65 - 0
cmd/stdiscosrv/apisrv_test.go

@@ -0,0 +1,65 @@
+// Copyright (C) 2018 The Syncthing Authors.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at https://mozilla.org/MPL/2.0/.
+
+package main
+
+import (
+	"fmt"
+	"net"
+	"testing"
+)
+
+func TestFixupAddresses(t *testing.T) {
+	cases := []struct {
+		remote net.IP
+		in     []string
+		out    []string
+	}{
+		{ // verbatim passthrough
+			in:  []string{"tcp://1.2.3.4:22000"},
+			out: []string{"tcp://1.2.3.4:22000"},
+		}, { // unspecified replaced by remote
+			remote: net.ParseIP("1.2.3.4"),
+			in:     []string{"tcp://:22000", "tcp://192.0.2.42:22000"},
+			out:    []string{"tcp://1.2.3.4:22000", "tcp://192.0.2.42:22000"},
+		}, { // unspecified not used as replacement
+			remote: net.ParseIP("0.0.0.0"),
+			in:     []string{"tcp://:22000", "tcp://192.0.2.42:22000"},
+			out:    []string{"tcp://192.0.2.42:22000"},
+		}, { // unspecified not used as replacement
+			remote: net.ParseIP("::"),
+			in:     []string{"tcp://:22000", "tcp://192.0.2.42:22000"},
+			out:    []string{"tcp://192.0.2.42:22000"},
+		}, { // localhost not used as replacement
+			remote: net.ParseIP("127.0.0.1"),
+			in:     []string{"tcp://:22000", "tcp://192.0.2.42:22000"},
+			out:    []string{"tcp://192.0.2.42:22000"},
+		}, { // localhost not used as replacement
+			remote: net.ParseIP("::1"),
+			in:     []string{"tcp://:22000", "tcp://192.0.2.42:22000"},
+			out:    []string{"tcp://192.0.2.42:22000"},
+		}, { // multicast not used as replacement
+			remote: net.ParseIP("224.0.0.1"),
+			in:     []string{"tcp://:22000", "tcp://192.0.2.42:22000"},
+			out:    []string{"tcp://192.0.2.42:22000"},
+		}, { // multicast not used as replacement
+			remote: net.ParseIP("ff80::42"),
+			in:     []string{"tcp://:22000", "tcp://192.0.2.42:22000"},
+			out:    []string{"tcp://192.0.2.42:22000"},
+		}, { // explicitly announced weirdness is also filtered
+			remote: net.ParseIP("192.0.2.42"),
+			in:     []string{"tcp://:22000", "tcp://127.1.2.3:22000", "tcp://[::1]:22000", "tcp://[ff80::42]:22000"},
+			out:    []string{"tcp://192.0.2.42:22000"},
+		},
+	}
+
+	for _, tc := range cases {
+		out := fixupAddresses(tc.remote, tc.in)
+		if fmt.Sprint(out) != fmt.Sprint(tc.out) {
+			t.Errorf("fixupAddresses(%v, %v) => %v, expected %v", tc.remote, tc.in, out, tc.out)
+		}
+	}
+}