/dev/qulogic/masterpassword: efe6019c9e91: Add a Secret Service ...

Elliott Sales de Andrade qulogic at pidgin.im
Thu Aug 23 02:12:32 EDT 2012


Changeset: efe6019c9e91e1b36cd7a5bc68caa4a179124b56
Author:	 Elliott Sales de Andrade <qulogic at pidgin.im>
Date:	 2012-08-23 01:27 -0400
Branch:	 soc.2008.masterpassword
URL: http://hg.pidgin.im/dev/qulogic/masterpassword/rev/efe6019c9e91

Description:

Add a Secret Service password plugin.

No, not *that* Secret Service... The password storing one:
http://developer.gnome.org/libsecret/

diffstat:

 configure.ac                               |   24 +
 libpurple/plugins/keyrings/Makefile.am     |   14 +
 libpurple/plugins/keyrings/secretservice.c |  360 +++++++++++++++++++++++++++++
 3 files changed, 398 insertions(+), 0 deletions(-)

diffs (truncated from 437 to 300 lines):

diff --git a/configure.ac b/configure.ac
--- a/configure.ac
+++ b/configure.ac
@@ -1447,6 +1447,29 @@ else
 fi
 
 dnl #######################################################################
+dnl # Check for Secret Service headers
+dnl #######################################################################
+
+AC_ARG_ENABLE(libsecret, [AC_HELP_STRING([--disable-secret-service], [disable Secret Service support])], enable_secret_service=$enableval, enable_secret_service=yes)
+
+dnl Check for libsecret; if we don't have it, oh well
+if test "x$enable_secret_service" = "xyes" ; then
+	PKG_CHECK_MODULES(SECRETSERVICE, [libsecret-1], [
+		AC_SUBST(SECRETSERVICE_CFLAGS)
+		AC_SUBST(SECRETSERVICE_LIBS)
+		AC_DEFINE(HAVE_SECRETSERVICE, 1, [Define if we have Secret Service.])
+	], [
+		if test "x$force_deps" = "xyes" ; then
+			AC_MSG_ERROR([
+Secret Service development headers not found.
+Use --disable-secret-service if you do not need Secret Service support.
+])
+		fi])
+fi
+
+AM_CONDITIONAL(ENABLE_SECRETSERVICE, test "x$enable_secret_service" = "xyes")
+
+dnl #######################################################################
 dnl # Check for GNOME Keyring headers
 dnl #######################################################################
 
@@ -2806,6 +2829,7 @@ if test "x$enable_dbus" = "xyes" ; then
 fi
 echo Build with GNU Libidn......... : $enable_idn
 echo Build with NetworkManager..... : $enable_nm
+echo Build with Secret Service..... : $enable_secret_service
 echo Build with GNOME Keyring...... : $enable_gnome_keyring
 echo Build with KWallet............ : $enable_kwallet
 echo SSL Library/Libraries......... : $msg_ssl
diff --git a/libpurple/plugins/keyrings/Makefile.am b/libpurple/plugins/keyrings/Makefile.am
--- a/libpurple/plugins/keyrings/Makefile.am
+++ b/libpurple/plugins/keyrings/Makefile.am
@@ -8,6 +8,15 @@ internalkeyring_la_LDFLAGS = -module -av
 internalkeyring_la_SOURCES = internalkeyring.c
 internalkeyring_la_LIBADD  = $(GLIB_LIBS)
 
+if ENABLE_SECRETSERVICE
+
+secretservice_la_CFLAGS  = $(AM_CPPFLAGS) $(SECRETSERVICE_CFLAGS)
+secretservice_la_LDFLAGS = -module -avoid-version
+secretservice_la_SOURCES = secretservice.c
+secretservice_la_LIBADD  = $(GLIB_LIBS) $(SECRETSERVICE_LIBS)
+
+endif
+
 if ENABLE_GNOMEKEYRING
 
 gnomekeyring_la_CFLAGS  = $(AM_CPPFLAGS) $(GNOMEKEYRING_CFLAGS)
@@ -35,6 +44,11 @@ if PLUGINS
 plugin_LTLIBRARIES = \
 	internalkeyring.la
 
+if ENABLE_SECRETSERVICE
+plugin_LTLIBRARIES += \
+	secretservice.la
+endif
+
 if ENABLE_GNOMEKEYRING
 plugin_LTLIBRARIES += \
 	gnomekeyring.la
