Description:
If the server.pem file in the datadir has an 'Not After' date which is in the past then the server starts without returning an error or warning. However all SSL connections fail.
How to repeat:
Place a set of pem files in the datadir (ca.pem, server-key.pem, server-cert.pem) of which only the server-cert.pem is expired.
The server starts. There is no warning written to the error log.
The only SSL related messages are these:
2017-01-15T12:41:14.705391Z 0 [Note] Found ca.pem, server-cert.pem and server-key.pem in data directory. Trying to enable SSL support using them.
2017-01-15T12:41:14.705765Z 0 [Warning] CA certificate ca.pem is self signed.
Looking at have_ssl everything looks fine..
mysql> show global variables like '%ssl%';
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| have_openssl | YES |
| have_ssl | YES |
| ssl_ca | ca.pem |
| ssl_capath | |
| ssl_cert | server-cert.pem |
| ssl_cipher | |
| ssl_crl | |
| ssl_crlpath | |
| ssl_key | server-key.pem |
+---------------+-----------------+
9 rows in set (0.01 sec)
But the first weird thing is that Ssl_server_not_after remains empty.
mysql> show global status like '%ssl%';
+--------------------------------+---------+
| Variable_name | Value |
+--------------------------------+---------+
| Com_show_processlist | 0 |
| Ssl_accept_renegotiates | 0 |
| Ssl_accepts | 0 |
| Ssl_callback_cache_hits | 0 |
| Ssl_cipher | |
| Ssl_cipher_list | |
| Ssl_client_connects | 0 |
| Ssl_connect_renegotiates | 0 |
| Ssl_ctx_verify_depth | 0 |
| Ssl_ctx_verify_mode | 0 |
| Ssl_default_timeout | 0 |
| Ssl_finished_accepts | 0 |
| Ssl_finished_connects | 0 |
| Ssl_server_not_after | |
| Ssl_server_not_before | |
| Ssl_session_cache_hits | 0 |
| Ssl_session_cache_misses | 0 |
| Ssl_session_cache_mode | Unknown |
| Ssl_session_cache_overflows | 0 |
| Ssl_session_cache_size | 0 |
| Ssl_session_cache_timeouts | 0 |
| Ssl_sessions_reused | 0 |
| Ssl_used_session_cache_entries | 0 |
| Ssl_verify_depth | 0 |
| Ssl_verify_mode | 0 |
| Ssl_version | |
+--------------------------------+---------+
26 rows in set (0.01 sec)
This is a MySQL 5.7.17 build w/ WITH_SSL=bundled (YaSSL).
If I look at a handshake with wireshark I see this:
S → C: Server Greeting (ssl flag set)
C → S: Login Request (ssl flag set)
S → C: Bad handshake
Instead of the 'Bad handshake' I expected the server to start an SSL/TLS handshake with an expired SSL certificate, which the client would then reject.
Suggested fix:
Make sure the ssl context is usable.
Not enabling SSL would have been better than enabling a broken SSL context.
Option 1:
Detect the expired certificate (or unusable SSL context)
Log an error to the error log about that
Disable SSL and startup
Option 2:
Detect the expired certificate
Somehow force loading of the certificate to make the context usable
Log a warning to the error log
Enable SSL and startup
Let the client decide if it wants to trust the certificate (and connection)
Note that 2 is somewhat similar to what happens if the certificate expires while the server is running.
Related to:
Bug #84300 Setting to disable checking of "Not After" for replication with SSL/TLS