PageRenderTime 44ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/ecrire/auth/spip.php

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