mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-07-22 02:35:25 +00:00
This commit is contained in:
parent
6810ef1422
commit
716a9c6c0d
|
@ -44,6 +44,14 @@ object. dbus-glib generates the same bound function names for D-Bus the methods
|
|||
<arg name="enable" type="b" direction="in"/>
|
||||
</method>
|
||||
|
||||
<method name="GetPermissions">
|
||||
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_manager_get_permissions"/>
|
||||
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
|
||||
<arg name="permissions" type="a{ss}" direction="out"/>
|
||||
</method>
|
||||
|
||||
<signal name="CheckPermissions"/>
|
||||
|
||||
<property name="NetworkingEnabled" type="b" access="read"/>
|
||||
<property name="WirelessEnabled" type="b" access="readwrite"/>
|
||||
<property name="WirelessHardwareEnabled" type="b" access="read"/>
|
||||
|
|
|
@ -116,6 +116,34 @@
|
|||
</arg>
|
||||
</method>
|
||||
|
||||
<method name="GetPermissions">
|
||||
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_manager_get_permissions"/>
|
||||
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
|
||||
<tp:docstring>
|
||||
Returns the permissions a caller has for various authenticated operations
|
||||
that NetworkManager provides, like Enable/Disable networking, changing
|
||||
WiFi, WWAN, and WiMAX state, etc.
|
||||
</tp:docstring>
|
||||
<arg name="permissions" type="a{ss}" direction="out">
|
||||
<tp:docstring>
|
||||
Dictionary of available permissions and results. Each permission
|
||||
is represented by a name (ie "org.freedesktop.NetworkManager.Foobar")
|
||||
and each result is one of the following values: "yes" (the permission
|
||||
is available), "auth" (the permission is available after a successful
|
||||
authentication), or "no" (the permission is denied). Clients may use
|
||||
these values in the UI to indicate the ability to perform certain
|
||||
operations.
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
</method>
|
||||
|
||||
<signal name="CheckPermissions">
|
||||
<tp:docstring>
|
||||
Emitted when system authorization details change, indicating that
|
||||
clients may wish to recheck permissions with GetPermissions.
|
||||
</tp:docstring>
|
||||
</signal>
|
||||
|
||||
<method name="SetLogging">
|
||||
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_manager_set_logging"/>
|
||||
<tp:docstring>
|
||||
|
|
|
@ -34,6 +34,7 @@ global:
|
|||
nm_client_get_device_by_path;
|
||||
nm_client_get_devices;
|
||||
nm_client_get_manager_running;
|
||||
nm_client_get_permission_result;
|
||||
nm_client_get_state;
|
||||
nm_client_get_type;
|
||||
nm_client_networking_get_enabled;
|
||||
|
|
|
@ -58,6 +58,9 @@ typedef struct {
|
|||
GPtrArray *devices;
|
||||
GPtrArray *active_connections;
|
||||
|
||||
DBusGProxyCall *perm_call;
|
||||
GHashTable *permissions;
|
||||
|
||||
gboolean have_networking_enabled;
|
||||
gboolean networking_enabled;
|
||||
gboolean wireless_enabled;
|
||||
|
@ -84,6 +87,7 @@ enum {
|
|||
enum {
|
||||
DEVICE_ADDED,
|
||||
DEVICE_REMOVED,
|
||||
PERMISSION_CHANGED,
|
||||
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
@ -118,6 +122,8 @@ nm_client_init (NMClient *client)
|
|||
|
||||
priv->state = NM_STATE_UNKNOWN;
|
||||
|
||||
priv->permissions = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
|
||||
g_signal_connect (client,
|
||||
"notify::" NM_CLIENT_NETWORKING_ENABLED,
|
||||
G_CALLBACK (handle_net_enabled_changed),
|
||||
|
@ -284,6 +290,114 @@ register_for_property_changed (NMClient *client)
|
|||
property_changed_info);
|
||||
}
|
||||
|
||||
#define NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK "org.freedesktop.NetworkManager.enable-disable-network"
|
||||
#define NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI "org.freedesktop.NetworkManager.enable-disable-wifi"
|
||||
#define NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN "org.freedesktop.NetworkManager.enable-disable-wwan"
|
||||
#define NM_AUTH_PERMISSION_USE_USER_CONNECTIONS "org.freedesktop.NetworkManager.use-user-connections"
|
||||
|
||||
static NMClientPermission
|
||||
nm_permission_to_client (const char *nm)
|
||||
{
|
||||
if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK))
|
||||
return NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK;
|
||||
else if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI))
|
||||
return NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI;
|
||||
else if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN))
|
||||
return NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN;
|
||||
else if (!strcmp (nm, NM_AUTH_PERMISSION_USE_USER_CONNECTIONS))
|
||||
return NM_CLIENT_PERMISSION_USE_USER_CONNECTIONS;
|
||||
return NM_CLIENT_PERMISSION_NONE;
|
||||
}
|
||||
|
||||
static NMClientPermissionResult
|
||||
nm_permission_result_to_client (const char *nm)
|
||||
{
|
||||
if (!strcmp (nm, "yes"))
|
||||
return NM_CLIENT_PERMISSION_RESULT_YES;
|
||||
else if (!strcmp (nm, "no"))
|
||||
return NM_CLIENT_PERMISSION_RESULT_NO;
|
||||
else if (!strcmp (nm, "auth"))
|
||||
return NM_CLIENT_PERMISSION_RESULT_AUTH;
|
||||
return NM_CLIENT_PERMISSION_RESULT_UNKNOWN;
|
||||
}
|
||||
|
||||
static void
|
||||
get_permissions_reply (DBusGProxy *proxy,
|
||||
GHashTable *permissions,
|
||||
GError *error,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMClient *self = NM_CLIENT (user_data);
|
||||
NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self);
|
||||
GHashTableIter iter;
|
||||
gpointer key, value;
|
||||
NMClientPermission perm;
|
||||
NMClientPermissionResult perm_result;
|
||||
GList *keys, *keys_iter;
|
||||
|
||||
priv->perm_call = NULL;
|
||||
|
||||
/* get list of old permissions for change notification */
|
||||
keys = g_hash_table_get_keys (priv->permissions);
|
||||
g_hash_table_remove_all (priv->permissions);
|
||||
|
||||
if (!error) {
|
||||
/* Process new permissions */
|
||||
g_hash_table_iter_init (&iter, permissions);
|
||||
while (g_hash_table_iter_next (&iter, &key, &value)) {
|
||||
perm = nm_permission_to_client ((const char *) key);
|
||||
perm_result = nm_permission_result_to_client ((const char *) value);
|
||||
if (perm) {
|
||||
g_hash_table_insert (priv->permissions,
|
||||
GUINT_TO_POINTER (perm),
|
||||
GUINT_TO_POINTER (perm_result));
|
||||
|
||||
/* Remove this permission from the list of previous permissions
|
||||
* we'll be sending NM_CLIENT_PERMISSION_RESULT_UNKNOWN for
|
||||
* in the change signal since it is still a known permission.
|
||||
*/
|
||||
keys = g_list_remove (keys, GUINT_TO_POINTER (perm));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Signal changes in all updated permissions */
|
||||
g_hash_table_iter_init (&iter, priv->permissions);
|
||||
while (g_hash_table_iter_next (&iter, &key, &value)) {
|
||||
g_signal_emit (self, signals[PERMISSION_CHANGED], 0,
|
||||
GPOINTER_TO_UINT (key),
|
||||
GPOINTER_TO_UINT (value));
|
||||
}
|
||||
|
||||
/* And signal changes in all permissions that used to be valid but for
|
||||
* some reason weren't received in the last request (if any).
|
||||
*/
|
||||
for (keys_iter = keys; keys_iter; keys_iter = g_list_next (keys_iter)) {
|
||||
g_signal_emit (self, signals[PERMISSION_CHANGED], 0,
|
||||
GPOINTER_TO_UINT (keys_iter->data),
|
||||
NM_CLIENT_PERMISSION_RESULT_UNKNOWN);
|
||||
}
|
||||
g_list_free (keys);
|
||||
}
|
||||
|
||||
static DBusGProxyCall *
|
||||
get_permissions (NMClient *self)
|
||||
{
|
||||
return org_freedesktop_NetworkManager_get_permissions_async (NM_CLIENT_GET_PRIVATE (self)->client_proxy,
|
||||
get_permissions_reply,
|
||||
self);
|
||||
}
|
||||
|
||||
static void
|
||||
client_recheck_permissions (DBusGProxy *proxy, gpointer user_data)
|
||||
{
|
||||
NMClient *self = NM_CLIENT (user_data);
|
||||
NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self);
|
||||
|
||||
if (!priv->perm_call)
|
||||
priv->perm_call = get_permissions (self);
|
||||
}
|
||||
|
||||
static GObject*
|
||||
constructor (GType type,
|
||||
guint n_construct_params,
|
||||
|
@ -324,6 +438,15 @@ constructor (GType type,
|
|||
object,
|
||||
NULL);
|
||||
|
||||
/* Permissions */
|
||||
dbus_g_proxy_add_signal (priv->client_proxy, "CheckPermissions", G_TYPE_INVALID);
|
||||
dbus_g_proxy_connect_signal (priv->client_proxy,
|
||||
"CheckPermissions",
|
||||
G_CALLBACK (client_recheck_permissions),
|
||||
object,
|
||||
NULL);
|
||||
priv->perm_call = get_permissions (NM_CLIENT (object));
|
||||
|
||||
priv->bus_proxy = dbus_g_proxy_new_for_name (connection,
|
||||
"org.freedesktop.DBus",
|
||||
"/org/freedesktop/DBus",
|
||||
|
@ -381,12 +504,17 @@ dispose (GObject *object)
|
|||
return;
|
||||
}
|
||||
|
||||
if (priv->perm_call)
|
||||
dbus_g_proxy_cancel_call (priv->client_proxy, priv->perm_call);
|
||||
|
||||
g_object_unref (priv->client_proxy);
|
||||
g_object_unref (priv->bus_proxy);
|
||||
|
||||
free_object_array (&priv->devices);
|
||||
free_object_array (&priv->active_connections);
|
||||
|
||||
g_hash_table_destroy (priv->permissions);
|
||||
|
||||
G_OBJECT_CLASS (nm_client_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
|
@ -626,6 +754,22 @@ nm_client_class_init (NMClientClass *client_class)
|
|||
g_cclosure_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE, 1,
|
||||
G_TYPE_OBJECT);
|
||||
|
||||
/**
|
||||
* NMClient::permission-changed:
|
||||
* @widget: the client that received the signal
|
||||
* @permission: a permission from #NMClientPermission
|
||||
* @result: the permission's result, one of #NMClientPermissionResult
|
||||
*
|
||||
* Notifies that a permission has changed
|
||||
**/
|
||||
signals[PERMISSION_CHANGED] =
|
||||
g_signal_new ("permission-changed",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
0, NULL, NULL,
|
||||
_nm_marshal_VOID__UINT_UINT,
|
||||
G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1158,3 +1302,25 @@ nm_client_get_manager_running (NMClient *client)
|
|||
return NM_CLIENT_GET_PRIVATE (client)->manager_running;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_client_get_permission_result:
|
||||
* @client: a #NMClient
|
||||
* @permission: the permission for which to return the result, one of #NMClientPermission
|
||||
*
|
||||
* Requests the result of a specific permission, which indicates whether the
|
||||
* client can or cannot perform the action the permission represents
|
||||
*
|
||||
* Returns: the permission's result, one of #NMClientPermissionResult
|
||||
**/
|
||||
NMClientPermissionResult
|
||||
nm_client_get_permission_result (NMClient *client, NMClientPermission permission)
|
||||
{
|
||||
gpointer result;
|
||||
|
||||
g_return_val_if_fail (NM_IS_CLIENT (client), NM_CLIENT_PERMISSION_RESULT_UNKNOWN);
|
||||
|
||||
result = g_hash_table_lookup (NM_CLIENT_GET_PRIVATE (client)->permissions,
|
||||
GUINT_TO_POINTER (permission));
|
||||
return GPOINTER_TO_UINT (result);
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,25 @@ G_BEGIN_DECLS
|
|||
#define NM_CLIENT_WWAN_HARDWARE_ENABLED "wwan-hardware-enabled"
|
||||
#define NM_CLIENT_ACTIVE_CONNECTIONS "active-connections"
|
||||
|
||||
/* Permissions */
|
||||
typedef enum {
|
||||
NM_CLIENT_PERMISSION_NONE = 0,
|
||||
NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK = 1,
|
||||
NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI = 2,
|
||||
NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN = 3,
|
||||
NM_CLIENT_PERMISSION_USE_USER_CONNECTIONS = 4,
|
||||
|
||||
NM_CLIENT_PERMISSION_LAST = NM_CLIENT_PERMISSION_USE_USER_CONNECTIONS
|
||||
} NMClientPermission;
|
||||
|
||||
typedef enum {
|
||||
NM_CLIENT_PERMISSION_RESULT_UNKNOWN = 0,
|
||||
NM_CLIENT_PERMISSION_RESULT_YES,
|
||||
NM_CLIENT_PERMISSION_RESULT_AUTH,
|
||||
NM_CLIENT_PERMISSION_RESULT_NO
|
||||
} NMClientPermissionResult;
|
||||
|
||||
|
||||
typedef struct {
|
||||
NMObject parent;
|
||||
} NMClient;
|
||||
|
@ -105,6 +124,9 @@ gboolean nm_client_get_manager_running (NMClient *client);
|
|||
const GPtrArray *nm_client_get_active_connections (NMClient *client);
|
||||
void nm_client_sleep (NMClient *client, gboolean sleep);
|
||||
|
||||
NMClientPermissionResult nm_client_get_permission_result (NMClient *client,
|
||||
NMClientPermission permission);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* NM_CLIENT_H */
|
||||
|
|
|
@ -11,6 +11,8 @@ libnm-util/crypto.c
|
|||
libnm-util/crypto_gnutls.c
|
||||
libnm-util/crypto_nss.c
|
||||
libnm-util/nm-utils.c
|
||||
policy/org.freedesktop.network-manager-settings.system.policy.in
|
||||
policy/org.freedesktop.NetworkManager.policy.in
|
||||
src/nm-netlink-monitor.c
|
||||
src/main.c
|
||||
src/dhcp-manager/nm-dhcp-dhclient.c
|
||||
|
@ -19,5 +21,4 @@ src/logging/nm-logging.c
|
|||
src/named-manager/nm-named-manager.c
|
||||
src/system-settings/nm-default-wired-connection.c
|
||||
system-settings/plugins/ifcfg-rh/reader.c
|
||||
policy/org.freedesktop.network-manager-settings.system.policy.in
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
polkit_policydir = $(datadir)/polkit-1/actions
|
||||
|
||||
dist_polkit_policy_in_files = org.freedesktop.network-manager-settings.system.policy.in
|
||||
dist_polkit_policy_in_files = \
|
||||
org.freedesktop.network-manager-settings.system.policy.in \
|
||||
org.freedesktop.NetworkManager.policy.in
|
||||
|
||||
dist_polkit_policy_DATA = $(dist_polkit_policy_in_files:.policy.in=.policy)
|
||||
|
||||
@INTLTOOL_POLICY_RULE@
|
||||
|
|
49
policy/org.freedesktop.NetworkManager.policy.in
Normal file
49
policy/org.freedesktop.NetworkManager.policy.in
Normal file
|
@ -0,0 +1,49 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE policyconfig PUBLIC
|
||||
"-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
|
||||
|
||||
<policyconfig>
|
||||
|
||||
<vendor>NetworkManager</vendor>
|
||||
<vendor_url>http://www.gnome.org/projects/NetworkManager</vendor_url>
|
||||
<icon_name>nm-icon</icon_name>
|
||||
|
||||
<action id="org.freedesktop.NetworkManager.enable-disable-network">
|
||||
<_description>Enable or disable system networking</_description>
|
||||
<_message>System policy prevents enabling or disabling system networking</_message>
|
||||
<defaults>
|
||||
<allow_inactive>no</allow_inactive>
|
||||
<allow_active>yes</allow_active>
|
||||
</defaults>
|
||||
</action>
|
||||
|
||||
<action id="org.freedesktop.NetworkManager.enable-disable-wifi">
|
||||
<_description>Enable or disable WiFi devices</_description>
|
||||
<_message>System policy prevents enabling or disabling WiFi devices</_message>
|
||||
<defaults>
|
||||
<allow_inactive>no</allow_inactive>
|
||||
<allow_active>yes</allow_active>
|
||||
</defaults>
|
||||
</action>
|
||||
|
||||
<action id="org.freedesktop.NetworkManager.enable-disable-wwan">
|
||||
<_description>Enable or disable mobile broadband devices</_description>
|
||||
<_message>System policy prevents enabling or disabling mobile broadband devices</_message>
|
||||
<defaults>
|
||||
<allow_inactive>no</allow_inactive>
|
||||
<allow_active>yes</allow_active>
|
||||
</defaults>
|
||||
</action>
|
||||
|
||||
<action id="org.freedesktop.NetworkManager.use-user-connections">
|
||||
<_description>Allow use of user-specific connections</_description>
|
||||
<_message>System policy prevents use of user-specific connections</_message>
|
||||
<defaults>
|
||||
<allow_inactive>no</allow_inactive>
|
||||
<allow_active>yes</allow_active>
|
||||
</defaults>
|
||||
</action>
|
||||
|
||||
</policyconfig>
|
||||
|
|
@ -133,6 +133,8 @@ NetworkManager_SOURCES = \
|
|||
nm-system.h \
|
||||
nm-manager.c \
|
||||
nm-manager.h \
|
||||
nm-manager-auth.c \
|
||||
nm-manager-auth.h \
|
||||
nm-netlink-monitor.c \
|
||||
nm-netlink-monitor.h \
|
||||
nm-activation-request.c \
|
||||
|
@ -211,6 +213,7 @@ NetworkManager_CPPFLAGS = \
|
|||
$(GUDEV_CFLAGS) \
|
||||
$(LIBNL_CFLAGS) \
|
||||
$(GMODULE_CFLAGS) \
|
||||
$(POLKIT_CFLAGS) \
|
||||
-DG_DISABLE_DEPRECATED \
|
||||
-DBINDIR=\"$(bindir)\" \
|
||||
-DSBINDIR=\"$(sbindir)\" \
|
||||
|
@ -242,6 +245,7 @@ NetworkManager_LDADD = \
|
|||
$(GUDEV_LIBS) \
|
||||
$(LIBNL_LIBS) \
|
||||
$(GMODULE_LIBS) \
|
||||
$(POLKIT_LIBS) \
|
||||
$(LIBM) \
|
||||
$(LIBDL)
|
||||
|
||||
|
|
212
src/nm-manager-auth.c
Normal file
212
src/nm-manager-auth.c
Normal file
|
@ -0,0 +1,212 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
/* NetworkManager -- Network link manager
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Copyright (C) 2010 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#include "nm-manager-auth.h"
|
||||
#include "nm-logging.h"
|
||||
|
||||
#include <dbus/dbus-glib-lowlevel.h>
|
||||
#include <string.h>
|
||||
|
||||
struct NMAuthChain {
|
||||
guint32 refcount;
|
||||
PolkitAuthority *authority;
|
||||
GSList *calls;
|
||||
|
||||
DBusGMethodInvocation *context;
|
||||
GError *error;
|
||||
|
||||
NMAuthChainResultFunc done_func;
|
||||
NMAuthChainCallFunc call_func;
|
||||
gpointer user_data;
|
||||
gpointer user_data2;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
NMAuthChain *chain;
|
||||
GCancellable *cancellable;
|
||||
char *permission;
|
||||
gboolean disposed;
|
||||
} PolkitCall;
|
||||
|
||||
|
||||
NMAuthChain *
|
||||
nm_auth_chain_new (PolkitAuthority *authority,
|
||||
DBusGMethodInvocation *context,
|
||||
NMAuthChainResultFunc done_func,
|
||||
NMAuthChainCallFunc call_func,
|
||||
gpointer user_data,
|
||||
gpointer user_data2)
|
||||
{
|
||||
NMAuthChain *self;
|
||||
|
||||
self = g_malloc0 (sizeof (NMAuthChain));
|
||||
self->refcount = 1;
|
||||
self->authority = g_object_ref (authority);
|
||||
self->done_func = done_func;
|
||||
self->call_func = call_func;
|
||||
self->context = context;
|
||||
self->user_data = user_data;
|
||||
self->user_data2 = user_data2;
|
||||
return self;
|
||||
}
|
||||
|
||||
static void
|
||||
nm_auth_chain_check_done (NMAuthChain *self)
|
||||
{
|
||||
g_return_if_fail (self != NULL);
|
||||
|
||||
if (g_slist_length (self->calls) == 0) {
|
||||
/* Ensure we say alive across the callback */
|
||||
self->refcount++;
|
||||
self->done_func (self, self->error, self->context, self->user_data, self->user_data2);
|
||||
nm_auth_chain_unref (self);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
polkit_call_cancel (PolkitCall *call)
|
||||
{
|
||||
call->disposed = TRUE;
|
||||
g_cancellable_cancel (call->cancellable);
|
||||
}
|
||||
|
||||
static void
|
||||
polkit_call_free (PolkitCall *call)
|
||||
{
|
||||
g_return_if_fail (call != NULL);
|
||||
|
||||
call->disposed = TRUE;
|
||||
g_free (call->permission);
|
||||
call->permission = NULL;
|
||||
call->chain = NULL;
|
||||
g_object_unref (call->cancellable);
|
||||
call->cancellable = NULL;
|
||||
g_free (call);
|
||||
}
|
||||
|
||||
static void
|
||||
pk_call_cb (GObject *object, GAsyncResult *result, gpointer user_data)
|
||||
{
|
||||
PolkitCall *call = user_data;
|
||||
NMAuthChain *chain;
|
||||
PolkitAuthorizationResult *pk_result;
|
||||
GError *error = NULL;
|
||||
guint call_result = NM_AUTH_CALL_RESULT_UNKNOWN;
|
||||
|
||||
/* If the call is already disposed do nothing */
|
||||
if (call->disposed) {
|
||||
polkit_call_free (call);
|
||||
return;
|
||||
}
|
||||
|
||||
chain = call->chain;
|
||||
chain->calls = g_slist_remove (chain->calls, call);
|
||||
|
||||
pk_result = polkit_authority_check_authorization_finish (chain->authority,
|
||||
result,
|
||||
&error);
|
||||
if (error) {
|
||||
if (!chain->error)
|
||||
chain->error = g_error_copy (error);
|
||||
|
||||
nm_log_warn (LOGD_CORE, "error requesting auth for %s: (%d) %s",
|
||||
call->permission,
|
||||
error ? error->code : -1,
|
||||
error && error->message ? error->message : "(unknown)");
|
||||
} else {
|
||||
if (polkit_authorization_result_get_is_authorized (pk_result)) {
|
||||
/* Caller has the permission */
|
||||
call_result = NM_AUTH_CALL_RESULT_YES;
|
||||
} else if (polkit_authorization_result_get_is_challenge (pk_result)) {
|
||||
/* Caller could authenticate to get the permission */
|
||||
call_result = NM_AUTH_CALL_RESULT_AUTH;
|
||||
} else
|
||||
call_result = NM_AUTH_CALL_RESULT_NO;
|
||||
}
|
||||
|
||||
chain->call_func (chain, call->permission, error, call_result, chain->user_data, chain->user_data2);
|
||||
nm_auth_chain_check_done (chain);
|
||||
|
||||
g_clear_error (&error);
|
||||
polkit_call_free (call);
|
||||
if (pk_result)
|
||||
g_object_unref (pk_result);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_auth_chain_add_call (NMAuthChain *self,
|
||||
const char *permission)
|
||||
{
|
||||
PolkitCall *call;
|
||||
char *sender;
|
||||
PolkitSubject *subject;
|
||||
|
||||
g_return_val_if_fail (self != NULL, FALSE);
|
||||
g_return_val_if_fail (self->context != NULL, FALSE);
|
||||
g_return_val_if_fail (permission != NULL, FALSE);
|
||||
|
||||
sender = dbus_g_method_get_sender (self->context);
|
||||
subject = polkit_system_bus_name_new (sender);
|
||||
g_free (sender);
|
||||
if (!subject)
|
||||
return FALSE;
|
||||
|
||||
call = g_malloc0 (sizeof (PolkitCall));
|
||||
call->chain = self;
|
||||
call->permission = g_strdup (permission);
|
||||
call->cancellable = g_cancellable_new ();
|
||||
|
||||
self->calls = g_slist_append (self->calls, call);
|
||||
|
||||
polkit_authority_check_authorization (self->authority,
|
||||
subject,
|
||||
permission,
|
||||
NULL,
|
||||
POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE,
|
||||
call->cancellable,
|
||||
pk_call_cb,
|
||||
call);
|
||||
g_object_unref (subject);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
nm_auth_chain_unref (NMAuthChain *self)
|
||||
{
|
||||
GSList *iter;
|
||||
|
||||
g_return_if_fail (self != NULL);
|
||||
|
||||
self->refcount--;
|
||||
if (self->refcount > 0)
|
||||
return;
|
||||
|
||||
g_object_unref (self->authority);
|
||||
|
||||
for (iter = self->calls; iter; iter = g_slist_next (iter))
|
||||
polkit_call_cancel ((PolkitCall *) iter->data);
|
||||
g_slist_free (self->calls);
|
||||
|
||||
g_clear_error (&self->error);
|
||||
|
||||
memset (self, 0, sizeof (NMAuthChain));
|
||||
g_free (self);
|
||||
}
|
||||
|
69
src/nm-manager-auth.h
Normal file
69
src/nm-manager-auth.h
Normal file
|
@ -0,0 +1,69 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
/* NetworkManager -- Network link manager
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Copyright (C) 2010 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#ifndef NM_MANAGER_AUTH_H
|
||||
#define NM_MANAGER_AUTH_H
|
||||
|
||||
#include <polkit/polkit.h>
|
||||
#include <glib.h>
|
||||
#include <dbus/dbus-glib.h>
|
||||
|
||||
#define NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK "org.freedesktop.NetworkManager.enable-disable-network"
|
||||
#define NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI "org.freedesktop.NetworkManager.enable-disable-wifi"
|
||||
#define NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN "org.freedesktop.NetworkManager.enable-disable-wwan"
|
||||
#define NM_AUTH_PERMISSION_USE_USER_CONNECTIONS "org.freedesktop.NetworkManager.use-user-connections"
|
||||
|
||||
|
||||
typedef struct NMAuthChain NMAuthChain;
|
||||
|
||||
enum {
|
||||
NM_AUTH_CALL_RESULT_UNKNOWN,
|
||||
NM_AUTH_CALL_RESULT_YES,
|
||||
NM_AUTH_CALL_RESULT_AUTH,
|
||||
NM_AUTH_CALL_RESULT_NO,
|
||||
};
|
||||
|
||||
typedef void (*NMAuthChainResultFunc) (NMAuthChain *chain,
|
||||
GError *error,
|
||||
DBusGMethodInvocation *context,
|
||||
gpointer user_data,
|
||||
gpointer user_data2);
|
||||
|
||||
typedef void (*NMAuthChainCallFunc) (NMAuthChain *chain,
|
||||
const char *permission,
|
||||
GError *error,
|
||||
guint result,
|
||||
gpointer user_data,
|
||||
gpointer user_data2);
|
||||
|
||||
NMAuthChain *nm_auth_chain_new (PolkitAuthority *authority,
|
||||
DBusGMethodInvocation *context,
|
||||
NMAuthChainResultFunc done_func,
|
||||
NMAuthChainCallFunc call_func,
|
||||
gpointer user_data,
|
||||
gpointer user_data2);
|
||||
|
||||
gboolean nm_auth_chain_add_call (NMAuthChain *chain,
|
||||
const char *permission);
|
||||
|
||||
void nm_auth_chain_unref (NMAuthChain *chain);
|
||||
|
||||
#endif /* NM_MANAGER_AUTH_H */
|
||||
|
133
src/nm-manager.c
133
src/nm-manager.c
|
@ -54,6 +54,7 @@
|
|||
#include "nm-secrets-provider-interface.h"
|
||||
#include "nm-settings-interface.h"
|
||||
#include "nm-settings-system-interface.h"
|
||||
#include "nm-manager-auth.h"
|
||||
|
||||
#define NM_AUTOIP_DBUS_SERVICE "org.freedesktop.nm_avahi_autoipd"
|
||||
#define NM_AUTOIP_DBUS_IFACE "org.freedesktop.nm_avahi_autoipd"
|
||||
|
@ -74,6 +75,9 @@ static gboolean impl_manager_sleep (NMManager *manager, gboolean sleep, GError *
|
|||
|
||||
static gboolean impl_manager_enable (NMManager *manager, gboolean enable, GError **err);
|
||||
|
||||
static void impl_manager_get_permissions (NMManager *manager,
|
||||
DBusGMethodInvocation *context);
|
||||
|
||||
static gboolean impl_manager_set_logging (NMManager *manager,
|
||||
const char *level,
|
||||
const char *domains,
|
||||
|
@ -196,6 +200,10 @@ typedef struct {
|
|||
|
||||
DBusGProxy *aipd_proxy;
|
||||
|
||||
PolkitAuthority *authority;
|
||||
guint auth_changed_id;
|
||||
GSList *auth_chains;
|
||||
|
||||
gboolean disposed;
|
||||
} NMManagerPrivate;
|
||||
|
||||
|
@ -215,6 +223,7 @@ enum {
|
|||
CONNECTION_ADDED,
|
||||
CONNECTION_UPDATED,
|
||||
CONNECTION_REMOVED,
|
||||
CHECK_PERMISSIONS,
|
||||
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
@ -2792,6 +2801,109 @@ impl_manager_enable (NMManager *self, gboolean enable, GError **error)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/* Permissions */
|
||||
|
||||
static void
|
||||
pk_authority_changed_cb (GObject *object, gpointer user_data)
|
||||
{
|
||||
/* Let clients know they should re-check their authorization */
|
||||
g_signal_emit (NM_MANAGER (user_data), signals[CHECK_PERMISSIONS], 0);
|
||||
}
|
||||
|
||||
static void
|
||||
get_permissions_done_cb (NMAuthChain *chain,
|
||||
GError *error,
|
||||
DBusGMethodInvocation *context,
|
||||
gpointer user_data,
|
||||
gpointer user_data2)
|
||||
{
|
||||
NMManager *self = NM_MANAGER (user_data);
|
||||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
|
||||
GHashTable *hash = user_data2;
|
||||
GError *ret_error;
|
||||
|
||||
priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
|
||||
if (error) {
|
||||
nm_log_dbg (LOGD_CORE, "Permissions request failed: %s", error->message);
|
||||
ret_error = g_error_new (NM_MANAGER_ERROR,
|
||||
NM_MANAGER_ERROR_PERMISSION_DENIED,
|
||||
"Permissions request failed: %s",
|
||||
error->message);
|
||||
dbus_g_method_return_error (context, ret_error);
|
||||
g_error_free (ret_error);
|
||||
} else {
|
||||
g_assert (user_data2);
|
||||
dbus_g_method_return (context, hash);
|
||||
}
|
||||
|
||||
g_hash_table_destroy (hash);
|
||||
nm_auth_chain_unref (chain);
|
||||
}
|
||||
|
||||
static void
|
||||
get_permissions_call_done_cb (NMAuthChain *chain,
|
||||
const char *permission,
|
||||
GError *error,
|
||||
guint result,
|
||||
gpointer user_data,
|
||||
gpointer user_data2)
|
||||
{
|
||||
GHashTable *hash = user_data2;
|
||||
const char *str_result = NULL;
|
||||
|
||||
if (!error) {
|
||||
g_assert (result != NM_AUTH_CALL_RESULT_UNKNOWN);
|
||||
|
||||
if (result == NM_AUTH_CALL_RESULT_YES)
|
||||
str_result = "yes";
|
||||
else if (result == NM_AUTH_CALL_RESULT_NO)
|
||||
str_result = "no";
|
||||
else if (result == NM_AUTH_CALL_RESULT_AUTH)
|
||||
str_result = "auth";
|
||||
else {
|
||||
nm_log_dbg (LOGD_CORE, "unknown auth chain result %d", result);
|
||||
}
|
||||
|
||||
if (str_result)
|
||||
g_hash_table_insert (hash, g_strdup (permission), g_strdup (str_result));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
impl_manager_get_permissions (NMManager *self,
|
||||
DBusGMethodInvocation *context)
|
||||
{
|
||||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
|
||||
NMAuthChain *chain;
|
||||
GHashTable *results;
|
||||
|
||||
if (!priv->authority) {
|
||||
GError *error;
|
||||
|
||||
error = g_error_new_literal (NM_MANAGER_ERROR,
|
||||
NM_MANAGER_ERROR_PERMISSION_DENIED,
|
||||
"Permissions request failed: PolicyKit not initialized");
|
||||
dbus_g_method_return_error (context, error);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
results = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||
chain = nm_auth_chain_new (priv->authority,
|
||||
context,
|
||||
get_permissions_done_cb,
|
||||
get_permissions_call_done_cb,
|
||||
self,
|
||||
results);
|
||||
g_assert (chain);
|
||||
priv->auth_chains = g_slist_append (priv->auth_chains, chain);
|
||||
|
||||
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK);
|
||||
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI);
|
||||
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN);
|
||||
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_USE_USER_CONNECTIONS);
|
||||
}
|
||||
|
||||
/* Legacy 0.6 compatibility interface */
|
||||
|
||||
static gboolean
|
||||
|
@ -3078,6 +3190,10 @@ dispose (GObject *object)
|
|||
pending_connection_info_destroy (priv->pending_connection_info);
|
||||
priv->pending_connection_info = NULL;
|
||||
|
||||
g_slist_foreach (priv->auth_chains, (GFunc) nm_auth_chain_unref, NULL);
|
||||
g_slist_free (priv->auth_chains);
|
||||
g_object_unref (priv->authority);
|
||||
|
||||
while (g_slist_length (priv->secrets_calls))
|
||||
free_get_secrets_info ((GetSecretsInfo *) priv->secrets_calls->data);
|
||||
|
||||
|
@ -3286,6 +3402,15 @@ nm_manager_init (NMManager *manager)
|
|||
NULL);
|
||||
} else
|
||||
nm_log_warn (LOGD_AUTOIP4, "could not initialize avahi-autoipd D-Bus proxy");
|
||||
|
||||
priv->authority = polkit_authority_get ();
|
||||
if (priv->authority) {
|
||||
priv->auth_changed_id = g_signal_connect (priv->authority,
|
||||
"changed",
|
||||
G_CALLBACK (pk_authority_changed_cb),
|
||||
manager);
|
||||
} else
|
||||
nm_log_warn (LOGD_CORE, "failed to create PolicyKit authority.");
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -3445,6 +3570,14 @@ nm_manager_class_init (NMManagerClass *manager_class)
|
|||
_nm_marshal_VOID__OBJECT_UINT,
|
||||
G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_UINT);
|
||||
|
||||
signals[CHECK_PERMISSIONS] =
|
||||
g_signal_new ("check-permissions",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
0, NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
/* StateChange is DEPRECATED */
|
||||
signals[STATE_CHANGE] =
|
||||
g_signal_new ("state-change",
|
||||
|
|
Loading…
Reference in a new issue