feat: userpass auth

This commit is contained in:
Toby 2023-08-06 12:11:46 -07:00
parent 601ad6b61c
commit 7307eea2a8
8 changed files with 241 additions and 3 deletions

View file

@ -0,0 +1,65 @@
package auth
import (
"net"
"testing"
)
func TestPasswordAuthenticator(t *testing.T) {
type fields struct {
Password string
}
type args struct {
addr net.Addr
auth string
tx uint64
}
tests := []struct {
name string
fields fields
args args
wantOk bool
wantId string
}{
{
name: "correct",
fields: fields{
Password: "yes,yes",
},
args: args{
addr: nil,
auth: "yes,yes",
tx: 0,
},
wantOk: true,
wantId: "user",
},
{
name: "incorrect",
fields: fields{
Password: "something_somehow",
},
args: args{
addr: nil,
auth: "random",
tx: 0,
},
wantOk: false,
wantId: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
a := &PasswordAuthenticator{
Password: tt.fields.Password,
}
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)
}
if gotId != tt.wantId {
t.Errorf("Authenticate() gotId = %v, want %v", gotId, tt.wantId)
}
})
}
}

40
extras/auth/userpass.go Normal file
View file

@ -0,0 +1,40 @@
package auth
import (
"net"
"strings"
"github.com/apernet/hysteria/core/server"
)
const (
userPassSeparator = ":"
)
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
}
func (a *UserPassAuthenticator) Authenticate(addr net.Addr, auth string, tx uint64) (ok bool, id string) {
u, p, ok := splitUserPass(auth)
if !ok {
return false, ""
}
rp, ok := a.Users[u]
if !ok || rp != p {
return false, ""
}
return true, u
}
func splitUserPass(auth string) (user, pass string, ok bool) {
rs := strings.SplitN(auth, userPassSeparator, 2)
if len(rs) != 2 {
return "", "", false
}
return rs[0], rs[1], true
}

View file

@ -0,0 +1,103 @@
package auth
import (
"net"
"testing"
)
func TestUserPassAuthenticator(t *testing.T) {
type fields struct {
Users map[string]string
}
type args struct {
addr net.Addr
auth string
tx uint64
}
tests := []struct {
name string
fields fields
args args
wantOk bool
wantId string
}{
{
name: "correct 1",
fields: fields{
Users: map[string]string{
"saul": "goodman",
"wang": "123",
},
},
args: args{
addr: nil,
auth: "wang:123",
tx: 0,
},
wantOk: true,
wantId: "wang",
},
{
name: "correct 2",
fields: fields{
Users: map[string]string{
"gawr": "gura",
"fubuki": "shirakami",
},
},
args: args{
addr: nil,
auth: "gawr:gura",
tx: 0,
},
wantOk: true,
wantId: "gawr",
},
{
name: "incorrect 1",
fields: fields{
Users: map[string]string{
"gawr": "gura",
"fubuki": "shirakami",
},
},
args: args{
addr: nil,
auth: "random:stranger",
tx: 0,
},
wantOk: false,
wantId: "",
},
{
name: "incorrect 2",
fields: fields{
Users: map[string]string{
"gawr": "gura",
"fubuki": "shirakami",
},
},
args: args{
addr: nil,
auth: "poop",
tx: 0,
},
wantOk: false,
wantId: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
a := &UserPassAuthenticator{
Users: 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)
}
if gotId != tt.wantId {
t.Errorf("Authenticate() gotId = %v, want %v", gotId, tt.wantId)
}
})
}
}