gnucash maint: Use libsecret if available

Geert Janssens gjanssens at code.gnucash.org
Thu Apr 24 17:50:09 EDT 2014


Updated	 via  https://github.com/Gnucash/gnucash/commit/54095654 (commit)
	from  https://github.com/Gnucash/gnucash/commit/171ac3de (commit)



commit 540956546e19aee42f95993d4ef2c3f67b90cf35
Author: Moritz Lipp <mlq at pwmt.org>
Date:   Wed Apr 16 10:49:13 2014 +0200

    Use libsecret if available
    
    This patch provides libsecret [1] support to gnucash since gnome-keyring has
    been deprecated. It will check for an installed libsecret version and will use
    it in favor of gnome-keyring.
    
    Since it is not recommended to use SECRET_SCHEMA_COMPAT_NETWORK for new uses, it
    uses its own defined scheme to store the credentials. Therefore passwords that
    have been stored in the network schema are migrated to the new schema by trying
    to access them with the old schema and storing them again in the new one.

diff --git a/configure.ac b/configure.ac
index 7cc3ef7..55000e3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1106,6 +1106,13 @@ then
       PKG_CHECK_MODULES(GNOME_KEYRING, gnome-keyring-1 >= "0.6",
           [AC_DEFINE(HAVE_GNOME_KEYRING,1,[System has gnome-keyring 0.6 or better])],
           [AC_DEFINE(HAVE_NO_KEYRING,1,[System has no suitable keyring service])])
+
+      PKG_CHECK_MODULES(LIBSECRET, libsecret-1 >= "0.18",
+          [AC_DEFINE(HAVE_LIBSECRET,1,[System has libsecret 0.18 or better])],
+          [AC_DEFINE(HAVE_NO_LIBSECRET,1,[System has no suitable libsecret service])])
+      AC_SUBST(LIBSECRET_CFLAGS)
+      AC_SUBST(LIBSECRET_LIBS)
+      ;;
   esac
 
   ### ----------------------------------------------------------------------
diff --git a/src/gnome-utils/Makefile.am b/src/gnome-utils/Makefile.am
index b973a6b..739ff25 100644
--- a/src/gnome-utils/Makefile.am
+++ b/src/gnome-utils/Makefile.am
@@ -17,6 +17,7 @@ AM_CPPFLAGS = \
   ${GLIB_CFLAGS} \
   ${GTK_CFLAGS} \
   ${GNOME_KEYRING_CFLAGS} \
+  ${LIBSECRET_CFLAGS} \
   ${GUILE_CFLAGS} \
   ${QOF_CFLAGS} \
   ${LIBGDA_CFLAGS} \
@@ -204,6 +205,7 @@ libgncmod_gnome_utils_la_LIBADD = \
   ${top_builddir}/src/libqof/qof/libgnc-qof.la \
   ${GTK_LIBS} \
   ${GNOME_KEYRING_LIBS} \
+  ${LIBSECRET_LIBS} \
   ${GUILE_LIBS} \
   ${GLIB_LIBS} \
   ${DB_LIBS} \
diff --git a/src/gnome-utils/gnc-keyring.c b/src/gnome-utils/gnc-keyring.c
index 75a4d27..9a1e16f 100644
--- a/src/gnome-utils/gnc-keyring.c
+++ b/src/gnome-utils/gnc-keyring.c
@@ -26,7 +26,12 @@
 #include "qof.h"
 #include "gnc-ui.h"
 #include "gnc-keyring.h"
-#ifdef HAVE_GNOME_KEYRING
+#ifdef HAVE_LIBSECRET
+#include <libsecret/secret.h>
+#endif
+#if HAVE_GNOME_KEYRING
+#define GNOME_KEYRING_DEPRECATED
+#define GNOME_KEYRING_DEPRECATED_FOR(x)
 #include <gnome-keyring.h>
 #endif
 #ifdef HAVE_OSX_KEYCHAIN
@@ -38,6 +43,27 @@
 /* This static indicates the debugging module that this .o belongs to. */
 G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_GUI;
 
