Set default name and verify if user is authorized to unregister 2F (#1386)
This commit is contained in:
parent
40b69bb63f
commit
ce08e5c899
|
@ -27,7 +27,7 @@ sub types {
|
||||||
|
|
||||||
BEGIN {
|
BEGIN {
|
||||||
${^WARNING_BITS} =
|
${^WARNING_BITS} =
|
||||||
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55\x01";
|
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55\x05";
|
||||||
}
|
}
|
||||||
eval "$s $val";
|
eval "$s $val";
|
||||||
my $err = join(
|
my $err = join(
|
||||||
|
@ -662,7 +662,7 @@ sub attributes {
|
||||||
|
|
||||||
BEGIN {
|
BEGIN {
|
||||||
${^WARNING_BITS} =
|
${^WARNING_BITS} =
|
||||||
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55\x01";
|
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55\x05";
|
||||||
}
|
}
|
||||||
eval "$s $val";
|
eval "$s $val";
|
||||||
my $err = join(
|
my $err = join(
|
||||||
|
@ -1026,7 +1026,7 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
|
||||||
|
|
||||||
BEGIN {
|
BEGIN {
|
||||||
${^WARNING_BITS} =
|
${^WARNING_BITS} =
|
||||||
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55\x01";
|
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55\x05";
|
||||||
}
|
}
|
||||||
eval $s;
|
eval $s;
|
||||||
my $err = join(
|
my $err = join(
|
||||||
|
@ -1111,7 +1111,7 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
|
||||||
|
|
||||||
BEGIN {
|
BEGIN {
|
||||||
${^WARNING_BITS} =
|
${^WARNING_BITS} =
|
||||||
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55\x01";
|
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55\x05";
|
||||||
}
|
}
|
||||||
eval "$s $val";
|
eval "$s $val";
|
||||||
my $err = join(
|
my $err = join(
|
||||||
|
@ -1134,7 +1134,7 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
|
||||||
|
|
||||||
BEGIN {
|
BEGIN {
|
||||||
${^WARNING_BITS} =
|
${^WARNING_BITS} =
|
||||||
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55\x01";
|
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55\x05";
|
||||||
}
|
}
|
||||||
eval "$s $val";
|
eval "$s $val";
|
||||||
my $err = join(
|
my $err = join(
|
||||||
|
@ -1489,7 +1489,7 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
|
||||||
|
|
||||||
BEGIN {
|
BEGIN {
|
||||||
${^WARNING_BITS} =
|
${^WARNING_BITS} =
|
||||||
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55\x01";
|
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55\x05";
|
||||||
}
|
}
|
||||||
eval $s;
|
eval $s;
|
||||||
my $err = join(
|
my $err = join(
|
||||||
|
@ -1526,7 +1526,7 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
|
||||||
|
|
||||||
BEGIN {
|
BEGIN {
|
||||||
${^WARNING_BITS} =
|
${^WARNING_BITS} =
|
||||||
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55\x01";
|
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55\x05";
|
||||||
}
|
}
|
||||||
eval "$s $val";
|
eval "$s $val";
|
||||||
my $err = join(
|
my $err = join(
|
||||||
|
@ -1877,7 +1877,7 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
|
||||||
|
|
||||||
BEGIN {
|
BEGIN {
|
||||||
${^WARNING_BITS} =
|
${^WARNING_BITS} =
|
||||||
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55\x01";
|
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55\x05";
|
||||||
}
|
}
|
||||||
eval "$s $val";
|
eval "$s $val";
|
||||||
my $err = join(
|
my $err = join(
|
||||||
|
@ -2214,7 +2214,7 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
|
||||||
|
|
||||||
BEGIN {
|
BEGIN {
|
||||||
${^WARNING_BITS} =
|
${^WARNING_BITS} =
|
||||||
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55\x01";
|
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55\x05";
|
||||||
}
|
}
|
||||||
eval "$s $val";
|
eval "$s $val";
|
||||||
my $err = join(
|
my $err = join(
|
||||||
|
@ -2917,7 +2917,7 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
|
||||||
|
|
||||||
BEGIN {
|
BEGIN {
|
||||||
${^WARNING_BITS} =
|
${^WARNING_BITS} =
|
||||||
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55\x01";
|
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55\x05";
|
||||||
}
|
}
|
||||||
eval "$s $val";
|
eval "$s $val";
|
||||||
my $err = join(
|
my $err = join(
|
||||||
|
@ -2996,19 +2996,19 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
|
||||||
'default' => 0,
|
'default' => 0,
|
||||||
'select' => [
|
'select' => [
|
||||||
{
|
{
|
||||||
'k' => '0',
|
'k' => 0,
|
||||||
'v' => 'unsecuredCookie'
|
'v' => 'unsecuredCookie'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'k' => '1',
|
'k' => 1,
|
||||||
'v' => 'securedCookie'
|
'v' => 'securedCookie'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'k' => '2',
|
'k' => 2,
|
||||||
'v' => 'doubleCookie'
|
'v' => 'doubleCookie'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'k' => '3',
|
'k' => 3,
|
||||||
'v' => 'doubleCookieForSingleSession'
|
'v' => 'doubleCookieForSingleSession'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
@ -65,17 +65,16 @@ sub run {
|
||||||
# Now check TOTP code to verify that user has a valid TOTP app
|
# Now check TOTP code to verify that user has a valid TOTP app
|
||||||
my $code = $req->param('code');
|
my $code = $req->param('code');
|
||||||
my $TOTPName = $req->param('TOTPName');
|
my $TOTPName = $req->param('TOTPName');
|
||||||
|
my $epoch = time();
|
||||||
|
|
||||||
|
# Set default name if empty
|
||||||
|
$TOTPName ||= $epoch;
|
||||||
|
|
||||||
unless ($code) {
|
unless ($code) {
|
||||||
$self->logger->userInfo('TOTP registration: empty validation form');
|
$self->logger->userInfo('TOTP registration: empty validation form');
|
||||||
return $self->p->sendError( $req, 'missingCode', 200 );
|
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 );
|
|
||||||
#}
|
|
||||||
my $r = $self->verifyCode(
|
my $r = $self->verifyCode(
|
||||||
$self->conf->{totp2fInterval},
|
$self->conf->{totp2fInterval},
|
||||||
$self->conf->{totp2fRange},
|
$self->conf->{totp2fRange},
|
||||||
|
@ -112,11 +111,11 @@ sub run {
|
||||||
type => 'TOTP',
|
type => 'TOTP',
|
||||||
name => $TOTPName,
|
name => $TOTPName,
|
||||||
_secret => $token->{_totp2fSecret},
|
_secret => $token->{_totp2fSecret},
|
||||||
epoch => time()
|
epoch => $epoch
|
||||||
};
|
};
|
||||||
|
|
||||||
#$self->logger->debug(
|
$self->logger->debug(
|
||||||
#"Append 2F Device : { type => 'totp', name => $TOTPName }");
|
"Append 2F Device : { type => 'totp', name => $TOTPName }");
|
||||||
$self->p->updatePersistentSession( $req,
|
$self->p->updatePersistentSession( $req,
|
||||||
{ list2FDevices => to_json($list2FDevices) } );
|
{ list2FDevices => to_json($list2FDevices) } );
|
||||||
|
|
||||||
|
@ -173,20 +172,19 @@ sub run {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $self->conf->{totp2fUserCanChangeKey} ) {
|
# Check if unregistration is allowed
|
||||||
return $self->p->sendError( $req, 'notAutorizated', 200 );
|
unless ( $self->conf->{totp2fUserCanChangeKey} ) {
|
||||||
}
|
return $self->p->sendError( $req, 'notAutorizated', 200 );
|
||||||
|
}
|
||||||
|
|
||||||
# Get or generate master key
|
# Get or generate master key
|
||||||
if ( $action eq 'unregister' ) {
|
if ( $action eq 'unregister' ) {
|
||||||
$self->p->updatePersistentSession( $req, { _totp2fSecret => '' } );
|
$self->p->updatePersistentSession( $req, { _totp2fSecret => '' } );
|
||||||
$self->userLogger->notice('TOTP unregistration succeed');
|
$self->userLogger->notice('TOTP unregistration succeed');
|
||||||
return [
|
return [ 200, [ 'Content-Type' => 'application/json' ],
|
||||||
200, [ 'Content-Type' => 'application/json' ],
|
['{"result":1}'] ];
|
||||||
['{"result":1}']
|
}
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
elsif ( $action eq 'delete' ) {
|
elsif ( $action eq 'delete' ) {
|
||||||
my $epoch = $req->param('epoch');
|
my $epoch = $req->param('epoch');
|
||||||
|
@ -201,7 +199,7 @@ sub run {
|
||||||
my @keep = ();
|
my @keep = ();
|
||||||
while (@$list2FDevices) {
|
while (@$list2FDevices) {
|
||||||
my $element = shift @$list2FDevices;
|
my $element = shift @$list2FDevices;
|
||||||
$self->logger->debug("Looking for 2F Device to delete ...");
|
$self->logger->debug("Looking for 2F device to delete ...");
|
||||||
push @keep, $element unless ( $element->{epoch} eq $epoch );
|
push @keep, $element unless ( $element->{epoch} eq $epoch );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,8 +46,7 @@ sub run {
|
||||||
my ( $resp, $challenge );
|
my ( $resp, $challenge );
|
||||||
$self->logger->debug('Registration response');
|
$self->logger->debug('Registration response');
|
||||||
unless ($resp = $req->param('registration')
|
unless ($resp = $req->param('registration')
|
||||||
and $challenge = $req->param('challenge')
|
and $challenge = $req->param('challenge') )
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return $self->p->sendError( $req, 'Missing registration parameter',
|
return $self->p->sendError( $req, 'Missing registration parameter',
|
||||||
400 );
|
400 );
|
||||||
|
@ -78,30 +77,12 @@ sub run {
|
||||||
$list2FDevices = [];
|
$list2FDevices = [];
|
||||||
}
|
}
|
||||||
my $keyName = $req->param('keyName');
|
my $keyName = $req->param('keyName');
|
||||||
my $epoch = time();
|
my $epoch = time();
|
||||||
|
|
||||||
|
# Set default name if empty
|
||||||
$keyName ||= $epoch;
|
$keyName ||= $epoch;
|
||||||
$self->logger->debug("Key name : $keyName");
|
$self->logger->debug("Key name : $keyName");
|
||||||
|
|
||||||
# Select U2F Devices only
|
|
||||||
#my @listU2FKeys = map {
|
|
||||||
#( $_->{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");
|
|
||||||
|
|
||||||
if ($SameU2FKeyFound) {
|
|
||||||
$self->userLogger->error("U2F Key already registered !");
|
|
||||||
return $self->p->sendError( $req, 'Bad challenge', 400 );
|
|
||||||
}
|
|
||||||
|
|
||||||
push @{$list2FDevices},
|
push @{$list2FDevices},
|
||||||
{
|
{
|
||||||
type => 'U2F',
|
type => 'U2F',
|
||||||
|
@ -230,7 +211,7 @@ sub run {
|
||||||
my @keep = ();
|
my @keep = ();
|
||||||
while (@$list2FDevices) {
|
while (@$list2FDevices) {
|
||||||
my $element = shift @$list2FDevices;
|
my $element = shift @$list2FDevices;
|
||||||
$self->logger->debug("Looking for 2F Device to delete ...");
|
$self->logger->debug("Looking for 2F device to delete ...");
|
||||||
push @keep, $element unless ( $element->{epoch} eq $epoch );
|
push @keep, $element unless ( $element->{epoch} eq $epoch );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,8 +35,11 @@ sub run {
|
||||||
if ( $action eq 'register' ) {
|
if ( $action eq 'register' ) {
|
||||||
my $otp = $req->param('otp');
|
my $otp = $req->param('otp');
|
||||||
my $UBKName = $req->param('UBKName');
|
my $UBKName = $req->param('UBKName');
|
||||||
if ( $UBKName
|
my $epoch = time();
|
||||||
and $otp
|
|
||||||
|
# Set default name if empty
|
||||||
|
$UBKName ||= $epoch;
|
||||||
|
if ( $otp
|
||||||
and length($otp) > $self->conf->{yubikey2fPublicIDSize} )
|
and length($otp) > $self->conf->{yubikey2fPublicIDSize} )
|
||||||
{
|
{
|
||||||
my $keys = $req->userData->{_yubikeys} || '';
|
my $keys = $req->userData->{_yubikeys} || '';
|
||||||
|
@ -53,13 +56,37 @@ sub run {
|
||||||
$self->logger->debug("No 2F Device found");
|
$self->logger->debug("No 2F Device found");
|
||||||
$list2FDevices = [];
|
$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 );
|
||||||
|
}
|
||||||
|
|
||||||
push @{$list2FDevices},
|
push @{$list2FDevices},
|
||||||
{
|
{
|
||||||
type => 'UBK',
|
type => 'UBK',
|
||||||
name => $UBKName,
|
name => $UBKName,
|
||||||
_yubikey => $key,
|
_yubikey => $key,
|
||||||
epoch => time()
|
epoch => $epoch
|
||||||
};
|
};
|
||||||
|
|
||||||
$self->logger->debug(
|
$self->logger->debug(
|
||||||
"Append 2F Device : { type => 'UBK', name => $UBKName }");
|
"Append 2F Device : { type => 'UBK', name => $UBKName }");
|
||||||
$self->p->updatePersistentSession( $req,
|
$self->p->updatePersistentSession( $req,
|
||||||
|
@ -86,9 +113,13 @@ sub run {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
elsif ( $action eq 'delete' ) {
|
# Check if unregistration is allowed
|
||||||
my $epoch = $req->param('epoch');
|
unless ( $self->conf->{u2fUserCanRemoveKey} ) {
|
||||||
|
return $self->p->sendError( $req, 'notAutorizated', 200 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $action eq 'delete' ) {
|
||||||
|
my $epoch = $req->param('epoch');
|
||||||
my $list2FDevices = eval {
|
my $list2FDevices = eval {
|
||||||
$self->logger->debug("Loading 2F Devices ...");
|
$self->logger->debug("Loading 2F Devices ...");
|
||||||
|
|
||||||
|
@ -99,7 +130,7 @@ sub run {
|
||||||
my @keep = ();
|
my @keep = ();
|
||||||
while (@$list2FDevices) {
|
while (@$list2FDevices) {
|
||||||
my $element = shift @$list2FDevices;
|
my $element = shift @$list2FDevices;
|
||||||
$self->logger->debug("Looking for 2F Device to delete ...");
|
$self->logger->debug("Looking for 2F device to delete ...");
|
||||||
push @keep, $element unless ( $element->{epoch} eq $epoch );
|
push @keep, $element unless ( $element->{epoch} eq $epoch );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user