Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
65d56c0
Enable TLS connections in Mysqli driver
andrepereiradasilva Jul 15, 2019
0d331d3
Enable TLS connections in PDO Mysql driver
andrepereiradasilva Jul 15, 2019
06a9396
Add getConnectionEncryption to interface
andrepereiradasilva Jul 15, 2019
5e73c2a
Add getConnectionEncryption() empty method to SqlLite Driver
andrepereiradasilva Jul 15, 2019
4502c64
Add getConnectionEncryption() empty method to Sqlsrv Driver
andrepereiradasilva Jul 15, 2019
c50fe4e
@andrepereiradasilva Add getConnectionEncryption() empty method to Pg…
andrepereiradasilva Jul 15, 2019
233f2ee
Add getConnectionEncryption() method to NoSQL Driver test
andrepereiradasilva Jul 15, 2019
829aa6b
Add getConnectionEncryption methos to driver mock
andrepereiradasilva Jul 15, 2019
55f1fbc
cs line size ...
andrepereiradasilva Jul 15, 2019
367784f
cs line size ...
andrepereiradasilva Jul 15, 2019
ddcadcb
cs again
andrepereiradasilva Jul 15, 2019
5936623
default cipher suit
andrepereiradasilva Jul 15, 2019
66c39cf
static...
andrepereiradasilva Jul 15, 2019
8de2ead
ups
andrepereiradasilva Jul 15, 2019
cbba29a
move tls options to main PDO driver so it's available fro all PDO dri…
andrepereiradasilva Jul 16, 2019
42f7bd8
move tls options to main PDO driver so it's available fro all PDO dri…
andrepereiradasilva Jul 16, 2019
1b61431
Add TLS encryption to postgresql PDO driver (by docs - not tested)
andrepereiradasilva Jul 16, 2019
1a7de1c
cs
andrepereiradasilva Jul 16, 2019
9b5820c
getConnectionEncryption for postgresql (form docs - not tested)
andrepereiradasilva Jul 16, 2019
c4ee862
Update src/Mysql/MysqlDriver.php
andrepereiradasilva Jul 22, 2019
84f5578
Update src/Mysql/MysqlDriver.php
andrepereiradasilva Jul 22, 2019
3da0568
Update src/Mysql/MysqlDriver.php
andrepereiradasilva Jul 22, 2019
19c1564
Update src/Mysql/MysqlDriver.php
andrepereiradasilva Jul 22, 2019
6c26322
Update src/Pdo/PdoDriver.php
andrepereiradasilva Jul 22, 2019
326ac82
Update MysqlDriver.php
andrepereiradasilva Jul 22, 2019
2392206
Update PdoDriver.php
richard67 Aug 6, 2019
2f5242a
Merge pull request #4 from richard67/patch-2
andrepereiradasilva Aug 6, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Tests/Mock/Driver.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public static function create(TestCase $test, $nullDate = '0000-00-00 00:00:00',
'getAffectedRows',
'getCollation',
'getConnectionCollation',
'getConnectionEncryption',
'getConnectors',
'getDateFormat',
'getInstance',
Expand Down
13 changes: 13 additions & 0 deletions Tests/Stubs/nosqldriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,19 @@ public function getConnectionCollation()
return false;
}

/**
* Method to get the database encryption details (cipher and protocol) in use.
*
* @return string The database encryption details.
*
* @since __DEPLOY_VERSION__
* @throws \RuntimeException
*/
public function getConnectionEncryption(): string
{
return '';
}

/**
* Get the number of returned rows for the previous executed SQL statement.
*
Expand Down
9 changes: 9 additions & 0 deletions src/DatabaseInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,15 @@ public function getConnection();
*/
public function getConnectionCollation();

/**
* Method to get the database encryption details (cipher and protocol) in use.
*
* @return string The database encryption details.
*
* @since __DEPLOY_VERSION__
*/
public function getConnectionEncryption(): string;

