Commit 3b1b2657 authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

proxy: allow socks:// prefix in proxy string

Inspired by a patch from OB.Conseil. Added test case 708 to verify.
parent 2cbe885c
Loading
Loading
Loading
Loading
+9 −9
Original line number Diff line number Diff line
@@ -1554,10 +1554,10 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
          newport = (unsigned short)(num & 0xffff);

          if(conn->bits.tunnel_proxy ||
             data->set.proxytype == CURLPROXY_SOCKS5 ||
             data->set.proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
             data->set.proxytype == CURLPROXY_SOCKS4 ||
             data->set.proxytype == CURLPROXY_SOCKS4A)
             conn->proxytype == CURLPROXY_SOCKS5 ||
             conn->proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
             conn->proxytype == CURLPROXY_SOCKS4 ||
             conn->proxytype == CURLPROXY_SOCKS4A)
            /* proxy tunnel -> use other host info because ip_addr_str is the
               proxy address not the ftp host */
            snprintf(newhost, sizeof(newhost), "%s", conn->host.name);
@@ -1610,10 +1610,10 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
            ip[0], ip[1], ip[2], ip[3],
            conn->ip_addr_str);
      if(conn->bits.tunnel_proxy ||
          data->set.proxytype == CURLPROXY_SOCKS5 ||
          data->set.proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
          data->set.proxytype == CURLPROXY_SOCKS4 ||
          data->set.proxytype == CURLPROXY_SOCKS4A)
         conn->proxytype == CURLPROXY_SOCKS5 ||
         conn->proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
         conn->proxytype == CURLPROXY_SOCKS4 ||
         conn->proxytype == CURLPROXY_SOCKS4A)
        /* proxy tunnel -> use other host info because ip_addr_str is the
           proxy address not the ftp host */
        snprintf(newhost, sizeof(newhost), "%s", conn->host.name);
