Windows Server 2022 uses version number 10.0.20348, which is less than 10.0.22000.
Therefore, instead of checking for build numbers >= 22000 (which would exclude Server 2022),
we must check for build numbers >= 20348 to correctly include both Windows Server 2022
and Windows 11.
This is safe because TLSv1.3 was first supported in:
- Windows 11 (starting with build 22000)
- Windows Server 2022 (starting with build 20348)
Earlier versions did not support TLSv1.3:
- Windows 10 (up to build 19044)
- Windows Server 2019 (latest build 17763)
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
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 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.
Implement proper verification for server certificate chain,
with refactoring of the certificate stuff.
If custom CA and CRL certs are given, load them into in-memory store, and
use CertVerifyCertificateChainPolicy() to verify the certificate chain.
There are minor errors fixed, such as
- now there is a support for private keys encoded as BEGIN/END PRIVATE KEY
in PEM, instead of only BEGIN/END RSA PRIVATE KEY
- memory leak around CryptAcquireContext() is fixed i.e when client loads
private key, it previously did never released it, not even when connection
ended.
The handling of certificates moved into schannel_certs.c from various places
Print error symbol (e.g S"EC_E_ILLEGAL_MESSAGE") in the error message
for some schannel errors, in addition to error message
Print error code for all errors coming from schannel.
Fix some whitespace.
Added support for pem files which contain certificate and private key.
In case the file will contain more than one certificate or key, the first
certificate or key found will be used.
of ssl version).
We do not need to know the version of schannel.dll. Its version is always
the same as OS version. So do not add extra file IOs to the client
library.
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.
The connection pointer mysql is now no longer part (and doesn't need to be updated) of schannel security context, since it can be obtained directly from tls container.
- Fix a breaking change where
SP_PROT_TLS1_2_CLIENT bit was set in Cred.grbitEnabledProtocols by default.
This makes any SSL connection to Windows server fai, because
all yassl-based servers, in all MariaDB versions would abort
a client that is trying to use TLS1.2
(This is covered MDEV-12190)
As a consequence, client on Windows would not connect to any
server on Windows. For compatibility reasons therefore, 1.2 should NOT
be used by clients by default, otherwise it will break applications
connectivity to both Oracle MySQL and MariaDB's yassl based servers.
This also holds after MDEV-12190 is fixed, because older servers
will be used for a while.
- Cred.dwFlag was missing SCH_CRED_NO_DEFAULT_CREDS flag,
which resulted in a popup on the build servers, asking to insert
a smartcard during client SSL handshake.
Smaller bugs in schannel :
cipher_name() was returning pointer to member of stack allocated struct
Socket IO fixes
- errno rather than WSAGetLastError() was tested on Windows in
pvio_socket_write/pvio_socket_read.
Fixed by using socker_errno and simplided function to avoid numerious #ifdef _WIN32
- simplified vio_set_blocking, it had a rather inefficient implementation
setting the same flags with ioctlsocket/fcntl over and over again.
To obtain the correct cipher suite name, we use the (undocumented) flag
SECPKG_ATTR_CIPHER_INFO, which delivers cipher suite id and IANA cipher suite name.
Added more cipher suites and mappings between IANA and OpenSSL cipher suite names
between the calls.
State can be unread buffer from DecryptMessage (SECBUFFER_EXTRA)
or decrypted data that did not fit into callers buffer
- Fix error handling - SEC_I_RENEGOTIATE is handled as error,
we're not doing it yet. Stop reading at SEC_I_CONTEXT_EXPIRED.
- Fix buffer sizes pased to SSPI ( so that large buffers can be read or written
"SELECT REPEAT('a', 20000)"
- Fix unchecked memcpy into the output buffer (size of the output buffer
was not checked, so it is a potential memory overrun)
- use CertFreeCertificateContext() to free memory allocated by QueryContextAttributes(SECPKG_ATTR_REMOTE_CERT_CONTEXT)
- consistently use "SSL connection error: " prefix for schannel errors
- remove global variables
- remove in memory certificate stores that cache all CRL and all CA
- verify certificate against ssl_ca and ssl_crl specified in
connection options (not against all CRL/CA in store)
- Do not acquire a named context, because this might run
into permissions problem.
- Avoid sending TLS1.2 version by default. Yassl wrongfully rejects it
with a bad handshake (it should consider that 1.1 and 1.0 are supported too
but it does not)
- At the moment the following session tracking types are supported:
SESSION_TRACK_SCHEMA
SESSION_TRACK_SYSTEM_VARIABLES
SESSION_TRACK_STATE_CHANGE
SESSION_TRACK_TRANSACTION_CHARACTERISTICS
- New API functions
mysql_session_track_get_next
mysql_session_track_get_first
changed type of length parameter in mysql_stmt_prepare,
mysql_real_query, mysql_stmt_send_long_data (incl. async _start
functions) from unsigned long to size_t.
Fixed warnings