- Added TLSv1.3 ciphers to cipher map.
- Fixed retrieval of cipher suite: Since gnutls_cipher_suite_get_name
supports only TLSv1.2 (and lower) cipher suites, we have to call
gnutls_ciphersuite_get() (requires GnuTLS 3.7.4 or newer).
- moved fingerprint verification to ma_tls.c
- don't verify cert again if fingerprint check
succeeded.
- Disable self signed check in fingerprint tests
(Schannel only).
* fix comments
* reorder errors to put hard errors on top
* report errors from openssl
* don't overwrite errors in C/C
* pass correct flags to gnutls_x509_crt_check_hostname2()
* use the same define name everywhere consistently
* don't recalculate fingerprint in openssl unnecessary
* misc
Peer certificate validation:
Since version 3.4 peer certificate verification is enabled by default.
It can be disabled via `mysql_optionsv`, using option
MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
my_bool verify= 0;
mysql_options(mariadb, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &verify);
Self signed certificates
If the client obtained a self signed peer certificate from MariaDB server
the verification will fail, with the following exceptions:
* If the connection between client and server is considered to be secure:, e.g.
* a unix_socket is used for client server communication
* hostname is localhost (Windows operating system), 127.0.0.1 or ::1
* a specified fingerprint matches the fingerprint of the peer certificate (see below)
* a client can verify the certificate using account password, it's possible if
* account has a password
* authentication plugin is "secure without TLS", that is, one of
mysql_native_password, ed25519 or parsec.
Fingerprint verification of the peer certificate
A fingerprint is a cryptographic hash (SHA-256, SHA-384 or SHA-512) of the peer
certificate's binary data. Even if the fingerprint matches, an expired or
revoked certificate will not be accepted.
For security reasons support for MD5 and SHA1 has been removed.
Technical details:
==================
- Peer certificate verification call was removed from ma_tls_connect, instead it
will be called directly after the handshake succeeded (my_auth.c)
- mysql->net.tls_self_signed_error was replaced by mysql->net.tls_verify_status which
contains the result of the peer certfificate verification:
The verification status can be obtained with mariadb_get_infov using new parameter
MARIADB_TLS_VERIFY_STATUS.
unsigned int tls_verify_status;
mariadb_get_infov(mysql, MARIADB_TLS_VERIFY_STATUS, &tls_verify_status);
The result is a combination of the following flags:
MARIADB_TLS_VERIFY_OK 0
MARIADB_TLS_VERIFY_TRUST 1
MARIADB_TLS_VERIFY_HOST 2
MARIADB_TLS_VERIFY_PERIOD 4
MARIADB_TLS_VERIFY_FINGERPRINT 8
MARIADB_TLS_VERIFY_REVOKED 16
MARIADB_TLS_VERIFY_UNKNOWN 32
- GnuTLS peer certificate verification callback was removed and replaced by
gnutls_verify_peers2() api function, so the peer certificate validation
will happen after handshake.
- OpenSSL implementation will no longer use SSL_verify_result to check the
validity of the peer certificate. Instead a callback function will be called
during the handshake, which collects all certificate validation errors.
- If the peer certificate is not trusted, hostname verification will be
skipped.
- Testing
Added new test tls, which implements a python based dummy server, which allows
to set different certificates and TLS options. Please note. that tests are
expected to fail, since the server doesn't support further steps like user
authentication etc. after the handshake. Prerequisite for running the tls test
is Python3.
wait_io_or_timeout() accepts milliseconds, while options has seconds,
since this is just plain MYSQL_OPT_READ_TIMEOUT/...
The one that has milliseconds are pvio->timeout[PVIO_*_TIMEOUT], so use
them.
Usually this is not a problem, but, in case of interrupt (i.e. signal -
EINTR) SSL_read() will return SSL_ERROR_WANT_READ/SSL_ERROR_WANT_WRITE,
and then wait_io_or_timeout() will be called, and timeout will be wrong,
may cause a failure.
Added a new structure MARIADB_X509_INFO, which
contains information about servers certificate.
The information can be obtained via mysql_get_infov API
function:
MARIADB_X509_INFO *info;
mariadb_get_infov(mysql, MARIADB_TLS_PEER_CERT_INFO, &info);
This reverts 395641549ac7..536d9e2b9e5b, in particular:
8dffd56936 MDEV-31857 enable MYSQL_OPT_SSL_VERIFY_SERVER_CERT by default
a99570c118 MDEV-31855 SSL cert validation protocol extension
9aa15e72a7 TLS fingerprint
and related commits
because the default value of every option is 0
(option and option.extension are bzero-ed to reset),
tls_verify_server_cert was renamed to tls_allow_invalid_server_cert
with the default value of 0, "do not allow".
API didn't change, it's still MYSQL_OPT_SSL_VERIFY_SERVER_CERT
* extend the client auth plugin API with a new callback
* relax the plugin version check to allow load a plugin with the
same major version, even if the minor versions differ
* implement the protocol extension:
- don't abort at once if the certificate is self signed and
no CA was explicitly specified
- allow it if it passes fingerprint check
- allow it if plugin has hash_password_bin callback, password was
non-empty and the control hash matches server's
Since the server certification option is used by client
only, there is no need to have this flag in server and or
client capabilities. The server itself validates client
certificate depending on the user definition.
Since TLS errors might happen not only when connecting and SSL protocol
is not longer used, errormessage for CR_SSL_CONNECTION_ERROR was replaced
by TLS/SSL error.
Added a new option MARIADB_OPT_SKIP_READ_RESPONSE which skips automatic
reading of server response after sending a command to the server.
Server packets have to be retrieved by calling the corresponding methods,
e.g:
Send command Read method
mysql_real_query/mysql_send_query db_read_query_result
mysql_stmt_prepare db_read_prepare_response
mysql_stmt_execute,
mariadb_stmt_execute_direct db_read_execute_response
We now check the return code of gnutls_record_send() and gnutls_record_recv().
If GNUTLS_E_AGAIN or GNUTLS_E_INTERRUPTED was returned we will loop and read/write
again until a timeout occurs or buffer was read or written.
Fixed crash in case certificate and key are stored in the same file.
Instead of reading key and cert separately we now call gnutls api function
gnutls_certificate_x509_keyfile2() to load certificate and key.
- don't run fingerprint and passphrase protected tests if the corresponding
files (sha1 and encrypted client key) are not found in CERT_PATH
- don't overwrite SSL errors if handshake failed
- Use gnutls read/write instead of pvio
Client part of MDEV-14101: Add support for tls-version, via
mysql_options(mysql, MARIADB_OPT_TLS_VERSION, value)
Accepted values are "TLSv1.1", "TLSv1.2" and "TLSv1.3".
Fixed testcase openssl_1 for schannel
When calling mariadb_get_infov with option MARIADB_TLS_LIBRARY
the functioni now returns the correct version number and name
of the tls/ssl library in use.