Test 2F TTL (#1782)

This commit is contained in:
Christophe Maudoux 2019-06-07 19:25:40 +02:00
parent bbe18393a5
commit e3c2766809
6 changed files with 92 additions and 6 deletions

View File

@ -3524,6 +3524,9 @@ qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-
'default' => 0,
'type' => 'boolOrExpr'
},
'totp2fTTL' => {
'type' => 'int'
},
'totp2fUserCanChangeKey' => {
'default' => 0,
'type' => 'bool'
@ -3563,6 +3566,9 @@ qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-
'default' => 0,
'type' => 'boolOrExpr'
},
'u2fTTL' => {
'type' => 'int'
},
'u2fUserCanRemoveKey' => {
'default' => 1,
'type' => 'bool'
@ -3764,6 +3770,9 @@ qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-
'default' => 0,
'type' => 'boolOrExpr'
},
'yubikey2fTTL' => {
'type' => 'int'
},
'yubikey2fUrl' => {
'type' => 'text'
},

View File

@ -1369,7 +1369,10 @@ sub attributes {
default => 1,
documentation => 'Authorize users to remove existing U2F key',
},
u2fTTL => {
type => 'int',
documentation => 'U2F device time to live',
},
# TOTP second factor
totp2fActivation => {
type => 'boolOrExpr',
@ -1421,6 +1424,10 @@ sub attributes {
default => 1,
documentation => 'Authorize users to remove existing TOTP secret',
},
totp2fTTL => {
type => 'int',
documentation => 'TOTP device time to live ',
},
# UTOTP 2F
utotp2fActivation => {
@ -1578,6 +1585,10 @@ sub attributes {
default => 1,
documentation => 'Authorize users to remove existing Yubikey',
},
yubikey2fTTL => {
type => 'int',
documentation => 'Yubikey device time to live',
},
# Single session
notifyDeleted => {

View File

@ -689,6 +689,7 @@ sub tree {
'totp2fDisplayExistingSecret',
'totp2fUserCanChangeKey',
'totp2fUserCanRemoveKey',
'totp2fTTL',
]
},
{
@ -698,6 +699,7 @@ sub tree {
nodes => [
'u2fActivation', 'u2fSelfRegistration',
'u2fAuthnLevel', 'u2fUserCanRemoveKey',
'u2fTTL',
]
},
{
@ -745,6 +747,7 @@ sub tree {
'yubikey2fUrl',
'yubikey2fPublicIDSize',
'yubikey2fUserCanRemoveKey',
'yubikey2fTTL',
],
},
'sfRequired',

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -20,7 +20,7 @@ use Lemonldap::NG::Portal::Main::Constants qw(
PE_TOKENEXPIRED
);
our $VERSION = '2.0.2';
our $VERSION = '2.0.5';
extends 'Lemonldap::NG::Portal::Main::Plugin';
@ -126,7 +126,6 @@ sub init {
);
}
}
return 1;
}
@ -137,7 +136,6 @@ sub init {
# run() is called at each authentication, just after sessionInfo populated
sub run {
my ( $self, $req ) = @_;
my $checkLogins = $req->param('checkLogins');
my $spoofId = $req->param('spoofId') || '';
$self->logger->debug("2F checkLogins set") if ($checkLogins);
@ -145,6 +143,71 @@ sub run {
# Skip 2F unless a module has been registered
return PE_OK unless ( @{ $self->sfModules } );
# Remove expired 2F devices
my $session = $req->sessionInfo;
if ( $session->{_2fDevices} ) {
$self->logger->debug("Loading 2F Devices ...");
# Read existing 2FDevices
my $_2fDevices =
eval { from_json( $session->{_2fDevices}, { allow_nonref => 1 } ); };
if ($@) {
$self->logger->error("Bad encoding in _2fDevices: $@");
return PE_ERROR;
}
$self->logger->debug(" -> 2F Device(s) found");
my $u2fTTL = $self->conf->{u2fTTL}
&& $self->conf->{u2fTTL} > 0 ? $self->conf->{u2fTTL} : 0;
my $totpTTL = $self->conf->{totp2fTTL}
&& $self->conf->{totp2fTTL} > 0 ? $self->conf->{totp2fTTL} : 0;
my $ubkTTL = $self->conf->{yubikey2fTTL}
&& $self->conf->{yubikey2fTTL} > 0 ? $self->conf->{yubikey2fTTL} : 0;
if ( $u2fTTL || $totpTTL || $ubkTTL ) {
my $now = time();
my $removed = 0;
$self->logger->debug("Looking for expired 2F device(s)...");
foreach (@$_2fDevices) {
if ( $_->{type} eq 'U2F' ) {
if ( $u2fTTL && $now - $_->{epoch} > $u2fTTL ) {
$self->logger->debug(
"Remove U2F -> $_->{name} / $_->{epoch}");
$self->userLogger->info("Remove expired U2F");
$_->{type} = 'EXPIRED';
$removed++;
}
}
if ( $_->{type} eq 'UBK' ) {
if ( $ubkTTL && $now - $_->{epoch} > $ubkTTL ) {
$self->logger->debug(
"Remove Yubikey -> $_->{name} / $_->{epoch}");
$self->userLogger->info("Remove expired Yubiked");
$_->{type} = 'EXPIRED';
$removed++;
}
}
if ( $_->{type} eq 'TOTP' ) {
if ( $totpTTL && $now - $_->{epoch} > $totpTTL ) {
$self->logger->debug(
"Remove TOTP -> $_->{name} / $_->{epoch}");
$self->userLogger->info("Remove expired TOTP");
$_->{type} = 'EXPIRED';
$removed++;
}
}
}
if ($removed) {
$self->logger->debug(
"Found EXPIRED 2F device(s) => Update persistent session");
@$_2fDevices =
map { $_->{type} =~ /\bEXPIRED\b/ ? () : $_ } @$_2fDevices;
$self->p->updatePersistentSession( $req,
{ _2fDevices => to_json($_2fDevices) } );
}
}
}
# Search for authorized modules for this user
my @am;
foreach my $m ( @{ $self->sfModules } ) {