Annotation of truecrypt/linux/cli/cli.c, revision 1.1.1.6

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.