Valider 81e6be96 rédigé par esj's avatar esj
Parcourir les fichiers

Refonte des sessions, pour deux raisons:

1. le code garantissant la perenité de la session en cas de vol de cookie n'était pas exécuté, d'une part parce qu'un & mal venu rendait son parametre méconnaissable, d'autre part parce que, meme cela corrigé, $profondeur_url etait défini trop tard et l'url_de_base etait fausse (et comme c'est un script en tache de fond, aucun message d'erreur nulle part...)

2. surtout: possibilité de surcharger la fonction inc_session pour gérer les sessions autrement que par des fichiers. Voir les specification de cette fonction dans inc/session.php
parent 0b951de0
Chargement en cours
Chargement en cours
Chargement en cours
Chargement en cours
+16 −23
Numéro de ligne d'origine Numéro de ligne de diff Ligne de diff
@@ -68,20 +68,8 @@ function action_spip_cookie_dist()

// rejoue le cookie pour renouveler spip_session
  if ($change_session == 'oui') {
	if (verifier_session($spip_session)) {
		// Attention : seul celui qui a le bon IP a le droit de rejouer,
		// ainsi un eventuel voleur de cookie ne pourrait pas deconnecter
		// sa victime, mais se ferait deconnecter par elle.
		if ($auteur_session['hash_env'] == hash_env()) {
			spip_log("rejoue session");
			$auteur_session['ip_change'] = false;
			$cookie = creer_cookie_session($auteur_session);
			supprimer_session($spip_session);
			spip_setcookie('spip_session', $cookie);
		}
		else
			spip_log("session non rejouee, changement d'IP ?");
	}
	$var_f = charger_fonction('session', 'inc');
	$var_f(true);
	envoie_image_vide();
	exit;
  }
