|
|
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.