Add the ability to enable various SSL bug workarounds.
There are lots of buggy SSL servers around and to connect to them you need to disable various features. This commit adds the ability to disable the SSL ticket extension, the ability to disable the insertion of empty fragments, and the ability to disable compression. Task-number: QTBUG-21906 Change-Id: I3e1d0347a46e9030b889bbf15b2aad19b8513b73 Merge-request: 68 Reviewed-by: Peter Hartmann <peter.hartmann@nokia.com>
This commit is contained in:
parent
5b6894de87
commit
78d02e93ac
@ -120,4 +120,34 @@ QT_BEGIN_NAMESPACE
|
||||
the correct setting for your protocol.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\enum QSsl::SslOption
|
||||
|
||||
Describes the options that can be used to control the details of
|
||||
SSL behaviour. These options are generally used to turn features off
|
||||
to work around buggy servers.
|
||||
|
||||
\value SslOptionDisableEmptyFragments Disables the insertion of empty
|
||||
fragments into the data when using block ciphers. When enabled, this
|
||||
prevents some attacks (such as the BEAST attack), however it is
|
||||
incompatible with some servers.
|
||||
\value SslOptionDisableTickets Disables the SSL session ticket
|
||||
extension. This can cause slower connection setup, however some servers
|
||||
are not compatible with the extension.
|
||||
\value SslOptionDisableCompression Disables the SSL compression
|
||||
extension. When enabled, this allows the data being passed over SSL to
|
||||
be compressed, however some servers are not compatible with this
|
||||
extension.
|
||||
\value SslOptionDisableServerNameIndication Disables the SSL server
|
||||
name indication extension. When enabled, this tells the server the virtual
|
||||
host being accessed allowing it to respond with the correct certificate.
|
||||
|
||||
By default, SslOptionDisableEmptyFragments is turned on since this causes
|
||||
problems with a large number of servers, but the other options are disabled.
|
||||
|
||||
Note: Availability of above options depends on the version of the SSL
|
||||
backend in use.
|
||||
*/
|
||||
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -44,6 +44,7 @@
|
||||
#define QSSL_H
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
#include <QtCore/QFlags>
|
||||
|
||||
QT_BEGIN_HEADER
|
||||
|
||||
@ -86,8 +87,18 @@ namespace QSsl {
|
||||
SecureProtocols,
|
||||
UnknownProtocol = -1
|
||||
};
|
||||
|
||||
enum SslOption {
|
||||
SslOptionDisableEmptyFragments = 0x01,
|
||||
SslOptionDisableSessionTickets = 0x02,
|
||||
SslOptionDisableCompression = 0x04,
|
||||
SslOptionDisableServerNameIndication = 0x08
|
||||
};
|
||||
Q_DECLARE_FLAGS(SslOptions, SslOption)
|
||||
}
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QSsl::SslOptions)
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
QT_END_HEADER
|
||||
|
@ -167,7 +167,8 @@ bool QSslConfiguration::operator==(const QSslConfiguration &other) const
|
||||
d->caCertificates == other.d->caCertificates &&
|
||||
d->protocol == other.d->protocol &&
|
||||
d->peerVerifyMode == other.d->peerVerifyMode &&
|
||||
d->peerVerifyDepth == other.d->peerVerifyDepth;
|
||||
d->peerVerifyDepth == other.d->peerVerifyDepth &&
|
||||
d->sslOptions == other.d->sslOptions;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -199,7 +200,8 @@ bool QSslConfiguration::isNull() const
|
||||
d->localCertificate.isNull() &&
|
||||
d->privateKey.isNull() &&
|
||||
d->peerCertificate.isNull() &&
|
||||
d->peerCertificateChain.count() == 0);
|
||||
d->peerCertificateChain.count() == 0 &&
|
||||
d->sslOptions == 0);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -506,6 +508,29 @@ void QSslConfiguration::setCaCertificates(const QList<QSslCertificate> &certific
|
||||
d->caCertificates = certificates;
|
||||
}
|
||||
|
||||
/*!
|
||||
Enables or disables an SSL compatibility option.
|
||||
|
||||
\sa testSSlOption()
|
||||
*/
|
||||
void QSslConfiguration::setSslOption(QSsl::SslOption option, bool on)
|
||||
{
|
||||
if (on)
|
||||
d->sslOptions |= option;
|
||||
else
|
||||
d->sslOptions &= ~option;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns true if the specified SSL compatibility option is enabled.
|
||||
|
||||
\sa testSSlOption()
|
||||
*/
|
||||
bool QSslConfiguration::testSslOption(QSsl::SslOption option) const
|
||||
{
|
||||
return d->sslOptions & option;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the default SSL configuration to be used in new SSL
|
||||
connections.
|
||||
|
@ -59,6 +59,7 @@
|
||||
|
||||
#include <QtCore/qshareddata.h>
|
||||
#include <QtNetwork/qsslsocket.h>
|
||||
#include <QtNetwork/qssl.h>
|
||||
|
||||
QT_BEGIN_HEADER
|
||||
|
||||
@ -118,6 +119,9 @@ public:
|
||||
QList<QSslCertificate> caCertificates() const;
|
||||
void setCaCertificates(const QList<QSslCertificate> &certificates);
|
||||
|
||||
void setSslOption(QSsl::SslOption option, bool on);
|
||||
bool testSslOption(QSsl::SslOption option) const;
|
||||
|
||||
static QSslConfiguration defaultConfiguration();
|
||||
static void setDefaultConfiguration(const QSslConfiguration &configuration);
|
||||
|
||||
|
@ -98,6 +98,8 @@ public:
|
||||
QSslSocket::PeerVerifyMode peerVerifyMode;
|
||||
int peerVerifyDepth;
|
||||
|
||||
QSsl::SslOptions sslOptions;
|
||||
|
||||
// in qsslsocket.cpp:
|
||||
static QSslConfiguration defaultConfiguration();
|
||||
static void setDefaultConfiguration(const QSslConfiguration &configuration);
|
||||
|
@ -897,6 +897,7 @@ void QSslSocket::setSslConfiguration(const QSslConfiguration &configuration)
|
||||
d->configuration.peerVerifyDepth = configuration.peerVerifyDepth();
|
||||
d->configuration.peerVerifyMode = configuration.peerVerifyMode();
|
||||
d->configuration.protocol = configuration.protocol();
|
||||
d->configuration.sslOptions = configuration.d->sslOptions;
|
||||
d->allowRootCertOnDemandLoading = false;
|
||||
}
|
||||
|
||||
@ -2049,6 +2050,7 @@ void QSslConfigurationPrivate::deepCopyDefaultConfiguration(QSslConfigurationPri
|
||||
ptr->protocol = global->protocol;
|
||||
ptr->peerVerifyMode = global->peerVerifyMode;
|
||||
ptr->peerVerifyDepth = global->peerVerifyDepth;
|
||||
ptr->sslOptions = global->sslOptions;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -285,12 +285,29 @@ init_context:
|
||||
return false;
|
||||
}
|
||||
|
||||
// Enable all bug workarounds.
|
||||
if (configuration.protocol == QSsl::TlsV1SslV3 || configuration.protocol == QSsl::SecureProtocols) {
|
||||
q_SSL_CTX_set_options(ctx, SSL_OP_ALL|SSL_OP_NO_SSLv2);
|
||||
} else {
|
||||
q_SSL_CTX_set_options(ctx, SSL_OP_ALL);
|
||||
}
|
||||
// Enable bug workarounds.
|
||||
long options;
|
||||
if (configuration.protocol == QSsl::TlsV1SslV3 || configuration.protocol == QSsl::SecureProtocols)
|
||||
options = SSL_OP_ALL|SSL_OP_NO_SSLv2;
|
||||
else
|
||||
options = SSL_OP_ALL;
|
||||
|
||||
// This option is disabled by default, so we need to be able to clear it
|
||||
if (configuration.sslOptions & QSsl::SslOptionDisableEmptyFragments)
|
||||
options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
|
||||
else
|
||||
options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
|
||||
|
||||
#ifdef SSL_OP_NO_TICKET
|
||||
if (configuration.sslOptions & QSsl::SslOptionDisableSessionTickets)
|
||||
options |= SSL_OP_NO_TICKET;
|
||||
#endif
|
||||
#ifdef SSL_OP_NO_COMPRESSION
|
||||
if (configuration.sslOptions & QSsl::SslOptionDisableCompression)
|
||||
options |= SSL_OP_NO_COMPRESSION;
|
||||
#endif
|
||||
|
||||
q_SSL_CTX_set_options(ctx, options);
|
||||
|
||||
// Initialize ciphers
|
||||
QByteArray cipherString;
|
||||
@ -426,7 +443,9 @@ init_context:
|
||||
tlsHostName = hostName;
|
||||
QByteArray ace = QUrl::toAce(tlsHostName);
|
||||
// only send the SNI header if the URL is valid and not an IP
|
||||
if (!ace.isEmpty() && !QHostAddress().setAddress(tlsHostName)) {
|
||||
if (!ace.isEmpty()
|
||||
&& !QHostAddress().setAddress(tlsHostName)
|
||||
&& !(configuration.sslOptions & QSsl::SslOptionDisableServerNameIndication)) {
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
||||
if (!q_SSL_ctrl(ssl, SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name, ace.data()))
|
||||
#else
|
||||
|
92
tests/manual/qssloptions/main.cpp
Normal file
92
tests/manual/qssloptions/main.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the test suite of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** 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, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia 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.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtNetwork/qsslconfiguration.h>
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/QTextStream>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
if (argc < 3) {
|
||||
QTextStream out(stdout);
|
||||
out << "Usage: " << argv[0] << " host port [options]" << endl;
|
||||
out << "The options can be one or more of the following:" << endl;
|
||||
out << "enable_empty_fragments" << endl;
|
||||
out << "disable_session_tickets" << endl;
|
||||
out << "disable_compression" << endl;
|
||||
out << "disable_sni" << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
QString host = QString::fromLocal8Bit(argv[1]);
|
||||
int port = QString::fromLocal8Bit(argv[2]).toInt();
|
||||
|
||||
QSslConfiguration config = QSslConfiguration::defaultConfiguration();
|
||||
|
||||
for (int i=3; i < argc; i++) {
|
||||
QString option = QString::fromLocal8Bit(argv[i]);
|
||||
|
||||
if (option == QStringLiteral("enable_empty_fragments"))
|
||||
config.setSslOption(QSsl::SslOptionDisableEmptyFragments, false);
|
||||
else if (option == QStringLiteral("disable_session_tickets"))
|
||||
config.setSslOption(QSsl::SslOptionDisableSessionTickets, true);
|
||||
else if (option == QStringLiteral("disable_compression"))
|
||||
config.setSslOption(QSsl::SslOptionDisableCompression, true);
|
||||
else if (option == QStringLiteral("disable_sni"))
|
||||
config.setSslOption(QSsl::SslOptionDisableServerNameIndication, true);
|
||||
}
|
||||
|
||||
QSslConfiguration::setDefaultConfiguration(config);
|
||||
|
||||
QSslSocket socket;
|
||||
//socket.setSslConfiguration(config);
|
||||
socket.connectToHostEncrypted(host, port);
|
||||
|
||||
if ( !socket.waitForEncrypted() ) {
|
||||
qDebug() << socket.errorString();
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
12
tests/manual/qssloptions/qssloptions.pro
Normal file
12
tests/manual/qssloptions/qssloptions.pro
Normal file
@ -0,0 +1,12 @@
|
||||
load(qttest_p4)
|
||||
TEMPLATE = app
|
||||
TARGET = tst_qssloptions
|
||||
DEPENDPATH += .
|
||||
INCLUDEPATH += .
|
||||
|
||||
QT -= gui
|
||||
QT += network
|
||||
|
||||
#CONFIG += release
|
||||
|
||||
SOURCES += main.cpp
|
Loading…
Reference in New Issue
Block a user