Better implementation of CORS.

This commit is contained in:
Juliusz Chroboczek
2025-06-13 14:26:40 +02:00
parent 321b2686af
commit 7204889085
4 changed files with 54 additions and 41 deletions
+2 -3
View File
@@ -109,9 +109,8 @@ The fields are as follows:
- `writableGroups`: if true, then the API can modify group description - `writableGroups`: if true, then the API can modify group description
files; by default, group files are treated as read-only; files; by default, group files are treated as read-only;
- `publicServer`: if true, then cross-origin access to the server is - `allowOrigin` is an array that contains the list of HTTP origins that
allowed. This makes the server vulnerable to cross-origin scripting are allowed to access the server.
attacks, but is necessary in some cases.
- `proxyURL`: if running behind a reverse proxy, this specifies the root - `proxyURL`: if running behind a reverse proxy, this specifies the root
URL that will be visible outside the proxy. URL that will be visible outside the proxy.
+2 -1
View File
@@ -916,8 +916,9 @@ type Configuration struct {
modTime time.Time `json:"-"` modTime time.Time `json:"-"`
fileSize int64 `json:"-"` fileSize int64 `json:"-"`
PublicServer bool `json:"publicServer"`
CanonicalHost string `json:"canonicalHost"` CanonicalHost string `json:"canonicalHost"`
AllowOrigin []string `json:"allowOrigin"`
AllowAdminOrigin []string `json:"allowAdminOrigin"`
ProxyURL string `json:"proxyURL"` ProxyURL string `json:"proxyURL"`
WritableGroups bool `json:"writableGroups"` WritableGroups bool `json:"writableGroups"`
Users map[string]UserDescription Users map[string]UserDescription
+44 -15
View File
@@ -502,29 +502,58 @@ func failAuthentication(w http.ResponseWriter, realm string) {
http.Error(w, "Haha!", http.StatusUnauthorized) http.Error(w, "Haha!", http.StatusUnauthorized)
} }
var wsUpgrader = websocket.Upgrader{ func CheckOrigin(w http.ResponseWriter, r *http.Request, admin bool) bool {
HandshakeTimeout: 30 * time.Second, if w != nil {
w.Header().Add("Vary", "Origin")
}
origins := r.Header["Origin"]
if len(origins) == 0 {
return true
}
origin := origins[0]
ok := false
o, err := url.Parse(origin)
if err == nil && strings.EqualFold(o.Host, r.Host) {
ok = true
} else {
conf, err := group.GetConfiguration()
if err != nil {
return false
}
allow := conf.AllowOrigin
if admin {
allow = conf.AllowAdminOrigin
}
for _, a := range allow {
if strings.EqualFold(origin, a) {
ok = true
break
}
}
}
if !ok {
return false
}
if w != nil {
w.Header().Add("Access-Control-Allow-Origin", origin)
}
return true
} }
var wsPublicUpgrader = websocket.Upgrader{ var wsUpgrader = websocket.Upgrader{
HandshakeTimeout: 30 * time.Second, HandshakeTimeout: 30 * time.Second,
CheckOrigin: func(r *http.Request) bool { CheckOrigin: func(r *http.Request) bool {
return true return CheckOrigin(nil, r, false)
}, },
} }
func wsHandler(w http.ResponseWriter, r *http.Request) { func wsHandler(w http.ResponseWriter, r *http.Request) {
conf, err := group.GetConfiguration() conn, err := wsUpgrader.Upgrade(w, r, nil)
if err != nil {
httpError(w, err)
return
}
upgrader := wsUpgrader
if conf.PublicServer {
upgrader = wsPublicUpgrader
}
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil { if err != nil {
log.Printf("Websocket upgrade: %v", err) log.Printf("Websocket upgrade: %v", err)
return return
+2 -18
View File
@@ -165,15 +165,7 @@ func whipEndpointHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
conf, err := group.GetConfiguration() CheckOrigin(w, r, false)
if err != nil {
httpError(w, err)
return
}
if conf.PublicServer {
w.Header().Set("Access-Control-Allow-Origin", "*")
}
if r.Method == "OPTIONS" { if r.Method == "OPTIONS" {
w.Header().Set("Access-Control-Allow-Methods", "OPTIONS, POST") w.Header().Set("Access-Control-Allow-Methods", "OPTIONS, POST")
@@ -309,15 +301,7 @@ func whipResourceHandler(w http.ResponseWriter, r *http.Request) {
} }
} }
conf, err := group.GetConfiguration() CheckOrigin(w, r, false)
if err != nil {
httpError(w, err)
return
}
if conf.PublicServer {
w.Header().Set("Access-Control-Allow-Origin", "*")
}
if r.Method == "OPTIONS" { if r.Method == "OPTIONS" {
w.Header().Set("Access-Control-Allow-Methods", w.Header().Set("Access-Control-Allow-Methods",