X-Git-Url: https://git.proxmox.com/?p=pve-access-control.git;a=blobdiff_plain;f=PVE%2FAuth%2FPlugin.pm;h=3356f691c55d1b5ff8bc3e1b5c5a54e63ac57a8e;hp=e9d54f0147c943ddb340dcc04acb396c669c166f;hb=54028297ea98e9f17ffaefeb2fa22723ed0bceb0;hpb=5bb4e06a6440c8b67e67e14de9e42ba17a966b23 diff --git a/PVE/Auth/Plugin.pm b/PVE/Auth/Plugin.pm index e9d54f0..3356f69 100755 --- a/PVE/Auth/Plugin.pm +++ b/PVE/Auth/Plugin.pm @@ -83,11 +83,65 @@ PVE::JSONSchema::register_standard_option('userid', { maxLength => 64, }); +PVE::JSONSchema::register_format('pve-tfa-config', \&verify_tfa_config); +sub verify_tfa_config { + my ($value, $noerr) = @_; + + return $value if parse_tfa_config($value); + + return undef if $noerr; + + die "unable to parse tfa option\n"; +} + +PVE::JSONSchema::register_standard_option('tfa', { + description => "Use Two-factor authentication.", + type => 'string', format => 'pve-tfa-config', + optional => 1, + maxLength => 128, +}); + +sub parse_tfa_config { + my ($data) = @_; + + my $res = {}; + + foreach my $kvp (split(/,/, $data)) { + + if ($kvp =~ m/^type=(yubico|oath)$/) { + $res->{type} = $1; + } elsif ($kvp =~ m/^id=(\S+)$/) { + $res->{id} = $1; + } elsif ($kvp =~ m/^key=(\S+)$/) { + $res->{key} = $1; + } elsif ($kvp =~ m/^url=(\S+)$/) { + $res->{url} = $1; + } elsif ($kvp =~ m/^digits=([6|7|8])$/) { + $res->{digits} = $1; + } elsif ($kvp =~ m/^step=([1-9]\d+)$/) { + $res->{step} = $1; + } else { + return undef; + } + } + + return undef if !$res->{type}; + + return $res; +} + +my $salt_starter = time(); + sub encrypt_pw { my ($pw) = @_; - my $time = substr(Digest::SHA::sha1_base64 (time), 0, 8); - return crypt(encode("utf8", $pw), "\$5\$$time\$"); + $salt_starter++; + my $salt = substr(Digest::SHA::sha1_base64(time() + $salt_starter + $$), 0, 8); + + # crypt does not want '+' in salt (see 'man crypt') + $salt =~ s/\+/X/g; + + return crypt(encode("utf8", $pw), "\$5\$$salt\$"); } my $defaultData = { @@ -140,16 +194,14 @@ sub parse_config { # add default domains - $cfg->{ids}->{pve} = { - type => 'pve', - comment => "Proxmox VE authentication server", - }; + $cfg->{ids}->{pve}->{type} = 'pve'; # force type + $cfg->{ids}->{pve}->{comment} = "Proxmox VE authentication server" + if !$cfg->{ids}->{pve}->{comment}; - $cfg->{ids}->{pam} = { - type => 'pam', - plugin => 'PVE::Auth::PAM', - comment => "Linux PAM standard authentication", - }; + $cfg->{ids}->{pam}->{type} = 'pam'; # force type + $cfg->{ids}->{pam}->{plugin} = 'PVE::Auth::PAM'; + $cfg->{ids}->{pam}->{comment} = "Linux PAM standard authentication" + if !$cfg->{ids}->{pam}->{comment}; return $cfg; }; @@ -157,9 +209,6 @@ sub parse_config { sub write_config { my ($class, $filename, $cfg) = @_; - delete $cfg->{ids}->{pve}; - delete $cfg->{ids}->{pam}; - foreach my $realm (keys %{$cfg->{ids}}) { my $data = $cfg->{ids}->{$realm}; if ($data->{comment}) {