diff --git a/libpurple/plugins/keyrings/secretservice.c b/libpurple/plugins/keyrings/secretservice.c
new file mode 100644
--- /dev/null
+++ b/libpurple/plugins/keyrings/secretservice.c
@@ -0,0 +1,360 @@
+/* purple
+ * @file secretservice.c Secret Service password storage
+ * @ingroup plugins
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program 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.
+ *
+ * This program 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+
+#include "internal.h"
+#include "account.h"
+#include "debug.h"
+#include "keyring.h"
+#include "plugin.h"
+#include "version.h"
+
+#include <libsecret/secret.h>
+
+#define SECRETSERVICE_NAME        N_("Secret Service")
+#define SECRETSERVICE_ID          "keyring-libsecret"
+
+#define ERR_SECRETSERVICEPLUGIN   (ss_error_domain())
+
+static PurpleKeyring *keyring_handler = NULL;
+
+static const SecretSchema purple_schema = {
+	"im.pidgin.Purple", SECRET_SCHEMA_NONE,
+	{
+		{"user", SECRET_SCHEMA_ATTRIBUTE_STRING},
+		{"protocol", SECRET_SCHEMA_ATTRIBUTE_STRING},
+		{"NULL", 0}
+	},
+	/* Reserved fields */
+	0, 0, 0, 0, 0, 0, 0, 0
+};
+
+typedef struct _InfoStorage InfoStorage;
+
+struct _InfoStorage
+{
+	PurpleAccount *account;
+	gpointer cb;
+	gpointer user_data;
+};
+
+static GQuark
+ss_error_domain(void)
+{
+	return g_quark_from_static_string("SecretService plugin");
+}
+
+
+/***********************************************/
+/*     Keyring interface                       */
+/***********************************************/
+static void
+ss_read_continue(GObject *object, GAsyncResult *result, gpointer data)
+{
+	InfoStorage *storage = data;
+	PurpleAccount *account = storage->account;
+	PurpleKeyringReadCallback cb = storage->cb;
+	char *password;
+	GError *error = NULL;
+
+	password = secret_password_lookup_finish(result, &error);
+
+	if (error != NULL) {
+		int code = error->code;
+		g_error_free(error);
+
+		switch (code) {
+			case G_DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND:
+			case G_DBUS_ERROR_IO_ERROR:
+				error = g_error_new(ERR_SECRETSERVICEPLUGIN,
+				                    PURPLE_KEYRING_ERROR_NOCHANNEL,
+				                    "Failed to communicate with Secret Service (account : %s).",
+				                    purple_account_get_username(account));
+				if (cb != NULL)
+					cb(account, NULL, error, storage->user_data);
+				g_error_free(error);
+				break;
+
+			default:
+				error = g_error_new(ERR_SECRETSERVICEPLUGIN,
+				                    PURPLE_KEYRING_ERROR_NOCHANNEL,
+				                    "Unknown error (account : %s).",
+				                    purple_account_get_username(account));
+				if (cb != NULL)
+					cb(account, NULL, error, storage->user_data);
+				g_error_free(error);
+				break;
+		}
+
+	} else if (password == NULL) {
+		error = g_error_new(ERR_SECRETSERVICEPLUGIN,
+		                    PURPLE_KEYRING_ERROR_NOPASSWD,
+		                    "No password found for account: %s",
+		                    purple_account_get_username(account));
+		if (cb != NULL)
+			cb(account, NULL, error, storage->user_data);
+		g_error_free(error);
+
+	} else {
+		if (cb != NULL)
+			cb(account, password, NULL, storage->user_data);
+	}
+
+	g_free(storage);
+}
+
+static void
+ss_read(PurpleAccount *account, PurpleKeyringReadCallback cb, gpointer data)
+{
+	InfoStorage *storage = g_new0(InfoStorage, 1);
+
+	storage->account = account;
+	storage->cb = cb;
+	storage->user_data = data;
+
+	secret_password_lookup(&purple_schema,
+	                       NULL, ss_read_continue, storage,
+	                       "user", purple_account_get_username(account),
+	                       "protocol", purple_account_get_protocol_id(account),
+	                       NULL);
+}
+
+static void
+ss_save_continue(GObject *object, GAsyncResult *result, gpointer data)
+{
+	InfoStorage *storage = data;
+	PurpleKeyringSaveCallback cb;
+	GError *error = NULL;
+	PurpleAccount *account;
+
+	account = storage->account;
+	cb = storage->cb;
+
+	secret_password_store_finish(result, &error);
+
+	if (error != NULL) {
+		int code = error->code;
+		g_error_free(error);
+
+		switch (code) {
+			case G_DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND:
+			case G_DBUS_ERROR_IO_ERROR:
+				purple_debug_info("keyring-libsecret",
+				                  "Failed to communicate with Secret Service (account : %s (%s)).\n",
+				                  purple_account_get_username(account),
+				                  purple_account_get_protocol_id(account));
+				error = g_error_new(ERR_SECRETSERVICEPLUGIN,
+				                    PURPLE_KEYRING_ERROR_NOCHANNEL,
+				                    "Failed to communicate with Secret Service (account : %s).",
+				                    purple_account_get_username(account));
+				if (cb != NULL)
+					cb(account, error, storage->user_data);
+				g_error_free(error);
+				break;
+
+			default:
+				purple_debug_info("keyring-libsecret",
+				                  "Unknown error (account : %s (%s)).\n",
+				                  purple_account_get_username(account),
+				                  purple_account_get_protocol_id(account));
+				error = g_error_new(ERR_SECRETSERVICEPLUGIN,
+				                    PURPLE_KEYRING_ERROR_NOCHANNEL,
+				                    "Unknown error (account : %s).",
+				                    purple_account_get_username(account));
+				if (cb != NULL)
+					cb(account, error, storage->user_data);
+				g_error_free(error);
+				break;
+		}
+
+	} else {
+		purple_debug_info("keyring-libsecret", "Password for %s updated.\n",
+			purple_account_get_username(account));
+
+		if (cb != NULL)
+			cb(account, NULL, storage->user_data);
+	}
+
+	g_free(storage);
+}
+
+static void
+ss_save(PurpleAccount *account,
+         const gchar *password,
+         PurpleKeyringSaveCallback cb,
+         gpointer data)
+{
+	InfoStorage *storage = g_new0(InfoStorage, 1);
+
+	storage->account = account;
+	storage->cb = cb;
+	storage->user_data = data;
+
+	if (password != NULL && *password != '\0') {
+		const char *username = purple_account_get_username(account);
+		char *label;
+
+		purple_debug_info("keyring-libsecret",
+			"Updating password for account %s (%s).\n",
+			username, purple_account_get_protocol_id(account));
+
+		label = g_strdup_printf(_("Pidgin IM password for account %s"), username);
+		secret_password_store(&purple_schema, SECRET_COLLECTION_DEFAULT,
+		                      label, password,
+		                      NULL, ss_save_continue, storage,



More information about the Commits mailing list