From 82729b4c075419c3f092cb1b4cbe352d3386c5d8 Mon Sep 17 00:00:00 2001 From: Raul Metsma Date: Fri, 8 Nov 2024 09:55:44 +0200 Subject: [PATCH] Keep existing filenames (#624) * Update version number and xmlsec to 1.3.6 IB-7927, Fixes #637, IB-8260 Signed-off-by: Raul Metsma * Keep existing filenames IB-8168 Signed-off-by: Raul Metsma --------- Signed-off-by: Raul Metsma --- src/ASiC_E.cpp | 61 ++++++++++++++++++++++----------------- src/ASiC_E.h | 13 +++++---- src/ASiC_S.cpp | 2 +- src/SignatureXAdES_B.cpp | 12 ++++---- src/SignatureXAdES_B.h | 4 +-- src/SignatureXAdES_LT.cpp | 6 ++-- src/SignatureXAdES_LT.h | 2 +- 7 files changed, 55 insertions(+), 45 deletions(-) diff --git a/src/ASiC_E.cpp b/src/ASiC_E.cpp index 5c69f5f03..18622b065 100644 --- a/src/ASiC_E.cpp +++ b/src/ASiC_E.cpp @@ -35,16 +35,19 @@ using namespace digidoc; using namespace digidoc::util; using namespace std; -const string_view ASiC_E::ASIC_TM_PROFILE = "time-mark"; -const string_view ASiC_E::ASIC_TS_PROFILE = "time-stamp"; -const string_view ASiC_E::ASIC_TSA_PROFILE = "time-stamp-archive"; -const string_view ASiC_E::ASIC_TMA_PROFILE = "time-mark-archive"; constexpr string_view MANIFEST_NS {"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"}; class ASiC_E::Private { public: + string unique_name() const + { + string file; + for(unsigned int i = 0; signatures.count(file = Log::format("META-INF/signatures%u.xml", i++)); ); + return file; + } vector metadata; + map signatures; }; /** @@ -57,7 +60,7 @@ ASiC_E::ASiC_E() } /** - * Opens BDOC container from a file + * Opens ASiC container from a file */ ASiC_E::ASiC_E(const string &path) : ASiContainer(MIMETYPE_ASIC_E) @@ -101,24 +104,28 @@ void ASiC_E::save(const string &path) s.addFile("mimetype", mimetype, zproperty("mimetype"), false); stringstream manifest; - createManifest(manifest); + if(!createManifest().save(manifest)) + THROW("Failed to create manifest XML"); s.addFile("META-INF/manifest.xml", manifest, zproperty("META-INF/manifest.xml")); for(const DataFile *file: dataFiles()) s.addFile(file->fileName(), *(static_cast(file)->m_is), zproperty(file->fileName())); std::set saved; - unsigned int i = 0; for(Signature *iter: signatures()) { - string file = Log::format("META-INF/signatures%u.xml", i++); - auto *signature = static_cast(iter); - if(!saved.insert(signature->signatures.get()).second) + auto *signatures = static_cast(iter)->signatures.get(); + if(!saved.insert(signatures).second) continue; + auto name = find_if(d->signatures.cbegin(), d->signatures.cend(), [signatures](const auto &k){ + return k.second == signatures; + }); + if(name == d->signatures.cend()) + THROW("Unkown signature object"); stringstream ofs; - if(!signature->signatures->save(ofs)) + if(!signatures->save(ofs)) THROW("Failed to create signature XML file."); - s.addFile(file, ofs, zproperty(file)); + s.addFile(name->first, ofs, zproperty(name->first)); } } @@ -142,12 +149,9 @@ void ASiC_E::addAdESSignature(istream &data) THROW("No documents in container, can not add signature."); if(mediaType() != MIMETYPE_ASIC_E) THROW("'%s' format is not supported", mediaType().c_str()); - try { - auto signatures = make_shared(data, this); - for(auto s = signatures->signature(); s; s++) - addSignature(make_unique(signatures, s, this)); + loadSignatures(data, d->unique_name()); } catch(const Exception &e) { @@ -164,14 +168,10 @@ unique_ptr ASiC_E::openInternal(const string &path) /** * Creates BDoc container manifest file and returns its path. * - * Note: If non-ascii characters are present in XML data, we depend on the LANG variable to be set properly - * (see iconv --list for the list of supported encoding values for libiconv). - * - * * @return returns created manifest file path. * @throws Exception exception is thrown if manifest file creation failed. */ -void ASiC_E::createManifest(ostream &os) +XMLDocument ASiC_E::createManifest() const { DEBUG("ASiC_E::createManifest()"); auto doc = XMLDocument::create("manifest", MANIFEST_NS, "manifest"); @@ -184,8 +184,15 @@ void ASiC_E::createManifest(ostream &os) add("/", mediaType()); for(const DataFile *file: dataFiles()) add(file->fileName(), file->mediaType()); - if(!doc.save(os)) - THROW("Failed to create manifest XML"); + return doc; +} + +void ASiC_E::loadSignatures(istream &data, const string &file) +{ + auto signatures = make_shared(data, mediaType()); + d->signatures.emplace(file, signatures.get()); + for(auto s = signatures->signature(); s; s++) + addSignature(make_unique(signatures, s, this)); } /** @@ -251,9 +258,7 @@ void ASiC_E::parseManifestAndLoadFiles(const ZipSerialize &z) try { auto data = z.extract(file); - auto signatures = make_shared(data, this); - for(auto s = signatures->signature(); s; s++) - addSignature(make_unique(signatures, s, this)); + loadSignatures(data, file); } catch(const Exception &e) { @@ -286,7 +291,9 @@ Signature* ASiC_E::prepareSignature(Signer *signer) THROW("No documents in container, can not sign container."); if(!signer) THROW("Null pointer in ASiC_E::sign"); - return addSignature(make_unique(newSignatureId(), this, signer)); + auto signatures = make_shared(); + d->signatures.emplace(d->unique_name(), signatures.get()); + return addSignature(make_unique(signatures, newSignatureId(), this, signer)); } Signature *ASiC_E::sign(Signer* signer) diff --git a/src/ASiC_E.h b/src/ASiC_E.h index 0a61ba87f..c7887d9fb 100644 --- a/src/ASiC_E.h +++ b/src/ASiC_E.h @@ -23,6 +23,8 @@ namespace digidoc { + struct XMLDocument; + /** * Implements the BDOC specification of the signed digital document container. * Container can contain several files and all these files can be signed using @@ -34,10 +36,10 @@ namespace digidoc class ASiC_E final : public ASiContainer { public: - static const std::string_view ASIC_TM_PROFILE; - static const std::string_view ASIC_TS_PROFILE; - static const std::string_view ASIC_TMA_PROFILE; - static const std::string_view ASIC_TSA_PROFILE; + static constexpr std::string_view ASIC_TM_PROFILE = "time-mark"; + static constexpr std::string_view ASIC_TS_PROFILE = "time-stamp"; + static constexpr std::string_view ASIC_TMA_PROFILE = "time-mark-archive"; + static constexpr std::string_view ASIC_TSA_PROFILE = "time-stamp-archive"; ~ASiC_E() final; void save(const std::string &path = {}) final; @@ -54,7 +56,8 @@ namespace digidoc ASiC_E(); ASiC_E(const std::string &path); DISABLE_COPY(ASiC_E); - void createManifest(std::ostream &os); + XMLDocument createManifest() const; + void loadSignatures(std::istream &data, const std::string &file); void parseManifestAndLoadFiles(const ZipSerialize &z); class Private; diff --git a/src/ASiC_S.cpp b/src/ASiC_S.cpp index 78fa9b51e..6cd83fc4a 100644 --- a/src/ASiC_S.cpp +++ b/src/ASiC_S.cpp @@ -61,7 +61,7 @@ ASiC_S::ASiC_S(const string &path): ASiContainer(MIMETYPE_ASIC_S) if(!signatures().empty()) THROW("Can not add signature to ASiC-S container which already contains a signature."); auto data = z.extract(file); - auto signatures = make_shared(data, this); + auto signatures = make_shared(data, mediaType()); for(auto s = signatures->signature(); s; s++) addSignature(make_unique(signatures, s, this)); } diff --git a/src/SignatureXAdES_B.cpp b/src/SignatureXAdES_B.cpp index aca9988c2..24d396b60 100644 --- a/src/SignatureXAdES_B.cpp +++ b/src/SignatureXAdES_B.cpp @@ -190,7 +190,7 @@ int initXmlSecCallback() return is; }, [](void *ctx, char *buf, int len) -> int { - auto *is = static_cast(ctx); + auto *is = static_cast(ctx); is->read(buf, len); return int(is->gcount()); }, @@ -207,7 +207,7 @@ Signatures::Signatures() addNS(XADES_NS, "xades"); } -Signatures::Signatures(istream &data, ASiContainer *container) +Signatures::Signatures(istream &data, string_view mediaType) : XMLDocument(openStream(data)) { /* http://www.etsi.org/deliver/etsi_ts/102900_102999/102918/01.03.01_60/ts_102918v010301p.pdf @@ -219,7 +219,7 @@ Signatures::Signatures(istream &data, ASiContainer *container) * Case container is ADoc 1.0 then handle document-signatures root element */ try { - if(container->mediaType() == ASiC_E::MIMETYPE_ADOC && name() == "document-signatures" && ns() == OPENDOCUMENT_NS) + if(mediaType == ASiC_E::MIMETYPE_ADOC && name() == "document-signatures" && ns() == OPENDOCUMENT_NS) validateSchema(File::path(Conf::instance()->xsdPath(), "OpenDocument_dsig.xsd")); else validateSchema(File::path(Conf::instance()->xsdPath(), "en_31916201v010101.xsd")); @@ -234,8 +234,8 @@ Signatures::Signatures(istream &data, ASiContainer *container) /** * Creates an empty BDOC-BES signature with mandatory XML nodes. */ -SignatureXAdES_B::SignatureXAdES_B(unsigned int id, ASiContainer *container, Signer *signer) - : signatures(make_shared()) +SignatureXAdES_B::SignatureXAdES_B(const shared_ptr &signatures, unsigned int id, ASiContainer *container, Signer *signer) + : signatures(signatures) , bdoc(container) { X509Cert c = signer->cert(); @@ -295,7 +295,7 @@ SignatureXAdES_B::SignatureXAdES_B(unsigned int id, ASiContainer *container, Sig * @param bdoc BDOC container * @throws SignatureException */ -SignatureXAdES_B::SignatureXAdES_B(const std::shared_ptr &signatures, XMLNode s, ASiContainer *container) +SignatureXAdES_B::SignatureXAdES_B(const shared_ptr &signatures, XMLNode s, ASiContainer *container) : signatures(signatures) , signature(s) , bdoc(container) diff --git a/src/SignatureXAdES_B.h b/src/SignatureXAdES_B.h index ee84bea9e..67605d1a0 100644 --- a/src/SignatureXAdES_B.h +++ b/src/SignatureXAdES_B.h @@ -43,7 +43,7 @@ namespace digidoc { public: explicit Signatures(); - Signatures(std::istream &data, ASiContainer *container); + Signatures(std::istream &data, std::string_view mediaType); constexpr XMLNode signature() const noexcept { @@ -55,7 +55,7 @@ namespace digidoc { public: - SignatureXAdES_B(unsigned int id, ASiContainer *bdoc, Signer *signer); + SignatureXAdES_B(const std::shared_ptr &signatures, unsigned int id, ASiContainer *bdoc, Signer *signer); SignatureXAdES_B(const std::shared_ptr &signatures, XMLNode s, ASiContainer *container); ~SignatureXAdES_B(); diff --git a/src/SignatureXAdES_LT.cpp b/src/SignatureXAdES_LT.cpp index e4ad59603..a69940d67 100644 --- a/src/SignatureXAdES_LT.cpp +++ b/src/SignatureXAdES_LT.cpp @@ -35,11 +35,11 @@ using namespace digidoc; using namespace std; -SignatureXAdES_LT::SignatureXAdES_LT(unsigned int id, ASiContainer *bdoc, Signer *signer) -: SignatureXAdES_T(id, bdoc, signer) +SignatureXAdES_LT::SignatureXAdES_LT(const shared_ptr &signatures, unsigned int id, ASiContainer *bdoc, Signer *signer) +: SignatureXAdES_T(signatures, id, bdoc, signer) {} -SignatureXAdES_LT::SignatureXAdES_LT(const std::shared_ptr &signatures, XMLNode s, ASiContainer *container) +SignatureXAdES_LT::SignatureXAdES_LT(const shared_ptr &signatures, XMLNode s, ASiContainer *container) : SignatureXAdES_T(signatures, s, container) { try { diff --git a/src/SignatureXAdES_LT.h b/src/SignatureXAdES_LT.h index 1cab1a7c3..47b345061 100644 --- a/src/SignatureXAdES_LT.h +++ b/src/SignatureXAdES_LT.h @@ -29,7 +29,7 @@ class OCSP; class SignatureXAdES_LT: public SignatureXAdES_T { public: - SignatureXAdES_LT(unsigned int id, ASiContainer *bdoc, Signer *signer); + SignatureXAdES_LT(const std::shared_ptr &signatures, unsigned int id, ASiContainer *bdoc, Signer *signer); SignatureXAdES_LT(const std::shared_ptr &signatures, XMLNode s, ASiContainer *container); std::string trustedSigningTime() const override;