Skip to content

Commit

Permalink
Don't allow to sign empty file (open-eid#623)
Browse files Browse the repository at this point in the history
IB-8195

Signed-off-by: Raul Metsma <[email protected]>
  • Loading branch information
metsma authored Oct 11, 2024
1 parent 1c99e5d commit db756a7
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 44 deletions.
57 changes: 20 additions & 37 deletions src/ASiContainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <algorithm>
#include <array>
#include <ctime>
#include <fstream>
#include <map>
Expand All @@ -48,29 +45,24 @@ class ASiContainer::Private
map<string, ZipSerialize::Properties> 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<Private>())
{
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<ZipSerialize> ASiContainer::load(const string &path, bool mimetypeRequired, const set<string> &supported)
unique_ptr<ZipSerialize> ASiContainer::load(const string &path, bool mimetypeRequired, const set<string_view> &supported)
{
DEBUG("ASiContainer::ASiContainer(path = '%s')", path.c_str());
auto z = make_unique<ZipSerialize>(d->path = path, false);
Expand All @@ -79,17 +71,17 @@ unique_ptr<ZipSerialize> 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);
Expand Down Expand Up @@ -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<istream> is;
if(useTempFile)
{
is = make_unique<ifstream>(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<istream> is = make_unique<ifstream>(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<stringstream>();
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);
}

Expand Down Expand Up @@ -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.
*
Expand All @@ -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)
Expand Down
14 changes: 7 additions & 7 deletions src/ASiContainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<std::istream> is, std::string fileName, std::string mediaType);
Signature* addSignature(std::unique_ptr<Signature> &&signature);
std::unique_ptr<std::iostream> dataStream(const std::string &path, const ZipSerialize &z) const;
std::unique_ptr<ZipSerialize> load(const std::string &path, bool requireMimetype, const std::set<std::string> &supported);
std::unique_ptr<ZipSerialize> load(const std::string &path, bool requireMimetype, const std::set<std::string_view> &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);
Expand Down

0 comments on commit db756a7

Please sign in to comment.