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