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

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: #define _LARGEFILE_SOURCE      1
                      9: #define _FILE_OFFSET_BITS      64
                     10: 
                     11: #include <getopt.h>
                     12: #include <inttypes.h>
                     13: #include <stdarg.h>
                     14: #include <stdio.h>
                     15: #include <stdlib.h>
                     16: #include <sys/mman.h>
                     17: #include <sys/stat.h>
                     18: #include <sys/types.h>
                     19: #include <sys/wait.h>
                     20: #include <termios.h>
                     21: #include <time.h>
                     22: #include <unistd.h>
                     23: #include <utime.h>
                     24: 
                     25: #include "Tcdefs.h"
                     26: #include "Keyfiles.h"
                     27: #include "Volumes.h"
                     28: #include "Tests.h"
                     29: #include "Dm-target.h"
                     30: 
                     31: #define MAX_VOLUMES    256
                     32: #define MAX_MINOR 256
                     33: 
                     34: #undef MAX_PATH
                     35: #define MAX_PATH 260
                     36: #define MAX_PATH_STR "259"
                     37: 
                     38: #define TC_MAP_DEV "/dev/mapper/truecrypt"
                     39: #define LOOP_DEV "/dev/loop"
                     40: 
                     41: #define error(fmt, args...) fprintf (stderr, "truecrypt: " fmt, ## args)
                     42: 
                     43: typedef struct
                     44: {
                     45:        int DeviceNumber;
                     46:        int DeviceMajor;
                     47:        int DeviceMinor;
                     48:        uint64_t VolumeSize;
                     49:        char VolumePath[MAX_PATH];
                     50:        int EA;
1.1.1.2 ! root       51:        int Mode;
1.1       root       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:        {
1.1.1.2 ! root      390:                int n = 0;
1.1       root      391:                char s[2048];
                    392:                MountListEntry *e = &MountList[i];
                    393: 
                    394:                if (!fgets (s, sizeof (s), p))
                    395:                        break;
                    396: 
1.1.1.2 ! root      397:                if (sscanf (s, "truecrypt%d: 0 %lld truecrypt %d %d 0 0 %d:%d %lld %lld %lld %lld %lld %d %n",
1.1       root      398:                        &e->DeviceNumber,
                    399:                        &e->VolumeSize,
                    400:                        &e->EA,
1.1.1.2 ! root      401:                        &e->Mode,
1.1       root      402:                        &e->DeviceMajor,
                    403:                        &e->DeviceMinor,
                    404:                        &e->Hidden,
                    405:                        &e->ReadOnlyStart,
                    406:                        &e->ReadOnlyEnd,
                    407:                        &e->ModTime,
                    408:                        &e->AcTime,
                    409:                        &e->Flags,
1.1.1.2 ! root      410:                        &n) >= 12 && n > 0)
1.1       root      411:                {
1.1.1.2 ! root      412:                        int l;
        !           413:                        strncpy (e->VolumePath, s + n, sizeof (e->VolumePath));
        !           414:                        l = strlen (s + n);
        !           415:                        if (l > 0)
        !           416:                                e->VolumePath[l - 1] = 0;
        !           417: 
1.1       root      418:                        e->Hidden = e->Hidden == 1 ? FALSE : TRUE;
                    419:                        e->VolumeSize *= SECTOR_SIZE;
                    420:                }
                    421:                else
                    422:                        i--;
                    423:        }
                    424: 
                    425:        MountList[i].DeviceNumber = -1;
                    426: 
                    427:        fclose (p);
                    428:        if (!WaitChild (TRUE, "dmsetup"))
                    429:                goto err;
                    430: 
                    431:        MountListValid = TRUE;
                    432:        return TRUE;
                    433: 
                    434: err:
                    435:        MountList[0].DeviceNumber = -1;
                    436:        return FALSE;
                    437: }
                    438: 
                    439: 
                    440: static BOOL IsVolumeMounted (char *volumePath)
                    441: {
                    442:        int i;
                    443:        if (!GetMountList ())
                    444:                return FALSE;
                    445: 
                    446:        for (i = 0; MountList[i].DeviceNumber != -1; i++)
                    447:                if (strcmp (volumePath, MountList[i].VolumePath) == 0)
                    448:                        return TRUE;
                    449: 
                    450:        return FALSE;
                    451: }
                    452: 
                    453: 
                    454: static int GetFreeMapDevice ()
                    455: {
                    456:        FILE *p;
                    457:        char cmd[128];
                    458:        int n;
                    459: 
                    460:        if (!GetMountList ())
                    461:                return -1;
                    462: 
                    463:        for (n = 0; n < MAX_MINOR; n++)
                    464:        {
                    465:                int j = 0;
                    466:                while (MountList[j].DeviceNumber != -1)
                    467:                {
                    468:                        if (MountList[j].DeviceNumber == n)
                    469:                                break;
                    470:                        j++;
                    471:                }
                    472: 
                    473:                if (MountList[j].DeviceNumber == -1)
                    474:                        return n;
                    475:        }
                    476: 
                    477:        return -1;
                    478: }
                    479: 
                    480: 
                    481: static BOOL DeleteLoopDevice (int loopDeviceNo)
                    482: {
                    483:        char dev[32];
                    484:        BOOL r;
                    485: 
                    486:        sprintf (dev, LOOP_DEV "%d", loopDeviceNo);
                    487:        if (!IsBlockDevice (dev))
                    488:                sprintf (dev, LOOP_DEV "/%d", loopDeviceNo);
                    489: 
                    490:        r = Execute (FALSE, "losetup", "-d", dev, NULL);
                    491: 
                    492:        if (r && Verbose > 1)
                    493:                printf ("Detached %s\n", dev);
                    494: 
                    495:        return r;
                    496: }
                    497: 
                    498: 
                    499: static BOOL OpenVolume (char *volumePath, Password *password, PCRYPTO_INFO *cryptoInfo, uint64_t *startSector, uint64_t *totalSectors, time_t *modTime, time_t *acTime)
                    500: {
                    501:        char header[SECTOR_SIZE];
                    502:        uint64_t r;
                    503:        FILE *f = NULL;
                    504:        struct stat volumeStat;
                    505: 
                    506:        if (stat (volumePath, &volumeStat) != 0)
                    507:        {
                    508:                perror ("Cannot open volume");
                    509:                volumeStat.st_ctime = 0;
                    510:                goto err;
                    511:        }
                    512: 
1.1.1.2 ! root      513:        f = fopen (volumePath, "rb");
1.1       root      514:        if (!f)
                    515:        {
                    516:                perror ("Cannot open volume");
                    517:                goto err;
                    518:        }
                    519: 
                    520:        // Normal header
                    521:        if (fread (header, 1, SECTOR_SIZE, f) != SECTOR_SIZE)
                    522:        {
                    523:                perror ("Cannot read volume header");
                    524:                goto err;
                    525:        }
                    526: 
                    527:        fseek (f, 0, SEEK_END);
                    528:        *totalSectors = ftello (f) / SECTOR_SIZE - 1;
                    529: 
1.1.1.2 ! root      530:        *startSector = 1;
1.1       root      531:        r = VolumeReadHeader (header, password, cryptoInfo);
                    532: 
1.1.1.2 ! root      533:        if (r == ERR_PASSWORD_WRONG)
1.1       root      534:        {
                    535:                // Hidden header
                    536:                if (fseek (f, -HIDDEN_VOL_HEADER_OFFSET, SEEK_END) == -1
                    537:                        || fread (header, 1, SECTOR_SIZE, f) != SECTOR_SIZE)
                    538:                {
                    539:                        perror ("Cannot read volume header");
                    540:                        goto err;
                    541:                }
                    542: 
                    543:                r = VolumeReadHeader (header, password, cryptoInfo);
                    544: 
1.1.1.2 ! root      545:                if (r == ERR_PASSWORD_WRONG)
1.1       root      546:                {
                    547:                        if (IsTerminal)
                    548:                                puts ("Incorrect password or not a TrueCrypt volume");
                    549:                        else
                    550:                                error ("Incorrect password or not a TrueCrypt volume\n");
                    551: 
                    552:                        goto err;
                    553:                }
                    554: 
                    555:                *startSector = (ftello (f) 
                    556:                        + SECTOR_SIZE * 2 
                    557:                        - (*cryptoInfo)->hiddenVolumeSize 
                    558:                        - HIDDEN_VOL_HEADER_OFFSET) / SECTOR_SIZE;
                    559: 
                    560:                *totalSectors = (*cryptoInfo)->hiddenVolumeSize / SECTOR_SIZE;
                    561:        }
1.1.1.2 ! root      562: 
        !           563:        // Report errors
        !           564:        if (r != 0 && r != ERR_PASSWORD_WRONG)
        !           565:        {
        !           566:                char msg[128];
        !           567: 
        !           568:                switch (r)
        !           569:                {
        !           570:                case ERR_NEW_VERSION_REQUIRED:
        !           571:                        strcpy (msg, "A newer version of TrueCrypt is required to open this volume"); 
        !           572:                        break;
        !           573: 
        !           574:                default:
        !           575:                        sprintf (msg, "Volume cannot be opened: Error %d", r);
        !           576:                        break;
        !           577:                }
        !           578: 
        !           579:                if (IsTerminal)
        !           580:                        printf ("%s\n", msg);
        !           581:                else
        !           582:                        error ("%s\n", msg);
        !           583: 
        !           584:                goto err;
        !           585:        }
1.1       root      586: 
                    587:        fclose (f);
                    588: 
                    589:        if (!UpdateTime)
                    590:                RestoreFileTime (volumePath, volumeStat.st_mtime, volumeStat.st_atime);
                    591: 
                    592:        *modTime = volumeStat.st_mtime;
                    593:        *acTime = volumeStat.st_atime;
                    594:        return TRUE;
                    595: 
                    596: err:
                    597:        *cryptoInfo = NULL;
                    598: 
                    599:        if (f)
                    600:                fclose (f);
                    601: 
                    602:        if (volumeStat.st_ctime != 0 && !UpdateTime)
                    603:                RestoreFileTime (volumePath, volumeStat.st_mtime, volumeStat.st_atime);
                    604: 
                    605:        return FALSE;
                    606: }
                    607: 
                    608: 
                    609: static void GetPassword (char *prompt, char *volumePath, Password *password)
                    610: {
                    611:        struct termios noEcho;
                    612: 
                    613:        if (tcgetattr (0, &TerminalAttributes) == 0)
                    614:        {
                    615:                IsTerminal = TRUE;
                    616:                noEcho = TerminalAttributes;
                    617: 
                    618:                if (!DisplayPassword)
                    619:                {
                    620:                        noEcho.c_lflag &= ~ECHO;
                    621:                        if (tcsetattr (0, TCSANOW, &noEcho) != 0)
                    622:                                error ("Failed to turn terminal echo off\n");
                    623:                }
                    624: 
                    625:                printf (prompt, volumePath);
                    626:        }
                    627: 
                    628:        if (fgets (password->Text, sizeof (password->Text), stdin))
                    629:        {
                    630:                char *newl = strchr (password->Text, '\n');
                    631:                if (newl) newl[0] = 0;
                    632: 
                    633:                password->Length = strlen (password->Text);
                    634:        }
                    635:        else
                    636:                password->Length = 0;
                    637: 
                    638:        if (IsTerminal && !DisplayPassword)
                    639:        {
                    640:                tcsetattr (0, TCSANOW, &TerminalAttributes);
                    641:                puts ("");
                    642:        }
                    643: }
                    644: 
                    645: 
