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.cpp97
1 files changed, 70 insertions, 27 deletions
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index 805adc734f..a5ee9bf0c1 100644
--- a/src/network/ssl/qsslsocket.cpp
+++ b/src/network/ssl/qsslsocket.cpp
@@ -1,32 +1,38 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
-** Contact: http://www.qt.io/licensing/
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtNetwork module of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** 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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** 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.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** 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$
**
@@ -506,6 +512,8 @@ bool QSslSocket::setSocketDescriptor(qintptr socketDescriptor, SocketState state
setPeerPort(d->plainSocket->peerPort());
setPeerAddress(d->plainSocket->peerAddress());
setPeerName(d->plainSocket->peerName());
+ d->readChannelCount = d->plainSocket->readChannelCount();
+ d->writeChannelCount = d->plainSocket->writeChannelCount();
return retVal;
}
@@ -1241,7 +1249,8 @@ void QSslSocket::setCiphers(const QString &ciphers)
{
Q_D(QSslSocket);
d->configuration.ciphers.clear();
- foreach (const QString &cipherName, ciphers.split(QLatin1Char(':'), QString::SkipEmptyParts)) {
+ const auto cipherNames = ciphers.split(QLatin1Char(':'), QString::SkipEmptyParts);
+ for (const QString &cipherName : cipherNames) {
QSslCipher cipher(cipherName);
if (!cipher.isNull())
d->configuration.ciphers << cipher;
@@ -1507,6 +1516,10 @@ QList<QSslCertificate> QSslSocket::defaultCaCertificates()
returned by defaultCaCertificates(). You can replace that database
with your own with setDefaultCaCertificates().
+ \note: On OS X, only certificates that are either trusted for all
+ purposes or trusted for the purpose of SSL in the keychain will be
+ returned.
+
\sa caCertificates(), defaultCaCertificates(), setDefaultCaCertificates()
*/
QList<QSslCertificate> QSslSocket::systemCaCertificates()
@@ -1915,6 +1928,7 @@ void QSslSocket::connectToHost(const QString &hostName, quint16 port, OpenMode o
d->plainSocket->setProxy(proxy());
#endif
QIODevice::open(openMode);
+ d->readChannelCount = d->writeChannelCount = 0;
d->plainSocket->connectToHost(hostName, port, openMode, d->preferredNetworkLayerProtocol);
d->cachedSocketDescriptor = d->plainSocket->socketDescriptor();
}
@@ -1994,8 +2008,7 @@ qint64 QSslSocket::writeData(const char *data, qint64 len)
if (d->mode == UnencryptedMode && !d->autoStartHandshake)
return d->plainSocket->write(data, len);
- char *writePtr = d->writeBuffer.reserve(len);
- ::memcpy(writePtr, data, len);
+ d->writeBuffer.append(data, len);
// make sure we flush to the plain socket's buffer
QMetaObject::invokeMethod(this, "_q_flushWriteBuffer", Qt::QueuedConnection);
@@ -2262,9 +2275,15 @@ void QSslSocketPrivate::createPlainSocket(QIODevice::OpenMode openMode)
q->connect(plainSocket, SIGNAL(readyRead()),
q, SLOT(_q_readyReadSlot()),
Qt::DirectConnection);
+ q->connect(plainSocket, SIGNAL(channelReadyRead(int)),
+ q, SLOT(_q_channelReadyReadSlot(int)),
+ Qt::DirectConnection);
q->connect(plainSocket, SIGNAL(bytesWritten(qint64)),
q, SLOT(_q_bytesWrittenSlot(qint64)),
Qt::DirectConnection);
+ q->connect(plainSocket, SIGNAL(channelBytesWritten(int, qint64)),
+ q, SLOT(_q_channelBytesWrittenSlot(int, qint64)),
+ Qt::DirectConnection);
#ifndef QT_NO_NETWORKPROXY
q->connect(plainSocket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
q, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
@@ -2318,6 +2337,7 @@ bool QSslSocketPrivate::bind(const QHostAddress &address, quint16 port, QAbstrac
localPort = plainSocket->localPort();
localAddress = plainSocket->localAddress();
cachedSocketDescriptor = plainSocket->socketDescriptor();
+ readChannelCount = writeChannelCount = 0;
return ret;
}
@@ -2333,6 +2353,8 @@ void QSslSocketPrivate::_q_connectedSlot()
q->setPeerAddress(plainSocket->peerAddress());
q->setPeerName(plainSocket->peerName());
cachedSocketDescriptor = plainSocket->socketDescriptor();
+ readChannelCount = plainSocket->readChannelCount();
+ writeChannelCount = plainSocket->writeChannelCount();
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << "QSslSocket::_q_connectedSlot()";
@@ -2438,6 +2460,16 @@ void QSslSocketPrivate::_q_readyReadSlot()
/*!
\internal
*/
+void QSslSocketPrivate::_q_channelReadyReadSlot(int channel)
+{
+ Q_Q(QSslSocket);
+ if (mode == QSslSocket::UnencryptedMode)
+ emit q->channelReadyRead(channel);
+}
+
+/*!
+ \internal
+*/
void QSslSocketPrivate::_q_bytesWrittenSlot(qint64 written)
{
Q_Q(QSslSocket);
@@ -2456,6 +2488,16 @@ void QSslSocketPrivate::_q_bytesWrittenSlot(qint64 written)
/*!
\internal
*/
+void QSslSocketPrivate::_q_channelBytesWrittenSlot(int channel, qint64 written)
+{
+ Q_Q(QSslSocket);
+ if (mode == QSslSocket::UnencryptedMode)
+ emit q->channelBytesWritten(channel, written);
+}
+
+/*!
+ \internal
+*/
void QSslSocketPrivate::_q_flushWriteBuffer()
{
Q_Q(QSslSocket);
@@ -2485,7 +2527,7 @@ void QSslSocketPrivate::_q_resumeImplementation()
if (verifyErrorsHaveBeenIgnored()) {
continueHandshake();
} else {
- setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, sslErrors.first().errorString());
+ setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, sslErrors.constFirst().errorString());
plainSocket->disconnectFromHost();
return;
}
@@ -2527,7 +2569,7 @@ qint64 QSslSocketPrivate::peek(char *data, qint64 maxSize)
if (mode == QSslSocket::UnencryptedMode && !autoStartHandshake) {
//unencrypted mode - do not use QIODevice::peek, as it reads ahead data from the plain socket
//peek at data already in the QIODevice buffer (from a previous read)
- qint64 r = buffer.peek(data, maxSize);
+ qint64 r = buffer.peek(data, maxSize, transactionPos);
if (r == maxSize)
return r;
data += r;
@@ -2556,7 +2598,7 @@ QByteArray QSslSocketPrivate::peek(qint64 maxSize)
//peek at data already in the QIODevice buffer (from a previous read)
QByteArray ret;
ret.reserve(maxSize);
- ret.resize(buffer.peek(ret.data(), maxSize));
+ ret.resize(buffer.peek(ret.data(), maxSize, transactionPos));
if (ret.length() == maxSize)
return ret;
//peek at data in the plain socket
@@ -2612,18 +2654,19 @@ QSharedPointer<QSslContext> QSslSocketPrivate::sslContext(QSslSocket *socket)
bool QSslSocketPrivate::isMatchingHostname(const QSslCertificate &cert, const QString &peerName)
{
- QStringList commonNameList = cert.subjectInfo(QSslCertificate::CommonName);
+ const QString lowerPeerName = peerName.toLower();
+ const QStringList commonNames = cert.subjectInfo(QSslCertificate::CommonName);
- foreach (const QString &commonName, commonNameList) {
- if (isMatchingHostname(commonName.toLower(), peerName.toLower())) {
+ for (const QString &commonName : commonNames) {
+ if (isMatchingHostname(commonName.toLower(), lowerPeerName))
return true;
- }
}
- foreach (const QString &altName, cert.subjectAlternativeNames().values(QSsl::DnsEntry)) {
- if (isMatchingHostname(altName.toLower(), peerName.toLower())) {
+ const auto subjectAlternativeNames = cert.subjectAlternativeNames();
+ const auto altNames = subjectAlternativeNames.equal_range(QSsl::DnsEntry);
+ for (auto it = altNames.first; it != altNames.second; ++it) {
+ if (isMatchingHostname(it->toLower(), lowerPeerName))
return true;
- }
}
return false;