Skip to content

Commit

Permalink
Validate CAdES signature in SiVa service (open-eid#552)
Browse files Browse the repository at this point in the history
IB-6671

Signed-off-by: Raul Metsma <[email protected]>
  • Loading branch information
metsma authored and klemensn committed Nov 12, 2024
1 parent 46d801e commit 5658efc
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 26 deletions.
20 changes: 7 additions & 13 deletions src/ASiContainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,21 +300,15 @@ string ASiContainer::readMimetype(const ZipSerialize &z)
DEBUG("ASiContainer::readMimetype()");
stringstream is;
z.extract("mimetype", is);

array<unsigned char,3> bom{};
is.read((char*)bom.data(), bom.size());
// Contains UTF-16 BOM
if((bom[0] == 0xFF && bom[1] == 0xEF) ||
(bom[0] == 0xEF && bom[1] == 0xFF))
THROW("Mimetype file must be UTF-8 format.");
// does not contain UTF-8 BOM reset pos
if(bom[0] != 0xEF || bom[1] != 0xBB || bom[2] != 0xBF)
is.seekg(0, ios::beg);

string text;
is >> text;
if(is.fail())
if(!is)
THROW("Failed to read mimetype.");

// Contains UTF-16 BOM
if(text.find("\xFF\xEF") == 0 || text.find("\xEF\xFF") == 0)
THROW("Mimetype file must be UTF-8 format.");
// contains UTF-8 BOM, remove
if(text.find("\xEF\xBB\xBF") == 0)
text.erase(text.cbegin(), text.cbegin() + 3);
return text;
}
4 changes: 2 additions & 2 deletions src/ASiContainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ namespace digidoc
void removeSignature(unsigned int id) override;
std::vector<Signature*> signatures() const override;

static std::string readMimetype(const ZipSerialize &z);

protected:
ASiContainer(const std::string &mimetype);

Expand All @@ -72,8 +74,6 @@ namespace digidoc
ZipSerialize::Properties zproperty(const std::string &file) const;
void zproperty(const std::string &file, ZipSerialize::Properties &&prop);

static std::string readMimetype(const ZipSerialize &z);

private:
DISABLE_COPY(ASiContainer);

Expand Down
50 changes: 40 additions & 10 deletions src/SiVaContainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@

#include "SiVaContainer.h"

#include "ASiContainer.h"
#include "Conf.h"
#include "DataFile_p.h"
#include "Signature.h"
#include "crypto/Connect.h"
#include "crypto/Digest.h"
#include "util/File.h"
#include "util/log.h"
#include "util/ZipSerialize.h"
#include "xml/xml.hxx"
#include "xml/SecureDOMParser.h"

Expand Down Expand Up @@ -142,27 +144,57 @@ void SignatureSiVa::validate(const string &policy) const
}


SiVaContainer::SiVaContainer(const string &path, const string &ext, bool useHashCode)
SiVaContainer::SiVaContainer(const string &path, bool useHashCode)
: d(make_unique<Private>())
{
string ext = File::fileExtension(path);
DEBUG("SiVaContainer::SiVaContainer(%s, %s, %d)", path.c_str(), ext.c_str(), useHashCode);
unique_ptr<istream> ifs = make_unique<ifstream>(File::encodeName(d->path = path), ifstream::binary);
auto fileName = File::fileName(path);
istream *is = ifs.get();
static const array asic {"asice", "sce", "asics", "scs"};
if(ext == "ddoc")
{
d->mediaType = "application/x-ddoc";
d->ddoc = std::move(ifs);
ifs = parseDDoc(useHashCode);
is = ifs.get();
}
else
else if(ext == "pdf")
{
d->mediaType = "application/pdf";
d->dataFiles.push_back(new DataFilePrivate(std::move(ifs), fileName, "application/pdf"));
}
else if(find(asic.cbegin(), asic.cend(), ext) != asic.cend())
{
ZipSerialize z(path, false);
vector<string> list = z.list();
if(list.empty() || list.front() != "mimetype")
THROW("Missing mimetype");
if(d->mediaType = ASiContainer::readMimetype(z);
d->mediaType != ASiContainer::MIMETYPE_ASIC_E && d->mediaType != ASiContainer::MIMETYPE_ASIC_S)
THROW("Unknown file");
if(none_of(list.cbegin(), list.cend(), [](const string &file) { return file.find("p7s") != string::npos; }))
THROW("Unknown file");

static const string metaInf = "META-INF/";
for(const string &file: list)
{
if(file == "mimetype" || file.substr(0, metaInf.size()) == metaInf)
continue;
const auto directory = File::directory(file);
if(directory.empty() || directory == "/" || directory == "./")
{
auto data = make_unique<stringstream>();
z.extract(file, *data);
d->dataFiles.push_back(new DataFilePrivate(std::move(data), file, "application/octet-stream"));
}
}
}
else
THROW("Unknown file");

array<XMLByte, 48*100> buf{};
array<XMLByte, 4800> buf{};
string b64;
is->clear();
is->seekg(0);
Expand Down Expand Up @@ -314,15 +346,13 @@ vector<DataFile *> SiVaContainer::dataFiles() const

unique_ptr<Container> SiVaContainer::openInternal(const string &path)
{
static const array supported {"pdf", "ddoc"};
string ext = File::fileExtension(path);
if(find(supported.cbegin(), supported.cend(), ext) == supported.cend())
return {};
try {
return unique_ptr<Container>(new SiVaContainer(path, ext, true));
return unique_ptr<Container>(new SiVaContainer(path, true));
} catch(const Exception &e) {
if(e.msg().find("Bad digest for DataFile") == 0)
return unique_ptr<Container>(new SiVaContainer(path, ext, false));
return unique_ptr<Container>(new SiVaContainer(path, false));
if(e.msg() == "Unknown file")
return {};
throw;
}
}
Expand All @@ -337,7 +367,7 @@ unique_ptr<istream> SiVaContainer::parseDDoc(bool useHashCode)
DOMNodeList *nodeList = dom->getElementsByTagName(cpXMLCh(u"DataFile"));
for(XMLSize_t i = 0; i < nodeList->getLength(); ++i)
{
DOMElement *item = static_cast<DOMElement*>(nodeList->item(i));
auto *item = static_cast<DOMElement*>(nodeList->item(i));
if(!item)
continue;

Expand Down
2 changes: 1 addition & 1 deletion src/SiVaContainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ class SiVaContainer final: public Container
static std::unique_ptr<Container> openInternal(const std::string &path);

private:
SiVaContainer(const std::string &path, const std::string &ext, bool useHashCode);
SiVaContainer(const std::string &path, bool useHashCode);
DISABLE_COPY(SiVaContainer);

std::unique_ptr<std::istream> parseDDoc(bool useHashCode);
Expand Down

0 comments on commit 5658efc

Please sign in to comment.