Add support for saving the passphrase with libsecret.
authorNeal H. Walfield <neal@gnu.org>
Thu, 7 May 2015 12:43:48 +0000 (14:43 +0200)
committerNeal H. Walfield <neal@gnu.org>
Thu, 7 May 2015 12:43:48 +0000 (14:43 +0200)
* configure.ac (COMMON_CFLAGS): New variable.  AC_SUBST it.
(COMMON_LIBS): Likewise.  AC_SUBST it.
(LIBSECRET_CFLAGS): Likewise.
(LIBSECRET_LIBS): Likewise.
(--enable-libsecret): Add option to enable support for libsecret.  If
enabled, check for its presense.
* pinentry/password-cache.h: New field.
* pinentry/password-cache.c: New field.
* pinentry/pinentry.h (struct pinentry): Add fields pin_from_cache,
allow_external_password_cache, tried_password_cache, keyinfo, and
may_cache_password.
* pinentry/pinentry.c: Include "password-cache.h".
(pinentry): Initialize new fields.
(option_handler): Handle the "allow-external-password-cache" option.
(cmd_setkeyinfo): Implement it.
(cmd_getpin): Read the password from the cache, if appropriate.  Save
it to the cache, if appropriate.
* pinentry/Makefile.am (AM_CPPFLAGS): Add $(COMMON_CFLAGS).
(LDADD): Add $(COMMON_LIBS).
(libpinentry_a_SOURCES): Add password-cache.h
password-cache.c.
* gtk+-2/pinentry-gtk-2.c (may_save_passphrase_toggled): New function.
(create_window): Take additional parameter, the pinentry's context.
Update callers.
[HAVE_LIBSECRET]: Show a checkbox asking whether the passphrase should
be saved.
* gtk+-2/Makefile.am (AM_CPPFLAGS): Add $(COMMON_CFLAGS).
(LDADD): Add $(COMMON_LIBS).
* curses/Makefile.am (AM_CPPFLAGS): Add $(COMMON_CFLAGS).
(LDADD): Add $(COMMON_LIBS).
* tty/Makefile.am (AM_CPPFLAGS): Add $(COMMON_CFLAGS).
(LDADD): Add $(COMMON_LIBS).
* doc/pinentry.texi (Protocol): Update documentation.  Describe the
protocol and provide some justification.

13 files changed:
configure.ac
curses/Makefile.am
doc/pinentry.texi
gtk+-2/Makefile.am
gtk+-2/pinentry-gtk-2.c
pinentry/Makefile.am
pinentry/password-cache.c [new file with mode: 0644]
pinentry/password-cache.h [new file with mode: 0644]
pinentry/pinentry.c
pinentry/pinentry.h
qt4/Makefile.am
tty/Makefile.am
tty/pinentry-tty.c

index 271234f..ec7bbfd 100644 (file)
@@ -1,6 +1,6 @@
 # configure.ac
 # Copyright (C) 1999 Robert Bihlmeyer <robbe@orcus.priv.at>
-# Copyright (C) 2001, 2002, 2003, 2004, 2007 g10 Code GmbH
+# Copyright (C) 2001, 2002, 2003, 2004, 2007, 2015 g10 Code GmbH
 #
 # This file is part of PINENTRY.
 #
@@ -167,6 +167,12 @@ dnl Checks for library functions.
 AC_CHECK_FUNCS(seteuid stpcpy mmap)
 GNUPG_CHECK_MLOCK
 
+# Common libraries and cflags.
+COMMON_CFLAGS=
+COMMON_LIBS=
+AC_SUBST(COMMON_CFLAGS)
+AC_SUBST(COMMON_LIBS)
+
 dnl Checks for libassuan.
 dnl -> None required because we use a stripped down version of libassuan.
 
@@ -310,6 +316,45 @@ if test "$pinentry_gtk_2" != "no"; then
 fi
 AM_CONDITIONAL(BUILD_PINENTRY_GTK_2, test "$pinentry_gtk_2" = "yes")
 
