1
0
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:
Mounir IDRASSI
2014-05-31 18:44:53 +02:00
parent 97011f179c
commit 7ffce028d0
203 changed files with 52120 additions and 0 deletions

20
src/Core/Core.h Normal file
View 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
View 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
View 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
View 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

View 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
View 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
View 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
View 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 &sector) = 0;
};
static void Format (WriteSectorCallback &writeSector, uint64 deviceSize, uint32 clusterSize, uint32 sectorSize);
};
}
#endif // TC_HEADER_Core_FatFormatter

47
src/Core/HostDevice.cpp Normal file
View 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
View 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
View 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
View 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

View 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;
}

View 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

View 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;
}

View 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

View 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

View 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);
}

View 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

View 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);
}

View 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
View 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
View 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

View 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
}

View 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

View 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

View 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);
}

View 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

View 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

View 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);
}

View 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

View 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

View 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

View 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);
}

View 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

View 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
View 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
View 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 &sector)
{
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
View 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