summaryrefslogtreecommitdiffstats
path: root/src/network/ssl
diff options
context:
space:
mode:
authorTimur Pocheptsov <timur.pocheptsov@qt.io>2021-03-12 12:12:59 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2021-03-18 07:10:51 +0000
commitb4f3c5d64697883b29ba292f315915e4c610bdba (patch)
treef3647bb3f30f88f429fe02a9e39da182a3a2de40 /src/network/ssl
parent63a0d263cf233ddf85a60678829298b50e8d1f26 (diff)
Stop using QSslConfigurationPrivate inside the plugin code
It was reasonable while backends were a part of QtNetwork. Now if moving them outside (or just trying to implement a new backend as a plugin), accessing data-members of QSslConfigurationPrivate means that any plugin knows about memory layout actual only for the version of Qt it was built with/for. Instead, we have to use the public class. Since it does not have all needed setters and some data-members have no access at all, we provide an API in QTlsBackend (which stays a part of QtNetwork) that knows the actual memory layout. Task-number: QTBUG-65922 Change-Id: I5ca1de4f982b4b11d9a87c4b40413367dcb83c16 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io> Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io> (cherry picked from commit 31cc0df7607a4d5887812c304aac0001c2cd7705) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'src/network/ssl')
-rw-r--r--src/network/ssl/qdtls_base.cpp29
-rw-r--r--src/network/ssl/qdtls_base_p.h4
-rw-r--r--src/network/ssl/qdtls_openssl.cpp55
-rw-r--r--src/network/ssl/qsslconfiguration.h8
-rw-r--r--src/network/ssl/qsslconfiguration_p.h4
-rw-r--r--src/network/ssl/qsslsocket.cpp8
-rw-r--r--src/network/ssl/qsslsocket_p.h1
-rw-r--r--src/network/ssl/qtls_openssl.cpp137
-rw-r--r--src/network/ssl/qtls_schannel.cpp110
-rw-r--r--src/network/ssl/qtls_st.cpp118
-rw-r--r--src/network/ssl/qtlsbackend.cpp86
-rw-r--r--src/network/ssl/qtlsbackend_p.h23
12 files changed, 334 insertions, 249 deletions
diff --git a/src/network/ssl/qdtls_base.cpp b/src/network/ssl/qdtls_base.cpp
index be10aac7db..6a5979eb9e 100644
--- a/src/network/ssl/qdtls_base.cpp
+++ b/src/network/ssl/qdtls_base.cpp
@@ -65,37 +65,12 @@ void QDtlsBasePrivate::clearDtlsError()
QSslConfiguration QDtlsBasePrivate::configuration() const
{
- auto copyPrivate = new QSslConfigurationPrivate(dtlsConfiguration);
- copyPrivate->ref.storeRelaxed(0); // the QSslConfiguration constructor refs up
- QSslConfiguration copy(copyPrivate);
- copyPrivate->sessionCipher = sessionCipher;
- copyPrivate->sessionProtocol = sessionProtocol;
-
- return copy;
+ return dtlsConfiguration;
}
void QDtlsBasePrivate::setConfiguration(const QSslConfiguration &configuration)
{
- dtlsConfiguration.localCertificateChain = configuration.localCertificateChain();
- dtlsConfiguration.privateKey = configuration.privateKey();
- dtlsConfiguration.ciphers = configuration.ciphers();
- dtlsConfiguration.ellipticCurves = configuration.ellipticCurves();
- dtlsConfiguration.preSharedKeyIdentityHint = configuration.preSharedKeyIdentityHint();
- dtlsConfiguration.dhParams = configuration.diffieHellmanParameters();
- dtlsConfiguration.caCertificates = configuration.caCertificates();
- dtlsConfiguration.peerVerifyDepth = configuration.peerVerifyDepth();
- dtlsConfiguration.peerVerifyMode = configuration.peerVerifyMode();
- dtlsConfiguration.protocol = configuration.protocol();
- dtlsConfiguration.sslOptions = configuration.d->sslOptions;
- dtlsConfiguration.sslSession = configuration.sessionTicket();
- dtlsConfiguration.sslSessionTicketLifeTimeHint = configuration.sessionTicketLifeTimeHint();
- dtlsConfiguration.nextAllowedProtocols = configuration.allowedNextProtocols();
- dtlsConfiguration.nextNegotiatedProtocol = configuration.nextNegotiatedProtocol();
- dtlsConfiguration.nextProtocolNegotiationStatus = configuration.nextProtocolNegotiationStatus();
- dtlsConfiguration.dtlsCookieEnabled = configuration.dtlsCookieVerificationEnabled();
- dtlsConfiguration.allowRootCertOnDemandLoading = configuration.d->allowRootCertOnDemandLoading;
- dtlsConfiguration.backendConfig = configuration.backendConfiguration();
-
+ dtlsConfiguration = configuration;
clearDtlsError();
}
diff --git a/src/network/ssl/qdtls_base_p.h b/src/network/ssl/qdtls_base_p.h
index bbca4ab57d..df35f514a2 100644
--- a/src/network/ssl/qdtls_base_p.h
+++ b/src/network/ssl/qdtls_base_p.h
@@ -55,7 +55,7 @@
QT_REQUIRE_CONFIG(dtls);
-#include "qsslconfiguration_p.h"
+#include "qsslconfiguration.h"
#include "qtlsbackend_p.h"
#include "qsslcipher.h"
#include "qsslsocket.h"
@@ -96,7 +96,7 @@ public:
QDtlsError errorCode = QDtlsError::NoError;
QString errorDescription;
- QSslConfigurationPrivate dtlsConfiguration;
+ QSslConfiguration dtlsConfiguration;
QSslSocket::SslMode mode = QSslSocket::SslClientMode;
QSslCipher sessionCipher;
QSsl::SslProtocol sessionProtocol = QSsl::UnknownProtocol;
diff --git a/src/network/ssl/qdtls_openssl.cpp b/src/network/ssl/qdtls_openssl.cpp
index 374839458c..80b5179f69 100644
--- a/src/network/ssl/qdtls_openssl.cpp
+++ b/src/network/ssl/qdtls_openssl.cpp
@@ -664,20 +664,15 @@ bool DtlsState::initCtxAndConnection(QDtlsBasePrivate *dtlsBase)
return false;
}
- if (!QDtlsBasePrivate::isDtlsProtocol(dtlsBase->dtlsConfiguration.protocol)) {
+ if (!QDtlsBasePrivate::isDtlsProtocol(dtlsBase->dtlsConfiguration.protocol())) {
dtlsBase->setDtlsError(QDtlsError::TlsInitializationError,
QDtls::tr("Invalid protocol version, DTLS protocol expected"));
return false;
}
- // Create a deep copy of our configuration
- auto configurationCopy = new QSslConfigurationPrivate(dtlsBase->dtlsConfiguration);
- configurationCopy->ref.storeRelaxed(0); // the QSslConfiguration constructor refs up
-
- // DTLSTODO: check we do not set something DTLS-incompatible there ...
- TlsContext newContext(QSslContext::sharedFromConfiguration(dtlsBase->mode,
- configurationCopy,
- dtlsBase->dtlsConfiguration.allowRootCertOnDemandLoading));
+ const bool rootsOnDemand = QTlsBackend::rootLoadingOnDemandAllowed(dtlsBase->dtlsConfiguration);
+ TlsContext newContext(QSslContext::sharedFromConfiguration(dtlsBase->mode, dtlsBase->dtlsConfiguration,
+ rootsOnDemand));
if (newContext->error() != QSslError::NoError) {
dtlsBase->setDtlsError(QDtlsError::TlsInitializationError, newContext->errorString());
@@ -695,14 +690,14 @@ bool DtlsState::initCtxAndConnection(QDtlsBasePrivate *dtlsBase)
QTlsBackendOpenSSL::s_indexForSSLExtraData,
this);
- if (set != 1 && configurationCopy->peerVerifyMode != QSslSocket::VerifyNone) {
+ if (set != 1 && dtlsBase->dtlsConfiguration.peerVerifyMode() != QSslSocket::VerifyNone) {
dtlsBase->setDtlsError(QDtlsError::TlsInitializationError,
msgFunctionFailed("SSL_set_ex_data"));
return false;
}
if (dtlsBase->mode == QSslSocket::SslServerMode) {
- if (dtlsBase->dtlsConfiguration.dtlsCookieEnabled)
+ if (dtlsBase->dtlsConfiguration.dtlsCookieVerificationEnabled())
q_SSL_set_options(newConnection.data(), SSL_OP_COOKIE_EXCHANGE);
q_SSL_set_psk_server_callback(newConnection.data(), dtlscallbacks::q_PSK_server_callback);
} else {
@@ -936,7 +931,7 @@ bool QDtlsPrivateOpenSSL::startHandshake(QUdpSocket *socket, const QByteArray &d
if (!dtls.init(this, socket, remoteAddress, remotePort, dgram))
return false;
- if (mode == QSslSocket::SslServerMode && dtlsConfiguration.dtlsCookieEnabled) {
+ if (mode == QSslSocket::SslServerMode && dtlsConfiguration.dtlsCookieVerificationEnabled()) {
dtls.secret = secret;
dtls.hashAlgorithm = hashAlgorithm;
// Let's prepare the state machine so that message sequence 1 does not
@@ -1040,8 +1035,8 @@ bool QDtlsPrivateOpenSSL::continueHandshake(QUdpSocket *socket, const QByteArray
storePeerCertificates();
fetchNegotiatedParameters();
- const bool doVerifyPeer = dtlsConfiguration.peerVerifyMode == QSslSocket::VerifyPeer
- || (dtlsConfiguration.peerVerifyMode == QSslSocket::AutoVerifyPeer
+ const bool doVerifyPeer = dtlsConfiguration.peerVerifyMode() == QSslSocket::VerifyPeer
+ || (dtlsConfiguration.peerVerifyMode() == QSslSocket::AutoVerifyPeer
&& mode == QSslSocket::SslClientMode);
if (!doVerifyPeer || verifyPeer() || tlsErrorsWereIgnored()) {
@@ -1308,7 +1303,7 @@ unsigned QDtlsPrivateOpenSSL::pskServerCallback(const char *identity, unsigned c
{
QSslPreSharedKeyAuthenticator authenticator;
// Fill in some read-only fields (for the user)
- QTlsBackend::setupServerPskAuth(&authenticator, identity, dtlsConfiguration.preSharedKeyIdentityHint,
+ QTlsBackend::setupServerPskAuth(&authenticator, identity, dtlsConfiguration.preSharedKeyIdentityHint(),
max_psk_len);
pskAuthenticator.swap(authenticator);
}
@@ -1331,17 +1326,18 @@ unsigned QDtlsPrivateOpenSSL::pskServerCallback(const char *identity, unsigned c
bool QDtlsPrivateOpenSSL::verifyPeer()
{
- // DTLSTODO: Windows-specific code for CA fetcher is not here yet.
QList<QSslError> errors;
// Check the whole chain for blacklisting (including root, as we check for
// subjectInfo and issuer)
- for (const QSslCertificate &cert : qAsConst(dtlsConfiguration.peerCertificateChain)) {
+ const auto &peerCertificateChain = dtlsConfiguration.peerCertificateChain();
+ for (const QSslCertificate &cert : peerCertificateChain) {
if (QSslCertificatePrivate::isBlacklisted(cert))
errors << QSslError(QSslError::CertificateBlacklisted, cert);
}
- if (dtlsConfiguration.peerCertificate.isNull()) {
+ const auto peerCertificate = dtlsConfiguration.peerCertificate();
+ if (peerCertificate.isNull()) {
errors << QSslError(QSslError::NoPeerCertificate);
} else if (mode == QSslSocket::SslClientMode) {
// Check the peer certificate itself. First try the subject's common name
@@ -1358,15 +1354,15 @@ bool QDtlsPrivateOpenSSL::verifyPeer()
name = dtls.udpSocket->peerName();
}
- if (!QTlsPrivate::TlsCryptograph::isMatchingHostname(dtlsConfiguration.peerCertificate, name))
- errors << QSslError(QSslError::HostNameMismatch, dtlsConfiguration.peerCertificate);
+ if (!QTlsPrivate::TlsCryptograph::isMatchingHostname(peerCertificate, name))
+ errors << QSslError(QSslError::HostNameMismatch, peerCertificate);
}
// Translate errors from the error list into QSslErrors
using CertClass = QTlsPrivate::X509CertificateOpenSSL;
errors.reserve(errors.size() + opensslErrors.size());
for (const auto &error : qAsConst(opensslErrors)) {
- const auto value = dtlsConfiguration.peerCertificateChain.value(error.depth);
+ const auto value = peerCertificateChain.value(error.depth);
errors << CertClass::openSSLErrorToQSslError(error.code, value);
}
@@ -1382,13 +1378,17 @@ void QDtlsPrivateOpenSSL::storePeerCertificates()
// peer certificate and the chain may be empty if the peer didn't present
// any certificate.
X509 *x509 = q_SSL_get_peer_certificate(dtls.tlsConnection.data());
- dtlsConfiguration.peerCertificate = QTlsPrivate::X509CertificateOpenSSL::certificateFromX509(x509);
+ const auto peerCertificate = QTlsPrivate::X509CertificateOpenSSL::certificateFromX509(x509);
+ QTlsBackend::storePeerCertificate(dtlsConfiguration, peerCertificate);
q_X509_free(x509);
- if (dtlsConfiguration.peerCertificateChain.isEmpty()) {
+
+ auto peerCertificateChain = dtlsConfiguration.peerCertificateChain();
+ if (peerCertificateChain.isEmpty()) {
auto stack = q_SSL_get_peer_cert_chain(dtls.tlsConnection.data());
- dtlsConfiguration.peerCertificateChain = QTlsPrivate::X509CertificateOpenSSL::stackOfX509ToQSslCertificates(stack);
- if (!dtlsConfiguration.peerCertificate.isNull() && mode == QSslSocket::SslServerMode)
- dtlsConfiguration.peerCertificateChain.prepend(dtlsConfiguration.peerCertificate);
+ peerCertificateChain = QTlsPrivate::X509CertificateOpenSSL::stackOfX509ToQSslCertificates(stack);
+ if (!peerCertificate.isNull() && mode == QSslSocket::SslServerMode)
+ peerCertificateChain.prepend(peerCertificate);
+ QTlsBackend::storePeerCertificateChain(dtlsConfiguration, peerCertificateChain);
}
}
@@ -1441,8 +1441,7 @@ void QDtlsPrivateOpenSSL::resetDtls()
connectionEncrypted = false;
tlsErrors.clear();
tlsErrorsToIgnore.clear();
- dtlsConfiguration.peerCertificate.clear();
- dtlsConfiguration.peerCertificateChain.clear();
+ QTlsBackend::clearPeerCertificates(dtlsConfiguration);
connectionWasShutdown = false;
handshakeState = QDtls::HandshakeNotStarted;
sessionCipher = {};
diff --git a/src/network/ssl/qsslconfiguration.h b/src/network/ssl/qsslconfiguration.h
index 716ea8ed7f..43566bc0cd 100644
--- a/src/network/ssl/qsslconfiguration.h
+++ b/src/network/ssl/qsslconfiguration.h
@@ -72,11 +72,6 @@ class QSslKey;
class QSslEllipticCurve;
class QSslDiffieHellmanParameters;
-namespace dtlsopenssl
-{
-class DtlsState;
-}
-
class QSslConfigurationPrivate;
class Q_NETWORK_EXPORT QSslConfiguration
{
@@ -202,8 +197,7 @@ private:
friend class QSslSocket;
friend class QSslConfigurationPrivate;
friend class QSslContext;
- friend class QDtlsBasePrivate;
- friend class dtlsopenssl::DtlsState;
+ friend class QTlsBackend;
QSslConfiguration(QSslConfigurationPrivate *dd);
QSharedDataPointer<QSslConfigurationPrivate> d;
};
diff --git a/src/network/ssl/qsslconfiguration_p.h b/src/network/ssl/qsslconfiguration_p.h
index 9a70fda653..43c736e012 100644
--- a/src/network/ssl/qsslconfiguration_p.h
+++ b/src/network/ssl/qsslconfiguration_p.h
@@ -79,7 +79,7 @@
QT_BEGIN_NAMESPACE
-class Q_NETWORK_PRIVATE_EXPORT QSslConfigurationPrivate: public QSharedData
+class QSslConfigurationPrivate: public QSharedData
{
public:
QSslConfigurationPrivate()
@@ -114,7 +114,7 @@ public:
bool allowRootCertOnDemandLoading;
bool peerSessionShared;
- static bool peerSessionWasShared(const QSslConfiguration &configuration);
+ Q_AUTOTEST_EXPORT static bool peerSessionWasShared(const QSslConfiguration &configuration);
QSsl::SslOptions sslOptions;
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index 91f8cb4528..546c26272d 100644
--- a/src/network/ssl/qsslsocket.cpp
+++ b/src/network/ssl/qsslsocket.cpp
@@ -3123,14 +3123,6 @@ QSslSocket::SslMode QSslSocketPrivate::tlsMode() const
/*!
\internal
*/
-QSslConfigurationPrivate &QSslSocketPrivate::privateConfiguration()
-{
- return configuration;
-}
-
-/*!
- \internal
-*/
bool QSslSocketPrivate::isRootsOnDemandAllowed() const
{
return allowRootCertOnDemandLoading;
diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h
index 6a03a23dc6..c90dfc8883 100644
--- a/src/network/ssl/qsslsocket_p.h
+++ b/src/network/ssl/qsslsocket_p.h
@@ -172,7 +172,6 @@ public:
// Needed by TlsCryptograph:
Q_NETWORK_PRIVATE_EXPORT QSslSocket::SslMode tlsMode() const;
- Q_NETWORK_PRIVATE_EXPORT QSslConfigurationPrivate &privateConfiguration();
Q_NETWORK_PRIVATE_EXPORT bool isRootsOnDemandAllowed() const;
Q_NETWORK_PRIVATE_EXPORT QString verificationName() const;
Q_NETWORK_PRIVATE_EXPORT QString tlsHostName() const;
diff --git a/src/network/ssl/qtls_openssl.cpp b/src/network/ssl/qtls_openssl.cpp
index 5149b4ce38..90561943f5 100644
--- a/src/network/ssl/qtls_openssl.cpp
+++ b/src/network/ssl/qtls_openssl.cpp
@@ -561,7 +561,6 @@ bool TlsCryptographOpenSSL::startHandshake()
return false;
const auto mode = d->tlsMode();
- auto &configuration = d->privateConfiguration();
pendingFatalAlert = false;
errorsReportedFromCallback = false;
@@ -582,10 +581,14 @@ bool TlsCryptographOpenSSL::startHandshake()
if (!lastErrors.isEmpty() || errorsReportedFromCallback)
storePeerCertificates();
+ // storePeerCertificate() if called above - would update the
+ // configuration with peer's certificates.
+ auto configuration = q->sslConfiguration();
if (!errorsReportedFromCallback) {
+ const auto &peerCertificateChain = configuration.peerCertificateChain();
for (const auto &currentError : qAsConst(lastErrors)) {
emit q->peerVerifyError(QTlsPrivate::X509CertificateOpenSSL::openSSLErrorToQSslError(currentError.code,
- configuration.peerCertificateChain.value(currentError.depth)));
+ peerCertificateChain.value(currentError.depth)));
if (q->state() != QAbstractSocket::ConnectedState)
break;
}
@@ -628,8 +631,11 @@ bool TlsCryptographOpenSSL::startHandshake()
// Start translating errors.
QList<QSslError> errors;
- // check the whole chain for blacklisting (including root, as we check for subjectInfo and issuer)
- for (const QSslCertificate &cert : qAsConst(configuration.peerCertificateChain)) {
+ // Note, the storePeerCerificates() probably updated the configuration at this point.
+ configuration = q->sslConfiguration();
+ // Check the whole chain for blacklisting (including root, as we check for subjectInfo and issuer)
+ const auto &peerCertificateChain = configuration.peerCertificateChain();
+ for (const QSslCertificate &cert : peerCertificateChain) {
if (QSslCertificatePrivate::isBlacklisted(cert)) {
QSslError error(QSslError::CertificateBlacklisted, cert);
errors << error;
@@ -639,14 +645,14 @@ bool TlsCryptographOpenSSL::startHandshake()
}
}
- const bool doVerifyPeer = configuration.peerVerifyMode == QSslSocket::VerifyPeer
- || (configuration.peerVerifyMode == QSslSocket::AutoVerifyPeer
+ const bool doVerifyPeer = configuration.peerVerifyMode() == QSslSocket::VerifyPeer
+ || (configuration.peerVerifyMode() == QSslSocket::AutoVerifyPeer
&& mode == QSslSocket::SslClientMode);
#if QT_CONFIG(ocsp)
// For now it's always QSslSocket::SslClientMode - initSslContext() will bail out early,
// if it's enabled in QSslSocket::SslServerMode. This can change.
- if (!configuration.peerCertificate.isNull() && configuration.ocspStaplingEnabled && doVerifyPeer) {
+ if (!configuration.peerCertificate().isNull() && configuration.ocspStaplingEnabled() && doVerifyPeer) {
if (!checkOcspStatus()) {
if (ocspErrors.isEmpty()) {
{
@@ -670,16 +676,16 @@ bool TlsCryptographOpenSSL::startHandshake()
// Check the peer certificate itself. First try the subject's common name
// (CN) as a wildcard, then try all alternate subject name DNS entries the
// same way.
- if (!configuration.peerCertificate.isNull()) {
+ if (!configuration.peerCertificate().isNull()) {
// but only if we're a client connecting to a server
// if we're the server, don't check CN
const auto verificationPeerName = d->verificationName();
if (mode == QSslSocket::SslClientMode) {
QString peerName = (verificationPeerName.isEmpty () ? q->peerName() : verificationPeerName);
- if (!isMatchingHostname(configuration.peerCertificate, peerName)) {
+ if (!isMatchingHostname(configuration.peerCertificate(), peerName)) {
// No matches in common names or alternate names.
- QSslError error(QSslError::HostNameMismatch, configuration.peerCertificate);
+ QSslError error(QSslError::HostNameMismatch, configuration.peerCertificate());
errors << error;
emit q->peerVerifyError(error);
if (q->state() != QAbstractSocket::ConnectedState)
@@ -701,7 +707,7 @@ bool TlsCryptographOpenSSL::startHandshake()
// Translate errors from the error list into QSslErrors.
errors.reserve(errors.size() + errorList.size());
for (const auto &error : qAsConst(errorList))
- errors << X509CertificateOpenSSL::openSSLErrorToQSslError(error.code, configuration.peerCertificateChain.value(error.depth));
+ errors << X509CertificateOpenSSL::openSSLErrorToQSslError(error.code, peerCertificateChain.value(error.depth));
if (!errors.isEmpty()) {
sslErrors = errors;
@@ -763,7 +769,6 @@ void TlsCryptographOpenSSL::continueHandshake()
auto *plainSocket = d->plainTcpSocket();
Q_ASSERT(plainSocket);
- auto &configuration = d->privateConfiguration();
const auto mode = d->tlsMode();
// if we have a max read buffer size, reset the plain socket's to match
@@ -771,7 +776,7 @@ void TlsCryptographOpenSSL::continueHandshake()
plainSocket->setReadBufferSize(maxSize);
if (q_SSL_session_reused(ssl))
- configuration.peerSessionShared = true;
+ QTlsBackend::setPeerSessionShared(d, true);
#ifdef QT_DECRYPT_SSL_TRAFFIC
if (q_SSL_get_session(ssl)) {
@@ -804,26 +809,29 @@ void TlsCryptographOpenSSL::continueHandshake()
}
#endif // QT_DECRYPT_SSL_TRAFFIC
+ const auto &configuration = q->sslConfiguration();
// Cache this SSL session inside the QSslContext
- if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionSharing)) {
+ if (!(configuration.testSslOption(QSsl::SslOptionDisableSessionSharing))) {
if (!sslContextPointer->cacheSession(ssl)) {
sslContextPointer.clear(); // we could not cache the session
} else {
// Cache the session for permanent usage as well
- if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionPersistence)) {
+ if (!(configuration.testSslOption(QSsl::SslOptionDisableSessionPersistence))) {
if (!sslContextPointer->sessionASN1().isEmpty())
- configuration.sslSession = sslContextPointer->sessionASN1();
- configuration.sslSessionTicketLifeTimeHint = sslContextPointer->sessionTicketLifeTimeHint();
+ QTlsBackend::setSessionAsn1(d, sslContextPointer->sessionASN1());
+ QTlsBackend::setSessionLifetimeHint(d, sslContextPointer->sessionTicketLifeTimeHint());
}
}
}
#if !defined(OPENSSL_NO_NEXTPROTONEG)
- configuration.nextProtocolNegotiationStatus = sslContextPointer->npnContext().status;
+ QTlsBackend::setAlpnStatus(d, sslContextPointer->npnContext().status);
if (sslContextPointer->npnContext().status == QSslConfiguration::NextProtocolNegotiationUnsupported) {
// we could not agree -> be conservative and use HTTP/1.1
- configuration.nextNegotiatedProtocol = QByteArrayLiteral("http/1.1");
+ // T.P.: I have to admit, this is a really strange notion of 'conservative',
+ // given the protocol-neutral nature of ALPN/NPN.
+ QTlsBackend::setNegotiatedProtocol(d, QByteArrayLiteral("http/1.1"));
} else {
const unsigned char *proto = nullptr;
unsigned int proto_len = 0;
@@ -831,7 +839,7 @@ void TlsCryptographOpenSSL::continueHandshake()
q_SSL_get0_alpn_selected(ssl, &proto, &proto_len);
if (proto_len && mode == QSslSocket::SslClientMode) {
// Client does not have a callback that sets it ...
- configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationNegotiated;
+ QTlsBackend::setAlpnStatus(d, QSslConfiguration::NextProtocolNegotiationNegotiated);
}
if (!proto_len) { // Test if NPN was more lucky ...
@@ -839,16 +847,16 @@ void TlsCryptographOpenSSL::continueHandshake()
}
if (proto_len)
- configuration.nextNegotiatedProtocol = QByteArray(reinterpret_cast<const char *>(proto), proto_len);
+ QTlsBackend::setNegotiatedProtocol(d, QByteArray(reinterpret_cast<const char *>(proto), proto_len));
else
- configuration.nextNegotiatedProtocol.clear();
+ QTlsBackend::setNegotiatedProtocol(d,{});
}
#endif // !defined(OPENSSL_NO_NEXTPROTONEG)
if (mode == QSslSocket::SslClientMode) {
EVP_PKEY *key;
if (q_SSL_get_server_tmp_key(ssl, &key))
- configuration.ephemeralServerKey = QSslKey(key, QSsl::PublicKey);
+ QTlsBackend::setEphemeralKey(d, QSslKey(key, QSsl::PublicKey));
}
d->setEncrypted(true);
@@ -1176,12 +1184,11 @@ bool TlsCryptographOpenSSL::checkSslErrors()
emit q->sslErrors(sslErrors);
- auto &configuration = d->privateConfiguration();
+ const auto vfyMode = q->peerVerifyMode();
const auto mode = d->tlsMode();
- bool doVerifyPeer = configuration.peerVerifyMode == QSslSocket::VerifyPeer
- || (configuration.peerVerifyMode == QSslSocket::AutoVerifyPeer
- && mode == QSslSocket::SslClientMode);
+ bool doVerifyPeer = vfyMode == QSslSocket::VerifyPeer || (vfyMode == QSslSocket::AutoVerifyPeer
+ && mode == QSslSocket::SslClientMode);
bool doEmitSslError = !d->verifyErrorsHaveBeenIgnored();
// check whether we need to emit an SSL handshake error
if (doVerifyPeer && doEmitSslError) {
@@ -1205,7 +1212,9 @@ int TlsCryptographOpenSSL::handleNewSessionTicket(SSL *connection)
// 0 would tell OpenSSL to deref (but they still have it in the
// internal cache).
Q_ASSERT(connection);
+
Q_ASSERT(q);
+ Q_ASSERT(d);
if (q->sslConfiguration().testSslOption(QSsl::SslOptionDisableSessionPersistence)) {
// We silently ignore, do nothing, remove from cache.
@@ -1245,9 +1254,8 @@ int TlsCryptographOpenSSL::handleNewSessionTicket(SSL *connection)
return 0;
}
- auto &configuration = d->privateConfiguration();
- configuration.sslSession = sessionTicket;
- configuration.sslSessionTicketLifeTimeHint = int(q_SSL_SESSION_get_ticket_lifetime_hint(currentSession));
+ QTlsBackend::setSessionAsn1(d, sessionTicket);
+ QTlsBackend::setSessionLifetimeHint(d, q_SSL_SESSION_get_ticket_lifetime_hint(currentSession));
emit q->newSessionTicketReceived();
return 0;
@@ -1345,17 +1353,11 @@ bool TlsCryptographOpenSSL::initSslContext()
Q_ASSERT(d);
// If no external context was set (e.g. by QHttpNetworkConnection) we will
- // create a default context
- auto &configuration = d->privateConfiguration();
+ // create a new one.
const auto mode = d->tlsMode();
-
- if (!sslContextPointer) {
- // create a deep copy of our configuration
- QSslConfigurationPrivate *configurationCopy = new QSslConfigurationPrivate(configuration);
- configurationCopy->ref.storeRelaxed(0); // the QSslConfiguration constructor refs up
- sslContextPointer = QSslContext::sharedFromPrivateConfiguration(mode, configurationCopy,
- d->isRootsOnDemandAllowed());
- }
+ const auto configuration = q->sslConfiguration();
+ if (!sslContextPointer)
+ sslContextPointer = QSslContext::sharedFromConfiguration(mode, configuration, d->isRootsOnDemandAllowed());
if (sslContextPointer->error() != QSslError::NoError) {
d->setErrorAndEmit(QAbstractSocket::SslInvalidUserDataError, sslContextPointer->errorString());
@@ -1370,7 +1372,7 @@ bool TlsCryptographOpenSSL::initSslContext()
return false;
}
- if (configuration.protocol != QSsl::UnknownProtocol && mode == QSslSocket::SslClientMode) {
+ if (configuration.protocol() != QSsl::UnknownProtocol && mode == QSslSocket::SslClientMode) {
const auto verificationPeerName = d->verificationName();
// Set server hostname on TLS extension. RFC4366 section 3.1 requires it in ACE format.
QString tlsHostName = verificationPeerName.isEmpty() ? q->peerName() : verificationPeerName;
@@ -1380,7 +1382,7 @@ bool TlsCryptographOpenSSL::initSslContext()
// only send the SNI header if the URL is valid and not an IP
if (!ace.isEmpty()
&& !QHostAddress().setAddress(tlsHostName)
- && !(configuration.sslOptions & QSsl::SslOptionDisableServerNameIndication)) {
+ && !(configuration.testSslOption(QSsl::SslOptionDisableServerNameIndication))) {
// We don't send the trailing dot from the host header if present see
// https://tools.ietf.org/html/rfc6066#section-3
if (ace.endsWith('.'))
@@ -1434,7 +1436,7 @@ bool TlsCryptographOpenSSL::initSslContext()
#endif // OPENSSL_NO_PSK
#if QT_CONFIG(ocsp)
- if (configuration.ocspStaplingEnabled) {
+ if (configuration.ocspStaplingEnabled()) {
if (mode == QSslSocket::SslServerMode) {
d->setErrorAndEmit(QAbstractSocket::SslInvalidUserDataError,
QSslSocket::tr("Server-side QSslSocket does not support OCSP stapling"));
@@ -1448,8 +1450,9 @@ bool TlsCryptographOpenSSL::initSslContext()
}
ocspResponseDer.clear();
- auto responsePos = configuration.backendConfig.find("Qt-OCSP-response");
- if (responsePos != configuration.backendConfig.end()) {
+ const auto backendConfig = configuration.backendConfiguration();
+ auto responsePos = backendConfig.find("Qt-OCSP-response");
+ if (responsePos != backendConfig.end()) {
// This is our private, undocumented 'API' we use for the auto-testing of
// OCSP-stapling. It must be a der-encoded OCSP response, presumably set
// by tst_QOcsp.
@@ -1492,18 +1495,22 @@ void TlsCryptographOpenSSL::destroySslContext()
void TlsCryptographOpenSSL::storePeerCertificates()
{
Q_ASSERT(d);
- auto &configuration = d->privateConfiguration();
+
// Store the peer certificate and chain. For clients, the peer certificate
// chain includes the peer certificate; for servers, it doesn't. Both the
// peer certificate and the chain may be empty if the peer didn't present
// any certificate.
X509 *x509 = q_SSL_get_peer_certificate(ssl);
- configuration.peerCertificate = QTlsPrivate::X509CertificateOpenSSL::certificateFromX509(x509);
+
+ const auto peerCertificate = QTlsPrivate::X509CertificateOpenSSL::certificateFromX509(x509);
+ QTlsBackend::storePeerCertificate(d, peerCertificate);
q_X509_free(x509);
- if (configuration.peerCertificateChain.isEmpty()) {
- configuration.peerCertificateChain = QTlsPrivate::X509CertificateOpenSSL::stackOfX509ToQSslCertificates(q_SSL_get_peer_cert_chain(ssl));
- if (!configuration.peerCertificate.isNull() && d->tlsMode() == QSslSocket::SslServerMode)
- configuration.peerCertificateChain.prepend(configuration.peerCertificate);
+ auto peerCertificateChain = q->peerCertificateChain();
+ if (peerCertificateChain.isEmpty()) {
+ peerCertificateChain = QTlsPrivate::X509CertificateOpenSSL::stackOfX509ToQSslCertificates(q_SSL_get_peer_cert_chain(ssl));
+ if (!peerCertificate.isNull() && d->tlsMode() == QSslSocket::SslServerMode)
+ peerCertificateChain.prepend(peerCertificate);
+ QTlsBackend::storePeerCertificateChain(d, peerCertificateChain);
}
}
@@ -1514,9 +1521,9 @@ bool TlsCryptographOpenSSL::checkOcspStatus()
Q_ASSERT(ssl);
Q_ASSERT(d);
- auto &configuration = d->privateConfiguration();
+ const auto &configuration = q->sslConfiguration();
Q_ASSERT(d->tlsMode() == QSslSocket::SslClientMode); // See initSslContext() for SslServerMode
- Q_ASSERT(configuration.peerVerifyMode != QSslSocket::VerifyNone);
+ Q_ASSERT(configuration.peerVerifyMode() != QSslSocket::VerifyNone);
const auto clearErrorQueue = qScopeGuard([] {
QTlsBackendOpenSSL::logAndClearErrorQueue();
@@ -1606,10 +1613,10 @@ bool TlsCryptographOpenSSL::checkOcspStatus()
// issuer's public key.
ocspResponses.push_back(QOcspResponse());
QOcspResponsePrivate *dResponse = ocspResponses.back().d.data();
- dResponse->subjectCert = configuration.peerCertificate;
+ dResponse->subjectCert = configuration.peerCertificate();
bool matchFound = false;
- if (configuration.peerCertificate.isSelfSigned()) {
- dResponse->signerCert = configuration.peerCertificate;
+ if (dResponse->subjectCert.isSelfSigned()) {
+ dResponse->signerCert = configuration.peerCertificate();
matchFound = qt_OCSP_certificate_match(singleResponse, peerX509, peerX509);
} else {
const STACK_OF(X509) *certs = q_SSL_get_peer_cert_chain(ssl);
@@ -1636,7 +1643,7 @@ bool TlsCryptographOpenSSL::checkOcspStatus()
if (!matchFound) {
dResponse->signerCert.clear();
- ocspErrors.push_back({QSslError::OcspResponseCertIdUnknown, configuration.peerCertificate});
+ ocspErrors.push_back({QSslError::OcspResponseCertIdUnknown, configuration.peerCertificate()});
}
// Check if the response is valid time-wise:
@@ -1664,7 +1671,7 @@ bool TlsCryptographOpenSSL::checkOcspStatus()
// next < this ? -> NEXT_BEFORE_THIS
// OK.
if (!q_OCSP_check_validity(thisUpdate, nextUpdate, 60, -1))
- ocspErrors.push_back({QSslError::OcspResponseExpired, configuration.peerCertificate});
+ ocspErrors.push_back({QSslError::OcspResponseExpired, configuration.peerCertificate()});
// And finally, the status:
switch (certStatus) {
@@ -1675,11 +1682,11 @@ bool TlsCryptographOpenSSL::checkOcspStatus()
case V_OCSP_CERTSTATUS_REVOKED:
dResponse->certificateStatus = QOcspCertificateStatus::Revoked;
dResponse->revocationReason = qt_OCSP_revocation_reason(reason);
- ocspErrors.push_back({QSslError::CertificateRevoked, configuration.peerCertificate});
+ ocspErrors.push_back({QSslError::CertificateRevoked, configuration.peerCertificate()});
break;
case V_OCSP_CERTSTATUS_UNKNOWN:
dResponse->certificateStatus = QOcspCertificateStatus::Unknown;
- ocspErrors.push_back({QSslError::OcspStatusUnknown, configuration.peerCertificate});
+ ocspErrors.push_back({QSslError::OcspStatusUnknown, configuration.peerCertificate()});
}
return !ocspErrors.size();
@@ -1723,7 +1730,7 @@ unsigned TlsCryptographOpenSSL::pskServerTlsCallback(const char *identity, unsig
QSslPreSharedKeyAuthenticator authenticator;
// Fill in some read-only fields (for the user)
- QTlsBackend::setupServerPskAuth(&authenticator, identity, d->privateConfiguration().preSharedKeyIdentityHint,
+ QTlsBackend::setupServerPskAuth(&authenticator, identity, q->sslConfiguration().preSharedKeyIdentityHint(),
max_psk_len);
emit q->preSharedKeyAuthenticationRequired(&authenticator);
@@ -1748,7 +1755,7 @@ void TlsCryptographOpenSSL::fetchCaRootForCert(const QSslCertificate &cert)
//so the request is done in a worker thread.
QList<QSslCertificate> customRoots;
if (fetchAuthorityInformation)
- customRoots = d->privateConfiguration().caCertificates;
+ customRoots = q->sslConfiguration().caCertificates();
//Remember we are fetching and what we are fetching:
caToFetch = cert;
@@ -1772,12 +1779,11 @@ void TlsCryptographOpenSSL::caRootLoaded(QSslCertificate cert, QSslCertificate t
Q_ASSERT(d);
Q_ASSERT(q);
- auto &configuration = d->privateConfiguration();
//Done, fetched already:
caToFetch = QSslCertificate{};
if (fetchAuthorityInformation) {
- if (!configuration.caCertificates.contains(trustedRoot))
+ if (!q->sslConfiguration().caCertificates().contains(trustedRoot))
trustedRoot = QSslCertificate{};
fetchAuthorityInformation = false;
}
@@ -1790,8 +1796,7 @@ void TlsCryptographOpenSSL::caRootLoaded(QSslCertificate cert, QSslCertificate t
QSslConfiguration::setDefaultConfiguration(defaultConfig);
}
//Add the new root cert to this socket for future connections
- if (!configuration.caCertificates.contains(trustedRoot))
- configuration.caCertificates += trustedRoot;
+ QTlsBackend::addTustedRoot(d, trustedRoot);
//Remove the broken chain ssl errors (as chain is verified by windows)
for (int i=sslErrors.count() - 1; i >= 0; --i) {
if (sslErrors.at(i).certificate() == cert) {
diff --git a/src/network/ssl/qtls_schannel.cpp b/src/network/ssl/qtls_schannel.cpp
index 760572a94f..cb4b9ce79d 100644
--- a/src/network/ssl/qtls_schannel.cpp
+++ b/src/network/ssl/qtls_schannel.cpp
@@ -764,6 +764,7 @@ QString TlsCryptographSchannel::targetName() const
ULONG TlsCryptographSchannel::getContextRequirements()
{
Q_ASSERT(d);
+ Q_ASSERT(q);
const bool isClient = d->tlsMode() == QSslSocket::SslClientMode;
ULONG req = 0;
@@ -777,7 +778,7 @@ ULONG TlsCryptographSchannel::getContextRequirements()
if (isClient) {
req |= ISC_REQ_MANUAL_CRED_VALIDATION; // Manually validate certificate
} else {
- switch (d->privateConfiguration().peerVerifyMode) {
+ switch (q->peerVerifyMode()) {
case QSslSocket::PeerVerifyMode::VerifyNone:
// There doesn't seem to be a way to ask for an optional client cert :-(
case QSslSocket::PeerVerifyMode::AutoVerifyPeer:
@@ -795,12 +796,13 @@ ULONG TlsCryptographSchannel::getContextRequirements()
bool TlsCryptographSchannel::acquireCredentialsHandle()
{
Q_ASSERT(d);
- const auto &configuration = d->privateConfiguration();
+ Q_ASSERT(q);
+ const auto &configuration = q->sslConfiguration();
Q_ASSERT(schannelState == SchannelState::InitializeHandshake);
const bool isClient = d->tlsMode() == QSslSocket::SslClientMode;
- const DWORD protocols = toSchannelProtocol(configuration.protocol);
+ const DWORD protocols = toSchannelProtocol(configuration.protocol());
if (protocols == DWORD(-1)) {
d->setErrorAndEmit(QAbstractSocket::SslInvalidUserDataError,
QSslSocket::tr("Invalid protocol chosen"));
@@ -820,7 +822,7 @@ bool TlsCryptographSchannel::acquireCredentialsHandle()
// Check if user has specified a certificate chain but it could not be loaded.
// This happens if there was something wrong with the certificate chain or there was no private
// key.
- if (!configuration.localCertificateChain.isEmpty() && !localCertificateStore)
+ if (!configuration.localCertificateChain().isEmpty() && !localCertificateStore)
return true; // 'true' because "tst_QSslSocket::setEmptyKey" expects us to not disconnect
if (localCertificateStore != nullptr) {
@@ -859,7 +861,7 @@ bool TlsCryptographSchannel::acquireCredentialsHandle()
TLS_PARAMETERS tlsParameters = {
0,
nullptr,
- toSchannelProtocolNegated(configuration.protocol), // what protocols to disable
+ toSchannelProtocolNegated(configuration.protocol()), // what protocols to disable
0,
nullptr,
0
@@ -960,8 +962,9 @@ void TlsCryptographSchannel::closeCertificateStores()
bool TlsCryptographSchannel::createContext()
{
+ Q_ASSERT(q);
Q_ASSERT(d);
- auto &configuration = d->privateConfiguration();
+ const auto &configuration = q->sslConfiguration();
Q_ASSERT(SecIsValidHandle(&credentialHandle));
Q_ASSERT(schannelState == SchannelState::InitializeHandshake);
@@ -989,8 +992,8 @@ bool TlsCryptographSchannel::createContext()
SecBufferDesc alpnBufferDesc;
bool useAlpn = false;
#ifdef SUPPORTS_ALPN
- configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationNone;
- QByteArray alpnString = createAlpnString(configuration.nextAllowedProtocols);
+ QTlsBackend::setAlpnStatus(d, QSslConfiguration::NextProtocolNegotiationNone);
+ QByteArray alpnString = createAlpnString(configuration.allowedNextProtocols());
useAlpn = !alpnString.isEmpty();
SecBuffer alpnBuffers[1];
alpnBuffers[0] = createSecBuffer(alpnString, SECBUFFER_APPLICATION_PROTOCOLS);
@@ -1032,7 +1035,8 @@ bool TlsCryptographSchannel::createContext()
bool TlsCryptographSchannel::acceptContext()
{
Q_ASSERT(d);
- auto &configuration = d->privateConfiguration();
+ Q_ASSERT(q);
+ const auto &configuration = q->sslConfiguration();
auto *plainSocket = d->plainTcpSocket();
Q_ASSERT(SecIsValidHandle(&credentialHandle));
@@ -1052,9 +1056,9 @@ bool TlsCryptographSchannel::acceptContext()
inBuffers[0] = createSecBuffer(intermediateBuffer, SECBUFFER_TOKEN);
#ifdef SUPPORTS_ALPN
- configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationNone;
+ QTlsBackend::setAlpnStatus(d, QSslConfiguration::NextProtocolNegotiationNone);
// The string must be alive when we call AcceptSecurityContext
- QByteArray alpnString = createAlpnString(configuration.nextAllowedProtocols);
+ QByteArray alpnString = createAlpnString(configuration.allowedNextProtocols());
if (!alpnString.isEmpty()) {
inBuffers[1] = createSecBuffer(alpnString, SECBUFFER_APPLICATION_PROTOCOLS);
} else
@@ -1269,7 +1273,7 @@ bool TlsCryptographSchannel::verifyHandshake()
{
Q_ASSERT(d);
Q_ASSERT(q);
- auto &configuration = d->privateConfiguration();
+ const auto &configuration = q->sslConfiguration();
sslErrors.clear();
@@ -1284,7 +1288,7 @@ bool TlsCryptographSchannel::verifyHandshake()
// Everything is set up, now make sure there's nothing wrong and query some attributes...
if (!matchesContextRequirements(contextAttributes, getContextRequirements(),
- configuration.peerVerifyMode, isClient)) {
+ configuration.peerVerifyMode(), isClient)) {
d->setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
QSslSocket::tr("Did not get the required attributes for the connection."));
return false;
@@ -1303,7 +1307,8 @@ bool TlsCryptographSchannel::verifyHandshake()
CHECK_STATUS(status);
#ifdef SUPPORTS_ALPN
- if (!configuration.nextAllowedProtocols.isEmpty() && supportsAlpn()) {
+ const auto allowedProtos = configuration.allowedNextProtocols();
+ if (!allowedProtos.isEmpty() && supportsAlpn()) {
SecPkgContext_ApplicationProtocol alpn;
status = QueryContextAttributes(&contextHandle,
SECPKG_ATTR_APPLICATION_PROTOCOL,
@@ -1312,16 +1317,16 @@ bool TlsCryptographSchannel::verifyHandshake()
if (alpn.ProtoNegoStatus == SecApplicationProtocolNegotiationStatus_Success) {
QByteArray negotiatedProto = QByteArray((const char *)alpn.ProtocolId,
alpn.ProtocolIdSize);
- if (!configuration.nextAllowedProtocols.contains(negotiatedProto)) {
+ if (!allowedProtos.contains(negotiatedProto)) {
d->setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
QSslSocket::tr("Unwanted protocol was negotiated"));
return false;
}
- configuration.nextNegotiatedProtocol = negotiatedProto;
- configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationNegotiated;
+ QTlsBackend::setNegotiatedProtocol(d, negotiatedProto);
+ QTlsBackend::setAlpnStatus(d, QSslConfiguration::NextProtocolNegotiationNegotiated);
} else {
- configuration.nextNegotiatedProtocol = "";
- configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationUnsupported;
+ QTlsBackend::setNegotiatedProtocol(d, {});
+ QTlsBackend::setAlpnStatus(d, QSslConfiguration::NextProtocolNegotiationUnsupported);
}
}
#endif // supports ALPN
@@ -1343,9 +1348,9 @@ bool TlsCryptographSchannel::verifyHandshake()
// To work around this we don't request a certificate at all for QueryPeer.
// For servers AutoVerifyPeer is supposed to be treated the same as QueryPeer.
// This means that servers using Schannel will only request client certificate for "VerifyPeer".
- if ((!isClient && configuration.peerVerifyMode == QSslSocket::PeerVerifyMode::VerifyPeer)
- || (isClient && configuration.peerVerifyMode != QSslSocket::PeerVerifyMode::VerifyNone
- && configuration.peerVerifyMode != QSslSocket::PeerVerifyMode::QueryPeer)) {
+ if ((!isClient && configuration.peerVerifyMode() == QSslSocket::PeerVerifyMode::VerifyPeer)
+ || (isClient && configuration.peerVerifyMode() != QSslSocket::PeerVerifyMode::VerifyNone
+ && configuration.peerVerifyMode() != QSslSocket::PeerVerifyMode::QueryPeer)) {
if (status != SEC_E_OK) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << "Couldn't retrieve peer certificate, status:"
@@ -1909,13 +1914,13 @@ bool TlsCryptographSchannel::checkSslErrors()
Q_ASSERT(q);
Q_ASSERT(d);
- const auto &configuration = d->privateConfiguration();
+ const auto &configuration = q->sslConfiguration();
auto *plainSocket = d->plainTcpSocket();
emit q->sslErrors(sslErrors);
- const bool doVerifyPeer = configuration.peerVerifyMode == QSslSocket::VerifyPeer
- || (configuration.peerVerifyMode == QSslSocket::AutoVerifyPeer
+ const bool doVerifyPeer = configuration.peerVerifyMode() == QSslSocket::VerifyPeer
+ || (configuration.peerVerifyMode() == QSslSocket::AutoVerifyPeer
&& d->tlsMode() == QSslSocket::SslClientMode);
const bool doEmitSslError = !d->verifyErrorsHaveBeenIgnored();
// check whether we need to emit an SSL handshake error
@@ -1938,7 +1943,8 @@ void TlsCryptographSchannel::initializeCertificateStores()
{
//// helper function which turns a chain into a certificate store
Q_ASSERT(d);
- const auto &configuration = d->privateConfiguration();
+ Q_ASSERT(q);
+ const auto &configuration = q->sslConfiguration();
auto createStoreFromCertificateChain = [](const QList<QSslCertificate> certChain, const QSslKey &privateKey) {
const wchar_t *passphrase = L"";
@@ -1952,22 +1958,22 @@ void TlsCryptographSchannel::initializeCertificateStores()
return QHCertStorePointer(PFXImportCertStore(&pfxBlob, passphrase, 0));
};
- if (!configuration.localCertificateChain.isEmpty()) {
- if (configuration.privateKey.isNull()) {
+ if (!configuration.localCertificateChain().isEmpty()) {
+ if (configuration.privateKey().isNull()) {
d->setErrorAndEmit(QAbstractSocket::SslInvalidUserDataError,
QSslSocket::tr("Cannot provide a certificate with no key"));
return;
}
if (localCertificateStore == nullptr) {
- localCertificateStore = createStoreFromCertificateChain(configuration.localCertificateChain,
- configuration.privateKey);
+ localCertificateStore = createStoreFromCertificateChain(configuration.localCertificateChain(),
+ configuration.privateKey());
if (localCertificateStore == nullptr)
qCWarning(lcSsl, "Failed to load certificate chain!");
}
}
- if (!configuration.caCertificates.isEmpty() && !caCertificateStore) {
- caCertificateStore = createStoreFromCertificateChain(configuration.caCertificates,
+ if (!configuration.caCertificates().isEmpty() && !caCertificateStore) {
+ caCertificateStore = createStoreFromCertificateChain(configuration.caCertificates(),
{}); // No private key for the CA certs
}
}
@@ -1977,7 +1983,6 @@ bool TlsCryptographSchannel::verifyCertContext(CERT_CONTEXT *certContext)
Q_ASSERT(certContext);
Q_ASSERT(q);
Q_ASSERT(d);
- auto &configuration = d->privateConfiguration();
const bool isClient = d->tlsMode() == QSslSocket::SslClientMode;
@@ -2038,8 +2043,7 @@ bool TlsCryptographSchannel::verifyCertContext(CERT_CONTEXT *certContext)
: szOID_PKIX_KP_CLIENT_AUTH);
parameters.RequestedUsage.Usage.rgpszUsageIdentifier = &oid;
- configuration.peerCertificate.clear();
- configuration.peerCertificateChain.clear();
+ QTlsBackend::clearPeerCertificates(d);
const CERT_CHAIN_CONTEXT *chainContext = nullptr;
auto freeCertChain = qScopeGuard([&chainContext]() {
if (chainContext)
@@ -2106,23 +2110,26 @@ bool TlsCryptographSchannel::verifyCertContext(CERT_CONTEXT *certContext)
}
DWORD verifyDepth = chain->cElement;
- if (configuration.peerVerifyDepth > 0 && DWORD(configuration.peerVerifyDepth) < verifyDepth)
- verifyDepth = DWORD(configuration.peerVerifyDepth);
+ if (q->peerVerifyDepth() > 0 && DWORD(q->peerVerifyDepth()) < verifyDepth)
+ verifyDepth = DWORD(q->peerVerifyDepth());
+ const auto &caCertificates = q->sslConfiguration().caCertificates();
+ QList<QSslCertificate> peerCertificateChain;
for (DWORD i = 0; i < verifyDepth; i++) {
CERT_CHAIN_ELEMENT *element = chain->rgpElement[i];
QSslCertificate certificate = getCertificateFromChainElement(element);
const QList<QSslCertificateExtension> extensions = certificate.extensions();
#ifdef QSSLSOCKET_DEBUG
- qCDebug(lcSsl) << "issuer:" << certificate.issuerDisplayName()
- << "\nsubject:" << certificate.subjectDisplayName()
- << "\nQSslCertificate info:" << certificate
- << "\nextended error info:" << element->pwszExtendedErrorInfo
- << "\nerror status:" << element->TrustStatus.dwErrorStatus;
+ qCDebug(lcTlsBackend) << "issuer:" << certificate.issuerDisplayName()
+ << "\nsubject:" << certificate.subjectDisplayName()
+ << "\nQSslCertificate info:" << certificate
+ << "\nextended error info:" << element->pwszExtendedErrorInfo
+ << "\nerror status:" << element->TrustStatus.dwErrorStatus;
#endif
- configuration.peerCertificateChain.append(certificate);
+ peerCertificateChain.append(certificate);
+ QTlsBackend::storePeerCertificateChain(d, peerCertificateChain);
if (certificate.isBlacklisted()) {
const auto error = QSslError(QSslError::CertificateBlacklisted, certificate);
@@ -2178,7 +2185,7 @@ bool TlsCryptographSchannel::verifyCertContext(CERT_CONTEXT *certContext)
}
if (element->TrustStatus.dwErrorStatus & CERT_TRUST_IS_UNTRUSTED_ROOT) {
// Override this error if we have the certificate inside our trusted CAs list.
- const bool isTrustedRoot = configuration.caCertificates.contains(certificate);
+ const bool isTrustedRoot = caCertificates.contains(certificate);
if (!isTrustedRoot) {
auto error = QSslError(QSslError::CertificateUntrusted, certificate);
sslErrors += error;
@@ -2257,25 +2264,26 @@ bool TlsCryptographSchannel::verifyCertContext(CERT_CONTEXT *certContext)
}
}
- if (!configuration.peerCertificateChain.isEmpty())
- configuration.peerCertificate = configuration.peerCertificateChain.first();
+ if (!peerCertificateChain.isEmpty())
+ QTlsBackend::storePeerCertificate(d, peerCertificateChain.first());
+ const auto &configuration = q->sslConfiguration(); // Probably, updated by QTlsBackend::storePeerCertificate etc.
// @Note: Somewhat copied from qsslsocket_mac.cpp
- const bool doVerifyPeer = configuration.peerVerifyMode == QSslSocket::VerifyPeer
- || (configuration.peerVerifyMode == QSslSocket::AutoVerifyPeer
+ const bool doVerifyPeer = q->peerVerifyMode() == QSslSocket::VerifyPeer
+ || (q->peerVerifyMode() == QSslSocket::AutoVerifyPeer
&& d->tlsMode() == QSslSocket::SslClientMode);
// Check the peer certificate itself. First try the subject's common name
// (CN) as a wildcard, then try all alternate subject name DNS entries the
// same way.
- if (!configuration.peerCertificate.isNull()) {
+ if (!configuration.peerCertificate().isNull()) {
// but only if we're a client connecting to a server
// if we're the server, don't check CN
if (d->tlsMode() == QSslSocket::SslClientMode) {
const auto verificationPeerName = d->verificationName();
const QString peerName(verificationPeerName.isEmpty() ? q->peerName() : verificationPeerName);
- if (!isMatchingHostname(configuration.peerCertificate, peerName)) {
+ if (!isMatchingHostname(configuration.peerCertificate(), peerName)) {
// No matches in common names or alternate names.
- const QSslError error(QSslError::HostNameMismatch, configuration.peerCertificate);
+ const QSslError error(QSslError::HostNameMismatch, configuration.peerCertificate());
sslErrors += error;
emit q->peerVerifyError(error);
if (q->state() != QAbstractSocket::ConnectedState)
diff --git a/src/network/ssl/qtls_st.cpp b/src/network/ssl/qtls_st.cpp
index 602f1ef409..e4f5c71c02 100644
--- a/src/network/ssl/qtls_st.cpp
+++ b/src/network/ssl/qtls_st.cpp
@@ -346,7 +346,7 @@ void TlsCryptographSecureTransport::continueHandshake()
Q_ASSERT(q);
Q_ASSERT(d);
d->setEncrypted(true);
-#ifdef QSSLSOCKET_DEBU
+#ifdef QSSLSOCKET_DEBUG
qCDebug(lcTlsBackend) << d->plainTcpSocket() << "connection encrypted";
#endif
@@ -355,12 +355,12 @@ void TlsCryptographSecureTransport::continueHandshake()
// a callback during handshake. We can only set our list of preferred protocols
// (and send it during handshake) and then receive what our peer has sent to us.
// And here we can finally try to find a match (if any).
- auto &configuration = d->privateConfiguration();
+ const auto &configuration = q->sslConfiguration();
if (__builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)) {
- const auto &requestedProtocols = configuration.nextAllowedProtocols;
+ const auto &requestedProtocols = configuration.allowedNextProtocols();
if (const int requestedCount = requestedProtocols.size()) {
- configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationNone;
- configuration.nextNegotiatedProtocol.clear();
+ QTlsBackend::setAlpnStatus(d, QSslConfiguration::NextProtocolNegotiationNone);
+ QTlsBackend::setNegotiatedProtocol(d, {});
QCFType<CFArrayRef> cfArray;
const OSStatus result = SSLCopyALPNProtocols(context, &cfArray);
@@ -374,12 +374,12 @@ void TlsCryptographSecureTransport::continueHandshake()
const auto requestedName = QString::fromLatin1(requestedProtocols[i]);
for (int j = 0; j < size; ++j) {
if (requestedName == peerProtocols[j]) {
- configuration.nextNegotiatedProtocol = requestedName.toLatin1();
- configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationNegotiated;
+ QTlsBackend::setNegotiatedProtocol(d, requestedName.toLatin1());
+ QTlsBackend::setAlpnStatus(d, QSslConfiguration::NextProtocolNegotiationNegotiated);
break;
}
}
- if (configuration.nextProtocolNegotiationStatus == QSslConfiguration::NextProtocolNegotiationNegotiated)
+ if (configuration.nextProtocolNegotiationStatus() == QSslConfiguration::NextProtocolNegotiationNegotiated)
break;
}
}
@@ -678,9 +678,9 @@ bool TlsCryptographSecureTransport::initSslContext()
SSLSetConnection(context, this);
- auto &configuration = d->privateConfiguration();
+ const auto &configuration = q->sslConfiguration();
if (mode == QSslSocket::SslServerMode
- && !configuration.localCertificateChain.isEmpty()) {
+ && !configuration.localCertificateChain().isEmpty()) {
QString errorDescription;
QAbstractSocket::SocketError errorCode = QAbstractSocket::UnknownSocketError;
if (!setSessionCertificate(errorDescription, errorCode)) {
@@ -698,7 +698,7 @@ bool TlsCryptographSecureTransport::initSslContext()
#if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_13_4, __IPHONE_11_0, __TVOS_11_0, __WATCHOS_4_0)
if (__builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)) {
- const auto protocolNames = configuration.nextAllowedProtocols;
+ const auto protocolNames = configuration.allowedNextProtocols();
QCFType<CFMutableArrayRef> cfNames(CFArrayCreateMutable(nullptr, 0, &kCFTypeArrayCallBacks));
if (cfNames) {
for (const QByteArray &name : protocolNames) {
@@ -748,7 +748,7 @@ bool TlsCryptographSecureTransport::initSslContext()
}
//
} else {
- if (configuration.peerVerifyMode != QSslSocket::VerifyNone) {
+ if (configuration.peerVerifyMode() != QSslSocket::VerifyNone) {
// kAlwaysAuthenticate - always fails even if we set break on client auth.
OSStatus err = SSLSetClientSideAuthenticate(context, kTryAuthenticate);
if (err == errSecSuccess) {
@@ -769,9 +769,9 @@ bool TlsCryptographSecureTransport::initSslContext()
SSLSetDiffieHellmanParams(context, dhparam, sizeof(dhparam));
#endif
}
- if (configuration.ciphers.size() > 0) {
+ if (configuration.ciphers().size() > 0) {
QVector<SSLCipherSuite> cfCiphers;
- for (const QSslCipher &cipher : configuration.ciphers) {
+ for (const QSslCipher &cipher : configuration.ciphers()) {
if (auto sslCipher = TlsCryptographSecureTransport::SSLCipherSuite_from_QSslCipher(cipher))
cfCiphers << sslCipher;
}
@@ -798,7 +798,7 @@ bool TlsCryptographSecureTransport::setSessionCertificate(QString &errorDescript
Q_ASSERT_X(context, Q_FUNC_INFO, "invalid SSL context (null)");
Q_ASSERT(d);
- const auto &configuration = d->privateConfiguration();
+ const auto &configuration = q->sslConfiguration();
#ifdef QSSLSOCKET_DEBUG
auto *plainSocket = d->plainTcpSocket();
@@ -806,12 +806,12 @@ bool TlsCryptographSecureTransport::setSessionCertificate(QString &errorDescript
QSslCertificate localCertificate;
- if (!configuration.localCertificateChain.isEmpty())
- localCertificate = configuration.localCertificateChain.at(0);
+ if (!configuration.localCertificateChain().isEmpty())
+ localCertificate = configuration.localCertificateChain().at(0);
if (!localCertificate.isNull()) {
// Require a private key as well.
- if (configuration.privateKey.isNull()) {
+ if (configuration.privateKey().isNull()) {
errorCode = QAbstractSocket::SslInvalidUserDataError;
errorDescription = QStringLiteral("Cannot provide a certificate with no key");
return false;
@@ -819,8 +819,8 @@ bool TlsCryptographSecureTransport::setSessionCertificate(QString &errorDescript
// import certificates and key
const QString passPhrase(QString::fromLatin1("foobar"));
- QCFType<CFDataRef> pkcs12 = _q_makePkcs12(configuration.localCertificateChain,
- configuration.privateKey, passPhrase).toCFData();
+ QCFType<CFDataRef> pkcs12 = _q_makePkcs12(configuration.localCertificateChain(),
+ configuration.privateKey(), passPhrase).toCFData();
QCFType<CFStringRef> password = passPhrase.toCFString();
const void *keys[2] = { kSecImportExportPassphrase };
const void *values[2] = { password };
@@ -904,14 +904,15 @@ bool TlsCryptographSecureTransport::setSessionCertificate(QString &errorDescript
bool TlsCryptographSecureTransport::setSessionProtocol()
{
Q_ASSERT_X(context, Q_FUNC_INFO, "invalid SSL context (null)");
+ Q_ASSERT(q);
Q_ASSERT(d);
// SecureTransport has kTLSProtocol13 constant and also, kTLSProtocolMaxSupported.
// Calling SSLSetProtocolVersionMax/Min with any of these two constants results
// in errInvalidParam and a failure to set the protocol version. This means
// no TLS 1.3 on macOS and iOS.
- const auto &configuration = d->privateConfiguration();
+ const auto &configuration = q->sslConfiguration();
auto *plainSocket = d->plainTcpSocket();
- switch (configuration.protocol) {
+ switch (configuration.protocol()) {
case QSsl::TlsV1_3:
case QSsl::TlsV1_3OrLater:
qCWarning(lcTlsBackend) << plainSocket << "SecureTransport does not support TLS 1.3";
@@ -921,48 +922,48 @@ bool TlsCryptographSecureTransport::setSessionProtocol()
OSStatus err = errSecSuccess;
- if (configuration.protocol == QSsl::TlsV1_0) {
+ if (configuration.protocol() == QSsl::TlsV1_0) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcTlsBackend) << plainSocket << "requesting : TLSv1.0";
#endif
err = SSLSetProtocolVersionMin(context, kTLSProtocol1);
if (err == errSecSuccess)
err = SSLSetProtocolVersionMax(context, kTLSProtocol1);
- } else if (configuration.protocol == QSsl::TlsV1_1) {
+ } else if (configuration.protocol() == QSsl::TlsV1_1) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcTlsBackend) << plainSocket << "requesting : TLSv1.1";
#endif
err = SSLSetProtocolVersionMin(context, kTLSProtocol11);
if (err == errSecSuccess)
err = SSLSetProtocolVersionMax(context, kTLSProtocol11);
- } else if (configuration.protocol == QSsl::TlsV1_2) {
+ } else if (configuration.protocol() == QSsl::TlsV1_2) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcTlsBackend) << plainSocket << "requesting : TLSv1.2";
#endif
err = SSLSetProtocolVersionMin(context, kTLSProtocol12);
if (err == errSecSuccess)
err = SSLSetProtocolVersionMax(context, kTLSProtocol12);
- } else if (configuration.protocol == QSsl::AnyProtocol) {
+ } else if (configuration.protocol() == QSsl::AnyProtocol) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcTlsBackend) << plainSocket << "requesting : any";
#endif
err = SSLSetProtocolVersionMin(context, kTLSProtocol1);
- } else if (configuration.protocol == QSsl::SecureProtocols) {
+ } else if (configuration.protocol() == QSsl::SecureProtocols) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcTlsBackend) << plainSocket << "requesting : TLSv1 - TLSv1.2";
#endif
err = SSLSetProtocolVersionMin(context, kTLSProtocol1);
- } else if (configuration.protocol == QSsl::TlsV1_0OrLater) {
+ } else if (configuration.protocol() == QSsl::TlsV1_0OrLater) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcTlsBackend) << plainSocket << "requesting : TLSv1 - TLSv1.2";
#endif
err = SSLSetProtocolVersionMin(context, kTLSProtocol1);
- } else if (configuration.protocol == QSsl::TlsV1_1OrLater) {
+ } else if (configuration.protocol() == QSsl::TlsV1_1OrLater) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcTlsBackend) << plainSocket << "requesting : TLSv1.1 - TLSv1.2";
#endif
err = SSLSetProtocolVersionMin(context, kTLSProtocol11);
- } else if (configuration.protocol == QSsl::TlsV1_2OrLater) {
+ } else if (configuration.protocol() == QSsl::TlsV1_2OrLater) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcTlsBackend) << plainSocket << "requesting : TLSv1.2";
#endif
@@ -979,9 +980,10 @@ bool TlsCryptographSecureTransport::setSessionProtocol()
bool TlsCryptographSecureTransport::canIgnoreTrustVerificationFailure() const
{
+ Q_ASSERT(q);
Q_ASSERT(d);
- const auto &configuration = d->privateConfiguration();
- const QSslSocket::PeerVerifyMode verifyMode = configuration.peerVerifyMode;
+ const auto &configuration = q->sslConfiguration();
+ const QSslSocket::PeerVerifyMode verifyMode = configuration.peerVerifyMode();
return d->tlsMode() == QSslSocket::SslServerMode
&& (verifyMode == QSslSocket::QueryPeer
|| verifyMode == QSslSocket::AutoVerifyPeer
@@ -990,24 +992,24 @@ bool TlsCryptographSecureTransport::canIgnoreTrustVerificationFailure() const
bool TlsCryptographSecureTransport::verifySessionProtocol() const
{
- Q_ASSERT(d);
+ Q_ASSERT(q);
- const auto &configuration = d->privateConfiguration();
+ const auto &configuration = q->sslConfiguration();
bool protocolOk = false;
- if (configuration.protocol == QSsl::AnyProtocol)
+ if (configuration.protocol() == QSsl::AnyProtocol)
protocolOk = true;
- else if (configuration.protocol == QSsl::SecureProtocols)
+ else if (configuration.protocol() == QSsl::SecureProtocols)
protocolOk = (sessionProtocol() >= QSsl::TlsV1_0);
- else if (configuration.protocol == QSsl::TlsV1_0OrLater)
+ else if (configuration.protocol() == QSsl::TlsV1_0OrLater)
protocolOk = (sessionProtocol() >= QSsl::TlsV1_0);
- else if (configuration.protocol == QSsl::TlsV1_1OrLater)
+ else if (configuration.protocol() == QSsl::TlsV1_1OrLater)
protocolOk = (sessionProtocol() >= QSsl::TlsV1_1);
- else if (configuration.protocol == QSsl::TlsV1_2OrLater)
+ else if (configuration.protocol() == QSsl::TlsV1_2OrLater)
protocolOk = (sessionProtocol() >= QSsl::TlsV1_2);
- else if (configuration.protocol == QSsl::TlsV1_3OrLater)
+ else if (configuration.protocol() == QSsl::TlsV1_3OrLater)
protocolOk = (sessionProtocol() >= QSsl::TlsV1_3OrLater);
else
- protocolOk = (sessionProtocol() == configuration.protocol);
+ protocolOk = (sessionProtocol() == configuration.protocol());
return protocolOk;
}
@@ -1017,9 +1019,8 @@ bool TlsCryptographSecureTransport::verifyPeerTrust()
Q_ASSERT(q);
Q_ASSERT(d);
- auto &configuration = d->privateConfiguration();
const auto mode = d->tlsMode();
- const QSslSocket::PeerVerifyMode verifyMode = configuration.peerVerifyMode;
+ const QSslSocket::PeerVerifyMode verifyMode = q->peerVerifyMode();
const bool canIgnoreVerify = canIgnoreTrustVerificationFailure();
Q_ASSERT_X(context, Q_FUNC_INFO, "invalid SSL context (null)");
@@ -1060,21 +1061,22 @@ bool TlsCryptographSecureTransport::verifyPeerTrust()
return false;
}
- configuration.peerCertificate.clear();
- configuration.peerCertificateChain.clear();
+ QTlsBackend::clearPeerCertificates(d);
+ QList<QSslCertificate> peerCertificateChain;
const CFIndex certCount = SecTrustGetCertificateCount(trust);
for (CFIndex i = 0; i < certCount; ++i) {
SecCertificateRef cert = SecTrustGetCertificateAtIndex(trust, i);
QCFType<CFDataRef> derData = SecCertificateCopyData(cert);
- configuration.peerCertificateChain << QSslCertificate(QByteArray::fromCFData(derData), QSsl::Der);
+ peerCertificateChain << QSslCertificate(QByteArray::fromCFData(derData), QSsl::Der);
}
+ QTlsBackend::storePeerCertificateChain(d, peerCertificateChain);
- if (configuration.peerCertificateChain.size())
- configuration.peerCertificate = configuration.peerCertificateChain.at(0);
+ if (peerCertificateChain.size())
+ QTlsBackend::storePeerCertificate(d, peerCertificateChain.at(0));
// Check the whole chain for blacklisting (including root, as we check for subjectInfo and issuer):
- for (const QSslCertificate &cert : qAsConst(configuration.peerCertificateChain)) {
+ for (const QSslCertificate &cert : qAsConst(peerCertificateChain)) {
if (QSslCertificatePrivate::isBlacklisted(cert) && !canIgnoreVerify) {
const QSslError error(QSslError::CertificateBlacklisted, cert);
errors << error;
@@ -1090,15 +1092,16 @@ bool TlsCryptographSecureTransport::verifyPeerTrust()
// Check the peer certificate itself. First try the subject's common name
// (CN) as a wildcard, then try all alternate subject name DNS entries the
// same way.
- if (!configuration.peerCertificate.isNull()) {
+ const auto &peerCertificate = q->peerCertificate();
+ if (!peerCertificate.isNull()) {
// but only if we're a client connecting to a server
// if we're the server, don't check CN
const QString verificationPeerName = d->verificationName();
if (mode == QSslSocket::SslClientMode) {
const QString peerName(verificationPeerName.isEmpty () ? q->peerName() : verificationPeerName);
- if (!isMatchingHostname(configuration.peerCertificate, peerName) && !canIgnoreVerify) {
+ if (!isMatchingHostname(peerCertificate, peerName) && !canIgnoreVerify) {
// No matches in common names or alternate names.
- const QSslError error(QSslError::HostNameMismatch, configuration.peerCertificate);
+ const QSslError error(QSslError::HostNameMismatch, peerCertificate);
errors << error;
emit q->peerVerifyError(error);
if (q->state() != QAbstractSocket::ConnectedState)
@@ -1119,7 +1122,8 @@ bool TlsCryptographSecureTransport::verifyPeerTrust()
// verify certificate chain
QCFType<CFMutableArrayRef> certArray = CFArrayCreateMutable(nullptr, 0, &kCFTypeArrayCallBacks);
- for (const QSslCertificate &cert : qAsConst(configuration.caCertificates)) {
+ const auto &caCertificates = q->sslConfiguration().caCertificates();
+ for (const QSslCertificate &cert : caCertificates) {
QCFType<CFDataRef> certData = cert.toDer().toCFData();
if (QCFType<SecCertificateRef> secRef = SecCertificateCreateWithData(nullptr, certData))
CFArrayAppendValue(certArray, secRef);
@@ -1165,7 +1169,7 @@ bool TlsCryptographSecureTransport::verifyPeerTrust()
break;
default:
if (!canIgnoreVerify) {
- const QSslError error(QSslError::CertificateUntrusted, configuration.peerCertificate);
+ const QSslError error(QSslError::CertificateUntrusted, peerCertificate);
errors << error;
emit q->peerVerifyError(error);
}
@@ -1199,9 +1203,9 @@ bool TlsCryptographSecureTransport::checkSslErrors()
emit q->sslErrors(sslErrors);
const auto mode = d->tlsMode();
- const auto &configuration = d->privateConfiguration();
- const bool doVerifyPeer = configuration.peerVerifyMode == QSslSocket::VerifyPeer
- || (configuration.peerVerifyMode == QSslSocket::AutoVerifyPeer
+ const auto &configuration = q->sslConfiguration();
+ const bool doVerifyPeer = configuration.peerVerifyMode() == QSslSocket::VerifyPeer
+ || (configuration.peerVerifyMode() == QSslSocket::AutoVerifyPeer
&& mode == QSslSocket::SslClientMode);
const bool doEmitSslError = !d->verifyErrorsHaveBeenIgnored();
// check whether we need to emit an SSL handshake error
diff --git a/src/network/ssl/qtlsbackend.cpp b/src/network/ssl/qtlsbackend.cpp
index 1d4cf2844f..079cbccbc0 100644
--- a/src/network/ssl/qtlsbackend.cpp
+++ b/src/network/ssl/qtlsbackend.cpp
@@ -701,6 +701,92 @@ void QTlsBackend::setDefaultCaCertificates(const QList<QSslCertificate> &certs)
QSslSocketPrivate::setDefaultCaCertificates(certs);
}
+bool QTlsBackend::rootLoadingOnDemandAllowed(const QSslConfiguration &configuration)
+{
+ return configuration.d->allowRootCertOnDemandLoading;
+}
+
+void QTlsBackend::storePeerCertificate(QSslConfiguration &configuration,
+ const QSslCertificate &peerCert)
+{
+ configuration.d->peerCertificate = peerCert;
+}
+
+void QTlsBackend::storePeerCertificateChain(QSslConfiguration &configuration,
+ const QList<QSslCertificate> &peerChain)
+{
+ configuration.d->peerCertificateChain = peerChain;
+}
+
+void QTlsBackend::clearPeerCertificates(QSslConfiguration &configuration)
+{
+ configuration.d->peerCertificate.clear();
+ configuration.d->peerCertificateChain.clear();
+}
+
+void QTlsBackend::clearPeerCertificates(QSslSocketPrivate *d)
+{
+ Q_ASSERT(d);
+ d->configuration.peerCertificate.clear();
+ d->configuration.peerCertificateChain.clear();
+}
+
+void QTlsBackend::setPeerSessionShared(QSslSocketPrivate *d, bool shared)
+{
+ Q_ASSERT(d);
+ d->configuration.peerSessionShared = shared;
+}
+
+void QTlsBackend::setSessionAsn1(QSslSocketPrivate *d, const QByteArray &asn1)
+{
+ Q_ASSERT(d);
+ d->configuration.sslSession = asn1;
+}
+
+void QTlsBackend::setSessionLifetimeHint(QSslSocketPrivate *d, int hint)
+{
+ Q_ASSERT(d);
+ d->configuration.sslSessionTicketLifeTimeHint = hint;
+}
+
+void QTlsBackend::setAlpnStatus(QSslSocketPrivate *d, AlpnNegotiationStatus st)
+{
+ Q_ASSERT(d);
+ d->configuration.nextProtocolNegotiationStatus = st;
+}
+
+void QTlsBackend::setNegotiatedProtocol(QSslSocketPrivate *d, const QByteArray &protocol)
+{
+ Q_ASSERT(d);
+ d->configuration.nextNegotiatedProtocol = protocol;
+}
+
+void QTlsBackend::storePeerCertificate(QSslSocketPrivate *d, const QSslCertificate &peerCert)
+{
+ Q_ASSERT(d);
+ d->configuration.peerCertificate = peerCert;
+}
+
+void QTlsBackend::storePeerCertificateChain(QSslSocketPrivate *d,
+ const QList<QSslCertificate> &peerChain)
+{
+ Q_ASSERT(d);
+ d->configuration.peerCertificateChain = peerChain;
+}
+
+void QTlsBackend::addTustedRoot(QSslSocketPrivate *d, const QSslCertificate &rootCert)
+{
+ Q_ASSERT(d);
+ if (!d->configuration.caCertificates.contains(rootCert))
+ d->configuration.caCertificates += rootCert;
+}
+
+void QTlsBackend::setEphemeralKey(QSslSocketPrivate *d, const QSslKey &key)
+{
+ Q_ASSERT(d);
+ d->configuration.ephemeralServerKey = key;
+}
+
#endif // QT_CONFIG(ssl)
QT_END_NAMESPACE
diff --git a/src/network/ssl/qtlsbackend_p.h b/src/network/ssl/qtlsbackend_p.h
index 9015be7a8e..4d2bc25300 100644
--- a/src/network/ssl/qtlsbackend_p.h
+++ b/src/network/ssl/qtlsbackend_p.h
@@ -405,6 +405,29 @@ public:
static void resetDefaultEllipticCurves();
static void setDefaultCaCertificates(const QList<QSslCertificate> &certs);
+
+ // Many thanks to people who designed QSslConfiguration with hidden
+ // data-members, that sneakily set by some 'friend' classes, having
+ // some twisted logic.
+ static bool rootLoadingOnDemandAllowed(const QSslConfiguration &configuration);
+ static void storePeerCertificate(QSslConfiguration &configuration, const QSslCertificate &peerCert);
+ static void storePeerCertificateChain(QSslConfiguration &configuration,
+ const QList<QSslCertificate> &peerCertificateChain);
+ static void clearPeerCertificates(QSslConfiguration &configuration);
+ // And those are even worse, this is where we don't have the original configuration,
+ // and can have only a copy. So instead we go to d->privateConfiguration.someMember:
+ static void clearPeerCertificates(QSslSocketPrivate *d);
+ static void setPeerSessionShared(QSslSocketPrivate *d, bool shared);
+ static void setSessionAsn1(QSslSocketPrivate *d, const QByteArray &asn1);
+ static void setSessionLifetimeHint(QSslSocketPrivate *d, int hint);
+ using AlpnNegotiationStatus = QSslConfiguration::NextProtocolNegotiationStatus;
+ static void setAlpnStatus(QSslSocketPrivate *d, AlpnNegotiationStatus st);
+ static void setNegotiatedProtocol(QSslSocketPrivate *d, const QByteArray &protocol);
+ static void storePeerCertificate(QSslSocketPrivate *d, const QSslCertificate &peerCert);
+ static void storePeerCertificateChain(QSslSocketPrivate *d, const QList<QSslCertificate> &peerChain);
+ static void addTustedRoot(QSslSocketPrivate *d, const QSslCertificate &rootCert);
+ // The next one - is a "very important" feature! Kidding ...
+ static void setEphemeralKey(QSslSocketPrivate *d, const QSslKey &key);
#endif // QT_CONFIG(ssl)
Q_DISABLE_COPY_MOVE(QTlsBackend)