Skip to content

Commit 72c5eb8

Browse files
authored
Validate CAdES signature in SiVa service (#552)
IB-6671 Signed-off-by: Raul Metsma <[email protected]>
1 parent 348bb0e commit 72c5eb8

File tree

4 files changed

+50
-26
lines changed

4 files changed

+50
-26
lines changed

src/ASiContainer.cpp

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -300,21 +300,15 @@ string ASiContainer::readMimetype(const ZipSerialize &z)
300300
DEBUG("ASiContainer::readMimetype()");
301301
stringstream is;
302302
z.extract("mimetype", is);
303-
304-
array<unsigned char,3> bom{};
305-
is.read((char*)bom.data(), bom.size());
306-
// Contains UTF-16 BOM
307-
if((bom[0] == 0xFF && bom[1] == 0xEF) ||
308-
(bom[0] == 0xEF && bom[1] == 0xFF))
309-
THROW("Mimetype file must be UTF-8 format.");
310-
// does not contain UTF-8 BOM reset pos
311-
if(bom[0] != 0xEF || bom[1] != 0xBB || bom[2] != 0xBF)
312-
is.seekg(0, ios::beg);
313-
314303
string text;
315304
is >> text;
316-
if(is.fail())
305+
if(!is)
317306
THROW("Failed to read mimetype.");
318-
307+
// Contains UTF-16 BOM
308+
if(text.find("\xFF\xEF") == 0 || text.find("\xEF\xFF") == 0)
309+
THROW("Mimetype file must be UTF-8 format.");
310+
// contains UTF-8 BOM, remove
311+
if(text.find("\xEF\xBB\xBF") == 0)
312+
text.erase(text.cbegin(), text.cbegin() + 3);
319313
return text;
320314
}

src/ASiContainer.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ namespace digidoc
5858
void removeSignature(unsigned int id) override;
5959
std::vector<Signature*> signatures() const override;
6060

61+
static std::string readMimetype(const ZipSerialize &z);
62+
6163
protected:
6264
ASiContainer(const std::string &mimetype);
6365

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

75-
static std::string readMimetype(const ZipSerialize &z);
76-
7777
private:
7878
DISABLE_COPY(ASiContainer);
7979

src/SiVaContainer.cpp

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,15 @@
2424

2525
#include "SiVaContainer.h"
2626

27+
#include "ASiContainer.h"
2728
#include "Conf.h"
2829
#include "DataFile_p.h"
2930
#include "Signature.h"
3031
#include "crypto/Connect.h"
3132
#include "crypto/Digest.h"
3233
#include "util/File.h"
3334
#include "util/log.h"
35+
#include "util/ZipSerialize.h"
3436
#include "xml/xml.hxx"
3537
#include "xml/SecureDOMParser.h"
3638

@@ -142,27 +144,57 @@ void SignatureSiVa::validate(const string &policy) const
142144
}
143145

144146

145-
SiVaContainer::SiVaContainer(const string &path, const string &ext, bool useHashCode)
147+
SiVaContainer::SiVaContainer(const string &path, bool useHashCode)
146148
: d(make_unique<Private>())
147149
{
150+
string ext = File::fileExtension(path);
148151
DEBUG("SiVaContainer::SiVaContainer(%s, %s, %d)", path.c_str(), ext.c_str(), useHashCode);
149152
unique_ptr<istream> ifs = make_unique<ifstream>(File::encodeName(d->path = path), ifstream::binary);
150153
auto fileName = File::fileName(path);
151154
istream *is = ifs.get();
155+
static const array asic {"asice", "sce", "asics", "scs"};
152156
if(ext == "ddoc")
153157
{
154158
d->mediaType = "application/x-ddoc";
155159
d->ddoc = std::move(ifs);
156160
ifs = parseDDoc(useHashCode);
157161
is = ifs.get();
158162
}
159-
else
163+
else if(ext == "pdf")
160164
{
161165
d->mediaType = "application/pdf";
162166
d->dataFiles.push_back(new DataFilePrivate(std::move(ifs), fileName, "application/pdf"));
163167
}
168+
else if(find(asic.cbegin(), asic.cend(), ext) != asic.cend())
169+
{
170+
ZipSerialize z(path, false);
171+
vector<string> list = z.list();
172+
if(list.empty() || list.front() != "mimetype")
173+
THROW("Missing mimetype");
174+
if(d->mediaType = ASiContainer::readMimetype(z);
175+
d->mediaType != ASiContainer::MIMETYPE_ASIC_E && d->mediaType != ASiContainer::MIMETYPE_ASIC_S)
176+
THROW("Unknown file");
177+
if(none_of(list.cbegin(), list.cend(), [](const string &file) { return file.find("p7s") != string::npos; }))
178+
THROW("Unknown file");
179+
180+
static const string metaInf = "META-INF/";
181+
for(const string &file: list)
182+
{
183+
if(file == "mimetype" || file.substr(0, metaInf.size()) == metaInf)
184+
continue;
185+
const auto directory = File::directory(file);
186+
if(directory.empty() || directory == "/" || directory == "./")
187+
{
188+
auto data = make_unique<stringstream>();
189+
z.extract(file, *data);
190+
d->dataFiles.push_back(new DataFilePrivate(std::move(data), file, "application/octet-stream"));
191+
}
192+
}
193+
}
194+
else
195+
THROW("Unknown file");
164196

165-
array<XMLByte, 48*100> buf{};
197+
array<XMLByte, 4800> buf{};
166198
string b64;
167199
is->clear();
168200
is->seekg(0);
@@ -314,15 +346,13 @@ vector<DataFile *> SiVaContainer::dataFiles() const
314346

315347
unique_ptr<Container> SiVaContainer::openInternal(const string &path)
316348
{
317-
static const array supported {"pdf", "ddoc"};
318-
string ext = File::fileExtension(path);
319-
if(find(supported.cbegin(), supported.cend(), ext) == supported.cend())
320-
return {};
321349
try {
322-
return unique_ptr<Container>(new SiVaContainer(path, ext, true));
350+
return unique_ptr<Container>(new SiVaContainer(path, true));
323351
} catch(const Exception &e) {
324352
if(e.msg().find("Bad digest for DataFile") == 0)
325-
return unique_ptr<Container>(new SiVaContainer(path, ext, false));
353+
return unique_ptr<Container>(new SiVaContainer(path, false));
354+
if(e.msg() == "Unknown file")
355+
return {};
326356
throw;
327357
}
328358
}
@@ -337,7 +367,7 @@ unique_ptr<istream> SiVaContainer::parseDDoc(bool useHashCode)
337367
DOMNodeList *nodeList = dom->getElementsByTagName(cpXMLCh(u"DataFile"));
338368
for(XMLSize_t i = 0; i < nodeList->getLength(); ++i)
339369
{
340-
DOMElement *item = static_cast<DOMElement*>(nodeList->item(i));
370+
auto *item = static_cast<DOMElement*>(nodeList->item(i));
341371
if(!item)
342372
continue;
343373

src/SiVaContainer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ class SiVaContainer final: public Container
102102
static std::unique_ptr<Container> openInternal(const std::string &path);
103103

104104
private:
105-
SiVaContainer(const std::string &path, const std::string &ext, bool useHashCode);
105+
SiVaContainer(const std::string &path, bool useHashCode);
106106
DISABLE_COPY(SiVaContainer);
107107

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

0 commit comments

Comments
 (0)