agent: ask secret agents for secrets when connection doesn't have any
Filter registered agents for each secrets request to ensure that the connection for which secrets are requested is visible to that agent, and add that agent to the queue. Ask each agent in the queue until one returns usable secrets. Ensure that if new agents register or existing agents quit during the secrets request, that the queue is updated accordingly, and ensure that an agent that's already been asked for secrets, unregisters, and re-registers before the secrets request is comple, isn't asked for secrets twice.
This commit is contained in:
@@ -92,63 +92,6 @@ enum {
|
||||
|
||||
/*******************************************************************/
|
||||
|
||||
#if 0
|
||||
static gboolean
|
||||
secrets_update_setting (NMSecretsProviderInterface *interface,
|
||||
const char *setting_name,
|
||||
GHashTable *new)
|
||||
{
|
||||
NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (interface);
|
||||
NMSetting *setting = NULL;
|
||||
GError *error = NULL;
|
||||
GType type;
|
||||
|
||||
g_return_val_if_fail (priv->connection != NULL, FALSE);
|
||||
|
||||
/* Check whether a complete & valid NMSetting object was returned. If
|
||||
* yes, replace the setting object in the connection. If not, just try
|
||||
* updating the secrets.
|
||||
*/
|
||||
type = nm_connection_lookup_setting_type (setting_name);
|
||||
if (type == 0)
|
||||
return FALSE;
|
||||
|
||||
setting = nm_setting_new_from_hash (type, new);
|
||||
if (setting) {
|
||||
NMSetting *s_8021x = NULL;
|
||||
GSList *all_settings = NULL;
|
||||
|
||||
/* The wireless-security setting might need the 802.1x setting in
|
||||
* the all_settings argument of the verify function. Ugh.
|
||||
*/
|
||||
s_8021x = nm_connection_get_setting (priv->connection, NM_TYPE_SETTING_802_1X);
|
||||
if (s_8021x)
|
||||
all_settings = g_slist_append (all_settings, s_8021x);
|
||||
|
||||
if (!nm_setting_verify (setting, all_settings, NULL)) {
|
||||
/* Just try updating secrets */
|
||||
g_object_unref (setting);
|
||||
setting = NULL;
|
||||
}
|
||||
|
||||
g_slist_free (all_settings);
|
||||
}
|
||||
|
||||
if (setting)
|
||||
nm_connection_add_setting (priv->connection, setting);
|
||||
else {
|
||||
if (!nm_connection_update_secrets (priv->connection, setting_name, new, &error)) {
|
||||
nm_log_warn (LOGD_DEVICE, "Failed to update connection secrets: %d %s",
|
||||
error ? error->code : -1,
|
||||
error && error->message ? error->message : "(none)");
|
||||
g_clear_error (&error);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
get_secrets_cb (NMAgentManager *manager,
|
||||
guint32 call_id,
|
||||
|
@@ -32,6 +32,7 @@
|
||||
#include "nm-secret-agent.h"
|
||||
#include "nm-manager-auth.h"
|
||||
#include "nm-sysconfig-connection.h"
|
||||
#include "nm-dbus-glib-types.h"
|
||||
|
||||
G_DEFINE_TYPE (NMAgentManager, nm_agent_manager, G_TYPE_OBJECT)
|
||||
|
||||
@@ -53,6 +54,13 @@ typedef struct {
|
||||
GHashTable *requests;
|
||||
} NMAgentManagerPrivate;
|
||||
|
||||
typedef struct _Request Request;
|
||||
|
||||
static void request_add_agent (Request *req,
|
||||
NMSecretAgent *agent,
|
||||
NMSessionMonitor *session_monitor);
|
||||
|
||||
static void request_remove_agent (Request *req, NMSecretAgent *agent);
|
||||
|
||||
static void impl_agent_manager_register (NMAgentManager *self,
|
||||
const char *identifier,
|
||||
@@ -74,7 +82,8 @@ typedef enum {
|
||||
NM_AGENT_MANAGER_ERROR_SESSION_NOT_FOUND,
|
||||
NM_AGENT_MANAGER_ERROR_INVALID_IDENTIFIER,
|
||||
NM_AGENT_MANAGER_ERROR_NOT_REGISTERED,
|
||||
NM_AGENT_MANAGER_ERROR_INTERNAL_ERROR
|
||||
NM_AGENT_MANAGER_ERROR_INTERNAL_ERROR,
|
||||
NM_AGENT_MANAGER_ERROR_NO_SECRETS
|
||||
} NMAgentManagerError;
|
||||
|
||||
static GQuark
|
||||
@@ -108,6 +117,8 @@ nm_agent_manager_error_get_type (void)
|
||||
ENUM_ENTRY (NM_AGENT_MANAGER_ERROR_NOT_REGISTERED, "NotRegistered"),
|
||||
/* Some internal error occurred */
|
||||
ENUM_ENTRY (NM_AGENT_MANAGER_ERROR_INTERNAL_ERROR, "InternalError"),
|
||||
/* No secrets were available */
|
||||
ENUM_ENTRY (NM_AGENT_MANAGER_ERROR_NO_SECRETS, "NoSecrets"),
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
@@ -123,20 +134,25 @@ remove_agent (NMAgentManager *self, const char *owner)
|
||||
{
|
||||
NMAgentManagerPrivate *priv = NM_AGENT_MANAGER_GET_PRIVATE (self);
|
||||
NMSecretAgent *agent;
|
||||
GHashTableIter iter;
|
||||
gpointer data;
|
||||
|
||||
g_return_val_if_fail (owner != NULL, FALSE);
|
||||
|
||||
/* Make sure this agent has already registered */
|
||||
agent = g_hash_table_lookup (priv->agents, owner);
|
||||
if (!agent)
|
||||
return FALSE;
|
||||
|
||||
/* FIXME: signal agent removal */
|
||||
nm_log_dbg (LOGD_AGENTS, "(%s) agent unregistered",
|
||||
nm_secret_agent_get_description (agent));
|
||||
|
||||
nm_log_dbg (LOGD_AGENTS, "(%s/%s) agent unregistered for UID %ld",
|
||||
nm_secret_agent_get_dbus_owner (agent),
|
||||
nm_secret_agent_get_identifier (agent),
|
||||
nm_secret_agent_get_owner_uid (agent));
|
||||
/* Remove this agent to any in-progress secrets requests */
|
||||
g_hash_table_iter_init (&iter, priv->requests);
|
||||
while (g_hash_table_iter_next (&iter, NULL, &data))
|
||||
request_remove_agent ((Request *) data, agent);
|
||||
|
||||
/* And dispose of the agent */
|
||||
g_hash_table_remove (priv->agents, owner);
|
||||
return TRUE;
|
||||
}
|
||||
@@ -208,6 +224,8 @@ impl_agent_manager_register (NMAgentManager *self,
|
||||
gulong sender_uid = G_MAXULONG;
|
||||
GError *error = NULL, *local = NULL;
|
||||
NMSecretAgent *agent;
|
||||
GHashTableIter iter;
|
||||
gpointer data;
|
||||
|
||||
if (!nm_auth_get_caller_uid (context,
|
||||
priv->dbus_mgr,
|
||||
@@ -243,7 +261,7 @@ impl_agent_manager_register (NMAgentManager *self,
|
||||
goto done;
|
||||
|
||||
/* Success, add the new agent */
|
||||
agent = nm_secret_agent_new (sender, identifier, sender_uid);
|
||||
agent = nm_secret_agent_new (priv->dbus_mgr, sender, identifier, sender_uid);
|
||||
if (!agent) {
|
||||
error = g_error_new_literal (NM_AGENT_MANAGER_ERROR,
|
||||
NM_AGENT_MANAGER_ERROR_INTERNAL_ERROR,
|
||||
@@ -252,12 +270,15 @@ impl_agent_manager_register (NMAgentManager *self,
|
||||
}
|
||||
|
||||
g_hash_table_insert (priv->agents, g_strdup (sender), agent);
|
||||
nm_log_dbg (LOGD_AGENTS, "(%s/%s) agent registered for UID %ld",
|
||||
nm_secret_agent_get_dbus_owner (agent),
|
||||
nm_secret_agent_get_identifier (agent),
|
||||
nm_secret_agent_get_owner_uid (agent));
|
||||
nm_log_dbg (LOGD_AGENTS, "(%s) agent registered",
|
||||
nm_secret_agent_get_description (agent));
|
||||
dbus_g_method_return (context);
|
||||
|
||||
/* Add this agent to any in-progress secrets requests */
|
||||
g_hash_table_iter_init (&iter, priv->requests);
|
||||
while (g_hash_table_iter_next (&iter, NULL, &data))
|
||||
request_add_agent ((Request *) data, agent, priv->session_monitor);
|
||||
|
||||
done:
|
||||
if (error)
|
||||
dbus_g_method_return_error (context, error);
|
||||
@@ -300,9 +321,6 @@ done:
|
||||
|
||||
/*************************************************************/
|
||||
|
||||
typedef struct _Request Request;
|
||||
|
||||
typedef void (*RequestNextFunc) (Request *req, gpointer user_data);
|
||||
typedef void (*RequestCompleteFunc) (Request *req,
|
||||
GHashTable *secrets,
|
||||
GError *error,
|
||||
@@ -316,6 +334,21 @@ struct _Request {
|
||||
gboolean request_new;
|
||||
char *hint;
|
||||
|
||||
/* Current agent being asked for secrets */
|
||||
NMSecretAgent *current;
|
||||
gpointer current_call_id;
|
||||
|
||||
/* Stores the sorted list of NMSecretAgents which will be
|
||||
* asked for secrets.
|
||||
*/
|
||||
GSList *pending;
|
||||
|
||||
/* Stores the list of NMSecretAgent hashes that we've already
|
||||
* asked for secrets, so that we don't ask the same agent twice
|
||||
* if it quits and re-registers during this secrets request.
|
||||
*/
|
||||
GSList *asked;
|
||||
|
||||
guint32 idle_id;
|
||||
|
||||
NMAgentSecretsResultFunc callback;
|
||||
@@ -323,9 +356,8 @@ struct _Request {
|
||||
gpointer other_data2;
|
||||
gpointer other_data3;
|
||||
|
||||
RequestNextFunc next_callback;
|
||||
RequestCompleteFunc complete_callback;
|
||||
gpointer req_callback_data;
|
||||
gpointer complete_callback_data;
|
||||
};
|
||||
|
||||
static Request *
|
||||
@@ -336,7 +368,9 @@ request_new (NMConnection *connection,
|
||||
NMAgentSecretsResultFunc callback,
|
||||
gpointer callback_data,
|
||||
gpointer other_data2,
|
||||
gpointer other_data3)
|
||||
gpointer other_data3,
|
||||
RequestCompleteFunc complete_callback,
|
||||
gpointer complete_callback_data)
|
||||
{
|
||||
Request *req;
|
||||
static guint32 next_id = 1;
|
||||
@@ -351,6 +385,8 @@ request_new (NMConnection *connection,
|
||||
req->callback_data = callback_data;
|
||||
req->other_data2 = other_data2;
|
||||
req->other_data3 = other_data3;
|
||||
req->complete_callback = complete_callback;
|
||||
req->complete_callback_data = complete_callback_data;
|
||||
|
||||
return req;
|
||||
}
|
||||
@@ -361,6 +397,11 @@ request_free (Request *req)
|
||||
if (req->idle_id)
|
||||
g_source_remove (req->idle_id);
|
||||
|
||||
if (req->current && req->current_call_id)
|
||||
nm_secret_agent_cancel_secrets (req->current, req->current_call_id);
|
||||
|
||||
g_slist_free (req->pending);
|
||||
g_slist_free (req->asked);
|
||||
g_object_unref (req->connection);
|
||||
g_free (req->setting_name);
|
||||
g_free (req->hint);
|
||||
@@ -368,15 +409,97 @@ request_free (Request *req)
|
||||
g_free (req);
|
||||
}
|
||||
|
||||
static void request_next (Request *req);
|
||||
|
||||
static void
|
||||
request_set_callbacks (Request *req,
|
||||
RequestNextFunc next_func,
|
||||
RequestCompleteFunc complete_func,
|
||||
gpointer user_data)
|
||||
request_secrets_done_cb (DBusGProxy *proxy,
|
||||
DBusGProxyCall *call_id,
|
||||
void *user_data)
|
||||
{
|
||||
req->next_callback = next_func;
|
||||
req->complete_callback = complete_func;
|
||||
req->req_callback_data = user_data;
|
||||
Request *req = user_data;
|
||||
GError *error = NULL;
|
||||
GHashTable *secrets = NULL;
|
||||
GHashTable *setting_secrets;
|
||||
NMSecretAgent *agent = NM_SECRET_AGENT (req->current);
|
||||
|
||||
if (call_id != req->current_call_id)
|
||||
return;
|
||||
|
||||
req->current = NULL;
|
||||
req->current_call_id = NULL;
|
||||
|
||||
if (!dbus_g_proxy_end_call (proxy, call_id, &error,
|
||||
DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, &secrets,
|
||||
G_TYPE_INVALID)) {
|
||||
nm_log_dbg (LOGD_AGENTS, "(%s) agent failed secrets request %p/%s: (%d) %s",
|
||||
nm_secret_agent_get_description (agent),
|
||||
req, req->setting_name,
|
||||
error ? error->code : -1,
|
||||
(error && error->message) ? error->message : "(unknown)");
|
||||
|
||||
/* Try the next agent */
|
||||
request_next (req);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ensure the setting we wanted secrets for got returned and has something in it */
|
||||
setting_secrets = g_hash_table_lookup (secrets, req->setting_name);
|
||||
if (!setting_secrets || !g_hash_table_size (setting_secrets)) {
|
||||
nm_log_dbg (LOGD_AGENTS, "(%s) agent returned no secrets for request %p/%s",
|
||||
nm_secret_agent_get_description (agent),
|
||||
req, req->setting_name);
|
||||
g_hash_table_destroy (secrets);
|
||||
|
||||
/* Try the next agent */
|
||||
request_next (req);
|
||||
return;
|
||||
}
|
||||
|
||||
nm_log_dbg (LOGD_AGENTS, "(%s) agent returned secrets for request %p/%s",
|
||||
nm_secret_agent_get_description (agent),
|
||||
req, req->setting_name);
|
||||
|
||||
/* Success! */
|
||||
req->complete_callback (req, secrets, NULL, req->complete_callback_data);
|
||||
g_hash_table_destroy (secrets);
|
||||
}
|
||||
|
||||
static void
|
||||
request_next (Request *req)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (req->pending == NULL) {
|
||||
/* No more secret agents are available to fulfill this secrets request */
|
||||
error = g_error_new_literal (NM_AGENT_MANAGER_ERROR,
|
||||
NM_AGENT_MANAGER_ERROR_NO_SECRETS,
|
||||
"No secrets were available for this request.");
|
||||
req->complete_callback (req, NULL, error, req->complete_callback_data);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Send a secrets request to the next agent */
|
||||
req->current = req->pending->data;
|
||||
req->pending = g_slist_remove (req->pending, req->current);
|
||||
|
||||
nm_log_dbg (LOGD_AGENTS, "(%s) agent getting secrets for request %p/%s",
|
||||
nm_secret_agent_get_description (req->current),
|
||||
req, req->setting_name);
|
||||
|
||||
req->current_call_id = nm_secret_agent_get_secrets (NM_SECRET_AGENT (req->current),
|
||||
req->connection,
|
||||
req->setting_name,
|
||||
req->hint,
|
||||
req->request_new,
|
||||
request_secrets_done_cb,
|
||||
req);
|
||||
if (req->current_call_id == NULL) {
|
||||
/* Shouldn't hit this, but handle it anyway */
|
||||
g_warn_if_fail (req->current_call_id != NULL);
|
||||
req->current = NULL;
|
||||
request_next (req);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -393,39 +516,135 @@ request_start_secrets (gpointer user_data)
|
||||
req->hint,
|
||||
req->request_new,
|
||||
&error);
|
||||
if (secrets) {
|
||||
if (secrets && g_hash_table_size (secrets)) {
|
||||
/* The connection already had secrets, no need to get any */
|
||||
req->complete_callback (req, secrets, NULL, req->req_callback_data);
|
||||
g_hash_table_destroy (secrets);
|
||||
} else if (error)
|
||||
req->complete_callback (req, NULL, error, req->req_callback_data);
|
||||
else {
|
||||
req->complete_callback (req, secrets, NULL, req->complete_callback_data);
|
||||
} else if (error) {
|
||||
/* Errors from the system settings are hard errors; we don't go on
|
||||
* to ask agents for secrets if the settings service failed.
|
||||
*/
|
||||
req->complete_callback (req, NULL, error, req->complete_callback_data);
|
||||
g_error_free (error);
|
||||
} else {
|
||||
/* Couldn't get secrets from system settings, so now we ask the
|
||||
* agents for secrets. Let the Agent Manager handle which agents
|
||||
* we'll ask and in which order.
|
||||
*/
|
||||
req->next_callback (req, req->req_callback_data);
|
||||
request_next (req);
|
||||
}
|
||||
|
||||
g_clear_error (&error);
|
||||
if (secrets)
|
||||
g_hash_table_destroy (secrets);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*************************************************************/
|
||||
static gint
|
||||
agent_compare_func (NMSecretAgent *a, NMSecretAgent *b, gpointer user_data)
|
||||
{
|
||||
NMSessionMonitor *session_monitor = NM_SESSION_MONITOR (user_data);
|
||||
gboolean a_active, b_active;
|
||||
|
||||
if (a && !b)
|
||||
return -1;
|
||||
else if (a == b)
|
||||
return 0;
|
||||
else if (!a && b)
|
||||
return 1;
|
||||
|
||||
/* Prefer agents in active sessions */
|
||||
a_active = nm_session_monitor_uid_active (session_monitor,
|
||||
nm_secret_agent_get_owner_uid (a),
|
||||
NULL);
|
||||
b_active = nm_session_monitor_uid_active (session_monitor,
|
||||
nm_secret_agent_get_owner_uid (b),
|
||||
NULL);
|
||||
if (a_active && !b_active)
|
||||
return -1;
|
||||
else if (a_active == b_active)
|
||||
return 0;
|
||||
else if (!a_active && b_active)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mgr_req_next_cb (Request *req, gpointer user_data)
|
||||
request_add_agent (Request *req,
|
||||
NMSecretAgent *agent,
|
||||
NMSessionMonitor *session_monitor)
|
||||
{
|
||||
#if 0
|
||||
NMAgentManager *self = NM_AGENT_MANAGER (user_data);
|
||||
NMAgentManagerPrivate *priv = NM_AGENT_MANAGER_GET_PRIVATE (self);
|
||||
uid_t agent_uid;
|
||||
|
||||
/* Look for the next agent to call for secrets based on whether that
|
||||
* agent's user is in the connection's ACL.
|
||||
g_return_if_fail (req != NULL);
|
||||
g_return_if_fail (agent != NULL);
|
||||
|
||||
if (g_slist_find (req->asked, GUINT_TO_POINTER (nm_secret_agent_get_hash (agent))))
|
||||
return;
|
||||
|
||||
/* Ensure the caller's username exists in the connection's permissions,
|
||||
* or that the permissions is empty (ie, visible by everyone).
|
||||
*/
|
||||
#endif
|
||||
agent_uid = nm_secret_agent_get_owner_uid (agent);
|
||||
if (0 != agent_uid) {
|
||||
if (!nm_auth_uid_in_acl (req->connection, session_monitor, agent_uid, NULL)) {
|
||||
nm_log_dbg (LOGD_AGENTS, "(%s) agent ignored for secrets request %p/%s",
|
||||
nm_secret_agent_get_description (agent),
|
||||
req, req->setting_name);
|
||||
/* Connection not visible to this agent's user */
|
||||
return;
|
||||
}
|
||||
/* Caller is allowed to add this connection */
|
||||
}
|
||||
|
||||
nm_log_dbg (LOGD_AGENTS, "(%s) agent allowed for secrets request %p/%s",
|
||||
nm_secret_agent_get_description (agent),
|
||||
req, req->setting_name);
|
||||
|
||||
/* Add this agent to the list, preferring active sessions */
|
||||
req->pending = g_slist_insert_sorted_with_data (req->pending,
|
||||
agent,
|
||||
(GCompareDataFunc) agent_compare_func,
|
||||
session_monitor);
|
||||
}
|
||||
|
||||
static void
|
||||
request_remove_agent (Request *req, NMSecretAgent *agent)
|
||||
{
|
||||
gboolean try_next = FALSE;
|
||||
const char *detail = "";
|
||||
|
||||
g_return_if_fail (req != NULL);
|
||||
g_return_if_fail (agent != NULL);
|
||||
|
||||
if (!g_slist_find (req->pending, agent))
|
||||
return;
|
||||
|
||||
/* If this agent is being asked right now, cancel the request */
|
||||
if (agent == req->current) {
|
||||
nm_secret_agent_cancel_secrets (req->current, req->current_call_id);
|
||||
req->current = NULL;
|
||||
req->current_call_id = NULL;
|
||||
try_next = TRUE;
|
||||
detail = " current";
|
||||
}
|
||||
|
||||
nm_log_dbg (LOGD_AGENTS, "(%s)%s agent removed from secrets request %p/%s",
|
||||
nm_secret_agent_get_description (agent),
|
||||
detail, req, req->setting_name);
|
||||
|
||||
req->pending = g_slist_remove (req->pending, agent);
|
||||
|
||||
if (try_next) {
|
||||
/* If the agent serving the in-progress secrets request went away then
|
||||
* we need to ask the next agent for secrets.
|
||||
*/
|
||||
request_next (req);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************/
|
||||
|
||||
static void
|
||||
mgr_req_complete_cb (Request *req,
|
||||
GHashTable *secrets,
|
||||
@@ -480,12 +699,19 @@ nm_agent_manager_get_secrets (NMAgentManager *self,
|
||||
{
|
||||
NMAgentManagerPrivate *priv = NM_AGENT_MANAGER_GET_PRIVATE (self);
|
||||
Request *req;
|
||||
GHashTableIter iter;
|
||||
gpointer data;
|
||||
|
||||
g_return_val_if_fail (self != NULL, 0);
|
||||
g_return_val_if_fail (connection != NULL, 0);
|
||||
g_return_val_if_fail (NM_IS_SYSCONFIG_CONNECTION (connection), 0);
|
||||
g_return_val_if_fail (callback != NULL, 0);
|
||||
|
||||
nm_log_dbg (LOGD_SETTINGS,
|
||||
"Secrets requested for connection %s (%s)",
|
||||
nm_connection_get_path (connection),
|
||||
setting_name);
|
||||
|
||||
req = request_new (connection,
|
||||
setting_name,
|
||||
get_new,
|
||||
@@ -493,11 +719,17 @@ nm_agent_manager_get_secrets (NMAgentManager *self,
|
||||
callback,
|
||||
callback_data,
|
||||
other_data2,
|
||||
other_data3);
|
||||
request_set_callbacks (req, mgr_req_next_cb, mgr_req_complete_cb, self);
|
||||
other_data3,
|
||||
mgr_req_complete_cb,
|
||||
self);
|
||||
|
||||
g_hash_table_insert (priv->requests, GUINT_TO_POINTER (req->reqid), req);
|
||||
|
||||
/* Add agents to the request */
|
||||
g_hash_table_iter_init (&iter, priv->agents);
|
||||
while (g_hash_table_iter_next (&iter, NULL, &data))
|
||||
request_add_agent (req, NM_SECRET_AGENT (data), priv->session_monitor);
|
||||
|
||||
req->idle_id = g_idle_add (request_start_secrets, req);
|
||||
|
||||
return req->reqid;
|
||||
|
@@ -24,7 +24,9 @@
|
||||
#include <dbus/dbus-glib.h>
|
||||
#include <dbus/dbus-glib-lowlevel.h>
|
||||
|
||||
#include "NetworkManager.h"
|
||||
#include "nm-secret-agent.h"
|
||||
#include "nm-dbus-glib-types.h"
|
||||
|
||||
G_DEFINE_TYPE (NMSecretAgent, nm_secret_agent, G_TYPE_OBJECT)
|
||||
|
||||
@@ -35,13 +37,37 @@ G_DEFINE_TYPE (NMSecretAgent, nm_secret_agent, G_TYPE_OBJECT)
|
||||
typedef struct {
|
||||
gboolean disposed;
|
||||
|
||||
char *description;
|
||||
char *owner;
|
||||
char *identifier;
|
||||
uid_t owner_uid;
|
||||
guint32 hash;
|
||||
|
||||
NMDBusManager *dbus_mgr;
|
||||
DBusGProxy *proxy;
|
||||
} NMSecretAgentPrivate;
|
||||
|
||||
/*************************************************************/
|
||||
|
||||
const char *
|
||||
nm_secret_agent_get_description (NMSecretAgent *agent)
|
||||
{
|
||||
NMSecretAgentPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (agent != NULL, NULL);
|
||||
g_return_val_if_fail (NM_IS_SECRET_AGENT (agent), NULL);
|
||||
|
||||
priv = NM_SECRET_AGENT_GET_PRIVATE (agent);
|
||||
if (!priv->description) {
|
||||
priv->description = g_strdup_printf ("%s/%s/%u",
|
||||
priv->owner,
|
||||
priv->identifier,
|
||||
priv->owner_uid);
|
||||
}
|
||||
|
||||
return priv->description;
|
||||
}
|
||||
|
||||
const char *
|
||||
nm_secret_agent_get_dbus_owner (NMSecretAgent *agent)
|
||||
{
|
||||
@@ -69,10 +95,68 @@ nm_secret_agent_get_owner_uid (NMSecretAgent *agent)
|
||||
return NM_SECRET_AGENT_GET_PRIVATE (agent)->owner_uid;
|
||||
}
|
||||
|
||||
guint32
|
||||
nm_secret_agent_get_hash (NMSecretAgent *agent)
|
||||
{
|
||||
g_return_val_if_fail (agent != NULL, 0);
|
||||
g_return_val_if_fail (NM_IS_SECRET_AGENT (agent), 0);
|
||||
|
||||
return NM_SECRET_AGENT_GET_PRIVATE (agent)->hash;
|
||||
}
|
||||
|
||||
/*************************************************************/
|
||||
|
||||
gpointer
|
||||
nm_secret_agent_get_secrets (NMSecretAgent *self,
|
||||
NMConnection *connection,
|
||||
const char *setting_name,
|
||||
const char *hint,
|
||||
gboolean request_new,
|
||||
DBusGProxyCallNotify done_callback,
|
||||
gpointer done_callback_data)
|
||||
{
|
||||
NMSecretAgentPrivate *priv;
|
||||
DBusGProxyCall *call;
|
||||
GHashTable *hash;
|
||||
const char *hints[2] = { hint, NULL };
|
||||
|
||||
g_return_val_if_fail (self != NULL, NULL);
|
||||
g_return_val_if_fail (connection != NULL, NULL);
|
||||
g_return_val_if_fail (setting_name != NULL, NULL);
|
||||
|
||||
priv = NM_SECRET_AGENT_GET_PRIVATE (self);
|
||||
|
||||
hash = nm_connection_to_hash (connection);
|
||||
call = dbus_g_proxy_begin_call_with_timeout (priv->proxy,
|
||||
"GetSecrets",
|
||||
done_callback,
|
||||
done_callback_data,
|
||||
NULL,
|
||||
120000, /* 120 seconds */
|
||||
DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, hash,
|
||||
DBUS_TYPE_G_OBJECT_PATH, nm_connection_get_path (connection),
|
||||
G_TYPE_STRING, setting_name,
|
||||
G_TYPE_STRV, hints,
|
||||
G_TYPE_BOOLEAN, request_new,
|
||||
G_TYPE_INVALID);
|
||||
g_hash_table_destroy (hash);
|
||||
|
||||
return call;
|
||||
}
|
||||
|
||||
void
|
||||
nm_secret_agent_cancel_secrets (NMSecretAgent *self, gpointer call_id)
|
||||
{
|
||||
g_return_if_fail (self != NULL);
|
||||
|
||||
dbus_g_proxy_cancel_call (NM_SECRET_AGENT_GET_PRIVATE (self)->proxy, call_id);
|
||||
}
|
||||
|
||||
/*************************************************************/
|
||||
|
||||
NMSecretAgent *
|
||||
nm_secret_agent_new (const char *owner,
|
||||
nm_secret_agent_new (NMDBusManager *dbus_mgr,
|
||||
const char *owner,
|
||||
const char *identifier,
|
||||
uid_t owner_uid)
|
||||
{
|
||||
@@ -84,11 +168,26 @@ nm_secret_agent_new (const char *owner,
|
||||
|
||||
self = (NMSecretAgent *) g_object_new (NM_TYPE_SECRET_AGENT, NULL);
|
||||
if (self) {
|
||||
DBusGConnection *bus;
|
||||
char *hash_str;
|
||||
|
||||
priv = NM_SECRET_AGENT_GET_PRIVATE (self);
|
||||
|
||||
priv->owner = g_strdup (owner);
|
||||
priv->identifier = g_strdup (identifier);
|
||||
priv->owner_uid = owner_uid;
|
||||
|
||||
hash_str = g_strdup_printf ("%08u%s", owner_uid, identifier);
|
||||
priv->hash = g_str_hash (hash_str);
|
||||
g_free (hash_str);
|
||||
|
||||
priv->dbus_mgr = g_object_ref (dbus_mgr);
|
||||
bus = nm_dbus_manager_get_connection (priv->dbus_mgr);
|
||||
priv->proxy = dbus_g_proxy_new_for_name (bus,
|
||||
owner,
|
||||
NM_DBUS_PATH_SECRET_AGENT,
|
||||
NM_DBUS_INTERFACE_SECRET_AGENT);
|
||||
g_assert (priv->proxy);
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -108,9 +207,13 @@ dispose (GObject *object)
|
||||
return;
|
||||
priv->disposed = TRUE;
|
||||
|
||||
g_free (priv->description);
|
||||
g_free (priv->owner);
|
||||
g_free (priv->identifier);
|
||||
|
||||
g_object_unref (priv->proxy);
|
||||
g_object_unref (priv->dbus_mgr);
|
||||
|
||||
G_OBJECT_CLASS (nm_secret_agent_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
|
@@ -23,6 +23,11 @@
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <dbus/dbus-glib.h>
|
||||
#include <dbus/dbus-glib-lowlevel.h>
|
||||
|
||||
#include <nm-connection.h>
|
||||
#include "nm-dbus-manager.h"
|
||||
|
||||
#define NM_TYPE_SECRET_AGENT (nm_secret_agent_get_type ())
|
||||
#define NM_SECRET_AGENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SECRET_AGENT, NMSecretAgent))
|
||||
@@ -41,14 +46,30 @@ typedef struct {
|
||||
|
||||
GType nm_secret_agent_get_type (void);
|
||||
|
||||
NMSecretAgent *nm_secret_agent_new (const char *owner,
|
||||
NMSecretAgent *nm_secret_agent_new (NMDBusManager *dbus_mgr,
|
||||
const char *owner,
|
||||
const char *identifier,
|
||||
uid_t owner_uid);
|
||||
|
||||
const char *nm_secret_agent_get_description (NMSecretAgent *agent);
|
||||
|
||||
const char *nm_secret_agent_get_dbus_owner (NMSecretAgent *agent);
|
||||
|
||||
const char *nm_secret_agent_get_identifier (NMSecretAgent *agent);
|
||||
|
||||
uid_t nm_secret_agent_get_owner_uid (NMSecretAgent *agent);
|
||||
|
||||
guint32 nm_secret_agent_get_hash (NMSecretAgent *agent);
|
||||
|
||||
gpointer nm_secret_agent_get_secrets (NMSecretAgent *agent,
|
||||
NMConnection *connection,
|
||||
const char *setting_name,
|
||||
const char *hint,
|
||||
gboolean request_new,
|
||||
DBusGProxyCallNotify done_callback,
|
||||
gpointer done_callback_data);
|
||||
|
||||
void nm_secret_agent_cancel_secrets (NMSecretAgent *agent,
|
||||
gpointer call_id);
|
||||
|
||||
#endif /* NM_SECRET_AGENT_H */
|
||||
|
@@ -781,32 +781,6 @@ nm_vpn_connection_disconnect (NMVPNConnection *connection,
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#if 0
|
||||
static gboolean
|
||||
secrets_update_setting (NMSecretsProviderInterface *interface,
|
||||
const char *setting_name,
|
||||
GHashTable *new)
|
||||
{
|
||||
NMVPNConnection *self = NM_VPN_CONNECTION (interface);
|
||||
NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self);
|
||||
GError *error = NULL;
|
||||
|
||||
g_return_val_if_fail (priv->connection != NULL, FALSE);
|
||||
|
||||
if (strcmp (setting_name, NM_SETTING_VPN_SETTING_NAME))
|
||||
return FALSE;
|
||||
|
||||
if (!nm_connection_update_secrets (priv->connection, NM_SETTING_VPN_SETTING_NAME, new, &error)) {
|
||||
nm_log_warn (LOGD_VPN, "Failed to update VPN secrets: %d %s",
|
||||
error ? error->code : -1,
|
||||
error && error->message ? error->message : "(none)");
|
||||
g_clear_error (&error);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
cancel_get_secrets (NMVPNConnection *self)
|
||||
{
|
||||
|
Reference in New Issue
Block a user