+3
.forgejo/workflows/ci.yaml
+3
.forgejo/workflows/ci.yaml
+17
-4
src/auth.go
+17
-4
src/auth.go
···
54
54
// this also rejects invalid characters and labels
55
55
host, err = idnaProfile.ToASCII(host)
56
56
if err != nil {
57
-
return "", AuthError{http.StatusBadRequest,
58
-
fmt.Sprintf("malformed host name %q", host)}
57
+
if config.Feature("relaxed-idna") {
58
+
// unfortunately, the go IDNA library has some significant issues around its
59
+
// Unicode TR46 implementation: https://github.com/golang/go/issues/76804
60
+
// we would like to allow *just* the _ here, but adding `idna.StrictDomainName(false)`
61
+
// would also accept domains like `*.foo.bar` which should clearly be disallowed.
62
+
// as a workaround, accept a domain name if it is valid with all `_` characters
63
+
// replaced with an alphanumeric character (we use `a`); this allows e.g. `foo_bar.xxx`
64
+
// and `foo__bar.xxx`, as well as `_foo.xxx` and `foo_.xxx`. labels starting with
65
+
// an underscore are explicitly rejected below.
66
+
_, err = idnaProfile.ToASCII(strings.ReplaceAll(host, "_", "a"))
67
+
}
68
+
if err != nil {
69
+
return "", AuthError{http.StatusBadRequest,
70
+
fmt.Sprintf("malformed host name %q", host)}
71
+
}
59
72
}
60
-
if strings.HasPrefix(host, ".") {
73
+
if strings.HasPrefix(host, ".") || strings.HasPrefix(host, "_") {
61
74
return "", AuthError{http.StatusBadRequest,
62
-
fmt.Sprintf("host name %q is reserved", host)}
75
+
fmt.Sprintf("reserved host name %q", host)}
63
76
}
64
77
host = strings.TrimSuffix(host, ".")
65
78
return host, nil
+55
src/pages_test.go
+55
src/pages_test.go
···
1
+
package git_pages
2
+
3
+
import (
4
+
"net/http"
5
+
"strings"
6
+
"testing"
7
+
)
8
+
9
+
func checkHost(t *testing.T, host string, expectOk string, expectErr string) {
10
+
host, err := GetHost(&http.Request{Host: host})
11
+
if expectErr != "" {
12
+
if err == nil || !strings.HasPrefix(err.Error(), expectErr) {
13
+
t.Errorf("%s: expect err %s, got err %s", host, expectErr, err)
14
+
}
15
+
}
16
+
if expectOk != "" {
17
+
if err != nil {
18
+
t.Errorf("%s: expect ok %s, got err %s", host, expectOk, err)
19
+
} else if host != expectOk {
20
+
t.Errorf("%s: expect ok %s, got ok %s", host, expectOk, host)
21
+
}
22
+
}
23
+
}
24
+
25
+
func TestHelloName(t *testing.T) {
26
+
config = &Config{Features: []string{}}
27
+
28
+
checkHost(t, "foo.bar", "foo.bar", "")
29
+
checkHost(t, "foo-baz.bar", "foo-baz.bar", "")
30
+
checkHost(t, "foo--baz.bar", "foo--baz.bar", "")
31
+
checkHost(t, "foo.bar.", "foo.bar", "")
32
+
checkHost(t, ".foo.bar", "", "reserved host name")
33
+
checkHost(t, "..foo.bar", "", "reserved host name")
34
+
35
+
checkHost(t, "ß.bar", "xn--zca.bar", "")
36
+
checkHost(t, "xn--zca.bar", "xn--zca.bar", "")
37
+
38
+
checkHost(t, "foo-.bar", "", "malformed host name")
39
+
checkHost(t, "-foo.bar", "", "malformed host name")
40
+
checkHost(t, "foo_.bar", "", "malformed host name")
41
+
checkHost(t, "_foo.bar", "", "malformed host name")
42
+
checkHost(t, "foo_baz.bar", "", "malformed host name")
43
+
checkHost(t, "foo__baz.bar", "", "malformed host name")
44
+
checkHost(t, "*.foo.bar", "", "malformed host name")
45
+
46
+
config = &Config{Features: []string{"relaxed-idna"}}
47
+
48
+
checkHost(t, "foo-.bar", "", "malformed host name")
49
+
checkHost(t, "-foo.bar", "", "malformed host name")
50
+
checkHost(t, "foo_.bar", "foo_.bar", "")
51
+
checkHost(t, "_foo.bar", "", "reserved host name")
52
+
checkHost(t, "foo_baz.bar", "foo_baz.bar", "")
53
+
checkHost(t, "foo__baz.bar", "foo__baz.bar", "")
54
+
checkHost(t, "*.foo.bar", "", "malformed host name")
55
+
}