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.
pull/7/merge
Moritz Lipp 12 years ago committed by Geert Janssens
parent 171ac3de90
commit 540956546e

@ -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
### ----------------------------------------------------------------------

@ -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} \

@ -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

Loading…
Cancel
Save