PolicyKit: Branch 'master'

David Zeuthen david at kemper.freedesktop.org
Wed Oct 31 20:25:41 PDT 2007


 polkit-dbus/polkit-dbus.c                          |   21 +-
 polkit-grant/polkit-authorization-db-dummy-write.c |   20 +-
 polkit-grant/polkit-authorization-db-write.c       |  161 +++++++++++----------
 polkit-grant/polkit-grant-helper.c                 |   49 +++++-
 polkit-grant/polkit-revoke-helper.c                |   50 ++++--
 polkit/polkit-authorization-db-dummy.c             |   12 +
 polkit/polkit-authorization-db.c                   |  104 +++++++++++++
 polkit/polkit-authorization-db.h                   |    6 
 polkit/polkit-authorization.c                      |   13 +
 polkit/polkit-authorization.h                      |    3 
 polkit/polkit-context.c                            |  154 +++++++++++---------
 polkit/polkit-context.h                            |    3 
 polkit/polkit-result.c                             |    2 
 polkit/polkit-result.h                             |   17 ++
 polkitd/org.freedesktop.PolicyKit.xml              |    8 -
 polkitd/polkit-daemon.c                            |   12 -
 polkitd/polkit-daemon.h                            |    4 
 tools/polkit-auth.c                                |   15 +
 18 files changed, 440 insertions(+), 214 deletions(-)

New commits:
commit 1b4fa91bb66135cf53d37117680cb2f23c3055ac
Author: David Zeuthen <davidz at redhat.com>
Date:   Wed Oct 31 23:23:33 2007 -0400

    introduce one-shot authorizations

