From db756a792061523a0579248b767c64d002d8ff09 Mon Sep 17 00:00:00 2001 From: Raul Metsma Date: Fri, 11 Oct 2024 14:02:53 +0300 Subject: [PATCH] Don't allow to sign empty file (#623) IB-8195 Signed-off-by: Raul Metsma --- src/ASiContainer.cpp | 57 ++++++++++++++++---------------------------- src/ASiContainer.h | 14 +++++------ 2 files changed, 27 insertions(+), 44 deletions(-) diff --git a/src/ASiContainer.cpp b/src/ASiContainer.cpp index ba8628056..e45c6c52a 100644 --- a/src/ASiContainer.cpp +++ b/src/ASiContainer.cpp @@ -21,13 +21,10 @@ #include "DataFile_p.h" #include "Signature.h" -#include "util/DateTime.h" #include "util/File.h" #include "util/log.h" -#include "util/ZipSerialize.h" #include -#include #include #include #include @@ -48,29 +45,24 @@ class ASiContainer::Private map properties; }; -const string ASiContainer::MIMETYPE_ASIC_E = "application/vnd.etsi.asic-e+zip"; -const string ASiContainer::MIMETYPE_ASIC_S = "application/vnd.etsi.asic-s+zip"; -//https://signa.mitsoft.lt/static/signa-web/webResources/docs/ADOC_specification_approved20090907_EN.pdf -const string ASiContainer::MIMETYPE_ADOC = "application/vnd.lt.archyvai.adoc-2008"; - /** - * Initialize BDOC container. + * Initialize Container. */ -ASiContainer::ASiContainer(const string &mimetype) +ASiContainer::ASiContainer(string_view mimetype) : d(make_unique()) { d->mimetype = mimetype; } /** - * Loads ASi Container from a file. + * Loads Container from a file. * * @param path name of the container file. * @param mimetypeRequired flag indicating if the mimetype must be present and checked. * @param supported supported mimetypes. * @return returns zip serializer for the container. */ -unique_ptr ASiContainer::load(const string &path, bool mimetypeRequired, const set &supported) +unique_ptr ASiContainer::load(const string &path, bool mimetypeRequired, const set &supported) { DEBUG("ASiContainer::ASiContainer(path = '%s')", path.c_str()); auto z = make_unique(d->path = path, false); @@ -79,17 +71,17 @@ unique_ptr ASiContainer::load(const string &path, bool mimetypeReq if(list.empty()) THROW("Failed to parse container"); + // ETSI TS 102 918: mimetype has to be the first in the archive if(mimetypeRequired && list.front() != "mimetype") THROW("required mimetype not found"); - // ETSI TS 102 918: mimetype has to be the first in the archive if(list.front() == "mimetype") { d->mimetype = readMimetype(*z); - DEBUG("mimetype = '%s'", d->mimetype.c_str()); if(supported.find(d->mimetype) == supported.cend()) THROW("Incorrect mimetype '%s'", d->mimetype.c_str()); } + DEBUG("mimetype = '%s'", d->mimetype.c_str()); for(const string &file: list) d->properties[file] = z->properties(file); @@ -167,24 +159,20 @@ void ASiContainer::addDataFile(const string &path, const string &mediaType) { string fileName = File::fileName(path); addDataFileChecks(fileName, mediaType); - if(!File::fileExists(path)) - THROW("Document file '%s' does not exist.", path.c_str()); - - ZipSerialize::Properties prop { appInfo(), File::modifiedTime(path), File::fileSize(path) }; - bool useTempFile = prop.size > MAX_MEM_FILE; - zproperty(fileName, std::move(prop)); - unique_ptr is; - if(useTempFile) - { - is = make_unique(File::encodeName(path), ifstream::binary); - } - else + auto size = File::fileSize(path); + if(size == 0) + THROW("Document file '%s' does not exist or is empty.", path.c_str()); + + unique_ptr is = make_unique(File::encodeName(path), ifstream::binary); + if(!*is) + THROW("Failed to open file for reading: %s.", path.c_str()); + if(size <= MAX_MEM_FILE) { auto data = make_unique(); - if(ifstream file{File::encodeName(path), ifstream::binary}) - *data << file.rdbuf(); + *data << is->rdbuf(); is = std::move(data); } + d->properties[fileName] = { appInfo(), File::modifiedTime(path), size }; addDataFilePrivate(std::move(is), std::move(fileName), mediaType); } @@ -270,18 +258,13 @@ string ASiContainer::zpath() const return d->path; } -ZipSerialize::Properties ASiContainer::zproperty(const string &file) const +const ZipSerialize::Properties& ASiContainer::zproperty(const string &file) const { if(auto i = d->properties.find(file); i != d->properties.cend()) return i->second; return d->properties[file] = { appInfo(), time(nullptr), 0 }; } -void ASiContainer::zproperty(const string &file, ZipSerialize::Properties &&prop) -{ - d->properties[file] = std::move(prop); -} - /** * Reads and parses container mimetype. Checks that the mimetype is supported. * @@ -294,9 +277,9 @@ string ASiContainer::readMimetype(const ZipSerialize &z) DEBUG("ASiContainer::readMimetype()"); stringstream is; z.extract("mimetype", is); - string text; - is >> text; - if(!is) + string text = is.str(); + text.erase(text.find_last_not_of(" \n\r\f\t\v") + 1); + if(text.empty()) THROW("Failed to read mimetype."); // Contains UTF-16 BOM if(text.find("\xFF\xEF") == 0 || text.find("\xEF\xFF") == 0) diff --git a/src/ASiContainer.h b/src/ASiContainer.h index de6fb098a..56162326c 100644 --- a/src/ASiContainer.h +++ b/src/ASiContainer.h @@ -38,9 +38,10 @@ namespace digidoc class ASiContainer: public Container { public: - static const std::string MIMETYPE_ASIC_E; - static const std::string MIMETYPE_ASIC_S; - static const std::string MIMETYPE_ADOC; + static constexpr std::string_view MIMETYPE_ASIC_E = "application/vnd.etsi.asic-e+zip"; + static constexpr std::string_view MIMETYPE_ASIC_S = "application/vnd.etsi.asic-s+zip"; + //https://signa.mitsoft.lt/static/signa-web/webResources/docs/ADOC_specification_approved20090907_EN.pdf + static constexpr std::string_view MIMETYPE_ADOC = "application/vnd.lt.archyvai.adoc-2008"; ~ASiContainer() override; std::string mediaType() const override; @@ -55,18 +56,17 @@ namespace digidoc static std::string readMimetype(const ZipSerialize &z); protected: - ASiContainer(const std::string &mimetype); + ASiContainer(std::string_view mimetype); void addDataFilePrivate(std::unique_ptr is, std::string fileName, std::string mediaType); Signature* addSignature(std::unique_ptr &&signature); std::unique_ptr dataStream(const std::string &path, const ZipSerialize &z) const; - std::unique_ptr load(const std::string &path, bool requireMimetype, const std::set &supported); + std::unique_ptr load(const std::string &path, bool requireMimetype, const std::set &supported); void deleteSignature(Signature* s); void zpath(const std::string &file); std::string zpath() const; - ZipSerialize::Properties zproperty(const std::string &file) const; - void zproperty(const std::string &file, ZipSerialize::Properties &&prop); + const ZipSerialize::Properties &zproperty(const std::string &file) const; private: DISABLE_COPY(ASiContainer);