Description:
In some cases, the error message returned when an SSL operation fails can be incorrect, giving a message such as the following:
SSL connection error: error:00000001:lib(0):func(0):reason(1)
rather than an actual description of the error.
This is a result of confusion between the error code returned from the SSL_get_error() and ERR_get_error() OpenSSL functions. These functions return different types of errors, and have different namespaces.
ssl_should_retry() in vio/viossl.c can set *ssl_errno_holder to an SSL error, rather than an ERR error like other functions. Other places in the code (for example, the client when printing an error message), will call ERR_error_string_n() or similar to produce a string describing the error. As it will receive an SSL error, rather than the expected ERR error, the message will be incorrect (usually a fallback message like the one above).
How to repeat:
This can be shown by trying to connect to a server whose certificate has the wrong CA.
For example, after starting the server with these flags:
--ssl-ca=$MYSQL_TEST_DIR/std_data/crl-ca-cert.pem
--ssl-key=$MYSQL_TEST_DIR/std_data/crl-server-key.pem
--ssl-cert=$MYSQL_TEST_DIR/std_data/crl-server-cert.pem
One can connect to the server with:
$MYSQL --ssl-ca=$MYSQL_TEST_DIR/std_data/cacert.pem test -e "SELECT 1"
The connection will fail with the message:
ERROR 2026 (HY000): SSL connection error: error:00000001:lib(0):func(0):reason(1)
The connection should fail with the message:
ERROR 2026 (HY000): SSL connection error: error:14090086:SSL
routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
These steps can be automated using the mtr test below (the -master.opt file should contain the aforementioned flags; note also that it'll fail for YaSSL):
--source include/have_ssl.inc
--source include/not_embedded.inc
--echo #
--echo # SSL error messages are incorrect
--echo #
--echo # try to connect with correct CA : should connect
--exec $MYSQL --ssl-ca=$MYSQL_TEST_DIR/std_data/crl-ca-cert.pem --ssl-key=$MYSQL_TEST_DIR/std_data/crl-client-key.pem --ssl-cert=$MYSQL_TEST_DIR/std_data/crl-client-cert.pem test -e "SELECT 1" 2>&1
--source include/have_ssl_communication.inc
--echo # try to connect with the wrong CA : should fail with a useful error message
--error 1
--exec $MYSQL --ssl-ca=$MYSQL_TEST_DIR/std_data/cacert.pem test -e "SELECT 1" 2>&1
Suggested fix:
Fix ssl_should_retry() to set *ssl_errno_holder to a correct ERR error, by calling ERR_get_error().
Note that the default case of the switch() over ssl_error does clear ERR with ERR_clear_error(), so ERR_get_error() should be called beforehand.