From 7abf03556e141ce5b25af1713f3f89e46e02f027 Mon Sep 17 00:00:00 2001 From: Raul Metsma Date: Mon, 7 Sep 2026 13:29:28 +0300 Subject: [PATCH] Add separate LTA TSA URL IB-9095 Signed-off-by: Raul Metsma --- CMakeLists.txt | 2 +- client/Application.cpp | 30 ++++++++++ client/Application.h | 1 + client/Diagnostics.cpp | 1 + client/Settings.cpp | 4 +- client/Settings.h | 2 + client/dialogs/SettingsDialog.cpp | 32 +++++++++++ client/dialogs/SettingsDialog.h | 1 + client/dialogs/SettingsDialog.ui | 92 +++++++++++++++++++++++++++++++ client/translations/en.ts | 12 ++++ client/translations/et.ts | 12 ++++ debian/control | 2 +- 12 files changed, 188 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d5da89210..314ca433f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,7 +46,7 @@ set(CPACK_RPM_PACKAGE_RELEASE_DIST ON) include(CPack) include(GNUInstallDirs) -find_package(libdigidocpp 4.5.0 REQUIRED HINTS /Library) +find_package(libdigidocpp 4.6.0 REQUIRED HINTS /Library) message("-- Found libdigidocpp: ${libdigidocpp_DIR} (found version \"${libdigidocpp_VERSION}\")") find_package(LDAP REQUIRED) find_package(Qt6 6.2.0 REQUIRED COMPONENTS Core Widgets Network PrintSupport SvgWidgets LinguistTools) diff --git a/client/Application.cpp b/client/Application.cpp index 66b4107d5..e28c2aba9 100644 --- a/client/Application.cpp +++ b/client/Application.cpp @@ -166,6 +166,33 @@ class DigidocConf final: public digidoc::XmlConfCurrent return valueUserScope(Settings::TSA_URL_CUSTOM, Settings::TSA_URL, digidoc::XmlConfCurrent::TSUrl()); } + std::vector TSCertsArchive() const final + { + if(digidoc::X509Cert cert = toCert(fromBase64(Settings::TSA_CERT_ARCHIVE))) + { + std::vector list = toCerts(QLatin1String("CERT-BUNDLE")); + list.push_back(std::move(cert)); + list.emplace_back(); // Make sure that TSA cert pinning is enabled + return list; + } + return TSCerts(); + } + + std::string TSUrlArchive() const final + { + if(std::string url = Settings::TSA_URL_ARCHIVE; Settings::TSA_URL_CUSTOM && !url.empty()) + return url; + if(auto value = Application::confValue(Settings::TSA_URL_ARCHIVE.KEY); value.isString()) + { + if(std::string url = value.toString().toStdString(); !url.empty()) + return url; + } + if(std::string url = digidoc::XmlConfCurrent::TSUrlArchive(); + !url.empty() && url != digidoc::XmlConfCurrent::TSUrl()) + return url; + return TSUrl(); + } + std::string TSLUrl() const final { return valueSystemScope(QLatin1String("TSL-URL"), digidoc::XmlConfCurrent::TSLUrl()); } std::vector TSLCerts() const final @@ -216,6 +243,8 @@ class DigidocConf final: public digidoc::XmlConfCurrent { if(Settings::TSA_URL == Application::confValue(Settings::TSA_URL.KEY).toString()) Settings::TSA_URL.clear(); // Cleanup user conf if it is default url + if(Settings::TSA_URL_ARCHIVE == Application::confValue(Settings::TSA_URL_ARCHIVE.KEY).toString()) + Settings::TSA_URL_ARCHIVE.clear(); // Cleanup user conf if it is default url } #endif @@ -621,6 +650,7 @@ QVariant Application::confValue( ConfParameter parameter, const QVariant &value { case SiVaUrl: r = i->verifyServiceUri().c_str(); break; case TSAUrl: r = i->TSUrl().c_str(); break; + case TSAUrlArchive: r = i->TSUrlArchive().c_str(); break; case TSLUrl: r = i->TSLUrl().c_str(); break; case TSLCache: r = i->TSLCache().c_str(); break; case TSLCerts: diff --git a/client/Application.h b/client/Application.h index c458af40a..9e2b686e2 100644 --- a/client/Application.h +++ b/client/Application.h @@ -47,6 +47,7 @@ class Application final: public BaseApplication { SiVaUrl, TSAUrl, + TSAUrlArchive, TSLUrl, TSLCerts, TSLCache, diff --git a/client/Diagnostics.cpp b/client/Diagnostics.cpp index c2c8b9aac..0b523290c 100644 --- a/client/Diagnostics.cpp +++ b/client/Diagnostics.cpp @@ -52,6 +52,7 @@ void Diagnostics::generalInfo(QTextStream &s) << "
RPUUID: " << (Settings::MID_UUID_CUSTOM ? tr("is set manually") : tr("is set by default")) << "
TSL_URL: " << Application::confValue(Application::TSLUrl).toString() << "
TSA_URL: " << Application::confValue(Application::TSAUrl).toString() + << "
TSA_URL_ARCHIVE: " << Application::confValue(Application::TSAUrlArchive).toString() << "
SIVA_URL: " << Application::confValue(Application::SiVaUrl).toString() << "
CDOC2:" << "
" << Settings::CDOC2_DEFAULT.KEY << ": " << Settings::CDOC2_DEFAULT diff --git a/client/Settings.cpp b/client/Settings.cpp index f1b3b2c1c..865c04237 100644 --- a/client/Settings.cpp +++ b/client/Settings.cpp @@ -88,9 +88,11 @@ const Option Settings::SIVA_URL { QStringLiteral("SIVA-URL") }; const Option Settings::SIVA_URL_CUSTOM { QStringLiteral("SIVA-URL-CUSTOM"), [] { return Settings::SIVA_URL.isSet(); } }; const Option Settings::TSA_CERT { QStringLiteral("TSA-CERT") }; +const Option Settings::TSA_CERT_ARCHIVE { QStringLiteral("TSA-CERT-ARCHIVE") }; const Option Settings::TSA_URL { QStringLiteral("TSA-URL") }; +const Option Settings::TSA_URL_ARCHIVE { QStringLiteral("TSA-URL-ARCHIVE") }; const Option Settings::TSA_URL_CUSTOM - { QStringLiteral("TSA-URL-CUSTOM"), [] { return Settings::TSA_URL.isSet(); } }; + { QStringLiteral("TSA-URL-CUSTOM"), [] { return Settings::TSA_URL.isSet() || Settings::TSA_URL_ARCHIVE.isSet(); } }; const Option Settings::DEFAULT_LTA { QStringLiteral("DefaultLTA"), false }; const Option Settings::DEFAULT_DIR { QStringLiteral("DefaultDir") }; diff --git a/client/Settings.h b/client/Settings.h index c5365723a..de39c0e2b 100644 --- a/client/Settings.h +++ b/client/Settings.h @@ -109,7 +109,9 @@ struct Settings static const Option SIVA_URL; static const Option SIVA_URL_CUSTOM; static const Option TSA_CERT; + static const Option TSA_CERT_ARCHIVE; static const Option TSA_URL; + static const Option TSA_URL_ARCHIVE; static const Option TSA_URL_CUSTOM; static const Option DEFAULT_LTA; diff --git a/client/dialogs/SettingsDialog.cpp b/client/dialogs/SettingsDialog.cpp index 9ad9e6a4f..3d5dc9366 100644 --- a/client/dialogs/SettingsDialog.cpp +++ b/client/dialogs/SettingsDialog.cpp @@ -101,11 +101,21 @@ SettingsDialog::SettingsDialog(int page, QWidget *parent) ui->txtTimeStamp->setVisible(ui->rdTimeStampCustom->isChecked()); ui->txtTimeStamp->setPlaceholderText(Application::confValue(Settings::TSA_URL.KEY).toString()); ui->txtTimeStamp->setText(Settings::TSA_URL); + ui->txtTimeStampArchive->setReadOnly(Settings::TSA_URL_ARCHIVE.isLocked()); + ui->lblTimeStampArchive->setVisible(ui->rdTimeStampCustom->isChecked()); + ui->txtTimeStampArchive->setVisible(ui->rdTimeStampCustom->isChecked()); + ui->txtTimeStampArchive->setPlaceholderText(Application::confValue(Application::TSAUrlArchive).toString()); + ui->txtTimeStampArchive->setText(Settings::TSA_URL_ARCHIVE); ui->wgtTSACert->setDisabled(Settings::TSA_CERT.isLocked()); ui->wgtTSACert->setVisible(ui->rdTimeStampCustom->isChecked()); + ui->wgtTSACertArchive->setDisabled(Settings::TSA_CERT_ARCHIVE.isLocked()); + ui->wgtTSACertArchive->setVisible(ui->rdTimeStampCustom->isChecked()); connect(ui->rdTimeStampCustom, &QRadioButton::toggled, ui->txtTimeStamp, [this](bool checked) { ui->txtTimeStamp->setVisible(checked); + ui->lblTimeStampArchive->setVisible(checked); + ui->txtTimeStampArchive->setVisible(checked); ui->wgtTSACert->setVisible(checked); + ui->wgtTSACertArchive->setVisible(checked); Settings::TSA_URL_CUSTOM = checked; }); connect(ui->txtTimeStamp, &QLineEdit::textChanged, this, [this](const QString &url) { @@ -116,6 +126,14 @@ SettingsDialog::SettingsDialog(int page, QWidget *parent) updateTSACert(QSslCertificate()); } }); + connect(ui->txtTimeStampArchive, &QLineEdit::textChanged, this, [this](const QString &url) { + Settings::TSA_URL_ARCHIVE = url; + if(url.isEmpty()) + { + Settings::TSA_CERT_ARCHIVE.clear(); + updateTSACertArchive(QSslCertificate()); + } + }); connect(ui->helpTimeStamp, &QToolButton::clicked, this, []{ QDesktopServices::openUrl(tr("https://www.id.ee/en/article/for-organisations-that-sign-large-quantities-of-documents-using-digidoc4-client/")); }); @@ -128,6 +146,15 @@ SettingsDialog::SettingsDialog(int page, QWidget *parent) updateTSACert(cert); }); updateTSACert(QSslCertificate(QByteArray::fromBase64(Settings::TSA_CERT), QSsl::Der)); + connect(ui->btInstallTSACertArchive, &QPushButton::clicked, this, [this] { + QSslCertificate cert = selectCert(tr("Select archive Time-Stamping server certificate"), + tr("Archive Time-Stamping service SSL certificate")); + if(cert.isNull()) + return; + Settings::TSA_CERT_ARCHIVE = cert.toDer().toBase64(); + updateTSACertArchive(cert); + }); + updateTSACertArchive(QSslCertificate(QByteArray::fromBase64(Settings::TSA_CERT_ARCHIVE), QSsl::Der)); // pageServices - MID ui->rdMIDUUIDDefault->setDisabled(Settings::MID_UUID_CUSTOM.isLocked()); @@ -482,6 +509,11 @@ void SettingsDialog::updateSiVaCert(const QSslCertificate &c) updateCert(c, ui->btShowSiVaCert, ui->txtSiVaCert); } +void SettingsDialog::updateTSACertArchive(const QSslCertificate &c) +{ + updateCert(c, ui->btShowTSACertArchive, ui->txtTSACertArchive); +} + void SettingsDialog::updateTSACert(const QSslCertificate &c) { updateCert(c, ui->btShowTSACert, ui->txtTSACert); diff --git a/client/dialogs/SettingsDialog.h b/client/dialogs/SettingsDialog.h index beb558d15..b7820adb3 100644 --- a/client/dialogs/SettingsDialog.h +++ b/client/dialogs/SettingsDialog.h @@ -73,6 +73,7 @@ class SettingsDialog final: public QDialog void updateCDoc2Cert(const QSslCertificate &c); void updateSiVaCert(const QSslCertificate &c); void updateTSACert(const QSslCertificate &c); + void updateTSACertArchive(const QSslCertificate &c); void updateDiagnostics(); void useDefaultSettings(); diff --git a/client/dialogs/SettingsDialog.ui b/client/dialogs/SettingsDialog.ui index 2ba5e1862..ac89ea55f 100644 --- a/client/dialogs/SettingsDialog.ui +++ b/client/dialogs/SettingsDialog.ui @@ -693,6 +693,26 @@ max-height: 22px; + + + + Qt::TabFocus + + + Access to archive Time-Stamping service + + + txtTimeStampArchive + + + + + + + true + + + @@ -765,6 +785,78 @@ max-height: 22px; + + + + + 24 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::TabFocus + + + Archive Time-Stamping service SSL certificate + + + + + + + Qt::TabFocus + + + + + + + 16 + + + + + Add certificate + + + + + + + Show certificate + + + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + + diff --git a/client/translations/en.ts b/client/translations/en.ts index e0ee8edf5..eb971590f 100644 --- a/client/translations/en.ts +++ b/client/translations/en.ts @@ -2362,6 +2362,10 @@ ID-Card Checking updates has failed. Checking updates has failed. + + Select archive Time-Stamping server certificate + Select archive Time-Stamping server certificate + Restart DigiDoc4 Client to activate logging Restart DigiDoc4 Client to activate logging @@ -2531,6 +2535,10 @@ Additional licenses and components Use Long Term Archival (LTA) format when signing Use Long Term Archival (LTA) format when signing + + Access to archive Time-Stamping service + Access to archive Time-Stamping service + Add certificate Add certificate @@ -2539,6 +2547,10 @@ Additional licenses and components Show certificate Show certificate + + Archive Time-Stamping service SSL certificate + Archive Time-Stamping service SSL certificate + Use CDOC1 file format for encryption Use CDOC1 file format for encryption diff --git a/client/translations/et.ts b/client/translations/et.ts index b8052a14a..36fccd0ff 100644 --- a/client/translations/et.ts +++ b/client/translations/et.ts @@ -2362,6 +2362,10 @@ ID-kaardiga Checking updates has failed. Värskenduste kontrollimine on ebaõnnestunud. + + Select archive Time-Stamping server certificate + Vali arhiveerimise ajatempliteenuse serveri sertifikaat + Restart DigiDoc4 Client to activate logging Logimise aktiveerimiseks taaskäivita DigiDoc4 klient @@ -2531,6 +2535,10 @@ Täiendavad litsentsid ja komponendid Use Long Term Archival (LTA) format when signing Kasutan allkirjastamisel arhiveerimise ajatempli (LTA) vormingut + + Access to archive Time-Stamping service + Ligipääs arhiveerimise ajatempliteenusele + Add certificate Lisa sertifikaat @@ -2539,6 +2547,10 @@ Täiendavad litsentsid ja komponendid Show certificate Näita sertifikaati + + Archive Time-Stamping service SSL certificate + Arhiveerimise ajatempliteenuse SSL sertifikaat + Use CDOC1 file format for encryption Kasuta krüpteerimiseks CDOC1 failivormingut diff --git a/debian/control b/debian/control index df7cf7a56..78f88b9eb 100644 --- a/debian/control +++ b/debian/control @@ -6,7 +6,7 @@ Build-Depends: pkg-config, debhelper-compat (= 13), cmake, - libdigidocpp-dev (>=3.0), + libdigidocpp-dev (>=4.6.0), libldap2-dev, libpcsclite-dev, libssl-dev,