Commit d812c005 authored by Bertrand Gauthier's avatar Bertrand Gauthier
Browse files

Merged release_3.2.10

parent ab3b5f33
Pipeline #11741 passed with stage
in 23 seconds
CHANGELOG
=========
4.0.1
-----
- Possibilité d'activer ou non (en config) les logs des échecs d'authentification LDAP.
4.0.0
-----
- Passage de Zend à Laminas
3.2.10
-----
- Possibilité d'activer ou non (en config) les logs des échecs d'authentification LDAP.
3.2.8
-----
......
......@@ -4,18 +4,35 @@ namespace UnicaenAuth;
use Laminas\EventManager\EventInterface;
use Laminas\ModuleManager\Feature\AutoloaderProviderInterface;
use Laminas\ModuleManager\Feature\BootstrapListenerInterface;
use Laminas\ModuleManager\Feature\ConfigProviderInterface;
use Laminas\ModuleManager\Feature\ServiceProviderInterface;
use ZfcUser\Form\Login;
use ZfcUser\Form\LoginFilter;
use Laminas\Mvc\MvcEvent;
use UnicaenAuth\Event\Listener\LdapAuthenticationFailureLoggerListener;
use UnicaenAuth\Options\ModuleOptions;
/**
* Point d'entrée du module d'authentification Unicaen.
*
* @author Bertrand GAUTHIER <bertrand.gauthier@unicaen.fr>
*/
class Module implements AutoloaderProviderInterface, ConfigProviderInterface, ServiceProviderInterface
class Module implements AutoloaderProviderInterface, ConfigProviderInterface, ServiceProviderInterface, BootstrapListenerInterface
{
/**
* @var \UnicaenAuth\Options\ModuleOptions
*/
private $moduleOptions;
/**
* @var \Laminas\EventManager\EventManagerInterface
*/
private $eventManager;
/**
* @var \Laminas\ServiceManager\ServiceManager
*/
private $serviceManager;
/**
* @return array
* @see ConfigProviderInterface
......@@ -41,16 +58,30 @@ class Module implements AutoloaderProviderInterface, ConfigProviderInterface, Se
}
/**
* This method is called once the MVC bootstrapping is complete,
* after the "loadModule.post" event, once $application->bootstrap() is called.
*
* @param EventInterface $e
*
* @see BootstrapListenerInterface
* @inheritDoc
*/
public function onBootstrap(EventInterface $e)
{
if ($e instanceof MvcEvent) {
/** @var \Laminas\Mvc\Application $application */
$application = $e->getApplication();
$this->serviceManager = $application->getServiceManager();
$this->eventManager = $application->getEventManager();
$this->moduleOptions = $this->serviceManager->get(ModuleOptions::class);
$this->attachEventListeners();
}
}
protected function attachEventListeners()
{
// log éventuel des erreurs d'authentification LDAP
$logLdapAuthenticationFailure = $this->moduleOptions->getLdap()['log_failures'] ?? false;
if ($logLdapAuthenticationFailure) {
/** @var LdapAuthenticationFailureLoggerListener $listener */
$listener = $this->serviceManager->get(LdapAuthenticationFailureLoggerListener::class);
$listener->attach($this->eventManager);
}
}
/**
......
......@@ -24,6 +24,8 @@ use UnicaenAuth\Controller\AuthController;
use UnicaenAuth\Controller\AuthControllerFactory;
use UnicaenAuth\Controller\DroitsControllerFactory;
use UnicaenAuth\Controller\UtilisateurControllerFactory;
use UnicaenAuth\Event\Listener\LdapAuthenticationFailureLoggerListener;
use UnicaenAuth\Event\Listener\LdapAuthenticationFailureLoggerListenerFactory;
use UnicaenAuth\Form\CasLoginForm;
use UnicaenAuth\Form\CasLoginFormFactory;
use UnicaenAuth\Form\Droits\RoleFormFactory;
......@@ -155,6 +157,8 @@ $settings = [
'enabled' => true,
'adapter' => Ldap::class,
'form' => LoginForm::class,
'log_failures' => false, /** @see \UnicaenAuth\Event\Listener\LdapAuthenticationFailureLoggerListener */
],
],
......@@ -701,7 +705,9 @@ return [
'UnicaenApp\HistoriqueListener' => HistoriqueListenerFactory::class,
'UnicaenAuth\HistoriqueListener' => HistoriqueListenerFactory::class,
\UnicaenAuth\Event\EventManager::class => \UnicaenAuth\Event\EventManagerFactory::class
\UnicaenAuth\Event\EventManager::class => \UnicaenAuth\Event\EventManagerFactory::class,
LdapAuthenticationFailureLoggerListener::class => LdapAuthenticationFailureLoggerListenerFactory::class,
],
'lazy_services' => [
// Mapping services to their class names is required since the ServiceManager is not a declarative DIC.
......
......@@ -57,6 +57,11 @@ return [
*/
'ldap' => [
'enabled' => true,
/**
* Activation ou non des logs (via `error_log` par défaut) à propos des échecs d'authentification LDAP.
*/
'log_failures' => false, /** @see \UnicaenAuth\Event\Listener\LdapAuthenticationFailureLoggerListener */
],
],
......
......@@ -206,24 +206,22 @@ class Ldap extends AbstractAdapter implements EventManagerAwareInterface
// LDAP auth
$result = $this->getLdapAuthAdapter()->setUsername($username)->setPassword($credential)->authenticate();
$success = $result->isValid();
// Déclenchement d'un événement contenant le nécessaire pour réagir à l'échec d'authentification (log, etc.)
if (!$success) {
$errorEvent = new Event(self::LDAP_AUTHENTIFICATION_FAIL, $this, [
'result' => $result,
'username' => $username,
// Envoi des erreurs LDAP dans un événement
if (!$result->isValid()) {
$messages = "LDAP ERROR : ";
$errorMessages = $result->getMessages();
if (count($errorMessages) > 0) {
// Clé conservée pour compatibilité :
'messages' => implode(PHP_EOL, array_slice($result->getMessages(), 0, 2)),
// On ne prend que les 2 premières lignes d'erreur (les suivantes contiennent souvent
// les mots de passe de l'utilisateur, et les mot de passe dans les logs... bof bof).
for ($i = 0; $i < 2 && count($errorMessages) >= $i; $i++) {
$messages .= $errorMessages[$i] . " ";
}
}
$errorEvent = new Event(self::LDAP_AUTHENTIFICATION_FAIL, null, ['messages' => $messages]);
$this->getEventManager()->triggerEvent($errorEvent);
// les mots de passe de l'utilisateur, et les mots de passe dans les logs... bof bof).
]);
$this->eventManager->triggerEvent($errorEvent);
}
$success = $result->isValid();
// verif existence du login usurpé
if ($this->usernameUsurpe) {
// s'il nexiste pas, échec de l'authentification
......
<?php
namespace UnicaenAuth\Event\Listener;
use Psr\Log\LoggerInterface;
use UnicaenAuth\Authentication\Adapter\Ldap;
use Laminas\Authentication\Result;
use Laminas\EventManager\Event;
use Laminas\EventManager\EventManagerInterface;
use Laminas\EventManager\ListenerAggregateInterface;
use Laminas\EventManager\ListenerAggregateTrait;
/**
* Permet de scruter les erreurs d'authentification LDAP pour les ajouter aux logs.
*
* @author Bertrand GAUTHIER <bertrand.gauthier at unicaen.fr>
*/
class LdapAuthenticationFailureLoggerListener implements ListenerAggregateInterface
{
use ListenerAggregateTrait;
/**
* @var \Psr\Log\LoggerInterface
*/
private $logger;
public function setLogger(LoggerInterface $logger): self
{
$this->logger = $logger;
return $this;
}
public function attach(EventManagerInterface $events, $priority = 1)
{
$this->listeners[] = $events->getSharedManager()->attach(
"*",
Ldap::LDAP_AUTHENTIFICATION_FAIL,
[$this, "onLdapError"],
100
);
}
public function onLdapError(Event $event)
{
/** @var \Laminas\Authentication\Result $result */
$result = $event->getParam('result');
$details = $result->getMessages() ?: ["Aucun détail supplémentaire."];
$username = $event->getParam('username');
$messages = [];
switch ($result->getCode()) {
case Result::FAILURE_IDENTITY_NOT_FOUND:
$messages[] = "Identifiant de connexion inconnu : '$username'.";
break;
case Result::FAILURE_CREDENTIAL_INVALID:
$messages[] = "Mot de passe incorrect pour l'identifiant de connexion '$username'.";
break;
case Result::FAILURE:
default:
$messages[] = "Erreur rencontrée lors de l'authentification : ";
break;
}
$messages = array_merge($messages, $details);
$error = "[SyGAL LDAP AUTH] " . implode(PHP_EOL, $messages);
$this->log($error);
}
protected function log(string $message)
{
if ($this->logger !== null) {
$this->logger->error($message);
} else {
error_log($message);
}
}
}
\ No newline at end of file
<?php
namespace UnicaenAuth\Event\Listener;
use Interop\Container\ContainerInterface;
class LdapAuthenticationFailureLoggerListenerFactory
{
public function __invoke(ContainerInterface $container): LdapAuthenticationFailureLoggerListener
{
return new LdapAuthenticationFailureLoggerListener();
}
}
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment