core: merge branch 'th/authchain-cleanup'

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/132
This commit is contained in:
Thomas Haller 2019-05-13 09:26:31 +02:00
commit a7bda40129
30 changed files with 1439 additions and 1324 deletions

View file

@ -335,6 +335,8 @@ shared_nm_glib_aux_libnm_glib_aux_la_CPPFLAGS = \
shared_nm_glib_aux_libnm_glib_aux_la_SOURCES = \
shared/nm-glib-aux/nm-c-list.h \
shared/nm-glib-aux/nm-dbus-aux.c \
shared/nm-glib-aux/nm-dbus-aux.h \
shared/nm-glib-aux/nm-dedup-multi.c \
shared/nm-glib-aux/nm-dedup-multi.h \
shared/nm-glib-aux/nm-enum-utils.c \

View file

@ -27,6 +27,7 @@
#include <stdlib.h>
#include "nm-glib-aux/nm-secret-utils.h"
#include "nm-glib-aux/nm-dbus-aux.h"
#include "nm-enum-types.h"
#include "nm-utils.h"
#include "nm-connection.h"
@ -499,16 +500,11 @@ watch_peer (NMVpnServicePlugin *plugin,
GDBusConnection *connection = g_dbus_method_invocation_get_connection (context);
const char *peer = g_dbus_message_get_sender (g_dbus_method_invocation_get_message (context));
return g_dbus_connection_signal_subscribe (connection,
"org.freedesktop.DBus",
"org.freedesktop.DBus",
"NameOwnerChanged",
"/org/freedesktop/DBus",
peer,
G_DBUS_SIGNAL_FLAGS_NONE,
peer_vanished,
plugin,
NULL);
return nm_dbus_connection_signal_subscribe_name_owner_changed (connection,
peer,
peer_vanished,
plugin,
NULL);
}
static void
@ -1190,11 +1186,8 @@ state_changed (NMVpnServicePlugin *plugin, NMVpnServiceState state)
nm_vpn_service_plugin_emit_quit (plugin);
else
schedule_quit_timer (plugin);
if (priv->peer_watch_id) {
g_dbus_connection_signal_unsubscribe (nm_vpn_service_plugin_get_connection (plugin),
priv->peer_watch_id);
priv->peer_watch_id = 0;
}
nm_clear_g_dbus_connection_signal (nm_vpn_service_plugin_get_connection (plugin),
&priv->peer_watch_id);
break;
default:
/* Clean up all timers we might have set up. */

View file

