From bf58623c94b769b12b5e5201bbfe9d2f230b5465 Mon Sep 17 00:00:00 2001 From: Cerdic <cedric@yterium.com> Date: Wed, 20 Jun 2012 07:21:52 +0000 Subject: [PATCH] =?UTF-8?q?Ferme=20#1963=20:=20calculer=20une=20url=20d'ac?= =?UTF-8?q?tion=20pour=20un=20n'importe=20quel=20auteur=20(par=20son=20id?= =?UTF-8?q?=5Fauteur)=20En=20mode=20url/array=20de=20securiser=5Faction=20?= =?UTF-8?q?on=20peut=20lui=20passer=20un=20id=5Fauteur=20dans=20l'argument?= =?UTF-8?q?=20$att,=20auquel=20cas=20l'url=20sera=20construite=20pour=20ce?= =?UTF-8?q?t=20id=5Fauteur=20pr=C3=A9cis.=20PHPDoc=20sur=20securiser=5Fact?= =?UTF-8?q?ion=20et=20fonctions=20satellites,=20pour=20expliciter/document?= =?UTF-8?q?er=20les=20diff=C3=A9rents=20arguments=20a=20tiroir=20La=20fonc?= =?UTF-8?q?tion=20calculer=5Faction=5Fauteur()=20parfois=20appel=C3=A9e=20?= =?UTF-8?q?directement=20prend=20aussi=20un=20$id=5Fauteur=20optionnel=20e?= =?UTF-8?q?n=20second=20argument?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A contrario, le mode formulaire qui suppose une interaction avec l'auteur connecté ne peut être généré que pour celui-ci, et la verification de signature de l'action, qui s'entend aussi pour l'auteur connecté, ne peut se faire que pour celui-ci également --- ecrire/inc/securiser_action.php | 166 ++++++++++++++++++++++++-------- ecrire/inc/utils.php | 19 +++- 2 files changed, 140 insertions(+), 45 deletions(-) diff --git a/ecrire/inc/securiser_action.php b/ecrire/inc/securiser_action.php index c0913a5778..9c8bea2a07 100644 --- a/ecrire/inc/securiser_action.php +++ b/ecrire/inc/securiser_action.php @@ -12,11 +12,26 @@ if (!defined('_ECRIRE_INC_VERSION')) return; -// interface d'appel: -// - au moins un argument: retourne une URL ou un formulaire securises -// - sans argument: verifie la securite et retourne _request('arg'), ou exit. - -// http://doc.spip.org/@inc_securiser_action_dist +/** + * interface d'appel: + * - au moins un argument: retourne une URL ou un formulaire securises + * - sans argument: verifie la securite et retourne _request('arg'), ou exit. + * + * http://doc.spip.org/@inc_securiser_action_dist + * + * @param string $action + * @param string $arg + * @param string $redirect + * @param bool|int|string $mode + * -1 : renvoyer action, arg et hash sous forme de array() + * true ou false : renvoyer une url, avec & (false) ou & (true) + * string : renvoyer un formulaire + * @param string|int $att + * id_auteur pour lequel generer l'action en mode url ou array() + * atributs du formulaire en mode formulaire + * @param bool $public + * @return array|string + */ function inc_securiser_action_dist($action='', $arg='', $redirect="", $mode=false, $att='', $public=false) { if ($action) @@ -33,24 +48,39 @@ function inc_securiser_action_dist($action='', $arg='', $redirect="", $mode=fals } } -// Attention: PHP applique urldecode sur $_GET mais pas sur $_POST -// cf http://fr.php.net/urldecode#48481 -// http://doc.spip.org/@securiser_action_auteur -function securiser_action_auteur($action, $arg, $redirect="", $mode=false, $att='', $public=false) -{ - static $id_auteur=0, $pass; - if (!$id_auteur) { - list($id_auteur, $pass) = caracteriser_auteur(); - } - $hash = _action_auteur("$action-$arg", $id_auteur, $pass, 'alea_ephemere'); +/** + * Attention: PHP applique urldecode sur $_GET mais pas sur $_POST + * cf http://fr.php.net/urldecode#48481 + * http://doc.spip.org/@securiser_action_auteur + * + * @param string $action + * @param string $arg + * @param string $redirect + * @param bool|int|string $mode + * -1 : renvoyer action, arg et hash sous forme de array() + * true ou false : renvoyer une url, avec & (false) ou & (true) + * string : renvoyer un formulaire + * @param string|int $att + * id_auteur pour lequel generer l'action en mode url ou array() + * atributs du formulaire en mode formulaire + * @param bool $public + * @return array|string + */ +function securiser_action_auteur($action, $arg, $redirect="", $mode=false, $att='', $public=false) { + + // mode URL ou array if (!is_string($mode)){ + $hash = calculer_action_auteur("$action-$arg",is_numeric($att)?$att:null); + $r = rawurlencode($redirect); if ($mode===-1) return array('action'=>$action,'arg'=>$arg,'hash'=>$hash); else - return generer_url_action($action, "arg=$arg&hash=$hash" . (!$r ? '' : "&redirect=$r"), $mode, $att); + return generer_url_action($action, "arg=$arg&hash=$hash" . (!$r ? '' : "&redirect=$r"), $mode, $public); } + // mode formulaire + $hash = calculer_action_auteur("$action-$arg"); $att .= " style='margin: 0px; border: 0px'"; if ($redirect) $redirect = "\n\t\t<input name='redirect' type='hidden' value='". str_replace("'", ''', $redirect) ."' />"; @@ -61,14 +91,18 @@ function securiser_action_auteur($action, $arg, $redirect="", $mode=false, $att= return generer_form_action($action, $mode, $att, $public); } -// http://doc.spip.org/@caracteriser_auteur -function caracteriser_auteur() { - global $visiteur_session; +/** + * Caracteriser un auteur : l'auteur loge si $id_auteur=null + * + * http://doc.spip.org/@caracteriser_auteur + * + * @param int|null $id_auteur + * @return array + */ +function caracteriser_auteur($id_auteur=null) { static $caracterisation = array(); - if ($caracterisation) return $caracterisation; - - if (!isset($visiteur_session['id_auteur'])) { + if (is_null($id_auteur) AND !isset($GLOBALS['visiteur_session']['id_auteur'])) { // si l'auteur courant n'est pas connu alors qu'il peut demander une action // c'est une connexion par php_auth ou 1 instal, on se rabat sur le cookie. // S'il n'avait pas le droit de realiser cette action, le hash sera faux. @@ -80,14 +114,19 @@ function caracteriser_auteur() { } else return array('0',''); } // Eviter l'acces SQL si le pass est connu de PHP - $id_auteur = $visiteur_session['id_auteur']; - if (isset($visiteur_session['pass']) AND $visiteur_session['pass']) - return $caracterisation = array($id_auteur, $visiteur_session['pass']); - else if ($id_auteur>0) { + if (is_null($id_auteur)){ + $id_auteur = isset($GLOBALS['visiteur_session']['id_auteur'])?$GLOBALS['visiteur_session']['id_auteur']:0; + if (isset($GLOBALS['visiteur_session']['pass']) AND $GLOBALS['visiteur_session']['pass']) + return $caracterisation[$id_auteur] = array($id_auteur, $GLOBALS['visiteur_session']['pass']); + } + + if ($caracterisation[$id_auteur]) return $caracterisation[$id_auteur]; + + if ($id_auteur) { include_spip('base/abstract_sql'); $t = sql_fetsel("id_auteur, pass", "spip_auteurs", "id_auteur=$id_auteur"); if ($t) - return $caracterisation = array($t['id_auteur'], $t['pass']); + return $caracterisation[$id_auteur] = array($t['id_auteur'], $t['pass']); include_spip('inc/minipres'); echo minipres(); exit; @@ -98,7 +137,19 @@ function caracteriser_auteur() { } } -// http://doc.spip.org/@_action_auteur +/** + * Calcule une cle securisee pour une action et un auteur donnes + * utilisee pour generer des urls personelles pour executer une action qui modifie la base + * et verifier la legitimite de l'appel a l'action + * + * http://doc.spip.org/@_action_auteur + * + * @param string $action + * @param int $id_auteur + * @param string $pass + * @param string $alea + * @return string + */ function _action_auteur($action, $id_auteur, $pass, $alea) { static $sha = array(); if (!isset($sha[$id_auteur.$pass.$alea])){ @@ -121,18 +172,34 @@ function _action_auteur($action, $id_auteur, $pass, $alea) { return md5($action.$sha[$id_auteur.$pass.$alea]); } -// http://doc.spip.org/@calculer_action_auteur -function calculer_action_auteur($action) { - list($id_auteur, $pass) = caracteriser_auteur(); +/** + * Calculer le hash qui signe une action pour un auteur + * http://doc.spip.org/@calculer_action_auteur + * + * @param string $action + * @param int|null $id_auteur + * @return string + */ +function calculer_action_auteur($action, $id_auteur=null) { + list($id_auteur, $pass) = caracteriser_auteur($id_auteur); return _action_auteur($action, $id_auteur, $pass, 'alea_ephemere'); } -// http://doc.spip.org/@verifier_action_auteur -function verifier_action_auteur($action, $valeur) { + +/** + * Verifier le hash de signature d'une action + * toujours exclusivement pour l'auteur en cours + * http://doc.spip.org/@verifier_action_auteur + * + * @param $action + * @param $hash + * @return bool + */ +function verifier_action_auteur($action, $hash) { list($id_auteur, $pass) = caracteriser_auteur(); - if ($valeur == _action_auteur($action, $id_auteur, $pass, 'alea_ephemere')) + if ($hash == _action_auteur($action, $id_auteur, $pass, 'alea_ephemere')) return true; - if ($valeur == _action_auteur($action, $id_auteur, $pass, 'alea_ephemere_ancien')) + if ($hash == _action_auteur($action, $id_auteur, $pass, 'alea_ephemere_ancien')) return true; return false; } @@ -142,9 +209,15 @@ function verifier_action_auteur($action, $valeur) { // par exemple que l'URL d'un document a la bonne cle de lecture // -// Le secret du site doit rester aussi secret que possible, et est eternel -// On ne doit pas l'exporter -// http://doc.spip.org/@secret_du_site +/** + * Renvoyer le secret du site, et le generer si il n'existe pas encore + * Le secret du site doit rester aussi secret que possible, et est eternel + * On ne doit pas l'exporter + * + * http://doc.spip.org/@secret_du_site + * + * @return string + */ function secret_du_site() { if (!isset($GLOBALS['meta']['secret_du_site'])){ include_spip('base/abstract_sql'); @@ -160,7 +233,13 @@ function secret_du_site() { return $GLOBALS['meta']['secret_du_site']; } -// http://doc.spip.org/@calculer_cle_action +/** + * Calculer une signature valable pour une action et pour le site + * http://doc.spip.org/@calculer_cle_action + * + * @param string $action + * @return string + */ function calculer_cle_action($action) { if (function_exists('sha1')) return sha1($action . secret_du_site()); @@ -168,7 +247,14 @@ function calculer_cle_action($action) { return md5($action . secret_du_site()); } -// http://doc.spip.org/@verifier_cle_action +/** + * Verifier la cle de signature d'une action valable pour le site + * http://doc.spip.org/@verifier_cle_action + * + * @param string $action + * @param string $cle + * @return bool + */ function verifier_cle_action($action, $cle) { return ($cle == calculer_cle_action($action)); } diff --git a/ecrire/inc/utils.php b/ecrire/inc/utils.php index c48a169683..d896675f25 100644 --- a/ecrire/inc/utils.php +++ b/ecrire/inc/utils.php @@ -1347,11 +1347,20 @@ function generer_form_ecrire($script, $corps, $atts='', $submit='') { . "</div></form>\n"; } -// Attention, JS/Ajax n'aime pas le melange de param GET/POST -// On n'applique pas la recommandation ci-dessus pour les scripts publics -// qui ne sont pas destines a etre mis en signets - -// http://doc.spip.org/@generer_form_action +/** + * Generer un formulaire pour lancer une action vers $script + * + * Attention, JS/Ajax n'aime pas le melange de param GET/POST + * On n'applique pas la recommandation ci-dessus pour les scripts publics + * qui ne sont pas destines a etre mis en signets + * http://doc.spip.org/@generer_form_action + * + * @param string $script + * @param string $corps + * @param string $atts + * @param bool $public + * @return string + */ function generer_form_action($script, $corps, $atts='', $public=false) { // si l'on est dans l'espace prive, on garde dans l'url // l'exec a l'origine de l'action, qui permet de savoir si il est necessaire -- GitLab