From 0637601d8bcebe6130d3613f223f18be9e18bf9b Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Tue, 3 Apr 2018 00:01:01 +0200 Subject: [PATCH] Add delete function to TOTP & Yubikey - TODO : Verify if user is authorized to delete (#1386) --- .../Lemonldap/NG/Portal/2F/Register/TOTP.pm | 42 ++++++++-- .../Lemonldap/NG/Portal/2F/Register/U2F.pm | 76 +++++++++---------- .../NG/Portal/2F/Register/Yubikey.pm | 31 ++++++++ 3 files changed, 99 insertions(+), 50 deletions(-) diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Register/TOTP.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Register/TOTP.pm index 9c8b4fd24..5b761f9a0 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Register/TOTP.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Register/TOTP.pm @@ -65,18 +65,16 @@ sub run { # Now check TOTP code to verify that user has a valid TOTP app my $code = $req->param('code'); my $TOTPName = $req->param('TOTPName'); - unless ($code) { $self->logger->userInfo('TOTP registration: empty validation form'); return $self->p->sendError( $req, 'missingCode', 200 ); } - - + #unless ( $code and $TOTPName ) { - #$self->logger->userInfo( - #'TOTP registration: empty code or name in validation form'); - #return $self->p->sendError( $req, 'missingCode', 200 ); + #$self->logger->userInfo( + #'TOTP registration: empty code or name in validation form'); + #return $self->p->sendError( $req, 'missingCode', 200 ); #} my $r = $self->verifyCode( $self->conf->{totp2fInterval}, @@ -111,13 +109,14 @@ sub run { } push @{$list2FDevices}, { - type => 'totp', + type => 'TOTP', name => $TOTPName, _secret => $token->{_totp2fSecret}, epoch => time() }; + #$self->logger->debug( - #"Append 2F Device : { type => 'totp', name => $TOTPName }"); + #"Append 2F Device : { type => 'totp', name => $TOTPName }"); $self->p->updatePersistentSession( $req, { list2FDevices => to_json($list2FDevices) } ); @@ -190,6 +189,33 @@ sub run { } } + elsif ( $action eq 'delete' ) { + my $epoch = $req->param('epoch'); + + my $list2FDevices = eval { + $self->logger->debug("Loading 2F Devices ..."); + + # Read existing 2FDevices + from_json( $req->userData->{list2FDevices}, { allow_nonref => 1 } ); + }; + + my @keep = (); + while (@$list2FDevices) { + my $element = shift @$list2FDevices; + $self->logger->debug("Looking for 2F Device to delete ..."); + push @keep, $element unless ( $element->{epoch} eq $epoch ); + } + + $self->logger->debug( + "Delete 2F Device : { type => 'TOTP', epoch => $epoch }"); + $self->p->updatePersistentSession( $req, + { list2FDevices => to_json( \@keep ) } ); + $self->userLogger->notice('TOTP deletion succeed'); + return [ 200, [ 'Content-Type' => 'application/json' ], + ['{"result":1}'] ]; + + } + } 1; diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Register/U2F.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Register/U2F.pm index c4e941539..b7e3a1b0d 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Register/U2F.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Register/U2F.pm @@ -66,42 +66,40 @@ sub run { my $list2FDevices = eval { $self->logger->debug("Looking for 2F Devices ..."); + # Read existing 2FDevices from_json( $req->userData->{list2FDevices}, { allow_nonref => 1 } ); }; unless ($list2FDevices) { $self->logger->debug("No 2F Device found"); + # Set default value $list2FDevices = []; } my $keyName = $req->param('keyName'); $self->logger->debug("Key name : $keyName"); - + # Select U2F Devices only #my @listU2FKeys = map { - #( $_->{type} eq "U2F" ) ? return $_ : return (); - #} @{$list2FDevices}; + #( $_->{type} eq "U2F" ) ? return $_ : return (); + #} @{$list2FDevices}; #$self->logger->debug("Select U2F Devices only ..."); - + # Search if U2F Key has been already registered my $SameU2FKeyFound = 0; - foreach ( @$list2FDevices ) { - $self->logger->debug("Reading U2F Keys ..."); - $SameU2FKeyFound ||= 1 if ( ( $_->{name} eq $keyName ) ); - }; - - $self->logger->debug("Same 2F Device found ? $SameU2FKeyFound"); - + foreach (@$list2FDevices) { + $self->logger->debug("Reading U2F Keys ..."); + $SameU2FKeyFound ||= 1 if ( ( $_->{name} eq $keyName ) ); + } + + $self->logger->debug("Same 2F Device found ? $SameU2FKeyFound"); if ($SameU2FKeyFound) { - $self->userLogger->error("U2F Key already registered !"); - return $self->p->sendError( $req, 'Bad challenge', 400 ); - } - - - - + $self->userLogger->error("U2F Key already registered !"); + return $self->p->sendError( $req, 'Bad challenge', 400 ); + } + push @{$list2FDevices}, { type => 'U2F', @@ -218,33 +216,27 @@ sub run { return $self->p->sendError( $req, $err, 200 ); } elsif ( $action eq 'delete' ) { - my $epoch = $req->param('epoch'); - - my $list2FDevices = eval { - $self->logger->debug("Looking for 2F Devices ..."); + my $epoch = $req->param('epoch'); + + my $list2FDevices = eval { + $self->logger->debug("Loading 2F Devices ..."); + # Read existing 2FDevices - from_json( $req->userData->{list2FDevices}, - { allow_nonref => 1 } ); + from_json( $req->userData->{list2FDevices}, { allow_nonref => 1 } ); }; - - my @keep = (); - while ( @$list2FDevices ) { - my $element = shift @$list2FDevices; - push @keep, $element unless ( $element->{epoch} eq $epoch ); - } - - - - - - - - $self->logger->debug( - "Delete 2F Device : { type => 'U2F', epoch => $epoch }"); + + my @keep = (); + while (@$list2FDevices) { + my $element = shift @$list2FDevices; + $self->logger->debug("Looking for 2F Device to delete ..."); + push @keep, $element unless ( $element->{epoch} eq $epoch ); + } + + $self->logger->debug( + "Delete 2F Device : { type => 'U2F', epoch => $epoch }"); $self->p->updatePersistentSession( $req, - { list2FDevices => to_json(\@keep) } ); - - + { list2FDevices => to_json( \@keep ) } ); + $self->p->updatePersistentSession( $req, { diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Register/Yubikey.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Register/Yubikey.pm index 44845e264..cff6480c8 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Register/Yubikey.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Register/Yubikey.pm @@ -85,6 +85,37 @@ sub run { ); } } + + elsif ( $action eq 'delete' ) { + my $epoch = $req->param('epoch'); + + my $list2FDevices = eval { + $self->logger->debug("Loading 2F Devices ..."); + + # Read existing 2FDevices + from_json( $req->userData->{list2FDevices}, { allow_nonref => 1 } ); + }; + + my @keep = (); + while (@$list2FDevices) { + my $element = shift @$list2FDevices; + $self->logger->debug("Looking for 2F Device to delete ..."); + push @keep, $element unless ( $element->{epoch} eq $epoch ); + } + + $self->logger->debug( + "Delete 2F Device : { type => 'UBK', epoch => $epoch }"); + $self->p->updatePersistentSession( $req, + { list2FDevices => to_json( \@keep ) } ); + + $self->userLogger->notice('Yubikey deletion succeed'); + return [ + 200, + [ 'Content-Type' => 'application/json', 'Content-Length' => 12, ], + ['{"result":1}'] + ]; + + } else { $self->userLogger->error("Unknown Yubikey action $action"); return $self->p->sendHtml(