📄 cli.c
字号:
{
int i;
if (!GetMountList (FALSE))
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 (FALSE))
return -1;
for (n = 0; n < TC_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[64];
BOOL r;
int i;
snprintf (dev, sizeof (dev), TC_LOOP_DEV "%d", loopDeviceNo);
if (!IsBlockDevice (dev))
snprintf (dev, sizeof (dev), TC_LOOP_DEV "/%d", loopDeviceNo);
for (i = 0; i < 10; i++)
{
r = Execute (TRUE, "losetup", "-d", dev, NULL);
if (r)
break;
usleep (200 * 1000);
}
if (r && Verbose > 1)
printf ("Detached %s\n", dev);
if (!r)
error ("Failed to detach %s\n", dev);
return r;
}
static int AskSelection (int defaultChoice, int min, int max)
{
int c;
char s[10];
while (1)
{
printf ("Select [%d]: ", defaultChoice);
if (fgets (s, sizeof (s), stdin) && sscanf (s, "%d", &c) == 1)
{
if (c < min || c > max)
continue;
puts ("");
return c;
}
if (s[0] != 0 && s[0] != '\n')
continue;
puts ("");
return defaultChoice;
}
}
static BOOL AskYesNo (char *prompt, BOOL defaultNo)
{
char s[4];
do
{
printf ("%s [%c/%c]: ", prompt, defaultNo ? 'y' : 'Y', defaultNo ? 'N' : 'n');
fgets (s, sizeof(s), stdin);
if (s[0] == 'y' || s[0] == 'Y')
return TRUE;
if (s[0] == 'n' || s[0] == 'N')
return FALSE;
} while (s[0] != '\n');
return !defaultNo;
}
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 BOOL ValidatePassword (Password *password, BOOL requireAscii)
{
int i;
if (password->Length > MAX_PASSWORD)
{
error ("Maximum password length is %d characters\n", MAX_PASSWORD);
return FALSE;
}
for (i = 0; i < password->Length; i++)
{
if (password->Text[i] >= 0x7f || password->Text[i] < 0x20)
{
error ("Password must be composed only of US-ASCII printable characters to maintain portability.\n");
if (requireAscii)
return FALSE;
else
break;
}
}
return TRUE;
}
static void AskPassword (char *prompt, char *volumePath, Password *password, BOOL requireAscii)
{
struct termios noEcho;
char pw[2048];
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");
}
}
while (TRUE)
{
char *newl;
if (IsTerminal)
printf (prompt, volumePath);
if (!fgets (pw, sizeof (pw), stdin))
{
password->Length = 0;
break;
}
newl = strchr (pw, '\n');
if (newl) newl[0] = 0;
snprintf ((char *)password->Text, sizeof (password->Text), "%s", pw);
password->Length = strlen ((char *)password->Text);
if (ValidatePassword (password, requireAscii))
break;
}
burn(pw, sizeof (pw));
if (IsTerminal && !DisplayPassword)
{
tcsetattr (0, TCSANOW, &TerminalAttributes);
puts ("");
}
}
static char *AskVolumePath (char *volumePath, char *prompt)
{
static char path[TC_MAX_PATH];
// Volume path
while (!volumePath || !volumePath[0])
{
volumePath = AskString (prompt, path, sizeof (path));
}
return volumePath;
}
static BOOL AskKeyFiles (char *prompt, KeyFile **firstKeyFile)
{
char path[TC_MAX_PATH];
char lprompt[128];
snprintf (lprompt, sizeof(lprompt), "%s [none]", prompt);
while (AskString (lprompt, path, sizeof (path)) && path[0] != 0)
{
KeyFile *kf = malloc (sizeof (KeyFile));
if (!kf)
{
perror ("malloc");
return FALSE;
}
snprintf (kf->FileName, sizeof (kf->FileName), "%s", path);
*firstKeyFile = KeyFileAdd (*firstKeyFile, kf);
snprintf (lprompt, sizeof(lprompt), "%s [finish]", prompt);
}
return TRUE;
}
static BOOL OpenVolume (char *volumePath, char *prompt, char *promptArg, BOOL secondaryPassword, PCRYPTO_INFO *cryptoInfo, unsigned long long *startSector, unsigned long long *totalSectors, time_t *modTime, time_t *acTime)
{
char header[SECTOR_SIZE];
FILE *f = NULL;
struct stat volumeStat;
int tries = PasswordEntryTries;
char msg[128];
BOOL ret = FALSE;
int r;
memset (&volumeStat, 0, sizeof (volumeStat));
if ((!UpdateTime || ReadOnly)
&& IsFile (volumePath) && 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;
}
do
{
Password *pw = &password;
if (!secondaryPassword && !CmdPasswordValid || (secondaryPassword && !CmdPassword2Valid))
AskPassword (prompt, promptArg, &password, FALSE);
else
pw = secondaryPassword ? &CmdPassword2 : &CmdPassword;
if ((!secondaryPassword
&& FirstKeyFile
&& !KeyFilesApply (pw, FirstKeyFile))
|| (secondaryPassword
&& FirstProtVolKeyFile
&& !KeyFilesApply (pw, FirstProtVolKeyFile)))
{
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 hidden volume header");
if (IsFile (volumePath))
error ("Please check the filesystem supports files larger than 2GB.\n");
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)
{
char s[128];
snprintf (s, sizeof (s), "Incorrect password %sor not a TrueCrypt volume."
, (FirstKeyFile || FirstProtVolKeyFile) ? "and/or keyfile(s) " : "");
if (IsTerminal)
{
puts (s);
continue;
}
else
{
error ("%s\n", s);
goto err;
}
}
}
// Report errors
switch (r)
{
case ERR_NEW_VERSION_REQUIRED:
snprintf (msg, sizeof (msg), "A newer version of TrueCrypt is required to open this volume.");
break;
default:
snprintf (msg, sizeof (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[TC_MAX_PATH * 2];
char *e = escapedString;
char c;
if (strlen (string) > TC_MAX_PATH)
return NULL;
while ((c = *string++))
{
if (c == ' ')
*e++ = '\\';
*e++ = c;
}
return escapedString;
}
static BOOL IsMountPointAvailable (char *mountPoint)
{
char md[TC_MAX_PATH], mp[TC_MAX_PATH];
while (EnumMountPoints (md, mp))
{
if (strcmp (mountPoint, mp) == 0)
{
EnumMountPoints (NULL, NULL);
return FALSE;
}
}
return TRUE;
}
static BOOL MountVolume (char *volumePath, char *mountPoint)
{
char hostDevice[TC_MAX_PATH];
char mapDevice[TC_MAX_PATH];
int loopDevNo = -1;
PCRYPTO_INFO ci = NULL;
unsigned long long startSector, totalSectors;
unsigned long long 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 (UseDeviceNumber != -1)
{
for (i = 0; MountList[i].DeviceNumber != -1; i++)
{
if (MountList[i].DeviceNumber == UseDeviceNumber)
{
error (TC_MAP_DEV "%d already in use\n", UseDeviceNumber);
return FALSE;
}
}
}
if (mountPoint && !IsMountPointAvailable (mountPoint))
{
error ("Mount directory %s is already in use\n", mountPoint);
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;
unsigned long long 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 < TC_MAX_MINOR; i++)
{
snprintf (hostDevice, sizeof (hostDevice), TC_LOOP_DEV "%d", i);
if (!IsBlockDevice (hostDevice))
{
snprintf (hostDevice, sizeof (hostDevice), TC_LOOP_DEV "/%d", i);
if (!IsBlockDevice (hostDevice))
continue;
}
if (Execute (TRUE, "losetup", hostDevice, volumePath, NULL))
break;
}
if (i >= TC_MAX_MINOR)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -