--- truecrypt/linux/cli/cli.c 2018/04/24 16:45:58 1.1.1.4 +++ truecrypt/linux/cli/cli.c 2018/04/24 16:46:50 1.1.1.5 @@ -1,8 +1,9 @@ -/* -Copyright (c) 2004-2006 TrueCrypt Foundation. All rights reserved. +/* + Copyright (c) TrueCrypt Foundation. All rights reserved. -Covered by TrueCrypt License 2.1 the full text of which is contained in the file -License.txt included in TrueCrypt binary and source code distribution archives. + Covered by the TrueCrypt License 2.2 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. */ #define _LARGEFILE_SOURCE 1 @@ -14,7 +15,7 @@ License.txt included in TrueCrypt binary #include #include #include -#include +#include #include #include #include @@ -33,6 +34,7 @@ License.txt included in TrueCrypt binary #include "Keyfiles.h" #include "Fat.h" #include "Format.h" +#include "Password.h" #include "Progress.h" #include "Random.h" #include "Volumes.h" @@ -129,7 +131,7 @@ static BOOL CheckAdminPrivileges () if (getuid () != 0) { - // Impersonate root to support executing of commands like mount + // Impersonate root to support execution of commands like mount setuid (0); // Allow execution of system binaries only @@ -151,7 +153,7 @@ static BOOL LockMemory () // Lock process memory if (mlockall (MCL_FUTURE) != 0) { - perror ("Cannot prevent memory swapping: mlockall"); + perror ("Cannot prevent paging of memory to disk: mlockall"); return FALSE; } @@ -233,7 +235,7 @@ static BOOL Execute (BOOL quiet, char *e execvp (execName, args); - fprintf (stderr, "%s ", execName); + fprintf (stderr, "(%s) ", execName); perror ("execlp"); _exit (1); } @@ -500,7 +502,7 @@ static BOOL GetMountList (BOOL force) if (!fgets (s, sizeof (s), p)) break; - if (sscanf (s, "truecrypt%d: 0 %llu truecrypt %d %d 0 0 %d:%d %llu %llu %llu %llu %llu %d %n", + if (sscanf (s, "truecrypt%d: 0 %llu truecrypt %d %d 0 0 %d:%d %llu %llu %llu %llu %llu %llu %d %n", &e->DeviceNumber, &e->VolumeSize, &e->EA, @@ -510,6 +512,7 @@ static BOOL GetMountList (BOOL force) &e->Hidden, &e->ReadOnlyStart, &e->ReadOnlyEnd, + &e->UserId, &e->ModTime, &e->AcTime, &e->Flags, @@ -616,7 +619,7 @@ static BOOL DeleteLoopDevice (int loopDe static int AskSelection (int defaultChoice, int min, int max) { int c; - char s[3]; + char s[10]; while (1) { @@ -631,6 +634,9 @@ static int AskSelection (int defaultChoi return c; } + if (s[0] != 0 && s[0] != '\n') + continue; + puts (""); return defaultChoice; } @@ -675,9 +681,33 @@ static char *AskString (char *prompt, ch } +static BOOL ValidatePassword (Password *password) +{ + int i; + + if (password->Length > MAX_PASSWORD) + { + error ("Maximum password length is %d characters\n", MAX_PASSWORD); + return FALSE; + } + + for (i = 0; i < password->Length; i++) + { + if (password->Text[i] >= 0x7f || password->Text[i] < 0x20) + { + error ("Password must be composed only of US-ASCII printable characters\n"); + return FALSE; + } + } + + return TRUE; +} + + static void AskPassword (char *prompt, char *volumePath, Password *password) { struct termios noEcho; + char pw[2048]; if (tcgetattr (0, &TerminalAttributes) == 0) { @@ -689,19 +719,32 @@ static void AskPassword (char *prompt, c if (tcsetattr (0, TCSANOW, &noEcho) != 0) error ("Failed to turn terminal echo off\n"); } - - printf (prompt, volumePath); } - if (fgets ((char *)password->Text, sizeof (password->Text), stdin)) + while (TRUE) { - char *newl = strchr ((char *)password->Text, '\n'); + char *newl; + + if (IsTerminal) + printf (prompt, volumePath); + + if (!fgets (pw, sizeof (pw), stdin)) + { + password->Length = 0; + break; + } + + newl = strchr (pw, '\n'); if (newl) newl[0] = 0; + strncpy ((char *)password->Text, pw, sizeof (password->Text)); password->Length = strlen ((char *)password->Text); + + if (ValidatePassword (password)) + break; } - else - password->Length = 0; + + burn(pw, sizeof (pw)); if (IsTerminal && !DisplayPassword) { @@ -934,6 +977,22 @@ static char *EscapeSpaces (char *string) } +static BOOL IsMountPointAvailable (char *mountPoint) +{ + char md[TC_MAX_PATH], mp[TC_MAX_PATH]; + + while (EnumMountPoints (md, mp)) + { + if (strcmp (mountPoint, mp) == 0) + { + EnumMountPoints (NULL, NULL); + return FALSE; + } + } + return TRUE; +} + + static BOOL MountVolume (char *volumePath, char *mountPoint) { char hostDevice[TC_MAX_PATH]; @@ -964,6 +1023,12 @@ static BOOL MountVolume (char *volumePat return FALSE; } + if (mountPoint && !IsMountPointAvailable (mountPoint)) + { + error ("Mount directory %s already in use\n", mountPoint); + return FALSE; + } + if (!OpenVolume (volumePath, "Enter password for '%s': ", volumePath, FALSE, &ci, &startSector, &totalSectors, &modTime, &acTime)) goto err; @@ -1018,7 +1083,7 @@ static BOOL MountVolume (char *volumePat if (i >= TC_MAX_MINOR) { - error ("No free loopback device available for file-hosted volume\n"); + error ("Failed to assign loopback device for file-hosted volume\n"); goto err; } @@ -1094,11 +1159,12 @@ static BOOL MountVolume (char *volumePat else if (ProtectHidden) flags |= TC_HIDDEN_VOLUME_PROTECTION; - fprintf (w, " %s %llu %llu %llu %llu %llu %d %s\n", + fprintf (w, " %s %llu %llu %llu %llu %llu %llu %d %s\n", hostDevice, startSector, readOnlyStartSector, readOnlySectors, + (unsigned long long) RealUserId, (unsigned long long) modTime, (unsigned long long) acTime, flags, @@ -1120,9 +1186,9 @@ static BOOL MountVolume (char *volumePat // Mount if (mountPoint) { - char fstype[64], opts[128]; + char fstype[64] = "-t"; + char opts[1024]; - strcpy (fstype, "-t"); if (Filesystem) strncat (fstype, Filesystem, sizeof (fstype) - 3); else @@ -1132,14 +1198,17 @@ static BOOL MountVolume (char *volumePat if (MountOpts) { strcat (opts, ","); - strncat (opts, MountOpts, sizeof (opts) - 6); + strncat (opts, MountOpts, 256); } + if (RealUserId != 0) + strcat (opts, ",nosuid"); + if (UserMount) { // Set default uid and gid char s[64]; - sprintf (s, ",uid=%d,gid=%d", RealUserId, RealGroupId); + sprintf (s, ",uid=%d,gid=%d,umask=077", RealUserId, RealGroupId); strcat (opts, s); } @@ -1274,7 +1343,7 @@ keyboard: i = 0; while (1) { - char buf[TC_REQUIRED_KEYSTROKES * 4]; + char buf[TC_REQUIRED_KEYSTROKES * 8]; int l; if (!fgets (buf, sizeof (buf), stdin)) @@ -1417,7 +1486,6 @@ static BOOL CreateVolume (char *hostPath case VOLUME_TYPE_HIDDEN: hiddenVolume = TRUE; - Quick = TRUE; break; default: @@ -1426,6 +1494,9 @@ static BOOL CreateVolume (char *hostPath break; } + if (hiddenVolume) + Quick = TRUE; + // Host file or device hostPath = AskVolumePath (hostPath, hiddenVolume ? "Enter volume path" : "Enter file or device path for new volume"); @@ -1438,16 +1509,24 @@ static BOOL CreateVolume (char *hostPath } f = fopen (hostPath, "r+b"); } - else if (!Overwrite - && IsFile (hostPath) - && (!IsTerminal || !AskYesNo ("Volume already exists - overwrite?", TRUE))) - { - if (!IsTerminal) - error ("Volume already exists.\n"); - return FALSE; - } - else + else { + if (!Overwrite + && IsFile (hostPath) + && (!IsTerminal || !AskYesNo ("Volume already exists - overwrite?", TRUE))) + { + if (!IsTerminal) + error ("Volume already exists.\n"); + return FALSE; + } + + if (!Overwrite + && IsBlockDevice (hostPath) + && (!IsTerminal || !AskYesNo ("WARNING: Data on device will be lost. Continue?", TRUE))) + { + return FALSE; + } + f = fopen (hostPath, "wb"); deleteOnError = TRUE; } @@ -1523,7 +1602,6 @@ static BOOL CreateVolume (char *hostPath if (EA == 0) { int max = 0; -ea: puts ("Encryption algorithm:"); for (i = EAGetFirst (); i != 0; i = EAGetNext (i)) @@ -1536,21 +1614,6 @@ ea: } EA = AskSelection (1, EAGetFirst (), max); - - if (CipherGetBlockSize (EAGetFirstCipher (EA)) == 8 - && VolumeSize > WARN_VOL_SIZE_BLOCK64) - { - char s[3]; - - AskString ("WARNING: You have selected a 64-bit block cipher. Due to security reasons,\n" - "for this volume size, it is strongly recommended to select a 128-bit block cipher\n" - "(for example, AES, Serpent, or Twofish) instead.\n\n" - "Continue? [y/N]", s, sizeof (s)); - puts (""); - - if (strcmp (s, "y") && strcmp (s, "Y")) - goto ea; - } } // Password @@ -1584,7 +1647,7 @@ ea: if (!FirstKeyFile && pw->Length == 0) { - error ("Password cannot be empty when no keyfiles are specified\n"); + error ("Password cannot be empty when no keyfile is specified\n"); goto err; } @@ -1763,7 +1826,7 @@ static BOOL ChangePassword (char *volume if (!FirstNewKeyFile && pw->Length == 0) { - error ("Password cannot be empty when no keyfiles are specified\n"); + error ("Password cannot be empty when no keyfile is specified\n"); goto err; } @@ -2168,11 +2231,15 @@ static BOOL DumpVolumeProperties (char * ci->noIterations ); - // Separated from above to prevent seg faults in buggy libraries + memset (timeBuf, 0, sizeof (timeBuf)); + memset (timeBuf2, 0, sizeof (timeBuf2)); + + if (ctime_r (&volCTime, timeBuf) == NULL || ctime_r (&headerMTime, timeBuf2) == NULL) + goto err; + printf (" Volume created: %s" " Header modified: %s", - ctime_r (&volCTime, timeBuf), - ctime_r (&headerMTime, timeBuf2)); + timeBuf, timeBuf2); ret = TRUE; err: @@ -2190,11 +2257,10 @@ static void DumpVersion (FILE *f) { fprintf (f, "truecrypt %s\n\n\ -Released under the TrueCrypt Collective License 1.0\n\n\ -Copyright (C) 2004-2006 TrueCrypt Foundation. All Rights Reserved.\n\ +Released under the TrueCrypt Collective License 1.1\n\n\ +Copyright (C) 2003-2007 TrueCrypt Foundation. All Rights Reserved.\n\ Copyright (C) 1998-2000 Paul Le Roux. All Rights Reserved.\n\ -Copyright (C) 2004 TrueCrypt Team. All Rights Reserved.\n\ -Copyright (C) 1999-2005 Dr. Brian Gladman. All Rights Reserved.\n\ +Copyright (C) 1999-2006 Dr. Brian Gladman. All Rights Reserved.\n\ Copyright (C) 1995-1997 Eric Young. All Rights Reserved.\n\ Copyright (C) 2001 Markus Friedl. All Rights Reserved.\n\n" , VERSION_STRING); @@ -2226,7 +2292,7 @@ static void DumpUsage (FILE *f) " --properties [VOLUME_PATH] Display properties of volume\n" " --restore-header FILE [VOLUME] Restore header of VOLUME from FILE\n" " --test Test algorithms\n" -" -V, --version Display version information\n" +" -V, --version Display program version and legal notices\n" "\nOptions:\n" " --cluster SIZE Cluster size\n" " --display-keys Display encryption keys\n" @@ -2281,13 +2347,12 @@ static void DumpHelp () "VOLUME_PATH [MOUNT_DIRECTORY]\n" " Open a TrueCrypt volume specified by VOLUME_PATH and map it as a block device\n" " /dev/mapper/truecryptN. N is the first available device number if not\n" -" otherwise specified with -N. To map a hidden volume, specify its password\n" +" otherwise specified with -N. Filesystem of the mapped volume is mounted at\n" +" MOUNT_DIRECTORY if specified. To open a hidden volume, specify its password\n" " and/or keyfiles (the outer volume cannot be mapped at the same time).\n" -" Filesystem of the mapped volume is mounted at MOUNT_DIRECTORY if specified.\n" -" See also options --display-password, --filesystem, -k, -M, -p, -P,\n" +" See also EXAMPLES and options --display-password, --filesystem, -k, -M, -p, -P,\n" " --password-tries, -r, -u, --update-time. Note that passing some of the options\n" -" may affect security or plausible deniability. See options -i and -p for more\n" -" information.\n" +" may affect security (see options -i and -p for more information).\n" "\n" "--backup-headers BACKUP_FILE [VOLUME_PATH]\n" " Backup headers of a volume specified by VOLUME_PATH to a file BACKUP_FILE.\n" @@ -2309,8 +2374,8 @@ static void DumpHelp () " Note that this command drops effective user ID.\n" " See also options --cluster, --disable-progress, --display-keys,\n" " --encryption, -k, --filesystem, --hash, -p, --random-source, --quick, --size,\n" -" --type. Note that passing some of the options may affect security or plausible\n" -" deniability. See option -p for more information.\n" +" --type. Note that passing some of the options may affect security (see option\n" +" -p for more information).\n" "\n" "-C, --change [VOLUME_PATH]\n" " Change a password and/or keyfile(s) of a volume. Volume path and passwords are\n" @@ -2327,9 +2392,8 @@ static void DumpHelp () " Display help information.\n" "\n" "-i, --interactive\n" -" Map and mount a volume interactively. Options which may affect security or\n" -" plausible deniability are requested from the user. See option -p for more\n" -" information.\n" +" Map and mount a volume interactively. Options which may affect security are\n" +" requested from the user. See option -p for more information.\n" "\n" "-l, --list [MAPPED_VOLUME]\n" " Display a list of mapped volumes. If MAPPED_VOLUME is not specified, all\n" @@ -2355,7 +2419,7 @@ static void DumpHelp () " Test all internal algorithms used in the process of encryption and decryption.\n" "\n" "-V, --version\n" -" Display version information.\n" +" Display program version and legal notices.\n" "\n" "MAPPED_VOLUME:\n" " Specifies a mapped or mounted volume. One of the following forms can be used:\n\n" @@ -2393,7 +2457,7 @@ static void DumpHelp () " Use specified keyfile to open a volume to be mapped (or when changing password\n" " and/or keyfiles). When a directory is specified, all files inside it will be\n" " used (non-recursively). Additional keyfiles can be specified with multiple -k\n" -" options. Empty keyfile (-k "") disables interactive requests for keyfiles\n" +" options. Empty keyfile (-k '') disables interactive requests for keyfiles\n" " (e.g., when creating a new volume). See also option -K.\n" "\n" "-K, --keyfile-protected FILE | DIRECTORY\n" @@ -2408,7 +2472,8 @@ static void DumpHelp () "\n" "-M, --mount-options OPTIONS\n" " Filesystem mount options. The OPTIONS argument is passed to mount(8)\n" -" command with option -o.\n" +" command with option -o. This option can be specified only by an administrator.\n" +" See also options -r and -u.\n" "\n" "-N, --device-number N\n" " Use device number N when mapping a volume as a block device\n" @@ -2420,7 +2485,7 @@ static void DumpHelp () "-p, --password PASSWORD\n" " Use specified password to open a volume. Additional passwords can be\n" " specified with multiple -p options. An empty password can also be specified\n" -" (\"\" in most shells). Note that passing a password on the command line is\n" +" ('' in most shells). Note that passing a password on the command line is\n" " potentially insecure as the password may be visible in the process list\n" " (see ps(1)) and/or stored in a command history file. \n" " \n" @@ -2464,9 +2529,10 @@ static void DumpHelp () "\n" "-u, --user-mount\n" " Set default user and group ID of the filesystem being mounted to the user and\n" -" group ID of the process which executed TrueCrypt. Some filesystems (like FAT)\n" -" do not support user permissions and, therefore, it is necessary to supply a\n" -" default user and group ID to the system when mounting such filesystems.\n" +" group ID of the process which executed TrueCrypt. Some filesystems (e.g., FAT)\n" +" do not support Unix-style access control and, therefore, it is necessary to\n" +" supply a default user and group ID to the operating system when mounting them.\n" +" Note that Unix-style filesystems (e.g., ext2) do not support this option.\n" "\n" "--update-time\n" " Do not preserve access and modification timestamps of volume containers and\n" @@ -2485,7 +2551,7 @@ static void DumpHelp () "truecrypt -u /dev/hda2 /mnt/tc\n" " Map a volume /dev/hda2 (first ATA disk, primary partition 2) and mount its\n" " filesystem at /mnt/tc. Default user-id is set, which is useful when mounting\n" -" a filesystem like FAT under a non-admin user account.\n" +" a filesystem such as FAT under a non-admin user account.\n" "\n" "truecrypt -i\n" " Map and mount a volume. Options are requested interactively.\n" @@ -2508,7 +2574,7 @@ static void DumpHelp () "truecrypt -P /dev/hdc1 /mnt/tc\n" " Map and mount outer volume /dev/hdc1 and protect hidden volume within it.\n" "\n" -"truecrypt -p \"\" -p \"\" -k key1 -k key2 -K key_hidden -P volume.tc\n" +"truecrypt -p '' -p '' -k key1 -k key2 -K key_hidden -P volume.tc\n" " Map outer volume ./volume.tc and protect hidden volume within it.\n" " The outer volume is opened with keyfiles ./key1 and ./key2 and the\n" " hidden volume with ./key_hidden. Passwords for both volumes are empty.\n" @@ -2545,8 +2611,8 @@ static void DumpHelp () " 5) Dismount the outer volume:\n" " truecrypt -d volume.tc\n" " 6) If a warning message has been displayed in 5), start again from 1). Either\n" -" a larger outer volume should be created in 1), or smaller files should be\n" -" copied to the outer volume in 4).\n" +" a larger outer volume should be created in 1), or less data should be copied\n" +" to the outer volume in 4).\n" "\n" "Report bugs at .\n" ); @@ -2620,6 +2686,7 @@ static BOOL DumpMountList (int devNo) static BOOL EnumMountPoints (char *device, char *mountPoint) { static FILE *m = NULL; + char mp[TC_MAX_PATH], *p; if (device == NULL) { @@ -2635,17 +2702,35 @@ static BOOL EnumMountPoints (char *devic { perror ("fopen /proc/mounts"); return FALSE; - } + } } if (fscanf (m, "%" TC_MAX_PATH_STR "s %" TC_MAX_PATH_STR "s %*s %*s %*s %*s", - device, mountPoint) != 2) + device, mp) != 2) { fclose (m); m = NULL; return FALSE; } + // Convert escaped characters + p = mp; + while (*p) + { + if (p[0] == '\\' && p[1] && p[2] && p[3]) + { + char c; + if (sscanf (p + 1, "%o", &c) == 1) + { + *mountPoint++ = c; + p += 4; + continue; + } + } + *mountPoint++ = *p++; + } + *mountPoint = 0; + return TRUE; } @@ -2710,10 +2795,18 @@ static BOOL DismountVolume (int devNo) BOOL dismounted = FALSE; found = TRUE; + sprintf (mapDevice, TC_MAP_DEV "%d", e->DeviceNumber); + + if (RealUserId != 0 && e->UserId != RealUserId) + { + error ("Dismount denied: %s mapped by a different user\n", mapDevice); + status = FALSE; + continue; + } + if (e->Flags & TC_PROTECTION_ACTIVATED) printf ("WARNING: Write to the hidden volume %s has been prevented!\n", e->VolumePath); - sprintf (mapDevice, TC_MAP_DEV "%d", e->DeviceNumber); if (DismountFileSystem (mapDevice)) { char name[32]; @@ -2850,7 +2943,7 @@ int main (int argc, char **argv) {"help", 0, 0, 'h'}, {"mount-options", required_argument, 0, 'M'}, {"overwrite", 0, 0, 0}, - {"password", required_argument, 0, 'l'}, + {"password", required_argument, 0, 'p'}, {"password-tries", required_argument, 0, 0}, {"properties", optional_argument, 0, 0}, {"protect-hidden", 0, 0, 'P'}, @@ -3003,6 +3096,12 @@ int main (int argc, char **argv) break; case 'M': + if (RealUserId != 0) + { + error ("--mount-options can be specified only by an administrator (see options -r, -u)\n"); + return 1; + } + MountOpts = optarg; break; @@ -3016,10 +3115,10 @@ int main (int argc, char **argv) if (!CmdPasswordValid) { strncpy ((char *)CmdPassword.Text, optarg, sizeof (CmdPassword.Text)); - CmdPassword.Length = strlen ((char *)CmdPassword.Text); - if (CmdPassword.Length > MAX_PASSWORD) - CmdPassword.Length = MAX_PASSWORD; + + if (!ValidatePassword (&CmdPassword)) + return 1; CmdPasswordValid = TRUE; } @@ -3028,8 +3127,8 @@ int main (int argc, char **argv) strncpy ((char *)CmdPassword2.Text, optarg, sizeof (CmdPassword2.Text)); CmdPassword2.Length = strlen ((char *)CmdPassword2.Text); - if (CmdPassword2.Length > MAX_PASSWORD) - CmdPassword2.Length = MAX_PASSWORD; + if (!ValidatePassword (&CmdPassword2)) + return 1; CmdPassword2Valid = TRUE; } @@ -3292,7 +3391,7 @@ int main (int argc, char **argv) volumePath = AskVolumePath (volumePath, "Enter volume path"); // Mount point - mountPoint = AskString ("Enter mount point [none]", mp, sizeof (mp)); + mountPoint = AskString ("Enter mount directory [none]", mp, sizeof (mp)); if (mp[0] == 0) mountPoint = NULL;