Quando estou em um sistema com acesso somente a uma conta, pelo menos o que eu faço quando quero verificar se 'resto-do-mundo' pode acessar os arquivos, é verificar as permissões para o arquivo E o caminho completo para isso:
# 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'
Isto é fácil de implementar com perl e File :: Specs, Cwd, File :: stat e Fncl
Este é um exemplo de script (infelizmente eu esqueci como usar as constantes S_I * de Fnctl (: mode) para operar a lógica bitwise com mode, ou o: FIELDS from File :: stat).
#!/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};
Resultado:
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
Aviso: esta é uma abordagem de meia força bruta (estou certo de que haveria melhores funções para verificar as permissões), mas pelo menos não usa chamadas de sistema e regex. E, pelo menos, aponte o fato de que você deve verificar todos os diretórios no caminho.
Por favor, comentários são bem-vindos para refatoração deste script. Eu apreciarei sugestões para remover o uso de substr para capturar o modo para outros.