]> sjero.net Git - wget/commitdiff
[svn] Use the CONNECT method to establish passthrough over SSL traffic
authorhniksic <devnull@localhost>
Fri, 28 Nov 2003 02:24:53 +0000 (18:24 -0800)
committerhniksic <devnull@localhost>
Fri, 28 Nov 2003 02:24:53 +0000 (18:24 -0800)
over proxies.

src/ChangeLog
src/http.c

index 05b9104b8335f14f6902046be7e569af311b1313..384730bc311d63b450b8b4f4ca03bc649c5c3b38 100644 (file)
@@ -1,3 +1,8 @@
+2003-11-28  Hrvoje Niksic  <hniksic@xemacs.org>
+
+       * http.c (gethttp): Use the CONNECT handle to establish SSL
+       passthrough through non-SSL proxies.
+
 2003-11-28  Hrvoje Niksic  <hniksic@xemacs.org>
 
        * init.c: Don't #include netinet/Winsock stuff.
index 8bdfbbc1eca2345bec81c0079fc3e79cf0ebd0af..f6498d38df041eb5671d5113e1ec7f5434084abf 100644 (file)
@@ -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);