Остальные значения могут быть определены как расширения стандарта; ваша функция диалога должна игнорировать их, если они не записываются для последующей их обработки, и должна просто передавать им NULL
-отклик. РАМ (вернее, модуль РАМ, производящий запрос) отвечает за освобождение каждой строки resp
, не содержащей NULL
, а также массивов структур pam_message
и pam_response
.
Член appdate_ptr
, который задается в структуре диалога, передается функции диалога. Это будет полезно в тех случаях, когда вы используете одну функцию диалога в нескольких контекстах, или если вы хотите передать контекстную информацию функции диалога. Эта информация может включать спецификацию дисплея X, внутреннюю структуру данных, в которой хранятся описатели файлов для соединения, или любые другие данные, которые могут быть полезны для вашего приложения. В любом случае, эта информация не интерпретируется библиотекой РАМ.
Функция диалога должна вернуть PAM_CONVERR
, если во время выполнения возникнет ошибка, в противном случае — PAM_SUCCESS
.
28.2.2. Действия РАМ
РАМ не хранит никакой статической информации в библиотеке между вызовами, а хранит всю постоянную информацию с использованием непрозрачной структуры данных, передаваемой всем вызовам. Этот непрозрачный объект, pam_handle
, управляется РАМ, однако хранится в вызывающем приложении. Он инициализируется с помощью функции pam_start()
и освобождается функцией pam_end()
.
#include <security/pam_appl.h>
int pam_start (const char * service_name, const char * user,
const struct pam_conv * pam_conversation,
pam_handle_t ** pamh);
int pam_end(pam_handle_t * pamh, int pam_status);
Аргумент service_name
должен представлять уникальное имя для вашего приложения. Это уникальное имя позволяет администратору системы конфигурировать защиту применительно к вашему приложению; два приложения, использующие одно и то же имя service name
, разделяют одну и ту же конфигурацию. Аргумент user
представляет имя аутентифицированного пользователя. Аргумент pam_conversation
представляет структуру диалога, о которой мы уже говорили. Аргумент pamh
представляет непрозрачный объект, который следит за внутренним состоянием. Функция pam_start()
показана в строке 97 кода.
Функция pam_end()
, показанная в строке 137 кода pamexample.с
, очищает каждое; состояние, хранящееся в непрозрачном объекте pamh
, и информирует модули, на которые он ссылается, о конечном состоянии действий. Если приложение успешно использовало РАМ, оно должно присвоить pam_status
значение PAM_SUCCESS
; в противном случае оно должно предоставить самую последнюю ошибку, возвращенную РАМ.
Бывают ситуации, когда модули РАМ могут использовать дополнительную информацию при принятии решения об аутентификации пользователя; эту информацию предоставляет система, а не пользователь. Кроме того, в некоторых случаях модули РАМ должны посылать приложению предупреждение об изменениях. Механизмом передачи этой дополнительной информации является элемент РАМ. Значение элемента задается с помощью функции pam_set_item()
, а его запрос осуществляется функцией pam_get_item()
.
#include <security/pam_appl.h>
extern int pam_set_item(pam_handle_t * pamh, int item_type,
const void * item);
extern int pam_get_item(const pam_handle_t * pamh, int item_type,
const void ** item);
Аргумент item_type
определяет идентичность и семантику элемента РАМ item
. Мы рассмотрим только наиболее часто используемые значения item_type
.
PAM_TTY |
item представляет указатель на строку, содержащую имя устройства TTY, с которым связан запрос аутентификации. Это может быть tty59 для первого последовательного порта в стандартной системе или pts/0 для первого псевдотерминала, или tty1 для первой виртуальной консоли. |
PAM_USER |
Функция pam_start() автоматически присваивает это значение аргументу user , переданному функции pam_start() . Важно отметить, что это имя может изменяться! Если вашему приложению нужно имя пользователя, то оно должно проверять значение посредством функции pam_get_item() после попадания в стек РАМ и перед производством изменения имени в другом коде. |
PAM_RUSER |
Для сетевых протоколов (например, rsh и ssh) этот элемент должен применяться для передачи имени пользователя удаленной системы любым модулям РАМ, которые используют его. Благодаря этому администратор системы сможет определить, разрешена ли аутентификация типа rhost . |
PAM_RHOST |
Подобно PAM_RUSER , PAM_RHOST необходимо задавать для сетевых протоколов, в которых имя удаленного хоста может использоваться как компонент аутентификации, или при управлении учетной записью. |
Все остальные функции принимают по два аргумента: непрозрачный объект pamh
и целое число, которое может быть либо нулевым, либо флагом РАМ_SILENT
. Флаг PAM_SILENT
требует, чтобы каркас и модули РАМ не генерировали информационных сообщений, однако при этом будет производиться запрос на ввод пароля. В обычных приложениях флаг РАМ_SILENT
не задается.
Функция pam_authenticate()
, показанная в строке 100 кода pamexample.с
, выполняет все, что было сконфигурировано администратором системы в данном приложении (что определяется аргументом service_name
функции pam_start()
) для аутентификации пользователя. Сюда может быть включено следующее: запрос на ввод одного или нескольких паролей; проверка, что пользователь с текущим именем пользователя (что определяется по элементу РАМ РАМ_USER
, а не по текущему uid; модули РАМ не рассматривают uid, поскольку приложения, вызывающие РАМ, обычно явным образом не выполняются после аутентификации пользователя) является текущим пользователем консоли; проверка, что текущий пользователь (снова по имени пользователя) недавно прошел аутентификацию для эквивалентного уровня обслуживания; проверка элементов РАМ PAM_RUSER и PAM_RHOST в отношении локальных таблиц эквивалентных удаленных пользователей и хостов (например, то, что выполняет демон rsh
), или что-либо подобное. (Обратите внимание, что в большинстве систем задействована система "теневых паролей", при котором с целью защиты пароля только процессы с полномочиями root могут проверять пароли произвольных пользователей; процесс, который не выполняется как root, может проверять только собственный пароль uid. Это единственное исключение из правила, когда модули РАМ принимают во внимание uid.)