1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * soup-password-manager-gnome.c: GNOME-keyring-based password manager
5 * Copyright (C) 2008 Red Hat, Inc.
12 #define LIBSOUP_I_HAVE_READ_BUG_594377_AND_KNOW_SOUP_PASSWORD_MANAGER_MIGHT_GO_AWAY
14 #include "soup-password-manager-gnome.h"
15 #include "soup-auth.h"
16 #include "soup-session-feature.h"
19 #include <gnome-keyring.h>
21 static void soup_password_manager_gnome_interface_init (SoupPasswordManagerInterface *password_manager_interface);
23 G_DEFINE_TYPE_EXTENDED (SoupPasswordManagerGNOME, soup_password_manager_gnome, G_TYPE_OBJECT, 0,
24 G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE, NULL)
25 G_IMPLEMENT_INTERFACE (SOUP_TYPE_PASSWORD_MANAGER, soup_password_manager_gnome_interface_init))
27 static void get_passwords_async (SoupPasswordManager *password_manager,
31 GMainContext *async_context,
32 GCancellable *cancellable,
33 SoupPasswordManagerCallback callback,
35 static void get_passwords_sync (SoupPasswordManager *password_manager,
38 GCancellable *cancellable);
41 soup_password_manager_gnome_init (SoupPasswordManagerGNOME *manager_gnome)
46 soup_password_manager_gnome_class_init (SoupPasswordManagerGNOMEClass *gnome_class)
51 soup_password_manager_gnome_interface_init (SoupPasswordManagerInterface *password_manager_interface)
53 password_manager_interface->get_passwords_async = get_passwords_async;
54 password_manager_interface->get_passwords_sync = get_passwords_sync;
59 save_password_callback (GnomeKeyringResult result, guint32 val, gpointer data)
64 async_save_password (SoupAuth *auth, const char *username,
65 const char *password, gpointer user_data)
67 SoupURI *uri = user_data;
69 gnome_keyring_set_network_password (
70 NULL, /* use default keyring */
72 soup_auth_get_realm (auth),
76 soup_auth_get_scheme_name (auth),
79 save_password_callback, NULL, NULL);
83 sync_save_password (SoupAuth *auth, const char *username,
84 const char *password, gpointer user_data)
86 SoupURI *uri = user_data;
89 gnome_keyring_set_network_password_sync (
90 NULL, /* use default keyring */
92 soup_auth_get_realm (auth),
96 soup_auth_get_scheme_name (auth),
103 update_auth_for_passwords (SoupAuth *auth, SoupMessage *msg,
104 GList *passwords, gboolean async)
106 GnomeKeyringNetworkPasswordData *pdata;
110 pdata = passwords->data;
111 soup_auth_has_saved_password (auth, pdata->user,
113 passwords = passwords->next;
116 uri = g_object_get_data (G_OBJECT (auth),
117 "SoupPasswordManagerGNOME-save_password-uri");
119 g_signal_handlers_disconnect_by_func (auth, async_save_password, uri);
120 g_signal_handlers_disconnect_by_func (auth, sync_save_password, uri);
123 uri = soup_uri_copy (soup_message_get_uri (msg));
124 g_signal_connect (auth, "save_password",
125 G_CALLBACK (async ? async_save_password : sync_save_password),
127 g_object_set_data_full (G_OBJECT (auth),
128 "SoupPasswordManagerGNOME-save_password-uri",
129 uri, (GDestroyNotify)soup_uri_free);
133 SoupPasswordManager *password_manager;
138 SoupPasswordManagerCallback callback;
142 } SoupPasswordManagerGNOMEAuthData;
145 find_password_callback (GnomeKeyringResult result, GList *list,
148 SoupPasswordManagerGNOMEAuthData *auth_data = user_data;
150 /* FIXME: check result? */
152 update_auth_for_passwords (auth_data->auth, auth_data->msg, list, TRUE);
153 auth_data->callback (auth_data->password_manager,
154 auth_data->msg, auth_data->auth,
155 auth_data->retrying, auth_data->user_data);
157 /* gnome-keyring will call free_auth_data to clean up for us. */
161 free_auth_data (gpointer data)
163 SoupPasswordManagerGNOMEAuthData *auth_data = data;
165 g_object_unref (auth_data->auth);
166 g_object_unref (auth_data->msg);
167 g_slice_free (SoupPasswordManagerGNOMEAuthData, auth_data);
171 get_passwords_async (SoupPasswordManager *password_manager,
175 GMainContext *async_context,
176 GCancellable *cancellable,
177 SoupPasswordManagerCallback callback,
180 SoupPasswordManagerGNOMEAuthData *auth_data;
181 SoupURI *uri = soup_message_get_uri (msg);
183 auth_data = g_slice_new (SoupPasswordManagerGNOMEAuthData);
184 auth_data->password_manager = password_manager;
185 auth_data->msg = g_object_ref (msg);
186 auth_data->auth = g_object_ref (auth);
187 auth_data->retrying = retrying;
189 /* FIXME: async_context, cancellable */
191 auth_data->callback = callback;
192 auth_data->user_data = user_data;
194 /* FIXME: should we be specifying protocol and port here, or
195 * leaving them NULL/0 and filtering results in the callback?
196 * We don't want to send https passwords to http, but the
197 * reverse might be OK (if that's how other clients tend to
200 auth_data->request = gnome_keyring_find_network_password (
201 NULL, /* user -- accept any */
202 soup_auth_get_realm (auth), /* domain */
203 uri->host, /* server */
204 NULL, /* object -- unused */
205 uri->scheme, /* protocol */
206 soup_auth_get_scheme_name (auth), /* authtype */
207 uri->port, /* port */
208 find_password_callback, auth_data, free_auth_data);
212 get_passwords_sync (SoupPasswordManager *password_manager,
215 GCancellable *cancellable)
217 SoupURI *uri = soup_message_get_uri (msg);
218 GList *results = NULL;
220 /* FIXME: cancellable */
222 gnome_keyring_find_network_password_sync (
223 NULL, /* user -- accept any */
224 soup_auth_get_realm (auth), /* domain */
225 uri->host, /* server */
226 NULL, /* object -- unused */
227 uri->scheme, /* protocol */
228 soup_auth_get_scheme_name (auth), /* authtype */
229 uri->port, /* port */
232 update_auth_for_passwords (auth, msg, results, FALSE);