115 lines
2.9 KiB
Go
115 lines
2.9 KiB
Go
package socks5
|
|
|
|
import (
|
|
"io"
|
|
)
|
|
|
|
// PasswordNegotiationRequest is the password negotiation reqeust packet
|
|
type PasswordNegotiationRequest struct {
|
|
UsernameLen byte
|
|
Username string
|
|
PasswordLen byte
|
|
Password string
|
|
}
|
|
|
|
// NewPasswordNegotiationRequest returns new password negotiation request packet
|
|
func NewPasswordNegotiationRequest(username string, password string) *PasswordNegotiationRequest {
|
|
return &PasswordNegotiationRequest{
|
|
UsernameLen: byte(len(username)),
|
|
Username: username,
|
|
PasswordLen: byte(len(password)),
|
|
Password: password,
|
|
}
|
|
}
|
|
|
|
// NewPasswordNegotiationRequestFrom reads password negotiation request packet from reader
|
|
func NewPasswordNegotiationRequestFrom(r io.Reader) (*PasswordNegotiationRequest, error) {
|
|
buf := make([]byte, 2)
|
|
if _, err := io.ReadFull(r, buf); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if buf[0] != PasswordVersion {
|
|
return nil, ErrPasswordAuthVersion
|
|
}
|
|
|
|
if buf[1] == 0 {
|
|
return nil, ErrBadRequest
|
|
}
|
|
|
|
usernameBuf := make([]byte, int(buf[1])+1)
|
|
if _, err := io.ReadFull(r, usernameBuf); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var passwordBuf []byte
|
|
if usernameBuf[int(buf[1])] != 0 {
|
|
passwordBuf = make([]byte, int(usernameBuf[int(buf[1])]))
|
|
if _, err := io.ReadFull(r, passwordBuf); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return &PasswordNegotiationRequest{
|
|
UsernameLen: buf[1],
|
|
Username: string(usernameBuf[:int(buf[1])]),
|
|
PasswordLen: usernameBuf[int(buf[1])],
|
|
Password: string(passwordBuf),
|
|
}, nil
|
|
}
|
|
|
|
// WriteTo writes password negotiation request packet
|
|
func (s *PasswordNegotiationRequest) WriteTo(w io.Writer) (int64, error) {
|
|
buf := []byte{PasswordVersion, s.UsernameLen}
|
|
buf = append(buf, []byte(s.Username)...)
|
|
buf = append(buf, s.PasswordLen)
|
|
buf = append(buf, []byte(s.Password)...)
|
|
|
|
n, err := w.Write(buf)
|
|
if err != nil {
|
|
return int64(n), err
|
|
}
|
|
|
|
return int64(n), nil
|
|
}
|
|
|
|
// PasswordNegotiationReply is the password negotiation reply packet
|
|
type PasswordNegotiationReply struct {
|
|
Status PasswordStatus
|
|
}
|
|
|
|
// NewPasswordNegotiationReply returns password negotiation reply packet
|
|
func NewPasswordNegotiationReply(status PasswordStatus) *PasswordNegotiationReply {
|
|
return &PasswordNegotiationReply{
|
|
Status: status,
|
|
}
|
|
}
|
|
|
|
// NewPasswordNegotiationReplyFrom reads password negotiation reply packet from reader
|
|
func NewPasswordNegotiationReplyFrom(r io.Reader) (*PasswordNegotiationReply, error) {
|
|
buf := make([]byte, 2)
|
|
if _, err := io.ReadFull(r, buf); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if buf[0] != PasswordVersion {
|
|
return nil, ErrPasswordAuthVersion
|
|
}
|
|
|
|
rep := &PasswordNegotiationReply{
|
|
Status: PasswordStatus(buf[1]),
|
|
}
|
|
|
|
return rep, nil
|
|
}
|
|
|
|
// WriteTo writes password negotiation reply packet
|
|
func (s *PasswordNegotiationReply) WriteTo(w io.Writer) (int64, error) {
|
|
n, err := w.Write([]byte{PasswordVersion, byte(s.Status)})
|
|
if err != nil {
|
|
return int64(n), err
|
|
}
|
|
|
|
return int64(n), nil
|
|
}
|