1.1.1.2 ! root      646: static char *EscapeSpaces (char *string)
        !           647: {
        !           648:        static char escapedString[MAX_PATH * 2];
        !           649:        char *e = escapedString;
        !           650:        char c;
        !           651: 
        !           652:        if (strlen (string) > MAX_PATH)
        !           653:                return NULL;
        !           654: 
        !           655:        while ((c = *string++))
        !           656:        {
        !           657:                if (c == ' ')
        !           658:                        *e++ = '\\';
        !           659: 
        !           660:                *e++ = c;
        !           661:        }
        !           662: 
        !           663:        return escapedString;
        !           664: }
        !           665: 
        !           666: 
1.1       root      667: static BOOL MountVolume (char *volumePath, char *mountPoint)
                    668: {
                    669:        char hostDevice[MAX_PATH];
                    670:        char mapDevice[MAX_PATH];
                    671:        int loopDevNo = -1;
                    672:        PCRYPTO_INFO ci = NULL;
                    673:        uint64_t startSector, totalSectors;
                    674:        uint64_t readOnlyStartSector = 0, readOnlySectors = 0;
                    675:        int pfd[2];
                    676:        int pid, res, devNo;
                    677:        time_t modTime, acTime;
                    678:        FILE *f, *w;
                    679:        int flags;
                    680:        int i;
                    681:        int tries = PasswordEntryTries;
                    682: 
                    683:        if (!AutoTestAlgorithms ())
                    684:        {
                    685:                error ("Self-tests of algorithms FAILED!\n");
                    686:                return FALSE;
                    687:        }
                    688: 
                    689:        if (IsVolumeMounted (volumePath))
                    690:        {
                    691:                error ("Volume already mounted\n");
                    692:                return FALSE;
                    693:        }
                    694: 
                    695:        do
                    696:        {
                    697:                Password *pw = &password;
                    698: 
                    699:                if (!CmdPasswordValid)
                    700:                        GetPassword ("Enter password for '%s': ", volumePath, &password);
                    701:                else
                    702:                        pw = &CmdPassword;
                    703: 
                    704:                if (FirstKeyFile && !KeyFilesApply (pw, FirstKeyFile, !UpdateTime))
                    705:                {
                    706:                        error ("Error while processing keyfiles\n");
                    707:                        goto err;
                    708:                }
                    709: 
                    710:                if (OpenVolume (volumePath, pw, &ci, &startSector, &totalSectors, &modTime, &acTime))
                    711:                        break;
                    712:                else
                    713:                        totalSectors = 0;
                    714: 
                    715:        } while (!CmdPasswordValid && IsTerminal && --tries > 0);
                    716: 
                    717:        if (totalSectors == 0)
                    718:                goto err;
                    719: 
                    720:        // Hidden volume protection
                    721:        if (ProtectHidden)
                    722:        {
                    723:                PCRYPTO_INFO ciH = NULL;
                    724:                uint64_t startSectorH, totalSectorsH;
                    725: 
                    726:                tries = PasswordEntryTries;
                    727:                do
                    728:                {
                    729:                        Password *pw = &password;
                    730: 
                    731:                        if (!CmdPassword2Valid)
                    732:                                GetPassword ("Enter hidden volume password: ", "", &password);
                    733:                        else
                    734:                                pw = &CmdPassword2;
                    735: 
                    736:                        if (FirstProtVolKeyFile && !KeyFilesApply (pw, FirstProtVolKeyFile, !UpdateTime))
                    737:                        {
                    738:                                error ("Error while processing keyfiles\n");
                    739:                                goto err;
                    740:                        }
                    741: 
                    742:                        if (OpenVolume (volumePath, pw, &ciH, &startSectorH, &totalSectorsH, &modTime, &acTime))
                    743:                        {
                    744:                                readOnlyStartSector = startSectorH;
                    745:                                readOnlySectors = startSectorH + totalSectorsH;
                    746:                                break;
                    747:                        }
                    748: 
                    749:                } while (!CmdPassword2Valid && IsTerminal && --tries > 0);
                    750:                
                    751:                if (ciH)
                    752:                        crypto_close (ciH);
                    753: 
                    754:                if (readOnlySectors == 0)
                    755:                        goto err;
                    756:        }
                    757: 
                    758:        // Headers decrypted
                    759: 
                    760:        // Loopback
                    761:        if (IsFile (volumePath))
                    762:        {
                    763:                int i;
                    764: 
                    765:                for (i = 0; i < MAX_MINOR; i++)
                    766:                {
                    767:                        snprintf (hostDevice, sizeof (hostDevice), LOOP_DEV "%d", i);
                    768: 
                    769:                        if (!IsBlockDevice (hostDevice))
                    770:                        {
                    771:                                snprintf (hostDevice, sizeof (hostDevice), LOOP_DEV "/%d", i);
                    772:                                if (!IsBlockDevice (hostDevice))
                    773:                                        continue;
                    774:                        }
                    775: 
                    776:                        if (Execute (TRUE, "losetup", hostDevice, volumePath, NULL))
                    777:                                break;
                    778:                }
                    779: 
                    780:                if (i >= MAX_MINOR)
                    781:                {
                    782:                        error ("No free loopback device available for file-hosted volume\n");
                    783:                        goto err;
                    784:                }
                    785: 
                    786:                loopDevNo = i;
                    787: 
                    788:                if (Verbose > 1)
                    789:                        printf ("Attached %s to %s\n", volumePath, hostDevice);
                    790: 
                    791:        }
                    792:        else
                    793:                strncpy (hostDevice, volumePath, sizeof (hostDevice));
                    794: 
                    795:        // Load kernel module
                    796:        if (!LoadKernelModule ())
                    797:                goto err;
                    798: 
                    799:        if (!CheckKernelModuleVersion (TRUE))
                    800:                goto err;
                    801: 
                    802:        // dmsetup
                    803:        devNo = UseDeviceNumber == -1 ? GetFreeMapDevice () : UseDeviceNumber;
                    804:        if (devNo == -1)
                    805:        {
                    806:                error ("Maximum number of volumes mounted\n");
                    807:                goto err;
                    808:        }
                    809: 
                    810:        sprintf (mapDevice, "truecrypt%d", devNo);
                    811: 
                    812:        pipe (pfd);
                    813:        pid = fork ();
                    814: 
                    815:        if (pid == -1)
                    816:        {
                    817:                perror ("fork");
                    818:                goto err;
                    819:        }
                    820:        else if (pid == 0)
                    821:        {
                    822:                SecurityCleanup ();
                    823: 
                    824:                close (pfd[1]);
                    825:                dup2 (pfd[0], STDIN_FILENO);
                    826: 
                    827:                execlp ("dmsetup", "dmsetup", "create", mapDevice, NULL);
                    828: 
                    829:                perror ("execlp dmsetup");
                    830:                _exit (1);
                    831:        }
                    832: 
                    833:        close (pfd[0]);
                    834:        w = fdopen (pfd[1], "a");
                    835:        if (w == NULL)
                    836:        {
                    837:                perror ("fdopen");
                    838:                goto err;
                    839:        }
                    840: 
1.1.1.2 ! root      841:        fprintf (w, "0 %lld truecrypt %d %d ", totalSectors, ci->ea, ci->mode);
1.1       root      842: 
                    843:        for (i = DISK_IV_SIZE; i < EAGetKeySize (ci->ea) + DISK_IV_SIZE; i++)
                    844:                fprintf (w, "%02x", ci->master_key[i]);
                    845: 
                    846:        fprintf (w, " ");
                    847: 
                    848:        for (i = 0; i < (int)sizeof (ci->iv); i++)
                    849:                fprintf (w, "%02x", ci->iv[i]);
                    850: 
                    851:        flags = 0;
                    852: 
                    853:        if (ReadOnly)
                    854:                flags |= FLAG_READ_ONLY;
                    855:        else if (ProtectHidden)
                    856:                flags |= FLAG_HIDDEN_VOLUME_PROTECTION;
                    857: 
                    858:        fprintf (w, " %s %lld %lld %lld %lld %lld %d %s\n",
                    859:                hostDevice,
                    860:                startSector,
                    861:                readOnlyStartSector,
                    862:                readOnlySectors,
                    863:                (uint64_t) modTime,
                    864:                (uint64_t) acTime,
                    865:                flags,
1.1.1.2 ! root      866:                EscapeSpaces (volumePath));
1.1       root      867: 
                    868:        fclose (w);
                    869: 
                    870:        if (!WaitChild (FALSE, "dmsetup"))
                    871:        {
                    872:                Execute (TRUE, "dmsetup", "remove", mapDevice, NULL);
                    873:                goto err;
                    874:        }
                    875: 
                    876:        sprintf (mapDevice, TC_MAP_DEV "%d", devNo);
                    877: 
                    878:        if (Verbose >= 1)
                    879:                printf ("Mapped %s as %s\n", volumePath, mapDevice);
                    880: 
                    881:        // Mount
                    882:        if (mountPoint)
                    883:        {
                    884:                char fstype[64], opts[128];
                    885: 
                    886:                strcpy (fstype, "-t");
                    887:                if (Filesystem)
                    888:                        strncat (fstype, Filesystem, sizeof (fstype) - 3);
                    889:                else
                    890:                        strcat (fstype, "auto");
                    891: 
                    892:                strcpy (opts, ReadOnly ? "-oro" : "-orw");
                    893:                if (MountOpts)
                    894:                {
                    895:                        strcat (opts, ",");
                    896:                        strncat (opts, MountOpts, sizeof (opts) - 6);
                    897:                }
                    898: 
                    899:                if (!Execute (FALSE, "mount", fstype, opts, mapDevice, mountPoint, NULL))
                    900:                {
                    901:                        error ("Mount failed\n");
                    902:                        loopDevNo = -1;
                    903:                        goto err;
                    904:                }
                    905: 
                    906:                if (Verbose >= 1)
                    907:                        printf ("Mounted %s at %s\n", mapDevice, mountPoint);
                    908:        }
                    909: 
                    910:        crypto_close (ci);
                    911: 
                    912:        return TRUE;
                    913: 
                    914: err:
                    915:        if (ci)
                    916:                crypto_close (ci);
                    917: 
                    918:        if (loopDevNo != -1)
                    919:                DeleteLoopDevice (loopDevNo);
                    920: 
                    921:        UnloadKernelModule (TRUE);
                    922: 
                    923:        return FALSE;
                    924: }
                    925: 
                    926: 
                    927: static void DumpVersion (FILE *f)
                    928: {
                    929:        fprintf (f, 
                    930: "truecrypt %s\n\n"
                    931: "Copyright (C) 2004-2005 TrueCrypt Foundation. All Rights Reserved.\n\
                    932: Copyright (C) 1998-2000 Paul Le Roux. All Rights Reserved.\n\
                    933: Copyright (C) 2004 TrueCrypt Team. All Rights Reserved.\n\
1.1.1.2 ! root      934: Copyright (C) 1999-2005 Dr. Brian Gladman. All Rights Reserved.\n\
1.1       root      935: Copyright (C) 1995-1997 Eric Young. All Rights Reserved.\n\
                    936: Copyright (C) 2001 Markus Friedl. All Rights Reserved.\n\n"
                    937:        , VERSION_STRING);
                    938: }
                    939: 
                    940: 
                    941: static void DumpUsage (FILE *f)
                    942: {
                    943:        fprintf (f,
                    944: "Usage: truecrypt [OPTIONS] VOLUME_PATH [MOUNT_DIRECTORY]\n"
                    945: "   or: truecrypt [OPTIONS] -d | --dismount | -l | --list [MAPPED_VOLUME]\n"
                    946: "   or: truecrypt -h | --help | --test | -V | --version\n"
                    947: "\nCommands:\n"
                    948: " VOLUME_PATH                         Map volume\n"
                    949: " VOLUME_PATH MOUNT_DIRECTORY         Map and mount volume\n"
                    950: " -d, --dismount [MAPPED_VOLUME]      Dismount and unmap volume\n"
                    951: " -h, --help                          Display help\n"
                    952: " -l, --list [MAPPED_VOLUME]          List mapped volumes\n"
                    953: "     --test                          Test algorithms\n"
                    954: " -V, --version                       Display version information\n"
                    955: "\nOptions:\n"
                    956: "     --device-number NUMBER          Map volume as device number\n"
                    957: "     --display-password              Display password while typing\n"
                    958: "     --filesystem TYPE               Filesystem type to mount\n"
                    959: " -k, --keyfile FILE|DIR              Keyfile for volume\n"
                    960: " -K, --keyfile-protected FILE|DIR    Keyfile for protected volume\n"
                    961: " -p, --password PASSWORD             Password for volume\n"
                    962: "     --password-tries NUMBER         Password entry tries\n"
                    963: " -P, --protect-hidden                Protect hidden volume\n"
                    964: "     --update-time                   Do not preserve timestamps\n"
                    965: " -r, --read-only                     Map/Mount read-only\n"
                    966: "     --mount-options OPTIONS         Mount options\n"
                    967: " -v, --verbose                       Verbose output\n"
                    968: "\n MAPPED_VOLUME = DEVICE_NUMBER | DEVICE_NAME | MOUNT_POINT | VOLUME_PATH\n"
                    969: "For a detailed help use --help or see truecrypt(1) man page.\n"
                    970: );
                    971: }
                    972: 
                    973: static void DumpHelp ()
                    974: {
                    975:        fprintf (stdout,
                    976: "Manages encrypted TrueCrypt volumes, which can be mapped as virtual block\n"
                    977: "devices and used as any other standard block device. All data being read\n"
                    978: "from a mapped TrueCrypt volume is transparently decrypted and all data being\n"
                    979: "written to it is transparently encrypted.\n"
                    980: "\n"
                    981: "Usage: truecrypt [OPTIONS] VOLUME_PATH [MOUNT_DIRECTORY]\n"
                    982: "   or: truecrypt [OPTIONS] -d | --dismount | -l | --list [MAPPED_VOLUME]\n"
                    983: "   or: truecrypt -h | --help | --test | -V | --version\n"
                    984: "\n"
                    985: "Options:\n"
                    986: "\n"
                    987: "VOLUME_PATH [MOUNT_DIRECTORY]\n"
                    988: " Open a TrueCrypt volume specified by VOLUME_PATH and map it as a block device\n"
                    989: " /dev/mapper/truecryptN. N is the first available device number if not\n"
                    990: " otherwise specified with --device-number. The filesystem of the mapped volume\n"
                    991: " is mounted at MOUNT_DIRECTORY if specified.\n"
                    992: "\n"
                    993: "-d, --dismount [MAPPED_VOLUME]\n"
                    994: " Dismount and unmap mapped volumes. If MAPPED_VOLUME is not specified, all\n"
                    995: " volumes are dismounted and unmapped. See below for a description of\n"
                    996: " MAPPED_VOLUME.\n"
                    997: "\n"
                    998: "-l, --list [MAPPED_VOLUME]\n"
                    999: " Display a list of mapped volumes. If MAPPED_VOLUME is not specified, all\n"
                   1000: " volumes are listed. By default, the list contains only volume path and mapped\n"
                   1001: " device name pairs. A more detailed list can be enabled by verbose output\n"
                   1002: " option (-v). See below for a description of MAPPED_VOLUME.\n"
                   1003: "\n"
                   1004: "MAPPED_VOLUME\n"
                   1005: " Specifies a mapped or mounted volume. One of the following forms can be used:\n\n"
                   1006: " 1) Path to the encrypted TrueCrypt volume.\n\n"
                   1007: " 2) Mount directory of the volume's filesystem (if mounted).\n\n"
                   1008: " 3) Device number of the mapped volume.\n\n"
                   1009: " 4) Device name of the mapped volume.\n\n"
                   1010: "\n"
                   1011: "--device-number N\n"
                   1012: " Use device number N when mapping a volume as a block device\n"
                   1013: " /dev/mapper/truecryptN. Default is the first available device.\n"
                   1014: "\n"
                   1015: "--display-password\n"
                   1016: " Display password characters while typing.\n"
                   1017: "\n"
                   1018: "--filesystem TYPE\n"
                   1019: " Filesystem type to mount. The TYPE argument is passed to mount(8) command\n"
                   1020: " with option -t. Default type is 'auto'.\n"
                   1021: "\n"
                   1022: "-h, --help\n"
                   1023: " Display help information.\n"
                   1024: "\n"
                   1025: "-k, --keyfile FILE | DIRECTORY\n"
                   1026: " Use specified keyfile to open a volume to be mapped. When a directory is\n"
                   1027: " specified, all files inside it will be used (non-recursively). Additional\n"
                   1028: " keyfiles can be specified with multiple -k options. See also option -K.\n"
                   1029: "\n"
                   1030: "-K, --keyfile-protected FILE | DIRECTORY\n"
                   1031: " Use specified keyfile to open a hidden volume to be protected. See also\n"
                   1032: " options -k and -P.\n"
                   1033: "\n"
                   1034: "--mount-options OPTIONS\n"
                   1035: " Filesystem mount options. The OPTIONS argument is passed to mount(8)\n"
                   1036: " command with option -o.\n"
                   1037: " \n"
                   1038: "-p, --password PASSWORD\n"
                   1039: " Use specified password to open a volume. Additional passwords can be\n"
                   1040: " specified with multiple -p options. An empty password can also be specified\n"
                   1041: " (\"\" in most shells). Note that passing a password on the command line is\n"
                   1042: " potentially insecure as the password may be visible in the process list\n"
                   1043: " (see ps(1)) and/or stored in a command history file. \n"
                   1044: " \n"
                   1045: "--password-tries NUMBER\n"
                   1046: " Prompt NUMBER of times for a password until the correct password is entered.\n"
                   1047: " Default is to prompt three times.\n"
                   1048: "\n"
                   1049: "-P, --protect-hidden\n"
                   1050: " Write-protect a hidden volume when mapping an outer volume. Before mapping the\n"
                   1051: " outer volume, the user will be prompted for a password to open the hidden\n"
                   1052: " volume. The size and position of the hidden volume is then determined and the\n"
                   1053: " outer volume is mounted with all sectors belonging to the hidden volume\n"
                   1054: " protected against write operations. When a write to the protected area is\n"
                   1055: " prevented, the whole volume is switched to read-only mode. Verbose list command\n"
                   1056: " (-vl) can be used to query the state of the hidden volume protection. Warning\n"
                   1057: " message is displayed when a volume switched to read-only is being dismounted.\n"
                   1058: " See also option -r.\n"
                   1059: " \n"
                   1060: "-r, --read-only\n"
                   1061: " Map and/or mount a volume as read-only. Write operations to the volume may not\n"
                   1062: " fail immediately due to the write buffering performed by the system, but the\n"
                   1063: " physical write will still be prevented.\n"
                   1064: " \n"
                   1065: "--test\n"
                   1066: " Test all internal algorithms used in the process of encryption and decryption.\n"
                   1067: "\n"
                   1068: "--update-time\n"
                   1069: " Do not preserve access and modification timestamps of volume containers and\n"
                   1070: " access timestamps of keyfiles. By default, timestamps are restored after\n"
                   1071: " a volume is unmapped or after a keyfile is closed.\n"
                   1072: "\n"
                   1073: "-v, --verbose\n"
                   1074: " Enable verbose output. Multiple -v options can be specified to increase the\n"
                   1075: " level of verbosity.\n"
                   1076: "\n"
                   1077: "-V, --version\n"
                   1078: " Display version information.\n"
                   1079: "\n"
                   1080: "Examples:\n"
                   1081: "\n"
                   1082: "truecrypt /root/volume.tc /mnt/tc\n"
                   1083: " Map a volume /root/volume.tc and mount its filesystem at /mnt/tc.\n"
                   1084: "\n"
                   1085: "truecrypt -d\n"
                   1086: " Dismount and unmap all mapped volumes.\n"
                   1087: "  \n"
                   1088: "truecrypt -d /root/volume.tc\n"
                   1089: " Dismount and unmap a volume /root/volume.tc.\n"
                   1090: "\n"
                   1091: "truecrypt -d /mnt/tc\n"
                   1092: " Dismount and unmap a volume mounted at /mnt/tc.\n"
                   1093: "\n"
                   1094: "truecrypt -vl\n"
                   1095: " Display a detailed list of all mapped volumes.\n"
                   1096: " \n"
                   1097: "truecrypt --device-number=1 /dev/hdc1 && mkfs /dev/mapper/truecrypt1\n"
                   1098: " Map a volume /dev/hdc1 and create a new filesystem on it.\n"
                   1099: "\n"
                   1100: "truecrypt -P /dev/hdc1 /mnt/tc\n"
                   1101: " Map and mount outer volume /dev/hdc1 and protect hidden volume within it.\n"
                   1102: "\n"
                   1103: "truecrypt -p \"\" -p \"\" -k key1 -k key2 -K key_hidden -P volume.tc\n"
                   1104: " Map outer volume ./volume.tc and protect hidden volume within it.\n"
                   1105: " The outer volume is opened with keyfiles ./key1 and ./key2 and the\n"
                   1106: " hidden volume with ./key_hidden. Passwords for both volumes are empty.\n"
                   1107: "\n"
                   1108: "Report bugs at <http://www.truecrypt.org/bugs>.\n"
                   1109:        );
                   1110: }
                   1111: 
                   1112: static BOOL DumpMountList (int devNo)
                   1113: {
                   1114:        int i;
                   1115: 
                   1116:        if (!CheckKernelModuleVersion (FALSE))
                   1117:                return FALSE;
                   1118: 
                   1119:        if (!GetMountList ())
                   1120:                return FALSE;
                   1121: 
                   1122:        for (i = 0; MountList[i].DeviceNumber != -1; i++)
                   1123:        {
                   1124:                MountListEntry *e = &MountList[i];
                   1125: 
                   1126:                if (devNo != -1 && e->DeviceNumber != devNo)
                   1127:                        continue;
                   1128: 
                   1129:                if (Verbose == 0)
                   1130:                {
                   1131:                        printf (TC_MAP_DEV "%d %s\n",
                   1132:                                e->DeviceNumber,
                   1133:                                e->VolumePath);
                   1134:                }
                   1135:                else
                   1136:                {
                   1137:                        char eaName[128];
                   1138:                        EAGetName (eaName, e->EA);
                   1139: 
                   1140:                        printf (TC_MAP_DEV "%d:\n"
                   1141:                                        " Volume: %s\n"
                   1142:                                        " Type: %s\n"
                   1143:                                        " Size: %lld bytes\n"
                   1144:                                        " Encryption algorithm: %s\n"
1.1.1.2 ! root     1145:                                        " Mode of operation: %s\n"
1.1       root     1146:                                        " Read-only: %s\n"
                   1147:                                        " Hidden volume protected: %s\n\n",
                   1148:                                e->DeviceNumber,
                   1149:                                e->VolumePath,
                   1150:                                e->Hidden ? "Hidden" : "Normal",
                   1151:                                e->VolumeSize,
                   1152:                                eaName,
1.1.1.2 ! root     1153:                                EAGetModeName (e->EA, e->Mode, TRUE),
1.1       root     1154:                                (e->Flags & FLAG_READ_ONLY) ? "Yes" : "No",
                   1155:                                (e->Flags & FLAG_PROTECTION_ACTIVATED) ? "Yes - damage prevented" : (
                   1156:                                        (e->Flags & FLAG_HIDDEN_VOLUME_PROTECTION) ? "Yes" : "No" )
                   1157:                                );
                   1158:                }
                   1159:        }
                   1160: 
                   1161:        return TRUE;
                   1162: }
                   1163: 
                   1164: 
                   1165: static BOOL EnumMountPoints (char *device, char *mountPoint)
                   1166: {
                   1167:        static FILE *m = NULL;
                   1168: 
                   1169:        if (device == NULL)
                   1170:        {
                   1171:                fclose (m);
                   1172:                m = NULL;
                   1173:                return TRUE;
                   1174:        }
                   1175: 
                   1176:        if (m == NULL)
                   1177:        {
                   1178:                m = fopen ("/proc/mounts", "r");
                   1179:                if (m == NULL)
                   1180:                {
                   1181:                        perror ("fopen /proc/mounts");
                   1182:                        return FALSE;
                   1183:                }
                   1184:        }
                   1185: 
                   1186:        if (fscanf (m, "%" MAX_PATH_STR "s %" MAX_PATH_STR "s %*s %*s %*s %*s",
                   1187:                device, mountPoint) != 2)
                   1188:        {
                   1189:                fclose (m);
                   1190:                m = NULL;
                   1191:                return FALSE;
                   1192:        }
                   1193: 
                   1194:        return TRUE;
                   1195: }
                   1196: 
                   1197: 
                   1198: static BOOL DismountFileSystem (char *device)
                   1199: {
                   1200:        char mountedDevice[MAX_PATH], mountPoint[MAX_PATH];
                   1201:        BOOL result = TRUE;
                   1202: 
                   1203:        while (EnumMountPoints (mountedDevice, mountPoint))
                   1204:        {
                   1205:                if (strcmp (mountedDevice, device) == 0)
                   1206:                {
                   1207:                        if (!Execute (FALSE, "umount", mountPoint, NULL))
                   1208:                                result = FALSE;
                   1209:                        else if (Verbose >= 1)
                   1210:                                printf ("Dismounted %s\n", mountPoint);
                   1211:                }
                   1212:        }
                   1213: 
                   1214:        return result;
                   1215: }
                   1216: 
                   1217: 
                   1218: // devNo: -1 = Dismount all volumes
                   1219: static BOOL DismountVolume (int devNo)
                   1220: {
                   1221:        char mapDevice[MAX_PATH];
                   1222:        int nMountedVolumes = 0;
                   1223:        int i;
                   1224:        BOOL found = FALSE;
                   1225:        BOOL status = TRUE;
                   1226: 
                   1227:        if (!CheckKernelModuleVersion (FALSE))
                   1228:                return FALSE;
                   1229: 
                   1230:        if (!GetMountList ())
                   1231:                return FALSE;
                   1232: 
                   1233:        if (devNo == -1 && MountList[0].DeviceNumber == -1)
                   1234:        {
                   1235:                error ("No volumes mounted\n");
                   1236:                return FALSE;
                   1237:        }
                   1238: 
                   1239:        // Flush write buffers before dismount if there are
                   1240:        // mounted volumes with hidden volume protection 
                   1241:        for (i = 0; MountList[i].DeviceNumber != -1; i++)
                   1242:        {
                   1243:                if (MountList[i].Flags & FLAG_HIDDEN_VOLUME_PROTECTION)
                   1244:                {
                   1245:                        sync ();
                   1246:                        MountListValid = FALSE;
                   1247:                        GetMountList ();
                   1248:                        break;
                   1249:                }
                   1250:        }
                   1251: 
                   1252:        for (i = 0; MountList[i].DeviceNumber != -1; i++)
                   1253:        {
                   1254:                MountListEntry *e = &MountList[i];
                   1255:                nMountedVolumes++;
                   1256: 
                   1257:                if (devNo == -1 || e->DeviceNumber == devNo)
                   1258:                {
                   1259:                        BOOL dismounted = FALSE;
                   1260:                        found = TRUE;
                   1261: 
                   1262:                        if (e->Flags & FLAG_PROTECTION_ACTIVATED)
                   1263:                                printf ("WARNING: Write to the hidden volume %s has been prevented!\n", e->VolumePath);
                   1264: 
                   1265:                        sprintf (mapDevice, TC_MAP_DEV "%d", e->DeviceNumber);
                   1266:                        if (DismountFileSystem (mapDevice))
                   1267:                        {
                   1268:                                char name[32];
                   1269:                                sprintf (name, "truecrypt%d", e->DeviceNumber);
                   1270:                                dismounted = Execute (FALSE, "dmsetup", "remove", name, NULL);
                   1271: 
                   1272:                                if (dismounted && IsFile (e->VolumePath))
                   1273:                                {
                   1274:                                        if (!DeleteLoopDevice (e->DeviceMinor))
                   1275:                                                status = FALSE;
                   1276: 
                   1277:                                        RestoreFileTime (e->VolumePath,
                   1278:                                                UpdateTime ? time (NULL) : (time_t) e->ModTime,
                   1279:                                                UpdateTime ? time (NULL) : (time_t) e->AcTime);
                   1280:                                }
                   1281:                        }
                   1282: 
                   1283:                        if (!dismounted)
                   1284:                        {
                   1285:                                error ("Cannot dismount %s\n", mapDevice);
                   1286:                                status = FALSE;
                   1287:                        }
                   1288:                        else
                   1289:                        {
                   1290:                                nMountedVolumes--;
                   1291:                                if (Verbose >= 1)
                   1292:                                        printf ("Unmapped %s\n", mapDevice);
                   1293:                        }
                   1294: 
                   1295:                        if (devNo != -1)
                   1296:                                break;
                   1297:                }
                   1298:        }
                   1299: 
                   1300:        if (!found)
                   1301:        {
                   1302:                error (TC_MAP_DEV "%d not mounted\n", devNo);
                   1303:                return FALSE;
                   1304:        }
                   1305: 
                   1306:        if (nMountedVolumes == 0)
                   1307:        {
                   1308:                // Ignore errors as volumes may be mounted asynchronously
                   1309:                UnloadKernelModule (TRUE);
                   1310:        }
                   1311: 
                   1312:        return status;
                   1313: }
                   1314: 
                   1315: 
                   1316: // Convert a string to device number
                   1317: // text: device number or name or mount point
                   1318: BOOL ToDeviceNumber (char *text, int *deviceNumber)
                   1319: {
                   1320:        char mountedDevice[MAX_PATH], mountPoint[MAX_PATH];
                   1321:        int i;
                   1322: 
                   1323:        if (sscanf (text, "%d", deviceNumber) == 1)
                   1324:                return TRUE;
                   1325: 
                   1326:        if (sscanf (text, TC_MAP_DEV "%d", deviceNumber) == 1)
                   1327:                return TRUE;
                   1328: 
                   1329:        while (EnumMountPoints (mountedDevice, mountPoint))
                   1330:        {
                   1331:                if (strcmp (mountPoint, text) == 0
                   1332:                        && sscanf (mountedDevice, TC_MAP_DEV "%d", deviceNumber) == 1)
                   1333:                {
                   1334:                        EnumMountPoints (NULL, NULL);
                   1335:                        return TRUE;
                   1336:                }
                   1337:        }
                   1338: 
                   1339:        if (!GetMountList ())
                   1340:                return FALSE;
                   1341: 
                   1342:        for (i = 0; MountList[i].DeviceNumber != -1; i++)
                   1343:        {
                   1344:                MountListEntry *e = &MountList[i];
                   1345:                if (e->DeviceNumber == -1)
                   1346:                        break;
                   1347: 
                   1348:                if (strcmp (text, e->VolumePath) == 0)
                   1349:                {
                   1350:                        *deviceNumber = e->DeviceNumber;
                   1351:                        return TRUE;
                   1352:                }
                   1353:        }
                   1354: 
                   1355:        error ("%s not mounted\n", text);
                   1356:        return FALSE;
                   1357: }
                   1358: 
                   1359: 
