Completed
Push — master ( 00d89c...39a0b7 )
by cam
01:17
created
ecrire/auth/spip.php 3 patches
Indentation   +413 added lines, -413 removed lines patch added patch discarded remove patch
@@ -19,7 +19,7 @@  discard block
 block discarded – undo
19 19
 use Spip\Chiffrer\SpipCles;
20 20
 
21 21
 if (!defined('_ECRIRE_INC_VERSION')) {
22
-	return;
22
+    return;
23 23
 }
24 24
 
25 25
 /**
@@ -34,171 +34,171 @@  discard block
 block discarded – undo
34 34
  */
35 35
 function auth_spip_dist($login, $pass, $serveur = '', $phpauth = false) {
36 36
 
37
-	// retrouver le login
38
-	$login = auth_spip_retrouver_login($login);
39
-	// login inconnu, n'allons pas plus loin
40
-	if (!$login) {
41
-		return [];
42
-	}
43
-
44
-	$md5pass = '';
45
-	$shapass = $shanext = '';
46
-	$auteur_peut_sauver_cles = false;
47
-
48
-	if ($pass) {
49
-		$row = sql_fetsel(
50
-			'*',
51
-			'spip_auteurs',
52
-			'login=' . sql_quote($login, $serveur, 'text') . " AND statut<>'5poubelle'",
53
-			'',
54
-			'',
55
-			'',
56
-			'',
57
-			$serveur
58
-		);
59
-
60
-		// lever un flag si cet auteur peut sauver les cles
61
-		if ($row['statut'] === '0minirezo' and $row['webmestre'] === 'oui' and isset($row['backup_cles'])) {
62
-			$auteur_peut_sauver_cles = true;
63
-		}
64
-	}
65
-
66
-	// login inexistant ou mot de passe vide
67
-	if (!$pass or !$row) {
68
-		return [];
69
-	}
70
-
71
-	include_spip('inc/chiffrer');
72
-	$cles = SpipCles::instance();
73
-	$secret = $cles->getSecretAuth();
74
-
75
-	$hash = null;
76
-	switch (strlen($row['pass'])) {
77
-
78
-		// legacy = md5 ou sha256
79
-		case 32:
80
-			// tres anciens mots de passe encodes en md5(alea.pass)
81
-			$hash = md5($row['alea_actuel'] . $pass);
82
-			$methode = 'md5';
83
-		case 64:
84
-			if (empty($hash)) {
85
-				// anciens mots de passe encodes en sha256(alea.pass)
86
-				include_spip('auth/sha256.inc');
87
-				$hash = spip_sha256($row['alea_actuel'] . $pass);
88
-				$methode = 'sha256';
89
-			}
90
-			if ($row['pass'] === $hash) {
91
-				spip_log("validation du mot de passe pour l'auteur #".$row['id_auteur']." $login via $methode", 'auth' . _LOG_DEBUG);
92
-				// ce n'est pas cense arriver, mais si jamais c'est un backup inutilisable, il faut le nettoyer pour ne pas bloquer la creation d'une nouvelle cle d'auth
93
-				if (!empty($row['backup_cles'])) {
94
-					sql_updateq('spip_auteurs', ['backup_cles' => ''], 'id_auteur=' . intval($row['id_auteur']));
95
-				}
96
-				break;
97
-			}
98
-
99
-		// on teste la methode par defaut, au cas ou ce serait un pass moderne qui a la malchance d'etre en 64char de long
100
-
101
-		case 60:
102
-		case 98:
103
-		default:
104
-			// doit-on restaurer un backup des cles ?
105
-			// si on a le bon pass on peut decoder le backup, retrouver la cle, et du coup valider le pass
106
-			if (
107
-				!$secret
108
-				and $auteur_peut_sauver_cles
109
-				and !empty($row['backup_cles'])
110
-			) {
111
-				if ($cles->restore($row['backup_cles'], $pass, $row['pass'], $row['id_auteur'])) {
112
-					spip_log('Les cles secretes ont ete restaurées avec le backup du webmestre #' . $row['id_auteur'], 'auth' . _LOG_INFO_IMPORTANTE);
113
-					if ($cles->save()) {
114
-						$secret = $cles->getSecretAuth();
115
-					}
116
-					else {
117
-						spip_log("Echec restauration des cles : verifier les droits d'ecriture ?", 'auth' . _LOG_ERREUR);
118
-						// et on echoue car on ne veut pas que la situation reste telle quelle
119
-						raler_fichier(_DIR_ETC . 'cles.php');
120
-					}
121
-				}
122
-				else {
123
-					spip_log('Pas de cle secrete disponible (fichier config/cle.php absent ?) mais le backup du webmestre #' . $row['id_auteur'] . " n'est pas valide", 'auth' . _LOG_ERREUR);
124
-					sql_updateq('spip_auteurs', ['backup_cles' => ''], 'id_auteur=' . intval($row['id_auteur']));
125
-				}
126
-			}
127
-
128
-			if (!$secret or !Password::verifier($pass, $row['pass'], $secret)) {
129
-				unset($row);
130
-			}
131
-			else {
132
-				spip_log("validation du mot de passe pour l'auteur #".$row['id_auteur']." $login via Password::verifier", 'auth' . _LOG_DEBUG);
133
-			}
134
-			break;
135
-	}
136
-
137
-	// Migration depuis ancienne version : si on a pas encore de cle
138
-	// ET si c'est le login d'un auteur qui peut sauver la cle
139
-	// créer la clé (en s'assurant bien que personne n'a de backup d'un precedent fichier cle.php)
140
-	// si c'est un auteur normal, on ne fait rien, il garde son ancien pass hashé en sha256 en attendant le login d'un webmestre
141
-	if (!$secret and $auteur_peut_sauver_cles) {
142
-		if (auth_spip_initialiser_secret()) {
143
-			$secret = $cles->getSecretAuth();
144
-		}
145
-	}
146
-
147
-	// login/mot de passe incorrect
148
-	if (empty($row)) {
149
-		return [];
150
-	}
151
-
152
-	// fait tourner le codage du pass dans la base
153
-	// sauf si phpauth : cela reviendrait a changer l'alea a chaque hit, et aucune action verifiable par securiser_action()
154
-	if (!$phpauth and $secret) {
155
-		include_spip('inc/acces'); // pour creer_uniqid et verifier_htaccess
156
-		$pass_hash_next = Password::hacher($pass, $secret);
157
-		if ($pass_hash_next) {
158
-			$set = [
159
-				'alea_actuel' => 'alea_futur', // @deprecated 4.1
160
-				'alea_futur' => sql_quote(creer_uniqid(), $serveur, 'text'), // @deprecated 4.1
161
-				'pass' => sql_quote($pass_hash_next, $serveur, 'text'),
162
-			];
163
-
164
-			// regenerer un htpass si on a active/desactive le plugin htpasswd
165
-			// et/ou que l'algo a change - pour etre certain de toujours utiliser le bon algo
166
-			$htpass = generer_htpass($pass);
167
-			if (strlen($htpass) !== strlen($row['htpass'])) {
168
-				$set['htpass'] = sql_quote($htpass, $serveur, 'text');
169
-			}
170
-
171
-			// a chaque login de webmestre : sauvegarde chiffree des clés du site (avec les pass du webmestre)
172
-			if ($auteur_peut_sauver_cles) {
173
-				$set['backup_cles'] = sql_quote($cles->backup($pass), $serveur, 'text');
174
-			}
175
-
176
-			@sql_update(
177
-				'spip_auteurs',
178
-				$set,
179
-				'id_auteur=' . intval($row['id_auteur']) . ' AND pass=' . sql_quote(
180
-					$row['pass'],
181
-					$serveur,
182
-					'text'
183
-				),
184
-				[],
185
-				$serveur
186
-			);
187
-
188
-			// si on a change le htpass car changement d'algo, regenerer les fichiers htpasswd
189
-			if (isset($set['htpass'])) {
190
-				ecrire_acces();
191
-			}
192
-		}
193
-
194
-		// En profiter pour verifier la securite de tmp/
195
-		// Si elle ne fonctionne pas a l'installation, prevenir
196
-		if (!verifier_htaccess(_DIR_TMP) and defined('_ECRIRE_INSTALL')) {
197
-			return false;
198
-		}
199
-	}
200
-
201
-	return $row;
37
+    // retrouver le login
38
+    $login = auth_spip_retrouver_login($login);
39
+    // login inconnu, n'allons pas plus loin
40
+    if (!$login) {
41
+        return [];
42
+    }
43
+
44
+    $md5pass = '';
45
+    $shapass = $shanext = '';
46
+    $auteur_peut_sauver_cles = false;
47
+
48
+    if ($pass) {
49
+        $row = sql_fetsel(
50
+            '*',
51
+            'spip_auteurs',
52
+            'login=' . sql_quote($login, $serveur, 'text') . " AND statut<>'5poubelle'",
53
+            '',
54
+            '',
55
+            '',
56
+            '',
57
+            $serveur
58
+        );
59
+
60
+        // lever un flag si cet auteur peut sauver les cles
61
+        if ($row['statut'] === '0minirezo' and $row['webmestre'] === 'oui' and isset($row['backup_cles'])) {
62
+            $auteur_peut_sauver_cles = true;
63
+        }
64
+    }
65
+
66
+    // login inexistant ou mot de passe vide
67
+    if (!$pass or !$row) {
68
+        return [];
69
+    }
70
+
71
+    include_spip('inc/chiffrer');
72
+    $cles = SpipCles::instance();
73
+    $secret = $cles->getSecretAuth();
74
+
75
+    $hash = null;
76
+    switch (strlen($row['pass'])) {
77
+
78
+        // legacy = md5 ou sha256
79
+        case 32:
80
+            // tres anciens mots de passe encodes en md5(alea.pass)
81
+            $hash = md5($row['alea_actuel'] . $pass);
82
+            $methode = 'md5';
83
+        case 64:
84
+            if (empty($hash)) {
85
+                // anciens mots de passe encodes en sha256(alea.pass)
86
+                include_spip('auth/sha256.inc');
87
+                $hash = spip_sha256($row['alea_actuel'] . $pass);
88
+                $methode = 'sha256';
89
+            }
90
+            if ($row['pass'] === $hash) {
91
+                spip_log("validation du mot de passe pour l'auteur #".$row['id_auteur']." $login via $methode", 'auth' . _LOG_DEBUG);
92
+                // ce n'est pas cense arriver, mais si jamais c'est un backup inutilisable, il faut le nettoyer pour ne pas bloquer la creation d'une nouvelle cle d'auth
93
+                if (!empty($row['backup_cles'])) {
94
+                    sql_updateq('spip_auteurs', ['backup_cles' => ''], 'id_auteur=' . intval($row['id_auteur']));
95
+                }
96
+                break;
97
+            }
98
+
99
+        // on teste la methode par defaut, au cas ou ce serait un pass moderne qui a la malchance d'etre en 64char de long
100
+
101
+        case 60:
102
+        case 98:
103
+        default:
104
+            // doit-on restaurer un backup des cles ?
105
+            // si on a le bon pass on peut decoder le backup, retrouver la cle, et du coup valider le pass
106
+            if (
107
+                !$secret
108
+                and $auteur_peut_sauver_cles
109
+                and !empty($row['backup_cles'])
110
+            ) {
111
+                if ($cles->restore($row['backup_cles'], $pass, $row['pass'], $row['id_auteur'])) {
112
+                    spip_log('Les cles secretes ont ete restaurées avec le backup du webmestre #' . $row['id_auteur'], 'auth' . _LOG_INFO_IMPORTANTE);
113
+                    if ($cles->save()) {
114
+                        $secret = $cles->getSecretAuth();
115
+                    }
116
+                    else {
117
+                        spip_log("Echec restauration des cles : verifier les droits d'ecriture ?", 'auth' . _LOG_ERREUR);
118
+                        // et on echoue car on ne veut pas que la situation reste telle quelle
119
+                        raler_fichier(_DIR_ETC . 'cles.php');
120
+                    }
121
+                }
122
+                else {
123
+                    spip_log('Pas de cle secrete disponible (fichier config/cle.php absent ?) mais le backup du webmestre #' . $row['id_auteur'] . " n'est pas valide", 'auth' . _LOG_ERREUR);
124
+                    sql_updateq('spip_auteurs', ['backup_cles' => ''], 'id_auteur=' . intval($row['id_auteur']));
125
+                }
126
+            }
127
+
128
+            if (!$secret or !Password::verifier($pass, $row['pass'], $secret)) {
129
+                unset($row);
130
+            }
131
+            else {
132
+                spip_log("validation du mot de passe pour l'auteur #".$row['id_auteur']." $login via Password::verifier", 'auth' . _LOG_DEBUG);
133
+            }
134
+            break;
135
+    }
136
+
137
+    // Migration depuis ancienne version : si on a pas encore de cle
138
+    // ET si c'est le login d'un auteur qui peut sauver la cle
139
+    // créer la clé (en s'assurant bien que personne n'a de backup d'un precedent fichier cle.php)
140
+    // si c'est un auteur normal, on ne fait rien, il garde son ancien pass hashé en sha256 en attendant le login d'un webmestre
141
+    if (!$secret and $auteur_peut_sauver_cles) {
142
+        if (auth_spip_initialiser_secret()) {
143
+            $secret = $cles->getSecretAuth();
144
+        }
145
+    }
146
+
147
+    // login/mot de passe incorrect
148
+    if (empty($row)) {
149
+        return [];
150
+    }
151
+
152
+    // fait tourner le codage du pass dans la base
153
+    // sauf si phpauth : cela reviendrait a changer l'alea a chaque hit, et aucune action verifiable par securiser_action()
154
+    if (!$phpauth and $secret) {
155
+        include_spip('inc/acces'); // pour creer_uniqid et verifier_htaccess
156
+        $pass_hash_next = Password::hacher($pass, $secret);
157
+        if ($pass_hash_next) {
158
+            $set = [
159
+                'alea_actuel' => 'alea_futur', // @deprecated 4.1
160
+                'alea_futur' => sql_quote(creer_uniqid(), $serveur, 'text'), // @deprecated 4.1
161
+                'pass' => sql_quote($pass_hash_next, $serveur, 'text'),
162
+            ];
163
+
164
+            // regenerer un htpass si on a active/desactive le plugin htpasswd
165
+            // et/ou que l'algo a change - pour etre certain de toujours utiliser le bon algo
166
+            $htpass = generer_htpass($pass);
167
+            if (strlen($htpass) !== strlen($row['htpass'])) {
168
+                $set['htpass'] = sql_quote($htpass, $serveur, 'text');
169
+            }
170
+
171
+            // a chaque login de webmestre : sauvegarde chiffree des clés du site (avec les pass du webmestre)
172
+            if ($auteur_peut_sauver_cles) {
173
+                $set['backup_cles'] = sql_quote($cles->backup($pass), $serveur, 'text');
174
+            }
175
+
176
+            @sql_update(
177
+                'spip_auteurs',
178
+                $set,
179
+                'id_auteur=' . intval($row['id_auteur']) . ' AND pass=' . sql_quote(
180
+                    $row['pass'],
181
+                    $serveur,
182
+                    'text'
183
+                ),
184
+                [],
185
+                $serveur
186
+            );
187
+
188
+            // si on a change le htpass car changement d'algo, regenerer les fichiers htpasswd
189
+            if (isset($set['htpass'])) {
190
+                ecrire_acces();
191
+            }
192
+        }
193
+
194
+        // En profiter pour verifier la securite de tmp/
195
+        // Si elle ne fonctionne pas a l'installation, prevenir
196
+        if (!verifier_htaccess(_DIR_TMP) and defined('_ECRIRE_INSTALL')) {
197
+            return false;
198
+        }
199
+    }
200
+
201
+    return $row;
202 202
 }
