From fb1b82a7c1f5fe7802b978ed5be7c9d5328a0297 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 18 Jun 2014 15:26:29 +0100 Subject: [PATCH] Use ssl_{read,write,gets} methods for unencrypted ("proxy") access too Signed-off-by: David Woodhouse --- http.c | 75 +++++++++++++++++++++++++----------------- openconnect-internal.h | 1 + 2 files changed, 45 insertions(+), 31 deletions(-) diff --git a/http.c b/http.c index ba77c806..c9e530dd 100644 --- a/http.c +++ b/http.c @@ -33,10 +33,8 @@ #include "openconnect-internal.h" -static int proxy_write(struct openconnect_info *vpninfo, int fd, - unsigned char *buf, size_t len); -static int proxy_read(struct openconnect_info *vpninfo, int fd, - unsigned char *buf, size_t len); +static int proxy_write(struct openconnect_info *vpninfo, char *buf, size_t len); +static int proxy_read(struct openconnect_info *vpninfo, char *buf, size_t len); #define MAX_BUF_LEN 131072 #define BUF_CHUNK_SIZE 4096 @@ -1300,8 +1298,7 @@ char *openconnect_create_useragent(const char *base) return uagent; } -static int proxy_gets(struct openconnect_info *vpninfo, int fd, - char *buf, size_t len) +static int proxy_gets(struct openconnect_info *vpninfo, char *buf, size_t len) { int i = 0; int ret; @@ -1309,7 +1306,7 @@ static int proxy_gets(struct openconnect_info *vpninfo, int fd, if (len < 2) return -EINVAL; - while ((ret = proxy_read(vpninfo, fd, (void *)(buf + i), 1)) == 1) { + while ((ret = proxy_read(vpninfo, (void *)(buf + i), 1)) == 1) { if (buf[i] == '\n') { buf[i] = 0; if (i && buf[i-1] == '\r') { @@ -1329,10 +1326,13 @@ static int proxy_gets(struct openconnect_info *vpninfo, int fd, return i ?: ret; } -static int proxy_write(struct openconnect_info *vpninfo, int fd, - unsigned char *buf, size_t len) +static int proxy_write(struct openconnect_info *vpninfo, char *buf, size_t len) { size_t count; + int fd = vpninfo->proxy_fd; + + if (fd == -1) + return -EINVAL; for (count = 0; count < len; ) { fd_set rd_set, wr_set; @@ -1361,10 +1361,13 @@ static int proxy_write(struct openconnect_info *vpninfo, int fd, return count; } -static int proxy_read(struct openconnect_info *vpninfo, int fd, - unsigned char *buf, size_t len) +static int proxy_read(struct openconnect_info *vpninfo, char *buf, size_t len) { size_t count; + int fd = vpninfo->proxy_fd; + + if (fd == -1) + return -EINVAL; for (count = 0; count < len; ) { fd_set rd_set; @@ -1404,23 +1407,23 @@ static const char *socks_errors[] = { N_("address type not supported") }; -static int process_socks_proxy(struct openconnect_info *vpninfo, int ssl_sock) +static int process_socks_proxy(struct openconnect_info *vpninfo) { - unsigned char buf[1024]; + char buf[1024]; int i; buf[0] = 5; /* SOCKS version */ buf[1] = 1; /* # auth methods */ buf[2] = 0; /* No auth supported */ - if ((i = proxy_write(vpninfo, ssl_sock, buf, 3)) < 0) { + if ((i = proxy_write(vpninfo, buf, 3)) < 0) { vpn_progress(vpninfo, PRG_ERR, _("Error writing auth request to SOCKS proxy: %s\n"), strerror(-i)); return i; } - if ((i = proxy_read(vpninfo, ssl_sock, buf, 2)) < 0) { + if ((i = proxy_read(vpninfo, buf, 2)) < 0) { vpn_progress(vpninfo, PRG_ERR, _("Error reading auth response from SOCKS proxy: %s\n"), strerror(-i)); @@ -1437,7 +1440,7 @@ static int process_socks_proxy(struct openconnect_info *vpninfo, int ssl_sock) if (buf[1] < sizeof(socks_errors) / sizeof(socks_errors[0])) vpn_progress(vpninfo, PRG_ERR, _("SOCKS proxy error %02x: %s\n"), - buf[1], _(socks_errors[buf[1]])); + buf[1], _(socks_errors[(unsigned char)buf[1]])); else vpn_progress(vpninfo, PRG_ERR, _("SOCKS proxy error %02x\n"), @@ -1459,7 +1462,7 @@ static int process_socks_proxy(struct openconnect_info *vpninfo, int ssl_sock) buf[i++] = vpninfo->port >> 8; buf[i++] = vpninfo->port & 0xff; - if ((i = proxy_write(vpninfo, ssl_sock, buf, i)) < 0) { + if ((i = proxy_write(vpninfo, buf, i)) < 0) { vpn_progress(vpninfo, PRG_ERR, _("Error writing connect request to SOCKS proxy: %s\n"), strerror(-i)); @@ -1467,7 +1470,7 @@ static int process_socks_proxy(struct openconnect_info *vpninfo, int ssl_sock) } /* Read 5 bytes -- up to and including the first byte of the returned address (which might be the length byte of a domain name) */ - if ((i = proxy_read(vpninfo, ssl_sock, buf, 5)) < 0) { + if ((i = proxy_read(vpninfo, buf, 5)) < 0) { vpn_progress(vpninfo, PRG_ERR, _("Error reading connect response from SOCKS proxy: %s\n"), strerror(-i)); @@ -1500,7 +1503,7 @@ static int process_socks_proxy(struct openconnect_info *vpninfo, int ssl_sock) return -EIO; } - if ((i = proxy_read(vpninfo, ssl_sock, buf, i)) < 0) { + if ((i = proxy_read(vpninfo, buf, i)) < 0) { vpn_progress(vpninfo, PRG_ERR, _("Error reading connect response from SOCKS proxy: %s\n"), strerror(-i)); @@ -1509,7 +1512,7 @@ static int process_socks_proxy(struct openconnect_info *vpninfo, int ssl_sock) return 0; } -static int process_http_proxy(struct openconnect_info *vpninfo, int ssl_sock) +static int process_http_proxy(struct openconnect_info *vpninfo) { char buf[MAX_BUF_LEN]; struct oc_text_buf *reqbuf; @@ -1531,7 +1534,7 @@ static int process_http_proxy(struct openconnect_info *vpninfo, int ssl_sock) _("Requesting HTTP proxy connection to %s:%d\n"), vpninfo->hostname, vpninfo->port); - result = proxy_write(vpninfo, ssl_sock, (unsigned char *)reqbuf->data, reqbuf->pos); + result = proxy_write(vpninfo, reqbuf->data, reqbuf->pos); buf_free(reqbuf); if (result < 0) { @@ -1541,7 +1544,7 @@ static int process_http_proxy(struct openconnect_info *vpninfo, int ssl_sock) return result; } - if (proxy_gets(vpninfo, ssl_sock, buf, sizeof(buf)) < 0) { + if (proxy_gets(vpninfo, buf, sizeof(buf)) < 0) { vpn_progress(vpninfo, PRG_ERR, _("Error fetching proxy response\n")); return -EIO; @@ -1560,7 +1563,7 @@ static int process_http_proxy(struct openconnect_info *vpninfo, int ssl_sock) return -EIO; } - while ((buflen = proxy_gets(vpninfo, ssl_sock, buf, sizeof(buf)))) { + while ((buflen = proxy_gets(vpninfo, buf, sizeof(buf)))) { if (buflen < 0) { vpn_progress(vpninfo, PRG_ERR, _("Failed to read proxy response\n")); @@ -1576,16 +1579,26 @@ static int process_http_proxy(struct openconnect_info *vpninfo, int ssl_sock) int process_proxy(struct openconnect_info *vpninfo, int ssl_sock) { - if (!vpninfo->proxy_type || !strcmp(vpninfo->proxy_type, "http")) - return process_http_proxy(vpninfo, ssl_sock); + int ret; - if (!strcmp(vpninfo->proxy_type, "socks") || - !strcmp(vpninfo->proxy_type, "socks5")) - return process_socks_proxy(vpninfo, ssl_sock); + vpninfo->proxy_fd = ssl_sock; + vpninfo->ssl_read = proxy_read; + vpninfo->ssl_write = proxy_write; + vpninfo->ssl_gets = proxy_gets; - vpn_progress(vpninfo, PRG_ERR, _("Unknown proxy type '%s'\n"), - vpninfo->proxy_type); - return -EIO; + if (!vpninfo->proxy_type || !strcmp(vpninfo->proxy_type, "http")) + ret = process_http_proxy(vpninfo); + else if (!strcmp(vpninfo->proxy_type, "socks") || + !strcmp(vpninfo->proxy_type, "socks5")) + ret = process_socks_proxy(vpninfo); + else { + vpn_progress(vpninfo, PRG_ERR, _("Unknown proxy type '%s'\n"), + vpninfo->proxy_type); + ret = -EIO; + } + + vpninfo->proxy_fd = -1; + return ret; } int openconnect_set_http_proxy(struct openconnect_info *vpninfo, char *proxy) diff --git a/openconnect-internal.h b/openconnect-internal.h index 799a1f16..f45057f1 100644 --- a/openconnect-internal.h +++ b/openconnect-internal.h @@ -167,6 +167,7 @@ struct openconnect_info { char *proxy_type; char *proxy; int proxy_port; + int proxy_fd; char *localname; char *hostname;