summaryrefslogtreecommitdiffstats
path: root/src/network/ssl/qsslsocket.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/ssl/qsslsocket.cpp')
-rw-r--r--src/network/ssl/qsslsocket.cpp537
1 files changed, 424 insertions, 113 deletions
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index 9a02f439ab..395394d432 100644
--- a/src/network/ssl/qsslsocket.cpp
+++ b/src/network/ssl/qsslsocket.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtNetwork module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2014 BlackBerry Limited. All rights reserved.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
//#define QSSLSOCKET_DEBUG
@@ -54,10 +18,10 @@
QSslSocket establishes a secure, encrypted TCP connection you can
use for transmitting encrypted data. It can operate in both client
- and server mode, and it supports modern SSL protocols, including
- SSL 3 and TLS 1.2. By default, QSslSocket uses only SSL protocols
+ and server mode, and it supports modern TLS protocols, including
+ TLS 1.3. By default, QSslSocket uses only TLS protocols
which are considered to be secure (QSsl::SecureProtocols), but you can
- change the SSL protocol by calling setProtocol() as long as you do
+ change the TLS protocol by calling setProtocol() as long as you do
it before the handshake has started.
SSL encryption operates on top of the existing TCP stream after
@@ -133,8 +97,7 @@
\list
\li The socket's cryptographic cipher suite can be customized before
- the handshake phase with QSslConfiguration::setCiphers()
- and QSslConfiguration::setDefaultCiphers().
+ the handshake phase with QSslConfiguration::setCiphers().
\li The socket's local certificate and private key can be customized
before the handshake phase with setLocalCertificate() and
setPrivateKey().
@@ -188,7 +151,7 @@
behavior is identical to QTcpSocket.
\value SslClientMode The socket is a client-side SSL socket.
- It is either alreayd encrypted, or it is in the SSL handshake
+ It is either already encrypted, or it is in the SSL handshake
phase (see QSslSocket::isEncrypted()).
\value SslServerMode The socket is a server-side SSL socket.
@@ -386,16 +349,8 @@
#include "qsslcipher.h"
#include "qocspresponse.h"
#include "qtlsbackend_p.h"
-#ifndef QT_NO_OPENSSL
-#include "qsslsocket_openssl_p.h"
-#endif
-#ifdef QT_SECURETRANSPORT
-#include "qsslsocket_mac_p.h"
-#endif
-#if QT_CONFIG(schannel)
-#include "qsslsocket_schannel_p.h"
-#endif
#include "qsslconfiguration_p.h"
+#include "qsslsocket_p.h"
#include <QtCore/qdebug.h>
#include <QtCore/qdir.h>
@@ -407,6 +362,14 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
+#ifdef Q_OS_VXWORKS
+constexpr auto isVxworks = true;
+#else
+constexpr auto isVxworks = false;
+#endif
+
class QSslSocketGlobalData
{
public:
@@ -433,7 +396,7 @@ Q_GLOBAL_STATIC(QSslSocketGlobalData, globalData)
set to the one returned by the static method defaultCiphers().
*/
QSslSocket::QSslSocket(QObject *parent)
- : QTcpSocket(*new QSslSocketBackendPrivate, parent)
+ : QTcpSocket(*new QSslSocketPrivate, parent)
{
Q_D(QSslSocket);
#ifdef QSSLSOCKET_DEBUG
@@ -903,7 +866,8 @@ void QSslSocket::close()
// On Windows, CertGetCertificateChain is probably still doing its
// job, if the socket is re-used, we want to ignore its reported
// root CA.
- d->caToFetch = QSslCertificate{};
+ if (auto *backend = d->backend.get())
+ backend->cancelCAFetch();
if (!d->abortCalled && (encryptedBytesToWrite() || !d->writeBuffer.isEmpty()))
flush();
@@ -1210,7 +1174,9 @@ QSsl::SslProtocol QSslSocket::sessionProtocol() const
QList<QOcspResponse> QSslSocket::ocspResponses() const
{
Q_D(const QSslSocket);
- return d->ocspResponses;
+ if (const auto *backend = d->backend.get())
+ return backend->ocsps();
+ return {};
}
/*!
@@ -1485,7 +1451,9 @@ bool QSslSocket::waitForDisconnected(int msecs)
QList<QSslError> QSslSocket::sslHandshakeErrors() const
{
Q_D(const QSslSocket);
- return d->sslErrors;
+ if (const auto *backend = d->backend.get())
+ return backend->tlsErrors();
+ return {};
}
/*!
@@ -1502,12 +1470,14 @@ bool QSslSocket::supportsSsl()
\since 5.0
Returns the version number of the SSL library in use. Note that
this is the version of the library in use at run-time not compile
- time. If no SSL support is available then this will return an
- undefined value.
+ time. If no SSL support is available then this will return -1.
*/
long QSslSocket::sslLibraryVersionNumber()
{
- return QSslSocketPrivate::sslLibraryVersionNumber();
+ if (const auto *tlsBackend = QSslSocketPrivate::tlsBackendInUse())
+ return tlsBackend->tlsLibraryVersionNumber();
+
+ return -1;
}
/*!
@@ -1518,20 +1488,23 @@ long QSslSocket::sslLibraryVersionNumber()
*/
QString QSslSocket::sslLibraryVersionString()
{
- return QSslSocketPrivate::sslLibraryVersionString();
+ if (const auto *tlsBackend = QSslSocketPrivate::tlsBackendInUse())
+ return tlsBackend->tlsLibraryVersionString();
+ return {};
}
/*!
\since 5.4
Returns the version number of the SSL library in use at compile
- time. If no SSL support is available then this will return an
- undefined value.
+ time. If no SSL support is available then this will return -1.
\sa sslLibraryVersionNumber()
*/
long QSslSocket::sslLibraryBuildVersionNumber()
{
- return QSslSocketPrivate::sslLibraryBuildVersionNumber();
+ if (const auto *tlsBackend = QSslSocketPrivate::tlsBackendInUse())
+ return tlsBackend->tlsLibraryBuildVersionNumber();
+ return -1;
}
/*!
@@ -1544,7 +1517,10 @@ long QSslSocket::sslLibraryBuildVersionNumber()
*/
QString QSslSocket::sslLibraryBuildVersionString()
{
- return QSslSocketPrivate::sslLibraryBuildVersionString();
+ if (const auto *tlsBackend = QSslSocketPrivate::tlsBackendInUse())
+ return tlsBackend->tlsLibraryBuildVersionString();
+
+ return {};
}
/*!
@@ -1568,7 +1544,12 @@ QList<QString> QSslSocket::availableBackends()
from the list of available backends.
\note When selecting a default backend implicitly, QSslSocket prefers
- native backends, such as SecureTransport on Darwin, or Schannel on Windows.
+ the OpenSSL backend if available. If it's not available, the Schannel backend
+ is implicitly selected on Windows, and Secure Transport on Darwin platforms.
+ Failing these, if a custom TLS backend is found, it is used.
+ If no other backend is found, the "certificate only" backend is selected.
+ For more information about TLS plugins, please see
+ \l {Enabling and Disabling SSL Support when Building Qt from Source}.
\sa setActiveBackend(), availableBackends()
*/
@@ -1857,7 +1838,8 @@ void QSslSocket::ignoreSslErrors(const QList<QSslError> &errors)
void QSslSocket::continueInterruptedHandshake()
{
Q_D(QSslSocket);
- d->handshakeInterrupted = false;
+ if (auto *backend = d->backend.get())
+ backend->enableHandshakeContinuation();
}
/*!
@@ -1914,7 +1896,8 @@ void QSslSocket::disconnectFromHost()
}
// Make sure we don't process any signal from the CA fetcher
// (Windows):
- d->caToFetch = QSslCertificate{};
+ if (auto *backend = d->backend.get())
+ backend->cancelCAFetch();
// Perhaps emit closing()
if (d->state != ClosingState) {
@@ -1982,6 +1965,8 @@ qint64 QSslSocket::writeData(const char *data, qint64 len)
return len;
}
+bool QSslSocketPrivate::s_loadRootCertsOnDemand = false;
+
/*!
\internal
*/
@@ -1990,7 +1975,6 @@ QSslSocketPrivate::QSslSocketPrivate()
, mode(QSslSocket::UnencryptedMode)
, autoStartHandshake(false)
, connectionEncrypted(false)
- , shutdown(false)
, ignoreAllSslErrors(false)
, readyReadEmittedPointer(nullptr)
, allowRootCertOnDemandLoading(true)
@@ -1999,6 +1983,21 @@ QSslSocketPrivate::QSslSocketPrivate()
, flushTriggered(false)
{
QSslConfigurationPrivate::deepCopyDefaultConfiguration(&configuration);
+ // If the global configuration doesn't allow root certificates to be loaded
+ // on demand then we have to disable it for this socket as well.
+ if (!configuration.allowRootCertOnDemandLoading)
+ allowRootCertOnDemandLoading = false;
+
+ const auto *tlsBackend = tlsBackendInUse();
+ if (!tlsBackend) {
+ qCWarning(lcSsl, "No TLS backend is available");
+ return;
+ }
+ backend.reset(tlsBackend->createTlsCryptograph());
+ if (!backend.get()) {
+ qCWarning(lcSsl) << "The backend named" << tlsBackend->backendName()
+ << "does not support TLS";
+ }
}
/*!
@@ -2011,28 +2010,54 @@ QSslSocketPrivate::~QSslSocketPrivate()
/*!
\internal
*/
+bool QSslSocketPrivate::supportsSsl()
+{
+ if (const auto *tlsBackend = tlsBackendInUse())
+ return tlsBackend->implementedClasses().contains(QSsl::ImplementedClass::Socket);
+ return false;
+}
+
+/*!
+ \internal
+
+ Declared static in QSslSocketPrivate, makes sure the SSL libraries have
+ been initialized.
+*/
+void QSslSocketPrivate::ensureInitialized()
+{
+ if (!supportsSsl())
+ return;
+
+ const auto *tlsBackend = tlsBackendInUse();
+ Q_ASSERT(tlsBackend);
+ tlsBackend->ensureInitialized();
+}
+
+/*!
+ \internal
+*/
void QSslSocketPrivate::init()
{
+ // TLSTODO: delete those data members.
mode = QSslSocket::UnencryptedMode;
autoStartHandshake = false;
connectionEncrypted = false;
ignoreAllSslErrors = false;
- shutdown = false;
abortCalled = false;
pendingClose = false;
flushTriggered = false;
- ocspResponses.clear();
- systemOrSslErrorDetected = false;
- // we don't want to clear the ignoreErrorsList, so
- // that it is possible setting it before connecting
-// ignoreErrorsList.clear();
+ // We don't want to clear the ignoreErrorsList, so
+ // that it is possible setting it before connecting.
buffer.clear();
writeBuffer.clear();
configuration.peerCertificate.clear();
configuration.peerCertificateChain.clear();
- fetchAuthorityInformation = false;
- caToFetch = QSslCertificate{};
+
+ if (backend.get()) {
+ Q_ASSERT(q_ptr);
+ backend->init(static_cast<QSslSocket *>(q_ptr), this);
+ }
}
/*!
@@ -2040,13 +2065,15 @@ void QSslSocketPrivate::init()
*/
bool QSslSocketPrivate::verifyProtocolSupported(const char *where)
{
- QLatin1String protocolName("DTLS");
+ auto protocolName = "DTLS"_L1;
switch (configuration.protocol) {
case QSsl::UnknownProtocol:
// UnknownProtocol, according to our docs, is for cipher whose protocol is unknown.
// Should not be used when configuring QSslSocket.
- protocolName = QLatin1String("UnknownProtocol");
+ protocolName = "UnknownProtocol"_L1;
Q_FALLTHROUGH();
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
case QSsl::DtlsV1_0:
case QSsl::DtlsV1_2:
case QSsl::DtlsV1_0OrLater:
@@ -2055,6 +2082,7 @@ bool QSslSocketPrivate::verifyProtocolSupported(const char *where)
setErrorAndEmit(QAbstractSocket::SslInvalidUserDataError,
QSslSocket::tr("Attempted to use an unsupported protocol."));
return false;
+QT_WARNING_POP
default:
return true;
}
@@ -2103,7 +2131,35 @@ void QSslSocketPrivate::setDefaultSupportedCiphers(const QList<QSslCipher> &ciph
/*!
\internal
*/
-void q_setDefaultDtlsCiphers(const QList<QSslCipher> &ciphers)
+void QSslSocketPrivate::resetDefaultEllipticCurves()
+{
+ const auto *tlsBackend = tlsBackendInUse();
+ if (!tlsBackend)
+ return;
+
+ auto ids = tlsBackend->ellipticCurvesIds();
+ if (!ids.size())
+ return;
+
+ QList<QSslEllipticCurve> curves;
+ curves.reserve(ids.size());
+ for (int id : ids) {
+ QSslEllipticCurve curve;
+ curve.id = id;
+ curves.append(curve);
+ }
+
+ // Set the list of supported ECs, but not the list
+ // of *default* ECs. OpenSSL doesn't like forcing an EC for the wrong
+ // ciphersuite, so don't try it -- leave the empty list to mean
+ // "the implementation will choose the most suitable one".
+ setDefaultSupportedEllipticCurves(curves);
+}
+
+/*!
+ \internal
+*/
+void QSslSocketPrivate::setDefaultDtlsCiphers(const QList<QSslCipher> &ciphers)
{
QMutexLocker locker(&globalData()->mutex);
globalData()->dtlsConfig.detach();
@@ -2113,7 +2169,7 @@ void q_setDefaultDtlsCiphers(const QList<QSslCipher> &ciphers)
/*!
\internal
*/
-QList<QSslCipher> q_getDefaultDtlsCiphers()
+QList<QSslCipher> QSslSocketPrivate::defaultDtlsCiphers()
{
QSslSocketPrivate::ensureInitialized();
QMutexLocker locker(&globalData()->mutex);
@@ -2239,6 +2295,7 @@ void QSslConfigurationPrivate::deepCopyDefaultConfiguration(QSslConfigurationPri
ptr->sessionProtocol = global->sessionProtocol;
ptr->ciphers = global->ciphers;
ptr->caCertificates = global->caCertificates;
+ ptr->allowRootCertOnDemandLoading = global->allowRootCertOnDemandLoading;
ptr->protocol = global->protocol;
ptr->peerVerifyMode = global->peerVerifyMode;
ptr->peerVerifyDepth = global->peerVerifyDepth;
@@ -2360,6 +2417,11 @@ bool QSslSocketPrivate::isPaused() const
return paused;
}
+void QSslSocketPrivate::setPaused(bool p)
+{
+ paused = p;
+}
+
bool QSslSocketPrivate::bind(const QHostAddress &address, quint16 port, QAbstractSocket::BindMode mode)
{
// this function is called from QAbstractSocket::bind
@@ -2590,6 +2652,7 @@ void QSslSocketPrivate::_q_resumeImplementation()
if (verifyErrorsHaveBeenIgnored()) {
continueHandshake();
} else {
+ const auto sslErrors = backend->tlsErrors();
Q_ASSERT(!sslErrors.isEmpty());
setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, sslErrors.constFirst().errorString());
plainSocket->disconnectFromHost();
@@ -2604,13 +2667,16 @@ void QSslSocketPrivate::_q_resumeImplementation()
*/
bool QSslSocketPrivate::verifyErrorsHaveBeenIgnored()
{
+ Q_ASSERT(backend.get());
+
bool doEmitSslError;
if (!ignoreErrorsList.empty()) {
// check whether the errors we got are all in the list of expected errors
// (applies only if the method QSslSocket::ignoreSslErrors(const QList<QSslError> &errors)
// was called)
+ const auto &sslErrors = backend->tlsErrors();
doEmitSslError = false;
- for (int a = 0; a < sslErrors.count(); a++) {
+ for (int a = 0; a < sslErrors.size(); a++) {
if (!ignoreErrorsList.contains(sslErrors.at(a))) {
doEmitSslError = true;
break;
@@ -2628,6 +2694,91 @@ bool QSslSocketPrivate::verifyErrorsHaveBeenIgnored()
/*!
\internal
*/
+bool QSslSocketPrivate::isAutoStartingHandshake() const
+{
+ return autoStartHandshake;
+}
+
+/*!
+ \internal
+*/
+bool QSslSocketPrivate::isPendingClose() const
+{
+ return pendingClose;
+}
+
+/*!
+ \internal
+*/
+void QSslSocketPrivate::setPendingClose(bool pc)
+{
+ pendingClose = pc;
+}
+
+/*!
+ \internal
+*/
+qint64 QSslSocketPrivate::maxReadBufferSize() const
+{
+ return readBufferMaxSize;
+}
+
+/*!
+ \internal
+*/
+void QSslSocketPrivate::setMaxReadBufferSize(qint64 maxSize)
+{
+ readBufferMaxSize = maxSize;
+}
+
+/*!
+ \internal
+*/
+void QSslSocketPrivate::setEncrypted(bool enc)
+{
+ connectionEncrypted = enc;
+}
+
+/*!
+ \internal
+*/
+QIODevicePrivate::QRingBufferRef &QSslSocketPrivate::tlsWriteBuffer()
+{
+ return writeBuffer;
+}
+
+/*!
+ \internal
+*/
+QIODevicePrivate::QRingBufferRef &QSslSocketPrivate::tlsBuffer()
+{
+ return buffer;
+}
+
+/*!
+ \internal
+*/
+bool &QSslSocketPrivate::tlsEmittedBytesWritten()
+{
+ return emittedBytesWritten;
+}
+
+/*!
+ \internal
+*/
+bool *QSslSocketPrivate::readyReadPointer()
+{
+ return readyReadEmittedPointer;
+}
+
+bool QSslSocketPrivate::hasUndecryptedData() const
+{
+ return backend.get() && backend->hasUndecryptedData();
+}
+
+/*!
+ \internal
+*/
qint64 QSslSocketPrivate::peek(char *data, qint64 maxSize)
{
if (mode == QSslSocket::UnencryptedMode && !autoStartHandshake) {
@@ -2643,9 +2794,9 @@ qint64 QSslSocketPrivate::peek(char *data, qint64 maxSize)
if (r2 < 0)
return (r > 0 ? r : r2);
return r + r2;
- } else {
- return -1;
}
+
+ return -1;
} else {
//encrypted mode - the socket engine will read and decrypt data into the QIODevice buffer
return QTcpSocketPrivate::peek(data, maxSize);
@@ -2663,13 +2814,13 @@ QByteArray QSslSocketPrivate::peek(qint64 maxSize)
QByteArray ret;
ret.reserve(maxSize);
ret.resize(buffer.peek(ret.data(), maxSize, transactionPos));
- if (ret.length() == maxSize)
+ if (ret.size() == maxSize)
return ret;
//peek at data in the plain socket
if (plainSocket)
- return ret + plainSocket->peek(maxSize - ret.length());
- else
- return QByteArray();
+ return ret + plainSocket->peek(maxSize - ret.size());
+
+ return QByteArray();
} else {
//encrypted mode - the socket engine will read and decrypt data into the QIODevice buffer
return QTcpSocketPrivate::peek(maxSize);
@@ -2711,6 +2862,82 @@ bool QSslSocketPrivate::flush()
/*!
\internal
*/
+void QSslSocketPrivate::startClientEncryption()
+{
+ if (backend.get())
+ backend->startClientEncryption();
+}
+
+/*!
+ \internal
+*/
+void QSslSocketPrivate::startServerEncryption()
+{
+ if (backend.get())
+ backend->startServerEncryption();
+}
+
+/*!
+ \internal
+*/
+void QSslSocketPrivate::transmit()
+{
+ if (backend.get())
+ backend->transmit();
+}
+
+/*!
+ \internal
+*/
+void QSslSocketPrivate::disconnectFromHost()
+{
+ if (backend.get())
+ backend->disconnectFromHost();
+}
+
+/*!
+ \internal
+*/
+void QSslSocketPrivate::disconnected()
+{
+ if (backend.get())
+ backend->disconnected();
+}
+
+/*!
+ \internal
+*/
+QSslCipher QSslSocketPrivate::sessionCipher() const
+{
+ if (backend.get())
+ return backend->sessionCipher();
+
+ return {};
+}
+
+/*!
+ \internal
+*/
+QSsl::SslProtocol QSslSocketPrivate::sessionProtocol() const
+{
+ if (backend.get())
+ return backend->sessionProtocol();
+
+ return QSsl::UnknownProtocol;
+}
+
+/*!
+ \internal
+*/
+void QSslSocketPrivate::continueHandshake()
+{
+ if (backend.get())
+ backend->continueHandshake();
+}
+
+/*!
+ \internal
+*/
bool QSslSocketPrivate::rootCertOnDemandLoadingSupported()
{
return s_loadRootCertsOnDemand;
@@ -2719,34 +2946,63 @@ bool QSslSocketPrivate::rootCertOnDemandLoadingSupported()
/*!
\internal
*/
+void QSslSocketPrivate::setRootCertOnDemandLoadingSupported(bool supported)
+{
+ s_loadRootCertsOnDemand = supported;
+}
+
+/*!
+ \internal
+*/
QList<QByteArray> QSslSocketPrivate::unixRootCertDirectories()
{
- return QList<QByteArray>() << "/etc/ssl/certs/" // (K)ubuntu, OpenSUSE, Mandriva ...
- << "/usr/lib/ssl/certs/" // Gentoo, Mandrake
- << "/usr/share/ssl/" // Centos, Redhat, SuSE
- << "/usr/local/ssl/" // Normal OpenSSL Tarball
- << "/var/ssl/certs/" // AIX
- << "/usr/local/ssl/certs/" // Solaris
- << "/etc/openssl/certs/" // BlackBerry
- << "/opt/openssl/certs/" // HP-UX
- << "/etc/ssl/"; // OpenBSD
+ const auto ba = [](const auto &cstr) constexpr {
+ return QByteArray::fromRawData(std::begin(cstr), std::size(cstr) - 1);
+ };
+ static const QByteArray dirs[] = {
+ ba("/etc/ssl/certs/"), // (K)ubuntu, OpenSUSE, Mandriva ...
+ ba("/usr/lib/ssl/certs/"), // Gentoo, Mandrake
+ ba("/usr/share/ssl/"), // Centos, Redhat, SuSE
+ ba("/usr/local/ssl/"), // Normal OpenSSL Tarball
+ ba("/var/ssl/certs/"), // AIX
+ ba("/usr/local/ssl/certs/"), // Solaris
+ ba("/etc/openssl/certs/"), // BlackBerry
+ ba("/opt/openssl/certs/"), // HP-UX
+ ba("/etc/ssl/"), // OpenBSD
+ };
+ QList<QByteArray> result = QList<QByteArray>::fromReadOnlyData(dirs);
+ if constexpr (isVxworks) {
+ static QByteArray vxworksCertsDir = qgetenv("VXWORKS_CERTS_DIR");
+ if (!vxworksCertsDir.isEmpty())
+ result.push_back(vxworksCertsDir);
+ }
+ return result;
}
/*!
\internal
*/
-void QSslSocketPrivate::checkSettingSslContext(QSslSocket* socket, QSharedPointer<QSslContext> sslContext)
+void QSslSocketPrivate::checkSettingSslContext(QSslSocket* socket, std::shared_ptr<QSslContext> tlsContext)
{
- if (socket->d_func()->sslContextPointer.isNull())
- socket->d_func()->sslContextPointer = sslContext;
+ if (!socket)
+ return;
+
+ if (auto *backend = socket->d_func()->backend.get())
+ backend->checkSettingSslContext(tlsContext);
}
/*!
\internal
*/
-QSharedPointer<QSslContext> QSslSocketPrivate::sslContext(QSslSocket *socket)
+std::shared_ptr<QSslContext> QSslSocketPrivate::sslContext(QSslSocket *socket)
{
- return (socket) ? socket->d_func()->sslContextPointer : QSharedPointer<QSslContext>();
+ if (!socket)
+ return {};
+
+ if (const auto *backend = socket->d_func()->backend.get())
+ return backend->sslContext();
+
+ return {};
}
bool QSslSocketPrivate::isMatchingHostname(const QSslCertificate &cert, const QString &peerName)
@@ -2786,17 +3042,17 @@ bool QSslSocketPrivate::isMatchingHostname(const QSslCertificate &cert, const QS
*/
bool QSslSocketPrivate::isMatchingHostname(const QString &cn, const QString &hostname)
{
- int wildcard = cn.indexOf(QLatin1Char('*'));
+ qsizetype wildcard = cn.indexOf(u'*');
// Check this is a wildcard cert, if not then just compare the strings
if (wildcard < 0)
- return QLatin1String(QUrl::toAce(cn)) == hostname;
+ return QLatin1StringView(QUrl::toAce(cn)) == hostname;
- int firstCnDot = cn.indexOf(QLatin1Char('.'));
- int secondCnDot = cn.indexOf(QLatin1Char('.'), firstCnDot+1);
+ qsizetype firstCnDot = cn.indexOf(u'.');
+ qsizetype secondCnDot = cn.indexOf(u'.', firstCnDot+1);
// Check at least 3 components
- if ((-1 == secondCnDot) || (secondCnDot+1 >= cn.length()))
+ if ((-1 == secondCnDot) || (secondCnDot+1 >= cn.size()))
return false;
// Check * is last character of 1st component (ie. there's a following .)
@@ -2804,12 +3060,12 @@ bool QSslSocketPrivate::isMatchingHostname(const QString &cn, const QString &hos
return false;
// Check only one star
- if (cn.lastIndexOf(QLatin1Char('*')) != wildcard)
+ if (cn.lastIndexOf(u'*') != wildcard)
return false;
// Reject wildcard character embedded within the A-labels or U-labels of an internationalized
// domain name (RFC6125 section 7.2)
- if (cn.startsWith(QLatin1String("xn--"), Qt::CaseInsensitive))
+ if (cn.startsWith("xn--"_L1, Qt::CaseInsensitive))
return false;
// Check characters preceding * (if any) match
@@ -2817,9 +3073,9 @@ bool QSslSocketPrivate::isMatchingHostname(const QString &cn, const QString &hos
return false;
// Check characters following first . match
- int hnDot = hostname.indexOf(QLatin1Char('.'));
+ qsizetype hnDot = hostname.indexOf(u'.');
if (QStringView{hostname}.mid(hnDot + 1) != QStringView{cn}.mid(firstCnDot + 1)
- && QStringView{hostname}.mid(hnDot + 1) != QLatin1String(QUrl::toAce(cn.mid(firstCnDot + 1)))) {
+ && QStringView{hostname}.mid(hnDot + 1) != QLatin1StringView(QUrl::toAce(cn.mid(firstCnDot + 1)))) {
return false;
}
@@ -2849,7 +3105,62 @@ QTlsBackend *QSslSocketPrivate::tlsBackendInUse()
return nullptr;
}
- return tlsBackend = QTlsBackend::findBackend(activeBackendName);
+ tlsBackend = QTlsBackend::findBackend(activeBackendName);
+ if (tlsBackend) {
+ QObject::connect(tlsBackend, &QObject::destroyed, tlsBackend, [] {
+ const QMutexLocker locker(&backendMutex);
+ tlsBackend = nullptr;
+ },
+ Qt::DirectConnection);
+ }
+ return tlsBackend;
+}
+
+/*!
+ \internal
+*/
+QSslSocket::SslMode QSslSocketPrivate::tlsMode() const
+{
+ return mode;
+}
+
+/*!
+ \internal
+*/
+bool QSslSocketPrivate::isRootsOnDemandAllowed() const
+{
+ return allowRootCertOnDemandLoading;
+}
+
+/*!
+ \internal
+*/
+QString QSslSocketPrivate::verificationName() const
+{
+ return verificationPeerName;
+}
+
+/*!
+ \internal
+*/
+QString QSslSocketPrivate::tlsHostName() const
+{
+ return hostName;
+}
+
+QTcpSocket *QSslSocketPrivate::plainTcpSocket() const
+{
+ return plainSocket;
+}
+
+/*!
+ \internal
+*/
+QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()
+{
+ if (const auto *tlsBackend = tlsBackendInUse())
+ return tlsBackend->systemCaCertificates();
+ return {};
}
QT_END_NAMESPACE