3f426d851b0ddb583707c349515ab5340e38df32
[velocampus/web/www.git] / www / ecrire / auth / spip.php
1 <?php
2
3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
5 * *
6 * Copyright (c) 2001-2011 *
7 * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
8 * *
9 * Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
10 * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
11 \***************************************************************************/
12
13 if (!defined('_ECRIRE_INC_VERSION')) return;
14
15 // Authentifie et si ok retourne le tableau de la ligne SQL de l'utilisateur
16 // Si risque de secu repere a l'installation retourne False
17 function auth_spip_dist ($login, $pass, $serveur='') {
18
19 // retrouver le login
20 $login = auth_spip_retrouver_login($login);
21 // login inconnu, n'allons pas plus loin
22 if (!$login) return array();
23
24 $md5pass = $md5next = "";
25 $shapass = $shanext = "";
26
27 if (preg_match(",^\{([0-9a-f]{64});([0-9a-f]{64})\}$,i",$pass,$regs)){
28 $shapass = $regs[1];
29 $shanext = $regs[2];
30 $pass="";
31 }
32 // compat avec une base mixte md5/sha256 : le js a envoye les 2 hash
33 elseif (preg_match(",^\{([0-9a-f]{64});([0-9a-f]{64});([0-9a-f]{32});([0-9a-f]{32})\}$,i",$pass,$regs)){
34 $shapass = $regs[1];
35 $shanext = $regs[2];
36 $md5pass = $regs[3];
37 $md5next = $regs[4];
38 $pass="";
39 }
40
41 // si envoi non crypte, crypter maintenant
42 elseif ($pass) {
43 $row = sql_fetsel("alea_actuel, alea_futur", "spip_auteurs", "login=" . sql_quote($login),'','','','',$serveur);
44
45 if ($row) {
46 include_spip('auth/sha256.inc');
47 $shapass = _nano_sha256($row['alea_actuel'] . $pass);
48 $shanext = _nano_sha256($row['alea_futur'] . $pass);
49 $md5pass = md5($row['alea_actuel'] . $pass);
50 }
51 }
52
53 // login inexistant ou mot de passe vide
54 if (!$shapass AND !$md5pass) return array();
55
56 $row = sql_fetsel("*", "spip_auteurs", "login=" . sql_quote($login) . " AND pass=" . sql_quote($shapass) . " AND statut<>'5poubelle'",'','','','',$serveur);
57
58 // compat avec les anciennes bases en md5
59 if (!$row AND $md5pass)
60 $row = sql_fetsel("*", "spip_auteurs", "login=" . sql_quote($login) . " AND pass=" . sql_quote($md5pass) . " AND statut<>'5poubelle'",'','','','',$serveur);
61
62 // login/mot de passe incorrect
63 if (!$row) return array();
64
65 // fait tourner le codage du pass dans la base
66 if ($shanext) {
67
68 include_spip('inc/acces'); // pour creer_uniqid
69 @sql_update('spip_auteurs', array('alea_actuel' => 'alea_futur', 'pass' => sql_quote($shanext), 'alea_futur' => sql_quote(creer_uniqid())), "id_auteur=" . $row['id_auteur'].' AND pass IN ('.sql_quote($shapass).', '.sql_quote($md5pass).')','',$serveur);
70 // En profiter pour verifier la securite de tmp/
71 // Si elle ne fonctionne pas a l'installation, prevenir
72 if (!verifier_htaccess(_DIR_TMP) AND defined('_ECRIRE_INSTALL'))
73 return false;
74 }
75 return $row;
76 }
77
78 function auth_spip_formulaire_login($flux){
79 // faut il encore envoyer md5 ?
80 // on regarde si il reste des pass md5 en base pour des auteurs en statut pas poubelle
81 // les hash md5 ont une longueur 32, les sha 64
82 $compat_md5 = sql_countsel("spip_auteurs", "length(pass)=32 AND statut<>'poubelle'");
83
84 // javascript qui gere la securite du login en evitant de faire circuler le pass en clair
85 $flux['data'].=
86 ($compat_md5?'<script type="text/javascript" src="'._DIR_JAVASCRIPT.'md5.js"></script>':'')
87 . '<script type="text/javascript" src="'._DIR_JAVASCRIPT.'sha256.js"></script>'
88 .'<script type="text/javascript" src="'._DIR_JAVASCRIPT.'login.js"></script>'
89 .'<script type="text/javascript">/*<![CDATA[*/'
90 ."var alea_actuel='".$flux['args']['contexte']['_alea_actuel']."';"
91 ."var alea_futur='".$flux['args']['contexte']['_alea_futur']."';"
92 ."var login='".$flux['args']['contexte']['var_login']."';"
93 ."var page_auteur = '".generer_url_public('informer_auteur')."';"
94 ."var informe_auteur_en_cours = false;"
95 ."var attente_informe = 0;"
96 ."var compat_md5 = ".($compat_md5?"true;":"false;")
97 ."jQuery(function(){
98 jQuery('#password')
99 .after(\"<em id='pass_securise'><img src='"._DIR_IMG_PACK."securise.gif' width='16' height='16' alt='" . attribut_html(_T('login_securise')) . "' title='" . attribut_html(_T('login_securise')) . "' \/><\/em>\");
100 affiche_login_secure();
101 jQuery('#var_login').change(actualise_auteur);
102 jQuery('form#formulaire_login').submit(login_submit);
103 });"
104 ."/*]]>*/</script>";
105
106 return $flux;
107 }
108
109
110 /**
111 * Informer du droit de modifier ou non son login
112 * @return bool
113 * toujours true pour un auteur cree dans SPIP
114 */
115 function auth_spip_autoriser_modifier_login($serveur=''){
116 if (strlen($serveur))
117 return false; // les fonctions d'ecriture sur base distante sont encore incompletes
118 return true;
119 }
120
121 /**
122 * Verification de la validite d'un login pour le mode d'auth concerne
123 *
124 * @param string $new_login
125 * @param int $id_auteur
126 * si auteur existant deja
127 * @return string
128 * message d'erreur si login non valide, chaine vide sinon
129 */
130 function auth_spip_verifier_login($new_login, $id_auteur=0, $serveur=''){
131 // login et mot de passe
132 if (strlen($new_login)){
133 if (strlen($new_login) < _LOGIN_TROP_COURT)
134 return 'info_login_trop_court';
135 else {
136 $n = sql_countsel('spip_auteurs', "login=" . sql_quote($new_login) . " AND id_auteur!=".intval($id_auteur)." AND statut!='5poubelle'",'','',$serveur);
137 if ($n)
138 return _T('info_login_existant');
139 }
140 }
141 return '';
142 }
143
144 /**
145 * Modifier le login d'un auteur SPIP
146 *
147 * @param string $new_login
148 * @param int $id_auteur
149 * @return bool
150 */
151 function auth_spip_modifier_login($new_login, $id_auteur, $serveur=''){
152 if (is_null($new_login) OR auth_spip_verifier_login($new_login,$id_auteur,$serveur)!='')
153 return false;
154 if (!$id_auteur = intval($id_auteur)
155 OR !$auteur = sql_fetsel('login','spip_auteurs','id_auteur='.intval($id_auteur),'','','','',$serveur))
156 return false;
157 if ($new_login == $auteur['login'])
158 return true; // on a rien fait mais c'est bon !
159
160 include_spip('inc/modifier');
161
162 // vider le login des auteurs a la poubelle qui avaient ce meme login
163 if (strlen($new_login)){
164 $anciens = sql_select('id_auteur','spip_auteurs','login='.sql_quote($new_login)." AND statut='5poubelle'",'','','','',$serveur);
165 while ($row = sql_fetch($anciens)){
166 revision_auteur($row['id_auteur'], array('login'=>'')); // manque la gestion de $serveur
167 }
168 }
169
170 include_spip('inc/modifier');
171 revision_auteur($id_auteur, array('login'=>$new_login)); // manque la gestion de $serveur
172
173 return true;
174 }
175
176 /**
177 * Retrouver le login de quelqu'un qui cherche a se loger
178 * Reconnaitre aussi ceux qui donnent leur nom ou email au lieu du login
179 *
180 * @param string $login
181 * @return string
182 */
183 function auth_spip_retrouver_login($login, $serveur=''){
184 if (!strlen($login)) return null; // pas la peine de requeter
185 $l = sql_quote($login);
186 if ($r = sql_getfetsel('login', 'spip_auteurs',
187 "statut<>'5poubelle'" .
188 " AND (length(pass)>0)" .
189 " AND (login=$l)",'','','','',$serveur))
190 return $r;
191 // Si pas d'auteur avec ce login
192 // regarder s'il a saisi son nom ou son mail.
193 // Ne pas fusionner avec la requete precedente
194 // car un nom peut etre homonyme d'un autre login
195 else return sql_getfetsel('login', 'spip_auteurs',
196 "statut<>'5poubelle'" .
197 " AND (length(pass)>0)" .
198 " AND (login<>'' AND (nom=$l OR email=$l))",'','','','',$serveur);
199 }
200
201
202 /**
203 * informer sur un login
204 * Ce dernier transmet le tableau ci-dessous a la fonction JS informer_auteur
205 * Il est invoque par la fonction JS actualise_auteur via la globale JS
206 * page_auteur=#URL_PAGE{informer_auteur} dans le squelette login
207 * N'y aurait-il pas plus simple ?
208 *
209 * @param array $infos
210 * @param array $row
211 * @param string $serveur
212 * @return array
213 */
214 function auth_spip_informer_login($infos, $row, $serveur=''){
215
216 // pour la methode SPIP on a besoin des alea en plus pour encoder le pass avec
217 $infos['alea_actuel'] = $row['alea_actuel'];
218 $infos['alea_futur'] = $row['alea_futur'];
219
220 return $infos;
221 }
222
223 /**
224 * Informer du droit de modifier ou non le pass
225 * @return bool
226 * toujours true pour un auteur cree dans SPIP
227 */
228 function auth_spip_autoriser_modifier_pass($serveur=''){
229 if (strlen($serveur))
230 return false; // les fonctions d'ecriture sur base distante sont encore incompletes
231 return true;
232 }
233
234
235 /**
236 * Verification de la validite d'un mot de passe pour le mode d'auth concerne
237 * c'est ici que se font eventuellement les verifications de longueur mini/maxi
238 * ou de force
239 *
240 * @param string $new_pass
241 * @param string $login
242 * le login de l'auteur : permet de verifier que pass et login sont differents
243 * meme a la creation lorsque l'auteur n'existe pas encore
244 * @param int $id_auteur
245 * si auteur existant deja
246 * @return string
247 * message d'erreur si login non valide, chaine vide sinon
248 */
249 function auth_spip_verifier_pass($login, $new_pass, $id_auteur=0, $serveur=''){
250 // login et mot de passe
251 if (strlen($new_pass) < 6)
252 return _T('info_passe_trop_court');
253
254 return '';
255 }
256
257 function auth_spip_modifier_pass($login, $new_pass, $id_auteur, $serveur=''){
258 if (is_null($new_pass) OR auth_spip_verifier_pass($login, $new_pass,$id_auteur,$serveur)!='')
259 return false;
260
261 if (!$id_auteur = intval($id_auteur)
262 OR !$auteur = sql_fetsel('login','spip_auteurs','id_auteur='.intval($id_auteur),'','','','',$serveur))
263 return false;
264
265 $c = array();
266 include_spip('inc/acces');
267 include_spip('auth/sha256.inc');
268 $htpass = generer_htpass($new_pass);
269 $alea_actuel = creer_uniqid();
270 $alea_futur = creer_uniqid();
271 $pass = _nano_sha256($alea_actuel.$new_pass);
272 $c['pass'] = $pass;
273 $c['htpass'] = $htpass;
274 $c['alea_actuel'] = $alea_actuel;
275 $c['alea_futur'] = $alea_futur;
276 $c['low_sec'] = '';
277
278 include_spip('inc/modifier');
279 revision_auteur($id_auteur, $c); // manque la gestion de $serveur
280
281 }
282
283 /**
284 * Synchroniser les fichiers htpasswd
285 *
286 * @param int $id_auteur
287 * @param array $champs
288 * @param array $options
289 * all=>true permet de demander la regeneration complete des acces apres operation en base (import, upgrade)
290 * @return void
291 */
292 function auth_spip_synchroniser_distant($id_auteur, $champs, $options = array(), $serveur=''){
293 // ne rien faire pour une base distante : on ne sait pas regenerer les htaccess
294 if (strlen($serveur))
295 return;
296 // si un login, pass ou statut a ete modifie
297 // regenerer les fichier htpass
298 if (isset($champs['login'])
299 OR isset($champs['pass'])
300 OR isset($champs['statut'])
301 OR (isset($options['all']) AND $options['all'])
302 ) {
303
304 $htaccess = _DIR_RESTREINT . _ACCESS_FILE_NAME;
305 $htpasswd = _DIR_TMP . _AUTH_USER_FILE;
306
307 // Cette variable de configuration peut etre posee par un plugin
308 // par exemple acces_restreint ;
309 // si .htaccess existe, outrepasser spip_meta
310 if (($GLOBALS['meta']['creer_htpasswd'] != 'oui')
311 AND !@file_exists($htaccess)) {
312 spip_unlink($htpasswd);
313 spip_unlink($htpasswd."-admin");
314 return;
315 }
316
317 # remarque : ici on laisse passer les "nouveau" de maniere a leur permettre
318 # de devenir redacteur le cas echeant (auth http)... a nettoyer
319 // attention, il faut au prealable se connecter a la base (necessaire car utilise par install)
320
321 $p1 = ''; // login:htpass pour tous
322 $p2 = ''; // login:htpass pour les admins
323 $s = sql_select("login, htpass, statut", "spip_auteurs", sql_in("statut", array('1comite','0minirezo','nouveau')));
324 while ($t = sql_fetch($s)) {
325 if (strlen($t['login']) AND strlen($t['htpass'])) {
326 $p1 .= $t['login'].':'.$t['htpass']."\n";
327 if ($t['statut'] == '0minirezo')
328 $p2 .= $t['login'].':'.$t['htpass']."\n";
329 }
330 }
331 if ($p1) {
332 ecrire_fichier($htpasswd, $p1);
333 ecrire_fichier($htpasswd.'-admin', $p2);
334 spip_log("Ecriture de $htpasswd et $htpasswd-admin");
335 }
336 }
337 }
338
339 ?>