diff options
Diffstat (limited to '')
-rw-r--r-- | Makefile | 14 | ||||
-rw-r--r-- | src/passphrase.c | 245 |
2 files changed, 233 insertions, 26 deletions
@@ -3,9 +3,17 @@ LIB = /lib INCLUDE = /include OPTIONS = -# PASSPHRASE_ECHO: Do not hide the passphrase -# PASSPHRASE_STAR: Use '*' for each character instead of no echo -# PASSPHRASE_REALLOC: Soften security by using `realloc` +# PASSPHRASE_ECHO: Do not hide the passphrase +# PASSPHRASE_STAR: Use '*' for each character instead of no echo +# PASSPHRASE_REALLOC: Soften security by using `realloc` +# PASSPHRASE_MOVE: Enable move of point +# PASSPHRASE_INSERT: Enable insert mode +# PASSPHRASE_OVERRIDE: Enable override mode +# PASSPHRASE_DELETE: Enable reversed erase command +# PASSPHRASE_CONTROL: Enable use of control key combinations +# PASSPHRASE_DEDICATED: Enable use of dedicated keys +# DEFAULT_INSERT: Use insert mode as default +# PASSPHRASE_INVALID: Prevent duplication of non-initialised memory OPTIMISE = -Os CPPFLAGS = $(foreach D, $(OPTIONS), -D'$(D)=1') diff --git a/src/passphrase.c b/src/passphrase.c index 8ff4c56..751a77b 100644 --- a/src/passphrase.c +++ b/src/passphrase.c @@ -27,7 +27,7 @@ #define START_PASSPHRASE_LIMIT 32 -#ifndef PASSPHRASE_ECHO +#if !defined(PASSPHRASE_ECHO) || defined(PASSPHRASE_MOVE) /** * The original TTY settings */ @@ -36,28 +36,43 @@ static struct termios saved_stty; #ifndef PASSPHRASE_REALLOC -static inline char* xrealloc(char* array, size_t size) +static inline char* xrealloc(char* array, size_t cur_size, size_t new_size) { - char* rc = malloc(size); - int i; + char* rc = malloc(new_size * sizeof(char)); + size_t i; if (rc) - for (i = 0; *(array + i); i++) - { + for (i = 0; i < cur_size; i++) *(rc + i) = *(array + i); - *(array + i) = 0; - } - else - for (i = 0; *(array + i); i++) - *(array + i) = 0; + for (i = 0; i < cur_size; i++) + *(array + i) = 0; free(array); return rc; } #else -#define xrealloc realloc +#define xrealloc(array, _cur_size, new_size) realloc(array, (new_size) * sizeof(char)) #endif -#define xprintf(...) ({ printf(__VA_ARGS__); fflush(stdout); }) +#if defined(PASSPHRASE_MOVE) && !defined(PASSPHRASE_STAR) && !defined(PASSPHRASE_ECHO) +# define xprintf(...) /* do nothing */ +# define xflush() /* do nothing */ +#elif defined(PASSPHRASE_MOVE) || defined(PASSPHRASE_STAR) +# define xprintf printf +# define xflush() fflush(stdout) +#else +# define xflush() fflush(stdout) +#endif + + +#ifdef PASSPHRASE_MOVE +# if defined(PASSPHRASE_STAR) +# define xputchar(C) ({ if ((c & 0xC0) != 0x80) putchar('*'); }) +# elif defined(PASSPHRASE_ECHO) +# define xputchar(C) putchar(C) +# else +# define xputchar(C) /* be silent */ +# endif +#endif /** @@ -69,7 +84,18 @@ char* passphrase_read(void) { char* rc = malloc(START_PASSPHRASE_LIMIT * sizeof(char)); long size = START_PASSPHRASE_LIMIT; - long len = 0; + long len = 0; +#ifdef PASSPHRASE_MOVE + long point = 0; + long i = 0; +# ifdef PASSPHRASE_OVERRIDE +# if defined(PASSPHRASE_INSERT) && defined(DEFAULT_INSERT) + char insert = 1; +# elif defined(PASSPHRASE_INSERT) + char insert = 0; +# endif +# endif +#endif int c; if (rc == NULL) @@ -85,28 +111,201 @@ char* passphrase_read(void) break; if (c != 0) { -#ifdef PASSPHRASE_STAR +#if defined(PASSPHRASE_MOVE) + /* \e[1~ \eOH ^A -1 home */ + /* \e[2~ -2 insert */ + /* \e[3~ ^D -3 delete */ + /* \e[4~ \eOF ^E -4 end */ + /* \8 \127 -5 erase */ + /* \e[C ^F -6 right */ + /* \e[D ^B -7 left */ + int cc = 0; +#ifdef PASSPHRASE_DEDICATED + if (c == '\033') + { + c = getchar(); + if (c == 'O') + { + c = getchar(); + if (c == 'H') cc = -1; + else if (c == 'F') cc = -4; + } + else if (c == '[') + { + c = getchar(); + if (c == 'C') cc = -6; + else if (c == 'D') cc = -7; + else if (('1' <= c) && (c <= '4') && (getchar() == '~')) + cc = -(c - '0'); + } + } + else +#endif + if ((c == 8) || (c == 127)) + cc = -5; + else if ((c < 0) || (c >= ' ')) + cc = ((int)c) & 255; +#ifdef PASSPHRASE_CONTROL + else if (c == 'A' - '@') cc = -1; + else if (c == 'B' - '@') cc = -7; + else if (c == 'D' - '@') cc = -3; + else if (c == 'E' - '@') cc = -4; + else if (c == 'F' - '@') cc = -6; +#endif + + if (cc > 0) + { + c = (char)cc; + if (point == len) + { + xputchar(c); + *(rc + len++) = c; + } +#ifdef PASSPHRASE_INSERT + else +#ifdef PASSPHRASE_OVERRIDE + if (insert) +#endif + { + if ((c & 0xC0) != 0x80) + xprintf("\033[@"); + xputchar(c); + for (i = point; i < len; i++) + *(rc + i + 1) = *(rc + i); + len++; + *(rc + point++) = c; + } +#endif +#ifdef PASSPHRASE_OVERRIDE + else + { + long n = 1; + char cn = c; + while (*(rc + point + n)) + n++; + for (i = point; i < len; i++) + *(rc + i) = *(rc + i + n); + for (i = len - n; i < len; i++) + *(rc + point + i) = 0; + len -= n; + n = 0; + while (cn & 0x80) + { + cn <<= 1; + n++; + } + n = n ?: 1; + if (len + n > size) + { + if ((rc = xrealloc(rc, size, size << 1L)) == NULL) + return NULL; + size <<= 1L; + } + for (i = point; i < len; i++) + *(rc + i + n) = *(rc + i); + len += n; + for (i = 0; i < n; i++) + { + if (i) + c = getchar(); + xputchar(c); + *(rc + point++) = c; + } + } +#endif + } + else if ((cc == -1) && point) /* home */ + { + xprintf("\033[%liD", point); + point = 0; + } +#if defined(PASSPHRASE_INSERT) && defined(PASSPHRASE_OVERRIDE) + else if (cc == -2) /* insert */ + insert ^= 1; +#endif +#ifdef PASSPHRASE_DELETE + else if ((cc == -3) && (len != point)) /* delete */ + { + xprintf("\033[P"); +#ifdef PASSPHRASE_INVALID + *(rc + len) = 0; +#endif + do + { + for (i = point; i < len; i++) + *(rc + i) = *(rc + i + 1); + len--; + } + while ((len != point) && ((*(rc + point) & 0xC0) == 0x80)); + } +#endif + else if ((cc == -4) && (len != point)) /* end */ + { + xprintf("\033[%liC", len - point); + point = len; + } + else if ((cc == -5) && point) /* erase */ + { + char redo = 1; + xprintf("\033[D\033[P"); +#ifdef PASSPHRASE_INVALID + *(rc + len) = 0; +#endif + while (redo) + { + redo = (*(rc + point) & 0xC0) == 0x80; + for (i = point; i <= len; i++) + *(rc + i - 1) = *(rc + i); + point--; + len--; + } + } + else if ((cc == -6) && (len != point)) /* right */ + { + xprintf("\033[C"); + do + point++; + while ((len != point) && ((*(rc + point) & 0xC0) == 0x80)); + } + else if ((cc == -7) && point) /* left */ + { + char redo = 1 + xprintf("\033[D"); + while (redo) + redo = (*(rc + point--) & 0xC0) == 0x80; + } + +#elif defined(PASSPHRASE_STAR) if ((c == 8) || (c == 127)) { if (len == 0) continue; xprintf("\033[D \033[D"); + xflush(); *(rc + --len) = 0; continue; } - putchar('*'); -#endif + if ((c & 0xC0) != 0x80) + putchar('*'); *(rc + len++) = c; +#else + *(rc + len++) = c; +#endif + + xflush(); if (len == size) - if ((rc = xrealloc(rc, (size <<= 1L) * sizeof(char))) == NULL) - return rc; + { + if ((rc = xrealloc(rc, size, size << 1L)) == NULL) + return NULL; + size <<= 1L; + } } } /* NUL-terminate passphrase */ *(rc + len) = 0; -#ifndef PASSPHRASE_ECHO +#if !defined(PASSPHRASE_ECHO) || defined(PASSPHRASE_MOVE) printf("\n"); #endif return rc; @@ -118,13 +317,13 @@ char* passphrase_read(void) */ void passphrase_disable_echo(void) { -#ifndef PASSPHRASE_ECHO +#if !defined(PASSPHRASE_ECHO) || defined(PASSPHRASE_MOVE) struct termios stty; tcgetattr(STDIN_FILENO, &stty); saved_stty = stty; stty.c_lflag &= ~ECHO; -#ifdef PASSPHRASE_STAR +#if defined(PASSPHRASE_STAR) || defined(PASSPHRASE_MOVE) stty.c_lflag &= ~ICANON; #endif tcsetattr(STDIN_FILENO, TCSAFLUSH, &stty); @@ -137,7 +336,7 @@ void passphrase_disable_echo(void) */ void passphrase_reenable_echo(void) { -#ifndef PASSPHRASE_ECHO +#if !defined(PASSPHRASE_ECHO) || defined(PASSPHRASE_MOVE) tcsetattr(STDIN_FILENO, TCSAFLUSH, &saved_stty); #endif } |