Файлы и "права доступа" к ним.
Поскольку Unix - система многопользовательская, в ней предусмотрен механизм ограничивающий доступ юзеров к файлам и директориям.
Естественно, "доступ" означает не только возможность читать или изменять содержимое отдельных файлов, но и возможность создавать файлы (директории), удалять их, запускать файлы (если они являются исполняемыми), менять им названия, а также менять все те атрибуты, которые и определяют "право доступа", то есть - "кто и что" может проделывать с данным файлом или директорией.
Прежде всего надо отметить, что правильнее говорить не о "правах юзера" по отношению к какому-нибудь файлу, а о "правах процесса" (выполняемой программы).
- Во-первых, если юзер и вносит какие-то изменения в файлы или директории, он это делает с помощью каких-то программ (редакторов, "коммандеров", системных утилит для копирования, удаления файлов и т.п.), которые в момент выполнения являются процессами.
- Во-вторых (что более важно), не все программы запускаются юзерами "вручную". Некоторые из них (демоны) запускаются при старте системы. Другие могут запускаться в определенные моменты времени (с помощью программы cron), или вызываться по мере необходимости для обслуживания запросов приходящих по сети (обычно их запускает программа-"диспетчер" inetd). Кроме того, существует ряд программ, которые для выполнения каких-то вспомогательных действий сами запускают другие программы (в этом случае говорят, что процесс-"родитель" запустил процесс-"потомок"). Понятно, что хотелось бы и этим программам (процессам) ограничить доступ к файлам.
- И наконец, в-третьих, в некоторых случаях очень полезно, чтобы программа, запущенная юзером, имела больше прав, чем обычно имеет этот юзер. Например, обычный юзер не может даже читать файл, в котором "спрятаны" пароли всех юзеров. В то же время, любой юзер должен иметь возможность поменять свой личный пароль, не обращаясь для этого к администратору. Но для этого ему надо иметь возможность записать что-то в файл паролей. Значит программа, которая это делает (passwd) в момент выполнения должна иметь права намного большие, чем юзер, который ее запускает.
- каждый процесс имеет идентификатор юзера (userID). Обычно он совпадает с userID'ом того юзера, который запустил этот процесс.
- процессы, которые запустились автоматически, тоже имеют userID, как будто их запустил реальный юзер. Чей именно userID получают эти программы обычно определяется теми программами, которые их стартуют (программа-загрузчик, cron, inetd и т.д.). В простейших случаях программы-"потомки" просто "наследуют" userID от программы-"родителя", но некоторые "родители" могут запускать программы с другим userID'ом (не совпадающим с собственным).
- некоторые программы в процессе выполнения могут поменять свой userID и, соответственно, получить права, которые сам юзер не имел. Естественно, для того, чтобы программа могла это сделать, администратор должен "разрешить" ей такое поведение (подробнее об этом будет сказано ниже). Кстати, изменение userID'а делается не только, когда нужно "расширить" права программы, но и наоборот - "сузить" до прав какого-нибудь конкретного юзера.
- если процесс может изменять свой userID, то различают "реальный userID" и "эффективный userID" (есть еще "сохраненный userID"). Реальный userID - это идентификатор юзера, который запустил процесс (или userID процесса-"родителя"). А эффективный - это новый userID, который задача получила во время выполнения.
- права на файл (или директорию) определяются по "эффективному userID" процесса. В простейшем случае, когда userID не меняется, "реальный" и "эффективный" userID'ы совпадают и можно говорить просто об userID'е процесса. Или даже просто о правах юзера (а не процесса) на файл.
Какие атрибуты файла определяют "право доступа".
Владелец файла и группа "допущенных".
Все юзеры для каждого файла (или директории) делятся на три категории
- владелец (или хозяин) этого файла
- группа "особо допущенных" к этому файлу
- все остальные.
Это означает, что можно установить три различных "допуска" (набора прав доступа) для каждого файла или директории. Один такой набор будет определять права юзера, который является владельцем файла, другой набор будет определять права для юзеров, которые входят в некую группу, но не являются владельцами и, наконец, третий набор устанавливает права для всех остальных юзеров, которые не входят в эту группу "особо допущенных" и не являются владельцем файла.
Следовательно, у каждого файла (директории) есть три атрибута, которые хранятся где-то в заголовке файла и регулируют доступ к нему. Конечно, атрибутов у файла не три, а больше. К атрибутам можно отнести имя файла, его размер, время создания и т.п. Но в данном случае нас интересуют только эти три.
Итак.
В заголовок файла записывается идентификатор юзера (userID), который считается его владельцем. Заметьте, что "хозяином" может быть только один определенный юзер.
Кроме того, в атрибуты записывается идентификатор группы (groupID), который и определяет ту группу "особо допущенных" о которой говорилось выше. Каждая такая группа (ее название, числовой идентификатор - groupID и состав) определяется администратором системы. То есть "рядовой" юзер, даже если он и является хозяином файла, не может произвольно составить список "близких друзей", которым он доверяет особые права в отношении к своему файлу. Он может только выбрать подходящую группу из имеющихся (и то, только если он сам входит в эту группу). Подробнее создании и изменении групп юзеров смотри в "Как поменять принадлежность юзера к группе (группам)?".
И, наконец, в атрибутах файла есть некий набор битов или "флажков", который и указывает - кто и что может проделать с этим файлом. Этот набор называется permissions, что можно перевести как "допуски" или "права на доступ".
Самое время, рассмотреть конкретный пример.
Если у вас уже есть под рукой какой-нибудь Unix, наберите команду
ls -l
(аналог команда dir в MS DOS)
и вы увидите несколько строчек типа
-rw-r--r-- 1 pascal users 4297 13 мар 21:45 file1 -rw-r--r-- 1 pascal users 1502 13 мар 22:09 file2 -rw-r--r-- 1 pascal users 5354 12 мар 20:11 filt3 \________/ \____/ \___/ \__/ \__________/ \___/ "права" владелец группа длина дата имя файла
В третьей колонке вы видите имя (login name) юзера - "хозяина" этих файлов (в данном случае это - pascal). В четвертой колонке - название группы, приписанной также к этим файлам (в данном случае - users). И, наконец, в самой первой колонке (набор знаков типа "r", "w" и "-") сами permissions для всех трех категорий пользователей.
Надо заметить, что в самом заголовке файла хранятся, не имена юзеров и групп, а их числовые номера, а "права", на самом деле, представляют собой не цепочку букв, а набор двоичных битов.
Просто команда ls изображает их в более "человеческом" виде.
Основные биты доступа (чтение/запись/выполнение)
Рассмотрим подробнее - что представляют собой "права доступа".
Еще раз вернемся к примеру. При распечатке содержимого директории (например, командой ls) каждая строчка имеет вид
-rw-r--r-- 1 pascal users 4297 13 мар 21:45 files1
причем нас интересует в данном случае только первая колонка.
Она состоит из десяти знаков. Однако, самый первый знак не имеет отношения к permissions, а обозначает "тип этого объекта". Поскольку, в директории кроме файлов могут находится поддиректории и, кроме того, в Юниксе, кроме обычных файлов существуют другие объекты ("линки", "очереди", "сокеты" и т.п.), которые также находятся в директориях и имеют атрибуты как и у обычных файлов. Так вот, первый символ как раз и показывает - что за объект мы видим, обычный файл (значок "-"), поддиректорию (значок "d") или еще какой-нибудь специфический Юниксовый объект ("l", "s", "p"...).
Остальные девять знаков на самом деле представляют собой три группы по три символа. Каждая такая группа определяет права для какой-либо из трех категорий юзеров
- первая группа - права "хозяина"
- вторая группа - права "группы особо допущенных"
- третья группа - права для "всех остальных"
Смысл отдельных битов в каждой такой группы "прав" одинаков для всех трех категорий пользователей, поэтому можно подробнее рассматривать любую такую группу, не уточняя - для какой категории юзеров она предназначена.
Однако, для файлов и директорий смысл этих битов немного отличается, поэтому их стоит рассмотреть отдельно.
Для файлов.
Первый бит, обозначается буквой "r" (read), и означает, что юзеру, подпадающему под соответствующую категорию, разрешается читать содержимое этого файла. То есть он может посмотреть содержимое файла, а также скопировать этот файл. Кстати, это не означает, что юзер сможет запустить его на выполнение (если это программа). Второй бит, обозначается буквой "w" (write) и разрешает писать в файл. То есть юзер сможет изменить содержимое файла (например, каким-нибудь редактором), дописать что-нибудь в конец или стереть все содержимое. Обратите внимание, этот бит еще не дает право удалить сам файл из директории или изменить ему название (это определяется правами на саму директорию), но дает возможность сделать этот файл пустым (нулевой длины) или скопировать в него содержимое другого файла (и тем самым "подменить" его). И, наконец, третий бит, обозначается буквой "x" (eXecute), позволяет запустить на выполнение этот файл, если он представляет собой программу или командный файл. Обратите внимание, что это также основной признак, по которому система догадывается о "запускаемости" этого файла. Часто начинающие пользователи составив какой-нибудь командный файл, забываю установить на него бит "исполнения" хотя бы для себя - владельца этого файла. В результате, при попытке запустить его, система сообщает, что "вы не имеете права" (выполнять этот файл). Естественно, что в данном случае причина не в том, что "злобный" администратор существенно "урезал" права этого юзера, а в том, что он сам забыл "наделить себя правом" (вполне законным).
Для директорий.
Первый бит ("r") разрешает читать оглавление этой директории, то есть список файлов и поддиректорий, находящихся в ней. Однако, этот бит еще не дает возможность зайти в эту директорию (командой cd) или получить доступ к содержимому, то есть читать/запускать/изменять файлы, даже если "права доступа" установленные на самих файлах это позволяют. Поэтому, само по себе "право чтения" директории практически бесполезно и этот бит, как правило ставиться только вместе с битом "x". Немного забегая вперед, рассмотрим сразу третий бит - "x". Для директорий он как раз означает, что юзер может получит доступ к "компонентам", то есть отдельным файлам и поддиректориям. Только при наличии это бита, система разрешит войти в эту директорию и выполнить какое-нибудь действие с файлом, если сами файлы ("права доступа" на них) это позволят. Кстати, обратите внимание, что если даже внутренние поддиректории имеют "нормальные" права для какой-то категории юзеров, а вышестоящая директория - нет (отсутствует бит "x"), то этим юзерам не удастся "занырнуть" в поддиректории, минуя вышестоящую. Система проверяет полный "путь" до конечной директории или файла (например, /usr/share/misc/fonts) и, если хотя бы один из компонентов этого пути не имеет соответствующего бита, то юзеру будет отказано в доступе. Наконец, бит "w", установленный на директории, позволяет изменять оглавление директории. То есть, разрешает создавать новые файлы (или копировать другие файлы в эту директорию), менять названия файлов и удалять файлы.
Обратите внимание на "разделение полномочий" между теми permissions, которые стоят на файле и теми, которые на директории.
Как уже говорилось, если права на директорию не позволяют юзеру удалить файл, находящийся в ней (нет бита "w") это не означает, что юзер не сможет "удалить содержимое" файла (например, "вытерев" все в нем редактором).
С другой стороны, если юзер имеет право менять содержимое директории, он сможет удалить или переименовать любой, находящийся в ней файл, даже если права на самом файле не позволяют ему не то что писать в файл, но и читать его.
(Правда, тут есть некоторые нюансы, смортри "Флаги")
И еще на что следует обратить внимание. Никакие из перечисленных здесь прав не имеют отношения к изменениям самих "атрибутов доступа", то есть - владельца файла, группы и permissions. Их изменение подчиняется другим законам, о которых будет сказано ниже (смотри "Как поменять...").
И последнее замечание. Все эти биты не имеют никакого эффекта для юзера root (и программ, которые во время выполнения поменяли свой "эффективный userID" на "рутовский"). То есть, он может делать с файлом или директорией все что хочет.
Правда, и здесь есть одно исключение. Поскольку бит "x" на файле является основным признаком "исполняемости" этого файла, даже root не сможет убедить систему, что файл является программой и его можно выполнять, пока не поставит в атрибутах этот бит.
Дополнительные биты доступа
Кроме рассмотренных выше битов (чтение,запись и "исполняемость"), которые устанавливаются раздельно по трем категориям юзеров, есть еще три бита доступа, которые можно отнести к файлу в целом, поскольку их действие не зависит от того какой юзер (в смысле из какой категории) пытается обратиться к файлу. Да и смысл этих битов состоит не в ограничении доступа к файлу (директории). Они изменяют некоторые свойства файлов или директорий.
Бит suid.
Бит suid. Расшифровывается как Set user ID, переводится как "установить идентификатор юзера". Поскольку подходящего русскоязычного термина не существует, его обычно называют "суидный" бит, а файлы, на которых он установлен - "суидными".
Смысл его состоит в том, что если он установлен на файле, который является программой, то при выполнении эта программа автоматически меняет "эффективный userID" на идентификатор того юзера, который является владельцем этого файла. То есть, не зависимо от того - кто запускает эту программу, она при выполнении имеет права хозяина этого файла.
Обычно это делается для того, чтобы юзер мог выполнить действия, которые требуют привилегий root'а (например, поменять свой пароль). Естественно, что для этого владельцем такой программы должен быть юзер root.
Понятно, что такая программа является "потенциально опасной". В "нормальном" случае она не позволит обычному юзеру сделать то, что выходит за пределы его полномочий (например, программа passwd разрешит юзеру изменить только собственный пароль, но не пароли других юзеров). Но, даже незначительная ошибка в такой программе может привести к тому, что "злоумышленник" сможет заставит ее выполнить еще какие-нибудь действия, не предусмотренные автором программы. Кстати, большинство известных способов "взлома" системы заключаются не в том, чтобы узнать пароль root'а, а как раз в том, чтобы заставить какую-нибудь из "суидных" программ выполнять действия необходимые "взломщику".
Вообще говоря, использование "суидных" программ (когда они нужны и для чего) - достаточно обширная тема выходящая за рамки разговора о permissions. Замечу только, что это не единственный путь сменить "эффективный userID". Это можно сделать из самой программы, вызвав специальную системную функцию, но для этого программы должна уже иметь права root'а. То есть, ее должен запустить юзер root, или она должна быть "суидной", как сказано выше.
Возвращаясь к разговору о "правах доступа", надо сказать, что у такого файла permissions выглядят как **s****** (если еще и установлен бит x для владельца файла) или как **S****** (если бит x не установлен). Однако, ставить suid бит на неисполняемые файлы обычно не имеет смысла (по крайней мере в FreeBSD). Хотя, мне попадались программы, которые проверяли этот бит даже для текстовых файлов.
Также, это бит не несет никакого смысла если его поставить на директорию, хотя никто не запрещает это сделать.
Бит sgid
Бит sgid. Расшифровывается как Set group ID, переводится как "установить идентификатор группы".
Эго смысл аналогичен смыслу предыдущего бита . Только меняется не идентификатор юзера, а идентификатор группы. То есть, при выполнении этого файла он имеет такие права как будто его запустил кто-то из группы, которая приписана к этому файлу.
Permissions такого файла выглядят как *****s*** (если установлен бит x для группы) или *****S** (если соответствующего бита x нет). Также как и в предыдущем случае, бит sgid для неисполняемых файлов никакого смысла не имеет.
А вот что касается бита sgid на директории...
Для FreeBSD (и других ветвей BSD) этот бит, опять же, не оказывает никакого действия. Но в некоторых других Юниксах он означает, что, когда файлы создаются в такой директории, в их атрибутах проставляется группа та же, что и у директории. Другими словами, файлы, создаваемые в такой директории "наследуют" группу от директории.
Бит sticky
Бит sticky. Никак не расшифровывается, переводится как "липкий". :-)
Выглядит в permissions как ********t (если вместе с битом x для "всех остальных") или ********T (если соответствующего бита x нет).
Для директорий его смысл заключается в том, что удалить файл из такой директории (или переименовать) может только владелец файла. Напомню, что в обычном случае (без такого бита) возможность удалять файлы (как и создавать) определяется правом записи (бит w) на директории. То есть, если какой-либо юзер принадлежит к категории, для которой разрешена запись в директорию, он может удалить в ней любой файл, независимо от атрибутов (владельца, группы, permissions) самого файла.
Применяют этот бит, обычно, на директориях, которые являются "публичными" (например, /tmp). Такие директории имеют права доступа, позволяющие всем юзерам создавать там свои файлы и удалять их. Однако, было бы неправильно, что любой другой юзер мог по ошибке или "из вредности" удалять файлы, к которым он не имеет никакого отношения. Для того, чтобы предотвратить возможность удаления файла "посторонним" юзером, как раз и служит sticky бит.
Этот бит может ставиться также на исполняемые файлы. В этом случае он означает, что файл, даже после завершения работы, должен оставаться в памяти (конечно, не в ОЗУ, а в swap'е).
Как говорится в документации, это полезно для "часто используемых исполняемых файлов общего пользования". К сожалению, реальных примеров таких файлов я не нашел. Возможно, практически он никем не используется.
"Странные" сочетания битов доступа.
Для файлов
Обычно права на файл (например, для "всех остальных") устанавливаются
- --- никаких прав (нельзя ни читать, ни изменять содержимое)
- r-- только чтение
- rw- и чтение и запись (изменение) файла.
Если файл является "исполняемым", то права могут выглядеть
- --- опять же, никаких прав (читать нельзя, запускать нельзя)
- r-x можно запустить файл-задачу на выполнение
- rwx можно не только запустить, но и что-нибудь в нем поменять
Остальные сочетания (например -w- или --x) кажутся бессмысленными.
Однако, это не всегда так. Рассмотрим подробнее.
Права -w- означают, что юзер из соответствующей категории не может прочитать этот файл, но может в него писать.
Конечно, для "исполняемого" файла это сочетание бессмыслено (запустить как задачу нельзя, но "покорежить" что-нибудь внутри - пожалуйста).
Однако, если этот файл представляет собой что-то вроде "лога" или почтового ящика, то такие permissions могут иметь смысл. Например, вы допускаете, что другие юзеры (или какие-нибудь программы-автоматы) будут дописывать сюда свои "донесения", но не хотите, чтобы те же юзеры могли посмотреть - что туда понаписали другие.
Правда, при этом никто не мешает тем же юзерам просто не читая, записать в этот файл что-нибудь, "похоронив" при этом все старое содержимое файла. Или даже скопировать туда файл нулевой длины (или /dev/null), при этом, естественно, вообще никакого "содержимого" у вашего файла не станет. Однако, чтобы предотвратить такую ситуацию можно поставить на тот же файл флаг "только дозапись". Он не помешает вам читать свой файл, а другим юзерам дописывать в него что-нибудь. Правда, не даст даже вам стирать из файла все лишнее или удалить файл, пока вы не "снимите" флаг.
Теперь посмотрим на исполняемые файлы.
Права --x на самом деле вполне законная комбинация. Она означает, что запустить эту задачу можно (и получить от нее какой-то результат). Нельзя только скопировать этот файл себе или "залезть" в него отладчиком.
Поэтому, такие permissions даже полезны, если вы хотите сохранить свою "интеллектуальную собственность". Комбинация -wx, пожалуй, смысла не имеет (как и просто -w- на исполняемом файле). Вы просто даете возможность изменить содержимое, причем "вслепую" (поскольку посмотреть это содержимое нельзя). Результатом может быть только порча вашего файла.
Также можно отнести к бессмысленным и права r-- на исполняемом файле. Если вы хотите таким способом "подразнить" кого-то (вот есть такой файл, можно посмотреть - как он внутри устроен, а выполнить нельзя), то не обольщайтесь. Другой юзер спокойно может скопировать этот файл себе, при этом он становится полноправным владельцем полученной копии. После этого он поставит на свою копию такие права, какие ему захочется и, все таки, запустит его.
Для директорий
Для директорий обычно права доступа устанавливаются
- --- никаких прав
- r-x нормальные права для "посещения" директории, но без права изменения (создавать/удалять/переименовывать файлы)
- rwx полный доступ (делай там что хочешь)
Имеет ли смысл устанавливать какие-либо другие сочетания?
Ну, во-первых, если отсутствует бит доступа --x (доступ к содержимому), то любая комбинация из двух остальных ничего полезного не даст.
Комбинация r-- даст возможность получить список файлов в этой директории, например командой ls, и не более того. Причем посмотреть можно будет только имена файлов, а такие подробности, как владелец/группа/permissions будут недоступны. В такую директорию нельзя "войти" командой cd. И, даже если внутри нее поддиректории имеют вполне нормальные права доступа (например r-x), попасть в них будет невозможно.
Комбинации -w- и rw- имеют еще меньше смысла. Все равно, изменить что-нибудь в директории с такими правами доступа не удастся.
А вот сочетания --x и -wx на самом деле вполне осмысленны.
Таким способом можно сделать "полусекретную" директорию. "Секретность" ее заключается в том, что никто посторонний не сможет посмотреть - что за файлы и директории в ней находятся. Но, если вы своим друзьям сообщите - как называется файл находящийся там, они смогут без проблем его взять оттуда или посмотреть его прямо на месте.
Аналогично и с поддиректориями. Если вы не хотите, чтобы кто-нибудь просто "бродя" по вашим директориям наткнулся на директорию с "секретным" содержанием (например sex-pictures :-), но, в тоже время, не против чтобы некоторые близкие друзья могли туда "захаживать" и знакомится с новыми пополнениями, "спрячьте" свои "приватные" директории в директорию (например private) с доступом --x. Тогда ваши друзья смогут попасть в нужную поддиректорию, указав полный путь (cd private/sex-pictures), а случайные посетители ее просто не найдут (если, конечно, этот посетитель не root).
Конечно, "секретность" в этом случае будет не полной, поскольку, если посторонний каким-то образом узнает правильное название файла или поддиректории, то получит те же возможности, что и "близкие друзья".
Права -wx отличаются от предыдущего тем, что "доверенным лицам" можно писать в эту директорию. Они могут скопировать туда файл, удалить (если, конечно, знают его точное название) и т.п. Опять же, посторонний сможет разве что записать туда файл, который вы не просили. Удалить там что-нибудь или переименовать, не зная названий файлов (и поддиректорий), он не сможет.
И, напоследок, еще один нестандартный случай, который касается распределения прав по категориям юзеров. Обычный порядок назначения прав различным категориям на файл или директорию
- владелец - полные права (rwx)
- группе доверенных лиц - тоже самое, но без права изменения (r-x)
- всем остальным - никаких прав (---)
Вообще-то, обычно права назначаются даже еще проще. Поскольку, группы составляет root и рядовые юзеры, как правило, не выбирают себе соседей по группе, то их файлы и директории имеют одинаковые "допуски" для группы и "всех остальных". Например, для "несекретных" файлов (директорий) - rwxr-xr-x, а те, которые владелец хочет оградить от посторонних rwx------.
Но в данном случае речь не об этом. Что будет, если "всем остальным" дать доступ, пусть и ограниченный, а для группы "особо приближенных" - наоборот убрать (выглядеть это будет примерно так - rwx---r-x)?
Тогда группа, приписанная к файлу, превратится из группы "особо допущенных" в группу "особо нелюбимых". То есть некий "черный список", куда можно занести (естественно, сделать это может только root) всех тех, кто не пользуется доверием. Обратите внимание, что система, проверяя права конкретного юзера по отношению к файлу, сначала проверяет - не является ли он владельцем, потом - не входит ли он в группу, а уже после этого относит его ко "всем остальным". Так что, даже если "все остальные" имеют допуск к файлу, но юзер имел несчастье попасть в соответствующую группу, к нему будут применяться права доступа группы.
Я не берусь судить - можно ли извлечь из этого какую-то пользу. Тем более, что составить "черный список" может только root. И, кроме того, не забудьте, что количество групп, в которые может входить юзер, ограничено, поэтому не стоит без особой надобность "плодить" дополнительные списки. Но, во всяком случае, возможность поступить таким образом есть.
Флаги.
Кроме уже рассмотренных атрибутов (владелец, группа, "права доступа"), существует еще один атрибут, который ограничивает возможные действия с файлом - "набор флагов".
Кстати, по умолчанию команда ls флаги не показывает (и большинство "коммандеров"/"файлменеджеров" - тоже). Для того, чтобы она их показала, надо указать ключ -lo.
С помощью флагов можно запретить изменять содержимое файла, его название или и то и другое.
Флаги являются более "сильнодействующим средством" чем permissions. Они действуют одинаково для всех юзеров, не разделяя их на категории. Более того, их действие не может игнорировать и владелец файла и даже root. Единственное отличие владельца и root'а от прочих пользователей в том, что они могут убрать флаги с файла (и то не всегда) и только потом уже делать то, что им хочется.
Рассмотрим их подробнее.
Флаги делятся на две группы "юзерские" флаги и "суперюзерские". Разница в том, что "юзерские" может поставить и убрать как root, так и владелец файла, а ставить/убирать "суперюзерские" может только root.
На самом деле, "снятие" флагов - вопрос более сложный. Он зависит от того, в каком "режиме безопасности" находится система. Но об этом немного позднее.
По своему назначению флаги делятся на
-
append - разрешается только "дописывать" файл (естественно, файл должен также иметь permssion "w"). Без этого флага, если юзеру из соответствующей категории разрешается писать в файл, он может как добавить что-либо к содержимому файла, так и "убавить", то есть стереть часть содержимого. При установленном флаге append, любой юзер (даже root) сможет только добавить что-нибудь в конец файла, но не сможет ничего изменить в уже имеющемся содержимом.
Если этот флаг поставить на директорию, то в ней можно создавать файлы (или копировать туда файлы из других директорий), но нельзя удалять или менять их названия. Естественно, на сами файлы действие флага не распространяется. - nounlink - файл (или директорию) нельзя удалить или переименовать, даже если права, установленные на директории (в которой находится файл) это позволяют. В то же время, этот флаг не запрещает менять содержимое файла (если, конечно, permissions это позволяют).
- immutable или change - "ничего нельзя" :-). То есть, файл (директорию) нельзя ни удалить, ни переименовать, ни изменить содержимое. Опять же, если это флаг стоит на директории, то на файлы (в ней содержащиеся) его действие не распространяется. То есть, вы не сможете ни добавить, ни убрать файл в директории, но менять содержимое самих файлов это флаг не запретит.
Как уже говорилось, эти три флага существуют в двух вариантах - "юзерские" и "суперюзерские". То есть, на самом деле их шесть
- три "юзерских" - uappend, uunlink и uimmutable
- и три "суперюзерских" - sappend, sunlink и simmutable.
Вообще-то, существует еще два "непарных" флага. Это флаги
- archived (архивный файл) - это файл "суперюзерский", то есть его может поставить только root, а аналогичного "юзерского" не существует;
- nodump (файл не надо "дампировать") - а это "юзерский" флаг, его может поставить не только root, но и владелец файла.
Эти флаги проверяются только некоторыми конкретными программами. Флаг nodump сообщает программе dump, что этот файл не надо сохранять в архиве. (Подробнее о программе dump вы можете прочитать в соответствующем man'уале - man dump).
Кем и для чего проверяется флаг archived, я, к сожалению, не знаю.
И, наконец, несколько слов о "режиме безопасности".
Дело в том, что в FreeBSD система может находится на разных "уровнях безопасности". Существует четыре уровня
- -1 - система безопасности выключена
- 0 - система безопасности включена, но никаких ограничений нет
- 1 - "режим безопасности", установлен ряд ограничений на работу с внешними устройствами и операции с флагами
- 2 - "повышенная безопасность", еще больше ограничений, чем на уровне 1.
Подробнее о том, в чем заключаются ограничения и как меняются "уровни безопасности", можно прочитать в man init (отмечу только, что "по умолчанию" система стартует с уровнем -1, то есть "безопасность" выключена).
Для нас в данный момент важно только, что на уровне 1 и 2, даже суперюзеру (root'у) запрещено снимать флаги sappend и simmutable.
Естественно, это делается не для того, чтобы "защитить" систему от собственного администратора. Он все равно, при желании, сможет убрать эти флаги (и удалить/изменить соответствующие файлы). Правда, для этого ему придется перезагрузить систему, причем с консоли.
А вот "взломщик", проникший в систему, даже если каким-то образом и получит root'овские права, не сможет изменить "жизненно важные файлы" (если, конечно, они защищены флагом simmutable) или "почистить логи" (если они защищены флагом sappend), чтобы "замести следы" своего пребывания в системе.
С какими правами файл "рождается"
На самом деле вопрос поставлен не совсем корректно.
Дело в том, что новый файл появляется в результате работы какой-либо программы. В то же время, в Юниксе существуют системные функции, которые позволяют менять владельца файла, группу и права доступа. Естественно, программа порождающая файл может вызывать эти функции и таким образом создать файл с любыми атрибутами.
Поэтому, правильный ответ - "это зависит от программы, которая этот файл создает".
Однако, большинство программ этими функциями не пользуются, поэтому можно сказать, что "в большинстве случаев" атрибуты создаваемых файлов все таки подчиняются нескольким простым правилам.
Итак. Какие же у только что созданного файла будут владелец, группа и права доступа?
Владелец
Владелец файла определяется "эффективным userID'ом" программы, которая его создает. Это означает, что в большинстве случаев владельцем файла будет тот юзер, который его создал (естественно, с помощью какой-нибудь программы). Если же программа "суидная", то есть во время выполнения имеет права того юзера, которой является владельцем этой программы, то, соответственно, все файлы, порожденные этой программой будут принадлежать хозяину программы, а не юзеру, который ее запустил.
Кстати, если даже в программе используются системные функции, которые меняют владельца файла, они сработают только в том случае, если ее "эффективный userID" будет userID root'а. То есть, если ее запустит юзер root или она является "суидной" и ее владелец root.
Другими словами, какие бы программы не использовал рядовой юзер (если, конечно, они не "суидные") он может создать файлы владельцем которых будет только он. "Подарить" файл кому-нибудь другому обычный юзер не может.
Группа
Группа создаваемого файла в FreeBSD определяется немного необычно. Она всегда "наследуется" от директории в которой этот файл создается. То есть файл будет иметь ту же группу, которую имеет директория.
Обратите внимание, что юзер, создающий файл, может даже не являться членом этой группы. Это, конечно, не очень хорошо с точки зрения безопасности системы. Дело в том, что если юзер создаст исполняемый файл и потом поставит на него бит sgid, то этот файл при выполнении получит права группы, в которую сам юзер не входит и, возможно, получит доступ к таким файлам, куда его в обычной ситуации "не подпускают".
Правда, в FreeBSD такая ситуация предусмотрена и система просто не даст юзеру поставить бит sgid на файл, если юзер не является членом группы, которая "приписана" к файлу.
В других разновидностях Юникса группа файлу, обычно, присваивается та, которая является "первичной" группой юзера, создающего файл (то есть, та, которая записана в его учетной карточке). А для того, чтобы группа как и в FreeBSD "наследовалась" от директории, на самой директории должен стоять бит sgid.
Права доступа
Права доступа, которые будут у "свежеиспеченного" файла определяются параметром umask. Он задает - какие биты прав доступа НЕ НАДО выставлять в permissions.
Если это параметр равен нулю, то у всех создаваемых файлов права доступа будут одинаковые для всех категорий и выглядеть как rw-rw-rw. Директории (созданные, например, командой mkdir) будут иметь права доступа rwxrwxrwx. Такие же права доступа получатся и у исполняемых файлов, которые создают различные трансляторы (они, естественно, ставят биты "исполняемости" на результат своей работы).
Параметр umask можно посмотреть или изменить "одноименной" командой umask. Команда umask без аргументов просто показывает текущее значение этого параметра. А для того, чтобы поменять его, надо этой команде в качестве аргумента указать число, которое система "развернет" в соответствующие биты.
Если каждую группу из трех бит (что соответствует отдельной категории в правах доступа) рассматривать как двоичное число, то "свернув" их поотдельности в десятичные цифры мы получим число из трех цифр, которое и отражает значение всех битов в permissions. Точнее, получается не десятичное, а восьмеричное представление прав доступа, но, если вы мало знакомы с восьмеричной системой счисления, то можете просто рассматривать это число как три отдельных десятичных цифры.
Еще раз напоминаю, что биты в umask отмечают - какие биты прав доступа НЕ надо ставить при создании файла. То есть, если вы хотите, чтобы у категории "все остальные" вообще не было никаких прав, а "группе допущенных" не ставился бит разрешающий запись, то umask должна выглядеть как 027.
В FreeBSD по умолчанию в командных файлах, которые выполняются при входе в систему, у всех юзеров (включая root'а) вставлена команда, которая задает umask равной 022. То есть отменяются только биты разрешения записи для группы и "всех остальных". Если вас это не устраивает, вы можете изменить аргумент в соответствующем файле (обычно это файл .login в домашней директории юзера) или поменять параметр umask в любой момент "вручную".
Как изменяются права доступа при копировании и перемещении файла.
Этот вопрос на самом деле более сложный, чем может показаться.
Дело в том, что ответ на него зависит от многих условий
- кто копирует (перемещает) файлы, root или обычный юзер
- какие программы и с какими ключами при этом используются
- копируется файл "на пустое место" или там уже существует файл с таким именем
Тем не менее, попробуем найти несколько общих правил, определяющих - какие права доступа могут получится в результат.
Во-первых, при копировании (например, командой cp) создается новый файл, а при перемещении (например, командой mv) меняется только место расположения файла (и, возможно, имя).
Поэтому, если "рядовой юзер" копирует файл, то действуют все те же правила, что и при создании файла. То есть, владельцем копии становится юзер, который ее создал, группа "наследуется" от директории, а сами права доступа определяются параметром umask.
Строго говоря, если копирование делает root, то эти правила действуют и для него (то есть, владельцем полученной копии будет root, группа будет взята от директории, а права выставятся в соответствии с umask). Однако, root может изменить поведение команды cp. У этой команды есть ключ (-p - сохранять permissions) который означает, что надо сохранить все атрибуты (владельца, группу и permissions) при копировании.
Обычный же юзер, даже используя ключ -p не сможет сохранить владельца и группу, но получит permissions такие же как у оригинального файла. К тому же биты suid и sgid при этом также "сбрасываются".
Существует еще одна ситуация, когда при копировании сохраняются все атрибуты доступа. Это происходит, когда в "месте назначения" файл с таким именем уже существует. Собственно, в этом случае файл не создается, а только замещается его содержимое. Поэтому, даже если эту операцию проделает обычный юзер (естественно, для этого надо, чтобы ему было разрешено писать в существующий файл), все атрибуты, в том числе владелец и группа сохранятся. Правда, биты suid и sgid все равно "сбросятся".
А вот при перемещении файла все атрибуты сохраняются (даже "опасные" биты suid и sgid). Однако, не забудьте, что для того, чтобы обычный юзер смог переместить чужой файл, он должен иметь право записи и в ту директорию, куда файл переносится и в ту, откуда он переносится (поскольку, там запись о файле должна быть удалена). Такие ситуации в нормальной системе, как правило, не встречаются.
Как поменять...
Владельца и группу.
Во-первых, надо отметить - кто может поменять для файла (директории) владельца и группу.
Безусловно, это может сделать root.
Поменять владельца файла не может никто, кроме root'а.
А вот группу для файла может, также, поменять сам владелец файла, но только в том случае, если он сам является членом этой (новой) группы.
Для изменения владельца файла служит команда chown ("change owner"). С ее помощью можно заодно заменить и группу, хотя для изменения этого атрибута есть специальная команда chgrp ("change group").
Подробно об этих командах можно прочитать в соответствующих man'уалах (man chown и man chgrp). Поэтому, рассмотрим только их краткое описание.
Команда chown
Команда chown выглядит очень просто
chown "новый владелец" "имя файла"
если же вы хотите поменять не только владелец, но и группу, то
chown "новый владелец":"новая группа" "имя файла"
Кстати, никто не мешает указать в команде "старого" владельца, тогда изменится только группа.
Ну и, конечно, если вы хотите заменить владельца (группу) сразу на нескольких файлах, вместо имени файла можно указать подходящий "шаблон", например "*" (выполнить операцию для всех файлов в текущей директории).
Если же вы хотите, чтобы аналогичная операция была проделана не только в текущей директории, но и во всех "нижележащих" поддиректориях, вам поможет ключ -R (recursively).
Например, команда
chown -R vasia:users *
заменит владельца на vasia, а группу на users для всех файлов и поддиректорий, находящихся в текущей директории и "ниже", то есть в самих поддиректориях.
Команда chgrp
Команда chgrp очень похожа не предыдущую, толко в качестве первого аргумента ей нужно указать название новой группы для файла (или файлов).
chgrp "новая группа" "имя файла"
Естественно, все что было сказано о команде chown относительно выполнения ее над несколькими файлами и о ключе -R, также относится и к команде chgrp.
Права доступа (permissions)
Права доступа, кроме root'а может поменять также и владелец этого файла (директории). Кстати, обратите внимание, что хозяин файла может нечаянно установить такие биты доступа, что сам не сможет пользоваться этим файлом по назначению. Правда, никто не помешает ему же и исправить собственную ошибку.
Итак, для изменения прав доступа (permissions) служит команда chmod ("change mode"). В целом эта команда выглядит как и предыдущие (которые меняют владельца и группу)
chmod "что сделать" "имя файла"
Но, в отличии от предыдущих команд, второй аргумент ("что сделать") имеет несколько более сложный вид.
В нем можно выделить три части
"категория юзеров" | "операция" | "биты прав доступа" |
---|---|---|
u (user) владелец g (group) группа o (other) все остальные a (all) все три категории |
- + = |
r w x s или t |
Как понятно из таблицы, первой задается категория юзеров (владелец, группа или "все остальные"). Причем, можно поставить сразу несколько букв, обозначив тем самым сразу несколько категорий. Например, go будет означать, что права меняются сразу и для группы и для "всех остальных". Если надо изменить права сразу для трех категорий, можно написать три буквы - ugo или одну букву a (все три категории).
Следом указывается "операция" (добавить права или наоборот - убрать). И, наконец, после "операции" один или несколько битов доступа, которые требуется изменить. Значение этих битов подробно рассматривалось выше, поэтому здесь не будем на них останавливаться.
Некоторых пояснений, наверное, требует "операция". Как можно догадаться, знаки "-" и "+" означают "убрать" или "поставить" соответствующие права.
А знак "=" означает сразу и то и другое. Дело в том, что если вы укажете, например o+x это будет означать - добавить бит x для категории "остальные", но никак не повлияет на биты r и w для этой же категории. А указав действие как o=rx, вы тем самым скажете системе - "установить биты r и x, и убрать бит w, если он там был".
Бит s имеет разный смысл (suid или sgid) в зависимости от того, в какой части permissions он находится. Поэтому, если вы хотите поставить именно suid бит, то "что сделать" должно выглядеть как u+s, а если вам нужен sgid, то - g+s. Sticky бит ставится командой chmod a+t ... .
Как видите, синтаксис этой команды достаточно гибкий (хотя и несколько сложноватый). Кроме того, второй аргумент ("что сделать") может состоять из нескольких "действий" перечисленных через запятую.
Например, можно задать команду
chmod a=rx,u+w mydir
это будет означать - "для всех категорий права r-x, а для владельца еще и w (право записи)".
Кроме того, команда chmod (точнее - ее первый аргумент) имеет еще одну форму.
Поскольку, все биты доступа это действительно двоичные биты из одной ячейки, "продвинутый" пользователь может указать сразу число (в восьмеричном виде) которое должно получится после изменения прав.
Восьмеричное представление выбрано потому, что при переводе в него двоичного числа, каждая группа из трех бит "сворачивается" в одну цифру. Таким образом, вам надо просто указать три цифры, каждая из которых описывает отдельную категорию юзеров (точнее - права для этой категории). Например, permissions rwxr-xr-x можно представить в восьмеричном виде как 755. И, следовательно, такие права могут быть выставлены командой
chmod 755 myfile
Что касается выполнения этой операций над несколькими файлами или "рекурсивного" обхода всех поддиректорий, здесь все так же, как для команд chown, chgrp. В качестве имени файла может быть задан "шаблон", а для обхода всех поддиректорий используйте ключ -R.
И, конечно, я советую все таки прочитать man chmod.
Флаги.
Кто может менять флаги (и какие) подробно описывалось в разделе о флагах.
Команда, которая их ставит/убирает - chflags ("change flags"). Формат ее достаточно простой
chflags "флаги" "имя файла"
Аргумент "флаги" - это название флага или нескольких флагов через запятую. Названия флагов описаны в разделе о флагах. Кроме того, эта команда понимает и сокращенные названия.
- sappend - sappnd
- uappend - uappnd
- sunlink - sunlnk
- uunlink - uunlnk
- simmutable - schange или schg
- uimmutable - uchange или uchg
- arcived - arch
- (флаг nodump не сокращается :-)
Для того, чтобы убрать флаг, надо указать его название с префиксом no - nosappnd, nosunlnk, noschg и т.п.
Исключение составляет флаг nodump. Чтобы его убрать нужно сказать не nonodump, а просто dump. :-)
Естественно, как и предыдущие команды chflags может применяться к нескольким файлам и "рекурсивно" обходить поддиректории (ключ тот же - -R).
Что делать если этого не хватает?
Рассмотренная система ограничения доступа к файлам и директориям, конечно, имеет свои недостатки.
Проблема первая
Первый круг проблем связан с тем, что система делит всех юзеров только на три категории. Причем только вторая категория представляет собой "четко очерченную" группу юзеров.
Первая категория состоит только из одного юзера - владельца, и ее права не так-то просто "размазать" на группу юзеров.
Третья же категория состоит вообще из всех юзеров, зарегистрированных на данной машине, то есть границ не имеет.
Если возникнет задача - наделить разными правами (по отношению к конкретному файлу) разные группы юзеров, причем это именно группы, а не "отдельный юзер" и не "все зарегистрированные юзеры", то возникнут проблемы даже у root'а.
Проблема вторая
Второй круг проблем связан с тем, что составлять группы может только root. Поэтому, если владелец файла захочет по своему усмотрению распределить права на свой файл различным юзерам, то оказывается, что он практически не имеет для этого никаких механизмов.
Он может "закрыть" файл от всех или, наоборот, "открыть" его всем. Наличие такой категории как "группа допущенных" не очень-то помогает, поскольку поменять состав этой группы "рядовой юзер" не сможет.
Итак. Что же делать, если "нужно что-то большее"?
Ну, первый круг проблем, на самом деле - не проблема :-).
Если не сочинять нереальные ситуации (например, одна группа только читает, вторая - только выполняет, третья - только пишет, четвертая - только пишет и выполняет и т.п.), то оказывается, что в реальных ситуациях может возникнуть необходимость в одной дополнительной группе (кроме владельца, обычной группы и "всех остальных").
Например, "все остальные" не должны иметь никакого доступа к файлу, но при этом должна быть группа, которым файл доступен на чтение и группа, которым файл доступен также для записи.
Другой разновидностью задачи может быть исполняемый файл, который целая группа может модифицировать (то есть иметь право на запись), другая группа может исполнять, но не изменять и, опять же, "все остальные" не должны иметь никаких прав на этот файл.
Как же добавить к файлу еще одну группу-категорию?
Есть по крайней мере два решения.
Решение первое
Первое состоит в том, чтобы "размазать" права владельца на группу. Обычно, владелец отличается тем, что имеет право записи (модификации файла). Соответственно, "группе допущенных" можно дать права только для чтения (и/или исполнения) файла, а "всем остальным" вообще не давать никаких прав.
Так вот. Если для изменения файла можно использовать только одну определенную программу, то надо сделать эту программу (или ее копию) "суидной", то есть такой, которая при выполнении меняет свой "эффективный userID" на ID владельца. Естественно, владельцем такой программы должен быть тот же юзер, что и владелец файла, который мы хотим модифицировать, а права на запуск этого файла надо дать только той группе, которой мы хотим дать права на модификацию. Кстати, "владелец" файла может быть и фиктивным юзером, то есть зарегистрированным в системе только для этой цели и не соответствовать никакому реальному человеку.
Таким образом, нужно создать две разные группы, в первую (writers) внести только тех юзеров, которые имеют право изменять файл, а во вторую (readers) тех, кто может только читать файл (ну и всех из writers, пожалуй, тоже).
Сам файл должен быть открыт для записи только владельцу (это может быть кто-нибудь из группы writers или вообще фиктивный юзер), для чтения - "группе допущенных" и это должна быть группа readers, и, наконец, для "всех остальных" можно смело убирать любые права. Ну, а та программа, которая предназначена для модификации, должна иметь того же владельца, что и исходный файл, группу - writers, быть "суидной" и права на запуск должны быть только у группы и владельца (хотя, если он фиктивный, то ему не обязательно).
Решение второе
Второе решение заключается в том, что файл надо "спрятать" в директорию, с соответствующими правами доступа.
Пусть у нас так же существуют две группы readers и writers, причем все члены группы writers входят также и в readers (но не наоборот :-).
Тогда директория, в которую прячется файл должна иметь группу readers (кто владелец в общем-то - не важно). Причем для группы доступ в директорию открыт, а для "всех остальных" закрыт. Это означает, что в директорию смогут войти только "читатели" и "писатели" (поскольку они входят в группу "читателей").
А сам файл должен иметь группу writers, причем этой группе файл должен быть открыт для записи. А право "только чтение" можно дать категории "все остальные", все равно это будут только те, кто входит в readers, но не попал в writers. Посторонние просто не попадут в эту директорию и даже не увидят, что такой файл существует.
Что можно сказать о втором круге проблем (невозможность самим владельцам файлов определять круг допущенных к файлу)?
Здесь все несколько хуже. Проблема даже не в том, что рядовой юзер не может сам менять состав групп. Эту то проблему можно решить достаточно просто. Можно было бы для каждого юзера завести отдельную группу (кстати, программа для добавления юзера adduser, так и предлагает делать) и написать специальную программу (естественно, "суидную"), которая исполнялась бы с правами root'а и позволяла юзеру менять состав группы, но не любой, а только его личной.
Однако, не торопитесь это делать. Проблема в том, что отдельный юзер может быть полноправным членом только 16-и групп. И если у юзера vasia окажется слишком много друзей, которые захотят включить его в свои группы, то реально он сможет "дружить" только с шестнадцатью, чьи группы будут первыми в списке групп.
Кроме того, это не решает проблему, если владелец файла захочет дать разные права нескольким разным группам.
Так что же делать?
Во-первых, если такое желание юзера не каприз, а вытекает из потребности организации (например, два отдела могут "подглядывать" в документы друг друга, но не менять их, при этом все остальные не должны даже смотреть), то имеет смысл обратиться к администратору. Пусть он создаст новые группы и определит их состав.
Если же у юзера просто ежедневно меняются симпатии и антипатии к другим юзерам этой же машины, то тут помочь практически нечем. Если уж надо "спрятать" файл от кого-то из членов группы, придется прятать от всей группы. Можно еще воспользоваться "полусекретными" директориями, как описано в "Странные" сочетания битов доступа..
И напоследок несколько слов о механизме, который решает все описанные проблемы, но, к сожалению, отсутствует во многих Юниксах (в том числе и в FreeBSD).
ACL
Речь идет о "Списках управления доступом" (Access Control Lists).
Например, в AIX (клон Юникса фирмы IBM) владелец файла может для любого файла составить такой список (acl). По умолчанию, у файла такой список отсутствует. Но, при желании, владелец файла может с помощью специальной утилиты (acledit) "включить" файлу acl и занести туда отдельных юзеров и/или группы, для которых он хочет задать особые права на файл. Естественно, он может как "расширить" права отдельным юзерам (например, дать право записи), так и "сузить" (то есть, наоборот - убрать все права доступа для отдельных юзеров).
Права задаются так же, как для отдельной категории юзеров в обычных файлах, то есть - тройка битов rwx.
При наличии acl'я система определяет права конкретного юзера по отношению к файлу в следующем порядке
- если юзер есть в списке, то права берутся оттуда
- если юзера нет в списке, но есть группа, членом которой он является, то применяются права для этой группы
- и, наконец, если ни юзера, ни группы в списке нет, то проверяются обычные permissions для этого файла.
Итак. Если описанные выше решения проблем вас никак не удовлетворяют, то могу дать еще один совет - смените Юникс, на такой, который поддерживает acl. Или ждите, пока эта поддержка появится в вашем любимом клоне Юникса. :-)