Fetching a URL with an embedded user and password when both the http_proxy and
no_proxy environment variables are set doesn't work correctly. For example:
$ export http_proxy=http://localhost:3128/
$ export no_proxy=192.168.1.1
This works as expected:
$ curl -v http://192.168.1.1/
* About to connect() to 192.168.1.1 port 80 (#0)
but this attempts to go through the proxy anyway:
$ curl -v http://u:[email protected]/
* About to connect() to proxy localhost port 3128 (#0)
I think the cause is the order of operations in create_conn(), which does
proxy detection before removing the user and password from conn->host.name.
The attached patch reorders the code to fix it. The reasoning behind this is:
1. ParseURLAndFillConnection() fills in conn->protostr and may also do
conn->protocol |= PROT_MISSING
2. setup_connection_internals() uses conn->protostr and sets conn->protocol
3. parse_url_userpass() needs conn->protocol
so the patch keeps these in the same order, but moves them before proxy
detection so that proxy detection gets the conn->host.name altered by
parse_url_userpass().
This problem came up on the #curl IRC channel.
James
? .url.c.swp
? ca-bundle.h
? no_proxy-auth-in-url.patch
Index: url.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/url.c,v
retrieving revision 1.797
diff -u -r1.797 url.c
--- url.c 12 May 2009 07:38:31 -0000 1.797
+++ url.c 15 May 2009 03:10:56 -0000
@@ -4316,6 +4316,44 @@
return result;
}
+ /*************************************************************
+ * No protocol part in URL was used, add it!
+ *************************************************************/
+ if(conn->protocol&PROT_MISSING) {
+ /* We're guessing prefixes here and if we're told to use a proxy or if
+ we're gonna follow a Location: later or... then we need the protocol
+ part added so that we have a valid URL. */
+ char *reurl;
+
+ reurl = aprintf("%s://%s", conn->protostr, data->change.url);
+
+ if(!reurl) {
+ Curl_safefree(proxy);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ data->change.url = reurl;
+ data->change.url_alloc = TRUE; /* free this later */
+ conn->protocol &= ~PROT_MISSING; /* switch that one off again */
+ }
+
+ /*************************************************************
+ * Setup internals depending on protocol
+ *************************************************************/
+ result = setup_connection_internals(data, conn);
+ if(result != CURLE_OK) {
+ Curl_safefree(proxy);
+ return result;
+ }
+
+ /*************************************************************
+ * Parse a user name and password in the URL and strip it out
+ * of the host name
+ *************************************************************/
+ result = parse_url_userpass(data, conn, user, passwd);
+ if(result != CURLE_OK)
+ return result;
+
#ifndef CURL_DISABLE_PROXY
/*************************************************************
* Extract the user and password from the authentication string
@@ -4371,37 +4409,6 @@
}
#endif /* CURL_DISABLE_PROXY */
- /*************************************************************
- * No protocol part in URL was used, add it!
- *************************************************************/
- if(conn->protocol&PROT_MISSING) {
- /* We're guessing prefixes here and if we're told to use a proxy or if
- we're gonna follow a Location: later or... then we need the protocol
- part added so that we have a valid URL. */
- char *reurl;
-
- reurl = aprintf("%s://%s", conn->protostr, data->change.url);
-
- if(!reurl) {
- Curl_safefree(proxy);
- return CURLE_OUT_OF_MEMORY;
- }
-
- data->change.url = reurl;
- data->change.url_alloc = TRUE; /* free this later */
- conn->protocol &= ~PROT_MISSING; /* switch that one off again */
- }
-
- /*************************************************************
- * Setup internals depending on protocol
- *************************************************************/
- result = setup_connection_internals(data, conn);
- if(result != CURLE_OK) {
- Curl_safefree(proxy);
- return result;
- }
-
-
#ifndef CURL_DISABLE_PROXY
/***********************************************************************
* If this is supposed to use a proxy, we need to figure out the proxy
@@ -4463,14 +4470,6 @@
conn->bits.tunnel_proxy = TRUE;
/*************************************************************
- * Parse a user name and password in the URL and strip it out
- * of the host name
- *************************************************************/
- result = parse_url_userpass(data, conn, user, passwd);
- if(result != CURLE_OK)
- return result;
-
- /*************************************************************
* Figure out the remote port number and fix it in the URL
*************************************************************/
result = parse_remote_port(data, conn);