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 &amp; (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 &amp; (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("'", '&#39;', $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