пятница, 21 августа 2009 г.

sudo и регулярные выражения

Как известно, sudo(1) позволяет администратору разрешить некоторым пользователям запускать определенные команды от имени root-а или другого пользователя. Если файл /etc/sudoers - сетевой, то можно дополнительно ограничить и список хостов, с которых разрешено выполнение той или иной команды. Всё это описано в руководстве.

Для большей гибкости, в sudo предусмотрена поддержка метасимволов * и ?, а также диапазонов [...] и [!...]. Глядя на них может возникнуть желание написать что-то вроде
jonh_smith  ALL=/bin/rm /only/below/this/dir/*
или
jonh_smith    ALL=/bin/mkdir /only/below/this/dir/[a-zA-Z0-9_-]*
даже не взирая на то в руководстве sudoers(4) четко написано:
sudo allows shell-style wildcards ... Note that these are not regular expressions.
Таким образом, sudo не будет возражать против команды
sudo rm /only/below/this/dir/../../other/dir/*
поскольку формально звёздочка "съест" все символы включая / и .. Также у sudo не возникнет вопросов по поводу пары команд
sudo mkdir /only/below/this/dir/a
sudo mkdir /only/below/this/dir/a/../../../another@dir
т.к. фактически на принадлежность к диапазону проверяется только первый символ.

Если регулярные выражения всё же нужны, можно воспользоваться известным приёмом: написать скрипт-обёртку, вызывамый через sudo с произвольными аргументами, который уже сам средствами языка программирования выполнит сколь угодно сложные проверки и только затем запустит потенциально опасную команду. Вот пример на Perl:

Содержимое /etc/sudoers:
jonh_smith  ALL=/usr/local/bin/safe_rm.pl
Исходный код /usr/local/bin/safe_rm.pl:
#!/usr/bin/perl

use strict;
use warnings;

sub main() {
foreach my $arg ( @ARGV ) {
if ( $arg !~ qr{^/only/below/this/dir/[a-zA-Z0-9_-]+$} ) {
die "Unsafe path: '$arg'\n";
}
}

if ( @ARGV > 0 ) {
return system( "/bin/rm", @ARGV );
} else {
die "Empty path list\n";
}
}

main();

Комментариев нет:

Отправить комментарий