Move TOTP verification in Common (#1359)

This Common module will be used also in admin interface
This commit is contained in:
Xavier Guimard 2018-02-19 22:34:23 +01:00
parent 99dc9ed87b
commit d37a384328
3 changed files with 58 additions and 39 deletions

View File

@ -57,6 +57,7 @@ lib/Lemonldap/NG/Common/Regexp.pm
lib/Lemonldap/NG/Common/Safelib.pm
lib/Lemonldap/NG/Common/Session.pm
lib/Lemonldap/NG/Common/Session/REST.pm
lib/Lemonldap/NG/Common/TOTP.pm
lib/Lemonldap/NG/Common/UserAgent.pm
Makefile.PL
MANIFEST This list of files

View File

@ -0,0 +1,40 @@
package Lemonldap::NG::Common::TOTP;
use strict;
use Mouse;
our $VERSION = '2.0.0';
sub verifyCode {
my ( $self, $interval, $range, $secret, $code ) = @_;
my $s = eval { decode_base32($secret) };
if ($@) {
$self->logger->error('Bad characters in TOTP secret');
return -1;
}
for ( 0 .. $range ) {
if ( $code eq $self->_code( $s, $_, $interval ) ) {
return 1;
}
}
return 0;
}
sub _code {
my ( $self, $secret, $r, $interval ) = @_;
my $hmac = hmac_sha1_hex(
pack( 'H*',
sprintf( '%016x', int( ( time + $r * $interval ) / $interval ) ) ),
$secret,
);
return sprintf(
'%06d',
(
hex( substr( $hmac, hex( substr( $hmac, -1 ) ) * 2, 8 ) ) &
0x7fffffff
) % 1000000
);
}
1;

View File

@ -12,7 +12,8 @@ use Lemonldap::NG::Portal::Main::Constants qw(
our $VERSION = '2.0.0';
extends 'Lemonldap::NG::Portal::Main::SecondFactor';
extends 'Lemonldap::NG::Portal::Main::SecondFactor',
'Lemonldap::NG::Common::TOTP';
# INITIALIZATION
@ -56,45 +57,22 @@ sub verify {
return PE_FORMEMPTY;
}
my $s = eval { decode_base32( $session->{_totp2fSecret} ) };
if ($@) {
$self->logger->error("Bad characters in secret, aborting");
return PE_ERROR;
}
for ( 0 .. $self->conf->{totp2fRange} ) {
if ( $code eq $self->code( $s, $_ ) ) {
$self->userLogger->info('TOTP verified');
return PE_OK;
}
}
$self->userLogger->notice(
'Invalid TOTP for ' . $session->{ $self->conf->{whatToTrace} } . ')' );
return PE_BADCREDENTIALS;
}
sub code {
my ( $self, $secret, $r ) = @_;
my $hmac = hmac_sha1_hex(
pack(
'H*',
sprintf(
'%016x',
int(
( time + $r * $self->conf->{totp2fInterval} ) /
$self->conf->{totp2fInterval}
)
)
),
_decode_base32($secret),
);
return sprintf(
'%06d',
(
hex( substr( $hmac, hex( substr( $hmac, -1 ) ) * 2, 8 ) ) &
0x7fffffff
) % 1000000
my $r = $self->verifyCode(
$self->conf->{totp2fInterval},
$self->conf->{totp2fRange},
$session->{_totp2fSecret}, $code
);
if ( $r == -1 ) { return PE_ERROR; }
elsif ($r) {
$self->userLogger->info('TOTP succeed');
return PE_OK;
}
else {
$self->userLogger->notice( 'Invalid TOTP for '
. $session->{ $self->conf->{whatToTrace} }
. ')' );
return PE_BADCREDENTIALS;
}
}
1;