|
|
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: #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>
16: #include <sys/mman.h>
17: #include <sys/stat.h>
18: #include <sys/types.h>
19: #include <sys/wait.h>
20: #include <termios.h>
21: #include <time.h>
22: #include <unistd.h>
23: #include <utime.h>
24:
25: #include "Tcdefs.h"
26: #include "Keyfiles.h"
27: #include "Volumes.h"
28: #include "Tests.h"
29: #include "Dm-target.h"
30:
31: #define MAX_VOLUMES 256
32: #define MAX_MINOR 256
33:
34: #undef MAX_PATH
35: #define MAX_PATH 260
36: #define MAX_PATH_STR "259"
37:
38: #define TC_MAP_DEV "/dev/mapper/truecrypt"
39: #define LOOP_DEV "/dev/loop"
40:
41: #define error(fmt, args...) fprintf (stderr, "truecrypt: " fmt, ## args)
42:
43: typedef struct
44: {
45: int DeviceNumber;
46: int DeviceMajor;
47: int DeviceMinor;
48: uint64_t VolumeSize;
49: char VolumePath[MAX_PATH];
50: int EA;
1.1.1.2 ! root 51: int Mode;
1.1 root 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: {
1.1.1.2 ! root 390: int n = 0;
1.1 root 391: char s[2048];
392: MountListEntry *e = &MountList[i];
393:
394: if (!fgets (s, sizeof (s), p))
395: break;
396:
1.1.1.2 ! root 397: if (sscanf (s, "truecrypt%d: 0 %lld truecrypt %d %d 0 0 %d:%d %lld %lld %lld %lld %lld %d %n",
1.1 root 398: &e->DeviceNumber,
399: &e->VolumeSize,
400: &e->EA,
1.1.1.2 ! root 401: &e->Mode,
1.1 root 402: &e->DeviceMajor,
403: &e->DeviceMinor,
404: &e->Hidden,
405: &e->ReadOnlyStart,
406: &e->ReadOnlyEnd,
407: &e->ModTime,
408: &e->AcTime,
409: &e->Flags,
1.1.1.2 ! root 410: &n) >= 12 && n > 0)
1.1 root 411: {
1.1.1.2 ! root 412: int l;
! 413: strncpy (e->VolumePath, s + n, sizeof (e->VolumePath));
! 414: l = strlen (s + n);
! 415: if (l > 0)
! 416: e->VolumePath[l - 1] = 0;
! 417:
1.1 root 418: e->Hidden = e->Hidden == 1 ? FALSE : TRUE;
419: e->VolumeSize *= SECTOR_SIZE;
420: }
421: else
422: i--;
423: }
424:
425: MountList[i].DeviceNumber = -1;
426:
427: fclose (p);
428: if (!WaitChild (TRUE, "dmsetup"))
429: goto err;
430:
431: MountListValid = TRUE;
432: return TRUE;
433:
434: err:
435: MountList[0].DeviceNumber = -1;
436: return FALSE;
437: }
438:
439:
440: static BOOL IsVolumeMounted (char *volumePath)
441: {
442: int i;
443: if (!GetMountList ())
444: return FALSE;
445:
446: for (i = 0; MountList[i].DeviceNumber != -1; i++)
447: if (strcmp (volumePath, MountList[i].VolumePath) == 0)
448: return TRUE;
449:
450: return FALSE;
451: }
452:
453:
454: static int GetFreeMapDevice ()
455: {
456: FILE *p;
457: char cmd[128];
458: int n;
459:
460: if (!GetMountList ())
461: return -1;
462:
463: for (n = 0; n < MAX_MINOR; n++)
464: {
465: int j = 0;
466: while (MountList[j].DeviceNumber != -1)
467: {
468: if (MountList[j].DeviceNumber == n)
469: break;
470: j++;
471: }
472:
473: if (MountList[j].DeviceNumber == -1)
474: return n;
475: }
476:
477: return -1;
478: }
479:
480:
481: static BOOL DeleteLoopDevice (int loopDeviceNo)
482: {
483: char dev[32];
484: BOOL r;
485:
486: sprintf (dev, LOOP_DEV "%d", loopDeviceNo);
487: if (!IsBlockDevice (dev))
488: sprintf (dev, LOOP_DEV "/%d", loopDeviceNo);
489:
490: r = Execute (FALSE, "losetup", "-d", dev, NULL);
491:
492: if (r && Verbose > 1)
493: printf ("Detached %s\n", dev);
494:
495: return r;
496: }
497:
498:
499: static BOOL OpenVolume (char *volumePath, Password *password, PCRYPTO_INFO *cryptoInfo, uint64_t *startSector, uint64_t *totalSectors, time_t *modTime, time_t *acTime)
500: {
501: char header[SECTOR_SIZE];
502: uint64_t r;
503: FILE *f = NULL;
504: struct stat volumeStat;
505:
506: if (stat (volumePath, &volumeStat) != 0)
507: {
508: perror ("Cannot open volume");
509: volumeStat.st_ctime = 0;
510: goto err;
511: }
512:
1.1.1.2 ! root 513: f = fopen (volumePath, "rb");
1.1 root 514: if (!f)
515: {
516: perror ("Cannot open volume");
517: goto err;
518: }
519:
520: // Normal header
521: if (fread (header, 1, SECTOR_SIZE, f) != SECTOR_SIZE)
522: {
523: perror ("Cannot read volume header");
524: goto err;
525: }
526:
527: fseek (f, 0, SEEK_END);
528: *totalSectors = ftello (f) / SECTOR_SIZE - 1;
529:
1.1.1.2 ! root 530: *startSector = 1;
1.1 root 531: r = VolumeReadHeader (header, password, cryptoInfo);
532:
1.1.1.2 ! root 533: if (r == ERR_PASSWORD_WRONG)
1.1 root 534: {
535: // Hidden header
536: if (fseek (f, -HIDDEN_VOL_HEADER_OFFSET, SEEK_END) == -1
537: || fread (header, 1, SECTOR_SIZE, f) != SECTOR_SIZE)
538: {
539: perror ("Cannot read volume header");
540: goto err;
541: }
542:
543: r = VolumeReadHeader (header, password, cryptoInfo);
544:
1.1.1.2 ! root 545: if (r == ERR_PASSWORD_WRONG)
1.1 root 546: {
547: if (IsTerminal)
548: puts ("Incorrect password or not a TrueCrypt volume");
549: else
550: error ("Incorrect password or not a TrueCrypt volume\n");
551:
552: goto err;
553: }
554:
555: *startSector = (ftello (f)
556: + SECTOR_SIZE * 2
557: - (*cryptoInfo)->hiddenVolumeSize
558: - HIDDEN_VOL_HEADER_OFFSET) / SECTOR_SIZE;
559:
560: *totalSectors = (*cryptoInfo)->hiddenVolumeSize / SECTOR_SIZE;
561: }
1.1.1.2 ! root 562:
! 563: // Report errors
! 564: if (r != 0 && r != ERR_PASSWORD_WRONG)
! 565: {
! 566: char msg[128];
! 567:
! 568: switch (r)
! 569: {
! 570: case ERR_NEW_VERSION_REQUIRED:
! 571: strcpy (msg, "A newer version of TrueCrypt is required to open this volume");
! 572: break;
! 573:
! 574: default:
! 575: sprintf (msg, "Volume cannot be opened: Error %d", r);
! 576: break;
! 577: }
! 578:
! 579: if (IsTerminal)
! 580: printf ("%s\n", msg);
! 581: else
! 582: error ("%s\n", msg);
! 583:
! 584: goto err;
! 585: }
1.1 root 586:
587: fclose (f);
588:
589: if (!UpdateTime)
590: RestoreFileTime (volumePath, volumeStat.st_mtime, volumeStat.st_atime);
591:
592: *modTime = volumeStat.st_mtime;
593: *acTime = volumeStat.st_atime;
594: return TRUE;
595:
596: err:
597: *cryptoInfo = NULL;
598:
599: if (f)
600: fclose (f);
601:
602: if (volumeStat.st_ctime != 0 && !UpdateTime)
603: RestoreFileTime (volumePath, volumeStat.st_mtime, volumeStat.st_atime);
604:
605: return FALSE;
606: }
607:
608:
609: static void GetPassword (char *prompt, char *volumePath, Password *password)
610: {
611: struct termios noEcho;
612:
613: if (tcgetattr (0, &TerminalAttributes) == 0)
614: {
615: IsTerminal = TRUE;
616: noEcho = TerminalAttributes;
617:
618: if (!DisplayPassword)
619: {
620: noEcho.c_lflag &= ~ECHO;
621: if (tcsetattr (0, TCSANOW, &noEcho) != 0)
622: error ("Failed to turn terminal echo off\n");
623: }
624:
625: printf (prompt, volumePath);
626: }
627:
628: if (fgets (password->Text, sizeof (password->Text), stdin))
629: {
630: char *newl = strchr (password->Text, '\n');
631: if (newl) newl[0] = 0;
632:
633: password->Length = strlen (password->Text);
634: }
635: else
636: password->Length = 0;
637:
638: if (IsTerminal && !DisplayPassword)
639: {
640: tcsetattr (0, TCSANOW, &TerminalAttributes);
641: puts ("");
642: }
643: }
644:
645:
1.1.1.2 ! root 646: static char *EscapeSpaces (char *string)
! 647: {
! 648: static char escapedString[MAX_PATH * 2];
! 649: char *e = escapedString;
! 650: char c;
! 651:
! 652: if (strlen (string) > MAX_PATH)
! 653: return NULL;
! 654:
! 655: while ((c = *string++))
! 656: {
! 657: if (c == ' ')
! 658: *e++ = '\\';
! 659:
! 660: *e++ = c;
! 661: }
! 662:
! 663: return escapedString;
! 664: }
! 665:
! 666:
1.1 root 667: static BOOL MountVolume (char *volumePath, char *mountPoint)
668: {
669: char hostDevice[MAX_PATH];
670: char mapDevice[MAX_PATH];
671: int loopDevNo = -1;
672: PCRYPTO_INFO ci = NULL;
673: uint64_t startSector, totalSectors;
674: uint64_t readOnlyStartSector = 0, readOnlySectors = 0;
675: int pfd[2];
676: int pid, res, devNo;
677: time_t modTime, acTime;
678: FILE *f, *w;
679: int flags;
680: int i;
681: int tries = PasswordEntryTries;
682:
683: if (!AutoTestAlgorithms ())
684: {
685: error ("Self-tests of algorithms FAILED!\n");
686: return FALSE;
687: }
688:
689: if (IsVolumeMounted (volumePath))
690: {
691: error ("Volume already mounted\n");
692: return FALSE;
693: }
694:
695: do
696: {
697: Password *pw = &password;
698:
699: if (!CmdPasswordValid)
700: GetPassword ("Enter password for '%s': ", volumePath, &password);
701: else
702: pw = &CmdPassword;
703:
704: if (FirstKeyFile && !KeyFilesApply (pw, FirstKeyFile, !UpdateTime))
705: {
706: error ("Error while processing keyfiles\n");
707: goto err;
708: }
709:
710: if (OpenVolume (volumePath, pw, &ci, &startSector, &totalSectors, &modTime, &acTime))
711: break;
712: else
713: totalSectors = 0;
714:
715: } while (!CmdPasswordValid && IsTerminal && --tries > 0);
716:
717: if (totalSectors == 0)
718: goto err;
719:
720: // Hidden volume protection
721: if (ProtectHidden)
722: {
723: PCRYPTO_INFO ciH = NULL;
724: uint64_t startSectorH, totalSectorsH;
725:
726: tries = PasswordEntryTries;
727: do
728: {
729: Password *pw = &password;
730:
731: if (!CmdPassword2Valid)
732: GetPassword ("Enter hidden volume password: ", "", &password);
733: else
734: pw = &CmdPassword2;
735:
736: if (FirstProtVolKeyFile && !KeyFilesApply (pw, FirstProtVolKeyFile, !UpdateTime))
737: {
738: error ("Error while processing keyfiles\n");
739: goto err;
740: }
741:
742: if (OpenVolume (volumePath, pw, &ciH, &startSectorH, &totalSectorsH, &modTime, &acTime))
743: {
744: readOnlyStartSector = startSectorH;
745: readOnlySectors = startSectorH + totalSectorsH;
746: break;
747: }
748:
749: } while (!CmdPassword2Valid && IsTerminal && --tries > 0);
750:
751: if (ciH)
752: crypto_close (ciH);
753:
754: if (readOnlySectors == 0)
755: goto err;
756: }
757:
758: // Headers decrypted
759:
760: // Loopback
761: if (IsFile (volumePath))
762: {
763: int i;
764:
765: for (i = 0; i < MAX_MINOR; i++)
766: {
767: snprintf (hostDevice, sizeof (hostDevice), LOOP_DEV "%d", i);
768:
769: if (!IsBlockDevice (hostDevice))
770: {
771: snprintf (hostDevice, sizeof (hostDevice), LOOP_DEV "/%d", i);
772: if (!IsBlockDevice (hostDevice))
773: continue;
774: }
775:
776: if (Execute (TRUE, "losetup", hostDevice, volumePath, NULL))
777: break;
778: }
779:
780: if (i >= MAX_MINOR)
781: {
782: error ("No free loopback device available for file-hosted volume\n");
783: goto err;
784: }
785:
786: loopDevNo = i;
787:
788: if (Verbose > 1)
789: printf ("Attached %s to %s\n", volumePath, hostDevice);
790:
791: }
792: else
793: strncpy (hostDevice, volumePath, sizeof (hostDevice));
794:
795: // Load kernel module
796: if (!LoadKernelModule ())
797: goto err;
798:
799: if (!CheckKernelModuleVersion (TRUE))
800: goto err;
801:
802: // dmsetup
803: devNo = UseDeviceNumber == -1 ? GetFreeMapDevice () : UseDeviceNumber;
804: if (devNo == -1)
805: {
806: error ("Maximum number of volumes mounted\n");
807: goto err;
808: }
809:
810: sprintf (mapDevice, "truecrypt%d", devNo);
811:
812: pipe (pfd);
813: pid = fork ();
814:
815: if (pid == -1)
816: {
817: perror ("fork");
818: goto err;
819: }
820: else if (pid == 0)
821: {
822: SecurityCleanup ();
823:
824: close (pfd[1]);
825: dup2 (pfd[0], STDIN_FILENO);
826:
827: execlp ("dmsetup", "dmsetup", "create", mapDevice, NULL);
828:
829: perror ("execlp dmsetup");
830: _exit (1);
831: }
832:
833: close (pfd[0]);
834: w = fdopen (pfd[1], "a");
835: if (w == NULL)
836: {
837: perror ("fdopen");
838: goto err;
839: }
840:
1.1.1.2 ! root 841: fprintf (w, "0 %lld truecrypt %d %d ", totalSectors, ci->ea, ci->mode);
1.1 root 842:
843: for (i = DISK_IV_SIZE; i < EAGetKeySize (ci->ea) + DISK_IV_SIZE; i++)
844: fprintf (w, "%02x", ci->master_key[i]);
845:
846: fprintf (w, " ");
847:
848: for (i = 0; i < (int)sizeof (ci->iv); i++)
849: fprintf (w, "%02x", ci->iv[i]);
850:
851: flags = 0;
852:
853: if (ReadOnly)
854: flags |= FLAG_READ_ONLY;
855: else if (ProtectHidden)
856: flags |= FLAG_HIDDEN_VOLUME_PROTECTION;
857:
858: fprintf (w, " %s %lld %lld %lld %lld %lld %d %s\n",
859: hostDevice,
860: startSector,
861: readOnlyStartSector,
862: readOnlySectors,
863: (uint64_t) modTime,
864: (uint64_t) acTime,
865: flags,
1.1.1.2 ! root 866: EscapeSpaces (volumePath));
1.1 root 867:
868: fclose (w);
869:
870: if (!WaitChild (FALSE, "dmsetup"))
871: {
872: Execute (TRUE, "dmsetup", "remove", mapDevice, NULL);
873: goto err;
874: }
875:
876: sprintf (mapDevice, TC_MAP_DEV "%d", devNo);
877:
878: if (Verbose >= 1)
879: printf ("Mapped %s as %s\n", volumePath, mapDevice);
880:
881: // Mount
882: if (mountPoint)
883: {
884: char fstype[64], opts[128];
885:
886: strcpy (fstype, "-t");
887: if (Filesystem)
888: strncat (fstype, Filesystem, sizeof (fstype) - 3);
889: else
890: strcat (fstype, "auto");
891:
892: strcpy (opts, ReadOnly ? "-oro" : "-orw");
893: if (MountOpts)
894: {
895: strcat (opts, ",");
896: strncat (opts, MountOpts, sizeof (opts) - 6);
897: }
898:
899: if (!Execute (FALSE, "mount", fstype, opts, mapDevice, mountPoint, NULL))
900: {
901: error ("Mount failed\n");
902: loopDevNo = -1;
903: goto err;
904: }
905:
906: if (Verbose >= 1)
907: printf ("Mounted %s at %s\n", mapDevice, mountPoint);
908: }
909:
910: crypto_close (ci);
911:
912: return TRUE;
913:
914: err:
915: if (ci)
916: crypto_close (ci);
917:
918: if (loopDevNo != -1)
919: DeleteLoopDevice (loopDevNo);
920:
921: UnloadKernelModule (TRUE);
922:
923: return FALSE;
924: }
925:
926:
927: static void DumpVersion (FILE *f)
928: {
929: fprintf (f,
930: "truecrypt %s\n\n"
931: "Copyright (C) 2004-2005 TrueCrypt Foundation. All Rights Reserved.\n\
932: Copyright (C) 1998-2000 Paul Le Roux. All Rights Reserved.\n\
933: Copyright (C) 2004 TrueCrypt Team. All Rights Reserved.\n\
1.1.1.2 ! root 934: Copyright (C) 1999-2005 Dr. Brian Gladman. All Rights Reserved.\n\
1.1 root 935: Copyright (C) 1995-1997 Eric Young. All Rights Reserved.\n\
936: Copyright (C) 2001 Markus Friedl. All Rights Reserved.\n\n"
937: , VERSION_STRING);
938: }
939:
940:
941: static void DumpUsage (FILE *f)
942: {
943: fprintf (f,
944: "Usage: truecrypt [OPTIONS] VOLUME_PATH [MOUNT_DIRECTORY]\n"
945: " or: truecrypt [OPTIONS] -d | --dismount | -l | --list [MAPPED_VOLUME]\n"
946: " or: truecrypt -h | --help | --test | -V | --version\n"
947: "\nCommands:\n"
948: " VOLUME_PATH Map volume\n"
949: " VOLUME_PATH MOUNT_DIRECTORY Map and mount volume\n"
950: " -d, --dismount [MAPPED_VOLUME] Dismount and unmap volume\n"
951: " -h, --help Display help\n"
952: " -l, --list [MAPPED_VOLUME] List mapped volumes\n"
953: " --test Test algorithms\n"
954: " -V, --version Display version information\n"
955: "\nOptions:\n"
956: " --device-number NUMBER Map volume as device number\n"
957: " --display-password Display password while typing\n"
958: " --filesystem TYPE Filesystem type to mount\n"
959: " -k, --keyfile FILE|DIR Keyfile for volume\n"
960: " -K, --keyfile-protected FILE|DIR Keyfile for protected volume\n"
961: " -p, --password PASSWORD Password for volume\n"
962: " --password-tries NUMBER Password entry tries\n"
963: " -P, --protect-hidden Protect hidden volume\n"
964: " --update-time Do not preserve timestamps\n"
965: " -r, --read-only Map/Mount read-only\n"
966: " --mount-options OPTIONS Mount options\n"
967: " -v, --verbose Verbose output\n"
968: "\n MAPPED_VOLUME = DEVICE_NUMBER | DEVICE_NAME | MOUNT_POINT | VOLUME_PATH\n"
969: "For a detailed help use --help or see truecrypt(1) man page.\n"
970: );
971: }
972:
973: static void DumpHelp ()
974: {
975: fprintf (stdout,
976: "Manages encrypted TrueCrypt volumes, which can be mapped as virtual block\n"
977: "devices and used as any other standard block device. All data being read\n"
978: "from a mapped TrueCrypt volume is transparently decrypted and all data being\n"
979: "written to it is transparently encrypted.\n"
980: "\n"
981: "Usage: truecrypt [OPTIONS] VOLUME_PATH [MOUNT_DIRECTORY]\n"
982: " or: truecrypt [OPTIONS] -d | --dismount | -l | --list [MAPPED_VOLUME]\n"
983: " or: truecrypt -h | --help | --test | -V | --version\n"
984: "\n"
985: "Options:\n"
986: "\n"
987: "VOLUME_PATH [MOUNT_DIRECTORY]\n"
988: " Open a TrueCrypt volume specified by VOLUME_PATH and map it as a block device\n"
989: " /dev/mapper/truecryptN. N is the first available device number if not\n"
990: " otherwise specified with --device-number. The filesystem of the mapped volume\n"
991: " is mounted at MOUNT_DIRECTORY if specified.\n"
992: "\n"
993: "-d, --dismount [MAPPED_VOLUME]\n"
994: " Dismount and unmap mapped volumes. If MAPPED_VOLUME is not specified, all\n"
995: " volumes are dismounted and unmapped. See below for a description of\n"
996: " MAPPED_VOLUME.\n"
997: "\n"
998: "-l, --list [MAPPED_VOLUME]\n"
999: " Display a list of mapped volumes. If MAPPED_VOLUME is not specified, all\n"
1000: " volumes are listed. By default, the list contains only volume path and mapped\n"
1001: " device name pairs. A more detailed list can be enabled by verbose output\n"
1002: " option (-v). See below for a description of MAPPED_VOLUME.\n"
1003: "\n"
1004: "MAPPED_VOLUME\n"
1005: " Specifies a mapped or mounted volume. One of the following forms can be used:\n\n"
1006: " 1) Path to the encrypted TrueCrypt volume.\n\n"
1007: " 2) Mount directory of the volume's filesystem (if mounted).\n\n"
1008: " 3) Device number of the mapped volume.\n\n"
1009: " 4) Device name of the mapped volume.\n\n"
1010: "\n"
1011: "--device-number N\n"
1012: " Use device number N when mapping a volume as a block device\n"
1013: " /dev/mapper/truecryptN. Default is the first available device.\n"
1014: "\n"
1015: "--display-password\n"
1016: " Display password characters while typing.\n"
1017: "\n"
1018: "--filesystem TYPE\n"
1019: " Filesystem type to mount. The TYPE argument is passed to mount(8) command\n"
1020: " with option -t. Default type is 'auto'.\n"
1021: "\n"
1022: "-h, --help\n"
1023: " Display help information.\n"
1024: "\n"
1025: "-k, --keyfile FILE | DIRECTORY\n"
1026: " Use specified keyfile to open a volume to be mapped. When a directory is\n"
1027: " specified, all files inside it will be used (non-recursively). Additional\n"
1028: " keyfiles can be specified with multiple -k options. See also option -K.\n"
1029: "\n"
1030: "-K, --keyfile-protected FILE | DIRECTORY\n"
1031: " Use specified keyfile to open a hidden volume to be protected. See also\n"
1032: " options -k and -P.\n"
1033: "\n"
1034: "--mount-options OPTIONS\n"
1035: " Filesystem mount options. The OPTIONS argument is passed to mount(8)\n"
1036: " command with option -o.\n"
1037: " \n"
1038: "-p, --password PASSWORD\n"
1039: " Use specified password to open a volume. Additional passwords can be\n"
1040: " specified with multiple -p options. An empty password can also be specified\n"
1041: " (\"\" in most shells). Note that passing a password on the command line is\n"
1042: " potentially insecure as the password may be visible in the process list\n"
1043: " (see ps(1)) and/or stored in a command history file. \n"
1044: " \n"
1045: "--password-tries NUMBER\n"
1046: " Prompt NUMBER of times for a password until the correct password is entered.\n"
1047: " Default is to prompt three times.\n"
1048: "\n"
1049: "-P, --protect-hidden\n"
1050: " Write-protect a hidden volume when mapping an outer volume. Before mapping the\n"
1051: " outer volume, the user will be prompted for a password to open the hidden\n"
1052: " volume. The size and position of the hidden volume is then determined and the\n"
1053: " outer volume is mounted with all sectors belonging to the hidden volume\n"
1054: " protected against write operations. When a write to the protected area is\n"
1055: " prevented, the whole volume is switched to read-only mode. Verbose list command\n"
1056: " (-vl) can be used to query the state of the hidden volume protection. Warning\n"
1057: " message is displayed when a volume switched to read-only is being dismounted.\n"
1058: " See also option -r.\n"
1059: " \n"
1060: "-r, --read-only\n"
1061: " Map and/or mount a volume as read-only. Write operations to the volume may not\n"
1062: " fail immediately due to the write buffering performed by the system, but the\n"
1063: " physical write will still be prevented.\n"
1064: " \n"
1065: "--test\n"
1066: " Test all internal algorithms used in the process of encryption and decryption.\n"
1067: "\n"
1068: "--update-time\n"
1069: " Do not preserve access and modification timestamps of volume containers and\n"
1070: " access timestamps of keyfiles. By default, timestamps are restored after\n"
1071: " a volume is unmapped or after a keyfile is closed.\n"
1072: "\n"
1073: "-v, --verbose\n"
1074: " Enable verbose output. Multiple -v options can be specified to increase the\n"
1075: " level of verbosity.\n"
1076: "\n"
1077: "-V, --version\n"
1078: " Display version information.\n"
1079: "\n"
1080: "Examples:\n"
1081: "\n"
1082: "truecrypt /root/volume.tc /mnt/tc\n"
1083: " Map a volume /root/volume.tc and mount its filesystem at /mnt/tc.\n"
1084: "\n"
1085: "truecrypt -d\n"
1086: " Dismount and unmap all mapped volumes.\n"
1087: " \n"
1088: "truecrypt -d /root/volume.tc\n"
1089: " Dismount and unmap a volume /root/volume.tc.\n"
1090: "\n"
1091: "truecrypt -d /mnt/tc\n"
1092: " Dismount and unmap a volume mounted at /mnt/tc.\n"
1093: "\n"
1094: "truecrypt -vl\n"
1095: " Display a detailed list of all mapped volumes.\n"
1096: " \n"
1097: "truecrypt --device-number=1 /dev/hdc1 && mkfs /dev/mapper/truecrypt1\n"
1098: " Map a volume /dev/hdc1 and create a new filesystem on it.\n"
1099: "\n"
1100: "truecrypt -P /dev/hdc1 /mnt/tc\n"
1101: " Map and mount outer volume /dev/hdc1 and protect hidden volume within it.\n"
1102: "\n"
1103: "truecrypt -p \"\" -p \"\" -k key1 -k key2 -K key_hidden -P volume.tc\n"
1104: " Map outer volume ./volume.tc and protect hidden volume within it.\n"
1105: " The outer volume is opened with keyfiles ./key1 and ./key2 and the\n"
1106: " hidden volume with ./key_hidden. Passwords for both volumes are empty.\n"
1107: "\n"
1108: "Report bugs at <http://www.truecrypt.org/bugs>.\n"
1109: );
1110: }
1111:
1112: static BOOL DumpMountList (int devNo)
1113: {
1114: int i;
1115:
1116: if (!CheckKernelModuleVersion (FALSE))
1117: return FALSE;
1118:
1119: if (!GetMountList ())
1120: return FALSE;
1121:
1122: for (i = 0; MountList[i].DeviceNumber != -1; i++)
1123: {
1124: MountListEntry *e = &MountList[i];
1125:
1126: if (devNo != -1 && e->DeviceNumber != devNo)
1127: continue;
1128:
1129: if (Verbose == 0)
1130: {
1131: printf (TC_MAP_DEV "%d %s\n",
1132: e->DeviceNumber,
1133: e->VolumePath);
1134: }
1135: else
1136: {
1137: char eaName[128];
1138: EAGetName (eaName, e->EA);
1139:
1140: printf (TC_MAP_DEV "%d:\n"
1141: " Volume: %s\n"
1142: " Type: %s\n"
1143: " Size: %lld bytes\n"
1144: " Encryption algorithm: %s\n"
1.1.1.2 ! root 1145: " Mode of operation: %s\n"
1.1 root 1146: " Read-only: %s\n"
1147: " Hidden volume protected: %s\n\n",
1148: e->DeviceNumber,
1149: e->VolumePath,
1150: e->Hidden ? "Hidden" : "Normal",
1151: e->VolumeSize,
1152: eaName,
1.1.1.2 ! root 1153: EAGetModeName (e->EA, e->Mode, TRUE),
1.1 root 1154: (e->Flags & FLAG_READ_ONLY) ? "Yes" : "No",
1155: (e->Flags & FLAG_PROTECTION_ACTIVATED) ? "Yes - damage prevented" : (
1156: (e->Flags & FLAG_HIDDEN_VOLUME_PROTECTION) ? "Yes" : "No" )
1157: );
1158: }
1159: }
1160:
1161: return TRUE;
1162: }
1163:
1164:
1165: static BOOL EnumMountPoints (char *device, char *mountPoint)
1166: {
1167: static FILE *m = NULL;
1168:
1169: if (device == NULL)
1170: {
1171: fclose (m);
1172: m = NULL;
1173: return TRUE;
1174: }
1175:
1176: if (m == NULL)
1177: {
1178: m = fopen ("/proc/mounts", "r");
1179: if (m == NULL)
1180: {
1181: perror ("fopen /proc/mounts");
1182: return FALSE;
1183: }
1184: }
1185:
1186: if (fscanf (m, "%" MAX_PATH_STR "s %" MAX_PATH_STR "s %*s %*s %*s %*s",
1187: device, mountPoint) != 2)
1188: {
1189: fclose (m);
1190: m = NULL;
1191: return FALSE;
1192: }
1193:
1194: return TRUE;
1195: }
1196:
1197:
1198: static BOOL DismountFileSystem (char *device)
1199: {
1200: char mountedDevice[MAX_PATH], mountPoint[MAX_PATH];
1201: BOOL result = TRUE;
1202:
1203: while (EnumMountPoints (mountedDevice, mountPoint))
1204: {
1205: if (strcmp (mountedDevice, device) == 0)
1206: {
1207: if (!Execute (FALSE, "umount", mountPoint, NULL))
1208: result = FALSE;
1209: else if (Verbose >= 1)
1210: printf ("Dismounted %s\n", mountPoint);
1211: }
1212: }
1213:
1214: return result;
1215: }
1216:
1217:
1218: // devNo: -1 = Dismount all volumes
1219: static BOOL DismountVolume (int devNo)
1220: {
1221: char mapDevice[MAX_PATH];
1222: int nMountedVolumes = 0;
1223: int i;
1224: BOOL found = FALSE;
1225: BOOL status = TRUE;
1226:
1227: if (!CheckKernelModuleVersion (FALSE))
1228: return FALSE;
1229:
1230: if (!GetMountList ())
1231: return FALSE;
1232:
1233: if (devNo == -1 && MountList[0].DeviceNumber == -1)
1234: {
1235: error ("No volumes mounted\n");
1236: return FALSE;
1237: }
1238:
1239: // Flush write buffers before dismount if there are
1240: // mounted volumes with hidden volume protection
1241: for (i = 0; MountList[i].DeviceNumber != -1; i++)
1242: {
1243: if (MountList[i].Flags & FLAG_HIDDEN_VOLUME_PROTECTION)
1244: {
1245: sync ();
1246: MountListValid = FALSE;
1247: GetMountList ();
1248: break;
1249: }
1250: }
1251:
1252: for (i = 0; MountList[i].DeviceNumber != -1; i++)
1253: {
1254: MountListEntry *e = &MountList[i];
1255: nMountedVolumes++;
1256:
1257: if (devNo == -1 || e->DeviceNumber == devNo)
1258: {
1259: BOOL dismounted = FALSE;
1260: found = TRUE;
1261:
1262: if (e->Flags & FLAG_PROTECTION_ACTIVATED)
1263: printf ("WARNING: Write to the hidden volume %s has been prevented!\n", e->VolumePath);
1264:
1265: sprintf (mapDevice, TC_MAP_DEV "%d", e->DeviceNumber);
1266: if (DismountFileSystem (mapDevice))
1267: {
1268: char name[32];
1269: sprintf (name, "truecrypt%d", e->DeviceNumber);
1270: dismounted = Execute (FALSE, "dmsetup", "remove", name, NULL);
1271:
1272: if (dismounted && IsFile (e->VolumePath))
1273: {
1274: if (!DeleteLoopDevice (e->DeviceMinor))
1275: status = FALSE;
1276:
1277: RestoreFileTime (e->VolumePath,
1278: UpdateTime ? time (NULL) : (time_t) e->ModTime,
1279: UpdateTime ? time (NULL) : (time_t) e->AcTime);
1280: }
1281: }
1282:
1283: if (!dismounted)
1284: {
1285: error ("Cannot dismount %s\n", mapDevice);
1286: status = FALSE;
1287: }
1288: else
1289: {
1290: nMountedVolumes--;
1291: if (Verbose >= 1)
1292: printf ("Unmapped %s\n", mapDevice);
1293: }
1294:
1295: if (devNo != -1)
1296: break;
1297: }
1298: }
1299:
1300: if (!found)
1301: {
1302: error (TC_MAP_DEV "%d not mounted\n", devNo);
1303: return FALSE;
1304: }
1305:
1306: if (nMountedVolumes == 0)
1307: {
1308: // Ignore errors as volumes may be mounted asynchronously
1309: UnloadKernelModule (TRUE);
1310: }
1311:
1312: return status;
1313: }
1314:
1315:
1316: // Convert a string to device number
1317: // text: device number or name or mount point
1318: BOOL ToDeviceNumber (char *text, int *deviceNumber)
1319: {
1320: char mountedDevice[MAX_PATH], mountPoint[MAX_PATH];
1321: int i;
1322:
1323: if (sscanf (text, "%d", deviceNumber) == 1)
1324: return TRUE;
1325:
1326: if (sscanf (text, TC_MAP_DEV "%d", deviceNumber) == 1)
1327: return TRUE;
1328:
1329: while (EnumMountPoints (mountedDevice, mountPoint))
1330: {
1331: if (strcmp (mountPoint, text) == 0
1332: && sscanf (mountedDevice, TC_MAP_DEV "%d", deviceNumber) == 1)
1333: {
1334: EnumMountPoints (NULL, NULL);
1335: return TRUE;
1336: }
1337: }
1338:
1339: if (!GetMountList ())
1340: return FALSE;
1341:
1342: for (i = 0; MountList[i].DeviceNumber != -1; i++)
1343: {
1344: MountListEntry *e = &MountList[i];
1345: if (e->DeviceNumber == -1)
1346: break;
1347:
1348: if (strcmp (text, e->VolumePath) == 0)
1349: {
1350: *deviceNumber = e->DeviceNumber;
1351: return TRUE;
1352: }
1353: }
1354:
1355: error ("%s not mounted\n", text);
1356: return FALSE;
1357: }
1358:
1359:
1.1.1.2 ! root 1360: BOOL CheckAdminPrivileges ()
! 1361: {
! 1362: char path[MAX_PATH];
! 1363: char *env;
! 1364:
! 1365: if (getuid () != 0 && geteuid () != 0)
! 1366: {
! 1367: error ("Administrator (root) privileges required\n");
! 1368: return FALSE;
! 1369: }
! 1370:
! 1371: if (getuid () != 0)
! 1372: {
! 1373: // Impersonate root to support executing of commands like mount
! 1374: setuid (0);
! 1375:
! 1376: env = getenv ("PATH");
! 1377:
! 1378: snprintf (path, sizeof (path),
! 1379: "%s%s/sbin:/usr/sbin:/bin",
! 1380: env ? env : "",
! 1381: env ? ":" : "");
! 1382:
! 1383: setenv ("PATH", path, 1);
! 1384: }
! 1385:
! 1386: return TRUE;
! 1387: }
! 1388:
! 1389:
! 1390: BOOL LockMemory ()
! 1391: {
! 1392: // Lock process memory
! 1393: if (mlockall (MCL_FUTURE) != 0)
! 1394: {
! 1395: perror ("Cannot prevent memory swapping: mlockall");
! 1396: return FALSE;
! 1397: }
! 1398:
! 1399: return TRUE;
! 1400: }
! 1401:
! 1402:
! 1403: int main (int argc, char **argv)
1.1 root 1404: {
1405: char *volumePath = NULL;
1406: char *mountPoint = NULL;
1407: char volumePathBuf[MAX_PATH];
1408: int i, o;
1409: int optIndex = 0;
1.1.1.2 ! root 1410: FILE *f;
1.1 root 1411:
1412: struct option longOptions[] = {
1413: {"device-number", required_argument, 0, 0},
1414: {"dismount", optional_argument, 0, 'd'},
1415: {"display-password", 0, 0, 0},
1416: {"keyfile", required_argument, 0, 'k'},
1417: {"keyfile-protected", required_argument, 0, 'K'},
1418: {"filesystem", required_argument, 0, 0},
1419: {"list", 0, 0, 'l'},
1420: {"help", 0, 0, 'h'},
1421: {"mount-options", required_argument, 0, 0},
1422: {"password", required_argument, 0, 'l'},
1423: {"password-tries", required_argument, 0, 0},
1424: {"protect-hidden", 0, 0, 'P'},
1425: {"read-only", 0, 0, 'r'},
1426: {"test", 0, 0, 0},
1427: {"update-time", 0, 0, 0},
1428: {"verbose", 0, 0, 'v'},
1429: {"version", 0, 0, 'V'},
1430: {0, 0, 0, 0}
1431: };
1432:
1.1.1.2 ! root 1433: // Make sure pipes will not use file descriptors <= STDERR_FILENO
! 1434: f = fdopen (STDIN_FILENO, "r");
! 1435: if (f == NULL)
! 1436: open ("/dev/null", 0);
! 1437:
! 1438: f = fdopen (STDOUT_FILENO, "w");
! 1439: if (f == NULL)
! 1440: open ("/dev/null", 0);
! 1441:
! 1442: f = fdopen (STDERR_FILENO, "w");
! 1443: if (f == NULL)
! 1444: open ("/dev/null", 0);
1.1 root 1445:
1446: signal (SIGHUP, OnSignal);
1447: signal (SIGINT, OnSignal);
1448: signal (SIGQUIT, OnSignal);
1449: signal (SIGABRT, OnSignal);
1450: signal (SIGPIPE, OnSignal);
1451: signal (SIGTERM, OnSignal);
1452:
1453: atexit (OnExit);
1454:
1455: while ((o = getopt_long (argc, argv, "dhk:K:lp:PrvV", longOptions, &optIndex)) != -1)
1456: {
1457: switch (o)
1458: {
1459: case 'd':
1460: // Dismount
1461: {
1462: int devNo;
1463:
1464: if (optind < argc)
1465: {
1466: if (!ToDeviceNumber (argv[optind++], &devNo))
1467: return 1;
1468:
1469: if (optind < argc)
1470: goto usage;
1471: }
1472: else
1473: devNo = -1;
1474:
1.1.1.2 ! root 1475: if (!CheckAdminPrivileges ())
! 1476: return 1;
! 1477:
1.1 root 1478: return DismountVolume (devNo) ? 0 : 1;
1479: }
1480:
1481: case 'l':
1482: // List
1483: {
1484: int devNo;
1485:
1486: if (optind < argc)
1487: {
1488: if (!ToDeviceNumber (argv[optind++], &devNo))
1489: return 1;
1490:
1491: if (optind < argc)
1492: goto usage;
1493: }
1494: else
1495: devNo = -1;
1496:
1.1.1.2 ! root 1497: if (!CheckAdminPrivileges ())
! 1498: return 1;
! 1499:
1.1 root 1500: return DumpMountList (devNo) ? 0 : 1;
1501: }
1502:
1503: case 'k':
1504: case 'K':
1505: // Keyfile
1506: {
1507: KeyFile *kf = malloc (sizeof (KeyFile));
1508: if (!kf)
1509: {
1510: perror ("malloc");
1511: return 1;
1512: }
1513: strncpy (kf->FileName, optarg, sizeof (kf->FileName));
1514: if (o == 'k')
1515: FirstKeyFile = KeyFileAdd (FirstKeyFile, kf);
1516: else
1517: FirstProtVolKeyFile = KeyFileAdd (FirstProtVolKeyFile, kf);
1518: }
1519: break;
1520:
1521:
1522: case 'p':
1523: // Password
1524: if (!CmdPasswordValid)
1525: {
1526: strncpy (CmdPassword.Text, optarg, sizeof (CmdPassword.Text));
1527: CmdPassword.Length = strlen (CmdPassword.Text);
1528: CmdPasswordValid = TRUE;
1529: }
1530: else if (!CmdPassword2Valid)
1531: {
1532: strncpy (CmdPassword2.Text, optarg, sizeof (CmdPassword2.Text));
1533: CmdPassword2.Length = strlen (CmdPassword2.Text);
1534: CmdPassword2Valid = TRUE;
1535: }
1536: break;
1537:
1538: case 'P':
1539: // Hidden volume protection
1540: ProtectHidden = TRUE;
1541: break;
1542:
1543: case 'r':
1544: ReadOnly = TRUE;
1545: break;
1546:
1547: case 'v':
1548: // Verbose
1549: Verbose++;
1550: break;
1551:
1552: case 'V':
1553: DumpVersion (stdout);
1554: return 0;
1555:
1556: case 'h':
1557: // Help
1558: DumpHelp ();
1559: return 0;
1560:
1561: case 0:
1562: if (strcmp ("display-password", longOptions[optIndex].name) == 0)
1563: {
1564: DisplayPassword = TRUE;
1565: break;
1566: }
1567:
1568: if (strcmp ("device-number", longOptions[optIndex].name) == 0)
1569: {
1570: if (sscanf (optarg, "%d", &UseDeviceNumber) == 1
1571: && UseDeviceNumber >= 0)
1572: break;
1573: else
1574: goto usage;
1575: }
1576:
1577: if (strcmp ("filesystem", longOptions[optIndex].name) == 0)
1578: {
1579: Filesystem = optarg;
1580: break;
1581: }
1582:
1583: if (strcmp ("mount-options", longOptions[optIndex].name) == 0)
1584: {
1585: MountOpts = optarg;
1586: break;
1587: }
1588:
1589: if (strcmp ("password-tries", longOptions[optIndex].name) == 0)
1590: {
1591: if (sscanf (optarg, "%d", &PasswordEntryTries) == 1)
1592: break;
1593: else
1594: goto usage;
1595: }
1596:
1597: if (strcmp ("test", longOptions[optIndex].name) == 0)
1598: {
1599: if (AutoTestAlgorithms ())
1600: {
1601: printf ("Self-tests of all algorithms passed.\n");
1602: return 0;
1603: }
1604:
1605: printf ("Self-tests of algorithms FAILED!\n");
1606: return 1;
1607: }
1608:
1609: if (strcmp ("update-time", longOptions[optIndex].name) == 0)
1610: {
1611: UpdateTime = TRUE;
1612: break;
1613: }
1614: goto usage;
1615:
1616: default:
1617: goto usage;
1618: }
1619: }
1620:
1621: if (optind >= argc)
1622: goto usage;
1623:
1624: if (optind < argc)
1625: volumePath = argv[optind++];
1626:
1627: if (optind < argc)
1628: mountPoint = argv[optind++];
1629:
1630: if (optind < argc)
1631: goto usage;
1632:
1.1.1.2 ! root 1633: if (!CheckAdminPrivileges ())
! 1634: return 1;
! 1635:
! 1636: LockMemory ();
! 1637:
1.1 root 1638: // Relative path => absolute
1639: if (volumePath[0] != '/')
1640: {
1641: char s[MAX_PATH];
1642: getcwd (s, sizeof (s));
1643: snprintf (volumePathBuf, sizeof (volumePathBuf), "%s/%s", s, volumePath);
1644: volumePath = volumePathBuf;
1645: }
1646:
1647: return MountVolume (volumePath, mountPoint) == FALSE;
1648:
1649: usage:
1650: DumpUsage (stderr);
1651:
1652: return 1;
1653: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.