From 5c009d449e19f38e22a940ea517fde617761f037 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Thu, 8 Jun 2017 01:16:05 +0200 Subject: Windows: Validate XML format of EFI DcsProp after user editing and before writing it to disk. Enhance UI handling of DcsProp editing and PlatformInfo display. --- src/Common/Dlgcode.c | 25 +++++--- src/Common/Dlgcode.h | 1 + src/Common/Language.xml | 6 ++ src/Mount/Mount.c | 155 ++++++++++++++++++++++++++++++++++++++++++++---- src/Mount/Mount.rc | 24 ++++---- src/Mount/Resource.h | 4 +- 6 files changed, 181 insertions(+), 34 deletions(-) diff --git a/src/Common/Dlgcode.c b/src/Common/Dlgcode.c index 67e6b379..33e02514 100644 --- a/src/Common/Dlgcode.c +++ b/src/Common/Dlgcode.c @@ -3361,13 +3361,13 @@ wstring GetDecoyOsInstructionsString (void) } struct _TEXT_EDIT_DIALOG_PARAM { - int Type; + BOOL ReadOnly; std::string& Text; const WCHAR* Title; HWND Parent; - _TEXT_EDIT_DIALOG_PARAM(int _type, const WCHAR* title, std::string& _text) : Title(title), Text(_text), Type(_type) {} + _TEXT_EDIT_DIALOG_PARAM(BOOL _readOnly, const WCHAR* title, std::string& _text) : Title(title), Text(_text), ReadOnly(_readOnly) {} _TEXT_EDIT_DIALOG_PARAM& operator=( const _TEXT_EDIT_DIALOG_PARAM& other) { - Type = other.Type; + ReadOnly = other.ReadOnly; Text = other.Text; Title = other.Title; return *this; @@ -3375,9 +3375,9 @@ struct _TEXT_EDIT_DIALOG_PARAM { }; typedef struct _TEXT_EDIT_DIALOG_PARAM TEXT_INFO_DIALOG_PARAM,*TEXT_INFO_DIALOG_PARAM_PTR; -INT_PTR TextEditDialogBox (int type, HWND parent, const WCHAR* Title, std::string& text) +INT_PTR TextEditDialogBox (BOOL readOnly, HWND parent, const WCHAR* Title, std::string& text) { - TEXT_INFO_DIALOG_PARAM pm(type, Title, text); + TEXT_INFO_DIALOG_PARAM pm(readOnly, Title, text); return DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TEXT_EDIT_DLG), parent, (DLGPROC) TextEditDlgProc, (LPARAM) &pm); } @@ -3398,6 +3398,14 @@ BOOL CALLBACK TextEditDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPa // Left margin for rich edit text field SendMessage (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), EM_SETMARGINS, (WPARAM) EC_LEFTMARGIN, (LPARAM) CompensateXDPI (4)); + if (prm->ReadOnly) + { + // switch rich edit control to ReadOnly + SendMessage(GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), ES_READONLY, TRUE, 0); + // hide cancel button + ShowWindow(GetDlgItem(hwndDlg, IDCANCEL), SW_HIDE); + } + SendMessage (hwndDlg, TC_APPMSG_LOAD_TEXT_BOX_CONTENT, 0, 0); } return 0; @@ -3405,8 +3413,11 @@ BOOL CALLBACK TextEditDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPa case WM_COMMAND: if (lw == IDOK ) { - prm->Text.resize(GetWindowTextLengthA (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT)) + 1); - GetWindowTextA (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), &(prm->Text)[0], prm->Text.size()); + if (!prm->ReadOnly) + { + prm->Text.resize(GetWindowTextLengthA (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT)) + 1); + GetWindowTextA (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), &(prm->Text)[0], prm->Text.size()); + } NormalCursor (); EndDialog (hwndDlg, IDOK); return 1; diff --git a/src/Common/Dlgcode.h b/src/Common/Dlgcode.h index 1a66e102..a585218c 100644 --- a/src/Common/Dlgcode.h +++ b/src/Common/Dlgcode.h @@ -624,6 +624,7 @@ inline std::wstring AppendSrcPos (const wchar_t* msg, const char* srcPos) return std::wstring (msg? msg : L"") + L"\n\nSource: " + SingleStringToWide (srcPos); } void UpdateMountableHostDeviceList (); +INT_PTR TextEditDialogBox (BOOL readOnly, HWND parent, const WCHAR* Title, std::string& text); // Display a wait dialog while calling the provided callback with the given parameter typedef void (CALLBACK* WaitThreadProc)(void* pArg, HWND hWaitDlg); diff --git a/src/Common/Language.xml b/src/Common/Language.xml index a2c1312f..36c3a42a 100644 --- a/src/Common/Language.xml +++ b/src/Common/Language.xml @@ -1415,6 +1415,12 @@ The Rescue Disk image has been created and stored in this file:\n%s\n\nNow you need to extract the Rescue Disk image to a USB stick that is formatted as FAT/FAT32.\n\nIMPORTANT: Note that the zip file must be extracted directly to the root of the USB stick. For example, if the drive letter of the USB stick is E: then extracting the zip file should create a folder E:\\EFI on the USB stick.\n\nAfter you create the Rescue Disk, select 'System' > 'Verify Rescue Disk' to verify that it has been correctly created. Use Secure Desktop for password entry The volume file size specified in the command line is incompatible with selected ReFS filesystem. + Edit Boot Loader Configuration + Display EFI Platform Information + Boot Loader Configuration File + EFI Platform Information + WARNING: Inexperienced users should never attempt to manually edit boot loader configurations.\n\nContinue? + WARNING: Failed to validate the XML format of the Boot Loader configuration. Please check your modifications. diff --git a/src/Mount/Mount.c b/src/Mount/Mount.c index 2525a65a..63dd199c 100644 --- a/src/Mount/Mount.c +++ b/src/Mount/Mount.c @@ -51,6 +51,8 @@ #include +#import + #include typedef BOOL (WINAPI *WTSREGISTERSESSIONNOTIFICATION)(HWND, DWORD); @@ -215,6 +217,125 @@ static void UnregisterWtsNotification(HWND hWnd) } } +static std::vector GetReadChildNodes (MSXML2::IXMLDOMNodeListPtr childs) +{ + std::vector list; + if (childs && childs->Getlength()) + { + for (long i = 0; i < childs->Getlength(); i++) + { + MSXML2::IXMLDOMNodePtr node = childs->Getitem(i); + if (node) + { + //skip comments + if (node->GetnodeType() == NODE_COMMENT) + continue; + // skip root xml node + if (node->GetbaseName().GetBSTR() && (0 == strcmp ("xml", (const char*) node->GetbaseName()))) + continue; + + list.push_back (node); + } + } + } + + return list; +} + +static bool validateDcsPropXml(const char* xmlData) +{ + bool bValid = false; + HRESULT hr = CoInitialize(NULL); + if(FAILED(hr)) + return false; + else + { + MSXML2::IXMLDOMDocumentPtr pXMLDom; + hr= pXMLDom.CreateInstance(__uuidof(MSXML2::DOMDocument60), NULL, CLSCTX_INPROC_SERVER); + if (SUCCEEDED(hr)) + { + try + { + pXMLDom->async = VARIANT_FALSE; + pXMLDom->validateOnParse = VARIANT_FALSE; + pXMLDom->resolveExternals = VARIANT_FALSE; + + if(pXMLDom->loadXML(xmlData) == VARIANT_TRUE && pXMLDom->hasChildNodes()) + { + MSXML2::IXMLDOMNodePtr veracryptNode, configurationNode, configNode; + std::vector nodes = GetReadChildNodes (pXMLDom->GetchildNodes()); + size_t nodesCount = nodes.size(); + if (nodesCount == 1 + && ((veracryptNode = nodes[0])->GetnodeType() == NODE_ELEMENT) + && veracryptNode->GetnodeName().GetBSTR() + && (0 == strcmp ((const char*) veracryptNode->GetnodeName(), "VeraCrypt")) + && veracryptNode->hasChildNodes() + + ) + { + nodes = GetReadChildNodes (veracryptNode->GetchildNodes()); + nodesCount = nodes.size(); + if ((nodesCount == 1) + && ((configurationNode = nodes[0])->GetnodeType() == NODE_ELEMENT) + && configurationNode->GetnodeName().GetBSTR() + && (0 == strcmp ((const char*) configurationNode->GetnodeName(), "configuration")) + && (configurationNode->hasChildNodes()) + ) + { + nodes = GetReadChildNodes (configurationNode->GetchildNodes()); + nodesCount = nodes.size(); + + if (nodesCount > 1) + { + bValid = true; + for (size_t i = 0; bValid && (i < nodesCount); i++) + { + configNode = nodes[i]; + if (configNode->GetnodeType() == NODE_COMMENT) + continue; + else if ( (configNode->GetnodeType() == NODE_ELEMENT) + && (configNode->GetnodeName().GetBSTR()) + && (0 == strcmp ((const char*) configNode->GetnodeName(), "config")) + ) + { + nodes = GetReadChildNodes (configNode->GetchildNodes()); + nodesCount = nodes.size(); + if ((nodesCount == 0 || (nodesCount == 1 && nodes[0]->GetnodeType() == NODE_TEXT)) + && configNode->Getattributes() + && (configNode->Getattributes()->Getlength() == 1) + && (configNode->Getattributes()->Getitem(0)) + ) + { + std::string val; + bstr_t bstr = configNode->Getattributes()->Getitem(0)->GetnodeName (); + if (bstr.GetBSTR()) + val = (const char*) bstr; + if (val != "key") + bValid = false; + } + else + bValid = false; + } + else + bValid = false; + } + } + } + } + } + } + catch(_com_error errorObject) + { + bValid = false; + } + } + } + + CoUninitialize(); + return bValid; +} + + static void localcleanup (void) { // Wipe command line @@ -10899,8 +11020,6 @@ void SecurityTokenPreferencesDialog (HWND hwndDlg) DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TOKEN_PREFERENCES), hwndDlg, (DLGPROC) SecurityTokenPreferencesDlgProc, 0); } -INT_PTR TextEditDialogBox (int type, HWND parent, const WCHAR* Title, std::string& text); - static BOOL CALLBACK BootLoaderPreferencesDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { WORD lw = LOWORD (wParam); @@ -10972,7 +11091,7 @@ static BOOL CALLBACK BootLoaderPreferencesDlgProc (HWND hwndDlg, UINT msg, WPARA case IDCANCEL: EndDialog (hwndDlg, lw); return 1; - case IDB_SHOW_PLATFORMINFO: + case IDC_SHOW_PLATFORMINFO: { try { @@ -10995,13 +11114,14 @@ static BOOL CALLBACK BootLoaderPreferencesDlgProc (HWND hwndDlg, UINT msg, WPARA else offset = 0; platforminfo = (const char*) &fileContent[offset]; - TextEditDialogBox(0, hwndDlg, L"PlatformInfo", platforminfo); + TextEditDialogBox(TRUE, hwndDlg, GetString ("EFI_PLATFORM_INFORMATION"), platforminfo); } catch (Exception &e) { e.Show(hwndDlg); } } return 0; - case IDB_EDIT_DCSPROP: + case IDC_EDIT_DCSPROP: + if (AskWarnNoYes ("EDIT_DCSPROP_FOR_ADVANCED_ONLY", hwndDlg) == IDYES) { try { @@ -11026,14 +11146,23 @@ static BOOL CALLBACK BootLoaderPreferencesDlgProc (HWND hwndDlg, UINT msg, WPARA offset = 0; dcsprop = (const char*) &fileContent[offset]; - if(TextEditDialogBox(0, hwndDlg, L"DcsProp", dcsprop) == IDOK) { - // Add UTF-8 BOM - fileContent.resize (dcsprop.length() + 3); - memcpy (fileContent.data(), "\xEF\xBB\xBF", 3); - memcpy (&fileContent[3], &dcsprop[0], dcsprop.length()); - File f2(path,false,true); - f2.Write(fileContent.data(), fileContent.size()); - f2.Close(); + while (TextEditDialogBox(FALSE, hwndDlg, GetString ("BOOT_LOADER_CONFIGURATION_FILE"), dcsprop) == IDOK) + { + if (validateDcsPropXml (dcsprop.c_str())) + { + // Add UTF-8 BOM + fileContent.resize (dcsprop.length() + 3); + memcpy (fileContent.data(), "\xEF\xBB\xBF", 3); + memcpy (&fileContent[3], &dcsprop[0], dcsprop.length()); + File f2(path,false,true); + f2.Write(fileContent.data(), fileContent.size()); + f2.Close(); + break; + } + else + { + MessageBoxW (hwndDlg, GetString ("DCSPROP_XML_VALIDATION_FAILED"), lpszTitle, ICON_HAND); + } } } catch (Exception &e) { e.Show(hwndDlg); } diff --git a/src/Mount/Mount.rc b/src/Mount/Mount.rc index 46d385ba..d07a9b4a 100644 --- a/src/Mount/Mount.rc +++ b/src/Mount/Mount.rc @@ -285,25 +285,25 @@ BEGIN LTEXT "",IDT_PKCS11_LIB_HELP,16,63,286,65 END -IDD_EFI_SYSENC_SETTINGS DIALOGEX 0, 0, 367, 134 +IDD_EFI_SYSENC_SETTINGS DIALOGEX 0, 0, 374, 156 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "VeraCrypt - System Encryption Settings" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN CONTROL "&Cache pre-boot authentication password in driver memory (for mounting of non-system volumes)",IDC_BOOT_LOADER_CACHE_PASSWORD, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,90,339,10 - DEFPUSHBUTTON "OK",IDOK,261,120,50,14 - PUSHBUTTON "Cancel",IDCANCEL,315,120,50,14 - GROUPBOX "Boot Loader Screen Options",IDT_BOOT_LOADER_SCREEN_OPTIONS,8,7,355,65 - GROUPBOX "Security Options",IDT_SECURITY_OPTIONS,6,75,355,44 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,68,339,10 + DEFPUSHBUTTON "OK",IDOK,258,132,50,14 + PUSHBUTTON "Cancel",IDCANCEL,317,132,50,14 + GROUPBOX "Boot Loader Screen Options",IDT_BOOT_LOADER_SCREEN_OPTIONS,8,7,355,45 + GROUPBOX "Security Options",IDT_SECURITY_OPTIONS,7,53,355,44 CONTROL "Include PIM when caching pre-boot authentication password",IDC_BOOT_LOADER_CACHE_PIM, - "Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,16,105,340,10 + "Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,16,83,340,10 CONTROL "Do not request PIM in the pre-boot authentication screen (PIM value is stored unencrypted on disk)",IDC_DISABLE_BOOT_LOADER_PIM_PROMPT, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,20,339,9 CONTROL "Do not request Hash algorithm in the pre-boot authentication screen",IDC_DISABLE_BOOT_LOADER_HASH_PROMPT, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,35,339,9 - PUSHBUTTON "Show PlatformInfo",IDB_SHOW_PLATFORMINFO,75,51,68,14 - DEFPUSHBUTTON "Edit DcsProp",IDB_EDIT_DCSPROP,15,51,50,14 + PUSHBUTTON "Display EFI Platform Information",IDC_SHOW_PLATFORMINFO,16,126,154,14 + PUSHBUTTON "Edit Boot Loader Configuration",IDC_EDIT_DCSPROP,16,105,154,14 END IDD_PERFORMANCE_SETTINGS DIALOGEX 0, 0, 370, 248 @@ -418,7 +418,7 @@ END // #ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO +GUIDELINES DESIGNINFO BEGIN IDD_PREFERENCES_DLG, DIALOG BEGIN @@ -483,9 +483,9 @@ BEGIN IDD_EFI_SYSENC_SETTINGS, DIALOG BEGIN LEFTMARGIN, 7 - RIGHTMARGIN, 360 + RIGHTMARGIN, 367 TOPMARGIN, 7 - BOTTOMMARGIN, 124 + BOTTOMMARGIN, 146 END IDD_PERFORMANCE_SETTINGS, DIALOG diff --git a/src/Mount/Resource.h b/src/Mount/Resource.h index c3a61c6e..62d7ea1a 100644 --- a/src/Mount/Resource.h +++ b/src/Mount/Resource.h @@ -184,8 +184,8 @@ #define IDC_HIDE_WAITING_DIALOG 1161 #define IDC_DISABLE_BOOT_LOADER_HASH_PROMPT 1162 #define IDC_SECURE_DESKTOP_PASSWORD_ENTRY 1163 -#define IDB_SHOW_PLATFORMINFO 1164 -#define IDB_EDIT_DCSPROP 1165 +#define IDC_SHOW_PLATFORMINFO 1164 +#define IDC_EDIT_DCSPROP 1165 #define IDM_HELP 40001 #define IDM_ABOUT 40002 #define IDM_UNMOUNT_VOLUME 40003 -- cgit v1.2.3