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

David Shaw's fix that unifies proxy string treatment so that a proxy given

with CURLOPT_PROXY can use a http:// prefix and user + password. The user
and password fields are now also URL decoded properly.

Test case 264 added to verify.
parent c73f8e83
Loading
Loading
Loading
Loading
+51 −58
Original line number Diff line number Diff line
@@ -2502,11 +2502,11 @@ static CURLcode CreateConnection(struct SessionHandle *data,
           "%" MAX_CURL_PASSWORD_LENGTH_TXT "[^\n]",
           proxyuser, proxypasswd);

    conn->proxyuser = strdup(proxyuser);
    conn->proxyuser = curl_unescape(proxyuser,0);
    if(!conn->proxyuser)
      return CURLE_OUT_OF_MEMORY;

    conn->proxypasswd = strdup(proxypasswd);
    conn->proxypasswd = curl_unescape(proxypasswd,0);
    if(!conn->proxypasswd)
      return CURLE_OUT_OF_MEMORY;
  }
@@ -2611,62 +2611,6 @@ static CURLcode CreateConnection(struct SessionHandle *data,
        }

        if(proxy && *proxy) {
          /* we have a proxy here to set */
          char *ptr;
          char proxyuser[MAX_CURL_USER_LENGTH];
          char proxypasswd[MAX_CURL_PASSWORD_LENGTH];

          char *fineptr;

          /* skip the possible protocol piece */
          ptr=strstr(proxy, "://");
          if(ptr)
            ptr += 3;
          else
            ptr = proxy;

          fineptr = ptr;

          /* check for an @-letter */
          ptr = strchr(ptr, '@');
          if(ptr && (2 == sscanf(fineptr,
                                 "%" MAX_CURL_USER_LENGTH_TXT"[^:]:"
                                 "%" MAX_CURL_PASSWORD_LENGTH_TXT "[^@]",
                                 proxyuser, proxypasswd))) {
            CURLcode res = CURLE_OK;

            /* found user and password, rip them out */
            Curl_safefree(conn->proxyuser);
            conn->proxyuser = strdup(proxyuser);

            if(!conn->proxyuser)
              res = CURLE_OUT_OF_MEMORY;
            else {
              Curl_safefree(conn->proxypasswd);
              conn->proxypasswd = strdup(proxypasswd);

              if(!conn->proxypasswd)
                res = CURLE_OUT_OF_MEMORY;
            }

            if(CURLE_OK == res) {
              conn->bits.proxy_user_passwd = TRUE; /* enable it */
              ptr = strdup(ptr+1); /* the right side of the @-letter */

              if(ptr) {
                free(proxy); /* free the former proxy string */
                proxy = ptr; /* now use this instead */
              }
              else
                res = CURLE_OUT_OF_MEMORY;
            }

            if(res) {
              free(proxy); /* free the allocated proxy string */
              return res;
            }
          }

          data->change.proxy = proxy;
          data->change.proxy_alloc=TRUE; /* this needs to be freed later */
          conn->bits.httpproxy = TRUE;
@@ -2944,6 +2888,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
    /* We use 'proxyptr' to point to the proxy name from now on... */
    char *proxyptr=proxydup;
    char *portptr;
    char *atsign;

    if(NULL == proxydup) {
      failf(data, "memory shortage");
@@ -2960,6 +2905,54 @@ static CURLcode CreateConnection(struct SessionHandle *data,
    if(endofprot)
      proxyptr = endofprot+3;

    /* Is there a username and password given in this proxy url? */
    atsign = strchr(proxyptr, '@');
    if(atsign) {
      char proxyuser[MAX_CURL_USER_LENGTH];
      char proxypasswd[MAX_CURL_PASSWORD_LENGTH];

      if(2 == sscanf(proxyptr,
		     "%" MAX_CURL_USER_LENGTH_TXT"[^:]:"
		     "%" MAX_CURL_PASSWORD_LENGTH_TXT "[^@]",
		     proxyuser, proxypasswd)) {
	CURLcode res = CURLE_OK;

	/* found user and password, rip them out.  note that we are
	   unescaping them, as there is otherwise no way to have a
	   username or password with reserved characters like ':' in
	   them. */
	Curl_safefree(conn->proxyuser);
	conn->proxyuser = curl_unescape(proxyuser,0);

	if(!conn->proxyuser)
	  res = CURLE_OUT_OF_MEMORY;
	else {
	  Curl_safefree(conn->proxypasswd);
	  conn->proxypasswd = curl_unescape(proxypasswd,0);

	  if(!conn->proxypasswd)
	    res = CURLE_OUT_OF_MEMORY;
	}

	if(CURLE_OK == res) {
	  conn->bits.proxy_user_passwd = TRUE; /* enable it */
	  atsign = strdup(atsign+1); /* the right side of the @-letter */

	  if(atsign) {
	    free(proxydup); /* free the former proxy string */
	    proxydup = proxyptr = atsign; /* now use this instead */
	  }
	  else
	    res = CURLE_OUT_OF_MEMORY;
	}

	if(res) {
	  free(proxydup); /* free the allocated proxy string */
	  return res;
	}
      }
    }

    /* start scanning for port number at this point */
    portptr = proxyptr;

+1 −1
Original line number Diff line number Diff line
@@ -32,4 +32,4 @@ EXTRA_DIST = test1 test108 test117 test127 test20 test27 test34 test46 \
 test231 test232 test228 test229 test233 test234 test235 test236 test520   \
 test237 test238 test239 test243 test245 test246 test247 test248 test249   \
 test250 test251 test252 test253 test254 test255 test521 test522 test523   \
 test256 test257 test258 test259 test260 test261 test262 test263
 test256 test257 test258 test259 test260 test261 test262 test263 test264

tests/data/test264

0 → 100644
+47 −0
Original line number Diff line number Diff line
<info>
<keywords>
HTTP
HTTP GET
HTTP proxy
HTTP proxy Basic auth
</keywords>
</info>
# Server-side
<reply>
<data>
HTTP/1.1 200 OK swsclose
Date: Thu, 09 Nov 2010 14:49:00 GMT
Content-Type: text/html

the content would go here
</data>
</reply>

# Client-side
<client>
<server>
http
</server>
 <name>
HTTP with proxy string including http:// and user+password
 </name>
 <command>
http://we.want.that.site.com/264 -x http://fake:user@%HOSTIP:%HTTPPORT
</command>
</client>

# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
</strip>
<protocol>
GET http://we.want.that.site.com/264 HTTP/1.1
Proxy-Authorization: Basic ZmFrZTp1c2Vy
Host: we.want.that.site.com
Pragma: no-cache
Accept: */*
Proxy-Connection: Keep-Alive

</protocol>
</verify>