В системе linux я выполнил команду chmod o+r -R mydir/ и хочу убедиться, что пользователи из группы 'o' могут читать содержимое mydir. Как я могу сделать 'ls mydir', как если бы я был пользователем других пользователей, не входящих в группу файла (o)?

Спасибо

2 ответа2

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.

Это пример сценария (к сожалению, я забыл, как использовать константы S_I * из Fnctl (:mode) для работы с побитовой логикой в режиме или:FIELDS из 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};

Результат:

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 для ловли режима для других.

0

Единственный известный мне метод - создать такого пользователя (если он еще не существует), а затем использовать пользователя su -c "ls mydir" user .

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .