Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 27 additions & 80 deletions src/ASiC_S.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

#include "ASiC_S.h"

#include "Conf.h"
#include "SignatureTST.h"
#include "SignatureXAdES_LTA.h"
#include "crypto/Signer.h"
Expand All @@ -33,18 +32,6 @@ using namespace digidoc;
using namespace digidoc::util;
using namespace std;

struct ASiC_S::Data {
std::string name, mime, data;

Digest digest(Digest digest = {}) const
{
digest.update((const unsigned char*)data.data(), data.size());
return digest;
}
};



/**
* Initialize ASiCS container.
*/
Expand All @@ -59,17 +46,20 @@ ASiC_S::ASiC_S(const string &path)
: ASiContainer(MIMETYPE_ASIC_S)
{
auto z = load(path, false, {mediaType()});
bool foundTimestamp = false;
bool foundManifest = false;
for(const string &file: z.list())
{
if(file == "mimetype")
continue;
if(file == "META-INF/timestamp.tst")
foundTimestamp = true;
if(file == "META-INF/ASiCArchiveManifest.xml")
{
if(!signatures().empty())
THROW("Can not add signature to ASiC-S container which already contains a signature.");
string tst = z.extract<stringstream>(file).str();
addSignature(make_unique<SignatureTST>(tst, this));
metadata.push_back({file, "application/vnd.etsi.timestamp-token", std::move(tst)});
addSignature(make_unique<SignatureTST>(true, z, this));
foundManifest = true;
}
else if(file == "META-INF/signatures.xml")
{
Expand All @@ -80,28 +70,6 @@ ASiC_S::ASiC_S(const string &path)
for(auto s = signatures->signature(); s; s++)
addSignature(make_unique<SignatureXAdES_LTA>(signatures, s, this));
}
else if(file == "META-INF/ASiCArchiveManifest.xml")
{
function<void(const string &, string_view)> add = [this, &add, &z](const string &file, string_view mime) {
auto xml = z.extract<stringstream>(file);
XMLDocument doc = XMLDocument::openStream(xml, {"ASiCManifest", ASIC_NS});
doc.validateSchema(util::File::path(Conf::instance()->xsdPath(), "en_31916201v010101.xsd"));

for(auto ref = doc/"DataObjectReference"; ref; ref++)
{
if(ref["Rootfile"] == "true")
add(util::File::fromUriPath(ref["URI"]), ref["MimeType"]);
}

auto ref = doc/"SigReference";
string uri = util::File::fromUriPath(ref["URI"]);
string tst = z.extract<stringstream>(uri).str();
addSignature(make_unique<SignatureTST>(file, ::move(doc), tst, this));
metadata.push_back({file, string(mime), xml.str()});
metadata.push_back({std::move(uri), string(ref["MimeType"]), std::move(tst)});
};
add(file, "text/xml");
}
else if(starts_with(file, "META-INF/"))
continue;
else if(const auto directory = File::directory(file);
Expand All @@ -112,6 +80,12 @@ ASiC_S::ASiC_S(const string &path)
else
addDataFile(dataStream(file, z), file, "application/octet-stream");
}
if(foundTimestamp && !foundManifest)
{
if(!signatures().empty())
THROW("Can not add signature to ASiC-S container which already contains a signature.");
addSignature(make_unique<SignatureTST>(false, z, this));
}

if(dataFiles().empty())
THROW("ASiC-S container does not contain any data objects.");
Expand Down Expand Up @@ -147,20 +121,20 @@ void ASiC_S::canSave()
THROW("ASiC-S container supports only saving TimeStampToken signatures.");
}

Digest ASiC_S::fileDigest(const string &file, string_view method) const
{
if(auto i = find_if(metadata.cbegin(), metadata.cend(), [&file](const auto &d) { return d.name == file; });
i != metadata.cend())
return i->digest(method);
THROW("File not found %s.", file.c_str());
}

unique_ptr<Container> ASiC_S::openInternal(const string &path, ContainerOpenCB * /*cb*/)
{
if (!isContainerSimpleFormat(path))
return {};
DEBUG("ASiC_S::openInternal(%s)", path.c_str());
return unique_ptr<Container>(new ASiC_S(path));
try
{
if(util::File::fileExtension(path, {"asice", "sce", "bdoc"}))
return {};
return unique_ptr<Container>(new ASiC_S(path));
}
catch(const Exception &)
{
// Ignore the exception: not ASiC/zip document
}
return {};
}

Signature* ASiC_S::prepareSignature(Signer * /*signer*/)
Expand All @@ -170,10 +144,11 @@ Signature* ASiC_S::prepareSignature(Signer * /*signer*/)

void ASiC_S::save(const ZipSerialize &s)
{
if(zproperty("META-INF/manifest.xml").size && !createManifest().save(s.addFile("META-INF/manifest.xml", zproperty("META-INF/manifest.xml")), true))
if(const auto &prop = zproperty("META-INF/manifest.xml");
prop.size && !createManifest().save(s.addFile("META-INF/manifest.xml", prop), true))
THROW("Failed to create manifest XML");
for(const auto &[name, mime, data]: metadata)
s.addFile(name, zproperty(name))(data);
for(Signature *sig: signatures())
static_cast<SignatureTST*>(sig)->save(s);
}

Signature *ASiC_S::sign(Signer *signer)
Expand All @@ -184,31 +159,3 @@ Signature *ASiC_S::sign(Signer *signer)
THROW("ASiC-S container supports only one TimeStampToken signature.");
return addSignature(make_unique<SignatureTST>(this, signer));
}

