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