From 051395a761d06443dbebbcb218cdc6112706da94 Mon Sep 17 00:00:00 2001 From: proller Date: Mon, 21 May 2018 20:27:18 +0300 Subject: [PATCH 1/2] `clickhouse-client`: option --ask-password for interactively ask for credentials #1044 --- CHANGELOG.draft.md | 11 +++++ dbms/src/Server/Client.cpp | 28 +++++++++++-- libs/libcommon/CMakeLists.txt | 2 + .../include/common/SetTerminalEcho.h | 4 ++ libs/libcommon/src/SetTerminalEcho.cpp | 42 +++++++++++++++++++ 5 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 CHANGELOG.draft.md create mode 100644 libs/libcommon/include/common/SetTerminalEcho.h create mode 100644 libs/libcommon/src/SetTerminalEcho.cpp diff --git a/CHANGELOG.draft.md b/CHANGELOG.draft.md new file mode 100644 index 00000000000..ccef5afadf6 --- /dev/null +++ b/CHANGELOG.draft.md @@ -0,0 +1,11 @@ +en: + +## Improvements: +* `clickhouse-client`: option --ask-password for interactively ask for credentials #1044 + + + +ru: + +## Улучшения: +* `clickhouse-client`: опция --ask-password для интерактивного ввода пароля #1044 diff --git a/dbms/src/Server/Client.cpp b/dbms/src/Server/Client.cpp index cb70c83425c..e3e4705c50d 100644 --- a/dbms/src/Server/Client.cpp +++ b/dbms/src/Server/Client.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +53,7 @@ #include "InterruptListener.h" #include #include +#include /// http://en.wikipedia.org/wiki/ANSI_escape_code @@ -197,7 +199,25 @@ private: default_database = config.getString("database", ""); user = config.getString("user", ""); - password = config.getString("password", ""); + + if (config.getBool("ask-password", false)) + { + if (config.has("password")) + throw Exception("Specified both --password and --ask-password. Remove one of them", ErrorCodes::BAD_ARGUMENTS); + + std::cout << "Password for user " << user << ": "; + SetTerminalEcho(false); + + SCOPE_EXIT({ + SetTerminalEcho(true); + }); + std::getline(std::cin, password); + std::cout << std::endl; + } + else + { + password = config.getString("password", ""); + } compression = config.getBool("compression", true) ? Protocol::Compression::Enable @@ -1375,8 +1395,9 @@ public: ("host,h", boost::program_options::value()->default_value("localhost"), "server host") ("port", boost::program_options::value()->default_value(9000), "server port") ("secure,s", "secure") - ("user,u", boost::program_options::value(), "user") + ("user,u", boost::program_options::value()->default_value("default"), "user") ("password", boost::program_options::value(), "password") + ("ask-password", "ask-password") ("query_id", boost::program_options::value(), "query_id") ("query,q", boost::program_options::value(), "query") ("database,d", boost::program_options::value(), "database") @@ -1483,7 +1504,8 @@ public: config().setString("user", options["user"].as()); if (options.count("password")) config().setString("password", options["password"].as()); - + if (options.count("ask-password")) + config().setBool("ask-password", true); if (options.count("multiline")) config().setBool("multiline", true); if (options.count("multiquery")) diff --git a/libs/libcommon/CMakeLists.txt b/libs/libcommon/CMakeLists.txt index cc0ac9770a6..0dd5939fc46 100644 --- a/libs/libcommon/CMakeLists.txt +++ b/libs/libcommon/CMakeLists.txt @@ -27,6 +27,7 @@ add_library (common ${SPLIT_SHARED} src/getMemoryAmount.cpp src/ThreadPool.cpp src/demangle.cpp + src/SetTerminalEcho.cpp include/common/Types.h include/common/DateLUT.h @@ -46,6 +47,7 @@ add_library (common ${SPLIT_SHARED} include/common/getMemoryAmount.h include/common/ThreadPool.h include/common/demangle.h + include/common/SetTerminalEcho.h include/ext/bit_cast.h include/ext/collection_cast.h diff --git a/libs/libcommon/include/common/SetTerminalEcho.h b/libs/libcommon/include/common/SetTerminalEcho.h new file mode 100644 index 00000000000..fa5ccc93436 --- /dev/null +++ b/libs/libcommon/include/common/SetTerminalEcho.h @@ -0,0 +1,4 @@ +#pragma once + +/// Enable or disable echoing of typed characters. Throws std::runtime_error on error. +void SetTerminalEcho(bool enable); diff --git a/libs/libcommon/src/SetTerminalEcho.cpp b/libs/libcommon/src/SetTerminalEcho.cpp new file mode 100644 index 00000000000..b000f221ef8 --- /dev/null +++ b/libs/libcommon/src/SetTerminalEcho.cpp @@ -0,0 +1,42 @@ +// https://stackoverflow.com/questions/1413445/reading-a-password-from-stdcin + +#include +#include +#include + +#ifdef WIN32 +#include +#else +#include +#include +#endif + +void SetTerminalEcho(bool enable) +{ +#ifdef WIN32 + auto handle = GetStdHandle(STD_INPUT_HANDLE); + DWORD mode; + if (!GetConsoleMode(handle, &mode)) + throw std::runtime_error(std::string("SetTerminalEcho failed get:") + std::to_string(GetLastError())); + + if (!enable) + mode &= ~ENABLE_ECHO_INPUT; + else + mode |= ENABLE_ECHO_INPUT; + + if (!SetConsoleMode(handle, mode)) + throw std::runtime_error(std::string("SetTerminalEcho failed set:") + std::to_string(GetLastError())); +#else + struct termios tty; + if (tcgetattr(STDIN_FILENO, &tty)) + throw std::runtime_error(std::string("SetTerminalEcho failed get:") + strerror(errno)); + if (!enable) + tty.c_lflag &= ~ECHO; + else + tty.c_lflag |= ECHO; + + auto ret = tcsetattr(STDIN_FILENO, TCSANOW, &tty); + if (ret) + throw std::runtime_error(std::string("SetTerminalEcho failed set:") + strerror(errno)); +#endif +} From 42a0e1e0c7b6aeee5c4dc9f7d9b45cc59225fbb8 Mon Sep 17 00:00:00 2001 From: alexey-milovidov Date: Mon, 21 May 2018 22:53:46 +0300 Subject: [PATCH 2/2] Update SetTerminalEcho.cpp --- libs/libcommon/src/SetTerminalEcho.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/libcommon/src/SetTerminalEcho.cpp b/libs/libcommon/src/SetTerminalEcho.cpp index b000f221ef8..b461c80abdf 100644 --- a/libs/libcommon/src/SetTerminalEcho.cpp +++ b/libs/libcommon/src/SetTerminalEcho.cpp @@ -17,7 +17,7 @@ void SetTerminalEcho(bool enable) auto handle = GetStdHandle(STD_INPUT_HANDLE); DWORD mode; if (!GetConsoleMode(handle, &mode)) - throw std::runtime_error(std::string("SetTerminalEcho failed get:") + std::to_string(GetLastError())); + throw std::runtime_error(std::string("SetTerminalEcho failed get: ") + std::to_string(GetLastError())); if (!enable) mode &= ~ENABLE_ECHO_INPUT; @@ -25,11 +25,11 @@ void SetTerminalEcho(bool enable) mode |= ENABLE_ECHO_INPUT; if (!SetConsoleMode(handle, mode)) - throw std::runtime_error(std::string("SetTerminalEcho failed set:") + std::to_string(GetLastError())); + throw std::runtime_error(std::string("SetTerminalEcho failed set: ") + std::to_string(GetLastError())); #else struct termios tty; if (tcgetattr(STDIN_FILENO, &tty)) - throw std::runtime_error(std::string("SetTerminalEcho failed get:") + strerror(errno)); + throw std::runtime_error(std::string("SetTerminalEcho failed get: ") + strerror(errno)); if (!enable) tty.c_lflag &= ~ECHO; else @@ -37,6 +37,6 @@ void SetTerminalEcho(bool enable) auto ret = tcsetattr(STDIN_FILENO, TCSANOW, &tty); if (ret) - throw std::runtime_error(std::string("SetTerminalEcho failed set:") + strerror(errno)); + throw std::runtime_error(std::string("SetTerminalEcho failed set: ") + strerror(errno)); #endif }