Merge pull request #1306 from apernet/wip-userpass-ignore-case

Make username of userpass case insensitive
This commit is contained in:
Toby 2025-02-03 18:05:27 -08:00 committed by GitHub
commit 401ed5245d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 32 additions and 7 deletions

View file

@ -755,7 +755,7 @@ func (c *serverConfig) fillAuthenticator(hyConfig *server.Config) error {
if len(c.Auth.UserPass) == 0 {
return configError{Field: "auth.userpass", Err: errors.New("empty auth userpass")}
}
hyConfig.Authenticator = &auth.UserPassAuthenticator{Users: c.Auth.UserPass}
hyConfig.Authenticator = auth.NewUserPassAuthenticator(c.Auth.UserPass)
return nil
case "http", "https":
if c.Auth.HTTP.URL == "" {

View file

@ -16,7 +16,17 @@ var _ server.Authenticator = &UserPassAuthenticator{}
// UserPassAuthenticator checks the provided auth string against a map of username/password pairs.
// The format of the auth string must be "username:password".
type UserPassAuthenticator struct {
Users map[string]string
users map[string]string
}
func NewUserPassAuthenticator(users map[string]string) *UserPassAuthenticator {
// Usernames are case-insensitive, as they are already lowercased by viper.
// Lowercase it again on our own to make it explicit.
lcUsers := make(map[string]string, len(users))
for user, pass := range users {
lcUsers[strings.ToLower(user)] = pass
}
return &UserPassAuthenticator{users: lcUsers}
}
func (a *UserPassAuthenticator) Authenticate(addr net.Addr, auth string, tx uint64) (ok bool, id string) {
@ -24,7 +34,7 @@ func (a *UserPassAuthenticator) Authenticate(addr net.Addr, auth string, tx uint
if !ok {
return false, ""
}
rp, ok := a.Users[u]
rp, ok := a.users[u]
if !ok || rp != p {
return false, ""
}
@ -36,5 +46,6 @@ func splitUserPass(auth string) (user, pass string, ok bool) {
if len(rs) != 2 {
return "", "", false
}
return rs[0], rs[1], true
// Usernames are case-insensitive
return strings.ToLower(rs[0]), rs[1], true
}

View file

@ -85,12 +85,26 @@ func TestUserPassAuthenticator(t *testing.T) {
wantOk: false,
wantId: "",
},
{
name: "case insensitive username",
fields: fields{
Users: map[string]string{
"gawR": "gura",
"fubuki": "shirakami",
},
},
args: args{
addr: nil,
auth: "Gawr:gura",
tx: 0,
},
wantOk: true,
wantId: "gawr",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
a := &UserPassAuthenticator{
Users: tt.fields.Users,
}
a := NewUserPassAuthenticator(tt.fields.Users)
gotOk, gotId := a.Authenticate(tt.args.addr, tt.args.auth, tt.args.tx)
if gotOk != tt.wantOk {
t.Errorf("Authenticate() gotOk = %v, want %v", gotOk, tt.wantOk)