database: upgrade bcrypt cost as needed

Closes: https://todo.sr.ht/~emersion/soju/136
This commit is contained in:
gildarts 2022-07-04 19:56:47 -04:00 committed by Simon Ser
parent 0777ca0d29
commit 48960a2992
2 changed files with 21 additions and 6 deletions

View File

@ -72,18 +72,26 @@ type User struct {
Admin bool Admin bool
} }
func (u *User) CheckPassword(password string) error { func (u *User) CheckPassword(password string) (upgraded bool, err error) {
// Password auth disabled // Password auth disabled
if u.Password == "" { if u.Password == "" {
return fmt.Errorf("password auth disabled") return false, fmt.Errorf("password auth disabled")
} }
err := bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password)) err = bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
if err != nil { if err != nil {
return fmt.Errorf("wrong password: %v", err) return false, fmt.Errorf("wrong password: %v", err)
} }
return nil passCost, err := bcrypt.Cost([]byte(u.Password))
if err != nil {
return false, fmt.Errorf("invalid password cost: %v", err)
}
if passCost < bcrypt.DefaultCost {
return true, u.SetPassword(password)
}
return false, nil
} }
func (u *User) SetPassword(password string) error { func (u *User) SetPassword(password string) error {

View File

@ -1312,10 +1312,17 @@ func (dc *downstreamConn) authenticate(ctx context.Context, username, password s
return newInvalidUsernameOrPasswordError(fmt.Errorf("user not found: %w", err)) return newInvalidUsernameOrPasswordError(fmt.Errorf("user not found: %w", err))
} }
if err := u.CheckPassword(password); err != nil { upgraded, err := u.CheckPassword(password)
if err != nil {
return newInvalidUsernameOrPasswordError(err) return newInvalidUsernameOrPasswordError(err)
} }
if upgraded {
if err := dc.srv.db.StoreUser(ctx, u); err != nil {
return err
}
}
dc.user = dc.srv.getUser(username) dc.user = dc.srv.getUser(username)
if dc.user == nil { if dc.user == nil {
return fmt.Errorf("user exists in the DB but hasn't been loaded by the bouncer -- a restart may help") return fmt.Errorf("user exists in the DB but hasn't been loaded by the bouncer -- a restart may help")