+dnl
+dnl Check for libsecret.
+dnl
+AC_ARG_ENABLE(libsecret,
+            AC_HELP_STRING([--enable-libsecret],
+           [optionally cache passphrases using libsecret]),
+            libsecret=$enableval, libsecret=maybe)
+
+dnl check for pkg-config
+if test "$libsecret" != "no"; then
+        AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
+       if test x"${PKG_CONFIG}" = xno ; then
+               libsecret=no
+       fi
+fi
+
+dnl check if the module libsecret exists
+if test "$libsecret" != "no"; then
+       AC_MSG_CHECKING([for libsecret])
+       "${PKG_CONFIG}" --exists 'libsecret-1'
+       if test $? -ne 0 ; then
+               AC_MSG_RESULT([no])
+               AC_MSG_WARN([pkg-config could not find the modules libsecret-1])
+               libsecret=no
+       else
+               AC_MSG_RESULT([yes])
+               LIBSECRET_CFLAGS=`"${PKG_CONFIG}" --cflags 'libsecret-1'`
+               LIBSECRET_LIBS=`"${PKG_CONFIG}" --libs 'libsecret-1'`
+               libsecret=yes
+       fi
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBSECRET, test "$libsecret" = "yes")
+if test "$libsecret" = "yes"; then
+  AC_DEFINE(HAVE_LIBSECRET, 1,
+    [The pinentries should optionally cache the passphrase using libsecret.])
+
+  COMMON_CFLAGS="$COMMON_CFLAGS $LIBSECRET_CFLAGS"
+  COMMON_LIBS="$COMMON_LIBS $LIBSECRET_LIBS"
+fi
 
 dnl
 dnl Check for Qt4 pinentry program.
@@ -453,5 +498,7 @@ AC_MSG_NOTICE([
 
        Fallback to Curses: $fallback_curses
 
+       libsecret ........: $libsecret
+
        Default Pinentry .: $PINENTRY_DEFAULT
 ])
index 404a8ed..e8ea031 100644 (file)
@@ -1,5 +1,5 @@
 # Makefile.am - PIN entry curses frontend.
-# Copyright (C) 2002 g10 Code GmbH
+# Copyright (C) 2002, 2015 g10 Code GmbH
 #
 # This file is part of PINENTRY.
 #
@@ -21,8 +21,9 @@
 
 bin_PROGRAMS = pinentry-curses
 
-AM_CPPFLAGS = $(NCURSES_INCLUDE) -I$(top_srcdir)/pinentry
-LDADD = ../pinentry/libpinentry.a ../pinentry/libpinentry-curses.a \
+AM_CPPFLAGS = $(COMMON_CFLAGS) $(NCURSES_INCLUDE) -I$(top_srcdir)/pinentry
+LDADD = $(COMMON_LIBS) \
+       ../pinentry/libpinentry.a ../pinentry/libpinentry-curses.a \
        ../assuan/libassuan.a ../secmem/libsecmem.a \
        $(LIBCAP) $(LIBCURSES) $(LIBICONV)
 
index fb4017e..c2df479 100644 (file)
@@ -414,6 +414,51 @@ strings.
 The strings are subject to accelerator marking, see SETPROMPT for
 details.
 
