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