PolicyKit: Branch 'master'
David Zeuthen
david at kemper.freedesktop.org
Wed Jul 15 09:52:24 PDT 2009
docs/polkit/polkit-1-docs.xml | 1
docs/polkit/polkit-1-sections.txt | 18
docs/polkit/polkit-1.types | 3
src/polkitbackend/Makefile.am | 2
src/polkitbackend/polkitbackend.h | 1
src/polkitbackend/polkitbackendinteractiveauthority.c | 1882 ++++++++++++++++++
src/polkitbackend/polkitbackendinteractiveauthority.h | 138 +
src/polkitbackend/polkitbackendlocalauthority.c | 1721 ----------------
src/polkitbackend/polkitbackendlocalauthority.h | 31
src/polkitbackend/polkitbackendtypes.h | 9
10 files changed, 2102 insertions(+), 1704 deletions(-)
New commits:
commit 84a83a871e1aefd3d6138f1094af76d3c17e94dd
Author: David Zeuthen <davidz at redhat.com>
Date: Wed Jul 15 12:48:32 2009 -0400
Move authentication agent bits to separate authority subclass
diff --git a/docs/polkit/polkit-1-docs.xml b/docs/polkit/polkit-1-docs.xml
index a4705f4..4744e58 100644
--- a/docs/polkit/polkit-1-docs.xml
+++ b/docs/polkit/polkit-1-docs.xml
@@ -90,6 +90,7 @@
<part id="ref-backend-api">
<title>Backend API Reference</title>
<xi:include href="xml/polkitbackendauthority.xml"/>
+ <xi:include href="xml/polkitbackendinteractiveauthority.xml"/>
<xi:include href="xml/polkitbackendlocalauthority.xml"/>
<xi:include href="xml/polkitbackendactionpool.xml"/>
<xi:include href="xml/polkitbackendsessionmonitor.xml"/>
diff --git a/docs/polkit/polkit-1-sections.txt b/docs/polkit/polkit-1-sections.txt
index 498b0b8..a5a03c8 100644
--- a/docs/polkit/polkit-1-sections.txt
+++ b/docs/polkit/polkit-1-sections.txt
@@ -291,7 +291,6 @@ POLKIT_BACKEND_ACTION_LOOKUP_GET_IFACE
<TITLE>PolkitBackendLocalAuthority</TITLE>
PolkitBackendLocalAuthority
PolkitBackendLocalAuthorityClass
-polkit_backend_local_authority_new
<SUBSECTION Standard>
POLKIT_BACKEND_LOCAL_AUTHORITY
POLKIT_BACKEND_IS_LOCAL_AUTHORITY
@@ -303,6 +302,23 @@ POLKIT_BACKEND_LOCAL_AUTHORITY_GET_CLASS
</SECTION>
<SECTION>
+<FILE>polkitbackendinteractiveauthority</FILE>
+<TITLE>PolkitBackendInteractiveAuthority</TITLE>
+PolkitBackendInteractiveAuthority
+PolkitBackendInteractiveAuthorityClass
+polkit_backend_interactive_authority_get_admin_identities
+polkit_backend_interactive_authority_check_authorization_sync
+<SUBSECTION Standard>
+POLKIT_BACKEND_INTERACTIVE_AUTHORITY
+POLKIT_BACKEND_IS_INTERACTIVE_AUTHORITY
+POLKIT_BACKEND_TYPE_INTERACTIVE_AUTHORITY
+polkit_backend_interactive_authority_get_type
+POLKIT_BACKEND_INTERACTIVE_AUTHORITY_CLASS
+POLKIT_BACKEND_IS_INTERACTIVE_AUTHORITY_CLASS
+POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_CLASS
+</SECTION>
+
+<SECTION>
<FILE>polkitbackendactionpool</FILE>
<TITLE>PolkitBackendActionPool</TITLE>
PolkitBackendActionPool
diff --git a/docs/polkit/polkit-1.types b/docs/polkit/polkit-1.types
index 0105bad..fd9fe53 100644
--- a/docs/polkit/polkit-1.types
+++ b/docs/polkit/polkit-1.types
@@ -14,8 +14,9 @@ polkit_error_get_type
polkit_authorization_result_get_type
polkit_backend_authority_get_type
-polkit_backend_action_lookup_get_type
+polkit_backend_interactive_authority_get_type
polkit_backend_local_authority_get_type
+polkit_backend_action_lookup_get_type
polkit_backend_action_pool_get_type
polkit_backend_session_monitor_get_type
polkit_backend_config_source_get_type
diff --git a/src/polkitbackend/Makefile.am b/src/polkitbackend/Makefile.am
index cf7a88c..a41201f 100644
--- a/src/polkitbackend/Makefile.am
+++ b/src/polkitbackend/Makefile.am
@@ -41,6 +41,7 @@ libpolkit_backend_1include_HEADERS = \
polkitbackend.h \
polkitbackendtypes.h \
polkitbackendauthority.h \
+ polkitbackendinteractiveauthority.h \
polkitbackendlocalauthority.h \
polkitbackendactionpool.h \
polkitbackendsessionmonitor.h \
@@ -55,6 +56,7 @@ libpolkit_backend_1_la_SOURCES = \
polkitbackendtypes.h \
polkitbackendprivate.h \
polkitbackendauthority.h polkitbackendauthority.c \
+ polkitbackendinteractiveauthority.h polkitbackendinteractiveauthority.c \
polkitbackendlocalauthority.h polkitbackendlocalauthority.c \
polkitbackendactionpool.h polkitbackendactionpool.c \
polkitbackendsessionmonitor.h polkitbackendsessionmonitor.c \
diff --git a/src/polkitbackend/polkitbackend.h b/src/polkitbackend/polkitbackend.h
index 3efa131..c734945 100644
--- a/src/polkitbackend/polkitbackend.h
+++ b/src/polkitbackend/polkitbackend.h
@@ -31,6 +31,7 @@
#define _POLKIT_BACKEND_INSIDE_POLKIT_BACKEND_H 1
#include <polkitbackend/polkitbackendtypes.h>
#include <polkitbackend/polkitbackendauthority.h>
+#include <polkitbackend/polkitbackendinteractiveauthority.h>
#include <polkitbackend/polkitbackendlocalauthority.h>
#include <polkitbackend/polkitbackendactionpool.h>
#include <polkitbackend/polkitbackendsessionmonitor.h>
diff --git a/src/polkitbackend/polkitbackendinteractiveauthority.c b/src/polkitbackend/polkitbackendinteractiveauthority.c
new file mode 100644
index 0000000..8018b00
--- /dev/null
+++ b/src/polkitbackend/polkitbackendinteractiveauthority.c
@@ -0,0 +1,1882 @@
+/*
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz at redhat.com>
+ */
+
+#include "config.h"
+#include <errno.h>
+#include <pwd.h>
+#include <grp.h>
+#include <string.h>
+#include <glib/gstdio.h>
+#include <locale.h>
+
+#include <polkit/polkit.h>
+#include "polkitbackendinteractiveauthority.h"
+#include "polkitbackendactionpool.h"
+#include "polkitbackendsessionmonitor.h"
+#include "polkitbackendconfigsource.h"
+#include "polkitbackendactionlookup.h"
+
+#include <polkit/polkitprivate.h>
+
+/**
+ * SECTION:polkitbackendinteractiveauthority
+ * @title: PolkitBackendInteractiveAuthority
+ * @short_description: Interactive Authority
+ * @stability: Unstable
+ *
+ * An subclass of #PolkitBackendAuthority that supports interaction
+ * with authentication agents.
+ */
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+typedef struct TemporaryAuthorizationStore TemporaryAuthorizationStore;
+
+static TemporaryAuthorizationStore *temporary_authorization_store_new (void);
+static void temporary_authorization_store_free (TemporaryAuthorizationStore *store);
+
+static gboolean temporary_authorization_store_has_authorization (TemporaryAuthorizationStore *store,
+ PolkitSubject *subject,
+ const gchar *action_id);
+
+static void temporary_authorization_store_add_authorization (TemporaryAuthorizationStore *store,
+ PolkitSubject *subject,
+ const gchar *action_id);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+struct AuthenticationAgent;
+typedef struct AuthenticationAgent AuthenticationAgent;
+
+struct AuthenticationSession;
+typedef struct AuthenticationSession AuthenticationSession;
+
+typedef void (*AuthenticationAgentCallback) (AuthenticationAgent *agent,
+ PolkitSubject *subject,
+ PolkitIdentity *user_of_subject,
+ PolkitBackendInteractiveAuthority *authority,
+ const gchar *action_id,
+ PolkitImplicitAuthorization implicit_authorization,
+ gboolean authentication_success,
+ gpointer user_data);
+
+static void authentication_agent_free (AuthenticationAgent *agent);
+
+static void authentication_agent_initiate_challenge (AuthenticationAgent *agent,
+ PolkitSubject *subject,
+ PolkitIdentity *user_of_subject,
+ PolkitBackendInteractiveAuthority *authority,
+ const gchar *action_id,
+ PolkitDetails *details,
+ PolkitSubject *caller,
+ PolkitImplicitAuthorization implicit_authorization,
+ GCancellable *cancellable,
+ AuthenticationAgentCallback callback,
+ gpointer user_data);
+
+static AuthenticationAgent *get_authentication_agent_for_subject (PolkitBackendInteractiveAuthority *authority,
+ PolkitSubject *subject);
+
+static AuthenticationSession *get_authentication_session_for_cookie (PolkitBackendInteractiveAuthority *authority,
+ const gchar *cookie);
+
+static GList *get_authentication_sessions_initiated_by_system_bus_unique_name (PolkitBackendInteractiveAuthority *authority,
+ const gchar *system_bus_unique_name);
+
+static void authentication_session_cancel (AuthenticationSession *session);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void polkit_backend_interactive_authority_system_bus_name_owner_changed (PolkitBackendAuthority *authority,
+ const gchar *name,
+ const gchar *old_owner,
+ const gchar *new_owner);
+
+static GList *polkit_backend_interactive_authority_enumerate_actions (PolkitBackendAuthority *authority,
+ PolkitSubject *caller,
+ const gchar *locale,
+ GError **error);
+
+static void polkit_backend_interactive_authority_check_authorization (PolkitBackendAuthority *authority,
+ PolkitSubject *caller,
+ PolkitSubject *subject,
+ const gchar *action_id,
+ PolkitDetails *details,
+ PolkitCheckAuthorizationFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+static PolkitAuthorizationResult *polkit_backend_interactive_authority_check_authorization_finish (
+ PolkitBackendAuthority *authority,
+ GAsyncResult *res,
+ GError **error);
+
+static PolkitAuthorizationResult *check_authorization_sync (PolkitBackendAuthority *authority,
+ PolkitSubject *caller,
+ PolkitSubject *subject,
+ const gchar *action_id,
+ PolkitDetails *details,
+ PolkitCheckAuthorizationFlags flags,
+ PolkitImplicitAuthorization *out_implicit_authorization,
+ GError **error);
+
+static gboolean polkit_backend_interactive_authority_register_authentication_agent (PolkitBackendAuthority *authority,
+ PolkitSubject *caller,
+ const gchar *session_id,
+ const gchar *locale,
+ const gchar *object_path,
+ GError **error);
+
+static gboolean polkit_backend_interactive_authority_unregister_authentication_agent (PolkitBackendAuthority *authority,
+ PolkitSubject *caller,
+ const gchar *session_id,
+ const gchar *object_path,
+ GError **error);
+
+static gboolean polkit_backend_interactive_authority_authentication_agent_response (PolkitBackendAuthority *authority,
+ PolkitSubject *caller,
+ const gchar *cookie,
+ PolkitIdentity *identity,
+ GError **error);
+
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+typedef struct
+{
+ PolkitBackendActionPool *action_pool;
+
+ PolkitBackendSessionMonitor *session_monitor;
+
+ TemporaryAuthorizationStore *temporary_authorization_store;
+
+ GHashTable *hash_session_to_authentication_agent;
+
+} PolkitBackendInteractiveAuthorityPrivate;
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+G_DEFINE_TYPE (PolkitBackendInteractiveAuthority,
+ polkit_backend_interactive_authority,
+ POLKIT_BACKEND_TYPE_AUTHORITY);
+
+#define POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), POLKIT_BACKEND_TYPE_INTERACTIVE_AUTHORITY, PolkitBackendInteractiveAuthorityPrivate))
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+action_pool_changed (PolkitBackendActionPool *action_pool,
+ PolkitBackendInteractiveAuthority *authority)
+{
+ g_signal_emit_by_name (authority, "changed");
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+polkit_backend_interactive_authority_init (PolkitBackendInteractiveAuthority *authority)
+{
+ PolkitBackendInteractiveAuthorityPrivate *priv;
+ GFile *directory;
+
+ priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (authority);
+
+ directory = g_file_new_for_path (PACKAGE_DATA_DIR "/polkit-1/actions");
+ priv->action_pool = polkit_backend_action_pool_new (directory);
+ g_object_unref (directory);
+ g_signal_connect (priv->action_pool,
+ "changed",
+ (GCallback) action_pool_changed,
+ authority);
+
+ priv->temporary_authorization_store = temporary_authorization_store_new ();
+
+ priv->hash_session_to_authentication_agent = g_hash_table_new_full ((GHashFunc) polkit_subject_hash,
+ (GEqualFunc) polkit_subject_equal,
+ (GDestroyNotify) g_object_unref,
+ (GDestroyNotify) authentication_agent_free);
+
+ priv->session_monitor = polkit_backend_session_monitor_new ();
+}
+
+static void
+polkit_backend_interactive_authority_finalize (GObject *object)
+{
+ PolkitBackendInteractiveAuthority *interactive_authority;
+ PolkitBackendInteractiveAuthorityPrivate *priv;
+
+ interactive_authority = POLKIT_BACKEND_INTERACTIVE_AUTHORITY (object);
+ priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (interactive_authority);
+
+ if (priv->action_pool != NULL)
+ g_object_unref (priv->action_pool);
+
+ if (priv->session_monitor != NULL)
+ g_object_unref (priv->session_monitor);
+
+ temporary_authorization_store_free (priv->temporary_authorization_store);
+
+ g_hash_table_unref (priv->hash_session_to_authentication_agent);
+
+ G_OBJECT_CLASS (polkit_backend_interactive_authority_parent_class)->finalize (object);
+}
+
+static void
+polkit_backend_interactive_authority_class_init (PolkitBackendInteractiveAuthorityClass *klass)
+{
+ GObjectClass *gobject_class;
+ PolkitBackendAuthorityClass *authority_class;
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ authority_class = POLKIT_BACKEND_AUTHORITY_CLASS (klass);
+
+ gobject_class->finalize = polkit_backend_interactive_authority_finalize;
+
+ authority_class->system_bus_name_owner_changed = polkit_backend_interactive_authority_system_bus_name_owner_changed;
+ authority_class->enumerate_actions = polkit_backend_interactive_authority_enumerate_actions;
+ authority_class->check_authorization = polkit_backend_interactive_authority_check_authorization;
+ authority_class->check_authorization_finish = polkit_backend_interactive_authority_check_authorization_finish;
+ authority_class->register_authentication_agent = polkit_backend_interactive_authority_register_authentication_agent;
+ authority_class->unregister_authentication_agent = polkit_backend_interactive_authority_unregister_authentication_agent;
+ authority_class->authentication_agent_response = polkit_backend_interactive_authority_authentication_agent_response;
+
+
+ g_type_class_add_private (klass, sizeof (PolkitBackendInteractiveAuthorityPrivate));
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static GList *
+polkit_backend_interactive_authority_enumerate_actions (PolkitBackendAuthority *authority,
+ PolkitSubject *caller,
+ const gchar *interactivee,
+ GError **error)
+{
+ PolkitBackendInteractiveAuthority *interactive_authority;
+ PolkitBackendInteractiveAuthorityPrivate *priv;
+ GList *actions;
+
+ interactive_authority = POLKIT_BACKEND_INTERACTIVE_AUTHORITY (authority);
+ priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (interactive_authority);
+
+ actions = polkit_backend_action_pool_get_all_actions (priv->action_pool, interactivee);
+
+ return actions;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+check_authorization_challenge_cb (AuthenticationAgent *agent,
+ PolkitSubject *subject,
+ PolkitIdentity *user_of_subject,
+ PolkitBackendInteractiveAuthority *authority,
+ const gchar *action_id,
+ PolkitImplicitAuthorization implicit_authorization,
+ gboolean authentication_success,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
+ PolkitBackendInteractiveAuthorityPrivate *priv;
+ PolkitAuthorizationResult *result;
+ gchar *subject_str;
+
+ priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (authority);
+
+ result = NULL;
+ subject_str = polkit_subject_to_string (subject);
+
+ g_debug ("In check_authorization_challenge_cb\n"
+ " subject %s\n"
+ " action_id %s\n"
+ " authentication_success %d\n",
+ subject_str,
+ action_id,
+ authentication_success);
+
+ if (authentication_success)
+ {
+ result = polkit_authorization_result_new (TRUE, FALSE, NULL);
+
+ /* store temporary authorization depending on value of implicit_authorization */
+ if (implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_AUTHENTICATION_REQUIRED_RETAINED ||
+ implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_ADMINISTRATOR_AUTHENTICATION_REQUIRED_RETAINED)
+ {
+ temporary_authorization_store_add_authorization (priv->temporary_authorization_store,
+ subject,
+ action_id);
+ }
+ }
+ else
+ {
+ /* TODO: maybe return set is_challenge? */
+ result = polkit_authorization_result_new (FALSE, FALSE, NULL);
+ }
+
+ g_simple_async_result_set_op_res_gpointer (simple,
+ result,
+ g_object_unref);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+
+ g_free (subject_str);
+}
+
+static PolkitAuthorizationResult *
+polkit_backend_interactive_authority_check_authorization_finish (PolkitBackendAuthority *authority,
+ GAsyncResult *res,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+ PolkitAuthorizationResult *result;
+
+ simple = G_SIMPLE_ASYNC_RESULT (res);
+
+ g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == polkit_backend_interactive_authority_check_authorization);
+
+ result = NULL;
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ goto out;
+
+ result = g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
+
+ out:
+ return result;
+}
+
+static void
+polkit_backend_interactive_authority_check_authorization (PolkitBackendAuthority *authority,
+ PolkitSubject *caller,
+ PolkitSubject *subject,
+ const gchar *action_id,
+ PolkitDetails *details,
+ PolkitCheckAuthorizationFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ PolkitBackendInteractiveAuthority *interactive_authority;
+ PolkitBackendInteractiveAuthorityPrivate *priv;
+ gchar *caller_str;
+ gchar *subject_str;
+ PolkitIdentity *user_of_caller;
+ PolkitIdentity *user_of_subject;
+ gchar *user_of_caller_str;
+ gchar *user_of_subject_str;
+ PolkitAuthorizationResult *result;
+ PolkitImplicitAuthorization implicit_authorization;
+ GError *error;
+ GSimpleAsyncResult *simple;
+
+ interactive_authority = POLKIT_BACKEND_INTERACTIVE_AUTHORITY (authority);
+ priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (interactive_authority);
+
+ error = NULL;
+ caller_str = NULL;
+ subject_str = NULL;
+ user_of_caller = NULL;
+ user_of_subject = NULL;
+ user_of_caller_str = NULL;
+ user_of_subject_str = NULL;
+ result = NULL;
+
+ simple = g_simple_async_result_new (G_OBJECT (authority),
+ callback,
+ user_data,
+ polkit_backend_interactive_authority_check_authorization);
+
+ caller_str = polkit_subject_to_string (caller);
+ subject_str = polkit_subject_to_string (subject);
+
+ g_debug ("%s is inquiring whether %s is authorized for %s",
+ caller_str,
+ subject_str,
+ action_id);
+
+ user_of_caller = polkit_backend_session_monitor_get_user_for_subject (priv->session_monitor,
+ caller,
+ &error);
+ if (error != NULL)
+ {
+ g_simple_async_result_set_from_error (simple, error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ g_error_free (error);
+ goto out;
+ }
+
+ user_of_caller_str = polkit_identity_to_string (user_of_caller);
+ g_debug (" user of caller is %s", user_of_caller_str);
+
+ /* we only allow trusted callers (uid 0 + others) to check authorizations */
+ if (!POLKIT_IS_UNIX_USER (user_of_caller) ||
+ polkit_unix_user_get_uid (POLKIT_UNIX_USER (user_of_caller)) != 0) /* TODO: allow other uids like 'haldaemon'? */
+ {
+ g_simple_async_result_set_error (simple,
+ POLKIT_ERROR,
+ POLKIT_ERROR_NOT_AUTHORIZED,
+ "Only trusted callers can use CheckAuthorization(), %s is not trusted",
+ user_of_caller_str);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ goto out;
+ }
+
+ user_of_subject = polkit_backend_session_monitor_get_user_for_subject (priv->session_monitor,
+ subject,
+ &error);
+ if (error != NULL)
+ {
+ g_simple_async_result_set_from_error (simple, error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ g_error_free (error);
+ goto out;
+ }
+
+ user_of_subject_str = polkit_identity_to_string (user_of_subject);
+ g_debug (" user of subject is %s", user_of_subject_str);
+
+ implicit_authorization = POLKIT_IMPLICIT_AUTHORIZATION_NOT_AUTHORIZED;
+ result = check_authorization_sync (authority,
+ caller,
+ subject,
+ action_id,
+ details,
+ flags,
+ &implicit_authorization,
+ &error);
+ if (error != NULL)
+ {
+ g_simple_async_result_set_from_error (simple, error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* Caller is up for a challenge! With light sabers! Use an authentication agent if one exists... */
+ if (polkit_authorization_result_get_is_challenge (result) &&
+ (flags & POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION))
+ {
+ AuthenticationAgent *agent;
+
+ agent = get_authentication_agent_for_subject (interactive_authority, subject);
+ if (agent != NULL)
+ {
+ g_object_unref (result);
+ result = NULL;
+
+ g_debug (" using authentication agent for challenge");
+
+ authentication_agent_initiate_challenge (agent,
+ subject,
+ user_of_subject,
+ interactive_authority,
+ action_id,
+ details,
+ caller,
+ implicit_authorization,
+ cancellable,
+ check_authorization_challenge_cb,
+ simple);
+
+ /* keep going */
+ goto out;
+ }
+ }
+
+ /* Otherwise just return the result */
+ g_simple_async_result_set_op_res_gpointer (simple,
+ result,
+ g_object_unref);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+
+ out:
+
+ if (user_of_caller != NULL)
+ g_object_unref (user_of_caller);
+
+ if (user_of_subject != NULL)
+ g_object_unref (user_of_subject);
+
+ g_free (caller_str);
+ g_free (subject_str);
+ g_free (user_of_caller_str);
+ g_free (user_of_subject_str);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static PolkitAuthorizationResult *
+check_authorization_sync (PolkitBackendAuthority *authority,
+ PolkitSubject *caller,
+ PolkitSubject *subject,
+ const gchar *action_id,
+ PolkitDetails *details,
+ PolkitCheckAuthorizationFlags flags,
+ PolkitImplicitAuthorization *out_implicit_authorization,
+ GError **error)
+{
+ PolkitBackendInteractiveAuthority *interactive_authority;
+ PolkitBackendInteractiveAuthorityPrivate *priv;
+ PolkitAuthorizationResult *result;
+ PolkitIdentity *user_of_subject;
+ PolkitSubject *session_for_subject;
+ gchar *subject_str;
+ GList *groups_of_user;
+ PolkitActionDescription *action_desc;
+ gboolean session_is_local;
+ gboolean session_is_active;
+ PolkitImplicitAuthorization implicit_authorization;
+
+ interactive_authority = POLKIT_BACKEND_INTERACTIVE_AUTHORITY (authority);
+ priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (interactive_authority);
+
+ result = NULL;
+
+ user_of_subject = NULL;
+ groups_of_user = NULL;
+ subject_str = NULL;
+ session_for_subject = NULL;
+
+ session_is_local = FALSE;
+ session_is_active = FALSE;
+
+ subject_str = polkit_subject_to_string (subject);
+
+ g_debug ("checking whether %s is authorized for %s",
+ subject_str,
+ action_id);
+
+ /* get the action description */
+ action_desc = polkit_backend_action_pool_get_action (priv->action_pool,
+ action_id,
+ NULL);
+
+ if (action_desc == NULL)
+ {
+ g_set_error (error,
+ POLKIT_ERROR,
+ POLKIT_ERROR_FAILED,
+ "Action %s is not registered",
+ action_id);
+ goto out;
+ }
+
+ /* every subject has a user */
+ user_of_subject = polkit_backend_session_monitor_get_user_for_subject (priv->session_monitor,
+ subject,
+ error);
+ if (user_of_subject == NULL)
+ goto out;
+
+ /* special case: uid 0, root, is _always_ authorized for anything */
+ if (POLKIT_IS_UNIX_USER (user_of_subject) && polkit_unix_user_get_uid (POLKIT_UNIX_USER (user_of_subject)) == 0)
+ {
+ result = polkit_authorization_result_new (TRUE, FALSE, NULL);
+ goto out;
+ }
+
+ /* a subject *may* be in a session */
+ session_for_subject = polkit_backend_session_monitor_get_session_for_subject (priv->session_monitor,
+ subject,
+ NULL);
+ g_debug (" %p", session_for_subject);
+ if (session_for_subject != NULL)
+ {
+ session_is_local = polkit_backend_session_monitor_is_session_local (priv->session_monitor, session_for_subject);
+ session_is_active = polkit_backend_session_monitor_is_session_active (priv->session_monitor, session_for_subject);
+
+ g_debug (" subject is in session %s (local=%d active=%d)",
+ polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (session_for_subject)),
+ session_is_local,
+ session_is_active);
+ }
+
+ /* find the implicit authorization to use; it depends on is_local and is_active */
+ if (session_is_local)
+ {
+ if (session_is_active)
+ implicit_authorization = polkit_action_description_get_implicit_active (action_desc);
+ else
+ implicit_authorization = polkit_action_description_get_implicit_inactive (action_desc);
+ }
+ else
+ {
+ implicit_authorization = polkit_action_description_get_implicit_any (action_desc);
+ }
+
+ /* allow subclasses to rewrite implicit_authorization */
+ implicit_authorization = polkit_backend_interactive_authority_check_authorization_sync (interactive_authority,
+ caller,
+ subject,
+ action_id,
+ details,
+ implicit_authorization);
+
+ /* first see if there's an implicit authorization for subject available */
+ if (implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED)
+ {
+ g_debug (" is authorized (has implicit authorization local=%d active=%d)",
+ session_is_local,
+ session_is_active);
+ result = polkit_authorization_result_new (TRUE, FALSE, NULL);
+ goto out;
+ }
+
+ /* then see if there's a temporary authorization for the subject */
+ if (temporary_authorization_store_has_authorization (priv->temporary_authorization_store,
+ subject,
+ action_id))
+ {
+ g_debug (" is authorized (has temporary authorization)");
+ result = polkit_authorization_result_new (TRUE, FALSE, NULL);
+ goto out;
+ }
+
+#if 0
+ /* then see if we have an authorization for the user */
+ if (check_authorization_for_identity (interactive_authority, user_of_subject, action_id))
+ {
+ g_debug (" is authorized (user identity has authorization)");
+ result = polkit_authorization_result_new (TRUE, FALSE, NULL);
+ goto out;
+ }
+
+ /* then see if we have a permanent authorization for any of the groups the user is in */
+ groups_of_user = get_groups_for_user (interactive_authority, user_of_subject);
+ for (l = groups_of_user; l != NULL; l = l->next)
+ {
+ PolkitIdentity *group = POLKIT_IDENTITY (l->data);
+
+ if (check_authorization_for_identity (interactive_authority, group, action_id))
+ {
+ g_debug (" is authorized (group identity has authorization)");
+ result = polkit_authorization_result_new (TRUE, FALSE, NULL);
+ goto out;
+ }
+ }
+#endif
+
+ if (implicit_authorization != POLKIT_IMPLICIT_AUTHORIZATION_NOT_AUTHORIZED)
+ {
+ result = polkit_authorization_result_new (FALSE, TRUE, NULL);
+
+ /* return implicit_authorization so the caller can use an authentication agent if applicable */
+ if (out_implicit_authorization != NULL)
+ *out_implicit_authorization = implicit_authorization;
+
+ g_debug (" challenge (implicit_authorization = %s)",
+ polkit_implicit_authorization_to_string (implicit_authorization));
+ }
+ else
+ {
+ result = polkit_authorization_result_new (FALSE, FALSE, NULL);
+ g_debug (" not authorized");
+ }
+ out:
+ g_free (subject_str);
+
+ g_list_foreach (groups_of_user, (GFunc) g_object_unref, NULL);
+ g_list_free (groups_of_user);
+
+ if (user_of_subject != NULL)
+ g_object_unref (user_of_subject);
+
+ if (session_for_subject != NULL)
+ g_object_unref (session_for_subject);
+
+ if (action_desc != NULL)
+ g_object_unref (action_desc);
+
+ g_debug (" ");
+
+ return result;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/**
+ * polkit_backend_interactive_authority_get_admin_identities:
+ * @authority: A #PolkitBackendInteractiveAuthority.
+ * @caller: The subject that is inquiring whether @subject is authorized.
+ * @subject: The subject we are about to authenticate for.
+ * @action_id: The action we are about to authenticate for.
+ * @details: Details about the action.
+ *
+ * Gets a list of identities to use for administrator authentication.
+ *
+ * The default implementation returns a list with a single element for the super user.
+ *
+ * Returns: A list of #PolkitIdentities. Free each element
+ * g_object_unref(), then free the list with g_list_free().
+ */
+GList *
+polkit_backend_interactive_authority_get_admin_identities (PolkitBackendInteractiveAuthority *authority,
+ PolkitSubject *caller,
+ PolkitSubject *subject,
+ const gchar *action_id,
+ PolkitDetails *details)
+{
+ PolkitBackendInteractiveAuthorityClass *klass;
+ GList *ret;
+
+ klass = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_CLASS (authority);
+
+ if (klass->get_admin_identities == NULL)
+ {
+ ret = g_list_prepend (NULL, polkit_unix_user_new (0));
+ }
+ else
+ {
+ ret = klass->get_admin_identities (authority,
+ caller,
+ subject,
+ action_id,
+ details);
+ }
+
+ return ret;
+}
+
+/**
+ * polkit_backend_interactive_authority_check_authorization_sync:
+ * @authority: A #PolkitBackendInteractiveAuthority.
+ * @caller: The subject that is inquiring whether @subject is authorized.
+ * @subject: The subject we are checking an authorization for.
+ * @action_id: The action we are checking an authorization for.
+ * @details: Details about the action.
+ * @implicit: A #PolkitImplicitAuthorization value computed from the policy file and @subject.
+ *
+ * Checks whether @subject is authorized to perform the action
+ * specified by @action_id and @details.
+ *
+ * The default implementation of this method simply returns @implicit.
+ *
+ * Returns: A #PolkitImplicitAuthorization that specifies if the subject is authorized or whether
+ * authentication is required.
+ */
+PolkitImplicitAuthorization
+polkit_backend_interactive_authority_check_authorization_sync (PolkitBackendInteractiveAuthority *authority,
+ PolkitSubject *caller,
+ PolkitSubject *subject,
+ const gchar *action_id,
+ PolkitDetails *details,
+ PolkitImplicitAuthorization implicit)
+{
+ PolkitBackendInteractiveAuthorityClass *klass;
+ PolkitImplicitAuthorization ret;
+
+ klass = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_CLASS (authority);
+
+ if (klass->check_authorization_sync == NULL)
+ {
+ ret = implicit;
+ }
+ else
+ {
+ ret = klass->check_authorization_sync (authority,
+ caller,
+ subject,
+ action_id,
+ details,
+ implicit);
+ }
+
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+struct AuthenticationAgent
+{
+ PolkitSubject *session;
+
+ gchar *locale;
+ gchar *object_path;
+ gchar *unique_system_bus_name;
+
+ EggDBusObjectProxy *object_proxy;
+
+ GList *active_sessions;
+};
+
+struct AuthenticationSession
+{
+ AuthenticationAgent *agent;
+
+ gchar *cookie;
+
+ PolkitSubject *subject;
+
+ PolkitIdentity *user_of_subject;
+
+ PolkitBackendInteractiveAuthority *authority;
+
+ GList *identities;
+
+ gchar *action_id;
+
+ gchar *initiated_by_system_bus_unique_name;
+
+ PolkitImplicitAuthorization implicit_authorization;
+
+ AuthenticationAgentCallback callback;
+
+ gpointer user_data;
+
+ guint call_id;
+
+ gboolean is_authenticated;
+
+ GCancellable *cancellable;
+
+ gulong cancellable_signal_handler_id;
+};
+
+static void
+authentication_session_cancelled_cb (GCancellable *cancellable,
+ AuthenticationSession *session)
+{
+ authentication_session_cancel (session);
+}
+
+static AuthenticationSession *
+authentication_session_new (AuthenticationAgent *agent,
+ const gchar *cookie,
+ PolkitSubject *subject,
+ PolkitIdentity *user_of_subject,
+ PolkitBackendInteractiveAuthority *authority,
+ GList *identities,
+ const gchar *action_id,
+ const gchar *initiated_by_system_bus_unique_name,
+ PolkitImplicitAuthorization implicit_authorization,
+ GCancellable *cancellable,
+ AuthenticationAgentCallback callback,
+ gpointer user_data)
+{
+ AuthenticationSession *session;
+
+ session = g_new0 (AuthenticationSession, 1);
+ session->agent = agent;
+ session->cookie = g_strdup (cookie);
+ session->subject = g_object_ref (subject);
+ session->user_of_subject = g_object_ref (user_of_subject);
+ session->authority = g_object_ref (authority);
+ session->identities = g_list_copy (identities);
+ g_list_foreach (session->identities, (GFunc) g_object_ref, NULL);
+ session->action_id = g_strdup (action_id);
+ session->initiated_by_system_bus_unique_name = g_strdup (initiated_by_system_bus_unique_name);
+ session->implicit_authorization = implicit_authorization;
+ session->cancellable = cancellable != NULL ? g_object_ref (cancellable) : NULL;
+ session->callback = callback;
+ session->user_data = user_data;
+
+ if (session->cancellable != NULL)
+ {
+ session->cancellable_signal_handler_id = g_signal_connect (session->cancellable,
+ "cancelled",
+ G_CALLBACK (authentication_session_cancelled_cb),
+ session);
+ }
+
+ return session;
+}
+
+static void
+authentication_session_free (AuthenticationSession *session)
+{
+ g_free (session->cookie);
+ g_list_foreach (session->identities, (GFunc) g_object_unref, NULL);
+ g_list_free (session->identities);
+ g_object_unref (session->subject);
+ g_object_unref (session->user_of_subject);
+ g_object_unref (session->authority);
+ g_free (session->action_id);
+ g_free (session->initiated_by_system_bus_unique_name);
+ if (session->cancellable_signal_handler_id > 0)
+ g_signal_handler_disconnect (session->cancellable, session->cancellable_signal_handler_id);
+ if (session->cancellable != NULL)
+ g_object_unref (session->cancellable);
+ g_free (session);
+}
+
+static gchar *
+authentication_agent_new_cookie (AuthenticationAgent *agent)
+{
+ static gint counter = 0;
+
+ /* TODO: use a more random-looking cookie */
+
+ return g_strdup_printf ("cookie%d", counter++);
+}
+
+static void
+authentication_agent_free (AuthenticationAgent *agent)
+{
+ /* cancel all active authentication sessions; use a copy of the list since
+ * callbacks will modify the list
+ */
+ if (agent->active_sessions != NULL)
+ {
+ GList *l;
+ GList *active_sessions;
+
+ active_sessions = g_list_copy (agent->active_sessions);
+ for (l = active_sessions; l != NULL; l = l->next)
+ {
+ AuthenticationSession *session = l->data;
+
+ authentication_session_cancel (session);
+ }
+ g_list_free (active_sessions);
+ }
+
+ g_object_unref (agent->object_proxy);
+
+ g_object_unref (agent->session);
+ g_free (agent->locale);
+ g_free (agent->object_path);
+ g_free (agent->unique_system_bus_name);
+ g_free (agent);
+}
+
+static AuthenticationAgent *
+authentication_agent_new (PolkitSubject *session,
+ const gchar *unique_system_bus_name,
+ const gchar *locale,
+ const gchar *object_path)
+{
+ AuthenticationAgent *agent;
+ EggDBusConnection *system_bus;
+
+ agent = g_new0 (AuthenticationAgent, 1);
+
+ agent->session = g_object_ref (session);
+ agent->object_path = g_strdup (object_path);
+ agent->unique_system_bus_name = g_strdup (unique_system_bus_name);
+ agent->locale = g_strdup (locale);
+
+ system_bus = egg_dbus_connection_get_for_bus (EGG_DBUS_BUS_TYPE_SYSTEM);
+
+ agent->object_proxy = egg_dbus_connection_get_object_proxy (system_bus,
+ agent->unique_system_bus_name,
+ agent->object_path);
+
+ g_object_unref (system_bus);
+
+ return agent;
+}
+
+static AuthenticationAgent *
+get_authentication_agent_for_subject (PolkitBackendInteractiveAuthority *authority,
+ PolkitSubject *subject)
+{
+ PolkitBackendInteractiveAuthorityPrivate *priv;
+ PolkitSubject *session_for_subject;
+ AuthenticationAgent *agent;
+
+ priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (authority);
+
+ agent = NULL;
+ session_for_subject = NULL;
+
+ session_for_subject = polkit_backend_session_monitor_get_session_for_subject (priv->session_monitor,
+ subject,
+ NULL);
+ if (session_for_subject == NULL)
+ goto out;
+
+ agent = g_hash_table_lookup (priv->hash_session_to_authentication_agent, session_for_subject);
+
+ out:
+ if (session_for_subject != NULL)
+ g_object_unref (session_for_subject);
+
+ return agent;
+}
+
+static AuthenticationSession *
+get_authentication_session_for_cookie (PolkitBackendInteractiveAuthority *authority,
+ const gchar *cookie)
+{
+ PolkitBackendInteractiveAuthorityPrivate *priv;
+ GHashTableIter hash_iter;
+ AuthenticationAgent *agent;
+ AuthenticationSession *result;
+
+ result = NULL;
+
+ /* TODO: perhaps use a hash on the cookie to speed this up */
+
+ priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (authority);
+
+ g_hash_table_iter_init (&hash_iter, priv->hash_session_to_authentication_agent);
+ while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &agent))
+ {
+ GList *l;
+
+ for (l = agent->active_sessions; l != NULL; l = l->next)
+ {
+ AuthenticationSession *session = l->data;
+
+ if (strcmp (session->cookie, cookie) == 0)
+ {
+ result = session;
+ goto out;
+ }
+ }
+ }
+
+ out:
+ return result;
+}
+
+static GList *
+get_authentication_sessions_initiated_by_system_bus_unique_name (PolkitBackendInteractiveAuthority *authority,
+ const gchar *system_bus_unique_name)
+{
+ PolkitBackendInteractiveAuthorityPrivate *priv;
+ GHashTableIter hash_iter;
+ AuthenticationAgent *agent;
+ GList *result;
+
+ result = NULL;
+
+ /* TODO: perhaps use a hash on the cookie to speed this up */
+
+ priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (authority);
+
+ g_hash_table_iter_init (&hash_iter, priv->hash_session_to_authentication_agent);
+ while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &agent))
+ {
+ GList *l;
+
+ for (l = agent->active_sessions; l != NULL; l = l->next)
+ {
+ AuthenticationSession *session = l->data;
+
+ if (strcmp (session->initiated_by_system_bus_unique_name, system_bus_unique_name) == 0)
+ {
+ result = g_list_prepend (result, session);
+ }
+ }
+ }
+
+ return result;
+}
+
+static GList *
+get_authentication_sessions_for_system_bus_unique_name_subject (PolkitBackendInteractiveAuthority *authority,
+ const gchar *system_bus_unique_name)
+{
+ PolkitBackendInteractiveAuthorityPrivate *priv;
+ GHashTableIter hash_iter;
+ AuthenticationAgent *agent;
+ GList *result;
+
+ result = NULL;
+
+ /* TODO: perhaps use a hash on the cookie to speed this up */
+
+ priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (authority);
+
+ g_hash_table_iter_init (&hash_iter, priv->hash_session_to_authentication_agent);
+ while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &agent))
+ {
+ GList *l;
+
+ for (l = agent->active_sessions; l != NULL; l = l->next)
+ {
+ AuthenticationSession *session = l->data;
+
+ if (POLKIT_IS_SYSTEM_BUS_NAME (session->subject) &&
+ strcmp (polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (session->subject)),
+ system_bus_unique_name) == 0)
+ {
+ result = g_list_prepend (result, session);
+ }
+ }
+ }
+
+ return result;
+}
+
+
+static AuthenticationAgent *
+get_authentication_agent_by_unique_system_bus_name (PolkitBackendInteractiveAuthority *authority,
+ const gchar *unique_system_bus_name)
+{
+ PolkitBackendInteractiveAuthorityPrivate *priv;
+ GHashTableIter hash_iter;
+ AuthenticationAgent *agent;
+
+ priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (authority);
+
+ g_hash_table_iter_init (&hash_iter, priv->hash_session_to_authentication_agent);
+ while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &agent))
+ {
+ if (strcmp (agent->unique_system_bus_name, unique_system_bus_name) == 0)
+ goto out;
+ }
+
+ agent = NULL;
+
+ out:
+ return agent;
+}
+
+static void
+authentication_agent_begin_callback (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ _PolkitAuthenticationAgent *agent_dbus = _POLKIT_AUTHENTICATION_AGENT (source_object);
+ AuthenticationSession *session = user_data;
+ GError *error;
+ gboolean gained_authorization;
+
+ error = NULL;
+ if (!_polkit_authentication_agent_begin_authentication_finish (agent_dbus,
+ res,
+ &error))
+ {
+ g_warning ("Error performing authentication: %s", error->message);
+ g_error_free (error);
+ gained_authorization = FALSE;
+ }
+ else
+ {
+ gained_authorization = session->is_authenticated;
+
+ g_debug ("Authentication complete, is_authenticated = %d", session->is_authenticated);
+ }
+
+ session->agent->active_sessions = g_list_remove (session->agent->active_sessions, session);
+
+ session->callback (session->agent,
+ session->subject,
+ session->user_of_subject,
+ session->authority,
+ session->action_id,
+ session->implicit_authorization,
+ gained_authorization,
+ session->user_data);
+
+ authentication_session_free (session);
+}
+
+static GList *
+get_action_lookup_list (void)
+{
+ GList *extensions;
+ GList *l;
+ GIOExtensionPoint *action_lookup_ep;
+ static GList *action_lookup_list = NULL;
+ static gboolean have_looked_up_extensions = FALSE;
+
+ if (have_looked_up_extensions)
+ goto out;
+
+ action_lookup_ep = g_io_extension_point_lookup (POLKIT_BACKEND_ACTION_LOOKUP_EXTENSION_POINT_NAME);
+ g_assert (action_lookup_ep != NULL);
+
+ extensions = g_io_extension_point_get_extensions (action_lookup_ep);
+ for (l = extensions; l != NULL; l = l->next)
+ {
+ GIOExtension *extension = l->data;
+ PolkitBackendActionLookup *lookup;
+
+ lookup = g_object_new (g_io_extension_get_type (extension), NULL);
+ action_lookup_list = g_list_prepend (action_lookup_list, lookup);
+ }
+ action_lookup_list = g_list_reverse (action_lookup_list);
+
+ out:
+ have_looked_up_extensions = TRUE;
+ return action_lookup_list;
+}
+
+static void
+get_localized_data_for_challenge (PolkitBackendInteractiveAuthority *authority,
+ PolkitSubject *caller,
+ PolkitSubject *subject,
+ PolkitIdentity *user_of_subject,
+ const gchar *action_id,
+ PolkitDetails *details,
+ const gchar *locale,
+ gchar **out_localized_message,
+ gchar **out_localized_icon_name,
+ EggDBusHashMap **out_localized_details)
+{
+ PolkitBackendInteractiveAuthorityPrivate *priv;
+ PolkitActionDescription *action_desc;
+ GList *action_lookup_list;
+ GList *l;
+ gchar *message;
+ gchar *icon_name;
+ PolkitDetails *localized_details;
+
+ priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (authority);
+
+ message = NULL;
+ icon_name = NULL;
+ localized_details = NULL;
+ action_desc = NULL;
+
+ *out_localized_message = NULL;
+ *out_localized_icon_name = NULL;
+ *out_localized_details = egg_dbus_hash_map_new (G_TYPE_STRING, NULL,
+ G_TYPE_STRING, NULL);
+
+ action_desc = polkit_backend_action_pool_get_action (priv->action_pool,
+ action_id,
+ locale);
+ if (action_desc == NULL)
+ goto out;
+
+ /* Set LANG and locale so gettext() + friends work when running the code in the extensions */
+ if (setlocale (LC_ALL, locale) == NULL)
+ {
+ g_warning ("Invalid locale '%s'", locale);
+ }
+ g_setenv ("LANG", locale, TRUE);
+
+ /* call into extension points to get localized auth dialog data - the list is sorted by priority */
+ action_lookup_list = get_action_lookup_list ();
+ for (l = action_lookup_list; l != NULL; l = l->next)
+ {
+ PolkitBackendActionLookup *lookup = POLKIT_BACKEND_ACTION_LOOKUP (l->data);
+
+ if (message != NULL && icon_name != NULL && localized_details != NULL)
+ break;
+
+ if (message == NULL)
+ message = polkit_backend_action_lookup_get_message (lookup,
+ action_id,
+ details,
+ action_desc);
+
+ if (icon_name == NULL)
+ icon_name = polkit_backend_action_lookup_get_icon_name (lookup,
+ action_id,
+ details,
+ action_desc);
+
+ if (localized_details == NULL)
+ localized_details = polkit_backend_action_lookup_get_details (lookup,
+ action_id,
+ details,
+ action_desc);
+ }
+
+ /* Back to C! */
+ setlocale (LC_ALL, "C");
+ g_setenv ("LANG", "C", TRUE);
+
+ /* fall back to action description */
+ if (message == NULL)
+ {
+ message = g_strdup (polkit_action_description_get_message (action_desc));
+ }
+ if (icon_name == NULL)
+ {
+ icon_name = g_strdup (polkit_action_description_get_icon_name (action_desc));
+ }
+
+
+ if (localized_details != NULL)
+ {
+ GHashTable *hash;
+ GHashTableIter iter;
+ const gchar *key;
+ const gchar *value;
+
+ hash = polkit_details_get_hash (localized_details);
+ if (hash != NULL)
+ {
+ g_hash_table_iter_init (&iter, hash);
+ while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &value))
+ {
+ egg_dbus_hash_map_insert (*out_localized_details, key, value);
+ }
+ }
+ }
+
+ out:
+ if (message == NULL)
+ message = g_strdup ("");
+ if (icon_name == NULL)
+ icon_name = g_strdup ("");
+ *out_localized_message = message;
+ *out_localized_icon_name = icon_name;
+ if (action_desc != NULL)
+ g_object_unref (action_desc);
+}
+
+static void
+authentication_agent_initiate_challenge (AuthenticationAgent *agent,
+ PolkitSubject *subject,
+ PolkitIdentity *user_of_subject,
+ PolkitBackendInteractiveAuthority *authority,
+ const gchar *action_id,
+ PolkitDetails *details,
+ PolkitSubject *caller,
+ PolkitImplicitAuthorization implicit_authorization,
+ GCancellable *cancellable,
+ AuthenticationAgentCallback callback,
+ gpointer user_data)
+{
+ AuthenticationSession *session;
+ _PolkitAuthenticationAgent *agent_dbus;
+ gchar *cookie;
+ GList *l;
+ GList *identities;
+ EggDBusArraySeq *real_identities;
+ gchar *localized_message;
+ gchar *localized_icon_name;
+ EggDBusHashMap *localized_details;
+
+ get_localized_data_for_challenge (authority,
+ caller,
+ subject,
+ user_of_subject,
+ action_id,
+ details,
+ agent->locale,
+ &localized_message,
+ &localized_icon_name,
+ &localized_details);
+
+ cookie = authentication_agent_new_cookie (agent);
+
+ identities = NULL;
+
+ /* select admin user if required by the implicit authorization */
+ if (implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_ADMINISTRATOR_AUTHENTICATION_REQUIRED ||
+ implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_ADMINISTRATOR_AUTHENTICATION_REQUIRED_RETAINED)
+ {
+ identities = polkit_backend_interactive_authority_get_admin_identities (authority,
+ caller,
+ subject,
+ action_id,
+ details);
+ }
+ else
+ {
+ identities = g_list_prepend (identities, g_object_ref (user_of_subject));
+ }
+
+ session = authentication_session_new (agent,
+ cookie,
+ subject,
+ user_of_subject,
+ authority,
+ identities,
+ action_id,
+ polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (caller)),
+ implicit_authorization,
+ cancellable,
+ callback,
+ user_data);
+
+ agent->active_sessions = g_list_prepend (agent->active_sessions, session);
+
+ agent_dbus = _POLKIT_QUERY_INTERFACE_AUTHENTICATION_AGENT (agent->object_proxy);
+
+ real_identities = egg_dbus_array_seq_new (EGG_DBUS_TYPE_STRUCTURE, g_object_unref, NULL, NULL);
+ for (l = identities; l != NULL; l = l->next)
+ {
+ PolkitIdentity *identity = POLKIT_IDENTITY (l->data);
+ egg_dbus_array_seq_add (real_identities, polkit_identity_get_real (identity));
+ }
+
+ session->call_id = _polkit_authentication_agent_begin_authentication (agent_dbus,
+ EGG_DBUS_CALL_FLAGS_TIMEOUT_NONE,
+ action_id,
+ localized_message,
+ localized_icon_name,
+ localized_details,
+ session->cookie,
+ real_identities,
+ NULL,
+ authentication_agent_begin_callback,
+ session);
+
+ g_list_foreach (identities, (GFunc) g_object_unref, NULL);
+ g_list_free (identities);
+ g_object_unref (real_identities);
+ g_free (cookie);
+
+ g_free (localized_message);
+ g_free (localized_icon_name);
+ g_object_unref (localized_details);
+}
+
+static void
+authentication_agent_cancel_callback (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ _PolkitAuthenticationAgent *agent_dbus = _POLKIT_AUTHENTICATION_AGENT (source_object);
+
+ _polkit_authentication_agent_cancel_authentication_finish (agent_dbus,
+ res,
+ NULL);
+}
+
+static void
+authentication_session_cancel (AuthenticationSession *session)
+{
+ EggDBusConnection *system_bus;
+ _PolkitAuthenticationAgent *agent_dbus;
+
+ system_bus = egg_dbus_connection_get_for_bus (EGG_DBUS_BUS_TYPE_SYSTEM);
+
+ agent_dbus = _POLKIT_QUERY_INTERFACE_AUTHENTICATION_AGENT (session->agent->object_proxy);
+
+ _polkit_authentication_agent_cancel_authentication (agent_dbus,
+ EGG_DBUS_CALL_FLAGS_NONE,
+ session->cookie,
+ NULL,
+ authentication_agent_cancel_callback,
+ NULL);
+
+ egg_dbus_connection_pending_call_cancel (system_bus, session->call_id);
+
+ g_object_unref (system_bus);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gboolean
+polkit_backend_interactive_authority_register_authentication_agent (PolkitBackendAuthority *authority,
+ PolkitSubject *caller,
+ const gchar *session_id,
+ const gchar *locale,
+ const gchar *object_path,
+ GError **error)
+{
+ PolkitBackendInteractiveAuthority *interactive_authority;
+ PolkitBackendInteractiveAuthorityPrivate *priv;
+ PolkitSubject *session_for_caller;
+ AuthenticationAgent *agent;
+ gboolean ret;
+
+ session_for_caller = NULL;
+ ret = FALSE;
+
+ interactive_authority = POLKIT_BACKEND_INTERACTIVE_AUTHORITY (authority);
+ priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (interactive_authority);
+
+ if (session_id != NULL && strlen (session_id) > 0)
+ {
+ g_set_error (error,
+ POLKIT_ERROR,
+ POLKIT_ERROR_FAILED,
+ "The session_id parameter must be blank for now.");
+ goto out;
+ }
+
+ session_for_caller = polkit_backend_session_monitor_get_session_for_subject (priv->session_monitor,
+ caller,
+ NULL);
+ if (session_for_caller == NULL)
+ {
+ g_set_error (error,
+ POLKIT_ERROR,
+ POLKIT_ERROR_FAILED,
+ "Cannot determine session");
+ goto out;
+ }
+
+ agent = g_hash_table_lookup (priv->hash_session_to_authentication_agent, session_for_caller);
+ if (agent != NULL)
+ {
+ g_set_error (error,
+ POLKIT_ERROR,
+ POLKIT_ERROR_FAILED,
+ "An authentication agent already exists for session");
+ goto out;
+ }
+
+ /* TODO: validate that object path is well-formed */
+
+ agent = authentication_agent_new (session_for_caller,
+ polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (caller)),
+ locale,
+ object_path);
+
+ g_hash_table_insert (priv->hash_session_to_authentication_agent,
+ g_object_ref (session_for_caller),
+ agent);
+
+ g_debug ("Added authentication agent for session %s at name %s, object path %s, locale %s",
+ polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (session_for_caller)),
+ polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (caller)),
+ object_path,
+ locale);
+
+ ret = TRUE;
+
+ out:
+ if (session_for_caller != NULL)
+ g_object_unref (session_for_caller);
+
+ return ret;
+}
+
+static gboolean
+polkit_backend_interactive_authority_unregister_authentication_agent (PolkitBackendAuthority *authority,
+ PolkitSubject *caller,
+ const gchar *session_id,
+ const gchar *object_path,
+ GError **error)
+{
+ PolkitBackendInteractiveAuthority *interactive_authority;
+ PolkitBackendInteractiveAuthorityPrivate *priv;
+ PolkitSubject *session_for_caller;
+ AuthenticationAgent *agent;
+ gboolean ret;
+
+ interactive_authority = POLKIT_BACKEND_INTERACTIVE_AUTHORITY (authority);
+ priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (interactive_authority);
+
+ ret = FALSE;
+ session_for_caller = NULL;
+
+ if (session_id != NULL && strlen (session_id) > 0)
+ {
+ g_set_error (error,
+ POLKIT_ERROR,
+ POLKIT_ERROR_FAILED,
+ "The session_id parameter must be blank for now.");
+ goto out;
+ }
+
+ session_for_caller = polkit_backend_session_monitor_get_session_for_subject (priv->session_monitor,
+ caller,
+ NULL);
+ if (session_for_caller == NULL)
+ {
+ g_set_error (error,
+ POLKIT_ERROR,
+ POLKIT_ERROR_FAILED,
+ "Cannot determine session");
+ goto out;
+ }
+
+ agent = g_hash_table_lookup (priv->hash_session_to_authentication_agent, session_for_caller);
+ if (agent == NULL)
+ {
+ g_set_error (error,
+ POLKIT_ERROR,
+ POLKIT_ERROR_FAILED,
+ "No such agent registered");
+ goto out;
+ }
+
+ if (strcmp (agent->unique_system_bus_name,
+ polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (caller))) != 0)
+ {
+ g_set_error (error,
+ POLKIT_ERROR,
+ POLKIT_ERROR_FAILED,
+ "System bus names do not match");
+ goto out;
+ }
+
+ if (strcmp (agent->object_path, object_path) != 0)
+ {
+ g_set_error (error,
+ POLKIT_ERROR,
+ POLKIT_ERROR_FAILED,
+ "Object paths do not match");
+ goto out;
+ }
+
+
+ g_debug ("Removing authentication agent for session %s at name %s, object path %s (unregistered)",
+ polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (agent->session)),
+ agent->unique_system_bus_name,
+ agent->object_path);
+
+ /* this works because we have exactly one agent per session */
+ g_hash_table_remove (priv->hash_session_to_authentication_agent, agent->session);
+
+ ret = TRUE;
+
+ out:
+ if (session_for_caller != NULL)
+ g_object_unref (session_for_caller);
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gboolean
+polkit_backend_interactive_authority_authentication_agent_response (PolkitBackendAuthority *authority,
+ PolkitSubject *caller,
+ const gchar *cookie,
+ PolkitIdentity *identity,
+ GError **error)
+{
+ PolkitBackendInteractiveAuthority *interactive_authority;
+ PolkitBackendInteractiveAuthorityPrivate *priv;
+ PolkitIdentity *user_of_caller;
+ gchar *identity_str;
+ AuthenticationSession *session;
+ GList *l;
+ gboolean ret;
+
+ interactive_authority = POLKIT_BACKEND_INTERACTIVE_AUTHORITY (authority);
+ priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (interactive_authority);
+
+ ret = FALSE;
+ user_of_caller = NULL;
+
+ identity_str = polkit_identity_to_string (identity);
+
+ g_debug ("In authentication_agent_response for cookie '%s' and identity %s",
+ cookie,
+ identity_str);
+
+ user_of_caller = polkit_backend_session_monitor_get_user_for_subject (priv->session_monitor,
+ caller,
+ error);
+ if (user_of_caller == NULL)
+ goto out;
+
+ /* only uid 0 is allowed to invoke this method */
+ if (!POLKIT_IS_UNIX_USER (user_of_caller) || polkit_unix_user_get_uid (POLKIT_UNIX_USER (user_of_caller)) != 0)
+ {
+ g_set_error (error,
+ POLKIT_ERROR,
+ POLKIT_ERROR_FAILED,
+ "Only uid 0 may invoke this method. This incident has been logged.");
+ /* TODO: actually log this */
+ goto out;
+ }
+
+ /* find the authentication session */
+ session = get_authentication_session_for_cookie (interactive_authority, cookie);
+ if (session == NULL)
+ {
+ g_set_error (error,
+ POLKIT_ERROR,
+ POLKIT_ERROR_FAILED,
+ "No session for cookie");
+ goto out;
+ }
+
+ /* check that the authentication identity was one of the possibilities we allowed */
+ for (l = session->identities; l != NULL; l = l->next)
+ {
+ PolkitIdentity *i = POLKIT_IDENTITY (l->data);
+
+ if (polkit_identity_equal (i, identity))
+ break;
+ }
+
+ if (l == NULL)
+ {
+ g_set_error (error,
+ POLKIT_ERROR,
+ POLKIT_ERROR_FAILED,
+ "The authenticated identity is wrong");
+ goto out;
+ }
+
+ /* checks out, mark the session as authenticated */
+ session->is_authenticated = TRUE;
+
+ ret = TRUE;
+
+ out:
+ g_free (identity_str);
+
+ if (user_of_caller != NULL)
+ g_object_unref (user_of_caller);
+
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+polkit_backend_interactive_authority_system_bus_name_owner_changed (PolkitBackendAuthority *authority,
+ const gchar *name,
+ const gchar *old_owner,
+ const gchar *new_owner)
+{
+ PolkitBackendInteractiveAuthority *interactive_authority;
+ PolkitBackendInteractiveAuthorityPrivate *priv;
+
+ interactive_authority = POLKIT_BACKEND_INTERACTIVE_AUTHORITY (authority);
+ priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (interactive_authority);
+
+ //g_debug ("name-owner-changed: '%s' '%s' '%s'", name, old_owner, new_owner);
+
+ if (name[0] == ':' && strlen (new_owner) == 0)
+ {
+ AuthenticationAgent *agent;
+ GList *sessions;
+ GList *l;
+
+ agent = get_authentication_agent_by_unique_system_bus_name (interactive_authority, name);
+ if (agent != NULL)
+ {
+ g_debug ("Removing authentication agent for session %s at name %s, object path %s (disconnected from bus)",
+ polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (agent->session)),
+ agent->unique_system_bus_name,
+ agent->object_path);
+
+ /* this works because we have exactly one agent per session */
+ g_hash_table_remove (priv->hash_session_to_authentication_agent, agent->session);
+ }
+
+ /* cancel all authentication sessions initiated by the process owning the vanished name */
+ sessions = get_authentication_sessions_initiated_by_system_bus_unique_name (interactive_authority, name);
+ for (l = sessions; l != NULL; l = l->next)
+ {
+ AuthenticationSession *session = l->data;
+
+ authentication_session_cancel (session);
+ }
+ g_list_free (sessions);
+
+ /* cancel all authentication sessions that is about the vanished name */
+ sessions = get_authentication_sessions_for_system_bus_unique_name_subject (interactive_authority, name);
+ for (l = sessions; l != NULL; l = l->next)
+ {
+ AuthenticationSession *session = l->data;
+
+ authentication_session_cancel (session);
+ }
+ g_list_free (sessions);
+
+ }
+
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+typedef struct TemporaryAuthorization TemporaryAuthorization;
+
+struct TemporaryAuthorizationStore
+{
+ GList *authorizations;
+};
+
+struct TemporaryAuthorization
+{
+ PolkitSubject *subject;
+ gchar *action_id;
+ guint64 time_granted;
+};
+
+static void
+temporary_authorization_free (TemporaryAuthorization *authorization)
+{
+ g_object_unref (authorization->subject);
+ g_free (authorization->action_id);
+ g_free (authorization);
+}
+
+static TemporaryAuthorization *
+temporary_authorization_new (PolkitSubject *subject,
+ const gchar *action_id)
+{
+ TemporaryAuthorization *authorization;
+
+ authorization = g_new0 (TemporaryAuthorization, 1);
+ authorization->subject = g_object_ref (subject);
+ authorization->action_id = g_strdup (action_id);
+ authorization->time_granted = time (NULL);
+
+ return authorization;
+}
+
+static TemporaryAuthorizationStore *
+temporary_authorization_store_new (void)
+{
+ TemporaryAuthorizationStore *store;
+
+ store = g_new0 (TemporaryAuthorizationStore, 1);
+ store->authorizations = NULL;
+
+ return store;
+}
+
+static void
+temporary_authorization_store_free (TemporaryAuthorizationStore *store)
+{
+ g_list_foreach (store->authorizations, (GFunc) temporary_authorization_free, NULL);
+ g_list_free (store->authorizations);
+ g_free (store);
+}
+
+static gboolean
+temporary_authorization_store_has_authorization (TemporaryAuthorizationStore *store,
+ PolkitSubject *subject,
+ const gchar *action_id)
+{
+ GList *l;
+ gboolean ret;
+
+ g_return_val_if_fail (store != NULL, FALSE);
+ g_return_val_if_fail (POLKIT_IS_SUBJECT (subject), FALSE);
+ g_return_val_if_fail (action_id != NULL, FALSE);
+
+ ret = FALSE;
+
+ for (l = store->authorizations; l != NULL; l = l->next) {
+ TemporaryAuthorization *authorization = l->data;
+
+ if (strcmp (action_id, authorization->action_id) == 0 &&
+ polkit_subject_equal (subject, authorization->subject))
+ {
+ ret = TRUE;
+ goto out;
+ }
+ }
+
+ out:
+ return ret;
+}
+
+static void
+temporary_authorization_store_add_authorization (TemporaryAuthorizationStore *store,
+ PolkitSubject *subject,
+ const gchar *action_id)
+{
+ g_return_if_fail (store != NULL);
+ g_return_if_fail (POLKIT_IS_SUBJECT (subject));
+ g_return_if_fail (action_id != NULL);
+ g_return_if_fail (!temporary_authorization_store_has_authorization (store, subject, action_id));
+
+ store->authorizations = g_list_prepend (store->authorizations,
+ temporary_authorization_new (subject, action_id));
+}
diff --git a/src/polkitbackend/polkitbackendinteractiveauthority.h b/src/polkitbackend/polkitbackendinteractiveauthority.h
new file mode 100644
index 0000000..efef0a4
--- /dev/null
+++ b/src/polkitbackend/polkitbackendinteractiveauthority.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz at redhat.com>
+ */
+
+#if !defined (_POLKIT_BACKEND_COMPILATION) && !defined(_POLKIT_BACKEND_INSIDE_POLKIT_BACKEND_H)
+#error "Only <polkitbackend/polkitbackend.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef __POLKIT_BACKEND_INTERACTIVE_AUTHORITY_H
+#define __POLKIT_BACKEND_INTERACTIVE_AUTHORITY_H
+
+#include <glib-object.h>
+#include <polkitbackend/polkitbackendtypes.h>
+#include <polkitbackend/polkitbackendauthority.h>
+
+G_BEGIN_DECLS
+
+#define POLKIT_BACKEND_TYPE_INTERACTIVE_AUTHORITY (polkit_backend_interactive_authority_get_type ())
+#define POLKIT_BACKEND_INTERACTIVE_AUTHORITY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), POLKIT_BACKEND_TYPE_INTERACTIVE_AUTHORITY, PolkitBackendInteractiveAuthority))
+#define POLKIT_BACKEND_INTERACTIVE_AUTHORITY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), POLKIT_BACKEND_TYPE_INTERACTIVE_AUTHORITY, PolkitBackendInteractiveAuthorityClass))
+#define POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), POLKIT_BACKEND_TYPE_INTERACTIVE_AUTHORITY,PolkitBackendInteractiveAuthorityClass))
+#define POLKIT_BACKEND_IS_INTERACTIVE_AUTHORITY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), POLKIT_BACKEND_TYPE_INTERACTIVE_AUTHORITY))
+#define POLKIT_BACKEND_IS_INTERACTIVE_AUTHORITY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), POLKIT_BACKEND_TYPE_INTERACTIVE_AUTHORITY))
+
+typedef struct _PolkitBackendInteractiveAuthorityClass PolkitBackendInteractiveAuthorityClass;
+
+/**
+ * PolkitBackendInteractiveAuthority:
+ *
+ * The #PolkitBackendInteractiveAuthority struct should not be accessed directly.
+ */
+struct _PolkitBackendInteractiveAuthority
+{
+ /*< private >*/
+ PolkitBackendAuthority parent_instance;
+};
+
+/**
+ * PolkitBackendInteractiveAuthorityClass:
+ * @parent_class: The parent class.
+ * @get_admin_identities: Returns list of identities for administrator authentication or %NULL to use the default
+ * implementation. See polkit_backend_interactive_authority_get_admin_identities() for details.
+ * @check_authorization_sync: Checks for an authorization or %NULL to use the default implementation.
+ * See polkit_backend_interactive_authority_check_authorization_sync() for details.
+ *
+ * Class structure for #PolkitBackendInteractiveAuthority.
+ */
+struct _PolkitBackendInteractiveAuthorityClass
+{
+ /*< public >*/
+ PolkitBackendAuthorityClass parent_class;
+
+ /* VTable */
+ GList * (*get_admin_identities) (PolkitBackendInteractiveAuthority *authority,
+ PolkitSubject *caller,
+ PolkitSubject *subject,
+ const gchar *action_id,
+ PolkitDetails *details);
+
+ PolkitImplicitAuthorization (*check_authorization_sync) (PolkitBackendInteractiveAuthority *authority,
+ PolkitSubject *caller,
+ PolkitSubject *subject,
+ const gchar *action_id,
+ PolkitDetails *details,
+ PolkitImplicitAuthorization implicit);
+
+ /*< private >*/
+ /* Padding for future expansion */
+ void (*_polkit_reserved1) (void);
+ void (*_polkit_reserved2) (void);
+ void (*_polkit_reserved3) (void);
+ void (*_polkit_reserved4) (void);
+ void (*_polkit_reserved5) (void);
+ void (*_polkit_reserved6) (void);
+ void (*_polkit_reserved7) (void);
+ void (*_polkit_reserved8) (void);
+ void (*_polkit_reserved9) (void);
+ void (*_polkit_reserved10) (void);
+ void (*_polkit_reserved11) (void);
+ void (*_polkit_reserved12) (void);
+ void (*_polkit_reserved13) (void);
+ void (*_polkit_reserved14) (void);
+ void (*_polkit_reserved15) (void);
+ void (*_polkit_reserved16) (void);
+ void (*_polkit_reserved17) (void);
+ void (*_polkit_reserved18) (void);
+ void (*_polkit_reserved19) (void);
+ void (*_polkit_reserved20) (void);
+ void (*_polkit_reserved21) (void);
+ void (*_polkit_reserved22) (void);
+ void (*_polkit_reserved23) (void);
+ void (*_polkit_reserved24) (void);
+ void (*_polkit_reserved25) (void);
+ void (*_polkit_reserved26) (void);
+ void (*_polkit_reserved27) (void);
+ void (*_polkit_reserved28) (void);
+ void (*_polkit_reserved29) (void);
+ void (*_polkit_reserved30) (void);
+ void (*_polkit_reserved31) (void);
+ void (*_polkit_reserved32) (void);
+};
+
+GType polkit_backend_interactive_authority_get_type (void) G_GNUC_CONST;
+GList *polkit_backend_interactive_authority_get_admin_identities (PolkitBackendInteractiveAuthority *authority,
+ PolkitSubject *caller,
+ PolkitSubject *subject,
+ const gchar *action_id,
+ PolkitDetails *details);
+
+PolkitImplicitAuthorization polkit_backend_interactive_authority_check_authorization_sync (
+ PolkitBackendInteractiveAuthority *authority,
+ PolkitSubject *caller,
+ PolkitSubject *subject,
+ const gchar *action_id,
+ PolkitDetails *details,
+ PolkitImplicitAuthorization implicit);
+
+G_END_DECLS
+
+#endif /* __POLKIT_BACKEND_INTERACTIVE_AUTHORITY_H */
+
diff --git a/src/polkitbackend/polkitbackendlocalauthority.c b/src/polkitbackend/polkitbackendlocalauthority.c
index 4bfa7da..a68663d 100644
--- a/src/polkitbackend/polkitbackendlocalauthority.c
+++ b/src/polkitbackend/polkitbackendlocalauthority.c
@@ -28,11 +28,8 @@
#include <locale.h>
#include <polkit/polkit.h>
-#include "polkitbackendlocalauthority.h"
-#include "polkitbackendactionpool.h"
-#include "polkitbackendsessionmonitor.h"
#include "polkitbackendconfigsource.h"
-#include "polkitbackendactionlookup.h"
+#include "polkitbackendlocalauthority.h"
#include <polkit/polkitprivate.h>
@@ -48,148 +45,37 @@
/* ---------------------------------------------------------------------------------------------------- */
-typedef struct TemporaryAuthorizationStore TemporaryAuthorizationStore;
-
-static TemporaryAuthorizationStore *temporary_authorization_store_new (void);
-static void temporary_authorization_store_free (TemporaryAuthorizationStore *store);
-
-static gboolean temporary_authorization_store_has_authorization (TemporaryAuthorizationStore *store,
- PolkitSubject *subject,
- const gchar *action_id);
-
-static void temporary_authorization_store_add_authorization (TemporaryAuthorizationStore *store,
- PolkitSubject *subject,
- const gchar *action_id);
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-struct AuthenticationAgent;
-typedef struct AuthenticationAgent AuthenticationAgent;
-
-struct AuthenticationSession;
-typedef struct AuthenticationSession AuthenticationSession;
-
-typedef void (*AuthenticationAgentCallback) (AuthenticationAgent *agent,
- PolkitSubject *subject,
- PolkitIdentity *user_of_subject,
- PolkitBackendLocalAuthority *authority,
- const gchar *action_id,
- PolkitImplicitAuthorization implicit_authorization,
- gboolean authentication_success,
- gpointer user_data);
-
-static void authentication_agent_free (AuthenticationAgent *agent);
-
-static void authentication_agent_initiate_challenge (AuthenticationAgent *agent,
- PolkitSubject *subject,
- PolkitIdentity *user_of_subject,
- PolkitBackendLocalAuthority *authority,
- const gchar *action_id,
- PolkitDetails *details,
- PolkitSubject *caller,
- PolkitImplicitAuthorization implicit_authorization,
- GCancellable *cancellable,
- AuthenticationAgentCallback callback,
- gpointer user_data);
-
-static AuthenticationAgent *get_authentication_agent_for_subject (PolkitBackendLocalAuthority *authority,
- PolkitSubject *subject);
-
-static AuthenticationSession *get_authentication_session_for_cookie (PolkitBackendLocalAuthority *authority,
- const gchar *cookie);
-
-static GList *get_authentication_sessions_initiated_by_system_bus_unique_name (PolkitBackendLocalAuthority *authority,
- const gchar *system_bus_unique_name);
-
-static void authentication_session_cancel (AuthenticationSession *session);
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static GList *get_users_in_group (PolkitBackendLocalAuthority *authority,
+static GList *get_users_in_group (PolkitBackendInteractiveAuthority *authority,
PolkitIdentity *group,
gboolean include_root);
#if 0
-static GList *get_groups_for_user (PolkitBackendLocalAuthority *authority,
+static GList *get_groups_for_user (PolkitBackendInteractiveAuthority *authority,
PolkitIdentity *user);
#endif
/* ---------------------------------------------------------------------------------------------------- */
-static void polkit_backend_local_authority_system_bus_name_owner_changed (PolkitBackendAuthority *authority,
- const gchar *name,
- const gchar *old_owner,
- const gchar *new_owner);
-
-static GList *polkit_backend_local_authority_enumerate_actions (PolkitBackendAuthority *authority,
- PolkitSubject *caller,
- const gchar *locale,
- GError **error);
-
-static void polkit_backend_local_authority_check_authorization (PolkitBackendAuthority *authority,
- PolkitSubject *caller,
- PolkitSubject *subject,
- const gchar *action_id,
- PolkitDetails *details,
- PolkitCheckAuthorizationFlags flags,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-
-static PolkitAuthorizationResult *polkit_backend_local_authority_check_authorization_finish (
- PolkitBackendAuthority *authority,
- GAsyncResult *res,
- GError **error);
-
-static PolkitAuthorizationResult *check_authorization_sync (PolkitBackendAuthority *authority,
- PolkitSubject *subject,
- const gchar *action_id,
- PolkitCheckAuthorizationFlags flags,
- PolkitImplicitAuthorization *out_implicit_authorization,
- GError **error);
-
-static gboolean polkit_backend_local_authority_register_authentication_agent (PolkitBackendAuthority *authority,
- PolkitSubject *caller,
- const gchar *session_id,
- const gchar *locale,
- const gchar *object_path,
- GError **error);
-
-static gboolean polkit_backend_local_authority_unregister_authentication_agent (PolkitBackendAuthority *authority,
- PolkitSubject *caller,
- const gchar *session_id,
- const gchar *object_path,
- GError **error);
-
-static gboolean polkit_backend_local_authority_authentication_agent_response (PolkitBackendAuthority *authority,
- PolkitSubject *caller,
- const gchar *cookie,
- PolkitIdentity *identity,
- GError **error);
-
-
-/* ---------------------------------------------------------------------------------------------------- */
-
typedef struct
{
- PolkitBackendActionPool *action_pool;
-
- PolkitBackendSessionMonitor *session_monitor;
-
PolkitBackendConfigSource *config_source;
- TemporaryAuthorizationStore *temporary_authorization_store;
-
- GHashTable *hash_session_to_authentication_agent;
-
} PolkitBackendLocalAuthorityPrivate;
/* ---------------------------------------------------------------------------------------------------- */
-G_DEFINE_TYPE_WITH_CODE (PolkitBackendLocalAuthority, polkit_backend_local_authority,POLKIT_BACKEND_TYPE_AUTHORITY,
+static GList *polkit_backend_local_authority_get_admin_auth_identities (PolkitBackendInteractiveAuthority *authority,
+ PolkitSubject *caller,
+ PolkitSubject *subject,
+ const gchar *action_id,
+ PolkitDetails *details);
+
+G_DEFINE_TYPE_WITH_CODE (PolkitBackendLocalAuthority,
+ polkit_backend_local_authority,
+ POLKIT_BACKEND_TYPE_INTERACTIVE_AUTHORITY,
g_io_extension_point_implement (POLKIT_BACKEND_AUTHORITY_EXTENSION_POINT_NAME,
g_define_type_id,
- "local-files " PACKAGE_VERSION,
+ "local-authority" PACKAGE_VERSION,
0));
#define POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), POLKIT_BACKEND_TYPE_LOCAL_AUTHORITY, PolkitBackendLocalAuthorityPrivate))
@@ -197,15 +83,6 @@ G_DEFINE_TYPE_WITH_CODE (PolkitBackendLocalAuthority, polkit_backend_local_autho
/* ---------------------------------------------------------------------------------------------------- */
static void
-action_pool_changed (PolkitBackendActionPool *action_pool,
- PolkitBackendLocalAuthority *authority)
-{
- g_signal_emit_by_name (authority, "changed");
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static void
polkit_backend_local_authority_init (PolkitBackendLocalAuthority *authority)
{
PolkitBackendLocalAuthorityPrivate *priv;
@@ -213,26 +90,9 @@ polkit_backend_local_authority_init (PolkitBackendLocalAuthority *authority)
priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (authority);
- directory = g_file_new_for_path (PACKAGE_DATA_DIR "/polkit-1/actions");
- priv->action_pool = polkit_backend_action_pool_new (directory);
- g_object_unref (directory);
- g_signal_connect (priv->action_pool,
- "changed",
- (GCallback) action_pool_changed,
- authority);
-
directory = g_file_new_for_path (PACKAGE_SYSCONF_DIR "/polkit-1/localauthority.conf.d");
priv->config_source = polkit_backend_config_source_new (directory);
g_object_unref (directory);
-
- priv->temporary_authorization_store = temporary_authorization_store_new ();
-
- priv->hash_session_to_authentication_agent = g_hash_table_new_full ((GHashFunc) polkit_subject_hash,
- (GEqualFunc) polkit_subject_equal,
- (GDestroyNotify) g_object_unref,
- (GDestroyNotify) authentication_agent_free);
-
- priv->session_monitor = polkit_backend_session_monitor_new ();
}
static void
@@ -244,19 +104,9 @@ polkit_backend_local_authority_finalize (GObject *object)
local_authority = POLKIT_BACKEND_LOCAL_AUTHORITY (object);
priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (local_authority);
- if (priv->action_pool != NULL)
- g_object_unref (priv->action_pool);
-
if (priv->config_source != NULL)
g_object_unref (priv->config_source);
- if (priv->session_monitor != NULL)
- g_object_unref (priv->session_monitor);
-
- temporary_authorization_store_free (priv->temporary_authorization_store);
-
- g_hash_table_unref (priv->hash_session_to_authentication_agent);
-
G_OBJECT_CLASS (polkit_backend_local_authority_parent_class)->finalize (object);
}
@@ -264,863 +114,33 @@ static void
polkit_backend_local_authority_class_init (PolkitBackendLocalAuthorityClass *klass)
{
GObjectClass *gobject_class;
- PolkitBackendAuthorityClass *authority_class;
+ PolkitBackendInteractiveAuthorityClass *interactive_authority_class;
gobject_class = G_OBJECT_CLASS (klass);
- authority_class = POLKIT_BACKEND_AUTHORITY_CLASS (klass);
-
- gobject_class->finalize = polkit_backend_local_authority_finalize;
-
- authority_class->system_bus_name_owner_changed = polkit_backend_local_authority_system_bus_name_owner_changed;
- authority_class->enumerate_actions = polkit_backend_local_authority_enumerate_actions;
- authority_class->check_authorization = polkit_backend_local_authority_check_authorization;
- authority_class->check_authorization_finish = polkit_backend_local_authority_check_authorization_finish;
- authority_class->register_authentication_agent = polkit_backend_local_authority_register_authentication_agent;
- authority_class->unregister_authentication_agent = polkit_backend_local_authority_unregister_authentication_agent;
- authority_class->authentication_agent_response = polkit_backend_local_authority_authentication_agent_response;
+ interactive_authority_class = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_CLASS (klass);
+ gobject_class->finalize = polkit_backend_local_authority_finalize;
+ interactive_authority_class->get_admin_identities = polkit_backend_local_authority_get_admin_auth_identities;
g_type_class_add_private (klass, sizeof (PolkitBackendLocalAuthorityPrivate));
}
-PolkitBackendAuthority *
-polkit_backend_local_authority_new (void)
-{
- return POLKIT_BACKEND_AUTHORITY (g_object_new (POLKIT_BACKEND_TYPE_LOCAL_AUTHORITY,
- NULL));
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
static GList *
-polkit_backend_local_authority_enumerate_actions (PolkitBackendAuthority *authority,
- PolkitSubject *caller,
- const gchar *locale,
- GError **error)
-{
- PolkitBackendLocalAuthority *local_authority;
- PolkitBackendLocalAuthorityPrivate *priv;
- GList *actions;
-
- local_authority = POLKIT_BACKEND_LOCAL_AUTHORITY (authority);
- priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (local_authority);
-
- actions = polkit_backend_action_pool_get_all_actions (priv->action_pool, locale);
-
- return actions;
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static void
-check_authorization_challenge_cb (AuthenticationAgent *agent,
- PolkitSubject *subject,
- PolkitIdentity *user_of_subject,
- PolkitBackendLocalAuthority *authority,
- const gchar *action_id,
- PolkitImplicitAuthorization implicit_authorization,
- gboolean authentication_success,
- gpointer user_data)
-{
- GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
- PolkitBackendLocalAuthorityPrivate *priv;
- PolkitAuthorizationResult *result;
- gchar *subject_str;
-
- priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (authority);
-
- result = NULL;
- subject_str = polkit_subject_to_string (subject);
-
- g_debug ("In check_authorization_challenge_cb\n"
- " subject %s\n"
- " action_id %s\n"
- " authentication_success %d\n",
- subject_str,
- action_id,
- authentication_success);
-
- if (authentication_success)
- {
- result = polkit_authorization_result_new (TRUE, FALSE, NULL);
-
- /* store temporary authorization depending on value of implicit_authorization */
- if (implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_AUTHENTICATION_REQUIRED_RETAINED ||
- implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_ADMINISTRATOR_AUTHENTICATION_REQUIRED_RETAINED)
- {
- temporary_authorization_store_add_authorization (priv->temporary_authorization_store,
- subject,
- action_id);
- }
- }
- else
- {
- /* TODO: maybe return set is_challenge? */
- result = polkit_authorization_result_new (FALSE, FALSE, NULL);
- }
-
- g_simple_async_result_set_op_res_gpointer (simple,
- result,
- g_object_unref);
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
-
- g_free (subject_str);
-}
-
-static PolkitAuthorizationResult *
-polkit_backend_local_authority_check_authorization_finish (PolkitBackendAuthority *authority,
- GAsyncResult *res,
- GError **error)
-{
- GSimpleAsyncResult *simple;
- PolkitAuthorizationResult *result;
-
- simple = G_SIMPLE_ASYNC_RESULT (res);
-
- g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == polkit_backend_local_authority_check_authorization);
-
- result = NULL;
-
- if (g_simple_async_result_propagate_error (simple, error))
- goto out;
-
- result = g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
-
- out:
- return result;
-}
-
-static void
-polkit_backend_local_authority_check_authorization (PolkitBackendAuthority *authority,
- PolkitSubject *caller,
- PolkitSubject *subject,
- const gchar *action_id,
- PolkitDetails *details,
- PolkitCheckAuthorizationFlags flags,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
+polkit_backend_local_authority_get_admin_auth_identities (PolkitBackendInteractiveAuthority *authority,
+ PolkitSubject *caller,
+ PolkitSubject *subject,
+ const gchar *action_id,
+ PolkitDetails *details)
{
PolkitBackendLocalAuthority *local_authority;
PolkitBackendLocalAuthorityPrivate *priv;
- gchar *caller_str;
- gchar *subject_str;
- PolkitIdentity *user_of_caller;
- PolkitIdentity *user_of_subject;
- gchar *user_of_caller_str;
- gchar *user_of_subject_str;
- PolkitAuthorizationResult *result;
- PolkitImplicitAuthorization implicit_authorization;
- GError *error;
- GSimpleAsyncResult *simple;
-
- local_authority = POLKIT_BACKEND_LOCAL_AUTHORITY (authority);
- priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (local_authority);
-
- error = NULL;
- caller_str = NULL;
- subject_str = NULL;
- user_of_caller = NULL;
- user_of_subject = NULL;
- user_of_caller_str = NULL;
- user_of_subject_str = NULL;
- result = NULL;
-
- simple = g_simple_async_result_new (G_OBJECT (authority),
- callback,
- user_data,
- polkit_backend_local_authority_check_authorization);
-
- caller_str = polkit_subject_to_string (caller);
- subject_str = polkit_subject_to_string (subject);
-
- g_debug ("%s is inquiring whether %s is authorized for %s",
- caller_str,
- subject_str,
- action_id);
-
- user_of_caller = polkit_backend_session_monitor_get_user_for_subject (priv->session_monitor,
- caller,
- &error);
- if (error != NULL)
- {
- g_simple_async_result_set_from_error (simple, error);
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
- g_error_free (error);
- goto out;
- }
-
- user_of_caller_str = polkit_identity_to_string (user_of_caller);
- g_debug (" user of caller is %s", user_of_caller_str);
-
- /* we only allow trusted callers (uid 0 + others) to check authorizations */
- if (!POLKIT_IS_UNIX_USER (user_of_caller) ||
- polkit_unix_user_get_uid (POLKIT_UNIX_USER (user_of_caller)) != 0) /* TODO: allow other uids like 'haldaemon'? */
- {
- g_simple_async_result_set_error (simple,
- POLKIT_ERROR,
- POLKIT_ERROR_NOT_AUTHORIZED,
- "Only trusted callers can use CheckAuthorization(), %s is not trusted",
- user_of_caller_str);
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
- goto out;
- }
-
- user_of_subject = polkit_backend_session_monitor_get_user_for_subject (priv->session_monitor,
- subject,
- &error);
- if (error != NULL)
- {
- g_simple_async_result_set_from_error (simple, error);
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
- g_error_free (error);
- goto out;
- }
-
- user_of_subject_str = polkit_identity_to_string (user_of_subject);
- g_debug (" user of subject is %s", user_of_subject_str);
-
- implicit_authorization = POLKIT_IMPLICIT_AUTHORIZATION_NOT_AUTHORIZED;
- result = check_authorization_sync (authority,
- subject,
- action_id,
- flags,
- &implicit_authorization,
- &error);
- if (error != NULL)
- {
- g_simple_async_result_set_from_error (simple, error);
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
- g_error_free (error);
- goto out;
- }
-
- /* Caller is up for a challenge! With light sabers! Use an authentication agent if one exists... */
- if (polkit_authorization_result_get_is_challenge (result) &&
- (flags & POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION))
- {
- AuthenticationAgent *agent;
-
- agent = get_authentication_agent_for_subject (local_authority, subject);
- if (agent != NULL)
- {
- g_object_unref (result);
- result = NULL;
-
- g_debug (" using authentication agent for challenge");
-
- authentication_agent_initiate_challenge (agent,
- subject,
- user_of_subject,
- local_authority,
- action_id,
- details,
- caller,
- implicit_authorization,
- cancellable,
- check_authorization_challenge_cb,
- simple);
-
- /* keep going */
- goto out;
- }
- }
-
- /* Otherwise just return the result */
- g_simple_async_result_set_op_res_gpointer (simple,
- result,
- g_object_unref);
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
-
- out:
-
- if (user_of_caller != NULL)
- g_object_unref (user_of_caller);
-
- if (user_of_subject != NULL)
- g_object_unref (user_of_subject);
-
- g_free (caller_str);
- g_free (subject_str);
- g_free (user_of_caller_str);
- g_free (user_of_subject_str);
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static PolkitAuthorizationResult *
-check_authorization_sync (PolkitBackendAuthority *authority,
- PolkitSubject *subject,
- const gchar *action_id,
- PolkitCheckAuthorizationFlags flags,
- PolkitImplicitAuthorization *out_implicit_authorization,
- GError **error)
-{
- PolkitBackendLocalAuthority *local_authority;
- PolkitBackendLocalAuthorityPrivate *priv;
- PolkitAuthorizationResult *result;
- PolkitIdentity *user_of_subject;
- PolkitSubject *session_for_subject;
- gchar *subject_str;
- GList *groups_of_user;
- PolkitActionDescription *action_desc;
- gboolean session_is_local;
- gboolean session_is_active;
- PolkitImplicitAuthorization implicit_authorization;
-
- local_authority = POLKIT_BACKEND_LOCAL_AUTHORITY (authority);
- priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (local_authority);
-
- result = NULL;
-
- user_of_subject = NULL;
- groups_of_user = NULL;
- subject_str = NULL;
- session_for_subject = NULL;
-
- session_is_local = FALSE;
- session_is_active = FALSE;
-
- subject_str = polkit_subject_to_string (subject);
-
- g_debug ("checking whether %s is authorized for %s",
- subject_str,
- action_id);
-
- /* get the action description */
- action_desc = polkit_backend_action_pool_get_action (priv->action_pool,
- action_id,
- NULL);
-
- if (action_desc == NULL)
- {
- g_set_error (error,
- POLKIT_ERROR,
- POLKIT_ERROR_FAILED,
- "Action %s is not registered",
- action_id);
- goto out;
- }
-
- /* every subject has a user */
- user_of_subject = polkit_backend_session_monitor_get_user_for_subject (priv->session_monitor,
- subject,
- error);
- if (user_of_subject == NULL)
- goto out;
-
- /* special case: uid 0, root, is _always_ authorized for anything */
- if (POLKIT_IS_UNIX_USER (user_of_subject) && polkit_unix_user_get_uid (POLKIT_UNIX_USER (user_of_subject)) == 0)
- {
- result = polkit_authorization_result_new (TRUE, FALSE, NULL);
- goto out;
- }
-
- /* a subject *may* be in a session */
- session_for_subject = polkit_backend_session_monitor_get_session_for_subject (priv->session_monitor,
- subject,
- NULL);
- g_debug (" %p", session_for_subject);
- if (session_for_subject != NULL)
- {
- session_is_local = polkit_backend_session_monitor_is_session_local (priv->session_monitor, session_for_subject);
- session_is_active = polkit_backend_session_monitor_is_session_active (priv->session_monitor, session_for_subject);
-
- g_debug (" subject is in session %s (local=%d active=%d)",
- polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (session_for_subject)),
- session_is_local,
- session_is_active);
- }
-
- /* find the implicit authorization to use; it depends on is_local and is_active */
- if (session_is_local)
- {
- if (session_is_active)
- implicit_authorization = polkit_action_description_get_implicit_active (action_desc);
- else
- implicit_authorization = polkit_action_description_get_implicit_inactive (action_desc);
- }
- else
- {
- implicit_authorization = polkit_action_description_get_implicit_any (action_desc);
- }
-
- /* first see if there's an implicit authorization for subject available */
- if (implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED)
- {
- g_debug (" is authorized (has implicit authorization local=%d active=%d)",
- session_is_local,
- session_is_active);
- result = polkit_authorization_result_new (TRUE, FALSE, NULL);
- goto out;
- }
-
- /* then see if there's a temporary authorization for the subject */
- if (temporary_authorization_store_has_authorization (priv->temporary_authorization_store,
- subject,
- action_id))
- {
- g_debug (" is authorized (has temporary authorization)");
- result = polkit_authorization_result_new (TRUE, FALSE, NULL);
- goto out;
- }
-
-#if 0
- /* then see if we have an authorization for the user */
- if (check_authorization_for_identity (local_authority, user_of_subject, action_id))
- {
- g_debug (" is authorized (user identity has authorization)");
- result = polkit_authorization_result_new (TRUE, FALSE, NULL);
- goto out;
- }
-
- /* then see if we have a permanent authorization for any of the groups the user is in */
- groups_of_user = get_groups_for_user (local_authority, user_of_subject);
- for (l = groups_of_user; l != NULL; l = l->next)
- {
- PolkitIdentity *group = POLKIT_IDENTITY (l->data);
-
- if (check_authorization_for_identity (local_authority, group, action_id))
- {
- g_debug (" is authorized (group identity has authorization)");
- result = polkit_authorization_result_new (TRUE, FALSE, NULL);
- goto out;
- }
- }
-#endif
-
- if (implicit_authorization != POLKIT_IMPLICIT_AUTHORIZATION_NOT_AUTHORIZED)
- {
- result = polkit_authorization_result_new (FALSE, TRUE, NULL);
-
- /* return implicit_authorization so the caller can use an authentication agent if applicable */
- if (out_implicit_authorization != NULL)
- *out_implicit_authorization = implicit_authorization;
-
- g_debug (" challenge (implicit_authorization = %s)",
- polkit_implicit_authorization_to_string (implicit_authorization));
- }
- else
- {
- result = polkit_authorization_result_new (FALSE, FALSE, NULL);
- g_debug (" not authorized");
- }
- out:
- g_free (subject_str);
-
- g_list_foreach (groups_of_user, (GFunc) g_object_unref, NULL);
- g_list_free (groups_of_user);
-
- if (user_of_subject != NULL)
- g_object_unref (user_of_subject);
-
- if (session_for_subject != NULL)
- g_object_unref (session_for_subject);
-
- if (action_desc != NULL)
- g_object_unref (action_desc);
-
- g_debug (" ");
-
- return result;
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-struct AuthenticationAgent
-{
- PolkitSubject *session;
-
- gchar *locale;
- gchar *object_path;
- gchar *unique_system_bus_name;
-
- EggDBusObjectProxy *object_proxy;
-
- GList *active_sessions;
-};
-
-struct AuthenticationSession
-{
- AuthenticationAgent *agent;
-
- gchar *cookie;
-
- PolkitSubject *subject;
-
- PolkitIdentity *user_of_subject;
-
- PolkitBackendLocalAuthority *authority;
-
- GList *identities;
-
- gchar *action_id;
-
- gchar *initiated_by_system_bus_unique_name;
-
- PolkitImplicitAuthorization implicit_authorization;
-
- AuthenticationAgentCallback callback;
-
- gpointer user_data;
-
- guint call_id;
-
- gboolean is_authenticated;
-
- GCancellable *cancellable;
-
- gulong cancellable_signal_handler_id;
-};
-
-static void
-authentication_session_cancelled_cb (GCancellable *cancellable,
- AuthenticationSession *session)
-{
- authentication_session_cancel (session);
-}
-
-static AuthenticationSession *
-authentication_session_new (AuthenticationAgent *agent,
- const gchar *cookie,
- PolkitSubject *subject,
- PolkitIdentity *user_of_subject,
- PolkitBackendLocalAuthority *authority,
- GList *identities,
- const gchar *action_id,
- const gchar *initiated_by_system_bus_unique_name,
- PolkitImplicitAuthorization implicit_authorization,
- GCancellable *cancellable,
- AuthenticationAgentCallback callback,
- gpointer user_data)
-{
- AuthenticationSession *session;
-
- session = g_new0 (AuthenticationSession, 1);
- session->agent = agent;
- session->cookie = g_strdup (cookie);
- session->subject = g_object_ref (subject);
- session->user_of_subject = g_object_ref (user_of_subject);
- session->authority = g_object_ref (authority);
- session->identities = g_list_copy (identities);
- g_list_foreach (session->identities, (GFunc) g_object_ref, NULL);
- session->action_id = g_strdup (action_id);
- session->initiated_by_system_bus_unique_name = g_strdup (initiated_by_system_bus_unique_name);
- session->implicit_authorization = implicit_authorization;
- session->cancellable = cancellable != NULL ? g_object_ref (cancellable) : NULL;
- session->callback = callback;
- session->user_data = user_data;
-
- if (session->cancellable != NULL)
- {
- session->cancellable_signal_handler_id = g_signal_connect (session->cancellable,
- "cancelled",
- G_CALLBACK (authentication_session_cancelled_cb),
- session);
- }
-
- return session;
-}
-
-static void
-authentication_session_free (AuthenticationSession *session)
-{
- g_free (session->cookie);
- g_list_foreach (session->identities, (GFunc) g_object_unref, NULL);
- g_list_free (session->identities);
- g_object_unref (session->subject);
- g_object_unref (session->user_of_subject);
- g_object_unref (session->authority);
- g_free (session->action_id);
- g_free (session->initiated_by_system_bus_unique_name);
- if (session->cancellable_signal_handler_id > 0)
- g_signal_handler_disconnect (session->cancellable, session->cancellable_signal_handler_id);
- if (session->cancellable != NULL)
- g_object_unref (session->cancellable);
- g_free (session);
-}
-
-static gchar *
-authentication_agent_new_cookie (AuthenticationAgent *agent)
-{
- static gint counter = 0;
-
- /* TODO: use a more random-looking cookie */
-
- return g_strdup_printf ("cookie%d", counter++);
-}
-
-static void
-authentication_agent_free (AuthenticationAgent *agent)
-{
- /* cancel all active authentication sessions; use a copy of the list since
- * callbacks will modify the list
- */
- if (agent->active_sessions != NULL)
- {
- GList *l;
- GList *active_sessions;
-
- active_sessions = g_list_copy (agent->active_sessions);
- for (l = active_sessions; l != NULL; l = l->next)
- {
- AuthenticationSession *session = l->data;
-
- authentication_session_cancel (session);
- }
- g_list_free (active_sessions);
- }
-
- g_object_unref (agent->object_proxy);
-
- g_object_unref (agent->session);
- g_free (agent->locale);
- g_free (agent->object_path);
- g_free (agent->unique_system_bus_name);
- g_free (agent);
-}
-
-static AuthenticationAgent *
-authentication_agent_new (PolkitSubject *session,
- const gchar *unique_system_bus_name,
- const gchar *locale,
- const gchar *object_path)
-{
- AuthenticationAgent *agent;
- EggDBusConnection *system_bus;
-
- agent = g_new0 (AuthenticationAgent, 1);
-
- agent->session = g_object_ref (session);
- agent->object_path = g_strdup (object_path);
- agent->unique_system_bus_name = g_strdup (unique_system_bus_name);
- agent->locale = g_strdup (locale);
-
- system_bus = egg_dbus_connection_get_for_bus (EGG_DBUS_BUS_TYPE_SYSTEM);
-
- agent->object_proxy = egg_dbus_connection_get_object_proxy (system_bus,
- agent->unique_system_bus_name,
- agent->object_path);
-
- g_object_unref (system_bus);
-
- return agent;
-}
-
-static AuthenticationAgent *
-get_authentication_agent_for_subject (PolkitBackendLocalAuthority *authority,
- PolkitSubject *subject)
-{
- PolkitBackendLocalAuthorityPrivate *priv;
- PolkitSubject *session_for_subject;
- AuthenticationAgent *agent;
-
- priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (authority);
-
- agent = NULL;
- session_for_subject = NULL;
-
- session_for_subject = polkit_backend_session_monitor_get_session_for_subject (priv->session_monitor,
- subject,
- NULL);
- if (session_for_subject == NULL)
- goto out;
-
- agent = g_hash_table_lookup (priv->hash_session_to_authentication_agent, session_for_subject);
-
- out:
- if (session_for_subject != NULL)
- g_object_unref (session_for_subject);
-
- return agent;
-}
-
-static AuthenticationSession *
-get_authentication_session_for_cookie (PolkitBackendLocalAuthority *authority,
- const gchar *cookie)
-{
- PolkitBackendLocalAuthorityPrivate *priv;
- GHashTableIter hash_iter;
- AuthenticationAgent *agent;
- AuthenticationSession *result;
-
- result = NULL;
-
- /* TODO: perhaps use a hash on the cookie to speed this up */
-
- priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (authority);
-
- g_hash_table_iter_init (&hash_iter, priv->hash_session_to_authentication_agent);
- while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &agent))
- {
- GList *l;
-
- for (l = agent->active_sessions; l != NULL; l = l->next)
- {
- AuthenticationSession *session = l->data;
-
- if (strcmp (session->cookie, cookie) == 0)
- {
- result = session;
- goto out;
- }
- }
- }
-
- out:
- return result;
-}
-
-static GList *
-get_authentication_sessions_initiated_by_system_bus_unique_name (PolkitBackendLocalAuthority *authority,
- const gchar *system_bus_unique_name)
-{
- PolkitBackendLocalAuthorityPrivate *priv;
- GHashTableIter hash_iter;
- AuthenticationAgent *agent;
- GList *result;
-
- result = NULL;
-
- /* TODO: perhaps use a hash on the cookie to speed this up */
-
- priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (authority);
-
- g_hash_table_iter_init (&hash_iter, priv->hash_session_to_authentication_agent);
- while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &agent))
- {
- GList *l;
-
- for (l = agent->active_sessions; l != NULL; l = l->next)
- {
- AuthenticationSession *session = l->data;
-
- if (strcmp (session->initiated_by_system_bus_unique_name, system_bus_unique_name) == 0)
- {
- result = g_list_prepend (result, session);
- }
- }
- }
-
- return result;
-}
-
-static GList *
-get_authentication_sessions_for_system_bus_unique_name_subject (PolkitBackendLocalAuthority *authority,
- const gchar *system_bus_unique_name)
-{
- PolkitBackendLocalAuthorityPrivate *priv;
- GHashTableIter hash_iter;
- AuthenticationAgent *agent;
- GList *result;
-
- result = NULL;
-
- /* TODO: perhaps use a hash on the cookie to speed this up */
-
- priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (authority);
-
- g_hash_table_iter_init (&hash_iter, priv->hash_session_to_authentication_agent);
- while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &agent))
- {
- GList *l;
-
- for (l = agent->active_sessions; l != NULL; l = l->next)
- {
- AuthenticationSession *session = l->data;
-
- if (POLKIT_IS_SYSTEM_BUS_NAME (session->subject) &&
- strcmp (polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (session->subject)),
- system_bus_unique_name) == 0)
- {
- result = g_list_prepend (result, session);
- }
- }
- }
-
- return result;
-}
-
-
-static AuthenticationAgent *
-get_authentication_agent_by_unique_system_bus_name (PolkitBackendLocalAuthority *authority,
- const gchar *unique_system_bus_name)
-{
- PolkitBackendLocalAuthorityPrivate *priv;
- GHashTableIter hash_iter;
- AuthenticationAgent *agent;
-
- priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (authority);
-
- g_hash_table_iter_init (&hash_iter, priv->hash_session_to_authentication_agent);
- while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &agent))
- {
- if (strcmp (agent->unique_system_bus_name, unique_system_bus_name) == 0)
- goto out;
- }
-
- agent = NULL;
-
- out:
- return agent;
-}
-
-static void
-authentication_agent_begin_callback (GObject *source_object,
- GAsyncResult *res,
- gpointer user_data)
-{
- _PolkitAuthenticationAgent *agent_dbus = _POLKIT_AUTHENTICATION_AGENT (source_object);
- AuthenticationSession *session = user_data;
- GError *error;
- gboolean gained_authorization;
-
- error = NULL;
- if (!_polkit_authentication_agent_begin_authentication_finish (agent_dbus,
- res,
- &error))
- {
- g_warning ("Error performing authentication: %s", error->message);
- g_error_free (error);
- gained_authorization = FALSE;
- }
- else
- {
- gained_authorization = session->is_authenticated;
-
- g_debug ("Authentication complete, is_authenticated = %d", session->is_authenticated);
- }
-
- session->agent->active_sessions = g_list_remove (session->agent->active_sessions, session);
-
- session->callback (session->agent,
- session->subject,
- session->user_of_subject,
- session->authority,
- session->action_id,
- session->implicit_authorization,
- gained_authorization,
- session->user_data);
-
- authentication_session_free (session);
-}
-
-static GList *
-get_admin_auth_identities (PolkitBackendLocalAuthority *authority)
-{
- PolkitBackendLocalAuthorityPrivate *priv;
GList *ret;
guint n;
gchar **admin_identities;
GError *error;
- priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (authority);
+ local_authority = POLKIT_BACKEND_LOCAL_AUTHORITY (authority);
+ priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (local_authority);
ret = NULL;
@@ -1174,699 +194,10 @@ get_admin_auth_identities (PolkitBackendLocalAuthority *authority)
return ret;
}
-static GList *
-get_action_lookup_list (void)
-{
- GList *extensions;
- GList *l;
- GIOExtensionPoint *action_lookup_ep;
- static GList *action_lookup_list = NULL;
- static gboolean have_looked_up_extensions = FALSE;
-
- if (have_looked_up_extensions)
- goto out;
-
- action_lookup_ep = g_io_extension_point_lookup (POLKIT_BACKEND_ACTION_LOOKUP_EXTENSION_POINT_NAME);
- g_assert (action_lookup_ep != NULL);
-
- extensions = g_io_extension_point_get_extensions (action_lookup_ep);
- for (l = extensions; l != NULL; l = l->next)
- {
- GIOExtension *extension = l->data;
- PolkitBackendActionLookup *lookup;
-
- lookup = g_object_new (g_io_extension_get_type (extension), NULL);
- action_lookup_list = g_list_prepend (action_lookup_list, lookup);
- }
- action_lookup_list = g_list_reverse (action_lookup_list);
-
- out:
- have_looked_up_extensions = TRUE;
- return action_lookup_list;
-}
-
-static void
-get_localized_data_for_challenge (PolkitBackendLocalAuthority *authority,
- PolkitSubject *caller,
- PolkitSubject *subject,
- PolkitIdentity *user_of_subject,
- const gchar *action_id,
- PolkitDetails *details,
- const gchar *locale,
- gchar **out_localized_message,
- gchar **out_localized_icon_name,
- EggDBusHashMap **out_localized_details)
-{
- PolkitBackendLocalAuthorityPrivate *priv;
- PolkitActionDescription *action_desc;
- GList *action_lookup_list;
- GList *l;
- gchar *message;
- gchar *icon_name;
- PolkitDetails *localized_details;
-
- priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (authority);
-
- message = NULL;
- icon_name = NULL;
- localized_details = NULL;
- action_desc = NULL;
-
- *out_localized_message = NULL;
- *out_localized_icon_name = NULL;
- *out_localized_details = egg_dbus_hash_map_new (G_TYPE_STRING, NULL,
- G_TYPE_STRING, NULL);
-
- action_desc = polkit_backend_action_pool_get_action (priv->action_pool,
- action_id,
- locale);
- if (action_desc == NULL)
- goto out;
-
- /* Set LANG and locale so gettext() + friends work when running the code in the extensions */
- if (setlocale (LC_ALL, locale) == NULL)
- {
- g_warning ("Invalid locale '%s'", locale);
- }
- g_setenv ("LANG", locale, TRUE);
-
- /* call into extension points to get localized auth dialog data - the list is sorted by priority */
- action_lookup_list = get_action_lookup_list ();
- for (l = action_lookup_list; l != NULL; l = l->next)
- {
- PolkitBackendActionLookup *lookup = POLKIT_BACKEND_ACTION_LOOKUP (l->data);
-
- if (message != NULL && icon_name != NULL && localized_details != NULL)
- break;
-
- if (message == NULL)
- message = polkit_backend_action_lookup_get_message (lookup,
- action_id,
- details,
- action_desc);
-
- if (icon_name == NULL)
- icon_name = polkit_backend_action_lookup_get_icon_name (lookup,
- action_id,
- details,
- action_desc);
-
- if (localized_details == NULL)
- localized_details = polkit_backend_action_lookup_get_details (lookup,
- action_id,
- details,
- action_desc);
- }
-
- /* Back to C! */
- setlocale (LC_ALL, "C");
- g_setenv ("LANG", "C", TRUE);
-
- /* fall back to action description */
- if (message == NULL)
- {
- message = g_strdup (polkit_action_description_get_message (action_desc));
- }
- if (icon_name == NULL)
- {
- icon_name = g_strdup (polkit_action_description_get_icon_name (action_desc));
- }
-
-
- if (localized_details != NULL)
- {
- GHashTable *hash;
- GHashTableIter iter;
- const gchar *key;
- const gchar *value;
-
- hash = polkit_details_get_hash (localized_details);
- if (hash != NULL)
- {
- g_hash_table_iter_init (&iter, hash);
- while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &value))
- {
- egg_dbus_hash_map_insert (*out_localized_details, key, value);
- }
- }
- }
-
- out:
- if (message == NULL)
- message = g_strdup ("");
- if (icon_name == NULL)
- icon_name = g_strdup ("");
- *out_localized_message = message;
- *out_localized_icon_name = icon_name;
- if (action_desc != NULL)
- g_object_unref (action_desc);
-}
-
-static void
-authentication_agent_initiate_challenge (AuthenticationAgent *agent,
- PolkitSubject *subject,
- PolkitIdentity *user_of_subject,
- PolkitBackendLocalAuthority *authority,
- const gchar *action_id,
- PolkitDetails *details,
- PolkitSubject *caller,
- PolkitImplicitAuthorization implicit_authorization,
- GCancellable *cancellable,
- AuthenticationAgentCallback callback,
- gpointer user_data)
-{
- AuthenticationSession *session;
- _PolkitAuthenticationAgent *agent_dbus;
- gchar *cookie;
- GList *l;
- GList *identities;
- EggDBusArraySeq *real_identities;
- gchar *localized_message;
- gchar *localized_icon_name;
- EggDBusHashMap *localized_details;
-
- get_localized_data_for_challenge (authority,
- caller,
- subject,
- user_of_subject,
- action_id,
- details,
- agent->locale,
- &localized_message,
- &localized_icon_name,
- &localized_details);
-
- cookie = authentication_agent_new_cookie (agent);
-
- identities = NULL;
-
- /* select admin user if required by the implicit authorization */
- if (implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_ADMINISTRATOR_AUTHENTICATION_REQUIRED ||
- implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_ADMINISTRATOR_AUTHENTICATION_REQUIRED_RETAINED)
- {
- identities = get_admin_auth_identities (authority);
- }
- else
- {
- identities = g_list_prepend (identities, g_object_ref (user_of_subject));
- }
-
- session = authentication_session_new (agent,
- cookie,
- subject,
- user_of_subject,
- authority,
- identities,
- action_id,
- polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (caller)),
- implicit_authorization,
- cancellable,
- callback,
- user_data);
-
- agent->active_sessions = g_list_prepend (agent->active_sessions, session);
-
- agent_dbus = _POLKIT_QUERY_INTERFACE_AUTHENTICATION_AGENT (agent->object_proxy);
-
- real_identities = egg_dbus_array_seq_new (EGG_DBUS_TYPE_STRUCTURE, g_object_unref, NULL, NULL);
- for (l = identities; l != NULL; l = l->next)
- {
- PolkitIdentity *identity = POLKIT_IDENTITY (l->data);
- egg_dbus_array_seq_add (real_identities, polkit_identity_get_real (identity));
- }
-
- session->call_id = _polkit_authentication_agent_begin_authentication (agent_dbus,
- EGG_DBUS_CALL_FLAGS_TIMEOUT_NONE,
- action_id,
- localized_message,
- localized_icon_name,
- localized_details,
- session->cookie,
- real_identities,
- NULL,
- authentication_agent_begin_callback,
- session);
-
- g_list_foreach (identities, (GFunc) g_object_unref, NULL);
- g_list_free (identities);
- g_object_unref (real_identities);
- g_free (cookie);
-
- g_free (localized_message);
- g_free (localized_icon_name);
- g_object_unref (localized_details);
-}
-
-static void
-authentication_agent_cancel_callback (GObject *source_object,
- GAsyncResult *res,
- gpointer user_data)
-{
- _PolkitAuthenticationAgent *agent_dbus = _POLKIT_AUTHENTICATION_AGENT (source_object);
-
- _polkit_authentication_agent_cancel_authentication_finish (agent_dbus,
- res,
- NULL);
-}
-
-static void
-authentication_session_cancel (AuthenticationSession *session)
-{
- EggDBusConnection *system_bus;
- _PolkitAuthenticationAgent *agent_dbus;
-
- system_bus = egg_dbus_connection_get_for_bus (EGG_DBUS_BUS_TYPE_SYSTEM);
-
- agent_dbus = _POLKIT_QUERY_INTERFACE_AUTHENTICATION_AGENT (session->agent->object_proxy);
-
- _polkit_authentication_agent_cancel_authentication (agent_dbus,
- EGG_DBUS_CALL_FLAGS_NONE,
- session->cookie,
- NULL,
- authentication_agent_cancel_callback,
- NULL);
-
- egg_dbus_connection_pending_call_cancel (system_bus, session->call_id);
-
- g_object_unref (system_bus);
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static gboolean
-polkit_backend_local_authority_register_authentication_agent (PolkitBackendAuthority *authority,
- PolkitSubject *caller,
- const gchar *session_id,
- const gchar *locale,
- const gchar *object_path,
- GError **error)
-{
- PolkitBackendLocalAuthority *local_authority;
- PolkitBackendLocalAuthorityPrivate *priv;
- PolkitSubject *session_for_caller;
- AuthenticationAgent *agent;
- gboolean ret;
-
- session_for_caller = NULL;
- ret = FALSE;
-
- local_authority = POLKIT_BACKEND_LOCAL_AUTHORITY (authority);
- priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (local_authority);
-
- if (session_id != NULL && strlen (session_id) > 0)
- {
- g_set_error (error,
- POLKIT_ERROR,
- POLKIT_ERROR_FAILED,
- "The session_id parameter must be blank for now.");
- goto out;
- }
-
- session_for_caller = polkit_backend_session_monitor_get_session_for_subject (priv->session_monitor,
- caller,
- NULL);
- if (session_for_caller == NULL)
- {
- g_set_error (error,
- POLKIT_ERROR,
- POLKIT_ERROR_FAILED,
- "Cannot determine session");
- goto out;
- }
-
- agent = g_hash_table_lookup (priv->hash_session_to_authentication_agent, session_for_caller);
- if (agent != NULL)
- {
- g_set_error (error,
- POLKIT_ERROR,
- POLKIT_ERROR_FAILED,
- "An authentication agent already exists for session");
- goto out;
- }
-
- /* TODO: validate that object path is well-formed */
-
- agent = authentication_agent_new (session_for_caller,
- polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (caller)),
- locale,
- object_path);
-
- g_hash_table_insert (priv->hash_session_to_authentication_agent,
- g_object_ref (session_for_caller),
- agent);
-
- g_debug ("Added authentication agent for session %s at name %s, object path %s, locale %s",
- polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (session_for_caller)),
- polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (caller)),
- object_path,
- locale);
-
- ret = TRUE;
-
- out:
- if (session_for_caller != NULL)
- g_object_unref (session_for_caller);
-
- return ret;
-}
-
-static gboolean
-polkit_backend_local_authority_unregister_authentication_agent (PolkitBackendAuthority *authority,
- PolkitSubject *caller,
- const gchar *session_id,
- const gchar *object_path,
- GError **error)
-{
- PolkitBackendLocalAuthority *local_authority;
- PolkitBackendLocalAuthorityPrivate *priv;
- PolkitSubject *session_for_caller;
- AuthenticationAgent *agent;
- gboolean ret;
-
- local_authority = POLKIT_BACKEND_LOCAL_AUTHORITY (authority);
- priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (local_authority);
-
- ret = FALSE;
- session_for_caller = NULL;
-
- if (session_id != NULL && strlen (session_id) > 0)
- {
- g_set_error (error,
- POLKIT_ERROR,
- POLKIT_ERROR_FAILED,
- "The session_id parameter must be blank for now.");
- goto out;
- }
-
- session_for_caller = polkit_backend_session_monitor_get_session_for_subject (priv->session_monitor,
- caller,
- NULL);
- if (session_for_caller == NULL)
- {
- g_set_error (error,
- POLKIT_ERROR,
- POLKIT_ERROR_FAILED,
- "Cannot determine session");
- goto out;
- }
-
- agent = g_hash_table_lookup (priv->hash_session_to_authentication_agent, session_for_caller);
- if (agent == NULL)
- {
- g_set_error (error,
- POLKIT_ERROR,
- POLKIT_ERROR_FAILED,
- "No such agent registered");
- goto out;
- }
-
- if (strcmp (agent->unique_system_bus_name,
- polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (caller))) != 0)
- {
- g_set_error (error,
- POLKIT_ERROR,
- POLKIT_ERROR_FAILED,
- "System bus names do not match");
- goto out;
- }
-
- if (strcmp (agent->object_path, object_path) != 0)
- {
- g_set_error (error,
- POLKIT_ERROR,
- POLKIT_ERROR_FAILED,
- "Object paths do not match");
- goto out;
- }
-
-
- g_debug ("Removing authentication agent for session %s at name %s, object path %s (unregistered)",
- polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (agent->session)),
- agent->unique_system_bus_name,
- agent->object_path);
-
- /* this works because we have exactly one agent per session */
- g_hash_table_remove (priv->hash_session_to_authentication_agent, agent->session);
-
- ret = TRUE;
-
- out:
- if (session_for_caller != NULL)
- g_object_unref (session_for_caller);
- return ret;
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static gboolean
-polkit_backend_local_authority_authentication_agent_response (PolkitBackendAuthority *authority,
- PolkitSubject *caller,
- const gchar *cookie,
- PolkitIdentity *identity,
- GError **error)
-{
- PolkitBackendLocalAuthority *local_authority;
- PolkitBackendLocalAuthorityPrivate *priv;
- PolkitIdentity *user_of_caller;
- gchar *identity_str;
- AuthenticationSession *session;
- GList *l;
- gboolean ret;
-
- local_authority = POLKIT_BACKEND_LOCAL_AUTHORITY (authority);
- priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (local_authority);
-
- ret = FALSE;
- user_of_caller = NULL;
-
- identity_str = polkit_identity_to_string (identity);
-
- g_debug ("In authentication_agent_response for cookie '%s' and identity %s",
- cookie,
- identity_str);
-
- user_of_caller = polkit_backend_session_monitor_get_user_for_subject (priv->session_monitor,
- caller,
- error);
- if (user_of_caller == NULL)
- goto out;
-
- /* only uid 0 is allowed to invoke this method */
- if (!POLKIT_IS_UNIX_USER (user_of_caller) || polkit_unix_user_get_uid (POLKIT_UNIX_USER (user_of_caller)) != 0)
- {
- g_set_error (error,
- POLKIT_ERROR,
- POLKIT_ERROR_FAILED,
- "Only uid 0 may invoke this method. This incident has been logged.");
- /* TODO: actually log this */
- goto out;
- }
-
- /* find the authentication session */
- session = get_authentication_session_for_cookie (local_authority, cookie);
- if (session == NULL)
- {
- g_set_error (error,
- POLKIT_ERROR,
- POLKIT_ERROR_FAILED,
- "No session for cookie");
- goto out;
- }
-
- /* check that the authentication identity was one of the possibilities we allowed */
- for (l = session->identities; l != NULL; l = l->next)
- {
- PolkitIdentity *i = POLKIT_IDENTITY (l->data);
-
- if (polkit_identity_equal (i, identity))
- break;
- }
-
- if (l == NULL)
- {
- g_set_error (error,
- POLKIT_ERROR,
- POLKIT_ERROR_FAILED,
- "The authenticated identity is wrong");
- goto out;
- }
-
- /* checks out, mark the session as authenticated */
- session->is_authenticated = TRUE;
-
- ret = TRUE;
-
- out:
- g_free (identity_str);
-
- if (user_of_caller != NULL)
- g_object_unref (user_of_caller);
-
- return ret;
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static void
-polkit_backend_local_authority_system_bus_name_owner_changed (PolkitBackendAuthority *authority,
- const gchar *name,
- const gchar *old_owner,
- const gchar *new_owner)
-{
- PolkitBackendLocalAuthority *local_authority;
- PolkitBackendLocalAuthorityPrivate *priv;
-
- local_authority = POLKIT_BACKEND_LOCAL_AUTHORITY (authority);
- priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (local_authority);
-
- //g_debug ("name-owner-changed: '%s' '%s' '%s'", name, old_owner, new_owner);
-
- if (name[0] == ':' && strlen (new_owner) == 0)
- {
- AuthenticationAgent *agent;
- GList *sessions;
- GList *l;
-
- agent = get_authentication_agent_by_unique_system_bus_name (local_authority, name);
- if (agent != NULL)
- {
- g_debug ("Removing authentication agent for session %s at name %s, object path %s (disconnected from bus)",
- polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (agent->session)),
- agent->unique_system_bus_name,
- agent->object_path);
-
- /* this works because we have exactly one agent per session */
- g_hash_table_remove (priv->hash_session_to_authentication_agent, agent->session);
- }
-
- /* cancel all authentication sessions initiated by the process owning the vanished name */
- sessions = get_authentication_sessions_initiated_by_system_bus_unique_name (local_authority, name);
- for (l = sessions; l != NULL; l = l->next)
- {
- AuthenticationSession *session = l->data;
-
- authentication_session_cancel (session);
- }
- g_list_free (sessions);
-
- /* cancel all authentication sessions that is about the vanished name */
- sessions = get_authentication_sessions_for_system_bus_unique_name_subject (local_authority, name);
- for (l = sessions; l != NULL; l = l->next)
- {
- AuthenticationSession *session = l->data;
-
- authentication_session_cancel (session);
- }
- g_list_free (sessions);
-
- }
-
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-typedef struct TemporaryAuthorization TemporaryAuthorization;
-
-struct TemporaryAuthorizationStore
-{
- GList *authorizations;
-};
-
-struct TemporaryAuthorization
-{
- PolkitSubject *subject;
- gchar *action_id;
- guint64 time_granted;
-};
-
-static void
-temporary_authorization_free (TemporaryAuthorization *authorization)
-{
- g_object_unref (authorization->subject);
- g_free (authorization->action_id);
- g_free (authorization);
-}
-
-static TemporaryAuthorization *
-temporary_authorization_new (PolkitSubject *subject,
- const gchar *action_id)
-{
- TemporaryAuthorization *authorization;
-
- authorization = g_new0 (TemporaryAuthorization, 1);
- authorization->subject = g_object_ref (subject);
- authorization->action_id = g_strdup (action_id);
- authorization->time_granted = time (NULL);
-
- return authorization;
-}
-
-static TemporaryAuthorizationStore *
-temporary_authorization_store_new (void)
-{
- TemporaryAuthorizationStore *store;
-
- store = g_new0 (TemporaryAuthorizationStore, 1);
- store->authorizations = NULL;
-
- return store;
-}
-
-static void
-temporary_authorization_store_free (TemporaryAuthorizationStore *store)
-{
- g_list_foreach (store->authorizations, (GFunc) temporary_authorization_free, NULL);
- g_list_free (store->authorizations);
- g_free (store);
-}
-
-static gboolean
-temporary_authorization_store_has_authorization (TemporaryAuthorizationStore *store,
- PolkitSubject *subject,
- const gchar *action_id)
-{
- GList *l;
- gboolean ret;
-
- g_return_val_if_fail (store != NULL, FALSE);
- g_return_val_if_fail (POLKIT_IS_SUBJECT (subject), FALSE);
- g_return_val_if_fail (action_id != NULL, FALSE);
-
- ret = FALSE;
-
- for (l = store->authorizations; l != NULL; l = l->next) {
- TemporaryAuthorization *authorization = l->data;
-
- if (strcmp (action_id, authorization->action_id) == 0 &&
- polkit_subject_equal (subject, authorization->subject))
- {
- ret = TRUE;
- goto out;
- }
- }
-
- out:
- return ret;
-}
-
-static void
-temporary_authorization_store_add_authorization (TemporaryAuthorizationStore *store,
- PolkitSubject *subject,
- const gchar *action_id)
-{
- g_return_if_fail (store != NULL);
- g_return_if_fail (POLKIT_IS_SUBJECT (subject));
- g_return_if_fail (action_id != NULL);
- g_return_if_fail (!temporary_authorization_store_has_authorization (store, subject, action_id));
-
- store->authorizations = g_list_prepend (store->authorizations,
- temporary_authorization_new (subject, action_id));
-}
-
/* ---------------------------------------------------------------------------------------------------- */
static GList *
-get_users_in_group (PolkitBackendLocalAuthority *authority,
+get_users_in_group (PolkitBackendInteractiveAuthority *authority,
PolkitIdentity *group,
gboolean include_root)
{
@@ -1914,7 +245,7 @@ get_users_in_group (PolkitBackendLocalAuthority *authority,
#if 0
static GList *
-get_groups_for_user (PolkitBackendLocalAuthority *authority,
+get_groups_for_user (PolkitBackendInteractiveAuthority *authority,
PolkitIdentity *user)
{
uid_t uid;
diff --git a/src/polkitbackend/polkitbackendlocalauthority.h b/src/polkitbackend/polkitbackendlocalauthority.h
index be0232f..553da3b 100644
--- a/src/polkitbackend/polkitbackendlocalauthority.h
+++ b/src/polkitbackend/polkitbackendlocalauthority.h
@@ -28,7 +28,7 @@
#include <glib-object.h>
#include <polkitbackend/polkitbackendtypes.h>
-#include <polkitbackend/polkitbackendauthority.h>
+#include <polkitbackend/polkitbackendinteractiveauthority.h>
G_BEGIN_DECLS
@@ -49,7 +49,7 @@ typedef struct _PolkitBackendLocalAuthorityClass PolkitBackendLocalAuthorityC
struct _PolkitBackendLocalAuthority
{
/*< private >*/
- PolkitBackendAuthority parent_instance;
+ PolkitBackendInteractiveAuthority parent_instance;
};
/**
@@ -61,7 +61,7 @@ struct _PolkitBackendLocalAuthority
struct _PolkitBackendLocalAuthorityClass
{
/*< public >*/
- PolkitBackendAuthorityClass parent_class;
+ PolkitBackendInteractiveAuthorityClass parent_class;
/*< private >*/
/* Padding for future expansion */
@@ -73,10 +73,33 @@ struct _PolkitBackendLocalAuthorityClass
void (*_polkit_reserved6) (void);
void (*_polkit_reserved7) (void);
void (*_polkit_reserved8) (void);
+ void (*_polkit_reserved9) (void);
+ void (*_polkit_reserved10) (void);
+ void (*_polkit_reserved11) (void);
+ void (*_polkit_reserved12) (void);
+ void (*_polkit_reserved13) (void);
+ void (*_polkit_reserved14) (void);
+ void (*_polkit_reserved15) (void);
+ void (*_polkit_reserved16) (void);
+ void (*_polkit_reserved17) (void);
+ void (*_polkit_reserved18) (void);
+ void (*_polkit_reserved19) (void);
+ void (*_polkit_reserved20) (void);
+ void (*_polkit_reserved21) (void);
+ void (*_polkit_reserved22) (void);
+ void (*_polkit_reserved23) (void);
+ void (*_polkit_reserved24) (void);
+ void (*_polkit_reserved25) (void);
+ void (*_polkit_reserved26) (void);
+ void (*_polkit_reserved27) (void);
+ void (*_polkit_reserved28) (void);
+ void (*_polkit_reserved29) (void);
+ void (*_polkit_reserved30) (void);
+ void (*_polkit_reserved31) (void);
+ void (*_polkit_reserved32) (void);
};
GType polkit_backend_local_authority_get_type (void) G_GNUC_CONST;
-PolkitBackendAuthority *polkit_backend_local_authority_new (void);
G_END_DECLS
diff --git a/src/polkitbackend/polkitbackendtypes.h b/src/polkitbackend/polkitbackendtypes.h
index e0906df..e130d16 100644
--- a/src/polkitbackend/polkitbackendtypes.h
+++ b/src/polkitbackend/polkitbackendtypes.h
@@ -24,9 +24,6 @@
#include <glib-object.h>
-struct _PolkitBackendAuthority;
-typedef struct _PolkitBackendAuthority PolkitBackendAuthority;
-
struct _PolkitBackendSessionMonitor;
typedef struct _PolkitBackendSessionMonitor PolkitBackendSessionMonitor;
@@ -36,6 +33,12 @@ typedef struct _PolkitBackendConfigSource PolkitBackendConfigSource;
struct _PolkitBackendActionLookup;
typedef struct _PolkitBackendActionLookup PolkitBackendActionLookup; /* Dummy typedef */
+struct _PolkitBackendAuthority;
+typedef struct _PolkitBackendAuthority PolkitBackendAuthority;
+
+struct _PolkitBackendInteractiveAuthority;
+typedef struct _PolkitBackendInteractiveAuthority PolkitBackendInteractiveAuthority;
+
struct _PolkitBackendLocalAuthority;
typedef struct _PolkitBackendLocalAuthority PolkitBackendLocalAuthority;
More information about the hal-commit
mailing list