1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
|
# --
# Copyright (C) 2001-2021 OTRS AG, https://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --
package Kernel::System::CustomerAuth::TwoFactor::GoogleAuthenticator;
use strict;
use warnings;
use Digest::SHA qw(sha1);
use Digest::HMAC qw(hmac_hex);
use parent qw(Kernel::System::Auth::TwoFactor::GoogleAuthenticator);
our @ObjectDependencies = (
'Kernel::Config',
'Kernel::System::CustomerUser',
'Kernel::System::Log',
);
sub new {
my ( $Type, %Param ) = @_;
# allocate new hash for object
my $Self = {};
bless( $Self, $Type );
$Self->{Count} = $Param{Count} || '';
return $Self;
}
sub Auth {
my ( $Self, %Param ) = @_;
# check needed stuff
if ( !$Param{User} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need User!"
);
return;
}
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
my $SecretPreferencesKey
= $ConfigObject->Get("Customer::AuthTwoFactorModule$Self->{Count}::SecretPreferencesKey") || '';
if ( !$SecretPreferencesKey ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Found no configuration for SecretPreferencesKey in Customer::AuthTwoFactorModule.",
);
return;
}
# check if customer has secret stored in preferences
my %UserPreferences = $Kernel::OM->Get('Kernel::System::CustomerUser')->GetPreferences(
UserID => $Param{User},
);
if ( !$UserPreferences{$SecretPreferencesKey} ) {
# if login without a stored secret key is permitted, this counts as passed
if ( $ConfigObject->Get("Customer::AuthTwoFactorModule$Self->{Count}::AllowEmptySecret") ) {
return 1;
}
# otherwise login counts as failed
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Found no SecretPreferencesKey for customer $Param{User}.",
);
return;
}
# if we get to here (user has preference), we need a passed token
if ( !$Param{TwoFactorToken} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'notice',
Message => "CustomerUser: $Param{User} two factor customer authentication failed (TwoFactorToken missing)."
);
return;
}
# generate otp based on secret from preferences
my $OTP = $Self->_GenerateOTP(
Secret => $UserPreferences{$SecretPreferencesKey},
);
# compare against user provided otp
if ( $Param{TwoFactorToken} ne $OTP ) {
# check if previous token is also to be accepted
if ( $ConfigObject->Get("Customer::AuthTwoFactorModule$Self->{Count}::AllowPreviousToken") ) {
# try again with previous otp (from 30 seconds ago)
$OTP = $Self->_GenerateOTP(
Secret => $UserPreferences{$SecretPreferencesKey},
Previous => 1,
);
}
if ( $Param{TwoFactorToken} ne $OTP ) {
# log failure
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'notice',
Message => "CustomerUser: $Param{User} two factor customer authentication failed (non-matching otp).",
);
return;
}
}
# log success
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'notice',
Message => "CustomerUser: $Param{User} two factor customer authentication ok.",
);
return 1;
}
1;
|