feat: install code of 3 to 24 letters and digits with a button to make a new one; guesses are limited per address

This commit is contained in:
redtea committed 2026-10-14 21:07:36 +03:00
1 parent 47f1b2e55b
commit 29353e5e6a
4 files changed
+71 -12

No files matched your search

+25 -1
View File
@@ -410,6 +410,7 @@ func (s *Server) handleSettings(w http.ResponseWriter, r *http.Request) {
"Admin": s.currentAdmin(r),
"Host": host,
"Secret": secret,
"CodeLen": s.db.InstallCodeLen(),
"Admins": admins,
"KeyCounts": keyCounts,
"PassOff": passOff,
@@ -516,7 +517,22 @@ func (s *Server) handleRotateSecret(w http.ResponseWriter, r *http.Request) {
}
_ = s.db.SetConfig(cfgEnrollSecret, randToken())
// Rotate the short install code too so old /i/<code> links stop working.
_ = s.db.SetConfig(cfgInstallCode, shortCode())
_ = s.db.SetConfig(cfgInstallCode, shortCode(s.db.InstallCodeLen()))
http.Redirect(w, r, "/settings", http.StatusSeeOther)
}
// POST /settings/install/code - a new install code, of the length given:
// the old /i/<code> link stops working.
func (s *Server) handleInstallCode(w http.ResponseWriter, r *http.Request) {
if !checkCSRF(r) {
http.Error(w, "bad csrf", http.StatusForbidden)
return
}
if n, err := strconv.Atoi(r.FormValue("len")); err == nil {
n = min(installCodeMax, max(installCodeMin, n))
_ = s.db.SetConfig(cfgInstallLen, strconv.Itoa(n))
}
_ = s.db.SetConfig(cfgInstallCode, shortCode(s.db.InstallCodeLen()))
http.Redirect(w, r, "/settings", http.StatusSeeOther)
}
@@ -603,9 +619,17 @@ func (s *Server) handleInstallScript(w http.ResponseWriter, r *http.Request) {
//
// wget -qO- https://host/i/<code> | sudo sh
func (s *Server) handleShortInstall(w http.ResponseWriter, r *http.Request) {
// A short code can be guessed: wrong ones count against the address
// like wrong passwords do.
ip := clientIP(r)
if s.limiter.blocked(ip) {
http.Error(w, "too many attempts", http.StatusTooManyRequests)
return
}
code := r.PathValue("code")
want := s.db.InstallCode()
if want == "" || !constantTimeEqual(code, want) {
s.limiter.fin(ip, false)
http.NotFound(w, r)
return
}