1.1.1.2 ! root     1360: BOOL CheckAdminPrivileges ()
        !          1361: {
        !          1362:        char path[MAX_PATH];
        !          1363:        char *env;
        !          1364: 
        !          1365:        if (getuid () != 0 && geteuid () != 0)
        !          1366:        {
        !          1367:                error ("Administrator (root) privileges required\n");
        !          1368:                return FALSE;
        !          1369:        }
        !          1370: 
        !          1371:        if (getuid () != 0)
        !          1372:        {
        !          1373:                // Impersonate root to support executing of commands like mount
        !          1374:                setuid (0);
        !          1375: 
        !          1376:                env = getenv ("PATH");
        !          1377:                
        !          1378:                snprintf (path, sizeof (path),
        !          1379:                        "%s%s/sbin:/usr/sbin:/bin",
        !          1380:                        env ? env : "",
        !          1381:                        env ? ":" : "");
        !          1382: 
        !          1383:                setenv ("PATH", path, 1);
        !          1384:        }
        !          1385: 
        !          1386:        return TRUE;
        !          1387: }
        !          1388: 
        !          1389: 
        !          1390: BOOL LockMemory ()
        !          1391: {
        !          1392:        // Lock process memory
        !          1393:        if (mlockall (MCL_FUTURE) != 0)
        !          1394:        {
        !          1395:                perror ("Cannot prevent memory swapping: mlockall");
        !          1396:                return FALSE;
        !          1397:        }
        !          1398: 
        !          1399:        return TRUE;
        !          1400: }
        !          1401: 
        !          1402: 
        !          1403: int main (int argc, char **argv)
