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