commit b45bf02c7559eecebf0924e507a4b2137e7042e6
Author: Mike Perry <[email protected]>
Date:   Thu Mar 26 23:29:39 2015 -0700

    Revert "Use a SOCKS5 listener instead of a SOCKS4a for goptlib."
    
    This reverts commit 9d26e0009fc6a8e89a48db2a976097459f14f45e, which broke 
the
    build.
---
 .../linux/gitian-pluggable-transports.yml          |    6 -
 .../mac/gitian-pluggable-transports.yml            |    6 -
 .../windows/gitian-pluggable-transports.yml        |    6 -
 gitian/patches/bug12535.patch                      | 1032 --------------------
 4 files changed, 1050 deletions(-)

diff --git a/gitian/descriptors/linux/gitian-pluggable-transports.yml 
b/gitian/descriptors/linux/gitian-pluggable-transports.yml
index 6adf16c..1ae9c0c 100644
--- a/gitian/descriptors/linux/gitian-pluggable-transports.yml
+++ b/gitian/descriptors/linux/gitian-pluggable-transports.yml
@@ -57,7 +57,6 @@ files:
 - "openssl-linux32-utils.zip"
 - "openssl-linux64-utils.zip"
 - "go.net.tar.bz2"
-- "bug12535.patch"
 script: |
   INSTDIR="$HOME/install"
   PTDIR="$INSTDIR/Tor/PluggableTransports"
@@ -209,11 +208,6 @@ script: |
 
   # Building goptlib
   cd goptlib
-  git update-index --refresh -q
-  export GIT_COMMITTER_NAME="nobody"
-  export GIT_COMMITTER_EMAIL="nobody@localhost"
-  export GIT_COMMITTER_DATE="$REFERENCE_DATETIME"
-  git am ~/build/bug12535.patch
   find -type f | xargs touch --date="$REFERENCE_DATETIME"
   mkdir -p "$GOPATH/src/git.torproject.org/pluggable-transports"
   ln -sf "$PWD" 
"$GOPATH/src/git.torproject.org/pluggable-transports/goptlib.git"
diff --git a/gitian/descriptors/mac/gitian-pluggable-transports.yml 
b/gitian/descriptors/mac/gitian-pluggable-transports.yml
index d72ab44..e2693e1 100644
--- a/gitian/descriptors/mac/gitian-pluggable-transports.yml
+++ b/gitian/descriptors/mac/gitian-pluggable-transports.yml
@@ -53,7 +53,6 @@ files:
 - 
"multiarch-darwin11-cctools127.2-gcc42-5666.3-llvmgcc42-2336.1-Linux-120724.tar.xz"
 - "dzip.sh"
 - "go.net.tar.bz2"
-- "bug12535.patch"
 - "gmp-mac64-utils.zip"
 - "openssl-mac64-utils.zip"
 script: |
@@ -235,11 +234,6 @@ script: |
 
   # Building goptlib
   cd goptlib
-  git update-index --refresh -q
-  export GIT_COMMITTER_NAME="nobody"
-  export GIT_COMMITTER_EMAIL="nobody@localhost"
-  export GIT_COMMITTER_DATE="$REFERENCE_DATETIME"
-  git am ~/build/bug12535.patch
   find -type f | xargs touch --date="$REFERENCE_DATETIME"
   mkdir -p "$GOPATH/src/git.torproject.org/pluggable-transports"
   ln -sf "$PWD" 
"$GOPATH/src/git.torproject.org/pluggable-transports/goptlib.git"
diff --git a/gitian/descriptors/windows/gitian-pluggable-transports.yml 
b/gitian/descriptors/windows/gitian-pluggable-transports.yml
index 0b0b5db..0f5ec84 100644
--- a/gitian/descriptors/windows/gitian-pluggable-transports.yml
+++ b/gitian/descriptors/windows/gitian-pluggable-transports.yml
@@ -60,7 +60,6 @@ files:
 - "gmp-win32-utils.zip"
 - "gcclibs-win32-utils.zip"
 - "go.net.tar.bz2"
-- "bug12535.patch"
 script: |
   # Set the timestamp on every .pyc file in a zip file, and re-dzip the zip 
