1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long *//*
Derived from source code of TrueCrypt 7.1a, which is
Copyright (c) 2008-2012 TrueCrypt Developers Association and which is governed
by the TrueCrypt License 3.0.
Modifications and additions to the original source code (contained in this file)
and all other portions of this file are Copyright (c) 2013-2017 IDRIX
and are governed by the Apache License 2.0 the full text of which is
contained in the file License.txt included in VeraCrypt binary and source
code distribution packages.
*/
#ifndef TC_HEADER_Main_UserPreferences
#define TC_HEADER_Main_UserPreferences
#include "System.h"
#include "Main.h"
#include "Hotkey.h"
namespace VeraCrypt
{
struct UserPreferences
{
UserPreferences ()
:
BackgroundTaskEnabled (true),
BackgroundTaskMenuDismountItemsEnabled (true),
BackgroundTaskMenuMountItemsEnabled (true),
BackgroundTaskMenuOpenItemsEnabled (true),
BeepAfterHotkeyMountDismount (false),
CloseBackgroundTaskOnNoVolumes (true),
CloseExplorerWindowsOnDismount (true),
CloseSecurityTokenSessionsAfterMount (false),
DisableKernelEncryptionModeWarning (false),
DismountOnInactivity (false),
DismountOnLogOff (true),
DismountOnPowerSaving (false),
DismountOnScreenSaver (false),
DisplayMessageAfterHotkeyDismount (false),
ForceAutoDismount (true),
LastSelectedSlotNumber (0),
MaxVolumeIdleTime (60),
MountDevicesOnLogon (false),
MountFavoritesOnLogon (false),
NonInteractive (false),
UseStandardInput (false),
OpenExplorerWindowAfterMount (false),
SaveHistory (false),
StartOnLogon (false),
UseKeyfiles (false),
Verbose (false),
WipeCacheOnAutoDismount (true),
WipeCacheOnClose (false)
{
}
virtual ~UserPreferences ()
{
}
void Load();
void Save() const;
HotkeyList Hotkeys;
KeyfileList DefaultKeyfiles;
MountOptions DefaultMountOptions;
bool BackgroundTaskEnabled;
bool BackgroundTaskMenuDismountItemsEnabled;
bool BackgroundTaskMenuMountItemsEnabled;
bool BackgroundTaskMenuOpenItemsEnabled;
bool BeepAfterHotkeyMountDismount;
bool CloseBackgroundTaskOnNoVolumes;
bool CloseExplorerWindowsOnDismount;
bool CloseSecurityTokenSessionsAfterMount;
bool DisableKernelEncryptionModeWarning;
bool DismountOnInactivity;
bool DismountOnLogOff;
bool DismountOnPowerSaving;
bool DismountOnScreenSaver;
bool DisplayMessageAfterHotkeyDismount;
bool ForceAutoDismount;
uint64 LastSelectedSlotNumber;
int32 MaxVolumeIdleTime;
bool MountDevicesOnLogon;
bool MountFavoritesOnLogon;
bool NonInteractive;
bool UseStandardInput;
bool OpenExplorerWindowAfterMount;
bool SaveHistory;
FilePath SecurityTokenModule;
bool StartOnLogon;
bool UseKeyfiles;
bool Verbose;
bool WipeCacheOnAutoDismount;
bool WipeCacheOnClose;
protected:
wxString GetDefaultKeyfilesFileName () const { return L"Default Keyfiles.xml"; }
#ifdef TC_PROTOTYPE
wxString GetPreferencesFileName () const { return L"Configuration_Debug.xml"; }
#else
wxString GetPreferencesFileName () const { return L"Configuration.xml"; }
#endif
void SetValue (const wxString &cfgText, bool &cfgVar);
void SetValue (const wxString &cfgText, int &cfgVar);
void SetValue (const wxString &cfgText, uint64 &cfgVar);
void SetValue (const wxString &cfgText, wstring &cfgVar);
void SetValue (const wxString &cfgText, wxString &cfgVar);
void SetValue (const wxString &cfgText, FilesystemPath &cfgVar);
};
}
#endif //*
Derived from source code of TrueCrypt 7.1a, which is
Copyright (c) 2008-2012 TrueCrypt Developers Association and which is governed
by the TrueCrypt License 3.0.
Modifications and additions to the original source code (contained in this file)
and all other portions of this file are Copyright (c) 2013-2016 IDRIX
and are governed by the Apache License 2.0 the full text of which is
contained in the file License.txt included in VeraCrypt binary and source
code distribution packages.
*/
#define FUSE_USE_VERSION 25
#include <errno.h>
#include <fcntl.h>
#include <fuse.h>
#include <iostream>
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <sys/wait.h>
#include "FuseService.h"
#include "Platform/FileStream.h"
#include "Platform/MemoryStream.h"
#include "Platform/Serializable.h"
#include "Platform/SystemLog.h"
#include "Platform/Unix/Pipe.h"
#include "Platform/Unix/Poller.h"
#include "Volume/EncryptionThreadPool.h"
#include "Core/Core.h"
namespace VeraCrypt
{
static int fuse_service_access (const char *path, int mask)
{
try
{
if (!FuseService::CheckAccessRights())
return -EACCES;
}
catch (...)
{
return FuseService::ExceptionToErrorCode();
}
return 0;
}
static void *fuse_service_init ()
{
try
{
// Termination signals are handled by a separate process to allow clean dismount on shutdown
struct sigaction action;
Memory::Zero (&action, sizeof (action));
action.sa_handler = SIG_IGN;
sigaction (SIGINT, &action, nullptr);
sigaction (SIGQUIT, &action, nullptr);
sigaction (SIGTERM, &action, nullptr);
if (!EncryptionThreadPool::IsRunning())
EncryptionThreadPool::Start();
}
catch (exception &e)
{
SystemLog::WriteException (e);
}
catch (...)
{
SystemLog::WriteException (UnknownException (SRC_POS));
}
return nullptr;
}
static void fuse_service_destroy (void *userdata)
{
try
{
FuseService::Dismount();
}
catch (exception &e)
{
SystemLog::WriteException (e);
}
catch (...)
{
SystemLog::WriteException (UnknownException (SRC_POS));
}
}
static int fuse_service_getattr (const char *path, struct stat *statData)
{
try
{
Memory::Zero (statData, sizeof(*statData));
statData->st_uid = FuseService::GetUserId();
statData->st_gid = FuseService::GetGroupId();
statData->st_atime = time (NULL);
statData->st_ctime = time (NULL);
statData->st_mtime = time (NULL);
if (strcmp (path, "/") == 0)
{
statData->st_mode = S_IFDIR | 0500;
statData->st_nlink = 2;
}
else
{
if (!FuseService::CheckAccessRights())
return -EACCES;
if (strcmp (path, FuseService::GetVolumeImagePath()) == 0)
{
statData->st_mode = S_IFREG | 0600;
statData->st_nlink = 1;
statData->st_size = FuseService::GetVolumeSize();
}
else if (strcmp (path, FuseService::GetControlPath()) == 0)
{
statData->st_mode = S_IFREG | 0600;
statData->st_nlink = 1;
statData->st_size = FuseService::GetVolumeInfo()->Size();
}
else
{
return -ENOENT;
}
}
}
catch (...)
{
return FuseService::ExceptionToErrorCode();
}
return 0;
}
static int fuse_service_opendir (const char *path, struct fuse_file_info *fi)
{
try
{
if (!FuseService::CheckAccessRights())
return -EACCES;
if (strcmp (path, "/") != 0)
return -ENOENT;
}
catch (...)
{
return FuseService::ExceptionToErrorCode();
}
return 0;
}
static int fuse_service_open (const char *path, struct fuse_file_info *fi)
{
try
{
if (!FuseService::CheckAccessRights())
return -EACCES;
if (strcmp (path, FuseService::GetVolumeImagePath()) == 0)
return 0;
if (strcmp (path, FuseService::GetControlPath()) == 0)
{
fi->direct_io = 1;
return 0;
}
}
catch (...)
{
return FuseService::ExceptionToErrorCode();
}
return -ENOENT;
}
static int fuse_service_read (const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi)
{
try
{
if (!FuseService::CheckAccessRights())
return -EACCES;
if (strcmp (path, FuseService::GetVolumeImagePath()) == 0)
{
try
{
// Test for read beyond the end of the volume
if ((uint64) offset + size > FuseService::GetVolumeSize())
size = FuseService::GetVolumeSize() - offset;
size_t sectorSize = FuseService::GetVolumeSectorSize();
if (size % sectorSize != 0 || offset % sectorSize != 0)
{
// Support for non-sector-aligned read operations is required by some loop device tools
// which may analyze the volume image before attaching it as a device
uint64 alignedOffset = offset - (offset % sectorSize);
uint64 alignedSize = size + (offset % sectorSize);
if (alignedSize % sectorSize != 0)
alignedSize += sectorSize - (alignedSize % sectorSize);
SecureBuffer alignedBuffer (alignedSize);
FuseService::ReadVolumeSectors (alignedBuffer, alignedOffset);
BufferPtr ((byte *) buf, size).CopyFrom (alignedBuffer.GetRange (offset % sectorSize, size));
}
else
{
FuseService::ReadVolumeSectors (BufferPtr ((byte *) buf, size), offset);
}
}
catch (MissingVolumeData)
{
return 0;
}
return size;
}
if (strcmp (path, FuseService::GetControlPath()) == 0)
{
shared_ptr <Buffer> infoBuf = FuseService::GetVolumeInfo();
BufferPtr outBuf ((byte *)buf, size);
if (offset >= (off_t) infoBuf->Size())
return 0;
if (offset + size > infoBuf->Size())
size = infoBuf->Size () - offset;
outBuf.CopyFrom (infoBuf->GetRange (offset, size));
return size;
}
}
catch (...)
{
return FuseService::ExceptionToErrorCode();
}
return -ENOENT;
}
static int fuse_service_readdir (const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi)
{
try
{
if (!FuseService::CheckAccessRights())
return -EACCES;
if (strcmp (path, "/") != 0)
return -ENOENT;
filler (buf, ".", NULL, 0);
filler (buf, "..", NULL, 0);
filler (buf, FuseService::GetVolumeImagePath() + 1, NULL, 0);
filler (buf, FuseService::GetControlPath() + 1, NULL, 0);
}
catch (...)
{
return FuseService::ExceptionToErrorCode();
}
return 0;
}
static int fuse_service_write (const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi)
{
try
{
if (!FuseService::CheckAccessRights())
return -EACCES;
if (strcmp (path, FuseService::GetVolumeImagePath()) == 0)
{
FuseService::WriteVolumeSectors (BufferPtr ((byte *) buf, size), offset);
return size;
}
if (strcmp (path, FuseService::GetControlPath()) == 0)
{
if (FuseService::AuxDeviceInfoReceived())
return -EACCES;
FuseService::ReceiveAuxDeviceInfo (ConstBufferPtr ((const byte *)buf, size));
return size;
}
}
#ifdef TC_FREEBSD
// FreeBSD apparently retries failed write operations forever, which may lead to a system crash.
catch (VolumeReadOnly&)
{
return size;
}
catch (VolumeProtected&)
{
return size;
}
#endif
catch (...)
{
return FuseService::ExceptionToErrorCode();
}
return -ENOENT;
}
bool FuseService::CheckAccessRights ()
{
return fuse_get_context()->uid == 0 || fuse_get_context()->uid == UserId;
}
void FuseService::CloseMountedVolume ()
{
if (MountedVolume)
{
// This process will exit before the use count of MountedVolume reaches zero
if (MountedVolume->GetFile().use_count() > 1)
MountedVolume->GetFile()->Close();
if (MountedVolume.use_count() > 1)
delete MountedVolume.get();
MountedVolume.reset();
}
}
void FuseService::Dismount ()
{
CloseMountedVolume();
if (EncryptionThreadPool::IsRunning())
EncryptionThreadPool::Stop();
}
int FuseService::ExceptionToErrorCode ()
{
try
{
throw;
}
catch (std::bad_alloc)
{
return -ENOMEM;
}
catch (ParameterIncorrect &e)
{
SystemLog::WriteException (e);
return -EINVAL;
}
catch (VolumeProtected&)
{
return -EPERM;
}
catch (VolumeReadOnly&)
{
return -EPERM;
}
catch (SystemException &e)
{
SystemLog::WriteException (e);
return -static_cast <int> (e.GetErrorCode());
}
catch (std::exception &e)
{
SystemLog::WriteException (e);
return -EINTR;
}
catch (...)
{
SystemLog::WriteException (UnknownException (SRC_POS));
return -EINTR;
}
}
shared_ptr <Buffer> FuseService::GetVolumeInfo ()
{
shared_ptr <Stream> stream (new MemoryStream);
{
ScopeLock lock (OpenVolumeInfoMutex);
OpenVolumeInfo.Set (*MountedVolume);
OpenVolumeInfo.SlotNumber = SlotNumber;
OpenVolumeInfo.Serialize (stream);
}
ConstBufferPtr infoBuf = dynamic_cast <MemoryStream&> (*stream);
shared_ptr <Buffer> outBuf (new Buffer (infoBuf.Size()));
outBuf->CopyFrom (infoBuf);
return outBuf;
}
const char *FuseService::GetVolumeImagePath ()
{
#ifdef TC_MACOSX
return "/volume.dmg";
#else
return "/volume";
#endif
}
uint64 FuseService::GetVolumeSize ()
{
if (!MountedVolume)
throw NotInitialized (SRC_POS);
return MountedVolume->GetSize();
}
void FuseService::Mount (shared_ptr <Volume> openVolume, VolumeSlotNumber slotNumber, const string &fuseMountPoint)
{
list <string> args;
args.push_back (FuseService::GetDeviceType());
args.push_back (fuseMountPoint);
#ifdef TC_MACOSX
args.push_back ("-o");
args.push_back ("noping_diskarb");
args.push_back ("-o");
args.push_back ("nobrowse");
if (getuid() == 0 || geteuid() == 0)
#endif
{
args.push_back ("-o");
args.push_back ("allow_other");
}
ExecFunctor execFunctor (openVolume, slotNumber);
Process::Execute ("fuse", args, -1, &execFunctor);
for (int t = 0; true; t++)
{
try
{
if (FilesystemPath (fuseMountPoint + FuseService::GetControlPath()).GetType() == FilesystemPathType::File)
break;
}
catch (...)
{
if (t > 50)
throw;
Thread::Sleep (100);
}
}
}
void FuseService::ReadVolumeSectors (const BufferPtr &buffer, uint64 byteOffset)
{
if (!MountedVolume)
throw NotInitialized (SRC_POS);
MountedVolume->ReadSectors (buffer, byteOffset);
}
void FuseService::ReceiveAuxDeviceInfo (const ConstBufferPtr &buffer)
{
shared_ptr <Stream> stream (new MemoryStream (buffer));
Serializer sr (stream);
ScopeLock lock (OpenVolumeInfoMutex);
OpenVolumeInfo.VirtualDevice = sr.DeserializeString ("VirtualDevice");
OpenVolumeInfo.LoopDevice = sr.DeserializeString ("LoopDevice");
}
void FuseService::SendAuxDeviceInfo (const DirectoryPath &fuseMountPoint, const DevicePath &virtualDevice, const DevicePath &loopDevice)
{
File fuseServiceControl;
fuseServiceControl.Open (string (fuseMountPoint) + GetControlPath(), File::OpenWrite);
shared_ptr <Stream> stream (new MemoryStream);
Serializer sr (stream);
sr.Serialize ("VirtualDevice", string (virtualDevice));
sr.Serialize ("LoopDevice", string (loopDevice));
fuseServiceControl.Write (dynamic_cast <MemoryStream&> (*stream));
}
void FuseService::WriteVolumeSectors (const ConstBufferPtr &buffer, uint64 byteOffset)
{
if (!MountedVolume)
throw NotInitialized (SRC_POS);
MountedVolume->WriteSectors (buffer, byteOffset);
}
void FuseService::OnSignal (int signal)
{
try
{
shared_ptr <VolumeInfo> volume = Core->GetMountedVolume (SlotNumber);
if (volume)
Core->DismountVolume (volume, true);
}
catch (...) { }
_exit (0);
}
void FuseService::ExecFunctor::operator() (int argc, char *argv[])
{
struct timeval tv;
gettimeofday (&tv, NULL);
FuseService::OpenVolumeInfo.SerialInstanceNumber = (uint64)tv.tv_sec * 1000000ULL + tv.tv_usec;
FuseService::MountedVolume = MountedVolume;
FuseService::SlotNumber = SlotNumber;
FuseService::UserId = getuid();
FuseService::GroupId = getgid();
if (getenv ("SUDO_UID"))
{
try
{
string s (getenv ("SUDO_UID"));
FuseService::UserId = static_cast <uid_t> (StringConverter::ToUInt64 (s));
if (getenv ("SUDO_GID"))
{
s = getenv ("SUDO_GID");
FuseService::GroupId = static_cast <gid_t> (StringConverter::ToUInt64 (s));
}
}
catch (...) { }
}
static fuse_operations fuse_service_oper;
fuse_service_oper.access = fuse_service_access;
fuse_service_oper.destroy = fuse_service_destroy;
fuse_service_oper.getattr = fuse_service_getattr;
fuse_service_oper.init = fuse_service_init;
fuse_service_oper.open = fuse_service_open;
fuse_service_oper.opendir = fuse_service_opendir;
fuse_service_oper.read = fuse_service_read;
fuse_service_oper.readdir = fuse_service_readdir;
fuse_service_oper.write = fuse_service_write;
// Create a new session
setsid ();
// Fork handler of termination signals
SignalHandlerPipe.reset (new Pipe);
int forkedPid = fork();
throw_sys_if (forkedPid == -1);
if (forkedPid == 0)
{
CloseMountedVolume();
struct sigaction action;
Memory::Zero (&action, sizeof (action));
action.sa_handler = OnSignal;
sigaction (SIGINT, &action, nullptr);
sigaction (SIGQUIT, &action, nullptr);
sigaction (SIGTERM, &action, nullptr);
// Wait for the exit of the main service
byte buf[1];
if (read (SignalHandlerPipe->GetReadFD(), buf, sizeof (buf))) { } // Errors ignored
_exit (0);
}
SignalHandlerPipe->GetWriteFD();
_exit (fuse_main (argc, argv, &fuse_service_oper));
}
VolumeInfo FuseService::OpenVolumeInfo;
Mutex FuseService::OpenVolumeInfoMutex;
shared_ptr <Volume> FuseService::MountedVolume;
VolumeSlotNumber FuseService::SlotNumber;
uid_t FuseService::UserId;
gid_t FuseService::GroupId;
auto_ptr <Pipe> FuseService::SignalHandlerPipe;
}
|