From 81a587aa1946106382efc24e1493063a699f1d13 Mon Sep 17 00:00:00 2001 From: agolebiowska Date: Tue, 28 Jan 2020 11:04:10 +0100 Subject: [PATCH] Backend: Support encrypted password (#231) See issue #221, only handles bcrypt --- internal/api/session.go | 2 +- internal/config/utils.go | 26 +++++++++++++++++++++++ internal/config/utils_test.go | 40 +++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 internal/config/utils.go create mode 100644 internal/config/utils_test.go diff --git a/internal/api/session.go b/internal/api/session.go index f1efb0327..146d82670 100644 --- a/internal/api/session.go +++ b/internal/api/session.go @@ -20,7 +20,7 @@ func CreateSession(router *gin.RouterGroup, conf *config.Config) { return } - if f.Password != conf.AdminPassword() { + if !conf.CheckPassword(f.Password) { c.AbortWithStatusJSON(400, gin.H{"error": "Invalid password"}) return } diff --git a/internal/config/utils.go b/internal/config/utils.go new file mode 100644 index 000000000..5008709b7 --- /dev/null +++ b/internal/config/utils.go @@ -0,0 +1,26 @@ +package config + +import ( + "regexp" + + "golang.org/x/crypto/bcrypt" +) + +func isBcrypt(s string) bool { + b, err := regexp.MatchString(`^\$2[ayb]\$.{56}$`, s) + if err != nil { + return false + } + return b +} + +func (c *Config) CheckPassword(p string) bool { + ap := c.AdminPassword() + + if isBcrypt(ap) { + err := bcrypt.CompareHashAndPassword([]byte(ap), []byte(p)) + return err == nil + } + + return ap == p +} diff --git a/internal/config/utils_test.go b/internal/config/utils_test.go new file mode 100644 index 000000000..018d2d24c --- /dev/null +++ b/internal/config/utils_test.go @@ -0,0 +1,40 @@ +package config + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestUtils_CheckPassword(t *testing.T) { + ctx := CliTestContext() + c := NewConfig(ctx) + formPassword := "photoprism" + + c.config.AdminPassword = "$2b$10$cRhWIleqJkbaFWhBMp54VOI25RvVubxOooCWzWgdrvl5COFxaBnAy" + check := c.CheckPassword(formPassword) + assert.True(t, check) + + c.config.AdminPassword = "photoprism" + check = c.CheckPassword(formPassword) + assert.True(t, check) + + c.config.AdminPassword = "$2b$10$yprZEQzm/Qy7AaePXtKfkem0kANBZgRwl8HbLE4JrjK6/8Pypgi1W" + check = c.CheckPassword(formPassword) + assert.False(t, check) + + c.config.AdminPassword = "admin" + check = c.CheckPassword(formPassword) + assert.False(t, check) +} + +func TestUtils_isBcrypt(t *testing.T) { + p := "$2b$10$cRhWIleqJkbaFWhBMp54VOI25RvVubxOooCWzWgdrvl5COFxaBnAy" + assert.True(t, isBcrypt(p)) + + p = "$2b$10$cRhWIleqJkbaFWhBMp54VOI25RvVubxOooCWzWgdrvl5COFxaBnA" + assert.False(t, isBcrypt(p)) + + p = "admin" + assert.False(t, isBcrypt(p)) +}