Improve the testability of QSslOptions.

The handling of QSslOptions is complicated not only by the subject, but
also by the fact that some of the openssl directives are negatives. This
commit tries to separate the inherent complexity from the complexity of
the api by allowing us to test them independently.

Change-Id: Ieb9386c69dd9b0b49dc42e26b2878a301f26ded1
Reviewed-by: Peter Hartmann <peter.hartmann@nokia.com>
This commit is contained in:
Richard Moore 2011-11-15 21:58:05 +00:00 committed by Qt by Nokia
parent 944b799944
commit bf7364f0aa
3 changed files with 79 additions and 29 deletions

View File

@ -232,6 +232,40 @@ static int q_X509Callback(int ok, X509_STORE_CTX *ctx)
return 1;
}
long QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions)
{
long options;
if (protocol == QSsl::TlsV1SslV3 || 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 (sslOptions & QSsl::SslOptionDisableEmptyFragments)
options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
else
options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
#ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
// This option is disabled by default, so we need to be able to clear it
if (sslOptions & QSsl::SslOptionDisableLegacyRenegotiation)
options &= ~SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
else
options |= SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
#endif
#ifdef SSL_OP_NO_TICKET
if (sslOptions & QSsl::SslOptionDisableSessionTickets)
options |= SSL_OP_NO_TICKET;
#endif
#ifdef SSL_OP_NO_COMPRESSION
if (sslOptions & QSsl::SslOptionDisableCompression)
options |= SSL_OP_NO_COMPRESSION;
#endif
return options;
}
bool QSslSocketBackendPrivate::initSslContext()
{
Q_Q(QSslSocket);
@ -275,35 +309,7 @@ init_context:
}
// 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_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
// This option is disabled by default, so we need to be able to clear it
if (configuration.sslOptions & QSsl::SslOptionDisableLegacyRenegotiation)
options &= ~SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
else
options |= SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
#endif
#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
long options = setupOpenSslOptions(configuration.protocol, configuration.sslOptions);
q_SSL_CTX_set_options(ctx, options);
// Initialize ciphers

View File

@ -118,6 +118,7 @@ public:
void disconnected();
QSslCipher sessionCipher() const;
Q_AUTOTEST_EXPORT static long setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions);
static QSslCipher QSslCipher_from_SSL_CIPHER(SSL_CIPHER *cipher);
static QList<QSslCertificate> STACKOFX509_to_QSslCertificates(STACK_OF(X509) *x509);
static bool isMatchingHostname(const QSslCertificate &cert, const QString &peerName);

View File

@ -192,6 +192,7 @@ private slots:
void blacklistedCertificates();
void setEmptyDefaultConfiguration();
void versionAccessors();
void sslOptions();
static void exitLoop()
{
@ -2052,6 +2053,48 @@ void tst_QSslSocket::versionAccessors()
qDebug() << QString::number(QSslSocket::sslLibraryVersionNumber(), 16);
}
void tst_QSslSocket::sslOptions()
{
if (!QSslSocket::supportsSsl())
return;
QCOMPARE(QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SecureProtocols,
QSsl::SslOptionDisableEmptyFragments
|QSsl::SslOptionDisableLegacyRenegotiation),
long(SSL_OP_ALL|SSL_OP_NO_SSLv2));
#ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
QCOMPARE(QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SecureProtocols,
QSsl::SslOptionDisableEmptyFragments),
long((SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)));
#endif
#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
QCOMPARE(QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SecureProtocols,
QSsl::SslOptionDisableLegacyRenegotiation),
long((SSL_OP_ALL|SSL_OP_NO_SSLv2) & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS));
#endif
#ifdef SSL_OP_NO_TICKET
QCOMPARE(QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SecureProtocols,
QSsl::SslOptionDisableEmptyFragments
|QSsl::SslOptionDisableLegacyRenegotiation
|QSsl::SslOptionDisableSessionTickets),
long((SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_TICKET)));
#endif
#ifdef SSL_OP_NO_TICKET
#ifdef SSL_OP_NO_COMPRESSION
QCOMPARE(QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SecureProtocols,
QSsl::SslOptionDisableEmptyFragments
|QSsl::SslOptionDisableLegacyRenegotiation
|QSsl::SslOptionDisableSessionTickets
|QSsl::SslOptionDisableCompression),
long((SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_TICKET|SSL_OP_NO_COMPRESSION)));
#endif
#endif
}
#endif // QT_NO_OPENSSL
QTEST_MAIN(tst_QSslSocket)