on bf461a2 help sign in
382 lines 13 kB history raw
1/*
2 * Copyright 2013 Canonical Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Alberto Ruiz <alberto.ruiz@canonical.com>
18 * Renato Araujo Oliveira Filho <renato@canonical.com>
19 */
22#include <glib.h>
23#include <glib-object.h>
24#include <nm-secret-agent.h>
25#include "secret-agent.h"
27#define UNITY_SETTINGS_TYPE_SECRET_AGENT (unity_settings_secret_agent_get_type ())
28#define UNITY_SETTINGS_SECRET_AGENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), UNITY_SETTINGS_TYPE_SECRET_AGENT, UnitySettingsSecretAgent))
29#define UNITY_SETTINGS_SECRET_AGENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UNITY_SETTINGS_TYPE_SECRET_AGENT, UnitySettingsSecretAgentClass))
30#define UNITY_SETTINGS_IS_SECRET_AGENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UNITY_SETTINGS_TYPE_SECRET_AGENT))
31#define UNITY_SETTINGS_IS_SECRET_AGENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UNITY_SETTINGS_TYPE_SECRET_AGENT))
32#define UNITY_SETTINGS_SECRET_AGENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UNITY_SETTINGS_TYPE_SECRET_AGENT, UnitySettingsSecretAgentClass))
33#define UNITY_SETTINGS_SECRET_AGENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), UNITY_SETTINGS_TYPE_SECRET_AGENT, UnitySettingsSecretAgentPrivate))
35#define AGENT_ID "com.canonical.settings.network.nm-agent"
37static gpointer unity_settings_secret_agent_parent_class = NULL;
39typedef struct _UnitySettingsSecretAgentPrivate UnitySettingsSecretAgentPrivate;
41struct _UnitySettingsSecretAgentPrivate {
42 GQueue *requests;
43};
45typedef struct _SecretRequest {
46 gint id;
47 NMSecretAgent *agent;
48 NMConnection *connection;
49 const char *connection_path;
50 const char *setting_name;
51 const char **hints;
52 NMSecretAgentGetSecretsFlags flags;
53 NMSecretAgentGetSecretsFunc callback;
54 gpointer callback_data;
55} SecretRequest;
57GType unity_settings_secret_agent_get_type (void) G_GNUC_CONST;
58enum {
59 UNITY_SETTINGS_SECRET_AGENT_DUMMY_PROPERTY
60};
62enum {
63 SECRET_REQUESTED,
64 REQUEST_CANCELLED,
65 LAST_SIGNAL
66};
68static guint signals[LAST_SIGNAL] = { 0 };
70UnitySettingsSecretAgent* unity_settings_secret_agent_new (void);
71UnitySettingsSecretAgent* unity_settings_secret_agent_construct (GType object_type);
73int
74secret_request_find (SecretRequest *req,
75 guint *id)
77 if (req->id > *id)
78 return -1;
80 if (req->id < *id)
81 return 1;
83 return 0;
86void
87unity_settings_secret_agent_provide_secret (UnitySettingsSecretAgent *agent,
88 guint request,
89 GHashTable *secrets)
91 GList *iter;
92 SecretRequest *req;
93 UnitySettingsSecretAgentPrivate *priv = agent->priv;
95 iter = g_queue_find_custom (priv->requests,
96 &request,
97 (GCompareFunc)secret_request_find);
99 if (iter == NULL || iter->data == NULL)
100 {
101 g_warning ("Secret request with id <%d> was not found", (int)request);
102 return;
103 }
105 req = iter->data;
107 req->callback (NM_SECRET_AGENT (agent),
108 req->connection,
109 secrets,
110 NULL,
111 req->callback_data);
113 g_queue_remove_all (priv->requests, req);
114 g_free (req);
115 return;
118void
119free_request (SecretRequest *req)
121 g_object_unref (req->connection);
122 g_free (req);
125void
126unity_settings_secret_agent_cancel_request (UnitySettingsSecretAgent *agent,
127 guint request)
129 GList *iter;
130 SecretRequest *req;
131 UnitySettingsSecretAgentPrivate *priv = agent->priv;
132 GError *error;
134 iter = g_queue_find_custom (priv->requests,
135 &request,
136 (GCompareFunc)secret_request_find);
138 if (iter == NULL || iter->data == NULL)
139 {
140 g_warning ("Secret request with id <%d> was not found", (int)request);
141 return;
142 }
144 req = iter->data;
145 error = g_error_new (NM_SECRET_AGENT_ERROR,
146 NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
147 "This secret request was canceled by the user.");
149 req->callback (NM_SECRET_AGENT (agent),
150 req->connection,
151 NULL,
152 error,
153 req->callback_data);
155 g_queue_remove_all (priv->requests, req);
156 free_request (req);
157 return;
160static void
161delete_secrets (NMSecretAgent *agent,
162 NMConnection *connection,
163 const char *connection_path,
164 NMSecretAgentDeleteSecretsFunc callback,
165 gpointer callback_data)
167 g_debug ("delete secrets");
170/* If it returns G_MAXUINT it's considered an error */
171static guint
172find_available_id (UnitySettingsSecretAgentPrivate *priv)
174 guint i = 0;
175 guint candidate = 0;
177 if (g_queue_get_length (priv->requests) == G_MAXUINT)
178 return G_MAXUINT;
180 while (i < g_queue_get_length (priv->requests))
181 {
182 SecretRequest *req = (SecretRequest*)g_queue_peek_nth (priv->requests, i);
184 if (req->id == candidate)
185 {
186 candidate++;
187 i = 0;
188 }
189 else
190 {
191 i++;
192 }
193 }
195 return i;
198static void
199get_secrets (NMSecretAgent *agent,
200 NMConnection *connection,
201 const char *connection_path,
202 const char *setting_name,
203 const char **hints,
204 NMSecretAgentGetSecretsFlags flags,
205 NMSecretAgentGetSecretsFunc callback,
206 gpointer callback_data)
208 guint id;
209 UnitySettingsSecretAgentPrivate *priv = UNITY_SETTINGS_SECRET_AGENT_GET_PRIVATE (agent);
210 SecretRequest *req = NULL;
212 if (flags == NM_SECRET_AGENT_GET_SECRETS_FLAG_NONE)
213 {
214 GError *error = g_error_new (NM_SECRET_AGENT_ERROR,
215 NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
216 "No password found for this connection.");
217 callback (agent, connection, NULL, error, callback_data);
218 g_error_free (error);
219 return;
220 }
222 id = find_available_id (priv);
223 if (id == G_MAXUINT)
224 {
225 GError *error = g_error_new (NM_SECRET_AGENT_ERROR,
226 NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
227 "Reached maximum number of requests.");
228 callback (agent, connection, NULL, error, callback_data);
229 g_error_free (error);
230 return;
231 }
233 /* Adding a request */
234 req = (SecretRequest*) g_malloc0 (sizeof (SecretRequest));
235 *req = ((SecretRequest)
236 { id,
237 agent,
238 connection,
239 connection_path,
240 setting_name,
241 hints,
242 flags,
243 callback,
244 callback_data });
246 g_object_ref (connection);
248 g_queue_push_tail (priv->requests, req);
250 g_signal_emit_by_name (agent,
251 UNITY_SETTINGS_SECRET_AGENT_SECRET_REQUESTED,
252 id,
253 connection,
254 setting_name,
255 hints,
256 flags);
259static void
260save_secrets (NMSecretAgent *agent,
261 NMConnection *connection,
262 const char *connection_path,
263 NMSecretAgentSaveSecretsFunc callback,
264 gpointer callback_data)
266 g_debug ("save secrets");
269static void
270cancel_get_secrets (NMSecretAgent *agent,
271 const char *connection_path,
272 const char *setting_name)
274 g_debug ("cancel get secrets");
277UnitySettingsSecretAgent*
278unity_settings_secret_agent_construct (GType object_type)
280 UnitySettingsSecretAgent * self = NULL;
281 self = (UnitySettingsSecretAgent*) g_object_new (object_type,
282 NM_SECRET_AGENT_IDENTIFIER, AGENT_ID,
283 NULL);
284 return self;
288UnitySettingsSecretAgent*
289unity_settings_secret_agent_new (void)
291 return unity_settings_secret_agent_construct (UNITY_SETTINGS_TYPE_SECRET_AGENT);
294static void
295destroy_pending_request (gpointer data)
297 SecretRequest* req = (SecretRequest*)data;
298 /* Reporting the cancellation of all pending requests */
299 g_signal_emit_by_name (req->agent,
300 UNITY_SETTINGS_SECRET_AGENT_REQUEST_CANCELLED,
301 req->id);
303 free_request (req);
306static void
307unity_settings_secret_agent_finalize (GObject *agent)
309 UnitySettingsSecretAgentPrivate *priv = UNITY_SETTINGS_SECRET_AGENT_GET_PRIVATE (agent);
311 g_queue_free_full (priv->requests, destroy_pending_request);
314static void
315unity_settings_secret_agent_class_init (UnitySettingsSecretAgentClass *klass)
317 unity_settings_secret_agent_parent_class = g_type_class_peek_parent (klass);
318 NMSecretAgentClass *parent_class = NM_SECRET_AGENT_CLASS (klass);
319 parent_class->get_secrets = get_secrets;
320 parent_class->save_secrets = save_secrets;
321 parent_class->delete_secrets = delete_secrets;
322 parent_class->cancel_get_secrets = cancel_get_secrets;
324 g_type_class_add_private (klass, sizeof(UnitySettingsSecretAgentPrivate));
325 G_OBJECT_CLASS (klass)->finalize = unity_settings_secret_agent_finalize;
328 signals[SECRET_REQUESTED] = g_signal_new (UNITY_SETTINGS_SECRET_AGENT_SECRET_REQUESTED,
329 G_OBJECT_CLASS_TYPE (G_OBJECT_CLASS (klass)),
330 G_SIGNAL_RUN_FIRST,
331 G_STRUCT_OFFSET (UnitySettingsSecretAgentClass, secret_requested),
332 NULL, NULL, NULL,
333 G_TYPE_NONE, 5,
334 G_TYPE_UINT, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_UINT);
336 signals[REQUEST_CANCELLED] = g_signal_new (UNITY_SETTINGS_SECRET_AGENT_REQUEST_CANCELLED,
337 G_OBJECT_CLASS_TYPE (G_OBJECT_CLASS (klass)),
338 G_SIGNAL_RUN_FIRST,
339 G_STRUCT_OFFSET (UnitySettingsSecretAgentClass, request_cancelled),
340 NULL, NULL, NULL,
341 G_TYPE_NONE, 1,
342 G_TYPE_UINT);
346static void
347unity_settings_secret_agent_instance_init (UnitySettingsSecretAgent *self)
349 self->priv = UNITY_SETTINGS_SECRET_AGENT_GET_PRIVATE (self);
350 self->priv->requests = g_queue_new ();
353GType
354unity_settings_secret_agent_get_type (void)
356 static volatile gsize unity_settings_secret_agent_type_id__volatile = 0;
357 if (g_once_init_enter (&unity_settings_secret_agent_type_id__volatile))
358 {
359 static const GTypeInfo g_define_type_info =
360 {
361 sizeof (UnitySettingsSecretAgentClass),
362 (GBaseInitFunc) NULL,
363 (GBaseFinalizeFunc) NULL,
364 (GClassInitFunc) unity_settings_secret_agent_class_init,
365 (GClassFinalizeFunc) NULL,
366 NULL,
367 sizeof (UnitySettingsSecretAgent),
368 0,
369 (GInstanceInitFunc) unity_settings_secret_agent_instance_init,
370 NULL
371 };
372 GType unity_settings_secret_agent_type_id;
373 unity_settings_secret_agent_type_id = g_type_register_static (NM_TYPE_SECRET_AGENT,
374 "UnitySettingsSecretAgent",
375 &g_define_type_info,
376 0);
377 g_once_init_leave (&unity_settings_secret_agent_type_id__volatile,
378 unity_settings_secret_agent_type_id);
379 }
381 return unity_settings_secret_agent_type_id__volatile;