Elgg  Version 3.0
Csrf.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Elgg\Security;
4 
5 use Elgg\Config;
7 use Elgg\Request;
9 use ElggCrypto;
10 use ElggSession;
11 
15 class Csrf {
16 
17  use TimeUsing;
18 
22  protected $config;
23 
27  protected $session;
28 
32  protected $crypto;
33 
37  protected $hmac;
38 
47  public function __construct(
52  ) {
53 
54  $this->config = $config;
55  $this->session = $session;
56  $this->crypto = $crypto;
57  $this->hmac = $hmac;
58  }
59 
68  public function validate(Request $request) {
69  $token = $request->getParam('__elgg_token');
70  $ts = $request->getParam('__elgg_ts');
71 
72  $session_id = $this->session->getId();
73 
74  if (($token) && ($ts) && ($session_id)) {
75  if ($this->validateTokenOwnership($token, $ts)) {
76  if ($this->validateTokenTimestamp($ts)) {
77  // We have already got this far, so unless anything
78  // else says something to the contrary we assume we're ok
79  $returnval = $request->elgg()->hooks->trigger('action_gatekeeper:permissions:check', 'all', [
80  'token' => $token,
81  'time' => $ts
82  ], true);
83 
84  if ($returnval) {
85  return;
86  } else {
87  throw new CsrfException($request->elgg()->echo('actiongatekeeper:pluginprevents'));
88  }
89  } else {
90  // this is necessary because of #5133
91  if ($request->isXhr()) {
92  throw new CsrfException($request->elgg()->echo(
93  'js:security:token_refresh_failed',
94  [$this->config->wwwroot]
95  ));
96  } else {
97  throw new CsrfException($request->elgg()->echo('actiongatekeeper:timeerror'));
98  }
99  }
100  } else {
101  // this is necessary because of #5133
102  if ($request->isXhr()) {
103  throw new CsrfException($request->elgg()->echo('js:security:token_refresh_failed', [$this->config->wwwroot]));
104  } else {
105  throw new CsrfException($request->elgg()->echo('actiongatekeeper:tokeninvalid'));
106  }
107  }
108  } else {
109  $error_msg = $request->elgg()->echo('actiongatekeeper:missingfields');
110  throw new CsrfException($request->elgg()->echo($error_msg));
111  }
112  }
113 
124  public function isValidToken($token, $ts) {
125  return $this->validateTokenOwnership($token, $ts) && $this->validateTokenTimestamp($ts);
126  }
127 
135  protected function validateTokenTimestamp($ts) {
136  $timeout = $this->getActionTokenTimeout();
137  $now = $this->getCurrentTime()->getTimestamp();
138 
139  return ($timeout == 0 || ($ts > $now - $timeout) && ($ts < $now + $timeout));
140  }
141 
151  public function getActionTokenTimeout() {
152  // default to 2 hours
153  $timeout = 2;
154  if ($this->config->hasValue('action_token_timeout')) {
155  // timeout set in config
156  $timeout = $this->config->action_token_timeout;
157  }
158 
159  $hour = 60 * 60;
160 
161  return (int) ((float) $timeout * $hour);
162  }
163 
174  public function validateTokenOwnership($token, $timestamp, $session_token = '') {
175  $required_token = $this->generateActionToken($timestamp, $session_token);
176 
177  return $this->crypto->areEqual($token, $required_token);
178  }
179 
191  public function generateActionToken($timestamp, $session_token = '') {
192  if (!$session_token) {
193  $session_token = $this->session->get('__elgg_session');
194  if (!$session_token) {
195  return false;
196  }
197  }
198 
199  return $this->hmac
200  ->getHmac([(int) $timestamp, $session_token], 'md5')
201  ->getToken();
202  }
203 
204 }
isValidToken($token, $ts)
Basic token validation.
Definition: Csrf.php:124
Elgg HTTP request.
Definition: Request.php:17
getActionTokenTimeout()
Returns the action token timeout in seconds.
Definition: Csrf.php:151
$request
Page handler for autocomplete endpoint.
Definition: livesearch.php:9
Thrown when CSRF tokens mismatch.
getCurrentTime($modifier= '')
Get the (cloned) time.
Definition: TimeUsing.php:27
$timestamp
Definition: date.php:33
getParam($key, $default=null, $filter_result=true)
Get some input from variables passed submitted through GET or POST.
Definition: Request.php:137
validateTokenTimestamp($ts)
Is the token timestamp within acceptable range?
Definition: Csrf.php:135
validateTokenOwnership($token, $timestamp, $session_token= '')
Was the given token generated for the session defined by session_token?
Definition: Csrf.php:174
__construct(Config $config, ElggSession $session, ElggCrypto $crypto, HmacFactory $hmac)
Constructor.
Definition: Csrf.php:47
$token
validate(Request $request)
Validate CSRF tokens present in the request.
Definition: Csrf.php:68
CSRF Protection.
Definition: Csrf.php:15
trait TimeUsing
Adds methods for setting the current time (for testing)
Definition: TimeUsing.php:12
generateActionToken($timestamp, $session_token= '')
Generate a token from a session token (specifying the user), the timestamp, and the site key...
Definition: Csrf.php:191
Provides a factory for HMAC objects.
Definition: HmacFactory.php:10