在 Linux 系统中,我执行了 chmod o+r -R mydir/,我想检查“o”组中的用户是否能够读取 mydir 的内容。我怎样才能像文件组 (o) 以外的其他用户一样执行“ls mydir”?
谢谢
答案1
当我处于只能访问一个帐户的系统中时,至少当我想检查“世界其他地方”是否可以访问这些文件时,我会检查文件的权限和它的完整路径:
# take the cannonic absolute path
# split the dirs and check for each one if it is x and r by 'others'
# check that the final file is readable by 'others'
使用 perl 和 File::Specs、Cwd、File::stat 和 Fncl 可以轻松实现这一点
这是一个示例脚本(不幸的是,我忘记了如何使用 Fnctl (:mode) 中的 S_I* 常量来操作带模式的按位逻辑,或者使用 File::stat 中的 :FIELDS)。
#!/usr/bin/env perl
=head check_file_access_for_all_users.pl
-- Given a path this script checks that all subpaths are
accessible for all users in the system. If no path is given,
then uses the current path
-- <TO_DO> add an option for testing access to all files and dirs
in the last dir of the path
=cut
use strict;
use File::Spec;
use Cwd 'realpath';
use File::stat;
use Fcntl qw(:mode);
my $path = shift;
$path ||='.'; # test current paths if no paths as an argument
# make it absolute and resolve symlinks
my $realpath = realpath($path);
print "realpath: $realpath\n";
# you can split with regex or split but I prefer splitdir
my @dirs= File::Spec->splitdir($realpath);
# last item of @dirs could be a file or symlink (check for (! -d) )
# Remove it: the dirs should be checked for rx and the file only for r
my $file;
if (! -d $dirs[-1]) {
$file = pop @dirs;
}
# prepend / to first element in @dirs: it is an absolute path
# create an array for all the paths to check
my $path_str;
my @paths_list = map {$path_str.='/'.$_;} grep {$_} @dirs;
# list of paths win no access for others
my @paths_for_chmod;
$DB::single=1;
foreach my $path_to_check (@paths_list) {
# this is a dir, so test is 'rw'
my $test = 'rw';
check_path_access($path_to_check, $test);
}
if ($file) {
# check that is readable
my $path_to_check = "$path_str/$file";
# this is a file, so test is 'r'
my $test = 'r';
check_path_access($path_to_check, $test);
}
$DB::single=1;
if (@paths_for_chmod){
print "#[NOT_OK]: Some elements of the path are not accesible by OTHER:\n";
printf ((" %s %s\n" x @paths_for_chmod), map{$_->[0], $_->[1]} @paths_for_chmod);
}
else {
print "The path $path and all its subpaths are accesible by OTHER\n";
}
print "end\n";
##################################################
# Methods
##################################################
sub check_path_access{
my ($path_to_check,$test) = @_;
# dispatch table
my $wanted_test = {
rw => {
test=> \&is_other_rx_bf,
msg => '',
},
r => {
test => \&is_other_r_bf,
msg => '',
},
};
my $mode = stat($path_to_check)->mode;
# get if is rw by others and the octal value of the file permisions
my ($has_o_access, $mode_oct) = $wanted_test->{$test}{test}->($mode);
my $status = $has_o_access?'':' NOT';
my $mode_str = $has_o_access?'':" (mode=$mode_oct)";
print {*STDERR} 'Others can '.$status .' access to ' .$path_to_check. $mode_str."\n";
push @paths_for_chmod, [$mode_str, $path_to_check] unless $has_o_access;
}
# brute force method for obaining mode for others (direct substr to mode string)
sub is_other_rx_bf{
my $mode =shift;
my $mode_oct = sprintf ("%04o", $mode & 07777);
my $oth_mod = substr($mode_oct,3,1);
return $oth_mod>=4?1:0, $mode_oct;
}
sub is_other_r_bf{
my $mode =shift;
my $mode_oct = sprintf ("%04o", $mode & 07777);
my $oth_mod = substr($mode_oct,3,1);
return $oth_mod>=4?1:0, $mode_oct;
}
# unfinished exploration for Fncl :mode constants
sub is_other_rx {
my $mode =shift;
die "not implemented yet\n";
# ?? I can remember how to do this test properly
my $allCanAccess = ($mode & S_IRUSR) # User can read
&& ($mode & S_IRGRP) # Group can read
&& ($mode & S_IROTH); # Others can read
#### perldoc -f stat
## use Fcntl ’:mode’;
##
## $mode = (stat($filename))[2];
##
## $user_rwx = ($mode & S_IRWXU) >> 6;
## $group_read = ($mode & S_IRGRP) >> 3;
## $other_execute = $mode & S_IXOTH;
##
## printf "Permissions are %04o\n", S_IMODE($mode), "\n";
##
## $is_setuid = $mode & S_ISUID;
## $is_setgid = S_ISDIR($mode);
##
## # Permissions: read, write, execute, for user, group, others.
##
## S_IRWXU S_IRUSR S_IWUSR S_IXUSR
## S_IRWXG S_IRGRP S_IWGRP S_IXGRP
## S_IRWXO S_IROTH S_IWOTH S_IXOTH
##
}
# chdir $path;
# my $canonical_path =qx{pwd -P};
结果:
perl check_file_access_for_all_users.pl /Users/pablo/tmp/dir1/dir2/dir3/txt1
Others can access to /Users
Others can access to /Users/pablo
Others can access to /Users/pablo/tmp
Others can NOT access to /Uspablo/pmg/tmp/dir1 (mode=0750)
Others can access to /Users/pablo/tmp/dir1/dir2
Others can access to /Users/pablo/tmp/dir1/dir2/dir3
Others can access to /Users/pablo/tmp/dir1/dir2/dir3/txt1
realpath: /Users/pablo/tmp/dir1/dir2/dir3/txt1
#[NOT_OK]: Some elements of the path are not accesible by OTHER:
(mode=0750) /Users/pablo/tmp/dir1
end
免责声明:这是一种半暴力方法(我相信会有更好的函数来检查权限),但至少它不使用系统调用和正则表达式。并且至少指出你应该检查路径中的所有目录。
欢迎评论以重构此脚本。我将非常感激大家提出建议,删除使用 substr 来捕获模式。
答案2
我知道的唯一方法是创建这样的用户(如果尚不存在),然后使用su -c "ls mydir" user
。