1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
// synology.go contains handlers and logic, such as authentication,
// that is specific to running the web client on Synology.
package web
import (
"errors"
"fmt"
"net/http"
"os/exec"
"strings"
"tailscale.com/util/groupmember"
)
// authorizeSynology authenticates the logged-in Synology user and verifies
// that they are authorized to use the web client.
// If the user is authenticated, but not authorized to use the client, an error is returned.
func authorizeSynology(r *http.Request) (authorized bool, err error) {
if !hasSynoToken(r) {
return false, nil
}
// authenticate the Synology user
cmd := exec.Command("/usr/syno/synoman/webman/modules/authenticate.cgi")
out, err := cmd.CombinedOutput()
if err != nil {
return false, fmt.Errorf("auth: %v: %s", err, out)
}
user := strings.TrimSpace(string(out))
// check if the user is in the administrators group
isAdmin, err := groupmember.IsMemberOfGroup("administrators", user)
if err != nil {
return false, err
}
if !isAdmin {
return false, errors.New("not a member of administrators group")
}
return true, nil
}
// hasSynoToken returns true if the request include a SynoToken used for synology auth.
func hasSynoToken(r *http.Request) bool {
if r.Header.Get("X-Syno-Token") != "" {
return true
}
if r.URL.Query().Get("SynoToken") != "" {
return true
}
if r.Method == "POST" && r.FormValue("SynoToken") != "" {
return true
}
return false
}
|