/* Derived from source code of TrueCrypt 7.1a, which is Copyright (c) 2008-2012 TrueCrypt Developers Association and which is governed by the TrueCrypt License 3.0. Modifications and additions to the original source code (contained in this file) and all other portions of this file are Copyright (c) 2013-2017 IDRIX and are governed by the Apache License 2.0 the full text of which is contained in the file License.txt included in VeraCrypt binary and source code distribution packages. */ #include "System.h" #include #ifdef TC_WINDOWS #include #endif #include "Common/SecurityToken.h" #include "Main/Main.h" #include "Main/Application.h" #include "Main/GraphicUserInterface.h" #include "Volume/Cipher.h" #include "PreferencesDialog.h" namespace VeraCrypt { PreferencesDialog::PreferencesDialog (wxWindow* parent) : PreferencesDialogBase (parent), LastVirtualKeyPressed (0), Preferences (Gui->GetPreferences()), RestoreValidatorBell (false) { #define TC_CHECK_BOX_VALIDATOR(NAME) (TC_JOIN(NAME,CheckBox))->SetValidator (wxGenericValidator (&Preferences.NAME)); #ifdef TC_MACOSX PreferencesNotebook->SetMinSize (wxSize (Gui->GetCharWidth (PreferencesNotebook) * 108, -1)); #endif // Security TC_CHECK_BOX_VALIDATOR (DismountOnLogOff); TC_CHECK_BOX_VALIDATOR (DismountOnPowerSaving); TC_CHECK_BOX_VALIDATOR (DismountOnScreenSaver); TC_CHECK_BOX_VALIDATOR (DismountOnInactivity); DismountOnInactivitySpinCtrl->SetValidator (wxGenericValidator (&Preferences.MaxVolumeIdleTime)); TC_CHECK_BOX_VALIDATOR (ForceAutoDismount); PreserveTimestampsCheckBox->SetValidator (wxGenericValidator (&Preferences.DefaultMountOptions.PreserveTimestamps)); TC_CHECK_BOX_VALIDATOR (WipeCacheOnAutoDismount); TC_CHECK_BOX_VALIDATOR (WipeCacheOnClose); // Mount options CachePasswordsCheckBox->SetValidator (wxGenericValidator (&Preferences.DefaultMountOptions.CachePassword)); MountReadOnlyCheckBox->SetValue (Preferences.DefaultMountOptions.Protection == VolumeProtection::ReadOnly); MountRemovableCheckBox->SetValidator (wxGenericValidator (&Preferences.DefaultMountOptions.Removable)); FilesystemOptionsTextCtrl->SetValue (Preferences.DefaultMountOptions.FilesystemOptions); TrueCryptModeCheckBox->SetValidator (wxGenericValidator (&Preferences.DefaultMountOptions.TrueCryptMode)); int index, prfInitialIndex = 0; Pkcs5PrfChoice->Append (LangString["AUTODETECTION"]); foreach_ref (const Pkcs5Kdf &kdf, Pkcs5Kdf::GetAvailableAlgorithms(false)) { index = Pkcs5PrfChoice->Append (kdf.GetName()); if (Preferences.DefaultMountOptions.Kdf && (Preferences.DefaultMountOptions.Kdf->GetName() == kdf.GetName()) ) { prfInitialIndex = index; } } Pkcs5PrfChoice->Select (prfInitialIndex); // Keyfiles TC_CHECK_BOX_VALIDATOR (UseKeyfiles); DefaultKeyfilesPanel = new KeyfilesPanel (DefaultKeyfilesPage, make_shared (Preferences.DefaultKeyfiles)); DefaultKeyfilesSizer->Add (DefaultKeyfilesPanel, 1, wxALL | wxEXPAND); DefaultKeyfilesSizer->Layout(); TC_CHECK_BOX_VALIDATOR (BackgroundTaskEnabled); TC_CHECK_BOX_VALIDATOR (CloseBackgroundTaskOnNoVolumes); CloseBackgroundTaskOnNoVolumesCheckBox->Show (!Core->IsInPortableMode()); TC_CHECK_BOX_VALIDATOR (BackgroundTaskMenuDismountItemsEnabled); TC_CHECK_BOX_VALIDATOR (BackgroundTaskMenuMountItemsEnabled); TC_CHECK_BOX_VALIDATOR (BackgroundTaskMenuOpenItemsEnabled); // Encryption AesHwCpuSupportedStaticText->SetLabel ( #ifdef TC_AES_HW_CPU (is_aes_hw_cpu_supported() ? LangString["UISTR_YES"] : LangString["UISTR_NO"])); #else LangString["NOT_APPLICABLE_OR_NOT_AVAILABLE"]); #endif NoHardwareCryptoCheckBox->SetValidator (wxGenericValidator (&Preferences.DefaultMountOptions.NoHardwareCrypto)); // Security tokens Pkcs11ModulePathTextCtrl->SetValue (wstring (Preferences.SecurityTokenModule)); TC_CHECK_BOX_VALIDATOR (CloseSecurityTokenSessionsAfterMount); // System integration TC_CHECK_BOX_VALIDATOR (StartOnLogon); TC_CHECK_BOX_VALIDATOR (MountDevicesOnLogon); TC_CHECK_BOX_VALIDATOR (MountFavoritesOnLogon); TC_CHECK_BOX_VALIDATOR (CloseExplorerWindowsOnDismount); TC_CHECK_BOX_VALIDATOR (OpenExplorerWindowAfterMount); NoKernelCryptoCheckBox->SetValidator (wxGenericValidator (&Preferences.DefaultMountOptions.NoKernelCrypto)); #ifdef TC_WINDOWS // Hotkeys TC_CHECK_BOX_VALIDATOR (BeepAfterHotkeyMountDismount); TC_CHECK_BOX_VALIDATOR (DisplayMessageAfterHotkeyDismount); #endif TransferDataToWindow(); // Code below relies on TransferDataToWindow() called at this point #if defined (TC_WINDOWS) || defined (TC_MACOSX) FilesystemSizer->Show (false); #else // Auto-dismount is not supported on Linux as dismount may require the user to enter admin password AutoDismountSizer->Show (false); WipeCacheOnAutoDismountCheckBox->Show (false); #endif #ifndef TC_WINDOWS LogOnSizer->Show (false); MountRemovableCheckBox->Show (false); CloseExplorerWindowsOnDismountCheckBox->Show (false); #endif #ifndef wxHAS_POWER_EVENTS DismountOnPowerSavingCheckBox->Show (false); #endif #ifdef TC_MACOSX DismountOnScreenSaverCheckBox->Show (false); DismountOnLogOffCheckBox->SetLabel (_("VeraCrypt quits")); OpenExplorerWindowAfterMountCheckBox->SetLabel (_("Open Finder window for successfully mounted volume")); MountRemovableCheckBox->Show (false); FilesystemSizer->Show (false); LogOnSizer->Show (false); CloseExplorerWindowsOnDismountCheckBox->Show (false); #endif #ifndef TC_LINUX KernelServicesSizer->Show (false); #endif #ifdef TC_WINDOWS // Hotkeys list colPermilles; HotkeyListCtrl->InsertColumn (ColumnHotkeyDescription, LangString["ACTION"], wxLIST_FORMAT_LEFT, 1); colPermilles.push_back (642); HotkeyListCtrl->InsertColumn (ColumnHotkey, LangString["SHORTCUT"], wxLIST_FORMAT_LEFT, 1); colPermilles.push_back (358); vector fields (HotkeyListCtrl->GetColumnCount()); UnregisteredHotkeys = Preferences.Hotkeys; Hotkey::UnregisterList (Gui->GetMainFrame(), UnregisteredHotkeys); foreach (shared_ptr hotkey, Preferences.Hotkeys) { fields[ColumnHotkeyDescription] = hotkey->Description; fields[ColumnHotkey] = hotkey->GetShortcutString(); Gui->AppendToListCtrl (HotkeyListCtrl, fields, -1, hotkey.get()); } Gui->SetListCtrlHeight (HotkeyListCtrl, 5); Layout(); Fit(); Gui->SetListCtrlColumnWidths (HotkeyListCtrl, colPermilles); RestoreValidatorBell = !wxTextValidator::IsSilent(); wxTextValidator::SuppressBellOnError (true); HotkeyTextCtrl->SetValidator (wxTextValidator (wxFILTER_INCLUDE_CHAR_LIST)); UpdateHotkeyButtons(); #endif // Page setup for (size_t page = 0; page < PreferencesNotebook->GetPageCount(); page++) { wxNotebookPage *np = PreferencesNotebook->GetPage (page); if (np == HotkeysPage) { #ifndef TC_WINDOWS PreferencesNotebook->RemovePage (page--); continue; #endif } np->Layout(); } Layout(); Fit(); Center(); StdButtonsOK->SetDefault(); #ifdef TC_WINDOWS // Hotkey timer class Timer : public wxTimer { public: Timer (PreferencesDialog *dialog) : Dialog (dialog) { } void Notify() { Dialog->OnTimer(); } PreferencesDialog *Dialog; }; mTimer.reset (dynamic_cast (new Timer (this))); mTimer->Start (25); #endif } PreferencesDialog::~PreferencesDialog () { #ifdef TC_WINDOWS if (RestoreValidatorBell) wxTextValidator::SuppressBellOnError (false); #endif } void PreferencesDialog::SelectPage (wxPanel *page) { for (size_t pageIndex = 0; pageIndex < PreferencesNotebook->GetPageCount(); pageIndex++) { if (PreferencesNotebook->GetPage (pageIndex) == page) PreferencesNotebook->ChangeSelection (pageIndex); } } void PreferencesDialog::OnAssignHotkeyButtonClick (wxCommandEvent& event) { #ifdef TC_WINDOWS foreach (long item, Gui->GetListCtrlSelectedItems (HotkeyListCtrl)) { Hotkey *hotkey = reinterpret_cast (HotkeyListCtrl->GetItemData (item)); int mods = 0; mods |= HotkeyShiftCheckBox->IsChecked() ? wxMOD_SHIFT : 0; mods |= HotkeyControlCheckBox->IsChecked() ? wxMOD_CONTROL : 0; mods |= HotkeyAltCheckBox->IsChecked() ? wxMOD_ALT : 0; mods |= HotkeyWinCheckBox->IsChecked() ? wxMOD_WIN : 0; // F1 is help and F12 is reserved for use by the debugger at all times if (mods == 0 && (LastVirtualKeyPressed == VK_F1 || LastVirtualKeyPressed == VK_F12)) { Gui->ShowError ("CANNOT_USE_RESERVED_KEY"); return; } // Test if the hotkey can be registered if (!this->RegisterHotKey (hotkey->Id, mods, LastVirtualKeyPressed)) { Gui->ShowError (SystemException (SRC_POS)); return; } UnregisterHotKey (hotkey->Id); foreach_ref (const Hotkey &h, Preferences.Hotkeys) { if (h.Id != hotkey->Id && h.VirtualKeyCode == LastVirtualKeyPressed && h.VirtualKeyModifiers == mods) { Gui->ShowError ("SHORTCUT_ALREADY_IN_USE"); return; } } hotkey->VirtualKeyCode = LastVirtualKeyPressed; hotkey->VirtualKeyModifiers = mods; vector fields (HotkeyListCtrl->GetColumnCount()); fields[ColumnHotkeyDescription] = hotkey->Description; fields[ColumnHotkey] = hotkey->GetShortcutString(); Gui->UpdateListCtrlItem (HotkeyListCtrl, item, fields); UpdateHotkeyButtons(); } #endif // TC_WINDOWS } void PreferencesDialog::OnBackgroundTaskEnabledCheckBoxClick (wxCommandEvent& event) { if (!event.IsChecked()) BackgroundTaskEnabledCheckBox->SetValue (!Gui->AskYesNo (LangString["CONFIRM_BACKGROUND_TASK_DISABLED"], false, true)); } void PreferencesDialog::OnNoHardwareCryptoCheckBoxClick (wxCommandEvent& event) { if (event.IsChecked()) { if (Gui->AskYesNo (LangString["CONFIRM_SETTING_DEGRADES_PERFORMANCE"], true, true)) { #ifdef TC_LINUX Gui->ShowWarning (_("Please note that this setting takes effect only if use of the kernel cryptographic services is disabled.")); #endif } else NoHardwareCryptoCheckBox->SetValue (false); } Gui->ShowWarning (_("Please note that any currently mounted volumes need to be remounted before they can use this setting.")); } void PreferencesDialog::OnNoKernelCryptoCheckBoxClick (wxCommandEvent& event) { if (event.IsChecked()) NoKernelCryptoCheckBox->SetValue (Gui->AskYesNo (_("Disabling the use of kernel cryptographic services can degrade performance.\n\nAre you sure?"), false, true)); } void PreferencesDialog::OnClose (wxCloseEvent& event) { #ifdef TC_WINDOWS Hotkey::RegisterList (Gui->GetMainFrame(), UnregisteredHotkeys); #endif event.Skip(); } void PreferencesDialog::OnDismountOnPowerSavingCheckBoxClick (wxCommandEvent& event) { if (event.IsChecked() && !ForceAutoDismountCheckBox->IsChecked()) Gui->ShowWarning ("WARN_PREF_AUTO_DISMOUNT"); } void PreferencesDialog::OnDismountOnScreenSaverCheckBoxClick (wxCommandEvent& event) { if (event.IsChecked() && !ForceAutoDismountCheckBox->IsChecked()) Gui->ShowWarning ("WARN_PREF_AUTO_DISMOUNT"); } void PreferencesDialog::OnForceAutoDismountCheckBoxClick (wxCommandEvent& event) { if (!event.IsChecked()) ForceAutoDismountCheckBox->SetValue (!Gui->AskYesNo (LangString["CONFIRM_NO_FORCED_AUTODISMOUNT"], false, true)); } void PreferencesDialog::OnHotkeyListItemDeselected (wxListEvent& event) { UpdateHotkeyButtons(); } void PreferencesDialog::OnHotkeyListItemSelected (wxListEvent& event) { UpdateHotkeyButtons(); HotkeyTextCtrl->ChangeValue (LangString ["PRESS_A_KEY_TO_ASSIGN"]); AssignHotkeyButton->Enable (false); } void PreferencesDialog::OnOKButtonClick (wxCommandEvent& event) { #ifdef TC_WINDOWS HotkeyTextCtrl->SetValidator (wxTextValidator (wxFILTER_NONE)); #endif if (!Validate()) return; shared_ptr selectedKdf; if (Pkcs5PrfChoice->GetSelection () != 0) { try { selectedKdf = Pkcs5Kdf::GetAlgorithm (wstring (Pkcs5PrfChoice->GetStringSelection ()), TrueCryptModeCheckBox->IsChecked ()); } catch (ParameterIncorrect&) { Gui->ShowWarning ("ALGO_NOT_SUPPORTED_FOR_TRUECRYPT_MODE"); return; } } TransferDataFromWindow(); Preferences.DefaultMountOptions.Protection = MountReadOnlyCheckBox->IsChecked() ? VolumeProtection::ReadOnly : VolumeProtection::None; Preferences.DefaultMountOptions.FilesystemOptions = FilesystemOptionsTextCtrl->GetValue(); Preferences.DefaultKeyfiles = *DefaultKeyfilesPanel->GetKeyfiles(); Preferences.DefaultMountOptions.Kdf = selectedKdf; Preferences.DefaultMountOptions.ProtectionKdf = selectedKdf; bool securityTokenModuleChanged = (Preferences.SecurityTokenModule != wstring (Pkcs11ModulePathTextCtrl->GetValue())); Preferences.SecurityTokenModule = wstring (Pkcs11ModulePathTextCtrl->GetValue()); Gui->SetPreferences (Preferences); try { if (securityTokenModuleChanged) { if (Preferences.SecurityTokenModule.IsEmpty()) { if (SecurityToken::IsInitialized()) SecurityToken::CloseLibrary (); } else { Gui->InitSecurityTokenLibrary(); } } } catch (exception &e) { Gui->ShowError (e); } #ifdef TC_WINDOWS // Hotkeys Hotkey::RegisterList (Gui->GetMainFrame(), Preferences.Hotkeys); #endif EndModal (wxID_OK); } void PreferencesDialog::OnPreserveTimestampsCheckBoxClick (wxCommandEvent& event) { #ifdef TC_LINUX if (!event.IsChecked()) Gui->ShowInfo (_("Please note that disabling this option may have no effect on volumes mounted using kernel cryptographic services.")); #endif } void PreferencesDialog::OnRemoveHotkeyButtonClick (wxCommandEvent& event) { #ifdef TC_WINDOWS foreach (long item, Gui->GetListCtrlSelectedItems (HotkeyListCtrl)) { Hotkey *hotkey = reinterpret_cast (HotkeyListCtrl->GetItemData (item)); hotkey->VirtualKeyCode = 0; hotkey->VirtualKeyModifiers = 0; vector fields (HotkeyListCtrl->GetColumnCount()); fields[ColumnHotkeyDescription] = hotkey->Description; fields[ColumnHotkey] = hotkey->GetShortcutString(); Gui->UpdateListCtrlItem (HotkeyListCtrl, item, fields); UpdateHotkeyButtons(); } #endif } void PreferencesDialog::OnSelectPkcs11ModuleButtonClick (wxCommandEvent& event) { list < pair > extensions; wxString libExtension; libExtension = wxDynamicLibrary::CanonicalizeName (L"x"); #ifdef TC_MACOSX extensions.push_back (make_pair (L"dylib", LangString["DLL_FILES"].ToStdWstring())); #endif if (!libExtension.empty()) { extensions.push_back (make_pair (libExtension.Mid (libExtension.find (L'.') + 1).ToStdWstring(), LangString["DLL_FILES"].ToStdWstring())); extensions.push_back (make_pair (L"*", L"")); } string libDir; #ifdef TC_WINDOWS char sysDir[TC_MAX_PATH]; GetSystemDirectoryA (sysDir, sizeof (sysDir)); libDir = sysDir; #elif defined (TC_MACOSX) libDir = "/usr/local/lib"; #elif defined (TC_UNIX) libDir = "/usr/lib"; #endif Gui->ShowInfo ("SELECT_PKCS11_MODULE_HELP"); FilePathList files = Gui->SelectFiles (this, LangString["SELECT_PKCS11_MODULE"], false, false, extensions, libDir); if (!files.empty()) Pkcs11ModulePathTextCtrl->SetValue (wstring (*files.front())); } void PreferencesDialog::OnTimer () { #ifdef TC_WINDOWS for (UINT vKey = 0; vKey <= 0xFF; vKey++) { if (GetAsyncKeyState (vKey) < 0) { bool shift = wxGetKeyState (WXK_SHIFT); bool control = wxGetKeyState (WXK_CONTROL); bool alt = wxGetKeyState (WXK_ALT); bool win = wxGetKeyState (WXK_WINDOWS_LEFT) || wxGetKeyState (WXK_WINDOWS_RIGHT); if (!Hotkey::GetVirtualKeyCodeString (vKey).empty()) // If the key is allowed and its name has been resolved { LastVirtualKeyPressed = vKey; HotkeyShiftCheckBox->SetValue (shift); HotkeyControlCheckBox->SetValue (control); HotkeyAltCheckBox->SetValue (alt); HotkeyWinCheckBox->SetValue (win); HotkeyTextCtrl->ChangeValue (Hotkey::GetVirtualKeyCodeString (LastVirtualKeyPressed)); UpdateHotkeyButtons(); return; } } } #endif } void PreferencesDialog::UpdateHotkeyButtons() { AssignHotkeyButton->Enable (!HotkeyTextCtrl->IsEmpty() && HotkeyListCtrl->GetSelectedItemCount() > 0); bool remove = false; foreach (long item, Gui->GetListCtrlSelectedItems (HotkeyListCtrl)) { if (reinterpret_cast (HotkeyListCtrl->GetItemData (item))->VirtualKeyCode != 0) remove = true; } RemoveHotkeyButton->Enable (remove); } }