Skip to content

Commit 67e0697

Browse files
committed
BUG/MAJOR: authorization: don't leak whether user or password is correct
Also don't allow for timing guesses whether user exists.
1 parent ff77f35 commit 67e0697

File tree

1 file changed

+24
-12
lines changed

1 file changed

+24
-12
lines changed

configuration/user.go

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"errors"
2020
"fmt"
2121
"io/fs"
22+
"net/http"
2223
"os"
2324
"slices"
2425
"strings"
@@ -35,6 +36,8 @@ import (
3536
"github.com/haproxytech/dataplaneapi/storagetype"
3637
)
3738

39+
const mockPass = "$2a$10$e.I1x5KPNu7xy9u0zSzJaOcr5it8kR1Awnaf3boOtYno9y4DolER."
40+
3841
var usersStore *Users
3942

4043
var syncUserStore sync.Once
@@ -164,32 +167,41 @@ func findUser(userName string, users []types.User) (*types.User, error) {
164167
func AuthenticateUser(user string, pass string) (interface{}, error) {
165168
users := GetUsersStore().GetUsers()
166169
if len(users) == 0 {
167-
return nil, api_errors.New(401, "no configured users")
170+
return nil, api_errors.New(http.StatusUnauthorized, "no configured users")
168171
}
169172

173+
unatuhorized := false
170174
u, err := findUser(user, users)
171175
if err != nil {
172-
return nil, err
176+
unatuhorized = true
177+
}
178+
179+
userPass := mockPass
180+
if u != nil {
181+
userPass = u.Password
173182
}
174183

175-
userPass := u.Password
176-
if strings.HasPrefix(u.Password, "\"${") && strings.HasSuffix(u.Password, "}\"") {
184+
if strings.HasPrefix(userPass, "\"${") && strings.HasSuffix(userPass, "}\"") {
177185
userPass = os.Getenv(misc.ExtractEnvVar(userPass))
178186
if userPass == "" {
179-
return nil, api_errors.New(401, "%s %s", "can not read password from env variable:", u.Password)
187+
unatuhorized = true
188+
userPass = mockPass
180189
}
181190
}
182191

183-
if u.IsInsecure {
184-
if pass == userPass {
185-
return user, nil
192+
if u != nil && u.IsInsecure {
193+
if pass != userPass {
194+
unatuhorized = true
195+
}
196+
} else {
197+
if !checkPassword(pass, userPass) {
198+
unatuhorized = true
186199
}
187-
return nil, api_errors.New(401, "%s %s", "invalid password:", pass)
188200
}
189-
if checkPassword(pass, userPass) {
190-
return user, nil
201+
if unatuhorized {
202+
return nil, api_errors.New(http.StatusUnauthorized, "unauthorized")
191203
}
192-
return nil, api_errors.New(401, "%s %s", "invalid password:", pass)
204+
return user, nil
193205
}
194206

195207
func checkPassword(pass, storedPass string) bool {

0 commit comments

Comments
 (0)