Dovecot + Kerberos/GSSAPI
Версия для печати

Конференция: Конференция iXBT.com (http://forum.ixbt.com/)
Форум: Программы: Unix-like системы (http://forum.ixbt.com/?id=76)
URL: http://forum.ixbt.com/topic.cgi?id=76:10089

Время GMT +03. Даты в формате dd.mm.yyyy.


SuSt, 30.08.2011 13:05
Задумал сделать я для своих доменных юзеров прозрачную авторизацию на почтовом сервере. Мучаю Dovecot 2.0.13 под управлением Debian GNU/Linux 6.0.2 (Squeeze). В качестве контроллера домена выступает Windows 2008 Server SP2, он же является Ticket Distribution Service.

Сделал всё по инструкции с официального сайта (http://wiki2.dovecot.org/Authentication/Kerberos) Dovecot-а. В-общем, оно работает как задумано, но при условии что я в настройках "голубятни" (Dovecot) выставляю
код:
auth_gssapi_hostname = "$ALL"

Если же я в этой директиве ставлю более религиозно верное имя хоста, вот так
код:
auth_gssapi_hostname = efim.test.local

то он не может найти нужный ключик в /etc/krb5.keytab и ругается:
код:
Aug 29 16:05:14 auth: Info: gssapi(?,192.168.4.12): While processing incoming data: Unspecified GSS failure.  Minor code may provide more information
Aug 29 16:05:14 auth: Info: gssapi(?,192.168.4.12): While processing incoming data: Wrong principal in request

При этом в отладочных логах есть вот такое:
код:
Aug 29 16:05:14 auth: Debug: gssapi(?,192.168.4.12): Obtaining credentials for imap@efim.test.local
Aug 29 16:05:14 auth: Debug: client out: CONT 1
Aug 29 16:05:14 auth: Debug: client in: CONT<hidden>
Aug 29 16:05:16 auth: Debug: client out: FAIL 1

Вот чего я никак не могу взять в толк.
В вики написано, что нужно создавать ключи вида "imap/efim.test.local@MYREALM.ORG". А реально Dovecot ищет в keytab-е ключ с именем "imap@efim.test.local". И исходный код модуля "mech-gssapi.c" является лишним тому подтверждением:
код:
static OM_uint32
obtain_service_credentials(struct auth_request *request, gss_cred_id_t *ret_r)
/* Бла-бла-бла (вырезал кусок) */
principal_name = t_str_new(128);
str_append(principal_name, service_name);
str_append_c(principal_name, '@');
str_append(principal_name, request->set->gssapi_hostname);

auth_request_log_debug(request, "gssapi",
"Obtaining credentials for %s", str_c(principal_name));

inbuf.length = str_len(principal_name);
inbuf.value = str_c_modifiable(principal_name);

major_status = gss_import_name(&minor_status, &inbuf,
GSS_C_NT_HOSTBASED_SERVICE,
&gss_principal);

Кто разбирается в C++ и Kerberos получше меня, проясните пожалуйста. Это ошибка в исходниках, в вики, или я чего-то недопонимаю?

В список рассылки самого Dovecot-а уже написал (http://dovecot.org/list/dovecot/2011-August/060738.html) . Кроме какого-то отечественного же Капитана Очевидность мне по существу вопроса никто там не ответил.

Есть идеи?

1. -Sorcerer-, 30.08.2011 14:32
PTR и A в DNSe сходятся?

2. SuSt, 30.08.2011 14:54
-Sorcerer-

Само собой разумеется.

3. arvidjaar, 31.08.2011 01:20
SuSt

Это ошибка в исходниках, в вики, или я чего-то недопонимаю?

Скорее последнее
цитата:
A service that is related to a particular host. For the Kerberos mechanism, the service name is specified as service@host. The service name is mapped to the principal service/primary-host@realm using the krb5_sname_to_principal() function. The primary host name must be associated with a Kerberos realm to map the service name to the proper principal.
За это сообщение сказали спасибо: SuSt

4. SuSt, 31.08.2011 15:47
arvidjaar

Это уже интереснее. Хотя, в исходниках "mech-gssapi.c" я нигде не смог найти пресловутую "krb5_sname_to_principal()". Там сначала формируется строковая переменная "principal_name" вида "service@host", потом эта строка является аргументом функции "gss_import_name()". Если верить документации, то вроде как всё верно: параметр "GSS_C_NT_HOSTBASED_SERVICE" действительно означает что туда передает "service@host".

Но тогда я вообще ничего не понимаю.

Специально включил отладку на своем Thunderbird-е:
код:
C:\Program Files\Mozilla Thunderbird>set NSPR_LOG_MODULES=negotiateauth:5
C:\Program Files\Mozilla Thunderbird>set NSPR_LOG_FILE=s:\log\tb.txt
C:\Program Files\Mozilla Thunderbird>start thunderbird


Смотрю что в логах на клиенте:
код:
1824[5a9e240]:   nsAuthSSPI::Init
1824[5a9e240]: InitSSPI
1824[5a9e240]: Using SPN of [imap/efim.test.local]
1824[5a9e240]: AcquireCredentialsHandle() succeeded.
1824[5a9e240]: entering nsAuthSSPI::GetNextToken()
1824[5a9e240]: InitializeSecurityContext: continue.


Thunderbird передает на сервер как раз то, что нужно: "Using SPN of [imap/efim.test.local]".

Проверяю keytab на сервере:
код:
slot KVNO Principal
---- ---- ---------------------------------------------------------------------
1 4 imap/efim.test.local@ROMASHKA.LAN
2 5 pop/efim.test.local@ROMASHKA.LAN
3 6 smtp/efim.test.local@ROMASHKA.LAN


То есть Thunderbird отдает как раз то, что сервер ожидает услышать. Сам клиент находится в AD-домене "romashka.lan". Что еще ему может не нравиться?

Коль скоро отлуп генерируется не Dovecot-ом, а где-то глубоко в недрах KRB-шных библиотек, становится совершенно не понятно как енто всё можно посмотреть/отладить.

Ну или второй вариант: забить на это и оставить auth_gssapi_hostname = "$ALL". Но хочется разобраться в чём дело.

5. -Sorcerer-, 31.08.2011 18:38
SuSt

В мейл-листе там чувак ответил по делу, и похоже на правду.

6. arvidjaar, 01.09.2011 15:18
-Sorcerer-
Да вообще-то там все ответы по делу, включая и самый первый
Начинать надо действительно с проверки базового kerberos. Как это делать, в ответах подробно расписано.

Хотя судя по симптомам я все-таки сколняюсь к прблемам с DNS. Поскольку krb5_sname_to_principa() выполняет name1 => IP => name2 и возвращает ошибку, если name1 != name2. При использовании $ALL этого шага нет, и поскольку при нем все работает, kerberos часть видимо функционирует.

7. SuSt, 01.09.2011 18:23
arvidjaar

Я разобрался в своей проблеме. Она оказалась OpenVZ-specific. Вся эта радость вместе с Dovecot-ом у меня крутится на виртуалке под управлением OpenVZ с Venet-интерфейсом. А Venet-интерфейс устроен несколько сюрпризно. Фактически это loopback с пачкой алиасов на нём. Видать, у кербероса сплющило мозХ и он так и не смог разрюхать какой там hostname к какому IP относится.

Как только я заменил venet на veth (более полная эмуляция сети), всё взлетело. Только вот попутно появился второй вопрос. Можно ли как-то керберосным библиотекам объяснить, что, мол, нефиг выпендриваться, давай хавай тот IP который дают?

8. -Sorcerer-, 02.09.2011 04:41
SuSt
Можно ли как-то керберосным библиотекам объяснить, что, мол, нефиг выпендриваться, давай хавай тот IP который дают?

Ага, т.е. я оказался прав и проблема с обратным резолвом таки была.
Керберос юзает gethostbyaddr() для получаения имени, если этот колл херово сэмулирован на OpenVZ - делать нечего.

9. SuSt, 02.09.2011 17:31
Вообще я бегло просмотрел исходники krb5-user. Не нашел ничего такого, что было бы конкретно завязано на сетевую конфигурацию. На насчет gethostbyaddr вряд ли ты прав. Ведь утилита host отрабатывает в любом случае. Да и список присвоенных интерфейсом IP-адресов в конечном счете один и тот же.

10. -Sorcerer-, 02.09.2011 20:47
SuSt
Ведь утилита host отрабатывает в любом случае.

И что теперь? ltrace не показывает, что онa юзает gethostbyaddr() или getaddrinfo()

Добавление от 02.09.2011 20:49:

SuSt
Вообще я бегло просмотрел исходники krb5-user.

Эээ... gss_import_name() это часть libgssapi, которая вызывает конкретные имплеменации, в зависимости от платформы.
Так что ессно, что в krb5-user ничего не будет.

11. SuSt, 02.09.2011 20:54
-Sorcerer-
ltrace не показывает
Приведите тогда пожалуйста пример какой-нибудь относительно простой утилиты, которая юзает. Для проверки этой версии происходящего.

которая вызывает конкретные имплеменации
И как же будет по-Вашему называться имплементация под Debian GNU/Linux 6.0.2 ? И в каком же пакете её искать?

12. arvidjaar, 03.09.2011 14:14
SuSt
Можно ли как-то керберосным библиотекам объяснить, что, мол, нефиг выпендриваться, давай хавай тот IP который дают?
"хавай что дают" немножко не соответствует целям kerberos ...
Вообще задачу "хавай что дают" как я понимаю решает использовние $ALL. Что именно вас в этом смущает?

При использовании krb5_sname_to_principal() напрямую действительно есть возможность принудительно использовать имя "as is". Но не в случае вызова из GSSAPI. При использовании GSSAPI можно просто передать в явном виде prinicpal - но тогда теряется универсальность на уровне приложения.

Единственное, что можно сделать - отключить вторую фазу (IP => name; т.е. вызов getaddrinfo()).
код:
/etc/krb5.conf:
...
[libdefaults]
...
rdns = no
...

В этом случае выполняется только getnameinfo(), с попыткой получения канонического имени. Если и это не будет работать, боюсь, проблема все-таки не в kerberos

13. SuSt, 05.09.2011 12:30
arvidjaar
Что именно вас в этом смущает?

Да не то чтобы "смущает". Я только хочу разобраться как всё это устроено изнутри, прежде чем ставить решение на боевое дежурство. Ибо потом будет уже поздно пить боржоми собирать грабли, попутно уворачиваясь от летящих в тебя тапков.

А решение получается какое-то очень капризное и трудно отлаживаемое. Так, например, если процесс Dovecot не имеет доступа на чтение к файлу "krb5.conf" — "привет", приехали: "Wrong principal in request". Казалось бы, какая ему разница? Есть же API. Ан-нет, всё рассыпается по малейшему чиху.

"rdns = no" не помогло. Ничего не изменилось.

но тогда теряется универсальность на уровне приложения

Вот тут не понял. У того же Dovecot-а есть настройка "auth_gssapi_hostname" в конфиге. Или вы что-то другое имели ввиду?

А вообще, чем дольше ковыряюсь, тем больше понимаю, что Kerberos — это не технология аутентификации, а какое-то шайтанство. Есть два рядом стоящих одинаковых десктопа с одинаковой виндой (XP), одинаковой версией Thunderbird, в одном и том же домене, с одинаковой настройкой и одним и тем же залогиненным в домен пользователем. Только на одном всё замечательно работает, на другом — "Wrong principal in request". Я уже вообще ничего не понимаю. И Wireshark не особо помогает. Не ясно даже как можно это всё отлаживать-то.

14. arvidjaar, 06.09.2011 17:15
SuSt
Или вы что-то другое имели ввиду?
GSSAPI - интерфейс, kerberos - реализация. В принципе, существуют другие технологии, и использовать параметры, специфические для конкретной реализации, как-то неправильно

Не ясно даже как можно это всё отлаживать-то.
На сервере в логах kerberos ничего полезного нет? Можно включить трассировку с более подробной информацией если у вас версия 1.9.

на одном всё замечательно работает, на другом — "Wrong principal in request"
Один получил тикет раньше другого, а вы за это время что-то изменили? В качестве гипотезы

Кстати, вам уже отвечали в списке рассылки dovecot, хочу обратить внимание еще раз - Microsoft официально предупреждает, что
цитата:
You cannot map multiple service instances to the same user account [using ktpass].
Поскольку одна из возможных причин вашей ошибки, приведенной в самом начале - именно несоответствие KVNO. Другая возможнная причина - дублированные SPN в AD.

15. SuSt, 06.09.2011 23:28
arvidjaar

существуют другие технологии
Теперь понял. Конкретно в случае с dovecot-ом GSSAPI однозначно подразумевает Kerberos. Но Вы правы, разумеется.

На сервере в логах kerberos ничего полезного нет?
Сервер ни с кем не общается по Kerberos. Когда я натравливаю на него Wireshark в режиме "слушать всё", то он даже DNS запросы никакие не генерирует. Он только проверяет тикеты, которые шлют ему клиенты. Какая-либо сетевая активность сервера проявляется только в трафике по POP3 и IMAP протоколам. Соответственно, в логах kerberos-а не сервере тоже ничего нет. Есть только скупые сообщения от GSSAPI, ретранслируемые "как есть" в отладочные логи почтаря (dovecot).

если у вас версия 1.9
Да, 1.9. Покопаю в этом направлении, спасибо за подсказку. Хотя снова не уверен, что правильно Вас понял.

Один получил тикет раньше другого, а вы за это время что-то изменили?
Нет. Специально ставил "максимально честный" эксперимент, проделывая все операции практически одну за другой. Пытаюсь проверять почту сначала на одной машине, потом сразу же на другой. Потом перезагружаю обе и повторяю в обратном порядке (сначала на второй, потом на первой). Результат одинаковый и не зависит от того, которая из них была первой, которая второй. В чем разница, понять вообще никак не могу. Системное время тоже проверял, тем более что они обе синхронизируются с контроллера домена.

You cannot map multiple service instances to the same user account
Вообще-то так было в 2003-ей винде. В 2008-ой уже всё нормально. Да и в рассылке David Warden упоминал, что мухлевал с principal-ами в LDAP-е при помощи setspn, целенаправленно "подвешивая" несколько сервайсов на один и тот же principal и KVNO. И данная версия не объясняет, почему две одинаковые машины аутентифицируются на сервере с разными результатами. Но я попробую, конечно, "развести" по разным аккаунтам, чтобы исключить эту причину. Попытка - не пытка.

Другая возможнная причина - дублированные SPN в AD
Да вроде бы не дублируются... Только вот как бы это проверить, чтобы лишний раз удостовериться?

16. arvidjaar, 07.09.2011 12:44
SuSt
Потом перезагружаю обе и повторяю в обратном порядке (сначала на второй, потом на первой).
Можно выложить протокол wireshark с обеих систем после перезагрузки?

Вообще-то так было в 2003-ей винде. В 2008-ой уже всё нормально.
Может и так. Цитата была из документа для 2008

Да вроде бы не дублируются... Только вот как бы это проверить
В w2k8: setspn -X. http://blogs.msdn.com/b/psssql/archive/2009/02/13/se…ittle-easier.aspx

17. SuSt, 08.09.2011 11:01
arvidjaar

Я грохнул в AD всех старых пользователей, которых создавал до этого. Потом новой создал трех отдельных пользователей - для POP, IMAP и SMTP. Проверил setspn-ом, что дубликатов в LDAP-е нет. Затем ktpass-ом еще раз и очень внимательно сгенерировал keytab-ы, объединил их и скормил почтарю.

Удивительно, но всё заработало. Причем, везде. Причем, даже с venet-интерфейсом. И независимо от настроек "rdns", "dns_lookup_realm", "dns_lookup_kdc" в krb5.conf. Так что типа Happy End и все дела.

По всей видимости, дело было именно в том, что у меня три разных principal-а были "завешены" на одного и того же пользователя в AD. Теперь мой keytab выглядит вот так:
код:
slot KVNO Principal
---- ---- ---------------------------------------------------------------------
1 3 pop/efim.test.local@ROMASHKA.LAN
2 3 imap/efim.test.local@ROMASHKA.LAN
3 3 smtp/efim.test.local@ROMASHKA.LAN


Спасибо большое за помощь, arvidjaar. Готов поставить вам сок, пиво или что там вы пьете.

Кстати, есть ли какая-нибудь хорошая бумажная книжка (не обязательно на русском), в которой достаточно наглядно были бы расписаны все премудрости Kerberos-а и GSSAPI, для дальнейшего изучения?

18. arvidjaar, 08.09.2011 17:26
SuSt
Кстати, есть ли какая-нибудь хорошая бумажная книжка (не обязательно на русском)
У O'Reilly есть Kerberos: The Definitive Guide (http://shop.oreilly.com/product/9780596004033.do) . Комментировать не могу, так как не читал, но к книгам O'Reilly отношусь с уважением

19. mc.sim, 12.11.2011 02:52
Спасибо вам за отличный траблешуттинг!!!!



URL: http://forum.ixbt.com/topic.cgi?id=76:10089

Время GMT +03. Даты в формате dd.mm.yyyy.