Files
core/PdfReader/Src/SecurityHandler.cpp
Ilya.Kirillov eb965c1d6d Добавлен новый проект PdfReader для кроссплатформенного чтения Pdf.
git-svn-id: svn://fileserver/activex/AVS/Sources/TeamlabOffice/trunk/ServerComponents@62480 954022d7-b5bf-4e40-9824-e11837661b57
2016-05-21 00:01:53 +03:00

306 lines
7.7 KiB
C++
Raw Blame History

#include "StringExt.h"
#include "PDFDoc.h"
#include "Decrypt.h"
#include "GlobalParams.h"
#include "SecurityHandler.h"
namespace PdfReader
{
//-------------------------------------------------------------------------------------------------------------------------------
// SecurityHandler
//-------------------------------------------------------------------------------------------------------------------------------
SecurityHandler *SecurityHandler::Make(PDFDoc *pDocument, Object *pEncryptDict)
{
SecurityHandler *pSecurityHandler = NULL;
Object oFilter;
pEncryptDict->DictLookup("Filter", &oFilter);
if (oFilter.IsName("Standard"))
{
pSecurityHandler = new StandardSecurityHandler(pDocument, pEncryptDict);
}
else if (oFilter.IsName())
{
// TO DO: Error "Couldn't find the security handler"
pSecurityHandler = NULL;
}
else
{
// TO DO: Error "Missing or invalid 'Filter' entry in encryption dictionary"
pSecurityHandler = NULL;
}
oFilter.Free();
return pSecurityHandler;
}
SecurityHandler::SecurityHandler(PDFDoc *pDocument)
{
m_pDocument = pDocument;
}
SecurityHandler::~SecurityHandler()
{
}
bool SecurityHandler::CheckEncryption(StringExt *seOwnerPassword, StringExt *seUserPassword)
{
void *pAuthData = NULL;
if (seOwnerPassword || seUserPassword)
{
pAuthData = MakeAuthData(seOwnerPassword, seUserPassword);
}
else
{
pAuthData = NULL;
}
bool bResult = Authorize(pAuthData);
if (pAuthData)
{
FreeAuthData(pAuthData);
}
for (int nIndex = 0; !bResult && nIndex < 3; ++nIndex)
{
if (!(pAuthData = GetAuthData()))
{
break;
}
bResult = Authorize(pAuthData);
if (pAuthData)
{
FreeAuthData(pAuthData);
}
}
if (!bResult)
{
// TO DO: Error "Incorrect password"
}
return bResult;
}
//-------------------------------------------------------------------------------------------------------------------------------
// StandardSecurityHandler
//-------------------------------------------------------------------------------------------------------------------------------
class StandardAuthData
{
public:
StandardAuthData(StringExt *seOwnerPassword, StringExt *seUserPassword)
{
m_seOwnerPassword = seOwnerPassword;
m_seUserPassword = seUserPassword;
}
~StandardAuthData()
{
if (m_seOwnerPassword)
{
delete m_seOwnerPassword;
}
if (m_seUserPassword)
{
delete m_seUserPassword;
}
}
public:
StringExt *m_seOwnerPassword;
StringExt *m_seUserPassword;
};
StandardSecurityHandler::StandardSecurityHandler(PDFDoc *pDocument, Object *pEncryptDict) :
SecurityHandler(pDocument)
{
m_bValid = false;
m_seFileID = NULL;
m_seOwnerKey = NULL;
m_seUserKey = NULL;
Object oVersion, oRevision, oLength, oOwnerKey, oUserKey, oPermission;
pEncryptDict->DictLookup("V", &oVersion);
pEncryptDict->DictLookup("R", &oRevision);
pEncryptDict->DictLookup("Length", &oLength);
pEncryptDict->DictLookup("O", &oOwnerKey);
pEncryptDict->DictLookup("U", &oUserKey);
pEncryptDict->DictLookup("P", &oPermission);
Object oFileID;
m_pDocument->GetXRef()->GetTrailerDict()->DictLookup("ID", &oFileID);
if (oVersion.IsInt() && oRevision.IsInt() && oOwnerKey.IsString() && oOwnerKey.GetString()->GetLength() == 32 && oUserKey.IsString() && oUserKey.GetString()->GetLength() == 32 && oPermission.IsInt())
{
m_nEncryptVersion = oVersion.GetInt();
m_nEncryptRevision = oRevision.GetInt();
m_eCryptType = cryptRC4;
// <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Revision = 2, <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> 40-<2D><><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> PDF-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Length
if (m_nEncryptRevision == 2 || !oLength.IsInt())
{
m_nFileKeyLength = 5; // 5 <20><><EFBFBD><EFBFBD> = 40-<2D><><EFBFBD>
}
else
{
m_nFileKeyLength = oLength.GetInt() / 8;
}
m_bEncryptMetadata = true;
if (m_nEncryptVersion == 4 && m_nEncryptRevision == 4)
{
Object oCryptFilters, oStreamFilter, oStringFilter;
pEncryptDict->DictLookup("CF", &oCryptFilters);
pEncryptDict->DictLookup("StmF", &oStreamFilter);
pEncryptDict->DictLookup("StrF", &oStringFilter);
if (oCryptFilters.IsDict() && oStreamFilter.IsName() && oStringFilter.IsName() && !strcmp(oStreamFilter.GetName(), oStringFilter.GetName()))
{
Object oCryptCurFilter;
if (oCryptFilters.DictLookup(oStreamFilter.GetName(), &oCryptCurFilter)->IsDict())
{
Object oCFM;
oCryptCurFilter.DictLookup("CFM", &oCFM);
if (oCFM.IsName("V2"))
{
m_nEncryptVersion = 2;
m_nEncryptRevision = 3;
Object oCFLength;
if (oCryptCurFilter.DictLookup("Length", &oCFLength)->IsInt())
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> oCFLength / 8
m_nFileKeyLength = oCFLength.GetInt();
}
oCFLength.Free();
}
else if (oCFM.IsName("AESV2"))
{
m_nEncryptVersion = 2;
m_nEncryptRevision = 3;
m_eCryptType = cryptAES;
Object oCFLength;
if (oCryptCurFilter.DictLookup("Length", &oCFLength)->IsInt())
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> oCFLength / 8
m_nFileKeyLength = oCFLength.GetInt();
}
oCFLength.Free();
}
oCFM.Free();
}
oCryptCurFilter.Free();
}
oStringFilter.Free();
oStreamFilter.Free();
oCryptFilters.Free();
Object oEncryptMetadata;
if (pEncryptDict->DictLookup("EncryptMetadata", &oEncryptMetadata)->IsBool())
{
m_bEncryptMetadata = oEncryptMetadata.GetBool();
}
oEncryptMetadata.Free();
}
m_nPermissionFlags = oPermission.GetInt();
m_seOwnerKey = oOwnerKey.GetString()->Copy();
m_seUserKey = oUserKey.GetString()->Copy();
if (m_nEncryptVersion >= 1 && m_nEncryptVersion <= 2 && m_nEncryptRevision >= 2 && m_nEncryptRevision <= 3)
{
if (oFileID.IsArray())
{
Object oFileIDString;
if (oFileID.ArrayGet(0, &oFileIDString)->IsString())
{
m_seFileID = oFileIDString.GetString()->Copy();
}
else
{
m_seFileID = new StringExt();
}
oFileIDString.Free();
}
else
{
m_seFileID = new StringExt();
}
m_bValid = true;
}
else
{
// TO DO: Error "Unsupported version/revision of Standard security handler"
}
}
else
{
// TO DO: Error "Weird encryption info"
}
if (m_nFileKeyLength > 16)
{
m_nFileKeyLength = 16;
}
oFileID.Free();
oPermission.Free();
oUserKey.Free();
oOwnerKey.Free();
oLength.Free();
oRevision.Free();
oVersion.Free();
}
StandardSecurityHandler::~StandardSecurityHandler()
{
if (m_seFileID)
{
delete m_seFileID;
}
if (m_seOwnerKey)
{
delete m_seOwnerKey;
}
if (m_seUserKey)
{
delete m_seUserKey;
}
}
void *StandardSecurityHandler::MakeAuthData(StringExt *seOwnerPassword, StringExt *seUserPassword)
{
return new StandardAuthData(seOwnerPassword ? seOwnerPassword->Copy() : (StringExt *)NULL, seUserPassword ? seUserPassword->Copy() : (StringExt *)NULL);
}
void *StandardSecurityHandler::GetAuthData()
{
return NULL;
}
void StandardSecurityHandler::FreeAuthData(void *pAuthData)
{
if (pAuthData)
delete (StandardAuthData *)pAuthData;
}
bool StandardSecurityHandler::Authorize(void *pAuthData)
{
StringExt *seOwnerPassword, *seUserPassword;
if (!m_bValid)
{
return false;
}
if (pAuthData)
{
seOwnerPassword = ((StandardAuthData *)pAuthData)->m_seOwnerPassword;
seUserPassword = ((StandardAuthData *)pAuthData)->m_seUserPassword;
}
else
{
seOwnerPassword = NULL;
seUserPassword = NULL;
}
if (!Decrypt::MakeFileKey(m_nEncryptVersion, m_nEncryptRevision, m_nFileKeyLength, m_seOwnerKey, m_seUserKey, m_nPermissionFlags, m_seFileID, seOwnerPassword, seUserPassword, m_sFileKey, m_bEncryptMetadata, &m_bOwnerPasswordValid))
{
return false;
}
return true;
}
}