Skip to content

Commit

Permalink
Make ciphersuite selection configurable; match Chromium by default. (a…
Browse files Browse the repository at this point in the history
…riya#12524)

New option --ssl-ciphers takes a colon-separated list of OpenSSL
cipher names and sets the client cipher list to exactly that list.

The default for this option is arranged to match Chromium 35, which
has had its cipher selection optimized for the modern Web
(see https://briansmith.org/browser-ciphersuites-01.html for
rationales).  (Newer versions are the same except that they also add
ChaCha20-based ciphersuites, which OpenSSL 1.0.1 hasn't yet picked up.)
  • Loading branch information
zackw authored and olivierlefloch committed Oct 15, 2014
1 parent 6288878 commit 0b8b6bb
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 0 deletions.
34 changes: 34 additions & 0 deletions src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ static const struct QCommandLineConfigEntry flags[] =
{ QCommandLine::Option, '\0', "script-encoding", "Sets the encoding used for the starting script, default is 'utf8'", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "web-security", "Enables web security, 'true' (default) or 'false'", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "ssl-protocol", "Selects a specific SSL protocol version to offer. Values (case insensitive): TLSv1.2, TLSv1.1, TLSv1.0, TLSv1 (same as v1.0), SSLv3, or ANY. Default is to offer all that Qt thinks are secure (SSLv3 and up). Not all values may be supported, depending on the system OpenSSL library.", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "ssl-ciphers", "Sets supported TLS/SSL ciphers. Argument is a colon-separated list of OpenSSL cipher names (macros like ALL, kRSA, etc. may not be used). Default matches modern browsers.", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "ssl-certificates-path", "Sets the location for custom CA certificates (if none set, uses system default)", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "webdriver", "Starts in 'Remote WebDriver mode' (embedded GhostDriver): '[[<IP>:]<PORT>]' (default '127.0.0.1:8910') ", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "webdriver-logfile", "File where to write the WebDriver's Log (default 'none') (NOTE: needs '--webdriver') ", QCommandLine::Optional },
Expand Down Expand Up @@ -540,6 +541,25 @@ void Config::resetToDefaults()
m_helpFlag = false;
m_printDebugMessages = false;
m_sslProtocol = "default";
// Default taken from Chromium 35.0.1916.153
m_sslCiphers = ("ECDHE-ECDSA-AES128-GCM-SHA256"
":ECDHE-RSA-AES128-GCM-SHA256"
":DHE-RSA-AES128-GCM-SHA256"
":ECDHE-ECDSA-AES256-SHA"
":ECDHE-ECDSA-AES128-SHA"
":ECDHE-RSA-AES128-SHA"
":ECDHE-RSA-AES256-SHA"
":ECDHE-ECDSA-RC4-SHA"
":ECDHE-RSA-RC4-SHA"
":DHE-RSA-AES128-SHA"
":DHE-DSS-AES128-SHA"
":DHE-RSA-AES256-SHA"
":AES128-GCM-SHA256"
":AES128-SHA"
":AES256-SHA"
":DES-CBC3-SHA"
":RC4-SHA"
":RC4-MD5");
m_sslCertificatesPath.clear();
m_webdriverIp = QString();
m_webdriverPort = QString();
Expand Down Expand Up @@ -693,6 +713,9 @@ void Config::handleOption(const QString &option, const QVariant &value)
if (option == "ssl-protocol") {
setSslProtocol(value.toString());
}
if (option == "ssl-ciphers") {
setSslCiphers(value.toString());
}
if (option == "ssl-certificates-path") {
setSslCertificatesPath(value.toString());
}
Expand Down Expand Up @@ -735,6 +758,17 @@ void Config::setSslProtocol(const QString& sslProtocolName)
m_sslProtocol = sslProtocolName.toLower();
}

QString Config::sslCiphers() const
{
return m_sslCiphers;
}

void Config::setSslCiphers(const QString& sslCiphersName)
{
// OpenSSL cipher strings are case sensitive.
m_sslCiphers = sslCiphersName;
}

QString Config::sslCertificatesPath() const
{
return m_sslCertificatesPath;
Expand Down
5 changes: 5 additions & 0 deletions src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class Config: public QObject
Q_PROPERTY(bool javascriptCanOpenWindows READ javascriptCanOpenWindows WRITE setJavascriptCanOpenWindows)
Q_PROPERTY(bool javascriptCanCloseWindows READ javascriptCanCloseWindows WRITE setJavascriptCanCloseWindows)
Q_PROPERTY(QString sslProtocol READ sslProtocol WRITE setSslProtocol)
Q_PROPERTY(QString sslCiphers READ sslCiphers WRITE setSslCiphers)
Q_PROPERTY(QString sslCertificatesPath READ sslCertificatesPath WRITE setSslCertificatesPath)
Q_PROPERTY(QString webdriver READ webdriver WRITE setWebdriver)
Q_PROPERTY(QString webdriverLogFile READ webdriverLogFile WRITE setWebdriverLogFile)
Expand Down Expand Up @@ -157,6 +158,9 @@ class Config: public QObject
void setSslProtocol(const QString& sslProtocolName);
QString sslProtocol() const;

void setSslCiphers(const QString& sslCiphersName);
QString sslCiphers() const;

void setSslCertificatesPath(const QString& sslCertificatesPath);
QString sslCertificatesPath() const;

Expand Down Expand Up @@ -217,6 +221,7 @@ public slots:
bool m_javascriptCanOpenWindows;
bool m_javascriptCanCloseWindows;
QString m_sslProtocol;
QString m_sslCiphers;
QString m_sslCertificatesPath;
QString m_webdriverIp;
QString m_webdriverPort;
Expand Down
16 changes: 16 additions & 0 deletions src/networkaccessmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <QNetworkRequest>
#include <QSslSocket>
#include <QSslCertificate>
#include <QSslCipher>
#include <QRegExp>

#include "phantom.h"
Expand Down Expand Up @@ -155,6 +156,21 @@ NetworkAccessManager::NetworkAccessManager(QObject *parent, const Config *config
m_sslConfiguration.setProtocol(QSsl::SecureProtocols);
}

// Essentially the same as what QSslSocket::setCiphers(QString) does.
// That overload isn't available on QSslConfiguration.
if (!config->sslCiphers().isEmpty()) {
QList<QSslCipher> cipherList;
foreach (const QString &cipherName,
config->sslCiphers().split(QLatin1String(":"),
QString::SkipEmptyParts)) {
QSslCipher cipher(cipherName);
if (!cipher.isNull())
cipherList << cipher;
}
if (!cipherList.isEmpty())
m_sslConfiguration.setCiphers(cipherList);
}

if (!config->sslCertificatesPath().isEmpty()) {
QList<QSslCertificate> caCerts = QSslCertificate::fromPath(
config->sslCertificatesPath(), QSsl::Pem, QRegExp::Wildcard);
Expand Down

0 comments on commit 0b8b6bb

Please sign in to comment.