From: Wolfgang Bumiller Date: Fri, 1 Jul 2016 08:15:28 +0000 (+0200) Subject: drop oathtool dependency X-Git-Url: https://git.proxmox.com/?p=pve-access-control.git;a=commitdiff_plain;h=9d52f6f2ae7db192d33312f88c3fe12e8043201e drop oathtool dependency Generate hotp/totp in perl directly, also support keys in hex notation (this is how eg. the yubikey-personalization-gui displays them, but without the whitespaces). --- diff --git a/PVE/AccessControl.pm b/PVE/AccessControl.pm index de2908e..0af92d7 100644 --- a/PVE/AccessControl.pm +++ b/PVE/AccessControl.pm @@ -8,6 +8,7 @@ use Crypt::OpenSSL::RSA; use Net::SSLeay; use Net::IP; use MIME::Base64; +use MIME::Base32 qw(RFC); #libmime-base32-perl use Digest::SHA; use URI::Escape; use LWP::UserAgent; @@ -1172,6 +1173,23 @@ sub remove_vm_from_pool { lock_user_config($delVMfromPoolFn, "pool cleanup for VM $vmid failed"); } +# hotp/totp code + +sub hotp($$;$) { + my ($binsecret, $number, $digits) = @_; + + $digits = 6 if !defined($digits); + + my $bincounter = pack('Q>', $number); + my $hmac = Digest::SHA::hmac_sha1($bincounter, $binsecret); + + my $offset = unpack('C', substr($hmac,19) & pack('C', 0x0F)); + my $part = substr($hmac, $offset, 4); + my $otp = unpack('N', $part); + my $value = ($otp & 0x7fffffff) % (10**$digits); + return sprintf("%0${digits}d", $value); +} + # experimental code for yubico OTP verification sub yubico_compute_param_sig { @@ -1278,20 +1296,23 @@ sub oath_verify_otp { $digits = 6 if !$digits; my $found; - - my $parser = sub { - my $line = shift; - - if ($line =~ m/^\d{6}$/) { - $found = 1 if $otp eq $line; - } - }; - foreach my $k (PVE::Tools::split_list($keys)) { # Note: we generate 3 values to allow small time drift - my $now = localtime(time() - $step); - my $cmd = ['oathtool', '--totp', '--digits', $digits, '-N', $now, '-s', $step, '-w', '2', '-b', $k]; - eval { run_command($cmd, outfunc => $parser, errfunc => sub {}); }; + my $binkey; + if ($k =~ /^[A-Z2-7=]{32}$/) { + $binkey = MIME::Base32::decode_rfc3548($k); + } elsif ($k =~ /^[A-Fa-f0-9]{40}$/) { + $binkey = pack('H*', $k); + } else { + die "unrecognized key format, must be hex or base32 encoded\n"; + } + + # force integer division for time/step + use integer; + my $now = time()/$step - 1; + $found = 1 if $otp eq hotp($binkey, $now+0, $digits); + $found = 1 if $otp eq hotp($binkey, $now+1, $digits); + $found = 1 if $otp eq hotp($binkey, $now+2, $digits); last if $found; } diff --git a/control.in b/control.in index b74aaf1..758e9a0 100644 --- a/control.in +++ b/control.in @@ -3,7 +3,7 @@ Version: @@VERSION@@-@@PKGRELEASE@@ Section: perl Priority: optional Architecture: @@ARCH@@ -Depends: libc6 (>= 2.3), perl (>= 5.6.0-16), libcrypt-openssl-rsa-perl, libcrypt-openssl-random-perl, libjson-xs-perl, libjson-perl, libterm-readline-gnu-perl,libnet-ldap-perl, libpve-common-perl, pve-cluster, libauthen-pam-perl, libnet-ssleay-perl, liburi-perl, libwww-perl, oathtool, libmime-base32-perl +Depends: libc6 (>= 2.3), perl (>= 5.6.0-16), libcrypt-openssl-rsa-perl, libcrypt-openssl-random-perl, libjson-xs-perl, libjson-perl, libterm-readline-gnu-perl,libnet-ldap-perl, libpve-common-perl, pve-cluster, libauthen-pam-perl, libnet-ssleay-perl, liburi-perl, libwww-perl, libmime-base32-perl Maintainer: Proxmox Support Team Description: Proxmox VE access control library This package contains the role based user management and access