203 203
 
204 204
 /**
@@ -213,37 +213,37 @@  discard block
 block discarded – undo
213 213
  * @return bool
214 214
  */
215 215
 function auth_spip_initialiser_secret(bool $force = false): bool {
216
-	include_spip('inc/chiffrer');
217
-	$cles = SpipCles::instance();
218
-	$secret = $cles->getSecretAuth();
219
-
220
-	// on ne fait rien si on a un secret dispo
221
-	if ($secret) {
222
-		return false;
223
-	}
224
-
225
-	// si force, on ne verifie pas la presence d'un backup chez un webmestre
226
-	if ($force) {
227
-		spip_log('Pas de cle secrete disponible, on regenere une nouvelle cle forcee - tous les mots de passe sont invalides', 'auth' . _LOG_INFO_IMPORTANTE);
228
-		$secret = $cles->getSecretAuth(true);
229
-		return true;
230
-	}
231
-
232
-	$has_backup = sql_allfetsel('id_auteur', 'spip_auteurs', 'statut=' . sql_quote('0minirezo') . ' AND webmestre=' . sql_quote('oui') . " AND backup_cles!=''");
233
-	$has_backup = array_column($has_backup, 'id_auteur');
234
-	if (empty($has_backup)) {
235
-		spip_log("Pas de cle secrete disponible, et aucun webmestre n'a de backup, on regenere une nouvelle cle - tous les mots de passe sont invalides", 'auth' . _LOG_INFO_IMPORTANTE);
236
-		if ($secret = $cles->getSecretAuth(true)) {
237
-			return true;
238
-		}
239
-		spip_log("Echec generation d'une nouvelle cle : verifier les droits d'ecriture ?", 'auth' . _LOG_ERREUR);
240
-		// et on echoue car on ne veut pas que la situation reste telle quelle
241
-		raler_fichier(_DIR_ETC . 'cles.php');
242
-	}
243
-	else {
244
-		spip_log('Pas de cle secrete disponible (fichier config/cle.php absent ?) un des webmestres #' . implode(', #', $has_backup) . ' doit se connecter pour restaurer son backup des cles', 'auth' . _LOG_ERREUR);
245
-	}
246
-	return false;
216
+    include_spip('inc/chiffrer');
217
+    $cles = SpipCles::instance();
218
+    $secret = $cles->getSecretAuth();
219
+
220
+    // on ne fait rien si on a un secret dispo
221
+    if ($secret) {
222
+        return false;
223
+    }
224
+
225
+    // si force, on ne verifie pas la presence d'un backup chez un webmestre
226
+    if ($force) {
227
+        spip_log('Pas de cle secrete disponible, on regenere une nouvelle cle forcee - tous les mots de passe sont invalides', 'auth' . _LOG_INFO_IMPORTANTE);
228
+        $secret = $cles->getSecretAuth(true);
229
+        return true;
230
+    }
231
+
232
+    $has_backup = sql_allfetsel('id_auteur', 'spip_auteurs', 'statut=' . sql_quote('0minirezo') . ' AND webmestre=' . sql_quote('oui') . " AND backup_cles!=''");
233
+    $has_backup = array_column($has_backup, 'id_auteur');
234
+    if (empty($has_backup)) {
235
+        spip_log("Pas de cle secrete disponible, et aucun webmestre n'a de backup, on regenere une nouvelle cle - tous les mots de passe sont invalides", 'auth' . _LOG_INFO_IMPORTANTE);
236
+        if ($secret = $cles->getSecretAuth(true)) {
237
+            return true;
238
+        }
239
+        spip_log("Echec generation d'une nouvelle cle : verifier les droits d'ecriture ?", 'auth' . _LOG_ERREUR);
240
+        // et on echoue car on ne veut pas que la situation reste telle quelle
241
+        raler_fichier(_DIR_ETC . 'cles.php');
242
+    }
243
+    else {
244
+        spip_log('Pas de cle secrete disponible (fichier config/cle.php absent ?) un des webmestres #' . implode(', #', $has_backup) . ' doit se connecter pour restaurer son backup des cles', 'auth' . _LOG_ERREUR);
245
+    }
246
+    return false;
247 247
 }
248 248
 
249 249
 /**
@@ -253,19 +253,19 @@  discard block
 block discarded – undo
253 253
  * @return array
254 254
  */
255 255
 function auth_spip_formulaire_login($flux) {
256
-	// javascript qui gere la securite du login en evitant de faire circuler le pass en clair
257
-	$js = file_get_contents(find_in_path('prive/javascript/login.js'));
258
-	$flux['data'] .=
259
-		  '<script type="text/javascript">/*<![CDATA[*/'
260
-		. "$js\n"
261
-		. "var login_info={'login':'" . $flux['args']['contexte']['var_login'] . "',"
262
-		. "'page_auteur': '" . generer_url_public('informer_auteur') . "',"
263
-		. "'informe_auteur_en_cours':false,"
264
-		. "'attente_informe':0};"
265
-		. "jQuery(function(){jQuery('#var_login').change(actualise_auteur);});"
266
-		. '/*]]>*/</script>';
267
-
268
-	return $flux;
256
+    // javascript qui gere la securite du login en evitant de faire circuler le pass en clair
257
+    $js = file_get_contents(find_in_path('prive/javascript/login.js'));
258
+    $flux['data'] .=
259
+            '<script type="text/javascript">/*<![CDATA[*/'
260
+        . "$js\n"
261
+        . "var login_info={'login':'" . $flux['args']['contexte']['var_login'] . "',"
262
+        . "'page_auteur': '" . generer_url_public('informer_auteur') . "',"
263
+        . "'informe_auteur_en_cours':false,"
264
+        . "'attente_informe':0};"
265
+        . "jQuery(function(){jQuery('#var_login').change(actualise_auteur);});"
266
+        . '/*]]>*/</script>';
267
+
268
+    return $flux;
269 269
 }