@ -139,7 +139,8 @@ shared_nm_glib_aux_c_args = [
shared_nm_glib_aux = static_library(
'nm-utils-base',
sources: files('nm-glib-aux/nm-dedup-multi.c',
sources: files('nm-glib-aux/nm-dbus-aux.c',
'nm-glib-aux/nm-dedup-multi.c',
'nm-glib-aux/nm-enum-utils.c',
'nm-glib-aux/nm-errno.c',
'nm-glib-aux/nm-hash-utils.c',

View file

@ -0,0 +1,69 @@
/* NetworkManager -- Network link manager
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* (C) Copyright 2019 Red Hat, Inc.
*/
#include "nm-default.h"
#include "nm-dbus-aux.h"
/*****************************************************************************/
static void
_nm_dbus_connection_call_get_name_owner_cb (GObject *source,
GAsyncResult *res,
gpointer user_data)
{
gs_unref_variant GVariant *ret = NULL;
gs_free_error GError *error = NULL;
const char *owner = NULL;
gpointer orig_user_data;
NMDBusConnectionCallGetNameOwnerCb callback;
nm_utils_user_data_unpack (user_data, &orig_user_data, &callback);
ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), res, &error);
if (ret)
g_variant_get (ret, "(&s)", &owner);
callback (owner, error, orig_user_data);
}
void
nm_dbus_connection_call_get_name_owner (GDBusConnection *dbus_connection,
const char *service_name,
int timeout_msec,
GCancellable *cancellable,
NMDBusConnectionCallGetNameOwnerCb callback,
gpointer user_data)
{
nm_assert (callback);
g_dbus_connection_call (dbus_connection,
DBUS_SERVICE_DBUS,
DBUS_PATH_DBUS,
DBUS_INTERFACE_DBUS,
"GetNameOwner",
g_variant_new ("(s)", service_name),
G_VARIANT_TYPE ("(s)"),
G_DBUS_CALL_FLAGS_NONE,
timeout_msec,
cancellable,
_nm_dbus_connection_call_get_name_owner_cb,
nm_utils_user_data_pack (user_data, callback));
}

View file

@ -0,0 +1,102 @@
/* NetworkManager -- Network link manager
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* (C) Copyright 2019 Red Hat, Inc.
*/
#ifndef __NM_DBUS_AUX_H__
#define __NM_DBUS_AUX_H__
#include "nm-std-aux/nm-dbus-compat.h"
/*****************************************************************************/
static inline gboolean
nm_clear_g_dbus_connection_signal (GDBusConnection *dbus_connection,
guint *id)
{
guint v;
if ( id
&& (v = *id)) {
*id = 0;
g_dbus_connection_signal_unsubscribe (dbus_connection, v);
return TRUE;
}
return FALSE;
}
/*****************************************************************************/
static inline void
nm_dbus_connection_call_start_service_by_name (GDBusConnection *dbus_connection,
const char *name,
int timeout_msec,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_dbus_connection_call (dbus_connection,
DBUS_SERVICE_DBUS,
DBUS_PATH_DBUS,
DBUS_INTERFACE_DBUS,
"StartServiceByName",
g_variant_new ("(su)", name, 0u),
G_VARIANT_TYPE ("(u)"),
G_DBUS_CALL_FLAGS_NONE,
timeout_msec,
cancellable,
callback,
user_data);
}
/*****************************************************************************/
static inline guint
nm_dbus_connection_signal_subscribe_name_owner_changed (GDBusConnection *dbus_connection,
const char *service_name,
GDBusSignalCallback callback,
gpointer user_data,
GDestroyNotify user_data_free_func)
{
return g_dbus_connection_signal_subscribe (dbus_connection,
DBUS_SERVICE_DBUS,
DBUS_INTERFACE_DBUS,
"NameOwnerChanged",
DBUS_PATH_DBUS,
service_name,
G_DBUS_SIGNAL_FLAGS_NONE,
callback,
user_data,
user_data_free_func);
}
typedef void (*NMDBusConnectionCallGetNameOwnerCb) (const char *name_owner,
GError *error,
gpointer user_data);
void nm_dbus_connection_call_get_name_owner (GDBusConnection *dbus_connection,
const char *service_name,
int timeout_msec,
GCancellable *cancellable,
NMDBusConnectionCallGetNameOwnerCb callback,
gpointer user_data);
/*****************************************************************************/
#endif /* __NM_DBUS_AUX_H__ */

View file

@ -45,7 +45,10 @@ _get_hash_key_init (void)
* to use it as guint* or guint64* pointer. */
static union {
guint8 v8[HASH_KEY_SIZE];
} g_arr _nm_alignas (guint64);
guint _align_as_uint;
guint32 _align_as_uint32;
guint64 _align_as_uint64;
} g_arr;
const guint8 *g;
union {
guint8 v8[HASH_KEY_SIZE];
@ -125,14 +128,17 @@ void
nm_hash_siphash42_init (CSipHash *h, guint static_seed)
{
const guint8 *g;
guint seed[HASH_KEY_SIZE_GUINT];
union {
guint64 _align_as_uint64;
guint arr[HASH_KEY_SIZE_GUINT];
} seed;
nm_assert (h);
g = _get_hash_key ();
memcpy (seed, g, HASH_KEY_SIZE);
seed[0] ^= static_seed;
c_siphash_init (h, (const guint8 *) seed);
memcpy (&seed, g, HASH_KEY_SIZE);
seed.arr[0] ^= static_seed;
c_siphash_init (h, (const guint8 *) &seed);
}
guint

View file

@ -34,7 +34,7 @@ void nm_hash_siphash42_init (CSipHash *h, guint static_seed);
*
* Note, that this is guaranteed to use siphash42 under the hood (contrary to
* all other NMHash API, which leave this undefined). That matters at the point,
* where the caller needs to be sure that a reasonably strong hasing algorithm
* where the caller needs to be sure that a reasonably strong hashing algorithm
* is used. (Yes, NMHash is all about siphash24, but otherwise that is not promised
* anywhere).
*
@ -291,7 +291,7 @@ gboolean nm_pstr_equal (gconstpointer a, gconstpointer b);
/*****************************************************************************/
#define NM_HASH_OBFUSCATE_PTR_FMT "%016llx"
#define NM_HASH_OBFUSCATE_PTR_FMT "%016" G_GINT64_MODIFIER "x"
/* sometimes we want to log a pointer directly, for providing context/information about
* the message that get logged. Logging pointer values directly defeats ASLR, so we should
@ -307,9 +307,19 @@ gboolean nm_pstr_equal (gconstpointer a, gconstpointer b);
\
nm_hash_init (&_h, (static_seed)); \
nm_hash_update_val (&_h, _val_obf_ptr); \
(unsigned long long) nm_hash_complete_u64 (&_h); \
nm_hash_complete_u64 (&_h); \
})
/* if you want to log obfuscated pointer for a certain context (like, NMPRuleManager
* logging user-tags), then you are advised to use nm_hash_obfuscate_ptr() with your
* own, unique static-seed.
*
* However, for example the singleton constructors log the obfuscated pointer values
* for all singletons, so they must all be obfuscated with the same seed. So, this
* macro uses a particular static seed that should be used by when comparing pointer
* values in a global context. */
#define NM_HASH_OBFUSCATE_PTR(ptr) (nm_hash_obfuscate_ptr (1678382159u, ptr))
/*****************************************************************************/
#endif /* __NM_HASH_UTILS_H__ */

View file

@ -78,7 +78,7 @@ NMPlatformRoutingRule *nm_ip_routing_rule_to_platform (const NMIPRoutingRule *ru
* SIGKILL.
*
* After NM_SHUTDOWN_TIMEOUT_MS, NetworkManager will however not yet terminate right
* away. It iterates the mainloop for another NM_SHUTDOWN_TIMEOUT_MS_EXTRA. This
* away. It iterates the mainloop for another NM_SHUTDOWN_TIMEOUT_MS_WATCHDOG. This
* should give time to reap the child process (after SIGKILL).
*
* So, the maximum time we should wait before sending SIGKILL should be at most

View file

@ -397,8 +397,7 @@ typedef struct _NMDevicePrivate {
/* Proxy Configuration */
NMProxyConfig *proxy_config;
NMPacrunnerManager *pacrunner_manager;
NMPacrunnerCallId *pacrunner_call_id;
NMPacrunnerConfId *pacrunner_conf_id;
/* IP configuration info. Combined config from VPN, settings, and device */
union {
@ -11128,21 +11127,17 @@ nm_device_reactivate_ip6_config (NMDevice *self,
}
static void
_pacrunner_manager_send (NMDevice *self)
_pacrunner_manager_add (NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
nm_pacrunner_manager_remove_clear (priv->pacrunner_manager,
&priv->pacrunner_call_id);
nm_pacrunner_manager_remove_clear (&priv->pacrunner_conf_id);
if (!priv->pacrunner_manager)
priv->pacrunner_manager = g_object_ref (nm_pacrunner_manager_get ());
priv->pacrunner_call_id = nm_pacrunner_manager_send (priv->pacrunner_manager,
nm_device_get_ip_iface (self),
priv->proxy_config,
NULL,
NULL);
priv->pacrunner_conf_id = nm_pacrunner_manager_add (nm_pacrunner_manager_get (),
priv->proxy_config,
nm_device_get_ip_iface (self),
NULL,
NULL);
}
static void
@ -11150,10 +11145,10 @@ reactivate_proxy_config (NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
if (!priv->pacrunner_call_id)
if (!priv->pacrunner_conf_id)
return;
nm_device_set_proxy_config (self, priv->dhcp4.pac_url);
_pacrunner_manager_send (self);
_pacrunner_manager_add (self);
}
static gboolean
@ -15081,8 +15076,7 @@ _set_state_full (NMDevice *self,
}
}
nm_pacrunner_manager_remove_clear (priv->pacrunner_manager,
&priv->pacrunner_call_id);
nm_pacrunner_manager_remove_clear (&priv->pacrunner_conf_id);
break;
case NM_DEVICE_STATE_DISCONNECTED:
if ( priv->queued_act_request
@ -15102,7 +15096,7 @@ _set_state_full (NMDevice *self,
NULL, NULL, NULL);
if (priv->proxy_config)
_pacrunner_manager_send (self);
_pacrunner_manager_add (self);
break;
case NM_DEVICE_STATE_FAILED:
/* Usually upon failure the activation chain is interrupted in
@ -16345,9 +16339,7 @@ dispose (GObject *object)
dispatcher_cleanup (self);
nm_pacrunner_manager_remove_clear (priv->pacrunner_manager,
&priv->pacrunner_call_id);
g_clear_object (&priv->pacrunner_manager);
nm_pacrunner_manager_remove_clear (&priv->pacrunner_conf_id);
_cleanup_generic_pre (self, CLEANUP_TYPE_KEEP);

View file

@ -32,6 +32,7 @@
#include <linux/if.h>
#include "nm-glib-aux/nm-c-list.h"
#include "nm-glib-aux/nm-dbus-aux.h"
#include "nm-core-internal.h"
#include "platform/nm-platform.h"
#include "nm-utils.h"
@ -304,18 +305,12 @@ send_updates (NMDnsSystemdResolved *self)
_LOGT ("send-updates: no name owner. Try start service...");
priv->try_start_blocked = TRUE;
g_dbus_connection_call (priv->dbus_connection,
DBUS_SERVICE_DBUS,
DBUS_PATH_DBUS,
DBUS_INTERFACE_DBUS,
"StartServiceByName",
g_variant_new ("(su)", SYSTEMD_RESOLVED_DBUS_SERVICE, 0u),
G_VARIANT_TYPE ("(u)"),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
NULL,
NULL);
nm_dbus_connection_call_start_service_by_name (priv->dbus_connection,
SYSTEMD_RESOLVED_DBUS_SERVICE,
-1,
NULL,
NULL,
NULL);
return;
}
@ -474,24 +469,17 @@ name_owner_changed_cb (GDBusConnection *connection,
}
static void
get_name_owner_cb (GObject *source,
GAsyncResult *res,
get_name_owner_cb (const char *name_owner,
GError *error,
gpointer user_data)
{
NMDnsSystemdResolved *self;
NMDnsSystemdResolvedPrivate *priv;
gs_unref_variant GVariant *ret = NULL;
gs_free_error GError *error = NULL;
const char *owner = NULL;
ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), res, &error);
if ( !ret
if ( !name_owner
&& g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
if (ret)
g_variant_get (ret, "(&s)", &owner);
self = user_data;
priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE (self);
@ -499,7 +487,7 @@ get_name_owner_cb (GObject *source,
priv->dbus_initied = TRUE;
name_owner_changed (self, owner);
name_owner_changed (self, name_owner);
}
/*****************************************************************************/
@ -527,35 +515,24 @@ nm_dns_systemd_resolved_init (NMDnsSystemdResolved *self)
c_list_init (&priv->request_queue_lst_head);
priv->dbus_connection = nm_g_object_ref (nm_dbus_manager_get_dbus_connection (nm_dbus_manager_get ()));
priv->dbus_connection = nm_g_object_ref (NM_MAIN_DBUS_CONNECTION_GET);
if (!priv->dbus_connection) {
_LOGD ("no D-Bus connection");
return;
}
priv->name_owner_changed_id = g_dbus_connection_signal_subscribe (priv->dbus_connection,
DBUS_SERVICE_DBUS,
DBUS_INTERFACE_DBUS,
"NameOwnerChanged",
DBUS_PATH_DBUS,
SYSTEMD_RESOLVED_DBUS_SERVICE,
G_DBUS_SIGNAL_FLAGS_NONE,
name_owner_changed_cb,
self,
NULL);
priv->name_owner_changed_id = nm_dbus_connection_signal_subscribe_name_owner_changed (priv->dbus_connection,
SYSTEMD_RESOLVED_DBUS_SERVICE,
name_owner_changed_cb,
self,
NULL);
priv->cancellable = g_cancellable_new ();
g_dbus_connection_call (priv->dbus_connection,
DBUS_SERVICE_DBUS,
DBUS_PATH_DBUS,
DBUS_INTERFACE_DBUS,
"GetNameOwner",
g_variant_new ("(s)", SYSTEMD_RESOLVED_DBUS_SERVICE),
G_VARIANT_TYPE ("(s)"),
G_DBUS_CALL_FLAGS_NONE,
-1,
priv->cancellable,
get_name_owner_cb,
self);
nm_dbus_connection_call_get_name_owner (priv->dbus_connection,
SYSTEMD_RESOLVED_DBUS_SERVICE,
-1,
priv->cancellable,
get_name_owner_cb,
self);
}
NMDnsPlugin *
@ -572,10 +549,8 @@ dispose (GObject *object)
free_pending_updates (self);
if (priv->name_owner_changed_id != 0) {
g_dbus_connection_signal_unsubscribe (priv->dbus_connection,
nm_steal_int (&priv->name_owner_changed_id));
}
nm_clear_g_dbus_connection_signal (priv->dbus_connection,
&priv->name_owner_changed_id);
nm_clear_g_cancellable (&priv->cancellable);

View file

@ -213,6 +213,35 @@ do_early_setup (int *argc, char **argv[], NMConfigCmdLineOptions *config_cli)
global_opt.pidfile = global_opt.pidfile ?: g_strdup(NM_DEFAULT_PID_FILE);
}
static gboolean
_dbus_manager_init (NMConfig *config)
{
NMDBusManager *busmgr;
NMConfigConfigureAndQuitType c_a_q_type;
busmgr = nm_dbus_manager_get ();
c_a_q_type = nm_config_get_configure_and_quit (config);
if (c_a_q_type == NM_CONFIG_CONFIGURE_AND_QUIT_DISABLED)
return nm_dbus_manager_acquire_bus (busmgr, TRUE);
if (c_a_q_type == NM_CONFIG_CONFIGURE_AND_QUIT_ENABLED) {
/* D-Bus is useless in configure and quit mode -- we're eventually dropping
* off and potential clients would have no way of knowing whether we're
* finished already or didn't start yet.
*
* But we still create a nm_dbus_manager_get_dbus_connection() D-Bus connection
* so that we can talk to other services like firewalld. */
return nm_dbus_manager_acquire_bus (busmgr, FALSE);
}
nm_assert (c_a_q_type == NM_CONFIG_CONFIGURE_AND_QUIT_INITRD);
/* in initrd we don't have D-Bus at all. Don't even try to get the G_BUS_TYPE_SYSTEM
* connection. And of course don't claim the D-Bus name. */
return TRUE;
}
/*
* main
*
@ -389,7 +418,9 @@ main (int argc, char *argv[])
#endif
);
/* Set up platform interaction layer */
if (!_dbus_manager_init (config))
goto done_no_manager;
nm_linux_platform_setup ();
NM_UTILS_KEEP_ALIVE (config, nm_netns_get (), "NMConfig-depends-on-NMNetns");
@ -399,15 +430,8 @@ main (int argc, char *argv[])
NM_CONFIG_KEYFILE_KEY_MAIN_AUTH_POLKIT,
NM_CONFIG_DEFAULT_MAIN_AUTH_POLKIT_BOOL));
if (!nm_config_get_configure_and_quit (config)) {
/* D-Bus is useless in configure and quit mode -- we're eventually dropping
* off and potential clients would have no way of knowing whether we're
* finished already or didn't start yet. */
if (!nm_dbus_manager_acquire_bus (nm_dbus_manager_get ()))
goto done_no_manager;
}
manager = nm_manager_setup ();
nm_dbus_manager_start (nm_dbus_manager_get(),
nm_manager_dbus_set_property_handle,
manager);

View file

@ -23,8 +23,10 @@
#include "nm-auth-manager.h"
#include "c-list/src/c-list.h"
#include "nm-glib-aux/nm-dbus-aux.h"
#include "nm-errors.h"
#include "nm-core-internal.h"
#include "nm-dbus-manager.h"
#include "NetworkManagerUtils.h"
#define POLKIT_SERVICE "org.freedesktop.PolicyKit1"
@ -49,13 +51,13 @@ static guint signals[LAST_SIGNAL] = {0};
typedef struct {
CList calls_lst_head;
GDBusProxy *proxy;
GCancellable *new_proxy_cancellable;
GCancellable *cancel_cancellable;
GDBusConnection *dbus_connection;
GCancellable *shutdown_cancellable;
guint64 call_numid_counter;
bool polkit_enabled:1;
guint changed_signal_id;
bool disposing:1;
bool shutting_down:1;
bool polkit_enabled_construct_only:1;
} NMAuthManagerPrivate;
struct _NMAuthManager {
@ -113,7 +115,7 @@ nm_auth_manager_get_polkit_enabled (NMAuthManager *self)
{
g_return_val_if_fail (NM_IS_AUTH_MANAGER (self), FALSE);
return NM_AUTH_MANAGER_GET_PRIVATE (self)->polkit_enabled;
return NM_AUTH_MANAGER_GET_PRIVATE (self)->dbus_connection != NULL;
}
/*****************************************************************************/
@ -131,7 +133,6 @@ typedef enum {
struct _NMAuthManagerCallId {
CList calls_lst;
NMAuthManager *self;
GVariant *dbus_parameters;
GCancellable *dbus_cancellable;
NMAuthManagerCheckAuthorizationCallback callback;
gpointer user_data;
@ -141,7 +142,7 @@ struct _NMAuthManagerCallId {
};
#define cancellation_id_to_str_a(call_numid) \
nm_sprintf_bufa (NM_STRLEN (CANCELLATION_ID_PREFIX) + 20, \
nm_sprintf_bufa (NM_STRLEN (CANCELLATION_ID_PREFIX) + 60, \
CANCELLATION_ID_PREFIX"%"G_GUINT64_FORMAT, \
(call_numid))
@ -150,8 +151,6 @@ _call_id_free (NMAuthManagerCallId *call_id)
{
c_list_unlink (&call_id->calls_lst);
nm_clear_g_source (&call_id->idle_id);
if (call_id->dbus_parameters)
g_variant_unref (g_steal_pointer (&call_id->dbus_parameters));
if (call_id->dbus_cancellable) {
/* we have a pending D-Bus call. We keep the call-id instance alive
@ -182,7 +181,7 @@ _call_id_invoke_callback (NMAuthManagerCallId *call_id,
}
static void
cancel_check_authorization_cb (GObject *proxy,
cancel_check_authorization_cb (GObject *source,
GAsyncResult *res,
gpointer user_data)
{
@ -190,7 +189,7 @@ cancel_check_authorization_cb (GObject *proxy,
gs_unref_variant GVariant *value = NULL;
gs_free_error GError *error= NULL;
value = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, &error);
value = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), res, &error);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
_LOG2T (call_id, "cancel request was cancelled");
else if (error)
@ -224,18 +223,18 @@ _call_check_authorize_cb (GObject *proxy,
self = call_id->self;
priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
value = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, G_VARIANT_TYPE ("((bba{ss}))"), &error);
value = g_dbus_connection_call_finish (G_DBUS_CONNECTION (proxy), res, &error);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
/* call_id was cancelled externally, but _call_id_free() kept call_id
* alive (and it has still the reference on @self. */
if (!priv->cancel_cancellable) {
if (!priv->shutdown_cancellable) {
/* we do a forced shutdown. There is no more time for cancelling... */
_call_id_free (call_id);
/* this shouldn't really happen, because:
* _call_check_authorize() only scheduled the D-Bus request at a time when
* cancel_cancellable was still set. It means, somebody called force-shutdown
* shutdown_cancellable was still set. It means, somebody called force-shutdown
* after call-id was schedule.
* force-shutdown should only be called after:
* - cancel all pending requests
@ -244,15 +243,19 @@ _call_check_authorize_cb (GObject *proxy,
g_return_if_reached ();
}
g_dbus_proxy_call (priv->proxy,
"CancelCheckAuthorization",
g_variant_new ("(s)",
cancellation_id_to_str_a (call_id->call_numid)),
G_DBUS_CALL_FLAGS_NONE,
CANCELLATION_TIMEOUT_MS,
priv->cancel_cancellable,
cancel_check_authorization_cb,
call_id);
g_dbus_connection_call (priv->dbus_connection,
POLKIT_SERVICE,
POLKIT_OBJECT_PATH,
POLKIT_INTERFACE,
"CancelCheckAuthorization",
g_variant_new ("(s)",
cancellation_id_to_str_a (call_id->call_numid)),
G_VARIANT_TYPE ("()"),
G_DBUS_CALL_FLAGS_NONE,
CANCELLATION_TIMEOUT_MS,
priv->shutdown_cancellable,
cancel_check_authorization_cb,
call_id);
return;
}
@ -270,30 +273,6 @@ _call_check_authorize_cb (GObject *proxy,
_call_id_invoke_callback (call_id, is_authorized, is_challenge, error);
}
static void
_call_check_authorize (NMAuthManagerCallId *call_id)
{
NMAuthManager *self = call_id->self;
NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
nm_assert (call_id->dbus_parameters);
nm_assert (g_variant_is_floating (call_id->dbus_parameters));
nm_assert (!call_id->dbus_cancellable);
call_id->dbus_cancellable = g_cancellable_new ();
nm_assert (priv->cancel_cancellable);
g_dbus_proxy_call (priv->proxy,
"CheckAuthorization",
g_steal_pointer (&call_id->dbus_parameters),
G_DBUS_CALL_FLAGS_NONE,
G_MAXINT, /* no timeout */
call_id->dbus_cancellable,
_call_check_authorize_cb,
call_id);
}
static gboolean
_call_on_idle (gpointer user_data)
{
@ -344,9 +323,6 @@ nm_auth_manager_check_authorization (NMAuthManager *self,
NMAuthManagerPrivate *priv;
PolkitCheckAuthorizationFlags flags;
char subject_buf[64];
GVariantBuilder builder;
GVariant *subject_value;
GVariant *details_value;
NMAuthManagerCallId *call_id;
g_return_val_if_fail (NM_IS_AUTH_MANAGER (self), NULL);
@ -365,14 +341,16 @@ nm_auth_manager_check_authorization (NMAuthManager *self,
? POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION
: POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE;
call_id = g_slice_new0 (NMAuthManagerCallId);
call_id->self = g_object_ref (self);
call_id->callback = callback;
call_id->user_data = user_data;
call_id->call_numid = ++priv->call_numid_counter;
call_id = g_slice_new (NMAuthManagerCallId);
*call_id = (NMAuthManagerCallId) {
.self = g_object_ref (self),
.callback = callback,
.user_data = user_data,
.call_numid = ++priv->call_numid_counter,
};
c_list_link_tail (&priv->calls_lst_head, &call_id->calls_lst);
if (!priv->polkit_enabled) {
if (!priv->dbus_connection) {
_LOG2T (call_id, "CheckAuthorization(%s), subject=%s (succeeding due to polkit authorization disabled)", action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf)));
call_id->idle_reason = IDLE_REASON_AUTHORIZED;
call_id->idle_id = g_idle_add (_call_on_idle, call_id);
@ -384,12 +362,12 @@ nm_auth_manager_check_authorization (NMAuthManager *self,
_LOG2T (call_id, "CheckAuthorization(%s), subject=%s (succeeding for root)", action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf)));
call_id->idle_reason = IDLE_REASON_AUTHORIZED;
call_id->idle_id = g_idle_add (_call_on_idle, call_id);
} else if ( !priv->proxy
&& !priv->new_proxy_cancellable) {
_LOG2T (call_id, "CheckAuthorization(%s), subject=%s (failing due to invalid DBUS proxy)", action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf)));
call_id->idle_reason = IDLE_REASON_NO_DBUS;
call_id->idle_id = g_idle_add (_call_on_idle, call_id);
} else {
GVariant *parameters;
GVariantBuilder builder;
GVariant *subject_value;
GVariant *details_value;
subject_value = nm_auth_subject_unix_process_to_polkit_gvariant (subject);
nm_assert (g_variant_is_floating (subject_value));
@ -397,18 +375,31 @@ nm_auth_manager_check_authorization (NMAuthManager *self,
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}"));
details_value = g_variant_builder_end (&builder);
call_id->dbus_parameters = g_variant_new ("(@(sa{sv})s@a{ss}us)",
subject_value,
action_id,
details_value,
(guint32) flags,
cancellation_id_to_str_a (call_id->call_numid));
if (!priv->proxy) {
_LOG2T (call_id, "CheckAuthorization(%s), subject=%s (wait for proxy)", action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf)));
} else {
_LOG2T (call_id, "CheckAuthorization(%s), subject=%s", action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf)));
_call_check_authorize (call_id);
}
parameters = g_variant_new ("(@(sa{sv})s@a{ss}us)",
subject_value,
action_id,
details_value,
(guint32) flags,
cancellation_id_to_str_a (call_id->call_numid));
_LOG2T (call_id, "CheckAuthorization(%s), subject=%s", action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf)));
call_id->dbus_cancellable = g_cancellable_new ();
nm_assert (priv->shutdown_cancellable);
g_dbus_connection_call (priv->dbus_connection,
POLKIT_SERVICE,
POLKIT_OBJECT_PATH,
POLKIT_INTERFACE,
"CheckAuthorization",
parameters,
G_VARIANT_TYPE ("((bba{ss}))"),
G_DBUS_CALL_FLAGS_NONE,
G_MAXINT, /* no timeout */
call_id->dbus_cancellable,
_call_check_authorize_cb,
call_id);
}
return call_id;
@ -440,113 +431,18 @@ nm_auth_manager_check_authorization_cancel (NMAuthManagerCallId *call_id)
/*****************************************************************************/
static void
_emit_changed_signal (NMAuthManager *self)
{
_LOGD ("emit changed signal");
g_signal_emit (self, signals[CHANGED_SIGNAL], 0);
}
static void
_log_name_owner (NMAuthManager *self, char **out_name_owner)
{
NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
gs_free char *name_owner = NULL;
name_owner = g_dbus_proxy_get_name_owner (priv->proxy);
if (name_owner)
_LOGD ("dbus name owner: '%s'", name_owner);
else
_LOGD ("dbus name owner: none");
NM_SET_OUT (out_name_owner, g_steal_pointer (&name_owner));
}
static void
_dbus_on_name_owner_notify_cb (GObject *object,
GParamSpec *pspec,
gpointer user_data)
changed_signal_cb (GDBusConnection *connection,
const char *sender_name,
const char *object_path,
const char *interface_name,
const char *signal_name,
GVariant *parameters,
gpointer user_data)
{
NMAuthManager *self = user_data;
gs_free char *name_owner = NULL;
nm_assert (NM_AUTH_MANAGER_GET_PRIVATE (self)->proxy == (GDBusProxy *) object);
_log_name_owner (self, &name_owner);
if (!name_owner) {
/* when the name disappears, we also want to raise a emit signal.
* When it appears, we raise one already. */
_emit_changed_signal (self);
}
}
static void
_dbus_on_changed_signal_cb (GDBusProxy *proxy,
gpointer user_data)
{
NMAuthManager *self = user_data;
nm_assert (NM_AUTH_MANAGER_GET_PRIVATE (self)->proxy == proxy);
_LOGD ("dbus signal: \"Changed\"");
_emit_changed_signal (self);
}
static void
_dbus_new_proxy_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
NMAuthManager *self;
NMAuthManagerPrivate *priv;
gs_free_error GError *error = NULL;
GDBusProxy *proxy;
NMAuthManagerCallId *call_id;
proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
self = user_data;
priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
priv->proxy = proxy;
g_clear_object (&priv->new_proxy_cancellable);
if (!priv->proxy) {
_LOGE ("could not create polkit proxy: %s", error->message);
again:
c_list_for_each_entry (call_id, &priv->calls_lst_head, calls_lst) {
if (call_id->dbus_parameters) {
_LOG2T (call_id, "completed: failed due to no D-Bus proxy after startup");
_call_id_invoke_callback (call_id, FALSE, FALSE, error);
goto again;
}
}
return;
}
priv->cancel_cancellable = g_cancellable_new ();
g_signal_connect (priv->proxy,
"notify::g-name-owner",
G_CALLBACK (_dbus_on_name_owner_notify_cb),
self);
_nm_dbus_signal_connect (priv->proxy, "Changed", NULL,
G_CALLBACK (_dbus_on_changed_signal_cb),
self);
_log_name_owner (self, NULL);
c_list_for_each_entry (call_id, &priv->calls_lst_head, calls_lst) {
if (call_id->dbus_parameters) {
_LOG2T (call_id, "CheckAuthorization invoke now");
_call_check_authorize (call_id);
}
}
_emit_changed_signal (self);
g_signal_emit (self, signals[CHANGED_SIGNAL], 0);
}
/*****************************************************************************/
@ -590,7 +486,7 @@ nm_auth_manager_force_shutdown (NMAuthManager *self)
*/
priv->shutting_down = TRUE;
nm_clear_g_cancellable (&priv->cancel_cancellable);
nm_clear_g_cancellable (&priv->shutdown_cancellable);
}
/*****************************************************************************/
@ -603,7 +499,7 @@ set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *p
switch (prop_id) {
case PROP_POLKIT_ENABLED:
/* construct-only */
priv->polkit_enabled = !!g_value_get_boolean (value);
priv->polkit_enabled_construct_only = !!g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -626,23 +522,42 @@ constructed (GObject *object)
{
NMAuthManager *self = NM_AUTH_MANAGER (object);
NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
NMLogLevel logl = LOGL_DEBUG;
const char *create_message;
G_OBJECT_CLASS (nm_auth_manager_parent_class)->constructed (object);
_LOGD ("create auth-manager: polkit %s", priv->polkit_enabled ? "enabled" : "disabled");
if (priv->polkit_enabled) {
priv->new_proxy_cancellable = g_cancellable_new ();
g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
NULL,
POLKIT_SERVICE,
POLKIT_OBJECT_PATH,
POLKIT_INTERFACE,
priv->new_proxy_cancellable,
_dbus_new_proxy_cb,
self);
if (!priv->polkit_enabled_construct_only) {
create_message = "polkit disabled";
goto out;
}
priv->dbus_connection = nm_g_object_ref (NM_MAIN_DBUS_CONNECTION_GET);
if (!priv->dbus_connection) {
/* This warrants an info level message. */
logl = LOGL_INFO;
create_message = "D-Bus connection not available. Polkit is disabled and all requests are authenticated.";
goto out;
}
priv->shutdown_cancellable = g_cancellable_new ();
priv->changed_signal_id = g_dbus_connection_signal_subscribe (priv->dbus_connection,
POLKIT_SERVICE,
POLKIT_INTERFACE,
"Changed",
POLKIT_OBJECT_PATH,
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
changed_signal_cb,
self,
NULL);
create_message = "polkit enabled";
out:
_NMLOG (logl, "create auth-manager: %s", create_message);
}
NMAuthManager *
@ -660,7 +575,8 @@ nm_auth_manager_setup (gboolean polkit_enabled)
singleton_instance = self;
nm_singleton_instance_register ();
nm_log_dbg (LOGD_CORE, "setup %s singleton (%p)", "NMAuthManager", singleton_instance);
nm_log_dbg (LOGD_CORE, "setup %s singleton ("NM_HASH_OBFUSCATE_PTR_FMT")",
"NMAuthManager", NM_HASH_OBFUSCATE_PTR (singleton_instance));
return self;
}
@ -677,15 +593,14 @@ dispose (GObject *object)
priv->disposing = TRUE;
nm_clear_g_cancellable (&priv->new_proxy_cancellable);
nm_clear_g_cancellable (&priv->cancel_cancellable);
nm_clear_g_cancellable (&priv->shutdown_cancellable);
if (priv->proxy) {
g_signal_handlers_disconnect_by_data (priv->proxy, self);
g_clear_object (&priv->proxy);
}
nm_clear_g_dbus_connection_signal (priv->dbus_connection,
&priv->changed_signal_id);
G_OBJECT_CLASS (nm_auth_manager_parent_class)->dispose (object);
g_clear_object (&priv->dbus_connection);
}
static void

View file

