mirror of
https://github.com/veracrypt/VeraCrypt.git
synced 2025-11-11 11:08:02 -06:00
Add TrueCrypt 7.1a MacOSX/Linux specific source files.
This commit is contained in:
20
src/Core/Core.h
Normal file
20
src/Core/Core.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright (c) 2008 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#ifndef TC_HEADER_Core_Core
|
||||
#define TC_HEADER_Core_Core
|
||||
|
||||
#include "CoreBase.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
extern auto_ptr <CoreBase> Core;
|
||||
extern auto_ptr <CoreBase> CoreDirect;
|
||||
}
|
||||
|
||||
#endif // TC_HEADER_Core_Core
|
||||
27
src/Core/Core.make
Normal file
27
src/Core/Core.make
Normal file
@@ -0,0 +1,27 @@
|
||||
#
|
||||
# Copyright (c) 2008 TrueCrypt Developers Association. All rights reserved.
|
||||
#
|
||||
# Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
# the file License.txt included in TrueCrypt binary and source code distribution
|
||||
# packages.
|
||||
#
|
||||
|
||||
OBJS :=
|
||||
OBJS += CoreBase.o
|
||||
OBJS += CoreException.o
|
||||
OBJS += FatFormatter.o
|
||||
OBJS += HostDevice.o
|
||||
OBJS += MountOptions.o
|
||||
OBJS += RandomNumberGenerator.o
|
||||
OBJS += VolumeCreator.o
|
||||
OBJS += Unix/CoreService.o
|
||||
OBJS += Unix/CoreServiceRequest.o
|
||||
OBJS += Unix/CoreServiceResponse.o
|
||||
OBJS += Unix/CoreUnix.o
|
||||
OBJS += Unix/$(PLATFORM)/Core$(PLATFORM).o
|
||||
OBJS += Unix/$(PLATFORM)/Core$(PLATFORM).o
|
||||
ifeq "$(PLATFORM)" "MacOSX"
|
||||
OBJS += Unix/FreeBSD/CoreFreeBSD.o
|
||||
endif
|
||||
|
||||
include $(BUILD_INC)/Makefile.inc
|
||||
279
src/Core/CoreBase.cpp
Normal file
279
src/Core/CoreBase.cpp
Normal file
@@ -0,0 +1,279 @@
|
||||
/*
|
||||
Copyright (c) 2008-2010 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "CoreBase.h"
|
||||
#include "RandomNumberGenerator.h"
|
||||
#include "Volume/Volume.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
CoreBase::CoreBase ()
|
||||
: DeviceChangeInProgress (false)
|
||||
{
|
||||
}
|
||||
|
||||
CoreBase::~CoreBase ()
|
||||
{
|
||||
}
|
||||
|
||||
void CoreBase::ChangePassword (shared_ptr <Volume> openVolume, shared_ptr <VolumePassword> newPassword, shared_ptr <KeyfileList> newKeyfiles, shared_ptr <Pkcs5Kdf> newPkcs5Kdf) const
|
||||
{
|
||||
if ((!newPassword || newPassword->Size() < 1) && (!newKeyfiles || newKeyfiles->empty()))
|
||||
throw PasswordEmpty (SRC_POS);
|
||||
|
||||
if (!newPkcs5Kdf)
|
||||
newPkcs5Kdf = openVolume->GetPkcs5Kdf();
|
||||
|
||||
if ((openVolume->GetHeader()->GetFlags() & TC_HEADER_FLAG_ENCRYPTED_SYSTEM) != 0
|
||||
&& openVolume->GetType() == VolumeType::Hidden
|
||||
&& openVolume->GetPath().IsDevice())
|
||||
{
|
||||
throw EncryptedSystemRequired (SRC_POS);
|
||||
}
|
||||
|
||||
RandomNumberGenerator::SetHash (newPkcs5Kdf->GetHash());
|
||||
|
||||
SecureBuffer newSalt (openVolume->GetSaltSize());
|
||||
SecureBuffer newHeaderKey (VolumeHeader::GetLargestSerializedKeySize());
|
||||
|
||||
shared_ptr <VolumePassword> password (Keyfile::ApplyListToPassword (newKeyfiles, newPassword));
|
||||
|
||||
bool backupHeader = false;
|
||||
while (true)
|
||||
{
|
||||
for (int i = 1; i <= SecureWipePassCount; i++)
|
||||
{
|
||||
if (i == SecureWipePassCount)
|
||||
RandomNumberGenerator::GetData (newSalt);
|
||||
else
|
||||
RandomNumberGenerator::GetDataFast (newSalt);
|
||||
|
||||
newPkcs5Kdf->DeriveKey (newHeaderKey, *password, newSalt);
|
||||
|
||||
openVolume->ReEncryptHeader (backupHeader, newSalt, newHeaderKey, newPkcs5Kdf);
|
||||
openVolume->GetFile()->Flush();
|
||||
}
|
||||
|
||||
if (!openVolume->GetLayout()->HasBackupHeader() || backupHeader)
|
||||
break;
|
||||
|
||||
backupHeader = true;
|
||||
}
|
||||
}
|
||||
|
||||
void CoreBase::ChangePassword (shared_ptr <VolumePath> volumePath, bool preserveTimestamps, shared_ptr <VolumePassword> password, shared_ptr <KeyfileList> keyfiles, shared_ptr <VolumePassword> newPassword, shared_ptr <KeyfileList> newKeyfiles, shared_ptr <Pkcs5Kdf> newPkcs5Kdf) const
|
||||
{
|
||||
shared_ptr <Volume> volume = OpenVolume (volumePath, preserveTimestamps, password, keyfiles);
|
||||
ChangePassword (volume, newPassword, newKeyfiles, newPkcs5Kdf);
|
||||
}
|
||||
|
||||
void CoreBase::CoalesceSlotNumberAndMountPoint (MountOptions &options) const
|
||||
{
|
||||
if (options.SlotNumber < GetFirstSlotNumber())
|
||||
{
|
||||
if (options.MountPoint && !options.MountPoint->IsEmpty())
|
||||
options.SlotNumber = MountPointToSlotNumber (*options.MountPoint);
|
||||
else
|
||||
options.SlotNumber = GetFirstFreeSlotNumber();
|
||||
}
|
||||
|
||||
if (!IsSlotNumberAvailable (options.SlotNumber))
|
||||
#ifdef TC_WINDOWS
|
||||
throw DriveLetterUnavailable (SRC_POS);
|
||||
#else
|
||||
throw VolumeSlotUnavailable (SRC_POS);
|
||||
#endif
|
||||
if (!options.NoFilesystem && (!options.MountPoint || options.MountPoint->IsEmpty()))
|
||||
options.MountPoint.reset (new DirectoryPath (SlotNumberToMountPoint (options.SlotNumber)));
|
||||
}
|
||||
|
||||
void CoreBase::CreateKeyfile (const FilePath &keyfilePath) const
|
||||
{
|
||||
SecureBuffer keyfileBuffer (VolumePassword::MaxSize);
|
||||
RandomNumberGenerator::GetData (keyfileBuffer);
|
||||
|
||||
File keyfile;
|
||||
keyfile.Open (keyfilePath, File::CreateWrite);
|
||||
keyfile.Write (keyfileBuffer);
|
||||
}
|
||||
|
||||
VolumeSlotNumber CoreBase::GetFirstFreeSlotNumber (VolumeSlotNumber startFrom) const
|
||||
{
|
||||
if (startFrom < GetFirstSlotNumber())
|
||||
startFrom = GetFirstSlotNumber();
|
||||
|
||||
set <VolumeSlotNumber> usedSlotNumbers;
|
||||
|
||||
foreach_ref (const VolumeInfo &volume, GetMountedVolumes())
|
||||
usedSlotNumbers.insert (volume.SlotNumber);
|
||||
|
||||
for (VolumeSlotNumber slotNumber = startFrom; slotNumber <= GetLastSlotNumber(); ++slotNumber)
|
||||
{
|
||||
if (usedSlotNumbers.find (slotNumber) == usedSlotNumbers.end()
|
||||
&& IsMountPointAvailable (SlotNumberToMountPoint (slotNumber)))
|
||||
return slotNumber;
|
||||
}
|
||||
#ifdef TC_WINDOWS
|
||||
throw DriveLetterUnavailable (SRC_POS);
|
||||
#else
|
||||
throw VolumeSlotUnavailable (SRC_POS);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64 CoreBase::GetMaxHiddenVolumeSize (shared_ptr <Volume> outerVolume) const
|
||||
{
|
||||
uint32 sectorSize = outerVolume->GetSectorSize();
|
||||
|
||||
SecureBuffer bootSectorBuffer (sectorSize);
|
||||
outerVolume->ReadSectors (bootSectorBuffer, 0);
|
||||
|
||||
int fatType;
|
||||
byte *bootSector = bootSectorBuffer.Ptr();
|
||||
|
||||
if (memcmp (bootSector + 54, "FAT12", 5) == 0)
|
||||
fatType = 12;
|
||||
else if (memcmp (bootSector + 54, "FAT16", 5) == 0)
|
||||
fatType = 16;
|
||||
else if (memcmp (bootSector + 82, "FAT32", 5) == 0)
|
||||
fatType = 32;
|
||||
else
|
||||
throw ParameterIncorrect (SRC_POS);
|
||||
|
||||
uint32 clusterSize = bootSector[13] * sectorSize;
|
||||
uint32 reservedSectorCount = Endian::Little (*(uint16 *) (bootSector + 14));
|
||||
uint32 fatCount = bootSector[16];
|
||||
|
||||
uint64 fatSectorCount;
|
||||
if (fatType == 32)
|
||||
fatSectorCount = Endian::Little (*(uint32 *) (bootSector + 36));
|
||||
else
|
||||
fatSectorCount = Endian::Little (*(uint16 *) (bootSector + 22));
|
||||
uint64 fatSize = fatSectorCount * sectorSize;
|
||||
|
||||
uint64 fatStartOffset = reservedSectorCount * sectorSize;
|
||||
uint64 dataAreaOffset = reservedSectorCount * sectorSize + fatSize * fatCount;
|
||||
|
||||
if (fatType < 32)
|
||||
dataAreaOffset += Endian::Little (*(uint16 *) (bootSector + 17)) * 32;
|
||||
|
||||
SecureBuffer sector (sectorSize);
|
||||
|
||||
// Find last used cluster
|
||||
for (uint64 readOffset = fatStartOffset + fatSize - sectorSize;
|
||||
readOffset >= fatStartOffset;
|
||||
readOffset -= sectorSize)
|
||||
{
|
||||
outerVolume->ReadSectors (sector, readOffset);
|
||||
|
||||
for (int offset = sectorSize - 4; offset >= 0; offset -= 4)
|
||||
{
|
||||
if (*(uint32 *) (sector.Ptr() + offset))
|
||||
{
|
||||
uint64 clusterNumber = readOffset - fatStartOffset + offset;
|
||||
|
||||
if (fatType == 12)
|
||||
clusterNumber = (clusterNumber * 8) / 12;
|
||||
else if (fatType == 16)
|
||||
clusterNumber /= 2;
|
||||
else if (fatType == 32)
|
||||
clusterNumber /= 4;
|
||||
|
||||
uint64 maxSize = outerVolume->GetSize() - dataAreaOffset;
|
||||
|
||||
// Some FAT entries may span over sector boundaries
|
||||
if (maxSize >= clusterSize)
|
||||
maxSize -= clusterSize;
|
||||
|
||||
uint64 clusterOffset = clusterNumber * clusterSize;
|
||||
if (maxSize < clusterOffset)
|
||||
return 0;
|
||||
|
||||
return maxSize - clusterOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
shared_ptr <VolumeInfo> CoreBase::GetMountedVolume (const VolumePath &volumePath) const
|
||||
{
|
||||
VolumeInfoList volumes = GetMountedVolumes (volumePath);
|
||||
if (volumes.empty())
|
||||
return shared_ptr <VolumeInfo> ();
|
||||
else
|
||||
return volumes.front();
|
||||
}
|
||||
|
||||
shared_ptr <VolumeInfo> CoreBase::GetMountedVolume (VolumeSlotNumber slot) const
|
||||
{
|
||||
foreach (shared_ptr <VolumeInfo> volume, GetMountedVolumes())
|
||||
{
|
||||
if (volume->SlotNumber == slot)
|
||||
return volume;
|
||||
}
|
||||
|
||||
return shared_ptr <VolumeInfo> ();
|
||||
}
|
||||
|
||||
bool CoreBase::IsSlotNumberAvailable (VolumeSlotNumber slotNumber) const
|
||||
{
|
||||
if (!IsMountPointAvailable (SlotNumberToMountPoint (slotNumber)))
|
||||
return false;
|
||||
|
||||
foreach_ref (const VolumeInfo &volume, GetMountedVolumes())
|
||||
{
|
||||
if (volume.SlotNumber == slotNumber)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CoreBase::IsVolumeMounted (const VolumePath &volumePath) const
|
||||
{
|
||||
return GetMountedVolume (volumePath);
|
||||
}
|
||||
|
||||
shared_ptr <Volume> CoreBase::OpenVolume (shared_ptr <VolumePath> volumePath, bool preserveTimestamps, shared_ptr <VolumePassword> password, shared_ptr <KeyfileList> keyfiles, VolumeProtection::Enum protection, shared_ptr <VolumePassword> protectionPassword, shared_ptr <KeyfileList> protectionKeyfiles, bool sharedAccessAllowed, VolumeType::Enum volumeType, bool useBackupHeaders, bool partitionInSystemEncryptionScope) const
|
||||
{
|
||||
make_shared_auto (Volume, volume);
|
||||
volume->Open (*volumePath, preserveTimestamps, password, keyfiles, protection, protectionPassword, protectionKeyfiles, sharedAccessAllowed, volumeType, useBackupHeaders, partitionInSystemEncryptionScope);
|
||||
return volume;
|
||||
}
|
||||
|
||||
void CoreBase::RandomizeEncryptionAlgorithmKey (shared_ptr <EncryptionAlgorithm> encryptionAlgorithm) const
|
||||
{
|
||||
SecureBuffer eaKey (encryptionAlgorithm->GetKeySize());
|
||||
RandomNumberGenerator::GetData (eaKey);
|
||||
encryptionAlgorithm->SetKey (eaKey);
|
||||
|
||||
SecureBuffer modeKey (encryptionAlgorithm->GetMode()->GetKeySize());
|
||||
RandomNumberGenerator::GetData (modeKey);
|
||||
encryptionAlgorithm->GetMode()->SetKey (modeKey);
|
||||
}
|
||||
|
||||
void CoreBase::ReEncryptVolumeHeaderWithNewSalt (const BufferPtr &newHeaderBuffer, shared_ptr <VolumeHeader> header, shared_ptr <VolumePassword> password, shared_ptr <KeyfileList> keyfiles) const
|
||||
{
|
||||
shared_ptr <Pkcs5Kdf> pkcs5Kdf = header->GetPkcs5Kdf();
|
||||
|
||||
RandomNumberGenerator::SetHash (pkcs5Kdf->GetHash());
|
||||
|
||||
SecureBuffer newSalt (header->GetSaltSize());
|
||||
SecureBuffer newHeaderKey (VolumeHeader::GetLargestSerializedKeySize());
|
||||
|
||||
shared_ptr <VolumePassword> passwordKey (Keyfile::ApplyListToPassword (keyfiles, password));
|
||||
|
||||
RandomNumberGenerator::GetData (newSalt);
|
||||
pkcs5Kdf->DeriveKey (newHeaderKey, *passwordKey, newSalt);
|
||||
|
||||
header->EncryptNew (newHeaderBuffer, newSalt, newHeaderKey, pkcs5Kdf);
|
||||
}
|
||||
}
|
||||
99
src/Core/CoreBase.h
Normal file
99
src/Core/CoreBase.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
Copyright (c) 2008-2010 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#ifndef TC_HEADER_Core_CoreBase
|
||||
#define TC_HEADER_Core_CoreBase
|
||||
|
||||
#include "Platform/Platform.h"
|
||||
#include "Platform/Functor.h"
|
||||
#include "Platform/User.h"
|
||||
#include "Common/Crypto.h"
|
||||
#include "Volume/Keyfile.h"
|
||||
#include "Volume/VolumeInfo.h"
|
||||
#include "Volume/Volume.h"
|
||||
#include "Volume/VolumePassword.h"
|
||||
#include "CoreException.h"
|
||||
#include "HostDevice.h"
|
||||
#include "MountOptions.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
class CoreBase
|
||||
{
|
||||
public:
|
||||
virtual ~CoreBase ();
|
||||
|
||||
virtual void ChangePassword (shared_ptr <Volume> openVolume, shared_ptr <VolumePassword> newPassword, shared_ptr <KeyfileList> newKeyfiles, shared_ptr <Pkcs5Kdf> newPkcs5Kdf = shared_ptr <Pkcs5Kdf> ()) const;
|
||||
virtual void ChangePassword (shared_ptr <VolumePath> volumePath, bool preserveTimestamps, shared_ptr <VolumePassword> password, shared_ptr <KeyfileList> keyfiles, shared_ptr <VolumePassword> newPassword, shared_ptr <KeyfileList> newKeyfiles, shared_ptr <Pkcs5Kdf> newPkcs5Kdf = shared_ptr <Pkcs5Kdf> ()) const;
|
||||
virtual void CheckFilesystem (shared_ptr <VolumeInfo> mountedVolume, bool repair = false) const = 0;
|
||||
virtual void CoalesceSlotNumberAndMountPoint (MountOptions &options) const;
|
||||
virtual void CreateKeyfile (const FilePath &keyfilePath) const;
|
||||
virtual void DismountFilesystem (const DirectoryPath &mountPoint, bool force) const = 0;
|
||||
virtual shared_ptr <VolumeInfo> DismountVolume (shared_ptr <VolumeInfo> mountedVolume, bool ignoreOpenFiles = false, bool syncVolumeInfo = false) = 0;
|
||||
virtual bool FilesystemSupportsLargeFiles (const FilePath &filePath) const = 0;
|
||||
virtual DirectoryPath GetDeviceMountPoint (const DevicePath &devicePath) const = 0;
|
||||
virtual uint32 GetDeviceSectorSize (const DevicePath &devicePath) const = 0;
|
||||
virtual uint64 GetDeviceSize (const DevicePath &devicePath) const = 0;
|
||||
virtual VolumeSlotNumber GetFirstFreeSlotNumber (VolumeSlotNumber startFrom = 0) const;
|
||||
virtual VolumeSlotNumber GetFirstSlotNumber () const { return 1; }
|
||||
virtual VolumeSlotNumber GetLastSlotNumber () const { return 64; }
|
||||
virtual HostDeviceList GetHostDevices (bool pathListOnly = false) const = 0;
|
||||
virtual FilePath GetApplicationExecutablePath () const { return ApplicationExecutablePath; }
|
||||
virtual uint64 GetMaxHiddenVolumeSize (shared_ptr <Volume> outerVolume) const;
|
||||
virtual int GetOSMajorVersion () const = 0;
|
||||
virtual int GetOSMinorVersion () const = 0;
|
||||
virtual shared_ptr <VolumeInfo> GetMountedVolume (const VolumePath &volumePath) const;
|
||||
virtual shared_ptr <VolumeInfo> GetMountedVolume (VolumeSlotNumber slot) const;
|
||||
virtual VolumeInfoList GetMountedVolumes (const VolumePath &volumePath = VolumePath()) const = 0;
|
||||
virtual bool HasAdminPrivileges () const = 0;
|
||||
virtual void Init () { }
|
||||
virtual bool IsDeviceChangeInProgress () const { return DeviceChangeInProgress; }
|
||||
virtual bool IsDevicePresent (const DevicePath &device) const = 0;
|
||||
virtual bool IsInPortableMode () const = 0;
|
||||
virtual bool IsMountPointAvailable (const DirectoryPath &mountPoint) const = 0;
|
||||
virtual bool IsOSVersion (int major, int minor) const = 0;
|
||||
virtual bool IsOSVersionLower (int major, int minor) const = 0;
|
||||
virtual bool IsPasswordCacheEmpty () const = 0;
|
||||
virtual bool IsSlotNumberAvailable (VolumeSlotNumber slotNumber) const;
|
||||
virtual bool IsSlotNumberValid (VolumeSlotNumber slotNumber) const { return slotNumber >= GetFirstSlotNumber() && slotNumber <= GetLastSlotNumber(); }
|
||||
virtual bool IsVolumeMounted (const VolumePath &volumePath) const;
|
||||
virtual VolumeSlotNumber MountPointToSlotNumber (const DirectoryPath &mountPoint) const = 0;
|
||||
virtual shared_ptr <VolumeInfo> MountVolume (MountOptions &options) = 0;
|
||||
virtual shared_ptr <Volume> OpenVolume (shared_ptr <VolumePath> volumePath, bool preserveTimestamps, shared_ptr <VolumePassword> password, shared_ptr <KeyfileList> keyfiles, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr <VolumePassword> protectionPassword = shared_ptr <VolumePassword> (), shared_ptr <KeyfileList> protectionKeyfiles = shared_ptr <KeyfileList> (), bool sharedAccessAllowed = false, VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false) const;
|
||||
virtual void RandomizeEncryptionAlgorithmKey (shared_ptr <EncryptionAlgorithm> encryptionAlgorithm) const;
|
||||
virtual void ReEncryptVolumeHeaderWithNewSalt (const BufferPtr &newHeaderBuffer, shared_ptr <VolumeHeader> header, shared_ptr <VolumePassword> password, shared_ptr <KeyfileList> keyfiles) const;
|
||||
virtual void SetAdminPasswordCallback (shared_ptr <GetStringFunctor> functor) { }
|
||||
virtual void SetApplicationExecutablePath (const FilePath &path) { ApplicationExecutablePath = path; }
|
||||
virtual void SetFileOwner (const FilesystemPath &path, const UserId &owner) const = 0;
|
||||
virtual DirectoryPath SlotNumberToMountPoint (VolumeSlotNumber slotNumber) const = 0;
|
||||
virtual void WipePasswordCache () const = 0;
|
||||
|
||||
Event VolumeDismountedEvent;
|
||||
Event VolumeMountedEvent;
|
||||
Event WarningEvent;
|
||||
|
||||
protected:
|
||||
CoreBase ();
|
||||
|
||||
static const int SecureWipePassCount = PRAND_DISK_WIPE_PASSES;
|
||||
bool DeviceChangeInProgress;
|
||||
FilePath ApplicationExecutablePath;
|
||||
|
||||
private:
|
||||
CoreBase (const CoreBase &);
|
||||
CoreBase &operator= (const CoreBase &);
|
||||
};
|
||||
|
||||
struct VolumeEventArgs : EventArgs
|
||||
{
|
||||
VolumeEventArgs (shared_ptr <VolumeInfo> volume) : mVolume (volume) { }
|
||||
shared_ptr <VolumeInfo> mVolume;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TC_HEADER_Core_CoreBase
|
||||
29
src/Core/CoreException.cpp
Normal file
29
src/Core/CoreException.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
Copyright (c) 2008 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#include "CoreException.h"
|
||||
#include "Platform/SerializerFactory.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
void ElevationFailed::Deserialize (shared_ptr <Stream> stream)
|
||||
{
|
||||
ExecutedProcessFailed::Deserialize (stream);
|
||||
}
|
||||
|
||||
void ElevationFailed::Serialize (shared_ptr <Stream> stream) const
|
||||
{
|
||||
ExecutedProcessFailed::Serialize (stream);
|
||||
}
|
||||
|
||||
#define TC_EXCEPTION(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE)
|
||||
#undef TC_EXCEPTION_NODECL
|
||||
#define TC_EXCEPTION_NODECL(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE)
|
||||
|
||||
TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET (CoreException);
|
||||
}
|
||||
52
src/Core/CoreException.h
Normal file
52
src/Core/CoreException.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
Copyright (c) 2008-2010 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#ifndef TC_HEADER_Core_CoreException
|
||||
#define TC_HEADER_Core_CoreException
|
||||
|
||||
#include "Platform/Platform.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
struct ElevationFailed : public ExecutedProcessFailed
|
||||
{
|
||||
ElevationFailed () { }
|
||||
ElevationFailed (const string &message, const string &command, int exitCode, const string &errorOutput)
|
||||
: ExecutedProcessFailed (message, command, exitCode, errorOutput) { }
|
||||
TC_SERIALIZABLE_EXCEPTION (ElevationFailed);
|
||||
};
|
||||
|
||||
TC_EXCEPTION_DECL (RootDeviceUnavailable, SystemException);
|
||||
|
||||
#define TC_EXCEPTION(NAME) TC_EXCEPTION_DECL(NAME,Exception)
|
||||
|
||||
#undef TC_EXCEPTION_SET
|
||||
#define TC_EXCEPTION_SET \
|
||||
TC_EXCEPTION_NODECL (ElevationFailed); \
|
||||
TC_EXCEPTION_NODECL (RootDeviceUnavailable); \
|
||||
TC_EXCEPTION (DriveLetterUnavailable); \
|
||||
TC_EXCEPTION (DriverError); \
|
||||
TC_EXCEPTION (EncryptedSystemRequired); \
|
||||
TC_EXCEPTION (HigherFuseVersionRequired); \
|
||||
TC_EXCEPTION (KernelCryptoServiceTestFailed); \
|
||||
TC_EXCEPTION (LoopDeviceSetupFailed); \
|
||||
TC_EXCEPTION (MountPointRequired); \
|
||||
TC_EXCEPTION (MountPointUnavailable); \
|
||||
TC_EXCEPTION (NoDriveLetterAvailable); \
|
||||
TC_EXCEPTION (TemporaryDirectoryFailure); \
|
||||
TC_EXCEPTION (UnsupportedSectorSizeHiddenVolumeProtection); \
|
||||
TC_EXCEPTION (UnsupportedSectorSizeNoKernelCrypto); \
|
||||
TC_EXCEPTION (VolumeAlreadyMounted); \
|
||||
TC_EXCEPTION (VolumeSlotUnavailable);
|
||||
|
||||
TC_EXCEPTION_SET;
|
||||
|
||||
#undef TC_EXCEPTION
|
||||
}
|
||||
|
||||
#endif // TC_HEADER_Core_CoreException
|
||||
384
src/Core/FatFormatter.cpp
Normal file
384
src/Core/FatFormatter.cpp
Normal file
@@ -0,0 +1,384 @@
|
||||
/*
|
||||
Legal Notice: Some portions of the source code contained in this file were
|
||||
derived from the source code of Encryption for the Masses 2.02a, which is
|
||||
Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License
|
||||
Agreement for Encryption for the Masses'. Modifications and additions to
|
||||
the original source code (contained in this file) and all other portions
|
||||
of this file are Copyright (c) 2003-2010 TrueCrypt Developers Association
|
||||
and are governed by the TrueCrypt License 3.0 the full text of which is
|
||||
contained in the file License.txt included in TrueCrypt binary and source
|
||||
code distribution packages. */
|
||||
|
||||
#include "Common/Tcdefs.h"
|
||||
#include "Platform/Platform.h"
|
||||
#include "Volume/VolumeHeader.h"
|
||||
#include "FatFormatter.h"
|
||||
#include "RandomNumberGenerator.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
struct fatparams
|
||||
{
|
||||
char volume_name[11];
|
||||
uint32 num_sectors; /* total number of sectors */
|
||||
uint32 cluster_count; /* number of clusters */
|
||||
uint32 size_root_dir; /* size of the root directory in bytes */
|
||||
uint32 size_fat; /* size of FAT */
|
||||
uint32 fats;
|
||||
uint32 media;
|
||||
uint32 cluster_size;
|
||||
uint32 fat_length;
|
||||
uint16 dir_entries;
|
||||
uint16 sector_size;
|
||||
uint32 hidden;
|
||||
uint16 reserved;
|
||||
uint16 sectors;
|
||||
uint32 total_sect;
|
||||
|
||||
uint16 heads;
|
||||
uint16 secs_track;
|
||||
|
||||
};
|
||||
|
||||
static void GetFatParams (fatparams * ft)
|
||||
{
|
||||
uint64 volumeSize = (uint64) ft->num_sectors * ft->sector_size;
|
||||
unsigned int fatsecs;
|
||||
|
||||
if(ft->cluster_size == 0) // 'Default' cluster size
|
||||
{
|
||||
uint32 clusterSize;
|
||||
|
||||
// Determine optimal cluster size to minimize FAT size (mounting delay), maximize number of files, keep 4 KB alignment, etc.
|
||||
if (volumeSize >= 2 * BYTES_PER_TB)
|
||||
clusterSize = 256 * BYTES_PER_KB;
|
||||
else if (volumeSize >= 512 * BYTES_PER_GB)
|
||||
clusterSize = 128 * BYTES_PER_KB;
|
||||
else if (volumeSize >= 128 * BYTES_PER_GB)
|
||||
clusterSize = 64 * BYTES_PER_KB;
|
||||
else if (volumeSize >= 64 * BYTES_PER_GB)
|
||||
clusterSize = 32 * BYTES_PER_KB;
|
||||
else if (volumeSize >= 32 * BYTES_PER_GB)
|
||||
clusterSize = 16 * BYTES_PER_KB;
|
||||
else if (volumeSize >= 16 * BYTES_PER_GB)
|
||||
clusterSize = 8 * BYTES_PER_KB;
|
||||
else if (volumeSize >= 512 * BYTES_PER_MB)
|
||||
clusterSize = 4 * BYTES_PER_KB;
|
||||
else if (volumeSize >= 256 * BYTES_PER_MB)
|
||||
clusterSize = 2 * BYTES_PER_KB;
|
||||
else if (volumeSize >= 1 * BYTES_PER_MB)
|
||||
clusterSize = 1 * BYTES_PER_KB;
|
||||
else
|
||||
clusterSize = 512;
|
||||
|
||||
ft->cluster_size = clusterSize / ft->sector_size;
|
||||
|
||||
if (ft->cluster_size == 0)
|
||||
ft->cluster_size = 1;
|
||||
|
||||
if (ft->cluster_size * ft->sector_size > TC_MAX_FAT_CLUSTER_SIZE)
|
||||
ft->cluster_size = TC_MAX_FAT_CLUSTER_SIZE / ft->sector_size;
|
||||
|
||||
if (ft->cluster_size > 128)
|
||||
ft->cluster_size = 128;
|
||||
}
|
||||
|
||||
if (volumeSize <= TC_MAX_FAT_CLUSTER_SIZE * 4)
|
||||
ft->cluster_size = 1;
|
||||
|
||||
// Geometry always set to SECTORS/1/1
|
||||
ft->secs_track = 1;
|
||||
ft->heads = 1;
|
||||
|
||||
ft->dir_entries = 512;
|
||||
ft->fats = 2;
|
||||
ft->media = 0xf8;
|
||||
ft->hidden = 0;
|
||||
|
||||
ft->size_root_dir = ft->dir_entries * 32;
|
||||
|
||||
// FAT12
|
||||
ft->size_fat = 12;
|
||||
ft->reserved = 2;
|
||||
fatsecs = ft->num_sectors - (ft->size_root_dir + ft->sector_size - 1) / ft->sector_size - ft->reserved;
|
||||
ft->cluster_count = (int) (((int64) fatsecs * ft->sector_size) / (ft->cluster_size * ft->sector_size));
|
||||
ft->fat_length = (((ft->cluster_count * 3 + 1) >> 1) + ft->sector_size - 1) / ft->sector_size;
|
||||
|
||||
if (ft->cluster_count >= 4085) // FAT16
|
||||
{
|
||||
ft->size_fat = 16;
|
||||
ft->reserved = 2;
|
||||
fatsecs = ft->num_sectors - (ft->size_root_dir + ft->sector_size - 1) / ft->sector_size - ft->reserved;
|
||||
ft->cluster_count = (int) (((int64) fatsecs * ft->sector_size) / (ft->cluster_size * ft->sector_size));
|
||||
ft->fat_length = (ft->cluster_count * 2 + ft->sector_size - 1) / ft->sector_size;
|
||||
}
|
||||
|
||||
if(ft->cluster_count >= 65525) // FAT32
|
||||
{
|
||||
ft->size_fat = 32;
|
||||
ft->reserved = 32 - 1;
|
||||
|
||||
do
|
||||
{
|
||||
ft->reserved++;
|
||||
|
||||
fatsecs = ft->num_sectors - ft->reserved;
|
||||
ft->size_root_dir = ft->cluster_size * ft->sector_size;
|
||||
ft->cluster_count = (int) (((int64) fatsecs * ft->sector_size) / (ft->cluster_size * ft->sector_size));
|
||||
ft->fat_length = (ft->cluster_count * 4 + ft->sector_size - 1) / ft->sector_size;
|
||||
|
||||
// Align data area on TC_MAX_VOLUME_SECTOR_SIZE
|
||||
|
||||
} while (ft->sector_size == TC_SECTOR_SIZE_LEGACY
|
||||
&& (ft->reserved * ft->sector_size + ft->fat_length * ft->fats * ft->sector_size) % TC_MAX_VOLUME_SECTOR_SIZE != 0);
|
||||
}
|
||||
|
||||
ft->cluster_count -= ft->fat_length * ft->fats / ft->cluster_size;
|
||||
|
||||
if (ft->num_sectors >= 65536 || ft->size_fat == 32)
|
||||
{
|
||||
ft->sectors = 0;
|
||||
ft->total_sect = ft->num_sectors;
|
||||
}
|
||||
else
|
||||
{
|
||||
ft->sectors = (uint16) ft->num_sectors;
|
||||
ft->total_sect = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void PutBoot (fatparams * ft, byte *boot, uint32 volumeId)
|
||||
{
|
||||
int cnt = 0;
|
||||
|
||||
boot[cnt++] = 0xeb; /* boot jump */
|
||||
boot[cnt++] = 0x3c;
|
||||
boot[cnt++] = 0x90;
|
||||
memcpy (boot + cnt, "MSDOS5.0", 8); /* system id */
|
||||
cnt += 8;
|
||||
*(int16 *)(boot + cnt) = Endian::Little (ft->sector_size); /* bytes per sector */
|
||||
cnt += 2;
|
||||
boot[cnt++] = (int8) ft->cluster_size; /* sectors per cluster */
|
||||
*(int16 *)(boot + cnt) = Endian::Little (ft->reserved); /* reserved sectors */
|
||||
cnt += 2;
|
||||
boot[cnt++] = (int8) ft->fats; /* 2 fats */
|
||||
|
||||
if(ft->size_fat == 32)
|
||||
{
|
||||
boot[cnt++] = 0x00;
|
||||
boot[cnt++] = 0x00;
|
||||
}
|
||||
else
|
||||
{
|
||||
*(int16 *)(boot + cnt) = Endian::Little (ft->dir_entries); /* 512 root entries */
|
||||
cnt += 2;
|
||||
}
|
||||
|
||||
*(int16 *)(boot + cnt) = Endian::Little (ft->sectors); /* # sectors */
|
||||
cnt += 2;
|
||||
boot[cnt++] = (int8) ft->media; /* media byte */
|
||||
|
||||
if(ft->size_fat == 32)
|
||||
{
|
||||
boot[cnt++] = 0x00;
|
||||
boot[cnt++] = 0x00;
|
||||
}
|
||||
else
|
||||
{
|
||||
*(uint16 *)(boot + cnt) = Endian::Little ((uint16) ft->fat_length); /* fat size */
|
||||
cnt += 2;
|
||||
}
|
||||
|
||||
*(int16 *)(boot + cnt) = Endian::Little (ft->secs_track); /* # sectors per track */
|
||||
cnt += 2;
|
||||
*(int16 *)(boot + cnt) = Endian::Little (ft->heads); /* # heads */
|
||||
cnt += 2;
|
||||
*(int32 *)(boot + cnt) = Endian::Little (ft->hidden); /* # hidden sectors */
|
||||
cnt += 4;
|
||||
*(int32 *)(boot + cnt) = Endian::Little (ft->total_sect); /* # huge sectors */
|
||||
cnt += 4;
|
||||
|
||||
if(ft->size_fat == 32)
|
||||
{
|
||||
*(int32 *)(boot + cnt) = Endian::Little (ft->fat_length); cnt += 4; /* fat size 32 */
|
||||
boot[cnt++] = 0x00; /* ExtFlags */
|
||||
boot[cnt++] = 0x00;
|
||||
boot[cnt++] = 0x00; /* FSVer */
|
||||
boot[cnt++] = 0x00;
|
||||
boot[cnt++] = 0x02; /* RootClus */
|
||||
boot[cnt++] = 0x00;
|
||||
boot[cnt++] = 0x00;
|
||||
boot[cnt++] = 0x00;
|
||||
boot[cnt++] = 0x01; /* FSInfo */
|
||||
boot[cnt++] = 0x00;
|
||||
boot[cnt++] = 0x06; /* BkBootSec */
|
||||
boot[cnt++] = 0x00;
|
||||
memset(boot+cnt, 0, 12); cnt+=12; /* Reserved */
|
||||
}
|
||||
|
||||
boot[cnt++] = 0x00; /* drive number */ // FIXED 80 > 00
|
||||
boot[cnt++] = 0x00; /* reserved */
|
||||
boot[cnt++] = 0x29; /* boot sig */
|
||||
|
||||
*(int32 *)(boot + cnt) = volumeId;
|
||||
cnt += 4;
|
||||
|
||||
memcpy (boot + cnt, ft->volume_name, 11); /* vol title */
|
||||
cnt += 11;
|
||||
|
||||
switch(ft->size_fat) /* filesystem type */
|
||||
{
|
||||
case 12: memcpy (boot + cnt, "FAT12 ", 8); break;
|
||||
case 16: memcpy (boot + cnt, "FAT16 ", 8); break;
|
||||
case 32: memcpy (boot + cnt, "FAT32 ", 8); break;
|
||||
}
|
||||
cnt += 8;
|
||||
|
||||
memset (boot + cnt, 0, ft->size_fat==32 ? 420:448); /* boot code */
|
||||
cnt += ft->size_fat==32 ? 420:448;
|
||||
boot[cnt++] = 0x55;
|
||||
boot[cnt++] = 0xaa; /* boot sig */
|
||||
}
|
||||
|
||||
|
||||
/* FAT32 FSInfo */
|
||||
static void PutFSInfo (byte *sector, fatparams *ft)
|
||||
{
|
||||
memset (sector, 0, ft->sector_size);
|
||||
sector[3] = 0x41; /* LeadSig */
|
||||
sector[2] = 0x61;
|
||||
sector[1] = 0x52;
|
||||
sector[0] = 0x52;
|
||||
sector[484+3] = 0x61; /* StrucSig */
|
||||
sector[484+2] = 0x41;
|
||||
sector[484+1] = 0x72;
|
||||
sector[484+0] = 0x72;
|
||||
|
||||
// Free cluster count
|
||||
*(uint32 *)(sector + 488) = Endian::Little (ft->cluster_count - ft->size_root_dir / ft->sector_size / ft->cluster_size);
|
||||
|
||||
// Next free cluster
|
||||
*(uint32 *)(sector + 492) = Endian::Little ((uint32) 2);
|
||||
|
||||
sector[508+3] = 0xaa; /* TrailSig */
|
||||
sector[508+2] = 0x55;
|
||||
sector[508+1] = 0x00;
|
||||
sector[508+0] = 0x00;
|
||||
}
|
||||
|
||||
void FatFormatter::Format (WriteSectorCallback &writeSector, uint64 deviceSize, uint32 clusterSize, uint32 sectorSize)
|
||||
{
|
||||
fatparams fatParams;
|
||||
|
||||
#if TC_MAX_VOLUME_SECTOR_SIZE > 0xFFFF
|
||||
#error TC_MAX_VOLUME_SECTOR_SIZE > 0xFFFF
|
||||
#endif
|
||||
fatParams.sector_size = (uint16) sectorSize;
|
||||
|
||||
if (deviceSize / fatParams.sector_size > 0xffffFFFF)
|
||||
throw ParameterIncorrect (SRC_POS);
|
||||
|
||||
fatParams.num_sectors = (uint32) (deviceSize / fatParams.sector_size);
|
||||
fatParams.cluster_size = clusterSize / fatParams.sector_size;
|
||||
memcpy (fatParams.volume_name, "NO NAME ", 11);
|
||||
GetFatParams (&fatParams);
|
||||
fatparams *ft = &fatParams;
|
||||
|
||||
SecureBuffer sector (ft->sector_size);
|
||||
uint32 sectorNumber = 0;
|
||||
|
||||
/* Write the data area */
|
||||
|
||||
sector.Zero();
|
||||
|
||||
uint32 volumeId;
|
||||
RandomNumberGenerator::GetDataFast (BufferPtr ((byte *) &volumeId, sizeof (volumeId)));
|
||||
|
||||
PutBoot (ft, (byte *) sector, volumeId);
|
||||
writeSector (sector); ++sectorNumber;
|
||||
|
||||
/* fat32 boot area */
|
||||
if (ft->size_fat == 32)
|
||||
{
|
||||
/* fsinfo */
|
||||
PutFSInfo((byte *) sector, ft);
|
||||
writeSector (sector); ++sectorNumber;
|
||||
|
||||
/* reserved */
|
||||
while (sectorNumber < 6)
|
||||
{
|
||||
sector.Zero();
|
||||
sector[508+3] = 0xaa; /* TrailSig */
|
||||
sector[508+2] = 0x55;
|
||||
writeSector (sector); ++sectorNumber;
|
||||
}
|
||||
|
||||
/* bootsector backup */
|
||||
sector.Zero();
|
||||
PutBoot (ft, (byte *) sector, volumeId);
|
||||
writeSector (sector); ++sectorNumber;
|
||||
|
||||
PutFSInfo((byte *) sector, ft);
|
||||
writeSector (sector); ++sectorNumber;
|
||||
}
|
||||
|
||||
/* reserved */
|
||||
while (sectorNumber < (uint32)ft->reserved)
|
||||
{
|
||||
sector.Zero();
|
||||
writeSector (sector); ++sectorNumber;
|
||||
}
|
||||
|
||||
/* write fat */
|
||||
for (uint32 x = 1; x <= ft->fats; x++)
|
||||
{
|
||||
for (uint32 n = 0; n < ft->fat_length; n++)
|
||||
{
|
||||
sector.Zero();
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
byte fat_sig[12];
|
||||
if (ft->size_fat == 32)
|
||||
{
|
||||
fat_sig[0] = (byte) ft->media;
|
||||
fat_sig[1] = fat_sig[2] = 0xff;
|
||||
fat_sig[3] = 0x0f;
|
||||
fat_sig[4] = fat_sig[5] = fat_sig[6] = 0xff;
|
||||
fat_sig[7] = 0x0f;
|
||||
fat_sig[8] = fat_sig[9] = fat_sig[10] = 0xff;
|
||||
fat_sig[11] = 0x0f;
|
||||
memcpy (sector, fat_sig, 12);
|
||||
}
|
||||
else if (ft->size_fat == 16)
|
||||
{
|
||||
fat_sig[0] = (byte) ft->media;
|
||||
fat_sig[1] = 0xff;
|
||||
fat_sig[2] = 0xff;
|
||||
fat_sig[3] = 0xff;
|
||||
memcpy (sector, fat_sig, 4);
|
||||
}
|
||||
else if (ft->size_fat == 12)
|
||||
{
|
||||
fat_sig[0] = (byte) ft->media;
|
||||
fat_sig[1] = 0xff;
|
||||
fat_sig[2] = 0xff;
|
||||
fat_sig[3] = 0x00;
|
||||
memcpy (sector, fat_sig, 4);
|
||||
}
|
||||
}
|
||||
|
||||
if (!writeSector (sector))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* write rootdir */
|
||||
for (uint32 x = 0; x < ft->size_root_dir / ft->sector_size; x++)
|
||||
{
|
||||
sector.Zero();
|
||||
if (!writeSector (sector))
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
29
src/Core/FatFormatter.h
Normal file
29
src/Core/FatFormatter.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
Copyright (c) 2008-2010 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#ifndef TC_HEADER_Core_FatFormatter
|
||||
#define TC_HEADER_Core_FatFormatter
|
||||
|
||||
#include "Platform/Platform.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
class FatFormatter
|
||||
{
|
||||
public:
|
||||
struct WriteSectorCallback
|
||||
{
|
||||
virtual ~WriteSectorCallback () { }
|
||||
virtual bool operator() (const BufferPtr §or) = 0;
|
||||
};
|
||||
|
||||
static void Format (WriteSectorCallback &writeSector, uint64 deviceSize, uint32 clusterSize, uint32 sectorSize);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TC_HEADER_Core_FatFormatter
|
||||
47
src/Core/HostDevice.cpp
Normal file
47
src/Core/HostDevice.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
Copyright (c) 2008 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#include "HostDevice.h"
|
||||
#include "Platform/SerializerFactory.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
void HostDevice::Deserialize (shared_ptr <Stream> stream)
|
||||
{
|
||||
Serializer sr (stream);
|
||||
MountPoint = sr.DeserializeWString ("MountPoint");
|
||||
sr.Deserialize ("Name", Name);
|
||||
Path = sr.DeserializeWString ("Path");
|
||||
sr.Deserialize ("Removable", Removable);
|
||||
sr.Deserialize ("Size", Size);
|
||||
sr.Deserialize ("SystemNumber", SystemNumber);
|
||||
|
||||
uint32 partitionCount;
|
||||
sr.Deserialize ("Partitions", partitionCount);
|
||||
for (uint32 i = 0; i < partitionCount; i++)
|
||||
Partitions.push_back (Serializable::DeserializeNew <HostDevice> (stream));
|
||||
}
|
||||
|
||||
void HostDevice::Serialize (shared_ptr <Stream> stream) const
|
||||
{
|
||||
Serializable::Serialize (stream);
|
||||
Serializer sr (stream);
|
||||
sr.Serialize ("MountPoint", wstring (MountPoint));
|
||||
sr.Serialize ("Name", Name);
|
||||
sr.Serialize ("Path", wstring (Path));
|
||||
sr.Serialize ("Removable", Removable);
|
||||
sr.Serialize ("Size", Size);
|
||||
sr.Serialize ("SystemNumber", SystemNumber);
|
||||
|
||||
sr.Serialize ("Partitions", (uint32) Partitions.size());
|
||||
foreach_ref (const HostDevice &partition, Partitions)
|
||||
partition.Serialize (stream);
|
||||
}
|
||||
|
||||
TC_SERIALIZER_FACTORY_ADD_CLASS (HostDevice);
|
||||
}
|
||||
45
src/Core/HostDevice.h
Normal file
45
src/Core/HostDevice.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
Copyright (c) 2008 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#ifndef TC_HEADER_Core_HostDevice
|
||||
#define TC_HEADER_Core_HostDevice
|
||||
|
||||
#include "Platform/Platform.h"
|
||||
#include "Platform/Serializable.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
struct HostDevice;
|
||||
typedef list < shared_ptr <HostDevice> > HostDeviceList;
|
||||
|
||||
struct HostDevice : public Serializable
|
||||
{
|
||||
HostDevice ()
|
||||
: Removable (false),
|
||||
Size (0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~HostDevice ()
|
||||
{
|
||||
}
|
||||
|
||||
TC_SERIALIZABLE (HostDevice);
|
||||
|
||||
DirectoryPath MountPoint;
|
||||
wstring Name;
|
||||
DevicePath Path;
|
||||
bool Removable;
|
||||
uint64 Size;
|
||||
uint32 SystemNumber;
|
||||
|
||||
HostDeviceList Partitions;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TC_HEADER_Core_HostDevice
|
||||
129
src/Core/MountOptions.cpp
Normal file
129
src/Core/MountOptions.cpp
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
Copyright (c) 2008 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#include "MountOptions.h"
|
||||
#include "Platform/MemoryStream.h"
|
||||
#include "Platform/SerializerFactory.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
void MountOptions::CopyFrom (const MountOptions &other)
|
||||
{
|
||||
#define TC_CLONE(NAME) NAME = other.NAME
|
||||
#define TC_CLONE_SHARED(TYPE,NAME) NAME = other.NAME ? make_shared <TYPE> (*other.NAME) : shared_ptr <TYPE> ()
|
||||
|
||||
TC_CLONE (CachePassword);
|
||||
TC_CLONE (FilesystemOptions);
|
||||
TC_CLONE (FilesystemType);
|
||||
TC_CLONE_SHARED (KeyfileList, Keyfiles);
|
||||
TC_CLONE_SHARED (DirectoryPath, MountPoint);
|
||||
TC_CLONE (NoFilesystem);
|
||||
TC_CLONE (NoHardwareCrypto);
|
||||
TC_CLONE (NoKernelCrypto);
|
||||
TC_CLONE_SHARED (VolumePassword, Password);
|
||||
TC_CLONE_SHARED (VolumePath, Path);
|
||||
TC_CLONE (PartitionInSystemEncryptionScope);
|
||||
TC_CLONE (PreserveTimestamps);
|
||||
TC_CLONE (Protection);
|
||||
TC_CLONE_SHARED (VolumePassword, ProtectionPassword);
|
||||
TC_CLONE_SHARED (KeyfileList, ProtectionKeyfiles);
|
||||
TC_CLONE (Removable);
|
||||
TC_CLONE (SharedAccessAllowed);
|
||||
TC_CLONE (SlotNumber);
|
||||
TC_CLONE (UseBackupHeaders);
|
||||
}
|
||||
|
||||
void MountOptions::Deserialize (shared_ptr <Stream> stream)
|
||||
{
|
||||
Serializer sr (stream);
|
||||
|
||||
sr.Deserialize ("CachePassword", CachePassword);
|
||||
sr.Deserialize ("FilesystemOptions", FilesystemOptions);
|
||||
sr.Deserialize ("FilesystemType", FilesystemType);
|
||||
|
||||
Keyfiles = Keyfile::DeserializeList (stream, "Keyfiles");
|
||||
|
||||
if (!sr.DeserializeBool ("MountPointNull"))
|
||||
MountPoint.reset (new DirectoryPath (sr.DeserializeWString ("MountPoint")));
|
||||
else
|
||||
MountPoint.reset();
|
||||
|
||||
sr.Deserialize ("NoFilesystem", NoFilesystem);
|
||||
sr.Deserialize ("NoHardwareCrypto", NoHardwareCrypto);
|
||||
sr.Deserialize ("NoKernelCrypto", NoKernelCrypto);
|
||||
|
||||
if (!sr.DeserializeBool ("PasswordNull"))
|
||||
Password = Serializable::DeserializeNew <VolumePassword> (stream);
|
||||
else
|
||||
Password.reset();
|
||||
|
||||
if (!sr.DeserializeBool ("PathNull"))
|
||||
Path.reset (new VolumePath (sr.DeserializeWString ("Path")));
|
||||
else
|
||||
Path.reset();
|
||||
|
||||
sr.Deserialize ("PartitionInSystemEncryptionScope", PartitionInSystemEncryptionScope);
|
||||
sr.Deserialize ("PreserveTimestamps", PreserveTimestamps);
|
||||
|
||||
Protection = static_cast <VolumeProtection::Enum> (sr.DeserializeInt32 ("Protection"));
|
||||
|
||||
if (!sr.DeserializeBool ("ProtectionPasswordNull"))
|
||||
ProtectionPassword = Serializable::DeserializeNew <VolumePassword> (stream);
|
||||
else
|
||||
ProtectionPassword.reset();
|
||||
|
||||
ProtectionKeyfiles = Keyfile::DeserializeList (stream, "ProtectionKeyfiles");
|
||||
sr.Deserialize ("Removable", Removable);
|
||||
sr.Deserialize ("SharedAccessAllowed", SharedAccessAllowed);
|
||||
sr.Deserialize ("SlotNumber", SlotNumber);
|
||||
sr.Deserialize ("UseBackupHeaders", UseBackupHeaders);
|
||||
}
|
||||
|
||||
void MountOptions::Serialize (shared_ptr <Stream> stream) const
|
||||
{
|
||||
Serializable::Serialize (stream);
|
||||
Serializer sr (stream);
|
||||
|
||||
sr.Serialize ("CachePassword", CachePassword);
|
||||
sr.Serialize ("FilesystemOptions", FilesystemOptions);
|
||||
sr.Serialize ("FilesystemType", FilesystemType);
|
||||
Keyfile::SerializeList (stream, "Keyfiles", Keyfiles);
|
||||
|
||||
sr.Serialize ("MountPointNull", MountPoint == nullptr);
|
||||
if (MountPoint)
|
||||
sr.Serialize ("MountPoint", wstring (*MountPoint));
|
||||
|
||||
sr.Serialize ("NoFilesystem", NoFilesystem);
|
||||
sr.Serialize ("NoHardwareCrypto", NoHardwareCrypto);
|
||||
sr.Serialize ("NoKernelCrypto", NoKernelCrypto);
|
||||
|
||||
sr.Serialize ("PasswordNull", Password == nullptr);
|
||||
if (Password)
|
||||
Password->Serialize (stream);
|
||||
|
||||
sr.Serialize ("PathNull", Path == nullptr);
|
||||
if (Path)
|
||||
sr.Serialize ("Path", wstring (*Path));
|
||||
|
||||
sr.Serialize ("PartitionInSystemEncryptionScope", PartitionInSystemEncryptionScope);
|
||||
sr.Serialize ("PreserveTimestamps", PreserveTimestamps);
|
||||
sr.Serialize ("Protection", static_cast <uint32> (Protection));
|
||||
|
||||
sr.Serialize ("ProtectionPasswordNull", ProtectionPassword == nullptr);
|
||||
if (ProtectionPassword)
|
||||
ProtectionPassword->Serialize (stream);
|
||||
|
||||
Keyfile::SerializeList (stream, "ProtectionKeyfiles", ProtectionKeyfiles);
|
||||
sr.Serialize ("Removable", Removable);
|
||||
sr.Serialize ("SharedAccessAllowed", SharedAccessAllowed);
|
||||
sr.Serialize ("SlotNumber", SlotNumber);
|
||||
sr.Serialize ("UseBackupHeaders", UseBackupHeaders);
|
||||
}
|
||||
|
||||
TC_SERIALIZER_FACTORY_ADD_CLASS (MountOptions);
|
||||
}
|
||||
70
src/Core/MountOptions.h
Normal file
70
src/Core/MountOptions.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
Copyright (c) 2008 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#ifndef TC_HEADER_Core_MountOptions
|
||||
#define TC_HEADER_Core_MountOptions
|
||||
|
||||
#include "Platform/Serializable.h"
|
||||
#include "Volume/Keyfile.h"
|
||||
#include "Volume/Volume.h"
|
||||
#include "Volume/VolumeSlot.h"
|
||||
#include "Volume/VolumePassword.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
struct MountOptions : public Serializable
|
||||
{
|
||||
MountOptions ()
|
||||
:
|
||||
CachePassword (false),
|
||||
NoFilesystem (false),
|
||||
NoHardwareCrypto (false),
|
||||
NoKernelCrypto (false),
|
||||
PartitionInSystemEncryptionScope (false),
|
||||
PreserveTimestamps (true),
|
||||
Protection (VolumeProtection::None),
|
||||
Removable (false),
|
||||
SharedAccessAllowed (false),
|
||||
SlotNumber (0),
|
||||
UseBackupHeaders (false)
|
||||
{
|
||||
}
|
||||
|
||||
MountOptions (const MountOptions &other) { CopyFrom (other); }
|
||||
virtual ~MountOptions () { }
|
||||
|
||||
MountOptions &operator= (const MountOptions &other) { CopyFrom (other); return *this; }
|
||||
|
||||
TC_SERIALIZABLE (MountOptions);
|
||||
|
||||
bool CachePassword;
|
||||
wstring FilesystemOptions;
|
||||
wstring FilesystemType;
|
||||
shared_ptr <KeyfileList> Keyfiles;
|
||||
shared_ptr <DirectoryPath> MountPoint;
|
||||
bool NoFilesystem;
|
||||
bool NoHardwareCrypto;
|
||||
bool NoKernelCrypto;
|
||||
shared_ptr <VolumePassword> Password;
|
||||
bool PartitionInSystemEncryptionScope;
|
||||
shared_ptr <VolumePath> Path;
|
||||
bool PreserveTimestamps;
|
||||
VolumeProtection::Enum Protection;
|
||||
shared_ptr <VolumePassword> ProtectionPassword;
|
||||
shared_ptr <KeyfileList> ProtectionKeyfiles;
|
||||
bool Removable;
|
||||
bool SharedAccessAllowed;
|
||||
VolumeSlotNumber SlotNumber;
|
||||
bool UseBackupHeaders;
|
||||
|
||||
protected:
|
||||
void CopyFrom (const MountOptions &other);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TC_HEADER_Core_MountOptions
|
||||
213
src/Core/RandomNumberGenerator.cpp
Normal file
213
src/Core/RandomNumberGenerator.cpp
Normal file
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
Copyright (c) 2008-2009 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#ifndef TC_WINDOWS
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include "RandomNumberGenerator.h"
|
||||
#include "Volume/Crc32.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
void RandomNumberGenerator::AddSystemDataToPool (bool fast)
|
||||
{
|
||||
SecureBuffer buffer (PoolSize);
|
||||
|
||||
#ifdef TC_WINDOWS
|
||||
#ifndef DEBUG
|
||||
throw NotImplemented (SRC_POS);
|
||||
#endif
|
||||
#else
|
||||
int urandom = open ("/dev/urandom", O_RDONLY);
|
||||
throw_sys_sub_if (urandom == -1, L"/dev/urandom");
|
||||
finally_do_arg (int, urandom, { close (finally_arg); });
|
||||
|
||||
throw_sys_sub_if (read (urandom, buffer, buffer.Size()) == -1, L"/dev/urandom");
|
||||
AddToPool (buffer);
|
||||
|
||||
if (!fast)
|
||||
{
|
||||
// Read all bytes available in /dev/random up to buffer size
|
||||
int random = open ("/dev/random", O_RDONLY | O_NONBLOCK);
|
||||
throw_sys_sub_if (random == -1, L"/dev/random");
|
||||
finally_do_arg (int, random, { close (finally_arg); });
|
||||
|
||||
throw_sys_sub_if (read (random, buffer, buffer.Size()) == -1 && errno != EAGAIN, L"/dev/random");
|
||||
AddToPool (buffer);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void RandomNumberGenerator::AddToPool (const ConstBufferPtr &data)
|
||||
{
|
||||
if (!Running)
|
||||
throw NotInitialized (SRC_POS);
|
||||
|
||||
ScopeLock lock (AccessMutex);
|
||||
|
||||
for (size_t i = 0; i < data.Size(); ++i)
|
||||
{
|
||||
Pool[WriteOffset++] += data[i];
|
||||
|
||||
if (WriteOffset >= PoolSize)
|
||||
WriteOffset = 0;
|
||||
|
||||
if (++BytesAddedSincePoolHashMix >= MaxBytesAddedBeforePoolHashMix)
|
||||
HashMixPool();
|
||||
}
|
||||
}
|
||||
|
||||
void RandomNumberGenerator::GetData (const BufferPtr &buffer, bool fast)
|
||||
{
|
||||
if (!Running)
|
||||
throw NotInitialized (SRC_POS);
|
||||
|
||||
if (buffer.Size() > PoolSize)
|
||||
throw ParameterIncorrect (SRC_POS);
|
||||
|
||||
ScopeLock lock (AccessMutex);
|
||||
|
||||
// Poll system for data
|
||||
AddSystemDataToPool (fast);
|
||||
HashMixPool();
|
||||
|
||||
// Transfer bytes from pool to output buffer
|
||||
for (size_t i = 0; i < buffer.Size(); ++i)
|
||||
{
|
||||
buffer[i] += Pool[ReadOffset++];
|
||||
|
||||
if (ReadOffset >= PoolSize)
|
||||
ReadOffset = 0;
|
||||
}
|
||||
|
||||
// Invert and mix the pool
|
||||
for (size_t i = 0; i < Pool.Size(); ++i)
|
||||
{
|
||||
Pool[i] = ~Pool[i];
|
||||
}
|
||||
|
||||
AddSystemDataToPool (true);
|
||||
HashMixPool();
|
||||
|
||||
// XOR the current pool content into the output buffer to prevent pool state leaks
|
||||
for (size_t i = 0; i < buffer.Size(); ++i)
|
||||
{
|
||||
buffer[i] ^= Pool[ReadOffset++];
|
||||
|
||||
if (ReadOffset >= PoolSize)
|
||||
ReadOffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
shared_ptr <Hash> RandomNumberGenerator::GetHash ()
|
||||
{
|
||||
ScopeLock lock (AccessMutex);
|
||||
return PoolHash;
|
||||
}
|
||||
|
||||
void RandomNumberGenerator::HashMixPool ()
|
||||
{
|
||||
BytesAddedSincePoolHashMix = 0;
|
||||
|
||||
for (size_t poolPos = 0; poolPos < Pool.Size(); )
|
||||
{
|
||||
// Compute the message digest of the entire pool using the selected hash function
|
||||
SecureBuffer digest (PoolHash->GetDigestSize());
|
||||
PoolHash->ProcessData (Pool);
|
||||
PoolHash->GetDigest (digest);
|
||||
|
||||
// Add the message digest to the pool
|
||||
for (size_t digestPos = 0; digestPos < digest.Size() && poolPos < Pool.Size(); ++digestPos)
|
||||
{
|
||||
Pool[poolPos++] += digest[digestPos];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RandomNumberGenerator::SetHash (shared_ptr <Hash> hash)
|
||||
{
|
||||
ScopeLock lock (AccessMutex);
|
||||
PoolHash = hash;
|
||||
}
|
||||
|
||||
void RandomNumberGenerator::Start ()
|
||||
{
|
||||
ScopeLock lock (AccessMutex);
|
||||
|
||||
if (IsRunning())
|
||||
return;
|
||||
|
||||
BytesAddedSincePoolHashMix = 0;
|
||||
ReadOffset = 0;
|
||||
WriteOffset = 0;
|
||||
Running = true;
|
||||
EnrichedByUser = false;
|
||||
|
||||
Pool.Allocate (PoolSize);
|
||||
Test();
|
||||
|
||||
if (!PoolHash)
|
||||
{
|
||||
// First hash algorithm is the default one
|
||||
PoolHash = Hash::GetAvailableAlgorithms().front();
|
||||
}
|
||||
|
||||
AddSystemDataToPool (true);
|
||||
}
|
||||
|
||||
void RandomNumberGenerator::Stop ()
|
||||
{
|
||||
ScopeLock lock (AccessMutex);
|
||||
|
||||
if (Pool.IsAllocated())
|
||||
Pool.Free ();
|
||||
|
||||
PoolHash.reset();
|
||||
|
||||
EnrichedByUser = false;
|
||||
Running = false;
|
||||
}
|
||||
|
||||
void RandomNumberGenerator::Test ()
|
||||
{
|
||||
shared_ptr <Hash> origPoolHash = PoolHash;
|
||||
PoolHash.reset (new Ripemd160());
|
||||
|
||||
Pool.Zero();
|
||||
Buffer buffer (1);
|
||||
for (size_t i = 0; i < PoolSize * 10; ++i)
|
||||
{
|
||||
buffer[0] = (byte) i;
|
||||
AddToPool (buffer);
|
||||
}
|
||||
|
||||
if (Crc32::ProcessBuffer (Pool) != 0x2de46d17)
|
||||
throw TestFailed (SRC_POS);
|
||||
|
||||
buffer.Allocate (PoolSize);
|
||||
buffer.CopyFrom (PeekPool());
|
||||
AddToPool (buffer);
|
||||
|
||||
if (Crc32::ProcessBuffer (Pool) != 0xcb88e019)
|
||||
throw TestFailed (SRC_POS);
|
||||
|
||||
PoolHash = origPoolHash;
|
||||
}
|
||||
|
||||
Mutex RandomNumberGenerator::AccessMutex;
|
||||
size_t RandomNumberGenerator::BytesAddedSincePoolHashMix;
|
||||
bool RandomNumberGenerator::EnrichedByUser;
|
||||
SecureBuffer RandomNumberGenerator::Pool;
|
||||
shared_ptr <Hash> RandomNumberGenerator::PoolHash;
|
||||
size_t RandomNumberGenerator::ReadOffset;
|
||||
bool RandomNumberGenerator::Running = false;
|
||||
size_t RandomNumberGenerator::WriteOffset;
|
||||
}
|
||||
55
src/Core/RandomNumberGenerator.h
Normal file
55
src/Core/RandomNumberGenerator.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
Copyright (c) 2008-2009 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#ifndef TC_HEADER_Core_RandomNumberGenerator
|
||||
#define TC_HEADER_Core_RandomNumberGenerator
|
||||
|
||||
#include "Platform/Platform.h"
|
||||
#include "Volume/Hash.h"
|
||||
#include "Common/Random.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
class RandomNumberGenerator
|
||||
{
|
||||
public:
|
||||
static void AddToPool (const ConstBufferPtr &buffer);
|
||||
static void GetData (const BufferPtr &buffer) { GetData (buffer, false); }
|
||||
static void GetDataFast (const BufferPtr &buffer) { GetData (buffer, true); }
|
||||
static shared_ptr <Hash> GetHash ();
|
||||
static bool IsEnrichedByUser () { return EnrichedByUser; }
|
||||
static bool IsRunning () { return Running; }
|
||||
static ConstBufferPtr PeekPool () { return Pool; }
|
||||
static void SetEnrichedByUserStatus (bool enriched) { EnrichedByUser = enriched; }
|
||||
static void SetHash (shared_ptr <Hash> hash);
|
||||
static void Start ();
|
||||
static void Stop ();
|
||||
|
||||
static const size_t PoolSize = RNG_POOL_SIZE;
|
||||
|
||||
protected:
|
||||
static void AddSystemDataToPool (bool fast);
|
||||
static void GetData (const BufferPtr &buffer, bool fast);
|
||||
static void HashMixPool ();
|
||||
static void Test ();
|
||||
RandomNumberGenerator ();
|
||||
|
||||
static const size_t MaxBytesAddedBeforePoolHashMix = RANDMIX_BYTE_INTERVAL;
|
||||
|
||||
static Mutex AccessMutex;
|
||||
static size_t BytesAddedSincePoolHashMix;
|
||||
static bool EnrichedByUser;
|
||||
static SecureBuffer Pool;
|
||||
static shared_ptr <Hash> PoolHash;
|
||||
static size_t ReadOffset;
|
||||
static bool Running;
|
||||
static size_t WriteOffset;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TC_HEADER_Core_RandomNumberGenerator
|
||||
544
src/Core/Unix/CoreService.cpp
Normal file
544
src/Core/Unix/CoreService.cpp
Normal file
@@ -0,0 +1,544 @@
|
||||
/*
|
||||
Copyright (c) 2008-2010 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#include "CoreService.h"
|
||||
#include <fcntl.h>
|
||||
#include <sys/wait.h>
|
||||
#include "Platform/FileStream.h"
|
||||
#include "Platform/MemoryStream.h"
|
||||
#include "Platform/Serializable.h"
|
||||
#include "Platform/SystemLog.h"
|
||||
#include "Platform/Thread.h"
|
||||
#include "Platform/Unix/Poller.h"
|
||||
#include "Core/Core.h"
|
||||
#include "CoreUnix.h"
|
||||
#include "CoreServiceRequest.h"
|
||||
#include "CoreServiceResponse.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
template <class T>
|
||||
auto_ptr <T> CoreService::GetResponse ()
|
||||
{
|
||||
auto_ptr <Serializable> deserializedObject (Serializable::DeserializeNew (ServiceOutputStream));
|
||||
|
||||
Exception *deserializedException = dynamic_cast <Exception*> (deserializedObject.get());
|
||||
if (deserializedException)
|
||||
deserializedException->Throw();
|
||||
|
||||
if (dynamic_cast <T *> (deserializedObject.get()) == nullptr)
|
||||
throw ParameterIncorrect (SRC_POS);
|
||||
|
||||
return auto_ptr <T> (dynamic_cast <T *> (deserializedObject.release()));
|
||||
}
|
||||
|
||||
void CoreService::ProcessElevatedRequests ()
|
||||
{
|
||||
int pid = fork();
|
||||
throw_sys_if (pid == -1);
|
||||
if (pid == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
int f = open ("/dev/null", 0);
|
||||
throw_sys_sub_if (f == -1, "/dev/null");
|
||||
throw_sys_if (dup2 (f, STDERR_FILENO) == -1);
|
||||
|
||||
// Wait for sync code
|
||||
while (true)
|
||||
{
|
||||
byte b;
|
||||
throw_sys_if (read (STDIN_FILENO, &b, 1) != 1);
|
||||
if (b != 0x00)
|
||||
continue;
|
||||
|
||||
throw_sys_if (read (STDIN_FILENO, &b, 1) != 1);
|
||||
if (b != 0x11)
|
||||
continue;
|
||||
|
||||
throw_sys_if (read (STDIN_FILENO, &b, 1) != 1);
|
||||
if (b == 0x22)
|
||||
break;
|
||||
}
|
||||
|
||||
ElevatedPrivileges = true;
|
||||
ProcessRequests (STDIN_FILENO, STDOUT_FILENO);
|
||||
_exit (0);
|
||||
}
|
||||
catch (exception &e)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
SystemLog::WriteException (e);
|
||||
#endif
|
||||
}
|
||||
catch (...) { }
|
||||
_exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
void CoreService::ProcessRequests (int inputFD, int outputFD)
|
||||
{
|
||||
try
|
||||
{
|
||||
Core = CoreDirect;
|
||||
|
||||
shared_ptr <Stream> inputStream (new FileStream (inputFD != -1 ? inputFD : InputPipe->GetReadFD()));
|
||||
shared_ptr <Stream> outputStream (new FileStream (outputFD != -1 ? outputFD : OutputPipe->GetWriteFD()));
|
||||
|
||||
while (true)
|
||||
{
|
||||
shared_ptr <CoreServiceRequest> request = Serializable::DeserializeNew <CoreServiceRequest> (inputStream);
|
||||
|
||||
try
|
||||
{
|
||||
// ExitRequest
|
||||
if (dynamic_cast <ExitRequest*> (request.get()) != nullptr)
|
||||
{
|
||||
if (ElevatedServiceAvailable)
|
||||
request->Serialize (ServiceInputStream);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ElevatedPrivileges && request->ElevateUserPrivileges)
|
||||
{
|
||||
if (!ElevatedServiceAvailable)
|
||||
{
|
||||
finally_do_arg (string *, &request->AdminPassword, { StringConverter::Erase (*finally_arg); });
|
||||
|
||||
CoreService::StartElevated (*request);
|
||||
ElevatedServiceAvailable = true;
|
||||
}
|
||||
|
||||
request->Serialize (ServiceInputStream);
|
||||
GetResponse <Serializable>()->Serialize (outputStream);
|
||||
continue;
|
||||
}
|
||||
|
||||
// CheckFilesystemRequest
|
||||
CheckFilesystemRequest *checkRequest = dynamic_cast <CheckFilesystemRequest*> (request.get());
|
||||
if (checkRequest)
|
||||
{
|
||||
Core->CheckFilesystem (checkRequest->MountedVolumeInfo, checkRequest->Repair);
|
||||
|
||||
CheckFilesystemResponse().Serialize (outputStream);
|
||||
continue;
|
||||
}
|
||||
|
||||
// DismountFilesystemRequest
|
||||
DismountFilesystemRequest *dismountFsRequest = dynamic_cast <DismountFilesystemRequest*> (request.get());
|
||||
if (dismountFsRequest)
|
||||
{
|
||||
Core->DismountFilesystem (dismountFsRequest->MountPoint, dismountFsRequest->Force);
|
||||
|
||||
DismountFilesystemResponse().Serialize (outputStream);
|
||||
continue;
|
||||
}
|
||||
|
||||
// DismountVolumeRequest
|
||||
DismountVolumeRequest *dismountRequest = dynamic_cast <DismountVolumeRequest*> (request.get());
|
||||
if (dismountRequest)
|
||||
{
|
||||
DismountVolumeResponse response;
|
||||
response.DismountedVolumeInfo = Core->DismountVolume (dismountRequest->MountedVolumeInfo, dismountRequest->IgnoreOpenFiles, dismountRequest->SyncVolumeInfo);
|
||||
response.Serialize (outputStream);
|
||||
continue;
|
||||
}
|
||||
|
||||
// GetDeviceSectorSizeRequest
|
||||
GetDeviceSectorSizeRequest *getDeviceSectorSizeRequest = dynamic_cast <GetDeviceSectorSizeRequest*> (request.get());
|
||||
if (getDeviceSectorSizeRequest)
|
||||
{
|
||||
GetDeviceSectorSizeResponse response;
|
||||
response.Size = Core->GetDeviceSectorSize (getDeviceSectorSizeRequest->Path);
|
||||
response.Serialize (outputStream);
|
||||
continue;
|
||||
}
|
||||
|
||||
// GetDeviceSizeRequest
|
||||
GetDeviceSizeRequest *getDeviceSizeRequest = dynamic_cast <GetDeviceSizeRequest*> (request.get());
|
||||
if (getDeviceSizeRequest)
|
||||
{
|
||||
GetDeviceSizeResponse response;
|
||||
response.Size = Core->GetDeviceSize (getDeviceSizeRequest->Path);
|
||||
response.Serialize (outputStream);
|
||||
continue;
|
||||
}
|
||||
|
||||
// GetHostDevicesRequest
|
||||
GetHostDevicesRequest *getHostDevicesRequest = dynamic_cast <GetHostDevicesRequest*> (request.get());
|
||||
if (getHostDevicesRequest)
|
||||
{
|
||||
GetHostDevicesResponse response;
|
||||
response.HostDevices = Core->GetHostDevices (getHostDevicesRequest->PathListOnly);
|
||||
response.Serialize (outputStream);
|
||||
continue;
|
||||
}
|
||||
|
||||
// MountVolumeRequest
|
||||
MountVolumeRequest *mountRequest = dynamic_cast <MountVolumeRequest*> (request.get());
|
||||
if (mountRequest)
|
||||
{
|
||||
MountVolumeResponse (
|
||||
Core->MountVolume (*mountRequest->Options)
|
||||
).Serialize (outputStream);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// SetFileOwnerRequest
|
||||
SetFileOwnerRequest *setFileOwnerRequest = dynamic_cast <SetFileOwnerRequest*> (request.get());
|
||||
if (setFileOwnerRequest)
|
||||
{
|
||||
CoreUnix *coreUnix = dynamic_cast <CoreUnix *> (Core.get());
|
||||
if (!coreUnix)
|
||||
throw ParameterIncorrect (SRC_POS);
|
||||
|
||||
coreUnix->SetFileOwner (setFileOwnerRequest->Path, setFileOwnerRequest->Owner);
|
||||
SetFileOwnerResponse().Serialize (outputStream);
|
||||
continue;
|
||||
}
|
||||
|
||||
throw ParameterIncorrect (SRC_POS);
|
||||
}
|
||||
catch (Exception &e)
|
||||
{
|
||||
e.Serialize (outputStream);
|
||||
}
|
||||
catch (exception &e)
|
||||
{
|
||||
ExternalException (SRC_POS, StringConverter::ToExceptionString (e)).Serialize (outputStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (exception &e)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
SystemLog::WriteException (e);
|
||||
#endif
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void CoreService::RequestCheckFilesystem (shared_ptr <VolumeInfo> mountedVolume, bool repair)
|
||||
{
|
||||
CheckFilesystemRequest request (mountedVolume, repair);
|
||||
SendRequest <CheckFilesystemResponse> (request);
|
||||
}
|
||||
|
||||
void CoreService::RequestDismountFilesystem (const DirectoryPath &mountPoint, bool force)
|
||||
{
|
||||
DismountFilesystemRequest request (mountPoint, force);
|
||||
SendRequest <DismountFilesystemResponse> (request);
|
||||
}
|
||||
|
||||
shared_ptr <VolumeInfo> CoreService::RequestDismountVolume (shared_ptr <VolumeInfo> mountedVolume, bool ignoreOpenFiles, bool syncVolumeInfo)
|
||||
{
|
||||
DismountVolumeRequest request (mountedVolume, ignoreOpenFiles, syncVolumeInfo);
|
||||
return SendRequest <DismountVolumeResponse> (request)->DismountedVolumeInfo;
|
||||
}
|
||||
|
||||
uint32 CoreService::RequestGetDeviceSectorSize (const DevicePath &devicePath)
|
||||
{
|
||||
GetDeviceSectorSizeRequest request (devicePath);
|
||||
return SendRequest <GetDeviceSectorSizeResponse> (request)->Size;
|
||||
}
|
||||
|
||||
uint64 CoreService::RequestGetDeviceSize (const DevicePath &devicePath)
|
||||
{
|
||||
GetDeviceSizeRequest request (devicePath);
|
||||
return SendRequest <GetDeviceSizeResponse> (request)->Size;
|
||||
}
|
||||
|
||||
HostDeviceList CoreService::RequestGetHostDevices (bool pathListOnly)
|
||||
{
|
||||
GetHostDevicesRequest request (pathListOnly);
|
||||
return SendRequest <GetHostDevicesResponse> (request)->HostDevices;
|
||||
}
|
||||
|
||||
shared_ptr <VolumeInfo> CoreService::RequestMountVolume (MountOptions &options)
|
||||
{
|
||||
MountVolumeRequest request (&options);
|
||||
return SendRequest <MountVolumeResponse> (request)->MountedVolumeInfo;
|
||||
}
|
||||
|
||||
void CoreService::RequestSetFileOwner (const FilesystemPath &path, const UserId &owner)
|
||||
{
|
||||
SetFileOwnerRequest request (path, owner);
|
||||
SendRequest <SetFileOwnerResponse> (request);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
auto_ptr <T> CoreService::SendRequest (CoreServiceRequest &request)
|
||||
{
|
||||
static Mutex mutex;
|
||||
ScopeLock lock (mutex);
|
||||
|
||||
if (request.RequiresElevation())
|
||||
{
|
||||
request.ElevateUserPrivileges = true;
|
||||
request.FastElevation = !ElevatedServiceAvailable;
|
||||
request.ApplicationExecutablePath = Core->GetApplicationExecutablePath();
|
||||
|
||||
while (!ElevatedServiceAvailable)
|
||||
{
|
||||
try
|
||||
{
|
||||
request.Serialize (ServiceInputStream);
|
||||
auto_ptr <T> response (GetResponse <T>());
|
||||
ElevatedServiceAvailable = true;
|
||||
return response;
|
||||
}
|
||||
catch (ElevationFailed &e)
|
||||
{
|
||||
if (!request.FastElevation)
|
||||
{
|
||||
ExceptionEventArgs args (e);
|
||||
Core->WarningEvent.Raise (args);
|
||||
}
|
||||
|
||||
request.FastElevation = false;
|
||||
(*AdminPasswordCallback) (request.AdminPassword);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
finally_do_arg (string *, &request.AdminPassword, { StringConverter::Erase (*finally_arg); });
|
||||
|
||||
request.Serialize (ServiceInputStream);
|
||||
return GetResponse <T>();
|
||||
}
|
||||
|
||||
void CoreService::Start ()
|
||||
{
|
||||
InputPipe.reset (new Pipe());
|
||||
OutputPipe.reset (new Pipe());
|
||||
|
||||
int pid = fork();
|
||||
throw_sys_if (pid == -1);
|
||||
|
||||
if (pid == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
ProcessRequests();
|
||||
_exit (0);
|
||||
}
|
||||
catch (...) { }
|
||||
_exit (1);
|
||||
}
|
||||
|
||||
ServiceInputStream = shared_ptr <Stream> (new FileStream (InputPipe->GetWriteFD()));
|
||||
ServiceOutputStream = shared_ptr <Stream> (new FileStream (OutputPipe->GetReadFD()));
|
||||
}
|
||||
|
||||
void CoreService::StartElevated (const CoreServiceRequest &request)
|
||||
{
|
||||
auto_ptr <Pipe> inPipe (new Pipe());
|
||||
auto_ptr <Pipe> outPipe (new Pipe());
|
||||
Pipe errPipe;
|
||||
|
||||
int forkedPid = fork();
|
||||
throw_sys_if (forkedPid == -1);
|
||||
|
||||
if (forkedPid == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
throw_sys_if (dup2 (inPipe->GetReadFD(), STDIN_FILENO) == -1);
|
||||
throw_sys_if (dup2 (outPipe->GetWriteFD(), STDOUT_FILENO) == -1);
|
||||
throw_sys_if (dup2 (errPipe.GetWriteFD(), STDERR_FILENO) == -1);
|
||||
|
||||
string appPath = request.ApplicationExecutablePath;
|
||||
if (appPath.empty())
|
||||
appPath = "truecrypt";
|
||||
|
||||
const char *args[] = { "sudo", "-S", "-p", "", appPath.c_str(), TC_CORE_SERVICE_CMDLINE_OPTION, nullptr };
|
||||
execvp (args[0], ((char* const*) args));
|
||||
throw SystemException (SRC_POS, args[0]);
|
||||
}
|
||||
catch (Exception &)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch (exception &e)
|
||||
{
|
||||
throw ExternalException (SRC_POS, StringConverter::ToExceptionString (e));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
throw UnknownException (SRC_POS);
|
||||
}
|
||||
}
|
||||
catch (Exception &e)
|
||||
{
|
||||
try
|
||||
{
|
||||
shared_ptr <Stream> outputStream (new FileStream (errPipe.GetWriteFD()));
|
||||
e.Serialize (outputStream);
|
||||
}
|
||||
catch (...) { }
|
||||
}
|
||||
|
||||
_exit (1);
|
||||
}
|
||||
|
||||
vector <char> adminPassword (request.AdminPassword.size() + 1);
|
||||
int timeout = 6000;
|
||||
|
||||
if (request.FastElevation)
|
||||
{
|
||||
string dummyPassword = "dummy\n";
|
||||
adminPassword = vector <char> (dummyPassword.size());
|
||||
Memory::Copy (&adminPassword.front(), dummyPassword.c_str(), dummyPassword.size());
|
||||
timeout = 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
Memory::Copy (&adminPassword.front(), request.AdminPassword.c_str(), request.AdminPassword.size());
|
||||
adminPassword[request.AdminPassword.size()] = '\n';
|
||||
}
|
||||
|
||||
if (write (inPipe->GetWriteFD(), &adminPassword.front(), adminPassword.size())) { } // Errors ignored
|
||||
|
||||
Memory::Erase (&adminPassword.front(), adminPassword.size());
|
||||
|
||||
throw_sys_if (fcntl (outPipe->GetReadFD(), F_SETFL, O_NONBLOCK) == -1);
|
||||
throw_sys_if (fcntl (errPipe.GetReadFD(), F_SETFL, O_NONBLOCK) == -1);
|
||||
|
||||
vector <char> buffer (4096), errOutput (4096);
|
||||
buffer.clear ();
|
||||
errOutput.clear ();
|
||||
|
||||
Poller poller (outPipe->GetReadFD(), errPipe.GetReadFD());
|
||||
int status, waitRes;
|
||||
int exitCode = 1;
|
||||
|
||||
try
|
||||
{
|
||||
do
|
||||
{
|
||||
ssize_t bytesRead = 0;
|
||||
foreach (int fd, poller.WaitForData (timeout))
|
||||
{
|
||||
bytesRead = read (fd, &buffer[0], buffer.capacity());
|
||||
if (bytesRead > 0 && fd == errPipe.GetReadFD())
|
||||
{
|
||||
errOutput.insert (errOutput.end(), buffer.begin(), buffer.begin() + bytesRead);
|
||||
|
||||
if (bytesRead > 5 && bytesRead < 80) // Short message captured
|
||||
timeout = 200;
|
||||
}
|
||||
}
|
||||
|
||||
if (bytesRead == 0)
|
||||
{
|
||||
waitRes = waitpid (forkedPid, &status, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
} while ((waitRes = waitpid (forkedPid, &status, WNOHANG)) == 0);
|
||||
}
|
||||
catch (TimeOut&)
|
||||
{
|
||||
if ((waitRes = waitpid (forkedPid, &status, WNOHANG)) == 0)
|
||||
{
|
||||
inPipe->Close();
|
||||
outPipe->Close();
|
||||
errPipe.Close();
|
||||
|
||||
if (request.FastElevation)
|
||||
{
|
||||
// Prevent defunct process
|
||||
struct WaitFunctor : public Functor
|
||||
{
|
||||
WaitFunctor (int pid) : Pid (pid) { }
|
||||
virtual void operator() ()
|
||||
{
|
||||
int status;
|
||||
for (int t = 0; t < 10 && waitpid (Pid, &status, WNOHANG) == 0; t++)
|
||||
Thread::Sleep (1000);
|
||||
}
|
||||
int Pid;
|
||||
};
|
||||
Thread thread;
|
||||
thread.Start (new WaitFunctor (forkedPid));
|
||||
|
||||
throw ElevationFailed (SRC_POS, "sudo", 1, "");
|
||||
}
|
||||
|
||||
waitRes = waitpid (forkedPid, &status, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (!errOutput.empty())
|
||||
{
|
||||
auto_ptr <Serializable> deserializedObject;
|
||||
Exception *deserializedException = nullptr;
|
||||
|
||||
try
|
||||
{
|
||||
shared_ptr <Stream> stream (new MemoryStream (ConstBufferPtr ((byte *) &errOutput[0], errOutput.size())));
|
||||
deserializedObject.reset (Serializable::DeserializeNew (stream));
|
||||
deserializedException = dynamic_cast <Exception*> (deserializedObject.get());
|
||||
}
|
||||
catch (...) { }
|
||||
|
||||
if (deserializedException)
|
||||
deserializedException->Throw();
|
||||
}
|
||||
|
||||
throw_sys_if (waitRes == -1);
|
||||
exitCode = (WIFEXITED (status) ? WEXITSTATUS (status) : 1);
|
||||
if (exitCode != 0)
|
||||
{
|
||||
string strErrOutput;
|
||||
|
||||
if (!errOutput.empty())
|
||||
strErrOutput.insert (strErrOutput.begin(), errOutput.begin(), errOutput.end());
|
||||
|
||||
// sudo may require a tty even if -S is used
|
||||
if (strErrOutput.find (" tty") != string::npos)
|
||||
strErrOutput += "\nTo enable use of 'sudo' by applications without a terminal window, please disable 'requiretty' option in '/etc/sudoers'. Newer versions of sudo automatically determine whether a terminal is required ('requiretty' option is obsolete).";
|
||||
|
||||
throw ElevationFailed (SRC_POS, "sudo", exitCode, strErrOutput);
|
||||
}
|
||||
|
||||
throw_sys_if (fcntl (outPipe->GetReadFD(), F_SETFL, 0) == -1);
|
||||
|
||||
ServiceInputStream = shared_ptr <Stream> (new FileStream (inPipe->GetWriteFD()));
|
||||
ServiceOutputStream = shared_ptr <Stream> (new FileStream (outPipe->GetReadFD()));
|
||||
|
||||
// Send sync code
|
||||
byte sync[] = { 0, 0x11, 0x22 };
|
||||
ServiceInputStream->Write (ConstBufferPtr (sync, array_capacity (sync)));
|
||||
|
||||
AdminInputPipe = inPipe;
|
||||
AdminOutputPipe = outPipe;
|
||||
}
|
||||
|
||||
void CoreService::Stop ()
|
||||
{
|
||||
ExitRequest exitRequest;
|
||||
exitRequest.Serialize (ServiceInputStream);
|
||||
}
|
||||
|
||||
shared_ptr <GetStringFunctor> CoreService::AdminPasswordCallback;
|
||||
|
||||
auto_ptr <Pipe> CoreService::AdminInputPipe;
|
||||
auto_ptr <Pipe> CoreService::AdminOutputPipe;
|
||||
|
||||
auto_ptr <Pipe> CoreService::InputPipe;
|
||||
auto_ptr <Pipe> CoreService::OutputPipe;
|
||||
shared_ptr <Stream> CoreService::ServiceInputStream;
|
||||
shared_ptr <Stream> CoreService::ServiceOutputStream;
|
||||
|
||||
bool CoreService::ElevatedPrivileges = false;
|
||||
bool CoreService::ElevatedServiceAvailable = false;
|
||||
}
|
||||
63
src/Core/Unix/CoreService.h
Normal file
63
src/Core/Unix/CoreService.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
Copyright (c) 2008-2010 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#ifndef TC_HEADER_Core_Unix_CoreService
|
||||
#define TC_HEADER_Core_Unix_CoreService
|
||||
|
||||
#include "CoreServiceRequest.h"
|
||||
#include "Platform/Stream.h"
|
||||
#include "Platform/Unix/Pipe.h"
|
||||
#include "Core/Core.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
// This service facilitates process forking and elevation of user privileges
|
||||
class CoreService
|
||||
{
|
||||
public:
|
||||
static void ProcessElevatedRequests ();
|
||||
static void ProcessRequests (int inputFD = -1, int outputFD = -1);
|
||||
static void RequestCheckFilesystem (shared_ptr <VolumeInfo> mountedVolume, bool repair);
|
||||
static void RequestDismountFilesystem (const DirectoryPath &mountPoint, bool force);
|
||||
static shared_ptr <VolumeInfo> RequestDismountVolume (shared_ptr <VolumeInfo> mountedVolume, bool ignoreOpenFiles = false, bool syncVolumeInfo = false);
|
||||
static uint32 RequestGetDeviceSectorSize (const DevicePath &devicePath);
|
||||
static uint64 RequestGetDeviceSize (const DevicePath &devicePath);
|
||||
static HostDeviceList RequestGetHostDevices (bool pathListOnly);
|
||||
static shared_ptr <VolumeInfo> RequestMountVolume (MountOptions &options);
|
||||
static void RequestSetFileOwner (const FilesystemPath &path, const UserId &owner);
|
||||
static void SetAdminPasswordCallback (shared_ptr <GetStringFunctor> functor) { AdminPasswordCallback = functor; }
|
||||
static void Start ();
|
||||
static void Stop ();
|
||||
|
||||
protected:
|
||||
template <class T> static auto_ptr <T> GetResponse ();
|
||||
template <class T> static auto_ptr <T> SendRequest (CoreServiceRequest &request);
|
||||
static void StartElevated (const CoreServiceRequest &request);
|
||||
|
||||
static shared_ptr <GetStringFunctor> AdminPasswordCallback;
|
||||
|
||||
static auto_ptr <Pipe> AdminInputPipe;
|
||||
static auto_ptr <Pipe> AdminOutputPipe;
|
||||
|
||||
static auto_ptr <Pipe> InputPipe;
|
||||
static auto_ptr <Pipe> OutputPipe;
|
||||
static shared_ptr <Stream> ServiceInputStream;
|
||||
static shared_ptr <Stream> ServiceOutputStream;
|
||||
|
||||
static bool ElevatedPrivileges;
|
||||
static bool ElevatedServiceAvailable;
|
||||
static bool Running;
|
||||
|
||||
private:
|
||||
CoreService ();
|
||||
};
|
||||
|
||||
#define TC_CORE_SERVICE_CMDLINE_OPTION "--core-service"
|
||||
}
|
||||
|
||||
#endif // TC_HEADER_Core_Unix_CoreService
|
||||
152
src/Core/Unix/CoreServiceProxy.h
Normal file
152
src/Core/Unix/CoreServiceProxy.h
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
Copyright (c) 2008-2010 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#ifndef TC_HEADER_Core_Windows_CoreServiceProxy
|
||||
#define TC_HEADER_Core_Windows_CoreServiceProxy
|
||||
|
||||
#include "CoreService.h"
|
||||
#include "Volume/VolumePasswordCache.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
template <class T>
|
||||
class CoreServiceProxy : public T
|
||||
{
|
||||
public:
|
||||
CoreServiceProxy () { }
|
||||
virtual ~CoreServiceProxy () { }
|
||||
|
||||
virtual void CheckFilesystem (shared_ptr <VolumeInfo> mountedVolume, bool repair) const
|
||||
{
|
||||
CoreService::RequestCheckFilesystem (mountedVolume, repair);
|
||||
}
|
||||
|
||||
virtual void DismountFilesystem (const DirectoryPath &mountPoint, bool force) const
|
||||
{
|
||||
CoreService::RequestDismountFilesystem (mountPoint, force);
|
||||
}
|
||||
|
||||
virtual shared_ptr <VolumeInfo> DismountVolume (shared_ptr <VolumeInfo> mountedVolume, bool ignoreOpenFiles = false, bool syncVolumeInfo = false)
|
||||
{
|
||||
shared_ptr <VolumeInfo> dismountedVolumeInfo = CoreService::RequestDismountVolume (mountedVolume, ignoreOpenFiles, syncVolumeInfo);
|
||||
|
||||
VolumeEventArgs eventArgs (dismountedVolumeInfo);
|
||||
T::VolumeDismountedEvent.Raise (eventArgs);
|
||||
|
||||
return dismountedVolumeInfo;
|
||||
}
|
||||
|
||||
virtual uint32 GetDeviceSectorSize (const DevicePath &devicePath) const
|
||||
{
|
||||
return CoreService::RequestGetDeviceSectorSize (devicePath);
|
||||
}
|
||||
|
||||
virtual uint64 GetDeviceSize (const DevicePath &devicePath) const
|
||||
{
|
||||
return CoreService::RequestGetDeviceSize (devicePath);
|
||||
}
|
||||
|
||||
#ifndef TC_LINUX
|
||||
virtual HostDeviceList GetHostDevices (bool pathListOnly = false) const
|
||||
{
|
||||
if (pathListOnly)
|
||||
return T::GetHostDevices (pathListOnly);
|
||||
else
|
||||
return CoreService::RequestGetHostDevices (pathListOnly);
|
||||
}
|
||||
#endif
|
||||
virtual bool IsPasswordCacheEmpty () const { return VolumePasswordCache::IsEmpty(); }
|
||||
|
||||
virtual shared_ptr <VolumeInfo> MountVolume (MountOptions &options)
|
||||
{
|
||||
shared_ptr <VolumeInfo> mountedVolume;
|
||||
|
||||
if (!VolumePasswordCache::IsEmpty()
|
||||
&& (!options.Password || options.Password->IsEmpty())
|
||||
&& (!options.Keyfiles || options.Keyfiles->empty()))
|
||||
{
|
||||
finally_do_arg (MountOptions*, &options, { if (finally_arg->Password) finally_arg->Password.reset(); });
|
||||
|
||||
PasswordIncorrect passwordException;
|
||||
foreach (shared_ptr <VolumePassword> password, VolumePasswordCache::GetPasswords())
|
||||
{
|
||||
try
|
||||
{
|
||||
options.Password = password;
|
||||
mountedVolume = CoreService::RequestMountVolume (options);
|
||||
break;
|
||||
}
|
||||
catch (PasswordIncorrect &e)
|
||||
{
|
||||
passwordException = e;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mountedVolume)
|
||||
passwordException.Throw();
|
||||
}
|
||||
else
|
||||
{
|
||||
MountOptions newOptions = options;
|
||||
|
||||
newOptions.Password = Keyfile::ApplyListToPassword (options.Keyfiles, options.Password);
|
||||
if (newOptions.Keyfiles)
|
||||
newOptions.Keyfiles->clear();
|
||||
|
||||
newOptions.ProtectionPassword = Keyfile::ApplyListToPassword (options.ProtectionKeyfiles, options.ProtectionPassword);
|
||||
if (newOptions.ProtectionKeyfiles)
|
||||
newOptions.ProtectionKeyfiles->clear();
|
||||
|
||||
try
|
||||
{
|
||||
mountedVolume = CoreService::RequestMountVolume (newOptions);
|
||||
}
|
||||
catch (ProtectionPasswordIncorrect &e)
|
||||
{
|
||||
if (options.ProtectionKeyfiles && !options.ProtectionKeyfiles->empty())
|
||||
throw ProtectionPasswordKeyfilesIncorrect (e.what());
|
||||
throw;
|
||||
}
|
||||
catch (PasswordIncorrect &e)
|
||||
{
|
||||
if (options.Keyfiles && !options.Keyfiles->empty())
|
||||
throw PasswordKeyfilesIncorrect (e.what());
|
||||
throw;
|
||||
}
|
||||
|
||||
if (options.CachePassword
|
||||
&& ((options.Password && !options.Password->IsEmpty()) || (options.Keyfiles && !options.Keyfiles->empty())))
|
||||
{
|
||||
VolumePasswordCache::Store (*Keyfile::ApplyListToPassword (options.Keyfiles, options.Password));
|
||||
}
|
||||
}
|
||||
|
||||
VolumeEventArgs eventArgs (mountedVolume);
|
||||
T::VolumeMountedEvent.Raise (eventArgs);
|
||||
|
||||
return mountedVolume;
|
||||
}
|
||||
|
||||
virtual void SetAdminPasswordCallback (shared_ptr <GetStringFunctor> functor)
|
||||
{
|
||||
CoreService::SetAdminPasswordCallback (functor);
|
||||
}
|
||||
|
||||
virtual void SetFileOwner (const FilesystemPath &path, const UserId &owner) const
|
||||
{
|
||||
CoreService::RequestSetFileOwner (path, owner);
|
||||
}
|
||||
|
||||
virtual void WipePasswordCache () const
|
||||
{
|
||||
VolumePasswordCache::Clear();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TC_HEADER_Core_Windows_CoreServiceProxy
|
||||
269
src/Core/Unix/CoreServiceRequest.cpp
Normal file
269
src/Core/Unix/CoreServiceRequest.cpp
Normal file
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
Copyright (c) 2008-2010 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include "CoreServiceRequest.h"
|
||||
#include "Platform/SerializerFactory.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
void CoreServiceRequest::Deserialize (shared_ptr <Stream> stream)
|
||||
{
|
||||
Serializer sr (stream);
|
||||
sr.Deserialize ("AdminPassword", AdminPassword);
|
||||
ApplicationExecutablePath = sr.DeserializeWString ("ApplicationExecutablePath");
|
||||
sr.Deserialize ("ElevateUserPrivileges", ElevateUserPrivileges);
|
||||
sr.Deserialize ("FastElevation", FastElevation);
|
||||
}
|
||||
|
||||
void CoreServiceRequest::Serialize (shared_ptr <Stream> stream) const
|
||||
{
|
||||
Serializable::Serialize (stream);
|
||||
Serializer sr (stream);
|
||||
sr.Serialize ("AdminPassword", AdminPassword);
|
||||
sr.Serialize ("ApplicationExecutablePath", wstring (ApplicationExecutablePath));
|
||||
sr.Serialize ("ElevateUserPrivileges", ElevateUserPrivileges);
|
||||
sr.Serialize ("FastElevation", FastElevation);
|
||||
}
|
||||
|
||||
// CheckFilesystemRequest
|
||||
void CheckFilesystemRequest::Deserialize (shared_ptr <Stream> stream)
|
||||
{
|
||||
CoreServiceRequest::Deserialize (stream);
|
||||
Serializer sr (stream);
|
||||
MountedVolumeInfo = Serializable::DeserializeNew <VolumeInfo> (stream);
|
||||
sr.Deserialize ("Repair", Repair);
|
||||
}
|
||||
|
||||
bool CheckFilesystemRequest::RequiresElevation () const
|
||||
{
|
||||
#ifdef TC_MACOSX
|
||||
return false;
|
||||
#endif
|
||||
return !Core->HasAdminPrivileges();
|
||||
}
|
||||
|
||||
void CheckFilesystemRequest::Serialize (shared_ptr <Stream> stream) const
|
||||
{
|
||||
CoreServiceRequest::Serialize (stream);
|
||||
Serializer sr (stream);
|
||||
MountedVolumeInfo->Serialize (stream);
|
||||
sr.Serialize ("Repair", Repair);
|
||||
}
|
||||
|
||||
// DismountFilesystemRequest
|
||||
void DismountFilesystemRequest::Deserialize (shared_ptr <Stream> stream)
|
||||
{
|
||||
CoreServiceRequest::Deserialize (stream);
|
||||
Serializer sr (stream);
|
||||
sr.Deserialize ("Force", Force);
|
||||
MountPoint = sr.DeserializeWString ("MountPoint");
|
||||
}
|
||||
|
||||
bool DismountFilesystemRequest::RequiresElevation () const
|
||||
{
|
||||
return !Core->HasAdminPrivileges();
|
||||
}
|
||||
|
||||
void DismountFilesystemRequest::Serialize (shared_ptr <Stream> stream) const
|
||||
{
|
||||
CoreServiceRequest::Serialize (stream);
|
||||
Serializer sr (stream);
|
||||
sr.Serialize ("Force", Force);
|
||||
sr.Serialize ("MountPoint", wstring (MountPoint));
|
||||
}
|
||||
|
||||
// DismountVolumeRequest
|
||||
void DismountVolumeRequest::Deserialize (shared_ptr <Stream> stream)
|
||||
{
|
||||
CoreServiceRequest::Deserialize (stream);
|
||||
Serializer sr (stream);
|
||||
sr.Deserialize ("IgnoreOpenFiles", IgnoreOpenFiles);
|
||||
sr.Deserialize ("SyncVolumeInfo", SyncVolumeInfo);
|
||||
MountedVolumeInfo = Serializable::DeserializeNew <VolumeInfo> (stream);
|
||||
}
|
||||
|
||||
bool DismountVolumeRequest::RequiresElevation () const
|
||||
{
|
||||
#ifdef TC_MACOSX
|
||||
if (MountedVolumeInfo->Path.IsDevice())
|
||||
{
|
||||
try
|
||||
{
|
||||
File file;
|
||||
file.Open (MountedVolumeInfo->Path, File::OpenReadWrite);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
#endif
|
||||
return !Core->HasAdminPrivileges();
|
||||
}
|
||||
|
||||
void DismountVolumeRequest::Serialize (shared_ptr <Stream> stream) const
|
||||
{
|
||||
CoreServiceRequest::Serialize (stream);
|
||||
Serializer sr (stream);
|
||||
sr.Serialize ("IgnoreOpenFiles", IgnoreOpenFiles);
|
||||
sr.Serialize ("SyncVolumeInfo", SyncVolumeInfo);
|
||||
MountedVolumeInfo->Serialize (stream);
|
||||
}
|
||||
|
||||
// GetDeviceSectorSizeRequest
|
||||
void GetDeviceSectorSizeRequest::Deserialize (shared_ptr <Stream> stream)
|
||||
{
|
||||
CoreServiceRequest::Deserialize (stream);
|
||||
Serializer sr (stream);
|
||||
Path = sr.DeserializeWString ("Path");
|
||||
}
|
||||
|
||||
bool GetDeviceSectorSizeRequest::RequiresElevation () const
|
||||
{
|
||||
return !Core->HasAdminPrivileges();
|
||||
}
|
||||
|
||||
void GetDeviceSectorSizeRequest::Serialize (shared_ptr <Stream> stream) const
|
||||
{
|
||||
CoreServiceRequest::Serialize (stream);
|
||||
Serializer sr (stream);
|
||||
sr.Serialize ("Path", wstring (Path));
|
||||
}
|
||||
|
||||
// GetDeviceSizeRequest
|
||||
void GetDeviceSizeRequest::Deserialize (shared_ptr <Stream> stream)
|
||||
{
|
||||
CoreServiceRequest::Deserialize (stream);
|
||||
Serializer sr (stream);
|
||||
Path = sr.DeserializeWString ("Path");
|
||||
}
|
||||
|
||||
bool GetDeviceSizeRequest::RequiresElevation () const
|
||||
{
|
||||
return !Core->HasAdminPrivileges();
|
||||
}
|
||||
|
||||
void GetDeviceSizeRequest::Serialize (shared_ptr <Stream> stream) const
|
||||
{
|
||||
CoreServiceRequest::Serialize (stream);
|
||||
Serializer sr (stream);
|
||||
sr.Serialize ("Path", wstring (Path));
|
||||
}
|
||||
|
||||
// GetHostDevicesRequest
|
||||
void GetHostDevicesRequest::Deserialize (shared_ptr <Stream> stream)
|
||||
{
|
||||
CoreServiceRequest::Deserialize (stream);
|
||||
Serializer sr (stream);
|
||||
sr.Deserialize ("PathListOnly", PathListOnly);
|
||||
}
|
||||
|
||||
bool GetHostDevicesRequest::RequiresElevation () const
|
||||
{
|
||||
return !Core->HasAdminPrivileges();
|
||||
}
|
||||
|
||||
void GetHostDevicesRequest::Serialize (shared_ptr <Stream> stream) const
|
||||
{
|
||||
CoreServiceRequest::Serialize (stream);
|
||||
Serializer sr (stream);
|
||||
sr.Serialize ("PathListOnly", PathListOnly);
|
||||
}
|
||||
|
||||
// ExitRequest
|
||||
void ExitRequest::Deserialize (shared_ptr <Stream> stream)
|
||||
{
|
||||
CoreServiceRequest::Deserialize (stream);
|
||||
}
|
||||
|
||||
void ExitRequest::Serialize (shared_ptr <Stream> stream) const
|
||||
{
|
||||
CoreServiceRequest::Serialize (stream);
|
||||
}
|
||||
|
||||
// MountVolumeRequest
|
||||
void MountVolumeRequest::Deserialize (shared_ptr <Stream> stream)
|
||||
{
|
||||
CoreServiceRequest::Deserialize (stream);
|
||||
Serializer sr (stream);
|
||||
DeserializedOptions = Serializable::DeserializeNew <MountOptions> (stream);
|
||||
Options = DeserializedOptions.get();
|
||||
}
|
||||
|
||||
bool MountVolumeRequest::RequiresElevation () const
|
||||
{
|
||||
#ifdef TC_MACOSX
|
||||
if (Options->Path->IsDevice())
|
||||
{
|
||||
try
|
||||
{
|
||||
File file;
|
||||
file.Open (*Options->Path, File::OpenReadWrite);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
#endif
|
||||
return !Core->HasAdminPrivileges();
|
||||
}
|
||||
|
||||
void MountVolumeRequest::Serialize (shared_ptr <Stream> stream) const
|
||||
{
|
||||
CoreServiceRequest::Serialize (stream);
|
||||
Serializer sr (stream);
|
||||
Options->Serialize (stream);
|
||||
}
|
||||
|
||||
// SetFileOwnerRequest
|
||||
void SetFileOwnerRequest::Deserialize (shared_ptr <Stream> stream)
|
||||
{
|
||||
CoreServiceRequest::Deserialize (stream);
|
||||
Serializer sr (stream);
|
||||
|
||||
uint64 owner;
|
||||
sr.Deserialize ("Owner", owner);
|
||||
Owner.SystemId = static_cast <uid_t> (owner);
|
||||
|
||||
Path = sr.DeserializeWString ("Path");
|
||||
}
|
||||
|
||||
bool SetFileOwnerRequest::RequiresElevation () const
|
||||
{
|
||||
return !Core->HasAdminPrivileges();
|
||||
}
|
||||
|
||||
void SetFileOwnerRequest::Serialize (shared_ptr <Stream> stream) const
|
||||
{
|
||||
CoreServiceRequest::Serialize (stream);
|
||||
Serializer sr (stream);
|
||||
|
||||
uint64 owner = Owner.SystemId;
|
||||
sr.Serialize ("Owner", owner);
|
||||
|
||||
sr.Serialize ("Path", wstring (Path));
|
||||
}
|
||||
|
||||
|
||||
TC_SERIALIZER_FACTORY_ADD_CLASS (CoreServiceRequest);
|
||||
TC_SERIALIZER_FACTORY_ADD_CLASS (CheckFilesystemRequest);
|
||||
TC_SERIALIZER_FACTORY_ADD_CLASS (DismountFilesystemRequest);
|
||||
TC_SERIALIZER_FACTORY_ADD_CLASS (DismountVolumeRequest);
|
||||
TC_SERIALIZER_FACTORY_ADD_CLASS (ExitRequest);
|
||||
TC_SERIALIZER_FACTORY_ADD_CLASS (GetDeviceSectorSizeRequest);
|
||||
TC_SERIALIZER_FACTORY_ADD_CLASS (GetDeviceSizeRequest);
|
||||
TC_SERIALIZER_FACTORY_ADD_CLASS (GetHostDevicesRequest);
|
||||
TC_SERIALIZER_FACTORY_ADD_CLASS (MountVolumeRequest);
|
||||
TC_SERIALIZER_FACTORY_ADD_CLASS (SetFileOwnerRequest);
|
||||
}
|
||||
136
src/Core/Unix/CoreServiceRequest.h
Normal file
136
src/Core/Unix/CoreServiceRequest.h
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
Copyright (c) 2008-2010 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#ifndef TC_HEADER_Core_Unix_CoreServiceRequest
|
||||
#define TC_HEADER_Core_Unix_CoreServiceRequest
|
||||
|
||||
#include "Platform/Serializable.h"
|
||||
#include "Core/Core.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
struct CoreServiceRequest : public Serializable
|
||||
{
|
||||
CoreServiceRequest () : ElevateUserPrivileges (false), FastElevation (false) { }
|
||||
TC_SERIALIZABLE (CoreServiceRequest);
|
||||
|
||||
virtual bool RequiresElevation () const { return false; }
|
||||
|
||||
string AdminPassword;
|
||||
FilePath ApplicationExecutablePath;
|
||||
bool ElevateUserPrivileges;
|
||||
bool FastElevation;
|
||||
};
|
||||
|
||||
struct CheckFilesystemRequest : CoreServiceRequest
|
||||
{
|
||||
CheckFilesystemRequest () { }
|
||||
CheckFilesystemRequest (shared_ptr <VolumeInfo> volumeInfo, bool repair)
|
||||
: MountedVolumeInfo (volumeInfo), Repair (repair) { }
|
||||
TC_SERIALIZABLE (CheckFilesystemRequest);
|
||||
|
||||
virtual bool RequiresElevation () const;
|
||||
|
||||
shared_ptr <VolumeInfo> MountedVolumeInfo;
|
||||
bool Repair;
|
||||
};
|
||||
|
||||
struct DismountFilesystemRequest : CoreServiceRequest
|
||||
{
|
||||
DismountFilesystemRequest () { }
|
||||
DismountFilesystemRequest (const DirectoryPath &mountPoint, bool force)
|
||||
: Force (force), MountPoint (mountPoint) { }
|
||||
TC_SERIALIZABLE (DismountFilesystemRequest);
|
||||
|
||||
virtual bool RequiresElevation () const;
|
||||
|
||||
bool Force;
|
||||
DirectoryPath MountPoint;
|
||||
};
|
||||
|
||||
struct DismountVolumeRequest : CoreServiceRequest
|
||||
{
|
||||
DismountVolumeRequest () { }
|
||||
DismountVolumeRequest (shared_ptr <VolumeInfo> volumeInfo, bool ignoreOpenFiles, bool syncVolumeInfo)
|
||||
: IgnoreOpenFiles (ignoreOpenFiles), MountedVolumeInfo (volumeInfo), SyncVolumeInfo (syncVolumeInfo) { }
|
||||
TC_SERIALIZABLE (DismountVolumeRequest);
|
||||
|
||||
virtual bool RequiresElevation () const;
|
||||
|
||||
bool IgnoreOpenFiles;
|
||||
shared_ptr <VolumeInfo> MountedVolumeInfo;
|
||||
bool SyncVolumeInfo;
|
||||
};
|
||||
|
||||
struct GetDeviceSectorSizeRequest : CoreServiceRequest
|
||||
{
|
||||
GetDeviceSectorSizeRequest () { }
|
||||
GetDeviceSectorSizeRequest (const DevicePath &path) : Path (path) { }
|
||||
TC_SERIALIZABLE (GetDeviceSectorSizeRequest);
|
||||
|
||||
virtual bool RequiresElevation () const;
|
||||
|
||||
DevicePath Path;
|
||||
};
|
||||
|
||||
struct GetDeviceSizeRequest : CoreServiceRequest
|
||||
{
|
||||
GetDeviceSizeRequest () { }
|
||||
GetDeviceSizeRequest (const DevicePath &path) : Path (path) { }
|
||||
TC_SERIALIZABLE (GetDeviceSizeRequest);
|
||||
|
||||
virtual bool RequiresElevation () const;
|
||||
|
||||
DevicePath Path;
|
||||
};
|
||||
|
||||
struct GetHostDevicesRequest : CoreServiceRequest
|
||||
{
|
||||
GetHostDevicesRequest () { }
|
||||
GetHostDevicesRequest (bool pathListOnly) : PathListOnly (pathListOnly) { }
|
||||
TC_SERIALIZABLE (GetHostDevicesRequest);
|
||||
|
||||
virtual bool RequiresElevation () const;
|
||||
|
||||
bool PathListOnly;
|
||||
};
|
||||
|
||||
struct ExitRequest : CoreServiceRequest
|
||||
{
|
||||
TC_SERIALIZABLE (ExitRequest);
|
||||
};
|
||||
|
||||
struct MountVolumeRequest : CoreServiceRequest
|
||||
{
|
||||
MountVolumeRequest () { }
|
||||
MountVolumeRequest (MountOptions *options) : Options (options) { }
|
||||
TC_SERIALIZABLE (MountVolumeRequest);
|
||||
|
||||
virtual bool RequiresElevation () const;
|
||||
|
||||
MountOptions *Options;
|
||||
|
||||
protected:
|
||||
shared_ptr <MountOptions> DeserializedOptions;
|
||||
};
|
||||
|
||||
|
||||
struct SetFileOwnerRequest : CoreServiceRequest
|
||||
{
|
||||
SetFileOwnerRequest () { }
|
||||
SetFileOwnerRequest (const FilesystemPath &path, const UserId &owner) : Owner (owner), Path (path) { }
|
||||
TC_SERIALIZABLE (SetFileOwnerRequest);
|
||||
|
||||
virtual bool RequiresElevation () const;
|
||||
|
||||
UserId Owner;
|
||||
FilesystemPath Path;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TC_HEADER_Core_Unix_CoreServiceRequest
|
||||
119
src/Core/Unix/CoreServiceResponse.cpp
Normal file
119
src/Core/Unix/CoreServiceResponse.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
Copyright (c) 2008-2010 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#include "CoreServiceResponse.h"
|
||||
#include "Platform/SerializerFactory.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
// CheckFilesystemResponse
|
||||
void CheckFilesystemResponse::Deserialize (shared_ptr <Stream> stream)
|
||||
{
|
||||
}
|
||||
|
||||
void CheckFilesystemResponse::Serialize (shared_ptr <Stream> stream) const
|
||||
{
|
||||
Serializable::Serialize (stream);
|
||||
}
|
||||
|
||||
// DismountFilesystemResponse
|
||||
void DismountFilesystemResponse::Deserialize (shared_ptr <Stream> stream)
|
||||
{
|
||||
}
|
||||
|
||||
void DismountFilesystemResponse::Serialize (shared_ptr <Stream> stream) const
|
||||
{
|
||||
Serializable::Serialize (stream);
|
||||
}
|
||||
|
||||
// DismountVolumeResponse
|
||||
void DismountVolumeResponse::Deserialize (shared_ptr <Stream> stream)
|
||||
{
|
||||
DismountedVolumeInfo = Serializable::DeserializeNew <VolumeInfo> (stream);
|
||||
}
|
||||
|
||||
void DismountVolumeResponse::Serialize (shared_ptr <Stream> stream) const
|
||||
{
|
||||
Serializable::Serialize (stream);
|
||||
Serializer sr (stream);
|
||||
DismountedVolumeInfo->Serialize (stream);
|
||||
}
|
||||
|
||||
// GetDeviceSectorSizeResponse
|
||||
void GetDeviceSectorSizeResponse::Deserialize (shared_ptr <Stream> stream)
|
||||
{
|
||||
Serializer sr (stream);
|
||||
sr.Deserialize ("Size", Size);
|
||||
}
|
||||
|
||||
void GetDeviceSectorSizeResponse::Serialize (shared_ptr <Stream> stream) const
|
||||
{
|
||||
Serializable::Serialize (stream);
|
||||
Serializer sr (stream);
|
||||
sr.Serialize ("Size", Size);
|
||||
}
|
||||
|
||||
// GetDeviceSizeResponse
|
||||
void GetDeviceSizeResponse::Deserialize (shared_ptr <Stream> stream)
|
||||
{
|
||||
Serializer sr (stream);
|
||||
sr.Deserialize ("Size", Size);
|
||||
}
|
||||
|
||||
void GetDeviceSizeResponse::Serialize (shared_ptr <Stream> stream) const
|
||||
{
|
||||
Serializable::Serialize (stream);
|
||||
Serializer sr (stream);
|
||||
sr.Serialize ("Size", Size);
|
||||
}
|
||||
|
||||
// GetHostDevicesResponse
|
||||
void GetHostDevicesResponse::Deserialize (shared_ptr <Stream> stream)
|
||||
{
|
||||
Serializable::DeserializeList (stream, HostDevices);
|
||||
}
|
||||
|
||||
void GetHostDevicesResponse::Serialize (shared_ptr <Stream> stream) const
|
||||
{
|
||||
Serializable::Serialize (stream);
|
||||
Serializable::SerializeList (stream, HostDevices);
|
||||
}
|
||||
|
||||
// MountVolumeResponse
|
||||
void MountVolumeResponse::Deserialize (shared_ptr <Stream> stream)
|
||||
{
|
||||
Serializer sr (stream);
|
||||
MountedVolumeInfo = Serializable::DeserializeNew <VolumeInfo> (stream);
|
||||
}
|
||||
|
||||
void MountVolumeResponse::Serialize (shared_ptr <Stream> stream) const
|
||||
{
|
||||
Serializable::Serialize (stream);
|
||||
Serializer sr (stream);
|
||||
MountedVolumeInfo->Serialize (stream);
|
||||
}
|
||||
|
||||
// SetFileOwnerResponse
|
||||
void SetFileOwnerResponse::Deserialize (shared_ptr <Stream> stream)
|
||||
{
|
||||
}
|
||||
|
||||
void SetFileOwnerResponse::Serialize (shared_ptr <Stream> stream) const
|
||||
{
|
||||
Serializable::Serialize (stream);
|
||||
}
|
||||
|
||||
TC_SERIALIZER_FACTORY_ADD_CLASS (CheckFilesystemResponse);
|
||||
TC_SERIALIZER_FACTORY_ADD_CLASS (DismountFilesystemResponse);
|
||||
TC_SERIALIZER_FACTORY_ADD_CLASS (DismountVolumeResponse);
|
||||
TC_SERIALIZER_FACTORY_ADD_CLASS (GetDeviceSectorSizeResponse);
|
||||
TC_SERIALIZER_FACTORY_ADD_CLASS (GetDeviceSizeResponse);
|
||||
TC_SERIALIZER_FACTORY_ADD_CLASS (GetHostDevicesResponse);
|
||||
TC_SERIALIZER_FACTORY_ADD_CLASS (MountVolumeResponse);
|
||||
TC_SERIALIZER_FACTORY_ADD_CLASS (SetFileOwnerResponse);
|
||||
}
|
||||
84
src/Core/Unix/CoreServiceResponse.h
Normal file
84
src/Core/Unix/CoreServiceResponse.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
Copyright (c) 2008-2010 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#ifndef TC_HEADER_Core_Unix_CoreServiceResponse
|
||||
#define TC_HEADER_Core_Unix_CoreServiceResponse
|
||||
|
||||
#include "Platform/Serializable.h"
|
||||
#include "Core/Core.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
struct CoreServiceResponse : public Serializable
|
||||
{
|
||||
};
|
||||
|
||||
struct CheckFilesystemResponse : CoreServiceResponse
|
||||
{
|
||||
CheckFilesystemResponse () { }
|
||||
TC_SERIALIZABLE (CheckFilesystemResponse);
|
||||
};
|
||||
|
||||
struct DismountFilesystemResponse : CoreServiceResponse
|
||||
{
|
||||
DismountFilesystemResponse () { }
|
||||
TC_SERIALIZABLE (DismountFilesystemResponse);
|
||||
};
|
||||
|
||||
struct DismountVolumeResponse : CoreServiceResponse
|
||||
{
|
||||
DismountVolumeResponse () { }
|
||||
TC_SERIALIZABLE (DismountVolumeResponse);
|
||||
|
||||
shared_ptr <VolumeInfo> DismountedVolumeInfo;
|
||||
};
|
||||
|
||||
struct GetDeviceSectorSizeResponse : CoreServiceResponse
|
||||
{
|
||||
GetDeviceSectorSizeResponse () { }
|
||||
GetDeviceSectorSizeResponse (uint32 size) : Size (size) { }
|
||||
TC_SERIALIZABLE (GetDeviceSectorSizeResponse);
|
||||
|
||||
uint32 Size;
|
||||
};
|
||||
|
||||
struct GetDeviceSizeResponse : CoreServiceResponse
|
||||
{
|
||||
GetDeviceSizeResponse () { }
|
||||
GetDeviceSizeResponse (uint64 size) : Size (size) { }
|
||||
TC_SERIALIZABLE (GetDeviceSizeResponse);
|
||||
|
||||
uint64 Size;
|
||||
};
|
||||
|
||||
struct GetHostDevicesResponse : CoreServiceResponse
|
||||
{
|
||||
GetHostDevicesResponse () { }
|
||||
GetHostDevicesResponse (const HostDeviceList &hostDevices) : HostDevices (hostDevices) { }
|
||||
TC_SERIALIZABLE (GetHostDevicesResponse);
|
||||
|
||||
HostDeviceList HostDevices;
|
||||
};
|
||||
|
||||
struct MountVolumeResponse : CoreServiceResponse
|
||||
{
|
||||
MountVolumeResponse () { }
|
||||
MountVolumeResponse (shared_ptr <VolumeInfo> volumeInfo) : MountedVolumeInfo (volumeInfo) { }
|
||||
TC_SERIALIZABLE (MountVolumeResponse);
|
||||
|
||||
shared_ptr <VolumeInfo> MountedVolumeInfo;
|
||||
};
|
||||
|
||||
struct SetFileOwnerResponse : CoreServiceResponse
|
||||
{
|
||||
SetFileOwnerResponse () { }
|
||||
TC_SERIALIZABLE (SetFileOwnerResponse);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TC_HEADER_Core_Unix_CoreServiceResponse
|
||||
618
src/Core/Unix/CoreUnix.cpp
Normal file
618
src/Core/Unix/CoreUnix.cpp
Normal file
@@ -0,0 +1,618 @@
|
||||
/*
|
||||
Copyright (c) 2008-2010 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#include "CoreUnix.h"
|
||||
#include <errno.h>
|
||||
#include <iostream>
|
||||
#include <signal.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include "Platform/FileStream.h"
|
||||
#include "Driver/Fuse/FuseService.h"
|
||||
#include "Volume/VolumePasswordCache.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
CoreUnix::CoreUnix ()
|
||||
{
|
||||
signal (SIGPIPE, SIG_IGN);
|
||||
|
||||
char *loc = setlocale (LC_ALL, "");
|
||||
if (!loc || string (loc) == "C")
|
||||
setlocale (LC_ALL, "en_US.UTF-8");
|
||||
}
|
||||
|
||||
CoreUnix::~CoreUnix ()
|
||||
{
|
||||
}
|
||||
|
||||
void CoreUnix::CheckFilesystem (shared_ptr <VolumeInfo> mountedVolume, bool repair) const
|
||||
{
|
||||
if (!mountedVolume->MountPoint.IsEmpty())
|
||||
DismountFilesystem (mountedVolume->MountPoint, false);
|
||||
|
||||
list <string> args;
|
||||
|
||||
args.push_back ("-T");
|
||||
args.push_back ("fsck");
|
||||
|
||||
args.push_back ("-e");
|
||||
|
||||
string xargs = "fsck ";
|
||||
|
||||
#ifdef TC_LINUX
|
||||
if (!repair)
|
||||
xargs += "-n ";
|
||||
else
|
||||
xargs += "-r ";
|
||||
#endif
|
||||
|
||||
xargs += string (mountedVolume->VirtualDevice) + "; echo '[Done]'; read W";
|
||||
args.push_back (xargs);
|
||||
|
||||
try
|
||||
{
|
||||
Process::Execute ("xterm", args, 1000);
|
||||
} catch (TimeOut&) { }
|
||||
}
|
||||
|
||||
void CoreUnix::DismountFilesystem (const DirectoryPath &mountPoint, bool force) const
|
||||
{
|
||||
list <string> args;
|
||||
|
||||
#ifdef TC_MACOSX
|
||||
if (force)
|
||||
args.push_back ("-f");
|
||||
#endif
|
||||
args.push_back ("--");
|
||||
args.push_back (mountPoint);
|
||||
|
||||
Process::Execute ("umount", args);
|
||||
}
|
||||
|
||||
shared_ptr <VolumeInfo> CoreUnix::DismountVolume (shared_ptr <VolumeInfo> mountedVolume, bool ignoreOpenFiles, bool syncVolumeInfo)
|
||||
{
|
||||
if (!mountedVolume->MountPoint.IsEmpty())
|
||||
{
|
||||
DismountFilesystem (mountedVolume->MountPoint, ignoreOpenFiles);
|
||||
|
||||
// Delete mount directory if a default path has been used
|
||||
if (string (mountedVolume->MountPoint).find (GetDefaultMountPointPrefix()) == 0)
|
||||
mountedVolume->MountPoint.Delete();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
DismountNativeVolume (mountedVolume);
|
||||
}
|
||||
catch (NotApplicable &) { }
|
||||
|
||||
if (!mountedVolume->LoopDevice.IsEmpty())
|
||||
{
|
||||
try
|
||||
{
|
||||
DetachLoopDevice (mountedVolume->LoopDevice);
|
||||
}
|
||||
catch (ExecutedProcessFailed&) { }
|
||||
}
|
||||
|
||||
if (syncVolumeInfo || mountedVolume->Protection == VolumeProtection::HiddenVolumeReadOnly)
|
||||
{
|
||||
sync();
|
||||
VolumeInfoList ml = GetMountedVolumes (mountedVolume->Path);
|
||||
|
||||
if (ml.size() > 0)
|
||||
mountedVolume = ml.front();
|
||||
}
|
||||
|
||||
list <string> args;
|
||||
args.push_back ("--");
|
||||
args.push_back (mountedVolume->AuxMountPoint);
|
||||
|
||||
for (int t = 0; true; t++)
|
||||
{
|
||||
try
|
||||
{
|
||||
Process::Execute ("umount", args);
|
||||
break;
|
||||
}
|
||||
catch (ExecutedProcessFailed&)
|
||||
{
|
||||
if (t > 10)
|
||||
throw;
|
||||
Thread::Sleep (200);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
mountedVolume->AuxMountPoint.Delete();
|
||||
}
|
||||
catch (...) { }
|
||||
|
||||
VolumeEventArgs eventArgs (mountedVolume);
|
||||
VolumeDismountedEvent.Raise (eventArgs);
|
||||
|
||||
return mountedVolume;
|
||||
}
|
||||
|
||||
bool CoreUnix::FilesystemSupportsLargeFiles (const FilePath &filePath) const
|
||||
{
|
||||
string path = filePath;
|
||||
size_t pos;
|
||||
|
||||
while ((pos = path.find_last_of ('/')) != string::npos)
|
||||
{
|
||||
path = path.substr (0, pos);
|
||||
|
||||
if (path.empty())
|
||||
break;
|
||||
|
||||
try
|
||||
{
|
||||
MountedFilesystemList filesystems = GetMountedFilesystems (DevicePath(), path);
|
||||
if (!filesystems.empty())
|
||||
{
|
||||
const MountedFilesystem &fs = *filesystems.front();
|
||||
|
||||
if (fs.Type == "fat"
|
||||
|| fs.Type == "fat32"
|
||||
|| fs.Type == "vfat"
|
||||
|| fs.Type == "fatfs"
|
||||
|| fs.Type == "msdos"
|
||||
|| fs.Type == "msdosfs"
|
||||
|| fs.Type == "umsdos"
|
||||
|| fs.Type == "dos"
|
||||
|| fs.Type == "dosfs"
|
||||
|| fs.Type == "pcfs"
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (...) { }
|
||||
}
|
||||
|
||||
return true; // Prevent errors if the filesystem cannot be identified
|
||||
}
|
||||
|
||||
bool CoreUnix::FilesystemSupportsUnixPermissions (const DevicePath &devicePath) const
|
||||
{
|
||||
File device;
|
||||
device.Open (devicePath);
|
||||
|
||||
Buffer bootSector (device.GetDeviceSectorSize());
|
||||
device.SeekAt (0);
|
||||
device.ReadCompleteBuffer (bootSector);
|
||||
|
||||
byte *b = bootSector.Ptr();
|
||||
|
||||
return memcmp (b + 3, "NTFS", 4) != 0
|
||||
&& memcmp (b + 54, "FAT", 3) != 0
|
||||
&& memcmp (b + 82, "FAT32", 5) != 0
|
||||
&& memcmp (b + 3, "EXFAT", 5) != 0;
|
||||
}
|
||||
|
||||
string CoreUnix::GetDefaultMountPointPrefix () const
|
||||
{
|
||||
const char *envPrefix = getenv ("TRUECRYPT_MOUNT_PREFIX");
|
||||
if (envPrefix && !string (envPrefix).empty())
|
||||
return envPrefix;
|
||||
|
||||
if (FilesystemPath ("/media").IsDirectory())
|
||||
return "/media/truecrypt";
|
||||
|
||||
if (FilesystemPath ("/mnt").IsDirectory())
|
||||
return "/mnt/truecrypt";
|
||||
|
||||
return GetTempDirectory() + "/truecrypt_mnt";
|
||||
}
|
||||
|
||||
uint32 CoreUnix::GetDeviceSectorSize (const DevicePath &devicePath) const
|
||||
{
|
||||
File dev;
|
||||
dev.Open (devicePath);
|
||||
return dev.GetDeviceSectorSize();
|
||||
}
|
||||
|
||||
uint64 CoreUnix::GetDeviceSize (const DevicePath &devicePath) const
|
||||
{
|
||||
File dev;
|
||||
dev.Open (devicePath);
|
||||
return dev.Length();
|
||||
}
|
||||
|
||||
DirectoryPath CoreUnix::GetDeviceMountPoint (const DevicePath &devicePath) const
|
||||
{
|
||||
DevicePath devPath = devicePath;
|
||||
#ifdef TC_MACOSX
|
||||
if (string (devPath).find ("/dev/rdisk") != string::npos)
|
||||
devPath = string ("/dev/") + string (devicePath).substr (6);
|
||||
#endif
|
||||
MountedFilesystemList mountedFilesystems = GetMountedFilesystems (devPath);
|
||||
|
||||
if (mountedFilesystems.size() < 1)
|
||||
return DirectoryPath();
|
||||
|
||||
return mountedFilesystems.front()->MountPoint;
|
||||
}
|
||||
|
||||
VolumeInfoList CoreUnix::GetMountedVolumes (const VolumePath &volumePath) const
|
||||
{
|
||||
VolumeInfoList volumes;
|
||||
|
||||
foreach_ref (const MountedFilesystem &mf, GetMountedFilesystems ())
|
||||
{
|
||||
if (string (mf.MountPoint).find (GetFuseMountDirPrefix()) == string::npos)
|
||||
continue;
|
||||
|
||||
shared_ptr <VolumeInfo> mountedVol;
|
||||
try
|
||||
{
|
||||
shared_ptr <File> controlFile (new File);
|
||||
controlFile->Open (string (mf.MountPoint) + FuseService::GetControlPath());
|
||||
|
||||
shared_ptr <Stream> controlFileStream (new FileStream (controlFile));
|
||||
mountedVol = Serializable::DeserializeNew <VolumeInfo> (controlFileStream);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!volumePath.IsEmpty() && wstring (mountedVol->Path).compare (volumePath) != 0)
|
||||
continue;
|
||||
|
||||
mountedVol->AuxMountPoint = mf.MountPoint;
|
||||
|
||||
if (!mountedVol->VirtualDevice.IsEmpty())
|
||||
{
|
||||
MountedFilesystemList mpl = GetMountedFilesystems (mountedVol->VirtualDevice);
|
||||
|
||||
if (mpl.size() > 0)
|
||||
mountedVol->MountPoint = mpl.front()->MountPoint;
|
||||
}
|
||||
|
||||
volumes.push_back (mountedVol);
|
||||
|
||||
if (!volumePath.IsEmpty())
|
||||
break;
|
||||
}
|
||||
|
||||
return volumes;
|
||||
}
|
||||
|
||||
gid_t CoreUnix::GetRealGroupId () const
|
||||
{
|
||||
const char *env = getenv ("SUDO_GID");
|
||||
if (env)
|
||||
{
|
||||
try
|
||||
{
|
||||
string s (env);
|
||||
return static_cast <gid_t> (StringConverter::ToUInt64 (s));
|
||||
}
|
||||
catch (...) { }
|
||||
}
|
||||
|
||||
return getgid();
|
||||
}
|
||||
|
||||
uid_t CoreUnix::GetRealUserId () const
|
||||
{
|
||||
const char *env = getenv ("SUDO_UID");
|
||||
if (env)
|
||||
{
|
||||
try
|
||||
{
|
||||
string s (env);
|
||||
return static_cast <uid_t> (StringConverter::ToUInt64 (s));
|
||||
}
|
||||
catch (...) { }
|
||||
}
|
||||
|
||||
return getuid();
|
||||
}
|
||||
|
||||
string CoreUnix::GetTempDirectory () const
|
||||
{
|
||||
char *envDir = getenv ("TMPDIR");
|
||||
return envDir ? envDir : "/tmp";
|
||||
}
|
||||
|
||||
bool CoreUnix::IsMountPointAvailable (const DirectoryPath &mountPoint) const
|
||||
{
|
||||
return GetMountedFilesystems (DevicePath(), mountPoint).size() == 0;
|
||||
}
|
||||
|
||||
void CoreUnix::MountFilesystem (const DevicePath &devicePath, const DirectoryPath &mountPoint, const string &filesystemType, bool readOnly, const string &systemMountOptions) const
|
||||
{
|
||||
if (GetMountedFilesystems (DevicePath(), mountPoint).size() > 0)
|
||||
throw MountPointUnavailable (SRC_POS);
|
||||
|
||||
list <string> args;
|
||||
string options;
|
||||
|
||||
if (!filesystemType.empty())
|
||||
{
|
||||
#ifdef TC_SOLARIS
|
||||
args.push_back ("-F");
|
||||
#else
|
||||
args.push_back ("-t");
|
||||
#endif
|
||||
args.push_back (filesystemType);
|
||||
}
|
||||
|
||||
if (readOnly)
|
||||
options = "-oro";
|
||||
|
||||
if (!systemMountOptions.empty())
|
||||
{
|
||||
if (options.empty())
|
||||
options = "-o";
|
||||
else
|
||||
options += ",";
|
||||
|
||||
options += systemMountOptions;
|
||||
}
|
||||
|
||||
if (!options.empty())
|
||||
args.push_back (options);
|
||||
|
||||
args.push_back ("--");
|
||||
args.push_back (devicePath);
|
||||
args.push_back (mountPoint);
|
||||
|
||||
Process::Execute ("mount", args);
|
||||
}
|
||||
|
||||
VolumeSlotNumber CoreUnix::MountPointToSlotNumber (const DirectoryPath &mountPoint) const
|
||||
{
|
||||
string mountPointStr (mountPoint);
|
||||
if (mountPointStr.find (GetDefaultMountPointPrefix()) == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
return StringConverter::ToUInt32 (StringConverter::GetTrailingNumber (mountPointStr));
|
||||
}
|
||||
catch (...) { }
|
||||
}
|
||||
return GetFirstFreeSlotNumber();
|
||||
}
|
||||
|
||||
shared_ptr <VolumeInfo> CoreUnix::MountVolume (MountOptions &options)
|
||||
{
|
||||
CoalesceSlotNumberAndMountPoint (options);
|
||||
|
||||
if (IsVolumeMounted (*options.Path))
|
||||
throw VolumeAlreadyMounted (SRC_POS);
|
||||
|
||||
Cipher::EnableHwSupport (!options.NoHardwareCrypto);
|
||||
|
||||
shared_ptr <Volume> volume;
|
||||
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
volume = OpenVolume (
|
||||
options.Path,
|
||||
options.PreserveTimestamps,
|
||||
options.Password,
|
||||
options.Keyfiles,
|
||||
options.Protection,
|
||||
options.ProtectionPassword,
|
||||
options.ProtectionKeyfiles,
|
||||
options.SharedAccessAllowed,
|
||||
VolumeType::Unknown,
|
||||
options.UseBackupHeaders,
|
||||
options.PartitionInSystemEncryptionScope
|
||||
);
|
||||
|
||||
options.Password.reset();
|
||||
}
|
||||
catch (SystemException &e)
|
||||
{
|
||||
if (options.Protection != VolumeProtection::ReadOnly
|
||||
&& (e.GetErrorCode() == EROFS || e.GetErrorCode() == EACCES || e.GetErrorCode() == EPERM))
|
||||
{
|
||||
// Read-only filesystem
|
||||
options.Protection = VolumeProtection::ReadOnly;
|
||||
continue;
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (options.Path->IsDevice())
|
||||
{
|
||||
if (volume->GetFile()->GetDeviceSectorSize() != volume->GetSectorSize())
|
||||
throw ParameterIncorrect (SRC_POS);
|
||||
|
||||
#if defined (TC_LINUX)
|
||||
if (volume->GetSectorSize() != TC_SECTOR_SIZE_LEGACY)
|
||||
{
|
||||
if (options.Protection == VolumeProtection::HiddenVolumeReadOnly)
|
||||
throw UnsupportedSectorSizeHiddenVolumeProtection();
|
||||
|
||||
if (options.NoKernelCrypto)
|
||||
throw UnsupportedSectorSizeNoKernelCrypto();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Find a free mount point for FUSE service
|
||||
MountedFilesystemList mountedFilesystems = GetMountedFilesystems ();
|
||||
string fuseMountPoint;
|
||||
for (int i = 1; true; i++)
|
||||
{
|
||||
stringstream path;
|
||||
path << GetTempDirectory() << "/" << GetFuseMountDirPrefix() << i;
|
||||
FilesystemPath fsPath (path.str());
|
||||
|
||||
bool inUse = false;
|
||||
|
||||
foreach_ref (const MountedFilesystem &mf, mountedFilesystems)
|
||||
{
|
||||
if (mf.MountPoint == path.str())
|
||||
{
|
||||
inUse = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!inUse)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (fsPath.IsDirectory())
|
||||
fsPath.Delete();
|
||||
|
||||
throw_sys_sub_if (mkdir (path.str().c_str(), S_IRUSR | S_IXUSR) == -1, path.str());
|
||||
|
||||
fuseMountPoint = fsPath;
|
||||
break;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
if (i > 255)
|
||||
throw TemporaryDirectoryFailure (SRC_POS, StringConverter::ToWide (path.str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
FuseService::Mount (volume, options.SlotNumber, fuseMountPoint);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
try
|
||||
{
|
||||
DirectoryPath (fuseMountPoint).Delete();
|
||||
}
|
||||
catch (...) { }
|
||||
throw;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Create a mount directory if a default path has been specified
|
||||
bool mountDirCreated = false;
|
||||
string mountPoint;
|
||||
if (!options.NoFilesystem && options.MountPoint)
|
||||
{
|
||||
mountPoint = *options.MountPoint;
|
||||
|
||||
#ifndef TC_MACOSX
|
||||
if (mountPoint.find (GetDefaultMountPointPrefix()) == 0 && !options.MountPoint->IsDirectory())
|
||||
{
|
||||
Directory::Create (*options.MountPoint);
|
||||
try
|
||||
{
|
||||
throw_sys_sub_if (chown (mountPoint.c_str(), GetRealUserId(), GetRealGroupId()) == -1, mountPoint);
|
||||
} catch (ParameterIncorrect&) { }
|
||||
|
||||
mountDirCreated = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
MountVolumeNative (volume, options, fuseMountPoint);
|
||||
}
|
||||
catch (NotApplicable&)
|
||||
{
|
||||
MountAuxVolumeImage (fuseMountPoint, options);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
if (mountDirCreated)
|
||||
remove (mountPoint.c_str());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
try
|
||||
{
|
||||
VolumeInfoList mountedVolumes = GetMountedVolumes (*options.Path);
|
||||
if (mountedVolumes.size() > 0)
|
||||
{
|
||||
shared_ptr <VolumeInfo> mountedVolume (mountedVolumes.front());
|
||||
DismountVolume (mountedVolume);
|
||||
}
|
||||
}
|
||||
catch (...) { }
|
||||
throw;
|
||||
}
|
||||
|
||||
VolumeInfoList mountedVolumes = GetMountedVolumes (*options.Path);
|
||||
if (mountedVolumes.size() != 1)
|
||||
throw ParameterIncorrect (SRC_POS);
|
||||
|
||||
VolumeEventArgs eventArgs (mountedVolumes.front());
|
||||
VolumeMountedEvent.Raise (eventArgs);
|
||||
|
||||
return mountedVolumes.front();
|
||||
}
|
||||
|
||||
void CoreUnix::MountAuxVolumeImage (const DirectoryPath &auxMountPoint, const MountOptions &options) const
|
||||
{
|
||||
DevicePath loopDev = AttachFileToLoopDevice (string (auxMountPoint) + FuseService::GetVolumeImagePath(), options.Protection == VolumeProtection::ReadOnly);
|
||||
|
||||
try
|
||||
{
|
||||
FuseService::SendAuxDeviceInfo (auxMountPoint, loopDev, loopDev);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
try
|
||||
{
|
||||
DetachLoopDevice (loopDev);
|
||||
}
|
||||
catch (...) { }
|
||||
throw;
|
||||
}
|
||||
|
||||
if (!options.NoFilesystem && options.MountPoint && !options.MountPoint->IsEmpty())
|
||||
{
|
||||
MountFilesystem (loopDev, *options.MountPoint,
|
||||
StringConverter::ToSingle (options.FilesystemType),
|
||||
options.Protection == VolumeProtection::ReadOnly,
|
||||
StringConverter::ToSingle (options.FilesystemOptions));
|
||||
}
|
||||
}
|
||||
|
||||
void CoreUnix::SetFileOwner (const FilesystemPath &path, const UserId &owner) const
|
||||
{
|
||||
throw_sys_if (chown (string (path).c_str(), owner.SystemId, (gid_t) -1) == -1);
|
||||
}
|
||||
|
||||
DirectoryPath CoreUnix::SlotNumberToMountPoint (VolumeSlotNumber slotNumber) const
|
||||
{
|
||||
if (slotNumber < GetFirstSlotNumber() || slotNumber > GetLastSlotNumber())
|
||||
throw ParameterIncorrect (SRC_POS);
|
||||
|
||||
stringstream s;
|
||||
s << GetDefaultMountPointPrefix() << slotNumber;
|
||||
return s.str();
|
||||
}
|
||||
}
|
||||
69
src/Core/Unix/CoreUnix.h
Normal file
69
src/Core/Unix/CoreUnix.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
Copyright (c) 2008-2010 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#ifndef TC_HEADER_Core_CoreUnix
|
||||
#define TC_HEADER_Core_CoreUnix
|
||||
|
||||
#include "System.h"
|
||||
#include "Platform/Unix/Process.h"
|
||||
#include "Core/CoreBase.h"
|
||||
#include "Core/Unix/MountedFilesystem.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
class CoreUnix : public CoreBase
|
||||
{
|
||||
public:
|
||||
CoreUnix ();
|
||||
virtual ~CoreUnix ();
|
||||
|
||||
virtual void CheckFilesystem (shared_ptr <VolumeInfo> mountedVolume, bool repair = false) const;
|
||||
virtual void DismountFilesystem (const DirectoryPath &mountPoint, bool force) const;
|
||||
virtual shared_ptr <VolumeInfo> DismountVolume (shared_ptr <VolumeInfo> mountedVolume, bool ignoreOpenFiles = false, bool syncVolumeInfo = false);
|
||||
virtual bool FilesystemSupportsLargeFiles (const FilePath &filePath) const;
|
||||
virtual DirectoryPath GetDeviceMountPoint (const DevicePath &devicePath) const;
|
||||
virtual uint32 GetDeviceSectorSize (const DevicePath &devicePath) const;
|
||||
virtual uint64 GetDeviceSize (const DevicePath &devicePath) const;
|
||||
virtual int GetOSMajorVersion () const { throw NotApplicable (SRC_POS); }
|
||||
virtual int GetOSMinorVersion () const { throw NotApplicable (SRC_POS); }
|
||||
virtual VolumeInfoList GetMountedVolumes (const VolumePath &volumePath = VolumePath()) const;
|
||||
virtual bool IsDevicePresent (const DevicePath &device) const { throw NotApplicable (SRC_POS); }
|
||||
virtual bool IsInPortableMode () const { return false; }
|
||||
virtual bool IsMountPointAvailable (const DirectoryPath &mountPoint) const;
|
||||
virtual bool IsOSVersion (int major, int minor) const { throw NotApplicable (SRC_POS); }
|
||||
virtual bool IsOSVersionLower (int major, int minor) const { throw NotApplicable (SRC_POS); }
|
||||
virtual bool IsPasswordCacheEmpty () const { throw NotApplicable (SRC_POS); }
|
||||
virtual bool HasAdminPrivileges () const { return getuid() == 0 || geteuid() == 0; }
|
||||
virtual VolumeSlotNumber MountPointToSlotNumber (const DirectoryPath &mountPoint) const;
|
||||
virtual shared_ptr <VolumeInfo> MountVolume (MountOptions &options);
|
||||
virtual void SetFileOwner (const FilesystemPath &path, const UserId &owner) const;
|
||||
virtual DirectoryPath SlotNumberToMountPoint (VolumeSlotNumber slotNumber) const;
|
||||
virtual void WipePasswordCache () const { throw NotApplicable (SRC_POS); }
|
||||
|
||||
protected:
|
||||
virtual DevicePath AttachFileToLoopDevice (const FilePath &filePath, bool readOnly) const { throw NotApplicable (SRC_POS); }
|
||||
virtual void DetachLoopDevice (const DevicePath &devicePath) const { throw NotApplicable (SRC_POS); }
|
||||
virtual void DismountNativeVolume (shared_ptr <VolumeInfo> mountedVolume) const { throw NotApplicable (SRC_POS); }
|
||||
virtual bool FilesystemSupportsUnixPermissions (const DevicePath &devicePath) const;
|
||||
virtual string GetDefaultMountPointPrefix () const;
|
||||
virtual string GetFuseMountDirPrefix () const { return ".truecrypt_aux_mnt"; }
|
||||
virtual MountedFilesystemList GetMountedFilesystems (const DevicePath &devicePath = DevicePath(), const DirectoryPath &mountPoint = DirectoryPath()) const = 0;
|
||||
virtual uid_t GetRealUserId () const;
|
||||
virtual gid_t GetRealGroupId () const;
|
||||
virtual string GetTempDirectory () const;
|
||||
virtual void MountFilesystem (const DevicePath &devicePath, const DirectoryPath &mountPoint, const string &filesystemType, bool readOnly, const string &systemMountOptions) const;
|
||||
virtual void MountAuxVolumeImage (const DirectoryPath &auxMountPoint, const MountOptions &options) const;
|
||||
virtual void MountVolumeNative (shared_ptr <Volume> volume, MountOptions &options, const DirectoryPath &auxMountPoint) const { throw NotApplicable (SRC_POS); }
|
||||
|
||||
private:
|
||||
CoreUnix (const CoreUnix &);
|
||||
CoreUnix &operator= (const CoreUnix &);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TC_HEADER_Core_CoreUnix
|
||||
202
src/Core/Unix/FreeBSD/CoreFreeBSD.cpp
Normal file
202
src/Core/Unix/FreeBSD/CoreFreeBSD.cpp
Normal file
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
Copyright (c) 2008 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#include <fstream>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/ucred.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/wait.h>
|
||||
#include "CoreFreeBSD.h"
|
||||
#include "Core/Unix/CoreServiceProxy.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
CoreFreeBSD::CoreFreeBSD ()
|
||||
{
|
||||
}
|
||||
|
||||
CoreFreeBSD::~CoreFreeBSD ()
|
||||
{
|
||||
}
|
||||
|
||||
DevicePath CoreFreeBSD::AttachFileToLoopDevice (const FilePath &filePath, bool readOnly) const
|
||||
{
|
||||
list <string> args;
|
||||
args.push_back ("-a");
|
||||
args.push_back ("-t");
|
||||
args.push_back ("vnode");
|
||||
|
||||
if (readOnly)
|
||||
{
|
||||
args.push_back ("-o");
|
||||
args.push_back ("readonly");
|
||||
}
|
||||
|
||||
args.push_back ("-f");
|
||||
args.push_back (filePath);
|
||||
|
||||
string dev = StringConverter::Trim (Process::Execute ("mdconfig", args));
|
||||
|
||||
if (dev.find ("/") == string::npos)
|
||||
dev = string ("/dev/") + dev;
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
void CoreFreeBSD::DetachLoopDevice (const DevicePath &devicePath) const
|
||||
{
|
||||
list <string> args;
|
||||
args.push_back ("-d");
|
||||
args.push_back ("-u");
|
||||
args.push_back (StringConverter::GetTrailingNumber (devicePath));
|
||||
|
||||
for (int t = 0; true; t++)
|
||||
{
|
||||
try
|
||||
{
|
||||
Process::Execute ("mdconfig", args);
|
||||
break;
|
||||
}
|
||||
catch (ExecutedProcessFailed&)
|
||||
{
|
||||
if (t > 5)
|
||||
throw;
|
||||
Thread::Sleep (200);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HostDeviceList CoreFreeBSD::GetHostDevices (bool pathListOnly) const
|
||||
{
|
||||
HostDeviceList devices;
|
||||
#ifdef TC_MACOSX
|
||||
const string busType = "rdisk";
|
||||
#else
|
||||
foreach (const string &busType, StringConverter::Split ("ad da"))
|
||||
#endif
|
||||
{
|
||||
for (int devNumber = 0; devNumber < 64; devNumber++)
|
||||
{
|
||||
stringstream devPath;
|
||||
devPath << "/dev/" << busType << devNumber;
|
||||
|
||||
if (FilesystemPath (devPath.str()).IsBlockDevice() || FilesystemPath (devPath.str()).IsCharacterDevice())
|
||||
{
|
||||
make_shared_auto (HostDevice, device);
|
||||
device->Path = devPath.str();
|
||||
if (!pathListOnly)
|
||||
{
|
||||
try
|
||||
{
|
||||
device->Size = GetDeviceSize (device->Path);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
device->Size = 0;
|
||||
}
|
||||
device->MountPoint = GetDeviceMountPoint (device->Path);
|
||||
device->SystemNumber = 0;
|
||||
}
|
||||
devices.push_back (device);
|
||||
|
||||
for (int partNumber = 1; partNumber < 32; partNumber++)
|
||||
{
|
||||
#ifdef TC_MACOSX
|
||||
const string partLetter = "";
|
||||
#else
|
||||
foreach (const string &partLetter, StringConverter::Split (",a,b,c,d,e,f,g,h", ",", true))
|
||||
#endif
|
||||
{
|
||||
stringstream partPath;
|
||||
partPath << devPath.str() << "s" << partNumber << partLetter;
|
||||
|
||||
if (FilesystemPath (partPath.str()).IsBlockDevice() || FilesystemPath (partPath.str()).IsCharacterDevice())
|
||||
{
|
||||
make_shared_auto (HostDevice, partition);
|
||||
partition->Path = partPath.str();
|
||||
if (!pathListOnly)
|
||||
{
|
||||
try
|
||||
{
|
||||
partition->Size = GetDeviceSize (partition->Path);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
partition->Size = 0;
|
||||
}
|
||||
partition->MountPoint = GetDeviceMountPoint (partition->Path);
|
||||
partition->SystemNumber = 0;
|
||||
}
|
||||
|
||||
device->Partitions.push_back (partition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
||||
MountedFilesystemList CoreFreeBSD::GetMountedFilesystems (const DevicePath &devicePath, const DirectoryPath &mountPoint) const
|
||||
{
|
||||
|
||||
static Mutex mutex;
|
||||
ScopeLock sl (mutex);
|
||||
|
||||
struct statfs *sysMountList;
|
||||
int count = getmntinfo (&sysMountList, MNT_NOWAIT);
|
||||
throw_sys_if (count == 0);
|
||||
|
||||
MountedFilesystemList mountedFilesystems;
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
make_shared_auto (MountedFilesystem, mf);
|
||||
|
||||
if (sysMountList[i].f_mntfromname[0])
|
||||
mf->Device = DevicePath (sysMountList[i].f_mntfromname);
|
||||
else
|
||||
continue;
|
||||
|
||||
if (sysMountList[i].f_mntonname[0])
|
||||
mf->MountPoint = DirectoryPath (sysMountList[i].f_mntonname);
|
||||
|
||||
mf->Type = sysMountList[i].f_fstypename;
|
||||
|
||||
if ((devicePath.IsEmpty() || devicePath == mf->Device) && (mountPoint.IsEmpty() || mountPoint == mf->MountPoint))
|
||||
mountedFilesystems.push_back (mf);
|
||||
}
|
||||
|
||||
return mountedFilesystems;
|
||||
}
|
||||
|
||||
void CoreFreeBSD::MountFilesystem (const DevicePath &devicePath, const DirectoryPath &mountPoint, const string &filesystemType, bool readOnly, const string &systemMountOptions) const
|
||||
{
|
||||
try
|
||||
{
|
||||
// Try to mount FAT by default as mount is unable to probe filesystem type on BSD
|
||||
CoreUnix::MountFilesystem (devicePath, mountPoint, filesystemType.empty() ? "msdos" : filesystemType, readOnly, systemMountOptions);
|
||||
}
|
||||
catch (ExecutedProcessFailed&)
|
||||
{
|
||||
if (!filesystemType.empty())
|
||||
throw;
|
||||
|
||||
CoreUnix::MountFilesystem (devicePath, mountPoint, filesystemType, readOnly, systemMountOptions);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TC_FREEBSD
|
||||
auto_ptr <CoreBase> Core (new CoreServiceProxy <CoreFreeBSD>);
|
||||
auto_ptr <CoreBase> CoreDirect (new CoreFreeBSD);
|
||||
#endif
|
||||
}
|
||||
37
src/Core/Unix/FreeBSD/CoreFreeBSD.h
Normal file
37
src/Core/Unix/FreeBSD/CoreFreeBSD.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
Copyright (c) 2008 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#ifndef TC_HEADER_Core_CoreFreeBSD
|
||||
#define TC_HEADER_Core_CoreFreeBSD
|
||||
|
||||
#include "System.h"
|
||||
#include "Core/Unix/CoreUnix.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
class CoreFreeBSD : public CoreUnix
|
||||
{
|
||||
public:
|
||||
CoreFreeBSD ();
|
||||
virtual ~CoreFreeBSD ();
|
||||
|
||||
virtual HostDeviceList GetHostDevices (bool pathListOnly = false) const;
|
||||
|
||||
protected:
|
||||
virtual DevicePath AttachFileToLoopDevice (const FilePath &filePath, bool readOnly) const;
|
||||
virtual void DetachLoopDevice (const DevicePath &devicePath) const;
|
||||
virtual MountedFilesystemList GetMountedFilesystems (const DevicePath &devicePath = DevicePath(), const DirectoryPath &mountPoint = DirectoryPath()) const;
|
||||
virtual void MountFilesystem (const DevicePath &devicePath, const DirectoryPath &mountPoint, const string &filesystemType, bool readOnly, const string &systemMountOptions) const;
|
||||
|
||||
private:
|
||||
CoreFreeBSD (const CoreFreeBSD &);
|
||||
CoreFreeBSD &operator= (const CoreFreeBSD &);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TC_HEADER_Core_CoreFreeBSD
|
||||
12
src/Core/Unix/FreeBSD/System.h
Normal file
12
src/Core/Unix/FreeBSD/System.h
Normal file
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
Copyright (c) 2008 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#ifndef TC_HEADER_Platform_FreeBSD_System
|
||||
#define TC_HEADER_Platform_FreeBSD_System
|
||||
|
||||
#endif // TC_HEADER_Platform_FreeBSD_System
|
||||
477
src/Core/Unix/Linux/CoreLinux.cpp
Normal file
477
src/Core/Unix/Linux/CoreLinux.cpp
Normal file
@@ -0,0 +1,477 @@
|
||||
/*
|
||||
Copyright (c) 2008-2010 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <mntent.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/wait.h>
|
||||
#include "CoreLinux.h"
|
||||
#include "Platform/SystemInfo.h"
|
||||
#include "Platform/TextReader.h"
|
||||
#include "Volume/EncryptionModeLRW.h"
|
||||
#include "Volume/EncryptionModeXTS.h"
|
||||
#include "Driver/Fuse/FuseService.h"
|
||||
#include "Core/Unix/CoreServiceProxy.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
CoreLinux::CoreLinux ()
|
||||
{
|
||||
}
|
||||
|
||||
CoreLinux::~CoreLinux ()
|
||||
{
|
||||
}
|
||||
|
||||
DevicePath CoreLinux::AttachFileToLoopDevice (const FilePath &filePath, bool readOnly) const
|
||||
{
|
||||
list <string> loopPaths;
|
||||
loopPaths.push_back ("/dev/loop");
|
||||
loopPaths.push_back ("/dev/loop/");
|
||||
loopPaths.push_back ("/dev/.static/dev/loop");
|
||||
|
||||
for (int devIndex = 0; devIndex < 256; devIndex++)
|
||||
{
|
||||
string loopDev;
|
||||
foreach (const string &loopPath, loopPaths)
|
||||
{
|
||||
loopDev = loopPath + StringConverter::ToSingle (devIndex);
|
||||
if (FilesystemPath (loopDev).IsBlockDevice())
|
||||
break;
|
||||
}
|
||||
|
||||
if (loopDev.empty())
|
||||
continue;
|
||||
|
||||
list <string> args;
|
||||
|
||||
list <string>::iterator readOnlyArg;
|
||||
if (readOnly)
|
||||
{
|
||||
args.push_back ("-r");
|
||||
readOnlyArg = --args.end();
|
||||
}
|
||||
|
||||
args.push_back ("--");
|
||||
args.push_back (loopDev);
|
||||
args.push_back (filePath);
|
||||
|
||||
try
|
||||
{
|
||||
Process::Execute ("losetup", args);
|
||||
return loopDev;
|
||||
}
|
||||
catch (ExecutedProcessFailed&)
|
||||
{
|
||||
if (readOnly)
|
||||
{
|
||||
try
|
||||
{
|
||||
args.erase (readOnlyArg);
|
||||
Process::Execute ("losetup", args);
|
||||
return loopDev;
|
||||
}
|
||||
catch (ExecutedProcessFailed&) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw LoopDeviceSetupFailed (SRC_POS, wstring (filePath));
|
||||
}
|
||||
|
||||
void CoreLinux::DetachLoopDevice (const DevicePath &devicePath) const
|
||||
{
|
||||
list <string> args;
|
||||
args.push_back ("-d");
|
||||
args.push_back (devicePath);
|
||||
|
||||
for (int t = 0; true; t++)
|
||||
{
|
||||
try
|
||||
{
|
||||
Process::Execute ("losetup", args);
|
||||
break;
|
||||
}
|
||||
catch (ExecutedProcessFailed&)
|
||||
{
|
||||
if (t > 5)
|
||||
throw;
|
||||
Thread::Sleep (200);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CoreLinux::DismountNativeVolume (shared_ptr <VolumeInfo> mountedVolume) const
|
||||
{
|
||||
string devPath = mountedVolume->VirtualDevice;
|
||||
|
||||
if (devPath.find ("/dev/mapper/truecrypt") != 0)
|
||||
throw NotApplicable (SRC_POS);
|
||||
|
||||
size_t devCount = 0;
|
||||
while (FilesystemPath (devPath).IsBlockDevice())
|
||||
{
|
||||
list <string> dmsetupArgs;
|
||||
dmsetupArgs.push_back ("remove");
|
||||
dmsetupArgs.push_back (StringConverter::Split (devPath, "/").back());
|
||||
|
||||
for (int t = 0; true; t++)
|
||||
{
|
||||
try
|
||||
{
|
||||
Process::Execute ("dmsetup", dmsetupArgs);
|
||||
break;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
if (t > 20)
|
||||
throw;
|
||||
|
||||
Thread::Sleep (100);
|
||||
}
|
||||
}
|
||||
|
||||
for (int t = 0; FilesystemPath (devPath).IsBlockDevice() && t < 20; t++)
|
||||
{
|
||||
Thread::Sleep (100);
|
||||
}
|
||||
|
||||
devPath = string (mountedVolume->VirtualDevice) + "_" + StringConverter::ToSingle (devCount++);
|
||||
}
|
||||
}
|
||||
|
||||
HostDeviceList CoreLinux::GetHostDevices (bool pathListOnly) const
|
||||
{
|
||||
HostDeviceList devices;
|
||||
TextReader tr ("/proc/partitions");
|
||||
|
||||
string line;
|
||||
while (tr.ReadLine (line))
|
||||
{
|
||||
vector <string> fields = StringConverter::Split (line);
|
||||
|
||||
if (fields.size() != 4
|
||||
|| fields[3].find ("loop") == 0 // skip loop devices
|
||||
|| fields[3].find ("cloop") == 0
|
||||
|| fields[3].find ("ram") == 0 // skip RAM devices
|
||||
|| fields[3].find ("dm-") == 0 // skip device mapper devices
|
||||
|| fields[2] == "1" // skip extended partitions
|
||||
)
|
||||
continue;
|
||||
|
||||
try
|
||||
{
|
||||
StringConverter::ToUInt32 (fields[0]);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
make_shared_auto (HostDevice, hostDevice);
|
||||
|
||||
hostDevice->Path = string (fields[3].find ("/dev/") == string::npos ? "/dev/" : "") + fields[3];
|
||||
|
||||
if (!pathListOnly)
|
||||
{
|
||||
hostDevice->Size = StringConverter::ToUInt64 (fields[2]) * 1024;
|
||||
hostDevice->MountPoint = GetDeviceMountPoint (hostDevice->Path);
|
||||
hostDevice->SystemNumber = 0;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
StringConverter::GetTrailingNumber (fields[3]);
|
||||
if (devices.size() > 0)
|
||||
{
|
||||
HostDevice &prevDev = **--devices.end();
|
||||
if (string (hostDevice->Path).find (prevDev.Path) == 0)
|
||||
{
|
||||
prevDev.Partitions.push_back (hostDevice);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...) { }
|
||||
|
||||
devices.push_back (hostDevice);
|
||||
continue;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
||||
MountedFilesystemList CoreLinux::GetMountedFilesystems (const DevicePath &devicePath, const DirectoryPath &mountPoint) const
|
||||
{
|
||||
MountedFilesystemList mountedFilesystems;
|
||||
DevicePath realDevicePath = devicePath;
|
||||
|
||||
if (!devicePath.IsEmpty())
|
||||
{
|
||||
char *resolvedPath = realpath (string (devicePath).c_str(), NULL);
|
||||
if (resolvedPath)
|
||||
{
|
||||
realDevicePath = resolvedPath;
|
||||
free (resolvedPath);
|
||||
}
|
||||
}
|
||||
|
||||
FILE *mtab = fopen ("/etc/mtab", "r");
|
||||
|
||||
if (!mtab)
|
||||
mtab = fopen ("/proc/mounts", "r");
|
||||
|
||||
throw_sys_sub_if (!mtab, "/proc/mounts");
|
||||
finally_do_arg (FILE *, mtab, { fclose (finally_arg); });
|
||||
|
||||
static Mutex mutex;
|
||||
ScopeLock sl (mutex);
|
||||
|
||||
struct mntent *entry;
|
||||
while ((entry = getmntent (mtab)) != nullptr)
|
||||
{
|
||||
make_shared_auto (MountedFilesystem, mf);
|
||||
|
||||
if (entry->mnt_fsname)
|
||||
mf->Device = DevicePath (entry->mnt_fsname);
|
||||
else
|
||||
continue;
|
||||
|
||||
if (entry->mnt_dir)
|
||||
mf->MountPoint = DirectoryPath (entry->mnt_dir);
|
||||
|
||||
if (entry->mnt_type)
|
||||
mf->Type = entry->mnt_type;
|
||||
|
||||
if ((devicePath.IsEmpty() || devicePath == mf->Device || realDevicePath == mf->Device) && (mountPoint.IsEmpty() || mountPoint == mf->MountPoint))
|
||||
mountedFilesystems.push_back (mf);
|
||||
}
|
||||
|
||||
return mountedFilesystems;
|
||||
}
|
||||
|
||||
void CoreLinux::MountFilesystem (const DevicePath &devicePath, const DirectoryPath &mountPoint, const string &filesystemType, bool readOnly, const string &systemMountOptions) const
|
||||
{
|
||||
bool fsMounted = false;
|
||||
|
||||
try
|
||||
{
|
||||
if (!FilesystemSupportsUnixPermissions (devicePath))
|
||||
{
|
||||
stringstream userMountOptions;
|
||||
userMountOptions << "uid=" << GetRealUserId() << ",gid=" << GetRealGroupId() << ",umask=077" << (!systemMountOptions.empty() ? "," : "");
|
||||
|
||||
CoreUnix::MountFilesystem (devicePath, mountPoint, filesystemType, readOnly, userMountOptions.str() + systemMountOptions);
|
||||
fsMounted = true;
|
||||
}
|
||||
}
|
||||
catch (...) { }
|
||||
|
||||
if (!fsMounted)
|
||||
CoreUnix::MountFilesystem (devicePath, mountPoint, filesystemType, readOnly, systemMountOptions);
|
||||
}
|
||||
|
||||
void CoreLinux::MountVolumeNative (shared_ptr <Volume> volume, MountOptions &options, const DirectoryPath &auxMountPoint) const
|
||||
{
|
||||
bool xts = (typeid (*volume->GetEncryptionMode()) == typeid (EncryptionModeXTS));
|
||||
bool lrw = (typeid (*volume->GetEncryptionMode()) == typeid (EncryptionModeLRW));
|
||||
|
||||
if (options.NoKernelCrypto
|
||||
|| (!xts && (!lrw || volume->GetEncryptionAlgorithm()->GetCiphers().size() > 1 || volume->GetEncryptionAlgorithm()->GetMinBlockSize() != 16))
|
||||
|| volume->GetProtectionType() == VolumeProtection::HiddenVolumeReadOnly)
|
||||
{
|
||||
throw NotApplicable (SRC_POS);
|
||||
}
|
||||
|
||||
if (!SystemInfo::IsVersionAtLeast (2, 6, xts ? 24 : 20))
|
||||
throw NotApplicable (SRC_POS);
|
||||
|
||||
// Load device mapper kernel module
|
||||
list <string> execArgs;
|
||||
foreach (const string &dmModule, StringConverter::Split ("dm_mod dm-mod dm"))
|
||||
{
|
||||
execArgs.clear();
|
||||
execArgs.push_back (dmModule);
|
||||
|
||||
try
|
||||
{
|
||||
Process::Execute ("modprobe", execArgs);
|
||||
break;
|
||||
}
|
||||
catch (...) { }
|
||||
}
|
||||
|
||||
bool loopDevAttached = false;
|
||||
bool nativeDevCreated = false;
|
||||
bool filesystemMounted = false;
|
||||
|
||||
// Attach volume to loopback device if required
|
||||
VolumePath volumePath = volume->GetPath();
|
||||
if (!volumePath.IsDevice())
|
||||
{
|
||||
volumePath = AttachFileToLoopDevice (volumePath, options.Protection == VolumeProtection::ReadOnly);
|
||||
loopDevAttached = true;
|
||||
}
|
||||
|
||||
string nativeDevPath;
|
||||
|
||||
try
|
||||
{
|
||||
// Create virtual device using device mapper
|
||||
size_t nativeDevCount = 0;
|
||||
size_t secondaryKeyOffset = volume->GetEncryptionMode()->GetKey().Size();
|
||||
size_t cipherCount = volume->GetEncryptionAlgorithm()->GetCiphers().size();
|
||||
|
||||
foreach_reverse_ref (const Cipher &cipher, volume->GetEncryptionAlgorithm()->GetCiphers())
|
||||
{
|
||||
stringstream dmCreateArgs;
|
||||
dmCreateArgs << "0 " << volume->GetSize() / ENCRYPTION_DATA_UNIT_SIZE << " crypt ";
|
||||
|
||||
// Mode
|
||||
dmCreateArgs << StringConverter::ToLower (StringConverter::ToSingle (cipher.GetName())) << (xts ? (SystemInfo::IsVersionAtLeast (2, 6, 33) ? "-xts-plain64 " : "-xts-plain ") : "-lrw-benbi ");
|
||||
|
||||
size_t keyArgOffset = dmCreateArgs.str().size();
|
||||
dmCreateArgs << setw (cipher.GetKeySize() * (xts ? 4 : 2) + (xts ? 0 : 16 * 2)) << 0 << setw (0);
|
||||
|
||||
// Sector and data unit offset
|
||||
uint64 startSector = volume->GetLayout()->GetDataOffset (volume->GetHostSize()) / ENCRYPTION_DATA_UNIT_SIZE;
|
||||
|
||||
dmCreateArgs << ' ' << (xts ? startSector + volume->GetEncryptionMode()->GetSectorOffset() : 0) << ' ';
|
||||
if (nativeDevCount == 0)
|
||||
dmCreateArgs << string (volumePath) << ' ' << startSector;
|
||||
else
|
||||
dmCreateArgs << nativeDevPath << " 0";
|
||||
|
||||
SecureBuffer dmCreateArgsBuf (dmCreateArgs.str().size());
|
||||
dmCreateArgsBuf.CopyFrom (ConstBufferPtr ((byte *) dmCreateArgs.str().c_str(), dmCreateArgs.str().size()));
|
||||
|
||||
// Keys
|
||||
const SecureBuffer &cipherKey = cipher.GetKey();
|
||||
secondaryKeyOffset -= cipherKey.Size();
|
||||
ConstBufferPtr secondaryKey = volume->GetEncryptionMode()->GetKey().GetRange (xts ? secondaryKeyOffset : 0, xts ? cipherKey.Size() : 16);
|
||||
|
||||
SecureBuffer hexStr (3);
|
||||
for (size_t i = 0; i < cipherKey.Size(); ++i)
|
||||
{
|
||||
sprintf ((char *) hexStr.Ptr(), "%02x", (int) cipherKey[i]);
|
||||
dmCreateArgsBuf.GetRange (keyArgOffset + i * 2, 2).CopyFrom (hexStr.GetRange (0, 2));
|
||||
|
||||
if (lrw && i >= 16)
|
||||
continue;
|
||||
|
||||
sprintf ((char *) hexStr.Ptr(), "%02x", (int) secondaryKey[i]);
|
||||
dmCreateArgsBuf.GetRange (keyArgOffset + cipherKey.Size() * 2 + i * 2, 2).CopyFrom (hexStr.GetRange (0, 2));
|
||||
}
|
||||
|
||||
stringstream nativeDevName;
|
||||
nativeDevName << "truecrypt" << options.SlotNumber;
|
||||
|
||||
if (nativeDevCount != cipherCount - 1)
|
||||
nativeDevName << "_" << cipherCount - nativeDevCount - 2;
|
||||
|
||||
nativeDevPath = "/dev/mapper/" + nativeDevName.str();
|
||||
|
||||
execArgs.clear();
|
||||
execArgs.push_back ("create");
|
||||
execArgs.push_back (nativeDevName.str());
|
||||
|
||||
Process::Execute ("dmsetup", execArgs, -1, nullptr, &dmCreateArgsBuf);
|
||||
|
||||
// Wait for the device to be created
|
||||
for (int t = 0; true; t++)
|
||||
{
|
||||
try
|
||||
{
|
||||
FilesystemPath (nativeDevPath).GetType();
|
||||
break;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
if (t > 20)
|
||||
throw;
|
||||
|
||||
Thread::Sleep (100);
|
||||
}
|
||||
}
|
||||
|
||||
nativeDevCreated = true;
|
||||
++nativeDevCount;
|
||||
}
|
||||
|
||||
// Test whether the device mapper is able to read and decrypt the last sector
|
||||
SecureBuffer lastSectorBuf (volume->GetSectorSize());
|
||||
uint64 lastSectorOffset = volume->GetSize() - volume->GetSectorSize();
|
||||
|
||||
File nativeDev;
|
||||
nativeDev.Open (nativeDevPath);
|
||||
nativeDev.ReadAt (lastSectorBuf, lastSectorOffset);
|
||||
|
||||
SecureBuffer lastSectorBuf2 (volume->GetSectorSize());
|
||||
volume->ReadSectors (lastSectorBuf2, lastSectorOffset);
|
||||
|
||||
if (memcmp (lastSectorBuf.Ptr(), lastSectorBuf2.Ptr(), volume->GetSectorSize()) != 0)
|
||||
throw KernelCryptoServiceTestFailed (SRC_POS);
|
||||
|
||||
// Mount filesystem
|
||||
if (!options.NoFilesystem && options.MountPoint && !options.MountPoint->IsEmpty())
|
||||
{
|
||||
MountFilesystem (nativeDevPath, *options.MountPoint,
|
||||
StringConverter::ToSingle (options.FilesystemType),
|
||||
options.Protection == VolumeProtection::ReadOnly,
|
||||
StringConverter::ToSingle (options.FilesystemOptions));
|
||||
|
||||
filesystemMounted = true;
|
||||
}
|
||||
|
||||
FuseService::SendAuxDeviceInfo (auxMountPoint, nativeDevPath, volumePath);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (filesystemMounted)
|
||||
DismountFilesystem (*options.MountPoint, true);
|
||||
}
|
||||
catch (...) { }
|
||||
|
||||
try
|
||||
{
|
||||
if (nativeDevCreated)
|
||||
{
|
||||
make_shared_auto (VolumeInfo, vol);
|
||||
vol->VirtualDevice = nativeDevPath;
|
||||
DismountNativeVolume (vol);
|
||||
}
|
||||
}
|
||||
catch (...) { }
|
||||
|
||||
try
|
||||
{
|
||||
if (loopDevAttached)
|
||||
DetachLoopDevice (volumePath);
|
||||
}
|
||||
catch (...) { }
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
auto_ptr <CoreBase> Core (new CoreServiceProxy <CoreLinux>);
|
||||
auto_ptr <CoreBase> CoreDirect (new CoreLinux);
|
||||
}
|
||||
39
src/Core/Unix/Linux/CoreLinux.h
Normal file
39
src/Core/Unix/Linux/CoreLinux.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Copyright (c) 2008 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#ifndef TC_HEADER_Core_CoreLinux
|
||||
#define TC_HEADER_Core_CoreLinux
|
||||
|
||||
#include "System.h"
|
||||
#include "Core/Unix/CoreUnix.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
class CoreLinux : public CoreUnix
|
||||
{
|
||||
public:
|
||||
CoreLinux ();
|
||||
virtual ~CoreLinux ();
|
||||
|
||||
virtual HostDeviceList GetHostDevices (bool pathListOnly = false) const;
|
||||
|
||||
protected:
|
||||
virtual DevicePath AttachFileToLoopDevice (const FilePath &filePath, bool readOnly) const;
|
||||
virtual void DetachLoopDevice (const DevicePath &devicePath) const;
|
||||
virtual void DismountNativeVolume (shared_ptr <VolumeInfo> mountedVolume) const;
|
||||
virtual MountedFilesystemList GetMountedFilesystems (const DevicePath &devicePath = DevicePath(), const DirectoryPath &mountPoint = DirectoryPath()) const;
|
||||
virtual void MountFilesystem (const DevicePath &devicePath, const DirectoryPath &mountPoint, const string &filesystemType, bool readOnly, const string &systemMountOptions) const;
|
||||
virtual void MountVolumeNative (shared_ptr <Volume> volume, MountOptions &options, const DirectoryPath &auxMountPoint) const;
|
||||
|
||||
private:
|
||||
CoreLinux (const CoreLinux &);
|
||||
CoreLinux &operator= (const CoreLinux &);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TC_HEADER_Core_CoreLinux
|
||||
12
src/Core/Unix/Linux/System.h
Normal file
12
src/Core/Unix/Linux/System.h
Normal file
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
Copyright (c) 2008 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#ifndef TC_HEADER_Platform_Linux_System
|
||||
#define TC_HEADER_Platform_Linux_System
|
||||
|
||||
#endif // TC_HEADER_Platform_Linux_System
|
||||
215
src/Core/Unix/MacOSX/CoreMacOSX.cpp
Normal file
215
src/Core/Unix/MacOSX/CoreMacOSX.cpp
Normal file
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
Copyright (c) 2008-2009 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#include <fstream>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/ucred.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include "CoreMacOSX.h"
|
||||
#include "Driver/Fuse/FuseService.h"
|
||||
#include "Core/Unix/CoreServiceProxy.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
CoreMacOSX::CoreMacOSX ()
|
||||
{
|
||||
}
|
||||
|
||||
CoreMacOSX::~CoreMacOSX ()
|
||||
{
|
||||
}
|
||||
|
||||
shared_ptr <VolumeInfo> CoreMacOSX::DismountVolume (shared_ptr <VolumeInfo> mountedVolume, bool ignoreOpenFiles, bool syncVolumeInfo)
|
||||
{
|
||||
if (!mountedVolume->VirtualDevice.IsEmpty() && mountedVolume->VirtualDevice.IsBlockDevice())
|
||||
{
|
||||
list <string> args;
|
||||
args.push_back ("detach");
|
||||
args.push_back (mountedVolume->VirtualDevice);
|
||||
|
||||
if (ignoreOpenFiles)
|
||||
args.push_back ("-force");
|
||||
|
||||
try
|
||||
{
|
||||
Process::Execute ("hdiutil", args);
|
||||
}
|
||||
catch (ExecutedProcessFailed &e)
|
||||
{
|
||||
if (!ignoreOpenFiles)
|
||||
{
|
||||
string err = e.GetErrorOutput();
|
||||
|
||||
if (err.find ("couldn't unmount") != string::npos
|
||||
|| err.find ("busy") != string::npos
|
||||
|| err.find ("49153") != string::npos)
|
||||
{
|
||||
throw MountedVolumeInUse (SRC_POS);
|
||||
}
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
if (syncVolumeInfo || mountedVolume->Protection == VolumeProtection::HiddenVolumeReadOnly)
|
||||
{
|
||||
sync();
|
||||
VolumeInfoList ml = GetMountedVolumes (mountedVolume->Path);
|
||||
|
||||
if (ml.size() > 0)
|
||||
mountedVolume = ml.front();
|
||||
}
|
||||
|
||||
list <string> args;
|
||||
args.push_back ("--");
|
||||
args.push_back (mountedVolume->AuxMountPoint);
|
||||
|
||||
for (int t = 0; true; t++)
|
||||
{
|
||||
try
|
||||
{
|
||||
Process::Execute ("umount", args);
|
||||
break;
|
||||
}
|
||||
catch (ExecutedProcessFailed&)
|
||||
{
|
||||
if (t > 10)
|
||||
throw;
|
||||
Thread::Sleep (200);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
mountedVolume->AuxMountPoint.Delete();
|
||||
}
|
||||
catch (...) { }
|
||||
|
||||
return mountedVolume;
|
||||
}
|
||||
|
||||
void CoreMacOSX::CheckFilesystem (shared_ptr <VolumeInfo> mountedVolume, bool repair) const
|
||||
{
|
||||
list <string> args;
|
||||
args.push_back ("/Applications/Utilities/Disk Utility.app");
|
||||
Process::Execute ("open", args);
|
||||
}
|
||||
|
||||
void CoreMacOSX::MountAuxVolumeImage (const DirectoryPath &auxMountPoint, const MountOptions &options) const
|
||||
{
|
||||
// Check FUSE version
|
||||
char fuseVersionString[MAXHOSTNAMELEN + 1] = { 0 };
|
||||
size_t fuseVersionStringLength = MAXHOSTNAMELEN;
|
||||
|
||||
if (sysctlbyname ("macfuse.version.number", fuseVersionString, &fuseVersionStringLength, NULL, 0) != 0)
|
||||
throw HigherFuseVersionRequired (SRC_POS);
|
||||
|
||||
vector <string> fuseVersion = StringConverter::Split (string (fuseVersionString), ".");
|
||||
if (fuseVersion.size() < 2)
|
||||
throw HigherFuseVersionRequired (SRC_POS);
|
||||
|
||||
uint32 fuseVersionMajor = StringConverter::ToUInt32 (fuseVersion[0]);
|
||||
uint32 fuseVersionMinor = StringConverter::ToUInt32 (fuseVersion[1]);
|
||||
|
||||
if (fuseVersionMajor < 1 || (fuseVersionMajor == 1 && fuseVersionMinor < 3))
|
||||
throw HigherFuseVersionRequired (SRC_POS);
|
||||
|
||||
// Mount volume image
|
||||
string volImage = string (auxMountPoint) + FuseService::GetVolumeImagePath();
|
||||
|
||||
list <string> args;
|
||||
args.push_back ("attach");
|
||||
args.push_back (volImage);
|
||||
args.push_back ("-plist");
|
||||
args.push_back ("-noautofsck");
|
||||
args.push_back ("-imagekey");
|
||||
args.push_back ("diskimage-class=CRawDiskImage");
|
||||
|
||||
if (!options.NoFilesystem && options.MountPoint && !options.MountPoint->IsEmpty())
|
||||
{
|
||||
args.push_back ("-mount");
|
||||
args.push_back ("required");
|
||||
|
||||
// Let the system specify mount point except when the user specified a non-default one
|
||||
if (string (*options.MountPoint).find (GetDefaultMountPointPrefix()) != 0)
|
||||
{
|
||||
args.push_back ("-mountpoint");
|
||||
args.push_back (*options.MountPoint);
|
||||
}
|
||||
}
|
||||
else
|
||||
args.push_back ("-nomount");
|
||||
|
||||
if (options.Protection == VolumeProtection::ReadOnly)
|
||||
args.push_back ("-readonly");
|
||||
|
||||
string xml;
|
||||
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
xml = Process::Execute ("hdiutil", args);
|
||||
break;
|
||||
}
|
||||
catch (ExecutedProcessFailed &e)
|
||||
{
|
||||
if (e.GetErrorOutput().find ("noautofsck") != string::npos)
|
||||
{
|
||||
args.remove ("-noautofsck");
|
||||
continue;
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
size_t p = xml.find ("<key>dev-entry</key>");
|
||||
if (p == string::npos)
|
||||
throw ParameterIncorrect (SRC_POS);
|
||||
|
||||
p = xml.find ("<string>", p);
|
||||
if (p == string::npos)
|
||||
throw ParameterIncorrect (SRC_POS);
|
||||
p += 8;
|
||||
|
||||
size_t e = xml.find ("</string>", p);
|
||||
if (e == string::npos)
|
||||
throw ParameterIncorrect (SRC_POS);
|
||||
|
||||
DevicePath virtualDev = StringConverter::Trim (xml.substr (p, e - p));
|
||||
|
||||
try
|
||||
{
|
||||
FuseService::SendAuxDeviceInfo (auxMountPoint, virtualDev);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
try
|
||||
{
|
||||
list <string> args;
|
||||
args.push_back ("detach");
|
||||
args.push_back (volImage);
|
||||
args.push_back ("-force");
|
||||
|
||||
Process::Execute ("hdiutil", args);
|
||||
}
|
||||
catch (ExecutedProcessFailed&) { }
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
auto_ptr <CoreBase> Core (new CoreServiceProxy <CoreMacOSX>);
|
||||
auto_ptr <CoreBase> CoreDirect (new CoreMacOSX);
|
||||
}
|
||||
36
src/Core/Unix/MacOSX/CoreMacOSX.h
Normal file
36
src/Core/Unix/MacOSX/CoreMacOSX.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
Copyright (c) 2008-2009 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#ifndef TC_HEADER_Core_CoreMacOSX
|
||||
#define TC_HEADER_Core_CoreMacOSX
|
||||
|
||||
#include "System.h"
|
||||
#include "Core/Unix/FreeBSD/CoreFreeBSD.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
class CoreMacOSX : public CoreFreeBSD
|
||||
{
|
||||
public:
|
||||
CoreMacOSX ();
|
||||
virtual ~CoreMacOSX ();
|
||||
|
||||
virtual void CheckFilesystem (shared_ptr <VolumeInfo> mountedVolume, bool repair = false) const;
|
||||
virtual shared_ptr <VolumeInfo> DismountVolume (shared_ptr <VolumeInfo> mountedVolume, bool ignoreOpenFiles = false, bool syncVolumeInfo = false);
|
||||
virtual string GetDefaultMountPointPrefix () const { return "/Volumes/truecrypt"; }
|
||||
|
||||
protected:
|
||||
virtual void MountAuxVolumeImage (const DirectoryPath &auxMountPoint, const MountOptions &options) const;
|
||||
|
||||
private:
|
||||
CoreMacOSX (const CoreMacOSX &);
|
||||
CoreMacOSX &operator= (const CoreMacOSX &);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TC_HEADER_Core_CoreMacOSX
|
||||
12
src/Core/Unix/MacOSX/System.h
Normal file
12
src/Core/Unix/MacOSX/System.h
Normal file
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
Copyright (c) 2008 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#ifndef TC_HEADER_Platform_MacOSX_System
|
||||
#define TC_HEADER_Platform_MacOSX_System
|
||||
|
||||
#endif // TC_HEADER_Platform_MacOSX_System
|
||||
27
src/Core/Unix/MountedFilesystem.h
Normal file
27
src/Core/Unix/MountedFilesystem.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (c) 2008 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#ifndef TC_HEADER_Core_Unix_MountedFilesystem
|
||||
#define TC_HEADER_Core_Unix_MountedFilesystem
|
||||
|
||||
#include "Platform/Platform.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
struct MountedFilesystem
|
||||
{
|
||||
public:
|
||||
DevicePath Device;
|
||||
DirectoryPath MountPoint;
|
||||
string Type;
|
||||
};
|
||||
|
||||
typedef list < shared_ptr <MountedFilesystem> > MountedFilesystemList;
|
||||
}
|
||||
|
||||
#endif // TC_HEADER_Core_Unix_MountedFilesystem
|
||||
174
src/Core/Unix/Solaris/CoreSolaris.cpp
Normal file
174
src/Core/Unix/Solaris/CoreSolaris.cpp
Normal file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
Copyright (c) 2008-2009 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/mntent.h>
|
||||
#include <sys/mnttab.h>
|
||||
#include "CoreSolaris.h"
|
||||
#include "Core/Unix/CoreServiceProxy.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
CoreSolaris::CoreSolaris ()
|
||||
{
|
||||
}
|
||||
|
||||
CoreSolaris::~CoreSolaris ()
|
||||
{
|
||||
}
|
||||
|
||||
DevicePath CoreSolaris::AttachFileToLoopDevice (const FilePath &filePath, bool readOnly) const
|
||||
{
|
||||
list <string> args;
|
||||
args.push_back ("-a");
|
||||
args.push_back (filePath);
|
||||
|
||||
return StringConverter::Trim (Process::Execute ("lofiadm", args));
|
||||
}
|
||||
|
||||
void CoreSolaris::DetachLoopDevice (const DevicePath &devicePath) const
|
||||
{
|
||||
list <string> args;
|
||||
args.push_back ("-d");
|
||||
args.push_back (devicePath);
|
||||
|
||||
for (int t = 0; true; t++)
|
||||
{
|
||||
try
|
||||
{
|
||||
Process::Execute ("lofiadm", args);
|
||||
break;
|
||||
}
|
||||
catch (ExecutedProcessFailed&)
|
||||
{
|
||||
if (t > 5)
|
||||
throw;
|
||||
Thread::Sleep (200);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HostDeviceList CoreSolaris::GetHostDevices (bool pathListOnly) const
|
||||
{
|
||||
HostDeviceList devices;
|
||||
|
||||
foreach_ref (const FilePath &devPath, Directory::GetFilePaths ("/dev/rdsk", false))
|
||||
{
|
||||
string drivePath = devPath;
|
||||
if (drivePath.rfind ("p0") == drivePath.size() - 2)
|
||||
{
|
||||
make_shared_auto (HostDevice, device);
|
||||
device->Path = drivePath;
|
||||
|
||||
try
|
||||
{
|
||||
device->Size = GetDeviceSize (device->Path);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
device->Size = 0;
|
||||
}
|
||||
|
||||
if (device->Size == 0)
|
||||
continue;
|
||||
|
||||
device->MountPoint = GetDeviceMountPoint (device->Path);
|
||||
device->SystemNumber = 0;
|
||||
|
||||
devices.push_back (device);
|
||||
|
||||
for (int partNumber = 1; partNumber <= 32; partNumber++)
|
||||
{
|
||||
stringstream partPath;
|
||||
partPath << drivePath.substr (0, drivePath.size() - 1) << partNumber;
|
||||
|
||||
if (FilesystemPath (partPath.str()).IsBlockDevice() || FilesystemPath (partPath.str()).IsCharacterDevice())
|
||||
{
|
||||
make_shared_auto (HostDevice, partition);
|
||||
partition->Path = partPath.str();
|
||||
|
||||
try
|
||||
{
|
||||
partition->Size = GetDeviceSize (partition->Path);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
partition->Size = 0;
|
||||
}
|
||||
|
||||
if (partition->Size == 0)
|
||||
continue;
|
||||
|
||||
partition->MountPoint = GetDeviceMountPoint (partition->Path);
|
||||
partition->SystemNumber = 0;
|
||||
|
||||
device->Partitions.push_back (partition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
||||
MountedFilesystemList CoreSolaris::GetMountedFilesystems (const DevicePath &devicePath, const DirectoryPath &mountPoint) const
|
||||
{
|
||||
MountedFilesystemList mountedFilesystems;
|
||||
|
||||
FILE *mtab = fopen ("/etc/mnttab", "r");
|
||||
throw_sys_sub_if (!mtab, "/etc/mnttab");
|
||||
finally_do_arg (FILE *, mtab, { fclose (finally_arg); });
|
||||
|
||||
int getmntentResult;
|
||||
struct mnttab entry;
|
||||
while ((getmntentResult = getmntent (mtab, &entry)) == 0)
|
||||
{
|
||||
make_shared_auto (MountedFilesystem, mf);
|
||||
|
||||
if (entry.mnt_special)
|
||||
mf->Device = DevicePath (entry.mnt_special);
|
||||
else
|
||||
continue;
|
||||
|
||||
if (entry.mnt_mountp)
|
||||
mf->MountPoint = DirectoryPath (entry.mnt_mountp);
|
||||
|
||||
if (entry.mnt_fstype)
|
||||
mf->Type = entry.mnt_fstype;
|
||||
|
||||
if ((devicePath.IsEmpty() || devicePath == mf->Device) && (mountPoint.IsEmpty() || mountPoint == mf->MountPoint))
|
||||
mountedFilesystems.push_back (mf);
|
||||
}
|
||||
|
||||
throw_sys_if (getmntentResult > 0);
|
||||
|
||||
return mountedFilesystems;
|
||||
}
|
||||
|
||||
void CoreSolaris::MountFilesystem (const DevicePath &devicePath, const DirectoryPath &mountPoint, const string &filesystemType, bool readOnly, const string &systemMountOptions) const
|
||||
{
|
||||
try
|
||||
{
|
||||
// Try to mount FAT by default as mount is unable to probe filesystem type on Solaris
|
||||
CoreUnix::MountFilesystem (devicePath, mountPoint, filesystemType.empty() ? "pcfs" : filesystemType, readOnly, systemMountOptions);
|
||||
}
|
||||
catch (ExecutedProcessFailed&)
|
||||
{
|
||||
if (!filesystemType.empty())
|
||||
throw;
|
||||
|
||||
CoreUnix::MountFilesystem (devicePath, mountPoint, filesystemType, readOnly, systemMountOptions);
|
||||
}
|
||||
}
|
||||
|
||||
auto_ptr <CoreBase> Core (new CoreServiceProxy <CoreSolaris>);
|
||||
auto_ptr <CoreBase> CoreDirect (new CoreSolaris);
|
||||
}
|
||||
37
src/Core/Unix/Solaris/CoreSolaris.h
Normal file
37
src/Core/Unix/Solaris/CoreSolaris.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
Copyright (c) 2008-2009 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#ifndef TC_HEADER_Core_CoreSolaris
|
||||
#define TC_HEADER_Core_CoreSolaris
|
||||
|
||||
#include "System.h"
|
||||
#include "Core/Unix/CoreUnix.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
class CoreSolaris : public CoreUnix
|
||||
{
|
||||
public:
|
||||
CoreSolaris ();
|
||||
virtual ~CoreSolaris ();
|
||||
|
||||
virtual HostDeviceList GetHostDevices (bool pathListOnly = false) const;
|
||||
|
||||
protected:
|
||||
virtual DevicePath AttachFileToLoopDevice (const FilePath &filePath, bool readOnly) const;
|
||||
virtual void DetachLoopDevice (const DevicePath &devicePath) const;
|
||||
virtual MountedFilesystemList GetMountedFilesystems (const DevicePath &devicePath = DevicePath(), const DirectoryPath &mountPoint = DirectoryPath()) const;
|
||||
virtual void MountFilesystem (const DevicePath &devicePath, const DirectoryPath &mountPoint, const string &filesystemType, bool readOnly, const string &systemMountOptions) const;
|
||||
|
||||
private:
|
||||
CoreSolaris (const CoreSolaris &);
|
||||
CoreSolaris &operator= (const CoreSolaris &);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TC_HEADER_Core_CoreSolaris
|
||||
12
src/Core/Unix/Solaris/System.h
Normal file
12
src/Core/Unix/Solaris/System.h
Normal file
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
Copyright (c) 2008-2009 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#ifndef TC_HEADER_Platform_Solaris_System
|
||||
#define TC_HEADER_Platform_Solaris_System
|
||||
|
||||
#endif // TC_HEADER_Platform_Solaris_System
|
||||
12
src/Core/Unix/System.h
Normal file
12
src/Core/Unix/System.h
Normal file
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
Copyright (c) 2008 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#ifndef TC_HEADER_Platform_Unix_System
|
||||
#define TC_HEADER_Platform_Unix_System
|
||||
|
||||
#endif // TC_HEADER_Platform_Unix_System
|
||||
345
src/Core/VolumeCreator.cpp
Normal file
345
src/Core/VolumeCreator.cpp
Normal file
@@ -0,0 +1,345 @@
|
||||
/*
|
||||
Copyright (c) 2008-2010 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#include "Volume/EncryptionTest.h"
|
||||
#include "Volume/EncryptionModeXTS.h"
|
||||
#include "Core.h"
|
||||
|
||||
#ifdef TC_UNIX
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "VolumeCreator.h"
|
||||
#include "FatFormatter.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
VolumeCreator::VolumeCreator ()
|
||||
: SizeDone (0)
|
||||
{
|
||||
}
|
||||
|
||||
VolumeCreator::~VolumeCreator ()
|
||||
{
|
||||
}
|
||||
|
||||
void VolumeCreator::Abort ()
|
||||
{
|
||||
AbortRequested = true;
|
||||
}
|
||||
|
||||
void VolumeCreator::CheckResult ()
|
||||
{
|
||||
if (ThreadException)
|
||||
ThreadException->Throw();
|
||||
}
|
||||
|
||||
void VolumeCreator::CreationThread ()
|
||||
{
|
||||
try
|
||||
{
|
||||
uint64 endOffset;
|
||||
uint64 filesystemSize = Layout->GetDataSize (HostSize);
|
||||
|
||||
if (filesystemSize < 1)
|
||||
throw ParameterIncorrect (SRC_POS);
|
||||
|
||||
DataStart = Layout->GetDataOffset (HostSize);
|
||||
WriteOffset = DataStart;
|
||||
endOffset = DataStart + Layout->GetDataSize (HostSize);
|
||||
|
||||
VolumeFile->SeekAt (DataStart);
|
||||
|
||||
// Create filesystem
|
||||
if (Options->Filesystem == VolumeCreationOptions::FilesystemType::FAT)
|
||||
{
|
||||
if (filesystemSize < TC_MIN_FAT_FS_SIZE || filesystemSize > TC_MAX_FAT_SECTOR_COUNT * Options->SectorSize)
|
||||
throw ParameterIncorrect (SRC_POS);
|
||||
|
||||
struct WriteSectorCallback : public FatFormatter::WriteSectorCallback
|
||||
{
|
||||
WriteSectorCallback (VolumeCreator *creator) : Creator (creator), OutputBuffer (File::GetOptimalWriteSize()), OutputBufferWritePos (0) { }
|
||||
|
||||
virtual bool operator() (const BufferPtr §or)
|
||||
{
|
||||
OutputBuffer.GetRange (OutputBufferWritePos, sector.Size()).CopyFrom (sector);
|
||||
OutputBufferWritePos += sector.Size();
|
||||
|
||||
if (OutputBufferWritePos >= OutputBuffer.Size())
|
||||
FlushOutputBuffer();
|
||||
|
||||
return !Creator->AbortRequested;
|
||||
}
|
||||
|
||||
void FlushOutputBuffer ()
|
||||
{
|
||||
if (OutputBufferWritePos > 0)
|
||||
{
|
||||
Creator->Options->EA->EncryptSectors (OutputBuffer.GetRange (0, OutputBufferWritePos),
|
||||
Creator->WriteOffset / ENCRYPTION_DATA_UNIT_SIZE, OutputBufferWritePos / ENCRYPTION_DATA_UNIT_SIZE, ENCRYPTION_DATA_UNIT_SIZE);
|
||||
|
||||
Creator->VolumeFile->Write (OutputBuffer.GetRange (0, OutputBufferWritePos));
|
||||
|
||||
Creator->WriteOffset += OutputBufferWritePos;
|
||||
Creator->SizeDone.Set (Creator->WriteOffset - Creator->DataStart);
|
||||
|
||||
OutputBufferWritePos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
VolumeCreator *Creator;
|
||||
SecureBuffer OutputBuffer;
|
||||
size_t OutputBufferWritePos;
|
||||
};
|
||||
|
||||
WriteSectorCallback sectorWriter (this);
|
||||
FatFormatter::Format (sectorWriter, filesystemSize, Options->FilesystemClusterSize, Options->SectorSize);
|
||||
sectorWriter.FlushOutputBuffer();
|
||||
}
|
||||
|
||||
if (!Options->Quick)
|
||||
{
|
||||
// Empty sectors are encrypted with different key to randomize plaintext
|
||||
Core->RandomizeEncryptionAlgorithmKey (Options->EA);
|
||||
|
||||
SecureBuffer outputBuffer (File::GetOptimalWriteSize());
|
||||
uint64 dataFragmentLength = outputBuffer.Size();
|
||||
|
||||
while (!AbortRequested && WriteOffset < endOffset)
|
||||
{
|
||||
if (WriteOffset + dataFragmentLength > endOffset)
|
||||
dataFragmentLength = endOffset - WriteOffset;
|
||||
|
||||
outputBuffer.Zero();
|
||||
Options->EA->EncryptSectors (outputBuffer, WriteOffset / ENCRYPTION_DATA_UNIT_SIZE, dataFragmentLength / ENCRYPTION_DATA_UNIT_SIZE, ENCRYPTION_DATA_UNIT_SIZE);
|
||||
VolumeFile->Write (outputBuffer, (size_t) dataFragmentLength);
|
||||
|
||||
WriteOffset += dataFragmentLength;
|
||||
SizeDone.Set (WriteOffset - DataStart);
|
||||
}
|
||||
}
|
||||
|
||||
if (!AbortRequested)
|
||||
{
|
||||
SizeDone.Set (Options->Size);
|
||||
|
||||
// Backup header
|
||||
SecureBuffer backupHeader (Layout->GetHeaderSize());
|
||||
|
||||
SecureBuffer backupHeaderSalt (VolumeHeader::GetSaltSize());
|
||||
RandomNumberGenerator::GetData (backupHeaderSalt);
|
||||
|
||||
Options->VolumeHeaderKdf->DeriveKey (HeaderKey, *PasswordKey, backupHeaderSalt);
|
||||
|
||||
Layout->GetHeader()->EncryptNew (backupHeader, backupHeaderSalt, HeaderKey, Options->VolumeHeaderKdf);
|
||||
|
||||
if (Options->Quick || Options->Type == VolumeType::Hidden)
|
||||
VolumeFile->SeekEnd (Layout->GetBackupHeaderOffset());
|
||||
|
||||
VolumeFile->Write (backupHeader);
|
||||
|
||||
if (Options->Type == VolumeType::Normal)
|
||||
{
|
||||
// Write random data to space reserved for hidden volume backup header
|
||||
Core->RandomizeEncryptionAlgorithmKey (Options->EA);
|
||||
Options->EA->Encrypt (backupHeader);
|
||||
|
||||
VolumeFile->Write (backupHeader);
|
||||
}
|
||||
|
||||
VolumeFile->Flush();
|
||||
}
|
||||
}
|
||||
catch (Exception &e)
|
||||
{
|
||||
ThreadException.reset (e.CloneNew());
|
||||
}
|
||||
catch (exception &e)
|
||||
{
|
||||
ThreadException.reset (new ExternalException (SRC_POS, StringConverter::ToExceptionString (e)));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
ThreadException.reset (new UnknownException (SRC_POS));
|
||||
}
|
||||
|
||||
VolumeFile.reset();
|
||||
mProgressInfo.CreationInProgress = false;
|
||||
}
|
||||
|
||||
void VolumeCreator::CreateVolume (shared_ptr <VolumeCreationOptions> options)
|
||||
{
|
||||
EncryptionTest::TestAll();
|
||||
|
||||
{
|
||||
#ifdef TC_UNIX
|
||||
// Temporarily take ownership of a device if the user is not an administrator
|
||||
UserId origDeviceOwner ((uid_t) -1);
|
||||
|
||||
if (!Core->HasAdminPrivileges() && options->Path.IsDevice())
|
||||
{
|
||||
origDeviceOwner = FilesystemPath (wstring (options->Path)).GetOwner();
|
||||
Core->SetFileOwner (options->Path, UserId (getuid()));
|
||||
}
|
||||
|
||||
finally_do_arg2 (FilesystemPath, options->Path, UserId, origDeviceOwner,
|
||||
{
|
||||
if (finally_arg2.SystemId != (uid_t) -1)
|
||||
Core->SetFileOwner (finally_arg, finally_arg2);
|
||||
});
|
||||
#endif
|
||||
|
||||
VolumeFile.reset (new File);
|
||||
VolumeFile->Open (options->Path,
|
||||
(options->Path.IsDevice() || options->Type == VolumeType::Hidden) ? File::OpenReadWrite : File::CreateReadWrite,
|
||||
File::ShareNone);
|
||||
|
||||
HostSize = VolumeFile->Length();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Sector size
|
||||
if (options->Path.IsDevice())
|
||||
{
|
||||
options->SectorSize = VolumeFile->GetDeviceSectorSize();
|
||||
|
||||
if (options->SectorSize < TC_MIN_VOLUME_SECTOR_SIZE
|
||||
|| options->SectorSize > TC_MAX_VOLUME_SECTOR_SIZE
|
||||
#if !defined (TC_LINUX)
|
||||
|| options->SectorSize != TC_SECTOR_SIZE_LEGACY
|
||||
#endif
|
||||
|| options->SectorSize % ENCRYPTION_DATA_UNIT_SIZE != 0)
|
||||
{
|
||||
throw UnsupportedSectorSize (SRC_POS);
|
||||
}
|
||||
}
|
||||
else
|
||||
options->SectorSize = TC_SECTOR_SIZE_FILE_HOSTED_VOLUME;
|
||||
|
||||
// Volume layout
|
||||
switch (options->Type)
|
||||
{
|
||||
case VolumeType::Normal:
|
||||
Layout.reset (new VolumeLayoutV2Normal());
|
||||
break;
|
||||
|
||||
case VolumeType::Hidden:
|
||||
Layout.reset (new VolumeLayoutV2Hidden());
|
||||
|
||||
if (HostSize < TC_MIN_HIDDEN_VOLUME_HOST_SIZE)
|
||||
throw ParameterIncorrect (SRC_POS);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw ParameterIncorrect (SRC_POS);
|
||||
}
|
||||
|
||||
// Volume header
|
||||
shared_ptr <VolumeHeader> header (Layout->GetHeader());
|
||||
SecureBuffer headerBuffer (Layout->GetHeaderSize());
|
||||
|
||||
VolumeHeaderCreationOptions headerOptions;
|
||||
headerOptions.EA = options->EA;
|
||||
headerOptions.Kdf = options->VolumeHeaderKdf;
|
||||
headerOptions.Type = options->Type;
|
||||
|
||||
headerOptions.SectorSize = options->SectorSize;
|
||||
|
||||
if (options->Type == VolumeType::Hidden)
|
||||
headerOptions.VolumeDataStart = HostSize - Layout->GetHeaderSize() * 2 - options->Size;
|
||||
else
|
||||
headerOptions.VolumeDataStart = Layout->GetHeaderSize() * 2;
|
||||
|
||||
headerOptions.VolumeDataSize = Layout->GetMaxDataSize (options->Size);
|
||||
|
||||
if (headerOptions.VolumeDataSize < 1)
|
||||
throw ParameterIncorrect (SRC_POS);
|
||||
|
||||
// Master data key
|
||||
MasterKey.Allocate (options->EA->GetKeySize() * 2);
|
||||
RandomNumberGenerator::GetData (MasterKey);
|
||||
headerOptions.DataKey = MasterKey;
|
||||
|
||||
// PKCS5 salt
|
||||
SecureBuffer salt (VolumeHeader::GetSaltSize());
|
||||
RandomNumberGenerator::GetData (salt);
|
||||
headerOptions.Salt = salt;
|
||||
|
||||
// Header key
|
||||
HeaderKey.Allocate (VolumeHeader::GetLargestSerializedKeySize());
|
||||
PasswordKey = Keyfile::ApplyListToPassword (options->Keyfiles, options->Password);
|
||||
options->VolumeHeaderKdf->DeriveKey (HeaderKey, *PasswordKey, salt);
|
||||
headerOptions.HeaderKey = HeaderKey;
|
||||
|
||||
header->Create (headerBuffer, headerOptions);
|
||||
|
||||
// Write new header
|
||||
if (Layout->GetHeaderOffset() >= 0)
|
||||
VolumeFile->SeekAt (Layout->GetHeaderOffset());
|
||||
else
|
||||
VolumeFile->SeekEnd (Layout->GetHeaderOffset());
|
||||
|
||||
VolumeFile->Write (headerBuffer);
|
||||
|
||||
if (options->Type == VolumeType::Normal)
|
||||
{
|
||||
// Write random data to space reserved for hidden volume header
|
||||
Core->RandomizeEncryptionAlgorithmKey (options->EA);
|
||||
options->EA->Encrypt (headerBuffer);
|
||||
|
||||
VolumeFile->Write (headerBuffer);
|
||||
}
|
||||
|
||||
// Data area keys
|
||||
options->EA->SetKey (MasterKey.GetRange (0, options->EA->GetKeySize()));
|
||||
shared_ptr <EncryptionMode> mode (new EncryptionModeXTS ());
|
||||
mode->SetKey (MasterKey.GetRange (options->EA->GetKeySize(), options->EA->GetKeySize()));
|
||||
options->EA->SetMode (mode);
|
||||
|
||||
Options = options;
|
||||
AbortRequested = false;
|
||||
|
||||
mProgressInfo.CreationInProgress = true;
|
||||
|
||||
struct ThreadFunctor : public Functor
|
||||
{
|
||||
ThreadFunctor (VolumeCreator *creator) : Creator (creator) { }
|
||||
virtual void operator() ()
|
||||
{
|
||||
Creator->CreationThread ();
|
||||
}
|
||||
VolumeCreator *Creator;
|
||||
};
|
||||
|
||||
Thread thread;
|
||||
thread.Start (new ThreadFunctor (this));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
VolumeFile.reset();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
VolumeCreator::KeyInfo VolumeCreator::GetKeyInfo () const
|
||||
{
|
||||
KeyInfo info;
|
||||
info.HeaderKey = HeaderKey;
|
||||
info.MasterKey = MasterKey;
|
||||
return info;
|
||||
}
|
||||
|
||||
VolumeCreator::ProgressInfo VolumeCreator::GetProgressInfo ()
|
||||
{
|
||||
mProgressInfo.SizeDone = SizeDone.Get();
|
||||
return mProgressInfo;
|
||||
}
|
||||
}
|
||||
119
src/Core/VolumeCreator.h
Normal file
119
src/Core/VolumeCreator.h
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
Copyright (c) 2008-2010 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#ifndef TC_HEADER_Volume_VolumeCreator
|
||||
#define TC_HEADER_Volume_VolumeCreator
|
||||
|
||||
#include "Platform/Platform.h"
|
||||
#include "Volume/Volume.h"
|
||||
#include "RandomNumberGenerator.h"
|
||||
|
||||
namespace TrueCrypt
|
||||
{
|
||||
|
||||
struct VolumeCreationOptions
|
||||
{
|
||||
VolumePath Path;
|
||||
VolumeType::Enum Type;
|
||||
uint64 Size;
|
||||
shared_ptr <VolumePassword> Password;
|
||||
shared_ptr <KeyfileList> Keyfiles;
|
||||
shared_ptr <Pkcs5Kdf> VolumeHeaderKdf;
|
||||
shared_ptr <EncryptionAlgorithm> EA;
|
||||
bool Quick;
|
||||
|
||||
struct FilesystemType
|
||||
{
|
||||
enum Enum
|
||||
{
|
||||
Unknown = 0,
|
||||
None,
|
||||
FAT,
|
||||
NTFS,
|
||||
Ext2,
|
||||
Ext3,
|
||||
Ext4,
|
||||
MacOsExt,
|
||||
UFS
|
||||
};
|
||||
|
||||
static Enum GetPlatformNative ()
|
||||
{
|
||||
#ifdef TC_WINDOWS
|
||||
return VolumeCreationOptions::FilesystemType::NTFS;
|
||||
#elif defined (TC_LINUX)
|
||||
return VolumeCreationOptions::FilesystemType::Ext3;
|
||||
#elif defined (TC_MACOSX)
|
||||
return VolumeCreationOptions::FilesystemType::MacOsExt;
|
||||
#elif defined (TC_FREEBSD) || defined (TC_SOLARIS)
|
||||
return VolumeCreationOptions::FilesystemType::UFS;
|
||||
#else
|
||||
return VolumeCreationOptions::FilesystemType::FAT;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
FilesystemType::Enum Filesystem;
|
||||
uint32 FilesystemClusterSize;
|
||||
uint32 SectorSize;
|
||||
};
|
||||
|
||||
class VolumeCreator
|
||||
{
|
||||
public:
|
||||
|
||||
struct ProgressInfo
|
||||
{
|
||||
bool CreationInProgress;
|
||||
uint64 TotalSize;
|
||||
uint64 SizeDone;
|
||||
};
|
||||
|
||||
struct KeyInfo
|
||||
{
|
||||
ConstBufferPtr HeaderKey;
|
||||
ConstBufferPtr MasterKey;
|
||||
};
|
||||
|
||||
VolumeCreator ();
|
||||
virtual ~VolumeCreator ();
|
||||
|
||||
void Abort ();
|
||||
void CheckResult ();
|
||||
void CreateVolume (shared_ptr <VolumeCreationOptions> options);
|
||||
KeyInfo GetKeyInfo () const;
|
||||
ProgressInfo GetProgressInfo ();
|
||||
|
||||
protected:
|
||||
void CreationThread ();
|
||||
|
||||
volatile bool AbortRequested;
|
||||
volatile bool CreationInProgress;
|
||||
uint64 DataStart;
|
||||
uint64 HostSize;
|
||||
shared_ptr <VolumeCreationOptions> Options;
|
||||
shared_ptr <Exception> ThreadException;
|
||||
uint64 VolumeSize;
|
||||
|
||||
shared_ptr <VolumeLayout> Layout;
|
||||
shared_ptr <File> VolumeFile;
|
||||
SharedVal <uint64> SizeDone;
|
||||
uint64 WriteOffset;
|
||||
ProgressInfo mProgressInfo;
|
||||
|
||||
SecureBuffer HeaderKey;
|
||||
shared_ptr <VolumePassword> PasswordKey;
|
||||
SecureBuffer MasterKey;
|
||||
|
||||
private:
|
||||
VolumeCreator (const VolumeCreator &);
|
||||
VolumeCreator &operator= (const VolumeCreator &);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TC_HEADER_Volume_VolumeCreator
|
||||
Reference in New Issue
Block a user