diff --git a/models/fixtures/user.yml b/models/fixtures/user.yml index b5f8b27215..b1c7fc0030 100644 --- a/models/fixtures/user.yml +++ b/models/fixtures/user.yml @@ -8,8 +8,8 @@ email: user1@example.com keep_email_private: false email_notifications_preference: enabled - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: user1 @@ -45,8 +45,8 @@ email: user2@example.com keep_email_private: true email_notifications_preference: enabled - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: user2 @@ -82,8 +82,8 @@ email: user3@example.com keep_email_private: false email_notifications_preference: onmention - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: user3 @@ -119,8 +119,8 @@ email: user4@example.com keep_email_private: false email_notifications_preference: onmention - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: user4 @@ -156,8 +156,8 @@ email: user5@example.com keep_email_private: false email_notifications_preference: enabled - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: user5 @@ -193,8 +193,8 @@ email: user6@example.com keep_email_private: false email_notifications_preference: enabled - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: user6 @@ -230,8 +230,8 @@ email: user7@example.com keep_email_private: false email_notifications_preference: disabled - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: user7 @@ -267,8 +267,8 @@ email: user8@example.com keep_email_private: false email_notifications_preference: enabled - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: user8 @@ -304,8 +304,8 @@ email: user9@example.com keep_email_private: false email_notifications_preference: onmention - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: user9 @@ -341,8 +341,8 @@ email: user10@example.com keep_email_private: false email_notifications_preference: enabled - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: user10 @@ -378,8 +378,8 @@ email: user11@example.com keep_email_private: false email_notifications_preference: enabled - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: user11 @@ -415,8 +415,8 @@ email: user12@example.com keep_email_private: false email_notifications_preference: enabled - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: user12 @@ -452,8 +452,8 @@ email: user13@example.com keep_email_private: false email_notifications_preference: enabled - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: user13 @@ -489,8 +489,8 @@ email: user14@example.com keep_email_private: false email_notifications_preference: enabled - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: user14 @@ -526,8 +526,8 @@ email: user15@example.com keep_email_private: false email_notifications_preference: enabled - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: user15 @@ -563,8 +563,8 @@ email: user16@example.com keep_email_private: false email_notifications_preference: enabled - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: user16 @@ -600,8 +600,8 @@ email: user17@example.com keep_email_private: false email_notifications_preference: enabled - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: user17 @@ -637,8 +637,8 @@ email: user18@example.com keep_email_private: false email_notifications_preference: enabled - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: user18 @@ -674,8 +674,8 @@ email: user19@example.com keep_email_private: false email_notifications_preference: enabled - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: user19 @@ -711,8 +711,8 @@ email: user20@example.com keep_email_private: false email_notifications_preference: enabled - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: user20 @@ -748,8 +748,8 @@ email: user21@example.com keep_email_private: false email_notifications_preference: enabled - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: user21 @@ -785,8 +785,8 @@ email: limited_org@example.com keep_email_private: false email_notifications_preference: enabled - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: limited_org @@ -822,8 +822,8 @@ email: privated_org@example.com keep_email_private: false email_notifications_preference: enabled - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: privated_org @@ -859,8 +859,8 @@ email: user24@example.com keep_email_private: true email_notifications_preference: enabled - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: user24 @@ -896,8 +896,8 @@ email: org25@example.com keep_email_private: false email_notifications_preference: enabled - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: org25 @@ -933,8 +933,8 @@ email: org26@example.com keep_email_private: false email_notifications_preference: onmention - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: org26 @@ -970,8 +970,8 @@ email: user27@example.com keep_email_private: false email_notifications_preference: enabled - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: user27 @@ -1007,8 +1007,8 @@ email: user28@example.com keep_email_private: true email_notifications_preference: enabled - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: user28 @@ -1044,8 +1044,8 @@ email: user29@example.com keep_email_private: false email_notifications_preference: enabled - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: user29 @@ -1081,8 +1081,8 @@ email: user30@example.com keep_email_private: false email_notifications_preference: enabled - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: user30 @@ -1118,8 +1118,8 @@ email: user31@example.com keep_email_private: false email_notifications_preference: enabled - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: user31 @@ -1155,8 +1155,8 @@ email: user32@example.com keep_email_private: false email_notifications_preference: enabled - passwd: 7d93daa0d1e6f2305cc8fa496847d61dc7320bb16262f9c55dd753480207234cdd96a93194e408341971742f47017 - passwd_hash_algo: argon2 + passwd: ZogKvWdyEx:notpassword + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: user32 @@ -1192,8 +1192,8 @@ email: user33@example.com keep_email_private: false email_notifications_preference: enabled - passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889 - passwd_hash_algo: pbkdf2$50000$50 + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy must_change_password: false login_source: 0 login_name: user33 diff --git a/models/unittest/fixtures.go b/models/unittest/fixtures.go index 9fba053825..545452a159 100644 --- a/models/unittest/fixtures.go +++ b/models/unittest/fixtures.go @@ -9,6 +9,8 @@ import ( "time" "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/modules/auth/password/hash" + "code.gitea.io/gitea/modules/setting" "github.com/go-testfixtures/testfixtures/v3" "xorm.io/xorm" @@ -64,6 +66,11 @@ func InitFixtures(opts FixturesOptions, engine ...*xorm.Engine) (err error) { return err } + // register the dummy hash algorithm function used in the test fixtures + _ = hash.Register("dummy", hash.NewDummyHasher) + + setting.PasswordHashAlgo, _ = hash.SetDefaultPasswordHashAlgorithm("dummy") + return err } @@ -115,5 +122,8 @@ func LoadFixtures(engine ...*xorm.Engine) error { } } } + _ = hash.Register("dummy", hash.NewDummyHasher) + setting.PasswordHashAlgo, _ = hash.SetDefaultPasswordHashAlgorithm("dummy") + return err } diff --git a/modules/auth/password/hash/argon2.go b/modules/auth/password/hash/argon2.go index 14c16b53c4..0cd6472fa1 100644 --- a/modules/auth/password/hash/argon2.go +++ b/modules/auth/password/hash/argon2.go @@ -13,7 +13,7 @@ import ( ) func init() { - Register("argon2", NewArgon2Hasher) + MustRegister("argon2", NewArgon2Hasher) } // Argon2Hasher implements PasswordHasher diff --git a/modules/auth/password/hash/bcrypt.go b/modules/auth/password/hash/bcrypt.go index ddf5420408..4607c169cd 100644 --- a/modules/auth/password/hash/bcrypt.go +++ b/modules/auth/password/hash/bcrypt.go @@ -8,7 +8,7 @@ import ( ) func init() { - Register("bcrypt", NewBcryptHasher) + MustRegister("bcrypt", NewBcryptHasher) } // BcryptHasher implements PasswordHasher diff --git a/modules/auth/password/hash/dummy.go b/modules/auth/password/hash/dummy.go new file mode 100644 index 0000000000..22f2e2f648 --- /dev/null +++ b/modules/auth/password/hash/dummy.go @@ -0,0 +1,33 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package hash + +import ( + "encoding/hex" +) + +// DummyHasher implements PasswordHasher and is a dummy hasher that simply +// puts the password in place with its salt +// This SHOULD NOT be used in production and is provided to make the integration +// tests faster only +type DummyHasher struct{} + +// HashWithSaltBytes a provided password and salt +func (hasher *DummyHasher) HashWithSaltBytes(password string, salt []byte) string { + if hasher == nil { + return "" + } + + if len(salt) == 10 { + return string(salt) + ":" + password + } + + return hex.EncodeToString(salt) + ":" + password +} + +// NewDummyHasher is a factory method to create a DummyHasher +// Any provided configuration is ignored +func NewDummyHasher(_ string) *DummyHasher { + return &DummyHasher{} +} diff --git a/modules/auth/password/hash/dummy_test.go b/modules/auth/password/hash/dummy_test.go new file mode 100644 index 0000000000..f3b36df625 --- /dev/null +++ b/modules/auth/password/hash/dummy_test.go @@ -0,0 +1,25 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package hash + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestDummyHasher(t *testing.T) { + dummy := &PasswordHashAlgorithm{ + PasswordSaltHasher: NewDummyHasher(""), + Specification: "dummy", + } + + password, salt := "password", "ZogKvWdyEx" + + hash, err := dummy.Hash(password, salt) + assert.Nil(t, err) + assert.Equal(t, hash, salt+":"+password) + + assert.True(t, dummy.VerifyPassword(password, hash, salt)) +} diff --git a/modules/auth/password/hash/hash.go b/modules/auth/password/hash/hash.go index 3572dd46d4..459320e1b0 100644 --- a/modules/auth/password/hash/hash.go +++ b/modules/auth/password/hash/hash.go @@ -83,17 +83,26 @@ var ( availableHasherFactories = map[string]func(string) PasswordSaltHasher{} ) +// MustRegister registers a PasswordSaltHasher with the availableHasherFactories +// Caution: This is not thread safe. +func MustRegister[T PasswordSaltHasher](name string, newFn func(config string) T) { + if err := Register(name, newFn); err != nil { + panic(err) + } +} + // Register registers a PasswordSaltHasher with the availableHasherFactories // Caution: This is not thread safe. -func Register[T PasswordSaltHasher](name string, newFn func(config string) T) { +func Register[T PasswordSaltHasher](name string, newFn func(config string) T) error { if _, has := availableHasherFactories[name]; has { - panic(fmt.Errorf("duplicate registration of password salt hasher: %s", name)) + return fmt.Errorf("duplicate registration of password salt hasher: %s", name) } availableHasherFactories[name] = func(config string) PasswordSaltHasher { n := newFn(config) return n } + return nil } // In early versions of gitea the password hash algorithm field of a user could be diff --git a/modules/auth/password/hash/hash_test.go b/modules/auth/password/hash/hash_test.go index 593c8386a3..7aa051733f 100644 --- a/modules/auth/password/hash/hash_test.go +++ b/modules/auth/password/hash/hash_test.go @@ -19,16 +19,20 @@ func (t testSaltHasher) HashWithSaltBytes(password string, salt []byte) string { } func Test_registerHasher(t *testing.T) { - Register("Test_registerHasher", func(config string) testSaltHasher { + MustRegister("Test_registerHasher", func(config string) testSaltHasher { return testSaltHasher(config) }) assert.Panics(t, func() { - Register("Test_registerHasher", func(config string) testSaltHasher { + MustRegister("Test_registerHasher", func(config string) testSaltHasher { return testSaltHasher(config) }) }) + assert.Error(t, Register("Test_registerHasher", func(config string) testSaltHasher { + return testSaltHasher(config) + })) + assert.Equal(t, "password$salt$", Parse("Test_registerHasher").PasswordSaltHasher.HashWithSaltBytes("password", []byte("salt"))) diff --git a/modules/auth/password/hash/pbkdf2.go b/modules/auth/password/hash/pbkdf2.go index be3121318e..27382fedb8 100644 --- a/modules/auth/password/hash/pbkdf2.go +++ b/modules/auth/password/hash/pbkdf2.go @@ -14,7 +14,7 @@ import ( ) func init() { - Register("pbkdf2", NewPBKDF2Hasher) + MustRegister("pbkdf2", NewPBKDF2Hasher) } // PBKDF2Hasher implements PasswordHasher diff --git a/modules/auth/password/hash/scrypt.go b/modules/auth/password/hash/scrypt.go index e77434fc32..f3d38f751a 100644 --- a/modules/auth/password/hash/scrypt.go +++ b/modules/auth/password/hash/scrypt.go @@ -13,7 +13,7 @@ import ( ) func init() { - Register("scrypt", NewScryptHasher) + MustRegister("scrypt", NewScryptHasher) } // ScryptHasher implements PasswordHasher diff --git a/modules/setting/setting.go b/modules/setting/setting.go index 83ebde9478..87b1e2797f 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -16,6 +16,7 @@ import ( "strings" "time" + "code.gitea.io/gitea/modules/auth/password/hash" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/user" "code.gitea.io/gitea/modules/util" @@ -232,6 +233,10 @@ func InitProviderAndLoadCommonSettingsForTest(extraConfigs ...string) { if err := PrepareAppDataPath(); err != nil { log.Fatal("Can not prepare APP_DATA_PATH: %v", err) } + // register the dummy hash algorithm function used in the test fixtures + _ = hash.Register("dummy", hash.NewDummyHasher) + + PasswordHashAlgo, _ = hash.SetDefaultPasswordHashAlgorithm("dummy") } // newFileProviderFromConf initializes configuration context.