summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2014-08-14 13:34:57 +0200
committerThomas Haller <thaller@redhat.com>2014-09-29 13:51:11 +0200
commiteabe7d856c243673bbaba3295ce74d72e188596d (patch)
tree3c85e2d33dace5f644d8e605fd47f02d3367372c
parent63a8c6a184a58176b656d9e22f99a280682e0e5f (diff)
auth: rework polkit autorization to use DBUS interface directly
This makes NetworkManager independent of <polkit/polkit.h> development headers and libpolkit-gobject-1.so library. Instead communicate directly with polkit using its DBUS interface. PolicyKit support is now always compiled in. You can control polkit authorization with the configuration option [main] auth-polkit=yes|no If the configure option is omitted, a build time default value is used. This default value can be set with the configure option --enable-polkit. This commit adds a new class NMAuthManager that reimplements the relevant DBUS client parts. It takes source code from the polkit library. https://bugzilla.gnome.org/show_bug.cgi?id=734146 Signed-off-by: Thomas Haller <thaller@redhat.com>
-rw-r--r--configure.ac34
-rw-r--r--contrib/fedora/rpm/NetworkManager.spec1
-rw-r--r--man/NetworkManager.conf.xml.in8
-rw-r--r--src/Makefile.am4
-rw-r--r--src/main.c3
-rw-r--r--src/nm-active-connection.c2
-rw-r--r--src/nm-auth-manager.c643
-rw-r--r--src/nm-auth-manager.h82
-rw-r--r--src/nm-auth-subject.c468
-rw-r--r--src/nm-auth-subject.h45
-rw-r--r--src/nm-auth-utils.c318
-rw-r--r--src/nm-auth-utils.h23
-rw-r--r--src/nm-config.c21
-rw-r--r--src/nm-config.h1
-rw-r--r--src/nm-manager.c61
-rw-r--r--src/settings/nm-agent-manager.c36
-rw-r--r--src/settings/nm-secret-agent.c17
-rw-r--r--src/settings/nm-settings-connection.c18
-rw-r--r--src/settings/nm-settings.c20
19 files changed, 1326 insertions, 479 deletions
diff --git a/configure.ac b/configure.ac
index 1a1cc28412..93fc135265 100644
--- a/configure.ac
+++ b/configure.ac
@@ -457,27 +457,21 @@ else
fi
AM_CONDITIONAL(WITH_TEAMDCTL, test "${enable_teamdctl}" = "yes")
-PKG_CHECK_MODULES(POLKIT, [polkit-gobject-1 >= 0.97], [have_polkit=yes],[have_polkit=no])
-AC_ARG_ENABLE(polkit, AS_HELP_STRING([--enable-polkit], [enable PolicyKit support]),
- [enable_polkit=${enableval}], [enable_polkit=${have_polkit}])
-if (test "${enable_polkit}" = "yes"); then
- if test x"$have_polkit" = x"no"; then
- AC_MSG_ERROR(PolicyKit development headers are required)
- fi
- AC_SUBST(POLKIT_CFLAGS)
- AC_SUBST(POLKIT_LIBS)
- AC_DEFINE(WITH_POLKIT, 1, [Define if you have PolicyKit support])
+AC_ARG_ENABLE(polkit, AS_HELP_STRING([--enable-polkit], [set default value for auth-polkit configuration option]),
+ [enable_polkit=${enableval}], [enable_polkit=yes])
+if (test "${enable_polkit}" != "no"); then
+ enable_polkit=yes
+ AC_DEFINE(NM_CONFIG_DEFAULT_AUTH_POLKIT, TRUE, [The default value of the auth-polkit configuration option])
+ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT='true'
else
- AC_DEFINE(WITH_POLKIT, 0, [Define if you have PolicyKit support])
+ AC_DEFINE(NM_CONFIG_DEFAULT_AUTH_POLKIT, FALSE, [The default value of the auth-polkit configuration option])
+ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT='false'
fi
-AM_CONDITIONAL(WITH_POLKIT, test "${enable_polkit}" = "yes")
+AC_SUBST(NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT)
AC_ARG_ENABLE(modify-system,
AS_HELP_STRING([--enable-modify-system], [Allow users to modify system connections]))
if test "${enable_modify_system}" = "yes"; then
- if ! test "${enable_polkit}" = "yes"; then
- AC_MSG_ERROR([--enable-modify-system requires --enable-polkit])
- fi
NM_MODIFY_SYSTEM_POLICY="yes"
else
NM_MODIFY_SYSTEM_POLICY="auth_admin_keep"
@@ -967,14 +961,10 @@ echo
echo "Platform:"
echo " session tracking: $with_session_tracking"
echo " suspend/resume: $with_suspend_resume"
-if test "${enable_polkit}" = "yes"; then
- if test "${enable_modify_system}" = "yes"; then
- echo " policykit: yes (permissive modify.system)"
- else
- echo " policykit: yes (restrictive modify.system)"
- fi
+if test "${enable_modify_system}" = "yes"; then
+ echo " policykit: yes (permissive modify.system) (default=${enable_polkit})"
else
- echo " policykit: no"
+ echo " policykit: yes (restrictive modify.system) (default=${enable_polkit})"
fi
echo " selinux: $have_selinux"
echo
diff --git a/contrib/fedora/rpm/NetworkManager.spec b/contrib/fedora/rpm/NetworkManager.spec
index def31b3602..8d3bc63bfb 100644
--- a/contrib/fedora/rpm/NetworkManager.spec
+++ b/contrib/fedora/rpm/NetworkManager.spec
@@ -139,7 +139,6 @@ BuildRequires: automake autoconf intltool libtool
BuildRequires: ppp = %{ppp_version}
BuildRequires: ppp-devel = %{ppp_version}
BuildRequires: nss-devel >= 3.11.7
-BuildRequires: polkit-devel
BuildRequires: dhclient
BuildRequires: readline-devel
%if %{regen_docs}
diff --git a/man/NetworkManager.conf.xml.in b/man/NetworkManager.conf.xml.in
index c017822e3f..06aa403a8b 100644
--- a/man/NetworkManager.conf.xml.in
+++ b/man/NetworkManager.conf.xml.in
@@ -123,6 +123,14 @@ Copyright (C) 2010 - 2013 Red Hat, Inc.
connection files any time they changed.</para></listitem>
</varlistentry>
<varlistentry>
+ <term><varname>auth-polkit</varname></term>
+ <listitem><para>Whether the system uses PolicyKit for authorization.
+ If <literal>false</literal>, all requests will be allowed. If
+ <literal>true</literal>, non-root requests are authorized using PolicyKit.
+ The default value is <literal>@NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@</literal>.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
<term><varname>dhcp</varname></term>
<listitem><para>This key sets up what DHCP client
NetworkManager will use. Presently
diff --git a/src/Makefile.am b/src/Makefile.am
index c72c85fefc..95df89be74 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -230,6 +230,8 @@ nm_sources = \
nm-ip6-config.h \
nm-logging.c \
nm-logging.h \
+ nm-auth-manager.c \
+ nm-auth-manager.h \
nm-auth-subject.c \
nm-auth-subject.h \
nm-auth-utils.c \
@@ -328,7 +330,6 @@ AM_CPPFLAGS += \
$(LIBNL_CFLAGS) \
$(LIBNDP_CFLAGS) \
$(LIBSOUP_CFLAGS) \
- $(POLKIT_CFLAGS) \
$(SYSTEMD_LOGIN_CFLAGS) \
\
-DBINDIR=\"$(bindir)\" \
@@ -365,7 +366,6 @@ libNetworkManager_la_LIBADD = \
$(GLIB_LIBS) \
$(GUDEV_LIBS) \
$(LIBNL_LIBS) \
- $(POLKIT_LIBS) \
$(SYSTEMD_LOGIN_LIBS) \
$(LIBNDP_LIBS) \
$(LIBDL) \
diff --git a/src/main.c b/src/main.c
index d41472d4ff..17769587a9 100644
--- a/src/main.c
+++ b/src/main.c
@@ -56,6 +56,7 @@
#include "nm-session-monitor.h"
#include "nm-dispatcher.h"
#include "nm-settings.h"
+#include "nm-auth-manager.h"
#if !defined(NM_DIST_VERSION)
# define NM_DIST_VERSION VERSION
@@ -592,6 +593,8 @@ main (int argc, char *argv[])
/* Set up platform interaction layer */
nm_linux_platform_setup ();
+ nm_auth_manager_setup (nm_config_get_auth_polkit (config));
+
/* Initialize our DBus service & connection */
dbus_mgr = nm_dbus_manager_get ();
g_assert (dbus_mgr != NULL);
diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c
index 888bbd1797..3e532e5225 100644
--- a/src/nm-active-connection.c
+++ b/src/nm-active-connection.c
@@ -319,7 +319,7 @@ nm_active_connection_get_user_requested (NMActiveConnection *self)
{
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), FALSE);
- return !nm_auth_subject_get_internal (NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->subject);
+ return nm_auth_subject_is_unix_process (NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->subject);
}
NMDevice *
diff --git a/src/nm-auth-manager.c b/src/nm-auth-manager.c
new file mode 100644
index 0000000000..092248fa5f
--- /dev/null
+++ b/src/nm-auth-manager.c
@@ -0,0 +1,643 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2014 Red Hat, Inc.
+ */
+
+#include "nm-auth-manager.h"
+
+#include "nm-logging.h"
+
+
+#define POLKIT_SERVICE "org.freedesktop.PolicyKit1"
+#define POLKIT_OBJECT_PATH "/org/freedesktop/PolicyKit1/Authority"
+#define POLKIT_INTERFACE "org.freedesktop.PolicyKit1.Authority"
+
+
+#define _LOG_DEFAULT_DOMAIN LOGD_CORE
+
+#define _LOG(level, domain, ...) \
+ G_STMT_START { \
+ if (nm_logging_enabled ((level), (domain))) { \
+ char __prefix[30] = "auth"; \
+ \
+ if ((self) != _instance) \
+ g_snprintf (__prefix, sizeof (__prefix), "auth[%p]", (self)); \
+ nm_log ((level), (domain), \
+ "%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
+ __prefix _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
+ } \
+ } G_STMT_END
+
+#define _LOGD(...) _LOG (LOGL_DEBUG, _LOG_DEFAULT_DOMAIN, __VA_ARGS__)
+#define _LOGI(...) _LOG (LOGL_INFO, _LOG_DEFAULT_DOMAIN, __VA_ARGS__)
+#define _LOGW(...) _LOG (LOGL_WARN, _LOG_DEFAULT_DOMAIN, __VA_ARGS__)
+#define _LOGE(...) _LOG (LOGL_ERR, _LOG_DEFAULT_DOMAIN, __VA_ARGS__)
+
+
+enum {
+ PROP_0,
+ PROP_POLKIT_ENABLED,
+
+ LAST_PROP
+};
+
+enum {
+ CHANGED_SIGNAL,
+
+ LAST_SIGNAL,
+};
+
+static guint signals[LAST_SIGNAL] = {0};
+
+typedef struct {
+ gboolean polkit_enabled;
+ guint call_id_counter;
+ GCancellable *new_proxy_cancellable;
+ GSList *queued_calls;
+ GDBusProxy *proxy;
+} NMAuthManagerPrivate;
+
+static NMAuthManager *_instance = NULL;
+
+G_DEFINE_TYPE (NMAuthManager, nm_auth_manager, G_TYPE_OBJECT)
+
+#define NM_AUTH_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_AUTH_MANAGER, NMAuthManagerPrivate))
+
+GQuark
+nm_auth_manager_error_quark (void)
+{
+ static GQuark quark = 0;
+
+ if (G_UNLIKELY (quark == 0))
+ quark = g_quark_from_static_string ("nm-auth-manager-error-quark");
+ return quark;
+}
+
+/*****************************************************************************/
+
+gboolean
+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;
+}
+
+/*****************************************************************************/
+
+typedef enum {
+ POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE = 0,
+ POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION = (1<<0),
+} PolkitCheckAuthorizationFlags;
+
+typedef struct {
+ guint call_id;
+ NMAuthManager *self;
+ GSimpleAsyncResult *simple;
+ gchar *cancellation_id;
+ GVariant *dbus_parameters;
+ GCancellable *cancellable;
+} CheckAuthData;
+
+static void
+_check_auth_data_free (CheckAuthData *data)
+{
+ if (data->dbus_parameters)
+ g_variant_unref (data->dbus_parameters);
+ g_object_unref (data->self);
+ g_object_unref (data->simple);
+ g_clear_object (&data->cancellable);
+ g_free (data->cancellation_id);
+ g_free (data);
+}
+
+static void
+_call_check_authorization_complete_with_error (CheckAuthData *data,
+ const char *error_message)
+{
+ NMAuthManager *self = data->self;
+ GError *error = NULL;
+
+ _LOGD ("call[%u]: CheckAuthorization failed due to internal error: %s", data->call_id, error_message);
+ g_set_error_literal (&error, NM_AUTH_MANAGER_ERROR, NM_AUTH_MANAGER_ERROR_DBUS_FAILURE, error_message);
+ g_simple_async_result_set_from_error (data->simple, error);
+ g_clear_error (&error);
+
+ g_simple_async_result_complete_in_idle (data->simple);
+
+ _check_auth_data_free (data);
+}
+
+static void
+cancel_check_authorization_cb (GDBusProxy *proxy,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ NMAuthManager *self = user_data;
+ GVariant *value;
+ GError *error= NULL;
+
+ value = g_dbus_proxy_call_finish (proxy, res, &error);
+ if (value == NULL) {
+ _LOGD ("Error cancelling authorization check: %s", error->message);
+ g_error_free (error);
+ } else
+ g_variant_unref (value);
+
+ g_object_unref (self);
+}
+
+typedef struct {
+ gboolean is_authorized;
+ gboolean is_challenge;
+} CheckAuthorizationResult;
+
+static void
+check_authorization_cb (GDBusProxy *proxy,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CheckAuthData *data = user_data;
+ NMAuthManager *self = data->self;
+ NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
+ GVariant *value;
+ GError *error = NULL;
+
+ value = g_dbus_proxy_call_finish (proxy, res, &error);
+ if (value == NULL) {
+ if (data->cancellation_id != NULL &&
+ (!g_dbus_error_is_remote_error (error) &&
+ error->domain == G_IO_ERROR &&
+ error->code == G_IO_ERROR_CANCELLED)) {
+ _LOGD ("call[%u]: CheckAuthorization cancelled", data->call_id);
+ g_dbus_proxy_call (priv->proxy,
+ "CancelCheckAuthorization",
+ g_variant_new ("(s)", data->cancellation_id),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL, /* GCancellable */
+ (GAsyncReadyCallback) cancel_check_authorization_cb,
+ g_object_ref (self));
+ } else
+ _LOGD ("call[%u]: CheckAuthorization failed: %s", data->call_id, error->message);
+ g_simple_async_result_set_from_error (data->simple, error);
+ g_error_free (error);
+ } else {
+ GVariant *result_value;
+ CheckAuthorizationResult *result;
+
+ result = g_new0 (CheckAuthorizationResult, 1);
+
+ result_value = g_variant_get_child_value (value, 0);
+ g_variant_get (result_value,
+ "(bb@a{ss})",
+ &result->is_authorized,
+ &result->is_challenge,
+ NULL);
+ g_variant_unref (result_value);
+ g_variant_unref (value);
+
+ _LOGD ("call[%u]: CheckAuthorization succeeded: (is_authorized=%d, is_challenge=%d)", data->call_id, result->is_authorized, result->is_challenge);
+ g_simple_async_result_set_op_res_gpointer (data->simple, result, g_free);
+ }
+
+ g_simple_async_result_complete (data->simple);
+
+ _check_auth_data_free (data);
+}
+
+static void
+_call_check_authorization (CheckAuthData *data)
+{
+ NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (data->self);
+
+ g_dbus_proxy_call (priv->proxy,
+ "CheckAuthorization",
+ data->dbus_parameters,
+ G_DBUS_CALL_FLAGS_NONE,
+ G_MAXINT, /* no timeout */
+ data->cancellable,
+ (GAsyncReadyCallback) check_authorization_cb,
+ data);
+ g_clear_object (&data->cancellable);
+ data->dbus_parameters = NULL;
+}
+
+void
+nm_auth_manager_polkit_authority_check_authorization (NMAuthManager *self,
+ NMAuthSubject *subject,
+ const char *action_id,
+ gboolean allow_user_interaction,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ NMAuthManagerPrivate *priv;
+ char subject_buf[64];
+ GVariantBuilder builder;
+ PolkitCheckAuthorizationFlags flags;
+ GVariant *subject_value;
+ GVariant *details_value;
+ CheckAuthData *data;
+
+ g_return_if_fail (NM_IS_AUTH_MANAGER (self));
+ g_return_if_fail (NM_IS_AUTH_SUBJECT (subject));
+ g_return_if_fail (nm_auth_subject_is_unix_process (subject));
+ g_return_if_fail (action_id != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+ priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
+
+ g_return_if_fail (priv->polkit_enabled);
+
+ flags = allow_user_interaction
+ ? POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION
+ : POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE;
+
+ subject_value = nm_auth_subject_unix_process_to_polkit_gvariant (subject);
+ g_assert (g_variant_is_floating (subject_value));
+
+ /* ((PolkitDetails *)NULL) */
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}"));
+ details_value = g_variant_builder_end (&builder);
+
+ data = g_new0 (CheckAuthData, 1);
+ data->call_id = ++priv->call_id_counter;
+ data->self = g_object_ref (self);
+ data->simple = g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ nm_auth_manager_polkit_authority_check_authorization);
+ if (cancellable != NULL) {
+ data->cancellation_id = g_strdup_printf ("cancellation-id-%u", data->call_id);
+ data->cancellable = g_object_ref (cancellable);
+ }
+
+ data->dbus_parameters = g_variant_new ("(@(sa{sv})s@a{ss}us)",
+ subject_value,
+ action_id,
+ details_value,
+ (guint32) flags,
+ data->cancellation_id != NULL ? data->cancellation_id : "");
+
+ if (priv->new_proxy_cancellable) {
+ _LOGD ("call[%u]: CheckAuthorization(%s), subject=%s (wait for proxy)", data->call_id, action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf)));
+
+ priv->queued_calls = g_slist_prepend (priv->queued_calls, data);
+ } else if (!priv->proxy) {
+ _LOGD ("call[%u]: CheckAuthorization(%s), subject=%s (fails due to invalid DBUS proxy)", data->call_id, action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf)));
+
+ _call_check_authorization_complete_with_error (data, "invalid DBUS proxy");
+ } else {
+ _LOGD ("call[%u]: CheckAuthorization(%s), subject=%s", data->call_id, action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf)));
+
+ _call_check_authorization (data);
+ }
+}
+
+gboolean
+nm_auth_manager_polkit_authority_check_authorization_finish (NMAuthManager *self,
+ GAsyncResult *res,
+ gboolean *out_is_authorized,
+ gboolean *out_is_challenge,
+ GError **error)
+{
+ gboolean success = FALSE;
+ gboolean is_authorized = FALSE;
+ gboolean is_challenge = FALSE;
+
+ g_return_val_if_fail (NM_IS_AUTH_MANAGER (self), FALSE);
+ g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (res), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ if (!g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) {
+ CheckAuthorizationResult *result;
+
+ result = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res));
+ is_authorized = !!result->is_authorized;
+ is_challenge = !!result->is_challenge;
+ success = TRUE;
+ }
+ g_assert ((success && !error) || (!success || error));
+
+ if (out_is_authorized)
+ *out_is_authorized = is_authorized;
+ if (out_is_challenge)
+ *out_is_challenge = is_challenge;
+ return success;
+}
+
+/*****************************************************************************/
+
+static void
+_emit_changed_signal (NMAuthManager *self)
+{
+ _LOGD ("emit changed signal");
+ g_signal_emit_by_name (self, NM_AUTH_MANAGER_SIGNAL_CHANGED);
+}
+
+static void
+_log_name_owner (NMAuthManager *self, char **out_name_owner)
+{
+ NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
+ char *name_owner;
+
+ 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");
+
+ if (out_name_owner)
+ *out_name_owner = name_owner;
+ else
+ g_free (name_owner);
+}
+
+static void
+_dbus_on_name_owner_notify_cb (GObject *object,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ NMAuthManager *self = user_data;
+ NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
+ char *name_owner;
+
+ g_return_if_fail (priv->proxy == (void *) 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);
+ }
+
+ g_free (name_owner);
+}
+
+static void
+_dbus_on_g_signal_cb (GDBusProxy *proxy,
+ const gchar *sender_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ NMAuthManager *self = user_data;
+ NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
+
+ g_return_if_fail (priv->proxy == proxy);
+
+ _LOGD ("dbus signal: \"%s\"", signal_name ? signal_name : "(null)");
+
+ if (g_strcmp0 (signal_name, "Changed") == 0)
+ _emit_changed_signal (self);
+}
+
+static void
+_dbus_new_proxy_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ NMAuthManager **p_self = user_data;
+ NMAuthManager *self = NULL;
+ NMAuthManagerPrivate *priv;
+ GError *error = NULL;
+ GDBusProxy *proxy;
+ CheckAuthData *data;
+
+ proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
+
+ if (!*p_self) {
+ _LOGD ("_dbus_new_proxy_cb(): manager destroyed before callback finished. Abort");
+ g_clear_object (&proxy);
+ g_clear_error (&error);
+ g_free (p_self);
+ return;
+ }
+ self = *p_self;
+ g_object_remove_weak_pointer (G_OBJECT (self), (void **)p_self);
+ g_free (p_self);
+
+ priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
+
+ g_return_if_fail (priv->new_proxy_cancellable);
+ g_return_if_fail (!priv->proxy);
+
+ g_clear_object (&priv->new_proxy_cancellable);
+
+ priv->queued_calls = g_slist_reverse (priv->queued_calls);
+
+ priv->proxy = proxy;
+ if (!priv->proxy) {
+ _LOGE ("could not get polkit proxy: %s", error->message);
+ g_clear_error (&error);
+
+ while (priv->queued_calls) {
+ data = priv->queued_calls->data;
+ priv->queued_calls = g_slist_remove (priv->queued_calls, data);
+
+ _call_check_authorization_complete_with_error (data, "error creating DBUS proxy");
+ }
+ return;
+ }
+
+ g_signal_connect (priv->proxy,
+ "notify::g-name-owner",
+ G_CALLBACK (_dbus_on_name_owner_notify_cb),
+ self);
+ g_signal_connect (priv->proxy,
+ "g-signal",
+ G_CALLBACK (_dbus_on_g_signal_cb),
+ self);
+
+ _log_name_owner (self, NULL);
+
+ while (priv->queued_calls) {
+ data = priv->queued_calls->data;
+ priv->queued_calls = g_slist_remove (priv->queued_calls, data);
+ _LOGD ("call[%u]: CheckAuthorization invoke now", data->call_id);
+ _call_check_authorization (data);
+ }
+ _emit_changed_signal (self);
+}
+
+/*****************************************************************************/
+
+NMAuthManager *
+nm_auth_manager_get ()
+{
+ g_return_val_if_fail (_instance, NULL);
+
+ return _instance;
+}
+
+NMAuthManager *
+nm_auth_manager_setup (gboolean polkit_enabled)
+{
+ NMAuthManager *self;
+
+ g_return_val_if_fail (!_instance, _instance);
+
+ self = g_object_new (NM_TYPE_AUTH_MANAGER,
+ NM_AUTH_MANAGER_POLKIT_ENABLED, polkit_enabled,
+ NULL);
+ _LOGD ("set instance");
+
+ return (_instance = self);
+}
+
+/*****************************************************************************/
+
+static void
+get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_POLKIT_ENABLED:
+ g_value_set_boolean (value, priv->polkit_enabled);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+ NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_POLKIT_ENABLED:
+ /* construct only */
+ priv->polkit_enabled = !!g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nm_auth_manager_init (NMAuthManager *self)
+{
+}
+
+static void
+constructed (GObject *object)
+{
+ NMAuthManager *self = NM_AUTH_MANAGER (object);
+ NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
+
+ 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) {
+ NMAuthManager **p_self;
+
+ priv->new_proxy_cancellable = g_cancellable_new ();
+ p_self = g_new (NMAuthManager *, 1);
+ *p_self = self;
+ g_object_add_weak_pointer (G_OBJECT (self), (void **) p_self);
+ 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,
+ p_self);
+ }
+}
+
+
+static void
+dispose (GObject *object)
+{
+ NMAuthManager* self = NM_AUTH_MANAGER (object);
+ NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
+
+ _LOGD ("dispose");
+
+ /* since we take a reference for each queued call, we don't expect to have any queued calls in dispose() */
+ g_assert (!priv->queued_calls);
+
+ if (priv->new_proxy_cancellable) {
+ g_cancellable_cancel (priv->new_proxy_cancellable);
+ g_clear_object (&priv->new_proxy_cancellable);
+ }
+
+ if (priv->proxy) {
+ g_signal_handlers_disconnect_by_func (priv->proxy, _dbus_on_name_owner_notify_cb, self);
+ g_signal_handlers_disconnect_by_func (priv->proxy, _dbus_on_g_signal_cb, self);
+ g_clear_object (&priv->proxy);
+ }
+
+ G_OBJECT_CLASS (nm_auth_manager_parent_class)->dispose (object);
+}
+
+static void
+finalize (GObject *object)
+{
+ NMAuthManager* self = NM_AUTH_MANAGER (object);
+
+ G_OBJECT_CLASS (nm_auth_manager_parent_class)->finalize (object);
+
+ if (self == _instance) {
+ _instance = NULL;
+ _LOGD ("unset instance");
+ }
+}
+
+static void
+nm_auth_manager_class_init (NMAuthManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (NMAuthManagerPrivate));
+
+ object_class->get_property = get_property;
+ object_class->set_property = set_property;
+ object_class->constructed = constructed;
+ object_class->dispose = dispose;
+ object_class->finalize = finalize;
+
+ g_object_class_install_property
+ (object_class, PROP_POLKIT_ENABLED,
+ g_param_spec_boolean (NM_AUTH_MANAGER_POLKIT_ENABLED, "", "",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ signals[CHANGED_SIGNAL] = g_signal_new (NM_AUTH_MANAGER_SIGNAL_CHANGED,
+ NM_TYPE_AUTH_MANAGER,
+ G_SIGNAL_RUN_LAST,
+ 0, /* class offset */
+ NULL, /* accumulator */
+ NULL, /* accumulator data */
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+}
+
diff --git a/src/nm-auth-manager.h b/src/nm-auth-manager.h
new file mode 100644
index 0000000000..3f5ebc6589
--- /dev/null
+++ b/src/nm-auth-manager.h
@@ -0,0 +1,82 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2014 Red Hat, Inc.
+ */
+
+#ifndef NM_AUTH_MANAGER_H
+#define NM_AUTH_MANAGER_H
+
+#include <gio/gio.h>
+
+#include "nm-auth-subject.h"
+
+G_BEGIN_DECLS
+
+
+#define NM_TYPE_AUTH_MANAGER (nm_auth_manager_get_type ())
+#define NM_AUTH_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_AUTH_MANAGER, NMAuthManager))
+#define NM_AUTH_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_AUTH_MANAGER, NMAuthManagerClass))
+#define NM_IS_AUTH_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_AUTH_MANAGER))
+#define NM_IS_AUTH_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_AUTH_MANAGER))
+#define NM_AUTH_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_AUTH_MANAGER, NMAuthManagerClass))
+
+
+#define NM_AUTH_MANAGER_POLKIT_ENABLED "polkit-enabled"
+
+#define NM_AUTH_MANAGER_SIGNAL_CHANGED "changed"
+
+#define NM_AUTH_MANAGER_ERROR (nm_auth_manager_error_quark ())
+
+typedef enum {
+ NM_AUTH_MANAGER_ERROR_DBUS_FAILURE = 1,
+} NMAuthManagerError;
+
+typedef struct {
+ GObject parent;
+} NMAuthManager;
+
+typedef struct {
+ GObjectClass parent;
+} NMAuthManagerClass;
+
+GType nm_auth_manager_get_type (void);
+GQuark nm_auth_manager_error_quark (void);
+
+NMAuthManager *nm_auth_manager_setup (gboolean polkit_enabled);
+NMAuthManager *nm_auth_manager_get (void);
+
+gboolean nm_auth_manager_get_polkit_enabled (NMAuthManager *self);
+
+void nm_auth_manager_polkit_authority_check_authorization (NMAuthManager *self,
+ NMAuthSubject *subject,
+ const char *action_id,
+ gboolean allow_user_interaction,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean nm_auth_manager_polkit_authority_check_authorization_finish (NMAuthManager *self,
+ GAsyncResult *res,
+ gboolean *out_is_authorized,
+ gboolean *out_is_challenge,
+ GError **error);
+
+
+G_END_DECLS
+
+#endif /* NM_AUTH_MANAGER_H */
+
diff --git a/src/nm-auth-subject.c b/src/nm-auth-subject.c
index e770af49ec..f982616677 100644
--- a/src/nm-auth-subject.c
+++ b/src/nm-auth-subject.c
@@ -15,7 +15,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
- * Copyright (C) 2013 Red Hat, Inc.
+ * Copyright (C) 2013 - 2014 Red Hat, Inc.
*/
/**
@@ -26,108 +26,262 @@
* makes requests, like process identifier and user UID.
*/
-#include <config.h>
-#include <glib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <unistd.h>
+#include "nm-auth-subject.h"
-#if WITH_POLKIT
-#include <polkit/polkit.h>
-#endif
+#include <string.h>
+#include <stdlib.h>
+#include <gio/gio.h>
-#include "nm-auth-subject.h"
#include "nm-dbus-manager.h"
+#include "nm-enum-types.h"
G_DEFINE_TYPE (NMAuthSubject, nm_auth_subject, G_TYPE_OBJECT)
#define NM_AUTH_SUBJECT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_AUTH_SUBJECT, NMAuthSubjectPrivate))
-typedef struct {
- gulong pid;
- gulong uid;
- char *dbus_sender;
+enum {
+ PROP_0,
+ PROP_SUBJECT_TYPE,
+ PROP_UNIX_PROCESS_DBUS_SENDER,
+ PROP_UNIX_PROCESS_PID,
+ PROP_UNIX_PROCESS_UID,
+
+ PROP_LAST,
+};
-#if WITH_POLKIT
- PolkitSubject *pk_subject;
-#endif
+typedef struct {
+ NMAuthSubjectType subject_type;
+ struct {
+ gulong pid;
+ gulong uid;
+ guint64 start_time;
+ char *dbus_sender;
+ } unix_process;
} NMAuthSubjectPrivate;
-static NMAuthSubject *
-_new_common (DBusGMethodInvocation *context,
- DBusConnection *connection,
- DBusMessage *message,
- gboolean internal)
-{
- NMAuthSubject *subject;
- NMAuthSubjectPrivate *priv;
- NMDBusManager *dbus_mgr;
- gboolean success = FALSE;
- g_return_val_if_fail (context || (connection && message) || internal, NULL);
- if (internal)
- g_return_val_if_fail (context == NULL && connection == NULL && message == NULL, NULL);
- subject = NM_AUTH_SUBJECT (g_object_new (NM_TYPE_AUTH_SUBJECT, NULL));
- priv = NM_AUTH_SUBJECT_GET_PRIVATE (subject);
+/**************************************************************/
+
+/* copied from polkit source (src/polkit/polkitunixprocess.c)
+ * and adjusted.
+ */
+static guint64
+get_start_time_for_pid (pid_t pid)
+{
+ guint64 start_time;
+ gchar *filename;
+ gchar *contents;
+ size_t length;
+ gchar **tokens;
+ guint num_tokens;
+ gchar *p;
+ gchar *endp;
+
+ start_time = 0;
+ contents = NULL;
+
+ filename = g_strdup_printf ("/proc/%d/stat", pid);
+
+ if (!g_file_get_contents (filename, &contents, &length, NULL))
+ goto out;
+
+ /* start time is the token at index 19 after the '(process name)' entry - since only this
+ * field can contain the ')' character, search backwards for this to avoid malicious
+ * processes trying to fool us
+ */
+ p = strrchr (contents, ')');
+ if (p == NULL)
+ goto out;
+ p += 2; /* skip ') ' */
+ if (p - contents >= (int) length)
+ goto out;
+
+ tokens = g_strsplit (p, " ", 0);
+
+ num_tokens = g_strv_length (tokens);
+
+ if (num_tokens < 20)
+ goto out;
+
+ start_time = strtoull (tokens[19], &endp, 10);
+ if (endp == tokens[19])
+ goto out;
+
+ g_strfreev (tokens);
+
+ out:
+ g_free (filename);
+ g_free (contents);
+
+ return start_time;
+}
+
+/**************************************************************/
- dbus_mgr = nm_dbus_manager_get ();
+#define CHECK_SUBJECT(self, error_value) \
+ NMAuthSubjectPrivate *priv; \
+ g_return_val_if_fail (NM_IS_AUTH_SUBJECT (self), error_value); \
+ priv = NM_AUTH_SUBJECT_GET_PRIVATE (self); \
- if (internal) {
- priv->uid = 0;
- priv->pid = 0;
- return subject;
+#define CHECK_SUBJECT_TYPED(self, expected_subject_type, error_value) \
+ CHECK_SUBJECT (self, error_value); \
+ g_return_val_if_fail (priv->subject_type == (expected_subject_type), error_value);
+
+const char *
+nm_auth_subject_to_string (NMAuthSubject *self, char *buf, gsize buf_len)
+{
+ CHECK_SUBJECT (self, NULL);
+
+ switch (priv->subject_type) {
+ case NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS:
+ g_snprintf (buf, buf_len, "unix-process[pid=%lu, uid=%lu, start=%llu]",
+ (long unsigned) priv->unix_process.pid,
+ (long unsigned) priv->unix_process.uid,
+ (long long unsigned) priv->unix_process.start_time);
+ break;
+ case NM_AUTH_SUBJECT_TYPE_INTERNAL:
+ g_strlcat (buf, "internal", buf_len);
+ break;
+ default:
+ g_strlcat (buf, "invalid", buf_len);
+ break;
}
+ return buf;
+}
+
+/* returns a floating variant */
+GVariant *
+nm_auth_subject_unix_process_to_polkit_gvariant (NMAuthSubject *self)
+{
+ GVariantBuilder builder;
+ GVariant *dict;
+ GVariant *ret;
+ CHECK_SUBJECT_TYPED (self, NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS, NULL);
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+ g_variant_builder_add (&builder, "{sv}", "pid",
+ g_variant_new_uint32 (priv->unix_process.pid));
+ g_variant_builder_add (&builder, "{sv}", "start-time",
+ g_variant_new_uint64 (priv->unix_process.start_time));
+ g_variant_builder_add (&builder, "{sv}", "uid",
+ g_variant_new_int32 (priv->unix_process.uid));
+ dict = g_variant_builder_end (&builder);
+ ret = g_variant_new ("(s@a{sv})", "unix-process", dict);
+ return ret;
+}
+
+NMAuthSubjectType
+nm_auth_subject_get_subject_type (NMAuthSubject *subject)
+{
+ CHECK_SUBJECT (subject, NM_AUTH_SUBJECT_TYPE_INVALID);
+
+ return priv->subject_type;
+}
+
+gboolean
+nm_auth_subject_is_internal (NMAuthSubject *subject)
+{
+ return nm_auth_subject_get_subject_type (subject) == NM_AUTH_SUBJECT_TYPE_INTERNAL;
+}
+
+gboolean
+nm_auth_subject_is_unix_process (NMAuthSubject *subject)
+{
+ return nm_auth_subject_get_subject_type (subject) == NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS;
+}
+
+gulong
+nm_auth_subject_get_unix_process_pid (NMAuthSubject *subject)
+{
+ CHECK_SUBJECT_TYPED (subject, NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS, G_MAXULONG);
+
+ return priv->unix_process.pid;
+}
+
+gulong
+nm_auth_subject_get_unix_process_uid (NMAuthSubject *subject)
+{
+ CHECK_SUBJECT_TYPED (subject, NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS, G_MAXULONG);
+
+ return priv->unix_process.uid;
+}
+
+const char *
+nm_auth_subject_get_unix_process_dbus_sender (NMAuthSubject *subject)
+{
+ CHECK_SUBJECT_TYPED (subject, NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS, NULL);
+
+ return priv->unix_process.dbus_sender;
+}
+
+/**************************************************************/
+
+static NMAuthSubject *
+_new_unix_process (DBusGMethodInvocation *context,
+ DBusConnection *connection,
+ DBusMessage *message)
+{
+ NMAuthSubject *self;
+ gboolean success = FALSE;
+ gulong pid = 0, uid = 0;
+ char *dbus_sender = NULL;
+
+ g_return_val_if_fail (context || (connection && message), NULL);
if (context) {
- success = nm_dbus_manager_get_caller_info (dbus_mgr,
+ success = nm_dbus_manager_get_caller_info (nm_dbus_manager_get (),
context,
- &priv->dbus_sender,
- &priv->uid,
- &priv->pid);
+ &dbus_sender,
+ &uid,
+ &pid);
} else if (message) {
- success = nm_dbus_manager_get_caller_info_from_message (dbus_mgr,
+ success = nm_dbus_manager_get_caller_info_from_message (nm_dbus_manager_get (),
connection,
message,
- &priv->dbus_sender,
- &priv->uid,
- &priv->pid);
+ &dbus_sender,
+ &uid,
+ &pid);
} else
g_assert_not_reached ();
- if (!success) {
- g_object_unref (subject);
+ if (!success)
return NULL;
- }
-
- g_assert (priv->dbus_sender);
- g_assert_cmpuint (priv->pid, !=, 0);
-
-#if WITH_POLKIT
- /* FIXME: should we use polkit_unix_session_new() to store the session ID
- * of a short-lived process, so that the process can exit but we can still
- * ask that user for authorization?
- */
- priv->pk_subject = polkit_unix_process_new_for_owner (priv->pid, 0, priv->uid);
- if (!priv->pk_subject)
- return NULL;
-#endif
- return subject;
+ g_return_val_if_fail (dbus_sender && *dbus_sender, NULL);
+ /* polkit glib library stores uid and pid as gint. There might be some
+ * pitfalls if the id ever happens to be larger then that. Just assert against
+ * it here. */
+ g_return_val_if_fail (uid <= MIN (G_MAXINT, G_MAXINT32), NULL);
+ g_return_val_if_fail (pid > 0 && pid <= MIN (G_MAXINT, G_MAXINT32), NULL);
+
+ self = NM_AUTH_SUBJECT (g_object_new (NM_TYPE_AUTH_SUBJECT,
+ NM_AUTH_SUBJECT_SUBJECT_TYPE, NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS,
+ NM_AUTH_SUBJECT_UNIX_PROCESS_DBUS_SENDER, dbus_sender,
+ NM_AUTH_SUBJECT_UNIX_PROCESS_PID, (gulong) pid,
+ NM_AUTH_SUBJECT_UNIX_PROCESS_UID, (gulong) uid,
+ NULL));
+
+ if (NM_AUTH_SUBJECT_GET_PRIVATE (self)->subject_type != NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS) {
+ /* this most likely happened because the process is gone (start_time==0).
+ * Either that is not assert-worthy, or constructed() already asserted.
+ * Just return NULL. */
+ g_clear_object (&self);
+ }
+ return self;
}
-
NMAuthSubject *
-nm_auth_subject_new_from_context (DBusGMethodInvocation *context)
+nm_auth_subject_new_unix_process_from_context (DBusGMethodInvocation *context)
{
- return _new_common (context, NULL, NULL, FALSE);
+ return _new_unix_process (context, NULL, NULL);
}
NMAuthSubject *
-nm_auth_subject_new_from_message (DBusConnection *connection,
- DBusMessage *message)
+nm_auth_subject_new_unix_process_from_message (DBusConnection *connection,
+ DBusMessage *message)
{
- return _new_common (NULL, connection, message, FALSE);
+ return _new_unix_process (NULL, connection, message);
}
/**
@@ -140,53 +294,135 @@ nm_auth_subject_new_from_message (DBusConnection *connection,
NMAuthSubject *
nm_auth_subject_new_internal (void)
{
- return _new_common (NULL, NULL, NULL, TRUE);
+ return NM_AUTH_SUBJECT (g_object_new (NM_TYPE_AUTH_SUBJECT,
+ NM_AUTH_SUBJECT_SUBJECT_TYPE, NM_AUTH_SUBJECT_TYPE_INTERNAL,
+ NULL));
}
/**************************************************************/
-gulong
-nm_auth_subject_get_uid (NMAuthSubject *subject)
+static void
+get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
- return NM_AUTH_SUBJECT_GET_PRIVATE (subject)->uid;
-}
+ NMAuthSubjectPrivate *priv = NM_AUTH_SUBJECT_GET_PRIVATE (object);
-gulong
-nm_auth_subject_get_pid (NMAuthSubject *subject)
-{
- return NM_AUTH_SUBJECT_GET_PRIVATE (subject)->pid;
+ switch (prop_id) {
+ case PROP_SUBJECT_TYPE:
+ g_value_set_enum (value, priv->subject_type);
+ break;
+ case PROP_UNIX_PROCESS_DBUS_SENDER:
+ g_value_set_string (value, priv->unix_process.dbus_sender);
+ break;
+ case PROP_UNIX_PROCESS_PID:
+ g_value_set_ulong (value, priv->unix_process.pid);
+ break;
+ case PROP_UNIX_PROCESS_UID:
+ g_value_set_ulong (value, priv->unix_process.uid);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
}
-const char *
-nm_auth_subject_get_dbus_sender (NMAuthSubject *subject)
+static void
+set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
- return NM_AUTH_SUBJECT_GET_PRIVATE (subject)->dbus_sender;
+ NMAuthSubjectPrivate *priv = NM_AUTH_SUBJECT_GET_PRIVATE (object);
+ NMAuthSubjectType subject_type;
+ const char *str;
+ gulong id;
+
+ /* all properties are construct-only */
+ switch (prop_id) {
+ case PROP_SUBJECT_TYPE:
+ subject_type = g_value_get_enum (value);
+ g_return_if_fail (subject_type != NM_AUTH_SUBJECT_TYPE_INVALID);
+ priv->subject_type |= subject_type;
+ g_return_if_fail (priv->subject_type == subject_type);
+ break;
+ case PROP_UNIX_PROCESS_DBUS_SENDER:
+ if ((str = g_value_get_string (value))) {
+ priv->subject_type |= NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS;
+ g_return_if_fail (priv->subject_type == NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS);
+ priv->unix_process.dbus_sender = g_strdup (str);
+ }
+ break;
+ case PROP_UNIX_PROCESS_PID:
+ if ((id = g_value_get_ulong (value)) != G_MAXULONG) {
+ priv->subject_type |= NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS;
+ g_return_if_fail (priv->subject_type == NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS);
+ priv->unix_process.pid = id;
+ }
+ break;
+ case PROP_UNIX_PROCESS_UID:
+ if ((id = g_value_get_ulong (value)) != G_MAXULONG) {
+ priv->subject_type |= NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS;
+ g_return_if_fail (priv->subject_type == NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS);
+ priv->unix_process.uid = id;
+ }
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
}
-gboolean
-nm_auth_subject_get_internal (NMAuthSubject *subject)
+static void
+_clear_private (NMAuthSubjectPrivate *priv)
{
- /* internal requests will have no dbus sender */
- return NM_AUTH_SUBJECT_GET_PRIVATE (subject)->dbus_sender ? FALSE : TRUE;
+ priv->subject_type = NM_AUTH_SUBJECT_TYPE_INVALID;
+ priv->unix_process.pid = G_MAXULONG;
+ priv->unix_process.uid = G_MAXULONG;
+ g_clear_pointer (&priv->unix_process.dbus_sender, g_free);
}
-#if WITH_POLKIT
-PolkitSubject *
-nm_auth_subject_get_polkit_subject (NMAuthSubject *subject)
+static void
+nm_auth_subject_init (NMAuthSubject *self)
{
- return NM_AUTH_SUBJECT_GET_PRIVATE (subject)->pk_subject;
+ _clear_private (NM_AUTH_SUBJECT_GET_PRIVATE (self));
}
-#endif
-
-/******************************************************************/
static void
-nm_auth_subject_init (NMAuthSubject *self)
+constructed (GObject *object)
{
+ NMAuthSubject *self = NM_AUTH_SUBJECT (object);
NMAuthSubjectPrivate *priv = NM_AUTH_SUBJECT_GET_PRIVATE (self);
- priv->pid = G_MAXULONG;
- priv->uid = G_MAXULONG;
+ /* validate that the created instance. */
+
+ switch (priv->subject_type) {
+ case NM_AUTH_SUBJECT_TYPE_INTERNAL:
+ priv->unix_process.pid = G_MAXULONG;
+ priv->unix_process.uid = 0; /* internal uses 'root' user */
+ return;
+ case NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS:
+ /* Ensure pid and uid to be representable as int32.
+ * DBUS treats them as uint32, polkit library as gint. */
+ if (priv->unix_process.pid > MIN (G_MAXINT, G_MAXINT32))
+ break;
+ if (priv->unix_process.uid > MIN (G_MAXINT, G_MAXINT32)) {
+ /* for uid==-1, libpolkit-gobject-1 detects the user based on the process id.
+ * Don't bother and require the user id as parameter. */
+ break;
+ }
+ if (!priv->unix_process.dbus_sender || !*priv->unix_process.dbus_sender)
+ break;
+
+ priv->unix_process.start_time = get_start_time_for_pid (priv->unix_process.pid);
+
+ if (!priv->unix_process.start_time) {
+ /* could not detect the process start time. The subject is invalid, but don't
+ * assert against it. */
+ _clear_private (priv);
+ }
+ return;
+ default:
+ break;
+ }
+
+ _clear_private (priv);
+ g_return_if_reached ();
}
static void
@@ -194,12 +430,7 @@ finalize (GObject *object)
{
NMAuthSubjectPrivate *priv = NM_AUTH_SUBJECT_GET_PRIVATE (object);
- g_free (priv->dbus_sender);
-
-#if WITH_POLKIT
- if (priv->pk_subject)
- g_object_unref (priv->pk_subject);
-#endif
+ _clear_private (priv);
G_OBJECT_CLASS (nm_auth_subject_parent_class)->finalize (object);
}
@@ -212,5 +443,42 @@ nm_auth_subject_class_init (NMAuthSubjectClass *config_class)
g_type_class_add_private (config_class, sizeof (NMAuthSubjectPrivate));
/* virtual methods */
+ object_class->get_property = get_property;
+ object_class->set_property = set_property;
+ object_class->constructed = constructed;
object_class->finalize = finalize;
+
+ g_object_class_install_property
+ (object_class, PROP_SUBJECT_TYPE,
+ g_param_spec_enum (NM_AUTH_SUBJECT_SUBJECT_TYPE, "", "",
+ NM_TYPE_AUTH_SUBJECT_TYPE,
+ NM_AUTH_SUBJECT_TYPE_INVALID,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property
+ (object_class, PROP_UNIX_PROCESS_DBUS_SENDER,
+ g_param_spec_string (NM_AUTH_SUBJECT_UNIX_PROCESS_DBUS_SENDER, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property
+ (object_class, PROP_UNIX_PROCESS_PID,
+ g_param_spec_ulong (NM_AUTH_SUBJECT_UNIX_PROCESS_PID, "", "",
+ 0, G_MAXULONG, G_MAXULONG,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property
+ (object_class, PROP_UNIX_PROCESS_UID,
+ g_param_spec_ulong (NM_AUTH_SUBJECT_UNIX_PROCESS_UID, "", "",
+ 0, G_MAXULONG, G_MAXULONG,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
}
diff --git a/src/nm-auth-subject.h b/src/nm-auth-subject.h
index 4834005e2e..4e1d83162f 100644
--- a/src/nm-auth-subject.h
+++ b/src/nm-auth-subject.h
@@ -27,10 +27,6 @@
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
-#if WITH_POLKIT
-#include <polkit/polkit.h>
-#endif
-
#include "nm-types.h"
#define NM_TYPE_AUTH_SUBJECT (nm_auth_subject_get_type ())
@@ -40,33 +36,52 @@
#define NM_IS_AUTH_SUBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_AUTH_SUBJECT))
#define NM_AUTH_SUBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_AUTH_SUBJECT, NMAuthSubjectClass))
+typedef enum {
+ NM_AUTH_SUBJECT_TYPE_INVALID = 0,
+ NM_AUTH_SUBJECT_TYPE_INTERNAL = 1,
+ NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS = 2,
+} NMAuthSubjectType;
+
+#define NM_AUTH_SUBJECT_SUBJECT_TYPE "subject-type"
+#define NM_AUTH_SUBJECT_UNIX_PROCESS_DBUS_SENDER "unix-process-dbus-sender"
+#define NM_AUTH_SUBJECT_UNIX_PROCESS_PID "unix-process-pid"
+#define NM_AUTH_SUBJECT_UNIX_PROCESS_UID "unix-process-uid"
+
struct _NMAuthSubject {
GObject parent;
};
typedef struct {
GObjectClass parent;
-
} NMAuthSubjectClass;
GType nm_auth_subject_get_type (void);
-NMAuthSubject *nm_auth_subject_new_from_context (DBusGMethodInvocation *context);
+NMAuthSubject *nm_auth_subject_new_internal (void);
-NMAuthSubject *nm_auth_subject_new_from_message (DBusConnection *connection, DBusMessage *message);
+NMAuthSubject *nm_auth_subject_new_unix_process_from_context (DBusGMethodInvocation *context);
-NMAuthSubject *nm_auth_subject_new_internal (void);
+NMAuthSubject *nm_auth_subject_new_unix_process_from_message (DBusConnection *connection, DBusMessage *message);
+
+
+NMAuthSubjectType nm_auth_subject_get_subject_type (NMAuthSubject *subject);
+
+
+gboolean nm_auth_subject_is_internal (NMAuthSubject *subject);
+
+
+gboolean nm_auth_subject_is_unix_process (NMAuthSubject *subject);
+
+gulong nm_auth_subject_get_unix_process_pid (NMAuthSubject *subject);
+
+const char *nm_auth_subject_get_unix_process_dbus_sender (NMAuthSubject *subject);
-gulong nm_auth_subject_get_uid (NMAuthSubject *subject);
-gulong nm_auth_subject_get_pid (NMAuthSubject *subject);
+gulong nm_auth_subject_get_unix_process_uid (NMAuthSubject *subject);
-const char *nm_auth_subject_get_dbus_sender (NMAuthSubject *subject);
-gboolean nm_auth_subject_get_internal (NMAuthSubject *subject);
+const char *nm_auth_subject_to_string (NMAuthSubject *self, char *buf, gsize buf_len);
-#if WITH_POLKIT
-PolkitSubject *nm_auth_subject_get_polkit_subject (NMAuthSubject *subject);
-#endif
+GVariant * nm_auth_subject_unix_process_to_polkit_gvariant (NMAuthSubject *self);
#endif /* __NETWORKMANAGER_AUTH_SUBJECT_H__ */
diff --git a/src/nm-auth-utils.c b/src/nm-auth-utils.c
index b2d7cb3cbd..0a652507e9 100644
--- a/src/nm-auth-utils.c
+++ b/src/nm-auth-utils.c
@@ -22,28 +22,21 @@
#include <string.h>
#include <gio/gio.h>
-#if WITH_POLKIT
-#include <polkit/polkit.h>
-#endif
-
+#include "gsystem-local-alloc.h"
#include "nm-setting-connection.h"
#include "nm-auth-utils.h"
#include "nm-logging.h"
#include "nm-dbus-manager.h"
#include "nm-auth-subject.h"
+#include "nm-auth-manager.h"
#include "nm-session-monitor.h"
struct NMAuthChain {
guint32 refcount;
-#if WITH_POLKIT
- PolkitAuthority *authority;
-#endif
GSList *calls;
GHashTable *data;
DBusGMethodInvocation *context;
- char *owner;
- gulong user_uid;
NMAuthSubject *subject;
GError *error;
@@ -90,69 +83,6 @@ auth_chain_finish (gpointer user_data)
return FALSE;
}
-#if WITH_POLKIT
-static PolkitAuthority *
-pk_authority_get (GError **error)
-{
- static PolkitAuthority *authority = NULL;
-
- if (authority == NULL)
- authority = polkit_authority_get_sync (NULL, error);
-
- /* Yes, ref every time; we want to keep the object alive */
- g_warn_if_fail (authority);
- return authority ? g_object_ref (authority) : NULL;
-}
-#endif
-
-static NMAuthChain *
-_auth_chain_new (NMAuthSubject *subject,
- const char *dbus_sender,
- gulong user_uid,
- DBusGMethodInvocation *context,
- NMAuthChainResultFunc done_func,
- gpointer user_data)
-{
- NMAuthChain *self;
-
- g_return_val_if_fail (subject || user_uid == 0 || dbus_sender, NULL);
-
- self = g_malloc0 (sizeof (NMAuthChain));
- self->refcount = 1;
-#if WITH_POLKIT
- self->authority = pk_authority_get (&self->error);
-#endif
- self->data = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, free_data);
- self->done_func = done_func;
- self->user_data = user_data;
- self->context = context;
-
- if (subject) {
- self->user_uid = nm_auth_subject_get_uid (subject);
- self->subject = g_object_ref (subject);
- } else {
- self->user_uid = user_uid;
- self->owner = g_strdup (dbus_sender);
- if (user_uid > 0 && !self->owner) {
- /* Need an owner */
- g_warn_if_fail (self->owner);
- nm_auth_chain_unref (self);
- self = NULL;
- }
- }
-
- return self;
-}
-
-NMAuthChain *
-nm_auth_chain_new_dbus_sender (const char *dbus_sender,
- gulong user_uid,
- NMAuthChainResultFunc done_func,
- gpointer user_data)
-{
- return _auth_chain_new (NULL, dbus_sender, user_uid, NULL, done_func, user_data);
-}
-
/* Creates the NMAuthSubject automatically */
NMAuthChain *
nm_auth_chain_new_context (DBusGMethodInvocation *context,
@@ -164,7 +94,7 @@ nm_auth_chain_new_context (DBusGMethodInvocation *context,
g_return_val_if_fail (context != NULL, NULL);
- subject = nm_auth_subject_new_from_context (context);
+ subject = nm_auth_subject_new_unix_process_from_context (context);
if (!subject)
return NULL;
@@ -183,16 +113,20 @@ nm_auth_chain_new_subject (NMAuthSubject *subject,
NMAuthChainResultFunc done_func,
gpointer user_data)
{
- NMAuthChain *chain;
+ NMAuthChain *self;
g_return_val_if_fail (NM_IS_AUTH_SUBJECT (subject), NULL);
- chain = _auth_chain_new (subject, NULL, G_MAXULONG, context, done_func, user_data);
+ g_return_val_if_fail (nm_auth_subject_is_unix_process (subject) || nm_auth_subject_is_internal (subject), NULL);
- /* Chains creation from a valid NMAuthSubject cannot fail since the
- * subject already has all the necessary auth info.
- */
- g_assert (chain);
- return chain;
+ self = g_malloc0 (sizeof (NMAuthChain));
+ self->refcount = 1;
+ self->data = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, free_data);
+ self->done_func = done_func;
+ self->user_data = user_data;
+ self->context = context;
+ self->subject = g_object_ref (subject);
+
+ return self;
}
gpointer
@@ -364,128 +298,86 @@ auth_call_cancel (gpointer user_data)
}
}
-#if WITH_POLKIT
static void
pk_call_cb (GObject *object, GAsyncResult *result, gpointer user_data)
{
AuthCall *call = user_data;
- PolkitAuthorizationResult *pk_result;
GError *error = NULL;
+ gboolean is_authorized, is_challenge;
- pk_result = polkit_authority_check_authorization_finish ((PolkitAuthority *) object, result, &error);
+ nm_auth_manager_polkit_authority_check_authorization_finish (NM_AUTH_MANAGER (object),
+ result,
+ &is_authorized,
+ &is_challenge,
+ &error);
/* If the call is already canceled do nothing */
if (!call->cancellable) {
+ nm_log_dbg (LOGD_CORE, "callback already cancelled");
g_clear_error (&error);
- g_clear_object (&pk_result);
auth_call_free (call);
return;
}
if (error) {
- if (!call->chain->error)
- call->chain->error = g_error_copy (error);
-
nm_log_warn (LOGD_CORE, "error requesting auth for %s: (%d) %s",
call->permission, error->code, error->message);
- g_clear_error (&error);
+
+ if (!call->chain->error) {
+ call->chain->error = error;
+ error = NULL;
+ } else
+ g_clear_error (&error);
} else {
guint call_result = NM_AUTH_CALL_RESULT_UNKNOWN;
- if (polkit_authorization_result_get_is_authorized (pk_result)) {
+ if (is_authorized) {
/* Caller has the permission */
call_result = NM_AUTH_CALL_RESULT_YES;
- } else if (polkit_authorization_result_get_is_challenge (pk_result)) {
+ } else if (is_challenge) {
/* Caller could authenticate to get the permission */
call_result = NM_AUTH_CALL_RESULT_AUTH;
} else
call_result = NM_AUTH_CALL_RESULT_NO;
nm_auth_chain_set_data (call->chain, call->permission, GUINT_TO_POINTER (call_result), NULL);
- g_object_unref (pk_result);
}
auth_call_complete (call);
}
-static void
-auth_call_schedule_complete_with_error (AuthCall *call, const char *msg)
-{
- if (!call->chain->error)
- call->chain->error = g_error_new_literal (DBUS_GERROR, DBUS_GERROR_FAILED, msg);
- call->call_idle_id = g_idle_add ((GSourceFunc) auth_call_complete, call);
-}
-
-static gboolean
-_add_call_polkit (NMAuthChain *self,
- const char *permission,
- gboolean allow_interaction)
-{
- PolkitSubject *subject;
- PolkitCheckAuthorizationFlags flags = POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE;
- AuthCall *call;
-
- g_return_val_if_fail (self != NULL, FALSE);
- g_return_val_if_fail (self->owner || self->subject, FALSE);
- g_return_val_if_fail (permission != NULL, FALSE);
-
- call = auth_call_new (self, permission);
-
- if (self->authority == NULL) {
- /* No polkit, no authorization */
- auth_call_schedule_complete_with_error (call, "PolicyKit not running");
- return FALSE;
- }
-
- if (self->subject) {
- subject = g_object_ref (nm_auth_subject_get_polkit_subject (self->subject));
- g_assert (subject);
- } else {
- g_assert (self->owner);
- subject = polkit_system_bus_name_new (self->owner);
- if (!subject) {
- auth_call_schedule_complete_with_error (call, "Failed to create polkit subject");
- return FALSE;
- }
- }
-
- if (allow_interaction)
- flags = POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION;
-
- call->cancellable = g_cancellable_new ();
- polkit_authority_check_authorization (self->authority,
- subject,
- permission,
- NULL,
- flags,
- call->cancellable,
- pk_call_cb,
- call);
- g_object_unref (subject);
- return TRUE;
-}
-#endif
-
-gboolean
+void
nm_auth_chain_add_call (NMAuthChain *self,
const char *permission,
gboolean allow_interaction)
{
AuthCall *call;
+ NMAuthManager *auth_manager = nm_auth_manager_get ();
- g_return_val_if_fail (self != NULL, FALSE);
-
-#if WITH_POLKIT
- /* Non-root always gets authenticated when using polkit */
- if (self->user_uid > 0)
- return _add_call_polkit (self, permission, allow_interaction);
-#endif
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (permission && *permission);
+ g_return_if_fail (self->subject);
+ g_return_if_fail (nm_auth_subject_is_unix_process (self->subject) || nm_auth_subject_is_internal (self->subject));
- /* Root user or non-polkit always gets the permission */
call = auth_call_new (self, permission);
- nm_auth_chain_set_data (self, permission, GUINT_TO_POINTER (NM_AUTH_CALL_RESULT_YES), NULL);
- call->call_idle_id = g_idle_add ((GSourceFunc) auth_call_complete, call);
- return TRUE;
+
+ if ( nm_auth_subject_is_internal (self->subject)
+ || nm_auth_subject_get_unix_process_uid (self->subject) == 0
+ || !nm_auth_manager_get_polkit_enabled (auth_manager)) {
+ /* Root user or non-polkit always gets the permission */
+ nm_auth_chain_set_data (self, permission, GUINT_TO_POINTER (NM_AUTH_CALL_RESULT_YES), NULL);
+ call->call_idle_id = g_idle_add ((GSourceFunc) auth_call_complete, call);
+ } else {
+ /* Non-root always gets authenticated when using polkit */
+ call->cancellable = g_cancellable_new ();
+ nm_auth_manager_polkit_authority_check_authorization (auth_manager,
+ self->subject,
+ permission,
+ allow_interaction,
+ call->cancellable,
+ pk_call_cb,
+ call);
+ }
}
void
@@ -500,11 +392,6 @@ nm_auth_chain_unref (NMAuthChain *self)
if (self->idle_id)
g_source_remove (self->idle_id);
-#if WITH_POLKIT
- if (self->authority)
- g_object_unref (self->authority);
-#endif
- g_free (self->owner);
g_object_unref (self->subject);
g_slist_free_full (self->calls, auth_call_cancel);
@@ -519,17 +406,25 @@ nm_auth_chain_unref (NMAuthChain *self)
/************ utils **************/
gboolean
-nm_auth_uid_in_acl (NMConnection *connection,
- NMSessionMonitor *smon,
- gulong uid,
- char **out_error_desc)
+nm_auth_is_subject_in_acl (NMConnection *connection,
+ NMSessionMonitor *smon,
+ NMAuthSubject *subject,
+ char **out_error_desc)
{
NMSettingConnection *s_con;
const char *user = NULL;
GError *local = NULL;
+ gulong uid;
g_return_val_if_fail (connection != NULL, FALSE);
g_return_val_if_fail (smon != NULL, 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);
+
+ if (nm_auth_subject_is_internal (subject))
+ return TRUE;
+
+ uid = nm_auth_subject_get_unix_process_uid (subject);
/* Root gets a free pass */
if (0 == uid)
@@ -570,87 +465,4 @@ nm_auth_uid_in_acl (NMConnection *connection,
return TRUE;
}
-typedef struct {
- GDestroyNotify changed_callback;
- gpointer changed_data;
-} PkChangedInfo;
-
-static GSList *funcs = NULL;
-
-#if WITH_POLKIT
-static void
-pk_authority_changed_cb (GObject *object, gpointer unused)
-{
- GSList *iter;
-
- for (iter = funcs; iter; iter = g_slist_next (iter)) {
- PkChangedInfo *info = iter->data;
-
- info->changed_callback (info->changed_data);
- }
-}
-#endif
-
-void
-nm_auth_changed_func_register (GDestroyNotify callback, gpointer callback_data)
-{
-#if WITH_POLKIT
- PolkitAuthority *authority;
- static guint32 changed_id = 0;
-#endif
- PkChangedInfo *info;
- GSList *iter;
- gboolean found = FALSE;
-
-#if WITH_POLKIT
- authority = pk_authority_get (NULL);
- if (!authority)
- return;
-
- /* Hook up the changed signal the first time a callback is registered */
- if (changed_id == 0) {
- changed_id = g_signal_connect (authority,
- "changed",
- G_CALLBACK (pk_authority_changed_cb),
- &funcs);
- }
-#endif
-
- /* No duplicates */
- for (iter = funcs; iter; iter = g_slist_next (iter)) {
- info = iter->data;
- if ((callback == info->changed_callback) && (callback_data == info->changed_data)) {
- found = TRUE;
- break;
- }
- }
-
- g_warn_if_fail (found == FALSE);
- if (found == FALSE) {
- info = g_malloc0 (sizeof (*info));
- info->changed_callback = callback;
- info->changed_data = callback_data;
- funcs = g_slist_append (funcs, info);
- }
-
-#if WITH_POLKIT
- g_object_unref (authority);
-#endif
-}
-
-void
-nm_auth_changed_func_unregister (GDestroyNotify callback, gpointer callback_data)
-{
- GSList *iter;
-
- for (iter = funcs; iter; iter = g_slist_next (iter)) {
- PkChangedInfo *info = iter->data;
-
- if ((callback == info->changed_callback) && (callback_data == info->changed_data)) {
- g_free (info);
- funcs = g_slist_delete_link (funcs, iter);
- break;
- }
- }
-}
diff --git a/src/nm-auth-utils.h b/src/nm-auth-utils.h
index 25f3cd591e..2ab026d012 100644
--- a/src/nm-auth-utils.h
+++ b/src/nm-auth-utils.h
@@ -54,11 +54,6 @@ typedef void (*NMAuthChainResultFunc) (NMAuthChain *chain,
DBusGMethodInvocation *context,
gpointer user_data);
-NMAuthChain *nm_auth_chain_new_dbus_sender (const char *dbus_sender,
- gulong user_uid,
- NMAuthChainResultFunc done_func,
- gpointer user_data);
-
NMAuthChain *nm_auth_chain_new_context (DBusGMethodInvocation *context,
NMAuthChainResultFunc done_func,
gpointer user_data);
@@ -86,21 +81,17 @@ gulong nm_auth_chain_get_data_ulong (NMAuthChain *chain, const char *tag);
NMAuthCallResult nm_auth_chain_get_result (NMAuthChain *chain,
const char *permission);
-gboolean nm_auth_chain_add_call (NMAuthChain *chain,
- const char *permission,
- gboolean allow_interaction);
+void nm_auth_chain_add_call (NMAuthChain *chain,
+ const char *permission,
+ gboolean allow_interaction);
void nm_auth_chain_unref (NMAuthChain *chain);
/* Caller must free returned error description */
-gboolean nm_auth_uid_in_acl (NMConnection *connection,
- NMSessionMonitor *smon,
- gulong uid,
- char **out_error_desc);
-
-void nm_auth_changed_func_register (GDestroyNotify callback, gpointer callback_data);
-
-void nm_auth_changed_func_unregister (GDestroyNotify callback, gpointer callback_data);
+gboolean nm_auth_is_subject_in_acl (NMConnection *connection,
+ NMSessionMonitor *smon,
+ NMAuthSubject *subect,
+ char **out_error_desc);
#endif /* __NETWORKMANAGER_MANAGER_AUTH_H__ */
diff --git a/src/nm-config.c b/src/nm-config.c
index 3978b56626..2580541a62 100644
--- a/src/nm-config.c
+++ b/src/nm-config.c
@@ -46,6 +46,7 @@ typedef struct {
char **plugins;
gboolean monitor_connection_files;
+ gboolean auth_polkit;
char *dhcp_client;
char *dns_mode;
@@ -142,6 +143,14 @@ nm_config_get_monitor_connection_files (NMConfig *config)
return NM_CONFIG_GET_PRIVATE (config)->monitor_connection_files;
}
+gboolean
+nm_config_get_auth_polkit (NMConfig *config)
+{
+ g_return_val_if_fail (NM_IS_CONFIG (config), NM_CONFIG_DEFAULT_AUTH_POLKIT);
+
+ return NM_CONFIG_GET_PRIVATE (config)->auth_polkit;
+}
+
const char *
nm_config_get_dhcp_client (NMConfig *config)
{
@@ -580,6 +589,16 @@ nm_config_new (GError **error)
g_free (value);
}
+ value = g_key_file_get_value (priv->keyfile, "main", "auth-polkit", NULL);
+ priv->auth_polkit = NM_CONFIG_DEFAULT_AUTH_POLKIT;
+ if (value) {
+ if (!_parse_bool_str (value, &priv->auth_polkit)) {
+ nm_log_warn (LOGD_CORE, "Unrecognized value for main.auth-polkit: %s. Assuming '%s'", value,
+ NM_CONFIG_DEFAULT_AUTH_POLKIT ? "true" : "false");
+ }
+ g_free (value);
+ }
+
priv->dhcp_client = g_key_file_get_value (priv->keyfile, "main", "dhcp", NULL);
priv->dns_mode = g_key_file_get_value (priv->keyfile, "main", "dns", NULL);
@@ -610,6 +629,8 @@ nm_config_init (NMConfig *config)
{
NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (config);
+ priv->auth_polkit = NM_CONFIG_DEFAULT_AUTH_POLKIT;
+
priv->keyfile = g_key_file_new ();
g_key_file_set_list_separator (priv->keyfile, ',');
diff --git a/src/nm-config.h b/src/nm-config.h
index 8f4fa1f7af..27da4cbbc6 100644
--- a/src/nm-config.h
+++ b/src/nm-config.h
@@ -52,6 +52,7 @@ const char *nm_config_get_path (NMConfig *config);
const char *nm_config_get_description (NMConfig *config);
const char **nm_config_get_plugins (NMConfig *config);
gboolean nm_config_get_monitor_connection_files (NMConfig *config);
+gboolean nm_config_get_auth_polkit (NMConfig *config);
const char *nm_config_get_dhcp_client (NMConfig *config);
const char *nm_config_get_dns_mode (NMConfig *config);
const char *nm_config_get_log_level (NMConfig *config);
diff --git a/src/nm-manager.c b/src/nm-manager.c
index 8f5d41f813..db46bf5be8 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -50,6 +50,7 @@
#include "nm-settings.h"
#include "nm-settings-connection.h"
#include "nm-auth-utils.h"
+#include "nm-auth-manager.h"
#include "NetworkManagerUtils.h"
#include "nm-utils.h"
#include "nm-device-factory.h"
@@ -1452,7 +1453,7 @@ device_auth_request_cb (NMDevice *device,
NMAuthChain *chain;
/* Validate the caller */
- subject = nm_auth_subject_new_from_context (context);
+ subject = nm_auth_subject_new_unix_process_from_context (context);
if (!subject) {
error = g_error_new_literal (NM_MANAGER_ERROR,
NM_MANAGER_ERROR_PERMISSION_DENIED,
@@ -1461,10 +1462,10 @@ device_auth_request_cb (NMDevice *device,
}
/* Ensure the subject has permissions for this connection */
- if (connection && !nm_auth_uid_in_acl (connection,
- nm_session_monitor_get (),
- nm_auth_subject_get_uid (subject),
- &error_desc)) {
+ if (connection && !nm_auth_is_subject_in_acl (connection,
+ nm_session_monitor_get (),
+ subject,
+ &error_desc)) {
error = g_error_new_literal (NM_MANAGER_ERROR,
NM_MANAGER_ERROR_PERMISSION_DENIED,
error_desc);
@@ -2662,10 +2663,10 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError *
existing_connection = nm_device_get_connection (device);
subject = nm_active_connection_get_subject (active);
if (existing_connection &&
- !nm_auth_uid_in_acl (existing_connection,
- nm_session_monitor_get (),
- nm_auth_subject_get_uid (subject),
- &error_desc)) {
+ !nm_auth_is_subject_in_acl (existing_connection,
+ nm_session_monitor_get (),
+ subject,
+ &error_desc)) {
g_set_error (error,
NM_MANAGER_ERROR,
NM_MANAGER_ERROR_PERMISSION_DENIED,
@@ -2954,10 +2955,10 @@ nm_manager_activate_connection (NMManager *self,
g_return_val_if_fail (*error == NULL, NULL);
/* Ensure the subject has permissions for this connection */
- if (!nm_auth_uid_in_acl (connection,
- nm_session_monitor_get (),
- nm_auth_subject_get_uid (subject),
- &error_desc)) {
+ if (!nm_auth_is_subject_in_acl (connection,
+ nm_session_monitor_get (),
+ subject,
+ &error_desc)) {
g_set_error_literal (error,
NM_MANAGER_ERROR,
NM_MANAGER_ERROR_PERMISSION_DENIED,
@@ -2998,7 +2999,7 @@ validate_activation_request (NMManager *self,
g_assert (out_vpn);
/* Validate the caller */
- subject = nm_auth_subject_new_from_context (context);
+ subject = nm_auth_subject_new_unix_process_from_context (context);
if (!subject) {
g_set_error_literal (error,
NM_MANAGER_ERROR,
@@ -3008,10 +3009,10 @@ validate_activation_request (NMManager *self,
}
/* Ensure the subject has permissions for this connection */
- if (!nm_auth_uid_in_acl (connection,
- nm_session_monitor_get (),
- nm_auth_subject_get_uid (subject),
- &error_desc)) {
+ if (!nm_auth_is_subject_in_acl (connection,
+ nm_session_monitor_get (),
+ subject,
+ &error_desc)) {
g_set_error_literal (error,
NM_MANAGER_ERROR,
NM_MANAGER_ERROR_PERMISSION_DENIED,
@@ -3528,7 +3529,7 @@ impl_manager_deactivate_connection (NMManager *self,
}
/* Validate the caller */
- subject = nm_auth_subject_new_from_context (context);
+ subject = nm_auth_subject_new_unix_process_from_context (context);
if (!subject) {
error = g_error_new_literal (NM_MANAGER_ERROR,
NM_MANAGER_ERROR_PERMISSION_DENIED,
@@ -3537,10 +3538,10 @@ impl_manager_deactivate_connection (NMManager *self,
}
/* Ensure the subject has permissions for this connection */
- if (!nm_auth_uid_in_acl (connection,
- nm_session_monitor_get (),
- nm_auth_subject_get_uid (subject),
- &error_desc)) {
+ if (!nm_auth_is_subject_in_acl (connection,
+ nm_session_monitor_get (),
+ subject,
+ &error_desc)) {
error = g_error_new_literal (NM_MANAGER_ERROR,
NM_MANAGER_ERROR_PERMISSION_DENIED,
error_desc);
@@ -4434,7 +4435,7 @@ prop_filter (DBusConnection *connection,
goto out;
}
- subject = nm_auth_subject_new_from_message (connection, message);
+ subject = nm_auth_subject_new_unix_process_from_message (connection, message);
if (!subject) {
reply = dbus_message_new_error (message, NM_PERM_DENIED_ERROR,
"Could not determine request UID.");
@@ -4469,7 +4470,7 @@ out:
}
static void
-authority_changed_cb (gpointer user_data)
+authority_changed_cb (NMAuthManager *auth_manager, gpointer user_data)
{
/* Let clients know they should re-check their authorization */
g_signal_emit (NM_MANAGER (user_data), signals[CHECK_PERMISSIONS], 0);
@@ -4834,7 +4835,11 @@ nm_manager_init (NMManager *manager)
G_CALLBACK (resuming_cb), manager);
/* Listen for authorization changes */
- nm_auth_changed_func_register (authority_changed_cb, manager);
+ g_signal_connect (nm_auth_manager_get (),
+ NM_AUTH_MANAGER_SIGNAL_CHANGED,
+ G_CALLBACK (authority_changed_cb),
+ manager);
+
/* Monitor the firmware directory */
if (strlen (KERNEL_FIRMWARE_DIR)) {
@@ -4986,7 +4991,9 @@ dispose (GObject *object)
g_slist_free_full (priv->auth_chains, (GDestroyNotify) nm_auth_chain_unref);
priv->auth_chains = NULL;
- nm_auth_changed_func_unregister (authority_changed_cb, manager);
+ g_signal_handlers_disconnect_by_func (nm_auth_manager_get (),
+ G_CALLBACK (authority_changed_cb),
+ manager);
/* Remove all devices */
while (priv->devices)
diff --git a/src/settings/nm-agent-manager.c b/src/settings/nm-agent-manager.c
index 26692c339f..0de63ffb16 100644
--- a/src/settings/nm-agent-manager.c
+++ b/src/settings/nm-agent-manager.c
@@ -36,7 +36,7 @@
#include "nm-setting-vpn.h"
#include "nm-setting-connection.h"
#include "nm-enum-types.h"
-#include "nm-auth-subject.h"
+#include "nm-auth-manager.h"
#include "nm-dbus-manager.h"
#include "nm-session-monitor.h"
#include "nm-simple-connection.h"
@@ -290,14 +290,14 @@ impl_agent_manager_register_with_capabilities (NMAgentManager *self,
NMSecretAgent *agent;
NMAuthChain *chain;
- subject = nm_auth_subject_new_from_context (context);
+ subject = nm_auth_subject_new_unix_process_from_context (context);
if (!subject) {
error = g_error_new_literal (NM_AGENT_MANAGER_ERROR,
NM_AGENT_MANAGER_ERROR_SENDER_UNKNOWN,
"Unable to determine request sender and UID.");
goto done;
}
- sender_uid = nm_auth_subject_get_uid (subject);
+ sender_uid = nm_auth_subject_get_unix_process_uid (subject);
if ( 0 != sender_uid
&& !nm_session_monitor_uid_has_session (nm_session_monitor_get (),
@@ -529,8 +529,8 @@ agent_compare_func (gconstpointer aa, gconstpointer bb, gpointer user_data)
gulong a_pid, b_pid, requester;
/* Prefer agents in the process the request came from */
- requester = nm_auth_subject_get_pid (req->subject);
- if (requester != G_MAXULONG) {
+ if (nm_auth_subject_is_unix_process (req->subject)) {
+ requester = nm_auth_subject_get_unix_process_pid (req->subject);
a_pid = nm_secret_agent_get_pid (a);
b_pid = nm_secret_agent_get_pid (b);
@@ -572,11 +572,11 @@ request_add_agent (Request *req, NMSecretAgent *agent)
return;
/* If the request should filter agents by UID, do that now */
- if (!nm_auth_subject_get_internal (req->subject)) {
+ if (nm_auth_subject_is_unix_process (req->subject)) {
uid_t agent_uid, subject_uid;
agent_uid = nm_secret_agent_get_owner_uid (agent);
- subject_uid = nm_auth_subject_get_uid (req->subject);
+ subject_uid = nm_auth_subject_get_unix_process_uid (req->subject);
if (agent_uid != subject_uid) {
nm_log_dbg (LOGD_AGENTS, "(%s) agent ignored for secrets request %p/%s "
"(uid %ld not required %ld)",
@@ -713,12 +713,12 @@ static gboolean
connection_request_add_agent (Request *parent, NMSecretAgent *agent)
{
ConnectionRequest *req = (ConnectionRequest *) parent;
- uid_t agent_uid = nm_secret_agent_get_owner_uid (agent);
+ NMAuthSubject *subject = nm_secret_agent_get_subject(agent);
/* Ensure the caller's username exists in the connection's permissions,
* or that the permissions is empty (ie, visible by everyone).
*/
- if (!nm_auth_uid_in_acl (req->connection, nm_session_monitor_get (), agent_uid, NULL)) {
+ if (!nm_auth_is_subject_in_acl (req->connection, nm_session_monitor_get (), subject, NULL)) {
nm_log_dbg (LOGD_AGENTS, "(%s) agent ignored for secrets request %p/%s (not in ACL)",
nm_secret_agent_get_description (agent),
parent, parent->detail);
@@ -1454,11 +1454,13 @@ nm_agent_manager_all_agents_have_capability (NMAgentManager *manager,
NMAgentManagerPrivate *priv = NM_AGENT_MANAGER_GET_PRIVATE (manager);
GHashTableIter iter;
NMSecretAgent *agent;
+ gboolean subject_is_unix_process = nm_auth_subject_is_unix_process (subject);
+ gulong subject_uid = subject_is_unix_process ? nm_auth_subject_get_unix_process_uid (subject) : 0;
g_hash_table_iter_init (&iter, priv->agents);
while (g_hash_table_iter_next (&iter, NULL, (gpointer) &agent)) {
- if ( !nm_auth_subject_get_internal (subject)
- && nm_secret_agent_get_owner_uid (agent) != nm_auth_subject_get_uid (subject))
+ if ( subject_is_unix_process
+ && nm_secret_agent_get_owner_uid (agent) != subject_uid)
continue;
if (!(nm_secret_agent_get_capabilities (agent) & capability))
@@ -1519,9 +1521,8 @@ agent_permissions_changed_done (NMAuthChain *chain,
}
static void
-authority_changed_cb (gpointer user_data)
+authority_changed_cb (NMAuthManager *auth_manager, NMAgentManager *self)
{
- NMAgentManager *self = NM_AGENT_MANAGER (user_data);
NMAgentManagerPrivate *priv = NM_AGENT_MANAGER_GET_PRIVATE (self);
GHashTableIter iter;
NMSecretAgent *agent;
@@ -1572,7 +1573,10 @@ nm_agent_manager_get (void)
G_CALLBACK (name_owner_changed_cb),
singleton);
- nm_auth_changed_func_register (authority_changed_cb, singleton);
+ g_signal_connect (nm_auth_manager_get (),
+ NM_AUTH_MANAGER_SIGNAL_CHANGED,
+ G_CALLBACK (authority_changed_cb),
+ singleton);
return singleton;
}
@@ -1597,7 +1601,9 @@ dispose (GObject *object)
if (!priv->disposed) {
priv->disposed = TRUE;
- nm_auth_changed_func_unregister (authority_changed_cb, NM_AGENT_MANAGER (object));
+ g_signal_handlers_disconnect_by_func (nm_auth_manager_get (),
+ G_CALLBACK (authority_changed_cb),
+ object);
g_slist_free_full (priv->chains, (GDestroyNotify) nm_auth_chain_unref);
diff --git a/src/settings/nm-secret-agent.c b/src/settings/nm-secret-agent.c
index a1c6954ee2..3099f4518b 100644
--- a/src/settings/nm-secret-agent.c
+++ b/src/settings/nm-secret-agent.c
@@ -108,9 +108,9 @@ nm_secret_agent_get_description (NMSecretAgent *agent)
priv = NM_SECRET_AGENT_GET_PRIVATE (agent);
if (!priv->description) {
priv->description = g_strdup_printf ("%s/%s/%lu",
- nm_auth_subject_get_dbus_sender (priv->subject),
+ nm_auth_subject_get_unix_process_dbus_sender (priv->subject),
priv->identifier,
- nm_auth_subject_get_uid (priv->subject));
+ nm_auth_subject_get_unix_process_uid (priv->subject));
}
return priv->description;
@@ -121,7 +121,7 @@ nm_secret_agent_get_dbus_owner (NMSecretAgent *agent)
{
g_return_val_if_fail (NM_IS_SECRET_AGENT (agent), NULL);
- return nm_auth_subject_get_dbus_sender (NM_SECRET_AGENT_GET_PRIVATE (agent)->subject);
+ return nm_auth_subject_get_unix_process_dbus_sender (NM_SECRET_AGENT_GET_PRIVATE (agent)->subject);
}
const char *
@@ -137,7 +137,7 @@ nm_secret_agent_get_owner_uid (NMSecretAgent *agent)
{
g_return_val_if_fail (NM_IS_SECRET_AGENT (agent), G_MAXULONG);
- return nm_auth_subject_get_uid (NM_SECRET_AGENT_GET_PRIVATE (agent)->subject);
+ return nm_auth_subject_get_unix_process_uid (NM_SECRET_AGENT_GET_PRIVATE (agent)->subject);
}
const char *
@@ -153,7 +153,7 @@ nm_secret_agent_get_pid (NMSecretAgent *agent)
{
g_return_val_if_fail (NM_IS_SECRET_AGENT (agent), G_MAXULONG);
- return nm_auth_subject_get_pid (NM_SECRET_AGENT_GET_PRIVATE (agent)->subject);
+ return nm_auth_subject_get_unix_process_pid (NM_SECRET_AGENT_GET_PRIVATE (agent)->subject);
}
NMSecretAgentCapabilities
@@ -477,9 +477,10 @@ nm_secret_agent_new (DBusGMethodInvocation *context,
g_return_val_if_fail (context != NULL, NULL);
g_return_val_if_fail (NM_IS_AUTH_SUBJECT (subject), NULL);
+ g_return_val_if_fail (nm_auth_subject_is_unix_process (subject), NULL);
g_return_val_if_fail (identifier != NULL, NULL);
- pw = getpwuid (nm_auth_subject_get_uid (subject));
+ pw = getpwuid (nm_auth_subject_get_unix_process_uid (subject));
g_return_val_if_fail (pw != NULL, NULL);
g_return_val_if_fail (pw->pw_name[0] != '\0', NULL);
username = g_strdup (pw->pw_name);
@@ -492,13 +493,13 @@ nm_secret_agent_new (DBusGMethodInvocation *context,
priv->capabilities = capabilities;
priv->subject = g_object_ref (subject);
- hash_str = g_strdup_printf ("%16lu%s", nm_auth_subject_get_uid (subject), identifier);
+ hash_str = g_strdup_printf ("%16lu%s", nm_auth_subject_get_unix_process_uid (subject), identifier);
priv->hash = g_str_hash (hash_str);
g_free (hash_str);
priv->proxy = nm_dbus_manager_new_proxy (nm_dbus_manager_get (),
context,
- nm_auth_subject_get_dbus_sender (subject),
+ nm_auth_subject_get_unix_process_dbus_sender (subject),
NM_DBUS_PATH_SECRET_AGENT,
NM_DBUS_INTERFACE_SECRET_AGENT);
g_assert (priv->proxy);
diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c
index 9cf90a5bc9..1e0106d07b 100644
--- a/src/settings/nm-settings-connection.c
+++ b/src/settings/nm-settings-connection.c
@@ -1029,7 +1029,7 @@ _new_auth_subject (DBusGMethodInvocation *context, GError **error)
{
NMAuthSubject *subject;
- subject = nm_auth_subject_new_from_context (context);
+ subject = nm_auth_subject_new_unix_process_from_context (context);
if (!subject) {
g_set_error_literal (error,
NM_SETTINGS_ERROR,
@@ -1057,10 +1057,10 @@ auth_start (NMSettingsConnection *self,
g_return_if_fail (NM_IS_AUTH_SUBJECT (subject));
/* Ensure the caller can view this connection */
- if (!nm_auth_uid_in_acl (NM_CONNECTION (self),
- priv->session_monitor,
- nm_auth_subject_get_uid (subject),
- &error_desc)) {
+ if (!nm_auth_is_subject_in_acl (NM_CONNECTION (self),
+ priv->session_monitor,
+ subject,
+ &error_desc)) {
error = g_error_new_literal (NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_PERMISSION_DENIED,
error_desc);
@@ -1414,10 +1414,10 @@ impl_settings_connection_update_helper (NMSettingsConnection *self,
* that's sending the update request. You can't make a connection
* invisible to yourself.
*/
- if (!nm_auth_uid_in_acl (tmp ? tmp : NM_CONNECTION (self),
- priv->session_monitor,
- nm_auth_subject_get_uid (subject),
- &error_desc)) {
+ if (!nm_auth_is_subject_in_acl (tmp ? tmp : NM_CONNECTION (self),
+ priv->session_monitor,
+ subject,
+ &error_desc)) {
error = g_error_new_literal (NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_PERMISSION_DENIED,
error_desc);
diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c
index 7876a69bf6..65bc241e48 100644
--- a/src/settings/nm-settings.c
+++ b/src/settings/nm-settings.c
@@ -288,7 +288,7 @@ impl_settings_get_connection_by_uuid (NMSettings *self,
goto error;
}
- subject = nm_auth_subject_new_from_context (context);
+ subject = nm_auth_subject_new_unix_process_from_context (context);
if (!subject) {
error = g_error_new_literal (NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_PERMISSION_DENIED,
@@ -296,10 +296,10 @@ impl_settings_get_connection_by_uuid (NMSettings *self,
goto error;
}
- if (!nm_auth_uid_in_acl (NM_CONNECTION (connection),
- nm_session_monitor_get (),
- nm_auth_subject_get_uid (subject),
- &error_desc)) {
+ if (!nm_auth_is_subject_in_acl (NM_CONNECTION (connection),
+ nm_session_monitor_get (),
+ subject,
+ &error_desc)) {
error = g_error_new_literal (NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_PERMISSION_DENIED,
error_desc);
@@ -1142,7 +1142,7 @@ nm_settings_add_connection_dbus (NMSettings *self,
goto done;
}
- subject = nm_auth_subject_new_from_context (context);
+ subject = nm_auth_subject_new_unix_process_from_context (context);
if (!subject) {
error = g_error_new_literal (NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_PERMISSION_DENIED,
@@ -1153,10 +1153,10 @@ nm_settings_add_connection_dbus (NMSettings *self,
/* Ensure the caller's username exists in the connection's permissions,
* or that the permissions is empty (ie, visible by everyone).
*/
- if (!nm_auth_uid_in_acl (connection,
- nm_session_monitor_get (),
- nm_auth_subject_get_uid (subject),
- &error_desc)) {
+ if (!nm_auth_is_subject_in_acl (connection,
+ nm_session_monitor_get (),
+ subject,
+ &error_desc)) {
error = g_error_new_literal (NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_PERMISSION_DENIED,
error_desc);