From 98975d9167c19f1441123f487b9b70c1623a92a6 Mon Sep 17 00:00:00 2001 From: powerjungle Date: Sun, 16 Feb 2025 12:30:37 +0000 Subject: [PATCH] feature(console): password confirmation when creating encrypted archive So that typos become less likely in the password. --- CPP/7zip/UI/Console/UpdateCallbackConsole.cpp | 4 +- CPP/7zip/UI/Console/UserInputUtils.cpp | 91 ++++++++++++++++--- CPP/7zip/UI/Console/UserInputUtils.h | 1 + 3 files changed, 79 insertions(+), 17 deletions(-) diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp index 5185d5c..bd25067 100644 --- a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp +++ b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp @@ -830,7 +830,7 @@ HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, { if (AskPassword) { - RINOK(GetPassword_HRESULT(_so, Password)) + RINOK(GetPasswordConfirm_HRESULT(_so, Password)) PasswordIsDefined = true; } } @@ -857,7 +857,7 @@ HRESULT CUpdateCallbackConsole::CryptoGetTextPassword(BSTR *password) if (!PasswordIsDefined) { { - RINOK(GetPassword_HRESULT(_so, Password)) + RINOK(GetPasswordConfirm_HRESULT(_so, Password)) PasswordIsDefined = true; } } diff --git a/CPP/7zip/UI/Console/UserInputUtils.cpp b/CPP/7zip/UI/Console/UserInputUtils.cpp index 2adf9df..c917ef0 100644 --- a/CPP/7zip/UI/Console/UserInputUtils.cpp +++ b/CPP/7zip/UI/Console/UserInputUtils.cpp @@ -60,21 +60,24 @@ NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream) #endif #endif -static bool GetPassword(CStdOutStream *outStream, UString &psw) +static void OutputPassInputMessage(CStdOutStream *outStream, const UString &msg) { if (outStream) { - *outStream << "\nEnter password" + *outStream << '\n' << msg #ifdef MY_DISABLE_ECHO - " (will not be echoed)" + << " (will not be echoed)" #endif - ":"; + << ":"; outStream->Flush(); } +} + +static bool PassInput(UString &psw) +{ + bool res = false; #ifdef MY_DISABLE_ECHO - - const HANDLE console = GetStdHandle(STD_INPUT_HANDLE); /* GetStdHandle() returns @@ -82,33 +85,81 @@ static bool GetPassword(CStdOutStream *outStream, UString &psw) NULL : If an application does not have associated standard handles, such as a service running on an interactive desktop, and has not redirected them. */ - bool wasChanged = false; + const HANDLE console = GetStdHandle(STD_INPUT_HANDLE); DWORD mode = 0; + bool wasChanged = false; + if (console != INVALID_HANDLE_VALUE && console != NULL) if (GetConsoleMode(console, &mode)) wasChanged = (SetConsoleMode(console, mode & ~(DWORD)ENABLE_ECHO_INPUT) != 0); - const bool res = g_StdIn.ScanUStringUntilNewLine(psw); + res = g_StdIn.ScanUStringUntilNewLine(psw); if (wasChanged) SetConsoleMode(console, mode); - - #else - - const bool res = g_StdIn.ScanUStringUntilNewLine(psw); - + + # else + + res = g_StdIn.ScanUStringUntilNewLine(psw); + #endif + return res; +} + +static void EndOutStream(CStdOutStream *outStream) +{ if (outStream) { *outStream << endl; outStream->Flush(); } +} +static bool GetPassword(CStdOutStream *outStream, UString &psw, const bool confirm) +{ + UString confirmPsw; + UString passInMsg; + bool res = false; + + passInMsg = "Enter password"; + OutputPassInputMessage(outStream, passInMsg); + res = PassInput(psw); + if (!res) + { + EndOutStream(outStream); + return res; + } + + if (confirm) + { + passInMsg = "Confirm password"; + OutputPassInputMessage(outStream, passInMsg); + res = PassInput(confirmPsw); + if (!res) + { + EndOutStream(outStream); + return res; + } + + if (psw != confirmPsw) + { + if (outStream) + { + *outStream << '\n' + << "Confirm password is different from " + << "the initially entered password, stopping. " + << "Try again!"; + } + res = false; + } + } + + EndOutStream(outStream); return res; } -HRESULT GetPassword_HRESULT(CStdOutStream *outStream, UString &psw) +static HRESULT HandleHRESULT(bool res, UString &psw) { - if (!GetPassword(outStream, psw)) + if (!res) return E_INVALIDARG; if (g_StdIn.Error()) return E_FAIL; @@ -116,3 +167,13 @@ HRESULT GetPassword_HRESULT(CStdOutStream *outStream, UString &psw) return E_ABORT; return S_OK; } + +HRESULT GetPasswordConfirm_HRESULT(CStdOutStream *outStream, UString &psw) +{ + return HandleHRESULT(GetPassword(outStream, psw, true), psw); +} + +HRESULT GetPassword_HRESULT(CStdOutStream *outStream, UString &psw) +{ + return HandleHRESULT(GetPassword(outStream, psw, false), psw); +} diff --git a/CPP/7zip/UI/Console/UserInputUtils.h b/CPP/7zip/UI/Console/UserInputUtils.h index 695a3e6..8de78eb 100644 --- a/CPP/7zip/UI/Console/UserInputUtils.h +++ b/CPP/7zip/UI/Console/UserInputUtils.h @@ -23,5 +23,6 @@ enum EEnum NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream); // bool GetPassword(CStdOutStream *outStream, UString &psw); HRESULT GetPassword_HRESULT(CStdOutStream *outStream, UString &psw); +HRESULT GetPasswordConfirm_HRESULT(CStdOutStream *outStream, UString &psw); #endif