|
|
1.1 ! root 1: /* ! 2: Copyright (c) 2004-2005 TrueCrypt Foundation. All rights reserved. ! 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: //FIXME remove stale dmsetup device ! 9: #define _LARGEFILE_SOURCE 1 ! 10: #define _FILE_OFFSET_BITS 64 ! 11: ! 12: #include <getopt.h> ! 13: #include <inttypes.h> ! 14: #include <stdarg.h> ! 15: #include <stdio.h> ! 16: #include <stdlib.h> ! 17: #include <sys/mman.h> ! 18: #include <sys/stat.h> ! 19: #include <sys/types.h> ! 20: #include <sys/wait.h> ! 21: #include <termios.h> ! 22: #include <time.h> ! 23: #include <unistd.h> ! 24: #include <utime.h> ! 25: ! 26: #include "Tcdefs.h" ! 27: #include "Keyfiles.h" ! 28: #include "Volumes.h" ! 29: #include "Tests.h" ! 30: #include "Dm-target.h" ! 31: ! 32: #define MAX_VOLUMES 256 ! 33: #define MAX_MINOR 256 ! 34: ! 35: #undef MAX_PATH ! 36: #define MAX_PATH 260 ! 37: #define MAX_PATH_STR "259" ! 38: ! 39: #define TC_MAP_DEV "/dev/mapper/truecrypt" ! 40: #define LOOP_DEV "/dev/loop" ! 41: ! 42: #define error(fmt, args...) fprintf (stderr, "truecrypt: " fmt, ## args) ! 43: ! 44: typedef struct ! 45: { ! 46: int DeviceNumber; ! 47: int DeviceMajor; ! 48: int DeviceMinor; ! 49: uint64_t VolumeSize; ! 50: char VolumePath[MAX_PATH]; ! 51: int EA; ! 52: BOOL Hidden; ! 53: uint64_t ReadOnlyStart; ! 54: uint64_t ReadOnlyEnd; ! 55: uint64_t ModTime; ! 56: uint64_t AcTime; ! 57: int Flags; ! 58: } MountListEntry; ! 59: ! 60: static MountListEntry MountList[MAX_VOLUMES]; ! 61: static BOOL MountListValid = FALSE; ! 62: ! 63: static BOOL DisplayPassword = FALSE; ! 64: static char *Filesystem = NULL; ! 65: static char *MountOpts = NULL; ! 66: static int PasswordEntryTries = 3; ! 67: static Password CmdPassword; ! 68: static Password CmdPassword2; ! 69: static BOOL CmdPasswordValid = FALSE; ! 70: ! 71: static BOOL CmdPassword2Valid = FALSE; ! 72: static int UseDeviceNumber = -1; ! 73: static BOOL ProtectHidden = FALSE; ! 74: static BOOL ReadOnly = FALSE; ! 75: static BOOL UpdateTime = FALSE; ! 76: static int Verbose = 0; ! 77: ! 78: static BOOL IsTerminal = FALSE; ! 79: static struct termios TerminalAttributes; ! 80: static Password password; ! 81: static KeyFile *FirstKeyFile; ! 82: static KeyFile *FirstProtVolKeyFile; ! 83: ! 84: ! 85: static void SecurityCleanup () ! 86: { ! 87: burn (&password, sizeof (password)); ! 88: burn (&CmdPassword, sizeof (CmdPassword)); ! 89: burn (&CmdPassword2, sizeof (CmdPassword2)); ! 90: } ! 91: ! 92: ! 93: static void OnSignal (int signal) ! 94: { ! 95: SecurityCleanup (); ! 96: ! 97: if (IsTerminal) ! 98: { ! 99: tcsetattr (0, TCSANOW, &TerminalAttributes); ! 100: puts (""); ! 101: } ! 102: ! 103: _exit (1); ! 104: } ! 105: ! 106: ! 107: static void OnExit () ! 108: { ! 109: SecurityCleanup (); ! 110: } ! 111: ! 112: ! 113: static BOOL WaitChild (BOOL quiet, char *execName) ! 114: { ! 115: int status; ! 116: if (wait (&status) == -1) ! 117: { ! 118: perror ("wait"); ! 119: return FALSE; ! 120: } ! 121: ! 122: if (!WIFEXITED (status) ! 123: || (WIFEXITED (status) && WEXITSTATUS (status))) ! 124: { ! 125: if (!quiet && Verbose >= 3) ! 126: error ("Error: %s returned %d\n", execName, WEXITSTATUS (status)); ! 127: return FALSE; ! 128: } ! 129: ! 130: return TRUE; ! 131: } ! 132: ! 133: ! 134: BOOL Execute (BOOL quiet, char *execName, ...) ! 135: { ! 136: int pid; ! 137: va_list vl; ! 138: va_start (vl, execName); ! 139: ! 140: pid = fork (); ! 141: if (pid == -1) ! 142: { ! 143: perror ("fork"); ! 144: goto err; ! 145: } ! 146: else if (pid == 0) ! 147: { ! 148: char *args[32]; ! 149: int i = 1; ! 150: ! 151: SecurityCleanup (); ! 152: ! 153: if (Verbose >= 3) ! 154: printf ("Executing %s", execName); ! 155: ! 156: args[0] = execName; ! 157: while (i < 32 && (args[i] = (va_arg (vl, char *)))) ! 158: { ! 159: if (Verbose >= 3) ! 160: printf (" %s", args[i]); ! 161: i++; ! 162: } ! 163: ! 164: if (Verbose >= 3) ! 165: puts (""); ! 166: ! 167: if (quiet) ! 168: { ! 169: // >/dev/null is safer than >&- ! 170: int i = open ("/dev/null", 0); ! 171: if (i == -1) ! 172: { ! 173: perror ("open /dev/null"); ! 174: _exit (1); ! 175: } ! 176: ! 177: dup2 (i, STDOUT_FILENO); ! 178: dup2 (i, STDERR_FILENO); ! 179: } ! 180: ! 181: execvp (execName, args); ! 182: ! 183: fprintf (stderr, "%s ", execName); ! 184: perror ("execlp"); ! 185: _exit (1); ! 186: } ! 187: ! 188: if (!WaitChild (quiet, execName)) ! 189: goto err; ! 190: ! 191: va_end (vl); ! 192: return TRUE; ! 193: err: ! 194: va_end (vl); ! 195: return FALSE; ! 196: } ! 197: ! 198: ! 199: static BOOL IsFile (char *path) ! 200: { ! 201: struct stat st; ! 202: if (stat (path, &st) != 0) ! 203: return FALSE; ! 204: ! 205: return S_ISREG (st.st_mode); ! 206: } ! 207: ! 208: ! 209: static BOOL IsBlockDevice (char *path) ! 210: { ! 211: struct stat st; ! 212: if (stat (path, &st) != 0) ! 213: return FALSE; ! 214: ! 215: return S_ISBLK (st.st_mode); ! 216: } ! 217: ! 218: ! 219: static BOOL RestoreFileTime (char *path, time_t modTime, time_t acTime) ! 220: { ! 221: struct utimbuf t; ! 222: ! 223: t.actime = acTime; ! 224: t.modtime = modTime; ! 225: ! 226: return utime (path, &t) != 0; ! 227: } ! 228: ! 229: ! 230: static BOOL LoadKernelModule () ! 231: { ! 232: char s[2048]; ! 233: FILE *m; ! 234: ! 235: m = fopen ("/proc/modules", "r"); ! 236: if (m == NULL) ! 237: { ! 238: perror ("fopen /proc/modules"); ! 239: return FALSE; ! 240: } ! 241: ! 242: while (fgets (s, sizeof (s), m)) ! 243: { ! 244: if (strstr (s, "truecrypt ") == s) ! 245: { ! 246: fclose (m); ! 247: return TRUE; ! 248: } ! 249: } ! 250: ! 251: fclose (m); ! 252: ! 253: if (!Execute (FALSE, "modprobe", "truecrypt", NULL)) ! 254: { ! 255: error ("Failed to load TrueCrypt kernel module\n"); ! 256: return FALSE; ! 257: } ! 258: return TRUE; ! 259: } ! 260: ! 261: ! 262: static BOOL UnloadKernelModule (BOOL quiet) ! 263: { ! 264: // rmmod is used instead of modprobe to prevent unload of dependencies ! 265: return Execute (quiet, "rmmod", "truecrypt", NULL); ! 266: } ! 267: ! 268: ! 269: static BOOL CheckKernelModuleVersion (BOOL wait) ! 270: { ! 271: FILE *p; ! 272: int pfd[2]; ! 273: int pid, res; ! 274: int i, dummy; ! 275: char s[2048]; ! 276: int ver1 = 0, ver2 = 0, ver3 = 0; ! 277: int tries = 10; ! 278: ! 279: do ! 280: { ! 281: pipe (pfd); ! 282: pid = fork (); ! 283: ! 284: if (pid == -1) ! 285: { ! 286: perror ("fork"); ! 287: return FALSE; ! 288: } ! 289: else if (pid == 0) ! 290: { ! 291: SecurityCleanup (); ! 292: ! 293: dup2 (pfd[1], STDOUT_FILENO); ! 294: close (pfd[0]); ! 295: close (STDERR_FILENO); ! 296: ! 297: execlp ("dmsetup", "dmsetup", "targets", NULL); ! 298: ! 299: perror ("execlp dmsetup"); ! 300: _exit (1); ! 301: } ! 302: ! 303: close (pfd[1]); ! 304: p = fdopen (pfd[0], "r"); ! 305: if (p == NULL) ! 306: { ! 307: perror ("fdopen"); ! 308: return FALSE; ! 309: } ! 310: ! 311: while (fgets (s, sizeof (s), p)) ! 312: { ! 313: char name[32]; ! 314: ! 315: if (sscanf (s, "%31s v%d.%d.%d", &name, &ver1, &ver2, &ver3) == 4 ! 316: && strcmp (name, "truecrypt") == 0) ! 317: { ! 318: fclose (p); ! 319: WaitChild (FALSE, "dmsetup"); ! 320: ! 321: if (ver1 == VERSION_NUM1 && ver2 == VERSION_NUM2 && ver3 == VERSION_NUM3) ! 322: return TRUE; ! 323: ! 324: error ("Incorrect version of kernel module loaded - version %s required\n", VERSION_STRING); ! 325: UnloadKernelModule (TRUE); ! 326: return FALSE; ! 327: } ! 328: } ! 329: ! 330: fclose (p); ! 331: WaitChild (FALSE, "dmsetup"); ! 332: ! 333: // Target registration may take some time ! 334: if (wait) ! 335: usleep (100 * 1000); ! 336: else ! 337: break; ! 338: ! 339: } while (tries--); ! 340: ! 341: error ("Kernel module not loaded\n"); ! 342: return FALSE; ! 343: } ! 344: ! 345: ! 346: static BOOL GetMountList () ! 347: { ! 348: FILE *p; ! 349: int pfd[2]; ! 350: int pid, res; ! 351: int i, dummy; ! 352: ! 353: if (MountListValid) ! 354: return TRUE; ! 355: ! 356: MountList[0].DeviceNumber = -1; ! 357: ! 358: pipe (pfd); ! 359: pid = fork (); ! 360: ! 361: if (pid == -1) ! 362: { ! 363: perror ("fork"); ! 364: goto err; ! 365: } ! 366: else if (pid == 0) ! 367: { ! 368: SecurityCleanup (); ! 369: ! 370: dup2 (pfd[1], STDOUT_FILENO); ! 371: close (pfd[0]); ! 372: close (STDERR_FILENO); ! 373: ! 374: execlp ("dmsetup", "dmsetup", "table", NULL); ! 375: ! 376: perror ("execlp dmsetup"); ! 377: _exit (1); ! 378: } ! 379: ! 380: close (pfd[1]); ! 381: p = fdopen (pfd[0], "r"); ! 382: if (p == NULL) ! 383: { ! 384: perror ("fdopen"); ! 385: goto err; ! 386: } ! 387: ! 388: for (i = 0; i < MAX_VOLUMES; i++) ! 389: { ! 390: char s[2048]; ! 391: MountListEntry *e = &MountList[i]; ! 392: ! 393: if (!fgets (s, sizeof (s), p)) ! 394: break; ! 395: ! 396: if (sscanf (s, "truecrypt%d: 0 %lld truecrypt %d 0 0 %d:%d %lld %lld %lld %lld %lld %d %" MAX_PATH_STR "s\n", ! 397: &e->DeviceNumber, ! 398: &e->VolumeSize, ! 399: &e->EA, ! 400: &e->DeviceMajor, ! 401: &e->DeviceMinor, ! 402: &e->Hidden, ! 403: &e->ReadOnlyStart, ! 404: &e->ReadOnlyEnd, ! 405: &e->ModTime, ! 406: &e->AcTime, ! 407: &e->Flags, ! 408: e->VolumePath) == 12) ! 409: { ! 410: e->Hidden = e->Hidden == 1 ? FALSE : TRUE; ! 411: e->VolumeSize *= SECTOR_SIZE; ! 412: } ! 413: else ! 414: i--; ! 415: } ! 416: ! 417: MountList[i].DeviceNumber = -1; ! 418: ! 419: fclose (p); ! 420: if (!WaitChild (TRUE, "dmsetup")) ! 421: goto err; ! 422: ! 423: MountListValid = TRUE; ! 424: return TRUE; ! 425: ! 426: err: ! 427: MountList[0].DeviceNumber = -1; ! 428: return FALSE; ! 429: } ! 430: ! 431: ! 432: static BOOL IsVolumeMounted (char *volumePath) ! 433: { ! 434: int i; ! 435: if (!GetMountList ()) ! 436: return FALSE; ! 437: ! 438: for (i = 0; MountList[i].DeviceNumber != -1; i++) ! 439: if (strcmp (volumePath, MountList[i].VolumePath) == 0) ! 440: return TRUE; ! 441: ! 442: return FALSE; ! 443: } ! 444: ! 445: ! 446: static int GetFreeMapDevice () ! 447: { ! 448: FILE *p; ! 449: char cmd[128]; ! 450: int n; ! 451: ! 452: if (!GetMountList ()) ! 453: return -1; ! 454: ! 455: for (n = 0; n < MAX_MINOR; n++) ! 456: { ! 457: int j = 0; ! 458: while (MountList[j].DeviceNumber != -1) ! 459: { ! 460: if (MountList[j].DeviceNumber == n) ! 461: break; ! 462: j++; ! 463: } ! 464: ! 465: if (MountList[j].DeviceNumber == -1) ! 466: return n; ! 467: } ! 468: ! 469: return -1; ! 470: } ! 471: ! 472: ! 473: static BOOL DeleteLoopDevice (int loopDeviceNo) ! 474: { ! 475: char dev[32]; ! 476: BOOL r; ! 477: ! 478: sprintf (dev, LOOP_DEV "%d", loopDeviceNo); ! 479: if (!IsBlockDevice (dev)) ! 480: sprintf (dev, LOOP_DEV "/%d", loopDeviceNo); ! 481: ! 482: r = Execute (FALSE, "losetup", "-d", dev, NULL); ! 483: ! 484: if (r && Verbose > 1) ! 485: printf ("Detached %s\n", dev); ! 486: ! 487: return r; ! 488: } ! 489: ! 490: ! 491: static BOOL OpenVolume (char *volumePath, Password *password, PCRYPTO_INFO *cryptoInfo, uint64_t *startSector, uint64_t *totalSectors, time_t *modTime, time_t *acTime) ! 492: { ! 493: char header[SECTOR_SIZE]; ! 494: uint64_t r; ! 495: FILE *f = NULL; ! 496: struct stat volumeStat; ! 497: ! 498: if (stat (volumePath, &volumeStat) != 0) ! 499: { ! 500: perror ("Cannot open volume"); ! 501: volumeStat.st_ctime = 0; ! 502: goto err; ! 503: } ! 504: ! 505: f = fopen (volumePath, "r"); ! 506: if (!f) ! 507: { ! 508: perror ("Cannot open volume"); ! 509: goto err; ! 510: } ! 511: ! 512: // Normal header ! 513: if (fread (header, 1, SECTOR_SIZE, f) != SECTOR_SIZE) ! 514: { ! 515: perror ("Cannot read volume header"); ! 516: goto err; ! 517: } ! 518: ! 519: fseek (f, 0, SEEK_END); ! 520: *totalSectors = ftello (f) / SECTOR_SIZE - 1; ! 521: ! 522: r = VolumeReadHeader (header, password, cryptoInfo); ! 523: ! 524: if (r != 0) ! 525: { ! 526: // Hidden header ! 527: if (fseek (f, -HIDDEN_VOL_HEADER_OFFSET, SEEK_END) == -1 ! 528: || fread (header, 1, SECTOR_SIZE, f) != SECTOR_SIZE) ! 529: { ! 530: perror ("Cannot read volume header"); ! 531: goto err; ! 532: } ! 533: ! 534: r = VolumeReadHeader (header, password, cryptoInfo); ! 535: ! 536: if (r != 0) ! 537: { ! 538: if (IsTerminal) ! 539: puts ("Incorrect password or not a TrueCrypt volume"); ! 540: else ! 541: error ("Incorrect password or not a TrueCrypt volume\n"); ! 542: ! 543: goto err; ! 544: } ! 545: ! 546: *startSector = (ftello (f) ! 547: + SECTOR_SIZE * 2 ! 548: - (*cryptoInfo)->hiddenVolumeSize ! 549: - HIDDEN_VOL_HEADER_OFFSET) / SECTOR_SIZE; ! 550: ! 551: *totalSectors = (*cryptoInfo)->hiddenVolumeSize / SECTOR_SIZE; ! 552: } ! 553: else ! 554: *startSector = 1; ! 555: ! 556: fclose (f); ! 557: ! 558: if (!UpdateTime) ! 559: RestoreFileTime (volumePath, volumeStat.st_mtime, volumeStat.st_atime); ! 560: ! 561: *modTime = volumeStat.st_mtime; ! 562: *acTime = volumeStat.st_atime; ! 563: return TRUE; ! 564: ! 565: err: ! 566: *cryptoInfo = NULL; ! 567: ! 568: if (f) ! 569: fclose (f); ! 570: ! 571: if (volumeStat.st_ctime != 0 && !UpdateTime) ! 572: RestoreFileTime (volumePath, volumeStat.st_mtime, volumeStat.st_atime); ! 573: ! 574: return FALSE; ! 575: } ! 576: ! 577: ! 578: static void GetPassword (char *prompt, char *volumePath, Password *password) ! 579: { ! 580: struct termios noEcho; ! 581: ! 582: if (tcgetattr (0, &TerminalAttributes) == 0) ! 583: { ! 584: IsTerminal = TRUE; ! 585: noEcho = TerminalAttributes; ! 586: ! 587: if (!DisplayPassword) ! 588: { ! 589: noEcho.c_lflag &= ~ECHO; ! 590: if (tcsetattr (0, TCSANOW, &noEcho) != 0) ! 591: error ("Failed to turn terminal echo off\n"); ! 592: } ! 593: ! 594: printf (prompt, volumePath); ! 595: } ! 596: ! 597: if (fgets (password->Text, sizeof (password->Text), stdin)) ! 598: { ! 599: char *newl = strchr (password->Text, '\n'); ! 600: if (newl) newl[0] = 0; ! 601: ! 602: password->Length = strlen (password->Text); ! 603: } ! 604: else ! 605: password->Length = 0; ! 606: ! 607: if (IsTerminal && !DisplayPassword) ! 608: { ! 609: tcsetattr (0, TCSANOW, &TerminalAttributes); ! 610: puts (""); ! 611: } ! 612: } ! 613: ! 614: ! 615: static BOOL MountVolume (char *volumePath, char *mountPoint) ! 616: { ! 617: char hostDevice[MAX_PATH]; ! 618: char mapDevice[MAX_PATH]; ! 619: int loopDevNo = -1; ! 620: PCRYPTO_INFO ci = NULL; ! 621: uint64_t startSector, totalSectors; ! 622: uint64_t readOnlyStartSector = 0, readOnlySectors = 0; ! 623: int pfd[2]; ! 624: int pid, res, devNo; ! 625: time_t modTime, acTime; ! 626: FILE *f, *w; ! 627: int flags; ! 628: int i; ! 629: int tries = PasswordEntryTries; ! 630: ! 631: if (!AutoTestAlgorithms ()) ! 632: { ! 633: error ("Self-tests of algorithms FAILED!\n"); ! 634: return FALSE; ! 635: } ! 636: ! 637: if (IsVolumeMounted (volumePath)) ! 638: { ! 639: error ("Volume already mounted\n"); ! 640: return FALSE; ! 641: } ! 642: ! 643: do ! 644: { ! 645: Password *pw = &password; ! 646: ! 647: if (!CmdPasswordValid) ! 648: GetPassword ("Enter password for '%s': ", volumePath, &password); ! 649: else ! 650: pw = &CmdPassword; ! 651: ! 652: if (FirstKeyFile && !KeyFilesApply (pw, FirstKeyFile, !UpdateTime)) ! 653: { ! 654: error ("Error while processing keyfiles\n"); ! 655: goto err; ! 656: } ! 657: ! 658: if (OpenVolume (volumePath, pw, &ci, &startSector, &totalSectors, &modTime, &acTime)) ! 659: break; ! 660: else ! 661: totalSectors = 0; ! 662: ! 663: } while (!CmdPasswordValid && IsTerminal && --tries > 0); ! 664: ! 665: if (totalSectors == 0) ! 666: goto err; ! 667: ! 668: // Hidden volume protection ! 669: if (ProtectHidden) ! 670: { ! 671: PCRYPTO_INFO ciH = NULL; ! 672: uint64_t startSectorH, totalSectorsH; ! 673: ! 674: tries = PasswordEntryTries; ! 675: do ! 676: { ! 677: Password *pw = &password; ! 678: ! 679: if (!CmdPassword2Valid) ! 680: GetPassword ("Enter hidden volume password: ", "", &password); ! 681: else ! 682: pw = &CmdPassword2; ! 683: ! 684: if (FirstProtVolKeyFile && !KeyFilesApply (pw, FirstProtVolKeyFile, !UpdateTime)) ! 685: { ! 686: error ("Error while processing keyfiles\n"); ! 687: goto err; ! 688: } ! 689: ! 690: if (OpenVolume (volumePath, pw, &ciH, &startSectorH, &totalSectorsH, &modTime, &acTime)) ! 691: { ! 692: readOnlyStartSector = startSectorH; ! 693: readOnlySectors = startSectorH + totalSectorsH; ! 694: break; ! 695: } ! 696: ! 697: } while (!CmdPassword2Valid && IsTerminal && --tries > 0); ! 698: ! 699: if (ciH) ! 700: crypto_close (ciH); ! 701: ! 702: if (readOnlySectors == 0) ! 703: goto err; ! 704: } ! 705: ! 706: // Headers decrypted ! 707: ! 708: // Loopback ! 709: if (IsFile (volumePath)) ! 710: { ! 711: int i; ! 712: ! 713: for (i = 0; i < MAX_MINOR; i++) ! 714: { ! 715: snprintf (hostDevice, sizeof (hostDevice), LOOP_DEV "%d", i); ! 716: ! 717: if (!IsBlockDevice (hostDevice)) ! 718: { ! 719: snprintf (hostDevice, sizeof (hostDevice), LOOP_DEV "/%d", i); ! 720: if (!IsBlockDevice (hostDevice)) ! 721: continue; ! 722: } ! 723: ! 724: if (Execute (TRUE, "losetup", hostDevice, volumePath, NULL)) ! 725: break; ! 726: } ! 727: ! 728: if (i >= MAX_MINOR) ! 729: { ! 730: error ("No free loopback device available for file-hosted volume\n"); ! 731: goto err; ! 732: } ! 733: ! 734: loopDevNo = i; ! 735: ! 736: if (Verbose > 1) ! 737: printf ("Attached %s to %s\n", volumePath, hostDevice); ! 738: ! 739: } ! 740: else ! 741: strncpy (hostDevice, volumePath, sizeof (hostDevice)); ! 742: ! 743: // Load kernel module ! 744: if (!LoadKernelModule ()) ! 745: goto err; ! 746: ! 747: if (!CheckKernelModuleVersion (TRUE)) ! 748: goto err; ! 749: ! 750: // dmsetup ! 751: devNo = UseDeviceNumber == -1 ? GetFreeMapDevice () : UseDeviceNumber; ! 752: if (devNo == -1) ! 753: { ! 754: error ("Maximum number of volumes mounted\n"); ! 755: goto err; ! 756: } ! 757: ! 758: sprintf (mapDevice, "truecrypt%d", devNo); ! 759: ! 760: pipe (pfd); ! 761: pid = fork (); ! 762: ! 763: if (pid == -1) ! 764: { ! 765: perror ("fork"); ! 766: goto err; ! 767: } ! 768: else if (pid == 0) ! 769: { ! 770: SecurityCleanup (); ! 771: ! 772: close (pfd[1]); ! 773: dup2 (pfd[0], STDIN_FILENO); ! 774: ! 775: execlp ("dmsetup", "dmsetup", "create", mapDevice, NULL); ! 776: ! 777: perror ("execlp dmsetup"); ! 778: _exit (1); ! 779: } ! 780: ! 781: close (pfd[0]); ! 782: w = fdopen (pfd[1], "a"); ! 783: if (w == NULL) ! 784: { ! 785: perror ("fdopen"); ! 786: goto err; ! 787: } ! 788: ! 789: fprintf (w, "0 %lld truecrypt %d ", totalSectors, ci->ea); ! 790: ! 791: for (i = DISK_IV_SIZE; i < EAGetKeySize (ci->ea) + DISK_IV_SIZE; i++) ! 792: fprintf (w, "%02x", ci->master_key[i]); ! 793: ! 794: fprintf (w, " "); ! 795: ! 796: for (i = 0; i < (int)sizeof (ci->iv); i++) ! 797: fprintf (w, "%02x", ci->iv[i]); ! 798: ! 799: flags = 0; ! 800: ! 801: if (ReadOnly) ! 802: flags |= FLAG_READ_ONLY; ! 803: else if (ProtectHidden) ! 804: flags |= FLAG_HIDDEN_VOLUME_PROTECTION; ! 805: ! 806: fprintf (w, " %s %lld %lld %lld %lld %lld %d %s\n", ! 807: hostDevice, ! 808: startSector, ! 809: readOnlyStartSector, ! 810: readOnlySectors, ! 811: (uint64_t) modTime, ! 812: (uint64_t) acTime, ! 813: flags, ! 814: volumePath); ! 815: ! 816: fclose (w); ! 817: ! 818: if (!WaitChild (FALSE, "dmsetup")) ! 819: { ! 820: Execute (TRUE, "dmsetup", "remove", mapDevice, NULL); ! 821: goto err; ! 822: } ! 823: ! 824: sprintf (mapDevice, TC_MAP_DEV "%d", devNo); ! 825: ! 826: if (Verbose >= 1) ! 827: printf ("Mapped %s as %s\n", volumePath, mapDevice); ! 828: ! 829: // Mount ! 830: if (mountPoint) ! 831: { ! 832: char fstype[64], opts[128]; ! 833: ! 834: strcpy (fstype, "-t"); ! 835: if (Filesystem) ! 836: strncat (fstype, Filesystem, sizeof (fstype) - 3); ! 837: else ! 838: strcat (fstype, "auto"); ! 839: ! 840: strcpy (opts, ReadOnly ? "-oro" : "-orw"); ! 841: if (MountOpts) ! 842: { ! 843: strcat (opts, ","); ! 844: strncat (opts, MountOpts, sizeof (opts) - 6); ! 845: } ! 846: ! 847: if (!Execute (FALSE, "mount", fstype, opts, mapDevice, mountPoint, NULL)) ! 848: { ! 849: error ("Mount failed\n"); ! 850: loopDevNo = -1; ! 851: goto err; ! 852: } ! 853: ! 854: if (Verbose >= 1) ! 855: printf ("Mounted %s at %s\n", mapDevice, mountPoint); ! 856: } ! 857: ! 858: crypto_close (ci); ! 859: ! 860: return TRUE; ! 861: ! 862: err: ! 863: if (ci) ! 864: crypto_close (ci); ! 865: ! 866: if (loopDevNo != -1) ! 867: DeleteLoopDevice (loopDevNo); ! 868: ! 869: UnloadKernelModule (TRUE); ! 870: ! 871: return FALSE; ! 872: } ! 873: ! 874: ! 875: static void DumpVersion (FILE *f) ! 876: { ! 877: fprintf (f, ! 878: "truecrypt %s\n\n" ! 879: "Copyright (C) 2004-2005 TrueCrypt Foundation. All Rights Reserved.\n\ ! 880: Copyright (C) 1998-2000 Paul Le Roux. All Rights Reserved.\n\ ! 881: Copyright (C) 2004 TrueCrypt Team. All Rights Reserved.\n\ ! 882: Copyright (C) 1995-1997 Eric Young. All Rights Reserved.\n\ ! 883: Copyright (C) 1999-2004 Dr. Brian Gladman. All Rights Reserved.\n\ ! 884: Copyright (C) 2001 Markus Friedl. All Rights Reserved.\n\n" ! 885: , VERSION_STRING); ! 886: } ! 887: ! 888: ! 889: static void DumpUsage (FILE *f) ! 890: { ! 891: fprintf (f, ! 892: "Usage: truecrypt [OPTIONS] VOLUME_PATH [MOUNT_DIRECTORY]\n" ! 893: " or: truecrypt [OPTIONS] -d | --dismount | -l | --list [MAPPED_VOLUME]\n" ! 894: " or: truecrypt -h | --help | --test | -V | --version\n" ! 895: "\nCommands:\n" ! 896: " VOLUME_PATH Map volume\n" ! 897: " VOLUME_PATH MOUNT_DIRECTORY Map and mount volume\n" ! 898: " -d, --dismount [MAPPED_VOLUME] Dismount and unmap volume\n" ! 899: " -h, --help Display help\n" ! 900: " -l, --list [MAPPED_VOLUME] List mapped volumes\n" ! 901: " --test Test algorithms\n" ! 902: " -V, --version Display version information\n" ! 903: "\nOptions:\n" ! 904: " --device-number NUMBER Map volume as device number\n" ! 905: " --display-password Display password while typing\n" ! 906: " --filesystem TYPE Filesystem type to mount\n" ! 907: " -k, --keyfile FILE|DIR Keyfile for volume\n" ! 908: " -K, --keyfile-protected FILE|DIR Keyfile for protected volume\n" ! 909: " -p, --password PASSWORD Password for volume\n" ! 910: " --password-tries NUMBER Password entry tries\n" ! 911: " -P, --protect-hidden Protect hidden volume\n" ! 912: " --update-time Do not preserve timestamps\n" ! 913: " -r, --read-only Map/Mount read-only\n" ! 914: " --mount-options OPTIONS Mount options\n" ! 915: " -v, --verbose Verbose output\n" ! 916: "\n MAPPED_VOLUME = DEVICE_NUMBER | DEVICE_NAME | MOUNT_POINT | VOLUME_PATH\n" ! 917: "For a detailed help use --help or see truecrypt(1) man page.\n" ! 918: ); ! 919: } ! 920: ! 921: static void DumpHelp () ! 922: { ! 923: fprintf (stdout, ! 924: "Manages encrypted TrueCrypt volumes, which can be mapped as virtual block\n" ! 925: "devices and used as any other standard block device. All data being read\n" ! 926: "from a mapped TrueCrypt volume is transparently decrypted and all data being\n" ! 927: "written to it is transparently encrypted.\n" ! 928: "\n" ! 929: "Usage: truecrypt [OPTIONS] VOLUME_PATH [MOUNT_DIRECTORY]\n" ! 930: " or: truecrypt [OPTIONS] -d | --dismount | -l | --list [MAPPED_VOLUME]\n" ! 931: " or: truecrypt -h | --help | --test | -V | --version\n" ! 932: "\n" ! 933: "Options:\n" ! 934: "\n" ! 935: "VOLUME_PATH [MOUNT_DIRECTORY]\n" ! 936: " Open a TrueCrypt volume specified by VOLUME_PATH and map it as a block device\n" ! 937: " /dev/mapper/truecryptN. N is the first available device number if not\n" ! 938: " otherwise specified with --device-number. The filesystem of the mapped volume\n" ! 939: " is mounted at MOUNT_DIRECTORY if specified.\n" ! 940: "\n" ! 941: "-d, --dismount [MAPPED_VOLUME]\n" ! 942: " Dismount and unmap mapped volumes. If MAPPED_VOLUME is not specified, all\n" ! 943: " volumes are dismounted and unmapped. See below for a description of\n" ! 944: " MAPPED_VOLUME.\n" ! 945: "\n" ! 946: "-l, --list [MAPPED_VOLUME]\n" ! 947: " Display a list of mapped volumes. If MAPPED_VOLUME is not specified, all\n" ! 948: " volumes are listed. By default, the list contains only volume path and mapped\n" ! 949: " device name pairs. A more detailed list can be enabled by verbose output\n" ! 950: " option (-v). See below for a description of MAPPED_VOLUME.\n" ! 951: "\n" ! 952: "MAPPED_VOLUME\n" ! 953: " Specifies a mapped or mounted volume. One of the following forms can be used:\n\n" ! 954: " 1) Path to the encrypted TrueCrypt volume.\n\n" ! 955: " 2) Mount directory of the volume's filesystem (if mounted).\n\n" ! 956: " 3) Device number of the mapped volume.\n\n" ! 957: " 4) Device name of the mapped volume.\n\n" ! 958: "\n" ! 959: "--device-number N\n" ! 960: " Use device number N when mapping a volume as a block device\n" ! 961: " /dev/mapper/truecryptN. Default is the first available device.\n" ! 962: "\n" ! 963: "--display-password\n" ! 964: " Display password characters while typing.\n" ! 965: "\n" ! 966: "--filesystem TYPE\n" ! 967: " Filesystem type to mount. The TYPE argument is passed to mount(8) command\n" ! 968: " with option -t. Default type is 'auto'.\n" ! 969: "\n" ! 970: "-h, --help\n" ! 971: " Display help information.\n" ! 972: "\n" ! 973: "-k, --keyfile FILE | DIRECTORY\n" ! 974: " Use specified keyfile to open a volume to be mapped. When a directory is\n" ! 975: " specified, all files inside it will be used (non-recursively). Additional\n" ! 976: " keyfiles can be specified with multiple -k options. See also option -K.\n" ! 977: "\n" ! 978: "-K, --keyfile-protected FILE | DIRECTORY\n" ! 979: " Use specified keyfile to open a hidden volume to be protected. See also\n" ! 980: " options -k and -P.\n" ! 981: "\n" ! 982: "--mount-options OPTIONS\n" ! 983: " Filesystem mount options. The OPTIONS argument is passed to mount(8)\n" ! 984: " command with option -o.\n" ! 985: " \n" ! 986: "-p, --password PASSWORD\n" ! 987: " Use specified password to open a volume. Additional passwords can be\n" ! 988: " specified with multiple -p options. An empty password can also be specified\n" ! 989: " (\"\" in most shells). Note that passing a password on the command line is\n" ! 990: " potentially insecure as the password may be visible in the process list\n" ! 991: " (see ps(1)) and/or stored in a command history file. \n" ! 992: " \n" ! 993: "--password-tries NUMBER\n" ! 994: " Prompt NUMBER of times for a password until the correct password is entered.\n" ! 995: " Default is to prompt three times.\n" ! 996: "\n" ! 997: "-P, --protect-hidden\n" ! 998: " Write-protect a hidden volume when mapping an outer volume. Before mapping the\n" ! 999: " outer volume, the user will be prompted for a password to open the hidden\n" ! 1000: " volume. The size and position of the hidden volume is then determined and the\n" ! 1001: " outer volume is mounted with all sectors belonging to the hidden volume\n" ! 1002: " protected against write operations. When a write to the protected area is\n" ! 1003: " prevented, the whole volume is switched to read-only mode. Verbose list command\n" ! 1004: " (-vl) can be used to query the state of the hidden volume protection. Warning\n" ! 1005: " message is displayed when a volume switched to read-only is being dismounted.\n" ! 1006: " See also option -r.\n" ! 1007: " \n" ! 1008: "-r, --read-only\n" ! 1009: " Map and/or mount a volume as read-only. Write operations to the volume may not\n" ! 1010: " fail immediately due to the write buffering performed by the system, but the\n" ! 1011: " physical write will still be prevented.\n" ! 1012: " \n" ! 1013: "--test\n" ! 1014: " Test all internal algorithms used in the process of encryption and decryption.\n" ! 1015: "\n" ! 1016: "--update-time\n" ! 1017: " Do not preserve access and modification timestamps of volume containers and\n" ! 1018: " access timestamps of keyfiles. By default, timestamps are restored after\n" ! 1019: " a volume is unmapped or after a keyfile is closed.\n" ! 1020: "\n" ! 1021: "-v, --verbose\n" ! 1022: " Enable verbose output. Multiple -v options can be specified to increase the\n" ! 1023: " level of verbosity.\n" ! 1024: "\n" ! 1025: "-V, --version\n" ! 1026: " Display version information.\n" ! 1027: "\n" ! 1028: "Examples:\n" ! 1029: "\n" ! 1030: "truecrypt /root/volume.tc /mnt/tc\n" ! 1031: " Map a volume /root/volume.tc and mount its filesystem at /mnt/tc.\n" ! 1032: "\n" ! 1033: "truecrypt -d\n" ! 1034: " Dismount and unmap all mapped volumes.\n" ! 1035: " \n" ! 1036: "truecrypt -d /root/volume.tc\n" ! 1037: " Dismount and unmap a volume /root/volume.tc.\n" ! 1038: "\n" ! 1039: "truecrypt -d /mnt/tc\n" ! 1040: " Dismount and unmap a volume mounted at /mnt/tc.\n" ! 1041: "\n" ! 1042: "truecrypt -vl\n" ! 1043: " Display a detailed list of all mapped volumes.\n" ! 1044: " \n" ! 1045: "truecrypt --device-number=1 /dev/hdc1 && mkfs /dev/mapper/truecrypt1\n" ! 1046: " Map a volume /dev/hdc1 and create a new filesystem on it.\n" ! 1047: "\n" ! 1048: "truecrypt -P /dev/hdc1 /mnt/tc\n" ! 1049: " Map and mount outer volume /dev/hdc1 and protect hidden volume within it.\n" ! 1050: "\n" ! 1051: "truecrypt -p \"\" -p \"\" -k key1 -k key2 -K key_hidden -P volume.tc\n" ! 1052: " Map outer volume ./volume.tc and protect hidden volume within it.\n" ! 1053: " The outer volume is opened with keyfiles ./key1 and ./key2 and the\n" ! 1054: " hidden volume with ./key_hidden. Passwords for both volumes are empty.\n" ! 1055: "\n" ! 1056: "Report bugs at <http://www.truecrypt.org/bugs>.\n" ! 1057: ); ! 1058: } ! 1059: ! 1060: static BOOL DumpMountList (int devNo) ! 1061: { ! 1062: int i; ! 1063: ! 1064: if (!CheckKernelModuleVersion (FALSE)) ! 1065: return FALSE; ! 1066: ! 1067: if (!GetMountList ()) ! 1068: return FALSE; ! 1069: ! 1070: for (i = 0; MountList[i].DeviceNumber != -1; i++) ! 1071: { ! 1072: MountListEntry *e = &MountList[i]; ! 1073: ! 1074: if (devNo != -1 && e->DeviceNumber != devNo) ! 1075: continue; ! 1076: ! 1077: if (Verbose == 0) ! 1078: { ! 1079: printf (TC_MAP_DEV "%d %s\n", ! 1080: e->DeviceNumber, ! 1081: e->VolumePath); ! 1082: } ! 1083: else ! 1084: { ! 1085: char eaName[128]; ! 1086: EAGetName (eaName, e->EA); ! 1087: ! 1088: printf (TC_MAP_DEV "%d:\n" ! 1089: " Volume: %s\n" ! 1090: " Type: %s\n" ! 1091: " Size: %lld bytes\n" ! 1092: " Encryption algorithm: %s\n" ! 1093: " Read-only: %s\n" ! 1094: " Hidden volume protected: %s\n\n", ! 1095: e->DeviceNumber, ! 1096: e->VolumePath, ! 1097: e->Hidden ? "Hidden" : "Normal", ! 1098: e->VolumeSize, ! 1099: eaName, ! 1100: (e->Flags & FLAG_READ_ONLY) ? "Yes" : "No", ! 1101: (e->Flags & FLAG_PROTECTION_ACTIVATED) ? "Yes - damage prevented" : ( ! 1102: (e->Flags & FLAG_HIDDEN_VOLUME_PROTECTION) ? "Yes" : "No" ) ! 1103: ); ! 1104: } ! 1105: } ! 1106: ! 1107: return TRUE; ! 1108: } ! 1109: ! 1110: ! 1111: static BOOL EnumMountPoints (char *device, char *mountPoint) ! 1112: { ! 1113: static FILE *m = NULL; ! 1114: ! 1115: if (device == NULL) ! 1116: { ! 1117: fclose (m); ! 1118: m = NULL; ! 1119: return TRUE; ! 1120: } ! 1121: ! 1122: if (m == NULL) ! 1123: { ! 1124: m = fopen ("/proc/mounts", "r"); ! 1125: if (m == NULL) ! 1126: { ! 1127: perror ("fopen /proc/mounts"); ! 1128: return FALSE; ! 1129: } ! 1130: } ! 1131: ! 1132: if (fscanf (m, "%" MAX_PATH_STR "s %" MAX_PATH_STR "s %*s %*s %*s %*s", ! 1133: device, mountPoint) != 2) ! 1134: { ! 1135: fclose (m); ! 1136: m = NULL; ! 1137: return FALSE; ! 1138: } ! 1139: ! 1140: return TRUE; ! 1141: } ! 1142: ! 1143: ! 1144: static BOOL DismountFileSystem (char *device) ! 1145: { ! 1146: char mountedDevice[MAX_PATH], mountPoint[MAX_PATH]; ! 1147: BOOL result = TRUE; ! 1148: ! 1149: while (EnumMountPoints (mountedDevice, mountPoint)) ! 1150: { ! 1151: if (strcmp (mountedDevice, device) == 0) ! 1152: { ! 1153: if (!Execute (FALSE, "umount", mountPoint, NULL)) ! 1154: result = FALSE; ! 1155: else if (Verbose >= 1) ! 1156: printf ("Dismounted %s\n", mountPoint); ! 1157: } ! 1158: } ! 1159: ! 1160: return result; ! 1161: } ! 1162: ! 1163: ! 1164: // devNo: -1 = Dismount all volumes ! 1165: static BOOL DismountVolume (int devNo) ! 1166: { ! 1167: char mapDevice[MAX_PATH]; ! 1168: int nMountedVolumes = 0; ! 1169: int i; ! 1170: BOOL found = FALSE; ! 1171: BOOL status = TRUE; ! 1172: ! 1173: if (!CheckKernelModuleVersion (FALSE)) ! 1174: return FALSE; ! 1175: ! 1176: if (!GetMountList ()) ! 1177: return FALSE; ! 1178: ! 1179: if (devNo == -1 && MountList[0].DeviceNumber == -1) ! 1180: { ! 1181: error ("No volumes mounted\n"); ! 1182: return FALSE; ! 1183: } ! 1184: ! 1185: // Flush write buffers before dismount if there are ! 1186: // mounted volumes with hidden volume protection ! 1187: for (i = 0; MountList[i].DeviceNumber != -1; i++) ! 1188: { ! 1189: if (MountList[i].Flags & FLAG_HIDDEN_VOLUME_PROTECTION) ! 1190: { ! 1191: sync (); ! 1192: MountListValid = FALSE; ! 1193: GetMountList (); ! 1194: break; ! 1195: } ! 1196: } ! 1197: ! 1198: for (i = 0; MountList[i].DeviceNumber != -1; i++) ! 1199: { ! 1200: MountListEntry *e = &MountList[i]; ! 1201: nMountedVolumes++; ! 1202: ! 1203: if (devNo == -1 || e->DeviceNumber == devNo) ! 1204: { ! 1205: BOOL dismounted = FALSE; ! 1206: found = TRUE; ! 1207: ! 1208: if (e->Flags & FLAG_PROTECTION_ACTIVATED) ! 1209: printf ("WARNING: Write to the hidden volume %s has been prevented!\n", e->VolumePath); ! 1210: ! 1211: sprintf (mapDevice, TC_MAP_DEV "%d", e->DeviceNumber); ! 1212: if (DismountFileSystem (mapDevice)) ! 1213: { ! 1214: char name[32]; ! 1215: sprintf (name, "truecrypt%d", e->DeviceNumber); ! 1216: dismounted = Execute (FALSE, "dmsetup", "remove", name, NULL); ! 1217: ! 1218: if (dismounted && IsFile (e->VolumePath)) ! 1219: { ! 1220: if (!DeleteLoopDevice (e->DeviceMinor)) ! 1221: status = FALSE; ! 1222: ! 1223: RestoreFileTime (e->VolumePath, ! 1224: UpdateTime ? time (NULL) : (time_t) e->ModTime, ! 1225: UpdateTime ? time (NULL) : (time_t) e->AcTime); ! 1226: } ! 1227: } ! 1228: ! 1229: if (!dismounted) ! 1230: { ! 1231: error ("Cannot dismount %s\n", mapDevice); ! 1232: status = FALSE; ! 1233: } ! 1234: else ! 1235: { ! 1236: nMountedVolumes--; ! 1237: if (Verbose >= 1) ! 1238: printf ("Unmapped %s\n", mapDevice); ! 1239: } ! 1240: ! 1241: if (devNo != -1) ! 1242: break; ! 1243: } ! 1244: } ! 1245: ! 1246: if (!found) ! 1247: { ! 1248: error (TC_MAP_DEV "%d not mounted\n", devNo); ! 1249: return FALSE; ! 1250: } ! 1251: ! 1252: if (nMountedVolumes == 0) ! 1253: { ! 1254: // Ignore errors as volumes may be mounted asynchronously ! 1255: UnloadKernelModule (TRUE); ! 1256: } ! 1257: ! 1258: return status; ! 1259: } ! 1260: ! 1261: ! 1262: // Convert a string to device number ! 1263: // text: device number or name or mount point ! 1264: BOOL ToDeviceNumber (char *text, int *deviceNumber) ! 1265: { ! 1266: char mountedDevice[MAX_PATH], mountPoint[MAX_PATH]; ! 1267: int i; ! 1268: ! 1269: if (sscanf (text, "%d", deviceNumber) == 1) ! 1270: return TRUE; ! 1271: ! 1272: if (sscanf (text, TC_MAP_DEV "%d", deviceNumber) == 1) ! 1273: return TRUE; ! 1274: ! 1275: while (EnumMountPoints (mountedDevice, mountPoint)) ! 1276: { ! 1277: if (strcmp (mountPoint, text) == 0 ! 1278: && sscanf (mountedDevice, TC_MAP_DEV "%d", deviceNumber) == 1) ! 1279: { ! 1280: EnumMountPoints (NULL, NULL); ! 1281: return TRUE; ! 1282: } ! 1283: } ! 1284: ! 1285: if (!GetMountList ()) ! 1286: return FALSE; ! 1287: ! 1288: for (i = 0; MountList[i].DeviceNumber != -1; i++) ! 1289: { ! 1290: MountListEntry *e = &MountList[i]; ! 1291: if (e->DeviceNumber == -1) ! 1292: break; ! 1293: ! 1294: if (strcmp (text, e->VolumePath) == 0) ! 1295: { ! 1296: *deviceNumber = e->DeviceNumber; ! 1297: return TRUE; ! 1298: } ! 1299: } ! 1300: ! 1301: error ("%s not mounted\n", text); ! 1302: return FALSE; ! 1303: } ! 1304: ! 1305: ! 1306: int main(int argc, char **argv) ! 1307: { ! 1308: char *volumePath = NULL; ! 1309: char *mountPoint = NULL; ! 1310: char volumePathBuf[MAX_PATH]; ! 1311: int i, o; ! 1312: int optIndex = 0; ! 1313: ! 1314: struct option longOptions[] = { ! 1315: {"device-number", required_argument, 0, 0}, ! 1316: {"dismount", optional_argument, 0, 'd'}, ! 1317: {"display-password", 0, 0, 0}, ! 1318: {"keyfile", required_argument, 0, 'k'}, ! 1319: {"keyfile-protected", required_argument, 0, 'K'}, ! 1320: {"filesystem", required_argument, 0, 0}, ! 1321: {"list", 0, 0, 'l'}, ! 1322: {"help", 0, 0, 'h'}, ! 1323: {"mount-options", required_argument, 0, 0}, ! 1324: {"password", required_argument, 0, 'l'}, ! 1325: {"password-tries", required_argument, 0, 0}, ! 1326: {"protect-hidden", 0, 0, 'P'}, ! 1327: {"read-only", 0, 0, 'r'}, ! 1328: {"test", 0, 0, 0}, ! 1329: {"update-time", 0, 0, 0}, ! 1330: {"verbose", 0, 0, 'v'}, ! 1331: {"version", 0, 0, 'V'}, ! 1332: {0, 0, 0, 0} ! 1333: }; ! 1334: ! 1335: if (getuid () != 0 && geteuid () != 0) ! 1336: { ! 1337: error ("administrator (root) privileges required\n"); ! 1338: return FALSE; ! 1339: } ! 1340: ! 1341: if (mlockall (MCL_FUTURE) != 0) ! 1342: perror ("Cannot prevent memory swapping: mlockall"); ! 1343: ! 1344: signal (SIGHUP, OnSignal); ! 1345: signal (SIGINT, OnSignal); ! 1346: signal (SIGQUIT, OnSignal); ! 1347: signal (SIGABRT, OnSignal); ! 1348: signal (SIGPIPE, OnSignal); ! 1349: signal (SIGTERM, OnSignal); ! 1350: ! 1351: atexit (OnExit); ! 1352: ! 1353: while ((o = getopt_long (argc, argv, "dhk:K:lp:PrvV", longOptions, &optIndex)) != -1) ! 1354: { ! 1355: switch (o) ! 1356: { ! 1357: case 'd': ! 1358: // Dismount ! 1359: { ! 1360: int devNo; ! 1361: ! 1362: if (optind < argc) ! 1363: { ! 1364: if (!ToDeviceNumber (argv[optind++], &devNo)) ! 1365: return 1; ! 1366: ! 1367: if (optind < argc) ! 1368: goto usage; ! 1369: } ! 1370: else ! 1371: devNo = -1; ! 1372: ! 1373: return DismountVolume (devNo) ? 0 : 1; ! 1374: } ! 1375: ! 1376: case 'l': ! 1377: // List ! 1378: { ! 1379: int devNo; ! 1380: ! 1381: if (optind < argc) ! 1382: { ! 1383: if (!ToDeviceNumber (argv[optind++], &devNo)) ! 1384: return 1; ! 1385: ! 1386: if (optind < argc) ! 1387: goto usage; ! 1388: } ! 1389: else ! 1390: devNo = -1; ! 1391: ! 1392: return DumpMountList (devNo) ? 0 : 1; ! 1393: } ! 1394: ! 1395: case 'k': ! 1396: case 'K': ! 1397: // Keyfile ! 1398: { ! 1399: KeyFile *kf = malloc (sizeof (KeyFile)); ! 1400: if (!kf) ! 1401: { ! 1402: perror ("malloc"); ! 1403: return 1; ! 1404: } ! 1405: strncpy (kf->FileName, optarg, sizeof (kf->FileName)); ! 1406: if (o == 'k') ! 1407: FirstKeyFile = KeyFileAdd (FirstKeyFile, kf); ! 1408: else ! 1409: FirstProtVolKeyFile = KeyFileAdd (FirstProtVolKeyFile, kf); ! 1410: } ! 1411: break; ! 1412: ! 1413: ! 1414: case 'p': ! 1415: // Password ! 1416: if (!CmdPasswordValid) ! 1417: { ! 1418: strncpy (CmdPassword.Text, optarg, sizeof (CmdPassword.Text)); ! 1419: CmdPassword.Length = strlen (CmdPassword.Text); ! 1420: CmdPasswordValid = TRUE; ! 1421: } ! 1422: else if (!CmdPassword2Valid) ! 1423: { ! 1424: strncpy (CmdPassword2.Text, optarg, sizeof (CmdPassword2.Text)); ! 1425: CmdPassword2.Length = strlen (CmdPassword2.Text); ! 1426: CmdPassword2Valid = TRUE; ! 1427: } ! 1428: break; ! 1429: ! 1430: case 'P': ! 1431: // Hidden volume protection ! 1432: ProtectHidden = TRUE; ! 1433: break; ! 1434: ! 1435: case 'r': ! 1436: ReadOnly = TRUE; ! 1437: break; ! 1438: ! 1439: case 'v': ! 1440: // Verbose ! 1441: Verbose++; ! 1442: break; ! 1443: ! 1444: case 'V': ! 1445: DumpVersion (stdout); ! 1446: return 0; ! 1447: ! 1448: case 'h': ! 1449: // Help ! 1450: DumpHelp (); ! 1451: return 0; ! 1452: ! 1453: case 0: ! 1454: if (strcmp ("display-password", longOptions[optIndex].name) == 0) ! 1455: { ! 1456: DisplayPassword = TRUE; ! 1457: break; ! 1458: } ! 1459: ! 1460: if (strcmp ("device-number", longOptions[optIndex].name) == 0) ! 1461: { ! 1462: if (sscanf (optarg, "%d", &UseDeviceNumber) == 1 ! 1463: && UseDeviceNumber >= 0) ! 1464: break; ! 1465: else ! 1466: goto usage; ! 1467: } ! 1468: ! 1469: if (strcmp ("filesystem", longOptions[optIndex].name) == 0) ! 1470: { ! 1471: Filesystem = optarg; ! 1472: break; ! 1473: } ! 1474: ! 1475: if (strcmp ("mount-options", longOptions[optIndex].name) == 0) ! 1476: { ! 1477: MountOpts = optarg; ! 1478: break; ! 1479: } ! 1480: ! 1481: if (strcmp ("password-tries", longOptions[optIndex].name) == 0) ! 1482: { ! 1483: if (sscanf (optarg, "%d", &PasswordEntryTries) == 1) ! 1484: break; ! 1485: else ! 1486: goto usage; ! 1487: } ! 1488: ! 1489: if (strcmp ("test", longOptions[optIndex].name) == 0) ! 1490: { ! 1491: if (AutoTestAlgorithms ()) ! 1492: { ! 1493: printf ("Self-tests of all algorithms passed.\n"); ! 1494: return 0; ! 1495: } ! 1496: ! 1497: printf ("Self-tests of algorithms FAILED!\n"); ! 1498: return 1; ! 1499: } ! 1500: ! 1501: if (strcmp ("update-time", longOptions[optIndex].name) == 0) ! 1502: { ! 1503: UpdateTime = TRUE; ! 1504: break; ! 1505: } ! 1506: goto usage; ! 1507: ! 1508: default: ! 1509: goto usage; ! 1510: } ! 1511: } ! 1512: ! 1513: if (optind >= argc) ! 1514: goto usage; ! 1515: ! 1516: if (optind < argc) ! 1517: volumePath = argv[optind++]; ! 1518: ! 1519: if (optind < argc) ! 1520: mountPoint = argv[optind++]; ! 1521: ! 1522: if (optind < argc) ! 1523: goto usage; ! 1524: ! 1525: // Relative path => absolute ! 1526: if (volumePath[0] != '/') ! 1527: { ! 1528: char s[MAX_PATH]; ! 1529: getcwd (s, sizeof (s)); ! 1530: snprintf (volumePathBuf, sizeof (volumePathBuf), "%s/%s", s, volumePath); ! 1531: volumePath = volumePathBuf; ! 1532: } ! 1533: ! 1534: return MountVolume (volumePath, mountPoint) == FALSE; ! 1535: ! 1536: usage: ! 1537: DumpUsage (stderr); ! 1538: ! 1539: return 1; ! 1540: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.