lemonldap-ng/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Register/Yubikey.pm

163 lines
4.9 KiB
Perl
Raw Normal View History

2018-03-30 21:24:34 +02:00
# Self Yubikey registration
2018-03-20 18:19:53 +01:00
package Lemonldap::NG::Portal::2F::Register::Yubikey;
use strict;
use Mouse;
use JSON qw(from_json to_json);
2018-03-20 18:19:53 +01:00
use Lemonldap::NG::Portal::Main::Constants qw(
PE_FORMEMPTY
PE_ERROR
);
our $VERSION = '2.0.0';
extends 'Lemonldap::NG::Portal::Main::Plugin';
# INITIALIZATION
has prefix => ( is => 'rw', default => 'yubikey' );
has template => ( is => 'ro', default => 'yubikey2fregister' );
has logo => ( is => 'rw', default => 'yubikey.png' );
2018-03-20 18:19:53 +01:00
sub init {
my ($self) = @_;
$self->conf->{yubikey2fPublicIDSize} ||= 12;
return 1;
}
# RUNNING METHODS
# Main method
sub run {
my ( $self, $req, $action ) = @_;
if ( $action eq 'register' ) {
my $otp = $req->param('otp');
my $UBKName = $req->param('UBKName');
my $epoch = time();
# Set default name if empty
$UBKName ||= $epoch;
if ( $otp
and length($otp) > $self->conf->{yubikey2fPublicIDSize} )
{
2018-03-20 18:19:53 +01:00
my $keys = $req->userData->{_yubikeys} || '';
$keys .= ( $keys ? ', ' : '' )
2018-03-26 10:15:37 +02:00
. substr( $otp, 0, $self->conf->{yubikey2fPublicIDSize} );
my $key = substr( $otp, 0, $self->conf->{yubikey2fPublicIDSize} );
my $list2FDevices = eval {
2018-03-30 21:24:34 +02:00
$self->logger->debug("Looking for 2F Devices ...");
from_json( $req->userData->{list2FDevices},
{ allow_nonref => 1 } );
};
unless ($list2FDevices) {
$self->logger->debug("No 2F Device found");
$list2FDevices = [];
}
# Select U2F Devices only
#my @listU2FKeys = map {
#( $_->{type} eq "U2F" ) ? return $_ : return ();
#} @{$list2FDevices};
#$self->logger->debug("Select U2F Devices only ...");
# Search if Yubikey has been already registered
my $SameUBKFound = 0;
foreach (@$list2FDevices) {
$self->logger->debug("Reading Yubikeys ...");
if ( $_->{_yubikey} eq $key ) {
$SameUBKFound = 1;
last;
}
}
$self->logger->debug("Same 2F Device found ? $SameUBKFound");
if ($SameUBKFound) {
$self->userLogger->error("Yubikey already registered !");
return $self->p->sendError( $req, 'Yubikey already registered', 200 );
}
2018-03-30 21:24:34 +02:00
push @{$list2FDevices},
{
type => 'UBK',
name => $UBKName,
_yubikey => $key,
epoch => $epoch
};
$self->logger->debug(
"Append 2F Device : { type => 'UBK', name => $UBKName }");
$self->p->updatePersistentSession( $req,
{ list2FDevices => to_json($list2FDevices) } );
2018-03-20 18:19:53 +01:00
$self->p->updatePersistentSession( $req, { _yubikeys => $keys } );
2018-03-26 10:15:37 +02:00
return $self->p->sendHtml(
$req, 'error',
params => {
RAW_ERROR => 'yourKeyIsRegistered',
2018-03-26 10:15:37 +02:00
AUTH_ERROR_TYPE => 'positive',
}
);
2018-03-20 18:19:53 +01:00
}
else {
$self->userLogger->error('Yubikey 2F: no code or name');
2018-03-26 10:15:37 +02:00
return $self->p->sendHtml(
$req, 'error',
params => {
AUTH_ERROR => PE_FORMEMPTY,
AUTH_ERROR_TYPE => 'positive',
}
);
2018-03-20 18:19:53 +01:00
}
}
# Check if unregistration is allowed
unless ( $self->conf->{u2fUserCanRemoveKey} ) {
return $self->p->sendError( $req, 'notAutorizated', 200 );
}
if ( $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}']
];
}
2018-03-20 18:19:53 +01:00
else {
$self->userLogger->error("Unknown Yubikey action $action");
2018-03-26 10:15:37 +02:00
return $self->p->sendHtml(
$req, 'error',
params => {
AUTH_ERROR => PE_ERROR,
AUTH_ERROR_TYPE => 'positive',
}
);
2018-03-20 18:19:53 +01:00
}
}
1;