|
|
1.1.1.5 ! root 1: /* ! 2: Copyright (c) TrueCrypt Foundation. All rights reserved. 1.1 root 3: 1.1.1.5 ! root 4: Covered by the TrueCrypt License 2.2 the full text of which is contained ! 5: in the file License.txt included in TrueCrypt binary and source code ! 6: distribution packages. 1.1 root 7: */ 8: 9: #define _LARGEFILE_SOURCE 1 10: #define _FILE_OFFSET_BITS 64 11: 1.1.1.4 root 12: #include <errno.h> 1.1 root 13: #include <getopt.h> 14: #include <inttypes.h> 15: #include <stdarg.h> 16: #include <stdio.h> 17: #include <stdlib.h> 1.1.1.5 ! root 18: #include <string.h> 1.1 root 19: #include <sys/mman.h> 20: #include <sys/stat.h> 1.1.1.3 root 21: #include <sys/time.h> 1.1 root 22: #include <sys/types.h> 1.1.1.4 root 23: #include <sys/utsname.h> 1.1 root 24: #include <sys/wait.h> 1.1.1.3 root 25: #include <fcntl.h> 1.1 root 26: #include <termios.h> 27: #include <time.h> 28: #include <unistd.h> 29: #include <utime.h> 30: 31: #include "Tcdefs.h" 1.1.1.4 root 32: #include "Crc.h" 33: #include "Dm-target.h" 1.1 root 34: #include "Keyfiles.h" 1.1.1.3 root 35: #include "Fat.h" 36: #include "Format.h" 1.1.1.5 ! root 37: #include "Password.h" 1.1.1.3 root 38: #include "Progress.h" 39: #include "Random.h" 1.1 root 40: #include "Volumes.h" 41: #include "Tests.h" 42: 1.1.1.4 root 43: #include "Cli.h" 1.1 root 44: 1.1.1.4 root 45: static MountListEntry MountList[TC_MAX_VOLUMES]; 1.1 root 46: static BOOL MountListValid = FALSE; 47: 1.1.1.4 root 48: static FILE *MiceDevice = NULL; 49: static int MiceDeviceErrNo; 50: 1.1.1.3 root 51: static BOOL DisplayKeys = FALSE; 1.1 root 52: static BOOL DisplayPassword = FALSE; 1.1.1.3 root 53: static BOOL DisplayProgress = TRUE; 54: static BOOL UserMount = FALSE; 1.1 root 55: static char *Filesystem = NULL; 56: static char *MountOpts = NULL; 57: static int PasswordEntryTries = 3; 58: static Password CmdPassword; 59: static Password CmdPassword2; 60: static BOOL CmdPasswordValid = FALSE; 61: static BOOL CmdPassword2Valid = FALSE; 62: static int UseDeviceNumber = -1; 63: static BOOL ProtectHidden = FALSE; 64: static BOOL ReadOnly = FALSE; 65: static BOOL UpdateTime = FALSE; 1.1.1.4 root 66: static BOOL Interactive = FALSE; 67: static BOOL Overwrite = FALSE; 1.1 root 68: static int Verbose = 0; 69: 70: static BOOL IsTerminal = FALSE; 71: static struct termios TerminalAttributes; 72: static Password password; 73: static KeyFile *FirstKeyFile; 74: static KeyFile *FirstProtVolKeyFile; 1.1.1.3 root 75: static KeyFile *FirstNewKeyFile; 1.1.1.4 root 76: static BOOL NoKeyFiles = FALSE; 77: static BOOL NoNewKeyFiles = FALSE; 1.1.1.3 root 78: 1.1.1.4 root 79: static unsigned long long VolumeSize; 1.1.1.3 root 80: static unsigned int ClusterSize = 0; 81: static int EA; 82: static int EAMode; 83: static int HashAlgorithm; 84: static char *Filesystem; 85: static int VolumeType = -1; 86: static BOOL Quick; 1.1.1.4 root 87: static char *RandomSource = NULL; 88: 89: static uid_t RealUserId; 90: static gid_t RealGroupId; 91: static int LastExitStatus; 92: 1.1 root 93: 94: static void SecurityCleanup () 95: { 96: burn (&password, sizeof (password)); 97: burn (&CmdPassword, sizeof (CmdPassword)); 98: burn (&CmdPassword2, sizeof (CmdPassword2)); 99: } 100: 101: 102: static void OnSignal (int signal) 103: { 104: SecurityCleanup (); 105: 106: if (IsTerminal) 107: { 108: tcsetattr (0, TCSANOW, &TerminalAttributes); 109: puts (""); 110: } 111: 112: _exit (1); 113: } 114: 115: 116: static void OnExit () 117: { 118: SecurityCleanup (); 119: } 120: 121: 1.1.1.4 root 122: static BOOL CheckAdminPrivileges () 1.1.1.3 root 123: { 124: char *env; 125: 126: if (getuid () != 0 && geteuid () != 0) 127: { 128: error ("Administrator (root) privileges required\n"); 129: return FALSE; 130: } 131: 132: if (getuid () != 0) 133: { 1.1.1.5 ! root 134: // Impersonate root to support execution of commands like mount 1.1.1.3 root 135: setuid (0); 136: 137: // Allow execution of system binaries only 138: setenv ("PATH", "/usr/sbin:/sbin:/usr/bin:/bin", 1); 139: } 140: 141: return TRUE; 142: } 143: 144: 1.1.1.4 root 145: static void DropEffectiveUserId () 1.1.1.3 root 146: { 147: setuid (getuid ()); 148: } 149: 150: 1.1.1.4 root 151: static BOOL LockMemory () 1.1.1.3 root 152: { 153: // Lock process memory 154: if (mlockall (MCL_FUTURE) != 0) 155: { 1.1.1.5 ! root 156: perror ("Cannot prevent paging of memory to disk: mlockall"); 1.1.1.3 root 157: return FALSE; 158: } 159: 160: return TRUE; 161: } 162: 163: 1.1 root 164: static BOOL WaitChild (BOOL quiet, char *execName) 165: { 166: int status; 167: if (wait (&status) == -1) 168: { 169: perror ("wait"); 170: return FALSE; 171: } 172: 1.1.1.4 root 173: LastExitStatus = WEXITSTATUS (status); 174: 1.1 root 175: if (!WIFEXITED (status) 176: || (WIFEXITED (status) && WEXITSTATUS (status))) 177: { 178: if (!quiet && Verbose >= 3) 179: error ("Error: %s returned %d\n", execName, WEXITSTATUS (status)); 180: return FALSE; 181: } 182: 183: return TRUE; 184: } 185: 186: 1.1.1.4 root 187: static BOOL Execute (BOOL quiet, char *execName, ...) 1.1 root 188: { 189: int pid; 190: va_list vl; 191: va_start (vl, execName); 192: 1.1.1.4 root 193: LastExitStatus = -1; 194: 1.1 root 195: pid = fork (); 196: if (pid == -1) 197: { 198: perror ("fork"); 199: goto err; 200: } 201: else if (pid == 0) 202: { 203: char *args[32]; 204: int i = 1; 205: 206: SecurityCleanup (); 207: 208: if (Verbose >= 3) 209: printf ("Executing %s", execName); 210: 211: args[0] = execName; 212: while (i < 32 && (args[i] = (va_arg (vl, char *)))) 213: { 214: if (Verbose >= 3) 215: printf (" %s", args[i]); 216: i++; 217: } 218: 219: if (Verbose >= 3) 220: puts (""); 221: 222: if (quiet) 223: { 224: // >/dev/null is safer than >&- 225: int i = open ("/dev/null", 0); 226: if (i == -1) 227: { 228: perror ("open /dev/null"); 229: _exit (1); 230: } 231: 232: dup2 (i, STDOUT_FILENO); 233: dup2 (i, STDERR_FILENO); 234: } 235: 236: execvp (execName, args); 237: 1.1.1.5 ! root 238: fprintf (stderr, "(%s) ", execName); 1.1 root 239: perror ("execlp"); 240: _exit (1); 241: } 242: 243: if (!WaitChild (quiet, execName)) 244: goto err; 245: 246: va_end (vl); 247: return TRUE; 248: err: 249: va_end (vl); 250: return FALSE; 251: } 252: 253: 254: static BOOL IsFile (char *path) 255: { 256: struct stat st; 257: if (stat (path, &st) != 0) 258: return FALSE; 259: 260: return S_ISREG (st.st_mode); 261: } 262: 263: 264: static BOOL IsBlockDevice (char *path) 265: { 266: struct stat st; 267: if (stat (path, &st) != 0) 268: return FALSE; 269: 270: return S_ISBLK (st.st_mode); 271: } 272: 273: 274: static BOOL RestoreFileTime (char *path, time_t modTime, time_t acTime) 275: { 276: struct utimbuf t; 277: 278: t.actime = acTime; 279: t.modtime = modTime; 280: 281: return utime (path, &t) != 0; 282: } 283: 284: 285: static BOOL LoadKernelModule () 286: { 287: char s[2048]; 288: FILE *m; 289: 290: m = fopen ("/proc/modules", "r"); 291: if (m == NULL) 292: { 293: perror ("fopen /proc/modules"); 294: return FALSE; 295: } 296: 297: while (fgets (s, sizeof (s), m)) 298: { 299: if (strstr (s, "truecrypt ") == s) 300: { 301: fclose (m); 302: return TRUE; 303: } 304: } 305: 306: fclose (m); 307: 1.1.1.4 root 308: if (!Execute (TRUE, "modprobe", "truecrypt", NULL)) 1.1 root 309: { 1.1.1.4 root 310: struct utsname u; 311: char module[128]; 312: int r1, r2, r3; 313: char *p; 314: 315: if (!Execute (TRUE, "modprobe", "dm-mod", NULL)) 316: Execute (TRUE, "modprobe", "dm", NULL); 317: 318: if (uname (&u) == 0 && sscanf (u.release, "%d.%d.%d", &r1, &r2, &r3) == 3) 319: { 320: sprintf (module, "%s/truecrypt.ko", TC_SHARE_KERNEL, r1, r2, r3); 321: if (IsFile (module) && Execute (TRUE, "insmod", module, NULL)) 322: return TRUE; 323: 324: sprintf (module, "%s/truecrypt-%d.%d.%d.ko", TC_SHARE_KERNEL, r1, r2, r3); 325: if (IsFile (module) && Execute (FALSE, "insmod", module, NULL)) 326: return TRUE; 327: } 328: 329: Execute (FALSE, "modprobe", "truecrypt", NULL); 1.1 root 330: error ("Failed to load TrueCrypt kernel module\n"); 331: return FALSE; 332: } 333: return TRUE; 334: } 335: 336: 337: static BOOL UnloadKernelModule (BOOL quiet) 338: { 339: // rmmod is used instead of modprobe to prevent unload of dependencies 340: return Execute (quiet, "rmmod", "truecrypt", NULL); 341: } 342: 343: 1.1.1.4 root 344: static BOOL CheckKernelModuleVersion (BOOL wait, BOOL quiet) 1.1 root 345: { 346: FILE *p; 347: int pfd[2]; 348: int pid, res; 349: int i, dummy; 350: char s[2048]; 351: int ver1 = 0, ver2 = 0, ver3 = 0; 352: int tries = 10; 353: 354: do 355: { 356: pipe (pfd); 357: pid = fork (); 358: 359: if (pid == -1) 360: { 361: perror ("fork"); 362: return FALSE; 363: } 364: else if (pid == 0) 365: { 366: SecurityCleanup (); 367: 368: dup2 (pfd[1], STDOUT_FILENO); 369: close (pfd[0]); 370: close (STDERR_FILENO); 371: 372: execlp ("dmsetup", "dmsetup", "targets", NULL); 373: 374: perror ("execlp dmsetup"); 375: _exit (1); 376: } 377: 378: close (pfd[1]); 379: p = fdopen (pfd[0], "r"); 380: if (p == NULL) 381: { 382: perror ("fdopen"); 383: return FALSE; 384: } 385: 386: while (fgets (s, sizeof (s), p)) 387: { 388: char name[32]; 389: 390: if (sscanf (s, "%31s v%d.%d.%d", &name, &ver1, &ver2, &ver3) == 4 391: && strcmp (name, "truecrypt") == 0) 392: { 393: fclose (p); 394: WaitChild (FALSE, "dmsetup"); 395: 1.1.1.4 root 396: if (ver1 == TC_VERSION_NUM1 && ver2 == TC_VERSION_NUM2 && ver3 == TC_VERSION_NUM3) 1.1 root 397: return TRUE; 398: 399: error ("Incorrect version of kernel module loaded - version %s required\n", VERSION_STRING); 400: UnloadKernelModule (TRUE); 401: return FALSE; 402: } 403: } 404: 405: fclose (p); 406: WaitChild (FALSE, "dmsetup"); 407: 408: // Target registration may take some time 409: if (wait) 410: usleep (100 * 1000); 411: else 412: break; 413: 414: } while (tries--); 415: 1.1.1.4 root 416: if (!quiet) 417: error ("Kernel module not loaded\n"); 418: 1.1 root 419: return FALSE; 420: } 421: 422: 1.1.1.4 root 423: static void OpenMiceDevice () 424: { 425: if (!MiceDevice) 426: { 427: FILE *m; 428: char s[2048]; 429: 430: m = fopen ("/proc/bus/input/devices", "r"); 431: if (m != NULL) 432: { 433: BOOL found = FALSE; 434: while (fgets (s, sizeof (s), m)) 435: { 436: if (strstr (s, "mouse") || strstr (s, "Mouse") || strstr (s, "MOUSE")) 437: { 438: found = TRUE; 439: break; 440: } 441: } 442: 443: fclose (m); 444: if (!found) 445: return; 446: } 447: 448: MiceDevice = fopen (TC_MICE_DEVICE, "rb"); 449: MiceDeviceErrNo = errno; 450: } 451: } 452: 453: 454: static BOOL GetMountList (BOOL force) 1.1 root 455: { 456: FILE *p; 457: int pfd[2]; 458: int pid, res; 459: int i, dummy; 460: 1.1.1.4 root 461: if (!force && MountListValid) 1.1 root 462: return TRUE; 463: 464: MountList[0].DeviceNumber = -1; 465: 466: pipe (pfd); 467: pid = fork (); 468: 469: if (pid == -1) 470: { 471: perror ("fork"); 472: goto err; 473: } 474: else if (pid == 0) 475: { 476: SecurityCleanup (); 477: 478: dup2 (pfd[1], STDOUT_FILENO); 479: close (pfd[0]); 480: close (STDERR_FILENO); 481: 482: execlp ("dmsetup", "dmsetup", "table", NULL); 483: 484: perror ("execlp dmsetup"); 485: _exit (1); 486: } 487: 488: close (pfd[1]); 489: p = fdopen (pfd[0], "r"); 490: if (p == NULL) 491: { 492: perror ("fdopen"); 493: goto err; 494: } 495: 1.1.1.4 root 496: for (i = 0; i < TC_MAX_VOLUMES; i++) 1.1 root 497: { 1.1.1.2 root 498: int n = 0; 1.1 root 499: char s[2048]; 500: MountListEntry *e = &MountList[i]; 501: 502: if (!fgets (s, sizeof (s), p)) 503: break; 504: 1.1.1.5 ! root 505: if (sscanf (s, "truecrypt%d: 0 %llu truecrypt %d %d 0 0 %d:%d %llu %llu %llu %llu %llu %llu %d %n", 1.1 root 506: &e->DeviceNumber, 507: &e->VolumeSize, 508: &e->EA, 1.1.1.2 root 509: &e->Mode, 1.1 root 510: &e->DeviceMajor, 511: &e->DeviceMinor, 512: &e->Hidden, 513: &e->ReadOnlyStart, 514: &e->ReadOnlyEnd, 1.1.1.5 ! root 515: &e->UserId, 1.1 root 516: &e->ModTime, 517: &e->AcTime, 518: &e->Flags, 1.1.1.2 root 519: &n) >= 12 && n > 0) 1.1 root 520: { 1.1.1.2 root 521: int l; 522: strncpy (e->VolumePath, s + n, sizeof (e->VolumePath)); 523: l = strlen (s + n); 524: if (l > 0) 525: e->VolumePath[l - 1] = 0; 526: 1.1 root 527: e->Hidden = e->Hidden == 1 ? FALSE : TRUE; 528: e->VolumeSize *= SECTOR_SIZE; 529: } 530: else 531: i--; 532: } 533: 534: MountList[i].DeviceNumber = -1; 535: 536: fclose (p); 537: if (!WaitChild (TRUE, "dmsetup")) 538: goto err; 539: 540: MountListValid = TRUE; 541: return TRUE; 542: 543: err: 544: MountList[0].DeviceNumber = -1; 545: return FALSE; 546: } 547: 548: 549: static BOOL IsVolumeMounted (char *volumePath) 550: { 551: int i; 1.1.1.4 root 552: if (!GetMountList (FALSE)) 1.1 root 553: return FALSE; 554: 555: for (i = 0; MountList[i].DeviceNumber != -1; i++) 556: if (strcmp (volumePath, MountList[i].VolumePath) == 0) 557: return TRUE; 558: 559: return FALSE; 560: } 561: 562: 563: static int GetFreeMapDevice () 564: { 565: FILE *p; 566: char cmd[128]; 567: int n; 568: 1.1.1.4 root 569: if (!GetMountList (FALSE)) 1.1 root 570: return -1; 571: 1.1.1.4 root 572: for (n = 0; n < TC_MAX_MINOR; n++) 1.1 root 573: { 574: int j = 0; 575: while (MountList[j].DeviceNumber != -1) 576: { 577: if (MountList[j].DeviceNumber == n) 578: break; 579: j++; 580: } 581: 582: if (MountList[j].DeviceNumber == -1) 583: return n; 584: } 585: 586: return -1; 587: } 588: 589: 590: static BOOL DeleteLoopDevice (int loopDeviceNo) 591: { 592: char dev[32]; 593: BOOL r; 1.1.1.4 root 594: int i; 1.1 root 595: 1.1.1.4 root 596: sprintf (dev, TC_LOOP_DEV "%d", loopDeviceNo); 1.1 root 597: if (!IsBlockDevice (dev)) 1.1.1.4 root 598: sprintf (dev, TC_LOOP_DEV "/%d", loopDeviceNo); 1.1 root 599: 1.1.1.4 root 600: for (i = 0; i < 10; i++) 601: { 602: r = Execute (TRUE, "losetup", "-d", dev, NULL); 603: if (r) 604: break; 605: 606: usleep (200 * 1000); 607: } 1.1 root 608: 609: if (r && Verbose > 1) 610: printf ("Detached %s\n", dev); 611: 1.1.1.4 root 612: if (!r) 613: error ("Failed to detach %s\n", dev); 614: 1.1 root 615: return r; 616: } 617: 618: 1.1.1.3 root 619: static int AskSelection (int defaultChoice, int min, int max) 620: { 621: int c; 1.1.1.5 ! root 622: char s[10]; 1.1.1.3 root 623: 624: while (1) 625: { 626: printf ("Select [%d]: ", defaultChoice); 627: 628: if (fgets (s, sizeof (s), stdin) && sscanf (s, "%d", &c) == 1) 629: { 630: if (c < min || c > max) 631: continue; 632: 633: puts (""); 634: return c; 635: } 636: 1.1.1.5 ! root 637: if (s[0] != 0 && s[0] != '\n') ! 638: continue; ! 639: 1.1.1.3 root 640: puts (""); 641: return defaultChoice; 642: } 643: } 644: 645: 1.1.1.4 root 646: static BOOL AskYesNo (char *prompt, BOOL defaultNo) 647: { 648: char s[4]; 649: 650: do 651: { 652: printf ("%s [%c/%c]: ", prompt, defaultNo ? 'y' : 'Y', defaultNo ? 'N' : 'n'); 653: fgets (s, sizeof(s), stdin); 654: 655: if (s[0] == 'y' || s[0] == 'Y') 656: return TRUE; 657: 658: if (s[0] == 'n' || s[0] == 'N') 659: return FALSE; 660: 661: } while (s[0] != '\n'); 662: 663: return !defaultNo; 664: } 665: 666: 1.1.1.3 root 667: static char *AskString (char *prompt, char *buf, int maxSize) 668: { 669: printf ("%s: ", prompt); 670: 671: if (fgets (buf, maxSize, stdin)) 672: { 673: char *lf = strchr (buf, '\n'); 674: if (lf) 675: lf[0] = 0; 676: 677: return buf; 678: } 679: 680: return NULL; 681: } 682: 683: 1.1.1.5 ! root 684: static BOOL ValidatePassword (Password *password) ! 685: { ! 686: int i; ! 687: ! 688: if (password->Length > MAX_PASSWORD) ! 689: { ! 690: error ("Maximum password length is %d characters\n", MAX_PASSWORD); ! 691: return FALSE; ! 692: } ! 693: ! 694: for (i = 0; i < password->Length; i++) ! 695: { ! 696: if (password->Text[i] >= 0x7f || password->Text[i] < 0x20) ! 697: { ! 698: error ("Password must be composed only of US-ASCII printable characters\n"); ! 699: return FALSE; ! 700: } ! 701: } ! 702: ! 703: return TRUE; ! 704: } ! 705: ! 706: 1.1.1.3 root 707: static void AskPassword (char *prompt, char *volumePath, Password *password) 708: { 709: struct termios noEcho; 1.1.1.5 ! root 710: char pw[2048]; 1.1.1.3 root 711: 712: if (tcgetattr (0, &TerminalAttributes) == 0) 713: { 714: noEcho = TerminalAttributes; 715: 716: if (!DisplayPassword) 717: { 718: noEcho.c_lflag &= ~ECHO; 719: if (tcsetattr (0, TCSANOW, &noEcho) != 0) 720: error ("Failed to turn terminal echo off\n"); 721: } 722: } 723: 1.1.1.5 ! root 724: while (TRUE) 1.1.1.3 root 725: { 1.1.1.5 ! root 726: char *newl; ! 727: ! 728: if (IsTerminal) ! 729: printf (prompt, volumePath); ! 730: ! 731: if (!fgets (pw, sizeof (pw), stdin)) ! 732: { ! 733: password->Length = 0; ! 734: break; ! 735: } ! 736: ! 737: newl = strchr (pw, '\n'); 1.1.1.3 root 738: if (newl) newl[0] = 0; 739: 1.1.1.5 ! root 740: strncpy ((char *)password->Text, pw, sizeof (password->Text)); 1.1.1.3 root 741: password->Length = strlen ((char *)password->Text); 1.1.1.5 ! root 742: ! 743: if (ValidatePassword (password)) ! 744: break; 1.1.1.3 root 745: } 1.1.1.5 ! root 746: ! 747: burn(pw, sizeof (pw)); 1.1.1.3 root 748: 749: if (IsTerminal && !DisplayPassword) 750: { 751: tcsetattr (0, TCSANOW, &TerminalAttributes); 752: puts (""); 753: } 754: } 755: 756: 757: static char *AskVolumePath (char *volumePath, char *prompt) 758: { 1.1.1.4 root 759: static char path[TC_MAX_PATH]; 1.1.1.3 root 760: 761: // Volume path 762: while (!volumePath || !volumePath[0]) 763: { 764: volumePath = AskString (prompt, path, sizeof (path)); 765: } 766: 767: return volumePath; 768: } 769: 770: 1.1.1.4 root 771: static BOOL AskKeyFiles (char *prompt, KeyFile **firstKeyFile) 772: { 773: char path[TC_MAX_PATH]; 774: char lprompt[128]; 775: 776: snprintf (lprompt, sizeof(lprompt), "%s [none]", prompt); 777: while (AskString (lprompt, path, sizeof (path)) && path[0] != 0) 778: { 779: KeyFile *kf = malloc (sizeof (KeyFile)); 780: if (!kf) 781: { 782: perror ("malloc"); 783: return FALSE; 784: } 785: strncpy (kf->FileName, path, sizeof (kf->FileName)); 786: *firstKeyFile = KeyFileAdd (*firstKeyFile, kf); 787: 788: snprintf (lprompt, sizeof(lprompt), "%s [finish]", prompt); 789: } 790: 791: return TRUE; 792: } 793: 794: 795: 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) 1.1 root 796: { 797: char header[SECTOR_SIZE]; 798: FILE *f = NULL; 799: struct stat volumeStat; 1.1.1.3 root 800: int tries = PasswordEntryTries; 801: char msg[128]; 802: BOOL ret = FALSE; 1.1.1.4 root 803: int r; 1.1 root 804: 1.1.1.4 root 805: memset (&volumeStat, 0, sizeof (volumeStat)); 806: if ((!UpdateTime || ReadOnly) 807: && IsFile (volumePath) && stat (volumePath, &volumeStat) != 0) 1.1 root 808: { 1.1.1.4 root 809: perror ("Cannot open volume"); 1.1 root 810: volumeStat.st_ctime = 0; 811: goto err; 812: } 813: 1.1.1.2 root 814: f = fopen (volumePath, "rb"); 1.1 root 815: if (!f) 816: { 817: perror ("Cannot open volume"); 818: goto err; 819: } 820: 1.1.1.3 root 821: do 1.1 root 822: { 1.1.1.3 root 823: Password *pw = &password; 1.1 root 824: 1.1.1.3 root 825: if (!secondaryPassword && !CmdPasswordValid || (secondaryPassword && !CmdPassword2Valid)) 826: AskPassword (prompt, promptArg, &password); 827: else 828: pw = secondaryPassword ? &CmdPassword2 : &CmdPassword; 1.1 root 829: 1.1.1.3 root 830: if ((!secondaryPassword 831: && FirstKeyFile 832: && !KeyFilesApply (pw, FirstKeyFile, !UpdateTime)) 833: || (secondaryPassword 834: && FirstProtVolKeyFile 835: && !KeyFilesApply (pw, FirstProtVolKeyFile, !UpdateTime))) 836: { 837: error ("Error while processing keyfiles\n"); 838: goto err; 839: } 1.1 root 840: 1.1.1.3 root 841: // Normal header 842: fseek (f, 0, SEEK_SET); 843: if (fread (header, 1, SECTOR_SIZE, f) != SECTOR_SIZE) 1.1 root 844: { 845: perror ("Cannot read volume header"); 846: goto err; 847: } 848: 1.1.1.3 root 849: if (fseek (f, 0, SEEK_END) == -1) 1.1 root 850: { 1.1.1.3 root 851: perror ("Cannot determine volume size"); 1.1 root 852: goto err; 853: } 854: 1.1.1.3 root 855: r = VolumeReadHeader (header, pw, cryptoInfo); 1.1 root 856: 1.1.1.3 root 857: if (r == 0) 858: { 859: *totalSectors = ftello (f) / SECTOR_SIZE - 1; 860: *startSector = 1; 861: ret = TRUE; 862: break; 863: } 1.1.1.2 root 864: 1.1.1.3 root 865: if (r == ERR_PASSWORD_WRONG) 866: { 867: // Hidden header 868: if (fseek (f, -HIDDEN_VOL_HEADER_OFFSET, SEEK_END) == -1 869: || fread (header, 1, SECTOR_SIZE, f) != SECTOR_SIZE) 870: { 1.1.1.4 root 871: perror ("Cannot read hidden volume header"); 872: if (IsFile (volumePath)) 873: error ("Please check the filesystem supports files larger than 2GB.\n"); 1.1.1.3 root 874: goto err; 875: } 876: 877: r = VolumeReadHeader (header, pw, cryptoInfo); 878: 879: if (r == 0) 880: { 881: *startSector = (ftello (f) 882: + SECTOR_SIZE * 2 883: - (*cryptoInfo)->hiddenVolumeSize 884: - HIDDEN_VOL_HEADER_OFFSET) / SECTOR_SIZE; 885: 886: *totalSectors = (*cryptoInfo)->hiddenVolumeSize / SECTOR_SIZE; 887: ret = TRUE; 888: break; 889: } 890: 891: if (r == ERR_PASSWORD_WRONG) 892: { 1.1.1.4 root 893: char s[128]; 894: 895: sprintf (s, "Incorrect password %sor not a TrueCrypt volume." 896: , (FirstKeyFile || FirstProtVolKeyFile) ? "and/or keyfile(s) " : ""); 897: 1.1.1.3 root 898: if (IsTerminal) 899: { 1.1.1.4 root 900: puts (s); 1.1.1.3 root 901: continue; 902: } 903: else 904: { 1.1.1.4 root 905: error ("%s\n", s); 1.1.1.3 root 906: goto err; 907: } 908: } 909: } 1.1.1.2 root 910: 1.1.1.3 root 911: // Report errors 1.1.1.2 root 912: switch (r) 913: { 914: case ERR_NEW_VERSION_REQUIRED: 1.1.1.3 root 915: strcpy (msg, "A newer version of TrueCrypt is required to open this volume."); 1.1.1.2 root 916: break; 917: 918: default: 919: sprintf (msg, "Volume cannot be opened: Error %d", r); 920: break; 921: } 922: 923: if (IsTerminal) 924: printf ("%s\n", msg); 925: else 926: error ("%s\n", msg); 927: 928: goto err; 1.1.1.3 root 929: 930: } while (IsTerminal 931: && --tries > 0 932: && ((!secondaryPassword && !CmdPasswordValid) 933: || (secondaryPassword && !CmdPassword2Valid))); 1.1 root 934: 935: fclose (f); 936: 937: if (!UpdateTime) 938: RestoreFileTime (volumePath, volumeStat.st_mtime, volumeStat.st_atime); 939: 940: *modTime = volumeStat.st_mtime; 941: *acTime = volumeStat.st_atime; 1.1.1.3 root 942: 943: return ret; 1.1 root 944: 945: err: 946: *cryptoInfo = NULL; 947: 948: if (f) 949: fclose (f); 950: 951: if (volumeStat.st_ctime != 0 && !UpdateTime) 952: RestoreFileTime (volumePath, volumeStat.st_mtime, volumeStat.st_atime); 953: 1.1.1.3 root 954: *totalSectors = 0; 1.1 root 955: return FALSE; 956: } 957: 958: 1.1.1.2 root 959: static char *EscapeSpaces (char *string) 960: { 1.1.1.4 root 961: static char escapedString[TC_MAX_PATH * 2]; 1.1.1.2 root 962: char *e = escapedString; 963: char c; 964: 1.1.1.4 root 965: if (strlen (string) > TC_MAX_PATH) 1.1.1.2 root 966: return NULL; 967: 968: while ((c = *string++)) 969: { 970: if (c == ' ') 971: *e++ = '\\'; 972: 973: *e++ = c; 974: } 975: 976: return escapedString; 977: } 978: 979: 1.1.1.5 ! root 980: static BOOL IsMountPointAvailable (char *mountPoint) ! 981: { ! 982: char md[TC_MAX_PATH], mp[TC_MAX_PATH]; ! 983: ! 984: while (EnumMountPoints (md, mp)) ! 985: { ! 986: if (strcmp (mountPoint, mp) == 0) ! 987: { ! 988: EnumMountPoints (NULL, NULL); ! 989: return FALSE; ! 990: } ! 991: } ! 992: return TRUE; ! 993: } ! 994: ! 995: 1.1 root 996: static BOOL MountVolume (char *volumePath, char *mountPoint) 997: { 1.1.1.4 root 998: char hostDevice[TC_MAX_PATH]; 999: char mapDevice[TC_MAX_PATH]; 1.1 root 1000: int loopDevNo = -1; 1001: PCRYPTO_INFO ci = NULL; 1.1.1.4 root 1002: unsigned long long startSector, totalSectors; 1003: unsigned long long readOnlyStartSector = 0, readOnlySectors = 0; 1.1 root 1004: int pfd[2]; 1005: int pid, res, devNo; 1006: time_t modTime, acTime; 1007: FILE *f, *w; 1008: int flags; 1009: int i; 1010: int tries = PasswordEntryTries; 1011: 1.1.1.3 root 1012: #if DEBUG 1.1 root 1013: if (!AutoTestAlgorithms ()) 1014: { 1015: error ("Self-tests of algorithms FAILED!\n"); 1016: return FALSE; 1017: } 1.1.1.3 root 1018: #endif 1.1 root 1019: 1020: if (IsVolumeMounted (volumePath)) 1021: { 1.1.1.3 root 1022: error ("Volume already mapped\n"); 1.1 root 1023: return FALSE; 1024: } 1025: 1.1.1.5 ! root 1026: if (mountPoint && !IsMountPointAvailable (mountPoint)) ! 1027: { ! 1028: error ("Mount directory %s already in use\n", mountPoint); ! 1029: return FALSE; ! 1030: } ! 1031: 1.1.1.3 root 1032: if (!OpenVolume (volumePath, "Enter password for '%s': ", volumePath, FALSE, 1033: &ci, &startSector, &totalSectors, &modTime, &acTime)) 1034: goto err; 1.1 root 1035: 1036: if (totalSectors == 0) 1.1.1.3 root 1037: { 1038: error ("Illegal volume size (0 bytes).\n"); 1.1 root 1039: goto err; 1.1.1.3 root 1040: } 1.1 root 1041: 1042: // Hidden volume protection 1043: if (ProtectHidden) 1044: { 1045: PCRYPTO_INFO ciH = NULL; 1.1.1.4 root 1046: unsigned long long startSectorH, totalSectorsH; 1.1 root 1047: 1.1.1.3 root 1048: if (OpenVolume (volumePath, "Enter hidden volume password: ", "", TRUE, 1049: &ciH, &startSectorH, &totalSectorsH, &modTime, &acTime)) 1.1 root 1050: { 1.1.1.3 root 1051: readOnlyStartSector = startSectorH; 1052: readOnlySectors = startSectorH + totalSectorsH; 1053: } 1.1 root 1054: 1055: if (ciH) 1056: crypto_close (ciH); 1057: 1058: if (readOnlySectors == 0) 1059: goto err; 1060: } 1061: 1062: // Headers decrypted 1063: 1064: // Loopback 1065: if (IsFile (volumePath)) 1066: { 1067: int i; 1068: 1.1.1.4 root 1069: for (i = 0; i < TC_MAX_MINOR; i++) 1.1 root 1070: { 1.1.1.4 root 1071: snprintf (hostDevice, sizeof (hostDevice), TC_LOOP_DEV "%d", i); 1.1 root 1072: 1073: if (!IsBlockDevice (hostDevice)) 1074: { 1.1.1.4 root 1075: snprintf (hostDevice, sizeof (hostDevice), TC_LOOP_DEV "/%d", i); 1.1 root 1076: if (!IsBlockDevice (hostDevice)) 1077: continue; 1078: } 1079: 1080: if (Execute (TRUE, "losetup", hostDevice, volumePath, NULL)) 1081: break; 1082: } 1083: 1.1.1.4 root 1084: if (i >= TC_MAX_MINOR) 1.1 root 1085: { 1.1.1.5 ! root 1086: error ("Failed to assign loopback device for file-hosted volume\n"); 1.1 root 1087: goto err; 1088: } 1089: 1090: loopDevNo = i; 1091: 1092: if (Verbose > 1) 1093: printf ("Attached %s to %s\n", volumePath, hostDevice); 1094: 1095: } 1096: else 1097: strncpy (hostDevice, volumePath, sizeof (hostDevice)); 1098: 1099: // Load kernel module 1100: if (!LoadKernelModule ()) 1101: goto err; 1102: 1.1.1.4 root 1103: if (!CheckKernelModuleVersion (TRUE, FALSE)) 1.1 root 1104: goto err; 1105: 1106: // dmsetup 1107: devNo = UseDeviceNumber == -1 ? GetFreeMapDevice () : UseDeviceNumber; 1108: if (devNo == -1) 1109: { 1110: error ("Maximum number of volumes mounted\n"); 1111: goto err; 1112: } 1113: 1114: sprintf (mapDevice, "truecrypt%d", devNo); 1115: 1116: pipe (pfd); 1117: pid = fork (); 1118: 1119: if (pid == -1) 1120: { 1121: perror ("fork"); 1122: goto err; 1123: } 1124: else if (pid == 0) 1125: { 1126: SecurityCleanup (); 1127: 1128: close (pfd[1]); 1129: dup2 (pfd[0], STDIN_FILENO); 1130: 1131: execlp ("dmsetup", "dmsetup", "create", mapDevice, NULL); 1132: 1133: perror ("execlp dmsetup"); 1134: _exit (1); 1135: } 1136: 1137: close (pfd[0]); 1138: w = fdopen (pfd[1], "a"); 1139: if (w == NULL) 1140: { 1141: perror ("fdopen"); 1142: goto err; 1143: } 1144: 1.1.1.4 root 1145: fprintf (w, "0 %llu truecrypt %d %d ", totalSectors, ci->ea, ci->mode); 1.1 root 1146: 1147: for (i = DISK_IV_SIZE; i < EAGetKeySize (ci->ea) + DISK_IV_SIZE; i++) 1148: fprintf (w, "%02x", ci->master_key[i]); 1149: 1150: fprintf (w, " "); 1151: 1152: for (i = 0; i < (int)sizeof (ci->iv); i++) 1153: fprintf (w, "%02x", ci->iv[i]); 1154: 1155: flags = 0; 1156: 1157: if (ReadOnly) 1.1.1.4 root 1158: flags |= TC_READ_ONLY; 1.1 root 1159: else if (ProtectHidden) 1.1.1.4 root 1160: flags |= TC_HIDDEN_VOLUME_PROTECTION; 1.1 root 1161: 1.1.1.5 ! root 1162: fprintf (w, " %s %llu %llu %llu %llu %llu %llu %d %s\n", 1.1 root 1163: hostDevice, 1164: startSector, 1165: readOnlyStartSector, 1166: readOnlySectors, 1.1.1.5 ! root 1167: (unsigned long long) RealUserId, 1.1.1.4 root 1168: (unsigned long long) modTime, 1169: (unsigned long long) acTime, 1.1 root 1170: flags, 1.1.1.2 root 1171: EscapeSpaces (volumePath)); 1.1 root 1172: 1173: fclose (w); 1174: 1175: if (!WaitChild (FALSE, "dmsetup")) 1176: { 1177: Execute (TRUE, "dmsetup", "remove", mapDevice, NULL); 1178: goto err; 1179: } 1180: 1181: sprintf (mapDevice, TC_MAP_DEV "%d", devNo); 1182: 1183: if (Verbose >= 1) 1184: printf ("Mapped %s as %s\n", volumePath, mapDevice); 1185: 1186: // Mount 1187: if (mountPoint) 1188: { 1.1.1.5 ! root 1189: char fstype[64] = "-t"; ! 1190: char opts[1024]; 1.1 root 1191: 1192: if (Filesystem) 1193: strncat (fstype, Filesystem, sizeof (fstype) - 3); 1194: else 1195: strcat (fstype, "auto"); 1196: 1197: strcpy (opts, ReadOnly ? "-oro" : "-orw"); 1198: if (MountOpts) 1199: { 1200: strcat (opts, ","); 1.1.1.5 ! root 1201: strncat (opts, MountOpts, 256); 1.1 root 1202: } 1203: 1.1.1.5 ! root 1204: if (RealUserId != 0) ! 1205: strcat (opts, ",nosuid"); ! 1206: 1.1.1.3 root 1207: if (UserMount) 1208: { 1209: // Set default uid and gid 1210: char s[64]; 1.1.1.5 ! root 1211: sprintf (s, ",uid=%d,gid=%d,umask=077", RealUserId, RealGroupId); 1.1.1.3 root 1212: strcat (opts, s); 1213: } 1214: 1.1 root 1215: if (!Execute (FALSE, "mount", fstype, opts, mapDevice, mountPoint, NULL)) 1216: { 1.1.1.4 root 1217: int devNo; 1.1 root 1218: error ("Mount failed\n"); 1.1.1.4 root 1219: 1220: if (GetMountList (TRUE) && ToDeviceNumber (mapDevice, &devNo)) 1221: DismountVolume (devNo); 1222: 1.1 root 1223: loopDevNo = -1; 1224: goto err; 1225: } 1226: 1227: if (Verbose >= 1) 1228: printf ("Mounted %s at %s\n", mapDevice, mountPoint); 1229: } 1230: 1231: crypto_close (ci); 1232: 1233: return TRUE; 1234: 1235: err: 1236: if (ci) 1237: crypto_close (ci); 1238: 1239: if (loopDevNo != -1) 1240: DeleteLoopDevice (loopDevNo); 1241: 1242: UnloadKernelModule (TRUE); 1243: 1244: return FALSE; 1245: } 1246: 1247: 1248: 1.1.1.4 root 1249: static void HexDump (unsigned __int8 *data, unsigned int length) 1250: { 1251: while (length--) 1252: printf ("%02x", (unsigned int) *data++); 1.1.1.3 root 1253: } 1254: 1255: 1.1.1.4 root 1256: static uint64_t GetTimeUsec () 1.1.1.3 root 1257: { 1.1.1.4 root 1258: struct timeval tv; 1259: gettimeofday (&tv, NULL); 1.1.1.3 root 1260: 1.1.1.4 root 1261: return (uint64_t)tv.tv_sec * 1000000 + tv.tv_usec; 1262: } 1.1.1.3 root 1263: 1264: 1.1.1.4 root 1265: static double GetTime () 1266: { 1267: struct timeval tv; 1268: gettimeofday (&tv, NULL); 1.1.1.3 root 1269: 1.1.1.4 root 1270: return (double)tv.tv_sec + (double)tv.tv_usec / 1000000; 1.1.1.3 root 1271: } 1272: 1273: 1.1.1.4 root 1274: 1275: static BOOL RandFillPool () 1.1.1.3 root 1276: { 1.1.1.4 root 1277: int i; 1.1.1.3 root 1278: 1.1.1.4 root 1279: if (Randinit () != 0) 1.1.1.3 root 1280: { 1.1.1.4 root 1281: error ("Error while initializing the TrueCrypt random number generator.\n"); 1.1.1.3 root 1282: return FALSE; 1283: } 1284: 1.1.1.4 root 1285: FastPoll (); 1286: 1287: if (IsTerminal && !RandomSource) 1.1.1.3 root 1288: { 1.1.1.4 root 1289: puts ("TrueCrypt will now collect random data."); 1.1.1.3 root 1290: 1.1.1.4 root 1291: if (MiceDevice != NULL) 1292: { 1293: if (AskYesNo ("\nIs your mouse connected directly to computer where TrueCrypt is running?", FALSE)) 1294: { 1295: // Mouse 1296: puts ("\nPlease move the mouse randomly until the required amount of data is captured..."); 1297: for (i = 0; i <= TC_REQUIRED_MOUSE_EVENTS; i++) 1298: { 1299: unsigned char buf[sizeof (uint64_t)]; 1.1.1.3 root 1300: 1.1.1.4 root 1301: printf ("\rMouse data captured: %d%% ", i * 100 / TC_REQUIRED_MOUSE_EVENTS); 1302: fflush (stdout); 1.1.1.3 root 1303: 1.1.1.4 root 1304: if (fread (buf, 1, 1, MiceDevice) != 1) 1305: { 1306: perror ("Cannot read from " TC_MICE_DEVICE); 1307: goto keyboard; 1308: } 1309: RandaddBuf (buf, 1); 1.1.1.3 root 1310: 1.1.1.4 root 1311: *(uint64_t *)buf += GetTimeUsec (); 1.1.1.3 root 1312: 1.1.1.4 root 1313: /* The role of CRC-32 is merely to perform diffusion. Note that the output 1314: of CRC-32 is subsequently processed using a cryptographically secure hash 1315: algorithm. */ 1316: RandAddInt (crc32 (buf, sizeof (buf))); 1317: } 1.1.1.3 root 1318: 1.1.1.4 root 1319: if (i >= TC_REQUIRED_MOUSE_EVENTS) 1320: { 1321: puts ("\n"); 1322: return TRUE; 1323: } 1324: } 1325: } 1326: else if (MiceDeviceErrNo == EACCES) 1327: { 1328: if (IsTerminal) 1329: { 1330: 1331: puts ("\nTo enable mouse movements to be used as a source of random data,\n" 1332: "please do one of the following:\n" 1333: "- Run TrueCrypt under administrator (root) account.\n" 1334: "- Install TrueCrypt as set-euid root.\n" 1335: "- Add read permission to mouse device for all users (chmod o+r " TC_MICE_DEVICE ")."); 1336: } 1337: } 1.1.1.3 root 1338: 1.1.1.4 root 1339: keyboard: 1340: // Keyboard 1341: printf ("\nPlease type at least %d randomly chosen characters and then press Enter:\n", TC_REQUIRED_KEYSTROKES); 1.1.1.3 root 1342: 1.1.1.4 root 1343: i = 0; 1344: while (1) 1345: { 1.1.1.5 ! root 1346: char buf[TC_REQUIRED_KEYSTROKES * 8]; 1.1.1.4 root 1347: int l; 1.1.1.3 root 1348: 1.1.1.4 root 1349: if (!fgets (buf, sizeof (buf), stdin)) 1350: return FALSE; 1.1.1.3 root 1351: 1.1.1.4 root 1352: l = strlen (buf) - 1; 1.1.1.3 root 1353: 1.1.1.4 root 1354: if (l > 0) 1355: { 1356: RandaddBuf (buf, l); 1357: i += l; 1358: } 1.1.1.3 root 1359: 1.1.1.4 root 1360: if (i >= TC_REQUIRED_KEYSTROKES) 1361: break; 1.1.1.3 root 1362: 1.1.1.4 root 1363: printf ("\nCharacters remaining: %d\n", TC_REQUIRED_KEYSTROKES - i); 1364: fflush (stdout); 1365: } 1366: puts (""); 1367: } 1368: else if (RandomSource) 1369: { 1370: // File 1371: char buf[RNG_POOL_SIZE]; 1372: FILE *f = NULL; 1373: int r; 1374: 1375: if (strcmp (RandomSource, "-") != 0) 1376: { 1377: f = fopen (RandomSource, "rb"); 1378: if (!f) 1379: { 1380: perror ("Cannot open source of random data"); 1381: return FALSE; 1382: } 1383: } 1384: 1385: if ((r = fread (buf, 1, sizeof (buf), f ? f : stdin)) < 1) 1386: { 1387: error ("Cannot read from source of random data"); 1388: if (f) 1389: fclose (f); 1390: return FALSE; 1391: } 1392: 1393: if (f) 1394: fclose (f); 1395: RandaddBuf (buf, r); 1396: } 1397: else 1398: { 1399: error ("Source of random data required (use --random-source).\n"); 1400: return FALSE; 1401: } 1402: 1403: return TRUE; 1.1.1.3 root 1404: } 1405: 1406: 1.1.1.4 root 1407: static unsigned __int64 TotalSectors, StartSector; 1.1.1.3 root 1408: static double StartTime; 1409: static double LastUpdateTime; 1410: 1411: void InitProgressBar (__int64 totalSectors) 1412: { 1413: LastUpdateTime = 0; 1414: StartTime = GetTime (); 1.1.1.4 root 1415: TotalSectors = (unsigned __int64) totalSectors; 1.1.1.3 root 1416: } 1417: 1418: 1419: BOOL UpdateProgressBar (__int64 sector) 1420: { 1.1.1.4 root 1421: unsigned __int64 s = (unsigned __int64) sector - StartSector; 1.1.1.3 root 1422: double t = GetTime (); 1423: double elapsed = t - StartTime; 1424: unsigned __int64 bytesDone = (s + 1) * SECTOR_SIZE; 1425: unsigned __int64 bytesPerSec = bytesDone / (1 + elapsed); 1426: int timeRemain = (int)((TotalSectors - s) / ((s + 1)/(elapsed + 1) + 1)); 1427: 1428: if (DisplayProgress && IsTerminal && t - LastUpdateTime > 0.2) 1429: { 1430: printf ("\rDone: %.2f MB Speed: %.2f MB/s Left: %d:%02d:%02d " 1431: , (double)bytesDone / 1024 / 1024 1432: , (double)bytesPerSec / 1024 / 1024 1433: , timeRemain / 3600 1434: , (timeRemain % 3600) / 60 1435: , (timeRemain % 3600) % 60); 1436: 1437: fflush (stdout); 1438: LastUpdateTime = t; 1439: } 1440: } 1441: 1442: 1.1.1.4 root 1443: static BOOL ParseSize (char *string, unsigned long long *size) 1.1.1.3 root 1444: { 1.1.1.4 root 1445: if (sscanf (string, "%llu", size) == 1) 1.1.1.3 root 1446: { 1447: if (strchr (string, 'k') || strchr (string, 'K')) 1448: *size *= 1024; 1449: else if (strchr (string, 'M')) 1450: *size *= 1024 * 1024; 1451: else if (strchr (string, 'G')) 1452: *size *= 1024 * 1024 * 1024; 1453: 1454: *size &= ~0x1FF; 1455: 1456: return TRUE; 1457: } 1458: return FALSE; 1459: } 1460: 1461: 1462: static BOOL CreateVolume (char *hostPath) 1463: { 1.1.1.4 root 1464: PCRYPTO_INFO ci = NULL; 1.1.1.3 root 1465: char header[HEADER_SIZE]; 1.1.1.4 root 1466: char path[TC_MAX_PATH]; 1.1.1.3 root 1467: char str[128]; 1468: FILE *f; 1469: fatparams ft; 1470: Password *pw = &password; 1.1.1.4 root 1471: unsigned long long startSector, totalSectors, hostSize; 1.1.1.3 root 1472: BOOL hiddenVolume; 1.1.1.4 root 1473: BOOL deleteOnError = FALSE; 1474: BOOL ret = FALSE; 1.1.1.3 root 1475: int i, r = 0; 1476: 1.1.1.4 root 1477: OpenMiceDevice (); 1.1.1.3 root 1478: DropEffectiveUserId (); 1479: 1480: // Volume type 1481: switch (VolumeType) 1482: { 1483: case VOLUME_TYPE_NORMAL: 1484: hiddenVolume = FALSE; 1485: break; 1486: 1487: case VOLUME_TYPE_HIDDEN: 1488: hiddenVolume = TRUE; 1489: break; 1490: 1491: default: 1492: puts ("Volume type:\n 1) Normal\n 2) Hidden"); 1493: hiddenVolume = AskSelection (1, 1, 2) == 2; 1494: break; 1495: } 1496: 1.1.1.5 ! root 1497: if (hiddenVolume) ! 1498: Quick = TRUE; ! 1499: 1.1.1.3 root 1500: // Host file or device 1.1.1.4 root 1501: hostPath = AskVolumePath (hostPath, hiddenVolume ? "Enter volume path" : "Enter file or device path for new volume"); 1.1.1.3 root 1502: 1503: if (hiddenVolume) 1504: { 1505: if (!IsFile (hostPath) && !IsBlockDevice (hostPath)) 1506: { 1507: error ("File or device %s does not exist. Hidden volume cannot be created.\n", hostPath); 1508: return FALSE; 1509: } 1510: f = fopen (hostPath, "r+b"); 1511: } 1.1.1.5 ! root 1512: else 1.1.1.3 root 1513: { 1.1.1.5 ! root 1514: if (!Overwrite ! 1515: && IsFile (hostPath) ! 1516: && (!IsTerminal || !AskYesNo ("Volume already exists - overwrite?", TRUE))) ! 1517: { ! 1518: if (!IsTerminal) ! 1519: error ("Volume already exists.\n"); ! 1520: return FALSE; ! 1521: } ! 1522: ! 1523: if (!Overwrite ! 1524: && IsBlockDevice (hostPath) ! 1525: && (!IsTerminal || !AskYesNo ("WARNING: Data on device will be lost. Continue?", TRUE))) ! 1526: { ! 1527: return FALSE; ! 1528: } ! 1529: 1.1.1.3 root 1530: f = fopen (hostPath, "wb"); 1.1.1.4 root 1531: deleteOnError = TRUE; 1.1.1.3 root 1532: } 1533: 1534: if (!f) 1535: { 1536: perror ("Cannot open file or device"); 1537: return FALSE; 1538: } 1539: 1540: EAMode = LRW; 1541: 1542: // Filesystem 1543: if (!Filesystem) 1544: { 1545: puts ("Filesystem:\n 1) FAT\n 2) None"); 1546: Filesystem = AskSelection (1, 1, 2) == 1 ? "FAT" : "None"; 1547: } 1548: 1549: // Host file/device size 1550: if (fseek (f, 0, SEEK_END) == -1 || (hostSize = ftello (f)) == (unsigned __int64)-1) 1551: { 1552: perror ("Cannot determine host file/device size"); 1553: goto err; 1554: } 1555: 1556: // Volume size 1557: if (IsBlockDevice (hostPath) && !hiddenVolume) 1558: { 1559: if (VolumeSize != 0) 1560: { 1561: error ("Volume size cannot be changed for device-hosted volumes.\n"); 1562: goto err; 1563: } 1564: 1565: VolumeSize = hostSize; 1566: } 1567: else if (VolumeSize == 0) 1568: { 1569: while (!AskString ("Enter volume size (bytes - size/sizeK/sizeM/sizeG)", str, sizeof (str)) 1570: || !ParseSize (str, &VolumeSize) 1571: || VolumeSize == 0); 1572: puts (""); 1573: } 1574: 1575: if (hiddenVolume && VolumeSize > hostSize - MIN_VOLUME_SIZE ) 1576: { 1577: error ("Outer volume too small for the size specified.\n"); 1578: goto err; 1579: } 1580: 1581: if (strcasecmp ("FAT", Filesystem) == 0) 1582: { 1583: if (VolumeSize < MIN_VOLUME_SIZE || VolumeSize > MAX_FAT_VOLUME_SIZE) 1584: { 1585: error ("Specified volume size cannot be used with FAT filesystem.\n"); 1586: goto err; 1587: } 1588: } 1589: 1590: // Hash algorithm 1591: if (HashAlgorithm == 0) 1592: { 1593: puts ("Hash algorithm:"); 1594: 1595: for (i = 1; i <= LAST_PRF_ID; i++) 1596: printf ("%2d) %s\n", i, HashGetName (i)); 1597: 1598: HashAlgorithm = AskSelection (1, 1, LAST_PRF_ID); 1599: } 1600: 1601: // Encryption algorithm 1602: if (EA == 0) 1603: { 1604: int max = 0; 1605: puts ("Encryption algorithm:"); 1606: 1607: for (i = EAGetFirst (); i != 0; i = EAGetNext (i)) 1608: { 1609: if (EAGetFirstMode (i) == LRW) 1610: { 1611: printf ("%2d) %s\n", i, EAGetName (str, i)); 1612: max = i; 1613: } 1614: } 1615: 1616: EA = AskSelection (1, EAGetFirst (), max); 1617: } 1618: 1619: // Password 1620: if (!CmdPasswordValid) 1621: { 1622: while (1) 1623: { 1624: AskPassword ("Enter password for new volume '%s': ", hostPath, &password); 1625: if (!DisplayPassword) 1626: { 1627: Password pv; 1628: AskPassword ("Re-enter password%s", ": ", &pv); 1629: if (password.Length != pv.Length || memcmp (password.Text, pv.Text, pv.Length)) 1630: { 1631: puts ("Passwords do not match.\n"); 1632: continue; 1633: } 1634: } 1635: break; 1636: } 1637: puts (""); 1638: } 1639: else 1640: pw = &CmdPassword; 1641: 1.1.1.4 root 1642: if (!NoKeyFiles && !FirstKeyFile) 1643: { 1644: AskKeyFiles ("Enter keyfile path", &FirstKeyFile); 1645: puts (""); 1646: } 1647: 1648: if (!FirstKeyFile && pw->Length == 0) 1649: { 1.1.1.5 ! root 1650: error ("Password cannot be empty when no keyfile is specified\n"); 1.1.1.4 root 1651: goto err; 1652: } 1653: 1.1.1.3 root 1654: if (FirstKeyFile && !KeyFilesApply (pw, FirstKeyFile, !UpdateTime)) 1655: { 1656: error ("Error while processing keyfiles\n"); 1657: goto err; 1658: } 1659: 1.1.1.4 root 1660: if (!RandFillPool ()) 1661: goto err; 1.1.1.3 root 1662: 1663: // Create volume header 1664: r = VolumeWriteHeader (header, 1665: EA, 1666: EAMode, 1667: pw, 1668: HashAlgorithm, 1669: 0, 1670: 0, 1671: &ci, 1672: hiddenVolume ? VolumeSize : 0, 1673: FALSE); 1674: 1675: if (r == ERR_CIPHER_INIT_WEAK_KEY) 1676: { 1677: error ("A weak or a potentially weak key has been generated. Please try again.\n"); 1678: goto err; 1679: } 1680: 1681: if (r != 0) 1682: { 1683: error ("Volume header creation failed.\n"); 1684: goto err; 1685: } 1686: 1687: totalSectors = VolumeSize / SECTOR_SIZE; 1688: ci->hiddenVolumeOffset = hostSize - VolumeSize - HIDDEN_VOL_HEADER_OFFSET; 1689: startSector = !hiddenVolume ? 1 : (ci->hiddenVolumeOffset / SECTOR_SIZE); 1690: 1691: if (DisplayKeys) 1692: { 1693: printf ("Master Key: "); 1694: HexDump (ci->master_key, EAGetKeySize (ci->ea)); 1695: printf ("\nSecondary Key: "); 1696: HexDump (ci->iv, sizeof (ci->iv)); 1697: puts ("\n"); 1698: } 1699: 1700: // Write header 1701: if (hiddenVolume) 1702: { 1703: if (fseek (f, -HIDDEN_VOL_HEADER_OFFSET, SEEK_END) == -1) 1704: { 1705: perror ("Cannot seek to hidden volume header location"); 1706: goto err; 1707: } 1708: } 1709: else 1710: { 1711: if (fseek (f, 0, SEEK_SET) == -1) 1712: { 1713: perror ("Cannot seek to volume header location"); 1714: goto err; 1715: } 1716: } 1717: 1718: if (fwrite (header, 1, HEADER_SIZE, f) != HEADER_SIZE) 1719: { 1720: perror ("Cannot write volume header"); 1721: goto err; 1722: } 1723: 1724: InitProgressBar (totalSectors - 1); 1725: StartSector = startSector; 1726: 1727: if (Quick && !hiddenVolume && IsFile (hostPath)) 1728: Quick = FALSE; 1729: 1730: if (strcasecmp ("FAT", Filesystem) == 0) 1731: { 1732: if (hiddenVolume) 1733: { 1734: if (fseeko (f, startSector * SECTOR_SIZE, SEEK_SET) == -1) 1735: { 1736: perror ("Cannot seek to hidden volume data area"); 1737: goto err; 1738: } 1739: } 1740: 1741: ft.num_sectors = (unsigned int) totalSectors - 1; 1742: ft.cluster_size = ClusterSize; 1743: memcpy (ft.volume_name, "NO NAME ", 11); 1744: GetFatParams (&ft); 1745: r = FormatFat (startSector, &ft, f, ci, Quick); 1746: } 1747: else if (!hiddenVolume) 1748: { 1749: r = FormatNoFs (startSector, totalSectors - 1, f, ci, Quick); 1750: } 1751: 1752: if (r == ERR_OS_ERROR) 1753: { 1754: perror ("Volume creation failed"); 1755: goto err; 1756: } 1757: 1758: if (DisplayProgress && IsTerminal) 1759: puts ("\nVolume created."); 1760: 1.1.1.4 root 1761: ret = TRUE; 1.1.1.3 root 1762: 1763: err: 1.1.1.4 root 1764: if (ci) 1765: crypto_close (ci); 1766: if (f) 1767: fclose (f); 1768: if (!ret && deleteOnError && IsFile (hostPath)) 1769: remove (hostPath); 1770: Randfree (); 1771: return ret; 1.1.1.3 root 1772: } 1773: 1774: 1775: static BOOL ChangePassword (char *volumePath) 1776: { 1777: char header[HEADER_SIZE]; 1.1.1.4 root 1778: char path[TC_MAX_PATH]; 1.1.1.3 root 1779: Password *pw = &password; 1780: PCRYPTO_INFO ci = NULL, ci2 = NULL; 1.1.1.4 root 1781: unsigned long long startSector, totalSectors; 1.1.1.3 root 1782: time_t modTime = 0, acTime; 1.1.1.4 root 1783: int wipePass, ret = FALSE; 1784: int fd = -1, r; 1.1.1.3 root 1785: FILE *f; 1786: 1787: // Volume path 1788: volumePath = AskVolumePath (volumePath, "Enter volume path"); 1789: 1.1.1.4 root 1790: if (!NoKeyFiles && !FirstKeyFile) 1791: AskKeyFiles ("Enter current keyfile path", &FirstKeyFile); 1792: 1.1.1.3 root 1793: // Open volume 1794: if (!OpenVolume (volumePath, "Enter current password for '%s': ", volumePath, FALSE, 1795: &ci, &startSector, &totalSectors, &modTime, &acTime)) 1796: return FALSE; 1797: 1.1.1.4 root 1798: puts (""); 1799: 1.1.1.3 root 1800: // New password and/or keyfile(s) 1.1.1.4 root 1801: if (!NoNewKeyFiles && !FirstNewKeyFile) 1802: AskKeyFiles ("Enter new keyfile path", &FirstNewKeyFile); 1803: 1.1.1.3 root 1804: if (!CmdPassword2Valid) 1805: { 1806: while (1) 1807: { 1808: AskPassword ("Enter new password for '%s': ", volumePath, &password); 1809: if (!DisplayPassword) 1810: { 1811: Password pv; 1812: AskPassword ("Re-enter new password%s", ": ", &pv); 1813: if (password.Length != pv.Length || memcmp (password.Text, pv.Text, pv.Length)) 1814: { 1815: puts ("Passwords do not match.\n"); 1816: continue; 1817: } 1818: } 1819: break; 1820: } 1821: 1822: puts (""); 1823: } 1824: else 1825: pw = &CmdPassword2; 1.1.1.4 root 1826: 1827: if (!FirstNewKeyFile && pw->Length == 0) 1828: { 1.1.1.5 ! root 1829: error ("Password cannot be empty when no keyfile is specified\n"); 1.1.1.4 root 1830: goto err; 1831: } 1.1.1.3 root 1832: 1833: if (FirstNewKeyFile && !KeyFilesApply (pw, FirstNewKeyFile, !UpdateTime)) 1834: { 1835: error ("Error while processing new keyfiles\n"); 1.1.1.4 root 1836: goto err; 1.1.1.3 root 1837: } 1838: 1839: fd = open (volumePath, O_RDWR | O_SYNC); 1840: if (fd == -1) 1841: { 1842: perror ("Cannot open file or device"); 1.1.1.4 root 1843: goto err; 1.1.1.3 root 1844: } 1.1.1.4 root 1845: 1846: OpenMiceDevice (); 1847: if (!RandFillPool ()) 1848: goto err; 1849: 1.1.1.3 root 1850: f = fdopen (fd, "r+b"); 1851: 1852: // Write a new volume header 1853: for (wipePass = 0; wipePass < DISK_WIPE_PASSES; wipePass++) 1854: { 1855: BOOL wipeMode = wipePass < DISK_WIPE_PASSES - 1; 1856: 1.1.1.4 root 1857: if (Verbose) 1.1.1.3 root 1858: { 1.1.1.4 root 1859: printf ("\rWriting header (pass %d)%s", wipePass, wipeMode ? "" : "\n"); 1860: fflush (stdout); 1.1.1.3 root 1861: } 1862: 1863: r = VolumeWriteHeader (header, 1864: ci->ea, 1865: ci->mode, 1866: pw, 1867: HashAlgorithm == 0 ? ci->pkcs5 : HashAlgorithm, 1868: (char *)ci->master_key, 1869: ci->volume_creation_time, 1870: &ci2, 1871: ci->hiddenVolumeSize, 1872: wipeMode); 1873: 1874: if (r == ERR_CIPHER_INIT_WEAK_KEY) 1875: { 1876: error ("A weak or a potentially weak key has been generated. Please try again.\n"); 1877: goto err; 1878: } 1879: 1880: if (r != 0) 1881: { 1882: error ("Volume header creation failed.\n"); 1883: goto err; 1884: } 1885: 1886: crypto_close (ci2); 1887: ci2 = NULL; 1888: 1889: if (ci->hiddenVolumeSize) 1890: { 1891: if (fseek (f, -HIDDEN_VOL_HEADER_OFFSET, SEEK_END) == -1) 1892: { 1893: perror ("Cannot seek to hidden volume header location"); 1894: goto err; 1895: } 1896: } 1897: else 1898: { 1899: if (fseek (f, 0, SEEK_SET) == -1) 1900: { 1901: perror ("Cannot seek to volume header location"); 1902: goto err; 1903: } 1904: } 1905: 1906: if (fwrite (header, 1, HEADER_SIZE, f) != HEADER_SIZE) 1907: { 1908: perror ("Cannot write volume header"); 1909: goto err; 1910: } 1911: 1912: fflush (f); 1913: fdatasync (fd); 1914: } 1915: 1.1.1.4 root 1916: if (Verbose) 1917: puts (""); 1918: 1919: printf ("Password %schanged.\n", FirstKeyFile && FirstNewKeyFile ? "and/or keyfile(s) " : ""); 1920: 1921: if (!FirstKeyFile && FirstNewKeyFile) 1922: puts ("Keyfiles added."); 1923: 1924: if (FirstKeyFile && !FirstNewKeyFile) 1925: puts ("Keyfiles removed."); 1926: 1927: ret = TRUE; 1.1.1.3 root 1928: 1929: err: 1.1.1.4 root 1930: if (ci) 1931: crypto_close (ci); 1932: if (fd != -1) 1933: close (fd); 1.1.1.3 root 1934: 1935: if (!UpdateTime && modTime != 0) 1936: RestoreFileTime (volumePath, modTime, acTime); 1937: 1.1.1.4 root 1938: Randfree (); 1.1.1.3 root 1939: return ret; 1940: } 1941: 1942: 1943: static BOOL BackupVolumeHeaders (char *backupFile, char *volumePath) 1944: { 1.1.1.4 root 1945: char path[TC_MAX_PATH]; 1.1.1.3 root 1946: char header[HEADER_SIZE * 2]; 1947: FILE *f = NULL, *fb = NULL; 1948: struct stat volumeStat; 1949: int ret = FALSE; 1950: 1951: DropEffectiveUserId (); 1952: 1953: // Volume path 1954: volumePath = AskVolumePath (volumePath, "Enter volume path"); 1955: 1956: if (strcmp (backupFile, volumePath) == 0) 1957: { 1958: error ("Volume path identical to backup file\n"); 1959: goto err; 1960: } 1961: 1962: volumeStat.st_mtime = 0; 1963: if (IsFile (volumePath) && stat (volumePath, &volumeStat) != 0) 1964: { 1965: perror ("Cannot read volume's modification and access time"); 1966: volumeStat.st_mtime = 0; 1967: goto err; 1968: } 1969: 1970: // Volume 1971: f = fopen (volumePath, "rb"); 1972: if (!f) 1973: { 1974: perror ("Cannot open volume"); 1975: goto err; 1976: } 1977: 1978: if (fread (header, 1, HEADER_SIZE, f) != HEADER_SIZE) 1979: { 1980: perror ("Cannot read volume header"); 1981: goto err; 1982: } 1983: 1984: if (fseek (f, -HIDDEN_VOL_HEADER_OFFSET, SEEK_END) == -1) 1985: { 1986: perror ("Cannot seek to hidden volume header location"); 1987: goto err; 1988: } 1989: 1990: if (fread (header + HEADER_SIZE, 1, HEADER_SIZE, f) != HEADER_SIZE) 1991: { 1992: perror ("Cannot read hidden volume header"); 1993: goto err; 1994: } 1995: 1996: // Backup file 1997: fb = fopen (backupFile, "wb"); 1998: if (!fb) 1999: { 2000: perror ("Cannot open backup file"); 2001: goto err; 2002: } 2003: 2004: if (fwrite (header, 1, HEADER_SIZE * 2, fb) != HEADER_SIZE * 2) 2005: { 2006: perror ("Cannot write backup file"); 2007: goto err; 2008: } 2009: 2010: ret = TRUE; 2011: 2012: err: 2013: if (f) 2014: fclose (f); 2015: if (f) 2016: fclose (fb); 2017: 2018: if (!UpdateTime && volumeStat.st_mtime != 0) 2019: RestoreFileTime (volumePath, volumeStat.st_mtime, volumeStat.st_atime); 2020: 2021: return ret; 2022: } 2023: 2024: 2025: static BOOL RestoreVolumeHeader (char *backupFile, char *volumePath) 2026: { 1.1.1.4 root 2027: char path[TC_MAX_PATH]; 1.1.1.3 root 2028: char header[HEADER_SIZE]; 2029: FILE *f = NULL, *fb = NULL; 2030: struct stat volumeStat; 2031: int ret = FALSE; 2032: BOOL hiddenVolume; 2033: 2034: DropEffectiveUserId (); 2035: 2036: // Backup file 2037: fb = fopen (backupFile, "rb"); 2038: if (!fb) 2039: { 2040: perror ("Cannot open backup file"); 2041: goto err; 2042: } 2043: 2044: // Volume path 2045: volumePath = AskVolumePath (volumePath, "Enter volume path"); 2046: 2047: if (strcmp (backupFile, volumePath) == 0) 2048: { 2049: error ("Volume path identical to backup file\n"); 2050: goto err; 2051: } 2052: 2053: // Volume type 2054: switch (VolumeType) 2055: { 2056: case VOLUME_TYPE_NORMAL: 2057: hiddenVolume = FALSE; 2058: break; 2059: 2060: case VOLUME_TYPE_HIDDEN: 2061: hiddenVolume = TRUE; 2062: Quick = TRUE; 2063: break; 2064: 2065: default: 1.1.1.4 root 2066: puts ("Restore header of:\n 1) Normal/Outer Volume\n 2) Hidden Volume"); 1.1.1.3 root 2067: hiddenVolume = AskSelection (1, 1, 2) == 2; 2068: break; 2069: } 2070: 2071: volumeStat.st_mtime = 0; 2072: if (IsFile (volumePath) && stat (volumePath, &volumeStat) != 0) 2073: { 2074: perror ("Cannot read volume's modification and access time"); 2075: volumeStat.st_mtime = 0; 2076: goto err; 2077: } 2078: 2079: f = fopen (volumePath, "r+b"); 2080: if (!f) 2081: { 2082: perror ("Cannot open volume"); 2083: goto err; 2084: } 2085: 2086: if (hiddenVolume) 2087: { 2088: 2089: if (fseek (fb, HEADER_SIZE, SEEK_SET) == -1) 2090: { 2091: perror ("Cannot seek to hidden volume header location in backup file"); 2092: goto err; 2093: } 2094: 2095: if (fseek (f, -HIDDEN_VOL_HEADER_OFFSET, SEEK_END) == -1) 2096: { 2097: perror ("Cannot seek to hidden volume header location"); 2098: goto err; 2099: } 2100: } 2101: 2102: if (fread (header, 1, HEADER_SIZE, fb) != HEADER_SIZE) 2103: { 2104: perror ("Cannot read backup file"); 2105: goto err; 2106: } 2107: 2108: if (fwrite (header, 1, HEADER_SIZE, f) != HEADER_SIZE) 2109: { 2110: perror ("Cannot write volume header"); 2111: goto err; 2112: } 2113: 2114: ret = TRUE; 2115: 2116: err: 2117: if (f) 2118: fclose (f); 2119: if (f) 2120: fclose (fb); 2121: 2122: if (!UpdateTime && volumeStat.st_mtime != 0) 2123: RestoreFileTime (volumePath, volumeStat.st_mtime, volumeStat.st_atime); 2124: 2125: return ret; 2126: } 2127: 2128: 2129: static BOOL CreateKeyfile (char *path) 2130: { 2131: uint8_t keyFile[MAX_PASSWORD]; 1.1.1.4 root 2132: FILE *f = NULL; 2133: int ret = FALSE; 1.1.1.3 root 2134: 1.1.1.4 root 2135: OpenMiceDevice (); 1.1.1.3 root 2136: DropEffectiveUserId (); 2137: 1.1.1.4 root 2138: if (!Overwrite 2139: && IsFile (path) 2140: && (!IsTerminal || !AskYesNo ("Keyfile already exists - overwrite?", TRUE))) 2141: { 2142: if (!IsTerminal) 2143: error ("Keyfile already exists.\n"); 1.1.1.3 root 2144: return FALSE; 1.1.1.4 root 2145: } 1.1.1.3 root 2146: 2147: f = fopen (path, "wb"); 2148: if (!f) 2149: { 2150: perror ("Cannot open file"); 1.1.1.4 root 2151: goto err; 1.1.1.3 root 2152: } 2153: 1.1.1.4 root 2154: if (!RandFillPool ()) 2155: goto err; 2156: 2157: if (!RandgetBytes (keyFile, sizeof (keyFile), FALSE)) 2158: goto err; 2159: 1.1.1.3 root 2160: if (fwrite (keyFile, 1, sizeof (keyFile), f) != sizeof (keyFile)) 2161: { 2162: perror ("Cannot write file"); 1.1.1.4 root 2163: goto err; 1.1.1.3 root 2164: } 2165: 2166: puts ("Keyfile created."); 1.1.1.4 root 2167: ret = TRUE; 2168: 2169: err: 2170: if (f) 2171: fclose (f); 2172: Randfree (); 2173: return ret; 1.1.1.3 root 2174: } 2175: 2176: 2177: static time_t WindowsFileTime2UnixTime (uint64_t wTime) 2178: { 2179: return (time_t) (wTime / 1000LL / 1000 / 10 - 134774LL * 24 * 3600); 2180: } 2181: 2182: 2183: static BOOL DumpVolumeProperties (char *volumePath) 2184: { 1.1.1.4 root 2185: unsigned long long startSector, totalSectors; 1.1.1.3 root 2186: time_t modTime = 0, acTime; 2187: PCRYPTO_INFO ci = NULL; 2188: BOOL ret = FALSE; 2189: char eaName[256], timeBuf[256], timeBuf2[256]; 2190: int keySize; 2191: time_t volCTime, headerMTime; 2192: 2193: volumePath = AskVolumePath (volumePath, "Enter volume path"); 2194: 1.1.1.4 root 2195: if (!NoKeyFiles && !FirstKeyFile) 2196: AskKeyFiles ("Enter keyfile path", &FirstKeyFile); 2197: 1.1.1.3 root 2198: if (!OpenVolume (volumePath, "Enter password for '%s': ", volumePath, FALSE, 2199: &ci, &startSector, &totalSectors, &modTime, &acTime)) 2200: goto err; 2201: 2202: EAGetName (eaName, ci->ea); 2203: 2204: keySize = EAGetKeySize (ci->ea); 2205: if (strcmp (eaName, "Triple DES") == 0) 2206: keySize -= 3; // Compensate for parity bytes 2207: 2208: volCTime = WindowsFileTime2UnixTime (ci->volume_creation_time); 2209: headerMTime = WindowsFileTime2UnixTime (ci->header_creation_time); 2210: 2211: printf ("%sVolume properties:\n" 2212: " Location: %s\n" 1.1.1.4 root 2213: " Size: %llu bytes\n" 1.1.1.3 root 2214: " Type: %s\n" 2215: " Encryption algorithm: %s\n" 2216: " Key size: %d bits\n" 2217: " Block size: %d bits\n" 2218: " Mode of operation: %s\n" 2219: " PKCS-5 PRF: %s\n" 2220: " PKCS-5 iteration count: %d\n" 2221: , 2222: CmdPasswordValid ? "" : "\n", 2223: volumePath, 2224: totalSectors * SECTOR_SIZE, 2225: ci->hiddenVolumeSize == 0 ? "Normal" : "Hidden", 2226: eaName, 2227: keySize * 8, 2228: CipherGetBlockSize (EAGetFirstCipher(ci->ea)) * 8, 2229: EAGetModeName (ci->ea, ci->mode, TRUE), 2230: get_pkcs5_prf_name (ci->pkcs5), 1.1.1.4 root 2231: ci->noIterations 1.1.1.3 root 2232: ); 2233: 1.1.1.5 ! root 2234: memset (timeBuf, 0, sizeof (timeBuf)); ! 2235: memset (timeBuf2, 0, sizeof (timeBuf2)); ! 2236: ! 2237: if (ctime_r (&volCTime, timeBuf) == NULL || ctime_r (&headerMTime, timeBuf2) == NULL) ! 2238: goto err; ! 2239: 1.1.1.4 root 2240: printf (" Volume created: %s" 2241: " Header modified: %s", 1.1.1.5 ! root 2242: timeBuf, timeBuf2); 1.1.1.4 root 2243: 1.1.1.3 root 2244: ret = TRUE; 2245: err: 2246: if (ci != NULL) 2247: crypto_close (ci); 2248: 2249: if (!UpdateTime && modTime != 0) 2250: RestoreFileTime (volumePath, modTime, acTime); 2251: 2252: return ret; 2253: } 2254: 2255: 2256: static void DumpVersion (FILE *f) 2257: { 2258: fprintf (f, 1.1.1.4 root 2259: "truecrypt %s\n\n\ 1.1.1.5 ! root 2260: Released under the TrueCrypt Collective License 1.1\n\n\ ! 2261: Copyright (C) 2003-2007 TrueCrypt Foundation. All Rights Reserved.\n\ 1.1.1.3 root 2262: Copyright (C) 1998-2000 Paul Le Roux. All Rights Reserved.\n\ 1.1.1.5 ! root 2263: Copyright (C) 1999-2006 Dr. Brian Gladman. All Rights Reserved.\n\ 1.1.1.3 root 2264: Copyright (C) 1995-1997 Eric Young. All Rights Reserved.\n\ 2265: Copyright (C) 2001 Markus Friedl. All Rights Reserved.\n\n" 2266: , VERSION_STRING); 2267: } 2268: 2269: 2270: static void DumpUsage (FILE *f) 2271: { 2272: fprintf (f, 2273: "Usage: truecrypt [OPTIONS] VOLUME_PATH [MOUNT_DIRECTORY]\n" 1.1.1.4 root 2274: " or: truecrypt [OPTIONS] -i\n" 1.1.1.3 root 2275: " or: truecrypt [OPTIONS] -c | --create | -C | --change [VOLUME_PATH]\n" 2276: " or: truecrypt [OPTIONS] -d | --dismount | -l | --list [MAPPED_VOLUME]\n" 2277: " or: truecrypt [OPTIONS] --backup-headers | --restore-header FILE [VOLUME]\n" 2278: " or: truecrypt [OPTIONS] --properties [VOLUME_PATH]\n" 1.1.1.4 root 2279: " or: truecrypt [OPTIONS] --keyfile-create FILE\n" 1.1.1.3 root 2280: " or: truecrypt -h | --help | --test | -V | --version\n" 2281: "\nCommands:\n" 2282: " VOLUME_PATH Map volume\n" 2283: " VOLUME_PATH MOUNT_DIRECTORY Map and mount volume\n" 2284: " --backup-headers FILE [VOLUME] Backup headers of VOLUME to FILE\n" 2285: " -c, --create [VOLUME_PATH] Create a new volume\n" 2286: " -C, --change [VOLUME_PATH] Change password/keyfile(s)\n" 2287: " -d, --dismount [MAPPED_VOLUME] Dismount and unmap volume\n" 2288: " -h, --help Display detailed help\n" 2289: " --keyfile-create FILE Create a new keyfile\n" 1.1.1.4 root 2290: " -i, --interactive Map and mount volume interactively\n" 1.1.1.3 root 2291: " -l, --list [MAPPED_VOLUME] List mapped volumes\n" 2292: " --properties [VOLUME_PATH] Display properties of volume\n" 1.1.1.4 root 2293: " --restore-header FILE [VOLUME] Restore header of VOLUME from FILE\n" 1.1.1.3 root 2294: " --test Test algorithms\n" 1.1.1.5 ! root 2295: " -V, --version Display program version and legal notices\n" 1.1.1.3 root 2296: "\nOptions:\n" 2297: " --cluster SIZE Cluster size\n" 2298: " --display-keys Display encryption keys\n" 2299: " --display-password Display password while typing\n" 2300: " --disable-progress Disable progress display\n" 2301: " --encryption EA Encryption algorithm\n" 1.1.1.4 root 2302: " --filesystem TYPE Filesystem type\n" 1.1.1.3 root 2303: " --hash HASH Hash algorithm\n" 2304: " -k, --keyfile FILE|DIR Keyfile for volume\n" 2305: " --keyfile-add FILE|DIR New keyfile for volume\n" 2306: " -K, --keyfile-protected FILE|DIR Keyfile for protected volume\n" 2307: " -M, --mount-options OPTIONS Mount options\n" 2308: " -N, --device-number NUMBER Map volume as device number\n" 1.1.1.4 root 2309: " --overwrite Overwrite files without confirmation\n" 1.1.1.3 root 2310: " -p, --password PASSWORD Password for volume\n" 2311: " --password-tries NUMBER Password entry tries\n" 2312: " -P, --protect-hidden Protect hidden volume\n" 1.1.1.4 root 2313: " --random-source FILE Random number generator input file\n" 1.1.1.3 root 2314: " --quick Use quick format\n" 2315: " --update-time Do not preserve timestamps\n" 1.1.1.4 root 2316: " -r, --read-only Map/Mount volume as read-only\n" 1.1.1.3 root 2317: " --size SIZE Volume size\n" 2318: " --type TYPE Volume type\n" 2319: " -u, --user-mount Set default user and group ID on mount\n" 2320: " -v, --verbose Verbose output\n" 2321: "\n MAPPED_VOLUME = DEVICE_NUMBER | DEVICE_NAME | MOUNT_POINT | VOLUME_PATH\n" 1.1.1.4 root 2322: "For a detailed help, use --help or see truecrypt(1) man page.\n" 2323: "For more information, visit <http://www.truecrypt.org/docs/>.\n" 1.1.1.3 root 2324: ); 1.1 root 2325: } 2326: 1.1.1.4 root 2327: 1.1 root 2328: static void DumpHelp () 2329: { 2330: fprintf (stdout, 2331: "Manages encrypted TrueCrypt volumes, which can be mapped as virtual block\n" 2332: "devices and used as any other standard block device. All data being read\n" 2333: "from a mapped TrueCrypt volume is transparently decrypted and all data being\n" 2334: "written to it is transparently encrypted.\n" 2335: "\n" 2336: "Usage: truecrypt [OPTIONS] VOLUME_PATH [MOUNT_DIRECTORY]\n" 1.1.1.4 root 2337: " or: truecrypt [OPTIONS] -i\n" 1.1.1.3 root 2338: " or: truecrypt [OPTIONS] -c | --create | -C | --change [VOLUME_PATH]\n" 1.1 root 2339: " or: truecrypt [OPTIONS] -d | --dismount | -l | --list [MAPPED_VOLUME]\n" 1.1.1.3 root 2340: " or: truecrypt [OPTIONS] --backup-headers | --restore-header FILE [VOLUME]\n" 2341: " or: truecrypt [OPTIONS] --properties [VOLUME_PATH]\n" 1.1.1.4 root 2342: " or: truecrypt [OPTIONS] --keyfile-create FILE\n" 1.1 root 2343: " or: truecrypt -h | --help | --test | -V | --version\n" 2344: "\n" 2345: "Options:\n" 2346: "\n" 2347: "VOLUME_PATH [MOUNT_DIRECTORY]\n" 2348: " Open a TrueCrypt volume specified by VOLUME_PATH and map it as a block device\n" 2349: " /dev/mapper/truecryptN. N is the first available device number if not\n" 1.1.1.5 ! root 2350: " otherwise specified with -N. Filesystem of the mapped volume is mounted at\n" ! 2351: " MOUNT_DIRECTORY if specified. To open a hidden volume, specify its password\n" 1.1.1.3 root 2352: " and/or keyfiles (the outer volume cannot be mapped at the same time).\n" 1.1.1.5 ! root 2353: " See also EXAMPLES and options --display-password, --filesystem, -k, -M, -p, -P,\n" 1.1.1.4 root 2354: " --password-tries, -r, -u, --update-time. Note that passing some of the options\n" 1.1.1.5 ! root 2355: " may affect security (see options -i and -p for more information).\n" 1.1.1.3 root 2356: "\n" 2357: "--backup-headers BACKUP_FILE [VOLUME_PATH]\n" 2358: " Backup headers of a volume specified by VOLUME_PATH to a file BACKUP_FILE.\n" 2359: " Volume path is requested from user if not specified on command line. Both\n" 2360: " normal/outer and hidden volume headers are stored in the backup file even\n" 2361: " if there is no hidden volume within the volume (to preserve plausible\n" 2362: " deniability). When restoring the volume header, it is possible to select\n" 2363: " which header is to be restored. Note that this command drops effective user\n" 2364: " ID. See also --restore-header.\n" 2365: "\n" 2366: "-c, --create [VOLUME_PATH]\n" 2367: " Create a new volume. Most options are requested from user if not specified\n" 2368: " on command line. Hidden volume can be created only in an existing file or\n" 2369: " device. Size of the hidden volume should not exceed the free space of the\n" 2370: " filesystem on the outer volume. Hidden volume protection (see option -P)\n" 2371: " should be used to update the outer volume contents after the hidden volume\n" 1.1.1.4 root 2372: " is created. WARNING: To prevent data corruption, you should follow the\n" 2373: " instructions in the EXAMPLES section on how to create a hidden volume.\n" 2374: " Note that this command drops effective user ID.\n" 1.1.1.3 root 2375: " See also options --cluster, --disable-progress, --display-keys,\n" 1.1.1.4 root 2376: " --encryption, -k, --filesystem, --hash, -p, --random-source, --quick, --size,\n" 1.1.1.5 ! root 2377: " --type. Note that passing some of the options may affect security (see option\n" ! 2378: " -p for more information).\n" 1.1.1.3 root 2379: "\n" 2380: "-C, --change [VOLUME_PATH]\n" 2381: " Change a password and/or keyfile(s) of a volume. Volume path and passwords are\n" 2382: " requested from user if not specified on command line. PKCS-5 PRF HMAC hash\n" 2383: " algorithm can be changed with option --hash. See also options -k,\n" 1.1.1.4 root 2384: " --keyfile-add, -p, --random-source, -v.\n" 1.1 root 2385: "\n" 2386: "-d, --dismount [MAPPED_VOLUME]\n" 2387: " Dismount and unmap mapped volumes. If MAPPED_VOLUME is not specified, all\n" 2388: " volumes are dismounted and unmapped. See below for a description of\n" 2389: " MAPPED_VOLUME.\n" 2390: "\n" 1.1.1.3 root 2391: "-h, --help\n" 2392: " Display help information.\n" 2393: "\n" 1.1.1.4 root 2394: "-i, --interactive\n" 1.1.1.5 ! root 2395: " Map and mount a volume interactively. Options which may affect security are\n" ! 2396: " requested from the user. See option -p for more information.\n" 1.1.1.4 root 2397: "\n" 1.1 root 2398: "-l, --list [MAPPED_VOLUME]\n" 2399: " Display a list of mapped volumes. If MAPPED_VOLUME is not specified, all\n" 2400: " volumes are listed. By default, the list contains only volume path and mapped\n" 2401: " device name pairs. A more detailed list can be enabled by verbose output\n" 2402: " option (-v). See below for a description of MAPPED_VOLUME.\n" 2403: "\n" 1.1.1.3 root 2404: "--keyfile-create FILE\n" 2405: " Create a new keyfile using the random number generator. FILE argument specifies\n" 2406: " the output file. Note that this command drops effective user ID.\n" 2407: "\n" 2408: "--properties [VOLUME_PATH]\n" 2409: " Display properties of a volume specified by VOLUME_PATH.\n" 2410: "\n" 2411: "--restore-header BACKUP_FILE [VOLUME_PATH]\n" 2412: " Restore header of a volume specified by VOLUME_PATH from a file BACKUP_FILE.\n" 2413: " Volume path is requested from user if not specified on command line.\n" 2414: " Type of the restored volume header (normal/hidden) is requested from user if\n" 2415: " not specified with --type. Note that this command drops effective user ID.\n" 2416: " See also --backup-headers.\n" 2417: "\n" 2418: "--test\n" 2419: " Test all internal algorithms used in the process of encryption and decryption.\n" 2420: "\n" 2421: "-V, --version\n" 1.1.1.5 ! root 2422: " Display program version and legal notices.\n" 1.1.1.3 root 2423: "\n" 1.1.1.4 root 2424: "MAPPED_VOLUME:\n" 1.1 root 2425: " Specifies a mapped or mounted volume. One of the following forms can be used:\n\n" 2426: " 1) Path to the encrypted TrueCrypt volume.\n\n" 2427: " 2) Mount directory of the volume's filesystem (if mounted).\n\n" 2428: " 3) Device number of the mapped volume.\n\n" 2429: " 4) Device name of the mapped volume.\n\n" 2430: "\n" 1.1.1.3 root 2431: "--cluster SIZE\n" 2432: " Use specified cluster size when creating a new volume. SIZE defines the number\n" 2433: " of sectors per cluster.\n" 2434: "\n" 2435: "--disable-progress\n" 2436: " Disable display of progress information during creation of a new volume.\n" 2437: "\n" 2438: "--display-keys\n" 2439: " Display encryption keys generated during creation of a new volume.\n" 1.1 root 2440: "\n" 2441: "--display-password\n" 2442: " Display password characters while typing.\n" 2443: "\n" 1.1.1.4 root 2444: "--encryption ENCRYPTION_ALGORITHM\n" 1.1.1.3 root 2445: " Use specified encryption algorithm when creating a new volume.\n" 2446: "\n" 1.1 root 2447: "--filesystem TYPE\n" 2448: " Filesystem type to mount. The TYPE argument is passed to mount(8) command\n" 1.1.1.3 root 2449: " with option -t. Default type is 'auto'. When creating a new volume, this\n" 2450: " option specifies the filesystem to be created on the new volume.\n" 1.1 root 2451: "\n" 1.1.1.3 root 2452: "--hash HASH\n" 2453: " Use specified hash algorithm when creating a new volume or changing password\n" 2454: " and/or keyfiles.\n" 1.1 root 2455: "\n" 2456: "-k, --keyfile FILE | DIRECTORY\n" 1.1.1.3 root 2457: " Use specified keyfile to open a volume to be mapped (or when changing password\n" 2458: " and/or keyfiles). When a directory is specified, all files inside it will be\n" 2459: " used (non-recursively). Additional keyfiles can be specified with multiple -k\n" 1.1.1.5 ! root 2460: " options. Empty keyfile (-k '') disables interactive requests for keyfiles\n" 1.1.1.4 root 2461: " (e.g., when creating a new volume). See also option -K.\n" 1.1 root 2462: "\n" 2463: "-K, --keyfile-protected FILE | DIRECTORY\n" 1.1.1.4 root 2464: " Use specified keyfile to open a hidden volume to be protected. This option\n" 2465: " may be used only when mounting an outer volume with hidden volume protected.\n" 2466: " See also options -k and -P.\n" 1.1 root 2467: "\n" 1.1.1.3 root 2468: "--keyfile-add FILE | DIRECTORY\n" 2469: " Add specified keyfile to a volume when changing its password and/or keyfiles.\n" 2470: " This option must be also used to keep all previous keyfiles asigned to a\n" 2471: " volume. See EXAMPLES for more information.\n" 2472: "\n" 2473: "-M, --mount-options OPTIONS\n" 1.1 root 2474: " Filesystem mount options. The OPTIONS argument is passed to mount(8)\n" 1.1.1.5 ! root 2475: " command with option -o. This option can be specified only by an administrator.\n" ! 2476: " See also options -r and -u.\n" 1.1.1.3 root 2477: "\n" 2478: "-N, --device-number N\n" 2479: " Use device number N when mapping a volume as a block device\n" 2480: " /dev/mapper/truecryptN. Default is the first available device.\n" 2481: "\n" 1.1.1.4 root 2482: "--overwrite\n" 2483: " Overwrite files without prompting the user for confirmation.\n" 2484: "\n" 1.1 root 2485: "-p, --password PASSWORD\n" 2486: " Use specified password to open a volume. Additional passwords can be\n" 2487: " specified with multiple -p options. An empty password can also be specified\n" 1.1.1.5 ! root 2488: " ('' in most shells). Note that passing a password on the command line is\n" 1.1 root 2489: " potentially insecure as the password may be visible in the process list\n" 2490: " (see ps(1)) and/or stored in a command history file. \n" 2491: " \n" 2492: "--password-tries NUMBER\n" 2493: " Prompt NUMBER of times for a password until the correct password is entered.\n" 2494: " Default is to prompt three times.\n" 2495: "\n" 2496: "-P, --protect-hidden\n" 2497: " Write-protect a hidden volume when mapping an outer volume. Before mapping the\n" 2498: " outer volume, the user will be prompted for a password to open the hidden\n" 2499: " volume. The size and position of the hidden volume is then determined and the\n" 1.1.1.3 root 2500: " outer volume is mapped with all sectors belonging to the hidden volume\n" 1.1 root 2501: " protected against write operations. When a write to the protected area is\n" 2502: " prevented, the whole volume is switched to read-only mode. Verbose list command\n" 2503: " (-vl) can be used to query the state of the hidden volume protection. Warning\n" 2504: " message is displayed when a volume switched to read-only is being dismounted.\n" 1.1.1.4 root 2505: " See also options -r and -i.\n" 1.1.1.3 root 2506: "\n" 2507: "--quick\n" 2508: " Use quick format when creating a new volume. This option can be used only\n" 2509: " when creating a device-hosted volume. Quick format is always used when\n" 2510: " creating a hidden volume.\n" 2511: "\n" 1.1.1.4 root 2512: "--random-source FILE\n" 2513: " Use FILE as a source of random numbers. Standard input is used if '-' is\n" 2514: " specified.\n" 2515: "\n" 1.1 root 2516: "-r, --read-only\n" 1.1.1.3 root 2517: " Map and mount a volume as read-only. Write operations to the volume may not\n" 1.1 root 2518: " fail immediately due to the write buffering performed by the system, but the\n" 2519: " physical write will still be prevented.\n" 1.1.1.3 root 2520: "\n" 2521: "--size SIZE\n" 2522: " Use specified size when creating a new volume. SIZE is defined as number of\n" 2523: " bytes or, when a size suffix K/M/G is used, Kilobytes/Megabytes/Gigabytes.\n" 2524: " Note that size must be a multiple of 512 bytes.\n" 2525: "\n" 2526: "--type TYPE\n" 2527: " Use specified volume type when creating a new volume or restoring a volume\n" 2528: " header. TYPE can be 'normal' or 'hidden'.\n" 2529: "\n" 2530: "-u, --user-mount\n" 2531: " Set default user and group ID of the filesystem being mounted to the user and\n" 1.1.1.5 ! root 2532: " group ID of the process which executed TrueCrypt. Some filesystems (e.g., FAT)\n" ! 2533: " do not support Unix-style access control and, therefore, it is necessary to\n" ! 2534: " supply a default user and group ID to the operating system when mounting them.\n" ! 2535: " Note that Unix-style filesystems (e.g., ext2) do not support this option.\n" 1.1 root 2536: "\n" 2537: "--update-time\n" 2538: " Do not preserve access and modification timestamps of volume containers and\n" 2539: " access timestamps of keyfiles. By default, timestamps are restored after\n" 2540: " a volume is unmapped or after a keyfile is closed.\n" 2541: "\n" 2542: "-v, --verbose\n" 2543: " Enable verbose output. Multiple -v options can be specified to increase the\n" 2544: " level of verbosity.\n" 2545: "\n" 2546: "Examples:\n" 2547: "\n" 2548: "truecrypt /root/volume.tc /mnt/tc\n" 1.1.1.3 root 2549: " Map a volume /root/volume.tc and mount its filesystem at directory /mnt/tc.\n" 2550: "\n" 2551: "truecrypt -u /dev/hda2 /mnt/tc\n" 2552: " Map a volume /dev/hda2 (first ATA disk, primary partition 2) and mount its\n" 2553: " filesystem at /mnt/tc. Default user-id is set, which is useful when mounting\n" 1.1.1.5 ! root 2554: " a filesystem such as FAT under a non-admin user account.\n" 1.1 root 2555: "\n" 1.1.1.4 root 2556: "truecrypt -i\n" 2557: " Map and mount a volume. Options are requested interactively.\n" 2558: "\n" 1.1 root 2559: "truecrypt -d\n" 2560: " Dismount and unmap all mapped volumes.\n" 1.1.1.4 root 2561: "\n" 1.1 root 2562: "truecrypt -d /root/volume.tc\n" 2563: " Dismount and unmap a volume /root/volume.tc.\n" 2564: "\n" 2565: "truecrypt -d /mnt/tc\n" 2566: " Dismount and unmap a volume mounted at /mnt/tc.\n" 2567: "\n" 2568: "truecrypt -vl\n" 2569: " Display a detailed list of all mapped volumes.\n" 2570: " \n" 1.1.1.3 root 2571: "truecrypt -N 1 /dev/hdc1 && mkfs /dev/mapper/truecrypt1\n" 1.1 root 2572: " Map a volume /dev/hdc1 and create a new filesystem on it.\n" 2573: "\n" 2574: "truecrypt -P /dev/hdc1 /mnt/tc\n" 2575: " Map and mount outer volume /dev/hdc1 and protect hidden volume within it.\n" 2576: "\n" 1.1.1.5 ! root 2577: "truecrypt -p '' -p '' -k key1 -k key2 -K key_hidden -P volume.tc\n" 1.1 root 2578: " Map outer volume ./volume.tc and protect hidden volume within it.\n" 2579: " The outer volume is opened with keyfiles ./key1 and ./key2 and the\n" 2580: " hidden volume with ./key_hidden. Passwords for both volumes are empty.\n" 2581: "\n" 1.1.1.3 root 2582: "truecrypt -c\n" 1.1.1.4 root 2583: " Create a new volume. Options are requested interactively." 2584: "\n" 2585: "truecrypt -c /dev/hda2\n" 2586: " Create a new volume hosted at the second primary partition of the first\n" 2587: " ATA disk.\n" 1.1.1.3 root 2588: "\n" 2589: "truecrypt -k keyfile --size 10M --encryption AES --hash SHA-1 -c vol.tc\n" 2590: " Create a new volume. Options which are not specified on command line are\n" 2591: " requested from the user.\n" 2592: "\n" 2593: "truecrypt --keyfile-add keyfile -C volume.tc\n" 2594: " Change password and add a new keyfile to volume.\n" 2595: "\n" 2596: "truecrypt -k keyfile -C volume.tc\n" 2597: " Change password and remove a keyfile from volume.\n" 2598: "\n" 2599: "truecrypt -k keyfile --keyfile-add keyfile -C volume.tc\n" 2600: " Change password and keep previous keyfile.\n" 2601: "\n" 1.1.1.4 root 2602: "Creating a hidden volume without risking data corruption:\n" 2603: " 1) Create an outer volume:\n" 2604: " truecrypt --type normal --size 100M -c volume.tc\n" 2605: " 2) Create a hidden volume:\n" 2606: " truecrypt --type hidden --size 50M -c volume.tc\n" 2607: " 3) Mount the outer volume with the hidden volume protected:\n" 2608: " truecrypt -P volume.tc /mnt/tc\n" 2609: " 4) Copy files to the outer volume:\n" 2610: " cp outer_volume_file.txt /mnt/tc\n" 2611: " 5) Dismount the outer volume:\n" 2612: " truecrypt -d volume.tc\n" 2613: " 6) If a warning message has been displayed in 5), start again from 1). Either\n" 1.1.1.5 ! root 2614: " a larger outer volume should be created in 1), or less data should be copied\n" ! 2615: " to the outer volume in 4).\n" 1.1.1.4 root 2616: "\n" 2617: "Report bugs at <http://www.truecrypt.org/bugs/>.\n" 1.1 root 2618: ); 2619: } 2620: 1.1.1.4 root 2621: 1.1 root 2622: static BOOL DumpMountList (int devNo) 2623: { 1.1.1.3 root 2624: BOOL found = FALSE; 1.1 root 2625: int i; 2626: 1.1.1.4 root 2627: if (!CheckKernelModuleVersion (FALSE, TRUE) 2628: || !GetMountList (FALSE) 2629: || (devNo == -1 && MountList[0].DeviceNumber == -1)) 1.1.1.3 root 2630: { 1.1.1.4 root 2631: error ("No volumes mapped\n"); 1.1.1.3 root 2632: return FALSE; 2633: } 2634: 1.1 root 2635: for (i = 0; MountList[i].DeviceNumber != -1; i++) 2636: { 2637: MountListEntry *e = &MountList[i]; 2638: 2639: if (devNo != -1 && e->DeviceNumber != devNo) 2640: continue; 2641: 1.1.1.3 root 2642: found = TRUE; 2643: 1.1 root 2644: if (Verbose == 0) 2645: { 2646: printf (TC_MAP_DEV "%d %s\n", 2647: e->DeviceNumber, 2648: e->VolumePath); 2649: } 2650: else 2651: { 2652: char eaName[128]; 2653: EAGetName (eaName, e->EA); 2654: 2655: printf (TC_MAP_DEV "%d:\n" 2656: " Volume: %s\n" 2657: " Type: %s\n" 1.1.1.4 root 2658: " Size: %llu bytes\n" 1.1 root 2659: " Encryption algorithm: %s\n" 1.1.1.2 root 2660: " Mode of operation: %s\n" 1.1 root 2661: " Read-only: %s\n" 2662: " Hidden volume protected: %s\n\n", 2663: e->DeviceNumber, 2664: e->VolumePath, 2665: e->Hidden ? "Hidden" : "Normal", 2666: e->VolumeSize, 2667: eaName, 1.1.1.2 root 2668: EAGetModeName (e->EA, e->Mode, TRUE), 1.1.1.4 root 2669: (e->Flags & TC_READ_ONLY) ? "Yes" : "No", 2670: (e->Flags & TC_PROTECTION_ACTIVATED) ? "Yes - damage prevented" : ( 2671: (e->Flags & TC_HIDDEN_VOLUME_PROTECTION) ? "Yes" : "No" ) 1.1 root 2672: ); 2673: } 2674: } 2675: 1.1.1.3 root 2676: if (!found) 2677: { 2678: error (TC_MAP_DEV "%d not mapped\n", devNo); 2679: return FALSE; 2680: } 2681: 1.1 root 2682: return TRUE; 2683: } 2684: 2685: 2686: static BOOL EnumMountPoints (char *device, char *mountPoint) 2687: { 2688: static FILE *m = NULL; 1.1.1.5 ! root 2689: char mp[TC_MAX_PATH], *p; 1.1 root 2690: 2691: if (device == NULL) 2692: { 2693: fclose (m); 2694: m = NULL; 2695: return TRUE; 2696: } 2697: 2698: if (m == NULL) 2699: { 2700: m = fopen ("/proc/mounts", "r"); 2701: if (m == NULL) 2702: { 2703: perror ("fopen /proc/mounts"); 2704: return FALSE; 1.1.1.5 ! root 2705: } 1.1 root 2706: } 2707: 1.1.1.4 root 2708: if (fscanf (m, "%" TC_MAX_PATH_STR "s %" TC_MAX_PATH_STR "s %*s %*s %*s %*s", 1.1.1.5 ! root 2709: device, mp) != 2) 1.1 root 2710: { 2711: fclose (m); 2712: m = NULL; 2713: return FALSE; 2714: } 2715: 1.1.1.5 ! root 2716: // Convert escaped characters ! 2717: p = mp; ! 2718: while (*p) ! 2719: { ! 2720: if (p[0] == '\\' && p[1] && p[2] && p[3]) ! 2721: { ! 2722: char c; ! 2723: if (sscanf (p + 1, "%o", &c) == 1) ! 2724: { ! 2725: *mountPoint++ = c; ! 2726: p += 4; ! 2727: continue; ! 2728: } ! 2729: } ! 2730: *mountPoint++ = *p++; ! 2731: } ! 2732: *mountPoint = 0; ! 2733: 1.1 root 2734: return TRUE; 2735: } 2736: 2737: 2738: static BOOL DismountFileSystem (char *device) 2739: { 1.1.1.4 root 2740: char mountedDevice[TC_MAX_PATH], mountPoint[TC_MAX_PATH]; 1.1 root 2741: BOOL result = TRUE; 2742: 2743: while (EnumMountPoints (mountedDevice, mountPoint)) 2744: { 2745: if (strcmp (mountedDevice, device) == 0) 2746: { 2747: if (!Execute (FALSE, "umount", mountPoint, NULL)) 2748: result = FALSE; 2749: else if (Verbose >= 1) 2750: printf ("Dismounted %s\n", mountPoint); 2751: } 2752: } 2753: 2754: return result; 2755: } 2756: 2757: 2758: // devNo: -1 = Dismount all volumes 2759: static BOOL DismountVolume (int devNo) 2760: { 1.1.1.4 root 2761: char mapDevice[TC_MAX_PATH]; 1.1 root 2762: int nMountedVolumes = 0; 2763: int i; 2764: BOOL found = FALSE; 2765: BOOL status = TRUE; 2766: 1.1.1.4 root 2767: if (!CheckKernelModuleVersion (FALSE, TRUE) 2768: || !GetMountList (FALSE) 2769: || (devNo == -1 && MountList[0].DeviceNumber == -1)) 1.1 root 2770: { 1.1.1.4 root 2771: error ("No volumes mapped\n"); 1.1 root 2772: return FALSE; 2773: } 2774: 2775: // Flush write buffers before dismount if there are 2776: // mounted volumes with hidden volume protection 2777: for (i = 0; MountList[i].DeviceNumber != -1; i++) 2778: { 1.1.1.4 root 2779: if (MountList[i].Flags & TC_HIDDEN_VOLUME_PROTECTION) 1.1 root 2780: { 2781: sync (); 2782: MountListValid = FALSE; 1.1.1.4 root 2783: GetMountList (FALSE); 1.1 root 2784: break; 2785: } 2786: } 2787: 2788: for (i = 0; MountList[i].DeviceNumber != -1; i++) 2789: { 2790: MountListEntry *e = &MountList[i]; 2791: nMountedVolumes++; 2792: 2793: if (devNo == -1 || e->DeviceNumber == devNo) 2794: { 2795: BOOL dismounted = FALSE; 2796: found = TRUE; 2797: 1.1.1.5 ! root 2798: sprintf (mapDevice, TC_MAP_DEV "%d", e->DeviceNumber); ! 2799: ! 2800: if (RealUserId != 0 && e->UserId != RealUserId) ! 2801: { ! 2802: error ("Dismount denied: %s mapped by a different user\n", mapDevice); ! 2803: status = FALSE; ! 2804: continue; ! 2805: } ! 2806: 1.1.1.4 root 2807: if (e->Flags & TC_PROTECTION_ACTIVATED) 1.1 root 2808: printf ("WARNING: Write to the hidden volume %s has been prevented!\n", e->VolumePath); 2809: 2810: if (DismountFileSystem (mapDevice)) 2811: { 2812: char name[32]; 2813: sprintf (name, "truecrypt%d", e->DeviceNumber); 2814: dismounted = Execute (FALSE, "dmsetup", "remove", name, NULL); 2815: 2816: if (dismounted && IsFile (e->VolumePath)) 2817: { 2818: if (!DeleteLoopDevice (e->DeviceMinor)) 2819: status = FALSE; 2820: 2821: RestoreFileTime (e->VolumePath, 1.1.1.4 root 2822: (UpdateTime || e->ModTime == 0) ? time (NULL) : (time_t) e->ModTime, 2823: (UpdateTime || e->AcTime == 0) ? time (NULL) : (time_t) e->AcTime); 1.1 root 2824: } 2825: } 2826: 2827: if (!dismounted) 2828: { 2829: error ("Cannot dismount %s\n", mapDevice); 2830: status = FALSE; 2831: } 2832: else 2833: { 2834: nMountedVolumes--; 2835: if (Verbose >= 1) 2836: printf ("Unmapped %s\n", mapDevice); 2837: } 2838: 2839: if (devNo != -1) 2840: break; 2841: } 2842: } 2843: 2844: if (!found) 2845: { 1.1.1.3 root 2846: error (TC_MAP_DEV "%d not mapped\n", devNo); 1.1 root 2847: return FALSE; 2848: } 2849: 2850: if (nMountedVolumes == 0) 2851: { 2852: // Ignore errors as volumes may be mounted asynchronously 2853: UnloadKernelModule (TRUE); 2854: } 2855: 2856: return status; 2857: } 2858: 2859: 2860: // Convert a string to device number 2861: // text: device number or name or mount point 1.1.1.4 root 2862: static BOOL ToDeviceNumber (char *text, int *deviceNumber) 1.1 root 2863: { 1.1.1.4 root 2864: char mountedDevice[TC_MAX_PATH], mountPoint[TC_MAX_PATH]; 1.1 root 2865: int i; 2866: 2867: if (sscanf (text, "%d", deviceNumber) == 1) 2868: return TRUE; 2869: 2870: if (sscanf (text, TC_MAP_DEV "%d", deviceNumber) == 1) 2871: return TRUE; 2872: 1.1.1.4 root 2873: // Relative path => absolute 2874: if (text[0] != '/') 2875: { 2876: char s[TC_MAX_PATH]; 2877: static char absolute[TC_MAX_PATH]; 2878: 2879: getcwd (s, sizeof (s)); 2880: snprintf (absolute, sizeof (absolute), "%s/%s", s, text); 2881: text = absolute; 2882: } 2883: 1.1 root 2884: while (EnumMountPoints (mountedDevice, mountPoint)) 2885: { 2886: if (strcmp (mountPoint, text) == 0 2887: && sscanf (mountedDevice, TC_MAP_DEV "%d", deviceNumber) == 1) 2888: { 2889: EnumMountPoints (NULL, NULL); 2890: return TRUE; 2891: } 2892: } 2893: 1.1.1.4 root 2894: if (!GetMountList (FALSE)) 1.1 root 2895: return FALSE; 2896: 2897: for (i = 0; MountList[i].DeviceNumber != -1; i++) 2898: { 2899: MountListEntry *e = &MountList[i]; 2900: if (e->DeviceNumber == -1) 2901: break; 2902: 2903: if (strcmp (text, e->VolumePath) == 0) 2904: { 2905: *deviceNumber = e->DeviceNumber; 2906: return TRUE; 2907: } 2908: } 2909: 2910: error ("%s not mounted\n", text); 2911: return FALSE; 2912: } 2913: 2914: 1.1.1.2 root 2915: int main (int argc, char **argv) 1.1 root 2916: { 2917: char *volumePath = NULL; 2918: char *mountPoint = NULL; 1.1.1.4 root 2919: char volumePathBuf[TC_MAX_PATH]; 1.1 root 2920: int i, o; 2921: int optIndex = 0; 1.1.1.2 root 2922: FILE *f; 1.1 root 2923: 2924: struct option longOptions[] = { 1.1.1.3 root 2925: {"backup-headers", required_argument, 0, 0}, 2926: {"cluster", required_argument, 0, 0}, 2927: {"change", optional_argument, 0, 'C'}, 2928: {"create", optional_argument, 0, 'c'}, 2929: {"device-number", required_argument, 0, 'N'}, 1.1 root 2930: {"dismount", optional_argument, 0, 'd'}, 1.1.1.3 root 2931: {"disable-progress", 0, 0, 0}, 2932: {"display-keys", 0, 0, 0}, 1.1 root 2933: {"display-password", 0, 0, 0}, 1.1.1.3 root 2934: {"encryption", required_argument, 0, 0}, 1.1 root 2935: {"keyfile", required_argument, 0, 'k'}, 1.1.1.3 root 2936: {"keyfile-add", required_argument, 0, 0}, 1.1 root 2937: {"keyfile-protected", required_argument, 0, 'K'}, 2938: {"filesystem", required_argument, 0, 0}, 1.1.1.4 root 2939: {"interactive", 0, 0, 'i'}, 1.1.1.3 root 2940: {"keyfile-create", required_argument, 0, 0}, 2941: {"list", optional_argument, 0, 'l'}, 2942: {"hash", required_argument, 0, 0}, 1.1 root 2943: {"help", 0, 0, 'h'}, 1.1.1.3 root 2944: {"mount-options", required_argument, 0, 'M'}, 1.1.1.4 root 2945: {"overwrite", 0, 0, 0}, 1.1.1.5 ! root 2946: {"password", required_argument, 0, 'p'}, 1.1 root 2947: {"password-tries", required_argument, 0, 0}, 1.1.1.3 root 2948: {"properties", optional_argument, 0, 0}, 1.1 root 2949: {"protect-hidden", 0, 0, 'P'}, 1.1.1.3 root 2950: {"quick", 0, 0, 0}, 1.1.1.4 root 2951: {"random-source", required_argument, 0, 0}, 1.1 root 2952: {"read-only", 0, 0, 'r'}, 1.1.1.3 root 2953: {"restore-header", required_argument, 0, 0}, 2954: {"size", required_argument, 0, 0}, 1.1 root 2955: {"test", 0, 0, 0}, 1.1.1.3 root 2956: {"type", required_argument, 0, 0}, 1.1 root 2957: {"update-time", 0, 0, 0}, 1.1.1.3 root 2958: {"user-mount", 0, 0, 'u'}, 1.1 root 2959: {"verbose", 0, 0, 'v'}, 2960: {"version", 0, 0, 'V'}, 2961: {0, 0, 0, 0} 2962: }; 2963: 1.1.1.2 root 2964: // Make sure pipes will not use file descriptors <= STDERR_FILENO 2965: f = fdopen (STDIN_FILENO, "r"); 2966: if (f == NULL) 2967: open ("/dev/null", 0); 2968: 2969: f = fdopen (STDOUT_FILENO, "w"); 2970: if (f == NULL) 2971: open ("/dev/null", 0); 2972: 2973: f = fdopen (STDERR_FILENO, "w"); 2974: if (f == NULL) 2975: open ("/dev/null", 0); 1.1 root 2976: 2977: signal (SIGHUP, OnSignal); 2978: signal (SIGINT, OnSignal); 2979: signal (SIGQUIT, OnSignal); 2980: signal (SIGABRT, OnSignal); 2981: signal (SIGPIPE, OnSignal); 2982: signal (SIGTERM, OnSignal); 2983: 1.1.1.3 root 2984: LockMemory (); 1.1 root 2985: atexit (OnExit); 2986: 1.1.1.3 root 2987: RealUserId = getuid (); 2988: RealGroupId = getgid (); 2989: 2990: if (tcgetattr (0, &TerminalAttributes) == 0) 2991: IsTerminal = TRUE; 2992: 1.1.1.4 root 2993: while ((o = getopt_long (argc, argv, "c::C::d::hik:K:l::M:N:p:PruvV", longOptions, &optIndex)) != -1) 1.1 root 2994: { 2995: switch (o) 2996: { 1.1.1.3 root 2997: case 'c': 2998: { 2999: char *hostPath = NULL; 3000: if (optind < argc) 3001: { 3002: hostPath = argv[optind++]; 3003: 3004: if (optind < argc) 3005: goto usage; 3006: } 3007: 3008: return CreateVolume (hostPath) ? 0 : 1; 3009: } 3010: 3011: case 'C': 3012: { 3013: char *hostPath = NULL; 3014: if (optind < argc) 3015: { 3016: hostPath = argv[optind++]; 3017: 3018: if (optind < argc) 3019: goto usage; 3020: } 3021: 3022: return ChangePassword (hostPath) ? 0 : 1; 3023: } 3024: 1.1 root 3025: case 'd': 3026: // Dismount 3027: { 3028: int devNo; 3029: 3030: if (optind < argc) 3031: { 3032: if (!ToDeviceNumber (argv[optind++], &devNo)) 3033: return 1; 3034: 3035: if (optind < argc) 3036: goto usage; 3037: } 3038: else 3039: devNo = -1; 3040: 1.1.1.2 root 3041: if (!CheckAdminPrivileges ()) 3042: return 1; 3043: 1.1 root 3044: return DismountVolume (devNo) ? 0 : 1; 3045: } 3046: 1.1.1.4 root 3047: case 'i': 3048: Interactive = TRUE; 3049: if (optind < argc) 3050: goto usage; 3051: break; 3052: 1.1 root 3053: case 'l': 3054: // List 3055: { 3056: int devNo; 3057: 3058: if (optind < argc) 3059: { 3060: if (!ToDeviceNumber (argv[optind++], &devNo)) 3061: return 1; 3062: 3063: if (optind < argc) 3064: goto usage; 3065: } 3066: else 3067: devNo = -1; 3068: 1.1.1.2 root 3069: if (!CheckAdminPrivileges ()) 3070: return 1; 3071: 1.1 root 3072: return DumpMountList (devNo) ? 0 : 1; 3073: } 3074: 3075: case 'k': 3076: case 'K': 3077: // Keyfile 1.1.1.4 root 3078: if (optarg[0] == 0) 3079: { 3080: NoKeyFiles = TRUE; 3081: } 3082: else 1.1 root 3083: { 3084: KeyFile *kf = malloc (sizeof (KeyFile)); 3085: if (!kf) 3086: { 3087: perror ("malloc"); 3088: return 1; 3089: } 3090: strncpy (kf->FileName, optarg, sizeof (kf->FileName)); 3091: if (o == 'k') 3092: FirstKeyFile = KeyFileAdd (FirstKeyFile, kf); 3093: else 3094: FirstProtVolKeyFile = KeyFileAdd (FirstProtVolKeyFile, kf); 3095: } 3096: break; 3097: 1.1.1.3 root 3098: case 'M': 1.1.1.5 ! root 3099: if (RealUserId != 0) ! 3100: { ! 3101: error ("--mount-options can be specified only by an administrator (see options -r, -u)\n"); ! 3102: return 1; ! 3103: } ! 3104: 1.1.1.3 root 3105: MountOpts = optarg; 3106: break; 3107: 3108: case 'N': 3109: if (sscanf (optarg, "%d", &UseDeviceNumber) == 1 && UseDeviceNumber >= 0) 3110: break; 3111: goto usage; 1.1 root 3112: 3113: case 'p': 3114: // Password 3115: if (!CmdPasswordValid) 3116: { 1.1.1.3 root 3117: strncpy ((char *)CmdPassword.Text, optarg, sizeof (CmdPassword.Text)); 3118: CmdPassword.Length = strlen ((char *)CmdPassword.Text); 1.1.1.5 ! root 3119: ! 3120: if (!ValidatePassword (&CmdPassword)) ! 3121: return 1; 1.1.1.4 root 3122: 1.1 root 3123: CmdPasswordValid = TRUE; 3124: } 3125: else if (!CmdPassword2Valid) 3126: { 1.1.1.3 root 3127: strncpy ((char *)CmdPassword2.Text, optarg, sizeof (CmdPassword2.Text)); 1.1.1.4 root 3128: 1.1.1.3 root 3129: CmdPassword2.Length = strlen ((char *)CmdPassword2.Text); 1.1.1.5 ! root 3130: if (!ValidatePassword (&CmdPassword2)) ! 3131: return 1; 1.1.1.4 root 3132: 1.1 root 3133: CmdPassword2Valid = TRUE; 3134: } 3135: break; 3136: 3137: case 'P': 3138: // Hidden volume protection 3139: ProtectHidden = TRUE; 3140: break; 3141: 3142: case 'r': 3143: ReadOnly = TRUE; 3144: break; 1.1.1.3 root 3145: 3146: case 'u': 3147: UserMount = TRUE; 3148: break; 1.1 root 3149: 3150: case 'v': 3151: // Verbose 3152: Verbose++; 3153: break; 3154: 3155: case 'V': 3156: DumpVersion (stdout); 3157: return 0; 3158: 3159: case 'h': 3160: // Help 3161: DumpHelp (); 3162: return 0; 3163: 3164: case 0: 1.1.1.3 root 3165: if (strcmp ("backup-headers", longOptions[optIndex].name) == 0) 3166: { 3167: char *volumePath = NULL; 3168: 3169: if (optind < argc) 3170: volumePath = argv[optind++]; 3171: 3172: if (optind < argc) 3173: goto usage; 3174: 3175: if (BackupVolumeHeaders (optarg, volumePath)) 3176: { 3177: printf ("Backup of volume headers succeeded.\n"); 3178: return 0; 3179: } 3180: 3181: return 1; 3182: } 3183: 3184: if (strcmp ("cluster", longOptions[optIndex].name) == 0) 3185: { 3186: if (sscanf (optarg, "%d", &ClusterSize) != 1) 3187: goto usage; 3188: break; 3189: } 3190: 3191: if (strcmp ("display-keys", longOptions[optIndex].name) == 0) 3192: { 3193: DisplayKeys = TRUE; 3194: break; 3195: } 3196: 1.1 root 3197: if (strcmp ("display-password", longOptions[optIndex].name) == 0) 3198: { 3199: DisplayPassword = TRUE; 3200: break; 3201: } 3202: 1.1.1.3 root 3203: if (strcmp ("disable-progress", longOptions[optIndex].name) == 0) 1.1 root 3204: { 1.1.1.3 root 3205: DisplayProgress = FALSE; 3206: break; 3207: } 3208: 3209: if (strcmp ("encryption", longOptions[optIndex].name) == 0) 3210: { 3211: EA = EAGetByName (optarg); 3212: 3213: if (EA == 0) 1.1 root 3214: goto usage; 1.1.1.3 root 3215: break; 1.1 root 3216: } 3217: 3218: if (strcmp ("filesystem", longOptions[optIndex].name) == 0) 3219: { 3220: Filesystem = optarg; 3221: break; 3222: } 3223: 1.1.1.3 root 3224: if (strcmp ("hash", longOptions[optIndex].name) == 0) 3225: { 3226: HashAlgorithm = 0; 3227: for (i = 1; i <= LAST_PRF_ID; i++) 3228: { 3229: if (strcasecmp (optarg, HashGetName (i)) == 0) 3230: { 3231: HashAlgorithm = i; 3232: break; 3233: } 3234: } 3235: 3236: if (HashAlgorithm == 0) 3237: goto usage; 3238: 3239: break; 3240: } 3241: 3242: if (strcmp ("keyfile-add", longOptions[optIndex].name) == 0) 3243: { 1.1.1.4 root 3244: if (optarg[0] == 0) 1.1.1.3 root 3245: { 1.1.1.4 root 3246: NoNewKeyFiles = TRUE; 3247: } 3248: else 3249: { 3250: KeyFile *kf = malloc (sizeof (KeyFile)); 3251: if (!kf) 3252: { 3253: perror ("malloc"); 3254: return 1; 3255: } 3256: strncpy (kf->FileName, optarg, sizeof (kf->FileName)); 3257: FirstNewKeyFile = KeyFileAdd (FirstNewKeyFile, kf); 1.1.1.3 root 3258: } 3259: break; 3260: } 3261: 3262: if (strcmp ("keyfile-create", longOptions[optIndex].name) == 0) 3263: { 3264: return CreateKeyfile (optarg) ? 0 : 1; 3265: } 3266: 1.1.1.4 root 3267: if (strcmp ("overwrite", longOptions[optIndex].name) == 0) 3268: { 3269: Overwrite = TRUE; 3270: break; 3271: } 3272: 1.1.1.3 root 3273: if (strcmp ("quick", longOptions[optIndex].name) == 0) 3274: { 3275: Quick = TRUE; 3276: break; 3277: } 3278: 3279: if (strcmp ("type", longOptions[optIndex].name) == 0) 1.1 root 3280: { 1.1.1.3 root 3281: if (strcasecmp (optarg, "normal") == 0) 3282: VolumeType = VOLUME_TYPE_NORMAL; 3283: else if (strcasecmp (optarg, "hidden") == 0) 3284: VolumeType = VOLUME_TYPE_HIDDEN; 3285: else 3286: goto usage; 3287: 1.1 root 3288: break; 3289: } 3290: 3291: if (strcmp ("password-tries", longOptions[optIndex].name) == 0) 3292: { 3293: if (sscanf (optarg, "%d", &PasswordEntryTries) == 1) 3294: break; 3295: else 3296: goto usage; 3297: } 1.1.1.3 root 3298: 3299: if (strcmp ("properties", longOptions[optIndex].name) == 0) 3300: { 3301: char *volumePath = NULL; 3302: 3303: if (optind < argc) 3304: volumePath = argv[optind++]; 3305: 3306: if (optind < argc) 3307: goto usage; 3308: 3309: return DumpVolumeProperties (volumePath) ? 0 : 1; 3310: } 1.1.1.4 root 3311: 3312: if (strcmp ("random-source", longOptions[optIndex].name) == 0) 3313: { 3314: RandomSource = optarg; 3315: break; 3316: } 1.1.1.3 root 3317: 3318: if (strcmp ("restore-header", longOptions[optIndex].name) == 0) 3319: { 3320: char *volumePath = NULL; 3321: 3322: if (optind < argc) 3323: volumePath = argv[optind++]; 3324: 3325: if (optind < argc) 3326: goto usage; 3327: 3328: if (RestoreVolumeHeader (optarg, volumePath)) 3329: { 3330: printf ("Restore of volume header succeeded.\n"); 3331: return 0; 3332: } 3333: 3334: return 1; 3335: } 3336: 3337: if (strcmp ("size", longOptions[optIndex].name) == 0) 3338: { 3339: if (!ParseSize (optarg, &VolumeSize)) 3340: goto usage; 3341: break; 3342: } 3343: 1.1 root 3344: if (strcmp ("test", longOptions[optIndex].name) == 0) 3345: { 3346: if (AutoTestAlgorithms ()) 3347: { 3348: printf ("Self-tests of all algorithms passed.\n"); 3349: return 0; 3350: } 3351: 3352: printf ("Self-tests of algorithms FAILED!\n"); 3353: return 1; 3354: } 3355: 3356: if (strcmp ("update-time", longOptions[optIndex].name) == 0) 3357: { 3358: UpdateTime = TRUE; 3359: break; 3360: } 3361: goto usage; 3362: 3363: default: 3364: goto usage; 3365: } 3366: } 3367: 1.1.1.4 root 3368: if (!Interactive) 3369: { 3370: if (optind >= argc) 3371: goto usage; 1.1 root 3372: 1.1.1.4 root 3373: if (optind < argc) 3374: volumePath = argv[optind++]; 1.1 root 3375: 1.1.1.4 root 3376: if (optind < argc) 3377: mountPoint = argv[optind++]; 1.1 root 3378: 1.1.1.4 root 3379: if (optind < argc) 3380: goto usage; 3381: } 1.1 root 3382: 1.1.1.2 root 3383: if (!CheckAdminPrivileges ()) 3384: return 1; 3385: 1.1.1.4 root 3386: if (Interactive) 3387: { 3388: static char mp[TC_MAX_PATH] = { 0 }; 3389: 3390: // Volume path 3391: volumePath = AskVolumePath (volumePath, "Enter volume path"); 3392: 3393: // Mount point 1.1.1.5 ! root 3394: mountPoint = AskString ("Enter mount directory [none]", mp, sizeof (mp)); 1.1.1.4 root 3395: if (mp[0] == 0) 3396: mountPoint = NULL; 3397: 3398: ProtectHidden = AskYesNo ("Protect hidden volume?", TRUE); 3399: 3400: AskKeyFiles ("Enter keyfile path", &FirstKeyFile); 3401: 3402: if (ProtectHidden) 3403: AskKeyFiles ("Enter keyfile path for hidden volume", &FirstProtVolKeyFile); 3404: } 3405: 1.1 root 3406: // Relative path => absolute 3407: if (volumePath[0] != '/') 3408: { 1.1.1.4 root 3409: char s[TC_MAX_PATH]; 1.1 root 3410: getcwd (s, sizeof (s)); 3411: snprintf (volumePathBuf, sizeof (volumePathBuf), "%s/%s", s, volumePath); 3412: volumePath = volumePathBuf; 3413: } 3414: 3415: return MountVolume (volumePath, mountPoint) == FALSE; 3416: 3417: usage: 1.1.1.3 root 3418: DumpUsage (stdout); 1.1 root 3419: 3420: return 1; 3421: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.