From ebad9bf9be166f83f8af1a1025b94cd06be47665 Mon Sep 17 00:00:00 2001 From: Tim Kourt Date: Tue, 27 Aug 2019 08:58:16 -0700 Subject: [PATCH] client: Enhance secret masking Due to the changed IO behavior, pasting of the secrets into the agent prompt became impossible. The reimplemented logic allows to add (paste) an arbitrary number of characters into a desired position of a secret string up to its max lengths. The deletion has also been reworked to accommodate the new behavior. --- client/display.c | 66 ++++++++++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 25 deletions(-) diff --git a/client/display.c b/client/display.c index f2cacd9a..7ee075dc 100644 --- a/client/display.c +++ b/client/display.c @@ -397,48 +397,64 @@ static void display_completion_matches(char **matches, int num_matches, static struct masked_input { bool use_mask; char passphrase[MAX_PASSPHRASE_LEN]; - char mask[MAX_PASSPHRASE_LEN]; + uint8_t point; + uint8_t end; } masked_input; static void mask_input(void) { - int point; - char *line; - size_t len; - if (!masked_input.use_mask) return; - line = rl_copy_text(0, rl_end); - len = strlen(line); - - if (!len) - goto done; - - point = rl_point; - - if (len > MAX_PASSPHRASE_LEN) { - point--; - } else if (strlen(masked_input.passphrase) > len) { - masked_input.passphrase[len] = 0; - masked_input.mask[len] = 0; - } else { - masked_input.passphrase[len - 1] = line[len - 1]; - masked_input.mask[len - 1] = '*'; + if (rl_end > MAX_PASSPHRASE_LEN) { + rl_point = rl_end = MAX_PASSPHRASE_LEN; + goto set_mask; } - rl_replace_line(masked_input.mask, 0); - rl_point = point; + if (masked_input.end == rl_end) { + /* Moving cursor. */ + goto done; + } else if (masked_input.end < rl_end) { + /* Insertion. */ + memcpy(masked_input.passphrase + rl_point, + masked_input.passphrase + masked_input.point, + masked_input.end - masked_input.point); + memcpy(masked_input.passphrase + masked_input.point, + rl_line_buffer + masked_input.point, + rl_point - masked_input.point); + } else { + /* Deletion. */ + if (masked_input.point > rl_point) + /* Backspace key. */ + memcpy(masked_input.passphrase + rl_point, + masked_input.passphrase + masked_input.point, + masked_input.end - masked_input.point); + else + /* Delete key. */ + memcpy(masked_input.passphrase + rl_point, + masked_input.passphrase + masked_input.point + + 1, + rl_end - rl_point); + memset(masked_input.passphrase + rl_end, 0, + masked_input.end - rl_end); + } + +set_mask: + memset(rl_line_buffer, '*', rl_end); + rl_line_buffer[rl_end] = '\0'; + rl_redisplay(); + masked_input.end = rl_end; done: - l_free(line); + masked_input.point = rl_point; } static void reset_masked_input(void) { memset(masked_input.passphrase, 0, MAX_PASSPHRASE_LEN); - memset(masked_input.mask, 0, MAX_PASSPHRASE_LEN); + masked_input.point = 0; + masked_input.end = 0; } static void readline_callback(char *prompt)