/**
* Detect ASiC format based on file extentions, mimetype or zip contents.<br/>
* Container format is simple (ASiC-S) or extended (ASiC-E).
*
* @param path Path of the container.
* @throws Exception
*/
bool ASiC_S::isContainerSimpleFormat(const string &path)
{
DEBUG("isContainerSimpleFormat(path = '%s')", path.c_str());
if(util::File::fileExtension(path, {"asice", "sce", "bdoc"}))
return false;
if(util::File::fileExtension(path, {"asics", "scs"}))
return true;
DEBUG("Check if ASiC/zip containter");
try
{
ZipSerialize z(path, false);
vector<string> list = z.list();
return list.front() == "mimetype" && readMimetype(z) == MIMETYPE_ASIC_S;
}
catch(const Exception &)
{
// Ignore the exception: not ASiC/zip document
}
return false;
}
9 changes: 1 addition & 8 deletions src/ASiC_S.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@

namespace digidoc
{
class Digest;

/**
* Implements the ASiC-S specification of the timestamped digital document container.
* Container contains a single datafile object and one time assertion file.
Expand All @@ -39,8 +37,6 @@ namespace digidoc
Signature* prepareSignature(Signer *signer) override;
Signature* sign(Signer* signer) override;

Digest fileDigest(const std::string &file, std::string_view method = {}) const;

static std::unique_ptr<Container> createInternal(const std::string &path);
static std::unique_ptr<Container> openInternal(const std::string &path, ContainerOpenCB *cb);

Expand All @@ -53,9 +49,6 @@ namespace digidoc
void canSave() final;
void save(const ZipSerialize &s) final;

static bool isContainerSimpleFormat(const std::string &path);

struct Data;
std::vector<Data> metadata;
friend class SignatureTST;
};
}
4 changes: 2 additions & 2 deletions src/ASiContainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@
#include "DataFile_p.h"
#include "Signature.h"
#include "XMLDocument.h"
#include "util/algorithm.h"
#include "util/File.h"
#include "util/log.h"

#include <algorithm>
#include <array>
#include <ctime>
#include <fstream>
Expand Down Expand Up @@ -93,7 +93,7 @@ ZipSerialize ASiContainer::load(const string &path, bool mimetypeRequired, const
if(list.front() == "mimetype")
{
d->mimetype = readMimetype(z);
if(supported.find(d->mimetype) == supported.cend())
if(!contains(supported, d->mimetype))
THROW("Incorrect mimetype '%s'", d->mimetype.c_str());
}
DEBUG("mimetype = '%s'", d->mimetype.c_str());
Expand Down
1 change: 1 addition & 0 deletions src/ASiContainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ namespace digidoc
//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";
static constexpr std::string_view MANIFEST_NS = "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0";
static constexpr std::string_view ASIC_NS = "http://uri.etsi.org/02918/v1.2.1#";

~ASiContainer() override;
std::string mediaType() const override;
Expand Down
Loading