From 2e74debbca36e8e7b146e29e5fc459835c9aae18 Mon Sep 17 00:00:00 2001 From: Raul Metsma Date: Wed, 12 Aug 2026 22:34:58 +0300 Subject: [PATCH] Preserve cause-less signature validation errors IB-9065 Signed-off-by: Raul Metsma --- src/Signature.cpp | 10 ++++++-- src/SignatureXAdES_LT.cpp | 4 ++- src/SignatureXAdES_LTA.cpp | 4 ++- src/SignatureXAdES_T.cpp | 4 ++- test/libdigidocpp_boost.cpp | 49 +++++++++++++++++++++++++++++++++++++ 5 files changed, 66 insertions(+), 5 deletions(-) diff --git a/src/Signature.cpp b/src/Signature.cpp index 3ce59b670..7ff2ec8cf 100644 --- a/src/Signature.cpp +++ b/src/Signature.cpp @@ -349,7 +349,12 @@ std::string Signature::Validator::diagnostics() const void Signature::Validator::parseException(const Exception &e) { - for(const Exception &child: e.causes()) + if(const Exception::Causes causes = e.causes(); causes.empty()) + { + d->diagnostics += e.msg() + "\n"; + d->result = std::max(d->result, Invalid); + } + else for(const Exception &child: causes) { d->diagnostics += child.msg() + "\n"; switch(child.code()) @@ -372,7 +377,8 @@ void Signature::Validator::parseException(const Exception &e) default: d->result = std::max(d->result, Invalid); } - parseException(child); + if(!child.causes().empty()) + parseException(child); } } diff --git a/src/SignatureXAdES_LT.cpp b/src/SignatureXAdES_LT.cpp index 7d38e4c1d..bf5b6f530 100644 --- a/src/SignatureXAdES_LT.cpp +++ b/src/SignatureXAdES_LT.cpp @@ -106,7 +106,9 @@ void SignatureXAdES_LT::validate(const string &policy) const try { SignatureXAdES_T::validate(policy); } catch(const Exception &e) { - for(const Exception &ex: e.causes()) + if(const Exception::Causes causes = e.causes(); causes.empty()) + exception.addCause(e); + else for(const Exception &ex: causes) exception.addCause(ex); } diff --git a/src/SignatureXAdES_LTA.cpp b/src/SignatureXAdES_LTA.cpp index 33d341a8b..f7d3553b7 100644 --- a/src/SignatureXAdES_LTA.cpp +++ b/src/SignatureXAdES_LTA.cpp @@ -123,7 +123,9 @@ void SignatureXAdES_LTA::validate(const string &policy) const try { SignatureXAdES_LT::validate(policy); } catch(const Exception &e) { - for(const Exception &ex: e.causes()) + if(const Exception::Causes causes = e.causes(); causes.empty()) + exception.addCause(e); + else for(const Exception &ex: causes) exception.addCause(ex); } diff --git a/src/SignatureXAdES_T.cpp b/src/SignatureXAdES_T.cpp index 614f80a4a..90ce72ff7 100644 --- a/src/SignatureXAdES_T.cpp +++ b/src/SignatureXAdES_T.cpp @@ -95,7 +95,9 @@ void SignatureXAdES_T::validate(const std::string &policy) const } catch(const Exception &e) { if(profile().find(ASiC_E::ASIC_TS_PROFILE) == string::npos) throw; - for(const Exception &ex: e.causes()) + if(const Exception::Causes causes = e.causes(); causes.empty()) + exception.addCause(e); + else for(const Exception &ex: causes) exception.addCause(ex); } diff --git a/test/libdigidocpp_boost.cpp b/test/libdigidocpp_boost.cpp index 9b0d9674a..1afcd4c8f 100644 --- a/test/libdigidocpp_boost.cpp +++ b/test/libdigidocpp_boost.cpp @@ -64,6 +64,55 @@ const string ASiCS::EXT = "asics"; BOOST_GLOBAL_FIXTURE(TestFixture); +namespace +{ +class ThrowingSignature final: public Signature +{ +public: + explicit ThrowingSignature(Exception exception) + : exception(std::move(exception)) + {} + + string id() const override { return {}; } + string claimedSigningTime() const override { return {}; } + string trustedSigningTime() const override { return {}; } + X509Cert signingCertificate() const override { return X509Cert(); } + string signatureMethod() const override { return {}; } + void validate() const override { throw exception; } + vector dataToSign() const override { return {}; } + void setSignatureValue(const vector &) override {} + string profile() const override { return {}; } + +private: + Exception exception; +}; +} + +BOOST_AUTO_TEST_SUITE(SignatureValidatorSuite) +BOOST_AUTO_TEST_CASE(causeLessExceptionIsInvalid) +{ + ThrowingSignature signature(Exception(EXCEPTION_PARAMS("Validation failed without causes"))); + Signature::Validator validator(&signature); + + BOOST_CHECK_EQUAL(validator.status(), Signature::Validator::Invalid); + BOOST_CHECK_EQUAL(validator.diagnostics(), "Validation failed without causes\n"); + BOOST_CHECK(validator.warnings().empty()); +} + +BOOST_AUTO_TEST_CASE(nestedWarningRemainsWarning) +{ + Exception warning(EXCEPTION_PARAMS("Signature digest weak")); + warning.setCode(Exception::SignatureDigestWeak); + ThrowingSignature signature(Exception(EXCEPTION_PARAMS("Signature validation"), warning)); + Signature::Validator validator(&signature); + + BOOST_CHECK_EQUAL(validator.status(), Signature::Validator::Warning); + BOOST_CHECK_EQUAL(validator.diagnostics(), "Signature digest weak\n"); + BOOST_REQUIRE_EQUAL(validator.warnings().size(), 1U); + BOOST_CHECK_EQUAL(validator.warnings().front(), Exception::SignatureDigestWeak); +} +BOOST_AUTO_TEST_SUITE_END() + BOOST_AUTO_TEST_SUITE(LogSuite) BOOST_AUTO_TEST_CASE(logEntryIsWrittenImmediately) {