+@item Passphrase caching
+
+Some environments, such as GNOME, cache passwords and passphrases.
+The @pinentry{} should only use an external cache if the
+@code{allow-external-password-cache} option was set and a stable key
+identifier (using SETKEYINFO) was provided.  In this case, if the
+passphrase was read from the cache, the @pinentry{} should send the
+@code{PASSWORD_FROM_CACHE} status message before returning the
+passphrase.  This indicates to GPG Agent that it should not increment
+the passphrase retry counter.
+
+@example
+  C: OPTION allow-external-password-cache
+  S: OK
+  C: SETKEYINFO key-grip
+  S: OK
+  C: getpin
+  S: S PASSWORD_FROM_CACHE
+  S: D 1234
+  C: OK
+@end example
+
+Note: if @code{allow-external-password-cache} is not specified, an
+external password cache must not be used: this can lead to subtle
+bugs.  In particular, if this option is not specified, then GPG Agent
+does not recognize the @code{PASSWORD_FROM_CACHE} status message and
+will count trying a cached password against the password retry count.
+If the password retry count is 1, then the user will never have the
+opportunity to correct the cached password.
+
+Note: it is strongly recommended that a pinentry supporting this
+feature provide the user an option to enable it manually.  That is,
+saving a passphrase in an external password manager should be opt-in.
+
+The key identifier provided by SETKEYINFO is the key grip, which is
+not the OpenPGP Key ID.  To map the key grip to a key, you can use the
+following:
+
+@example
+  # gpg2 --with-keygrip --list-secret-keys
+@end example
+
+@noindent
+and search for the key grip.
+
 @end table
 
 @c ---------------------------------------------------------------------
index 94346c0..c98139f 100644 (file)
@@ -1,5 +1,5 @@
 # Makefile.am - PIN entry GTK+ frontend.
-# Copyright (C) 2002 g10 Code GmbH
+# Copyright (C) 2002, 2015 g10 Code GmbH
 #
 # This file is part of PINENTRY.
 #
@@ -29,9 +29,10 @@ ncurses_include =
 libcurses =
 endif
 
-AM_CPPFLAGS = $(GTK2CFLAGS) $(ncurses_include) \
+AM_CPPFLAGS = $(COMMON_CFLAGS) $(GTK2CFLAGS) $(ncurses_include) \
        -I$(top_srcdir)/secmem -I$(top_srcdir)/pinentry
-LDADD = ../pinentry/libpinentry.a ../assuan/libassuan.a ../secmem/libsecmem.a \
+LDADD = $(COMMON_LIBS) \
+       ../pinentry/libpinentry.a ../assuan/libassuan.a ../secmem/libsecmem.a \
        $(LIBCAP) $(GTK2LIBS) $(libcurses)
 
 pinentry_gtk_2_SOURCES = pinentry-gtk-2.c \
