dbhub: Use certificate manager to get client cert for authentication

When trying to fetch a database don't load a hardcoded client
certificate but grab one from the certificate manager in the preferences
dialog.

Also add support for password protected private keys.

Note: Since this is all testing code on the front-end side, we just use
the first certificate in case multiple certificates are configured.
This commit is contained in:
Martin Kleusberg
2016-11-06 14:50:27 +01:00
parent 982e4c4d34
commit eeeec5f2fc
3 changed files with 36 additions and 14 deletions

View File

@@ -2145,7 +2145,8 @@ void MainWindow::on_actionOpen_Remote_triggered()
QString url = QInputDialog::getText(this, qApp->applicationName(), tr("Please enter the URL of the database file to open."));
if(!url.isEmpty())
{
m_remoteDb.fetchDatabase(url);
QStringList certs = Settings::getSettingsValue("remote", "client_certificates").toStringList();
m_remoteDb.fetchDatabase(url, (certs.size() ? certs.at(0) : ""));
}
}

View File

@@ -5,6 +5,7 @@
#include <QFile>
#include <QSslKey>
#include <QProgressDialog>
#include <QInputDialog>
#include "RemoteDatabase.h"
#include "version.h"
@@ -28,16 +29,6 @@ RemoteDatabase::RemoteDatabase() :
caCerts += QSslCertificate::fromPath(":/certs/" + caCertName);
m_sslConfiguration.setCaCertificates(caCerts);
// Load client cert and private key
QFile fileClientCert("client.cert.pem");
fileClientCert.open(QFile::ReadOnly);
QSslCertificate clientCert(&fileClientCert);
fileClientCert.seek(0);
QSslKey clientKey(&fileClientCert, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
fileClientCert.close();
m_sslConfiguration.setLocalCertificate(clientCert);
m_sslConfiguration.setPrivateKey(clientKey);
// Load settings and set up some more stuff while doing so
reloadSettings();
@@ -70,7 +61,7 @@ void RemoteDatabase::reloadSettings()
// TODO Add support for proxies here
}
void RemoteDatabase::fetchDatabase(const QString& url)
void RemoteDatabase::fetchDatabase(const QString& url, const QString& clientCert)
{
// Check if network is accessible. If not, abort right here
if(m_manager->networkAccessible() == QNetworkAccessManager::NotAccessible)
@@ -79,15 +70,45 @@ void RemoteDatabase::fetchDatabase(const QString& url)
return;
}
// Check if client cert exists
bool https = QUrl(url).scheme().compare("https", Qt::CaseInsensitive) == 0;
const QSslCertificate& cert = m_clientCertFiles[clientCert];
if(https && cert.isNull())
{
QMessageBox::warning(0, qApp->applicationName(), tr("Error: Invalid client certificate speicified."));
return;
}
// Build network request
QNetworkRequest request;
request.setUrl(url);
request.setRawHeader("User-Agent", QString("%1 %2").arg(qApp->organizationName()).arg(APP_VERSION).toUtf8());
// Set SSL configuration when trying to access a file via the HTTPS protocol
bool https = QUrl(url).scheme().compare("https", Qt::CaseInsensitive) == 0;
if(https)
{
// Load private key for the client certificate
QFile fileClientCert(clientCert);
fileClientCert.open(QFile::ReadOnly);
QSslKey clientKey(&fileClientCert, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
while(clientKey.isNull())
{
// If the private key couldn't be read, we assume it's password protected. So ask the user for the correct password and try reading it
// again. If the user cancels the password dialog, abort the whole process.
QString password = QInputDialog::getText(0, qApp->applicationName(), tr("Please enter the passphrase for this client certificate in order to authenticate."));
if(password.isEmpty())
return;
clientKey = QSslKey(&fileClientCert, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, password.toUtf8());
}
fileClientCert.close();
// Set client certificate (from the cache) and private key (just loaded)
m_sslConfiguration.setLocalCertificate(cert);
m_sslConfiguration.setPrivateKey(clientKey);
// Apply SSL configuration
request.setSslConfiguration(m_sslConfiguration);
}
// Fetch database and save pending reply. Note that we're only supporting one active download here at the moment.
m_currentReply = m_manager->get(request);

View File

@@ -23,7 +23,7 @@ public:
const QList<QSslCertificate>& caCertificates() const;
const QMap<QString, QSslCertificate>& clientCertificates() const { return m_clientCertFiles; }
void fetchDatabase(const QString& url);
void fetchDatabase(const QString& url, const QString& clientCert);
signals:
void openFile(QString path);