mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-05-07 04:58:01 +02:00
core: more flattening of PendingActivation objects
Do less authentication in the PA and make the DBusGMethodInvocation opaque to the PA. This pushes the responsibility for replying to the D-Bus method call closer to the D-Bus method handler instead of stuffing it all into the PA. This does mean we need to get the D-Bus sender name and the sender UID and pass that into the pending_activation_new(), but we'll clean that up in a bit.
This commit is contained in:
parent
f94ac164a6
commit
4e4e14e65c
1 changed files with 128 additions and 93 deletions
221
src/nm-manager.c
221
src/nm-manager.c
|
|
@ -183,16 +183,19 @@ platform_link_added_cb (NMPlatform *platform,
|
||||||
|
|
||||||
typedef struct PendingActivation PendingActivation;
|
typedef struct PendingActivation PendingActivation;
|
||||||
typedef void (*PendingActivationFunc) (PendingActivation *pending,
|
typedef void (*PendingActivationFunc) (PendingActivation *pending,
|
||||||
|
gpointer user_data,
|
||||||
GError *error);
|
GError *error);
|
||||||
|
|
||||||
struct PendingActivation {
|
struct PendingActivation {
|
||||||
NMManager *manager;
|
NMManager *manager;
|
||||||
|
|
||||||
DBusGMethodInvocation *context;
|
|
||||||
PendingActivationFunc callback;
|
PendingActivationFunc callback;
|
||||||
|
gpointer user_data;
|
||||||
|
|
||||||
|
char *dbus_sender;
|
||||||
|
gulong sender_uid;
|
||||||
NMAuthChain *chain;
|
NMAuthChain *chain;
|
||||||
const char *wifi_shared_permission;
|
const char *wifi_shared_permission;
|
||||||
gboolean add_and_activate;
|
|
||||||
|
|
||||||
NMConnection *connection;
|
NMConnection *connection;
|
||||||
NMDevice *device;
|
NMDevice *device;
|
||||||
|
|
@ -848,20 +851,22 @@ nm_manager_get_state (NMManager *manager)
|
||||||
|
|
||||||
static PendingActivation *
|
static PendingActivation *
|
||||||
pending_activation_new (NMManager *manager,
|
pending_activation_new (NMManager *manager,
|
||||||
DBusGMethodInvocation *context,
|
char *dbus_sender,
|
||||||
|
gulong sender_uid,
|
||||||
NMDevice *device,
|
NMDevice *device,
|
||||||
NMConnection *connection,
|
NMConnection *connection,
|
||||||
const char *specific_object_path,
|
const char *specific_object_path,
|
||||||
gboolean add_and_activate,
|
|
||||||
PendingActivationFunc callback,
|
PendingActivationFunc callback,
|
||||||
|
gpointer user_data,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
PendingActivation *pending;
|
PendingActivation *pending;
|
||||||
|
|
||||||
g_return_val_if_fail (manager != NULL, NULL);
|
g_return_val_if_fail (manager != NULL, NULL);
|
||||||
g_return_val_if_fail (context != NULL, NULL);
|
g_return_val_if_fail (dbus_sender != NULL, NULL);
|
||||||
g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
|
g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
|
||||||
g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
|
g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
|
||||||
|
g_return_val_if_fail (callback != NULL, NULL);
|
||||||
|
|
||||||
/* A object path of "/" means NULL */
|
/* A object path of "/" means NULL */
|
||||||
if (g_strcmp0 (specific_object_path, "/") == 0)
|
if (g_strcmp0 (specific_object_path, "/") == 0)
|
||||||
|
|
@ -869,13 +874,15 @@ pending_activation_new (NMManager *manager,
|
||||||
|
|
||||||
pending = g_slice_new0 (PendingActivation);
|
pending = g_slice_new0 (PendingActivation);
|
||||||
pending->manager = manager;
|
pending->manager = manager;
|
||||||
pending->context = context;
|
|
||||||
pending->callback = callback;
|
|
||||||
pending->add_and_activate = add_and_activate;
|
|
||||||
pending->connection = g_object_ref (connection);
|
pending->connection = g_object_ref (connection);
|
||||||
pending->device = g_object_ref (device);
|
pending->device = g_object_ref (device);
|
||||||
pending->specific_object_path = g_strdup (specific_object_path);
|
pending->specific_object_path = g_strdup (specific_object_path);
|
||||||
|
|
||||||
|
pending->callback = callback;
|
||||||
|
pending->user_data = user_data;
|
||||||
|
pending->dbus_sender = dbus_sender;
|
||||||
|
pending->sender_uid = sender_uid;
|
||||||
|
|
||||||
return pending;
|
return pending;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -908,7 +915,7 @@ pending_auth_done (NMAuthChain *chain,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pending->callback (pending, tmp_error);
|
pending->callback (pending, pending->user_data, tmp_error);
|
||||||
g_clear_error (&tmp_error);
|
g_clear_error (&tmp_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -917,17 +924,16 @@ pending_activation_check_authorized (PendingActivation *pending)
|
||||||
{
|
{
|
||||||
GError *error;
|
GError *error;
|
||||||
const char *wifi_permission = NULL;
|
const char *wifi_permission = NULL;
|
||||||
const char *error_desc = NULL;
|
|
||||||
|
|
||||||
g_return_if_fail (pending != NULL);
|
g_return_if_fail (pending != NULL);
|
||||||
|
|
||||||
/* First check if the user is allowed to use networking at all, giving
|
/* First check if the user is allowed to use networking at all, giving
|
||||||
* the user a chance to authenticate to gain the permission.
|
* the user a chance to authenticate to gain the permission.
|
||||||
*/
|
*/
|
||||||
pending->chain = nm_auth_chain_new (pending->context,
|
pending->chain = nm_auth_chain_new_dbus_sender (pending->dbus_sender,
|
||||||
pending_auth_done,
|
pending->sender_uid,
|
||||||
pending,
|
pending_auth_done,
|
||||||
&error_desc);
|
pending);
|
||||||
if (pending->chain) {
|
if (pending->chain) {
|
||||||
nm_auth_chain_add_call (pending->chain, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE);
|
nm_auth_chain_add_call (pending->chain, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE);
|
||||||
|
|
||||||
|
|
@ -940,33 +946,19 @@ pending_activation_check_authorized (PendingActivation *pending)
|
||||||
} else {
|
} else {
|
||||||
error = g_error_new_literal (NM_MANAGER_ERROR,
|
error = g_error_new_literal (NM_MANAGER_ERROR,
|
||||||
NM_MANAGER_ERROR_PERMISSION_DENIED,
|
NM_MANAGER_ERROR_PERMISSION_DENIED,
|
||||||
error_desc);
|
"Failed to authorize");
|
||||||
pending->callback (pending, error);
|
pending->callback (pending, pending->user_data, error);
|
||||||
g_error_free (error);
|
g_error_free (error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pending_activation_destroy (PendingActivation *pending,
|
pending_activation_destroy (PendingActivation *pending)
|
||||||
GError *error,
|
|
||||||
NMActiveConnection *ac)
|
|
||||||
{
|
{
|
||||||
g_return_if_fail (pending != NULL);
|
g_return_if_fail (pending != NULL);
|
||||||
|
|
||||||
if (error)
|
|
||||||
dbus_g_method_return_error (pending->context, error);
|
|
||||||
else if (ac) {
|
|
||||||
if (pending->add_and_activate) {
|
|
||||||
dbus_g_method_return (pending->context,
|
|
||||||
nm_connection_get_path (pending->connection),
|
|
||||||
nm_active_connection_get_path (ac));
|
|
||||||
} else {
|
|
||||||
dbus_g_method_return (pending->context,
|
|
||||||
nm_active_connection_get_path (ac));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g_free (pending->specific_object_path);
|
g_free (pending->specific_object_path);
|
||||||
|
g_free (pending->dbus_sender);
|
||||||
g_clear_object (&pending->device);
|
g_clear_object (&pending->device);
|
||||||
g_clear_object (&pending->connection);
|
g_clear_object (&pending->connection);
|
||||||
|
|
||||||
|
|
@ -3106,71 +3098,58 @@ activated:
|
||||||
return ac;
|
return ac;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Finally activate a pending activation request; on success returns the new
|
||||||
* TODO this function was created and named in the era of user settings, where
|
* NMActiveConnection object, otherwise NULL and sets an error.
|
||||||
* we could get activation requests for a connection before we got the settings
|
|
||||||
* data of that connection. Now that user settings are gone, flatten or rename
|
|
||||||
* it.
|
|
||||||
*/
|
*/
|
||||||
static void
|
static NMActiveConnection *
|
||||||
pending_activate (PendingActivation *pending, NMSettingsConnection *new_connection)
|
pending_activate (PendingActivation *pending,
|
||||||
|
NMSettingsConnection *new_connection,
|
||||||
|
GError **error)
|
||||||
{
|
{
|
||||||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (pending->manager);
|
|
||||||
NMActiveConnection *ac = NULL;
|
NMActiveConnection *ac = NULL;
|
||||||
char *sender = NULL;
|
GError *local = NULL;
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
/* If we're given a new NMSettingsConnection (ie, from AddAndActivate now
|
|
||||||
* that the connection is saved) swap out the old one for the new one.
|
|
||||||
*/
|
|
||||||
if (new_connection) {
|
|
||||||
g_assert (pending->add_and_activate);
|
|
||||||
g_object_unref (pending->connection);
|
|
||||||
pending->connection = g_object_ref (new_connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!nm_dbus_manager_get_caller_info (priv->dbus_mgr,
|
|
||||||
pending->context,
|
|
||||||
&sender,
|
|
||||||
NULL)) {
|
|
||||||
error = g_error_new_literal (NM_MANAGER_ERROR,
|
|
||||||
NM_MANAGER_ERROR_PERMISSION_DENIED,
|
|
||||||
"D-Bus sender could not be determined.");
|
|
||||||
} else {
|
|
||||||
g_assert (sender);
|
|
||||||
ac = nm_manager_activate_connection (pending->manager,
|
|
||||||
NM_CONNECTION (pending->connection),
|
|
||||||
pending->specific_object_path,
|
|
||||||
pending->device,
|
|
||||||
sender,
|
|
||||||
&error);
|
|
||||||
g_free (sender);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
ac = nm_manager_activate_connection (pending->manager,
|
||||||
|
new_connection ?
|
||||||
|
NM_CONNECTION (new_connection) : pending->connection,
|
||||||
|
pending->specific_object_path,
|
||||||
|
pending->device,
|
||||||
|
pending->dbus_sender,
|
||||||
|
&local);
|
||||||
if (!ac) {
|
if (!ac) {
|
||||||
nm_log_warn (LOGD_CORE, "connection %s failed to activate: (%d) %s",
|
nm_log_warn (LOGD_CORE, "connection %s failed to activate: (%d) %s",
|
||||||
nm_connection_get_path (pending->connection),
|
nm_connection_get_path (pending->connection),
|
||||||
error ? error->code : -1,
|
local->code, local->message ? local->message : "(unknown)");
|
||||||
error && error->message ? error->message : "(unknown)");
|
g_propagate_error (error, local);
|
||||||
}
|
}
|
||||||
|
|
||||||
pending_activation_destroy (pending, error, ac);
|
return ac;
|
||||||
g_clear_error (&error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
validate_activation_request (NMManager *self,
|
validate_activation_request (NMManager *self,
|
||||||
|
DBusGMethodInvocation *context,
|
||||||
NMConnection *connection,
|
NMConnection *connection,
|
||||||
const char *device_path,
|
const char *device_path,
|
||||||
NMDevice **out_device,
|
NMDevice **out_device,
|
||||||
gboolean *out_vpn,
|
gboolean *out_vpn,
|
||||||
|
gulong *out_sender_uid,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
|
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
|
||||||
NMDevice *device = NULL;
|
NMDevice *device = NULL;
|
||||||
gboolean vpn = FALSE;
|
gboolean vpn = FALSE;
|
||||||
|
|
||||||
g_assert (connection);
|
g_assert (connection);
|
||||||
|
|
||||||
|
/* Get caller's UID */
|
||||||
|
if (!nm_dbus_manager_get_caller_info (priv->dbus_mgr, context, NULL, out_sender_uid)) {
|
||||||
|
g_set_error_literal (error,
|
||||||
|
NM_MANAGER_ERROR, NM_MANAGER_ERROR_PERMISSION_DENIED,
|
||||||
|
"Failed to get request UID.");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check whether it's a VPN or not */
|
/* Check whether it's a VPN or not */
|
||||||
if ( nm_connection_get_setting_vpn (connection)
|
if ( nm_connection_get_setting_vpn (connection)
|
||||||
|| nm_connection_is_type (connection, NM_SETTING_VPN_SETTING_NAME))
|
|| nm_connection_is_type (connection, NM_SETTING_VPN_SETTING_NAME))
|
||||||
|
|
@ -3204,13 +3183,29 @@ validate_activation_request (NMManager *self,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
activation_auth_done (PendingActivation *pending, GError *error)
|
activation_auth_done (PendingActivation *pending, gpointer user_data, GError *error)
|
||||||
{
|
{
|
||||||
if (error)
|
DBusGMethodInvocation *context = user_data;
|
||||||
pending_activation_destroy (pending, error, NULL);
|
NMActiveConnection *ac = NULL;
|
||||||
|
GError *local = NULL;
|
||||||
|
|
||||||
|
if (!error) {
|
||||||
|
/* Try to activate the connection */
|
||||||
|
ac = pending_activate (pending, NULL, &local);
|
||||||
|
if (!ac)
|
||||||
|
error = local;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ac)
|
||||||
|
dbus_g_method_return (context, nm_active_connection_get_path (ac));
|
||||||
else
|
else
|
||||||
pending_activate (pending, NULL);
|
dbus_g_method_return_error (context, error);
|
||||||
|
|
||||||
|
g_clear_error (&local);
|
||||||
|
pending_activation_destroy (pending);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -3225,6 +3220,7 @@ impl_manager_activate_connection (NMManager *self,
|
||||||
NMConnection *connection;
|
NMConnection *connection;
|
||||||
NMDevice *device = NULL;
|
NMDevice *device = NULL;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
gulong sender_uid = G_MAXULONG;
|
||||||
|
|
||||||
connection = (NMConnection *) nm_settings_get_connection_by_path (priv->settings, connection_path);
|
connection = (NMConnection *) nm_settings_get_connection_by_path (priv->settings, connection_path);
|
||||||
if (!connection) {
|
if (!connection) {
|
||||||
|
|
@ -3234,19 +3230,27 @@ impl_manager_activate_connection (NMManager *self,
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!validate_activation_request (self, connection, device_path, &device, NULL, &error))
|
if (!validate_activation_request (self,
|
||||||
|
context,
|
||||||
|
connection,
|
||||||
|
device_path,
|
||||||
|
&device,
|
||||||
|
NULL,
|
||||||
|
&sender_uid,
|
||||||
|
&error))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/* Need to check the caller's permissions and stuff before we can
|
/* Need to check the caller's permissions and stuff before we can
|
||||||
* activate the connection.
|
* activate the connection.
|
||||||
*/
|
*/
|
||||||
pending = pending_activation_new (self,
|
pending = pending_activation_new (self,
|
||||||
context,
|
dbus_g_method_get_sender (context),
|
||||||
|
sender_uid,
|
||||||
device,
|
device,
|
||||||
connection,
|
connection,
|
||||||
specific_object_path,
|
specific_object_path,
|
||||||
FALSE,
|
|
||||||
activation_auth_done,
|
activation_auth_done,
|
||||||
|
context,
|
||||||
&error);
|
&error);
|
||||||
if (pending) {
|
if (pending) {
|
||||||
/* Success */
|
/* Success */
|
||||||
|
|
@ -3260,35 +3264,55 @@ error:
|
||||||
g_error_free (error);
|
g_error_free (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
activation_add_done (NMSettings *self,
|
activation_add_done (NMSettings *self,
|
||||||
NMSettingsConnection *connection,
|
NMSettingsConnection *new_connection,
|
||||||
GError *error,
|
GError *error,
|
||||||
DBusGMethodInvocation *context,
|
DBusGMethodInvocation *context,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
PendingActivation *pending = user_data;
|
PendingActivation *pending = user_data;
|
||||||
|
NMActiveConnection *ac = NULL;
|
||||||
|
GError *local = NULL;
|
||||||
|
|
||||||
if (error)
|
if (!error) {
|
||||||
pending_activation_destroy (pending, error, NULL);
|
/* Try to activate the connection */
|
||||||
else {
|
ac = pending_activate (pending, new_connection, &local);
|
||||||
pending_activate (pending, connection);
|
if (!ac)
|
||||||
|
error = local;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ac) {
|
||||||
|
dbus_g_method_return (context,
|
||||||
|
nm_connection_get_path (NM_CONNECTION (new_connection)),
|
||||||
|
nm_active_connection_get_path (ac));
|
||||||
|
} else
|
||||||
|
dbus_g_method_return_error (context, error);
|
||||||
|
|
||||||
|
g_clear_error (&local);
|
||||||
|
pending_activation_destroy (pending);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_and_activate_auth_done (PendingActivation *pending, GError *error)
|
add_and_activate_auth_done (PendingActivation *pending,
|
||||||
|
gpointer user_data,
|
||||||
|
GError *error)
|
||||||
{
|
{
|
||||||
if (error)
|
DBusGMethodInvocation *context = user_data;
|
||||||
pending_activation_destroy (pending, error, NULL);
|
|
||||||
else {
|
if (error) {
|
||||||
|
dbus_g_method_return_error (context, error);
|
||||||
|
pending_activation_destroy (pending);
|
||||||
|
} else {
|
||||||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (pending->manager);
|
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (pending->manager);
|
||||||
|
|
||||||
/* Basic sender auth checks performed; try to add the connection */
|
/* Basic sender auth checks performed; try to add the connection */
|
||||||
nm_settings_add_connection_dbus (priv->settings,
|
nm_settings_add_connection_dbus (priv->settings,
|
||||||
pending->connection,
|
pending->connection,
|
||||||
TRUE,
|
TRUE,
|
||||||
pending->context,
|
context,
|
||||||
activation_add_done,
|
activation_add_done,
|
||||||
pending);
|
pending);
|
||||||
}
|
}
|
||||||
|
|
@ -3308,6 +3332,7 @@ impl_manager_add_and_activate_connection (NMManager *self,
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
NMDevice *device = NULL;
|
NMDevice *device = NULL;
|
||||||
gboolean vpn = FALSE;
|
gboolean vpn = FALSE;
|
||||||
|
gulong sender_uid = G_MAXULONG;
|
||||||
|
|
||||||
if (!settings || !g_hash_table_size (settings)) {
|
if (!settings || !g_hash_table_size (settings)) {
|
||||||
error = g_error_new_literal (NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_CONNECTION,
|
error = g_error_new_literal (NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_CONNECTION,
|
||||||
|
|
@ -3319,7 +3344,14 @@ impl_manager_add_and_activate_connection (NMManager *self,
|
||||||
connection = nm_connection_new ();
|
connection = nm_connection_new ();
|
||||||
nm_connection_replace_settings (connection, settings, NULL);
|
nm_connection_replace_settings (connection, settings, NULL);
|
||||||
|
|
||||||
if (!validate_activation_request (self, connection, device_path, &device, &vpn, &error))
|
if (!validate_activation_request (self,
|
||||||
|
context,
|
||||||
|
connection,
|
||||||
|
device_path,
|
||||||
|
&device,
|
||||||
|
&vpn,
|
||||||
|
&sender_uid,
|
||||||
|
&error))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
all_connections = nm_settings_get_connections (priv->settings);
|
all_connections = nm_settings_get_connections (priv->settings);
|
||||||
|
|
@ -3354,12 +3386,13 @@ impl_manager_add_and_activate_connection (NMManager *self,
|
||||||
* activate the connection.
|
* activate the connection.
|
||||||
*/
|
*/
|
||||||
pending = pending_activation_new (self,
|
pending = pending_activation_new (self,
|
||||||
context,
|
dbus_g_method_get_sender (context),
|
||||||
|
sender_uid,
|
||||||
device,
|
device,
|
||||||
connection,
|
connection,
|
||||||
specific_object_path,
|
specific_object_path,
|
||||||
TRUE,
|
|
||||||
add_and_activate_auth_done,
|
add_and_activate_auth_done,
|
||||||
|
context,
|
||||||
&error);
|
&error);
|
||||||
if (pending) {
|
if (pending) {
|
||||||
/* Success! */
|
/* Success! */
|
||||||
|
|
@ -3377,6 +3410,8 @@ error:
|
||||||
g_error_free (error);
|
g_error_free (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
nm_manager_deactivate_connection (NMManager *manager,
|
nm_manager_deactivate_connection (NMManager *manager,
|
||||||
const char *connection_path,
|
const char *connection_path,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue