implementing #16
This commit is contained in:
parent
053c3f5fb9
commit
3c825a8f55
|
|
@ -38,7 +38,7 @@ $mail_subscription_user_key = NULL;
|
||||||
// CAREFUL: only enable temporarily on debug systems. Will log all queries to given PUBLIC file
|
// CAREFUL: only enable temporarily on debug systems. Will log all queries to given PUBLIC file
|
||||||
$debug = NULL; //'debug.log';
|
$debug = NULL; //'debug.log';
|
||||||
|
|
||||||
// Local network interface or IP to be used for the relayed query
|
// Local network interface or IP to be used for the relayed query
|
||||||
// This is usefull in some VPN configurations (see CURLOPT_INTERFACE)
|
// This is usefull in some VPN configurations (see CURLOPT_INTERFACE)
|
||||||
$target_interface = NULL;
|
$target_interface = NULL;
|
||||||
|
|
||||||
|
|
@ -91,6 +91,10 @@ $rest_allowed_actions = array(
|
||||||
'getsingle' => array(
|
'getsingle' => array(
|
||||||
'first_name' => 'string',
|
'first_name' => 'string',
|
||||||
'last_name' => 'string',
|
'last_name' => 'string',
|
||||||
|
// the following means *all* remaining parameters will be
|
||||||
|
// added and sanitised as 'string'. Better leave it out
|
||||||
|
// if you know which parameters you expect
|
||||||
|
'*' => 'string',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
128
proxy/proxy.php
128
proxy/proxy.php
|
|
@ -14,10 +14,10 @@ $civiproxy_logo = "<img src='{$proxy_base}/static/images/proxy-logo.png' alt=
|
||||||
/**
|
/**
|
||||||
* this will redirect the request to another URL,
|
* this will redirect the request to another URL,
|
||||||
* i.e. will pass the reply on to this request
|
* i.e. will pass the reply on to this request
|
||||||
*
|
*
|
||||||
* @see losely based on https://code.google.com/p/php-proxy/
|
* @see losely based on https://code.google.com/p/php-proxy/
|
||||||
*
|
*
|
||||||
* @param $url the URL to which the
|
* @param $url the URL to which the
|
||||||
* where type can be 'int', 'string' (unchecked),
|
* where type can be 'int', 'string' (unchecked),
|
||||||
*/
|
*/
|
||||||
function civiproxy_redirect($url_requested, $parameters) {
|
function civiproxy_redirect($url_requested, $parameters) {
|
||||||
|
|
@ -58,8 +58,8 @@ function civiproxy_redirect($url_requested, $parameters) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//Send the request and store the result in an array
|
//Send the request and store the result in an array
|
||||||
$response = curl_exec($curlSession);
|
$response = curl_exec($curlSession);
|
||||||
|
|
||||||
// Check that a connection was made
|
// Check that a connection was made
|
||||||
if (curl_error($curlSession)){
|
if (curl_error($curlSession)){
|
||||||
civiproxy_http_error(curl_error($curlSession), curl_errno($curlSession));
|
civiproxy_http_error(curl_error($curlSession), curl_errno($curlSession));
|
||||||
|
|
@ -67,7 +67,7 @@ function civiproxy_redirect($url_requested, $parameters) {
|
||||||
} else {
|
} else {
|
||||||
//clean duplicate header that seems to appear on fastcgi with output buffer on some servers!!
|
//clean duplicate header that seems to appear on fastcgi with output buffer on some servers!!
|
||||||
$response = str_replace("HTTP/1.1 100 Continue\r\n\r\n","",$response);
|
$response = str_replace("HTTP/1.1 100 Continue\r\n\r\n","",$response);
|
||||||
|
|
||||||
// split header / content
|
// split header / content
|
||||||
$content = explode("\r\n\r\n", $response, 2);
|
$content = explode("\r\n\r\n", $response, 2);
|
||||||
$header = $content[0];
|
$header = $content[0];
|
||||||
|
|
@ -103,25 +103,25 @@ function civiproxy_mend_URLs(&$string) {
|
||||||
$string = preg_replace("#$target_rest#", $proxy_base . '/rest.php', $string);
|
$string = preg_replace("#$target_rest#", $proxy_base . '/rest.php', $string);
|
||||||
}
|
}
|
||||||
if ($target_url) {
|
if ($target_url) {
|
||||||
$string = preg_replace("#$target_url#", $proxy_base . '/url.php', $string);
|
$string = preg_replace("#$target_url#", $proxy_base . '/url.php', $string);
|
||||||
}
|
}
|
||||||
if ($target_open) {
|
if ($target_open) {
|
||||||
$string = preg_replace("#$target_open#", $proxy_base . '/open.php', $string);
|
$string = preg_replace("#$target_open#", $proxy_base . '/open.php', $string);
|
||||||
}
|
}
|
||||||
if ($target_mail) {
|
if ($target_mail) {
|
||||||
$string = preg_replace("#$target_mail#", $proxy_base . '/mail.php', $string);
|
$string = preg_replace("#$target_mail#", $proxy_base . '/mail.php', $string);
|
||||||
}
|
}
|
||||||
if ($target_file) {
|
if ($target_file) {
|
||||||
$string = preg_replace("#$target_file#", $proxy_base . '/file.php?id=', $string);
|
$string = preg_replace("#$target_file#", $proxy_base . '/file.php?id=', $string);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will check the incoming connection.
|
* Will check the incoming connection.
|
||||||
* This hook allowes for (future) checks for flooding, spoofing,
|
* This hook allowes for (future) checks for flooding, spoofing,
|
||||||
* unauthorized access quantities, etc.
|
* unauthorized access quantities, etc.
|
||||||
*
|
*
|
||||||
* @param $target
|
* @param $target
|
||||||
* @param $quit if TRUE, quit immediately if access denied
|
* @param $quit if TRUE, quit immediately if access denied
|
||||||
*
|
*
|
||||||
* @return TRUE if allowed, FALSE if not (or quits if $quit is set)
|
* @return TRUE if allowed, FALSE if not (or quits if $quit is set)
|
||||||
|
|
@ -130,7 +130,7 @@ function civiproxy_security_check($target, $quit=TRUE) {
|
||||||
// verify that we're SSL encrypted
|
// verify that we're SSL encrypted
|
||||||
if ($_SERVER['HTTPS'] != "on") {
|
if ($_SERVER['HTTPS'] != "on") {
|
||||||
civiproxy_http_error("This CiviProxy installation requires SSL encryption.", 400);
|
civiproxy_http_error("This CiviProxy installation requires SSL encryption.", 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
global $debug;
|
global $debug;
|
||||||
if (!empty($debug)) {
|
if (!empty($debug)) {
|
||||||
|
|
@ -138,7 +138,7 @@ function civiproxy_security_check($target, $quit=TRUE) {
|
||||||
fwrite($file, "REQUEST FROM " . $_SERVER['REMOTE_ADDR'] . " ON " . date('Y-m-d H:i:s') . ' -- ' . print_r($_REQUEST,1));
|
fwrite($file, "REQUEST FROM " . $_SERVER['REMOTE_ADDR'] . " ON " . date('Y-m-d H:i:s') . ' -- ' . print_r($_REQUEST,1));
|
||||||
fclose($file);
|
fclose($file);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: implement
|
// TODO: implement
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
@ -146,57 +146,81 @@ function civiproxy_security_check($target, $quit=TRUE) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* extract and type check the parameters from the call params
|
* extract and type check the parameters from the call params
|
||||||
*
|
*
|
||||||
* @param $valid_parameters array '<parameter name> => '<expected type>'
|
* @param $valid_parameters array '<parameter name> => '<expected type>'
|
||||||
* where type can be 'int', 'string' (unchecked),
|
* where type can be 'int', 'string' (unchecked),
|
||||||
*/
|
*/
|
||||||
function civiproxy_get_parameters($valid_parameters) {
|
function civiproxy_get_parameters($valid_parameters) {
|
||||||
$result = array();
|
$result = array();
|
||||||
|
$default_sanitation = NULL;
|
||||||
|
|
||||||
foreach ($valid_parameters as $name => $type) {
|
foreach ($valid_parameters as $name => $type) {
|
||||||
|
if ($name == '*') {
|
||||||
|
// this sets default_sanitation
|
||||||
|
$default_sanitation = $type;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (isset($_REQUEST[$name])) {
|
if (isset($_REQUEST[$name])) {
|
||||||
$value = $_REQUEST[$name];
|
$result[$name] = civiproxy_sanitise($_REQUEST[$name], $type);
|
||||||
if ($type=='int') {
|
}
|
||||||
$value = (int) $value;
|
}
|
||||||
} elseif ($type == 'string') {
|
|
||||||
// TODO: sanitize? SQL?
|
// process wildcard elements
|
||||||
$value = $value;
|
if ($default_sanitation !== NULL) {
|
||||||
} elseif ($type == 'float2') {
|
// i.e. we want the others too
|
||||||
// TODO: check if safe wrt l10n. rather use sprintf
|
$remove_parameters = array('key', 'api_key', 'version', 'entity', 'action');
|
||||||
$value = number_format($value, 2, '.', '');
|
foreach ($_REQUEST as $name => $value) {
|
||||||
} elseif ($type == 'hex') {
|
if (!in_array($name, $remove_parameters) && !isset($valid_parameters[$name])) {
|
||||||
// hex code
|
$result[$name] = civiproxy_sanitise($value, $default_sanitation);
|
||||||
if (!preg_match("#^[0-9a-f]*$#i", $value)) {
|
|
||||||
error_log("CiviProxy: removed invalid hex parameter: " . $value);
|
|
||||||
$value = '';
|
|
||||||
}
|
|
||||||
} elseif ($type == 'email') {
|
|
||||||
// valid email
|
|
||||||
if (!preg_match("#^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$#i", $value)) {
|
|
||||||
error_log("CiviProxy: removed invalid email parameter: " . $value);
|
|
||||||
$value = '';
|
|
||||||
}
|
|
||||||
} elseif (is_array($type)) {
|
|
||||||
// this is a list of valid options
|
|
||||||
$requested_value = $value;
|
|
||||||
$value = '';
|
|
||||||
foreach ($type as $allowed_value) {
|
|
||||||
if ($requested_value === $allowed_value) {
|
|
||||||
$value = $requested_value;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
error_log("CiviProxy: unknown type '$type'. Ignored.");
|
|
||||||
$value = '';
|
|
||||||
}
|
}
|
||||||
$result[$name] = $value;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sanitise the given value with the given sanitiation type
|
||||||
|
*/
|
||||||
|
function civiproxy_sanitise($value, $type) {
|
||||||
|
if ($type=='int') {
|
||||||
|
$value = (int) $value;
|
||||||
|
} elseif ($type == 'string') {
|
||||||
|
// TODO: sanitize? SQL?
|
||||||
|
$value = $value;
|
||||||
|
} elseif ($type == 'float2') {
|
||||||
|
// TODO: check if safe wrt l10n. rather use sprintf
|
||||||
|
$value = number_format($value, 2, '.', '');
|
||||||
|
} elseif ($type == 'hex') {
|
||||||
|
// hex code
|
||||||
|
if (!preg_match("#^[0-9a-f]*$#i", $value)) {
|
||||||
|
error_log("CiviProxy: removed invalid hex parameter: " . $value);
|
||||||
|
$value = '';
|
||||||
|
}
|
||||||
|
} elseif ($type == 'email') {
|
||||||
|
// valid email
|
||||||
|
if (!preg_match("#^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$#i", $value)) {
|
||||||
|
error_log("CiviProxy: removed invalid email parameter: " . $value);
|
||||||
|
$value = '';
|
||||||
|
}
|
||||||
|
} elseif (is_array($type)) {
|
||||||
|
// this is a list of valid options
|
||||||
|
$requested_value = $value;
|
||||||
|
$value = '';
|
||||||
|
foreach ($type as $allowed_value) {
|
||||||
|
if ($requested_value === $allowed_value) {
|
||||||
|
$value = $requested_value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error_log("CiviProxy: unknown type '$type'. Ignored.");
|
||||||
|
$value = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* generates a CiviCRM REST API compliant error
|
* generates a CiviCRM REST API compliant error
|
||||||
* and ends processing
|
* and ends processing
|
||||||
|
|
@ -224,7 +248,7 @@ function civicrm_api3($entity, $action, $data) {
|
||||||
// extract site key
|
// extract site key
|
||||||
$site_keys = array_values($sys_key_map);
|
$site_keys = array_values($sys_key_map);
|
||||||
if (empty($site_keys)) civiproxy_http_error('No site key set.');
|
if (empty($site_keys)) civiproxy_http_error('No site key set.');
|
||||||
|
|
||||||
$query = $data; // array copy(!)
|
$query = $data; // array copy(!)
|
||||||
$query['key'] = $site_keys[0];
|
$query['key'] = $site_keys[0];
|
||||||
$query['json'] = 1;
|
$query['json'] = 1;
|
||||||
|
|
@ -247,7 +271,7 @@ function civicrm_api3($entity, $action, $data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
$response = curl_exec($curlSession);
|
$response = curl_exec($curlSession);
|
||||||
|
|
||||||
if (curl_error($curlSession)){
|
if (curl_error($curlSession)){
|
||||||
civiproxy_http_error(curl_error($curlSession));
|
civiproxy_http_error(curl_error($curlSession));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ if (empty($credentials['api_key'])) {
|
||||||
// check if the call itself is allowed
|
// check if the call itself is allowed
|
||||||
$action = civiproxy_get_parameters(array('entity' => 'string', 'action' => 'string', 'version' => 'int', 'json' => 'int', 'sequential' => 'int'));
|
$action = civiproxy_get_parameters(array('entity' => 'string', 'action' => 'string', 'version' => 'int', 'json' => 'int', 'sequential' => 'int'));
|
||||||
if (!isset($action['version']) || $action['version'] != 3) {
|
if (!isset($action['version']) || $action['version'] != 3) {
|
||||||
civiproxy_rest_error("Invalid entity/action.");
|
civiproxy_rest_error("API 'version' information missing.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// in release 0.4, allowed entity/actions per IP were introduced. To introduce backward compatibility,
|
// in release 0.4, allowed entity/actions per IP were introduced. To introduce backward compatibility,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue