forked from things-go/go-socks5
-
Notifications
You must be signed in to change notification settings - Fork 0
/
auth.go
78 lines (66 loc) · 2.33 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
package socks5
import (
"io"
"github.com/thinkgos/go-socks5/statute"
)
// AuthContext A Request encapsulates authentication state provided
// during negotiation
type AuthContext struct {
// Provided auth method
Method uint8
// Payload provided during negotiation.
// Keys depend on the used auth method.
// For UserPass auth contains username/password
Payload map[string]string
}
// Authenticator provide auth
type Authenticator interface {
Authenticate(reader io.Reader, writer io.Writer, userAddr string) (*AuthContext, error)
GetCode() uint8
}
// NoAuthAuthenticator is used to handle the "No Authentication" mode
type NoAuthAuthenticator struct{}
// GetCode implement interface Authenticator
func (a NoAuthAuthenticator) GetCode() uint8 { return statute.MethodNoAuth }
// Authenticate implement interface Authenticator
func (a NoAuthAuthenticator) Authenticate(_ io.Reader, writer io.Writer, _ string) (*AuthContext, error) {
_, err := writer.Write([]byte{statute.VersionSocks5, statute.MethodNoAuth})
return &AuthContext{statute.MethodNoAuth, make(map[string]string)}, err
}
// UserPassAuthenticator is used to handle username/password based
// authentication
type UserPassAuthenticator struct {
Credentials CredentialStore
}
// GetCode implement interface Authenticator
func (a UserPassAuthenticator) GetCode() uint8 { return statute.MethodUserPassAuth }
// Authenticate implement interface Authenticator
func (a UserPassAuthenticator) Authenticate(reader io.Reader, writer io.Writer, userAddr string) (*AuthContext, error) {
// reply the client to use user/pass auth
if _, err := writer.Write([]byte{statute.VersionSocks5, statute.MethodUserPassAuth}); err != nil {
return nil, err
}
// get user and user's password
nup, err := statute.ParseUserPassRequest(reader)
if err != nil {
return nil, err
}
// Verify the password
if !a.Credentials.Valid(string(nup.User), string(nup.Pass), userAddr) {
if _, err := writer.Write([]byte{statute.UserPassAuthVersion, statute.AuthFailure}); err != nil {
return nil, err
}
return nil, statute.ErrUserAuthFailed
}
if _, err := writer.Write([]byte{statute.UserPassAuthVersion, statute.AuthSuccess}); err != nil {
return nil, err
}
// Done
return &AuthContext{
statute.MethodUserPassAuth,
map[string]string{
"username": string(nup.User),
"password": string(nup.Pass),
},
}, nil
}