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

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

unix.superglobalmegacorp.com

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