NetworkManager/src/core/nm-act-request.c

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

509 lines
17 KiB
C
Raw Normal View History

/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2005 - 2012 Red Hat, Inc.
* Copyright (C) 2007 - 2008 Novell, Inc.
*/
#include "src/core/nm-default-daemon.h"
#include "nm-act-request.h"
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
2008-03-17 Dan Williams <dcbw@redhat.com> Split the 802.1x bits out of the wireless-security setting so they are generalized enough for wired 802.1x to use too. * introspection/nm-exported-connection.xml - GetSecrets now returns 'a{sa{sv}}' (a hash of settings hashes) instead of just a hash of the secrets for one setting * libnm-util/nm-setting-wireless-security.c libnm-util/nm-setting-wireless-security.h - Remove 802.1x-specific stuff - Added leap-username and leap-password properties for old-school LEAP * src/nm-device.c src/nm-device.h - (connection_secrets_updated_cb): take a list of updated settings names, not just one * src/supplicant-manager/nm-supplicant-config.c src/supplicant-manager/nm-supplicant-config.h - (nm_supplicant_config_add_setting_wireless_security): remove 802.1x specific stuff; fix for updated LEAP bits; punt 802.1x stuff to nm_supplicant_config_add_setting_8021x() - (nm_supplicant_config_add_setting_8021x): add an 802-1x setting to the supplicant config * src/nm-device-802-11-wireless.c - (build_supplicant_config): pass in the 802.1x setting too, if any - (real_connection_secrets_updated): take a list of updated settings names, not just one * src/nm-device-802-3-ethernet.c src/nm-cdma-device.c src/nm-gsm-device.c - (real_connection_secrets_updated_cb): take a list of updated settings names, not just one * src/nm-activation-request.c src/nm-activation-request.h - (nm_act_request_class_init): the 'connection-secrets-updated' signal now passes a list of updated settings names, not just one - (update_one_setting): new function; handle one updated setting - (get_secrets_cb): handle multiple settings returned from the settings service; have to be careful of ordering here as there are some dependencies between settings (ex. wireless-security and 802.1x in some cases) * src/marshallers/nm-marshal.list - new marshaller for connection-secrets-updated signal * libnm-util/nm-setting-8021x.c - Add back the 'pin' and 'psk' settings, for EAP-SIM and EAP-PSK auth methods - (verify): a valid 'eap' property is now required * libnm-util/nm-connection.c - (register_default_settings): add priorities to settings; there are some dependencies between settings, and during the need_secrets calls this priority needs to be respected. For example, only the wireless-security setting knows whether or not the connection is going to use 802.1x or now, so it must be asked for secrets before any existing 802.1x setting is - (nm_connection_lookup_setting_type): expose * libnm-util/nm-setting-wireless.c - (verify): should verify even if all_settings is NULL; otherwise won't catch the case where there is missing security * libnm-util/nm-setting-wireless-security.c - Remove everything to do with 802.1x - Add old-school LEAP specific properties for username and password - (need_secrets): rework LEAP secrets checking - (verify): rework for LEAP and 802.1x verification git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3470 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-03-17 19:37:23 +00:00
#include "c-list/src/c-list.h"
#include "libnm-core-aux-intern/nm-auth-subject.h"
2008-03-17 Dan Williams <dcbw@redhat.com> Split the 802.1x bits out of the wireless-security setting so they are generalized enough for wired 802.1x to use too. * introspection/nm-exported-connection.xml - GetSecrets now returns 'a{sa{sv}}' (a hash of settings hashes) instead of just a hash of the secrets for one setting * libnm-util/nm-setting-wireless-security.c libnm-util/nm-setting-wireless-security.h - Remove 802.1x-specific stuff - Added leap-username and leap-password properties for old-school LEAP * src/nm-device.c src/nm-device.h - (connection_secrets_updated_cb): take a list of updated settings names, not just one * src/supplicant-manager/nm-supplicant-config.c src/supplicant-manager/nm-supplicant-config.h - (nm_supplicant_config_add_setting_wireless_security): remove 802.1x specific stuff; fix for updated LEAP bits; punt 802.1x stuff to nm_supplicant_config_add_setting_8021x() - (nm_supplicant_config_add_setting_8021x): add an 802-1x setting to the supplicant config * src/nm-device-802-11-wireless.c - (build_supplicant_config): pass in the 802.1x setting too, if any - (real_connection_secrets_updated): take a list of updated settings names, not just one * src/nm-device-802-3-ethernet.c src/nm-cdma-device.c src/nm-gsm-device.c - (real_connection_secrets_updated_cb): take a list of updated settings names, not just one * src/nm-activation-request.c src/nm-activation-request.h - (nm_act_request_class_init): the 'connection-secrets-updated' signal now passes a list of updated settings names, not just one - (update_one_setting): new function; handle one updated setting - (get_secrets_cb): handle multiple settings returned from the settings service; have to be careful of ordering here as there are some dependencies between settings (ex. wireless-security and 802.1x in some cases) * src/marshallers/nm-marshal.list - new marshaller for connection-secrets-updated signal * libnm-util/nm-setting-8021x.c - Add back the 'pin' and 'psk' settings, for EAP-SIM and EAP-PSK auth methods - (verify): a valid 'eap' property is now required * libnm-util/nm-connection.c - (register_default_settings): add priorities to settings; there are some dependencies between settings, and during the need_secrets calls this priority needs to be respected. For example, only the wireless-security setting knows whether or not the connection is going to use 802.1x or now, so it must be asked for secrets before any existing 802.1x setting is - (nm_connection_lookup_setting_type): expose * libnm-util/nm-setting-wireless.c - (verify): should verify even if all_settings is NULL; otherwise won't catch the case where there is missing security * libnm-util/nm-setting-wireless-security.c - Remove everything to do with 802.1x - Add old-school LEAP specific properties for username and password - (need_secrets): rework LEAP secrets checking - (verify): rework for LEAP and 802.1x verification git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3470 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-03-17 19:37:23 +00:00
#include "nm-setting-8021x.h"
#include "nm-setting-wireless-security.h"
#include "devices/nm-device.h"
#include "nm-active-connection.h"
#include "nm-firewall-utils.h"
#include "settings/nm-settings-connection.h"
2007-09-28 Tambet Ingo <tambet@gmail.com> * src/nm-manager.c: * src/nm-manager.h: Implement device activation through NMManager. Implement "pending device activation" here - If the connection isn't found, we try to wait for up to 5 seconds for the connection to be provided. Add NMConnectionType argument to "connection-added" and "connection-removed" signals. (nm_manager_get): Remove. Finally. * src/nm-activation-request.c: * src/nm-activation-request.h: Remove all the deferred activation code. * src/nm-device.c: Remove all the deferred activation code. Once * the device activation is started, it's started. Update the activation virtual function signature. * src/nm-device-interface.c: * src/nm-device-interface.h: Device activation now takes only NMActRequest argument. Don't expose device activation directly on dbus, it's supposed to go through NMManager now. * src/NetworkManagerPolicy.c (nm_policy_device_change_check): * Make the code a bit more compact. Use the new device activation methods through NMManager. * introspection/nm-manager-client.xml: * introspection/nm-manager.xml: * libnm-glib/nm-client.c: * libnm-glib/nm-client.h: Add device activation method. * libnm-glib/nm-device.c: * libnm-glib/nm-device.h: * introspection/nm-device.xml: Remove device activation method. It's done through NMManager now. * src/vpn-manager/nm-vpn-manager.c (impl_vpn_manager_connect): * Use the shiny new (nm_manager_get_device_by_path) function, get rid of our own )find_device). git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@2915 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2007-10-01 15:38:39 +00:00
typedef struct {
CList call_ids_lst_head;
} NMActRequestPrivate;
struct _NMActRequest {
NMActiveConnection parent;
NMActRequestPrivate _priv;
};
typedef struct {
NMActiveConnectionClass parent;
} NMActRequestClass;
enum {
PROP_0,
PROP_IP4_CONFIG,
PROP_DHCP4_CONFIG,
PROP_IP6_CONFIG,
PROP_DHCP6_CONFIG,
LAST_PROP
};
G_DEFINE_TYPE(NMActRequest, nm_act_request, NM_TYPE_ACTIVE_CONNECTION)
#define NM_ACT_REQUEST_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMActRequest, NM_IS_ACT_REQUEST)
/*****************************************************************************/
NMSettingsConnection *
nm_act_request_get_settings_connection(NMActRequest *req)
{
g_return_val_if_fail(NM_IS_ACT_REQUEST(req), NULL);
return nm_active_connection_get_settings_connection(NM_ACTIVE_CONNECTION(req));
}
NMConnection *
nm_act_request_get_applied_connection(NMActRequest *req)
{
g_return_val_if_fail(NM_IS_ACT_REQUEST(req), NULL);
return nm_active_connection_get_applied_connection(NM_ACTIVE_CONNECTION(req));
}
/*****************************************************************************/
struct _NMActRequestGetSecretsCallId {
CList call_ids_lst;
NMActRequest * self;
NMActRequestSecretsFunc callback;
gpointer callback_data;
NMSettingsConnectionCallId *call_id;
bool has_ref;
};
static void
_get_secrets_call_id_free(NMActRequestGetSecretsCallId *call_id)
{
nm_assert(call_id);
nm_assert(!c_list_is_linked(&call_id->call_ids_lst));
if (call_id->has_ref)
g_object_unref(call_id->self);
g_slice_free(NMActRequestGetSecretsCallId, call_id);
}
static void
get_secrets_cb(NMSettingsConnection * connection,
NMSettingsConnectionCallId *call_id_s,
const char * agent_username,
const char * setting_name,
GError * error,
gpointer user_data)
{
NMActRequestGetSecretsCallId *call_id = user_data;
NMActRequestPrivate * priv;
g_return_if_fail(call_id && call_id->call_id == call_id_s);
g_return_if_fail(NM_IS_ACT_REQUEST(call_id->self));
if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
priv = NM_ACT_REQUEST_GET_PRIVATE(call_id->self);
nm_assert(c_list_contains(&priv->call_ids_lst_head, &call_id->call_ids_lst));
c_list_unlink(&call_id->call_ids_lst);
if (call_id->callback)
call_id->callback(call_id->self, call_id, connection, error, call_id->callback_data);
_get_secrets_call_id_free(call_id);
}
/**
* nm_act_request_get_secrets:
* @self:
* @ref_self: if %TRUE, the pending call take a reference on @self.
* It also allows you to omit the @self argument in nm_act_request_cancel_secrets().
* @setting_name:
* @flags:
* @hint:
* @callback:
* @callback_data:
*
* Asynchronously starts the request for secrets. This function cannot
* fail.
*
* The return call-id can be used to cancel the request. You are
* only allowed to cancel a still pending operation (once).
* The callback will always be invoked once, even for canceling
* or disposing of NMActRequest.
*
* Returns: a call-id.
*/
NMActRequestGetSecretsCallId *
nm_act_request_get_secrets(NMActRequest * self,
gboolean ref_self,
const char * setting_name,
NMSecretAgentGetSecretsFlags flags,
const char *const * hints,
NMActRequestSecretsFunc callback,
gpointer callback_data)
{
NMActRequestPrivate * priv;
NMActRequestGetSecretsCallId *call_id;
NMSettingsConnectionCallId * call_id_s;
NMSettingsConnection * settings_connection;
NMConnection * applied_connection;
g_return_val_if_fail(NM_IS_ACT_REQUEST(self), NULL);
priv = NM_ACT_REQUEST_GET_PRIVATE(self);
settings_connection = nm_act_request_get_settings_connection(self);
applied_connection = nm_act_request_get_applied_connection(self);
call_id = g_slice_new0(NMActRequestGetSecretsCallId);
call_id->has_ref = ref_self;
call_id->self = ref_self ? g_object_ref(self) : self;
call_id->callback = callback;
call_id->callback_data = callback_data;
c_list_link_tail(&priv->call_ids_lst_head, &call_id->call_ids_lst);
if (nm_active_connection_get_user_requested(NM_ACTIVE_CONNECTION(self)))
flags |= NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED;
call_id_s = nm_settings_connection_get_secrets(
settings_connection,
applied_connection,
nm_active_connection_get_subject(NM_ACTIVE_CONNECTION(self)),
setting_name,
flags,
hints,
get_secrets_cb,
call_id);
call_id->call_id = call_id_s;
g_return_val_if_fail(call_id_s, NULL);
return call_id;
}
static void
_do_cancel_secrets(NMActRequest *self, NMActRequestGetSecretsCallId *call_id, gboolean is_disposing)
{
NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE(self);
nm_assert(call_id && call_id->self == self);
nm_assert(c_list_contains(&priv->call_ids_lst_head, &call_id->call_ids_lst));
c_list_unlink(&call_id->call_ids_lst);
nm_settings_connection_cancel_secrets(nm_act_request_get_settings_connection(self),
call_id->call_id);
if (call_id->callback) {
gs_free_error GError *error = NULL;
nm_utils_error_set_cancelled(&error, is_disposing, "NMActRequest");
call_id->callback(self, call_id, NULL, error, call_id->callback_data);
}
_get_secrets_call_id_free(call_id);
}
/**
* nm_act_request_cancel_secrets:
* @self: The #NMActRequest. Note that this argument can be %NULL if, and only if
* the call_id was created with @take_ref.
* @call_id:
*
* You are only allowed to cancel the call once, and only before the callback
* is already invoked. Note that cancelling causes the callback to be invoked
* synchronously.
*/
void
nm_act_request_cancel_secrets(NMActRequest *self, NMActRequestGetSecretsCallId *call_id)
{
g_return_if_fail(call_id);
if (self) {
g_return_if_fail(NM_IS_ACT_REQUEST(self));
g_return_if_fail(self == call_id->self);
} else {
g_return_if_fail(call_id->has_ref);
g_return_if_fail(NM_IS_ACT_REQUEST(call_id->self));
self = call_id->self;
}
if (!c_list_is_linked(&call_id->call_ids_lst))
g_return_if_reached();
_do_cancel_secrets(self, call_id, FALSE);
}
void
nm_act_request_clear_secrets(NMActRequest *self)
{
g_return_if_fail(NM_IS_ACT_REQUEST(self));
nm_active_connection_clear_secrets((NMActiveConnection *) self);
}
/*****************************************************************************/
static void
device_notify(GObject *object, GParamSpec *pspec, gpointer self)
{
g_object_notify(self, pspec->name);
}
static void
device_state_changed(NMActiveConnection *active,
NMDevice * device,
NMDeviceState new_state,
NMDeviceState old_state)
{
NMActiveConnectionState cur_ac_state = nm_active_connection_get_state(active);
NMActiveConnectionState ac_state = NM_ACTIVE_CONNECTION_STATE_UNKNOWN;
NMActiveConnectionStateReason ac_state_reason = NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN;
/* Decide which device state changes to handle when this active connection
* is not the device's current request. Two cases here: (a) the AC is
* pending and not yet active, and (b) the AC was active but the device is
* entering DISCONNECTED state (which clears the device's current AC before
* emitting the state change signal).
*/
if (NM_ACTIVE_CONNECTION(nm_device_get_act_request(device)) != active) {
/* Some other request is activating; this one must be pending */
if (new_state >= NM_DEVICE_STATE_PREPARE)
return;
else if (new_state == NM_DEVICE_STATE_DISCONNECTED) {
/* This request hasn't started activating yet; the device is
* disconnecting and cleaning up a previous activation request.
*/
if (cur_ac_state < NM_ACTIVE_CONNECTION_STATE_ACTIVATING)
return;
/* Catch device disconnections after this request has been active */
}
/* All states < DISCONNECTED are fatal and handled */
}
/* Set NMActiveConnection state based on the device's state */
switch (new_state) {
case NM_DEVICE_STATE_PREPARE:
case NM_DEVICE_STATE_CONFIG:
case NM_DEVICE_STATE_NEED_AUTH:
case NM_DEVICE_STATE_IP_CONFIG:
case NM_DEVICE_STATE_IP_CHECK:
case NM_DEVICE_STATE_SECONDARIES:
ac_state = NM_ACTIVE_CONNECTION_STATE_ACTIVATING;
break;
case NM_DEVICE_STATE_ACTIVATED:
ac_state = NM_ACTIVE_CONNECTION_STATE_ACTIVATED;
g_signal_connect(device,
"notify::" NM_DEVICE_IP4_CONFIG,
G_CALLBACK(device_notify),
active);
g_signal_connect(device,
"notify::" NM_DEVICE_DHCP4_CONFIG,
G_CALLBACK(device_notify),
active);
g_signal_connect(device,
"notify::" NM_DEVICE_IP6_CONFIG,
G_CALLBACK(device_notify),
active);
g_signal_connect(device,
"notify::" NM_DEVICE_DHCP6_CONFIG,
G_CALLBACK(device_notify),
active);
break;
case NM_DEVICE_STATE_DEACTIVATING:
ac_state = NM_ACTIVE_CONNECTION_STATE_DEACTIVATING;
break;
case NM_DEVICE_STATE_FAILED:
case NM_DEVICE_STATE_DISCONNECTED:
case NM_DEVICE_STATE_UNMANAGED:
case NM_DEVICE_STATE_UNAVAILABLE:
ac_state = NM_ACTIVE_CONNECTION_STATE_DEACTIVATED;
ac_state_reason = NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED;
g_signal_handlers_disconnect_by_func(device, G_CALLBACK(device_notify), active);
break;
default:
break;
}
if (ac_state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED
|| ac_state == NM_ACTIVE_CONNECTION_STATE_UNKNOWN)
nm_active_connection_set_default(active, AF_UNSPEC, FALSE);
nm_active_connection_set_state(active, ac_state, ac_state_reason);
}
static void
master_failed(NMActiveConnection *self)
{
NMDevice * device;
NMDeviceState device_state;
/* If the connection has an active device, fail it */
device = nm_active_connection_get_device(self);
if (device) {
device_state = nm_device_get_state(device);
if (nm_device_is_activating(device) || (device_state == NM_DEVICE_STATE_ACTIVATED)) {
act-request: queue failing the slave when master fails We might be already handling a state change: Aug 17 05:26:34 dacan.local NetworkManager[618]: (devices/nm-device.c:10982): _set_state_full: runtime check failed: (priv->in_state_changed == FALSE) (gdb) bt #0 0x00007fc218dad643 in g_logv (log_domain=0x7fc21c0db3c3 "NetworkManager", log_level=G_LOG_LEVEL_WARNING, format=<optimized out>, args=args@entry=0x7ffe6f0b30d0) at gmessages.c:1086 #1 0x00007fc218dad7bf in g_log (log_domain=log_domain@entry=0x7fc21c0db3c3 "NetworkManager", log_level=log_level@entry=G_LOG_LEVEL_WARNING, format=format@entry=0x7fc218e1b70f "%s") at gmessages.c:1119 #2 0x00007fc218dadb16 in g_warn_message (domain=domain@entry=0x7fc21c0db3c3 "NetworkManager", file=file@entry=0x7fc21c0d6597 "devices/nm-device.c", line=line@entry=10982, func=func@entry=0x7fc21c0dabf0 <__FUNCTION__.42233> "_set_state_full", warnexpr=warnexpr@entry=0x7fc21c0d95a0 "priv->in_state_changed == FALSE") at gmessages.c:1152 #3 0x00007fc21bf79bd6 in _set_state_full (self=0x7fc21ccd88b0 [NMDeviceEthernet], state=NM_DEVICE_STATE_FAILED, reason=NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED, quitting=0) at devices/nm-device.c:10982 #7 0x00007fc2190bdd9f in <emit signal notify:master on instance 0x7fc21ccd88b0 [NMDeviceEthernet]> (instance=instance@entry=0x7fc21ccd88b0, signal_id=<optimized out>, detail=<optimized out>) at gsignal.c:3439 #4 0x00007fc2190a3908 in g_closure_invoke (closure=0x7fc21cd009e0, return_value=return_value@entry=0x0, n_param_values=2, param_values=param_values@entry=0x7ffe6f0b34b0, invocation_hint=invocation_hint@entry=0x7ffe6f0b3450) at gclosure.c:801 #5 0x00007fc2190b5a1d in signal_emit_unlocked_R (node=node@entry=0x7fc21cb66500, detail=detail@entry=588, instance=instance@entry=0x7fc21ccd88b0, emission_return=emission_return@entry=0x0, instance_and_params=instance_and_params@entry=0x7ffe6f0b34b0) at gsignal.c:3627 #6 0x00007fc2190bdab1 in g_signal_emit_valist (instance=<optimized out>, signal_id=<optimized out>, detail=<optimized out>, var_args=var_args@entry=0x7ffe6f0b3640) at gsignal.c:3383 #8 0x00007fc2190a7fd4 in g_object_dispatch_properties_changed (object=0x7fc21ccd88b0 [NMDeviceEthernet], n_pspecs=<optimized out>, pspecs=<optimized out>) at gobject.c:1061 #9 0x00007fc2190aa619 in g_object_notify_by_pspec (pspec=<optimized out>, object=0x7fc21ccd88b0 [NMDeviceEthernet]) at gobject.c:1155 #10 0x00007fc2190aa619 in g_object_notify_by_pspec (object=object@entry=0x7fc21ccd88b0 [NMDeviceEthernet], pspec=<optimized out>) at gobject.c:1264 #11 0x00007fc21bf7de3f in nm_device_master_enslave_slave (prop=PROP_MASTER, obj=0x7fc21ccd88b0 [NMDeviceEthernet]) at devices/nm-device.c:103 #12 0x00007fc21bf7de3f in nm_device_master_enslave_slave (success=1, self=0x7fc21ccd88b0 [NMDeviceEthernet]) at devices/nm-device.c:2757 #13 0x00007fc21bf7de3f in nm_device_master_enslave_slave (self=0x7fc21cd42810 [NMDeviceBond], slave=0x7fc21ccd88b0 [NMDeviceEthernet], connection=<optimized out>) at devices/nm-device.c:1300 #14 0x00007fc2167c8dcc in ffi_call_unix64 () at ../src/x86/unix64.S:76 #15 0x00007fc2167c86f5 in ffi_call (cif=cif@entry=0x7ffe6f0b3a10, fn=<optimized out>, rvalue=0x7ffe6f0b3980, avalue=avalue@entry=0x7ffe6f0b3900) at ../src/x86/ffi64.c:522 #20 0x00007fc2190be2e8 in <emit signal 0x7fc21c0ea3d5 "state-changed" on instance 0x7fc21ccd88b0 [NMDeviceEthernet]> (instance=instance@entry=0x7fc21ccd88b0, detailed_signal=detailed_signal@entry=0x7fc21c0ea3d5 "state-changed") at gsignal.c:3479 #16 0x00007fc2190a4148 in g_cclosure_marshal_generic (closure=0x7fc21cc84de0, return_gvalue=0x0, n_param_values=<optimized out>, param_values=<optimized out>, invocation_hint=<optimized out>, marshal_data=0x0) at gclosure.c:1487 #17 0x00007fc2190a3908 in g_closure_invoke (closure=0x7fc21cc84de0, return_value=return_value@entry=0x0, n_param_values=4, param_values=param_values@entry=0x7ffe6f0b3c10, invocation_hint=invocation_hint@entry=0x7ffe6f0b3bb0) at gclosure.c:801 #18 0x00007fc2190b5a1d in signal_emit_unlocked_R (node=node@entry=0x7fc21cbeef20, detail=detail@entry=0, instance=instance@entry=0x7fc21ccd88b0, emission_return=emission_return@entry=0x0, instance_and_params=instance_and_params@entry=0x7ffe6f0b3c10) at gsignal.c:3627 #19 0x00007fc2190bdab1 in g_signal_emit_valist (instance=instance@entry=0x7fc21ccd88b0, signal_id=signal_id@entry=112, detail=detail@entry=0, var_args=var_args@entry=0x7ffe6f0b3e48) at gsignal.c:3383 #21 0x00007fc21bf79e3d in _set_state_full (self=self@entry=0x7fc21ccd88b0 [NMDeviceEthernet], state=state@entry=NM_DEVICE_STATE_IP_CONFIG, reason=reason@entry=NM_DEVICE_STATE_REASON_NONE, quitting=quitting@entry=0) at devices/nm-device.c:11123 #22 0x00007fc21bf7a707 in nm_device_state_changed (self=self@entry=0x7fc21ccd88b0 [NMDeviceEthernet], state=state@entry=NM_DEVICE_STATE_IP_CONFIG, reason=reason@entry=NM_DEVICE_STATE_REASON_NONE) at devices/nm-device.c:11308 #23 0x00007fc21bf7e92f in activate_stage3_ip_config_start (self=0x7fc21ccd88b0 [NMDeviceEthernet]) at devices/nm-device.c:6759 #24 0x00007fc21bf68dac in activation_source_handle_cb (self=0x7fc21ccd88b0 [NMDeviceEthernet], family=family@entry=2) at devices/nm-device.c:3627 #25 0x00007fc21bf68e6e in activation_source_handle_cb4 (user_data=<optimized out>) at devices/nm-device.c:3564 #26 0x00007fc218da6d7a in g_main_context_dispatch (context=0x7fc21cb6e000) at gmain.c:3152 #27 0x00007fc218da6d7a in g_main_context_dispatch (context=context@entry=0x7fc21cb6e000) at gmain.c:3767 #28 0x00007fc218da70b8 in g_main_context_iterate (context=0x7fc21cb6e000, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3838 #29 0x00007fc218da738a in g_main_loop_run (loop=0x7fc21cb6c8c0) at gmain.c:4032 #30 0x00007fc21bf4a23e in main (argc=1, argv=0x7ffe6f0b43e8) at main.c:411 (gdb) https://bugzilla.redhat.com/show_bug.cgi?id=1367702
2016-08-17 13:49:43 +02:00
nm_device_queue_state(device,
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED);
return;
}
}
/* If no device, or the device wasn't active, just move to deactivated state */
nm_active_connection_set_state(self,
NM_ACTIVE_CONNECTION_STATE_DEACTIVATED,
NM_ACTIVE_CONNECTION_STATE_REASON_DEPENDENCY_FAILED);
}
/*****************************************************************************/
static void
get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
NMActiveConnection *active;
NMDevice * device;
char * name;
switch (prop_id) {
case PROP_IP4_CONFIG:
name = NM_DEVICE_IP4_CONFIG;
break;
case PROP_DHCP4_CONFIG:
name = NM_DEVICE_DHCP4_CONFIG;
break;
case PROP_IP6_CONFIG:
name = NM_DEVICE_IP6_CONFIG;
break;
case PROP_DHCP6_CONFIG:
name = NM_DEVICE_DHCP6_CONFIG;
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
return;
}
active = NM_ACTIVE_CONNECTION(object);
device = nm_active_connection_get_device(active);
if (!device
|| !NM_IN_SET(nm_active_connection_get_state(active),
NM_ACTIVE_CONNECTION_STATE_ACTIVATED,
NM_ACTIVE_CONNECTION_STATE_DEACTIVATING)) {
g_value_set_string(value, NULL);
return;
}
g_object_get_property(G_OBJECT(device), name, value);
}
static void
nm_act_request_init(NMActRequest *req)
{
NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE(req);
c_list_init(&priv->call_ids_lst_head);
}
/**
* nm_act_request_new:
*
* @settings_connection: (allow-none): the connection to activate @device with
* @applied_connection: (allow-none): the applied connection
* @specific_object: the object path of the specific object (ie, Wi-Fi access point,
* etc) that will be used to activate @connection and @device
* @subject: the #NMAuthSubject representing the requestor of the activation
* @activation_type: the #NMActivationType
* @activation_reason: the reason for activation
core: improve and fix keeping connection active based on "connection.permissions" By setting "connection.permissions", a profile is restricted to a particular user. That means for example, that another user cannot see, modify, delete, activate or deactivate the profile. It also means, that the profile will only autoconnect when the user is logged in (has a session). Note that root is always able to activate the profile. Likewise, the user is also allowed to manually activate the own profile, even if no session currently exists (which can easily happen with `sudo`). When the user logs out (the session goes away), we want do disconnect the profile, however there are conflicting goals here: 1) if the profile was activate by root user, then logging out the user should not disconnect the profile. The patch fixes that by not binding the activation to the connection, if the activation is done by the root user. 2) if the profile was activated by the owner when it had no session, then it should stay alive until the user logs in (once) and logs out again. This is already handled by the previous commit. Yes, this point is odd. If you first do $ sudo -u $OTHER_USER nmcli connection up $PROFILE the profile activates despite not having a session. If you then $ ssh guest@localhost nmcli device you'll still see the profile active. However, the moment the SSH session ends, a session closes and the profile disconnects. It's unclear, how to solve that any better. I think, a user who cares about this, should not activate the profile without having a session in the first place. There are quite some special cases, in particular with internal activations. In those cases we need to decide whether to bind the activation to the profile's visibility. Also, expose the "bind" setting in the D-Bus API. Note, that in the future this flag may be modified via D-Bus API. Like we may also add related API that allows to tweak the lifetime of the activation. Also, I think we broke handling of connection visiblity with 37e8c53eeed "core: Introduce helper class to track connection keep alive". This should be fixed now too, with improved behavior. Fixes: 37e8c53eeed579fe34a68819cd12f3295d581394 https://bugzilla.redhat.com/show_bug.cgi?id=1530977
2018-11-21 13:30:16 +01:00
* @initial_state_flags: the initial state flags.
* @device: the device/interface to configure according to @connection
*
* Creates a new device-based activation request. If an applied connection is
* supplied, it shall not be modified by the caller afterwards.
*
* Returns: the new activation request on success, %NULL on error.
*/
NMActRequest *
nm_act_request_new(NMSettingsConnection * settings_connection,
NMConnection * applied_connection,
const char * specific_object,
NMAuthSubject * subject,
NMActivationType activation_type,
NMActivationReason activation_reason,
core: improve and fix keeping connection active based on "connection.permissions" By setting "connection.permissions", a profile is restricted to a particular user. That means for example, that another user cannot see, modify, delete, activate or deactivate the profile. It also means, that the profile will only autoconnect when the user is logged in (has a session). Note that root is always able to activate the profile. Likewise, the user is also allowed to manually activate the own profile, even if no session currently exists (which can easily happen with `sudo`). When the user logs out (the session goes away), we want do disconnect the profile, however there are conflicting goals here: 1) if the profile was activate by root user, then logging out the user should not disconnect the profile. The patch fixes that by not binding the activation to the connection, if the activation is done by the root user. 2) if the profile was activated by the owner when it had no session, then it should stay alive until the user logs in (once) and logs out again. This is already handled by the previous commit. Yes, this point is odd. If you first do $ sudo -u $OTHER_USER nmcli connection up $PROFILE the profile activates despite not having a session. If you then $ ssh guest@localhost nmcli device you'll still see the profile active. However, the moment the SSH session ends, a session closes and the profile disconnects. It's unclear, how to solve that any better. I think, a user who cares about this, should not activate the profile without having a session in the first place. There are quite some special cases, in particular with internal activations. In those cases we need to decide whether to bind the activation to the profile's visibility. Also, expose the "bind" setting in the D-Bus API. Note, that in the future this flag may be modified via D-Bus API. Like we may also add related API that allows to tweak the lifetime of the activation. Also, I think we broke handling of connection visiblity with 37e8c53eeed "core: Introduce helper class to track connection keep alive". This should be fixed now too, with improved behavior. Fixes: 37e8c53eeed579fe34a68819cd12f3295d581394 https://bugzilla.redhat.com/show_bug.cgi?id=1530977
2018-11-21 13:30:16 +01:00
NMActivationStateFlags initial_state_flags,
NMDevice * device)
{
g_return_val_if_fail(!settings_connection || NM_IS_SETTINGS_CONNECTION(settings_connection),
NULL);
g_return_val_if_fail(NM_IS_DEVICE(device), NULL);
g_return_val_if_fail(NM_IS_AUTH_SUBJECT(subject), NULL);
return g_object_new(NM_TYPE_ACT_REQUEST,
NM_ACTIVE_CONNECTION_INT_APPLIED_CONNECTION,
applied_connection,
NM_ACTIVE_CONNECTION_INT_SETTINGS_CONNECTION,
settings_connection,
NM_ACTIVE_CONNECTION_INT_DEVICE,
device,
NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT,
specific_object,
NM_ACTIVE_CONNECTION_INT_SUBJECT,
subject,
NM_ACTIVE_CONNECTION_INT_ACTIVATION_TYPE,
(int) activation_type,
NM_ACTIVE_CONNECTION_INT_ACTIVATION_REASON,
(int) activation_reason,
NM_ACTIVE_CONNECTION_STATE_FLAGS,
(guint) initial_state_flags,
NULL);
}
static void
dispose(GObject *object)
{
NMActRequest * self = NM_ACT_REQUEST(object);
NMActRequestPrivate * priv = NM_ACT_REQUEST_GET_PRIVATE(self);
NMActRequestGetSecretsCallId *call_id, *call_id_safe;
/* Kill any in-progress secrets requests */
c_list_for_each_entry_safe (call_id, call_id_safe, &priv->call_ids_lst_head, call_ids_lst)
_do_cancel_secrets(self, call_id, TRUE);
G_OBJECT_CLASS(nm_act_request_parent_class)->dispose(object);
}
static void
nm_act_request_class_init(NMActRequestClass *req_class)
{
GObjectClass * object_class = G_OBJECT_CLASS(req_class);
NMActiveConnectionClass *active_class = NM_ACTIVE_CONNECTION_CLASS(req_class);
/* virtual methods */
object_class->dispose = dispose;
object_class->get_property = get_property;
active_class->master_failed = master_failed;
active_class->device_state_changed = device_state_changed;
/* properties */
g_object_class_override_property(object_class,
PROP_IP4_CONFIG,
NM_ACTIVE_CONNECTION_IP4_CONFIG);
g_object_class_override_property(object_class,
PROP_DHCP4_CONFIG,
NM_ACTIVE_CONNECTION_DHCP4_CONFIG);
g_object_class_override_property(object_class,
PROP_IP6_CONFIG,
NM_ACTIVE_CONNECTION_IP6_CONFIG);
g_object_class_override_property(object_class,
PROP_DHCP6_CONFIG,
NM_ACTIVE_CONNECTION_DHCP6_CONFIG);
}