SSLのVerifyで「 21 (unable to verify the first certificate)」エラーが発生する。

事の始まりは、MacOS X Yosemite上のPhpStormでHTTPSで提供されるSVNサーバーにアクセスすると、

Server SSL certificate rejected

が出てアクセスできない。サーバー証明書を手動で信頼させてもアクセスできない。

このSVNサーバーはComodoのPositiveSSLサーバー証明書を取得している。
更新したばかりで有効期間も正しい。
GoogleChromeで同じURLにSSLでアクセスしても問題がない。
最初はMacOS X のJava 6にバンドルされているCA証明書リストにComodoのPositiveSSLのCAが無いのかと調べてみたが、入っているようだ。

keytool -list -v -keystore /Library/Java/Home/lib/security/cacerts
※キーストアのパスワード「changeit」

次にsvnをコマンドラインで動作させてみると、SVNでもサーバー証明書のVerifyがNG。

$ svn checkout https://host1.mydomain.com/svn/
Error validating server certificate for 'https://host1.mydomain.com:443':
 - The certificate is not issued by a trusted authority. Use the
   fingerprint to validate the certificate manually!
Certificate information:
 - Hostname: host1.mydomain.com
 - Valid: from Mon, 10 Mar 2015 00:00:00 GMT until Sat, 13 Mar 2016 23:59:59 GMT
 - Issuer: COMODO CA Limited, Salford, Greater Manchester, GB
 - Fingerprint: 64:f4:c4:a0:d1:c4:ec:bd:a7:bd:6f:59:bf:cc:3f:2e:01:2d:43:51
(R)eject, accept (t)emporarily or accept (p)ermanently? p

今度はOpenSSLで接続してみる。
やはりエラーで、「21 (unable to verify the first certificate)」だ。

# openssl s_client  -connect host1.mydomain.com:443
CONNECTED(00000003)
depth=0 /OU=Domain Control Validated/OU=PositiveSSL/CN=host1.mydomain.com
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 /OU=Domain Control Validated/OU=PositiveSSL/CN=host1.mydomain.com
verify error:num=27:certificate not trusted
verify return:1
depth=0 /OU=Domain Control Validated/OU=PositiveSSL/CN=host1.mydomain.com
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
 0 s:/OU=Domain Control Validated/OU=PositiveSSL/CN=host1.mydomain.com
   i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA
 1 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=PositiveSSL CA 2
   i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
---
Server certificate
-----BEGIN CERTIFICATE-----
・
・
・
-----END CERTIFICATE-----
subject=/OU=Domain Control Validated/OU=PositiveSSL/CN=host1.mydomain.com
issuer=/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA
---
No client certificate CA names sent
---
SSL handshake has read 3342 bytes and written 328 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : DHE-RSA-AES256-SHA
    Session-ID: 265CA7E8B4EC72706F26AEF50DCF74FF4D363D780455369BBD3AA0F01130FDD3
    Session-ID-ctx: 
    Master-Key: 0E011D80FCDBC2E065404D47530690800327CDCDAA6E092DF9D82ED315AA2921C49C1FCD2B9B6619329F739A8708BEFD
    Key-Arg   : None
    Start Time: 1428449852
    Timeout   : 300 (sec)
    Verify return code: 21 (unable to verify the first certificate)
---

しかし証明書チェーンをよく見ると、サーバー証明書の発行元である中間証明書がおかしい。
Issure(発行元)のCN(CommonName)が発行元である中間証明書のSubject CNと合っていない。
サーバーがSSL通信の際に送信してくる証明書チェーンがおかしいようだ。

Certificate chain 
0 s:/OU=Domain Control Validated/OU=PositiveSSL/CN=host1.mydomain.com  
i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA
1 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=PositiveSSL CA 2
i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External 

CA Root サーバーの設定を見てみると、Apache のSSLCertificateChainFile設定のファイルが間違っていた…

異なる中間証明書ファイルを指定している。

修正して、再度OpenSSLで検証してみると、今度は「Verify return code: 0 (ok)」で成功した。

# openssl s_client  -connect host1.mydomain.com:443
CONNECTED(00000003)
depth=3 /C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
verify error:num=19:self signed certificate in certificate chain
verify return:0
---
Certificate chain
 0 s:/OU=Domain Control Validated/OU=PositiveSSL/CN=host1.mydomain.com
   i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA
 1 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA
   i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority
 2 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority
   i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
 3 s:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
   i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIFYzCCBEugAwIBAgIQbYL++FqtsyI30fivYWz5rDANBgkqhkiG9w0BAQsFADCB
・
・
・
-----END CERTIFICATE-----
subject=/OU=Domain Control Validated/OU=PositiveSSL/CN=host1.mydomain.com
issuer=/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA
---
No client certificate CA names sent
---
SSL handshake has read 6121 bytes and written 328 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : DHE-RSA-AES256-SHA
    Session-ID: C557C49D71576C23AC61575E93031941E3CF42F87814C433B9275663A578F3C0
    Session-ID-ctx: 
    Master-Key: E15F08E0C06F4AAB5AF18FDFA06D4C300C0462CAA286CAE70C0A46B6EA472A1B3F44CF31D95CE08174D1C28FF2249D96
    Key-Arg   : None
    Start Time: 1428450901
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---