270 270
 
271 271
 
@@ -277,11 +277,11 @@  discard block
 block discarded – undo
277 277
  *   toujours true pour un auteur cree dans SPIP
278 278
  */
279 279
 function auth_spip_autoriser_modifier_login(string $serveur = ''): bool {
280
-	// les fonctions d'ecriture sur base distante sont encore incompletes
281
-	if (strlen($serveur)) {
282
-		return false;
283
-	}
284
-	return true;
280
+    // les fonctions d'ecriture sur base distante sont encore incompletes
281
+    if (strlen($serveur)) {
282
+        return false;
283
+    }
284
+    return true;
285 285
 }
286 286
 
287 287
 /**
@@ -295,25 +295,25 @@  discard block
 block discarded – undo
295 295
  *  message d'erreur si login non valide, chaine vide sinon
296 296
  */
297 297
 function auth_spip_verifier_login($new_login, $id_auteur = 0, $serveur = '') {
298
-	// login et mot de passe
299
-	if (strlen($new_login)) {
300
-		if (strlen($new_login) < _LOGIN_TROP_COURT) {
301
-			return _T('info_login_trop_court_car_pluriel', ['nb' => _LOGIN_TROP_COURT]);
302
-		} else {
303
-			$n = sql_countsel(
304
-				'spip_auteurs',
305
-				'login=' . sql_quote($new_login) . ' AND id_auteur!=' . intval($id_auteur) . " AND statut!='5poubelle'",
306
-				'',
307
-				'',
308
-				$serveur
309
-			);
310
-			if ($n) {
311
-				return _T('info_login_existant');
312
-			}
313
-		}
314
-	}
315
-
316
-	return '';
298
+    // login et mot de passe
299
+    if (strlen($new_login)) {
300
+        if (strlen($new_login) < _LOGIN_TROP_COURT) {
301
+            return _T('info_login_trop_court_car_pluriel', ['nb' => _LOGIN_TROP_COURT]);
302
+        } else {
303
+            $n = sql_countsel(
304
+                'spip_auteurs',
305
+                'login=' . sql_quote($new_login) . ' AND id_auteur!=' . intval($id_auteur) . " AND statut!='5poubelle'",
306
+                '',
307
+                '',
308
+                $serveur
309
+            );
310
+            if ($n) {
311
+                return _T('info_login_existant');
312
+            }
313
+        }
314
+    }
315
+
316
+    return '';
317 317
 }
318 318
 
319 319
 /**
@@ -325,41 +325,41 @@  discard block
 block discarded – undo
325 325
  * @return bool
326 326
  */
327 327
 function auth_spip_modifier_login($new_login, $id_auteur, $serveur = '') {
328
-	if (is_null($new_login) or auth_spip_verifier_login($new_login, $id_auteur, $serveur) != '') {
329
-		return false;
330
-	}
331
-	if (
332
-		!$id_auteur = intval($id_auteur)
333
-		or !$auteur = sql_fetsel('login', 'spip_auteurs', 'id_auteur=' . intval($id_auteur), '', '', '', '', $serveur)
334
-	) {
335
-		return false;
336
-	}
337
-	if ($new_login == $auteur['login']) {
338
-		return true;
339
-	} // on a rien fait mais c'est bon !
340
-
341
-	include_spip('action/editer_auteur');
342
-
343
-	// vider le login des auteurs a la poubelle qui avaient ce meme login
344
-	if (strlen($new_login)) {
345
-		$anciens = sql_allfetsel(
346
-			'id_auteur',
347
-			'spip_auteurs',
348
-			'login=' . sql_quote($new_login, $serveur, 'text') . " AND statut='5poubelle'",
349
-			'',
350
-			'',
351
-			'',
352
-			'',
353
-			$serveur
354
-		);
355
-		while ($row = array_pop($anciens)) {
356
-			auteur_modifier($row['id_auteur'], ['login' => ''], true); // manque la gestion de $serveur
357
-		}
358
-	}
359
-
360
-	auteur_modifier($id_auteur, ['login' => $new_login], true); // manque la gestion de $serveur
361
-
362
-	return true;
328
+    if (is_null($new_login) or auth_spip_verifier_login($new_login, $id_auteur, $serveur) != '') {
329
+        return false;
330
+    }
331
+    if (
332
+        !$id_auteur = intval($id_auteur)
333
+        or !$auteur = sql_fetsel('login', 'spip_auteurs', 'id_auteur=' . intval($id_auteur), '', '', '', '', $serveur)
334
+    ) {
335
+        return false;
336
+    }
337
+    if ($new_login == $auteur['login']) {
338
+        return true;
339
+    } // on a rien fait mais c'est bon !
340
+
341
+    include_spip('action/editer_auteur');
342
+
343
+    // vider le login des auteurs a la poubelle qui avaient ce meme login
344
+    if (strlen($new_login)) {
345
+        $anciens = sql_allfetsel(
346
+            'id_auteur',
347
+            'spip_auteurs',
348
+            'login=' . sql_quote($new_login, $serveur, 'text') . " AND statut='5poubelle'",
349
+            '',
350
+            '',
351
+            '',
352
+            '',
353
+            $serveur
354
+        );
355
+        while ($row = array_pop($anciens)) {
356
+            auteur_modifier($row['id_auteur'], ['login' => ''], true); // manque la gestion de $serveur
357
+        }
358
+    }
359
+
360
+    auteur_modifier($id_auteur, ['login' => $new_login], true); // manque la gestion de $serveur
361
+
362
+    return true;
363 363
 }
364 364
 
365 365
 /**
@@ -371,44 +371,44 @@  discard block
 block discarded – undo
371 371
  * @return string
372 372
  */
373 373
 function auth_spip_retrouver_login($login, $serveur = '') {
374
-	if (!strlen($login)) {
375
-		return null;
376
-	} // pas la peine de requeter
377
-	$l = sql_quote($login, $serveur, 'text');
378
-	if (
379
-		$r = sql_getfetsel(
380
-			'login',
381
-			'spip_auteurs',
382
-			"statut<>'5poubelle'" .
383
-			' AND (length(pass)>0)' .
384
-			" AND (login=$l)",
385
-			'',
386
-			'',
387
-			'',
388
-			'',
389
-			$serveur
390
-		)
391
-	) {
392
-		return $r;
393
-	}
394
-	// Si pas d'auteur avec ce login
395
-	// regarder s'il a saisi son nom ou son mail.
396
-	// Ne pas fusionner avec la requete precedente
397
-	// car un nom peut etre homonyme d'un autre login
398
-	else {
399
-		return sql_getfetsel(
400
-			'login',
401
-			'spip_auteurs',
402
-			"statut<>'5poubelle'" .
403
-			' AND (length(pass)>0)' .
404
-			" AND (login<>'' AND (nom=$l OR email=$l))",
405
-			'',
406
-			'',
407
-			'',
408
-			'',
409
-			$serveur
410
-		);
411
-	}
374
+    if (!strlen($login)) {
375
+        return null;
376
+    } // pas la peine de requeter
377
+    $l = sql_quote($login, $serveur, 'text');
378
+    if (
379
+        $r = sql_getfetsel(
380
+            'login',
381
+            'spip_auteurs',
382
+            "statut<>'5poubelle'" .
383
+            ' AND (length(pass)>0)' .
384
+            " AND (login=$l)",
385
+            '',
386
+            '',
387
+            '',
388
+            '',
389
+            $serveur
390
+        )
391
+    ) {
392
+        return $r;
393
+    }
394
+    // Si pas d'auteur avec ce login
395
+    // regarder s'il a saisi son nom ou son mail.
396
+    // Ne pas fusionner avec la requete precedente
397
+    // car un nom peut etre homonyme d'un autre login
398
+    else {
399
+        return sql_getfetsel(
400
+            'login',
401
+            'spip_auteurs',
402
+            "statut<>'5poubelle'" .
403
+            ' AND (length(pass)>0)' .
404
+            " AND (login<>'' AND (nom=$l OR email=$l))",
405
+            '',
406
+            '',
407
+            '',
408
+            '',
409
+            $serveur
410
+        );
411
+    }
412 412
 }
413 413
 
414 414
 /**
@@ -419,11 +419,11 @@  discard block
 block discarded – undo
419 419
  *  toujours true pour un auteur cree dans SPIP
420 420
  */
421 421
 function auth_spip_autoriser_modifier_pass(string $serveur = ''): bool {
422
-	// les fonctions d'ecriture sur base distante sont encore incompletes
423
-	if (strlen($serveur)) {
424
-		return false;
425
-	}
426
-	return true;
422
+    // les fonctions d'ecriture sur base distante sont encore incompletes
423
+    if (strlen($serveur)) {
424
+        return false;
425
+    }
426
+    return true;
427 427
 }
428 428
 
429 429
 
@@ -444,12 +444,12 @@  discard block
 block discarded – undo
444 444
  *  message d'erreur si login non valide, chaine vide sinon
445 445
  */
446 446
 function auth_spip_verifier_pass($login, $new_pass, $id_auteur = 0, $serveur = '') {
447
-	// login et mot de passe
448
-	if (strlen($new_pass) < _PASS_LONGUEUR_MINI) {
449
-		return _T('info_passe_trop_court_car_pluriel', ['nb' => _PASS_LONGUEUR_MINI]);
450
-	}
447
+    // login et mot de passe
448
+    if (strlen($new_pass) < _PASS_LONGUEUR_MINI) {
449
+        return _T('info_passe_trop_court_car_pluriel', ['nb' => _PASS_LONGUEUR_MINI]);
450
+    }
451 451
 
452
-	return '';
452
+    return '';
453 453
 }
454 454
 
455 455
 /**
@@ -463,48 +463,48 @@  discard block
 block discarded – undo
463 463
  * @return bool
464 464
  */