+#ifdef HAVE_LIBSECRET
+const SecretSchema* gnucash_get_secret_schema(void) G_GNUC_CONST;
+const SecretSchema* gnucash_get_secret_schema(void)
+{
+  static const SecretSchema secret_schema = {
+    "org.gnucash.password", SECRET_SCHEMA_NONE,
+    {
+      { "protocol", SECRET_SCHEMA_ATTRIBUTE_STRING },
+      { "server", SECRET_SCHEMA_ATTRIBUTE_STRING },
+      { "port", SECRET_SCHEMA_ATTRIBUTE_INTEGER },
+      { "user", SECRET_SCHEMA_ATTRIBUTE_STRING },
+      { "NULL", 0 },
+    }
+  };
+
+  return &secret_schema;
+}
+
+#define SECRET_SCHEMA_GNUCASH gnucash_get_secret_schema()
+#endif
+
 void gnc_keyring_set_password (const gchar *access_method,
                                const gchar *server,
                                guint32 port,
@@ -45,8 +71,29 @@ void gnc_keyring_set_password (const gchar *access_method,
                                const gchar *user,
                                const gchar* password)
 {
+#ifdef HAVE_LIBSECRET
+  GError* error = NULL;
+  gchar* label = NULL;
+
+  label = g_strdup_printf("GnuCash password for %s://%s@%s", access_method, user, server);
 
-#ifdef HAVE_GNOME_KEYRING
+  secret_password_store_sync (SECRET_SCHEMA_GNUCASH, SECRET_COLLECTION_DEFAULT,
+                            label, password, NULL, &error,
+                            "protocol", access_method,
+                            "server", server,
+                            "port", port,
+                            "user", user,
+                            NULL);
+
+  g_free(label);
+
+  if (error != NULL)
+  {
+      PWARN ("libsecret error: %s", error->message);
+      PWARN ("The user will be prompted for a password again next time.");
+      g_error_free(error);
+  }
+#elif HAVE_GNOME_KEYRING
     GnomeKeyringResult  gkr_result;
     guint32 item_id = 0;
 
@@ -105,7 +152,11 @@ gboolean gnc_keyring_get_password ( GtkWidget *parent,
                                     gchar **password)
 {
     gboolean password_found = FALSE;
-#ifdef HAVE_GNOME_KEYRING
+#ifdef HAVE_LIBSECRET
+    GError* error = NULL;
+    char* libsecret_password;
+#endif
+#if HAVE_GNOME_KEYRING
     GnomeKeyringResult  gkr_result;
     GList *found_list = NULL;
     GnomeKeyringNetworkPasswordData *found;
@@ -121,25 +172,57 @@ gboolean gnc_keyring_get_password ( GtkWidget *parent,
 
     *password = NULL;
 
-#ifdef HAVE_GNOME_KEYRING
-    gkr_result = gnome_keyring_find_network_password_sync
-                 ( *user, NULL, server, service,
-                   access_method, NULL, port, &found_list );
+#ifdef HAVE_LIBSECRET
+    libsecret_password = secret_password_lookup_sync (SECRET_SCHEMA_GNUCASH, NULL, &error,
+        "protocol", access_method,
+        "server", server,
+        "port", port,
+        "user", *user,
+        NULL);
 
-    if (gkr_result == GNOME_KEYRING_RESULT_OK)
-    {
-        found = (GnomeKeyringNetworkPasswordData *) found_list->data;
-        if (found->password)
-            *password = g_strdup(found->password);
+    if (libsecret_password == NULL) {
+        if (error != NULL) {
+            PWARN ("libsecret access failed: %s.", error->message);
+            g_error_free(error);
+        }
+    } else {
         password_found = TRUE;
+        *password = g_strdup (libsecret_password);
+        secret_password_free (libsecret_password);
     }
-    else
-        PWARN ("Gnome-keyring access failed: %s.",
-               gnome_keyring_result_to_message(gkr_result));
+#endif /* HAVE_LIBSECRET */
+
+#if HAVE_GNOME_KEYRING
+    if (password_found == FALSE) {
+        gkr_result = gnome_keyring_find_network_password_sync
+                     ( *user, NULL, server, service,
+                       access_method, NULL, port, &found_list );
 
-    gnome_keyring_network_password_list_free(found_list);
+        if (gkr_result == GNOME_KEYRING_RESULT_OK)
+        {
+            found = (GnomeKeyringNetworkPasswordData *) found_list->data;
+            if (found->password)
+                *password = g_strdup(found->password);
+            password_found = TRUE;
+        }
+        else
+            PWARN ("Gnome-keyring access failed: %s.",
+                   gnome_keyring_result_to_message(gkr_result));
+
+        gnome_keyring_network_password_list_free(found_list);
+    }
 #endif /* HAVE_GNOME_KEYRING */
 
+#if defined(HAVE_LIBSECRET) && defined(HAVE_GNOME_KEYRING)
+    /* If we were not able to retrieve the password with libsecret and the new
+     * schema and libgnome-keyring was successful to retrieve the password using
+     * the old schema, we immediatly store it in the new schema.
+     */
+    if (libsecret_password == NULL && password_found == TRUE) {
+        gnc_keyring_set_password(access_method, server, port, service, *user, *password);
+    }
+#endif /* HAVE_LIBSECRET && HAVE_GNOME_KEYRING */
+
 #ifdef HAVE_OSX_KEYCHAIN
     /* mysql and postgres aren't valid protocols on Mac OS X.
      * So we use the security domain parameter to allow us to



Summary of changes:
 configure.ac                  |   7 +++
 src/gnome-utils/Makefile.am   |   2 +
 src/gnome-utils/gnc-keyring.c | 115 ++++++++++++++++++++++++++++++++++++------
 3 files changed, 108 insertions(+), 16 deletions(-)



More information about the gnucash-changes mailing list