Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate CAdES signature in SiVa service #552

Merged
merged 1 commit into from
Nov 9, 2023
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
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ jobs:
steps:
- name: Install Deps
run: |
dnf install -y \
dnf install -y --setopt=install_weak_deps=False \
git gcc-c++ cmake rpm-build xml-security-c-devel zlib-devel vim-common doxygen boost-test swig python3-devel java-1.8.0-openjdk-devel \
https://www.codesynthesis.com/download/xsd/4.0/linux-gnu/x86_64/xsd-4.0.0-1.x86_64.rpm
- name: Checkout
Expand All @@ -105,7 +105,7 @@ jobs:
container: ${{ matrix.container }}
strategy:
matrix:
container: ['ubuntu:20.04', 'ubuntu:22.04', 'ubuntu:23.04']
container: ['ubuntu:20.04', 'ubuntu:22.04', 'ubuntu:23.04', 'ubuntu:23.10']
env:
DEBIAN_FRONTEND: noninteractive
DEBFULLNAME: github-actions
Expand Down
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
Loading