From f614af210f293ad0da15b78331506f369caacc81 Mon Sep 17 00:00:00 2001 From: Pali Date: Sat, 15 Apr 2017 13:58:03 +0200 Subject: [PATCH] Add new database handle attribute mysql_ssl_cipher It returns SSL encryption cipher or undef if SSL is not used. It can be used by application to check if SSL was established or not. --- MANIFEST | 1 + dbdimp.c | 8 ++++++++ lib/DBD/mysql.pm | 28 +++++++++++++++++++++------- t/92ssl_connection.t | 30 ++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 7 deletions(-) create mode 100644 t/92ssl_connection.t diff --git a/MANIFEST b/MANIFEST index 1fe8141d..64f2057d 100644 --- a/MANIFEST +++ b/MANIFEST @@ -72,6 +72,7 @@ t/88async-multi-stmts.t t/89async-method-check.t t/90utf8_params.t t/91errcheck.t +t/92ssl_connection.t t/92ssl_optional.t t/92ssl_backronym_vulnerability.t t/92ssl_riddle_vulnerability.t diff --git a/dbdimp.c b/dbdimp.c index f8668b7d..2d03d202 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -3015,6 +3015,14 @@ SV* dbd_db_FETCH_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv) result= serverinfo ? sv_2mortal(newSVpvn(serverinfo, strlen(serverinfo))) : &PL_sv_undef; } +#if ((MYSQL_VERSION_ID >= 50023 && MYSQL_VERSION_ID < 50100) || MYSQL_VERSION_ID >= 50111) + else if (kl == 10 && strEQ(key, "ssl_cipher")) + { + const char* ssl_cipher = mysql_get_ssl_cipher(imp_dbh->pmysql); + result= ssl_cipher ? + sv_2mortal(newSVpvn(ssl_cipher, strlen(ssl_cipher))) : &PL_sv_undef; + } +#endif else if (kl == 13 && strEQ(key, "serverversion")) result= sv_2mortal(my_ulonglong2sv(aTHX_ mysql_get_server_version(imp_dbh->pmysql))); else if (strEQ(key, "sock")) diff --git a/lib/DBD/mysql.pm b/lib/DBD/mysql.pm index 468c3c85..c060395f 100644 --- a/lib/DBD/mysql.pm +++ b/lib/DBD/mysql.pm @@ -1446,18 +1446,19 @@ handles (read only): $errno = $dbh->{'mysql_errno'}; $error = $dbh->{'mysql_error'}; - $info = $dbh->{'mysql_hostinfo'}; + $hostinfo = $dbh->{'mysql_hostinfo'}; $info = $dbh->{'mysql_info'}; $insertid = $dbh->{'mysql_insertid'}; - $info = $dbh->{'mysql_protoinfo'}; - $info = $dbh->{'mysql_serverinfo'}; - $info = $dbh->{'mysql_stat'}; - $threadId = $dbh->{'mysql_thread_id'}; + $protoinfo = $dbh->{'mysql_protoinfo'}; + $serverinfo = $dbh->{'mysql_serverinfo'}; + $ssl_cipher = $dbh->{'mysql_ssl_cipher'}; + $stat = $dbh->{'mysql_stat'}; + $thread_id = $dbh->{'mysql_thread_id'}; These correspond to mysql_errno(), mysql_error(), mysql_get_host_info(), mysql_info(), mysql_insert_id(), mysql_get_proto_info(), -mysql_get_server_info(), mysql_stat() and mysql_thread_id(), -respectively. +mysql_get_server_info(), mysql_stat(), mysql_get_ssl_cipher() +and mysql_thread_id() respectively. =over 2 @@ -1482,6 +1483,19 @@ against: 50200 +=item mysql_ssl_cipher + +Returns the SSL encryption cipher used for the given connection to +the server. In case SSL encryption was not enabled with C +or was not established returns undef. + + my $ssl_cipher = $dbh->{mysql_ssl_cipher}; + if (defined $ssl_cipher) { + print "Connection with server is encrypted with cipher: $ssl_cipher\n"; + } else { + print "Connection with server is not encrypted\n"; + } + =item mysql_dbd_stats $info_hashref = $dhb->{mysql_dbd_stats}; diff --git a/t/92ssl_connection.t b/t/92ssl_connection.t new file mode 100644 index 00000000..9819b3bd --- /dev/null +++ b/t/92ssl_connection.t @@ -0,0 +1,30 @@ +use strict; +use warnings; + +use Test::More; +use DBI; + +use vars qw($test_dsn $test_user $test_password); +use lib 't', '.'; +require "lib.pl"; + +my $dbh = DbiTestConnect($test_dsn, $test_user, $test_password, { PrintError => 0, RaiseError => 1 }); +my $have_ssl = eval { $dbh->selectrow_hashref("SHOW VARIABLES WHERE Variable_name = 'have_ssl'") }; +$dbh->disconnect(); +plan skip_all => 'Server does not support SSL connections' unless $have_ssl and $have_ssl->{Value} eq 'YES'; + +plan tests => 4; + +$dbh = DBI->connect($test_dsn, $test_user, $test_password, { PrintError => 0, RaiseError => 0, mysql_ssl => 1, mysql_ssl_optional => 1 }); +ok(defined $dbh, 'DBD::mysql supports mysql_ssl=1 with mysql_ssl_optional=1 and connect to server') or diag('Error code: ' . ($DBI::err || 'none') . "\n" . 'Error message: ' . ($DBI::errstr || 'unknown')); + +ok(defined $dbh && defined $dbh->{mysql_ssl_cipher}, 'SSL connection was established') and diag("mysql_ssl_cipher is: ". $dbh->{mysql_ssl_cipher}); + +$dbh = DBI->connect($test_dsn, $test_user, $test_password, { PrintError => 0, RaiseError => 0, mysql_ssl => 1 }); +if (defined $dbh) { + pass('DBD::mysql supports mysql_ssl=1 without mysql_ssl_optional=1 and connect to server'); + ok(defined $dbh->{mysql_ssl_cipher}, 'SSL connection was established'); +} else { + is($DBI::errstr, 'SSL connection error: Enforcing SSL encryption is not supported', 'DBD::mysql supports mysql_ssl=1 without mysql_ssl_optional=1 and fail because cannot enforce SSL encryption') or diag('Error message: ' . ($DBI::errstr || 'unknown')); + is($DBI::err, 2026, 'DBD::mysql error code is SSL related') or diag('Error code: ' . ($DBI::err || 'unknown')); +}