📄 cli.c
字号:
/*
Copyright (c) 2004-2006 TrueCrypt Foundation. All rights reserved.
Covered by TrueCrypt License 2.0 the full text of which is contained in the file
License.txt included in TrueCrypt binary and source code distribution archives.
*/
#define _LARGEFILE_SOURCE 1
#define _FILE_OFFSET_BITS 64
#include <getopt.h>
#include <inttypes.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <termios.h>
#include <time.h>
#include <unistd.h>
#include <utime.h>
#include "Tcdefs.h"
#include "Keyfiles.h"
#include "Fat.h"
#include "Format.h"
#include "Progress.h"
#include "Random.h"
#include "Volumes.h"
#include "Tests.h"
#include "Dm-target.h"
#define MAX_VOLUMES 256
#define MAX_MINOR 256
#undef MAX_PATH
#define MAX_PATH 260
#define MAX_PATH_STR "259"
#define TC_MAP_DEV "/dev/mapper/truecrypt"
#define LOOP_DEV "/dev/loop"
#define error(fmt, args...) fprintf (stderr, "truecrypt: " fmt, ## args)
typedef struct
{
int DeviceNumber;
int DeviceMajor;
int DeviceMinor;
uint64_t VolumeSize;
char VolumePath[MAX_PATH];
int EA;
int Mode;
BOOL Hidden;
uint64_t ReadOnlyStart;
uint64_t ReadOnlyEnd;
uint64_t ModTime;
uint64_t AcTime;
int Flags;
} MountListEntry;
static MountListEntry MountList[MAX_VOLUMES];
static BOOL MountListValid = FALSE;
static BOOL DisplayKeys = FALSE;
static BOOL DisplayPassword = FALSE;
static BOOL DisplayProgress = TRUE;
static BOOL UserMount = FALSE;
static char *Filesystem = NULL;
static char *MountOpts = NULL;
static int PasswordEntryTries = 3;
static Password CmdPassword;
static Password CmdPassword2;
static BOOL CmdPasswordValid = FALSE;
static BOOL CmdPassword2Valid = FALSE;
static int UseDeviceNumber = -1;
static BOOL ProtectHidden = FALSE;
static BOOL ReadOnly = FALSE;
static BOOL UpdateTime = FALSE;
static int Verbose = 0;
static BOOL IsTerminal = FALSE;
static struct termios TerminalAttributes;
static Password password;
static KeyFile *FirstKeyFile;
static KeyFile *FirstProtVolKeyFile;
static KeyFile *FirstNewKeyFile;
static uid_t RealUserId;
static gid_t RealGroupId;
static unsigned __int64 VolumeSize;
static unsigned int ClusterSize = 0;
static int EA;
static int EAMode;
static int HashAlgorithm;
static char *Filesystem;
static int VolumeType = -1;
static BOOL Quick;
static void SecurityCleanup ()
{
burn (&password, sizeof (password));
burn (&CmdPassword, sizeof (CmdPassword));
burn (&CmdPassword2, sizeof (CmdPassword2));
}
static void OnSignal (int signal)
{
SecurityCleanup ();
if (IsTerminal)
{
tcsetattr (0, TCSANOW, &TerminalAttributes);
puts ("");
}
_exit (1);
}
static void OnExit ()
{
SecurityCleanup ();
}
BOOL CheckAdminPrivileges ()
{
char *env;
if (getuid () != 0 && geteuid () != 0)
{
error ("Administrator (root) privileges required\n");
return FALSE;
}
if (getuid () != 0)
{
// Impersonate root to support executing of commands like mount
setuid (0);
// Allow execution of system binaries only
setenv ("PATH", "/usr/sbin:/sbin:/usr/bin:/bin", 1);
}
return TRUE;
}
void DropEffectiveUserId ()
{
setuid (getuid ());
}
BOOL LockMemory ()
{
// Lock process memory
if (mlockall (MCL_FUTURE) != 0)
{
perror ("Cannot prevent memory swapping: mlockall");
return FALSE;
}
return TRUE;
}
static BOOL WaitChild (BOOL quiet, char *execName)
{
int status;
if (wait (&status) == -1)
{
perror ("wait");
return FALSE;
}
if (!WIFEXITED (status)
|| (WIFEXITED (status) && WEXITSTATUS (status)))
{
if (!quiet && Verbose >= 3)
error ("Error: %s returned %d\n", execName, WEXITSTATUS (status));
return FALSE;
}
return TRUE;
}
BOOL Execute (BOOL quiet, char *execName, ...)
{
int pid;
va_list vl;
va_start (vl, execName);
pid = fork ();
if (pid == -1)
{
perror ("fork");
goto err;
}
else if (pid == 0)
{
char *args[32];
int i = 1;
SecurityCleanup ();
if (Verbose >= 3)
printf ("Executing %s", execName);
args[0] = execName;
while (i < 32 && (args[i] = (va_arg (vl, char *))))
{
if (Verbose >= 3)
printf (" %s", args[i]);
i++;
}
if (Verbose >= 3)
puts ("");
if (quiet)
{
// >/dev/null is safer than >&-
int i = open ("/dev/null", 0);
if (i == -1)
{
perror ("open /dev/null");
_exit (1);
}
dup2 (i, STDOUT_FILENO);
dup2 (i, STDERR_FILENO);
}
execvp (execName, args);
fprintf (stderr, "%s ", execName);
perror ("execlp");
_exit (1);
}
if (!WaitChild (quiet, execName))
goto err;
va_end (vl);
return TRUE;
err:
va_end (vl);
return FALSE;
}
static BOOL IsFile (char *path)
{
struct stat st;
if (stat (path, &st) != 0)
return FALSE;
return S_ISREG (st.st_mode);
}
static BOOL IsBlockDevice (char *path)
{
struct stat st;
if (stat (path, &st) != 0)
return FALSE;
return S_ISBLK (st.st_mode);
}
static BOOL RestoreFileTime (char *path, time_t modTime, time_t acTime)
{
struct utimbuf t;
t.actime = acTime;
t.modtime = modTime;
return utime (path, &t) != 0;
}
static BOOL LoadKernelModule ()
{
char s[2048];
FILE *m;
m = fopen ("/proc/modules", "r");
if (m == NULL)
{
perror ("fopen /proc/modules");
return FALSE;
}
while (fgets (s, sizeof (s), m))
{
if (strstr (s, "truecrypt ") == s)
{
fclose (m);
return TRUE;
}
}
fclose (m);
if (!Execute (FALSE, "modprobe", "truecrypt", NULL))
{
error ("Failed to load TrueCrypt kernel module\n");
return FALSE;
}
return TRUE;
}
static BOOL UnloadKernelModule (BOOL quiet)
{
// rmmod is used instead of modprobe to prevent unload of dependencies
return Execute (quiet, "rmmod", "truecrypt", NULL);
}
static BOOL CheckKernelModuleVersion (BOOL wait)
{
FILE *p;
int pfd[2];
int pid, res;
int i, dummy;
char s[2048];
int ver1 = 0, ver2 = 0, ver3 = 0;
int tries = 10;
do
{
pipe (pfd);
pid = fork ();
if (pid == -1)
{
perror ("fork");
return FALSE;
}
else if (pid == 0)
{
SecurityCleanup ();
dup2 (pfd[1], STDOUT_FILENO);
close (pfd[0]);
close (STDERR_FILENO);
execlp ("dmsetup", "dmsetup", "targets", NULL);
perror ("execlp dmsetup");
_exit (1);
}
close (pfd[1]);
p = fdopen (pfd[0], "r");
if (p == NULL)
{
perror ("fdopen");
return FALSE;
}
while (fgets (s, sizeof (s), p))
{
char name[32];
if (sscanf (s, "%31s v%d.%d.%d", &name, &ver1, &ver2, &ver3) == 4
&& strcmp (name, "truecrypt") == 0)
{
fclose (p);
WaitChild (FALSE, "dmsetup");
if (ver1 == VERSION_NUM1 && ver2 == VERSION_NUM2 && ver3 == VERSION_NUM3)
return TRUE;
error ("Incorrect version of kernel module loaded - version %s required\n", VERSION_STRING);
UnloadKernelModule (TRUE);
return FALSE;
}
}
fclose (p);
WaitChild (FALSE, "dmsetup");
// Target registration may take some time
if (wait)
usleep (100 * 1000);
else
break;
} while (tries--);
error ("Kernel module not loaded\n");
return FALSE;
}
static BOOL GetMountList ()
{
FILE *p;
int pfd[2];
int pid, res;
int i, dummy;
if (MountListValid)
return TRUE;
MountList[0].DeviceNumber = -1;
pipe (pfd);
pid = fork ();
if (pid == -1)
{
perror ("fork");
goto err;
}
else if (pid == 0)
{
SecurityCleanup ();
dup2 (pfd[1], STDOUT_FILENO);
close (pfd[0]);
close (STDERR_FILENO);
execlp ("dmsetup", "dmsetup", "table", NULL);
perror ("execlp dmsetup");
_exit (1);
}
close (pfd[1]);
p = fdopen (pfd[0], "r");
if (p == NULL)
{
perror ("fdopen");
goto err;
}
for (i = 0; i < MAX_VOLUMES; i++)
{
int n = 0;
char s[2048];
MountListEntry *e = &MountList[i];
if (!fgets (s, sizeof (s), p))
break;
if (sscanf (s, "truecrypt%d: 0 %lld truecrypt %d %d 0 0 %d:%d %lld %lld %lld %lld %lld %d %n",
&e->DeviceNumber,
&e->VolumeSize,
&e->EA,
&e->Mode,
&e->DeviceMajor,
&e->DeviceMinor,
&e->Hidden,
&e->ReadOnlyStart,
&e->ReadOnlyEnd,
&e->ModTime,
&e->AcTime,
&e->Flags,
&n) >= 12 && n > 0)
{
int l;
strncpy (e->VolumePath, s + n, sizeof (e->VolumePath));
l = strlen (s + n);
if (l > 0)
e->VolumePath[l - 1] = 0;
e->Hidden = e->Hidden == 1 ? FALSE : TRUE;
e->VolumeSize *= SECTOR_SIZE;
}
else
i--;
}
MountList[i].DeviceNumber = -1;
fclose (p);
if (!WaitChild (TRUE, "dmsetup"))
goto err;
MountListValid = TRUE;
return TRUE;
err:
MountList[0].DeviceNumber = -1;
return FALSE;
}
static BOOL IsVolumeMounted (char *volumePath)
{
int i;
if (!GetMountList ())
return FALSE;
for (i = 0; MountList[i].DeviceNumber != -1; i++)
if (strcmp (volumePath, MountList[i].VolumePath) == 0)
return TRUE;
return FALSE;
}
static int GetFreeMapDevice ()
{
FILE *p;
char cmd[128];
int n;
if (!GetMountList ())
return -1;
for (n = 0; n < MAX_MINOR; n++)
{
int j = 0;
while (MountList[j].DeviceNumber != -1)
{
if (MountList[j].DeviceNumber == n)
break;
j++;
}
if (MountList[j].DeviceNumber == -1)
return n;
}
return -1;
}
static BOOL DeleteLoopDevice (int loopDeviceNo)
{
char dev[32];
BOOL r;
sprintf (dev, LOOP_DEV "%d", loopDeviceNo);
if (!IsBlockDevice (dev))
sprintf (dev, LOOP_DEV "/%d", loopDeviceNo);
r = Execute (FALSE, "losetup", "-d", dev, NULL);
if (r && Verbose > 1)
printf ("Detached %s\n", dev);
return r;
}
static int AskSelection (int defaultChoice, int min, int max)
{
int c;
char s[3];
while (1)
{
printf ("Select [%d]: ", defaultChoice);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -