diff options
author | Jack Lloyd <[email protected]> | 2018-12-02 16:31:16 -0500 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2018-12-02 16:31:16 -0500 |
commit | 163e59f4af51f802c5e77fc0bb8c0901a7fa62ea (patch) | |
tree | d6d274f449efea663d236bd293f4e1bebf7fc7c4 /src/lib/utils/os_utils.cpp | |
parent | 7bc0745c3ff2824f9a3607db19e7e1a3e563c5bc (diff) | |
parent | c3cbf959aa628ae541e4009894b040ab242dd45e (diff) |
Merge GH #1756 Support getting passphrase from the console
Diffstat (limited to 'src/lib/utils/os_utils.cpp')
-rw-r--r-- | src/lib/utils/os_utils.cpp | 101 |
1 files changed, 100 insertions, 1 deletions
diff --git a/src/lib/utils/os_utils.cpp b/src/lib/utils/os_utils.cpp index ab9c73b0c..6bebbab58 100644 --- a/src/lib/utils/os_utils.cpp +++ b/src/lib/utils/os_utils.cpp @@ -1,6 +1,6 @@ /* * OS and machine specific utility functions -* (C) 2015,2016,2017 Jack Lloyd +* (C) 2015,2016,2017,2018 Jack Lloyd * (C) 2016 Daniel Neus * * Botan is released under the Simplified BSD License (see license.txt) @@ -26,6 +26,8 @@ #include <setjmp.h> #include <unistd.h> #include <errno.h> + #include <termios.h> + #undef B0 #endif #if defined(BOTAN_TARGET_OS_IS_EMSCRIPTEN) @@ -470,4 +472,101 @@ int OS::run_cpu_instruction_probe(std::function<int ()> probe_fn) return probe_result; } +std::unique_ptr<OS::Echo_Suppression> OS::suppress_echo_on_terminal() + { +#if defined(BOTAN_TARGET_OS_HAS_POSIX1) + class POSIX_Echo_Suppression : public Echo_Suppression + { + public: + POSIX_Echo_Suppression() + { + m_stdin_fd = fileno(stdin); + if(::tcgetattr(m_stdin_fd, &m_old_termios) != 0) + throw System_Error("Getting terminal status failed", errno); + + struct termios noecho_flags = m_old_termios; + noecho_flags.c_lflag &= ~ECHO; + noecho_flags.c_lflag |= ECHONL; + + if(::tcsetattr(m_stdin_fd, TCSANOW, &noecho_flags) != 0) + throw System_Error("Clearing terminal echo bit failed", errno); + } + + void reenable_echo() override + { + if(m_stdin_fd > 0) + { + if(::tcsetattr(m_stdin_fd, TCSANOW, &m_old_termios) != 0) + throw System_Error("Restoring terminal echo bit failed", errno); + m_stdin_fd = -1; + } + } + + ~POSIX_Echo_Suppression() + { + try + { + reenable_echo(); + } + catch(...) + { + } + } + + private: + int m_stdin_fd; + struct termios m_old_termios; + }; + + return std::unique_ptr<Echo_Suppression>(new POSIX_Echo_Suppression); + +#elif defined(BOTAN_TARGET_OS_HAS_WIN32) + + class Win32_Echo_Suppression : public Echo_Suppression + { + public: + Win32_Echo_Suppression() + { + m_input_handle = ::GetStdHandle(STD_INPUT_HANDLE); + if(::GetConsoleMode(m_input_handle, &m_console_state) == 0) + throw System_Error("Getting console mode failed", ::GetLastError()); + + DWORD new_mode = ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT; + if(::SetConsoleMode(m_input_handle, new_mode) == 0) + throw System_Error("Setting console mode failed", ::GetLastError()); + } + + void reenable_echo() override + { + if(m_input_handle != INVALID_HANDLE_VALUE) + { + if(::SetConsoleMode(m_input_handle, m_console_state) == 0) + throw System_Error("Setting console mode failed", ::GetLastError()); + m_input_handle = INVALID_HANDLE_VALUE; + } + } + + ~Win32_Echo_Suppression() + { + try + { + reenable_echo(); + } + catch(...) + { + } + } + + private: + HANDLE m_input_handle; + DWORD m_console_state; + }; + + return std::unique_ptr<Echo_Suppression>(new Win32_Echo_Suppression); +#endif + + // Not supported on this platform, return null + return std::unique_ptr<Echo_Suppression>(); + } + } |