PAM + pam_ldap + Active Directory
Решил научить vsftpd авторизации пользователей из Windows-домена.
Для этого на dc завел тестовую пользователя ftp1 и группу LAS_ftp, членам которой будет разрешена авторизация на моем FTP-сервере.
(Конечно же, пользователь ftp1 является членом группы LAS_ftp.)
Работать все должно было по следующей схеме:
- vsftpd настраиваем на авторизацию с помощю PAM;
- в PAM для этого приложения говорим использовать pam_ldap;
- для проверки принадлежности пользователя к группе будем использовать модуль pam_require (он у нас правда flagged для x86);
- для создания домашних директорий для этих “виртуальных” пользователей будем использовать модуль pam_mkhomedir;
Вот мой конфиг PAM (приведу вместе с комментами):
LAS ~ # cat /etc/pam.d/vsftpd #%PAM-1.0 # auth - Аутентификация. Эта подсистема, реализует аутентификацию аппликанта и # выяснение полномочий учётной записи. Она предоставляет два примитива: # # Функция pam_authenticate(3) аутентифицирует аппликанта, обычно запрашивая # аутентификационный ключ и сравнивая его со значением, хранящимся в базе # данных или получаемым от сервера аутентификации. # # Функция pam_setcred(3) устанавливает полномочия учётной записи, такие, как # идентификатор пользователя, членство в группах и ограничения на # использование ресурсов. auth required pam_ldap.so # account - Управление учётной записью. Эта подсистема обрабатывает вопросы # доступности учетной записи, не связанные с аутентификацией, такие, # как ограничения в доступе на основе времени суток или загрузки # сервера. Он предоставляет единственный примитив: # # Функция pam_acct_mgmt(3) проверяет, доступна ли запрашиваемая учётная # запись. account required pam_ldap.so # Разрешение на вход только пользователям, входящим в группу LAS_ftp #account required pam_require.so no_case @LAS_ftp # password - Управление паролем. Эта подсистема используется для изменения # ключа аутентификации, связанного с учетной записью, по причине # истечения его срока действия или желания пользователя изменить # его. Она предоставляет единственный примитив: # # Функция pam_chauthtok(3) изменяет ключ аутентификации, опционально # проверяя, что он труден для подбора, не использовался ранее и так далее. # (Обойдутся без смены пароля!) # session - Управление сеансом. Эта подсистема отрабатывает задачи, связанные # с установлением и закрытием сеанса, такие, как учет входов # пользователей. Она предоставляет два примитива: # # Функция pam_open_session(3) выполняет действия, связанные с установлением # сеанса: добавление записей в базы данных utmp и wtmp, запуск агента SSH и # так далее. # # Функция pam_close_session(3) выполняет действия, связанные с закрытием # сеанса: добавление записей в базы данных utmp и wtmp, завершение работы # агента SSH и так далее. # Автоматическое создание домашней директории для новых пользователей session required /lib/security/pam_mkhomedir.so skel=/home/xdomain.local/default.skel umask=0700
Не получилось, настойчиво ругался, что не может авторизовать =(
Nov 2 14:22:21 LAS vsftpd[16378]: [ftp1] FAIL LOGIN: Client "10.10.1.5"
Долго пытался понять, в чем именно ошибка, перечитал немало форумов и мануалов… Решил написать свое маленькое приложение, использующее PAM, чтоб однозначно понять, где именно происходит сбой в процессе авторизации:
#include <security/pam_appl.h> #include <security/pam_misc.h> #include <pwd.h> #include <sys/types.h> #include <stdio.h> #define MY_CONFIG "vsftpd" #define MY_USER "ftp1" static struct pam_conv conv = { misc_conv, NULL }; main( ) { pam_handle_t *pamh; int result; if ((result = pam_start(MY_CONFIG, MY_USER, &conv, &pamh)) != PAM_SUCCESS) { fprintf(stderr, "start failed: %d\n", result); } else if ((result = pam_authenticate(pamh, 0)) != PAM_SUCCESS) { fprintf(stderr, "authenticate failed: %d\n", result); } else if ((result = pam_acct_mgmt(pamh, 0)) != PAM_SUCCESS) { fprintf(stderr, "acct_mgmt failed: %d\n", result); } /* else if ((result = pam_open_session(pamh, 0)) != PAM_SUCCESS) { fprintf(stderr, "open session failed: %d\n", result); } else if ((result = pam_close_session(pamh, 0)) != PAM_SUCCESS) { fprintf(stderr, "close session failed: %d\n", result); } */ else if ((result = pam_end(pamh, result)) != PAM_SUCCESS) { fprintf(stderr, "end failed: %d\n", result); } else { fprintf(stderr,"Success authenticate!\n"); }; }
Здесь закомментированы функции начала и окончания сессии пользователя, потому отработают тока модули из PAM-подсистем auth и account.
В конфиге PAM для vsftpd закомментирован вызов pam_require, потому на принадлежность группе пока пользователя не проверяем.
1) Компилим приложение (gcc ./chkpam.c -lpam -lpam_misc -o chkpam
), запускаем, вводим пароль – все хорошо, аутентификация пройдена! (при неправильном пароле – аутентификация будет провалена, из чего я предпологаю, что pam_ldap отрабатывает нормально)
LAS ~ # ./chkpam ... Password: ... Success authenticate!
2) Раскомментируем вызов pam_require (в /etc/pam.d/vsftpd) и заново запустим наше приложение – все плохо (((
PAM у меня собран с debug, так что, вот что он нам говорит:
LAS ~ # ./chkpam ... [pam_handlers.c:_pam_init_handlers(342)] _pam_init_handlers called [pam_dispatch.c:_pam_dispatch_aux(106)] passing control to module... [pam_item.c:pam_get_user(280)] called. [pam_data.c:pam_get_data(123)] called [pam_data.c:_pam_locate_data(46)] called [pam_data.c:pam_set_data(70)] called [pam_data.c:_pam_locate_data(46)] called [pam_item.c:pam_get_item(179)] called. [pam_item.c:pam_get_item(179)] called. [misc_conv.c:misc_conv(279)] allocating empty response structure array. [misc_conv.c:misc_conv(288)] entering conversation function. [misc_conv.c:read_string(136)] called with echo='OFF', prompt='Password: '. Password: [misc_conv.c:read_string(203)] we got some user input [pam_item.c:pam_set_item(31)] called [pam_item.c:pam_get_item(179)] called. [pam_dispatch.c:_pam_dispatch_aux(114)] module returned: Success [pam_dispatch.c:_pam_dispatch_aux(198)] use_cached_chain=0 action=-1 cached_retval=0 retval=0 [pam_item.c:pam_set_item(31)] called [pam_item.c:pam_set_item(31)] called [pam_delay.c:_pam_await_timer(90)] waiting?... [pam_delay.c:_pam_compute_delay(76)] random number: base=0 -> ans=0 [pam_delay.c:_pam_reset_timer(27)] setting pamh->fail_delay.set to FALSE [pam_delay.c:_pam_await_timer(126)] waiting done [pam_auth.c:pam_authenticate(39)] pam_authenticate exit [pam_account.c:pam_acct_mgmt(11)] called [pam_handlers.c:_pam_init_handlers(342)] _pam_init_handlers called [pam_dispatch.c:_pam_dispatch_aux(106)] passing control to module... [pam_item.c:pam_get_item(179)] called. [pam_data.c:pam_get_data(123)] called [pam_data.c:_pam_locate_data(46)] called [pam_item.c:pam_get_user(280)] called. [pam_data.c:pam_get_data(123)] called [pam_data.c:_pam_locate_data(46)] called [pam_dispatch.c:_pam_dispatch_aux(114)] module returned: Success [pam_dispatch.c:_pam_dispatch_aux(198)] use_cached_chain=0 action=-1 cached_retval=0 retval=0 [pam_dispatch.c:_pam_dispatch_aux(106)] passing control to module... [pam_item.c:pam_get_user(280)] called. [pam_dispatch.c:_pam_dispatch_aux(114)] module returned: Authentication failure [pam_dispatch.c:_pam_dispatch_aux(198)] use_cached_chain=0 action=-3 cached_retval=7 retval=7 acct_mgmt failed: 7
ну да бог с ним, с этим flagged модулем, комментируем его обратно и идем дальше!
2) Раскомментируем функции начала и окончания сессии для нашего пользователя, скомпилим и заново запустим наше приложение – все снова плохо (((
LAS ~ # ./chkpam ... Password: [misc_conv.c:read_string(203)] we got some user input [pam_item.c:pam_set_item(31)] called [pam_item.c:pam_get_item(179)] called. [pam_dispatch.c:_pam_dispatch_aux(114)] module returned: Success [pam_dispatch.c:_pam_dispatch_aux(198)] use_cached_chain=0 action=-1 cached_retval=0 retval=0 [pam_item.c:pam_set_item(31)] called [pam_item.c:pam_set_item(31)] called [pam_delay.c:_pam_await_timer(90)] waiting?... [pam_delay.c:_pam_compute_delay(76)] random number: base=0 -> ans=0 [pam_delay.c:_pam_reset_timer(27)] setting pamh->fail_delay.set to FALSE [pam_delay.c:_pam_await_timer(126)] waiting done [pam_auth.c:pam_authenticate(39)] pam_authenticate exit [pam_account.c:pam_acct_mgmt(11)] called [pam_handlers.c:_pam_init_handlers(342)] _pam_init_handlers called [pam_dispatch.c:_pam_dispatch_aux(106)] passing control to module... [pam_item.c:pam_get_item(179)] called. [pam_data.c:pam_get_data(123)] called [pam_data.c:_pam_locate_data(46)] called [pam_item.c:pam_get_user(280)] called. [pam_data.c:pam_get_data(123)] called [pam_data.c:_pam_locate_data(46)] called [pam_dispatch.c:_pam_dispatch_aux(114)] module returned: Success [pam_dispatch.c:_pam_dispatch_aux(198)] use_cached_chain=0 action=-1 cached_retval=0 retval=0 [pam_session.c:pam_open_session(15)] called [pam_handlers.c:_pam_init_handlers(342)] _pam_init_handlers called [pam_dispatch.c:_pam_dispatch_aux(106)] passing control to module... [pam_item.c:pam_get_item(179)] called. [pam_item.c:pam_get_item(196)] returning user=ftp1 [pam_modutil_getpwnam.c:pam_modutil_getpwnam(112)] pwd structure took 1052 bytes or so of memory [pam_mkhomedir.c:pam_sm_open_session(219)] couldn't identify user ftp1 [pam_dispatch.c:_pam_dispatch_aux(114)] module returned: Insufficient credentials to access authentication data [pam_dispatch.c:_pam_dispatch_aux(198)] use_cached_chain=0 action=-3 cached_retval=8 retval=8 open session failed: 8
хм... ну ладно с flagged pam_require, но ведь pam_mkhomedir собирается в базовом (стабильном) пакете pam, что с ним может быть не так?
Конечно же я комментировал лишнее и вызывал модуль pam_mkhomedir с опциями по умолчанию… (стандартный umask и путь до skel) не помогло – результат был абсолютно идентичным!
Люди, помогите чем модежете, уж больно хочеться разобраться где затык?!!
- Для комментирования войдите или зарегистрируйтесь
/
Рано тебя в глухие дебри занесло.
Думается мне, конерь проблемы практически на поверхности.
Система (на которой стоит FTP-сервер) какой механизм авторизации использует?
FTP-пользователи относительно системы скорее всего вирутальные!
Какой может быть домашний каталог (создаваемый как бы не стандартными системными инструментами) у вирутального (не существующего в системе) пользователя?!?
Как у тебя приземляется FTP-сервер (с виртуальными пользователями) для доступа к файловой системе (ограничивается для реальных системных пользователей)?
:wq
--
Live free or die
Anarchist
PAM
конешно виртуальные
FTP дает доступ виртуальным пользователям к локальным папкам и файлоам от имени урезанного в правах пользователя, pam_mkhomedir используется только для создания им стартового каталога.
Примеров использования этого модуля для vsfpd с "витруальными" пользователями полно в сети, вот один из них:
http://www.propheta.ru/2008/03/vsftpd-ldap.html
Весьма вероятно, что vsftpd более гибко работает с PAM, чем моя програмулина =) сейчас еще раз поковыряю vsftpd.conf на предмет локального (ограниченного в правах доступа) пользователя (при закомментированном pam_require).
хм, действительно в конфиге я
хм, действительно в конфиге я забыл поставить опцию virtual_use_local_privs=YES, однако, ее добавление также не помогло =(
Все попытки залогиниться тщетны...
Вот мой конфиг vsftpd:
Я вот тока nss_ldap не ставил, как в указанном мною примере, потому как его использование я встретил тока у этого автора... (а разлчных примеров конфигрурирования vsftpd я повидал более нескольких дестков...) Вот терь думаю, что может зря этого не сделал.
.
Одну опечатку обнаружили :)
Несколько десятков примеров конфигурирования подходящих для втоей задачи???
nss_ldap
является необходимым и органическим дополнением кpam_ldap
. До того, что (в нормальном случае, а не в цитированном тобой примере) они используют один и тот же конфигурационный файл.А ещё заслуживает рассмотрения вопрос структуры дерева LDAP и набора атрибутов пользователя в оном дереве.
:wq
--
Live free or die
/
С практической точки зрения к подобным примерам необходимо относится с изрядной долей осторожности.
Сужу по личному опыту на примере задачи перевода системной авторизации на использование базы пользователей в OpenLDAP.
:wq
--
Live free or die
Задачу решил. Правы были те
Задачу решил. Правы были те скептики, которые говорили, что вся проблема в продуктах MS.
Для того, чтоб Linux ldap-утилиты нормально отрабатывали, нужно расширить схему на DC Windows.
Для Windows 2000 и 2003 (не R2) нужны Сервисы Microsoft Windows для UNIX (Microsoft Windows Services for UNIX, SFU)
(подробнее тут и тут.)
Для Windows 2003 R2 старше эти компоненты уже частично включены в систему, из них нам нужна Subsystem for UNIX-based Applications (SUA)
(подробнее тут.)
Угу, все так . причем здесь
Угу, все так .
причем здесь MS, слабо понятно, ибо лто то все равно должен маппить юзеров из SSIDов в id.
ссылки как бы оч. быстро находятся на самом течнете
http://technet.microsoft.com/en-us/magazine/2008.12.linux.aspx - как введение
и если совсем чуть поискать , то там же еще куча статей по этой теме от мелкомягких
находится сдесь
Compute:
Bosch M2.8.1 -> custom Bosch M2.8.3 clone from Russia.
Speed about 260 km,Ram 2 pers.,HDD - 70 kg,210 FLOPS ;)
Да, с пользователями все
Да, с пользователями все норм, аутентификацию можно наладить и так...
Зато как только дело доходит до групп, и выяснения членства в них - все гораздо хуже (((
На течнете действительно есть вагон и маленькая тележка статей по поводу совмещения MS и Linux продуктов, только как правило админы начинают изучать доки не со стороны MS продуктов, а со стороны LDAP, и тут в Рунете оказывается на удивленее мало толковых статей, которые бы посоветовали поближе познакомиться с MS SFU и его потомками...
.
1. И правильно делают!
2. Лично я бы с большим интересом почитал результаты допроса мелкомягких разработчиков на предмет: почему некоторое время назад категорически не рекомендовалось менять (как минимум в сторону увеличения) число возвращаемых AD записей и как с этим обстоит сейчас?
Проприетарщину надо мочить, а не изучать!
:wq
--
Live free or die