diff options
Diffstat (limited to 'src/network/ssl/qsslsocket.cpp')
-rw-r--r-- | src/network/ssl/qsslsocket.cpp | 119 |
1 files changed, 57 insertions, 62 deletions
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index 47f4968f03..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. @@ -399,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: @@ -1573,7 +1544,12 @@ QList<QString> QSslSocket::availableBackends() from the list of available backends. \note When selecting a default backend implicitly, QSslSocket prefers - the OpenSSL backend if available. + 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() */ @@ -2007,6 +1983,10 @@ 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) { @@ -2085,12 +2065,12 @@ 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 @@ -2315,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; @@ -2695,7 +2676,7 @@ bool QSslSocketPrivate::verifyErrorsHaveBeenIgnored() // 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; @@ -2833,11 +2814,11 @@ 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()); + return ret + plainSocket->peek(maxSize - ret.size()); return QByteArray(); } else { @@ -2989,7 +2970,13 @@ QList<QByteArray> QSslSocketPrivate::unixRootCertDirectories() ba("/opt/openssl/certs/"), // HP-UX ba("/etc/ssl/"), // OpenBSD }; - return QList<QByteArray>::fromReadOnlyData(dirs); + 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; } /*! @@ -3055,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 .) @@ -3073,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 @@ -3086,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; } @@ -3118,7 +3105,15 @@ 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; } /*! |