10.5. Аутентификация пользователей
10.5. Аутентификация пользователей
Программы, у которых установлен бит SUID, не должны запускаться кем попало. Например, программа su, прежде чем менять идентификатор пользователя, заставляет его ввести пароль. Это называется аутентификацией — программа проверяет, получил ли пользователь права суперпользователя.
Администраторам высоконадежных систем недостаточно, чтобы пользователи просто вводили пароли. У пользователей есть вредная привычка записывать свои пароли на бумажке, приклеенной к монитору, или выбирать пароли, в которых закодирован день рождения, имя любимой собаки, жены и т.п. Все это облегчает задачу злоумышленникам, пытающимся незаконно проникнуть в систему.
Во многих организациях требуется использовать "одноразовые" пароли, генерируемые специальными электронными карточками, которые пользователи хранят при себе. Одни и тот же пароль не может встретиться дважды, а прежде чем получить пароль, требуется ввести личный код. Следовательно, для взлома системы хакеру требуется раздобыть электронную карточку и узнать соответствующий личный код. В сверхсекретных учреждениях используются устройства сканирования сетчатки глаза или другие биометрические приборы.
При написании аутентификационной программы важно позволить системному администратору использовать тот механизм аутентификации, который он считает приемлемым. В Linux этой цели служат подключаемые модули аутентификации (РАМ, pluggable authentication modules). Рассмотрим простейшее приложение (листинг 10.4).
Листинг 10.4. (pam.c) Пример использования модулей РАМ
#include <security/pam_appl.h>
#include <security/pam_misc.h>
#include <stdio.h>
int main() {
pam_handle_t* pamh;
struct pam_conv pamc;
/* Указание диалоговой функции. */
pamc.conv = &misc_conv;
pamc.eppdata_ptr = NULL;
/* Начало сеанса аутентификации. */
pam_start("su", getenv("USER"), &pamc, &pamh);
/* Аутентификация пользователя. */
if (pam_authenticate(pamh, 0) != PAM_SUCCESS)
fprintf(stderr, "Authentication failed! ");
else
fprintf(stderr, "Authentication OK. ");
/* Конец сеанса. */
pam_end(pamh, 0);
return 0;
}
Чтобы скомпилировать эту программу, необходимо подключить к ней две библиотеки: libpam и libpam_misс:
% gcc -о para pam.c -lpam -lpam_misc
Сначала программа создает объект диалога, который используется библиотекой РАМ, когда ей требуется запросить у пользователя данные. Функция misc_conv(), адрес которой записывается в объект, — это стандартная диалоговая функция, осуществляющая терминальный ввод-вывод. Можно написать собственную функцию, отображающую всплывающее окно, использующую голосовой ввод-вывод или реализующую другие способы общения с пользователем.
Затем вызывается функция pam_start(), которая инициализирует библиотеку РАМ. Первый аргумент функции — это имя сервиса. Оно должно уникальным образом идентифицировать приложение. Программа не будет работать, пока системный администратор не настроит систему на использование указанного сервиса. В данном случае задействуется сервис su, при котором программа аутентифицирует пользователей так же, как это делает команда su. В реальных программах так поступать не следует. Выберите реальное имя сервиса и создайте сценарий инсталляции, который позволит системному администратору правильно настраивать механизм аутентификации.
Второй аргумент функции — это имя пользователя, которого требуется аутентифицировать. В данном примере имя пользователя берется из переменной среды USER (обычно это имя соответствует эффективному идентификатору текущего процесса, но так бывает не всегда). В большинстве реальных программ в данном месте выдается запрос на ввод имени. Третьим аргументом является ссылка на объект диалога. В четвертом аргументе указывается переменная, в которую функция pam_start() запишет дескриптор сеанса. Этот дескриптор должен передаваться всем последующим функциям библиотеки РАМ.
Далее в программе вызывается функция pam_authenticate(). Во втором ее аргументе указываются различные флаги. Значение 0 означает стандартные установки. Возвращаемое значение функции говорит о том. как прошла аутентификация. В конце программы вызывается функция pam_end(), которая удаляет выделенные ранее структуры данных.
Предположим, что пользователь должен ввести пароль "password". Если это будет сделано, получим следующее:
% ./pam
Password: password
Authentication OK.
Будучи запущенной в терминальном окне, программа не покажет введенный пароль, чтобы кто-нибудь посторонний не смог его подглядеть.
Вот что произойдет, если в систему попробует вломиться хакер:
% ./pam
Password: badguess
Authentication failed!
Полное описание работы модулей аутентификации приведено в каталоге /usr/doc/pam.