WIP: NMSysconfig: enforce access controls
This commit is contained in:
@@ -33,6 +33,7 @@
|
|||||||
Get the settings maps describing this object.
|
Get the settings maps describing this object.
|
||||||
</tp:docstring>
|
</tp:docstring>
|
||||||
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_sysconfig_connection_get_settings"/>
|
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_sysconfig_connection_get_settings"/>
|
||||||
|
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
|
||||||
<arg name="settings" type="a{sa{sv}}" direction="out" tp:type="String_String_Variant_Map_Map">
|
<arg name="settings" type="a{sa{sv}}" direction="out" tp:type="String_String_Variant_Map_Map">
|
||||||
<tp:docstring>
|
<tp:docstring>
|
||||||
The nested settings maps describing this object.
|
The nested settings maps describing this object.
|
||||||
@@ -53,7 +54,13 @@
|
|||||||
|
|
||||||
<signal name="Removed">
|
<signal name="Removed">
|
||||||
<tp:docstring>
|
<tp:docstring>
|
||||||
Emitted when this connection has been deleted/removed. After receipt of this signal, the object no longer exists.
|
Emitted when this connection is no longer available. This happens when the connection is deleted or if it is no longer accessable by any of the system's logged in users. After receipt of this signal, the object no longer exists.
|
||||||
|
</tp:docstring>
|
||||||
|
</signal>
|
||||||
|
|
||||||
|
<signal name="CheckPermissions">
|
||||||
|
<tp:docstring>
|
||||||
|
Emitted when a client's permission to access this connection may have changed. Generally, clients should re-test their ability to access this connecton whenever this signal is emmited.
|
||||||
</tp:docstring>
|
</tp:docstring>
|
||||||
</signal>
|
</signal>
|
||||||
|
|
||||||
|
@@ -22,16 +22,18 @@
|
|||||||
#include <NetworkManager.h>
|
#include <NetworkManager.h>
|
||||||
#include <dbus/dbus-glib-lowlevel.h>
|
#include <dbus/dbus-glib-lowlevel.h>
|
||||||
#include <nm-setting-connection.h>
|
#include <nm-setting-connection.h>
|
||||||
|
#include <nm-utils.h>
|
||||||
|
|
||||||
#include "nm-sysconfig-connection.h"
|
#include "nm-sysconfig-connection.h"
|
||||||
|
#include "nm-session-manager.h"
|
||||||
|
#include "nm-dbus-manager.h"
|
||||||
#include "nm-system-config-error.h"
|
#include "nm-system-config-error.h"
|
||||||
#include "nm-dbus-glib-types.h"
|
#include "nm-dbus-glib-types.h"
|
||||||
#include "nm-polkit-helpers.h"
|
#include "nm-polkit-helpers.h"
|
||||||
#include "nm-logging.h"
|
#include "nm-logging.h"
|
||||||
|
|
||||||
static gboolean impl_sysconfig_connection_get_settings (NMSysconfigConnection *connection,
|
static void impl_sysconfig_connection_get_settings (NMSysconfigConnection *connection,
|
||||||
GHashTable **settings,
|
DBusGMethodInvocation *context);
|
||||||
GError **error);
|
|
||||||
|
|
||||||
static void impl_sysconfig_connection_update (NMSysconfigConnection *connection,
|
static void impl_sysconfig_connection_update (NMSysconfigConnection *connection,
|
||||||
GHashTable *new_settings,
|
GHashTable *new_settings,
|
||||||
@@ -56,7 +58,10 @@ G_DEFINE_TYPE (NMSysconfigConnection, nm_sysconfig_connection, NM_TYPE_CONNECTIO
|
|||||||
|
|
||||||
enum {
|
enum {
|
||||||
UPDATED,
|
UPDATED,
|
||||||
|
CHECK_PERMISSIONS,
|
||||||
REMOVED,
|
REMOVED,
|
||||||
|
PURGED,
|
||||||
|
UNHIDDEN,
|
||||||
|
|
||||||
LAST_SIGNAL
|
LAST_SIGNAL
|
||||||
};
|
};
|
||||||
@@ -64,12 +69,220 @@ static guint signals[LAST_SIGNAL] = { 0 };
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PolkitAuthority *authority;
|
PolkitAuthority *authority;
|
||||||
GSList *pk_calls;
|
GSList *pending_auths; /* List of PendingAuth structs*/
|
||||||
NMConnection *secrets;
|
NMConnection *secrets;
|
||||||
|
gboolean visible; /* Is this connection is visible by some session? */
|
||||||
|
GHashTable *access_list; /* Sessions that may access this connection. */
|
||||||
} NMSysconfigConnectionPrivate;
|
} NMSysconfigConnectionPrivate;
|
||||||
|
|
||||||
/**************************************************************/
|
/**************************************************************/
|
||||||
|
|
||||||
|
/* Returns true iff the given session should be permitted to access this
|
||||||
|
* connection. Used to update the access list */
|
||||||
|
static gboolean
|
||||||
|
session_allowed (NMSysconfigConnection *connection,
|
||||||
|
NMSessionInfo *session)
|
||||||
|
{
|
||||||
|
NMSettingConnection *setting_connection = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (connection), NM_TYPE_SETTING_CONNECTION);
|
||||||
|
GSList *permissions_entries;
|
||||||
|
char *session_user;
|
||||||
|
GSList *session_groups;
|
||||||
|
GSList *p_iter;
|
||||||
|
gboolean allowed = FALSE;
|
||||||
|
|
||||||
|
g_object_get (setting_connection, NM_SETTING_CONNECTION_PERMISSIONS, &permissions_entries, NULL);
|
||||||
|
|
||||||
|
/* If permissions list is empty, the connection is world-accessible. */
|
||||||
|
if (permissions_entries == NULL) {
|
||||||
|
allowed = TRUE;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The "default session" can only access world-accessible connections. */
|
||||||
|
if (nm_session_info_is_default_session (session)) {
|
||||||
|
allowed = FALSE;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
session_user = nm_session_info_get_unix_user (session);
|
||||||
|
session_groups = nm_session_info_get_unix_groups (session);
|
||||||
|
|
||||||
|
for (p_iter = permissions_entries; p_iter != NULL; p_iter = p_iter->next) {
|
||||||
|
char **p_comps = g_strsplit ((char *)p_iter->data, ":", 3);
|
||||||
|
char *type = p_comps[0];
|
||||||
|
char *name = p_comps[1];
|
||||||
|
|
||||||
|
if (g_str_equal (type, "user")) {
|
||||||
|
if (g_str_equal (session_user, name)) {
|
||||||
|
allowed = TRUE;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (g_str_equal (type, "group")) {
|
||||||
|
GSList *g_iter;
|
||||||
|
|
||||||
|
for (g_iter = session_groups; g_iter != NULL; g_iter = g_iter->next ) {
|
||||||
|
char *group_name = (char *) g_iter->data;
|
||||||
|
if (g_str_equal (group_name, name)) {
|
||||||
|
allowed = TRUE;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nm_log_err (LOGD_SYS_SET,
|
||||||
|
"connection %s: failed to parse permissions entry '%s'",
|
||||||
|
nm_setting_connection_get_id (setting_connection),
|
||||||
|
(char *) p_iter->data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
nm_utils_slist_free (permissions_entries, g_free);
|
||||||
|
return allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_visibility (NMSysconfigConnection *self, gboolean new_visibility)
|
||||||
|
{
|
||||||
|
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
|
||||||
|
DBusGConnection *connection = nm_dbus_manager_get_connection (nm_dbus_manager_get());
|
||||||
|
const char *dbus_path = nm_connection_get_path (NM_CONNECTION (self));
|
||||||
|
|
||||||
|
if (new_visibility && !priv->visible) {
|
||||||
|
priv->visible = TRUE;
|
||||||
|
|
||||||
|
dbus_g_connection_register_g_object (connection, dbus_path, G_OBJECT (self));
|
||||||
|
g_signal_emit (self, signals[UNHIDDEN], 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (!new_visibility && priv->visible) {
|
||||||
|
priv->visible = FALSE;
|
||||||
|
|
||||||
|
g_signal_emit (self, signals[REMOVED], 0);
|
||||||
|
dbus_g_connection_unregister_g_object (connection, G_OBJECT (self));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* One of the sessions on our access list has been removed. */
|
||||||
|
static void
|
||||||
|
session_removed_cb (NMSessionInfo *removed_session,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
NMSysconfigConnection *connection = NM_SYSCONFIG_CONNECTION (user_data);
|
||||||
|
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (connection);
|
||||||
|
char *removed_session_id = nm_session_info_get_id (removed_session);
|
||||||
|
|
||||||
|
g_hash_table_remove (priv->access_list, removed_session_id);
|
||||||
|
|
||||||
|
if (g_hash_table_size (priv->access_list) == 0) {
|
||||||
|
set_visibility (connection, FALSE);
|
||||||
|
} else {
|
||||||
|
g_signal_emit (connection, signals[CHECK_PERMISSIONS], 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The session manager reports that a new session has been added. */
|
||||||
|
static void
|
||||||
|
session_added_cb (NMSessionManager *mananager,
|
||||||
|
NMSessionInfo *session,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
NMSysconfigConnection *connection = NM_SYSCONFIG_CONNECTION (user_data);
|
||||||
|
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (connection);
|
||||||
|
|
||||||
|
if (session_allowed (connection, session)) {
|
||||||
|
g_object_ref (session);
|
||||||
|
g_signal_connect (session, NM_SESSION_INFO_REMOVED,
|
||||||
|
G_CALLBACK(session_removed_cb), connection);
|
||||||
|
g_hash_table_insert (priv->access_list, nm_session_info_get_id (session), session);
|
||||||
|
g_signal_emit (connection, signals[CHECK_PERMISSIONS], 0);
|
||||||
|
set_visibility (connection, TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Our permissions property may have been changed. Update the access list. */
|
||||||
|
static void
|
||||||
|
update_access_list (NMSysconfigConnection *connection)
|
||||||
|
{
|
||||||
|
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (connection);
|
||||||
|
NMSessionManager *session_manager = nm_session_manager_get();
|
||||||
|
GSList *sessions = nm_session_manager_get_sessions (session_manager);
|
||||||
|
GSList *iter;
|
||||||
|
|
||||||
|
if (!priv->access_list)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_hash_table_remove_all (priv->access_list);
|
||||||
|
for (iter = sessions; iter != NULL; iter = iter->next) {
|
||||||
|
NMSessionInfo *session = (NMSessionInfo *) iter->data;
|
||||||
|
if (session_allowed (connection, iter->data)) {
|
||||||
|
g_object_ref (session);
|
||||||
|
g_signal_connect (session, NM_SESSION_INFO_REMOVED,
|
||||||
|
G_CALLBACK(session_removed_cb), connection);
|
||||||
|
g_hash_table_insert (priv->access_list, nm_session_info_get_id (session), session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_hash_table_size (priv->access_list) == 0) {
|
||||||
|
set_visibility (connection, FALSE);
|
||||||
|
} else {
|
||||||
|
g_signal_emit (connection, signals[CHECK_PERMISSIONS], 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nm_sysconfig_connection_is_visible (NMSysconfigConnection *connection)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (NM_SYSCONFIG_CONNECTION (connection), FALSE);
|
||||||
|
|
||||||
|
return NM_SYSCONFIG_CONNECTION_GET_PRIVATE (connection)->visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
prepend_slist (gpointer key, gpointer value, gpointer user_data)
|
||||||
|
{
|
||||||
|
GSList **sessions = (GSList **) user_data;
|
||||||
|
|
||||||
|
*sessions = g_slist_prepend (*sessions, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
GSList *
|
||||||
|
nm_sysconfig_connection_get_session_access_list (NMSysconfigConnection *connection)
|
||||||
|
{
|
||||||
|
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (connection);
|
||||||
|
GSList *sessions = NULL;
|
||||||
|
|
||||||
|
if (priv->access_list)
|
||||||
|
g_hash_table_foreach (priv->access_list, prepend_slist, &sessions);
|
||||||
|
|
||||||
|
return sessions;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nm_sysconfig_connection_is_accessible_by_session (NMSysconfigConnection *connection,
|
||||||
|
NMSessionInfo *session)
|
||||||
|
{
|
||||||
|
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (connection);
|
||||||
|
NMSessionInfo *stored_session = NULL;
|
||||||
|
|
||||||
|
g_return_val_if_fail (NM_IS_SYSCONFIG_CONNECTION (connection), FALSE);
|
||||||
|
g_return_val_if_fail (NM_IS_SESSION_INFO (session), FALSE);
|
||||||
|
|
||||||
|
if (!priv->access_list)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
stored_session = g_hash_table_lookup (priv->access_list,
|
||||||
|
nm_session_info_get_id (session));
|
||||||
|
|
||||||
|
if (stored_session == session)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************/
|
||||||
|
|
||||||
/* Update the settings of this connection to match that of 'new', taking care to
|
/* Update the settings of this connection to match that of 'new', taking care to
|
||||||
* make a private copy of secrets. */
|
* make a private copy of secrets. */
|
||||||
gboolean
|
gboolean
|
||||||
@@ -98,6 +311,8 @@ nm_sysconfig_connection_replace_settings (NMSysconfigConnection *self,
|
|||||||
g_object_unref (priv->secrets);
|
g_object_unref (priv->secrets);
|
||||||
priv->secrets = nm_connection_duplicate (NM_CONNECTION (self));
|
priv->secrets = nm_connection_duplicate (NM_CONNECTION (self));
|
||||||
|
|
||||||
|
update_access_list (self);
|
||||||
|
|
||||||
success = TRUE;
|
success = TRUE;
|
||||||
}
|
}
|
||||||
g_hash_table_destroy (new_settings);
|
g_hash_table_destroy (new_settings);
|
||||||
@@ -254,7 +469,8 @@ do_delete (NMSysconfigConnection *connection,
|
|||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
g_object_ref (connection);
|
g_object_ref (connection);
|
||||||
g_signal_emit (connection, signals[REMOVED], 0);
|
set_visibility (connection, FALSE);
|
||||||
|
g_signal_emit (connection, signals[PURGED], 0);
|
||||||
callback (connection, NULL, user_data);
|
callback (connection, NULL, user_data);
|
||||||
g_object_unref (connection);
|
g_object_unref (connection);
|
||||||
}
|
}
|
||||||
@@ -388,28 +604,158 @@ get_secrets (NMSysconfigConnection *connection,
|
|||||||
g_hash_table_destroy (settings);
|
g_hash_table_destroy (settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************/
|
/**** User authorization **************************************/
|
||||||
|
|
||||||
static gboolean
|
typedef void (*AuthCallback) (NMSysconfigConnection *connection,
|
||||||
impl_sysconfig_connection_get_settings (NMSysconfigConnection *self,
|
DBusGMethodInvocation *context,
|
||||||
GHashTable **settings,
|
GError *error,
|
||||||
GError **error)
|
gpointer data);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
NMSysconfigConnection *self;
|
||||||
|
DBusGMethodInvocation *context;
|
||||||
|
PolkitSubject *subject;
|
||||||
|
GCancellable *cancellable;
|
||||||
|
gboolean check_modify;
|
||||||
|
gboolean disposed;
|
||||||
|
|
||||||
|
AuthCallback callback;
|
||||||
|
gpointer callback_data;
|
||||||
|
} PendingAuth;
|
||||||
|
|
||||||
|
static void
|
||||||
|
auth_finish (PendingAuth *info, GError *error)
|
||||||
{
|
{
|
||||||
NMConnection *no_secrets;
|
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (info->self);
|
||||||
|
priv->pending_auths = g_slist_remove (priv->pending_auths, info);
|
||||||
|
|
||||||
/* Secrets should *never* be returned by the GetSettings method, they
|
info->callback (info->self, info->context, error, info->callback_data);
|
||||||
* get returned by the GetSecrets method which can be better
|
|
||||||
* protected against leakage of secrets to unprivileged callers.
|
if (info->subject)
|
||||||
*/
|
g_object_unref (info->subject);
|
||||||
no_secrets = nm_connection_duplicate (NM_CONNECTION (self));
|
if (info->cancellable)
|
||||||
g_assert (no_secrets);
|
g_object_unref (info->cancellable);
|
||||||
nm_connection_clear_secrets (no_secrets);
|
|
||||||
*settings = nm_connection_to_hash (no_secrets);
|
g_slice_free (PendingAuth, info);
|
||||||
g_assert (*settings);
|
|
||||||
g_object_unref (no_secrets);
|
|
||||||
return *settings ? TRUE : FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
auth_pk_cb (GObject *object, GAsyncResult *result, gpointer user_data)
|
||||||
|
{
|
||||||
|
PendingAuth *info = user_data;
|
||||||
|
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (info->self);
|
||||||
|
PolkitAuthorizationResult *pk_result;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
if (info->disposed) {
|
||||||
|
error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
|
||||||
|
NM_SYSCONFIG_SETTINGS_ERROR_GENERAL,
|
||||||
|
"Request was canceled.");
|
||||||
|
auth_finish (info, error);
|
||||||
|
g_error_free (error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pk_result = polkit_authority_check_authorization_finish (priv->authority,
|
||||||
|
result,
|
||||||
|
&error);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
auth_finish (info, error);
|
||||||
|
g_error_free (error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!polkit_authorization_result_get_is_authorized (pk_result)) {
|
||||||
|
error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
|
||||||
|
NM_SYSCONFIG_SETTINGS_ERROR_NOT_PRIVILEGED,
|
||||||
|
"Insufficient privileges.");
|
||||||
|
auth_finish (info, error);
|
||||||
|
g_error_free (error);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
auth_finish (info, NULL);
|
||||||
|
|
||||||
|
out:
|
||||||
|
g_object_unref (pk_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
auth_get_session_cb (NMSessionInfo *session,
|
||||||
|
GError *session_error,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
PendingAuth *info = user_data;
|
||||||
|
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (info->self);
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
if (info->disposed || !session) {
|
||||||
|
error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
|
||||||
|
NM_SYSCONFIG_SETTINGS_ERROR_GENERAL,
|
||||||
|
"Request was canceled.");
|
||||||
|
auth_finish (info, error);
|
||||||
|
g_error_free (error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nm_sysconfig_connection_is_accessible_by_session (info->self, session)) {
|
||||||
|
error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
|
||||||
|
NM_SYSCONFIG_SETTINGS_ERROR_PERMISSION_DENIED,
|
||||||
|
"Caller's session is not authorized to access connection.");
|
||||||
|
auth_finish (info, error);
|
||||||
|
g_error_free (error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!info->check_modify) {
|
||||||
|
auth_finish (info, NULL);
|
||||||
|
} else {
|
||||||
|
char *sender = dbus_g_method_get_sender (info->context);
|
||||||
|
info->subject = polkit_system_bus_name_new (sender);
|
||||||
|
info->cancellable = g_cancellable_new();
|
||||||
|
g_free (sender);
|
||||||
|
|
||||||
|
polkit_authority_check_authorization (priv->authority,
|
||||||
|
info->subject,
|
||||||
|
NM_SYSCONFIG_POLICY_ACTION_CONNECTION_MODIFY,
|
||||||
|
NULL,
|
||||||
|
POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
|
||||||
|
info->cancellable,
|
||||||
|
auth_pk_cb,
|
||||||
|
info);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
auth_start (NMSysconfigConnection *self,
|
||||||
|
DBusGMethodInvocation *context,
|
||||||
|
gboolean check_modify,
|
||||||
|
AuthCallback callback,
|
||||||
|
gpointer callback_data)
|
||||||
|
{
|
||||||
|
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
|
||||||
|
PendingAuth *info = g_slice_new (PendingAuth);
|
||||||
|
info->self = self;
|
||||||
|
info->context = context;
|
||||||
|
info->subject = NULL;
|
||||||
|
info->cancellable = NULL;
|
||||||
|
info->check_modify = check_modify;
|
||||||
|
info->disposed = FALSE;
|
||||||
|
info->callback_data = callback_data;
|
||||||
|
|
||||||
|
priv->pending_auths = g_slist_prepend (priv->pending_auths, info);
|
||||||
|
|
||||||
|
nm_session_manager_get_session_of_caller (nm_session_manager_get(),
|
||||||
|
context,
|
||||||
|
auth_get_session_cb,
|
||||||
|
info);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**** DBus method handlers ************************************/
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
check_writable (NMConnection *connection, GError **error)
|
check_writable (NMConnection *connection, GError **error)
|
||||||
{
|
{
|
||||||
@@ -443,65 +789,41 @@ check_writable (NMConnection *connection, GError **error)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
static void
|
||||||
NMSysconfigConnection *self;
|
get_settings_auth_cb (NMSysconfigConnection *self,
|
||||||
DBusGMethodInvocation *context;
|
|
||||||
PolkitSubject *subject;
|
|
||||||
GCancellable *cancellable;
|
|
||||||
gboolean disposed;
|
|
||||||
|
|
||||||
/* Update */
|
|
||||||
NMConnection *connection;
|
|
||||||
|
|
||||||
/* Secrets */
|
|
||||||
char *setting_name;
|
|
||||||
char **hints;
|
|
||||||
gboolean request_new;
|
|
||||||
} PolkitCall;
|
|
||||||
|
|
||||||
static PolkitCall *
|
|
||||||
polkit_call_new (NMSysconfigConnection *self,
|
|
||||||
DBusGMethodInvocation *context,
|
DBusGMethodInvocation *context,
|
||||||
NMConnection *connection,
|
GError *error,
|
||||||
const char *setting_name,
|
gpointer data)
|
||||||
const char **hints,
|
|
||||||
gboolean request_new)
|
|
||||||
{
|
{
|
||||||
PolkitCall *call;
|
NMConnection *no_secrets;
|
||||||
char *sender;
|
GHashTable *settings;
|
||||||
|
|
||||||
g_return_val_if_fail (self != NULL, NULL);
|
if (error) {
|
||||||
g_return_val_if_fail (context != NULL, NULL);
|
dbus_g_method_return_error (context, error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
call = g_malloc0 (sizeof (PolkitCall));
|
/* Secrets should *never* be returned by the GetSettings method, they
|
||||||
call->self = self;
|
* get returned by the GetSecrets method which can be better
|
||||||
call->context = context;
|
* protected against leakage of secrets to unprivileged callers.
|
||||||
call->cancellable = g_cancellable_new ();
|
*/
|
||||||
call->connection = connection;
|
no_secrets = nm_connection_duplicate (NM_CONNECTION (self));
|
||||||
call->setting_name = g_strdup (setting_name);
|
g_assert (no_secrets);
|
||||||
if (hints)
|
nm_connection_clear_secrets (no_secrets);
|
||||||
call->hints = g_strdupv ((char **) hints);
|
settings = nm_connection_to_hash (no_secrets);
|
||||||
call->request_new = request_new;
|
g_assert (settings);
|
||||||
|
|
||||||
sender = dbus_g_method_get_sender (context);
|
dbus_g_method_return (context, settings);
|
||||||
call->subject = polkit_system_bus_name_new (sender);
|
|
||||||
g_free (sender);
|
|
||||||
|
|
||||||
return call;
|
g_object_unref (no_secrets);
|
||||||
|
g_object_unref (settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
polkit_call_free (PolkitCall *call)
|
impl_sysconfig_connection_get_settings (NMSysconfigConnection *self,
|
||||||
|
DBusGMethodInvocation *context)
|
||||||
{
|
{
|
||||||
if (call->connection)
|
auth_start (self, context, FALSE, get_settings_auth_cb, NULL);
|
||||||
g_object_unref (call->connection);
|
|
||||||
g_free (call->setting_name);
|
|
||||||
if (call->hints)
|
|
||||||
g_strfreev (call->hints);
|
|
||||||
|
|
||||||
g_object_unref (call->subject);
|
|
||||||
g_object_unref (call->cancellable);
|
|
||||||
g_free (call);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -509,70 +831,35 @@ con_update_cb (NMSysconfigConnection *connection,
|
|||||||
GError *error,
|
GError *error,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
PolkitCall *call = user_data;
|
DBusGMethodInvocation *context = user_data;
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
dbus_g_method_return_error (call->context, error);
|
dbus_g_method_return_error (context, error);
|
||||||
else
|
else
|
||||||
dbus_g_method_return (call->context);
|
dbus_g_method_return (context);
|
||||||
|
|
||||||
polkit_call_free (call);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pk_update_cb (GObject *object, GAsyncResult *result, gpointer user_data)
|
update_auth_cb (NMSysconfigConnection *self,
|
||||||
|
DBusGMethodInvocation *context,
|
||||||
|
GError *error,
|
||||||
|
gpointer data)
|
||||||
{
|
{
|
||||||
PolkitCall *call = user_data;
|
NMConnection *new_settings = data;
|
||||||
NMSysconfigConnection *self = call->self;
|
|
||||||
NMSysconfigConnectionPrivate *priv;
|
|
||||||
PolkitAuthorizationResult *pk_result;
|
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
/* If our NMSysconfigConnection is already gone, do nothing */
|
|
||||||
if (call->disposed) {
|
|
||||||
error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
|
|
||||||
NM_SYSCONFIG_SETTINGS_ERROR_GENERAL,
|
|
||||||
"Request was canceled.");
|
|
||||||
dbus_g_method_return_error (call->context, error);
|
|
||||||
g_error_free (error);
|
|
||||||
polkit_call_free (call);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
|
|
||||||
|
|
||||||
priv->pk_calls = g_slist_remove (priv->pk_calls, call);
|
|
||||||
|
|
||||||
pk_result = polkit_authority_check_authorization_finish (priv->authority,
|
|
||||||
result,
|
|
||||||
&error);
|
|
||||||
/* Some random error happened */
|
|
||||||
if (error) {
|
if (error) {
|
||||||
dbus_g_method_return_error (call->context, error);
|
dbus_g_method_return_error (context, error);
|
||||||
g_error_free (error);
|
|
||||||
polkit_call_free (call);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Caller didn't successfully authenticate */
|
|
||||||
if (!polkit_authorization_result_get_is_authorized (pk_result)) {
|
|
||||||
error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
|
|
||||||
NM_SYSCONFIG_SETTINGS_ERROR_NOT_PRIVILEGED,
|
|
||||||
"Insufficient privileges.");
|
|
||||||
dbus_g_method_return_error (call->context, error);
|
|
||||||
g_error_free (error);
|
|
||||||
polkit_call_free (call);
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update and commit our settings. */
|
/* Update and commit our settings. */
|
||||||
nm_sysconfig_connection_replace_and_commit (self,
|
nm_sysconfig_connection_replace_and_commit (self,
|
||||||
call->connection,
|
new_settings,
|
||||||
con_update_cb,
|
con_update_cb,
|
||||||
call);
|
context);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
g_object_unref (pk_result);
|
g_object_unref (new_settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -580,8 +867,6 @@ impl_sysconfig_connection_update (NMSysconfigConnection *self,
|
|||||||
GHashTable *new_settings,
|
GHashTable *new_settings,
|
||||||
DBusGMethodInvocation *context)
|
DBusGMethodInvocation *context)
|
||||||
{
|
{
|
||||||
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
|
|
||||||
PolkitCall *call;
|
|
||||||
NMConnection *tmp;
|
NMConnection *tmp;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
|
||||||
@@ -604,17 +889,7 @@ impl_sysconfig_connection_update (NMSysconfigConnection *self,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
call = polkit_call_new (self, context, tmp, NULL, NULL, FALSE);
|
auth_start (self, context, TRUE, update_auth_cb, tmp);
|
||||||
g_assert (call);
|
|
||||||
polkit_authority_check_authorization (priv->authority,
|
|
||||||
call->subject,
|
|
||||||
NM_SYSCONFIG_POLICY_ACTION_CONNECTION_MODIFY,
|
|
||||||
NULL,
|
|
||||||
POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
|
|
||||||
call->cancellable,
|
|
||||||
pk_update_cb,
|
|
||||||
call);
|
|
||||||
priv->pk_calls = g_slist_prepend (priv->pk_calls, call);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -622,75 +897,32 @@ con_delete_cb (NMSysconfigConnection *connection,
|
|||||||
GError *error,
|
GError *error,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
PolkitCall *call = user_data;
|
DBusGMethodInvocation *context = user_data;
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
dbus_g_method_return_error (call->context, error);
|
dbus_g_method_return_error (context, error);
|
||||||
else
|
else
|
||||||
dbus_g_method_return (call->context);
|
dbus_g_method_return (context);
|
||||||
|
|
||||||
polkit_call_free (call);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pk_delete_cb (GObject *object, GAsyncResult *result, gpointer user_data)
|
delete_auth_cb (NMSysconfigConnection *self,
|
||||||
|
DBusGMethodInvocation *context,
|
||||||
|
GError *error,
|
||||||
|
gpointer data)
|
||||||
{
|
{
|
||||||
PolkitCall *call = user_data;
|
|
||||||
NMSysconfigConnection *self = call->self;
|
|
||||||
NMSysconfigConnectionPrivate *priv;
|
|
||||||
PolkitAuthorizationResult *pk_result;
|
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
/* If our NMSysconfigConnection is already gone, do nothing */
|
|
||||||
if (call->disposed) {
|
|
||||||
error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
|
|
||||||
NM_SYSCONFIG_SETTINGS_ERROR_GENERAL,
|
|
||||||
"Request was canceled.");
|
|
||||||
dbus_g_method_return_error (call->context, error);
|
|
||||||
g_error_free (error);
|
|
||||||
polkit_call_free (call);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
|
|
||||||
|
|
||||||
priv->pk_calls = g_slist_remove (priv->pk_calls, call);
|
|
||||||
|
|
||||||
pk_result = polkit_authority_check_authorization_finish (priv->authority,
|
|
||||||
result,
|
|
||||||
&error);
|
|
||||||
/* Some random error happened */
|
|
||||||
if (error) {
|
if (error) {
|
||||||
dbus_g_method_return_error (call->context, error);
|
dbus_g_method_return_error (context, error);
|
||||||
g_error_free (error);
|
|
||||||
polkit_call_free (call);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Caller didn't successfully authenticate */
|
nm_sysconfig_connection_delete (self, con_delete_cb, context);
|
||||||
if (!polkit_authorization_result_get_is_authorized (pk_result)) {
|
|
||||||
error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
|
|
||||||
NM_SYSCONFIG_SETTINGS_ERROR_NOT_PRIVILEGED,
|
|
||||||
"Insufficient privileges.");
|
|
||||||
dbus_g_method_return_error (call->context, error);
|
|
||||||
g_error_free (error);
|
|
||||||
polkit_call_free (call);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Caller is authenticated, now we can finally try to delete */
|
|
||||||
nm_sysconfig_connection_delete (self, con_delete_cb, call);
|
|
||||||
|
|
||||||
out:
|
|
||||||
g_object_unref (pk_result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
impl_sysconfig_connection_delete (NMSysconfigConnection *self,
|
impl_sysconfig_connection_delete (NMSysconfigConnection *self,
|
||||||
DBusGMethodInvocation *context)
|
DBusGMethodInvocation *context)
|
||||||
{
|
{
|
||||||
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
|
|
||||||
PolkitCall *call;
|
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
|
||||||
if (!check_writable (NM_CONNECTION (self), &error)) {
|
if (!check_writable (NM_CONNECTION (self), &error)) {
|
||||||
@@ -699,91 +931,53 @@ impl_sysconfig_connection_delete (NMSysconfigConnection *self,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
call = polkit_call_new (self, context, NULL, NULL, NULL, FALSE);
|
auth_start (self, context, TRUE, delete_auth_cb, NULL);
|
||||||
g_assert (call);
|
|
||||||
polkit_authority_check_authorization (priv->authority,
|
|
||||||
call->subject,
|
|
||||||
NM_SYSCONFIG_POLICY_ACTION_CONNECTION_MODIFY,
|
|
||||||
NULL,
|
|
||||||
POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
|
|
||||||
call->cancellable,
|
|
||||||
pk_delete_cb,
|
|
||||||
call);
|
|
||||||
priv->pk_calls = g_slist_prepend (priv->pk_calls, call);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *setting_name;
|
||||||
|
char **hints;
|
||||||
|
gboolean request_new;
|
||||||
|
} GetSecretsInfo;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
con_secrets_cb (NMSysconfigConnection *connection,
|
con_secrets_cb (NMSysconfigConnection *connection,
|
||||||
GHashTable *secrets,
|
GHashTable *secrets,
|
||||||
GError *error,
|
GError *error,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
PolkitCall *call = user_data;
|
DBusGMethodInvocation *context = user_data;
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
dbus_g_method_return_error (call->context, error);
|
dbus_g_method_return_error (context, error);
|
||||||
else
|
else
|
||||||
dbus_g_method_return (call->context, secrets);
|
dbus_g_method_return (context, secrets);
|
||||||
|
|
||||||
polkit_call_free (call);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pk_secrets_cb (GObject *object, GAsyncResult *result, gpointer user_data)
|
secrets_auth_cb (NMSysconfigConnection *self,
|
||||||
|
DBusGMethodInvocation *context,
|
||||||
|
GError *error,
|
||||||
|
gpointer data)
|
||||||
{
|
{
|
||||||
PolkitCall *call = user_data;
|
GetSecretsInfo *info = data;
|
||||||
NMSysconfigConnection *self = call->self;
|
|
||||||
NMSysconfigConnectionPrivate *priv;
|
|
||||||
PolkitAuthorizationResult *pk_result;
|
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
/* If our NMSysconfigConnection is already gone, do nothing */
|
|
||||||
if (call->disposed) {
|
|
||||||
error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
|
|
||||||
NM_SYSCONFIG_SETTINGS_ERROR_GENERAL,
|
|
||||||
"Request was canceled.");
|
|
||||||
dbus_g_method_return_error (call->context, error);
|
|
||||||
g_error_free (error);
|
|
||||||
polkit_call_free (call);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
|
|
||||||
|
|
||||||
priv->pk_calls = g_slist_remove (priv->pk_calls, call);
|
|
||||||
|
|
||||||
pk_result = polkit_authority_check_authorization_finish (priv->authority,
|
|
||||||
result,
|
|
||||||
&error);
|
|
||||||
/* Some random error happened */
|
|
||||||
if (error) {
|
if (error) {
|
||||||
dbus_g_method_return_error (call->context, error);
|
dbus_g_method_return_error (context, error);
|
||||||
g_error_free (error);
|
|
||||||
polkit_call_free (call);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Caller didn't successfully authenticate */
|
|
||||||
if (!polkit_authorization_result_get_is_authorized (pk_result)) {
|
|
||||||
error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
|
|
||||||
NM_SYSCONFIG_SETTINGS_ERROR_NOT_PRIVILEGED,
|
|
||||||
"Insufficient privileges.");
|
|
||||||
dbus_g_method_return_error (call->context, error);
|
|
||||||
g_error_free (error);
|
|
||||||
polkit_call_free (call);
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Caller is authenticated, now we can finally try to update */
|
|
||||||
nm_sysconfig_connection_get_secrets (self,
|
nm_sysconfig_connection_get_secrets (self,
|
||||||
call->setting_name,
|
info->setting_name,
|
||||||
(const char **) call->hints,
|
(const char **) info->hints,
|
||||||
call->request_new,
|
info->request_new,
|
||||||
con_secrets_cb,
|
con_secrets_cb,
|
||||||
call);
|
context);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
g_object_unref (pk_result);
|
g_free (info->setting_name);
|
||||||
|
g_strfreev (info->hints);
|
||||||
|
g_slice_free (GetSecretsInfo, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -793,20 +987,12 @@ impl_sysconfig_connection_get_secrets (NMSysconfigConnection *self,
|
|||||||
gboolean request_new,
|
gboolean request_new,
|
||||||
DBusGMethodInvocation *context)
|
DBusGMethodInvocation *context)
|
||||||
{
|
{
|
||||||
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
|
GetSecretsInfo *info = g_slice_new (GetSecretsInfo);
|
||||||
PolkitCall *call;
|
info->setting_name = g_strdup (setting_name);
|
||||||
|
info->hints = g_strdupv ((char **) hints);
|
||||||
|
info->request_new = request_new;
|
||||||
|
|
||||||
call = polkit_call_new (self, context, NULL, setting_name, hints, request_new);
|
auth_start (self, context, TRUE, secrets_auth_cb, info);
|
||||||
g_assert (call);
|
|
||||||
polkit_authority_check_authorization (priv->authority,
|
|
||||||
call->subject,
|
|
||||||
NM_SYSCONFIG_POLICY_ACTION_CONNECTION_MODIFY,
|
|
||||||
NULL,
|
|
||||||
POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
|
|
||||||
call->cancellable,
|
|
||||||
pk_secrets_cb,
|
|
||||||
call);
|
|
||||||
priv->pk_calls = g_slist_prepend (priv->pk_calls, call);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************/
|
/**************************************************************/
|
||||||
@@ -815,11 +1001,34 @@ static void
|
|||||||
nm_sysconfig_connection_init (NMSysconfigConnection *self)
|
nm_sysconfig_connection_init (NMSysconfigConnection *self)
|
||||||
{
|
{
|
||||||
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
|
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
|
||||||
|
NMSessionManager *session_manager;
|
||||||
|
static guint32 dbus_counter = 0;
|
||||||
|
char *dbus_path;
|
||||||
|
|
||||||
priv->authority = polkit_authority_get ();
|
priv->authority = polkit_authority_get ();
|
||||||
if (!priv->authority) {
|
if (!priv->authority) {
|
||||||
nm_log_err (LOGD_SYS_SET, "%s: error creating PolicyKit authority");
|
nm_log_err (LOGD_SYS_SET, "%s:error creating PolicyKit authority");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dbus_path = g_strdup_printf ("%s/%u", NM_DBUS_PATH_SETTINGS, dbus_counter++);
|
||||||
|
nm_connection_set_path (NM_CONNECTION (self), dbus_path);
|
||||||
|
g_free (dbus_path);
|
||||||
|
priv->visible = FALSE;
|
||||||
|
|
||||||
|
priv->access_list = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
|
||||||
|
session_manager = nm_session_manager_get();
|
||||||
|
g_signal_connect (session_manager, NM_SESSION_MANAGER_SESSION_ADDED,
|
||||||
|
G_CALLBACK (session_added_cb), self);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
access_list_dispose (gpointer key, gpointer value, gpointer user_data)
|
||||||
|
{
|
||||||
|
NMSysconfigConnection *connection = (NMSysconfigConnection *) user_data;
|
||||||
|
NMSessionInfo *session = (NMSessionInfo *) value;
|
||||||
|
|
||||||
|
g_signal_handlers_disconnect_by_func (session, session_removed_cb, connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -827,20 +1036,27 @@ dispose (GObject *object)
|
|||||||
{
|
{
|
||||||
NMSysconfigConnection *self = NM_SYSCONFIG_CONNECTION (object);
|
NMSysconfigConnection *self = NM_SYSCONFIG_CONNECTION (object);
|
||||||
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
|
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
|
||||||
|
NMSessionManager *session_manager = nm_session_manager_get ();
|
||||||
GSList *iter;
|
GSList *iter;
|
||||||
|
|
||||||
if (priv->secrets)
|
if (priv->secrets)
|
||||||
g_object_unref (priv->secrets);
|
g_object_unref (priv->secrets);
|
||||||
|
|
||||||
/* Cancel PolicyKit requests */
|
/* Cancel PolicyKit requests */
|
||||||
for (iter = priv->pk_calls; iter; iter = g_slist_next (iter)) {
|
for (iter = priv->pending_auths; iter; iter = g_slist_next (iter)) {
|
||||||
PolkitCall *call = iter->data;
|
PendingAuth *call = iter->data;
|
||||||
|
|
||||||
call->disposed = TRUE;
|
call->disposed = TRUE;
|
||||||
g_cancellable_cancel (call->cancellable);
|
g_cancellable_cancel (call->cancellable);
|
||||||
}
|
}
|
||||||
g_slist_free (priv->pk_calls);
|
g_slist_free (priv->pending_auths);
|
||||||
priv->pk_calls = NULL;
|
priv->pending_auths = NULL;
|
||||||
|
|
||||||
|
set_visibility (self, FALSE);
|
||||||
|
g_signal_handlers_disconnect_by_func (session_manager, session_added_cb, self);
|
||||||
|
g_hash_table_foreach (priv->access_list, access_list_dispose, self);
|
||||||
|
g_hash_table_unref (priv->access_list);
|
||||||
|
priv->access_list = NULL;
|
||||||
|
|
||||||
G_OBJECT_CLASS (nm_sysconfig_connection_parent_class)->dispose (object);
|
G_OBJECT_CLASS (nm_sysconfig_connection_parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
@@ -877,6 +1093,24 @@ nm_sysconfig_connection_class_init (NMSysconfigConnectionClass *class)
|
|||||||
g_cclosure_marshal_VOID__VOID,
|
g_cclosure_marshal_VOID__VOID,
|
||||||
G_TYPE_NONE, 0);
|
G_TYPE_NONE, 0);
|
||||||
|
|
||||||
|
signals[PURGED] =
|
||||||
|
g_signal_new (NM_SYSCONFIG_CONNECTION_PURGED,
|
||||||
|
G_TYPE_FROM_CLASS (class),
|
||||||
|
G_SIGNAL_RUN_FIRST,
|
||||||
|
0,
|
||||||
|
NULL, NULL,
|
||||||
|
g_cclosure_marshal_VOID__VOID,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
|
||||||
|
signals[UNHIDDEN] =
|
||||||
|
g_signal_new (NM_SYSCONFIG_CONNECTION_UNHIDDEN,
|
||||||
|
G_TYPE_FROM_CLASS (class),
|
||||||
|
G_SIGNAL_RUN_FIRST,
|
||||||
|
0,
|
||||||
|
NULL, NULL,
|
||||||
|
g_cclosure_marshal_VOID__VOID,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
|
||||||
dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (class),
|
dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (class),
|
||||||
&dbus_glib_nm_sysconfig_connection_object_info);
|
&dbus_glib_nm_sysconfig_connection_object_info);
|
||||||
|
|
||||||
|
@@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include <nm-connection.h>
|
#include <nm-connection.h>
|
||||||
#include <dbus/dbus-glib.h>
|
#include <dbus/dbus-glib.h>
|
||||||
|
#include "nm-session-info.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
@@ -35,6 +36,8 @@ G_BEGIN_DECLS
|
|||||||
|
|
||||||
#define NM_SYSCONFIG_CONNECTION_UPDATED "updated"
|
#define NM_SYSCONFIG_CONNECTION_UPDATED "updated"
|
||||||
#define NM_SYSCONFIG_CONNECTION_REMOVED "removed"
|
#define NM_SYSCONFIG_CONNECTION_REMOVED "removed"
|
||||||
|
#define NM_SYSCONFIG_CONNECTION_PURGED "purged"
|
||||||
|
#define NM_SYSCONFIG_CONNECTION_UNHIDDEN "unhidden"
|
||||||
|
|
||||||
typedef struct _NMSysconfigConnection NMSysconfigConnection;
|
typedef struct _NMSysconfigConnection NMSysconfigConnection;
|
||||||
|
|
||||||
@@ -102,6 +105,14 @@ void nm_sysconfig_connection_get_secrets (NMSysconfigConnection *connection,
|
|||||||
NMSysconfigConnectionGetSecretsFunc callback,
|
NMSysconfigConnectionGetSecretsFunc callback,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
|
|
||||||
|
gboolean nm_sysconfig_connection_is_visible (NMSysconfigConnection *connection);
|
||||||
|
|
||||||
|
gboolean nm_sysconfig_connection_is_accessible_by_session (NMSysconfigConnection *connection,
|
||||||
|
NMSessionInfo *session);
|
||||||
|
|
||||||
|
GSList * nm_sysconfig_connection_get_session_access_list (NMSysconfigConnection *connection);
|
||||||
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* NM_SYSCONFIG_CONNECTION_H */
|
#endif /* NM_SYSCONFIG_CONNECTION_H */
|
||||||
|
@@ -112,7 +112,8 @@ typedef struct {
|
|||||||
|
|
||||||
GSList *plugins;
|
GSList *plugins;
|
||||||
gboolean connections_loaded;
|
gboolean connections_loaded;
|
||||||
GHashTable *connections;
|
GHashTable *visible_connections;
|
||||||
|
GHashTable *all_connections;
|
||||||
GSList *unmanaged_specs;
|
GSList *unmanaged_specs;
|
||||||
} NMSysconfigSettingsPrivate;
|
} NMSysconfigSettingsPrivate;
|
||||||
|
|
||||||
@@ -186,7 +187,7 @@ nm_sysconfig_settings_list_connections (NMSysconfigSettings *settings)
|
|||||||
|
|
||||||
load_connections (settings);
|
load_connections (settings);
|
||||||
|
|
||||||
g_hash_table_iter_init (&iter, priv->connections);
|
g_hash_table_iter_init (&iter, priv->visible_connections);
|
||||||
while (g_hash_table_iter_next (&iter, &key, NULL))
|
while (g_hash_table_iter_next (&iter, &key, NULL))
|
||||||
list = g_slist_prepend (list, NM_SYSCONFIG_CONNECTION (key));
|
list = g_slist_prepend (list, NM_SYSCONFIG_CONNECTION (key));
|
||||||
return g_slist_reverse (list);
|
return g_slist_reverse (list);
|
||||||
@@ -536,28 +537,28 @@ connection_removed (NMSysconfigConnection *connection,
|
|||||||
{
|
{
|
||||||
NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (user_data);
|
NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (user_data);
|
||||||
|
|
||||||
g_hash_table_remove (priv->connections, connection);
|
g_hash_table_remove (priv->visible_connections, connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
export_connection (NMSysconfigConnection *connection)
|
connection_unhidden (NMSysconfigConnection *connection,
|
||||||
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
DBusGConnection *bus;
|
NMSysconfigSettings *settings = user_data;
|
||||||
static guint32 ec_counter = 0;
|
NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (settings);
|
||||||
char *path;
|
|
||||||
|
|
||||||
g_return_if_fail (connection != NULL);
|
g_hash_table_insert (priv->visible_connections,
|
||||||
g_return_if_fail (NM_IS_SYSCONFIG_CONNECTION (connection));
|
connection, GINT_TO_POINTER (1));
|
||||||
|
g_signal_emit (settings, signals[NEW_CONNECTION], 0, connection);
|
||||||
|
}
|
||||||
|
|
||||||
/* Don't allow exporting twice */
|
static void
|
||||||
g_return_if_fail (nm_connection_get_path (NM_CONNECTION (connection)) == NULL);
|
connection_purged (NMSysconfigConnection *connection,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (user_data);
|
||||||
|
|
||||||
path = g_strdup_printf ("%s/%u", NM_DBUS_PATH_SETTINGS, ec_counter++);
|
g_hash_table_remove (priv->all_connections, connection);
|
||||||
nm_connection_set_path (NM_CONNECTION (connection), path);
|
|
||||||
|
|
||||||
bus = nm_dbus_manager_get_connection (nm_dbus_manager_get ());
|
|
||||||
dbus_g_connection_register_g_object (bus, path, G_OBJECT (connection));
|
|
||||||
g_free (path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -570,22 +571,33 @@ claim_connection (NMSysconfigSettings *self,
|
|||||||
g_return_if_fail (NM_IS_SYSCONFIG_SETTINGS (self));
|
g_return_if_fail (NM_IS_SYSCONFIG_SETTINGS (self));
|
||||||
g_return_if_fail (NM_IS_SYSCONFIG_CONNECTION (connection));
|
g_return_if_fail (NM_IS_SYSCONFIG_CONNECTION (connection));
|
||||||
|
|
||||||
if (g_hash_table_lookup (priv->connections, connection))
|
if (g_hash_table_lookup (priv->all_connections, connection))
|
||||||
/* A plugin is lying to us. */
|
/* A plugin is lying to us. */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
g_hash_table_insert (priv->connections, g_object_ref (connection), GINT_TO_POINTER (1));
|
g_hash_table_insert (priv->all_connections, g_object_ref (connection), GINT_TO_POINTER (1));
|
||||||
g_signal_connect (connection,
|
g_signal_connect (connection,
|
||||||
NM_SYSCONFIG_CONNECTION_REMOVED,
|
NM_SYSCONFIG_CONNECTION_REMOVED,
|
||||||
G_CALLBACK (connection_removed),
|
G_CALLBACK (connection_removed),
|
||||||
self);
|
self);
|
||||||
|
g_signal_connect (connection,
|
||||||
|
NM_SYSCONFIG_CONNECTION_PURGED,
|
||||||
|
G_CALLBACK (connection_purged),
|
||||||
|
self);
|
||||||
|
g_signal_connect (connection,
|
||||||
|
NM_SYSCONFIG_CONNECTION_UNHIDDEN,
|
||||||
|
G_CALLBACK (connection_unhidden),
|
||||||
|
self);
|
||||||
|
|
||||||
if (do_export) {
|
if (nm_sysconfig_connection_is_visible (connection)) {
|
||||||
export_connection (connection);
|
g_hash_table_insert (priv->visible_connections, connection, GINT_TO_POINTER (1));
|
||||||
g_signal_emit (self, signals[NEW_CONNECTION], 0, connection);
|
g_signal_emit (self, signals[NEW_CONNECTION], 0, connection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO it seems that this is only ever used to remove a
|
||||||
|
// NMDefaultWiredConnection, and it probably needs to stay that way. So this
|
||||||
|
// *needs* a better name!
|
||||||
static void
|
static void
|
||||||
remove_connection (NMSysconfigSettings *self,
|
remove_connection (NMSysconfigSettings *self,
|
||||||
NMSysconfigConnection *connection,
|
NMSysconfigConnection *connection,
|
||||||
@@ -593,9 +605,14 @@ remove_connection (NMSysconfigSettings *self,
|
|||||||
{
|
{
|
||||||
NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
|
NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
|
||||||
|
|
||||||
if (g_hash_table_lookup (priv->connections, connection)) {
|
if (g_hash_table_lookup (priv->visible_connections, connection)) {
|
||||||
g_signal_emit_by_name (G_OBJECT (connection), NM_SYSCONFIG_CONNECTION_REMOVED);
|
g_signal_emit_by_name (G_OBJECT (connection), NM_SYSCONFIG_CONNECTION_REMOVED);
|
||||||
g_hash_table_remove (priv->connections, connection);
|
g_hash_table_remove (priv->visible_connections, connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_hash_table_lookup (priv->all_connections, connection)) {
|
||||||
|
g_signal_emit_by_name (G_OBJECT (connection), NM_SYSCONFIG_CONNECTION_PURGED);
|
||||||
|
g_hash_table_remove (priv->all_connections, connection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1056,7 +1073,7 @@ have_connection_for_device (NMSysconfigSettings *self, GByteArray *mac)
|
|||||||
g_return_val_if_fail (mac != NULL, FALSE);
|
g_return_val_if_fail (mac != NULL, FALSE);
|
||||||
|
|
||||||
/* Find a wired connection locked to the given MAC address, if any */
|
/* Find a wired connection locked to the given MAC address, if any */
|
||||||
g_hash_table_iter_init (&iter, priv->connections);
|
g_hash_table_iter_init (&iter, priv->visible_connections);
|
||||||
while (g_hash_table_iter_next (&iter, &key, NULL)) {
|
while (g_hash_table_iter_next (&iter, &key, NULL)) {
|
||||||
NMConnection *connection = NM_CONNECTION (key);
|
NMConnection *connection = NM_CONNECTION (key);
|
||||||
const char *connection_type;
|
const char *connection_type;
|
||||||
@@ -1442,7 +1459,8 @@ finalize (GObject *object)
|
|||||||
NMSysconfigSettings *self = NM_SYSCONFIG_SETTINGS (object);
|
NMSysconfigSettings *self = NM_SYSCONFIG_SETTINGS (object);
|
||||||
NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
|
NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
|
||||||
|
|
||||||
g_hash_table_destroy (priv->connections);
|
g_hash_table_destroy (priv->visible_connections);
|
||||||
|
g_hash_table_destroy (priv->all_connections);
|
||||||
|
|
||||||
clear_unmanaged_specs (self);
|
clear_unmanaged_specs (self);
|
||||||
|
|
||||||
@@ -1584,7 +1602,8 @@ nm_sysconfig_settings_init (NMSysconfigSettings *self)
|
|||||||
{
|
{
|
||||||
NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
|
NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
|
||||||
|
|
||||||
priv->connections = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL);
|
priv->visible_connections = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||||
|
priv->all_connections = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL);
|
||||||
|
|
||||||
priv->authority = polkit_authority_get ();
|
priv->authority = polkit_authority_get ();
|
||||||
if (priv->authority) {
|
if (priv->authority) {
|
||||||
|
Reference in New Issue
Block a user