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:
@ -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
|
||||
|
Reference in New Issue
Block a user