📄 cli.c
字号:
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) { error ("Failed to assign loopback device for file-hosted volume\n"); goto err; } loopDevNo = i; if (Verbose > 1) printf ("Attached %s to %s\n", volumePath, hostDevice); } else snprintf (hostDevice, sizeof (hostDevice), "%s", volumePath); // Load kernel module if (!LoadKernelModule ()) goto err; if (!CheckKernelModuleVersion (TRUE, FALSE)) goto err; // dmsetup devNo = UseDeviceNumber == -1 ? GetFreeMapDevice () : UseDeviceNumber; if (devNo == -1) { error ("Maximum number of volumes mounted\n"); goto err; } snprintf (mapDevice, sizeof (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) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -