суббота, 30 августа 2014 г.

Linux. Упражнения с rwx

Я собираюсь исследовать на практике то, что в общих чертах представляю себе в теории. А именно: на простых примерах разобраться, как работают права доступа к файлам и каталогам в Linux. Все приводимые далее примеры я буду выполнять в консоли Ubuntu 14.04.

Для начала, создам пользователя для экспериментов:

andrey@tsuki:~$ sudo useradd -m ay
[sudo] password for andrey: 
andrey@tsuki:~$ sudo passwd ay
Enter new UNIX password: 
Retype new UNIX password: 
passwd: password updated successfully

(Введенный мной пароль не виден. А имя моего компьютера 'tsuki' по-японски значит 'луна'.) Смотрю информацию о только что созданном пользователе:

andrey@tsuki:~$ grep 'ay' /etc/passwd
ay:x:1002:1002::/home/ay:

В 3-ем поле - идентификатор пользователя (uid) 1002. Первичная (primary) группа нового пользователя - в 4-ом поле - имеет идентификатор (gid) 1002, совпадающий с идентификатором пользователя. Эта персональная группа была создана командой useradd вместе с новым пользователем ay и специально для него, и этот пользователь - единственный ее член.

andrey@tsuki:~$ grep 1002 /etc/group
ay:x:1002:
andrey@tsuki:~$ groups ay
ay : ay

Первичная группа присваивается всем каталогам и файлам, создаваемым пользователем. Из-за того, что первичной группой назначена персональная группа, создаваемые пользователем каталоги и файлы по умолчанию принадлежат группе, единственный член которой - этот пользователь. Это такой трюк - для обеспечения приватности данных пользователя.

Теперь открою рабочий сеанс как пользователь ay и проверю разрешения (permissions), по умолчанию установленные для его домашнего каталога.

andrey@tsuki:~$ su - ay
Password: 
ay@tsuki:~$ pwd
/home/ay
ay@tsuki:~$ ls -ld /home/ay
drwxr-xr-x 2 ay ay 4096 авг.  27 21:15 /home/ay
ay@tsuki:~$ ls -ld /home
drwxr-xr-x 5 root root 4096 авг.  27 21:15 /home
ay@tsuki:~$ 

Как видим, пользователь ay по умолчанию обладает всеми правами на свой домашний каталог /home/ay, а все остальные могут читать (r) этот каталог и получать доступ к файлам в нем (x). Всеми правами на каталог /home обладает его владелец root, а остальные пользователи могут читать этот каталог и получать доступ к файлам в нем.

Замечу, что разрешения (и их отсутствие) на доступ к каталогу для некоторого пользователя не ограничивают возможность доступа этого пользователя к подкаталогам данного каталога. Посмотрите еще раз на владельцев и разрешения для каталогов /home и /home/ay, чтобы понять, о чем речь. Пользователь ay очевидно не может создать файл в каталоге /home, но может сделать это в каталоге /home/ay:

ay@tsuki:~$ echo Hello > /home/hello.txt
-su: /home/hello.txt: Permission denied
ay@tsuki:~$ echo Hello > /home/ay/hello.txt
ay@tsuki:~$ cat /home/ay/hello.txt
Hello

Понять, как работают разрешения rwx для каталога, поможет сравнение каталога с коробкой, на крышке которой имеется список ее содержимого. Тогда

  • r позволяет читать список содержимого каталога, например, выполнить команду ls (но не дает доступа к файлам в каталоге),
  • w позволяет изменять список содержимого, но не само содержимое (не дает доступа к файлам в каталоге); однако работает только вместе с x,
  • x позволяет сделать каталог текущим (влезть в коробку) и дает доступ к файлам в каталоге (но не позволяет читать или изменять список на крышке).

Если у вас есть x, но нет r для каталога, вы не сможете получить список файлов в каталоге. Но при этом, если вы знаете имя файла в каталоге, то сможете получить доступ к этому файлу!

Для экспериментальной проверки сказанного создам каталог dummy:

ay@tsuki:~$ mkdir dummy
ay@tsuki:~$ ls -ld dummy
drwxrwxr-x 2 ay ay 4096 авг.  27 21:32 dummy

Почему созданный каталог имеет разрешения rwxrwxr-x? Разрешения для новых каталогов формируются так: берется полный набор разрешений rwxrwxrwx и от него отнимаются разрешения, заданные восьмиричной маской создания пользовательских файлов (umask). Посмотрим значение этой маски:

ay@tsuki:~$ umask
0002

Таким образом, для нового каталога из триады разрешений other исключается разрешение w, соответствующее установленному биту маски.

В отличие от каталогов, у новых файлов, создаваемых пользователем, по умолчанию отключены как разрешения x во всех триадах, так и разрешения, заданные umask:

ay@tsuki:~$ ls -l hello.txt
-rw-rw-r-- 1 ay ay 6 авг.  27 21:31 hello.txt

Разрешения по умолчанию для новых файлов и каталогов можно изменить. Для этого с помощью команды umask нужно установить другую маску создания пользовательских файлов. (Часто в файле .profile можно увидеть umask 0022, что делает создаваемые пользователем файлы и каталоги доступными на запись только владельцу.)

Прежде чем приступиить к экспериментам с каталогом dummy, положу в него что-нибудь:

ay@tsuki:~$ mv hello.txt dummy/
ay@tsuki:~$ ls dummy
hello.txt

Я собираюсь выполнять операции с каталогом и файлами в нем при различных установленных разрешениях для каталога. Кстати, изменять разрешения каталога или файла может только его владелец и root (так что никаких специальных разрешений на изменение разрешений не существует).

Я буду пытаться

  1. получить список файлов в каталоге командой ls,
  2. создать новый файл в каталоге,
  3. изменить существующий файл в каталоге,
  4. удалить существующий файл в каталоге,
  5. создать линк (еще одно имя) для файла в каталоге,
  6. сделать каталог текущим.

Начну с единственного разрешения r для каталога:

ay@tsuki:~$ chmod 400 dummy
ay@tsuki:~$ ls -ld dummy
dr-------- 2 ay ay 4096 авг.  27 21:36 dummy
ay@tsuki:~$ ls -l dummy
ls: cannot access dummy/hello.txt: Permission denied
total 0
-????????? ? ? ? ?              ? hello.txt
ay@tsuki:~$ echo Bye > dummy/bye.txt
-su: dummy/bye.txt: Permission denied
ay@tsuki:~$ echo "world" >> dummy/hello.txt
-su: dummy/hello.txt: Permission denied
ay@tsuki:~$ rm dummy/hello.txt
rm: cannot remove ‘dummy/hello.txt’: Permission denied
ay@tsuki:~$ ln dummy/hello.txt hello.here
ln: failed to access ‘dummy/hello.txt’: Permission denied
ay@tsuki:~$ cd dummy
-su: cd: dummy: Permission denied

Как видим, разрешения r достаточно для получения имен файлов в каталоге, но не других атрибутов файла. Ожидаемо нельзя создать, переименовать, удалить файл в этом каталоге, нельзя создать линк (новое имя) для файла, находящегося в каталоге, нельзя сделать каталог текущим.

Я написал программку, которая проверяет возможность выполнения этих операций для каталога с разными комбинациями разрешений и выводит результаты в удобочитаемой форме. Вот ее текст и результат выполнения:

ay@tsuki:~/dummy$ report() {
>     if [ $? == 0 ]
>     then
>         echo '### Succeeded' $1
>     else
>         echo '### Failed' $1
>     fi
> }

ay@tsuki:~/dummy$ for x in 100 200 300 400 500 600 700
> do
>     # re-create initial test conditions
>     cd
>     chmod -R 700 dummy
>     rm dummy/* hello*
>     echo Hello > dummy/hello.txt
>     echo Hello > dummy/hello.two
> 
>     # set catalog permissions
>     echo '### ------------------------------'
>     chmod $x dummy
>     echo '###' `ls -ld dummy`
> 
>     # perform operations
>     ls dummy
>     report 'ls dummy'
> 
>     echo Bye > dummy/bye.txt
>     report 'to create file in dummy'
> 
>     ln -v dummy/hello.txt hello.here
>     report 'to create link for file in dummy'
> 
>     mv dummy/hello.txt dummy/hello.renamed
>     report 'to rename file in dummy'
> 
>     rm -v dummy/hello.two
>     report 'to remove file in dummy'
> 
>     cd dummy
>     report 'cd dummy'
> done 2> /dev/null | grep '###'

### ------------------------------
### d--x------ 2 ay ay 4096 авг. 27 22:43 dummy
### Failed ls dummy
### Failed to create file in dummy
### Succeeded to create link for file in dummy
### Failed to rename file in dummy
### Failed to remove file in dummy
### Succeeded cd dummy
### ------------------------------
### d-w------- 2 ay ay 4096 авг. 27 22:43 dummy
### Failed ls dummy
### Failed to create file in dummy
### Failed to create link for file in dummy
### Failed to rename file in dummy
### Failed to remove file in dummy
### Failed cd dummy
### ------------------------------
### d-wx------ 2 ay ay 4096 авг. 27 22:43 dummy
### Failed ls dummy
### Succeeded to create file in dummy
### Succeeded to create link for file in dummy
### Succeeded to rename file in dummy
### Succeeded to remove file in dummy
### Succeeded cd dummy
### ------------------------------
### dr-------- 2 ay ay 4096 авг. 27 22:43 dummy
### Succeeded ls dummy
### Failed to create file in dummy
### Failed to create link for file in dummy
### Failed to rename file in dummy
### Failed to remove file in dummy
### Failed cd dummy
### ------------------------------
### dr-x------ 2 ay ay 4096 авг. 27 22:43 dummy
### Succeeded ls dummy
### Failed to create file in dummy
### Succeeded to create link for file in dummy
### Failed to rename file in dummy
### Failed to remove file in dummy
### Succeeded cd dummy
### ------------------------------
### drw------- 2 ay ay 4096 авг. 27 22:43 dummy
### Succeeded ls dummy
### Failed to create file in dummy
### Failed to create link for file in dummy
### Failed to rename file in dummy
### Failed to remove file in dummy
### Failed cd dummy
### ------------------------------
### drwx------ 2 ay ay 4096 авг. 27 22:43 dummy
### Succeeded ls dummy
### Succeeded to create file in dummy
### Succeeded to create link for file in dummy
### Succeeded to rename file in dummy
### Succeeded to remove file in dummy
### Succeeded cd dummy

Советую строчка за строчкой прочитать вывод программы (если вы этого еще не сделали) и убедиться, что вы понимаете, почему та или иная операция удалась или не удалась. Как видим, разрешения rwx для каталога по одиночке позволяют очень немногое, но их комбинации уже достаточно функциональны.

Обратите внимание, что возможности создания, переименования, удаления файла, а также создания линка на файл, полностью определяются разрешениями каталога, в котором находятся (или будут создаваться) файлы! И совсем не зависят от прав доступа самих файлов.

Вот пример успешного переименования и удаления файла, у которого отобраны все разрешения:

ay@tsuki:~$ rm dummy/*
ay@tsuki:~$ echo Hello > dummy/hello.txt
ay@tsuki:~$ chmod 000 dummy/hello.txt
ay@tsuki:~$ ls -l dummy
total 4
---------- 1 ay ay 6 авг.  27 22:49 hello.txt
ay@tsuki:~$ mv dummy/hello.txt dummy/hi.txt
ay@tsuki:~$ ls -l dummy
total 4
---------- 1 ay ay 6 авг.  27 22:49 hi.txt
ay@tsuki:~$ rm dummy/hi.txt
rm: remove write-protected regular file ‘dummy/hi.txt’? yes
ay@tsuki:~$ ls -l dummy
total 0

С разрешениями на доступ к файлу дело обстоит проще, чем с разрешениями каталога:

  • r позволяет читать содержимое файла,
  • w позволяет изменять содержимое файла,
  • x позволяет выполнять файл (это должен быть файл с программой).

Приведу примеры, демонстрирующие, как работают rwx разрешения файла. Для этого создам файл hello, содержащий исполняемую команду (ведь предстоит проверить возможность исполнения файла):

ay@tsuki:~$ echo 'echo Hello' > hello
ay@tsuki:~$ bash hello
Hello

Сделаю файл доступным только на чтение и попробую

  1. прочитать его,
  2. изменить его содержимое,
  3. выполнить его.
ay@tsuki:~$ chmod u=r,go= hello
ay@tsuki:~$ ls -l hello
-r-------- 1 ay ay 11 авг.  30 12:14 hello
ay@tsuki:~$ cat hello
echo Hello
ay@tsuki:~$ echo 'echo world' >> hello
-su: hello: Permission denied
ay@tsuki:~$ ./hello
-su: ./hello: Permission denied

Теперь систематически проделаю эти же операции для разных комбинаций разрешений файла, вопользовавшись уже известным подходом:

ay@tsuki:~$ report() {
>     if [ $? == 0 ]
>     then
>         echo '### Succeeded' $1
>     else
>         echo '### Failed' $1
>     fi
> }

ay@tsuki:~$ for x in 100 200 300 400 500 600 700
> do
>     # re-create initial test conditions
> 
>     # set file permissions
>     echo '### ------------------------------'
>     chmod $x hello
>     echo '###' `ls -l hello`
> 
>     # perform operations
>     cat hello
>     report 'to read hello'
> 
>     echo 'echo world' >> hello
>     report 'to change hello'
> 
>     ./hello
>     report 'to execute hello'
> 
> done 2> /dev/null | grep '###'

### ------------------------------
### ---x------ 1 ay ay 11 авг. 30 12:14 hello
### Failed to read hello
### Failed to change hello
### Failed to execute hello
### ------------------------------
### --w------- 1 ay ay 11 авг. 30 12:14 hello
### Failed to read hello
### Succeeded to change hello
### Failed to execute hello
### ------------------------------
### --wx------ 1 ay ay 22 авг. 30 12:19 hello
### Failed to read hello
### Succeeded to change hello
### Failed to execute hello
### ------------------------------
### -r-------- 1 ay ay 33 авг. 30 12:19 hello
### Succeeded to read hello
### Failed to change hello
### Failed to execute hello
### ------------------------------
### -r-x------ 1 ay ay 33 авг. 30 12:19 hello
### Succeeded to read hello
### Failed to change hello
### Succeeded to execute hello
### ------------------------------
### -rw------- 1 ay ay 33 авг. 30 12:19 hello
### Succeeded to read hello
### Succeeded to change hello
### Failed to execute hello
### ------------------------------
### -rwx------ 1 ay ay 44 авг. 30 12:19 hello
### Succeeded to read hello
### Succeeded to change hello
### Succeeded to execute hello

Как видим, одного разрешения x недостаточно для выполнения файла. Нельзя выполнить файл, который нельзя прочитать - поэтому x работает вместе с r.

На сегодня это все. В следующий раз я собираюсь поэкспериментировать с атрибутами каталогов и файлов setuid, setgid и sticky bit, и тем самым сверить с действительностью еще кусочек моей картины мира Linux.

В заключение, подчеркну очевидное. Базовый механизм контроля доступа в Unix предусматривает предоставление разных прав доступа к файлу или каталогу только для трех (и не более трех!) категорий пользователей:

  • владелец каталога или файла,
  • группа-владелец каталога или файла (то есть, все ее члены),
  • все остальные пользователи.

Это довольно существенное ограничение. Так, предоставить двум разным группам разный доступ к каталогу или файлу и при этом отказать в доступе всем остальным не получится! А ведь сценарий, когда каталог и файлы в нем должны быть доступны для чтения группе A, для изменения - группе B, и должны быть недоступны всем остальным пользователям, совсем не сложен...

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

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