PolicyKit: Branch 'master'
David Zeuthen
david at kemper.freedesktop.org
Mon Feb 9 12:56:15 PST 2009
data/org.freedesktop.PolicyKit1.Authority.xml | 47 ++++
docs/polkit/polkit-sections.txt | 3
docs/polkitbackend/polkitbackend-sections.txt | 2
src/examples/Makefile.am | 13 +
src/examples/cancelobtain.c | 104 +++++++++
src/polkit/polkitauthority.c | 205 ++++++++++++++++++
src/polkit/polkitauthority.h | 16 +
src/polkitbackend/polkitbackendauthority.c | 219 ++++++++++++++++++++
src/polkitbackend/polkitbackendauthority.h | 31 ++
src/polkitbackend/polkitbackendlocalauthority.c | 259 ++++++++++++++++++++++++
src/programs/polkit.c | 27 --
11 files changed, 905 insertions(+), 21 deletions(-)
New commits:
commit b891d8a3245d364975cecb2289c442f54b2327c6
Author: David Zeuthen <davidz at redhat.com>
Date: Mon Feb 9 15:53:51 2009 -0500
add the ObtainAuthorization() method and use in for the 'polkit-1 run' command
Also add an example for this.
diff --git a/data/org.freedesktop.PolicyKit1.Authority.xml b/data/org.freedesktop.PolicyKit1.Authority.xml
index 34a2b4b..a3d5741 100644
--- a/data/org.freedesktop.PolicyKit1.Authority.xml
+++ b/data/org.freedesktop.PolicyKit1.Authority.xml
@@ -6,6 +6,8 @@
<annotation name="org.gtk.EggDBus.DocString.Summary" value="Authority Interface"/>
<annotation name="org.gtk.EggDBus.DocString" value="This D-Bus interface is implemented by the <literal>/org/freedesktop/PoliycKit1/Authority</literal> object on the well-known name <literal>org.freedesktop.PolicyKit1</literal> on the system message bus."/>
+ <!-- ---------------------------------------------------------------------------------------------------- -->
+
<!-- Subject struct -->
<annotation name="org.gtk.EggDBus.DeclareStruct" value="Subject">
<annotation name="org.gtk.EggDBus.DocString.Summary" value="Subjects"/>
@@ -21,6 +23,8 @@
</annotation>
+ <!-- ---------------------------------------------------------------------------------------------------- -->
+
<!-- Identity struct -->
<annotation name="org.gtk.EggDBus.DeclareStruct" value="Identity">
<annotation name="org.gtk.EggDBus.DocString.Summary" value="Subjects"/>
@@ -38,6 +42,8 @@
</annotation>
+ <!-- ---------------------------------------------------------------------------------------------------- -->
+
<!-- ActionDescription struct -->
<annotation name="org.gtk.EggDBus.DeclareStruct" value="ActionDescription">
<annotation name="org.gtk.EggDBus.DocString.Summary" value="Actions"/>
@@ -88,6 +94,8 @@
</annotation>
+ <!-- ---------------------------------------------------------------------------------------------------- -->
+
<!-- Flags used for checking authorizations -->
<annotation name="org.gtk.EggDBus.DeclareFlags" value="CheckAuthorizationFlags">
<annotation name="org.gtk.EggDBus.DocString.Summary" value="Flags used when checking authorizations"/>
@@ -98,6 +106,8 @@
</annotation>
</annotation>
+ <!-- ---------------------------------------------------------------------------------------------------- -->
+
<!-- An enumeration for results when checking for an authorization -->
<annotation name="org.gtk.EggDBus.DeclareEnum" value="AuthorizationResult">
<annotation name="org.gtk.EggDBus.DocString.Summary" value="Possible results for checking authorizations"/>
@@ -114,6 +124,8 @@
</annotation>
</annotation>
+ <!-- ---------------------------------------------------------------------------------------------------- -->
+
<!-- An enumeration for implicit authorizations -->
<annotation name="org.gtk.EggDBus.DeclareEnum" value="ImplicitAuthorization">
<annotation name="org.gtk.EggDBus.DocString.Summary" value="Implicit authorizations"/>
@@ -145,6 +157,8 @@
</annotation>
+ <!-- ---------------------------------------------------------------------------------------------------- -->
+
<!-- The error domain used for reporting errors -->
<annotation name="org.gtk.EggDBus.DeclareErrorDomain" value="Error">
<annotation name="org.gtk.EggDBus.DocString.Summary" value="Errors"/>
@@ -170,6 +184,8 @@
</annotation>
</annotation>
+ <!-- ---------------------------------------------------------------------------------------------------- -->
+
<method name="EnumerateActions">
<annotation name="org.gtk.EggDBus.DocString" value="Enumerates all registered PolicyKit actions."/>
@@ -183,6 +199,8 @@
</arg>
</method>
+ <!-- ---------------------------------------------------------------------------------------------------- -->
+
<method name="CheckAuthorization">
<annotation name="org.gtk.EggDBus.DocString" value="<para>Checks if @subject is authorized to perform the action with identifier @action_id.</para><para>If @cancellation_id is non-empty and already in use for the caller, the %org.freedesktop.PolicyKit1.Error.CancellationIdNotUnique error is returned.</para>"/>
@@ -218,6 +236,35 @@
</arg>
</method>
+ <!-- ---------------------------------------------------------------------------------------------------- -->
+
+ <method name="ObtainAuthorization">
+ <annotation name="org.gtk.EggDBus.DocString" value="Obtains a temporary authorization for @subject to perform the action identified by @action_id. If @subject is already authorized, this method returns immediately without error. If the authorization could not be obtained or @action_id doesn't allow temporary authorizations, the %org.freedesktop.PolicyKit1.Error.Failed error is returned."/>
+
+ <arg name="subject" direction="in" type="(sa{sv})">
+ <annotation name="org.gtk.EggDBus.DocString" value="A #Subject struct."/>
+ <annotation name="org.gtk.EggDBus.Type" value="Subject"/>
+ </arg>
+
+ <arg name="action_id" direction="in" type="s">
+ <annotation name="org.gtk.EggDBus.DocString" value="Identifier for the action that @subject is attempting to do."/>
+ </arg>
+
+ <arg name="cancellation_id" direction="in" type="s">
+ <annotation name="org.gtk.EggDBus.DocString" value="A unique id used to cancel the the authentication check via org.freedesktop.PolicyKit1.Authority.CancelObtainAuthorization() or the empty string if cancellation is not needed."/>
+ </arg>
+ </method>
+
+ <method name="CancelObtainAuthorization">
+ <annotation name="org.gtk.EggDBus.DocString" value="Cancels an attempt to obtain an authorization."/>
+
+ <arg name="cancellation_id" direction="in" type="s">
+ <annotation name="org.gtk.EggDBus.DocString" value="The @cancellation_id passed to org.freedesktop.PolicyKit1.Authority.ObtainAuthorization()."/>
+ </arg>
+ </method>
+
+ <!-- ---------------------------------------------------------------------------------------------------- -->
+
<method name="RegisterAuthenticationAgent">
<annotation name="org.gtk.EggDBus.DocString" value="<para>Register an authentication agent.</para><para>Note that current versions of PolicyKit will only work if @session_id is set to the empty string. In the future it might work for non-empty strings if the caller is sufficiently privileged.</para>"/>
diff --git a/docs/polkit/polkit-sections.txt b/docs/polkit/polkit-sections.txt
index 2094a3f..9f21599 100644
--- a/docs/polkit/polkit-sections.txt
+++ b/docs/polkit/polkit-sections.txt
@@ -54,6 +54,7 @@ PolkitAuthorizationResult
polkit_authority_get
polkit_authority_enumerate_actions_sync
polkit_authority_check_authorization_sync
+polkit_authority_obtain_authorization_sync
polkit_authority_register_authentication_agent_sync
polkit_authority_unregister_authentication_agent_sync
polkit_authority_authentication_agent_response_sync
@@ -61,6 +62,8 @@ polkit_authority_enumerate_actions
polkit_authority_enumerate_actions_finish
polkit_authority_check_authorization
polkit_authority_check_authorization_finish
+polkit_authority_obtain_authorization
+polkit_authority_obtain_authorization_finish
polkit_authority_register_authentication_agent
polkit_authority_register_authentication_agent_finish
polkit_authority_unregister_authentication_agent
diff --git a/docs/polkitbackend/polkitbackend-sections.txt b/docs/polkitbackend/polkitbackend-sections.txt
index 5af0b97..1c8f925 100644
--- a/docs/polkitbackend/polkitbackend-sections.txt
+++ b/docs/polkitbackend/polkitbackend-sections.txt
@@ -6,6 +6,8 @@ PolkitBackendAuthority
PolkitBackendAuthorityClass
polkit_backend_authority_check_authorization
polkit_backend_authority_check_authorization_finish
+polkit_backend_authority_obtain_authorization
+polkit_backend_authority_obtain_authorization_finish
polkit_backend_authority_register_authentication_agent
polkit_backend_authority_unregister_authentication_agent
polkit_backend_authority_authentication_agent_response
diff --git a/src/examples/Makefile.am b/src/examples/Makefile.am
index 1c40863..524e67b 100644
--- a/src/examples/Makefile.am
+++ b/src/examples/Makefile.am
@@ -15,7 +15,7 @@ INCLUDES = \
-D_REENTRANT \
$(NULL)
-noinst_PROGRAMS = cancel
+noinst_PROGRAMS = cancel cancelobtain
cancel_SOURCES = cancel.c
@@ -28,5 +28,16 @@ cancel_LDADD = \
$(top_builddir)/src/polkit/libpolkit-gobject-1.la \
$(NULL)
+cancelobtain_SOURCES = cancelobtain.c
+
+cancelobtain_CFLAGS = \
+ $(GLIB_CFLAGS) \
+ $(NULL)
+
+cancelobtain_LDADD = \
+ $(GLIB_LDADD) \
+ $(top_builddir)/src/polkit/libpolkit-gobject-1.la \
+ $(NULL)
+
clean-local :
rm -f *~
diff --git a/src/examples/cancelobtain.c b/src/examples/cancelobtain.c
new file mode 100644
index 0000000..ea37d8f
--- /dev/null
+++ b/src/examples/cancelobtain.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2009 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>
+ */
+
+/* Simple example that shows how to obtain an authorization including
+ * cancelling the request.
+ */
+
+#include <polkit/polkit.h>
+
+static void
+obtain_authorization_cb (PolkitAuthority *authority,
+ GAsyncResult *res,
+ GMainLoop *loop)
+{
+ GError *error;
+
+ error = NULL;
+ if (!polkit_authority_obtain_authorization_finish (authority, res, &error))
+ {
+ g_print ("Error obtaining authorization: %s\n", error->message);
+ g_error_free (error);
+ }
+
+ g_main_loop_quit (loop);
+}
+
+static gboolean
+do_cancel (GCancellable *cancellable)
+{
+ g_print ("Timer has expired; cancelling request\n");
+ g_cancellable_cancel (cancellable);
+ return FALSE;
+}
+
+int
+main (int argc, char *argv[])
+{
+ int ret;
+ GMainLoop *loop;
+ PolkitSubject *calling_process;
+ PolkitAuthority *authority;
+ GCancellable *cancellable;
+
+ g_type_init ();
+
+ ret = 1;
+
+ if (argc != 2)
+ {
+ g_printerr ("usage: cancelobtain <actionid>\n");
+ goto out;
+ }
+
+ loop = g_main_loop_new (NULL, FALSE);
+
+ authority = polkit_authority_get ();
+
+ calling_process = polkit_unix_process_new (getppid ());
+
+ cancellable = g_cancellable_new ();
+
+ g_print ("Will cancel request in 10 seconds\n");
+ g_timeout_add (10 * 1000,
+ (GSourceFunc) do_cancel,
+ cancellable);
+
+ polkit_authority_obtain_authorization (authority,
+ calling_process,
+ argv[1],
+ cancellable,
+ (GAsyncReadyCallback) obtain_authorization_cb,
+ loop);
+
+ g_main_loop_run (loop);
+
+ g_object_unref (authority);
+ g_object_unref (calling_process);
+ g_object_unref (cancellable);
+ g_main_loop_unref (loop);
+
+ ret = 0;
+
+ out:
+
+ return ret;
+}
diff --git a/src/polkit/polkitauthority.c b/src/polkit/polkitauthority.c
index c4ab0da..cbd2cc8 100644
--- a/src/polkit/polkitauthority.c
+++ b/src/polkit/polkitauthority.c
@@ -325,6 +325,7 @@ polkit_authority_enumerate_actions_sync (PolkitAuthority *authority,
}
/* ---------------------------------------------------------------------------------------------------- */
+
static guint
polkit_authority_check_authorization_async (PolkitAuthority *authority,
PolkitSubject *subject,
@@ -490,7 +491,7 @@ polkit_authority_check_authorization_finish (PolkitAuthority *authority
}
/**
- * polkit_authority_check_authorization:
+ * polkit_authority_check_authorization_sync:
* @authority: A #PolkitAuthority.
* @subject: A #PolkitSubject.
* @action_id: The action to check for.
@@ -535,6 +536,208 @@ polkit_authority_check_authorization_sync (PolkitAuthority *author
/* ---------------------------------------------------------------------------------------------------- */
static guint
+polkit_authority_obtain_authorization_async (PolkitAuthority *authority,
+ PolkitSubject *subject,
+ const gchar *action_id,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ _PolkitSubject *real_subject;
+ guint call_id;
+ GSimpleAsyncResult *simple;
+ gchar *cancellation_id;
+
+ real_subject = polkit_subject_get_real (subject);
+
+ simple = g_simple_async_result_new (G_OBJECT (authority),
+ callback,
+ user_data,
+ polkit_authority_obtain_authorization_async);
+
+ cancellation_id = NULL;
+ if (cancellable != NULL)
+ {
+ cancellation_id = g_strdup_printf ("cancellation-id-%d", authority->cancellation_id_counter++);
+ g_object_set_data_full (G_OBJECT (simple), "polkit-1-cancellation-id", cancellation_id, g_free);
+ }
+
+ call_id = _polkit_authority_obtain_authorization (authority->real,
+ EGG_DBUS_CALL_FLAGS_TIMEOUT_NONE,
+ real_subject,
+ action_id,
+ cancellation_id,
+ cancellable,
+ generic_async_cb,
+ simple);
+
+ g_object_unref (real_subject);
+
+ return call_id;
+}
+
+/**
+ * polkit_authority_obtain_authorization:
+ * @authority: A #PolkitAuthority.
+ * @subject: A #PolkitSubject.
+ * @action_id: The action to obtain an authorization for.
+ * @cancellable: A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
+ * @user_data: The data to pass to @callback.
+ *
+ * Asynchronously obtains a temporary authorization for @subject to
+ * perform the action represented by @action_id.
+ *
+ * When the operation is finished, @callback will be invoked. You can
+ * then call polkit_authority_obtain_authorization_finish() to get the
+ * result of the operation.
+ **/
+void
+polkit_authority_obtain_authorization (PolkitAuthority *authority,
+ PolkitSubject *subject,
+ const gchar *action_id,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ polkit_authority_obtain_authorization_async (authority,
+ subject,
+ action_id,
+ cancellable,
+ callback,
+ user_data);
+}
+
+static void
+authorization_obtain_cancelled_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GError *error;
+
+ error = NULL;
+ if (!_polkit_authority_cancel_obtain_authorization_finish (_POLKIT_AUTHORITY (source_object),
+ res,
+ &error))
+ {
+ g_warning ("Error cancelling obtain authorization call: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+/**
+ * polkit_authority_obtain_authorization_finish:
+ * @authority: A #PolkitAuthority.
+ * @res: A #GAsyncResult obtained from the callback.
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes obtaining an authorization.
+ *
+ * Returns: %TRUE if the authorization was obtained, %FALSE if @error is set.
+ **/
+gboolean
+polkit_authority_obtain_authorization_finish (PolkitAuthority *authority,
+ GAsyncResult *res,
+ GError **error)
+{
+ gboolean result;
+ GSimpleAsyncResult *simple;
+ GAsyncResult *real_res;
+ GError *local_error;
+
+ simple = G_SIMPLE_ASYNC_RESULT (res);
+ real_res = G_ASYNC_RESULT (g_simple_async_result_get_op_res_gpointer (simple));
+
+ g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == polkit_authority_obtain_authorization_async);
+
+ result = _POLKIT_AUTHORIZATION_RESULT_NOT_AUTHORIZED;
+
+ local_error = NULL;
+ result = _polkit_authority_obtain_authorization_finish (authority->real,
+ real_res,
+ &local_error);
+
+ if (local_error != NULL)
+ {
+ if (local_error->domain == EGG_DBUS_ERROR && local_error->code == EGG_DBUS_ERROR_CANCELLED)
+ {
+ const gchar *cancellation_id;
+
+ /* if the operation was cancelled locally, make sure to tell the daemon so the authentication
+ * dialog etc. can be removed
+ */
+ cancellation_id = g_object_get_data (G_OBJECT (simple), "polkit-1-cancellation-id");
+ if (cancellation_id != NULL)
+ {
+ _polkit_authority_cancel_obtain_authorization (authority->real,
+ EGG_DBUS_CALL_FLAGS_NONE,
+ cancellation_id,
+ NULL,
+ authorization_obtain_cancelled_cb,
+ NULL);
+ }
+
+ g_set_error (error,
+ POLKIT_ERROR,
+ POLKIT_ERROR_CANCELLED,
+ "The operation was cancelled");
+ g_error_free (local_error);
+ }
+ else
+ {
+ g_propagate_error (error, local_error);
+ }
+ }
+
+ g_object_unref (real_res);
+ return result;
+}
+
+/**
+ * polkit_authority_obtain_authorization_sync:
+ * @authority: A #PolkitAuthority.
+ * @subject: A #PolkitSubject.
+ * @action_id: The action to obtain for.
+ * @flags: A set of #PolkitObtainAuthorizationFlags.
+ * @cancellable: A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
+ * @user_data: The data to pass to @callback.
+ *
+ * Obtains a temporary authorization for @subject to perform the
+ * action represented by @action_id.
+ *
+ * Returns: %TRUE if the authorization was obtained, %FALSE if @error is set.
+ */
+gboolean
+polkit_authority_obtain_authorization_sync (PolkitAuthority *authority,
+ PolkitSubject *subject,
+ const gchar *action_id,
+ GCancellable *cancellable,
+ GError **error)
+{
+ guint call_id;
+ GAsyncResult *res;
+ gboolean result;
+
+ call_id = polkit_authority_obtain_authorization_async (authority,
+ subject,
+ action_id,
+ cancellable,
+ generic_cb,
+ &res);
+
+ egg_dbus_connection_pending_call_block (authority->system_bus, call_id);
+
+ result = polkit_authority_obtain_authorization_finish (authority, res, error);
+
+ g_object_unref (res);
+
+ return result;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static guint
polkit_authority_register_authentication_agent_async (PolkitAuthority *authority,
const gchar *session_id,
const gchar *object_path,
diff --git a/src/polkit/polkitauthority.h b/src/polkit/polkitauthority.h
index 24d7a94..1337d48 100644
--- a/src/polkit/polkitauthority.h
+++ b/src/polkit/polkitauthority.h
@@ -65,6 +65,12 @@ PolkitAuthorizationResult polkit_authority_check_authorization_sync (PolkitAuth
GCancellable *cancellable,
GError **error);
+gboolean polkit_authority_obtain_authorization_sync (PolkitAuthority *authority,
+ PolkitSubject *subject,
+ const gchar *action_id,
+ GCancellable *cancellable,
+ GError **error);
+
gboolean polkit_authority_register_authentication_agent_sync (PolkitAuthority *authority,
const gchar *session_id,
const gchar *object_path,
@@ -106,6 +112,16 @@ PolkitAuthorizationResult polkit_authority_check_authorization_finish (PolkitAu
GAsyncResult *res,
GError **error);
+void polkit_authority_obtain_authorization (PolkitAuthority *authority,
+ PolkitSubject *subject,
+ const gchar *action_id,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean polkit_authority_obtain_authorization_finish (PolkitAuthority *authority,
+ GAsyncResult *res,
+ GError **error);
void polkit_authority_register_authentication_agent (PolkitAuthority *authority,
const gchar *session_id,
diff --git a/src/polkitbackend/polkitbackendauthority.c b/src/polkitbackend/polkitbackendauthority.c
index bf40283..961fc49 100644
--- a/src/polkitbackend/polkitbackendauthority.c
+++ b/src/polkitbackend/polkitbackendauthority.c
@@ -195,6 +195,8 @@ polkit_backend_authority_enumerate_groups (PolkitBackendAuthority *authority,
}
}
+/* ---------------------------------------------------------------------------------------------------- */
+
/**
* polkit_backend_authority_check_authorization:
* @authority: A #PolkitBackendAuthority.
@@ -279,6 +281,91 @@ polkit_backend_authority_check_authorization_finish (PolkitBackendAuthority *au
}
}
+/* ---------------------------------------------------------------------------------------------------- */
+
+/**
+ * polkit_backend_authority_obtain_authorization:
+ * @authority: A #PolkitBackendAuthority.
+ * @caller: The system bus name that initiated the query.
+ * @subject: A #PolkitSubject.
+ * @action_id: The action to obtain.
+ * @cancellable: A #GCancellable.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
+ * @user_data: The data to pass to @callback.
+ *
+ * Asynchronously obtains a temporary authorization for @subject to
+ * perform the action represented by @action_id. If @subject is already
+ * authorized for @action_id, return %TRUE. If @action_id doesn't allow
+ * temporary authorizations, return a %POLKIT_ERROR_FAILED error.
+ *
+ * When the operation is finished, @callback will be invoked. You can then
+ * call polkit_backend_authority_obtain_authorization_finish() to get the result of
+ * the operation.
+ **/
+void
+polkit_backend_authority_obtain_authorization (PolkitBackendAuthority *authority,
+ PolkitSubject *caller,
+ PolkitSubject *subject,
+ const gchar *action_id,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ PolkitBackendAuthorityClass *klass;
+
+ klass = POLKIT_BACKEND_AUTHORITY_GET_CLASS (authority);
+
+ if (klass->obtain_authorization == NULL)
+ {
+ GSimpleAsyncResult *simple;
+
+ simple = g_simple_async_result_new_error (G_OBJECT (authority),
+ callback,
+ user_data,
+ POLKIT_ERROR,
+ POLKIT_ERROR_NOT_SUPPORTED,
+ "Operation not supported");
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ }
+ else
+ {
+ klass->obtain_authorization (authority, caller, subject, action_id, cancellable, callback, user_data);
+ }
+}
+
+/**
+ * polkit_backend_authority_obtain_authorization_finish:
+ * @authority: A #PolkitBackendAuthority.
+ * @res: A #GAsyncResult obtained from the callback.
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes obtaining an authorization.
+ *
+ * Returns: %TRUE if the authorization was obtained, %FALSE if @error is set.
+ **/
+gboolean
+polkit_backend_authority_obtain_authorization_finish (PolkitBackendAuthority *authority,
+ GAsyncResult *res,
+ GError **error)
+{
+ PolkitBackendAuthorityClass *klass;
+
+ klass = POLKIT_BACKEND_AUTHORITY_GET_CLASS (authority);
+
+ if (klass->obtain_authorization_finish == NULL)
+ {
+ g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
+ return FALSE;
+ }
+ else
+ {
+ return klass->obtain_authorization_finish (authority, res, error);
+ }
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
/**
* polkit_backend_authority_enumerate_authorizations:
* @authority: A #PolkitBackendAuthority.
@@ -904,6 +991,136 @@ authority_handle_cancel_check_authorization (_PolkitAuthority *ins
/* ---------------------------------------------------------------------------------------------------- */
static void
+obtain_auth_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ EggDBusMethodInvocation *method_invocation = EGG_DBUS_METHOD_INVOCATION (user_data);
+ const gchar *full_cancellation_id;
+ GError *error;
+
+ error = NULL;
+ polkit_backend_authority_obtain_authorization_finish (POLKIT_BACKEND_AUTHORITY (source_object),
+ res,
+ &error);
+
+ full_cancellation_id = g_object_get_data (G_OBJECT (method_invocation), "cancellation-id");
+ if (full_cancellation_id != NULL)
+ {
+ Server *server;
+ server = SERVER (g_object_get_data (G_OBJECT (method_invocation), "server"));
+ g_hash_table_remove (server->cancellation_id_to_cancellable, full_cancellation_id);
+ }
+
+ if (error != NULL)
+ {
+ egg_dbus_method_invocation_return_gerror (method_invocation, error);
+ g_error_free (error);
+ }
+ else
+ {
+ _polkit_authority_handle_obtain_authorization_finish (method_invocation);
+ }
+}
+
+static void
+authority_handle_obtain_authorization (_PolkitAuthority *instance,
+ _PolkitSubject *real_subject,
+ const gchar *action_id,
+ const gchar *cancellation_id,
+ EggDBusMethodInvocation *method_invocation)
+{
+ Server *server = SERVER (instance);
+ const gchar *caller_name;
+ PolkitSubject *subject;
+ PolkitSubject *caller;
+ GCancellable *cancellable;
+
+ caller_name = egg_dbus_method_invocation_get_caller (method_invocation);
+ caller = polkit_system_bus_name_new (caller_name);
+
+ subject = polkit_subject_new_for_real (real_subject);
+
+ g_object_set_data_full (G_OBJECT (method_invocation), "caller", caller, (GDestroyNotify) g_object_unref);
+ g_object_set_data_full (G_OBJECT (method_invocation), "subject", subject, (GDestroyNotify) g_object_unref);
+
+ cancellable = NULL;
+ if (cancellation_id != NULL && strlen (cancellation_id) > 0)
+ {
+ gchar *full_cancellation_id;
+
+ full_cancellation_id = g_strdup_printf ("%s-%s", caller_name, cancellation_id);
+
+ if (g_hash_table_lookup (server->cancellation_id_to_cancellable, full_cancellation_id) != NULL)
+ {
+ egg_dbus_method_invocation_return_error (method_invocation,
+ _POLKIT_ERROR,
+ _POLKIT_ERROR_CANCELLATION_ID_NOT_UNIQUE,
+ "Given cancellation_id %s is already in use for name %s",
+ cancellation_id,
+ caller_name);
+ g_free (full_cancellation_id);
+ goto out;
+ }
+
+ cancellable = g_cancellable_new ();
+
+ g_hash_table_insert (server->cancellation_id_to_cancellable,
+ full_cancellation_id,
+ cancellable);
+
+ g_object_set_data (G_OBJECT (method_invocation), "server", server);
+ g_object_set_data (G_OBJECT (method_invocation), "cancellation-id", full_cancellation_id);
+ }
+
+ polkit_backend_authority_obtain_authorization (server->authority,
+ caller,
+ subject,
+ action_id,
+ cancellable,
+ obtain_auth_cb,
+ method_invocation);
+ out:
+ ;
+}
+
+static void
+authority_handle_cancel_obtain_authorization (_PolkitAuthority *instance,
+ const gchar *cancellation_id,
+ EggDBusMethodInvocation *method_invocation)
+{
+ Server *server = SERVER (instance);
+ GCancellable *cancellable;
+ const gchar *caller_name;
+ gchar *full_cancellation_id;
+
+ caller_name = egg_dbus_method_invocation_get_caller (method_invocation);
+
+ full_cancellation_id = g_strdup_printf ("%s-%s", caller_name, cancellation_id);
+
+ cancellable = g_hash_table_lookup (server->cancellation_id_to_cancellable, full_cancellation_id);
+ if (cancellable == NULL)
+ {
+ egg_dbus_method_invocation_return_error (method_invocation,
+ _POLKIT_ERROR,
+ _POLKIT_ERROR_FAILED,
+ "No such cancellation_id %s for name %s",
+ cancellation_id,
+ caller_name);
+ goto out;
+ }
+
+ g_cancellable_cancel (cancellable);
+
+ _polkit_authority_handle_cancel_obtain_authorization_finish (method_invocation);
+
+ out:
+ g_free (full_cancellation_id);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
authority_manager_handle_enumerate_authorizations (_PolkitAuthorityManager *instance,
_PolkitIdentity *real_identity,
EggDBusMethodInvocation *method_invocation)
@@ -1153,6 +1370,8 @@ authority_iface_init (_PolkitAuthorityIface *authority_iface)
authority_iface->handle_enumerate_actions = authority_handle_enumerate_actions;
authority_iface->handle_check_authorization = authority_handle_check_authorization;
authority_iface->handle_cancel_check_authorization = authority_handle_cancel_check_authorization;
+ authority_iface->handle_obtain_authorization = authority_handle_obtain_authorization;
+ authority_iface->handle_cancel_obtain_authorization = authority_handle_cancel_obtain_authorization;
authority_iface->handle_register_authentication_agent = authority_handle_register_authentication_agent;
authority_iface->handle_unregister_authentication_agent = authority_handle_unregister_authentication_agent;
authority_iface->handle_authentication_agent_response = authority_handle_authentication_agent_response;
diff --git a/src/polkitbackend/polkitbackendauthority.h b/src/polkitbackend/polkitbackendauthority.h
index e08360b..ce63f5d 100644
--- a/src/polkitbackend/polkitbackendauthority.h
+++ b/src/polkitbackend/polkitbackendauthority.h
@@ -70,6 +70,13 @@ struct _PolkitBackendAuthority
* @check_authorization_finish: Called when finishing an authorization
* check. See polkit_backend_authority_check_authorization_finish()
* for details.
+ * @obtain_authorization: Called to obtain an authorization or %NULL
+ * if the backend doesn't support the operation. See
+ * polkit_backend_authority_obtain_authorization() for details.
+ * @obtain_authorization_finish: Called when finishing obtaining
+ * an authorization or %NULL if the backend doesn't support the
+ * operation. See polkit_backend_authority_obtain_authorization_finish()
+ * for details.
* @register_authentication_agent: Called when an authentication agent
* is attempting to register or %NULL if the backend doesn't support
* the operation. See
@@ -132,6 +139,18 @@ struct _PolkitBackendAuthorityClass
GAsyncResult *res,
GError **error);
+ void (*obtain_authorization) (PolkitBackendAuthority *authority,
+ PolkitSubject *caller,
+ PolkitSubject *subject,
+ const gchar *action_id,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+ gboolean (*obtain_authorization_finish) (PolkitBackendAuthority *authority,
+ GAsyncResult *res,
+ GError **error);
+
gboolean (*register_authentication_agent) (PolkitBackendAuthority *authority,
PolkitSubject *caller,
const gchar *session_id,
@@ -228,6 +247,18 @@ PolkitAuthorizationResult polkit_backend_authority_check_authorization_finish (P
GAsyncResult *res,
GError **error);
+void polkit_backend_authority_obtain_authorization (PolkitBackendAuthority *authority,
+ PolkitSubject *caller,
+ PolkitSubject *subject,
+ const gchar *action_id,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean polkit_backend_authority_obtain_authorization_finish (PolkitBackendAuthority *authority,
+ GAsyncResult *res,
+ GError **error);
+
GList *polkit_backend_authority_enumerate_authorizations (PolkitBackendAuthority *authority,
PolkitSubject *caller,
PolkitIdentity *identity,
diff --git a/src/polkitbackend/polkitbackendlocalauthority.c b/src/polkitbackend/polkitbackendlocalauthority.c
index c735c8c..be09d37 100644
--- a/src/polkitbackend/polkitbackendlocalauthority.c
+++ b/src/polkitbackend/polkitbackendlocalauthority.c
@@ -167,6 +167,18 @@ static PolkitAuthorizationResult polkit_backend_local_authority_check_authorizat
GAsyncResult *res,
GError **error);
+static void polkit_backend_local_authority_obtain_authorization (PolkitBackendAuthority *authority,
+ PolkitSubject *caller,
+ PolkitSubject *subject,
+ const gchar *action_id,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+static gboolean polkit_backend_local_authority_obtain_authorization_finish (PolkitBackendAuthority *authority,
+ GAsyncResult *res,
+ GError **error);
+
static PolkitAuthorizationResult check_authorization_sync (PolkitBackendAuthority *authority,
PolkitSubject *subject,
const gchar *action_id,
@@ -297,6 +309,8 @@ polkit_backend_local_authority_class_init (PolkitBackendLocalAuthorityClass *kla
authority_class->enumerate_groups = polkit_backend_local_authority_enumerate_groups;
authority_class->check_authorization = polkit_backend_local_authority_check_authorization;
authority_class->check_authorization_finish = polkit_backend_local_authority_check_authorization_finish;
+ authority_class->obtain_authorization = polkit_backend_local_authority_obtain_authorization;
+ authority_class->obtain_authorization_finish = polkit_backend_local_authority_obtain_authorization_finish;
authority_class->enumerate_authorizations = polkit_backend_local_authority_enumerate_authorizations;
authority_class->add_authorization = polkit_backend_local_authority_add_authorization;
authority_class->remove_authorization = polkit_backend_local_authority_remove_authorization;
@@ -426,6 +440,251 @@ polkit_backend_local_authority_enumerate_groups (PolkitBackendAuthority *autho
/* ---------------------------------------------------------------------------------------------------- */
static void
+obtain_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);
+ gchar *subject_str;
+
+ subject_str = polkit_subject_to_string (subject);
+
+ g_debug ("In obtain_authorization_challenge_cb\n"
+ " subject %s\n"
+ " action_id %s\n"
+ " authentication_success %d\n",
+ subject_str,
+ action_id,
+ authentication_success);
+
+ if (authentication_success)
+ {
+ GError *error;
+ PolkitAuthorization *authorization;
+
+ authorization = polkit_authorization_new (action_id,
+ subject,
+ FALSE);
+
+ if (!add_authorization_for_identity (authority,
+ user_of_subject,
+ authorization,
+ &error))
+ {
+ g_simple_async_result_set_from_error (simple, error);
+ g_error_free (error);
+ }
+ }
+ else
+ {
+ g_simple_async_result_set_error (simple,
+ POLKIT_ERROR,
+ POLKIT_ERROR_FAILED,
+ "Could not obtain authorization");
+ }
+
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+
+ g_free (subject_str);
+}
+
+static gboolean
+polkit_backend_local_authority_obtain_authorization_finish (PolkitBackendAuthority *authority,
+ GAsyncResult *res,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+
+ simple = G_SIMPLE_ASYNC_RESULT (res);
+
+ g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == polkit_backend_local_authority_obtain_authorization);
+
+ return g_simple_async_result_propagate_error (simple, error);
+}
+
+static void
+polkit_backend_local_authority_obtain_authorization (PolkitBackendAuthority *authority,
+ PolkitSubject *caller,
+ PolkitSubject *subject,
+ const gchar *action_id,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ 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;
+
+ simple = g_simple_async_result_new (G_OBJECT (authority),
+ callback,
+ user_data,
+ polkit_backend_local_authority_obtain_authorization);
+
+ caller_str = polkit_subject_to_string (caller);
+ subject_str = polkit_subject_to_string (subject);
+
+ g_debug ("%s is attempting to obtain an temporary authorization for %s to perform %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);
+
+ 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);
+
+ /* if the user of the caller and the user of the subject isn't the same, then fail */
+ if (!polkit_identity_equal (user_of_caller, user_of_subject))
+ {
+ g_simple_async_result_set_error (simple,
+ POLKIT_ERROR,
+ POLKIT_ERROR_NOT_AUTHORIZED,
+ "%s is not authorized to request an authorization for %s",
+ caller_str,
+ subject_str);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ goto out;
+ }
+
+ /* see if subject already has an authorization */
+ result = check_authorization_sync (authority,
+ subject,
+ action_id,
+ POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE,
+ &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;
+ }
+
+ /* If the user can indeed obtain the authorization and the authorization can be retained, then do so */
+ if (result == POLKIT_AUTHORIZATION_RESULT_CHALLENGE &&
+ (implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_AUTHENTICATION_REQUIRED_RETAINED ||
+ implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_ADMINISTRATOR_AUTHENTICATION_REQUIRED_RETAINED))
+ {
+ AuthenticationAgent *agent;
+
+ agent = get_authentication_agent_for_subject (local_authority, subject);
+ if (agent == NULL)
+ {
+ g_simple_async_result_set_error (simple,
+ POLKIT_ERROR,
+ POLKIT_ERROR_FAILED,
+ "Authorization can be obtained, but no suitable authentication agent is available");
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ goto out;
+ }
+ else
+ {
+ g_debug (" using authentication agent for challenge to obtain an authorization");
+
+ authentication_agent_initiate_challenge (agent,
+ subject,
+ user_of_subject,
+ local_authority,
+ action_id,
+ caller,
+ implicit_authorization,
+ cancellable,
+ obtain_authorization_challenge_cb,
+ simple);
+
+ /* keep going */
+ goto out;
+ }
+ }
+
+ /* if the subject is already authorized, return without an error */
+ if (result == POLKIT_AUTHORIZATION_RESULT_AUTHORIZED)
+ {
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ goto out;
+ }
+
+ /* otherwise return an error */
+ g_simple_async_result_set_error (simple,
+ POLKIT_ERROR,
+ POLKIT_ERROR_FAILED,
+ "Desired authorization cannot be obtained. This incident has been logged.");
+ 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 void
check_authorization_challenge_cb (AuthenticationAgent *agent,
PolkitSubject *subject,
PolkitIdentity *user_of_subject,
diff --git a/src/programs/polkit.c b/src/programs/polkit.c
index ea2cacd..1bc2579 100644
--- a/src/programs/polkit.c
+++ b/src/programs/polkit.c
@@ -632,35 +632,24 @@ list_groups (void)
static gint
do_run (gint argc, gchar *argv[])
{
- PolkitAuthorizationResult result;
PolkitSubject *calling_process;
GError *error;
- gboolean ret;
- ret = FALSE;
- error = NULL;
calling_process = polkit_unix_process_new (getpid ());
- result = polkit_authority_check_authorization_sync (authority,
- calling_process,
- action_id,
- POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
- NULL,
- &error);
- if (error != NULL)
+ error = NULL;
+ if (!polkit_authority_obtain_authorization_sync (authority,
+ calling_process,
+ action_id,
+ NULL,
+ &error))
{
- g_printerr ("Error checking authorization for action %s: %s\n", action_id, error->message);
+ g_printerr ("Error obtaining authorization for action %s: %s\n", action_id, error->message);
g_error_free (error);
goto out;
}
- if (result != POLKIT_AUTHORIZATION_RESULT_AUTHORIZED)
- {
- g_printerr ("Error obtaining authorization for action %s (%d)\n", action_id, result);
- goto out;
- }
-
execvp (argv[0], argv);
g_printerr ("Error launching program: %m\n");
@@ -669,7 +658,7 @@ do_run (gint argc, gchar *argv[])
g_object_unref (calling_process);
- return ret;
+ return FALSE;
}
/* ---------------------------------------------------------------------------------------------------- */
More information about the hal-commit
mailing list