mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-21 16:38:23 +01:00
allow hmac authentication for read-file
This commit is contained in:
parent
4c68fc4ceb
commit
5f9f02d1cb
@ -37,6 +37,7 @@ import (
|
||||
"github.com/wavetermdev/waveterm/waveshell/pkg/wlog"
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/cmdrunner"
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/pcloud"
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/promptenc"
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/releasechecker"
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/remote"
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/rtnstate"
|
||||
@ -695,6 +696,35 @@ func AuthKeyMiddleWare(next http.Handler) http.Handler {
|
||||
})
|
||||
}
|
||||
|
||||
func AuthKeyWrapAllowHmac(fn WebFnType) WebFnType {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
reqAuthKey := r.Header.Get("X-AuthKey")
|
||||
if reqAuthKey == "" {
|
||||
// try hmac
|
||||
qvals := r.URL.Query()
|
||||
if !qvals.Has("hmac") {
|
||||
w.WriteHeader(500)
|
||||
w.Write([]byte("no x-authkey header"))
|
||||
return
|
||||
}
|
||||
hmacOk, err := promptenc.ValidateUrlHmac([]byte(GlobalAuthKey), r.URL.Path, qvals)
|
||||
if err != nil || !hmacOk {
|
||||
w.WriteHeader(500)
|
||||
w.Write([]byte(fmt.Sprintf("error validating hmac")))
|
||||
return
|
||||
}
|
||||
// fallthrough (hmac is valid)
|
||||
} else if reqAuthKey != GlobalAuthKey {
|
||||
w.WriteHeader(500)
|
||||
w.Write([]byte("x-authkey header is invalid"))
|
||||
return
|
||||
}
|
||||
w.Header().Set(CacheControlHeaderKey, CacheControlHeaderNoCache)
|
||||
fn(w, r)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func AuthKeyWrap(fn WebFnType) WebFnType {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
reqAuthKey := r.Header.Get("X-AuthKey")
|
||||
@ -921,7 +951,7 @@ func main() {
|
||||
gr.HandleFunc("/api/get-client-data", AuthKeyWrap(HandleGetClientData))
|
||||
gr.HandleFunc("/api/set-winsize", AuthKeyWrap(HandleSetWinSize))
|
||||
gr.HandleFunc("/api/log-active-state", AuthKeyWrap(HandleLogActiveState))
|
||||
gr.HandleFunc("/api/read-file", AuthKeyWrap(HandleReadFile))
|
||||
gr.HandleFunc("/api/read-file", AuthKeyWrapAllowHmac(HandleReadFile))
|
||||
gr.HandleFunc("/api/write-file", AuthKeyWrap(HandleWriteFile)).Methods("POST")
|
||||
configPath := path.Join(scbase.GetWaveHomeDir(), "config") + "/"
|
||||
log.Printf("[wave] config path: %q\n", configPath)
|
||||
|
52
wavesrv/pkg/promptenc/hmac.go
Normal file
52
wavesrv/pkg/promptenc/hmac.go
Normal file
@ -0,0 +1,52 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package promptenc
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
func ComputeUrlHmac(key []byte, baseUrl string, qvals url.Values) (string, error) {
|
||||
if qvals.Has("nonce") {
|
||||
return "", fmt.Errorf("nonce is required for hmac")
|
||||
}
|
||||
if qvals.Has("hmac") {
|
||||
return "", fmt.Errorf("hmac is already present")
|
||||
}
|
||||
encStr := baseUrl + "?" + qvals.Encode()
|
||||
mac := hmac.New(sha256.New, key)
|
||||
mac.Write([]byte(encStr))
|
||||
rtn := mac.Sum(nil)
|
||||
return base64.URLEncoding.EncodeToString(rtn), nil
|
||||
}
|
||||
|
||||
func copyUrlValues(src url.Values) url.Values {
|
||||
rtn := make(url.Values)
|
||||
for k, v := range src {
|
||||
rtn[k] = v
|
||||
}
|
||||
return rtn
|
||||
}
|
||||
|
||||
func ValidateUrlHmac(key []byte, baseUrl string, qvalsOrig url.Values) (bool, error) {
|
||||
qvals := copyUrlValues(qvalsOrig)
|
||||
hmacStr := qvals.Get("hmac")
|
||||
if hmacStr == "" {
|
||||
return false, fmt.Errorf("no hmac key found"))
|
||||
}
|
||||
qvals.Del("hmac")
|
||||
encStr := baseUrl + "?" + qvals.Encode()
|
||||
mac := hmac.New(sha256.New, key)
|
||||
mac.Write([]byte(encStr))
|
||||
expected := mac.Sum(nil)
|
||||
actual, err := base64.URLEncoding.DecodeString(hmacStr)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("error decoding hmac: %w", err)
|
||||
}
|
||||
return hmac.Equal(expected, actual), nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user