aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cli/cli.cpp39
-rw-r--r--src/lib/utils/os_utils.cpp56
-rw-r--r--src/lib/utils/os_utils.h27
3 files changed, 96 insertions, 26 deletions
diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp
index f8ec55e7b..988fa623a 100644
--- a/src/cli/cli.cpp
+++ b/src/cli/cli.cpp
@@ -8,13 +8,10 @@
#include "argparse.h"
#include <botan/rng.h>
#include <botan/parsing.h>
+#include <botan/internal/os_utils.h>
#include <iostream>
#include <fstream>
-#if defined(BOTAN_TARGET_OS_HAS_POSIX1)
- #include <termios.h>
-#endif
-
namespace Botan_CLI {
Command::Command(const std::string& cmd_spec) : m_spec(cmd_spec)
@@ -210,34 +207,28 @@ Botan::RandomNumberGenerator& Command::rng()
return *m_rng.get();
}
-std::string Command::get_passphrase(const std::string& prompt)
- {
- error_output() << prompt << ": " << std::flush;
- std::string pass;
+namespace {
-#if defined(BOTAN_TARGET_OS_HAS_POSIX1)
+bool echo_suppression_supported()
+ {
+ auto echo = Botan::OS::suppress_echo_on_terminal();
+ return (echo != nullptr);
+ }
- struct termios old_flags;
- int stdin_fd = fileno(stdin);
- ::tcgetattr(stdin_fd, &old_flags);
- struct termios noecho_flags = old_flags;
- noecho_flags.c_lflag &= ~ECHO;
- noecho_flags.c_lflag |= ECHONL;
+}
- if(::tcsetattr(stdin_fd, TCSANOW, &noecho_flags) != 0)
- throw CLI_Error("Clearing terminal echo bit failed");
+std::string Command::get_passphrase(const std::string& prompt)
+ {
+ if(echo_suppression_supported() == false)
+ error_output() << "Warning: terminal echo suppression not enabled for this platform\n";
- std::getline(std::cin, pass);
+ error_output() << prompt << ": " << std::flush;
+ std::string pass;
- if(::tcsetattr(stdin_fd, TCSANOW, &old_flags) != 0)
- throw CLI_Error("Restoring terminal echo bit failed");
-#else
+ auto echo_suppress = Botan::OS::suppress_echo_on_terminal();
- // TODO equivalent for Windows ...
std::getline(std::cin, pass);
-#endif
-
return pass;
}
diff --git a/src/lib/utils/os_utils.cpp b/src/lib/utils/os_utils.cpp
index ab9c73b0c..4c3aab476 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,7 @@
#include <setjmp.h>
#include <unistd.h>
#include <errno.h>
+ #include <termios.h>
#endif
#if defined(BOTAN_TARGET_OS_IS_EMSCRIPTEN)
@@ -470,4 +471,57 @@ 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 Botan::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 Botan::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 Botan::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);
+#endif
+
+ // Not supported on this platform, return null
+ return std::unique_ptr<Echo_Suppression>();
+ }
+
}
diff --git a/src/lib/utils/os_utils.h b/src/lib/utils/os_utils.h
index 778ace4e9..39e30fcb7 100644
--- a/src/lib/utils/os_utils.h
+++ b/src/lib/utils/os_utils.h
@@ -1,6 +1,6 @@
/*
* OS specific utility functions
-* (C) 2015,2016,2017 Jack Lloyd
+* (C) 2015,2016,2017,2018 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -117,6 +117,31 @@ void free_locked_pages(void* ptr, size_t length);
*/
int BOTAN_TEST_API run_cpu_instruction_probe(std::function<int ()> probe_fn);
+/**
+* Represents a terminal state
+*/
+class BOTAN_UNSTABLE_API Echo_Suppression
+ {
+ public:
+ /**
+ * Reenable echo on this terminal. Can be safely called
+ * multiple times. May throw if an error occurs.
+ */
+ virtual void reenable_echo() = 0;
+
+ /**
+ * Implicitly calls reenable_echo, but swallows/ignored all
+ * errors which would leave the terminal in an invalid state.
+ */
+ virtual ~Echo_Suppression() = default;
+ };
+
+/**
+* Suppress echo on the terminal
+* Returns null if this operation is not supported on the current system.
+*/
+std::unique_ptr<Echo_Suppression> BOTAN_UNSTABLE_API suppress_echo_on_terminal();
+
}
}