]> xenbits.xensource.com Git - people/julieng/freebsd.git/commitdiff
Fix two bugs in HTTPS tunnelling:
authordes <des@FreeBSD.org>
Fri, 16 Oct 2015 12:21:44 +0000 (12:21 +0000)
committerdes <des@FreeBSD.org>
Fri, 16 Oct 2015 12:21:44 +0000 (12:21 +0000)
 - If the proxy returns a non-200 result, set the error code accordingly
   so the caller / user gets a somewhat meaningful error message.
 - Consume and discard any HTTP response header following the result line.

PR: 194483
Tested by: Fabian Keil <fk@fabiankeil.de>
MFC after: 1 week

lib/libfetch/http.c

index 91ca6a399739856db42ef81b81d6e4931e7d9d87..f6a74540c8fc8c3efc5b5a5a5d3fcf2c7aa8bed9 100644 (file)
@@ -1376,8 +1376,12 @@ http_connect(struct url *URL, struct url *purl, const char *flags)
 {
        struct url *curl;
        conn_t *conn;
+       hdr_t h;
+       http_headerbuf_t headerbuf;
+       const char *p;
        int verbose;
        int af, val;
+       int serrno;
 
 #ifdef INET6
        af = AF_UNSPEC;
@@ -1398,6 +1402,7 @@ http_connect(struct url *URL, struct url *purl, const char *flags)
        if ((conn = fetch_connect(curl->host, curl->port, af, verbose)) == NULL)
                /* fetch_connect() has already set an error code */
                return (NULL);
+       init_http_headerbuf(&headerbuf);
        if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0 && purl) {
                http_cmd(conn, "CONNECT %s:%d HTTP/1.1",
                    URL->host, URL->port);
@@ -1405,10 +1410,26 @@ http_connect(struct url *URL, struct url *purl, const char *flags)
                    URL->host, URL->port);
                http_cmd(conn, "");
                if (http_get_reply(conn) != HTTP_OK) {
-                       fetch_close(conn);
-                       return (NULL);
+                       http_seterr(conn->err);
+                       goto ouch;
+               }
+               /* Read and discard the rest of the proxy response */
+               if (fetch_getln(conn) < 0) {
+                       fetch_syserr();
+                       goto ouch;
                }
-               http_get_reply(conn);
+               do {
+                       switch ((h = http_next_header(conn, &headerbuf, &p))) {
+                       case hdr_syserror:
+                               fetch_syserr();
+                               goto ouch;
+                       case hdr_error:
+                               http_seterr(HTTP_PROTOCOL_ERROR);
+                               goto ouch;
+                       default:
+                               /* ignore */ ;
+                       }
+               } while (h < hdr_end);
        }
        if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0 &&
            fetch_ssl(conn, URL, verbose) == -1) {
@@ -1416,13 +1437,20 @@ http_connect(struct url *URL, struct url *purl, const char *flags)
                /* grrr */
                errno = EAUTH;
                fetch_syserr();
-               return (NULL);
+               goto ouch;
        }
 
        val = 1;
        setsockopt(conn->sd, IPPROTO_TCP, TCP_NOPUSH, &val, sizeof(val));
 
+       clean_http_headerbuf(&headerbuf);
        return (conn);
+ouch:
+       serrno = errno;
+       clean_http_headerbuf(&headerbuf);
+       fetch_close(conn);
+       errno = serrno;
+       return (NULL);
 }
 
 static struct url *