summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRose Hogenson <rosehogenson@posteo.net>2025-11-10 22:31:03 -0800
committerRose Hogenson <rosehogenson@posteo.net>2025-11-10 22:31:03 -0800
commita14f5d08c264637639d518267a1397e137823fcf (patch)
treefdd9b146a34f21b9bb9b38c75fb5f965eeb67be8
parent7ebfd2d33571b662a4997004cdba53f220631e8b (diff)
downloadroseh.moe-a14f5d08c264637639d518267a1397e137823fcf.tar.zst
Validate the QR code
Since the qr code is generated by a 3rd party dependency that I probably won't update, let's make sure to only pass it trusted input.
-rw-r--r--roseh.moe.go24
-rw-r--r--templates/wormhole.html.template2
2 files changed, 20 insertions, 6 deletions
diff --git a/roseh.moe.go b/roseh.moe.go
index f5141f3..213e44f 100644
--- a/roseh.moe.go
+++ b/roseh.moe.go
@@ -191,6 +191,7 @@ var (
type wormholeTemplateArgs struct {
Self string
Hole string
+ Sig string
}
func makeHole() string {
@@ -205,11 +206,12 @@ func makeHole() string {
}
func newWormhole(w http.ResponseWriter, r *http.Request) {
- http.Redirect(w, r, "/wormhole/"+makeHole()+"/upload", http.StatusSeeOther)
+ hole := makeHole()
+ http.Redirect(w, r, "/wormhole/"+hole+"/upload?s="+base64.RawURLEncoding.EncodeToString(mac([]byte(hole))), http.StatusSeeOther)
}
func wormhole(w http.ResponseWriter, r *http.Request) {
- if err := wormholeTemplate.Execute(w, wormholeTemplateArgs{Self: *selfURL, Hole: r.PathValue("hole")}); err != nil {
+ if err := wormholeTemplate.Execute(w, wormholeTemplateArgs{Self: *selfURL, Hole: r.PathValue("hole"), Sig: r.FormValue("s")}); err != nil {
log.Printf("Warning: wormhole: %s", err)
}
}
@@ -300,6 +302,16 @@ func wormholeRecv(w http.ResponseWriter, r *http.Request) {
}
func wormholeQR(w http.ResponseWriter, r *http.Request) {
+ sig, err := base64.RawURLEncoding.DecodeString(r.FormValue("s"))
+ if err != nil {
+ http.Error(w, fmt.Sprintf("Bad signature: %s", err), http.StatusBadRequest)
+ return
+ }
+ expectedMAC := mac([]byte(r.PathValue("hole")))
+ if !hmac.Equal(sig, expectedMAC) {
+ http.Error(w, "Bad signature", http.StatusBadRequest)
+ return
+ }
qr, err := qrcode.Encode(*selfURL+"/wormhole/"+r.PathValue("hole"), qrcode.Medium, 200)
if err != nil {
http.Error(w, fmt.Sprintf("failed to encode QR code: %s", err), http.StatusInternalServerError)
@@ -309,10 +321,12 @@ func wormholeQR(w http.ResponseWriter, r *http.Request) {
w.Write(qr)
}
+const macSize = 16 // sorry
+
func mac(msg []byte) []byte {
mac := hmac.New(sha256.New, secretKey)
mac.Write(msg)
- return mac.Sum(nil)
+ return mac.Sum(nil)[:macSize]
}
func sign(msg []byte) []byte {
@@ -320,10 +334,10 @@ func sign(msg []byte) []byte {
}
func verify(msg []byte) ([]byte, bool) {
- if len(msg) < sha256.Size {
+ if len(msg) < macSize {
return nil, false
}
- msg, messageMAC := msg[:len(msg)-sha256.Size], msg[len(msg)-sha256.Size:]
+ msg, messageMAC := msg[:len(msg)-macSize], msg[len(msg)-macSize:]
expectedMAC := mac(msg)
if !hmac.Equal(messageMAC, expectedMAC) {
return nil, false
diff --git a/templates/wormhole.html.template b/templates/wormhole.html.template
index ad23b57..eb423ca 100644
--- a/templates/wormhole.html.template
+++ b/templates/wormhole.html.template
@@ -12,7 +12,7 @@
</li>
<li>
<p>Visit this URL <a href="/wormhole/{{.Hole}}">{{.Self}}/wormhole/{{.Hole}}</a> or scan QR code:</p>
- <img src="/wormhole/{{.Hole}}/qr.png" alt="QR code for {{.Self}}/wormhole/{{.Hole}}">
+ <img src="/wormhole/{{.Hole}}/qr.png?s={{.Sig}}" alt="QR code for {{.Self}}/wormhole/{{.Hole}}">
</li>
<li>
<label for="submit">Click here:</label>