- 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).
Add fallback if CryptAcquireContext fails with ERROR_ACCESS_DENIED,
as seen in Jenkins CI.
The fallback, also suggested by https://stackoverflow.com/a/14053718/547065,
is to retry with machine-wide key container, if user-specific fails.
Use SCH_CREDENTIAL structure, to support TLSv1.3
Allow TLSv1.3 starting with Windows 11 / Server 2022, which are
first Windows releases to officially support latest TLS version
There is no real renegotiation in TLSv1.3 protocol, so it is
some internal schannel thing, that makes DecryptMessage() to return
SEC_I_RENEGOTIATE, to replay a handshake step.
This pops up when TLSv1.3 is enabled.
The bug happens only when connecting with SSL with client certificates.
Apparently if client certificates are used in TLS handshake,
private keys for cert should be loaded into named persistent
container.This is because AcquireCredentialsHandle is done partically
out-of-process in lsass.exe, and lsass wants to read private keys from disk
See discussion in https://github.com/dotnet/runtime/issues/23749
Schannel has legacy behavior for ephemeral keys, not involving lsass,
and this is why it worked for us so far, however there are limitations.
It appears to only use rsa_sha1 for signature verification, and newer
OpenSSL no longer allows SHA1 for it, and this ends up in
"algorithm mismatch" message from schannel.
The above is just my understanding of how it works, because there is no
real documentation, the conclusion is based on discussion in
https://github.com/dotnet/runtime/issues/23749
The fix:
So storing the key in persistent named container evidently fixes it,
and this is what is done in this patch. Care is takes to destroy
key container after key is no longer needed, to
avoid filling %AppData%\Roaming\Microsoft\Crypto\RSA with tiny encrypted
key files. Thus the "persistency window" of the key in container on disk
is only for duration of AcquireCredentialsHandle
SSL_{read,write}'s return values == 0 signify the operation was
unsuccessful, but here it's being treated as success. Other calls of
these functions already properly checks the return value.
Signed-off-by: Josh Hunt <johunt@akamai.com>
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
schannel_certs.c - conflicting headers, include winsock2.h before windows.h,
strerror_r is now defined also with mingw
do not build mariadb_config on Windows, getopt.h is missing
CryptOpenAlgorithmProvider() documentation states:
"We recommend that you cache any algorithm provider handles that you will
use more than once, rather than opening and closing the algorithm providers
over and over."
This patch implements algorithm handle caching,
and also simplifies how hashes are handled in win_crypt.c
- MA_HASH_CTX* is now just BCrypt hash handle.
- We no longer allocate or free memory any memory outselves.
There are small change in the ma_hash API:
ma_hash_new() lost the second parameter, only used on Windows previously
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.
according to `man SSL_get_error`
The SSL_ERROR_SYSCALL with errno value of 0 indicates unexpected EOF
from the peer. This will be properly reported as SSL_ERROR_SSL with
reason code SSL_R_UNEXPECTED_EOF_WHILE_READING in the OpenSSL 3.0
release because it is truly a TLS protocol error to terminate the
connection without a SSL_shutdown().
let's use a conventional CR_SERVER_LOST in this case instead of
"TLS/SSL error: Success(0)"
Based on its interpretation of RFC 6125 section 6.4.2[^1], OpenSSL's
implementation[^2] of `X509_check_host` treats the `namelen` parameter
in a peculiar way:
- If `namelen` is non-zero, use it;
- Otherwise, use `strlen(name)` instead
There are now many forks of OpenSSL. Implementer of the forks may
interpret RFC 6125 section 6.4.2 a little differently. They may always
expect `strlen(name)` and NOT `0`. We have come across that with
AWS-LC[^3]. AWS-LC has agreed to make an adjustment so it is consistent
with OpenSSL in this matter. But other forks may not.
To make MariaDB connector C more robust, I think it's better that we
always pass `strlen(name)` instead of `0`. Unless there are compelling
reasons not doing so.
All new code of the whole pull request, including one or several files
that are either new files or modified ones, are contributed under the
BSD-new license. I am contributing on behalf of my employer Amazon Web
Services, Inc.
[^1]: https://www.rfc-editor.org/rfc/rfc6125.html#section-6.4.2
[^2]: https://www.openssl.org/docs/man3.0/man3/X509_check_host.html
[^3]: https://github.com/awslabs/aws-lc
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.
Since alerts may happen after handshake (for example with described
test in CONC-587 using TLSv1.3 protocol or by renegotiation) the
tls error message needs to be retrieved if error is a protocol error
(SSL_ERROR_SSL) and/or if errno was not set.
Removed callback function for crypto threads, since the callback function
cannot be cleared. For OpenSSL <= 1.0.2 the default implementation will be used:
address of errno (Posix) or GetCurrentThreadId (Windows).
Apparently, it complains about wild pointer freed in when using
ASAN_OPTIONS= windows_hook_rtl_allocators=true
while it seems like a false positive, take it as a good opportunity to
remove allocators from Win3.1 times, and replace with simple malloc/free
It looks like CertFreeCertificateContext() would try to access
freed memory.
Fix it by using CERT_STORE_NO_CRYPT_RELEASE_FLAG when setting private key
in certificate, i.e avoid releasing the crypto provider when certificate
is freed.
Note:
My attempts to fix with less code , i.e just omit CryptReleaseContext(),
failed, there was a small memory leak left after freeing each SSL
connection.
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
Added cipher suites ECDHE-RSA-AES128-SHA256 (0xC027) and
ECDHE-RSA-AES256-SHA384 (0xC028) to the cipher map which maps
cipher suite names to the corresponding algorithm ids.
Since this list is still incomplete, and additional list containing
the cipher suite ids and openssl cipher suite names was added. This
list will be used now to detect the cipher suite for the current
connection.