From: hniksic Date: Fri, 28 Nov 2003 02:24:53 +0000 (-0800) Subject: [svn] Use the CONNECT method to establish passthrough over SSL traffic X-Git-Tag: v1.13~1358 X-Git-Url: http://sjero.net/git/?p=wget;a=commitdiff_plain;h=76b59b1ad7f2830aee114d6906605834c850463f [svn] Use the CONNECT method to establish passthrough over SSL traffic over proxies. --- diff --git a/src/ChangeLog b/src/ChangeLog index 05b9104b..384730bc 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +2003-11-28 Hrvoje Niksic + + * http.c (gethttp): Use the CONNECT handle to establish SSL + passthrough through non-SSL proxies. + 2003-11-28 Hrvoje Niksic * init.c: Don't #include netinet/Winsock stuff. diff --git a/src/http.c b/src/http.c index 8bdfbbc1..f6498d38 100644 --- a/src/http.c +++ b/src/http.c @@ -804,7 +804,7 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy) authenticate_h = NULL; auth_tried_already = 0; - inhibit_keep_alive = !opt.http_keep_alive || proxy != NULL; + inhibit_keep_alive = !opt.http_keep_alive; again: /* We need to come back here when the initial attempt to retrieve @@ -825,21 +825,72 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy) hs->remote_time = NULL; hs->error = NULL; - /* If we're using a proxy, we will be connecting to the proxy - server. */ - conn = proxy ? proxy : u; + conn = u; + + proxyauth = NULL; + if (proxy) + { + char *proxy_user, *proxy_passwd; + /* For normal username and password, URL components override + command-line/wgetrc parameters. With proxy + authentication, it's the reverse, because proxy URLs are + normally the "permanent" ones, so command-line args + should take precedence. */ + if (opt.proxy_user && opt.proxy_passwd) + { + proxy_user = opt.proxy_user; + proxy_passwd = opt.proxy_passwd; + } + else + { + proxy_user = proxy->user; + proxy_passwd = proxy->passwd; + } + /* #### This does not appear right. Can't the proxy request, + say, `Digest' authentication? */ + if (proxy_user && proxy_passwd) + proxyauth = basic_authentication_encode (proxy_user, proxy_passwd, + "Proxy-Authorization"); + + /* If we're using a proxy, we will be connecting to the proxy + server. */ + conn = proxy; + } host_lookup_failed = 0; + sock = -1; /* First: establish the connection. */ - if (inhibit_keep_alive - || !persistent_available_p (conn->host, conn->port, + + if (!inhibit_keep_alive) + { + /* Look for a persistent connection to target host, unless a + proxy is used. The exception is when SSL is in use, in which + case the proxy is nothing but a passthrough to the target + host, registered as a connection to the latter. */ + struct url *relevant = conn; #ifdef HAVE_SSL - u->scheme == SCHEME_HTTPS + if (u->scheme == SCHEME_HTTPS) + relevant = u; +#endif + + if (persistent_available_p (relevant->host, relevant->port, +#ifdef HAVE_SSL + relevant->scheme == SCHEME_HTTPS, #else - 0 + 0, #endif - , &host_lookup_failed)) + &host_lookup_failed)) + { + sock = pconn.socket; + using_ssl = pconn.ssl; + logprintf (LOG_VERBOSE, _("Reusing existing connection to %s:%d.\n"), + pconn.host, pconn.port); + DEBUGP (("Reusing fd %d.\n", sock)); + } + } + + if (sock < 0) { /* In its current implementation, persistent_available_p will look up conn->host in some cases. If that lookup failed, we @@ -855,28 +906,75 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy) ? CONERROR : CONIMPOSSIBLE); #ifdef HAVE_SSL - if (conn->scheme == SCHEME_HTTPS) - { - if (!ssl_connect (sock)) - { - logputs (LOG_VERBOSE, "\n"); - logprintf (LOG_NOTQUIET, - _("Unable to establish SSL connection.\n")); - fd_close (sock); - return CONSSLERR; - } - using_ssl = 1; - } + if (proxy && u->scheme == SCHEME_HTTPS) + { + /* When requesting SSL URLs through proxies, use the + CONNECT method to request passthrough. */ + char *connect = + (char *) alloca (64 + + strlen (u->host) + + (proxyauth ? strlen (proxyauth) : 0)); + sprintf (connect, "CONNECT %s:%d HTTP/1.0\r\n%s\r\n", + u->host, u->port, proxyauth ? proxyauth : ""); + DEBUGP (("Writing to proxy: [%s]\n", connect)); + write_error = fd_write (sock, connect, strlen (connect), -1); + if (write_error < 0) + { + xfree_null (proxyauth); + logprintf (LOG_VERBOSE, _("Failed writing to proxy: %s.\n"), + strerror (errno)); + CLOSE_INVALIDATE (sock); + return WRITEFAILED; + } + + head = fd_read_http_head (sock); + if (!head) + { + xfree_null (proxyauth); + logprintf (LOG_VERBOSE, _("Failed reading proxy response: %s\n"), + strerror (errno)); + CLOSE_INVALIDATE (sock); + return HERR; + } + message = NULL; + if (!*head) + { + xfree (head); + goto failed_tunnel; + } + DEBUGP (("proxy responded with: [%s]\n", head)); + + resp = response_new (head); + statcode = response_status (resp, &message); + response_free (resp); + if (statcode != 200) + { + failed_tunnel: + xfree_null (proxyauth); + logprintf (LOG_NOTQUIET, _("Proxy tunneling failed: %s"), + message ? message : "?"); + xfree_null (message); + return CONSSLERR; + } + xfree (message); + + /* SOCK is now *really* connected to u->host, so update CONN + to reflect this. That way register_persistent will + register SOCK as being connected to u->host:u->port. */ + conn = u; + } + + if (conn->scheme == SCHEME_HTTPS) + { + if (!ssl_connect (sock)) + { + fd_close (sock); + return CONSSLERR; + } + using_ssl = 1; + } #endif /* HAVE_SSL */ } - else - { - logprintf (LOG_VERBOSE, _("Reusing existing connection to %s:%d.\n"), - pconn.host, pconn.port); - sock = pconn.socket; - using_ssl = pconn.ssl; - DEBUGP (("Reusing fd %d.\n", sock)); - } if (*dt & HEAD_ONLY) command = "HEAD"; @@ -964,32 +1062,6 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy) } } - proxyauth = NULL; - if (proxy) - { - char *proxy_user, *proxy_passwd; - /* For normal username and password, URL components override - command-line/wgetrc parameters. With proxy authentication, - it's the reverse, because proxy URLs are normally the - "permanent" ones, so command-line args should take - precedence. */ - if (opt.proxy_user && opt.proxy_passwd) - { - proxy_user = opt.proxy_user; - proxy_passwd = opt.proxy_passwd; - } - else - { - proxy_user = proxy->user; - proxy_passwd = proxy->passwd; - } - /* #### This does not appear right. Can't the proxy request, - say, `Digest' authentication? */ - if (proxy_user && proxy_passwd) - proxyauth = basic_authentication_encode (proxy_user, proxy_passwd, - "Proxy-Authorization"); - } - /* String of the form :PORT. Used only for non-standard ports. */ port_maybe = NULL; if (u->port != scheme_default_port (u->scheme)) @@ -1141,10 +1213,7 @@ Accept: %s\r\n\ return HERR; } } - - DEBUGP (("\n---response begin---\n")); - DEBUGP (("%s", head)); - DEBUGP (("---response end---\n")); + DEBUGP (("\n---response begin---\n%s---response end---\n", head)); resp = response_new (head);