Add early checks for user hashes.

pull/525/head
Clement Michaud 2019-12-27 18:09:57 +01:00 committed by Clément Michaud
parent 1ee442e86f
commit 716e017521
2 changed files with 45 additions and 7 deletions

View File

@ -35,8 +35,15 @@ func NewFileUserProvider(filepath string) *FileUserProvider {
database, err := readDatabase(filepath) database, err := readDatabase(filepath)
if err != nil { if err != nil {
// Panic since the file does not exist when Authelia is starting. // Panic since the file does not exist when Authelia is starting.
panic(err) panic(err.Error())
} }
// Early check whether hashed passwords are correct for all users
err = checkPasswordHashes(database)
if err != nil {
panic(err.Error())
}
return &FileUserProvider{ return &FileUserProvider{
path: &filepath, path: &filepath,
database: database, database: database,
@ -44,24 +51,34 @@ func NewFileUserProvider(filepath string) *FileUserProvider {
} }
} }
func checkPasswordHashes(database *DatabaseModel) error {
for u, v := range database.Users {
_, err := ParseHash(v.HashedPassword)
if err != nil {
return fmt.Errorf("Unable to parse hash of user %s: %s", u, err)
}
}
return nil
}
func readDatabase(path string) (*DatabaseModel, error) { func readDatabase(path string) (*DatabaseModel, error) {
content, err := ioutil.ReadFile(path) content, err := ioutil.ReadFile(path)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("Unable to read database from file %s: %s", path, err)
} }
db := DatabaseModel{} db := DatabaseModel{}
err = yaml.Unmarshal(content, &db) err = yaml.Unmarshal(content, &db)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("Unable to parse database: %s", err)
} }
ok, err := govalidator.ValidateStruct(db) ok, err := govalidator.ValidateStruct(db)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("Invalid schema of database: %s", err)
} }
if !ok { if !ok {
return nil, fmt.Errorf("The database format is invalid: %s", err.Error()) return nil, fmt.Errorf("The database format is invalid: %s", err)
} }
return &db, nil return &db, nil
} }

View File

@ -84,7 +84,7 @@ func TestShouldUpdatePassword(t *testing.T) {
func TestShouldRaiseWhenLoadingMalformedDatabaseForFirstTime(t *testing.T) { func TestShouldRaiseWhenLoadingMalformedDatabaseForFirstTime(t *testing.T) {
WithDatabase(MalformedUserDatabaseContent, func(path string) { WithDatabase(MalformedUserDatabaseContent, func(path string) {
assert.Panics(t, func() { assert.PanicsWithValue(t, "Unable to parse database: yaml: line 4: mapping values are not allowed in this context", func() {
NewFileUserProvider(path) NewFileUserProvider(path)
}) })
}) })
@ -92,7 +92,15 @@ func TestShouldRaiseWhenLoadingMalformedDatabaseForFirstTime(t *testing.T) {
func TestShouldRaiseWhenLoadingDatabaseWithBadSchemaForFirstTime(t *testing.T) { func TestShouldRaiseWhenLoadingDatabaseWithBadSchemaForFirstTime(t *testing.T) {
WithDatabase(BadSchemaUserDatabaseContent, func(path string) { WithDatabase(BadSchemaUserDatabaseContent, func(path string) {
assert.Panics(t, func() { assert.PanicsWithValue(t, "Invalid schema of database: Users: non zero value required", func() {
NewFileUserProvider(path)
})
})
}
func TestShouldRaiseWhenLoadingDatabaseWithBadHashesForTheFirstTime(t *testing.T) {
WithDatabase(BadHashContent, func(path string) {
assert.PanicsWithValue(t, "Unable to parse hash of user john: Cannot match pattern 'rounds=<int>' to find the number of rounds", func() {
NewFileUserProvider(path) NewFileUserProvider(path)
}) })
}) })
@ -165,3 +173,16 @@ users:
password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/" password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/"
email: james.dean@authelia.com email: james.dean@authelia.com
`) `)
var BadHashContent = []byte(`
users:
john:
password: "$6$rounds00000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/"
email: john.doe@authelia.com
groups:
- admins
- dev
james:
password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/"
email: james.dean@authelia.com
`)