From fb1cdd7b0ebece16ffe60a30e4d01c5dbb1ca92b Mon Sep 17 00:00:00 2001 From: Ben Kibbey Date: Sun, 11 Sep 2011 16:55:34 -0400 Subject: [PATCH] Handle pinentry-mode=loopback. When this mode is set an inquire will be sent to the client to retrieve the passphrase. This adds a new inquire keyword "NEW_PASSPHRASE" that the GENKEY and PASSWD commands use when generating a new key. --- agent/ChangeLog | 9 +++++++++ agent/agent.h | 3 +++ agent/call-pinentry.c | 41 +++++++++++++++++++++++++++++++++++++++-- agent/command.c | 15 +++++++++++++++ agent/genkey.c | 17 +++++++++++++++++ 5 files changed, 83 insertions(+), 2 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index ec2dca219..18a94916d 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,12 @@ +2011-09-10 Ben Kibbey + + * agent.h (pinentry_loopback): New prototype. + * command.c (pinentry_loopback): New function to inquire a passphrase + from the client. For use with pinentry-mode=loopback. + * call-pinentry.c (agent_askpin): Handle PINENTRY_MODE_LOOPBACK. + * call-pinentry.c (agent_get_passphrase): Ditto. + * genkey.c (agent_ask_new_passphrase): Ditto. + 2011-08-10 Werner Koch * genkey.c (check_passphrase_pattern): Use gpg_strerror instead of diff --git a/agent/agent.h b/agent/agent.h index fbd71d51e..b323718fc 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -252,6 +252,9 @@ gpg_error_t agent_write_status (ctrl_t ctrl, const char *keyword, ...) void bump_key_eventcounter (void); void bump_card_eventcounter (void); void start_command_handler (ctrl_t, gnupg_fd_t, gnupg_fd_t); +gpg_error_t pinentry_loopback(ctrl_t, const char *keyword, + unsigned char **buffer, size_t *size, + size_t max_length); /*-- command-ssh.c --*/ void start_command_handler_ssh (ctrl_t, gnupg_fd_t); diff --git a/agent/call-pinentry.c b/agent/call-pinentry.c index 4c30f6dea..d0cfd2b79 100644 --- a/agent/call-pinentry.c +++ b/agent/call-pinentry.c @@ -746,8 +746,29 @@ agent_askpin (ctrl_t ctrl, { if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL) return gpg_error (GPG_ERR_CANCELED); - /*FIXME: Implement loopback mode. */ - return gpg_error (GPG_ERR_NO_PIN_ENTRY); + if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK) + { + unsigned char *passphrase; + size_t size; + + *pininfo->pin = 0; /* Reset the PIN. */ + rc = pinentry_loopback(ctrl, "PASSPHRASE", &passphrase, &size, + pininfo->max_length); + if (rc) + return rc; + + memcpy(&pininfo->pin, passphrase, size); + xfree(passphrase); + pininfo->pin[size] = 0; + if (pininfo->check_cb) + { + /* More checks by utilizing the optional callback. */ + pininfo->cb_errtext = NULL; + rc = pininfo->check_cb (pininfo); + } + return rc; + } + return gpg_error(GPG_ERR_NO_PIN_ENTRY); } if (!pininfo || pininfo->max_length < 1) @@ -908,6 +929,22 @@ agent_get_passphrase (ctrl_t ctrl, if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL) return gpg_error (GPG_ERR_CANCELED); + if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK) + { + size_t size; + size_t len = ASSUAN_LINELENGTH/2; + unsigned char *buffer = gcry_malloc_secure (len); + + rc = pinentry_loopback(ctrl, "PASSPHRASE", &buffer, &size, len); + if (rc) + xfree(buffer); + else + { + buffer[size] = 0; + *retpass = buffer; + } + return rc; + } return gpg_error (GPG_ERR_NO_PIN_ENTRY); } diff --git a/agent/command.c b/agent/command.c index 6973e78e5..f310a980c 100644 --- a/agent/command.c +++ b/agent/command.c @@ -2731,3 +2731,18 @@ start_command_handler (ctrl_t ctrl, gnupg_fd_t listen_fd, gnupg_fd_t fd) xfree (ctrl->server_local); ctrl->server_local = NULL; } + + +gpg_error_t +pinentry_loopback(ctrl_t ctrl, const char *keyword, + unsigned char **buffer, size_t *size, + size_t max_length) +{ + gpg_error_t rc; + assuan_context_t ctx = ctrl->server_local->assuan_ctx; + + assuan_begin_confidential (ctx); + rc = assuan_inquire (ctx, keyword, buffer, size, max_length); + assuan_end_confidential (ctx); + return rc; +} diff --git a/agent/genkey.c b/agent/genkey.c index 09f1c72aa..85ba7023a 100644 --- a/agent/genkey.c +++ b/agent/genkey.c @@ -304,6 +304,23 @@ agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt, *r_passphrase = NULL; + if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK) + { + size_t size; + size_t len = 100; + unsigned char *buffer; + + err = pinentry_loopback(ctrl, "NEW_PASSPHRASE", &buffer, &size, len); + if (err) + xfree(buffer); + else + { + buffer[size] = 0; + *r_passphrase = buffer; + } + return err; + } + pi = gcry_calloc_secure (2, sizeof (*pi) + 100); pi2 = pi + (sizeof *pi + 100); pi->max_length = 100;