summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJakob Borg <jakob@kastelo.net>2023-09-24 19:23:49 +0200
committerGitHub <noreply@github.com>2023-09-24 19:23:49 +0200
commit6ed9c0c34cd5f98b5769288d36b7c654e7ebb513 (patch)
tree9be10ce6c8cc8e11e962bdfa3f77c853303d190c
parent19bbf4f6bf3cf2fc56d3e983e455be5fe2ffddcb (diff)
lib/config: Accept pre-hashed password (fixes #9123) (#9124)
-rw-r--r--cmd/syncthing/generate/generate.go4
-rw-r--r--lib/api/api_auth_test.go2
-rw-r--r--lib/api/confighandler.go4
-rw-r--r--lib/config/config_test.go14
-rw-r--r--lib/config/guiconfiguration.go17
5 files changed, 32 insertions, 9 deletions
diff --git a/cmd/syncthing/generate/generate.go b/cmd/syncthing/generate/generate.go
index 6b3d0b3690..5446cb3baf 100644
--- a/cmd/syncthing/generate/generate.go
+++ b/cmd/syncthing/generate/generate.go
@@ -69,7 +69,7 @@ func Generate(l logger.Logger, confDir, guiUser, guiPassword string, noDefaultFo
return err
}
- if err := syncthing.EnsureDir(dir, 0700); err != nil {
+ if err := syncthing.EnsureDir(dir, 0o700); err != nil {
return err
}
locations.SetBaseDir(locations.ConfigBaseDir, dir)
@@ -127,7 +127,7 @@ func updateGUIAuthentication(l logger.Logger, guiCfg *config.GUIConfiguration, g
}
if guiPassword != "" && guiCfg.Password != guiPassword {
- if err := guiCfg.HashAndSetPassword(guiPassword); err != nil {
+ if err := guiCfg.SetPassword(guiPassword); err != nil {
return fmt.Errorf("failed to set GUI authentication password: %w", err)
}
l.Infoln("Updated GUI authentication password.")
diff --git a/lib/api/api_auth_test.go b/lib/api/api_auth_test.go
index be6a0c3a80..ed3677eeb2 100644
--- a/lib/api/api_auth_test.go
+++ b/lib/api/api_auth_test.go
@@ -16,7 +16,7 @@ var guiCfg config.GUIConfiguration
func init() {
guiCfg.User = "user"
- guiCfg.HashAndSetPassword("pass")
+ guiCfg.SetPassword("pass")
}
func TestStaticAuthOK(t *testing.T) {
diff --git a/lib/api/confighandler.go b/lib/api/confighandler.go
index 5abc1f055e..fc3e73a598 100644
--- a/lib/api/confighandler.go
+++ b/lib/api/confighandler.go
@@ -319,7 +319,7 @@ func (c *configMuxBuilder) adjustConfig(w http.ResponseWriter, r *http.Request)
var status int
waiter, err := c.cfg.Modify(func(cfg *config.Configuration) {
if to.GUI.Password != cfg.GUI.Password {
- if err := to.GUI.HashAndSetPassword(to.GUI.Password); err != nil {
+ if err := to.GUI.SetPassword(to.GUI.Password); err != nil {
l.Warnln("hashing password:", err)
errMsg = err.Error()
status = http.StatusInternalServerError
@@ -401,7 +401,7 @@ func (c *configMuxBuilder) adjustGUI(w http.ResponseWriter, r *http.Request, gui
var status int
waiter, err := c.cfg.Modify(func(cfg *config.Configuration) {
if gui.Password != oldPassword {
- if err := gui.HashAndSetPassword(gui.Password); err != nil {
+ if err := gui.SetPassword(gui.Password); err != nil {
l.Warnln("hashing password:", err)
errMsg = err.Error()
status = http.StatusInternalServerError
diff --git a/lib/config/config_test.go b/lib/config/config_test.go
index 241cc2b596..d90e01fb94 100644
--- a/lib/config/config_test.go
+++ b/lib/config/config_test.go
@@ -22,6 +22,7 @@ import (
"testing"
"github.com/d4l3k/messagediff"
+ "golang.org/x/crypto/bcrypt"
"github.com/syncthing/syncthing/lib/build"
"github.com/syncthing/syncthing/lib/events"
@@ -773,8 +774,9 @@ func TestGUIConfigURL(t *testing.T) {
func TestGUIPasswordHash(t *testing.T) {
var c GUIConfiguration
+ // Setting a plaintext password should work
testPass := "pass"
- if err := c.HashAndSetPassword(testPass); err != nil {
+ if err := c.SetPassword(testPass); err != nil {
t.Fatal(err)
}
if c.Password == testPass {
@@ -789,6 +791,16 @@ func TestGUIPasswordHash(t *testing.T) {
if err := c.CompareHashedPassword(failPass); err == nil {
t.Errorf("Match on different password: %v", err)
}
+
+ // Setting a bcrypt hash directly should also work
+ hash, err := bcrypt.GenerateFromPassword([]byte("test"), bcrypt.MinCost)
+ if err != nil {
+ t.Fatal(err)
+ }
+ c.SetPassword(string(hash))
+ if err := c.CompareHashedPassword("test"); err != nil {
+ t.Errorf("No match on hashed password: %v", err)
+ }
}
func TestDuplicateDevices(t *testing.T) {
diff --git a/lib/config/guiconfiguration.go b/lib/config/guiconfiguration.go
index cbedfffcb1..9f5df227ff 100644
--- a/lib/config/guiconfiguration.go
+++ b/lib/config/guiconfiguration.go
@@ -9,6 +9,7 @@ package config
import (
"net/url"
"os"
+ "regexp"
"strconv"
"strings"
@@ -115,9 +116,19 @@ func (c GUIConfiguration) URL() string {
return u.String()
}
-// SetHashedPassword hashes the given plaintext password and stores the new hash.
-func (c *GUIConfiguration) HashAndSetPassword(password string) error {
- hash, err := bcrypt.GenerateFromPassword([]byte(password), 0)
+// matches a bcrypt hash and not too much else
+var bcryptExpr = regexp.MustCompile(`^\$2[aby]\$\d+\$.{50,}`)
+
+// SetPassword takes a bcrypt hash or a plaintext password and stores it.
+// Plaintext passwords are hashed. Returns an error if the password is not
+// valid.
+func (c *GUIConfiguration) SetPassword(password string) error {
+ if bcryptExpr.MatchString(password) {
+ // Already hashed
+ c.Password = password
+ return nil
+ }
+ hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
return err
}