mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-21 07:30:31 +01:00
settings: rework scheduling of authorization requests in settings-connection
Get rid of the NMAuthChain layer. I think NMAuthChain only makes sense if we schedule multiple requests together for the same topic. But NMSettingsConnection never does that: each D-Bus request corresponds to only one polkit authorization request. So, we can just call NMAuthManager directly.
This commit is contained in:
parent
6ab0939e34
commit
9385c7a7cf
1 changed files with 74 additions and 65 deletions
|
|
@ -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 */
|
||||
|
||||
|
|
@ -1361,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,
|
||||
|
|
@ -1369,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_destroy (chain);
|
||||
g_object_unref (auth_data->invocation);
|
||||
g_object_unref (auth_data->subject);
|
||||
g_slice_free (AuthData, auth_data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1436,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 ************************************/
|
||||
|
|
@ -2067,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;
|
||||
|
||||
|
|
@ -2276,18 +2291,14 @@ void
|
|||
nm_settings_connection_signal_remove (NMSettingsConnection *self)
|
||||
{
|
||||
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
|
||||
GSList *pending_auth;
|
||||
AuthData *auth_data;
|
||||
|
||||
if (priv->removed)
|
||||
return;
|
||||
priv->removed = TRUE;
|
||||
|
||||
while ((pending_auth = priv->pending_auths)) {
|
||||
NMAuthChain *chain = pending_auth->data;
|
||||
|
||||
priv->pending_auths = g_slist_delete_link (priv->pending_auths, pending_auth);
|
||||
nm_auth_chain_destroy (chain);
|
||||
}
|
||||
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,
|
||||
|
|
@ -2977,6 +2988,7 @@ nm_settings_connection_init (NMSettingsConnection *self)
|
|||
|
||||
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,
|
||||
|
|
@ -3013,6 +3025,7 @@ 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) {
|
||||
|
|
@ -3031,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_destroy);
|
||||
priv->pending_auths = NULL;
|
||||
|
||||
g_clear_pointer (&priv->seen_bssids, g_hash_table_destroy);
|
||||
|
||||
set_visible (self, FALSE);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue