summaryrefslogtreecommitdiffstats
path: root/src/lib/mysql
diff options
context:
space:
mode:
authorAndrei Pavel <andrei@isc.org>2024-05-17 11:17:12 +0200
committerAndrei Pavel <andrei@isc.org>2024-05-20 22:28:17 +0200
commit934d8276fa0ddfabc2da847d00eac5e7f96542ca (patch)
tree202804ee9d0c19cd6cfa41410855be3d84de3c24 /src/lib/mysql
parent[#3256] convert mysql_ssl_set to mysql_options (diff)
downloadkea-934d8276fa0ddfabc2da847d00eac5e7f96542ca.tar.xz
kea-934d8276fa0ddfabc2da847d00eac5e7f96542ca.zip
[#3256] check result of mysql_options
... and throw exception if result is unfortunate. ... and check exceptions thrown in unit tests because it is important now to distinguish that the old exceptions are thrown instead of the new.
Diffstat (limited to 'src/lib/mysql')
-rw-r--r--src/lib/mysql/mysql_connection.cc28
-rw-r--r--src/lib/mysql/tests/mysql_connection_unittest.cc109
2 files changed, 115 insertions, 22 deletions
diff --git a/src/lib/mysql/mysql_connection.cc b/src/lib/mysql/mysql_connection.cc
index 8a78c4c844..84523d8b79 100644
--- a/src/lib/mysql/mysql_connection.cc
+++ b/src/lib/mysql/mysql_connection.cc
@@ -237,12 +237,30 @@ MySqlConnection::openDatabase() {
// If TLS is enabled set it. If something should go wrong it will happen
// later at the mysql_real_connect call.
if (tls_) {
- mysql_options(mysql_, MYSQL_OPT_SSL_KEY, key_file);
- mysql_options(mysql_, MYSQL_OPT_SSL_CERT, cert_file);
- mysql_options(mysql_, MYSQL_OPT_SSL_CA, ca_file);
- mysql_options(mysql_, MYSQL_OPT_SSL_CAPATH, ca_dir);
- mysql_options(mysql_, MYSQL_OPT_SSL_CIPHER, cipher_list);
+ result = mysql_options(mysql_, MYSQL_OPT_SSL_KEY, key_file);
+ if (result != 0) {
+ isc_throw(DbOpenError, "unable to set key: " << mysql_error(mysql_));
+ }
+ result = mysql_options(mysql_, MYSQL_OPT_SSL_CERT, cert_file);
+ if (result != 0) {
+ isc_throw(DbOpenError, "unable to set certificate: " << mysql_error(mysql_));
+ }
+
+ result = mysql_options(mysql_, MYSQL_OPT_SSL_CA, ca_file);
+ if (result != 0) {
+ isc_throw(DbOpenError, "unable to set CA: " << mysql_error(mysql_));
+ }
+
+ result = mysql_options(mysql_, MYSQL_OPT_SSL_CAPATH, ca_dir);
+ if (result != 0) {
+ isc_throw(DbOpenError, "unable to set CA path: " << mysql_error(mysql_));
+ }
+
+ result = mysql_options(mysql_, MYSQL_OPT_SSL_CIPHER, cipher_list);
+ if (result != 0) {
+ isc_throw(DbOpenError, "unable to set cipher: " << mysql_error(mysql_));
+ }
}
// Open the database.
diff --git a/src/lib/mysql/tests/mysql_connection_unittest.cc b/src/lib/mysql/tests/mysql_connection_unittest.cc
index 8ac4e13c5c..0591192ab7 100644
--- a/src/lib/mysql/tests/mysql_connection_unittest.cc
+++ b/src/lib/mysql/tests/mysql_connection_unittest.cc
@@ -609,8 +609,10 @@ TEST_F(MySqlConnectionTest, transactions) {
EXPECT_EQ("4", result[0][0]);
// Committing or rolling back a not started transaction is a coding error.
- EXPECT_THROW(conn_.commit(), isc::Unexpected);
- EXPECT_THROW(conn_.rollback(), isc::Unexpected);
+ EXPECT_THROW_MSG(conn_.commit(), isc::Unexpected,
+ "commit called for not started transaction - coding error");
+ EXPECT_THROW_MSG(conn_.rollback(), isc::Unexpected,
+ "rollback called for not started transaction - coding error");
}
// Tests that invalid port value causes an error.
@@ -619,7 +621,8 @@ TEST_F(MySqlConnectionTest, portInvalid) {
VALID_HOST_TCP, VALID_USER,
VALID_PASSWORD, INVALID_PORT_1);
MySqlConnection conn(DatabaseConnection::parse(conn_str));
- EXPECT_THROW(conn.openDatabase(), DbInvalidPort);
+ EXPECT_THROW_MSG(conn.openDatabase(), DbInvalidPort,
+ "port parameter (65536) must be an integer between 0 and 65535");
}
// Tests that invalid timeout value type causes an error.
@@ -628,7 +631,8 @@ TEST_F(MySqlConnectionTest, connectionTimeoutInvalid) {
VALID_HOST_TCP, VALID_USER,
VALID_PASSWORD, INVALID_TIMEOUT_1);
MySqlConnection conn(DatabaseConnection::parse(conn_str));
- EXPECT_THROW(conn.openDatabase(), DbInvalidTimeout);
+ EXPECT_THROW_MSG(conn.openDatabase(), DbInvalidTimeout,
+ "connect-timeout parameter (foo) must be an integer between 1 and 2147483647");
}
// Tests that a negative connection timeout value causes an error.
@@ -637,7 +641,8 @@ TEST_F(MySqlConnectionTest, connectionTimeoutInvalid2) {
VALID_HOST_TCP, VALID_USER,
VALID_PASSWORD, INVALID_TIMEOUT_2);
MySqlConnection conn(DatabaseConnection::parse(conn_str));
- EXPECT_THROW(conn.openDatabase(), DbInvalidTimeout);
+ EXPECT_THROW_MSG(conn.openDatabase(), DbInvalidTimeout,
+ "connect-timeout parameter (-17) must be an integer between 1 and 2147483647");
}
// Tests that a zero connection timeout value causes an error.
@@ -646,7 +651,8 @@ TEST_F(MySqlConnectionTest, connectionTimeoutInvalid3) {
VALID_HOST_TCP, VALID_USER,
VALID_PASSWORD, INVALID_TIMEOUT_3);
MySqlConnection conn(DatabaseConnection::parse(conn_str));
- EXPECT_THROW(conn.openDatabase(), DbInvalidTimeout);
+ EXPECT_THROW_MSG(conn.openDatabase(), DbInvalidTimeout,
+ "connect-timeout parameter (0) must be an integer between 1 and 2147483647");
}
// Tests that an invalid read timeout causes an error.
@@ -655,7 +661,8 @@ TEST_F(MySqlConnectionTest, readTimeoutInvalid) {
VALID_HOST_TCP, VALID_USER,
VALID_PASSWORD, INVALID_READ_TIMEOUT_1);
MySqlConnection conn(DatabaseConnection::parse(conn_str));
- EXPECT_THROW(conn.openDatabase(), DbInvalidTimeout);
+ EXPECT_THROW_MSG(conn.openDatabase(), DbInvalidTimeout,
+ "read-timeout parameter (bar) must be an integer between 0 and 2147483647");
}
// Tests that an invalid write timeout causes an error.
@@ -664,7 +671,8 @@ TEST_F(MySqlConnectionTest, writeTimeoutInvalid) {
VALID_HOST_TCP, VALID_USER,
VALID_PASSWORD, INVALID_WRITE_TIMEOUT_1);
MySqlConnection conn(DatabaseConnection::parse(conn_str));
- EXPECT_THROW(conn.openDatabase(), DbInvalidTimeout);
+ EXPECT_THROW_MSG(conn.openDatabase(), DbInvalidTimeout,
+ "write-timeout parameter (baz) must be an integer between 0 and 2147483647");
}
#ifdef HAVE_MYSQL_GET_OPTION
@@ -875,7 +883,24 @@ TEST_F(MySqlSecureConnectionTest, TlsInvalidPassword) {
VALID_CERT, VALID_KEY, VALID_CA,
VALID_CIPHER);
MySqlConnection conn(DatabaseConnection::parse(conn_str));
- EXPECT_THROW(conn.openDatabase(), DbOpenError);
+
+ try {
+ conn.openDatabase();
+ } catch (DbOpenError const& exception) {
+ string const message(exception.what());
+ vector<string> const expected{
+ "TLS/SSL error: No or insufficient priorities were set.", // OpenSSL 1.1.1n
+ "Access denied for user 'keatest_secure'",
+ };
+ for (string const& i : expected) {
+ if (message.find(i) != string::npos) {
+ return;
+ }
+ }
+ ADD_FAILURE() << "Unexpected exception message '" << message << "'";
+ } catch (exception const& exception) {
+ ADD_FAILURE() << exception.what();
+ }
}
/// @brief Check the SSL/TLS protected connection requires crypto parameters.
@@ -885,7 +910,19 @@ TEST_F(MySqlSecureConnectionTest, TlsNoCrypto) {
VALID_HOST_TCP, VALID_SECURE_USER,
VALID_PASSWORD);
MySqlConnection conn(DatabaseConnection::parse(conn_str));
- EXPECT_THROW(conn.openDatabase(), DbOpenError);
+
+ try {
+ conn.openDatabase();
+ } catch (DbOpenError const& exception) {
+ string const message(exception.what());
+ string const expected("Access denied for user 'keatest_secure'");
+ if (message.find(expected) == string::npos) {
+ ADD_FAILURE()
+ << "Expected exception message '" << expected << ".*', got '" << message << "'";
+ }
+ } catch (exception const& exception) {
+ ADD_FAILURE() << exception.what();
+ }
}
/// @brief Check the SSL/TLS protected connection requires valid key.
@@ -897,7 +934,22 @@ TEST_F(MySqlSecureConnectionTest, TlsInvalidKey) {
VALID_CERT, INVALID_KEY, VALID_CA,
VALID_CIPHER);
MySqlConnection conn(DatabaseConnection::parse(conn_str));
- EXPECT_THROW(conn.openDatabase(), DbOpenError);
+
+ try {
+ conn.openDatabase();
+ } catch (DbOpenError const& exception) {
+ string const message(exception.what());
+ vector<string> const expected{
+ "TLS/SSL error: The certificate and the given key do not match.", // OpenSSL 1.1.1n
+ "SSL connection error: Unable to get private key", // OpenSSL 3.0.2
+ "TLS/SSL error: key values mismatch", // OpenSSL 3.3.0
+ };
+ if (!std::count(expected.begin(), expected.end(), message)) {
+ ADD_FAILURE() << "Unexpected exception message '" << message << "'";
+ }
+ } catch (exception const& exception) {
+ ADD_FAILURE() << exception.what();
+ }
}
/// @brief Check the SSL/TLS protected connection requires a key.
@@ -909,7 +961,24 @@ TEST_F(MySqlSecureConnectionTest, TlsNoKey) {
VALID_CERT, 0, VALID_CA,
VALID_CIPHER);
MySqlConnection conn(DatabaseConnection::parse(conn_str));
- EXPECT_THROW(conn.openDatabase(), DbOpenError);
+
+ try {
+ conn.openDatabase();
+ } catch (DbOpenError const& exception) {
+ string const message(exception.what());
+ vector<string> const expected{
+ "TLS/SSL error: The requested data were not available.", // OpenSSL 1.1.1n
+ "TLS/SSL error: no start line", // OpenSSL 1.1.1w
+ "SSL connection error: Unable to get private key", // OpenSSL 3.0.2
+ "TLS/SSL error: no certificate assigned", // OpenSSL 3.0.9
+ "TLS/SSL error: unsupported", // OpenSSL 3.3.0
+ };
+ if (!std::count(expected.begin(), expected.end(), message)) {
+ ADD_FAILURE() << "Unexpected exception message '" << message << "'";
+ }
+ } catch (exception const& exception) {
+ ADD_FAILURE() << exception.what();
+ }
}
/// @brief Check ensureSchemaVersion when schema is not created.
@@ -1016,11 +1085,17 @@ TEST_F(MySqlConnectionTest, toKeaAdminParameters) {
/// mysql_options() directly, omitting calls for those options for which the option value is NULL.
TEST_F(MySqlConnectionTest, mysqlOptions) {
MySqlHolder mysql;
- mysql_options(mysql, MYSQL_OPT_SSL_KEY, nullptr);
- mysql_options(mysql, MYSQL_OPT_SSL_CERT, nullptr);
- mysql_options(mysql, MYSQL_OPT_SSL_CA, nullptr);
- mysql_options(mysql, MYSQL_OPT_SSL_CAPATH, nullptr);
- mysql_options(mysql, MYSQL_OPT_SSL_CIPHER, nullptr);
+ int result;
+ EXPECT_NO_THROW_LOG(result = mysql_options(mysql, MYSQL_OPT_SSL_KEY, nullptr));
+ EXPECT_EQ(0, result);
+ EXPECT_NO_THROW_LOG(result = mysql_options(mysql, MYSQL_OPT_SSL_CERT, nullptr));
+ EXPECT_EQ(0, result);
+ EXPECT_NO_THROW_LOG(result = mysql_options(mysql, MYSQL_OPT_SSL_CA, nullptr));
+ EXPECT_EQ(0, result);
+ EXPECT_NO_THROW_LOG(result = mysql_options(mysql, MYSQL_OPT_SSL_CAPATH, nullptr));
+ EXPECT_EQ(0, result);
+ EXPECT_NO_THROW_LOG(result = mysql_options(mysql, MYSQL_OPT_SSL_CIPHER, nullptr));
+ EXPECT_EQ(0, result);
}
} // namespace