diff --git a/src/pgp/gpg.c b/src/pgp/gpg.c index cda77e13..3d6bdc09 100644 --- a/src/pgp/gpg.c +++ b/src/pgp/gpg.c @@ -48,6 +48,7 @@ #include "log.h" #include "common.h" #include "tools/autocomplete.h" +#include "ui/ui.h" #define PGP_SIGNATURE_HEADER "-----BEGIN PGP SIGNATURE-----" #define PGP_SIGNATURE_FOOTER "-----END PGP SIGNATURE-----" @@ -60,6 +61,9 @@ static GHashTable *pubkeys; static gchar *pubsloc; static GKeyFile *pubkeyfile; +static char *passphrase; +static char *passphrase_attempt; + static Autocomplete key_ac; static char* _remove_header_footer(char *str, const char * const footer); @@ -75,6 +79,33 @@ _p_gpg_free_pubkeyid(ProfPGPPubKeyId *pubkeyid) free(pubkeyid); } +static gpgme_error_t * +_p_gpg_passphrase_cb(void *hook, const char *uid_hint, const char *passphrase_info, int prev_was_bad, int fd) +{ + if (passphrase) { + gpgme_io_writen(fd, passphrase, strlen(passphrase)); + } else { + GString *pass_term = g_string_new(""); + + char *password = ui_ask_pgp_passphrase(uid_hint, prev_was_bad); + if (password) { + g_string_append(pass_term, password); + free(password); + } + + g_string_append(pass_term, "\n"); + if (passphrase_attempt) { + free(passphrase_attempt); + } + passphrase_attempt = pass_term->str; + g_string_free(pass_term, FALSE); + + gpgme_io_writen(fd, passphrase_attempt, strlen(passphrase_attempt)); + } + + return 0; +} + void p_gpg_init(void) { @@ -87,6 +118,9 @@ p_gpg_init(void) key_ac = autocomplete_new(); GHashTable *keys = p_gpg_list_keys(); p_gpg_free_keys(keys); + + passphrase = NULL; + passphrase_attempt = NULL; } void @@ -107,6 +141,16 @@ p_gpg_close(void) autocomplete_free(key_ac); key_ac = NULL; + + if (passphrase) { + free(passphrase); + passphrase = NULL; + } + + if (passphrase_attempt) { + free(passphrase_attempt); + passphrase_attempt = NULL; + } } void @@ -205,6 +249,16 @@ p_gpg_on_disconnect(void) free(pubsloc); pubsloc = NULL; + + if (passphrase) { + free(passphrase); + passphrase = NULL; + } + + if (passphrase_attempt) { + free(passphrase_attempt); + passphrase_attempt = NULL; + } } gboolean @@ -470,6 +524,8 @@ p_gpg_sign(const char * const str, const char * const fp) return NULL; } + gpgme_set_passphrase_cb(ctx, (gpgme_passphrase_cb_t)_p_gpg_passphrase_cb, NULL); + gpgme_key_t key = NULL; error = gpgme_get_key(ctx, fp, &key, 1); @@ -525,6 +581,10 @@ p_gpg_sign(const char * const str, const char * const fp) gpgme_free(signed_str); } + if (passphrase_attempt) { + passphrase = strdup(passphrase_attempt); + } + return result; } @@ -605,6 +665,8 @@ p_gpg_decrypt(const char * const cipher) return NULL; } + gpgme_set_passphrase_cb(ctx, (gpgme_passphrase_cb_t)_p_gpg_passphrase_cb, NULL); + char *cipher_with_headers = _add_header_footer(cipher, PGP_MESSAGE_HEADER, PGP_MESSAGE_FOOTER); gpgme_data_t cipher_data; gpgme_data_new_from_mem(&cipher_data, cipher_with_headers, strlen(cipher_with_headers), 1); @@ -650,6 +712,10 @@ p_gpg_decrypt(const char * const cipher) } gpgme_free(plain_str); + if (passphrase_attempt) { + passphrase = strdup(passphrase_attempt); + } + return result; } diff --git a/src/ui/core.c b/src/ui/core.c index 9ee8b9a5..5735f462 100644 --- a/src/ui/core.c +++ b/src/ui/core.c @@ -2101,9 +2101,33 @@ ui_win_unread(int index) char * ui_ask_password(void) { - status_bar_get_password(); - status_bar_update_virtual(); - return inp_get_password(); + status_bar_get_password(); + status_bar_update_virtual(); + return inp_get_password(); +} + +char * +ui_ask_pgp_passphrase(const char *hint, int prev_fail) +{ + ProfWin *current = wins_get_current(); + + win_println(current, 0, ""); + + if (prev_fail) { + win_print(current, '!', 0, NULL, 0, 0, "", "Incorrect passphrase"); + } + + if (hint) { + win_vprint(current, '!', 0, NULL, 0, 0, "", "Enter PGP key passphrase for %s", hint); + } else { + win_print(current, '!', 0, NULL, 0, 0, "", "Enter PGP key passphrase"); + } + + ui_update(); + + status_bar_get_password(); + status_bar_update_virtual(); + return inp_get_password(); } void diff --git a/src/ui/inputwin.c b/src/ui/inputwin.c index cb4d7a7e..9b4eddfb 100644 --- a/src/ui/inputwin.c +++ b/src/ui/inputwin.c @@ -230,7 +230,6 @@ inp_get_password(void) { werase(inp_win); wmove(inp_win, 0, 0); - pad_start = 0; _inp_win_update_virtual(); doupdate(); char *password = NULL; diff --git a/src/ui/ui.h b/src/ui/ui.h index e47cbddd..27395048 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -102,6 +102,7 @@ win_type_t ui_win_type(int index); void ui_close_win(int index); int ui_win_unread(int index); char * ui_ask_password(void); +char * ui_ask_pgp_passphrase(const char *hint, int prev_fail); void ui_handle_stanza(const char * const msg);