@@ -102,7 +90,8 @@ if ($logout) {
	if ($auteur_session['login'] == $logout) {
		spip_query("UPDATE spip_auteurs SET en_ligne = DATE_SUB(NOW(),INTERVAL 6 MINUTE) WHERE id_auteur = ".$auteur_session['id_auteur']);
		if ($spip_session) {
			zap_sessions($auteur_session['id_auteur'], true);
			$var_f = charger_fonction('session', 'inc');
			$var_f($auteur_session['id_auteur']);
			spip_setcookie('spip_session', $spip_session, time() - 3600 * 24);
		}
		
@@ -160,14 +149,16 @@ if ($essai_login == "oui") {
	} else {
		spip_log("login de $session_login vers $redirect");
		// Si on se connecte dans l'espace prive, 
		// ajouter "bonjour" (inutilise)
		// ajouter "bonjour" (repere a peu pres les cookies desactives)
		if (ereg(_DIR_RESTREINT_ABS, $redirect)) {
			$redirect .= ((false !== strpos($redirect, "?")) ? "&" : "?")
				. 'bonjour=oui';
		}
		if ($row_auteur['statut'] == '0minirezo')
			$cookie_admin = "@".$session_login;
		$cookie_session = creer_cookie_session($row_auteur);
	        
		$var_f = charger_fonction('session', 'inc');
		$cookie_session = $var_f($row_auteur);
	}
}

@@ -196,7 +187,8 @@ if ($cookie_session) {

	$prefs = ($row_auteur['prefs']) ? unserialize($row_auteur['prefs']) : array();
	$prefs['cnx'] = ($session_remember == 'oui') ? 'perma' : '';
	update_prefs_session($prefs, $row_auteur['id_auteur']);

	spip_query("UPDATE spip_auteurs SET prefs = " . spip_abstract_quote(serialize($prefs)) . " WHERE id_auteur = " . $row_auteur['id_auteur']);
 }

// changement de langue espace public
@@ -217,11 +209,12 @@ if ($var_lang_ecrire) {
	spip_setcookie('spip_lang_ecrire', $var_lang_ecrire, time() + 365 * 24 * 3600);
	spip_setcookie('spip_lang', $var_lang_ecrire, time() + 365 * 24 * 3600);

	// ce ajouter_session me semble deja fait si on arrive jusqu'ici
	// avec id_auteur defini
	if (_FILE_CONNECT AND $id_auteur) {
		if (verifier_action_auteur("cookie-var_lang_ecrire", $hash, $id_auteur)) {
			ajouter_session($auteur_session, $spip_session, $var_lang_ecrire);
			spip_query("UPDATE spip_auteurs SET lang = " . spip_abstract_quote($var_lang_ecrire) . " WHERE id_auteur = " . intval($id_auteur));
			$auteur_session['lang'] = $var_lang_ecrire;
			$var_f = charger_fonction('session', 'inc');
			$var_f($auteur_session);
		}
	}

+2 −4
Numéro de ligne d'origine Numéro de ligne de diff Ligne de diff
@@ -105,10 +105,8 @@ if (strval($nom)!='') {
	}

	if ($modif_login) {
		include_spip('inc/session');
		zap_sessions ($auteur['id_auteur'], true);
		if ($connect_id_auteur == $auteur['id_auteur'])
			supprimer_session($GLOBALS['spip_session']);
		$var_f = charger_fonction('session', 'inc');
		$var_f($auteur['id_auteur']);
	}

	// email
+2 −1
Numéro de ligne d'origine Numéro de ligne de diff Ligne de diff
@@ -91,7 +91,8 @@ function inc_auth_dist() {

	// Authentification session
	if ($cookie_session = $_COOKIE['spip_session']) {
		if (verifier_session($cookie_session)) {
		$var_f = charger_fonction('session', 'inc');
		if ($var_f()) {
			if ($auteur_session['statut'] == '0minirezo'
			OR $auteur_session['statut'] == '1comite') {
				$connect_login = $auteur_session['login'];
+1 −11
Numéro de ligne d'origine Numéro de ligne de diff Ligne de diff
@@ -2857,17 +2857,7 @@ function debut_droite($rubrique="") {

function fin_html() {

	echo "</font>";

	// rejouer le cookie de session si l'IP a change
	if ($GLOBALS['spip_session'] && $GLOBALS['auteur_session']['ip_change']) {
		echo 
		  http_img_pack('rien.gif', " ", "name='img_session' width='0' height='0'"),
		  http_script("\ndocument.img_session.src='" . generer_url_public('spip_cookie','change_session=oui') . "'");
	}

	echo "</body></html>\n";

	echo "</font>", $GLOBALS['rejoue_session'], "</body></html>\n";
}


+100 −107
Numéro de ligne d'origine Numéro de ligne de diff Ligne de diff
@@ -22,38 +22,38 @@ include_spip('inc/meta');
 */

$GLOBALS['auteur_session'] = '';
$GLOBALS['rejoue_session'] = '';

//
// On verifie l'IP et le nom du navigateur
//
function hash_env() {
	return md5($GLOBALS['ip'] . $_SERVER['HTTP_USER_AGENT']);
}


//
// Calcule le nom du fichier session
// 3 actions sur les sessions, selon le type de l'argument:
//
function fichier_session($id_session, $alea) {
	if (ereg("^([0-9]+_)", $id_session, $regs))
		$id_auteur = $regs[1];
	return _DIR_SESSIONS . 'session_'.$id_auteur.md5($id_session.' '.$alea). '.php';
// - numérique: efface toutes les sessions de l'id_auteur (retour quelconque)
// - tableau: cree une session pour l'auteur decrit et retourne l'identifiant
// - autre: predicat de validite de la session indiquee par le cookie

function inc_session_dist($auteur=false)
{
	if (is_numeric($auteur))
		return supprimer_sessions($auteur);
	else if (is_array($auteur))
		return ajouter_session($auteur);
	else return verifier_session($auteur);
}

//
// Ajouter une session pour l'auteur specifie
// Ajoute une session pour l'auteur decrit par un tableau issu d'un SELECT-SQL
//
function ajouter_session($auteur, $id_session, $lang='') {

	global $auteur_session;
	if ($lang) {
		spip_query("UPDATE spip_auteurs SET lang = " . spip_abstract_quote($lang) . " WHERE id_auteur = " . intval($auteur['id_auteur']));
		$auteur_session['lang'] = $lang;
	}
function ajouter_session($auteur) {

	global $spip_session;
	renouvelle_alea();
	$fichier_session = fichier_session($id_session, $GLOBALS['meta']['alea_ephemere']);
	if (!$spip_session) 
		$spip_session = $auteur['id_auteur'].'_'.md5(creer_uniqid());

	$fichier_session = fichier_session($spip_session, $GLOBALS['meta']['alea_ephemere']);

	if (!isset($auteur['hash_env'])) $auteur['hash_env'] = hash_env();

	$texte = "<"."?php\n";
	foreach (array('id_auteur', 'nom', 'login', 'email', 'statut', 'lang', 'ip_change', 'hash_env') AS $var) {
@@ -64,73 +64,106 @@ function ajouter_session($auteur, $id_session, $lang='') {

	if (!ecrire_fichier($fichier_session, $texte))
		redirige_par_entete(generer_url_action('test_dirs','',true));
	else return $spip_session;
}

function update_prefs_session($prefs, $id_auteur)
{
	$prefs = serialize($prefs);
	spip_query("UPDATE spip_auteurs SET prefs = " . spip_abstract_quote($prefs) . " WHERE id_auteur = $id_auteur");
//
// Cette fonction efface toutes les sessions appartenant a l'auteur
// On en profite pour effacer toutes les sessions creees il y a plus de 48 h
//

function supprimer_sessions($id_auteur) {

	$dir = opendir(_DIR_SESSIONS);
	$t = time()  - (48 * 3600);
	while(($f = readdir($dir)) !== false) {

		if (ereg("^session_([0-9]+)_[a-z0-9]+\.php[3]?$", $f, $regs)){
			$f = _DIR_SESSIONS . $f;
			if (($regs[1] == $id_auteur) OR ($t > filemtime($f)))
				@unlink($f);
		}
	}
}

//
// Verifier et inclure une session
// Verifie et inclut une session. 
// La rejoue si IP change puis accepte le changement si $change=true
//
function verifier_session($id_session) {

function verifier_session($change=false) {

	global $spip_session; // issu du cookie

	// Tester avec alea courant
	$ok = false;
	if ($id_session) {
		$fichier_session = fichier_session($id_session, $GLOBALS['meta']['alea_ephemere']);
	if (!$spip_session) return false;

	$fichier_session = fichier_session($spip_session, $GLOBALS['meta']['alea_ephemere']);
	if (@file_exists($fichier_session)) {
		include($fichier_session);
			$ok = true;
		}
		else {
	} else {
		// Sinon, tester avec alea precedent
			$fichier_session = fichier_session($id_session, $GLOBALS['meta']['alea_ephemere_ancien']);
			if (@file_exists($fichier_session)) {
				// Renouveler la session (avec l'alea courant)
		$fichier_session = fichier_session($spip_session, $GLOBALS['meta']['alea_ephemere_ancien']);
		if (!@file_exists($fichier_session)) return false;

		// Renouveler la session avec l'alea courant
		include($fichier_session);
				supprimer_session($id_session);
				ajouter_session($GLOBALS['auteur_session'], $id_session);
				$ok = true;
			}
		}
		@unlink($fichier_session);
		ajouter_session($GLOBALS['auteur_session']);
	}

	// marquer la session comme "ip-change" si le cas se presente
	if ($ok AND (hash_env() != $GLOBALS['auteur_session']['hash_env']) AND !$GLOBALS['auteur_session']['ip_change']) {
	// Si l'adresse IP change, inc/presentation mettra une balise image
	// avec un URL de rappel demandant a changer le nom de la session.
	// Seul celui qui a l'IP d'origine est rejoue
	// ainsi un eventuel voleur de cookie ne pourrait pas deconnecter
	// sa victime, mais se ferait deconnecter par elle.

	if (hash_env() != $GLOBALS['auteur_session']['hash_env']) {
	    if (!$GLOBALS['auteur_session']['ip_change']) {
		$GLOBALS['rejoue_session'] = rejouer_session();
		$GLOBALS['auteur_session']['ip_change'] = true;
		ajouter_session($GLOBALS['auteur_session'], $id_session);
		ajouter_session($GLOBALS['auteur_session']);
	    } else if ($change)
	      spip_log("session non rejouee, vol de cookie ?");
	} else { if ($change) {
		spip_log("rejoue session $fichier_session $spip_session");
		@unlink($fichier_session);
		$auteur_session['ip_change'] = false;
		unset($spip_session);
		$cookie= ajouter_session($auteur_session);
		spip_setcookie('spip_session', $cookie);
	  }
	}
	return 	true;
}

// Code a inserer par inc/presentation pour rejouer la session
// Voir action/cookie qui sera appele.

	return $ok;
function rejouer_session()
{
	include_spip('inc/minipres');
	return	  http_img_pack('rien.gif', " ", "id='img_session' width='0' height='0'") .
		  http_script("\ndocument.img_session.src='" . generer_url_action('cookie','change_session=oui', true) .  "'");
}

//
// Supprimer une session
// Calcule le nom du fichier session
//
function supprimer_session($id_session) {
	$fichier_session = fichier_session($id_session, $GLOBALS['meta']['alea_ephemere']);
	if (@file_exists($fichier_session)) {
		@unlink($fichier_session);
	}
	$fichier_session = fichier_session($id_session, $GLOBALS['meta']['alea_ephemere_ancien']);
	if (@file_exists($fichier_session)) {
		@unlink($fichier_session);
	}
function fichier_session($id_session, $alea) {
	if (ereg("^([0-9]+_)", $id_session, $regs))
		$id_auteur = $regs[1];
	return _DIR_SESSIONS . 'session_'.$id_auteur.md5($id_session.' '.$alea). '.php';
}

//
// Creer une session et retourne le cookie correspondant (a poser)
// On verifie l'IP et le nom du navigateur
//
function creer_cookie_session($auteur) {
	if ($id_auteur = $auteur['id_auteur']) {
		$id_session = $id_auteur.'_'.md5(creer_uniqid());
		$auteur['hash_env'] = hash_env();
		ajouter_session($auteur, $id_session);
		return $id_session;
	}

function hash_env() {
  static $res ='';
  if ($res) return $res;
  return $res = md5($GLOBALS['ip'] . $_SERVER['HTTP_USER_AGENT']);
}

//
@@ -152,38 +185,6 @@ function creer_uniqid() {
}


//
// Cette fonction efface toutes les sessions appartenant a l'auteur
// On en profite pour effacer toutes les sessions creees il y a plus de 48 h
//
function zap_sessions ($id_auteur, $zap) {

	// ne pas se zapper soi-meme
	if ($s = $GLOBALS['spip_session'])
		$fichier_session = fichier_session($s, $GLOBALS['meta']['alea_ephemere']);

	$dir = opendir(_DIR_SESSIONS);
	$t = time();
	while(($item = readdir($dir)) !== false) {
		$chemin = _DIR_SESSIONS . $item;
		if (ereg("^session_([0-9]+_)?([a-z0-9]+)\.php[3]?$", $item, $regs)) {

			// Si c'est une vieille session, on jette
			if (($t - filemtime($chemin)) > 48 * 3600)
				@unlink($chemin);

			// sinon voir si c'est une session du meme auteur
			else if ($regs[1] == $id_auteur.'_') {
				$zap_num ++;
				if ($zap)
					@unlink($chemin);
			}

		}
	}

	return $zap_num;
}

//
// reconnaitre un utilisateur authentifie en php_auth
@@ -222,14 +223,6 @@ function ask_php_auth($pb, $raison, $retour, $url='', $re='', $lien='') {
	exit;
}

//
// verifie si on a un cookie de session ou un auth_php correct
// et charge ses valeurs dans $GLOBALS['auteur_session']
//
function verifier_session_visiteur() {
	return verifier_session($_COOKIE['spip_session']) ? true : verifier_php_auth();
}

//
// Renouvellement de l'alea utilise pour valider certaines operations
// (session, ajouter une image, etc.)
Chargement en cours