]> git.proxmox.com Git - pmg-api.git/blame - PMG/AccessControl.pm
extended fix #1974: traffic_stat_graph: go through all entries
[pmg-api.git] / PMG / AccessControl.pm
CommitLineData
1360e6f0
DM
1package PMG::AccessControl;
2
3use strict;
4use warnings;
5use Authen::PAM;
6
1a8170cf 7use PVE::Tools;
1360e6f0 8use PVE::JSONSchema qw(get_standard_option);
5232f267 9use PVE::Exception qw(raise raise_perm_exc);
1360e6f0 10
62ebb4bc 11use PMG::UserConfig;
6c54c10a
DM
12use PMG::LDAPConfig;
13use PMG::LDAPSet;
1360e6f0
DM
14
15sub normalize_path {
16 my $path = shift;
17
18 $path =~ s|/+|/|g;
19
20 $path =~ s|/$||;
21
22 $path = '/' if !$path;
23
24 $path = "/$path" if $path !~ m|^/|;
25
26 return undef if $path !~ m|^[[:alnum:]\.\-\_\/]+$|;
27
28 return $path;
29}
30
1360e6f0
DM
31# password should be utf8 encoded
32# Note: some plugins delay/sleep if auth fails
33sub authenticate_user {
34 my ($username, $password, $otp) = @_;
35
36 die "no username specified\n" if !$username;
37
38 my ($ruid, $realm);
39
62ebb4bc 40 ($username, $ruid, $realm) = PMG::Utils::verify_username($username);
1360e6f0
DM
41
42 if ($realm eq 'pam') {
62ebb4bc
DM
43 die "invalid pam user (only root allowed)\n" if $ruid ne 'root';
44 authenticate_pam_user($ruid, $password);
1360e6f0 45 return $username;
6c54c10a 46 } elsif ($realm eq 'pmg') {
62ebb4bc 47 my $usercfg = PMG::UserConfig->new();
be06bc52 48 $usercfg->authenticate_user($username, $password);
62ebb4bc 49 return $username;
6c54c10a
DM
50 } elsif ($realm eq 'quarantine') {
51 my $ldap_cfg = PMG::LDAPConfig->new();
52 my $ldap = PMG::LDAPSet->new_from_ldap_cfg($ldap_cfg, 1);
53
54 if (my $ldapinfo = $ldap->account_info($ruid, $password)) {
55 my $pmail = $ldapinfo->{pmail};
56 return $pmail . '@quarantine';
57 } else {
58 die "ldap login failed\n";
59 }
60 }
62ebb4bc 61
1360e6f0
DM
62 die "no such realm '$realm'\n";
63}
64
be06bc52
DM
65sub set_user_password {
66 my ($username, $password) = @_;
1360e6f0 67
be06bc52
DM
68 my ($ruid, $realm);
69
70 ($username, $ruid, $realm) = PMG::Utils::verify_username($username);
1360e6f0 71
62ebb4bc
DM
72 if ($realm eq 'pam') {
73 die "invalid pam user (only root allowed)\n" if $ruid ne 'root';
1360e6f0 74
62ebb4bc 75 my $cmd = ['usermod'];
1360e6f0 76
1a8170cf 77 my $epw = PVE::Tools::encrypt_pw($password);
1360e6f0 78
62ebb4bc 79 push @$cmd, '-p', $epw, $ruid;
1360e6f0 80
5437c8d1 81 PVE::Tools::run_command($cmd, errmsg => "change password for '$ruid' failed");
1360e6f0 82
62ebb4bc 83 } elsif ($realm eq 'pmg') {
be06bc52 84 PMG::UserConfig->set_user_password($username, $password);
62ebb4bc
DM
85 } else {
86 die "no such realm '$realm'\n";
87 }
1360e6f0
DM
88}
89
62ebb4bc 90# test if user exists and is enabled
d3d13358 91# returns: role
1360e6f0 92sub check_user_enabled {
27ca2dae 93 my ($usercfg, $username, $noerr) = @_;
1360e6f0 94
be06bc52
DM
95 my ($ruid, $realm);
96
97 ($username, $ruid, $realm) = PMG::Utils::verify_username($username, 1);
1360e6f0 98
62ebb4bc
DM
99 if ($realm && $ruid) {
100 if ($realm eq 'pam') {
d3d13358 101 return 'root' if $ruid eq 'root';
62ebb4bc
DM
102 } elsif ($realm eq 'pmg') {
103 my $usercfg = PMG::UserConfig->new();
be06bc52 104 my $data = $usercfg->lookup_user_data($username, $noerr);
d3d13358 105 return $data->{role} if $data && $data->{enable};
6c54c10a
DM
106 } elsif ($realm eq 'quarantine') {
107 return 'quser';
62ebb4bc
DM
108 }
109 }
1360e6f0 110
5232f267 111 raise_perm_exc("user '$username' is disabled") if !$noerr;
1360e6f0
DM
112
113 return undef;
114}
115
62ebb4bc 116sub authenticate_pam_user {
1360e6f0
DM
117 my ($username, $password) = @_;
118
62ebb4bc 119 # user need to be able to read /etc/passwd /etc/shadow
1360e6f0
DM
120
121 my $pamh = Authen::PAM->new('common-auth', $username, sub {
122 my @res;
123 while(@_) {
124 my $msg_type = shift;
125 my $msg = shift;
126 push @res, (0, $password);
127 }
128 push @res, 0;
129 return @res;
130 });
131
132 if (!ref($pamh)) {
133 my $err = $pamh->pam_strerror($pamh);
134 die "Error during PAM init: $err";
135 }
136
137 my $res;
138
139 if (($res = $pamh->pam_authenticate(0)) != PAM_SUCCESS) {
140 my $err = $pamh->pam_strerror($res);
141 die "auth failed: $err";
142 }
143
9d7f54a3 144 if (($res = $pamh->pam_acct_mgmt(0)) != PAM_SUCCESS) {
1360e6f0
DM
145 my $err = $pamh->pam_strerror($res);
146 die "auth failed: $err";
147 }
148
149 $pamh = 0; # call destructor
150
151 return 1;
152}
153
1360e6f0 1541;