aboutsummaryrefslogtreecommitdiff
path: root/dpi/https.c
diff options
context:
space:
mode:
Diffstat (limited to 'dpi/https.c')
-rw-r--r--dpi/https.c247
1 files changed, 163 insertions, 84 deletions
diff --git a/dpi/https.c b/dpi/https.c
index 00ceb0c1..3f474b81 100644
--- a/dpi/https.c
+++ b/dpi/https.c
@@ -25,7 +25,7 @@
* the https dillo plugin with the OpenSSL project's "OpenSSL"
* library, and distribute the linked executables, without including
* the source code for OpenSSL in the source distribution. You must
- * obey the GNU General Public License, version 2, in all respects
+ * obey the GNU General Public License, version 3, in all respects
* for all of the code used other than "OpenSSL".
*
*/
@@ -64,12 +64,15 @@
/*
* Debugging macros
*/
+#define SILENT 1
#define _MSG(...)
-#define MSG(...) printf("[https dpi]: " __VA_ARGS__)
+#if SILENT
+ #define MSG(...)
+#else
+ #define MSG(...) fprintf(stderr, "[https dpi]: " __VA_ARGS__)
+#endif
-#define ENABLE_SSL
-#undef ENABLE_SSL
#ifdef ENABLE_SSL
#include <openssl/ssl.h>
@@ -88,7 +91,7 @@ static int save_certificate_home(X509 * cert);
* Global variables
*/
static char *root_url = NULL; /*Holds the URL we are connecting to*/
-static SockHandler *sh;
+static Dsh *sh;
#ifdef ENABLE_SSL
@@ -104,8 +107,8 @@ static int dialog_get_answer_number(void)
char *dpip_tag, *response;
/* Read the dpi command from STDIN */
- dpip_tag = sock_handler_read(sh);
- response = a_Dpip_get_attr(dpip_tag, strlen(dpip_tag), "msg");
+ dpip_tag = a_Dpip_dsh_read_token(sh, 1);
+ response = a_Dpip_get_attr(dpip_tag, "msg");
response_number = (response) ? strtol (response, NULL, 10) : -1;
dFree(dpip_tag);
dFree(response);
@@ -126,9 +129,10 @@ 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 ret = 0;
int network_socket = -1;
@@ -189,10 +193,13 @@ static void yes_ssl_support(void)
SSL_set_verify(ssl_connection, SSL_VERIFY_NONE, 0);
/*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");
- url = a_Dpip_get_attr(dpip_tag, strlen(dpip_tag), "url");
- http_query = a_Dpip_get_attr(dpip_tag, strlen(dpip_tag), "query");
+ dpip_tag = a_Dpip_dsh_read_token(sh, 1);
+ cmd = a_Dpip_get_attr(dpip_tag, "cmd");
+ proxy_url = a_Dpip_get_attr(dpip_tag, "proxy_url");
+ proxy_connect =
+ a_Dpip_get_attr(dpip_tag, "proxy_connect");
+ url = a_Dpip_get_attr(dpip_tag, "url");
+ http_query = a_Dpip_get_attr(dpip_tag, "query");
if (cmd == NULL || url == NULL || http_query == NULL){
MSG("***Value of cmd, url or http_query is NULL"
@@ -202,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 */
@@ -244,14 +304,14 @@ static void yes_ssl_support(void)
/*Send dpi command*/
d_cmd = a_Dpip_build_cmd("cmd=%s url=%s", "start_send_page", url);
- sock_handler_write_str(sh, 1, d_cmd);
+ a_Dpip_dsh_write_str(sh, 1, d_cmd);
dFree(d_cmd);
/*Send remaining data*/
- while ((retval = SSL_read(ssl_connection, buf, 4096)) > 0 ){
+ while ((ret = SSL_read(ssl_connection, buf, 4096)) > 0 ){
/* flush is good for dialup speed */
- sock_handler_write(sh, 1, buf, (size_t)retval);
+ a_Dpip_dsh_write(sh, 1, buf, (size_t)ret);
}
}
@@ -260,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);
@@ -288,12 +350,15 @@ static int get_network_connection(char * url)
int s;
int url_offset = 0;
int portnum = 443;
- unsigned int url_look_up_length = 0;
+ uint_t url_look_up_length = 0;
char * url_look_up = NULL;
/*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*/
@@ -305,7 +370,7 @@ static int get_network_connection(char * url)
/*Check for port number*/
if (strchr(url+url_offset, ':') ==
(url + url_offset + url_look_up_length)){
- portnum = atoi(url + url_offset + url_look_up_length + 1);
+ portnum = strtol(url + url_offset + url_look_up_length + 1, NULL, 10);
}
} else {
url_look_up = url + url_offset;
@@ -314,7 +379,7 @@ static int get_network_connection(char * url)
root_url = dStrdup(url_look_up);
hp=gethostbyname(url_look_up);
- /*url_look_uip no longer needed, so free if neccessary*/
+ /*url_look_uip no longer needed, so free if necessary*/
if (url_look_up_length != 0){
dFree(url_look_up);
}
@@ -349,9 +414,9 @@ static int get_network_connection(char * url)
static int handle_certificate_problem(SSL * ssl_connection)
{
int response_number;
- int retval = -1;
+ int ret = -1;
long st;
- char *cn, *cn_end;
+ char *cn;
char buf[4096], *d_cmd, *msg;
X509 * remote_cert;
@@ -366,7 +431,7 @@ static int handle_certificate_problem(SSL * ssl_connection)
"This site CAN NOT be trusted. Sending data is NOT SAFE.\n"
"What do I do?",
"Continue", "Cancel");
- sock_handler_write_str(sh, 1, d_cmd);
+ a_Dpip_dsh_write_str(sh, 1, d_cmd);
dFree(d_cmd);
/*Read the user's response*/
@@ -374,7 +439,7 @@ static int handle_certificate_problem(SSL * ssl_connection)
/*Abort on anything but "Continue"*/
if (response_number == 1){
- retval = 0;
+ ret = 0;
}
} else {
@@ -382,36 +447,37 @@ static int handle_certificate_problem(SSL * ssl_connection)
st = SSL_get_verify_result(ssl_connection);
switch (st) {
case X509_V_OK: /*Everything is Kosher*/
- retval = 0;
+ ret = 0;
break;
case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
/*Either self signed and untrusted*/
/*Extract CN from certificate name information*/
- cn = strstr(remote_cert->name, "/CN=") + 4;
- if (cn == NULL)
- break;
-
- if ((cn_end = strstr(cn, "/")) == NULL )
- cn_end = cn + strlen(cn);
+ if ((cn = strstr(remote_cert->name, "/CN=")) == NULL) {
+ strcpy(buf, "(no CN given)");
+ } else {
+ char *cn_end;
- strncpy(buf, cn, (size_t) (cn_end - cn));
+ cn += 4;
- /*Add terminating NULL*/
- buf[cn_end - cn] = 0;
+ if ((cn_end = strstr(cn, "/")) == NULL )
+ cn_end = cn + strlen(cn);
+ strncpy(buf, cn, (size_t) (cn_end - cn));
+ buf[cn_end - cn] = '\0';
+ }
msg = dStrconcat("The remote certificate is self-signed and "
"untrusted.\nFor address: ", buf, NULL);
d_cmd = a_Dpip_build_cmd(
"cmd=%s msg=%s alt1=%s alt2=%s alt3=%s",
- "dialog", msg, "Continue", "Cancel", "Trust Certificate");
- sock_handler_write_str(sh, 1, d_cmd);
+ "dialog", msg, "Continue", "Cancel", "Save Certificate");
+ a_Dpip_dsh_write_str(sh, 1, d_cmd);
dFree(d_cmd);
dFree(msg);
response_number = dialog_get_answer_number();
switch (response_number){
case 1:
- retval = 0;
+ ret = 0;
break;
case 2:
break;
@@ -420,7 +486,7 @@ static int handle_certificate_problem(SSL * ssl_connection)
/*Potential security problems because we are writing
*to the filesystem*/
save_certificate_home(remote_cert);
- retval = 1;
+ ret = 1;
break;
default:
break;
@@ -434,12 +500,12 @@ static int handle_certificate_problem(SSL * ssl_connection)
"The issuer for the remote certificate cannot be found\n"
"The authenticity of the remote certificate cannot be trusted",
"Continue", "Cancel");
- sock_handler_write_str(sh, 1, d_cmd);
+ a_Dpip_dsh_write_str(sh, 1, d_cmd);
dFree(d_cmd);
response_number = dialog_get_answer_number();
if (response_number == 1) {
- retval = 0;
+ ret = 0;
}
break;
@@ -453,12 +519,12 @@ static int handle_certificate_problem(SSL * ssl_connection)
"The remote certificate signature could not be read\n"
"or is invalid and should not be trusted",
"Continue", "Cancel");
- sock_handler_write_str(sh, 1, d_cmd);
+ a_Dpip_dsh_write_str(sh, 1, d_cmd);
dFree(d_cmd);
response_number = dialog_get_answer_number();
if (response_number == 1) {
- retval = 0;
+ ret = 0;
}
break;
case X509_V_ERR_CERT_NOT_YET_VALID:
@@ -472,12 +538,12 @@ static int handle_certificate_problem(SSL * ssl_connection)
"presented has a starting validity after today's date\n"
"You should be cautious about using this site",
"Continue", "Cancel");
- sock_handler_write_str(sh, 1, d_cmd);
+ a_Dpip_dsh_write_str(sh, 1, d_cmd);
dFree(d_cmd);
response_number = dialog_get_answer_number();
if (response_number == 1) {
- retval = 0;
+ ret = 0;
}
break;
case X509_V_ERR_CERT_HAS_EXPIRED:
@@ -489,11 +555,11 @@ static int handle_certificate_problem(SSL * ssl_connection)
"wasn't designed to last this long. You should avoid \n"
"this site.",
"Continue", "Cancel");
- sock_handler_write_str(sh, 1, d_cmd);
+ a_Dpip_dsh_write_str(sh, 1, d_cmd);
dFree(d_cmd);
response_number = dialog_get_answer_number();
if (response_number == 1) {
- retval = 0;
+ ret = 0;
}
break;
case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
@@ -508,11 +574,11 @@ static int handle_certificate_problem(SSL * ssl_connection)
"making it impossible to determine if the certificate\n"
"is valid. You should not trust this certificate.",
"Continue", "Cancel");
- sock_handler_write_str(sh, 1, d_cmd);
+ a_Dpip_dsh_write_str(sh, 1, d_cmd);
dFree(d_cmd);
response_number = dialog_get_answer_number();
if (response_number == 1) {
- retval = 0;
+ ret = 0;
}
break;
case X509_V_ERR_INVALID_CA:
@@ -528,11 +594,11 @@ static int handle_certificate_problem(SSL * ssl_connection)
"with the remote system. The connection should not\n"
"be trusted",
"Continue", "Cancel");
- sock_handler_write_str(sh, 1, d_cmd);
+ a_Dpip_dsh_write_str(sh, 1, d_cmd);
dFree(d_cmd);
response_number = dialog_get_answer_number();
if (response_number == 1) {
- retval = 0;
+ ret = 0;
}
break;
case X509_V_ERR_SUBJECT_ISSUER_MISMATCH:
@@ -543,9 +609,9 @@ static int handle_certificate_problem(SSL * ssl_connection)
"dialog",
"Some of the information presented by the remote system\n"
"does not match other information presented\n"
- "This may be an attempt to evesdrop on communications",
+ "This may be an attempt to eavesdrop on communications",
"Continue", "Cancel");
- sock_handler_write_str(sh, 1, d_cmd);
+ a_Dpip_dsh_write_str(sh, 1, d_cmd);
dFree(d_cmd);
default: /*Need to add more options later*/
snprintf(buf, 80,
@@ -553,19 +619,19 @@ static int handle_certificate_problem(SSL * ssl_connection)
d_cmd = a_Dpip_build_cmd(
"cmd=%s msg=%s alt1=%s alt2=%s",
"dialog", buf, "Continue", "Cancel");
- sock_handler_write_str(sh, 1, d_cmd);
+ a_Dpip_dsh_write_str(sh, 1, d_cmd);
dFree(d_cmd);
response_number = dialog_get_answer_number();
/*abort on anything but "Continue"*/
if (response_number == 1){
- retval = 0;
+ ret = 0;
}
}
X509_free(remote_cert);
remote_cert = 0;
}
- return retval;
+ return ret;
}
/*
@@ -577,8 +643,8 @@ static int save_certificate_home(X509 * cert)
char buf[4096];
FILE * fp = NULL;
- unsigned int i = 0;
- int retval = 1;
+ uint_t i = 0;
+ int ret = 1;
/*Attempt to create .dillo/certs blindly - check later*/
snprintf(buf,4096,"%s/.dillo/", dGethomedir());
@@ -586,7 +652,7 @@ static int save_certificate_home(X509 * cert)
snprintf(buf,4096,"%s/.dillo/certs/", dGethomedir());
mkdir(buf, 01777);
- do{
+ do {
snprintf(buf, 4096, "%s/.dillo/certs/%lx.%u",
dGethomedir(), X509_subject_name_hash(cert), i);
@@ -601,7 +667,7 @@ static int save_certificate_home(X509 * cert)
PEM_write_X509(fp, cert);
fclose(fp);
MSG("Wrote certificate\n");
- retval = 0;
+ ret = 0;
break;
}
} else {
@@ -609,9 +675,9 @@ static int save_certificate_home(X509 * cert)
}
i++;
/*Don't loop too many times - just give up*/
- } while( i < 1024 );
+ } while (i < 1024);
- return retval;
+ return ret;
}
@@ -629,14 +695,14 @@ static void no_ssl_support(void)
char *d_cmd;
/* Read the dpi command from STDIN */
- dpip_tag = sock_handler_read(sh);
+ dpip_tag = a_Dpip_dsh_read_token(sh, 1);
MSG("{In https.filter.dpi}\n");
MSG("no_ssl_support version\n");
- cmd = a_Dpip_get_attr(dpip_tag, strlen(dpip_tag), "cmd");
- url = a_Dpip_get_attr(dpip_tag, strlen(dpip_tag), "url");
- http_query = a_Dpip_get_attr(dpip_tag, strlen(dpip_tag), "query");
+ cmd = a_Dpip_get_attr(dpip_tag, "cmd");
+ url = a_Dpip_get_attr(dpip_tag, "url");
+ http_query = a_Dpip_get_attr(dpip_tag, "query");
MSG("{ cmd: %s}\n", cmd);
MSG("{ url: %s}\n", url);
@@ -645,33 +711,35 @@ static void no_ssl_support(void)
MSG("{ sending dpip cmd...}\n");
d_cmd = a_Dpip_build_cmd("cmd=%s url=%s", "start_send_page", url);
- sock_handler_write_str(sh, 1, d_cmd);
+ a_Dpip_dsh_write_str(sh, 1, d_cmd);
dFree(d_cmd);
MSG("{ dpip cmd sent.}\n");
MSG("{ sending HTML...}\n");
- sock_handler_printf(sh, 1,
+ a_Dpip_dsh_printf(sh, 1,
"Content-type: text/html\n\n"
"<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'>\n"
- "<html><body><pre>\n"
- "<b>Hi!\n\n"
- " This is the https dpi that just got a request to send\n"
- " the following HTTP query:\n{</b>\n"
- "<code>%s</code>\n"
- "<b>}</b>\n\n"
- " <b>*** Dillo's prototype plugin for https support"
- " is disabled now ***</b>\n\n"
- " If you want to test this <b>alpha</b> support code, just remove\n"
- " line 72 from dpi/https.c, recompile and reinstall.\n\n"
- " (beware that this https support is very limited now)\n\n"
+ "<html><head><title>SSL support is disabled</title></head>\n"
+ "<body>\n"
+ "<p>\n"
+ " The https dpi was unable to send\n"
+ " the following HTTP query:\n"
+ " <blockquote><pre>%s</pre></blockquote>\n"
+ " because Dillo's prototype plugin for https support"
+ " is disabled.\n\n"
+ "<p>\n"
+ " If you want to test this <b>alpha</b> support code,\n"
+ " just reconfigure with <code>--enable-ssl</code>,\n"
+ " recompile and reinstall.\n\n"
+ " (Beware that this https support is very limited now)\n\n"
" To use https and SSL, you must have \n"
" the OpenSSL development libraries installed. Check your\n"
" O/S distribution provider, or check out\n"
- " <a href=\"http://www.openssl.org\">www.openssl.org</a>\n\n"
- " --\n"
- "</pre></body></html>\n",
+ " <a href=\"http://www.openssl.org\">www.openssl.org</a>.\n\n"
+ "</p>\n\n"
+ "</body></html>\n",
http_query
);
MSG("{ HTML content sent.}\n");
@@ -691,8 +759,19 @@ static void no_ssl_support(void)
/*---------------------------------------------------------------------------*/
int main(void)
{
+ char *dpip_tag;
+
/* Initialize the SockHandler for this filter dpi */
- sh = sock_handler_new(STDIN_FILENO, STDOUT_FILENO, 8*1024);
+ sh = a_Dpip_dsh_new(STDIN_FILENO, STDOUT_FILENO, 8*1024);
+
+ /* Authenticate our client... */
+ if (!(dpip_tag = a_Dpip_dsh_read_token(sh, 1)) ||
+ a_Dpip_check_auth(dpip_tag) < 0) {
+ MSG("can't authenticate request: %s\n", dStrerror(errno));
+ a_Dpip_dsh_close(sh);
+ return 1;
+ }
+ dFree(dpip_tag);
#ifdef ENABLE_SSL
yes_ssl_support();
@@ -701,8 +780,8 @@ int main(void)
#endif
/* Finish the SockHandler */
- sock_handler_close(sh);
- sock_handler_free(sh);
+ a_Dpip_dsh_close(sh);
+ a_Dpip_dsh_free(sh);
dFree(root_url);