3. Основы PAM

3.1. Подсистемы и примитивы

API для PAM предоставляет шесть различных примитивов для аутентификации, сгруппированных в четыре подсистемы, каждая из которых описывается ниже.

auth

Аутентификация. Эта подсистема, собственно говоря, реализует аутентификацию аппликанта и выяснение полномочий учётной записи. Она предоставляет два примитива:

  • Функция pam_authenticate(3) аутентифицирует аппликанта, обычно запрашивая аутентификационный ключ и сравнивая его со значением, хранящимся в базе данных или получаемым от сервера аутентификации.

  • Функция pam_setcred(3) устанавливает полномочия учётной записи, такие, как идентификатор пользователя, членство в группах и ограничения на использование ресурсов.

account

Управление учётной записью. Эта подсистема обрабатывает вопросы доступности учетной записи, не связанные с аутентификацией, такие, как ограничения в доступе на основе времени суток или загрузки сервера. Он предоставляет единственный примитив:

  • Функция pam_acct_mgmt(3) проверяет, доступна ли запрашиваемая учётная запись.

session

Управление сеансом. Эта подсистема отрабатывает задачи, связанные с установлением и закрытием сеанса, такие, как учет входов пользователей. Она предоставляет два примитива:

  • Функция pam_open_session(3) выполняет действия, связанные с установлением сеанса: добавление записей в базы данных utmp и wtmp, запуск агента SSH и так далее.

  • Функция pam_close_session(3) выполняет действия, связанные с закрытием сеанса: добавление записей в базы данных utmp и wtmp, завершение работы агента SSH и так далее.

password

Управление паролем. Эта подсистема используется для изменения ключа аутентификации, связанного с учетной записью, по причине истечения его срока действия или желания пользователя изменить его. Она предоставляет единственный примитив:

  • Функция pam_chauthtok(3) изменяет ключ аутентификации, опционально проверяя, что он труден для подбора, не использовался ранее и так далее.

3.2. Модули

Модули являются центральной концепцией в PAM; в конце концов, им соответствует буква ''M'' в сокращении ''PAM''. Модуль PAM представляет собой самодостаточный кусок программного кода, который реализует примитивы одной или большего количества подсистем одного конкретного механизма; к возможным механизмам для подсистемы аутентификации, к примеру, относятся базы данных паролей UNIX®, системы NIS, LDAP или Radius.

3.2.1. Именование модулей

Во FreeBSD каждый механизм реализуется в отдельном модуле с именем pam_mechanism.so (например, pam_unix.so для механизма UNIX.) В других реализациях иногда отдельные модули используются для разных подсистем, и в их имя включается, кроме названия механизма, и имя подсистемы. К примеру, в Solaris™ имеется модуль pam_dial_auth.so.1, который часто используется для аутентификации пользователей, работающих по коммутируемым каналам связи.

3.2.2. Версии модулей

Изначальная реализация PAM во FreeBSD, которая была основана на Linux-PAM, не использовала номера версий для модулей PAM. Это будет приводить к проблемам при работе унаследованных приложений, которые могут быть скомпонованы со старыми версиями системных библиотек, так как способа подгрузить соответствующую версию требуемых модулей нет.

OpenPAM, с другой стороны, ищет модули, которые имеют тот же самый номер версии, что и библиотека PAM (на данный момент 2), и использует модуль без версии, только если модуль с известной версией не был загружен. Поэтому для старых приложений могут предоставляться старые модули, при этом новые (или заново построенные) приложения будут использовать все возможности последних версий модулей.

Хотя модули PAM в Solaris имеют номер версии, по-настоящему номер версии в них не отслеживается, потому что номер является частью имени и должен включаться в конфигурацию.

3.3. Цепочки и политики

Когда сервер инициирует PAM-транзакцию, библиотека PAM пытается загрузить политику для службы, указанной при вызове функции pam_start(3). Политика определяет, как должны обрабатываться запросы на аутентификацию, и задаётся в конфигурационном файле. Это составляет другую основополагающую концепцию PAM: возможность администратору настраивать политику безопасности системы (в самом широком её понимании) простым редактированием текстового файла.

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

