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

1.1     ! root        1: /* 
        !             2: Copyright (c) 2004-2005 TrueCrypt Foundation. All rights reserved. 
        !             3: 
        !             4: Covered by TrueCrypt License 2.0 the full text of which is contained in the file
        !             5: License.txt included in TrueCrypt binary and source code distribution archives. 
        !             6: */
        !             7: 
        !             8: //FIXME remove stale dmsetup device
        !             9: #define _LARGEFILE_SOURCE      1
        !            10: #define _FILE_OFFSET_BITS      64
        !            11: 
        !            12: #include <getopt.h>
        !            13: #include <inttypes.h>
        !            14: #include <stdarg.h>
        !            15: #include <stdio.h>
        !            16: #include <stdlib.h>
        !            17: #include <sys/mman.h>
        !            18: #include <sys/stat.h>
        !            19: #include <sys/types.h>
        !            20: #include <sys/wait.h>
        !            21: #include <termios.h>
        !            22: #include <time.h>
        !            23: #include <unistd.h>
        !            24: #include <utime.h>
        !            25: 
        !            26: #include "Tcdefs.h"
        !            27: #include "Keyfiles.h"
        !            28: #include "Volumes.h"
        !            29: #include "Tests.h"
        !            30: #include "Dm-target.h"
        !            31: 
        !            32: #define MAX_VOLUMES    256
        !            33: #define MAX_MINOR 256
        !            34: 
        !            35: #undef MAX_PATH
        !            36: #define MAX_PATH 260
        !            37: #define MAX_PATH_STR "259"
        !            38: 
        !            39: #define TC_MAP_DEV "/dev/mapper/truecrypt"
        !            40: #define LOOP_DEV "/dev/loop"
        !            41: 
        !            42: #define error(fmt, args...) fprintf (stderr, "truecrypt: " fmt, ## args)
        !            43: 
        !            44: typedef struct
        !            45: {
        !            46:        int DeviceNumber;
        !            47:        int DeviceMajor;
        !            48:        int DeviceMinor;
        !            49:        uint64_t VolumeSize;
        !            50:        char VolumePath[MAX_PATH];
        !            51:        int EA;
        !            52:        BOOL Hidden;
        !            53:        uint64_t ReadOnlyStart;
        !            54:        uint64_t ReadOnlyEnd;
        !            55:        uint64_t ModTime;
        !            56:        uint64_t AcTime;
        !            57:        int Flags;
        !            58: } MountListEntry;
        !            59: 
        !            60: static MountListEntry MountList[MAX_VOLUMES];
        !            61: static BOOL MountListValid = FALSE;
        !            62: 
        !            63: static BOOL DisplayPassword = FALSE;
        !            64: static char *Filesystem = NULL;
        !            65: static char *MountOpts = NULL;
        !            66: static int PasswordEntryTries = 3;
        !            67: static Password CmdPassword;
        !            68: static Password CmdPassword2;
        !            69: static BOOL CmdPasswordValid = FALSE;
        !            70: 
        !            71: static BOOL CmdPassword2Valid = FALSE;
        !            72: static int UseDeviceNumber = -1;
        !            73: static BOOL ProtectHidden = FALSE;
        !            74: static BOOL ReadOnly = FALSE;
        !            75: static BOOL UpdateTime = FALSE;
        !            76: static int Verbose = 0;
        !            77: 
        !            78: static BOOL    IsTerminal = FALSE;
        !            79: static struct termios TerminalAttributes;
        !            80: static Password password;
        !            81: static KeyFile *FirstKeyFile;
        !            82: static KeyFile *FirstProtVolKeyFile;
        !            83: 
        !            84: 
        !            85: static void SecurityCleanup ()
        !            86: {
        !            87:        burn (&password, sizeof (password));
        !            88:        burn (&CmdPassword, sizeof (CmdPassword));
        !            89:        burn (&CmdPassword2, sizeof (CmdPassword2));
        !            90: }
        !            91: 
        !            92: 
        !            93: static void OnSignal (int signal)
        !            94: {
        !            95:        SecurityCleanup ();
        !            96: 
        !            97:        if (IsTerminal)
        !            98:        {
        !            99:                tcsetattr (0, TCSANOW, &TerminalAttributes);
        !           100:                puts ("");
        !           101:        }
        !           102: 
        !           103:        _exit (1);
        !           104: }
        !           105: 
        !           106: 
        !           107: static void OnExit ()
        !           108: {
        !           109:        SecurityCleanup ();
        !           110: }
        !           111: 
        !           112: 
        !           113: static BOOL WaitChild (BOOL quiet, char *execName)
        !           114: {
        !           115:        int status;
        !           116:        if (wait (&status) == -1)
        !           117:        {
        !           118:                perror ("wait");
        !           119:                return FALSE;
        !           120:        }
        !           121: 
        !           122:        if (!WIFEXITED (status)
        !           123:                || (WIFEXITED (status) && WEXITSTATUS (status)))
        !           124:        {
        !           125:                if (!quiet && Verbose >= 3)
        !           126:                        error ("Error: %s returned %d\n", execName, WEXITSTATUS (status));
        !           127:                return FALSE;
        !           128:        }
        !           129: 
        !           130:        return TRUE;
        !           131: }
        !           132: 
        !           133: 
        !           134: BOOL Execute (BOOL quiet, char *execName, ...)
        !           135: {
        !           136:        int pid;
        !           137:        va_list vl;
        !           138:        va_start (vl, execName);
        !           139: 
        !           140:        pid = fork ();
        !           141:        if (pid == -1)
        !           142:        {
        !           143:                perror ("fork");
        !           144:                goto err;
        !           145:        }
        !           146:        else if (pid == 0)
        !           147:        {
        !           148:                char *args[32];
        !           149:                int i = 1;
        !           150: 
        !           151:                SecurityCleanup ();
        !           152: 
        !           153:                if (Verbose >= 3)
        !           154:                        printf ("Executing %s", execName);
        !           155: 
        !           156:                args[0] = execName;
        !           157:                while (i < 32 && (args[i] = (va_arg (vl, char *))))
        !           158:                {
        !           159:                        if (Verbose >= 3)
        !           160:                                printf (" %s", args[i]);
        !           161:                        i++;
        !           162:                }
        !           163: 
        !           164:                if (Verbose >= 3)
        !           165:                        puts ("");
        !           166: 
        !           167:                if (quiet)
        !           168:                {
        !           169:                        // >/dev/null is safer than >&-
        !           170:                        int i = open ("/dev/null", 0);
        !           171:                        if (i == -1)
        !           172:                        {
        !           173:                                perror ("open /dev/null");
        !           174:                                _exit (1);
        !           175:                        }
        !           176: 
        !           177:                        dup2 (i, STDOUT_FILENO);
        !           178:                        dup2 (i, STDERR_FILENO);
        !           179:                }
        !           180: 
        !           181:                execvp (execName, args);
        !           182: 
        !           183:                fprintf (stderr, "%s ", execName);
        !           184:                perror ("execlp");
        !           185:                _exit (1);
        !           186:        }
        !           187: 
        !           188:        if (!WaitChild (quiet, execName))
        !           189:                goto err;
        !           190: 
        !           191:        va_end (vl);
        !           192:        return TRUE;
        !           193: err:
        !           194:        va_end (vl);
        !           195:        return FALSE;
        !           196: }
        !           197: 
        !           198: 
        !           199: static BOOL IsFile (char *path)
        !           200: {
        !           201:        struct stat st;
        !           202:        if (stat (path, &st) != 0)
        !           203:                return FALSE;
        !           204: 
        !           205:        return S_ISREG (st.st_mode);
        !           206: }
        !           207: 
        !           208: 
        !           209: static BOOL IsBlockDevice (char *path)
        !           210: {
        !           211:        struct stat st;
        !           212:        if (stat (path, &st) != 0)
        !           213:                return FALSE;
        !           214: 
        !           215:        return S_ISBLK (st.st_mode);
        !           216: }
        !           217: 
        !           218: 
        !           219: static BOOL RestoreFileTime (char *path, time_t modTime, time_t acTime)
        !           220: {
        !           221:        struct utimbuf t;
        !           222: 
        !           223:        t.actime = acTime;
        !           224:        t.modtime = modTime;
        !           225: 
        !           226:        return utime (path, &t) != 0;
        !           227: }
        !           228: 
        !           229: 
        !           230: static BOOL LoadKernelModule ()
        !           231: {
        !           232:        char s[2048];   
        !           233:        FILE *m;
        !           234:        
        !           235:        m = fopen ("/proc/modules", "r");
        !           236:        if (m == NULL)
        !           237:        {
        !           238:                perror ("fopen /proc/modules");
        !           239:                return FALSE;
        !           240:        }
        !           241: 
        !           242:        while (fgets (s, sizeof (s), m))
        !           243:        {
        !           244:                if (strstr (s, "truecrypt ") == s)
        !           245:                {
        !           246:                        fclose (m);
        !           247:                        return TRUE;
        !           248:                }
        !           249:        }
        !           250: 
        !           251:        fclose (m);
        !           252: 
        !           253:        if (!Execute (FALSE, "modprobe", "truecrypt", NULL))
        !           254:        {
        !           255:                error ("Failed to load TrueCrypt kernel module\n");
        !           256:                return FALSE;
        !           257:        }
        !           258:        return TRUE;
        !           259: }
        !           260: 
        !           261: 
        !           262: static BOOL UnloadKernelModule (BOOL quiet)
        !           263: {
        !           264:        // rmmod is used instead of modprobe to prevent unload of dependencies
        !           265:        return Execute (quiet, "rmmod", "truecrypt", NULL);
        !           266: }
        !           267: 
        !           268: 
        !           269: static BOOL CheckKernelModuleVersion (BOOL wait)
        !           270: {
        !           271:        FILE *p;
        !           272:        int pfd[2];
        !           273:        int pid, res;
        !           274:        int i, dummy;
        !           275:        char s[2048];
        !           276:        int ver1 = 0, ver2 = 0, ver3 = 0;
        !           277:        int tries = 10;
        !           278: 
        !           279:        do
        !           280:        {
        !           281:                pipe (pfd);
        !           282:                pid = fork ();
        !           283: 
        !           284:                if (pid == -1)
        !           285:                {
        !           286:                        perror ("fork");
        !           287:                        return FALSE;
        !           288:                }
        !           289:                else if (pid == 0)
        !           290:                {
        !           291:                        SecurityCleanup ();
        !           292: 
        !           293:                        dup2 (pfd[1], STDOUT_FILENO);
        !           294:                        close (pfd[0]);
        !           295:                        close (STDERR_FILENO);
        !           296: 
        !           297:                        execlp ("dmsetup", "dmsetup", "targets", NULL);
        !           298: 
        !           299:                        perror ("execlp dmsetup");
        !           300:                        _exit (1);
        !           301:                }
        !           302: 
        !           303:                close (pfd[1]);
        !           304:                p = fdopen (pfd[0], "r");
        !           305:                if (p == NULL)
        !           306:                {
        !           307:                        perror ("fdopen");
        !           308:                        return FALSE;
        !           309:                }
        !           310: 
        !           311:                while (fgets (s, sizeof (s), p))
        !           312:                {
        !           313:                        char name[32];
        !           314: 
        !           315:                        if (sscanf (s, "%31s v%d.%d.%d", &name, &ver1, &ver2, &ver3) == 4
        !           316:                                && strcmp (name, "truecrypt") == 0)
        !           317:                        {
        !           318:                                fclose (p);
        !           319:                                WaitChild (FALSE, "dmsetup");
        !           320: 
        !           321:                                if (ver1 == VERSION_NUM1 && ver2 == VERSION_NUM2 && ver3 == VERSION_NUM3)
        !           322:                                        return TRUE;
        !           323: 
        !           324:                                error ("Incorrect version of kernel module loaded - version %s required\n", VERSION_STRING);
        !           325:                                UnloadKernelModule (TRUE);
        !           326:                                return FALSE;
        !           327:                        }
        !           328:                }
        !           329: 
        !           330:                fclose (p);
        !           331:                WaitChild (FALSE, "dmsetup");
        !           332: 
        !           333:                // Target registration may take some time
        !           334:                if (wait)
        !           335:                        usleep (100 * 1000);
        !           336:                else
        !           337:                        break;
        !           338: 
        !           339:        } while (tries--);
        !           340: 
        !           341:        error ("Kernel module not loaded\n");
        !           342:        return FALSE;
        !           343: }
        !           344: 
        !           345: 
        !           346: static BOOL GetMountList ()
        !           347: {
        !           348:        FILE *p;
        !           349:        int pfd[2];
        !           350:        int pid, res;
        !           351:        int i, dummy;
        !           352: 
        !           353:        if (MountListValid)
        !           354:                return TRUE;
        !           355: 
        !           356:        MountList[0].DeviceNumber = -1;
        !           357: 
        !           358:        pipe (pfd);
        !           359:        pid = fork ();
        !           360: 
        !           361:        if (pid == -1)
        !           362:        {
        !           363:                perror ("fork");
        !           364:                goto err;
        !           365:        }
        !           366:        else if (pid == 0)
        !           367:        {
        !           368:                SecurityCleanup ();
        !           369: 
        !           370:                dup2 (pfd[1], STDOUT_FILENO);
        !           371:                close (pfd[0]);
        !           372:                close (STDERR_FILENO);
        !           373: 
        !           374:                execlp ("dmsetup", "dmsetup", "table", NULL);
        !           375: 
        !           376:                perror ("execlp dmsetup");
        !           377:                _exit (1);
        !           378:        }
        !           379: 
        !           380:        close (pfd[1]);
        !           381:        p = fdopen (pfd[0], "r");
        !           382:        if (p == NULL)
        !           383:        {
        !           384:                perror ("fdopen");
        !           385:                goto err;
        !           386:        }
        !           387: 
        !           388:        for (i = 0; i < MAX_VOLUMES; i++)
        !           389:        {
        !           390:                char s[2048];
        !           391:                MountListEntry *e = &MountList[i];
        !           392: 
        !           393:                if (!fgets (s, sizeof (s), p))
        !           394:                        break;
        !           395: 
        !           396:                if (sscanf (s, "truecrypt%d: 0 %lld truecrypt %d 0 0 %d:%d %lld %lld %lld %lld %lld %d %" MAX_PATH_STR "s\n",
        !           397:                        &e->DeviceNumber,
        !           398:                        &e->VolumeSize,
        !           399:                        &e->EA,
        !           400:                        &e->DeviceMajor,
        !           401:                        &e->DeviceMinor,
        !           402:                        &e->Hidden,
        !           403:                        &e->ReadOnlyStart,
        !           404:                        &e->ReadOnlyEnd,
        !           405:                        &e->ModTime,
        !           406:                        &e->AcTime,
        !           407:                        &e->Flags,
        !           408:                        e->VolumePath) == 12)
        !           409:                {
        !           410:                        e->Hidden = e->Hidden == 1 ? FALSE : TRUE;
        !           411:                        e->VolumeSize *= SECTOR_SIZE;
        !           412:                }
        !           413:                else
        !           414:                        i--;
        !           415:        }
        !           416: 
        !           417:        MountList[i].DeviceNumber = -1;
        !           418: 
        !           419:        fclose (p);
        !           420:        if (!WaitChild (TRUE, "dmsetup"))
        !           421:                goto err;
        !           422: 
        !           423:        MountListValid = TRUE;
        !           424:        return TRUE;
        !           425: 
        !           426: err:
        !           427:        MountList[0].DeviceNumber = -1;
        !           428:        return FALSE;
        !           429: }
        !           430: 
        !           431: 
        !           432: static BOOL IsVolumeMounted (char *volumePath)
        !           433: {
        !           434:        int i;
        !           435:        if (!GetMountList ())
        !           436:                return FALSE;
        !           437: 
        !           438:        for (i = 0; MountList[i].DeviceNumber != -1; i++)
        !           439:                if (strcmp (volumePath, MountList[i].VolumePath) == 0)
        !           440:                        return TRUE;
        !           441: 
        !           442:        return FALSE;
        !           443: }
        !           444: 
        !           445: 
        !           446: static int GetFreeMapDevice ()
        !           447: {
        !           448:        FILE *p;
        !           449:        char cmd[128];
        !           450:        int n;
        !           451: 
        !           452:        if (!GetMountList ())
        !           453:                return -1;
        !           454: 
        !           455:        for (n = 0; n < MAX_MINOR; n++)
        !           456:        {
        !           457:                int j = 0;
        !           458:                while (MountList[j].DeviceNumber != -1)
        !           459:                {
        !           460:                        if (MountList[j].DeviceNumber == n)
        !           461:                                break;
        !           462:                        j++;
        !           463:                }
        !           464: 
        !           465:                if (MountList[j].DeviceNumber == -1)
        !           466:                        return n;
        !           467:        }
        !           468: 
        !           469:        return -1;
        !           470: }
        !           471: 
        !           472: 
        !           473: static BOOL DeleteLoopDevice (int loopDeviceNo)
        !           474: {
        !           475:        char dev[32];
        !           476:        BOOL r;
        !           477: 
        !           478:        sprintf (dev, LOOP_DEV "%d", loopDeviceNo);
        !           479:        if (!IsBlockDevice (dev))
        !           480:                sprintf (dev, LOOP_DEV "/%d", loopDeviceNo);
        !           481: 
        !           482:        r = Execute (FALSE, "losetup", "-d", dev, NULL);
        !           483: 
        !           484:        if (r && Verbose > 1)
        !           485:                printf ("Detached %s\n", dev);
        !           486: 
        !           487:        return r;
        !           488: }
        !           489: 
        !           490: 
        !           491: static BOOL OpenVolume (char *volumePath, Password *password, PCRYPTO_INFO *cryptoInfo, uint64_t *startSector, uint64_t *totalSectors, time_t *modTime, time_t *acTime)
        !           492: {
        !           493:        char header[SECTOR_SIZE];
        !           494:        uint64_t r;
        !           495:        FILE *f = NULL;
        !           496:        struct stat volumeStat;
        !           497: 
        !           498:        if (stat (volumePath, &volumeStat) != 0)
        !           499:        {
        !           500:                perror ("Cannot open volume");
        !           501:                volumeStat.st_ctime = 0;
        !           502:                goto err;
        !           503:        }
        !           504: 
        !           505:        f = fopen (volumePath, "r");
        !           506:        if (!f)
        !           507:        {
        !           508:                perror ("Cannot open volume");
        !           509:                goto err;
        !           510:        }
        !           511: 
        !           512:        // Normal header
        !           513:        if (fread (header, 1, SECTOR_SIZE, f) != SECTOR_SIZE)
        !           514:        {
        !           515:                perror ("Cannot read volume header");
        !           516:                goto err;
        !           517:        }
        !           518: 
        !           519:        fseek (f, 0, SEEK_END);
        !           520:        *totalSectors = ftello (f) / SECTOR_SIZE - 1;
        !           521: 
        !           522:        r = VolumeReadHeader (header, password, cryptoInfo);
        !           523: 
        !           524:        if (r != 0)
        !           525:        {
        !           526:                // Hidden header
        !           527:                if (fseek (f, -HIDDEN_VOL_HEADER_OFFSET, SEEK_END) == -1
        !           528:                        || fread (header, 1, SECTOR_SIZE, f) != SECTOR_SIZE)
        !           529:                {
        !           530:                        perror ("Cannot read volume header");
        !           531:                        goto err;
        !           532:                }
        !           533: 
        !           534:                r = VolumeReadHeader (header, password, cryptoInfo);
        !           535: 
        !           536:                if (r != 0)
        !           537:                {
        !           538:                        if (IsTerminal)
        !           539:                                puts ("Incorrect password or not a TrueCrypt volume");
        !           540:                        else
        !           541:                                error ("Incorrect password or not a TrueCrypt volume\n");
        !           542: 
        !           543:                        goto err;
        !           544:                }
        !           545: 
        !           546:                *startSector = (ftello (f) 
        !           547:                        + SECTOR_SIZE * 2 
        !           548:                        - (*cryptoInfo)->hiddenVolumeSize 
        !           549:                        - HIDDEN_VOL_HEADER_OFFSET) / SECTOR_SIZE;
        !           550: 
        !           551:                *totalSectors = (*cryptoInfo)->hiddenVolumeSize / SECTOR_SIZE;
        !           552:        }
        !           553:        else
        !           554:                *startSector = 1;
        !           555: 
        !           556:        fclose (f);
        !           557: 
        !           558:        if (!UpdateTime)
        !           559:                RestoreFileTime (volumePath, volumeStat.st_mtime, volumeStat.st_atime);
        !           560: 
        !           561:        *modTime = volumeStat.st_mtime;
        !           562:        *acTime = volumeStat.st_atime;
        !           563:        return TRUE;
        !           564: 
        !           565: err:
        !           566:        *cryptoInfo = NULL;
        !           567: 
        !           568:        if (f)
        !           569:                fclose (f);
        !           570: 
        !           571:        if (volumeStat.st_ctime != 0 && !UpdateTime)
        !           572:                RestoreFileTime (volumePath, volumeStat.st_mtime, volumeStat.st_atime);
        !           573: 
        !           574:        return FALSE;
        !           575: }
        !           576: 
        !           577: 
        !           578: static void GetPassword (char *prompt, char *volumePath, Password *password)
        !           579: {
        !           580:        struct termios noEcho;
        !           581: 
        !           582:        if (tcgetattr (0, &TerminalAttributes) == 0)
        !           583:        {
        !           584:                IsTerminal = TRUE;
        !           585:                noEcho = TerminalAttributes;
        !           586: 
        !           587:                if (!DisplayPassword)
        !           588:                {
        !           589:                        noEcho.c_lflag &= ~ECHO;
        !           590:                        if (tcsetattr (0, TCSANOW, &noEcho) != 0)
        !           591:                                error ("Failed to turn terminal echo off\n");
        !           592:                }
        !           593: 
        !           594:                printf (prompt, volumePath);
        !           595:        }
        !           596: 
        !           597:        if (fgets (password->Text, sizeof (password->Text), stdin))
        !           598:        {
        !           599:                char *newl = strchr (password->Text, '\n');
        !           600:                if (newl) newl[0] = 0;
        !           601: 
        !           602:                password->Length = strlen (password->Text);
        !           603:        }
        !           604:        else
        !           605:                password->Length = 0;
        !           606: 
        !           607:        if (IsTerminal && !DisplayPassword)
        !           608:        {
        !           609:                tcsetattr (0, TCSANOW, &TerminalAttributes);
        !           610:                puts ("");
        !           611:        }
        !           612: }
        !           613: 
        !           614: 
        !           615: static BOOL MountVolume (char *volumePath, char *mountPoint)
        !           616: {
        !           617:        char hostDevice[MAX_PATH];
        !           618:        char mapDevice[MAX_PATH];
        !           619:        int loopDevNo = -1;
        !           620:        PCRYPTO_INFO ci = NULL;
        !           621:        uint64_t startSector, totalSectors;
        !           622:        uint64_t readOnlyStartSector = 0, readOnlySectors = 0;
        !           623:        int pfd[2];
        !           624:        int pid, res, devNo;
        !           625:        time_t modTime, acTime;
        !           626:        FILE *f, *w;
        !           627:        int flags;
        !           628:        int i;
        !           629:        int tries = PasswordEntryTries;
        !           630: 
        !           631:        if (!AutoTestAlgorithms ())
        !           632:        {
        !           633:                error ("Self-tests of algorithms FAILED!\n");
        !           634:                return FALSE;
        !           635:        }
        !           636: 
        !           637:        if (IsVolumeMounted (volumePath))
        !           638:        {
        !           639:                error ("Volume already mounted\n");
        !           640:                return FALSE;
        !           641:        }
        !           642: 
        !           643:        do
        !           644:        {
        !           645:                Password *pw = &password;
        !           646: 
        !           647:                if (!CmdPasswordValid)
        !           648:                        GetPassword ("Enter password for '%s': ", volumePath, &password);
        !           649:                else
        !           650:                        pw = &CmdPassword;
        !           651: 
        !           652:                if (FirstKeyFile && !KeyFilesApply (pw, FirstKeyFile, !UpdateTime))
        !           653:                {
        !           654:                        error ("Error while processing keyfiles\n");
        !           655:                        goto err;
        !           656:                }
        !           657: 
        !           658:                if (OpenVolume (volumePath, pw, &ci, &startSector, &totalSectors, &modTime, &acTime))
        !           659:                        break;
        !           660:                else
        !           661:                        totalSectors = 0;
        !           662: 
        !           663:        } while (!CmdPasswordValid && IsTerminal && --tries > 0);
        !           664: 
        !           665:        if (totalSectors == 0)
        !           666:                goto err;
        !           667: 
        !           668:        // Hidden volume protection
        !           669:        if (ProtectHidden)
        !           670:        {
        !           671:                PCRYPTO_INFO ciH = NULL;
        !           672:                uint64_t startSectorH, totalSectorsH;
        !           673: 
        !           674:                tries = PasswordEntryTries;
        !           675:                do
        !           676:                {
        !           677:                        Password *pw = &password;
        !           678: 
        !           679:                        if (!CmdPassword2Valid)
        !           680:                                GetPassword ("Enter hidden volume password: ", "", &password);
        !           681:                        else
        !           682:                                pw = &CmdPassword2;
        !           683: 
        !           684:                        if (FirstProtVolKeyFile && !KeyFilesApply (pw, FirstProtVolKeyFile, !UpdateTime))
        !           685:                        {
        !           686:                                error ("Error while processing keyfiles\n");
        !           687:                                goto err;
        !           688:                        }
        !           689: 
        !           690:                        if (OpenVolume (volumePath, pw, &ciH, &startSectorH, &totalSectorsH, &modTime, &acTime))
        !           691:                        {
        !           692:                                readOnlyStartSector = startSectorH;
        !           693:                                readOnlySectors = startSectorH + totalSectorsH;
        !           694:                                break;
        !           695:                        }
        !           696: 
        !           697:                } while (!CmdPassword2Valid && IsTerminal && --tries > 0);
        !           698:                
        !           699:                if (ciH)
        !           700:                        crypto_close (ciH);
        !           701: 
        !           702:                if (readOnlySectors == 0)
        !           703:                        goto err;
        !           704:        }
        !           705: 
        !           706:        // Headers decrypted
        !           707: 
        !           708:        // Loopback
        !           709:        if (IsFile (volumePath))
        !           710:        {
        !           711:                int i;
        !           712: 
        !           713:                for (i = 0; i < MAX_MINOR; i++)
        !           714:                {
        !           715:                        snprintf (hostDevice, sizeof (hostDevice), LOOP_DEV "%d", i);
        !           716: 
        !           717:                        if (!IsBlockDevice (hostDevice))
        !           718:                        {
        !           719:                                snprintf (hostDevice, sizeof (hostDevice), LOOP_DEV "/%d", i);
        !           720:                                if (!IsBlockDevice (hostDevice))
        !           721:                                        continue;
        !           722:                        }
        !           723: 
        !           724:                        if (Execute (TRUE, "losetup", hostDevice, volumePath, NULL))
        !           725:                                break;
        !           726:                }
        !           727: 
        !           728:                if (i >= MAX_MINOR)
        !           729:                {
        !           730:                        error ("No free loopback device available for file-hosted volume\n");
        !           731:                        goto err;
        !           732:                }
        !           733: 
        !           734:                loopDevNo = i;
        !           735: 
        !           736:                if (Verbose > 1)
        !           737:                        printf ("Attached %s to %s\n", volumePath, hostDevice);
        !           738: 
        !           739:        }
        !           740:        else
        !           741:                strncpy (hostDevice, volumePath, sizeof (hostDevice));
        !           742: 
        !           743:        // Load kernel module
        !           744:        if (!LoadKernelModule ())
        !           745:                goto err;
        !           746: 
        !           747:        if (!CheckKernelModuleVersion (TRUE))
        !           748:                goto err;
        !           749: 
        !           750:        // dmsetup
        !           751:        devNo = UseDeviceNumber == -1 ? GetFreeMapDevice () : UseDeviceNumber;
        !           752:        if (devNo == -1)
        !           753:        {
        !           754:                error ("Maximum number of volumes mounted\n");
        !           755:                goto err;
        !           756:        }
        !           757: 
        !           758:        sprintf (mapDevice, "truecrypt%d", devNo);
        !           759: 
        !           760:        pipe (pfd);
        !           761:        pid = fork ();
        !           762: 
        !           763:        if (pid == -1)
        !           764:        {
        !           765:                perror ("fork");
        !           766:                goto err;
        !           767:        }
        !           768:        else if (pid == 0)
        !           769:        {
        !           770:                SecurityCleanup ();
        !           771: 
        !           772:                close (pfd[1]);
        !           773:                dup2 (pfd[0], STDIN_FILENO);
        !           774: 
        !           775:                execlp ("dmsetup", "dmsetup", "create", mapDevice, NULL);
        !           776: 
        !           777:                perror ("execlp dmsetup");
        !           778:                _exit (1);
        !           779:        }
        !           780: 
        !           781:        close (pfd[0]);
        !           782:        w = fdopen (pfd[1], "a");
        !           783:        if (w == NULL)
        !           784:        {
        !           785:                perror ("fdopen");
        !           786:                goto err;
        !           787:        }
        !           788: 
        !           789:        fprintf (w, "0 %lld truecrypt %d ", totalSectors, ci->ea);
        !           790: 
        !           791:        for (i = DISK_IV_SIZE; i < EAGetKeySize (ci->ea) + DISK_IV_SIZE; i++)
        !           792:                fprintf (w, "%02x", ci->master_key[i]);
        !           793: 
        !           794:        fprintf (w, " ");
        !           795: 
        !           796:        for (i = 0; i < (int)sizeof (ci->iv); i++)
        !           797:                fprintf (w, "%02x", ci->iv[i]);
        !           798: 
        !           799:        flags = 0;
        !           800: 
        !           801:        if (ReadOnly)
        !           802:                flags |= FLAG_READ_ONLY;
        !           803:        else if (ProtectHidden)
        !           804:                flags |= FLAG_HIDDEN_VOLUME_PROTECTION;
        !           805: 
        !           806:        fprintf (w, " %s %lld %lld %lld %lld %lld %d %s\n",
        !           807:                hostDevice,
        !           808:                startSector,
        !           809:                readOnlyStartSector,
        !           810:                readOnlySectors,
        !           811:                (uint64_t) modTime,
        !           812:                (uint64_t) acTime,
        !           813:                flags,
        !           814:                volumePath);
        !           815: 
        !           816:        fclose (w);
        !           817: 
        !           818:        if (!WaitChild (FALSE, "dmsetup"))
        !           819:        {
        !           820:                Execute (TRUE, "dmsetup", "remove", mapDevice, NULL);
        !           821:                goto err;
        !           822:        }
        !           823: 
        !           824:        sprintf (mapDevice, TC_MAP_DEV "%d", devNo);
        !           825: 
        !           826:        if (Verbose >= 1)
        !           827:                printf ("Mapped %s as %s\n", volumePath, mapDevice);
        !           828: 
        !           829:        // Mount
        !           830:        if (mountPoint)
        !           831:        {
        !           832:                char fstype[64], opts[128];
        !           833: 
        !           834:                strcpy (fstype, "-t");
        !           835:                if (Filesystem)
        !           836:                        strncat (fstype, Filesystem, sizeof (fstype) - 3);
        !           837:                else
        !           838:                        strcat (fstype, "auto");
        !           839: 
        !           840:                strcpy (opts, ReadOnly ? "-oro" : "-orw");
        !           841:                if (MountOpts)
        !           842:                {
        !           843:                        strcat (opts, ",");
        !           844:                        strncat (opts, MountOpts, sizeof (opts) - 6);
        !           845:                }
        !           846: 
        !           847:                if (!Execute (FALSE, "mount", fstype, opts, mapDevice, mountPoint, NULL))
        !           848:                {
        !           849:                        error ("Mount failed\n");
        !           850:                        loopDevNo = -1;
        !           851:                        goto err;
        !           852:                }
        !           853: 
        !           854:                if (Verbose >= 1)
        !           855:                        printf ("Mounted %s at %s\n", mapDevice, mountPoint);
        !           856:        }
        !           857: 
        !           858:        crypto_close (ci);
        !           859: 
        !           860:        return TRUE;
        !           861: 
        !           862: err:
        !           863:        if (ci)
        !           864:                crypto_close (ci);
        !           865: 
        !           866:        if (loopDevNo != -1)
        !           867:                DeleteLoopDevice (loopDevNo);
        !           868: 
        !           869:        UnloadKernelModule (TRUE);
        !           870: 
        !           871:        return FALSE;
        !           872: }
        !           873: 
        !           874: 
        !           875: static void DumpVersion (FILE *f)
        !           876: {
        !           877:        fprintf (f, 
        !           878: "truecrypt %s\n\n"
        !           879: "Copyright (C) 2004-2005 TrueCrypt Foundation. All Rights Reserved.\n\
        !           880: Copyright (C) 1998-2000 Paul Le Roux. All Rights Reserved.\n\
        !           881: Copyright (C) 2004 TrueCrypt Team. All Rights Reserved.\n\
        !           882: Copyright (C) 1995-1997 Eric Young. All Rights Reserved.\n\
        !           883: Copyright (C) 1999-2004 Dr. Brian Gladman. All Rights Reserved.\n\
        !           884: Copyright (C) 2001 Markus Friedl. All Rights Reserved.\n\n"
        !           885:        , VERSION_STRING);
        !           886: }
        !           887: 
        !           888: 
        !           889: static void DumpUsage (FILE *f)
        !           890: {
        !           891:        fprintf (f,
        !           892: "Usage: truecrypt [OPTIONS] VOLUME_PATH [MOUNT_DIRECTORY]\n"
        !           893: "   or: truecrypt [OPTIONS] -d | --dismount | -l | --list [MAPPED_VOLUME]\n"
        !           894: "   or: truecrypt -h | --help | --test | -V | --version\n"
        !           895: "\nCommands:\n"
        !           896: " VOLUME_PATH                         Map volume\n"
        !           897: " VOLUME_PATH MOUNT_DIRECTORY         Map and mount volume\n"
        !           898: " -d, --dismount [MAPPED_VOLUME]      Dismount and unmap volume\n"
        !           899: " -h, --help                          Display help\n"
        !           900: " -l, --list [MAPPED_VOLUME]          List mapped volumes\n"
        !           901: "     --test                          Test algorithms\n"
        !           902: " -V, --version                       Display version information\n"
        !           903: "\nOptions:\n"
        !           904: "     --device-number NUMBER          Map volume as device number\n"
        !           905: "     --display-password              Display password while typing\n"
        !           906: "     --filesystem TYPE               Filesystem type to mount\n"
        !           907: " -k, --keyfile FILE|DIR              Keyfile for volume\n"
        !           908: " -K, --keyfile-protected FILE|DIR    Keyfile for protected volume\n"
        !           909: " -p, --password PASSWORD             Password for volume\n"
        !           910: "     --password-tries NUMBER         Password entry tries\n"
        !           911: " -P, --protect-hidden                Protect hidden volume\n"
        !           912: "     --update-time                   Do not preserve timestamps\n"
        !           913: " -r, --read-only                     Map/Mount read-only\n"
        !           914: "     --mount-options OPTIONS         Mount options\n"
        !           915: " -v, --verbose                       Verbose output\n"
        !           916: "\n MAPPED_VOLUME = DEVICE_NUMBER | DEVICE_NAME | MOUNT_POINT | VOLUME_PATH\n"
        !           917: "For a detailed help use --help or see truecrypt(1) man page.\n"
        !           918: );
        !           919: }
        !           920: 
        !           921: static void DumpHelp ()
        !           922: {
        !           923:        fprintf (stdout,
        !           924: "Manages encrypted TrueCrypt volumes, which can be mapped as virtual block\n"
        !           925: "devices and used as any other standard block device. All data being read\n"
        !           926: "from a mapped TrueCrypt volume is transparently decrypted and all data being\n"
        !           927: "written to it is transparently encrypted.\n"
        !           928: "\n"
        !           929: "Usage: truecrypt [OPTIONS] VOLUME_PATH [MOUNT_DIRECTORY]\n"
        !           930: "   or: truecrypt [OPTIONS] -d | --dismount | -l | --list [MAPPED_VOLUME]\n"
        !           931: "   or: truecrypt -h | --help | --test | -V | --version\n"
        !           932: "\n"
        !           933: "Options:\n"
        !           934: "\n"
        !           935: "VOLUME_PATH [MOUNT_DIRECTORY]\n"
        !           936: " Open a TrueCrypt volume specified by VOLUME_PATH and map it as a block device\n"
        !           937: " /dev/mapper/truecryptN. N is the first available device number if not\n"
        !           938: " otherwise specified with --device-number. The filesystem of the mapped volume\n"
        !           939: " is mounted at MOUNT_DIRECTORY if specified.\n"
        !           940: "\n"
        !           941: "-d, --dismount [MAPPED_VOLUME]\n"
        !           942: " Dismount and unmap mapped volumes. If MAPPED_VOLUME is not specified, all\n"
        !           943: " volumes are dismounted and unmapped. See below for a description of\n"
        !           944: " MAPPED_VOLUME.\n"
        !           945: "\n"
        !           946: "-l, --list [MAPPED_VOLUME]\n"
        !           947: " Display a list of mapped volumes. If MAPPED_VOLUME is not specified, all\n"
        !           948: " volumes are listed. By default, the list contains only volume path and mapped\n"
        !           949: " device name pairs. A more detailed list can be enabled by verbose output\n"
        !           950: " option (-v). See below for a description of MAPPED_VOLUME.\n"
        !           951: "\n"
        !           952: "MAPPED_VOLUME\n"
        !           953: " Specifies a mapped or mounted volume. One of the following forms can be used:\n\n"
        !           954: " 1) Path to the encrypted TrueCrypt volume.\n\n"
        !           955: " 2) Mount directory of the volume's filesystem (if mounted).\n\n"
        !           956: " 3) Device number of the mapped volume.\n\n"
        !           957: " 4) Device name of the mapped volume.\n\n"
        !           958: "\n"
        !           959: "--device-number N\n"
        !           960: " Use device number N when mapping a volume as a block device\n"
        !           961: " /dev/mapper/truecryptN. Default is the first available device.\n"
        !           962: "\n"
        !           963: "--display-password\n"
        !           964: " Display password characters while typing.\n"
        !           965: "\n"
        !           966: "--filesystem TYPE\n"
        !           967: " Filesystem type to mount. The TYPE argument is passed to mount(8) command\n"
        !           968: " with option -t. Default type is 'auto'.\n"
        !           969: "\n"
        !           970: "-h, --help\n"
        !           971: " Display help information.\n"
        !           972: "\n"
        !           973: "-k, --keyfile FILE | DIRECTORY\n"
        !           974: " Use specified keyfile to open a volume to be mapped. When a directory is\n"
        !           975: " specified, all files inside it will be used (non-recursively). Additional\n"
        !           976: " keyfiles can be specified with multiple -k options. See also option -K.\n"
        !           977: "\n"
        !           978: "-K, --keyfile-protected FILE | DIRECTORY\n"
        !           979: " Use specified keyfile to open a hidden volume to be protected. See also\n"
        !           980: " options -k and -P.\n"
        !           981: "\n"
        !           982: "--mount-options OPTIONS\n"
        !           983: " Filesystem mount options. The OPTIONS argument is passed to mount(8)\n"
        !           984: " command with option -o.\n"
        !           985: " \n"
        !           986: "-p, --password PASSWORD\n"
        !           987: " Use specified password to open a volume. Additional passwords can be\n"
        !           988: " specified with multiple -p options. An empty password can also be specified\n"
        !           989: " (\"\" in most shells). Note that passing a password on the command line is\n"
        !           990: " potentially insecure as the password may be visible in the process list\n"
        !           991: " (see ps(1)) and/or stored in a command history file. \n"
        !           992: " \n"
        !           993: "--password-tries NUMBER\n"
        !           994: " Prompt NUMBER of times for a password until the correct password is entered.\n"
        !           995: " Default is to prompt three times.\n"
        !           996: "\n"
        !           997: "-P, --protect-hidden\n"
        !           998: " Write-protect a hidden volume when mapping an outer volume. Before mapping the\n"
        !           999: " outer volume, the user will be prompted for a password to open the hidden\n"
        !          1000: " volume. The size and position of the hidden volume is then determined and the\n"
        !          1001: " outer volume is mounted with all sectors belonging to the hidden volume\n"
        !          1002: " protected against write operations. When a write to the protected area is\n"
        !          1003: " prevented, the whole volume is switched to read-only mode. Verbose list command\n"
        !          1004: " (-vl) can be used to query the state of the hidden volume protection. Warning\n"
        !          1005: " message is displayed when a volume switched to read-only is being dismounted.\n"
        !          1006: " See also option -r.\n"
        !          1007: " \n"
        !          1008: "-r, --read-only\n"
        !          1009: " Map and/or mount a volume as read-only. Write operations to the volume may not\n"
        !          1010: " fail immediately due to the write buffering performed by the system, but the\n"
        !          1011: " physical write will still be prevented.\n"
        !          1012: " \n"
        !          1013: "--test\n"
        !          1014: " Test all internal algorithms used in the process of encryption and decryption.\n"
        !          1015: "\n"
        !          1016: "--update-time\n"
        !          1017: " Do not preserve access and modification timestamps of volume containers and\n"
        !          1018: " access timestamps of keyfiles. By default, timestamps are restored after\n"
        !          1019: " a volume is unmapped or after a keyfile is closed.\n"
        !          1020: "\n"
        !          1021: "-v, --verbose\n"
        !          1022: " Enable verbose output. Multiple -v options can be specified to increase the\n"
        !          1023: " level of verbosity.\n"
        !          1024: "\n"
        !          1025: "-V, --version\n"
        !          1026: " Display version information.\n"
        !          1027: "\n"
        !          1028: "Examples:\n"
        !          1029: "\n"
        !          1030: "truecrypt /root/volume.tc /mnt/tc\n"
        !          1031: " Map a volume /root/volume.tc and mount its filesystem at /mnt/tc.\n"
        !          1032: "\n"
        !          1033: "truecrypt -d\n"
        !          1034: " Dismount and unmap all mapped volumes.\n"
        !          1035: "  \n"
        !          1036: "truecrypt -d /root/volume.tc\n"
        !          1037: " Dismount and unmap a volume /root/volume.tc.\n"
        !          1038: "\n"
        !          1039: "truecrypt -d /mnt/tc\n"
        !          1040: " Dismount and unmap a volume mounted at /mnt/tc.\n"
        !          1041: "\n"
        !          1042: "truecrypt -vl\n"
        !          1043: " Display a detailed list of all mapped volumes.\n"
        !          1044: " \n"
        !          1045: "truecrypt --device-number=1 /dev/hdc1 && mkfs /dev/mapper/truecrypt1\n"
        !          1046: " Map a volume /dev/hdc1 and create a new filesystem on it.\n"
        !          1047: "\n"
        !          1048: "truecrypt -P /dev/hdc1 /mnt/tc\n"
        !          1049: " Map and mount outer volume /dev/hdc1 and protect hidden volume within it.\n"
        !          1050: "\n"
        !          1051: "truecrypt -p \"\" -p \"\" -k key1 -k key2 -K key_hidden -P volume.tc\n"
        !          1052: " Map outer volume ./volume.tc and protect hidden volume within it.\n"
        !          1053: " The outer volume is opened with keyfiles ./key1 and ./key2 and the\n"
        !          1054: " hidden volume with ./key_hidden. Passwords for both volumes are empty.\n"
        !          1055: "\n"
        !          1056: "Report bugs at <http://www.truecrypt.org/bugs>.\n"
        !          1057:        );
        !          1058: }
        !          1059: 
        !          1060: static BOOL DumpMountList (int devNo)
        !          1061: {
        !          1062:        int i;
        !          1063: 
        !          1064:        if (!CheckKernelModuleVersion (FALSE))
        !          1065:                return FALSE;
        !          1066: 
        !          1067:        if (!GetMountList ())
        !          1068:                return FALSE;
        !          1069: 
        !          1070:        for (i = 0; MountList[i].DeviceNumber != -1; i++)
        !          1071:        {
        !          1072:                MountListEntry *e = &MountList[i];
        !          1073: 
        !          1074:                if (devNo != -1 && e->DeviceNumber != devNo)
        !          1075:                        continue;
        !          1076: 
        !          1077:                if (Verbose == 0)
        !          1078:                {
        !          1079:                        printf (TC_MAP_DEV "%d %s\n",
        !          1080:                                e->DeviceNumber,
        !          1081:                                e->VolumePath);
        !          1082:                }
        !          1083:                else
        !          1084:                {
        !          1085:                        char eaName[128];
        !          1086:                        EAGetName (eaName, e->EA);
        !          1087: 
        !          1088:                        printf (TC_MAP_DEV "%d:\n"
        !          1089:                                        " Volume: %s\n"
        !          1090:                                        " Type: %s\n"
        !          1091:                                        " Size: %lld bytes\n"
        !          1092:                                        " Encryption algorithm: %s\n"
        !          1093:                                        " Read-only: %s\n"
        !          1094:                                        " Hidden volume protected: %s\n\n",
        !          1095:                                e->DeviceNumber,
        !          1096:                                e->VolumePath,
        !          1097:                                e->Hidden ? "Hidden" : "Normal",
        !          1098:                                e->VolumeSize,
        !          1099:                                eaName,
        !          1100:                                (e->Flags & FLAG_READ_ONLY) ? "Yes" : "No",
        !          1101:                                (e->Flags & FLAG_PROTECTION_ACTIVATED) ? "Yes - damage prevented" : (
        !          1102:                                        (e->Flags & FLAG_HIDDEN_VOLUME_PROTECTION) ? "Yes" : "No" )
        !          1103:                                );
        !          1104:                }
        !          1105:        }
        !          1106: 
        !          1107:        return TRUE;
        !          1108: }
        !          1109: 
        !          1110: 
        !          1111: static BOOL EnumMountPoints (char *device, char *mountPoint)
        !          1112: {
        !          1113:        static FILE *m = NULL;
        !          1114: 
        !          1115:        if (device == NULL)
        !          1116:        {
        !          1117:                fclose (m);
        !          1118:                m = NULL;
        !          1119:                return TRUE;
        !          1120:        }
        !          1121: 
        !          1122:        if (m == NULL)
        !          1123:        {
        !          1124:                m = fopen ("/proc/mounts", "r");
        !          1125:                if (m == NULL)
        !          1126:                {
        !          1127:                        perror ("fopen /proc/mounts");
        !          1128:                        return FALSE;
        !          1129:                }
        !          1130:        }
        !          1131: 
        !          1132:        if (fscanf (m, "%" MAX_PATH_STR "s %" MAX_PATH_STR "s %*s %*s %*s %*s",
        !          1133:                device, mountPoint) != 2)
        !          1134:        {
        !          1135:                fclose (m);
        !          1136:                m = NULL;
        !          1137:                return FALSE;
        !          1138:        }
        !          1139: 
        !          1140:        return TRUE;
        !          1141: }
        !          1142: 
        !          1143: 
        !          1144: static BOOL DismountFileSystem (char *device)
        !          1145: {
        !          1146:        char mountedDevice[MAX_PATH], mountPoint[MAX_PATH];
        !          1147:        BOOL result = TRUE;
        !          1148: 
        !          1149:        while (EnumMountPoints (mountedDevice, mountPoint))
        !          1150:        {
        !          1151:                if (strcmp (mountedDevice, device) == 0)
        !          1152:                {
        !          1153:                        if (!Execute (FALSE, "umount", mountPoint, NULL))
        !          1154:                                result = FALSE;
        !          1155:                        else if (Verbose >= 1)
        !          1156:                                printf ("Dismounted %s\n", mountPoint);
        !          1157:                }
        !          1158:        }
        !          1159: 
        !          1160:        return result;
        !          1161: }
        !          1162: 
        !          1163: 
        !          1164: // devNo: -1 = Dismount all volumes
        !          1165: static BOOL DismountVolume (int devNo)
        !          1166: {
        !          1167:        char mapDevice[MAX_PATH];
        !          1168:        int nMountedVolumes = 0;
        !          1169:        int i;
        !          1170:        BOOL found = FALSE;
        !          1171:        BOOL status = TRUE;
        !          1172: 
        !          1173:        if (!CheckKernelModuleVersion (FALSE))
        !          1174:                return FALSE;
        !          1175: 
        !          1176:        if (!GetMountList ())
        !          1177:                return FALSE;
        !          1178: 
        !          1179:        if (devNo == -1 && MountList[0].DeviceNumber == -1)
        !          1180:        {
        !          1181:                error ("No volumes mounted\n");
        !          1182:                return FALSE;
        !          1183:        }
        !          1184: 
        !          1185:        // Flush write buffers before dismount if there are
        !          1186:        // mounted volumes with hidden volume protection 
        !          1187:        for (i = 0; MountList[i].DeviceNumber != -1; i++)
        !          1188:        {
        !          1189:                if (MountList[i].Flags & FLAG_HIDDEN_VOLUME_PROTECTION)
        !          1190:                {
        !          1191:                        sync ();
        !          1192:                        MountListValid = FALSE;
        !          1193:                        GetMountList ();
        !          1194:                        break;
        !          1195:                }
        !          1196:        }
        !          1197: 
        !          1198:        for (i = 0; MountList[i].DeviceNumber != -1; i++)
        !          1199:        {
        !          1200:                MountListEntry *e = &MountList[i];
        !          1201:                nMountedVolumes++;
        !          1202: 
        !          1203:                if (devNo == -1 || e->DeviceNumber == devNo)
        !          1204:                {
        !          1205:                        BOOL dismounted = FALSE;
        !          1206:                        found = TRUE;
        !          1207: 
        !          1208:                        if (e->Flags & FLAG_PROTECTION_ACTIVATED)
        !          1209:                                printf ("WARNING: Write to the hidden volume %s has been prevented!\n", e->VolumePath);
        !          1210: 
        !          1211:                        sprintf (mapDevice, TC_MAP_DEV "%d", e->DeviceNumber);
        !          1212:                        if (DismountFileSystem (mapDevice))
        !          1213:                        {
        !          1214:                                char name[32];
        !          1215:                                sprintf (name, "truecrypt%d", e->DeviceNumber);
        !          1216:                                dismounted = Execute (FALSE, "dmsetup", "remove", name, NULL);
        !          1217: 
        !          1218:                                if (dismounted && IsFile (e->VolumePath))
        !          1219:                                {
        !          1220:                                        if (!DeleteLoopDevice (e->DeviceMinor))
        !          1221:                                                status = FALSE;
        !          1222: 
        !          1223:                                        RestoreFileTime (e->VolumePath,
        !          1224:                                                UpdateTime ? time (NULL) : (time_t) e->ModTime,
        !          1225:                                                UpdateTime ? time (NULL) : (time_t) e->AcTime);
        !          1226:                                }
        !          1227:                        }
        !          1228: 
        !          1229:                        if (!dismounted)
        !          1230:                        {
        !          1231:                                error ("Cannot dismount %s\n", mapDevice);
        !          1232:                                status = FALSE;
        !          1233:                        }
        !          1234:                        else
        !          1235:                        {
        !          1236:                                nMountedVolumes--;
        !          1237:                                if (Verbose >= 1)
        !          1238:                                        printf ("Unmapped %s\n", mapDevice);
        !          1239:                        }
        !          1240: 
        !          1241:                        if (devNo != -1)
        !          1242:                                break;
        !          1243:                }
        !          1244:        }
        !          1245: 
        !          1246:        if (!found)
        !          1247:        {
        !          1248:                error (TC_MAP_DEV "%d not mounted\n", devNo);
        !          1249:                return FALSE;
        !          1250:        }
        !          1251: 
        !          1252:        if (nMountedVolumes == 0)
        !          1253:        {
        !          1254:                // Ignore errors as volumes may be mounted asynchronously
        !          1255:                UnloadKernelModule (TRUE);
        !          1256:        }
        !          1257: 
        !          1258:        return status;
        !          1259: }
        !          1260: 
        !          1261: 
        !          1262: // Convert a string to device number
        !          1263: // text: device number or name or mount point
        !          1264: BOOL ToDeviceNumber (char *text, int *deviceNumber)
        !          1265: {
        !          1266:        char mountedDevice[MAX_PATH], mountPoint[MAX_PATH];
        !          1267:        int i;
        !          1268: 
        !          1269:        if (sscanf (text, "%d", deviceNumber) == 1)
        !          1270:                return TRUE;
        !          1271: 
        !          1272:        if (sscanf (text, TC_MAP_DEV "%d", deviceNumber) == 1)
        !          1273:                return TRUE;
        !          1274: 
        !          1275:        while (EnumMountPoints (mountedDevice, mountPoint))
        !          1276:        {
        !          1277:                if (strcmp (mountPoint, text) == 0
        !          1278:                        && sscanf (mountedDevice, TC_MAP_DEV "%d", deviceNumber) == 1)
        !          1279:                {
        !          1280:                        EnumMountPoints (NULL, NULL);
        !          1281:                        return TRUE;
        !          1282:                }
        !          1283:        }
        !          1284: 
        !          1285:        if (!GetMountList ())
        !          1286:                return FALSE;
        !          1287: 
        !          1288:        for (i = 0; MountList[i].DeviceNumber != -1; i++)
        !          1289:        {
        !          1290:                MountListEntry *e = &MountList[i];
        !          1291:                if (e->DeviceNumber == -1)
        !          1292:                        break;
        !          1293: 
        !          1294:                if (strcmp (text, e->VolumePath) == 0)
        !          1295:                {
        !          1296:                        *deviceNumber = e->DeviceNumber;
        !          1297:                        return TRUE;
        !          1298:                }
        !          1299:        }
        !          1300: 
        !          1301:        error ("%s not mounted\n", text);
        !          1302:        return FALSE;
        !          1303: }
        !          1304: 
        !          1305: 
        !          1306: int main(int argc, char **argv)
        !          1307: {
        !          1308:        char *volumePath = NULL;
        !          1309:        char *mountPoint = NULL;
        !          1310:        char volumePathBuf[MAX_PATH];
        !          1311:        int i, o;
        !          1312:        int optIndex = 0;
        !          1313: 
        !          1314:        struct option longOptions[] = {
        !          1315:                {"device-number", required_argument, 0, 0},
        !          1316:                {"dismount", optional_argument, 0, 'd'},
        !          1317:                {"display-password", 0, 0, 0},
        !          1318:                {"keyfile", required_argument, 0, 'k'},
        !          1319:                {"keyfile-protected", required_argument, 0, 'K'},
        !          1320:                {"filesystem", required_argument, 0, 0},
        !          1321:                {"list", 0, 0, 'l'},
        !          1322:                {"help", 0, 0, 'h'},
        !          1323:                {"mount-options", required_argument, 0, 0},
        !          1324:                {"password", required_argument, 0, 'l'},
        !          1325:                {"password-tries", required_argument, 0, 0},
        !          1326:                {"protect-hidden", 0, 0, 'P'},
        !          1327:                {"read-only", 0, 0, 'r'},
        !          1328:                {"test", 0, 0, 0},
        !          1329:                {"update-time", 0, 0, 0},
        !          1330:                {"verbose", 0, 0, 'v'},
        !          1331:                {"version", 0, 0, 'V'},
        !          1332:                {0, 0, 0, 0}
        !          1333:        };
        !          1334: 
        !          1335:        if (getuid () != 0 && geteuid () != 0)
        !          1336:        {
        !          1337:                error ("administrator (root) privileges required\n");
        !          1338:                return FALSE;
        !          1339:        }
        !          1340: 
        !          1341:        if (mlockall (MCL_FUTURE) != 0)
        !          1342:                perror ("Cannot prevent memory swapping: mlockall");
        !          1343: 
        !          1344:        signal (SIGHUP, OnSignal);
        !          1345:        signal (SIGINT, OnSignal);
        !          1346:        signal (SIGQUIT, OnSignal);
        !          1347:        signal (SIGABRT, OnSignal);
        !          1348:        signal (SIGPIPE, OnSignal);
        !          1349:        signal (SIGTERM, OnSignal);
        !          1350: 
        !          1351:        atexit (OnExit);
        !          1352: 
        !          1353:        while ((o = getopt_long (argc, argv, "dhk:K:lp:PrvV", longOptions, &optIndex)) != -1)
        !          1354:        {
        !          1355:                switch (o)
        !          1356:                {
        !          1357:                case 'd':
        !          1358:                        // Dismount
        !          1359:                        {
        !          1360:                                int devNo;
        !          1361: 
        !          1362:                                if (optind < argc)
        !          1363:                                {
        !          1364:                                        if (!ToDeviceNumber (argv[optind++], &devNo))
        !          1365:                                                return 1;
        !          1366: 
        !          1367:                                        if (optind < argc)
        !          1368:                                                goto usage;
        !          1369:                                }
        !          1370:                                else
        !          1371:                                        devNo = -1;
        !          1372: 
        !          1373:                                return DismountVolume (devNo) ? 0 : 1;
        !          1374:                        }
        !          1375: 
        !          1376:                case 'l':
        !          1377:                        // List
        !          1378:                        {
        !          1379:                                int devNo;
        !          1380: 
        !          1381:                                if (optind < argc)
        !          1382:                                {
        !          1383:                                        if (!ToDeviceNumber (argv[optind++], &devNo))
        !          1384:                                                return 1;
        !          1385: 
        !          1386:                                        if (optind < argc)
        !          1387:                                                goto usage;
        !          1388:                                }
        !          1389:                                else
        !          1390:                                        devNo = -1;
        !          1391: 
        !          1392:                                return DumpMountList (devNo) ? 0 : 1;
        !          1393:                        }
        !          1394: 
        !          1395:                case 'k':
        !          1396:                case 'K':
        !          1397:                        // Keyfile
        !          1398:                        {
        !          1399:                                KeyFile *kf = malloc (sizeof (KeyFile));
        !          1400:                                if (!kf)
        !          1401:                                {
        !          1402:                                        perror ("malloc");
        !          1403:                                        return 1;
        !          1404:                                }
        !          1405:                                strncpy (kf->FileName, optarg, sizeof (kf->FileName));
        !          1406:                                if (o == 'k')
        !          1407:                                        FirstKeyFile = KeyFileAdd (FirstKeyFile, kf);
        !          1408:                                else
        !          1409:                                        FirstProtVolKeyFile = KeyFileAdd (FirstProtVolKeyFile, kf);
        !          1410:                        }
        !          1411:                        break;
        !          1412: 
        !          1413: 
        !          1414:                case 'p':
        !          1415:                        // Password
        !          1416:                        if (!CmdPasswordValid)
        !          1417:                        {
        !          1418:                                strncpy (CmdPassword.Text, optarg, sizeof (CmdPassword.Text));
        !          1419:                                CmdPassword.Length = strlen (CmdPassword.Text);
        !          1420:                                CmdPasswordValid = TRUE;
        !          1421:                        }
        !          1422:                        else if (!CmdPassword2Valid)
        !          1423:                        {
        !          1424:                                strncpy (CmdPassword2.Text, optarg, sizeof (CmdPassword2.Text));
        !          1425:                                CmdPassword2.Length = strlen (CmdPassword2.Text);
        !          1426:                                CmdPassword2Valid = TRUE;
        !          1427:                        }
        !          1428:                        break;
        !          1429: 
        !          1430:                case 'P':
        !          1431:                        // Hidden volume protection
        !          1432:                        ProtectHidden = TRUE;
        !          1433:                        break;
        !          1434: 
        !          1435:                case 'r':
        !          1436:                        ReadOnly = TRUE;
        !          1437:                        break;
        !          1438: 
        !          1439:                case 'v':
        !          1440:                        // Verbose
        !          1441:                        Verbose++;
        !          1442:                        break;
        !          1443: 
        !          1444:                case 'V':
        !          1445:                        DumpVersion (stdout);
        !          1446:                        return 0;
        !          1447: 
        !          1448:                case 'h':
        !          1449:                        // Help
        !          1450:                        DumpHelp ();
        !          1451:                        return 0;
        !          1452: 
        !          1453:                case 0:
        !          1454:                        if (strcmp ("display-password", longOptions[optIndex].name) == 0)
        !          1455:                        {
        !          1456:                                DisplayPassword = TRUE;
        !          1457:                                break;
        !          1458:                        }
        !          1459: 
        !          1460:                        if (strcmp ("device-number", longOptions[optIndex].name) == 0)
        !          1461:                        {
        !          1462:                                if (sscanf (optarg, "%d", &UseDeviceNumber) == 1
        !          1463:                                        && UseDeviceNumber >= 0)
        !          1464:                                        break;
        !          1465:                                else
        !          1466:                                        goto usage;
        !          1467:                        }
        !          1468: 
        !          1469:                        if (strcmp ("filesystem", longOptions[optIndex].name) == 0)
        !          1470:                        {
        !          1471:                                Filesystem = optarg;
        !          1472:                                break;
        !          1473:                        }
        !          1474: 
        !          1475:                        if (strcmp ("mount-options", longOptions[optIndex].name) == 0)
        !          1476:                        {
        !          1477:                                MountOpts = optarg;
        !          1478:                                break;
        !          1479:                        }
        !          1480: 
        !          1481:                        if (strcmp ("password-tries", longOptions[optIndex].name) == 0)
        !          1482:                        {
        !          1483:                                if (sscanf (optarg, "%d", &PasswordEntryTries) == 1)
        !          1484:                                        break;
        !          1485:                                else
        !          1486:                                        goto usage;
        !          1487:                        }
        !          1488:                        
        !          1489:                        if (strcmp ("test", longOptions[optIndex].name) == 0)
        !          1490:                        {
        !          1491:                                if (AutoTestAlgorithms ())
        !          1492:                                {
        !          1493:                                        printf ("Self-tests of all algorithms passed.\n");
        !          1494:                                        return 0;
        !          1495:                                }
        !          1496: 
        !          1497:                                printf ("Self-tests of algorithms FAILED!\n");
        !          1498:                                return 1;
        !          1499:                        }
        !          1500: 
        !          1501:                        if (strcmp ("update-time", longOptions[optIndex].name) == 0)
        !          1502:                        {
        !          1503:                                UpdateTime = TRUE;
        !          1504:                                break;
        !          1505:                        }
        !          1506:                        goto usage;
        !          1507: 
        !          1508:                default:
        !          1509:                        goto usage;
        !          1510:                }
        !          1511:        }
        !          1512:        
        !          1513:        if (optind >= argc)
        !          1514:                goto usage;
        !          1515: 
        !          1516:        if (optind < argc)
        !          1517:                volumePath = argv[optind++];
        !          1518: 
        !          1519:        if (optind < argc)
        !          1520:                mountPoint = argv[optind++];
        !          1521: 
        !          1522:        if (optind < argc)
        !          1523:                goto usage;
        !          1524: 
        !          1525:        // Relative path => absolute
        !          1526:        if (volumePath[0] != '/')
        !          1527:        {
        !          1528:                char s[MAX_PATH];
        !          1529:                getcwd (s, sizeof (s));
        !          1530:                snprintf (volumePathBuf, sizeof (volumePathBuf), "%s/%s", s, volumePath);
        !          1531:                volumePath = volumePathBuf;
        !          1532:        }
        !          1533: 
        !          1534:        return MountVolume (volumePath, mountPoint) == FALSE;
        !          1535: 
        !          1536: usage:
        !          1537:        DumpUsage (stderr);
        !          1538: 
        !          1539:        return 1;
        !          1540: }

unix.superglobalmegacorp.com

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