libnm: accept invalid connections in NMSecretAgentOld
[NetworkManager.git] / libnm / nm-secret-agent-old.c
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 /*
3  * This library is free software; you can redistribute it and/or
4  * modify it under the terms of the GNU Lesser General Public
5  * License as published by the Free Software Foundation; either
6  * version 2 of the License, or (at your option) any later version.
7  *
8  * This library 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 GNU
11  * Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public
14  * License along with this library; if not, write to the
15  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16  * Boston, MA 02110-1301 USA.
17  *
18  * Copyright 2010 - 2011 Red Hat, Inc.
19  */
20
21 #include "nm-default.h"
22
23 #include <string.h>
24
25 #include "nm-dbus-interface.h"
26 #include "nm-secret-agent-old.h"
27 #include "nm-enum-types.h"
28 #include "nm-dbus-helpers.h"
29 #include "nm-simple-connection.h"
30 #include "nm-core-internal.h"
31
32 #include "nmdbus-secret-agent.h"
33 #include "nmdbus-agent-manager.h"
34
35 static void nm_secret_agent_old_initable_iface_init (GInitableIface *iface);
36 static void nm_secret_agent_old_async_initable_iface_init (GAsyncInitableIface *iface);
37 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (NMSecretAgentOld, nm_secret_agent_old, G_TYPE_OBJECT,
38                                   G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_secret_agent_old_initable_iface_init);
39                                   G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_secret_agent_old_async_initable_iface_init);
40                                   )
41
42 #define NM_SECRET_AGENT_OLD_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SECRET_AGENT_OLD, NMSecretAgentOldPrivate))
43
44 typedef struct {
45         gboolean registered;
46         gboolean registering;
47         NMSecretAgentCapabilities capabilities;
48
49         GDBusConnection *bus;
50         gboolean private_bus;
51         gboolean session_bus;
52         NMDBusAgentManager *manager_proxy;
53         NMDBusSecretAgent *dbus_secret_agent;
54
55         /* GetSecretsInfo structs of in-flight GetSecrets requests */
56         GSList *pending_gets;
57
58         char *identifier;
59         gboolean auto_register;
60         gboolean suppress_auto;
61 } NMSecretAgentOldPrivate;
62
63 enum {
64         PROP_0,
65         PROP_IDENTIFIER,
66         PROP_AUTO_REGISTER,
67         PROP_REGISTERED,
68         PROP_CAPABILITIES,
69
70         LAST_PROP
71 };
72
73 /*************************************************************/
74
75 static void
76 _internal_unregister (NMSecretAgentOld *self)
77 {
78         NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
79
80         if (priv->registered) {
81                 g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (priv->dbus_secret_agent));
82                 priv->registered = FALSE;
83                 priv->registering = FALSE;
84                 g_object_notify (G_OBJECT (self), NM_SECRET_AGENT_OLD_REGISTERED);
85         }
86 }
87
88 typedef struct {
89         char *path;
90         char *setting_name;
91         GDBusMethodInvocation *context;
92 } GetSecretsInfo;
93
94 static void
95 get_secrets_info_finalize (NMSecretAgentOld *self, GetSecretsInfo *info)
96 {
97         NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
98
99         g_return_if_fail (info != NULL);
100
101         priv->pending_gets = g_slist_remove (priv->pending_gets, info);
102
103         g_free (info->path);
104         g_free (info->setting_name);
105         memset (info, 0, sizeof (*info));
106         g_free (info);
107 }
108
109 static inline gboolean
110 should_auto_register (NMSecretAgentOld *self)
111 {
112         NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
113
114         return (   priv->auto_register
115                 && !priv->suppress_auto
116                 && !priv->registered
117                 && !priv->registering);
118 }
119
120 static void
121 name_owner_changed (GObject *proxy,
122                     GParamSpec *pspec,
123                     gpointer user_data)
124 {
125         NMSecretAgentOld *self = NM_SECRET_AGENT_OLD (user_data);
126         NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
127         GSList *iter;
128         char *owner;
129
130         owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (proxy));
131         if (owner != NULL) {
132                 if (should_auto_register (self))
133                         nm_secret_agent_old_register_async (self, NULL, NULL, NULL);
134                 g_free (owner);
135         } else {
136                 /* Cancel any pending secrets requests */
137                 for (iter = priv->pending_gets; iter; iter = g_slist_next (iter)) {
138                         GetSecretsInfo *info = iter->data;
139
140                         NM_SECRET_AGENT_OLD_GET_CLASS (self)->cancel_get_secrets (self,
141                                                                               info->path,
142                                                                               info->setting_name);
143                 }
144                 g_slist_free (priv->pending_gets);
145                 priv->pending_gets = NULL;
146
147                 _internal_unregister (self);
148         }
149 }
150
151 static gboolean
152 verify_sender (NMSecretAgentOld *self,
153                GDBusMethodInvocation *context,
154                GError **error)
155 {
156         NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
157         char *nm_owner;
158         const char *sender;
159         guint32 sender_uid;
160         GVariant *ret;
161         GError *local = NULL;
162
163         g_return_val_if_fail (context != NULL, FALSE);
164
165         /* Private bus connection is always to NetworkManager, which is always
166          * UID 0.
167          */
168         if (priv->private_bus)
169                 return TRUE;
170
171         /* Verify that the sender is the same as NetworkManager's bus name owner. */
172
173         nm_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (priv->manager_proxy));
174         if (!nm_owner) {
175                 g_set_error_literal (error,
176                                      NM_SECRET_AGENT_ERROR,
177                                      NM_SECRET_AGENT_ERROR_PERMISSION_DENIED,
178                                      "NetworkManager bus name owner unknown.");
179                 return FALSE;
180         }
181
182         sender = g_dbus_method_invocation_get_sender (context);
183         if (!sender) {
184                 g_set_error_literal (error,
185                                      NM_SECRET_AGENT_ERROR,
186                                      NM_SECRET_AGENT_ERROR_PERMISSION_DENIED,
187                                      "Failed to get request sender.");
188                 g_free (nm_owner);
189                 return FALSE;
190         }
191
192         /* Check that the sender matches the current NM bus name owner */
193         if (strcmp (sender, nm_owner) != 0) {
194                 g_set_error_literal (error,
195                                      NM_SECRET_AGENT_ERROR,
196                                      NM_SECRET_AGENT_ERROR_PERMISSION_DENIED,
197                                      "Request sender does not match NetworkManager bus name owner.");
198                 g_free (nm_owner);
199                 return FALSE;
200         }
201         g_free (nm_owner);
202
203         /* If we're connected to the session bus, then this must be a test program,
204          * so skip the UID check.
205          */
206         if (priv->session_bus)
207                 return TRUE;
208
209         /* Check the UID of the sender */
210         ret = g_dbus_connection_call_sync (priv->bus,
211                                            DBUS_SERVICE_DBUS,
212                                            DBUS_PATH_DBUS,
213                                            DBUS_INTERFACE_DBUS,
214                                            "GetConnectionUnixUser",
215                                            g_variant_new ("(s)", sender),
216                                            G_VARIANT_TYPE ("(u)"),
217                                            G_DBUS_CALL_FLAGS_NONE, -1,
218                                            NULL, &local);
219         if (!ret) {
220                 char *remote_error = g_dbus_error_get_remote_error (local);
221
222                 g_dbus_error_strip_remote_error (local);
223                 g_set_error (error,
224                              NM_SECRET_AGENT_ERROR,
225                              NM_SECRET_AGENT_ERROR_PERMISSION_DENIED,
226                              "Failed to request unix user: (%s) %s.",
227                              remote_error ? remote_error : "",
228                              local->message);
229                 g_free (remote_error);
230                 g_error_free (local);
231                 return FALSE;
232         }
233         g_variant_get (ret, "(u)", &sender_uid);
234         g_variant_unref (ret);
235
236         /* We only accept requests from NM, which always runs as root */
237         if (0 != sender_uid) {
238                 g_set_error_literal (error,
239                                      NM_SECRET_AGENT_ERROR,
240                                      NM_SECRET_AGENT_ERROR_PERMISSION_DENIED,
241                                      "Request sender is not root.");
242                 return FALSE;
243         }
244
245         return TRUE;
246 }
247
248 static gboolean
249 verify_request (NMSecretAgentOld *self,
250                 GDBusMethodInvocation *context,
251                 GVariant *connection_dict,
252                 const char *connection_path,
253                 NMConnection **out_connection,
254                 GError **error)
255 {
256         NMConnection *connection = NULL;
257         GError *local = NULL;
258
259         if (!verify_sender (self, context, error))
260                 return FALSE;
261
262         /* No connection?  If the sender verified, then we allow the request */
263         if (connection_dict == NULL)
264                 return TRUE;
265
266         /* If we have a connection dictionary, we require a path too */
267         if (connection_path == NULL) {
268                 g_set_error_literal (error,
269                                      NM_SECRET_AGENT_ERROR,
270                                      NM_SECRET_AGENT_ERROR_INVALID_CONNECTION,
271                                      "Invalid connection: no connection path given.");
272                 return FALSE;
273         }
274
275         /* Make sure the given connection is valid */
276         g_assert (out_connection);
277         connection = _nm_simple_connection_new_from_dbus (connection_dict, NM_SETTING_PARSE_FLAGS_BEST_EFFORT, &local);
278         if (connection) {
279                 nm_connection_set_path (connection, connection_path);
280                 *out_connection = connection;
281         } else {
282                 g_set_error (error,
283                              NM_SECRET_AGENT_ERROR,
284                              NM_SECRET_AGENT_ERROR_INVALID_CONNECTION,
285                              "Invalid connection: %s", local->message);
286                 g_clear_error (&local);
287         }
288
289         return !!connection;
290 }
291
292 static void
293 get_secrets_cb (NMSecretAgentOld *self,
294                 NMConnection *connection,
295                 GVariant *secrets,
296                 GError *error,
297                 gpointer user_data)
298 {
299         GetSecretsInfo *info = user_data;
300
301         if (error)
302                 g_dbus_method_invocation_return_gerror (info->context, error);
303         else {
304                 g_variant_take_ref (secrets);
305                 g_dbus_method_invocation_return_value (info->context,
306                                                        g_variant_new ("(@a{sa{sv}})", secrets));
307         }
308
309         /* Remove the request from internal tracking */
310         get_secrets_info_finalize (self, info);
311 }
312
313 static void
314 impl_secret_agent_old_get_secrets (NMSecretAgentOld *self,
315                                    GDBusMethodInvocation *context,
316                                    GVariant *connection_dict,
317                                    const char *connection_path,
318                                    const char *setting_name,
319                                    const char * const *hints,
320                                    guint flags,
321                                    gpointer user_data)
322 {
323         NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
324         GError *error = NULL;
325         NMConnection *connection = NULL;
326         GetSecretsInfo *info;
327
328         /* Make sure the request comes from NetworkManager and is valid */
329         if (!verify_request (self, context, connection_dict, connection_path, &connection, &error)) {
330                 g_dbus_method_invocation_take_error (context, error);
331                 return;
332         }
333
334         info = g_malloc0 (sizeof (GetSecretsInfo));
335         info->path = g_strdup (connection_path);
336         info->setting_name = g_strdup (setting_name);
337         info->context = context;
338         priv->pending_gets = g_slist_append (priv->pending_gets, info);
339
340         NM_SECRET_AGENT_OLD_GET_CLASS (self)->get_secrets (self,
341                                                        connection,
342                                                        connection_path,
343                                                        setting_name,
344                                                        (const char **) hints,
345                                                        flags,
346                                                        get_secrets_cb,
347                                                        info);
348         g_object_unref (connection);
349 }
350
351 static GetSecretsInfo *
352 find_get_secrets_info (GSList *list, const char *path, const char *setting_name)
353 {
354         GSList *iter;
355
356         for (iter = list; iter; iter = g_slist_next (iter)) {
357                 GetSecretsInfo *candidate = iter->data;
358
359                 if (   g_strcmp0 (path, candidate->path) == 0
360                     && g_strcmp0 (setting_name, candidate->setting_name) == 0)
361                         return candidate;
362         }
363         return NULL;
364 }
365
366 static void
367 impl_secret_agent_old_cancel_get_secrets (NMSecretAgentOld *self,
368                                           GDBusMethodInvocation *context,
369                                           const char *connection_path,
370                                           const char *setting_name,
371                                           gpointer user_data)
372 {
373         NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
374         GError *error = NULL;
375         GetSecretsInfo *info;
376
377         /* Make sure the request comes from NetworkManager and is valid */
378         if (!verify_request (self, context, NULL, NULL, NULL, &error)) {
379                 g_dbus_method_invocation_take_error (context, error);
380                 return;
381         }
382
383         info = find_get_secrets_info (priv->pending_gets, connection_path, setting_name);
384         if (!info) {
385                 g_dbus_method_invocation_return_error (context,
386                                                        NM_SECRET_AGENT_ERROR,
387                                                        NM_SECRET_AGENT_ERROR_FAILED,
388                                                        "No secrets request in progress for this connection.");
389                 return;
390         }
391
392         /* Send the cancel request up to the subclass and finalize it */
393         NM_SECRET_AGENT_OLD_GET_CLASS (self)->cancel_get_secrets (self,
394                                                               info->path,
395                                                               info->setting_name);
396         g_dbus_method_invocation_return_value (context, NULL);
397 }
398
399 static void
400 save_secrets_cb (NMSecretAgentOld *self,
401                  NMConnection *connection,
402                  GError *error,
403                  gpointer user_data)
404 {
405         GDBusMethodInvocation *context = user_data;
406
407         if (error)
408                 g_dbus_method_invocation_return_gerror (context, error);
409         else
410                 g_dbus_method_invocation_return_value (context, NULL);
411 }
412
413 static void
414 impl_secret_agent_old_save_secrets (NMSecretAgentOld *self,
415                                     GDBusMethodInvocation *context,
416                                     GVariant *connection_dict,
417                                     const char *connection_path,
418                                     gpointer user_data)
419 {
420         GError *error = NULL;
421         NMConnection *connection = NULL;
422
423         /* Make sure the request comes from NetworkManager and is valid */
424         if (!verify_request (self, context, connection_dict, connection_path, &connection, &error)) {
425                 g_dbus_method_invocation_take_error (context, error);
426                 return;
427         }
428
429         NM_SECRET_AGENT_OLD_GET_CLASS (self)->save_secrets (self,
430                                                         connection,
431                                                         connection_path,
432                                                         save_secrets_cb,
433                                                         context);
434         g_object_unref (connection);
435 }
436
437 static void
438 delete_secrets_cb (NMSecretAgentOld *self,
439                    NMConnection *connection,
440                    GError *error,
441                    gpointer user_data)
442 {
443         GDBusMethodInvocation *context = user_data;
444
445         if (error)
446                 g_dbus_method_invocation_return_gerror (context, error);
447         else
448                 g_dbus_method_invocation_return_value (context, NULL);
449 }
450
451 static void
452 impl_secret_agent_old_delete_secrets (NMSecretAgentOld *self,
453                                       GDBusMethodInvocation *context,
454                                       GVariant *connection_dict,
455                                       const char *connection_path,
456                                       gpointer user_data)
457 {
458         GError *error = NULL;
459         NMConnection *connection = NULL;
460
461         /* Make sure the request comes from NetworkManager and is valid */
462         if (!verify_request (self, context, connection_dict, connection_path, &connection, &error)) {
463                 g_dbus_method_invocation_take_error (context, error);
464                 return;
465         }
466
467         NM_SECRET_AGENT_OLD_GET_CLASS (self)->delete_secrets (self,
468                                                           connection,
469                                                           connection_path,
470                                                           delete_secrets_cb,
471                                                           context);
472         g_object_unref (connection);
473 }
474
475 /**************************************************************/
476
477 static gboolean
478 check_nm_running (NMSecretAgentOld *self, GError **error)
479 {
480         NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
481         char *owner;
482
483         if (priv->private_bus)
484                 return TRUE;
485         owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (priv->manager_proxy));
486         if (owner) {
487                 g_free (owner);
488                 return TRUE;
489         }
490
491         g_set_error (error, NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_FAILED,
492                      "NetworkManager is not running");
493         return FALSE;
494 }
495
496 /**************************************************************/
497
498 /**
499  * nm_secret_agent_old_register:
500  * @self: a #NMSecretAgentOld
501  * @cancellable: a #GCancellable, or %NULL
502  * @error: return location for a #GError, or %NULL
503  *
504  * Registers the #NMSecretAgentOld with the NetworkManager secret manager,
505  * indicating to NetworkManager that the agent is able to provide and save
506  * secrets for connections on behalf of its user.
507  *
508  * It is a programmer error to attempt to register an agent that is already
509  * registered, or in the process of registering.
510  *
511  * Returns: %TRUE if registration was successful, %FALSE on error.
512  **/
513 gboolean
514 nm_secret_agent_old_register (NMSecretAgentOld *self,
515                               GCancellable *cancellable,
516                               GError **error)
517 {
518         NMSecretAgentOldPrivate *priv;
519         NMSecretAgentOldClass *class;
520
521         g_return_val_if_fail (NM_IS_SECRET_AGENT_OLD (self), FALSE);
522
523         priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
524
525         g_return_val_if_fail (priv->registered == FALSE, FALSE);
526         g_return_val_if_fail (priv->registering == FALSE, FALSE);
527         g_return_val_if_fail (priv->bus != NULL, FALSE);
528         g_return_val_if_fail (priv->manager_proxy != NULL, FALSE);
529
530         /* Also make sure the subclass can actually respond to secrets requests */
531         class = NM_SECRET_AGENT_OLD_GET_CLASS (self);
532         g_return_val_if_fail (class->get_secrets != NULL, FALSE);
533         g_return_val_if_fail (class->save_secrets != NULL, FALSE);
534         g_return_val_if_fail (class->delete_secrets != NULL, FALSE);
535
536         if (!check_nm_running (self, error))
537                 return FALSE;
538
539         priv->suppress_auto = FALSE;
540
541         /* Export our secret agent interface before registering with the manager */
542         if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (priv->dbus_secret_agent),
543                                                priv->bus,
544                                                NM_DBUS_PATH_SECRET_AGENT,
545                                                error))
546                 return FALSE;
547
548         priv->registering = TRUE;
549         if (nmdbus_agent_manager_call_register_with_capabilities_sync (priv->manager_proxy,
550                                                                        priv->identifier,
551                                                                        priv->capabilities,
552                                                                        cancellable, NULL))
553                 goto success;
554
555         /* Might be an old NetworkManager that doesn't support capabilities;
556          * fall back to old Register() method instead.
557          */
558         if (nmdbus_agent_manager_call_register_sync (priv->manager_proxy,
559                                                      priv->identifier,
560                                                      cancellable, error))
561                 goto success;
562
563         /* Failure */
564         priv->registering = FALSE;
565         _internal_unregister (self);
566         return FALSE;
567
568 success:
569         priv->registering = FALSE;
570         priv->registered = TRUE;
571         g_object_notify (G_OBJECT (self), NM_SECRET_AGENT_OLD_REGISTERED);
572         return TRUE;
573 }
574
575 static void
576 reg_result (NMSecretAgentOld *self, GSimpleAsyncResult *simple, GError *error)
577 {
578         NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
579
580         priv->registering = FALSE;
581
582         if (error) {
583                 g_simple_async_result_take_error (simple, error);
584                 g_simple_async_result_complete (simple);
585
586                 /* If registration failed we shouldn't expose ourselves on the bus */
587                 _internal_unregister (self);
588         } else {
589                 priv->registered = TRUE;
590                 g_object_notify (G_OBJECT (self), NM_SECRET_AGENT_OLD_REGISTERED);
591
592                 g_simple_async_result_set_op_res_gboolean (simple, TRUE);
593                 g_simple_async_result_complete (simple);
594         }
595
596         g_object_unref (simple);
597 }
598
599 static void
600 reg_request_cb (GObject *proxy,
601                 GAsyncResult *result,
602                 gpointer user_data)
603 {
604         GSimpleAsyncResult *simple = user_data;
605         NMSecretAgentOld *self;
606         NMSecretAgentOldPrivate *priv;
607         GError *error = NULL;
608
609         self = NM_SECRET_AGENT_OLD (g_async_result_get_source_object (G_ASYNC_RESULT (simple)));
610         g_object_unref (self); /* drop extra ref added by get_source_object() */
611         priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
612
613         if (!nmdbus_agent_manager_call_register_finish (NMDBUS_AGENT_MANAGER (proxy), result, &error))
614                 g_dbus_error_strip_remote_error (error);
615         reg_result (self, simple, error);
616         g_clear_error (&error);
617 }
618
619 static void
620 reg_with_caps_cb (GObject *proxy,
621                   GAsyncResult *result,
622                   gpointer user_data)
623 {
624         GSimpleAsyncResult *simple = user_data;
625         NMSecretAgentOld *self;
626         NMSecretAgentOldPrivate *priv;
627
628         self = NM_SECRET_AGENT_OLD (g_async_result_get_source_object (G_ASYNC_RESULT (simple)));
629         g_object_unref (self); /* drop extra ref added by get_source_object() */
630         priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
631
632         if (nmdbus_agent_manager_call_register_with_capabilities_finish (NMDBUS_AGENT_MANAGER (proxy), result, NULL)) {
633                 reg_result (self, simple, NULL);
634                 return;
635         }
636
637         /* Might be an old NetworkManager that doesn't support capabilities;
638          * fall back to old Register() method instead.
639          */
640         nmdbus_agent_manager_call_register (priv->manager_proxy,
641                                             priv->identifier,
642                                             NULL, reg_request_cb, simple);
643 }
644
645 /**
646  * nm_secret_agent_old_register_async:
647  * @self: a #NMSecretAgentOld
648  * @cancellable: a #GCancellable, or %NULL
649  * @callback: callback to call when the agent is registered
650  * @user_data: data for @callback
651  *
652  * Asynchronously registers the #NMSecretAgentOld with the NetworkManager secret
653  * manager, indicating to NetworkManager that the agent is able to provide and
654  * save secrets for connections on behalf of its user.
655  *
656  * It is a programmer error to attempt to register an agent that is already
657  * registered, or in the process of registering.
658  **/
659 void
660 nm_secret_agent_old_register_async (NMSecretAgentOld *self,
661                                     GCancellable *cancellable,
662                                     GAsyncReadyCallback callback,
663                                     gpointer user_data)
664 {
665         NMSecretAgentOldPrivate *priv;
666         NMSecretAgentOldClass *class;
667         GSimpleAsyncResult *simple;
668         GError *error = NULL;
669
670         g_return_if_fail (NM_IS_SECRET_AGENT_OLD (self));
671
672         priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
673
674         g_return_if_fail (priv->registered == FALSE);
675         g_return_if_fail (priv->registering == FALSE);
676         g_return_if_fail (priv->bus != NULL);
677         g_return_if_fail (priv->manager_proxy != NULL);
678
679         /* Also make sure the subclass can actually respond to secrets requests */
680         class = NM_SECRET_AGENT_OLD_GET_CLASS (self);
681         g_return_if_fail (class->get_secrets != NULL);
682         g_return_if_fail (class->save_secrets != NULL);
683         g_return_if_fail (class->delete_secrets != NULL);
684
685         simple = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
686                                             nm_secret_agent_old_register_async);
687
688         if (!check_nm_running (self, &error)) {
689                 g_simple_async_result_take_error (simple, error);
690                 g_simple_async_result_complete_in_idle (simple);
691                 g_object_unref (simple);
692                 return;
693         }
694
695         /* Export our secret agent interface before registering with the manager */
696         if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (priv->dbus_secret_agent),
697                                                priv->bus,
698                                                NM_DBUS_PATH_SECRET_AGENT,
699                                                &error)) {
700                 g_simple_async_result_take_error (simple, error);
701                 g_simple_async_result_complete_in_idle (simple);
702                 g_object_unref (simple);
703                 return;
704         }
705
706         priv->suppress_auto = FALSE;
707         priv->registering = TRUE;
708
709         nmdbus_agent_manager_call_register_with_capabilities (priv->manager_proxy,
710                                                               priv->identifier,
711                                                               priv->capabilities,
712                                                               NULL,
713                                                               reg_with_caps_cb, simple);
714 }
715
716 /**
717  * nm_secret_agent_old_register_finish:
718  * @self: a #NMSecretAgentOld
719  * @result: the result passed to the #GAsyncReadyCallback
720  * @error: return location for a #GError, or %NULL
721  *
722  * Gets the result of a call to nm_secret_agent_old_register_async().
723  *
724  * Returns: %TRUE if registration was successful, %FALSE on error.
725  **/
726 gboolean
727 nm_secret_agent_old_register_finish (NMSecretAgentOld *self,
728                                      GAsyncResult *result,
729                                      GError **error)
730 {
731         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self), nm_secret_agent_old_register_async), FALSE);
732
733         if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
734                 return FALSE;
735         else
736                 return TRUE;
737 }
738
739 /**
740  * nm_secret_agent_old_unregister:
741  * @self: a #NMSecretAgentOld
742  * @cancellable: a #GCancellable, or %NULL
743  * @error: return location for a #GError, or %NULL
744  *
745  * Unregisters the #NMSecretAgentOld with the NetworkManager secret manager,
746  * indicating to NetworkManager that the agent will no longer provide or
747  * store secrets on behalf of this user.
748  *
749  * It is a programmer error to attempt to unregister an agent that is not
750  * registered.
751  *
752  * Returns: %TRUE if unregistration was successful, %FALSE on error
753  **/
754 gboolean
755 nm_secret_agent_old_unregister (NMSecretAgentOld *self,
756                                 GCancellable *cancellable,
757                                 GError **error)
758 {
759         NMSecretAgentOldPrivate *priv;
760         gboolean success;
761
762         g_return_val_if_fail (NM_IS_SECRET_AGENT_OLD (self), FALSE);
763
764         priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
765
766         g_return_val_if_fail (priv->registered == TRUE, FALSE);
767         g_return_val_if_fail (priv->bus != NULL, FALSE);
768         g_return_val_if_fail (priv->manager_proxy != NULL, FALSE);
769
770         priv->suppress_auto = TRUE;
771
772         success = nmdbus_agent_manager_call_unregister_sync (priv->manager_proxy, cancellable, error);
773         if (error && *error)
774                 g_dbus_error_strip_remote_error (*error);
775         _internal_unregister (self);
776
777         return success;
778 }
779
780 static void
781 unregister_cb (GObject *proxy, GAsyncResult *result, gpointer user_data)
782 {
783         GSimpleAsyncResult *simple = user_data;
784         NMSecretAgentOld *self;
785         GError *error = NULL;
786
787         self = NM_SECRET_AGENT_OLD (g_async_result_get_source_object (G_ASYNC_RESULT (simple)));
788         g_object_unref (self); /* drop extra ref added by get_source_object() */
789
790         _internal_unregister (self);
791
792         if (nmdbus_agent_manager_call_unregister_finish (NMDBUS_AGENT_MANAGER (proxy),
793                                                          result, &error))
794                 g_simple_async_result_set_op_res_gboolean (simple, TRUE);
795         else {
796                 g_dbus_error_strip_remote_error (error);
797                 g_simple_async_result_take_error (simple, error);
798         }
799
800         g_simple_async_result_complete (simple);
801         g_object_unref (simple);
802 }
803
804 /**
805  * nm_secret_agent_old_unregister_async:
806  * @self: a #NMSecretAgentOld
807  * @cancellable: a #GCancellable, or %NULL
808  * @callback: callback to call when the agent is unregistered
809  * @user_data: data for @callback
810  *
811  * Asynchronously unregisters the #NMSecretAgentOld with the NetworkManager secret
812  * manager, indicating to NetworkManager that the agent will no longer provide
813  * or store secrets on behalf of this user.
814  *
815  * It is a programmer error to attempt to unregister an agent that is not
816  * registered.
817  **/
818 void
819 nm_secret_agent_old_unregister_async (NMSecretAgentOld *self,
820                                       GCancellable *cancellable,
821                                       GAsyncReadyCallback callback,
822                                       gpointer user_data)
823 {
824         NMSecretAgentOldPrivate *priv;
825         GSimpleAsyncResult *simple;
826         GError *error = NULL;
827
828         g_return_if_fail (NM_IS_SECRET_AGENT_OLD (self));
829
830         priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
831
832         g_return_if_fail (priv->registered == TRUE);
833         g_return_if_fail (priv->bus != NULL);
834         g_return_if_fail (priv->manager_proxy != NULL);
835
836         simple = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
837                                             nm_secret_agent_old_unregister_async);
838
839         if (!check_nm_running (self, &error)) {
840                 g_simple_async_result_take_error (simple, error);
841                 g_simple_async_result_complete_in_idle (simple);
842                 g_object_unref (simple);
843                 return;
844         }
845
846         priv->suppress_auto = TRUE;
847
848         nmdbus_agent_manager_call_unregister (priv->manager_proxy, cancellable,
849                                               unregister_cb, simple);
850 }
851
852 /**
853  * nm_secret_agent_old_unregister_finish:
854  * @self: a #NMSecretAgentOld
855  * @result: the result passed to the #GAsyncReadyCallback
856  * @error: return location for a #GError, or %NULL
857  *
858  * Gets the result of a call to nm_secret_agent_old_unregister_async().
859  *
860  * Returns: %TRUE if unregistration was successful, %FALSE on error.
861  **/
862 gboolean
863 nm_secret_agent_old_unregister_finish (NMSecretAgentOld *self,
864                                        GAsyncResult *result,
865                                        GError **error)
866 {
867         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self), nm_secret_agent_old_unregister_async), FALSE);
868
869         if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
870                 return FALSE;
871         else
872                 return TRUE;
873 }
874
875 /**
876  * nm_secret_agent_old_get_registered:
877  * @self: a #NMSecretAgentOld
878  *
879  * Returns: a %TRUE if the agent is registered, %FALSE if it is not.
880  **/
881 gboolean
882 nm_secret_agent_old_get_registered (NMSecretAgentOld *self)
883 {
884         g_return_val_if_fail (NM_IS_SECRET_AGENT_OLD (self), FALSE);
885
886         return NM_SECRET_AGENT_OLD_GET_PRIVATE (self)->registered;
887 }
888
889 /**************************************************************/
890
891 /**
892  * nm_secret_agent_old_get_secrets:
893  * @self: a #NMSecretAgentOld
894  * @connection: the #NMConnection for which we're asked secrets
895  * @setting_name: the name of the secret setting
896  * @hints: (array zero-terminated=1): hints to the agent
897  * @flags: flags that modify the behavior of the request
898  * @callback: (scope async): a callback, to be invoked when the operation is done
899  * @user_data: (closure): caller-specific data to be passed to @callback
900  *
901  * Asynchronously retrieves secrets belonging to @connection for the
902  * setting @setting_name.  @flags indicate specific behavior that the secret
903  * agent should use when performing the request, for example returning only
904  * existing secrets without user interaction, or requesting entirely new
905  * secrets from the user.
906  *
907  * Virtual: get_secrets
908  */
909 void
910 nm_secret_agent_old_get_secrets (NMSecretAgentOld *self,
911                                  NMConnection *connection,
912                                  const char *setting_name,
913                                  const char **hints,
914                                  NMSecretAgentGetSecretsFlags flags,
915                                  NMSecretAgentOldGetSecretsFunc callback,
916                                  gpointer user_data)
917 {
918         g_return_if_fail (NM_IS_SECRET_AGENT_OLD (self));
919         g_return_if_fail (NM_IS_CONNECTION (connection));
920         g_return_if_fail (nm_connection_get_path (connection));
921         g_return_if_fail (setting_name != NULL);
922         g_return_if_fail (strlen (setting_name) > 0);
923         g_return_if_fail (!(flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_ONLY_SYSTEM));
924         g_return_if_fail (!(flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_NO_ERRORS));
925         g_return_if_fail (callback != NULL);
926
927         NM_SECRET_AGENT_OLD_GET_CLASS (self)->get_secrets (self,
928                                                        connection,
929                                                        nm_connection_get_path (connection),
930                                                        setting_name,
931                                                        hints,
932                                                        flags,
933                                                        callback,
934                                                        user_data);
935 }
936
937 /**
938  * nm_secret_agent_old_save_secrets:
939  * @self: a #NMSecretAgentOld
940  * @connection: a #NMConnection
941  * @callback: (scope async): a callback, to be invoked when the operation is done
942  * @user_data: (closure): caller-specific data to be passed to @callback
943  *
944  * Asynchronously ensures that all secrets inside @connection are stored to
945  * disk.
946  *
947  * Virtual: save_secrets
948  */
949 void
950 nm_secret_agent_old_save_secrets (NMSecretAgentOld *self,
951                                   NMConnection *connection,
952                                   NMSecretAgentOldSaveSecretsFunc callback,
953                                   gpointer user_data)
954 {
955         g_return_if_fail (NM_IS_SECRET_AGENT_OLD (self));
956         g_return_if_fail (NM_IS_CONNECTION (connection));
957         g_return_if_fail (nm_connection_get_path (connection));
958
959         NM_SECRET_AGENT_OLD_GET_CLASS (self)->save_secrets (self,
960                                                         connection,
961                                                         nm_connection_get_path (connection),
962                                                         callback,
963                                                         user_data);
964 }
965
966 /**
967  * nm_secret_agent_old_delete_secrets:
968  * @self: a #NMSecretAgentOld
969  * @connection: a #NMConnection
970  * @callback: (scope async): a callback, to be invoked when the operation is done
971  * @user_data: (closure): caller-specific data to be passed to @callback
972  *
973  * Asynchronously asks the agent to delete all saved secrets belonging to
974  * @connection.
975  *
976  * Virtual: delete_secrets
977  */
978 void
979 nm_secret_agent_old_delete_secrets (NMSecretAgentOld *self,
980                                     NMConnection *connection,
981                                     NMSecretAgentOldDeleteSecretsFunc callback,
982                                     gpointer user_data)
983 {
984         g_return_if_fail (NM_IS_SECRET_AGENT_OLD (self));
985         g_return_if_fail (NM_IS_CONNECTION (connection));
986         g_return_if_fail (nm_connection_get_path (connection));
987
988         NM_SECRET_AGENT_OLD_GET_CLASS (self)->delete_secrets (self,
989                                                           connection,
990                                                           nm_connection_get_path (connection),
991                                                           callback,
992                                                           user_data);
993 }
994
995 /**************************************************************/
996
997 static gboolean
998 validate_identifier (const char *identifier)
999 {
1000         const char *p = identifier;
1001         size_t id_len;
1002
1003         /* Length between 3 and 255 characters inclusive */
1004         id_len = strlen (identifier);
1005         if (id_len < 3 || id_len > 255)
1006                 return FALSE;
1007
1008         if ((identifier[0] == '.') || (identifier[id_len - 1] == '.'))
1009                 return FALSE;
1010
1011         /* FIXME: do complete validation here */
1012         while (p && *p) {
1013                 if (!g_ascii_isalnum (*p) && (*p != '_') && (*p != '-') && (*p != '.'))
1014                         return FALSE;
1015                 if ((*p == '.') && (*(p + 1) == '.'))
1016                         return FALSE;
1017                 p++;
1018         }
1019
1020         return TRUE;
1021 }
1022
1023 static void
1024 nm_secret_agent_old_init (NMSecretAgentOld *self)
1025 {
1026         NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
1027
1028         priv->dbus_secret_agent = nmdbus_secret_agent_skeleton_new ();
1029         _nm_dbus_bind_properties (self, priv->dbus_secret_agent);
1030         _nm_dbus_bind_methods (self, priv->dbus_secret_agent,
1031                                "GetSecrets", impl_secret_agent_old_get_secrets,
1032                                "CancelGetSecrets", impl_secret_agent_old_cancel_get_secrets,
1033                                "DeleteSecrets", impl_secret_agent_old_delete_secrets,
1034                                "SaveSecrets", impl_secret_agent_old_save_secrets,
1035                                NULL);
1036 }
1037
1038 static void
1039 init_common (NMSecretAgentOld *self)
1040 {
1041         NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
1042
1043         priv->private_bus = _nm_dbus_is_connection_private (priv->bus);
1044
1045         if (priv->private_bus == FALSE) {
1046                 priv->session_bus = _nm_dbus_bus_type () == G_BUS_TYPE_SESSION;
1047
1048                 g_signal_connect (priv->manager_proxy, "notify::g-name-owner",
1049                                   G_CALLBACK (name_owner_changed), self);
1050         }
1051 }
1052
1053 static gboolean
1054 init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
1055 {
1056         NMSecretAgentOld *self = NM_SECRET_AGENT_OLD (initable);
1057         NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
1058         GDBusProxy *proxy;
1059
1060         priv->bus = _nm_dbus_new_connection (cancellable, error);
1061         if (!priv->bus)
1062                 return FALSE;
1063
1064         proxy = _nm_dbus_new_proxy_for_connection (priv->bus,
1065                                                    NM_DBUS_PATH_AGENT_MANAGER,
1066                                                    NM_DBUS_INTERFACE_AGENT_MANAGER,
1067                                                    cancellable, error);
1068         if (!proxy)
1069                 return FALSE;
1070         priv->manager_proxy = NMDBUS_AGENT_MANAGER (proxy);
1071
1072         init_common (self);
1073
1074         if (priv->auto_register)
1075                 return nm_secret_agent_old_register (self, cancellable, error);
1076         else
1077                 return TRUE;
1078 }
1079
1080 typedef struct {
1081         NMSecretAgentOld *self;
1082         GCancellable *cancellable;
1083         GSimpleAsyncResult *simple;
1084 } NMSecretAgentOldInitData;
1085
1086 static void
1087 init_async_complete (NMSecretAgentOldInitData *init_data, GError *error)
1088 {
1089         if (!error)
1090                 g_simple_async_result_set_op_res_gboolean (init_data->simple, TRUE);
1091         else
1092                 g_simple_async_result_take_error (init_data->simple, error);
1093
1094         g_simple_async_result_complete_in_idle (init_data->simple);
1095
1096         g_object_unref (init_data->simple);
1097         g_clear_object (&init_data->cancellable);
1098         g_slice_free (NMSecretAgentOldInitData, init_data);
1099 }
1100
1101 static void
1102 init_async_registered (GObject *object, GAsyncResult *result, gpointer user_data)
1103 {
1104         NMSecretAgentOld *self = NM_SECRET_AGENT_OLD (object);
1105         NMSecretAgentOldInitData *init_data = user_data;
1106         GError *error = NULL;
1107
1108         nm_secret_agent_old_register_finish (self, result, &error);
1109         init_async_complete (init_data, error);
1110 }
1111
1112 static void
1113 init_async_got_proxy (GObject *object, GAsyncResult *result, gpointer user_data)
1114 {
1115         NMSecretAgentOldInitData *init_data = user_data;
1116         NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (init_data->self);
1117         GDBusProxy *proxy;
1118         GError *error = NULL;
1119
1120         proxy = _nm_dbus_new_proxy_for_connection_finish (result, &error);
1121         if (!proxy) {
1122                 init_async_complete (init_data, error);
1123                 return;
1124         }
1125         priv->manager_proxy = NMDBUS_AGENT_MANAGER (proxy);
1126
1127         init_common (init_data->self);
1128
1129         if (priv->auto_register) {
1130                 nm_secret_agent_old_register_async (init_data->self, init_data->cancellable,
1131                                                 init_async_registered, init_data);
1132         } else
1133                 init_async_complete (init_data, NULL);
1134 }
1135
1136 static void
1137 init_async_got_bus (GObject *initable, GAsyncResult *result, gpointer user_data)
1138 {
1139         NMSecretAgentOldInitData *init_data = user_data;
1140         NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (init_data->self);
1141         GError *error = NULL;
1142
1143         priv->bus = _nm_dbus_new_connection_finish (result, &error);
1144         if (!priv->bus) {
1145                 init_async_complete (init_data, error);
1146                 return;
1147         }
1148
1149         _nm_dbus_new_proxy_for_connection_async (priv->bus,
1150                                                  NM_DBUS_PATH_AGENT_MANAGER,
1151                                                  NM_DBUS_INTERFACE_AGENT_MANAGER,
1152                                                  init_data->cancellable,
1153                                                  init_async_got_proxy, init_data);
1154 }
1155
1156 static void
1157 init_async (GAsyncInitable *initable, int io_priority,
1158             GCancellable *cancellable, GAsyncReadyCallback callback,
1159             gpointer user_data)
1160 {
1161         NMSecretAgentOld *self = NM_SECRET_AGENT_OLD (initable);
1162         NMSecretAgentOldInitData *init_data;
1163
1164         init_data = g_slice_new (NMSecretAgentOldInitData);
1165         init_data->self = self;
1166         init_data->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
1167
1168         init_data->simple = g_simple_async_result_new (G_OBJECT (initable), callback,
1169                                                        user_data, init_async);
1170
1171         _nm_dbus_new_connection_async (cancellable, init_async_got_bus, init_data);
1172 }
1173
1174 static gboolean
1175 init_finish (GAsyncInitable *initable, GAsyncResult *result, GError **error)
1176 {
1177         GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
1178
1179         if (g_simple_async_result_propagate_error (simple, error))
1180                 return FALSE;
1181         else
1182                 return TRUE;
1183 }
1184
1185 static void
1186 get_property (GObject *object,
1187               guint prop_id,
1188               GValue *value,
1189               GParamSpec *pspec)
1190 {
1191         NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (object);
1192
1193         switch (prop_id) {
1194         case PROP_IDENTIFIER:
1195                 g_value_set_string (value, priv->identifier);
1196                 break;
1197         case PROP_AUTO_REGISTER:
1198                 g_value_set_boolean (value, priv->auto_register);
1199                 break;
1200         case PROP_REGISTERED:
1201                 g_value_set_boolean (value, priv->registered);
1202                 break;
1203         case PROP_CAPABILITIES:
1204                 g_value_set_flags (value, priv->capabilities);
1205                 break;
1206         default:
1207                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1208                 break;
1209         }
1210 }
1211
1212 static void
1213 set_property (GObject *object,
1214               guint prop_id,
1215               const GValue *value,
1216               GParamSpec *pspec)
1217 {
1218         NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (object);
1219         const char *identifier;
1220
1221         switch (prop_id) {
1222         case PROP_IDENTIFIER:
1223                 identifier = g_value_get_string (value);
1224
1225                 g_return_if_fail (validate_identifier (identifier));
1226
1227                 g_free (priv->identifier);
1228                 priv->identifier = g_strdup (identifier);
1229                 break;
1230         case PROP_AUTO_REGISTER:
1231                 priv->auto_register = g_value_get_boolean (value);
1232                 break;
1233         case PROP_CAPABILITIES:
1234                 priv->capabilities = g_value_get_flags (value);
1235                 break;
1236         default:
1237                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1238                 break;
1239         }
1240 }
1241
1242 static void
1243 dispose (GObject *object)
1244 {
1245         NMSecretAgentOld *self = NM_SECRET_AGENT_OLD (object);
1246         NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
1247
1248         if (priv->registered)
1249                 nm_secret_agent_old_unregister_async (self, NULL, NULL, NULL);
1250
1251         g_clear_pointer (&priv->identifier, g_free);
1252
1253         while (priv->pending_gets)
1254                 get_secrets_info_finalize (self, priv->pending_gets->data);
1255
1256         g_signal_handlers_disconnect_matched (priv->dbus_secret_agent, G_SIGNAL_MATCH_DATA,
1257                                               0, 0, NULL, NULL, self);
1258         g_object_unref (priv->dbus_secret_agent);
1259
1260         g_clear_object (&priv->manager_proxy);
1261         g_clear_object (&priv->bus);
1262
1263         G_OBJECT_CLASS (nm_secret_agent_old_parent_class)->dispose (object);
1264 }
1265
1266 static void
1267 nm_secret_agent_old_class_init (NMSecretAgentOldClass *class)
1268 {
1269         GObjectClass *object_class = G_OBJECT_CLASS (class);
1270
1271         g_type_class_add_private (class, sizeof (NMSecretAgentOldPrivate));
1272
1273         /* Virtual methods */
1274         object_class->dispose = dispose;
1275         object_class->get_property = get_property;
1276         object_class->set_property = set_property;
1277
1278         /**
1279          * NMSecretAgentOld:identifier:
1280          *
1281          * Identifies this agent; only one agent in each user session may use the
1282          * same identifier.  Identifier formatting follows the same rules as
1283          * D-Bus bus names with the exception that the ':' character is not
1284          * allowed.  The valid set of characters is "[A-Z][a-z][0-9]_-." and the
1285          * identifier is limited in length to 255 characters with a minimum
1286          * of 3 characters.  An example valid identifier is 'org.gnome.nm-applet'
1287          * (without quotes).
1288          **/
1289         g_object_class_install_property
1290                 (object_class, PROP_IDENTIFIER,
1291                  g_param_spec_string (NM_SECRET_AGENT_OLD_IDENTIFIER, "", "",
1292                                       NULL,
1293                                       G_PARAM_READWRITE |
1294                                       G_PARAM_CONSTRUCT_ONLY |
1295                                       G_PARAM_STATIC_STRINGS));
1296
1297         /**
1298          * NMSecretAgentOld:auto-register:
1299          *
1300          * If %TRUE (the default), the agent will always be registered when
1301          * NetworkManager is running; if NetworkManager exits and restarts, the
1302          * agent will re-register itself automatically.
1303          *
1304          * In particular, if this property is %TRUE at construct time, then the
1305          * agent will register itself with NetworkManager during
1306          * construction/initialization, and initialization will fail with an error
1307          * if the agent is unable to register itself.
1308          *
1309          * If the property is %FALSE, the agent will not automatically register with
1310          * NetworkManager, and nm_secret_agent_old_register() or
1311          * nm_secret_agent_old_register_async() must be called to register it.
1312          *
1313          * Calling nm_secret_agent_old_unregister() will suppress auto-registration
1314          * until nm_secret_agent_old_register() is called, which re-enables
1315          * auto-registration. This ensures that the agent remains un-registered when
1316          * you expect it to be unregistered.
1317          **/
1318         g_object_class_install_property
1319                 (object_class, PROP_AUTO_REGISTER,
1320                  g_param_spec_boolean (NM_SECRET_AGENT_OLD_AUTO_REGISTER, "", "",
1321                                        TRUE,
1322                                        G_PARAM_READWRITE |
1323                                        G_PARAM_CONSTRUCT |
1324                                        G_PARAM_STATIC_STRINGS));
1325
1326         /**
1327          * NMSecretAgentOld:registered:
1328          *
1329          * %TRUE if the agent is registered with NetworkManager, %FALSE if not.
1330          **/
1331         g_object_class_install_property
1332                 (object_class, PROP_REGISTERED,
1333                  g_param_spec_boolean (NM_SECRET_AGENT_OLD_REGISTERED, "", "",
1334                                        FALSE,
1335                                        G_PARAM_READABLE |
1336                                        G_PARAM_STATIC_STRINGS));
1337
1338         /**
1339          * NMSecretAgentOld:capabilities:
1340          *
1341          * A bitfield of %NMSecretAgentCapabilities.
1342          **/
1343         g_object_class_install_property
1344                 (object_class, PROP_CAPABILITIES,
1345                  g_param_spec_flags (NM_SECRET_AGENT_OLD_CAPABILITIES, "", "",
1346                                      NM_TYPE_SECRET_AGENT_CAPABILITIES,
1347                                      NM_SECRET_AGENT_CAPABILITY_NONE,
1348                                      G_PARAM_READWRITE |
1349                                      G_PARAM_CONSTRUCT |
1350                                      G_PARAM_STATIC_STRINGS));
1351
1352         _nm_dbus_register_proxy_type (NM_DBUS_INTERFACE_AGENT_MANAGER,
1353                                       NMDBUS_TYPE_AGENT_MANAGER_PROXY);
1354 }
1355
1356 static void
1357 nm_secret_agent_old_initable_iface_init (GInitableIface *iface)
1358 {
1359         iface->init = init_sync;
1360 }
1361
1362 static void
1363 nm_secret_agent_old_async_initable_iface_init (GAsyncInitableIface *iface)
1364 {
1365         iface->init_async = init_async;
1366         iface->init_finish = init_finish;
1367 }