aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engine/lib/actions.php83
-rw-r--r--languages/en.php9
-rw-r--r--views/default/input/button.php2
-rw-r--r--views/default/input/form.php17
4 files changed, 104 insertions, 7 deletions
diff --git a/engine/lib/actions.php b/engine/lib/actions.php
index 682e13b55..0779e5d6a 100644
--- a/engine/lib/actions.php
+++ b/engine/lib/actions.php
@@ -107,6 +107,89 @@
function actions_init($event, $object_type, $object) {
register_action("error");
return true;
+ }
+
+ /**
+ * Action gatekeeper.
+ * This function verifies form input for security features (like a generated token), and forwards
+ * the page if they are invalid.
+ *
+ * Place at the head of actions.
+ */
+ function action_gatekeeper()
+ {
+ $token = get_input('__elgg_token');
+ $action = get_input('__elgg_action');
+ $ts = get_input('__elgg_ts');
+ $session_id = session_id();
+
+ if (($token) && ($action) && ($ts) && ($session_id))
+ {
+ // generate token, check with input and forward if invalid
+ $generated_token = generate_action_token($action, $ts);
+
+ // Validate token
+ if (strcmp($token, $generated_token)==0)
+ {
+
+ // TODO: Validate time to ensure its not crazy
+
+
+ return true;
+ }
+ else
+ register_error(elgg_echo('actiongatekeeper:tokeninvalid'));
+ }
+ else
+ register_error(elgg_echo('actiongatekeeper:missingfields'));
+
+ forward();
+ exit;
+ }
+
+ /**
+ * Generate a token for the current user suitable for being placed in a hidden field in action forms.
+ *
+ * @param string $action The action being called
+ * @param int $timestamp Unix timestamp
+ */
+ function generate_action_token($action, $timestamp)
+ {
+ // Get input values
+ $site_secret = get_site_secret();
+
+ // Current session id
+ $session_id = session_id();
+
+ if (($site_secret) && ($session_id))
+ return md5($site_secret.$action.$timestamp.$session_id);
+
+ return false;
+ }
+
+ /**
+ * Initialise the site secret.
+ *
+ */
+ function init_site_secret()
+ {
+ $secret = md5(rand().microtime());
+ if (datalist_set('__site_secret__', $secret))
+ return $secret;
+
+ return false;
+ }
+
+ /**
+ * Retrieve the site secret.
+ *
+ */
+ function get_site_secret()
+ {
+ $secret = datalist_get('__site_secret__');
+ if (!$secret) $secret = init_site_secret();
+
+ return $secret;
}
// Register some actions ***************************************************
diff --git a/languages/en.php b/languages/en.php
index 787ec58e3..f51f9128c 100644
--- a/languages/en.php
+++ b/languages/en.php
@@ -697,7 +697,14 @@ You cannot reply to this email.",
'entity:default:missingsupport:popup' => 'This entity cannot be displayed correctly. This may be because it requires support provided by a plugin that is no longer installed.',
'entity:delete:success' => 'Entity %s has been deleted',
- 'entity:delete:fail' => 'Entity %s could not be deleted',
+ 'entity:delete:fail' => 'Entity %s could not be deleted',
+
+
+ /**
+ * Action gatekeeper
+ */
+ 'actiongatekeeper:missingfields' => 'Form is missing __action, __token or __ts fields',
+ 'actiongatekeeper:tokeninvalid' => 'Token provided by form does not match that generated by server.',
/**
* Languages according to ISO 639-1
diff --git a/views/default/input/button.php b/views/default/input/button.php
index 115324533..2249158e6 100644
--- a/views/default/input/button.php
+++ b/views/default/input/button.php
@@ -35,4 +35,4 @@
$src = $vars['src'];
if (strpos($src,$CONFIG->wwwroot)===false) $src = ""; // blank src if trying to access an offsite image.
?>
-<input type="<?php echo $type; ?>" class="<?php echo $type; ?>_button" <?php echo $vars['js']; ?> value="<?php $value; ?>" src="<?php echo $src; ?>" /> \ No newline at end of file
+<input type="<?php echo $type; ?>" class="<?php echo $type; ?>_button" <?php echo $vars['js']; ?> value="<?php echo $value; ?>" src="<?php echo $src; ?>" /> \ No newline at end of file
diff --git a/views/default/input/form.php b/views/default/input/form.php
index 1f15b046f..5e4c7b001 100644
--- a/views/default/input/form.php
+++ b/views/default/input/form.php
@@ -17,15 +17,22 @@
* @uses $vars['action'] URL of the action being called
*
*/
-
-$body = $vars['body'];
-$action = $vars['action'];
-$enctype = $vars['enctype'];
-$method = $vars['method']; if (!$method) $method = 'POST';
+
+ $body = $vars['body'];
+ $action = $vars['action'];
+ $enctype = $vars['enctype'];
+ $method = $vars['method']; if (!$method) $method = 'POST';
// TODO: Token generation
+ // Generate a security header
+ $ts = time();
+ $token = generate_action_token($action, $ts);
+ $security_header = elgg_view('input/hidden', array('internalname' => '__elgg_token', 'value' => $token));
+ $security_header .= elgg_view('input/hidden', array('internalname' => '__elgg_action', 'value' => $action));
+ $security_header .= elgg_view('input/hidden', array('internalname' => '__elgg_ts', 'value' => $ts));
?>
<form action="<?php echo $action; ?>" method="<?php echo $method; ?>" <?php if ($enctype!="") echo "enctype=\"$enctype\""; ?>>
+<?php echo $security_header; ?>
<?php echo $body; ?>
</form> \ No newline at end of file