index b3698c0..b154831 100644 (file)
@@ -1,6 +1,6 @@
 /* pinentry-gtk-2.c
    Copyright (C) 1999 Robert Bihlmeyer <robbe@orcus.priv.at>
-   Copyright (C) 2001, 2002, 2007 g10 Code GmbH
+   Copyright (C) 2001, 2002, 2007, 2015 g10 Code GmbH
    Copyright (C) 2004 by Albrecht Dreß <albrecht.dress@arcor.de>
 
    pinentry-gtk-2 is a pinentry application for the Gtk+-2 widget set.
@@ -328,6 +328,18 @@ changed_text_handler (GtkWidget *widget)
 }
 
 
+#ifdef HAVE_LIBSECRET
+static void
+may_save_passphrase_toggled (GtkWidget *widget, gpointer data)
+{
+  GtkToggleButton *button = GTK_TOGGLE_BUTTON (widget);
+  pinentry_t ctx = (pinentry_t) data;
+
+  ctx->may_cache_password = gtk_toggle_button_get_active (button);
+}
+#endif
+
+
 static gboolean
 timeout_cb (gpointer data)
 {
@@ -339,7 +351,7 @@ timeout_cb (gpointer data)
 
 
 static GtkWidget *
-create_window (int confirm_mode)
+create_window (pinentry_t ctx, int confirm_mode)
 {
   GtkWidget *w;
   GtkWidget *win, *box;
@@ -552,6 +564,21 @@ create_window (int confirm_mode)
   gtk_box_set_spacing (GTK_BOX (bbox), 6);
   gtk_box_pack_start (GTK_BOX (wvbox), bbox, TRUE, FALSE, 0);
 
+#ifdef HAVE_LIBSECRET
+  if (ctx->allow_external_password_cache && ctx->keyinfo)
+    /* Only show this if we can cache passwords and we have a stable
+       key identifier.  */
+    {
+      w = gtk_check_button_new_with_label ("Save passphrase using libsecret");
+      gtk_box_pack_start (GTK_BOX (box), w, TRUE, FALSE, 0);
+      gtk_widget_show (w);
+
+      g_signal_connect (G_OBJECT (w), "toggled",
+                        G_CALLBACK (may_save_passphrase_toggled),
+                       (gpointer) ctx);
+    }
+#endif
+
   if (!pinentry->one_button)
     {
       if (pinentry->cancel)
@@ -661,7 +688,7 @@ gtk_cmd_handler (pinentry_t pe)
   pinentry = pe;
   confirm_value = CONFIRM_CANCEL;
   passphrase_ok = 0;
-  w = create_window (want_pass ? 0 : 1);
+  w = create_window (pe, want_pass ? 0 : 1);
   gtk_main ();
   gtk_widget_destroy (w);
   while (gtk_events_pending ())
index c3926b2..7fbbab6 100644 (file)
@@ -1,5 +1,5 @@
 # Pinentry support library Makefile
-# Copyright (C) 2002 g10 Code GmbH
+# Copyright (C) 2002, 2015 g10 Code GmbH
 #
 # This file is part of PINENTRY.
 #
@@ -29,7 +29,9 @@ endif
 
 noinst_LIBRARIES = libpinentry.a $(pinentry_curses)
 
-AM_CPPFLAGS = -I$(top_srcdir)/assuan -I$(top_srcdir)/secmem
+LDADD = $(COMMON_LIBS)
+AM_CPPFLAGS = $(COMMON_CFLAGS) -I$(top_srcdir)/assuan -I$(top_srcdir)/secmem
 
-libpinentry_a_SOURCES = pinentry.h pinentry.c argparse.c argparse.h
+libpinentry_a_SOURCES = pinentry.h pinentry.c argparse.c argparse.h \
+       password-cache.h password-cache.c
 libpinentry_curses_a_SOURCES = pinentry-curses.h pinentry-curses.c
diff --git a/pinentry/password-cache.c b/pinentry/password-cache.c
new file mode 100644 (file)
index 0000000..53bb39f
--- /dev/null
@@ -0,0 +1,131 @@
+/* password-cache.c - Password cache support.
+   Copyright (C) 2015 g10 Code GmbH
+
+   This file is part of PINENTRY.
+
+   PINENTRY is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   PINENTRY is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef HAVE_LIBSECRET
+# include <libsecret/secret.h>
+#endif
+
+#include "password-cache.h"
+#include "memory.h"
+
+#ifdef HAVE_LIBSECRET
+static const SecretSchema *
+gpg_schema (void)
+{
+    static const SecretSchema the_schema = {
+        "org.gnupg.Passphrase", SECRET_SCHEMA_NONE,
+        {
+         { "stored-by", SECRET_SCHEMA_ATTRIBUTE_STRING },
+         { "key-grip", SECRET_SCHEMA_ATTRIBUTE_STRING },
+         { "NULL", 0 },
+       }
+    };
+    return &the_schema;
+}
+
+static char *
+key_grip_to_label (const char *key_grip)
+{
+  char *label = NULL;
+  if (asprintf(&label, "GnuPG: %s", key_grip) < 0)
+    return NULL;
+  return label;
+}
+#endif
+
+void
+password_cache_save (const char *key_grip, const char *password)
+{
+#ifdef HAVE_LIBSECRET
+  char *label;
+  GError *error = NULL;
+
+  if (! *key_grip)
+    return;
+
+  label = key_grip_to_label (key_grip);
+  if (! label)
+    return;
+
+  if (! secret_password_store_sync (gpg_schema (),
+                                   SECRET_COLLECTION_DEFAULT,
+                                   label, password, NULL, &error,
+                                   "stored-by", "GnuPG Pinentry",
+                                   "key-grip", key_grip, NULL))
+    {
+      printf("Failed to cache password for key %s with secret service: %s\n",
+            key_grip, error->message);
+
+      g_error_free (error);
+    }
+
+  free (label);
+#else
+  return;
+#endif
+}
+
+char *
+password_cache_lookup (const char *key_grip)
+{
+#ifdef HAVE_LIBSECRET
+  GError *error = NULL;
+  char *password;
+  char *password2;
+
+  if (! *key_grip)
+    return NULL;
+
+  password = secret_password_lookup_nonpageable_sync
+    (gpg_schema (), NULL, &error,
+     "key-grip", key_grip, NULL);
+
+  if (error != NULL)
+    {
+      printf("Failed to lookup password for key %s with secret service: %s\n",
+            key_grip, error->message);
+      g_error_free (error);
+      return NULL;
+    }
+  if (! password)
+    /* The password for this key is not cached.  Just return NULL.  */
+    return NULL;
+
+  /* The password needs to be returned in secmem allocated memory.  */
+  password2 = secmem_malloc (strlen (password) + 1);
+  if (password2)
+    strcpy(password2, password);
+  else
+    printf("secmem_malloc failed: can't copy password!\n");
+
+  secret_password_free (password);
+
+  return password2;
+#else
+  return NULL;
+#endif
+}
diff --git a/pinentry/password-cache.h b/pinentry/password-cache.h
new file mode 100644 (file)
index 0000000..7c6cd5a
--- /dev/null
@@ -0,0 +1,27 @@
+/* password-cache.h - Password cache support interfaces.
+   Copyright (C) 2015 g10 Code GmbH
+
+   This file is part of PINENTRY.
+
+   PINENTRY is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   PINENTRY is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef PASSWORD_CACHE_H
+#define PASSWORD_CACHE_H
+
+void password_cache_save (const char *key_grip, const char *password);
+
+char *password_cache_lookup (const char *key_grip);
+
+#endif
index 04de1aa..7b3fde5 100644 (file)
@@ -47,6 +47,7 @@
 #include "secmem-util.h"
 #include "argparse.h"
 #include "pinentry.h"
+#include "password-cache.h"
 
 #ifdef HAVE_W32CE_SYSTEM
 #define getpid() GetCurrentProcessId ()
@@ -67,6 +68,7 @@ struct pinentry pinentry =
     NULL,      /* Cancel button.  */
     NULL,      /* PIN.  */
     2048,      /* PIN length.  */
