Про аутентификацию пользователей написано масса статей и для оной процедуры изготовлено сотни скриптов. Однако, в большинстве своем все эти методы рассчитаны на хранение логинов/паролей в отдельном файле, или на аутентификацию пользователей с помошью апачесвкого .htaccess. Здесь же речь пойдет про аутентификацию реальных пользователей unix сервера через веб-интерфейс. Есть довольно много методов для решения этой задачи, но используют в основном два способа: шифруют пароль, введенный в веб-форме и сравнивают его с паролем в файле passwd или shadow, используют pop3 аутентификацию. Первый метод весьма скользкий, ибо его реализация требует прав суперпользователя (root) для открытия файла зашифрованных паролей (shadow), и, как следствие, является дырой в безопасности сервера. Он реализуется путем исполнения cgi-скрипта с правами root (suid). Вообщем, алгоритм простой: взять пару логин/пароль с web-формы; зашифровать пароль тем же алгоритмом, что и на сервере; открыть файл shadow для сравнения пароля, там хранящегося с полученным с web-формы. Ежели результат сравнения положителен, аутентификация прошла успешна и увы в противном случае. Не забыть позакрывать все файлы. Все вообщем-то довольно просто. Открыли файл, прочитали в буфер, нашли нужную нам строчку, закриптовали пароль, сравнили с тем, что в файле и по делам ихним воздаем аутентифицирующемуся юзеру. В unix системах шифрование происходит в одну сторону - к зашифрованному паролю добаваляется хорошая порция избыточной информации (salt - соли), и выдернуть пароль назад оттуда не представляется возможным. Так что, "взлом" паролей возможен лишь методом подбора оного. Ну, а если пользователь легальный и пароль действительный, то зашифруя его, мы сразу же успешно проходим аутентификацию. За что мне нравится perl, так это ненужность изобретать велосипеды. Проверка пароля сводится к вызову стандартной системной функции crypt($text,$salt). Действует она так: в качестве параметров подается пароль в "чистом" виде и зашифрованный, на выходе она должна выдать тот же зашифрованный пароль. Если этого не произошло, значит пароль в виде простого текста был неправильный. В общем вся процедура выглядит все где-то так: #!/usr/bin/suidperl # # читаем форму ......... &check_passwd; sub check_passwd { my $shadow = "/etc/shadow"; # ниже две строчки = переданные из формы пароль/логин $plaintext = $form{'password'}; $username = $form{'login'}; # пытаемся открыть файл зашифрованных паролей (на нормальной системе # он доступен только для чтения только root-ом.) # и заодно попытаемся его залочить. open (shadow, "<$shadow") or die "internal system error: $!"; flock (shadow, 2) or die "internal lock error: $!"; @shadows=; flock shadow, 8; # закроем shadow close shadow; foreach $line(@shadows) { chomp($line); ($currentuser, $currentpass, $restofline) = split /:/, $line, 3; if ($currentuser eq $username) # Выдергиваем зашифрованный пароль из shadow $saltedpass = $currentpass; # Проверяем его стандартной функцией crypt if ( crypt ($plaintext, $saltedpass) eq $saltedpass) { print "authentification for $username success!n"; } else { print "authentification for $username failure!n"; } } } } Файлу, содержащему сей "шедевр" программистского искусства следует в целях безопасности установить атрибуты: Владелец - root, Взведенный бит установки id пользователя при исполнении режим доступа r-sr-xr-x. Грубо говоря, в восьмеричном отображении оно будет выглядеть как 104555 В этом suid-e и кроется опасность, - если кто-то умудрится всунуть кусок своего кода в вашу программу, то сможет получить доступ к вашей системе. (Для неверующих - прочитайте что-нибудь про ramen - он еще и не то делает/делал). А посему сей метод, как небезопасный, лучше не использовать. Лучше взять готовую perl-библиотеку: net. 2. pop3 Аутентификация. Простой и безопасный метод проверки подлинности пользователя. Берется библиотека net::pop3 и стандартными методами пытаемся влогиниться в почтовый ящик. Если нам это удалось, то логин/пароль верны, и обратный результат в ином случае. Модуль net::pop3 дает пользователю создать объект и 14 методов к нему. Все методы изучать нет смысла - они довольно-таки неподробно описаны в документации к модулю, нас более интересует метод login($user,$passwd). Он возвращает значение undef в случае неудачной аутентификации, или, в случае удачного входа в почтовый ящик, количество писем в оном, или строку "0e0", если писем нет , т.е. "пишут". Порядок работы с ним следующий: use net::pop3; &parse_form # Читаем из формы переданные пароль/логин # Создаем объект $pop = net::pop3->new('popserver') || print "cannot create connectionn"; # пробуем влогиниться # в $res будет возвращен результат логина $res = $pop->login($form{'login'},$form{'password'}); if ($res == undef) { # неудача print "incorrect username or password!n"; } else { # влогинились # делаем, что надо # # следующий код нарисован для того, чтобы хоть что-то # делалось. if ($res eq "0e0") { # писем нет print "you have $res messages in mailbox.n"; } else { # письма есть print "you have $res messages in mailbox.n"; } } #закрываем соединение. $pop->quit(); Намного проще и безопаснее, чем лезть в святая святых безопасности unix систем- файл shadow. Да и не нужно просить сисадмина сервера установить на ваш скрипт setuid bit, хотя заранее можно сказать, что любой нормальный сисадмин вам в этом откажет, и будет на все сто прав. А библиотека net есть практически на любом web-сервере, где есть доступ к perl интерпретатору.
|