Skip to content
This repository has been archived by the owner on Jan 2, 2023. It is now read-only.

Added support for ssl client certificates #3206

Merged
merged 9 commits into from Jan 5, 2017
1 change: 1 addition & 0 deletions AUTHORS
Expand Up @@ -38,3 +38,4 @@ Mehdi Abbad
Lyes Amazouz
Pascal Bach
Mário Silva
Jason Smith <JasonParallel@gmail.com>
9 changes: 9 additions & 0 deletions include/wkhtmltox/loadsettings.hh
Expand Up @@ -67,6 +67,15 @@ struct DLL_PUBLIC LoadPage {
//! Password used for http auth login
QString password;

//! Path to the ssl client cert private key in OpenSSL PEM format
QString clientSslKeyPath;

//! Password to ssl client cert private key
QString clientSslKeyPassword;

//! Path to the ssl client cert public key in OpenSSL PEM format, optionally followed by intermediate ca and trusted certs
QString clientSslCrtPath;

//! How many milliseconds should we wait for a Javascript redirect
int jsdelay;

Expand Down
9 changes: 9 additions & 0 deletions src/lib/loadsettings.hh
Expand Up @@ -70,6 +70,15 @@ struct DLL_PUBLIC LoadPage {
//! Password used for http auth login
QString password;

//! Path to the ssl client cert private key in OpenSSL PEM format
QString clientSslKeyPath;

//! Password to ssl client cert private key
QString clientSslKeyPassword;

//! Path to the ssl client cert public key in OpenSSL PEM format, optionally followed by intermediate ca and trusted certs
QString clientSslCrtPath;

//! How many milliseconds should we wait for a Javascript redirect
int jsdelay;

Expand Down
34 changes: 34 additions & 0 deletions src/lib/multipageloader.cc
Expand Up @@ -26,6 +26,13 @@
#include <QNetworkDiskCache>
#include <QTimer>
#include <QUuid>
#include <QList>
#include <QByteArray>
#if (QT_VERSION >= 0x050000 && !defined QT_NO_SSL) || !defined QT_NO_OPENSSL
#include <QSslCertificate>
#include <QSslKey>
#include <QSslConfiguration>
#endif
#if QT_VERSION >= 0x050000
#include <QUrlQuery>
#endif
Expand Down Expand Up @@ -104,6 +111,33 @@ QNetworkReply * MyNetworkAccessManager::createRequest(Operation op, const QNetwo
foreach (const HT & j, settings.customHeaders)
r3.setRawHeader(j.first.toLatin1(), j.second.toLatin1());
}

#if (QT_VERSION >= 0x050000 && !defined QT_NO_SSL) || !defined QT_NO_OPENSSL
if(!settings.clientSslKeyPath.isEmpty() && !settings.clientSslKeyPassword.isEmpty()
&& !settings.clientSslCrtPath.isEmpty()){
bool success = true;
QSslConfiguration sslConfig = QSslConfiguration::defaultConfiguration();

QFile keyFile(settings.clientSslKeyPath);
if(keyFile.open(QFile::ReadOnly)){
QSslKey key(&keyFile, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, settings.clientSslKeyPassword.toUtf8());
sslConfig.setPrivateKey(key);
keyFile.close();

QList<QSslCertificate> chainCerts =
QSslCertificate::fromPath(settings.clientSslCrtPath.toLatin1(), QSsl::Pem, QRegExp::FixedString);
QList<QSslCertificate> cas = sslConfig.caCertificates();
cas.append(chainCerts);
if(!chainCerts.isEmpty()){
sslConfig.setLocalCertificate(chainCerts.first());
sslConfig.setCaCertificates(cas);

r3.setSslConfiguration(sslConfig);
}
}
}
#endif

return QNetworkAccessManager::createRequest(op, r3, outgoingData);
}

Expand Down
3 changes: 3 additions & 0 deletions src/lib/reflect.cc
Expand Up @@ -57,6 +57,9 @@ ReflectImpl<LoadGlobal>::ReflectImpl(LoadGlobal & c) {
ReflectImpl<LoadPage>::ReflectImpl(LoadPage & c) {
WKHTMLTOPDF_REFLECT(username);
WKHTMLTOPDF_REFLECT(password);
WKHTMLTOPDF_REFLECT(clientSslKeyPath);
WKHTMLTOPDF_REFLECT(clientSslKeyPassword);
WKHTMLTOPDF_REFLECT(clientSslCrtPath);
WKHTMLTOPDF_REFLECT(jsdelay);
WKHTMLTOPDF_REFLECT(windowStatus);
WKHTMLTOPDF_REFLECT(zoomFactor);
Expand Down
3 changes: 3 additions & 0 deletions src/shared/commonarguments.cc
Expand Up @@ -206,6 +206,9 @@ void CommandLineParserBase::addPageLoadArgs(LoadPage & s) {
addarg("bypass-proxy-for", 0, "Bypass proxy for host (repeatable)", new StringListSetter(s.bypassProxyForHosts, "value"));
addarg("username",0,"HTTP Authentication username", new QStrSetter(s.username, "username"));
addarg("password",0,"HTTP Authentication password", new QStrSetter(s.password, "password"));
addarg("ssl-key-path",0,"Path to ssl client cert private key in OpenSSL PEM format", new QStrSetter(s.clientSslKeyPath, "path"));
addarg("ssl-key-password",0,"Password to ssl client cert private key", new QStrSetter(s.clientSslKeyPassword, "password"));
addarg("ssl-crt-path",0,"Path to the ssl client cert public key in OpenSSL PEM format, optionally followed by intermediate ca and trusted certs", new QStrSetter(s.clientSslCrtPath, "path"));
addarg("load-error-handling", 0, "Specify how to handle pages that fail to load: abort, ignore or skip", new LoadErrorHandlingSetting(s.loadErrorHandling, "handler"));
addarg("load-media-error-handling", 0, "Specify how to handle media files that fail to load: abort, ignore or skip", new LoadErrorHandlingSetting(s.mediaLoadErrorHandling, "handler"));
addarg("custom-header",0,"Set an additional HTTP header (repeatable)", new MapSetter<>(s.customHeaders, "name", "value"));
Expand Down