@ -31,7 +31,7 @@
/*****************************************************************************/
struct NMAuthChain {
GHashTable *data_hash;
CList data_lst_head;
CList auth_call_lst_head;
@ -41,26 +41,47 @@ struct NMAuthChain {
NMAuthChainResultFunc done_func;
gpointer user_data;
guint32 refcount;
guint num_pending_auth_calls;
bool done:1;
bool is_destroyed:1;
bool is_finishing:1;
};
typedef struct {
CList auth_call_lst;
NMAuthChain *chain;
NMAuthManagerCallId *call_id;
char *permission;
const char *permission;
NMAuthCallResult result;
} AuthCall;
/*****************************************************************************/
static void _auth_chain_destroy (NMAuthChain *self);
/*****************************************************************************/
static void
_ASSERT_call (AuthCall *call)
{
nm_assert (call);
nm_assert (call->chain);
nm_assert (call->permission && strlen (call->permission) > 0);
nm_assert (nm_c_list_contains_entry (&call->chain->auth_call_lst_head, call, auth_call_lst));
#if NM_MORE_ASSERTS > 5
{
AuthCall *auth_call;
guint n = 0;
c_list_for_each_entry (auth_call, &call->chain->auth_call_lst_head, auth_call_lst) {
nm_assert ( auth_call->result == NM_AUTH_CALL_RESULT_UNKNOWN
|| !auth_call->call_id);
if (auth_call->call_id)
n++;
}
nm_assert (n == call->chain->num_pending_auth_calls);
}
#endif
}
/*****************************************************************************/
@ -68,67 +89,68 @@ _ASSERT_call (AuthCall *call)
static void
auth_call_free (AuthCall *call)
{
if (call->call_id)
nm_auth_manager_check_authorization_cancel (call->call_id);
_ASSERT_call (call);
c_list_unlink_stale (&call->auth_call_lst);
g_free (call->permission);
if (call->call_id) {
call->chain->num_pending_auth_calls--;
nm_auth_manager_check_authorization_cancel (call->call_id);
}
g_slice_free (AuthCall, call);
}
static AuthCall *
_find_auth_call (NMAuthChain *self, const char *permission)
{
AuthCall *auth_call;
c_list_for_each_entry (auth_call, &self->auth_call_lst_head, auth_call_lst) {
if (nm_streq (auth_call->permission, permission))
return auth_call;
}
return NULL;
}
/*****************************************************************************/
typedef struct {
/* must be the first field. */
CList data_lst;
const char *tag;
gpointer data;
GDestroyNotify destroy;
char tag_data[];
} ChainData;
static ChainData *
chain_data_new (const char *tag, gpointer data, GDestroyNotify destroy)
{
ChainData *tmp;
gsize l = strlen (tag);
tmp = g_malloc (sizeof (ChainData) + l + 1);
tmp->tag = &tmp->tag_data[0];
tmp->data = data;
tmp->destroy = destroy;
memcpy (&tmp->tag_data[0], tag, l + 1);
return tmp;
}
static void
chain_data_free (gpointer data)
chain_data_free (ChainData *chain_data)
{
ChainData *tmp = data;
if (tmp->destroy)
tmp->destroy (tmp->data);
g_free (tmp);
c_list_unlink_stale (&chain_data->data_lst);
if (chain_data->destroy)
chain_data->destroy (chain_data->data);
g_slice_free (ChainData, chain_data);
}
static gpointer
static ChainData *
_get_data (NMAuthChain *self, const char *tag)
{
ChainData *tmp;
ChainData *chain_data;
if (!self->data_hash)
return NULL;
tmp = g_hash_table_lookup (self->data_hash, &tag);
return tmp ? tmp->data : NULL;
c_list_for_each_entry (chain_data, &self->data_lst_head, data_lst) {
if (nm_streq (chain_data->tag, tag))
return chain_data;
}
return NULL;
}
gpointer
nm_auth_chain_get_data (NMAuthChain *self, const char *tag)
{
ChainData *chain_data;
g_return_val_if_fail (self, NULL);
g_return_val_if_fail (tag, NULL);
return _get_data (self, tag);
chain_data = _get_data (self, tag);
return chain_data ? chain_data->data : NULL;
}
/**
@ -145,47 +167,77 @@ nm_auth_chain_get_data (NMAuthChain *self, const char *tag)
gpointer
nm_auth_chain_steal_data (NMAuthChain *self, const char *tag)
{
ChainData *tmp;
gpointer value = NULL;
ChainData *chain_data;
gpointer value;
g_return_val_if_fail (self, NULL);
g_return_val_if_fail (tag, NULL);
if (!self->data_hash)
chain_data = _get_data (self, tag);
if (!chain_data)
return NULL;
tmp = g_hash_table_lookup (self->data_hash, &tag);
if (!tmp)
return NULL;
value = tmp->data;
value = chain_data->data;
/* Make sure the destroy handler isn't called when freeing */
tmp->destroy = NULL;
g_hash_table_remove (self->data_hash, tmp);
chain_data->destroy = NULL;
chain_data_free (chain_data);
return value;
}
/**
* nm_auth_chain_set_data_unsafe:
* @self: the #NMAuthChain
* @tag: the tag for referencing the attached data.
* @data: the data to attach. If %NULL, this call has no effect
* and nothing is attached.
* @data_destroy: (allow-none): the destroy function for the data pointer.
*
* @tag string is not cloned and must outlife @self. That is why
* the function is "unsafe". Use nm_auth_chain_set_data() with a C literal
* instead.
*
* It is a bug to add the same tag more than once.
*/
void
nm_auth_chain_set_data (NMAuthChain *self,
const char *tag,
gpointer data,
GDestroyNotify data_destroy)
nm_auth_chain_set_data_unsafe (NMAuthChain *self,
const char *tag,
gpointer data,
GDestroyNotify data_destroy)
{
ChainData *chain_data;
g_return_if_fail (self);
g_return_if_fail (tag);
if (data == NULL) {
if (self->data_hash)
g_hash_table_remove (self->data_hash, &tag);
} else {
if (!self->data_hash) {
self->data_hash = g_hash_table_new_full (nm_pstr_hash, nm_pstr_equal,
NULL, chain_data_free);
}
g_hash_table_add (self->data_hash,
chain_data_new (tag, data, data_destroy));
/* we should not track a large number of elements via a linked list. If this becomes
* necessary, revert the code to use GHashTable again. */
nm_assert (c_list_length (&self->data_lst_head) < 25);
/* The tag must not yet exist. Otherwise we'd have to first search the linked
* list for an existing entry. */
nm_assert (!_get_data (self, tag));
if (!data) {
/* we don't track user data of %NULL.
*
* In the past this had also the meaning of removing a user-data. But since
* nm_auth_chain_set_data() does not allow being called more than once
* for the same tag, we don't need to remove anything. */
return;
}
chain_data = g_slice_new (ChainData);
*chain_data = (ChainData) {
.tag = tag,
.data = data,
.destroy = data_destroy,
};
/* we assert that no duplicate tags are added. But still, add the new
* element to the front, so that it would shadow the duplicate element
* in the list. */
c_list_link_front (&self->data_lst_head, &chain_data->data_lst);
}
/*****************************************************************************/
@ -193,13 +245,26 @@ nm_auth_chain_set_data (NMAuthChain *self,
NMAuthCallResult
nm_auth_chain_get_result (NMAuthChain *self, const char *permission)
{
gpointer data;
AuthCall *auth_call;
g_return_val_if_fail (self, NM_AUTH_CALL_RESULT_UNKNOWN);
g_return_val_if_fail (permission, NM_AUTH_CALL_RESULT_UNKNOWN);
data = _get_data (self, permission);
return data ? GPOINTER_TO_UINT (data) : NM_AUTH_CALL_RESULT_UNKNOWN;
/* it is a bug to request the result other than from the done_func()
* callback. You are not supposed to poll for the result but request
* it upon notification. */
nm_assert (self->is_finishing);
auth_call = _find_auth_call (self, permission);
/* it is a bug to request a permission result that was not
* previously requested or which did not complete yet. */
if (!auth_call)
g_return_val_if_reached (NM_AUTH_CALL_RESULT_UNKNOWN);
nm_assert (!auth_call->call_id);
return auth_call->result;
}
NMAuthSubject *
@ -212,39 +277,6 @@ nm_auth_chain_get_subject (NMAuthChain *self)
/*****************************************************************************/
static gboolean
auth_chain_finish (NMAuthChain *self)
{
self->done = TRUE;
/* Ensure we stay alive across the callback */
nm_assert (self->refcount == 1);
self->refcount++;
self->done_func (self, NULL, self->context, self->user_data);
nm_assert (NM_IN_SET (self->refcount, 1, 2));
nm_auth_chain_destroy (self);
return FALSE;
}
static void
auth_call_complete (AuthCall *call)
{
NMAuthChain *self;
_ASSERT_call (call);
self = call->chain;
nm_assert (!self->done);
auth_call_free (call);
if (c_list_is_empty (&self->auth_call_lst_head)) {
/* we are on an idle-handler or a clean call-stack (non-reentrant). */
auth_chain_finish (self);
}
}
static void
pk_call_cb (NMAuthManager *auth_manager,
NMAuthManagerCallId *call_id,
@ -253,49 +285,110 @@ pk_call_cb (NMAuthManager *auth_manager,
GError *error,
gpointer user_data)
{
NMAuthChain *self;
AuthCall *call;
NMAuthCallResult call_result;
nm_assert (call_id);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
call = user_data;
_ASSERT_call (call);
nm_assert (call->call_id == call_id);
nm_assert (call->result == NM_AUTH_CALL_RESULT_UNKNOWN);
self = call->chain;
nm_assert (!self->is_destroyed);
nm_assert (!self->is_finishing);
call->call_id = NULL;
call_result = nm_auth_call_result_eval (is_authorized, is_challenge, error);
call->result = nm_auth_call_result_eval (is_authorized, is_challenge, error);
nm_auth_chain_set_data (call->chain, call->permission, GUINT_TO_POINTER (call_result), NULL);
call->chain->num_pending_auth_calls--;
auth_call_complete (call);
_ASSERT_call (call);
if (call->chain->num_pending_auth_calls == 0) {
/* we are on an idle-handler or a clean call-stack (non-reentrant) so it's safe
* to invoke the callback right away. */
self->is_finishing = TRUE;
self->done_func (self, self->context, self->user_data);
nm_assert (self->is_finishing);
_auth_chain_destroy (self);
}
}
/**
* nm_auth_chain_add_call_unsafe:
* @self: the #NMAuthChain
* @permission: the permission string. This string is kept by reference
* and you must make sure that it's lifetime lasts until the NMAuthChain
* gets destroyed. That's why the function is "unsafe". Use
* nm_auth_chain_add_call() instead.
* @allow_interaction: flag
*
* It's "unsafe" because @permission is not copied. It's the callers responsibility
* that the permission string stays valid as long as NMAuthChain.
*
* If you can, use nm_auth_chain_add_call() instead!
*
* If you have a non-static string, you may attach the permission string as
* user-data via nm_auth_chain_set_data().
*/
void
nm_auth_chain_add_call (NMAuthChain *self,
const char *permission,
gboolean allow_interaction)
nm_auth_chain_add_call_unsafe (NMAuthChain *self,
const char *permission,
gboolean allow_interaction)
{
AuthCall *call;
NMAuthManager *auth_manager = nm_auth_manager_get ();
g_return_if_fail (self);
g_return_if_fail (self->subject);
g_return_if_fail (!self->done);
g_return_if_fail (!self->is_finishing);
g_return_if_fail (!self->is_destroyed);
g_return_if_fail (permission && *permission);
g_return_if_fail (nm_auth_subject_is_unix_process (self->subject) || nm_auth_subject_is_internal (self->subject));
nm_assert ( nm_auth_subject_is_unix_process (self->subject)
|| nm_auth_subject_is_internal (self->subject));
call = g_slice_new0 (AuthCall);
call->chain = self;
call->permission = g_strdup (permission);
c_list_link_tail (&self->auth_call_lst_head, &call->auth_call_lst);
call->call_id = nm_auth_manager_check_authorization (auth_manager,
/* duplicate permissions are not supported, also because nm_auth_chain_get_result()
* can only return one-permission. */
nm_assert (!_find_auth_call (self, permission));
call = g_slice_new (AuthCall);
*call = (AuthCall) {
.chain = self,
.call_id = NULL,
.result = NM_AUTH_CALL_RESULT_UNKNOWN,
/* we don't clone the permission string. It's the callers responsiblity. */
.permission = permission,
};
/* above we assert that no duplicate permissions are added. Still, track the
* new request to the front of the list so that it would shadow an earlier
* call. */
c_list_link_front (&self->auth_call_lst_head, &call->auth_call_lst);
call->call_id = nm_auth_manager_check_authorization (nm_auth_manager_get (),
self->subject,
permission,
allow_interaction,
pk_call_cb,
call);
self->num_pending_auth_calls++;
_ASSERT_call (call);
/* we track auth-calls in a linked list. If we end up requesting too many permissions this
* becomes inefficient. If that ever happens, consider a more efficient data structure for
* a large number of requests. */
nm_assert (self->num_pending_auth_calls < 25);
}
/*****************************************************************************/
@ -310,6 +403,7 @@ nm_auth_chain_new_context (GDBusMethodInvocation *context,
NMAuthChain *chain;
g_return_val_if_fail (context, NULL);
nm_assert (done_func);
subject = nm_auth_subject_new_unix_process_from_context (context);
if (!subject)
@ -323,7 +417,6 @@ nm_auth_chain_new_context (GDBusMethodInvocation *context,
return chain;
}
/* Requires an NMAuthSubject */
NMAuthChain *
nm_auth_chain_new_subject (NMAuthSubject *subject,
GDBusMethodInvocation *context,
@ -333,15 +426,19 @@ nm_auth_chain_new_subject (NMAuthSubject *subject,
NMAuthChain *self;
g_return_val_if_fail (NM_IS_AUTH_SUBJECT (subject), NULL);
nm_assert (nm_auth_subject_is_unix_process (subject) || nm_auth_subject_is_internal (subject));
nm_assert ( nm_auth_subject_is_unix_process (subject)
|| nm_auth_subject_is_internal (subject));
nm_assert (done_func);
self = g_slice_new0 (NMAuthChain);
c_list_init (&self->auth_call_lst_head);
self->refcount = 1;
self->done_func = done_func;
self->user_data = user_data;
self->context = context ? g_object_ref (context) : NULL;
self->subject = g_object_ref (subject);
self = g_slice_new (NMAuthChain);
*self = (NMAuthChain) {
.done_func = done_func,
.user_data = user_data,
.context = nm_g_object_ref (context),
.subject = g_object_ref (subject),
.data_lst_head = C_LIST_INIT (self->data_lst_head),
.auth_call_lst_head = C_LIST_INIT (self->auth_call_lst_head),
};
return self;
}
@ -352,30 +449,49 @@ nm_auth_chain_new_subject (NMAuthSubject *subject,
* Destroys the auth-chain. By destroying the auth-chain, you also cancel
* the receipt of the done-callback. IOW, the callback will not be invoked.
*
* The only exception is, if may call nm_auth_chain_destroy() from inside
* the callback. In this case, @self stays alive until the callback returns.
* The only exception is, you may call nm_auth_chain_destroy() from inside
* the callback. In this case the call has no effect and @self stays alive
* until the callback returns.
*
* Note that you might only destroy an auth-chain exactly once, and never
* after the callback was handled.
* after the callback was handled. After the callback returns, the auth chain
* always gets automatically destroyed. So you only need to explicitly destroy
* it, if you want to abort it before the callback complets.
*/
void
nm_auth_chain_destroy (NMAuthChain *self)
{
AuthCall *call;
g_return_if_fail (self);
g_return_if_fail (NM_IN_SET (self->refcount, 1, 2));
g_return_if_fail (!self->is_destroyed);
if (--self->refcount > 0)
self->is_destroyed = TRUE;
if (self->is_finishing) {
/* we are called from inside the callback. Keep the instance alive for the moment. */
return;
}
_auth_chain_destroy (self);
}
static void
_auth_chain_destroy (NMAuthChain *self)
{
AuthCall *call;
ChainData *chain_data;
nm_clear_g_object (&self->subject);
nm_clear_g_object (&self->context);
/* we must first destry all AuthCall instances before ChainData. The reason is
* that AuthData.permission is not cloned and the lifetime of the string must
* be ensured by the caller. A sensible thing to do for the caller is attach the
* permission string via nm_auth_chain_set_data(). Hence, first free the AuthCall. */
while ((call = c_list_first_entry (&self->auth_call_lst_head, AuthCall, auth_call_lst)))
auth_call_free (call);
nm_clear_pointer (&self->data_hash, g_hash_table_destroy);
while ((chain_data = c_list_first_entry (&self->data_lst_head, ChainData, data_lst)))
chain_data_free (chain_data);
g_slice_free (NMAuthChain, self);
}
@ -395,7 +511,8 @@ nm_auth_is_subject_in_acl (NMConnection *connection,
g_return_val_if_fail (connection, FALSE);
g_return_val_if_fail (NM_IS_AUTH_SUBJECT (subject), FALSE);
g_return_val_if_fail (nm_auth_subject_is_internal (subject) || nm_auth_subject_is_unix_process (subject), FALSE);
nm_assert ( nm_auth_subject_is_internal (subject)
|| nm_auth_subject_is_unix_process (subject));
if (nm_auth_subject_is_internal (subject))
return TRUE;

View file

@ -28,7 +28,6 @@
typedef struct NMAuthChain NMAuthChain;
typedef void (*NMAuthChainResultFunc) (NMAuthChain *chain,
GError *error,
GDBusMethodInvocation *context,
gpointer user_data);
@ -45,17 +44,23 @@ gpointer nm_auth_chain_get_data (NMAuthChain *chain, const char *tag);
gpointer nm_auth_chain_steal_data (NMAuthChain *chain, const char *tag);
void nm_auth_chain_set_data (NMAuthChain *chain,
const char *tag,
gpointer data,
GDestroyNotify data_destroy);
void nm_auth_chain_set_data_unsafe (NMAuthChain *chain,
const char *tag,
gpointer data,
GDestroyNotify data_destroy);
#define nm_auth_chain_set_data(chain, tag, data, data_destroy) \
nm_auth_chain_set_data_unsafe ((chain), ""tag"", (data), (data_destroy))
NMAuthCallResult nm_auth_chain_get_result (NMAuthChain *chain,
const char *permission);
void nm_auth_chain_add_call (NMAuthChain *chain,
const char *permission,
gboolean allow_interaction);
void nm_auth_chain_add_call_unsafe (NMAuthChain *chain,
const char *permission,
gboolean allow_interaction);
#define nm_auth_chain_add_call(chain, permission, allow_interaction) \
nm_auth_chain_add_call_unsafe ((chain), ""permission"", (allow_interaction))
void nm_auth_chain_destroy (NMAuthChain *chain);

View file

@ -2709,7 +2709,8 @@ nm_config_setup (const NMConfigCmdLineOptions *cli, char **atomic_section_prefix
/* usually, you would not see this logging line because when creating the
* NMConfig instance, the logging is not yet set up to print debug message. */
nm_log_dbg (LOGD_CORE, "setup %s singleton (%p)", "NMConfig", singleton_instance);
nm_log_dbg (LOGD_CORE, "setup %s singleton ("NM_HASH_OBFUSCATE_PTR_FMT")",
"NMConfig", NM_HASH_OBFUSCATE_PTR (singleton_instance));
}
return singleton_instance;
}

View file

@ -863,7 +863,7 @@ nm_connectivity_check_start (NMConnectivity *self,
if (has_systemd_resolved) {
GDBusConnection *dbus_connection;
dbus_connection = nm_dbus_manager_get_dbus_connection (nm_dbus_manager_get ());
dbus_connection = NM_MAIN_DBUS_CONNECTION_GET;
if (!dbus_connection) {
/* we have no D-Bus connection? That might happen in configure and quit mode.
*
@ -876,7 +876,7 @@ nm_connectivity_check_start (NMConnectivity *self,
cb_data->concheck.resolve_cancellable = g_cancellable_new ();
g_dbus_connection_call (nm_dbus_manager_get_dbus_connection (nm_dbus_manager_get ()),
g_dbus_connection_call (dbus_connection,
"org.freedesktop.resolve1",
"/org/freedesktop/resolve1",
"org.freedesktop.resolve1.Manager",

View file

@ -142,8 +142,10 @@ _nm_singleton_instance_destroy (void)
g_object_weak_unref (instance, _nm_singleton_instance_weak_cb, NULL);
if (instance->ref_count > 1)
nm_log_dbg (LOGD_CORE, "disown %s singleton (%p)", G_OBJECT_TYPE_NAME (instance), instance);
if (instance->ref_count > 1) {
nm_log_dbg (LOGD_CORE, "disown %s singleton ("NM_HASH_OBFUSCATE_PTR_FMT")",
G_OBJECT_TYPE_NAME (instance), NM_HASH_OBFUSCATE_PTR (instance));
}
g_object_unref (instance);
}

View file

@ -42,7 +42,9 @@ static void \
_singleton_instance_weak_ref_cb (gpointer data, \
GObject *where_the_object_was) \
{ \
nm_log_dbg (LOGD_CORE, "disposing %s singleton (%p)", G_STRINGIFY (TYPE), singleton_instance); \
nm_log_dbg (LOGD_CORE, "disposing %s singleton ("NM_HASH_OBFUSCATE_PTR_FMT")", \
G_STRINGIFY (TYPE), \
NM_HASH_OBFUSCATE_PTR (singleton_instance)); \
singleton_instance = NULL; \
} \
static inline void \
@ -73,7 +75,9 @@ GETTER (void) \
singleton_instance = (g_object_new (GTYPE, ##__VA_ARGS__, NULL)); \
g_assert (singleton_instance); \
nm_singleton_instance_register (); \
nm_log_dbg (LOGD_CORE, "create %s singleton (%p)", G_STRINGIFY (TYPE), singleton_instance); \
nm_log_dbg (LOGD_CORE, "create %s singleton ("NM_HASH_OBFUSCATE_PTR_FMT")", \
G_STRINGIFY (TYPE), \
NM_HASH_OBFUSCATE_PTR (singleton_instance)); \
} \
return singleton_instance; \
} \

View file

@ -471,6 +471,9 @@ _bus_get_unix_pid (NMDBusManager *self,
guint32 unix_pid = G_MAXUINT32;
gs_unref_variant GVariant *ret = NULL;
if (!priv->main_dbus_connection)
return FALSE;
ret = g_dbus_connection_call_sync (priv->main_dbus_connection,
DBUS_SERVICE_DBUS,
DBUS_PATH_DBUS,
@ -500,6 +503,9 @@ _bus_get_unix_user (NMDBusManager *self,
guint32 unix_uid = G_MAXUINT32;
gs_unref_variant GVariant *ret = NULL;
if (!priv->main_dbus_connection)
return FALSE;
ret = g_dbus_connection_call_sync (priv->main_dbus_connection,
DBUS_SERVICE_DBUS,
DBUS_PATH_DBUS,
@ -1024,6 +1030,7 @@ _obj_register (NMDBusManager *self,
nm_assert (c_list_is_empty (&obj->internal.registration_lst_head));
nm_assert (priv->main_dbus_connection);
nm_assert (priv->objmgr_registration_id != 0);
nm_assert (priv->started);
n_klasses = 0;
@ -1119,15 +1126,10 @@ _obj_unregister (NMDBusManager *self,
GVariantBuilder builder;
nm_assert (NM_IS_DBUS_OBJECT (obj));
if (!priv->main_dbus_connection) {
/* nothing to do for the moment. */
nm_assert (c_list_is_empty (&obj->internal.registration_lst_head));
return;
}
nm_assert (priv->main_dbus_connection);
nm_assert (priv->objmgr_registration_id != 0);
nm_assert (priv->started);
nm_assert (!c_list_is_empty (&obj->internal.registration_lst_head));
nm_assert (priv->objmgr_registration_id);
g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
@ -1202,7 +1204,7 @@ _nm_dbus_manager_obj_export (NMDBusObject *obj)
nm_assert_not_reached ();
c_list_link_tail (&priv->objects_lst_head, &obj->internal.objects_lst);
if (priv->main_dbus_connection && priv->started)
if (priv->started)
_obj_register (self, obj);
}
@ -1223,7 +1225,10 @@ _nm_dbus_manager_obj_unexport (NMDBusObject *obj)
nm_assert (&obj->internal == g_hash_table_lookup (priv->objects_by_path, &obj->internal));
nm_assert (c_list_contains (&priv->objects_lst_head, &obj->internal.objects_lst));
_obj_unregister (self, obj);
if (priv->started)
_obj_unregister (self, obj);
else
nm_assert (c_list_is_empty (&obj->internal.registration_lst_head));
if (!g_hash_table_remove (priv->objects_by_path, &obj->internal))
nm_assert_not_reached ();
@ -1249,6 +1254,16 @@ _nm_dbus_manager_obj_notify (NMDBusObject *obj,
nm_assert (NM_IS_DBUS_MANAGER (obj->internal.bus_manager));
nm_assert (!c_list_is_empty (&obj->internal.objects_lst));
self = obj->internal.bus_manager;
priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
nm_assert (!priv->started || priv->objmgr_registration_id != 0);
nm_assert (priv->objmgr_registration_id == 0 || priv->main_dbus_connection);
nm_assert (c_list_is_empty (&obj->internal.registration_lst_head) != priv->started);
if (G_UNLIKELY (!priv->started))
return;
c_list_for_each_entry (reg_data, &obj->internal.registration_lst_head, registration_lst) {
if (_reg_data_get_interface_info (reg_data)->legacy_property_changed) {
any_legacy_signals = TRUE;
@ -1256,9 +1271,6 @@ _nm_dbus_manager_obj_notify (NMDBusObject *obj,
}
}
self = obj->internal.bus_manager;
priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
/* do a naive search for the matching NMDBusPropertyInfoExtended infos. Since the number of
* (interfaces x properties) is static and possibly small, this naive search is effectively
* O(1). We might wanna introduce some index to lookup the properties in question faster.
@ -1401,7 +1413,7 @@ _nm_dbus_manager_obj_emit_signal (NMDBusObject *obj,
self = obj->internal.bus_manager;
priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
if (!priv->main_dbus_connection || !priv->started) {
if (!priv->started) {
nm_g_variant_unref_floating (args);
return;
}
@ -1565,9 +1577,12 @@ nm_dbus_manager_start (NMDBusManager *self,
NMDBusObject *obj;
g_return_if_fail (NM_IS_DBUS_MANAGER (self));
priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
if (!priv->main_dbus_connection) {
nm_assert (!priv->started);
if (priv->objmgr_registration_id == 0) {
/* Do nothing. We're presumably in the configure-and-quit mode. */
return;
}
@ -1581,12 +1596,12 @@ nm_dbus_manager_start (NMDBusManager *self,
}
gboolean
nm_dbus_manager_acquire_bus (NMDBusManager *self)
nm_dbus_manager_acquire_bus (NMDBusManager *self,
gboolean request_name)
{
NMDBusManagerPrivate *priv;
gs_free_error GError *error = NULL;
gs_unref_variant GVariant *ret = NULL;
gs_unref_object GDBusConnection *connection = NULL;
guint32 result;
guint registration_id;
@ -1599,17 +1614,22 @@ nm_dbus_manager_acquire_bus (NMDBusManager *self)
* acquire the name despite connecting to the bus successfully.
* It means that something is gravely broken -- such as another NetworkManager
* instance running. */
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM,
NULL,
&error);
if (!connection) {
_LOGI ("cannot connect to D-Bus: %s", error->message);
priv->main_dbus_connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM,
NULL,
&error);
if (!priv->main_dbus_connection) {
_LOGE ("cannot connect to D-Bus: %s", error->message);
return FALSE;
}
g_dbus_connection_set_exit_on_close (connection, FALSE);
g_dbus_connection_set_exit_on_close (priv->main_dbus_connection, FALSE);
registration_id = g_dbus_connection_register_object (connection,
if (!request_name) {
_LOGD ("D-Bus connection created");
return TRUE;
}
registration_id = g_dbus_connection_register_object (priv->main_dbus_connection,
OBJECT_MANAGER_SERVER_BASE_PATH,
NM_UNCONST_PTR (GDBusInterfaceInfo, &interface_info_objmgr),
&dbus_vtable_objmgr,
@ -1621,7 +1641,7 @@ nm_dbus_manager_acquire_bus (NMDBusManager *self)
return FALSE;
}
ret = g_dbus_connection_call_sync (connection,
ret = g_dbus_connection_call_sync (priv->main_dbus_connection,
DBUS_SERVICE_DBUS,
DBUS_PATH_DBUS,
DBUS_INTERFACE_DBUS,
@ -1634,13 +1654,10 @@ nm_dbus_manager_acquire_bus (NMDBusManager *self)
-1,
NULL,
&error);
if (!ret)
return FALSE;
if (!ret) {
_LOGE ("fatal failure to acquire D-Bus service \"%s"": %s",
NM_DBUS_SERVICE, error->message);
g_dbus_connection_unregister_object(connection, registration_id);
g_dbus_connection_unregister_object (priv->main_dbus_connection, registration_id);
return FALSE;
}
@ -1648,12 +1665,11 @@ nm_dbus_manager_acquire_bus (NMDBusManager *self)
if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
_LOGE ("fatal failure to acquire D-Bus service \"%s\" (%u). Service already taken",
NM_DBUS_SERVICE, (guint) result);
g_dbus_connection_unregister_object(connection, registration_id);
g_dbus_connection_unregister_object (priv->main_dbus_connection, registration_id);
return FALSE;
}
priv->objmgr_registration_id = registration_id;
priv->main_dbus_connection = g_steal_pointer (&connection);
_LOGI ("acquired D-Bus service \"%s\"", NM_DBUS_SERVICE);
@ -1690,6 +1706,7 @@ nm_dbus_manager_init (NMDBusManager *self)
c_list_init (&priv->private_servers_lst_head);
c_list_init (&priv->objects_lst_head);
priv->objects_by_path = g_hash_table_new ((GHashFunc) _objects_by_path_hash, (GEqualFunc) _objects_by_path_equal);
c_list_init (&priv->caller_info_lst_head);

View file

@ -49,10 +49,13 @@ typedef void (*NMDBusManagerSetPropertyHandler) (NMDBusObject *obj,
GVariant *value,
gpointer user_data);
gboolean nm_dbus_manager_acquire_bus (NMDBusManager *self);
gboolean nm_dbus_manager_acquire_bus (NMDBusManager *self,
gboolean request_name);
GDBusConnection *nm_dbus_manager_get_dbus_connection (NMDBusManager *self);
#define NM_MAIN_DBUS_CONNECTION_GET (nm_dbus_manager_get_dbus_connection (nm_dbus_manager_get ()))
void nm_dbus_manager_start (NMDBusManager *self,
NMDBusManagerSetPropertyHandler set_property_handler,
gpointer set_property_handler_data);

View file

@ -24,6 +24,7 @@
#include "nm-keep-alive.h"
#include "settings/nm-settings-connection.h"
#include "nm-glib-aux/nm-dbus-aux.h"
/*****************************************************************************/
@ -211,32 +212,24 @@ nm_keep_alive_set_settings_connection_watch_visible (NMKeepAlive *self,
/*****************************************************************************/
static void
get_name_owner_cb (GObject *source_object,
GAsyncResult *res,
get_name_owner_cb (const char *name_owner,
GError *error,
gpointer user_data)
{
NMKeepAlive *self = user_data;
NMKeepAlive *self;
NMKeepAlivePrivate *priv;
gs_free_error GError *error = NULL;
gs_unref_variant GVariant *result = NULL;
const char *name_owner;
result = g_dbus_connection_call_finish ((GDBusConnection *) source_object,
res,
&error);
if ( !result
if ( !name_owner
&& g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
if (result) {
g_variant_get (result, "(&s)", &name_owner);
self = user_data;
priv = NM_KEEP_ALIVE_GET_PRIVATE (self);
priv = NM_KEEP_ALIVE_GET_PRIVATE (self);
if (nm_streq (name_owner, priv->dbus_client)) {
/* all good, the name is confirmed. */
return;
}
if ( name_owner
&& nm_streq (name_owner, priv->dbus_client)) {
/* all good, the name is confirmed. */
return;
}
_LOGD ("DBus client for keep alive is not on the bus");
@ -259,18 +252,12 @@ _is_alive_dbus_client (NMKeepAlive *self)
priv->dbus_client_confirmed = TRUE;
priv->dbus_client_confirm_cancellable = g_cancellable_new ();
g_dbus_connection_call (priv->dbus_connection,
"org.freedesktop.DBus",
"/org/freedesktop/DBus",
"org.freedesktop.DBus",
"GetNameOwner",
g_variant_new ("(s)", priv->dbus_client),
G_VARIANT_TYPE ("(s)"),
G_DBUS_CALL_FLAGS_NONE,
-1,
priv->dbus_client_confirm_cancellable,
get_name_owner_cb,
self);
nm_dbus_connection_call_get_name_owner (priv->dbus_connection,
priv->dbus_client,
-1,
priv->dbus_client_confirm_cancellable,
get_name_owner_cb,
self);
}
return TRUE;
}
@ -289,7 +276,7 @@ cleanup_dbus_watch (NMKeepAlive *self)
nm_clear_g_free (&priv->dbus_client);
if (priv->dbus_connection) {
g_dbus_connection_signal_unsubscribe (priv->dbus_connection,
priv->subscription_id);
nm_steal_int (&priv->subscription_id));
g_clear_object (&priv->dbus_connection);
}
}
@ -336,16 +323,11 @@ nm_keep_alive_set_dbus_client_watch (NMKeepAlive *self,
priv->dbus_client_watching = TRUE;
priv->dbus_client_confirmed = FALSE;
priv->dbus_connection = g_object_ref (connection);
priv->subscription_id = g_dbus_connection_signal_subscribe (connection,
"org.freedesktop.DBus",
"org.freedesktop.DBus",
"NameOwnerChanged",
"/org/freedesktop/DBus",
priv->dbus_client,
G_DBUS_SIGNAL_FLAGS_NONE,
name_owner_changed_cb,
self,
NULL);
priv->subscription_id = nm_dbus_connection_signal_subscribe_name_owner_changed (priv->dbus_connection,
priv->dbus_client,
name_owner_changed_cb,
self,
NULL);
} else
priv->dbus_client_watching = FALSE;

View file

@ -1129,7 +1129,6 @@ _config_changed_cb (NMConfig *config, NMConfigData *config_data, NMConfigChangeF
static void
_reload_auth_cb (NMAuthChain *chain,
GError *error,
GDBusMethodInvocation *context,
gpointer user_data)
{
@ -1142,7 +1141,7 @@ _reload_auth_cb (NMAuthChain *chain,
char s_buf[60];
NMConfigChangeFlags reload_type = NM_CONFIG_CHANGE_NONE;
g_assert (context);
nm_assert (G_IS_DBUS_METHOD_INVOCATION (context));
priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
flags = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "flags"));
@ -1150,13 +1149,7 @@ _reload_auth_cb (NMAuthChain *chain,
subject = nm_auth_chain_get_subject (chain);
result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_RELOAD);
if (error) {
_LOGD (LOGD_CORE, "Reload request failed: %s", error->message);
ret_error = g_error_new (NM_MANAGER_ERROR,
NM_MANAGER_ERROR_PERMISSION_DENIED,
"Reload request failed: %s",
error->message);
} else if (result != NM_AUTH_CALL_RESULT_YES) {
if (result != NM_AUTH_CALL_RESULT_YES) {
ret_error = g_error_new_literal (NM_MANAGER_ERROR,
NM_MANAGER_ERROR_PERMISSION_DENIED,
"Not authorized to reload configuration");
@ -1188,14 +1181,11 @@ _reload_auth_cb (NMAuthChain *chain,
if (ret_error) {
g_dbus_method_invocation_take_error (context, ret_error);
goto out;
return;
}
nm_config_reload (priv->config, reload_type, TRUE);
g_dbus_method_invocation_return_value (context, NULL);
out:
nm_auth_chain_destroy (chain);
}
static void
@ -2338,41 +2328,33 @@ nm_manager_rfkill_update (NMManager *self, RfKillType rtype)
static void
device_auth_done_cb (NMAuthChain *chain,
GError *auth_error,
GDBusMethodInvocation *context,
gpointer user_data)
{
NMManager *self = NM_MANAGER (user_data);
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
GError *error = NULL;
gs_free_error GError *error = NULL;
NMAuthCallResult result;
NMDevice *device;
const char *permission;
NMDeviceAuthRequestFunc callback;
NMAuthSubject *subject;
g_assert (context);
nm_assert (G_IS_DBUS_METHOD_INVOCATION (context));
priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
permission = nm_auth_chain_get_data (chain, "requested-permission");
g_assert (permission);
permission = nm_auth_chain_get_data (chain, "perm");
nm_assert (permission);
callback = nm_auth_chain_get_data (chain, "callback");
g_assert (callback);
nm_assert (callback);
device = nm_auth_chain_get_data (chain, "device");
g_assert (device);
nm_assert (NM_IS_DEVICE (device));
result = nm_auth_chain_get_result (chain, permission);
subject = nm_auth_chain_get_subject (chain);
if (auth_error) {
/* translate the auth error into a manager permission denied error */
_LOGD (LOGD_CORE, "%s request failed: %s", permission, auth_error->message);
error = g_error_new (NM_MANAGER_ERROR,
NM_MANAGER_ERROR_PERMISSION_DENIED,
"%s request failed: %s",
permission, auth_error->message);
} else if (result != NM_AUTH_CALL_RESULT_YES) {
if (result != NM_AUTH_CALL_RESULT_YES) {
_LOGD (LOGD_CORE, "%s request failed: not authorized", permission);
error = g_error_new (NM_MANAGER_ERROR,
NM_MANAGER_ERROR_PERMISSION_DENIED,
@ -2380,16 +2362,13 @@ device_auth_done_cb (NMAuthChain *chain,
permission);
}
g_assert (error || (result == NM_AUTH_CALL_RESULT_YES));
nm_assert (error || (result == NM_AUTH_CALL_RESULT_YES));
callback (device,
context,
subject,
error,
nm_auth_chain_get_data (chain, "user-data"));
g_clear_error (&error);
nm_auth_chain_destroy (chain);
}
static void
@ -2406,6 +2385,7 @@ device_auth_request_cb (NMDevice *device,
GError *error = NULL;
NMAuthSubject *subject = NULL;
NMAuthChain *chain;
char *permission_dup;
/* Validate the caller */
subject = nm_auth_subject_new_unix_process_from_context (context);
@ -2434,12 +2414,14 @@ device_auth_request_cb (NMDevice *device,
goto done;
}
permission_dup = g_strdup (permission);
priv->auth_chains = g_slist_append (priv->auth_chains, chain);
nm_auth_chain_set_data (chain, "device", g_object_ref (device), g_object_unref);
nm_auth_chain_set_data (chain, "requested-permission", g_strdup (permission), g_free);
nm_auth_chain_set_data (chain, "callback", callback, NULL);
nm_auth_chain_set_data (chain, "user-data", user_data, NULL);
nm_auth_chain_add_call (chain, permission, allow_interaction);
nm_auth_chain_set_data (chain, "perm", permission_dup /* transfer ownership */, g_free);
nm_auth_chain_add_call_unsafe (chain, permission_dup, allow_interaction);
done:
if (error)
@ -5625,7 +5607,6 @@ nm_manager_deactivate_connection (NMManager *manager,
static void
deactivate_net_auth_done_cb (NMAuthChain *chain,
GError *auth_error,
GDBusMethodInvocation *context,
gpointer user_data)
{
@ -5636,7 +5617,7 @@ deactivate_net_auth_done_cb (NMAuthChain *chain,
NMActiveConnection *active;
char *path;
g_assert (context);
nm_assert (G_IS_DBUS_METHOD_INVOCATION (context));
priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
@ -5644,13 +5625,7 @@ deactivate_net_auth_done_cb (NMAuthChain *chain,
result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL);
active = active_connection_get_by_path (self, path);
if (auth_error) {
_LOGD (LOGD_CORE, "Disconnect request failed: %s", auth_error->message);
error = g_error_new (NM_MANAGER_ERROR,
NM_MANAGER_ERROR_PERMISSION_DENIED,
"Deactivate request failed: %s",
auth_error->message);
} else if (result != NM_AUTH_CALL_RESULT_YES) {
if (result != NM_AUTH_CALL_RESULT_YES) {
error = g_error_new_literal (NM_MANAGER_ERROR,
NM_MANAGER_ERROR_PERMISSION_DENIED,
"Not authorized to deactivate connections");
@ -5680,8 +5655,6 @@ deactivate_net_auth_done_cb (NMAuthChain *chain,
g_dbus_method_invocation_take_error (context, error);
else
g_dbus_method_invocation_return_value (context, NULL);
nm_auth_chain_destroy (chain);
}
static void
@ -5984,45 +5957,6 @@ _internal_sleep (NMManager *self, gboolean do_sleep)
_notify (self, PROP_SLEEPING);
}
#if 0
static void
sleep_auth_done_cb (NMAuthChain *chain,
GError *error,
GDBusMethodInvocation *context,
gpointer user_data)
{
NMManager *self = NM_MANAGER (user_data);
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
GError *ret_error;
NMAuthCallResult result;
gboolean do_sleep;
priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_SLEEP_WAKE);
if (error) {
_LOGD (LOGD_SUSPEND, "Sleep/wake request failed: %s", error->message);
ret_error = g_error_new (NM_MANAGER_ERROR,
NM_MANAGER_ERROR_PERMISSION_DENIED,
"Sleep/wake request failed: %s",
error->message);
g_dbus_method_invocation_take_error (context, ret_error);
} else if (result != NM_AUTH_CALL_RESULT_YES) {
ret_error = g_error_new_literal (NM_MANAGER_ERROR,
NM_MANAGER_ERROR_PERMISSION_DENIED,
"Not authorized to sleep/wake");
g_dbus_method_invocation_take_error (context, ret_error);
} else {
/* Auth success */
do_sleep = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "sleep"));
_internal_sleep (self, do_sleep);
g_dbus_method_invocation_return_value (context, NULL);
}
nm_auth_chain_destroy (chain);
}
#endif
static void
impl_manager_sleep (NMDBusObject *obj,
const NMDBusInterfaceInfoExtended *interface_info,
@ -6097,49 +6031,38 @@ _internal_enable (NMManager *self, gboolean enable)
static void
enable_net_done_cb (NMAuthChain *chain,
GError *error,
GDBusMethodInvocation *context,
gpointer user_data)
{
NMManager *self = NM_MANAGER (user_data);
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
GError *ret_error = NULL;
NMAuthCallResult result;
gboolean enable;
NMAuthSubject *subject;
g_assert (context);
nm_assert (G_IS_DBUS_METHOD_INVOCATION (context));
priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
enable = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "enable"));
subject = nm_auth_chain_get_subject (chain);
result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK);
if (error) {
_LOGD (LOGD_CORE, "Enable request failed: %s", error->message);
ret_error = g_error_new (NM_MANAGER_ERROR,
NM_MANAGER_ERROR_PERMISSION_DENIED,
"Enable request failed: %s",
error->message);
} else if (result != NM_AUTH_CALL_RESULT_YES) {
if (result != NM_AUTH_CALL_RESULT_YES) {
GError *ret_error;
ret_error = g_error_new_literal (NM_MANAGER_ERROR,
NM_MANAGER_ERROR_PERMISSION_DENIED,
"Not authorized to enable/disable networking");
} else {
/* Auth success */
_internal_enable (self, enable);
g_dbus_method_invocation_return_value (context, NULL);
nm_audit_log_control_op (NM_AUDIT_OP_NET_CONTROL, enable ? "on" : "off", TRUE,
subject, NULL);
}
if (ret_error) {
nm_audit_log_control_op (NM_AUDIT_OP_NET_CONTROL, enable ? "on" : "off", FALSE,
subject, ret_error->message);
g_dbus_method_invocation_take_error (context, ret_error);
return;
}
nm_auth_chain_destroy (chain);
_internal_enable (self, enable);
g_dbus_method_invocation_return_value (context, NULL);
nm_audit_log_control_op (NM_AUDIT_OP_NET_CONTROL, enable ? "on" : "off", TRUE,
subject, NULL);
}
static void
@ -6204,50 +6127,38 @@ get_perm_add_result (NMManager *self, NMAuthChain *chain, GVariantBuilder *resul
static void
get_permissions_done_cb (NMAuthChain *chain,
GError *error,
GDBusMethodInvocation *context,
gpointer user_data)
{
NMManager *self = NM_MANAGER (user_data);
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
GError *ret_error;
GVariantBuilder results;
g_assert (context);
nm_assert (G_IS_DBUS_METHOD_INVOCATION (context));
priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
if (error) {
_LOGD (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);
g_dbus_method_invocation_take_error (context, ret_error);
} else {
g_variant_builder_init (&results, G_VARIANT_TYPE ("a{ss}"));
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_SLEEP_WAKE);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_NETWORK_CONTROL);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_RELOAD);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_ENABLE_DISABLE_STATISTICS);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK);
g_variant_builder_init (&results, G_VARIANT_TYPE ("a{ss}"));
g_dbus_method_invocation_return_value (context,
g_variant_new ("(a{ss})", &results));
}
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_SLEEP_WAKE);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_NETWORK_CONTROL);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_RELOAD);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_ENABLE_DISABLE_STATISTICS);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK);
nm_auth_chain_destroy (chain);
g_dbus_method_invocation_return_value (context,
g_variant_new ("(a{ss})", &results));
}
static void
@ -6413,7 +6324,6 @@ device_connectivity_done (NMDevice *device,
static void
check_connectivity_auth_done_cb (NMAuthChain *chain,
GError *auth_error,
GDBusMethodInvocation *context,
gpointer user_data)
{
@ -6428,21 +6338,14 @@ check_connectivity_auth_done_cb (NMAuthChain *chain,
result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL);
if (auth_error) {
_LOGD (LOGD_CORE, "CheckConnectivity request failed: %s", auth_error->message);
error = g_error_new (NM_MANAGER_ERROR,
NM_MANAGER_ERROR_PERMISSION_DENIED,
"Connectivity check request failed: %s",
auth_error->message);
} else if (result != NM_AUTH_CALL_RESULT_YES) {
if (result != NM_AUTH_CALL_RESULT_YES) {
error = g_error_new_literal (NM_MANAGER_ERROR,
NM_MANAGER_ERROR_PERMISSION_DENIED,
"Not authorized to recheck connectivity");
}
if (error) {
g_dbus_method_invocation_take_error (context, error);
goto out;
return;
}
data = g_slice_new (ConnectivityCheckData);
@ -6473,9 +6376,6 @@ check_connectivity_auth_done_cb (NMAuthChain *chain,
data);
/* @data got destroyed. */
}
out:
nm_auth_chain_destroy (chain);
}
static void
@ -6847,7 +6747,6 @@ typedef struct {
static void
_dbus_set_property_auth_cb (NMAuthChain *chain,
GError *error,
GDBusMethodInvocation *invocation,
gpointer user_data)
{
@ -6870,10 +6769,9 @@ _dbus_set_property_auth_cb (NMAuthChain *chain,
priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
result = nm_auth_chain_get_result (chain, property_info->writable.permission);
if ( error
|| result != NM_AUTH_CALL_RESULT_YES) {
if (result != NM_AUTH_CALL_RESULT_YES) {
error_name = NM_PERM_DENIED_ERROR;
error_message = error ? error->message : "Not authorized to perform this operation";
error_message = "Not authorized to perform this operation";
goto out;
}
@ -6914,7 +6812,6 @@ out:
g_dbus_method_invocation_return_dbus_error (invocation, error_name, error_message);
else
g_dbus_method_invocation_return_value (invocation, NULL);
nm_auth_chain_destroy (chain);
}
void
@ -6950,7 +6847,7 @@ nm_manager_dbus_set_property_handle (NMDBusObject *obj,
chain = nm_auth_chain_new_subject (subject, invocation, _dbus_set_property_auth_cb, handle_data);
priv->auth_chains = g_slist_append (priv->auth_chains, chain);
nm_auth_chain_add_call (chain, property_info->writable.permission, TRUE);
nm_auth_chain_add_call_unsafe (chain, property_info->writable.permission, TRUE);
return;
err:
@ -6979,7 +6876,6 @@ _checkpoint_mgr_get (NMManager *self, gboolean create_as_needed)
static void
checkpoint_auth_done_cb (NMAuthChain *chain,
GError *auth_error,
GDBusMethodInvocation *context,
gpointer user_data)
{
@ -7003,12 +6899,7 @@ checkpoint_auth_done_cb (NMAuthChain *chain,
NM_AUDIT_OP_CHECKPOINT_ADJUST_ROLLBACK_TIMEOUT))
arg = checkpoint_path = nm_auth_chain_get_data (chain, "checkpoint_path");
if (auth_error) {
error = g_error_new (NM_MANAGER_ERROR,
NM_MANAGER_ERROR_PERMISSION_DENIED,
"checkpoint check request failed: %s",
auth_error->message);
} else if (result != NM_AUTH_CALL_RESULT_YES) {
if (result != NM_AUTH_CALL_RESULT_YES) {
error = g_error_new_literal (NM_MANAGER_ERROR,
NM_MANAGER_ERROR_PERMISSION_DENIED,
"Not authorized to checkpoint/rollback");
@ -7048,8 +6939,6 @@ checkpoint_auth_done_cb (NMAuthChain *chain,
g_dbus_method_invocation_take_error (context, error);
else
g_dbus_method_invocation_return_value (context, variant);
nm_auth_chain_destroy (chain);
}
static void
@ -7383,7 +7272,8 @@ nm_manager_setup (void)
singleton_instance = self;
nm_singleton_instance_register ();
_LOGD (LOGD_CORE, "setup %s singleton (%p)", "NMManager", singleton_instance);
nm_log_dbg (LOGD_CORE, "setup %s singleton ("NM_HASH_OBFUSCATE_PTR_FMT")",
"NMManager", NM_HASH_OBFUSCATE_PTR (singleton_instance));
nm_dbus_object_export (NM_DBUS_OBJECT (self));
return self;

View file

@ -23,11 +23,14 @@
#include "nm-pacrunner-manager.h"
#include "nm-utils.h"
#include "NetworkManagerUtils.h"
#include "platform/nm-platform.h"
#include "nm-dbus-manager.h"
#include "nm-proxy-config.h"
#include "nm-ip4-config.h"
#include "nm-ip6-config.h"
#include "c-list/src/c-list.h"
#include "nm-glib-aux/nm-dbus-aux.h"
#define PACRUNNER_DBUS_SERVICE "org.pacrunner"
#define PACRUNNER_DBUS_INTERFACE "org.pacrunner.Manager"
@ -35,25 +38,27 @@
/*****************************************************************************/
struct _NMPacrunnerCallId {
CList lst;
struct _NMPacrunnerConfId {
CList conf_id_lst;
/* this might be a dangling pointer after the async operation
* is cancelled. */
NMPacrunnerManager *manager_maybe_dangling;
NMPacrunnerManager *self;
GVariant *parameters;
GVariant *args;
char *path;
guint64 log_id;
guint refcount;
};
typedef struct _NMPacrunnerCallId Config;
typedef struct {
char *iface;
GDBusProxy *pacrunner;
GDBusConnection *dbus_connection;
GCancellable *cancellable;
CList configs;
CList conf_id_lst_head;
guint64 log_id_counter;
guint name_owner_changed_id;
bool dbus_initied:1;
bool has_name_owner:1;
bool try_start_blocked:1;
} NMPacrunnerManagerPrivate;
struct _NMPacrunnerManager {
@ -79,332 +84,139 @@ NM_DEFINE_SINGLETON_GETTER (NMPacrunnerManager, nm_pacrunner_manager_get, NM_TYP
#define _NMLOG(level, ...) __NMLOG_DEFAULT (level, _NMLOG_DOMAIN, "pacrunner", __VA_ARGS__)
#define _NMLOG2_PREFIX_NAME "pacrunner"
#define _NMLOG2(level, config, ...) \
#define _NMLOG2(level, conf_id, ...) \
G_STMT_START { \
nm_log ((level), _NMLOG_DOMAIN, NULL, NULL, \
"%s%p]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
"%s%"G_GUINT64_FORMAT"]: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \
_NMLOG2_PREFIX_NAME": call[", \
(config) \
_NM_UTILS_MACRO_REST(__VA_ARGS__)); \
(conf_id)->log_id \
_NM_UTILS_MACRO_REST (__VA_ARGS__)); \
} G_STMT_END
/*****************************************************************************/
static void pacrunner_remove_done (GObject *source, GAsyncResult *res, gpointer user_data);
static void _call_destroy_proxy_configuration (NMPacrunnerManager *self,
NMPacrunnerConfId *conf_id,
const char *path,
gboolean verbose_log);
/*****************************************************************************/
static Config *
config_new (NMPacrunnerManager *manager, GVariant *args)
static NMPacrunnerConfId *
conf_id_ref (NMPacrunnerConfId *conf_id)
{
Config *config;
nm_assert (conf_id);
nm_assert (conf_id->refcount > 0);
config = g_slice_new0 (Config);
config->manager_maybe_dangling = manager;
config->args = g_variant_ref_sink (args);
config->refcount = 1;
c_list_link_tail (&NM_PACRUNNER_MANAGER_GET_PRIVATE (manager)->configs,
&config->lst);
return config;
}
static Config *
config_ref (Config *config)
{
nm_assert (config);
nm_assert (config->refcount > 0);
config->refcount++;
return config;
conf_id->refcount++;
return conf_id;
}
static void
config_unref (Config *config)
conf_id_unref (NMPacrunnerConfId *conf_id)
{
nm_assert (config);
nm_assert (config->refcount > 0);
nm_assert (conf_id);
nm_assert (conf_id->refcount > 0);
if (config->refcount == 1) {
g_variant_unref (config->args);
g_free (config->path);
c_list_unlink_stale (&config->lst);
g_slice_free (Config, config);
if (conf_id->refcount == 1) {
g_variant_unref (conf_id->parameters);
g_free (conf_id->path);
c_list_unlink_stale (&conf_id->conf_id_lst);
g_object_unref (conf_id->self);
g_slice_free (NMPacrunnerConfId, conf_id);
} else
config->refcount--;
conf_id->refcount--;
}
NM_AUTO_DEFINE_FCN0 (NMPacrunnerConfId *, _nm_auto_unref_conf_id, conf_id_unref);
#define nm_auto_unref_conf_id nm_auto (_nm_auto_unref_conf_id)
/*****************************************************************************/
static void
add_proxy_config (GVariantBuilder *proxy_data, const NMProxyConfig *proxy_config)
{
const char *pac_url, *pac_script;
NMProxyConfigMethod method;
method = nm_proxy_config_get_method (proxy_config);
if (method == NM_PROXY_CONFIG_METHOD_AUTO) {
pac_url = nm_proxy_config_get_pac_url (proxy_config);
if (pac_url) {
g_variant_builder_add (proxy_data, "{sv}",
"URL",
g_variant_new_string (pac_url));
}
pac_script = nm_proxy_config_get_pac_script (proxy_config);
if (pac_script) {
g_variant_builder_add (proxy_data, "{sv}",
"Script",
g_variant_new_string (pac_script));
}
}
g_variant_builder_add (proxy_data, "{sv}",
"BrowserOnly",
g_variant_new_boolean (nm_proxy_config_get_browser_only (proxy_config)));
}
static void
get_ip4_domains (GPtrArray *domains, NMIP4Config *ip4)
get_ip_domains (GPtrArray *domains, NMIPConfig *ip_config)
{
NMDedupMultiIter ipconf_iter;
char *cidr;
const NMPlatformIP4Address *address;
const NMPlatformIP4Route *routes;
guint i;
guint i, num;
char sbuf[NM_UTILS_INET_ADDRSTRLEN];
int addr_family;
/* Extract searches */
for (i = 0; i < nm_ip4_config_get_num_searches (ip4); i++)
g_ptr_array_add (domains, g_strdup (nm_ip4_config_get_search (ip4, i)));
/* Extract domains */
for (i = 0; i < nm_ip4_config_get_num_domains (ip4); i++)
g_ptr_array_add (domains, g_strdup (nm_ip4_config_get_domain (ip4, i)));
/* Add addresses and routes in CIDR form */
nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, ip4, &address) {
cidr = g_strdup_printf ("%s/%u",
nm_utils_inet4_ntop (address->address, sbuf),
address->plen);
g_ptr_array_add (domains, cidr);
}
nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, ip4, &routes) {
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (routes))
continue;
cidr = g_strdup_printf ("%s/%u",
nm_utils_inet4_ntop (routes->network, sbuf),
routes->plen);
g_ptr_array_add (domains, cidr);
}
}
static void
get_ip6_domains (GPtrArray *domains, NMIP6Config *ip6)
{
NMDedupMultiIter ipconf_iter;
char *cidr;
const NMPlatformIP6Address *address;
const NMPlatformIP6Route *routes;
guint i;
char sbuf[NM_UTILS_INET_ADDRSTRLEN];
/* Extract searches */
for (i = 0; i < nm_ip6_config_get_num_searches (ip6); i++)
g_ptr_array_add (domains, g_strdup (nm_ip6_config_get_search (ip6, i)));
/* Extract domains */
for (i = 0; i < nm_ip6_config_get_num_domains (ip6); i++)
g_ptr_array_add (domains, g_strdup (nm_ip6_config_get_domain (ip6, i)));
/* Add addresses and routes in CIDR form */
nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, ip6, &address) {
cidr = g_strdup_printf ("%s/%u",
nm_utils_inet6_ntop (&address->address, sbuf),
address->plen);
g_ptr_array_add (domains, cidr);
}
nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, ip6, &routes) {
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (routes))
continue;
cidr = g_strdup_printf ("%s/%u",
nm_utils_inet6_ntop (&routes->network, sbuf),
routes->plen);
g_ptr_array_add (domains, cidr);
}
}
/*****************************************************************************/
static GCancellable *
_ensure_cancellable (NMPacrunnerManagerPrivate *priv)
{
if (G_UNLIKELY (!priv->cancellable))
priv->cancellable = g_cancellable_new ();
return priv->cancellable;
}
static void
pacrunner_send_done (GObject *source, GAsyncResult *res, gpointer user_data)
{
Config *config = user_data;
NMPacrunnerManager *self;
NMPacrunnerManagerPrivate *priv;
gs_free_error GError *error = NULL;
gs_unref_variant GVariant *variant = NULL;
const char *path = NULL;
nm_assert (!config->path);
variant = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
goto out;
self = NM_PACRUNNER_MANAGER (config->manager_maybe_dangling);
priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self);
if (!variant)
_LOG2D (config, "sending failed: %s", error->message);
else {
g_variant_get (variant, "(&o)", &path);
if (c_list_is_empty (&config->lst)) {
_LOG2D (config, "sent (%s), but destroy it right away", path);
g_dbus_proxy_call (priv->pacrunner,
"DestroyProxyConfiguration",
g_variant_new ("(o)", path),
G_DBUS_CALL_FLAGS_NO_AUTO_START,
-1,
_ensure_cancellable (priv),
pacrunner_remove_done,
config_ref (config));
} else {
_LOG2D (config, "sent (%s)", path);
config->path = g_strdup (path);
}
}
out:
config_unref (config);
}
static void
pacrunner_send_config (NMPacrunnerManager *self, Config *config)
{
NMPacrunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self);
if (priv->pacrunner) {
_LOG2T (config, "sending...");
nm_assert (!config->path);
g_dbus_proxy_call (priv->pacrunner,
"CreateProxyConfiguration",
config->args,
G_DBUS_CALL_FLAGS_NO_AUTO_START,
-1,
_ensure_cancellable (priv),
pacrunner_send_done,
config_ref (config));
}
}
static void
name_owner_changed (NMPacrunnerManager *self)
{
NMPacrunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self);
gs_free char *owner = NULL;
CList *iter;
owner = g_dbus_proxy_get_name_owner (priv->pacrunner);
if (owner) {
_LOGD ("name owner appeared (%s)", owner);
c_list_for_each (iter, &priv->configs)
pacrunner_send_config (self, c_list_entry (iter, Config, lst));
} else {
_LOGD ("name owner disappeared");
nm_clear_g_cancellable (&priv->cancellable);
c_list_for_each (iter, &priv->configs)
nm_clear_g_free (&c_list_entry (iter, Config, lst)->path);
}
}
static void
name_owner_changed_cb (GObject *object,
GParamSpec *pspec,
gpointer user_data)
{
name_owner_changed (user_data);
}
static void
pacrunner_proxy_cb (GObject *source, GAsyncResult *res, gpointer user_data)
{
NMPacrunnerManager *self = user_data;
NMPacrunnerManagerPrivate *priv;
gs_free_error GError *error = NULL;
GDBusProxy *proxy;
proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
if (!proxy) {
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
_LOGE ("failed to create D-Bus proxy for pacrunner: %s", error->message);
if (!ip_config)
return;
addr_family = nm_ip_config_get_addr_family (ip_config);
num = nm_ip_config_get_num_searches (ip_config);
for (i = 0; i < num; i++)
g_ptr_array_add (domains, g_strdup (nm_ip_config_get_search (ip_config, i)));
num = nm_ip_config_get_num_domains (ip_config);
for (i = 0; i < num; i++)
g_ptr_array_add (domains, g_strdup (nm_ip_config_get_domain (ip_config, i)));
if (addr_family == AF_INET) {
const NMPlatformIP4Address *address;
nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, (NMIP4Config *) ip_config, &address) {
cidr = g_strdup_printf ("%s/%u",
nm_utils_inet4_ntop (address->address, sbuf),
address->plen);
g_ptr_array_add (domains, cidr);
}
} else {
const NMPlatformIP6Address *address;
nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, (NMIP6Config *) ip_config, &address) {
cidr = g_strdup_printf ("%s/%u",
nm_utils_inet6_ntop (&address->address, sbuf),
address->plen);
g_ptr_array_add (domains, cidr);
}
}
priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self);
if (addr_family == AF_INET) {
const NMPlatformIP4Route *routes;
priv->pacrunner = proxy;
g_signal_connect (priv->pacrunner, "notify::g-name-owner",
G_CALLBACK (name_owner_changed_cb), self);
name_owner_changed (self);
nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, (NMIP4Config *) ip_config, &routes) {
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (routes))
continue;
cidr = g_strdup_printf ("%s/%u",
nm_utils_inet4_ntop (routes->network, sbuf),
routes->plen);
g_ptr_array_add (domains, cidr);
}
} else {
const NMPlatformIP6Route *routes;
nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, (NMIP6Config *) ip_config, &routes) {
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (routes))
continue;
cidr = g_strdup_printf ("%s/%u",
nm_utils_inet6_ntop (&routes->network, sbuf),
routes->plen);
g_ptr_array_add (domains, cidr);
}
}
}
/**
* nm_pacrunner_manager_send:
* @self: the #NMPacrunnerManager
* @iface: the iface for the connection or %NULL
* @proxy_config: proxy config of the connection
* @ip4_config: IP4 config of the connection to extract domain info from
* @ip6_config: IP6 config of the connection to extract domain info from
*
* Returns: a #NMPacrunnerCallId call id. The function cannot
* fail and always returns a non NULL pointer. The call-id may
* be used to remove the configuration later via nm_pacrunner_manager_remove().
* Note that the call-id does not keep the @self instance alive.
* If you plan to remove the configuration later, you must keep
* the instance alive long enough. You can remove the configuration
* at most once using this call call-id.
*/
NMPacrunnerCallId *
nm_pacrunner_manager_send (NMPacrunnerManager *self,
const char *iface,
NMProxyConfig *proxy_config,
NMIP4Config *ip4_config,
NMIP6Config *ip6_config)
static GVariant *
_make_request_create_proxy_configuration (NMProxyConfig *proxy_config,
const char *iface,
NMIP4Config *ip4_config,
NMIP6Config *ip6_config)
{
char **strv = NULL;
GVariantBuilder builder;
NMProxyConfigMethod method;
NMPacrunnerManagerPrivate *priv;
GVariantBuilder proxy_data;
GPtrArray *domains;
Config *config;
const char *pac_url;
const char *pac_script;
g_return_val_if_fail (NM_IS_PACRUNNER_MANAGER (self), NULL);
g_return_val_if_fail (proxy_config, NULL);
nm_assert (NM_IS_PROXY_CONFIG (proxy_config));
priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self);
g_free (priv->iface);
priv->iface = g_strdup (iface);
g_variant_builder_init (&proxy_data, G_VARIANT_TYPE_VARDICT);
g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
if (iface) {
g_variant_builder_add (&proxy_data, "{sv}",
g_variant_builder_add (&builder, "{sv}",
"Interface",
g_variant_new_string (iface));
}
@ -412,167 +224,410 @@ nm_pacrunner_manager_send (NMPacrunnerManager *self,
method = nm_proxy_config_get_method (proxy_config);
switch (method) {
case NM_PROXY_CONFIG_METHOD_AUTO:
g_variant_builder_add (&proxy_data, "{sv}",
g_variant_builder_add (&builder, "{sv}",
"Method",
g_variant_new_string ("auto"));
pac_url = nm_proxy_config_get_pac_url (proxy_config);
if (pac_url) {
g_variant_builder_add (&builder, "{sv}",
"URL",
g_variant_new_string (pac_url));
}
pac_script = nm_proxy_config_get_pac_script (proxy_config);
if (pac_script) {
g_variant_builder_add (&builder, "{sv}",
"Script",
g_variant_new_string (pac_script));
}
break;
case NM_PROXY_CONFIG_METHOD_NONE:
g_variant_builder_add (&proxy_data, "{sv}",
g_variant_builder_add (&builder, "{sv}",
"Method",
g_variant_new_string ("direct"));
break;
}
/* Extract stuff from configs */
add_proxy_config (&proxy_data, proxy_config);
g_variant_builder_add (&builder, "{sv}",
"BrowserOnly",
g_variant_new_boolean (nm_proxy_config_get_browser_only (proxy_config)));
if (ip4_config || ip6_config) {
gs_unref_ptrarray GPtrArray *domains = NULL;
domains = g_ptr_array_new_with_free_func (g_free);
if (ip4_config)
get_ip4_domains (domains, ip4_config);
if (ip6_config)
get_ip6_domains (domains, ip6_config);
get_ip_domains (domains, NM_IP_CONFIG_CAST (ip4_config));
get_ip_domains (domains, NM_IP_CONFIG_CAST (ip6_config));
g_ptr_array_add (domains, NULL);
strv = (char **) g_ptr_array_free (domains, (domains->len == 1));
if (strv) {
g_variant_builder_add (&proxy_data, "{sv}",
if (domains->len > 0) {
g_variant_builder_add (&builder, "{sv}",
"Domains",
g_variant_new_strv ((const char *const *) strv, -1));
g_strfreev (strv);
g_variant_new_strv ((const char *const*) domains->pdata,
domains->len));
}
}
config = config_new (self, g_variant_new ("(a{sv})", &proxy_data));
{
gs_free char *args_str = NULL;
_LOG2D (config, "send: new config %s",
(args_str = g_variant_print (config->args, FALSE)));
}
/* Send if pacrunner is available on bus, otherwise
* config has already been appended above to be
* sent when pacrunner appears.
*/
pacrunner_send_config (self, config);
return config;
return g_variant_new ("(a{sv})", &builder);
}
/*****************************************************************************/
static void
pacrunner_remove_done (GObject *source, GAsyncResult *res, gpointer user_data)
_call_destroy_proxy_configuration_cb (GObject *source,
GAsyncResult *res,
gpointer user_data)
{
Config *config = user_data;
nm_auto_unref_conf_id NMPacrunnerConfId *conf_id = user_data;
gs_free_error GError *error = NULL;
gs_unref_variant GVariant *ret = NULL;
ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), res, &error);
if (!ret) {
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
goto out;
_LOG2D (config, "remove failed: %s", error->message);
goto out;
_LOG2T (conf_id, "destroy proxy configuration: failed with %s", error->message);
else
_LOG2T (conf_id, "destroy proxy configuration: cancelled");
return;
}
_LOG2T (conf_id, "destroy proxy configuration: success");
}
static void
_call_create_proxy_configuration_cb (GObject *source,
GAsyncResult *res,
gpointer user_data)
{
nm_auto_unref_conf_id NMPacrunnerConfId *conf_id = user_data;
NMPacrunnerManager *self = NM_PACRUNNER_MANAGER (conf_id->self);
gs_free_error GError *error = NULL;
gs_unref_variant GVariant *variant = NULL;
const char *path = NULL;
nm_assert (!conf_id->path);
variant = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), res, &error);
if (!variant) {
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
_LOG2T (conf_id, "create proxy configuration failed: %s", error->message);
else
_LOG2T (conf_id, "create proxy configuration cancelled");
return;
}
_LOG2D (config, "removed");
g_variant_get (variant, "(&o)", &path);
out:
config_unref (config);
if (c_list_is_empty (&conf_id->conf_id_lst)) {
_LOG2T (conf_id, "create proxy configuration succeeded (%s), but destroy it right away", path);
_call_destroy_proxy_configuration (self,
conf_id,
path,
FALSE);
} else {
_LOG2T (conf_id, "create proxy configuration succeeded (%s)", path);
conf_id->path = g_strdup (path);
}
}
static void
_call_destroy_proxy_configuration (NMPacrunnerManager *self,
NMPacrunnerConfId *conf_id,
const char *path,
gboolean verbose_log)
{
NMPacrunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self);
if (verbose_log)
_LOG2T (conf_id, "destroy proxy configuration %s...", path);
g_dbus_connection_call (priv->dbus_connection,
PACRUNNER_DBUS_SERVICE,
PACRUNNER_DBUS_PATH,
PACRUNNER_DBUS_INTERFACE,
"DestroyProxyConfiguration",
g_variant_new ("(o)", path),
G_VARIANT_TYPE ("()"),
G_DBUS_CALL_FLAGS_NO_AUTO_START,
NM_SHUTDOWN_TIMEOUT_MS,
priv->cancellable,
_call_destroy_proxy_configuration_cb,
conf_id_ref (conf_id));
}
static void
_call_create_proxy_configuration (NMPacrunnerManager *self,
NMPacrunnerConfId *conf_id,
gboolean verbose_log)
{
NMPacrunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self);
if (verbose_log)
_LOG2T (conf_id, "create proxy configuration...");
g_dbus_connection_call (priv->dbus_connection,
PACRUNNER_DBUS_SERVICE,
PACRUNNER_DBUS_PATH,
PACRUNNER_DBUS_INTERFACE,
"CreateProxyConfiguration",
conf_id->parameters,
G_VARIANT_TYPE ("(o)"),
G_DBUS_CALL_FLAGS_NO_AUTO_START,
NM_SHUTDOWN_TIMEOUT_MS,
priv->cancellable,
_call_create_proxy_configuration_cb,
conf_id_ref (conf_id));
}
static gboolean
_try_start_service_by_name (NMPacrunnerManager *self)
{
NMPacrunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self);
if ( priv->try_start_blocked
|| !priv->dbus_initied)
return FALSE;
_LOGD ("try D-Bus activating pacrunner...");
priv->try_start_blocked = TRUE;
nm_dbus_connection_call_start_service_by_name (priv->dbus_connection,
PACRUNNER_DBUS_SERVICE,
-1,
NULL,
NULL,
NULL);
return TRUE;
}
/*****************************************************************************/
/**
* nm_pacrunner_manager_add:
* @self: the #NMPacrunnerManager
* @proxy_config: proxy config of the connection
* @iface: the iface for the connection or %NULL
* @ip4_config: IP4 config of the connection to extract domain info from
* @ip6_config: IP6 config of the connection to extract domain info from
*
* Returns: a #NMPacrunnerConfId id. The function cannot
* fail and always returns a non NULL pointer. The conf-id may
* be used to remove the configuration later via nm_pacrunner_manager_remove().
* Note that the conf-id keeps the @self instance alive.
*/
NMPacrunnerConfId *
nm_pacrunner_manager_add (NMPacrunnerManager *self,
NMProxyConfig *proxy_config,
const char *iface,
NMIP4Config *ip4_config,
NMIP6Config *ip6_config)
{
NMPacrunnerManagerPrivate *priv;
NMPacrunnerConfId *conf_id;
gs_free char *log_msg = NULL;
g_return_val_if_fail (NM_IS_PACRUNNER_MANAGER (self), NULL);
g_return_val_if_fail (proxy_config, NULL);
priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self);
conf_id = g_slice_new (NMPacrunnerConfId);
*conf_id = (NMPacrunnerConfId) {
.log_id = ++priv->log_id_counter,
.refcount = 1,
.self = g_object_ref (self),
.parameters = g_variant_ref_sink (_make_request_create_proxy_configuration (proxy_config,
iface,
ip4_config,
ip6_config)),
};
c_list_link_tail (&priv->conf_id_lst_head,
&conf_id->conf_id_lst);
if (!priv->has_name_owner) {
_LOG2T (conf_id, "add config: %s (%s)",
(log_msg = g_variant_print (conf_id->parameters, FALSE)),
"pacrunner D-Bus service not running");
_try_start_service_by_name (self);
} else {
_LOG2T (conf_id, "add config: %s (%s)",
(log_msg = g_variant_print (conf_id->parameters, FALSE)),
"create proxy configuration");
_call_create_proxy_configuration (self, conf_id, FALSE);
}
return conf_id;
}
/**
* nm_pacrunner_manager_remove:
* @self: the #NMPacrunnerManager
* @call_id: the call-id obtained from nm_pacrunner_manager_send()
* @conf_id: the conf id obtained from nm_pacrunner_manager_add()
*/
void
nm_pacrunner_manager_remove (NMPacrunnerManager *self, NMPacrunnerCallId *call_id)
nm_pacrunner_manager_remove (NMPacrunnerConfId *conf_id)
{
_nm_unused nm_auto_unref_conf_id NMPacrunnerConfId *conf_id_free = conf_id;
NMPacrunnerManager *self;
NMPacrunnerManagerPrivate *priv;
Config *config;
g_return_if_fail (conf_id);
self = conf_id->self;
g_return_if_fail (NM_IS_PACRUNNER_MANAGER (self));
g_return_if_fail (call_id);
config = call_id;
priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self);
_LOG2T (config, "removing...");
_LOG2T (conf_id, "removing...");
nm_assert (c_list_contains (&priv->configs, &config->lst));
nm_assert (c_list_contains (&priv->conf_id_lst_head, &conf_id->conf_id_lst));
if (priv->pacrunner) {
if (!config->path) {
/* send() failed or is still pending. The item is unlinked from
* priv->configs, so pacrunner_send_done() knows to call
* DestroyProxyConfiguration right away.
*/
} else {
g_dbus_proxy_call (priv->pacrunner,
"DestroyProxyConfiguration",
g_variant_new ("(o)", config->path),
G_DBUS_CALL_FLAGS_NO_AUTO_START,
-1,
_ensure_cancellable (priv),
pacrunner_remove_done,
config_ref (config));
nm_clear_g_free (&config->path);
}
c_list_unlink (&conf_id->conf_id_lst);
if (!conf_id->path) {
/* There is no ID to destroy the configuration.
*
* That can happen because:
*
* - pacrunner D-Bus service is not running (no name owner) and we didn't call CreateProxyConfiguration.
* - CreateProxyConfiguration failed.
* - CreateProxyConfiguration is in progress.
*
* In all cases there is nothing to do. Note that if CreateProxyConfiguration is in progress
* it has a reference on the conf-id and it will automatically destroy the configuration
* when it completes.
*/
return;
}
c_list_unlink (&config->lst);
config_unref (config);
_call_destroy_proxy_configuration (self, conf_id, conf_id->path, TRUE);
}
gboolean
nm_pacrunner_manager_remove_clear (NMPacrunnerManager *self,
NMPacrunnerCallId **p_call_id)
nm_pacrunner_manager_remove_clear (NMPacrunnerConfId **p_conf_id)
{
g_return_val_if_fail (p_call_id, FALSE);
g_return_val_if_fail (p_conf_id, FALSE);
/* if we have no call-id, allow for %NULL */
g_return_val_if_fail ((!self && !*p_call_id) || NM_IS_PACRUNNER_MANAGER (self), FALSE);
if (!*p_call_id)
if (!*p_conf_id)
return FALSE;
nm_pacrunner_manager_remove (self,
g_steal_pointer (p_call_id));
nm_pacrunner_manager_remove (g_steal_pointer (p_conf_id));
return TRUE;
}
/*****************************************************************************/
static void
name_owner_changed (NMPacrunnerManager *self,
const char *name_owner)
{
NMPacrunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self);
NMPacrunnerConfId *conf_id;
gboolean has_name_owner;
has_name_owner = (name_owner && name_owner[0]);
if ( priv->dbus_initied
&& priv->has_name_owner == has_name_owner)
return;
priv->has_name_owner = has_name_owner;
nm_clear_g_cancellable (&priv->cancellable);
if (has_name_owner) {
priv->dbus_initied = TRUE;
priv->try_start_blocked = FALSE;
_LOGD ("pacrunner appeared on D-Bus (%s)", name_owner);
priv->cancellable = g_cancellable_new ();
c_list_for_each_entry (conf_id, &priv->conf_id_lst_head, conf_id_lst)
_call_create_proxy_configuration (self, conf_id, TRUE);
} else {
if (!priv->dbus_initied) {
priv->dbus_initied = TRUE;
nm_assert (!priv->try_start_blocked);
_LOGD ("pacrunner not on D-Bus");
} else
_LOGD ("pacrunner disappeared from D-Bus");
if (!c_list_is_empty (&priv->conf_id_lst_head)) {
c_list_for_each_entry (conf_id, &priv->conf_id_lst_head, conf_id_lst)
nm_clear_g_free (&conf_id->path);
_try_start_service_by_name (self);
}
}
}
static void
name_owner_changed_cb (GDBusConnection *connection,
const char *sender_name,
const char *object_path,
const char *interface_name,
const char *signal_name,
GVariant *parameters,
gpointer user_data)
{
const char *new_owner;
if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(sss)")))
return;
g_variant_get (parameters,
"(&s&s&s)",
NULL,
NULL,
&new_owner);
name_owner_changed (user_data, new_owner);
}
static void
get_name_owner_cb (const char *name_owner,
GError *error,
gpointer user_data)
{
if ( !name_owner
&& g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
name_owner_changed (user_data, name_owner);
}
/*****************************************************************************/
static void
nm_pacrunner_manager_init (NMPacrunnerManager *self)
{
NMPacrunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self);
c_list_init (&priv->configs);
g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
PACRUNNER_DBUS_SERVICE,
PACRUNNER_DBUS_PATH,
PACRUNNER_DBUS_INTERFACE,
_ensure_cancellable (priv),
pacrunner_proxy_cb,
self);
c_list_init (&priv->conf_id_lst_head);
priv->dbus_connection = nm_g_object_ref (NM_MAIN_DBUS_CONNECTION_GET);
if (!priv->dbus_connection) {
_LOGD ("no D-Bus connection to talk to pacrunner");
return;
}
priv->name_owner_changed_id = nm_dbus_connection_signal_subscribe_name_owner_changed (priv->dbus_connection,
PACRUNNER_DBUS_SERVICE,
name_owner_changed_cb,
self,
NULL);
priv->cancellable = g_cancellable_new ();
nm_dbus_connection_call_get_name_owner (priv->dbus_connection,
PACRUNNER_DBUS_SERVICE,
-1,
priv->cancellable,
get_name_owner_cb,
self);
}
static void
dispose (GObject *object)
{
NMPacrunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE ((NMPacrunnerManager *) object);
CList *iter, *safe;
c_list_for_each_safe (iter, safe, &priv->configs) {
c_list_unlink (iter);
config_unref (c_list_entry (iter, Config, lst));
}
nm_assert (c_list_is_empty (&priv->conf_id_lst_head));
/* we cancel all pending operations. Note that pacrunner automatically
* removes all configuration once NetworkManager disconnects from
@ -580,8 +635,9 @@ dispose (GObject *object)
*/
nm_clear_g_cancellable (&priv->cancellable);
g_clear_pointer (&priv->iface, g_free);
g_clear_object (&priv->pacrunner);
nm_clear_g_dbus_connection_signal (priv->dbus_connection,
&priv->name_owner_changed_id);
g_clear_object (&priv->dbus_connection);
G_OBJECT_CLASS (nm_pacrunner_manager_parent_class)->dispose (object);
}

View file

@ -31,22 +31,20 @@
typedef struct _NMPacrunnerManagerClass NMPacrunnerManagerClass;
typedef struct _NMPacrunnerCallId NMPacrunnerCallId;
typedef struct _NMPacrunnerConfId NMPacrunnerConfId;
GType nm_pacrunner_manager_get_type (void);
NMPacrunnerManager *nm_pacrunner_manager_get (void);
NMPacrunnerCallId *nm_pacrunner_manager_send (NMPacrunnerManager *self,
const char *iface,
NMProxyConfig *proxy_config,
NMIP4Config *ip4_config,
NMIP6Config *ip6_config);
NMPacrunnerConfId *nm_pacrunner_manager_add (NMPacrunnerManager *self,
NMProxyConfig *proxy_config,
const char *iface,
NMIP4Config *ip4_config,
NMIP6Config *ip6_config);
void nm_pacrunner_manager_remove (NMPacrunnerManager *self,
NMPacrunnerCallId *call_id);
void nm_pacrunner_manager_remove (NMPacrunnerConfId *conf_id);
gboolean nm_pacrunner_manager_remove_clear (NMPacrunnerManager *self,
NMPacrunnerCallId **p_call_id);
gboolean nm_pacrunner_manager_remove_clear (NMPacrunnerConfId **p_conf_id);
#endif /* __NETWORKMANAGER_PACRUNNER_MANAGER_H__ */

View file

@ -221,7 +221,8 @@ nm_platform_setup (NMPlatform *instance)
nm_singleton_instance_register ();
nm_log_dbg (LOGD_CORE, "setup %s singleton (%p, %s)", "NMPlatform", singleton_instance, G_OBJECT_TYPE_NAME (instance));
nm_log_dbg (LOGD_CORE, "setup %s singleton ("NM_HASH_OBFUSCATE_PTR_FMT")",
"NMPlatform", NM_HASH_OBFUSCATE_PTR (instance));
}
/**

View file

@ -46,17 +46,18 @@ int plugin_init (void);
char pppd_version[] = VERSION;
static GDBusProxy *proxy = NULL;
static struct {
GDBusConnection *dbus_connection;
char *ipparam;
} gl;
static void
nm_phasechange (void *data, int arg)
{
NMPPPStatus ppp_status = NM_PPP_STATUS_UNKNOWN;
char new_name[IF_NAMESIZE];
char *ppp_phase;
int index;
g_return_if_fail (G_IS_DBUS_PROXY (proxy));
g_return_if_fail (G_IS_DBUS_CONNECTION (gl.dbus_connection));
switch (arg) {
case PHASE_DEAD:
@ -117,33 +118,49 @@ nm_phasechange (void *data, int arg)
break;
}
g_message ("nm-ppp-plugin: (%s): status %d / phase '%s'",
__func__,
g_message ("nm-ppp-plugin: status %d / phase '%s'",
ppp_status,
ppp_phase);
if (ppp_status != NM_PPP_STATUS_UNKNOWN) {
g_dbus_proxy_call (proxy,
"SetState",
g_variant_new ("(u)", ppp_status),
G_DBUS_CALL_FLAGS_NONE, -1,
NULL,
NULL, NULL);
g_dbus_connection_call (gl.dbus_connection,
NM_DBUS_SERVICE,
gl.ipparam,
NM_DBUS_INTERFACE_PPP,
"SetState",
g_variant_new ("(u)", ppp_status),
G_VARIANT_TYPE ("()"),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
NULL,
NULL);
}
if (ppp_status == NM_PPP_STATUS_RUNNING) {
index = if_nametoindex (ifname);
gs_unref_variant GVariant *ret = NULL;
char new_name[IF_NAMESIZE];
int ifindex;
ifindex = if_nametoindex (ifname);
/* Make a sync call to ensure that when the call
* terminates the interface already has its final
* name. */
g_dbus_proxy_call_sync (proxy,
"SetIfindex",
g_variant_new ("(i)", index),
G_DBUS_CALL_FLAGS_NONE,
25000,
NULL, NULL);
ret = g_dbus_connection_call_sync (gl.dbus_connection,
NM_DBUS_SERVICE,
gl.ipparam,
NM_DBUS_INTERFACE_PPP,
"SetIfindex",
g_variant_new ("(i)", ifindex),
G_VARIANT_TYPE ("()"),
G_DBUS_CALL_FLAGS_NONE,
25000,
NULL,
NULL);
/* Update the name in pppd if NM changed it */
if ( if_indextoname (index, new_name)
if ( if_indextoname (ifindex, new_name)
&& !nm_streq0 (ifname, new_name)) {
g_message ("nm-ppp-plugin: interface name changed from '%s' to '%s'", ifname, new_name);
g_strlcpy (ifname, new_name, IF_NAMESIZE);
@ -159,12 +176,12 @@ nm_ip_up (void *data, int arg)
GVariantBuilder builder;
guint32 pppd_made_up_address = htonl (0x0a404040 + ifunit);
g_return_if_fail (G_IS_DBUS_PROXY (proxy));
g_return_if_fail (G_IS_DBUS_CONNECTION (gl.dbus_connection));
g_message ("nm-ppp-plugin: (%s): ip-up event", __func__);
g_message ("nm-ppp-plugin: ip-up event");
if (!opts.ouraddr) {
g_warning ("nm-ppp-plugin: (%s): didn't receive an internal IP from pppd!", __func__);
g_warning ("nm-ppp-plugin: didn't receive an internal IP from pppd!");
nm_phasechange (NULL, PHASE_DEAD);
return;
}
@ -235,14 +252,20 @@ nm_ip_up (void *data, int arg)
wins, len, sizeof (guint32)));
}
g_message ("nm-ppp-plugin: (%s): sending IPv4 config to NetworkManager...", __func__);
g_message ("nm-ppp-plugin: sending IPv4 config to NetworkManager...");
g_dbus_proxy_call (proxy,
"SetIp4Config",
g_variant_new ("(a{sv})", &builder),
G_DBUS_CALL_FLAGS_NONE, -1,
NULL,
NULL, NULL);
g_dbus_connection_call (gl.dbus_connection,
NM_DBUS_SERVICE,
gl.ipparam,
NM_DBUS_INTERFACE_PPP,
"SetIp4Config",
g_variant_new ("(a{sv})", &builder),
G_VARIANT_TYPE ("()"),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
NULL,
NULL);
}
static GVariant *
@ -263,9 +286,9 @@ nm_ip6_up (void *data, int arg)
ipv6cp_options *go = &ipv6cp_gotoptions[0];
GVariantBuilder builder;
g_return_if_fail (G_IS_DBUS_PROXY (proxy));
g_return_if_fail (G_IS_DBUS_CONNECTION (gl.dbus_connection));
g_message ("nm-ppp-plugin: (%s): ip6-up event", __func__);
g_message ("nm-ppp-plugin: ip6-up event");
g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
/* Keep sending the interface name to be backwards compatible
@ -283,14 +306,20 @@ nm_ip6_up (void *data, int arg)
/* DNS is done via DHCPv6 or router advertisements */
g_message ("nm-ppp-plugin: (%s): sending IPv6 config to NetworkManager...", __func__);
g_message ("nm-ppp-plugin: sending IPv6 config to NetworkManager...");
g_dbus_proxy_call (proxy,
"SetIp6Config",
g_variant_new ("(a{sv})", &builder),
G_DBUS_CALL_FLAGS_NONE, -1,
NULL,
NULL, NULL);
g_dbus_connection_call (gl.dbus_connection,
NM_DBUS_SERVICE,
gl.ipparam,
NM_DBUS_INTERFACE_PPP,
"SetIp6Config",
g_variant_new ("(a{sv})", &builder),
G_VARIANT_TYPE ("()"),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
NULL,
NULL);
}
static int
@ -308,10 +337,10 @@ get_pap_check (void)
static int
get_credentials (char *username, char *password)
{
const char *my_username = NULL;
const char *my_password = NULL;
GVariant *ret;
GError *err = NULL;
gs_unref_variant GVariant *ret = NULL;
gs_free_error GError *error = NULL;
const char *my_username;
const char *my_password;
if (!password) {
/* pppd is checking pap support; return 1 for supported */
@ -320,34 +349,33 @@ get_credentials (char *username, char *password)
}
g_return_val_if_fail (username, -1);
g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), -1);
g_return_val_if_fail (G_IS_DBUS_CONNECTION (gl.dbus_connection), -1);
g_message ("nm-ppp-plugin: (%s): passwd-hook, requesting credentials...", __func__);
g_message ("nm-ppp-plugin: passwd-hook, requesting credentials...");
ret = g_dbus_proxy_call_sync (proxy,
"NeedSecrets",
NULL,
G_DBUS_CALL_FLAGS_NONE, -1,
NULL, &err);
ret = g_dbus_connection_call_sync (gl.dbus_connection,
NM_DBUS_SERVICE,
gl.ipparam,
NM_DBUS_INTERFACE_PPP,
"NeedSecrets",
NULL,
G_VARIANT_TYPE ("(ss)"),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error);
if (!ret) {
g_warning ("nm-ppp-plugin: (%s): could not get secrets: %s",
__func__,
err->message);
g_error_free (err);
g_warning ("nm-ppp-plugin: could not get secrets: %s",
error->message);
return -1;
}
g_message ("nm-ppp-plugin: (%s): got credentials from NetworkManager", __func__);
g_message ("nm-ppp-plugin: got credentials from NetworkManager");
g_variant_get (ret, "(&s&s)", &my_username, &my_password);
if (my_username)
g_strlcpy (username, my_username, MAXNAMELEN);
if (my_password)
g_strlcpy (password, my_password, MAXSECRETLEN);
g_variant_unref (ret);
g_strlcpy (username, my_username, MAXNAMELEN);
g_strlcpy (password, my_password, MAXSECRETLEN);
return 1;
}
@ -355,12 +383,12 @@ get_credentials (char *username, char *password)
static void
nm_exit_notify (void *data, int arg)
{
g_return_if_fail (G_IS_DBUS_PROXY (proxy));
g_return_if_fail (G_IS_DBUS_CONNECTION (gl.dbus_connection));
g_message ("nm-ppp-plugin: (%s): cleaning up", __func__);
g_message ("nm-ppp-plugin: cleaning up");
g_object_unref (proxy);
proxy = NULL;
g_clear_object (&gl.dbus_connection);
nm_clear_g_free (&gl.ipparam);
}
static void
@ -387,37 +415,21 @@ add_ip6_notifier (void)
int
plugin_init (void)
{
GDBusConnection *bus;
GError *err = NULL;
gs_free_error GError *err = NULL;
g_message ("nm-ppp-plugin: (%s): initializing", __func__);
g_message ("nm-ppp-plugin: initializing");
bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &err);
if (!bus) {
g_warning ("nm-pppd-plugin: (%s): couldn't connect to system bus: %s",
__func__, err->message);
g_error_free (err);
nm_assert (!gl.dbus_connection);
nm_assert (!gl.ipparam);
gl.dbus_connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &err);
if (!gl.dbus_connection) {
g_warning ("nm-pppd-plugin: couldn't connect to system bus: %s",
err->message);
return -1;
}
/* NM passes in the object path of the corresponding PPPManager
* object as the 'ipparam' argument to pppd.
*/
proxy = g_dbus_proxy_new_sync (bus,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
NM_DBUS_SERVICE,
ipparam,
NM_DBUS_INTERFACE_PPP,
NULL, &err);
g_object_unref (bus);
if (!proxy) {
g_warning ("nm-pppd-plugin: (%s): couldn't create D-Bus proxy: %s",
__func__, err->message);
g_error_free (err);
return -1;
}
gl.ipparam = g_strdup (ipparam);
chap_passwd_hook = get_credentials;
chap_check_hook = get_chap_check;
@ -426,7 +438,7 @@ plugin_init (void)
add_notifier (&phasechange, nm_phasechange, NULL);
add_notifier (&ip_up_notifier, nm_ip_up, NULL);
add_notifier (&exitnotify, nm_exit_notify, proxy);
add_notifier (&exitnotify, nm_exit_notify, NULL);
add_ip6_notifier ();
return 0;

