Skip to content

Commit 11cbbd1

Browse files
authored
Merge pull request #977 from Cold-Coast/fix/cors_match
Fix cors match
2 parents edba87c + d3ff757 commit 11cbbd1

File tree

3 files changed

+174
-8
lines changed

3 files changed

+174
-8
lines changed

server/media/media.go

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,23 +59,68 @@ func GetIdFromUrl(url, serveUrl string) types.Uid {
5959

6060
// matchCORSOrigin compares origin from the HTTP request to a list of allowed origins.
6161
func matchCORSOrigin(allowed []string, origin string) string {
62-
if origin == "" {
63-
// Request has no Origin header.
62+
if len(allowed) == 0 {
63+
// Not configured
6464
return ""
6565
}
6666

67-
if len(allowed) == 0 {
68-
// Not configured
67+
if origin == "" && allowed[0] != "*" {
68+
// Request has no Origin header and "*" (any origin) not allowed.
6969
return ""
7070
}
7171

7272
if allowed[0] == "*" {
73-
return "*"
73+
if origin == "" {
74+
return "*"
75+
}
76+
return origin
77+
}
78+
79+
originUrl, err := url.ParseRequestURI(origin)
80+
if err != nil {
81+
return ""
7482
}
83+
originParts := strings.Split(originUrl.Hostname(), ".")
7584

76-
origin = strings.ToLower(origin)
7785
for _, val := range allowed {
78-
if strings.ToLower(val) == origin {
86+
if val == origin {
87+
return origin
88+
}
89+
90+
if !strings.Contains(val, "*") {
91+
continue
92+
}
93+
94+
allowedUrl, err := url.ParseRequestURI(val)
95+
if err != nil {
96+
continue
97+
}
98+
99+
if originUrl.Scheme != allowedUrl.Scheme {
100+
continue
101+
}
102+
103+
if originUrl.Port() != allowedUrl.Port() {
104+
continue
105+
}
106+
107+
allowedParts := strings.Split(allowedUrl.Hostname(), ".")
108+
109+
if len(originParts) != len(allowedParts) {
110+
continue
111+
}
112+
113+
matched := true
114+
for i, part := range allowedParts {
115+
if part == "*" {
116+
continue
117+
}
118+
if part != originParts[i] {
119+
matched = false
120+
break
121+
}
122+
}
123+
if matched {
79124
return origin
80125
}
81126
}

server/media/media_test.go

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
package media
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestMatchCORSOrigin(t *testing.T) {
8+
cases := []struct {
9+
allowed []string
10+
origin string
11+
expected string
12+
}{
13+
{
14+
allowed: []string{"https://example.com"},
15+
origin: "https://example.com",
16+
expected: "https://example.com",
17+
},
18+
{
19+
allowed: []string{"https://example2.com", "https://example.com"},
20+
origin: "https://example.com",
21+
expected: "https://example.com",
22+
},
23+
{
24+
allowed: []string{"*"},
25+
origin: "https://example.com",
26+
expected: "https://example.com",
27+
},
28+
{
29+
allowed: []string{""},
30+
origin: "https://example.com",
31+
expected: "",
32+
},
33+
{
34+
allowed: []string{},
35+
origin: "",
36+
expected: "",
37+
},
38+
{
39+
allowed: []string{"https://example.com"},
40+
origin: "",
41+
expected: "",
42+
},
43+
{
44+
allowed: []string{},
45+
origin: "https://example.com",
46+
expected: "",
47+
},
48+
{
49+
allowed: []string{"http://example.com"},
50+
origin: "https://example.com",
51+
expected: "",
52+
},
53+
{
54+
allowed: []string{"https://example.com"},
55+
origin: "http://example.com",
56+
expected: "",
57+
},
58+
{
59+
allowed: []string{"http://example.com:8000"},
60+
origin: "http://example.com:8000",
61+
expected: "http://example.com:8000",
62+
},
63+
{
64+
allowed: []string{"http://localhost:8090"},
65+
origin: "http://localhost:8090",
66+
expected: "http://localhost:8090",
67+
},
68+
{
69+
allowed: []string{"http://localhost:8090"},
70+
origin: "http://localhost:8080",
71+
expected: "",
72+
},
73+
{
74+
allowed: []string{"https://example.com"},
75+
origin: "https://sub.example.com",
76+
expected: "",
77+
},
78+
{
79+
allowed: []string{"https://*.example.com"},
80+
origin: "https://sub.example.com",
81+
expected: "https://sub.example.com",
82+
},
83+
{
84+
allowed: []string{"https://*.example.com"},
85+
origin: "https://pre.sub.example.com",
86+
expected: "",
87+
},
88+
{
89+
allowed: []string{"https://*.example.com", "https://*.sub.example.com"},
90+
origin: "https://pre.sub.example.com",
91+
expected: "https://pre.sub.example.com",
92+
},
93+
{
94+
allowed: []string{"https://*.*.example.com"},
95+
origin: "https://pre.sub.example.com",
96+
expected: "https://pre.sub.example.com",
97+
},
98+
{
99+
allowed: []string{"https://*.sub.example.com"},
100+
origin: "https://pre.asd.example.com",
101+
expected: "",
102+
},
103+
{
104+
allowed: []string{"https://pre.*.example.com"},
105+
origin: "https://pre.sub.example.com",
106+
expected: "https://pre.sub.example.com",
107+
},
108+
{
109+
allowed: []string{"https://*.*.*.example.com"},
110+
origin: "https://www.pre.sub.example.com",
111+
expected: "https://www.pre.sub.example.com",
112+
},
113+
}
114+
115+
for _, tc := range cases {
116+
result := matchCORSOrigin(tc.allowed, tc.origin)
117+
if result != tc.expected {
118+
t.Errorf("Match CORS origin got wrong result. Expected %s, got %s", tc.expected, result)
119+
}
120+
}
121+
}

server/tinode.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@
110110
"upload_dir": "uploads",
111111
// Cache-Control header to use for uploaded files. 86400 seconds = 24 hours.
112112
"cache_control": "max-age=86400",
113-
// Origin URLs allowed to download/upload files, e.g. ["https://www.example.com", "http://example.com"].
113+
// Origin URLs allowed to download/upload files, e.g. ["https://www.example.com", "http://example.com", "https://*.example.com", "http://*.*.example.com"].
114114
// Not necessary in most cases.
115115
// "cors_origins": ["*"]
116116
},

0 commit comments

Comments
 (0)