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

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

unix.superglobalmegacorp.com

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