📄 cli.c
字号:
/* Copyright (c) 2004-2005 TrueCrypt Foundation. All rights reserved. Covered by TrueCrypt License 2.0 the full text of which is contained in the fileLicense.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 <sys/mman.h>#include <sys/stat.h>#include <sys/types.h>#include <sys/wait.h>#include <termios.h>#include <time.h>#include <unistd.h>#include <utime.h>#include "Tcdefs.h"#include "Keyfiles.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 DisplayPassword = 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 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 ();}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 BOOL OpenVolume (char *volumePath, Password *password, PCRYPTO_INFO *cryptoInfo, uint64_t *startSector, uint64_t *totalSectors, time_t *modTime, time_t *acTime){ char header[SECTOR_SIZE]; uint64_t r; FILE *f = NULL; struct stat volumeStat; if (stat (volumePath, &volumeStat) != 0) { perror ("Cannot open volume"); volumeStat.st_ctime = 0; goto err; } f = fopen (volumePath, "rb"); if (!f) { perror ("Cannot open volume"); goto err; } // Normal header if (fread (header, 1, SECTOR_SIZE, f) != SECTOR_SIZE) { perror ("Cannot read volume header"); goto err; } fseek (f, 0, SEEK_END); *totalSectors = ftello (f) / SECTOR_SIZE - 1; *startSector = 1; r = VolumeReadHeader (header, password, cryptoInfo); if (r == ERR_PASSWORD_WRONG) { // Hidden header if (fseek (f, -HIDDEN_VOL_HEADER_OFFSET, SEEK_END) == -1 || fread (header, 1, SECTOR_SIZE, f) != SECTOR_SIZE) { perror ("Cannot read volume header"); goto err; } r = VolumeReadHeader (header, password, cryptoInfo); if (r == ERR_PASSWORD_WRONG) { if (IsTerminal) puts ("Incorrect password or not a TrueCrypt volume"); else error ("Incorrect password or not a TrueCrypt volume\n"); goto err;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -