如何让 SASL 身份验证与 OpenLDAP 的 DIGEST-MD5 协同工作?

如何让 SASL 身份验证与 OpenLDAP 的 DIGEST-MD5 协同工作?

我正在 Ubuntu 14.04 Trusty Tahr 上设置 OpenLDAP slapd。我希望某些非用户的实例(复制等)能够通过SASL使用DIGEST-MD5机制登录。

与用户不同的是,他们不是应该在目录树中有一个对应的 DN(以及密码)。相反,他们的凭证应该存储在外部,因此SASL

saslauthd现在正在使用(例如,如果它可以通过直接访问 sasldb 来工作,那么这不是一个硬性要求),并且使用机制和它可以正常工作,PLAIN但使用机制和则LOGIN失败。DIGEST-MD5CRAM-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调试输出中没有任何内容,这可能表明甚至没有将身份验证移交给(与工作情况相反,见下文)。saslauthdslapdsaslauthd


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的工作 方式肯定存在一些差异。LOGINDIGEST-MD5CRAM-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 不必实际存在于树中(至少对于PLAINLOGIN来说必须如此,因为它在那里工作正常)。
出于测试目的,我目前使用它olcAccess: to * by dn.regex="replication" read by * break来确保复制登录至少对主 LDAP 树中的所有内容具有读取权限(是的,我知道这不安全,我将为其提供适当的生产权限)。

凭证已输入,使用或/etc/sasldb2时已成功检查凭证(见上文)。作为参考,它看起来像这样:PLAINLOGIN

# 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(可能是因为我遗漏了某些东西或者做错了某些事情),所以数据库可能也没有被查阅。

答案1

我的秘诀是使用 OpenLDAP 直接检查/etc/sasldb2

第一步:确保/etc/sasldb2由 slapd 用户拥有。

下一步:不必slapd在目录树中查找凭据,其操作如下:

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

稍后,您还需要一条olcAuthzRegexp规则,但为了测试身份验证是否有效,这不是必需的。

这些设置适用于从源代码构建的 Debian GNU/Linux Jessie OpenLDAP-2.4.40。

答案2

CRAM-MD5 和 DIGEST-MD5 方法无法通过“pwcheck_method: saslauthd”实现。它们需要 LDAP 目录中的明文、未加密密码。

答案3

我针对各种配置使用不同的凭据进行了一些广泛的测试sasldb

总之,这里最困扰我的问题是,根据所使用的身份验证方法(saslauthdvs. auxprop)(这又取决于请求的身份验证机制 - DIGEST-MD5/ CRAM-MD5vs. PLAIN/ LOGIN),它正在寻找不同的domain。我没有想到这一点,而且由于我在 中只有一个用户域对sasldb,所以它找不到另一个。

我将列出我的一些结论和观察,希望能够帮助其他人理解这个问题并解决它:

  1. 如果您请求PLAINLOGIN机制,将使用在下slapd配置的身份验证方法。pwcheck_method/etc/ldap/sasl2/slapd.conf
  2. 如果您请求DIGEST-MD5CRAM-MD5机制,slapd将始终使用该auxprop方法,无论配置了什么pwcheck_method
  3. 实际上,这意味着slapd如果您配置了 ,则可以对所有 4 种机制使用相同的方法pwcheck_method: auxprop。或者,如果您为 进行了其他配置,则可以决定使用 2 种不同的方法pwcheck_method
  4. 在任何情况下,都会忽略auxprop_pluginin 。而是使用其自身配置数据库中配置的内容。请注意,对于请求或机制时的隐式方法以及请求其他 2 种机制之一时的显式配置,这都是正确的。/etc/ldap/sasl2/slapd.confslapdolcSaslAuxpropsauxpropDIGEST-MD5CRAM-MD5pwcheck_method: auxprop
  5. 在我的例子中,使用未修饰的主机名(即,仅)作为组件saslauthd来查找凭据。如果我要进行有根据的猜测,我会说它使用类似于 的东西来得出这个结论,因此这可能是可以配置的。ldap-masterdomaingethostname()
  6. 就我而言,无论通过auxprop哪种方式,slapd都会使用完全限定域名(即ldap-master.example.com)作为domain组件。它很可能从原始请求 URL 中获取该域名(当我想使用 STARTTLS 并希望能够正确验证服务器证书(该证书要求匹配域名)时,我生成请求的替代方案是有限的),但它很可能可以通过在配置数据库olcSaslHost中进行设置来配置slapd。请注意,我还没有尝试配置它。

因此,为了制定可行的配置,您有以下几种选择:

  1. 如果您对STARTTLS 上的仅PLAIN和机制感到满意,请根据需要进行配置。如果要使用,还请在的配置数据库中进行配置(例如,如果您想将其用作凭证存储,请将其设置为 )。LOGINpwcheck_method/etc/ldap/sasl2/slapd.confauxpropolcSaslAuxpropsslapdsasldb/etc/sasldb2
  2. 如果您对此感到满意DIGEST-MD5(我通常CRAM-MD5不建议这样做,因为其安全性较差,因此请尝试避免使用它),请olcSaslAuxpropsslapd的配置数据库中进行设置,因为auxprop无论您为其配置什么,都将使用该方法pwcheck_method
  3. 如果您希望能够使用 集合中的机制DIGEST-MD5CRAM-MD5但请尽量避免CRAM-MD5)以及 集合中的机制PLAINLOGIN确保这些机制仅通过加密连接使用,例如 STARTTLS),并且希望对所有这些机制使用相同的身份验证方法并检查同一组凭据,则您只能使用auxprop。根据需要pwcheck_method: auxprop在 中配置/etc/ldap/sasl2/slapd.conf并设置olcSaslAuxpropsslapd配置数据库。
  4. 如果您希望能够使用这两组中的机制,同时对它们使用不同的身份验证方法(对我来说这听起来像是一场管理噩梦,但您可以这样做),请相应地pwcheck_method配置和,并记住您必须使用(如果您坚持的话)并根据需要在的配置数据库中进行设置。/etc/ldap/sasl2/slapd.confPLAINLOGINauxpropDIGEST-MD5CRAM-MD5olcSaslAuxpropsslapd

    • 如果您碰巧配置了saslauthd未散列的机制,并确保 saslauthd 访问的数据库与slapd通过访问的数据库不同,或者使用除forauxprop之外的其他东西,那么您就可以很好地将它们分开,而无需担心。sasldbolcSaslAuxprops

    • 如果您碰巧配置了saslauthd非散列机制和散列机制,并让它们访问相同的凭据数据库,那么您有 3 个选项,按优先顺序排列sasldbauxprop

      1. 以某种方式,确保两者saslauthd以及直接通过查询相同的凭据slapd访问 sasldb (尝试设置或强制使用 FQDN),这样您只需要关心每个实体的一个凭据条目即可进行身份验证。auxpropdomainolcSaslHostsaslauthd
      2. 特意决定对未散列机制和散列机制使用不同的凭据。对上面的未散列机制使用userid-对,对通过的散列机制使用-对。hostnamesaslauthduseridhostname.domain.nameauxprop
      3. 每个实体保留两个凭证条目以进行身份​​验证 - 一个使用“hostname”,另一个使用“hostname.domain.name” - 并保持两个密码同步(呃)。

相关内容