From 4e6adec81ab841c8f2ff042702b418ffbb4a569f Mon Sep 17 00:00:00 2001 From: Umar Getagazov Date: Mon, 14 Nov 2022 22:12:50 +0300 Subject: [PATCH] Validate the revision hash on /rev{,-text}/ pages --- history/histweb/histview.go | 11 +---------- util/util.go | 15 +++++++++++++++ web/readers.go | 33 ++++++++++++++++++--------------- 3 files changed, 34 insertions(+), 25 deletions(-) diff --git a/history/histweb/histview.go b/history/histweb/histview.go index 4467b44..4737817 100644 --- a/history/histweb/histview.go +++ b/history/histweb/histview.go @@ -3,7 +3,6 @@ package histweb import ( "embed" - "encoding/hex" "fmt" "github.com/bouncepaw/mycorrhiza/cfg" "github.com/bouncepaw/mycorrhiza/files" @@ -39,15 +38,7 @@ func handlerPrimitiveDiff(w http.ResponseWriter, rq *http.Request) { util.PrepareRq(rq) shorterURL := strings.TrimPrefix(rq.URL.Path, "/primitive-diff/") revHash, slug, found := strings.Cut(shorterURL, "/") - if !found || len(revHash) < 7 || len(slug) < 1 { - http.Error(w, "403 bad request", http.StatusBadRequest) - return - } - paddedRevHash := revHash - if len(paddedRevHash)%2 != 0 { - paddedRevHash = paddedRevHash[:len(paddedRevHash)-1] - } - if _, err := hex.DecodeString(paddedRevHash); err != nil { + if !found || !util.IsRevHash(revHash) || len(slug) < 1 { http.Error(w, "403 bad request", http.StatusBadRequest) return } diff --git a/util/util.go b/util/util.go index 98e37f8..a00230c 100644 --- a/util/util.go +++ b/util/util.go @@ -135,3 +135,18 @@ func (f FormData) Get(key string) string { func (f FormData) Put(key, value string) { f.fields[key] = value } + +// IsRevHash checks if the revision hash is valid. +func IsRevHash(revHash string) bool { + if len(revHash) < 7 { + return false + } + paddedRevHash := revHash + if len(paddedRevHash)%2 != 0 { + paddedRevHash = paddedRevHash[:len(paddedRevHash)-1] + } + if _, err := hex.DecodeString(paddedRevHash); err != nil { + return false + } + return true +} diff --git a/web/readers.go b/web/readers.go index 2bc9a38..53f7576 100644 --- a/web/readers.go +++ b/web/readers.go @@ -59,12 +59,15 @@ func handlerMedia(w http.ResponseWriter, rq *http.Request) { // /rev-text// func handlerRevisionText(w http.ResponseWriter, rq *http.Request) { util.PrepareRq(rq) + shorterURL := strings.TrimPrefix(rq.URL.Path, "/rev-text/") + revHash, slug, found := strings.Cut(shorterURL, "/") + if !found || !util.IsRevHash(revHash) || len(slug) < 1 { + http.Error(w, "403 bad request", http.StatusBadRequest) + return + } var ( - shorterURL = strings.TrimPrefix(rq.URL.Path, "/rev-text/") - firstSlashIndex = strings.IndexRune(shorterURL, '/') - revHash = shorterURL[:firstSlashIndex] - hyphaName = util.CanonicalName(shorterURL[firstSlashIndex+1:]) - h = hyphae.ByName(hyphaName) + hyphaName = util.CanonicalName(slug) + h = hyphae.ByName(hyphaName) ) w.Header().Set("Content-Type", "text/plain; charset=utf-8") switch h := h.(type) { @@ -103,17 +106,17 @@ func handlerRevisionText(w http.ResponseWriter, rq *http.Request) { // handlerRevision displays a specific revision of the text part the hypha func handlerRevision(w http.ResponseWriter, rq *http.Request) { util.PrepareRq(rq) + lc := l18n.FromRequest(rq) + shorterURL := strings.TrimPrefix(rq.URL.Path, "/rev/") + revHash, slug, found := strings.Cut(shorterURL, "/") + if !found || !util.IsRevHash(revHash) || len(slug) < 1 { + http.Error(w, "403 bad request", http.StatusBadRequest) + return + } var ( - lc = l18n.FromRequest(rq) - shorterURL = strings.TrimPrefix(rq.URL.Path, "/rev/") - firstSlashIndex = strings.IndexRune(shorterURL, '/') - revHash = shorterURL[:firstSlashIndex] - hyphaName = util.CanonicalName(shorterURL[firstSlashIndex+1:]) - h = hyphae.ByName(hyphaName) - contents = fmt.Sprintf(`

%s

`, lc.Get("ui.revision_no_text")) - ) - - var ( + hyphaName = util.CanonicalName(slug) + h = hyphae.ByName(hyphaName) + contents = fmt.Sprintf(`

%s

`, lc.Get("ui.revision_no_text")) textContents string err error mycoFilePath string