我正在 Ubuntu 14.04 Trusty Tahr 上设置 OpenLDAP slapd
。我希望某些非用户的实例(复制等)能够通过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
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
(可能是因为我遗漏了某些东西或者做错了某些事情),所以数据库可能也没有被查阅。
答案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
。
总之,这里最困扰我的问题是,根据所使用的身份验证方法(saslauthd
vs. auxprop
)(这又取决于请求的身份验证机制 - DIGEST-MD5
/ CRAM-MD5
vs. PLAIN
/ LOGIN
),它正在寻找不同的domain
。我没有想到这一点,而且由于我在 中只有一个用户域对sasldb
,所以它找不到另一个。
我将列出我的一些结论和观察,希望能够帮助其他人理解这个问题并解决它:
- 如果您请求
PLAIN
或LOGIN
机制,将使用在下slapd
配置的身份验证方法。pwcheck_method
/etc/ldap/sasl2/slapd.conf
- 如果您请求
DIGEST-MD5
或CRAM-MD5
机制,slapd
将始终使用该auxprop
方法,无论配置了什么pwcheck_method
。 - 实际上,这意味着
slapd
如果您配置了 ,则可以对所有 4 种机制使用相同的方法pwcheck_method: auxprop
。或者,如果您为 进行了其他配置,则可以决定使用 2 种不同的方法pwcheck_method
。 - 在任何情况下,都会忽略
auxprop_plugin
in 。而是使用其自身配置数据库中配置的内容。请注意,对于请求或机制时的隐式方法以及请求其他 2 种机制之一时的显式配置,这都是正确的。/etc/ldap/sasl2/slapd.conf
slapd
olcSaslAuxprops
auxprop
DIGEST-MD5
CRAM-MD5
pwcheck_method: auxprop
- 在我的例子中,使用未修饰的主机名(即,仅)作为组件
saslauthd
来查找凭据。如果我要进行有根据的猜测,我会说它使用类似于 的东西来得出这个结论,因此这可能是可以配置的。ldap-master
domain
gethostname()
- 就我而言,无论通过
auxprop
哪种方式,slapd
都会使用完全限定域名(即ldap-master.example.com
)作为domain
组件。它很可能从原始请求 URL 中获取该域名(当我想使用 STARTTLS 并希望能够正确验证服务器证书(该证书要求匹配域名)时,我生成请求的替代方案是有限的),但它很可能可以通过在配置数据库olcSaslHost
中进行设置来配置slapd
。请注意,我还没有尝试配置它。
因此,为了制定可行的配置,您有以下几种选择:
- 如果您对STARTTLS 上的仅
PLAIN
和机制感到满意,请根据需要进行配置。如果要使用,还请在的配置数据库中进行配置(例如,如果您想将其用作凭证存储,请将其设置为 )。LOGIN
pwcheck_method
/etc/ldap/sasl2/slapd.conf
auxprop
olcSaslAuxprops
slapd
sasldb
/etc/sasldb2
- 如果您对此感到满意
DIGEST-MD5
(我通常CRAM-MD5
不建议这样做,因为其安全性较差,因此请尝试避免使用它),请olcSaslAuxprops
在slapd
的配置数据库中进行设置,因为auxprop
无论您为其配置什么,都将使用该方法pwcheck_method
。 - 如果您希望能够使用 集合中的机制
DIGEST-MD5
(CRAM-MD5
但请尽量避免CRAM-MD5
)以及 集合中的机制PLAIN
(LOGIN
确保这些机制仅通过加密连接使用,例如 STARTTLS),并且希望对所有这些机制使用相同的身份验证方法并检查同一组凭据,则您只能使用auxprop
。根据需要pwcheck_method: auxprop
在 中配置/etc/ldap/sasl2/slapd.conf
并设置olcSaslAuxprops
的slapd
配置数据库。 如果您希望能够使用这两组中的机制,同时对它们使用不同的身份验证方法(对我来说这听起来像是一场管理噩梦,但您可以这样做),请相应地
pwcheck_method
配置和,并记住您必须使用(如果您坚持的话)并根据需要在的配置数据库中进行设置。/etc/ldap/sasl2/slapd.conf
PLAIN
LOGIN
auxprop
DIGEST-MD5
CRAM-MD5
olcSaslAuxprops
slapd
如果您碰巧配置了
saslauthd
未散列的机制,并确保 saslauthd 访问的数据库与slapd
通过访问的数据库不同,或者使用除forauxprop
之外的其他东西,那么您就可以很好地将它们分开,而无需担心。sasldb
olcSaslAuxprops
如果您碰巧配置了
saslauthd
非散列机制和散列机制,并让它们访问相同的凭据数据库,那么您有 3 个选项,按优先顺序排列sasldb
:auxprop
- 以某种方式,确保两者
saslauthd
以及直接通过查询相同的凭据slapd
访问 sasldb (尝试设置或强制使用 FQDN),这样您只需要关心每个实体的一个凭据条目即可进行身份验证。auxprop
domain
olcSaslHost
saslauthd
- 特意决定对未散列机制和散列机制使用不同的凭据。对上面的未散列机制使用
userid
-对,对通过的散列机制使用-对。hostname
saslauthd
userid
hostname.domain.name
auxprop
- 每个实体保留两个凭证条目以进行身份验证 - 一个使用“hostname”,另一个使用“hostname.domain.name” - 并保持两个密码同步(呃)。
- 以某种方式,确保两者