1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-06-30 19:12:48 -05:00

Unix Pageant: implement GUI passphrase prompting.

I've written my own analogue of OpenSSH's ssh-askpass. At the moment,
it's contained inside Pageant proper, though it could easily be
compiled into a standalone binary as well or instead.

Unlike OpenSSH's version, I don't use a GTK edit box; instead I just
process key events myself and append them to a buffer. The big
advantage of doing this is that I can arrange for ^W and ^U to
function as they do in terminal line editing, i.e. delete a word or
delete the whole line.

^W in particular is really valuable when typing a multiple-word
passphrase unseen. If you feel yourself making the kind of typo in
which you're not sure if you pressed six keys or just five, you can
hit ^W and restart just that word, without either having to go right
back to the beginning or carry on and see if you feel lucky.

A delete-word function would of course be an information leak in even
an obscured edit box (displaying a blob per character), so instead I
give a visual acknowledgment of keypresses by a more ad-hoc means: I
display three lights in the box, and every meaningful keypress turns
off the currently active one and instead turns on a randomly selected
one of the others. (So the lit light doesn't even indicate _mod 3_ how
many keys have been pressed.)
This commit is contained in:
Simon Tatham
2015-05-13 13:55:08 +01:00
parent 460c45dd23
commit 75b7ba26d3
3 changed files with 432 additions and 24 deletions

View File

@ -292,30 +292,50 @@ const char *display = NULL;
static char *askpass(const char *comment)
{
prompts_t *p = new_prompts(NULL);
int ret;
if (have_controlling_tty()) {
int ret;
prompts_t *p = new_prompts(NULL);
p->to_server = FALSE;
p->name = dupstr("Pageant passphrase prompt");
add_prompt(p,
dupprintf("Enter passphrase to load key '%s': ", comment),
FALSE);
ret = console_get_userpass_input(p, NULL, 0);
assert(ret >= 0);
/*
* FIXME: if we don't have a terminal, and have to do this by X11,
* there's a big missing piece.
*/
if (!ret) {
perror("pageant: unable to read passphrase");
free_prompts(p);
return NULL;
} else {
char *passphrase = dupstr(p->prompts[0]->result);
free_prompts(p);
return passphrase;
}
} else if (display) {
char *prompt, *passphrase;
int success;
p->to_server = FALSE;
p->name = dupstr("Pageant passphrase prompt");
add_prompt(p,
dupprintf("Enter passphrase to load key '%s': ", comment),
FALSE);
ret = console_get_userpass_input(p, NULL, 0);
assert(ret >= 0);
/* in gtkask.c */
char *gtk_askpass_main(const char *display, const char *wintitle,
const char *prompt, int *success);
if (!ret) {
perror("pageant: unable to read passphrase");
free_prompts(p);
return NULL;
} else {
char *passphrase = dupstr(p->prompts[0]->result);
free_prompts(p);
prompt = dupprintf("Enter passphrase to load key '%s': ", comment);
passphrase = gtk_askpass_main(display,
"Pageant passphrase prompt",
prompt, &success);
sfree(prompt);
if (!success) {
/* return value is error message */
fprintf(stderr, "%s\n", passphrase);
sfree(passphrase);
passphrase = NULL;
}
return passphrase;
} else {
fprintf(stderr, "no way to read a passphrase without tty or "
"X display\n");
return NULL;
}
}
@ -697,8 +717,6 @@ void run_agent(void)
NULL
};
if (!display)
display = getenv("DISPLAY");
if (!display) {
fprintf(stderr, "pageant: no DISPLAY for -X mode\n");
exit(1);
@ -982,6 +1000,12 @@ int main(int argc, char **argv)
sk_init();
uxsel_init();
if (!display) {
display = getenv("DISPLAY");
if (display && !*display)
display = NULL;
}
/*
* Now distinguish our two main running modes. Either we're
* actually starting up an agent, in which case we should have a