@@ -1715,7 +1715,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
    /* this just dumps information about this second connection */
    ftp_pasv_verbose(conn, conninfo, newhost, connectport);

  switch(data->set.proxytype) {
  switch(conn->proxytype) {
    /* FIX: this MUST wait for a proper connect first if 'connected' is
     * FALSE */
  case CURLPROXY_SOCKS5:
+1 −1
Original line number Diff line number Diff line
@@ -385,7 +385,7 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
  curl_socket_t sock = conn->sock[sockindex];
  struct SessionHandle *data = conn->data;
  long timeout;
  bool socks5_resolve_local = (bool)(data->set.proxytype == CURLPROXY_SOCKS5);
  bool socks5_resolve_local = (bool)(conn->proxytype == CURLPROXY_SOCKS5);
  const size_t hostname_len = strlen(hostname);
  ssize_t packetsize = 0;

+40 −36
Original line number Diff line number Diff line
@@ -3132,25 +3132,22 @@ ConnectionStore(struct SessionHandle *data,
*/
CURLcode Curl_connected_proxy(struct connectdata *conn)
{
  CURLcode result = CURLE_OK;
  struct SessionHandle *data = conn->data;

  switch(data->set.proxytype) {
  switch(conn->proxytype) {
#ifndef CURL_DISABLE_PROXY
  case CURLPROXY_SOCKS5:
  case CURLPROXY_SOCKS5_HOSTNAME:
    result = Curl_SOCKS5(conn->proxyuser, conn->proxypasswd,
    return Curl_SOCKS5(conn->proxyuser, conn->proxypasswd,
                       conn->host.name, conn->remote_port,
                       FIRSTSOCKET, conn);
    break;

  case CURLPROXY_SOCKS4:
    result = Curl_SOCKS4(conn->proxyuser, conn->host.name,
    return Curl_SOCKS4(conn->proxyuser, conn->host.name,
                       conn->remote_port, FIRSTSOCKET, conn, FALSE);
    break;

  case CURLPROXY_SOCKS4A:
    result = Curl_SOCKS4(conn->proxyuser, conn->host.name,
    return Curl_SOCKS4(conn->proxyuser, conn->host.name,
                       conn->remote_port, FIRSTSOCKET, conn, TRUE);
    break;

#endif /* CURL_DISABLE_PROXY */
  case CURLPROXY_HTTP:
  case CURLPROXY_HTTP_1_0:
@@ -3160,7 +3157,7 @@ CURLcode Curl_connected_proxy(struct connectdata *conn)
    break;
  } /* switch proxytype */

  return result;
  return CURLE_OK;
}

static CURLcode ConnectPlease(struct SessionHandle *data,
@@ -4066,16 +4063,23 @@ static CURLcode parse_proxy(struct SessionHandle *data,
  char *atsign;

  /* We do the proxy host string parsing here. We want the host name and the
   * port name. Accept a protocol:// prefix, even though it should just be
   * ignored.
   * port name. Accept a protocol:// prefix
   */

  /* Skip the protocol part if present */
  /* Parse the protocol part if present */
  endofprot = strstr(proxy, "://");
  if(endofprot)
  if(endofprot) {
    proxyptr = endofprot+3;
    if(checkprefix("socks5", proxy))
      conn->proxytype = CURLPROXY_SOCKS5;
    else if(checkprefix("socks4a", proxy))
      conn->proxytype = CURLPROXY_SOCKS4A;
    else if(checkprefix("socks4", proxy))
      conn->proxytype = CURLPROXY_SOCKS4;
    /* Any other xxx:// : change to http proxy */
  }
  else
    proxyptr = proxy;
    proxyptr = proxy; /* No xxx:// head: It's a HTTP proxy */

  /* Is there a username and password given in this proxy url? */
  atsign = strchr(proxyptr, '@');
@@ -4763,12 +4767,24 @@ static CURLcode create_conn(struct SessionHandle *data,
  else if(!proxy)
    proxy = detect_proxy(conn);

  if(proxy && !*proxy) {
    free(proxy);  /* Don't bother with an empty proxy string */
  if(proxy && (!*proxy || (conn->handler->flags & PROTOPT_BANPROXY))) {
    free(proxy);  /* Don't bother with an empty proxy string or if the
                     protocol doesn't work with proxy */
    proxy = NULL;
  }
  /* proxy must be freed later unless NULL */
  if(proxy && !(conn->handler->flags & PROTOPT_BANPROXY)) {

  /***********************************************************************
   * If this is supposed to use a proxy, we need to figure out the proxy host
   * name, proxy type and port number, so that we can re-use an existing
   * connection that may exist registered to the same proxy host.
   ***********************************************************************/
  if(proxy) {
    result = parse_proxy(data, conn, proxy);

    /* parse_proxy has freed the proxy string, so don't try to use it again */
    if(result != CURLE_OK)
      return result;

    if((conn->proxytype == CURLPROXY_HTTP) ||
       (conn->proxytype == CURLPROXY_HTTP_1_0)) {
#ifdef CURL_DISABLE_HTTP
@@ -4790,18 +4806,6 @@ static CURLcode create_conn(struct SessionHandle *data,
    conn->bits.tunnel_proxy = FALSE;
  }

  /***********************************************************************
   * If this is supposed to use a proxy, we need to figure out the proxy
   * host name, so that we can re-use an existing connection
   * that may exist registered to the same proxy host.
   ***********************************************************************/
  if(proxy) {
    result = parse_proxy(data, conn, proxy);
    /* parse_proxy has freed the proxy string, so don't try to use it again */
    proxy = NULL;
    if(result != CURLE_OK)
      return result;
  }
#endif /* CURL_DISABLE_PROXY */

  /*************************************************************
+2 −1
Original line number Diff line number Diff line
@@ -71,7 +71,8 @@ EXTRA_DIST = test1 test108 test117 test127 test20 test27 test34 test46 \
 test1203 test1117 test1118 test1119 test1120 test1300 test1301 test1302 \
 test1303 test320 test321 test322 test323 test324 test1121 test581 test580 \
 test1304 test1305 test1306 test1307 test582 test583 test808 test809       \
 test810 test811 test812 test813 test584 test1122 test1123 test1124 test1125
 test810 test811 test812 test813 test584 test1122 test1123 test1124 test1125 \
 test708

filecheck:
	@mkdir test-place; \

tests/data/test708

0 → 100644
+60 −0
Original line number Diff line number Diff line
<testcase>
<info>
<keywords>
HTTP
HTTP GET
SOCKS4
</keywords>
</info>

#
# Server-side
<reply name="1">
<data>
HTTP/1.1 200 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Content-Length: 6
Connection: close
Content-Type: text/html
Funny-head: yesyes

-foo-
</data>
</reply>

#
# Client-side
<client>
<server>
http
socks4
</server>
<setenv>
all_proxy=socks4://%HOSTIP:%SOCKSPORT
</setenv>
 <name>
HTTP GET via SOCKS4 proxy
 </name>
 <command>
http://%HOSTIP:%HTTPPORT/708
</command>
</client>

#
# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
</strip>
<protocol>
GET /708 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*

</protocol>
</verify>
</testcase>