/
auth.go
108 lines (95 loc) · 2.53 KB
/
auth.go
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package statute
import (
"fmt"
"io"
)
// auth error defined
var (
ErrUserAuthFailed = fmt.Errorf("user authentication failed")
ErrNoSupportedAuth = fmt.Errorf("no supported authentication mechanism")
)
// UserPassRequest is the negotiation user's password request packet
// The SOCKS handshake user's password request is formed as follows:
//
// +--------------+------+----------+------+----------+
// | USERPASS_VER | ULEN | USER | PLEN | PASS |
// +--------------+------+----------+------+----------+
// | 1 | 1 | Variable | 1 | Variable |
// +--------------+------+----------+------+----------+
type UserPassRequest struct {
Ver byte
Ulen byte
Plen byte
User []byte // 1-255 bytes
Pass []byte // 1-255 bytes
}
// NewUserPassRequest new user's password request packet with ver,user, pass
func NewUserPassRequest(ver byte, user, pass []byte) UserPassRequest {
return UserPassRequest{
ver,
byte(len(user)),
byte(len(pass)),
user,
pass,
}
}
// ParseUserPassRequest parse user's password request.
//
//nolint:nakedret
func ParseUserPassRequest(r io.Reader) (nup UserPassRequest, err error) {
tmp := []byte{0, 0}
// Get the version and username length
if _, err = io.ReadAtLeast(r, tmp, 2); err != nil {
return
}
nup.Ver, nup.Ulen = tmp[0], tmp[1]
// Ensure the UserPass version
if nup.Ver != UserPassAuthVersion {
err = fmt.Errorf("unsupported auth version: %v", nup.Ver)
return
}
// Get the user name
nup.User = make([]byte, nup.Ulen)
if _, err = io.ReadAtLeast(r, nup.User, int(nup.Ulen)); err != nil {
return
}
// Get the password length
if _, err = r.Read(tmp[:1]); err != nil {
return
}
nup.Plen = tmp[0]
// Get the password
nup.Pass = make([]byte, nup.Plen)
_, err = io.ReadAtLeast(r, nup.Pass, int(nup.Plen))
return nup, err
}
// Bytes to bytes
func (sf UserPassRequest) Bytes() []byte {
b := make([]byte, 0, 3+sf.Ulen+sf.Plen)
b = append(b, sf.Ver, sf.Ulen)
b = append(b, sf.User...)
b = append(b, sf.Plen)
b = append(b, sf.Pass...)
return b
}
// UserPassReply is the negotiation user's password reply packet
// The SOCKS handshake user's password response is formed as follows:
//
// +-----+--------+
// | VER | status |
// +-----+--------+
// | 1 | 1 |
// +-----+--------+
type UserPassReply struct {
Ver byte
Status byte
}
// ParseUserPassReply parse user's password reply packet.
func ParseUserPassReply(r io.Reader) (upr UserPassReply, err error) {
bb := []byte{0, 0}
if _, err = io.ReadFull(r, bb); err != nil {
return
}
upr.Ver, upr.Status = bb[0], bb[1]
return
}