1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
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.
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.
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.
18 * Copyright 2010 - 2011 Red Hat, Inc.
21 #include "nm-default.h"
24 #include <dbus/dbus-glib-lowlevel.h>
26 #include "NetworkManager.h"
27 #include "nm-secret-agent.h"
28 #include "nm-glib-enum-types.h"
29 #include "nm-dbus-helpers-private.h"
31 static void impl_secret_agent_get_secrets (NMSecretAgent *self,
32 GHashTable *connection_hash,
33 const char *connection_path,
34 const char *setting_name,
37 DBusGMethodInvocation *context);
39 static void impl_secret_agent_cancel_get_secrets (NMSecretAgent *self,
40 const char *connection_path,
41 const char *setting_name,
42 DBusGMethodInvocation *context);
44 static void impl_secret_agent_save_secrets (NMSecretAgent *self,
45 GHashTable *connection_hash,
46 const char *connection_path,
47 DBusGMethodInvocation *context);
49 static void impl_secret_agent_delete_secrets (NMSecretAgent *self,
50 GHashTable *connection_hash,
51 const char *connection_path,
52 DBusGMethodInvocation *context);
54 #include "nm-secret-agent-glue.h"
56 G_DEFINE_ABSTRACT_TYPE (NMSecretAgent, nm_secret_agent, G_TYPE_OBJECT)
58 #define NM_SECRET_AGENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SECRET_AGENT, NMSecretAgentPrivate))
60 static gboolean auto_register_cb (gpointer user_data);
64 NMSecretAgentCapabilities capabilities;
67 DBusGProxy *dbus_proxy;
68 DBusGProxy *manager_proxy;
69 DBusGProxyCall *reg_call;
71 /* GetSecretsInfo structs of in-flight GetSecrets requests */
77 gboolean auto_register;
78 gboolean suppress_auto;
79 gboolean auto_register_id;
80 } NMSecretAgentPrivate;
98 static guint signals[LAST_SIGNAL] = { 0 };
101 /********************************************************************/
104 nm_secret_agent_error_quark (void)
106 static GQuark ret = 0;
108 if (G_UNLIKELY (ret == 0))
109 ret = g_quark_from_static_string ("nm-secret-agent-error");
113 /*************************************************************/
116 get_nm_owner (NMSecretAgent *self)
118 NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
119 GError *error = NULL;
122 if (!priv->nm_owner) {
123 if (!dbus_g_proxy_call_with_timeout (priv->dbus_proxy,
124 "GetNameOwner", 2000, &error,
125 G_TYPE_STRING, NM_DBUS_SERVICE,
127 G_TYPE_STRING, &owner,
131 priv->nm_owner = g_strdup (owner);
135 return priv->nm_owner;
139 _internal_unregister (NMSecretAgent *self)
141 NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
143 if (priv->registered) {
144 dbus_g_connection_unregister_g_object (priv->bus, G_OBJECT (self));
145 priv->registered = FALSE;
146 g_object_notify (G_OBJECT (self), NM_SECRET_AGENT_REGISTERED);
153 DBusGMethodInvocation *context;
157 get_secrets_info_finalize (NMSecretAgent *self, GetSecretsInfo *info)
159 NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
161 g_return_if_fail (info != NULL);
163 priv->pending_gets = g_slist_remove (priv->pending_gets, info);
166 g_free (info->setting_name);
167 memset (info, 0, sizeof (*info));
172 name_owner_changed (DBusGProxy *proxy,
174 const char *old_owner,
175 const char *new_owner,
178 NMSecretAgent *self = NM_SECRET_AGENT (user_data);
179 NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
180 gboolean old_owner_good = (old_owner && strlen (old_owner));
181 gboolean new_owner_good = (new_owner && strlen (new_owner));
184 if (strcmp (name, NM_DBUS_SERVICE) == 0) {
185 g_free (priv->nm_owner);
186 priv->nm_owner = g_strdup (new_owner);
188 if (!old_owner_good && new_owner_good) {
190 auto_register_cb (self);
191 } else if (old_owner_good && !new_owner_good) {
192 /* Cancel any pending secrets requests */
193 for (iter = priv->pending_gets; iter; iter = g_slist_next (iter)) {
194 GetSecretsInfo *info = iter->data;
196 NM_SECRET_AGENT_GET_CLASS (self)->cancel_get_secrets (self,
200 g_slist_free (priv->pending_gets);
201 priv->pending_gets = NULL;
204 _internal_unregister (self);
205 } else if (old_owner_good && new_owner_good && strcmp (old_owner, new_owner)) {
206 /* Hmm, NM magically restarted */
207 _internal_unregister (self);
208 auto_register_cb (self);
214 verify_sender (NMSecretAgent *self,
215 DBusGMethodInvocation *context,
218 NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
221 const char *nm_owner;
222 DBusError dbus_error;
223 uid_t sender_uid = G_MAXUINT;
224 gboolean allowed = FALSE;
226 g_return_val_if_fail (context != NULL, FALSE);
228 /* Verify the sender's UID is 0, and that the sender is the same as
229 * NetworkManager's bus name owner.
232 nm_owner = get_nm_owner (self);
234 g_set_error_literal (error,
235 NM_SECRET_AGENT_ERROR,
236 NM_SECRET_AGENT_ERROR_NOT_AUTHORIZED,
237 "NetworkManager bus name owner unknown.");
241 bus = dbus_g_connection_get_connection (priv->bus);
243 g_set_error_literal (error,
244 NM_SECRET_AGENT_ERROR,
245 NM_SECRET_AGENT_ERROR_NOT_AUTHORIZED,
246 "Failed to get DBus connection.");
250 sender = dbus_g_method_get_sender (context);
252 g_set_error_literal (error,
253 NM_SECRET_AGENT_ERROR,
254 NM_SECRET_AGENT_ERROR_NOT_AUTHORIZED,
255 "Failed to get request sender.");
259 /* Check that the sender matches the current NM bus name owner */
260 if (strcmp (sender, nm_owner) != 0) {
261 g_set_error_literal (error,
262 NM_SECRET_AGENT_ERROR,
263 NM_SECRET_AGENT_ERROR_NOT_AUTHORIZED,
264 "Request sender does not match NetworkManager bus name owner.");
268 dbus_error_init (&dbus_error);
269 sender_uid = dbus_bus_get_unix_user (bus, sender, &dbus_error);
270 if (dbus_error_is_set (&dbus_error)) {
272 NM_SECRET_AGENT_ERROR,
273 NM_SECRET_AGENT_ERROR_NOT_AUTHORIZED,
274 "Failed to get request unix user: (%s) %s.",
275 dbus_error.name, dbus_error.message);
276 dbus_error_free (&dbus_error);
280 /* We only accept requests from NM, which always runs as root */
281 if (0 != sender_uid) {
282 g_set_error_literal (error,
283 NM_SECRET_AGENT_ERROR,
284 NM_SECRET_AGENT_ERROR_NOT_AUTHORIZED,
285 "Request sender is not root.");
297 verify_request (NMSecretAgent *self,
298 DBusGMethodInvocation *context,
299 GHashTable *connection_hash,
300 const char *connection_path,
301 NMConnection **out_connection,
304 NMConnection *connection = NULL;
305 GError *local = NULL;
307 if (!verify_sender (self, context, error))
310 /* No connection? If the sender verified, then we allow the request */
311 if (connection_hash == NULL)
314 /* If we have a connection hash, we require a path too */
315 if (connection_path == NULL) {
316 g_set_error_literal (error,
317 NM_SECRET_AGENT_ERROR,
318 NM_SECRET_AGENT_ERROR_INVALID_CONNECTION,
319 "Invalid connection: no connection path given.");
323 /* Make sure the given connection is valid */
324 g_assert (out_connection);
325 connection = nm_connection_new_from_hash (connection_hash, &local);
327 nm_connection_set_path (connection, connection_path);
328 *out_connection = connection;
331 NM_SECRET_AGENT_ERROR,
332 NM_SECRET_AGENT_ERROR_INVALID_CONNECTION,
333 "Invalid connection: %s",
335 g_clear_error (&local);
342 get_secrets_cb (NMSecretAgent *self,
343 NMConnection *connection,
348 GetSecretsInfo *info = user_data;
351 dbus_g_method_return_error (info->context, error);
353 dbus_g_method_return (info->context, secrets);
355 /* Remove the request from internal tracking */
356 get_secrets_info_finalize (self, info);
360 impl_secret_agent_get_secrets (NMSecretAgent *self,
361 GHashTable *connection_hash,
362 const char *connection_path,
363 const char *setting_name,
366 DBusGMethodInvocation *context)
368 NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
369 GError *error = NULL;
370 NMConnection *connection = NULL;
371 GetSecretsInfo *info;
373 /* Make sure the request comes from NetworkManager and is valid */
374 if (!verify_request (self, context, connection_hash, connection_path, &connection, &error)) {
375 dbus_g_method_return_error (context, error);
376 g_clear_error (&error);
380 info = g_malloc0 (sizeof (GetSecretsInfo));
381 info->path = g_strdup (connection_path);
382 info->setting_name = g_strdup (setting_name);
383 info->context = context;
384 priv->pending_gets = g_slist_append (priv->pending_gets, info);
386 NM_SECRET_AGENT_GET_CLASS (self)->get_secrets (self,
394 g_object_unref (connection);
397 static GetSecretsInfo *
398 find_get_secrets_info (GSList *list, const char *path, const char *setting_name)
402 for (iter = list; iter; iter = g_slist_next (iter)) {
403 GetSecretsInfo *candidate = iter->data;
405 if ( g_strcmp0 (path, candidate->path) == 0
406 && g_strcmp0 (setting_name, candidate->setting_name) == 0)
413 impl_secret_agent_cancel_get_secrets (NMSecretAgent *self,
414 const char *connection_path,
415 const char *setting_name,
416 DBusGMethodInvocation *context)
418 NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
419 GError *error = NULL;
420 GetSecretsInfo *info;
422 /* Make sure the request comes from NetworkManager and is valid */
423 if (!verify_request (self, context, NULL, NULL, NULL, &error)) {
424 dbus_g_method_return_error (context, error);
425 g_clear_error (&error);
429 info = find_get_secrets_info (priv->pending_gets, connection_path, setting_name);
431 g_set_error_literal (&error,
432 NM_SECRET_AGENT_ERROR,
433 NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
434 "No secrets request in progress for this connection.");
435 dbus_g_method_return_error (context, error);
436 g_clear_error (&error);
440 /* Send the cancel request up to the subclass and finalize it */
441 NM_SECRET_AGENT_GET_CLASS (self)->cancel_get_secrets (self,
444 dbus_g_method_return (context);
448 save_secrets_cb (NMSecretAgent *self,
449 NMConnection *connection,
453 DBusGMethodInvocation *context = user_data;
456 dbus_g_method_return_error (context, error);
458 dbus_g_method_return (context);
462 impl_secret_agent_save_secrets (NMSecretAgent *self,
463 GHashTable *connection_hash,
464 const char *connection_path,
465 DBusGMethodInvocation *context)
467 GError *error = NULL;
468 NMConnection *connection = NULL;
470 /* Make sure the request comes from NetworkManager and is valid */
471 if (!verify_request (self, context, connection_hash, connection_path, &connection, &error)) {
472 dbus_g_method_return_error (context, error);
473 g_clear_error (&error);
477 NM_SECRET_AGENT_GET_CLASS (self)->save_secrets (self,
482 g_object_unref (connection);
486 delete_secrets_cb (NMSecretAgent *self,
487 NMConnection *connection,
491 DBusGMethodInvocation *context = user_data;
494 dbus_g_method_return_error (context, error);
496 dbus_g_method_return (context);
500 impl_secret_agent_delete_secrets (NMSecretAgent *self,
501 GHashTable *connection_hash,
502 const char *connection_path,
503 DBusGMethodInvocation *context)
505 GError *error = NULL;
506 NMConnection *connection = NULL;
508 /* Make sure the request comes from NetworkManager and is valid */
509 if (!verify_request (self, context, connection_hash, connection_path, &connection, &error)) {
510 dbus_g_method_return_error (context, error);
511 g_clear_error (&error);
515 NM_SECRET_AGENT_GET_CLASS (self)->delete_secrets (self,
520 g_object_unref (connection);
523 /**************************************************************/
526 reg_result (NMSecretAgent *self, GError *error)
528 NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
531 /* If registration failed we shouldn't expose ourselves on the bus */
532 _internal_unregister (self);
534 priv->registered = TRUE;
535 g_object_notify (G_OBJECT (self), NM_SECRET_AGENT_REGISTERED);
538 g_signal_emit (self, signals[REGISTRATION_RESULT], 0, error);
542 reg_request_cb (DBusGProxy *proxy,
543 DBusGProxyCall *call,
546 NMSecretAgent *self = NM_SECRET_AGENT (user_data);
547 NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
548 GError *error = NULL;
550 priv->reg_call = NULL;
552 dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID);
553 reg_result (self, error);
554 g_clear_error (&error);
558 reg_with_caps_cb (DBusGProxy *proxy,
559 DBusGProxyCall *call,
562 NMSecretAgent *self = NM_SECRET_AGENT (user_data);
563 NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
565 priv->reg_call = NULL;
567 if (dbus_g_proxy_end_call (proxy, call, NULL, G_TYPE_INVALID)) {
568 reg_result (self, NULL);
572 /* Might be an old NetworkManager that doesn't support capabilities;
573 * fall back to old Register() method instead.
575 priv->reg_call = dbus_g_proxy_begin_call_with_timeout (priv->manager_proxy,
581 G_TYPE_STRING, priv->identifier,
586 * nm_secret_agent_register:
587 * @self: a #NMSecretAgent
589 * Registers the #NMSecretAgent with the NetworkManager secret manager,
590 * indicating to NetworkManager that the agent is able to provide and save
591 * secrets for connections on behalf of its user. Registration is an
592 * asynchronous operation and its success or failure is indicated via the
593 * 'registration-result' signal.
595 * Returns: a new %TRUE if registration was successfully requested (this does
596 * not mean registration itself was successful), %FALSE if registration was not
597 * successfully requested.
600 nm_secret_agent_register (NMSecretAgent *self)
602 NMSecretAgentPrivate *priv;
603 NMSecretAgentClass *class;
605 g_return_val_if_fail (NM_IS_SECRET_AGENT (self), FALSE);
607 priv = NM_SECRET_AGENT_GET_PRIVATE (self);
609 g_return_val_if_fail (priv->registered == FALSE, FALSE);
610 g_return_val_if_fail (priv->reg_call == NULL, FALSE);
611 g_return_val_if_fail (priv->bus != NULL, FALSE);
612 g_return_val_if_fail (priv->manager_proxy != NULL, FALSE);
614 /* Also make sure the subclass can actually respond to secrets requests */
615 class = NM_SECRET_AGENT_GET_CLASS (self);
616 g_return_val_if_fail (class->get_secrets != NULL, FALSE);
617 g_return_val_if_fail (class->save_secrets != NULL, FALSE);
618 g_return_val_if_fail (class->delete_secrets != NULL, FALSE);
623 priv->suppress_auto = FALSE;
625 /* Export our secret agent interface before registering with the manager */
626 dbus_g_connection_register_g_object (priv->bus,
627 NM_DBUS_PATH_SECRET_AGENT,
630 priv->reg_call = dbus_g_proxy_begin_call_with_timeout (priv->manager_proxy,
631 "RegisterWithCapabilities",
636 G_TYPE_STRING, priv->identifier,
637 G_TYPE_UINT, priv->capabilities,
643 * nm_secret_agent_unregister:
644 * @self: a #NMSecretAgent
646 * Unregisters the #NMSecretAgent with the NetworkManager secret manager,
647 * indicating to NetworkManager that the agent is will no longer provide or
648 * store secrets on behalf of this user.
650 * Returns: a new %TRUE if unregistration was successful, %FALSE if it was not.
653 nm_secret_agent_unregister (NMSecretAgent *self)
655 NMSecretAgentPrivate *priv;
657 g_return_val_if_fail (NM_IS_SECRET_AGENT (self), FALSE);
659 priv = NM_SECRET_AGENT_GET_PRIVATE (self);
661 g_return_val_if_fail (priv->registered == TRUE, FALSE);
662 g_return_val_if_fail (priv->bus != NULL, FALSE);
663 g_return_val_if_fail (priv->manager_proxy != NULL, FALSE);
668 dbus_g_proxy_call_no_reply (priv->manager_proxy, "Unregister", G_TYPE_INVALID);
670 _internal_unregister (self);
671 priv->suppress_auto = TRUE;
677 * nm_secret_agent_get_registered:
678 * @self: a #NMSecretAgent
680 * Returns: a %TRUE if the agent is registered, %FALSE if it is not.
683 nm_secret_agent_get_registered (NMSecretAgent *self)
685 g_return_val_if_fail (NM_IS_SECRET_AGENT (self), FALSE);
687 return NM_SECRET_AGENT_GET_PRIVATE (self)->registered;
691 auto_register_cb (gpointer user_data)
693 NMSecretAgent *self = NM_SECRET_AGENT (user_data);
694 NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
696 priv->auto_register_id = 0;
697 if (priv->auto_register && !priv->suppress_auto &&
698 (priv->reg_call == NULL && !priv->registered))
699 nm_secret_agent_register (self);
703 /**************************************************************/
706 * nm_secret_agent_get_secrets:
707 * @self: a #NMSecretAgent
708 * @connection: the #NMConnection for which we're asked secrets
709 * @setting_name: the name of the secret setting
710 * @hints: (array zero-terminated=1): hints to the agent
711 * @flags: flags that modify the behavior of the request
712 * @callback: (scope async): a callback, to be invoked when the operation is done
713 * @user_data: (closure): caller-specific data to be passed to @callback
715 * Asyncronously retrieve secrets belonging to @connection for the
716 * setting @setting_name. @flags indicate specific behavior that the secret
717 * agent should use when performing the request, for example returning only
718 * existing secrets without user interaction, or requesting entirely new
719 * secrets from the user.
721 * Virtual: get_secrets
724 nm_secret_agent_get_secrets (NMSecretAgent *self,
725 NMConnection *connection,
726 const char *setting_name,
728 NMSecretAgentGetSecretsFlags flags,
729 NMSecretAgentGetSecretsFunc callback,
732 g_return_if_fail (NM_IS_SECRET_AGENT (self));
733 g_return_if_fail (NM_IS_CONNECTION (connection));
734 g_return_if_fail (nm_connection_get_path (connection));
735 g_return_if_fail (setting_name != NULL);
736 g_return_if_fail (strlen (setting_name) > 0);
737 g_return_if_fail (callback != NULL);
739 NM_SECRET_AGENT_GET_CLASS (self)->get_secrets (self,
741 nm_connection_get_path (connection),
750 * nm_secret_agent_save_secrets:
751 * @self: a #NMSecretAgent
752 * @connection: a #NMConnection
753 * @callback: (scope async): a callback, to be invoked when the operation is done
754 * @user_data: (closure): caller-specific data to be passed to @callback
756 * Asyncronously ensure that all secrets inside @connection
757 * are stored to disk.
759 * Virtual: save_secrets
762 nm_secret_agent_save_secrets (NMSecretAgent *self,
763 NMConnection *connection,
764 NMSecretAgentSaveSecretsFunc callback,
767 g_return_if_fail (NM_IS_SECRET_AGENT (self));
768 g_return_if_fail (NM_IS_CONNECTION (connection));
769 g_return_if_fail (nm_connection_get_path (connection));
771 NM_SECRET_AGENT_GET_CLASS (self)->save_secrets (self,
773 nm_connection_get_path (connection),
779 * nm_secret_agent_delete_secrets:
780 * @self: a #NMSecretAgent
781 * @connection: a #NMConnection
782 * @callback: (scope async): a callback, to be invoked when the operation is done
783 * @user_data: (closure): caller-specific data to be passed to @callback
785 * Asynchronously ask the agent to delete all saved secrets belonging to
788 * Virtual: delete_secrets
791 nm_secret_agent_delete_secrets (NMSecretAgent *self,
792 NMConnection *connection,
793 NMSecretAgentDeleteSecretsFunc callback,
796 g_return_if_fail (NM_IS_SECRET_AGENT (self));
797 g_return_if_fail (NM_IS_CONNECTION (connection));
798 g_return_if_fail (nm_connection_get_path (connection));
800 NM_SECRET_AGENT_GET_CLASS (self)->delete_secrets (self,
802 nm_connection_get_path (connection),
807 /**************************************************************/
810 validate_identifier (const char *identifier)
812 const char *p = identifier;
815 /* Length between 3 and 255 characters inclusive */
816 id_len = strlen (identifier);
817 if (id_len < 3 || id_len > 255)
820 if ((identifier[0] == '.') || (identifier[id_len - 1] == '.'))
823 /* FIXME: do complete validation here */
825 if (!g_ascii_isalnum (*p) && (*p != '_') && (*p != '-') && (*p != '.'))
827 if ((*p == '.') && (*(p + 1) == '.'))
836 nm_secret_agent_init (NMSecretAgent *self)
838 NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
839 GError *error = NULL;
841 priv->bus = _nm_dbus_new_connection (&error);
843 g_warning ("Couldn't connect to system bus: %s", error->message);
844 g_error_free (error);
848 priv->dbus_proxy = dbus_g_proxy_new_for_name (priv->bus,
851 DBUS_INTERFACE_DBUS);
852 g_assert (priv->dbus_proxy);
854 dbus_g_object_register_marshaller (g_cclosure_marshal_generic,
856 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
858 dbus_g_proxy_add_signal (priv->dbus_proxy, "NameOwnerChanged",
859 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
861 dbus_g_proxy_connect_signal (priv->dbus_proxy,
863 G_CALLBACK (name_owner_changed),
868 priv->manager_proxy = _nm_dbus_new_proxy_for_connection (priv->bus,
869 NM_DBUS_PATH_AGENT_MANAGER,
870 NM_DBUS_INTERFACE_AGENT_MANAGER);
871 if (!priv->manager_proxy) {
872 g_warning ("Couldn't create NM agent manager proxy.");
877 priv->auto_register_id = g_idle_add (auto_register_cb, self);
881 get_property (GObject *object,
886 NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (object);
889 case PROP_IDENTIFIER:
890 g_value_set_string (value, priv->identifier);
892 case PROP_AUTO_REGISTER:
893 g_value_set_boolean (value, priv->auto_register);
895 case PROP_REGISTERED:
896 g_value_set_boolean (value, priv->registered);
898 case PROP_CAPABILITIES:
899 g_value_set_flags (value, priv->capabilities);
902 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
908 set_property (GObject *object,
913 NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (object);
914 const char *identifier;
917 case PROP_IDENTIFIER:
918 identifier = g_value_get_string (value);
920 g_return_if_fail (validate_identifier (identifier));
922 g_free (priv->identifier);
923 priv->identifier = g_strdup (identifier);
925 case PROP_AUTO_REGISTER:
926 priv->auto_register = g_value_get_boolean (value);
928 case PROP_CAPABILITIES:
929 priv->capabilities = g_value_get_flags (value);
932 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
938 dispose (GObject *object)
940 NMSecretAgent *self = NM_SECRET_AGENT (object);
941 NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
943 if (priv->registered)
944 nm_secret_agent_unregister (self);
946 if (priv->auto_register_id) {
947 g_source_remove (priv->auto_register_id);
948 priv->auto_register_id = 0;
951 g_free (priv->identifier);
952 priv->identifier = NULL;
953 g_free (priv->nm_owner);
954 priv->nm_owner = NULL;
956 while (priv->pending_gets)
957 get_secrets_info_finalize (self, priv->pending_gets->data);
959 g_clear_object (&priv->dbus_proxy);
960 g_clear_object (&priv->manager_proxy);
963 dbus_g_connection_unref (priv->bus);
967 G_OBJECT_CLASS (nm_secret_agent_parent_class)->dispose (object);
971 nm_secret_agent_class_init (NMSecretAgentClass *class)
973 GObjectClass *object_class = G_OBJECT_CLASS (class);
975 g_type_class_add_private (class, sizeof (NMSecretAgentPrivate));
977 /* Virtual methods */
978 object_class->dispose = dispose;
979 object_class->get_property = get_property;
980 object_class->set_property = set_property;
983 * NMSecretAgent:identifier:
985 * Identifies this agent; only one agent in each user session may use the
986 * same identifier. Identifier formatting follows the same rules as
987 * D-Bus bus names with the exception that the ':' character is not
988 * allowed. The valid set of characters is "[A-Z][a-z][0-9]_-." and the
989 * identifier is limited in length to 255 characters with a minimum
990 * of 3 characters. An example valid identifier is 'org.gnome.nm-applet'
993 g_object_class_install_property
994 (object_class, PROP_IDENTIFIER,
995 g_param_spec_string (NM_SECRET_AGENT_IDENTIFIER, "", "",
998 G_PARAM_CONSTRUCT_ONLY |
999 G_PARAM_STATIC_STRINGS));
1002 * NMSecretAgent:auto-register:
1004 * If TRUE, the agent will attempt to automatically register itself after
1005 * it is created (via an idle handler) and to re-register itself if
1006 * NetworkManager restarts. If FALSE, the agent does not automatically
1007 * register with NetworkManager, and nm_secret_agent_register() must be
1008 * called. If 'auto-register' is TRUE, calling nm_secret_agent_unregister()
1009 * will suppress auto-registration until nm_secret_agent_register() is
1010 * called, which re-enables auto-registration.
1012 g_object_class_install_property
1013 (object_class, PROP_AUTO_REGISTER,
1014 g_param_spec_boolean (NM_SECRET_AGENT_AUTO_REGISTER, "", "",
1018 G_PARAM_STATIC_STRINGS));
1021 * NMSecretAgent:registered:
1023 * %TRUE if the agent is registered with NetworkManager, %FALSE if not.
1025 g_object_class_install_property
1026 (object_class, PROP_REGISTERED,
1027 g_param_spec_boolean (NM_SECRET_AGENT_REGISTERED, "", "",
1030 G_PARAM_STATIC_STRINGS));
1033 * NMSecretAgent:capabilities:
1035 * A bitfield of %NMSecretAgentCapabilities.
1037 g_object_class_install_property
1038 (object_class, PROP_CAPABILITIES,
1039 g_param_spec_flags (NM_SECRET_AGENT_CAPABILITIES, "", "",
1040 NM_TYPE_SECRET_AGENT_CAPABILITIES,
1041 NM_SECRET_AGENT_CAPABILITY_NONE,
1044 G_PARAM_STATIC_STRINGS));
1047 * NMSecretAgent::registration-result:
1048 * @agent: the agent that received the signal
1049 * @error: the error, if any, that occured while registering
1051 * Indicates the result of a registration request; if @error is NULL the
1052 * request was successful.
1054 signals[REGISTRATION_RESULT] =
1055 g_signal_new (NM_SECRET_AGENT_REGISTRATION_RESULT,
1056 G_OBJECT_CLASS_TYPE (object_class),
1058 0, NULL, NULL, NULL,
1059 G_TYPE_NONE, 1, G_TYPE_POINTER);
1061 dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (class),
1062 &dbus_glib_nm_secret_agent_object_info);
1064 dbus_g_error_domain_register (NM_SECRET_AGENT_ERROR,
1065 NM_DBUS_INTERFACE_SECRET_AGENT,
1066 NM_TYPE_SECRET_AGENT_ERROR);