OOXMLVerifier without CFileBinary

This commit is contained in:
Kulikova Svetlana
2021-05-11 17:17:35 +03:00
parent 8110e5de7c
commit 6d6e217e64
6 changed files with 148 additions and 92 deletions

View File

@ -15,7 +15,7 @@ public:
void SetImageValid (const std::wstring& file);
void SetImageInvalid(const std::wstring& file);
int Sign(const std::wstring& sFiletoWrite);
int Sign(unsigned char*& pFiletoWrite, unsigned long& dwLenFiletoWrite);
private:
COOXMLSigner_private* m_internal;

View File

@ -39,6 +39,7 @@ class Q_DECL_EXPORT COOXMLVerifier
{
public:
COOXMLVerifier(const std::wstring& sFolder);
COOXMLVerifier(unsigned char* data, unsigned long length);
~COOXMLVerifier();
int GetSignatureCount();

View File

@ -15,7 +15,7 @@ public:
virtual bool exists(const std::wstring& path) = 0;
virtual void remove(const std::wstring& path) = 0;
virtual void createDirectory(const std::wstring& path) = 0;
virtual void writeZipFolder (const std::wstring& path) = 0;
virtual void writeZipFolder(BYTE* data, DWORD& length) = 0;
virtual std::vector<std::wstring> getFiles(const std::wstring& path, bool bIsRecursion) = 0;
};
@ -60,7 +60,7 @@ public:
if (!NSDirectory::Exists(path))
NSDirectory::CreateDirectory(path);
}
virtual void writeZipFolder (const std::wstring& path)
virtual void writeZipFolder(BYTE* data, DWORD& length)
{
}
virtual std::vector<std::wstring> getFiles(const std::wstring& path, bool bIsRecursion)
@ -164,7 +164,7 @@ public:
virtual void createDirectory(const std::wstring& path)
{
}
virtual void writeZipFolder (const std::wstring& path)
virtual void writeZipFolder(BYTE* data, DWORD& length)
{
CData* oData = new CData();
oData->SkipLen();
@ -181,10 +181,8 @@ public:
Zlib* zipFile = Zlib_Create();
BYTE* oRes = Zlib_CompressFiles(zipFile, oData->GetBuffer());
NSFile::CFileBinary oFile;
oFile.CreateFileW(path);
oFile.WriteFile(oRes + 4, GetLength(oRes));
oFile.CloseFile();
data = oRes + 4;
length = GetLength(oRes);
}
virtual std::vector<std::wstring> getFiles(const std::wstring& path, bool bIsRecursion)
{

View File

@ -663,7 +663,7 @@ public:
return nSignNum;
}
int Sign(const std::wstring& sFiletoWrite)
int Sign(BYTE*& pFiletoWrite, DWORD& dwLenFiletoWrite)
{
Parse();
@ -702,7 +702,7 @@ public:
NSFile::CUtf8Converter::GetUtf8StringFromUnicode(builderResult.GetData().c_str(), builderResult.GetSize(), pData, nLen);
m_pZipFolder->write(m_sFolder + L"/_xmlsignatures/sig" + std::to_wstring(nSignNum + 1) + L".xml", pData, nLen);
m_pZipFolder->writeZipFolder(sFiletoWrite);
m_pZipFolder->writeZipFolder(pFiletoWrite, dwLenFiletoWrite);
return (sSignedXml.empty()) ? 1 : 0;
}
};
@ -737,7 +737,7 @@ void COOXMLSigner::SetImageInvalid(const std::wstring& file)
m_internal->SetImageInvalid(file);
}
int COOXMLSigner::Sign(const std::wstring& sFiletoWrite)
int COOXMLSigner::Sign(BYTE*& pFiletoWrite, DWORD& dwLenFiletoWrite)
{
return m_internal->Sign(sFiletoWrite);
return m_internal->Sign(pFiletoWrite, dwLenFiletoWrite);
}

View File

@ -1,5 +1,6 @@
#include "./XmlTransform.h"
#include "./../include/OOXMLVerifier.h"
#include "./../include/ZipFolder.h"
class COOXMLSignature_private
{
@ -12,6 +13,7 @@ public:
std::string m_sImageInvalidBase64;
std::wstring m_sFolder;
IZipFolder* m_pZipFolder;
std::wstring m_sFile;
std::string m_sDate;
@ -399,7 +401,7 @@ public:
sFile = sFile.substr(0, nPos);
sFile = m_sFolder + sFile;
if (!NSFile::CFileBinary::Exists(sFile))
if (!m_pZipFolder->exists(sFile))
return OOXML_SIGNATURE_INVALID;
XmlUtils::CXmlNode nodeMethod = node.ReadNode(L"DigestMethod");
@ -420,7 +422,11 @@ public:
if (!nodeTransform.IsValid())
{
// simple hash
sCalcValue = m_cert->GetHash(sFile, nAlg);
BYTE* pData = NULL;
DWORD dwLen = 0;
m_pZipFolder->read(sFile, pData, dwLen);
sCalcValue = m_cert->GetHash(pData, dwLen, nAlg);
sValue = U_TO_UTF8((node.ReadNodeText(L"DigestValue")));
MakeBase64_NOCRLF(sValue);
}
@ -431,10 +437,10 @@ public:
if (!oTransforms.GetValid())
return OOXML_SIGNATURE_NOTSUPPORTED;
std::string sXml;
NSFile::CFileBinary::ReadAllTextUtf8A(sFile, sXml);
sXml = oTransforms.Transform(sXml);
BYTE* pData = NULL;
DWORD dwLen = 0;
m_pZipFolder->read(sFile, pData, dwLen);
std::string sXml = oTransforms.Transform(std::string((char*)pData, dwLen));
sCalcValue = m_cert->GetHash(sXml, nAlg);
sValue = U_TO_UTF8((node.ReadNodeText(L"DigestValue")));
@ -560,6 +566,7 @@ class COOXMLVerifier_private
{
public:
std::wstring m_sFolder;
IZipFolder* m_pZipFolder;
std::vector<COOXMLSignature*> m_arSignatures;
std::vector<std::wstring> m_arSignaturesFiles;
@ -567,9 +574,10 @@ public:
COOXMLVerifier_private(const std::wstring& sFolder)
{
m_sFolder = sFolder;
m_pZipFolder = new CZipFolder(sFolder);
// check .sig file
std::vector<std::wstring> arFiles = NSDirectory::GetFiles(m_sFolder + L"/_xmlsignatures", false);
std::vector<std::wstring> arFiles = m_pZipFolder->getFiles(m_sFolder + L"/_xmlsignatures", false);
bool bIsFound = false;
for (std::vector<std::wstring>::iterator i = arFiles.begin(); i != arFiles.end(); i++)
{
@ -583,8 +591,12 @@ public:
if (!bIsFound)
return;
BYTE* pData = NULL;
DWORD dwLen = 0;
m_pZipFolder->read(m_sFolder + L"/[Content_Types].xml", pData, dwLen);
XmlUtils::CXmlNode oContentTypes;
if (!oContentTypes.FromXmlFile(m_sFolder + L"/[Content_Types].xml"))
if (!oContentTypes.FromXmlString(NSFile::CUtf8Converter::GetUnicodeStringFromUTF8(pData, dwLen)))
return;
XmlUtils::CXmlNodes oOverrides = oContentTypes.GetNodes(L"Override");
@ -599,8 +611,12 @@ public:
continue;
std::wstring sFile = m_sFolder + node.GetAttribute("PartName");
BYTE* pData = NULL;
DWORD dwLen = 0;
m_pZipFolder->read(sFile, pData, dwLen);
XmlUtils::CXmlNode nodeSig;
if (!nodeSig.FromXmlFile(sFile))
if (!nodeSig.FromXmlString(NSFile::CUtf8Converter::GetUnicodeStringFromUTF8(pData, dwLen)))
continue;
if (nodeSig.GetName() != L"Signature")
@ -610,6 +626,69 @@ public:
pSignature->m_internal->m_sFile = sFile;
pSignature->m_internal->m_node = nodeSig;
pSignature->m_internal->m_sFolder = m_sFolder;
pSignature->m_internal->m_pZipFolder = m_pZipFolder;
pSignature->Check();
m_arSignatures.push_back(pSignature);
m_arSignaturesFiles.push_back(sFile);
}
}
COOXMLVerifier_private(BYTE* data, DWORD length)
{
m_sFolder = L"";
m_pZipFolder = new CZipFolderMemory(data, length);
// check .sig file
std::vector<std::wstring> arFiles = m_pZipFolder->getFiles(m_sFolder + L"/_xmlsignatures", false);
bool bIsFound = false;
for (std::vector<std::wstring>::iterator i = arFiles.begin(); i != arFiles.end(); i++)
{
if (NSFile::GetFileExtention(*i) == L"sigs")
{
bIsFound = true;
break;
}
}
if (!bIsFound)
return;
BYTE* pData = NULL;
DWORD dwLen = 0;
m_pZipFolder->read(m_sFolder + L"/[Content_Types].xml", pData, dwLen);
XmlUtils::CXmlNode oContentTypes;
if (!oContentTypes.FromXmlString(NSFile::CUtf8Converter::GetUnicodeStringFromUTF8(pData, dwLen)))
return;
XmlUtils::CXmlNodes oOverrides = oContentTypes.GetNodes(L"Override");
int nCount = oOverrides.GetCount();
for (int i = 0; i < nCount; i++)
{
XmlUtils::CXmlNode node;
oOverrides.GetAt(i, node);
if (node.GetAttributeA("ContentType") != "application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml")
continue;
std::wstring sFile = m_sFolder + node.GetAttribute("PartName");
BYTE* pData = NULL;
DWORD dwLen = 0;
m_pZipFolder->read(sFile, pData, dwLen);
XmlUtils::CXmlNode nodeSig;
if (!nodeSig.FromXmlString(NSFile::CUtf8Converter::GetUnicodeStringFromUTF8(pData, dwLen)))
continue;
if (nodeSig.GetName() != L"Signature")
continue;
COOXMLSignature* pSignature = new COOXMLSignature();
pSignature->m_internal->m_sFile = sFile;
pSignature->m_internal->m_node = nodeSig;
pSignature->m_internal->m_sFolder = m_sFolder;
pSignature->m_internal->m_pZipFolder = m_pZipFolder;
pSignature->Check();
m_arSignatures.push_back(pSignature);
@ -654,13 +733,17 @@ public:
}
if (!sFile.empty())
NSFile::CFileBinary::Remove(sFile);
m_pZipFolder->remove(sFile);
if (!bIsRemoveAll && sFile.empty())
return;
BYTE* pData = NULL;
DWORD dwLen = 0;
m_pZipFolder->read(m_sFolder + L"/[Content_Types].xml", pData, dwLen);
XmlUtils::CXmlNode oContentTypes;
if (!oContentTypes.FromXmlFile(m_sFolder + L"/[Content_Types].xml"))
if (!oContentTypes.FromXmlString(NSFile::CUtf8Converter::GetUnicodeStringFromUTF8(pData, dwLen)))
return;
std::wstring sXml = L"<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">";
@ -696,14 +779,24 @@ public:
}
}
sXml += L"</Types>";
NSFile::CFileBinary::SaveToFile(m_sFolder + L"/[Content_Types].xml", sXml);
BYTE* pXmlData = NULL;
LONG nLen = 0;
NSFile::CUtf8Converter::GetUtf8StringFromUnicode(sXml.c_str(), sXml.length(), pXmlData, nLen);
m_pZipFolder->write(m_sFolder + L"/[Content_Types].xml", pXmlData, nLen);
if (bIsRemoveAll)
{
NSDirectory::DeleteDirectory(m_sFolder + L"/_xmlsignatures");
std::vector<std::wstring> arrDeleteFiles = m_pZipFolder->getFiles(m_sFolder + L"/_xmlsignatures", true);
for (const std::wstring& sPath : arrDeleteFiles)
m_pZipFolder->remove(sPath);
BYTE* pData = NULL;
DWORD dwLen = 0;
m_pZipFolder->read(m_sFolder + L"/_rels/.rels", pData, dwLen);
XmlUtils::CXmlNode oRels;
if (!oRels.FromXmlFile(m_sFolder + L"/_rels/.rels"))
if (!oRels.FromXmlString(NSFile::CUtf8Converter::GetUnicodeStringFromUTF8(pData, dwLen)))
return;
sXml = L"<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">";
@ -725,7 +818,11 @@ public:
}
}
sXml += L"</Relationships>";
NSFile::CFileBinary::SaveToFile(m_sFolder + L"/_rels/.rels", sXml);
BYTE* pXmlData = NULL;
LONG nLen = 0;
NSFile::CUtf8Converter::GetUtf8StringFromUnicode(sXml.c_str(), sXml.length(), pXmlData, nLen);
m_pZipFolder->write(m_sFolder + L"/_rels/.rels", pXmlData, nLen);
}
else
{
@ -736,8 +833,12 @@ public:
std::wstring sOriginRels = m_sFolder + L"/_xmlsignatures/_rels/origin.sigs.rels";
BYTE* pData = NULL;
DWORD dwLen = 0;
m_pZipFolder->read(sOriginRels, pData, dwLen);
XmlUtils::CXmlNode oRels;
if (!oRels.FromXmlFile(sOriginRels))
if (!oRels.FromXmlString(NSFile::CUtf8Converter::GetUnicodeStringFromUTF8(pData, dwLen)))
return;
sXml = L"<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">";
@ -760,7 +861,11 @@ public:
}
}
sXml += L"</Relationships>";
NSFile::CFileBinary::SaveToFile(sOriginRels, sXml);
BYTE* pXmlData = NULL;
LONG nLen = 0;
NSFile::CUtf8Converter::GetUtf8StringFromUnicode(sXml.c_str(), sXml.length(), pXmlData, nLen);
m_pZipFolder->write(sOriginRels, pXmlData, nLen);
}
}
};
@ -770,6 +875,11 @@ COOXMLVerifier::COOXMLVerifier(const std::wstring& sFolder)
m_internal = new COOXMLVerifier_private(sFolder);
}
COOXMLVerifier::COOXMLVerifier(BYTE* data, DWORD length)
{
m_internal = new COOXMLVerifier_private(data, length);
}
COOXMLVerifier::~COOXMLVerifier()
{
RELEASEOBJECT(m_internal);
@ -789,8 +899,16 @@ COOXMLSignature* COOXMLVerifier::GetSignature(const int& index)
void COOXMLVerifier::RemoveSignature(const std::string& sGuid)
{
BYTE* pData = NULL;
DWORD dwLen = 0;
std::wstring sFolder = m_internal->m_sFolder;
if (sFolder.empty())
m_internal->m_pZipFolder->writeZipFolder(pData, dwLen);
m_internal->RemoveSignature(sGuid);
RELEASEOBJECT(m_internal);
m_internal = new COOXMLVerifier_private(sFolder);
if (sFolder.empty())
m_internal = new COOXMLVerifier_private(pData, dwLen);
else
m_internal = new COOXMLVerifier_private(sFolder);
}

View File

@ -161,68 +161,7 @@ public:
return builder.GetData();
}
void CheckOriginSigs(const std::wstring& file)
{
int rId = 0;
std::string sReplace = "";
std::vector<COOXMLRelationship>::iterator i = rels.begin();
while (i != rels.end())
{
if (0 == i->target.find(L"_xmlsignatures/"))
{
sReplace = U_TO_UTF8(i->target);
break;
}
std::wstring rid = i->rid;
rid = rid.substr(3);
int nTemp = std::stoi(rid);
if (nTemp > rId)
rId = nTemp;
i++;
}
if (!sReplace.empty())
{
if (sReplace == "_xmlsignatures/origin.sigs")
return;
std::string sXmlA;
NSFile::CFileBinary::ReadAllTextUtf8A(file, sXmlA);
NSStringUtils::string_replaceA(sXmlA, sReplace, "_xmlsignatures/origin.sigs");
NSFile::CFileBinary::Remove(file);
NSFile::CFileBinary oFile;
oFile.CreateFileW(file);
oFile.WriteFile((BYTE*)sXmlA.c_str(), (DWORD)sXmlA.length());
oFile.CloseFile();
return;
}
std::string sXmlA;
NSFile::CFileBinary::ReadAllTextUtf8A(file, sXmlA);
std::string::size_type pos = sXmlA.rfind("</Relationships>");
if (pos == std::string::npos)
return;
rId++;
std::string sRet = sXmlA.substr(0, pos);
sRet += ("<Relationship Id=\"rId" + std::to_string(rId) + "\" \
Type=\"http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/origin\" Target=\"_xmlsignatures/origin.sigs\"/>\
</Relationships>");
NSFile::CFileBinary::Remove(file);
NSFile::CFileBinary oFile;
oFile.CreateFileW(file);
oFile.WriteFile((BYTE*)sRet.c_str(), (DWORD)sRet.length());
oFile.CloseFile();
}
void CheckOriginSigs(BYTE* pData, LONG& nSize)
void CheckOriginSigs(BYTE*& pData, LONG& nSize)
{
int rId = 0;
std::wstring sReplace = L"";