diff --git a/transport/socks5/socks5.go b/transport/socks5/socks5.go index 1b4c8c99..899abebb 100644 --- a/transport/socks5/socks5.go +++ b/transport/socks5/socks5.go @@ -195,17 +195,29 @@ func ClientHandshake(rw io.ReadWriter, addr Addr, command Command, user *User) ( return nil, errors.New("auth required") } - authMsgLen := 1 + 1 + len(user.Username) + 1 + len(user.Password) - if authMsgLen > MaxAuthLen { - return nil, errors.New("auth message too long") + uLen := len(user.Username) + pLen := len(user.Password) + + // Both ULEN and PLEN are limited to the range [1, 255]. + switch { + case uLen == 0: + return nil, errors.New("auth user missing") + case uLen > MaxAuthLen: + return nil, errors.New("auth user too long") + case pLen == 0: + return nil, errors.New("auth password missing") + case pLen > MaxAuthLen: + return nil, errors.New("auth password too long") } + authMsgLen := 1 + 1 + uLen + 1 + pLen + // password protocol version authMsg := bytes.NewBuffer(make([]byte, 0, authMsgLen)) authMsg.WriteByte(0x01 /* VER */) - authMsg.WriteByte(byte(len(user.Username)) /* ULEN */) + authMsg.WriteByte(byte(uLen) /* ULEN */) authMsg.WriteString(user.Username /* UNAME */) - authMsg.WriteByte(byte(len(user.Password)) /* PLEN */) + authMsg.WriteByte(byte(pLen) /* PLEN */) authMsg.WriteString(user.Password /* PASSWD */) if _, err := rw.Write(authMsg.Bytes()); err != nil {