From 79dbb537deded43a343d754169d819985e090a71 Mon Sep 17 00:00:00 2001 From: Jon goldberg Date: Tue, 25 Apr 2017 18:19:41 -0400 Subject: [PATCH 1/5] Include PEAR in README as a requirement --- README.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index d157c7a..74e6c6d 100644 --- a/README.md +++ b/README.md @@ -34,9 +34,9 @@ DISCLAIMER: This software has not (yet) been audited for security. The best option to install CiviProxy is a simple managed webspace, that you can rent cheaply from the hoster of your choice. It should have its own IP address, but other than that there are virtually no restrictions. This approach comes with a lot of advantages: 1. Since there are a multitude of clients like you on such a server, the level of security can be expected to be very high, and it should be managed and monitored by professionals 24/7. - + 2. For the same reason, the bandwith and connectivity of such a server should be very high as well. - + ### Installation @@ -53,15 +53,16 @@ The installation is as simple as it gets: There shouldn't be any requirements that any web hoster wouldn't comply with, but here they are: 1. PHP 5.3+ - 2. Read/write permissions on your webspace - 3. Reasonable amount of protection, i.e. only authorised users (you) can upload/download the files - 4. Ideally with it's own IP address (makes configuring the VPN easier) - + 2. PHP PEAR (to install on Debian/Ubunto, run `apt-get install php-pear`). + 3. Read/write permissions on your webspace + 4. Reasonable amount of protection, i.e. only authorised users (you) can upload/download the files + 5. Ideally with it's own IP address (makes configuring the VPN easier) + ## Why not an application firewall? The traditional approach to this problem would be an application firewall / reverse proxy setup. However, CiviCRM can have very complex interactions with other systems (e.g. via the API), and a malicious request can sometimes only be detected by understanding the meaning of the individual parameters. -Creating firewall rules for this level of detail is very complex and is very hard to maintain. +Creating firewall rules for this level of detail is very complex and is very hard to maintain. For this reason we wanted to take another approach and build a simple "bridgehead" system that *understands* CiviCRM, thus making its configuration and maintenance as easy as possible. From 32966f0802596065bd48f217a588e9e628997f9f Mon Sep 17 00:00:00 2001 From: Jon goldberg Date: Wed, 26 Apr 2017 15:54:13 -0400 Subject: [PATCH 2/5] check for a mosaico parameter; change URL if it's found; strip out chunked transfer header --- proxy/file.php | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/proxy/file.php b/proxy/file.php index 36684dd..d00d1bf 100644 --- a/proxy/file.php +++ b/proxy/file.php @@ -10,16 +10,17 @@ require_once "config.php"; require_once "proxy.php"; +// basic restraints +$valid_parameters = array( 'id' => 'string', 'mosaico' => 'int' ); +$parameters = civiproxy_get_parameters($valid_parameters); // see if file caching is enabled -if (!$target_file) civiproxy_http_error("Feature disabled", 405); +if ((!$target_file && !$parameters['mosaico']) || (!$target_mosaico_file && $parameters['mosaico'])) { + civiproxy_http_error("Feature disabled", 405); +} // basic check civiproxy_security_check('file'); -// basic restraints -$valid_parameters = array( 'id' => 'string' ); -$parameters = civiproxy_get_parameters($valid_parameters); - // check if id specified if (empty($parameters['id'])) civiproxy_http_error("Resource not found"); @@ -66,9 +67,13 @@ if ($header && $data) { print $data; exit(); } - // if we get here, we have a cache miss => load -$url = $target_file . $parameters['id']; +if ($parameters['mosaico'] == 1) { + $url = $target_mosaico_file . $parameters['id']; +} +else { + $url = $target_file . $parameters['id']; +} // error_log("CACHE MISS. LOADING $url"); $curlSession = curl_init(); @@ -92,7 +97,6 @@ if (curl_error($curlSession)) { error_log(curl_error($curlSession)); civiproxy_http_error(curl_error($curlSession), curl_errno($curlSession)); } - // process the results $content = explode("\r\n\r\n", $response, 2); $header = $content[0]; @@ -107,7 +111,9 @@ $file_cache->save($body, $data_key); // and reply foreach ($header_lines as $header_line) { - header($header_line); + if($header_line !== 'Transfer-Encoding: chunked ') { + header($header_line); + } } print $body; From 4fcf7cf6950e1cf7713dac4c5ef226091fa39fc4 Mon Sep 17 00:00:00 2001 From: Jon goldberg Date: Wed, 26 Apr 2017 15:55:24 -0400 Subject: [PATCH 3/5] Insert Mosaico target path into config.php --- proxy/config.php | 1 + 1 file changed, 1 insertion(+) diff --git a/proxy/config.php b/proxy/config.php index eeda1fc..57b8c9a 100644 --- a/proxy/config.php +++ b/proxy/config.php @@ -30,6 +30,7 @@ $target_url = $target_civicrm . '/sites/all/modules/civicrm/extern/url.php $target_open = $target_civicrm . '/sites/all/modules/civicrm/extern/open.php'; $target_file = $target_civicrm . '/sites/default/files/civicrm/persist/'; $target_mail_view = $target_civicrm . '/civicrm/mailing/view'; +$target_mosaico_file = $target_civicrm . '/civicrm/mosaico/img?src='; // Set api-key for mail subscribe/unsubscribe user // Set to NULL/FALSE to disable the feature From cd4c59a691b80e419fbb62439d2dc95e470f63f3 Mon Sep 17 00:00:00 2001 From: Jon goldberg Date: Wed, 26 Apr 2017 15:58:56 -0400 Subject: [PATCH 4/5] Encode Mosaico images properly in the Civi extension --- de.systopia.civiproxy/CRM/Civiproxy/Mailer.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/de.systopia.civiproxy/CRM/Civiproxy/Mailer.php b/de.systopia.civiproxy/CRM/Civiproxy/Mailer.php index f62eb9e..15ed411 100644 --- a/de.systopia.civiproxy/CRM/Civiproxy/Mailer.php +++ b/de.systopia.civiproxy/CRM/Civiproxy/Mailer.php @@ -55,7 +55,8 @@ class CRM_Civiproxy_Mailer { // General external functions $value = preg_replace("#{$system_base}sites/all/modules/civicrm/extern/url.php#i", $proxy_base.'/url.php', $value); $value = preg_replace("#{$system_base}sites/all/modules/civicrm/extern/open.php#i", $proxy_base.'/open.php', $value); - $value = preg_replace("#{$system_base}sites/default/files/civicrm/persist/#i", $proxy_base.'/file.php?id=', $value); + $value = preg_replace("#{$system_base}sites/default/files/civicrm/persist/#i", $proxy_base.'/file.php?mosaico=0&id=', $value); + $value = preg_replace("#{$system_base}civicrm/mosaico/img\?src=#i", $proxy_base.'/file.php?mosaico=1&id=', $value); // Mailing related functions $value = preg_replace("#{$system_base}civicrm/mailing/view#i", $proxy_base.'/mailing/mail.php', $value); From fed7a8ee7a0dba1774f7585bd61207d197f971bc Mon Sep 17 00:00:00 2001 From: Jon goldberg Date: Wed, 26 Apr 2017 16:51:59 -0400 Subject: [PATCH 5/5] Remove chunked transfer encoding header BEFORE saving to cache --- proxy/file.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/proxy/file.php b/proxy/file.php index d00d1bf..fa52084 100644 --- a/proxy/file.php +++ b/proxy/file.php @@ -6,7 +6,6 @@ | Author: B. Endres (endres -at- systopia.de) | | http://www.systopia.de/ | +---------------------------------------------------------*/ - require_once "config.php"; require_once "proxy.php"; @@ -105,15 +104,20 @@ $body = $content[1]; // extract headers $header_lines = explode(chr(10), $header); +// Remove chunked encoding header +foreach ($header_lines as $k => $header_line) { + if(strpos($header_line,'Transfer-Encoding: chunked') !== FALSE) { + unset($header_lines[$k]); + } +} + // store the information in the cache $file_cache->save(json_encode($header_lines), $header_key); $file_cache->save($body, $data_key); // and reply foreach ($header_lines as $header_line) { - if($header_line !== 'Transfer-Encoding: chunked ') { - header($header_line); - } + header($header_line); } print $body;