/**
* Get the total number of SQL statements executed by the database driver.
*
Expand Down
65 changes: 65 additions & 0 deletions src/Mysql/MysqlDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,20 @@ class MysqlDriver extends PdoDriver implements UTF8MB4SupportInterface
*/
protected static $dbMinMariadb = '10.0';

/**
* The default cipher suite for TLS connections.
*
* @var array
* @since __DEPLOY_VERSION__
*/
protected static $defaultCipherSuite = [
'AES128-GCM-SHA256',
'AES256-GCM-SHA384',
'AES128-CBC-SHA256',
'AES256-CBC-SHA384',
'DES-CBC3-SHA',
];

/**
* Constructor.
*
Expand Down Expand Up @@ -132,6 +146,34 @@ public function connect()
return;
}

// For SSL/TLS connection encryption.
if ($this->options['ssl'] !== [] && $this->options['ssl']['enable'] === true)
{
$sslContextIsNull = true;

// If customised, add cipher suite, ca file path, ca path, private key file path and certificate file path to PDO driver options.
foreach (['cipher', 'ca', 'capath', 'key', 'cert'] as $key => $value)
{
if ($this->options['ssl'][$value] !== null)
{
$this->options['driverOptions'][constant('\PDO::MYSQL_ATTR_SSL_' . strtoupper($value))] = $this->options['ssl'][$value];
$sslContextIsNull = false;
}
}

// PDO, if no cipher, ca, capath, cert and key are set, can't start TLS one-way connection, set a common ciphers suite to force it.
if ($sslContextIsNull === true)
{
$this->options['driverOptions'][\PDO::MYSQL_ATTR_SSL_CIPHER] = implode(':', static::$defaultCipherSuite);
}

// If customised, for capable systems (PHP 7.0.14+ and 7.1.4+) verify certificate chain and Common Name to driver options.
if ($this->options['ssl']['verify_server_cert'] !== null && defined('\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT'))
{
$this->options['driverOptions'][\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = $this->options['ssl']['verify_server_cert'];
}
}

try
{
// Try to connect to MySQL
Expand Down Expand Up @@ -296,6 +338,29 @@ public function getConnectionCollation()
return $this->setQuery('SELECT @@collation_connection;')->loadResult();
}

/**
* Method to get the database encryption details (cipher and protocol) in use.
*
* @return string The database encryption details.
*
* @since __DEPLOY_VERSION__
* @throws \RuntimeException
*/
public function getConnectionEncryption(): string
{
$this->connect();

$variables = $this->setQuery('SHOW SESSION STATUS WHERE `Variable_name` IN (\'Ssl_version\', \'Ssl_cipher\')')
->loadObjectList('Variable_name');

if (!empty($variables['Ssl_cipher']->Value))
{
return $variables['Ssl_version']->Value . ' (' . $variables['Ssl_cipher']->Value . ')';
}

return '';
}

