From dfa86cadfe846b26e8f838b17cad0cc5a6da2593 Mon Sep 17 00:00:00 2001
From: Robin Tarsiger <rtt@dasyatidae.com>
Date: Mon, 24 Jul 2017 20:28:09 -0500
Subject: [PATCH 06/12] PT2.0: Adjust outgoing SOCKS auth negotiation for PT

This adds the PT2 JSON method when there are PT parameters to
negotiate. (Though possibly it should only do that if we have a
known PT2 on the other side, per #21816 comment 3.) It also
switches to the correct state to activate handling for it: this
is the part that makes the PROXY_SOCKS5_WANT_AUTH_METHOD_PT2
state live.
---
 src/or/connection.c | 27 ++++++++++++++++++++-------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/src/or/connection.c b/src/or/connection.c
index 853c9d60c..798b2968f 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -2215,23 +2215,36 @@ connection_proxy_connect(connection_t *conn, int type)
     }
 
     case PROXY_SOCKS5: {
-      unsigned char buf[4]; /* fields: vers, num methods, method list */
+      unsigned char buf[16]; /* fields: vers, num methods, method list */
 
       /* Send a SOCKS5 greeting (connect request must wait) */
 
       buf[0] = 5; /* version */
+      /* buf[1] will be the count of auth methods, and buf[2...] will
+         be the identifying numbers of the auth methods. */
 
       /* We have to use SOCKS5 authentication, if we have a
          Socks5ProxyUsername or if we want to pass arguments to our
          pluggable transport proxy: */
-      if ((options->Socks5ProxyUsername) ||
-          (get_proxy_type() == PROXY_PLUGGABLE &&
-           (get_socks_args_by_bridge_addrport(&conn->addr, conn->port)))) {
-      /* number of auth methods */
+      if (options->Socks5ProxyUsername) {
         buf[1] = 2;
-        buf[2] = 0x00; /* no authentication */
-        buf[3] = 0x02; /* rfc1929 Username/Passwd auth */
+        buf[2] = 0x00; /* none - credentials weren't needed */
+        buf[3] = 0x02; /* RFC1929 - use username/password */
+
         conn->proxy_state = PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929;
+      } else if (get_proxy_type() == PROXY_PLUGGABLE) {
+        if (get_socks_args_by_bridge_addrport(&conn->addr, conn->port)) {
+          /* Only negotiate methods that have nonempty parameters. */
+          buf[1] = 2;
+          buf[2] = 0x02; /* RFC1929 - params in username/password */
+          buf[3] = 0x80; /* PT2 JSON - params as JSON object */
+        } else {
+          /* Only negotiate parameterless method. */
+          buf[1] = 1;
+          buf[2] = 0x00; /* none - parameterless */
+        }
+
+        conn->proxy_state = PROXY_SOCKS5_WANT_AUTH_METHOD_PT2;
       } else {
         buf[1] = 1;
         buf[2] = 0x00; /* no authentication */
-- 
2.14.0


