diff options
author | Johannes Hofmann <Johannes.Hofmann@gmx.de> | 2010-08-20 23:24:19 +0200 |
---|---|---|
committer | Johannes Hofmann <Johannes.Hofmann@gmx.de> | 2010-08-20 23:24:19 +0200 |
commit | f5c598b518d1f906148534d015f50075d3e8242d (patch) | |
tree | 21dd70add5b366c3dd80641b77f6b18e0baa009e /dpi/https.c | |
parent | e98d02a01ffeb18ede86af025e51ae1ec011c75a (diff) | |
parent | 5f0fc0e48b8cbee7e1795935da0abff6627fd498 (diff) |
merge
Diffstat (limited to 'dpi/https.c')
-rw-r--r-- | dpi/https.c | 247 |
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); |