Я хочу найти файлы, которые конкретный пользователь не сможет прочитать.
Предположим, что имя пользователя «user123», и они находятся в группе под названием «user123». Я хочу найти файлы, которые, если они принадлежат user123, имеют u + r; в противном случае, если файл является группой user123, он должен иметь g + r; в противном случае он может иметь o + r.
Так как GNU find имеет "-читаемый", я мог бы сделать это:
sudo -u user123 find /start ! -readable -ls
Однако процесс должен запускаться пользователем, который не имеет доступа sudo. Поэтому я попробовал это: (он не проверяет o + r, но это не важно в данный момент)
find /start \( -user user123 ! -perm -u=r \) -o \( -group user123 ! -perm -g=r \) -ls
но он перечисляет этот файл:
272118 4 -rw------- 1 user123 user123 3243 Jul 3 19:50 /start/blah/blah/file.txt
Этот файл является единственным файлом, к /start
которому принадлежит user123 с g=r
off. Это как если бы найти интерпретирует -u=r
как -g=r
.
Я решил попробовать поменять логику и вместо этого проверить not ( truth )
:
find /etc/puppet ! \( \( -user puppet -perm -u=r \) -o \( -group puppet -perm -g=r \) -o \( -perm -o=r \) \) -ls
Это работает!
Почему оригинал find
потерпел неудачу? Это ошибка find
(маловероятно) или логика неверна?
Обновление: у меня была неправильная логика. Как указано ниже, так как! (A || B || C) == (! A &&! B &&! C) это два эквивалентных утверждения:
find /start ! \( \( -user user123 -perm -u=r \) -o \( -group user123 -perm -g=r \) -o \( ! \( -user user123 -o -group user123 \) -perm -o=r \) \) -ls
find /start ! \( -user user123 -perm -u=r \) ! \( -group user123 -perm -g=r \) ! \( ! \( -user user123 -o -group user123 \) -perm -o=r \) -ls
Моей целью было не проверять пользователя / группу дважды. Что мне действительно нужно, так это более сложная структура if-then-else, которая, вероятно, была бы возможна только при наличии оператора -xor. Я мог бы построить xor из и / или / нет, но он был бы более сложным, чем два решения выше.
puppet
имеет доступ к файлу с--wxrwxrwx puppet puppet
.Ответы:
Логика неверна. Вы думаете, что этот файл не должен был быть указан в списке, потому что он принадлежит
user123
и имеет установленныйr
бит пользователя . Тем не менее, он указан, потому что он соответствует второму критерию (принадлежит группеuser123
иr
бит группы не установлен).Ваша вторая версия работает из-за одного из законов де Моргана : отрицание логического ИЛИ группы утверждений логически эквивалентно И отрицанию отдельных утверждений. Другими словами:
Таким образом, рабочая
find
ищет файл, которыйuser123
и читается указанным пользователем) Иuser123
и читается указанной группой) Ив то время как первый
find
ищет файл, которыйuser123
и не читается указанным пользователем ИЛИuser123
и не может быть прочитана указанной группой ИЛИ (если вы ее завершили)Таким образом, файл, соответствующий ЛЮБОМУ из 3 приведенных выше критериев (и не обязательно всех), будет указан, как вы видели.
редактировать
Кстати (после просмотра вашего профиля) я большой поклонник вашей книги О'Рейли :)
источник
( !A && !B && !C )
но я переместил!
внутрь каждой части, которая не действительна. Благодарность!Есть еще много вещей, которые необходимо учитывать, чтобы проверить, есть ли у пользователя доступ к файлу по заданному пути:
За исключением фактического переключения всех uids и gids на пользовательские и проверки, очень трудно реализовать ту же логику, что и система.
С zsh вы можете сделать (как root):
Или с
perl
:То есть в обоих случаях спускайтесь по дереву каталогов,
root
но проверяйте доступ к файлу как соответствующий пользователь.Запуск ,
find -readable
какsome-user
не в тех случаях , когда он не сможет пройти мимо каталогов , для которых пользователь не имеет доступа или нет разрешения на чтение (но , возможно , доступ).Даже если вы рассматриваете только разрешение и владение самим файлом (а не списками ACL или компонентами пути ...), вам нужно как минимум (здесь синтаксис GNU):
Идея заключается в том, что если файл принадлежит пользователю, все остальные разрешения не имеют значения. Если нет, то, если файл принадлежит группе какой-либо из групп пользователей, то разрешение «прочее» не имеет значения.
источник
access()
она использует тот же код ядра, что иopen()
. Таким образом,sudo -u user123 find /start -readable
это лучшее решение, еслиsudo
есть вариант.sudo -u user123 find -readable
, он не будет сообщать о файлах в каталогах, которые вы не можете ввести, или в каталогах, которые вы не можете прочитать (поэтому будут ложные негативы и ложные срабатывания). Вот почему я предлагаю использоватьzsh
для спуска по дереву каталогов как корень и сделатьaccess()
([ -r ... ]
) в качестве фактического пользователя (установка$USERNAME
вzsh
изменениях всех UIDS и GID , какsudo
бы).