From c3bb2a255619f9a96ac14ad606f34f847907fedc Mon Sep 17 00:00:00 2001 From: "Steffen (Daode) Nurpmeso" Date: Sat, 22 Feb 2014 20:19:27 +0100 Subject: [PATCH] Make password prompts interruptable.. Thanks to a message from Andy Switala (andy DOT switala AT gmail DOT com) i came back to non-interruptable password prompts. We have to use patched SIGINT handlers for this to work for quite some time, but since implementing this made me realize an ever-existing memory leak (sclose(): free socket write buffer..) and an oddity in `smemtrace' pointer display (auxlily.c: _HOPE_GET_TRACE(): adjust pointer..) it's a good thing. --- imap.c | 1 - openssl.c | 48 ++++++++++++++---------------------------------- pop3.c | 1 - tty.c | 44 ++++++++++++++++++++++++++++++++++++++------ 4 files changed, 52 insertions(+), 42 deletions(-) diff --git a/imap.c b/imap.c index 8525b401..f9252302 100644 --- a/imap.c +++ b/imap.c @@ -570,7 +570,6 @@ static void imapcatch(int s) { NYD_X; /* Signal handler */ - termios_state_reset(); switch (s) { case SIGINT: fprintf(stderr, tr(102, "Interrupt\n")); diff --git a/openssl.c b/openssl.c index 3dd11117..b1078886 100644 --- a/openssl.c +++ b/openssl.c @@ -129,13 +129,11 @@ static struct smime_cipher const _smime_ciphers[] = { # error cipher algorithms that are required to support S/MIME #endif -static sigjmp_buf ssljmp; static int initialized; static int rand_init; static int message_number; static int verify_error_found; -static void sslcatch(int s); static int ssl_rand_init(void); static void ssl_init(void); static int ssl_verify_cb(int success, X509_STORE_CTX *store); @@ -158,14 +156,6 @@ static enum okay load_crl1(X509_STORE *store, char const *name); #endif static enum okay load_crls(X509_STORE *store, enum okeys fok, enum okeys dok); -static void -sslcatch(int s) -{ - NYD_X; /* Signal handler */ - termios_state_reset(); - siglongjmp(ssljmp, s); -} - static int ssl_rand_init(void) { @@ -548,30 +538,20 @@ jleave: static int ssl_password_cb(char *buf, int size, int rwflag, void *userdata) { - sighandler_type volatile saveint; - char *pass = NULL; + char *pass; size_t len; NYD_ENTER; UNUSED(rwflag); UNUSED(userdata); - saveint = safe_signal(SIGINT, SIG_IGN); - if (sigsetjmp(ssljmp, 1) == 0) { - if (saveint != SIG_IGN) - safe_signal(SIGINT, sslcatch); - pass = getpassword("PEM pass phrase:"); - } - safe_signal(SIGINT, saveint); - - if (pass == NULL) { + if ((pass = getpassword("PEM pass phrase:")) != NULL) { + len = strlen(pass); + if (UICMP(z, len, >=, size)) + len = size -1; + memcpy(buf, pass, len); + buf[len] = '\0'; + } else len = 0; - goto jleave; - } - len = strlen(pass); - if (UICMP(z, len, >, size)) - len = size; - memcpy(buf, pass, len); -jleave: NYD_LEAVE; return (int)len; } @@ -677,7 +657,7 @@ smime_sign_include_chain_creat(_STACKOF(X509) **chain, char const *cfiles) perror(cfiles); goto jerr; } - if ((tmp = PEM_read_X509(fp, NULL, ssl_password_cb, NULL)) == NULL) { + if ((tmp = PEM_read_X509(fp, NULL, &ssl_password_cb, NULL)) == NULL) { ssl_gen_err(tr(560, "Error reading certificate from \"%s\""), rest); Fclose(fp); goto jerr; @@ -941,13 +921,13 @@ smime_sign(FILE *ip, struct header *headp) if ((fp = smime_sign_cert(addr, NULL, 1)) == NULL) goto jleave; - if ((pkey = PEM_read_PrivateKey(fp, NULL, ssl_password_cb, NULL)) == NULL) { + if ((pkey = PEM_read_PrivateKey(fp, NULL, &ssl_password_cb, NULL)) == NULL) { ssl_gen_err(tr(532, "Error reading private key from")); goto jleave; } rewind(fp); - if ((cert = PEM_read_X509(fp, NULL, ssl_password_cb, NULL)) == NULL) { + if ((cert = PEM_read_X509(fp, NULL, &ssl_password_cb, NULL)) == NULL) { ssl_gen_err(tr(533, "Error reading signer certificate from")); goto jleave; } @@ -1039,7 +1019,7 @@ smime_encrypt(FILE *ip, char const *xcertfile, char const *to) goto jleave; } - if ((cert = PEM_read_X509(fp, NULL, ssl_password_cb, NULL)) == NULL) { + if ((cert = PEM_read_X509(fp, NULL, &ssl_password_cb, NULL)) == NULL) { ssl_gen_err(tr(547, "Error reading encryption certificate from \"%s\""), certfile); bail = TRU1; @@ -1121,7 +1101,7 @@ smime_decrypt(struct message *m, char const *to, char const *cc, int signcall) ssl_init(); if ((fp = smime_sign_cert(to, cc, 0)) != NULL) { - pkey = PEM_read_PrivateKey(fp, NULL, ssl_password_cb, NULL); + pkey = PEM_read_PrivateKey(fp, NULL, &ssl_password_cb, NULL); if (pkey == NULL) { ssl_gen_err(tr(551, "Error reading private key")); Fclose(fp); @@ -1129,7 +1109,7 @@ smime_decrypt(struct message *m, char const *to, char const *cc, int signcall) } rewind(fp); - if ((cert = PEM_read_X509(fp, NULL, ssl_password_cb, NULL)) == NULL) { + if ((cert = PEM_read_X509(fp, NULL, &ssl_password_cb, NULL)) == NULL) { ssl_gen_err(tr(552, "Error reading decryption certificate")); Fclose(fp); EVP_PKEY_free(pkey); diff --git a/pop3.c b/pop3.c index 345b9b2e..6d95a093 100644 --- a/pop3.c +++ b/pop3.c @@ -397,7 +397,6 @@ static void pop3catch(int s) { NYD_X; /* Signal handler */ - termios_state_reset(); switch (s) { case SIGINT: fprintf(stderr, tr(102, "Interrupt\n")); diff --git a/tty.c b/tty.c index 6529a885..5957a59a 100644 --- a/tty.c +++ b/tty.c @@ -130,6 +130,15 @@ jleave:\ * and place the implementations one after the other below the other externals */ +static sigjmp_buf __tty_actjmp; /* TODO someday, we won't need it no more */ +static void +__tty_acthdl(int s) /* TODO someday, we won't need it no more */ +{ + NYD_X; /* Signal handler */ + termios_state_reset(); + siglongjmp(__tty_actjmp, s); +} + FL bool_t getapproval(char const *prompt, bool_t noninteract_default) { @@ -173,29 +182,42 @@ yorn(char const *msg) /* TODO obsolete */ } FL char * -getuser(char const *query) +getuser(char const * volatile query) { + sighandler_type volatile ohdl; char *user = NULL; + bool_t hadsig = FAL0; NYD_ENTER; if (query == NULL) query = tr(509, "User: "); -/* FIXME WE NEED TO BE INTERRUPTIBLE - steal the getpassword stuff from - * FIXME openssl.c, remove it there! */ + ohdl = safe_signal(SIGINT, SIG_IGN); + if (sigsetjmp(__tty_actjmp, 1) != 0) { + hadsig = TRU1; + goto jrestore; + } + safe_signal(SIGINT, &__tty_acthdl); + if (readline_input(query, FAL0, &termios_state.ts_linebuf, &termios_state.ts_linesize, NULL) >= 0) user = termios_state.ts_linebuf; +jrestore: termios_state_reset(); + safe_signal(SIGINT, ohdl); NYD_LEAVE; + if (hadsig && ohdl != SIG_IGN) + kill(0, SIGINT); return user; } FL char * getpassword(char const *query) /* FIXME encaps ttystate signal safe */ { + sighandler_type volatile ohdl; struct termios tios; char *pass = NULL; + bool_t hadsig = FAL0; NYD_ENTER; if (query == NULL) @@ -204,7 +226,8 @@ getpassword(char const *query) /* FIXME encaps ttystate signal safe */ fflush(stdout); /* FIXME everywhere: tcsetattr() generates SIGTTOU when we're not in - * FIXME foreground pgrp, and can fail with EINTR!! */ + * FIXME foreground pgrp, and can fail with EINTR!! also affects + * FIXME termios_state_reset() */ if (options & OPT_TTYIN) { tcgetattr(STDIN_FILENO, &termios_state.ts_tios); memcpy(&tios, &termios_state.ts_tios, sizeof tios); @@ -214,15 +237,24 @@ getpassword(char const *query) /* FIXME encaps ttystate signal safe */ tcsetattr(STDIN_FILENO, TCSAFLUSH, &tios); } -/* FIXME WE NEED TO BE INTERRUPTIBLE */ + ohdl = safe_signal(SIGINT, SIG_IGN); + if (sigsetjmp(__tty_actjmp, 1) != 0) { + hadsig = TRU1; + goto jrestore; + } + safe_signal(SIGINT, &__tty_acthdl); + if (readline_restart(stdin, &termios_state.ts_linebuf, &termios_state.ts_linesize, 0) >= 0) pass = termios_state.ts_linebuf; +jrestore: termios_state_reset(); - + safe_signal(SIGINT, ohdl); if (options & OPT_TTYIN) fputc('\n', stdout); NYD_LEAVE; + if (hadsig && ohdl != SIG_IGN) + kill(0, SIGINT); return pass; } -- 2.11.4.GIT