Stop accessing user data in downstreamConn.authenticate
This becomes racy once user.Password is updated on-the-fly.
This commit is contained in:
parent
551d41335e
commit
2fff645129
15
db.go
15
db.go
@ -106,6 +106,21 @@ func (db *DB) ListUsers() ([]User, error) {
|
|||||||
return users, nil
|
return users, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (db *DB) GetUser(username string) (*User, error) {
|
||||||
|
db.lock.RLock()
|
||||||
|
defer db.lock.RUnlock()
|
||||||
|
|
||||||
|
user := &User{Username: username}
|
||||||
|
|
||||||
|
var password *string
|
||||||
|
row := db.db.QueryRow("SELECT password FROM User WHERE username = ?", username)
|
||||||
|
if err := row.Scan(&password); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
user.Password = fromStringPtr(password)
|
||||||
|
return user, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (db *DB) CreateUser(user *User) error {
|
func (db *DB) CreateUser(user *User) error {
|
||||||
db.lock.Lock()
|
db.lock.Lock()
|
||||||
defer db.lock.Unlock()
|
defer db.lock.Unlock()
|
||||||
|
@ -586,19 +586,23 @@ func unmarshalUsername(rawUsername string) (username, network string) {
|
|||||||
func (dc *downstreamConn) authenticate(username, password string) error {
|
func (dc *downstreamConn) authenticate(username, password string) error {
|
||||||
username, networkName := unmarshalUsername(username)
|
username, networkName := unmarshalUsername(username)
|
||||||
|
|
||||||
u := dc.srv.getUser(username)
|
u, err := dc.srv.db.GetUser(username)
|
||||||
if u == nil {
|
|
||||||
dc.logger.Printf("failed authentication for %q: unknown username", username)
|
|
||||||
return errAuthFailed
|
|
||||||
}
|
|
||||||
|
|
||||||
err := bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
dc.logger.Printf("failed authentication for %q: %v", username, err)
|
dc.logger.Printf("failed authentication for %q: %v", username, err)
|
||||||
return errAuthFailed
|
return errAuthFailed
|
||||||
}
|
}
|
||||||
|
|
||||||
dc.user = u
|
err = bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
|
||||||
|
if err != nil {
|
||||||
|
dc.logger.Printf("failed authentication for %q: %v", username, err)
|
||||||
|
return errAuthFailed
|
||||||
|
}
|
||||||
|
|
||||||
|
dc.user = dc.srv.getUser(username)
|
||||||
|
if dc.user == nil {
|
||||||
|
dc.logger.Printf("failed authentication for %q: user not active", username)
|
||||||
|
return errAuthFailed
|
||||||
|
}
|
||||||
dc.networkName = networkName
|
dc.networkName = networkName
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user