]> git.proxmox.com Git - pmg-api.git/blobdiff - PMG/AccessControl.pm
pmgversion: be compatible with minimized container installation
[pmg-api.git] / PMG / AccessControl.pm
index 3147fabe29f434b97f2b44548d8a74810affa280..693e5ef110d182f110cf4554f5c4ce51a2287bcf 100644 (file)
@@ -4,61 +4,13 @@ use strict;
 use warnings;
 use Authen::PAM;
 
+use PVE::Tools;
 use PVE::JSONSchema qw(get_standard_option);
+use PVE::Exception qw(raise raise_perm_exc);
 
-my $realm_regex = qr/[A-Za-z][A-Za-z0-9\.\-_]+/;
-
-PVE::JSONSchema::register_format('pmg-realm', \&verify_realm);
-sub verify_realm {
-    my ($realm, $noerr) = @_;
-
-    if ($realm !~ m/^${realm_regex}$/) {
-       return undef if $noerr;
-       die "value does not look like a valid realm\n";
-    }
-    return $realm;
-}
-
-PVE::JSONSchema::register_standard_option('realm', {
-    description => "Authentication domain ID",
-    type => 'string', format => 'pmg-realm',
-    maxLength => 32,
-});
-
-PVE::JSONSchema::register_format('pmg-userid', \&verify_username);
-sub verify_username {
-    my ($username, $noerr) = @_;
-
-    $username = '' if !$username;
-    my $len = length($username);
-    if ($len < 3) {
-       die "user name '$username' is too short\n" if !$noerr;
-       return undef;
-    }
-    if ($len > 64) {
-       die "user name '$username' is too long ($len > 64)\n" if !$noerr;
-       return undef;
-    }
-
-    # we only allow a limited set of characters
-    # colon is not allowed, because we store usernames in
-    # colon separated lists)!
-    # slash is not allowed because it is used as pve API delimiter
-    # also see "man useradd"
-    if ($username =~ m!^([^\s:/]+)\@(${realm_regex})$!) {
-       return wantarray ? ($username, $1, $2) : $username;
-    }
-
-    die "value '$username' does not look like a valid user name\n" if !$noerr;
-
-    return undef;
-}
-
-PVE::JSONSchema::register_standard_option('userid', {
-    description => "User ID",
-    type => 'string', format => 'pmg-userid',
-    maxLength => 64,
-});
+use PMG::UserConfig;
+use PMG::LDAPConfig;
+use PMG::LDAPSet;
 
 sub normalize_path {
     my $path = shift;
@@ -76,7 +28,6 @@ sub normalize_path {
     return $path;
 }
 
-
 # password should be utf8 encoded
 # Note: some plugins delay/sleep if auth fails
 sub authenticate_user {
@@ -86,54 +37,86 @@ sub authenticate_user {
 
     my ($ruid, $realm);
 
-    ($username, $ruid, $realm) = verify_username($username);
+    ($username, $ruid, $realm) = PMG::Utils::verify_username($username);
 
     if ($realm eq 'pam') {
-       is_valid_user_utf8($ruid, $password);
+       die "invalid pam user (only root allowed)\n" if $ruid ne 'root';
+       authenticate_pam_user($ruid, $password);
+       return $username;
+    } elsif ($realm eq 'pmg') {
+       my $usercfg = PMG::UserConfig->new();
+       $usercfg->authenticate_user($username, $password);
        return $username;
+    } elsif ($realm eq 'quarantine') {
+       my $ldap_cfg = PMG::LDAPConfig->new();
+       my $ldap = PMG::LDAPSet->new_from_ldap_cfg($ldap_cfg, 1);
+
+       if (my $ldapinfo = $ldap->account_info($ruid, $password)) {
+           my $pmail = $ldapinfo->{pmail};
+           return $pmail . '@quarantine';
+       } else {
+           die "ldap login failed\n";
+       }
     }
 
     die "no such realm '$realm'\n";
 }
 
-sub domain_set_password {
-    my ($realm, $username, $password) = @_;
+sub set_user_password {
+    my ($username, $password) = @_;
 
-    die "no auth domain specified" if !$realm;
+    my ($ruid, $realm);
+    
+    ($username, $ruid, $realm) = PMG::Utils::verify_username($username);
 
-    die "not implemented";
-}
+    if ($realm eq 'pam') {
+       die "invalid pam user (only root allowed)\n" if $ruid ne 'root';
 
-sub check_user_exist {
-    my ($usercfg, $username, $noerr) = @_;
+       my $cmd = ['usermod'];
 
-    $username = verify_username($username, $noerr);
-    return undef if !$username;
+       my $epw = PVE::Tools::encrypt_pw($password);
 
-    return $usercfg->{users}->{$username} if $usercfg && $usercfg->{users}->{$username};
+       push @$cmd, '-p', $epw, $ruid;
 
-    die "no such user ('$username')\n" if !$noerr;
+       PVE::Tools::run_command($cmd, errmsg => "change password for '$ruid' failed");
 
-    return undef;
+    } elsif ($realm eq 'pmg') {
+       PMG::UserConfig->set_user_password($username, $password);
+    } else {
+       die "no such realm '$realm'\n";
+    }
 }
 
+# test if user exists and is enabled
+# returns: role
 sub check_user_enabled {
     my ($usercfg, $username, $noerr) = @_;
 
-    my $data = check_user_exist($usercfg, $username, $noerr);
-    return undef if !$data;
+    my ($ruid, $realm);
 
-    return 1 if $data->{enable};
+    ($username, $ruid, $realm) = PMG::Utils::verify_username($username, 1);
+
+    if ($realm && $ruid) {
+       if ($realm eq 'pam') {
+           return 'root' if $ruid eq 'root';
+       } elsif ($realm eq 'pmg') {
+           my $usercfg = PMG::UserConfig->new();
+           my $data = $usercfg->lookup_user_data($username, $noerr);
+           return $data->{role} if $data && $data->{enable};
+       } elsif ($realm eq 'quarantine') {
+           return 'quser';
+       }
+    }
 
-    die "user '$username' is disabled\n" if !$noerr;
+    raise_perm_exc("user '$username' is disabled") if !$noerr;
 
     return undef;
 }
 
-sub is_valid_user_utf8 {
+sub authenticate_pam_user {
     my ($username, $password) = @_;
 
-    # user (www-data) need to be able to read /etc/passwd /etc/shadow
+    # user need to be able to read /etc/passwd /etc/shadow
 
     my $pamh = Authen::PAM->new('common-auth', $username, sub {
        my @res;
@@ -158,7 +141,7 @@ sub is_valid_user_utf8 {
        die "auth failed: $err";
     }
 
-    if (($res = $pamh->pam_acct_mgmt (0)) != PAM_SUCCESS) {
+    if (($res = $pamh->pam_acct_mgmt(0)) != PAM_SUCCESS) {
        my $err = $pamh->pam_strerror($res);
        die "auth failed: $err";
     }
@@ -168,10 +151,4 @@ sub is_valid_user_utf8 {
     return 1;
 }
 
-sub is_valid_user {
-    my ($username, $password) = @_;
-
-    return is_valid_user_utf8 ($username, encode("utf8", $password));
-}
-
 1;