summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/settings/nm-agent-manager.c33
-rw-r--r--src/settings/nm-secret-agent.c625
-rw-r--r--src/settings/nm-secret-agent.h6
3 files changed, 351 insertions, 313 deletions
diff --git a/src/settings/nm-agent-manager.c b/src/settings/nm-agent-manager.c
index 2f9827d54a..571ab721b6 100644
--- a/src/settings/nm-agent-manager.c
+++ b/src/settings/nm-agent-manager.c
@@ -93,13 +93,13 @@ NM_DEFINE_SINGLETON_GETTER (NMAgentManager, nm_agent_manager_get, NM_TYPE_AGENT_
if (!(self)) \
g_snprintf (__prefix1, sizeof (__prefix1), "%s%s", ""_NMLOG_PREFIX_NAME"", "[]"); \
else if ((self) != singleton_instance) \
- g_snprintf (__prefix1, sizeof (__prefix1), "%s[%p]", ""_NMLOG_PREFIX_NAME"", (self)); \
+ g_snprintf (__prefix1, sizeof (__prefix1), "%s["NM_HASH_OBFUSCATE_PTR_FMT"]", ""_NMLOG_PREFIX_NAME"", NM_HASH_OBFUSCATE_PTR (self)); \
else \
g_strlcpy (__prefix1, _NMLOG_PREFIX_NAME, sizeof (__prefix1)); \
if (__agent) { \
g_snprintf (__prefix2, sizeof (__prefix2), \
- ": req[%p, %s]", \
- __agent, \
+ ": agent["NM_HASH_OBFUSCATE_PTR_FMT",%s]", \
+ NM_HASH_OBFUSCATE_PTR (__agent), \
nm_secret_agent_get_description (__agent)); \
} else \
__prefix2[0] = '\0'; \
@@ -109,9 +109,9 @@ NM_DEFINE_SINGLETON_GETTER (NMAgentManager, nm_agent_manager_get, NM_TYPE_AGENT_
} \
} G_STMT_END
-#define LOG_REQ_FMT "[%p/%s%s%s%s%s%s]"
+#define LOG_REQ_FMT "["NM_HASH_OBFUSCATE_PTR_FMT"/%s%s%s%s%s%s]"
#define LOG_REQ_ARG(req) \
- (req), \
+ NM_HASH_OBFUSCATE_PTR (req), \
NM_PRINT_FMT_QUOTE_STRING ((req)->detail), \
NM_PRINT_FMT_QUOTED (((req)->request_type == REQUEST_TYPE_CON_GET) && (req)->con.get.setting_name, \
"/\"", (req)->con.get.setting_name, "\"", \
@@ -539,12 +539,10 @@ request_free (Request *req)
if (req->idle_id)
g_source_remove (req->idle_id);
- if (req->current && req->current_call_id) {
- /* cancel-secrets invokes the done-callback synchronously -- in which case
- * the handler just return.
- * Hence, we can proceed to free @req... */
- nm_secret_agent_cancel_secrets (req->current, req->current_call_id);
- }
+ /* cancel-secrets invokes the done-callback synchronously -- in which case
+ * the handler just return.
+ * Hence, we can proceed to free @req... */
+ nm_secret_agent_cancel_call (req->current, req->current_call_id);
g_object_unref (req->subject);
@@ -742,12 +740,9 @@ request_next_agent (Request *req)
self = req->self;
- if (req->current) {
- if (req->current_call_id)
- nm_secret_agent_cancel_secrets (req->current, req->current_call_id);
- g_clear_object (&req->current);
- }
+ nm_secret_agent_cancel_call (req->current, req->current_call_id);
nm_assert (!req->current_call_id);
+ g_clear_object (&req->current);
if (req->pending) {
/* Send the request to the next agent */
@@ -882,10 +877,8 @@ _con_get_request_done (NMSecretAgent *agent,
req_complete_error (req, error);
g_error_free (error);
} else {
- if (req->current_call_id) {
- /* Tell the failed agent we're no longer interested. */
- nm_secret_agent_cancel_secrets (req->current, req->current_call_id);
- }
+ /* Tell the failed agent we're no longer interested. */
+ nm_secret_agent_cancel_call (req->current, req->current_call_id);
/* Try the next agent */
request_next_agent (req);
diff --git a/src/settings/nm-secret-agent.c b/src/settings/nm-secret-agent.c
index 141e385b1f..e6d4630a2c 100644
--- a/src/settings/nm-secret-agent.c
+++ b/src/settings/nm-secret-agent.c
@@ -35,11 +35,17 @@
/*****************************************************************************/
+#define METHOD_GET_SECRETS "GetSecrets"
+#define METHOD_CANCEL_GET_SECRETS "CancelGetSecrets"
+#define METHOD_SAVE_SECRETS "SaveSecrets"
+#define METHOD_DELETE_SECRETS "DeleteSecrets"
+
enum {
DISCONNECTED,
LAST_SIGNAL
};
+
static guint signals[LAST_SIGNAL] = { 0 };
typedef struct {
@@ -49,11 +55,12 @@ typedef struct {
char *identifier;
char *owner_username;
char *dbus_owner;
- NMSecretAgentCapabilities capabilities;
- GDBusProxy *proxy;
GDBusConnection *dbus_connection;
+ GCancellable *name_owner_cancellable;
CList requests;
- guint on_disconnected_id;
+ NMSecretAgentCapabilities capabilities;
+ guint name_owner_changed_id;
+ bool shutdown_wait_obj_registered:1;
} NMSecretAgentPrivate;
struct _NMSecretAgent {
@@ -81,8 +88,7 @@ G_DEFINE_TYPE (NMSecretAgent, nm_secret_agent, G_TYPE_OBJECT)
if ((self)) { \
g_snprintf (_prefix, \
sizeof (_prefix), \
- "%s["NM_HASH_OBFUSCATE_PTR_FMT"]", \
- ""_NMLOG_PREFIX_NAME"", \
+ _NMLOG_PREFIX_NAME"["NM_HASH_OBFUSCATE_PTR_FMT"]", \
NM_HASH_OBFUSCATE_PTR (self)); \
} else \
g_strlcpy (_prefix, _NMLOG_PREFIX_NAME, sizeof (_prefix)); \
@@ -98,17 +104,30 @@ G_DEFINE_TYPE (NMSecretAgent, nm_secret_agent, G_TYPE_OBJECT)
} \
} G_STMT_END
-#define LOG_REQ_FMT "req["NM_HASH_OBFUSCATE_PTR_FMT",%s,%s%s%s%s]"
-#define LOG_REQ_ARG(req) \
- NM_HASH_OBFUSCATE_PTR (req), \
- (req)->dbus_command, \
- NM_PRINT_FMT_QUOTE_STRING ((req)->path), \
- ((req)->cancellable ? "" : " (cancelled)")
+#define _NMLOG2(level, call_id, ...) \
+ G_STMT_START { \
+ NMSecretAgentCallId *const _call_id = (call_id); \
+ \
+ nm_assert (_call_id); \
+ \
+ nm_log ((level), \
+ (_NMLOG_DOMAIN), \
+ NULL, \
+ NULL, \
+ "%s["NM_HASH_OBFUSCATE_PTR_FMT"] request ["NM_HASH_OBFUSCATE_PTR_FMT",%s,%s%s%s%s]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
+ _NMLOG_PREFIX_NAME, \
+ NM_HASH_OBFUSCATE_PTR (_call_id->self), \
+ NM_HASH_OBFUSCATE_PTR (_call_id), \
+ _call_id->method_name, \
+ NM_PRINT_FMT_QUOTE_STRING (_call_id->path), \
+ (_call_id->cancellable ? "" : " (cancelled)") \
+ _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
+ } G_STMT_END
/*****************************************************************************/
NM_UTILS_FLAGS2STR_DEFINE_STATIC (_capabilities_to_string, NMSecretAgentCapabilities,
- NM_UTILS_FLAGS2STR (NM_SECRET_AGENT_CAPABILITY_NONE, "none"),
+ NM_UTILS_FLAGS2STR (NM_SECRET_AGENT_CAPABILITY_NONE, "none"),
NM_UTILS_FLAGS2STR (NM_SECRET_AGENT_CAPABILITY_VPN_HINTS, "vpn-hints"),
);
@@ -116,69 +135,100 @@ NM_UTILS_FLAGS2STR_DEFINE_STATIC (_capabilities_to_string, NMSecretAgentCapabili
struct _NMSecretAgentCallId {
CList lst;
- NMSecretAgent *agent;
+ NMSecretAgent *self;
GCancellable *cancellable;
char *path;
- const char *dbus_command;
+ const char *method_name;
char *setting_name;
- gboolean is_get_secrets;
NMSecretAgentCallback callback;
gpointer callback_data;
};
static NMSecretAgentCallId *
-request_new (NMSecretAgent *self,
- const char *dbus_command, /* this must be a static string. */
- const char *path,
- const char *setting_name,
- NMSecretAgentCallback callback,
- gpointer callback_data)
+_call_id_new (NMSecretAgent *self,
+ const char *method_name, /* this must be a static string. */
+ const char *path,
+ const char *setting_name,
+ NMSecretAgentCallback callback,
+ gpointer callback_data)
{
- NMSecretAgentCallId *r;
-
- r = g_slice_new0 (NMSecretAgentCallId);
- r->agent = self;
- r->path = g_strdup (path);
- r->setting_name = g_strdup (setting_name);
- r->dbus_command = dbus_command,
- r->callback = callback;
- r->callback_data = callback_data;
- r->cancellable = g_cancellable_new ();
- c_list_link_tail (&NM_SECRET_AGENT_GET_PRIVATE (self)->requests,
- &r->lst);
- _LOGT ("request "LOG_REQ_FMT": created", LOG_REQ_ARG (r));
- return r;
+ NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
+ NMSecretAgentCallId *call_id;
+
+ call_id = g_slice_new (NMSecretAgentCallId);
+ *call_id = (NMSecretAgentCallId) {
+ .self = g_object_ref (self),
+ .path = g_strdup (path),
+ .setting_name = g_strdup (setting_name),
+ .method_name = method_name,
+ .callback = callback,
+ .callback_data = callback_data,
+ .cancellable = g_cancellable_new (),
+ };
+ c_list_link_tail (&priv->requests, &call_id->lst);
+
+ _LOG2T (call_id, "new request...");
+
+ if (!priv->shutdown_wait_obj_registered) {
+ /* self has async requests (that keep self alive). As long as
+ * we have pending requests, shutdown is blocked. */
+ priv->shutdown_wait_obj_registered = TRUE;
+ nm_shutdown_wait_obj_register (G_OBJECT (self), "secret-agent");
+ }
+
+ return call_id;
}
-#define request_new(self,dbus_command,path,setting_name,callback,callback_data) request_new(self,""dbus_command"",path,setting_name,callback,callback_data)
+
+#define _call_id_new(self, method_name, path, setting_name, callback, callback_data) _call_id_new(self, ""method_name"", path, setting_name, callback, callback_data)
static void
-request_free (NMSecretAgentCallId *r)
+_call_id_free (NMSecretAgentCallId *call_id)
{
- NMSecretAgent *self = r->agent;
-
- _LOGT ("request "LOG_REQ_FMT": destroyed", LOG_REQ_ARG (r));
- c_list_unlink_stale (&r->lst);
- g_free (r->path);
- g_free (r->setting_name);
- if (r->cancellable)
- g_object_unref (r->cancellable);
- g_slice_free (NMSecretAgentCallId, r);
+ c_list_unlink_stale (&call_id->lst);
+ g_free (call_id->path);
+ g_free (call_id->setting_name);
+ nm_g_object_unref (call_id->cancellable);
+ g_object_unref (call_id->self);
+ nm_g_slice_free (call_id);
}
-static gboolean
-request_check_return (NMSecretAgentCallId *r)
+static void
+_call_id_invoke_callback (NMSecretAgentCallId *call_id,
+ GVariant *secrets,
+ GError *error,
+ gboolean cancelled,
+ gboolean free_call_id)
{
- if (!r->cancellable)
- return FALSE;
+ gs_free_error GError *error_cancelled = NULL;
+
+ nm_assert (call_id);
+ nm_assert (!c_list_is_empty (&call_id->lst));
- g_return_val_if_fail (NM_IS_SECRET_AGENT (r->agent), FALSE);
+ c_list_unlink (&call_id->lst);
- nm_assert (c_list_contains (&NM_SECRET_AGENT_GET_PRIVATE (r->agent)->requests,
- &r->lst));
+ if (cancelled) {
+ nm_assert (!secrets);
+ nm_assert (!error);
+ if (call_id->callback) {
+ nm_utils_error_set_cancelled (&error_cancelled, FALSE, "NMSecretAgent");
+ error = error_cancelled;
+ }
+ _LOG2T (call_id, "cancelled");
+ } else if (error) {
+ nm_assert (!secrets);
+ _LOG2T (call_id, "completed with failure: %s", error->message);
+ } else {
+ nm_assert ( !secrets
+ || g_variant_is_of_type (secrets, G_VARIANT_TYPE ("a{sa{sv}}")));
+ nm_assert ((!!secrets) == nm_streq0 (call_id->method_name, METHOD_GET_SECRETS));
+ _LOG2T (call_id, "completed successfully");
+ }
- c_list_unlink (&r->lst);
+ if (call_id->callback)
+ call_id->callback (call_id->self, call_id, secrets, error, call_id->callback_data);
- return TRUE;
+ if (free_call_id)
+ _call_id_free (call_id);
}
/*****************************************************************************/
@@ -209,6 +259,8 @@ nm_secret_agent_get_description (NMSecretAgent *agent)
return priv->description;
}
+/*****************************************************************************/
+
const char *
nm_secret_agent_get_dbus_owner (NMSecretAgent *agent)
{
@@ -265,6 +317,8 @@ nm_secret_agent_get_subject (NMSecretAgent *agent)
return NM_SECRET_AGENT_GET_PRIVATE (agent)->subject;
}
+/*****************************************************************************/
+
/**
* nm_secret_agent_add_permission:
* @agent: A #NMSecretAgent.
@@ -323,32 +377,38 @@ nm_secret_agent_has_permission (NMSecretAgent *agent, const char *permission)
/*****************************************************************************/
static void
-get_callback (GObject *proxy,
- GAsyncResult *result,
- gpointer user_data)
+_dbus_call_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
{
- NMSecretAgentCallId *r = user_data;
-
- if (request_check_return (r)) {
- NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (r->agent);
- gs_free_error GError *error = NULL;
- gs_unref_variant GVariant *ret = NULL;
- gs_unref_variant GVariant *secrets = NULL;
-
- ret = _nm_dbus_proxy_call_finish (priv->proxy, result, G_VARIANT_TYPE ("(a{sa{sv}})"), &error);
- if (!ret)
- g_dbus_error_strip_remote_error (error);
- else {
+ NMSecretAgentCallId *call_id;
+ gs_unref_variant GVariant *ret = NULL;
+ gs_unref_variant GVariant *secrets = NULL;
+ gs_free_error GError *error = NULL;
+
+ ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
+
+ if ( !ret
+ && nm_utils_error_is_cancelled (error, FALSE))
+ return;
+
+ call_id = user_data;
+
+ if (!ret)
+ g_dbus_error_strip_remote_error (error);
+ else {
+ if (nm_streq (call_id->method_name, METHOD_GET_SECRETS)) {
g_variant_get (ret,
"(@a{sa{sv}})",
&secrets);
}
- r->callback (r->agent, r, secrets, error, r->callback_data);
}
- request_free (r);
+ _call_id_invoke_callback (call_id, secrets, error, FALSE, TRUE);
}
+/*****************************************************************************/
+
NMSecretAgentCallId *
nm_secret_agent_get_secrets (NMSecretAgent *self,
const char *path,
@@ -361,160 +421,139 @@ nm_secret_agent_get_secrets (NMSecretAgent *self,
{
NMSecretAgentPrivate *priv;
GVariant *dict;
- NMSecretAgentCallId *r;
+ NMSecretAgentCallId *call_id;
g_return_val_if_fail (NM_IS_SECRET_AGENT (self), NULL);
g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
g_return_val_if_fail (path && *path, NULL);
- g_return_val_if_fail (setting_name != NULL, NULL);
+ g_return_val_if_fail (setting_name, NULL);
+ g_return_val_if_fail (callback, NULL);
priv = NM_SECRET_AGENT_GET_PRIVATE (self);
- g_return_val_if_fail (priv->proxy != NULL, NULL);
dict = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL);
/* Mask off the private flags if present */
- flags &= ~NM_SECRET_AGENT_GET_SECRETS_FLAG_ONLY_SYSTEM;
- flags &= ~NM_SECRET_AGENT_GET_SECRETS_FLAG_NO_ERRORS;
-
- r = request_new (self, "GetSecrets", path, setting_name, callback, callback_data);
- r->is_get_secrets = TRUE;
-
- g_dbus_proxy_call (priv->proxy,
- "GetSecrets",
- g_variant_new ("(@a{sa{sv}}os^asu)",
- dict,
- path,
- setting_name,
- hints ?: NM_PTRARRAY_EMPTY (const char *),
- (guint32) flags),
- G_DBUS_CALL_FLAGS_NONE,
- 120000,
- r->cancellable,
- get_callback,
- r);
-
- g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (priv->proxy), -1);
-
- return r;
+ flags &= ~( NM_SECRET_AGENT_GET_SECRETS_FLAG_ONLY_SYSTEM
+ | NM_SECRET_AGENT_GET_SECRETS_FLAG_NO_ERRORS);
+
+ call_id = _call_id_new (self, METHOD_GET_SECRETS, path, setting_name, callback, callback_data);
+
+ g_dbus_connection_call (priv->dbus_connection,
+ priv->dbus_owner,
+ NM_DBUS_PATH_SECRET_AGENT,
+ NM_DBUS_INTERFACE_SECRET_AGENT,
+ call_id->method_name,
+ g_variant_new ("(@a{sa{sv}}os^asu)",
+ dict,
+ path,
+ setting_name,
+ hints ?: NM_PTRARRAY_EMPTY (const char *),
+ (guint32) flags),
+ G_VARIANT_TYPE ("(a{sa{sv}})"),
+ G_DBUS_CALL_FLAGS_NO_AUTO_START,
+ 120000,
+ call_id->cancellable,
+ _dbus_call_cb,
+ call_id);
+
+ return call_id;
}
/*****************************************************************************/
static void
-cancel_done (GObject *proxy, GAsyncResult *result, gpointer user_data)
+_call_cancel_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
{
- gs_free char *description = user_data;
+ NMSecretAgentCallId *call_id = user_data;
gs_free_error GError *error = NULL;
gs_unref_variant GVariant *ret = NULL;
- ret = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, G_VARIANT_TYPE ("()"), &error);
- if (!ret) {
- nm_log_dbg (LOGD_AGENTS, "%s%s%s: agent failed to cancel secrets: %s",
- NM_PRINT_FMT_QUOTED (description, "(", description, ")", "???"),
- error->message);
- }
-}
+ ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
-static void
-do_cancel_secrets (NMSecretAgent *self, NMSecretAgentCallId *r, gboolean disposing)
-{
- NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
- GCancellable *cancellable;
- NMSecretAgentCallback callback;
- gpointer callback_data;
-
- g_return_if_fail (r->agent == self);
- g_return_if_fail (r->cancellable);
-
- if ( r->is_get_secrets
- && priv->proxy) {
- /* for GetSecrets call, we must cancel the request. */
- g_dbus_proxy_call (G_DBUS_PROXY (priv->proxy),
- "CancelGetSecrets",
- g_variant_new ("(os)",
- r->path,
- r->setting_name),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL,
- cancel_done,
- g_strdup (nm_secret_agent_get_description (self)));
+ if (ret)
+ _LOG2T (call_id, "success cancelling GetSecrets");
+ else if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN))
+ _LOG2T (call_id, "cancelling GetSecrets no longer works as service disconnected");
+ else {
+ _LOG2T (call_id, "failed to cancel GetSecrets: %s",
+ error->message);
}
- cancellable = r->cancellable;
- callback = r->callback;
- callback_data = r->callback_data;
-
- /* During g_cancellable_cancel() the d-bus method might return synchronously.
- * Clear r->cancellable first, so that it doesn't actually do anything.
- * After that, @r might be already freed. */
- r->cancellable = NULL;
- g_cancellable_cancel (cancellable);
- g_object_unref (cancellable);
-
- /* Don't free the request @r. It will be freed when the d-bus call returns.
- * Only clear r->cancellable to indicate that the request was cancelled. */
-
- if (callback) {
- gs_free_error GError *error = NULL;
-
- nm_utils_error_set_cancelled (&error, disposing, "NMSecretAgent");
- /* @r might be a dangling pointer at this point. However, that is no problem
- * to pass it as (opaque) call_id. */
- callback (self, r, NULL, error, callback_data);
- }
+ _call_id_free (call_id);
}
/**
- * nm_secret_agent_cancel_secrets:
- * @self: #NMSecretAgent instance
- * @call_id: the call id to cancel
+ * nm_secret_agent_cancel_call:
+ * @self: the #NMSecretAgent instance for the @call_id.
+ * Maybe be %NULL if @call_id is %NULL.
+ * @call_id: (allow-none): the call id to cancel. May be %NULL for convenience,
+ * in which case it does nothing.
*
* It is an error to pass an invalid @call_id or a @call_id for an operation
- * that already completed. NMSecretAgent will always invoke the callback,
- * also for cancel() and dispose().
- * In case of nm_secret_agent_cancel_secrets() this will synchronously invoke the
- * callback before nm_secret_agent_cancel_secrets() returns.
+ * that already completed. It is also an error to cancel the call from inside
+ * the callback, at that point the call is already completed.
+ * In case of nm_secret_agent_cancel_call() this will synchronously invoke the
+ * callback before nm_secret_agent_cancel_call() returns.
*/
void
-nm_secret_agent_cancel_secrets (NMSecretAgent *self, NMSecretAgentCallId *call_id)
+nm_secret_agent_cancel_call (NMSecretAgent *self,
+ NMSecretAgentCallId *call_id)
{
- NMSecretAgentCallId *r = call_id;
-
- g_return_if_fail (NM_IS_SECRET_AGENT (self));
- g_return_if_fail (r);
-
- nm_assert (c_list_contains (&NM_SECRET_AGENT_GET_PRIVATE (self)->requests,
- &r->lst));
-
- c_list_unlink (&r->lst);
+ NMSecretAgentPrivate *priv;
+ gboolean free_call_id = TRUE;
- do_cancel_secrets (self, r, FALSE);
-}
+ if (!call_id) {
+ /* for convenience, %NULL is accepted fine. */
+ nm_assert (!self || NM_IS_SECRET_AGENT (self));
+ return;
+ }
-/*****************************************************************************/
+ g_return_if_fail (NM_IS_SECRET_AGENT (call_id->self));
+ g_return_if_fail (!c_list_is_empty (&call_id->lst));
-static void
-agent_save_cb (GObject *proxy,
- GAsyncResult *result,
- gpointer user_data)
-{
- NMSecretAgentCallId *r = user_data;
+ /* Theoretically, call-id already has a self pointer. But nm_secret_agent_cancel_call() has only
+ * one user: NMAgentManager. And that one has the self-pointer at hand, so the only purpose of
+ * the @self argument is to assert that we are cancelling the expected call.
+ *
+ * We could drop the @self argument, but that just remove an additional assert-check from
+ * our code, without making a simplification for the only caller of this function. */
+ g_return_if_fail (self == call_id->self);
- if (request_check_return (r)) {
- gs_free_error GError *error = NULL;
- gs_unref_variant GVariant *ret = NULL;
+ priv = NM_SECRET_AGENT_GET_PRIVATE (self);
- ret = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, G_VARIANT_TYPE ("()"), &error);
- if (!ret)
- g_dbus_error_strip_remote_error (error);
- r->callback (r->agent, r, NULL, error, r->callback_data);
+ nm_assert (c_list_contains (&priv->requests,
+ &call_id->lst));
+
+ nm_clear_g_cancellable (&call_id->cancellable);
+
+ if (nm_streq (call_id->method_name, METHOD_GET_SECRETS)) {
+ g_dbus_connection_call (priv->dbus_connection,
+ priv->dbus_owner,
+ NM_DBUS_PATH_SECRET_AGENT,
+ NM_DBUS_INTERFACE_SECRET_AGENT,
+ METHOD_CANCEL_GET_SECRETS,
+ g_variant_new ("(os)",
+ call_id->path,
+ call_id->setting_name),
+ G_VARIANT_TYPE ("()"),
+ G_DBUS_CALL_FLAGS_NO_AUTO_START,
+ NM_SHUTDOWN_TIMEOUT_MS,
+ NULL, /* this operation is not cancellable. We rely on the timeout. */
+ _call_cancel_cb,
+ call_id);
+ /* we keep call-id alive, but it will be unlinked from priv->requests.
+ * _call_cancel_cb() will finally free it later. */
+ free_call_id = FALSE;
}
- request_free (r);
+ _call_id_invoke_callback (call_id, NULL, NULL, TRUE, free_call_id);
}
+/*****************************************************************************/
+
NMSecretAgentCallId *
nm_secret_agent_save_secrets (NMSecretAgent *self,
const char *path,
@@ -524,7 +563,7 @@ nm_secret_agent_save_secrets (NMSecretAgent *self,
{
NMSecretAgentPrivate *priv;
GVariant *dict;
- NMSecretAgentCallId *r;
+ NMSecretAgentCallId *call_id;
g_return_val_if_fail (NM_IS_SECRET_AGENT (self), NULL);
g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
@@ -535,43 +574,28 @@ nm_secret_agent_save_secrets (NMSecretAgent *self,
/* Caller should have ensured that only agent-owned secrets exist in 'connection' */
dict = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL);
- r = request_new (self, "SaveSecrets", path, NULL, callback, callback_data);
- g_dbus_proxy_call (priv->proxy,
- "SaveSecrets",
- g_variant_new ("(@a{sa{sv}}o)",
- dict,
- path),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL, /* cancelling the request does *not* cancel the D-Bus call. */
- agent_save_cb,
- r);
-
- return r;
+ call_id = _call_id_new (self, METHOD_SAVE_SECRETS, path, NULL, callback, callback_data);
+
+ g_dbus_connection_call (priv->dbus_connection,
+ priv->dbus_owner,
+ NM_DBUS_PATH_SECRET_AGENT,
+ NM_DBUS_INTERFACE_SECRET_AGENT,
+ call_id->method_name,
+ g_variant_new ("(@a{sa{sv}}o)",
+ dict,
+ path),
+ G_VARIANT_TYPE ("()"),
+ G_DBUS_CALL_FLAGS_NO_AUTO_START,
+ 60000,
+ call_id->cancellable,
+ _dbus_call_cb,
+ call_id);
+
+ return call_id;
}
/*****************************************************************************/
-static void
-agent_delete_cb (GObject *proxy,
- GAsyncResult *result,
- gpointer user_data)
-{
- NMSecretAgentCallId *r = user_data;
-
- if (request_check_return (r)) {
- gs_free_error GError *error = NULL;
- gs_unref_variant GVariant *ret = NULL;
-
- ret = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, G_VARIANT_TYPE ("()"), &error);
- if (!ret)
- g_dbus_error_strip_remote_error (error);
- r->callback (r->agent, r, NULL, error, r->callback_data);
- }
-
- request_free (r);
-}
-
NMSecretAgentCallId *
nm_secret_agent_delete_secrets (NMSecretAgent *self,
const char *path,
@@ -581,7 +605,7 @@ nm_secret_agent_delete_secrets (NMSecretAgent *self,
{
NMSecretAgentPrivate *priv;
GVariant *dict;
- NMSecretAgentCallId *r;
+ NMSecretAgentCallId *call_id;
g_return_val_if_fail (NM_IS_SECRET_AGENT (self), NULL);
g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
@@ -592,58 +616,90 @@ nm_secret_agent_delete_secrets (NMSecretAgent *self,
/* No secrets sent; agents must be smart enough to track secrets using the UUID or something */
dict = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_NO_SECRETS);
- r = request_new (self, "DeleteSecrets", path, NULL, callback, callback_data);
- g_dbus_proxy_call (priv->proxy,
- "DeleteSecrets",
- g_variant_new ("(@a{sa{sv}}o)",
- dict,
- path),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL, /* cancelling the request does *not* cancel the D-Bus call. */
- agent_delete_cb,
- r);
- return r;
+ call_id = _call_id_new (self, METHOD_DELETE_SECRETS, path, NULL, callback, callback_data);
+
+ g_dbus_connection_call (priv->dbus_connection,
+ priv->dbus_owner,
+ NM_DBUS_PATH_SECRET_AGENT,
+ NM_DBUS_INTERFACE_SECRET_AGENT,
+ call_id->method_name,
+ g_variant_new ("(@a{sa{sv}}o)",
+ dict,
+ path),
+ G_VARIANT_TYPE ("()"),
+ G_DBUS_CALL_FLAGS_NO_AUTO_START,
+ 60000,
+ call_id->cancellable,
+ _dbus_call_cb,
+ call_id);
+ return call_id;
}
/*****************************************************************************/
static void
-_on_disconnected_cleanup (NMSecretAgentPrivate *priv)
+name_owner_changed (NMSecretAgent *self,
+ const char *owner)
{
+ NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
+
+ nm_assert (!priv->name_owner_cancellable);
+
+ owner = nm_str_not_empty (owner);
+
+ _LOGT ("name-owner-changed: %s%s%s",
+ NM_PRINT_FMT_QUOTED (owner, "has ", owner, "", "disconnected"));
+
+ if (owner)
+ return;
+
nm_clear_g_dbus_connection_signal (priv->dbus_connection,
- &priv->on_disconnected_id);
- g_clear_object (&priv->dbus_connection);
- g_clear_object (&priv->proxy);
+ &priv->name_owner_changed_id);
+
+ g_signal_emit (self, signals[DISCONNECTED], 0);
}
static void
-_on_disconnected_name_owner_changed (GDBusConnection *dbus_connection,
- const char *sender_name,
- const char *object_path,
- const char *interface_name,
- const char *signal_name,
- GVariant *parameters,
- gpointer user_data)
+name_owner_changed_cb (GDBusConnection *dbus_connection,
+ const char *sender_name,
+ const char *object_path,
+ const char *interface_name,
+ const char *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
{
NMSecretAgent *self = NM_SECRET_AGENT (user_data);
- NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
- const char *old_owner = NULL, *new_owner = NULL;
+ const char *new_owner = NULL;
+
+ if (g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(sss)"))) {
+ g_variant_get (parameters,
+ "(&s&s&s)",
+ NULL,
+ NULL,
+ &new_owner);
+ }
- g_variant_get (parameters,
- "(&s&s&s)",
- NULL,
- &old_owner,
- &new_owner);
+ nm_clear_g_cancellable (&NM_SECRET_AGENT_GET_PRIVATE (self)->name_owner_cancellable);
- _LOGT ("name-owner-changed: %s%s%s => %s%s%s",
- NM_PRINT_FMT_QUOTE_STRING (old_owner),
- NM_PRINT_FMT_QUOTE_STRING (new_owner));
+ name_owner_changed (self, new_owner);
+}
- if (!*new_owner) {
- _on_disconnected_cleanup (priv);
- g_signal_emit (self, signals[DISCONNECTED], 0);
- }
+static void
+get_name_owner_cb (const char *name_owner,
+ GError *error,
+ gpointer user_data)
+{
+ NMSecretAgent *self;
+
+ if ( !name_owner
+ && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+
+ self = user_data;
+
+ g_clear_object (&NM_SECRET_AGENT_GET_PRIVATE (self)->name_owner_cancellable);
+
+ name_owner_changed (self, name_owner);
}
/*****************************************************************************/
@@ -664,7 +720,6 @@ nm_secret_agent_new (GDBusMethodInvocation *context,
char buf_caps[150];
gulong uid;
GDBusConnection *dbus_connection;
- gs_free_error GError *error = NULL;
g_return_val_if_fail (context != NULL, NULL);
g_return_val_if_fail (NM_IS_AUTH_SUBJECT (subject), NULL);
@@ -703,28 +758,19 @@ nm_secret_agent_new (GDBusMethodInvocation *context,
priv->capabilities = capabilities;
priv->subject = g_object_ref (subject);
- priv->proxy = g_dbus_proxy_new_sync (priv->dbus_connection,
- G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES
- | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
- NULL,
- priv->dbus_owner,
- NM_DBUS_PATH_SECRET_AGENT,
- NM_DBUS_INTERFACE_SECRET_AGENT,
- NULL,
- &error);
- if (!priv->proxy) {
- _LOGW ("could not create proxy for %s on connection %s: %s",
- NM_DBUS_INTERFACE_SECRET_AGENT,
- priv->dbus_owner,
- error->message);
- g_clear_error (&error);
- }
+ priv->name_owner_changed_id = nm_dbus_connection_signal_subscribe_name_owner_changed (priv->dbus_connection,
+ priv->dbus_owner,
+ name_owner_changed_cb,
+ self,
+ NULL);
- priv->on_disconnected_id = nm_dbus_connection_signal_subscribe_name_owner_changed (priv->dbus_connection,
- priv->dbus_owner,
- _on_disconnected_name_owner_changed,
- self,
- NULL);
+ priv->name_owner_cancellable = g_cancellable_new ();
+ nm_dbus_connection_call_get_name_owner (priv->dbus_connection,
+ priv->dbus_owner,
+ -1,
+ priv->name_owner_cancellable,
+ get_name_owner_cb,
+ self);
return self;
}
@@ -743,18 +789,13 @@ dispose (GObject *object)
{
NMSecretAgent *self = NM_SECRET_AGENT (object);
NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
- CList *iter;
-again:
- c_list_for_each (iter, &priv->requests) {
- c_list_unlink (iter);
- do_cancel_secrets (self, c_list_entry (iter, NMSecretAgentCallId, lst), TRUE);
- goto again;
- }
+ nm_assert (c_list_is_empty (&priv->requests));
- _on_disconnected_cleanup (priv);
+ nm_clear_g_dbus_connection_signal (priv->dbus_connection,
+ &priv->name_owner_changed_id);
- g_clear_object (&priv->subject);
+ nm_clear_g_cancellable (&priv->name_owner_cancellable);
G_OBJECT_CLASS (nm_secret_agent_parent_class)->dispose (object);
}
@@ -772,6 +813,10 @@ finalize (GObject *object)
nm_c_list_elem_free_all (&priv->permissions, g_free);
+ g_clear_object (&priv->subject);
+
+ g_clear_object (&priv->dbus_connection);
+
G_OBJECT_CLASS (nm_secret_agent_parent_class)->finalize (object);
_LOGT ("finalized");
diff --git a/src/settings/nm-secret-agent.h b/src/settings/nm-secret-agent.h
index 209a10094b..b85a8b8748 100644
--- a/src/settings/nm-secret-agent.h
+++ b/src/settings/nm-secret-agent.h
@@ -79,9 +79,6 @@ NMSecretAgentCallId *nm_secret_agent_get_secrets (NMSecretAgent *agent,
NMSecretAgentCallback callback,
gpointer callback_data);
-void nm_secret_agent_cancel_secrets (NMSecretAgent *agent,
- NMSecretAgentCallId *call_id);
-
NMSecretAgentCallId *nm_secret_agent_save_secrets (NMSecretAgent *agent,
const char *path,
NMConnection *connection,
@@ -94,4 +91,7 @@ NMSecretAgentCallId *nm_secret_agent_delete_secrets (NMSecretAgent *agent,
NMSecretAgentCallback callback,
gpointer callback_data);
+void nm_secret_agent_cancel_call (NMSecretAgent *self,
+ NMSecretAgentCallId *call_id);
+
#endif /* __NETWORKMANAGER_SECRET_AGENT_H__ */