Handle pinentry-mode=loopback.
authorBen Kibbey <bjk@luxsci.net>
Sun, 11 Sep 2011 20:55:34 +0000 (16:55 -0400)
committerWerner Koch <wk@gnupg.org>
Mon, 12 Sep 2011 07:54:16 +0000 (09:54 +0200)
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
agent/agent.h
agent/call-pinentry.c
agent/command.c
agent/genkey.c

index ec2dca2..18a9491 100644 (file)
@@ -1,3 +1,12 @@
+2011-09-10  Ben Kibbey <bjk@luxsci.net>
+
+       * 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  <wk@g10code.com>
 
        * genkey.c (check_passphrase_pattern): Use gpg_strerror instead of
index fbd71d5..b323718 100644 (file)
@@ -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);
index 4c30f6d..d0cfd2b 100644 (file)
@@ -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);
     }
 
index 6973e78..f310a98 100644 (file)
@@ -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;
+}
index 09f1c72..85ba702 100644 (file)
@@ -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;