2018-03-09 07:17:25 +01:00
|
|
|
package Lemonldap::NG::Portal::2F::Ext2F;
|
2017-03-22 23:18:28 +01:00
|
|
|
|
|
|
|
use strict;
|
|
|
|
use Mouse;
|
|
|
|
use Lemonldap::NG::Portal::Main::Constants qw(
|
2019-03-07 18:22:16 +01:00
|
|
|
PE_BADCREDENTIALS
|
|
|
|
PE_ERROR
|
|
|
|
PE_FORMEMPTY
|
|
|
|
PE_OK
|
|
|
|
PE_SENDRESPONSE
|
2017-03-22 23:18:28 +01:00
|
|
|
);
|
|
|
|
|
2019-05-06 14:07:42 +02:00
|
|
|
our $VERSION = '2.0.4';
|
2017-03-22 23:18:28 +01:00
|
|
|
|
2017-03-23 12:17:01 +01:00
|
|
|
extends 'Lemonldap::NG::Portal::Main::SecondFactor';
|
2017-03-22 23:18:28 +01:00
|
|
|
|
|
|
|
# INITIALIZATION
|
|
|
|
|
2019-07-18 22:41:24 +02:00
|
|
|
has prefix => ( is => 'rw', default => 'ext' );
|
2019-02-14 22:43:38 +01:00
|
|
|
has random => ( is => 'rw' );
|
2017-03-23 07:20:06 +01:00
|
|
|
|
2017-03-22 23:18:28 +01:00
|
|
|
sub init {
|
|
|
|
my ($self) = @_;
|
2019-02-14 22:43:38 +01:00
|
|
|
unless ( $self->conf->{ext2fCodeActivation} ) {
|
|
|
|
foreach (qw(ext2FSendCommand ext2FValidateCommand)) {
|
|
|
|
unless ( $self->conf->{$_} ) {
|
|
|
|
$self->error("Missing $_ parameter, aborting");
|
|
|
|
return 0;
|
|
|
|
}
|
2017-03-22 23:18:28 +01:00
|
|
|
}
|
2019-07-18 22:41:24 +02:00
|
|
|
$self->prefix( $self->conf->{sfPrefix} )
|
2019-08-01 17:27:14 +02:00
|
|
|
if ( $self->conf->{sfPrefix} );
|
2019-02-14 22:43:38 +01:00
|
|
|
return $self->SUPER::init();
|
2017-03-22 23:18:28 +01:00
|
|
|
}
|
2019-02-16 21:59:53 +01:00
|
|
|
if ( $self->conf->{ext2fCodeActivation} ) {
|
|
|
|
unless ( $self->conf->{ext2FSendCommand} ) {
|
|
|
|
$self->error("Missing 'ext2FSendCommand' parameter, aborting");
|
|
|
|
return 0;
|
|
|
|
}
|
2019-06-27 18:39:01 +02:00
|
|
|
$self->random( Lemonldap::NG::Common::Crypto::srandom() );
|
2019-07-18 22:41:24 +02:00
|
|
|
$self->prefix( $self->conf->{sfPrefix} )
|
2019-08-01 17:27:14 +02:00
|
|
|
if ( $self->conf->{sfPrefix} );
|
2019-02-14 22:43:38 +01:00
|
|
|
return $self->SUPER::init();
|
|
|
|
}
|
|
|
|
return 0;
|
2017-03-22 23:18:28 +01:00
|
|
|
}
|
|
|
|
|
2017-03-23 12:17:01 +01:00
|
|
|
# RUNNING METHODS
|
2017-03-23 07:20:06 +01:00
|
|
|
|
2017-03-23 12:17:01 +01:00
|
|
|
sub run {
|
|
|
|
my ( $self, $req, $token ) = @_;
|
2018-06-21 21:35:16 +02:00
|
|
|
|
2018-06-12 22:49:49 +02:00
|
|
|
my $checkLogins = $req->param('checkLogins');
|
|
|
|
$self->logger->debug("Ext2F checkLogins set") if ($checkLogins);
|
2017-03-22 23:18:28 +01:00
|
|
|
|
2019-02-16 21:59:53 +01:00
|
|
|
# Generate Code to send
|
|
|
|
my $code;
|
|
|
|
if ( $self->conf->{ext2fCodeActivation} ) {
|
2019-03-07 18:22:16 +01:00
|
|
|
$code = $self->random->randregex( $self->conf->{ext2fCodeActivation} );
|
2019-02-14 22:43:38 +01:00
|
|
|
$self->logger->debug("Generated ext2f code : $code");
|
|
|
|
$self->ott->updateToken( $token, __ext2fcode => $code );
|
|
|
|
}
|
|
|
|
|
2017-03-22 23:18:28 +01:00
|
|
|
# Prepare command and launch it
|
2018-10-12 10:04:03 +02:00
|
|
|
$self->logger->debug( 'Launching "Send" external 2F command -> '
|
2019-03-07 18:22:16 +01:00
|
|
|
. $self->conf->{ext2FSendCommand} );
|
|
|
|
if (
|
|
|
|
my $c = $self->launch(
|
2019-02-16 22:42:08 +01:00
|
|
|
$req->sessionInfo, $self->conf->{ext2FSendCommand}, $code
|
|
|
|
)
|
2019-03-07 18:22:16 +01:00
|
|
|
)
|
2017-03-23 07:20:06 +01:00
|
|
|
{
|
2018-10-12 10:04:03 +02:00
|
|
|
$self->logger->error("External send command failed (code $c)");
|
2019-05-06 14:07:42 +02:00
|
|
|
return PE_ERROR;
|
2017-03-22 23:18:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
# Prepare form
|
|
|
|
my $tmp = $self->p->sendHtml(
|
|
|
|
$req,
|
|
|
|
'ext2fcheck',
|
|
|
|
params => {
|
2018-10-12 19:41:13 +02:00
|
|
|
MAIN_LOGO => $self->conf->{portalMainLogo},
|
2019-06-28 15:56:57 +02:00
|
|
|
SKIN => $self->p->getSkin($req),
|
2018-06-21 21:35:16 +02:00
|
|
|
TOKEN => $token,
|
2019-07-18 22:41:24 +02:00
|
|
|
TARGET => '/' . $self->prefix . '2fcheck',
|
2018-06-12 22:49:49 +02:00
|
|
|
CHECKLOGINS => $checkLogins
|
2017-03-22 23:18:28 +01:00
|
|
|
}
|
|
|
|
);
|
2018-02-19 14:15:29 +01:00
|
|
|
$self->logger->debug("Prepare external 2F verification");
|
2017-03-22 23:18:28 +01:00
|
|
|
|
|
|
|
$req->response($tmp);
|
|
|
|
return PE_SENDRESPONSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub verify {
|
2017-03-23 12:17:01 +01:00
|
|
|
my ( $self, $req, $session ) = @_;
|
2019-02-14 22:43:38 +01:00
|
|
|
my $usercode;
|
|
|
|
unless ( $usercode = $req->param('code') ) {
|
2019-02-16 21:59:53 +01:00
|
|
|
$self->userLogger->error('External 2F: no code found');
|
2017-03-23 12:17:01 +01:00
|
|
|
return PE_FORMEMPTY;
|
2017-03-22 23:18:28 +01:00
|
|
|
}
|
|
|
|
|
2019-02-14 22:43:38 +01:00
|
|
|
unless ( $self->conf->{ext2fCodeActivation} ) {
|
|
|
|
|
|
|
|
# Prepare command and launch it
|
|
|
|
$self->logger->debug( 'Launching "Validate" external 2F command -> '
|
2019-03-07 18:22:16 +01:00
|
|
|
. $self->conf->{ext2FValidateCommand} );
|
2019-02-14 22:43:38 +01:00
|
|
|
$self->logger->debug(" code -> $usercode");
|
2019-03-07 18:22:16 +01:00
|
|
|
if (
|
|
|
|
my $c = $self->launch(
|
2019-02-14 22:43:38 +01:00
|
|
|
$session, $self->conf->{ext2FValidateCommand}, $usercode
|
|
|
|
)
|
2019-03-07 18:22:16 +01:00
|
|
|
)
|
2019-02-14 22:43:38 +01:00
|
|
|
{
|
|
|
|
$self->userLogger->warn( 'Second factor failed for '
|
2019-03-07 18:22:16 +01:00
|
|
|
. $session->{ $self->conf->{whatToTrace} } );
|
2019-02-14 22:43:38 +01:00
|
|
|
$self->logger->error("External verify command failed (code $c)");
|
|
|
|
return PE_BADCREDENTIALS;
|
|
|
|
}
|
|
|
|
return PE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
my $savedcode = $session->{__ext2fcode};
|
|
|
|
unless ($savedcode) {
|
|
|
|
$self->logger->error(
|
|
|
|
'Unable to find generated 2F code in token session');
|
|
|
|
return PE_ERROR;
|
2017-03-22 23:18:28 +01:00
|
|
|
}
|
2019-02-14 22:43:38 +01:00
|
|
|
|
|
|
|
$self->logger->debug("Verifying Ext 2F code: $usercode VS $savedcode");
|
|
|
|
return PE_OK if ( $usercode eq $savedcode );
|
|
|
|
|
|
|
|
$self->userLogger->warn( 'Second factor failed for '
|
2019-03-07 18:22:16 +01:00
|
|
|
. $session->{ $self->conf->{whatToTrace} } );
|
2019-02-14 22:43:38 +01:00
|
|
|
return PE_BADCREDENTIALS;
|
2017-03-22 23:18:28 +01:00
|
|
|
}
|
|
|
|
|
2017-03-22 23:46:49 +01:00
|
|
|
# system() is used with an array to avoid shell injection
|
|
|
|
sub launch {
|
|
|
|
my ( $self, $session, $command, $code ) = @_;
|
|
|
|
my @args;
|
|
|
|
foreach ( split( /\s+/, $command ) ) {
|
|
|
|
if ( defined $code ) {
|
|
|
|
s#\$code\b#$code#g;
|
|
|
|
}
|
|
|
|
s#\$(\w+)#$session->{$1} // ''#ge;
|
|
|
|
push @args, $_;
|
|
|
|
}
|
2019-05-06 14:28:28 +02:00
|
|
|
$self->logger->debug( "Executing command: " . join( " ", @args ) );
|
2017-03-22 23:46:49 +01:00
|
|
|
return system @args;
|
|
|
|
}
|
|
|
|
|
2017-03-22 23:18:28 +01:00
|
|
|
1;
|
2019-02-14 22:43:38 +01:00
|
|
|
|