core: re-implement device disconnect using generic auth request signal
This commit is contained in:
@@ -63,6 +63,7 @@
|
|||||||
#include "nm-settings-connection.h"
|
#include "nm-settings-connection.h"
|
||||||
#include "nm-connection-provider.h"
|
#include "nm-connection-provider.h"
|
||||||
#include "nm-posix-signals.h"
|
#include "nm-posix-signals.h"
|
||||||
|
#include "nm-manager-auth.h"
|
||||||
|
|
||||||
static void impl_device_disconnect (NMDevice *device, DBusGMethodInvocation *context);
|
static void impl_device_disconnect (NMDevice *device, DBusGMethodInvocation *context);
|
||||||
|
|
||||||
@@ -89,7 +90,6 @@ nm_device_error_quark (void)
|
|||||||
|
|
||||||
enum {
|
enum {
|
||||||
STATE_CHANGED,
|
STATE_CHANGED,
|
||||||
DISCONNECT_REQUEST,
|
|
||||||
AUTOCONNECT_ALLOWED,
|
AUTOCONNECT_ALLOWED,
|
||||||
AUTH_REQUEST,
|
AUTH_REQUEST,
|
||||||
LAST_SIGNAL,
|
LAST_SIGNAL,
|
||||||
@@ -3187,32 +3187,56 @@ nm_device_deactivate (NMDevice *self, NMDeviceStateReason reason)
|
|||||||
nm_device_set_ip6_config (self, NULL, &ignored);
|
nm_device_set_ip6_config (self, NULL, &ignored);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
static void
|
||||||
nm_device_disconnect (NMDevice *device, GError **error)
|
disconnect_cb (NMDevice *device,
|
||||||
|
DBusGMethodInvocation *context,
|
||||||
|
GError *error,
|
||||||
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
NMDevicePrivate *priv;
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
|
||||||
|
GError *local = NULL;
|
||||||
|
|
||||||
g_return_val_if_fail (device != NULL, FALSE);
|
if (error)
|
||||||
g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
|
dbus_g_method_return_error (context, error);
|
||||||
|
else {
|
||||||
priv = NM_DEVICE_GET_PRIVATE (device);
|
/* Authorized */
|
||||||
if (priv->state <= NM_DEVICE_STATE_DISCONNECTED) {
|
if (priv->state <= NM_DEVICE_STATE_DISCONNECTED) {
|
||||||
g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_NOT_ACTIVE,
|
local = g_error_new_literal (NM_DEVICE_ERROR,
|
||||||
"Cannot disconnect an inactive device.");
|
NM_DEVICE_ERROR_NOT_ACTIVE,
|
||||||
return FALSE;
|
"Device is not active");
|
||||||
|
dbus_g_method_return_error (context, local);
|
||||||
|
g_error_free (local);
|
||||||
|
} else {
|
||||||
|
priv->autoconnect = FALSE;
|
||||||
|
nm_device_state_changed (device,
|
||||||
|
NM_DEVICE_STATE_DISCONNECTED,
|
||||||
|
NM_DEVICE_STATE_REASON_USER_REQUESTED);
|
||||||
|
dbus_g_method_return (context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->autoconnect = FALSE;
|
|
||||||
nm_device_state_changed (device,
|
|
||||||
NM_DEVICE_STATE_DISCONNECTED,
|
|
||||||
NM_DEVICE_STATE_REASON_USER_REQUESTED);
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
impl_device_disconnect (NMDevice *device, DBusGMethodInvocation *context)
|
impl_device_disconnect (NMDevice *device, DBusGMethodInvocation *context)
|
||||||
{
|
{
|
||||||
g_signal_emit (device, signals[DISCONNECT_REQUEST], 0, context);
|
GError *error = NULL;
|
||||||
|
|
||||||
|
if (NM_DEVICE_GET_PRIVATE (device)->act_request == NULL) {
|
||||||
|
error = g_error_new_literal (NM_DEVICE_ERROR,
|
||||||
|
NM_DEVICE_ERROR_NOT_ACTIVE,
|
||||||
|
"This device is not active");
|
||||||
|
dbus_g_method_return_error (context, error);
|
||||||
|
g_error_free (error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ask the manager to authenticate this request for us */
|
||||||
|
g_signal_emit (device, signals[AUTH_REQUEST], 0,
|
||||||
|
context,
|
||||||
|
NM_AUTH_PERMISSION_NETWORK_CONTROL,
|
||||||
|
TRUE,
|
||||||
|
disconnect_cb,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@@ -4141,14 +4165,6 @@ nm_device_class_init (NMDeviceClass *klass)
|
|||||||
G_TYPE_NONE, 3,
|
G_TYPE_NONE, 3,
|
||||||
G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT);
|
G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT);
|
||||||
|
|
||||||
signals[DISCONNECT_REQUEST] =
|
|
||||||
g_signal_new (NM_DEVICE_DISCONNECT_REQUEST,
|
|
||||||
G_OBJECT_CLASS_TYPE (object_class),
|
|
||||||
G_SIGNAL_RUN_FIRST,
|
|
||||||
0, NULL, NULL,
|
|
||||||
g_cclosure_marshal_VOID__POINTER,
|
|
||||||
G_TYPE_NONE, 1, G_TYPE_POINTER);
|
|
||||||
|
|
||||||
signals[AUTOCONNECT_ALLOWED] =
|
signals[AUTOCONNECT_ALLOWED] =
|
||||||
g_signal_new ("autoconnect-allowed",
|
g_signal_new ("autoconnect-allowed",
|
||||||
G_OBJECT_CLASS_TYPE (object_class),
|
G_OBJECT_CLASS_TYPE (object_class),
|
||||||
|
@@ -59,7 +59,6 @@
|
|||||||
#define NM_DEVICE_IFINDEX "ifindex" /* Internal only */
|
#define NM_DEVICE_IFINDEX "ifindex" /* Internal only */
|
||||||
|
|
||||||
/* Internal signal */
|
/* Internal signal */
|
||||||
#define NM_DEVICE_DISCONNECT_REQUEST "disconnect-request"
|
|
||||||
#define NM_DEVICE_AUTH_REQUEST "auth-request"
|
#define NM_DEVICE_AUTH_REQUEST "auth-request"
|
||||||
|
|
||||||
|
|
||||||
@@ -269,8 +268,6 @@ gboolean nm_device_get_firmware_missing (NMDevice *self);
|
|||||||
|
|
||||||
gboolean nm_device_activate (NMDevice *device, NMActRequest *req, GError **error);
|
gboolean nm_device_activate (NMDevice *device, NMActRequest *req, GError **error);
|
||||||
|
|
||||||
gboolean nm_device_disconnect (NMDevice *device, GError **error);
|
|
||||||
|
|
||||||
void nm_device_set_connection_provider (NMDevice *device, NMConnectionProvider *provider);
|
void nm_device_set_connection_provider (NMDevice *device, NMConnectionProvider *provider);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
126
src/nm-manager.c
126
src/nm-manager.c
@@ -1532,114 +1532,6 @@ manager_modem_enabled_changed (NMModem *device, gpointer user_data)
|
|||||||
nm_manager_rfkill_update (NM_MANAGER (user_data), RFKILL_TYPE_WWAN);
|
nm_manager_rfkill_update (NM_MANAGER (user_data), RFKILL_TYPE_WWAN);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GError *
|
|
||||||
deactivate_disconnect_check_error (GError *auth_error,
|
|
||||||
NMAuthCallResult result,
|
|
||||||
const char *detail)
|
|
||||||
{
|
|
||||||
if (auth_error) {
|
|
||||||
nm_log_dbg (LOGD_CORE, "%s request failed: %s", detail, auth_error->message);
|
|
||||||
return g_error_new (NM_MANAGER_ERROR,
|
|
||||||
NM_MANAGER_ERROR_PERMISSION_DENIED,
|
|
||||||
"%s request failed: %s",
|
|
||||||
detail, auth_error->message);
|
|
||||||
} else if (result != NM_AUTH_CALL_RESULT_YES) {
|
|
||||||
return g_error_new (NM_MANAGER_ERROR,
|
|
||||||
NM_MANAGER_ERROR_PERMISSION_DENIED,
|
|
||||||
"Not authorized to %s connections",
|
|
||||||
detail);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
disconnect_net_auth_done_cb (NMAuthChain *chain,
|
|
||||||
GError *auth_error,
|
|
||||||
DBusGMethodInvocation *context,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
NMManager *self = NM_MANAGER (user_data);
|
|
||||||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
|
|
||||||
GError *error = NULL;
|
|
||||||
NMAuthCallResult result;
|
|
||||||
NMDevice *device;
|
|
||||||
|
|
||||||
priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
|
|
||||||
|
|
||||||
result = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL));
|
|
||||||
error = deactivate_disconnect_check_error (auth_error, result, "Disconnect");
|
|
||||||
if (!error) {
|
|
||||||
device = nm_auth_chain_get_data (chain, "device");
|
|
||||||
if (!nm_device_disconnect (device, &error))
|
|
||||||
g_assert (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error)
|
|
||||||
dbus_g_method_return_error (context, error);
|
|
||||||
else
|
|
||||||
dbus_g_method_return (context);
|
|
||||||
|
|
||||||
g_clear_error (&error);
|
|
||||||
nm_auth_chain_unref (chain);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
manager_device_disconnect_request (NMDevice *device,
|
|
||||||
DBusGMethodInvocation *context,
|
|
||||||
NMManager *self)
|
|
||||||
{
|
|
||||||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
|
|
||||||
NMActRequest *req;
|
|
||||||
GError *error = NULL;
|
|
||||||
gulong sender_uid = G_MAXULONG;
|
|
||||||
char *error_desc = NULL;
|
|
||||||
|
|
||||||
req = nm_device_get_act_request (device);
|
|
||||||
if (!req) {
|
|
||||||
error = g_error_new_literal (NM_MANAGER_ERROR,
|
|
||||||
NM_MANAGER_ERROR_UNKNOWN_CONNECTION,
|
|
||||||
"This device is not active");
|
|
||||||
dbus_g_method_return_error (context, error);
|
|
||||||
g_error_free (error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Need to check the caller's permissions and stuff before we can
|
|
||||||
* deactivate the connection.
|
|
||||||
*/
|
|
||||||
if (!nm_auth_get_caller_uid (context,
|
|
||||||
priv->dbus_mgr,
|
|
||||||
&sender_uid,
|
|
||||||
&error_desc)) {
|
|
||||||
error = g_error_new_literal (NM_MANAGER_ERROR,
|
|
||||||
NM_MANAGER_ERROR_PERMISSION_DENIED,
|
|
||||||
error_desc);
|
|
||||||
dbus_g_method_return_error (context, error);
|
|
||||||
g_error_free (error);
|
|
||||||
g_free (error_desc);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Yay for root */
|
|
||||||
if (0 == sender_uid) {
|
|
||||||
if (!nm_device_disconnect (device, &error)) {
|
|
||||||
dbus_g_method_return_error (context, error);
|
|
||||||
g_clear_error (&error);
|
|
||||||
} else
|
|
||||||
dbus_g_method_return (context);
|
|
||||||
} else {
|
|
||||||
NMAuthChain *chain;
|
|
||||||
|
|
||||||
/* Otherwise validate the user request */
|
|
||||||
chain = nm_auth_chain_new (context, NULL, disconnect_net_auth_done_cb, self);
|
|
||||||
g_assert (chain);
|
|
||||||
priv->auth_chains = g_slist_append (priv->auth_chains, chain);
|
|
||||||
|
|
||||||
nm_auth_chain_set_data (chain, "device", g_object_ref (device), g_object_unref);
|
|
||||||
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
device_auth_done_cb (NMAuthChain *chain,
|
device_auth_done_cb (NMAuthChain *chain,
|
||||||
GError *auth_error,
|
GError *auth_error,
|
||||||
@@ -1772,10 +1664,6 @@ add_device (NMManager *self, NMDevice *device)
|
|||||||
G_CALLBACK (manager_device_state_changed),
|
G_CALLBACK (manager_device_state_changed),
|
||||||
self);
|
self);
|
||||||
|
|
||||||
g_signal_connect (device, NM_DEVICE_DISCONNECT_REQUEST,
|
|
||||||
G_CALLBACK (manager_device_disconnect_request),
|
|
||||||
self);
|
|
||||||
|
|
||||||
g_signal_connect (device, NM_DEVICE_AUTH_REQUEST,
|
g_signal_connect (device, NM_DEVICE_AUTH_REQUEST,
|
||||||
G_CALLBACK (device_auth_request_cb),
|
G_CALLBACK (device_auth_request_cb),
|
||||||
self);
|
self);
|
||||||
@@ -3082,8 +2970,18 @@ deactivate_net_auth_done_cb (NMAuthChain *chain,
|
|||||||
priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
|
priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
|
||||||
|
|
||||||
result = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL));
|
result = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL));
|
||||||
error = deactivate_disconnect_check_error (auth_error, result, "Deactivate");
|
if (auth_error) {
|
||||||
if (!error) {
|
nm_log_dbg (LOGD_CORE, "Disconnect request failed: %s", auth_error->message);
|
||||||
|
error = g_error_new (NM_MANAGER_ERROR,
|
||||||
|
NM_MANAGER_ERROR_PERMISSION_DENIED,
|
||||||
|
"Deactivate request failed: %s",
|
||||||
|
auth_error->message);
|
||||||
|
} else if (result != NM_AUTH_CALL_RESULT_YES) {
|
||||||
|
error = g_error_new_literal (NM_MANAGER_ERROR,
|
||||||
|
NM_MANAGER_ERROR_PERMISSION_DENIED,
|
||||||
|
"Not authorized to deactivate connections");
|
||||||
|
} else {
|
||||||
|
/* success; deactivation allowed */
|
||||||
active_path = nm_auth_chain_get_data (chain, "path");
|
active_path = nm_auth_chain_get_data (chain, "path");
|
||||||
if (!nm_manager_deactivate_connection (self,
|
if (!nm_manager_deactivate_connection (self,
|
||||||
active_path,
|
active_path,
|
||||||
|
Reference in New Issue
Block a user