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
files; by default, group files are treated as read-only;
- `publicServer`: if true, then cross-origin access to the server is
allowed. This makes the server vulnerable to cross-origin scripting
attacks, but is necessary in some cases.
- `allowOrigin` is an array that contains the list of HTTP origins that
are allowed to access the server.
- `proxyURL`: if running behind a reverse proxy, this specifies the root
URL that will be visible outside the proxy.
+2 -1
View File
@@ -916,8 +916,9 @@ type Configuration struct {
modTime time.Time `json:"-"`
fileSize int64 `json:"-"`
PublicServer bool `json:"publicServer"`
CanonicalHost string `json:"canonicalHost"`
AllowOrigin []string `json:"allowOrigin"`
AllowAdminOrigin []string `json:"allowAdminOrigin"`
ProxyURL string `json:"proxyURL"`
WritableGroups bool `json:"writableGroups"`
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)
}
var wsUpgrader = websocket.Upgrader{
HandshakeTimeout: 30 * time.Second,
func CheckOrigin(w http.ResponseWriter, r *http.Request, admin bool) bool {
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,
CheckOrigin: func(r *http.Request) bool {
return true
return CheckOrigin(nil, r, false)
},
}
func wsHandler(w http.ResponseWriter, r *http.Request) {
conf, err := group.GetConfiguration()
if err != nil {
httpError(w, err)
return
}
upgrader := wsUpgrader
if conf.PublicServer {
upgrader = wsPublicUpgrader
}
conn, err := upgrader.Upgrade(w, r, nil)
conn, err := wsUpgrader.Upgrade(w, r, nil)
if err != nil {
log.Printf("Websocket upgrade: %v", err)
return
+2 -18
View File
@@ -165,15 +165,7 @@ func whipEndpointHandler(w http.ResponseWriter, r *http.Request) {
return
}
conf, err := group.GetConfiguration()
if err != nil {
httpError(w, err)
return
}
if conf.PublicServer {
w.Header().Set("Access-Control-Allow-Origin", "*")
}
CheckOrigin(w, r, false)
if r.Method == "OPTIONS" {
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()
if err != nil {
httpError(w, err)
return
}
if conf.PublicServer {
w.Header().Set("Access-Control-Allow-Origin", "*")
}
CheckOrigin(w, r, false)
if r.Method == "OPTIONS" {
w.Header().Set("Access-Control-Allow-Methods",