1.1       root     1404: {
                   1405:        char *volumePath = NULL;
                   1406:        char *mountPoint = NULL;
                   1407:        char volumePathBuf[MAX_PATH];
                   1408:        int i, o;
                   1409:        int optIndex = 0;
1.1.1.2 ! root     1410:        FILE *f;
1.1       root     1411: 
                   1412:        struct option longOptions[] = {
                   1413:                {"device-number", required_argument, 0, 0},
                   1414:                {"dismount", optional_argument, 0, 'd'},
                   1415:                {"display-password", 0, 0, 0},
                   1416:                {"keyfile", required_argument, 0, 'k'},
                   1417:                {"keyfile-protected", required_argument, 0, 'K'},
                   1418:                {"filesystem", required_argument, 0, 0},
                   1419:                {"list", 0, 0, 'l'},
                   1420:                {"help", 0, 0, 'h'},
                   1421:                {"mount-options", required_argument, 0, 0},
                   1422:                {"password", required_argument, 0, 'l'},
                   1423:                {"password-tries", required_argument, 0, 0},
                   1424:                {"protect-hidden", 0, 0, 'P'},
                   1425:                {"read-only", 0, 0, 'r'},
                   1426:                {"test", 0, 0, 0},
                   1427:                {"update-time", 0, 0, 0},
                   1428:                {"verbose", 0, 0, 'v'},
                   1429:                {"version", 0, 0, 'V'},
                   1430:                {0, 0, 0, 0}
                   1431:        };
                   1432: 
1.1.1.2 ! root     1433:        // Make sure pipes will not use file descriptors <= STDERR_FILENO
        !          1434:        f = fdopen (STDIN_FILENO, "r");
        !          1435:        if (f == NULL)
        !          1436:                open ("/dev/null", 0);
        !          1437: 
        !          1438:        f = fdopen (STDOUT_FILENO, "w");
        !          1439:        if (f == NULL)
        !          1440:                open ("/dev/null", 0);
        !          1441: 
        !          1442:        f = fdopen (STDERR_FILENO, "w");
        !          1443:        if (f == NULL)
        !          1444:                open ("/dev/null", 0);
1.1       root     1445: 
                   1446:        signal (SIGHUP, OnSignal);
                   1447:        signal (SIGINT, OnSignal);
                   1448:        signal (SIGQUIT, OnSignal);
                   1449:        signal (SIGABRT, OnSignal);
                   1450:        signal (SIGPIPE, OnSignal);
                   1451:        signal (SIGTERM, OnSignal);
                   1452: 
                   1453:        atexit (OnExit);
                   1454: 
                   1455:        while ((o = getopt_long (argc, argv, "dhk:K:lp:PrvV", longOptions, &optIndex)) != -1)
                   1456:        {
                   1457:                switch (o)
                   1458:                {
                   1459:                case 'd':
                   1460:                        // Dismount
                   1461:                        {
                   1462:                                int devNo;
                   1463: 
                   1464:                                if (optind < argc)
                   1465:                                {
                   1466:                                        if (!ToDeviceNumber (argv[optind++], &devNo))
                   1467:                                                return 1;
                   1468: 
                   1469:                                        if (optind < argc)
                   1470:                                                goto usage;
                   1471:                                }
                   1472:                                else
                   1473:                                        devNo = -1;
                   1474: 
1.1.1.2 ! root     1475:                                if (!CheckAdminPrivileges ())
        !          1476:                                        return 1;
        !          1477: 
1.1       root     1478:                                return DismountVolume (devNo) ? 0 : 1;
                   1479:                        }
                   1480: 
                   1481:                case 'l':
                   1482:                        // List
                   1483:                        {
                   1484:                                int devNo;
                   1485: 
                   1486:                                if (optind < argc)
                   1487:                                {
                   1488:                                        if (!ToDeviceNumber (argv[optind++], &devNo))
                   1489:                                                return 1;
                   1490: 
                   1491:                                        if (optind < argc)
                   1492:                                                goto usage;
                   1493:                                }
                   1494:                                else
                   1495:                                        devNo = -1;
                   1496: 
1.1.1.2 ! root     1497:                                if (!CheckAdminPrivileges ())
        !          1498:                                        return 1;
        !          1499: 
1.1       root     1500:                                return DumpMountList (devNo) ? 0 : 1;
                   1501:                        }
                   1502: 
                   1503:                case 'k':
                   1504:                case 'K':
                   1505:                        // Keyfile
                   1506:                        {
                   1507:                                KeyFile *kf = malloc (sizeof (KeyFile));
                   1508:                                if (!kf)
                   1509:                                {
                   1510:                                        perror ("malloc");
                   1511:                                        return 1;
                   1512:                                }
                   1513:                                strncpy (kf->FileName, optarg, sizeof (kf->FileName));
                   1514:                                if (o == 'k')
                   1515:                                        FirstKeyFile = KeyFileAdd (FirstKeyFile, kf);
                   1516:                                else
                   1517:                                        FirstProtVolKeyFile = KeyFileAdd (FirstProtVolKeyFile, kf);
                   1518:                        }
                   1519:                        break;
                   1520: 
                   1521: 
                   1522:                case 'p':
                   1523:                        // Password
                   1524:                        if (!CmdPasswordValid)
                   1525:                        {
                   1526:                                strncpy (CmdPassword.Text, optarg, sizeof (CmdPassword.Text));
                   1527:                                CmdPassword.Length = strlen (CmdPassword.Text);
                   1528:                                CmdPasswordValid = TRUE;
                   1529:                        }
                   1530:                        else if (!CmdPassword2Valid)
                   1531:                        {
                   1532:                                strncpy (CmdPassword2.Text, optarg, sizeof (CmdPassword2.Text));
                   1533:                                CmdPassword2.Length = strlen (CmdPassword2.Text);
                   1534:                                CmdPassword2Valid = TRUE;
                   1535:                        }
                   1536:                        break;
                   1537: 
                   1538:                case 'P':
                   1539:                        // Hidden volume protection
                   1540:                        ProtectHidden = TRUE;
                   1541:                        break;
                   1542: 
                   1543:                case 'r':
                   1544:                        ReadOnly = TRUE;
                   1545:                        break;
                   1546: 
                   1547:                case 'v':
                   1548:                        // Verbose
                   1549:                        Verbose++;
                   1550:                        break;
                   1551: 
                   1552:                case 'V':
                   1553:                        DumpVersion (stdout);
                   1554:                        return 0;
                   1555: 
                   1556:                case 'h':
                   1557:                        // Help
                   1558:                        DumpHelp ();
                   1559:                        return 0;
                   1560: 
                   1561:                case 0:
                   1562:                        if (strcmp ("display-password", longOptions[optIndex].name) == 0)
                   1563:                        {
                   1564:                                DisplayPassword = TRUE;
                   1565:                                break;
                   1566:                        }
                   1567: 
                   1568:                        if (strcmp ("device-number", longOptions[optIndex].name) == 0)
                   1569:                        {
                   1570:                                if (sscanf (optarg, "%d", &UseDeviceNumber) == 1
                   1571:                                        && UseDeviceNumber >= 0)
                   1572:                                        break;
                   1573:                                else
                   1574:                                        goto usage;
                   1575:                        }
                   1576: 
                   1577:                        if (strcmp ("filesystem", longOptions[optIndex].name) == 0)
                   1578:                        {
                   1579:                                Filesystem = optarg;
                   1580:                                break;
                   1581:                        }
                   1582: 
                   1583:                        if (strcmp ("mount-options", longOptions[optIndex].name) == 0)
                   1584:                        {
                   1585:                                MountOpts = optarg;
                   1586:                                break;
                   1587:                        }
                   1588: 
                   1589:                        if (strcmp ("password-tries", longOptions[optIndex].name) == 0)
                   1590:                        {
                   1591:                                if (sscanf (optarg, "%d", &PasswordEntryTries) == 1)
                   1592:                                        break;
                   1593:                                else
                   1594:                                        goto usage;
                   1595:                        }
                   1596:                        
                   1597:                        if (strcmp ("test", longOptions[optIndex].name) == 0)
                   1598:                        {
                   1599:                                if (AutoTestAlgorithms ())
                   1600:                                {
                   1601:                                        printf ("Self-tests of all algorithms passed.\n");
                   1602:                                        return 0;
                   1603:                                }
                   1604: 
                   1605:                                printf ("Self-tests of algorithms FAILED!\n");
                   1606:                                return 1;
                   1607:                        }
                   1608: 
                   1609:                        if (strcmp ("update-time", longOptions[optIndex].name) == 0)
                   1610:                        {
                   1611:                                UpdateTime = TRUE;
                   1612:                                break;
                   1613:                        }
                   1614:                        goto usage;
                   1615: 
                   1616:                default:
                   1617:                        goto usage;
                   1618:                }
                   1619:        }
                   1620:        
                   1621:        if (optind >= argc)
                   1622:                goto usage;
                   1623: 
                   1624:        if (optind < argc)
                   1625:                volumePath = argv[optind++];
                   1626: 
                   1627:        if (optind < argc)
                   1628:                mountPoint = argv[optind++];
                   1629: 
                   1630:        if (optind < argc)
                   1631:                goto usage;
                   1632: 
1.1.1.2 ! root     1633:        if (!CheckAdminPrivileges ())
        !          1634:                return 1;
        !          1635: 
        !          1636:        LockMemory ();
        !          1637: 
1.1       root     1638:        // Relative path => absolute
                   1639:        if (volumePath[0] != '/')
                   1640:        {
                   1641:                char s[MAX_PATH];
                   1642:                getcwd (s, sizeof (s));
                   1643:                snprintf (volumePathBuf, sizeof (volumePathBuf), "%s/%s", s, volumePath);
                   1644:                volumePath = volumePathBuf;
                   1645:        }
                   1646: 
                   1647:        return MountVolume (volumePath, mountPoint) == FALSE;
                   1648: 
                   1649: usage:
                   1650:        DumpUsage (stderr);
                   1651: 
                   1652:        return 1;
                   1653: }

unix.superglobalmegacorp.com

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