diff --git a/database/database.go b/database/database.go index fda61c8..eb5240e 100644 --- a/database/database.go +++ b/database/database.go @@ -72,18 +72,26 @@ type User struct { Admin bool } -func (u *User) CheckPassword(password string) error { +func (u *User) CheckPassword(password string) (upgraded bool, err error) { // Password auth disabled 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 { - 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 { diff --git a/downstream.go b/downstream.go index f728e30..9c70029 100644 --- a/downstream.go +++ b/downstream.go @@ -1312,10 +1312,17 @@ func (dc *downstreamConn) authenticate(ctx context.Context, username, password s 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) } + if upgraded { + if err := dc.srv.db.StoreUser(ctx, u); err != nil { + return err + } + } + dc.user = dc.srv.getUser(username) if dc.user == nil { return fmt.Errorf("user exists in the DB but hasn't been loaded by the bouncer -- a restart may help")