465 465
 function auth_spip_modifier_pass($login, $new_pass, $id_auteur, $serveur = '') {
466
-	if (is_null($new_pass) or auth_spip_verifier_pass($login, $new_pass, $id_auteur, $serveur) != '') {
467
-		return false;
468
-	}
469
-
470
-	if (
471
-		!$id_auteur = intval($id_auteur)
472
-		or !$auteur = sql_fetsel('login, statut, webmestre', 'spip_auteurs', 'id_auteur=' . intval($id_auteur), '', '', '', '', $serveur)
473
-	) {
474
-		return false;
475
-	}
476
-
477
-	include_spip('inc/chiffrer');
478
-	$cles = SpipCles::instance();
479
-	$secret = $cles->getSecretAuth();
480
-	if (!$secret) {
481
-		if (auth_spip_initialiser_secret()) {
482
-			$secret = $cles->getSecretAuth();
483
-		}
484
-		else {
485
-			return false;
486
-		}
487
-	}
488
-
489
-
490
-	include_spip('inc/acces');
491
-	$set = [
492
-		'pass' => Password::hacher($new_pass, $secret),
493
-		'htpass' => generer_htpass($new_pass),
494
-		'alea_actuel' => creer_uniqid(), // @deprecated 4.1
495
-		'alea_futur' => creer_uniqid(), // @deprecated 4.1
496
-		'low_sec' => '',
497
-	];
498
-
499
-	// si c'est un webmestre, on met a jour son backup des cles
500
-	if ($auteur['statut'] === '0minirezo' and $auteur['webmestre'] === 'oui') {
501
-		$set['backup_cles'] = $cles->backup($new_pass);
502
-	}
503
-
504
-	include_spip('action/editer_auteur');
505
-	auteur_modifier($id_auteur, $set, true); // manque la gestion de $serveur
506
-
507
-	return true; // on a bien modifie le pass
466
+    if (is_null($new_pass) or auth_spip_verifier_pass($login, $new_pass, $id_auteur, $serveur) != '') {
467
+        return false;
468
+    }
469
+
470
+    if (
471
+        !$id_auteur = intval($id_auteur)
472
+        or !$auteur = sql_fetsel('login, statut, webmestre', 'spip_auteurs', 'id_auteur=' . intval($id_auteur), '', '', '', '', $serveur)
473
+    ) {
474
+        return false;
475
+    }
476
+
477
+    include_spip('inc/chiffrer');
478
+    $cles = SpipCles::instance();
479
+    $secret = $cles->getSecretAuth();
480
+    if (!$secret) {
481
+        if (auth_spip_initialiser_secret()) {
482
+            $secret = $cles->getSecretAuth();
483
+        }
484
+        else {
485
+            return false;
486
+        }
487
+    }
488
+
489
+
490
+    include_spip('inc/acces');
491
+    $set = [
492
+        'pass' => Password::hacher($new_pass, $secret),
493
+        'htpass' => generer_htpass($new_pass),
494
+        'alea_actuel' => creer_uniqid(), // @deprecated 4.1
495
+        'alea_futur' => creer_uniqid(), // @deprecated 4.1
496
+        'low_sec' => '',
497
+    ];
498
+
499
+    // si c'est un webmestre, on met a jour son backup des cles
500
+    if ($auteur['statut'] === '0minirezo' and $auteur['webmestre'] === 'oui') {
501
+        $set['backup_cles'] = $cles->backup($new_pass);
502
+    }
503
+
504
+    include_spip('action/editer_auteur');
505
+    auteur_modifier($id_auteur, $set, true); // manque la gestion de $serveur
506
+
507
+    return true; // on a bien modifie le pass
508 508
 }
509 509
 
510 510
 /**
@@ -518,58 +518,58 @@  discard block
 block discarded – undo
518 518
  * @return void
519 519
  */
520 520
 function auth_spip_synchroniser_distant($id_auteur, $champs, $options = [], string $serveur = ''): void {
521
-	// ne rien faire pour une base distante : on ne sait pas regenerer les htaccess
522
-	if (strlen($serveur)) {
523
-		return;
524
-	}
525
-	// si un login, pass ou statut a ete modifie
526
-	// regenerer les fichier htpass
527
-	if (
528
-		isset($champs['login'])
529
-		or isset($champs['pass'])
530
-		or isset($champs['statut'])
531
-		or (isset($options['all']) and $options['all'])
532
-	) {
533
-		$htaccess = _DIR_RESTREINT . _ACCESS_FILE_NAME;
534
-		$htpasswd = _DIR_TMP . _AUTH_USER_FILE;
535
-
536
-		// Cette variable de configuration peut etre posee par un plugin
537
-		// par exemple acces_restreint ;
538
-		// si .htaccess existe, outrepasser spip_meta
539
-		if (
540
-			(!isset($GLOBALS['meta']['creer_htpasswd']) or ($GLOBALS['meta']['creer_htpasswd'] != 'oui'))
541
-			and !@file_exists($htaccess)
542
-		) {
543
-			spip_unlink($htpasswd);
544
-			spip_unlink($htpasswd . '-admin');
545
-
546
-			return;
547
-		}
548
-
549
-		# remarque : ici on laisse passer les "nouveau" de maniere a leur permettre
550
-		# de devenir redacteur le cas echeant (auth http)... a nettoyer
551
-		// attention, il faut au prealable se connecter a la base (necessaire car utilise par install)
552
-
553
-		$p1 = ''; // login:htpass pour tous
554
-		$p2 = ''; // login:htpass pour les admins
555
-		$s = sql_select(
556
-			'login, htpass, statut',
557
-			'spip_auteurs',
558
-			sql_in('statut', ['1comite', '0minirezo', 'nouveau'])
559
-		);
560
-		while ($t = sql_fetch($s)) {
561
-			if (strlen($t['login']) and strlen($t['htpass'])) {
562
-				$p1 .= $t['login'] . ':' . $t['htpass'] . "\n";
563
-				if ($t['statut'] == '0minirezo') {
564
-					$p2 .= $t['login'] . ':' . $t['htpass'] . "\n";
565
-				}
566
-			}
567
-		}
568
-		sql_free($s);
569
-		if ($p1) {
570
-			ecrire_fichier($htpasswd, $p1);
571
-			ecrire_fichier($htpasswd . '-admin', $p2);
572
-			spip_log("Ecriture de $htpasswd et $htpasswd-admin");
573
-		}
574
-	}
521
+    // ne rien faire pour une base distante : on ne sait pas regenerer les htaccess
522
+    if (strlen($serveur)) {
523
+        return;
524
+    }
525
+    // si un login, pass ou statut a ete modifie
526
+    // regenerer les fichier htpass
527
+    if (
528
+        isset($champs['login'])
529
+        or isset($champs['pass'])
530
+        or isset($champs['statut'])
531
+        or (isset($options['all']) and $options['all'])
532
+    ) {
533
+        $htaccess = _DIR_RESTREINT . _ACCESS_FILE_NAME;
534
+        $htpasswd = _DIR_TMP . _AUTH_USER_FILE;
535
+
536
+        // Cette variable de configuration peut etre posee par un plugin
537
+        // par exemple acces_restreint ;
538
+        // si .htaccess existe, outrepasser spip_meta
539
+        if (
540
+            (!isset($GLOBALS['meta']['creer_htpasswd']) or ($GLOBALS['meta']['creer_htpasswd'] != 'oui'))
541
+            and !@file_exists($htaccess)
542
+        ) {
543
+            spip_unlink($htpasswd);
544
+            spip_unlink($htpasswd . '-admin');
545
+
546
+            return;
547
+        }
548
+
549
+        # remarque : ici on laisse passer les "nouveau" de maniere a leur permettre
550
+        # de devenir redacteur le cas echeant (auth http)... a nettoyer
551
+        // attention, il faut au prealable se connecter a la base (necessaire car utilise par install)
552
+
553
+        $p1 = ''; // login:htpass pour tous
554
+        $p2 = ''; // login:htpass pour les admins
555
+        $s = sql_select(
556
+            'login, htpass, statut',
557
+            'spip_auteurs',
558
+            sql_in('statut', ['1comite', '0minirezo', 'nouveau'])
559
+        );
560
+        while ($t = sql_fetch($s)) {
561
+            if (strlen($t['login']) and strlen($t['htpass'])) {
562
+                $p1 .= $t['login'] . ':' . $t['htpass'] . "\n";
563
+                if ($t['statut'] == '0minirezo') {
564
+                    $p2 .= $t['login'] . ':' . $t['htpass'] . "\n";
565
+                }
566
+            }
567
+        }
568
+        sql_free($s);
569
+        if ($p1) {
570
+            ecrire_fichier($htpasswd, $p1);
571
+            ecrire_fichier($htpasswd . '-admin', $p2);
572
+            spip_log("Ecriture de $htpasswd et $htpasswd-admin");
573
+        }
574
+    }
575 575
 }
Please login to merge, or discard this patch.
Spacing   +34 added lines, -34 removed lines patch added patch discarded remove patch
@@ -49,7 +49,7 @@  discard block
 block discarded – undo
49 49
 		$row = sql_fetsel(
50 50
 			'*',
51 51
 			'spip_auteurs',
52
-			'login=' . sql_quote($login, $serveur, 'text') . " AND statut<>'5poubelle'",
52
+			'login='.sql_quote($login, $serveur, 'text')." AND statut<>'5poubelle'",
53 53
 			'',
54 54
 			'',
55 55
 			'',
@@ -78,20 +78,20 @@  discard block
 block discarded – undo
78 78
 		// legacy = md5 ou sha256
79 79
 		case 32:
80 80
 			// tres anciens mots de passe encodes en md5(alea.pass)
81
-			$hash = md5($row['alea_actuel'] . $pass);
81
+			$hash = md5($row['alea_actuel'].$pass);
82 82
 			$methode = 'md5';
83 83
 		case 64:
84 84
 			if (empty($hash)) {
85 85
 				// anciens mots de passe encodes en sha256(alea.pass)
86 86
 				include_spip('auth/sha256.inc');
87
-				$hash = spip_sha256($row['alea_actuel'] . $pass);
87
+				$hash = spip_sha256($row['alea_actuel'].$pass);
88 88
 				$methode = 'sha256';
89 89
 			}
90 90
 			if ($row['pass'] === $hash) {
91
-				spip_log("validation du mot de passe pour l'auteur #".$row['id_auteur']." $login via $methode", 'auth' . _LOG_DEBUG);
91
+				spip_log("validation du mot de passe pour l'auteur #".$row['id_auteur']." $login via $methode", 'auth'._LOG_DEBUG);
92 92
 				// ce n'est pas cense arriver, mais si jamais c'est un backup inutilisable, il faut le nettoyer pour ne pas bloquer la creation d'une nouvelle cle d'auth
93 93
 				if (!empty($row['backup_cles'])) {
94
-					sql_updateq('spip_auteurs', ['backup_cles' => ''], 'id_auteur=' . intval($row['id_auteur']));
94
+					sql_updateq('spip_auteurs', ['backup_cles' => ''], 'id_auteur='.intval($row['id_auteur']));
95 95
 				}
96 96
 				break;
97 97
 			}
@@ -109,19 +109,19 @@  discard block
 block discarded – undo
109 109
 				and !empty($row['backup_cles'])
110 110
 			) {
111 111
 				if ($cles->restore($row['backup_cles'], $pass, $row['pass'], $row['id_auteur'])) {
112
-					spip_log('Les cles secretes ont ete restaurées avec le backup du webmestre #' . $row['id_auteur'], 'auth' . _LOG_INFO_IMPORTANTE);
112
+					spip_log('Les cles secretes ont ete restaurées avec le backup du webmestre #'.$row['id_auteur'], 'auth'._LOG_INFO_IMPORTANTE);
113 113
 					if ($cles->save()) {
114 114
 						$secret = $cles->getSecretAuth();
115 115
 					}
116 116
 					else {
117
-						spip_log("Echec restauration des cles : verifier les droits d'ecriture ?", 'auth' . _LOG_ERREUR);
117
+						spip_log("Echec restauration des cles : verifier les droits d'ecriture ?", 'auth'._LOG_ERREUR);
118 118
 						// et on echoue car on ne veut pas que la situation reste telle quelle
119
-						raler_fichier(_DIR_ETC . 'cles.php');
119
+						raler_fichier(_DIR_ETC.'cles.php');
120 120
 					}
121 121
 				}
122 122
 				else {
123
-					spip_log('Pas de cle secrete disponible (fichier config/cle.php absent ?) mais le backup du webmestre #' . $row['id_auteur'] . " n'est pas valide", 'auth' . _LOG_ERREUR);
124
-					sql_updateq('spip_auteurs', ['backup_cles' => ''], 'id_auteur=' . intval($row['id_auteur']));
123
+					spip_log('Pas de cle secrete disponible (fichier config/cle.php absent ?) mais le backup du webmestre #'.$row['id_auteur']." n'est pas valide", 'auth'._LOG_ERREUR);
124
+					sql_updateq('spip_auteurs', ['backup_cles' => ''], 'id_auteur='.intval($row['id_auteur']));
125 125
 				}
126 126
 			}
