Назад | Перейти на главную страницу

Как заставить SASL-аутентификацию работать с DIGEST-MD5 для OpenLDAP?

Я настраиваю OpenLDAP slapd на Ubuntu 14.04 Trusty Tahr. Я хочу, чтобы определенные экземпляры (репликация и т. Д.), Которые не являются пользователями, могли входить в систему через SASL с помощью DIGEST-MD5 механизм.

В отличие от пользователей они не должен иметь соответствующий DN (вместе с паролем) в дереве каталогов. Вместо этого предполагается, что их учетные данные будут храниться извне, поэтому SASL.

я использую saslauthd прямо сейчас (это несложное требование, если, например, его можно заставить работать с прямым доступом к sasldb), и он отлично работает, используя механизмы PLAIN и LOGIN пока он не использует механизмы DIGEST-MD5 и CRAM-MD5.

Что я упускаю или делаю не так? Как мне заставить его работать с DIGEST-MD5?


OpenLDAP настроен для SASL в /etc/ldap/sasl2/slapd.conf как это:

mech_list: EXTERNAL DIGEST-MD5 CRAM-MD5 PLAIN LOGIN
pwcheck_method: saslauthd
saslauthd_path: /var/run/saslauthd/mux


Интересные (измененные) опции в /etc/default/saslauthd являются:

START=yes
MECHANISMS="sasldb"

Они приводят к saslauthd запускается так:

/usr/sbin/saslauthd -a sasldb -c -m /var/run/saslauthd -n 5


Я воспроизвожу неудачный случай с DIGEST-MD5 как это:

# ldapsearch -U replication -ZZ -Y DIGEST-MD5 -H ldap://ldap-master.example.com/ -b "dc=example,dc=com" "(objectClass=*)"
SASL/DIGEST-MD5 authentication started
Please enter your password: 
ldap_sasl_interactive_bind_s: Invalid credentials (49)
    additional info: SASL(-13): user not found: no secret in database

Часть журнала slapd, где кажется, что произошел сбой (ведение журнала включено any) выглядит так:

slapd[23330]: [rw] authid: "uid=replication,cn=digest-md5,cn=auth" -> "uid=replication,cn=digest-md5,cn=auth"
slapd[23330]: slap_parseURI: parsing uid=replication,cn=digest-md5,cn=auth
slapd[23330]: >>> dnNormalize: <uid=replication,cn=digest-md5,cn=auth>
slapd[23330]: <<< dnNormalize: <uid=replication,cn=digest-md5,cn=auth>
slapd[23330]: <==slap_sasl2dn: Converted SASL name to uid=replication,cn=digest-md5,cn=auth
slapd[23330]: slap_sasl_getdn: dn:id converted to uid=replication,cn=digest-md5,cn=auth
slapd[23330]: SASL Canonicalize [conn=1002]: slapAuthcDN="uid=replication,cn=digest-md5,cn=auth"
slapd[23330]: SASL [conn=1002] Failure: no secret in database
slapd[23330]: SASL [conn=1002] Debug: DIGEST-MD5 common mech dispose
slapd[23330]: send_ldap_result: conn=1002 op=2 p=3
slapd[23330]: send_ldap_result: err=49 matched="" text="SASL(-13): user not found: no secret in database"
slapd[23330]: send_ldap_response: msgid=3 tag=97 err=49

Нет ничего в /var/log/auth.log ни в отладочном выводе saslauthd когда я запускаю его вручную, что, вероятно, означает, что slapd даже не дошел до передачи аутентификации saslauthd (в отличие от рабочего корпуса, см. ниже).


Воспроизводю рабочий корпус с помощью PLAIN или LOGIN как это:

# ldapsearch -U replication -ZZ -Y PLAIN -H ldap://ldap-master.example.com/ -b "dc=example,dc=com" "(objectClass=*)"
SASL/PLAIN authentication started
Please enter your password: 
SASL username: replication
SASL SSF: 0
# extended LDIF
…

Соответствующая часть в slapd журнал, который указывал на сбой в приведенном выше случае, теперь выглядит так:

