HTTP_Request2によるクライアント接続
今度、ファイルアップロードを受けるサーバを立ち上げる必要ができた。簡単のためにサーバ側はPHPで記述する。そのサーバをテストする目的で、やはり簡単のためにクライアント側もPHPで記述することにした。
最初HTTP_Requestを使ってみたが、どうもdeprecatedのようで、HTTP_Request2を使えとのメッセージが出ていたので(どこで見たかは忘れた)、HTTP_Request2を使うことにした。
そこでHTTP_Request2を調べてみたが、Web上には余り情報がない。しかも、https接続に関して危険な誤りが多かったので、ここで情報開示する。
設定なし
最も簡単なアップロードスクリプトは以下のようになるだろう。
<?php require_once "HTTP/Request2.php"; $url = "https://xxx.izumi-si.co.jp/server.php"; try { $req = new HTTP_Request2($url,HTTP_Request2::METHOD_POST); $req->setAuth("username","password"); $req->addUpload("key","real_filepath","filename_on_server","mime_type"); $result = $req->send(); echo $result->getBody(); } catch(HTTP_Request2_Exception $e) { die($e->getMessage()); } catch (Exception $e) { die($e->getMessage()); }
ところが、セキュアサイトに接続すると以下のようなエラーが出る。
stream_socket_client(): Failed to enable crypto stream_socket_client(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
これは、証明書が検証できないというエラーである。
間違った対処法
これに対して、ネット上で多く見られた間違った情報は、次のような対処法である。
<?php $req->setConfig(array( 'ssl_verify_peer' => false, ));
確かにこれでエラーはなくなるが、これは根本的に間違っている。それは、この設定が「サーバ証明書を検証しない」ことを表すからであり、これではhttps接続の意義が半減する。
なお、これはHTTP_Request2の例だけでなく、Rubyパッケージの例などについても多く見られた誤りなので、注意されたい。一種のセキュリティーホールと言えなくはない危険な誤りである。
正しい対処法
正しい対処法は以下である。
<?php $req->setConfig(array( 'ssl_verify_peer' => true, 'ssl_capath' => '/etc/ssl/certs', ));
これは、ルートCA証明書を保存したフォルダを設定するものだ。上記のパスはDebian Wheezyのものだが、opensslパッケージで作成される証明書のハッシュが収められたフォルダである。但し、このフォルダにCA証明書そのものが収められているとは限らないので、注意のこと。あくまでも、「証明書」ではなく「証明書のハッシュ」が保存されたフォルダを指定すること。
「ssl_capath」を使用した実例がネット上に少なかったので、あえて開示した。