256 lines
10 KiB
Diff
256 lines
10 KiB
Diff
|
From 6bbd5189e967e8ddc36100bf22cd12bcb152ab5f Mon Sep 17 00:00:00 2001
|
||
|
From: David Zeuthen <davidz@redhat.com>
|
||
|
Date: Tue, 20 Sep 2011 14:13:12 -0400
|
||
|
Subject: [PATCH 1/3] Add support for the org.freedesktop.policykit.imply annotation
|
||
|
|
||
|
For example, GNOME control center can now defined e.g.
|
||
|
|
||
|
<action id="org.zee.example.meta">
|
||
|
<description>Meta Action</description>
|
||
|
<message>Example of a meta action, blabla</message>
|
||
|
<defaults>
|
||
|
<allow_any>no</allow_any>
|
||
|
<allow_inactive>no</allow_inactive>
|
||
|
<allow_active>auth_admin_keep</allow_active>
|
||
|
</defaults>
|
||
|
<annotate key="org.freedesktop.policykit.imply">org.freedesktop.udisks2.ata-smart-selftest org.freedesktop.udisks2.encrypted-lock-others org.freedesktop.udisks2.filesystem-unmount-others</annotate>
|
||
|
</action>
|
||
|
|
||
|
and set up a single GtkLockButton for a PolkitPermission for action id
|
||
|
"org.zee.example.meta".
|
||
|
|
||
|
When unlocked the given subject will now be authorized for the actions
|
||
|
mentioned in the annotation.
|
||
|
|
||
|
Example test program:
|
||
|
|
||
|
int
|
||
|
main (int argc, char *argv[])
|
||
|
{
|
||
|
PolkitSubject *subject;
|
||
|
GtkWidget *window;
|
||
|
GtkWidget *table;
|
||
|
GMainLoop *loop;
|
||
|
guint n;
|
||
|
|
||
|
gtk_init (&argc, &argv);
|
||
|
|
||
|
subject = polkit_unix_process_new (getpid ());
|
||
|
|
||
|
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||
|
|
||
|
table = gtk_table_new (1, 2, FALSE);
|
||
|
for (n = 1; n < argc; n++)
|
||
|
{
|
||
|
const gchar *action_id = argv[n];
|
||
|
GPermission *permission;
|
||
|
GtkWidget *label;
|
||
|
GtkWidget *lock_button;
|
||
|
GError *error = NULL;
|
||
|
|
||
|
label = gtk_label_new (action_id);
|
||
|
|
||
|
permission = polkit_permission_new_sync (action_id, subject, NULL, &error);
|
||
|
if (permission == NULL)
|
||
|
{
|
||
|
g_error ("Error constructing permission for action_id %s: %s (%s, %d)",
|
||
|
action_id, error->message, g_quark_to_string (error->domain), error->code);
|
||
|
goto out;
|
||
|
}
|
||
|
lock_button = gtk_lock_button_new (permission);
|
||
|
g_object_unref (permission);
|
||
|
|
||
|
gtk_table_attach (GTK_TABLE (table), label, 0, 1, n - 1, n, GTK_FILL, GTK_FILL, 0, 0);
|
||
|
gtk_table_attach (GTK_TABLE (table), lock_button, 1, 2, n - 1, n, GTK_FILL, GTK_FILL, 0, 0);
|
||
|
}
|
||
|
gtk_container_add (GTK_CONTAINER (window), table);
|
||
|
|
||
|
gtk_widget_show_all (window);
|
||
|
|
||
|
loop = g_main_loop_new (NULL, FALSE);
|
||
|
g_main_loop_run (loop);
|
||
|
|
||
|
out:
|
||
|
;
|
||
|
}
|
||
|
|
||
|
Compile with:
|
||
|
|
||
|
gcc -o showpolkit showpolkit.c `pkg-config --cflags --libs polkit-gobject-1 gtk+-3.0` -g -O0
|
||
|
|
||
|
Run with:
|
||
|
|
||
|
./showpolkit org.freedesktop.udisks2.ata-smart-selftest org.freedesktop.udisks2.encrypted-lock-others org.freedesktop.udisks2.filesystem-unmount-others org.zee.example.meta
|
||
|
|
||
|
Signed-off-by: David Zeuthen <davidz@redhat.com>
|
||
|
---
|
||
|
docs/man/polkit.xml | 25 +++++++-
|
||
|
.../polkitbackendinteractiveauthority.c | 67 ++++++++++++++++++++
|
||
|
2 files changed, 90 insertions(+), 2 deletions(-)
|
||
|
|
||
|
diff --git a/docs/man/polkit.xml b/docs/man/polkit.xml
|
||
|
index bcb276b..bfa5ccd 100644
|
||
|
--- a/docs/man/polkit.xml
|
||
|
+++ b/docs/man/polkit.xml
|
||
|
@@ -369,8 +369,7 @@ System Context | |
|
||
|
the <literal>key</literal> attribute and the value is
|
||
|
specified using the <literal>value</literal> attribute. This
|
||
|
element may appear zero or more times. See
|
||
|
- <citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||
|
- for an example of how this can be used. </para></listitem>
|
||
|
+ below for known annotations. </para></listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term><emphasis>vendor</emphasis></term>
|
||
|
@@ -398,6 +397,28 @@ System Context | |
|
||
|
<citerefentry><refentrytitle>pkaction</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||
|
command.
|
||
|
</para>
|
||
|
+
|
||
|
+ <refsect2><title>Known annotations</title>
|
||
|
+ <para>
|
||
|
+ The <literal>org.freedesktop.policykit.exec.path</literal>
|
||
|
+ annotation is used by the <command>pkexec</command> program
|
||
|
+ shipped with PolicyKit - see the
|
||
|
+ <citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||
|
+ man page for details.
|
||
|
+ </para>
|
||
|
+ <para>
|
||
|
+ The <literal>org.freedesktop.policykit.imply</literal>
|
||
|
+ annotation (its value is a string containing a space separated
|
||
|
+ list of action identifiers) can be used to define <emphasis>meta
|
||
|
+ actions</emphasis>. The way it works is that if a subject is
|
||
|
+ authorized for an action with this annotation, then it is also
|
||
|
+ authorized for any action specified by the annotation. A typical
|
||
|
+ use of this annotation is when defining an UI shell with a
|
||
|
+ single lock button that should unlock multiple actions from
|
||
|
+ distinct mechanisms.
|
||
|
+ </para>
|
||
|
+ </refsect2>
|
||
|
+
|
||
|
</refsect1>
|
||
|
|
||
|
<refsect1 id="polkit-author"><title>AUTHOR</title>
|
||
|
diff --git a/src/polkitbackend/polkitbackendinteractiveauthority.c b/src/polkitbackend/polkitbackendinteractiveauthority.c
|
||
|
index 8b32459..3566248 100644
|
||
|
--- a/src/polkitbackend/polkitbackendinteractiveauthority.c
|
||
|
+++ b/src/polkitbackend/polkitbackendinteractiveauthority.c
|
||
|
@@ -148,6 +148,7 @@ static PolkitAuthorizationResult *check_authorization_sync (PolkitBackendAuthori
|
||
|
PolkitDetails *details,
|
||
|
PolkitCheckAuthorizationFlags flags,
|
||
|
PolkitImplicitAuthorization *out_implicit_authorization,
|
||
|
+ gboolean checking_imply,
|
||
|
GError **error);
|
||
|
|
||
|
static gboolean polkit_backend_interactive_authority_register_authentication_agent (PolkitBackendAuthority *authority,
|
||
|
@@ -890,6 +891,7 @@ polkit_backend_interactive_authority_check_authorization (PolkitBackendAuthority
|
||
|
details,
|
||
|
flags,
|
||
|
&implicit_authorization,
|
||
|
+ FALSE, /* checking_imply */
|
||
|
&error);
|
||
|
if (error != NULL)
|
||
|
{
|
||
|
@@ -964,6 +966,7 @@ check_authorization_sync (PolkitBackendAuthority *authority,
|
||
|
PolkitDetails *details,
|
||
|
PolkitCheckAuthorizationFlags flags,
|
||
|
PolkitImplicitAuthorization *out_implicit_authorization,
|
||
|
+ gboolean checking_imply,
|
||
|
GError **error)
|
||
|
{
|
||
|
PolkitBackendInteractiveAuthority *interactive_authority;
|
||
|
@@ -979,12 +982,15 @@ check_authorization_sync (PolkitBackendAuthority *authority,
|
||
|
PolkitImplicitAuthorization implicit_authorization;
|
||
|
const gchar *tmp_authz_id;
|
||
|
PolkitDetails *result_details;
|
||
|
+ GList *actions;
|
||
|
+ GList *l;
|
||
|
|
||
|
interactive_authority = POLKIT_BACKEND_INTERACTIVE_AUTHORITY (authority);
|
||
|
priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (interactive_authority);
|
||
|
|
||
|
result = NULL;
|
||
|
|
||
|
+ actions = NULL;
|
||
|
user_of_subject = NULL;
|
||
|
groups_of_user = NULL;
|
||
|
subject_str = NULL;
|
||
|
@@ -1095,6 +1101,64 @@ check_authorization_sync (PolkitBackendAuthority *authority,
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
+ /* then see if implied by another action that the subject is authorized for
|
||
|
+ * (but only one level deep to avoid infinite recursion)
|
||
|
+ *
|
||
|
+ * TODO: if this is slow, we can maintain a hash table for looking up what
|
||
|
+ * actions implies a given action
|
||
|
+ */
|
||
|
+ if (!checking_imply)
|
||
|
+ {
|
||
|
+ actions = polkit_backend_action_pool_get_all_actions (priv->action_pool, NULL);
|
||
|
+ for (l = actions; l != NULL; l = l->next)
|
||
|
+ {
|
||
|
+ PolkitActionDescription *imply_ad = POLKIT_ACTION_DESCRIPTION (l->data);
|
||
|
+ const gchar *imply;
|
||
|
+ imply = polkit_action_description_get_annotation (imply_ad, "org.freedesktop.policykit.imply");
|
||
|
+ if (imply != NULL)
|
||
|
+ {
|
||
|
+ gchar **tokens;
|
||
|
+ guint n;
|
||
|
+ tokens = g_strsplit (imply, " ", 0);
|
||
|
+ for (n = 0; tokens[n] != NULL; n++)
|
||
|
+ {
|
||
|
+ if (g_strcmp0 (tokens[n], action_id) == 0)
|
||
|
+ {
|
||
|
+ PolkitAuthorizationResult *implied_result = NULL;
|
||
|
+ PolkitImplicitAuthorization implied_implicit_authorization;
|
||
|
+ GError *implied_error = NULL;
|
||
|
+ const gchar *imply_action_id;
|
||
|
+
|
||
|
+ imply_action_id = polkit_action_description_get_action_id (imply_ad);
|
||
|
+
|
||
|
+ /* g_debug ("%s is implied by %s, checking", action_id, imply_action_id); */
|
||
|
+ implied_result = check_authorization_sync (authority, caller, subject,
|
||
|
+ imply_action_id,
|
||
|
+ details, flags,
|
||
|
+ &implied_implicit_authorization, TRUE,
|
||
|
+ &implied_error);
|
||
|
+ if (implied_result != NULL)
|
||
|
+ {
|
||
|
+ if (polkit_authorization_result_get_is_authorized (implied_result))
|
||
|
+ {
|
||
|
+ g_debug (" is authorized (implied by %s)", imply_action_id);
|
||
|
+ result = implied_result;
|
||
|
+ /* cleanup */
|
||
|
+ g_object_unref (result_details);
|
||
|
+ g_strfreev (tokens);
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+ g_object_unref (implied_result);
|
||
|
+ }
|
||
|
+ if (implied_error != NULL)
|
||
|
+ g_error_free (implied_error);
|
||
|
+ }
|
||
|
+ }
|
||
|
+ g_strfreev (tokens);
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
if (implicit_authorization != POLKIT_IMPLICIT_AUTHORIZATION_NOT_AUTHORIZED)
|
||
|
{
|
||
|
if (implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_AUTHENTICATION_REQUIRED_RETAINED ||
|
||
|
@@ -1118,6 +1182,9 @@ check_authorization_sync (PolkitBackendAuthority *authority,
|
||
|
g_debug (" not authorized");
|
||
|
}
|
||
|
out:
|
||
|
+ g_list_foreach (actions, (GFunc) g_object_unref, NULL);
|
||
|
+ g_list_free (actions);
|
||
|
+
|
||
|
g_free (subject_str);
|
||
|
|
||
|
g_list_foreach (groups_of_user, (GFunc) g_object_unref, NULL);
|
||
|
--
|
||
|
1.7.3.4
|
||
|
|