public function validateRequest() : bool
{
if (!isset($this->session[$this->sessionIndex])) {
// We don't even have a session array initialized
$this->session[$this->sessionIndex] = [];
return false;
}
if (!isset($this->post[$this->formIndex]) || !isset($this->post[$this->formToken])) {
// User must transmit a complete index/token pair
return false;
}
// Let's pull the POST data
$index = $this->post[$this->formIndex];
$token = $this->post[$this->formToken];
if (!isset($this->session[$this->sessionIndex][$index])) {
// CSRF Token not found
return false;
}
if (!\is_string($index) || !\is_string($token)) {
return false;
}
// Grab the value stored at $index
$stored = $this->session[$this->sessionIndex][$index];
// We don't need this anymore
unset($this->session[$this->sessionIndex][$index]);
// Which form action="" is this token locked to?
$lockTo = $this->server['REQUEST_URI'];
if (\preg_match('#/$#', $lockTo)) {
// Trailing slashes are to be ignored
$lockTo = Binary::safeSubstr($lockTo, 0, Binary::safeStrlen($lockTo) - 1);
}
if (!\hash_equals($lockTo, $stored['lockTo'])) {
// Form target did not match the request this token is locked to!
return false;
}
// This is the expected token value
if ($this->hmac_ip === false) {
// We just stored it wholesale
$expected = $stored['token'];
} else {
// We mixed in the client IP address to generate the output
$expected = Base64::encode(\hash_hmac($this->hashAlgo, isset($this->server['REMOTE_ADDR']) ? $this->server['REMOTE_ADDR'] : '127.0.0.1', Base64::decode($stored['token']), true));
}
return \hash_equals($token, $expected);
}