cmd/tailscale/cli/web: add QNAP NAS_SID authentication

QTS 5.0 doesn't always pass a qtoken, in some circumstances
it sends a NAS_SID cookie for us to verify instead.

Signed-off-by: Denton Gentry <dgentry@tailscale.com>
This commit is contained in:
Denton Gentry 2022-07-16 16:08:19 -07:00 committed by Denton Gentry
parent 0d52674a84
commit 9fcda1f0a0

View File

@ -208,12 +208,20 @@ func qnapAuthn(r *http.Request) (string, *qnapAuthResponse, error) {
return "", nil, err return "", nil, err
} }
token, err := r.Cookie("qtoken") token, err := r.Cookie("qtoken")
if err != nil { if err == nil {
return "", nil, err return qnapAuthnQtoken(r, user.Value, token.Value)
} }
sid, err := r.Cookie("NAS_SID")
if err == nil {
return qnapAuthnSid(r, user.Value, sid.Value)
}
return "", nil, fmt.Errorf("not authenticated by any mechanism")
}
func qnapAuthnQtoken(r *http.Request, user, token string) (string, *qnapAuthResponse, error) {
query := url.Values{ query := url.Values{
"qtoken": []string{token.Value}, "qtoken": []string{token},
"user": []string{user.Value}, "user": []string{user},
} }
u := url.URL{ u := url.URL{
Scheme: r.URL.Scheme, Scheme: r.URL.Scheme,
@ -221,7 +229,26 @@ func qnapAuthn(r *http.Request) (string, *qnapAuthResponse, error) {
Path: "/cgi-bin/authLogin.cgi", Path: "/cgi-bin/authLogin.cgi",
RawQuery: query.Encode(), RawQuery: query.Encode(),
} }
resp, err := http.Get(u.String())
return qnapAuthnFinish(user, u.String())
}
func qnapAuthnSid(r *http.Request, user, sid string) (string, *qnapAuthResponse, error) {
query := url.Values{
"sid": []string{sid},
}
u := url.URL{
Scheme: r.URL.Scheme,
Host: r.URL.Host,
Path: "/cgi-bin/authLogin.cgi",
RawQuery: query.Encode(),
}
return qnapAuthnFinish(user, u.String())
}
func qnapAuthnFinish(user, url string) (string, *qnapAuthResponse, error) {
resp, err := http.Get(url)
if err != nil { if err != nil {
return "", nil, err return "", nil, err
} }
@ -237,7 +264,7 @@ func qnapAuthn(r *http.Request) (string, *qnapAuthResponse, error) {
if authResp.AuthPassed == 0 { if authResp.AuthPassed == 0 {
return "", nil, fmt.Errorf("not authenticated") return "", nil, fmt.Errorf("not authenticated")
} }
return user.Value, authResp, nil return user, authResp, nil
} }
func synoAuthn() (string, error) { func synoAuthn() (string, error) {