Refuse a host in a short or legacy numeric form (127.1, 2130706433, 0x7f.0.0.1) in netcheck_request before any lookup, so the refusal does not depend on the resolver
mesh/merge-gate head a01e1ea7fb64 merged into trunk d74c1cb995a4 — pass: builds netcheck → ace, g14, novox, shanks; no bus step; every machine composes wit…
mesh/repo-check head a01e1ea7fb64 merged into trunk d74c1cb995a4 — pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-…
mesh/delivery delivered
mesh/merge-gate head a01e1ea7fb64 merged into trunk d74c1cb995a4 — pass: builds netcheck → ace, g14, novox, shanks; no bus step; every machine composes wit…
mesh/repo-check head a01e1ea7fb64 merged into trunk d74c1cb995a4 — pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-…
mesh/delivery delivered
This commit is contained in:
@@ -82,6 +82,39 @@ func guardDial(_, address string, _ syscall.RawConn) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// shortFormAddress: a host made only of numeric labels (decimal, octal or 0x hex) that net/netip does not
|
||||
// take as an address. The C resolver expands these (127.1 is 127.0.0.1, 2130706433 too), so the tool
|
||||
// refuses them on its own words before any lookup rather than rely on the resolver.
|
||||
func shortFormAddress(host string) bool {
|
||||
if host == "" || strings.Contains(host, ":") {
|
||||
return false
|
||||
}
|
||||
if _, err := netip.ParseAddr(host); err == nil {
|
||||
return false
|
||||
}
|
||||
for _, label := range strings.Split(strings.TrimSuffix(host, "."), ".") {
|
||||
digits := label
|
||||
if len(label) > 2 && (label[:2] == "0x" || label[:2] == "0X") {
|
||||
digits = label[2:]
|
||||
for _, c := range digits {
|
||||
if !strings.ContainsRune("0123456789abcdefABCDEF", c) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
if digits == "" {
|
||||
return false
|
||||
}
|
||||
for _, c := range digits {
|
||||
if c < '0' || c > '9' {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func runRequest(args map[string]any) (any, error) {
|
||||
raw, err := text(args, "url")
|
||||
if err != nil {
|
||||
@@ -97,6 +130,9 @@ func runRequest(args map[string]any) (any, error) {
|
||||
if u.Host == "" {
|
||||
return nil, fmt.Errorf("url %q has no host", raw)
|
||||
}
|
||||
if shortFormAddress(u.Hostname()) {
|
||||
return nil, fmt.Errorf("refused: host %q is an address in a short or legacy form (as 127.1, 2130706433 or 0x7f.0.0.1), which the resolver may read as loopback, unspecified or link-local; write the full address", u.Hostname())
|
||||
}
|
||||
method := "GET"
|
||||
if m, _ := args["method"].(string); strings.TrimSpace(m) != "" {
|
||||
method = strings.ToUpper(strings.TrimSpace(m))
|
||||
|
||||
@@ -34,7 +34,7 @@ func TestRequestRefusesLocalAddresses(t *testing.T) {
|
||||
port := srv.Listener.Addr().(*net.TCPAddr).Port
|
||||
refusing(t)
|
||||
for _, host := range []string{
|
||||
"127.0.0.1", "localhost", "127.1", "[::1]", "[::ffff:127.0.0.1]", "0.0.0.0", "[::]",
|
||||
"127.0.0.1", "localhost", "127.1", "2130706433", "0x7f.0.0.1", "0x7f.1", "0177.0.0.1", "[::1]", "[::ffff:127.0.0.1]", "0.0.0.0", "[::]",
|
||||
"169.254.169.254", "[fe80::1]",
|
||||
} {
|
||||
u := "http://" + host + ":" + strconv.Itoa(port) + "/"
|
||||
@@ -45,6 +45,20 @@ func TestRequestRefusesLocalAddresses(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestShortFormAddressIsRefusedOnItsOwnWords(t *testing.T) {
|
||||
for _, host := range []string{"127.1", "2130706433", "0x7f.0.0.1", "0x7f.1", "0177.0.0.1"} {
|
||||
_, err := asked(t, map[string]any{"url": "http://" + host + ":1/", "timeout_ms": float64(2000)})
|
||||
if err == nil || !strings.Contains(err.Error(), "short or legacy form") {
|
||||
t.Errorf("%s: want the short-form refusal, got %v", host, err)
|
||||
}
|
||||
}
|
||||
for _, host := range []string{"example.com", "127.0.0.1", "1.example.com", "[::1]", "10.0.0.1"} {
|
||||
if shortFormAddress(strings.Trim(host, "[]")) {
|
||||
t.Errorf("%s taken for a short form", host)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRequestIgnoresProxyEnvironment(t *testing.T) {
|
||||
t.Setenv("HTTP_PROXY", "http://127.0.0.1:1")
|
||||
t.Setenv("http_proxy", "http://127.0.0.1:1")
|
||||
|
||||
Reference in New Issue
Block a user