commit 9e566e98f49511827774799e7fdaa52acf097944 Author: Christopher James Halse Rogers Date: Thu Sep 29 12:02:14 2011 +1000 Add support for the org.freedesktop.policykit.owner annotation. This allows a mechanism daemon running as a system user to query whether clients are authorised for the annotated action. For example, colord running as the 'colord' system user would annotate its actions with unix-user:colord. Signed-off-by: Christopher James Halse Rogers diff --git a/docs/man/polkit.xml b/docs/man/polkit.xml index bfa5ccd..d484459 100644 --- a/docs/man/polkit.xml +++ b/docs/man/polkit.xml @@ -417,6 +417,18 @@ System Context | | single lock button that should unlock multiple actions from distinct mechanisms. + + The org.freedesktop.policykit.owner + annotation can be used to define a set of users who can + query whether a client is authorized to perform this action. + If this annotation is not specified then only root can query whether + a client running as a different user is authorized for an action. + A typical use of this annotation is for a mechanism daemon that runs + as a system user rather than root. + The value of this annotation is a string containing a space separated + list of PolkitIdentity of the form + unix-user:[uid|username]. + diff --git a/src/polkitbackend/polkitbackendinteractiveauthority.c b/src/polkitbackend/polkitbackendinteractiveauthority.c index 3566248..54695d4 100644 --- a/src/polkitbackend/polkitbackendinteractiveauthority.c +++ b/src/polkitbackend/polkitbackendinteractiveauthority.c @@ -762,10 +762,13 @@ polkit_backend_interactive_authority_check_authorization (PolkitBackendAuthority { PolkitBackendInteractiveAuthority *interactive_authority; PolkitBackendInteractiveAuthorityPrivate *priv; + PolkitActionDescription *action_desc; gchar *caller_str; gchar *subject_str; + const gchar *owners; PolkitIdentity *user_of_caller; PolkitIdentity *user_of_subject; + GList *owners_of_action; gchar *user_of_caller_str; gchar *user_of_subject_str; PolkitAuthorizationResult *result; @@ -781,8 +784,10 @@ polkit_backend_interactive_authority_check_authorization (PolkitBackendAuthority error = NULL; caller_str = NULL; subject_str = NULL; + owners = NULL; user_of_caller = NULL; user_of_subject = NULL; + owners_of_action = NULL; user_of_caller_str = NULL; user_of_subject_str = NULL; result = NULL; @@ -840,6 +845,53 @@ polkit_backend_interactive_authority_check_authorization (PolkitBackendAuthority user_of_subject_str = polkit_identity_to_string (user_of_subject); g_debug (" user of subject is %s", user_of_subject_str); + 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); + 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; + } + + owners = polkit_action_description_get_annotation (action_desc, "org.freedesktop.policykit.owner"); + + if (owners != NULL) + { + gchar **tokens; + gint n; + + tokens = g_strsplit (owners, " ", 0); + for (n = 0; tokens[n] != NULL; n++) + { + g_debug (" adding %s as an owner of action", tokens[n]); + owners_of_action = g_list_prepend (owners_of_action, polkit_identity_from_string (tokens[n], &error)); + + if (error != NULL) + { + g_strfreev (tokens); + 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; + } + } + + g_strfreev (tokens); + } + /* root is implicitly an owner of everything */ + owners_of_action = g_list_prepend (owners_of_action, polkit_unix_user_new (0)); + has_details = FALSE; if (details != NULL) { @@ -853,20 +905,30 @@ polkit_backend_interactive_authority_check_authorization (PolkitBackendAuthority } if (!polkit_identity_equal (user_of_caller, user_of_subject) || has_details) { - /* we only allow trusted callers (uid 0 + others) to check authorizations for subjects + /* we only allow trusted callers (uid 0 or owner) to check authorizations for subjects * they don't own - and only if there are no details passed (to avoid spoofing dialogs). - * - * TODO: allow other uids like 'haldaemon'? */ - if (!POLKIT_IS_UNIX_USER (user_of_caller) || - polkit_unix_user_get_uid (POLKIT_UNIX_USER (user_of_caller)) != 0) + + GList *l; + gboolean owned = FALSE; + + for (l = owners_of_action; l != NULL; l = g_list_next (l)) + { + if (polkit_identity_equal (user_of_caller, POLKIT_IDENTITY (l->data))) + { + owned = TRUE; + break; + } + } + + if (!owned) { if (has_details) { g_simple_async_result_set_error (simple, POLKIT_ERROR, POLKIT_ERROR_NOT_AUTHORIZED, - "Only trusted callers (e.g. uid 0) can use CheckAuthorization() and " + "Only trusted callers (e.g. uid 0 or an action owner) can use CheckAuthorization() and " "pass details"); } else @@ -874,7 +936,7 @@ polkit_backend_interactive_authority_check_authorization (PolkitBackendAuthority g_simple_async_result_set_error (simple, POLKIT_ERROR, POLKIT_ERROR_NOT_AUTHORIZED, - "Only trusted callers (e.g. uid 0) can use CheckAuthorization() for " + "Only trusted callers (e.g. uid 0 or an action owner) can use CheckAuthorization() for " "subjects belonging to other identities"); } g_simple_async_result_complete (simple); @@ -944,6 +1006,12 @@ polkit_backend_interactive_authority_check_authorization (PolkitBackendAuthority out: + g_list_foreach (owners_of_action, (GFunc) g_object_unref, NULL); + g_list_free (owners_of_action); + + if (action_desc != NULL) + g_object_unref (action_desc); + if (user_of_caller != NULL) g_object_unref (user_of_caller);