View file

@ -311,7 +311,6 @@ validate_identifier (const char *identifier, GError **error)
static void
agent_register_permissions_done (NMAuthChain *chain,
GError *error,
GDBusMethodInvocation *context,
gpointer user_data)
{
@ -319,47 +318,36 @@ agent_register_permissions_done (NMAuthChain *chain,
NMAgentManagerPrivate *priv = NM_AGENT_MANAGER_GET_PRIVATE (self);
NMSecretAgent *agent;
const char *sender;
GError *local = NULL;
NMAuthCallResult result;
CList *iter;
g_assert (context);
nm_assert (G_IS_DBUS_METHOD_INVOCATION (context));
priv->chains = g_slist_remove (priv->chains, chain);
if (error) {
local = g_error_new (NM_AGENT_MANAGER_ERROR,
NM_AGENT_MANAGER_ERROR_PERMISSION_DENIED,
"Failed to request agent permissions: %s",
error->message);
g_dbus_method_invocation_take_error (context, local);
} else {
agent = nm_auth_chain_steal_data (chain, "agent");
g_assert (agent);
agent = nm_auth_chain_steal_data (chain, "agent");
nm_assert (agent);
result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED);
if (result == NM_AUTH_CALL_RESULT_YES)
nm_secret_agent_add_permission (agent, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED, TRUE);
result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED);
if (result == NM_AUTH_CALL_RESULT_YES)
nm_secret_agent_add_permission (agent, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED, TRUE);
result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN);
if (result == NM_AUTH_CALL_RESULT_YES)
nm_secret_agent_add_permission (agent, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN, TRUE);
result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN);
if (result == NM_AUTH_CALL_RESULT_YES)
nm_secret_agent_add_permission (agent, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN, TRUE);
priv->agent_version_id += 1;
sender = nm_secret_agent_get_dbus_owner (agent);
g_hash_table_insert (priv->agents, g_strdup (sender), agent);
_LOGI (agent, "agent registered");
g_dbus_method_invocation_return_value (context, NULL);
priv->agent_version_id += 1;
sender = nm_secret_agent_get_dbus_owner (agent);
g_hash_table_insert (priv->agents, g_strdup (sender), agent);
_LOGI (agent, "agent registered");
g_dbus_method_invocation_return_value (context, NULL);
/* Signal an agent was registered */
g_signal_emit (self, signals[AGENT_REGISTERED], 0, agent);
/* Signal an agent was registered */
g_signal_emit (self, signals[AGENT_REGISTERED], 0, agent);
/* Add this agent to any in-progress secrets requests */
c_list_for_each (iter, &priv->requests)
request_add_agent (c_list_entry (iter, Request, lst_request), agent);
}
nm_auth_chain_destroy (chain);
/* Add this agent to any in-progress secrets requests */
c_list_for_each (iter, &priv->requests)
request_add_agent (c_list_entry (iter, Request, lst_request), agent);
}
static NMSecretAgent *
@ -537,8 +525,7 @@ request_free (Request *req)
case REQUEST_TYPE_CON_DEL:
g_object_unref (req->con.connection);
g_free (req->con.path);
if (req->con.chain)
nm_auth_chain_destroy (req->con.chain);
nm_clear_pointer (&req->con.chain, nm_auth_chain_destroy);
if (req->request_type == REQUEST_TYPE_CON_GET) {
g_free (req->con.get.setting_name);
g_strfreev (req->con.get.hints);
@ -815,11 +802,8 @@ request_remove_agent (Request *req, NMSecretAgent *agent)
case REQUEST_TYPE_CON_GET:
case REQUEST_TYPE_CON_SAVE:
case REQUEST_TYPE_CON_DEL:
if (req->con.chain) {
/* This cancels the pending authorization requests. */
nm_auth_chain_destroy (req->con.chain);
req->con.chain = NULL;
}
/* This cancels the pending authorization requests. */
nm_clear_pointer (&req->con.chain, nm_auth_chain_destroy);
break;
default:
g_assert_not_reached ();
@ -1017,7 +1001,6 @@ _con_get_request_start_proceed (Request *req, gboolean include_system_secrets)
static void
_con_get_request_start_validated (NMAuthChain *chain,
GError *error,
GDBusMethodInvocation *context,
gpointer user_data)
{
@ -1031,30 +1014,20 @@ _con_get_request_start_validated (NMAuthChain *chain,
req->con.chain = NULL;
if (error) {
_LOGD (req->current, "agent "LOG_REQ_FMT" MODIFY check error: %s",
LOG_REQ_ARG (req),
error->message);
/* Try the next agent */
request_next_agent (req);
} else {
/* If the agent obtained the 'modify' permission, we send all system secrets
* to it. If it didn't, we still ask it for secrets, but we don't send
* any system secrets.
*/
perm = nm_auth_chain_get_data (chain, "perm");
g_assert (perm);
if (nm_auth_chain_get_result (chain, perm) == NM_AUTH_CALL_RESULT_YES)
req->con.current_has_modify = TRUE;
/* If the agent obtained the 'modify' permission, we send all system secrets
* to it. If it didn't, we still ask it for secrets, but we don't send
* any system secrets.
*/
perm = nm_auth_chain_get_data (chain, "perm");
g_assert (perm);
if (nm_auth_chain_get_result (chain, perm) == NM_AUTH_CALL_RESULT_YES)
req->con.current_has_modify = TRUE;
_LOGD (req->current, "agent "LOG_REQ_FMT" MODIFY check result %s",
LOG_REQ_ARG (req),
req->con.current_has_modify ? "YES" : "NO");
_LOGD (req->current, "agent "LOG_REQ_FMT" MODIFY check result %s",
LOG_REQ_ARG (req),
req->con.current_has_modify ? "YES" : "NO");
_con_get_request_start_proceed (req, req->con.current_has_modify);
}
nm_auth_chain_destroy (chain);
_con_get_request_start_proceed (req, req->con.current_has_modify);
}
static void
@ -1100,7 +1073,7 @@ _con_get_request_start (Request *req)
perm = NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM;
nm_auth_chain_set_data (req->con.chain, "perm", (gpointer) perm, NULL);
nm_auth_chain_add_call (req->con.chain, perm, TRUE);
nm_auth_chain_add_call_unsafe (req->con.chain, perm, TRUE);
} else {
_LOGD (NULL, "("LOG_REQ_FMT") requesting user-owned secrets from agent %s",
LOG_REQ_ARG (req), agent_dbus_owner);
@ -1478,7 +1451,6 @@ nm_agent_manager_all_agents_have_capability (NMAgentManager *manager,
static void
agent_permissions_changed_done (NMAuthChain *chain,
GError *error,
GDBusMethodInvocation *context,
gpointer user_data)
{
@ -1492,21 +1464,15 @@ agent_permissions_changed_done (NMAuthChain *chain,
agent = nm_auth_chain_get_data (chain, "agent");
g_assert (agent);
if (error)
_LOGD (agent, "failed to request updated agent permissions");
else {
_LOGD (agent, "updated agent permissions");
_LOGD (agent, "updated agent permissions");
if (nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED) == NM_AUTH_CALL_RESULT_YES)
share_protected = TRUE;
if (nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN) == NM_AUTH_CALL_RESULT_YES)
share_open = TRUE;
}
if (nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED) == NM_AUTH_CALL_RESULT_YES)
share_protected = TRUE;
if (nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN) == NM_AUTH_CALL_RESULT_YES)
share_open = TRUE;
nm_secret_agent_add_permission (agent, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED, share_protected);
nm_secret_agent_add_permission (agent, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN, share_open);
nm_auth_chain_destroy (chain);
}
static void