127 127
 
@@ -129,7 +129,7 @@  discard block
 block discarded – undo
129 129
 				unset($row);
130 130
 			}
131 131
 			else {
132
-				spip_log("validation du mot de passe pour l'auteur #".$row['id_auteur']." $login via Password::verifier", 'auth' . _LOG_DEBUG);
132
+				spip_log("validation du mot de passe pour l'auteur #".$row['id_auteur']." $login via Password::verifier", 'auth'._LOG_DEBUG);
133 133
 			}
134 134
 			break;
135 135
 	}
@@ -176,7 +176,7 @@  discard block
 block discarded – undo
176 176
 			@sql_update(
177 177
 				'spip_auteurs',
178 178
 				$set,
179
-				'id_auteur=' . intval($row['id_auteur']) . ' AND pass=' . sql_quote(
179
+				'id_auteur='.intval($row['id_auteur']).' AND pass='.sql_quote(
180 180
 					$row['pass'],
181 181
 					$serveur,
182 182
 					'text'
@@ -224,24 +224,24 @@  discard block
 block discarded – undo
224 224
 
225 225
 	// si force, on ne verifie pas la presence d'un backup chez un webmestre
226 226
 	if ($force) {
227
-		spip_log('Pas de cle secrete disponible, on regenere une nouvelle cle forcee - tous les mots de passe sont invalides', 'auth' . _LOG_INFO_IMPORTANTE);
227
+		spip_log('Pas de cle secrete disponible, on regenere une nouvelle cle forcee - tous les mots de passe sont invalides', 'auth'._LOG_INFO_IMPORTANTE);
228 228
 		$secret = $cles->getSecretAuth(true);
229 229
 		return true;
230 230
 	}
231 231
 
232
-	$has_backup = sql_allfetsel('id_auteur', 'spip_auteurs', 'statut=' . sql_quote('0minirezo') . ' AND webmestre=' . sql_quote('oui') . " AND backup_cles!=''");
232
+	$has_backup = sql_allfetsel('id_auteur', 'spip_auteurs', 'statut='.sql_quote('0minirezo').' AND webmestre='.sql_quote('oui')." AND backup_cles!=''");
233 233
 	$has_backup = array_column($has_backup, 'id_auteur');
234 234
 	if (empty($has_backup)) {
235
-		spip_log("Pas de cle secrete disponible, et aucun webmestre n'a de backup, on regenere une nouvelle cle - tous les mots de passe sont invalides", 'auth' . _LOG_INFO_IMPORTANTE);
235
+		spip_log("Pas de cle secrete disponible, et aucun webmestre n'a de backup, on regenere une nouvelle cle - tous les mots de passe sont invalides", 'auth'._LOG_INFO_IMPORTANTE);
236 236
 		if ($secret = $cles->getSecretAuth(true)) {
237 237
 			return true;
238 238
 		}
239
-		spip_log("Echec generation d'une nouvelle cle : verifier les droits d'ecriture ?", 'auth' . _LOG_ERREUR);
239
+		spip_log("Echec generation d'une nouvelle cle : verifier les droits d'ecriture ?", 'auth'._LOG_ERREUR);
240 240
 		// et on echoue car on ne veut pas que la situation reste telle quelle
241
-		raler_fichier(_DIR_ETC . 'cles.php');
241
+		raler_fichier(_DIR_ETC.'cles.php');
242 242
 	}
243 243
 	else {
244
-		spip_log('Pas de cle secrete disponible (fichier config/cle.php absent ?) un des webmestres #' . implode(', #', $has_backup) . ' doit se connecter pour restaurer son backup des cles', 'auth' . _LOG_ERREUR);
244
+		spip_log('Pas de cle secrete disponible (fichier config/cle.php absent ?) un des webmestres #'.implode(', #', $has_backup).' doit se connecter pour restaurer son backup des cles', 'auth'._LOG_ERREUR);
245 245
 	}
246 246
 	return false;
247 247
 }
@@ -258,8 +258,8 @@  discard block
 block discarded – undo
258 258
 	$flux['data'] .=
259 259
 		  '<script type="text/javascript">/*<![CDATA[*/'
260 260
 		. "$js\n"
261
-		. "var login_info={'login':'" . $flux['args']['contexte']['var_login'] . "',"
262
-		. "'page_auteur': '" . generer_url_public('informer_auteur') . "',"
261
+		. "var login_info={'login':'".$flux['args']['contexte']['var_login']."',"
262
+		. "'page_auteur': '".generer_url_public('informer_auteur')."',"
263 263
 		. "'informe_auteur_en_cours':false,"
264 264
 		. "'attente_informe':0};"
265 265
 		. "jQuery(function(){jQuery('#var_login').change(actualise_auteur);});"
@@ -302,7 +302,7 @@  discard block
 block discarded – undo
302 302
 		} else {
303 303
 			$n = sql_countsel(
304 304
 				'spip_auteurs',
305
-				'login=' . sql_quote($new_login) . ' AND id_auteur!=' . intval($id_auteur) . " AND statut!='5poubelle'",
305
+				'login='.sql_quote($new_login).' AND id_auteur!='.intval($id_auteur)." AND statut!='5poubelle'",
306 306
 				'',
307 307
 				'',
308 308
 				$serveur
@@ -330,7 +330,7 @@  discard block
 block discarded – undo
330 330
 	}
331 331
 	if (
332 332
 		!$id_auteur = intval($id_auteur)
333
-		or !$auteur = sql_fetsel('login', 'spip_auteurs', 'id_auteur=' . intval($id_auteur), '', '', '', '', $serveur)
333
+		or !$auteur = sql_fetsel('login', 'spip_auteurs', 'id_auteur='.intval($id_auteur), '', '', '', '', $serveur)
334 334
 	) {
335 335
 		return false;
336 336
 	}
@@ -345,7 +345,7 @@  discard block
 block discarded – undo
345 345
 		$anciens = sql_allfetsel(
346 346
 			'id_auteur',
347 347
 			'spip_auteurs',
348
-			'login=' . sql_quote($new_login, $serveur, 'text') . " AND statut='5poubelle'",
348
+			'login='.sql_quote($new_login, $serveur, 'text')." AND statut='5poubelle'",
349 349
 			'',
350 350
 			'',
351 351
 			'',
@@ -379,8 +379,8 @@  discard block
 block discarded – undo
379 379
 		$r = sql_getfetsel(
380 380
 			'login',
381 381
 			'spip_auteurs',
382
-			"statut<>'5poubelle'" .
383
-			' AND (length(pass)>0)' .
382
+			"statut<>'5poubelle'".
383
+			' AND (length(pass)>0)'.
384 384
 			" AND (login=$l)",
385 385
 			'',
386 386
 			'',
@@ -399,8 +399,8 @@  discard block
 block discarded – undo
399 399
 		return sql_getfetsel(
400 400
 			'login',
401 401
 			'spip_auteurs',
402
-			"statut<>'5poubelle'" .
403
-			' AND (length(pass)>0)' .
402
+			"statut<>'5poubelle'".
403
+			' AND (length(pass)>0)'.
404 404
 			" AND (login<>'' AND (nom=$l OR email=$l))",
405 405
 			'',
406 406
 			'',
@@ -469,7 +469,7 @@  discard block
 block discarded – undo
469 469
 
470 470
 	if (
471 471
 		!$id_auteur = intval($id_auteur)
472
-		or !$auteur = sql_fetsel('login, statut, webmestre', 'spip_auteurs', 'id_auteur=' . intval($id_auteur), '', '', '', '', $serveur)
472
+		or !$auteur = sql_fetsel('login, statut, webmestre', 'spip_auteurs', 'id_auteur='.intval($id_auteur), '', '', '', '', $serveur)
473 473
 	) {
474 474
 		return false;
475 475
 	}
@@ -530,8 +530,8 @@  discard block
 block discarded – undo
530 530
 		or isset($champs['statut'])
531 531
 		or (isset($options['all']) and $options['all'])
532 532
 	) {
533
-		$htaccess = _DIR_RESTREINT . _ACCESS_FILE_NAME;
534
-		$htpasswd = _DIR_TMP . _AUTH_USER_FILE;
533
+		$htaccess = _DIR_RESTREINT._ACCESS_FILE_NAME;
534
+		$htpasswd = _DIR_TMP._AUTH_USER_FILE;
535 535
 
536 536
 		// Cette variable de configuration peut etre posee par un plugin
537 537
 		// par exemple acces_restreint ;
@@ -541,7 +541,7 @@  discard block
 block discarded – undo
541 541
 			and !@file_exists($htaccess)
542 542
 		) {
543 543
 			spip_unlink($htpasswd);
544
-			spip_unlink($htpasswd . '-admin');
544
+			spip_unlink($htpasswd.'-admin');
545 545
 
546 546
 			return;
547 547
 		}
@@ -559,16 +559,16 @@  discard block
 block discarded – undo
559 559
 		);
560 560
 		while ($t = sql_fetch($s)) {
561 561
 			if (strlen($t['login']) and strlen($t['htpass'])) {
562
-				$p1 .= $t['login'] . ':' . $t['htpass'] . "\n";
562
+				$p1 .= $t['login'].':'.$t['htpass']."\n";
563 563
 				if ($t['statut'] == '0minirezo') {
564
-					$p2 .= $t['login'] . ':' . $t['htpass'] . "\n";
564
+					$p2 .= $t['login'].':'.$t['htpass']."\n";
565 565
 				}
566 566
 			}
567 567
 		}
568 568
 		sql_free($s);
569 569
 		if ($p1) {
570 570
 			ecrire_fichier($htpasswd, $p1);
571
-			ecrire_fichier($htpasswd . '-admin', $p2);
571
+			ecrire_fichier($htpasswd.'-admin', $p2);
572 572
 			spip_log("Ecriture de $htpasswd et $htpasswd-admin");
573 573
 		}
574 574
 	}
Please login to merge, or discard this patch.
Braces   +5 added lines, -10 removed lines patch added patch discarded remove patch
@@ -112,14 +112,12 @@  discard block
 block discarded – undo
112 112
 					spip_log('Les cles secretes ont ete restaurées avec le backup du webmestre #' . $row['id_auteur'], 'auth' . _LOG_INFO_IMPORTANTE);
113 113
 					if ($cles->save()) {
114 114
 						$secret = $cles->getSecretAuth();
115
-					}
116
-					else {
115
+					} else {
117 116
 						spip_log("Echec restauration des cles : verifier les droits d'ecriture ?", 'auth' . _LOG_ERREUR);
118 117
 						// et on echoue car on ne veut pas que la situation reste telle quelle
119 118
 						raler_fichier(_DIR_ETC . 'cles.php');
120 119
 					}
121
-				}
122
-				else {
120
+				} else {
123 121
 					spip_log('Pas de cle secrete disponible (fichier config/cle.php absent ?) mais le backup du webmestre #' . $row['id_auteur'] . " n'est pas valide", 'auth' . _LOG_ERREUR);
124 122
 					sql_updateq('spip_auteurs', ['backup_cles' => ''], 'id_auteur=' . intval($row['id_auteur']));
125 123
 				}
@@ -127,8 +125,7 @@  discard block
 block discarded – undo
127 125
 
128 126
 			if (!$secret or !Password::verifier($pass, $row['pass'], $secret)) {
129 127
 				unset($row);
130
-			}
131
-			else {
128
+			} else {
132 129
 				spip_log("validation du mot de passe pour l'auteur #".$row['id_auteur']." $login via Password::verifier", 'auth' . _LOG_DEBUG);
133 130
 			}
134 131
 			break;
@@ -239,8 +236,7 @@  discard block
 block discarded – undo
239 236
 		spip_log("Echec generation d'une nouvelle cle : verifier les droits d'ecriture ?", 'auth' . _LOG_ERREUR);
240 237
 		// et on echoue car on ne veut pas que la situation reste telle quelle
241 238
 		raler_fichier(_DIR_ETC . 'cles.php');
242
-	}
243
-	else {
239
+	} else {
244 240
 		spip_log('Pas de cle secrete disponible (fichier config/cle.php absent ?) un des webmestres #' . implode(', #', $has_backup) . ' doit se connecter pour restaurer son backup des cles', 'auth' . _LOG_ERREUR);
245 241
 	}
