Repository navigation
Expand file tree
/
Copy pathauth_handler.go
More file actions
77 lines (64 loc) · 2 KB
/
Copy pathauth_handler.go
File metadata and controls
77 lines (64 loc) · 2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package socks
import (
"fmt"
"io"
)
const (
// NoAuth means no authentication is used when connecting
NoAuth = uint8(0)
// UserPassAuth means a user/password is used when connecting
UserPassAuth = uint8(2)
noAcceptable = uint8(255)
userAuthVersion = uint8(1)
authSuccess = uint8(0)
authFailure = uint8(1)
)
// AuthHandler handles socks authentication requests
type AuthHandler interface {
Handle(io.Reader, io.Writer) error
Register(uint8, Authenticator)
}
// StandardAuthHandler loads the default authenticators
type StandardAuthHandler struct {
authenticators map[uint8]Authenticator
}
// NewAuthHandler creates a default auth handler
func NewAuthHandler() AuthHandler {
defaults := make(map[uint8]Authenticator)
defaults[NoAuth] = NewNoAuthAuthenticator()
return &StandardAuthHandler{
authenticators: defaults,
}
}
// Register adds/replaces an Authenticator to use when handling Authentication requests
func (h *StandardAuthHandler) Register(method uint8, a Authenticator) {
h.authenticators[method] = a
}
// Handle gets the methods from the SOCKS5 client and authenticates with the first supported method
func (h *StandardAuthHandler) Handle(bufConn io.Reader, conn io.Writer) error {
methods, err := readMethods(bufConn)
if err != nil {
return fmt.Errorf("Failed to read auth methods: %v", err)
}
// first supported method is used
for _, method := range methods {
authenticator := h.authenticators[method]
if authenticator != nil {
return authenticator.Handle(bufConn, conn)
}
}
// failed to authenticate. No supported authentication type found
conn.Write([]byte{socks5Version, noAcceptable})
return fmt.Errorf("unknown authentication type")
}
// readMethods is used to read the number and type of methods
func readMethods(r io.Reader) ([]byte, error) {
header := []byte{0}
if _, err := r.Read(header); err != nil {
return nil, err
}
numMethods := int(header[0])
methods := make([]byte, numMethods)
_, err := io.ReadAtLeast(r, methods, numMethods)
return methods, err
}