[PATCH] pinentry-curses: Handle SETREPEAT.
Ben Kibbey
bjk at luxsci.net
Wed Aug 17 02:51:35 CEST 2016
* pinentry/pinentry-curses.c (DIALOG_POS_REPEAT_PIN): New.
(dialog_t): Separate members for repeat.
(dialog_create): Create passphrase repeat field.
(dialog_switch_pos): Handle DIALOG_POS_REPEAT_PIN.
(dialog_input): Modify to handle the repeat field.
(test_repeat): New.
(dialog_run): Skip OK when changing fields and passphrases do not match.
Signed-off-by: Ben Kibbey <bjk at luxsci.net>
---
pinentry/pinentry-curses.c | 287 +++++++++++++++++++++++++++++++++++----------
1 file changed, 227 insertions(+), 60 deletions(-)
diff --git a/pinentry/pinentry-curses.c b/pinentry/pinentry-curses.c
index 659fa47..267d5be 100644
--- a/pinentry/pinentry-curses.c
+++ b/pinentry/pinentry-curses.c
@@ -70,6 +70,7 @@ typedef enum
{
DIALOG_POS_NONE,
DIALOG_POS_PIN,
+ DIALOG_POS_REPEAT_PIN,
DIALOG_POS_OK,
DIALOG_POS_NOTOK,
DIALOG_POS_CANCEL
@@ -79,15 +80,21 @@ dialog_pos_t;
struct dialog
{
dialog_pos_t pos;
+ char *repeat_pin;
int pin_y;
int pin_x;
+ int repeat_pin_y;
+ int repeat_pin_x;
/* Width of the PIN field. */
int pin_size;
+ int repeat_pin_size;
/* Cursor location in PIN field. */
int pin_loc;
+ int repeat_pin_loc;
int pin_max;
/* Length of PIN. */
int pin_len;
+ int repeat_pin_len;
int ok_y;
int ok_x;
@@ -236,6 +243,7 @@ dialog_create (pinentry_t pinentry, dialog_t dialog)
CH *description = NULL;
CH *error = NULL;
CH *prompt = NULL;
+ CH *repeat_passphrase = NULL;
dialog->pinentry = pinentry;
@@ -256,6 +264,7 @@ dialog_create (pinentry_t pinentry, dialog_t dialog)
COPY_OUT (description);
COPY_OUT (error);
COPY_OUT (prompt);
+ COPY_OUT (repeat_passphrase);
/* There is no pinentry->default_notok. Map it to
pinentry->notok. */
@@ -364,6 +373,9 @@ dialog_create (pinentry_t pinentry, dialog_t dialog)
y += 2; /* Error message. */
}
y += 2; /* Pin entry field. */
+
+ if (pinentry->repeat_passphrase)
+ y += 2;
}
y += 2; /* OK/Cancel and bottom frame. */
@@ -401,8 +413,12 @@ dialog_create (pinentry_t pinentry, dialog_t dialog)
new_x = MIN_PINENTRY_LENGTH;
if (prompt)
{
- new_x += STRLEN (prompt) + 1; /* One space after prompt. */
+ int n = repeat_passphrase ? STRLEN (repeat_passphrase) : 0;
+ new_x += STRLEN (prompt) + n + 1; /* One space after prompt. */
}
+ else if (repeat_passphrase)
+ new_x += STRLEN (repeat_passphrase) + 1;
+
if (new_x > size_x - 4)
new_x = size_x - 4;
if (new_x > x)
@@ -431,8 +447,8 @@ dialog_create (pinentry_t pinentry, dialog_t dialog)
dialog->pos = DIALOG_POS_NONE;
dialog->pin_max = pinentry->pin_len;
- dialog->pin_loc = 0;
- dialog->pin_len = 0;
+ dialog->pin_loc = dialog->repeat_pin_loc = 0;
+ dialog->pin_len = dialog->repeat_pin_len = 0;
ypos = (size_y - y) / 2;
xpos = (size_x - x) / 2;
move (ypos, xpos);
@@ -545,6 +561,35 @@ dialog_create (pinentry_t pinentry, dialog_t dialog)
move (ypos, xpos);
addch (ACS_VLINE);
ypos++;
+
+ if (repeat_passphrase)
+ {
+ CH *p = repeat_passphrase;
+
+ move (ypos, xpos);
+ addch (ACS_VLINE);
+ addch (' ');
+
+ dialog->repeat_pin_y = ypos;
+ dialog->repeat_pin_x = xpos + 2;
+ dialog->repeat_pin_size = x - 4;
+ i = STRLEN (p);
+ if (i > x - 4 - MIN_PINENTRY_LENGTH)
+ i = x - 4 - MIN_PINENTRY_LENGTH;
+ dialog->repeat_pin_x += i + 1;
+ dialog->repeat_pin_size -= i + 1;
+ while (i-- > 0)
+ {
+ ADDCH (*(p++));
+ }
+ addch (' ');
+ for (i = 0; i < dialog->repeat_pin_size; i++)
+ addch ('_');
+ ypos++;
+ move (ypos, xpos);
+ addch (ACS_VLINE);
+ ypos++;
+ }
}
move (ypos, xpos);
addch (ACS_VLINE);
@@ -590,6 +635,8 @@ dialog_create (pinentry_t pinentry, dialog_t dialog)
free (error);
if (prompt)
free (prompt);
+ if (repeat_passphrase)
+ free (repeat_passphrase);
return err;
}
@@ -620,8 +667,8 @@ dialog_switch_pos (dialog_t diag, dialog_pos_t new_pos)
switch (diag->pos)
{
case DIALOG_POS_OK:
- move (diag->ok_y, diag->ok_x);
- addstr (diag->ok);
+ move (diag->ok_y, diag->ok_x);
+ addstr (diag->ok);
break;
case DIALOG_POS_NOTOK:
if (diag->notok)
@@ -647,13 +694,17 @@ dialog_switch_pos (dialog_t diag, dialog_pos_t new_pos)
move (diag->pin_y, diag->pin_x + diag->pin_loc);
set_cursor_state (1);
break;
+ case DIALOG_POS_REPEAT_PIN:
+ move (diag->repeat_pin_y, diag->repeat_pin_x + diag->repeat_pin_loc);
+ set_cursor_state (1);
+ break;
case DIALOG_POS_OK:
set_cursor_state (0);
- move (diag->ok_y, diag->ok_x);
- standout ();
- addstr (diag->ok);
- standend ();
- move (diag->ok_y, diag->ok_x);
+ move (diag->ok_y, diag->ok_x);
+ standout ();
+ addstr (diag->ok);
+ standend ();
+ move (diag->ok_y, diag->ok_x);
break;
case DIALOG_POS_NOTOK:
if (diag->notok)
@@ -690,9 +741,36 @@ dialog_switch_pos (dialog_t diag, dialog_pos_t new_pos)
static void
dialog_input (dialog_t diag, int alt, int chr)
{
- int old_loc = diag->pin_loc;
+ int old_loc = diag->pos == DIALOG_POS_PIN ? diag->pin_loc
+ : diag->repeat_pin_loc;
+ int *pin_len;
+ int *pin_loc;
+ int *pin_size;
+ int *pin_x, *pin_y;
+ int *pin_max = &diag->pin_max;
+ char *pin;
+
assert (diag->pinentry->pin);
- assert (diag->pos == DIALOG_POS_PIN);
+ assert (diag->pos == DIALOG_POS_PIN || diag->pos == DIALOG_POS_REPEAT_PIN);
+
+ if (diag->pos == DIALOG_POS_PIN)
+ {
+ pin_len = &diag->pin_len;
+ pin_loc = &diag->pin_loc;
+ pin_size = &diag->pin_size;
+ pin_x = &diag->pin_x;
+ pin_y = &diag->pin_y;
+ pin = diag->pinentry->pin;
+ }
+ else
+ {
+ pin_len = &diag->repeat_pin_len;
+ pin_loc = &diag->repeat_pin_loc;
+ pin_size = &diag->repeat_pin_size;
+ pin_x = &diag->repeat_pin_x;
+ pin_y = &diag->repeat_pin_y;
+ pin = diag->repeat_pin;
+ }
if (alt && chr == KEY_BACKSPACE)
/* Remap alt-backspace to control-W. */
@@ -706,15 +784,15 @@ dialog_input (dialog_t diag, int alt, int chr)
/* ASCII DEL. What Mac OS X apparently emits when the "delete"
(backspace) key is pressed. */
case 127:
- if (diag->pin_len > 0)
+ if (*pin_len > 0)
{
- diag->pin_len--;
- diag->pin_loc--;
- if (diag->pin_loc == 0 && diag->pin_len > 0)
+ (*pin_len)--;
+ (*pin_loc)--;
+ if (*pin_loc == 0 && *pin_len > 0)
{
- diag->pin_loc = diag->pin_size - 5;
- if (diag->pin_loc > diag->pin_len)
- diag->pin_loc = diag->pin_len;
+ *pin_loc = *pin_size - 5;
+ if (*pin_loc > *pin_len)
+ *pin_loc = *pin_len;
}
}
break;
@@ -727,47 +805,45 @@ dialog_input (dialog_t diag, int alt, int chr)
case 'u' - 'a' + 1: /* control-u */
/* Erase the whole line. */
- if (diag->pin_len > 0)
+ if (*pin_len > 0)
{
- diag->pin_len = 0;
- diag->pin_loc = 0;
+ *pin_len = 0;
+ *pin_loc = 0;
}
break;
case 'w' - 'a' + 1: /* control-w. */
- while (diag->pin_len > 0
- && diag->pinentry->pin[diag->pin_len - 1] == ' ')
+ while (*pin_len > 0 && pin[*pin_len - 1] == ' ')
{
- diag->pin_len --;
- diag->pin_loc --;
- if (diag->pin_loc < 0)
+ (*pin_len)--;
+ (*pin_loc)--;
+ if (*pin_loc < 0)
{
- diag->pin_loc += diag->pin_size;
- if (diag->pin_loc > diag->pin_len)
- diag->pin_loc = diag->pin_len;
+ *pin_loc += *pin_size;
+ if (*pin_loc > *pin_len)
+ *pin_loc = *pin_len;
}
}
- while (diag->pin_len > 0
- && diag->pinentry->pin[diag->pin_len - 1] != ' ')
+ while (*pin_len > 0 && pin[*pin_len - 1] != ' ')
{
- diag->pin_len --;
- diag->pin_loc --;
- if (diag->pin_loc < 0)
+ (*pin_len)--;
+ (*pin_loc)--;
+ if (*pin_loc < 0)
{
- diag->pin_loc += diag->pin_size;
- if (diag->pin_loc > diag->pin_len)
- diag->pin_loc = diag->pin_len;
+ *pin_loc += *pin_size;
+ if (*pin_loc > *pin_len)
+ *pin_loc = *pin_len;
}
}
break;
default:
- if (chr > 0 && chr < 256 && diag->pin_len < diag->pin_max)
+ if (chr > 0 && chr < 256 && *pin_len < *pin_max)
{
/* Make sure there is enough room for this character and a
following NUL byte. */
- if (! pinentry_setbufferlen (diag->pinentry, diag->pin_len + 2))
+ if (! pinentry_setbufferlen (diag->pinentry, *pin_len + 2))
{
/* Bail. Here we use a simple approach. It would be
better to have a pinentry_bug function. */
@@ -775,32 +851,85 @@ dialog_input (dialog_t diag, int alt, int chr)
abort ();
}
- diag->pinentry->pin[diag->pin_len] = (char) chr;
- diag->pin_len++;
- diag->pin_loc++;
- if (diag->pin_loc == diag->pin_size && diag->pin_len < diag->pin_max)
+ if (diag->pos == DIALOG_POS_REPEAT_PIN)
+ {
+ if (!*pin_len || *pin_len > diag->repeat_pin_len)
+ {
+ char *newp = secmem_realloc (diag->repeat_pin, *pin_len + 2);
+
+ if (newp)
+ pin = diag->repeat_pin = newp;
+ else
+ {
+ secmem_free (diag->pinentry->pin);
+ diag->pinentry->pin = 0;
+ diag->pinentry->pin_len = 0;
+ secmem_free (diag->repeat_pin);
+ diag->repeat_pin = 0;
+ *pin_len = 0;
+ /* Bail. Here we use a simple approach. It would be
+ better to have a pinentry_bug function. */
+ assert (!"setbufferlen failed");
+ abort ();
+ }
+ }
+ }
+ else
+ pin = diag->pinentry->pin;
+
+ pin[*pin_len] = (char) chr;
+ (*pin_len)++;
+ (*pin_loc)++;
+ if (*pin_loc == *pin_size && *pin_len < *pin_max)
{
- diag->pin_loc = 5;
- if (diag->pin_loc < diag->pin_size - (diag->pin_max + 1 - diag->pin_len))
- diag->pin_loc = diag->pin_size - (diag->pin_max + 1 - diag->pin_len);
+ *pin_loc = 5;
+ if (*pin_loc < *pin_size - (*pin_max + 1 - *pin_len))
+ *pin_loc = *pin_size - (*pin_max + 1 - *pin_len);
}
}
break;
}
- if (old_loc < diag->pin_loc)
+ if (pin)
+ pin[*pin_len] = 0;
+
+ if (old_loc < *pin_loc)
{
- move (diag->pin_y, diag->pin_x + old_loc);
- while (old_loc++ < diag->pin_loc)
+ move (*pin_y, *pin_x + old_loc);
+ while (old_loc++ < *pin_loc)
addch ('*');
}
- else if (old_loc > diag->pin_loc)
+ else if (old_loc > *pin_loc)
{
- move (diag->pin_y, diag->pin_x + diag->pin_loc);
- while (old_loc-- > diag->pin_loc)
+ move (*pin_y, *pin_x + *pin_loc);
+ while (old_loc-- > *pin_loc)
addch ('_');
}
- move (diag->pin_y, diag->pin_x + diag->pin_loc);
+ move (*pin_y, *pin_x + *pin_loc);
+}
+
+static int
+test_repeat (dialog_t diag)
+{
+ if (!diag->pinentry->repeat_passphrase)
+ return 1;
+
+ if (!diag->pinentry->pin && !diag->repeat_pin)
+ return 1;
+
+ if ((diag->pinentry->pin && !*diag->pinentry->pin
+ && (!diag->repeat_pin || !*diag->repeat_pin)))
+ return 1;
+
+ if (diag->repeat_pin && !*diag->repeat_pin
+ && (!diag->pinentry->pin || !*diag->pinentry->pin))
+ return 1;
+
+ if (diag->pinentry->pin && diag->repeat_pin
+ && !strcmp (diag->pinentry->pin, diag->repeat_pin))
+ return 1;
+
+ return 0;
}
static int
@@ -957,9 +1086,15 @@ dialog_run (pinentry_t pinentry, const char *tty_name, const char *tty_type)
switch (diag.pos)
{
case DIALOG_POS_OK:
- if (diag.pinentry->pin)
+ if (diag.pinentry->repeat_passphrase)
+ dialog_switch_pos (&diag, DIALOG_POS_REPEAT_PIN);
+ else if (diag.pinentry->pin)
dialog_switch_pos (&diag, DIALOG_POS_PIN);
break;
+ case DIALOG_POS_REPEAT_PIN:
+ if (diag.pinentry->pin)
+ dialog_switch_pos (&diag, DIALOG_POS_PIN);
+ break;
case DIALOG_POS_NOTOK:
dialog_switch_pos (&diag, DIALOG_POS_OK);
break;
@@ -967,7 +1102,12 @@ dialog_run (pinentry_t pinentry, const char *tty_name, const char *tty_type)
if (diag.notok)
dialog_switch_pos (&diag, DIALOG_POS_NOTOK);
else
- dialog_switch_pos (&diag, DIALOG_POS_OK);
+ {
+ if (!test_repeat (&diag))
+ dialog_switch_pos (&diag, DIALOG_POS_REPEAT_PIN);
+ else
+ dialog_switch_pos (&diag, DIALOG_POS_OK);
+ }
break;
default:
break;
@@ -979,8 +1119,17 @@ dialog_run (pinentry_t pinentry, const char *tty_name, const char *tty_type)
switch (diag.pos)
{
case DIALOG_POS_PIN:
- dialog_switch_pos (&diag, DIALOG_POS_OK);
+ if (diag.pinentry->repeat_passphrase)
+ dialog_switch_pos (&diag, DIALOG_POS_REPEAT_PIN);
+ else
+ dialog_switch_pos (&diag, DIALOG_POS_OK);
break;
+ case DIALOG_POS_REPEAT_PIN:
+ if (test_repeat (&diag))
+ dialog_switch_pos (&diag, DIALOG_POS_OK);
+ else
+ dialog_switch_pos (&diag, DIALOG_POS_CANCEL);
+ break;
case DIALOG_POS_OK:
if (diag.notok)
dialog_switch_pos (&diag, DIALOG_POS_NOTOK);
@@ -999,8 +1148,17 @@ dialog_run (pinentry_t pinentry, const char *tty_name, const char *tty_type)
switch (diag.pos)
{
case DIALOG_POS_PIN:
- dialog_switch_pos (&diag, DIALOG_POS_OK);
+ if (diag.pinentry->repeat_passphrase)
+ dialog_switch_pos (&diag, DIALOG_POS_REPEAT_PIN);
+ else
+ dialog_switch_pos (&diag, DIALOG_POS_OK);
break;
+ case DIALOG_POS_REPEAT_PIN:
+ if (test_repeat (&diag))
+ dialog_switch_pos (&diag, DIALOG_POS_OK);
+ else
+ dialog_switch_pos (&diag, DIALOG_POS_CANCEL);
+ break;
case DIALOG_POS_OK:
if (diag.notok)
dialog_switch_pos (&diag, DIALOG_POS_NOTOK);
@@ -1029,7 +1187,10 @@ dialog_run (pinentry_t pinentry, const char *tty_name, const char *tty_type)
switch (diag.pos)
{
case DIALOG_POS_PIN:
+ case DIALOG_POS_REPEAT_PIN:
case DIALOG_POS_OK:
+ if (!test_repeat (&diag))
+ break;
done = 1;
break;
case DIALOG_POS_NOTOK:
@@ -1044,8 +1205,11 @@ dialog_run (pinentry_t pinentry, const char *tty_name, const char *tty_type)
break;
default:
- if (diag.pos == DIALOG_POS_PIN)
- dialog_input (&diag, alt, c);
+ if (diag.pos == DIALOG_POS_PIN || diag.pos == DIALOG_POS_REPEAT_PIN)
+ {
+ dialog_input (&diag, alt, c);
+ diag.pinentry->repeat_okay = test_repeat (&diag);
+ }
}
#ifndef HAVE_DOSISH_SYSTEM
no_input = 0;
@@ -1097,6 +1261,9 @@ dialog_run (pinentry_t pinentry, const char *tty_name, const char *tty_type)
}
}
+ if (diag.repeat_pin)
+ secmem_free (diag.repeat_pin);
+
if (done == -2)
pinentry->canceled = 1;
--
2.8.1
More information about the Gnupg-devel
mailing list