Files
core/PdfReader/Src/SecurityHandler.cpp
Ilya.Kirillov 65d72ae4ec Убраны лишние файлы. Все файлы сконвертированы в UTF8.
git-svn-id: svn://fileserver/activex/AVS/Sources/TeamlabOffice/trunk/ServerComponents@62550 954022d7-b5bf-4e40-9824-e11837661b57
2016-05-21 00:02:55 +03:00

306 lines
7.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
// В случае Revision = 2, ключ должен быть 40-бит - некоторые PDF-генераторы неправильно пишут значение Length
if (m_nEncryptRevision == 2 || !oLength.IsInt())
{
m_nFileKeyLength = 5; // 5 байт = 40-бит
}
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())
{
// Согласно спецификации, должно быть 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())
{
// Согласно спецификации, должно быть 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;
}
}