diff options
Diffstat (limited to 'src/network')
59 files changed, 593 insertions, 396 deletions
diff --git a/src/network/access/qabstractnetworkcache.h b/src/network/access/qabstractnetworkcache.h index 6a4d36ced3..b9a086f047 100644 --- a/src/network/access/qabstractnetworkcache.h +++ b/src/network/access/qabstractnetworkcache.h @@ -47,8 +47,6 @@ #include <QtCore/qpair.h> #include <QtNetwork/qnetworkrequest.h> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -141,6 +139,4 @@ private: QT_END_NAMESPACE -QT_END_HEADER - #endif diff --git a/src/network/access/qftp_p.h b/src/network/access/qftp_p.h index d87a743036..ee5d124650 100644 --- a/src/network/access/qftp_p.h +++ b/src/network/access/qftp_p.h @@ -57,8 +57,6 @@ #include <private/qurlinfo_p.h> #include <QtCore/qobject.h> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -176,6 +174,4 @@ private: QT_END_NAMESPACE -QT_END_HEADER - #endif // QFTP_H diff --git a/src/network/access/qhttpmultipart.h b/src/network/access/qhttpmultipart.h index 9913b64de6..71075ad2f3 100644 --- a/src/network/access/qhttpmultipart.h +++ b/src/network/access/qhttpmultipart.h @@ -47,8 +47,6 @@ #include <QtCore/QIODevice> #include <QtNetwork/QNetworkRequest> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -119,6 +117,4 @@ private: QT_END_NAMESPACE -QT_END_HEADER - #endif // QHTTPMULTIPART_H diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index eec5cfa96d..509f8b3251 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -1224,6 +1224,18 @@ void QHttpNetworkConnection::setSslConfiguration(const QSslConfiguration &config d->channels[i].setSslConfiguration(config); } +QSharedPointer<QSslContext> QHttpNetworkConnection::sslContext() +{ + Q_D(QHttpNetworkConnection); + return d->sslContext; +} + +void QHttpNetworkConnection::setSslContext(QSharedPointer<QSslContext> context) +{ + Q_D(QHttpNetworkConnection); + d->sslContext = context; +} + void QHttpNetworkConnection::ignoreSslErrors(int channel) { Q_D(QHttpNetworkConnection); diff --git a/src/network/access/qhttpnetworkconnection_p.h b/src/network/access/qhttpnetworkconnection_p.h index 57d40bfcf2..956499ddab 100644 --- a/src/network/access/qhttpnetworkconnection_p.h +++ b/src/network/access/qhttpnetworkconnection_p.h @@ -62,6 +62,7 @@ #include <qnetworkproxy.h> #include <qbuffer.h> #include <qtimer.h> +#include <qsharedpointer.h> #include <private/qhttpnetworkheader_p.h> #include <private/qhttpnetworkrequest_p.h> @@ -72,6 +73,8 @@ #ifndef QT_NO_HTTP #ifndef QT_NO_SSL +# include <private/qsslcontext_p.h> +# include <private/qsslsocket_p.h> # include <QtNetwork/qsslsocket.h> # include <QtNetwork/qsslerror.h> #else @@ -124,6 +127,8 @@ public: void setSslConfiguration(const QSslConfiguration &config); void ignoreSslErrors(int channel = -1); void ignoreSslErrors(const QList<QSslError> &errors, int channel = -1); + QSharedPointer<QSslContext> sslContext(); + void setSslContext(QSharedPointer<QSslContext> context); #endif private: @@ -234,6 +239,10 @@ public: QList<HttpMessagePair> highPriorityQueue; QList<HttpMessagePair> lowPriorityQueue; +#ifndef QT_NO_SSL + QSharedPointer<QSslContext> sslContext; +#endif + #ifndef QT_NO_BEARERMANAGEMENT QSharedPointer<QNetworkSession> networkSession; #endif diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index 38723a7032..4dfed762f5 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -622,6 +622,13 @@ bool QHttpNetworkConnectionChannel::ensureConnection() if (ssl) { #ifndef QT_NO_SSL QSslSocket *sslSocket = qobject_cast<QSslSocket*>(socket); + + // check whether we can re-use an existing SSL session + // (meaning another socket in this connection has already + // performed a full handshake) + if (!connection->sslContext().isNull()) + QSslSocketPrivate::checkSettingSslContext(sslSocket, connection->sslContext()); + sslSocket->connectToHostEncrypted(connectHost, connectPort, QIODevice::ReadWrite, networkLayerPreference); if (ignoreAllSslErrors) sslSocket->ignoreSslErrors(); @@ -1065,7 +1072,17 @@ void QHttpNetworkConnectionChannel::_q_connected() // ### FIXME: if the server closes the connection unexpectedly, we shouldn't send the same broken request again! //channels[i].reconnectAttempts = 2; - if (!pendingEncrypt) { + if (pendingEncrypt) { +#ifndef QT_NO_SSL + if (connection->sslContext().isNull()) { + // this socket is making the 1st handshake for this connection, + // we need to set the SSL context so new sockets can reuse it + QSharedPointer<QSslContext> socketSslContext = QSslSocketPrivate::sslContext(static_cast<QSslSocket*>(socket)); + if (!socketSslContext.isNull()) + connection->setSslContext(socketSslContext); + } +#endif + } else { state = QHttpNetworkConnectionChannel::IdleState; if (!reply) connection->d_func()->dequeueRequest(socket); diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 6899653800..f185f7f695 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -834,10 +834,12 @@ QNetworkConfiguration QNetworkAccessManager::configuration() const Q_D(const QNetworkAccessManager); QSharedPointer<QNetworkSession> session(d->getNetworkSession()); - if (session) + if (session) { return session->configuration(); - else - return QNetworkConfiguration(); + } else { + QNetworkConfigurationManager manager; + return manager.defaultConfiguration(); + } } /*! @@ -860,13 +862,12 @@ QNetworkConfiguration QNetworkAccessManager::activeConfiguration() const Q_D(const QNetworkAccessManager); QSharedPointer<QNetworkSession> networkSession(d->getNetworkSession()); + QNetworkConfigurationManager manager; if (networkSession) { - QNetworkConfigurationManager manager; - return manager.configurationFromIdentifier( networkSession->sessionProperty(QLatin1String("ActiveConfiguration")).toString()); } else { - return QNetworkConfiguration(); + return manager.defaultConfiguration(); } } diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h index af5f6933a4..0caba127fc 100644 --- a/src/network/access/qnetworkaccessmanager.h +++ b/src/network/access/qnetworkaccessmanager.h @@ -44,8 +44,6 @@ #include <QtCore/QObject> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -170,6 +168,4 @@ private: QT_END_NAMESPACE -QT_END_HEADER - #endif diff --git a/src/network/access/qnetworkcookie.h b/src/network/access/qnetworkcookie.h index e7f6c8fe3f..2a4e686b2c 100644 --- a/src/network/access/qnetworkcookie.h +++ b/src/network/access/qnetworkcookie.h @@ -47,8 +47,6 @@ #include <QtCore/QMetaType> #include <QtCore/QObject> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -121,6 +119,4 @@ QT_END_NAMESPACE Q_DECLARE_METATYPE(QNetworkCookie) -QT_END_HEADER - #endif diff --git a/src/network/access/qnetworkcookiejar.h b/src/network/access/qnetworkcookiejar.h index 7868e1fc04..3c787c5dd8 100644 --- a/src/network/access/qnetworkcookiejar.h +++ b/src/network/access/qnetworkcookiejar.h @@ -45,8 +45,6 @@ #include <QtCore/QObject> #include <QtCore/QUrl> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -79,6 +77,4 @@ private: QT_END_NAMESPACE -QT_END_HEADER - #endif diff --git a/src/network/access/qnetworkdiskcache.h b/src/network/access/qnetworkdiskcache.h index 1d5f293a2c..20a412c96e 100644 --- a/src/network/access/qnetworkdiskcache.h +++ b/src/network/access/qnetworkdiskcache.h @@ -44,8 +44,6 @@ #include <QtNetwork/qabstractnetworkcache.h> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -91,6 +89,4 @@ private: QT_END_NAMESPACE -QT_END_HEADER - #endif // QNETWORKDISKCACHE_H diff --git a/src/network/access/qnetworkreply.h b/src/network/access/qnetworkreply.h index 8e770bc96b..39901aafb6 100644 --- a/src/network/access/qnetworkreply.h +++ b/src/network/access/qnetworkreply.h @@ -49,8 +49,6 @@ #include <QtNetwork/QNetworkRequest> #include <QtNetwork/QNetworkAccessManager> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -182,6 +180,4 @@ QT_END_NAMESPACE Q_DECLARE_METATYPE(QNetworkReply::NetworkError) -QT_END_HEADER - #endif diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp index 1520816e8d..522965c104 100644 --- a/src/network/access/qnetworkreplyhttpimpl.cpp +++ b/src/network/access/qnetworkreplyhttpimpl.cpp @@ -610,14 +610,14 @@ void QNetworkReplyHttpImplPrivate::postRequest() if (synchronous) { // A synchronous HTTP request uses its own thread thread = new QThread(); - thread->setObjectName(QStringLiteral("httpReply")); + thread->setObjectName(QStringLiteral("Qt HTTP synchronous thread")); QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); thread->start(); } else if (!managerPrivate->httpThread) { // We use the manager-global thread. // At some point we could switch to having multiple threads if it makes sense. managerPrivate->httpThread = new QThread(); - managerPrivate->httpThread->setObjectName(QStringLiteral("httpThread")); + managerPrivate->httpThread->setObjectName(QStringLiteral("Qt HTTP thread")); managerPrivate->httpThread->start(); thread = managerPrivate->httpThread; diff --git a/src/network/access/qnetworkrequest.h b/src/network/access/qnetworkrequest.h index 0d3c72d18a..1512c6dadd 100644 --- a/src/network/access/qnetworkrequest.h +++ b/src/network/access/qnetworkrequest.h @@ -47,8 +47,6 @@ #include <QtCore/QUrl> #include <QtCore/QVariant> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -159,6 +157,4 @@ QT_END_NAMESPACE Q_DECLARE_METATYPE(QNetworkRequest) -QT_END_HEADER - #endif diff --git a/src/network/bearer/qbearerplugin_p.h b/src/network/bearer/qbearerplugin_p.h index cd646d61a5..7b4611074b 100644 --- a/src/network/bearer/qbearerplugin_p.h +++ b/src/network/bearer/qbearerplugin_p.h @@ -60,8 +60,6 @@ #ifndef QT_NO_BEARERMANAGEMENT -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -79,8 +77,6 @@ public: QT_END_NAMESPACE -QT_END_HEADER - #endif // QT_NO_BEARERMANAGEMENT #endif // QBEARERPLUGIN_P_H diff --git a/src/network/bearer/qnetworkconfigmanager.h b/src/network/bearer/qnetworkconfigmanager.h index c1b3b57825..62b93b19c1 100644 --- a/src/network/bearer/qnetworkconfigmanager.h +++ b/src/network/bearer/qnetworkconfigmanager.h @@ -47,8 +47,6 @@ #ifndef QT_NO_BEARERMANAGEMENT -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE class QNetworkConfigurationManagerPrivate; @@ -98,8 +96,6 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QNetworkConfigurationManager::Capabilities) QT_END_NAMESPACE -QT_END_HEADER - #endif // QT_NO_BEARERMANAGEMENT #endif // QNETWORKCONFIGMANAGER_H diff --git a/src/network/bearer/qnetworkconfigmanager_p.cpp b/src/network/bearer/qnetworkconfigmanager_p.cpp index c710556f1c..192bf15b50 100644 --- a/src/network/bearer/qnetworkconfigmanager_p.cpp +++ b/src/network/bearer/qnetworkconfigmanager_p.cpp @@ -70,7 +70,7 @@ void QNetworkConfigurationManagerPrivate::initialize() { //Two stage construction, because we only want to do this heavyweight work for the winner of the Q_GLOBAL_STATIC race. bearerThread = new QThread(); - bearerThread->setObjectName(QStringLiteral("bearerThread")); + bearerThread->setObjectName(QStringLiteral("Qt bearer thread")); bearerThread->moveToThread(QCoreApplicationPrivate::mainThread()); // because cleanup() is called in main thread context. moveToThread(bearerThread); diff --git a/src/network/bearer/qnetworkconfiguration.h b/src/network/bearer/qnetworkconfiguration.h index 97fb1d270b..25dafcb282 100644 --- a/src/network/bearer/qnetworkconfiguration.h +++ b/src/network/bearer/qnetworkconfiguration.h @@ -49,8 +49,6 @@ #include <QtCore/qlist.h> #include <QtCore/qmetatype.h> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE class QNetworkConfigurationPrivate; @@ -130,6 +128,4 @@ QT_END_NAMESPACE Q_DECLARE_METATYPE(QNetworkConfiguration) -QT_END_HEADER - #endif // QNETWORKCONFIGURATION_H diff --git a/src/network/bearer/qnetworksession.h b/src/network/bearer/qnetworksession.h index 94ab133040..1a76b232e7 100644 --- a/src/network/bearer/qnetworksession.h +++ b/src/network/bearer/qnetworksession.h @@ -54,8 +54,6 @@ #undef interface #endif -QT_BEGIN_HEADER - #include <QtCore/qshareddata.h> QT_BEGIN_NAMESPACE @@ -148,8 +146,6 @@ Q_DECLARE_METATYPE(QNetworkSession::State) Q_DECLARE_METATYPE(QNetworkSession::SessionError) Q_DECLARE_METATYPE(QNetworkSession::UsagePolicies) -QT_END_HEADER - #endif // QT_NO_BEARERMANAGEMENT #endif // QNETWORKSESSION_H diff --git a/src/network/kernel/qauthenticator.cpp b/src/network/kernel/qauthenticator.cpp index e337a39415..73991aba96 100644 --- a/src/network/kernel/qauthenticator.cpp +++ b/src/network/kernel/qauthenticator.cpp @@ -852,7 +852,6 @@ QByteArray QAuthenticatorPrivate::digestMd5Response(const QByteArray &challenge, //************************Global variables*************************** const int blockSize = 64; //As per RFC2104 Block-size is 512 bits -const int nDigestLen = 16; //Trunctaion Length of the Hmac-Md5 digest const quint8 respversion = 1; const quint8 hirespversion = 1; diff --git a/src/network/kernel/qauthenticator.h b/src/network/kernel/qauthenticator.h index 7d199d1dce..b784cd7f50 100644 --- a/src/network/kernel/qauthenticator.h +++ b/src/network/kernel/qauthenticator.h @@ -45,8 +45,6 @@ #include <QtCore/qstring.h> #include <QtCore/qvariant.h> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -86,6 +84,4 @@ private: QT_END_NAMESPACE -QT_END_HEADER - #endif diff --git a/src/network/kernel/qdnslookup.h b/src/network/kernel/qdnslookup.h index 5218c2618a..1df21d866e 100644 --- a/src/network/kernel/qdnslookup.h +++ b/src/network/kernel/qdnslookup.h @@ -48,8 +48,6 @@ #include <QtCore/qsharedpointer.h> #include <QtCore/qstring.h> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE class QHostAddress; @@ -248,6 +246,4 @@ private: QT_END_NAMESPACE -QT_END_HEADER - #endif // QDNSLOOKUP_H diff --git a/src/network/kernel/qhostaddress.h b/src/network/kernel/qhostaddress.h index 0e50a677ed..77a2ec4105 100644 --- a/src/network/kernel/qhostaddress.h +++ b/src/network/kernel/qhostaddress.h @@ -49,8 +49,6 @@ struct sockaddr; -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -142,5 +140,4 @@ Q_NETWORK_EXPORT QDataStream &operator>>(QDataStream &, QHostAddress &); QT_END_NAMESPACE -QT_END_HEADER #endif // QHOSTADDRESS_H diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp index 6de83c3754..d9d8396011 100644 --- a/src/network/kernel/qhostinfo.cpp +++ b/src/network/kernel/qhostinfo.cpp @@ -699,8 +699,8 @@ void Q_AUTOTEST_EXPORT qt_qhostinfo_enable_cache(bool e) } // cache for 60 seconds -// cache 64 items -QHostInfoCache::QHostInfoCache() : max_age(60), enabled(true), cache(64) +// cache 128 items +QHostInfoCache::QHostInfoCache() : max_age(60), enabled(true), cache(128) { #ifdef QT_QHOSTINFO_CACHE_DISABLED_BY_DEFAULT enabled = false; diff --git a/src/network/kernel/qhostinfo.h b/src/network/kernel/qhostinfo.h index 89cc5ba26b..38d55def34 100644 --- a/src/network/kernel/qhostinfo.h +++ b/src/network/kernel/qhostinfo.h @@ -46,8 +46,6 @@ #include <QtCore/qscopedpointer.h> #include <QtNetwork/qhostaddress.h> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -98,6 +96,4 @@ QT_END_NAMESPACE Q_DECLARE_METATYPE(QHostInfo) -QT_END_HEADER - #endif // QHOSTINFO_H diff --git a/src/network/kernel/qnetworkfunctions_wince.h b/src/network/kernel/qnetworkfunctions_wince.h index 858600bcca..ccf1ed9e38 100644 --- a/src/network/kernel/qnetworkfunctions_wince.h +++ b/src/network/kernel/qnetworkfunctions_wince.h @@ -50,8 +50,6 @@ #include <qt_windows.h> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE DECLARE_HANDLE(SC_HANDLE); @@ -96,7 +94,5 @@ typedef LPENUM_SERVICE_STATUS_PROCESSA LPENUM_SERVICE_STATUS_PROCESS; QT_END_NAMESPACE -QT_END_HEADER - #endif // Q_OS_WINCE #endif // QNETWORKFUNCTIONS_WINCE_H diff --git a/src/network/kernel/qnetworkinterface.h b/src/network/kernel/qnetworkinterface.h index 9ecc371b54..f288b8d938 100644 --- a/src/network/kernel/qnetworkinterface.h +++ b/src/network/kernel/qnetworkinterface.h @@ -48,8 +48,6 @@ #ifndef QT_NO_NETWORKINTERFACE -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -137,8 +135,6 @@ Q_NETWORK_EXPORT QDebug operator<<(QDebug debug, const QNetworkInterface &networ QT_END_NAMESPACE -QT_END_HEADER - #endif // QT_NO_NETWORKINTERFACE #endif diff --git a/src/network/kernel/qnetworkproxy.cpp b/src/network/kernel/qnetworkproxy.cpp index 242855eaba..931c52eab0 100644 --- a/src/network/kernel/qnetworkproxy.cpp +++ b/src/network/kernel/qnetworkproxy.cpp @@ -1562,7 +1562,7 @@ void QNetworkProxyFactory::setApplicationProxyFactory(QNetworkProxyFactory *fact \li On Windows platforms, this function may take several seconds to execute depending on the configuration of the user's system. - \li On BlackBerry, only UrlRequest queries are supported. SOCKS is + \li On BlackBerry, only UrlRequest and TcpSocket queries are supported. SOCKS is not supported. The proxy credentials are only retrieved for the default configuration. \endlist diff --git a/src/network/kernel/qnetworkproxy.h b/src/network/kernel/qnetworkproxy.h index 081a993e33..153c84028a 100644 --- a/src/network/kernel/qnetworkproxy.h +++ b/src/network/kernel/qnetworkproxy.h @@ -48,8 +48,6 @@ #ifndef QT_NO_NETWORKPROXY -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -220,8 +218,6 @@ QT_END_NAMESPACE Q_DECLARE_METATYPE(QNetworkProxy) -QT_END_HEADER - #endif // QT_NO_NETWORKPROXY #endif // QHOSTINFO_H diff --git a/src/network/kernel/qnetworkproxy_blackberry.cpp b/src/network/kernel/qnetworkproxy_blackberry.cpp index 2743b90404..c0f5c43a78 100644 --- a/src/network/kernel/qnetworkproxy_blackberry.cpp +++ b/src/network/kernel/qnetworkproxy_blackberry.cpp @@ -63,14 +63,36 @@ QT_BEGIN_NAMESPACE QList<QNetworkProxy> QNetworkProxyFactory::systemProxyForQuery(const QNetworkProxyQuery &query) { - QNetworkProxy proxy; + if (query.url().scheme() == QLatin1String("file") + || query.url().scheme() == QLatin1String("qrc")) + return QList<QNetworkProxy>() << QNetworkProxy(QNetworkProxy::NoProxy); - if (query.queryType() != QNetworkProxyQuery::UrlRequest) { + if (query.queryType() != QNetworkProxyQuery::UrlRequest + && query.queryType() != QNetworkProxyQuery::TcpSocket) { qWarning("Unsupported query type: %d", query.queryType()); return QList<QNetworkProxy>() << QNetworkProxy(QNetworkProxy::NoProxy); } - QUrl url = query.url(); + QUrl url; + if (query.queryType() == QNetworkProxyQuery::UrlRequest) { + url = query.url(); + } else if (query.queryType() == QNetworkProxyQuery::TcpSocket + && !query.peerHostName().isEmpty()) { + url.setHost(query.peerHostName()); + switch (query.peerPort()) { + case 443: + url.setScheme(QStringLiteral("https")); + break; + case 21: + url.setScheme(QStringLiteral("ftp")); + break; + default: + // for unknown ports, we just pretend we are dealing + // with a HTTP URL, otherwise we will not get a proxy + // from the netstatus API + url.setScheme(QStringLiteral("http")); + } + } if (!url.isValid()) { qWarning("Invalid URL: %s", qPrintable(url.toString())); @@ -112,6 +134,8 @@ QList<QNetworkProxy> QNetworkProxyFactory::systemProxyForQuery(const QNetworkPro return QList<QNetworkProxy>() << QNetworkProxy(QNetworkProxy::NoProxy); } + QNetworkProxy proxy; + QString protocol = query.protocolTag(); if (protocol.startsWith(QLatin1String("http"), Qt::CaseInsensitive)) { // http, https proxy.setType((QNetworkProxy::HttpProxy)); diff --git a/src/network/kernel/qnetworkproxy_mac.cpp b/src/network/kernel/qnetworkproxy_mac.cpp index a283b7ee05..4a4acb59d4 100644 --- a/src/network/kernel/qnetworkproxy_mac.cpp +++ b/src/network/kernel/qnetworkproxy_mac.cpp @@ -231,7 +231,6 @@ QList<QNetworkProxy> macQueryInternal(const QNetworkProxyQuery &query) // PAC is enabled CFStringRef cfPacLocation = (CFStringRef)CFDictionaryGetValue(dict, kSCPropNetProxiesProxyAutoConfigURLString); -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { QCFType<CFDataRef> pacData; QCFType<CFURLRef> pacUrl = CFURLCreateWithString(kCFAllocatorDefault, cfPacLocation, NULL); @@ -275,9 +274,7 @@ QList<QNetworkProxy> macQueryInternal(const QNetworkProxyQuery &query) result << proxyFromDictionary(proxy); } return result; - } else -#endif - { + } else { QString pacLocation = QCFString::toQString(cfPacLocation); qWarning("Mac system proxy: PAC script at \"%s\" not handled", qPrintable(pacLocation)); } diff --git a/src/network/kernel/qurlinfo_p.h b/src/network/kernel/qurlinfo_p.h index 955a2eb325..1aa59f25ad 100644 --- a/src/network/kernel/qurlinfo_p.h +++ b/src/network/kernel/qurlinfo_p.h @@ -46,8 +46,6 @@ #include <QtCore/qstring.h> #include <QtCore/qiodevice.h> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -125,6 +123,4 @@ private: QT_END_NAMESPACE -QT_END_HEADER - #endif // QURLINFO_H diff --git a/src/network/socket/qabstractsocket.h b/src/network/socket/qabstractsocket.h index b7e3f2853a..46114abf73 100644 --- a/src/network/socket/qabstractsocket.h +++ b/src/network/socket/qabstractsocket.h @@ -48,8 +48,6 @@ #include <QtCore/qdebug.h> #endif -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -242,6 +240,4 @@ QT_END_NAMESPACE Q_DECLARE_METATYPE(QAbstractSocket::SocketState) Q_DECLARE_METATYPE(QAbstractSocket::SocketError) -QT_END_HEADER - #endif // QABSTRACTSOCKET_H diff --git a/src/network/socket/qlocalserver.h b/src/network/socket/qlocalserver.h index d7d6b16e10..b5791db653 100644 --- a/src/network/socket/qlocalserver.h +++ b/src/network/socket/qlocalserver.h @@ -44,8 +44,6 @@ #include <QtNetwork/qabstractsocket.h> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -109,7 +107,5 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QLocalServer::SocketOptions) QT_END_NAMESPACE -QT_END_HEADER - #endif // QLOCALSERVER_H diff --git a/src/network/socket/qlocalserver_unix.cpp b/src/network/socket/qlocalserver_unix.cpp index 2bcf1ac83e..51a33a4b35 100644 --- a/src/network/socket/qlocalserver_unix.cpp +++ b/src/network/socket/qlocalserver_unix.cpp @@ -297,9 +297,9 @@ void QLocalServerPrivate::waitForNewConnection(int msec, bool *timedOut) FD_ZERO(&readfds); FD_SET(listenSocket, &readfds); - timeval timeout; + struct timespec timeout; timeout.tv_sec = msec / 1000; - timeout.tv_usec = (msec % 1000) * 1000; + timeout.tv_nsec = (msec % 1000) * 1000 * 1000; int result = -1; result = qt_safe_select(listenSocket + 1, &readfds, 0, 0, (msec == -1) ? 0 : &timeout); diff --git a/src/network/socket/qlocalsocket.h b/src/network/socket/qlocalsocket.h index e1ee174608..2ff4b2fc5b 100644 --- a/src/network/socket/qlocalsocket.h +++ b/src/network/socket/qlocalsocket.h @@ -45,8 +45,6 @@ #include <QtCore/qiodevice.h> #include <QtNetwork/qabstractsocket.h> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -152,6 +150,4 @@ Q_NETWORK_EXPORT QDebug operator<<(QDebug, QLocalSocket::LocalSocketState); QT_END_NAMESPACE -QT_END_HEADER - #endif // QLOCALSOCKET_H diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index 4f3408b067..4c94c4dbb9 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -1126,9 +1126,9 @@ int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool selectForRead) co FD_ZERO(&fds); FD_SET(socketDescriptor, &fds); - struct timeval tv; + struct timespec tv; tv.tv_sec = timeout / 1000; - tv.tv_usec = (timeout % 1000) * 1000; + tv.tv_nsec = (timeout % 1000) * 1000 * 1000; int retval; if (selectForRead) @@ -1152,9 +1152,9 @@ int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool c if (checkWrite) FD_SET(socketDescriptor, &fdwrite); - struct timeval tv; + struct timespec tv; tv.tv_sec = timeout / 1000; - tv.tv_usec = (timeout % 1000) * 1000; + tv.tv_nsec = (timeout % 1000) * 1000 * 1000; int ret; ret = qt_safe_select(socketDescriptor + 1, &fdread, &fdwrite, 0, timeout < 0 ? 0 : &tv); diff --git a/src/network/socket/qtcpserver.h b/src/network/socket/qtcpserver.h index dfabfa1be7..8e25aa5a29 100644 --- a/src/network/socket/qtcpserver.h +++ b/src/network/socket/qtcpserver.h @@ -46,8 +46,6 @@ #include <QtNetwork/qabstractsocket.h> #include <QtNetwork/qhostaddress.h> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -108,6 +106,4 @@ private: QT_END_NAMESPACE -QT_END_HEADER - #endif // QTCPSERVER_H diff --git a/src/network/socket/qtcpsocket.h b/src/network/socket/qtcpsocket.h index 44fb68a207..ed5ce4aeed 100644 --- a/src/network/socket/qtcpsocket.h +++ b/src/network/socket/qtcpsocket.h @@ -45,8 +45,6 @@ #include <QtNetwork/qabstractsocket.h> #include <QtCore/qvariant.h> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -69,6 +67,4 @@ private: QT_END_NAMESPACE -QT_END_HEADER - #endif // QTCPSOCKET_H diff --git a/src/network/socket/qudpsocket.h b/src/network/socket/qudpsocket.h index 7a064a3432..da6306a430 100644 --- a/src/network/socket/qudpsocket.h +++ b/src/network/socket/qudpsocket.h @@ -45,8 +45,6 @@ #include <QtNetwork/qabstractsocket.h> #include <QtNetwork/qhostaddress.h> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -90,6 +88,4 @@ private: QT_END_NAMESPACE -QT_END_HEADER - #endif // QUDPSOCKET_H diff --git a/src/network/ssl/qssl.h b/src/network/ssl/qssl.h index 80ccfadecb..06d80965e2 100644 --- a/src/network/ssl/qssl.h +++ b/src/network/ssl/qssl.h @@ -46,8 +46,6 @@ #include <QtCore/qglobal.h> #include <QtCore/QFlags> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -106,6 +104,4 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QSsl::SslOptions) QT_END_NAMESPACE -QT_END_HEADER - #endif // QSSL_H diff --git a/src/network/ssl/qsslcertificate.h b/src/network/ssl/qsslcertificate.h index 23f9638981..988071eb9d 100644 --- a/src/network/ssl/qsslcertificate.h +++ b/src/network/ssl/qsslcertificate.h @@ -56,8 +56,6 @@ #include <QtCore/qmap.h> #include <QtNetwork/qssl.h> -QT_BEGIN_HEADER - #ifndef QT_NO_SSL QT_BEGIN_NAMESPACE @@ -164,6 +162,4 @@ Q_DECLARE_METATYPE(QSslCertificate) #endif // QT_NO_SSL -QT_END_HEADER - #endif diff --git a/src/network/ssl/qsslcertificateextension.h b/src/network/ssl/qsslcertificateextension.h index ce7ff54941..080b1ccc4e 100644 --- a/src/network/ssl/qsslcertificateextension.h +++ b/src/network/ssl/qsslcertificateextension.h @@ -47,8 +47,6 @@ #include <QtCore/qstring.h> #include <QtCore/qvariant.h> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -85,8 +83,6 @@ Q_DECLARE_SHARED(QSslCertificateExtension) QT_END_NAMESPACE -QT_END_HEADER - #endif // QSSLCERTIFICATEEXTENSION_H diff --git a/src/network/ssl/qsslcipher.h b/src/network/ssl/qsslcipher.h index 93ae15c3f5..e351d7949b 100644 --- a/src/network/ssl/qsslcipher.h +++ b/src/network/ssl/qsslcipher.h @@ -47,8 +47,6 @@ #include <QtCore/qscopedpointer.h> #include <QtNetwork/qssl.h> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -97,7 +95,5 @@ Q_NETWORK_EXPORT QDebug operator<<(QDebug debug, const QSslCipher &cipher); QT_END_NAMESPACE -QT_END_HEADER - #endif diff --git a/src/network/ssl/qsslconfiguration.cpp b/src/network/ssl/qsslconfiguration.cpp index 0ae67b3c1f..145cd7be5d 100644 --- a/src/network/ssl/qsslconfiguration.cpp +++ b/src/network/ssl/qsslconfiguration.cpp @@ -584,4 +584,10 @@ void QSslConfiguration::setDefaultConfiguration(const QSslConfiguration &configu QSslConfigurationPrivate::setDefaultConfiguration(configuration); } +/*! \internal +*/ +bool QSslConfigurationPrivate::peerSessionWasShared(const QSslConfiguration &configuration) { + return configuration.d->peerSessionShared; + } + QT_END_NAMESPACE diff --git a/src/network/ssl/qsslconfiguration.h b/src/network/ssl/qsslconfiguration.h index ae6e225ce5..064e1b96a8 100644 --- a/src/network/ssl/qsslconfiguration.h +++ b/src/network/ssl/qsslconfiguration.h @@ -61,8 +61,6 @@ #include <QtNetwork/qsslsocket.h> #include <QtNetwork/qssl.h> -QT_BEGIN_HEADER - #ifndef QT_NO_SSL QT_BEGIN_NAMESPACE @@ -129,6 +127,8 @@ public: private: friend class QSslSocket; friend class QSslConfigurationPrivate; + friend class QSslSocketBackendPrivate; + friend class QSslContext; QSslConfiguration(QSslConfigurationPrivate *dd); QSharedDataPointer<QSslConfigurationPrivate> d; }; @@ -141,6 +141,4 @@ Q_DECLARE_METATYPE(QSslConfiguration) #endif // QT_NO_SSL -QT_END_HEADER - #endif diff --git a/src/network/ssl/qsslconfiguration_p.h b/src/network/ssl/qsslconfiguration_p.h index 30f1ed66f9..a6c22db707 100644 --- a/src/network/ssl/qsslconfiguration_p.h +++ b/src/network/ssl/qsslconfiguration_p.h @@ -84,11 +84,13 @@ public: peerVerifyMode(QSslSocket::AutoVerifyPeer), peerVerifyDepth(0), allowRootCertOnDemandLoading(true), + peerSessionShared(false), sslOptions(QSslConfigurationPrivate::defaultSslOptions) { } QSslCertificate peerCertificate; QList<QSslCertificate> peerCertificateChain; + QSslCertificate localCertificate; QSslKey privateKey; @@ -100,6 +102,9 @@ public: QSslSocket::PeerVerifyMode peerVerifyMode; int peerVerifyDepth; bool allowRootCertOnDemandLoading; + bool peerSessionShared; + + Q_AUTOTEST_EXPORT static bool peerSessionWasShared(const QSslConfiguration &configuration); QSsl::SslOptions sslOptions; diff --git a/src/network/ssl/qsslcontext.cpp b/src/network/ssl/qsslcontext.cpp new file mode 100644 index 0000000000..f75ff3796d --- /dev/null +++ b/src/network/ssl/qsslcontext.cpp @@ -0,0 +1,298 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt 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 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtNetwork/qsslsocket.h> +#include <QtCore/qmutex.h> + +#include "private/qsslcontext_p.h" +#include "private/qsslsocket_p.h" +#include "private/qsslsocket_openssl_p.h" +#include "private/qsslsocket_openssl_symbols_p.h" + +QT_BEGIN_NAMESPACE + +// defined in qsslsocket_openssl.cpp: +extern int q_X509Callback(int ok, X509_STORE_CTX *ctx); +extern QString getErrorsFromOpenSsl(); + +QSslContext::QSslContext() + : ctx(0), + pkey(0), + session(0) +{ +} + +QSslContext::~QSslContext() +{ + if (ctx) + // This will decrement the reference count by 1 and free the context eventually when possible + q_SSL_CTX_free(ctx); + + if (pkey) + q_EVP_PKEY_free(pkey); + + if (session) + q_SSL_SESSION_free(session); +} + +QSslContext* QSslContext::fromConfiguration(QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading) +{ + QSslContext *sslContext = new QSslContext(); + sslContext->sslConfiguration = configuration; + sslContext->errorCode = QSslError::NoError; + + bool client = (mode == QSslSocket::SslClientMode); + + bool reinitialized = false; +init_context: + switch (sslContext->sslConfiguration.protocol()) { + case QSsl::SslV2: +#ifndef OPENSSL_NO_SSL2 + sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv2_client_method() : q_SSLv2_server_method()); +#else + sslContext->ctx = 0; // SSL 2 not supported by the system, but chosen deliberately -> error +#endif + break; + case QSsl::SslV3: + sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv3_client_method() : q_SSLv3_server_method()); + break; + case QSsl::SecureProtocols: // SslV2 will be disabled below + case QSsl::TlsV1SslV3: // SslV2 will be disabled below + case QSsl::AnyProtocol: + default: + sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method()); + break; + case QSsl::TlsV1_0: + sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_client_method() : q_TLSv1_server_method()); + break; + case QSsl::TlsV1_1: +#if OPENSSL_VERSION_NUMBER >= 0x10001000L + sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_1_client_method() : q_TLSv1_1_server_method()); +#else + sslContext->ctx = 0; // TLS 1.1 not supported by the system, but chosen deliberately -> error +#endif + break; + case QSsl::TlsV1_2: +#if OPENSSL_VERSION_NUMBER >= 0x10001000L + sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_2_client_method() : q_TLSv1_2_server_method()); +#else + sslContext->ctx = 0; // TLS 1.2 not supported by the system, but chosen deliberately -> error +#endif + break; + } + if (!sslContext->ctx) { + // After stopping Flash 10 the SSL library looses its ciphers. Try re-adding them + // by re-initializing the library. + if (!reinitialized) { + reinitialized = true; + if (q_SSL_library_init() == 1) + goto init_context; + } + + sslContext->errorStr = QSslSocket::tr("Error creating SSL context (%1)").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl()); + sslContext->errorCode = QSslError::UnspecifiedError; + return sslContext; + } + + // Enable bug workarounds. + long options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions); + q_SSL_CTX_set_options(sslContext->ctx, options); + +#if OPENSSL_VERSION_NUMBER >= 0x10000000L + // Tell OpenSSL to release memory early + // http://www.openssl.org/docs/ssl/SSL_CTX_set_mode.html + if (q_SSLeay() >= 0x10000000L) + q_SSL_CTX_set_mode(sslContext->ctx, SSL_MODE_RELEASE_BUFFERS); +#endif + + // Initialize ciphers + QByteArray cipherString; + int first = true; + QList<QSslCipher> ciphers = sslContext->sslConfiguration.ciphers(); + if (ciphers.isEmpty()) + ciphers = QSslSocketPrivate::defaultCiphers(); + foreach (const QSslCipher &cipher, ciphers) { + if (first) + first = false; + else + cipherString.append(':'); + cipherString.append(cipher.name().toLatin1()); + } + + if (!q_SSL_CTX_set_cipher_list(sslContext->ctx, cipherString.data())) { + sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl()); + sslContext->errorCode = QSslError::UnspecifiedError; + return sslContext; + } + + // Add all our CAs to this store. + QList<QSslCertificate> expiredCerts; + foreach (const QSslCertificate &caCertificate, sslContext->sslConfiguration.caCertificates()) { + // add expired certs later, so that the + // valid ones are used before the expired ones + if (caCertificate.expiryDate() < QDateTime::currentDateTime()) { + expiredCerts.append(caCertificate); + } else { + q_X509_STORE_add_cert(sslContext->ctx->cert_store, (X509 *)caCertificate.handle()); + } + } + + // now add the expired certs + foreach (const QSslCertificate &caCertificate, expiredCerts) { + q_X509_STORE_add_cert(sslContext->ctx->cert_store, reinterpret_cast<X509 *>(caCertificate.handle())); + } + + if (QSslSocketPrivate::s_loadRootCertsOnDemand && allowRootCertOnDemandLoading) { + // tell OpenSSL the directories where to look up the root certs on demand + QList<QByteArray> unixDirs = QSslSocketPrivate::unixRootCertDirectories(); + for (int a = 0; a < unixDirs.count(); ++a) + q_SSL_CTX_load_verify_locations(sslContext->ctx, 0, unixDirs.at(a).constData()); + } + + // Register a custom callback to get all verification errors. + X509_STORE_set_verify_cb_func(sslContext->ctx->cert_store, q_X509Callback); + + if (!sslContext->sslConfiguration.localCertificate().isNull()) { + // Require a private key as well. + if (sslContext->sslConfiguration.privateKey().isNull()) { + sslContext->errorStr = QSslSocket::tr("Cannot provide a certificate with no key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl()); + sslContext->errorCode = QSslError::UnspecifiedError; + return sslContext; + } + + // Load certificate + if (!q_SSL_CTX_use_certificate(sslContext->ctx, (X509 *)sslContext->sslConfiguration.localCertificate().handle())) { + sslContext->errorStr = QSslSocket::tr("Error loading local certificate, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl()); + sslContext->errorCode = QSslError::UnspecifiedError; + return sslContext; + } + + if (configuration.d->privateKey.algorithm() == QSsl::Opaque) { + sslContext->pkey = reinterpret_cast<EVP_PKEY *>(configuration.d->privateKey.handle()); + } else { + // Load private key + sslContext->pkey = q_EVP_PKEY_new(); + // before we were using EVP_PKEY_assign_R* functions and did not use EVP_PKEY_free. + // this lead to a memory leak. Now we use the *_set1_* functions which do not + // take ownership of the RSA/DSA key instance because the QSslKey already has ownership. + if (configuration.d->privateKey.algorithm() == QSsl::Rsa) + q_EVP_PKEY_set1_RSA(sslContext->pkey, reinterpret_cast<RSA *>(configuration.d->privateKey.handle())); + else + q_EVP_PKEY_set1_DSA(sslContext->pkey, reinterpret_cast<DSA *>(configuration.d->privateKey.handle())); + } + + if (!q_SSL_CTX_use_PrivateKey(sslContext->ctx, sslContext->pkey)) { + sslContext->errorStr = QSslSocket::tr("Error loading private key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl()); + sslContext->errorCode = QSslError::UnspecifiedError; + return sslContext; + } + if (configuration.d->privateKey.algorithm() == QSsl::Opaque) + sslContext->pkey = 0; // Don't free the private key, it belongs to QSslKey + + // Check if the certificate matches the private key. + if (!q_SSL_CTX_check_private_key(sslContext->ctx)) { + sslContext->errorStr = QSslSocket::tr("Private key does not certify public key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl()); + sslContext->errorCode = QSslError::UnspecifiedError; + return sslContext; + } + } + + // Initialize peer verification. + if (sslContext->sslConfiguration.peerVerifyMode() == QSslSocket::VerifyNone) { + q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_NONE, 0); + } else { + q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_PEER, q_X509Callback); + } + + // Set verification depth. + if (sslContext->sslConfiguration.peerVerifyDepth() != 0) + q_SSL_CTX_set_verify_depth(sslContext->ctx, sslContext->sslConfiguration.peerVerifyDepth()); + + return sslContext; +} + +// Needs to be deleted by caller +SSL* QSslContext::createSsl() +{ + SSL* ssl = q_SSL_new(ctx); + q_SSL_clear(ssl); + + if (session) { + // Try to resume the last session we cached + if (!q_SSL_set_session(ssl, session)) { + qWarning("could not set SSL session"); + q_SSL_SESSION_free(session); + session = 0; + } + } + return ssl; +} + +// We cache exactly one session here +bool QSslContext::cacheSession(SSL* ssl) +{ + // dont cache the same session again + if (session && session == q_SSL_get_session(ssl)) + return true; + + // decrease refcount of currently stored session + // (this might happen if there are several concurrent handshakes in flight) + if (session) + q_SSL_SESSION_free(session); + + // cache the session the caller gave us and increase reference count + session = q_SSL_get1_session(ssl); + return (session != NULL); + +} + +QSslError::SslError QSslContext::error() const +{ + return errorCode; +} + +QString QSslContext::errorString() const +{ + return errorStr; +} + +QT_END_NAMESPACE diff --git a/src/network/ssl/qsslcontext_p.h b/src/network/ssl/qsslcontext_p.h new file mode 100644 index 0000000000..c8578d349e --- /dev/null +++ b/src/network/ssl/qsslcontext_p.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt 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 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QSSLCONTEXT_H +#define QSSLCONTEXT_H + +#include <QtCore/qvariant.h> +#include <QtNetwork/qsslcertificate.h> +#include <QtNetwork/qsslconfiguration.h> +#include <openssl/ssl.h> + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_SSL + +class QSslContextPrivate; + +class QSslContext +{ +public: + + ~QSslContext(); + + static QSslContext* fromConfiguration(QSslSocket::SslMode mode, const QSslConfiguration &configuration, + bool allowRootCertOnDemandLoading); + + QSslError::SslError error() const; + QString errorString() const; + + SSL* createSsl(); + bool cacheSession(SSL*); // should be called when handshake completed + +protected: + QSslContext(); + +private: + SSL_CTX* ctx; + EVP_PKEY *pkey; + SSL_SESSION *session; + QSslError::SslError errorCode; + QString errorStr; + QSslConfiguration sslConfiguration; +}; + +#endif // QT_NO_SSL + +QT_END_NAMESPACE + +#endif // QSSLCONTEXT_H diff --git a/src/network/ssl/qsslerror.h b/src/network/ssl/qsslerror.h index 847a48cbc1..135ba11ece 100644 --- a/src/network/ssl/qsslerror.h +++ b/src/network/ssl/qsslerror.h @@ -46,8 +46,6 @@ #include <QtCore/qvariant.h> #include <QtNetwork/qsslcertificate.h> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -126,6 +124,4 @@ QT_END_NAMESPACE Q_DECLARE_METATYPE(QList<QSslError>) #endif -QT_END_HEADER - #endif diff --git a/src/network/ssl/qsslkey.h b/src/network/ssl/qsslkey.h index 986b1c41de..145d4a28f1 100644 --- a/src/network/ssl/qsslkey.h +++ b/src/network/ssl/qsslkey.h @@ -48,8 +48,6 @@ #include <QtCore/qsharedpointer.h> #include <QtNetwork/qssl.h> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -110,6 +108,4 @@ Q_NETWORK_EXPORT QDebug operator<<(QDebug debug, const QSslKey &key); QT_END_NAMESPACE -QT_END_HEADER - #endif diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index f0c3f40a28..c86234a5ac 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -2410,6 +2410,23 @@ QList<QByteArray> QSslSocketPrivate::unixRootCertDirectories() << "/opt/openssl/certs/"; // HP-UX } +/*! + \internal +*/ +void QSslSocketPrivate::checkSettingSslContext(QSslSocket* socket, QSharedPointer<QSslContext> sslContext) +{ + if (socket->d_func()->sslContextPointer.isNull()) + socket->d_func()->sslContextPointer = sslContext; +} + +/*! + \internal +*/ +QSharedPointer<QSslContext> QSslSocketPrivate::sslContext(QSslSocket *socket) +{ + return (socket) ? socket->d_func()->sslContextPointer : QSharedPointer<QSslContext>(); +} + QT_END_NAMESPACE #include "moc_qsslsocket.cpp" diff --git a/src/network/ssl/qsslsocket.h b/src/network/ssl/qsslsocket.h index 929e437554..55141243ff 100644 --- a/src/network/ssl/qsslsocket.h +++ b/src/network/ssl/qsslsocket.h @@ -50,8 +50,6 @@ # include <QtNetwork/qsslerror.h> #endif -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -223,6 +221,4 @@ private: QT_END_NAMESPACE -QT_END_HEADER - #endif diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index f846bf2d8b..6845752d8b 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -156,6 +156,19 @@ private: }; Q_GLOBAL_STATIC(QOpenSslLocks, openssl_locks) +QString QSslSocketBackendPrivate::getErrorsFromOpenSsl() +{ + QString errorString; + unsigned long errNum; + while ((errNum = q_ERR_get_error())) { + if (! errorString.isEmpty()) + errorString.append(QLatin1String(", ")); + const char *error = q_ERR_error_string(errNum, NULL); + errorString.append(QString::fromLatin1(error)); // error is ascii according to man ERR_error_string + } + return errorString; +} + extern "C" { static void locking_function(int mode, int lockNumber, const char *, int) { @@ -175,8 +188,6 @@ static unsigned long id_function() QSslSocketBackendPrivate::QSslSocketBackendPrivate() : ssl(0), - ctx(0), - pkey(0), readBio(0), writeBio(0), session(0) @@ -240,7 +251,8 @@ struct QSslErrorList QList<QPair<int, int> > errors; }; Q_GLOBAL_STATIC(QSslErrorList, _q_sslErrorList) -static int q_X509Callback(int ok, X509_STORE_CTX *ctx) + +int q_X509Callback(int ok, X509_STORE_CTX *ctx) { if (!ok) { // Store the error and at which depth the error was detected. @@ -311,191 +323,21 @@ bool QSslSocketBackendPrivate::initSslContext() { Q_Q(QSslSocket); - // Create and initialize SSL context. Accept SSLv2, SSLv3 and TLSv1_0. - bool client = (mode == QSslSocket::SslClientMode); + // If no external context was set (e.g. bei QHttpNetworkConnection) we will create a default context + if (!sslContextPointer) + sslContextPointer = QSharedPointer<QSslContext>( + QSslContext::fromConfiguration(mode, QSslConfiguration(&configuration), allowRootCertOnDemandLoading)); - bool reinitialized = false; - -init_context: - switch (configuration.protocol) { - case QSsl::SslV2: -#ifndef OPENSSL_NO_SSL2 - ctx = q_SSL_CTX_new(client ? q_SSLv2_client_method() : q_SSLv2_server_method()); -#else - ctx = 0; // SSL 2 not supported by the system, but chosen deliberately -> error -#endif - break; - case QSsl::SslV3: - ctx = q_SSL_CTX_new(client ? q_SSLv3_client_method() : q_SSLv3_server_method()); - break; - case QSsl::SecureProtocols: // SslV2 will be disabled below - case QSsl::TlsV1SslV3: // SslV2 will be disabled below - case QSsl::AnyProtocol: - default: - ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method()); - break; - case QSsl::TlsV1_0: - ctx = q_SSL_CTX_new(client ? q_TLSv1_client_method() : q_TLSv1_server_method()); - break; - case QSsl::TlsV1_1: -#if OPENSSL_VERSION_NUMBER >= 0x10001000L - ctx = q_SSL_CTX_new(client ? q_TLSv1_1_client_method() : q_TLSv1_1_server_method()); -#else - ctx = 0; // TLS 1.1 not supported by the system, but chosen deliberately -> error -#endif - break; - case QSsl::TlsV1_2: -#if OPENSSL_VERSION_NUMBER >= 0x10001000L - ctx = q_SSL_CTX_new(client ? q_TLSv1_2_client_method() : q_TLSv1_2_server_method()); -#else - ctx = 0; // TLS 1.2 not supported by the system, but chosen deliberately -> error -#endif - break; - } - if (!ctx) { - // After stopping Flash 10 the SSL library looses its ciphers. Try re-adding them - // by re-initializing the library. - if (!reinitialized) { - reinitialized = true; - if (q_SSL_library_init() == 1) - goto init_context; - } - - q->setErrorString(QSslSocket::tr("Error creating SSL context (%1)").arg(getErrorsFromOpenSsl())); - q->setSocketError(QAbstractSocket::SslInternalError); - emit q->error(QAbstractSocket::SslInternalError); - return false; - } - - // Enable bug workarounds. - long options = setupOpenSslOptions(configuration.protocol, configuration.sslOptions); - q_SSL_CTX_set_options(ctx, options); - -#if OPENSSL_VERSION_NUMBER >= 0x10000000L - // Tell OpenSSL to release memory early - // http://www.openssl.org/docs/ssl/SSL_CTX_set_mode.html - if (q_SSLeay() >= 0x10000000L) - q_SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS); -#endif - - // Initialize ciphers - QByteArray cipherString; - int first = true; - QList<QSslCipher> ciphers = configuration.ciphers; - if (ciphers.isEmpty()) - ciphers = defaultCiphers(); - foreach (const QSslCipher &cipher, ciphers) { - if (first) - first = false; - else - cipherString.append(':'); - cipherString.append(cipher.name().toLatin1()); - } - - if (!q_SSL_CTX_set_cipher_list(ctx, cipherString.data())) { - q->setErrorString(QSslSocket::tr("Invalid or empty cipher list (%1)").arg(getErrorsFromOpenSsl())); + if (sslContextPointer->error() != QSslError::NoError) { + q->setErrorString(sslContextPointer->errorString()); q->setSocketError(QAbstractSocket::SslInvalidUserDataError); emit q->error(QAbstractSocket::SslInvalidUserDataError); + sslContextPointer.clear(); // deletes the QSslContext return false; } - // Add all our CAs to this store. - QList<QSslCertificate> expiredCerts; - foreach (const QSslCertificate &caCertificate, q->caCertificates()) { - // add expired certs later, so that the - // valid ones are used before the expired ones - if (caCertificate.expiryDate() < QDateTime::currentDateTime()) { - expiredCerts.append(caCertificate); - } else { - q_X509_STORE_add_cert(ctx->cert_store, reinterpret_cast<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 - if (addExpiredCerts) { - foreach (const QSslCertificate &caCertificate, expiredCerts) { - q_X509_STORE_add_cert(ctx->cert_store, reinterpret_cast<X509 *>(caCertificate.handle())); - } - } - - if (s_loadRootCertsOnDemand && allowRootCertOnDemandLoading) { - // tell OpenSSL the directories where to look up the root certs on demand - QList<QByteArray> unixDirs = unixRootCertDirectories(); - for (int a = 0; a < unixDirs.count(); ++a) - q_SSL_CTX_load_verify_locations(ctx, 0, unixDirs.at(a).constData()); - } - - // Register a custom callback to get all verification errors. - X509_STORE_set_verify_cb_func(ctx->cert_store, q_X509Callback); - - if (!configuration.localCertificate.isNull()) { - // Require a private key as well. - if (configuration.privateKey.isNull()) { - q->setErrorString(QSslSocket::tr("Cannot provide a certificate with no key, %1").arg(getErrorsFromOpenSsl())); - q->setSocketError(QAbstractSocket::SslInvalidUserDataError); - emit q->error(QAbstractSocket::SslInvalidUserDataError); - return false; - } - - // Load certificate - if (!q_SSL_CTX_use_certificate(ctx, reinterpret_cast<X509 *>(configuration.localCertificate.handle()))) { - q->setErrorString(QSslSocket::tr("Error loading local certificate, %1").arg(getErrorsFromOpenSsl())); - q->setSocketError(QAbstractSocket::SslInternalError); - emit q->error(QAbstractSocket::SslInternalError); - return false; - } - - if (configuration.privateKey.algorithm() == QSsl::Opaque) { - pkey = reinterpret_cast<EVP_PKEY *>(configuration.privateKey.handle()); - } else { - // Load private key - pkey = q_EVP_PKEY_new(); - // before we were using EVP_PKEY_assign_R* functions and did not use EVP_PKEY_free. - // this lead to a memory leak. Now we use the *_set1_* functions which do not - // take ownership of the RSA/DSA key instance because the QSslKey already has ownership. - if (configuration.privateKey.algorithm() == QSsl::Rsa) - q_EVP_PKEY_set1_RSA(pkey, reinterpret_cast<RSA *>(configuration.privateKey.handle())); - else - q_EVP_PKEY_set1_DSA(pkey, reinterpret_cast<DSA *>(configuration.privateKey.handle())); - } - - if (!q_SSL_CTX_use_PrivateKey(ctx, pkey)) { - q->setErrorString(QSslSocket::tr("Error loading private key, %1").arg(getErrorsFromOpenSsl())); - q->setSocketError(QAbstractSocket::SslInternalError); - emit q->error(QAbstractSocket::SslInternalError); - return false; - } - if (configuration.privateKey.algorithm() == QSsl::Opaque) - pkey = 0; // Don't free the private key, it belongs to QSslKey - - // Check if the certificate matches the private key. - if (!q_SSL_CTX_check_private_key(ctx)) { - q->setErrorString(QSslSocket::tr("Private key does not certify public key, %1").arg(getErrorsFromOpenSsl())); - q->setSocketError(QAbstractSocket::SslInvalidUserDataError); - emit q->error(QAbstractSocket::SslInvalidUserDataError); - return false; - } - } - - // Initialize peer verification. - if (configuration.peerVerifyMode == QSslSocket::VerifyNone) { - q_SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); - } else { - q_SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, q_X509Callback); - } - - // Set verification depth. - if (configuration.peerVerifyDepth != 0) - q_SSL_CTX_set_verify_depth(ctx, configuration.peerVerifyDepth); - // Create and initialize SSL session - if (!(ssl = q_SSL_new(ctx))) { + if (!(ssl = sslContextPointer->createSsl())) { // ### Bad error code q->setErrorString(QSslSocket::tr("Error creating SSL session, %1").arg(getErrorsFromOpenSsl())); q->setSocketError(QAbstractSocket::SslInternalError); @@ -510,7 +352,7 @@ init_context: configuration.protocol == QSsl::TlsV1_2 || configuration.protocol == QSsl::SecureProtocols || configuration.protocol == QSsl::AnyProtocol) && - client && q_SSLeay() >= 0x00090806fL) { + mode == QSslSocket::SslClientMode && q_SSLeay() >= 0x00090806fL) { // Set server hostname on TLS extension. RFC4366 section 3.1 requires it in ACE format. QString tlsHostName = verificationPeerName.isEmpty() ? q->peerName() : verificationPeerName; if (tlsHostName.isEmpty()) @@ -527,7 +369,6 @@ init_context: #endif // Clear the session. - q_SSL_clear(ssl); errorList.clear(); // Initialize memory BIOs for encryption and decryption. @@ -557,14 +398,7 @@ void QSslSocketBackendPrivate::destroySslContext() q_SSL_free(ssl); ssl = 0; } - if (ctx) { - q_SSL_CTX_free(ctx); - ctx = 0; - } - if (pkey) { - q_EVP_PKEY_free(pkey); - pkey = 0; - } + sslContextPointer.clear(); } /*! @@ -1102,7 +936,7 @@ void QSslSocketBackendPrivate::transmit() break; } } while (ssl && readBytes > 0); - } while (ssl && ctx && transmitting); + } while (ssl && transmitting); } static QSslError _q_OpenSSL_to_QSslError(int errorCode, const QSslCertificate &cert) @@ -1308,7 +1142,6 @@ bool QSslSocketBackendPrivate::startHandshake() } } #endif - if (!checkSslErrors()) return false; } else { @@ -1532,7 +1365,7 @@ void QSslSocketBackendPrivate::disconnected() QSslCipher QSslSocketBackendPrivate::sessionCipher() const { - if (!ssl || !ctx) + if (!ssl) return QSslCipher(); #if OPENSSL_VERSION_NUMBER >= 0x10000000L // FIXME This is fairly evil, but needed to keep source level compatibility @@ -1552,6 +1385,15 @@ void QSslSocketBackendPrivate::continueHandshake() if (readBufferMaxSize) plainSocket->setReadBufferSize(readBufferMaxSize); + if (q_SSL_ctrl((ssl), SSL_CTRL_GET_SESSION_REUSED, 0, NULL)) + configuration.peerSessionShared = true; + + // Cache this SSL session inside the QSslContext + if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionTickets)) { + if (!sslContextPointer->cacheSession(ssl)) + sslContextPointer.clear(); // we could not cache the session + } + connectionEncrypted = true; emit q->encrypted(); if (autoStartHandshake && pendingClose) { @@ -1571,19 +1413,6 @@ QList<QSslCertificate> QSslSocketBackendPrivate::STACKOFX509_to_QSslCertificates return certificates; } -QString QSslSocketBackendPrivate::getErrorsFromOpenSsl() -{ - QString errorString; - unsigned long errNum; - while((errNum = q_ERR_get_error())) { - if (! errorString.isEmpty()) - errorString.append(QLatin1String(", ")); - const char *error = q_ERR_error_string(errNum, NULL); - errorString.append(QString::fromLatin1(error)); // error is ascii according to man ERR_error_string - } - return errorString; -} - bool QSslSocketBackendPrivate::isMatchingHostname(const QSslCertificate &cert, const QString &peerName) { QStringList commonNameList = cert.subjectInfo(QSslCertificate::CommonName); @@ -1675,17 +1504,9 @@ QList<QSslError> QSslSocketBackendPrivate::verify(QList<QSslCertificate> certifi } } - 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 - if (addExpiredCerts) { - foreach (const QSslCertificate &caCertificate, expiredCerts) { - q_X509_STORE_add_cert(certStore, reinterpret_cast<X509 *>(caCertificate.handle())); - } + foreach (const QSslCertificate &caCertificate, expiredCerts) { + q_X509_STORE_add_cert(certStore, reinterpret_cast<X509 *>(caCertificate.handle())); } QMutexLocker sslErrorListMutexLocker(&_q_sslErrorList()->mutex); diff --git a/src/network/ssl/qsslsocket_openssl_p.h b/src/network/ssl/qsslsocket_openssl_p.h index d6675197b4..c8b23e6cad 100644 --- a/src/network/ssl/qsslsocket_openssl_p.h +++ b/src/network/ssl/qsslsocket_openssl_p.h @@ -75,7 +75,10 @@ #if defined(OCSP_RESPONSE) #undef OCSP_RESPONSE #endif +#if defined(X509_NAME) +#undef X509_NAME #endif +#endif // Q_OS_WIN #include <openssl/asn1.h> #include <openssl/bio.h> @@ -115,8 +118,6 @@ public: bool initSslContext(); void destroySslContext(); SSL *ssl; - SSL_CTX *ctx; - EVP_PKEY *pkey; BIO *readBio; BIO *writeBio; SSL_SESSION *session; diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp index 9f271f863a..2be62515e8 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols.cpp +++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp @@ -245,6 +245,10 @@ DEFINEFUNC3(void, SSL_set_bio, SSL *a, a, BIO *b, b, BIO *c, c, return, DUMMYARG DEFINEFUNC(void, SSL_set_accept_state, SSL *a, a, return, DUMMYARG) DEFINEFUNC(void, SSL_set_connect_state, SSL *a, a, return, DUMMYARG) DEFINEFUNC(int, SSL_shutdown, SSL *a, a, return -1, return) +DEFINEFUNC2(int, SSL_set_session, SSL* to, to, SSL_SESSION *session, session, return -1, return) +DEFINEFUNC(void, SSL_SESSION_free, SSL_SESSION *ses, ses, return, DUMMYARG) +DEFINEFUNC(SSL_SESSION*, SSL_get1_session, SSL *ssl, ssl, return 0, return) +DEFINEFUNC(SSL_SESSION*, SSL_get_session, const SSL *ssl, ssl, return 0, return) #if OPENSSL_VERSION_NUMBER >= 0x10000000L #ifndef OPENSSL_NO_SSL2 DEFINEFUNC(const SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return 0, return) @@ -457,28 +461,46 @@ static QStringList findAllLibCrypto() # endif #ifdef Q_OS_WIN -static QPair<QSystemLibrary*, QSystemLibrary*> loadOpenSslWin32() +static bool tryToLoadOpenSslWin32Library(QLatin1String ssleay32LibName, QLatin1String libeay32LibName, QPair<QSystemLibrary*, QSystemLibrary*> &pair) { - QPair<QSystemLibrary*,QSystemLibrary*> pair; pair.first = 0; pair.second = 0; - QSystemLibrary *ssleay32 = new QSystemLibrary(QLatin1String("ssleay32")); + QSystemLibrary *ssleay32 = new QSystemLibrary(ssleay32LibName); if (!ssleay32->load(false)) { - // Cannot find ssleay32.dll delete ssleay32; - return pair; + return FALSE; } - QSystemLibrary *libeay32 = new QSystemLibrary(QLatin1String("libeay32")); + QSystemLibrary *libeay32 = new QSystemLibrary(libeay32LibName); if (!libeay32->load(false)) { delete ssleay32; delete libeay32; - return pair; + return FALSE; } pair.first = ssleay32; pair.second = libeay32; + return TRUE; +} + +static QPair<QSystemLibrary*, QSystemLibrary*> loadOpenSslWin32() +{ + QPair<QSystemLibrary*,QSystemLibrary*> pair; + pair.first = 0; + pair.second = 0; + + // When OpenSSL is built using MSVC then the libraries are named 'ssleay32.dll' and 'libeay32'dll'. + // When OpenSSL is built using GCC then different library names are used (depending on the OpenSSL version) + // The oldest version of a GCC-based OpenSSL which can be detected by the code below is 0.9.8g (released in 2007) + if (!tryToLoadOpenSslWin32Library(QLatin1String("ssleay32"), QLatin1String("libeay32"), pair)) { + if (!tryToLoadOpenSslWin32Library(QLatin1String("libssl-10"), QLatin1String("libcrypto-10"), pair)) { + if (!tryToLoadOpenSslWin32Library(QLatin1String("libssl-8"), QLatin1String("libcrypto-8"), pair)) { + tryToLoadOpenSslWin32Library(QLatin1String("libssl-7"), QLatin1String("libcrypto-7"), pair); + } + } + } + return pair; } #else @@ -699,6 +721,10 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(SSL_set_bio) RESOLVEFUNC(SSL_set_connect_state) RESOLVEFUNC(SSL_shutdown) + RESOLVEFUNC(SSL_set_session) + RESOLVEFUNC(SSL_SESSION_free) + RESOLVEFUNC(SSL_get1_session) + RESOLVEFUNC(SSL_get_session) RESOLVEFUNC(SSL_write) #ifndef OPENSSL_NO_SSL2 RESOLVEFUNC(SSLv2_client_method) diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h index ccd9d3cfb9..62648e3e37 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols_p.h +++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h @@ -347,6 +347,10 @@ void q_SSL_set_bio(SSL *a, BIO *b, BIO *c); void q_SSL_set_accept_state(SSL *a); void q_SSL_set_connect_state(SSL *a); int q_SSL_shutdown(SSL *a); +int q_SSL_set_session(SSL *to, SSL_SESSION *session); +void q_SSL_SESSION_free(SSL_SESSION *ses); +SSL_SESSION *q_SSL_get1_session(SSL *ssl); +SSL_SESSION *q_SSL_get_session(const SSL *ssl); #if OPENSSL_VERSION_NUMBER >= 0x10000000L const SSL_METHOD *q_SSLv2_client_method(); const SSL_METHOD *q_SSLv3_client_method(); diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h index 851dec5840..72117353ac 100644 --- a/src/network/ssl/qsslsocket_p.h +++ b/src/network/ssl/qsslsocket_p.h @@ -59,6 +59,7 @@ #include <private/qtcpsocket_p.h> #include "qsslkey.h" #include "qsslconfiguration_p.h" +#include <private/qsslcontext_p.h> #include <QtCore/qstringlist.h> @@ -114,6 +115,7 @@ public: QSslConfigurationPrivate configuration; QList<QSslError> sslErrors; + QSharedPointer<QSslContext> sslContextPointer; // if set, this hostname is used for certificate validation instead of the hostname // that was used for connecting to. @@ -121,6 +123,8 @@ public: bool allowRootCertOnDemandLoading; + static bool s_loadRootCertsOnDemand; + static bool supportsSsl(); static long sslLibraryVersionNumber(); static QString sslLibraryVersionString(); @@ -155,6 +159,9 @@ public: void createPlainSocket(QIODevice::OpenMode openMode); static void pauseSocketNotifiers(QSslSocket*); static void resumeSocketNotifiers(QSslSocket*); + // ### The 2 methods below should be made member methods once the QSslContext class is made public + static void checkSettingSslContext(QSslSocket*, QSharedPointer<QSslContext>); + static QSharedPointer<QSslContext> sslContext(QSslSocket *socket); bool isPaused() const; void _q_connectedSlot(); void _q_hostFoundSlot(); @@ -170,6 +177,8 @@ public: virtual void _q_caRootLoaded(QSslCertificate,QSslCertificate) = 0; #endif + static QList<QByteArray> unixRootCertDirectories(); // used also by QSslContext + virtual qint64 peek(char *data, qint64 maxSize); virtual QByteArray peek(qint64 maxSize); @@ -192,8 +201,6 @@ private: static bool s_loadedCiphersAndCerts; protected: bool verifyErrorsHaveBeenIgnored(); - static bool s_loadRootCertsOnDemand; - static QList<QByteArray> unixRootCertDirectories(); bool paused; }; diff --git a/src/network/ssl/ssl.pri b/src/network/ssl/ssl.pri index 8ebb4b29af..f5afb43759 100644 --- a/src/network/ssl/ssl.pri +++ b/src/network/ssl/ssl.pri @@ -14,7 +14,8 @@ contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked) { ssl/qsslsocket_openssl_symbols_p.h \ ssl/qsslsocket_p.h \ ssl/qsslcertificateextension.h \ - ssl/qsslcertificateextension_p.h + ssl/qsslcertificateextension_p.h \ + ssl/qsslcontext_p.h SOURCES += ssl/qssl.cpp \ ssl/qsslcertificate.cpp \ ssl/qsslconfiguration.cpp \ @@ -24,7 +25,8 @@ contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked) { ssl/qsslsocket.cpp \ ssl/qsslsocket_openssl.cpp \ ssl/qsslsocket_openssl_symbols.cpp \ - ssl/qsslcertificateextension.cpp + ssl/qsslcertificateextension.cpp \ + ssl/qsslcontext.cpp # Add optional SSL libs # Static linking of OpenSSL with msvc: |