Browse Source

Added support for ssl client certificates (#3206)

* Added support for ssl client certificates

* Removed key and cert string params & moved client ssl code

Removed key and cert string params. Moved client ssl code to
MyNetworkAccessManager::createRequest

* Code Review Updates

Code Review Updates

* Code Review Updates

Code Review Updates

* Code Review Formatting Correction

Code Review Formatting Correction

* Code Review Formating Update

Code Review Formating Update

* Updating contact info

Updating contact info

* Added check for empty or missing ssl ctr file

Added check for empty or missing ssl ctr file

* Added check for building without ssl support
jasonparallel 8 years ago
parent
commit
399e6a09c6

+ 1 - 0
AUTHORS

@@ -38,3 +38,4 @@ Mehdi Abbad
 Lyes Amazouz
 Pascal Bach
 Mário Silva
+Jason Smith         <JasonParallel@gmail.com>

+ 9 - 0
include/wkhtmltox/loadsettings.hh

@@ -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;
 

+ 9 - 0
src/lib/loadsettings.hh

@@ -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;
 

+ 34 - 0
src/lib/multipageloader.cc

@@ -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
@@ -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);
 }
 

+ 3 - 0
src/lib/reflect.cc

@@ -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);

+ 3 - 0
src/shared/commonarguments.cc

@@ -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"));