slapd[23330]: [rw] authid: "uid=replication,cn=plain,cn=auth" -> "uid=replication,cn=plain,cn=auth"
slapd[23330]: slap_parseURI: parsing uid=replication,cn=plain,cn=auth
slapd[23330]: >>> dnNormalize: <uid=replication,cn=plain,cn=auth>
slapd[23330]: <<< dnNormalize: <uid=replication,cn=plain,cn=auth>
slapd[23330]: <==slap_sasl2dn: Converted SASL name to uid=replication,cn=plain,cn=auth
slapd[23330]: slap_sasl_getdn: dn:id converted to uid=replication,cn=plain,cn=auth
slapd[23330]: SASL Canonicalize [conn=1006]: slapAuthcDN="uid=replication,cn=plain,cn=auth"
slapd[23330]: daemon: activity on 1 descriptor
slapd[23330]: daemon: activity on:
slapd[23330]: 
slapd[23330]: daemon: epoll: listen=8 active_threads=0 tvp=zero
slapd[23330]: daemon: epoll: listen=9 active_threads=0 tvp=zero
slapd[23330]: daemon: epoll: listen=10 active_threads=0 tvp=zero
slapd[23330]: SASL proxy authorize [conn=1006]: authcid="replication" authzid="replication"
slapd[23330]: conn=1006 op=1 BIND authcid="replication" authzid="replication"
slapd[23330]: SASL Authorize [conn=1006]:  proxy authorization allowed authzDN=""
slapd[23330]: send_ldap_sasl: err=0 len=-1
slapd[23330]: conn=1006 op=1 BIND dn="uid=replication,cn=plain,cn=auth" mech=PLAIN sasl_ssf=0 ssf=128
slapd[23330]: do_bind: SASL/PLAIN bind: dn="uid=replication,cn=plain,cn=auth" sasl_ssf=0
slapd[23330]: send_ldap_response: msgid=2 tag=97 err=0

Обе /var/log/auth.log и вывод отладки из saslauthd теперь содержат это:

saslauthd[23354]: rel_accept_lock : released accept lock
saslauthd[23358]: get_accept_lock : acquired accept lock
saslauthd[23354]: cache_get_rlock : attempting a read lock on slot: 458
saslauthd[23354]: cache_lookup    : [login=replication] [service=] [realm=ldap]: not found, update pending
saslauthd[23354]: cache_un_lock   : attempting to release lock on slot: 458
saslauthd[23354]: cache_get_wlock : attempting a write lock on slot: 458
saslauthd[23354]: cache_commit    : lookup committed
saslauthd[23354]: cache_un_lock   : attempting to release lock on slot: 458
saslauthd[23354]: do_auth         : auth success: [user=replication] [service=ldap] [realm=] [mech=sasldb]
saslauthd[23354]: do_request      : response: OK


Видимо, должна быть какая-то разница в том, как это работает с PLAIN и LOGIN vs. DIGEST-MD5 и CRAM-MD5.


Обновление и уточнение:

DN, используемые для авторизации доступа к дереву: uid=replication,cn=digest-md5,cn=auth и uid=replication,cn=plain,cn=auth соответственно и согласно разделу 15.2.5 http://www.openldap.org/doc/admin24/sasl.html эти DN не обязательно должны существовать в дереве (что должно быть верно по крайней мере для PLAIN и LOGIN как он там работает нормально).
В целях тестирования я сейчас использую olcAccess: to * by dn.regex="replication" read by * break чтобы гарантировать, что логин репликации получит хотя бы доступ для чтения ко всему (да, я знаю, что это небезопасно, и я дам ему соответствующие разрешения для производства) в главном дереве LDAP.

Учетные данные находятся в /etc/sasldb2 и они успешно проверяются при использовании PLAIN или LOGIN (см. выше). Для справки это выглядит так:

# sasldblistusers2
replication@ldap-master: userPassword
…

# db_dump -p /etc/sasldb2 
VERSION=3
format=print
type=hash
h_nelem=4
db_pagesize=4096
HEADER=END
 replication\00ldap-master\00userPassword
 PasswordCensored
…

Однако в случае DIGEST-MD5 и CRAM-MD5 это не похоже на контакт saslauthd вообще (возможно, из-за того, что я что-то упускаю или делаю что-то не так), так что с базой данных, скорее всего, тоже не обращаются.

Мой рецепт для OpenLDAP, чтобы проверить напрямую /etc/sasldb2.

Первый шаг: убедитесь, что /etc/sasldb2 принадлежит пользователю slapd.

Следующий шаг: иметь slapd не искать учетные данные в дереве каталогов, это делается следующим образом:

dn: cn=config
changetype: modify
replace: olcSaslAuxprops
olcSaslAuxprops: sasldb

Позже вам также понадобится olcAuthzRegexp правило, но чтобы проверить, работает ли auth, это не обязательно.

Эти настройки работают в Debian GNU / Linux Jessie OpenLDAP-2.4.40, созданном из исходных текстов.

Методы CRAM-MD5 и DIGEST-MD5 невозможны с "pwcheck_method: saslauthd". Им нужны простые, незашифрованные пароли в самом каталоге LDAP.

Я провел несколько обширных тестов для различных конфигураций с разными учетными данными в sasldb.

В заключение выясняется, что больше всего меня преследовала проблема, в соответствии с которым метод аутентификации (saslauthd vs. auxprop) (который, в свою очередь, зависит от запрошенного механизма аутентификации - DIGEST-MD5/CRAM-MD5 vs. PLAIN/LOGIN), он искал другой domain. Я не ожидал этого, и поскольку у меня была только одна пара пользователь-домен в sasldb, другого не нашлось.

Я перечислю некоторые из своих выводов и наблюдений в надежде, что это поможет другим понять проблему и решить ее:

  1. Если вы запросите PLAIN или LOGIN механизм, slapd будет использовать метод аутентификации, настроенный в pwcheck_method в /etc/ldap/sasl2/slapd.conf.
  2. В случае вашего запроса DIGEST-MD5 или CRAM-MD5 механизм, slapd всегда будет использовать auxprop независимо от того, что настроено для pwcheck_method.
  3. По сути, это означает, что вы можете slapd используйте тот же метод для всех 4 механизмов, если вы настроили pwcheck_method: auxprop. Или вы можете решить использовать 2 разных метода, если настроите что-то еще для pwcheck_method.
  4. В любом слючае, auxprop_plugin в /etc/ldap/sasl2/slapd.conf игнорируется. Вместо slapd использует то, что настроено для olcSaslAuxprops в собственной базе данных конфигурации. Обратите внимание, что это верно как для неявного auxprop метод при запросе DIGEST-MD5 или CRAM-MD5 механизмы, а также для явно настроенных pwcheck_method: auxprop при запросе одного из двух других механизмов.
  5. В моем случае, saslauthd ищет учетные данные с неприукрашенным именем хоста (т. е. просто ldap-master) как domain составная часть. Если бы я сделал обоснованное предположение, я бы сказал, что он использует что-то вроде gethostname() чтобы придумать это, чтобы это можно было как-то настроить.
  6. В моем случае при прохождении auxprop так или другой, slapd использует полное доменное имя (т.е. ldap-master.example.com) как domain составная часть. Вероятно, он получает это из исходного URL-адреса запроса (мои альтернативы для генерации запроса ограничены, когда я хочу использовать STARTTLS и хочу иметь возможность правильно проверить сертификат сервера, который запрашивает соответствующее доменное имя), но, вероятно, это может быть настраивается путем установки olcSaslHost в slapdбаза данных конфигурации. Обратите внимание, что я не пробовал его настраивать.

Итак, чтобы придумать рабочую конфигурацию, у вас есть несколько вариантов:

  1. Если тебе нравится просто PLAIN и LOGIN механизмы через STARTTLS, настроить pwcheck_method в /etc/ldap/sasl2/slapd.conf как требуется. Если это будет auxprop, также настроить olcSaslAuxprops в slapdбаза данных конфигурации (установите для нее sasldb, например, если вы хотите использовать /etc/sasldb2 как хранилище учетных данных).
  2. Если тебе нравится просто DIGEST-MD5 (Я обычно вижу CRAM-MD5 не рекомендуется из-за низкого уровня безопасности, поэтому старайтесь избегать этого), установите olcSaslAuxprops в slapdбазы данных конфигурации, поскольку auxprop будет использоваться независимо от того, что вы настроили для pwcheck_method.
  3. Если вы хотите использовать механизмы как из набора DIGEST-MD5, CRAM-MD5 (однако старайтесь избегать CRAM-MD5) а также множество PLAIN, LOGIN (убедитесь, что они используются только через зашифрованное соединение, например STARTTLS-one) и предпочитаете использовать один и тот же метод аутентификации для всех из них, а также проверять один и тот же набор учетных данных, вы ограничены auxprop. Настроить pwcheck_method: auxprop в /etc/ldap/sasl2/slapd.conf и установить olcSaslAuxprops в slapdбаза данных конфигурации по мере необходимости.
  4. Если вы хотите иметь возможность использовать механизмы из обоих наборов при использовании для них разных методов аутентификации (для меня это звучит как кошмар администрирования, но готово), настройте pwcheck_method в /etc/ldap/sasl2/slapd.conf соответственно для PLAIN и LOGIN и помните, что вы вынуждены использовать auxprop для DIGEST-MD5CRAM-MD5 если вы настаиваете) и установите olcSaslAuxprops в slapdбаза данных конфигурации по мере необходимости.

    • Если вам довелось настроить saslauthd для нехешированных механизмов и убедитесь, что saslauthd обращается к базе данных, отличной от той, что slapd доступ через auxprop или используйте что-то еще, кроме sasldb для olcSaslAuxprops, у вас они хорошо разделены, и вам не о чем беспокоиться.

    • Если вам довелось настроить saslauthd для нехешированных механизмов и sasldb для auxprop для механизмов хеширования и получения доступа к одной и той же базе данных учетных данных у вас есть 3 варианта в порядке предпочтения:

      1. Так или иначе, убедитесь, что оба saslauthd так же как slapd доступ к sasldb напрямую через auxprop запросить учетные данные с тем же domain (попробуйте установить olcSaslHost или принуждение saslauthd чтобы использовать полное доменное имя), поэтому для аутентификации вам нужно будет позаботиться только об одной записи учетных данных для каждого объекта.
      2. Сознательно примите решение использовать разные учетные данные для механизмов без хеширования и для механизмов хеширования. Использовать userid-hostname пара для нехешированных механизмов над saslauthd и использовать userid-hostname.domain.name пара для механизмов хеширования через auxprop.
      3. Сохраните две учетные записи для каждого объекта для аутентификации - одну с именем хоста, а другую с именем хоста.domain.name - и синхронизируйте пароли обоих (тьфу).