go-socks5/auth.go

79 lines
2.3 KiB
Go
Raw Normal View History

2014-01-23 19:27:48 +00:00
package socks5
import (
"io"
2022-10-17 01:36:23 +00:00
"git.tcp.direct/kayos/go-socks5/statute"
2014-01-23 19:27:48 +00:00
)
2020-04-22 02:15:40 +00:00
// 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.
2020-08-05 06:40:07 +00:00
// For UserPass auth contains username/password
Payload map[string]string
}
2020-04-22 02:15:40 +00:00
// Authenticator provide auth
2014-02-18 14:21:03 +00:00
type Authenticator interface {
2020-04-21 14:31:04 +00:00
Authenticate(reader io.Reader, writer io.Writer, userAddr string) (*AuthContext, error)
2014-02-18 14:21:03 +00:00
GetCode() uint8
}
2014-01-23 19:27:48 +00:00
2014-02-18 14:21:03 +00:00
// NoAuthAuthenticator is used to handle the "No Authentication" mode
type NoAuthAuthenticator struct{}
2014-01-23 19:27:48 +00:00
2020-04-22 02:15:40 +00:00
// GetCode implement interface Authenticator
2020-08-05 06:40:07 +00:00
func (a NoAuthAuthenticator) GetCode() uint8 { return statute.MethodNoAuth }
2014-01-23 19:27:48 +00:00
2020-04-22 02:15:40 +00:00
// Authenticate implement interface Authenticator
2020-04-22 02:32:03 +00:00
func (a NoAuthAuthenticator) Authenticate(_ io.Reader, writer io.Writer, _ string) (*AuthContext, error) {
2020-08-05 05:17:05 +00:00
_, err := writer.Write([]byte{statute.VersionSocks5, statute.MethodNoAuth})
return &AuthContext{statute.MethodNoAuth, make(map[string]string)}, err
2014-01-23 19:27:48 +00:00
}
2014-02-18 14:21:03 +00:00
// UserPassAuthenticator is used to handle username/password based
2014-01-23 19:27:48 +00:00
// authentication
2014-02-18 14:21:03 +00:00
type UserPassAuthenticator struct {
Credentials CredentialStore
}
2020-04-22 02:15:40 +00:00
// GetCode implement interface Authenticator
2020-08-05 06:40:07 +00:00
func (a UserPassAuthenticator) GetCode() uint8 { return statute.MethodUserPassAuth }
2014-02-18 14:21:03 +00:00
2020-04-22 02:15:40 +00:00
// Authenticate implement interface Authenticator
2020-04-21 14:31:04 +00:00
func (a UserPassAuthenticator) Authenticate(reader io.Reader, writer io.Writer, userAddr string) (*AuthContext, error) {
2020-08-05 05:54:05 +00:00
// reply the client to use user/pass auth
2020-08-05 05:17:05 +00:00
if _, err := writer.Write([]byte{statute.VersionSocks5, statute.MethodUserPassAuth}); err != nil {
return nil, err
2014-01-23 19:27:48 +00:00
}
2020-08-05 05:54:05 +00:00
// get user and user's password
2020-08-05 05:17:05 +00:00
nup, err := statute.ParseUserPassRequest(reader)
if err != nil {
return nil, err
2014-01-23 19:27:48 +00:00
}
// Verify the password
2020-08-05 05:17:05 +00:00
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
2014-01-23 19:27:48 +00:00
}
2020-08-05 05:17:05 +00:00
return nil, statute.ErrUserAuthFailed
}
if _, err := writer.Write([]byte{statute.UserPassAuthVersion, statute.AuthSuccess}); err != nil {
return nil, err
2014-01-23 19:27:48 +00:00
}
// Done
2020-08-05 05:17:05 +00:00
return &AuthContext{
statute.MethodUserPassAuth,
map[string]string{
"username": string(nup.User),
"password": string(nup.Pass),
},
}, nil
2014-01-23 19:27:48 +00:00
}