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

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