问题
我们在 OSX 10.10 Yosemite + Server.app v4 上创建了一个 Open Directory 主服务器:
$ sudo slapconfig -createldapmasterandadmin admin Administrator 1000
这会生成一个根 CA、一个中间 CA 和一个主机 SSL 证书(所有证书均正确放置在系统钥匙串和目录中/etc/certificates
)。但是,当通过 SSL 连接时,slapd
提供仅主机证书,而不是整个证书链:
$ openssl s_client -connect a.b.c:636
CONNECTED(00000003)
depth=0 CN = a.b.c, C = GB, emailAddress = [email protected].
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 CN = a.b.c, C = GB, emailAddress = [email protected]
verify error:num=27:certificate not trusted
verify return:1
depth=0 CN = a.b.c, C = GB, emailAddress = [email protected]
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
0 s:/CN=a.b.c/C=GB/[email protected]
i:/CN=IntermediateCA_A.B.C_1/O=b/OU=MACOSX OpenDirectory Intermediate CA/[email protected]
---
当然,这是一个问题,因为客户端(仅信任根 CA)无法验证主机证书并中止连接。
记录解决方案
根据OpenLDAP 软件 2.4 管理员指南,第 16 章“使用 TLS”:
16.2.1.1. TLSCACertificateFile <文件名>
此指令指定包含 slapd 将信任的 CA 证书的 PEM 格式文件。签署服务器证书的 CA 的证书必须包含在这些证书中。如果签署 CA 不是顶级(根)CA,则应存在从签署 CA 到顶级 CA 的整个 CA 序列的证书。多个证书只需附加到文件即可;顺序并不重要。
(为避免疑问,slapd
随后将向连接客户端提供证书链的事实最近被在 openldap-technical 邮件列表上确认—尽管先前指出这会导致有问题的冲突,因为不同的信任锚用于 TLS 客户端证书)。
苹果的特色
由于 Apple 的构建使用了slapd.d
,人们通常会期望通过 — 来配置此选项olcTLSCACertificateFile
,但是,根据slapd-config(5)
(强调添加):
olcTLSCACertificateFile:<文件名>
指定包含 slapd 可以识别的所有证书颁发机构的证书的文件。
使用 SecureTransport 时此选项无效。请改用 olcTLSTrustedCerts 选项。
[德莱蒂亚]olcTLSTrustedCerts
列出系统钥匙串中受信任的证书,以“|”分隔。例如:olcTLSTrustedCerts Frobozz, Inc.|Widgets R Us|www.example.com
由 SecureTransport 使用,而不是 olcTLSCACertificateFile 和 olcTLSCACertificatePath。被 OpenSSL、GnuTLS 和 Mozilla NSS 忽略。
(安全传输是 Apple 的 SSL 库)。
我们的尝试…
令人惊讶的是,olcTLSTrustedCerts
并没有在我们的目录中创建slapconfig
,尽管主机证书曾是在(相关)中命名olcTLSIdentity
。也就是说,slapd
无论如何都会忽略系统钥匙串中的偏好olcTLSIdentity
:OPENDIRECTORY_SSL_IDENTITY
TLS:OPENDIRECTORY_SSL_IDENTITY 身份偏好覆盖了配置的 olcTLSIdentity“abc”
因此,我们尝试了以下方法(独立和共同尝试):
正在添加
olcTLSTrustedCerts
。slapd
清楚地解析此选项中列出的 CN 并在系统钥匙串中找到 CA 证书,因为它记录了故意提供不正确值的情况:TLS:SecItemCopyMatching(foo.bar)失败(检查 olcTLSTrustedCerts 设置):在钥匙串中找不到指定的项目。(-25300)
OPENDIRECTORY_SSL_IDENTITY
从系统钥匙串中删除偏好设置.slapd
不再抱怨olcTLSIdentity
已被覆盖(并且只要该配置选项的值与系统钥匙串中的证书的 CN 匹配,它就会继续支持 SSL,否则它会抱怨类似于上面引用的错误 - 表明它正在按预期使用该配置选项)。
但完整的证书链仍未提供给连接客户端。如何解决这个问题?
答案1
问题有两个方面:
安全传输使用证书链确切地由 API 客户端提供。API 文档和源代码注释都暗示(没有明确)这是一个错误:在这种情况下,安全传输似乎应该尝试从系统钥匙串构建证书链。
苹果的打击总是为安全传输提供主机身份证书仅有的和绝不证书链。请参阅以下摘录自的片段
libraries/libldap/tls_st.c
:ctx->identity_certs = /* */ CFArrayCreate(NULL, (const void **) &identRef, 1, &kCFTypeArrayCallBacks); SSLSetCertificate(ssl, ctx->identity_certs);
因此,就目前情况而言,苹果的不能发送完整的证书链。