cURL に HTTPS でアクセスできるように証明書を追加する
ウェブサービスの開発をしていると、プログラムの中で HTTP で通信をするために cURL を使うことが多いと思います。
PHP からも cURL を使うための 便利なライブラリ があります。
普通の HTTP のリクエストを投げる場合は用意されたものをそのまま使えばいいのですが、HTTPS で通信を行いたい場合は、サイトによっては証明書が必要だったりします。
素のままの状態で、例えば https://mixi.jp/ にアクセスすると、次のようなエラーでアクセスすることができません。
% curl 'https://mixi.jp/' curl: (60) SSL certificate problem, verify that the CA cert is OK. Details: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed More details here: http://curl.haxx.se/docs/sslcerts.html curl performs SSL certificate verification by default, using a "bundle" of Certificate Authority (CA) public keys (CA certs). The default bundle is named curl-ca-bundle.crt; you can specify an alternate file using the --cacert option. If this HTTPS server uses a certificate signed by a CA represented in the bundle, the certificate verification probably failed due to a problem with the certificate (it might be expired, or the name might not match the domain name in the URL). If you'd like to turn off curl's verification of the certificate, use the -k (or --insecure) option.
cURL - Details on Server SSL Certificates によると、cURL には初期状態では証明書が入っていないようです。
Until 7.18.0, curl bundled a severely outdated ca bundle file that was installed by default. These days, the curl archives include no ca certs at all. You need to get them elsewhere.
なので、必要に応じて証明書を追加してやります。
上記の cURL のドキュメントによると、証明書を取得する方法はいくつかあるようなのですが、どれもうまくいかなかったので、試行錯誤の結果、うまくいった方法をここに書いておくことにします。
まず、お目当てのページに普通のウェブブラウザでアクセスします。ここでは Mac の Firefox を使うことにします。
ここで、右下にある鍵マークをダブルクリックして、Page Info の窓を出します。
Security タブに View Certificate というボタンがあるので、それをクリックし、詳細画面を出します。
Certificate Fields のどこかをクリックして選択しておいて、左下の Export ボタンをクリックします。
証明書の保存形式を聞かれるので、X.509 Certificate with chain (PEM)を選択します。ここが重要です。
1つ上の X.509 Certificate (PEM) でよさそうですが、これだとうまくかないです。
ただの PEM だと証明書が1つしか入っていませんが、with chain の方だと3つ入っていて、これが何らかの意味があるみたいです。
証明書に適当な名前をつけて保存します。ここでは mixi.crt としておきます。
必要な証明書を入手したら、これを既存の証明書ファイルに追加してやります。
上記の cURL のドキュメントによると、cURL では証明書を一切持っていないと書いてありましたが、FreeBSD の ports や CentOS の rpm で入るパッケージにはいくつかの証明書が入っていました。
FreeBSD の cURL は、証明書を /usr/local/share/curl/curl-ca-bundle.crt から読み込んでいるので、ここに先ほどの mixi.crt を追加してやります。
# cat mixi.crt >> /usr/local/share/curl/curl-ca-bundle.crt
curl-ca-bundle.crt は root でないと書き込めないので、root 権限で作業するなり、一時的のパーミッションを変更するなりして作業をします。
curl-ca-bundle.crt の PATH は cRUL をコンパイルする時にオプションで指定できるようになっていて、システムによって PATH が違う場合があります。
FreeBSD では /usr/local/share/curl/curl-ca-bundle.crt に設定されていて curl の ports パッケージに含まれていましたが、CentOS では /usr/share/ssl/certs/ca-bundle.crt に設定されていて、curl ではなく openssl のパッケージに含まれていました。
curl-ca-bundle.crt の PATH がわからない時には、libcurl.so の中を直接覗いてやると、それらしい文字列が含まれています。
% strings /usr/local/lib/libcurl.so.4 | grep bundle /usr/local/share/curl/curl-ca-bundle.crt
証明書を追加した後では、ちゃんとアクセスできるようになります。
以上、curl で https でアクセスするための証明書を追加する方法でした。



