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/Safelib.pm
|
||||||
lib/Lemonldap/NG/Common/Session.pm
|
lib/Lemonldap/NG/Common/Session.pm
|
||||||
lib/Lemonldap/NG/Common/Session/REST.pm
|
lib/Lemonldap/NG/Common/Session/REST.pm
|
||||||
|
lib/Lemonldap/NG/Common/TOTP.pm
|
||||||
lib/Lemonldap/NG/Common/UserAgent.pm
|
lib/Lemonldap/NG/Common/UserAgent.pm
|
||||||
Makefile.PL
|
Makefile.PL
|
||||||
MANIFEST This list of files
|
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';
|
our $VERSION = '2.0.0';
|
||||||
|
|
||||||
extends 'Lemonldap::NG::Portal::Main::SecondFactor';
|
extends 'Lemonldap::NG::Portal::Main::SecondFactor',
|
||||||
|
'Lemonldap::NG::Common::TOTP';
|
||||||
|
|
||||||
# INITIALIZATION
|
# INITIALIZATION
|
||||||
|
|
||||||
|
@ -56,45 +57,22 @@ sub verify {
|
||||||
return PE_FORMEMPTY;
|
return PE_FORMEMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
my $s = eval { decode_base32( $session->{_totp2fSecret} ) };
|
my $r = $self->verifyCode(
|
||||||
if ($@) {
|
$self->conf->{totp2fInterval},
|
||||||
$self->logger->error("Bad characters in secret, aborting");
|
$self->conf->{totp2fRange},
|
||||||
return PE_ERROR;
|
$session->{_totp2fSecret}, $code
|
||||||
}
|
);
|
||||||
for ( 0 .. $self->conf->{totp2fRange} ) {
|
if ( $r == -1 ) { return PE_ERROR; }
|
||||||
if ( $code eq $self->code( $s, $_ ) ) {
|
elsif ($r) {
|
||||||
$self->userLogger->info('TOTP verified');
|
$self->userLogger->info('TOTP succeed');
|
||||||
return PE_OK;
|
return PE_OK;
|
||||||
}
|
}
|
||||||
}
|
else {
|
||||||
$self->userLogger->notice(
|
$self->userLogger->notice( 'Invalid TOTP for '
|
||||||
'Invalid TOTP for ' . $session->{ $self->conf->{whatToTrace} } . ')' );
|
. $session->{ $self->conf->{whatToTrace} }
|
||||||
|
. ')' );
|
||||||
return PE_BADCREDENTIALS;
|
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
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user