diff options
-rw-r--r-- | Makefile.am | 10 | ||||
-rw-r--r-- | clients/cli/agent.c | 36 | ||||
-rw-r--r-- | clients/cli/meson.build | 29 | ||||
-rw-r--r-- | clients/cli/polkit-agent.c | 97 | ||||
-rw-r--r-- | clients/common/meson.build | 3 | ||||
-rw-r--r-- | clients/common/nm-polkit-listener.c | 1042 | ||||
-rw-r--r-- | clients/common/nm-polkit-listener.h | 133 | ||||
-rw-r--r-- | config.h.meson | 4 | ||||
-rw-r--r-- | configure.ac | 18 | ||||
-rw-r--r-- | contrib/fedora/rpm/NetworkManager.spec | 2 | ||||
-rw-r--r-- | meson.build | 10 |
11 files changed, 911 insertions, 473 deletions
diff --git a/Makefile.am b/Makefile.am index c213eb75c7..249a188c81 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4255,6 +4255,8 @@ clients_common_libnmc_base_la_SOURCES = \ clients/common/nm-vpn-helpers.h \ clients/common/nm-client-utils.c \ clients/common/nm-client-utils.h \ + clients/common/nm-polkit-listener.c \ + clients/common/nm-polkit-listener.h \ $(NULL) EXTRA_DIST += \ @@ -4446,14 +4448,6 @@ clients_cli_nmcli_LDADD = \ $(GLIB_LIBS) \ $(READLINE_LIBS) -if WITH_POLKIT_AGENT -clients_cli_nmcli_CPPFLAGS += $(POLKIT_CFLAGS) -clients_cli_nmcli_SOURCES += \ - clients/common/nm-polkit-listener.c \ - clients/common/nm-polkit-listener.h -clients_cli_nmcli_LDADD += $(POLKIT_LIBS) -endif - clients_cli_nmcli_LDFLAGS = \ -Wl,--version-script="$(srcdir)/linker-script-binary.ver" \ $(SANITIZER_EXEC_LDFLAGS) diff --git a/clients/cli/agent.c b/clients/cli/agent.c index f4057df9e9..93b5ca079a 100644 --- a/clients/cli/agent.c +++ b/clients/cli/agent.c @@ -16,6 +16,7 @@ #include "utils.h" #include "nm-secret-agent-simple.h" #include "polkit-agent.h" +#include "nm-polkit-listener.h" static void usage (void) @@ -149,27 +150,50 @@ do_agent_secret (NmCli *nmc, int argc, char **argv) return nmc->return_value; } +static void +polkit_registered (gpointer instance, + gpointer user_data) +{ + g_print (_("nmcli successfully registered as a polkit agent.\n")); +} + +static void +polkit_error (gpointer instance, + const char *error, + gpointer user_data) +{ + g_main_loop_quit (loop); +} + static NMCResultCode do_agent_polkit (NmCli *nmc, int argc, char **argv) { - GError *error = NULL; + gs_free_error GError *error = NULL; next_arg (nmc, &argc, &argv, NULL); if (nmc->complete) return nmc->return_value; - /* Initialize polkit agent */ if (!nmc_polkit_agent_init (nmc, TRUE, &error)) { g_dbus_error_strip_remote_error (error); - g_string_printf (nmc->return_text, _("Error: polkit agent initialization failed: %s"), + g_string_printf (nmc->return_text, + _("Error: polkit agent initialization failed: %s"), error->message); nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; - g_error_free (error); } else { /* We keep running */ nmc->should_wait++; - - g_print (_("nmcli successfully registered as a polkit agent.\n")); + g_signal_connect (nmc->pk_listener, + NM_POLKIT_LISTENER_SIGNAL_ERROR, + G_CALLBACK (polkit_error), + NULL); + g_signal_connect (nmc->pk_listener, + NM_POLKIT_LISTENER_SIGNAL_REGISTERED, + G_CALLBACK (polkit_registered), + NULL); + + /* keep running */ + nmc->should_wait++; } return nmc->return_value; diff --git a/clients/cli/meson.build b/clients/cli/meson.build index 1c8148920c..b1b2426910 100644 --- a/clients/cli/meson.build +++ b/clients/cli/meson.build @@ -6,18 +6,6 @@ install_data( install_dir: join_paths(nm_datadir, 'bash-completion', 'completions'), ) -sources = files( - 'agent.c', - 'common.c', - 'connections.c', - 'devices.c', - 'general.c', - 'nmcli.c', - 'polkit-agent.c', - 'settings.c', - 'utils.c', -) - deps = [ libnmc_base_dep, libnmc_dep, @@ -25,14 +13,19 @@ deps = [ libnm_libnm_aux_dep, ] -if enable_polkit_agent - sources += nm_polkit_listener - deps += polkit_agent_dep -endif - executable( name, - sources, + files( + 'agent.c', + 'common.c', + 'connections.c', + 'devices.c', + 'general.c', + 'nmcli.c', + 'polkit-agent.c', + 'settings.c', + 'utils.c', + ), dependencies: deps, c_args: clients_c_flags + ['-DG_LOG_DOMAIN="@0@"'.format(name)], link_args: ldflags_linker_script_binary, diff --git a/clients/cli/polkit-agent.c b/clients/cli/polkit-agent.c index 69bfb68dd3..376a2f5d52 100644 --- a/clients/cli/polkit-agent.c +++ b/clients/cli/polkit-agent.c @@ -14,16 +14,12 @@ #include "nm-polkit-listener.h" #include "common.h" -#if WITH_POLKIT_AGENT static char * -polkit_request (NMPolkitListener *listener, - const char *request, - const char *action_id, - const char *message, - const char *icon_name, - const char *user, - gboolean echo_on, - gpointer user_data) +polkit_read_passwd (gpointer instance, + const char *action_id, + const char *message, + const char *user, + gpointer user_data) { NmCli *nmc = user_data; @@ -32,87 +28,68 @@ polkit_request (NMPolkitListener *listener, /* Ask user for polkit authorization password */ if (user) { - gs_free char *tmp = NULL; - char *p; - - /* chop of ": " if present */ - tmp = g_strdup (request); - p = strrchr (tmp, ':'); - if (p && nm_streq (p, ": ")) - *p = '\0'; - return nmc_readline_echo (&nmc->nmc_config, echo_on, "%s (%s): ", tmp, user); + return nmc_readline_echo (&nmc->nmc_config, FALSE, "password (%s): ", user); } - - return nmc_readline_echo (&nmc->nmc_config, echo_on, "%s", request); + return nmc_readline_echo (&nmc->nmc_config, FALSE, "password: "); } static void -polkit_show_info (NMPolkitListener *listener, - const char *text, - gpointer user_data) +polkit_error (gpointer instance, + const char *error, + gpointer user_data) { - g_print (_("Authentication message: %s\n"), text); + g_printerr (_("Error: polkit agent failed: %s\n"), error); } -static void -polkit_show_error (NMPolkitListener *listener, - const char *text, - gpointer user_data) -{ - g_print (_("Authentication error: %s\n"), text); -} - -static void -polkit_completed (NMPolkitListener *listener, - gboolean gained_authorization, - gpointer user_data) -{ - /* We don't print anything here. The outcome will be evident from - * the operation result anyway. */ -} -#endif - gboolean nmc_polkit_agent_init (NmCli* nmc, gboolean for_session, GError **error) { -#if WITH_POLKIT_AGENT - static const NMPolkitListenVtable vtable = { - .on_request = polkit_request, - .on_show_info = polkit_show_info, - .on_show_error = polkit_show_error, - .on_completed = polkit_completed, - }; NMPolkitListener *listener; + GDBusConnection *dbus_connection = NULL; g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - listener = nm_polkit_listener_new (for_session, error); - if (!listener) - return FALSE; + if (nmc->client && nm_client_get_dbus_connection (nmc->client)) { + dbus_connection = nm_client_get_dbus_connection (nmc->client); + listener = nm_polkit_listener_new (dbus_connection, for_session); + } else { + dbus_connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, + NULL, + error); + + if (!dbus_connection) { + return FALSE; + } + + listener = nm_polkit_listener_new (dbus_connection, for_session); + g_object_unref (dbus_connection); + } - nm_polkit_listener_set_vtable (listener, &vtable, nmc); + g_signal_connect (listener, + NM_POLKIT_LISTENER_SIGNAL_REQUEST, + G_CALLBACK (polkit_read_passwd), + nmc); + g_signal_connect (listener, + NM_POLKIT_LISTENER_SIGNAL_ERROR, + G_CALLBACK (polkit_error), + NULL); nmc->pk_listener = listener; -#endif return TRUE; } void nmc_polkit_agent_fini (NmCli* nmc) { -#if WITH_POLKIT_AGENT if (nmc->pk_listener) { - nm_polkit_listener_set_vtable (nmc->pk_listener, NULL, NULL); g_clear_object (&nmc->pk_listener); } -#endif } gboolean nmc_start_polkit_agent_start_try (NmCli *nmc) { -#if WITH_POLKIT_AGENT - GError *error = NULL; + gs_free_error GError *error = NULL; /* We don't register polkit agent at all when running non-interactively */ if (!nmc->ask) @@ -121,9 +98,7 @@ nmc_start_polkit_agent_start_try (NmCli *nmc) if (!nmc_polkit_agent_init (nmc, FALSE, &error)) { g_printerr (_("Warning: polkit agent initialization failed: %s\n"), error->message); - g_error_free (error); return FALSE; } -#endif return TRUE; } diff --git a/clients/common/meson.build b/clients/common/meson.build index afa257b1df..f68435ec9e 100644 --- a/clients/common/meson.build +++ b/clients/common/meson.build @@ -1,7 +1,5 @@ common_inc = include_directories('.') -nm_polkit_listener = files('nm-polkit-listener.c') - common_deps = [ libnm_dep, libnm_nm_default_dep, @@ -13,6 +11,7 @@ sources = files( 'nm-client-utils.c', 'nm-secret-agent-simple.c', 'nm-vpn-helpers.c', + 'nm-polkit-listener.c', ) libnmc_base = static_library( diff --git a/clients/common/nm-polkit-listener.c b/clients/common/nm-polkit-listener.c index b294165237..f1c1ba45a6 100644 --- a/clients/common/nm-polkit-listener.c +++ b/clients/common/nm-polkit-listener.c @@ -22,339 +22,917 @@ #include "nm-polkit-listener.h" -#include <stdio.h> -#include <stdlib.h> +#include <gio/gio.h> +#include <glib-unix.h> +#include <pwd.h> -#if WITH_POLKIT_AGENT +#include "nm-glib-aux/nm-dbus-aux.h" +#include "nm-glib-aux/nm-secret-utils.h" +#include "nm-glib-aux/nm-io-utils.h" +#include "nm-libnm-core-intern/nm-auth-subject.h" +#include "c-list/src/c-list.h" + +#define LOGIND_BUS_NAME "org.freedesktop.login1" +#define POLKIT_BUS_NAME "org.freedesktop.PolicyKit1" + +#define POLKIT_AUTHORITY_OBJ_PATH "/org/freedesktop/PolicyKit1/Authority" +#define POLKIT_AUTHORITY_IFACE_NAME "org.freedesktop.PolicyKit1.Authority" + +#define POLKIT_AGENT_OBJ_PATH "/org/freedesktop/PolicyKit1/AuthenticationAgent" +#define POLKIT_AGENT_DBUS_INTERFACE "org.freedesktop.PolicyKit1.AuthenticationAgent" + +#define LOGIND_OBJ_PATH "/org/freedesktop/login1" +#define LOGIND_MANAGER_INTERFACE "org.freedesktop.login1.Manager" + +#define NM_POLKIT_LISTENER_DBUS_CONNECTION "dbus-connection" +#define NM_POLKIT_LISTENER_SESSION_AGENT "session-agent" /*****************************************************************************/ -typedef struct { - gpointer reg_handle; /* handle of polkit agent registration */ +enum { + REGISTERED, + REQUEST, + ERROR, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +struct _NMPolkitListener { + GObject parent; - GSimpleAsyncResult *simple; - PolkitAgentSession *active_session; - gulong cancel_id; + GDBusConnection *dbus_connection; + char *name_owner; + guint pk_auth_agent_reg_id; + guint name_owner_changed_id; GCancellable *cancellable; + GMainContext *main_context; + gboolean session_agent; + CList request_lst_head; +}; + +G_DEFINE_TYPE (NMPolkitListener, nm_polkit_listener, G_TYPE_OBJECT) + +/*****************************************************************************/ + +typedef struct { + CList request_lst; + NMPolkitListener *listener; char *action_id; char *message; - char *icon_name; - char *identity; + char *username; + char *cookie; + GString *in_buffer; + GString *out_buffer; + size_t out_buffer_offset; + + int child_stdout; + int child_stdin; + GSource *child_stdout_watch_source; + GSource *child_stdin_watch_source; + GDBusMethodInvocation *dbus_invocation; +} AuthRequest; + +static const GDBusInterfaceInfo interface_info = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( + POLKIT_AGENT_DBUS_INTERFACE, + .methods = NM_DEFINE_GDBUS_METHOD_INFOS ( + NM_DEFINE_GDBUS_METHOD_INFO ( + "BeginAuthentication", + .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( + NM_DEFINE_GDBUS_ARG_INFO ("action_id", "s"), + NM_DEFINE_GDBUS_ARG_INFO ("message", "s"), + NM_DEFINE_GDBUS_ARG_INFO ("icon_name", "s"), + NM_DEFINE_GDBUS_ARG_INFO ("details", "a{ss}"), + NM_DEFINE_GDBUS_ARG_INFO ("cookie", "s"), + NM_DEFINE_GDBUS_ARG_INFO ("identities", "a(sa{sv})"), + ), + ), + NM_DEFINE_GDBUS_METHOD_INFO ( + "CancelAuthentication", + .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( + NM_DEFINE_GDBUS_ARG_INFO ("cookie", "s"), + ), + ), + ), +); - const NMPolkitListenVtable *vtable; - gpointer vtable_user_data; -} NMPolkitListenerPrivate; +static void +remove_request (AuthRequest *request) +{ + c_list_unlink (&request->request_lst); + + nm_clear_g_free (&request->action_id); + nm_clear_g_free (&request->message); + nm_clear_g_free (&request->username); + nm_clear_g_free (&request->cookie); + nm_clear_g_source_inst (&request->child_stdout_watch_source); + nm_clear_g_source_inst (&request->child_stdin_watch_source); + + nm_explicit_bzero (request->out_buffer->str, + request->out_buffer->len); + g_string_free (request->out_buffer, TRUE); + g_string_free (request->in_buffer, TRUE); + + if (request->child_stdout != -1) { + nm_close (request->child_stdout); + request->child_stdout = -1; + } -G_DEFINE_TYPE (NMPolkitListener, nm_polkit_listener, POLKIT_AGENT_TYPE_LISTENER) + if (request->child_stdin != -1) { + nm_close (request->child_stdin); + request->child_stdin = -1; + } -#define NM_POLKIT_LISTENER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_POLKIT_LISTENER, NMPolkitListenerPrivate)) + g_slice_free (AuthRequest, request); +} -/*****************************************************************************/ +static const char * +uid_to_name (uid_t uid) +{ + const char *name = NULL; + struct passwd *passwd; + + passwd = getpwuid (uid); + if (passwd != NULL) + name = passwd->pw_name; + return name; +} -void -nm_polkit_listener_set_vtable (NMPolkitListener *self, - const NMPolkitListenVtable *vtable, - gpointer user_data) +static gboolean +find_identity (uid_t uid, gpointer user_data) { - NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (self); + return nm_streq0 (user_data, uid_to_name (uid)); +} - priv->vtable = vtable; - priv->vtable_user_data = user_data; +static gboolean +first_identity (uid_t uid, gpointer user_data) +{ + return true; } -/*****************************************************************************/ +static gint64 +_choose_identity (GVariant *identities, + gboolean (*predicate) (uid_t uid, gpointer user_data), + gpointer user_data) +{ + GVariantIter identity_iter; + GVariantIter *identity_details_iter; + GVariant *unix_id_variant; + uid_t unix_id; + + g_return_val_if_fail (predicate != NULL, FALSE); + + g_variant_iter_init (&identity_iter, identities); + + while (g_variant_iter_loop (&identity_iter, "(&sa{sv})", NULL, &identity_details_iter)) { + while (g_variant_iter_loop (identity_details_iter, "{sv}", NULL, &unix_id_variant)) { + unix_id = g_variant_get_uint32 (unix_id_variant); + + if (predicate (unix_id, user_data)) { + g_variant_unref (unix_id_variant); + g_variant_iter_free (identity_details_iter); + return unix_id; + } + } + g_variant_iter_free (identity_details_iter); + } + return -1; +} + +static uid_t +choose_identity (GVariant *identities) +{ + const char *user; + gint64 id; + + /* Choose identity. First try current user, then root, and else + * take the first one */ + user = getenv ("USER"); + + if ((id = _choose_identity (identities, find_identity, (gpointer) user)) >= 0) { + return id; + } else if ((id = _choose_identity (identities, find_identity, "root")) >= 0) { + return id; + } + + return _choose_identity (identities, first_identity, NULL); +} static void -on_request (PolkitAgentSession *session, - const char *request, - gboolean echo_on, - gpointer user_data) +agent_register_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) { - NMPolkitListener *self = NM_POLKIT_LISTENER (user_data); - NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (self); - gs_free char *response = NULL; + NMPolkitListener *listener = NM_POLKIT_LISTENER (user_data); + GDBusConnection *dbus_connection = G_DBUS_CONNECTION (source_object); + gs_free_error GError *error = NULL; + gs_unref_variant GVariant *ret = NULL; + + ret = g_dbus_connection_call_finish (dbus_connection, + res, + &error); - if (priv->vtable && priv->vtable->on_request) { - response = priv->vtable->on_request (self, - request, priv->action_id, - priv->message, priv->icon_name, - priv->identity, echo_on, - priv->vtable_user_data); + if (nm_utils_error_is_cancelled (error, FALSE)) { + return; } - if (response) - polkit_agent_session_response (session, response); - else { - //FIXME: polkit_agent_session_cancel() should emit "completed", but it doesn't work for me ??? - //polkit_agent_session_cancel (session); - polkit_agent_session_response (session, ""); + if (ret) { + g_signal_emit (listener, + signals[REGISTERED], + 0); + } else { + g_signal_emit (listener, + signals[ERROR], + 0, + error->message); } } static void -on_show_info (PolkitAgentSession *session, - const char *text, - gpointer user_data) +agent_register (NMPolkitListener *self, const char *session_id) { - NMPolkitListener *self = NM_POLKIT_LISTENER (user_data); - NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (self); + const char *locale = NULL; + gs_unref_object NMAuthSubject *subject = NULL; + GVariant *subject_variant = NULL; + + locale = g_getenv ("LANG"); + if (locale == NULL) { + locale = "en_US.UTF-8"; + } - if (priv->vtable && priv->vtable->on_show_info) { - priv->vtable->on_show_info (self, text, - priv->vtable_user_data); + if (self->session_agent) { + subject = nm_auth_subject_new_unix_session (session_id); + } else { + subject = nm_auth_subject_new_unix_process_self (); } + subject_variant = nm_auth_subject_unix_to_polkit_gvariant (subject); + + g_dbus_connection_call (self->dbus_connection, + self->name_owner, + POLKIT_AUTHORITY_OBJ_PATH, + POLKIT_AUTHORITY_IFACE_NAME, + "RegisterAuthenticationAgent", + g_variant_new ("(@(sa{sv})ss)", + subject_variant, + locale, + POLKIT_AGENT_OBJ_PATH), + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + self->cancellable, + agent_register_cb, + self); } static void -on_show_error (PolkitAgentSession *session, - const char *text, - gpointer user_data) +agent_unregister (NMPolkitListener *self) { - NMPolkitListener *self = NM_POLKIT_LISTENER (user_data); - NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (self); + gs_unref_object NMAuthSubject *subject = NULL; + GVariant *subject_variant = NULL; + + subject = nm_auth_subject_new_unix_process_self (); + subject_variant = nm_auth_subject_unix_to_polkit_gvariant (subject); + + g_dbus_connection_call (self->dbus_connection, + self->name_owner, + POLKIT_AUTHORITY_OBJ_PATH, + POLKIT_AUTHORITY_IFACE_NAME, + "UnregisterAuthenticationAgent", + g_variant_new ("(@(sa{sv})s)", + subject_variant, + POLKIT_AGENT_OBJ_PATH), + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + NULL, + self); +} - if (priv->vtable && priv->vtable->on_show_error) { - priv->vtable->on_show_error (self, text, - priv->vtable_user_data); +static void +retrieve_session_id_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + NMPolkitListener *listener = NM_POLKIT_LISTENER (user_data); + char *session_id; + guint32 session_uid; + nm_auto_free_variant_iter GVariantIter *iter; + gs_unref_variant GVariant *ret = NULL; + gs_free_error GError *error = NULL; + gs_free char *err_str = NULL; + uid_t uid = getuid (); + + ret = g_dbus_connection_call_finish (listener->dbus_connection, + res, + &error); + + if (nm_utils_error_is_cancelled (error, FALSE)) { + return; } + + if (ret) { + g_variant_get_child (ret, 0, "a(susso)", &iter); + + while (g_variant_iter_next (iter, "(&su@s@s@o)", + &session_id, + &session_uid, + NULL, NULL, NULL)) { + if (session_uid == uid) { + agent_register (listener, session_id); + return; + } + } + } + + err_str = g_strdup_printf (_("Could not retrieve session id: %s"), + error->message); + + g_signal_emit (listener, + signals[ERROR], + 0, + err_str); } static void -on_completed (PolkitAgentSession *session, - gboolean gained_authorization, - gpointer user_data) +retrieve_session_id (NMPolkitListener *self) { - NMPolkitListener *self = NM_POLKIT_LISTENER (user_data); - NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (self); + g_dbus_connection_call (self->dbus_connection, + LOGIND_BUS_NAME, + LOGIND_OBJ_PATH, + LOGIND_MANAGER_INTERFACE, + "ListSessions", + NULL, + G_VARIANT_TYPE ("(a(susso))"), + G_DBUS_CALL_FLAGS_NONE, + -1, + self->cancellable, + retrieve_session_id_cb, + self); +} + +static void +complete_authentication (AuthRequest *request, + gboolean result) +{ + if (result) { + g_dbus_method_invocation_return_value (request->dbus_invocation, NULL); + } else { + g_dbus_method_invocation_return_dbus_error (request->dbus_invocation, + "org.freedesktop.PolicyKit1.Error.Failed", + ""); + } + remove_request (request); +} - if (priv->vtable->on_completed) { - priv->vtable->on_completed (self, gained_authorization, - priv->vtable_user_data); +static gboolean +io_watch_can_write (int fd, + GIOCondition condition, + gpointer user_data) +{ + AuthRequest *request = user_data; + ssize_t n_written; + gboolean done = FALSE; + + if (condition & G_IO_HUP || + condition & G_IO_ERR) { + done = TRUE; + goto done; } - g_simple_async_result_complete_in_idle (priv->simple); + n_written = write (request->child_stdin, + &request->out_buffer->str[request->out_buffer_offset], + request->out_buffer->len - request->out_buffer_offset); + + if (n_written < 0 && errno != EAGAIN) { + done = TRUE; + goto done; + } - g_object_unref (priv->simple); - g_object_unref (priv->active_session); - if (priv->cancellable) { - g_cancellable_disconnect (priv->cancellable, priv->cancel_id); - g_object_unref (priv->cancellable); + if (n_written > 0) { + if ((size_t) n_written == (request->out_buffer->len - request->out_buffer_offset)) { + done = TRUE; + goto done; + } + request->out_buffer_offset += n_written; } - priv->simple = NULL; - priv->active_session = NULL; - priv->cancel_id = 0; +done: + if (done) { + nm_explicit_bzero (request->out_buffer->str, + request->out_buffer->len); + g_string_set_size (request->out_buffer, 0); + request->out_buffer_offset = 0; + nm_clear_g_source_inst (&request->child_stdin_watch_source); + } - g_clear_pointer (&priv->action_id, g_free); - g_clear_pointer (&priv->message, g_free); - g_clear_pointer (&priv->icon_name, g_free); - g_clear_pointer (&priv->identity, g_free); + return G_SOURCE_CONTINUE; } static void -on_cancelled (GCancellable *cancellable, gpointer user_data) +queue_string_to_helper (AuthRequest *request, const char *response) { - NMPolkitListener *self = NM_POLKIT_LISTENER (user_data); - NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (self); + g_return_if_fail (response); + + g_string_append (request->out_buffer, response); + + if ( request->out_buffer->len == 0 + || request->out_buffer->str[request->out_buffer->len - 1] != '\n') + g_string_append_c (request->out_buffer, '\n'); + + if (!request->child_stdin_watch_source) { + request->child_stdin_watch_source = g_unix_fd_source_new (request->child_stdin, + G_IO_OUT | G_IO_ERR | G_IO_HUP); + g_source_set_callback (request->child_stdin_watch_source, + G_SOURCE_FUNC (io_watch_can_write), + request, + NULL); + g_source_attach (request->child_stdin_watch_source, + request->listener->main_context); + } +} - polkit_agent_session_cancel (priv->active_session); +static gboolean +io_watch_have_data (int fd, + GIOCondition condition, + gpointer user_data) +{ + AuthRequest *request = user_data; + gs_free char *unescaped = NULL; + char *response = NULL; + char* line_terminator = 0; + gboolean auth_result = FALSE; + gboolean complete_auth = FALSE; + ssize_t n_read; + + if (condition & G_IO_HUP || + condition & G_IO_ERR) { + complete_auth = TRUE; + auth_result = FALSE; + goto out; + } + + n_read = nm_utils_fd_read (fd, request->in_buffer); + + if (n_read == -EAGAIN) { + return G_SOURCE_CONTINUE; + } + + if (n_read < 0) { + complete_auth = TRUE; + auth_result = FALSE; + goto out; + } + + line_terminator = strchr (request->in_buffer->str, '\n'); + if (!line_terminator) { + return G_SOURCE_CONTINUE; + } + *line_terminator = '\0'; + + unescaped = g_strcompress (request->in_buffer->str); + + if (NM_STR_HAS_PREFIX (unescaped, "PAM_PROMPT_ECHO")) { + /* emit signal and wait for response */ + g_signal_emit (request->listener, + signals[REQUEST], + 0, + request->action_id, + request->message, + request->username, + &response); + + if (response) { + queue_string_to_helper (request, response); + nm_free_secret (response); + } else { + complete_auth = TRUE; + auth_result = FALSE; + } + } else if (NM_STR_HAS_PREFIX (unescaped, "SUCCESS")) { + complete_auth = TRUE; + auth_result = TRUE; + } else if (NM_STR_HAS_PREFIX (unescaped, "FAILURE")) { + complete_auth = TRUE; + auth_result = FALSE; + } else { + complete_auth = TRUE; + auth_result = FALSE; + } + +out: + g_string_set_size (request->in_buffer, 0); + + if (complete_auth) { + complete_authentication (request, auth_result); + } + return G_SOURCE_CONTINUE; } -static int -compare_users (gconstpointer a, gconstpointer b) +static void +begin_authentication (AuthRequest *request) { - char *user; - int ret; + int fd_flags; + char *helper_argv[3]; + + helper_argv[0] = POLKIT_PACKAGE_PREFIX "/lib/polkit-1/polkit-agent-helper-1"; + helper_argv[1] = request->username; + helper_argv[2] = NULL; + + if (!g_spawn_async_with_pipes (NULL, + helper_argv, + NULL, + G_SPAWN_DEFAULT, + NULL, + NULL, + NULL, + &request->child_stdin, + &request->child_stdout, + NULL, + NULL)) { + complete_authentication (request, FALSE); + return; + } + + fd_flags = fcntl (request->child_stdin, F_GETFD, 0); + fcntl (request->child_stdin, F_SETFL, fd_flags | O_NONBLOCK); + + fd_flags = fcntl (request->child_stdout, F_GETFD, 0); + fcntl (request->child_stdout, F_SETFL, fd_flags | O_NONBLOCK); - if (POLKIT_IS_UNIX_USER (a)) - user = g_strdup (polkit_unix_user_get_name (POLKIT_UNIX_USER (a))); - else - user = polkit_identity_to_string (POLKIT_IDENTITY (a)); + request->child_stdout_watch_source = g_unix_fd_source_new (request->child_stdout, + G_IO_IN | G_IO_ERR | G_IO_HUP); + g_source_set_callback (request->child_stdout_watch_source, + G_SOURCE_FUNC (io_watch_have_data), + request, + NULL); + g_source_attach (request->child_stdout_watch_source, + request->listener->main_context); - ret = g_strcmp0 ((const char *) user, (const char *) b); - g_free (user); - return ret; + /* Write the cookie on stdin so it can't be seen by other processes */ + queue_string_to_helper (request, request->cookie); + + return; } -static PolkitIdentity * -choose_identity (GList *identities) +static AuthRequest* +get_request (NMPolkitListener *listener, + const char *cookie) { - const char *user; - GList *elem; + AuthRequest *request; - /* Choose identity. First try current user, then root, and else - * take the first one */ - user = getenv("USER"); - elem = g_list_find_custom (identities, user, (GCompareFunc) compare_users); - if (!elem) { - elem = g_list_find_custom (identities, "root", (GCompareFunc) compare_users); - if (!elem) - elem = identities; + c_list_for_each_entry (request, &listener->request_lst_head, request_lst) { + if (nm_streq0 (cookie, request->cookie)) { + return request; + } + } + return NULL; +} + +static AuthRequest* +create_request (NMPolkitListener *listener, + GDBusMethodInvocation *invocation, + const char *action_id, + const char *message, + const char *username, + const char *cookie) +{ + AuthRequest *request = g_slice_new0(AuthRequest); + + request->listener = listener; + request->dbus_invocation = invocation; + request->action_id = g_strdup (action_id); + request->message = g_strdup (message); + request->username = g_strdup (username); + request->cookie = g_strdup (cookie); + request->in_buffer = g_string_new (""); + + /* preallocate a large enough buffer so that + * secrets don't get reallocated, thus leaked */ + request->out_buffer = g_string_sized_new (1024); + + c_list_link_tail (&listener->request_lst_head, &request->request_lst); + return request; +} + +static void +dbus_method_call_cb (GDBusConnection *connection, + const char *sender, + const char *object_path, + const char *interface_name, + const char *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + NMPolkitListener *listener = NM_POLKIT_LISTENER (user_data); + const char *action_id; + const char *message; + const char *cookie; + AuthRequest *request; + gs_unref_variant GVariant *identities_gvariant; + uid_t uid; + + if (nm_streq (method_name, "BeginAuthentication")) { + g_variant_get (parameters, + "(&s&s&s@a{ss}&s@a(sa{sv}))", + &action_id, + &message, + NULL, + NULL, + &cookie, + &identities_gvariant); + + uid = choose_identity (identities_gvariant); + + request = create_request (listener, + invocation, + action_id, + message, + uid_to_name (uid), + cookie); + begin_authentication (request); + } else if (nm_streq (method_name, "CancelAuthentication")) { + g_variant_get (parameters, + "&s", + &cookie); + request = get_request (listener, cookie); + + if (request) { + complete_authentication (request, FALSE); + } + } +} + +static gboolean +export_dbus_iface (NMPolkitListener *self, GError **error) +{ + GDBusInterfaceVTable interface_vtable = { + .method_call = dbus_method_call_cb, + .set_property = NULL, + .get_property = NULL, + }; + + g_return_val_if_fail (NM_IS_POLKIT_LISTENER (self), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + /* Agent listener iface has been exported already */ + if (self->pk_auth_agent_reg_id) { + return TRUE; } - return elem->data; + self->pk_auth_agent_reg_id = + g_dbus_connection_register_object (self->dbus_connection, + POLKIT_AGENT_OBJ_PATH, + (GDBusInterfaceInfo*) &interface_info, + &interface_vtable, + self, + NULL, + error); + if (!self->pk_auth_agent_reg_id) { + g_signal_emit (self, + signals[ERROR], + 0, + "Could not register as a PolicyKit Authentication Agent"); + } + return self->pk_auth_agent_reg_id; } static void -initiate_authentication (PolkitAgentListener *listener, - const char *action_id, - const char *message, - const char *icon_name, - PolkitDetails *details, - const char *cookie, - GList *identities, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) +name_owner_changed (NMPolkitListener *self, + const char *name_owner) { - NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (listener); - GSimpleAsyncResult *simple; - PolkitIdentity *identity; - - simple = g_simple_async_result_new (G_OBJECT (listener), - callback, - user_data, - initiate_authentication); - if (cancellable) - g_simple_async_result_set_check_cancellable (simple, cancellable); - if (priv->active_session != NULL) { - g_simple_async_result_set_error (simple, - POLKIT_ERROR, - POLKIT_ERROR_FAILED, - _("An authentication session is already underway.")); - g_simple_async_result_complete_in_idle (simple); - g_object_unref (simple); + gs_free_error GError *error = NULL; + + name_owner = nm_str_not_empty (name_owner); + + if (nm_streq0 (self->name_owner, name_owner)) { return; } - /* Choose identity */ - identity = choose_identity (identities); - - priv->active_session = polkit_agent_session_new (identity, cookie); - g_signal_connect (priv->active_session, - "completed", - G_CALLBACK (on_completed), - listener); - g_signal_connect (priv->active_session, - "request", - G_CALLBACK (on_request), - listener); - g_signal_connect (priv->active_session, - "show-info", - G_CALLBACK (on_show_info), - listener); - g_signal_connect (priv->active_session, - "show-error", - G_CALLBACK (on_show_error), - listener); - - priv->action_id = g_strdup (action_id); - priv->message = g_strdup (message); - priv->icon_name = g_strdup (icon_name); - if (POLKIT_IS_UNIX_USER (identity)) - priv->identity = g_strdup (polkit_unix_user_get_name (POLKIT_UNIX_USER (identity))); - else - priv->identity = polkit_identity_to_string (identity); - - priv->simple = simple; - priv->cancellable = g_object_ref (cancellable); - priv->cancel_id = g_cancellable_connect (cancellable, - G_CALLBACK (on_cancelled), - listener, - NULL); - - polkit_agent_session_initiate (priv->active_session); + g_free (self->name_owner); + self->name_owner = g_strdup (name_owner); + + if (!self->name_owner) { + return; + } + + if (export_dbus_iface (self, &error)) { + if (self->session_agent) { + retrieve_session_id (self); + } else { + agent_register (self, NULL); + } + } else { + g_signal_emit (self, + signals[ERROR], + 0, + "Could not export the PolicyKit Authentication Agent DBus interface"); + } } -static gboolean -initiate_authentication_finish (PolkitAgentListener *listener, - GAsyncResult *result, - GError **error) +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) +{ + NMPolkitListener *self = user_data; + const char *new_owner; + + if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(sss)"))) { + return; + } + + g_variant_get (parameters, + "(&s&s&s)", + NULL, + NULL, + &new_owner); + + name_owner_changed (self, new_owner); +} + +static void +get_name_owner_cb (const char *name_owner, + GError *error, + gpointer user_data) { - return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error); + if (!name_owner && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + return; + } + name_owner_changed (user_data, name_owner); } /*****************************************************************************/ +NM_GOBJECT_PROPERTIES_DEFINE (NMPolkitListener, + PROP_DBUS_CONNECTION, + PROP_SESSION_AGENT, +); + static void -nm_polkit_listener_init (NMPolkitListener *agent) +set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) { + NMPolkitListener *self = NM_POLKIT_LISTENER (object); + + switch (prop_id) { + case PROP_DBUS_CONNECTION: + self->dbus_connection = g_value_dup_object (value); + break; + case PROP_SESSION_AGENT: + self->session_agent = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_polkit_listener_init (NMPolkitListener *self) +{ + c_list_init (&self->request_lst_head); + self->main_context = g_main_context_ref_thread_default (); +} + +static void +constructed (GObject *object) +{ + NMPolkitListener *self = NM_POLKIT_LISTENER (object); + + self->cancellable = g_cancellable_new (); + + self->name_owner_changed_id = + nm_dbus_connection_signal_subscribe_name_owner_changed (self->dbus_connection, + POLKIT_BUS_NAME, + name_owner_changed_cb, + self, + NULL); + + nm_dbus_connection_call_get_name_owner (self->dbus_connection, + POLKIT_BUS_NAME, + -1, + self->cancellable, + get_name_owner_cb, + self); + + G_OBJECT_CLASS (nm_polkit_listener_parent_class)->constructed (object); } /** * nm_polkit_listener_new: - * @for_session: %TRUE for registering the polkit agent for the user session, - * %FALSE for registering it for the running process - * @vtable: mandatory callbacks - * @user_data: user-data pointer for callbacks - * @error: location to store error, or %NULL + * @dbus_connection: a open DBus connection + * @session_agent: TRUE if a session agent is wanted, FALSE for a process agent * * Creates a new #NMPolkitListener and registers it as a polkit agent. * * Returns: a new #NMPolkitListener */ NMPolkitListener * -nm_polkit_listener_new (gboolean for_session, - GError **error) +nm_polkit_listener_new (GDBusConnection *dbus_connection, gboolean session_agent) { - NMPolkitListener *listener; - PolkitSubject* session; - NMPolkitListenerPrivate *priv; - - g_return_val_if_fail (!error || !*error, NULL); - - listener = g_object_new (NM_TYPE_POLKIT_LISTENER, NULL); - - priv = NM_POLKIT_LISTENER_GET_PRIVATE (listener); - - if (for_session) { - session = polkit_unix_session_new_for_process_sync (getpid (), NULL, error); - if (!session) - return NULL; - } else - session = polkit_unix_process_new_for_owner (getpid (), 0, getuid ()); - - priv->reg_handle = polkit_agent_listener_register (POLKIT_AGENT_LISTENER (listener), - POLKIT_AGENT_REGISTER_FLAGS_NONE, - session, NULL, NULL, error); - if (!priv->reg_handle) { - g_object_unref (listener); - g_object_unref (session); - return NULL; - } - - return listener; + return g_object_new (NM_TYPE_POLKIT_LISTENER, + NM_POLKIT_LISTENER_DBUS_CONNECTION, dbus_connection, + NM_POLKIT_LISTENER_SESSION_AGENT, session_agent, + NULL); } static void -nm_polkit_listener_finalize (GObject *object) +dispose (GObject *object) { - NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (object); + NMPolkitListener *self = NM_POLKIT_LISTENER (object); + AuthRequest *request; + + nm_clear_g_cancellable (&self->cancellable); - if (priv->reg_handle) - polkit_agent_listener_unregister (priv->reg_handle); + while ((request = c_list_first_entry (&self->request_lst_head, AuthRequest, request_lst))) { + remove_request (request); + } + + if (self->dbus_connection) { + nm_clear_g_dbus_connection_signal (self->dbus_connection, + &self->name_owner_changed_id); + g_dbus_connection_unregister_object (self->dbus_connection, + self->pk_auth_agent_reg_id); + agent_unregister (self); + nm_clear_g_free (&self->name_owner); + g_clear_object (&self->dbus_connection); + } - g_free (priv->action_id); - g_free (priv->message); - g_free (priv->icon_name); - g_free (priv->identity); + nm_clear_pointer (&self->main_context, g_main_context_unref); - G_OBJECT_CLASS (nm_polkit_listener_parent_class)->finalize (object); + G_OBJECT_CLASS (nm_polkit_listener_parent_class)->dispose (object); } static void nm_polkit_listener_class_init (NMPolkitListenerClass *klass) { - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - PolkitAgentListenerClass *pkal_class = POLKIT_AGENT_LISTENER_CLASS (klass); - - g_type_class_add_private (klass, sizeof (NMPolkitListenerPrivate)); - - gobject_class->finalize = nm_polkit_listener_finalize; - - pkal_class->initiate_authentication = initiate_authentication; - pkal_class->initiate_authentication_finish = initiate_authentication_finish; + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->set_property = set_property; + object_class->constructed = constructed; + object_class->dispose = dispose; + + obj_properties[PROP_DBUS_CONNECTION] = + g_param_spec_object (NM_POLKIT_LISTENER_DBUS_CONNECTION, "", "", + G_TYPE_DBUS_CONNECTION, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_WRITABLE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_SESSION_AGENT] = + g_param_spec_boolean (NM_POLKIT_LISTENER_SESSION_AGENT, "", "", + FALSE, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_WRITABLE | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, + _PROPERTY_ENUMS_LAST, + obj_properties); + + signals[REQUEST] = + g_signal_new (NM_POLKIT_LISTENER_SIGNAL_REQUEST, + NM_TYPE_POLKIT_LISTENER, + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + NULL, + G_TYPE_STRING, + 3, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING); + + signals[REGISTERED] = + g_signal_new (NM_POLKIT_LISTENER_SIGNAL_REGISTERED, + NM_TYPE_POLKIT_LISTENER, + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 0); + + signals[ERROR] = + g_signal_new (NM_POLKIT_LISTENER_SIGNAL_ERROR, + NM_TYPE_POLKIT_LISTENER, + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 1, + G_TYPE_STRING); } - -#endif /* WITH_POLKIT_AGENT */ diff --git a/clients/common/nm-polkit-listener.h b/clients/common/nm-polkit-listener.h index 42da1bc13f..d84f3a1bb5 100644 --- a/clients/common/nm-polkit-listener.h +++ b/clients/common/nm-polkit-listener.h @@ -6,133 +6,16 @@ #ifndef __NM_POLKIT_LISTENER_H__ #define __NM_POLKIT_LISTENER_H__ -#if WITH_POLKIT_AGENT - -typedef struct _NMPolkitListener NMPolkitListener; -typedef struct _NMPolkitListenerClass NMPolkitListenerClass; - -typedef struct { - - /* - * @request: the request asked by polkit agent - * @action_id: the action_id of the polkit request - * @message: the message of the polkit request - * @icon_name: the icon name of the polkit request - * @user: user name - * @echo_on: whether the response to the request should be echoed to the screen - * @user_data: user data for the callback - * - * Called as a result of a request by polkit. The function should obtain response - * to the request from user, i.e. get the password required. - */ - char *(*on_request) (NMPolkitListener *self, - const char *request, - const char *action_id, - const char *message, - const char *icon_name, - const char *user, - gboolean echo_on, - gpointer user_data); - - /* - * @text: the info text from polkit - * - * Called as a result of show-info signal by polkit. - */ - void (*on_show_info) (NMPolkitListener *self, - const char *text, - gpointer user_data); - - /* - * @text: the error text from polkit - * - * Called as a result of show-error signal by polkit. - */ - void (*on_show_error) (NMPolkitListener *self, - const char *text, - gpointer user_data); - - /* - * @gained_authorization: whether the authorization was successful - * - * Called as a result of completed signal by polkit. - */ - void (*on_completed) (NMPolkitListener *self, - gboolean gained_authorization, - gpointer user_data); -} NMPolkitListenVtable; - -/*****************************************************************************/ - -#define POLKIT_AGENT_I_KNOW_API_IS_SUBJECT_TO_CHANGE -#include <polkitagent/polkitagent.h> - #define NM_TYPE_POLKIT_LISTENER (nm_polkit_listener_get_type ()) -#define NM_POLKIT_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_POLKIT_LISTENER, NMPolkitListener)) -#define NM_POLKIT_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_POLKIT_LISTENER, NMPolkitListenerClass)) -#define NM_IS_POLKIT_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_POLKIT_LISTENER)) -#define NM_IS_POLKIT_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_POLKIT_LISTENER)) -#define NM_POLKIT_LISTENER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_POLKIT_LISTENER, NMPolkitListenerClass)) - -/** - * NMPolkitListenerOnRequestFunc: - * @request: the request asked by polkit agent - * @action_id: the action_id of the polkit request - * @message: the message of the polkit request - * @icon_name: the icon name of the polkit request - * @user: user name - * @echo_on: whether the response to the request should be echoed to the screen - * @user_data: user data for the callback - * - * Called as a result of a request by polkit. The function should obtain response - * to the request from user, i.e. get the password required. - */ -typedef char * (*NMPolkitListenerOnRequestFunc) (const char *request, - const char *action_id, - const char *message, - const char *icon_name, - const char *user, - gboolean echo_on, - gpointer user_data); -/** - * NMPolkitListenerOnShowInfoFunc: - * @text: the info text from polkit - * - * Called as a result of show-info signal by polkit. - */ -typedef void (*NMPolkitListenerOnShowInfoFunc) (const char *text); -/** - * NMPolkitListenerOnShowErrorFunc: - * @text: the error text from polkit - * - * Called as a result of show-error signal by polkit. - */ -typedef void (*NMPolkitListenerOnShowErrorFunc) (const char *text); -/** - * NMPolkitListenerCompletedFunc: - * @gained_authorization: whether the authorization was successful - * - * Called as a result of completed signal by polkit. - */ -typedef void (*NMPolkitListenerOnCompletedFunc) (gboolean gained_authorization); - -struct _NMPolkitListener { - PolkitAgentListener parent; -}; - -struct _NMPolkitListenerClass { - PolkitAgentListenerClass parent; -}; - -GType nm_polkit_listener_get_type (void); - -NMPolkitListener *nm_polkit_listener_new (gboolean for_session, - GError **error); +G_DECLARE_FINAL_TYPE (NMPolkitListener, nm_polkit_listener, NM, POLKIT_LISTENER, GObject) -void nm_polkit_listener_set_vtable (NMPolkitListener *self, - const NMPolkitListenVtable *vtable, - gpointer user_data); +NMPolkitListener *nm_polkit_listener_new (GDBusConnection *dbus_connection, gboolean session_agent); -#endif +/* Signals */ +#define NM_POLKIT_LISTENER_SIGNAL_REGISTERED "registered" +#define NM_POLKIT_LISTENER_SIGNAL_REQUEST "secret-request" +#define NM_POLKIT_LISTENER_SIGNAL_AUTH_SUCCESS "auth-success" +#define NM_POLKIT_LISTENER_SIGNAL_AUTH_FAILURE "auth-failure" +#define NM_POLKIT_LISTENER_SIGNAL_ERROR "error" #endif /* __NM_POLKIT_LISTENER_H__ */ diff --git a/config.h.meson b/config.h.meson index 0514418138..009c635da4 100644 --- a/config.h.meson +++ b/config.h.meson @@ -221,8 +221,8 @@ /* Define if you have oFono support (experimental) */ #mesondefine WITH_OFONO -/* Define if you have polkit agent */ -#mesondefine WITH_POLKIT_AGENT +/* Define the polkit agent package prefix */ +#mesondefine POLKIT_PACKAGE_PREFIX /* Define if you have PPP support */ #mesondefine WITH_PPP diff --git a/configure.ac b/configure.ac index 24b3f7c435..22cecb6efc 100644 --- a/configure.ac +++ b/configure.ac @@ -655,18 +655,13 @@ AC_DEFINE_UNQUOTED(NM_CONFIG_DEFAULT_MAIN_AUTH_POLKIT, "$enable_polkit", [The de AC_SUBST(NM_CONFIG_DEFAULT_MAIN_AUTH_POLKIT_TEXT, "$enable_polkit") PKG_CHECK_MODULES(POLKIT, [polkit-agent-1 >= 0.97], [have_pk_agent=yes],[have_pk_agent=no]) -AC_ARG_ENABLE(polkit-agent, - AS_HELP_STRING([--enable-polkit-agent], [enable polkit agent for clients]), - [enable_polkit_agent=${enableval}], [enable_polkit_agent=${have_pk_agent}]) -if (test "${enable_polkit_agent}" = "yes"); then - if test x"$have_pk_agent" = x"no"; then - AC_MSG_ERROR(Polkit agent is required) - fi - AC_DEFINE(WITH_POLKIT_AGENT, 1, [Define if you have polkit agent]) -else - AC_DEFINE(WITH_POLKIT_AGENT, 0, [Define if you have polkit agent]) +if test x"$have_pk_agent" = x"no"; then + AC_MSG_ERROR(Polkit agent is required) fi -AM_CONDITIONAL(WITH_POLKIT_AGENT, test "${enable_polkit_agent}" = "yes") +POLKIT_PACKAGE_PREFIX=`$PKG_CONFIG --variable=prefix polkit-agent-1` +AC_DEFINE_UNQUOTED([POLKIT_PACKAGE_PREFIX], + ["$POLKIT_PACKAGE_PREFIX"], + [polkit-agent package prefix]) AC_ARG_ENABLE(modify-system, AS_HELP_STRING([--enable-modify-system], [Allow users to modify system connections])) if test "${enable_modify_system}" = "yes"; then @@ -1323,7 +1318,6 @@ if test "${enable_modify_system}" = "yes"; then else echo " policykit: main.auth-polkit=${enable_polkit} (restrictive modify.system)" fi -echo " polkit agent: ${enable_polkit_agent}" echo " selinux: $have_selinux" echo " systemd-journald: $have_systemd_journal (default: logging.backend=${nm_config_logging_backend_default})" echo " hostname persist: ${hostname_persist}" diff --git a/contrib/fedora/rpm/NetworkManager.spec b/contrib/fedora/rpm/NetworkManager.spec index d7e3612dc4..c706ce1b79 100644 --- a/contrib/fedora/rpm/NetworkManager.spec +++ b/contrib/fedora/rpm/NetworkManager.spec @@ -586,7 +586,6 @@ This tool is still experimental. -Dselinux=true \ -Dpolkit=true \ -Dconfig_auth_polkit_default=true \ - -Dpolkit_agent=true \ -Dmodify_system=true \ -Dconcheck=true \ %if 0%{?fedora} @@ -717,7 +716,6 @@ intltoolize --automake --copy --force %endif --with-selinux=yes \ --enable-polkit=yes \ - --enable-polkit-agent \ --enable-modify-system=yes \ --enable-concheck \ %if 0%{?fedora} diff --git a/meson.build b/meson.build index 69bbccd818..0d7b29e2bf 100644 --- a/meson.build +++ b/meson.build @@ -494,11 +494,12 @@ config_h.set_quoted('NM_CONFIG_DEFAULT_MAIN_AUTH_POLKIT', config_auth_polkit_def enable_modify_system = get_option('modify_system') -enable_polkit_agent = get_option('polkit_agent') -if enable_polkit_agent - polkit_agent_dep = dependency('polkit-agent-1', version: '>= 0.97') +polkit_agent_dep = dependency('polkit-agent-1', version: '>= 0.97', required : false) +if polkit_agent_dep.found() + config_h.set_quoted('POLKIT_PACKAGE_PREFIX', polkit_agent_dep.get_pkgconfig_variable('prefix')) +else + config_h.set_quoted('POLKIT_PACKAGE_PREFIX', '/usr') endif -config_h.set10('WITH_POLKIT_AGENT', enable_polkit_agent) crypto = get_option('crypto') @@ -971,7 +972,6 @@ if enable_polkit output += ' modify.system)' endif output += '\n' -output += ' polkit agent: ' + enable_polkit_agent.to_string() + '\n' output += ' selinux: ' + enable_selinux.to_string() + '\n' output += ' systemd-journald: ' + enable_systemd_journal.to_string() + ' (default: logging.backend=' + config_logging_backend_default + ')\n' output += ' hostname persist: ' + hostname_persist + '\n' |