mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-10 22:10:17 +01:00
settings: ensure an agent is authorized before overwriting system-owned secrets
If the agent returns system-owned secrets, like when activating a new connection which was created with no secrets, make sure the agent is authorized to modify network settings before saving or using the new secrets.
This commit is contained in:
parent
4ff0b5f0b7
commit
76aabe4b72
3 changed files with 325 additions and 22 deletions
|
|
@ -322,6 +322,7 @@ done:
|
|||
|
||||
typedef void (*RequestCompleteFunc) (Request *req,
|
||||
GHashTable *secrets,
|
||||
const char *agent_dbus_owner,
|
||||
GError *error,
|
||||
gpointer user_data);
|
||||
typedef void (*RequestNextFunc) (Request *req);
|
||||
|
|
@ -341,9 +342,7 @@ struct _Request {
|
|||
NMSecretAgent *current;
|
||||
gconstpointer current_call_id;
|
||||
|
||||
/* Stores the sorted list of NMSecretAgents which will be
|
||||
* asked for secrets.
|
||||
*/
|
||||
/* Stores the sorted list of NMSecretAgents which will be asked for secrets */
|
||||
GSList *pending;
|
||||
|
||||
/* Stores the list of NMSecretAgent hashes that we've already
|
||||
|
|
@ -584,7 +583,7 @@ next_generic (Request *req, const char *detail)
|
|||
error = g_error_new_literal (NM_AGENT_MANAGER_ERROR,
|
||||
NM_AGENT_MANAGER_ERROR_NO_SECRETS,
|
||||
"No agents were available for this request.");
|
||||
req->complete_callback (req, NULL, error, req->complete_callback_data);
|
||||
req->complete_callback (req, NULL, NULL, error, req->complete_callback_data);
|
||||
g_error_free (error);
|
||||
} else {
|
||||
/* Send a secrets request to the next agent */
|
||||
|
|
@ -622,6 +621,7 @@ get_done_cb (NMSecretAgent *agent,
|
|||
{
|
||||
Request *req = user_data;
|
||||
GHashTable *setting_secrets;
|
||||
const char *agent_dbus_owner;
|
||||
|
||||
g_return_if_fail (call_id == req->current_call_id);
|
||||
|
||||
|
|
@ -656,7 +656,8 @@ get_done_cb (NMSecretAgent *agent,
|
|||
nm_secret_agent_get_description (agent),
|
||||
req, req->setting_name);
|
||||
|
||||
req->complete_callback (req, secrets, NULL, req->complete_callback_data);
|
||||
agent_dbus_owner = nm_secret_agent_get_dbus_owner (agent);
|
||||
req->complete_callback (req, secrets, agent_dbus_owner, NULL, req->complete_callback_data);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -705,7 +706,7 @@ get_start (gpointer user_data)
|
|||
g_assert (tmp);
|
||||
|
||||
if (!nm_connection_update_secrets (tmp, req->setting_name, req->existing_secrets, &error)) {
|
||||
req->complete_callback (req, NULL, error, req->complete_callback_data);
|
||||
req->complete_callback (req, NULL, NULL, error, req->complete_callback_data);
|
||||
g_clear_error (&error);
|
||||
} else {
|
||||
/* Do we have everything we need? */
|
||||
|
|
@ -715,7 +716,7 @@ get_start (gpointer user_data)
|
|||
req, req->setting_name);
|
||||
|
||||
/* Got everything, we're done */
|
||||
req->complete_callback (req, req->existing_secrets, NULL, req->complete_callback_data);
|
||||
req->complete_callback (req, req->existing_secrets, NULL, NULL, req->complete_callback_data);
|
||||
} else {
|
||||
nm_log_dbg (LOGD_AGENTS, "(%p/%s) system settings secrets insufficient, asking agents",
|
||||
req, req->setting_name);
|
||||
|
|
@ -739,6 +740,7 @@ get_start (gpointer user_data)
|
|||
static void
|
||||
get_complete_cb (Request *req,
|
||||
GHashTable *secrets,
|
||||
const char *agent_dbus_owner,
|
||||
GError *error,
|
||||
gpointer user_data)
|
||||
{
|
||||
|
|
@ -748,7 +750,9 @@ get_complete_cb (Request *req,
|
|||
/* Send secrets back to the requesting object */
|
||||
req->callback (self,
|
||||
req->reqid,
|
||||
agent_dbus_owner,
|
||||
req->setting_name,
|
||||
req->flags,
|
||||
error ? NULL : secrets,
|
||||
error,
|
||||
req->callback_data,
|
||||
|
|
@ -837,6 +841,7 @@ save_done_cb (NMSecretAgent *agent,
|
|||
gpointer user_data)
|
||||
{
|
||||
Request *req = user_data;
|
||||
const char *agent_dbus_owner;
|
||||
|
||||
g_return_if_fail (call_id == req->current_call_id);
|
||||
|
||||
|
|
@ -859,7 +864,8 @@ save_done_cb (NMSecretAgent *agent,
|
|||
nm_secret_agent_get_description (agent),
|
||||
req, req->setting_name);
|
||||
|
||||
req->complete_callback (req, NULL, NULL, req->complete_callback_data);
|
||||
agent_dbus_owner = nm_secret_agent_get_dbus_owner (agent);
|
||||
req->complete_callback (req, NULL, agent_dbus_owner, NULL, req->complete_callback_data);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -883,6 +889,7 @@ save_next_cb (Request *req)
|
|||
static void
|
||||
save_complete_cb (Request *req,
|
||||
GHashTable *secrets,
|
||||
const char *agent_dbus_owner,
|
||||
GError *error,
|
||||
gpointer user_data)
|
||||
{
|
||||
|
|
@ -977,6 +984,7 @@ delete_next_cb (Request *req)
|
|||
static void
|
||||
delete_complete_cb (Request *req,
|
||||
GHashTable *secrets,
|
||||
const char *agent_dbus_owner,
|
||||
GError *error,
|
||||
gpointer user_data)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -44,9 +44,12 @@ GType nm_agent_manager_get_type (void);
|
|||
|
||||
NMAgentManager *nm_agent_manager_get (void);
|
||||
|
||||
/* If no agent fulfilled the secrets request, agent_dbus_owner will be NULL */
|
||||
typedef void (*NMAgentSecretsResultFunc) (NMAgentManager *manager,
|
||||
guint32 call_id,
|
||||
const char *agent_dbus_owner,
|
||||
const char *setting_name,
|
||||
guint32 flags,
|
||||
GHashTable *secrets,
|
||||
GError *error,
|
||||
gpointer user_data,
|
||||
|
|
|
|||
|
|
@ -352,10 +352,216 @@ supports_secrets (NMSettingsConnection *connection, const char *setting_name)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/* Return TRUE to continue, FALSE to stop */
|
||||
typedef gboolean (*ForEachSecretFunc) (GHashTableIter *iter,
|
||||
NMSettingSecretFlags flags,
|
||||
gpointer user_data);
|
||||
|
||||
static gboolean
|
||||
clear_system_owned_secrets (GHashTableIter *iter,
|
||||
NMSettingSecretFlags flags,
|
||||
gpointer user_data)
|
||||
{
|
||||
if (flags == NM_SETTING_SECRET_FLAG_SYSTEM_OWNED)
|
||||
g_hash_table_iter_remove (iter);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
has_system_owned_secrets (GHashTableIter *iter,
|
||||
NMSettingSecretFlags flags,
|
||||
gpointer user_data)
|
||||
{
|
||||
gboolean *has_system_owned = user_data;
|
||||
|
||||
if (flags == NM_SETTING_SECRET_FLAG_SYSTEM_OWNED) {
|
||||
*has_system_owned = TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
for_each_secret (NMConnection *connection,
|
||||
GHashTable *secrets,
|
||||
ForEachSecretFunc callback,
|
||||
gpointer callback_data)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
const char *setting_name;
|
||||
GHashTable *setting_hash;
|
||||
|
||||
/* Walk through the list of setting hashes */
|
||||
g_hash_table_iter_init (&iter, secrets);
|
||||
while (g_hash_table_iter_next (&iter,
|
||||
(gpointer *) &setting_name,
|
||||
(gpointer *) &setting_hash)) {
|
||||
GHashTableIter setting_iter;
|
||||
const char *secret_name;
|
||||
|
||||
/* Walk through the list of keys in each setting hash */
|
||||
g_hash_table_iter_init (&setting_iter, setting_hash);
|
||||
while (g_hash_table_iter_next (&setting_iter, (gpointer *) &secret_name, NULL)) {
|
||||
NMSetting *setting;
|
||||
NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_SYSTEM_OWNED;
|
||||
|
||||
/* Get the actual NMSetting from the connection so we can get secret flags */
|
||||
setting = nm_connection_get_setting_by_name (connection, setting_name);
|
||||
if (setting && nm_setting_get_secret_flags (setting, secret_name, &flags, NULL)) {
|
||||
if (callback (&setting_iter, flags, callback_data) == FALSE)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
new_secrets_commit_cb (NMSettingsConnection *connection,
|
||||
GError *error,
|
||||
gpointer user_data)
|
||||
{
|
||||
if (error) {
|
||||
nm_log_warn (LOGD_SETTINGS, "Error saving new secrets to backing storage: (%d) %s",
|
||||
error->code, error->message ? error->message : "(unknown)");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
get_secrets_done (NMSettingsConnection *self,
|
||||
guint32 call_id,
|
||||
const char *setting_name,
|
||||
GHashTable *secrets,
|
||||
GError *error,
|
||||
NMSettingsConnectionSecretsFunc callback,
|
||||
gpointer callback_data)
|
||||
{
|
||||
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
|
||||
NMSettingConnection *s_con;
|
||||
GError *local = NULL;
|
||||
GHashTable *hash = NULL;
|
||||
|
||||
s_con = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (self), NM_TYPE_SETTING_CONNECTION);
|
||||
g_assert (s_con);
|
||||
|
||||
if (error) {
|
||||
nm_log_dbg (LOGD_SETTINGS, "(%s/%s:%u) secrets request completed; error: (%d) %s",
|
||||
nm_setting_connection_get_uuid (s_con),
|
||||
setting_name,
|
||||
call_id,
|
||||
error->code,
|
||||
error->message ? error->message : "(unknown)");
|
||||
callback (self, call_id, setting_name, error, callback_data);
|
||||
return;
|
||||
}
|
||||
|
||||
nm_log_dbg (LOGD_SETTINGS, "(%s/%s:%u) secrets request completed successfully",
|
||||
nm_setting_connection_get_uuid (s_con),
|
||||
setting_name,
|
||||
call_id);
|
||||
|
||||
/* Update the connection with our existing secrets from backing storage */
|
||||
nm_connection_clear_secrets (NM_CONNECTION (self));
|
||||
hash = nm_connection_to_hash (priv->secrets, NM_SETTING_HASH_FLAG_ONLY_SECRETS);
|
||||
if (nm_connection_update_secrets (NM_CONNECTION (self), setting_name, hash, &local)) {
|
||||
/* Update the connection with the agent's secrets; by this point if any
|
||||
* system-owned secrets exist in 'secrets' the agent that provided them
|
||||
* will have been authenticated, so those secrets can replace the existing
|
||||
* system secrets.
|
||||
*/
|
||||
if (nm_connection_update_secrets (NM_CONNECTION (self), setting_name, secrets, &local)) {
|
||||
/* Now that all secrets are updated, copy and cache new secrets,
|
||||
* then save them to backing storage.
|
||||
*/
|
||||
if (priv->secrets)
|
||||
g_object_unref (priv->secrets);
|
||||
priv->secrets = nm_connection_duplicate (NM_CONNECTION (self));
|
||||
|
||||
nm_log_dbg (LOGD_SETTINGS, "(%s/%s:%u) saving new secrets to backing storage",
|
||||
nm_setting_connection_get_uuid (s_con),
|
||||
setting_name,
|
||||
call_id);
|
||||
|
||||
nm_settings_connection_commit_changes (self, new_secrets_commit_cb, NULL);
|
||||
} else {
|
||||
nm_log_dbg (LOGD_SETTINGS, "(%s/%s:%u) failed to update with agent secrets: (%d) %s",
|
||||
nm_setting_connection_get_uuid (s_con),
|
||||
setting_name,
|
||||
call_id,
|
||||
local->code,
|
||||
local->message ? local->message : "(unknown)");
|
||||
}
|
||||
} else {
|
||||
nm_log_dbg (LOGD_SETTINGS, "(%s/%s:%u) failed to update with existing secrets: (%d) %s",
|
||||
nm_setting_connection_get_uuid (s_con),
|
||||
setting_name,
|
||||
call_id,
|
||||
local->code,
|
||||
local->message ? local->message : "(unknown)");
|
||||
}
|
||||
|
||||
callback (self, call_id, setting_name, local, callback_data);
|
||||
g_clear_error (&local);
|
||||
if (hash)
|
||||
g_hash_table_destroy (hash);
|
||||
}
|
||||
|
||||
static void
|
||||
agent_secrets_modify_auth_cb (NMAuthChain *chain,
|
||||
GError *error,
|
||||
DBusGMethodInvocation *context,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMSettingsConnection *self = NM_SETTINGS_CONNECTION (user_data);
|
||||
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
|
||||
NMSettingConnection *s_con;
|
||||
NMAuthCallResult result;
|
||||
GHashTable *secrets = nm_auth_chain_get_data (chain, "secrets");
|
||||
const char *setting_name = nm_auth_chain_get_data (chain, "setting-name");
|
||||
guint32 call_id = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "call-id"));
|
||||
|
||||
s_con = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (self), NM_TYPE_SETTING_CONNECTION);
|
||||
g_assert (s_con);
|
||||
|
||||
priv->pending_auths = g_slist_remove (priv->pending_auths, chain);
|
||||
|
||||
result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_SETTINGS_CONNECTION_MODIFY);
|
||||
|
||||
nm_log_dbg (LOGD_SETTINGS, "(%s/%s:%u) agent MODIFY check result %d",
|
||||
nm_setting_connection_get_uuid (s_con),
|
||||
setting_name,
|
||||
call_id,
|
||||
result);
|
||||
|
||||
if (result == NM_AUTH_CALL_RESULT_YES) {
|
||||
/* Agent can modify system connections; system-owned secrets it returned
|
||||
* replace any secrets in backing storage.
|
||||
*/
|
||||
} else {
|
||||
/* Agent didn't successfully authenticate; clear system-owned secrets
|
||||
* from the secrets the agent returned.
|
||||
*/
|
||||
nm_log_dbg (LOGD_SETTINGS, "(%s/%s:%u) agent failed to authenticate after providing system secrets",
|
||||
nm_setting_connection_get_uuid (s_con),
|
||||
setting_name,
|
||||
call_id);
|
||||
for_each_secret (NM_CONNECTION (self), secrets, clear_system_owned_secrets, NULL);
|
||||
}
|
||||
|
||||
get_secrets_done (self,
|
||||
call_id,
|
||||
setting_name,
|
||||
secrets,
|
||||
error,
|
||||
nm_auth_chain_get_data (chain, "callback"),
|
||||
nm_auth_chain_get_data (chain, "callback_data"));
|
||||
}
|
||||
|
||||
static void
|
||||
agent_secrets_done_cb (NMAgentManager *manager,
|
||||
guint32 call_id,
|
||||
const char *agent_dbus_owner,
|
||||
const char *setting_name,
|
||||
guint32 flags,
|
||||
GHashTable *secrets,
|
||||
GError *error,
|
||||
gpointer user_data,
|
||||
|
|
@ -366,29 +572,100 @@ agent_secrets_done_cb (NMAgentManager *manager,
|
|||
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
|
||||
NMSettingsConnectionSecretsFunc callback = other_data2;
|
||||
gpointer callback_data = other_data3;
|
||||
NMSettingConnection *s_con;
|
||||
GError *local = NULL;
|
||||
GHashTable *hash;
|
||||
|
||||
s_con = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (self), NM_TYPE_SETTING_CONNECTION);
|
||||
g_assert (s_con);
|
||||
|
||||
if (error) {
|
||||
nm_log_dbg (LOGD_SETTINGS, "(%s/%s:%u) secrets request error: (%d) %s",
|
||||
nm_setting_connection_get_uuid (s_con),
|
||||
setting_name,
|
||||
call_id,
|
||||
error->code,
|
||||
error->message ? error->message : "(unknown)");
|
||||
|
||||
callback (self, call_id, setting_name, error, callback_data);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Update the connection with the agent's secrets */
|
||||
nm_connection_clear_secrets (NM_CONNECTION (self));
|
||||
if (nm_connection_update_secrets (NM_CONNECTION (self), setting_name, secrets, &local)) {
|
||||
/* FIXME: if the agent's owner has "modify" permission, then agent
|
||||
* supplied secrets should overwrite existing secrets, and those agent
|
||||
* supplied secrets should get written back out to persistent storage.
|
||||
*/
|
||||
|
||||
hash = nm_connection_to_hash (priv->secrets, NM_SETTING_HASH_FLAG_ONLY_SECRETS);
|
||||
nm_connection_update_secrets (NM_CONNECTION (self), setting_name, hash, &local);
|
||||
g_hash_table_destroy (hash);
|
||||
if (!nm_connection_get_setting_by_name (NM_CONNECTION (self), setting_name)) {
|
||||
local = g_error_new (NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_SETTING,
|
||||
"%s.%d - Connection didn't have requested setting '%s'.",
|
||||
__FILE__, __LINE__, setting_name);
|
||||
callback (self, call_id, setting_name, local, callback_data);
|
||||
g_clear_error (&local);
|
||||
return;
|
||||
}
|
||||
|
||||
callback (self, call_id, setting_name, local, callback_data);
|
||||
g_clear_error (&local);
|
||||
g_assert (secrets);
|
||||
if (agent_dbus_owner) {
|
||||
gboolean has_system = FALSE;
|
||||
|
||||
nm_log_dbg (LOGD_SETTINGS, "(%s/%s:%u) secrets returned from agent %s",
|
||||
nm_setting_connection_get_uuid (s_con),
|
||||
setting_name,
|
||||
call_id,
|
||||
agent_dbus_owner);
|
||||
|
||||
/* If the agent returned any system-owned secrets (initial connect and no
|
||||
* secrets given when the connection was created, or something like that)
|
||||
* make sure the agent's UID has the 'modify' permission before we use or
|
||||
* save those system-owned secrets. If not, discard them and use the
|
||||
* existing secrets, or fail the connection.
|
||||
*/
|
||||
for_each_secret (NM_CONNECTION (self), secrets, has_system_owned_secrets, &has_system);
|
||||
if (has_system) {
|
||||
if (flags == 0) { /* ie SECRETS_FLAG_NONE */
|
||||
/* No user interaction was allowed when requesting secrets; the
|
||||
* agent is being bad. Remove system-owned secrets.
|
||||
*/
|
||||
for_each_secret (NM_CONNECTION (self), secrets, clear_system_owned_secrets, NULL);
|
||||
|
||||
nm_log_dbg (LOGD_SETTINGS, "(%s/%s:%u) interaction forbidden but agent %s returned system secrets",
|
||||
nm_setting_connection_get_uuid (s_con),
|
||||
setting_name,
|
||||
call_id,
|
||||
agent_dbus_owner);
|
||||
} else {
|
||||
NMAuthChain *chain;
|
||||
|
||||
nm_log_dbg (LOGD_SETTINGS, "(%s/%s:%u) agent %s returned system secrets; checking for MODIFY",
|
||||
nm_setting_connection_get_uuid (s_con),
|
||||
setting_name,
|
||||
call_id,
|
||||
agent_dbus_owner);
|
||||
|
||||
/* User interaction was allowed, check whether the agent's UID
|
||||
* has the 'modify' privilege before using the system-owned
|
||||
* secrets supplied by the agent.
|
||||
*/
|
||||
chain = nm_auth_chain_new_dbus_sender (priv->authority,
|
||||
agent_dbus_owner,
|
||||
agent_secrets_modify_auth_cb,
|
||||
self);
|
||||
g_assert (chain);
|
||||
|
||||
nm_auth_chain_set_data (chain, "call-id", GUINT_TO_POINTER (call_id), NULL);
|
||||
nm_auth_chain_set_data (chain, "setting-name", g_strdup (setting_name), g_free);
|
||||
nm_auth_chain_set_data (chain, "secrets", g_hash_table_ref (secrets), (GDestroyNotify) g_hash_table_unref);
|
||||
nm_auth_chain_set_data (chain, "callback", callback, NULL);
|
||||
nm_auth_chain_set_data (chain, "callback-data", callback_data, NULL);
|
||||
|
||||
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SETTINGS_CONNECTION_MODIFY, TRUE);
|
||||
priv->pending_auths = g_slist_append (priv->pending_auths, chain);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
nm_log_dbg (LOGD_SETTINGS, "(%s/%s:%u) existing secrets returned",
|
||||
nm_setting_connection_get_uuid (s_con),
|
||||
setting_name,
|
||||
call_id);
|
||||
}
|
||||
|
||||
get_secrets_done (self, call_id, setting_name, secrets, error, callback, callback_data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -421,6 +698,7 @@ nm_settings_connection_get_secrets (NMSettingsConnection *self,
|
|||
GError **error)
|
||||
{
|
||||
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
|
||||
NMSettingConnection *s_con;
|
||||
GHashTable *existing_secrets;
|
||||
guint32 call_id = 0;
|
||||
|
||||
|
|
@ -460,6 +738,14 @@ nm_settings_connection_get_secrets (NMSettingsConnection *self,
|
|||
callback_data);
|
||||
g_hash_table_unref (existing_secrets);
|
||||
|
||||
s_con = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (self), NM_TYPE_SETTING_CONNECTION);
|
||||
nm_log_dbg (LOGD_SETTINGS, "(%s/%s:%u) secrets requested flags 0x%X hint '%s'",
|
||||
nm_setting_connection_get_uuid (s_con),
|
||||
setting_name,
|
||||
call_id,
|
||||
flags,
|
||||
hint);
|
||||
|
||||
return call_id;
|
||||
}
|
||||
|
||||
|
|
@ -468,6 +754,12 @@ nm_settings_connection_cancel_secrets (NMSettingsConnection *self,
|
|||
guint32 call_id)
|
||||
{
|
||||
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
|
||||
NMSettingConnection *s_con;
|
||||
|
||||
s_con = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (self), NM_TYPE_SETTING_CONNECTION);
|
||||
nm_log_dbg (LOGD_SETTINGS, "(%s:%u) secrets canceled",
|
||||
nm_setting_connection_get_uuid (s_con),
|
||||
call_id);
|
||||
|
||||
priv->reqs = g_slist_remove (priv->reqs, GUINT_TO_POINTER (call_id));
|
||||
nm_agent_manager_cancel_secrets (priv->agent_mgr, call_id);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue