]> git.proxmox.com Git - pve-access-control.git/blob - PVE/Auth/PVE.pm
de39d35bef9022c48d8e9ef17499cf2e1e37070f
[pve-access-control.git] / PVE / Auth / PVE.pm
1 package PVE::Auth::PVE;
2
3 use strict;
4 use warnings;
5 use Encode;
6
7 use PVE::Tools;
8 use PVE::Auth::Plugin;
9 use PVE::Cluster qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
10
11 use base qw(PVE::Auth::Plugin);
12
13 my $shadowconfigfile = "priv/shadow.cfg";
14
15 cfs_register_file($shadowconfigfile,
16 \&parse_shadow_passwd,
17 \&write_shadow_config);
18
19 sub parse_shadow_passwd {
20 my ($filename, $raw) = @_;
21
22 my $shadow = {};
23
24 return $shadow if !defined($raw);
25
26 while ($raw =~ /^\s*(.+?)\s*$/gm) {
27 my $line = $1;
28
29 if ($line !~ m/^\S+:\S+:$/) {
30 warn "pve shadow password: ignore invalid line $.\n";
31 next;
32 }
33
34 my ($userid, $crypt_pass) = split (/:/, $line);
35 $shadow->{users}->{$userid}->{shadow} = $crypt_pass;
36 }
37
38 return $shadow;
39 }
40
41 sub write_shadow_config {
42 my ($filename, $cfg) = @_;
43
44 my $data = '';
45 foreach my $userid (keys %{$cfg->{users}}) {
46 my $crypt_pass = $cfg->{users}->{$userid}->{shadow};
47 $data .= "$userid:$crypt_pass:\n";
48 }
49
50 return $data
51 }
52
53 sub lock_shadow_config {
54 my ($code, $errmsg) = @_;
55
56 cfs_lock_file($shadowconfigfile, undef, $code);
57 my $err = $@;
58 if ($err) {
59 $errmsg ? die "$errmsg: $err" : die $err;
60 }
61 }
62
63 sub type {
64 return 'pve';
65 }
66
67 sub options {
68 return {
69 default => { optional => 1 },
70 comment => { optional => 1 },
71 tfa => { optional => 1 },
72 };
73 }
74
75 sub authenticate_user {
76 my ($class, $config, $realm, $username, $password) = @_;
77
78 die "no password\n" if !$password;
79
80 my $shadow_cfg = cfs_read_file($shadowconfigfile);
81
82 if ($shadow_cfg->{users}->{$username}) {
83 my $encpw = crypt(Encode::encode('utf8', $password),
84 $shadow_cfg->{users}->{$username}->{shadow});
85 die "invalid credentials\n" if ($encpw ne $shadow_cfg->{users}->{$username}->{shadow});
86 } else {
87 die "no password set\n";
88 }
89
90 return 1;
91 }
92
93 sub store_password {
94 my ($class, $config, $realm, $username, $password) = @_;
95
96 lock_shadow_config(sub {
97 my $shadow_cfg = cfs_read_file($shadowconfigfile);
98 my $epw = PVE::Tools::encrypt_pw($password);
99 $shadow_cfg->{users}->{$username}->{shadow} = $epw;
100 cfs_write_file($shadowconfigfile, $shadow_cfg);
101 });
102 }
103
104 sub delete_user {
105 my ($class, $config, $realm, $username) = @_;
106
107 lock_shadow_config(sub {
108 my $shadow_cfg = cfs_read_file($shadowconfigfile);
109
110 delete $shadow_cfg->{users}->{$username};
111
112 cfs_write_file($shadowconfigfile, $shadow_cfg);
113 });
114 }
115
116 1;