📄 cpgpdiskheaders.cpp
字号:
// Class CPGPdiskMainHeader member functions
CPGPdiskMainHeader::CPGPdiskMainHeader(const CPGPdiskContext *pContext) :
CPGPdiskHeader(pContext), mIsOldHeaderAvailable(FALSE), mOldHeader(NULL)
{
}
CPGPdiskMainHeader::~CPGPdiskMainHeader()
{
if (IsOldHeaderAvailable())
{
delete mOldHeader;
mOldHeader = NULL;
}
}
void
CPGPdiskMainHeader::Create(
PGPUInt64 headerBlocks,
PGPUInt64 dataBlocks,
PGPdiskEncryptionAlgorithm algorithm,
const Crypto::PassphraseSalt& salt,
const char * defaultRoot)
{
CommonCreate(headerBlocks, dataBlocks, algorithm, salt, defaultRoot);
}
void
CPGPdiskMainHeader::ConvertOldVersion()
{
if (MajorVersion() >= OnDiskMainHeader::kPreSubKeyMajorVersion)
return;
// Store old header for retrieval by re-encrypters.
if (IsOldHeaderAvailable())
{
delete mOldHeader;
mOldHeader = NULL;
}
mOldHeader = new PGPdiskOldFormat::MainHeader;
mIsOldHeaderAvailable = TRUE;
pgpCopyMemory(mHeaderBytes.Get(), mOldHeader,
sizeof(PGPdiskOldFormat::MainHeader));
// Fill in new header structure.
Crypto::PassphraseSalt salt;
pgpClearMemory(&salt.bytes, sizeof(salt.bytes));
pgpCopyMemory(mOldHeader->salt.bytes, salt.bytes,
sizeof(mOldHeader->salt.bytes));
CString root;
root.Format("%c:\\", UString::NumberToLetter(mOldHeader->drive));
CommonCreate(mOldHeader->numHeaderBlocks, mOldHeader->numDataBlocks,
mOldHeader->algorithm, salt, root);
NextHeaderOffset() = mOldHeader->headerInfo.nextHeaderOffset;
}
void
CPGPdiskMainHeader::CanonicalizeHeader()
{
CPGPdiskHeader::CanonicalizeHeader();
if (!IsMainType())
THROW_PGPERROR(kPGPClientError_CorruptDiskHeader);
OnDiskMainHeader *pHeader = GetAsMainHeader();
if (MajorVersion() < OnDiskMainHeader::kCompatMajorVersion)
THROW_PGPERROR(kPGPClientError_DiskTooOld);
if (MajorVersion() < OnDiskMainHeader::kMajorVersion)
ConvertOldVersion();
if (MajorVersion() > OnDiskMainHeader::kMajorVersion)
THROW_PGPERROR(kPGPClientError_DiskTooNew);
if (NumDataBlocks() > NumFileBlocks())
THROW_PGPERROR(kPGPClientError_CorruptDiskHeader);
if (NumHeaderBlocks() + NumDataBlocks() > NumFileBlocks())
THROW_PGPERROR(kPGPClientError_CorruptDiskHeader);
}
void
CPGPdiskMainHeader::CommonCreate(
PGPUInt64 headerBlocks,
PGPUInt64 dataBlocks,
PGPdiskEncryptionAlgorithm algorithm,
const Crypto::PassphraseSalt& salt,
const char *defaultRoot)
{
pgpAssertStrValid(defaultRoot);
// Allocate header.
mHeaderBytes.Resize(sizeof(OnDiskMainHeader));
mHeaderBytes.Wipe();
// Initialize fields.
HeaderMagic() = OnDiskHeaderInfo::kHeaderMagic;
HeaderType() = OnDiskHeaderInfo::kMainType;
HeaderSize() = sizeof(OnDiskMainHeader);
MajorVersion() = OnDiskMainHeader::kMajorVersion;
MinorVersion() = OnDiskMainHeader::kMinorVersion;
Algorithm() = algorithm;
NumHeaderBlocks() = headerBlocks;
NumDataBlocks() = dataBlocks;
NumFileBlocks() = headerBlocks + dataBlocks;
Salt() = salt;
SetDefaultRoot(defaultRoot);
}
// Class CPGPdiskUserHeader member functions
CPGPdiskUserHeader::CPGPdiskUserHeader(const CPGPdiskContext *pContext) :
CPGPdiskHeader(pContext)
{
}
void
CPGPdiskUserHeader::GetUser(CPGPdiskUser& user)
{
user.Import(mHeaderBytes.Get() + ExportedUserOffset(),
ExportedUserSize());
}
void
CPGPdiskUserHeader::Create(const CPGPdiskUser& user)
{
pgpAssert(user.IsAssigned());
// Expand header large enough to hold user.
PGPUInt32 onDiskSize = sizeof(OnDiskUserHeader) +
user.GetSizeForExport();
mHeaderBytes.Resize(onDiskSize);
mHeaderBytes.Wipe();
// Initialize fields.
HeaderMagic() = OnDiskHeaderInfo::kHeaderMagic;
HeaderType() = OnDiskHeaderInfo::kUserType;
HeaderSize() = onDiskSize;
// Get exported user.
ExportedUserOffset() = sizeof(OnDiskUserHeader);
ExportedUserSize() = user.GetSizeForExport();
user.Export(mHeaderBytes.Get() + ExportedUserOffset(),
user.GetSizeForExport());
}
void
CPGPdiskUserHeader::CreateFromOldKeyInfo(
const PGPdiskOldCrypto::PassphraseKeyInfo *pOldKeyInfo,
PGPBoolean isAdmin)
{
pgpAssertAddrValid(pOldKeyInfo, PGPdiskOldCrypto::PassphraseKeyInfo);
// Re-encrypt crypto.
Crypto::PassphraseKeyInfo keyInfo;
pgpClearMemory(&keyInfo, sizeof(keyInfo));
pgpCopyMemory(pOldKeyInfo->encryptedKey.bytes,
keyInfo.encryptedKey.bytes, sizeof(pOldKeyInfo->encryptedKey));
pgpCopyMemory(pOldKeyInfo->checkBytes.bytes,
keyInfo.checkBytes.bytes, sizeof(pOldKeyInfo->checkBytes));
keyInfo.hashReps = pOldKeyInfo->hashReps;
CPGPdiskUser user(Context());
user.ImportRawSymmetricKey(keyInfo, UCommonStrings::Get(
UCommonStrings::kUnknownUserString), pOldKeyInfo->readOnly);
if (isAdmin)
user.SetIsAdminUser(TRUE);
// Punt to Create();
Create(user);
}
void
CPGPdiskUserHeader::ConvertFromOldPubKeyHeader()
{
PGPdiskOldFormat::PublicKeyHeader *pOldHeader =
reinterpret_cast<PGPdiskOldFormat::PublicKeyHeader *>(
mHeaderBytes.Get());
const PGPByte *pExportedKeyID = mHeaderBytes.Get() +
pOldHeader->keyIDOffset;
const PGPByte *pEncryptedKey = mHeaderBytes.Get() +
pOldHeader->encryptedKeyOffset;
Crypto::CheckBytes checkBytes;
pgpClearMemory(&checkBytes.bytes, sizeof(checkBytes.bytes));
pgpCopyMemory(pOldHeader->checkBytes.bytes, checkBytes.bytes,
sizeof(pOldHeader->checkBytes.bytes));
CPGPdiskUser user(Context());
user.ImportRawPublicKey(pExportedKeyID, pOldHeader->keyIDSize,
pEncryptedKey, pOldHeader->encryptedKeySize, checkBytes,
pOldHeader->algorithm, pOldHeader->readOnly, pOldHeader->locked);
// Punt to Create();
Create(user);
}
void
CPGPdiskUserHeader::CanonicalizeHeader()
{
CPGPdiskHeader::CanonicalizeHeader();
if (IsOldPubKeyType())
ConvertFromOldPubKeyHeader();
if (!IsUserType())
THROW_PGPERROR(kPGPClientError_CorruptDiskHeader);
if (ExportedUserOffset() + ExportedUserSize() > HeaderSize())
THROW_PGPERROR(kPGPClientError_CorruptDiskHeader);
}
// Class CPGPdiskHeaders member functions
CPGPdiskHeaders::~CPGPdiskHeaders()
{
ClearHeaders();
}
PGPBoolean
CPGPdiskHeaders::HasOldHeaders() const
{
pgpAssert(HeadersRead());
return MainHeader()->IsOldHeaderAvailable();
}
PGPUInt64
CPGPdiskHeaders::NumFileBlocks() const
{
pgpAssert(HeadersRead());
return MainHeader()->NumFileBlocks();
}
PGPUInt64
CPGPdiskHeaders::NumHeaderBlocks() const
{
pgpAssert(HeadersRead());
return MainHeader()->NumHeaderBlocks();
}
PGPUInt64
CPGPdiskHeaders::NumDataBlocks() const
{
pgpAssert(HeadersRead());
return MainHeader()->NumDataBlocks();
}
PGPdiskEncryptionAlgorithm
CPGPdiskHeaders::Algorithm() const
{
pgpAssert(HeadersRead());
return MainHeader()->Algorithm();
}
PGPBoolean
CPGPdiskHeaders::IsBeingReEncrypted() const
{
pgpAssert(HeadersRead());
return MainHeader()->GetIsBeingReEncrypted();
}
PGPBoolean
CPGPdiskHeaders::AreUsersWiped() const
{
pgpAssert(HeadersRead());
return MainHeader()->GetIsWiped();
}
PGPBoolean
CPGPdiskHeaders::UsesCustomTimeout() const
{
// Could happen if the network cable is unplugged--headers couldn't be read
// This was reported to happen when PGPdisk is mounted from a network
// drive, PGPkeys is opened to change passphrase, and then network is
// disconnected before closing PGPkeys.
if(!HeadersRead())
{
return FALSE;
}
pgpAssert(HeadersRead());
return MainHeader()->GetUsesCustomTimeout();
}
const char *
CPGPdiskHeaders::DefaultRoot() const
{
pgpAssert(HeadersRead());
return MainHeader()->DefaultRoot();
}
PGPUInt32
CPGPdiskHeaders::CustomTimeout() const
{
pgpAssert(HeadersRead());
return MainHeader()->CustomTimeout();
}
PGPUInt64
CPGPdiskHeaders::BlocksDisk() const
{
pgpAssert(HeadersRead());
return MainHeader()->NumDataBlocks();
}
void
CPGPdiskHeaders::SetUsesCustomTimeout(PGPBoolean usesCustom)
{
pgpAssert(HeadersRead());
MainHeader()->SetUsesCustomTimeout(usesCustom);
}
void
CPGPdiskHeaders::SetCustomTimeout(PGPUInt32 customTimeout)
{
pgpAssert(HeadersRead());
MainHeader()->CustomTimeout() = customTimeout;
}
void
CPGPdiskHeaders::SetDefaultRoot(const char * root)
{
pgpAssert(HeadersRead());
MainHeader()->SetDefaultRoot(root);
}
void
CPGPdiskHeaders::ExportUserSet(CPGPdiskUserSet& userSet) const
{
CPGPdiskHeader *pHeader = MainHeader();
userSet.Empty();
while (IsntNull(pHeader))
{
if (pHeader->IsUserType())
{
CPGPdiskUserHeader *pUserHeader =
reinterpret_cast<CPGPdiskUserHeader *>(pHeader);
if (!pUserHeader->GetIsNotExported())
{
CPGPdiskUser user(Context());
pUserHeader->GetUser(user);
userSet.Add(user);
}
}
pHeader = mHeaders.Next(pHeader);
}
}
void
CPGPdiskHeaders::ImportUserSet(const CPGPdiskUserSet& userSet)
{
CPGPdiskUser *pUser;
CPGPdiskUserIter userIter(&userSet);
if (userSet.Count() == 0)
THROW_PGPERROR(kPGPError_BadParams);
NukeAllUserHeaders();
// First pass: ensure only one user is the admin.
PGPBoolean sawAdmin = FALSE;
while (TRUE)
{
pUser = userIter.Next();
if (IsNull(pUser))
break;
if (pUser->IsAdminUser())
{
if (sawAdmin)
pUser->SetIsAdminUser(FALSE);
sawAdmin = TRUE;
}
}
userIter.Rewind();
// Second pass: create user headers.
while (TRUE)
{
pUser = userIter.Next();
if (IsNull(pUser))
break;
// If no admin was seen on first pass, first user becomes admin.
if (!sawAdmin)
{
pUser->SetIsAdminUser(TRUE);
sawAdmin = TRUE;
}
// Create and add new user header.
auto_ptr<CPGPdiskUserHeader> pUserHeader(
new CPGPdiskUserHeader(Context()));
pUserHeader->Create(*pUser);
mHeaders.AddTail(pUserHeader.release());
}
}
void
CPGPdiskHeaders::EnableCipheringOnUser(
CPGPdiskUser& user,
const char *passphrase,
int passkeylen)
{
pgpAssert(HeadersRead());
pgpAssert(user.IsAssigned());
user.EnableCiphering(passphrase, passkeylen, Algorithm(), MainHeader()->Salt());
}
void
CPGPdiskHeaders::WipeUsers(CFile& diskFile)
{
pgpAssert(HeadersRead());
pgpAssert(diskFile.IsOpened());
// Remove all symmetric user headers.
CPGPdiskUserSet userSet, usersToRemove;
ExportUserSet(userSet);
CPGPdiskUserIter userIter(&userSet);
CPGPdiskUser *pUser;
PGPBoolean sawPubKey = FALSE;
while (TRUE)
{
pUser = userIter.Next();
if (IsNull(pUser))
break;
if (pUser->HasPublicKey())
sawPubKey = TRUE;
if (pUser->HasSymmetricKey())
usersToRemove.Add(*pUser);
}
// Only proceed if at least one public key was seen.
if (!sawPubKey)
THROW_PGPERROR(kPGPClientError_NeedPubKeyToWipeDisk);
// Remove and update users.
userSet.Remove(usersToRemove);
ImportUserSet(userSet);
// Mark disk as wiped.
MainHeader()->SetIsWiped(TRUE);
// Make sure we write out now and flush.
WriteHeaders(diskFile);
diskFile.Flush();
}
void
CPGPdiskHeaders::BeginReEncryption(
CFile& diskFile,
const char *adminPassphrase,
PGPdiskEncryptionAlgorithm newAlgorithm)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -