mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-06 16:20:34 +01:00
core: removal of PendingActivation object from nm-manager.c (bgo #707335)
This branch decouples NMActiveConnection creation from device activation so that the NMActiveConnection object tracks the entire activation request (either internally-requested by the Policy or externally via D-Bus) from start to finish, instead of the previous situation where the PendingActivation handled D-Bus requests separately. This also will allow implementation of the DEACTIVATING state in the future. The NMActiveConnection object tracking the activation is not actually exported to D-Bus until the device or VPN activation is completely authorized and actually begins. It also encapsulates all the details needed to authorize a request into a new NMAuthSubject class, replacing various "dbus_sender" and "user_requested" arguments throughout the code.
This commit is contained in:
commit
8a173e1d7a
31 changed files with 2127 additions and 1374 deletions
|
|
@ -248,6 +248,8 @@ nm_sources = \
|
|||
nm-ip6-config.h \
|
||||
nm-manager-auth.c \
|
||||
nm-manager-auth.h \
|
||||
nm-auth-subject.c \
|
||||
nm-auth-subject.h \
|
||||
nm-manager.c \
|
||||
nm-manager.h \
|
||||
nm-netlink-monitor.c \
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@ get_generic_capabilities (NMDevice *dev)
|
|||
static NMActStageReturn
|
||||
act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
|
||||
{
|
||||
NMActStageReturn ret;
|
||||
NMActRequest *req;
|
||||
NMConnection *connection;
|
||||
NMSettingInfiniband *s_infiniband;
|
||||
|
|
@ -156,6 +157,10 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
|
|||
|
||||
g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
|
||||
ret = NM_DEVICE_CLASS (nm_device_infiniband_parent_class)->act_stage1_prepare (dev, reason);
|
||||
if (ret != NM_ACT_STAGE_RETURN_SUCCESS)
|
||||
return ret;
|
||||
|
||||
req = nm_device_get_act_request (dev);
|
||||
g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
|
||||
|
|
@ -186,7 +191,7 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
|
|||
return NM_ACT_STAGE_RETURN_FAILURE;
|
||||
}
|
||||
|
||||
return NM_DEVICE_CLASS (nm_device_infiniband_parent_class)->act_stage1_prepare (dev, reason);
|
||||
return NM_ACT_STAGE_RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -252,8 +252,13 @@ deactivate (NMDevice *device)
|
|||
static NMActStageReturn
|
||||
act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
|
||||
{
|
||||
NMActStageReturn ret;
|
||||
NMActRequest *req;
|
||||
|
||||
ret = NM_DEVICE_CLASS (nm_device_modem_parent_class)->act_stage1_prepare (device, reason);
|
||||
if (ret != NM_ACT_STAGE_RETURN_SUCCESS)
|
||||
return ret;
|
||||
|
||||
req = nm_device_get_act_request (device);
|
||||
g_assert (req);
|
||||
|
||||
|
|
|
|||
|
|
@ -252,8 +252,13 @@ static NMActStageReturn
|
|||
act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
|
||||
{
|
||||
NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (dev);
|
||||
NMActStageReturn ret;
|
||||
gboolean scanning;
|
||||
|
||||
ret = NM_DEVICE_CLASS (nm_device_olpc_mesh_parent_class)->act_stage1_prepare (dev, reason);
|
||||
if (ret != NM_ACT_STAGE_RETURN_SUCCESS)
|
||||
return ret;
|
||||
|
||||
/* disconnect companion device, if it is connected */
|
||||
if (nm_device_get_act_request (NM_DEVICE (priv->companion))) {
|
||||
nm_log_info (LOGD_OLPC_MESH, "(%s): disconnecting companion device %s",
|
||||
|
|
|
|||
|
|
@ -2790,6 +2790,7 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
|
|||
{
|
||||
NMDeviceWifi *self = NM_DEVICE_WIFI (dev);
|
||||
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
NMActStageReturn ret;
|
||||
NMAccessPoint *ap = NULL;
|
||||
NMActRequest *req;
|
||||
NMConnection *connection;
|
||||
|
|
@ -2798,6 +2799,10 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
|
|||
GSList *iter;
|
||||
const char *mode;
|
||||
|
||||
ret = NM_DEVICE_CLASS (nm_device_wifi_parent_class)->act_stage1_prepare (dev, reason);
|
||||
if (ret != NM_ACT_STAGE_RETURN_SUCCESS)
|
||||
return ret;
|
||||
|
||||
req = nm_device_get_act_request (NM_DEVICE (self));
|
||||
g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
|
||||
|
|
|
|||
|
|
@ -288,6 +288,7 @@ typedef struct {
|
|||
/* master interface for bridge/bond/team slave */
|
||||
NMDevice * master;
|
||||
gboolean enslaved;
|
||||
guint master_ready_id;
|
||||
|
||||
/* slave management */
|
||||
gboolean is_master;
|
||||
|
|
@ -1935,10 +1936,61 @@ nm_device_ip_config_should_fail (NMDevice *self, gboolean ip6)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
master_ready_cb (NMActiveConnection *active,
|
||||
GParamSpec *pspec,
|
||||
NMDevice *self)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
NMActiveConnection *master;
|
||||
|
||||
g_assert (priv->state == NM_DEVICE_STATE_PREPARE);
|
||||
|
||||
/* Notify a master device that it has a new slave */
|
||||
g_assert (nm_active_connection_get_master_ready (active));
|
||||
master = nm_active_connection_get_master (active);
|
||||
|
||||
priv->master = g_object_ref (nm_active_connection_get_device (master));
|
||||
nm_device_master_add_slave (priv->master, self);
|
||||
|
||||
nm_log_dbg (LOGD_DEVICE, "(%s): master connection ready; master device %s",
|
||||
nm_device_get_iface (self),
|
||||
nm_device_get_iface (priv->master));
|
||||
|
||||
if (priv->master_ready_id) {
|
||||
g_signal_handler_disconnect (active, priv->master_ready_id);
|
||||
priv->master_ready_id = 0;
|
||||
}
|
||||
|
||||
nm_device_activate_schedule_stage2_device_config (self);
|
||||
}
|
||||
|
||||
static NMActStageReturn
|
||||
act_stage1_prepare (NMDevice *self, NMDeviceStateReason *reason)
|
||||
{
|
||||
return NM_ACT_STAGE_RETURN_SUCCESS;
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS;
|
||||
NMActiveConnection *active = NM_ACTIVE_CONNECTION (priv->act_request);
|
||||
|
||||
if (nm_active_connection_get_master (active)) {
|
||||
/* If the master connection is ready for slaves, attach ourselves */
|
||||
if (nm_active_connection_get_master_ready (active))
|
||||
master_ready_cb (active, NULL, self);
|
||||
else {
|
||||
nm_log_dbg (LOGD_DEVICE, "(%s): waiting for master connection to become ready",
|
||||
nm_device_get_iface (self));
|
||||
|
||||
/* Attach a signal handler and wait for the master connection to begin activating */
|
||||
g_assert (priv->master_ready_id == 0);
|
||||
priv->master_ready_id = g_signal_connect (active,
|
||||
"notify::" NM_ACTIVE_CONNECTION_INT_MASTER_READY,
|
||||
(GCallback) master_ready_cb,
|
||||
self);
|
||||
ret = NM_ACT_STAGE_RETURN_POSTPONE;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -3445,7 +3497,8 @@ nm_device_activate_stage3_ip_config_start (gpointer user_data)
|
|||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
const char *iface;
|
||||
int ifindex;
|
||||
NMDevice *master;
|
||||
NMActiveConnection *master;
|
||||
NMDevice *master_device;
|
||||
|
||||
/* Clear the activation source ID now that this stage has run */
|
||||
activation_source_clear (self, FALSE, 0);
|
||||
|
|
@ -3471,11 +3524,12 @@ nm_device_activate_stage3_ip_config_start (gpointer user_data)
|
|||
*/
|
||||
master = nm_active_connection_get_master (NM_ACTIVE_CONNECTION (priv->act_request));
|
||||
if (master) {
|
||||
if (priv->enslaved == FALSE) {
|
||||
master_device = nm_active_connection_get_device (master);
|
||||
if (master_device && priv->enslaved == FALSE) {
|
||||
nm_log_info (LOGD_DEVICE, "Activation (%s) connection '%s' waiting on master '%s'",
|
||||
nm_device_get_iface (self),
|
||||
nm_connection_get_id (nm_device_get_connection (self)),
|
||||
nm_device_get_iface (master));
|
||||
nm_device_get_iface (master_device));
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -4022,6 +4076,11 @@ clear_act_request (NMDevice *self)
|
|||
|
||||
nm_active_connection_set_default (NM_ACTIVE_CONNECTION (priv->act_request), FALSE);
|
||||
|
||||
if (priv->master_ready_id) {
|
||||
g_signal_handler_disconnect (priv->act_request, priv->master_ready_id);
|
||||
priv->master_ready_id = 0;
|
||||
}
|
||||
|
||||
g_object_unref (priv->act_request);
|
||||
priv->act_request = NULL;
|
||||
}
|
||||
|
|
@ -4425,8 +4484,6 @@ nm_device_activate (NMDevice *self, NMActRequest *req)
|
|||
nm_device_state_changed (self, NM_DEVICE_STATE_IP_CONFIG, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED);
|
||||
nm_device_activate_schedule_stage3_ip_config_start (self);
|
||||
} else {
|
||||
NMDevice *master;
|
||||
|
||||
/* HACK: update the state a bit early to avoid a race between the
|
||||
* scheduled stage1 handler and nm_policy_device_change_check() thinking
|
||||
* that the activation request isn't deferred because the deferred bit
|
||||
|
|
@ -4434,17 +4491,6 @@ nm_device_activate (NMDevice *self, NMActRequest *req)
|
|||
*/
|
||||
nm_device_state_changed (self, NM_DEVICE_STATE_PREPARE, NM_DEVICE_STATE_REASON_NONE);
|
||||
|
||||
/* Handle any dependencies this connection might have */
|
||||
master = nm_active_connection_get_master (NM_ACTIVE_CONNECTION (req));
|
||||
if (master) {
|
||||
/* Master should at least already be activating */
|
||||
g_assert (nm_device_get_state (master) > NM_DEVICE_STATE_DISCONNECTED);
|
||||
|
||||
g_assert (priv->master == NULL);
|
||||
priv->master = g_object_ref (master);
|
||||
nm_device_master_add_slave (master, self);
|
||||
}
|
||||
|
||||
nm_device_activate_schedule_stage1_device_prepare (self);
|
||||
}
|
||||
}
|
||||
|
|
@ -5027,6 +5073,7 @@ dispose (GObject *object)
|
|||
dnsmasq_cleanup (self);
|
||||
|
||||
g_warn_if_fail (priv->slaves == NULL);
|
||||
g_assert (priv->master_ready_id == 0);
|
||||
|
||||
/* Take the device itself down and clear its IPv4 configuration */
|
||||
if (nm_device_get_managed (self) && deconfigure) {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ AM_CPPFLAGS = \
|
|||
-I${top_builddir}/libnm-util \
|
||||
-I${top_srcdir}/libnm-util \
|
||||
$(DBUS_CFLAGS) \
|
||||
$(POLKIT_CFLAGS) \
|
||||
$(IWMX_SDK_CFLAGS) \
|
||||
$(LIBNL_CFLAGS) \
|
||||
$(GUDEV_CFLAGS)
|
||||
|
|
|
|||
|
|
@ -51,10 +51,6 @@ typedef struct {
|
|||
} ShareRule;
|
||||
|
||||
typedef struct {
|
||||
NMConnection *connection;
|
||||
NMDevice *device;
|
||||
guint device_state_id;
|
||||
char *dbus_sender;
|
||||
GSList *secrets_calls;
|
||||
gboolean shared;
|
||||
GSList *share_rules;
|
||||
|
|
@ -70,14 +66,6 @@ nm_act_request_get_connection (NMActRequest *req)
|
|||
return nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (req));
|
||||
}
|
||||
|
||||
const char *
|
||||
nm_act_request_get_dbus_sender (NMActRequest *req)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_ACT_REQUEST (req), NULL);
|
||||
|
||||
return NM_ACT_REQUEST_GET_PRIVATE (req)->dbus_sender;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -157,6 +145,7 @@ void
|
|||
nm_act_request_cancel_secrets (NMActRequest *self, guint32 call_id)
|
||||
{
|
||||
NMActRequestPrivate *priv;
|
||||
NMConnection *connection;
|
||||
GSList *iter;
|
||||
|
||||
g_return_if_fail (self);
|
||||
|
|
@ -165,6 +154,7 @@ nm_act_request_cancel_secrets (NMActRequest *self, guint32 call_id)
|
|||
|
||||
priv = NM_ACT_REQUEST_GET_PRIVATE (self);
|
||||
|
||||
connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (self));
|
||||
for (iter = priv->secrets_calls; iter; iter = g_slist_next (iter)) {
|
||||
GetSecretsInfo *info = iter->data;
|
||||
|
||||
|
|
@ -173,7 +163,7 @@ nm_act_request_cancel_secrets (NMActRequest *self, guint32 call_id)
|
|||
priv->secrets_calls = g_slist_remove_link (priv->secrets_calls, iter);
|
||||
g_slist_free (iter);
|
||||
|
||||
nm_settings_connection_cancel_secrets (NM_SETTINGS_CONNECTION (priv->connection), call_id);
|
||||
nm_settings_connection_cancel_secrets (NM_SETTINGS_CONNECTION (connection), call_id);
|
||||
g_free (info);
|
||||
break;
|
||||
}
|
||||
|
|
@ -295,13 +285,15 @@ nm_act_request_add_share_rule (NMActRequest *req,
|
|||
/********************************************************************/
|
||||
|
||||
static void
|
||||
device_state_changed (NMDevice *device, GParamSpec *pspec, NMActRequest *self)
|
||||
device_state_changed (NMActiveConnection *active,
|
||||
NMDevice *device,
|
||||
NMDeviceState new_state,
|
||||
NMDeviceState old_state)
|
||||
{
|
||||
NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (self);
|
||||
NMActiveConnectionState ac_state = NM_ACTIVE_CONNECTION_STATE_UNKNOWN;
|
||||
|
||||
/* Set NMActiveConnection state based on the device's state */
|
||||
switch (nm_device_get_state (device)) {
|
||||
switch (new_state) {
|
||||
case NM_DEVICE_STATE_PREPARE:
|
||||
case NM_DEVICE_STATE_CONFIG:
|
||||
case NM_DEVICE_STATE_NEED_AUTH:
|
||||
|
|
@ -321,13 +313,6 @@ device_state_changed (NMDevice *device, GParamSpec *pspec, NMActRequest *self)
|
|||
case NM_DEVICE_STATE_UNMANAGED:
|
||||
case NM_DEVICE_STATE_UNAVAILABLE:
|
||||
ac_state = NM_ACTIVE_CONNECTION_STATE_DEACTIVATED;
|
||||
|
||||
/* No longer need to pay attention to device state */
|
||||
if (priv->device && priv->device_state_id) {
|
||||
g_signal_handler_disconnect (priv->device, priv->device_state_id);
|
||||
priv->device_state_id = 0;
|
||||
}
|
||||
g_clear_object (&priv->device);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -335,11 +320,33 @@ device_state_changed (NMDevice *device, GParamSpec *pspec, NMActRequest *self)
|
|||
|
||||
if ( ac_state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED
|
||||
|| ac_state == NM_ACTIVE_CONNECTION_STATE_UNKNOWN) {
|
||||
nm_active_connection_set_default (NM_ACTIVE_CONNECTION (self), FALSE);
|
||||
nm_active_connection_set_default6 (NM_ACTIVE_CONNECTION (self), FALSE);
|
||||
nm_active_connection_set_default (active, FALSE);
|
||||
nm_active_connection_set_default6 (active, FALSE);
|
||||
}
|
||||
|
||||
nm_active_connection_set_state (NM_ACTIVE_CONNECTION (self), ac_state);
|
||||
nm_active_connection_set_state (active, ac_state);
|
||||
}
|
||||
|
||||
static void
|
||||
master_failed (NMActiveConnection *self)
|
||||
{
|
||||
NMDevice *device;
|
||||
NMDeviceState device_state;
|
||||
|
||||
/* If the connection has an active device, fail it */
|
||||
device = nm_active_connection_get_device (self);
|
||||
if (device) {
|
||||
device_state = nm_device_get_state (device);
|
||||
if (nm_device_is_activating (device) || (device_state == NM_DEVICE_STATE_ACTIVATED)) {
|
||||
nm_device_state_changed (device,
|
||||
NM_DEVICE_STATE_FAILED,
|
||||
NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* If no device, or the device wasn't active, just move to deactivated state */
|
||||
nm_active_connection_set_state (self, NM_ACTIVE_CONNECTION_STATE_DEACTIVATED);
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
|
|
@ -350,48 +357,31 @@ device_state_changed (NMDevice *device, GParamSpec *pspec, NMActRequest *self)
|
|||
* @connection: the connection to activate @device with
|
||||
* @specific_object: the object path of the specific object (ie, WiFi access point,
|
||||
* etc) that will be used to activate @connection and @device
|
||||
* @user_requested: pass %TRUE if the activation was requested via D-Bus,
|
||||
* otherwise %FALSE if requested internally by NM (ie, autoconnect)
|
||||
* @user_uid: if @user_requested is %TRUE, the Unix UID of the user that requested
|
||||
* @dbus_sender: if @user_requested is %TRUE, the D-BUS sender that requested
|
||||
* the activation
|
||||
* @device: the device/interface to configure according to @connection
|
||||
* @master: if the activation depends on another device (ie, bond or bridge
|
||||
* or team master to which this device will be enslaved) pass the #NMDevice
|
||||
* that this activation request be enslaved to
|
||||
* @subject: the #NMAuthSubject representing the requestor of the activation
|
||||
* @device: the device/interface to configure according to @connection; or %NULL
|
||||
* if the connection describes a software device which will be created during
|
||||
* connection activation
|
||||
*
|
||||
* Begins activation of @device using the given @connection and other details.
|
||||
* Creates a new device-based activation request.
|
||||
*
|
||||
* Returns: the new activation request on success, %NULL on error.
|
||||
*/
|
||||
NMActRequest *
|
||||
nm_act_request_new (NMConnection *connection,
|
||||
const char *specific_object,
|
||||
gboolean user_requested,
|
||||
gulong user_uid,
|
||||
const char *dbus_sender,
|
||||
NMDevice *device,
|
||||
NMDevice *master)
|
||||
NMAuthSubject *subject,
|
||||
NMDevice *device)
|
||||
{
|
||||
GObject *object;
|
||||
|
||||
g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
|
||||
g_return_val_if_fail (NM_DEVICE (device), NULL);
|
||||
g_return_val_if_fail (!device || NM_IS_DEVICE (device), NULL);
|
||||
g_return_val_if_fail (NM_IS_AUTH_SUBJECT (subject), NULL);
|
||||
|
||||
object = g_object_new (NM_TYPE_ACT_REQUEST,
|
||||
NM_ACTIVE_CONNECTION_INT_CONNECTION, connection,
|
||||
NM_ACTIVE_CONNECTION_INT_DEVICE, device,
|
||||
NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT, specific_object,
|
||||
NM_ACTIVE_CONNECTION_INT_USER_REQUESTED, user_requested,
|
||||
NM_ACTIVE_CONNECTION_INT_USER_UID, user_uid,
|
||||
NM_ACTIVE_CONNECTION_INT_MASTER, master,
|
||||
NULL);
|
||||
if (object) {
|
||||
nm_active_connection_export (NM_ACTIVE_CONNECTION (object));
|
||||
NM_ACT_REQUEST_GET_PRIVATE (object)->dbus_sender = g_strdup (dbus_sender);
|
||||
}
|
||||
|
||||
return (NMActRequest *) object;
|
||||
return (NMActRequest *) g_object_new (NM_TYPE_ACT_REQUEST,
|
||||
NM_ACTIVE_CONNECTION_INT_CONNECTION, connection,
|
||||
NM_ACTIVE_CONNECTION_INT_DEVICE, device,
|
||||
NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT, specific_object,
|
||||
NM_ACTIVE_CONNECTION_INT_SUBJECT, subject,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -399,39 +389,13 @@ nm_act_request_init (NMActRequest *req)
|
|||
{
|
||||
}
|
||||
|
||||
static void
|
||||
constructed (GObject *object)
|
||||
{
|
||||
NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (object);
|
||||
NMConnection *connection;
|
||||
NMDevice *device;
|
||||
|
||||
G_OBJECT_CLASS (nm_act_request_parent_class)->constructed (object);
|
||||
|
||||
connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (object));
|
||||
priv->connection = g_object_ref (connection);
|
||||
|
||||
device = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (object));
|
||||
if (device) {
|
||||
priv->device = g_object_ref (device);
|
||||
priv->device_state_id = g_signal_connect (priv->device,
|
||||
"notify::" NM_DEVICE_STATE,
|
||||
G_CALLBACK (device_state_changed),
|
||||
NM_ACT_REQUEST (object));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dispose (GObject *object)
|
||||
{
|
||||
NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (object);
|
||||
NMConnection *connection;
|
||||
GSList *iter;
|
||||
|
||||
if (priv->device && priv->device_state_id) {
|
||||
g_signal_handler_disconnect (priv->device, priv->device_state_id);
|
||||
priv->device_state_id = 0;
|
||||
}
|
||||
|
||||
/* Clear any share rules */
|
||||
if (priv->share_rules) {
|
||||
nm_act_request_set_shared (NM_ACT_REQUEST (object), FALSE);
|
||||
|
|
@ -439,22 +403,16 @@ dispose (GObject *object)
|
|||
}
|
||||
|
||||
/* Kill any in-progress secrets requests */
|
||||
for (iter = priv->secrets_calls; iter; iter = g_slist_next (iter)) {
|
||||
connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (object));
|
||||
for (iter = priv->secrets_calls; connection && iter; iter = g_slist_next (iter)) {
|
||||
GetSecretsInfo *info = iter->data;
|
||||
|
||||
g_assert (priv->connection);
|
||||
nm_settings_connection_cancel_secrets (NM_SETTINGS_CONNECTION (priv->connection), info->call_id);
|
||||
nm_settings_connection_cancel_secrets (NM_SETTINGS_CONNECTION (connection), info->call_id);
|
||||
g_free (info);
|
||||
}
|
||||
g_slist_free (priv->secrets_calls);
|
||||
priv->secrets_calls = NULL;
|
||||
|
||||
g_free (priv->dbus_sender);
|
||||
priv->dbus_sender = NULL;
|
||||
|
||||
g_clear_object (&priv->device);
|
||||
g_clear_object (&priv->connection);
|
||||
|
||||
G_OBJECT_CLASS (nm_act_request_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
|
|
@ -462,11 +420,13 @@ static void
|
|||
nm_act_request_class_init (NMActRequestClass *req_class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (req_class);
|
||||
NMActiveConnectionClass *active_class = NM_ACTIVE_CONNECTION_CLASS (req_class);
|
||||
|
||||
g_type_class_add_private (req_class, sizeof (NMActRequestPrivate));
|
||||
|
||||
/* virtual methods */
|
||||
object_class->constructed = constructed;
|
||||
object_class->dispose = dispose;
|
||||
active_class->master_failed = master_failed;
|
||||
active_class->device_state_changed = device_state_changed;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -48,18 +48,11 @@ GType nm_act_request_get_type (void);
|
|||
|
||||
NMActRequest *nm_act_request_new (NMConnection *connection,
|
||||
const char *specific_object,
|
||||
gboolean user_requested,
|
||||
gulong user_uid,
|
||||
const char *dbus_sender,
|
||||
NMDevice *device,
|
||||
NMDevice *master);
|
||||
NMAuthSubject *subject,
|
||||
NMDevice *device);
|
||||
|
||||
NMConnection *nm_act_request_get_connection (NMActRequest *req);
|
||||
|
||||
gulong nm_act_request_get_user_uid (NMActRequest *req);
|
||||
|
||||
const char *nm_act_request_get_dbus_sender (NMActRequest *req);
|
||||
|
||||
gboolean nm_act_request_get_shared (NMActRequest *req);
|
||||
|
||||
void nm_act_request_set_shared (NMActRequest *req, gboolean shared);
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
#include "nm-dbus-manager.h"
|
||||
#include "nm-device.h"
|
||||
#include "nm-settings-connection.h"
|
||||
#include "nm-manager-auth.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
|
||||
#include "nm-active-connection-glue.h"
|
||||
|
||||
|
|
@ -42,15 +44,22 @@ typedef struct {
|
|||
char *path;
|
||||
char *specific_object;
|
||||
NMDevice *device;
|
||||
guint32 device_state_id;
|
||||
|
||||
gboolean is_default;
|
||||
gboolean is_default6;
|
||||
NMActiveConnectionState state;
|
||||
gboolean vpn;
|
||||
|
||||
gboolean user_requested;
|
||||
gulong user_uid;
|
||||
NMDevice *master;
|
||||
NMAuthSubject *subject;
|
||||
NMActiveConnection *master;
|
||||
gboolean master_ready;
|
||||
|
||||
NMAuthChain *chain;
|
||||
const char *wifi_shared_permission;
|
||||
NMActiveConnectionAuthResultFunc result_func;
|
||||
gpointer user_data1;
|
||||
gpointer user_data2;
|
||||
} NMActiveConnectionPrivate;
|
||||
|
||||
enum {
|
||||
|
|
@ -67,15 +76,35 @@ enum {
|
|||
|
||||
PROP_INT_CONNECTION,
|
||||
PROP_INT_DEVICE,
|
||||
PROP_INT_USER_REQUESTED,
|
||||
PROP_INT_USER_UID,
|
||||
PROP_INT_SUBJECT,
|
||||
PROP_INT_MASTER,
|
||||
PROP_INT_MASTER_READY,
|
||||
|
||||
LAST_PROP
|
||||
};
|
||||
|
||||
static void check_master_ready (NMActiveConnection *self);
|
||||
|
||||
/****************************************************************/
|
||||
|
||||
static const char *
|
||||
state_to_string (NMActiveConnectionState state)
|
||||
{
|
||||
switch (state) {
|
||||
case NM_ACTIVE_CONNECTION_STATE_UNKNOWN:
|
||||
return "unknown";
|
||||
case NM_ACTIVE_CONNECTION_STATE_ACTIVATING:
|
||||
return "activating";
|
||||
case NM_ACTIVE_CONNECTION_STATE_ACTIVATED:
|
||||
return "activated";
|
||||
case NM_ACTIVE_CONNECTION_STATE_DEACTIVATING:
|
||||
return "deactivating";
|
||||
case NM_ACTIVE_CONNECTION_STATE_DEACTIVATED:
|
||||
return "deactivated";
|
||||
}
|
||||
return "(none)";
|
||||
}
|
||||
|
||||
NMActiveConnectionState
|
||||
nm_active_connection_get_state (NMActiveConnection *self)
|
||||
{
|
||||
|
|
@ -100,6 +129,8 @@ nm_active_connection_set_state (NMActiveConnection *self,
|
|||
priv->state = new_state;
|
||||
g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_STATE);
|
||||
|
||||
check_master_ready (self);
|
||||
|
||||
if ( new_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED
|
||||
|| old_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
|
||||
nm_settings_connection_update_timestamp (NM_SETTINGS_CONNECTION (priv->connection),
|
||||
|
|
@ -107,8 +138,10 @@ nm_active_connection_set_state (NMActiveConnection *self,
|
|||
}
|
||||
|
||||
if (priv->state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) {
|
||||
/* Device is no longer relevant when deactivated */
|
||||
g_clear_object (&priv->device);
|
||||
/* Device is no longer relevant when deactivated; emit property change
|
||||
* notification so clients re-read the value, which will be NULL due to
|
||||
* conditions in get_property().
|
||||
*/
|
||||
g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_DEVICES);
|
||||
}
|
||||
}
|
||||
|
|
@ -127,6 +160,21 @@ nm_active_connection_get_connection (NMActiveConnection *self)
|
|||
return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->connection;
|
||||
}
|
||||
|
||||
void
|
||||
nm_active_connection_set_connection (NMActiveConnection *self,
|
||||
NMConnection *connection)
|
||||
{
|
||||
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
||||
|
||||
/* Can't change connection after the ActiveConnection is exported over D-Bus */
|
||||
g_return_if_fail (priv->path == NULL);
|
||||
g_return_if_fail (priv->connection == NULL || !NM_IS_SETTINGS_CONNECTION (priv->connection));
|
||||
|
||||
if (priv->connection)
|
||||
g_object_unref (priv->connection);
|
||||
priv->connection = g_object_ref (connection);
|
||||
}
|
||||
|
||||
const char *
|
||||
nm_active_connection_get_path (NMActiveConnection *self)
|
||||
{
|
||||
|
|
@ -145,6 +193,11 @@ nm_active_connection_set_specific_object (NMActiveConnection *self,
|
|||
{
|
||||
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
||||
|
||||
/* Nothing that calls this function should be using paths from D-Bus,
|
||||
* where NM uses "/" to mean NULL.
|
||||
*/
|
||||
g_assert (g_strcmp0 (specific_object, "/") != 0);
|
||||
|
||||
if (g_strcmp0 (priv->specific_object, specific_object) == 0)
|
||||
return;
|
||||
|
||||
|
|
@ -205,24 +258,37 @@ nm_active_connection_export (NMActiveConnection *self)
|
|||
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
||||
static guint32 counter = 0;
|
||||
|
||||
g_assert (priv->device || priv->vpn);
|
||||
|
||||
priv->path = g_strdup_printf (NM_DBUS_PATH "/ActiveConnection/%d", counter++);
|
||||
nm_dbus_manager_register_object (nm_dbus_manager_get (), priv->path, self);
|
||||
}
|
||||
|
||||
NMAuthSubject *
|
||||
nm_active_connection_get_subject (NMActiveConnection *self)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), NULL);
|
||||
|
||||
return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->subject;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_active_connection_get_user_requested (NMActiveConnection *self)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), FALSE);
|
||||
|
||||
return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->user_requested;
|
||||
return !nm_auth_subject_get_internal (NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->subject);
|
||||
}
|
||||
|
||||
gulong
|
||||
nm_active_connection_get_user_uid (NMActiveConnection *self)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), G_MAXULONG);
|
||||
NMActiveConnectionPrivate *priv;
|
||||
|
||||
return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->user_uid;
|
||||
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), G_MAXULONG);
|
||||
priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
||||
|
||||
return nm_auth_subject_get_uid (priv->subject);
|
||||
}
|
||||
|
||||
NMDevice *
|
||||
|
|
@ -233,7 +299,73 @@ nm_active_connection_get_device (NMActiveConnection *self)
|
|||
return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->device;
|
||||
}
|
||||
|
||||
NMDevice *
|
||||
static void
|
||||
device_state_changed (NMDevice *device,
|
||||
NMDeviceState new_state,
|
||||
NMDeviceState old_state,
|
||||
NMDeviceStateReason reason,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMActiveConnection *self = NM_ACTIVE_CONNECTION (user_data);
|
||||
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
||||
|
||||
if (old_state < NM_DEVICE_STATE_DISCONNECTED)
|
||||
return;
|
||||
|
||||
if (old_state > NM_DEVICE_STATE_DISCONNECTED) {
|
||||
/* Ignore disconnects if this ActiveConnection has not yet started
|
||||
* activating. This is caused by activating a device when it's
|
||||
* already activated, which causes a deactivating of the device before
|
||||
* activating the new connection.
|
||||
*/
|
||||
if (new_state == NM_DEVICE_STATE_DISCONNECTED &&
|
||||
old_state > NM_DEVICE_STATE_DISCONNECTED &&
|
||||
priv->state == NM_ACTIVE_CONNECTION_STATE_UNKNOWN) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the device used to be active, but now is disconnected/failed, we
|
||||
* no longer care about its state.
|
||||
*/
|
||||
if (new_state <= NM_DEVICE_STATE_DISCONNECTED || new_state == NM_DEVICE_STATE_FAILED) {
|
||||
g_signal_handler_disconnect (device, priv->device_state_id);
|
||||
priv->device_state_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Let subclasses handle the state change */
|
||||
if (NM_ACTIVE_CONNECTION_GET_CLASS (self)->device_state_changed)
|
||||
NM_ACTIVE_CONNECTION_GET_CLASS (self)->device_state_changed (self, device, new_state, old_state);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_active_connection_set_device (NMActiveConnection *self, NMDevice *device)
|
||||
{
|
||||
NMActiveConnectionPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), FALSE);
|
||||
g_return_val_if_fail (!device || NM_IS_DEVICE (device), FALSE);
|
||||
|
||||
priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
||||
|
||||
if (device) {
|
||||
g_return_val_if_fail (priv->device == NULL, FALSE);
|
||||
|
||||
/* Device obviously can't be its own master */
|
||||
g_return_val_if_fail (!priv->master || device != nm_active_connection_get_device (priv->master), FALSE);
|
||||
|
||||
priv->device = g_object_ref (device);
|
||||
g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_INT_DEVICE);
|
||||
|
||||
priv->device_state_id = g_signal_connect (device,
|
||||
"state-changed",
|
||||
G_CALLBACK (device_state_changed),
|
||||
self);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
NMActiveConnection *
|
||||
nm_active_connection_get_master (NMActiveConnection *self)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), NULL);
|
||||
|
|
@ -241,6 +373,234 @@ nm_active_connection_get_master (NMActiveConnection *self)
|
|||
return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->master;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_active_connection_get_master_ready:
|
||||
* @self: the #NMActiveConnection
|
||||
*
|
||||
* Returns: %TRUE if the connection has a master connection, and that
|
||||
* master connection is ready to accept slaves. Otherwise %FALSE.
|
||||
*/
|
||||
gboolean
|
||||
nm_active_connection_get_master_ready (NMActiveConnection *self)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), FALSE);
|
||||
|
||||
return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->master_ready;
|
||||
}
|
||||
|
||||
static void
|
||||
check_master_ready (NMActiveConnection *self)
|
||||
{
|
||||
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
||||
NMActiveConnectionState master_state = NM_ACTIVE_CONNECTION_STATE_UNKNOWN;
|
||||
|
||||
if (priv->state != NM_ACTIVE_CONNECTION_STATE_ACTIVATING) {
|
||||
nm_log_dbg (LOGD_DEVICE, "(%p): not signalling master-ready (not activating)", self);
|
||||
return;
|
||||
}
|
||||
if (!priv->master) {
|
||||
nm_log_dbg (LOGD_DEVICE, "(%p): not signalling master-ready (no master)", self);
|
||||
return;
|
||||
}
|
||||
if (priv->master_ready) {
|
||||
nm_log_dbg (LOGD_DEVICE, "(%p): not signalling master-ready (already signaled)", self);
|
||||
return;
|
||||
}
|
||||
|
||||
/* ActiveConnetions don't enter the ACTIVATING state until they have a
|
||||
* NMDevice in PREPARE or higher states, so the master active connection's
|
||||
* device will be ready to accept slaves when the master is in ACTIVATING
|
||||
* or higher states.
|
||||
*/
|
||||
master_state = nm_active_connection_get_state (priv->master);
|
||||
nm_log_dbg (LOGD_DEVICE, "(%p): master ActiveConnection [%p] state now '%s' (%d)",
|
||||
self, priv->master, state_to_string (master_state), master_state);
|
||||
|
||||
if ( master_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING
|
||||
|| master_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
|
||||
nm_log_dbg (LOGD_DEVICE, "(%p): signalling master-ready", self);
|
||||
|
||||
priv->master_ready = TRUE;
|
||||
g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_INT_MASTER_READY);
|
||||
|
||||
/* Also notify clients to recheck the exported 'master' property to
|
||||
* ensure that if the master connection was created without a device
|
||||
* that we notify clients when the master device is known.
|
||||
*/
|
||||
g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_MASTER);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
master_state_cb (NMActiveConnection *master,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMActiveConnection *self = NM_ACTIVE_CONNECTION (user_data);
|
||||
NMActiveConnectionState self_state = nm_active_connection_get_state (self);
|
||||
NMActiveConnectionState master_state = nm_active_connection_get_state (master);
|
||||
|
||||
check_master_ready (self);
|
||||
|
||||
nm_log_dbg (LOGD_DEVICE, "(%p): master ActiveConnection [%p] state now '%s' (%d)",
|
||||
self, master, state_to_string (master_state), master_state);
|
||||
|
||||
/* Master is deactivating, so this active connection must also deactivate */
|
||||
if (self_state < NM_ACTIVE_CONNECTION_STATE_DEACTIVATING &&
|
||||
master_state >= NM_ACTIVE_CONNECTION_STATE_DEACTIVATING) {
|
||||
nm_log_dbg (LOGD_DEVICE, "(%p): master ActiveConnection [%p] '%s' failed",
|
||||
self, master, nm_active_connection_get_name (master));
|
||||
|
||||
g_signal_handlers_disconnect_by_func (master,
|
||||
(GCallback) master_state_cb,
|
||||
self);
|
||||
if (NM_ACTIVE_CONNECTION_GET_CLASS (self)->master_failed)
|
||||
NM_ACTIVE_CONNECTION_GET_CLASS (self)->master_failed (self);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_active_connection_set_master:
|
||||
* @self: the #NMActiveConnection
|
||||
* @master: if the activation depends on another device (ie, bond or bridge
|
||||
* master to which this device will be enslaved) pass the #NMActiveConnection
|
||||
* that this activation request is a child of
|
||||
*
|
||||
* Sets the master active connection of @self.
|
||||
*/
|
||||
void
|
||||
nm_active_connection_set_master (NMActiveConnection *self, NMActiveConnection *master)
|
||||
{
|
||||
NMActiveConnectionPrivate *priv;
|
||||
|
||||
g_return_if_fail (NM_IS_ACTIVE_CONNECTION (self));
|
||||
g_return_if_fail (NM_IS_ACTIVE_CONNECTION (master));
|
||||
|
||||
priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
||||
|
||||
/* Master is write-once, and must be set before exporting the object */
|
||||
g_return_if_fail (priv->master == NULL);
|
||||
g_return_if_fail (priv->path == NULL);
|
||||
if (priv->device) {
|
||||
/* Note, the master ActiveConnection may not yet have a device */
|
||||
g_return_if_fail (priv->device != nm_active_connection_get_device (master));
|
||||
}
|
||||
|
||||
nm_log_dbg (LOGD_DEVICE, "(%p): master ActiveConnection is [%p] %s",
|
||||
self, master, nm_active_connection_get_name (master));
|
||||
|
||||
priv->master = g_object_ref (master);
|
||||
g_signal_connect (priv->master,
|
||||
"notify::" NM_ACTIVE_CONNECTION_STATE,
|
||||
(GCallback) master_state_cb,
|
||||
self);
|
||||
|
||||
check_master_ready (self);
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
|
||||
static void
|
||||
auth_done (NMAuthChain *chain,
|
||||
GError *error,
|
||||
DBusGMethodInvocation *unused,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMActiveConnection *self = NM_ACTIVE_CONNECTION (user_data);
|
||||
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
||||
NMAuthCallResult result;
|
||||
|
||||
g_assert (priv->chain == chain);
|
||||
g_assert (priv->result_func != NULL);
|
||||
|
||||
/* Must stay alive over the callback */
|
||||
g_object_ref (self);
|
||||
|
||||
if (error) {
|
||||
priv->result_func (self, FALSE, error->message, priv->user_data1, priv->user_data2);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Caller has had a chance to obtain authorization, so we only need to
|
||||
* check for 'yes' here.
|
||||
*/
|
||||
result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL);
|
||||
if (result != NM_AUTH_CALL_RESULT_YES) {
|
||||
priv->result_func (self,
|
||||
FALSE,
|
||||
"Not authorized to control networking.",
|
||||
priv->user_data1,
|
||||
priv->user_data2);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (priv->wifi_shared_permission) {
|
||||
result = nm_auth_chain_get_result (chain, priv->wifi_shared_permission);
|
||||
if (result != NM_AUTH_CALL_RESULT_YES) {
|
||||
priv->result_func (self,
|
||||
FALSE,
|
||||
"Not authorized to share connections via wifi.",
|
||||
priv->user_data1,
|
||||
priv->user_data2);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise authorized and available to activate */
|
||||
priv->result_func (self, TRUE, NULL, priv->user_data1, priv->user_data2);
|
||||
|
||||
done:
|
||||
nm_auth_chain_unref (chain);
|
||||
priv->chain = NULL;
|
||||
priv->result_func = NULL;
|
||||
priv->user_data1 = NULL;
|
||||
priv->user_data2 = NULL;
|
||||
|
||||
g_object_unref (self);
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_active_connection_authorize:
|
||||
* @self: the #NMActiveConnection
|
||||
* @result_func: function to be called on success or error
|
||||
* @user_data1: pointer passed to @result_func
|
||||
* @user_data2: additional pointer passed to @result_func
|
||||
*
|
||||
* Checks whether the subject that initiated the active connection (read from
|
||||
* the #NMActiveConnection::subject property) is authorized to complete this
|
||||
* activation request.
|
||||
*/
|
||||
void
|
||||
nm_active_connection_authorize (NMActiveConnection *self,
|
||||
NMActiveConnectionAuthResultFunc result_func,
|
||||
gpointer user_data1,
|
||||
gpointer user_data2)
|
||||
{
|
||||
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
||||
const char *wifi_permission = NULL;
|
||||
|
||||
g_return_if_fail (result_func != NULL);
|
||||
g_return_if_fail (priv->chain == NULL);
|
||||
|
||||
priv->chain = nm_auth_chain_new_subject (priv->subject, NULL, auth_done, self);
|
||||
g_assert (priv->chain);
|
||||
|
||||
/* Check that the subject is allowed to use networking at all */
|
||||
nm_auth_chain_add_call (priv->chain, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE);
|
||||
|
||||
/* Shared wifi connections require special permissions too */
|
||||
wifi_permission = nm_utils_get_shared_wifi_permission (priv->connection);
|
||||
if (wifi_permission) {
|
||||
priv->wifi_shared_permission = wifi_permission;
|
||||
nm_auth_chain_add_call (priv->chain, wifi_permission, TRUE);
|
||||
}
|
||||
|
||||
/* Wait for authorization */
|
||||
priv->result_func = result_func;
|
||||
priv->user_data1 = user_data1;
|
||||
priv->user_data2 = user_data2;
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
|
||||
static void
|
||||
|
|
@ -248,11 +608,19 @@ nm_active_connection_init (NMActiveConnection *self)
|
|||
{
|
||||
}
|
||||
|
||||
static void
|
||||
constructed (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (nm_active_connection_parent_class)->constructed (object);
|
||||
g_assert (NM_ACTIVE_CONNECTION_GET_PRIVATE (object)->subject);
|
||||
}
|
||||
|
||||
static void
|
||||
set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object);
|
||||
const char *tmp;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_INT_CONNECTION:
|
||||
|
|
@ -260,25 +628,19 @@ set_property (GObject *object, guint prop_id,
|
|||
priv->connection = g_value_dup_object (value);
|
||||
break;
|
||||
case PROP_INT_DEVICE:
|
||||
g_warn_if_fail (priv->device == NULL);
|
||||
priv->device = g_value_dup_object (value);
|
||||
if (priv->device)
|
||||
g_warn_if_fail (priv->device != priv->master);
|
||||
nm_active_connection_set_device (NM_ACTIVE_CONNECTION (object), g_value_get_object (value));
|
||||
break;
|
||||
case PROP_INT_USER_REQUESTED:
|
||||
priv->user_requested = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_INT_USER_UID:
|
||||
priv->user_uid = g_value_get_ulong (value);
|
||||
case PROP_INT_SUBJECT:
|
||||
priv->subject = g_value_dup_object (value);
|
||||
break;
|
||||
case PROP_INT_MASTER:
|
||||
g_warn_if_fail (priv->master == NULL);
|
||||
priv->master = g_value_dup_object (value);
|
||||
if (priv->master)
|
||||
g_warn_if_fail (priv->master != priv->device);
|
||||
nm_active_connection_set_master (NM_ACTIVE_CONNECTION (object), g_value_get_object (value));
|
||||
break;
|
||||
case PROP_SPECIFIC_OBJECT:
|
||||
priv->specific_object = g_value_dup_boxed (value);
|
||||
tmp = g_value_get_boxed (value);
|
||||
/* NM uses "/" to mean NULL */
|
||||
if (g_strcmp0 (tmp, "/") != 0)
|
||||
priv->specific_object = g_value_dup_boxed (value);
|
||||
break;
|
||||
case PROP_DEFAULT:
|
||||
priv->is_default = g_value_get_boolean (value);
|
||||
|
|
@ -303,6 +665,7 @@ get_property (GObject *object, guint prop_id,
|
|||
{
|
||||
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object);
|
||||
GPtrArray *devices;
|
||||
NMDevice *master_device = NULL;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_CONNECTION:
|
||||
|
|
@ -316,7 +679,7 @@ get_property (GObject *object, guint prop_id,
|
|||
break;
|
||||
case PROP_DEVICES:
|
||||
devices = g_ptr_array_sized_new (1);
|
||||
if (priv->device)
|
||||
if (priv->device && priv->state < NM_ACTIVE_CONNECTION_STATE_DEACTIVATED)
|
||||
g_ptr_array_add (devices, g_strdup (nm_device_get_path (priv->device)));
|
||||
g_value_take_boxed (value, devices);
|
||||
break;
|
||||
|
|
@ -333,7 +696,15 @@ get_property (GObject *object, guint prop_id,
|
|||
g_value_set_boolean (value, priv->vpn);
|
||||
break;
|
||||
case PROP_MASTER:
|
||||
g_value_set_boxed (value, priv->master ? nm_device_get_path (priv->master) : "/");
|
||||
if (priv->master)
|
||||
master_device = nm_active_connection_get_device (priv->master);
|
||||
g_value_set_boxed (value, master_device ? nm_device_get_path (master_device) : "/");
|
||||
break;
|
||||
case PROP_INT_SUBJECT:
|
||||
g_value_set_object (value, priv->subject);
|
||||
break;
|
||||
case PROP_INT_MASTER_READY:
|
||||
g_value_set_boolean (value, priv->master_ready);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
|
|
@ -346,14 +717,32 @@ dispose (GObject *object)
|
|||
{
|
||||
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object);
|
||||
|
||||
if (priv->chain) {
|
||||
nm_auth_chain_unref (priv->chain);
|
||||
priv->chain = NULL;
|
||||
}
|
||||
|
||||
g_free (priv->path);
|
||||
priv->path = NULL;
|
||||
g_free (priv->specific_object);
|
||||
priv->specific_object = NULL;
|
||||
|
||||
g_clear_object (&priv->connection);
|
||||
|
||||
if (priv->device_state_id) {
|
||||
g_assert (priv->device);
|
||||
g_signal_handler_disconnect (priv->device, priv->device_state_id);
|
||||
priv->device_state_id = 0;
|
||||
}
|
||||
g_clear_object (&priv->device);
|
||||
|
||||
if (priv->master) {
|
||||
g_signal_handlers_disconnect_by_func (priv->master,
|
||||
(GCallback) master_state_cb,
|
||||
NM_ACTIVE_CONNECTION (object));
|
||||
}
|
||||
g_clear_object (&priv->master);
|
||||
g_clear_object (&priv->subject);
|
||||
|
||||
G_OBJECT_CLASS (nm_active_connection_parent_class)->dispose (object);
|
||||
}
|
||||
|
|
@ -368,6 +757,7 @@ nm_active_connection_class_init (NMActiveConnectionClass *ac_class)
|
|||
/* virtual methods */
|
||||
object_class->get_property = get_property;
|
||||
object_class->set_property = set_property;
|
||||
object_class->constructed = constructed;
|
||||
object_class->dispose = dispose;
|
||||
|
||||
/* D-Bus exported properties */
|
||||
|
|
@ -449,28 +839,27 @@ nm_active_connection_class_init (NMActiveConnectionClass *ac_class)
|
|||
"Internal device",
|
||||
"Internal device",
|
||||
NM_TYPE_DEVICE,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_INT_SUBJECT,
|
||||
g_param_spec_object (NM_ACTIVE_CONNECTION_INT_SUBJECT,
|
||||
"Subject",
|
||||
"Subject",
|
||||
NM_TYPE_AUTH_SUBJECT,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_INT_USER_REQUESTED,
|
||||
g_param_spec_boolean (NM_ACTIVE_CONNECTION_INT_USER_REQUESTED,
|
||||
"User requested",
|
||||
"User requested",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_INT_USER_UID,
|
||||
g_param_spec_ulong (NM_ACTIVE_CONNECTION_INT_USER_UID,
|
||||
"User UID",
|
||||
"User UID (if user requested)",
|
||||
0, G_MAXULONG, 0,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_INT_MASTER,
|
||||
g_param_spec_object (NM_ACTIVE_CONNECTION_INT_MASTER,
|
||||
"Internal master device",
|
||||
"Internal device",
|
||||
NM_TYPE_DEVICE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
"Internal master active connection",
|
||||
"Internal active connection",
|
||||
NM_TYPE_ACTIVE_CONNECTION,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_INT_MASTER_READY,
|
||||
g_param_spec_boolean (NM_ACTIVE_CONNECTION_INT_MASTER_READY,
|
||||
"Internal master active connection ready for slaves",
|
||||
"Internal active connection ready",
|
||||
FALSE, G_PARAM_READABLE));
|
||||
|
||||
nm_dbus_manager_register_exported_type (nm_dbus_manager_get (),
|
||||
G_TYPE_FROM_CLASS (ac_class),
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include <glib-object.h>
|
||||
#include "nm-types.h"
|
||||
#include "nm-connection.h"
|
||||
#include "nm-auth-subject.h"
|
||||
|
||||
#define NM_TYPE_ACTIVE_CONNECTION (nm_active_connection_get_type ())
|
||||
#define NM_ACTIVE_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_ACTIVE_CONNECTION, NMActiveConnection))
|
||||
|
|
@ -43,13 +44,12 @@
|
|||
#define NM_ACTIVE_CONNECTION_VPN "vpn"
|
||||
#define NM_ACTIVE_CONNECTION_MASTER "master"
|
||||
|
||||
/* Internal non-exported construct-time properties */
|
||||
/* Internal non-exported properties */
|
||||
#define NM_ACTIVE_CONNECTION_INT_CONNECTION "int-connection"
|
||||
#define NM_ACTIVE_CONNECTION_INT_DEVICE "int-device"
|
||||
#define NM_ACTIVE_CONNECTION_INT_USER_REQUESTED "int-user-requested"
|
||||
#define NM_ACTIVE_CONNECTION_INT_USER_UID "int-user-uid"
|
||||
#define NM_ACTIVE_CONNECTION_INT_SUBJECT "int-subject"
|
||||
#define NM_ACTIVE_CONNECTION_INT_MASTER "int-master"
|
||||
|
||||
#define NM_ACTIVE_CONNECTION_INT_MASTER_READY "int-master-ready"
|
||||
|
||||
typedef struct {
|
||||
GObject parent;
|
||||
|
|
@ -58,13 +58,36 @@ typedef struct {
|
|||
typedef struct {
|
||||
GObjectClass parent;
|
||||
|
||||
/* re-emits device state changes as a convenience for subclasses for
|
||||
* device states >= DISCONNECTED.
|
||||
*/
|
||||
void (*device_state_changed) (NMActiveConnection *connection,
|
||||
NMDevice *device,
|
||||
NMDeviceState new_state,
|
||||
NMDeviceState old_state);
|
||||
void (*master_failed) (NMActiveConnection *connection);
|
||||
} NMActiveConnectionClass;
|
||||
|
||||
GType nm_active_connection_get_type (void);
|
||||
|
||||
typedef void (*NMActiveConnectionAuthResultFunc) (NMActiveConnection *self,
|
||||
gboolean success,
|
||||
const char *error_desc,
|
||||
gpointer user_data1,
|
||||
gpointer user_data2);
|
||||
|
||||
void nm_active_connection_authorize (NMActiveConnection *self,
|
||||
NMActiveConnectionAuthResultFunc result_func,
|
||||
gpointer user_data1,
|
||||
gpointer user_data2);
|
||||
|
||||
void nm_active_connection_export (NMActiveConnection *self);
|
||||
|
||||
NMConnection *nm_active_connection_get_connection (NMActiveConnection *self);
|
||||
|
||||
void nm_active_connection_set_connection (NMActiveConnection *self,
|
||||
NMConnection *connection);
|
||||
|
||||
const char * nm_active_connection_get_name (NMActiveConnection *self);
|
||||
|
||||
const char * nm_active_connection_get_path (NMActiveConnection *self);
|
||||
|
|
@ -91,10 +114,19 @@ void nm_active_connection_set_state (NMActiveConnection *self,
|
|||
|
||||
NMDevice * nm_active_connection_get_device (NMActiveConnection *self);
|
||||
|
||||
gboolean nm_active_connection_set_device (NMActiveConnection *self, NMDevice *device);
|
||||
|
||||
NMAuthSubject *nm_active_connection_get_subject (NMActiveConnection *self);
|
||||
|
||||
gboolean nm_active_connection_get_user_requested (NMActiveConnection *self);
|
||||
|
||||
gulong nm_active_connection_get_user_uid (NMActiveConnection *self);
|
||||
|
||||
NMDevice * nm_active_connection_get_master (NMActiveConnection *self);
|
||||
NMActiveConnection *nm_active_connection_get_master (NMActiveConnection *self);
|
||||
|
||||
gboolean nm_active_connection_get_master_ready (NMActiveConnection *self);
|
||||
|
||||
void nm_active_connection_set_master (NMActiveConnection *self,
|
||||
NMActiveConnection *master);
|
||||
|
||||
#endif /* NM_ACTIVE_CONNECTION_H */
|
||||
|
|
|
|||
210
src/nm-auth-subject.c
Normal file
210
src/nm-auth-subject.c
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
/* NetworkManager -- Network link manager
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Copyright (C) 2013 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:nm-auth-subject
|
||||
* @short_description: Encapsulates authentication information about a requestor
|
||||
*
|
||||
* #NMAuthSubject encpasulates identifying information about an entity that
|
||||
* makes requests, like process identifier and user UID.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <glib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if WITH_POLKIT
|
||||
#include <polkit/polkit.h>
|
||||
#endif
|
||||
|
||||
#include "nm-auth-subject.h"
|
||||
#include "nm-dbus-manager.h"
|
||||
|
||||
G_DEFINE_TYPE (NMAuthSubject, nm_auth_subject, G_TYPE_OBJECT)
|
||||
|
||||
#define NM_AUTH_SUBJECT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_AUTH_SUBJECT, NMAuthSubjectPrivate))
|
||||
|
||||
typedef struct {
|
||||
gulong pid;
|
||||
gulong uid;
|
||||
char *dbus_sender;
|
||||
|
||||
#if WITH_POLKIT
|
||||
PolkitSubject *pk_subject;
|
||||
#endif
|
||||
} NMAuthSubjectPrivate;
|
||||
|
||||
static NMAuthSubject *
|
||||
_new_common (DBusGMethodInvocation *context,
|
||||
DBusConnection *connection,
|
||||
DBusMessage *message,
|
||||
gboolean internal)
|
||||
{
|
||||
NMAuthSubject *subject;
|
||||
NMAuthSubjectPrivate *priv;
|
||||
NMDBusManager *dbus_mgr;
|
||||
gboolean success = FALSE;
|
||||
|
||||
g_return_val_if_fail (context || (connection && message) || internal, NULL);
|
||||
if (internal)
|
||||
g_return_val_if_fail (context == NULL && connection == NULL && message == NULL, NULL);
|
||||
|
||||
subject = NM_AUTH_SUBJECT (g_object_new (NM_TYPE_AUTH_SUBJECT, NULL));
|
||||
priv = NM_AUTH_SUBJECT_GET_PRIVATE (subject);
|
||||
|
||||
dbus_mgr = nm_dbus_manager_get ();
|
||||
|
||||
if (internal) {
|
||||
priv->uid = 0;
|
||||
priv->pid = 0;
|
||||
return subject;
|
||||
}
|
||||
|
||||
if (context) {
|
||||
success = nm_dbus_manager_get_caller_info (dbus_mgr,
|
||||
context,
|
||||
&priv->dbus_sender,
|
||||
&priv->uid,
|
||||
&priv->pid);
|
||||
} else if (message) {
|
||||
success = nm_dbus_manager_get_caller_info_from_message (dbus_mgr,
|
||||
connection,
|
||||
message,
|
||||
&priv->dbus_sender,
|
||||
&priv->uid,
|
||||
&priv->pid);
|
||||
} else
|
||||
g_assert_not_reached ();
|
||||
|
||||
if (!success) {
|
||||
g_object_unref (subject);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_assert (priv->dbus_sender);
|
||||
g_assert_cmpuint (priv->pid, !=, 0);
|
||||
|
||||
#if WITH_POLKIT
|
||||
/* FIXME: should we use polkit_unix_session_new() to store the session ID
|
||||
* of a short-lived process, so that the process can exit but we can still
|
||||
* ask that user for authorization?
|
||||
*/
|
||||
priv->pk_subject = polkit_unix_process_new_for_owner (priv->pid, 0, priv->uid);
|
||||
if (!priv->pk_subject)
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
return subject;
|
||||
}
|
||||
|
||||
|
||||
NMAuthSubject *
|
||||
nm_auth_subject_new_from_context (DBusGMethodInvocation *context)
|
||||
{
|
||||
return _new_common (context, NULL, NULL, FALSE);
|
||||
}
|
||||
|
||||
NMAuthSubject *
|
||||
nm_auth_subject_new_from_message (DBusConnection *connection,
|
||||
DBusMessage *message)
|
||||
{
|
||||
return _new_common (NULL, connection, message, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_auth_subject_new_internal():
|
||||
*
|
||||
* Creates a new auth subject representing the NetworkManager process itself.
|
||||
*
|
||||
* Returns: the new #NMAuthSubject
|
||||
*/
|
||||
NMAuthSubject *
|
||||
nm_auth_subject_new_internal (void)
|
||||
{
|
||||
return _new_common (NULL, NULL, NULL, TRUE);
|
||||
}
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
gulong
|
||||
nm_auth_subject_get_uid (NMAuthSubject *subject)
|
||||
{
|
||||
return NM_AUTH_SUBJECT_GET_PRIVATE (subject)->uid;
|
||||
}
|
||||
|
||||
const char *
|
||||
nm_auth_subject_get_dbus_sender (NMAuthSubject *subject)
|
||||
{
|
||||
return NM_AUTH_SUBJECT_GET_PRIVATE (subject)->dbus_sender;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_auth_subject_get_internal (NMAuthSubject *subject)
|
||||
{
|
||||
/* internal requests will have no dbus sender */
|
||||
return NM_AUTH_SUBJECT_GET_PRIVATE (subject)->dbus_sender ? FALSE : TRUE;
|
||||
}
|
||||
|
||||
#if WITH_POLKIT
|
||||
PolkitSubject *
|
||||
nm_auth_subject_get_polkit_subject (NMAuthSubject *subject)
|
||||
{
|
||||
return NM_AUTH_SUBJECT_GET_PRIVATE (subject)->pk_subject;
|
||||
}
|
||||
#endif
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
static void
|
||||
nm_auth_subject_init (NMAuthSubject *self)
|
||||
{
|
||||
NMAuthSubjectPrivate *priv = NM_AUTH_SUBJECT_GET_PRIVATE (self);
|
||||
|
||||
priv->pid = G_MAXULONG;
|
||||
priv->uid = G_MAXULONG;
|
||||
}
|
||||
|
||||
static void
|
||||
finalize (GObject *object)
|
||||
{
|
||||
NMAuthSubjectPrivate *priv = NM_AUTH_SUBJECT_GET_PRIVATE (object);
|
||||
|
||||
g_free (priv->dbus_sender);
|
||||
|
||||
#if WITH_POLKIT
|
||||
if (priv->pk_subject)
|
||||
g_object_unref (priv->pk_subject);
|
||||
#endif
|
||||
|
||||
G_OBJECT_CLASS (nm_auth_subject_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
nm_auth_subject_class_init (NMAuthSubjectClass *config_class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (config_class);
|
||||
|
||||
g_type_class_add_private (config_class, sizeof (NMAuthSubjectPrivate));
|
||||
|
||||
/* virtual methods */
|
||||
object_class->finalize = finalize;
|
||||
}
|
||||
68
src/nm-auth-subject.h
Normal file
68
src/nm-auth-subject.h
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
/* NetworkManager -- Network link manager
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Copyright (C) 2013 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#ifndef NM_AUTH_SUBJECT_H
|
||||
#define NM_AUTH_SUBJECT_H
|
||||
|
||||
#include <config.h>
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <dbus/dbus.h>
|
||||
#include <dbus/dbus-glib.h>
|
||||
|
||||
#if WITH_POLKIT
|
||||
#include <polkit/polkit.h>
|
||||
#endif
|
||||
|
||||
#define NM_TYPE_AUTH_SUBJECT (nm_auth_subject_get_type ())
|
||||
#define NM_AUTH_SUBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_AUTH_SUBJECT, NMAuthSubject))
|
||||
#define NM_AUTH_SUBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_AUTH_SUBJECT, NMAuthSubjectClass))
|
||||
#define NM_IS_AUTH_SUBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_AUTH_SUBJECT))
|
||||
#define NM_IS_AUTH_SUBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_AUTH_SUBJECT))
|
||||
#define NM_AUTH_SUBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_AUTH_SUBJECT, NMAuthSubjectClass))
|
||||
|
||||
typedef struct {
|
||||
GObject parent;
|
||||
} NMAuthSubject;
|
||||
|
||||
typedef struct {
|
||||
GObjectClass parent;
|
||||
|
||||
} NMAuthSubjectClass;
|
||||
|
||||
GType nm_auth_subject_get_type (void);
|
||||
|
||||
NMAuthSubject *nm_auth_subject_new_from_context (DBusGMethodInvocation *context);
|
||||
|
||||
NMAuthSubject *nm_auth_subject_new_from_message (DBusConnection *connection, DBusMessage *message);
|
||||
|
||||
NMAuthSubject *nm_auth_subject_new_internal (void);
|
||||
|
||||
gulong nm_auth_subject_get_uid (NMAuthSubject *subject);
|
||||
|
||||
const char *nm_auth_subject_get_dbus_sender (NMAuthSubject *subject);
|
||||
|
||||
gboolean nm_auth_subject_get_internal (NMAuthSubject *subject);
|
||||
|
||||
#if WITH_POLKIT
|
||||
PolkitSubject *nm_auth_subject_get_polkit_subject (NMAuthSubject *subject);
|
||||
#endif
|
||||
|
||||
#endif /* NM_AUTH_SUBJECT_H */
|
||||
|
|
@ -267,6 +267,27 @@ private_server_get_connection_owner (PrivateServer *s, DBusGConnection *connecti
|
|||
|
||||
/**************************************************************/
|
||||
|
||||
static gboolean
|
||||
_bus_get_unix_pid (NMDBusManager *self,
|
||||
const char *sender,
|
||||
gulong *out_pid,
|
||||
GError **error)
|
||||
{
|
||||
guint32 unix_pid = G_MAXUINT32;
|
||||
|
||||
if (!dbus_g_proxy_call_with_timeout (NM_DBUS_MANAGER_GET_PRIVATE (self)->proxy,
|
||||
"GetConnectionUnixProcessID", 2000, error,
|
||||
G_TYPE_STRING, sender,
|
||||
G_TYPE_INVALID,
|
||||
G_TYPE_UINT, &unix_pid,
|
||||
G_TYPE_INVALID)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*out_pid = (gulong) unix_pid;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* _get_caller_info_from_context():
|
||||
*
|
||||
|
|
@ -279,7 +300,8 @@ _get_caller_info (NMDBusManager *self,
|
|||
DBusConnection *connection,
|
||||
DBusMessage *message,
|
||||
char **out_sender,
|
||||
gulong *out_uid)
|
||||
gulong *out_uid,
|
||||
gulong *out_pid)
|
||||
{
|
||||
NMDBusManagerPrivate *priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
|
||||
DBusGConnection *gconn;
|
||||
|
|
@ -312,6 +334,10 @@ _get_caller_info (NMDBusManager *self,
|
|||
*out_uid = 0;
|
||||
if (out_sender)
|
||||
*out_sender = g_strdup (priv_sender);
|
||||
if (out_pid) {
|
||||
if (!dbus_connection_get_unix_process_id (connection, out_pid))
|
||||
*out_pid = G_MAXULONG;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
|
@ -331,6 +357,14 @@ _get_caller_info (NMDBusManager *self,
|
|||
}
|
||||
}
|
||||
|
||||
if (out_pid) {
|
||||
if (!_bus_get_unix_pid (self, sender, out_pid, NULL)) {
|
||||
*out_pid = G_MAXULONG;
|
||||
g_free (sender);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (out_sender)
|
||||
*out_sender = g_strdup (sender);
|
||||
|
||||
|
|
@ -342,9 +376,10 @@ gboolean
|
|||
nm_dbus_manager_get_caller_info (NMDBusManager *self,
|
||||
DBusGMethodInvocation *context,
|
||||
char **out_sender,
|
||||
gulong *out_uid)
|
||||
gulong *out_uid,
|
||||
gulong *out_pid)
|
||||
{
|
||||
return _get_caller_info (self, context, NULL, NULL, out_sender, out_uid);
|
||||
return _get_caller_info (self, context, NULL, NULL, out_sender, out_uid, out_pid);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
|
@ -352,9 +387,10 @@ nm_dbus_manager_get_caller_info_from_message (NMDBusManager *self,
|
|||
DBusConnection *connection,
|
||||
DBusMessage *message,
|
||||
char **out_sender,
|
||||
gulong *out_uid)
|
||||
gulong *out_uid,
|
||||
gulong *out_pid)
|
||||
{
|
||||
return _get_caller_info (self, NULL, connection, message, out_sender, out_uid);
|
||||
return _get_caller_info (self, NULL, connection, message, out_sender, out_uid, out_pid);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
|
|
|||
|
|
@ -87,7 +87,8 @@ DBusGConnection * nm_dbus_manager_get_connection (NMDBusManager *self);
|
|||
gboolean nm_dbus_manager_get_caller_info (NMDBusManager *self,
|
||||
DBusGMethodInvocation *context,
|
||||
char **out_sender,
|
||||
gulong *out_uid);
|
||||
gulong *out_uid,
|
||||
gulong *out_pid);
|
||||
|
||||
gboolean nm_dbus_manager_get_unix_user (NMDBusManager *self,
|
||||
const char *sender,
|
||||
|
|
@ -97,7 +98,8 @@ gboolean nm_dbus_manager_get_caller_info_from_message (NMDBusManager *self,
|
|||
DBusConnection *connection,
|
||||
DBusMessage *message,
|
||||
char **out_sender,
|
||||
gulong *out_uid);
|
||||
gulong *out_uid,
|
||||
gulong *out_pid);
|
||||
|
||||
void nm_dbus_manager_register_exported_type (NMDBusManager *self,
|
||||
GType object_type,
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "nm-manager-auth.h"
|
||||
#include "nm-logging.h"
|
||||
#include "nm-dbus-manager.h"
|
||||
#include "nm-auth-subject.h"
|
||||
|
||||
struct NMAuthChain {
|
||||
guint32 refcount;
|
||||
|
|
@ -43,6 +44,7 @@ struct NMAuthChain {
|
|||
DBusGMethodInvocation *context;
|
||||
char *owner;
|
||||
gulong user_uid;
|
||||
NMAuthSubject *subject;
|
||||
GError *error;
|
||||
|
||||
guint idle_id;
|
||||
|
|
@ -105,16 +107,16 @@ pk_authority_get (GError **error)
|
|||
#endif
|
||||
|
||||
static NMAuthChain *
|
||||
_auth_chain_new (DBusGMethodInvocation *context,
|
||||
DBusMessage *message,
|
||||
_auth_chain_new (NMAuthSubject *subject,
|
||||
const char *dbus_sender,
|
||||
gulong user_uid,
|
||||
DBusGMethodInvocation *context,
|
||||
NMAuthChainResultFunc done_func,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMAuthChain *self;
|
||||
|
||||
g_return_val_if_fail (message || dbus_sender, NULL);
|
||||
g_return_val_if_fail (subject || user_uid == 0 || dbus_sender, NULL);
|
||||
|
||||
self = g_malloc0 (sizeof (NMAuthChain));
|
||||
self->refcount = 1;
|
||||
|
|
@ -125,65 +127,73 @@ _auth_chain_new (DBusGMethodInvocation *context,
|
|||
self->done_func = done_func;
|
||||
self->user_data = user_data;
|
||||
self->context = context;
|
||||
self->user_uid = user_uid;
|
||||
|
||||
if (message)
|
||||
self->owner = g_strdup (dbus_message_get_sender (message));
|
||||
else if (dbus_sender)
|
||||
if (subject) {
|
||||
self->user_uid = nm_auth_subject_get_uid (subject);
|
||||
self->subject = g_object_ref (subject);
|
||||
} else {
|
||||
self->user_uid = user_uid;
|
||||
self->owner = g_strdup (dbus_sender);
|
||||
|
||||
if (user_uid > 0 && !self->owner) {
|
||||
/* Need an owner */
|
||||
g_warn_if_fail (self->owner);
|
||||
nm_auth_chain_unref (self);
|
||||
self = NULL;
|
||||
if (user_uid > 0 && !self->owner) {
|
||||
/* Need an owner */
|
||||
g_warn_if_fail (self->owner);
|
||||
nm_auth_chain_unref (self);
|
||||
self = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
NMAuthChain *
|
||||
nm_auth_chain_new (DBusGMethodInvocation *context,
|
||||
NMAuthChainResultFunc done_func,
|
||||
gpointer user_data,
|
||||
const char **out_error_desc)
|
||||
{
|
||||
gulong sender_uid = G_MAXULONG;
|
||||
char *sender = NULL;
|
||||
NMAuthChain *chain = NULL;
|
||||
|
||||
g_return_val_if_fail (context != NULL, NULL);
|
||||
|
||||
if (nm_dbus_manager_get_caller_info (nm_dbus_manager_get (),
|
||||
context,
|
||||
&sender,
|
||||
&sender_uid)) {
|
||||
chain = _auth_chain_new (context, NULL, sender, sender_uid, done_func, user_data);
|
||||
}
|
||||
|
||||
if (!chain && out_error_desc)
|
||||
*out_error_desc = "Unable to determine request UID and sender.";
|
||||
|
||||
g_free (sender);
|
||||
return chain;
|
||||
}
|
||||
|
||||
NMAuthChain *
|
||||
nm_auth_chain_new_raw_message (DBusMessage *message,
|
||||
gulong user_uid,
|
||||
NMAuthChainResultFunc done_func,
|
||||
gpointer user_data)
|
||||
{
|
||||
return _auth_chain_new (NULL, message, NULL, user_uid, done_func, user_data);
|
||||
}
|
||||
|
||||
NMAuthChain *
|
||||
nm_auth_chain_new_dbus_sender (const char *dbus_sender,
|
||||
gulong user_uid,
|
||||
NMAuthChainResultFunc done_func,
|
||||
gpointer user_data)
|
||||
{
|
||||
return _auth_chain_new (NULL, NULL, dbus_sender, user_uid, done_func, user_data);
|
||||
return _auth_chain_new (NULL, dbus_sender, user_uid, NULL, done_func, user_data);
|
||||
}
|
||||
|
||||
/* Creates the NMAuthSubject automatically */
|
||||
NMAuthChain *
|
||||
nm_auth_chain_new_context (DBusGMethodInvocation *context,
|
||||
NMAuthChainResultFunc done_func,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMAuthSubject *subject;
|
||||
NMAuthChain *chain;
|
||||
|
||||
g_return_val_if_fail (context != NULL, NULL);
|
||||
|
||||
subject = nm_auth_subject_new_from_context (context);
|
||||
if (!subject)
|
||||
return NULL;
|
||||
|
||||
chain = nm_auth_chain_new_subject (subject,
|
||||
context,
|
||||
done_func,
|
||||
user_data);
|
||||
g_object_unref (subject);
|
||||
return chain;
|
||||
}
|
||||
|
||||
/* Requires an NMAuthSubject */
|
||||
NMAuthChain *
|
||||
nm_auth_chain_new_subject (NMAuthSubject *subject,
|
||||
DBusGMethodInvocation *context,
|
||||
NMAuthChainResultFunc done_func,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMAuthChain *chain;
|
||||
|
||||
g_return_val_if_fail (NM_IS_AUTH_SUBJECT (subject), NULL);
|
||||
chain = _auth_chain_new (subject, NULL, G_MAXULONG, context, done_func, user_data);
|
||||
|
||||
/* Chains creation from a valid NMAuthSubject cannot fail since the
|
||||
* subject already has all the necessary auth info.
|
||||
*/
|
||||
g_assert (chain);
|
||||
return chain;
|
||||
}
|
||||
|
||||
gpointer
|
||||
|
|
@ -422,7 +432,7 @@ _add_call_polkit (NMAuthChain *self,
|
|||
AuthCall *call;
|
||||
|
||||
g_return_val_if_fail (self != NULL, FALSE);
|
||||
g_return_val_if_fail (self->owner != NULL, FALSE);
|
||||
g_return_val_if_fail (self->owner || self->subject, FALSE);
|
||||
g_return_val_if_fail (permission != NULL, FALSE);
|
||||
|
||||
call = auth_call_new (self, permission);
|
||||
|
|
@ -433,10 +443,16 @@ _add_call_polkit (NMAuthChain *self,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
subject = polkit_system_bus_name_new (self->owner);
|
||||
if (!subject) {
|
||||
auth_call_schedule_complete_with_error (call, "Failed to create polkit subject");
|
||||
return FALSE;
|
||||
if (self->subject) {
|
||||
subject = g_object_ref (nm_auth_subject_get_polkit_subject (self->subject));
|
||||
g_assert (subject);
|
||||
} else {
|
||||
g_assert (self->owner);
|
||||
subject = polkit_system_bus_name_new (self->owner);
|
||||
if (!subject) {
|
||||
auth_call_schedule_complete_with_error (call, "Failed to create polkit subject");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (allow_interaction)
|
||||
|
|
@ -496,6 +512,7 @@ nm_auth_chain_unref (NMAuthChain *self)
|
|||
g_object_unref (self->authority);
|
||||
#endif
|
||||
g_free (self->owner);
|
||||
g_object_unref (self->subject);
|
||||
|
||||
for (iter = self->calls; iter; iter = g_slist_next (iter))
|
||||
auth_call_cancel ((AuthCall *) iter->data);
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include <nm-connection.h>
|
||||
#include "nm-dbus-manager.h"
|
||||
#include "nm-session-monitor.h"
|
||||
#include "nm-auth-subject.h"
|
||||
|
||||
#define NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK "org.freedesktop.NetworkManager.enable-disable-network"
|
||||
#define NM_AUTH_PERMISSION_SLEEP_WAKE "org.freedesktop.NetworkManager.sleep-wake"
|
||||
|
|
@ -55,21 +56,20 @@ typedef void (*NMAuthChainResultFunc) (NMAuthChain *chain,
|
|||
DBusGMethodInvocation *context,
|
||||
gpointer user_data);
|
||||
|
||||
NMAuthChain *nm_auth_chain_new (DBusGMethodInvocation *context,
|
||||
NMAuthChainResultFunc done_func,
|
||||
gpointer user_data,
|
||||
const char **out_error_desc);
|
||||
|
||||
NMAuthChain *nm_auth_chain_new_raw_message (DBusMessage *message,
|
||||
gulong user_uid,
|
||||
NMAuthChainResultFunc done_func,
|
||||
gpointer user_data);
|
||||
|
||||
NMAuthChain *nm_auth_chain_new_dbus_sender (const char *dbus_sender,
|
||||
gulong user_uid,
|
||||
NMAuthChainResultFunc done_func,
|
||||
gpointer user_data);
|
||||
|
||||
NMAuthChain *nm_auth_chain_new_context (DBusGMethodInvocation *context,
|
||||
NMAuthChainResultFunc done_func,
|
||||
gpointer user_data);
|
||||
|
||||
NMAuthChain *nm_auth_chain_new_subject (NMAuthSubject *subject,
|
||||
DBusGMethodInvocation *context,
|
||||
NMAuthChainResultFunc done_func,
|
||||
gpointer user_data);
|
||||
|
||||
gpointer nm_auth_chain_get_data (NMAuthChain *chain, const char *tag);
|
||||
|
||||
gpointer nm_auth_chain_steal_data (NMAuthChain *chain, const char *tag);
|
||||
|
|
|
|||
1440
src/nm-manager.c
1440
src/nm-manager.c
File diff suppressed because it is too large
Load diff
|
|
@ -27,6 +27,7 @@
|
|||
#include <dbus/dbus-glib.h>
|
||||
#include "nm-device.h"
|
||||
#include "nm-settings.h"
|
||||
#include "nm-auth-subject.h"
|
||||
|
||||
#define NM_TYPE_MANAGER (nm_manager_get_type ())
|
||||
#define NM_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_MANAGER, NMManager))
|
||||
|
|
@ -116,8 +117,8 @@ NMDevice *nm_manager_get_device_by_ifindex (NMManager *manager,
|
|||
NMActiveConnection *nm_manager_activate_connection (NMManager *manager,
|
||||
NMConnection *connection,
|
||||
const char *specific_object,
|
||||
const char *device_path,
|
||||
const char *dbus_sender, /* NULL if automatic */
|
||||
NMDevice *device,
|
||||
NMAuthSubject *subject,
|
||||
GError **error);
|
||||
|
||||
gboolean nm_manager_deactivate_connection (NMManager *manager,
|
||||
|
|
|
|||
162
src/nm-policy.c
162
src/nm-policy.c
|
|
@ -669,7 +669,7 @@ update_ip4_routing (NMPolicy *policy, gboolean force_update)
|
|||
gw_addr = nm_ip4_config_get_gateway (ip4_config);
|
||||
|
||||
if (vpn) {
|
||||
NMDevice *parent = nm_vpn_connection_get_parent_device (vpn);
|
||||
NMDevice *parent = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (vpn));
|
||||
int parent_ifindex = nm_device_get_ip_ifindex (parent);
|
||||
NMIP4Config *parent_ip4 = nm_device_get_ip4_config (parent);
|
||||
guint32 parent_mss = parent_ip4 ? nm_ip4_config_get_mss (parent_ip4) : 0;
|
||||
|
|
@ -683,7 +683,7 @@ update_ip4_routing (NMPolicy *policy, gboolean force_update)
|
|||
}
|
||||
}
|
||||
|
||||
default_device = nm_vpn_connection_get_parent_device (vpn);
|
||||
default_device = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (vpn));
|
||||
} else {
|
||||
int mss = nm_ip4_config_get_mss (ip4_config);
|
||||
|
||||
|
|
@ -856,7 +856,7 @@ update_ip6_routing (NMPolicy *policy, gboolean force_update)
|
|||
gw_addr = &in6addr_any;
|
||||
|
||||
if (vpn) {
|
||||
NMDevice *parent = nm_vpn_connection_get_parent_device (vpn);
|
||||
NMDevice *parent = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (vpn));
|
||||
int parent_ifindex = nm_device_get_ip_ifindex (parent);
|
||||
NMIP6Config *parent_ip6 = nm_device_get_ip6_config (parent);
|
||||
guint32 parent_mss = parent_ip6 ? nm_ip6_config_get_mss (parent_ip6) : 0;
|
||||
|
|
@ -873,7 +873,7 @@ update_ip6_routing (NMPolicy *policy, gboolean force_update)
|
|||
}
|
||||
}
|
||||
|
||||
default_device6 = nm_vpn_connection_get_parent_device (vpn);
|
||||
default_device6 = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (vpn));
|
||||
} else {
|
||||
int mss = nm_ip6_config_get_mss (ip6_config);
|
||||
|
||||
|
|
@ -1034,14 +1034,16 @@ auto_activate_device (gpointer user_data)
|
|||
best_connection = nm_device_get_best_auto_connection (data->device, connections, &specific_object);
|
||||
if (best_connection) {
|
||||
GError *error = NULL;
|
||||
NMAuthSubject *subject;
|
||||
|
||||
nm_log_info (LOGD_DEVICE, "Auto-activating connection '%s'.",
|
||||
nm_connection_get_id (best_connection));
|
||||
subject = nm_auth_subject_new_internal ();
|
||||
if (!nm_manager_activate_connection (priv->manager,
|
||||
best_connection,
|
||||
specific_object,
|
||||
nm_device_get_path (data->device),
|
||||
NULL,
|
||||
data->device,
|
||||
subject,
|
||||
&error)) {
|
||||
nm_log_info (LOGD_DEVICE, "Connection '%s' auto-activation failed: (%d) %s",
|
||||
nm_connection_get_id (best_connection),
|
||||
|
|
@ -1049,6 +1051,7 @@ auto_activate_device (gpointer user_data)
|
|||
error ? error->message : "(none)");
|
||||
g_error_free (error);
|
||||
}
|
||||
g_object_unref (subject);
|
||||
}
|
||||
|
||||
g_slist_free (connections);
|
||||
|
|
@ -1110,7 +1113,7 @@ static void
|
|||
pending_secondary_data_free (PendingSecondaryData *data)
|
||||
{
|
||||
g_object_unref (data->device);
|
||||
g_slist_free_full (data->secondaries, g_free);
|
||||
g_slist_free_full (data->secondaries, g_object_unref);
|
||||
memset (data, 0, sizeof (*data));
|
||||
g_free (data);
|
||||
}
|
||||
|
|
@ -1121,51 +1124,47 @@ process_secondaries (NMPolicy *policy,
|
|||
gboolean connected)
|
||||
{
|
||||
NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy);
|
||||
NMDevice *device = NULL;
|
||||
const char *ac_path;
|
||||
GSList *iter, *iter2;
|
||||
|
||||
nm_log_dbg (LOGD_DEVICE, "Secondary connection '%s' %s; active path '%s'",
|
||||
nm_active_connection_get_name (active),
|
||||
connected ? "SUCCEEDED" : "FAILED",
|
||||
nm_active_connection_get_path (active));
|
||||
|
||||
ac_path = nm_active_connection_get_path (active);
|
||||
|
||||
if (NM_IS_VPN_CONNECTION (active))
|
||||
device = nm_vpn_connection_get_parent_device (NM_VPN_CONNECTION (active));
|
||||
|
||||
/* Loop through devices waiting for secondary connections to activate */
|
||||
for (iter = priv->pending_secondaries; iter; iter = g_slist_next (iter)) {
|
||||
PendingSecondaryData *secondary_data = (PendingSecondaryData *) iter->data;
|
||||
NMDevice *item_device = secondary_data->device;
|
||||
|
||||
if (!device || item_device == device) {
|
||||
for (iter2 = secondary_data->secondaries; iter2; iter2 = g_slist_next (iter2)) {
|
||||
char *list_ac_path = (char *) iter2->data;
|
||||
/* Look for 'active' in each device's secondary connections list */
|
||||
for (iter2 = secondary_data->secondaries; iter2; iter2 = g_slist_next (iter2)) {
|
||||
NMActiveConnection *secondary_active = NM_ACTIVE_CONNECTION (iter2->data);
|
||||
|
||||
if (g_strcmp0 (ac_path, list_ac_path) == 0) {
|
||||
if (connected) {
|
||||
/* Secondary connection activated */
|
||||
secondary_data->secondaries = g_slist_remove (secondary_data->secondaries, list_ac_path);
|
||||
g_free (list_ac_path);
|
||||
if (!secondary_data->secondaries) {
|
||||
/* None secondary UUID remained -> remove the secondary data item */
|
||||
priv->pending_secondaries = g_slist_remove (priv->pending_secondaries, secondary_data);
|
||||
pending_secondary_data_free (secondary_data);
|
||||
nm_device_state_changed (item_device, NM_DEVICE_STATE_ACTIVATED, NM_DEVICE_STATE_REASON_NONE);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
/* Secondary connection failed -> do not watch other connections */
|
||||
priv->pending_secondaries = g_slist_remove (priv->pending_secondaries, secondary_data);
|
||||
pending_secondary_data_free (secondary_data);
|
||||
nm_device_state_changed (item_device, NM_DEVICE_STATE_FAILED,
|
||||
NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED);
|
||||
return;
|
||||
}
|
||||
if (active != secondary_active)
|
||||
continue;
|
||||
|
||||
if (connected) {
|
||||
nm_log_dbg (LOGD_DEVICE, "Secondary connection '%s' SUCCEEDED; active path '%s'",
|
||||
nm_active_connection_get_name (active),
|
||||
nm_active_connection_get_path (active));
|
||||
|
||||
/* Secondary connection activated */
|
||||
secondary_data->secondaries = g_slist_remove (secondary_data->secondaries, secondary_active);
|
||||
g_object_unref (secondary_active);
|
||||
if (!secondary_data->secondaries) {
|
||||
/* No secondary UUID remained -> remove the secondary data item */
|
||||
priv->pending_secondaries = g_slist_remove (priv->pending_secondaries, secondary_data);
|
||||
pending_secondary_data_free (secondary_data);
|
||||
nm_device_state_changed (item_device, NM_DEVICE_STATE_ACTIVATED, NM_DEVICE_STATE_REASON_NONE);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
nm_log_dbg (LOGD_DEVICE, "Secondary connection '%s' FAILED; active path '%s'",
|
||||
nm_active_connection_get_name (active),
|
||||
nm_active_connection_get_path (active));
|
||||
|
||||
/* Secondary connection failed -> do not watch other connections */
|
||||
priv->pending_secondaries = g_slist_remove (priv->pending_secondaries, secondary_data);
|
||||
pending_secondary_data_free (secondary_data);
|
||||
nm_device_state_changed (item_device, NM_DEVICE_STATE_FAILED,
|
||||
NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1233,6 +1232,7 @@ schedule_activate_check (NMPolicy *policy, NMDevice *device, guint delay_seconds
|
|||
{
|
||||
NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy);
|
||||
ActivateData *data;
|
||||
const GSList *active_connections, *iter;
|
||||
|
||||
if (nm_manager_get_state (priv->manager) == NM_STATE_ASLEEP)
|
||||
return;
|
||||
|
|
@ -1246,6 +1246,15 @@ schedule_activate_check (NMPolicy *policy, NMDevice *device, guint delay_seconds
|
|||
if (!nm_device_autoconnect_allowed (device))
|
||||
return;
|
||||
|
||||
/* If the device already has an activation in-progress or waiting for
|
||||
* authentication, don't start an auto-activation for it.
|
||||
*/
|
||||
active_connections = nm_manager_get_active_connections (priv->manager);
|
||||
for (iter = active_connections; iter; iter = iter->next) {
|
||||
if (nm_active_connection_get_device (NM_ACTIVE_CONNECTION (iter->data)) == device)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Schedule an auto-activation if there isn't one already for this device */
|
||||
if (find_pending_activation (priv->pending_activation_checks, device) == NULL) {
|
||||
data = activate_data_new (policy, device, delay_seconds);
|
||||
|
|
@ -1357,13 +1366,12 @@ activate_secondary_connections (NMPolicy *policy,
|
|||
ac = nm_manager_activate_connection (priv->manager,
|
||||
NM_CONNECTION (settings_con),
|
||||
nm_active_connection_get_path (NM_ACTIVE_CONNECTION (req)),
|
||||
nm_device_get_path (device),
|
||||
nm_act_request_get_dbus_sender (req),
|
||||
device,
|
||||
nm_active_connection_get_subject (NM_ACTIVE_CONNECTION (req)),
|
||||
&error);
|
||||
if (ac) {
|
||||
secondary_ac_list = g_slist_append (secondary_ac_list,
|
||||
g_strdup (nm_active_connection_get_path (ac)));
|
||||
} else {
|
||||
if (ac)
|
||||
secondary_ac_list = g_slist_append (secondary_ac_list, g_object_ref (ac));
|
||||
else {
|
||||
nm_log_warn (LOGD_DEVICE, "Secondary connection '%s' auto-activation failed: (%d) %s",
|
||||
sec_uuid,
|
||||
error ? error->code : 0,
|
||||
|
|
@ -1384,7 +1392,7 @@ activate_secondary_connections (NMPolicy *policy,
|
|||
secondary_data = pending_secondary_data_new (device, secondary_ac_list);
|
||||
priv->pending_secondaries = g_slist_append (priv->pending_secondaries, secondary_data);
|
||||
} else
|
||||
g_slist_free_full (secondary_ac_list, g_free);
|
||||
g_slist_free_full (secondary_ac_list, g_object_unref);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
|
@ -1720,8 +1728,6 @@ vpn_connection_activated (NMPolicy *policy, NMVPNConnection *vpn)
|
|||
update_routing_and_dns (policy, TRUE);
|
||||
|
||||
nm_dns_manager_end_updates (mgr, __func__);
|
||||
|
||||
process_secondaries (policy, NM_ACTIVE_CONNECTION (vpn), TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1737,7 +1743,7 @@ vpn_connection_deactivated (NMPolicy *policy, NMVPNConnection *vpn)
|
|||
nm_dns_manager_begin_updates (mgr, __func__);
|
||||
|
||||
ip_iface = nm_vpn_connection_get_ip_iface (vpn);
|
||||
parent = nm_vpn_connection_get_parent_device (vpn);
|
||||
parent = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (vpn));
|
||||
|
||||
ip4_config = nm_vpn_connection_get_ip4_config (vpn);
|
||||
if (ip4_config) {
|
||||
|
|
@ -1754,8 +1760,23 @@ vpn_connection_deactivated (NMPolicy *policy, NMVPNConnection *vpn)
|
|||
update_routing_and_dns (policy, TRUE);
|
||||
|
||||
nm_dns_manager_end_updates (mgr, __func__);
|
||||
}
|
||||
|
||||
process_secondaries (policy, NM_ACTIVE_CONNECTION (vpn), FALSE);
|
||||
static void
|
||||
vpn_connection_state_changed (NMVPNConnection *vpn,
|
||||
NMVPNConnectionState new_state,
|
||||
NMVPNConnectionState old_state,
|
||||
NMVPNConnectionStateReason reason,
|
||||
NMPolicy *policy)
|
||||
{
|
||||
if (new_state == NM_VPN_CONNECTION_STATE_ACTIVATED)
|
||||
vpn_connection_activated (policy, vpn);
|
||||
else if (new_state >= NM_VPN_CONNECTION_STATE_FAILED) {
|
||||
/* Only clean up IP/DNS if the connection ever got past IP_CONFIG */
|
||||
if (old_state >= NM_VPN_CONNECTION_STATE_IP_CONFIG_GET &&
|
||||
old_state <= NM_VPN_CONNECTION_STATE_ACTIVATED)
|
||||
vpn_connection_deactivated (policy, vpn);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1763,18 +1784,12 @@ active_connection_state_changed (NMActiveConnection *active,
|
|||
GParamSpec *pspec,
|
||||
NMPolicy *policy)
|
||||
{
|
||||
switch (nm_active_connection_get_state (active)) {
|
||||
case NM_ACTIVE_CONNECTION_STATE_ACTIVATED:
|
||||
if (NM_IS_VPN_CONNECTION (active))
|
||||
vpn_connection_activated (policy, NM_VPN_CONNECTION (active));
|
||||
break;
|
||||
case NM_ACTIVE_CONNECTION_STATE_DEACTIVATED:
|
||||
if (NM_IS_VPN_CONNECTION (active))
|
||||
vpn_connection_deactivated (policy, NM_VPN_CONNECTION (active));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
NMActiveConnectionState state = nm_active_connection_get_state (active);
|
||||
|
||||
if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED)
|
||||
process_secondaries (policy, active, TRUE);
|
||||
else if (state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED)
|
||||
process_secondaries (policy, active, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1782,7 +1797,13 @@ active_connection_added (NMManager *manager,
|
|||
NMActiveConnection *active,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMPolicy *policy = (NMPolicy *) user_data;
|
||||
NMPolicy *policy = NM_POLICY (user_data);
|
||||
|
||||
if (NM_IS_VPN_CONNECTION (active)) {
|
||||
g_signal_connect (active, NM_VPN_CONNECTION_INTERNAL_STATE_CHANGED,
|
||||
G_CALLBACK (vpn_connection_state_changed),
|
||||
policy);
|
||||
}
|
||||
|
||||
g_signal_connect (active, "notify::" NM_ACTIVE_CONNECTION_STATE,
|
||||
G_CALLBACK (active_connection_state_changed),
|
||||
|
|
@ -1794,9 +1815,14 @@ active_connection_removed (NMManager *manager,
|
|||
NMActiveConnection *active,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMPolicy *policy = NM_POLICY (user_data);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (active,
|
||||
vpn_connection_state_changed,
|
||||
policy);
|
||||
g_signal_handlers_disconnect_by_func (active,
|
||||
active_connection_state_changed,
|
||||
(NMPolicy *) user_data);
|
||||
policy);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
|
|
|||
|
|
@ -206,6 +206,8 @@ agent_register_permissions_done (NMAuthChain *chain,
|
|||
GHashTableIter iter;
|
||||
Request *req;
|
||||
|
||||
g_assert (context);
|
||||
|
||||
priv->chains = g_slist_remove (priv->chains, chain);
|
||||
|
||||
if (error) {
|
||||
|
|
@ -270,22 +272,20 @@ impl_agent_manager_register_with_capabilities (NMAgentManager *self,
|
|||
DBusGMethodInvocation *context)
|
||||
{
|
||||
NMAgentManagerPrivate *priv = NM_AGENT_MANAGER_GET_PRIVATE (self);
|
||||
char *sender = NULL;
|
||||
NMAuthSubject *subject;
|
||||
gulong sender_uid = G_MAXULONG;
|
||||
GError *error = NULL, *local = NULL;
|
||||
NMSecretAgent *agent;
|
||||
NMAuthChain *chain;
|
||||
const char *error_desc = NULL;
|
||||
|
||||
if (!nm_dbus_manager_get_caller_info (priv->dbus_mgr,
|
||||
context,
|
||||
&sender,
|
||||
&sender_uid)) {
|
||||
subject = nm_auth_subject_new_from_context (context);
|
||||
if (!subject) {
|
||||
error = g_error_new_literal (NM_AGENT_MANAGER_ERROR,
|
||||
NM_AGENT_MANAGER_ERROR_SENDER_UNKNOWN,
|
||||
"Unable to determine request sender and UID.");
|
||||
goto done;
|
||||
}
|
||||
sender_uid = nm_auth_subject_get_uid (subject);
|
||||
|
||||
if ( 0 != sender_uid
|
||||
&& !nm_session_monitor_uid_has_session (priv->session_monitor,
|
||||
|
|
@ -311,7 +311,7 @@ impl_agent_manager_register_with_capabilities (NMAgentManager *self,
|
|||
}
|
||||
|
||||
/* Success, add the new agent */
|
||||
agent = nm_secret_agent_new (context, sender, identifier, sender_uid, capabilities);
|
||||
agent = nm_secret_agent_new (context, subject, identifier, capabilities);
|
||||
if (!agent) {
|
||||
error = g_error_new_literal (NM_AGENT_MANAGER_ERROR,
|
||||
NM_AGENT_MANAGER_ERROR_INTERNAL_ERROR,
|
||||
|
|
@ -323,7 +323,7 @@ impl_agent_manager_register_with_capabilities (NMAgentManager *self,
|
|||
nm_secret_agent_get_description (agent));
|
||||
|
||||
/* Kick off permissions requests for this agent */
|
||||
chain = nm_auth_chain_new (context, agent_register_permissions_done, self, &error_desc);
|
||||
chain = nm_auth_chain_new_subject (subject, context, agent_register_permissions_done, self);
|
||||
if (chain) {
|
||||
nm_auth_chain_set_data (chain, "agent", agent, g_object_unref);
|
||||
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED, FALSE);
|
||||
|
|
@ -333,7 +333,7 @@ impl_agent_manager_register_with_capabilities (NMAgentManager *self,
|
|||
} else {
|
||||
error = g_error_new_literal (NM_AGENT_MANAGER_ERROR,
|
||||
NM_AGENT_MANAGER_ERROR_SENDER_UNKNOWN,
|
||||
error_desc);
|
||||
"Unable to start agent authentication.");
|
||||
}
|
||||
|
||||
done:
|
||||
|
|
@ -341,7 +341,7 @@ done:
|
|||
dbus_g_method_return_error (context, error);
|
||||
g_clear_error (&error);
|
||||
g_clear_error (&local);
|
||||
g_free (sender);
|
||||
g_clear_object (&subject);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -363,6 +363,7 @@ impl_agent_manager_unregister (NMAgentManager *self,
|
|||
if (!nm_dbus_manager_get_caller_info (priv->dbus_mgr,
|
||||
context,
|
||||
&sender,
|
||||
NULL,
|
||||
NULL)) {
|
||||
error = g_error_new_literal (NM_AGENT_MANAGER_ERROR,
|
||||
NM_AGENT_MANAGER_ERROR_SENDER_UNKNOWN,
|
||||
|
|
@ -1016,10 +1017,10 @@ get_next_cb (Request *parent)
|
|||
nm_log_dbg (LOGD_AGENTS, "(%p/%s/%s) request has system secrets; checking agent %s for MODIFY",
|
||||
req, parent->detail, req->setting_name, agent_dbus_owner);
|
||||
|
||||
req->chain = nm_auth_chain_new_dbus_sender (agent_dbus_owner,
|
||||
nm_secret_agent_get_owner_uid (parent->current),
|
||||
get_agent_modify_auth_cb,
|
||||
req);
|
||||
req->chain = nm_auth_chain_new_subject (nm_secret_agent_get_subject (parent->current),
|
||||
NULL,
|
||||
get_agent_modify_auth_cb,
|
||||
req);
|
||||
g_assert (req->chain);
|
||||
|
||||
/* If the caller is the only user in the connection's permissions, then
|
||||
|
|
@ -1502,10 +1503,10 @@ authority_changed_cb (gpointer user_data)
|
|||
NMAuthChain *chain;
|
||||
|
||||
/* Kick off permissions requests for this agent */
|
||||
chain = nm_auth_chain_new_dbus_sender (nm_secret_agent_get_dbus_owner (agent),
|
||||
nm_secret_agent_get_owner_uid (agent),
|
||||
agent_permissions_changed_done,
|
||||
self);
|
||||
chain = nm_auth_chain_new_subject (nm_secret_agent_get_subject (agent),
|
||||
NULL,
|
||||
agent_permissions_changed_done,
|
||||
self);
|
||||
g_assert (chain);
|
||||
priv->chains = g_slist_append (priv->chains, chain);
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "nm-secret-agent.h"
|
||||
#include "nm-dbus-manager.h"
|
||||
#include "nm-dbus-glib-types.h"
|
||||
#include "nm-glib-compat.h"
|
||||
#include "nm-logging.h"
|
||||
|
||||
G_DEFINE_TYPE (NMSecretAgent, nm_secret_agent, G_TYPE_OBJECT)
|
||||
|
|
@ -40,12 +41,9 @@ G_DEFINE_TYPE (NMSecretAgent, nm_secret_agent, G_TYPE_OBJECT)
|
|||
NMSecretAgentPrivate))
|
||||
|
||||
typedef struct {
|
||||
gboolean disposed;
|
||||
|
||||
char *description;
|
||||
char *owner;
|
||||
NMAuthSubject *subject;
|
||||
char *identifier;
|
||||
uid_t owner_uid;
|
||||
char *owner_username;
|
||||
NMSecretAgentCapabilities capabilities;
|
||||
guint32 hash;
|
||||
|
|
@ -106,10 +104,10 @@ nm_secret_agent_get_description (NMSecretAgent *agent)
|
|||
|
||||
priv = NM_SECRET_AGENT_GET_PRIVATE (agent);
|
||||
if (!priv->description) {
|
||||
priv->description = g_strdup_printf ("%s/%s/%u",
|
||||
priv->owner,
|
||||
priv->description = g_strdup_printf ("%s/%s/%lu",
|
||||
nm_auth_subject_get_dbus_sender (priv->subject),
|
||||
priv->identifier,
|
||||
priv->owner_uid);
|
||||
nm_auth_subject_get_uid (priv->subject));
|
||||
}
|
||||
|
||||
return priv->description;
|
||||
|
|
@ -120,7 +118,7 @@ nm_secret_agent_get_dbus_owner (NMSecretAgent *agent)
|
|||
{
|
||||
g_return_val_if_fail (NM_IS_SECRET_AGENT (agent), NULL);
|
||||
|
||||
return NM_SECRET_AGENT_GET_PRIVATE (agent)->owner;
|
||||
return nm_auth_subject_get_dbus_sender (NM_SECRET_AGENT_GET_PRIVATE (agent)->subject);
|
||||
}
|
||||
|
||||
const char *
|
||||
|
|
@ -131,16 +129,16 @@ nm_secret_agent_get_identifier (NMSecretAgent *agent)
|
|||
return NM_SECRET_AGENT_GET_PRIVATE (agent)->identifier;
|
||||
}
|
||||
|
||||
uid_t
|
||||
gulong
|
||||
nm_secret_agent_get_owner_uid (NMSecretAgent *agent)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_SECRET_AGENT (agent), G_MAXUINT);
|
||||
g_return_val_if_fail (NM_IS_SECRET_AGENT (agent), G_MAXULONG);
|
||||
|
||||
return NM_SECRET_AGENT_GET_PRIVATE (agent)->owner_uid;
|
||||
return nm_auth_subject_get_uid (NM_SECRET_AGENT_GET_PRIVATE (agent)->subject);
|
||||
}
|
||||
|
||||
const char *
|
||||
nm_secret_agent_get_owner_username(NMSecretAgent *agent)
|
||||
nm_secret_agent_get_owner_username (NMSecretAgent *agent)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_SECRET_AGENT (agent), NULL);
|
||||
|
||||
|
|
@ -156,13 +154,21 @@ nm_secret_agent_get_capabilities (NMSecretAgent *agent)
|
|||
}
|
||||
|
||||
guint32
|
||||
nm_secret_agent_get_hash (NMSecretAgent *agent)
|
||||
nm_secret_agent_get_hash (NMSecretAgent *agent)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_SECRET_AGENT (agent), 0);
|
||||
|
||||
return NM_SECRET_AGENT_GET_PRIVATE (agent)->hash;
|
||||
}
|
||||
|
||||
NMAuthSubject *
|
||||
nm_secret_agent_get_subject (NMSecretAgent *agent)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_SECRET_AGENT (agent), NULL);
|
||||
|
||||
return NM_SECRET_AGENT_GET_PRIVATE (agent)->subject;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_secret_agent_add_permission:
|
||||
* @agent: A #NMSecretAgent.
|
||||
|
|
@ -443,9 +449,8 @@ proxy_cleanup (NMSecretAgent *self)
|
|||
|
||||
NMSecretAgent *
|
||||
nm_secret_agent_new (DBusGMethodInvocation *context,
|
||||
const char *owner,
|
||||
NMAuthSubject *subject,
|
||||
const char *identifier,
|
||||
uid_t owner_uid,
|
||||
NMSecretAgentCapabilities capabilities)
|
||||
{
|
||||
NMSecretAgent *self;
|
||||
|
|
@ -453,10 +458,11 @@ nm_secret_agent_new (DBusGMethodInvocation *context,
|
|||
char *hash_str, *username;
|
||||
struct passwd *pw;
|
||||
|
||||
g_return_val_if_fail (owner != NULL, NULL);
|
||||
g_return_val_if_fail (context != NULL, NULL);
|
||||
g_return_val_if_fail (NM_IS_AUTH_SUBJECT (subject), NULL);
|
||||
g_return_val_if_fail (identifier != NULL, NULL);
|
||||
|
||||
pw = getpwuid (owner_uid);
|
||||
pw = getpwuid (nm_auth_subject_get_uid (subject));
|
||||
g_return_val_if_fail (pw != NULL, NULL);
|
||||
g_return_val_if_fail (pw->pw_name[0] != '\0', NULL);
|
||||
username = g_strdup (pw->pw_name);
|
||||
|
|
@ -464,19 +470,18 @@ nm_secret_agent_new (DBusGMethodInvocation *context,
|
|||
self = (NMSecretAgent *) g_object_new (NM_TYPE_SECRET_AGENT, NULL);
|
||||
priv = NM_SECRET_AGENT_GET_PRIVATE (self);
|
||||
|
||||
priv->owner = g_strdup (owner);
|
||||
priv->identifier = g_strdup (identifier);
|
||||
priv->owner_uid = owner_uid;
|
||||
priv->owner_username = g_strdup (username);
|
||||
priv->capabilities = capabilities;
|
||||
priv->subject = g_object_ref (subject);
|
||||
|
||||
hash_str = g_strdup_printf ("%08u%s", owner_uid, identifier);
|
||||
hash_str = g_strdup_printf ("%16lu%s", nm_auth_subject_get_uid (subject), identifier);
|
||||
priv->hash = g_str_hash (hash_str);
|
||||
g_free (hash_str);
|
||||
|
||||
priv->proxy = nm_dbus_manager_new_proxy (nm_dbus_manager_get (),
|
||||
context,
|
||||
owner,
|
||||
nm_auth_subject_get_dbus_sender (subject),
|
||||
NM_DBUS_PATH_SECRET_AGENT,
|
||||
NM_DBUS_INTERFACE_SECRET_AGENT);
|
||||
g_assert (priv->proxy);
|
||||
|
|
@ -501,21 +506,21 @@ dispose (GObject *object)
|
|||
{
|
||||
NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (object);
|
||||
|
||||
if (!priv->disposed) {
|
||||
priv->disposed = TRUE;
|
||||
g_clear_pointer (&priv->description, g_free);
|
||||
g_clear_pointer (&priv->identifier, g_free);
|
||||
g_clear_pointer (&priv->owner_username, g_free);
|
||||
|
||||
g_free (priv->description);
|
||||
g_free (priv->owner);
|
||||
g_free (priv->identifier);
|
||||
g_free (priv->owner_username);
|
||||
|
||||
g_slist_free_full (priv->permissions, g_free);
|
||||
g_slist_free_full (priv->permissions, g_free);
|
||||
priv->permissions = NULL;
|
||||
|
||||
if (priv->requests) {
|
||||
g_hash_table_destroy (priv->requests);
|
||||
|
||||
proxy_cleanup (NM_SECRET_AGENT (object));
|
||||
priv->requests = NULL;
|
||||
}
|
||||
|
||||
proxy_cleanup (NM_SECRET_AGENT (object));
|
||||
g_clear_object (&priv->subject);
|
||||
|
||||
G_OBJECT_CLASS (nm_secret_agent_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include <nm-connection.h>
|
||||
#include "nm-dbus-manager.h"
|
||||
#include "nm-settings-flags.h"
|
||||
#include "nm-auth-subject.h"
|
||||
|
||||
/* NOTE: ensure these capabilities match those in introspection/nm-secret-agent.xml and
|
||||
* libnm-glib/nm-secret-agent.h.
|
||||
|
|
@ -56,9 +57,8 @@ typedef struct {
|
|||
GType nm_secret_agent_get_type (void);
|
||||
|
||||
NMSecretAgent *nm_secret_agent_new (DBusGMethodInvocation *context,
|
||||
const char *owner,
|
||||
NMAuthSubject *subject,
|
||||
const char *identifier,
|
||||
uid_t owner_uid,
|
||||
NMSecretAgentCapabilities capabilities);
|
||||
|
||||
const char *nm_secret_agent_get_description (NMSecretAgent *agent);
|
||||
|
|
@ -67,7 +67,7 @@ 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);
|
||||
gulong nm_secret_agent_get_owner_uid (NMSecretAgent *agent);
|
||||
|
||||
const char *nm_secret_agent_get_owner_username (NMSecretAgent *agent);
|
||||
|
||||
|
|
@ -75,6 +75,8 @@ NMSecretAgentCapabilities nm_secret_agent_get_capabilities (NMSecretAgent *agent
|
|||
|
||||
guint32 nm_secret_agent_get_hash (NMSecretAgent *agent);
|
||||
|
||||
NMAuthSubject *nm_secret_agent_get_subject (NMSecretAgent *agent);
|
||||
|
||||
void nm_secret_agent_add_permission (NMSecretAgent *agent,
|
||||
const char *permission,
|
||||
gboolean allowed);
|
||||
|
|
|
|||
|
|
@ -994,47 +994,35 @@ pk_auth_cb (NMAuthChain *chain,
|
|||
nm_auth_chain_unref (chain);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_user_in_acl (NMConnection *connection,
|
||||
DBusGMethodInvocation *context,
|
||||
NMSessionMonitor *session_monitor,
|
||||
gulong *out_sender_uid,
|
||||
GError **error)
|
||||
/**
|
||||
* _new_auth_subject:
|
||||
* @context: the D-Bus method invocation context
|
||||
* @error: on failure, a #GError
|
||||
*
|
||||
* Creates an NMAuthSubject for the caller.
|
||||
*
|
||||
* Returns: the #NMAuthSubject on success, or %NULL on failure and sets @error
|
||||
*/
|
||||
static NMAuthSubject *
|
||||
_new_auth_subject (DBusGMethodInvocation *context, GError **error)
|
||||
{
|
||||
gulong sender_uid = G_MAXULONG;
|
||||
char *error_desc = NULL;
|
||||
NMAuthSubject *subject;
|
||||
|
||||
g_return_val_if_fail (connection != NULL, FALSE);
|
||||
g_return_val_if_fail (context != NULL, FALSE);
|
||||
g_return_val_if_fail (session_monitor != NULL, FALSE);
|
||||
|
||||
/* Get the caller's UID */
|
||||
if (!nm_dbus_manager_get_caller_info (nm_dbus_manager_get (), context, NULL, &sender_uid)) {
|
||||
subject = nm_auth_subject_new_from_context (context);
|
||||
if (!subject) {
|
||||
g_set_error_literal (error,
|
||||
NM_SETTINGS_ERROR,
|
||||
NM_SETTINGS_ERROR_PERMISSION_DENIED,
|
||||
"Unable to determine UID of request.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Make sure the UID can view this connection */
|
||||
if (!nm_auth_uid_in_acl (connection, session_monitor, sender_uid, &error_desc)) {
|
||||
g_set_error_literal (error,
|
||||
NM_SETTINGS_ERROR,
|
||||
NM_SETTINGS_ERROR_PERMISSION_DENIED,
|
||||
error_desc);
|
||||
g_free (error_desc);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (out_sender_uid)
|
||||
*out_sender_uid = sender_uid;
|
||||
return TRUE;
|
||||
return subject;
|
||||
}
|
||||
|
||||
static void
|
||||
auth_start (NMSettingsConnection *self,
|
||||
DBusGMethodInvocation *context,
|
||||
NMAuthSubject *subject,
|
||||
const char *check_permission,
|
||||
AuthCallback callback,
|
||||
gpointer callback_data)
|
||||
|
|
@ -1043,41 +1031,49 @@ auth_start (NMSettingsConnection *self,
|
|||
NMAuthChain *chain;
|
||||
gulong sender_uid = G_MAXULONG;
|
||||
GError *error = NULL;
|
||||
const char *error_desc = NULL;
|
||||
char *error_desc = NULL;
|
||||
|
||||
g_return_if_fail (context != NULL);
|
||||
g_return_if_fail (NM_IS_AUTH_SUBJECT (subject));
|
||||
|
||||
/* Ensure the caller can view this connection */
|
||||
if (!nm_auth_uid_in_acl (NM_CONNECTION (self),
|
||||
priv->session_monitor,
|
||||
nm_auth_subject_get_uid (subject),
|
||||
&error_desc)) {
|
||||
error = g_error_new_literal (NM_SETTINGS_ERROR,
|
||||
NM_SETTINGS_ERROR_PERMISSION_DENIED,
|
||||
error_desc);
|
||||
g_free (error_desc);
|
||||
|
||||
if (!check_user_in_acl (NM_CONNECTION (self),
|
||||
context,
|
||||
priv->session_monitor,
|
||||
&sender_uid,
|
||||
&error)) {
|
||||
callback (self, context, G_MAXULONG, error, callback_data);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (check_permission) {
|
||||
chain = nm_auth_chain_new (context, pk_auth_cb, self, &error_desc);
|
||||
if (chain) {
|
||||
priv->pending_auths = g_slist_append (priv->pending_auths, chain);
|
||||
|
||||
nm_auth_chain_set_data (chain, "perm", (gpointer) check_permission, NULL);
|
||||
nm_auth_chain_set_data (chain, "callback", callback, NULL);
|
||||
nm_auth_chain_set_data (chain, "callback-data", callback_data, NULL);
|
||||
nm_auth_chain_set_data_ulong (chain, "sender-uid", sender_uid);
|
||||
|
||||
nm_auth_chain_add_call (chain, check_permission, TRUE);
|
||||
} else {
|
||||
g_set_error_literal (&error,
|
||||
NM_SETTINGS_ERROR,
|
||||
NM_SETTINGS_ERROR_PERMISSION_DENIED,
|
||||
error_desc);
|
||||
callback (self, context, G_MAXULONG, error, callback_data);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
} else {
|
||||
if (!check_permission) {
|
||||
/* Don't need polkit auth, automatic success */
|
||||
callback (self, context, sender_uid, NULL, callback_data);
|
||||
callback (self, context, nm_auth_subject_get_uid (subject), NULL, callback_data);
|
||||
return;
|
||||
}
|
||||
|
||||
chain = nm_auth_chain_new_subject (subject, context, pk_auth_cb, self);
|
||||
if (!chain) {
|
||||
g_set_error_literal (&error,
|
||||
NM_SETTINGS_ERROR,
|
||||
NM_SETTINGS_ERROR_PERMISSION_DENIED,
|
||||
"Unable to authenticate the request.");
|
||||
callback (self, context, G_MAXULONG, error, callback_data);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
priv->pending_auths = g_slist_append (priv->pending_auths, chain);
|
||||
nm_auth_chain_set_data (chain, "perm", (gpointer) check_permission, NULL);
|
||||
nm_auth_chain_set_data (chain, "callback", callback, NULL);
|
||||
nm_auth_chain_set_data (chain, "callback-data", callback_data, NULL);
|
||||
nm_auth_chain_set_data_ulong (chain, "sender-uid", sender_uid);
|
||||
nm_auth_chain_add_call (chain, check_permission, TRUE);
|
||||
}
|
||||
|
||||
/**** DBus method handlers ************************************/
|
||||
|
|
@ -1184,7 +1180,17 @@ static void
|
|||
impl_settings_connection_get_settings (NMSettingsConnection *self,
|
||||
DBusGMethodInvocation *context)
|
||||
{
|
||||
auth_start (self, context, NULL, get_settings_auth_cb, NULL);
|
||||
NMAuthSubject *subject;
|
||||
GError *error = NULL;
|
||||
|
||||
subject = _new_auth_subject (context, &error);
|
||||
if (subject) {
|
||||
auth_start (self, context, subject, NULL, get_settings_auth_cb, NULL);
|
||||
g_object_unref (subject);
|
||||
} else {
|
||||
dbus_g_method_return_error (context, error);
|
||||
g_error_free (error);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -1307,10 +1313,12 @@ impl_settings_connection_update_helper (NMSettingsConnection *self,
|
|||
gboolean save_to_disk)
|
||||
{
|
||||
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
|
||||
NMAuthSubject *subject = NULL;
|
||||
NMConnection *tmp = NULL;
|
||||
GError *error = NULL;
|
||||
UpdateInfo *info;
|
||||
const char *permission;
|
||||
char *error_desc = NULL;
|
||||
|
||||
g_assert (new_settings != NULL || save_to_disk == TRUE);
|
||||
|
||||
|
|
@ -1318,36 +1326,35 @@ impl_settings_connection_update_helper (NMSettingsConnection *self,
|
|||
* the problem (ex a system settings plugin that can't write connections out)
|
||||
* instead of over D-Bus.
|
||||
*/
|
||||
if (!check_writable (NM_CONNECTION (self), &error)) {
|
||||
dbus_g_method_return_error (context, error);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
if (!check_writable (NM_CONNECTION (self), &error))
|
||||
goto error;
|
||||
|
||||
/* Check if the settings are valid first */
|
||||
if (new_settings) {
|
||||
tmp = nm_connection_new_from_hash (new_settings, &error);
|
||||
if (!tmp) {
|
||||
g_assert (error);
|
||||
dbus_g_method_return_error (context, error);
|
||||
g_error_free (error);
|
||||
return;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
subject = _new_auth_subject (context, &error);
|
||||
if (!subject)
|
||||
goto error;
|
||||
|
||||
/* And that the new connection settings will be visible to the user
|
||||
* that's sending the update request. You can't make a connection
|
||||
* invisible to yourself.
|
||||
*/
|
||||
if (!check_user_in_acl (tmp ? tmp : NM_CONNECTION (self),
|
||||
context,
|
||||
priv->session_monitor,
|
||||
NULL,
|
||||
&error)) {
|
||||
dbus_g_method_return_error (context, error);
|
||||
g_clear_error (&error);
|
||||
g_object_unref (tmp);
|
||||
return;
|
||||
if (!nm_auth_uid_in_acl (tmp ? tmp : NM_CONNECTION (self),
|
||||
priv->session_monitor,
|
||||
nm_auth_subject_get_uid (subject),
|
||||
&error_desc)) {
|
||||
error = g_error_new_literal (NM_SETTINGS_ERROR,
|
||||
NM_SETTINGS_ERROR_PERMISSION_DENIED,
|
||||
error_desc);
|
||||
g_free (error_desc);
|
||||
goto error;
|
||||
}
|
||||
|
||||
info = g_malloc0 (sizeof (*info));
|
||||
|
|
@ -1359,7 +1366,16 @@ impl_settings_connection_update_helper (NMSettingsConnection *self,
|
|||
|
||||
permission = get_update_modify_permission (NM_CONNECTION (self),
|
||||
tmp ? tmp : NM_CONNECTION (self));
|
||||
auth_start (self, context, permission, update_auth_cb, info);
|
||||
auth_start (self, context, subject, permission, update_auth_cb, info);
|
||||
g_object_unref (subject);
|
||||
return;
|
||||
|
||||
error:
|
||||
g_clear_object (&tmp);
|
||||
g_clear_object (&subject);
|
||||
|
||||
dbus_g_method_return_error (context, error);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1440,6 +1456,7 @@ static void
|
|||
impl_settings_connection_delete (NMSettingsConnection *self,
|
||||
DBusGMethodInvocation *context)
|
||||
{
|
||||
NMAuthSubject *subject;
|
||||
GError *error = NULL;
|
||||
|
||||
if (!check_writable (NM_CONNECTION (self), &error)) {
|
||||
|
|
@ -1448,7 +1465,14 @@ impl_settings_connection_delete (NMSettingsConnection *self,
|
|||
return;
|
||||
}
|
||||
|
||||
auth_start (self, context, get_modify_permission_basic (self), delete_auth_cb, NULL);
|
||||
subject = _new_auth_subject (context, &error);
|
||||
if (subject) {
|
||||
auth_start (self, context, subject, get_modify_permission_basic (self), delete_auth_cb, NULL);
|
||||
g_object_unref (subject);
|
||||
} else {
|
||||
dbus_g_method_return_error (context, error);
|
||||
g_error_free (error);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************/
|
||||
|
|
@ -1524,11 +1548,22 @@ impl_settings_connection_get_secrets (NMSettingsConnection *self,
|
|||
const gchar *setting_name,
|
||||
DBusGMethodInvocation *context)
|
||||
{
|
||||
auth_start (self,
|
||||
context,
|
||||
get_modify_permission_basic (self),
|
||||
dbus_secrets_auth_cb,
|
||||
g_strdup (setting_name));
|
||||
NMAuthSubject *subject;
|
||||
GError *error = NULL;
|
||||
|
||||
subject = _new_auth_subject (context, &error);
|
||||
if (subject) {
|
||||
auth_start (self,
|
||||
context,
|
||||
subject,
|
||||
get_modify_permission_basic (self),
|
||||
dbus_secrets_auth_cb,
|
||||
g_strdup (setting_name));
|
||||
g_object_unref (subject);
|
||||
} else {
|
||||
dbus_g_method_return_error (context, error);
|
||||
g_error_free (error);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************/
|
||||
|
|
|
|||
|
|
@ -1013,6 +1013,8 @@ pk_add_cb (NMAuthChain *chain,
|
|||
const char *perm;
|
||||
gboolean save_to_disk;
|
||||
|
||||
g_assert (context);
|
||||
|
||||
priv->auths = g_slist_remove (priv->auths, chain);
|
||||
|
||||
perm = nm_auth_chain_get_data (chain, "perm");
|
||||
|
|
@ -1092,13 +1094,15 @@ nm_settings_add_connection_dbus (NMSettings *self,
|
|||
{
|
||||
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
|
||||
NMSettingConnection *s_con;
|
||||
NMAuthSubject *subject = NULL;
|
||||
NMAuthChain *chain;
|
||||
GError *error = NULL, *tmp_error = NULL;
|
||||
gulong caller_uid = G_MAXULONG;
|
||||
char *error_desc = NULL;
|
||||
const char *auth_error_desc = NULL;
|
||||
const char *perm;
|
||||
|
||||
g_return_if_fail (connection != NULL);
|
||||
g_return_if_fail (context != NULL);
|
||||
|
||||
/* Connection must be valid, of course */
|
||||
if (!nm_connection_verify (connection, &tmp_error)) {
|
||||
error = g_error_new (NM_SETTINGS_ERROR,
|
||||
|
|
@ -1106,9 +1110,7 @@ nm_settings_add_connection_dbus (NMSettings *self,
|
|||
"The connection was invalid: %s",
|
||||
tmp_error ? tmp_error->message : "(unknown)");
|
||||
g_error_free (tmp_error);
|
||||
callback (self, NULL, error, context, user_data);
|
||||
g_error_free (error);
|
||||
return;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* The kernel doesn't support Ad-Hoc WPA connections well at this time,
|
||||
|
|
@ -1119,9 +1121,7 @@ nm_settings_add_connection_dbus (NMSettings *self,
|
|||
error = g_error_new_literal (NM_SETTINGS_ERROR,
|
||||
NM_SETTINGS_ERROR_INVALID_CONNECTION,
|
||||
"WPA Ad-Hoc disabled due to kernel bugs");
|
||||
callback (self, NULL, error, context, user_data);
|
||||
g_error_free (error);
|
||||
return;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Do any of the plugins support adding? */
|
||||
|
|
@ -1129,32 +1129,29 @@ nm_settings_add_connection_dbus (NMSettings *self,
|
|||
error = g_error_new_literal (NM_SETTINGS_ERROR,
|
||||
NM_SETTINGS_ERROR_ADD_NOT_SUPPORTED,
|
||||
"None of the registered plugins support add.");
|
||||
callback (self, NULL, error, context, user_data);
|
||||
g_error_free (error);
|
||||
return;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Get the caller's UID */
|
||||
if (!nm_dbus_manager_get_caller_info (priv->dbus_mgr, context, NULL, &caller_uid)) {
|
||||
subject = nm_auth_subject_new_from_context (context);
|
||||
if (!subject) {
|
||||
error = g_error_new_literal (NM_SETTINGS_ERROR,
|
||||
NM_SETTINGS_ERROR_PERMISSION_DENIED,
|
||||
"Unable to determine request UID.");
|
||||
callback (self, NULL, error, context, user_data);
|
||||
g_error_free (error);
|
||||
return;
|
||||
"Unable to determine UID of request.");
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Ensure the caller's username exists in the connection's permissions,
|
||||
* or that the permissions is empty (ie, visible by everyone).
|
||||
*/
|
||||
if (!nm_auth_uid_in_acl (connection, priv->session_monitor, caller_uid, &error_desc)) {
|
||||
if (!nm_auth_uid_in_acl (connection,
|
||||
priv->session_monitor,
|
||||
nm_auth_subject_get_uid (subject),
|
||||
&error_desc)) {
|
||||
error = g_error_new_literal (NM_SETTINGS_ERROR,
|
||||
NM_SETTINGS_ERROR_PERMISSION_DENIED,
|
||||
error_desc);
|
||||
g_free (error_desc);
|
||||
callback (self, NULL, error, context, user_data);
|
||||
g_error_free (error);
|
||||
return;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* If the caller is the only user in the connection's permissions, then
|
||||
|
|
@ -1169,23 +1166,29 @@ nm_settings_add_connection_dbus (NMSettings *self,
|
|||
perm = NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM;
|
||||
|
||||
/* Validate the user request */
|
||||
chain = nm_auth_chain_new (context, pk_add_cb, self, &auth_error_desc);
|
||||
if (chain) {
|
||||
priv->auths = g_slist_append (priv->auths, chain);
|
||||
nm_auth_chain_add_call (chain, perm, TRUE);
|
||||
nm_auth_chain_set_data (chain, "perm", (gpointer) perm, NULL);
|
||||
nm_auth_chain_set_data (chain, "connection", g_object_ref (connection), g_object_unref);
|
||||
nm_auth_chain_set_data (chain, "callback", callback, NULL);
|
||||
nm_auth_chain_set_data (chain, "callback-data", user_data, NULL);
|
||||
nm_auth_chain_set_data_ulong (chain, "caller-uid", caller_uid);
|
||||
nm_auth_chain_set_data (chain, "save-to-disk", GUINT_TO_POINTER (save_to_disk), NULL);
|
||||
} else {
|
||||
chain = nm_auth_chain_new_subject (subject, context, pk_add_cb, self);
|
||||
if (!chain) {
|
||||
error = g_error_new_literal (NM_SETTINGS_ERROR,
|
||||
NM_SETTINGS_ERROR_PERMISSION_DENIED,
|
||||
auth_error_desc);
|
||||
callback (self, NULL, error, context, user_data);
|
||||
g_error_free (error);
|
||||
"Unable to authenticate the request.");
|
||||
goto done;
|
||||
}
|
||||
|
||||
priv->auths = g_slist_append (priv->auths, chain);
|
||||
nm_auth_chain_add_call (chain, perm, TRUE);
|
||||
nm_auth_chain_set_data (chain, "perm", (gpointer) perm, NULL);
|
||||
nm_auth_chain_set_data (chain, "connection", g_object_ref (connection), g_object_unref);
|
||||
nm_auth_chain_set_data (chain, "callback", callback, NULL);
|
||||
nm_auth_chain_set_data (chain, "callback-data", user_data, NULL);
|
||||
nm_auth_chain_set_data_ulong (chain, "caller-uid", nm_auth_subject_get_uid (subject));
|
||||
nm_auth_chain_set_data (chain, "save-to-disk", GUINT_TO_POINTER (save_to_disk), NULL);
|
||||
|
||||
done:
|
||||
if (error)
|
||||
callback (self, NULL, error, context, user_data);
|
||||
|
||||
g_clear_error (&error);
|
||||
g_clear_object (&subject);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1251,7 +1254,7 @@ impl_settings_reload_connections (NMSettings *self,
|
|||
gulong caller_uid;
|
||||
GError *error = NULL;
|
||||
|
||||
if (!nm_dbus_manager_get_caller_info (priv->dbus_mgr, context, NULL, &caller_uid)) {
|
||||
if (!nm_dbus_manager_get_caller_info (priv->dbus_mgr, context, NULL, &caller_uid, NULL)) {
|
||||
error = g_error_new_literal (NM_SETTINGS_ERROR,
|
||||
NM_SETTINGS_ERROR_PERMISSION_DENIED,
|
||||
"Unable to determine request UID.");
|
||||
|
|
@ -1294,6 +1297,8 @@ pk_hostname_cb (NMAuthChain *chain,
|
|||
GSList *iter;
|
||||
const char *hostname;
|
||||
|
||||
g_assert (context);
|
||||
|
||||
priv->auths = g_slist_remove (priv->auths, chain);
|
||||
|
||||
result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME);
|
||||
|
|
@ -1344,30 +1349,31 @@ impl_settings_save_hostname (NMSettings *self,
|
|||
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
|
||||
NMAuthChain *chain;
|
||||
GError *error = NULL;
|
||||
const char *error_desc = NULL;
|
||||
|
||||
/* Do any of the plugins support setting the hostname? */
|
||||
if (!get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME)) {
|
||||
error = g_error_new_literal (NM_SETTINGS_ERROR,
|
||||
NM_SETTINGS_ERROR_SAVE_HOSTNAME_NOT_SUPPORTED,
|
||||
"None of the registered plugins support setting the hostname.");
|
||||
} else {
|
||||
chain = nm_auth_chain_new (context, pk_hostname_cb, self, &error_desc);
|
||||
if (chain) {
|
||||
priv->auths = g_slist_append (priv->auths, chain);
|
||||
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME, TRUE);
|
||||
nm_auth_chain_set_data (chain, "hostname", g_strdup (hostname), g_free);
|
||||
} else {
|
||||
error = g_error_new_literal (NM_SETTINGS_ERROR,
|
||||
NM_SETTINGS_ERROR_PERMISSION_DENIED,
|
||||
error_desc);
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
dbus_g_method_return_error (context, error);
|
||||
g_error_free (error);
|
||||
chain = nm_auth_chain_new_context (context, pk_hostname_cb, self);
|
||||
if (!chain) {
|
||||
error = g_error_new_literal (NM_SETTINGS_ERROR,
|
||||
NM_SETTINGS_ERROR_PERMISSION_DENIED,
|
||||
"Unable to authenticate the request.");
|
||||
goto done;
|
||||
}
|
||||
|
||||
priv->auths = g_slist_append (priv->auths, chain);
|
||||
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME, TRUE);
|
||||
nm_auth_chain_set_data (chain, "hostname", g_strdup (hostname), g_free);
|
||||
|
||||
done:
|
||||
if (error)
|
||||
dbus_g_method_return_error (context, error);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
|
|||
|
|
@ -71,9 +71,6 @@ typedef struct {
|
|||
SecretsReq secrets_idx;
|
||||
char *username;
|
||||
|
||||
NMDevice *parent_dev;
|
||||
gulong device_monitor;
|
||||
|
||||
NMVPNConnectionState vpn_state;
|
||||
NMVPNConnectionStateReason failure_reason;
|
||||
DBusGProxy *proxy;
|
||||
|
|
@ -163,7 +160,7 @@ call_plugin_disconnect (NMVPNConnection *self)
|
|||
}
|
||||
|
||||
static void
|
||||
vpn_cleanup (NMVPNConnection *connection)
|
||||
vpn_cleanup (NMVPNConnection *connection, NMDevice *parent_dev)
|
||||
{
|
||||
NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection);
|
||||
|
||||
|
|
@ -173,8 +170,8 @@ vpn_cleanup (NMVPNConnection *connection)
|
|||
nm_platform_address_flush (priv->ip_ifindex);
|
||||
}
|
||||
|
||||
nm_device_set_vpn4_config (priv->parent_dev, NULL);
|
||||
nm_device_set_vpn6_config (priv->parent_dev, NULL);
|
||||
nm_device_set_vpn4_config (parent_dev, NULL);
|
||||
nm_device_set_vpn6_config (parent_dev, NULL);
|
||||
|
||||
g_free (priv->banner);
|
||||
priv->banner = NULL;
|
||||
|
|
@ -197,6 +194,7 @@ nm_vpn_connection_set_vpn_state (NMVPNConnection *connection,
|
|||
{
|
||||
NMVPNConnectionPrivate *priv;
|
||||
NMVPNConnectionState old_vpn_state;
|
||||
NMDevice *parent_dev = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (connection));
|
||||
|
||||
g_return_if_fail (NM_IS_VPN_CONNECTION (connection));
|
||||
|
||||
|
|
@ -242,7 +240,7 @@ nm_vpn_connection_set_vpn_state (NMVPNConnection *connection,
|
|||
/* Let dispatcher scripts know we're up and running */
|
||||
nm_dispatcher_call_vpn (DISPATCHER_ACTION_VPN_UP,
|
||||
priv->connection,
|
||||
priv->parent_dev,
|
||||
parent_dev,
|
||||
priv->ip_iface,
|
||||
priv->ip4_config,
|
||||
priv->ip6_config,
|
||||
|
|
@ -255,7 +253,7 @@ nm_vpn_connection_set_vpn_state (NMVPNConnection *connection,
|
|||
/* Let dispatcher scripts know we're about to go down */
|
||||
nm_dispatcher_call_vpn (DISPATCHER_ACTION_VPN_DOWN,
|
||||
priv->connection,
|
||||
priv->parent_dev,
|
||||
parent_dev,
|
||||
priv->ip_iface,
|
||||
NULL,
|
||||
NULL,
|
||||
|
|
@ -265,7 +263,7 @@ nm_vpn_connection_set_vpn_state (NMVPNConnection *connection,
|
|||
|
||||
/* Tear down and clean up the connection */
|
||||
call_plugin_disconnect (connection);
|
||||
vpn_cleanup (connection);
|
||||
vpn_cleanup (connection, parent_dev);
|
||||
/* Fall through */
|
||||
default:
|
||||
priv->secrets_idx = SECRETS_REQ_SYSTEM;
|
||||
|
|
@ -276,25 +274,33 @@ nm_vpn_connection_set_vpn_state (NMVPNConnection *connection,
|
|||
}
|
||||
|
||||
static void
|
||||
device_state_changed (NMDevice *device,
|
||||
device_state_changed (NMActiveConnection *active,
|
||||
NMDevice *device,
|
||||
NMDeviceState new_state,
|
||||
NMDeviceState old_state,
|
||||
NMDeviceStateReason reason,
|
||||
gpointer user_data)
|
||||
NMDeviceState old_state)
|
||||
{
|
||||
NMVPNConnection *connection = NM_VPN_CONNECTION (user_data);
|
||||
|
||||
if (new_state <= NM_DEVICE_STATE_DISCONNECTED) {
|
||||
nm_vpn_connection_set_vpn_state (connection,
|
||||
nm_vpn_connection_set_vpn_state (NM_VPN_CONNECTION (active),
|
||||
NM_VPN_CONNECTION_STATE_DISCONNECTED,
|
||||
NM_VPN_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED);
|
||||
} else if (new_state == NM_DEVICE_STATE_FAILED) {
|
||||
nm_vpn_connection_set_vpn_state (connection,
|
||||
nm_vpn_connection_set_vpn_state (NM_VPN_CONNECTION (active),
|
||||
NM_VPN_CONNECTION_STATE_FAILED,
|
||||
NM_VPN_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
master_failed (NMActiveConnection *self)
|
||||
{
|
||||
NMVPNConnection *connection = NM_VPN_CONNECTION (self);
|
||||
|
||||
/* Master failure fails the VPN */
|
||||
nm_vpn_connection_set_vpn_state (connection,
|
||||
NM_VPN_CONNECTION_STATE_FAILED,
|
||||
NM_VPN_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED);
|
||||
}
|
||||
|
||||
static void
|
||||
add_ip4_vpn_gateway_route (NMDevice *parent_device, guint32 vpn_gw)
|
||||
{
|
||||
|
|
@ -400,26 +406,18 @@ NMVPNConnection *
|
|||
nm_vpn_connection_new (NMConnection *connection,
|
||||
NMDevice *parent_device,
|
||||
const char *specific_object,
|
||||
gboolean user_requested,
|
||||
gulong user_uid)
|
||||
NMAuthSubject *subject)
|
||||
{
|
||||
NMVPNConnection *self;
|
||||
|
||||
g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
|
||||
g_return_val_if_fail (NM_IS_DEVICE (parent_device), NULL);
|
||||
|
||||
self = (NMVPNConnection *) g_object_new (NM_TYPE_VPN_CONNECTION,
|
||||
return (NMVPNConnection *) g_object_new (NM_TYPE_VPN_CONNECTION,
|
||||
NM_ACTIVE_CONNECTION_INT_CONNECTION, connection,
|
||||
NM_ACTIVE_CONNECTION_INT_DEVICE, parent_device,
|
||||
NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT, specific_object,
|
||||
NM_ACTIVE_CONNECTION_INT_USER_REQUESTED, user_requested,
|
||||
NM_ACTIVE_CONNECTION_INT_USER_UID, user_uid,
|
||||
NM_ACTIVE_CONNECTION_INT_SUBJECT, subject,
|
||||
NM_ACTIVE_CONNECTION_VPN, TRUE,
|
||||
NULL);
|
||||
if (self)
|
||||
nm_active_connection_export (NM_ACTIVE_CONNECTION (self));
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static const char *
|
||||
|
|
@ -652,6 +650,7 @@ static gboolean
|
|||
nm_vpn_connection_apply_config (NMVPNConnection *connection)
|
||||
{
|
||||
NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection);
|
||||
NMDevice *parent_dev = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (connection));
|
||||
|
||||
nm_platform_link_set_up (priv->ip_ifindex);
|
||||
|
||||
|
|
@ -668,9 +667,9 @@ nm_vpn_connection_apply_config (NMVPNConnection *connection)
|
|||
|
||||
/* Add any explicit route to the VPN gateway through the parent device */
|
||||
if (priv->ip4_external_gw)
|
||||
add_ip4_vpn_gateway_route (priv->parent_dev, priv->ip4_external_gw);
|
||||
add_ip4_vpn_gateway_route (parent_dev, priv->ip4_external_gw);
|
||||
if (priv->ip6_external_gw)
|
||||
add_ip6_vpn_gateway_route (priv->parent_dev, priv->ip6_external_gw);
|
||||
add_ip6_vpn_gateway_route (parent_dev, priv->ip6_external_gw);
|
||||
|
||||
nm_log_info (LOGD_VPN, "VPN connection '%s' (IP Config Get) complete.",
|
||||
nm_connection_get_id (priv->connection));
|
||||
|
|
@ -1397,14 +1396,6 @@ nm_vpn_connection_get_ip_ifindex (NMVPNConnection *connection)
|
|||
return NM_VPN_CONNECTION_GET_PRIVATE (connection)->ip_ifindex;
|
||||
}
|
||||
|
||||
NMDevice *
|
||||
nm_vpn_connection_get_parent_device (NMVPNConnection *connection)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_VPN_CONNECTION (connection), NULL);
|
||||
|
||||
return NM_VPN_CONNECTION_GET_PRIVATE (connection)->parent_dev;
|
||||
}
|
||||
|
||||
guint32
|
||||
nm_vpn_connection_get_ip4_internal_gateway (NMVPNConnection *connection)
|
||||
{
|
||||
|
|
@ -1674,23 +1665,12 @@ nm_vpn_connection_init (NMVPNConnection *self)
|
|||
static void
|
||||
constructed (GObject *object)
|
||||
{
|
||||
NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (object);
|
||||
NMConnection *connection;
|
||||
NMDevice *device;
|
||||
|
||||
G_OBJECT_CLASS (nm_vpn_connection_parent_class)->constructed (object);
|
||||
|
||||
connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (object));
|
||||
priv->connection = g_object_ref (connection);
|
||||
|
||||
device = (NMDevice *) nm_active_connection_get_device (NM_ACTIVE_CONNECTION (object));
|
||||
g_assert (device);
|
||||
|
||||
priv->parent_dev = g_object_ref (device);
|
||||
|
||||
priv->device_monitor = g_signal_connect (device, "state-changed",
|
||||
G_CALLBACK (device_state_changed),
|
||||
object);
|
||||
NM_VPN_CONNECTION_GET_PRIVATE (object)->connection = g_object_ref (connection);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1712,11 +1692,6 @@ dispose (GObject *object)
|
|||
if (priv->ip6_external_gw)
|
||||
g_free (priv->ip6_external_gw);
|
||||
|
||||
if (priv->device_monitor)
|
||||
g_signal_handler_disconnect (priv->parent_dev, priv->device_monitor);
|
||||
|
||||
g_clear_object (&priv->parent_dev);
|
||||
|
||||
if (priv->ip4_config)
|
||||
g_object_unref (priv->ip4_config);
|
||||
if (priv->ip6_config)
|
||||
|
|
@ -1755,6 +1730,7 @@ get_property (GObject *object, guint prop_id,
|
|||
GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (object);
|
||||
NMDevice *parent_dev;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_VPN_STATE:
|
||||
|
|
@ -1764,7 +1740,8 @@ get_property (GObject *object, guint prop_id,
|
|||
g_value_set_string (value, priv->banner ? priv->banner : "");
|
||||
break;
|
||||
case PROP_MASTER:
|
||||
g_value_set_boxed (value, nm_device_get_path (priv->parent_dev));
|
||||
parent_dev = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (object));
|
||||
g_value_set_boxed (value, parent_dev ? nm_device_get_path (parent_dev) : "/");
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
|
|
@ -1776,6 +1753,7 @@ static void
|
|||
nm_vpn_connection_class_init (NMVPNConnectionClass *connection_class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (connection_class);
|
||||
NMActiveConnectionClass *active_class = NM_ACTIVE_CONNECTION_CLASS (connection_class);
|
||||
|
||||
g_type_class_add_private (connection_class, sizeof (NMVPNConnectionPrivate));
|
||||
|
||||
|
|
@ -1784,6 +1762,8 @@ nm_vpn_connection_class_init (NMVPNConnectionClass *connection_class)
|
|||
object_class->constructed = constructed;
|
||||
object_class->dispose = dispose;
|
||||
object_class->finalize = finalize;
|
||||
active_class->master_failed = master_failed;
|
||||
active_class->device_state_changed = device_state_changed;
|
||||
|
||||
g_object_class_override_property (object_class, PROP_MASTER, NM_ACTIVE_CONNECTION_MASTER);
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include <glib-object.h>
|
||||
#include "NetworkManagerVPN.h"
|
||||
#include "nm-device.h"
|
||||
#include "nm-auth-subject.h"
|
||||
|
||||
#define NM_TYPE_VPN_CONNECTION (nm_vpn_connection_get_type ())
|
||||
#define NM_VPN_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VPN_CONNECTION, NMVPNConnection))
|
||||
|
|
@ -67,8 +68,7 @@ GType nm_vpn_connection_get_type (void);
|
|||
NMVPNConnection * nm_vpn_connection_new (NMConnection *connection,
|
||||
NMDevice *parent_device,
|
||||
const char *specific_object,
|
||||
gboolean user_requested,
|
||||
gulong user_uid);
|
||||
NMAuthSubject *subject);
|
||||
|
||||
void nm_vpn_connection_activate (NMVPNConnection *connection);
|
||||
NMConnection * nm_vpn_connection_get_connection (NMVPNConnection *connection);
|
||||
|
|
@ -82,7 +82,6 @@ NMIP4Config * nm_vpn_connection_get_ip4_config (NMVPNConnection *connect
|
|||
NMIP6Config * nm_vpn_connection_get_ip6_config (NMVPNConnection *connection);
|
||||
const char * nm_vpn_connection_get_ip_iface (NMVPNConnection *connection);
|
||||
int nm_vpn_connection_get_ip_ifindex (NMVPNConnection *connection);
|
||||
NMDevice * nm_vpn_connection_get_parent_device (NMVPNConnection *connection);
|
||||
guint32 nm_vpn_connection_get_ip4_internal_gateway (NMVPNConnection *connection);
|
||||
struct in6_addr * nm_vpn_connection_get_ip6_internal_gateway (NMVPNConnection *connection);
|
||||
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ get_service_by_namefile (NMVPNManager *self, const char *namefile)
|
|||
}
|
||||
|
||||
static NMVPNConnection *
|
||||
find_active_vpn_connection_by_connection (NMVPNManager *self, NMConnection *connection)
|
||||
find_active_vpn_connection (NMVPNManager *self, NMConnection *connection)
|
||||
{
|
||||
NMVPNManagerPrivate *priv = NM_VPN_MANAGER_GET_PRIVATE (self);
|
||||
GHashTableIter iter;
|
||||
|
|
@ -104,66 +104,53 @@ find_active_vpn_connection_by_connection (NMVPNManager *self, NMConnection *conn
|
|||
return found;
|
||||
}
|
||||
|
||||
NMActiveConnection *
|
||||
gboolean
|
||||
nm_vpn_manager_activate_connection (NMVPNManager *manager,
|
||||
NMConnection *connection,
|
||||
NMDevice *device,
|
||||
const char *specific_object,
|
||||
gboolean user_requested,
|
||||
gulong user_uid,
|
||||
NMVPNConnection *vpn,
|
||||
GError **error)
|
||||
{
|
||||
NMSettingVPN *vpn_setting;
|
||||
NMVPNConnection *existing = NULL;
|
||||
NMConnection *connection;
|
||||
NMSettingVPN *s_vpn;
|
||||
NMVPNService *service;
|
||||
NMVPNConnection *vpn = NULL;
|
||||
const char *service_name;
|
||||
NMDevice *device;
|
||||
|
||||
g_return_val_if_fail (NM_IS_VPN_MANAGER (manager), NULL);
|
||||
g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
|
||||
g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
|
||||
g_return_val_if_fail (error != NULL, NULL);
|
||||
g_return_val_if_fail (*error == NULL, NULL);
|
||||
g_return_val_if_fail (NM_IS_VPN_MANAGER (manager), FALSE);
|
||||
g_return_val_if_fail (NM_IS_VPN_CONNECTION (vpn), FALSE);
|
||||
g_return_val_if_fail (error != NULL, FALSE);
|
||||
g_return_val_if_fail (*error == NULL, FALSE);
|
||||
|
||||
device = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (vpn));
|
||||
g_assert (device);
|
||||
if ( nm_device_get_state (device) != NM_DEVICE_STATE_ACTIVATED
|
||||
&& nm_device_get_state (device) != NM_DEVICE_STATE_SECONDARIES) {
|
||||
g_set_error (error,
|
||||
NM_VPN_MANAGER_ERROR, NM_VPN_MANAGER_ERROR_DEVICE_NOT_ACTIVE,
|
||||
"%s", "The base device for the VPN connection was not active.");
|
||||
return NULL;
|
||||
g_set_error_literal (error, NM_VPN_MANAGER_ERROR, NM_VPN_MANAGER_ERROR_DEVICE_NOT_ACTIVE,
|
||||
"The base device for the VPN connection was not active.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
vpn_setting = nm_connection_get_setting_vpn (connection);
|
||||
if (!vpn_setting) {
|
||||
g_set_error (error,
|
||||
NM_VPN_MANAGER_ERROR, NM_VPN_MANAGER_ERROR_CONNECTION_INVALID,
|
||||
"%s", "The connection was not a VPN connection.");
|
||||
return NULL;
|
||||
}
|
||||
connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (vpn));
|
||||
g_assert (connection);
|
||||
s_vpn = nm_connection_get_setting_vpn (connection);
|
||||
g_assert (s_vpn);
|
||||
|
||||
vpn = find_active_vpn_connection_by_connection (manager, connection);
|
||||
if (vpn) {
|
||||
nm_vpn_connection_disconnect (vpn, NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED);
|
||||
vpn = NULL;
|
||||
}
|
||||
|
||||
service_name = nm_setting_vpn_get_service_type (vpn_setting);
|
||||
service_name = nm_setting_vpn_get_service_type (s_vpn);
|
||||
g_assert (service_name);
|
||||
service = g_hash_table_lookup (NM_VPN_MANAGER_GET_PRIVATE (manager)->services, service_name);
|
||||
if (!service) {
|
||||
g_set_error (error,
|
||||
NM_VPN_MANAGER_ERROR, NM_VPN_MANAGER_ERROR_SERVICE_INVALID,
|
||||
g_set_error (error, NM_VPN_MANAGER_ERROR, NM_VPN_MANAGER_ERROR_SERVICE_INVALID,
|
||||
"The VPN service '%s' was not installed.",
|
||||
service_name);
|
||||
return NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return (NMActiveConnection *) nm_vpn_service_activate (service,
|
||||
connection,
|
||||
device,
|
||||
specific_object,
|
||||
user_requested,
|
||||
user_uid,
|
||||
error);
|
||||
existing = find_active_vpn_connection (manager,
|
||||
nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (vpn)));
|
||||
if (existing)
|
||||
nm_vpn_connection_disconnect (vpn, NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED);
|
||||
|
||||
return nm_vpn_service_activate (service, vpn, error);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
|
|
|||
|
|
@ -59,13 +59,9 @@ GType nm_vpn_manager_get_type (void);
|
|||
|
||||
NMVPNManager *nm_vpn_manager_get (void);
|
||||
|
||||
NMActiveConnection *nm_vpn_manager_activate_connection (NMVPNManager *manager,
|
||||
NMConnection *connection,
|
||||
NMDevice *device,
|
||||
const char *specific_object,
|
||||
gboolean user_requested,
|
||||
gulong user_uid,
|
||||
GError **error);
|
||||
gboolean nm_vpn_manager_activate_connection (NMVPNManager *manager,
|
||||
NMVPNConnection *vpn,
|
||||
GError **error);
|
||||
|
||||
gboolean nm_vpn_manager_deactivate_connection (NMVPNManager *manager,
|
||||
NMVPNConnection *connection,
|
||||
|
|
|
|||
|
|
@ -323,45 +323,37 @@ connection_vpn_state_changed (NMVPNConnection *connection,
|
|||
}
|
||||
}
|
||||
|
||||
NMVPNConnection *
|
||||
gboolean
|
||||
nm_vpn_service_activate (NMVPNService *service,
|
||||
NMConnection *connection,
|
||||
NMDevice *device,
|
||||
const char *specific_object,
|
||||
gboolean user_requested,
|
||||
gulong user_uid,
|
||||
NMVPNConnection *vpn,
|
||||
GError **error)
|
||||
{
|
||||
NMVPNConnection *vpn;
|
||||
NMVPNServicePrivate *priv;
|
||||
|
||||
g_return_val_if_fail (NM_IS_VPN_SERVICE (service), NULL);
|
||||
g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
|
||||
g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
|
||||
g_return_val_if_fail (error != NULL, NULL);
|
||||
g_return_val_if_fail (*error == NULL, NULL);
|
||||
g_return_val_if_fail (NM_IS_VPN_SERVICE (service), FALSE);
|
||||
g_return_val_if_fail (NM_IS_VPN_CONNECTION (vpn), FALSE);
|
||||
g_return_val_if_fail (error != NULL, FALSE);
|
||||
g_return_val_if_fail (*error == NULL, FALSE);
|
||||
|
||||
priv = NM_VPN_SERVICE_GET_PRIVATE (service);
|
||||
|
||||
clear_quit_timeout (service);
|
||||
|
||||
vpn = nm_vpn_connection_new (connection, device, specific_object, user_requested, user_uid);
|
||||
g_signal_connect (vpn, NM_VPN_CONNECTION_INTERNAL_STATE_CHANGED,
|
||||
G_CALLBACK (connection_vpn_state_changed),
|
||||
service);
|
||||
|
||||
priv->connections = g_slist_prepend (priv->connections, g_object_ref (vpn));
|
||||
|
||||
if (nm_dbus_manager_name_has_owner (priv->dbus_mgr, priv->dbus_service)) {
|
||||
// FIXME: fill in error when errors happen
|
||||
if (nm_dbus_manager_name_has_owner (priv->dbus_mgr, priv->dbus_service))
|
||||
nm_vpn_connection_activate (vpn);
|
||||
} else if (priv->start_timeout == 0) {
|
||||
else if (priv->start_timeout == 0) {
|
||||
nm_log_info (LOGD_VPN, "Starting VPN service '%s'...", priv->name);
|
||||
if (!nm_vpn_service_daemon_exec (service, error))
|
||||
vpn = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return vpn;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
const GSList *
|
||||
|
|
|
|||
|
|
@ -54,13 +54,9 @@ const char *nm_vpn_service_get_dbus_service (NMVPNService *service);
|
|||
/* Returns the path of the VPN service's .name file */
|
||||
const char *nm_vpn_service_get_name_file (NMVPNService *service);
|
||||
|
||||
NMVPNConnection * nm_vpn_service_activate (NMVPNService *service,
|
||||
NMConnection *connection,
|
||||
NMDevice *device,
|
||||
const char *specific_object,
|
||||
gboolean user_requested,
|
||||
gulong user_uid,
|
||||
GError **error);
|
||||
gboolean nm_vpn_service_activate (NMVPNService *service,
|
||||
NMVPNConnection *vpn,
|
||||
GError **error);
|
||||
|
||||
const GSList *nm_vpn_service_get_active_connections (NMVPNService *service);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue