Skip to content
Extraits de code Groupes Projets
Valider defd583b rédigé par esj's avatar esj
Parcourir les fichiers

LDAP & authentification: refonte de l'interface des deux méthodes...

LDAP & authentification: refonte de l'interface des deux méthodes d'authentification. La classe Auth_ldap s'est révélée malcommode  pour importer d'un serveur LDAP des utilisateurs destinés à avoir des statuts Spip différents. De plus elle devait se soumettre au modèle de sa consoeur Auth_spip et réciproquement, d'où systématiquement 2 appels redondants au serveur MySQL dans les deux méthodes d'identification.

Du coup ces deux classes disparaissent et on prend l'interface charger_fontion habituelle, en essayant d'abord auth_spip puis auth_ldap si un serveur LDAP est disponible. En l'absence de surcharge, le statut par défaut est celui spécifié à l'installation du LDAP comme avant. Mais il suffit de définir inc_auth_ldap pour prendre la main à la place de inc_auth_ldap_dist, en particulier pour qu'à la première connexion un nouvel auteur puisse etre affecté à un statut dépendant des informations du LDAP, pour importer sa clé PGP, sa biographie etc. Cette souplesse vaut aussi pour inc_auth_spip_dist / inc_auth_spip, bien utile maintenant que visiteurs ET rédacteurs peuvent s'inscrire sur un meme site.

