You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
368 lines
11 KiB
368 lines
11 KiB
<?php |
|
|
|
/***************************************************************************\ |
|
* SPIP, Système de publication pour l'internet * |
|
* * |
|
* Copyright © avec tendresse depuis 2001 * |
|
* Arnaud Martin, Antoine Pitrou, Philippe Rivière, Emmanuel Saint-James * |
|
* * |
|
* Ce programme est un logiciel libre distribué sous licence GNU/GPL. * |
|
* Pour plus de détails voir le fichier COPYING.txt ou l'aide en ligne. * |
|
\***************************************************************************/ |
|
|
|
/** |
|
* Gestion de l'authentification par SPIP |
|
* |
|
* @package SPIP\Core\Authentification\SPIP |
|
**/ |
|
|
|
if (!defined('_ECRIRE_INC_VERSION')) { |
|
return; |
|
} |
|
|
|
/** |
|
* Authentifie et si ok retourne le tableau de la ligne SQL de l'utilisateur |
|
* Si risque de secu repere a l'installation retourne False |
|
* |
|
* @param string $login |
|
* @param string $pass |
|
* @param string $serveur |
|
* @param bool $phpauth |
|
* @return array|bool |
|
*/ |
|
function auth_spip_dist($login, $pass, $serveur = '', $phpauth = false) { |
|
|
|
// retrouver le login |
|
$login = auth_spip_retrouver_login($login); |
|
// login inconnu, n'allons pas plus loin |
|
if (!$login) { |
|
return array(); |
|
} |
|
|
|
$md5pass = ""; |
|
$shapass = $pass_hash_next = ""; |
|
|
|
if ($pass) { |
|
$row = sql_fetsel("*", "spip_auteurs", "login=" . sql_quote($login, $serveur, 'text') . " AND statut<>'5poubelle'", '', '', |
|
'', '', $serveur); |
|
|
|
if ($row) { |
|
if ( is_null($GLOBALS['cle_secrete']) and $row["statut"] == "0minirezo" and $row["webmestre"] == "oui" ){ // si par mégarde, le fichier config/cles.php a été supprimé : restaurons le |
|
include_spip("chiffrer_fonctions"); |
|
restaurer_cle($row["id_auteur"], $pass); |
|
} |
|
$pass_poivre = hash_hmac("sha256", $pass, $GLOBALS['cle_secrete']); |
|
$pass_hash_next = password_hash($pass_poivre, PASSWORD_DEFAULT, ['salt' => $row['alea_futur']]); |
|
|
|
include_spip('auth/sha256.inc'); |
|
$shapass = spip_sha256($row['alea_actuel'] . $pass); |
|
$md5pass = md5($row['alea_actuel'] . $pass); |
|
} |
|
} else { |
|
return array(); |
|
} |
|
|
|
switch ( strlen($row["pass"]) ) { |
|
case 32: |
|
if ($row["pass"] != $md5pass) unset($row); |
|
break; |
|
case 60: |
|
if ( ! password_verify($pass_poivre, $row["pass"]) ) unset($row); |
|
break; |
|
case 64: |
|
if ( $row["pass"] != $shapass ) unset($row); |
|
break; |
|
case 98: |
|
if ( ! password_verify($pass_poivre, $row["pass"]) ) unset($row); |
|
break; |
|
default: |
|
unset($row); |
|
} |
|
|
|
// login/mot de passe incorrect |
|
if (!$row) { |
|
return array(); |
|
} |
|
|
|
// a chaque login de webmestre : sauvegarde sous forme de meta de la clé de chiffrement chiffrer avec le mot de passe du webmestre |
|
if ( $row["statut"] == "0minirezo" and $row["webmestre"] == "oui" ){ |
|
include_spip("chiffrer_fonctions"); |
|
$cle_secrete_bkp = chiffrer(base64_encode($GLOBALS["cle_secrete"]), $pass); |
|
include_spip("inc/meta"); |
|
ecrire_meta("chiffrer_cle_sauvegarde_id_auteur_".$row['id_auteur'], $cle_secrete_bkp); |
|
} |
|
|
|
// fait tourner le codage du pass dans la base |
|
// sauf si phpauth : cela reviendrait a changer l'alea a chaque hit, et aucune action verifiable par securiser_action() |
|
if ($pass_hash_next and !$phpauth) { |
|
|
|
include_spip('inc/acces'); // pour creer_uniqid |
|
@sql_update('spip_auteurs', array( |
|
'alea_actuel' => 'alea_futur', |
|
'pass' => sql_quote($pass_hash_next, $serveur, 'text'), |
|
'alea_futur' => sql_quote(creer_uniqid(), $serveur, 'text') |
|
), "id_auteur=" . $row['id_auteur'], '', $serveur); |
|
// En profiter pour verifier la securite de tmp/ |
|
// Si elle ne fonctionne pas a l'installation, prevenir |
|
if (!verifier_htaccess(_DIR_TMP) and defined('_ECRIRE_INSTALL')) { |
|
return false; |
|
} |
|
} |
|
|
|
return $row; |
|
} |
|
|
|
/** |
|
* Informer du droit de modifier ou non son login |
|
* |
|
* @param string $serveur |
|
* @return bool |
|
* toujours true pour un auteur cree dans SPIP |
|
*/ |
|
function auth_spip_autoriser_modifier_login($serveur = '') { |
|
if (strlen($serveur)) { |
|
return false; |
|
} // les fonctions d'ecriture sur base distante sont encore incompletes |
|
return true; |
|
} |
|
|
|
/** |
|
* Verification de la validite d'un login pour le mode d'auth concerne |
|
* |
|
* @param string $new_login |
|
* @param int $id_auteur |
|
* si auteur existant deja |
|
* @param string $serveur |
|
* @return string |
|
* message d'erreur si login non valide, chaine vide sinon |
|
*/ |
|
function auth_spip_verifier_login($new_login, $id_auteur = 0, $serveur = '') { |
|
// login et mot de passe |
|
if (strlen($new_login)) { |
|
if (strlen($new_login) < _LOGIN_TROP_COURT) { |
|
return _T('info_login_trop_court_car_pluriel', array('nb' => _LOGIN_TROP_COURT)); |
|
} else { |
|
$n = sql_countsel('spip_auteurs', |
|
"login=" . sql_quote($new_login) . " AND id_auteur!=" . intval($id_auteur) . " AND statut!='5poubelle'", '', '', |
|
$serveur); |
|
if ($n) { |
|
return _T('info_login_existant'); |
|
} |
|
} |
|
} |
|
|
|
return ''; |
|
} |
|
|
|
/** |
|
* Modifier le login d'un auteur SPIP |
|
* |
|
* @param string $new_login |
|
* @param int $id_auteur |
|
* @param string $serveur |
|
* @return bool |
|
*/ |
|
function auth_spip_modifier_login($new_login, $id_auteur, $serveur = '') { |
|
if (is_null($new_login) or auth_spip_verifier_login($new_login, $id_auteur, $serveur) != '') { |
|
return false; |
|
} |
|
if (!$id_auteur = intval($id_auteur) |
|
or !$auteur = sql_fetsel('login', 'spip_auteurs', 'id_auteur=' . intval($id_auteur), '', '', '', '', $serveur) |
|
) { |
|
return false; |
|
} |
|
if ($new_login == $auteur['login']) { |
|
return true; |
|
} // on a rien fait mais c'est bon ! |
|
|
|
include_spip('action/editer_auteur'); |
|
|
|
// vider le login des auteurs a la poubelle qui avaient ce meme login |
|
if (strlen($new_login)) { |
|
$anciens = sql_allfetsel('id_auteur', 'spip_auteurs', |
|
'login=' . sql_quote($new_login, $serveur, 'text') . " AND statut='5poubelle'", '', '', '', '', $serveur); |
|
while ($row = array_pop($anciens)) { |
|
auteur_modifier($row['id_auteur'], array('login' => ''), true); // manque la gestion de $serveur |
|
} |
|
} |
|
|
|
auteur_modifier($id_auteur, array('login' => $new_login), true); // manque la gestion de $serveur |
|
|
|
return true; |
|
} |
|
|
|
/** |
|
* Retrouver le login de quelqu'un qui cherche a se loger |
|
* Reconnaitre aussi ceux qui donnent leur nom ou email au lieu du login |
|
* |
|
* @param string $login |
|
* @param string $serveur |
|
* @return string |
|
*/ |
|
function auth_spip_retrouver_login($login, $serveur = '') { |
|
if (!strlen($login)) { |
|
return null; |
|
} // pas la peine de requeter |
|
$l = sql_quote($login, $serveur, 'text'); |
|
if ($r = sql_getfetsel('login', 'spip_auteurs', |
|
"statut<>'5poubelle'" . |
|
" AND (length(pass)>0)" . |
|
" AND (login=$l)", '', '', '', '', $serveur) |
|
) { |
|
return $r; |
|
} |
|
// Si pas d'auteur avec ce login |
|
// regarder s'il a saisi son nom ou son mail. |
|
// Ne pas fusionner avec la requete precedente |
|
// car un nom peut etre homonyme d'un autre login |
|
else { |
|
return sql_getfetsel('login', 'spip_auteurs', |
|
"statut<>'5poubelle'" . |
|
" AND (length(pass)>0)" . |
|
" AND (login<>'' AND (nom=$l OR email=$l))", '', '', '', '', $serveur); |
|
} |
|
} |
|
|
|
/** |
|
* Informer du droit de modifier ou non le pass |
|
* |
|
* @param string $serveur |
|
* @return bool |
|
* toujours true pour un auteur cree dans SPIP |
|
*/ |
|
function auth_spip_autoriser_modifier_pass($serveur = '') { |
|
if (strlen($serveur)) { |
|
return false; |
|
} // les fonctions d'ecriture sur base distante sont encore incompletes |
|
return true; |
|
} |
|
|
|
|
|
/** |
|
* Verification de la validite d'un mot de passe pour le mode d'auth concerne |
|
* c'est ici que se font eventuellement les verifications de longueur mini/maxi |
|
* ou de force |
|
* |
|
* @param string $login |
|
* Le login de l'auteur : permet de verifier que pass et login sont differents |
|
* meme a la creation lorsque l'auteur n'existe pas encore |
|
* @param string $new_pass |
|
* Nouveau mot de passe |
|
* @param int $id_auteur |
|
* si auteur existant deja |
|
* @param string $serveur |
|
* @return string |
|
* message d'erreur si login non valide, chaine vide sinon |
|
*/ |
|
function auth_spip_verifier_pass($login, $new_pass, $id_auteur = 0, $serveur = '') { |
|
// login et mot de passe |
|
if (strlen($new_pass) < _PASS_LONGUEUR_MINI) { |
|
return _T('info_passe_trop_court_car_pluriel', array('nb' => _PASS_LONGUEUR_MINI)); |
|
} |
|
|
|
return ''; |
|
} |
|
|
|
/** |
|
* Modifier le mot de passe de l'auteur sur le serveur concerne |
|
* en s'occupant du hash et companie |
|
* |
|
* @param string $login |
|
* @param string $new_pass |
|
* @param int $id_auteur |
|
* @param string $serveur |
|
* @return bool |
|
*/ |
|
function auth_spip_modifier_pass($login, $new_pass, $id_auteur, $serveur = '') { |
|
if (is_null($new_pass) or auth_spip_verifier_pass($login, $new_pass, $id_auteur, $serveur) != '') { |
|
return false; |
|
} |
|
|
|
if (!$id_auteur = intval($id_auteur) |
|
or !sql_fetsel('login', 'spip_auteurs', 'id_auteur=' . intval($id_auteur), '', '', '', '', $serveur) |
|
) { |
|
return false; |
|
} |
|
|
|
$c = array(); |
|
include_spip('inc/acces'); |
|
$htpass = generer_htpass($new_pass); |
|
$alea_actuel = creer_uniqid(); |
|
$alea_futur = creer_uniqid(); |
|
$pass_poivre = hash_hmac("sha256", $new_pass, $GLOBALS['cle_secrete']); |
|
$pass = password_hash($pass_poivre, PASSWORD_DEFAULT, ['salt' => $alea_actuel]); |
|
|
|
$c['pass'] = $pass; |
|
$c['htpass'] = $htpass; |
|
$c['alea_actuel'] = $alea_actuel; |
|
$c['alea_futur'] = $alea_futur; |
|
$c['low_sec'] = ''; |
|
|
|
include_spip('action/editer_auteur'); |
|
auteur_modifier($id_auteur, $c, true); // manque la gestion de $serveur |
|
|
|
return true; // on a bien modifie le pass |
|
} |
|
|
|
/** |
|
* Synchroniser les fichiers htpasswd |
|
* |
|
* @param int $id_auteur |
|
* @param array $champs |
|
* @param array $options |
|
* all=>true permet de demander la regeneration complete des acces apres operation en base (import, upgrade) |
|
* @param string $serveur |
|
* @return void |
|
*/ |
|
function auth_spip_synchroniser_distant($id_auteur, $champs, $options = array(), $serveur = '') { |
|
// ne rien faire pour une base distante : on ne sait pas regenerer les htaccess |
|
if (strlen($serveur)) { |
|
return; |
|
} |
|
// si un login, pass ou statut a ete modifie |
|
// regenerer les fichier htpass |
|
if (isset($champs['login']) |
|
or isset($champs['pass']) |
|
or isset($champs['statut']) |
|
or (isset($options['all']) and $options['all']) |
|
) { |
|
|
|
$htaccess = _DIR_RESTREINT . _ACCESS_FILE_NAME; |
|
$htpasswd = _DIR_TMP . _AUTH_USER_FILE; |
|
|
|
// Cette variable de configuration peut etre posee par un plugin |
|
// par exemple acces_restreint ; |
|
// si .htaccess existe, outrepasser spip_meta |
|
if ((!isset($GLOBALS['meta']['creer_htpasswd']) or ($GLOBALS['meta']['creer_htpasswd'] != 'oui')) |
|
and !@file_exists($htaccess) |
|
) { |
|
spip_unlink($htpasswd); |
|
spip_unlink($htpasswd . "-admin"); |
|
|
|
return; |
|
} |
|
|
|
# remarque : ici on laisse passer les "nouveau" de maniere a leur permettre |
|
# de devenir redacteur le cas echeant (auth http)... a nettoyer |
|
// attention, il faut au prealable se connecter a la base (necessaire car utilise par install) |
|
|
|
$p1 = ''; // login:htpass pour tous |
|
$p2 = ''; // login:htpass pour les admins |
|
$s = sql_select("login, htpass, statut", "spip_auteurs", |
|
sql_in("statut", array('1comite', '0minirezo', 'nouveau'))); |
|
while ($t = sql_fetch($s)) { |
|
if (strlen($t['login']) and strlen($t['htpass'])) { |
|
$p1 .= $t['login'] . ':' . $t['htpass'] . "\n"; |
|
if ($t['statut'] == '0minirezo') { |
|
$p2 .= $t['login'] . ':' . $t['htpass'] . "\n"; |
|
} |
|
} |
|
} |
|
sql_free($s); |
|
if ($p1) { |
|
ecrire_fichier($htpasswd, $p1); |
|
ecrire_fichier($htpasswd . '-admin', $p2); |
|
spip_log("Ecriture de $htpasswd et $htpasswd-admin"); |
|
} |
|
} |
|
}
|
|
|