+    0,          /* pin_from_cache.  */
     0,         /* Display.  */
     0,         /* TTY name.  */
     0,         /* TTY type.  */
@@ -98,6 +100,10 @@ struct pinentry pinentry =
     NULL,        /* default_ok  */
     NULL,        /* default_cancel  */
     NULL,        /* default_prompt  */
+    0,           /* allow_external_password_cache.  */
+    0,           /* tried_password_cached.  */
+    NULL,        /* keyinfo  */
+    0,           /* may_cache_password. */
     NULL         /* Assuan context.  */
   };
 
@@ -711,6 +717,11 @@ option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value)
       if (!pinentry.default_prompt)
        return ASSUAN_Out_Of_Core;
     }
+  else if (!strcmp (key, "allow-external-password-cache") && !*value)
+    {
+      pinentry.allow_external_password_cache = 1;
+      pinentry.tried_password_cache = 0;
+    }
   else
     return ASSUAN_Invalid_Option;
   return 0;
@@ -772,13 +783,20 @@ cmd_setprompt (ASSUAN_CONTEXT ctx, char *line)
 
 
 /* The data provided at LINE may be used by pinentry implementations
-   to identify a key for caching strategies of its own.  As of now
-   this is here only for documentation purposes.  */
+   to identify a key for caching strategies of its own.  The empty
+   string and --clear mean that the key does not have a stable
+   identifier.  */
 static int
 cmd_setkeyinfo (ASSUAN_CONTEXT ctx, char *line)
 {
-  (void)ctx;
-  (void)line;
+  if (pinentry.keyinfo)
+    free (pinentry.keyinfo);
+
+  if (*line && strcmp(line, "--clear") != 0)
+    pinentry.keyinfo = strdup (line);
+  else
+    pinentry.keyinfo = NULL;
+
   return 0;
 }
 
