Annotation of truecrypt/linux/cli/cli.c, revision 1.1.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.