mirror of
https://github.com/Gnucash/gnucash.git
synced 2024-11-25 10:20:18 -06:00
Bug 746873 - Gnucash asks sql passwords before wallet password
If libsecret is available use it to search for both libsecret based passwords as gnome-keyring based ones. This catches the situation where a password was stored earlier using gnome-keyring, while the user is now trying to retrieve it on a system that only has libsecret available. This used to fail because gnucash depended on gnome-keyring to be present in that situation.
This commit is contained in:
parent
61021c4620
commit
f604348d9b
@ -28,8 +28,7 @@
|
|||||||
#include "gnc-keyring.h"
|
#include "gnc-keyring.h"
|
||||||
#ifdef HAVE_LIBSECRET
|
#ifdef HAVE_LIBSECRET
|
||||||
#include <libsecret/secret.h>
|
#include <libsecret/secret.h>
|
||||||
#endif
|
#elif HAVE_GNOME_KEYRING
|
||||||
#if HAVE_GNOME_KEYRING
|
|
||||||
#define GNOME_KEYRING_DEPRECATED
|
#define GNOME_KEYRING_DEPRECATED
|
||||||
#define GNOME_KEYRING_DEPRECATED_FOR(x)
|
#define GNOME_KEYRING_DEPRECATED_FOR(x)
|
||||||
#include <gnome-keyring.h>
|
#include <gnome-keyring.h>
|
||||||
@ -77,13 +76,21 @@ void gnc_keyring_set_password (const gchar *access_method,
|
|||||||
|
|
||||||
label = g_strdup_printf("GnuCash password for %s://%s@%s", access_method, user, server);
|
label = g_strdup_printf("GnuCash password for %s://%s@%s", access_method, user, server);
|
||||||
|
|
||||||
secret_password_store_sync (SECRET_SCHEMA_GNUCASH, SECRET_COLLECTION_DEFAULT,
|
if (port == 0)
|
||||||
label, password, NULL, &error,
|
secret_password_store_sync (SECRET_SCHEMA_GNUCASH, SECRET_COLLECTION_DEFAULT,
|
||||||
"protocol", access_method,
|
label, password, NULL, &error,
|
||||||
"server", server,
|
"protocol", access_method,
|
||||||
"port", port,
|
"server", server,
|
||||||
"user", user,
|
"user", user,
|
||||||
NULL);
|
NULL);
|
||||||
|
else
|
||||||
|
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);
|
g_free(label);
|
||||||
|
|
||||||
@ -117,7 +124,7 @@ void gnc_keyring_set_password (const gchar *access_method,
|
|||||||
* distinguish between these two.
|
* distinguish between these two.
|
||||||
*/
|
*/
|
||||||
// FIXME I'm not sure this works if a password was already in the keychain
|
// FIXME I'm not sure this works if a password was already in the keychain
|
||||||
// I may have to do a lookup first and if it exists, run some update
|
// I may have to do a lookup first and if it exists, run some
|
||||||
// update function instead
|
// update function instead
|
||||||
status = SecKeychainAddInternetPassword ( NULL, /* keychain */
|
status = SecKeychainAddInternetPassword ( NULL, /* keychain */
|
||||||
strlen(server), server, /* servername */
|
strlen(server), server, /* servername */
|
||||||
@ -152,11 +159,11 @@ gboolean gnc_keyring_get_password ( GtkWidget *parent,
|
|||||||
gchar **password)
|
gchar **password)
|
||||||
{
|
{
|
||||||
gboolean password_found = FALSE;
|
gboolean password_found = FALSE;
|
||||||
|
gchar *db_path, *heading;
|
||||||
#ifdef HAVE_LIBSECRET
|
#ifdef HAVE_LIBSECRET
|
||||||
GError* error = NULL;
|
GError* error = NULL;
|
||||||
char* libsecret_password;
|
char* libsecret_password;
|
||||||
#endif
|
#elif HAVE_GNOME_KEYRING
|
||||||
#if HAVE_GNOME_KEYRING
|
|
||||||
GnomeKeyringResult gkr_result;
|
GnomeKeyringResult gkr_result;
|
||||||
GList *found_list = NULL;
|
GList *found_list = NULL;
|
||||||
GnomeKeyringNetworkPasswordData *found;
|
GnomeKeyringNetworkPasswordData *found;
|
||||||
@ -173,55 +180,101 @@ gboolean gnc_keyring_get_password ( GtkWidget *parent,
|
|||||||
*password = NULL;
|
*password = NULL;
|
||||||
|
|
||||||
#ifdef HAVE_LIBSECRET
|
#ifdef HAVE_LIBSECRET
|
||||||
|
/* Note: only use the port attribute if it was set by the user. */
|
||||||
|
if (port == 0)
|
||||||
|
libsecret_password = secret_password_lookup_sync (SECRET_SCHEMA_GNUCASH, NULL, &error,
|
||||||
|
"protocol", access_method,
|
||||||
|
"server", server,
|
||||||
|
"user", *user,
|
||||||
|
NULL);
|
||||||
|
else
|
||||||
|
libsecret_password = secret_password_lookup_sync (SECRET_SCHEMA_GNUCASH, NULL, &error,
|
||||||
|
"protocol", access_method,
|
||||||
|
"server", server,
|
||||||
|
"port", port,
|
||||||
|
"user", *user,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (libsecret_password != NULL) {
|
||||||
|
*password = g_strdup (libsecret_password);
|
||||||
|
secret_password_free (libsecret_password);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No password found yet. Perhaps it was written with a port equal to 0.
|
||||||
|
* Gnucash versions prior to 2.6.7 did this unfortunately... */
|
||||||
libsecret_password = secret_password_lookup_sync (SECRET_SCHEMA_GNUCASH, NULL, &error,
|
libsecret_password = secret_password_lookup_sync (SECRET_SCHEMA_GNUCASH, NULL, &error,
|
||||||
"protocol", access_method,
|
"protocol", access_method,
|
||||||
"server", server,
|
"server", server,
|
||||||
"port", port,
|
"port", 0,
|
||||||
"user", *user,
|
"user", *user,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
if (libsecret_password == NULL) {
|
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);
|
*password = g_strdup (libsecret_password);
|
||||||
secret_password_free (libsecret_password);
|
secret_password_free (libsecret_password);
|
||||||
}
|
|
||||||
#endif /* HAVE_LIBSECRET */
|
|
||||||
|
|
||||||
#if HAVE_GNOME_KEYRING
|
/* Ok, got an password with 0 port.
|
||||||
if (password_found == FALSE) {
|
Store a copy in a more recent gnucash style. */
|
||||||
gkr_result = gnome_keyring_find_network_password_sync
|
|
||||||
( *user, NULL, server, service,
|
|
||||||
access_method, NULL, port, &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);
|
gnc_keyring_set_password(access_method, server, port, service, *user, *password);
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
#endif /* HAVE_LIBSECRET && HAVE_GNOME_KEYRING */
|
|
||||||
|
/* No password was found while querying libsecret using the gnucash schema,
|
||||||
|
Look for a password stored via gnome-keyring instead */
|
||||||
|
if (port == 0)
|
||||||
|
libsecret_password = secret_password_lookup_sync (SECRET_SCHEMA_COMPAT_NETWORK, NULL, &error,
|
||||||
|
"protocol", access_method,
|
||||||
|
"server", server,
|
||||||
|
"object", service,
|
||||||
|
"user", *user,
|
||||||
|
NULL);
|
||||||
|
else
|
||||||
|
libsecret_password = secret_password_lookup_sync (SECRET_SCHEMA_COMPAT_NETWORK, NULL, &error,
|
||||||
|
"protocol", access_method,
|
||||||
|
"server", server,
|
||||||
|
"port", port,
|
||||||
|
"object", service,
|
||||||
|
"user", *user,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (libsecret_password != NULL) {
|
||||||
|
*password = g_strdup (libsecret_password);
|
||||||
|
secret_password_free (libsecret_password);
|
||||||
|
|
||||||
|
/* Ok, got an old gnome-keyring password.
|
||||||
|
* Store a copy of it in a libsecret compatible format. */
|
||||||
|
gnc_keyring_set_password(access_method, server, port, service, *user, *password);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Something went wrong while attempting to access libsecret
|
||||||
|
* Log the error message and carry on... */
|
||||||
|
if (error != NULL) {
|
||||||
|
PWARN ("libsecret access failed: %s.", error->message);
|
||||||
|
g_error_free(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif HAVE_GNOME_KEYRING
|
||||||
|
gkr_result = gnome_keyring_find_network_password_sync
|
||||||
|
( *user, NULL, server, service,
|
||||||
|
access_method, NULL, port, &found_list );
|
||||||
|
|
||||||
|
if (gkr_result == GNOME_KEYRING_RESULT_OK)
|
||||||
|
{
|
||||||
|
found = (GnomeKeyringNetworkPasswordData *) found_list->data;
|
||||||
|
if (found->password)
|
||||||
|
*password = g_strdup(found->password);
|
||||||
|
gnome_keyring_network_password_list_free(found_list);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Something went wrong while attempting to access libsecret
|
||||||
|
* Log the error message and carry on... */
|
||||||
|
PWARN ("Gnome-keyring access failed: %s.",
|
||||||
|
gnome_keyring_result_to_message(gkr_result));
|
||||||
|
gnome_keyring_network_password_list_free(found_list);
|
||||||
|
#endif /* HAVE_LIBSECRET or HAVE_GNOME_KEYRING */
|
||||||
|
|
||||||
#ifdef HAVE_OSX_KEYCHAIN
|
#ifdef HAVE_OSX_KEYCHAIN
|
||||||
/* mysql and postgres aren't valid protocols on Mac OS X.
|
/* mysql and postgres aren't valid protocols on Mac OS X.
|
||||||
@ -244,8 +297,8 @@ gboolean gnc_keyring_get_password ( GtkWidget *parent,
|
|||||||
if ( status == noErr )
|
if ( status == noErr )
|
||||||
{
|
{
|
||||||
*password = g_strndup(password_data, password_length);
|
*password = g_strndup(password_data, password_length);
|
||||||
password_found = TRUE;
|
|
||||||
SecKeychainItemFreeContent(NULL, password_data);
|
SecKeychainItemFreeContent(NULL, password_data);
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -258,46 +311,42 @@ gboolean gnc_keyring_get_password ( GtkWidget *parent,
|
|||||||
}
|
}
|
||||||
#endif /* HAVE_OSX_KEYCHAIN */
|
#endif /* HAVE_OSX_KEYCHAIN */
|
||||||
|
|
||||||
if ( !password_found )
|
/* If we got here, either no proper password store is
|
||||||
|
* available on this system, or we couldn't retrieve
|
||||||
|
* a password from it. In both cases, just ask the user
|
||||||
|
* to enter one
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ( port == 0 )
|
||||||
|
db_path = g_strdup_printf ( "%s://%s/%s", access_method, server, service );
|
||||||
|
else
|
||||||
|
db_path = g_strdup_printf ( "%s://%s:%d/%s", access_method, server, port, service );
|
||||||
|
heading = g_strdup_printf ( /* Translators: %s is a path to a database or any other url,
|
||||||
|
like mysql://user@server.somewhere/somedb, http://www.somequotes.com/thequotes */
|
||||||
|
_("Enter a user name and password to connect to: %s"),
|
||||||
|
db_path );
|
||||||
|
|
||||||
|
password_found = gnc_get_username_password ( parent, heading,
|
||||||
|
*user, NULL,
|
||||||
|
user, password );
|
||||||
|
g_free ( db_path );
|
||||||
|
g_free ( heading );
|
||||||
|
|
||||||
|
if ( password_found )
|
||||||
{
|
{
|
||||||
/* If we got here, either no proper password store is
|
/* User entered new user/password information
|
||||||
* available on this system, or we couldn't retrieve
|
* Let's try to add it to a password store.
|
||||||
* a password from it. In both cases, just ask the user
|
*/
|
||||||
* to enter one
|
gchar *newuser = g_strdup( *user );
|
||||||
*/
|
gchar *newpassword = g_strdup( *password );
|
||||||
gchar *db_path, *heading;
|
gnc_keyring_set_password ( access_method,
|
||||||
|
server,
|
||||||
if ( port == 0 )
|
port,
|
||||||
db_path = g_strdup_printf ( "%s://%s/%s", access_method, server, service );
|
service,
|
||||||
else
|
newuser,
|
||||||
db_path = g_strdup_printf ( "%s://%s:%d/%s", access_method, server, port, service );
|
newpassword );
|
||||||
heading = g_strdup_printf ( /* Translators: %s is a path to a database or any other url,
|
g_free ( newuser );
|
||||||
like mysql://user@server.somewhere/somedb, http://www.somequotes.com/thequotes */
|
g_free ( newpassword );
|
||||||
_("Enter a user name and password to connect to: %s"),
|
|
||||||
db_path );
|
|
||||||
|
|
||||||
password_found = gnc_get_username_password ( parent, heading,
|
|
||||||
*user, NULL,
|
|
||||||
user, password );
|
|
||||||
g_free ( db_path );
|
|
||||||
g_free ( heading );
|
|
||||||
|
|
||||||
if ( password_found )
|
|
||||||
{
|
|
||||||
/* User entered new user/password information
|
|
||||||
* Let's try to add it to a password store.
|
|
||||||
*/
|
|
||||||
gchar *newuser = g_strdup( *user );
|
|
||||||
gchar *newpassword = g_strdup( *password );
|
|
||||||
gnc_keyring_set_password ( access_method,
|
|
||||||
server,
|
|
||||||
port,
|
|
||||||
service,
|
|
||||||
newuser,
|
|
||||||
newpassword );
|
|
||||||
g_free ( newuser );
|
|
||||||
g_free ( newpassword );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return password_found;
|
return password_found;
|
||||||
|
Loading…
Reference in New Issue
Block a user