如何強制 Open Directory 伺服器向連接的客戶端提供其完整的證書鏈?
問題
我們在 OSX 10.10 Yosemite + Server.app v4 上創建了一個 Open Directory master:
$ 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 = a@b.c. verify error:num=20:unable to get local issuer certificate verify return:1 depth=0 CN = a.b.c, C = GB, emailAddress = a@b.c verify error:num=27:certificate not trusted verify return:1 depth=0 CN = a.b.c, C = GB, emailAddress = a@b.c verify error:num=21:unable to verify the first certificate verify return:1 --- Certificate chain 0 s:/CN=a.b.c/C=GB/emailAddress=a@b.c i:/CN=IntermediateCA_A.B.C_1/O=b/OU=MACOSX OpenDirectory Intermediate CA/emailAddress=a@b.c ---
當然,這是一個問題,因為客戶端(僅信任根 CA)無法驗證主機證書併中止連接。
記錄在案的解決方案
根據OpenLDAP Software 2.4 Administrator’s Guide,第 16 章“使用 TLS”:
16.2.1.1。TLSCACertificateFile <文件名>
該指令指定 PEM 格式文件,其中包含 slapd 將信任的 CA 的證書。簽署伺服器證書的 CA 的證書必須包含在這些證書中。如果簽名 CA 不是頂級(根)CA,則應該存在從簽名 CA 到頂級 CA 的整個 CA 序列的證書。多個證書只是附加到文件中;順序不重要。
(為避免疑義,最近在 openldap-technical 郵件列表上確認了
slapd
隨後將向連接客戶端提供證書鏈的事實——儘管之前已經註意到這會導致使用不同信任錨的問題衝突對於 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 忽略。
(SecureTransport是 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
已被覆蓋(並且它只繼續支持 SSL,只要該配置選項的值與系統鑰匙串中證書的 CN 匹配,否則它會抱怨類似於上面引用的錯誤 - 表明它正在使用該預期的配置選項)。然而,完整的證書鏈仍然沒有提供給連接的客戶端。如何解決這個問題?
問題是雙重的:
- 安全傳輸使用 API 客戶端提供給它的證書鏈。API 文件和原始碼註釋都暗示(沒有明確表示)這是一個錯誤:在這種情況下,安全傳輸似乎應該嘗試從系統鑰匙串建構證書鏈。
- Apple 的 slapd始終**只為 Secure Transport 提供主機身份證書,而不是證書鏈。請參閱從以下摘錄的片段
libraries/libldap/tls_st.c
:[ctx->identity_certs =](https://github.com/aosm/OpenLDAP/blob/ed3398e553abcb349419fdb038e489283feca6cd/OpenLDAP/libraries/libldap/tls_st.c#L1026) /* */ [CFArrayCreate(NULL, (const void **) &identRef, 1, &kCFTypeArrayCallBacks);](https://github.com/aosm/OpenLDAP/blob/ed3398e553abcb349419fdb038e489283feca6cd/OpenLDAP/libraries/libldap/tls_st.c#L578) [SSLSetCertificate(ssl, ctx->identity_certs);](https://github.com/aosm/OpenLDAP/blob/ed3398e553abcb349419fdb038e489283feca6cd/OpenLDAP/libraries/libldap/tls_st.c#L1120)
因此,就目前情況而言,Apple 的 slapd無法發送完整的證書鏈。