From 114a03f99cdaa9a9f58d33ebef277ef70637f2be Mon Sep 17 00:00:00 2001 From: Valera Cogut Date: Thu, 15 Nov 2018 02:14:50 +0200 Subject: [PATCH] Added secret mode for hiding sensitive information --- examples/cli.c | 6 +++++ include/editline.h | 3 +++ src/complete.c | 24 +++++++++++++++-- src/editline.c | 65 +++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 89 insertions(+), 9 deletions(-) diff --git a/examples/cli.c b/examples/cli.c index 4e9a6c0..e63a460 100644 --- a/examples/cli.c +++ b/examples/cli.c @@ -134,6 +134,11 @@ static int my_rl_check_secret(const char *line) return rc; } +static void my_rl_flush_secret_mode() +{ + return; +} + int main(void) { char *line; @@ -143,6 +148,7 @@ int main(void) rl_set_complete_func(&my_rl_complete); rl_set_list_possib_func(&my_rl_list_possib); rl_set_check_secret_func(&my_rl_check_secret); + rl_set_flush_secret_mode_func(&my_rl_flush_secret_mode); el_bind_key('?', list_possible); el_bind_key(CTL('C'), do_break); el_bind_key(CTL('D'), do_exit); diff --git a/include/editline.h b/include/editline.h index 7d7e5f4..db32369 100644 --- a/include/editline.h +++ b/include/editline.h @@ -46,6 +46,7 @@ typedef enum { /* Editline specific types, despite rl_ prefix. From Heimdal project. */ typedef int rl_list_possib_func_t(char*, char***); typedef int rl_check_secret_func_t(const char*); +typedef void rl_flush_secret_mode_func_t(void); typedef el_status_t el_keymap_func_t(void); typedef int rl_hook_func_t(void); typedef int rl_getc_func_t(void); @@ -78,6 +79,7 @@ extern int rl_list_possib(char *token, char ***av); extern char **rl_completion_matches(const char *token, rl_compentry_func_t *generator); extern char *rl_filename_completion_function(const char *text, int state); extern int rl_check_secret(const char *source); +extern void rl_flush_secret_mode(void); /* For compatibility with FSF readline. */ extern int rl_point; @@ -120,6 +122,7 @@ extern rl_completion_func_t *rl_attempted_completion_function; extern rl_complete_func_t *rl_set_complete_func (rl_complete_func_t *func); extern rl_list_possib_func_t *rl_set_list_possib_func (rl_list_possib_func_t *func); extern rl_check_secret_func_t *rl_set_check_secret_func (rl_check_secret_func_t *func); +extern rl_flush_secret_mode_func_t *rl_set_flush_secret_mode_func (rl_flush_secret_mode_func_t *func); /* Alternate interface to plain readline(), for event loops */ extern void rl_callback_handler_install (const char *prompt, rl_vcpfunc_t *lhandler); diff --git a/src/complete.c b/src/complete.c index 7809ae2..1c34f6b 100644 --- a/src/complete.c +++ b/src/complete.c @@ -397,9 +397,9 @@ char *rl_complete(char *token, int *match) return el_filename_complete(token, match); } +/* Added for the BitShares Core project. */ static rl_check_secret_func_t *el_check_secret_func = NULL; -/* Added for the BitShares Core project. */ rl_check_secret_func_t *rl_set_check_secret_func(rl_check_secret_func_t *func) { rl_check_secret_func_t *old = el_check_secret_func; @@ -412,11 +412,31 @@ rl_check_secret_func_t *rl_set_check_secret_func(rl_check_secret_func_t *func) int rl_check_secret(const char *line) { if (el_check_secret_func) - return el_check_secret_func(line); + return el_check_secret_func(line); return 0; } +/* Added for the BitShares Core project. */ +static rl_flush_secret_mode_func_t *el_flush_secret_mode_func = NULL; + +rl_flush_secret_mode_func_t *rl_set_flush_secret_mode_func(rl_flush_secret_mode_func_t *func) +{ + rl_flush_secret_mode_func_t *old = el_flush_secret_mode_func; + + el_flush_secret_mode_func = func; + + return old; +} + +void rl_flush_secret_mode() +{ + if (el_flush_secret_mode_func) + return el_flush_secret_mode_func(); + + return; +} + static rl_list_possib_func_t *el_list_possib_func = NULL; /* For compatibility with the Heimdal project. */ diff --git a/src/editline.c b/src/editline.c index b968c17..92b1a39 100644 --- a/src/editline.c +++ b/src/editline.c @@ -114,6 +114,7 @@ static const char *old_prompt = NULL; static rl_vcpfunc_t *line_handler = NULL; int el_no_echo = 0; /* e.g., under Emacs */ +int el_old_no_echo = 0; int el_no_hist = 0; int rl_point; int rl_mark; @@ -121,7 +122,9 @@ int rl_end; int rl_meta_chars = 0; /* Display 8-bit chars as the actual char(0) or as `M-x'(1)? */ int rl_inhibit_complete = 0; char *rl_line_buffer = NULL; +char *rl_saved_line_buffer = NULL; const char *rl_prompt = NULL; +const char *rl_secret_prompt = "\nEnter secret: "; const char *rl_readline_name = NULL; /* Set by calling program, for conditional parsing of ~/.inputrc - Not supported yet! */ FILE *rl_instream = NULL; /* The stdio stream from which input is read. Defaults to stdin if NULL */ FILE *rl_outstream = NULL; /* The stdio stream to which output is flushed. Defaults to stdout if NULL */ @@ -154,6 +157,57 @@ static int is_alpha_num(unsigned char c) ** TTY input/output functions. */ +static void tty_push(int c) +{ + el_pushed = 1; + el_push_back = c; +} + +ssize_t tty_enter_secret_mode(void) +{ + el_old_no_echo = el_no_echo; + el_no_echo = 1; + + rl_saved_line_buffer = strdup(rl_line_buffer); + + rl_end = 0; + rl_line_buffer[0] = '\0'; + + tty_push(CSeof); + + ssize_t rez = write(el_outfd, rl_secret_prompt, strlen(rl_secret_prompt)); + + rl_flush_secret_mode(); + + return rez; +} + +void tty_exit_secret_mode(void) +{ + if (!rl_saved_line_buffer) + return; + + unsigned int saved_len = strlen(rl_saved_line_buffer); + unsigned int len = strlen(rl_line_buffer) + saved_len; + + char* str = malloc(sizeof(char) * len); + + for (unsigned int i=0; i < len; i++) { + if (i < saved_len) + str[i] = rl_saved_line_buffer[i]; + else + str[i] = rl_line_buffer[i - strlen(rl_saved_line_buffer)]; + } + + rl_end += saved_len; + + free(rl_line_buffer); + rl_line_buffer = strdup(str); + + free(str); + free(rl_saved_line_buffer); +} + static void tty_flush(void) { ssize_t res; @@ -163,7 +217,7 @@ static void tty_flush(void) if (!el_no_echo) { if (rl_check_secret(rl_line_buffer)) - res = write(el_outfd, "", 1); + res = tty_enter_secret_mode(); else res = write(el_outfd, Screen, ScreenCount); @@ -213,12 +267,6 @@ static void tty_string(char *p) tty_show(*p++); } -static void tty_push(int c) -{ - el_pushed = 1; - el_push_back = c; -} - int rl_getc(void) { int r; @@ -1242,6 +1290,8 @@ void rl_initialize(void) if (!rl_prompt) rl_prompt = "? "; + el_no_echo = el_old_no_echo; + hist_alloc(); /* Setup I/O descriptors */ @@ -1642,6 +1692,7 @@ static el_status_t c_complete(void) static el_status_t accept_line(void) { + tty_exit_secret_mode(); rl_line_buffer[rl_end] = '\0'; return CSdone; }