diff --git a/admin/polls.php b/admin/polls.php index ac5780a..bf91aac 100644 --- a/admin/polls.php +++ b/admin/polls.php @@ -20,6 +20,7 @@ use Framadate\Services\AdminPollService; use Framadate\Services\LogService; use Framadate\Services\PollService; +use Framadate\Services\SecurityService; use Framadate\Services\SuperAdminService; use Framadate\Utils; @@ -39,18 +40,19 @@ $logService = new LogService(); $pollService = new PollService($connect, $logService); $adminPollService = new AdminPollService($connect, $pollService, $logService); $superAdminService = new SuperAdminService($connect); +$securityService = new SecurityService(); /* PAGE */ /* ---- */ -if (!empty($_POST['delete_poll'])) { - $delete_id = filter_input(INPUT_POST, 'delete_poll', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => '/^[a-z0-9]+$/']]); +if (!empty($_POST['delete_poll']) && $securityService->checkCsrf('admin', $_POST['csrf'])) { + $delete_id = filter_input(INPUT_POST, 'delete_poll', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]); $poll_to_delete = $pollService->findById($delete_id); } // Traitement de la confirmation de suppression -if (!empty($_POST['delete_confirm'])) { - $poll_id = filter_input(INPUT_POST, 'delete_confirm', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => '/^[a-z0-9]+$/']]); +if (!empty($_POST['delete_confirm']) && $securityService->checkCsrf('admin', $_POST['csrf'])) { + $poll_id = filter_input(INPUT_POST, 'delete_confirm', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]); $adminPollService->deleteEntirePoll($poll_id); } @@ -60,5 +62,6 @@ $polls = $superAdminService->findAllPolls(); $smarty->assign('polls', $polls); $smarty->assign('poll_to_delete', $poll_to_delete); $smarty->assign('log_file', is_readable('../' . LOG_FILE) ? LOG_FILE : null); +$smarty->assign('crsf', $securityService->getToken('admin')); $smarty->display('admin/polls.tpl'); diff --git a/app/classes/Framadate/Security/Token.php b/app/classes/Framadate/Security/Token.php index 2f06afc..7222dbf 100644 --- a/app/classes/Framadate/Security/Token.php +++ b/app/classes/Framadate/Security/Token.php @@ -3,18 +3,32 @@ namespace Framadate\Security; class Token { - private $tokan_name; private $time; private $value; - function __construct($tokan_name, $time) { - $this->tokan_name = $tokan_name; - $this->time = $time; - $this->value = $this->generate(); + function __construct() { + $this->time = time() + TOKEN_TIME; + $this->value = $this->generate(); } private function generate() { - // TODO + return sha1(uniqid(mt_rand(), true)); + } + + public function getTime() { + return $this->time; + } + + public function getValue() { + return $this->value; + } + + public function isGone() { + return $this->time < time(); + } + + public function check($value) { + return $value === $this->value; } } diff --git a/app/classes/Framadate/Services/SecurityService.php b/app/classes/Framadate/Services/SecurityService.php index ea570e0..fc67a72 100644 --- a/app/classes/Framadate/Services/SecurityService.php +++ b/app/classes/Framadate/Services/SecurityService.php @@ -8,12 +8,44 @@ class SecurityService { function __construct() { } + /** + * Get a CSRF token by name, or (re)create it. + * + * It creates a new token if : + * + * + * @param $tokan_name string The name of the CSRF token + * @return Token The token + */ function getToken($tokan_name) { - if (!isset($_SESSION['token']) || !isset($_SESSION['token'][$tokan_name])) { - $_SESSION['token'][$tokan_name] = new Token($tokan_name, 60*5); + if (!isset($_SESSION['tokens'])) { + $_SESSION['tokens'] = []; + } + if (!isset($_SESSION['tokens'][$tokan_name]) || $_SESSION['tokens'][$tokan_name]->isGone()) { + $_SESSION['tokens'][$tokan_name] = new Token(); } - return $_SESSION['token'][$tokan_name]->getValue(); + return $_SESSION['tokens'][$tokan_name]->getValue(); + } + + /** + * Check if a given value is corresponding to the token in session. + * + * @param $tokan_name string Name of the token + * @param $csrf string Value to check + * @return bool true if the token is well checked + */ + public function checkCsrf($tokan_name, $csrf) { + $checked = $_SESSION['tokens'][$tokan_name]->getValue() === $csrf; + + if($checked) { + unset($_SESSION['tokens'][$tokan_name]); + } + + return $checked; } } diff --git a/tpl/admin/polls.tpl b/tpl/admin/polls.tpl index c594caa..1758f13 100644 --- a/tpl/admin/polls.tpl +++ b/tpl/admin/polls.tpl @@ -2,6 +2,7 @@ {block 'admin_main'}
+ {if $poll_to_delete}

{_("Confirm removal of the poll ")}"{$poll_to_delete->id}"