file.
   function py2exe_zip_timestomp {
@@ -311,11 +310,6 @@ script: |
 
   # Building goptlib
   cd goptlib
-  git update-index --refresh -q
-  export GIT_COMMITTER_NAME="nobody"
-  export GIT_COMMITTER_EMAIL="nobody@localhost"
-  export GIT_COMMITTER_DATE="$REFERENCE_DATETIME"
-  git am ~/build/bug12535.patch
   find -type f | xargs touch --date="$REFERENCE_DATETIME"
   mkdir -p "$GOPATH/src/git.torproject.org/pluggable-transports"
   ln -sf "$PWD" 
"$GOPATH/src/git.torproject.org/pluggable-transports/goptlib.git"
diff --git a/gitian/patches/bug12535.patch b/gitian/patches/bug12535.patch
deleted file mode 100644
index dae6818..0000000
--- a/gitian/patches/bug12535.patch
+++ /dev/null
@@ -1,1032 +0,0 @@
-From 743ae58b6c33dda837ffb1267867f564597dd59d Mon Sep 17 00:00:00 2001
-From: Yawning Angel <[email protected]>
-Date: Mon, 8 Sep 2014 18:24:08 +0000
-Subject: [PATCH] Replace the SOCKS4a listener with a SOCKS5 listener.
-
-The change is designed to be transparent to calling code and implements
-enough of RFC1928/RFC1929 such that pluggable transports can be written.
-
-Notable incompatibilities/limitations:
- * GSSAPI authentication is not supported.
- * BND.ADDR/BND.PORT in responses is always "0.0.0.0:0" instead of the
-   bound address/port of the outgoing socket.
- * RFC1929 Username/Password authentication is setup exclusively for
-   pluggable transport arguments.
- * The BIND and UDP ASSOCIATE commands are not supported.
----
- pt.go         |   5 +-
- socks.go      | 386 +++++++++++++++++++++++++++++++++++++-------
- socks_test.go | 510 +++++++++++++++++++++++++++++++++++++++++-----------------
- 3 files changed, 685 insertions(+), 216 deletions(-)
-
-diff --git a/pt.go b/pt.go
-index 62dfc38..47f8273 100644
---- a/pt.go
-+++ b/pt.go
-@@ -119,10 +119,11 @@
- // Extended ORPort Authentication:
- // 
https://gitweb.torproject.org/torspec.git/blob/HEAD:/proposals/217-ext-orport-auth.txt.
- //
--// The package implements a SOCKS4a server sufficient for a Tor client 
transport
-+// The package implements a SOCKS5 server sufficient for a Tor client 
transport
- // plugin.
- //
--// http://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4.protocol
-+// https://www.ietf.org/rfc/rfc1928.txt
-+// https://www.ietf.org/rfc/rfc1929.txt
- package pt
- 
- import (
-diff --git a/socks.go b/socks.go
-index 6ad6542..e4488e8 100644
---- a/socks.go
-+++ b/socks.go
-@@ -9,11 +9,40 @@ import (
- )
- 
- const (
--      socksVersion         = 0x04
--      socksCmdConnect      = 0x01
--      socksResponseVersion = 0x00
--      socksRequestGranted  = 0x5a
--      socksRequestRejected = 0x5b
-+      socksVersion = 0x05
-+
-+      socksAuthNoneRequired        = 0x00
-+      socksAuthUsernamePassword    = 0x02
-+      socksAuthNoAcceptableMethods = 0xff
-+
-+      socksCmdConnect = 0x01
-+      socksRsv        = 0x00
-+
-+      socksAtypeV4         = 0x01
-+      socksAtypeDomainName = 0x03
-+      socksAtypeV6         = 0x04
-+
-+      socksAuthRFC1929Ver     = 0x01
-+      socksAuthRFC1929Success = 0x00
-+      socksAuthRFC1929Fail    = 0x01
-+
-+      socksRepSucceeded = 0x00
-+      // "general SOCKS server failure"
-+      SocksRepGeneralFailure = 0x01
-+      // "connection not allowed by ruleset"
-+      SocksRepConnectionNotAllowed = 0x02
-+      // "Network unreachable"
-+      SocksRepNetworkUnreachable = 0x03
-+      // "Host unreachable"
-+      SocksRepHostUnreachable = 0x04
-+      // "Connection refused"
-+      SocksRepConnectionRefused = 0x05
-+      // "TTL expired"
-+      SocksRepTTLExpired = 0x06
-+      // "Command not supported"
-+      SocksRepCommandNotSupported = 0x07
-+      // "Address type not supported"
-+      SocksRepAddressNotSupported = 0x08
- )
- 
- // Put a sanity timeout on how long we wait for a SOCKS request.
-@@ -25,6 +54,8 @@ type SocksRequest struct {
-       Target string
-       // The userid string sent by the client.
-       Username string
-+      // The password string sent by the client.
-+      Password string
-       // The parsed contents of Username as a key–value mapping.
-       Args Args
- }
-@@ -36,15 +67,23 @@ type SocksConn struct {
- }
- 
- // Send a message to the proxy client that access to the given address is
--// granted. If the IP field inside addr is not an IPv4 address, the IP portion
--// of the response will be four zero bytes.
-+// granted. Addr is ignored, and "0.0.0.0:0" is always sent back for
-+// BND.ADDR/BND.PORT in the SOCKS response.
- func (conn *SocksConn) Grant(addr *net.TCPAddr) error {
--      return sendSocks4aResponseGranted(conn, addr)
-+      return sendSocks5ResponseGranted(conn)
- }
- 
--// Send a message to the proxy client that access was rejected or failed.
-+// Send a message to the proxy client that access was rejected or failed.  
This
-+// sends back a "General Failure" error code.  RejectReason should be used if
-+// more specific error reporting is desired.
- func (conn *SocksConn) Reject() error {
--      return sendSocks4aResponseRejected(conn)
-+      return conn.RejectReason(SocksRepGeneralFailure)
-+}
-+
-+// Send a message to the proxy client that access was rejected, with the
-+// specific error code indicating the reason behind the rejection.
-+func (conn *SocksConn) RejectReason(reason byte) error {
-+      return sendSocks5ResponseRejected(conn, reason)
- }
- 
- // SocksListener wraps a net.Listener in order to read a SOCKS request on 
Accept.
-@@ -138,7 +177,7 @@ func (ln *SocksListener) AcceptSocks() (*SocksConn, error) 
{
-       if err != nil {
-               return nil, err
-       }
--      conn.Req, err = readSocks4aConnect(conn)
-+      conn.Req, err = socks5Handshake(conn)
-       if err != nil {
-               conn.Close()
-               return nil, err
-@@ -150,58 +189,251 @@ func (ln *SocksListener) AcceptSocks() (*SocksConn, 
error) {
-       return conn, nil
- }
- 
--// Returns "socks4", suitable to be included in a call to Cmethod.
-+// Returns "socks5", suitable to be included in a call to Cmethod.
- func (ln *SocksListener) Version() string {
--      return "socks4"
-+      return "socks5"
- }
- 
--// Read a SOCKS4a connect request. Returns a SocksRequest.
--func readSocks4aConnect(s io.Reader) (req SocksRequest, err error) {
--      r := bufio.NewReader(s)
-+// socks5handshake conducts the SOCKS5 handshake up to the point where the
-+// client command is read and the proxy must open the outgoing connection.
-+// Returns a SocksRequest.
-+func socks5Handshake(s io.ReadWriter) (req SocksRequest, err error) {
-+      rw := bufio.NewReadWriter(bufio.NewReader(s), bufio.NewWriter(s))
- 
--      var h [8]byte
--      _, err = io.ReadFull(r, h[:])
--      if err != nil {
-+      // Negotiate the authentication method.
-+      var method byte
-+      if method, err = socksNegotiateAuth(rw); err != nil {
-               return
-       }
--      if h[0] != socksVersion {
--              err = fmt.Errorf("SOCKS header had version 0x%02x, not 0x%02x", 
h[0], socksVersion)
-+
-+      // Authenticate the client.
-+      if err = socksAuthenticate(rw, method, &req); err != nil {
-               return
-       }
--      if h[1] != socksCmdConnect {
--              err = fmt.Errorf("SOCKS header had command 0x%02x, not 0x%02x", 
h[1], socksCmdConnect)
-+
-+      // Read the command.
-+      err = socksReadCommand(rw, &req)
-+      return
-+}
-+
-+// socksNegotiateAuth negotiates the authentication method and returns the
-+// selected method as a byte.  On negotiation failures an error is returned.
-+func socksNegotiateAuth(rw *bufio.ReadWriter) (method byte, err error) {
-+      // Validate the version.
-+      if err = socksReadByteVerify(rw, "version", socksVersion); err != nil {
-               return
-       }
- 
--      var usernameBytes []byte
--      usernameBytes, err = r.ReadBytes('\x00')
--      if err != nil {
-+      // Read the number of methods.
-+      var nmethods byte
-+      if nmethods, err = socksReadByte(rw); err != nil {
-               return
-       }
--      req.Username = string(usernameBytes[:len(usernameBytes)-1])
- 
--      req.Args, err = parseClientParameters(req.Username)
--      if err != nil {
-+      // Read the methods.
-+      var methods []byte
-+      if methods, err = socksReadBytes(rw, int(nmethods)); err != nil {
-               return
-       }
- 
--      var port int
--      var host string
-+      // Pick the most "suitable" method.
-+      method = socksAuthNoAcceptableMethods
-+      for _, m := range methods {
-+              switch m {
-+              case socksAuthNoneRequired:
-+                      // Pick Username/Password over None if the client 
happens to
-+                      // send both.
-+                      if method == socksAuthNoAcceptableMethods {
-+                              method = m
-+                      }
-+
-+              case socksAuthUsernamePassword:
-+                      method = m
-+              }
-+      }
-+
-+      // Send the negotiated method.
-+      var msg [2]byte
-+      msg[0] = socksVersion
-+      msg[1] = method
-+      if _, err = rw.Writer.Write(msg[:]); err != nil {
-+              return
-+      }
-+
-+      if err = socksFlushBuffers(rw); err != nil {
-+              return
-+      }
-+      return
-+}
-+
-+// socksAuthenticate authenticates the client via the chosen authentication
-+// mechanism.
-+func socksAuthenticate(rw *bufio.ReadWriter, method byte, req *SocksRequest) 
(err error) {
-+      switch method {
-+      case socksAuthNoneRequired:
-+              // Straight into reading the connect.
- 
--      port = int(h[2])<<8 | int(h[3])<<0
--      if h[4] == 0 && h[5] == 0 && h[6] == 0 && h[7] != 0 {
--              var hostBytes []byte
--              hostBytes, err = r.ReadBytes('\x00')
--              if err != nil {
-+      case socksAuthUsernamePassword:
-+              if err = socksAuthRFC1929(rw, req); err != nil {
-                       return
-               }
--              host = string(hostBytes[:len(hostBytes)-1])
-+
-+      case socksAuthNoAcceptableMethods:
-+              err = fmt.Errorf("SOCKS method select had no compatible 
methods")
-+              return
-+
-+      default:
-+              err = fmt.Errorf("SOCKS method select picked a unsupported 
method 0x%02x", method)
-+              return
-+      }
-+
-+      if err = socksFlushBuffers(rw); err != nil {
-+              return
-+      }
-+      return
-+}
-+
-+// socksAuthRFC1929 authenticates the client via RFC 1929 username/password
-+// auth.  As a design decision any valid username/password is accepted as this
-+// field is primarily used as an out-of-band argument passing mechanism for
-+// pluggable transports.
-+func socksAuthRFC1929(rw *bufio.ReadWriter, req *SocksRequest) (err error) {
-+      sendErrResp := func() {
-+              // Swallow the write/flush error here, we are going to close the
-+              // connection and the original failure is more useful.
-+              resp := []byte{socksAuthRFC1929Ver, socksAuthRFC1929Fail}
-+              rw.Write(resp[:])
-+              socksFlushBuffers(rw)
-+      }
-+
-+      // Validate the fixed parts of the command message.
-+      if err = socksReadByteVerify(rw, "auth version", socksAuthRFC1929Ver); 
err != nil {
-+              sendErrResp()
-+              return
-+      }
-+
-+      // Read the username.
-+      var ulen byte
-+      if ulen, err = socksReadByte(rw); err != nil {
-+              return
-+      }
-+      if ulen < 1 {
-+              sendErrResp()
-+              err = fmt.Errorf("RFC1929 username with 0 length")
-+              return
-+      }
-+      var uname []byte
-+      if uname, err = socksReadBytes(rw, int(ulen)); err != nil {
-+              return
-+      }
-+      req.Username = string(uname)
-+
-+      // Read the password.
-+      var plen byte
-+      if plen, err = socksReadByte(rw); err != nil {
-+              return
-+      }
-+      if plen < 1 {
-+              sendErrResp()
-+              err = fmt.Errorf("RFC1929 password with 0 length")
-+              return
-+      }
-+      var passwd []byte
-+      if passwd, err = socksReadBytes(rw, int(plen)); err != nil {
-+              return
-+      }
-+      if !(plen == 1 && passwd[0] == 0x00) {
-+              // tor will set the password to 'NUL' if there are no arguments.
-+              req.Password = string(passwd)
-+      }
-+
-+      // Mash the username/password together and parse it as a pluggable
-+      // transport argument string.
-+      if req.Args, err = parseClientParameters(req.Username + req.Password); 
err != nil {
-+              sendErrResp()
-       } else {
--              host = net.IPv4(h[4], h[5], h[6], h[7]).String()
-+              resp := []byte{socksAuthRFC1929Ver, socksAuthRFC1929Success}
-+              _, err = rw.Write(resp[:])
-+      }
-+      return
-+}
-+
-+// socksReadCommand reads a SOCKS5 client command and parses out the relevant
-+// fields into a SocksRequest.  Only CMD_CONNECT is supported.
-+func socksReadCommand(rw *bufio.ReadWriter, req *SocksRequest) (err error) {
-+      sendErrResp := func(reason byte) {
-+              // Swallow errors that occur when writing/flushing the response,
-+              // connection will be closed anyway.
-+              sendSocks5ResponseRejected(rw, reason)
-+              socksFlushBuffers(rw)
-+      }
-+
-+      // Validate the fixed parts of the command message.
-+      if err = socksReadByteVerify(rw, "version", socksVersion); err != nil {
-+              sendErrResp(SocksRepGeneralFailure)
-+              return
-+      }
-+      if err = socksReadByteVerify(rw, "command", socksCmdConnect); err != 
nil {
-+              sendErrResp(SocksRepCommandNotSupported)
-+              return
-+      }
-+      if err = socksReadByteVerify(rw, "reserved", socksRsv); err != nil {
-+              sendErrResp(SocksRepGeneralFailure)
-+              return
-+      }
-+
-+      // Read the destination address/port.
-+      // XXX: This should probably eventually send socks 5 error messages 
instead
-+      // of rudely closing connections on invalid addresses.
-+      var atype byte
-+      if atype, err = socksReadByte(rw); err != nil {
-+              return
-+      }
-+      var host string
-+      switch atype {
-+      case socksAtypeV4:
-+              var addr []byte
-+              if addr, err = socksReadBytes(rw, net.IPv4len); err != nil {
-+                      return
-+              }
-+              host = net.IPv4(addr[0], addr[1], addr[2], addr[3]).String()
-+
-+      case socksAtypeDomainName:
-+              var alen byte
-+              if alen, err = socksReadByte(rw); err != nil {
-+                      return
-+              }
-+              if alen == 0 {
-+                      err = fmt.Errorf("SOCKS request had domain name with 0 
length")
-+                      return
-+              }
-+              var addr []byte
-+              if addr, err = socksReadBytes(rw, int(alen)); err != nil {
-+                      return
-+              }
-+              host = string(addr)
-+
-+      case socksAtypeV6:
-+              var rawAddr []byte
-+              if rawAddr, err = socksReadBytes(rw, net.IPv6len); err != nil {
-+                      return
-+              }
-+              addr := make(net.IP, net.IPv6len)
-+              copy(addr[:], rawAddr[:])
-+              host = fmt.Sprintf("[%s]", addr.String())
-+
-+      default:
-+              sendErrResp(SocksRepAddressNotSupported)
-+              err = fmt.Errorf("SOCKS request had unsupported address type 
0x%02x", atype)
-+              return
-       }
-+      var rawPort []byte
-+      if rawPort, err = socksReadBytes(rw, 2); err != nil {
-+              return
-+      }
-+      port := int(rawPort[0])<<8 | int(rawPort[1])<<0
- 
--      if r.Buffered() != 0 {
--              err = fmt.Errorf("%d bytes left after SOCKS header", 
r.Buffered())
-+      if err = socksFlushBuffers(rw); err != nil {
-               return
-       }
- 
-@@ -209,34 +441,64 @@ func readSocks4aConnect(s io.Reader) (req SocksRequest, 
err error) {
-       return
- }
- 
--// Send a SOCKS4a response with the given code and address. If the IP field
--// inside addr is not an IPv4 address, the IP portion of the response will be
--// four zero bytes.
--func sendSocks4aResponse(w io.Writer, code byte, addr *net.TCPAddr) error {
--      var resp [8]byte
--      resp[0] = socksResponseVersion
-+// Send a SOCKS5 response with the given code. BND.ADDR/BND.PORT is always the
-+// IPv4 address/port "0.0.0.0:0".
-+func sendSocks5Response(w io.Writer, code byte) error {
-+      resp := make([]byte, 4+4+2)
-+      resp[0] = socksVersion
-       resp[1] = code
--      resp[2] = byte((addr.Port >> 8) & 0xff)
--      resp[3] = byte((addr.Port >> 0) & 0xff)
--      ipv4 := addr.IP.To4()
--      if ipv4 != nil {
--              resp[4] = ipv4[0]
--              resp[5] = ipv4[1]
--              resp[6] = ipv4[2]
--              resp[7] = ipv4[3]
--      }
-+      resp[2] = socksRsv
-+      resp[3] = socksAtypeV4
-+
-+      // BND.ADDR/BND.PORT should be the address and port that the outgoing
-+      // connection is bound to on the proxy, but Tor does not use this
-+      // information, so all zeroes are sent.
-+
-       _, err := w.Write(resp[:])
-       return err
- }
- 
--var emptyAddr = net.TCPAddr{IP: net.IPv4(0, 0, 0, 0), Port: 0}
-+// Send a SOCKS5 response code 0x00.
-+func sendSocks5ResponseGranted(w io.Writer) error {
-+      return sendSocks5Response(w, socksRepSucceeded)
-+}
- 
--// Send a SOCKS4a response code 0x5a.
--func sendSocks4aResponseGranted(w io.Writer, addr *net.TCPAddr) error {
--      return sendSocks4aResponse(w, socksRequestGranted, addr)
-+// Send a SOCKS5 response with the provided failure reason.
-+func sendSocks5ResponseRejected(w io.Writer, reason byte) error {
-+      return sendSocks5Response(w, reason)
- }
- 
--// Send a SOCKS4a response code 0x5b (with an all-zero address).
--func sendSocks4aResponseRejected(w io.Writer) error {
--      return sendSocks4aResponse(w, socksRequestRejected, &emptyAddr)
-+func socksFlushBuffers(rw *bufio.ReadWriter) error {
-+      if err := rw.Writer.Flush(); err != nil {
-+              return err
-+      }
-+      if rw.Reader.Buffered() > 0 {
-+              return fmt.Errorf("%d bytes left after SOCKS message", 
rw.Reader.Buffered())
-+      }
-+      return nil
-+}
-+
-+func socksReadByte(rw *bufio.ReadWriter) (byte, error) {
-+      return rw.Reader.ReadByte()
-+}
-+
-+func socksReadBytes(rw *bufio.ReadWriter, n int) ([]byte, error) {
-+      ret := make([]byte, n)
-+      if _, err := io.ReadFull(rw.Reader, ret); err != nil {
-+              return nil, err
-+      }
-+      return ret, nil
- }
-+
-+func socksReadByteVerify(rw *bufio.ReadWriter, descr string, expected byte) 
error {
-+      val, err := socksReadByte(rw)
-+      if err != nil {
-+              return err
-+      }
-+      if val != expected {
-+              return fmt.Errorf("SOCKS message field %s was 0x%02x, not 
0x%02x", descr, val, expected)
-+      }
-+      return nil
-+}
-+
-+var _ net.Listener = (*SocksListener)(nil)
-diff --git a/socks_test.go b/socks_test.go
-index 18d141a..aa27d4c 100644
---- a/socks_test.go
-+++ b/socks_test.go
-@@ -1,162 +1,368 @@
- package pt
- 
- import (
-+      "bufio"
-       "bytes"
-+      "encoding/hex"
-+      "io"
-       "net"
-       "testing"
- )
- 
--func TestReadSocks4aConnect(t *testing.T) {
--      badTests := [...][]byte{
--              []byte(""),
--              // missing userid
--              []byte("\x04\x01\x12\x34\x01\x02\x03\x04"),
--              // missing \x00 after userid
--              []byte("\x04\x01\x12\x34\x01\x02\x03\x04key=value"),
--              // missing hostname
--              []byte("\x04\x01\x12\x34\x00\x00\x00\x01key=value\x00"),
--              // missing \x00 after hostname
--              []byte("\x04\x01\x12\x34\x00\x00\x00\x01key=value\x00hostname"),
--              // bad name–value mapping
--              
[]byte("\x04\x01\x12\x34\x00\x00\x00\x01userid\x00hostname\x00"),
--              // bad version number
--              []byte("\x03\x01\x12\x34\x01\x02\x03\x04\x00"),
--              // BIND request
--              []byte("\x04\x02\x12\x34\x01\x02\x03\x04\x00"),
--              // SOCKS5
--              []byte("\x05\x01\x00"),
--      }
--      ipTests := [...]struct {
--              input  []byte
--              addr   net.TCPAddr
--              userid string
--      }{
--              {
--                      []byte("\x04\x01\x12\x34\x01\x02\x03\x04key=value\x00"),
--                      net.TCPAddr{IP: net.ParseIP("1.2.3.4"), Port: 0x1234},
--                      "key=value",
--              },
--              {
--                      []byte("\x04\x01\x12\x34\x01\x02\x03\x04\x00"),
--                      net.TCPAddr{IP: net.ParseIP("1.2.3.4"), Port: 0x1234},
--                      "",
--              },
--      }
--      hostnameTests := [...]struct {
--              input  []byte
--              target string
--              userid string
--      }{
--              {
--                      
[]byte("\x04\x01\x12\x34\x00\x00\x00\x01key=value\x00hostname\x00"),
--                      "hostname:4660",
--                      "key=value",
--              },
--              {
--                      
[]byte("\x04\x01\x12\x34\x00\x00\x00\x01\x00hostname\x00"),
--                      "hostname:4660",
--                      "",
--              },
--              {
--                      
[]byte("\x04\x01\x12\x34\x00\x00\x00\x01key=value\x00\x00"),
--                      ":4660",
--                      "key=value",
--              },
--              {
--                      []byte("\x04\x01\x12\x34\x00\x00\x00\x01\x00\x00"),
--                      ":4660",
--                      "",
--              },
--      }
--
--      for _, input := range badTests {
--              var buf bytes.Buffer
--              buf.Write(input)
--              _, err := readSocks4aConnect(&buf)
--              if err == nil {
--                      t.Errorf("%q unexpectedly succeeded", input)
--              }
--      }
--
--      for _, test := range ipTests {
--              var buf bytes.Buffer
--              buf.Write(test.input)
--              req, err := readSocks4aConnect(&buf)
--              if err != nil {
--                      t.Errorf("%q unexpectedly returned an error: %s", 
test.input, err)
--              }
--              addr, err := net.ResolveTCPAddr("tcp", req.Target)
--              if err != nil {
--                      t.Errorf("%q → target %q: cannot resolve: %s", 
test.input,
--                              req.Target, err)
--              }
--              if !tcpAddrsEqual(addr, &test.addr) {
--                      t.Errorf("%q → address %s (expected %s)", test.input,
--                              req.Target, test.addr.String())
--              }
--              if req.Username != test.userid {
--                      t.Errorf("%q → username %q (expected %q)", test.input,
--                              req.Username, test.userid)
--              }
--              if req.Args == nil {
--                      t.Errorf("%q → unexpected nil Args from username %q", 
test.input, req.Username)
--              }
--      }
--
--      for _, test := range hostnameTests {
--              var buf bytes.Buffer
--              buf.Write(test.input)
--              req, err := readSocks4aConnect(&buf)
--              if err != nil {
--                      t.Errorf("%q unexpectedly returned an error: %s", 
test.input, err)
--              }
--              if req.Target != test.target {
--                      t.Errorf("%q → target %q (expected %q)", test.input,
--                              req.Target, test.target)
--              }
--              if req.Username != test.userid {
--                      t.Errorf("%q → username %q (expected %q)", test.input,
--                              req.Username, test.userid)
--              }
--              if req.Args == nil {
--                      t.Errorf("%q → unexpected nil Args from username %q", 
test.input, req.Username)
--              }
--      }
--}
--
--func TestSendSocks4aResponse(t *testing.T) {
--      tests := [...]struct {
--              code     byte
--              addr     net.TCPAddr
--              expected []byte
--      }{
--              {
--                      socksRequestGranted,
--                      net.TCPAddr{IP: net.ParseIP("1.2.3.4"), Port: 0x1234},
--                      []byte("\x00\x5a\x12\x34\x01\x02\x03\x04"),
--              },
--              {
--                      socksRequestRejected,
--                      net.TCPAddr{IP: net.ParseIP("1:2::3:4"), Port: 0x1234},
--                      []byte("\x00\x5b\x12\x34\x00\x00\x00\x00"),
--              },
--      }
--
--      for _, test := range tests {
--              var buf bytes.Buffer
--              err := sendSocks4aResponse(&buf, test.code, &test.addr)
--              if err != nil {
--                      t.Errorf("0x%02x %s unexpectedly returned an error: 
%s", test.code, &test.addr, err)
--              }
--              p := make([]byte, 1024)
--              n, err := buf.Read(p)
--              if err != nil {
--                      t.Fatal(err)
--              }
--              output := p[:n]
--              if !bytes.Equal(output, test.expected) {
--                      t.Errorf("0x%02x %s → %v (expected %v)",
--                              test.code, &test.addr, output, test.expected)
--              }
-+// testReadWriter is a bytes.Buffer backed io.ReadWriter used for testing.  
The
-+// Read and Write routines are to be used by the component being tested.  Data
-+// can be written to and read back via the writeHex and readHex routines.
-+type testReadWriter struct {
-+      readBuf  bytes.Buffer
-+      writeBuf bytes.Buffer
-+}
-+
-+func (c *testReadWriter) Read(buf []byte) (n int, err error) {
-+      return c.readBuf.Read(buf)
-+}
-+
-+func (c *testReadWriter) Write(buf []byte) (n int, err error) {
-+      return c.writeBuf.Write(buf)
-+}
-+
-+func (c *testReadWriter) writeHex(str string) (n int, err error) {
-+      var buf []byte
-+      if buf, err = hex.DecodeString(str); err != nil {
-+              return
-+      }
-+      return c.readBuf.Write(buf)
-+}
-+
-+func (c *testReadWriter) readHex() string {
-+      return hex.EncodeToString(c.writeBuf.Bytes())
-+}
-+
-+func (c *testReadWriter) toBufio() *bufio.ReadWriter {
-+      return bufio.NewReadWriter(bufio.NewReader(c), bufio.NewWriter(c))
-+}
-+
-+func (c *testReadWriter) reset() {
-+      c.readBuf.Reset()
-+      c.writeBuf.Reset()
-+}
-+
-+// TestAuthInvalidVersion tests auth negotiation with an invalid version.
-+func TestAuthInvalidVersion(t *testing.T) {
-+      c := new(testReadWriter)
-+
-+      // VER = 03, NMETHODS = 01, METHODS = [00]
-+      c.writeHex("030100")
-+      if _, err := socksNegotiateAuth(c.toBufio()); err == nil {
-+              t.Error("socksNegotiateAuth(InvalidVersion) succeded")
-+      }
-+}
-+
-+// TestAuthInvalidNMethods tests auth negotiaton with no methods.
-+func TestAuthInvalidNMethods(t *testing.T) {
-+      c := new(testReadWriter)
-+      var err error
-+      var method byte
-+
-+      // VER = 05, NMETHODS = 00
-+      c.writeHex("0500")
-+      if method, err = socksNegotiateAuth(c.toBufio()); err != nil {
-+              t.Error("socksNegotiateAuth(No Methods) failed:", err)
-+      }
-+      if method != socksAuthNoAcceptableMethods {
-+              t.Error("socksNegotiateAuth(No Methods) picked unexpected 
method:", method)
-+      }
-+      if msg := c.readHex(); msg != "05ff" {
-+              t.Error("socksNegotiateAuth(No Methods) invalid response:", msg)
-+      }
-+}
-+
-+// TestAuthNoneRequired tests auth negotiaton with NO AUTHENTICATION REQUIRED.
-+func TestAuthNoneRequired(t *testing.T) {
-+      c := new(testReadWriter)
-+      var err error
-+      var method byte
-+
-+      // VER = 05, NMETHODS = 01, METHODS = [00]
-+      c.writeHex("050100")
-+      if method, err = socksNegotiateAuth(c.toBufio()); err != nil {
-+              t.Error("socksNegotiateAuth(None) failed:", err)
-+      }
-+      if method != socksAuthNoneRequired {
-+              t.Error("socksNegotiateAuth(None) unexpected method:", method)
-+      }
-+      if msg := c.readHex(); msg != "0500" {
-+              t.Error("socksNegotiateAuth(None) invalid response:", msg)
-+      }
-+}
-+
-+// TestAuthUsernamePassword tests auth negotiation with USERNAME/PASSWORD.
-+func TestAuthUsernamePassword(t *testing.T) {
-+      c := new(testReadWriter)
-+      var err error
-+      var method byte
-+
-+      // VER = 05, NMETHODS = 01, METHODS = [02]
-+      c.writeHex("050102")
-+      if method, err = socksNegotiateAuth(c.toBufio()); err != nil {
-+              t.Error("socksNegotiateAuth(UsernamePassword) failed:", err)
-+      }
-+      if method != socksAuthUsernamePassword {
-+              t.Error("socksNegotiateAuth(UsernamePassword) unexpected 
method:", method)
-+      }
-+      if msg := c.readHex(); msg != "0502" {
-+              t.Error("socksNegotiateAuth(UsernamePassword) invalid 
response:", msg)
-       }
- }
-+
-+// TestAuthBoth tests auth negotiation containing both NO AUTHENTICATION
-+// REQUIRED and USERNAME/PASSWORD.
-+func TestAuthBoth(t *testing.T) {
-+      c := new(testReadWriter)
-+      var err error
-+      var method byte
-+
-+      // VER = 05, NMETHODS = 02, METHODS = [00, 02]
-+      c.writeHex("05020002")
-+      if method, err = socksNegotiateAuth(c.toBufio()); err != nil {
-+              t.Error("socksNegotiateAuth(Both) failed:", err)
-+      }
-+      if method != socksAuthUsernamePassword {
-+              t.Error("socksNegotiateAuth(Both) unexpected method:", method)
-+      }
-+      if msg := c.readHex(); msg != "0502" {
-+              t.Error("socksNegotiateAuth(Both) invalid response:", msg)
-+      }
-+}
-+
-+// TestAuthUnsupported tests auth negotiation with a unsupported method.
-+func TestAuthUnsupported(t *testing.T) {
-+      c := new(testReadWriter)
-+      var err error
-+      var method byte
-+
-+      // VER = 05, NMETHODS = 01, METHODS = [01] (GSSAPI)
-+      c.writeHex("050101")
-+      if method, err = socksNegotiateAuth(c.toBufio()); err != nil {
-+              t.Error("socksNegotiateAuth(Unknown) failed:", err)
-+      }
-+      if method != socksAuthNoAcceptableMethods {
-+              t.Error("socksNegotiateAuth(Unknown) picked unexpected 
method:", method)
-+      }
-+      if msg := c.readHex(); msg != "05ff" {
-+              t.Error("socksNegotiateAuth(Unknown) invalid response:", msg)
-+      }
-+}
-+
-+// TestAuthUnsupported2 tests auth negotiation with supported and unsupported
-+// methods.
-+func TestAuthUnsupported2(t *testing.T) {
-+      c := new(testReadWriter)
-+      var err error
-+      var method byte
-+
-+      // VER = 05, NMETHODS = 03, METHODS = [00,01,02]
-+      c.writeHex("0503000102")
-+      if method, err = socksNegotiateAuth(c.toBufio()); err != nil {
-+              t.Error("socksNegotiateAuth(Unknown2) failed:", err)
-+      }
-+      if method != socksAuthUsernamePassword {
-+              t.Error("socksNegotiateAuth(Unknown2) picked unexpected 
method:", method)
-+      }
-+      if msg := c.readHex(); msg != "0502" {
-+              t.Error("socksNegotiateAuth(Unknown2) invalid response:", msg)
-+      }
-+}
-+
-+// TestRFC1929InvalidVersion tests RFC1929 auth with an invalid version.
-+func TestRFC1929InvalidVersion(t *testing.T) {
-+      c := new(testReadWriter)
-+      var req SocksRequest
-+
-+      // VER = 03, ULEN = 5, UNAME = "ABCDE", PLEN = 5, PASSWD = "abcde"
-+      c.writeHex("03054142434445056162636465")
-+      if err := socksAuthenticate(c.toBufio(), socksAuthUsernamePassword, 
&req); err == nil {
-+              t.Error("socksAuthenticate(InvalidVersion) succeded")
-+      }
-+      if msg := c.readHex(); msg != "0101" {
-+              t.Error("socksAuthenticate(InvalidVersion) invalid response:", 
msg)
-+      }
-+}
-+
-+// TestRFC1929InvalidUlen tests RFC1929 auth with an invalid ULEN.
-+func TestRFC1929InvalidUlen(t *testing.T) {
-+      c := new(testReadWriter)
-+      var req SocksRequest
-+
-+      // VER = 01, ULEN = 0, UNAME = "", PLEN = 5, PASSWD = "abcde"
-+      c.writeHex("0100056162636465")
-+      if err := socksAuthenticate(c.toBufio(), socksAuthUsernamePassword, 
&req); err == nil {
-+              t.Error("socksAuthenticate(InvalidUlen) succeded")
-+      }
-+      if msg := c.readHex(); msg != "0101" {
-+              t.Error("socksAuthenticate(InvalidUlen) invalid response:", msg)
-+      }
-+}
-+
-+// TestRFC1929InvalidPlen tests RFC1929 auth with an invalid PLEN.
-+func TestRFC1929InvalidPlen(t *testing.T) {
-+      c := new(testReadWriter)
-+      var req SocksRequest
-+
-+      // VER = 01, ULEN = 5, UNAME = "ABCDE", PLEN = 0, PASSWD = ""
-+      c.writeHex("0105414243444500")
-+      if err := socksAuthenticate(c.toBufio(), socksAuthUsernamePassword, 
&req); err == nil {
-+              t.Error("socksAuthenticate(InvalidPlen) succeded")
-+      }
-+      if msg := c.readHex(); msg != "0101" {
-+              t.Error("socksAuthenticate(InvalidPlen) invalid response:", msg)
-+      }
-+}
-+
-+// TestRFC1929InvalidArgs tests RFC1929 auth with invalid pt args.
-+func TestRFC1929InvalidPTArgs(t *testing.T) {
-+      c := new(testReadWriter)
-+      var req SocksRequest
-+
-+      // VER = 01, ULEN = 5, UNAME = "ABCDE", PLEN = 5, PASSWD = "abcde"
-+      c.writeHex("01054142434445056162636465")
-+      if err := socksAuthenticate(c.toBufio(), socksAuthUsernamePassword, 
&req); err == nil {
-+              t.Error("socksAuthenticate(InvalidArgs) succeded")
-+      }
-+      if msg := c.readHex(); msg != "0101" {
-+              t.Error("socksAuthenticate(InvalidArgs) invalid response:", msg)
-+      }
-+}
-+
-+// TestRFC1929Success tests RFC1929 auth with valid pt args.
-+func TestRFC1929Success(t *testing.T) {
-+      c := new(testReadWriter)
-+      var req SocksRequest
-+
-+      // VER = 01, ULEN = 9, UNAME = "key=value", PLEN = 1, PASSWD = "\0"
-+      c.writeHex("01096b65793d76616c75650100")
-+      if err := socksAuthenticate(c.toBufio(), socksAuthUsernamePassword, 
&req); err != nil {
-+              t.Error("socksAuthenticate(Success) failed:", err)
-+      }
-+      if msg := c.readHex(); msg != "0100" {
-+              t.Error("socksAuthenticate(Success) invalid response:", msg)
-+      }
-+      v, ok := req.Args.Get("key")
-+      if v != "value" || !ok {
-+              t.Error("RFC1929 k,v parse failure:", v)
-+      }
-+}
-+
-+// TestRequestInvalidHdr tests SOCKS5 requests with invalid VER/CMD/RSV/ATYPE
-+func TestRequestInvalidHdr(t *testing.T) {
-+      c := new(testReadWriter)
-+      var req SocksRequest
-+
-+      // VER = 03, CMD = 01, RSV = 00, ATYPE = 01, DST.ADDR = 127.0.0.1, 
DST.PORT = 9050
-+      c.writeHex("030100017f000001235a")
-+      if err := socksReadCommand(c.toBufio(), &req); err == nil {
-+              t.Error("socksReadCommand(InvalidVer) succeded")
-+      }
-+      if msg := c.readHex(); msg != "05010001000000000000" {
-+              t.Error("socksReadCommand(InvalidVer) invalid response:", msg)
-+      }
-+      c.reset()
-+
-+      // VER = 05, CMD = 05, RSV = 00, ATYPE = 01, DST.ADDR = 127.0.0.1, 
DST.PORT = 9050
-+      c.writeHex("050500017f000001235a")
-+      if err := socksReadCommand(c.toBufio(), &req); err == nil {
-+              t.Error("socksReadCommand(InvalidCmd) succeded")
-+      }
-+      if msg := c.readHex(); msg != "05070001000000000000" {
-+              t.Error("socksReadCommand(InvalidCmd) invalid response:", msg)
-+      }
-+      c.reset()
-+
-+      // VER = 05, CMD = 01, RSV = 30, ATYPE = 01, DST.ADDR = 127.0.0.1, 
DST.PORT = 9050
-+      c.writeHex("050130017f000001235a")
-+      if err := socksReadCommand(c.toBufio(), &req); err == nil {
-+              t.Error("socksReadCommand(InvalidRsv) succeded")
-+      }
-+      if msg := c.readHex(); msg != "05010001000000000000" {
-+              t.Error("socksReadCommand(InvalidRsv) invalid response:", msg)
-+      }
-+      c.reset()
-+
-+      // VER = 05, CMD = 01, RSV = 01, ATYPE = 05, DST.ADDR = 127.0.0.1, 
DST.PORT = 9050
-+      c.writeHex("050100057f000001235a")
-+      if err := socksReadCommand(c.toBufio(), &req); err == nil {
-+              t.Error("socksReadCommand(InvalidAtype) succeded")
-+      }
-+      if msg := c.readHex(); msg != "05080001000000000000" {
-+              t.Error("socksAuthenticate(InvalidAtype) invalid response:", 
msg)
-+      }
-+      c.reset()
-+}
-+
-+// TestRequestIPv4 tests IPv4 SOCKS5 requests.
-+func TestRequestIPv4(t *testing.T) {
-+      c := new(testReadWriter)
-+      var req SocksRequest
-+
-+      // VER = 05, CMD = 01, RSV = 00, ATYPE = 01, DST.ADDR = 127.0.0.1, 
DST.PORT = 9050
-+      c.writeHex("050100017f000001235a")
-+      if err := socksReadCommand(c.toBufio(), &req); err != nil {
-+              t.Error("socksReadCommand(IPv4) failed:", err)
-+      }
-+      addr, err := net.ResolveTCPAddr("tcp", req.Target)
-+      if err != nil {
-+              t.Error("net.ResolveTCPAddr failed:", err)
-+      }
-+      if !tcpAddrsEqual(addr, &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), 
Port: 9050}) {
-+              t.Error("Unexpected target:", addr)
-+      }
-+}
-+
-+// TestRequestIPv6 tests IPv4 SOCKS5 requests.
-+func TestRequestIPv6(t *testing.T) {
-+      c := new(testReadWriter)
-+      var req SocksRequest
-+
-+      // VER = 05, CMD = 01, RSV = 00, ATYPE = 04, DST.ADDR = 
0102:0304:0506:0708:090a:0b0c:0d0e:0f10, DST.PORT = 9050
-+      c.writeHex("050100040102030405060708090a0b0c0d0e0f10235a")
-+      if err := socksReadCommand(c.toBufio(), &req); err != nil {
-+              t.Error("socksReadCommand(IPv6) failed:", err)
-+      }
-+      addr, err := net.ResolveTCPAddr("tcp", req.Target)
-+      if err != nil {
-+              t.Error("net.ResolveTCPAddr failed:", err)
-+      }
-+      if !tcpAddrsEqual(addr, &net.TCPAddr{IP: 
net.ParseIP("0102:0304:0506:0708:090a:0b0c:0d0e:0f10"), Port: 9050}) {
-+              t.Error("Unexpected target:", addr)
-+      }
-+}
-+
-+// TestRequestFQDN tests FQDN (DOMAINNAME) SOCKS5 requests.
-+func TestRequestFQDN(t *testing.T) {
-+      c := new(testReadWriter)
-+      var req SocksRequest
-+
-+      // VER = 05, CMD = 01, RSV = 00, ATYPE = 04, DST.ADDR = example.com, 
DST.PORT = 9050
-+      c.writeHex("050100030b6578616d706c652e636f6d235a")
-+      if err := socksReadCommand(c.toBufio(), &req); err != nil {
-+              t.Error("socksReadCommand(FQDN) failed:", err)
-+      }
-+      if req.Target != "example.com:9050" {
-+              t.Error("Unexpected target:", req.Target)
-+      }
-+}
-+
-+// TestResponseNil tests nil address SOCKS5 responses.
-+func TestResponseNil(t *testing.T) {
-+      c := new(testReadWriter)
-+
-+      b := c.toBufio()
-+      if err := sendSocks5ResponseGranted(b); err != nil {
-+              t.Error("sendSocks5ResponseGranted() failed:", err)
-+      }
-+      b.Flush()
-+      if msg := c.readHex(); msg != "05000001000000000000" {
-+              t.Error("sendSocks5ResponseGranted(nil) invalid response:", msg)
-+      }
-+}
-+
-+var _ io.ReadWriter = (*testReadWriter)(nil)
--- 
-2.3.3
-

_______________________________________________
tor-commits mailing list
[email protected]
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits

Reply via email to