diff options
Diffstat (limited to 'roseh.moe.go')
| -rw-r--r-- | roseh.moe.go | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/roseh.moe.go b/roseh.moe.go index 53deb02..e8f2d41 100644 --- a/roseh.moe.go +++ b/roseh.moe.go @@ -829,6 +829,63 @@ func logout(w http.ResponseWriter, r *http.Request) { } var ( + //go:embed templates/otp.html.template + otpString string + otpTemplate = template.Must(outlinedTemplate(otpString)) + + otpMu sync.Mutex + currentOTP string +) + +type otpTemplateArgs struct { + URL string + QR string +} + +func otp(w http.ResponseWriter, r *http.Request) { + buf := make([]byte, 20) + rand.Read(buf) + newOTP := new(strings.Builder) + for i := range 10 { + if i > 0 { + newOTP.WriteString("-") + } + newOTP.WriteString(wordlist.Words[binary.NativeEndian.Uint16(buf[2*i:])&0x1fff]) + } + otpMu.Lock() + currentOTP = newOTP.String() + otpMu.Unlock() + downloadURL := selfURL.String() + "/otp/" + newOTP.String() + if err := otpTemplate.Execute(w, otpTemplateArgs{ + URL: downloadURL, + QR: "/qr.png?" + url.Values{"t": []string{downloadURL}, "s": []string{base64.RawURLEncoding.EncodeToString(mac([]byte(downloadURL), "qr"))}}.Encode(), + }); err != nil { + log.Printf("Warning: otp: %s", err) + } +} + +func otpCode(w http.ResponseWriter, r *http.Request) { + code := r.PathValue("code") + if code == "" { + notFound(w, r) + return + } + matched := false + otpMu.Lock() + if code == currentOTP { + currentOTP = "" + matched = true + } + otpMu.Unlock() + if !matched { + notFound(w, r) + return + } + attachCookie(w) + io.WriteString(w, "logged in\n") +} + +var ( //go:embed templates/note.html.template notepadString string notepadTemplate = template.Must(outlinedTemplate(notepadString)) @@ -1140,6 +1197,8 @@ func main() { mux.HandleFunc("GET /wormhole/{hole}", wormholeDownload) mux.HandleFunc("GET /login", serveLogin) mux.HandleFunc("POST /login", login) + mux.Handle("GET /otp", &authHandler{h: http.HandlerFunc(otp)}) + mux.HandleFunc("GET /otp/{code}", otpCode) mux.Handle("GET /logout", &authHandler{h: http.HandlerFunc(logout), noRedirect: true}) mux.Handle("GET /notepad", &authHandler{h: http.HandlerFunc(notepad)}) mux.Handle("POST /notepad", &authHandler{h: http.HandlerFunc(autosave), noRedirect: true}) |