246 242
 	return false;
@@ -480,8 +476,7 @@  discard block
 block discarded – undo
480 476
 	if (!$secret) {
481 477
 		if (auth_spip_initialiser_secret()) {
482 478
 			$secret = $cles->getSecretAuth();
483
-		}
484
-		else {
479
+		} else {
485 480
 			return false;
486 481
 		}
487 482
 	}
Please login to merge, or discard this patch.
ecrire/src/Chiffrer/Chiffrement.php 2 patches
Indentation   +70 added lines, -70 removed lines patch added patch discarded remove patch
@@ -19,78 +19,78 @@
 block discarded – undo
19 19
  * @link https://www.php.net/manual/fr/book.sodium.php
20 20
  */
21 21
 class Chiffrement {
22
-	/** Chiffre un message en utilisant une clé ou un mot de passe */
23
-	public static function chiffrer(
24
-		string $message,
25
-		#[\SensitiveParameter]
26
-		string $key
27
-	): ?string {
28
-		// create a random salt for key derivation
29
-		$salt = random_bytes(SODIUM_CRYPTO_PWHASH_SALTBYTES);
30
-		$key = self::deriveKeyFromPassword($key, $salt);
31
-		$nonce = random_bytes(\SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
32
-		$padded_message = sodium_pad($message, 16);
33
-		$encrypted = sodium_crypto_secretbox($padded_message, $nonce, $key);
34
-		$encoded = base64_encode($salt . $nonce . $encrypted);
35
-		sodium_memzero($key);
36
-		sodium_memzero($nonce);
37
-		sodium_memzero($salt);
38
-		#spip_log("chiffrer($message)=$encoded", 'chiffrer' . _LOG_DEBUG);
39
-		return $encoded;
40
-	}
22
+    /** Chiffre un message en utilisant une clé ou un mot de passe */
23
+    public static function chiffrer(
24
+        string $message,
25
+        #[\SensitiveParameter]
26
+        string $key
27
+    ): ?string {
28
+        // create a random salt for key derivation
29
+        $salt = random_bytes(SODIUM_CRYPTO_PWHASH_SALTBYTES);
30
+        $key = self::deriveKeyFromPassword($key, $salt);
31
+        $nonce = random_bytes(\SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
32
+        $padded_message = sodium_pad($message, 16);
33
+        $encrypted = sodium_crypto_secretbox($padded_message, $nonce, $key);
34
+        $encoded = base64_encode($salt . $nonce . $encrypted);
35
+        sodium_memzero($key);
36
+        sodium_memzero($nonce);
37
+        sodium_memzero($salt);
38
+        #spip_log("chiffrer($message)=$encoded", 'chiffrer' . _LOG_DEBUG);
39
+        return $encoded;
40
+    }
41 41
 
42
-	/** Déchiffre un message en utilisant une clé ou un mot de passe */
43
-	public static function dechiffrer(
44
-		string $encoded,
45
-		#[\SensitiveParameter]
46
-		string $key
47
-	): ?string {
48
-		$decoded = base64_decode($encoded);
49
-		$salt = substr($decoded, 0, \SODIUM_CRYPTO_PWHASH_SALTBYTES);
50
-		$nonce = substr($decoded, \SODIUM_CRYPTO_PWHASH_SALTBYTES, \SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
51
-		$encrypted = substr($decoded, \SODIUM_CRYPTO_PWHASH_SALTBYTES + \SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
52
-		$key = self::deriveKeyFromPassword($key, $salt);
53
-		$padded_message = sodium_crypto_secretbox_open($encrypted, $nonce, $key);
54
-		sodium_memzero($key);
55
-		sodium_memzero($nonce);
56
-		sodium_memzero($salt);
57
-		if ($padded_message === false) {
58
-			spip_log("dechiffrer() chiffre corrompu `$encoded`", 'chiffrer' . _LOG_DEBUG);
59
-			return null;
60
-		}
61
-		$message = sodium_unpad($padded_message, 16);
62
-		#spip_log("dechiffrer($encoded)=$message", 'chiffrer' . _LOG_DEBUG);
63
-		return $message;
64
-	}
42
+    /** Déchiffre un message en utilisant une clé ou un mot de passe */
43
+    public static function dechiffrer(
44
+        string $encoded,
45
+        #[\SensitiveParameter]
46
+        string $key
47
+    ): ?string {
48
+        $decoded = base64_decode($encoded);
49
+        $salt = substr($decoded, 0, \SODIUM_CRYPTO_PWHASH_SALTBYTES);
50
+        $nonce = substr($decoded, \SODIUM_CRYPTO_PWHASH_SALTBYTES, \SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
51
+        $encrypted = substr($decoded, \SODIUM_CRYPTO_PWHASH_SALTBYTES + \SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
52
+        $key = self::deriveKeyFromPassword($key, $salt);
53
+        $padded_message = sodium_crypto_secretbox_open($encrypted, $nonce, $key);
54
+        sodium_memzero($key);
55
+        sodium_memzero($nonce);
56
+        sodium_memzero($salt);
57
+        if ($padded_message === false) {
58
+            spip_log("dechiffrer() chiffre corrompu `$encoded`", 'chiffrer' . _LOG_DEBUG);
59
+            return null;
60
+        }
61
+        $message = sodium_unpad($padded_message, 16);
62
+        #spip_log("dechiffrer($encoded)=$message", 'chiffrer' . _LOG_DEBUG);
63
+        return $message;
64
+    }
65 65
 
66
-	/** Génère une clé de la taille attendue pour le chiffrement */
67
-	public static function keygen(): string {
68
-		return sodium_crypto_secretbox_keygen();
69
-	}
66
+    /** Génère une clé de la taille attendue pour le chiffrement */
67
+    public static function keygen(): string {
68
+        return sodium_crypto_secretbox_keygen();
69
+    }
70 70
 
71
-	/**
72
-	 * Retourne une clé de la taille attendue pour le chiffrement
73
-	 *
74
-	 * Notamment si on utilise un mot de passe comme clé, il faut le hacher
75
-	 * pour servir de clé à la taille correspondante.
76
-	 */
77
-	private static function deriveKeyFromPassword(
78
-		#[\SensitiveParameter]
79
-		string $password,
80
-		string $salt
81
-	): string {
82
-		if (strlen($password) === \SODIUM_CRYPTO_SECRETBOX_KEYBYTES) {
83
-			return $password;
84
-		}
85
-		$key = sodium_crypto_pwhash(
86
-			\SODIUM_CRYPTO_SECRETBOX_KEYBYTES,
87
-			$password,
88
-			$salt,
89
-			\SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE,
90
-			\SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE
91
-		);
92
-		sodium_memzero($password);
71
+    /**
72
+     * Retourne une clé de la taille attendue pour le chiffrement
73
+     *
74
+     * Notamment si on utilise un mot de passe comme clé, il faut le hacher
75
+     * pour servir de clé à la taille correspondante.
76
+     */
77
+    private static function deriveKeyFromPassword(
78
+        #[\SensitiveParameter]
79
+        string $password,
80
+        string $salt
81
+    ): string {
82
+        if (strlen($password) === \SODIUM_CRYPTO_SECRETBOX_KEYBYTES) {
83
+            return $password;
84
+        }
85
+        $key = sodium_crypto_pwhash(
86
+            \SODIUM_CRYPTO_SECRETBOX_KEYBYTES,
87
+            $password,
88
+            $salt,
89
+            \SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE,
90
+            \SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE
91
+        );
92
+        sodium_memzero($password);
93 93
 
94
-		return $key;
95
-	}
94
+        return $key;
95
+    }
96 96
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -31,7 +31,7 @@  discard block
 block discarded – undo
31 31
 		$nonce = random_bytes(\SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
32 32
 		$padded_message = sodium_pad($message, 16);
33 33
 		$encrypted = sodium_crypto_secretbox($padded_message, $nonce, $key);
34
-		$encoded = base64_encode($salt . $nonce . $encrypted);
34
+		$encoded = base64_encode($salt.$nonce.$encrypted);
35 35
 		sodium_memzero($key);
36 36
 		sodium_memzero($nonce);
37 37
 		sodium_memzero($salt);
@@ -48,14 +48,14 @@  discard block
 block discarded – undo
48 48
 		$decoded = base64_decode($encoded);
49 49
 		$salt = substr($decoded, 0, \SODIUM_CRYPTO_PWHASH_SALTBYTES);
50 50
 		$nonce = substr($decoded, \SODIUM_CRYPTO_PWHASH_SALTBYTES, \SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
51
-		$encrypted = substr($decoded, \SODIUM_CRYPTO_PWHASH_SALTBYTES + \SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
51
+		$encrypted = substr($decoded, \SODIUM_CRYPTO_PWHASH_SALTBYTES +\SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
52 52
 		$key = self::deriveKeyFromPassword($key, $salt);
53 53
 		$padded_message = sodium_crypto_secretbox_open($encrypted, $nonce, $key);
54 54
 		sodium_memzero($key);
55 55
 		sodium_memzero($nonce);
56 56
 		sodium_memzero($salt);
57 57
 		if ($padded_message === false) {
58
-			spip_log("dechiffrer() chiffre corrompu `$encoded`", 'chiffrer' . _LOG_DEBUG);
58
+			spip_log("dechiffrer() chiffre corrompu `$encoded`", 'chiffrer'._LOG_DEBUG);
59 59
 			return null;
60 60
 		}
61 61
 		$message = sodium_unpad($padded_message, 16);
Please login to merge, or discard this patch.
ecrire/src/Chiffrer/SpipCles.php 2 patches
Indentation   +167 added lines, -167 removed lines patch added patch discarded remove patch
@@ -14,171 +14,171 @@
 block discarded – undo
14 14
 
15 15
 /** Gestion des clés d’authentification / chiffrement de SPIP */
16 16
 final class SpipCles {
17
-	private static array $instances = [];
18
-
19
-	private string $file = _DIR_ETC . 'cles.php';
20
-	private Cles $cles;
21
-
22
-	public static function instance(string $file = ''): self {
23
-		if (empty(self::$instances[$file])) {
24
-			self::$instances[$file] = new self($file);
25
-		}
26
-		return self::$instances[$file];
27
-	}
28
-
29
-	/**
30
-	 * Retourne le secret du site (shorthand)
31
-	 * @uses self::getSecretSite()
32
-	 */
33
-	public static function secret_du_site(): ?string {
34
-		return (self::instance())->getSecretSite();
35
-	}
36
-
37
-	private function __construct(string $file = '') {
38
-		if ($file) {
39
-			$this->file = $file;
40
-		}
41
-		$this->cles = new Cles($this->read());
42
-	}
43
-
44
-	/**
45
-	 * Renvoyer le secret du site
46
-	 *
47
-	 * Le secret du site doit rester aussi secret que possible, et est eternel
48
-	 * On ne doit pas l'exporter
49
-	 *
50
-	 * Le secret est partagé entre une clé disque et une clé bdd
51
-	 *
52
-	 * @return string
53
-	 */
54
-	public function getSecretSite(bool $autoInit = true): ?string {
55
-		$key = $this->getKey('secret_du_site', $autoInit);
56
-		$meta = $this->getMetaKey('secret_du_site', $autoInit);
57
-		// conserve la même longeur.
58
-		return $key ^ $meta;
59
-	}
60
-
61
-	/** Renvoyer le secret des authentifications */
62
-	public function getSecretAuth(bool $autoInit = false): ?string {
63
-		return $this->getKey('secret_des_auth', $autoInit);
64
-	}
65
-	public function save(): bool {
66
-		return ecrire_fichier_securise($this->file, $this->cles->toJson());
67
-	}
68
-
69
-	/**
70
-	 * Fournir une sauvegarde chiffree des cles (a l'aide d'une autre clé, comme le pass d'un auteur)
71
-	 *
72
-	 * @param string $withKey Clé de chiffrage de la sauvegarde
73
-	 * @return string Contenu de la sauvegarde chiffrée générée
74
-	 */
75
-	public function backup(
76
-		#[\SensitiveParameter]
77
-		string $withKey
78
-	): string {
79
-		if (count($this->cles)) {
80
-			return Chiffrement::chiffrer($this->cles->toJson(), $withKey);
81
-		}
82
-		return '';
83
-	}
84
-
85
-	/**
86
-	 * Restaurer les cles manquantes depuis une sauvegarde chiffree des cles
87
-	 * (si la sauvegarde est bien valide)
88
-	 *
89
-	 * @param string $backup Sauvegarde chiffrée (générée par backup())
90
-	 * @param int $id_auteur
91
-	 * @param string $pass
92
-	 * @return void
93
-	 */
94
-	public function restore(
95
-		string $backup,
96
-		#[\SensitiveParameter]
97
-		string $password_clair,
98
-		#[\SensitiveParameter]
99
-		string $password_hash,
100
-		int $id_auteur
101
-	): bool {
102
-		if (empty($backup)) {
103
-			return false;
104
-		}
105
-
106
-		$sauvegarde = Chiffrement::dechiffrer($backup, $password_clair);
107
-		$json = json_decode($sauvegarde, true);
108
-		if (!$json) {
109
-			return false;
110
-		}
111
-
112
-		// cela semble une sauvegarde valide
113
-		$cles_potentielles = array_map('base64_decode', $json);
114
-
115
-		// il faut faire une double verif sur secret_des_auth
116
-		// pour s'assurer qu'elle permet bien de decrypter le pass de l'auteur qui fournit la sauvegarde
117
-		// et par extension tous les passwords
118
-		if (!empty($cles_potentielles['secret_des_auth'])) {
119
-			if (!Password::verifier($password_clair, $password_hash, $cles_potentielles['secret_des_auth'])) {
120
-				spip_log("Restauration de la cle `secret_des_auth` par id_auteur $id_auteur erronnee, on ignore", 'chiffrer' . _LOG_INFO_IMPORTANTE);
121
-				unset($cles_potentielles['secret_des_auth']);
122
-			}
123
-		}
124
-
125
-		// on merge les cles pour recuperer les cles manquantes
126
-		$restauration = false;
127
-		foreach ($cles_potentielles as $name => $key) {
128
-			if (!$this->cles->has($name)) {
129
-				$this->cles->set($name, $key);
130
-				spip_log("Restauration de la cle $name par id_auteur $id_auteur", 'chiffrer' . _LOG_INFO_IMPORTANTE);
131
-				$restauration = true;
132
-			}
133
-		}
134
-		return $restauration;
135
-	}
136
-
137
-	private function getKey(string $name, bool $autoInit): ?string {
138
-		if ($this->cles->has($name)) {
139
-			return $this->cles->get($name);
140
-		}
141
-		if ($autoInit) {
142
-			$this->cles->generate($name);
143
-			// si l'ecriture de fichier a bien marche on peut utiliser la cle
144
-			if ($this->save()) {
145
-				return $this->cles->get($name);
146
-			}
147
-			// sinon loger et annule la cle generee car il ne faut pas l'utiliser
148
-			spip_log("Echec ecriture du fichier cle ".$this->file." ; impossible de generer une cle $name", 'chiffrer' . _LOG_ERREUR);
149
-			$this->cles->delete($name);
150
-		}
151
-		return null;
152
-	}
153
-
154
-	private function getMetaKey(string $name, bool $autoInit = true): ?string {
155
-		if (!isset($GLOBALS['meta'][$name])) {
156
-			include_spip('base/abstract_sql');
157
-			$GLOBALS['meta'][$name] = sql_getfetsel('valeur', 'spip_meta', 'nom = ' . sql_quote($name, '', 'string'));
158
-		}
159
-		$key = base64_decode($GLOBALS['meta'][$name] ?? '');
160
-		if (strlen($key) === \SODIUM_CRYPTO_SECRETBOX_KEYBYTES) {
161
-			return $key;
162
-		}
163
-		if (!$autoInit) {
164
-			return null;
165
-		}
166
-		$key = Chiffrement::keygen();
167
-		ecrire_meta($name, base64_encode($key), 'non');
168
-		lire_metas(); // au cas ou ecrire_meta() ne fonctionne pas
169
-
170
-		return $key;
171
-	}
172
-
173
-	private function read(): array {
174
-		lire_fichier_securise($this->file, $json);
175
-		if (
176
-			$json
177
-			and $json = \json_decode($json, true)
178
-			and is_array($json)
179
-		) {
180
-			return array_map('base64_decode', $json);
181
-		}
182
-		return [];
183
-	}
17
+    private static array $instances = [];
18
+
19
+    private string $file = _DIR_ETC . 'cles.php';
20
+    private Cles $cles;
21
+
22
+    public static function instance(string $file = ''): self {
23
+        if (empty(self::$instances[$file])) {
24
+            self::$instances[$file] = new self($file);
25
+        }
26
+        return self::$instances[$file];
27
+    }
28
+
29
+    /**
30
+     * Retourne le secret du site (shorthand)
31
+     * @uses self::getSecretSite()
32
+     */
33
+    public static function secret_du_site(): ?string {
34
+        return (self::instance())->getSecretSite();
35
+    }
36
+
37
+    private function __construct(string $file = '') {
38
+        if ($file) {
39
+            $this->file = $file;
40
+        }
41
+        $this->cles = new Cles($this->read());
42
+    }
43
+
44
+    /**
45
+     * Renvoyer le secret du site
46
+     *
47
+     * Le secret du site doit rester aussi secret que possible, et est eternel
48
+     * On ne doit pas l'exporter
49
+     *
50
+     * Le secret est partagé entre une clé disque et une clé bdd
51
+     *
52
+     * @return string
53
+     */
54
+    public function getSecretSite(bool $autoInit = true): ?string {
55
+        $key = $this->getKey('secret_du_site', $autoInit);
56
+        $meta = $this->getMetaKey('secret_du_site', $autoInit);
57
+        // conserve la même longeur.
58
+        return $key ^ $meta;
59
+    }
60
+
61
+    /** Renvoyer le secret des authentifications */
62
+    public function getSecretAuth(bool $autoInit = false): ?string {
63
+        return $this->getKey('secret_des_auth', $autoInit);
64
+    }
65
+    public function save(): bool {
66
+        return ecrire_fichier_securise($this->file, $this->cles->toJson());
67
+    }
68
+
69
+    /**
70
+     * Fournir une sauvegarde chiffree des cles (a l'aide d'une autre clé, comme le pass d'un auteur)
71
+     *
72
+     * @param string $withKey Clé de chiffrage de la sauvegarde
73
+     * @return string Contenu de la sauvegarde chiffrée générée
74
+     */
75
+    public function backup(
76
+        #[\SensitiveParameter]
77
+        string $withKey
78
+    ): string {
79
+        if (count($this->cles)) {
80
+            return Chiffrement::chiffrer($this->cles->toJson(), $withKey);
81
+        }
82
+        return '';
83
+    }
84
+
85
+    /**
86
+     * Restaurer les cles manquantes depuis une sauvegarde chiffree des cles
87
+     * (si la sauvegarde est bien valide)
88
+     *
89
+     * @param string $backup Sauvegarde chiffrée (générée par backup())
90
+     * @param int $id_auteur
91
+     * @param string $pass
92
+     * @return void
93
+     */
94
+    public function restore(
95
+        string $backup,
96
+        #[\SensitiveParameter]
97
+        string $password_clair,
98
+        #[\SensitiveParameter]
99
+        string $password_hash,
100
+        int $id_auteur
101
+    ): bool {
102
+        if (empty($backup)) {
103
+            return false;
104
+        }
105
+
106
+        $sauvegarde = Chiffrement::dechiffrer($backup, $password_clair);
107
+        $json = json_decode($sauvegarde, true);
108
+        if (!$json) {
109
+            return false;
110
+        }
111
+
112
+        // cela semble une sauvegarde valide
113
+        $cles_potentielles = array_map('base64_decode', $json);
114
+
115
+        // il faut faire une double verif sur secret_des_auth
116
+        // pour s'assurer qu'elle permet bien de decrypter le pass de l'auteur qui fournit la sauvegarde
117
+        // et par extension tous les passwords
118
+        if (!empty($cles_potentielles['secret_des_auth'])) {
119
+            if (!Password::verifier($password_clair, $password_hash, $cles_potentielles['secret_des_auth'])) {
120
+                spip_log("Restauration de la cle `secret_des_auth` par id_auteur $id_auteur erronnee, on ignore", 'chiffrer' . _LOG_INFO_IMPORTANTE);
121
+                unset($cles_potentielles['secret_des_auth']);
122
+            }
123
+        }
124
+
125
+        // on merge les cles pour recuperer les cles manquantes
126
+        $restauration = false;
127
+        foreach ($cles_potentielles as $name => $key) {
128
+            if (!$this->cles->has($name)) {
129
+                $this->cles->set($name, $key);
130
+                spip_log("Restauration de la cle $name par id_auteur $id_auteur", 'chiffrer' . _LOG_INFO_IMPORTANTE);
131
+                $restauration = true;
132
+            }
133
+        }
134
+        return $restauration;
135
+    }
136
+
137
+    private function getKey(string $name, bool $autoInit): ?string {
138
+        if ($this->cles->has($name)) {
139
+            return $this->cles->get($name);
140
+        }
141
+        if ($autoInit) {
142
+            $this->cles->generate($name);
143
+            // si l'ecriture de fichier a bien marche on peut utiliser la cle
144
+            if ($this->save()) {
145
+                return $this->cles->get($name);
146
+            }
147
+            // sinon loger et annule la cle generee car il ne faut pas l'utiliser
148
+            spip_log("Echec ecriture du fichier cle ".$this->file." ; impossible de generer une cle $name", 'chiffrer' . _LOG_ERREUR);
149
+            $this->cles->delete($name);
150
+        }
151
+        return null;
152
+    }
153
+
154
+    private function getMetaKey(string $name, bool $autoInit = true): ?string {
155
+        if (!isset($GLOBALS['meta'][$name])) {
156
+            include_spip('base/abstract_sql');
157
+            $GLOBALS['meta'][$name] = sql_getfetsel('valeur', 'spip_meta', 'nom = ' . sql_quote($name, '', 'string'));
158
+        }
159
+        $key = base64_decode($GLOBALS['meta'][$name] ?? '');
160
+        if (strlen($key) === \SODIUM_CRYPTO_SECRETBOX_KEYBYTES) {
161
+            return $key;
162
+        }
163
+        if (!$autoInit) {
164
+            return null;
165
+        }
166
+        $key = Chiffrement::keygen();
167
+        ecrire_meta($name, base64_encode($key), 'non');
168
+        lire_metas(); // au cas ou ecrire_meta() ne fonctionne pas
169
+
170
+        return $key;
171
+    }
172
+
173
+    private function read(): array {
174
+        lire_fichier_securise($this->file, $json);
175
+        if (
176
+            $json
177
+            and $json = \json_decode($json, true)
178
+            and is_array($json)
179
+        ) {
180
+            return array_map('base64_decode', $json);
181
+        }
182
+        return [];
183
+    }
184 184
 }
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -16,7 +16,7 @@  discard block
 block discarded – undo
16 16
 final class SpipCles {
17 17
 	private static array $instances = [];
18 18
 
19
-	private string $file = _DIR_ETC . 'cles.php';
19
+	private string $file = _DIR_ETC.'cles.php';
20 20
 	private Cles $cles;
21 21
 
22 22
 	public static function instance(string $file = ''): self {
@@ -117,7 +117,7 @@  discard block
 block discarded – undo
117 117
 		// et par extension tous les passwords
118 118
 		if (!empty($cles_potentielles['secret_des_auth'])) {
119 119
 			if (!Password::verifier($password_clair, $password_hash, $cles_potentielles['secret_des_auth'])) {
120
-				spip_log("Restauration de la cle `secret_des_auth` par id_auteur $id_auteur erronnee, on ignore", 'chiffrer' . _LOG_INFO_IMPORTANTE);
120
+				spip_log("Restauration de la cle `secret_des_auth` par id_auteur $id_auteur erronnee, on ignore", 'chiffrer'._LOG_INFO_IMPORTANTE);
121 121
 				unset($cles_potentielles['secret_des_auth']);
122 122
 			}
123 123
 		}
@@ -127,7 +127,7 @@  discard block
 block discarded – undo
127 127
 		foreach ($cles_potentielles as $name => $key) {
128 128
 			if (!$this->cles->has($name)) {
129 129
 				$this->cles->set($name, $key);
130
-				spip_log("Restauration de la cle $name par id_auteur $id_auteur", 'chiffrer' . _LOG_INFO_IMPORTANTE);
130
+				spip_log("Restauration de la cle $name par id_auteur $id_auteur", 'chiffrer'._LOG_INFO_IMPORTANTE);
131 131
 				$restauration = true;
132 132
 			}
133 133
 		}
@@ -145,7 +145,7 @@  discard block
 block discarded – undo
145 145
 				return $this->cles->get($name);
146 146
 			}
147 147
 			// sinon loger et annule la cle generee car il ne faut pas l'utiliser
148
-			spip_log("Echec ecriture du fichier cle ".$this->file." ; impossible de generer une cle $name", 'chiffrer' . _LOG_ERREUR);
148
+			spip_log("Echec ecriture du fichier cle ".$this->file." ; impossible de generer une cle $name", 'chiffrer'._LOG_ERREUR);
149 149
 			$this->cles->delete($name);
150 150
 		}
151 151
 		return null;
@@ -154,7 +154,7 @@  discard block
 block discarded – undo
154 154
 	private function getMetaKey(string $name, bool $autoInit = true): ?string {
155 155
 		if (!isset($GLOBALS['meta'][$name])) {
156 156
 			include_spip('base/abstract_sql');
157
-			$GLOBALS['meta'][$name] = sql_getfetsel('valeur', 'spip_meta', 'nom = ' . sql_quote($name, '', 'string'));
157
+			$GLOBALS['meta'][$name] = sql_getfetsel('valeur', 'spip_meta', 'nom = '.sql_quote($name, '', 'string'));
158 158
 		}
159 159
 		$key = base64_decode($GLOBALS['meta'][$name] ?? '');
160 160
 		if (strlen($key) === \SODIUM_CRYPTO_SECRETBOX_KEYBYTES) {
Please login to merge, or discard this patch.
ecrire/src/Chiffrer/Cles.php 1 patch
Indentation   +44 added lines, -44 removed lines patch added patch discarded remove patch
@@ -14,48 +14,48 @@
 block discarded – undo
14 14
 
15 15
 /** Conteneur de clés (chiffrement, authentification) */
16 16
 class Cles implements \Countable /* , ContainerInterface */ {
17
-	private array $keys;
18
-	public function __construct(array $keys) {
19
-		$this->keys = $keys;
20
-	}
21
-
22
-	public function has(string $name): bool {
23
-		return array_key_exists($name, $this->keys);
24
-	}
25
-
26
-	public function get(string $name): ?string {
27
-		return $this->keys[$name] ?? null;
28
-	}
29
-
30
-	public function generate(string $name): string {
31
-		$key = Chiffrement::keygen();
32
-		$this->keys[$name] = $key;
33
-		spip_log("Création de la cle $name", 'chiffrer' . _LOG_INFO_IMPORTANTE);
34
-		return $key;
35
-	}
36
-
37
-	public function set(
38
-		string $name,
39
-		#[\SensitiveParameter]
40
-		string $key
41
-	): void {
42
-		$this->keys[$name] = $key;
43
-	}
44
-
45
-	public function delete(string $name): bool {
46
-		if (isset($this->keys[$name])) {
47
-			unset($this->keys[$name]);
48
-			return true;
49
-		};
50
-		return false;
51
-	}
52
-
53
-	public function count(): int {
54
-		return count($this->keys);
55
-	}
56
-
57
-	public function toJson(): string {
58
-		$json = array_map('base64_encode', $this->keys);
59
-		return \json_encode($json);
60
-	}
17
+    private array $keys;
18
+    public function __construct(array $keys) {
19
+        $this->keys = $keys;
20
+    }
21
+
22
+    public function has(string $name): bool {
23
+        return array_key_exists($name, $this->keys);
24
+    }
25
+
26
+    public function get(string $name): ?string {
27
+        return $this->keys[$name] ?? null;
28
+    }
29
+
30
+    public function generate(string $name): string {
31
+        $key = Chiffrement::keygen();
32
+        $this->keys[$name] = $key;
33
+        spip_log("Création de la cle $name", 'chiffrer' . _LOG_INFO_IMPORTANTE);
34
+        return $key;
35
+    }
36
+
37
+    public function set(
38
+        string $name,
39
+        #[\SensitiveParameter]
40
+        string $key
41
+    ): void {
42
+        $this->keys[$name] = $key;
43
+    }
44
+
45
+    public function delete(string $name): bool {
46
+        if (isset($this->keys[$name])) {
47
+            unset($this->keys[$name]);
48
+            return true;
49
+        };
50
+        return false;
51
+    }
52
+
53
+    public function count(): int {
54
+        return count($this->keys);
55
+    }
56
+
57
+    public function toJson(): string {
58
+        $json = array_map('base64_encode', $this->keys);
59
+        return \json_encode($json);
60
+    }
61 61
 }
Please login to merge, or discard this patch.