Commit 1b4fa91b authored by David Zeuthen's avatar David Zeuthen
Browse files

introduce one-shot authorizations

parent 035e6ee4
......@@ -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
......
......@@ -48,6 +48,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,
......@@ -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;
}
......@@ -201,6 +201,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
......@@ -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;
......
......@@ -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),
......
......@@ -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);
......
......@@ -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;
}
......@@ -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 */