WordPressでの「SSL3_READ_BYTES:sslv3 alert handshake failure」を解決。

 WordPress 3.7 から ca-bundle.crt が含まれるようになったんだが,その後,「Upgrade Network」のときにエラーが出るようになった。ところで,「Warning! Problem updating https://SITENAME.」というのを1つのサイトだけおかしいんだと勘違いしていたのだが,一番初めに調べたサイトでエラーが出てるんだから,あとは調べてないわけだよな(汗)。

 はじめのエラーは,「Error message: SSL certificate problem: self signed certificate in certificate chain」というので,これは自前認証局を使ってるせいだったんだが, Oiram の教えてくれた通り, ca-bundle.crt に自前の CA のデータを書き加えてやったら,よくなった。

 で,次が「“Error message: error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure」。これに2か月以上手を焼いていたが,本日,やっと,解決した \(^o^)/。

 振り返ってみると,結局のところ3つのポイントがあったようだ。

  1. うちの client.crt には ssl_client extension を使っていなかった。で, client.crt を ssl_client extension 付きで作り直した。参考にしたのは, “sslv3 alert handshake failure when using SSL client auth”
    まず, openssl.cnf に次の行を追加した。

    [ ssl_client ]
    basicConstraints = CA:FALSE
    nsCertType = client
    keyUsage = digitalSignature, keyEncipherment
    extendedKeyUsage = clientAuth
    nsComment = “OpenSSL Certificate for SSL Client”

    でもって, ssl_client extension を使って client.crt を作り直した。
    >openssl ca -config openssl.cnf -policy policy_anything -extensions ssl_client -in client.csr -out client.crt

    • 古いほうの client.crt で “openssl s_client -connect o6asan.com:443 -cert client.crt -key client.key -CAfile cacert.pem” をやると,下の2つのエラーが出ていたが,新しいのだと出なくなった。
    • error:14094418:SSL routines:SSL3_READ_BYTES: ~
      error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure: ~
    • 当然ながら, clientcert.p12 も作り直した。
  2. WordPress は「Upgrade Network」のときに cURL を利用しているのだが, cURL は P12 format certificates を受用しないので, PEM format に直さなければ使えない。
    • clientcert.p12 から clientcert.pem を作る
      >openssl pkcs12 -in clientcert.p12 -nokeys -clcerts -out clientcert.pem
    • clientcert.p12 から clientkey.pem を作る。
      >openssl pkcs12 -in clientcert.p12 -nocerts -out clientkey.pem
       
      clientkey.pem のコピーを作り, pass phrase を削除する。
      >copy clientkey.pem cp_clientkey.pem
      >openssl rsa <cp_clientkey.pem> clientkey.pem
  3. WordPress に client 証明書の場所を教えてやる
    • class-http.php の「curl_setopt( $handle, CURLOPT_CAINFO, $r[‘sslcertificates’] );」行の直前に,以下の2行を書き加える。

      curl_setopt( $handle, CURLOPT_SSLCERT, 'clientcert.pem の絶対パス' );
      curl_setopt( $handle, CURLOPT_SSLKEY, 'clientkey.pem の絶対パス' );

      WordPress の core スクリプトを書き換えるのは嫌なので,何とかほかの方法でやろうと頑張ったのだが,どうしてもうまくいかなくて,結局, class-http.php をいじることにした。

      clientcert.pem と clientkey.pem をサーバ上のどこか,外部のものがネット経由でアクセスできない,より安全な場所にコピーする。

    参考サイトは, Client URL Library

 自前認証局の作り方は,「本家のお世話-#68。(WordPress SSL ログイン-#1)」をどうぞ。

 エラーが消えたよ。満足じゃ。パチパチ!!