/**
* Return the query string to create new Database.
*
Expand Down
78 changes: 77 additions & 1 deletion src/Mysqli/MysqliDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,18 @@ public function __construct(array $options)
$options['socket'] = $options['socket'] ?? null;
$options['utf8mb4'] = isset($options['utf8mb4']) ? (bool) $options['utf8mb4'] : false;
$options['sqlModes'] = isset($options['sqlModes']) ? (array) $options['sqlModes'] : $sqlModes;
$options['ssl'] = isset($options['ssl']) ? $options['ssl'] : [];

if ($options['ssl'] !== [])
{
$options['ssl']['enable'] = isset($options['ssl']['enable']) ? $options['ssl']['enable'] : false;
$options['ssl']['cipher'] = isset($options['ssl']['cipher']) ? $options['ssl']['cipher'] : null;
$options['ssl']['ca'] = isset($options['ssl']['ca']) ? $options['ssl']['ca'] : null;
$options['ssl']['capath'] = isset($options['ssl']['capath']) ? $options['ssl']['capath'] : null;
$options['ssl']['key'] = isset($options['ssl']['key']) ? $options['ssl']['key'] : null;
$options['ssl']['cert'] = isset($options['ssl']['cert']) ? $options['ssl']['cert'] : null;
$options['ssl']['verify_server_cert'] = isset($options['ssl']['verify_server_cert']) ? $options['ssl']['verify_server_cert'] : null;
}

// Finalize initialisation.
parent::__construct($options);
Expand Down Expand Up @@ -211,9 +223,50 @@ public function connect()

$this->connection = mysqli_init();

$connectionFlags = 0;

// For SSL/TLS connection encryption.
if ($this->options['ssl'] !== [] && $this->options['ssl']['enable'] === true)
{
$connectionFlags += MYSQLI_CLIENT_SSL;

// Verify server certificate is only availble in PHP 5.6.16+. See https://www.php.net/ChangeLog-5.php#5.6.16
if (isset($this->options['ssl']['verify_server_cert']))
{
// New constants in PHP 5.6.16+. See https://www.php.net/ChangeLog-5.php#5.6.16
if ($this->options['ssl']['verify_server_cert'] === true && defined('MYSQLI_CLIENT_SSL_VERIFY_SERVER_CERT'))
{
$connectionFlags += MYSQLI_CLIENT_SSL_VERIFY_SERVER_CERT;
}
elseif ($this->options['ssl']['verify_server_cert'] === false && defined('MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT'))
{
$connectionFlags += MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT;
}
elseif (defined('MYSQLI_OPT_SSL_VERIFY_SERVER_CERT'))
{
$this->connection->options(MYSQLI_OPT_SSL_VERIFY_SERVER_CERT, $this->options['ssl']['verify_server_cert']);
}
}

// Add SSL/TLS options only if changed.
$this->connection->ssl_set(
$this->options['ssl']['key'],
$this->options['ssl']['cert'],
$this->options['ssl']['ca'],
$this->options['ssl']['capath'],
$this->options['ssl']['cipher']
);
}

// Attempt to connect to the server, use error suppression to silence warnings and allow us to throw an Exception separately.
$connected = @$this->connection->real_connect(
$this->options['host'], $this->options['user'], $this->options['password'], null, $this->options['port'], $this->options['socket']
$this->options['host'],
$this->options['user'],
$this->options['password'],
null,
$this->options['port'],
$this->options['socket'],
$connectionFlags
);

if (!$connected)
Expand Down Expand Up @@ -408,6 +461,29 @@ public function getConnectionCollation()
return $this->setQuery('SELECT @@collation_connection;')->loadResult();
}

/**
* Method to get the database encryption details (cipher and protocol) in use.
*
* @return string The database encryption details.
*
* @since __DEPLOY_VERSION__
* @throws \RuntimeException
*/
public function getConnectionEncryption(): string
{
$this->connect();

$variables = $this->setQuery('SHOW SESSION STATUS WHERE `Variable_name` IN (\'Ssl_version\', \'Ssl_cipher\')')
->loadObjectList('Variable_name');

if (!empty($variables['Ssl_cipher']->Value))
{
return $variables['Ssl_version']->Value . ' (' . $variables['Ssl_cipher']->Value . ')';
}

return '';
}

/**
* Return the query string to create new Database.
*
Expand Down
42 changes: 42 additions & 0 deletions src/Pdo/PdoDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,18 @@ public function __construct(array $options)
$options['port'] = isset($options['port']) ? (int) $options['port'] : null;
$options['password'] = $options['password'] ?? '';
$options['driverOptions'] = $options['driverOptions'] ?? [];
$options['ssl'] = isset($options['ssl']) ? $options['ssl'] : [];

if ($options['ssl'] !== [])
{
$options['ssl']['enable'] = isset($options['ssl']['enable']) ? $options['ssl']['enable'] : false;
$options['ssl']['cipher'] = isset($options['ssl']['cipher']) ? $options['ssl']['cipher'] : null;
$options['ssl']['ca'] = isset($options['ssl']['ca']) ? $options['ssl']['ca'] : null;
$options['ssl']['capath'] = isset($options['ssl']['capath']) ? $options['ssl']['capath'] : null;
$options['ssl']['key'] = isset($options['ssl']['key']) ? $options['ssl']['key'] : null;
$options['ssl']['cert'] = isset($options['ssl']['cert']) ? $options['ssl']['cert'] : null;
$options['ssl']['verify_server_cert'] = isset($options['ssl']['verify_server_cert']) ? $options['ssl']['verify_server_cert'] : null;
}

// Finalize initialisation
parent::__construct($options);
Expand Down Expand Up @@ -253,6 +265,36 @@ public function connect()
$replace = ['#HOST#', '#PORT#', '#DBNAME#'];
$with = [$this->options['host'], $this->options['port'], $this->options['database']];

// For data in transit TLS encryption.
if ($this->options['ssl'] !== [] && $this->options['ssl']['enable'] === true)
{
if (isset($this->options['ssl']['verify_server_cert']) && $this->options['ssl']['verify_server_cert'] === true)
{
$format .= ';sslmode=verify-full';
}
else
{
$format .= ';sslmode=require';
}

$sslKeysMapping = [
'cipher' => null,
'ca' => 'sslrootcert',
'capath' => null,
'key' => 'sslkey',
'cert' => 'sslcert',
];

// If customised, add cipher suite, ca file path, ca path, private key file path and certificate file path to PDO driver options.
foreach ($sslKeysMapping as $key => $value)
{
if ($value !== null && $this->options['ssl'][$key] !== null)
{
$format .= ';' . $value . '=' . $this->options['ssl'][$key];
}
}
}

break;

case 'sqlite':
Expand Down
25 changes: 25 additions & 0 deletions src/Pgsql/PgsqlDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,31 @@ public function getConnectionCollation()
return $array[0]['lc_collate'];
}

/**
* Method to get the database encryption details (cipher and protocol) in use.
*
* @return string The database encryption details.
*
* @since __DEPLOY_VERSION__
* @throws \RuntimeException
*/
public function getConnectionEncryption(): string
{
$query = $this->getQuery(true)
->select($this->quoteName(['version', 'cipher']))
->from($this->quoteName('pg_stat_ssl'))
->where($this->quoteName('pid') . ' = pg_backend_pid()');

$variables = $this->setQuery($query)->loadAssoc();

if (!empty($variables['cipher']))
{
return $variables['version'] . ' (' . $variables['cipher'] . ')';
}

return '';
}

/**
* Shows the table CREATE statement that creates the given tables.
*
Expand Down
14 changes: 14 additions & 0 deletions src/Sqlite/SqliteDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,20 @@ public function getConnectionCollation()
return $this->charset;
}

/**
* Method to get the database encryption details (cipher and protocol) in use.
*
* @return string The database encryption details.
*
* @since __DEPLOY_VERSION__
* @throws \RuntimeException
*/
public function getConnectionEncryption(): string
{
// TODO: Not fake this
return '';
}

/**
* Shows the table CREATE statement that creates the given tables.
*
Expand Down
14 changes: 14 additions & 0 deletions src/Sqlsrv/SqlsrvDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,20 @@ public function getConnectionCollation()
return 'MSSQL UTF-8 (UCS2)';
}

/**
* Method to get the database encryption details (cipher and protocol) in use.
*
* @return string The database encryption details.
*
* @since __DEPLOY_VERSION__
* @throws \RuntimeException
*/
public function getConnectionEncryption(): string
{
// TODO: Not fake this
return '';
}

/**
* Retrieves field information about the given tables.
*
Expand Down