@@ -955,10 +973,57 @@ cmd_getpin (ASSUAN_CONTEXT ctx, char *line)
 {
   int result;
   int set_prompt = 0;
+  int just_read_password_from_cache = 0;
 
   pinentry.pin = secmem_malloc (pinentry.pin_len);
   if (!pinentry.pin)
     return ASSUAN_Out_Of_Core;
+
+  /* Try reading from the password cache.  */
+  if (/* If repeat passphrase is set, then we don't want to read from
+        the cache.  */
+      ! pinentry.repeat_passphrase
+      /* Are we allowed to read from the cache?  */
+      && pinentry.allow_external_password_cache
+      && pinentry.keyinfo
+      /* Only read from the cache if we haven't already tried it.  */
+      && ! pinentry.tried_password_cache)
+    {
+      char *password;
+
+      pinentry.tried_password_cache = 1;
+
+      password = password_cache_lookup (pinentry.keyinfo);
+      if (password)
+       /* There is a cached password.  Try it.  */
+       {
+         int len = strlen(password) + 1;
+         if (len > pinentry.pin_len)
+           len = pinentry.pin_len;
+
+         memcpy (pinentry.pin, password, len);
+         pinentry.pin[len] = '\0';
+
+         secmem_free (password);
+
+         pinentry.pin_from_cache = 1;
+
+         assuan_write_status (ctx, "PASSWORD_FROM_CACHE", "");
+
+         /* Result is the length of the password not including the
+            NUL terminator.  */
+         result = len - 1;
+
+         just_read_password_from_cache = 1;
+
+         goto out;
+       }
+    }
+
+  /* The password was not cached (or we are not allowed to / cannot
+     use the cache).  Prompt the user.  */
+  pinentry.pin_from_cache = 0;
+
   if (!pinentry.prompt)
     {
       pinentry.prompt = pinentry.default_prompt?pinentry.default_prompt:"PIN:";
@@ -999,6 +1064,7 @@ cmd_getpin (ASSUAN_CONTEXT ctx, char *line)
       return pinentry.locale_err? ASSUAN_Locale_Problem: ASSUAN_Canceled;
     }
 
+ out:
   if (result)
     {
       if (pinentry.repeat_okay)
@@ -1006,6 +1072,15 @@ cmd_getpin (ASSUAN_CONTEXT ctx, char *line)
       result = assuan_send_data (ctx, pinentry.pin, result);
       if (!result)
        result = assuan_send_data (ctx, NULL, 0);
+
+      if (/* GPG Agent says it's okay.  */
+         pinentry.allow_external_password_cache && pinentry.keyinfo
+         /* We didn't just read it from the cache.  */
+         && ! just_read_password_from_cache
+         /* And the user said it's okay.  */
+         && pinentry.may_cache_password)
+       /* Cache the password.  */
+       password_cache_save (pinentry.keyinfo, pinentry.pin);
     }
 
   if (pinentry.pin)
index 6787130..02f76a3 100644 (file)
@@ -1,5 +1,5 @@
 /* pinentry.h - The interface for the PIN entry support library.
-   Copyright (C) 2002, 2003, 2010 g10 Code GmbH
+   Copyright (C) 2002, 2003, 2010, 2015 g10 Code GmbH
 
    This file is part of PINENTRY.
 
@@ -57,6 +57,9 @@ struct pinentry
   char *pin;
   /* The length of the buffer.  */
   int pin_len;
+  /* Whether the pin was read from an external cache (1) or entered by
+     the user (0). */
+  int pin_from_cache;
 
   /* The name of the X display to use if X is available and supported.  */
   char *display;
@@ -111,7 +114,7 @@ struct pinentry
      dismiss button is required. */
   int one_button;
 
-  /* If true a second prompt for the passphrase is show and the user
+  /* If true a second prompt for the passphrase is shown and the user
      is expected to enter the same passphrase again.  Pinentry checks
      that both match.  */
   char *repeat_passphrase;
@@ -146,6 +149,22 @@ struct pinentry
   char *default_cancel;
   char *default_prompt;
 
+  /* Whether we are allowed to read the password from an external
+     cache.  */
+  int allow_external_password_cache;
+
+  /* We only try the cache once.  */
+  int tried_password_cache;
+
+  /* A stable identifier for the key.  */
+  char *keyinfo;
+
+  /* Whether we may cache the password (according to the user).  */
+  int may_cache_password;
+
+  /* NOTE: If you add any additional fields to this structure, be sure
+     to update the initializer in pinentry/pinentry.c!!!  */
+
   /* For the quality indicator we need to do an inquiry.  Thus we need
      to save the assuan ctx.  */
   void *ctx_assuan;
@@ -158,7 +177,8 @@ typedef struct pinentry *pinentry_t;
    PIN.  If PIN->pin is zero, request a confirmation, otherwise a PIN
    entry.  On confirmation, the function should return TRUE if
    confirmed, and FALSE otherwise.  On PIN entry, the function should
-   return -1 if cancelled and the length of the secret otherwise.  */
+   return -1 if an error occured or the user cancelled the operation
+   and the length of the secret otherwise.  */
 typedef int (*pinentry_cmd_handler_t) (pinentry_t pin);
 
 /* Start the pinentry event loop.  The program will start to process
index e52169c..31274bb 100644 (file)
@@ -1,6 +1,6 @@
 # Makefile.am
 # Copyright (C) 2002 g10 Code GmbH, Klarälvdalens Datakonsult AB
-# Copyright (C) 2008 g10 Code GmbH
+# Copyright (C) 2008, 2015 g10 Code GmbH
 #
 # This file is part of PINENTRY.
 #
@@ -34,10 +34,12 @@ libcurses =
 endif
 
 
-AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/assuan -I$(top_srcdir)/secmem \
+AM_CPPFLAGS = $(COMMON_CFLAGS) \
+       -I$(top_srcdir) -I$(top_srcdir)/assuan -I$(top_srcdir)/secmem \
        $(ncurses_include) -I$(top_srcdir)/pinentry
 AM_CXXFLAGS = $(QT4_CORE_CFLAGS) $(QT4_GUI_CFLAGS)
-pinentry_qt4_LDADD = $(QT4_CORE_LIBS) $(QT4_GUI_LIBS) $(libcurses) \
+pinentry_qt4_LDADD = $(COMMON_LIBS) \
+       $(QT4_CORE_LIBS) $(QT4_GUI_LIBS) $(libcurses) \
        ../pinentry/libpinentry.a $(top_builddir)/assuan/libassuan.a \
        $(top_builddir)/secmem/libsecmem.a $(LIBCAP)
 
index d872fcc..798c08f 100644 (file)
@@ -1,5 +1,5 @@
 # Makefile.am - PIN entry curses frontend.
-# Copyright (C) 2002 g10 Code GmbH
+# Copyright (C) 2002, 2015 g10 Code GmbH
 #
 # This file is part of PINENTRY.
 #
@@ -20,8 +20,8 @@
 
 bin_PROGRAMS = pinentry-tty
 
-AM_CPPFLAGS = -I$(top_srcdir)/pinentry
-LDADD = ../pinentry/libpinentry.a \
+AM_CPPFLAGS = $(COMMON_CFLAGS) -I$(top_srcdir)/pinentry
+LDADD = $(COMMON_LIBS) ../pinentry/libpinentry.a \
        ../assuan/libassuan.a ../secmem/libsecmem.a \
        $(LIBCAP) $(LIBICONV)
 
index 5891697..8c15eac 100644 (file)
@@ -1,7 +1,7 @@
 /* pinentry-curses.c - A secure curses dialog for PIN entry, library version
    Copyright (C) 2014 Serge Voilokov
    Copyright (C) 2015 Daniel Kahn Gillmor <dkg@fifthhorseman.net>
* Copyright (C) 2015 g10 Code GmbH
  Copyright (C) 2015 g10 Code GmbH
 
    This file is part of PINENTRY.