package PVE::Auth::PVE; use strict; use warnings; use PVE::Auth::Plugin; use PVE::Cluster qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file); use base qw(PVE::Auth::Plugin); my $shadowconfigfile = "priv/shadow.cfg"; cfs_register_file($shadowconfigfile, \&parse_shadow_passwd, \&write_shadow_config); sub parse_shadow_passwd { my ($filename, $raw) = @_; my $shadow = {}; while ($raw && $raw =~ s/^(.*?)(\n|$)//) { my $line = $1; next if $line =~ m/^\s*$/; # skip empty lines if ($line !~ m/^\S+:\S+:$/) { warn "pve shadow password: ignore invalid line $.\n"; next; } my ($userid, $crypt_pass) = split (/:/, $line); $shadow->{users}->{$userid}->{shadow} = $crypt_pass; } return $shadow; } sub write_shadow_config { my ($filename, $cfg) = @_; my $data = ''; foreach my $userid (keys %{$cfg->{users}}) { my $crypt_pass = $cfg->{users}->{$userid}->{shadow}; $data .= "$userid:$crypt_pass:\n"; } return $data } sub lock_shadow_config { my ($code, $errmsg) = @_; cfs_lock_file($shadowconfigfile, undef, $code); my $err = $@; if ($err) { $errmsg ? die "$errmsg: $err" : die $err; } } sub type { return 'pve'; } sub defaults { return { default => { optional => 1 }, comment => { optional => 1 }, }; } sub authenticate_user { my ($class, $config, $realm, $username, $password) = @_; die "no password\n" if !$password; my $shadow_cfg = cfs_read_file($shadowconfigfile); if ($shadow_cfg->{users}->{$username}) { my $encpw = crypt($password, $shadow_cfg->{users}->{$username}->{shadow}); die "invalid credentials\n" if ($encpw ne $shadow_cfg->{users}->{$username}->{shadow}); } else { die "no password set\n"; } return 1; } sub store_password { my ($class, $config, $realm, $username, $password) = @_; lock_shadow_config(sub { my $shadow_cfg = cfs_read_file($shadowconfigfile); my $epw = PVE::Auth::Plugin::encrypt_pw($password); $shadow_cfg->{users}->{$username}->{shadow} = $epw; cfs_write_file($shadowconfigfile, $shadow_cfg); }); } sub delete_user { my ($class, $config, $realm, $username) = @_; lock_shadow_config(sub { my $shadow_cfg = cfs_read_file($shadowconfigfile); delete $shadow_cfg->{users}->{$username}; cfs_write_file($shadowconfigfile, $shadow_cfg); }); } 1;