mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-27 21:00:10 +01:00
core: merge branch 'th/settings-cleanup'
https://github.com/NetworkManager/NetworkManager/pull/85
This commit is contained in:
commit
f69dbd71fe
28 changed files with 1247 additions and 969 deletions
|
|
@ -214,9 +214,6 @@
|
|||
/* Define if you have oFono support (experimental) */
|
||||
#mesondefine WITH_OFONO
|
||||
|
||||
/* whether to compile polkit support */
|
||||
#mesondefine WITH_POLKIT
|
||||
|
||||
/* Define if you have polkit agent */
|
||||
#mesondefine WITH_POLKIT_AGENT
|
||||
|
||||
|
|
|
|||
26
configure.ac
26
configure.ac
|
|
@ -629,26 +629,20 @@ AM_CONDITIONAL(WITH_JSON_VALIDATION, test "${enable_json_validation}" != "no")
|
|||
|
||||
# we usually compile with polkit support. --enable-polkit=yes|no only sets the
|
||||
# default configuration for main.auth-polkit. User can always enable/disable polkit
|
||||
# autorization via config. Only when specifying --enable-polkit=disabled, we do
|
||||
# not compile support. In this case, the user cannot enable polkit authorization via
|
||||
# configuration.
|
||||
# autorization via config.
|
||||
AC_ARG_ENABLE(polkit,
|
||||
AS_HELP_STRING([--enable-polkit=yes|no|disabled],
|
||||
[set default value for auth-polkit configuration option. This value can be overwritten by NM configuration. 'disabled' compiles NM without any support]),
|
||||
AS_HELP_STRING([--enable-polkit=yes|no],
|
||||
[set default value for auth-polkit configuration option. This value can be overwritten by NM configuration. 'disabled' is an alias for 'no']),
|
||||
[enable_polkit=${enableval}], [enable_polkit=yes])
|
||||
if (test "${enable_polkit}" != "no" -a "${enable_polkit}" != "disabled"); then
|
||||
enable_polkit=yes
|
||||
enable_polkit=true
|
||||
AC_DEFINE(NM_CONFIG_DEFAULT_MAIN_AUTH_POLKIT, "true", [The default value of the auth-polkit configuration option])
|
||||
AC_SUBST(NM_CONFIG_DEFAULT_MAIN_AUTH_POLKIT_TEXT, true)
|
||||
else
|
||||
enable_polkit=false
|
||||
AC_DEFINE(NM_CONFIG_DEFAULT_MAIN_AUTH_POLKIT, "false", [The default value of the auth-polkit configuration option])
|
||||
AC_SUBST(NM_CONFIG_DEFAULT_MAIN_AUTH_POLKIT_TEXT, false)
|
||||
fi
|
||||
if (test "${enable_polkit}" != "disabled"); then
|
||||
AC_DEFINE(WITH_POLKIT, 1, [whether to compile polkit support])
|
||||
else
|
||||
AC_DEFINE(WITH_POLKIT, 0, [whether to compile polkit support])
|
||||
fi
|
||||
|
||||
PKG_CHECK_MODULES(POLKIT, [polkit-agent-1 >= 0.97], [have_pk_agent=yes],[have_pk_agent=no])
|
||||
AC_ARG_ENABLE(polkit-agent,
|
||||
|
|
@ -1341,14 +1335,10 @@ echo
|
|||
echo "Platform:"
|
||||
echo " session tracking: $session_tracking"
|
||||
echo " suspend/resume: $with_suspend_resume"
|
||||
if test "${enable_polkit}" = "yes"; then
|
||||
if test "${enable_modify_system}" = "yes"; then
|
||||
echo " policykit: yes (permissive modify.system) (default: main.auth-polkit=${enable_polkit})"
|
||||
else
|
||||
echo " policykit: yes (restrictive modify.system) (default: main.auth-polkit=${enable_polkit})"
|
||||
fi
|
||||
if test "${enable_modify_system}" = "yes"; then
|
||||
echo " policykit: main.auth-polkit=${enable_polkit} (permissive modify.system)"
|
||||
else
|
||||
echo " policykit: no"
|
||||
echo " policykit: main.auth-polkit=${enable_polkit} (restrictive modify.system)"
|
||||
fi
|
||||
echo " polkit agent: ${enable_polkit_agent}"
|
||||
echo " selinux: $have_selinux"
|
||||
|
|
|
|||
|
|
@ -113,11 +113,16 @@ NMConnection *
|
|||
nm_simple_connection_new_clone (NMConnection *connection)
|
||||
{
|
||||
NMConnection *clone;
|
||||
const char *path;
|
||||
|
||||
g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
|
||||
|
||||
clone = nm_simple_connection_new ();
|
||||
nm_connection_set_path (clone, nm_connection_get_path (connection));
|
||||
|
||||
path = nm_connection_get_path (connection);
|
||||
if (path)
|
||||
nm_connection_set_path (clone, path);
|
||||
|
||||
nm_connection_replace_settings_from_connection (clone, connection);
|
||||
|
||||
return clone;
|
||||
|
|
|
|||
|
|
@ -448,7 +448,6 @@ endif
|
|||
|
||||
config_default_main_auth_polkit = (polkit == 'yes').to_string()
|
||||
config_h.set_quoted('NM_CONFIG_DEFAULT_MAIN_AUTH_POLKIT', config_default_main_auth_polkit)
|
||||
config_h.set10('WITH_POLKIT', enable_polkit)
|
||||
|
||||
enable_modify_system = get_option('modify_system')
|
||||
|
||||
|
|
|
|||
|
|
@ -256,7 +256,7 @@ typedef struct _NMDevicePrivate {
|
|||
GSList *pending_actions;
|
||||
GSList *dad6_failed_addrs;
|
||||
|
||||
NMDevice *parent_device;
|
||||
NMDBusTrackObjPath parent_device;
|
||||
|
||||
char * udi;
|
||||
char * iface; /* may change, could be renamed by user */
|
||||
|
|
@ -321,9 +321,7 @@ typedef struct _NMDevicePrivate {
|
|||
|
||||
NMActRequest * queued_act_request;
|
||||
bool queued_act_request_is_waiting_for_carrier:1;
|
||||
bool act_request_public:1;
|
||||
NMActRequest *act_request;
|
||||
gulong act_request_id;
|
||||
NMDBusTrackObjPath act_request;
|
||||
ActivationHandleData act_handle4; /* for layer2 and IPv4. */
|
||||
ActivationHandleData act_handle6;
|
||||
guint recheck_assume_id;
|
||||
|
|
@ -1514,12 +1512,9 @@ nm_device_parent_get_ifindex (NMDevice *self)
|
|||
NMDevice *
|
||||
nm_device_parent_get_device (NMDevice *self)
|
||||
{
|
||||
NMDevicePrivate *priv;
|
||||
|
||||
g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
|
||||
|
||||
priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
return priv->parent_device;
|
||||
return NM_DEVICE_GET_PRIVATE (self)->parent_device.obj;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1541,7 +1536,7 @@ _parent_set_ifindex (NMDevice *self,
|
|||
NMDevice *parent_device;
|
||||
gboolean changed = FALSE;
|
||||
int old_ifindex;
|
||||
NMDevice *old_device;
|
||||
gs_unref_object NMDevice *old_device = NULL;
|
||||
|
||||
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
||||
|
||||
|
|
@ -1551,16 +1546,15 @@ _parent_set_ifindex (NMDevice *self,
|
|||
parent_ifindex = 0;
|
||||
|
||||
old_ifindex = priv->parent_ifindex;
|
||||
old_device = priv->parent_device;
|
||||
|
||||
if (priv->parent_ifindex == parent_ifindex) {
|
||||
if (parent_ifindex > 0) {
|
||||
if ( !force_check
|
||||
&& priv->parent_device
|
||||
&& nm_device_get_ifindex (priv->parent_device) == parent_ifindex)
|
||||
&& priv->parent_device.obj
|
||||
&& nm_device_get_ifindex (priv->parent_device.obj) == parent_ifindex)
|
||||
return FALSE;
|
||||
} else {
|
||||
if (!priv->parent_device)
|
||||
if (!priv->parent_device.obj)
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -1575,24 +1569,23 @@ _parent_set_ifindex (NMDevice *self,
|
|||
} else
|
||||
parent_device = NULL;
|
||||
|
||||
if (parent_device != priv->parent_device) {
|
||||
priv->parent_device = parent_device;
|
||||
if (parent_device != priv->parent_device.obj) {
|
||||
old_device = nm_g_object_ref (priv->parent_device.obj);
|
||||
nm_dbus_track_obj_path_set (&priv->parent_device, parent_device, TRUE);
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
if (priv->parent_ifindex <= 0)
|
||||
_LOGD (LOGD_DEVICE, "parent: clear");
|
||||
else if (!priv->parent_device)
|
||||
else if (!priv->parent_device.obj)
|
||||
_LOGD (LOGD_DEVICE, "parent: ifindex %d, no device", priv->parent_ifindex);
|
||||
else {
|
||||
_LOGD (LOGD_DEVICE, "parent: ifindex %d, device %p, %s", priv->parent_ifindex,
|
||||
priv->parent_device, nm_device_get_iface (priv->parent_device));
|
||||
priv->parent_device.obj, nm_device_get_iface (priv->parent_device.obj));
|
||||
}
|
||||
|
||||
NM_DEVICE_GET_CLASS (self)->parent_changed_notify (self, old_ifindex, old_device, priv->parent_ifindex, priv->parent_device);
|
||||
|
||||
_notify (self, PROP_PARENT);
|
||||
NM_DEVICE_GET_CLASS (self)->parent_changed_notify (self, old_ifindex, old_device, priv->parent_ifindex, priv->parent_device.obj);
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
|
@ -1617,7 +1610,7 @@ nm_device_parent_notify_changed (NMDevice *self,
|
|||
priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
if (priv->parent_ifindex > 0) {
|
||||
if ( priv->parent_device == change_candidate
|
||||
if ( priv->parent_device.obj == change_candidate
|
||||
|| priv->parent_ifindex == nm_device_get_ifindex (change_candidate))
|
||||
return _parent_set_ifindex (self, priv->parent_ifindex, device_removed);
|
||||
}
|
||||
|
|
@ -2164,7 +2157,7 @@ nm_device_get_act_request (NMDevice *self)
|
|||
{
|
||||
g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
|
||||
|
||||
return NM_DEVICE_GET_PRIVATE (self)->act_request;
|
||||
return NM_DEVICE_GET_PRIVATE (self)->act_request.obj;
|
||||
}
|
||||
|
||||
NMSettingsConnection *
|
||||
|
|
@ -2172,7 +2165,7 @@ nm_device_get_settings_connection (NMDevice *self)
|
|||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
return priv->act_request ? nm_act_request_get_settings_connection (priv->act_request) : NULL;
|
||||
return priv->act_request.obj ? nm_act_request_get_settings_connection (priv->act_request.obj) : NULL;
|
||||
}
|
||||
|
||||
NMConnection *
|
||||
|
|
@ -2184,7 +2177,7 @@ nm_device_get_applied_connection (NMDevice *self)
|
|||
|
||||
priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
return priv->act_request ? nm_act_request_get_applied_connection (priv->act_request) : NULL;
|
||||
return priv->act_request.obj ? nm_act_request_get_applied_connection (priv->act_request.obj) : NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
|
@ -2192,10 +2185,10 @@ nm_device_has_unmodified_applied_connection (NMDevice *self, NMSettingCompareFla
|
|||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
if (!priv->act_request)
|
||||
if (!priv->act_request.obj)
|
||||
return FALSE;
|
||||
|
||||
return nm_active_connection_has_unmodified_applied_connection ((NMActiveConnection *) priv->act_request, compare_flags);
|
||||
return nm_active_connection_has_unmodified_applied_connection ((NMActiveConnection *) priv->act_request.obj, compare_flags);
|
||||
}
|
||||
|
||||
NMSetting *
|
||||
|
|
@ -4533,7 +4526,7 @@ check_ip_state (NMDevice *self, gboolean may_fail, gboolean full_state_update)
|
|||
|
||||
/* Don't progress into IP_CHECK or SECONDARIES if we're waiting for the
|
||||
* master to enslave us. */
|
||||
if ( nm_active_connection_get_master (NM_ACTIVE_CONNECTION (priv->act_request))
|
||||
if ( nm_active_connection_get_master (NM_ACTIVE_CONNECTION (priv->act_request.obj))
|
||||
&& !priv->is_enslaved)
|
||||
return;
|
||||
|
||||
|
|
@ -5726,8 +5719,9 @@ activate_stage1_device_prepare (NMDevice *self)
|
|||
_set_ip_state (self, AF_INET6, IP_NONE);
|
||||
|
||||
/* Notify the new ActiveConnection along with the state change */
|
||||
priv->act_request_public = TRUE;
|
||||
_notify (self, PROP_ACTIVE_CONNECTION);
|
||||
nm_dbus_track_obj_path_set (&priv->act_request,
|
||||
priv->act_request.obj,
|
||||
TRUE);
|
||||
|
||||
nm_device_state_changed (self, NM_DEVICE_STATE_PREPARE, NM_DEVICE_STATE_REASON_NONE);
|
||||
|
||||
|
|
@ -5763,7 +5757,7 @@ nm_device_activate_schedule_stage1_device_prepare (NMDevice *self)
|
|||
g_return_if_fail (NM_IS_DEVICE (self));
|
||||
|
||||
priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
g_return_if_fail (priv->act_request);
|
||||
g_return_if_fail (priv->act_request.obj);
|
||||
|
||||
activation_source_schedule (self, activate_stage1_device_prepare, AF_INET);
|
||||
}
|
||||
|
|
@ -5940,7 +5934,7 @@ activate_stage2_device_config (NMDevice *self)
|
|||
|
||||
if (slave_state == NM_DEVICE_STATE_IP_CONFIG)
|
||||
nm_device_master_enslave_slave (self, info->slave, nm_device_get_applied_connection (info->slave));
|
||||
else if ( priv->act_request
|
||||
else if ( priv->act_request.obj
|
||||
&& nm_device_sys_iface_state_is_external (self)
|
||||
&& slave_state <= NM_DEVICE_STATE_DISCONNECTED)
|
||||
nm_device_queue_recheck_assume (info->slave);
|
||||
|
|
@ -5965,10 +5959,10 @@ nm_device_activate_schedule_stage2_device_config (NMDevice *self)
|
|||
g_return_if_fail (NM_IS_DEVICE (self));
|
||||
|
||||
priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
g_return_if_fail (priv->act_request);
|
||||
g_return_if_fail (priv->act_request.obj);
|
||||
|
||||
if (!priv->master_ready_handled) {
|
||||
NMActiveConnection *active = NM_ACTIVE_CONNECTION (priv->act_request);
|
||||
NMActiveConnection *active = NM_ACTIVE_CONNECTION (priv->act_request.obj);
|
||||
NMActiveConnection *master;
|
||||
|
||||
master = nm_active_connection_get_master (active);
|
||||
|
|
@ -6256,10 +6250,10 @@ nm_device_handle_ipv4ll_event (sd_ipv4ll *ll, int event, void *data)
|
|||
NMIP4Config *config;
|
||||
int r;
|
||||
|
||||
if (priv->act_request == NULL)
|
||||
if (priv->act_request.obj == NULL)
|
||||
return;
|
||||
|
||||
connection = nm_act_request_get_applied_connection (priv->act_request);
|
||||
connection = nm_act_request_get_applied_connection (priv->act_request.obj);
|
||||
g_assert (connection);
|
||||
|
||||
/* Ignore if the connection isn't an AutoIP connection */
|
||||
|
|
@ -8179,7 +8173,7 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in
|
|||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
guint i;
|
||||
|
||||
g_return_if_fail (priv->act_request);
|
||||
g_return_if_fail (priv->act_request.obj);
|
||||
|
||||
if (!applied_config_get_current (&priv->ac_ip6_config))
|
||||
applied_config_init_new (&priv->ac_ip6_config, self, AF_INET6);
|
||||
|
|
@ -8991,7 +8985,7 @@ nm_device_activate_schedule_stage3_ip_config_start (NMDevice *self)
|
|||
g_return_if_fail (NM_IS_DEVICE (self));
|
||||
|
||||
priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
g_return_if_fail (priv->act_request);
|
||||
g_return_if_fail (priv->act_request.obj);
|
||||
|
||||
/* Add the interface to the specified firewall zone */
|
||||
if (priv->fw_state == FIREWALL_STATE_UNMANAGED) {
|
||||
|
|
@ -9063,7 +9057,7 @@ nm_device_activate_schedule_ip4_config_timeout (NMDevice *self)
|
|||
g_return_if_fail (NM_IS_DEVICE (self));
|
||||
|
||||
priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
g_return_if_fail (priv->act_request);
|
||||
g_return_if_fail (priv->act_request.obj);
|
||||
|
||||
activation_source_schedule (self, activate_stage4_ip4_config_timeout, AF_INET);
|
||||
}
|
||||
|
|
@ -9119,7 +9113,7 @@ nm_device_activate_schedule_ip6_config_timeout (NMDevice *self)
|
|||
g_return_if_fail (NM_IS_DEVICE (self));
|
||||
|
||||
priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
g_return_if_fail (priv->act_request);
|
||||
g_return_if_fail (priv->act_request.obj);
|
||||
|
||||
activation_source_schedule (self, activate_stage4_ip6_config_timeout, AF_INET6);
|
||||
}
|
||||
|
|
@ -9576,44 +9570,27 @@ nm_device_activate_ip6_state_done (NMDevice *self)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
act_request_set_cb (NMActRequest *act_request,
|
||||
GParamSpec *pspec,
|
||||
NMDevice *self)
|
||||
{
|
||||
_notify (self, PROP_ACTIVE_CONNECTION);
|
||||
}
|
||||
|
||||
static void
|
||||
act_request_set (NMDevice *self, NMActRequest *act_request)
|
||||
{
|
||||
NMDevicePrivate *priv;
|
||||
gs_unref_object NMActRequest *old_act_requst = NULL;
|
||||
|
||||
nm_assert (NM_IS_DEVICE (self));
|
||||
nm_assert (!act_request || NM_IS_ACT_REQUEST (act_request));
|
||||
|
||||
priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
if ( !priv->act_request_public
|
||||
&& priv->act_request == act_request)
|
||||
if ( !priv->act_request.visible
|
||||
&& priv->act_request.obj == act_request)
|
||||
return;
|
||||
|
||||
/* always clear the public flag. The few callers that set a new @act_request
|
||||
* don't want that the property is public yet. */
|
||||
priv->act_request_public = FALSE;
|
||||
|
||||
nm_clear_g_signal_handler (priv->act_request, &priv->act_request_id);
|
||||
|
||||
old_act_requst = priv->act_request;
|
||||
priv->act_request = nm_g_object_ref (act_request);
|
||||
nm_dbus_track_obj_path_set (&priv->act_request,
|
||||
act_request,
|
||||
FALSE);
|
||||
|
||||
if (act_request) {
|
||||
priv->act_request_id = g_signal_connect (act_request,
|
||||
"notify::"NM_DBUS_OBJECT_PATH,
|
||||
G_CALLBACK (act_request_set_cb),
|
||||
self);
|
||||
|
||||
switch (nm_active_connection_get_activation_type (NM_ACTIVE_CONNECTION (act_request))) {
|
||||
case NM_ACTIVATION_TYPE_EXTERNAL:
|
||||
break;
|
||||
|
|
@ -9630,8 +9607,6 @@ act_request_set (NMDevice *self, NMActRequest *act_request)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_notify (self, PROP_ACTIVE_CONNECTION);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -10096,7 +10071,7 @@ check_and_reapply_connection (NMDevice *self,
|
|||
}
|
||||
|
||||
if ( version_id != 0
|
||||
&& version_id != nm_active_connection_version_id_get ((NMActiveConnection *) priv->act_request)) {
|
||||
&& version_id != nm_active_connection_version_id_get ((NMActiveConnection *) priv->act_request.obj)) {
|
||||
g_set_error_literal (error,
|
||||
NM_DEVICE_ERROR,
|
||||
NM_DEVICE_ERROR_VERSION_ID_MISMATCH,
|
||||
|
|
@ -10109,10 +10084,10 @@ check_and_reapply_connection (NMDevice *self,
|
|||
*************************************************************************/
|
||||
|
||||
if (diffs)
|
||||
nm_active_connection_version_id_bump ((NMActiveConnection *) priv->act_request);
|
||||
nm_active_connection_version_id_bump ((NMActiveConnection *) priv->act_request.obj);
|
||||
|
||||
_LOGD (LOGD_DEVICE, "reapply (version-id %llu%s)",
|
||||
(unsigned long long) nm_active_connection_version_id_get (((NMActiveConnection *) priv->act_request)),
|
||||
(unsigned long long) nm_active_connection_version_id_get (((NMActiveConnection *) priv->act_request.obj)),
|
||||
diffs ? "" : " (unmodified)");
|
||||
|
||||
if (diffs) {
|
||||
|
|
@ -10362,7 +10337,7 @@ get_applied_connection_cb (NMDevice *self,
|
|||
g_dbus_method_invocation_return_value (context,
|
||||
g_variant_new ("(@a{sa{sv}}t)",
|
||||
settings,
|
||||
nm_active_connection_version_id_get ((NMActiveConnection *) priv->act_request)));
|
||||
nm_active_connection_version_id_get ((NMActiveConnection *) priv->act_request.obj)));
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -10560,7 +10535,7 @@ impl_device_disconnect (NMDBusObject *obj,
|
|||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
NMConnection *connection;
|
||||
|
||||
if (!priv->act_request) {
|
||||
if (!priv->act_request.obj) {
|
||||
g_dbus_method_invocation_return_error_literal (invocation,
|
||||
NM_DEVICE_ERROR,
|
||||
NM_DEVICE_ERROR_NOT_ACTIVE,
|
||||
|
|
@ -10748,8 +10723,8 @@ nm_device_steal_connection (NMDevice *self, NMSettingsConnection *connection)
|
|||
&& connection == nm_active_connection_get_settings_connection (NM_ACTIVE_CONNECTION (priv->queued_act_request)))
|
||||
_clear_queued_act_request (priv);
|
||||
|
||||
if ( priv->act_request
|
||||
&& connection == nm_active_connection_get_settings_connection (NM_ACTIVE_CONNECTION (priv->act_request))
|
||||
if ( priv->act_request.obj
|
||||
&& connection == nm_active_connection_get_settings_connection (NM_ACTIVE_CONNECTION (priv->act_request.obj))
|
||||
&& priv->state < NM_DEVICE_STATE_DEACTIVATING) {
|
||||
nm_device_state_changed (self,
|
||||
NM_DEVICE_STATE_DEACTIVATING,
|
||||
|
|
@ -10765,7 +10740,7 @@ nm_device_queue_activation (NMDevice *self, NMActRequest *req)
|
|||
|
||||
must_queue = _carrier_wait_check_act_request_must_queue (self, req);
|
||||
|
||||
if ( !priv->act_request
|
||||
if ( !priv->act_request.obj
|
||||
&& !must_queue
|
||||
&& nm_device_is_real (self)) {
|
||||
_device_activate (self, req);
|
||||
|
|
@ -10780,7 +10755,7 @@ nm_device_queue_activation (NMDevice *self, NMActRequest *req)
|
|||
_LOGD (LOGD_DEVICE, "queue activation request waiting for %s", must_queue ? "carrier" : "currently active connection to disconnect");
|
||||
|
||||
/* Deactivate existing activation request first */
|
||||
if (priv->act_request) {
|
||||
if (priv->act_request.obj) {
|
||||
_LOGI (LOGD_DEVICE, "disconnecting for new activation request.");
|
||||
nm_device_state_changed (self,
|
||||
NM_DEVICE_STATE_DEACTIVATING,
|
||||
|
|
@ -10995,7 +10970,7 @@ nm_device_set_ip_config (NMDevice *self,
|
|||
&& (settings_connection = nm_device_get_settings_connection (self))
|
||||
&& NM_FLAGS_HAS (nm_settings_connection_get_flags (settings_connection),
|
||||
NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED)
|
||||
&& nm_active_connection_get_activation_type (NM_ACTIVE_CONNECTION (priv->act_request)) == NM_ACTIVATION_TYPE_EXTERNAL) {
|
||||
&& nm_active_connection_get_activation_type (NM_ACTIVE_CONNECTION (priv->act_request.obj)) == NM_ACTIVATION_TYPE_EXTERNAL) {
|
||||
g_object_freeze_notify (G_OBJECT (settings_connection));
|
||||
nm_connection_add_setting (NM_CONNECTION (settings_connection),
|
||||
IS_IPv4
|
||||
|
|
@ -12470,7 +12445,7 @@ nm_device_reapply_settings_immediately (NMDevice *self)
|
|||
if (g_strcmp0 ((zone = nm_setting_connection_get_zone (s_con_settings)),
|
||||
nm_setting_connection_get_zone (s_con_applied)) != 0) {
|
||||
|
||||
version_id = nm_active_connection_version_id_bump ((NMActiveConnection *) self->_priv->act_request);
|
||||
version_id = nm_active_connection_version_id_bump ((NMActiveConnection *) self->_priv->act_request.obj);
|
||||
_LOGD (LOGD_DEVICE, "reapply setting: zone = %s%s%s (version-id %llu)", NM_PRINT_FMT_QUOTE_STRING (zone), (unsigned long long) version_id);
|
||||
|
||||
g_object_set (G_OBJECT (s_con_applied),
|
||||
|
|
@ -12482,7 +12457,7 @@ nm_device_reapply_settings_immediately (NMDevice *self)
|
|||
|
||||
if ((metered = nm_setting_connection_get_metered (s_con_settings)) != nm_setting_connection_get_metered (s_con_applied)) {
|
||||
|
||||
version_id = nm_active_connection_version_id_bump ((NMActiveConnection *) self->_priv->act_request);
|
||||
version_id = nm_active_connection_version_id_bump ((NMActiveConnection *) self->_priv->act_request.obj);
|
||||
_LOGD (LOGD_DEVICE, "reapply setting: metered = %d (version-id %llu)", (int) metered, (unsigned long long) version_id);
|
||||
|
||||
g_object_set (G_OBJECT (s_con_applied),
|
||||
|
|
@ -12841,19 +12816,19 @@ cp_connection_added_or_updated (NMDevice *self, NMConnection *connection)
|
|||
}
|
||||
|
||||
static void
|
||||
cp_connection_added (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data)
|
||||
cp_connection_added (NMSettings *settings, NMConnection *connection, gpointer user_data)
|
||||
{
|
||||
cp_connection_added_or_updated (user_data, connection);
|
||||
}
|
||||
|
||||
static void
|
||||
cp_connection_updated (NMConnectionProvider *cp, NMConnection *connection, gboolean by_user, gpointer user_data)
|
||||
cp_connection_updated (NMSettings *settings, NMConnection *connection, gboolean by_user, gpointer user_data)
|
||||
{
|
||||
cp_connection_added_or_updated (user_data, connection);
|
||||
}
|
||||
|
||||
static void
|
||||
cp_connection_removed (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data)
|
||||
cp_connection_removed (NMSettings *settings, NMConnection *connection, gpointer user_data)
|
||||
{
|
||||
NMDevice *self = user_data;
|
||||
|
||||
|
|
@ -13088,11 +13063,11 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type)
|
|||
* above disables them. */
|
||||
nm_assert (priv->needs_ip6_subnet == FALSE);
|
||||
|
||||
if (priv->act_request) {
|
||||
nm_active_connection_set_default (NM_ACTIVE_CONNECTION (priv->act_request), AF_INET, FALSE);
|
||||
if (priv->act_request.obj) {
|
||||
nm_active_connection_set_default (NM_ACTIVE_CONNECTION (priv->act_request.obj), AF_INET, FALSE);
|
||||
|
||||
priv->master_ready_handled = FALSE;
|
||||
nm_clear_g_signal_handler (priv->act_request, &priv->master_ready_id);
|
||||
nm_clear_g_signal_handler (priv->act_request.obj, &priv->master_ready_id);
|
||||
|
||||
act_request_set (self, NULL);
|
||||
}
|
||||
|
|
@ -13544,7 +13519,7 @@ _set_state_full (NMDevice *self,
|
|||
g_cancellable_cancel (priv->deactivating_cancellable);
|
||||
|
||||
/* Cache the activation request for the dispatcher */
|
||||
req = nm_g_object_ref (priv->act_request);
|
||||
req = nm_g_object_ref (priv->act_request.obj);
|
||||
|
||||
if ( state > NM_DEVICE_STATE_UNMANAGED
|
||||
&& state <= NM_DEVICE_STATE_ACTIVATED
|
||||
|
|
@ -14792,6 +14767,9 @@ nm_device_init (NMDevice *self)
|
|||
|
||||
priv->connectivity_state = NM_CONNECTIVITY_UNKNOWN;
|
||||
|
||||
nm_dbus_track_obj_path_init (&priv->parent_device, G_OBJECT (self), obj_properties[PROP_PARENT]);
|
||||
nm_dbus_track_obj_path_init (&priv->act_request, G_OBJECT (self), obj_properties[PROP_ACTIVE_CONNECTION]);
|
||||
|
||||
priv->netns = g_object_ref (NM_NETNS_GET);
|
||||
|
||||
priv->autoconnect_blocked_flags = DEFAULT_AUTOCONNECT
|
||||
|
|
@ -15030,6 +15008,9 @@ finalize (GObject *object)
|
|||
g_hash_table_unref (priv->ip6_saved_properties);
|
||||
g_hash_table_unref (priv->available_connections);
|
||||
|
||||
nm_dbus_track_obj_path_deinit (&priv->parent_device);
|
||||
nm_dbus_track_obj_path_deinit (&priv->act_request);
|
||||
|
||||
G_OBJECT_CLASS (nm_device_parent_class)->finalize (object);
|
||||
|
||||
/* for testing, NMDeviceTest does not invoke NMDevice::constructed,
|
||||
|
|
@ -15146,9 +15127,6 @@ get_property (GObject *object, guint prop_id,
|
|||
{
|
||||
NMDevice *self = NM_DEVICE (object);
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
GPtrArray *array;
|
||||
GHashTableIter iter;
|
||||
NMConnection *connection;
|
||||
GVariantBuilder array_builder;
|
||||
|
||||
switch (prop_id) {
|
||||
|
|
@ -15223,7 +15201,7 @@ get_property (GObject *object, guint prop_id,
|
|||
g_variant_new ("(uu)", priv->state, priv->state_reason));
|
||||
break;
|
||||
case PROP_ACTIVE_CONNECTION:
|
||||
nm_dbus_utils_g_value_set_object_path (value, priv->act_request_public ? priv->act_request : NULL);
|
||||
g_value_set_string (value, nm_dbus_track_obj_path_get (&priv->act_request));
|
||||
break;
|
||||
case PROP_DEVICE_TYPE:
|
||||
g_value_set_uint (value, priv->type);
|
||||
|
|
@ -15254,12 +15232,9 @@ get_property (GObject *object, guint prop_id,
|
|||
g_value_set_uint (value, priv->rfkill_type);
|
||||
break;
|
||||
case PROP_AVAILABLE_CONNECTIONS:
|
||||
array = g_ptr_array_sized_new (g_hash_table_size (priv->available_connections));
|
||||
g_hash_table_iter_init (&iter, priv->available_connections);
|
||||
while (g_hash_table_iter_next (&iter, (gpointer) &connection, NULL))
|
||||
g_ptr_array_add (array, g_strdup (nm_connection_get_path (connection)));
|
||||
g_ptr_array_add (array, NULL);
|
||||
g_value_take_boxed (value, (char **) g_ptr_array_free (array, FALSE));
|
||||
nm_dbus_utils_g_value_set_object_path_from_hash (value,
|
||||
priv->available_connections,
|
||||
TRUE);
|
||||
break;
|
||||
case PROP_PHYSICAL_PORT_ID:
|
||||
g_value_set_string (value, priv->physical_port_id);
|
||||
|
|
@ -15268,7 +15243,7 @@ get_property (GObject *object, guint prop_id,
|
|||
g_value_set_object (value, nm_device_get_master (self));
|
||||
break;
|
||||
case PROP_PARENT:
|
||||
nm_dbus_utils_g_value_set_object_path (value, priv->parent_device);
|
||||
g_value_set_string (value, nm_dbus_track_obj_path_get (&priv->parent_device));
|
||||
break;
|
||||
case PROP_HW_ADDRESS:
|
||||
g_value_set_string (value, priv->hw_addr);
|
||||
|
|
|
|||
|
|
@ -28,12 +28,15 @@
|
|||
#include "settings/nm-settings-connection.h"
|
||||
#include "nm-simple-connection.h"
|
||||
#include "nm-auth-utils.h"
|
||||
#include "nm-auth-manager.h"
|
||||
#include "nm-auth-subject.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
#include "nm-core-internal.h"
|
||||
|
||||
#define AUTH_CALL_ID_SHARED_WIFI_PERMISSION_FAILED ((NMAuthManagerCallId *) GINT_TO_POINTER (1))
|
||||
|
||||
typedef struct _NMActiveConnectionPrivate {
|
||||
NMSettingsConnection *settings_connection;
|
||||
NMDBusTrackObjPath settings_connection;
|
||||
NMConnection *applied_connection;
|
||||
char *specific_object;
|
||||
NMDevice *device;
|
||||
|
|
@ -59,11 +62,15 @@ typedef struct _NMActiveConnectionPrivate {
|
|||
|
||||
NMActiveConnection *parent;
|
||||
|
||||
NMAuthChain *chain;
|
||||
const char *wifi_shared_permission;
|
||||
NMActiveConnectionAuthResultFunc result_func;
|
||||
gpointer user_data1;
|
||||
gpointer user_data2;
|
||||
struct {
|
||||
NMAuthManagerCallId *call_id_network_control;
|
||||
NMAuthManagerCallId *call_id_wifi_shared_permission;
|
||||
|
||||
NMActiveConnectionAuthResultFunc result_func;
|
||||
gpointer user_data1;
|
||||
gpointer user_data2;
|
||||
} auth;
|
||||
|
||||
} NMActiveConnectionPrivate;
|
||||
|
||||
NM_GOBJECT_PROPERTIES_DEFINE (NMActiveConnection,
|
||||
|
|
@ -183,41 +190,25 @@ _settings_connection_updated (NMSettingsConnection *connection,
|
|||
* settings-connection. */
|
||||
}
|
||||
|
||||
static void
|
||||
_settings_connection_removed (NMSettingsConnection *connection,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMActiveConnection *self = user_data;
|
||||
|
||||
/* Our settings connection is about to drop off. The next active connection
|
||||
* cleanup is going to tear us down (at least until we grow the capability to
|
||||
* re-link; in that case we'd just clean the references to the old connection here).
|
||||
* Let's remove ourselves from the bus so that we're not exposed with a dangling
|
||||
* reference to the setting connection once it's gone. */
|
||||
if (nm_dbus_object_is_exported (NM_DBUS_OBJECT (self)))
|
||||
nm_dbus_object_unexport (NM_DBUS_OBJECT (self));
|
||||
}
|
||||
|
||||
static void
|
||||
_set_settings_connection (NMActiveConnection *self, NMSettingsConnection *connection)
|
||||
{
|
||||
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
||||
|
||||
if (priv->settings_connection == connection)
|
||||
if (priv->settings_connection.obj == connection)
|
||||
return;
|
||||
if (priv->settings_connection) {
|
||||
g_signal_handlers_disconnect_by_func (priv->settings_connection, _settings_connection_updated, self);
|
||||
g_signal_handlers_disconnect_by_func (priv->settings_connection, _settings_connection_removed, self);
|
||||
g_signal_handlers_disconnect_by_func (priv->settings_connection, _settings_connection_notify_flags, self);
|
||||
g_clear_object (&priv->settings_connection);
|
||||
|
||||
if (priv->settings_connection.obj) {
|
||||
g_signal_handlers_disconnect_by_func (priv->settings_connection.obj, _settings_connection_updated, self);
|
||||
g_signal_handlers_disconnect_by_func (priv->settings_connection.obj, _settings_connection_notify_flags, self);
|
||||
}
|
||||
if (connection) {
|
||||
priv->settings_connection = g_object_ref (connection);
|
||||
g_signal_connect (connection, NM_SETTINGS_CONNECTION_UPDATED_INTERNAL, (GCallback) _settings_connection_updated, self);
|
||||
g_signal_connect (connection, NM_SETTINGS_CONNECTION_REMOVED, (GCallback) _settings_connection_removed, self);
|
||||
if (nm_active_connection_get_activation_type (self) == NM_ACTIVATION_TYPE_EXTERNAL)
|
||||
g_signal_connect (connection, "notify::"NM_SETTINGS_CONNECTION_FLAGS, (GCallback) _settings_connection_notify_flags, self);
|
||||
}
|
||||
|
||||
nm_dbus_track_obj_path_set (&priv->settings_connection, connection, TRUE);
|
||||
}
|
||||
|
||||
NMActiveConnectionState
|
||||
|
|
@ -275,7 +266,7 @@ nm_active_connection_set_state (NMActiveConnection *self,
|
|||
|
||||
if ( new_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED
|
||||
|| old_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
|
||||
nm_settings_connection_update_timestamp (priv->settings_connection,
|
||||
nm_settings_connection_update_timestamp (priv->settings_connection.obj,
|
||||
(guint64) time (NULL), TRUE);
|
||||
}
|
||||
|
||||
|
|
@ -371,7 +362,7 @@ nm_active_connection_get_settings_connection_id (NMActiveConnection *self)
|
|||
|
||||
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), NULL);
|
||||
|
||||
con = NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->settings_connection;
|
||||
con = NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->settings_connection.obj;
|
||||
return con
|
||||
? nm_connection_get_id (NM_CONNECTION (con))
|
||||
: NULL;
|
||||
|
|
@ -382,7 +373,7 @@ _nm_active_connection_get_settings_connection (NMActiveConnection *self)
|
|||
{
|
||||
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), NULL);
|
||||
|
||||
return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->settings_connection;
|
||||
return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->settings_connection.obj;
|
||||
}
|
||||
|
||||
NMSettingsConnection *
|
||||
|
|
@ -456,7 +447,7 @@ nm_active_connection_set_settings_connection (NMActiveConnection *self,
|
|||
priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
||||
|
||||
g_return_if_fail (NM_IS_SETTINGS_CONNECTION (connection));
|
||||
g_return_if_fail (!priv->settings_connection);
|
||||
g_return_if_fail (!priv->settings_connection.obj);
|
||||
g_return_if_fail (!priv->applied_connection);
|
||||
|
||||
/* Can't change connection after the ActiveConnection is exported over D-Bus.
|
||||
|
|
@ -471,7 +462,7 @@ nm_active_connection_set_settings_connection (NMActiveConnection *self,
|
|||
_set_settings_connection (self, connection);
|
||||
|
||||
_set_applied_connection_take (self,
|
||||
nm_simple_connection_new_clone (NM_CONNECTION (priv->settings_connection)));
|
||||
nm_simple_connection_new_clone (NM_CONNECTION (priv->settings_connection.obj)));
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
|
@ -483,9 +474,9 @@ nm_active_connection_has_unmodified_applied_connection (NMActiveConnection *self
|
|||
|
||||
priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
||||
|
||||
g_return_val_if_fail (priv->settings_connection, FALSE);
|
||||
g_return_val_if_fail (priv->settings_connection.obj, FALSE);
|
||||
|
||||
return nm_settings_connection_has_unmodified_applied_connection (priv->settings_connection,
|
||||
return nm_settings_connection_has_unmodified_applied_connection (priv->settings_connection.obj,
|
||||
priv->applied_connection,
|
||||
compare_flags);
|
||||
}
|
||||
|
|
@ -501,10 +492,10 @@ nm_active_connection_clear_secrets (NMActiveConnection *self)
|
|||
|
||||
priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
||||
|
||||
if (nm_settings_connection_has_unmodified_applied_connection (priv->settings_connection,
|
||||
if (nm_settings_connection_has_unmodified_applied_connection (priv->settings_connection.obj,
|
||||
priv->applied_connection,
|
||||
NM_SETTING_COMPARE_FLAG_NONE))
|
||||
nm_connection_clear_secrets ((NMConnection *) priv->settings_connection);
|
||||
nm_connection_clear_secrets ((NMConnection *) priv->settings_connection.obj);
|
||||
nm_connection_clear_secrets (priv->applied_connection);
|
||||
}
|
||||
|
||||
|
|
@ -864,11 +855,11 @@ _set_activation_type (NMActiveConnection *self,
|
|||
|
||||
priv->activation_type = activation_type;
|
||||
|
||||
if (priv->settings_connection) {
|
||||
if (priv->settings_connection.obj) {
|
||||
if (activation_type == NM_ACTIVATION_TYPE_EXTERNAL)
|
||||
g_signal_connect (priv->settings_connection, "notify::"NM_SETTINGS_CONNECTION_FLAGS, (GCallback) _settings_connection_notify_flags, self);
|
||||
g_signal_connect (priv->settings_connection.obj, "notify::"NM_SETTINGS_CONNECTION_FLAGS, (GCallback) _settings_connection_notify_flags, self);
|
||||
else
|
||||
g_signal_handlers_disconnect_by_func (priv->settings_connection, _settings_connection_notify_flags, self);
|
||||
g_signal_handlers_disconnect_by_func (priv->settings_connection.obj, _settings_connection_notify_flags, self);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -914,7 +905,7 @@ _settings_connection_notify_flags (NMSettingsConnection *settings_connection,
|
|||
nm_assert (NM_IS_ACTIVE_CONNECTION (self));
|
||||
nm_assert (NM_IS_SETTINGS_CONNECTION (settings_connection));
|
||||
nm_assert (nm_active_connection_get_activation_type (self) == NM_ACTIVATION_TYPE_EXTERNAL);
|
||||
nm_assert (NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->settings_connection == settings_connection);
|
||||
nm_assert (NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->settings_connection.obj == settings_connection);
|
||||
|
||||
if (NM_FLAGS_HAS (nm_settings_connection_get_flags (settings_connection),
|
||||
NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED))
|
||||
|
|
@ -997,62 +988,93 @@ nm_active_connection_set_parent (NMActiveConnection *self, NMActiveConnection *p
|
|||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
auth_done (NMAuthChain *chain,
|
||||
auth_cancel (NMActiveConnection *self)
|
||||
{
|
||||
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
||||
|
||||
if (priv->auth.call_id_network_control)
|
||||
nm_auth_manager_check_authorization_cancel (priv->auth.call_id_network_control);
|
||||
if (priv->auth.call_id_wifi_shared_permission) {
|
||||
if (priv->auth.call_id_wifi_shared_permission == AUTH_CALL_ID_SHARED_WIFI_PERMISSION_FAILED)
|
||||
priv->auth.call_id_wifi_shared_permission = NULL;
|
||||
else
|
||||
nm_auth_manager_check_authorization_cancel (priv->auth.call_id_wifi_shared_permission);
|
||||
}
|
||||
priv->auth.result_func = NULL;
|
||||
priv->auth.user_data1 = NULL;
|
||||
priv->auth.user_data2 = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
auth_complete (NMActiveConnection *self, gboolean result, const char *message)
|
||||
{
|
||||
_nm_unused gs_unref_object NMActiveConnection *self_keep_alive = g_object_ref (self);
|
||||
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
||||
|
||||
priv->auth.result_func (self,
|
||||
result,
|
||||
message,
|
||||
priv->auth.user_data1,
|
||||
priv->auth.user_data2);
|
||||
auth_cancel (self);
|
||||
}
|
||||
|
||||
static void
|
||||
auth_done (NMAuthManager *auth_mgr,
|
||||
NMAuthManagerCallId *auth_call_id,
|
||||
gboolean is_authorized,
|
||||
gboolean is_challenge,
|
||||
GError *error,
|
||||
GDBusMethodInvocation *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);
|
||||
nm_assert (auth_call_id);
|
||||
nm_assert (priv->auth.result_func);
|
||||
|
||||
/* 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;
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
||||
if (auth_call_id == priv->auth.call_id_network_control)
|
||||
priv->auth.call_id_network_control = NULL;
|
||||
else {
|
||||
nm_assert (auth_call_id == priv->auth.call_id_wifi_shared_permission);
|
||||
priv->auth.call_id_wifi_shared_permission = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Otherwise authorized and available to activate */
|
||||
priv->result_func (self, TRUE, NULL, priv->user_data1, priv->user_data2);
|
||||
result = nm_auth_call_result_eval (is_authorized, is_challenge, error);
|
||||
|
||||
done:
|
||||
nm_auth_chain_unref (chain);
|
||||
priv->chain = NULL;
|
||||
priv->result_func = NULL;
|
||||
priv->user_data1 = NULL;
|
||||
priv->user_data2 = NULL;
|
||||
if (auth_call_id == priv->auth.call_id_network_control) {
|
||||
priv->auth.call_id_network_control = NULL;
|
||||
if (result != NM_AUTH_CALL_RESULT_YES) {
|
||||
auth_complete (self, FALSE, "Not authorized to control networking.");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
nm_assert (auth_call_id == priv->auth.call_id_wifi_shared_permission);
|
||||
if (result != NM_AUTH_CALL_RESULT_YES) {
|
||||
/* we don't fail right away. Instead, we mark that wifi-shared-permissions
|
||||
* are missing. We prefer to report the failure about network-control.
|
||||
* Below, we will wait longer for call_id_network_control (if it's still
|
||||
* pending). */
|
||||
priv->auth.call_id_wifi_shared_permission = AUTH_CALL_ID_SHARED_WIFI_PERMISSION_FAILED;
|
||||
} else
|
||||
priv->auth.call_id_wifi_shared_permission = NULL;
|
||||
}
|
||||
|
||||
g_object_unref (self);
|
||||
if (priv->auth.call_id_network_control)
|
||||
return;
|
||||
|
||||
if (priv->auth.call_id_wifi_shared_permission) {
|
||||
if (priv->auth.call_id_wifi_shared_permission == AUTH_CALL_ID_SHARED_WIFI_PERMISSION_FAILED)
|
||||
auth_complete (self, FALSE, "Not authorized to share connections via wifi.");
|
||||
return;
|
||||
}
|
||||
|
||||
auth_complete (self, TRUE, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1080,37 +1102,43 @@ nm_active_connection_authorize (NMActiveConnection *self,
|
|||
const char *wifi_permission = NULL;
|
||||
NMConnection *con;
|
||||
|
||||
g_return_if_fail (result_func != NULL);
|
||||
g_return_if_fail (priv->chain == NULL);
|
||||
g_return_if_fail (result_func);
|
||||
g_return_if_fail (!priv->auth.call_id_network_control);
|
||||
nm_assert (!priv->auth.call_id_wifi_shared_permission);
|
||||
|
||||
if (initial_connection) {
|
||||
g_return_if_fail (NM_IS_CONNECTION (initial_connection));
|
||||
g_return_if_fail (!priv->settings_connection);
|
||||
g_return_if_fail (!priv->settings_connection.obj);
|
||||
g_return_if_fail (!priv->applied_connection);
|
||||
con = initial_connection;
|
||||
} else {
|
||||
g_return_if_fail (NM_IS_SETTINGS_CONNECTION (priv->settings_connection));
|
||||
g_return_if_fail (NM_IS_SETTINGS_CONNECTION (priv->settings_connection.obj));
|
||||
g_return_if_fail (NM_IS_CONNECTION (priv->applied_connection));
|
||||
con = priv->applied_connection;
|
||||
}
|
||||
|
||||
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);
|
||||
priv->auth.call_id_network_control = nm_auth_manager_check_authorization (nm_auth_manager_get (),
|
||||
priv->subject,
|
||||
NM_AUTH_PERMISSION_NETWORK_CONTROL,
|
||||
TRUE,
|
||||
auth_done,
|
||||
self);
|
||||
|
||||
/* Shared wifi connections require special permissions too */
|
||||
wifi_permission = nm_utils_get_shared_wifi_permission (con);
|
||||
if (wifi_permission) {
|
||||
priv->wifi_shared_permission = wifi_permission;
|
||||
nm_auth_chain_add_call (priv->chain, wifi_permission, TRUE);
|
||||
priv->auth.call_id_wifi_shared_permission = nm_auth_manager_check_authorization (nm_auth_manager_get (),
|
||||
priv->subject,
|
||||
wifi_permission,
|
||||
TRUE,
|
||||
auth_done,
|
||||
self);
|
||||
}
|
||||
|
||||
/* Wait for authorization */
|
||||
priv->result_func = result_func;
|
||||
priv->user_data1 = user_data1;
|
||||
priv->user_data2 = user_data2;
|
||||
priv->auth.result_func = result_func;
|
||||
priv->auth.user_data1 = user_data1;
|
||||
priv->auth.user_data2 = user_data2;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -1172,31 +1200,40 @@ get_property (GObject *object, guint prop_id,
|
|||
GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE ((NMActiveConnection *) object);
|
||||
GPtrArray *devices;
|
||||
char **strv;
|
||||
NMDevice *master_device = NULL;
|
||||
|
||||
switch (prop_id) {
|
||||
|
||||
/* note that while priv->settings_connection.obj might not be set initially,
|
||||
* it will be set before the object is exported on D-Bus. Hence,
|
||||
* nobody is calling these property getters before the object is
|
||||
* exported, at which point we will have a valid settings-connection.
|
||||
*
|
||||
* Therefore, intentionally not check whether priv->settings_connection.obj
|
||||
* is set, to get an assertion failure if somebody tries to access the
|
||||
* getters at the wrong time. */
|
||||
case PROP_CONNECTION:
|
||||
g_value_set_string (value, nm_connection_get_path (NM_CONNECTION (priv->settings_connection)));
|
||||
g_value_set_string (value, nm_dbus_track_obj_path_get (&priv->settings_connection));
|
||||
break;
|
||||
case PROP_ID:
|
||||
g_value_set_string (value, nm_connection_get_id (NM_CONNECTION (priv->settings_connection)));
|
||||
g_value_set_string (value, nm_connection_get_id (NM_CONNECTION (priv->settings_connection.obj)));
|
||||
break;
|
||||
case PROP_UUID:
|
||||
g_value_set_string (value, nm_connection_get_uuid (NM_CONNECTION (priv->settings_connection)));
|
||||
g_value_set_string (value, nm_connection_get_uuid (NM_CONNECTION (priv->settings_connection.obj)));
|
||||
break;
|
||||
case PROP_TYPE:
|
||||
g_value_set_string (value, nm_connection_get_connection_type (NM_CONNECTION (priv->settings_connection)));
|
||||
g_value_set_string (value, nm_connection_get_connection_type (NM_CONNECTION (priv->settings_connection.obj)));
|
||||
break;
|
||||
|
||||
case PROP_SPECIFIC_OBJECT:
|
||||
g_value_set_string (value, priv->specific_object ? priv->specific_object : "/");
|
||||
break;
|
||||
case PROP_DEVICES:
|
||||
devices = g_ptr_array_sized_new (2);
|
||||
strv = g_new0 (char *, 2);
|
||||
if (priv->device && priv->state < NM_ACTIVE_CONNECTION_STATE_DEACTIVATED)
|
||||
g_ptr_array_add (devices, g_strdup (nm_dbus_object_get_path (NM_DBUS_OBJECT (priv->device))));
|
||||
g_ptr_array_add (devices, NULL);
|
||||
g_value_take_boxed (value, (char **) g_ptr_array_free (devices, FALSE));
|
||||
strv[0] = g_strdup (nm_dbus_object_get_path (NM_DBUS_OBJECT (priv->device)));
|
||||
g_value_take_boxed (value, strv);
|
||||
break;
|
||||
case PROP_STATE:
|
||||
if (priv->state_set)
|
||||
|
|
@ -1342,6 +1379,10 @@ nm_active_connection_init (NMActiveConnection *self)
|
|||
priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_ACTIVE_CONNECTION, NMActiveConnectionPrivate);
|
||||
self->_priv = priv;
|
||||
|
||||
nm_dbus_track_obj_path_init (&priv->settings_connection,
|
||||
G_OBJECT (self),
|
||||
obj_properties[PROP_CONNECTION]);
|
||||
|
||||
c_list_init (&self->active_connections_lst);
|
||||
|
||||
_LOGT ("creating");
|
||||
|
|
@ -1359,8 +1400,8 @@ constructed (GObject *object)
|
|||
G_OBJECT_CLASS (nm_active_connection_parent_class)->constructed (object);
|
||||
|
||||
if ( !priv->applied_connection
|
||||
&& priv->settings_connection)
|
||||
priv->applied_connection = nm_simple_connection_new_clone (NM_CONNECTION (priv->settings_connection));
|
||||
&& priv->settings_connection.obj)
|
||||
priv->applied_connection = nm_simple_connection_new_clone (NM_CONNECTION (priv->settings_connection.obj));
|
||||
|
||||
_LOGD ("constructed (%s, version-id %llu, type %s)",
|
||||
G_OBJECT_TYPE_NAME (self),
|
||||
|
|
@ -1390,10 +1431,7 @@ dispose (GObject *object)
|
|||
|
||||
_LOGD ("disposing");
|
||||
|
||||
if (priv->chain) {
|
||||
nm_auth_chain_unref (priv->chain);
|
||||
priv->chain = NULL;
|
||||
}
|
||||
auth_cancel (self);
|
||||
|
||||
g_free (priv->specific_object);
|
||||
priv->specific_object = NULL;
|
||||
|
|
@ -1418,6 +1456,17 @@ dispose (GObject *object)
|
|||
G_OBJECT_CLASS (nm_active_connection_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
finalize (GObject *object)
|
||||
{
|
||||
NMActiveConnection *self = NM_ACTIVE_CONNECTION (object);
|
||||
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
||||
|
||||
nm_dbus_track_obj_path_set (&priv->settings_connection, NULL, FALSE);
|
||||
|
||||
G_OBJECT_CLASS (nm_active_connection_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static const GDBusSignalInfo signal_info_state_changed = NM_DEFINE_GDBUS_SIGNAL_INFO_INIT (
|
||||
"StateChanged",
|
||||
.args = NM_DEFINE_GDBUS_ARG_INFOS (
|
||||
|
|
@ -1470,6 +1519,7 @@ nm_active_connection_class_init (NMActiveConnectionClass *ac_class)
|
|||
object_class->set_property = set_property;
|
||||
object_class->constructed = constructed;
|
||||
object_class->dispose = dispose;
|
||||
object_class->finalize = finalize;
|
||||
|
||||
obj_properties[PROP_CONNECTION] =
|
||||
g_param_spec_string (NM_ACTIVE_CONNECTION_CONNECTION, "", "",
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include "nm-auth-manager.h"
|
||||
|
||||
#include "nm-utils/c-list.h"
|
||||
#include "nm-errors.h"
|
||||
#include "nm-core-internal.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
|
|
@ -30,6 +31,9 @@
|
|||
#define POLKIT_OBJECT_PATH "/org/freedesktop/PolicyKit1/Authority"
|
||||
#define POLKIT_INTERFACE "org.freedesktop.PolicyKit1.Authority"
|
||||
|
||||
#define CANCELLATION_ID_PREFIX "cancellation-id-"
|
||||
#define CANCELLATION_TIMEOUT_MS 5000
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NM_GOBJECT_PROPERTIES_DEFINE_BASE (
|
||||
|
|
@ -44,13 +48,14 @@ enum {
|
|||
static guint signals[LAST_SIGNAL] = {0};
|
||||
|
||||
typedef struct {
|
||||
gboolean polkit_enabled;
|
||||
#if WITH_POLKIT
|
||||
guint call_id_counter;
|
||||
GCancellable *new_proxy_cancellable;
|
||||
GSList *queued_calls;
|
||||
CList calls_lst_head;
|
||||
GDBusProxy *proxy;
|
||||
#endif
|
||||
GCancellable *new_proxy_cancellable;
|
||||
GCancellable *cancel_cancellable;
|
||||
guint64 call_numid_counter;
|
||||
bool polkit_enabled:1;
|
||||
bool disposing:1;
|
||||
bool shutting_down:1;
|
||||
} NMAuthManagerPrivate;
|
||||
|
||||
struct _NMAuthManager {
|
||||
|
|
@ -85,6 +90,22 @@ NM_DEFINE_SINGLETON_REGISTER (NMAuthManager);
|
|||
} \
|
||||
} G_STMT_END
|
||||
|
||||
#define _NMLOG2(level, call_id, ...) \
|
||||
G_STMT_START { \
|
||||
if (nm_logging_enabled ((level), (_NMLOG_DOMAIN))) { \
|
||||
NMAuthManagerCallId *_call_id = (call_id); \
|
||||
char __prefix[30] = _NMLOG_PREFIX_NAME; \
|
||||
\
|
||||
if (_call_id->self != singleton_instance) \
|
||||
g_snprintf (__prefix, sizeof (__prefix), ""_NMLOG_PREFIX_NAME"[%p]", _call_id->self); \
|
||||
_nm_log ((level), (_NMLOG_DOMAIN), 0, NULL, NULL, \
|
||||
"%s: call[%"G_GUINT64_FORMAT"]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
|
||||
__prefix, \
|
||||
_call_id->call_numid \
|
||||
_NM_UTILS_MACRO_REST(__VA_ARGS__)); \
|
||||
} \
|
||||
} G_STMT_END
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gboolean
|
||||
|
|
@ -97,251 +118,323 @@ nm_auth_manager_get_polkit_enabled (NMAuthManager *self)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
#if WITH_POLKIT
|
||||
|
||||
typedef enum {
|
||||
POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE = 0,
|
||||
POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION = (1<<0),
|
||||
} PolkitCheckAuthorizationFlags;
|
||||
|
||||
typedef struct {
|
||||
guint call_id;
|
||||
typedef enum {
|
||||
IDLE_REASON_AUTHORIZED,
|
||||
IDLE_REASON_NO_DBUS,
|
||||
} IdleReason;
|
||||
|
||||
struct _NMAuthManagerCallId {
|
||||
CList calls_lst;
|
||||
NMAuthManager *self;
|
||||
GSimpleAsyncResult *simple;
|
||||
gchar *cancellation_id;
|
||||
GVariant *dbus_parameters;
|
||||
GCancellable *cancellable;
|
||||
} CheckAuthData;
|
||||
GCancellable *dbus_cancellable;
|
||||
NMAuthManagerCheckAuthorizationCallback callback;
|
||||
gpointer user_data;
|
||||
guint64 call_numid;
|
||||
guint idle_id;
|
||||
IdleReason idle_reason:8;
|
||||
};
|
||||
|
||||
#define cancellation_id_to_str_a(call_numid) \
|
||||
nm_sprintf_bufa (NM_STRLEN (CANCELLATION_ID_PREFIX) + 20, \
|
||||
CANCELLATION_ID_PREFIX"%"G_GUINT64_FORMAT, \
|
||||
(call_numid))
|
||||
|
||||
static void
|
||||
_check_auth_data_free (CheckAuthData *data)
|
||||
_call_id_free (NMAuthManagerCallId *call_id)
|
||||
{
|
||||
if (data->dbus_parameters)
|
||||
g_variant_unref (data->dbus_parameters);
|
||||
g_object_unref (data->self);
|
||||
g_object_unref (data->simple);
|
||||
g_clear_object (&data->cancellable);
|
||||
g_free (data->cancellation_id);
|
||||
g_free (data);
|
||||
c_list_unlink (&call_id->calls_lst);
|
||||
nm_clear_g_source (&call_id->idle_id);
|
||||
if (call_id->dbus_parameters)
|
||||
g_variant_unref (g_steal_pointer (&call_id->dbus_parameters));
|
||||
|
||||
if (call_id->dbus_cancellable) {
|
||||
/* we have a pending D-Bus call. We keep the call-id instance alive
|
||||
* for _call_check_authorize_cb() */
|
||||
g_cancellable_cancel (call_id->dbus_cancellable);
|
||||
return;
|
||||
}
|
||||
|
||||
g_object_unref (call_id->self);
|
||||
g_slice_free (NMAuthManagerCallId, call_id);
|
||||
}
|
||||
|
||||
static void
|
||||
_call_check_authorization_complete_with_error (CheckAuthData *data,
|
||||
const char *error_message)
|
||||
_call_id_invoke_callback (NMAuthManagerCallId *call_id,
|
||||
gboolean is_authorized,
|
||||
gboolean is_challenge,
|
||||
GError *error)
|
||||
{
|
||||
NMAuthManager *self = data->self;
|
||||
c_list_unlink (&call_id->calls_lst);
|
||||
|
||||
_LOGD ("call[%u]: CheckAuthorization failed due to internal error: %s", data->call_id, error_message);
|
||||
g_simple_async_result_set_error (data->simple,
|
||||
NM_MANAGER_ERROR,
|
||||
NM_MANAGER_ERROR_FAILED,
|
||||
"Authorization check failed: %s",
|
||||
error_message);
|
||||
|
||||
g_simple_async_result_complete_in_idle (data->simple);
|
||||
|
||||
_check_auth_data_free (data);
|
||||
call_id->callback (call_id->self,
|
||||
call_id,
|
||||
is_authorized,
|
||||
is_challenge,
|
||||
error,
|
||||
call_id->user_data);
|
||||
_call_id_free (call_id);
|
||||
}
|
||||
|
||||
static void
|
||||
cancel_check_authorization_cb (GDBusProxy *proxy,
|
||||
cancel_check_authorization_cb (GObject *proxy,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMAuthManager *self = user_data;
|
||||
GVariant *value;
|
||||
GError *error= NULL;
|
||||
NMAuthManagerCallId *call_id = user_data;
|
||||
gs_unref_variant GVariant *value = NULL;
|
||||
gs_free_error GError *error= NULL;
|
||||
|
||||
value = g_dbus_proxy_call_finish (proxy, res, &error);
|
||||
if (value == NULL) {
|
||||
g_dbus_error_strip_remote_error (error);
|
||||
_LOGD ("Error cancelling authorization check: %s", error->message);
|
||||
g_error_free (error);
|
||||
} else
|
||||
g_variant_unref (value);
|
||||
value = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, &error);
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
_LOG2T (call_id, "cancel request was cancelled");
|
||||
else if (error)
|
||||
_LOG2T (call_id, "cancel request failed: %s", error->message);
|
||||
else
|
||||
_LOG2T (call_id, "cancel request succeeded");
|
||||
|
||||
g_object_unref (self);
|
||||
_call_id_free (call_id);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
gboolean is_authorized;
|
||||
gboolean is_challenge;
|
||||
} CheckAuthorizationResult;
|
||||
|
||||
static void
|
||||
check_authorization_cb (GDBusProxy *proxy,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
_call_check_authorize_cb (GObject *proxy,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
CheckAuthData *data = user_data;
|
||||
NMAuthManager *self = data->self;
|
||||
NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
|
||||
GVariant *value;
|
||||
GError *error = NULL;
|
||||
NMAuthManagerCallId *call_id = user_data;
|
||||
NMAuthManager *self;
|
||||
NMAuthManagerPrivate *priv;
|
||||
gs_unref_variant GVariant *value = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
gboolean is_authorized = FALSE;
|
||||
gboolean is_challenge = FALSE;
|
||||
|
||||
value = _nm_dbus_proxy_call_finish (proxy, res, G_VARIANT_TYPE ("((bba{ss}))"), &error);
|
||||
if (value == NULL) {
|
||||
if (data->cancellation_id != NULL &&
|
||||
( g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)
|
||||
&& !g_dbus_error_is_remote_error (error))) {
|
||||
_LOGD ("call[%u]: CheckAuthorization cancelled", data->call_id);
|
||||
g_dbus_proxy_call (priv->proxy,
|
||||
"CancelCheckAuthorization",
|
||||
g_variant_new ("(s)", data->cancellation_id),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
NULL, /* GCancellable */
|
||||
(GAsyncReadyCallback) cancel_check_authorization_cb,
|
||||
g_object_ref (self));
|
||||
} else
|
||||
_LOGD ("call[%u]: CheckAuthorization failed: %s", data->call_id, error->message);
|
||||
g_dbus_error_strip_remote_error (error);
|
||||
g_simple_async_result_set_error (data->simple,
|
||||
NM_MANAGER_ERROR,
|
||||
NM_MANAGER_ERROR_FAILED,
|
||||
"Authorization check failed: %s",
|
||||
error->message);
|
||||
g_error_free (error);
|
||||
} else {
|
||||
CheckAuthorizationResult *result;
|
||||
/* we need to clear the cancelable, to signal for _call_id_free() that we
|
||||
* are not in a pending call.
|
||||
*
|
||||
* Note how _call_id_free() kept call-id alive, even if the request was
|
||||
* already cancelled. */
|
||||
g_clear_object (&call_id->dbus_cancellable);
|
||||
|
||||
result = g_new0 (CheckAuthorizationResult, 1);
|
||||
self = call_id->self;
|
||||
priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
|
||||
|
||||
g_variant_get (value,
|
||||
"((bb@a{ss}))",
|
||||
&result->is_authorized,
|
||||
&result->is_challenge,
|
||||
NULL);
|
||||
g_variant_unref (value);
|
||||
value = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, G_VARIANT_TYPE ("((bba{ss}))"), &error);
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
||||
/* call_id was cancelled externally, but _call_id_free() kept call_id
|
||||
* alive (and it has still the reference on @self. */
|
||||
|
||||
_LOGD ("call[%u]: CheckAuthorization succeeded: (is_authorized=%d, is_challenge=%d)", data->call_id, result->is_authorized, result->is_challenge);
|
||||
g_simple_async_result_set_op_res_gpointer (data->simple, result, g_free);
|
||||
if (!priv->cancel_cancellable) {
|
||||
/* we do a forced shutdown. There is no more time for cancelling... */
|
||||
_call_id_free (call_id);
|
||||
|
||||
/* this shouldn't really happen, because:
|
||||
* _call_check_authorize() only scheduled the D-Bus request at a time when
|
||||
* cancel_cancellable was still set. It means, somebody called force-shutdown
|
||||
* after call-id was schedule.
|
||||
* force-shutdown should only be called after:
|
||||
* - cancel all pending requests
|
||||
* - give enough time to cancel the request and schedule a D-Bus call
|
||||
* to CancelCheckAuthorization (below), before issuing force-shutdown. */
|
||||
g_return_if_reached ();
|
||||
}
|
||||
|
||||
g_dbus_proxy_call (priv->proxy,
|
||||
"CancelCheckAuthorization",
|
||||
g_variant_new ("(s)",
|
||||
cancellation_id_to_str_a (call_id->call_numid)),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
CANCELLATION_TIMEOUT_MS,
|
||||
priv->cancel_cancellable,
|
||||
cancel_check_authorization_cb,
|
||||
call_id);
|
||||
return;
|
||||
}
|
||||
|
||||
g_simple_async_result_complete (data->simple);
|
||||
if (!error) {
|
||||
g_variant_get (value,
|
||||
"((bb@a{ss}))",
|
||||
&is_authorized,
|
||||
&is_challenge,
|
||||
NULL);
|
||||
_LOG2T (call_id, "completed: authorized=%d, challenge=%d",
|
||||
is_authorized, is_challenge);
|
||||
} else
|
||||
_LOG2T (call_id, "completed: failed: %s", error->message);
|
||||
|
||||
_check_auth_data_free (data);
|
||||
_call_id_invoke_callback (call_id, is_authorized, is_challenge, error);
|
||||
}
|
||||
|
||||
static void
|
||||
_call_check_authorization (CheckAuthData *data)
|
||||
_call_check_authorize (NMAuthManagerCallId *call_id)
|
||||
{
|
||||
NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (data->self);
|
||||
NMAuthManager *self = call_id->self;
|
||||
NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
|
||||
|
||||
nm_assert (call_id->dbus_parameters);
|
||||
nm_assert (g_variant_is_floating (call_id->dbus_parameters));
|
||||
nm_assert (!call_id->dbus_cancellable);
|
||||
|
||||
call_id->dbus_cancellable = g_cancellable_new ();
|
||||
|
||||
nm_assert (priv->cancel_cancellable);
|
||||
|
||||
g_dbus_proxy_call (priv->proxy,
|
||||
"CheckAuthorization",
|
||||
data->dbus_parameters,
|
||||
g_steal_pointer (&call_id->dbus_parameters),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
G_MAXINT, /* no timeout */
|
||||
data->cancellable,
|
||||
(GAsyncReadyCallback) check_authorization_cb,
|
||||
data);
|
||||
g_clear_object (&data->cancellable);
|
||||
data->dbus_parameters = NULL;
|
||||
call_id->dbus_cancellable,
|
||||
_call_check_authorize_cb,
|
||||
call_id);
|
||||
}
|
||||
|
||||
void
|
||||
nm_auth_manager_polkit_authority_check_authorization (NMAuthManager *self,
|
||||
NMAuthSubject *subject,
|
||||
const char *action_id,
|
||||
gboolean allow_user_interaction,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
static gboolean
|
||||
_call_on_idle (gpointer user_data)
|
||||
{
|
||||
NMAuthManagerCallId *call_id = user_data;
|
||||
gs_free_error GError *error = NULL;
|
||||
gboolean is_authorized = FALSE;
|
||||
gboolean is_challenge = FALSE;
|
||||
const char *error_msg = NULL;
|
||||
|
||||
call_id->idle_id = 0;
|
||||
if (call_id->idle_reason == IDLE_REASON_AUTHORIZED) {
|
||||
is_authorized = TRUE;
|
||||
_LOG2T (call_id, "completed: authorized=%d, challenge=%d (simulated)",
|
||||
is_authorized, is_challenge);
|
||||
} else {
|
||||
nm_assert (call_id->idle_reason == IDLE_REASON_NO_DBUS);
|
||||
error_msg = "failure creating GDBusProxy for authorization request";
|
||||
_LOG2T (call_id, "completed: failed due to no D-Bus proxy");
|
||||
}
|
||||
|
||||
if (error_msg)
|
||||
g_set_error_literal (&error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, error_msg);
|
||||
_call_id_invoke_callback (call_id, is_authorized, is_challenge, error);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
/*
|
||||
* @callback must never be invoked synchronously.
|
||||
*
|
||||
* @callback is always invoked exactly once, and never synchronously.
|
||||
* You may cancel the invocation with nm_auth_manager_check_authorization_cancel(),
|
||||
* but: you may only do so exactly once, and only before @callback is
|
||||
* invoked. Even if you cancel the request, @callback will still be invoked
|
||||
* (synchronously, during the _cancel() callback).
|
||||
*
|
||||
* The request keeps @self alive (it needs to do so, because when cancelling a
|
||||
* request we might need to do an additional CancelCheckAuthorization call, for
|
||||
* which @self must be live long enough).
|
||||
*/
|
||||
NMAuthManagerCallId *
|
||||
nm_auth_manager_check_authorization (NMAuthManager *self,
|
||||
NMAuthSubject *subject,
|
||||
const char *action_id,
|
||||
gboolean allow_user_interaction,
|
||||
NMAuthManagerCheckAuthorizationCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMAuthManagerPrivate *priv;
|
||||
PolkitCheckAuthorizationFlags flags;
|
||||
char subject_buf[64];
|
||||
GVariantBuilder builder;
|
||||
PolkitCheckAuthorizationFlags flags;
|
||||
GVariant *subject_value;
|
||||
GVariant *details_value;
|
||||
CheckAuthData *data;
|
||||
NMAuthManagerCallId *call_id;
|
||||
|
||||
g_return_if_fail (NM_IS_AUTH_MANAGER (self));
|
||||
g_return_if_fail (NM_IS_AUTH_SUBJECT (subject));
|
||||
g_return_if_fail (nm_auth_subject_is_unix_process (subject));
|
||||
g_return_if_fail (action_id != NULL);
|
||||
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||
g_return_val_if_fail (NM_IS_AUTH_MANAGER (self), NULL);
|
||||
g_return_val_if_fail (NM_IN_SET (nm_auth_subject_get_subject_type (subject),
|
||||
NM_AUTH_SUBJECT_TYPE_INTERNAL,
|
||||
NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS),
|
||||
NULL);
|
||||
g_return_val_if_fail (action_id, NULL);
|
||||
|
||||
priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
|
||||
|
||||
g_return_if_fail (priv->polkit_enabled);
|
||||
g_return_val_if_fail (!priv->disposing, NULL);
|
||||
g_return_val_if_fail (!priv->shutting_down, NULL);
|
||||
|
||||
flags = allow_user_interaction
|
||||
? POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION
|
||||
: POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE;
|
||||
|
||||
subject_value = nm_auth_subject_unix_process_to_polkit_gvariant (subject);
|
||||
nm_assert (g_variant_is_floating (subject_value));
|
||||
call_id = g_slice_new0 (NMAuthManagerCallId);
|
||||
call_id->self = g_object_ref (self);
|
||||
call_id->callback = callback;
|
||||
call_id->user_data = user_data;
|
||||
call_id->call_numid = ++priv->call_numid_counter;
|
||||
c_list_link_tail (&priv->calls_lst_head, &call_id->calls_lst);
|
||||
|
||||
/* ((PolkitDetails *)NULL) */
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}"));
|
||||
details_value = g_variant_builder_end (&builder);
|
||||
|
||||
data = g_new0 (CheckAuthData, 1);
|
||||
data->call_id = ++priv->call_id_counter;
|
||||
data->self = g_object_ref (self);
|
||||
data->simple = g_simple_async_result_new (G_OBJECT (self),
|
||||
callback,
|
||||
user_data,
|
||||
nm_auth_manager_polkit_authority_check_authorization);
|
||||
if (cancellable != NULL) {
|
||||
data->cancellation_id = g_strdup_printf ("cancellation-id-%u", data->call_id);
|
||||
data->cancellable = g_object_ref (cancellable);
|
||||
}
|
||||
|
||||
data->dbus_parameters = g_variant_new ("(@(sa{sv})s@a{ss}us)",
|
||||
subject_value,
|
||||
action_id,
|
||||
details_value,
|
||||
(guint32) flags,
|
||||
data->cancellation_id != NULL ? data->cancellation_id : "");
|
||||
|
||||
if (priv->new_proxy_cancellable) {
|
||||
_LOGD ("call[%u]: CheckAuthorization(%s), subject=%s (wait for proxy)", data->call_id, action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf)));
|
||||
|
||||
priv->queued_calls = g_slist_prepend (priv->queued_calls, data);
|
||||
} else if (!priv->proxy) {
|
||||
_LOGD ("call[%u]: CheckAuthorization(%s), subject=%s (fails due to invalid DBUS proxy)", data->call_id, action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf)));
|
||||
|
||||
_call_check_authorization_complete_with_error (data, "invalid DBUS proxy");
|
||||
if (!priv->polkit_enabled) {
|
||||
_LOG2T (call_id, "CheckAuthorization(%s), subject=%s (succeeding due to polkit authorization disabled)", action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf)));
|
||||
call_id->idle_reason = IDLE_REASON_AUTHORIZED;
|
||||
call_id->idle_id = g_idle_add (_call_on_idle, call_id);
|
||||
} else if (nm_auth_subject_is_internal (subject)) {
|
||||
_LOG2T (call_id, "CheckAuthorization(%s), subject=%s (succeeding for internal request)", action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf)));
|
||||
call_id->idle_reason = IDLE_REASON_AUTHORIZED;
|
||||
call_id->idle_id = g_idle_add (_call_on_idle, call_id);
|
||||
} else if (nm_auth_subject_get_unix_process_uid (subject) == 0) {
|
||||
_LOG2T (call_id, "CheckAuthorization(%s), subject=%s (succeeding for root)", action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf)));
|
||||
call_id->idle_reason = IDLE_REASON_AUTHORIZED;
|
||||
call_id->idle_id = g_idle_add (_call_on_idle, call_id);
|
||||
} else if ( !priv->proxy
|
||||
&& !priv->new_proxy_cancellable) {
|
||||
_LOG2T (call_id, "CheckAuthorization(%s), subject=%s (failing due to invalid DBUS proxy)", action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf)));
|
||||
call_id->idle_reason = IDLE_REASON_NO_DBUS;
|
||||
call_id->idle_id = g_idle_add (_call_on_idle, call_id);
|
||||
} else {
|
||||
_LOGD ("call[%u]: CheckAuthorization(%s), subject=%s", data->call_id, action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf)));
|
||||
subject_value = nm_auth_subject_unix_process_to_polkit_gvariant (subject);
|
||||
nm_assert (g_variant_is_floating (subject_value));
|
||||
|
||||
_call_check_authorization (data);
|
||||
/* ((PolkitDetails *)NULL) */
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}"));
|
||||
details_value = g_variant_builder_end (&builder);
|
||||
|
||||
call_id->dbus_parameters = g_variant_new ("(@(sa{sv})s@a{ss}us)",
|
||||
subject_value,
|
||||
action_id,
|
||||
details_value,
|
||||
(guint32) flags,
|
||||
cancellation_id_to_str_a (call_id->call_numid));
|
||||
if (!priv->proxy) {
|
||||
_LOG2T (call_id, "CheckAuthorization(%s), subject=%s (wait for proxy)", action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf)));
|
||||
} else {
|
||||
_LOG2T (call_id, "CheckAuthorization(%s), subject=%s", action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf)));
|
||||
_call_check_authorize (call_id);
|
||||
}
|
||||
}
|
||||
|
||||
return call_id;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_auth_manager_polkit_authority_check_authorization_finish (NMAuthManager *self,
|
||||
GAsyncResult *res,
|
||||
gboolean *out_is_authorized,
|
||||
gboolean *out_is_challenge,
|
||||
GError **error)
|
||||
void
|
||||
nm_auth_manager_check_authorization_cancel (NMAuthManagerCallId *call_id)
|
||||
{
|
||||
gboolean success = FALSE;
|
||||
gboolean is_authorized = FALSE;
|
||||
gboolean is_challenge = FALSE;
|
||||
NMAuthManager *self;
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
g_return_val_if_fail (NM_IS_AUTH_MANAGER (self), FALSE);
|
||||
g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (res), FALSE);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||
g_return_if_fail (call_id);
|
||||
|
||||
if (!g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) {
|
||||
CheckAuthorizationResult *result;
|
||||
self = call_id->self;
|
||||
|
||||
result = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res));
|
||||
is_authorized = !!result->is_authorized;
|
||||
is_challenge = !!result->is_challenge;
|
||||
success = TRUE;
|
||||
}
|
||||
g_assert ((success && !error) || (!success || error));
|
||||
g_return_if_fail (NM_IS_AUTH_MANAGER (self));
|
||||
g_return_if_fail (!c_list_is_empty (&call_id->calls_lst));
|
||||
|
||||
if (out_is_authorized)
|
||||
*out_is_authorized = is_authorized;
|
||||
if (out_is_challenge)
|
||||
*out_is_challenge = is_challenge;
|
||||
return success;
|
||||
nm_assert (c_list_contains (&NM_AUTH_MANAGER_GET_PRIVATE (self)->calls_lst_head, &call_id->calls_lst));
|
||||
|
||||
nm_utils_error_set_cancelled (&error, FALSE, "NMAuthManager");
|
||||
_LOG2T (call_id, "completed: failed due to call cancelled");
|
||||
_call_id_invoke_callback (call_id,
|
||||
FALSE,
|
||||
FALSE,
|
||||
error);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -350,14 +443,14 @@ static void
|
|||
_emit_changed_signal (NMAuthManager *self)
|
||||
{
|
||||
_LOGD ("emit changed signal");
|
||||
g_signal_emit_by_name (self, NM_AUTH_MANAGER_SIGNAL_CHANGED);
|
||||
g_signal_emit (self, signals[CHANGED_SIGNAL], 0);
|
||||
}
|
||||
|
||||
static void
|
||||
_log_name_owner (NMAuthManager *self, char **out_name_owner)
|
||||
{
|
||||
NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
|
||||
char *name_owner;
|
||||
gs_free char *name_owner = NULL;
|
||||
|
||||
name_owner = g_dbus_proxy_get_name_owner (priv->proxy);
|
||||
if (name_owner)
|
||||
|
|
@ -365,10 +458,7 @@ _log_name_owner (NMAuthManager *self, char **out_name_owner)
|
|||
else
|
||||
_LOGD ("dbus name owner: none");
|
||||
|
||||
if (out_name_owner)
|
||||
*out_name_owner = name_owner;
|
||||
else
|
||||
g_free (name_owner);
|
||||
NM_SET_OUT (out_name_owner, g_steal_pointer (&name_owner));
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -377,20 +467,16 @@ _dbus_on_name_owner_notify_cb (GObject *object,
|
|||
gpointer user_data)
|
||||
{
|
||||
NMAuthManager *self = user_data;
|
||||
NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
|
||||
char *name_owner;
|
||||
gs_free char *name_owner = NULL;
|
||||
|
||||
g_return_if_fail (priv->proxy == (void *) object);
|
||||
nm_assert (NM_AUTH_MANAGER_GET_PRIVATE (self)->proxy == (GDBusProxy *) object);
|
||||
|
||||
_log_name_owner (self, &name_owner);
|
||||
|
||||
if (!name_owner) {
|
||||
/* when the name disappears, we also want to raise a emit signal.
|
||||
* When it appears, we raise one already. */
|
||||
_emit_changed_signal (self);
|
||||
}
|
||||
|
||||
g_free (name_owner);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -398,9 +484,8 @@ _dbus_on_changed_signal_cb (GDBusProxy *proxy,
|
|||
gpointer user_data)
|
||||
{
|
||||
NMAuthManager *self = user_data;
|
||||
NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
|
||||
|
||||
g_return_if_fail (priv->proxy == proxy);
|
||||
nm_assert (NM_AUTH_MANAGER_GET_PRIVATE (self)->proxy == proxy);
|
||||
|
||||
_LOGD ("dbus signal: \"Changed\"");
|
||||
_emit_changed_signal (self);
|
||||
|
|
@ -411,49 +496,35 @@ _dbus_new_proxy_cb (GObject *source_object,
|
|||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMAuthManager **p_self = user_data;
|
||||
NMAuthManager *self = NULL;
|
||||
NMAuthManager *self;
|
||||
NMAuthManagerPrivate *priv;
|
||||
GError *error = NULL;
|
||||
gs_free GError *error = NULL;
|
||||
GDBusProxy *proxy;
|
||||
CheckAuthData *data;
|
||||
NMAuthManagerCallId *call_id;
|
||||
|
||||
proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
|
||||
|
||||
if (!*p_self) {
|
||||
_LOGD ("_dbus_new_proxy_cb(): manager destroyed before callback finished. Abort");
|
||||
g_clear_object (&proxy);
|
||||
g_clear_error (&error);
|
||||
g_free (p_self);
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
}
|
||||
self = *p_self;
|
||||
g_object_remove_weak_pointer (G_OBJECT (self), (void **)p_self);
|
||||
g_free (p_self);
|
||||
|
||||
self = user_data;
|
||||
priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
|
||||
|
||||
g_return_if_fail (priv->new_proxy_cancellable);
|
||||
g_return_if_fail (!priv->proxy);
|
||||
|
||||
priv->proxy = proxy;
|
||||
g_clear_object (&priv->new_proxy_cancellable);
|
||||
|
||||
priv->queued_calls = g_slist_reverse (priv->queued_calls);
|
||||
|
||||
priv->proxy = proxy;
|
||||
if (!priv->proxy) {
|
||||
_LOGE ("could not get polkit proxy: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
_LOGE ("could not create polkit proxy: %s", error->message);
|
||||
|
||||
while (priv->queued_calls) {
|
||||
data = priv->queued_calls->data;
|
||||
priv->queued_calls = g_slist_remove (priv->queued_calls, data);
|
||||
|
||||
_call_check_authorization_complete_with_error (data, "error creating DBUS proxy");
|
||||
while ((call_id = c_list_first_entry (&priv->calls_lst_head, NMAuthManagerCallId, calls_lst))) {
|
||||
_LOG2T (call_id, "completed: failed due to no D-Bus proxy after startup");
|
||||
_call_id_invoke_callback (call_id, FALSE, FALSE, error);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
priv->cancel_cancellable = g_cancellable_new ();
|
||||
|
||||
g_signal_connect (priv->proxy,
|
||||
"notify::g-name-owner",
|
||||
G_CALLBACK (_dbus_on_name_owner_notify_cb),
|
||||
|
|
@ -464,17 +535,14 @@ _dbus_new_proxy_cb (GObject *source_object,
|
|||
|
||||
_log_name_owner (self, NULL);
|
||||
|
||||
while (priv->queued_calls) {
|
||||
data = priv->queued_calls->data;
|
||||
priv->queued_calls = g_slist_remove (priv->queued_calls, data);
|
||||
_LOGD ("call[%u]: CheckAuthorization invoke now", data->call_id);
|
||||
_call_check_authorization (data);
|
||||
while ((call_id = c_list_first_entry (&priv->calls_lst_head, NMAuthManagerCallId, calls_lst))) {
|
||||
_LOG2T (call_id, "CheckAuthorization invoke now");
|
||||
_call_check_authorize (call_id);
|
||||
}
|
||||
|
||||
_emit_changed_signal (self);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMAuthManager *
|
||||
|
|
@ -485,23 +553,42 @@ nm_auth_manager_get ()
|
|||
return singleton_instance;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
void
|
||||
nm_auth_manager_force_shutdown (NMAuthManager *self)
|
||||
{
|
||||
NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE ((NMAuthManager *) object);
|
||||
NMAuthManagerPrivate *priv;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_POLKIT_ENABLED:
|
||||
g_value_set_boolean (value, priv->polkit_enabled);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
g_return_if_fail (NM_IS_AUTH_MANAGER (self));
|
||||
|
||||
priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
|
||||
|
||||
/* while we have pending requests (NMAuthManagerCallId), the instance
|
||||
* is kept alive.
|
||||
*
|
||||
* Even if the caller cancells all pending call-ids, we still need to keep
|
||||
* a reference to self, in order to handle pending CancelCheckAuthorization
|
||||
* requests.
|
||||
*
|
||||
* To do a corrdinated shutdown, do the following:
|
||||
* - cancel all pending NMAuthManagerCallId requests.
|
||||
* - ensure everybody unrefs the NMAuthManager instance. If by that, the instance
|
||||
* gets destroyed, the shutdown already completed successfully.
|
||||
* - Otherwise, the object is kept alive by pending CancelCheckAuthorization requests.
|
||||
* wait a certain timeout (1 second) for all requests to complete (by watching
|
||||
* for destruction of NMAuthManager).
|
||||
* - if that doesn't happen within timeout, issue nm_auth_manager_force_shutdown() and
|
||||
* wait longer. After that, soon the instance should be destroyed and you
|
||||
* did a successful shutdown.
|
||||
* - if the instance was still not destroyed within a short timeout, you leaked
|
||||
* resources. You cannot properly shutdown.
|
||||
*/
|
||||
|
||||
priv->shutting_down = TRUE;
|
||||
nm_clear_g_cancellable (&priv->cancel_cancellable);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
|
|
@ -523,6 +610,9 @@ set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *p
|
|||
static void
|
||||
nm_auth_manager_init (NMAuthManager *self)
|
||||
{
|
||||
NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
|
||||
|
||||
c_list_init (&priv->calls_lst_head);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -533,16 +623,10 @@ constructed (GObject *object)
|
|||
|
||||
G_OBJECT_CLASS (nm_auth_manager_parent_class)->constructed (object);
|
||||
|
||||
#if WITH_POLKIT
|
||||
_LOGD ("create auth-manager: polkit %s", priv->polkit_enabled ? "enabled" : "disabled");
|
||||
|
||||
if (priv->polkit_enabled) {
|
||||
NMAuthManager **p_self;
|
||||
|
||||
priv->new_proxy_cancellable = g_cancellable_new ();
|
||||
p_self = g_new (NMAuthManager *, 1);
|
||||
*p_self = self;
|
||||
g_object_add_weak_pointer (G_OBJECT (self), (void **) p_self);
|
||||
g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
|
||||
NULL,
|
||||
|
|
@ -551,14 +635,8 @@ constructed (GObject *object)
|
|||
POLKIT_INTERFACE,
|
||||
priv->new_proxy_cancellable,
|
||||
_dbus_new_proxy_cb,
|
||||
p_self);
|
||||
self);
|
||||
}
|
||||
#else
|
||||
if (priv->polkit_enabled)
|
||||
_LOGW ("create auth-manager: polkit disabled at compile time. All authentication requests will fail");
|
||||
else
|
||||
_LOGD ("create auth-manager: polkit disabled at compile time");
|
||||
#endif
|
||||
}
|
||||
|
||||
NMAuthManager *
|
||||
|
|
@ -585,23 +663,22 @@ static void
|
|||
dispose (GObject *object)
|
||||
{
|
||||
NMAuthManager* self = NM_AUTH_MANAGER (object);
|
||||
#if WITH_POLKIT
|
||||
NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
|
||||
#endif
|
||||
gs_free_error GError *error_disposing = NULL;
|
||||
|
||||
_LOGD ("dispose");
|
||||
|
||||
#if WITH_POLKIT
|
||||
/* since we take a reference for each queued call, we don't expect to have any queued calls in dispose() */
|
||||
g_assert (!priv->queued_calls);
|
||||
nm_assert (!c_list_is_empty (&priv->calls_lst_head));
|
||||
|
||||
priv->disposing = TRUE;
|
||||
|
||||
nm_clear_g_cancellable (&priv->new_proxy_cancellable);
|
||||
nm_clear_g_cancellable (&priv->cancel_cancellable);
|
||||
|
||||
if (priv->proxy) {
|
||||
g_signal_handlers_disconnect_by_data (priv->proxy, self);
|
||||
g_clear_object (&priv->proxy);
|
||||
}
|
||||
#endif
|
||||
|
||||
G_OBJECT_CLASS (nm_auth_manager_parent_class)->dispose (object);
|
||||
}
|
||||
|
|
@ -611,7 +688,6 @@ nm_auth_manager_class_init (NMAuthManagerClass *klass)
|
|||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->get_property = get_property;
|
||||
object_class->set_property = set_property;
|
||||
object_class->constructed = constructed;
|
||||
object_class->dispose = dispose;
|
||||
|
|
@ -619,7 +695,7 @@ nm_auth_manager_class_init (NMAuthManagerClass *klass)
|
|||
obj_properties[PROP_POLKIT_ENABLED] =
|
||||
g_param_spec_boolean (NM_AUTH_MANAGER_POLKIT_ENABLED, "", "",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_WRITABLE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
|
|
@ -628,11 +704,7 @@ nm_auth_manager_class_init (NMAuthManagerClass *klass)
|
|||
signals[CHANGED_SIGNAL] = g_signal_new (NM_AUTH_MANAGER_SIGNAL_CHANGED,
|
||||
NM_TYPE_AUTH_MANAGER,
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0, /* class offset */
|
||||
NULL, /* accumulator */
|
||||
NULL, /* accumulator data */
|
||||
0, NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE,
|
||||
0);
|
||||
G_TYPE_NONE, 0);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,31 @@
|
|||
|
||||
#include "nm-auth-subject.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef enum {
|
||||
NM_AUTH_CALL_RESULT_UNKNOWN,
|
||||
NM_AUTH_CALL_RESULT_YES,
|
||||
NM_AUTH_CALL_RESULT_AUTH,
|
||||
NM_AUTH_CALL_RESULT_NO,
|
||||
} NMAuthCallResult;
|
||||
|
||||
static inline NMAuthCallResult
|
||||
nm_auth_call_result_eval (gboolean is_authorized,
|
||||
gboolean is_challenge,
|
||||
GError *error)
|
||||
{
|
||||
if (error)
|
||||
return NM_AUTH_CALL_RESULT_UNKNOWN;
|
||||
if (is_authorized)
|
||||
return NM_AUTH_CALL_RESULT_YES;
|
||||
if (is_challenge)
|
||||
return NM_AUTH_CALL_RESULT_AUTH;
|
||||
return NM_AUTH_CALL_RESULT_NO;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define NM_TYPE_AUTH_MANAGER (nm_auth_manager_get_type ())
|
||||
#define NM_AUTH_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_AUTH_MANAGER, NMAuthManager))
|
||||
#define NM_AUTH_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_AUTH_MANAGER, NMAuthManagerClass))
|
||||
|
|
@ -42,23 +67,28 @@ GType nm_auth_manager_get_type (void);
|
|||
NMAuthManager *nm_auth_manager_setup (gboolean polkit_enabled);
|
||||
NMAuthManager *nm_auth_manager_get (void);
|
||||
|
||||
void nm_auth_manager_force_shutdown (NMAuthManager *self);
|
||||
|
||||
gboolean nm_auth_manager_get_polkit_enabled (NMAuthManager *self);
|
||||
|
||||
#if WITH_POLKIT
|
||||
/*****************************************************************************/
|
||||
|
||||
void nm_auth_manager_polkit_authority_check_authorization (NMAuthManager *self,
|
||||
NMAuthSubject *subject,
|
||||
const char *action_id,
|
||||
gboolean allow_user_interaction,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
gboolean nm_auth_manager_polkit_authority_check_authorization_finish (NMAuthManager *self,
|
||||
GAsyncResult *res,
|
||||
gboolean *out_is_authorized,
|
||||
gboolean *out_is_challenge,
|
||||
GError **error);
|
||||
typedef struct _NMAuthManagerCallId NMAuthManagerCallId;
|
||||
|
||||
#endif
|
||||
typedef void (*NMAuthManagerCheckAuthorizationCallback) (NMAuthManager *self,
|
||||
NMAuthManagerCallId *call_id,
|
||||
gboolean is_authorized,
|
||||
gboolean is_challenge,
|
||||
GError *error,
|
||||
gpointer user_data);
|
||||
|
||||
NMAuthManagerCallId *nm_auth_manager_check_authorization (NMAuthManager *self,
|
||||
NMAuthSubject *subject,
|
||||
const char *action_id,
|
||||
gboolean allow_user_interaction,
|
||||
NMAuthManagerCheckAuthorizationCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
void nm_auth_manager_check_authorization_cancel (NMAuthManagerCallId *call_id);
|
||||
|
||||
#endif /* NM_AUTH_MANAGER_H */
|
||||
|
|
|
|||
|
|
@ -34,19 +34,16 @@
|
|||
/*****************************************************************************/
|
||||
|
||||
struct NMAuthChain {
|
||||
GHashTable *data;
|
||||
GHashTable *data_hash;
|
||||
|
||||
CList auth_call_lst_head;
|
||||
|
||||
GDBusMethodInvocation *context;
|
||||
NMAuthSubject *subject;
|
||||
GError *error;
|
||||
|
||||
NMAuthChainResultFunc done_func;
|
||||
gpointer user_data;
|
||||
|
||||
guint idle_id;
|
||||
|
||||
guint32 refcount;
|
||||
|
||||
bool done:1;
|
||||
|
|
@ -55,9 +52,8 @@ struct NMAuthChain {
|
|||
typedef struct {
|
||||
CList auth_call_lst;
|
||||
NMAuthChain *chain;
|
||||
GCancellable *cancellable;
|
||||
NMAuthManagerCallId *call_id;
|
||||
char *permission;
|
||||
guint call_idle_id;
|
||||
} AuthCall;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -75,8 +71,8 @@ _ASSERT_call (AuthCall *call)
|
|||
static void
|
||||
auth_call_free (AuthCall *call)
|
||||
{
|
||||
nm_clear_g_source (&call->call_idle_id);
|
||||
nm_clear_g_cancellable (&call->cancellable);
|
||||
if (call->call_id)
|
||||
nm_auth_manager_check_authorization_cancel (call->call_id);
|
||||
c_list_unlink_stale (&call->auth_call_lst);
|
||||
g_free (call->permission);
|
||||
g_slice_free (AuthCall, call);
|
||||
|
|
@ -123,7 +119,9 @@ _get_data (NMAuthChain *self, const char *tag)
|
|||
{
|
||||
ChainData *tmp;
|
||||
|
||||
tmp = g_hash_table_lookup (self->data, &tag);
|
||||
if (!self->data_hash)
|
||||
return NULL;
|
||||
tmp = g_hash_table_lookup (self->data_hash, &tag);
|
||||
return tmp ? tmp->data : NULL;
|
||||
}
|
||||
|
||||
|
|
@ -156,7 +154,10 @@ nm_auth_chain_steal_data (NMAuthChain *self, const char *tag)
|
|||
g_return_val_if_fail (self, NULL);
|
||||
g_return_val_if_fail (tag, NULL);
|
||||
|
||||
tmp = g_hash_table_lookup (self->data, &tag);
|
||||
if (!self->data_hash)
|
||||
return NULL;
|
||||
|
||||
tmp = g_hash_table_lookup (self->data_hash, &tag);
|
||||
if (!tmp)
|
||||
return NULL;
|
||||
|
||||
|
|
@ -164,7 +165,7 @@ nm_auth_chain_steal_data (NMAuthChain *self, const char *tag)
|
|||
|
||||
/* Make sure the destroy handler isn't called when freeing */
|
||||
tmp->destroy = NULL;
|
||||
g_hash_table_remove (self->data, tmp);
|
||||
g_hash_table_remove (self->data_hash, tmp);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
|
@ -177,10 +178,15 @@ nm_auth_chain_set_data (NMAuthChain *self,
|
|||
g_return_if_fail (self);
|
||||
g_return_if_fail (tag);
|
||||
|
||||
if (data == NULL)
|
||||
g_hash_table_remove (self->data, &tag);
|
||||
else {
|
||||
g_hash_table_add (self->data,
|
||||
if (data == NULL) {
|
||||
if (self->data_hash)
|
||||
g_hash_table_remove (self->data_hash, &tag);
|
||||
} else {
|
||||
if (!self->data_hash) {
|
||||
self->data_hash = g_hash_table_new_full (nm_pstr_hash, nm_pstr_equal,
|
||||
NULL, chain_data_free);
|
||||
}
|
||||
g_hash_table_add (self->data_hash,
|
||||
chain_data_new (tag, data, data_destroy));
|
||||
}
|
||||
}
|
||||
|
|
@ -210,17 +216,16 @@ nm_auth_chain_get_subject (NMAuthChain *self)
|
|||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
auth_chain_finish (gpointer user_data)
|
||||
auth_chain_finish (NMAuthChain *self)
|
||||
{
|
||||
NMAuthChain *self = user_data;
|
||||
|
||||
self->idle_id = 0;
|
||||
self->done = TRUE;
|
||||
|
||||
/* Ensure we stay alive across the callback */
|
||||
nm_assert (self->refcount == 1);
|
||||
self->refcount++;
|
||||
self->done_func (self, self->error, self->context, self->user_data);
|
||||
nm_auth_chain_unref (self);
|
||||
self->done_func (self, NULL, self->context, self->user_data);
|
||||
nm_assert (NM_IN_SET (self->refcount, 1, 2));
|
||||
nm_auth_chain_destroy (self);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -233,71 +238,42 @@ auth_call_complete (AuthCall *call)
|
|||
|
||||
self = call->chain;
|
||||
|
||||
c_list_unlink (&call->auth_call_lst);
|
||||
|
||||
if (c_list_is_empty (&self->auth_call_lst_head)) {
|
||||
nm_assert (!self->idle_id && !self->done);
|
||||
self->idle_id = g_idle_add (auth_chain_finish, self);
|
||||
}
|
||||
nm_assert (!self->done);
|
||||
|
||||
auth_call_free (call);
|
||||
|
||||
if (c_list_is_empty (&self->auth_call_lst_head)) {
|
||||
/* we are on an idle-handler or a clean call-stack (non-reentrant). */
|
||||
auth_chain_finish (self);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
auth_call_complete_idle_cb (gpointer user_data)
|
||||
{
|
||||
AuthCall *call = user_data;
|
||||
|
||||
_ASSERT_call (call);
|
||||
|
||||
call->call_idle_id = 0;
|
||||
auth_call_complete (call);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
#if WITH_POLKIT
|
||||
static void
|
||||
pk_call_cb (GObject *object, GAsyncResult *result, gpointer user_data)
|
||||
pk_call_cb (NMAuthManager *auth_manager,
|
||||
NMAuthManagerCallId *call_id,
|
||||
gboolean is_authorized,
|
||||
gboolean is_challenge,
|
||||
GError *error,
|
||||
gpointer user_data)
|
||||
{
|
||||
AuthCall *call;
|
||||
gs_free_error GError *error = NULL;
|
||||
gboolean is_authorized = FALSE, is_challenge = FALSE;
|
||||
guint call_result = NM_AUTH_CALL_RESULT_UNKNOWN;
|
||||
NMAuthCallResult call_result;
|
||||
|
||||
nm_auth_manager_polkit_authority_check_authorization_finish (NM_AUTH_MANAGER (object),
|
||||
result,
|
||||
&is_authorized,
|
||||
&is_challenge,
|
||||
&error);
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
||||
nm_log_dbg (LOGD_CORE, "callback already cancelled");
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
}
|
||||
|
||||
call = user_data;
|
||||
|
||||
g_clear_object (&call->cancellable);
|
||||
nm_assert (call->call_id == call_id);
|
||||
|
||||
if (error) {
|
||||
/* Don't ruin the chain. Just leave the result unknown. */
|
||||
nm_log_warn (LOGD_CORE, "error requesting auth for %s: %s",
|
||||
call->permission, error->message);
|
||||
} else {
|
||||
if (is_authorized) {
|
||||
/* Caller has the permission */
|
||||
call_result = NM_AUTH_CALL_RESULT_YES;
|
||||
} else if (is_challenge) {
|
||||
/* Caller could authenticate to get the permission */
|
||||
call_result = NM_AUTH_CALL_RESULT_AUTH;
|
||||
} else
|
||||
call_result = NM_AUTH_CALL_RESULT_NO;
|
||||
}
|
||||
call->call_id = NULL;
|
||||
|
||||
call_result = nm_auth_call_result_eval (is_authorized, is_challenge, error);
|
||||
|
||||
nm_auth_chain_set_data (call->chain, call->permission, GUINT_TO_POINTER (call_result), NULL);
|
||||
|
||||
auth_call_complete (call);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
nm_auth_chain_add_call (NMAuthChain *self,
|
||||
|
|
@ -308,42 +284,21 @@ nm_auth_chain_add_call (NMAuthChain *self,
|
|||
NMAuthManager *auth_manager = nm_auth_manager_get ();
|
||||
|
||||
g_return_if_fail (self);
|
||||
g_return_if_fail (permission && *permission);
|
||||
g_return_if_fail (self->subject);
|
||||
g_return_if_fail (!self->done);
|
||||
g_return_if_fail (permission && *permission);
|
||||
g_return_if_fail (nm_auth_subject_is_unix_process (self->subject) || nm_auth_subject_is_internal (self->subject));
|
||||
g_return_if_fail (!self->idle_id && !self->done);
|
||||
|
||||
call = g_slice_new0 (AuthCall);
|
||||
call->chain = self;
|
||||
call->permission = g_strdup (permission);
|
||||
c_list_link_tail (&self->auth_call_lst_head, &call->auth_call_lst);
|
||||
|
||||
if ( nm_auth_subject_is_internal (self->subject)
|
||||
|| nm_auth_subject_get_unix_process_uid (self->subject) == 0
|
||||
|| !nm_auth_manager_get_polkit_enabled (auth_manager)) {
|
||||
/* Root user or non-polkit always gets the permission */
|
||||
nm_auth_chain_set_data (self, permission, GUINT_TO_POINTER (NM_AUTH_CALL_RESULT_YES), NULL);
|
||||
call->call_idle_id = g_idle_add (auth_call_complete_idle_cb, call);
|
||||
} else {
|
||||
/* Non-root always gets authenticated when using polkit */
|
||||
#if WITH_POLKIT
|
||||
call->cancellable = g_cancellable_new ();
|
||||
nm_auth_manager_polkit_authority_check_authorization (auth_manager,
|
||||
self->subject,
|
||||
permission,
|
||||
allow_interaction,
|
||||
call->cancellable,
|
||||
pk_call_cb,
|
||||
call);
|
||||
#else
|
||||
if (!call->chain->error) {
|
||||
call->chain->error = g_error_new_literal (NM_MANAGER_ERROR,
|
||||
NM_MANAGER_ERROR_FAILED,
|
||||
"Polkit support is disabled at compile time");
|
||||
}
|
||||
call->call_idle_id = g_idle_add (auth_call_complete_idle_cb, call);
|
||||
#endif
|
||||
}
|
||||
call->call_id = nm_auth_manager_check_authorization (auth_manager,
|
||||
self->subject,
|
||||
permission,
|
||||
allow_interaction,
|
||||
pk_call_cb,
|
||||
call);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -386,7 +341,6 @@ nm_auth_chain_new_subject (NMAuthSubject *subject,
|
|||
self = g_slice_new0 (NMAuthChain);
|
||||
c_list_init (&self->auth_call_lst_head);
|
||||
self->refcount = 1;
|
||||
self->data = g_hash_table_new_full (nm_pstr_hash, nm_pstr_equal, NULL, chain_data_free);
|
||||
self->done_func = done_func;
|
||||
self->user_data = user_data;
|
||||
self->context = context ? g_object_ref (context) : NULL;
|
||||
|
|
@ -395,36 +349,36 @@ nm_auth_chain_new_subject (NMAuthSubject *subject,
|
|||
}
|
||||
|
||||
/**
|
||||
* nm_auth_chain_unref:
|
||||
* nm_auth_chain_destroy:
|
||||
* @self: the auth-chain
|
||||
*
|
||||
* Unrefs the auth-chain. By unrefing the auth-chain, you also cancel
|
||||
* Destroys the auth-chain. By destroying the auth-chain, you also cancel
|
||||
* the receipt of the done-callback. IOW, the callback will not be invoked.
|
||||
*
|
||||
* The only exception is, if you call nm_auth_chain_unref() from inside
|
||||
* The only exception is, if may call nm_auth_chain_destroy() from inside
|
||||
* the callback. In this case, @self stays alive until the callback returns.
|
||||
*
|
||||
* Note that you might only destroy an auth-chain exactly once, and never
|
||||
* after the callback was handled.
|
||||
*/
|
||||
void
|
||||
nm_auth_chain_unref (NMAuthChain *self)
|
||||
nm_auth_chain_destroy (NMAuthChain *self)
|
||||
{
|
||||
AuthCall *call;
|
||||
|
||||
g_return_if_fail (self);
|
||||
g_return_if_fail (self->refcount > 0);
|
||||
g_return_if_fail (NM_IN_SET (self->refcount, 1, 2));
|
||||
|
||||
if (--self->refcount > 0)
|
||||
return;
|
||||
|
||||
nm_clear_g_source (&self->idle_id);
|
||||
|
||||
nm_clear_g_object (&self->subject);
|
||||
nm_clear_g_object (&self->context);
|
||||
|
||||
while ((call = c_list_first_entry (&self->auth_call_lst_head, AuthCall, auth_call_lst)))
|
||||
auth_call_free (call);
|
||||
|
||||
g_clear_error (&self->error);
|
||||
nm_clear_pointer (&self->data, g_hash_table_destroy);
|
||||
nm_clear_pointer (&self->data_hash, g_hash_table_destroy);
|
||||
|
||||
g_slice_free (NMAuthChain, self);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,14 +23,9 @@
|
|||
|
||||
#include "nm-connection.h"
|
||||
|
||||
typedef struct NMAuthChain NMAuthChain;
|
||||
#include "nm-auth-manager.h"
|
||||
|
||||
typedef enum {
|
||||
NM_AUTH_CALL_RESULT_UNKNOWN,
|
||||
NM_AUTH_CALL_RESULT_YES,
|
||||
NM_AUTH_CALL_RESULT_AUTH,
|
||||
NM_AUTH_CALL_RESULT_NO,
|
||||
} NMAuthCallResult;
|
||||
typedef struct NMAuthChain NMAuthChain;
|
||||
|
||||
typedef void (*NMAuthChainResultFunc) (NMAuthChain *chain,
|
||||
GError *error,
|
||||
|
|
@ -62,7 +57,7 @@ void nm_auth_chain_add_call (NMAuthChain *chain,
|
|||
const char *permission,
|
||||
gboolean allow_interaction);
|
||||
|
||||
void nm_auth_chain_unref (NMAuthChain *chain);
|
||||
void nm_auth_chain_destroy (NMAuthChain *chain);
|
||||
|
||||
/* Caller must free returned error description */
|
||||
gboolean nm_auth_is_subject_in_acl (NMConnection *connection,
|
||||
|
|
|
|||
|
|
@ -2234,7 +2234,13 @@ _log_connection_sort_names (LogConnectionSettingData *setting_data, GArray *sort
|
|||
}
|
||||
|
||||
void
|
||||
nm_utils_log_connection_diff (NMConnection *connection, NMConnection *diff_base, guint32 level, guint64 domain, const char *name, const char *prefix)
|
||||
nm_utils_log_connection_diff (NMConnection *connection,
|
||||
NMConnection *diff_base,
|
||||
guint32 level,
|
||||
guint64 domain,
|
||||
const char *name,
|
||||
const char *prefix,
|
||||
const char *dbus_path)
|
||||
{
|
||||
GHashTable *connection_diff = NULL;
|
||||
GArray *sorted_hashes;
|
||||
|
|
@ -2310,7 +2316,6 @@ nm_utils_log_connection_diff (NMConnection *connection, NMConnection *diff_base,
|
|||
|
||||
if (print_header) {
|
||||
GError *err_verify = NULL;
|
||||
const char *path = nm_connection_get_path (connection);
|
||||
const char *t1, *t2;
|
||||
|
||||
t1 = nm_connection_get_connection_type (connection);
|
||||
|
|
@ -2320,12 +2325,12 @@ nm_utils_log_connection_diff (NMConnection *connection, NMConnection *diff_base,
|
|||
prefix, name,
|
||||
connection, G_OBJECT_TYPE_NAME (connection), NM_PRINT_FMT_QUOTE_STRING (t1),
|
||||
diff_base, G_OBJECT_TYPE_NAME (diff_base), NM_PRINT_FMT_QUOTE_STRING (t2),
|
||||
NM_PRINT_FMT_QUOTED (path, " [", path, "]", ""));
|
||||
NM_PRINT_FMT_QUOTED (dbus_path, " [", dbus_path, "]", ""));
|
||||
} else {
|
||||
nm_log (level, domain, NULL, NULL, "%sconnection '%s' (%p/%s/%s%s%s):%s%s%s",
|
||||
prefix, name,
|
||||
connection, G_OBJECT_TYPE_NAME (connection), NM_PRINT_FMT_QUOTE_STRING (t1),
|
||||
NM_PRINT_FMT_QUOTED (path, " [", path, "]", ""));
|
||||
NM_PRINT_FMT_QUOTED (dbus_path, " [", dbus_path, "]", ""));
|
||||
}
|
||||
print_header = FALSE;
|
||||
|
||||
|
|
@ -3645,7 +3650,8 @@ nm_utils_setpgid (gpointer unused G_GNUC_UNUSED)
|
|||
/**
|
||||
* nm_utils_g_value_set_strv:
|
||||
* @value: a #GValue, initialized to store a #G_TYPE_STRV
|
||||
* @strings: a #GPtrArray of strings
|
||||
* @strings: a #GPtrArray of strings. %NULL values are not
|
||||
* allowed.
|
||||
*
|
||||
* Converts @strings to a #GStrv and stores it in @value.
|
||||
*/
|
||||
|
|
@ -3653,11 +3659,13 @@ void
|
|||
nm_utils_g_value_set_strv (GValue *value, GPtrArray *strings)
|
||||
{
|
||||
char **strv;
|
||||
int i;
|
||||
guint i;
|
||||
|
||||
strv = g_new (char *, strings->len + 1);
|
||||
for (i = 0; i < strings->len; i++)
|
||||
for (i = 0; i < strings->len; i++) {
|
||||
nm_assert (strings->pdata[i]);
|
||||
strv[i] = g_strdup (strings->pdata[i]);
|
||||
}
|
||||
strv[i] = NULL;
|
||||
|
||||
g_value_take_boxed (value, strv);
|
||||
|
|
|
|||
|
|
@ -231,7 +231,12 @@ const char *nm_utils_new_infiniband_name (char *name, const char *parent_name, i
|
|||
|
||||
int nm_utils_cmp_connection_by_autoconnect_priority (NMConnection *a, NMConnection *b);
|
||||
|
||||
void nm_utils_log_connection_diff (NMConnection *connection, NMConnection *diff_base, guint32 level, guint64 domain, const char *name, const char *prefix);
|
||||
void nm_utils_log_connection_diff (NMConnection *connection,
|
||||
NMConnection *diff_base,
|
||||
guint32 level, guint64 domain,
|
||||
const char *name,
|
||||
const char *prefix,
|
||||
const char *dbus_path);
|
||||
|
||||
gint64 nm_utils_get_monotonic_timestamp_ns (void);
|
||||
gint64 nm_utils_get_monotonic_timestamp_us (void);
|
||||
|
|
|
|||
|
|
@ -37,9 +37,13 @@ nm_dbus_object_set_quitting (void)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
NM_GOBJECT_PROPERTIES_DEFINE (NMDBusObject,
|
||||
PROP_PATH,
|
||||
);
|
||||
enum {
|
||||
EXPORTED_CHANGED,
|
||||
|
||||
LAST_SIGNAL,
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (NMDBusObject, nm_dbus_object, G_TYPE_OBJECT);
|
||||
|
||||
|
|
@ -53,6 +57,12 @@ G_DEFINE_ABSTRACT_TYPE (NMDBusObject, nm_dbus_object, G_TYPE_OBJECT);
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
_emit_exported_changed (NMDBusObject *self)
|
||||
{
|
||||
g_signal_emit (self, signals[EXPORTED_CHANGED], 0);
|
||||
}
|
||||
|
||||
static char *
|
||||
_create_export_path (NMDBusObjectClass *klass)
|
||||
{
|
||||
|
|
@ -107,6 +117,8 @@ nm_dbus_object_export (NMDBusObject *self)
|
|||
|
||||
g_return_val_if_fail (!self->internal.path, self->internal.path);
|
||||
|
||||
nm_assert (!self->internal.is_unexporting);
|
||||
|
||||
self->internal.path = _create_export_path (NM_DBUS_OBJECT_GET_CLASS (self));
|
||||
|
||||
self->internal.export_version_id = ++id_counter;
|
||||
|
|
@ -115,7 +127,7 @@ nm_dbus_object_export (NMDBusObject *self)
|
|||
|
||||
_nm_dbus_manager_obj_export (self);
|
||||
|
||||
_notify (self, PROP_PATH);
|
||||
_emit_exported_changed (self);
|
||||
return self->internal.path;
|
||||
}
|
||||
|
||||
|
|
@ -135,12 +147,27 @@ nm_dbus_object_unexport (NMDBusObject *self)
|
|||
|
||||
_LOGT ("unexport: \"%s\"", self->internal.path);
|
||||
|
||||
/* note that we emit the signal *before* actually unexporting the object.
|
||||
* The reason is, that listeners want to use this signal to know that
|
||||
* the object goes away, and clear their D-Bus path to this object.
|
||||
*
|
||||
* But this must happen before we actually unregister the object, so
|
||||
* that we first emit a D-Bus signal that other objects no longer
|
||||
* reference this object, before finally unregistering the object itself.
|
||||
*
|
||||
* The inconvenient part is, that at this point nm_dbus_object_get_path()
|
||||
* still returns the path. So, the callee needs to handle that. Possibly
|
||||
* by using "nm_dbus_object_get_path_still_exported()". */
|
||||
self->internal.is_unexporting = TRUE;
|
||||
|
||||
_emit_exported_changed (self);
|
||||
|
||||
_nm_dbus_manager_obj_unexport (self);
|
||||
|
||||
g_clear_pointer (&self->internal.path, g_free);
|
||||
self->internal.export_version_id = 0;
|
||||
|
||||
_notify (self, PROP_PATH);
|
||||
self->internal.is_unexporting = FALSE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -204,22 +231,6 @@ nm_dbus_object_emit_signal (NMDBusObject *self,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
NMDBusObject *self = NM_DBUS_OBJECT (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_PATH:
|
||||
g_value_set_string (value, self->internal.path);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dispatch_properties_changed (GObject *object,
|
||||
guint n_pspecs,
|
||||
|
|
@ -284,10 +295,11 @@ dispose (GObject *object)
|
|||
g_warn_if_reached ();
|
||||
nm_dbus_object_unexport (self);
|
||||
}
|
||||
} else if (nm_clear_g_free (&self->internal.path)) {
|
||||
} else if (self->internal.path) {
|
||||
/* FIXME: do a proper, coordinate shutdown, so that no objects stay
|
||||
* alive nor exported. */
|
||||
_notify (self, PROP_PATH);
|
||||
_emit_exported_changed (self);
|
||||
nm_clear_g_free (&self->internal.path);
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (nm_dbus_object_parent_class)->dispose (object);
|
||||
|
|
@ -302,14 +314,13 @@ nm_dbus_object_class_init (NMDBusObjectClass *klass)
|
|||
|
||||
object_class->constructed = constructed;
|
||||
object_class->dispose = dispose;
|
||||
object_class->get_property = get_property;
|
||||
object_class->dispatch_properties_changed = dispatch_properties_changed;
|
||||
|
||||
obj_properties[PROP_PATH] =
|
||||
g_param_spec_string (NM_DBUS_OBJECT_PATH, "", "",
|
||||
NULL,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
|
||||
signals[EXPORTED_CHANGED] =
|
||||
g_signal_new (NM_DBUS_OBJECT_EXPORTED_CHANGED,
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
0, NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ extern const NMDBusInterfaceInfoExtended nm_interface_info_device_statistics;
|
|||
#define NM_IS_DBUS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DBUS_OBJECT))
|
||||
#define NM_DBUS_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DBUS_OBJECT, NMDBusObjectClass))
|
||||
|
||||
#define NM_DBUS_OBJECT_PATH "path"
|
||||
#define NM_DBUS_OBJECT_EXPORTED_CHANGED "exported-changed"
|
||||
|
||||
/* NMDBusObject and NMDBusManager cooperate strongly. Hence, there is an
|
||||
* internal data structure attached to the NMDBusObject accessible to both of them. */
|
||||
|
|
@ -99,6 +99,7 @@ struct _NMDBusObjectInternal {
|
|||
* unexported, or even re-exported afterwards. If that happens, we want
|
||||
* to fail the request. For that, we keep track of a version id. */
|
||||
guint64 export_version_id;
|
||||
bool is_unexporting:1;
|
||||
};
|
||||
|
||||
struct _NMDBusObject {
|
||||
|
|
@ -169,6 +170,18 @@ nm_dbus_object_is_exported (NMDBusObject *self)
|
|||
return !!nm_dbus_object_get_path (self);
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
nm_dbus_object_get_path_still_exported (NMDBusObject *self)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_DBUS_OBJECT (self), NULL);
|
||||
|
||||
/* like nm_dbus_object_get_path(), however, while unexporting
|
||||
* (exported-changed signal), returns %NULL instead of the path. */
|
||||
return self->internal.is_unexporting
|
||||
? NULL
|
||||
: self->internal.path;
|
||||
}
|
||||
|
||||
const char *nm_dbus_object_export (NMDBusObject *self);
|
||||
void nm_dbus_object_unexport (NMDBusObject *self);
|
||||
|
||||
|
|
|
|||
|
|
@ -120,6 +120,20 @@ nm_dbus_utils_g_value_set_object_path (GValue *value, gpointer object)
|
|||
g_value_set_string (value, "/");
|
||||
}
|
||||
|
||||
void
|
||||
nm_dbus_utils_g_value_set_object_path_still_exported (GValue *value, gpointer object)
|
||||
{
|
||||
const char *path;
|
||||
|
||||
g_return_if_fail (!object || NM_IS_DBUS_OBJECT (object));
|
||||
|
||||
if ( object
|
||||
&& (path = nm_dbus_object_get_path_still_exported (object)))
|
||||
g_value_set_string (value, path);
|
||||
else
|
||||
g_value_set_string (value, "/");
|
||||
}
|
||||
|
||||
void
|
||||
nm_dbus_utils_g_value_set_object_path_from_hash (GValue *value,
|
||||
GHashTable *hash /* has keys of NMDBusObject type. */,
|
||||
|
|
@ -152,4 +166,143 @@ nm_dbus_utils_g_value_set_object_path_from_hash (GValue *value,
|
|||
g_value_take_boxed (value, strv);
|
||||
}
|
||||
|
||||
const char **
|
||||
nm_dbus_utils_get_paths_for_clist (const CList *lst_head,
|
||||
gssize lst_len,
|
||||
guint member_offset,
|
||||
gboolean expect_all_exported)
|
||||
{
|
||||
const CList *iter;
|
||||
const char **strv;
|
||||
const char *path;
|
||||
gsize i, n;
|
||||
|
||||
nm_assert (lst_head);
|
||||
|
||||
if (lst_len < 0)
|
||||
n = c_list_length (lst_head);
|
||||
else {
|
||||
n = lst_len;
|
||||
nm_assert (n == c_list_length (lst_head));
|
||||
}
|
||||
|
||||
i = 0;
|
||||
strv = g_new (const char *, n + 1);
|
||||
c_list_for_each (iter, lst_head) {
|
||||
NMDBusObject *obj = (NMDBusObject *) (((const char *) iter) - member_offset);
|
||||
|
||||
path = nm_dbus_object_get_path (obj);
|
||||
if (!path) {
|
||||
nm_assert (expect_all_exported);
|
||||
continue;
|
||||
}
|
||||
|
||||
nm_assert (i < n);
|
||||
strv[i++] = path;
|
||||
}
|
||||
nm_assert (i <= n);
|
||||
strv[i] = NULL;
|
||||
|
||||
return strv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void
|
||||
nm_dbus_track_obj_path_init (NMDBusTrackObjPath *track,
|
||||
GObject *target,
|
||||
const GParamSpec *pspec)
|
||||
{
|
||||
nm_assert (track);
|
||||
nm_assert (G_IS_OBJECT (target));
|
||||
nm_assert (G_IS_PARAM_SPEC (pspec));
|
||||
|
||||
track->_obj = NULL;
|
||||
track->_notify_target = target;
|
||||
track->_notify_pspec = pspec;
|
||||
track->_notify_signal_id = 0;
|
||||
track->_visible = FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
nm_dbus_track_obj_path_deinit (NMDBusTrackObjPath *track)
|
||||
{
|
||||
/* we allow deinit() to be called multiple times (e.g. from
|
||||
* dispose(), which must be re-entrant). */
|
||||
nm_assert (track);
|
||||
nm_assert (!track->_notify_target || G_IS_OBJECT (track->_notify_target));
|
||||
|
||||
nm_clear_g_signal_handler (track->obj, &track->_notify_signal_id);
|
||||
track->_notify_target = NULL;
|
||||
track->_notify_pspec = NULL;
|
||||
track->_visible = FALSE;
|
||||
nm_clear_g_object (&track->_obj);
|
||||
}
|
||||
|
||||
void
|
||||
nm_dbus_track_obj_path_notify (const NMDBusTrackObjPath *track)
|
||||
{
|
||||
nm_assert (track);
|
||||
nm_assert (G_IS_OBJECT (track->_notify_target));
|
||||
nm_assert (G_IS_PARAM_SPEC (track->_notify_pspec));
|
||||
|
||||
g_object_notify_by_pspec (track->_notify_target,
|
||||
(GParamSpec *) track->_notify_pspec);
|
||||
}
|
||||
|
||||
const char *
|
||||
nm_dbus_track_obj_path_get (const NMDBusTrackObjPath *track)
|
||||
{
|
||||
nm_assert (track);
|
||||
nm_assert (G_IS_OBJECT (track->_notify_target));
|
||||
|
||||
return track->obj && track->visible
|
||||
? nm_dbus_object_get_path_still_exported (track->obj)
|
||||
: NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_track_obj_exported_changed (NMDBusObject *obj,
|
||||
NMDBusTrackObjPath *track)
|
||||
{
|
||||
nm_dbus_track_obj_path_notify (track);
|
||||
}
|
||||
|
||||
void
|
||||
nm_dbus_track_obj_path_set (NMDBusTrackObjPath *track,
|
||||
gpointer obj,
|
||||
gboolean visible)
|
||||
{
|
||||
gs_unref_object NMDBusObject *old_obj = NULL;
|
||||
const char *old_path;
|
||||
|
||||
nm_assert (track);
|
||||
nm_assert (G_IS_OBJECT (track->_notify_target));
|
||||
|
||||
g_return_if_fail (!obj || NM_IS_DBUS_OBJECT (obj));
|
||||
|
||||
if ( track->obj == obj
|
||||
&& track->visible == !!visible)
|
||||
return;
|
||||
|
||||
old_path = nm_dbus_track_obj_path_get (track);
|
||||
|
||||
track->_visible = visible;
|
||||
|
||||
if (track->obj != obj) {
|
||||
nm_clear_g_signal_handler (track->obj, &track->_notify_signal_id);
|
||||
|
||||
old_obj = track->obj;
|
||||
track->_obj = nm_g_object_ref (obj);
|
||||
|
||||
if (obj) {
|
||||
track->_notify_signal_id = g_signal_connect (obj,
|
||||
NM_DBUS_OBJECT_EXPORTED_CHANGED,
|
||||
G_CALLBACK (_track_obj_exported_changed),
|
||||
track);
|
||||
}
|
||||
}
|
||||
|
||||
if (!nm_streq0 (old_path, nm_dbus_track_obj_path_get (track)))
|
||||
nm_dbus_track_obj_path_notify (track);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -164,10 +164,49 @@ GVariant *nm_dbus_utils_get_property (GObject *obj,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
struct CList;
|
||||
|
||||
const char **nm_dbus_utils_get_paths_for_clist (const struct CList *lst_head,
|
||||
gssize lst_len,
|
||||
guint member_offset,
|
||||
gboolean expect_all_exported);
|
||||
|
||||
void nm_dbus_utils_g_value_set_object_path (GValue *value, gpointer object);
|
||||
|
||||
void nm_dbus_utils_g_value_set_object_path_still_exported (GValue *value, gpointer object);
|
||||
|
||||
void nm_dbus_utils_g_value_set_object_path_from_hash (GValue *value,
|
||||
GHashTable *hash,
|
||||
gboolean expect_all_exported);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
gpointer const obj;
|
||||
gpointer _obj;
|
||||
};
|
||||
GObject *_notify_target;
|
||||
const GParamSpec *_notify_pspec;
|
||||
gulong _notify_signal_id;
|
||||
union {
|
||||
const bool visible;
|
||||
bool _visible;
|
||||
};
|
||||
} NMDBusTrackObjPath;
|
||||
|
||||
void nm_dbus_track_obj_path_init (NMDBusTrackObjPath *track,
|
||||
GObject *target,
|
||||
const GParamSpec *pspec);
|
||||
|
||||
void nm_dbus_track_obj_path_deinit (NMDBusTrackObjPath *track);
|
||||
|
||||
void nm_dbus_track_obj_path_notify (const NMDBusTrackObjPath *track);
|
||||
|
||||
const char *nm_dbus_track_obj_path_get (const NMDBusTrackObjPath *track);
|
||||
|
||||
void nm_dbus_track_obj_path_set (NMDBusTrackObjPath *track,
|
||||
gpointer obj,
|
||||
gboolean visible);
|
||||
|
||||
#endif /* __NM_DBUS_UTILS_H__ */
|
||||
|
|
|
|||
|
|
@ -579,7 +579,7 @@ _dispatcher_call (NMDispatcherAction action,
|
|||
const char *connection_path;
|
||||
const char *filename;
|
||||
|
||||
connection_path = nm_connection_get_path (NM_CONNECTION (settings_connection));
|
||||
connection_path = nm_dbus_object_get_path (NM_DBUS_OBJECT (settings_connection));
|
||||
if (connection_path) {
|
||||
g_variant_builder_add (&connection_props, "{sv}",
|
||||
NMD_CONNECTION_PROPS_PATH,
|
||||
|
|
|
|||
|
|
@ -953,7 +953,7 @@ _reload_auth_cb (NMAuthChain *chain,
|
|||
g_dbus_method_invocation_return_value (context, NULL);
|
||||
|
||||
out:
|
||||
nm_auth_chain_unref (chain);
|
||||
nm_auth_chain_destroy (chain);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -2100,7 +2100,7 @@ device_auth_done_cb (NMAuthChain *chain,
|
|||
nm_auth_chain_get_data (chain, "user-data"));
|
||||
|
||||
g_clear_error (&error);
|
||||
nm_auth_chain_unref (chain);
|
||||
nm_auth_chain_destroy (chain);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -2392,7 +2392,7 @@ recheck_assume_connection (NMManager *self,
|
|||
|
||||
if (!active) {
|
||||
_LOGW (LOGD_DEVICE, "assume: assumed connection %s failed to activate: %s",
|
||||
nm_connection_get_path (NM_CONNECTION (connection)),
|
||||
nm_dbus_object_get_path (NM_DBUS_OBJECT (connection)),
|
||||
error->message);
|
||||
g_error_free (error);
|
||||
|
||||
|
|
@ -4517,7 +4517,7 @@ activation_add_done (NMSettings *settings,
|
|||
g_dbus_method_invocation_return_value (
|
||||
context,
|
||||
g_variant_new ("(oo)",
|
||||
nm_connection_get_path (NM_CONNECTION (new_connection)),
|
||||
nm_dbus_object_get_path (NM_DBUS_OBJECT (new_connection)),
|
||||
nm_dbus_object_get_path (NM_DBUS_OBJECT (active))));
|
||||
nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD_ACTIVATE,
|
||||
nm_active_connection_get_settings_connection (active),
|
||||
|
|
@ -4796,7 +4796,7 @@ deactivate_net_auth_done_cb (NMAuthChain *chain,
|
|||
else
|
||||
g_dbus_method_invocation_return_value (context, NULL);
|
||||
|
||||
nm_auth_chain_unref (chain);
|
||||
nm_auth_chain_destroy (chain);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -5138,7 +5138,7 @@ sleep_auth_done_cb (NMAuthChain *chain,
|
|||
g_dbus_method_invocation_return_value (context, NULL);
|
||||
}
|
||||
|
||||
nm_auth_chain_unref (chain);
|
||||
nm_auth_chain_destroy (chain);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -5276,7 +5276,7 @@ enable_net_done_cb (NMAuthChain *chain,
|
|||
g_dbus_method_invocation_take_error (context, ret_error);
|
||||
}
|
||||
|
||||
nm_auth_chain_unref (chain);
|
||||
nm_auth_chain_destroy (chain);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -5384,7 +5384,7 @@ get_permissions_done_cb (NMAuthChain *chain,
|
|||
g_variant_new ("(a{ss})", &results));
|
||||
}
|
||||
|
||||
nm_auth_chain_unref (chain);
|
||||
nm_auth_chain_destroy (chain);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -5606,7 +5606,7 @@ check_connectivity_auth_done_cb (NMAuthChain *chain,
|
|||
}
|
||||
|
||||
out:
|
||||
nm_auth_chain_unref (chain);
|
||||
nm_auth_chain_destroy (chain);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -6017,7 +6017,7 @@ out:
|
|||
g_dbus_method_invocation_return_dbus_error (invocation, error_name, error_message);
|
||||
else
|
||||
g_dbus_method_invocation_return_value (invocation, NULL);
|
||||
nm_auth_chain_unref (chain);
|
||||
nm_auth_chain_destroy (chain);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -6152,7 +6152,7 @@ checkpoint_auth_done_cb (NMAuthChain *chain,
|
|||
else
|
||||
g_dbus_method_invocation_return_value (context, variant);
|
||||
|
||||
nm_auth_chain_unref (chain);
|
||||
nm_auth_chain_destroy (chain);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -6830,7 +6830,7 @@ dispose (GObject *object)
|
|||
g_slice_free (PlatformLinkCbData, data);
|
||||
}
|
||||
|
||||
g_slist_free_full (priv->auth_chains, (GDestroyNotify) nm_auth_chain_unref);
|
||||
g_slist_free_full (priv->auth_chains, (GDestroyNotify) nm_auth_chain_destroy);
|
||||
priv->auth_chains = NULL;
|
||||
|
||||
nm_clear_g_source (&priv->devices_inited_id);
|
||||
|
|
|
|||
|
|
@ -2321,10 +2321,9 @@ _deactivate_if_active (NMPolicy *self, NMSettingsConnection *connection)
|
|||
nm_assert (NM_IS_SETTINGS_CONNECTION (connection));
|
||||
|
||||
nm_manager_for_each_active_connection (priv->manager, ac, tmp_list) {
|
||||
NMActiveConnectionState state = nm_active_connection_get_state (ac);
|
||||
|
||||
if ( nm_active_connection_get_settings_connection (ac) == connection
|
||||
&& (state <= NM_ACTIVE_CONNECTION_STATE_ACTIVATED)) {
|
||||
&& (nm_active_connection_get_state (ac) <= NM_ACTIVE_CONNECTION_STATE_ACTIVATED)) {
|
||||
if (!nm_manager_deactivate_connection (priv->manager,
|
||||
ac,
|
||||
NM_DEVICE_STATE_REASON_CONNECTION_REMOVED,
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ typedef struct _NMDBusManager NMDBusManager;
|
|||
typedef struct _NMConfig NMConfig;
|
||||
typedef struct _NMConfigData NMConfigData;
|
||||
typedef struct _NMArpingManager NMArpingManager;
|
||||
typedef struct _NMConnectionProvider NMConnectionProvider;
|
||||
typedef struct _NMConnectivity NMConnectivity;
|
||||
typedef struct _NMDevice NMDevice;
|
||||
typedef struct _NMDhcp4Config NMDhcp4Config;
|
||||
|
|
|
|||
|
|
@ -360,7 +360,7 @@ agent_register_permissions_done (NMAuthChain *chain,
|
|||
request_add_agent (c_list_entry (iter, Request, lst_request), agent);
|
||||
}
|
||||
|
||||
nm_auth_chain_unref (chain);
|
||||
nm_auth_chain_destroy (chain);
|
||||
}
|
||||
|
||||
static NMSecretAgent *
|
||||
|
|
@ -539,7 +539,7 @@ request_free (Request *req)
|
|||
g_object_unref (req->con.connection);
|
||||
g_free (req->con.path);
|
||||
if (req->con.chain)
|
||||
nm_auth_chain_unref (req->con.chain);
|
||||
nm_auth_chain_destroy (req->con.chain);
|
||||
if (req->request_type == REQUEST_TYPE_CON_GET) {
|
||||
g_free (req->con.get.setting_name);
|
||||
g_strfreev (req->con.get.hints);
|
||||
|
|
@ -810,7 +810,7 @@ request_remove_agent (Request *req, NMSecretAgent *agent)
|
|||
case REQUEST_TYPE_CON_DEL:
|
||||
if (req->con.chain) {
|
||||
/* This cancels the pending authorization requests. */
|
||||
nm_auth_chain_unref (req->con.chain);
|
||||
nm_auth_chain_destroy (req->con.chain);
|
||||
req->con.chain = NULL;
|
||||
}
|
||||
break;
|
||||
|
|
@ -1047,7 +1047,7 @@ _con_get_request_start_validated (NMAuthChain *chain,
|
|||
_con_get_request_start_proceed (req, req->con.current_has_modify);
|
||||
}
|
||||
|
||||
nm_auth_chain_unref (chain);
|
||||
nm_auth_chain_destroy (chain);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1541,7 +1541,7 @@ agent_permissions_changed_done (NMAuthChain *chain,
|
|||
nm_secret_agent_add_permission (agent, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED, share_protected);
|
||||
nm_secret_agent_add_permission (agent, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN, share_open);
|
||||
|
||||
nm_auth_chain_unref (chain);
|
||||
nm_auth_chain_destroy (chain);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1616,7 +1616,7 @@ cancel_more:
|
|||
goto cancel_more;
|
||||
}
|
||||
|
||||
g_slist_free_full (priv->chains, (GDestroyNotify) nm_auth_chain_unref);
|
||||
g_slist_free_full (priv->chains, (GDestroyNotify) nm_auth_chain_destroy);
|
||||
priv->chains = NULL;
|
||||
|
||||
if (priv->agents) {
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "nm-config-data.h"
|
||||
#include "nm-dbus-interface.h"
|
||||
#include "nm-session-monitor.h"
|
||||
#include "nm-auth-manager.h"
|
||||
#include "nm-auth-utils.h"
|
||||
#include "nm-auth-subject.h"
|
||||
#include "nm-agent-manager.h"
|
||||
|
|
@ -80,7 +81,8 @@ typedef struct _NMSettingsConnectionPrivate {
|
|||
|
||||
NMSettingsAutoconnectBlockedReason autoconnect_blocked_reason:4;
|
||||
|
||||
GSList *pending_auths; /* List of pending authentication requests */
|
||||
/* List of pending authentication requests */
|
||||
CList auth_lst_head;
|
||||
|
||||
CList call_ids_lst_head; /* in-progress secrets requests */
|
||||
|
||||
|
|
@ -581,7 +583,7 @@ _update_prepare (NMSettingsConnection *self,
|
|||
if (!nm_connection_normalize (new_connection, NULL, NULL, error))
|
||||
return FALSE;
|
||||
|
||||
if ( nm_connection_get_path (NM_CONNECTION (self))
|
||||
if ( nm_dbus_object_get_path (NM_DBUS_OBJECT (self))
|
||||
&& g_strcmp0 (nm_settings_connection_get_uuid (self), nm_connection_get_uuid (new_connection)) != 0) {
|
||||
/* Updating the UUID is not allowed once the path is exported. */
|
||||
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
|
||||
|
|
@ -661,8 +663,10 @@ nm_settings_connection_update (NMSettingsConnection *self,
|
|||
NM_SETTING_COMPARE_FLAG_EXACT)) {
|
||||
gs_unref_object NMConnection *simple = NULL;
|
||||
|
||||
if (log_diff_name)
|
||||
nm_utils_log_connection_diff (replace_connection, NM_CONNECTION (self), LOGL_DEBUG, LOGD_CORE, log_diff_name, "++ ");
|
||||
if (log_diff_name) {
|
||||
nm_utils_log_connection_diff (replace_connection, NM_CONNECTION (self), LOGL_DEBUG, LOGD_CORE, log_diff_name, "++ ",
|
||||
nm_dbus_object_get_path (NM_DBUS_OBJECT (self)));
|
||||
}
|
||||
|
||||
/* Make a copy of agent-owned secrets because they won't be present in
|
||||
* the connection returned by plugins, as plugins return only what was
|
||||
|
|
@ -798,7 +802,7 @@ nm_settings_connection_delete (NMSettingsConnection *self,
|
|||
for_agents = nm_simple_connection_new_clone (NM_CONNECTION (self));
|
||||
nm_connection_clear_secrets (for_agents);
|
||||
nm_agent_manager_delete_secrets (priv->agent_mgr,
|
||||
nm_connection_get_path (NM_CONNECTION (self)),
|
||||
nm_dbus_object_get_path (NM_DBUS_OBJECT (self)),
|
||||
for_agents);
|
||||
g_object_unref (for_agents);
|
||||
|
||||
|
|
@ -1295,7 +1299,7 @@ nm_settings_connection_get_secrets (NMSettingsConnection *self,
|
|||
priv->last_secret_agent_version_id = nm_agent_manager_get_agent_version_id (priv->agent_mgr);
|
||||
|
||||
call_id_a = nm_agent_manager_get_secrets (priv->agent_mgr,
|
||||
nm_connection_get_path (NM_CONNECTION (self)),
|
||||
nm_dbus_object_get_path (NM_DBUS_OBJECT (self)),
|
||||
NM_CONNECTION (self),
|
||||
subject,
|
||||
existing_secrets,
|
||||
|
|
@ -1359,7 +1363,7 @@ nm_settings_connection_cancel_secrets (NMSettingsConnection *self,
|
|||
_get_secrets_cancel (self, call_id, FALSE);
|
||||
}
|
||||
|
||||
/**** User authorization **************************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef void (*AuthCallback) (NMSettingsConnection *self,
|
||||
GDBusMethodInvocation *context,
|
||||
|
|
@ -1367,46 +1371,61 @@ typedef void (*AuthCallback) (NMSettingsConnection *self,
|
|||
GError *error,
|
||||
gpointer data);
|
||||
|
||||
static void
|
||||
pk_auth_cb (NMAuthChain *chain,
|
||||
GError *chain_error,
|
||||
GDBusMethodInvocation *context,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMSettingsConnection *self = NM_SETTINGS_CONNECTION (user_data);
|
||||
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
|
||||
GError *error = NULL;
|
||||
NMAuthCallResult result;
|
||||
const char *perm;
|
||||
typedef struct {
|
||||
CList auth_lst;
|
||||
NMAuthManagerCallId *call_id;
|
||||
NMSettingsConnection *self;
|
||||
AuthCallback callback;
|
||||
gpointer callback_data;
|
||||
GDBusMethodInvocation *invocation;
|
||||
NMAuthSubject *subject;
|
||||
} AuthData;
|
||||
|
||||
priv->pending_auths = g_slist_remove (priv->pending_auths, chain);
|
||||
static void
|
||||
pk_auth_cb (NMAuthManager *auth_manager,
|
||||
NMAuthManagerCallId *auth_call_id,
|
||||
gboolean is_authorized,
|
||||
gboolean is_challenge,
|
||||
GError *auth_error,
|
||||
gpointer user_data)
|
||||
{
|
||||
AuthData *auth_data = user_data;
|
||||
NMSettingsConnection *self;
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
perm = nm_auth_chain_get_data (chain, "perm");
|
||||
g_assert (perm);
|
||||
result = nm_auth_chain_get_result (chain, perm);
|
||||
nm_assert (auth_data);
|
||||
nm_assert (NM_IS_SETTINGS_CONNECTION (auth_data->self));
|
||||
|
||||
/* If our NMSettingsConnection is already gone, do nothing */
|
||||
if (chain_error) {
|
||||
self = auth_data->self;
|
||||
|
||||
auth_data->call_id = NULL;
|
||||
|
||||
c_list_unlink (&auth_data->auth_lst);
|
||||
|
||||
if (g_error_matches (auth_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
||||
error = g_error_new (NM_SETTINGS_ERROR,
|
||||
NM_SETTINGS_ERROR_FAILED,
|
||||
"Error checking authorization: connection was deleted");
|
||||
} else if (auth_error) {
|
||||
error = g_error_new (NM_SETTINGS_ERROR,
|
||||
NM_SETTINGS_ERROR_FAILED,
|
||||
"Error checking authorization: %s",
|
||||
chain_error->message ? chain_error->message : "(unknown)");
|
||||
} else if (result != NM_AUTH_CALL_RESULT_YES) {
|
||||
auth_error->message);
|
||||
} else if (nm_auth_call_result_eval (is_authorized, is_challenge, auth_error) != NM_AUTH_CALL_RESULT_YES) {
|
||||
error = g_error_new_literal (NM_SETTINGS_ERROR,
|
||||
NM_SETTINGS_ERROR_PERMISSION_DENIED,
|
||||
"Insufficient privileges.");
|
||||
"Insufficient privileges");
|
||||
}
|
||||
|
||||
callback = nm_auth_chain_get_data (chain, "callback");
|
||||
callback_data = nm_auth_chain_get_data (chain, "callback-data");
|
||||
subject = nm_auth_chain_get_data (chain, "subject");
|
||||
callback (self, context, subject, error, callback_data);
|
||||
auth_data->callback (self,
|
||||
auth_data->invocation,
|
||||
auth_data->subject,
|
||||
error,
|
||||
auth_data->callback_data);
|
||||
|
||||
g_clear_error (&error);
|
||||
nm_auth_chain_unref (chain);
|
||||
g_object_unref (auth_data->invocation);
|
||||
g_object_unref (auth_data->subject);
|
||||
g_slice_free (AuthData, auth_data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1434,59 +1453,57 @@ _new_auth_subject (GDBusMethodInvocation *context, GError **error)
|
|||
return subject;
|
||||
}
|
||||
|
||||
/* may either invoke callback synchronously or asynchronously. */
|
||||
static void
|
||||
auth_start (NMSettingsConnection *self,
|
||||
GDBusMethodInvocation *context,
|
||||
GDBusMethodInvocation *invocation,
|
||||
NMAuthSubject *subject,
|
||||
const char *check_permission,
|
||||
AuthCallback callback,
|
||||
gpointer callback_data)
|
||||
{
|
||||
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
|
||||
NMAuthChain *chain;
|
||||
GError *error = NULL;
|
||||
AuthData *auth_data;
|
||||
char *error_desc = NULL;
|
||||
|
||||
g_return_if_fail (context != NULL);
|
||||
g_return_if_fail (NM_IS_AUTH_SUBJECT (subject));
|
||||
nm_assert (nm_dbus_object_is_exported (NM_DBUS_OBJECT (self)));
|
||||
nm_assert (G_IS_DBUS_METHOD_INVOCATION (invocation));
|
||||
nm_assert (NM_IS_AUTH_SUBJECT (subject));
|
||||
|
||||
/* Ensure the caller can view this connection */
|
||||
if (!nm_auth_is_subject_in_acl (NM_CONNECTION (self),
|
||||
subject,
|
||||
&error_desc)) {
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
error = g_error_new_literal (NM_SETTINGS_ERROR,
|
||||
NM_SETTINGS_ERROR_PERMISSION_DENIED,
|
||||
error_desc);
|
||||
g_free (error_desc);
|
||||
|
||||
callback (self, context, subject, error, callback_data);
|
||||
g_clear_error (&error);
|
||||
callback (self, invocation, subject, error, callback_data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!check_permission) {
|
||||
/* Don't need polkit auth, automatic success */
|
||||
callback (self, context, subject, NULL, callback_data);
|
||||
callback (self, invocation, 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, subject, 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 (chain, "subject", g_object_ref (subject), g_object_unref);
|
||||
nm_auth_chain_add_call (chain, check_permission, TRUE);
|
||||
auth_data = g_slice_new (AuthData);
|
||||
auth_data->self = self;
|
||||
auth_data->callback = callback;
|
||||
auth_data->callback_data = callback_data;
|
||||
auth_data->invocation = g_object_ref (invocation);
|
||||
auth_data->subject = g_object_ref (subject);
|
||||
c_list_link_tail (&priv->auth_lst_head, &auth_data->auth_lst);
|
||||
auth_data->call_id = nm_auth_manager_check_authorization (nm_auth_manager_get (),
|
||||
subject,
|
||||
check_permission,
|
||||
TRUE,
|
||||
pk_auth_cb,
|
||||
auth_data);
|
||||
}
|
||||
|
||||
/**** DBus method handlers ************************************/
|
||||
|
|
@ -1789,7 +1806,7 @@ update_auth_cb (NMSettingsConnection *self,
|
|||
secrets_filter_cb,
|
||||
GUINT_TO_POINTER (NM_SETTING_SECRET_FLAG_AGENT_OWNED));
|
||||
nm_agent_manager_save_secrets (info->agent_mgr,
|
||||
nm_connection_get_path (NM_CONNECTION (self)),
|
||||
nm_dbus_object_get_path (NM_DBUS_OBJECT (self)),
|
||||
for_agent,
|
||||
info->subject);
|
||||
}
|
||||
|
|
@ -2065,7 +2082,7 @@ get_modify_permission_basic (NMSettingsConnection *self)
|
|||
* request affects more than just the caller, require 'modify.system'.
|
||||
*/
|
||||
s_con = nm_connection_get_setting_connection (NM_CONNECTION (self));
|
||||
g_assert (s_con);
|
||||
nm_assert (s_con);
|
||||
if (nm_setting_connection_get_num_permissions (s_con) == 1)
|
||||
return NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN;
|
||||
|
||||
|
|
@ -2210,7 +2227,7 @@ dbus_clear_secrets_auth_cb (NMSettingsConnection *self,
|
|||
|
||||
/* Tell agents to remove secrets for this connection */
|
||||
nm_agent_manager_delete_secrets (priv->agent_mgr,
|
||||
nm_connection_get_path (NM_CONNECTION (self)),
|
||||
nm_dbus_object_get_path (NM_DBUS_OBJECT (self)),
|
||||
NM_CONNECTION (self));
|
||||
|
||||
nm_settings_connection_update (self,
|
||||
|
|
@ -2274,11 +2291,15 @@ void
|
|||
nm_settings_connection_signal_remove (NMSettingsConnection *self)
|
||||
{
|
||||
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
|
||||
AuthData *auth_data;
|
||||
|
||||
if (priv->removed)
|
||||
return;
|
||||
priv->removed = TRUE;
|
||||
|
||||
while ((auth_data = c_list_first_entry (&priv->auth_lst_head, AuthData, auth_lst)))
|
||||
nm_auth_manager_check_authorization_cancel (auth_data->call_id);
|
||||
|
||||
nm_dbus_object_emit_signal (NM_DBUS_OBJECT (self),
|
||||
&interface_info_settings_connection,
|
||||
&signal_info_removed,
|
||||
|
|
@ -2963,8 +2984,11 @@ nm_settings_connection_init (NMSettingsConnection *self)
|
|||
priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_SETTINGS_CONNECTION, NMSettingsConnectionPrivate);
|
||||
self->_priv = priv;
|
||||
|
||||
c_list_init (&self->_connections_lst);
|
||||
|
||||
priv->ready = TRUE;
|
||||
c_list_init (&priv->call_ids_lst_head);
|
||||
c_list_init (&priv->auth_lst_head);
|
||||
|
||||
priv->session_monitor = g_object_ref (nm_session_monitor_get ());
|
||||
priv->session_changed_id = g_signal_connect (priv->session_monitor,
|
||||
|
|
@ -3000,6 +3024,9 @@ dispose (GObject *object)
|
|||
|
||||
_LOGD ("disposing");
|
||||
|
||||
nm_assert (c_list_is_empty (&self->_connections_lst));
|
||||
nm_assert (c_list_is_empty (&priv->auth_lst_head));
|
||||
|
||||
/* Cancel in-progress secrets requests */
|
||||
if (priv->agent_mgr) {
|
||||
c_list_for_each_entry_safe (call_id, call_id_safe, &priv->call_ids_lst_head, call_ids_lst)
|
||||
|
|
@ -3017,10 +3044,6 @@ dispose (GObject *object)
|
|||
g_clear_object (&priv->system_secrets);
|
||||
g_clear_object (&priv->agent_secrets);
|
||||
|
||||
/* Cancel PolicyKit requests */
|
||||
g_slist_free_full (priv->pending_auths, (GDestroyNotify) nm_auth_chain_unref);
|
||||
priv->pending_auths = NULL;
|
||||
|
||||
g_clear_pointer (&priv->seen_bssids, g_hash_table_destroy);
|
||||
|
||||
set_visible (self, FALSE);
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ struct _NMSettingsConnectionPrivate;
|
|||
struct _NMSettingsConnection {
|
||||
NMDBusObject parent;
|
||||
struct _NMSettingsConnectionPrivate *_priv;
|
||||
CList _connections_lst;
|
||||
};
|
||||
|
||||
struct _NMSettingsConnectionClass {
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@
|
|||
#include "nm-utils.h"
|
||||
#include "nm-core-internal.h"
|
||||
|
||||
#include "nm-utils/nm-c-list.h"
|
||||
#include "nm-dbus-object.h"
|
||||
#include "devices/nm-device-ethernet.h"
|
||||
#include "nm-settings-connection.h"
|
||||
|
|
@ -119,17 +120,21 @@ typedef struct {
|
|||
GSList *auths;
|
||||
|
||||
GSList *plugins;
|
||||
gboolean connections_loaded;
|
||||
GHashTable *connections;
|
||||
|
||||
CList connections_lst_head;
|
||||
|
||||
NMSettingsConnection **connections_cached_list;
|
||||
GSList *unmanaged_specs;
|
||||
GSList *unrecognized_specs;
|
||||
|
||||
gboolean started;
|
||||
gboolean startup_complete;
|
||||
|
||||
NMHostnameManager *hostname_manager;
|
||||
|
||||
guint connections_len;
|
||||
|
||||
bool started:1;
|
||||
bool startup_complete:1;
|
||||
bool connections_loaded:1;
|
||||
|
||||
} NMSettingsPrivate;
|
||||
|
||||
struct _NMSettings {
|
||||
|
|
@ -166,27 +171,29 @@ static void connection_ready_changed (NMSettingsConnection *conn,
|
|||
GParamSpec *pspec,
|
||||
gpointer user_data);
|
||||
|
||||
static void default_wired_clear_tag (NMSettings *self,
|
||||
NMDevice *device,
|
||||
NMSettingsConnection *connection,
|
||||
gboolean add_to_no_auto_default);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
check_startup_complete (NMSettings *self)
|
||||
{
|
||||
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
|
||||
GHashTableIter iter;
|
||||
NMSettingsConnection *conn;
|
||||
|
||||
if (priv->startup_complete)
|
||||
return;
|
||||
|
||||
g_hash_table_iter_init (&iter, priv->connections);
|
||||
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &conn)) {
|
||||
c_list_for_each_entry (conn, &priv->connections_lst_head, _connections_lst) {
|
||||
if (!nm_settings_connection_get_ready (conn))
|
||||
return;
|
||||
}
|
||||
|
||||
/* the connection_ready_changed signal handler is no longer needed. */
|
||||
g_hash_table_iter_init (&iter, priv->connections);
|
||||
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &conn))
|
||||
c_list_for_each_entry (conn, &priv->connections_lst_head, _connections_lst)
|
||||
g_signal_handlers_disconnect_by_func (conn, G_CALLBACK (connection_ready_changed), self);
|
||||
|
||||
priv->startup_complete = TRUE;
|
||||
|
|
@ -249,48 +256,25 @@ load_connections (NMSettings *self)
|
|||
unrecognized_specs_changed (NULL, self);
|
||||
}
|
||||
|
||||
void
|
||||
nm_settings_for_each_connection (NMSettings *self,
|
||||
NMSettingsForEachFunc for_each_func,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMSettingsPrivate *priv;
|
||||
GHashTableIter iter;
|
||||
gpointer data;
|
||||
|
||||
g_return_if_fail (NM_IS_SETTINGS (self));
|
||||
g_return_if_fail (for_each_func != NULL);
|
||||
|
||||
priv = NM_SETTINGS_GET_PRIVATE (self);
|
||||
|
||||
g_hash_table_iter_init (&iter, priv->connections);
|
||||
while (g_hash_table_iter_next (&iter, NULL, &data))
|
||||
for_each_func (self, NM_SETTINGS_CONNECTION (data), user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
impl_settings_list_connections (NMDBusObject *obj,
|
||||
const NMDBusInterfaceInfoExtended *interface_info,
|
||||
const NMDBusMethodInfoExtended *method_info,
|
||||
GDBusConnection *connection,
|
||||
GDBusConnection *dbus_connection,
|
||||
const char *sender,
|
||||
GDBusMethodInvocation *invocation,
|
||||
GVariant *parameters)
|
||||
{
|
||||
NMSettings *self = NM_SETTINGS (obj);
|
||||
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
|
||||
gs_unref_ptrarray GPtrArray *connections = NULL;
|
||||
GHashTableIter iter;
|
||||
gpointer key;
|
||||
|
||||
connections = g_ptr_array_sized_new (g_hash_table_size (priv->connections) + 1);
|
||||
g_hash_table_iter_init (&iter, priv->connections);
|
||||
while (g_hash_table_iter_next (&iter, &key, NULL))
|
||||
g_ptr_array_add (connections, key);
|
||||
g_ptr_array_add (connections, NULL);
|
||||
gs_free const char **strv = NULL;
|
||||
|
||||
strv = nm_dbus_utils_get_paths_for_clist (&priv->connections_lst_head,
|
||||
priv->connections_len,
|
||||
G_STRUCT_OFFSET (NMSettingsConnection, _connections_lst),
|
||||
TRUE);
|
||||
g_dbus_method_invocation_return_value (invocation,
|
||||
g_variant_new ("(^ao)", connections->pdata));
|
||||
g_variant_new ("(^ao)", strv));
|
||||
}
|
||||
|
||||
NMSettingsConnection *
|
||||
|
|
@ -298,16 +282,14 @@ nm_settings_get_connection_by_uuid (NMSettings *self, const char *uuid)
|
|||
{
|
||||
NMSettingsPrivate *priv;
|
||||
NMSettingsConnection *candidate;
|
||||
GHashTableIter iter;
|
||||
|
||||
g_return_val_if_fail (NM_IS_SETTINGS (self), NULL);
|
||||
g_return_val_if_fail (uuid != NULL, NULL);
|
||||
|
||||
priv = NM_SETTINGS_GET_PRIVATE (self);
|
||||
|
||||
g_hash_table_iter_init (&iter, priv->connections);
|
||||
while (g_hash_table_iter_next (&iter, NULL, (gpointer) &candidate)) {
|
||||
if (g_strcmp0 (uuid, nm_settings_connection_get_uuid (candidate)) == 0)
|
||||
c_list_for_each_entry (candidate, &priv->connections_lst_head, _connections_lst) {
|
||||
if (nm_streq (uuid, nm_settings_connection_get_uuid (candidate)))
|
||||
return candidate;
|
||||
}
|
||||
|
||||
|
|
@ -360,7 +342,7 @@ impl_settings_get_connection_by_uuid (NMDBusObject *obj,
|
|||
|
||||
g_dbus_method_invocation_return_value (invocation,
|
||||
g_variant_new ("(o)",
|
||||
nm_connection_get_path (NM_CONNECTION (connection))));
|
||||
nm_dbus_object_get_path (NM_DBUS_OBJECT (connection))));
|
||||
return;
|
||||
|
||||
error:
|
||||
|
|
@ -368,19 +350,23 @@ error:
|
|||
}
|
||||
|
||||
static void
|
||||
_clear_connections_cached_list (NMSettingsConnection ***p_connections_cached_list)
|
||||
_clear_connections_cached_list (NMSettingsPrivate *priv)
|
||||
{
|
||||
if (!priv->connections_cached_list)
|
||||
return;
|
||||
|
||||
nm_assert (priv->connections_len == NM_PTRARRAY_LEN (priv->connections_cached_list));
|
||||
|
||||
#if NM_MORE_ASSERTS
|
||||
/* set the pointer to a bogus value. This makes it more apparent
|
||||
* if somebody has a reference to the cached list and still uses
|
||||
* it. That is a bug, this code just tries to make it blow up
|
||||
* more eagerly. */
|
||||
if (*p_connections_cached_list) {
|
||||
NMSettingsConnection **p = *p_connections_cached_list;
|
||||
memset (p, 0xdeaddead, sizeof (NMSettingsConnection *) * (NM_PTRARRAY_LEN (p) + 1));
|
||||
}
|
||||
memset (priv->connections_cached_list,
|
||||
0xdeaddead,
|
||||
sizeof (NMSettingsConnection *) * (priv->connections_len + 1));
|
||||
#endif
|
||||
g_clear_pointer (p_connections_cached_list, g_free);
|
||||
nm_clear_g_free (&priv->connections_cached_list);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -398,37 +384,33 @@ _clear_connections_cached_list (NMSettingsConnection ***p_connections_cached_lis
|
|||
NMSettingsConnection *const*
|
||||
nm_settings_get_connections (NMSettings *self, guint *out_len)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
NMSettingsPrivate *priv;
|
||||
guint l, i;
|
||||
NMSettingsConnection **v;
|
||||
NMSettingsConnection *con;
|
||||
guint i;
|
||||
|
||||
g_return_val_if_fail (NM_IS_SETTINGS (self), NULL);
|
||||
|
||||
priv = NM_SETTINGS_GET_PRIVATE (self);
|
||||
|
||||
if (G_LIKELY (priv->connections_cached_list)) {
|
||||
NM_SET_OUT (out_len, g_hash_table_size (priv->connections));
|
||||
return priv->connections_cached_list;
|
||||
nm_assert (priv->connections_len == c_list_length (&priv->connections_lst_head));
|
||||
|
||||
if (G_UNLIKELY (!priv->connections_cached_list)) {
|
||||
v = g_new (NMSettingsConnection *, priv->connections_len + 1);
|
||||
|
||||
i = 0;
|
||||
c_list_for_each_entry (con, &priv->connections_lst_head, _connections_lst) {
|
||||
nm_assert (i < priv->connections_len);
|
||||
v[i++] = con;
|
||||
}
|
||||
nm_assert (i == priv->connections_len);
|
||||
v[i] = NULL;
|
||||
|
||||
priv->connections_cached_list = v;
|
||||
}
|
||||
|
||||
l = g_hash_table_size (priv->connections);
|
||||
|
||||
v = g_new (NMSettingsConnection *, (gsize) l + 1);
|
||||
|
||||
i = 0;
|
||||
g_hash_table_iter_init (&iter, priv->connections);
|
||||
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &con)) {
|
||||
nm_assert (i < l);
|
||||
v[i++] = con;
|
||||
}
|
||||
nm_assert (i == l);
|
||||
v[i] = NULL;
|
||||
|
||||
NM_SET_OUT (out_len, l);
|
||||
priv->connections_cached_list = v;
|
||||
return v;
|
||||
NM_SET_OUT (out_len, priv->connections_len);
|
||||
return priv->connections_cached_list;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -495,28 +477,41 @@ NMSettingsConnection *
|
|||
nm_settings_get_connection_by_path (NMSettings *self, const char *path)
|
||||
{
|
||||
NMSettingsPrivate *priv;
|
||||
NMSettingsConnection *connection;
|
||||
|
||||
g_return_val_if_fail (NM_IS_SETTINGS (self), NULL);
|
||||
g_return_val_if_fail (path != NULL, NULL);
|
||||
g_return_val_if_fail (path, NULL);
|
||||
|
||||
priv = NM_SETTINGS_GET_PRIVATE (self);
|
||||
|
||||
return (NMSettingsConnection *) g_hash_table_lookup (priv->connections, path);
|
||||
connection = (NMSettingsConnection *) nm_dbus_manager_lookup_object (nm_dbus_object_get_manager (NM_DBUS_OBJECT (self)),
|
||||
path);
|
||||
if ( !connection
|
||||
|| !NM_IS_SETTINGS_CONNECTION (connection))
|
||||
return NULL;
|
||||
|
||||
nm_assert (c_list_contains (&priv->connections_lst_head, &connection->_connections_lst));
|
||||
return connection;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_settings_has_connection (NMSettings *self, NMSettingsConnection *connection)
|
||||
{
|
||||
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
|
||||
GHashTableIter iter;
|
||||
gpointer data;
|
||||
NMSettingsConnection *candidate = NULL;
|
||||
const char *path;
|
||||
|
||||
g_hash_table_iter_init (&iter, priv->connections);
|
||||
while (g_hash_table_iter_next (&iter, NULL, &data))
|
||||
if (data == connection)
|
||||
return TRUE;
|
||||
g_return_val_if_fail (NM_IS_SETTINGS (self), FALSE);
|
||||
g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION (connection), FALSE);
|
||||
|
||||
return FALSE;
|
||||
path = nm_dbus_object_get_path (NM_DBUS_OBJECT (connection));
|
||||
if (path)
|
||||
candidate = nm_settings_get_connection_by_path (self, path);
|
||||
|
||||
nm_assert (!candidate || candidate == connection);
|
||||
nm_assert (!!candidate == nm_c_list_contains_entry (&NM_SETTINGS_GET_PRIVATE (self)->connections_lst_head,
|
||||
connection,
|
||||
_connections_lst));
|
||||
return !!candidate;
|
||||
}
|
||||
|
||||
const GSList *
|
||||
|
|
@ -843,29 +838,25 @@ connection_flags_changed (NMSettingsConnection *connection,
|
|||
connection);
|
||||
}
|
||||
|
||||
static void
|
||||
_emit_connection_removed (NMSettings *self,
|
||||
NMSettingsConnection *connection)
|
||||
{
|
||||
nm_dbus_object_emit_signal (NM_DBUS_OBJECT (self),
|
||||
&interface_info_settings,
|
||||
&signal_info_connection_removed,
|
||||
"(o)",
|
||||
nm_connection_get_path (NM_CONNECTION (connection)));
|
||||
|
||||
g_signal_emit (self, signals[CONNECTION_REMOVED], 0, connection);
|
||||
}
|
||||
|
||||
static void
|
||||
connection_removed (NMSettingsConnection *connection, gpointer user_data)
|
||||
{
|
||||
NMSettings *self = NM_SETTINGS (user_data);
|
||||
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
|
||||
const char *cpath = nm_connection_get_path (NM_CONNECTION (connection));
|
||||
NMDevice *device;
|
||||
|
||||
if (!g_hash_table_lookup (priv->connections, cpath))
|
||||
g_return_if_reached ();
|
||||
g_object_ref (connection);
|
||||
g_return_if_fail (NM_IS_SETTINGS_CONNECTION (connection));
|
||||
g_return_if_fail (!c_list_is_empty (&connection->_connections_lst));
|
||||
nm_assert (c_list_contains (&priv->connections_lst_head, &connection->_connections_lst));
|
||||
|
||||
/* When the default wired connection is removed (either deleted or saved to
|
||||
* a new persistent connection by a plugin), write the MAC address of the
|
||||
* wired device to the config file and don't create a new default wired
|
||||
* connection for that device again.
|
||||
*/
|
||||
device = g_object_get_qdata (G_OBJECT (connection), _default_wired_device_quark ());
|
||||
if (device)
|
||||
default_wired_clear_tag (self, device, connection, TRUE);
|
||||
|
||||
/* Disconnect signal handlers, as plugins might still keep references
|
||||
* to the connection (and thus the signal handlers would still be live)
|
||||
|
|
@ -877,22 +868,30 @@ connection_removed (NMSettingsConnection *connection, gpointer user_data)
|
|||
g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (connection_flags_changed), self);
|
||||
if (!priv->startup_complete)
|
||||
g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (connection_ready_changed), self);
|
||||
g_object_unref (self);
|
||||
|
||||
/* Forget about the connection internally */
|
||||
g_hash_table_remove (priv->connections, (gpointer) cpath);
|
||||
_clear_connections_cached_list (&priv->connections_cached_list);
|
||||
_clear_connections_cached_list (priv);
|
||||
priv->connections_len--;
|
||||
c_list_unlink (&connection->_connections_lst);
|
||||
|
||||
_emit_connection_removed (self, connection);
|
||||
if (priv->connections_loaded) {
|
||||
_notify (self, PROP_CONNECTIONS);
|
||||
|
||||
/* Re-emit for listeners like NMPolicy */
|
||||
_notify (self, PROP_CONNECTIONS);
|
||||
if (nm_dbus_object_is_exported (NM_DBUS_OBJECT (connection)))
|
||||
nm_dbus_object_unexport (NM_DBUS_OBJECT (connection));
|
||||
nm_dbus_object_emit_signal (NM_DBUS_OBJECT (self),
|
||||
&interface_info_settings,
|
||||
&signal_info_connection_removed,
|
||||
"(o)",
|
||||
nm_dbus_object_get_path (NM_DBUS_OBJECT (connection)));
|
||||
}
|
||||
|
||||
nm_dbus_object_unexport (NM_DBUS_OBJECT (connection));
|
||||
|
||||
if (priv->connections_loaded)
|
||||
g_signal_emit (self, signals[CONNECTION_REMOVED], 0, connection);
|
||||
|
||||
g_object_ref (connection);
|
||||
|
||||
check_startup_complete (self);
|
||||
|
||||
g_object_unref (connection);
|
||||
}
|
||||
|
||||
#define NM_DBUS_SERVICE_OPENCONNECT "org.freedesktop.NetworkManager.openconnect"
|
||||
|
|
@ -940,19 +939,16 @@ claim_connection (NMSettings *self, NMSettingsConnection *connection)
|
|||
{
|
||||
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
|
||||
GError *error = NULL;
|
||||
GHashTableIter iter;
|
||||
gpointer data;
|
||||
const char *path;
|
||||
NMSettingsConnection *existing;
|
||||
|
||||
g_return_if_fail (NM_IS_SETTINGS_CONNECTION (connection));
|
||||
g_return_if_fail (nm_connection_get_path (NM_CONNECTION (connection)) == NULL);
|
||||
g_return_if_fail (!nm_dbus_object_is_exported (NM_DBUS_OBJECT (connection)));
|
||||
|
||||
g_hash_table_iter_init (&iter, priv->connections);
|
||||
while (g_hash_table_iter_next (&iter, NULL, &data)) {
|
||||
/* prevent duplicates */
|
||||
if (data == connection)
|
||||
return;
|
||||
/* prevent duplicates */
|
||||
if (!c_list_is_empty (&connection->_connections_lst)) {
|
||||
nm_assert (c_list_contains (&priv->connections_lst_head, &connection->_connections_lst));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!nm_connection_normalize (NM_CONNECTION (connection), NULL, NULL, &error)) {
|
||||
|
|
@ -990,7 +986,6 @@ claim_connection (NMSettings *self, NMSettingsConnection *connection)
|
|||
/* Evil openconnect migration hack */
|
||||
openconnect_migrate_hack (NM_CONNECTION (connection));
|
||||
|
||||
g_object_ref (self);
|
||||
/* This one unexports the connection, it needs to run late to give the active
|
||||
* connection a chance to deal with its reference to this settings connection. */
|
||||
g_signal_connect_after (connection, NM_SETTINGS_CONNECTION_REMOVED,
|
||||
|
|
@ -1006,17 +1001,15 @@ claim_connection (NMSettings *self, NMSettingsConnection *connection)
|
|||
self);
|
||||
}
|
||||
|
||||
/* Export the connection over D-Bus */
|
||||
g_warn_if_fail (nm_connection_get_path (NM_CONNECTION (connection)) == NULL);
|
||||
_clear_connections_cached_list (priv);
|
||||
|
||||
priv->connections_len++;
|
||||
c_list_link_tail (&priv->connections_lst_head, &connection->_connections_lst);
|
||||
|
||||
path = nm_dbus_object_export (NM_DBUS_OBJECT (connection));
|
||||
nm_connection_set_path (NM_CONNECTION (connection), path);
|
||||
|
||||
g_hash_table_insert (priv->connections,
|
||||
(gpointer) nm_connection_get_path (NM_CONNECTION (connection)),
|
||||
g_object_ref (connection));
|
||||
_clear_connections_cached_list (&priv->connections_cached_list);
|
||||
|
||||
nm_utils_log_connection_diff (NM_CONNECTION (connection), NULL, LOGL_DEBUG, LOGD_CORE, "new connection", "++ ");
|
||||
nm_utils_log_connection_diff (NM_CONNECTION (connection), NULL, LOGL_DEBUG, LOGD_CORE, "new connection", "++ ",
|
||||
path);
|
||||
|
||||
/* Only emit the individual connection-added signal after connections
|
||||
* have been initially loaded.
|
||||
|
|
@ -1026,7 +1019,7 @@ claim_connection (NMSettings *self, NMSettingsConnection *connection)
|
|||
&interface_info_settings,
|
||||
&signal_info_new_connection,
|
||||
"(o)",
|
||||
nm_connection_get_path (NM_CONNECTION (connection)));
|
||||
nm_dbus_object_get_path (NM_DBUS_OBJECT (connection)));
|
||||
|
||||
g_signal_emit (self, signals[CONNECTION_ADDED], 0, connection);
|
||||
_notify (self, PROP_CONNECTIONS);
|
||||
|
|
@ -1077,14 +1070,14 @@ nm_settings_add_connection (NMSettings *self,
|
|||
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
|
||||
GSList *iter;
|
||||
NMSettingsConnection *added = NULL;
|
||||
GHashTableIter citer;
|
||||
NMConnection *candidate = NULL;
|
||||
NMSettingsConnection *candidate = NULL;
|
||||
const char *uuid;
|
||||
|
||||
uuid = nm_connection_get_uuid (connection);
|
||||
|
||||
/* Make sure a connection with this UUID doesn't already exist */
|
||||
g_hash_table_iter_init (&citer, priv->connections);
|
||||
while (g_hash_table_iter_next (&citer, NULL, (gpointer *) &candidate)) {
|
||||
if (g_strcmp0 (nm_connection_get_uuid (connection),
|
||||
nm_connection_get_uuid (candidate)) == 0) {
|
||||
c_list_for_each_entry (candidate, &priv->connections_lst_head, _connections_lst) {
|
||||
if (nm_streq0 (uuid, nm_connection_get_uuid (NM_CONNECTION (candidate)))) {
|
||||
g_set_error_literal (error,
|
||||
NM_SETTINGS_ERROR,
|
||||
NM_SETTINGS_ERROR_UUID_EXISTS,
|
||||
|
|
@ -1152,7 +1145,7 @@ send_agent_owned_secrets (NMSettings *self,
|
|||
secrets_filter_cb,
|
||||
GUINT_TO_POINTER (NM_SETTING_SECRET_FLAG_AGENT_OWNED));
|
||||
nm_agent_manager_save_secrets (priv->agent_mgr,
|
||||
nm_connection_get_path (NM_CONNECTION (connection)),
|
||||
nm_dbus_object_get_path (NM_DBUS_OBJECT (connection)),
|
||||
for_agent,
|
||||
subject);
|
||||
g_object_unref (for_agent);
|
||||
|
|
@ -1212,7 +1205,7 @@ pk_add_cb (NMAuthChain *chain,
|
|||
send_agent_owned_secrets (self, added, subject);
|
||||
|
||||
g_clear_error (&error);
|
||||
nm_auth_chain_unref (chain);
|
||||
nm_auth_chain_destroy (chain);
|
||||
}
|
||||
|
||||
/* FIXME: remove if/when kernel supports adhoc wpa */
|
||||
|
|
@ -1365,9 +1358,9 @@ settings_add_connection_add_cb (NMSettings *self,
|
|||
g_dbus_method_invocation_return_gerror (context, error);
|
||||
nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD, NULL, FALSE, NULL, subject, error->message);
|
||||
} else {
|
||||
g_dbus_method_invocation_return_value (
|
||||
context,
|
||||
g_variant_new ("(o)", nm_connection_get_path (NM_CONNECTION (connection))));
|
||||
g_dbus_method_invocation_return_value (context,
|
||||
g_variant_new ("(o)",
|
||||
nm_dbus_object_get_path (NM_DBUS_OBJECT (connection))));
|
||||
nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD, connection, TRUE, NULL,
|
||||
subject, NULL);
|
||||
}
|
||||
|
|
@ -1570,7 +1563,7 @@ pk_hostname_cb (NMAuthChain *chain,
|
|||
else
|
||||
g_dbus_method_invocation_return_value (context, NULL);
|
||||
|
||||
nm_auth_chain_unref (chain);
|
||||
nm_auth_chain_destroy (chain);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1618,27 +1611,24 @@ static gboolean
|
|||
have_connection_for_device (NMSettings *self, NMDevice *device)
|
||||
{
|
||||
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
|
||||
GHashTableIter iter;
|
||||
gpointer data;
|
||||
NMSettingConnection *s_con;
|
||||
NMSettingWired *s_wired;
|
||||
const char *setting_hwaddr;
|
||||
const char *perm_hw_addr;
|
||||
NMSettingsConnection *connection;
|
||||
|
||||
g_return_val_if_fail (NM_IS_SETTINGS (self), FALSE);
|
||||
|
||||
perm_hw_addr = nm_device_get_permanent_hw_address (device);
|
||||
|
||||
/* Find a wired connection locked to the given MAC address, if any */
|
||||
g_hash_table_iter_init (&iter, priv->connections);
|
||||
while (g_hash_table_iter_next (&iter, NULL, &data)) {
|
||||
NMConnection *connection = NM_CONNECTION (data);
|
||||
c_list_for_each_entry (connection, &priv->connections_lst_head, _connections_lst) {
|
||||
const char *ctype, *iface;
|
||||
|
||||
if (!nm_device_check_connection_compatible (device, connection))
|
||||
if (!nm_device_check_connection_compatible (device, NM_CONNECTION (connection)))
|
||||
continue;
|
||||
|
||||
s_con = nm_connection_get_setting_connection (connection);
|
||||
s_con = nm_connection_get_setting_connection (NM_CONNECTION (connection));
|
||||
|
||||
iface = nm_setting_connection_get_interface_name (s_con);
|
||||
if (iface && strcmp (iface, nm_device_get_iface (device)) != 0)
|
||||
|
|
@ -1649,7 +1639,7 @@ have_connection_for_device (NMSettings *self, NMDevice *device)
|
|||
&& strcmp (ctype, NM_SETTING_PPPOE_SETTING_NAME))
|
||||
continue;
|
||||
|
||||
s_wired = nm_connection_get_setting_wired (connection);
|
||||
s_wired = nm_connection_get_setting_wired (NM_CONNECTION (connection));
|
||||
|
||||
if (!s_wired && !strcmp (ctype, NM_SETTING_PPPOE_SETTING_NAME)) {
|
||||
/* No wired setting; therefore the PPPoE connection applies to any device */
|
||||
|
|
@ -1677,26 +1667,6 @@ have_connection_for_device (NMSettings *self, NMDevice *device)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static void default_wired_clear_tag (NMSettings *self,
|
||||
NMDevice *device,
|
||||
NMSettingsConnection *connection,
|
||||
gboolean add_to_no_auto_default);
|
||||
|
||||
static void
|
||||
default_wired_connection_removed_cb (NMSettingsConnection *connection, NMSettings *self)
|
||||
{
|
||||
NMDevice *device;
|
||||
|
||||
/* When the default wired connection is removed (either deleted or saved to
|
||||
* a new persistent connection by a plugin), write the MAC address of the
|
||||
* wired device to the config file and don't create a new default wired
|
||||
* connection for that device again.
|
||||
*/
|
||||
device = g_object_get_qdata (G_OBJECT (connection), _default_wired_device_quark ());
|
||||
if (device)
|
||||
default_wired_clear_tag (self, device, connection, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
default_wired_connection_updated_by_user_cb (NMSettingsConnection *connection, gboolean by_user, NMSettings *self)
|
||||
{
|
||||
|
|
@ -1729,7 +1699,6 @@ default_wired_clear_tag (NMSettings *self,
|
|||
g_object_set_qdata (G_OBJECT (connection), _default_wired_device_quark (), NULL);
|
||||
g_object_set_qdata (G_OBJECT (device), _default_wired_connection_quark (), NULL);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (default_wired_connection_removed_cb), self);
|
||||
g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (default_wired_connection_updated_by_user_cb), self);
|
||||
|
||||
if (add_to_no_auto_default)
|
||||
|
|
@ -1781,8 +1750,6 @@ device_realized (NMDevice *device, GParamSpec *pspec, NMSettings *self)
|
|||
|
||||
g_signal_connect (added, NM_SETTINGS_CONNECTION_UPDATED_INTERNAL,
|
||||
G_CALLBACK (default_wired_connection_updated_by_user_cb), self);
|
||||
g_signal_connect (added, NM_SETTINGS_CONNECTION_REMOVED,
|
||||
G_CALLBACK (default_wired_connection_removed_cb), self);
|
||||
|
||||
_LOGI ("(%s): created default wired connection '%s'",
|
||||
nm_device_get_iface (device),
|
||||
|
|
@ -1855,10 +1822,8 @@ nm_settings_start (NMSettings *self, GError **error)
|
|||
/* Load the plugins; fail if a plugin is not found. */
|
||||
plugins = nm_config_data_get_plugins (nm_config_get_data_orig (priv->config), TRUE);
|
||||
|
||||
if (!load_plugins (self, (const char **) plugins, error)) {
|
||||
g_object_unref (self);
|
||||
if (!load_plugins (self, (const char **) plugins, error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
load_connections (self);
|
||||
check_startup_complete (self);
|
||||
|
|
@ -1883,18 +1848,19 @@ get_property (GObject *object, guint prop_id,
|
|||
NMSettings *self = NM_SETTINGS (object);
|
||||
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
|
||||
const GSList *specs, *iter;
|
||||
GHashTableIter citer;
|
||||
GPtrArray *array;
|
||||
const char *path;
|
||||
guint i;
|
||||
char **strvs;
|
||||
const char **strv;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_UNMANAGED_SPECS:
|
||||
array = g_ptr_array_new ();
|
||||
specs = nm_settings_get_unmanaged_specs (self);
|
||||
for (iter = specs; iter; iter = g_slist_next (iter))
|
||||
g_ptr_array_add (array, g_strdup (iter->data));
|
||||
g_ptr_array_add (array, NULL);
|
||||
g_value_take_boxed (value, (char **) g_ptr_array_free (array, FALSE));
|
||||
strvs = g_new (char *, g_slist_length ((GSList *) specs) + 1);
|
||||
i = 0;
|
||||
for (iter = specs; iter; iter = iter->next)
|
||||
strvs[i++] = g_strdup (iter->data);
|
||||
strvs[i] = NULL;
|
||||
g_value_take_boxed (value, strvs);
|
||||
break;
|
||||
case PROP_HOSTNAME:
|
||||
g_value_set_string (value,
|
||||
|
|
@ -1906,12 +1872,11 @@ get_property (GObject *object, guint prop_id,
|
|||
g_value_set_boolean (value, !!get_plugin (self, NM_SETTINGS_PLUGIN_CAP_MODIFY_CONNECTIONS));
|
||||
break;
|
||||
case PROP_CONNECTIONS:
|
||||
array = g_ptr_array_sized_new (g_hash_table_size (priv->connections) + 1);
|
||||
g_hash_table_iter_init (&citer, priv->connections);
|
||||
while (g_hash_table_iter_next (&citer, (gpointer) &path, NULL))
|
||||
g_ptr_array_add (array, g_strdup (path));
|
||||
g_ptr_array_add (array, NULL);
|
||||
g_value_take_boxed (value, (char **) g_ptr_array_free (array, FALSE));
|
||||
strv = nm_dbus_utils_get_paths_for_clist (&priv->connections_lst_head,
|
||||
priv->connections_len,
|
||||
G_STRUCT_OFFSET (NMSettingsConnection, _connections_lst),
|
||||
TRUE);
|
||||
g_value_take_boxed (value, nm_utils_strv_make_deep_copied (strv));
|
||||
break;
|
||||
case PROP_STARTUP_COMPLETE:
|
||||
g_value_set_boolean (value, nm_settings_get_startup_complete (self));
|
||||
|
|
@ -1929,7 +1894,7 @@ nm_settings_init (NMSettings *self)
|
|||
{
|
||||
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
|
||||
|
||||
priv->connections = g_hash_table_new_full (nm_str_hash, g_str_equal, NULL, g_object_unref);
|
||||
c_list_init (&priv->connections_lst_head);
|
||||
|
||||
priv->agent_mgr = g_object_ref (nm_agent_manager_get ());
|
||||
priv->config = g_object_ref (nm_config_get ());
|
||||
|
|
@ -1947,7 +1912,7 @@ dispose (GObject *object)
|
|||
NMSettings *self = NM_SETTINGS (object);
|
||||
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
|
||||
|
||||
g_slist_free_full (priv->auths, (GDestroyNotify) nm_auth_chain_unref);
|
||||
g_slist_free_full (priv->auths, (GDestroyNotify) nm_auth_chain_destroy);
|
||||
priv->auths = NULL;
|
||||
|
||||
g_object_unref (priv->agent_mgr);
|
||||
|
|
@ -1968,8 +1933,9 @@ finalize (GObject *object)
|
|||
NMSettings *self = NM_SETTINGS (object);
|
||||
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
|
||||
|
||||
g_hash_table_destroy (priv->connections);
|
||||
_clear_connections_cached_list (&priv->connections_cached_list);
|
||||
_clear_connections_cached_list (priv);
|
||||
|
||||
nm_assert (c_list_is_empty (&priv->connections_lst_head));
|
||||
|
||||
g_slist_free_full (priv->unmanaged_specs, g_free);
|
||||
g_slist_free_full (priv->unrecognized_specs, g_free);
|
||||
|
|
|
|||
|
|
@ -70,14 +70,6 @@ NMSettings *nm_settings_get (void);
|
|||
NMSettings *nm_settings_new (void);
|
||||
gboolean nm_settings_start (NMSettings *self, GError **error);
|
||||
|
||||
typedef void (*NMSettingsForEachFunc) (NMSettings *settings,
|
||||
NMSettingsConnection *connection,
|
||||
gpointer user_data);
|
||||
|
||||
void nm_settings_for_each_connection (NMSettings *settings,
|
||||
NMSettingsForEachFunc for_each_func,
|
||||
gpointer user_data);
|
||||
|
||||
typedef void (*NMSettingsAddCallback) (NMSettings *settings,
|
||||
NMSettingsConnection *connection,
|
||||
GError *error,
|
||||
|
|
|
|||
|
|
@ -326,21 +326,21 @@ update_connection (SettingsPluginIfcfg *self,
|
|||
|
||||
if (new_unmanaged || new_unrecognized) {
|
||||
if (!old_unmanaged && !old_unrecognized) {
|
||||
/* ref connection first, because we put it into priv->connections below.
|
||||
* Emitting signal-removed might otherwise delete it. */
|
||||
g_object_ref (connection_by_uuid);
|
||||
|
||||
/* Unexport the connection by telling the settings service it's
|
||||
* been removed.
|
||||
*/
|
||||
nm_settings_connection_signal_remove (NM_SETTINGS_CONNECTION (connection_by_uuid));
|
||||
/* Remove the path so that claim_connection() doesn't complain later when
|
||||
* interface gets managed and connection is re-added. */
|
||||
nm_connection_set_path (NM_CONNECTION (connection_by_uuid), NULL);
|
||||
|
||||
/* signal_remove() will end up removing the connection from our hash,
|
||||
* so add it back now.
|
||||
*/
|
||||
g_hash_table_insert (priv->connections,
|
||||
g_strdup (nm_connection_get_uuid (NM_CONNECTION (connection_by_uuid))),
|
||||
connection_by_uuid);
|
||||
connection_by_uuid/*<< took reference above*/);
|
||||
}
|
||||
} else {
|
||||
if (old_unmanaged /* && !new_unmanaged */) {
|
||||
|
|
@ -372,7 +372,9 @@ update_connection (SettingsPluginIfcfg *self,
|
|||
_LOGI ("add connection "NM_IFCFG_CONNECTION_LOG_FMT, NM_IFCFG_CONNECTION_LOG_ARG (connection_new));
|
||||
else
|
||||
_LOGI ("new connection "NM_IFCFG_CONNECTION_LOG_FMT, NM_IFCFG_CONNECTION_LOG_ARG (connection_new));
|
||||
g_hash_table_insert (priv->connections, g_strdup (uuid), connection_new);
|
||||
g_hash_table_insert (priv->connections,
|
||||
g_strdup (uuid),
|
||||
connection_new /* take reference */);
|
||||
|
||||
g_signal_connect (connection_new, NM_SETTINGS_CONNECTION_REMOVED,
|
||||
G_CALLBACK (connection_removed_cb),
|
||||
|
|
@ -748,7 +750,7 @@ impl_ifcfgrh_get_ifcfg_details (SettingsPluginIfcfg *plugin,
|
|||
return;
|
||||
}
|
||||
|
||||
path = nm_connection_get_path (NM_CONNECTION (connection));
|
||||
path = nm_dbus_object_get_path (NM_DBUS_OBJECT (connection));
|
||||
if (!path) {
|
||||
g_dbus_method_invocation_return_error (context,
|
||||
NM_SETTINGS_ERROR,
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ nm_test_device_init (NMTestDevice *self)
|
|||
}
|
||||
|
||||
/* We jump over NMDevice's construct/destruct methods, which require NMPlatform
|
||||
* and NMConnectionProvider to be initialized.
|
||||
* and NMSettings to be initialized.
|
||||
*/
|
||||
static void
|
||||
constructed (GObject *object)
|
||||
|
|
|
|||
|
|
@ -232,13 +232,13 @@ test_nm_utils_log_connection_diff (void)
|
|||
|
||||
connection = nm_simple_connection_new ();
|
||||
nm_connection_add_setting (connection, nm_setting_connection_new ());
|
||||
nm_utils_log_connection_diff (connection, NULL, LOGL_DEBUG, LOGD_CORE, "test1", ">>> ");
|
||||
nm_utils_log_connection_diff (connection, NULL, LOGL_DEBUG, LOGD_CORE, "test1", ">>> ", NULL);
|
||||
|
||||
nm_connection_add_setting (connection, nm_setting_wired_new ());
|
||||
nm_utils_log_connection_diff (connection, NULL, LOGL_DEBUG, LOGD_CORE, "test2", ">>> ");
|
||||
nm_utils_log_connection_diff (connection, NULL, LOGL_DEBUG, LOGD_CORE, "test2", ">>> ", NULL);
|
||||
|
||||
connection2 = nm_simple_connection_new_clone (connection);
|
||||
nm_utils_log_connection_diff (connection, connection2, LOGL_DEBUG, LOGD_CORE, "test3", ">>> ");
|
||||
nm_utils_log_connection_diff (connection, connection2, LOGL_DEBUG, LOGD_CORE, "test3", ">>> ", NULL);
|
||||
|
||||
g_object_set (nm_connection_get_setting_connection (connection),
|
||||
NM_SETTING_CONNECTION_ID, "id",
|
||||
|
|
@ -248,24 +248,24 @@ test_nm_utils_log_connection_diff (void)
|
|||
NM_SETTING_CONNECTION_ID, "id2",
|
||||
NM_SETTING_CONNECTION_MASTER, "master2",
|
||||
NULL);
|
||||
nm_utils_log_connection_diff (connection, connection2, LOGL_DEBUG, LOGD_CORE, "test4", ">>> ");
|
||||
nm_utils_log_connection_diff (connection, connection2, LOGL_DEBUG, LOGD_CORE, "test4", ">>> ", NULL);
|
||||
|
||||
nm_connection_add_setting (connection, nm_setting_802_1x_new ());
|
||||
nm_utils_log_connection_diff (connection, connection2, LOGL_DEBUG, LOGD_CORE, "test5", ">>> ");
|
||||
nm_utils_log_connection_diff (connection, connection2, LOGL_DEBUG, LOGD_CORE, "test5", ">>> ", NULL);
|
||||
|
||||
g_object_set (nm_connection_get_setting_802_1x (connection),
|
||||
NM_SETTING_802_1X_PASSWORD, "id2",
|
||||
NM_SETTING_802_1X_PASSWORD_FLAGS, NM_SETTING_SECRET_FLAG_NOT_SAVED,
|
||||
NULL);
|
||||
nm_utils_log_connection_diff (connection, NULL, LOGL_DEBUG, LOGD_CORE, "test6", ">>> ");
|
||||
nm_utils_log_connection_diff (connection, connection2, LOGL_DEBUG, LOGD_CORE, "test7", ">>> ");
|
||||
nm_utils_log_connection_diff (connection2, connection, LOGL_DEBUG, LOGD_CORE, "test8", ">>> ");
|
||||
nm_utils_log_connection_diff (connection, NULL, LOGL_DEBUG, LOGD_CORE, "test6", ">>> ", NULL);
|
||||
nm_utils_log_connection_diff (connection, connection2, LOGL_DEBUG, LOGD_CORE, "test7", ">>> ", NULL);
|
||||
nm_utils_log_connection_diff (connection2, connection, LOGL_DEBUG, LOGD_CORE, "test8", ">>> ", NULL);
|
||||
|
||||
g_clear_object (&connection);
|
||||
g_clear_object (&connection2);
|
||||
|
||||
connection = nmtst_create_minimal_connection ("id-vpn-1", NULL, NM_SETTING_VPN_SETTING_NAME, NULL);
|
||||
nm_utils_log_connection_diff (connection, NULL, LOGL_DEBUG, LOGD_CORE, "test-vpn-1", ">>> ");
|
||||
nm_utils_log_connection_diff (connection, NULL, LOGL_DEBUG, LOGD_CORE, "test-vpn-1", ">>> ", NULL);
|
||||
|
||||
g_clear_object (&connection);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue