📄 pgpdisk.cpp
字号:
//////////////////////////////////////////////////////////////////////////////
// PGPdisk.cpp
//
// Class PGPdisk definition.
//////////////////////////////////////////////////////////////////////////////
// $Id: PGPdisk.cpp,v 1.9 1999/02/26 04:09:57 nryan Exp $
// Copyright (C) 1998 by Network Associates, Inc.
// All rights reserved.
#include "StdAfx.h"
#include <new.h>
#include "Required.h"
#include "pgpUtilities.h"
#include "CommonStrings.h"
#include "GlobalPGPContext.h"
#include "PGPdiskFileFormat.h"
#include "PGPdiskHighLevelUtils.h"
#include "PGPdiskLowLevelUtils.h"
#include "PGPdiskPublicKeyUtils.h"
#include "SecureMemory.h"
#include "UtilityFunctions.h"
#include "Win32Utils.h"
#include "CipherContext.h"
#include "SHA.h"
#include "Globals.h"
#include "PGPdisk.h"
////////////
// Constants
////////////
const PGPUInt32 kNumBlocksToConvertAtATime = 128;
const PGPUInt32 kOffsetToCCIStruct = kDefaultBlockSize -
sizeof(PGPdiskCASTConvertInfo);
////////////////////////////////////////
// Class PGPdisk public member functions
////////////////////////////////////////
// The (LPCSTR, PGPUInt8) overloaded constructor attaches a drive and a
// pathname for an already mounted PGPdisk.
PGPdisk::PGPdisk(LPCSTR path, PGPUInt8 drive, PGPUInt64 sessionId)
: VolFile(path, drive)
{
mProgressBarHwnd = NULL;
mPCancelFlag = NULL;
mInitErr = VolFile::mInitErr;
// Read the session ID.
if (mInitErr.IsntError())
{
if (IsntNull(path))
{
pgpAssert(sessionId != kInvalidSessionId);
mUniqueSessionId = sessionId;
}
}
}
// BestGuessComparePaths uses a number of methods to determine if the
// specified file is the same as the current mounted PGPdisk.
PGPBoolean
PGPdisk::BestGuessComparePaths(LPCSTR path)
{
File testFile;
CString csPath, PGPdiskBareName, testBareName;
DualErr derr;
PGPBoolean failedTest = FALSE;
PGPUInt32 i, indexLastPGPdiskPathSlash, indexLastTestFilePathSlash;
PGPUInt32 numPGPdiskPathElems, numTestFilePathElems;
CString diskPath;
CString checkPath;
pgpAssert(Mounted());
// First try the easy case.
if (ComparePaths(path))
return TRUE;
// Convert paths to canonical form.
if (VerifyAndCanonicalizePath(path, &csPath).IsError())
csPath = path;
// See if the number of path elements in each path is the same.
numPGPdiskPathElems = 0;
for (i=0; i<strlen(diskPath); i++)
{
if ((diskPath.GetAt(i) == '\\') ||
(diskPath.GetAt(i) == '/'))
{
indexLastPGPdiskPathSlash = i;
numPGPdiskPathElems++;
}
}
numTestFilePathElems = 0;
for (i=0; i<strlen(checkPath); i++)
{
if ((checkPath.GetAt(i) == '\\') ||
(checkPath.GetAt(i) == '/'))
{
indexLastTestFilePathSlash = i;
numTestFilePathElems++;
}
}
if (numPGPdiskPathElems != numTestFilePathElems)
failedTest = TRUE;
// Compare the file names.
if (_stricmp(diskPath.Mid(indexLastPGPdiskPathSlash + 1),
checkPath.Mid(indexLastTestFilePathSlash + 1)) != 0)
{
failedTest = TRUE;
}
// Check if the test file is in use (which must be the case with any
// mounted PGPdisk.
if (derr.IsntError() && !failedTest)
{
if (!App->IsFileInUse(checkPath))
failedTest = TRUE;
}
// Finally return false if there was an error.
if (derr.IsError())
{
failedTest = TRUE;
}
return !failedTest;
}
// GetUniqueSessionId returns the unique session ID for the PGPdisk.
PGPUInt64
PGPdisk::GetUniqueSessionId()
{
pgpAssert(Mounted());
return mUniqueSessionId;
}
// ReadInUniqueSessionId reads in the unique session ID from the PGPdisk.
void
PGPdisk::ReadInUniqueSessionId(LPCSTR path)
{
mUniqueSessionId = GetPGPdiskUniqueSessionId(path);
}
// MakeUniqueSessionId makes a unique session ID for the PGPdisk.
DualErr
PGPdisk::MakeUniqueSessionId(LPCSTR path)
{
FILETIME fileTime;
PGPUInt64 tenthMsSince1601;
GetSystemTimeAsFileTime(&fileTime);
tenthMsSince1601 = MakeQWord(fileTime.dwLowDateTime,
fileTime.dwHighDateTime);
return SetPGPdiskUniqueSessionId(path, tenthMsSince1601);
}
// Mount asks the driver to mount the PGPdisk specified by 'path' with the
// specified password.
DualErr
PGPdisk::Mount(
LPCSTR path,
SecureString *passphrase,
PGPUInt8 drive,
PGPBoolean mountReadOnly)
{
AD_Mount MNT;
CASTKey *decryptedKey;
CipherContext *pContext = NULL;
DualErr derr;
const PassphraseKey *userInfo;
PGPBoolean readOnlyDueToADK = FALSE;
PGPBoolean readHeader = FALSE;
PGPdiskFileHeader *fileHeader;
PGPUInt16 index;
SecureMemory smDecryptedKey(sizeof(CASTKey));
SecureMemory smContext(sizeof(CipherContext));
pgpAssertStrValid(path);
pgpAssertAddrValid(passphrase, SecureString);
pgpAssert(Unmounted());
pgpAssert(!Opened());
// Did we get our locked memory?
derr = smDecryptedKey.mInitErr;
if (derr.IsntError())
{
derr = smContext.mInitErr;
}
if (derr.IsntError())
{
// Initialize the pointers to our locked memory.
decryptedKey = (CASTKey *) smDecryptedKey.GetPtr();
pContext = new (smContext.GetPtr()) CipherContext; // <new.h>
// Set and get the session ID and the drive letter preference.
if (!mountReadOnly)
{
MakeUniqueSessionId(path);
SetDriveLetterPref(path, drive);
}
ReadInUniqueSessionId(path);
}
// Read the header.
if (derr.IsntError())
{
derr = ReadPGPdiskFileMainHeader(path, &fileHeader);
readHeader = derr.IsntError();
}
if (derr.IsntError())
{
// Look for corresponding normal passphrase key.
derr = FindMatchingPassphrase(fileHeader, passphrase, &index);
if (derr.IsntError())
{
// Get a pointer to the passphrase info.
userInfo = GetPassphraseKeyPtr(fileHeader, index);
// Force read-only if the key is read-only.
if (userInfo->readOnly)
mountReadOnly = TRUE;
// Decrypt the encrypted key.
derr = DecryptPassphraseKey(userInfo, &fileHeader->salt,
passphrase, decryptedKey);
}
else
{
PGPBoolean gotPubKeyHdr = FALSE;
PGPdiskPublicKeyHeader *pubKeyHdr;
// Look for corresponding public key header.
derr = FindPublicPGPdiskKeyHeader(path, passphrase, &pubKeyHdr);
gotPubKeyHdr = derr.IsntError();
if (derr.IsntError())
{
// Force read-only if the key is read-only.
if (pubKeyHdr->readOnly)
{
if (!mountReadOnly)
readOnlyDueToADK = TRUE;
mountReadOnly = TRUE;
}
// Get decrypted key.
derr = GetDecryptedKeyUsingPublicKey(passphrase, pubKeyHdr,
decryptedKey);
}
if (gotPubKeyHdr)
FreePGPdiskFileHeader((PGPdiskFileHeaderInfo *) pubKeyHdr);
}
}
if (derr.IsntError())
{
// Initialize the cipher context.
pContext->InitContext(fileHeader->algorithm, decryptedKey->keyBytes,
fileHeader->salt.saltBytes);
// If NTFS perform checks.
if (IsPGPdiskNTFS(path, pContext))
{
if (IsWin95CompatibleMachine())
{
derr = DualErr(kPGDMinorError_TriedNTFSOnWin95);
}
else if (mountReadOnly)
{
if (readOnlyDueToADK)
mountReadOnly = FALSE;
else
derr = DualErr(kPGDMinorError_TriedReadOnlyNTFS);
}
}
}
if (derr.IsntError())
{
// Prepare the mount request packet; base classes will do the rest.
MNT.pContext = pContext;
// Call the request down.
derr = VolFile::Mount(path, drive, mountReadOnly, &MNT);
}
if (readHeader)
FreePGPdiskFileHeader((PGPdiskFileHeaderInfo *) fileHeader);
if (IsntNull(pContext))
pContext->~CipherContext();
return derr;
}
// Unmount asks the driver to unmount us.
DualErr
PGPdisk::Unmount(PGPBoolean isThisEmergency)
{
DualErr derr;
pgpAssert(Mounted());
// Call the request down.
derr = VolFile::Unmount(isThisEmergency);
return derr;
}
// CreatePGPdisk creates a new PGPdisk at the location specified by 'path'
// and with the desired free space specified in 'blocksData'.
DualErr
PGPdisk::CreatePGPdisk(
LPCSTR path,
PGPUInt64 blocksDisk,
PGPdiskEncryptionAlgorithm algorithm,
SecureString *passphrase,
PGPUInt8 drive)
{
DualErr derr;
PGPdiskFileHeader *fileHeader;
SecureMemory smFileHeader(sizeof(PGPdiskFileHeader));
pgpAssertAddrValid(passphrase, SecureString);
pgpAssertStrValid(path);
pgpAssert(algorithm != kInvalidEncryptionAlgorithm);
pgpAssert(blocksDisk > 0);
// Did we get our locked memory?
derr = smFileHeader.mInitErr;
if (derr.IsntError())
{
// Get a pointer to the locked memory.
fileHeader = (PGPdiskFileHeader *) smFileHeader.GetPtr();
// Create the file.
DeleteFile(path);
derr = Open(path, kOF_Trunc);
}
// Set its length.
if (derr.IsntError())
{
PGPUInt64 blocksLength;
blocksLength = kPGPdiskReservedHeaderBlocks + blocksDisk +
kPGPdiskAlternateHeaderBlocks;
derr = SetLength(blocksLength*kDefaultBlockSize);
}
if (derr.IsntError())
{
// Initialize the PGPdisk file header.
InitPGPdiskFileHeader(fileHeader, blocksDisk, algorithm, passphrase,
drive);
}
// Encrypt the disk.
if (derr.IsntError())
{
derr = FirstTimeEncryptDiskFile(fileHeader, passphrase);
}
// Write the header out to the PGPdisk file. Need to do this
if (derr.IsntError())
{
derr = FirstTimeWriteHeaderDiskFile(fileHeader);
}
// Close the file.
if (Opened())
Close();
// Cleanup in case of error.
if (derr.IsError())
{
DeleteFile(path);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -