Files
gosocks5/server/selector.go
T
2018-11-03 18:52:23 +08:00

71 lines
1.6 KiB
Go

package server
import (
"net"
"net/url"
"github.com/ginuerzh/gosocks5"
)
type serverSelector struct {
methods []uint8
Users []*url.Userinfo
}
func (selector *serverSelector) Methods() []uint8 {
return selector.methods
}
func (selector *serverSelector) AddMethod(methods ...uint8) {
selector.methods = append(selector.methods, methods...)
}
func (selector *serverSelector) Select(methods ...uint8) (method uint8) {
method = gosocks5.MethodNoAuth
// when user/pass is set, auth is mandatory
if len(selector.Users) > 0 {
method = gosocks5.MethodUserPass
}
return
}
func (selector *serverSelector) OnSelected(method uint8, conn net.Conn) (net.Conn, error) {
switch method {
case gosocks5.MethodUserPass:
req, err := gosocks5.ReadUserPassRequest(conn)
if err != nil {
return nil, err
}
valid := false
for _, user := range selector.Users {
username := user.Username()
password, _ := user.Password()
if (req.Username == username && req.Password == password) ||
(req.Username == username && password == "") ||
(username == "" && req.Password == password) {
valid = true
break
}
}
if len(selector.Users) > 0 && !valid {
resp := gosocks5.NewUserPassResponse(gosocks5.UserPassVer, gosocks5.Failure)
if err := resp.Write(conn); err != nil {
return nil, err
}
return nil, gosocks5.ErrAuthFailure
}
resp := gosocks5.NewUserPassResponse(gosocks5.UserPassVer, gosocks5.Succeeded)
if err := resp.Write(conn); err != nil {
return nil, err
}
case gosocks5.MethodNoAcceptable:
return nil, gosocks5.ErrBadMethod
}
return conn, nil
}