Et en plus il y a moins de code qu'avant.
parent a789a2f8
Branches
Étiquettes
Aucune requête de fusion associée trouvée
...@@ -49,7 +49,6 @@ function action_spip_cookie_dist() ...@@ -49,7 +49,6 @@ function action_spip_cookie_dist()
$essai_login, $essai_login,
$id_auteur, $id_auteur,
$ignore_auth_http, $ignore_auth_http,
$ldap_present,
$logout, $logout,
$logout_public, $logout_public,
$next_session_password_md5, $next_session_password_md5,
...@@ -130,70 +129,46 @@ if ($test_echec_cookie == 'oui') { ...@@ -130,70 +129,46 @@ if ($test_echec_cookie == 'oui') {
// Tentative de login // Tentative de login
unset ($cookie_session); unset ($cookie_session);
$redirect = ($url ? $url : _DIR_RESTREINT_ABS); $redirect = ($url ? $url : _DIR_RESTREINT_ABS);
if ($essai_login == "oui") { if ($essai_login == "oui") {
// Recuperer le login en champ hidden // Recuperer le login en champ hidden
if ($session_login_hidden AND !$session_login) if ($session_login_hidden AND !$session_login)
$session_login = $session_login_hidden; $session_login = $session_login_hidden;
$login = $session_login; $row_auteur = array();
spip_connect();
// Essayer differentes methodes d'authentification // Essayer l'authentification par MySQL
$auths = array('spip'); $f = charger_fonction('auth_spip', 'inc', true);
spip_connect(); // pour savoir si ldap est present if ($f) $row_auteur = $f($session_login, $session_password);
if ($ldap_present) $auths[] = 'ldap'; // Marche pas: essayer l'authentification par LDAP si present
$ok = false; if (!$row_auteur AND $GLOBALS['ldap_present']) {
foreach ($auths as $nom_auth) { $f = charger_fonction('auth_ldap', 'inc', true);
include_spip('inc/auth_'.$nom_auth); if ($f) $row_auteur = $f($session_login, $session_password);
$classe_auth = "Auth_".$nom_auth;
$auth = new $classe_auth;
if ($auth->init()) {
// Essayer les mots de passe md5
$ok = $auth->verifier_challenge_md5($login, $session_password_md5, $next_session_password_md5);
// Sinon essayer avec le mot de passe en clair
if (!$ok && $session_password) $ok = $auth->verifier($login, $session_password);
if ($ok) { $auth->lire(); break; }
}
} }
// Si la connexion a reussi // Marche pas, renvoyer le formulaire avec message d'erreur si 2e fois
if ($ok) { if (!$row_auteur) {
// Nouveau redacteur ou visiteur inscrit par mail :
// 'nouveau' -> '1comite' ou '6forum'
// Si LDAP : importer l'utilisateur vers la base SPIP
$auth->activer();
if ($auth->login AND $auth->statut == '0minirezo') // force le cookie pour les admins
$cookie_admin = "@".$auth->login;
// On est connecte : recuperer les donnees auteurs
// poser le cookie session, puis le cas echeant
// verifier que le statut correspond au minimum requis,
$result = spip_query("SELECT * FROM spip_auteurs WHERE login=" . spip_abstract_quote($auth->login));
if ($row_auteur = spip_fetch_array($result)) {
$cookie_session = creer_cookie_session($row_auteur);
} else
$ok = false;
// Si on se connecte dans l'espace prive, ajouter "bonjour" (inutilise)
if ($ok AND ereg(_DIR_RESTREINT_ABS, $redirect)) {
$redirect .= ((false !== strpos($redirect, "?")) ? "&" : "?")
. 'bonjour=oui';
}
}
if (!$ok) {
if (ereg(_DIR_RESTREINT_ABS, $redirect)) if (ereg(_DIR_RESTREINT_ABS, $redirect))
$redirect = generer_url_public('login', $redirect = generer_url_public('login',
"var_login=$login", true); "var_login=$session_login", true);
if ($session_password || $session_password_md5) if ($session_password || $session_password_md5)
$redirect = parametre_url($redirect, 'var_erreur', 'pass', '&'); $redirect = parametre_url($redirect, 'var_erreur', 'pass', '&');
$redirect .= '&url=' . rawurlencode($url); $redirect .= '&url=' . rawurlencode($url);
spip_log("echec login: $login"); spip_log("echec login: $session_login");
} else {
spip_log("login de $session_login vers $redirect");
// Si on se connecte dans l'espace prive,
// ajouter "bonjour" (inutilise)
if (ereg(_DIR_RESTREINT_ABS, $redirect)) {
$redirect .= ((false !== strpos($redirect, "?")) ? "&" : "?")
. 'bonjour=oui';
}
if ($row_auteur['statut'] == '0minirezo')
$cookie_admin = "@".$session_login;
$cookie_session = creer_cookie_session($row_auteur);
} }
else
spip_log("login: $login");
} }
// cookie d'admin ? // cookie d'admin ?
......
...@@ -118,16 +118,14 @@ function inc_auth_dist() { ...@@ -118,16 +118,14 @@ function inc_auth_dist() {
$result = @spip_query("SELECT * FROM spip_auteurs WHERE login=" . spip_abstract_quote($auth_login) . " AND statut!='5poubelle'"); $result = @spip_query("SELECT * FROM spip_auteurs WHERE login=" . spip_abstract_quote($auth_login) . " AND statut!='5poubelle'");
if (!$row = spip_fetch_array($result)) { if (!$row = spip_fetch_array($result)) {
auth_areconnecter($auth_login); auth_areconnecter($auth_login);
exit; exit;
} } else {
elseif ($row['statut']=='6forum')
return auth_arefaire();
else {
$connect_id_auteur = $row['id_auteur']; $connect_id_auteur = $row['id_auteur'];
$connect_login = $row['login']; $connect_login = $row['login'];
$connect_pass = $row['pass']; $connect_pass = $row['pass'];
$connect_statut = acces_statut($connect_id_auteur, $row['statut'], $row['bio']); $connect_statut = acces_statut($connect_id_auteur, $row['statut'], $row['bio']);
if ($row['statut']=='6forum') return auth_arefaire();
// Special : si dans la fiche auteur on modifie les valeurs // Special : si dans la fiche auteur on modifie les valeurs
// de messagerie, utiliser ces valeurs plutot que celle de la base. // de messagerie, utiliser ces valeurs plutot que celle de la base.
......
...@@ -12,128 +12,101 @@ ...@@ -12,128 +12,101 @@
if (!defined("_ECRIRE_INC_VERSION")) return; if (!defined("_ECRIRE_INC_VERSION")) return;
class Auth_ldap { // Authentifie via LDAP et retourne la ligne SQL decrivant l'utilisateur si ok
var $user_dn;
var $nom, $login, $email, $pass, $statut, $bio;
function init() {
// Verifier la presence de LDAP
if (!$GLOBALS['ldap_present']) return false;
return spip_connect_ldap();
}
function verifier_challenge_md5($login, $mdpass_actuel, $mdpass_futur) { function inc_auth_ldap_dist ($login, $pass) {
return false;
}
function verifier($login, $pass) { // Securite contre un serveur LDAP laxiste
global $ldap_link, $ldap_base; if (!$login || !$pass) return array();
// Securite, au cas ou le serveur LDAP est tres laxiste // Serveur joignable ?
if (!$login || !$pass) return false; if (!@spip_connect_ldap()) return array();
// Attributs testes pour egalite avec le login // Utilisateur connu ?
$atts = array('sAMAccountName', 'uid', 'login', 'userid', 'cn', 'sn'); if (!($dn = auth_ldap_search($login, $pass))) return array();
$login_search = ereg_replace("[^-@._[:space:][:alnum:]]", "", $login); // securite
// Tenter une recherche pour essayer de retrouver le DN // Si l'utilisateur figure deja dans la base, y recuperer les infos
reset($atts); $result = spip_query("SELECT * FROM spip_auteurs WHERE login=" . spip_abstract_quote($login) . " AND source='ldap'");
while (list(, $att) = each($atts)) {
$filter = "$att=$login_search"; // sinon importer les infos depuis LDAP,
$result = @ldap_search($ldap_link, $ldap_base, $filter, array("dn")); // avec le statut par defaut a l'install
$info = @ldap_get_entries($ldap_link, $result); if (!spip_num_rows($result))
$result = auth_ldap_inserer($dn, $GLOBALS['meta']["ldap_statut_import"]);
return $result ? spip_fetch_array($result) : array();
}
function auth_ldap_search($login, $pass)
{
global $ldap_link, $ldap_base;
// Attributs testes pour egalite avec le login
$atts = array('sAMAccountName', 'uid', 'login', 'userid', 'cn', 'sn');
$login_search = ereg_replace("[^-@._[:space:][:alnum:]]", "", $login); // securite
// Tenter une recherche pour essayer de retrouver le DN
reset($atts);
while (list(, $att) = each($atts)) {
$result = @ldap_search($ldap_link, $ldap_base, "$att=$login_search", array("dn"));
$info = @ldap_get_entries($ldap_link, $result);
// Ne pas accepter les resultats si plus d'une entree // Ne pas accepter les resultats si plus d'une entree
// (on veut un attribut unique) // (on veut un attribut unique)
if (is_array($info) AND $info['count'] == 1) { if (is_array($info) AND $info['count'] == 1) {
$dn = $info[0]['dn']; $dn = $info[0]['dn'];
if (@ldap_bind($ldap_link, $dn, $pass)) { if (@ldap_bind($ldap_link, $dn, $pass)) return $dn;
$this->user_dn = $dn;
$this->login = $login;
return true;
}
}
} }
}
if (!isset($dn)) {
// Si echec, essayer de deviner le DN // Si echec, essayer de deviner le DN
reset($atts); reset($atts);
while (list(, $att) = each($atts)) { while (list(, $att) = each($atts)) {
$dn = "$att=$login_search, $ldap_base"; if (@ldap_bind($ldap_link, $dn, $pass))
if (@ldap_bind($ldap_link, $dn, $pass)) { return "$att=$login_search, $ldap_base";
$this->user_dn = $dn;
$this->login = $login;
return true;
}
} }
return false;
} }
return '';
}
function lire() { function auth_ldap_inserer($dn, $statut)
global $ldap_link, $ldap_base; {
$this->nom = $this->email = $this->pass = $this->statut = ''; global $ldap_link, $ldap_base;
if (!$this->login) return false;
// Si l'auteur existe dans la base, y recuperer les infos
$row = spip_fetch_array(spip_query("SELECT * FROM spip_auteurs WHERE login=" . spip_abstract_quote($this->login) . " AND source='ldap'"));
if ($row) { // refuser d'importer n'importe qui
$this->nom = $row['nom']; if (!$statut) return false;
$this->email = $row['email'];
$this->statut = $row['statut'];
$this->bio = $row['bio'];
return true;
}
// Lire les infos sur l'auteur depuis LDAP // Lire les infos sur l'utilisateur depuis LDAP
$result = @ldap_read($ldap_link, $this->user_dn, "objectClass=*", array("uid", "cn", "mail", "description")); $result = @ldap_read($ldap_link, $dn, "objectClass=*", array("uid", "cn", "mail", "description"));
// Si l'utilisateur ne peut lire ses infos, se reconnecter avec le compte principal // Si l'utilisateur ne peut lire ses infos,
if (!$result) { // se reconnecter avec le compte principal
if (spip_connect_ldap()) if (!$result AND spip_connect_ldap())
$result = @ldap_read($ldap_link, $this->user_dn, "objectClass=*", array("uid", "cn", "mail", "description")); $result = @ldap_read($ldap_link, $dn, "objectClass=*", array("uid", "cn", "mail", "description"));
else
return false; if (!$result) return array();
}
if (!$result) return false; // Recuperer les donnees de l'auteur
$info = @ldap_get_entries($ldap_link, $result);
// Recuperer les donnees de l'auteur if (!is_array($info)) return array();
$info = @ldap_get_entries($ldap_link, $result); for ($i = 0; $i < $info["count"]; $i++) {
if (!is_array($info)) return false; $val = $info[$i];
for ($i = 0; $i < $info["count"]; $i++) { if (is_array($val)) {
$val = $info[$i]; if (!$nom) $nom = $val['cn'][0];
if (is_array($val)) { if (!$email) $email = $val['mail'][0];
if (!$this->nom) $this->nom = $val['cn'][0]; if (!$login) $login = $val['uid'][0];
if (!$this->email) $this->email = $val['mail'][0]; if (!$bio) $bio = $val['description'][0];
if (!$this->login) $this->login = $val['uid'][0];
if (!$this->bio) $this->bio = $val['description'][0];
}
} }
// Convertir depuis UTF-8 (jeu de caracteres par defaut)
include_spip('inc/charsets');
$this->nom = importer_charset($this->nom, 'utf-8');
$this->email = importer_charset($this->email, 'utf-8');
$this->login = importer_charset($this->login, 'utf-8');
$this->bio = importer_charset($this->bio, 'utf-8');
return true;
} }
function activer() { // Convertir depuis UTF-8 (jeu de caracteres par defaut)
$login = strtolower(($this->login)); include_spip('inc/charsets');
$statut = $GLOBALS['meta']["ldap_statut_import"]; $nom = importer_charset($nom, 'utf-8');
$email = importer_charset($email, 'utf-8');
if (!$statut) return false; $bio = importer_charset($bio, 'utf-8');
$login = strtolower(importer_charset($login, 'utf-8'));
// Si l'auteur n'existe pas, l'inserer avec le statut par defaut (defini a l'install) include_spip('base/abstract_sql');
$n = spip_abstract_insert('spip_auteurs', '(source, nom, login, email, bio, statut, pass)', "('ldap', " . spip_abstract_quote($nom) . ", " . spip_abstract_quote($login) . ", " . spip_abstract_quote($email) . ", " . spip_abstract_quote($bio) . ", " . spip_abstract_quote($statut) . ", '')");
$n = spip_num_rows(spip_query("SELECT id_auteur FROM spip_auteurs WHERE login=" . spip_abstract_quote($login))); return spip_query("SELECT * FROM spip_auteurs WHERE id_auteur=$n");
if ($n) return false;
$n = spip_query("INSERT IGNORE INTO spip_auteurs (source, nom, login, email, bio, statut, pass) VALUES ('ldap', " . spip_abstract_quote($this->nom) . ", " . spip_abstract_quote($login) . ", " . spip_abstract_quote($this->email) . ", " . spip_abstract_quote($this->bio) . ", '$statut', '')");
return $n;
}
} }
?> ?>
...@@ -12,64 +12,44 @@ ...@@ -12,64 +12,44 @@
if (!defined("_ECRIRE_INC_VERSION")) return; if (!defined("_ECRIRE_INC_VERSION")) return;
class Auth_spip { // Authentifie et retourne la ligne SQL decrivant l'utilisateur si ok
var $id_auteur, $nom, $login, $email, $md5pass, $md5next, $alea_futur, $statut, $bio;
function init() { function inc_auth_spip_dist ($login, $pass) {
return true;
}
// Verification du mot passe crypte (javascript) // recuperer le cryptage par JavaScript
function verifier_challenge_md5($login, $mdpass_actuel, $mdpass_futur) { $md5pass = $_POST['session_password_md5'];
// Interdire mot de passe vide $md5next = $_POST['next_session_password_md5'];
if ($mdpass_actuel == '') return false;
$result = spip_query("SELECT * FROM spip_auteurs WHERE login=" . spip_abstract_quote($login) . " AND pass=" . spip_abstract_quote($mdpass_actuel) . " AND statut<>'5poubelle'"); // si envoi non crypte, crypter maintenant
if (!$md5pass AND $pass) {
$result = spip_query("SELECT alea_actuel, alea_futur FROM spip_auteurs WHERE login=" . spip_abstract_quote($login));
if ($row = spip_fetch_array($result)) { if ($row = spip_fetch_array($result)) {
$this->id_auteur = $row['id_auteur']; $md5pass = md5($row['alea_actuel'] . $pass);
$this->nom = $row['nom']; $md5next = md5($row['alea_futur'] . $pass);
$this->login = $row['login']; }
$this->email = $row['email'];
$this->statut = $row['statut'];
$this->bio = $row['bio'];
$this->md5pass = $mdpass_actuel;
$this->md5next = $mdpass_futur;
return true;
} }
return false; // login inexistant ou mot de passe vide
} if (!$md5pass) return array();
// Verification du mot passe en clair (sans javascript) $result = spip_query("SELECT * FROM spip_auteurs WHERE login=" . spip_abstract_quote($login) . " AND pass=" . spip_abstract_quote($md5pass) . " AND statut<>'5poubelle'");
function verifier($login, $pass) { $row = spip_fetch_array($result);
// Interdire mot de passe vide
if ($pass == '') return false;
$result = spip_query("SELECT alea_actuel, alea_futur FROM spip_auteurs WHERE login=" . spip_abstract_quote($login)); // login/mot de passe incorrect
if (!$row) return array();
if ($row = spip_fetch_array($result)) {
$md5pass = md5($row['alea_actuel'] . $pass);
$md5next = md5($row['alea_futur'] . $pass);
return $this->verifier_challenge_md5($login, $md5pass, $md5next);
}
return false;
}
function lire() { if ($row['statut'] == 'nouveau') {
return true; include_spip('inc/auth');
$row['statut'] = acces_statut($row['id_auteur'], $row['statut'], $row['bio']);
} }
function activer() { // fait tourner le codage du pass dans la base
include_spip('inc/auth'); if ($md5next) {
$this->statut = acces_statut($this->id_auteur, $this->statut, $this->bio);
if ($this->md5next) {
include_spip('inc/session'); include_spip('inc/session');
// fait tourner le codage du pass dans la base @spip_query("UPDATE spip_auteurs SET alea_actuel = alea_futur, pass = " . spip_abstract_quote($md5next) . ", alea_futur = '" . creer_uniqid() ."' WHERE id_auteur=" . $row['id_auteur']);
$nouvel_alea_futur = creer_uniqid();
@spip_query("UPDATE spip_auteurs SET alea_actuel = alea_futur, pass = " . spip_abstract_quote($this->md5next) . ", alea_futur = '$nouvel_alea_futur' WHERE id_auteur=" . $this->id_auteur);
}
} }
return $row;
} }
?> ?>
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Veuillez vous inscrire ou vous pour commenter