diff options
author | corvid <corvid@lavabit.com> | 2009-06-01 01:29:42 +0000 |
---|---|---|
committer | corvid <corvid@lavabit.com> | 2009-06-01 01:29:42 +0000 |
commit | 16e260e5621cde71a2a7baef681e5b658c2cc2b3 (patch) | |
tree | 4daf1644375c7ee5e98deaaec86b769ce2e1e784 | |
parent | fe833a994380f5e200904ecb367ae5d2b79701fd (diff) |
proxy support for HTTPS
-rw-r--r-- | ChangeLog | 1 | ||||
-rw-r--r-- | dillorc | 5 | ||||
-rw-r--r-- | dpi/https.c | 66 | ||||
-rw-r--r-- | src/IO/Url.h | 2 | ||||
-rw-r--r-- | src/IO/http.c | 51 | ||||
-rw-r--r-- | src/capi.c | 15 |
6 files changed, 132 insertions, 8 deletions
@@ -37,6 +37,7 @@ dillo-2.1 - Added "View Stylesheets" to the page menu. - Remove standard_widget_colors dillorc option. - Added dillo(1) man page. + - Proxy support for HTTPS. Patches: place (AKA corvid) +- Switched SSL-enabled to configure.in (./configure --enable-ssl). - Standardised the installation of dpid/dpidrc with auto* tools. @@ -115,9 +115,8 @@ # Set the proxy information for http. # Note that the http_proxy environment variable overrides this setting. -# WARNING: - HTTPS does not currently use the proxy settings. -# - FTP and downloads plugins use wget. To use a proxy with them, -# you will need to configure wget accordingly. +# WARNING: FTP and downloads plugins use wget. To use a proxy with them, +# you will need to configure wget accordingly. # http_proxy="http://localhost:8080/" #(by default, no proxy is used) diff --git a/dpi/https.c b/dpi/https.c index ba6c73a9..34d2b5f3 100644 --- a/dpi/https.c +++ b/dpi/https.c @@ -129,7 +129,8 @@ static void yes_ssl_support(void) SSL_CTX * ssl_context = NULL; SSL * ssl_connection = NULL; - char *dpip_tag = NULL, *cmd = NULL, *url = NULL, *http_query = NULL; + char *dpip_tag = NULL, *cmd = NULL, *url = NULL, *http_query = NULL, + *proxy_url = NULL, *proxy_connect = NULL; char buf[4096]; int retval = 0; int network_socket = -1; @@ -194,6 +195,9 @@ static void yes_ssl_support(void) /*Get the network address and command to be used*/ dpip_tag = sock_handler_read(sh); cmd = a_Dpip_get_attr(dpip_tag, strlen(dpip_tag), "cmd"); + proxy_url = a_Dpip_get_attr(dpip_tag, strlen(dpip_tag), "proxy_url"); + proxy_connect = + a_Dpip_get_attr(dpip_tag, strlen(dpip_tag), "proxy_connect"); url = a_Dpip_get_attr(dpip_tag, strlen(dpip_tag), "url"); http_query = a_Dpip_get_attr(dpip_tag, strlen(dpip_tag), "query"); @@ -205,13 +209,66 @@ static void yes_ssl_support(void) } if (exit_error == 0){ - network_socket = get_network_connection(url); + char *connect_url = proxy_url ? proxy_url : url; + + network_socket = get_network_connection(connect_url); if (network_socket<0){ MSG("Network socket create error\n"); exit_error = 1; } } + if (exit_error == 0 && proxy_connect != NULL) { + ssize_t St; + const char *p = proxy_connect; + int writelen = strlen(proxy_connect); + + while (writelen > 0) { + St = write(network_socket, p, writelen); + if (St < 0) { + /* Error */ + if (errno != EINTR) { + MSG("Error writing to proxy.\n"); + exit_error = 1; + break; + } + } else { + p += St; + writelen -= St; + } + } + if (exit_error == 0) { + const size_t buflen = 200; + char buf[buflen]; + Dstr *reply = dStr_new(""); + + while (1) { + St = read(network_socket, buf, buflen); + if (St > 0) { + dStr_append_l(reply, buf, St); + if (strstr(reply->str, "\r\n\r\n")) { + /* have whole reply header */ + if (reply->len >= 12 && reply->str[9] == '2') { + /* e.g. "HTTP/1.1 200 Connection established[...]" */ + MSG("CONNECT through proxy succeeded.\n"); + } else { + /* TODO: send reply body to dillo */ + exit_error = 1; + MSG("CONNECT through proxy failed.\n"); + } + break; + } + } else if (St < 0) { + if (errno != EINTR) { + exit_error = 1; + MSG("Error reading from proxy.\n"); + break; + } + } + } + dStr_free(reply, 1); + } + } if (exit_error == 0){ /* Configure SSL to use network file descriptor */ @@ -263,6 +320,8 @@ static void yes_ssl_support(void) dFree(cmd); dFree(url); dFree(http_query); + dFree(proxy_url); + dFree(proxy_connect); if (network_socket != -1){ close(network_socket); @@ -297,6 +356,9 @@ static int get_network_connection(char * url) /*Determine how much of url we chop off as unneeded*/ if (dStrncasecmp(url, "https://", 8) == 0){ url_offset = 8; + } else if (dStrncasecmp(url, "http://", 7) == 0) { + url_offset = 7; + portnum = 80; } /*Find end of URL*/ diff --git a/src/IO/Url.h b/src/IO/Url.h index d57e9251..f144bfad 100644 --- a/src/IO/Url.h +++ b/src/IO/Url.h @@ -16,6 +16,8 @@ extern void a_Http_freeall(void); int a_Http_init(void); int a_Http_proxy_auth(void); void a_Http_set_proxy_passwd(const char *str); +char *a_Http_make_connect_str(const DilloUrl *url); +const char *a_Http_get_proxy_urlstr(); Dstr *a_Http_make_query_str(const DilloUrl *url, bool_t use_proxy); void a_Http_ccc (int Op, int Branch, int Dir, ChainLink *Info, diff --git a/src/IO/http.c b/src/IO/http.c index 55ba3502..ae87c8d0 100644 --- a/src/IO/http.c +++ b/src/IO/http.c @@ -16,6 +16,7 @@ #include <config.h> +#include <ctype.h> /* isdigit */ #include <unistd.h> #include <errno.h> /* for errno */ #include <stdlib.h> @@ -415,6 +416,56 @@ static int Http_must_use_proxy(const DilloUrl *url) } /* + * Return a new string for the request used to tunnel HTTPS through a proxy. + * As of 2009, the best reference appears to be section 5 of RFC 2817. + */ +char *a_Http_make_connect_str(const DilloUrl *url) +{ + Dstr *dstr; + const char *auth1; + int auth_len; + char *auth2, *proxy_auth, *retstr; + + dReturn_val_if_fail(Http_must_use_proxy(url), NULL); + + dstr = dStr_new(""); + auth1 = URL_AUTHORITY(url); + auth_len = strlen(auth1); + if (auth_len > 0 && !isdigit(auth1[auth_len - 1])) + /* if no port number, add HTTPS port */ + auth2 = dStrconcat(auth1, ":443", NULL); + else + auth2 = dStrdup(auth1); + proxy_auth = HTTP_Proxy_Auth_base64 ? + dStrconcat ("Proxy-Authorization: Basic ", + HTTP_Proxy_Auth_base64, "\r\n", NULL) : + dStrdup(""); + dStr_sprintfa( + dstr, + "CONNECT %s HTTP/1.1\r\n" + "Host: %s\r\n" + "%s" + "\r\n", + auth2, + auth2, + proxy_auth); + + dFree(auth2); + dFree(proxy_auth); + retstr = dstr->str; + dStr_free(dstr, 0); + return retstr; +} + +/* + * Return URL string of HTTP proxy, if any + */ +const char *a_Http_get_proxy_urlstr() +{ + return HTTP_Proxy ? URL_STR(HTTP_Proxy) : NULL; +} + +/* * Callback function for the DNS resolver. * Continue connecting the socket, or abort upon error condition. * S->web is checked to assert the operation wasn't aborted while waiting. @@ -265,7 +265,6 @@ static int Capi_url_uses_dpi(DilloUrl *url, char **server_ptr) /* * Build the dpip command tag, according to URL and server. - * TODO: make it PROXY-aware (AFAIS, it should be easy) */ static char *Capi_dpi_build_cmd(DilloWeb *web, char *server) { @@ -273,10 +272,20 @@ static char *Capi_dpi_build_cmd(DilloWeb *web, char *server) if (strcmp(server, "proto.https") == 0) { /* Let's be kind and make the HTTP query string for the dpi */ + char *proxy_connect = a_Http_make_connect_str(web->url); Dstr *http_query = a_Http_make_query_str(web->url, FALSE); /* BUG: embedded NULLs in query data will truncate message */ - cmd = a_Dpip_build_cmd("cmd=%s url=%s query=%s", - "open_url", URL_STR(web->url), http_query->str); + if (proxy_connect) { + const char *proxy_urlstr = a_Http_get_proxy_urlstr(); + cmd = a_Dpip_build_cmd("cmd=%s proxy_url=%s proxy_connect=%s " + "url=%s query=%s", "open_url", proxy_urlstr, + proxy_connect, URL_STR(web->url), + http_query->str); + } else { + cmd = a_Dpip_build_cmd("cmd=%s url=%s query=%s", + "open_url", URL_STR(web->url),http_query->str); + } + dFree(proxy_connect); dStr_free(http_query, 1); } else if (strcmp(server, "downloads") == 0) { |