📄 cli.c
字号:
if (fgets (s, sizeof (s), stdin) && sscanf (s, "%d", &c) == 1)
{
if (c < min || c > max)
continue;
puts ("");
return c;
}
puts ("");
return defaultChoice;
}
}
static char *AskString (char *prompt, char *buf, int maxSize)
{
printf ("%s: ", prompt);
if (fgets (buf, maxSize, stdin))
{
char *lf = strchr (buf, '\n');
if (lf)
lf[0] = 0;
return buf;
}
return NULL;
}
static void AskPassword (char *prompt, char *volumePath, Password *password)
{
struct termios noEcho;
if (tcgetattr (0, &TerminalAttributes) == 0)
{
noEcho = TerminalAttributes;
if (!DisplayPassword)
{
noEcho.c_lflag &= ~ECHO;
if (tcsetattr (0, TCSANOW, &noEcho) != 0)
error ("Failed to turn terminal echo off\n");
}
printf (prompt, volumePath);
}
if (fgets ((char *)password->Text, sizeof (password->Text), stdin))
{
char *newl = strchr ((char *)password->Text, '\n');
if (newl) newl[0] = 0;
password->Length = strlen ((char *)password->Text);
}
else
password->Length = 0;
if (IsTerminal && !DisplayPassword)
{
tcsetattr (0, TCSANOW, &TerminalAttributes);
puts ("");
}
}
static char *AskVolumePath (char *volumePath, char *prompt)
{
static char path[MAX_PATH];
// Volume path
while (!volumePath || !volumePath[0])
{
volumePath = AskString (prompt, path, sizeof (path));
}
return volumePath;
}
static BOOL OpenVolume (char *volumePath, char *prompt, char *promptArg, BOOL secondaryPassword, 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;
int tries = PasswordEntryTries;
char msg[128];
BOOL ret = FALSE;
if (stat (volumePath, &volumeStat) != 0)
{
perror ("Cannot read volume's modification and access time");
volumeStat.st_ctime = 0;
goto err;
}
f = fopen (volumePath, "rb");
if (!f)
{
perror ("Cannot open volume");
goto err;
}
do
{
Password *pw = &password;
if (!secondaryPassword && !CmdPasswordValid || (secondaryPassword && !CmdPassword2Valid))
AskPassword (prompt, promptArg, &password);
else
pw = secondaryPassword ? &CmdPassword2 : &CmdPassword;
if ((!secondaryPassword
&& FirstKeyFile
&& !KeyFilesApply (pw, FirstKeyFile, !UpdateTime))
|| (secondaryPassword
&& FirstProtVolKeyFile
&& !KeyFilesApply (pw, FirstProtVolKeyFile, !UpdateTime)))
{
error ("Error while processing keyfiles\n");
goto err;
}
// Normal header
fseek (f, 0, SEEK_SET);
if (fread (header, 1, SECTOR_SIZE, f) != SECTOR_SIZE)
{
perror ("Cannot read volume header");
goto err;
}
if (fseek (f, 0, SEEK_END) == -1)
{
perror ("Cannot determine volume size");
goto err;
}
r = VolumeReadHeader (header, pw, cryptoInfo);
if (r == 0)
{
*totalSectors = ftello (f) / SECTOR_SIZE - 1;
*startSector = 1;
ret = TRUE;
break;
}
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, pw, cryptoInfo);
if (r == 0)
{
*startSector = (ftello (f)
+ SECTOR_SIZE * 2
- (*cryptoInfo)->hiddenVolumeSize
- HIDDEN_VOL_HEADER_OFFSET) / SECTOR_SIZE;
*totalSectors = (*cryptoInfo)->hiddenVolumeSize / SECTOR_SIZE;
ret = TRUE;
break;
}
if (r == ERR_PASSWORD_WRONG)
{
if (IsTerminal)
{
puts ("Incorrect password or not a TrueCrypt volume.");
continue;
}
else
{
error ("Incorrect password or not a TrueCrypt volume.\n");
goto err;
}
}
}
// Report errors
switch (r)
{
case ERR_NEW_VERSION_REQUIRED:
strcpy (msg, "A newer version of TrueCrypt is required to open this volume.");
break;
default:
sprintf (msg, "Volume cannot be opened: Error %d", r);
break;
}
if (IsTerminal)
printf ("%s\n", msg);
else
error ("%s\n", msg);
goto err;
} while (IsTerminal
&& --tries > 0
&& ((!secondaryPassword && !CmdPasswordValid)
|| (secondaryPassword && !CmdPassword2Valid)));
fclose (f);
if (!UpdateTime)
RestoreFileTime (volumePath, volumeStat.st_mtime, volumeStat.st_atime);
*modTime = volumeStat.st_mtime;
*acTime = volumeStat.st_atime;
return ret;
err:
*cryptoInfo = NULL;
if (f)
fclose (f);
if (volumeStat.st_ctime != 0 && !UpdateTime)
RestoreFileTime (volumePath, volumeStat.st_mtime, volumeStat.st_atime);
*totalSectors = 0;
return FALSE;
}
static char *EscapeSpaces (char *string)
{
static char escapedString[MAX_PATH * 2];
char *e = escapedString;
char c;
if (strlen (string) > MAX_PATH)
return NULL;
while ((c = *string++))
{
if (c == ' ')
*e++ = '\\';
*e++ = c;
}
return escapedString;
}
static BOOL MountVolume (char *volumePath, char *mountPoint)
{
char hostDevice[MAX_PATH];
char mapDevice[MAX_PATH];
int loopDevNo = -1;
PCRYPTO_INFO ci = NULL;
uint64_t startSector, totalSectors;
uint64_t readOnlyStartSector = 0, readOnlySectors = 0;
int pfd[2];
int pid, res, devNo;
time_t modTime, acTime;
FILE *f, *w;
int flags;
int i;
int tries = PasswordEntryTries;
#if DEBUG
if (!AutoTestAlgorithms ())
{
error ("Self-tests of algorithms FAILED!\n");
return FALSE;
}
#endif
if (IsVolumeMounted (volumePath))
{
error ("Volume already mapped\n");
return FALSE;
}
if (!OpenVolume (volumePath, "Enter password for '%s': ", volumePath, FALSE,
&ci, &startSector, &totalSectors, &modTime, &acTime))
goto err;
if (totalSectors == 0)
{
error ("Illegal volume size (0 bytes).\n");
goto err;
}
// Hidden volume protection
if (ProtectHidden)
{
PCRYPTO_INFO ciH = NULL;
uint64_t startSectorH, totalSectorsH;
if (OpenVolume (volumePath, "Enter hidden volume password: ", "", TRUE,
&ciH, &startSectorH, &totalSectorsH, &modTime, &acTime))
{
readOnlyStartSector = startSectorH;
readOnlySectors = startSectorH + totalSectorsH;
}
if (ciH)
crypto_close (ciH);
if (readOnlySectors == 0)
goto err;
}
// Headers decrypted
// Loopback
if (IsFile (volumePath))
{
int i;
for (i = 0; i < MAX_MINOR; i++)
{
snprintf (hostDevice, sizeof (hostDevice), LOOP_DEV "%d", i);
if (!IsBlockDevice (hostDevice))
{
snprintf (hostDevice, sizeof (hostDevice), LOOP_DEV "/%d", i);
if (!IsBlockDevice (hostDevice))
continue;
}
if (Execute (TRUE, "losetup", hostDevice, volumePath, NULL))
break;
}
if (i >= MAX_MINOR)
{
error ("No free loopback device available for file-hosted volume\n");
goto err;
}
loopDevNo = i;
if (Verbose > 1)
printf ("Attached %s to %s\n", volumePath, hostDevice);
}
else
strncpy (hostDevice, volumePath, sizeof (hostDevice));
// Load kernel module
if (!LoadKernelModule ())
goto err;
if (!CheckKernelModuleVersion (TRUE))
goto err;
// dmsetup
devNo = UseDeviceNumber == -1 ? GetFreeMapDevice () : UseDeviceNumber;
if (devNo == -1)
{
error ("Maximum number of volumes mounted\n");
goto err;
}
sprintf (mapDevice, "truecrypt%d", devNo);
pipe (pfd);
pid = fork ();
if (pid == -1)
{
perror ("fork");
goto err;
}
else if (pid == 0)
{
SecurityCleanup ();
close (pfd[1]);
dup2 (pfd[0], STDIN_FILENO);
execlp ("dmsetup", "dmsetup", "create", mapDevice, NULL);
perror ("execlp dmsetup");
_exit (1);
}
close (pfd[0]);
w = fdopen (pfd[1], "a");
if (w == NULL)
{
perror ("fdopen");
goto err;
}
fprintf (w, "0 %lld truecrypt %d %d ", totalSectors, ci->ea, ci->mode);
for (i = DISK_IV_SIZE; i < EAGetKeySize (ci->ea) + DISK_IV_SIZE; i++)
fprintf (w, "%02x", ci->master_key[i]);
fprintf (w, " ");
for (i = 0; i < (int)sizeof (ci->iv); i++)
fprintf (w, "%02x", ci->iv[i]);
flags = 0;
if (ReadOnly)
flags |= FLAG_READ_ONLY;
else if (ProtectHidden)
flags |= FLAG_HIDDEN_VOLUME_PROTECTION;
fprintf (w, " %s %lld %lld %lld %lld %lld %d %s\n",
hostDevice,
startSector,
readOnlyStartSector,
readOnlySectors,
(uint64_t) modTime,
(uint64_t) acTime,
flags,
EscapeSpaces (volumePath));
fclose (w);
if (!WaitChild (FALSE, "dmsetup"))
{
Execute (TRUE, "dmsetup", "remove", mapDevice, NULL);
goto err;
}
sprintf (mapDevice, TC_MAP_DEV "%d", devNo);
if (Verbose >= 1)
printf ("Mapped %s as %s\n", volumePath, mapDevice);
// Mount
if (mountPoint)
{
char fstype[64], opts[128];
strcpy (fstype, "-t");
if (Filesystem)
strncat (fstype, Filesystem, sizeof (fstype) - 3);
else
strcat (fstype, "auto");
strcpy (opts, ReadOnly ? "-oro" : "-orw");
if (MountOpts)
{
strcat (opts, ",");
strncat (opts, MountOpts, sizeof (opts) - 6);
}
if (UserMount)
{
// Set default uid and gid
char s[64];
sprintf (s, ",uid=%d,gid=%d", RealUserId, RealGroupId);
strcat (opts, s);
}
if (!Execute (FALSE, "mount", fstype, opts, mapDevice, mountPoint, NULL))
{
error ("Mount failed\n");
loopDevNo = -1;
goto err;
}
if (Verbose >= 1)
printf ("Mounted %s at %s\n", mapDevice, mountPoint);
}
crypto_close (ci);
return TRUE;
err:
if (ci)
crypto_close (ci);
if (loopDevNo != -1)
DeleteLoopDevice (loopDevNo);
UnloadKernelModule (TRUE);
return FALSE;
}
int RandGetBytesAvailable ()
{
int n = -1;
FILE *f = fopen ("/proc/sys/kernel/random/entropy_avail", "r");
if (f == NULL)
return -1;
if (fscanf (f, "%d", &n) == 1)
n /= 8;
fclose (f);
return n;
}
void RandBytesFillRequired (int randReq)
{
int n;
if (RandGetBytesAvailable () < randReq)
{
printf ("There is not enough entropy available in the kernel random pool. Please move\n"
"the mouse randomly and/or press random keys. Both the mouse and keyboard must\n"
"be physically connected to the computer where TrueCrypt is running. Disk\n"
"activity (read/write) can also be used to fill the kernel random pool.\n\n");
while ((n = RandGetBytesAvailable()) < randReq)
{
if (n < 0)
{
printf ("WARNING: Number of random bytes available could not be determined.\n"
"If the volume creation does not start, try moving the mouse or pressing keys\n"
"to increase the random pool entropy.\n");
break;
}
printf ("\rRandom bytes available: %d%%", n * 100 / (randReq));
fflush (stdout);
usleep (200 * 1000);
}
if (n > 0)
printf ("\rRandom bytes available: 100%%\n\n");
}
}
BOOL RandpeekBytes (unsigned char *buf , int len)
{
int f = open ("/dev/urandom", 0);
if (f == -1)
{
perror ("Cannot open /dev/urandom");
return FALSE;
}
if (read (f, buf, len) != len)
{
perror ("Read from /dev/urandom failed");
return FALSE;
}
close (f);
return TRUE;
}
BOOL RandgetBytes (unsigned char *buf , int len, BOOL forceSlowPoll)
{
char m[128];
int f = open ("/dev/random", 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -