Maxxer
Maxxer

Reputation: 1097

PHP PDO SSL MySQL connection fails

I'm trying to develop a PHP application which connects to a MySQL server using SSL. I tried using mysql_connect and works fine, but with PDO it does not. When I try to connect I get the following error:

PDO::__construct(): this stream does not support SSL/crypto

What looks strange is that if I tweak cert paths (to point to non existent files) I get the same error!

I'm using php 5.3.10 on Debian Squeeze, the following packages are installed:

php5-cgi 
php5-cli
php5-common
php5-fpm
php5-gd
php5-mcrypt
php5-mysql
php5-suhosin

Any idea? thanks

Upvotes: 4

Views: 4090

Answers (2)

Caleb Pitman
Caleb Pitman

Reputation: 1165

You need php-mysql removed and php-mysqlnd installed. On Centos:

sudo yum remove php-mysql
sudo yum install php-mysqlnd
sudo yum reboot

Ubuntu/Debian

sudo apt-get remove php5-mysql
sudo apt-get install php5-mysqlnd
sudo reboot

mysqli procedural:

$con=mysqli_init();
if (!$con)
  {
  die("mysqli_init failed");
  }

mysqli_ssl_set($con,'/ssl/client-key.pem','/ssl/client-cert.pem', '/ssl/ca.pem',NULL,NULL);

if (!mysqli_real_connect($con,'xx.xxx.xxx.xxx', 'user', 'pass' ,'dbname'))
  {
  die("Connect Error: " . mysqli_connect_error());
  }

mysqli_close($con);
?>

PDO

$ssl = array(
                PDO::MYSQL_ATTR_SSL_KEY    =>'/ssl/client-key.pem',
                PDO::MYSQL_ATTR_SSL_CERT=>'/ssl/client-cert.pem',
                PDO::MYSQL_ATTR_SSL_CA    =>'/ssl/ca.pem'
        );
        try {
                $dbl = new PDO("mysql:host=$host;dbname=$database", $user, $password, $ssl);
                $dbl->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        } catch(PDOException $e) {
echo $e->getMessage();
die;
        }

Your certs paths must be correct. Try this in your SSL to ensure the files are there:

if(file_exists('/ssl/client-key.pem') && file_exists('/ssl/client-cert.pem') && file_exists('/ssl/ca.pem')) echo 'file exists';

The remote host (database server) must also have SSL enabled. Run the query

SHOW VARIABLES LIKE '%ssl%';

OUTPUT:

+---------------+----------------------+
| Variable_name | Value                |
+---------------+----------------------+
| have_openssl  | YES                  |
| have_ssl      | YES                  |
| ssl_ca        | /ssl/ca.pem          |
| ssl_capath    |                      |
| ssl_cert      | /ssl/server-cert.pem |
| ssl_cipher    | DHE-RSA-AES256-SHA   |
| ssl_key       | /ssl/server-key.pem  |
+---------------+----------------------+

If it's disabled, it will not work. Your /etc/my.cnf (or where your my.cnf is located) must contain:

ssl-ca=/ssl/ca.pem
ssl-cert=/ssl/server-cert.pem
ssl-key=/ssl/server-key.pem
ssl-cipher=DHE-RSA-AES256-SHA

MySQL Resource to generate keys: http://dev.mysql.com/doc/refman/5.0/en/creating-ssl-files-using-openssl.html

Lastly, the DHE cipher is not considered safe anymore. Ciphers are continually being broke, so you'll have to find out which are considered secure today.

Upvotes: 2

lll
lll

Reputation: 12889

Your list of modules doesn't include include openssl

You can check the compiled in modules with php -m. And you can check all modules loaded at runtime by running php -a then executing var_dump(get_loaded_extensions());

You will need this to be either compiled in, or loaded as an extension in order to use SSL connectivity.

If the extension exists on disk (check your php extensions directory - location in php.ini) then also check your php.ini for the line extension=php_openssl.so and make sure it is not commented out.

Upvotes: 1

Related Questions