Понимание смысла управляющего флага необходимо для понимания конфигурационных файлов PAM. Существуют четыре различных управляющих флага:

binding

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

Этот управляющий флаг был добавлен компанией Sun в Solaris 9 (SunOS™ 5.9), и поддерживается в OpenPAM.

required

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

requisite

Если модуль возвращает положительный ответ, выполняется оставшаяся часть цепочки, запрос удовлетворяется, если никакой другой модуль не отработает отрицательно. Если же модуль отрабатывает отрицательно, то отработка цепочки немедленно прекращается, а запрос отвергается.

sufficient

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

Так как семантика этого флага может оказаться запутанной, особенно при его использовании с последним модулем в цепочке, рекомендуется вместо него использовать управляющий флаг binding, если реализация его поддерживает.

optional

Модуль отрабатывается, но результат выполнения игнорируется. Если все модули в цепочке помечены как optional, то удовлетворяться будут все запросы.

Когда сервер вызывает один из шести PAM-примитивов, PAM запрашивает цепочку подсистемы, к которой принадлежит примитив, и запускает каждый модуль, перечисленный в цепочке в порядке их перечисления, пока список не будет исчерпан либо не будет определено, что дальнейшей обработки не нужно (по причине достижение модуля, вернувшего положительный ответ при условии binding или sufficient, либо отрицательный с условием requisite). Запрос подтверждается, если только был вызван по крайней мере один модуль, и все неопциональные модули вернули положительный ответ.

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

3.4. Транзакции

Жизненный цикл типичной PAM-транзакции описан ниже. Заметьте, что в случае, если любой из перечисленных шагов оканчивается неудачно, сервер должен выдать клиенту соответствующее сообщение об ошибке и прервать транзакцию.

  1. Если это необходимо, сервер получает полномочия арбитратора через независимый от PAM механизм—чаще всего по факту запуска пользователем root или с установленным setuid-битом root.

  2. Сервер вызывает функцию pam_start(3) для инициализации библиотеки PAM и задания имени сервиса и целевой учётной записи, а также регистрации подходящего способа общения.

  3. Сервер получает различную информацию, относящуюся к транзакции (такую, как имя пользователя аппликанта и имя хоста, на котором запущен клиент), и отправляет её в PAM при помощи функции pam_set_item(3).

  4. Сервер вызывает функцию pam_authenticate(3) для аутентификации аппликанта.

  5. Сервер вызывает функцию pam_acct_mgmt(3) для проверки того, что запрошенная учётная запись доступна и корректна. Если пароль верен, но его срок истёк, pam_acct_mgmt(3) возвратит результат PAM_NEW_AUTHTOK_REQD, а не PAM_SUCCESS.

  6. Если на предыдущем шаге был получен результат PAM_NEW_AUTHTOK_REQD, то сервер вызывает функцию pam_chauthtok(3) для того, чтобы вынудить клиента изменить ключ аутентификации для запрошенной учётной записи.

  7. Теперь, когда аппликант полностью аутентифицирован, сервер вызывает функцию pam_setcred(3) для получения полномочий запрошенной учётной записи. Сделать это возможно, потому что он работает как арбитратор, и оставляет за собой полномочия арбитратора.

  8. После получения необходимых полномочий, сервер вызывает функцию pam_open_session(3) для установления сеанса.

  9. Теперь сервер выполняет тот сервис, который затребовал клиент—например, предоставляет аппликанту оболочку.

  10. После того, как сервер закончил обслуживание клиента, он вызывает функцию pam_close_session(3) для закрытия сеанса.

  11. Наконец, сервер вызывает функцию pam_end(3) для оповещения библиотеки PAM о том, что работа с ней завершена и какие-либо выделенные в течение сеанса ресурсы можно освободить.

Этот, и другие документы, могут быть скачаны с ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.

По вопросам, связанным с FreeBSD, прочитайте документацию прежде чем писать в <questions@FreeBSD.org>.
По вопросам, связанным с этой документацией, пишите <doc@FreeBSD.org>.
По вопросам, связанным с русским переводом документации, пишите в рассылку <frdp@FreeBSD.org.ua>.
Информация по подписке на эту рассылку находится на сайте проекта перевода.