about summary refs log tree commit diff
path: root/src/nm-auth-manager.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2019-07-31 10:51:42 +0200
committerMichael Biebl <biebl@debian.org>2019-07-31 10:51:42 +0200
commit2e5fa45ddfbb5cffa1e78221f1cea706e2f298af (patch)
tree86f69d36c56de3074280456eddc854a780b8e04b /src/nm-auth-manager.c
parent85563b7fc7ec2cd21e38debb9b28db342e2e8e7c (diff)
New upstream version 1.19.90 upstream/1.19.90
Diffstat (limited to 'src/nm-auth-manager.c')
-rw-r--r--src/nm-auth-manager.c312
1 files changed, 113 insertions, 199 deletions
diff --git a/src/nm-auth-manager.c b/src/nm-auth-manager.c
index 09a217ea..0663e207 100644
--- a/src/nm-auth-manager.c
+++ b/src/nm-auth-manager.c
@@ -1,4 +1,3 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 /* NetworkManager -- Network link manager
  *
  * This program is free software; you can redistribute it and/or modify
@@ -23,8 +22,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 +50,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 +114,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 +132,6 @@ typedef enum {
 struct _NMAuthManagerCallId {
 	CList calls_lst;
 	NMAuthManager *self;
-	GVariant *dbus_parameters;
 	GCancellable *dbus_cancellable;
 	NMAuthManagerCheckAuthorizationCallback callback;
 	gpointer user_data;
@@ -141,7 +141,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 +150,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 +180,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 +188,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 +222,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 +242,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 +272,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 +322,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 +340,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 +361,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 +374,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 +430,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)
-{
-	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)
+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;
 
-	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 +485,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 +498,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 +521,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 +574,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 +592,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