Skip to content

Commit

Permalink
Add option to modify TSA Pinning certificate
Browse files Browse the repository at this point in the history
IB-7392

Signed-off-by: Raul Metsma <raul@metsma.ee>
  • Loading branch information
metsma committed Oct 31, 2022
1 parent 59140e6 commit 8b745b1
Show file tree
Hide file tree
Showing 7 changed files with 588 additions and 434 deletions.
134 changes: 74 additions & 60 deletions client/Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,42 +118,26 @@ class DigidocConf final: public digidoc::XmlConfCurrent

std::string proxyHost() const final
{
switch(s.value(QStringLiteral("ProxyConfig")).toUInt())
{
case 0: return {};
case 1: return systemProxy().hostName().toStdString();
default: return s.value(QStringLiteral("ProxyHost"), QString::fromStdString(digidoc::XmlConfCurrent::proxyHost()) ).toString().toStdString();
}
return proxyConf(&QNetworkProxy::hostName,
QStringLiteral("ProxyHost"), &digidoc::XmlConfCurrent::proxyHost);
}

std::string proxyPort() const final
{
switch(s.value(QStringLiteral("ProxyConfig")).toUInt())
{
case 0: return {};
case 1: return QString::number(systemProxy().port()).toStdString();
default: return s.value(QStringLiteral("ProxyPort"), QString::fromStdString(digidoc::XmlConfCurrent::proxyPort()) ).toString().toStdString();
}
return proxyConf([](const QNetworkProxy &systemProxy) { return QString::number(systemProxy.port()); },
QStringLiteral("ProxyPort"), &digidoc::XmlConfCurrent::proxyPort);
}

std::string proxyUser() const final
{
switch(s.value(QStringLiteral("ProxyConfig")).toUInt())
{
case 0: return {};
case 1: return systemProxy().user().toStdString();
default: return s.value(QStringLiteral("ProxyUser"), QString::fromStdString(digidoc::XmlConfCurrent::proxyUser()) ).toString().toStdString();
}
return proxyConf(&QNetworkProxy::user,
QStringLiteral("ProxyUser"), &digidoc::XmlConfCurrent::proxyUser);
}

std::string proxyPass() const final
{
switch(s.value(QStringLiteral("ProxyConfig")).toUInt())
{
case 0: return {};
case 1: return systemProxy().password().toStdString();
default: return s.value(QStringLiteral("ProxyPass"), QString::fromStdString(digidoc::XmlConfCurrent::proxyPass())).toString().toStdString();
}
return proxyConf(&QNetworkProxy::password,
QStringLiteral("ProxyPass"), &digidoc::XmlConfCurrent::proxyPass);
}

#ifdef Q_OS_MAC
Expand All @@ -167,13 +151,13 @@ class DigidocConf final: public digidoc::XmlConfCurrent
{ return s.value(QStringLiteral("TSLOnlineDigest"), digidoc::XmlConfCurrent::TSLOnlineDigest()).toBool(); }

void setProxyHost( const std::string &host ) final
{ SettingsDialog::setValueEx(QStringLiteral("ProxyHost"), QString::fromStdString( host )); }
{ SettingsDialog::setValueEx(QStringLiteral("ProxyHost"), fromStdString(host)); }
void setProxyPort( const std::string &port ) final
{ SettingsDialog::setValueEx(QStringLiteral("ProxyPort"), QString::fromStdString( port )); }
{ SettingsDialog::setValueEx(QStringLiteral("ProxyPort"), fromStdString(port)); }
void setProxyUser( const std::string &user ) final
{ SettingsDialog::setValueEx(QStringLiteral("ProxyUser"), QString::fromStdString( user )); }
{ SettingsDialog::setValueEx(QStringLiteral("ProxyUser"), fromStdString(user)); }
void setProxyPass( const std::string &pass ) final
{ SettingsDialog::setValueEx(QStringLiteral("ProxyPass"), QString::fromStdString( pass )); }
{ SettingsDialog::setValueEx(QStringLiteral("ProxyPass"), fromStdString(pass)); }
void setProxyTunnelSSL( bool enable ) final
{ SettingsDialog::setValueEx(QStringLiteral("ProxyTunnelSSL"), enable, digidoc::XmlConfCurrent::proxyTunnelSSL()); }
void setPKCS12Cert( const std::string & /*cert*/) final {}
Expand All @@ -184,43 +168,42 @@ class DigidocConf final: public digidoc::XmlConfCurrent
{ SettingsDialog::setValueEx(QStringLiteral("TSLOnlineDigest"), enable, digidoc::XmlConfCurrent::TSLOnlineDigest()); }
#endif

std::vector<digidoc::X509Cert> TSCerts() const final
{
std::vector<digidoc::X509Cert> list = toCerts(QStringLiteral("CERT-BUNDLE"));
if(digidoc::X509Cert cert = toCert(fromBase64(s.value(QStringLiteral("TSA-CERT")))))
list.push_back(cert);
return list;
}

std::string TSUrl() const final
{
if(s.value(QStringLiteral("TSA-URL-CUSTOM"), s.contains(QStringLiteral("TSA-URL"))).toBool())
return valueUserScope(QStringLiteral("TSA-URL"), digidoc::XmlConfCurrent::TSUrl());
return valueSystemScope(QStringLiteral("TSA-URL"), digidoc::XmlConfCurrent::TSUrl());
}
void setTSUrl(const std::string &url) final
{ SettingsDialog::setValueEx(QStringLiteral("TSA-URL"), QString::fromStdString(url)); }
{ SettingsDialog::setValueEx(QStringLiteral("TSA-URL"), fromStdString(url)); }

std::string TSLUrl() const final { return valueSystemScope(QStringLiteral("TSL-URL"), digidoc::XmlConfCurrent::TSLUrl()); }
std::vector<digidoc::X509Cert> TSLCerts() const final
{
std::vector<digidoc::X509Cert> tslcerts;
for(const QJsonValue &val: obj.value(QStringLiteral("TSL-CERTS")).toArray())
{
QByteArray cert = QByteArray::fromBase64(val.toString().toLatin1());
tslcerts.emplace_back((const unsigned char*)cert.constData(), size_t(cert.size()));
}
std::vector<digidoc::X509Cert> tslcerts = toCerts(QStringLiteral("TSL-CERTS"));
return tslcerts.empty() ? digidoc::XmlConfCurrent::TSLCerts() : tslcerts;
}

digidoc::X509Cert verifyServiceCert() const final
{
QByteArray cert = QByteArray::fromBase64(obj.value(QStringLiteral("SIVA-CERT")).toString().toLatin1());
QByteArray cert = fromBase64(obj.value(QStringLiteral("SIVA-CERT")));
if(cert.isEmpty())
return digidoc::XmlConfCurrent::verifyServiceCert();
return digidoc::X509Cert((const unsigned char*)cert.constData(), size_t(cert.size()));
return toCert(cert);
}
std::vector<digidoc::X509Cert> verifyServiceCerts() const final
{
std::vector<digidoc::X509Cert> list;
list.push_back(verifyServiceCert());
for(const QJsonValue &cert: obj.value(QStringLiteral("CERT-BUNDLE")).toArray())
{
QByteArray der = QByteArray::fromBase64(cert.toString().toLatin1());
list.emplace_back((const unsigned char*)der.constData(), size_t(der.size()));
}
std::vector<digidoc::X509Cert> list = toCerts(QStringLiteral("CERT-BUNDLE"));
if(digidoc::X509Cert cert = verifyServiceCert())
list.push_back(cert);
return list;
}
std::string verifyServiceUri() const final
Expand All @@ -240,7 +223,7 @@ class DigidocConf final: public digidoc::XmlConfCurrent
if(issuer == i.key().toStdString())
return i.value().toString().toStdString();
}
return obj.value(QStringLiteral("OCSP-URL")).toString(QString::fromStdString(digidoc::XmlConfCurrent::ocsp(issuer))).toStdString();
return obj.value(QStringLiteral("OCSP-URL")).toString(fromStdString(digidoc::XmlConfCurrent::ocsp(issuer))).toStdString();
}

