From 78e58376f3c2f073fc6798fcdc305b1b16e7c872 Mon Sep 17 00:00:00 2001 From: Pau Date: Fri, 2 Dec 2016 10:06:03 +0100 Subject: [PATCH] Mysqli: Allow secure connections using SSL The current driver has no option to allow the usage of SSL connections on mysql. I've used the same name params as mysql client. An example of mysql client usage would be: mysql --ssl-ca='path_to_ca.pem' --ssl-cert='path_to_client_cert.pem' --ssl-key='path_to_client_key.pem' refactor secure connection as params remove space add space refactor secure connection rename method rename method docs: add ssl params to use in mysqli driver rename test method refactor method setSecureConnection fix bug add comment to method remove string escaping --- docs/en/reference/configuration.rst | 5 +++ .../DBAL/Driver/Mysqli/MysqliConnection.php | 32 +++++++++++++++++ .../Driver/Mysqli/MysqliConnectionTest.php | 35 ++++++++++++++++++- 3 files changed, 71 insertions(+), 1 deletion(-) diff --git a/docs/en/reference/configuration.rst b/docs/en/reference/configuration.rst index 7122dd1b50b..cce98f6c188 100644 --- a/docs/en/reference/configuration.rst +++ b/docs/en/reference/configuration.rst @@ -235,6 +235,11 @@ mysqli the database. - ``charset`` (string): The charset used when connecting to the database. +- ``ssl_key`` (string): The path name to the key file to use for SSL encryption. +- ``ssl_cert`` (string): The path name to the certificate file to use for SSL encryption. +- ``ssl_ca`` (string): The path name to the certificate authority file to use for SSL encryption. +- ``ssl_capath`` (string): The pathname to a directory that contains trusted SSL CA certificates in PEM format. +- ``ssl_cipher`` (string): A list of allowable ciphers to use for SSL encryption. - ``driverOptions`` Any supported flags for mysqli found on `http://www.php.net/manual/en/mysqli.real-connect.php` pdo\_pgsql diff --git a/lib/Doctrine/DBAL/Driver/Mysqli/MysqliConnection.php b/lib/Doctrine/DBAL/Driver/Mysqli/MysqliConnection.php index ae3502c1682..cff8b15c10e 100644 --- a/lib/Doctrine/DBAL/Driver/Mysqli/MysqliConnection.php +++ b/lib/Doctrine/DBAL/Driver/Mysqli/MysqliConnection.php @@ -63,6 +63,7 @@ public function __construct(array $params, $username, $password, array $driverOp $this->_conn = mysqli_init(); + $this->setSecureConnection($params); $this->setDriverOptions($driverOptions); set_error_handler(function () {}); @@ -263,4 +264,35 @@ public function ping() { return $this->_conn->ping(); } + + /** + * Establish a secure connection + * + * @param array $params + * @throws MysqliException + */ + private function setSecureConnection(array $params) + { + if (! isset($params['ssl_key']) && + ! isset($params['ssl_cert']) && + ! isset($params['ssl_ca']) && + ! isset($params['ssl_capath']) && + ! isset($params['ssl_cipher']) + ) { + return; + } + + if (! isset($params['ssl_key']) || ! isset($params['ssl_cert'])) { + $msg = '"ssl_key" and "ssl_cert" parameters are mandatory when using secure connection parameters.'; + throw new MysqliException($msg); + } + + $this->_conn->ssl_set( + $params['ssl_key'], + $params['ssl_cert'], + $params['ssl_ca'] ?? null, + $params['ssl_capath'] ?? null, + $params['ssl_cipher'] ?? null + ); + } } diff --git a/tests/Doctrine/Tests/DBAL/Driver/Mysqli/MysqliConnectionTest.php b/tests/Doctrine/Tests/DBAL/Driver/Mysqli/MysqliConnectionTest.php index e040ede9911..dd3e7fd151a 100644 --- a/tests/Doctrine/Tests/DBAL/Driver/Mysqli/MysqliConnectionTest.php +++ b/tests/Doctrine/Tests/DBAL/Driver/Mysqli/MysqliConnectionTest.php @@ -2,6 +2,8 @@ namespace Doctrine\Tests\DBAL\Driver\Mysqli; +use Doctrine\DBAL\Driver\Mysqli\MysqliConnection; +use Doctrine\DBAL\Driver\Mysqli\MysqliException; use Doctrine\Tests\DbalTestCase; class MysqliConnectionTest extends DbalTestCase @@ -21,7 +23,7 @@ protected function setUp() parent::setUp(); - $this->connectionMock = $this->getMockBuilder('Doctrine\DBAL\Driver\Mysqli\MysqliConnection') + $this->connectionMock = $this->getMockBuilder(MysqliConnection::class) ->disableOriginalConstructor() ->getMockForAbstractClass(); } @@ -30,4 +32,35 @@ public function testDoesNotRequireQueryForServerVersion() { $this->assertFalse($this->connectionMock->requiresQueryForServerVersion()); } + + /** + * @dataProvider secureMissingParamsProvider + */ + public function testThrowsExceptionWhenMissingMandatorySecureParams(array $secureParams) + { + $this->expectException(MysqliException::class); + $msg = '"ssl_key" and "ssl_cert" parameters are mandatory when using secure connection parameters.'; + $this->expectExceptionMessage($msg); + + new MysqliConnection($secureParams, 'xxx', 'xxx'); + } + + public function secureMissingParamsProvider() + { + return [ + [ + ['ssl_cert' => 'cert.pem'] + ], + [ + ['ssl_key' => 'key.pem'] + ], + [ + ['ssl_key' => 'key.pem', 'ssl_ca' => 'ca.pem', 'ssl_capath' => 'xxx', 'ssl_cipher' => 'xxx'] + ], + [ + ['ssl_ca' => 'ca.pem', 'ssl_capath' => 'xxx', 'ssl_cipher' => 'xxx'] + ] + ]; + } } +