]> git.proxmox.com Git - pve-access-control.git/blobdiff - src/PVE/RPCEnvironment.pm
bump version to 7.1-8
[pve-access-control.git] / src / PVE / RPCEnvironment.pm
index 8aae0940e5157cb7380c29fa801aaeb1517b4891..ed5625e8b65608c2163427ae1f0f4808df0714f8 100644 (file)
@@ -82,7 +82,13 @@ my $compile_acl_path = sub {
     if ($username && $username ne 'root@pam') {
        # intersect user and token permissions
        my $user_privs = $cache->{$username}->{privs}->{$path};
-       $privs = { map { $_ => $user_privs->{$_} && $privs->{$_} } keys %$privs };
+       my $filtered_privs = [ grep { $user_privs->{$_} } keys %$privs ];
+       $privs = { map { $_ => $user_privs->{$_} && $privs->{$_} } @$filtered_privs };
+    }
+
+    foreach my $priv (keys %$privs) {
+       # safeguard, this should never happen anyway
+       delete $privs->{$priv} if !defined($privs->{$priv});
     }
 
     $data->{privs}->{$path} = $privs;
@@ -154,6 +160,8 @@ sub compute_api_permission {
        my $toplevel = ($path =~ /^\/(\w+)/) ? $1 : 'dc';
        if ($toplevel eq 'pool') {
            foreach my $priv (keys %$path_perm) {
+               next if !defined($path_perm->{$priv});
+
                if ($priv =~ m/^VM\./) {
                    $res->{vms}->{$priv} = 1;
                } elsif ($priv =~ m/^Datastore\./) {
@@ -166,6 +174,8 @@ sub compute_api_permission {
        } else {
            my $priv_regex = $priv_re_map->{$toplevel} // next;
            foreach my $priv (keys %$path_perm) {
+               next if !defined($path_perm->{$priv});
+
                next if $priv !~ m/^($priv_regex)/;
                $res->{$toplevel}->{$priv} = 1;
            }
@@ -185,6 +195,7 @@ sub get_effective_permissions {
        '/access/groups' => 1,
        '/nodes' => 1,
        '/pools' => 1,
+       '/sdn' => 1,
        '/storage' => 1,
        '/vms' => 1,
     };
@@ -210,6 +221,9 @@ sub get_effective_permissions {
     my $perms = {};
     foreach my $path (keys %$paths) {
        my $path_perms = $self->permissions($user, $path);
+       foreach my $priv (keys %$path_perms) {
+           delete $path_perms->{$priv} if !defined($path_perms->{$priv});
+       }
        # filter paths where user has NO permissions
        $perms->{$path} = $path_perms if %$path_perms;
     }
@@ -394,17 +408,25 @@ sub exec_api2_perm_check {
     } elsif ($test eq 'userid-group') {
        my $userid = $param->{userid};
        my ($t, $privs, %options) = @$check;
-       return 0 if !$options{groups_param} && !$self->check_user_exist($userid, $noerr);
+
+       my $check_existing_user = !$options{groups_param} || $options{groups_param} ne 'create';
+       return 0 if $check_existing_user && !$self->check_user_exist($userid, $noerr);
+
+       # check permission for ALL groups (and thus ALL users)
        if (!$self->check_any($username, "/access/groups", $privs, 1)) {
+           # list of groups $username has any of $privs on
            my $groups = $self->filter_groups($username, $privs, 1);
            if ($options{groups_param}) {
+               # does $username have any of $privs on all new/updated/.. groups?
                my @group_param = PVE::Tools::split_list($param->{groups});
                raise_perm_exc("/access/groups, " . join("|", @$privs)) if !scalar(@group_param);
                foreach my $pg (@group_param) {
                    raise_perm_exc("/access/groups/$pg, " . join("|", @$privs))
                        if !$groups->{$pg};
                }
-           } else {
+           }
+           if ($check_existing_user) {
+               # does $username have any of $privs on any existing group of $userid
                my $allowed_users = $self->group_member_join([keys %$groups]);
                if (!$allowed_users->{$userid}) {
                    return 0 if $noerr;
@@ -428,12 +450,12 @@ sub exec_api2_perm_check {
        } else {
            die "unknown userid-param test";
        }
-     } elsif ($test eq 'perm-modify') {
+    } elsif ($test eq 'perm-modify') {
        my ($t, $tmplpath) = @$check;
        my $path = PVE::Tools::template_replace($tmplpath, $param);
        $path = PVE::AccessControl::normalize_path($path);
        return $self->check_perm_modify($username, $path, $noerr);
-   } else {
+    } else {
        die "unknown permission test";
     }
 };