diff options
author | des <des@FreeBSD.org> | 2015-10-16 12:21:44 +0000 |
---|---|---|
committer | des <des@FreeBSD.org> | 2015-10-16 12:21:44 +0000 |
commit | 7cd58b9488563c5becfc657f8fdc56f141ae9aec (patch) | |
tree | 8868fc562d1b24540e135a75c5d571150285e715 /lib | |
parent | 7f5fdd9fd0fe05175bb9505518308a90bbe9674c (diff) | |
download | FreeBSD-src-7cd58b9488563c5becfc657f8fdc56f141ae9aec.zip FreeBSD-src-7cd58b9488563c5becfc657f8fdc56f141ae9aec.tar.gz |
Fix two bugs in HTTPS tunnelling:
- 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
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libfetch/http.c | 36 |
1 files changed, 32 insertions, 4 deletions
diff --git a/lib/libfetch/http.c b/lib/libfetch/http.c index 91ca6a3..f6a7454 100644 --- a/lib/libfetch/http.c +++ b/lib/libfetch/http.c @@ -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 * |