"Fossies" - the Fresh Open Source Software Archive

Member "src/Main/CommandLineInterface.cpp" (10 Oct 2018, 24825 Bytes) of package /windows/misc/VeraCrypt_1.23-Hotfix-2_Source.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "CommandLineInterface.cpp" see the Fossies "Dox" file reference documentation.

    1 /*
    2  Derived from source code of TrueCrypt 7.1a, which is
    3  Copyright (c) 2008-2012 TrueCrypt Developers Association and which is governed
    4  by the TrueCrypt License 3.0.
    5 
    6  Modifications and additions to the original source code (contained in this file)
    7  and all other portions of this file are Copyright (c) 2013-2017 IDRIX
    8  and are governed by the Apache License 2.0 the full text of which is
    9  contained in the file License.txt included in VeraCrypt binary and source
   10  code distribution packages.
   11 */
   12 
   13 #include "System.h"
   14 #include <wx/cmdline.h>
   15 #include <wx/tokenzr.h>
   16 #include "Core/Core.h"
   17 #include "Application.h"
   18 #include "CommandLineInterface.h"
   19 #include "LanguageStrings.h"
   20 #include "UserInterfaceException.h"
   21 
   22 namespace VeraCrypt
   23 {
   24     CommandLineInterface::CommandLineInterface (int argc, wchar_t** argv, UserInterfaceType::Enum interfaceType) :
   25         ArgCommand (CommandId::None),
   26         ArgFilesystem (VolumeCreationOptions::FilesystemType::Unknown),
   27         ArgNewPim (-1),
   28         ArgNoHiddenVolumeProtection (false),
   29         ArgPim (-1),
   30         ArgSize (0),
   31         ArgVolumeType (VolumeType::Unknown),
   32         ArgTrueCryptMode (false),
   33         StartBackgroundTask (false)
   34     {
   35         wxCmdLineParser parser;
   36         parser.SetCmdLine (argc, argv);
   37 
   38         parser.SetSwitchChars (L"-");
   39 
   40         parser.AddOption (L"",  L"auto-mount",          _("Auto mount device-hosted/favorite volumes"));
   41         parser.AddSwitch (L"",  L"backup-headers",      _("Backup volume headers"));
   42         parser.AddSwitch (L"",  L"background-task",     _("Start Background Task"));
   43 #ifdef TC_WINDOWS
   44         parser.AddSwitch (L"",  L"cache",               _("Cache passwords and keyfiles"));
   45 #endif
   46         parser.AddSwitch (L"C", L"change",              _("Change password or keyfiles"));
   47         parser.AddSwitch (L"c", L"create",              _("Create new volume"));
   48         parser.AddSwitch (L"",  L"create-keyfile",      _("Create new keyfile"));
   49         parser.AddSwitch (L"",  L"delete-token-keyfiles", _("Delete security token keyfiles"));
   50         parser.AddSwitch (L"d", L"dismount",            _("Dismount volume"));
   51         parser.AddSwitch (L"",  L"display-password",    _("Display password while typing"));
   52         parser.AddOption (L"",  L"encryption",          _("Encryption algorithm"));
   53         parser.AddSwitch (L"",  L"explore",             _("Open explorer window for mounted volume"));
   54         parser.AddSwitch (L"",  L"export-token-keyfile",_("Export keyfile from security token"));
   55         parser.AddOption (L"",  L"filesystem",          _("Filesystem type"));
   56         parser.AddSwitch (L"f", L"force",               _("Force mount/dismount/overwrite"));
   57 #if !defined(TC_WINDOWS) && !defined(TC_MACOSX)
   58         parser.AddOption (L"",  L"fs-options",          _("Filesystem mount options"));
   59 #endif
   60         parser.AddOption (L"",  L"hash",                _("Hash algorithm"));
   61         parser.AddSwitch (L"h", L"help",                _("Display detailed command line help"), wxCMD_LINE_OPTION_HELP);
   62         parser.AddSwitch (L"",  L"import-token-keyfiles", _("Import keyfiles to security token"));
   63         parser.AddOption (L"k", L"keyfiles",            _("Keyfiles"));
   64         parser.AddSwitch (L"l", L"list",                _("List mounted volumes"));
   65         parser.AddSwitch (L"",  L"list-token-keyfiles", _("List security token keyfiles"));
   66         parser.AddSwitch (L"",  L"load-preferences",    _("Load user preferences"));
   67         parser.AddSwitch (L"",  L"mount",               _("Mount volume interactively"));
   68         parser.AddOption (L"m", L"mount-options",       _("VeraCrypt volume mount options"));
   69         parser.AddOption (L"",  L"new-hash",            _("New hash algorithm"));
   70         parser.AddOption (L"",  L"new-keyfiles",        _("New keyfiles"));
   71         parser.AddOption (L"",  L"new-password",        _("New password"));
   72         parser.AddOption (L"",  L"new-pim",             _("New PIM"));
   73         parser.AddSwitch (L"",  L"non-interactive",     _("Do not interact with user"));
   74         parser.AddSwitch (L"",  L"stdin",               _("Read password from standard input"));
   75         parser.AddOption (L"p", L"password",            _("Password"));
   76         parser.AddOption (L"",  L"pim",                 _("PIM"));
   77         parser.AddOption (L"",  L"protect-hidden",      _("Protect hidden volume"));
   78         parser.AddOption (L"",  L"protection-hash",     _("Hash algorithm for protected hidden volume"));
   79         parser.AddOption (L"",  L"protection-keyfiles", _("Keyfiles for protected hidden volume"));
   80         parser.AddOption (L"",  L"protection-password", _("Password for protected hidden volume"));
   81         parser.AddOption (L"",  L"protection-pim",      _("PIM for protected hidden volume"));
   82         parser.AddOption (L"",  L"random-source",       _("Use file as source of random data"));
   83         parser.AddSwitch (L"",  L"restore-headers",     _("Restore volume headers"));
   84         parser.AddSwitch (L"",  L"save-preferences",    _("Save user preferences"));
   85         parser.AddSwitch (L"",  L"quick",               _("Enable quick format"));
   86         parser.AddOption (L"",  L"size",                _("Size in bytes"));
   87         parser.AddOption (L"",  L"slot",                _("Volume slot number"));
   88         parser.AddSwitch (L"tc",L"truecrypt",           _("Enable TrueCrypt mode. Should be put first to avoid issues."));
   89         parser.AddSwitch (L"",  L"test",                _("Test internal algorithms"));
   90         parser.AddSwitch (L"t", L"text",                _("Use text user interface"));
   91         parser.AddOption (L"",  L"token-lib",           _("Security token library"));
   92         parser.AddOption (L"",  L"token-pin",           _("Security token PIN"));
   93         parser.AddSwitch (L"v", L"verbose",             _("Enable verbose output"));
   94         parser.AddSwitch (L"",  L"version",             _("Display version information"));
   95         parser.AddSwitch (L"",  L"volume-properties",   _("Display volume properties"));
   96         parser.AddOption (L"",  L"volume-type",         _("Volume type"));
   97         parser.AddParam (                               _("Volume path"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL);
   98         parser.AddParam (                               _("Mount point"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL);
   99 
  100         wxString str;
  101         bool param1IsVolume = false;
  102         bool param1IsMountedVolumeSpec = false;
  103         bool param1IsMountPoint = false;
  104         bool param1IsFile = false;
  105 
  106         if (parser.Parse () > 0)
  107             throw_err (_("Incorrect command line specified."));
  108 
  109         if (parser.Found (L"help"))
  110         {
  111             ArgCommand = CommandId::Help;
  112             return;
  113         }
  114 
  115         if (parser.Found (L"text") && interfaceType != UserInterfaceType::Text)
  116         {
  117             wstring msg = wstring (_("Option -t or --text must be specified as the first argument."));
  118             wcerr << msg << endl;
  119             throw_err (msg);
  120         }
  121 
  122         if (parser.Found (L"version"))
  123         {
  124             ArgCommand = CommandId::DisplayVersion;
  125             return;
  126         }
  127 
  128         // Preferences
  129         if (parser.Found (L"load-preferences"))
  130         {
  131             // Load preferences first to allow command line options to override them
  132             Preferences.Load();
  133             ArgMountOptions = Preferences.DefaultMountOptions;
  134         }
  135 
  136         // Commands
  137         if (parser.Found (L"auto-mount", &str))
  138         {
  139             CheckCommandSingle();
  140 
  141             wxStringTokenizer tokenizer (str, L",");
  142             while (tokenizer.HasMoreTokens())
  143             {
  144                 wxString token = tokenizer.GetNextToken();
  145 
  146                 if (token == L"devices")
  147                 {
  148                     if (ArgCommand == CommandId::AutoMountFavorites)
  149                         ArgCommand = CommandId::AutoMountDevicesFavorites;
  150                     else
  151                         ArgCommand = CommandId::AutoMountDevices;
  152 
  153                     param1IsMountPoint = true;
  154                 }
  155                 else if (token == L"favorites")
  156                 {
  157                     if (ArgCommand == CommandId::AutoMountDevices)
  158                         ArgCommand = CommandId::AutoMountDevicesFavorites;
  159                     else
  160                         ArgCommand = CommandId::AutoMountFavorites;
  161                 }
  162                 else
  163                 {
  164                     throw_err (LangString["UNKNOWN_OPTION"] + L": " + token);
  165                 }
  166             }
  167         }
  168 
  169         if (parser.Found (L"backup-headers"))
  170         {
  171             CheckCommandSingle();
  172             ArgCommand = CommandId::BackupHeaders;
  173             param1IsVolume = true;
  174         }
  175 
  176         if (parser.Found (L"change"))
  177         {
  178             CheckCommandSingle();
  179             ArgCommand = CommandId::ChangePassword;
  180             param1IsVolume = true;
  181         }
  182 
  183         if (parser.Found (L"create"))
  184         {
  185             CheckCommandSingle();
  186             ArgCommand = CommandId::CreateVolume;
  187             param1IsVolume = true;
  188         }
  189 
  190         if (parser.Found (L"create-keyfile"))
  191         {
  192             CheckCommandSingle();
  193             ArgCommand = CommandId::CreateKeyfile;
  194             param1IsFile = true;
  195         }
  196 
  197         if (parser.Found (L"delete-token-keyfiles"))
  198         {
  199             CheckCommandSingle();
  200             ArgCommand = CommandId::DeleteSecurityTokenKeyfiles;
  201         }
  202 
  203         if (parser.Found (L"dismount"))
  204         {
  205             CheckCommandSingle();
  206             ArgCommand = CommandId::DismountVolumes;
  207             param1IsMountedVolumeSpec = true;
  208         }
  209 
  210         if (parser.Found (L"export-token-keyfile"))
  211         {
  212             CheckCommandSingle();
  213             ArgCommand = CommandId::ExportSecurityTokenKeyfile;
  214         }
  215 
  216         if (parser.Found (L"import-token-keyfiles"))
  217         {
  218             CheckCommandSingle();
  219             ArgCommand = CommandId::ImportSecurityTokenKeyfiles;
  220         }
  221 
  222         if (parser.Found (L"list"))
  223         {
  224             CheckCommandSingle();
  225             ArgCommand = CommandId::ListVolumes;
  226             param1IsMountedVolumeSpec = true;
  227         }
  228 
  229         if (parser.Found (L"list-token-keyfiles"))
  230         {
  231             CheckCommandSingle();
  232             ArgCommand = CommandId::ListSecurityTokenKeyfiles;
  233         }
  234 
  235         if (parser.Found (L"mount"))
  236         {
  237             CheckCommandSingle();
  238             ArgCommand = CommandId::MountVolume;
  239             param1IsVolume = true;
  240         }
  241 
  242         if (parser.Found (L"save-preferences"))
  243         {
  244             CheckCommandSingle();
  245             ArgCommand = CommandId::SavePreferences;
  246         }
  247 
  248         if (parser.Found (L"test"))
  249         {
  250             CheckCommandSingle();
  251             ArgCommand = CommandId::Test;
  252         }
  253 
  254         if (parser.Found (L"volume-properties"))
  255         {
  256             CheckCommandSingle();
  257             ArgCommand = CommandId::DisplayVolumeProperties;
  258             param1IsMountedVolumeSpec = true;
  259         }
  260 
  261         // Options
  262         if (parser.Found (L"background-task"))
  263             StartBackgroundTask = true;
  264 
  265 #ifdef TC_WINDOWS
  266         if (parser.Found (L"cache"))
  267             ArgMountOptions.CachePassword = true;
  268 #endif
  269         ArgDisplayPassword = parser.Found (L"display-password");
  270 
  271         if (parser.Found (L"encryption", &str))
  272         {
  273             ArgEncryptionAlgorithm.reset();
  274 
  275             foreach (shared_ptr <EncryptionAlgorithm> ea, EncryptionAlgorithm::GetAvailableAlgorithms())
  276             {
  277                 if (!ea->IsDeprecated() && wxString (ea->GetName()).IsSameAs (str, false))
  278                     ArgEncryptionAlgorithm = ea;
  279             }
  280 
  281             if (!ArgEncryptionAlgorithm)
  282                 throw_err (LangString["UNKNOWN_OPTION"] + L": " + str);
  283         }
  284 
  285         if (parser.Found (L"explore"))
  286             Preferences.OpenExplorerWindowAfterMount = true;
  287 
  288         if (parser.Found (L"filesystem", &str))
  289         {
  290             if (str.IsSameAs (L"none", false))
  291             {
  292                 ArgMountOptions.NoFilesystem = true;
  293                 ArgFilesystem = VolumeCreationOptions::FilesystemType::None;
  294             }
  295             else
  296             {
  297                 ArgMountOptions.FilesystemType = wstring (str);
  298 
  299                 if (str.IsSameAs (L"FAT", false))
  300                     ArgFilesystem = VolumeCreationOptions::FilesystemType::FAT;
  301 #ifdef TC_LINUX
  302                 else if (str.IsSameAs (L"Ext2", false))
  303                     ArgFilesystem = VolumeCreationOptions::FilesystemType::Ext2;
  304                 else if (str.IsSameAs (L"Ext3", false))
  305                     ArgFilesystem = VolumeCreationOptions::FilesystemType::Ext3;
  306                 else if (str.IsSameAs (L"Ext4", false))
  307                     ArgFilesystem = VolumeCreationOptions::FilesystemType::Ext4;
  308                 else if (str.IsSameAs (L"NTFS", false))
  309                     ArgFilesystem = VolumeCreationOptions::FilesystemType::NTFS;
  310                 else if (str.IsSameAs (L"exFAT", false))
  311                     ArgFilesystem = VolumeCreationOptions::FilesystemType::exFAT;
  312 #elif defined (TC_MACOSX)
  313                 else if (   str.IsSameAs (L"HFS", false)
  314                         ||  str.IsSameAs (L"HFS+", false)
  315                         ||  str.IsSameAs (L"MacOsExt", false)
  316                         )
  317                 {
  318                     ArgFilesystem = VolumeCreationOptions::FilesystemType::MacOsExt;
  319                 }
  320                 else if (str.IsSameAs (L"exFAT", false))
  321                     ArgFilesystem = VolumeCreationOptions::FilesystemType::exFAT;
  322 #elif defined (TC_FREEBSD) || defined (TC_SOLARIS)
  323                 else if (str.IsSameAs (L"UFS", false))
  324                     ArgFilesystem = VolumeCreationOptions::FilesystemType::UFS;
  325 #endif
  326                 else
  327                     ArgFilesystem = VolumeCreationOptions::FilesystemType::None;
  328             }
  329         }
  330 
  331         ArgForce = parser.Found (L"force");
  332 
  333         ArgTrueCryptMode = parser.Found (L"truecrypt");
  334 
  335 #if !defined(TC_WINDOWS) && !defined(TC_MACOSX)
  336         if (parser.Found (L"fs-options", &str))
  337             ArgMountOptions.FilesystemOptions = str;
  338 #endif
  339 
  340         if (parser.Found (L"hash", &str))
  341         {
  342             ArgHash.reset();
  343 
  344             foreach (shared_ptr <Hash> hash, Hash::GetAvailableAlgorithms())
  345             {
  346                 wxString hashName (hash->GetName());
  347                 wxString hashAltName (hash->GetAltName());
  348                 if (hashName.IsSameAs (str, false) || hashAltName.IsSameAs (str, false))
  349                     ArgHash = hash;
  350             }
  351 
  352             if (!ArgHash)
  353                 throw_err (LangString["UNKNOWN_OPTION"] + L": " + str);
  354         }
  355 
  356         if (parser.Found (L"new-hash", &str))
  357         {
  358             ArgNewHash.reset();
  359 
  360             foreach (shared_ptr <Hash> hash, Hash::GetAvailableAlgorithms())
  361             {
  362                 wxString hashName (hash->GetName());
  363                 wxString hashAltName (hash->GetAltName());
  364                 if (hashName.IsSameAs (str, false) || hashAltName.IsSameAs (str, false))
  365                     ArgNewHash = hash;
  366             }
  367 
  368             if (!ArgNewHash)
  369                 throw_err (LangString["UNKNOWN_OPTION"] + L": " + str);
  370         }
  371 
  372         if (parser.Found (L"keyfiles", &str))
  373             ArgKeyfiles = ToKeyfileList (str);
  374 
  375         if (parser.Found (L"mount-options", &str))
  376         {
  377             wxStringTokenizer tokenizer (str, L",");
  378             while (tokenizer.HasMoreTokens())
  379             {
  380                 wxString token = tokenizer.GetNextToken();
  381 
  382                 if (token == L"headerbak")
  383                     ArgMountOptions.UseBackupHeaders = true;
  384                 else if (token == L"nokernelcrypto")
  385                     ArgMountOptions.NoKernelCrypto = true;
  386                 else if (token == L"readonly" || token == L"ro")
  387                     ArgMountOptions.Protection = VolumeProtection::ReadOnly;
  388                 else if (token == L"system")
  389                     ArgMountOptions.PartitionInSystemEncryptionScope = true;
  390                 else if (token == L"timestamp" || token == L"ts")
  391                     ArgMountOptions.PreserveTimestamps = false;
  392 #ifdef TC_WINDOWS
  393                 else if (token == L"removable" || token == L"rm")
  394                     ArgMountOptions.Removable = true;
  395 #endif
  396                 else
  397                     throw_err (LangString["UNKNOWN_OPTION"] + L": " + token);
  398             }
  399         }
  400 
  401         if (parser.Found (L"new-keyfiles", &str))
  402             ArgNewKeyfiles = ToKeyfileList (str);
  403 
  404         if (parser.Found (L"new-password", &str))
  405             ArgNewPassword = ToUTF8Password (str.c_str());
  406 
  407         if (parser.Found (L"new-pim", &str))
  408         {
  409             try
  410             {
  411                 ArgNewPim = StringConverter::ToInt32 (wstring (str));
  412             }
  413             catch (...)
  414             {
  415                 throw_err (LangString["PARAMETER_INCORRECT"] + L": " + str);
  416             }
  417 
  418             if (ArgNewPim < 0 || ArgNewPim > (ArgMountOptions.PartitionInSystemEncryptionScope? MAX_BOOT_PIM_VALUE: MAX_PIM_VALUE))
  419                 throw_err (LangString["PARAMETER_INCORRECT"] + L": " + str);
  420             else if (ArgNewPim > 0 && ArgTrueCryptMode)
  421                 throw_err (LangString["PIM_NOT_SUPPORTED_FOR_TRUECRYPT_MODE"]);
  422         }
  423 
  424         if (parser.Found (L"non-interactive"))
  425         {
  426             if (interfaceType != UserInterfaceType::Text)
  427                 throw_err (L"--non-interactive is supported only in text mode");
  428 
  429             Preferences.NonInteractive = true;
  430         }
  431 
  432         if (parser.Found (L"stdin"))
  433         {
  434             if (!Preferences.NonInteractive)
  435                 throw_err (L"--stdin is supported only in non-interactive mode");
  436 
  437             Preferences.UseStandardInput = true;
  438         }
  439 
  440         if (parser.Found (L"password", &str))
  441         {
  442             if (Preferences.UseStandardInput)
  443                 throw_err (L"--password cannot be used with --stdin");
  444             ArgPassword = ToUTF8Password (str.c_str());
  445         }
  446 
  447         if (parser.Found (L"pim", &str))
  448         {
  449             try
  450             {
  451                 ArgPim = StringConverter::ToInt32 (wstring (str));
  452             }
  453             catch (...)
  454             {
  455                 throw_err (LangString["PARAMETER_INCORRECT"] + L": " + str);
  456             }
  457 
  458             if (ArgPim < 0 || ArgPim > (ArgMountOptions.PartitionInSystemEncryptionScope? MAX_BOOT_PIM_VALUE: MAX_PIM_VALUE))
  459                 throw_err (LangString["PARAMETER_INCORRECT"] + L": " + str);
  460             else if (ArgPim > 0 && ArgTrueCryptMode)
  461                 throw_err (LangString["PIM_NOT_SUPPORTED_FOR_TRUECRYPT_MODE"]);
  462         }
  463 
  464         if (parser.Found (L"protect-hidden", &str))
  465         {
  466             if (str == L"yes")
  467             {
  468                 if (ArgMountOptions.Protection != VolumeProtection::ReadOnly)
  469                     ArgMountOptions.Protection = VolumeProtection::HiddenVolumeReadOnly;
  470             }
  471             else if (str == L"no")
  472                 ArgNoHiddenVolumeProtection = true;
  473             else
  474                 throw_err (LangString["UNKNOWN_OPTION"] + L": " + str);
  475         }
  476 
  477         if (parser.Found (L"protection-keyfiles", &str))
  478         {
  479             ArgMountOptions.ProtectionKeyfiles = ToKeyfileList (str);
  480             ArgMountOptions.Protection = VolumeProtection::HiddenVolumeReadOnly;
  481         }
  482 
  483         if (parser.Found (L"protection-password", &str))
  484         {
  485             ArgMountOptions.ProtectionPassword = ToUTF8Password (str.c_str());
  486             ArgMountOptions.Protection = VolumeProtection::HiddenVolumeReadOnly;
  487         }
  488 
  489         if (parser.Found (L"protection-pim", &str))
  490         {
  491             int pim = -1;
  492             try
  493             {
  494                 pim = StringConverter::ToInt32 (wstring (str));
  495                 if (pim < 0 || pim > (ArgMountOptions.PartitionInSystemEncryptionScope? MAX_BOOT_PIM_VALUE: MAX_PIM_VALUE))
  496                     throw_err (LangString["PARAMETER_INCORRECT"] + L": " + str);
  497             }
  498             catch (...)
  499             {
  500                 throw_err (LangString["PARAMETER_INCORRECT"] + L": " + str);
  501             }
  502             ArgMountOptions.ProtectionPim = pim;
  503             ArgMountOptions.Protection = VolumeProtection::HiddenVolumeReadOnly;
  504         }
  505 
  506         if (parser.Found (L"protection-hash", &str))
  507         {
  508             bool bHashFound = false;
  509             foreach (shared_ptr <Hash> hash, Hash::GetAvailableAlgorithms())
  510             {
  511                 wxString hashName (hash->GetName());
  512                 wxString hashAltName (hash->GetAltName());
  513                 if (hashName.IsSameAs (str, false) || hashAltName.IsSameAs (str, false))
  514                 {
  515                     bHashFound = true;
  516                     ArgMountOptions.ProtectionKdf = Pkcs5Kdf::GetAlgorithm (*hash, ArgTrueCryptMode);
  517                 }
  518             }
  519 
  520             if (!bHashFound)
  521                 throw_err (LangString["UNKNOWN_OPTION"] + L": " + str);
  522         }
  523 
  524         ArgQuick = parser.Found (L"quick");
  525 
  526         if (parser.Found (L"random-source", &str))
  527             ArgRandomSourcePath = FilesystemPath (str.wc_str());
  528 
  529         if (parser.Found (L"restore-headers"))
  530         {
  531             CheckCommandSingle();
  532             ArgCommand = CommandId::RestoreHeaders;
  533             param1IsVolume = true;
  534         }
  535 
  536         if (parser.Found (L"slot", &str))
  537         {
  538             unsigned long number;
  539             if (!str.ToULong (&number) || number < Core->GetFirstSlotNumber() || number > Core->GetLastSlotNumber())
  540                 throw_err (LangString["PARAMETER_INCORRECT"] + L": " + str);
  541 
  542             ArgMountOptions.SlotNumber = number;
  543 
  544             if (param1IsMountedVolumeSpec)
  545             {
  546                 shared_ptr <VolumeInfo> volume = Core->GetMountedVolume (number);
  547                 if (!volume)
  548                     throw_err (_("No such volume is mounted."));
  549 
  550                 ArgVolumes.push_back (volume);
  551                 param1IsMountedVolumeSpec = false;
  552             }
  553         }
  554 
  555         if (parser.Found (L"size", &str))
  556         {
  557             uint64 multiplier;
  558             wxChar lastChar = str [str.Length () - 1];
  559             if (lastChar >= wxT('0') && lastChar <= wxT('9'))
  560                 multiplier = 1;
  561             else if (lastChar == wxT('K') || lastChar == wxT('k'))
  562                 multiplier = BYTES_PER_KB;
  563             else if (lastChar == wxT('M') || lastChar == wxT('m'))
  564                 multiplier = BYTES_PER_MB;
  565             else if (lastChar == wxT('G') || lastChar == wxT('g'))
  566                 multiplier = BYTES_PER_GB;
  567             else if (lastChar == wxT('T') || lastChar == wxT('t'))
  568                 multiplier = BYTES_PER_TB;
  569             else
  570                 throw_err (LangString["PARAMETER_INCORRECT"] + L": " + str);
  571 
  572             // remove suffix if present
  573             if (multiplier != 1)
  574                 str.RemoveLast ();
  575             // check that we only have digits in the string
  576             size_t index = str.find_first_not_of (wxT("0123456789"));
  577             if (index != (size_t) wxNOT_FOUND)
  578             {
  579                 // restore last characater for error display
  580                 if (multiplier != 1)
  581                     str += lastChar;
  582                 throw_err (LangString["PARAMETER_INCORRECT"] + L": " + str);
  583             }
  584             try
  585             {
  586                 ArgSize = multiplier * StringConverter::ToUInt64 (wstring (str));
  587             }
  588             catch (...)
  589             {
  590                 throw_err (LangString["PARAMETER_INCORRECT"] + L": " + str);
  591             }
  592         }
  593 
  594         if (parser.Found (L"token-lib", &str))
  595             Preferences.SecurityTokenModule = wstring (str);
  596 
  597         if (parser.Found (L"token-pin", &str) && !str.IsEmpty ())
  598         {
  599             ArgTokenPin = ToUTF8Buffer (str.c_str(), str.Len ());
  600         }
  601 
  602         if (parser.Found (L"verbose"))
  603             Preferences.Verbose = true;
  604 
  605         if (parser.Found (L"volume-type", &str))
  606         {
  607             if (str.IsSameAs (L"normal", false))
  608                 ArgVolumeType = VolumeType::Normal;
  609             else if (str.IsSameAs (L"hidden", false))
  610                 ArgVolumeType = VolumeType::Hidden;
  611             else
  612                 throw_err (LangString["UNKNOWN_OPTION"] + L": " + str);
  613         }
  614 
  615         // Parameters
  616         if (parser.GetParamCount() > 0)
  617         {
  618             // in case of GUI interface, we load the preference when only
  619             // specifying volume path without any option/switch
  620             if (Application::GetUserInterfaceType() != UserInterfaceType::Text)
  621             {
  622                 // check if only parameters were specified in the command line
  623                 // (e.g. when associating .hc extension in mimetype with /usr/bin/veracrypt)
  624                 bool onlyParametersPresent = (parser.GetParamCount() == (size_t) (argc - 1));
  625 
  626                 if (onlyParametersPresent)
  627                 {
  628                     // no options/switches, so we load prefences now
  629                     Preferences.Load();
  630                     ArgMountOptions = Preferences.DefaultMountOptions;
  631                 }
  632             }
  633 
  634             if (ArgCommand == CommandId::None)
  635             {
  636                 ArgCommand = CommandId::MountVolume;
  637                 param1IsVolume = true;
  638             }
  639 
  640             if (param1IsVolume)
  641             {
  642                 wxFileName volPath (parser.GetParam (0));
  643 
  644 #ifdef TC_WINDOWS
  645                 if (!parser.GetParam (0).StartsWith (L"\\Device\\"))
  646 #endif
  647                     volPath.Normalize (wxPATH_NORM_ABSOLUTE | wxPATH_NORM_DOTS);
  648 
  649                 ArgVolumePath.reset (new VolumePath (wstring (volPath.GetFullPath())));
  650             }
  651 
  652             if (param1IsMountPoint || parser.GetParamCount() >= 2)
  653             {
  654                 wstring s (parser.GetParam (param1IsMountPoint ? 0 : 1));
  655 
  656                 if (s.empty())
  657                     ArgMountOptions.NoFilesystem = true;
  658 
  659                 wxFileName mountPoint (wstring (Directory::AppendSeparator (s)));
  660                 mountPoint.Normalize (wxPATH_NORM_ABSOLUTE | wxPATH_NORM_DOTS);
  661                 ArgMountPoint.reset (new DirectoryPath (wstring (mountPoint.GetPath())));
  662             }
  663 
  664             if (param1IsFile)
  665             {
  666                 ArgFilePath.reset (new FilePath (parser.GetParam (0).wc_str()));
  667             }
  668         }
  669 
  670         if (param1IsMountedVolumeSpec)
  671             ArgVolumes = GetMountedVolumes (parser.GetParamCount() > 0 ? parser.GetParam (0) : wxString());
  672 
  673         if (ArgCommand == CommandId::None && Application::GetUserInterfaceType() == UserInterfaceType::Text)
  674             parser.Usage();
  675     }
  676 
  677     CommandLineInterface::~CommandLineInterface ()
  678     {
  679     }
  680 
  681     void CommandLineInterface::CheckCommandSingle () const
  682     {
  683         if (ArgCommand != CommandId::None)
  684             throw_err (_("Only a single command can be specified at a time."));
  685     }
  686 
  687     shared_ptr <KeyfileList> CommandLineInterface::ToKeyfileList (const wxString &arg) const
  688     {
  689         wxStringTokenizer tokenizer (arg, L",", wxTOKEN_RET_EMPTY_ALL);
  690 
  691         // Handle escaped separator
  692         wxArrayString arr;
  693         bool prevEmpty = false;
  694         while (tokenizer.HasMoreTokens())
  695         {
  696             wxString token = tokenizer.GetNextToken();
  697 
  698             if (prevEmpty && token.empty() && tokenizer.HasMoreTokens())
  699             {
  700                 token = tokenizer.GetNextToken();
  701                 if (!token.empty())
  702                 {
  703                     arr.Add (token);
  704                     prevEmpty = true;
  705                     continue;
  706                 }
  707             }
  708 
  709             if (token.empty() && !tokenizer.HasMoreTokens())
  710                 break;
  711 
  712             if (prevEmpty || token.empty())
  713             {
  714                 if (arr.Count() < 1)
  715                 {
  716                     arr.Add (L"");
  717                     continue;
  718                 }
  719                 arr.Last() += token.empty() ? L"," : token.wc_str();
  720             }
  721             else
  722                 arr.Add (token);
  723 
  724             prevEmpty = token.empty();
  725         }
  726 
  727         make_shared_auto (KeyfileList, keyfileList);
  728         for (size_t i = 0; i < arr.GetCount(); i++)
  729         {
  730             if (!arr[i].empty())
  731                 keyfileList->push_back (make_shared <Keyfile> (wstring (arr[i])));
  732         }
  733 
  734         return keyfileList;
  735     }
  736 
  737     VolumeInfoList CommandLineInterface::GetMountedVolumes (const wxString &mountedVolumeSpec) const
  738     {
  739         VolumeInfoList volumes = Core->GetMountedVolumes ();
  740         VolumeInfoList filteredVolumes;
  741 
  742         wxFileName pathFilter;
  743         if (!mountedVolumeSpec.empty())
  744         {
  745             pathFilter = mountedVolumeSpec;
  746             pathFilter.Normalize (wxPATH_NORM_ABSOLUTE | wxPATH_NORM_DOTS);
  747         }
  748         else
  749             return volumes;
  750 
  751         foreach (shared_ptr <VolumeInfo> volume, volumes)
  752         {
  753             if (mountedVolumeSpec.empty())
  754             {
  755                 filteredVolumes.push_back (volume);
  756             }
  757             else if (wxString (wstring(volume->Path)) == pathFilter.GetFullPath())
  758             {
  759                 filteredVolumes.push_back (volume);
  760             }
  761             else if (wxString (wstring(volume->MountPoint)) == pathFilter.GetFullPath()
  762                 || (wxString (wstring(volume->MountPoint)) + wxFileName::GetPathSeparator()) == pathFilter.GetFullPath())
  763             {
  764                 filteredVolumes.push_back (volume);
  765             }
  766         }
  767 
  768         if (!mountedVolumeSpec.IsEmpty() && filteredVolumes.size() < 1)
  769             throw_err (_("No such volume is mounted."));
  770 
  771         return filteredVolumes;
  772     }
  773 
  774     shared_ptr<VolumePassword> ToUTF8Password (const wchar_t* str, size_t charCount)
  775     {
  776         if (charCount > 0)
  777         {
  778             shared_ptr<SecureBuffer> utf8Buffer = ToUTF8Buffer (str, charCount);
  779             return shared_ptr<VolumePassword>(new VolumePassword (*utf8Buffer));
  780         }
  781         else
  782             return shared_ptr<VolumePassword>(new VolumePassword ());
  783     }
  784 
  785     shared_ptr<SecureBuffer> ToUTF8Buffer (const wchar_t* str, size_t charCount)
  786     {
  787         if (charCount == (size_t) -1)
  788             charCount = wcslen (str);
  789 
  790         if (charCount > 0)
  791         {
  792             wxMBConvUTF8 utf8;
  793             size_t ulen = utf8.FromWChar (NULL, 0, str, charCount);
  794             if (wxCONV_FAILED == ulen)
  795                 throw PasswordUTF8Invalid (SRC_POS);
  796             SecureBuffer passwordBuf(ulen);
  797             ulen = utf8.FromWChar ((char*) (byte*) passwordBuf, ulen, str, charCount);
  798             if (wxCONV_FAILED == ulen)
  799                 throw PasswordUTF8Invalid (SRC_POS);
  800             if (ulen > VolumePassword::MaxSize)
  801                 throw PasswordUTF8TooLong (SRC_POS);
  802 
  803             ConstBufferPtr utf8Buffer ((byte*) passwordBuf, ulen);
  804             return shared_ptr<SecureBuffer>(new SecureBuffer (utf8Buffer));
  805         }
  806         else
  807             return shared_ptr<SecureBuffer>(new SecureBuffer ());
  808     }
  809 
  810     auto_ptr <CommandLineInterface> CmdLine;
  811 }