Move TOTP verification in Common (#1359)
This Common module will be used also in admin interface
This commit is contained in:
parent
99dc9ed87b
commit
d37a384328
|
@ -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
|
||||
|
|
40
lemonldap-ng-common/lib/Lemonldap/NG/Common/TOTP.pm
Normal file
40
lemonldap-ng-common/lib/Lemonldap/NG/Common/TOTP.pm
Normal 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;
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue
Block a user