From c9c929d9a6c74156a1b97e8b706312f67b853b89 Mon Sep 17 00:00:00 2001
From: Fil <fil@rezo.net>
Date: Sun, 1 Jan 2006 17:20:03 +0000
Subject: [PATCH] Introduction d'un modele de securite a deux niveaux : -
 [(#TEXTE)] : on applique propre() et interdire_script() - [(#TEXTE*)] : on
 n'applique plus propre(), mais toujours interdire_script() - [(#TEXTE**)] :
 on n'applique plus rien ; question seccurite tout devient possible, au
 webmestre de filtrer comme il se doit pour eviter toute injection de php,
 javascript etc.

Par ailleurs les appels a safehtml() se rationalisent un peu (mais pas encore definitif, je pense).
---
 inc-balises.php3       |  46 ------------------
 inc-compilo-api.php3   |  30 ++++--------
 inc-compilo-index.php3 | 106 ++++++++++++++++++++++++++++++++++-------
 inc-html-squel.php3    |   2 +-
 4 files changed, 99 insertions(+), 85 deletions(-)

diff --git a/inc-balises.php3 b/inc-balises.php3
index ea81174062..55ecbc422f 100644
--- a/inc-balises.php3
+++ b/inc-balises.php3
@@ -23,52 +23,6 @@
 if (!defined("_ECRIRE_INC_VERSION")) return;
 
 
-//
-// Traitements standard de divers champs
-//
-function champs_traitements ($p) {
-	global $table_des_traitements;
-
-	if (!is_array($table_des_traitements[$p->nom_champ]))
-	  // old style
-		$ps = $table_des_traitements[$p->nom_champ];
-	else {
-		if ($p->nom_boucle)
-			$type = $p->boucles[$p->nom_boucle]->type_requete;
-		else
-			$type = $p->type_requete;
-		$ps = $table_des_traitements[$p->nom_champ][$type];
-		if (!$ps)
-			$ps = $table_des_traitements[$p->nom_champ][0];
-	}
-		 
-	if (!$ps) return $p->code;
-	if ($p->descr['documents']) {
-		$ps = 'traiter_doublons_documents($doublons, '.$ps.')';
-	}
-
-	// on supprime les < IMGnnn > tant qu'on ne rapatrie pas
-	// les documents distants joints..
-	// il faudrait aussi corriger les raccourcis d'URL locales
-	return str_replace('%s',
-		(!$p->boucles[$p->id_boucle]->sql_serveur ?
-		$p->code :
-		('supprime_img(' . $p->code . ')')),
-		$ps);
-}
-
-// il faudrait savoir traiter les formulaires en local 
-// tout en appelant le serveur SQL distant.
-// En attendant, cette fonction permet de refuser une authentification 
-// sur qqch qui n'a rien a voir.
-
-function balise_distante_interdite($p) {
-	$nom = $p->id_boucle;
-	if ($p->boucles[$nom]->sql_serveur) {
-		erreur_squelette($p->nom_champ .' '._T('zbug_distant_interdit'), $nom);
-	}
-}
-
 //
 // Definition des balises
 //
diff --git a/inc-compilo-api.php3 b/inc-compilo-api.php3
index c544c0903d..6eaea401ce 100644
--- a/inc-compilo-api.php3
+++ b/inc-compilo-api.php3
@@ -252,26 +252,26 @@ $exceptions_des_jointures['titre_mot'] = 'titre';
 $exceptions_des_jointures['type_mot'] = 'type';
 
 global  $table_des_traitements;
-$table_des_traitements['BIO'][]= 'traiter_raccourcis(%s)';
-$table_des_traitements['CHAPO'][]= 'traiter_raccourcis(nettoyer_chapo(%s))';
+$table_des_traitements['BIO'][]= 'propre(%s)';
+$table_des_traitements['CHAPO'][]= 'propre(nettoyer_chapo(%s))';
 $table_des_traitements['DATE'][]= 'vider_date(%s)';
 $table_des_traitements['DATE_MODIF'][]= 'vider_date(%s)';
 $table_des_traitements['DATE_NOUVEAUTES'][]= 'vider_date(%s)';
 $table_des_traitements['DATE_REDAC'][]= 'vider_date(%s)';
-$table_des_traitements['DESCRIPTIF'][]= 'traiter_raccourcis(%s)';
+$table_des_traitements['DESCRIPTIF'][]= 'propre(%s)';
 $table_des_traitements['LIEN_TITRE'][]= 'typo(%s)';
 $table_des_traitements['LIEN_URL'][]= 'htmlspecialchars(vider_url(%s))';
-$table_des_traitements['MESSAGE'][]= 'traiter_raccourcis(%s)';
+$table_des_traitements['MESSAGE'][]= 'propre(%s)';
 $table_des_traitements['NOM_SITE_SPIP'][]= 'typo(%s)';
 $table_des_traitements['NOM_SITE'][]= 'typo(%s)';
 $table_des_traitements['NOM'][]= 'typo(%s)';
 $table_des_traitements['PARAMETRES_FORUM'][]= 'htmlspecialchars(lang_parametres_forum(%s))';
-$table_des_traitements['PS'][]= 'traiter_raccourcis(%s)';
+$table_des_traitements['PS'][]= 'propre(%s)';
 $table_des_traitements['SOURCE'][]= 'typo(%s)';
 $table_des_traitements['SOUSTITRE'][]= 'typo(%s)';
 $table_des_traitements['SURTITRE'][]= 'typo(%s)';
 $table_des_traitements['TAGS'][]= '%s';
-$table_des_traitements['TEXTE'][]= 'traiter_raccourcis(%s)';
+$table_des_traitements['TEXTE'][]= 'propre(%s)';
 $table_des_traitements['TITRE'][]= 'typo(%s)';
 $table_des_traitements['TYPE'][]= 'typo(%s)';
 $table_des_traitements['URL_ARTICLE'][]= 'htmlspecialchars(vider_url(%s))';
@@ -287,21 +287,11 @@ $table_des_traitements['URL_SYNDIC'][]= 'htmlspecialchars(vider_url(%s))';
 $table_des_traitements['ENV'][]= 'entites_html(%s)';
 
 
-// Securite supplementaire pour certaines tables
-
-// Articles syndiques : remplacer les filtres par safehtml()
+// Articles syndiques : passage des donnees telles quelles, sans traitement typo
+// A noter, dans applique_filtres la securite et compliance XHTML de ces champs
+// est assuree par safehtml()
 foreach(array('TITRE','DESCRIPTIF','SOURCE') as $balise)
 	if (!isset($table_des_traitements[$balise]['syndic_articles']))
-		$table_des_traitements[$balise]['syndic_articles'] = 'safehtml(%s)';
-
-// Forums & petitions : ajouter safehtml aux filtres existants
-foreach(array('TITRE','TEXTE','AUTEUR','EMAIL_AUTEUR','NOM_SITE') as $balise)
-	if (!isset($table_des_traitements[$balise]['forums']))
-		$table_des_traitements[$balise]['forums'] =
-			'safehtml('.$table_des_traitements[$balise][0].')';
-foreach(array('NOM','NOM_SITE','MESSAGE','AD_EMAIL') as $balise)
-	if (!isset($table_des_traitements[$balise]['signatures']))
-		$table_des_traitements[$balise]['signatures'] =
-			'safehtml('.$table_des_traitements[$balise][0].')';
+		$table_des_traitements[$balise]['syndic_articles'] = '%s';
 
 ?>
diff --git a/inc-compilo-index.php3 b/inc-compilo-index.php3
index 3d8a8ce785..7f59224208 100644
--- a/inc-compilo-index.php3
+++ b/inc-compilo-index.php3
@@ -246,28 +246,98 @@ function collecter_balise_dynamique($l, $p) {
 	return $args;
 }
 
-function applique_filtres($p) {
 
-	// pretraitements standards (explication dans inc-compilo-index)
-	switch ($statut) {
-		case 'num':
-			$code = "intval($code)";
-			break;
-		case 'php':
-			break;
-		case 'html':
-		default:
-			$code = "trim($code)";
-			break;
+// il faudrait savoir traiter les formulaires en local
+// tout en appelant le serveur SQL distant.
+// En attendant, cette fonction permet de refuser une authentification
+// sur qqch qui n'a rien a voir.
+
+function balise_distante_interdite($p) {
+	$nom = $p->id_boucle;
+	if ($p->boucles[$nom]->sql_serveur) {
+		erreur_squelette($p->nom_champ .' '._T('zbug_distant_interdit'), $nom);
 	}
+}
+
+
+//
+// Traitements standard de divers champs
+// definis par $table_des_traitements, cf. inc-compilo-api.php3
+//
+function champs_traitements ($p) {
+	global $table_des_traitements;
+
+	if (!is_array($table_des_traitements[$p->nom_champ]))
+	  // old style
+		$ps = $table_des_traitements[$p->nom_champ];
+	else {
+		if ($p->nom_boucle)
+			$type = $p->boucles[$p->nom_boucle]->type_requete;
+		else
+			$type = $p->type_requete;
+		$ps = $table_des_traitements[$p->nom_champ][$type];
+		if (!$ps)
+			$ps = $table_des_traitements[$p->nom_champ][0];
+	}
+		 
+	if (!$ps) return $p->code;
+
+	// Si une boucle sous-jacente (?) traite les documents, on insere ici
+	// une fonction de remplissage du tableau des doublons -- mais seulement
+	// si on rencontre le filtre propre (qui traite les
+	// raccourcis <docXX> qui nous interessent)
+	if ($p->descr['documents']
+	AND preg_match(',propre,', $ps))
+		$ps = 'traiter_doublons_documents($doublons, '.$ps.')';
+
+	// De meme, en cas de sql_serveur, on supprime les < IMGnnn > tant
+	// qu'on ne rapatrie pas les documents distants joints..
+	// il faudrait aussi corriger les raccourcis d'URL locales
+	if ($p->boucles[$p->id_boucle]->sql_serveur)
+		$p->code = 'supprime_img(' . $p->code . ')';
+
+	// Remplacer enfin le placeholder %s par le vrai code de la balise
+	return str_replace('%s', $p->code, $ps);
+}
+
+
+//
+// Appliquer les filtres a un champ [(#CHAMP|filtre1|filtre2)]
+// retourne un code php compile exprimant ce champ filtre et securise
+//  - une etoile => pas de processeurs standards
+//  - deux etoiles => pas de securite non plus !
+//
+function applique_filtres($p) {
+
+	// Traitements standards (cf. supra)
+	if ($p->etoile == '')
+		$code = champs_traitements($p);
+	else
+		$code = $p->code;
 
-//  processeurs standards (cf inc-balises)
-	$code = ($p->etoile ? $p->code : champs_traitements($p));
 	// Appliquer les filtres perso
-	if ($p->param) $code = compose_filtres($p, $code);
-	// post-traitement securite
-	if ($p->interdire_scripts)
-		$code = "interdire_scripts($code)";
+	if ($p->param)
+		$code = compose_filtres($p, $code);
+
+	// Securite
+	if ($p->interdire_scripts
+	AND $p->etoile != '**') {
+
+		switch ($p->type_requete) {
+			// Passer |safehtml sur les boucles "sensibles"
+			case 'forums':
+			case 'signatures':
+			case 'syndic_articles':
+				$code = "safehtml($code)";
+				break;
+
+			// et |interdire_scripts sur les autres
+			default:
+				$code = "interdire_scripts($code)";
+				break;
+		}
+	}
+
 	return $code;
 }
 
diff --git a/inc-html-squel.php3 b/inc-html-squel.php3
index f6682e251a..fbf16bc301 100644
--- a/inc-html-squel.php3
+++ b/inc-html-squel.php3
@@ -28,7 +28,7 @@ define('TYPE_RECURSIF', 'boucle');
 define('SPEC_BOUCLE','/\s*\(\s*([^\s)]+)(\s*[^)]*)\)/');
 define('NOM_DE_BOUCLE', "[0-9]+|[-_][-_.a-zA-Z0-9]*");
 # ecriture alambiquee pour rester compatible avec les hexadecimaux des vieux squelettes
-define('NOM_DE_CHAMP', "#((" . NOM_DE_BOUCLE . "):)?(([A-F]*[G-Z_][A-Z_0-9]*)|[A-Z_]+)(\*?)");
+define('NOM_DE_CHAMP', "#((" . NOM_DE_BOUCLE . "):)?(([A-F]*[G-Z_][A-Z_0-9]*)|[A-Z_]+)(\*{0,2})");
 define('CHAMP_ETENDU', '\[([^]\[]*)\(' . NOM_DE_CHAMP . '([^[)]*\)[^]\[]*)\]');
 
 define('BALISE_INCLURE','<INCLU[DR]E[[:space:]]*\(([^)]*)\)');
-- 
GitLab