PDOを使ってMySQLにSSL接続するパッチ

こんにちは、熊谷です。

PHPからMySQLに接続するドライバはいくつかあります。MySQL拡張モジュールやMySQL改良版拡張モジュール、または抽象化レイヤであるPDOを通して。

最近はPDOを使用して接続するのが一般的なのかなと思ったりするのですが、symfonyを使用する場合、どうしても選択肢はPDOをになってしまいます。今までPDOを使っていて何の問題もなかったのですが、最近一つの問題に突き当たりました。それはMySQLへのSSL接続です。

MySQLは5.0からSSLでの暗号化接続が比較的簡単に行えるようになっています。SSLでの接続方法についてはいろいろ検索すると出てきますので、そちらを参照してください。

そんなMySQLのSSL接続ですが、現時点、PHPから行うにはMySQL改良版拡張モジュールしか対応していないようで、PDOではSSL接続を行うことが出来ません。ということは、symfonyからも出来ないということになり、これは困った状態です。

いろいろ調べてみると、MySQLでSSL接続を行うにはmysql_real_connect()を呼び出す前にmysql_ssl_set()を実行するればいいとのことなので、PDOのMySQLドライバであるpdo_mysqlにそれを実装してみることにしました。実装といってもそんな大がかりなものではなく、mysql_driver.cにそれ用のコードを追加します。


--- mysql_driver.c.orig 2009-09-04 23:10:02.000000000 +0900
+++ mysql_driver.c      2009-09-07 17:37:47.000000000 +0900
@@ -444,6 +444,11 @@
                { "host",   "localhost",        0 },
                { "port",   "3306",     0 },
                { "unix_socket",  PDO_MYSQL_UNIX_ADDR,  0 },
+               { "ssl_key",            NULL,   0 },
+               { "ssl_cert",           NULL,   0 },
+               { "ssl_ca",                     NULL,   0 },
+               { "ssl_ca_path",        NULL,   0 },
+               { "ssl_cipher",         NULL,   0 },
        };
        int connect_opts = 0
 #ifdef CLIENT_MULTI_RESULTS
@@ -454,7 +459,7 @@
 #endif
                ;
 
-       php_pdo_parse_data_source(dbh->data_source, dbh->data_source_len, vars, 5);
+       php_pdo_parse_data_source(dbh->data_source, dbh->data_source_len, vars, 10);
 
        H = pecalloc(1, sizeof(pdo_mysql_db_handle), dbh->is_persistent);
 
@@ -550,6 +555,12 @@
        if (vars[2].optval  & & !strcmp("localhost", vars[2].optval)) {
                unix_socket = vars[4].optval;  
        }
+
+       // SSL connection
+       if(vars[5].optval || vars[6].optval || vars[7].optval || vars[8].optval || vars[9].optval) {
+               mysql_ssl_set(H->server, vars[5].optval, vars[6].optval, vars[7].optval, vars[8].optval, vars[9].optval);
+       }
+
        if (mysql_real_connect(H->server, host, dbh->username, dbh->password, dbname, port, unix_socket, connect_opts) == NULL) {
                pdo_mysql_error(dbh);
                goto cleanup;

そして、phpize、configure、make installで完了です。使い方は、DSNでssl_ca=やssl_cert=等々オプションを指定するだけです。例えば、


<?php
$dsn = 'mysql:host=localhost;dbname=sampledb;ssl_ca=/var/www/sample/config/cacert.pem';
$user = 'user1';
$pass = 'hogehoge';
$pdo = new PDO($dsn, $user, $pass);

というようなコードでMySQLに対してPHPからPDOを通してSSL接続することが可能になります。

PDOでMySQLにSSL接続出来ないよという方は試してみてください。