From aab91a3e141d0ced1568fe0c5f3f562d2549d34a Mon Sep 17 00:00:00 2001 From: simon Date: Sat, 21 Sep 2002 16:07:43 +0000 Subject: [PATCH] Support username/password authentication in SOCKS 5. git-svn-id: svn://svn.tartarus.org/sgt/putty@1972 cda61777-01e9-0310-a592-d414129be87e --- doc/config.but | 9 ++++---- proxy.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 67 insertions(+), 12 deletions(-) diff --git a/doc/config.but b/doc/config.but index c2383b6b..50f16e7c 100644 --- a/doc/config.but +++ b/doc/config.but @@ -1,4 +1,4 @@ -\versionid $Id: config.but,v 1.39 2002/09/21 14:03:05 simon Exp $ +\versionid $Id: config.but,v 1.40 2002/09/21 16:07:43 simon Exp $ \C{config} Configuring PuTTY @@ -1433,15 +1433,14 @@ This excludes both of the above ranges at once. If your proxy requires authentication, you can enter a username and a password in the \q{Username} and \q{Password} boxes. -Authentication is not supported for all forms of proxy. Currently: +Authentication is not supported for all forms of proxy: -\b Username and password authentication is supported for HTTP proxies. +\b Username and password authentication is supported for HTTP +proxies and SOCKS 5 proxies. \b SOCKS 4 can use the \q{Username} field, but does not support passwords. -\b PuTTY does not support authentication in SOCKS 5 at all. - \b Authentication is meaningless in Telnet proxies. \S{config-proxy-command} Specifying the Telnet proxy command diff --git a/proxy.c b/proxy.c index f73b9ad1..408552a4 100644 --- a/proxy.c +++ b/proxy.c @@ -683,6 +683,7 @@ int proxy_socks4_negotiate (Proxy_Socket p, int change) return 1; } + bufchain_consume(&p->pending_input_data, 2); /* we're done */ proxy_activate(p); @@ -713,13 +714,22 @@ int proxy_socks5_negotiate (Proxy_Socket p, int change) * 0x03 = CHAP */ - char command[3]; + char command[4]; + int len; command[0] = 5; /* version 5 */ - command[1] = 1; /* TODO: we don't currently support any auth methods */ - command[2] = 0x00; /* no authentication */ + if (cfg.proxy_username[0] || cfg.proxy_password[0]) { + command[1] = 2; /* two methods supported: */ + command[2] = 0x00; /* no authentication */ + command[3] = 0x02; /* username/password */ + len = 4; + } else { + command[1] = 1; /* one methods supported: */ + command[2] = 0x00; /* no authentication */ + len = 3; + } - sk_write(p->sub_socket, command, 3); + sk_write(p->sub_socket, command, len); p->state = 1; return 0; @@ -795,6 +805,36 @@ int proxy_socks5_negotiate (Proxy_Socket p, int change) PROXY_ERROR_GENERAL, 0); return 1; } + bufchain_consume(&p->pending_input_data, 2); + } + + if (p->state == 7) { + + /* password authentication reply format: + * version number (1 bytes) = 1 + * reply code (1 byte) + * 0 = succeeded + * >0 = failed + */ + + /* get the response */ + bufchain_prefix(&p->pending_input_data, &data, &len); + + if (data[0] != 1) { + plug_closing(p->plug, "Network error: Error while communicating with proxy", + PROXY_ERROR_GENERAL, 0); + return 1; + } + + if (data[1] != 0) { + + plug_closing(p->plug, "Network error: Proxy refused authentication", + PROXY_ERROR_GENERAL, 0); + return 1; + } + + bufchain_consume(&p->pending_input_data, 2); + p->state = 2; /* now proceed as authenticated */ } if (p->state == 2) { @@ -909,9 +949,24 @@ int proxy_socks5_negotiate (Proxy_Socket p, int change) } if (p->state == 5) { - /* TODO: Handle username/password authentication */ - plug_closing(p->plug, "Network error: We don't support username/password " - "authentication", + if (cfg.proxy_username[0] || cfg.proxy_password[0]) { + char userpwbuf[514]; + int ulen, plen; + ulen = strlen(cfg.proxy_username); + if (ulen > 255) ulen = 255; if (ulen < 1) ulen = 1; + plen = strlen(cfg.proxy_password); + if (plen > 255) plen = 255; if (plen < 1) plen = 1; + userpwbuf[0] = 1; /* version number of subnegotiation */ + userpwbuf[1] = ulen; + memcpy(userpwbuf+2, cfg.proxy_username, ulen); + userpwbuf[ulen+2] = plen; + memcpy(userpwbuf+ulen+3, cfg.proxy_password, plen); + sk_write(p->sub_socket, userpwbuf, ulen + plen + 3); + p->state = 7; + } else + plug_closing(p->plug, "Network error: Server chose " + "username/password authentication but we " + "didn't offer it!", PROXY_ERROR_GENERAL, 0); return 1; } @@ -922,6 +977,7 @@ int proxy_socks5_negotiate (Proxy_Socket p, int change) PROXY_ERROR_GENERAL, 0); return 1; } + } plug_closing(p->plug, "Network error: Unexpected proxy error", -- 2.11.0