diff options
Diffstat (limited to 'src/nm-auth-manager.c')
| -rw-r--r-- | src/nm-auth-manager.c | 1103 |
1 files changed, 561 insertions, 542 deletions
diff --git a/src/nm-auth-manager.c b/src/nm-auth-manager.c index 5b3702ec..1cb4834a 100644 --- a/src/nm-auth-manager.c +++ b/src/nm-auth-manager.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2014 Red Hat, Inc. */ @@ -14,270 +14,275 @@ #include "nm-dbus-manager.h" #include "NetworkManagerUtils.h" -#define POLKIT_SERVICE "org.freedesktop.PolicyKit1" -#define POLKIT_OBJECT_PATH "/org/freedesktop/PolicyKit1/Authority" -#define POLKIT_INTERFACE "org.freedesktop.PolicyKit1.Authority" +#define POLKIT_SERVICE "org.freedesktop.PolicyKit1" +#define POLKIT_OBJECT_PATH "/org/freedesktop/PolicyKit1/Authority" +#define POLKIT_INTERFACE "org.freedesktop.PolicyKit1.Authority" -#define CANCELLATION_ID_PREFIX "cancellation-id-" +#define CANCELLATION_ID_PREFIX "cancellation-id-" #define CANCELLATION_TIMEOUT_MS 5000 /*****************************************************************************/ -NM_GOBJECT_PROPERTIES_DEFINE_BASE ( - PROP_POLKIT_ENABLED, -); +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_POLKIT_ENABLED, ); enum { - CHANGED_SIGNAL, - LAST_SIGNAL, + CHANGED_SIGNAL, + LAST_SIGNAL, }; static guint signals[LAST_SIGNAL] = {0}; typedef struct { - CList calls_lst_head; - GDBusConnection *dbus_connection; - GCancellable *main_cancellable; - char *name_owner; - guint64 call_numid_counter; - guint changed_id; - guint name_owner_changed_id; - bool disposing:1; - bool shutting_down:1; - bool got_name_owner:1; - NMAuthPolkitMode auth_polkit_mode:3; + CList calls_lst_head; + GDBusConnection *dbus_connection; + GCancellable * main_cancellable; + char * name_owner; + guint64 call_numid_counter; + guint changed_id; + guint name_owner_changed_id; + bool disposing : 1; + bool shutting_down : 1; + bool got_name_owner : 1; + NMAuthPolkitMode auth_polkit_mode : 3; } NMAuthManagerPrivate; struct _NMAuthManager { - GObject parent; - NMAuthManagerPrivate _priv; + GObject parent; + NMAuthManagerPrivate _priv; }; struct _NMAuthManagerClass { - GObjectClass parent; + GObjectClass parent; }; -G_DEFINE_TYPE (NMAuthManager, nm_auth_manager, G_TYPE_OBJECT) +G_DEFINE_TYPE(NMAuthManager, nm_auth_manager, G_TYPE_OBJECT) -#define NM_AUTH_MANAGER_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMAuthManager, NM_IS_AUTH_MANAGER) +#define NM_AUTH_MANAGER_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMAuthManager, NM_IS_AUTH_MANAGER) -NM_DEFINE_SINGLETON_REGISTER (NMAuthManager); +NM_DEFINE_SINGLETON_REGISTER(NMAuthManager); /*****************************************************************************/ -#define _NMLOG_PREFIX_NAME "auth" -#define _NMLOG_DOMAIN LOGD_CORE -#define _NMLOG(level, ...) \ - G_STMT_START { \ - if (nm_logging_enabled ((level), (_NMLOG_DOMAIN))) { \ - char __prefix[30] = _NMLOG_PREFIX_NAME; \ - \ - if ((self) != singleton_instance) \ - g_snprintf (__prefix, sizeof (__prefix), ""_NMLOG_PREFIX_NAME"[%p]", (self)); \ - _nm_log ((level), (_NMLOG_DOMAIN), 0, NULL, NULL, \ - "%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - __prefix _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ - } \ - } G_STMT_END - -#define _NMLOG2(level, call_id, ...) \ - G_STMT_START { \ - if (nm_logging_enabled ((level), (_NMLOG_DOMAIN))) { \ - NMAuthManagerCallId *_call_id = (call_id); \ - char __prefix[30] = _NMLOG_PREFIX_NAME; \ - \ - if (_call_id->self != singleton_instance) \ - g_snprintf (__prefix, sizeof (__prefix), ""_NMLOG_PREFIX_NAME"[%p]", _call_id->self); \ - _nm_log ((level), (_NMLOG_DOMAIN), 0, NULL, NULL, \ - "%s: call[%"G_GUINT64_FORMAT"]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - __prefix, \ - _call_id->call_numid \ - _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ - } \ - } G_STMT_END +#define _NMLOG_PREFIX_NAME "auth" +#define _NMLOG_DOMAIN LOGD_CORE +#define _NMLOG(level, ...) \ + G_STMT_START \ + { \ + if (nm_logging_enabled((level), (_NMLOG_DOMAIN))) { \ + char __prefix[30] = _NMLOG_PREFIX_NAME; \ + \ + if ((self) != singleton_instance) \ + g_snprintf(__prefix, \ + sizeof(__prefix), \ + ""_NMLOG_PREFIX_NAME \ + "[%p]", \ + (self)); \ + _nm_log((level), \ + (_NMLOG_DOMAIN), \ + 0, \ + NULL, \ + NULL, \ + "%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + __prefix _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + } \ + G_STMT_END + +#define _NMLOG2(level, call_id, ...) \ + G_STMT_START \ + { \ + if (nm_logging_enabled((level), (_NMLOG_DOMAIN))) { \ + NMAuthManagerCallId *_call_id = (call_id); \ + char __prefix[30] = _NMLOG_PREFIX_NAME; \ + \ + if (_call_id->self != singleton_instance) \ + g_snprintf(__prefix, \ + sizeof(__prefix), \ + ""_NMLOG_PREFIX_NAME \ + "[%p]", \ + _call_id->self); \ + _nm_log((level), \ + (_NMLOG_DOMAIN), \ + 0, \ + NULL, \ + NULL, \ + "%s: call[%" G_GUINT64_FORMAT "]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + __prefix, \ + _call_id->call_numid _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + } \ + G_STMT_END /*****************************************************************************/ gboolean -nm_auth_manager_get_polkit_enabled (NMAuthManager *self) +nm_auth_manager_get_polkit_enabled(NMAuthManager *self) { - g_return_val_if_fail (NM_IS_AUTH_MANAGER (self), FALSE); + g_return_val_if_fail(NM_IS_AUTH_MANAGER(self), FALSE); - return NM_AUTH_MANAGER_GET_PRIVATE (self)->dbus_connection != NULL; + return NM_AUTH_MANAGER_GET_PRIVATE(self)->dbus_connection != NULL; } /*****************************************************************************/ static void -_emit_changed_signal (NMAuthManager *self) +_emit_changed_signal(NMAuthManager *self) { - g_signal_emit (self, signals[CHANGED_SIGNAL], 0); + g_signal_emit(self, signals[CHANGED_SIGNAL], 0); } typedef enum { - POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE = 0, - POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION = (1<<0), + POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE = 0, + POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION = (1 << 0), } PolkitCheckAuthorizationFlags; struct _NMAuthManagerCallId { - CList calls_lst; - NMAuthManager *self; - GCancellable *dbus_cancellable; - NMAuthManagerCheckAuthorizationCallback callback; - gpointer user_data; - guint64 call_numid; - guint idle_id; - bool idle_is_authorized:1; + CList calls_lst; + NMAuthManager * self; + GCancellable * dbus_cancellable; + NMAuthManagerCheckAuthorizationCallback callback; + gpointer user_data; + guint64 call_numid; + guint idle_id; + bool idle_is_authorized : 1; }; -#define cancellation_id_to_str_a(call_numid) \ - nm_sprintf_bufa (NM_STRLEN (CANCELLATION_ID_PREFIX) + 60, \ - CANCELLATION_ID_PREFIX"%"G_GUINT64_FORMAT, \ - (call_numid)) +#define cancellation_id_to_str_a(call_numid) \ + nm_sprintf_bufa(NM_STRLEN(CANCELLATION_ID_PREFIX) + 60, \ + CANCELLATION_ID_PREFIX "%" G_GUINT64_FORMAT, \ + (call_numid)) static void -_call_id_free (NMAuthManagerCallId *call_id) +_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_cancellable) { - /* we have a pending D-Bus call. We keep the call-id instance alive - * for _call_check_authorize_cb() */ - g_cancellable_cancel (call_id->dbus_cancellable); - return; - } - - g_object_unref (call_id->self); - g_slice_free (NMAuthManagerCallId, call_id); + c_list_unlink(&call_id->calls_lst); + nm_clear_g_source(&call_id->idle_id); + + if (call_id->dbus_cancellable) { + /* we have a pending D-Bus call. We keep the call-id instance alive + * for _call_check_authorize_cb() */ + g_cancellable_cancel(call_id->dbus_cancellable); + return; + } + + g_object_unref(call_id->self); + g_slice_free(NMAuthManagerCallId, call_id); } static void -_call_id_invoke_callback (NMAuthManagerCallId *call_id, - gboolean is_authorized, - gboolean is_challenge, - GError *error) +_call_id_invoke_callback(NMAuthManagerCallId *call_id, + gboolean is_authorized, + gboolean is_challenge, + GError * error) { - c_list_unlink (&call_id->calls_lst); - - call_id->callback (call_id->self, - call_id, - is_authorized, - is_challenge, - error, - call_id->user_data); - _call_id_free (call_id); + c_list_unlink(&call_id->calls_lst); + + call_id + ->callback(call_id->self, call_id, is_authorized, is_challenge, error, call_id->user_data); + _call_id_free(call_id); } static void -cancel_check_authorization_cb (GObject *source, - GAsyncResult *res, - gpointer user_data) +cancel_check_authorization_cb(GObject *source, GAsyncResult *res, gpointer user_data) { - NMAuthManagerCallId *call_id = user_data; - gs_unref_variant GVariant *value = NULL; - gs_free_error GError *error= NULL; - - 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) - _LOG2T (call_id, "cancel request failed: %s", error->message); - else - _LOG2T (call_id, "cancel request succeeded"); - - _call_id_free (call_id); + NMAuthManagerCallId *call_id = user_data; + gs_unref_variant GVariant *value = NULL; + gs_free_error GError *error = NULL; + + 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) + _LOG2T(call_id, "cancel request failed: %s", error->message); + else + _LOG2T(call_id, "cancel request succeeded"); + + _call_id_free(call_id); } static void -_call_check_authorize_cb (GObject *proxy, - GAsyncResult *res, - gpointer user_data) +_call_check_authorize_cb(GObject *proxy, GAsyncResult *res, gpointer user_data) { - NMAuthManagerCallId *call_id = user_data; - NMAuthManager *self; - NMAuthManagerPrivate *priv; - gs_unref_variant GVariant *value = NULL; - gs_free_error GError *error = NULL; - gboolean is_authorized = FALSE; - gboolean is_challenge = FALSE; - - /* we need to clear the cancelable, to signal for _call_id_free() that we - * are not in a pending call. - * - * Note how _call_id_free() kept call-id alive, even if the request was - * already cancelled. */ - g_clear_object (&call_id->dbus_cancellable); - - self = call_id->self; - priv = NM_AUTH_MANAGER_GET_PRIVATE (self); - - value = g_dbus_connection_call_finish (G_DBUS_CONNECTION (proxy), res, &error); - - if (nm_utils_error_is_cancelled (error)) { - /* call_id was cancelled externally, but _call_id_free() kept call_id - * alive (and it has still the reference on @self. */ - - if (!priv->main_cancellable) { - /* we do a forced shutdown. There is no more time for cancelling... */ - _call_id_free (call_id); - - /* this shouldn't really happen, because: - * nm_auth_manager_check_authorization() only scheduled the D-Bus request at a time when - * main_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 - * - give enough time to cancel the request and schedule a D-Bus call - * to CancelCheckAuthorization (below), before issuing force-shutdown. */ - g_return_if_reached (); - } - - 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->main_cancellable, - cancel_check_authorization_cb, - call_id); - return; - } - - if (!error) { - g_variant_get (value, - "((bb@a{ss}))", - &is_authorized, - &is_challenge, - NULL); - _LOG2T (call_id, "completed: authorized=%d, challenge=%d", - is_authorized, is_challenge); - } else - _LOG2T (call_id, "completed: failed: %s", error->message); - - _call_id_invoke_callback (call_id, is_authorized, is_challenge, error); + NMAuthManagerCallId * call_id = user_data; + NMAuthManager * self; + NMAuthManagerPrivate *priv; + gs_unref_variant GVariant *value = NULL; + gs_free_error GError *error = NULL; + gboolean is_authorized = FALSE; + gboolean is_challenge = FALSE; + + /* we need to clear the cancelable, to signal for _call_id_free() that we + * are not in a pending call. + * + * Note how _call_id_free() kept call-id alive, even if the request was + * already cancelled. */ + g_clear_object(&call_id->dbus_cancellable); + + self = call_id->self; + priv = NM_AUTH_MANAGER_GET_PRIVATE(self); + + value = g_dbus_connection_call_finish(G_DBUS_CONNECTION(proxy), res, &error); + + if (nm_utils_error_is_cancelled(error)) { + /* call_id was cancelled externally, but _call_id_free() kept call_id + * alive (and it has still the reference on @self. */ + + if (!priv->main_cancellable) { + /* we do a forced shutdown. There is no more time for cancelling... */ + _call_id_free(call_id); + + /* this shouldn't really happen, because: + * nm_auth_manager_check_authorization() only scheduled the D-Bus request at a time when + * main_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 + * - give enough time to cancel the request and schedule a D-Bus call + * to CancelCheckAuthorization (below), before issuing force-shutdown. */ + g_return_if_reached(); + } + + 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->main_cancellable, + cancel_check_authorization_cb, + call_id); + return; + } + + if (!error) { + g_variant_get(value, "((bb@a{ss}))", &is_authorized, &is_challenge, NULL); + _LOG2T(call_id, "completed: authorized=%d, challenge=%d", is_authorized, is_challenge); + } else + _LOG2T(call_id, "completed: failed: %s", error->message); + + _call_id_invoke_callback(call_id, is_authorized, is_challenge, error); } static gboolean -_call_on_idle (gpointer user_data) +_call_on_idle(gpointer user_data) { - NMAuthManagerCallId *call_id = user_data; - gboolean is_authorized; - gboolean is_challenge = FALSE; + NMAuthManagerCallId *call_id = user_data; + gboolean is_authorized; + gboolean is_challenge = FALSE; - is_authorized = call_id->idle_is_authorized; - call_id->idle_id = 0; + is_authorized = call_id->idle_is_authorized; + call_id->idle_id = 0; - _LOG2T (call_id, "completed: authorized=%d, challenge=%d (simulated)", - is_authorized, is_challenge); + _LOG2T(call_id, + "completed: authorized=%d, challenge=%d (simulated)", + is_authorized, + is_challenge); - _call_id_invoke_callback (call_id, is_authorized, is_challenge, NULL); - return G_SOURCE_REMOVE; + _call_id_invoke_callback(call_id, is_authorized, is_challenge, NULL); + return G_SOURCE_REMOVE; } /* @@ -294,439 +299,453 @@ _call_on_idle (gpointer user_data) * which @self must be live long enough). */ NMAuthManagerCallId * -nm_auth_manager_check_authorization (NMAuthManager *self, - NMAuthSubject *subject, - const char *action_id, - gboolean allow_user_interaction, - NMAuthManagerCheckAuthorizationCallback callback, - gpointer user_data) +nm_auth_manager_check_authorization(NMAuthManager * self, + NMAuthSubject * subject, + const char * action_id, + gboolean allow_user_interaction, + NMAuthManagerCheckAuthorizationCallback callback, + gpointer user_data) { - NMAuthManagerPrivate *priv; - PolkitCheckAuthorizationFlags flags; - char subject_buf[64]; - NMAuthManagerCallId *call_id; - - g_return_val_if_fail (NM_IS_AUTH_MANAGER (self), NULL); - g_return_val_if_fail (NM_IN_SET (nm_auth_subject_get_subject_type (subject), - NM_AUTH_SUBJECT_TYPE_INTERNAL, - NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS), - NULL); - g_return_val_if_fail (action_id, NULL); - - priv = NM_AUTH_MANAGER_GET_PRIVATE (self); - - g_return_val_if_fail (!priv->disposing, NULL); - g_return_val_if_fail (!priv->shutting_down, NULL); - - flags = allow_user_interaction - ? POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION - : POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE; - - 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, - .idle_is_authorized = TRUE, - }; - c_list_link_tail (&priv->calls_lst_head, &call_id->calls_lst); - - if (nm_auth_subject_get_subject_type (subject) == NM_AUTH_SUBJECT_TYPE_INTERNAL) { - _LOG2T (call_id, "CheckAuthorization(%s), subject=%s (succeeding for internal request)", action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf))); - call_id->idle_id = g_idle_add (_call_on_idle, call_id); - } else if (nm_auth_subject_get_unix_process_uid (subject) == 0) { - _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_id = g_idle_add (_call_on_idle, call_id); - } else if (priv->auth_polkit_mode != NM_AUTH_POLKIT_MODE_USE_POLKIT) { - _LOG2T (call_id, "CheckAuthorization(%s), subject=%s (PolicyKit disabled and always %s authorization to non-root user)", action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf)), - priv->auth_polkit_mode == NM_AUTH_POLKIT_MODE_ALLOW_ALL ? "grant" : "deny"); - call_id->idle_is_authorized = (priv->auth_polkit_mode == NM_AUTH_POLKIT_MODE_ALLOW_ALL); - 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_to_polkit_gvariant (subject); - nm_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); - - 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->main_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; + NMAuthManagerPrivate * priv; + PolkitCheckAuthorizationFlags flags; + char subject_buf[64]; + NMAuthManagerCallId * call_id; + + g_return_val_if_fail(NM_IS_AUTH_MANAGER(self), NULL); + g_return_val_if_fail(NM_IN_SET(nm_auth_subject_get_subject_type(subject), + NM_AUTH_SUBJECT_TYPE_INTERNAL, + NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS), + NULL); + g_return_val_if_fail(action_id, NULL); + + priv = NM_AUTH_MANAGER_GET_PRIVATE(self); + + g_return_val_if_fail(!priv->disposing, NULL); + g_return_val_if_fail(!priv->shutting_down, NULL); + + flags = allow_user_interaction ? POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION + : POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE; + + 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, + .idle_is_authorized = TRUE, + }; + c_list_link_tail(&priv->calls_lst_head, &call_id->calls_lst); + + if (nm_auth_subject_get_subject_type(subject) == NM_AUTH_SUBJECT_TYPE_INTERNAL) { + _LOG2T(call_id, + "CheckAuthorization(%s), subject=%s (succeeding for internal request)", + action_id, + nm_auth_subject_to_string(subject, subject_buf, sizeof(subject_buf))); + call_id->idle_id = g_idle_add(_call_on_idle, call_id); + } else if (nm_auth_subject_get_unix_process_uid(subject) == 0) { + _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_id = g_idle_add(_call_on_idle, call_id); + } else if (priv->auth_polkit_mode != NM_AUTH_POLKIT_MODE_USE_POLKIT) { + _LOG2T(call_id, + "CheckAuthorization(%s), subject=%s (PolicyKit disabled and always %s authorization " + "to non-root user)", + action_id, + nm_auth_subject_to_string(subject, subject_buf, sizeof(subject_buf)), + priv->auth_polkit_mode == NM_AUTH_POLKIT_MODE_ALLOW_ALL ? "grant" : "deny"); + call_id->idle_is_authorized = (priv->auth_polkit_mode == NM_AUTH_POLKIT_MODE_ALLOW_ALL); + 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_to_polkit_gvariant(subject); + nm_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); + + 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->main_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; } void -nm_auth_manager_check_authorization_cancel (NMAuthManagerCallId *call_id) +nm_auth_manager_check_authorization_cancel(NMAuthManagerCallId *call_id) { - NMAuthManager *self; - gs_free_error GError *error = NULL; + NMAuthManager *self; + gs_free_error GError *error = NULL; - g_return_if_fail (call_id); + g_return_if_fail(call_id); - self = call_id->self; + self = call_id->self; - g_return_if_fail (NM_IS_AUTH_MANAGER (self)); - g_return_if_fail (!c_list_is_empty (&call_id->calls_lst)); + g_return_if_fail(NM_IS_AUTH_MANAGER(self)); + g_return_if_fail(!c_list_is_empty(&call_id->calls_lst)); - nm_assert (c_list_contains (&NM_AUTH_MANAGER_GET_PRIVATE (self)->calls_lst_head, &call_id->calls_lst)); + nm_assert( + c_list_contains(&NM_AUTH_MANAGER_GET_PRIVATE(self)->calls_lst_head, &call_id->calls_lst)); - nm_utils_error_set_cancelled (&error, FALSE, "NMAuthManager"); - _LOG2T (call_id, "completed: failed due to call cancelled"); - _call_id_invoke_callback (call_id, - FALSE, - FALSE, - error); + nm_utils_error_set_cancelled(&error, FALSE, "NMAuthManager"); + _LOG2T(call_id, "completed: failed due to call cancelled"); + _call_id_invoke_callback(call_id, FALSE, FALSE, error); } /*****************************************************************************/ static void -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) +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; - NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (self); - gboolean valid_sender; + NMAuthManager * self = user_data; + NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE(self); + gboolean valid_sender; - nm_assert (nm_streq0 (signal_name, "Changed")); + nm_assert(nm_streq0(signal_name, "Changed")); - valid_sender = nm_streq0 (priv->name_owner, sender_name); + valid_sender = nm_streq0(priv->name_owner, sender_name); - _LOGD ("dbus-signal: \"Changed\" notification%s", valid_sender ? "" : " (ignore)"); + _LOGD("dbus-signal: \"Changed\" notification%s", valid_sender ? "" : " (ignore)"); - if (valid_sender) - _emit_changed_signal (self); + if (valid_sender) + _emit_changed_signal(self); } static void -_name_owner_changed (NMAuthManager *self, - const char *name_owner, - gboolean is_initial) +_name_owner_changed(NMAuthManager *self, const char *name_owner, gboolean is_initial) { - NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (self); - gboolean is_changed; - gs_free char *old_name_owner = NULL; - - if (is_initial) - priv->got_name_owner = TRUE; - else { - if (!priv->got_name_owner) - return; - } - - name_owner = nm_str_not_empty (name_owner); - - is_changed = !nm_streq0 (priv->name_owner, name_owner); - if (is_changed) { - old_name_owner = g_steal_pointer (&priv->name_owner); - priv->name_owner = g_strdup (name_owner); - } else { - if (!is_initial) - return; - } - - if (!priv->name_owner) { - if (is_initial) - _LOGT ("name-owner: polkit not running"); - else - _LOGT ("name-owner: polkit stopped (was %s)", old_name_owner); - } else { - if (is_initial) - _LOGT ("name-owner: polkit is running (now %s)", priv->name_owner); - else if (old_name_owner) - _LOGT ("name-owner: polkit restarted (now %s, was %s)", priv->name_owner, old_name_owner); - else - _LOGT ("name-owner: polkit started (now %s)", priv->name_owner); - } - - if (priv->name_owner) - _emit_changed_signal (self); + NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE(self); + gboolean is_changed; + gs_free char * old_name_owner = NULL; + + if (is_initial) + priv->got_name_owner = TRUE; + else { + if (!priv->got_name_owner) + return; + } + + name_owner = nm_str_not_empty(name_owner); + + is_changed = !nm_streq0(priv->name_owner, name_owner); + if (is_changed) { + old_name_owner = g_steal_pointer(&priv->name_owner); + priv->name_owner = g_strdup(name_owner); + } else { + if (!is_initial) + return; + } + + if (!priv->name_owner) { + if (is_initial) + _LOGT("name-owner: polkit not running"); + else + _LOGT("name-owner: polkit stopped (was %s)", old_name_owner); + } else { + if (is_initial) + _LOGT("name-owner: polkit is running (now %s)", priv->name_owner); + else if (old_name_owner) + _LOGT("name-owner: polkit restarted (now %s, was %s)", + priv->name_owner, + old_name_owner); + else + _LOGT("name-owner: polkit started (now %s)", priv->name_owner); + } + + if (priv->name_owner) + _emit_changed_signal(self); } static void -_name_owner_changed_cb (GDBusConnection *connection, - const char *sender_name, - const char *object_path, - const char *interface_name, - const char *signal_name, - GVariant *parameters, - gpointer user_data) +_name_owner_changed_cb(GDBusConnection *connection, + const char * sender_name, + const char * object_path, + const char * interface_name, + const char * signal_name, + GVariant * parameters, + gpointer user_data) { - NMAuthManager *self = user_data; - const char *new_owner; + NMAuthManager *self = user_data; + const char * new_owner; - if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(sss)"))) - return; + if (!g_variant_is_of_type(parameters, G_VARIANT_TYPE("(sss)"))) + return; - g_variant_get (parameters, - "(&s&s&s)", - NULL, - NULL, - &new_owner); + g_variant_get(parameters, "(&s&s&s)", NULL, NULL, &new_owner); - _name_owner_changed (self, new_owner, FALSE); + _name_owner_changed(self, new_owner, FALSE); } static void -_name_owner_get_cb (const char *name_owner, - GError *error, - gpointer user_data) +_name_owner_get_cb(const char *name_owner, GError *error, gpointer user_data) { - if (!nm_utils_error_is_cancelled (error)) - _name_owner_changed (user_data, name_owner, TRUE); + if (!nm_utils_error_is_cancelled(error)) + _name_owner_changed(user_data, name_owner, TRUE); } /*****************************************************************************/ NMAuthManager * -nm_auth_manager_get () +nm_auth_manager_get() { - g_return_val_if_fail (singleton_instance, NULL); + g_return_val_if_fail(singleton_instance, NULL); - return singleton_instance; + return singleton_instance; } void -nm_auth_manager_force_shutdown (NMAuthManager *self) +nm_auth_manager_force_shutdown(NMAuthManager *self) { - NMAuthManagerPrivate *priv; - - g_return_if_fail (NM_IS_AUTH_MANAGER (self)); - - priv = NM_AUTH_MANAGER_GET_PRIVATE (self); - - /* FIXME(shutdown): ensure we properly call this API during shutdown as - * described next. */ - - /* while we have pending requests (NMAuthManagerCallId), the instance - * is kept alive. - * - * Even if the caller cancels all pending call-ids, we still need to keep - * a reference to self, in order to handle pending CancelCheckAuthorization - * requests. - * - * To do a coordinated shutdown, do the following: - * - cancel all pending NMAuthManagerCallId requests. - * - ensure everybody unrefs the NMAuthManager instance. If by that, the instance - * gets destroyed, the shutdown already completed successfully. - * - Otherwise, the object is kept alive by pending CancelCheckAuthorization requests. - * wait a certain timeout (1 second) for all requests to complete (by watching - * for destruction of NMAuthManager). - * - if that doesn't happen within timeout, issue nm_auth_manager_force_shutdown() and - * wait longer. After that, soon the instance should be destroyed and you - * did a successful shutdown. - * - if the instance was still not destroyed within a short timeout, you leaked - * resources. You cannot properly shutdown. - */ - - priv->shutting_down = TRUE; - nm_clear_g_cancellable (&priv->main_cancellable); + NMAuthManagerPrivate *priv; + + g_return_if_fail(NM_IS_AUTH_MANAGER(self)); + + priv = NM_AUTH_MANAGER_GET_PRIVATE(self); + + /* FIXME(shutdown): ensure we properly call this API during shutdown as + * described next. */ + + /* while we have pending requests (NMAuthManagerCallId), the instance + * is kept alive. + * + * Even if the caller cancels all pending call-ids, we still need to keep + * a reference to self, in order to handle pending CancelCheckAuthorization + * requests. + * + * To do a coordinated shutdown, do the following: + * - cancel all pending NMAuthManagerCallId requests. + * - ensure everybody unrefs the NMAuthManager instance. If by that, the instance + * gets destroyed, the shutdown already completed successfully. + * - Otherwise, the object is kept alive by pending CancelCheckAuthorization requests. + * wait a certain timeout (1 second) for all requests to complete (by watching + * for destruction of NMAuthManager). + * - if that doesn't happen within timeout, issue nm_auth_manager_force_shutdown() and + * wait longer. After that, soon the instance should be destroyed and you + * did a successful shutdown. + * - if the instance was still not destroyed within a short timeout, you leaked + * resources. You cannot properly shutdown. + */ + + priv->shutting_down = TRUE; + nm_clear_g_cancellable(&priv->main_cancellable); } /*****************************************************************************/ static void -set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { - NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (object); - int v_int; - - switch (prop_id) { - case PROP_POLKIT_ENABLED: - /* construct-only */ - v_int = g_value_get_int (value); - g_return_if_fail (NM_IN_SET (v_int, NM_AUTH_POLKIT_MODE_ROOT_ONLY, - NM_AUTH_POLKIT_MODE_ALLOW_ALL, - NM_AUTH_POLKIT_MODE_USE_POLKIT)); - priv->auth_polkit_mode = v_int; - nm_assert (priv->auth_polkit_mode == v_int); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } + NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE(object); + int v_int; + + switch (prop_id) { + case PROP_POLKIT_ENABLED: + /* construct-only */ + v_int = g_value_get_int(value); + g_return_if_fail(NM_IN_SET(v_int, + NM_AUTH_POLKIT_MODE_ROOT_ONLY, + NM_AUTH_POLKIT_MODE_ALLOW_ALL, + NM_AUTH_POLKIT_MODE_USE_POLKIT)); + priv->auth_polkit_mode = v_int; + nm_assert(priv->auth_polkit_mode == v_int); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } } /*****************************************************************************/ static void -nm_auth_manager_init (NMAuthManager *self) +nm_auth_manager_init(NMAuthManager *self) { - NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (self); + NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE(self); - c_list_init (&priv->calls_lst_head); - priv->auth_polkit_mode = NM_AUTH_POLKIT_MODE_ROOT_ONLY; + c_list_init(&priv->calls_lst_head); + priv->auth_polkit_mode = NM_AUTH_POLKIT_MODE_ROOT_ONLY; } static void -constructed (GObject *object) +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); - - if (priv->auth_polkit_mode != NM_AUTH_POLKIT_MODE_USE_POLKIT) { - if (priv->auth_polkit_mode == NM_AUTH_POLKIT_MODE_ROOT_ONLY) - create_message = "polkit disabled, root-only"; - else - create_message = "polkit disabled, allow-all"; - 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 only root will be authorized."; - priv->auth_polkit_mode = NM_AUTH_POLKIT_MODE_ROOT_ONLY; - goto out; - } - - priv->main_cancellable = g_cancellable_new (); - - priv->name_owner_changed_id = nm_dbus_connection_signal_subscribe_name_owner_changed (priv->dbus_connection, - POLKIT_SERVICE, - _name_owner_changed_cb, - self, - NULL); - - priv->changed_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); - - nm_dbus_connection_call_get_name_owner (priv->dbus_connection, - POLKIT_SERVICE, - -1, - priv->main_cancellable, - _name_owner_get_cb, - self); - - create_message = "polkit enabled"; + 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); + + if (priv->auth_polkit_mode != NM_AUTH_POLKIT_MODE_USE_POLKIT) { + if (priv->auth_polkit_mode == NM_AUTH_POLKIT_MODE_ROOT_ONLY) + create_message = "polkit disabled, root-only"; + else + create_message = "polkit disabled, allow-all"; + 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 only root will be authorized."; + priv->auth_polkit_mode = NM_AUTH_POLKIT_MODE_ROOT_ONLY; + goto out; + } + + priv->main_cancellable = g_cancellable_new(); + + priv->name_owner_changed_id = + nm_dbus_connection_signal_subscribe_name_owner_changed(priv->dbus_connection, + POLKIT_SERVICE, + _name_owner_changed_cb, + self, + NULL); + + priv->changed_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); + + nm_dbus_connection_call_get_name_owner(priv->dbus_connection, + POLKIT_SERVICE, + -1, + priv->main_cancellable, + _name_owner_get_cb, + self); + + create_message = "polkit enabled"; out: - _NMLOG (logl, "create auth-manager: %s", create_message); + _NMLOG(logl, "create auth-manager: %s", create_message); } NMAuthManager * -nm_auth_manager_setup (NMAuthPolkitMode auth_polkit_mode) +nm_auth_manager_setup(NMAuthPolkitMode auth_polkit_mode) { - NMAuthManager *self; + NMAuthManager *self; - g_return_val_if_fail (!singleton_instance, singleton_instance); - nm_assert (NM_IN_SET (auth_polkit_mode, NM_AUTH_POLKIT_MODE_ROOT_ONLY, - NM_AUTH_POLKIT_MODE_ALLOW_ALL, - NM_AUTH_POLKIT_MODE_USE_POLKIT)); + g_return_val_if_fail(!singleton_instance, singleton_instance); + nm_assert(NM_IN_SET(auth_polkit_mode, + NM_AUTH_POLKIT_MODE_ROOT_ONLY, + NM_AUTH_POLKIT_MODE_ALLOW_ALL, + NM_AUTH_POLKIT_MODE_USE_POLKIT)); - self = g_object_new (NM_TYPE_AUTH_MANAGER, - NM_AUTH_MANAGER_POLKIT_ENABLED, (int) auth_polkit_mode, - NULL); - _LOGD ("set instance"); + self = g_object_new(NM_TYPE_AUTH_MANAGER, + NM_AUTH_MANAGER_POLKIT_ENABLED, + (int) auth_polkit_mode, + NULL); + _LOGD("set instance"); - singleton_instance = self; - nm_singleton_instance_register (); + singleton_instance = self; + nm_singleton_instance_register(); - nm_log_dbg (LOGD_CORE, "setup %s singleton ("NM_HASH_OBFUSCATE_PTR_FMT")", - "NMAuthManager", NM_HASH_OBFUSCATE_PTR (singleton_instance)); + nm_log_dbg(LOGD_CORE, + "setup %s singleton (" NM_HASH_OBFUSCATE_PTR_FMT ")", + "NMAuthManager", + NM_HASH_OBFUSCATE_PTR(singleton_instance)); - return self; + return self; } static void -dispose (GObject *object) +dispose(GObject *object) { - NMAuthManager* self = NM_AUTH_MANAGER (object); - NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (self); + NMAuthManager * self = NM_AUTH_MANAGER(object); + NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE(self); - _LOGD ("dispose"); + _LOGD("dispose"); - nm_assert (c_list_is_empty (&priv->calls_lst_head)); + nm_assert(c_list_is_empty(&priv->calls_lst_head)); - priv->disposing = TRUE; + priv->disposing = TRUE; - nm_clear_g_cancellable (&priv->main_cancellable); + nm_clear_g_cancellable(&priv->main_cancellable); - nm_clear_g_dbus_connection_signal (priv->dbus_connection, - &priv->name_owner_changed_id); + nm_clear_g_dbus_connection_signal(priv->dbus_connection, &priv->name_owner_changed_id); - nm_clear_g_dbus_connection_signal (priv->dbus_connection, - &priv->changed_id); + nm_clear_g_dbus_connection_signal(priv->dbus_connection, &priv->changed_id); - G_OBJECT_CLASS (nm_auth_manager_parent_class)->dispose (object); + G_OBJECT_CLASS(nm_auth_manager_parent_class)->dispose(object); - g_clear_object (&priv->dbus_connection); + g_clear_object(&priv->dbus_connection); - nm_clear_g_free (&priv->name_owner); + nm_clear_g_free(&priv->name_owner); } static void -nm_auth_manager_class_init (NMAuthManagerClass *klass) +nm_auth_manager_class_init(NMAuthManagerClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->set_property = set_property; - object_class->constructed = constructed; - object_class->dispose = dispose; - - obj_properties[PROP_POLKIT_ENABLED] = - g_param_spec_int (NM_AUTH_MANAGER_POLKIT_ENABLED, "", "", - NM_AUTH_POLKIT_MODE_ROOT_ONLY, NM_AUTH_POLKIT_MODE_USE_POLKIT, NM_AUTH_POLKIT_MODE_USE_POLKIT, - G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - signals[CHANGED_SIGNAL] = g_signal_new (NM_AUTH_MANAGER_SIGNAL_CHANGED, - NM_TYPE_AUTH_MANAGER, - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); + GObjectClass *object_class = G_OBJECT_CLASS(klass); + + object_class->set_property = set_property; + object_class->constructed = constructed; + object_class->dispose = dispose; + + obj_properties[PROP_POLKIT_ENABLED] = + g_param_spec_int(NM_AUTH_MANAGER_POLKIT_ENABLED, + "", + "", + NM_AUTH_POLKIT_MODE_ROOT_ONLY, + NM_AUTH_POLKIT_MODE_USE_POLKIT, + NM_AUTH_POLKIT_MODE_USE_POLKIT, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + signals[CHANGED_SIGNAL] = g_signal_new(NM_AUTH_MANAGER_SIGNAL_CHANGED, + NM_TYPE_AUTH_MANAGER, + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); } |