diff --git a/polkit-dbus/polkit-dbus.c b/polkit-dbus/polkit-dbus.c
index 76ae4e6..9ead04a 100644
--- a/polkit-dbus/polkit-dbus.c
+++ b/polkit-dbus/polkit-dbus.c
@@ -812,6 +812,7 @@ _polkit_is_authorization_relevant_internal (DBusConnection *con,
         uid = polkit_authorization_get_uid (auth);
 
         switch (polkit_authorization_get_scope (auth)) {
+        case POLKIT_AUTHORIZATION_SCOPE_PROCESS_ONE_SHOT:
         case POLKIT_AUTHORIZATION_SCOPE_PROCESS:
                 if (!polkit_authorization_scope_process_get_pid (auth,
                                                                  &pid,
@@ -862,11 +863,11 @@ out:
  * @auth: authorization to check for
  * @error: return location for error
  *
- * As explicit authorizations are scoped (process, session or
- * everything), they become irrelevant once the entity (process or
- * session) ceases to exist. This function determines whether the
- * authorization is still relevant; it's useful for reporting
- * and graphical tools displaying authorizations.
+ * As explicit authorizations are scoped (process single shot,
+ * process, session or everything), they become irrelevant once the
+ * entity (process or session) ceases to exist. This function
+ * determines whether the authorization is still relevant; it's useful
+ * for reporting and graphical tools displaying authorizations.
  *
  * Note that this may do blocking IO to check for session
  * authorizations so it is best avoided if your process already
@@ -1455,11 +1456,11 @@ polkit_tracker_get_caller_from_pid (PolKitTracker *pk_tracker, pid_t pid, DBusEr
  * @auth: authorization to check for
  * @error: return location for error
  *
- * As explicit authorizations are scoped (process, session or
- * everything), they become irrelevant once the entity (process or
- * session) ceases to exist. This function determines whether the
- * authorization is still relevant; it's useful for reporting
- * and graphical tools displaying authorizations.
+ * As explicit authorizations are scoped (process single shot,
+ * process, session or everything), they become irrelevant once the
+ * entity (process or session) ceases to exist. This function
+ * determines whether the authorization is still relevant; it's useful
+ * for reporting and graphical tools displaying authorizations.
  *
  * This function is similar to polkit_is_authorization_relevant() only
  * that it avoids IPC overhead on the 2nd and subsequent calls when
diff --git a/polkit-grant/polkit-authorization-db-dummy-write.c b/polkit-grant/polkit-authorization-db-dummy-write.c
index 8f55c14..9852da1 100644
--- a/polkit-grant/polkit-authorization-db-dummy-write.c
+++ b/polkit-grant/polkit-authorization-db-dummy-write.c
@@ -49,6 +49,15 @@
 /* PolKitAuthorizationDB structure is defined in polkit/polkit-private.h */
 
 polkit_bool_t
+polkit_authorization_db_add_entry_process_one_shot (PolKitAuthorizationDB *authdb,
+                                                    PolKitAction          *action,
+                                                    PolKitCaller          *caller,
+                                                    uid_t                  user_authenticated_as)
+{
+        return FALSE;
+}
+
+polkit_bool_t
 polkit_authorization_db_add_entry_process          (PolKitAuthorizationDB *authdb,
                                                     PolKitAction          *action,
                                                     PolKitCaller          *caller,
@@ -85,14 +94,3 @@ polkit_authorization_db_grant_to_uid           (PolKitAuthorizationDB          *
         polkit_error_set_error (error, POLKIT_ERROR_NOT_SUPPORTED, "Not supported");
         return FALSE;
 }
-
-polkit_bool_t
-polkit_authorization_db_revoke_entry (PolKitAuthorizationDB *authdb,
-                                      PolKitAuthorization *auth,
-                                      PolKitError **error)
-{
-        polkit_error_set_error (error, POLKIT_ERROR_NOT_SUPPORTED, "Not supported");
-        return FALSE;
-}
-
-
diff --git a/polkit-grant/polkit-authorization-db-write.c b/polkit-grant/polkit-authorization-db-write.c
index 946759b..145aed9 100644
--- a/polkit-grant/polkit-authorization-db-write.c
+++ b/polkit-grant/polkit-authorization-db-write.c
@@ -202,6 +202,91 @@ out:
 
 
 /**
+ * polkit_authorization_db_add_entry_process_one_shot:
+ * @authdb: the authorization database
+ * @action: the action
+ * @caller: the caller
+ * @user_authenticated_as: the user that was authenticated
+ *
+ * Write an entry to the authorization database to indicate that the
+ * given caller is authorized for the given action a single time.
+ *
+ * Note that this function should only be used by
+ * <literal>libpolkit-grant</literal> or other sufficiently privileged
+ * processes that deals with managing authorizations. It should never
+ * be used by mechanisms or applications. The caller must have
+ * egid=polkituser and umask set so creating files with mode 0460 will
+ * work.
+ *
+ * This function is in <literal>libpolkit-grant</literal>.
+ *
+ * Returns: #TRUE if an entry was written to the authorization
+ * database, #FALSE if the caller of this function is not sufficiently
+ * privileged.
+ *
+ * Since: 0.7
+ */
+polkit_bool_t
+polkit_authorization_db_add_entry_process_one_shot (PolKitAuthorizationDB *authdb,
+                                                    PolKitAction          *action,
+                                                    PolKitCaller          *caller,
+                                                    uid_t                  user_authenticated_as)
+{
+        char *action_id;
+        uid_t caller_uid;
+        pid_t caller_pid;
+        char *grant_line;
+        polkit_bool_t ret;
+        polkit_uint64_t pid_start_time;
+        struct timeval now;
+        PolKitAuthorizationConstraint *constraint;
+        char cbuf[256];
+
+        g_return_val_if_fail (authdb != NULL, FALSE);
+        g_return_val_if_fail (action != NULL, FALSE);
+        g_return_val_if_fail (caller != NULL, FALSE);
+
+        if (!polkit_action_get_action_id (action, &action_id))
+                return FALSE;
+
+        if (!polkit_caller_get_pid (caller, &caller_pid))
+                return FALSE;
+
+        if (!polkit_caller_get_uid (caller, &caller_uid))
+                return FALSE;
+
+        pid_start_time = polkit_sysdeps_get_start_time_for_pid (caller_pid);
+        if (pid_start_time == 0)
+                return FALSE;
+
+        if (gettimeofday (&now, NULL) != 0) {
+                g_warning ("Error calling gettimeofday: %m");
+                return FALSE;
+        }
+
+        constraint = polkit_authorization_constraint_get_from_caller (caller);
+        if (polkit_authorization_constraint_to_string (constraint, cbuf, sizeof (cbuf)) >= sizeof (cbuf)) {
+                g_warning ("buffer for auth constraint is too small");
+                return FALSE;
+        }
+
+        grant_line = g_strdup_printf ("process-one-shot:%d:%Lu:%s:%Lu:%d:%s\n", 
+                                      caller_pid, 
+                                      pid_start_time, 
+                                      action_id,
+                                      (polkit_uint64_t) now.tv_sec,
+                                      user_authenticated_as,
+                                      cbuf);
+
+        ret = _polkit_authorization_db_auth_file_add (PACKAGE_LOCALSTATE_DIR "/run/PolicyKit", 
+                                                      TRUE, 
+                                                      caller_uid, 
+                                                      grant_line);
+        g_free (grant_line);
+        return ret;
+}
+
+/**
  * polkit_authorization_db_add_entry_process:
  * @authdb: the authorization database
  * @action: the action
@@ -444,82 +529,6 @@ polkit_authorization_db_add_entry_always           (PolKitAuthorizationDB *authd
         return ret;
 }
 
-/**
- * polkit_authorization_db_revoke_entry:
- * @authdb: the authorization database
- * @auth: the authorization to revoke
- * @error: return location for error
- *
- * Removes an authorization from the authorization database. This uses
- * a privileged helper /usr/libexec/polkit-revoke-helper.
- *
- * This function is in <literal>libpolkit-grant</literal>.
- *
- * Returns: #TRUE if the authorization was revoked, #FALSE otherwise and error is set
- *
- * Since: 0.7
- */
-polkit_bool_t
-polkit_authorization_db_revoke_entry (PolKitAuthorizationDB *authdb,
-                                      PolKitAuthorization   *auth,
-                                      PolKitError           **error)
-{
-        GError *g_error;
-        char *helper_argv[] = {PACKAGE_LIBEXEC_DIR "/polkit-revoke-helper", "", NULL, NULL, NULL};
-        const char *auth_file_entry;
-        gboolean ret;
-        gint exit_status;
-
-        ret = FALSE;
-
-        g_return_val_if_fail (authdb != NULL, FALSE);
-        g_return_val_if_fail (auth != NULL, FALSE);
-
-        auth_file_entry = _polkit_authorization_get_authfile_entry (auth);
-        //g_debug ("should delete line '%s'", auth_file_entry);
-
-        helper_argv[1] = (char *) auth_file_entry;
-        helper_argv[2] = "uid";
-        helper_argv[3] = g_strdup_printf ("%d", polkit_authorization_get_uid (auth));
-
-        g_error = NULL;
-        if (!g_spawn_sync (NULL,         /* const gchar *working_directory */
-                           helper_argv,  /* gchar **argv */
-                           NULL,         /* gchar **envp */
-                           0,            /* GSpawnFlags flags */
-                           NULL,         /* GSpawnChildSetupFunc child_setup */
-                           NULL,         /* gpointer user_data */
-                           NULL,         /* gchar **standard_output */
-                           NULL,         /* gchar **standard_error */
-                           &exit_status, /* gint *exit_status */
-                           &g_error)) {  /* GError **error */
-                polkit_error_set_error (error, 
-                                        POLKIT_ERROR_GENERAL_ERROR, 
-                                        "Error spawning revoke helper: %s",
-                                        g_error->message);
-                g_error_free (g_error);
-                goto out;
-        }
-
-        if (!WIFEXITED (exit_status)) {
-                g_warning ("Revoke helper crashed!");
-                polkit_error_set_error (error, 
-                                        POLKIT_ERROR_GENERAL_ERROR, 
-                                        "Revoke helper crashed!");
-                goto out;
-        } else if (WEXITSTATUS(exit_status) != 0) {
-                polkit_error_set_error (error, 
-                                        POLKIT_ERROR_NOT_AUTHORIZED_TO_REVOKE_AUTHORIZATIONS_FROM_OTHER_USERS, 
-                                        "uid %d is not authorized to revoke authorizations from uid %d (requires org.freedesktop.policykit.revoke)",
-                                        getuid (), polkit_authorization_get_uid (auth));
-        } else {
-                ret = TRUE;
-        }
-        
-out:
-        g_free (helper_argv[3]);
-        return ret;
-}
 
 typedef struct {
         char *action_id;
diff --git a/polkit-grant/polkit-grant-helper.c b/polkit-grant/polkit-grant-helper.c
index 43153f7..d1694b1 100644
--- a/polkit-grant/polkit-grant-helper.c
+++ b/polkit-grant/polkit-grant-helper.c
@@ -52,6 +52,7 @@
  */
 #undef PGH_DEBUG
 /* #define PGH_DEBUG */
+#define PGH_DEBUG
 
 /* synopsis: polkit-grant-helper <pid> <action-name>
  *
@@ -279,9 +280,11 @@ verify_with_polkit (PolKitContext *pol_ctx,
                 goto error;
         }
 
-        if (*out_result != POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH &&
+        if (*out_result != POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT &&
+            *out_result != POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH &&
             *out_result != POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION &&
             *out_result != POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS &&
+            *out_result != POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT &&
             *out_result != POLKIT_RESULT_ONLY_VIA_SELF_AUTH &&
             *out_result != POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION &&
             *out_result != POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS) {
@@ -295,7 +298,8 @@ verify_with_polkit (PolKitContext *pol_ctx,
         /* for admin auth, get a list of users that can be used - this is basically evaluating the
          * <define_admin_auth/> directives in the config file...
          */
-        if (*out_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH ||
+        if (*out_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT ||
+            *out_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH ||
             *out_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION ||
             *out_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS) {
                 PolKitConfig *pk_config;
@@ -436,33 +440,47 @@ get_and_validate_override_details (PolKitResult *result)
          * it comes down to this... users can only choose a more restricted granting type...
          */
         switch (*result) {
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT:
+                if (desired_result != POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT)
+                        goto error;
+                break;
         case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH:
-                if (desired_result != POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH)
+                if (desired_result != POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT &&
+                    desired_result != POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH)
                         goto error;
                 break;
         case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION:
-                if (desired_result != POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH &&
+                if (desired_result != POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT &&
+                    desired_result != POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH &&
                     desired_result != POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION)
                         goto error;
                 break;
         case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS:
-                if (desired_result != POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH &&
+                if (desired_result != POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT &&
+                    desired_result != POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH &&
                     desired_result != POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION &&
                     desired_result != POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS)
                         goto error;
                 break;
 
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT:
+                if (desired_result != POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT)
+                        goto error;
+                break;
         case POLKIT_RESULT_ONLY_VIA_SELF_AUTH:
-                if (desired_result != POLKIT_RESULT_ONLY_VIA_SELF_AUTH)
+                if (desired_result != POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT &&
+                    desired_result != POLKIT_RESULT_ONLY_VIA_SELF_AUTH)
                         goto error;
                 break;
         case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION:
-                if (desired_result != POLKIT_RESULT_ONLY_VIA_SELF_AUTH &&
+                if (desired_result != POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT &&
+                    desired_result != POLKIT_RESULT_ONLY_VIA_SELF_AUTH &&
                     desired_result != POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION)
                         goto error;
                 break;
         case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS:
-                if (desired_result != POLKIT_RESULT_ONLY_VIA_SELF_AUTH &&
+                if (desired_result != POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT &&
+                    desired_result != POLKIT_RESULT_ONLY_VIA_SELF_AUTH &&
                     desired_result != POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION &&
                     desired_result != POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS)
                         goto error;
@@ -700,7 +718,8 @@ main (int argc, char *argv[])
 
         } else {
                 /* figure out what user to auth */
-                if (result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH ||
+                if (result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT ||
+                    result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH ||
                     result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION ||
                     result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS) {
                         user_to_auth = "root";
@@ -755,6 +774,18 @@ main (int argc, char *argv[])
         umask (002);
 
         switch (result) {
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT:
+                dbres = polkit_authorization_db_add_entry_process_one_shot (polkit_context_get_authorization_db (context), 
+                                                                            action, 
+                                                                            caller,
+                                                                            uid_of_user_to_auth);
+                if (dbres) {
+                        syslog (LOG_INFO, "granted one shot authorization for %s to pid %d [uid=%d] [auth=%s]",
+                                action_name, caller_pid, invoking_user_id, user_to_auth);
+                }
+                break;
+
         case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH:
         case POLKIT_RESULT_ONLY_VIA_SELF_AUTH:
                 dbres = polkit_authorization_db_add_entry_process (polkit_context_get_authorization_db (context), 
diff --git a/polkit-grant/polkit-revoke-helper.c b/polkit-grant/polkit-revoke-helper.c
index 13d4b67..f588afc 100644
--- a/polkit-grant/polkit-revoke-helper.c
+++ b/polkit-grant/polkit-revoke-helper.c
@@ -46,7 +46,7 @@
 #include <polkit-dbus/polkit-dbus.h>
 
 static polkit_bool_t
-check_for_revoke_authorization (pid_t caller_pid)
+check_for_authorization (const char *action_id, pid_t caller_pid)
 {
         polkit_bool_t ret;
         DBusError error;
@@ -80,7 +80,7 @@ check_for_revoke_authorization (pid_t caller_pid)
                 fprintf (stderr, "polkit-revoke-helper: cannot allocate PolKitAction\n");
                 goto out;
         }
-        if (!polkit_action_set_action_id (action, "org.freedesktop.policykit.revoke")) {
+        if (!polkit_action_set_action_id (action, action_id)) {
                 fprintf (stderr, "polkit-revoke-helper: cannot set action_id\n");
                 goto out;
         }
@@ -171,6 +171,7 @@ main (int argc, char *argv[])
         char *target_type;
         char *target_value;
         struct passwd *pw;
+        polkit_bool_t is_one_shot;
 
         ret = 1;
 
@@ -252,6 +253,23 @@ found:
 
         /* OK, we're done parsing ... */
 
+        is_one_shot = FALSE;
+        if (strcmp (scope, "process") == 0) {
+                root = PACKAGE_LOCALSTATE_DIR "/run/PolicyKit";
+        } else if (strcmp (scope, "process-one-shot") == 0) {
+                root = PACKAGE_LOCALSTATE_DIR "/run/PolicyKit";
+                is_one_shot = TRUE;
+        } else if (strcmp (scope, "session") == 0) {
+                root = PACKAGE_LOCALSTATE_DIR "/run/PolicyKit";
+        } else if (strcmp (scope, "always") == 0) {
+                root = PACKAGE_LOCALSTATE_DIR "/lib/PolicyKit";
+        } else if (strcmp (scope, "grant") == 0) {
+                root = PACKAGE_LOCALSTATE_DIR "/lib/PolicyKit";
+        } else {
+                fprintf (stderr, "polkit-revoke-helper: unknown scope '%s'\n", scope);
+                goto out;
+        }
+
         if (invoking_uid != 0) {
                 /* Check that the caller is privileged to do this... */
                 if (invoking_uid != uid_to_revoke) {
@@ -262,25 +280,23 @@ found:
                          *
                          * authorization
                          */
-                        if (!check_for_revoke_authorization (getppid ())) {
-                                goto out;
+                        if (!check_for_authorization ("org.freedesktop.policykit.revoke", getppid ())) {
+
+                                /* if it's about revoking a one-shot authorization, it's sufficient to have
+                                 * org.freedesktop.policykit.read - see polkit_context_is_caller_authorized()
+                                 * for why...
+                                 */
+                                if (is_one_shot) {
+                                        if (!check_for_authorization ("org.freedesktop.policykit.read", getppid ())) {
+                                                goto out;
+                                        }
+                                } else {
+                                        goto out;
+                                }
                         }
                 }
         }
 
-        if (strcmp (scope, "process") == 0) {
-                root = PACKAGE_LOCALSTATE_DIR "/run/PolicyKit";
-        } else if (strcmp (scope, "session") == 0) {
-                root = PACKAGE_LOCALSTATE_DIR "/run/PolicyKit";
-        } else if (strcmp (scope, "always") == 0) {
-                root = PACKAGE_LOCALSTATE_DIR "/lib/PolicyKit";
-        } else if (strcmp (scope, "grant") == 0) {
-                root = PACKAGE_LOCALSTATE_DIR "/lib/PolicyKit";
-        } else {
-                fprintf (stderr, "polkit-revoke-helper: unknown scope '%s'\n", scope);
-                goto out;
-        }
-
         pw = getpwuid (uid_to_revoke);
         if (pw == NULL) {
                 fprintf (stderr, "polkit-revoke-helper: cannot lookup user name for uid %d\n", uid_to_revoke);
diff --git a/polkit/polkit-authorization-db-dummy.c b/polkit/polkit-authorization-db-dummy.c
index 8936605..64eecb0 100644
--- a/polkit/polkit-authorization-db-dummy.c
+++ b/polkit/polkit-authorization-db-dummy.c
@@ -131,6 +131,7 @@ polkit_bool_t
 polkit_authorization_db_is_caller_authorized (PolKitAuthorizationDB *authdb,
                                               PolKitAction          *action,
                                               PolKitCaller          *caller,
+                                              polkit_bool_t          revoke_if_one_shot,
                                               polkit_bool_t         *out_is_authorized)
 {
         *out_is_authorized = FALSE;
@@ -177,3 +178,14 @@ polkit_authorization_db_foreach_for_action_for_uid (PolKitAuthorizationDB
 {
         return FALSE;
 }
+
+polkit_bool_t
+polkit_authorization_db_revoke_entry (PolKitAuthorizationDB *authdb,
+                                      PolKitAuthorization *auth,
+                                      PolKitError **error)
+{
+        polkit_error_set_error (error, POLKIT_ERROR_NOT_SUPPORTED, "Not supported");
+        return FALSE;
+}
+
+
diff --git a/polkit/polkit-authorization-db.c b/polkit/polkit-authorization-db.c
index 055c64a..edccfc6 100644
--- a/polkit/polkit-authorization-db.c
+++ b/polkit/polkit-authorization-db.c
@@ -551,6 +551,7 @@ _check_auth_for_session (PolKitAuthorizationDB *authdb, PolKitAuthorization *aut
 
         switch (polkit_authorization_get_scope (auth))
         {
+        case POLKIT_AUTHORIZATION_SCOPE_PROCESS_ONE_SHOT:
         case POLKIT_AUTHORIZATION_SCOPE_PROCESS:
                 goto no_match;
 
@@ -576,9 +577,8 @@ no_match:
  * @session: the session to check for
  * @out_is_authorized: return location
  *
- * Looks in the authorization database and determine if a processes
- * from the given session are authorized to do the given specific
- * action.
+ * Looks in the authorization database and determine if processes from
+ * the given session are authorized to do the given specific action.
  *
  * Returns: #TRUE if the look up was performed; #FALSE if the caller
  * of this function lacks privileges to ask this question (e.g. asking
@@ -634,16 +634,19 @@ typedef struct {
         polkit_uint64_t caller_pid_start_time;
         char *session_objpath;
         PolKitCaller *caller;
+        polkit_bool_t revoke_if_one_shot;
 } CheckData;
 
 static polkit_bool_t 
 _check_auth_for_caller (PolKitAuthorizationDB *authdb, PolKitAuthorization *auth, void *user_data)
 {
+
         gboolean ret;
         pid_t caller_pid;
         polkit_uint64_t caller_pid_start_time;
         CheckData *cd = (CheckData *) user_data;
         PolKitAuthorizationConstraint *constraint;
+        PolKitError *error;
 
         ret = FALSE;
 
@@ -656,11 +659,26 @@ _check_auth_for_caller (PolKitAuthorizationDB *authdb, PolKitAuthorization *auth
 
         switch (polkit_authorization_get_scope (auth))
         {
+        case POLKIT_AUTHORIZATION_SCOPE_PROCESS_ONE_SHOT:
         case POLKIT_AUTHORIZATION_SCOPE_PROCESS:
                 if (!polkit_authorization_scope_process_get_pid (auth, &caller_pid, &caller_pid_start_time))
                         goto no_match;
                 if (!(caller_pid == cd->caller_pid && caller_pid_start_time == cd->caller_pid_start_time))
                         goto no_match;
+
+                if (polkit_authorization_get_scope (auth) == POLKIT_AUTHORIZATION_SCOPE_PROCESS_ONE_SHOT) {
+
+                        /* it's a match already; revoke if asked to do so */
+                        if (cd->revoke_if_one_shot) {
+                                error = NULL;
+                                if (!polkit_authorization_db_revoke_entry (authdb, auth, &error)) {
+                                        g_warning ("Cannot revoke one-shot auth: %s: %s", 
+                                                   polkit_error_get_error_name (error),
+                                                   polkit_error_get_error_message (error));
+                                        polkit_error_free (error);
+                                }
+                        }
+                }
                 break;
 
         case POLKIT_AUTHORIZATION_SCOPE_SESSION:
@@ -676,6 +694,7 @@ _check_auth_for_caller (PolKitAuthorizationDB *authdb, PolKitAuthorization *auth
 
         ret = TRUE;
 
+
 no_match:
         return ret;
 }
@@ -685,6 +704,8 @@ no_match:
  * @authdb: the authorization database
  * @action: the action to check for
  * @caller: the caller to check for
+ * @revoke_if_one_shot: Whether to revoke one-shot authorizations. See
+ * discussion in polkit_context_is_caller_authorized() for details.
  * @out_is_authorized: return location
  *
  * Looks in the authorization database if the given caller is
@@ -700,6 +721,7 @@ polkit_bool_t
 polkit_authorization_db_is_caller_authorized (PolKitAuthorizationDB *authdb,
                                               PolKitAction          *action,
                                               PolKitCaller          *caller,
+                                              polkit_bool_t          revoke_if_one_shot,
                                               polkit_bool_t         *out_is_authorized)
 {
         PolKitSession *session;
@@ -723,6 +745,7 @@ polkit_authorization_db_is_caller_authorized (PolKitAuthorizationDB *authdb,
                 return FALSE;
 
         cd.caller = caller;
+        cd.revoke_if_one_shot = revoke_if_one_shot;
 
         cd.caller_pid_start_time = polkit_sysdeps_get_start_time_for_pid (cd.caller_pid);
         if (cd.caller_pid_start_time == 0)
@@ -748,3 +771,78 @@ polkit_authorization_db_is_caller_authorized (PolKitAuthorizationDB *authdb,
 
         return ret;
 }
+
+/**
+ * polkit_authorization_db_revoke_entry:
+ * @authdb: the authorization database
+ * @auth: the authorization to revoke
+ * @error: return location for error
+ *
+ * Removes an authorization from the authorization database. This uses
+ * a privileged helper /usr/libexec/polkit-revoke-helper.
+ *
+ * Returns: #TRUE if the authorization was revoked, #FALSE otherwise and error is set
+ *
+ * Since: 0.7
+ */
+polkit_bool_t
+polkit_authorization_db_revoke_entry (PolKitAuthorizationDB *authdb,
+                                      PolKitAuthorization   *auth,
+                                      PolKitError           **error)
+{
+        GError *g_error;
+        char *helper_argv[] = {PACKAGE_LIBEXEC_DIR "/polkit-revoke-helper", "", NULL, NULL, NULL};
+        const char *auth_file_entry;
+        gboolean ret;
+        gint exit_status;
+
+        ret = FALSE;
+
+        g_return_val_if_fail (authdb != NULL, FALSE);
+        g_return_val_if_fail (auth != NULL, FALSE);
+
+        auth_file_entry = _polkit_authorization_get_authfile_entry (auth);
+        //g_debug ("should delete line '%s'", auth_file_entry);
+
+        helper_argv[1] = (char *) auth_file_entry;
+        helper_argv[2] = "uid";
+        helper_argv[3] = g_strdup_printf ("%d", polkit_authorization_get_uid (auth));
+
+        g_error = NULL;
+        if (!g_spawn_sync (NULL,         /* const gchar *working_directory */
+                           helper_argv,  /* gchar **argv */
+                           NULL,         /* gchar **envp */
+                           0,            /* GSpawnFlags flags */
+                           NULL,         /* GSpawnChildSetupFunc child_setup */
+                           NULL,         /* gpointer user_data */
+                           NULL,         /* gchar **standard_output */
+                           NULL,         /* gchar **standard_error */
+                           &exit_status, /* gint *exit_status */
+                           &g_error)) {  /* GError **error */
+                polkit_error_set_error (error, 
+                                        POLKIT_ERROR_GENERAL_ERROR, 
+                                        "Error spawning revoke helper: %s",
+                                        g_error->message);
+                g_error_free (g_error);
+                goto out;
+        }
+
+        if (!WIFEXITED (exit_status)) {
+                g_warning ("Revoke helper crashed!");
+                polkit_error_set_error (error, 
+                                        POLKIT_ERROR_GENERAL_ERROR, 
+                                        "Revoke helper crashed!");
+                goto out;
+        } else if (WEXITSTATUS(exit_status) != 0) {
+                polkit_error_set_error (error, 
+                                        POLKIT_ERROR_NOT_AUTHORIZED_TO_REVOKE_AUTHORIZATIONS_FROM_OTHER_USERS, 
+                                        "uid %d is not authorized to revoke authorizations from uid %d (requires org.freedesktop.policykit.revoke)",
+                                        getuid (), polkit_authorization_get_uid (auth));
+        } else {
+                ret = TRUE;
+        }
+        
+out:
+        g_free (helper_argv[3]);
+        return ret;
+}
diff --git a/polkit/polkit-authorization-db.h b/polkit/polkit-authorization-db.h
index 2434015..8089bd4 100644
--- a/polkit/polkit-authorization-db.h
+++ b/polkit/polkit-authorization-db.h
@@ -73,6 +73,7 @@ polkit_bool_t polkit_authorization_db_is_session_authorized (PolKitAuthorization
 polkit_bool_t polkit_authorization_db_is_caller_authorized (PolKitAuthorizationDB *authdb,
                                                             PolKitAction          *action,
                                                             PolKitCaller          *caller,
+                                                            polkit_bool_t          revoke_if_one_shot,
                                                             polkit_bool_t         *out_is_authorized);
 
 /**
@@ -117,6 +118,11 @@ polkit_bool_t polkit_authorization_db_foreach_for_action_for_uid (PolKitAuthoriz
                                                                   void                        *user_data,
                                                                   PolKitError                **error);
 
+polkit_bool_t polkit_authorization_db_add_entry_process_one_shot (PolKitAuthorizationDB *authdb,
+                                                                  PolKitAction          *action,
+                                                                  PolKitCaller          *caller,
+                                                                  uid_t                  user_authenticated_as);
+
 polkit_bool_t polkit_authorization_db_add_entry_process          (PolKitAuthorizationDB *authdb,
                                                                   PolKitAction          *action,
                                                                   PolKitCaller          *caller,
diff --git a/polkit/polkit-authorization.c b/polkit/polkit-authorization.c
index 733e1a0..660183a 100644
--- a/polkit/polkit-authorization.c
+++ b/polkit/polkit-authorization.c
@@ -125,11 +125,15 @@ _polkit_authorization_new_for_uid (const char *entry_in_auth_file, uid_t uid)
  */
         n = 1;
 
-        if (strcmp (t[0], "process") == 0) {
+        if (strcmp (t[0], "process") == 0 ||
+            strcmp (t[0], "process-one-shot") == 0) {
                 if (num_t != 7)
                         goto error;
 
-                auth->scope = POLKIT_AUTHORIZATION_SCOPE_PROCESS;
+                if (strcmp (t[0], "process") == 0)
+                        auth->scope = POLKIT_AUTHORIZATION_SCOPE_PROCESS;
+                else
+                        auth->scope = POLKIT_AUTHORIZATION_SCOPE_PROCESS_ONE_SHOT;
 
                 auth->pid = strtoul (t[n++], &ep, 10);
                 if (*ep != '\0')
@@ -416,7 +420,8 @@ polkit_authorization_scope_process_get_pid (PolKitAuthorization *auth,
         g_return_val_if_fail (auth != NULL, FALSE);
         g_return_val_if_fail (out_pid != NULL, FALSE);
         g_return_val_if_fail (out_pid_start_time != NULL, FALSE);
-        g_return_val_if_fail (auth->scope == POLKIT_AUTHORIZATION_SCOPE_PROCESS, FALSE);
+        g_return_val_if_fail (auth->scope == POLKIT_AUTHORIZATION_SCOPE_PROCESS || 
+                              auth->scope == POLKIT_AUTHORIZATION_SCOPE_PROCESS_ONE_SHOT, FALSE);
 
         *out_pid = auth->pid;
         *out_pid_start_time = auth->pid_start_time;
@@ -470,7 +475,7 @@ polkit_authorization_get_uid (PolKitAuthorization *auth)
  * is UNIX time, e.g. number of seconds since the Epoch Jan 1, 1970
  * 0:00 UTC.
  *
- * Returns: #TRUE if information was returned
+ * Returns: When authorization was granted
  *
  * Since: 0.7
  */ 
diff --git a/polkit/polkit-authorization.h b/polkit/polkit-authorization.h
index 4f6fe70..0e107be 100644
--- a/polkit/polkit-authorization.h
+++ b/polkit/polkit-authorization.h
@@ -50,6 +50,8 @@ polkit_bool_t        polkit_authorization_validate       (PolKitAuthorization *a
 
 /**
  * PolKitAuthorizationScope:
+ * @POLKIT_AUTHORIZATION_SCOPE_PROCESS_ONE_SHOT: The authorization is
+ * limited for a single shot for a single process on the system
  * @POLKIT_AUTHORIZATION_SCOPE_PROCESS: The authorization is limited
  * for a single process on the system
  * @POLKIT_AUTHORIZATION_SCOPE_SESSION: The authorization is limited
@@ -61,6 +63,7 @@ polkit_bool_t        polkit_authorization_validate       (PolKitAuthorization *a
  * process, a session or unlimited.
  */
 typedef enum {
+        POLKIT_AUTHORIZATION_SCOPE_PROCESS_ONE_SHOT,
         POLKIT_AUTHORIZATION_SCOPE_PROCESS,
         POLKIT_AUTHORIZATION_SCOPE_SESSION,
         POLKIT_AUTHORIZATION_SCOPE_ALWAYS,
diff --git a/polkit/polkit-context.c b/polkit/polkit-context.c
index d506c8d..1f25d58 100644
--- a/polkit/polkit-context.c
+++ b/polkit/polkit-context.c
@@ -426,8 +426,6 @@ polkit_context_get_policy_cache (PolKitContext *pk_context)
  * @pk_context: the PolicyKit context
  * @action: the type of access to check for
  * @session: the session in question
- * @is_mechanism: Whether the mechanism carrying out the action is
- * asking. This can be used to revoke one-time-only authorizations.
  * @error: return location for error
  *
  * Determine if any caller from a giver session is authorized to do a
@@ -442,65 +440,8 @@ PolKitResult
 polkit_context_is_session_authorized (PolKitContext         *pk_context,
                                       PolKitAction          *action,
                                       PolKitSession         *session,
-                                      polkit_bool_t          is_mechanism,
                                       PolKitError          **error)
 {
-        /* TODO: properly implement */
-        return polkit_context_can_session_do_action (pk_context, action, session);
-}
-
-/**
- * polkit_context_is_caller_authorized:
- * @pk_context: the PolicyKit context
- * @action: the type of access to check for
- * @caller: the caller in question
- * @is_mechanism: Whether the mechanism carrying out the action is
- * asking. This can be used to revoke one-time-only authorizations.
- * @error: return location for error
- *
- * Determine if a given caller is authorized to do a given
- * action. 
- *
- * This can fail with the following errors: 
- * #POLKIT_ERROR_NOT_AUTHORIZED_TO_READ_AUTHORIZATIONS_FOR_OTHER_USERS
- *
- * Returns: A #PolKitResult specifying if, and how, the caller can
- * do a specific action. 
- *
- * Since: 0.7
- */
-PolKitResult
-polkit_context_is_caller_authorized (PolKitContext         *pk_context,
-                                     PolKitAction          *action,
-                                     PolKitCaller          *caller,
-                                     polkit_bool_t          is_mechnanism,
-                                     PolKitError          **error)
-{
-        /* TODO: properly implement */
-        return polkit_context_can_caller_do_action (pk_context, action, caller);
-}
-
-/**
- * polkit_context_can_session_do_action:
- * @pk_context: the PolicyKit context
- * @action: the type of access to check for
- * @session: the session in question
- *
- * Determine if a given session can do a given action.
- *
- * This can fail with the following errors: 
- * #POLKIT_ERROR_NOT_AUTHORIZED_TO_READ_AUTHORIZATIONS_FOR_OTHER_USERS
- *
- * Returns: A #PolKitResult - can only be one of
- * #POLKIT_RESULT_YES, #POLKIT_RESULT_NO.
- *
- * Deprecated: 0.7: use polkit_context_is_session_authorized() instead.
- */
-PolKitResult
-polkit_context_can_session_do_action (PolKitContext   *pk_context,
-                                      PolKitAction    *action,
-                                      PolKitSession   *session)
-{
         PolKitPolicyCache *cache;
         PolKitPolicyFileEntry *pfe;
         PolKitPolicyDefault *policy_default;
@@ -566,9 +507,11 @@ polkit_context_can_session_do_action (PolKitContext   *pk_context,
          */
         if (result_from_config != POLKIT_RESULT_UNKNOWN) {
                 /* it does.. use it.. although try to use an existing grant if there is one */
-                if ((result_from_config == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH ||
+                if ((result_from_config == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT ||
+                     result_from_config == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH ||
                      result_from_config == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION ||
                      result_from_config == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS ||
+                     result_from_config == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT ||
                      result_from_config == POLKIT_RESULT_ONLY_VIA_SELF_AUTH ||
                      result_from_config == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION ||
                      result_from_config == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS) &&
@@ -605,23 +548,50 @@ out:
 }
 
 /**
- * polkit_context_can_caller_do_action:
+ * polkit_context_is_caller_authorized:
  * @pk_context: the PolicyKit context
  * @action: the type of access to check for
  * @caller: the caller in question
+ * @revoke_if_one_shot: Whether to revoke one-shot authorizations. See
+ * below for discussion.
+ * @error: return location for error
  *
- * Determine if a given caller can do a given action.
+ * Determine if a given caller is authorized to do a given
+ * action. 
+ *
+ * It is important to understand how one-shot authorizations work.
+ * The revoke_if_one_shot parameter, if #TRUE, specifies whether
+ * one-shot authorizations should be revoked if they are used
+ * to make the decision to return #POLKIT_RESULT_YES.
+ *
+ * UI applications wanting to hint whether a caller is authorized must
+ * pass #FALSE here. Mechanisms that wants to check authorizations
+ * before carrying out work on behalf of a caller must pass #TRUE
+ * here.
+ *
+ * As a side-effect, any process with the authorization
+ * org.freedesktop.policykit.read can revoke one-shot authorizations
+ * from other users. Even though the window for doing so is small
+ * (one-shot auths are typically used right away), be careful who you
+ * grant that authorization to.
+ *
+ * This can fail with the following errors: 
+ * #POLKIT_ERROR_NOT_AUTHORIZED_TO_READ_AUTHORIZATIONS_FOR_OTHER_USERS
  *
  * Returns: A #PolKitResult specifying if, and how, the caller can
- * do a specific action
+ * do a specific action. 
  *
- * Deprecated: 0.7: use polkit_context_is_caller_authorized() instead.
+ * Since: 0.7
  */
 PolKitResult
-polkit_context_can_caller_do_action (PolKitContext   *pk_context,
-                                     PolKitAction    *action,
-                                     PolKitCaller    *caller)
+polkit_context_is_caller_authorized (PolKitContext         *pk_context,
+                                     PolKitAction          *action,
+                                     PolKitCaller          *caller,
+                                     polkit_bool_t          revoke_if_one_shot,
+                                     PolKitError          **error)
 {
+
+
         PolKitPolicyCache *cache;
         PolKitPolicyFileEntry *pfe;
         PolKitResult result;
@@ -676,6 +646,7 @@ polkit_context_can_caller_do_action (PolKitContext   *pk_context,
         if (polkit_authorization_db_is_caller_authorized (pk_context->authdb, 
                                                           action, 
                                                           caller,
+                                                          revoke_if_one_shot,
                                                           &from_authdb)) {
                 if (from_authdb)
                         result_from_grantdb = POLKIT_RESULT_YES;
@@ -687,9 +658,11 @@ polkit_context_can_caller_do_action (PolKitContext   *pk_context,
          */
         if (result_from_config != POLKIT_RESULT_UNKNOWN) {
                 /* it does.. use it.. although try to use an existing grant if there is one */
-                if ((result_from_config == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH ||
+                if ((result_from_config == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT ||
+                     result_from_config == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH ||
                      result_from_config == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION ||
                      result_from_config == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS ||
+                     result_from_config == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT ||
                      result_from_config == POLKIT_RESULT_ONLY_VIA_SELF_AUTH ||
                      result_from_config == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION ||
                      result_from_config == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS) &&
@@ -726,6 +699,51 @@ out:
 }
 
 /**
+ * polkit_context_can_session_do_action:
+ * @pk_context: the PolicyKit context
+ * @action: the type of access to check for
+ * @session: the session in question
+ *
+ * Determine if a given session can do a given action.
+ *
+ * This can fail with the following errors: 
+ * #POLKIT_ERROR_NOT_AUTHORIZED_TO_READ_AUTHORIZATIONS_FOR_OTHER_USERS
+ *
+ * Returns: A #PolKitResult - can only be one of
+ * #POLKIT_RESULT_YES, #POLKIT_RESULT_NO.
+ *
+ * Deprecated: 0.7: use polkit_context_is_session_authorized() instead.
+ */
+PolKitResult
+polkit_context_can_session_do_action (PolKitContext   *pk_context,
+                                      PolKitAction    *action,
+                                      PolKitSession   *session)
+{
+        return polkit_context_is_session_authorized (pk_context, action, session, NULL);
+}
+
+/**
+ * polkit_context_can_caller_do_action:
+ * @pk_context: the PolicyKit context
+ * @action: the type of access to check for
+ * @caller: the caller in question
+ *
+ * Determine if a given caller can do a given action.
+ *
+ * Returns: A #PolKitResult specifying if, and how, the caller can
+ * do a specific action
+ *
+ * Deprecated: 0.7: use polkit_context_is_caller_authorized() instead.
+ */
+PolKitResult
+polkit_context_can_caller_do_action (PolKitContext   *pk_context,
+                                     PolKitAction    *action,
+                                     PolKitCaller    *caller)
+{
+        return polkit_context_is_caller_authorized (pk_context, action, caller, TRUE, NULL);
+}
+
+/**
  * polkit_context_get_config:
  * @pk_context: the PolicyKit context
  * @error: Return location for error
diff --git a/polkit/polkit-context.h b/polkit/polkit-context.h
index 165ad50..72e4ad8 100644
--- a/polkit/polkit-context.h
+++ b/polkit/polkit-context.h
@@ -173,13 +173,12 @@ PolKitConfig *polkit_context_get_config (PolKitContext *pk_context, PolKitError
 PolKitResult polkit_context_is_caller_authorized (PolKitContext         *pk_context,
                                                   PolKitAction          *action,
                                                   PolKitCaller          *caller,
-                                                  polkit_bool_t          is_mechanism,
+                                                  polkit_bool_t          revoke_if_one_shot,
                                                   PolKitError          **error);
 
 PolKitResult polkit_context_is_session_authorized (PolKitContext         *pk_context,
                                                    PolKitAction          *action,
                                                    PolKitSession         *session,
-                                                   polkit_bool_t          is_mechanism,
                                                    PolKitError          **error);
 
 PolKitAuthorizationDB *polkit_context_get_authorization_db (PolKitContext *pk_context);
diff --git a/polkit/polkit-result.c b/polkit/polkit-result.c
index 15e674e..bd12020 100644
--- a/polkit/polkit-result.c
+++ b/polkit/polkit-result.c
@@ -62,6 +62,8 @@ static const struct {
         {POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION, "auth_self_keep_session"},
         {POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS, "auth_self_keep_always"},
         {POLKIT_RESULT_YES, "yes"},
+        {POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT, "auth_admin_one_shot"},
+        {POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT, "auth_self_one_shot"},
         {0, NULL}
 };
 
diff --git a/polkit/polkit-result.h b/polkit/polkit-result.h
index 3ebd17d..17b45df 100644
--- a/polkit/polkit-result.h
+++ b/polkit/polkit-result.h
@@ -39,6 +39,12 @@ POLKIT_BEGIN_DECLS
  * @POLKIT_RESULT_UNKNOWN: The result is unknown / cannot be
  * computed. This is mostly used internally in libpolkit.
  * @POLKIT_RESULT_NO: Access denied.
+ * @POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT: Access denied, but
+ * authentication by the caller as administrator (e.g. root or a
+ * member in the wheel group depending on configuration) will grant
+ * access exactly one time to the process the caller is originating
+ * from. See polkit_context_is_caller_authorized() for discussion (and
+ * limitations) about one-shot authorizations.
  * @POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH: Access denied, but
  * authentication by the caller as administrator (e.g. root or a
  * member in the wheel group depending on configuration) will grant
@@ -51,6 +57,11 @@ POLKIT_BEGIN_DECLS
  * authentication by the caller as administrator (e.g. root or a
  * member in the wheel group depending on configuration) will grant
  * access in the future.
+ * @POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT: Access denied, but
+ * authentication by the caller as himself will grant access exactly
+ * one time to the process the caller is originating from. See
+ * polkit_context_is_caller_authorized() for discussion (and
+ * limitations) about one-shot authorizations.
  * @POLKIT_RESULT_ONLY_VIA_SELF_AUTH: Access denied, but
  * authentication by the caller as himself will grant access to the
  * process the caller is originating from.
@@ -64,7 +75,7 @@ POLKIT_BEGIN_DECLS
  * @POLKIT_RESULT_N_RESULTS: Number of result codes
  *
  * Result codes from queries to PolicyKit. This enumeration may grow
- * in the future.
+ * in the future. One should never rely on the ordering
  */
 typedef enum
 {
@@ -81,6 +92,10 @@ typedef enum
         POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS,
 
         POLKIT_RESULT_YES,
+
+        POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT,
+        POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT,
+
         POLKIT_RESULT_N_RESULTS
 } PolKitResult;
 
diff --git a/polkitd/org.freedesktop.PolicyKit.xml b/polkitd/org.freedesktop.PolicyKit.xml
index 7202913..4539043 100644
--- a/polkitd/org.freedesktop.PolicyKit.xml
+++ b/polkitd/org.freedesktop.PolicyKit.xml
@@ -9,8 +9,8 @@
       <arg name="action_id" direction="in" type="s"/>
       <!-- IN: process id of caller to check for -->
       <arg name="pid" direction="in" type="u"/>
-      <!-- IN: see parameter 'is_mechanism' in polkit_context_is_caller_authorized()  -->
-      <arg name="is_mechanism" direction="in" type="b"/>
+      <!-- IN: see parameter 'revoke_if_one_shot' in polkit_context_is_caller_authorized()  -->
+      <arg name="revoke_if_one_shot" direction="in" type="b"/>
 
       <!-- OUT: the PolKitResult in textual form -->
       <arg name="result" direction="out" type="s"/>
@@ -22,8 +22,8 @@
       <arg name="action_id" direction="in" type="s"/>
       <!-- IN: Unique name on the system bus of the caller to check for -->
       <arg name="system_bus_name" direction="in" type="s"/>
-      <!-- IN: see parameter 'is_mechanism' in polkit_context_is_caller_authorized()  -->
-      <arg name="is_mechanism" direction="in" type="b"/>
+      <!-- IN: see parameter 'revoke_if_one_shot' in polkit_context_is_caller_authorized()  -->
+      <arg name="revoke_if_one_shot" direction="in" type="b"/>
       <!-- OUT: the PolKitResult in textual form -->
       <arg name="result" direction="out" type="s"/>
     </method>
diff --git a/polkitd/polkit-daemon.c b/polkitd/polkit-daemon.c
index 9a74246..d5f4386 100644
--- a/polkitd/polkit-daemon.c
+++ b/polkitd/polkit-daemon.c
@@ -381,7 +381,7 @@ static gboolean
 is_caller_authorized (PolKitDaemon          *daemon, 
                       const char            *action_id, 
                       PolKitCaller          *pk_caller, 
-                      gboolean               is_mechanism,
+                      gboolean               revoke_if_one_shot,
                       DBusGMethodInvocation *context)
 {
         gboolean ret;
@@ -436,7 +436,7 @@ is_caller_authorized (PolKitDaemon          *daemon,
         pk_result = polkit_context_is_caller_authorized (daemon->priv->pk_context, 
                                                          pk_action, 
                                                          pk_caller, 
-                                                         is_mechanism,
+                                                         revoke_if_one_shot,
                                                          NULL);
         polkit_action_unref (pk_action);
 
@@ -456,7 +456,7 @@ gboolean
 polkit_daemon_is_process_authorized (PolKitDaemon          *daemon,
                                      const char            *action_id, 
                                      guint32                pid,
-                                     gboolean               is_mechanism,
+                                     gboolean               revoke_if_one_shot,
                                      DBusGMethodInvocation *context)
 {
         gboolean ret;
@@ -483,7 +483,7 @@ polkit_daemon_is_process_authorized (PolKitDaemon          *daemon,
                 goto out;
         }
 
-        ret = is_caller_authorized (daemon, action_id, pk_caller, is_mechanism, context);
+        ret = is_caller_authorized (daemon, action_id, pk_caller, revoke_if_one_shot, context);
 
 out:
         return ret;
@@ -493,7 +493,7 @@ gboolean
 polkit_daemon_is_system_bus_name_authorized (PolKitDaemon          *daemon,
                                              const char            *action_id, 
                                              const char            *system_bus_name,
-                                             gboolean               is_mechanism,
+                                             gboolean               revoke_if_one_shot,
                                              DBusGMethodInvocation *context)
 {
         gboolean ret;
@@ -529,7 +529,7 @@ polkit_daemon_is_system_bus_name_authorized (PolKitDaemon          *daemon,
                 goto out;
         }
 
-        ret = is_caller_authorized (daemon, action_id, pk_caller, is_mechanism, context);
+        ret = is_caller_authorized (daemon, action_id, pk_caller, revoke_if_one_shot, context);
 
 out:
         return ret;
diff --git a/polkitd/polkit-daemon.h b/polkitd/polkit-daemon.h
index 402156f..d3f73bc 100644
--- a/polkitd/polkit-daemon.h
+++ b/polkitd/polkit-daemon.h
@@ -67,13 +67,13 @@ PolKitDaemon *polkit_daemon_new                 (gboolean no_exit);
 gboolean polkit_daemon_is_process_authorized         (PolKitDaemon          *daemon,
                                                       const char            *action_id, 
                                                       guint32                pid,
-                                                      gboolean               is_mechanism,
+                                                      gboolean               revoke_if_one_shot,
                                                       DBusGMethodInvocation *context);
 
 gboolean polkit_daemon_is_system_bus_name_authorized (PolKitDaemon          *daemon,
                                                       const char            *action_id, 
                                                       const char            *system_bus_name,
-                                                      gboolean               is_mechanism,
+                                                      gboolean               revoke_if_one_shot,
                                                       DBusGMethodInvocation *context);
 
 G_END_DECLS
diff --git a/tools/polkit-auth.c b/tools/polkit-auth.c
index 65d2d28..dd6f285 100644
--- a/tools/polkit-auth.c
+++ b/tools/polkit-auth.c
@@ -67,12 +67,14 @@ static void
 conversation_type (PolKitGrant *polkit_grant, PolKitResult auth_type, void *user_data)
 {
         switch (auth_type) {
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT:
         case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH:
         case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION:
         case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS:
                 printf ("Authentication as an administrative user is required.\n");
                 break;
 
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT:
         case POLKIT_RESULT_ONLY_VIA_SELF_AUTH:
         case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION:
         case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS:
@@ -172,6 +174,8 @@ conversation_override_grant_type (PolKitGrant *polkit_grant, PolKitResult auth_t
         PolKitResult overridden_auth_type;
 
         switch (auth_type) {
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT:
         case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH:
         case POLKIT_RESULT_ONLY_VIA_SELF_AUTH:
                 break;
@@ -213,6 +217,7 @@ conversation_override_grant_type (PolKitGrant *polkit_grant, PolKitResult auth_t
         }
 
         switch (auth_type) {
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT:
         case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH:
         case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION:
         case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS:
@@ -223,6 +228,7 @@ conversation_override_grant_type (PolKitGrant *polkit_grant, PolKitResult auth_t
                         overridden_auth_type = POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS;
                 break;
 
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT:
         case POLKIT_RESULT_ONLY_VIA_SELF_AUTH:
         case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION:
         case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS:
@@ -432,12 +438,17 @@ auth_iterator_cb (PolKitAuthorizationDB *authdb,
                 printf ("  Authorized:  %s\n", pk_result == POLKIT_RESULT_YES ? "Yes" : "No");
 
                 switch (polkit_authorization_get_scope (auth)) {
+                case POLKIT_AUTHORIZATION_SCOPE_PROCESS_ONE_SHOT:
                 case POLKIT_AUTHORIZATION_SCOPE_PROCESS:
                         polkit_authorization_scope_process_get_pid (auth, &pid, &pid_start_time);
                         if (polkit_sysdeps_get_exe_for_pid (pid, exe, sizeof (exe)) == -1)
                                 strncpy (exe, "unknown", sizeof (exe));
-                        printf ("  Scope:       Confined to pid %d (%s)\n", pid, exe);
 
+                        if (polkit_authorization_get_scope (auth) == POLKIT_AUTHORIZATION_SCOPE_PROCESS_ONE_SHOT) {
+                                printf ("  Scope:       Confined to single shot from pid %d (%s)\n", pid, exe);
+                        } else {
+                                printf ("  Scope:       Confined to pid %d (%s)\n", pid, exe);
+                        }
                         break;
                 case POLKIT_AUTHORIZATION_SCOPE_SESSION:
                         printf ("  Scope:       Confined to session %s\n", polkit_authorization_scope_session_get_ck_objref (auth));
@@ -528,9 +539,11 @@ pfe_iterator_show_obtainable_cb (PolKitPolicyCache *policy_cache,
         case POLKIT_RESULT_YES:
                 break;
 
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT:
         case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH:
         case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION:
         case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT:
         case POLKIT_RESULT_ONLY_VIA_SELF_AUTH:
         case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION:
         case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS:


More information about the hal-commit mailing list