diff options
author | David Zeuthen <davidz@redhat.com> | 2011-09-20 14:13:12 -0400 |
---|---|---|
committer | David Zeuthen <davidz@redhat.com> | 2011-09-20 14:13:51 -0400 |
commit | 6bbd5189e967e8ddc36100bf22cd12bcb152ab5f (patch) | |
tree | 4f300223c3ef8bda12985fe97ec297a1f3e8d11b | |
parent | bb3339a57a4db04aae650d77a6f4b98752a88eaf (diff) | |
download | polkit-6bbd5189e967e8ddc36100bf22cd12bcb152ab5f.tar.gz |
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>
-rw-r--r-- | docs/man/polkit.xml | 25 | ||||
-rw-r--r-- | src/polkitbackend/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); |