View file

@ -25,6 +25,7 @@
#include <sys/types.h>
#include <pwd.h>
#include "nm-glib-aux/nm-dbus-aux.h"
#include "nm-dbus-interface.h"
#include "nm-dbus-manager.h"
#include "nm-core-internal.h"
@ -54,7 +55,10 @@ typedef struct {
NMDBusManager *bus_mgr;
GDBusConnection *connection;
CList requests;
gulong on_disconnected_id;
union {
gulong obj_signal;
guint dbus_signal;
} on_disconnected_id;
bool connection_is_private:1;
} NMSecretAgentPrivate;
@ -614,15 +618,12 @@ nm_secret_agent_delete_secrets (NMSecretAgent *self,
static void
_on_disconnected_cleanup (NMSecretAgentPrivate *priv)
{
if (priv->on_disconnected_id) {
if (priv->connection_is_private) {
g_signal_handler_disconnect (priv->bus_mgr,
priv->on_disconnected_id);
} else {
g_dbus_connection_signal_unsubscribe (priv->connection,
priv->on_disconnected_id);
}
priv->on_disconnected_id = 0;
if (priv->connection_is_private) {
nm_clear_g_signal_handler (priv->bus_mgr,
&priv->on_disconnected_id.obj_signal);
} else {
nm_clear_g_dbus_connection_signal (priv->connection,
&priv->on_disconnected_id.dbus_signal);
}
g_clear_object (&priv->connection);
@ -744,21 +745,16 @@ nm_secret_agent_new (GDBusMethodInvocation *context,
/* we cannot subscribe to notify::g-name-owner because that doesn't work
* for unique names and it doesn't work for private connections. */
if (priv->connection_is_private) {
priv->on_disconnected_id = g_signal_connect (priv->bus_mgr,
NM_DBUS_MANAGER_PRIVATE_CONNECTION_DISCONNECTED,
G_CALLBACK (_on_disconnected_private_connection),
self);
priv->on_disconnected_id.obj_signal = g_signal_connect (priv->bus_mgr,
NM_DBUS_MANAGER_PRIVATE_CONNECTION_DISCONNECTED,
G_CALLBACK (_on_disconnected_private_connection),
self);
} else {
priv->on_disconnected_id = g_dbus_connection_signal_subscribe (priv->connection,
"org.freedesktop.DBus", /* name */
"org.freedesktop.DBus", /* interface */
"NameOwnerChanged", /* signal name */
"/org/freedesktop/DBus", /* path */
priv->dbus_owner, /* arg0 */
G_DBUS_SIGNAL_FLAGS_NONE,
_on_disconnected_name_owner_changed,
self,
NULL);
priv->on_disconnected_id.dbus_signal = nm_dbus_connection_signal_subscribe_name_owner_changed (priv->connection,
priv->dbus_owner,
_on_disconnected_name_owner_changed,
self,
NULL);
}
return self;

View file

@ -1134,14 +1134,13 @@ send_agent_owned_secrets (NMSettings *self,
static void
pk_add_cb (NMAuthChain *chain,
GError *chain_error,
GDBusMethodInvocation *context,
gpointer user_data)
{
NMSettings *self = NM_SETTINGS (user_data);
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
NMAuthCallResult result;
GError *error = NULL;
gs_free_error GError *error = NULL;
NMConnection *connection = NULL;
gs_unref_object NMSettingsConnection *added = NULL;
NMSettingsAddCallback callback;
@ -1150,20 +1149,16 @@ pk_add_cb (NMAuthChain *chain,
const char *perm;
gboolean save_to_disk;
g_assert (context);
nm_assert (G_IS_DBUS_METHOD_INVOCATION (context));
priv->auths = g_slist_remove (priv->auths, chain);
perm = nm_auth_chain_get_data (chain, "perm");
g_assert (perm);
nm_assert (perm);
result = nm_auth_chain_get_result (chain, perm);
if (chain_error) {
error = g_error_new (NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_FAILED,
"Error checking authorization: %s",
chain_error->message);
} else if (result != NM_AUTH_CALL_RESULT_YES) {
if (result != NM_AUTH_CALL_RESULT_YES) {
error = g_error_new_literal (NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_PERMISSION_DENIED,
"Insufficient privileges.");
@ -1189,11 +1184,10 @@ pk_add_cb (NMAuthChain *chain,
callback (self, added, error, context, subject, callback_data);
/* Send agent-owned secrets to the agents */
if (!error && added && nm_settings_has_connection (self, added))
if ( !error
&& added
&& nm_settings_has_connection (self, added))
send_agent_owned_secrets (self, added, subject);
g_clear_error (&error);
nm_auth_chain_destroy (chain);
}
/* FIXME: remove if/when kernel supports adhoc wpa */
@ -1280,7 +1274,7 @@ nm_settings_add_connection_dbus (NMSettings *self,
* request affects more than just the caller, require 'modify.system'.
*/
s_con = nm_connection_get_setting_connection (connection);
g_assert (s_con);
nm_assert (s_con);
if (nm_setting_connection_get_num_permissions (s_con) == 1)
perm = NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN;
else
@ -1302,7 +1296,7 @@ nm_settings_add_connection_dbus (NMSettings *self,
nm_auth_chain_set_data (chain, "callback-data", user_data, NULL);
nm_auth_chain_set_data (chain, "subject", g_object_ref (subject), g_object_unref);
nm_auth_chain_set_data (chain, "save-to-disk", GUINT_TO_POINTER (save_to_disk), NULL);
nm_auth_chain_add_call (chain, perm, TRUE);
nm_auth_chain_add_call_unsafe (chain, perm, TRUE);
return;
done:
@ -1503,7 +1497,6 @@ impl_settings_reload_connections (NMDBusObject *obj,
static void
pk_hostname_cb (NMAuthChain *chain,
GError *chain_error,
GDBusMethodInvocation *context,
gpointer user_data)
{
@ -1513,19 +1506,14 @@ pk_hostname_cb (NMAuthChain *chain,
GError *error = NULL;
const char *hostname;
g_assert (context);
nm_assert (G_IS_DBUS_METHOD_INVOCATION (context));
priv->auths = g_slist_remove (priv->auths, chain);
result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME);
/* If our NMSettingsConnection is already gone, do nothing */
if (chain_error) {
error = g_error_new (NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_FAILED,
"Error checking authorization: %s",
chain_error->message);
} else if (result != NM_AUTH_CALL_RESULT_YES) {
if (result != NM_AUTH_CALL_RESULT_YES) {
error = g_error_new_literal (NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_PERMISSION_DENIED,
"Insufficient privileges.");
@ -1543,8 +1531,6 @@ pk_hostname_cb (NMAuthChain *chain,
g_dbus_method_invocation_take_error (context, error);
else
g_dbus_method_invocation_return_value (context, NULL);
nm_auth_chain_destroy (chain);
}
static void

View file

@ -124,8 +124,7 @@ typedef struct {
GVariant *connect_hash;
guint connect_timeout;
NMProxyConfig *proxy_config;
NMPacrunnerManager *pacrunner_manager;
NMPacrunnerCallId *pacrunner_call_id;
NMPacrunnerConfId *pacrunner_conf_id;
gboolean has_ip4;
NMIP4Config *ip4_config;
guint32 ip4_internal_gw;
@ -552,18 +551,12 @@ _set_vpn_state (NMVpnConnection *self,
NULL);
if (priv->proxy_config) {
nm_pacrunner_manager_remove_clear (priv->pacrunner_manager,
&priv->pacrunner_call_id);
if (!priv->pacrunner_manager) {
/* the pending call doesn't keep NMPacrunnerManager alive.
* Take a reference to it. */
priv->pacrunner_manager = g_object_ref (nm_pacrunner_manager_get ());
}
priv->pacrunner_call_id = nm_pacrunner_manager_send (priv->pacrunner_manager,
priv->ip_iface,
priv->proxy_config,
priv->ip4_config,
priv->ip6_config);
nm_pacrunner_manager_remove_clear (&priv->pacrunner_conf_id);
priv->pacrunner_conf_id = nm_pacrunner_manager_add (nm_pacrunner_manager_get (),
priv->proxy_config,
priv->ip_iface,
priv->ip4_config,
priv->ip6_config);
}
break;
case STATE_DEACTIVATING:
@ -594,8 +587,7 @@ _set_vpn_state (NMVpnConnection *self,
}
}
nm_pacrunner_manager_remove_clear (priv->pacrunner_manager,
&priv->pacrunner_call_id);
nm_pacrunner_manager_remove_clear (&priv->pacrunner_conf_id);
break;
case STATE_FAILED:
case STATE_DISCONNECTED:
@ -2801,9 +2793,7 @@ dispose (GObject *object)
fw_call_cleanup (self);
nm_pacrunner_manager_remove_clear (priv->pacrunner_manager,
&priv->pacrunner_call_id);
g_clear_object (&priv->pacrunner_manager);
nm_pacrunner_manager_remove_clear (&priv->pacrunner_conf_id);
G_OBJECT_CLASS (nm_vpn_connection_parent_class)->dispose (object);
}