diff options
Diffstat (limited to 'src/network')
-rw-r--r-- | src/network/access/qftp.cpp | 4 | ||||
-rw-r--r-- | src/network/access/qhttpnetworkconnectionchannel.cpp | 15 | ||||
-rw-r--r-- | src/network/access/qnetworkaccesshttpbackend.cpp | 18 | ||||
-rw-r--r-- | src/network/access/qnetworkreplyimpl.cpp | 7 | ||||
-rw-r--r-- | src/network/bearer/qnetworkconfigmanager.cpp | 3 | ||||
-rw-r--r-- | src/network/bearer/qsharednetworksession.cpp | 7 | ||||
-rw-r--r-- | src/network/kernel/qnetworkinterface_symbian.cpp | 2 | ||||
-rw-r--r-- | src/network/ssl/qsslcertificate.cpp | 34 | ||||
-rw-r--r-- | src/network/ssl/qsslcertificate_p.h | 1 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_openssl.cpp | 20 |
10 files changed, 92 insertions, 19 deletions
diff --git a/src/network/access/qftp.cpp b/src/network/access/qftp.cpp index ccc20e6..69e59d1 100644 --- a/src/network/access/qftp.cpp +++ b/src/network/access/qftp.cpp @@ -363,9 +363,9 @@ qint64 QFtpDTP::read(char *data, qint64 maxlen) if (socket && socket->state() == QTcpSocket::ConnectedState) { read = socket->read(data, maxlen); } else { - read = bytesFromSocket.size(); + read = qMin(maxlen, qint64(bytesFromSocket.size())); memcpy(data, bytesFromSocket.data(), read); - bytesFromSocket.clear(); + bytesFromSocket.remove(0, read); } bytesDone += read; diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index 82b5ce3..700b455 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -963,8 +963,20 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket } else { errorCode = QNetworkReply::RemoteHostClosedError; } + } else if (state == QHttpNetworkConnectionChannel::ReadingState) { + if (!reply->d_func()->expectContent()) { + // No content expected, this is a valid way to have the connection closed by the server + return; + } + if (reply->contentLength() == -1 && !reply->d_func()->isChunked()) { + // There was no content-length header and it's not chunked encoding, + // so this is a valid way to have the connection closed by the server + return; + } + // ok, we got a disconnect even though we did not expect it + errorCode = QNetworkReply::RemoteHostClosedError; } else { - return; + errorCode = QNetworkReply::RemoteHostClosedError; } break; case QAbstractSocket::SocketTimeoutError: @@ -992,6 +1004,7 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket if (reply) { reply->d_func()->errorString = errorString; emit reply->finishedWithError(errorCode, errorString); + reply = 0; } // send the next request QMetaObject::invokeMethod(that, "_q_startNextRequest", Qt::QueuedConnection); diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp index 4189743..7c90f68 100644 --- a/src/network/access/qnetworkaccesshttpbackend.cpp +++ b/src/network/access/qnetworkaccesshttpbackend.cpp @@ -360,6 +360,11 @@ void QNetworkAccessHttpBackend::validateCache(QHttpNetworkRequest &httpRequest, return; } + // The disk cache API does not currently support partial content retrieval. + // That is why we don't use the disk cache for any such requests. + if (request().hasRawHeader("Range")) + return; + QAbstractNetworkCache *nc = networkCache(); if (!nc) return; // no local cache @@ -996,14 +1001,11 @@ QNetworkCacheMetaData QNetworkAccessHttpBackend::fetchCacheMetaData(const QNetwo if (hop_by_hop) continue; - // for 4.6.0, we were planning to not store the date header in the - // cached resource; through that we planned to reduce the number - // of writes to disk when using a QNetworkDiskCache (i.e. don't - // write to disk when only the date changes). - // However, without the date we cannot calculate the age of the page - // anymore. - //if (header == "date") - //continue; + // we are currently not using the date header to determine the expiration time of a page, + // but only the "Expires", "max-age" and "s-maxage" headers, see + // QNetworkAccessHttpBackend::validateCache() and below ("metaData.setExpirationDate()"). + if (header == "date") + continue; // Don't store Warning 1xx headers if (header == "warning") { diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index 343f344..894df79 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -505,6 +505,13 @@ void QNetworkReplyImplPrivate::initCacheSaveDevice() { Q_Q(QNetworkReplyImpl); + // The disk cache does not support partial content, so don't even try to + // save any such content into the cache. + if (q->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 206) { + cacheEnabled = false; + return; + } + // save the meta data QNetworkCacheMetaData metaData; metaData.setUrl(url); diff --git a/src/network/bearer/qnetworkconfigmanager.cpp b/src/network/bearer/qnetworkconfigmanager.cpp index dc4e4f7..8634b6b 100644 --- a/src/network/bearer/qnetworkconfigmanager.cpp +++ b/src/network/bearer/qnetworkconfigmanager.cpp @@ -196,6 +196,9 @@ QNetworkConfigurationManagerPrivate *qNetworkConfigurationManagerPrivate() /*! Constructs a QNetworkConfigurationManager with the given \a parent. + + Note that to ensure a valid list of current configurations immediately available, updating + is done during construction which causes some delay. */ QNetworkConfigurationManager::QNetworkConfigurationManager( QObject* parent ) : QObject(parent) diff --git a/src/network/bearer/qsharednetworksession.cpp b/src/network/bearer/qsharednetworksession.cpp index 28ca173..fcb0128 100644 --- a/src/network/bearer/qsharednetworksession.cpp +++ b/src/network/bearer/qsharednetworksession.cpp @@ -59,6 +59,11 @@ inline QSharedNetworkSessionManager* sharedNetworkSessionManager() return rv; } +static void doDeleteLater(QObject* obj) +{ + obj->deleteLater(); +} + QSharedPointer<QNetworkSession> QSharedNetworkSessionManager::getSession(QNetworkConfiguration config) { QSharedNetworkSessionManager *m(sharedNetworkSessionManager()); @@ -69,7 +74,7 @@ QSharedPointer<QNetworkSession> QSharedNetworkSessionManager::getSession(QNetwor return p; } //otherwise make one - QSharedPointer<QNetworkSession> session(new QNetworkSession(config)); + QSharedPointer<QNetworkSession> session(new QNetworkSession(config), doDeleteLater); m->sessions[config] = session; return session; } diff --git a/src/network/kernel/qnetworkinterface_symbian.cpp b/src/network/kernel/qnetworkinterface_symbian.cpp index 03133d0..8e5db3c 100644 --- a/src/network/kernel/qnetworkinterface_symbian.cpp +++ b/src/network/kernel/qnetworkinterface_symbian.cpp @@ -43,7 +43,7 @@ #include "qnetworkinterface.h" #include "qnetworkinterface_p.h" -#include "../corelib/kernel/qcore_symbian_p.h" +#include <private/qcore_symbian_p.h> #ifndef QT_NO_NETWORKINTERFACE diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp index 618ac79..a5cdf01 100644 --- a/src/network/ssl/qsslcertificate.cpp +++ b/src/network/ssl/qsslcertificate.cpp @@ -219,17 +219,19 @@ bool QSslCertificate::isNull() const Returns true if this certificate is valid; otherwise returns false. - Note: Currently, this function only checks that the current + Note: Currently, this function checks that the current data-time is within the date-time range during which the - certificate is considered valid. No other checks are - currently performed. + certificate is considered valid, and checks that the + certificate is not in a blacklist of fraudulent certificates. \sa isNull() */ bool QSslCertificate::isValid() const { const QDateTime currentTime = QDateTime::currentDateTime(); - return currentTime >= d->notValidBefore && currentTime <= d->notValidAfter; + return currentTime >= d->notValidBefore && + currentTime <= d->notValidAfter && + ! QSslCertificatePrivate::isBlacklisted(*this); } /*! @@ -798,6 +800,30 @@ QList<QSslCertificate> QSslCertificatePrivate::certificatesFromDer(const QByteAr return certificates; } +// These certificates are known to be fraudulent and were created during the comodo +// compromise. See http://www.comodo.com/Comodo-Fraud-Incident-2011-03-23.html +static const char *certificate_blacklist[] = { + "04:7e:cb:e9:fc:a5:5f:7b:d0:9e:ae:36:e1:0c:ae:1e", + "f5:c8:6a:f3:61:62:f1:3a:64:f5:4f:6d:c9:58:7c:06", + "d7:55:8f:da:f5:f1:10:5b:b2:13:28:2b:70:77:29:a3", + "39:2a:43:4f:0e:07:df:1f:8a:a3:05:de:34:e0:c2:29", + "3e:75:ce:d4:6b:69:30:21:21:88:30:ae:86:a8:2a:71", + "e9:02:8b:95:78:e4:15:dc:1a:71:0a:2b:88:15:44:47", + "92:39:d5:34:8f:40:d1:69:5a:74:54:70:e1:f2:3f:43", + "b0:b7:13:3e:d0:96:f9:b5:6f:ae:91:c8:74:bd:3a:c0", + "d8:f3:5f:4e:b7:87:2b:2d:ab:06:92:e3:15:38:2f:b0", + 0 +}; + +bool QSslCertificatePrivate::isBlacklisted(const QSslCertificate &certificate) +{ + for (int a = 0; certificate_blacklist[a] != 0; a++) { + if (certificate.serialNumber() == certificate_blacklist[a]) + return true; + } + return false; +} + #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug debug, const QSslCertificate &certificate) { diff --git a/src/network/ssl/qsslcertificate_p.h b/src/network/ssl/qsslcertificate_p.h index cdceb0f..1ce33d3 100644 --- a/src/network/ssl/qsslcertificate_p.h +++ b/src/network/ssl/qsslcertificate_p.h @@ -96,6 +96,7 @@ public: static QSslCertificate QSslCertificate_from_X509(X509 *x509); static QList<QSslCertificate> certificatesFromPem(const QByteArray &pem, int count = -1); static QList<QSslCertificate> certificatesFromDer(const QByteArray &der, int count = -1); + static bool isBlacklisted(const QSslCertificate &certificate); friend class QSslSocketBackendPrivate; diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index 84e14ff..2427193 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -312,9 +312,18 @@ init_context: q_X509_STORE_add_cert(ctx->cert_store, (X509 *)caCertificate.handle()); } } + + bool addExpiredCerts = true; +#if defined(Q_OS_MAC) && (MAC_OS_X_VERSION_MAX_ALLOWED == MAC_OS_X_VERSION_10_5) + //On Leopard SSL does not work if we add the expired certificates. + if (QSysInfo::MacintoshVersion == QSysInfo::MV_10_5) + addExpiredCerts = false; +#endif // now add the expired certs - foreach (const QSslCertificate &caCertificate, expiredCerts) { - q_X509_STORE_add_cert(ctx->cert_store, (X509 *)caCertificate.handle()); + if (addExpiredCerts) { + foreach (const QSslCertificate &caCertificate, expiredCerts) { + q_X509_STORE_add_cert(ctx->cert_store, (X509 *)caCertificate.handle()); + } } // Register a custom callback to get all verification errors. @@ -1184,6 +1193,13 @@ bool QSslSocketBackendPrivate::startHandshake() X509 *x509 = q_SSL_get_peer_certificate(ssl); configuration.peerCertificate = QSslCertificatePrivate::QSslCertificate_from_X509(x509); q_X509_free(x509); + if (QSslCertificatePrivate::isBlacklisted(configuration.peerCertificate)) { + q->setErrorString(QSslSocket::tr("The peer certificate is blacklisted")); + q->setSocketError(QAbstractSocket::SslHandshakeFailedError); + emit q->error(QAbstractSocket::SslHandshakeFailedError); + plainSocket->disconnectFromHost(); + return false; + } // Start translating errors. QList<QSslError> errors; |