simplexml_load_file で自己署名証明書を許容する方法

2018-06-16
PHP

結論

simplexml_load_fileを呼び出す前に下記のコードにて、stream_contextを設定してあげればいい。 なお、 'allow_self_signed'=> trueまたは'verify_peer' => falseのいずれかを設定すればOK。

1
2
3
4
5
6
$context = stream_context_create(array('ssl'=>array(
'allow_self_signed'=> true,
'verify_peer' => false,
)));
libxml_set_streams_context($context);
$xml = simplexml_load_file($url);

解説

PHP5.6以降において、OpenSSL関連の処理の変更がありました。

PHP: PHP 5.6.x における OpenSSL 関連の変更 - Manual

暗号化されたすべてのクライアントストリームで、ピア検証がデフォルトで有効になりました。 デフォルトでは、OpenSSL のデフォルト CA バンドルを使ってピア証明書を検証します。 たいていの場合は、正しい SSL 証明書を持つサーバーと通信するならこれを変更する必要はありません。 OpenSSL が、よく知られた CA バンドルを使うように設定されているからです。

そのため、自己署名証明書のURLに対して、simplexml_load_fileを実行するとfalseが返ってくるようになりました。ステージング環境や、本番環境は正式なSSL証明書を使うので問題がないのですが、開発環境などで自己署名証明書を使う場合に困ってました。

あれこれ調べた結果、下記の2つの関数を使って事前にstream_contextを設定してあげれば許容することが出来るというのが分かりました。

PHP: libxml_set_streams_context - Manual

PHP: simplexml_load_file - Manual

PHPソースコードのチェック

php-5.6.36

該当ファイル ext/openssl/xp_ssl.c
該当関数 451 static int apply_peer_verification_policy(SSL *ssl, X509 *peer, php_stream *stream TSRMLS_DC)

1
2
3
463     must_verify_peer = GET_VER_OPT("verify_peer")
464 ? zend_is_true(*val)
465 : sslsock->is_client;

verify_peerの設定がfalseでなければ、基本的にピア検証を行う。

php-5.5.38

該当ファイル ext/openssl/openssl.c
該当関数 4573 int php_openssl_apply_verification_policy(SSL *ssl, X509 *peer, php_stream *stream TSRMLS_DC)

1
2
3
4
4581     /* verification is turned off */
4582 if (!(GET_VER_OPT("verify_peer") && zval_is_true(*val))) {
4583 return SUCCESS;
4584 }

verify_peerの設定がtrueでなければ、ピア検証は行わない。

まとめ

5.6以上で、自己署名証明書を使った開発環境での simplexml_load_file

  • verify_peerfalse -> php5.5 以前と同じ状態

  • allow_self_signedtrue -> 証明書のチェックを行うが、自己署名証明書をOKとする。

のどちらかで許容してあげることができます。

おまけ

5.6以降のPHP7.0, 7.1, 7.2で上記の設定について検証しましたが、問題なく動作しました。