bool TSLAllowExpired() const final
Expand All @@ -267,36 +250,67 @@ class DigidocConf final: public digidoc::XmlConfCurrent
if(s.value(QStringLiteral("TSA-URL")) == obj.value(QStringLiteral("TSA-URL")))
s.remove(QStringLiteral("TSA-URL")); // Cleanup user conf if it is default url
QList<QSslCertificate> list;
for(const QJsonValue &cert: obj.value(QStringLiteral("CERT-BUNDLE")).toArray())
list << QSslCertificate(QByteArray::fromBase64(cert.toString().toLatin1()), QSsl::Der);
for(const auto &cert: obj.value(QStringLiteral("CERT-BUNDLE")).toArray())
list.append(QSslCertificate(fromBase64(cert), QSsl::Der));
QSslConfiguration ssl = QSslConfiguration::defaultConfiguration();
ssl.setCaCertificates(list);
QSslConfiguration::setDefaultConfiguration(ssl);
}
#endif

QNetworkProxy systemProxy() const
std::string valueSystemScope(const QString &key, const std::string &defaultValue) const
{
for(const QNetworkProxy &proxy: QNetworkProxyFactory::systemProxyForQuery())
return obj.value(key).toString(fromStdString(defaultValue)).toStdString();
}

std::string valueUserScope(const QString &key, const std::string &defaultValue) const
{
return s.value(key, obj.value(key).toString(fromStdString(defaultValue))).toString().toStdString();
}

template<typename System, typename Config>
std::string proxyConf(System &&system, const QString &key, Config &&config) const
{
switch(s.value(QStringLiteral("ProxyConfig")).toUInt())
{
if(proxy.type() == QNetworkProxy::HttpProxy)
return proxy;
case 0: return {};
case 1: return std::invoke(system, [] {
for(const QNetworkProxy &proxy: QNetworkProxyFactory::systemProxyForQuery())
{
if(proxy.type() == QNetworkProxy::HttpProxy)
return proxy;
}
return QNetworkProxy{};
}()).toStdString();
default: return s.value(key, fromStdString(std::invoke(config, this))).toString().toStdString();
}
return {};
}

std::string valueSystemScope(const QString &key, const std::string &defaultValue) const
template<class T>
QByteArray fromBase64(const T &data) const
{
return obj.value(key).toString(QString::fromStdString(defaultValue)).toStdString();
return QByteArray::fromBase64(data.toString().toLatin1());
}

std::string valueUserScope(const QString &key, const std::string &defaultValue) const
digidoc::X509Cert toCert(const QByteArray &der) const
{
return s.value(key, obj.value(key).toString(QString::fromStdString(defaultValue))).toString().toStdString();
return digidoc::X509Cert((const unsigned char*)der.constData(), size_t(der.size()));
}

std::vector<digidoc::X509Cert> toCerts(const QString &key) const
{
std::vector<digidoc::X509Cert> certs;
for(const auto &cert: obj.value(key).toArray())
{
QByteArray der = fromBase64(cert);
certs.emplace_back((const unsigned char*)der.constData(), size_t(der.size()));
}
return certs;
}

static constexpr auto fromStdString = &QString::fromStdString;
QSettings s;
bool debug = false;
bool debug = false;
public:
QJsonObject obj;
};
Expand Down Expand Up @@ -530,7 +544,7 @@ void Application::activate( QWidget *w )
#ifdef Q_OS_WIN
void Application::addTempFile(const QString &file)
{
d->tempFiles << file;
d->tempFiles.append(file);
}
#endif

Expand Down Expand Up @@ -623,7 +637,7 @@ QVariant Application::confValue( ConfParameter parameter, const QVariant &value
{
std::vector<unsigned char> v = cert;
if(!v.empty())
list << QSslCertificate(QByteArray::fromRawData((const char*)v.data(), int(v.size())), QSsl::Der);
list.append(QSslCertificate(QByteArray::fromRawData((const char*)v.data(), int(v.size())), QSsl::Der));
}
return QVariant::fromValue(list);
}
Expand Down Expand Up @@ -992,7 +1006,7 @@ void Application::parseArgs( const QString &msg )
#endif
{
QUrl url( param, QUrl::StrictMode );
params << (param != QLatin1String("-crypto") && !url.toLocalFile().isEmpty() ? url.toLocalFile() : param);
params.append(param != QLatin1String("-crypto") && !url.toLocalFile().isEmpty() ? url.toLocalFile() : param);
}
parseArgs( params );
}
Expand Down
Loading

0 comments on commit 8b745b1

Please sign in to comment.