forked from extern/nushell
Check all user groups. (#7775)
Previously the group check was only for the current users gid, now we check against all the users groups. # Description Currently when using the `cd` command to enter a directory there was only a check against the current user id, and exact current group id, meaning if a directory had a group permission and that group wasn't the users group it was effectively ignored. The fix simply implements a check through all the users current groups. Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
This commit is contained in:
parent
8acced56b2
commit
adcc74ab8d
@ -1,5 +1,7 @@
|
||||
use crate::filesystem::cd_query::query;
|
||||
use crate::{get_current_shell, get_shells};
|
||||
#[cfg(unix)]
|
||||
use libc::gid_t;
|
||||
use nu_engine::{current_dir, CallExt};
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
@ -246,14 +248,17 @@ fn have_permission(dir: impl AsRef<Path>) -> PermissionResult<'static> {
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
let bits = metadata.mode();
|
||||
let has_bit = |bit| bits & bit == bit;
|
||||
let current_user = users::get_current_uid();
|
||||
if current_user == 0 {
|
||||
let current_user_uid = users::get_current_uid();
|
||||
if current_user_uid == 0 {
|
||||
return PermissionResult::PermissionOk;
|
||||
}
|
||||
let current_group = users::get_current_gid();
|
||||
let current_user_gid = users::get_current_gid();
|
||||
let owner_user = metadata.uid();
|
||||
let owner_group = metadata.gid();
|
||||
match (current_user == owner_user, current_group == owner_group) {
|
||||
match (
|
||||
current_user_uid == owner_user,
|
||||
current_user_gid == owner_group,
|
||||
) {
|
||||
(true, _) => {
|
||||
if has_bit(permission_mods::unix::USER_EXECUTE) {
|
||||
PermissionResult::PermissionOk
|
||||
@ -272,9 +277,11 @@ fn have_permission(dir: impl AsRef<Path>) -> PermissionResult<'static> {
|
||||
)
|
||||
}
|
||||
}
|
||||
// other_user or root
|
||||
(false, false) => {
|
||||
if has_bit(permission_mods::unix::OTHER_EXECUTE) {
|
||||
if has_bit(permission_mods::unix::OTHER_EXECUTE)
|
||||
|| (has_bit(permission_mods::unix::GROUP_EXECUTE)
|
||||
&& any_group(current_user_gid, owner_group))
|
||||
{
|
||||
PermissionResult::PermissionOk
|
||||
} else {
|
||||
PermissionResult::PermissionDenied(
|
||||
@ -287,3 +294,29 @@ fn have_permission(dir: impl AsRef<Path>) -> PermissionResult<'static> {
|
||||
Err(_) => PermissionResult::PermissionDenied("Could not retrieve the metadata"),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn any_group(current_user_gid: gid_t, owner_group: u32) -> bool {
|
||||
users::get_current_username()
|
||||
.map(|name| {
|
||||
users::get_user_groups(&name, current_user_gid)
|
||||
.map(|mut groups| {
|
||||
// Fixes https://github.com/ogham/rust-users/issues/44
|
||||
// If a user isn't in more than one group then this fix won't work,
|
||||
// However its common for a user to be in more than one group, so this should work for most.
|
||||
if groups.len() == 2 && groups[1].gid() == 0 {
|
||||
// We have no way of knowing if this is due to the issue or the user is actually in the root group
|
||||
// So we will assume they are in the root group and leave it.
|
||||
// It's not the end of the world if we are wrong, they will just get a permission denied error once inside.
|
||||
} else {
|
||||
groups.pop();
|
||||
}
|
||||
|
||||
groups
|
||||
})
|
||||
.unwrap_or_default()
|
||||
})
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.any(|group| group.gid() == owner_group)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user