Update mail2f to use code2f lib (#2762)

This commit is contained in:
Maxime Besson 2022-06-20 21:21:16 +02:00
parent 93cb4df897
commit 181f8c4be1
1 changed files with 42 additions and 64 deletions

View File

@ -11,22 +11,22 @@ use Lemonldap::NG::Portal::Main::Constants qw(
PE_MUSTHAVEMAIL
);
our $VERSION = '2.0.12';
our $VERSION = '2.0.15';
extends qw(
Lemonldap::NG::Portal::Main::SecondFactor
Lemonldap::NG::Portal::Lib::Code2F
Lemonldap::NG::Portal::Lib::SMTP
);
# INITIALIZATION
# Prefix can overriden by sfExtra and is used for routes
has prefix => ( is => 'rw', default => 'mail' );
has random => (
is => 'rw',
default => sub {
return Lemonldap::NG::Common::Crypto::srandom();
}
);
# Type is used to lookup config
has type => ( is => 'ro', default => 'mail' );
has legend => ( is => 'rw', default => 'enterMail2fCode' );
has ott => (
is => 'rw',
@ -50,31 +50,34 @@ has sessionKey => (
}
);
# Mail2F always uses code generation
has code_activation => (
is => 'rw',
lazy => 1,
default => sub {
$_[0]->{conf}->{ mail2fCodeRegex } || '\d{6}';
}
);
sub init {
my ($self) = @_;
$self->{conf}->{mail2fCodeRegex} ||= '\d{6}';
unless ( $self->sessionKey ) {
$self->error("Missing session key parameter, aborting");
return 0;
}
$self->prefix( $self->conf->{sfPrefix} )
if ( $self->conf->{sfPrefix} );
return $self->SUPER::init();
}
# Return custom code when no email
sub run {
my ( $self, $req, $token ) = @_;
my $checkLogins = $req->param('checkLogins');
$self->logger->debug("Mail2F: checkLogins set") if $checkLogins;
my $stayconnected = $req->param('stayconnected');
$self->logger->debug("Mail2F: stayconnected set") if $stayconnected;
my $code = $self->random->randregex( $self->conf->{mail2fCodeRegex} );
$self->logger->debug("Generated two-factor code: $code");
$self->ott->updateToken( $token, __mail2fcode => $code );
my $dest = $req->{sessionInfo}->{ $self->sessionKey };
unless ($dest) {
$self->logger->error( "Could not find mail attribute for login "
@ -82,6 +85,16 @@ sub run {
return PE_MUSTHAVEMAIL;
}
# Delegate code generation to SUPER
return $self->SUPER::run($req, $token);
}
sub sendCode {
my ( $self, $req, $sessionInfo, $code ) = @_;
my $dest = $sessionInfo->{ $self->sessionKey };
# Build mail content
my $tr = $self->translate($req);
my $subject = $self->conf->{mail2fSubject};
@ -98,11 +111,15 @@ sub run {
# Replace variables in body
$body =~ s/\$code/$code/g;
$body =~ s/\$(\w+)/$req->{sessionInfo}->{$1} || ''/ge;
$body =~ s/\$(\w+)/$sessionInfo->{$1} || ''/ge;
}
else {
# Template engine expects $req->sessionInfo to be populated
# which is not the case during a resend
$req->sessionInfo($sessionInfo);
# Use HTML template
$body = $self->loadMailTemplate(
$req,
@ -118,54 +135,15 @@ sub run {
# Send mail
unless ( $self->send_mail( $dest, $subject, $body, $html ) ) {
$self->logger->error( 'Unable to send 2F code mail to ' . $dest );
return PE_ERROR;
return 0;
}
# Prepare form
my $tmp = $self->p->sendHtml(
$req,
'ext2fcheck',
params => {
MAIN_LOGO => $self->conf->{portalMainLogo},
SKIN => $self->p->getSkin($req),
TOKEN => $token,
PREFIX => $self->prefix,
TARGET => '/'
. $self->prefix
. '2fcheck?skin='
. $self->p->getSkin($req),
LEGEND => 'enterMail2fCode',
CHECKLOGINS => $checkLogins,
STAYCONNECTED => $stayconnected
}
);
$req->response($tmp);
return PE_SENDRESPONSE;
return 1;
}
sub verify {
my ( $self, $req, $session ) = @_;
my $usercode;
unless ( $usercode = $req->param('code') ) {
$self->logger->error('Mail2F: no code');
return PE_FORMEMPTY;
}
my $savedcode = $session->{__mail2fcode};
unless ($savedcode) {
$self->logger->error(
'Unable to find generated 2F code in token session');
sub verify_external {
my ($self, $req, $session, $usercode) = @_;
$self->logger->error("Error in Mail2F: verify_external is not supposed to be invoked");
return PE_ERROR;
}
$self->logger->debug(
"Verifying Mail 2F code: $usercode against $savedcode");
return PE_OK if ( $usercode eq $savedcode );
$self->userLogger->warn( 'Second factor failed for '
. $session->{ $self->conf->{whatToTrace} } );
return PE_BADOTP;
}
1;