summaryrefslogtreecommitdiff
path: root/src/programs/pkexec.c
diff options
context:
space:
mode:
authorDavid Zeuthen <davidz@redhat.com>2010-08-12 16:51:51 -0400
committerDavid Zeuthen <davidz@redhat.com>2010-08-12 16:51:51 -0400
commit42177383585e1e01cd6150f891176afcd4538a82 (patch)
tree924bcbd61405b7c0c504718f02791aefa7bcfaf6 /src/programs/pkexec.c
parent17f0600529dc926ae4a0c85dc56c393cc09e4011 (diff)
Add textual authentication agent and use it in pkexec(1)
This makes pkexec(1) work when e.g. logging in via ssh(1) or the linux console but also when using `su -'. Example: [davidz@x61 ~]$ su - bateman Password: [bateman@x61 ~]$ pkexec bash ==== AUTHENTICATING FOR org.freedesktop.policykit.exec === Authentication is needed to run `/bin/bash' as the super user Authenticating as: root Password: ==== AUTHENTICATION COMPLETE === [root@x61 ~]# Summary of changes - Added a PolkitAgentTextListener class - Add new polkit_agent_listener_register() (and _unregister()) API - Deprecate polkit_agent_register_listener API - Allow registering authentication agents for PolkitUnixProcess subjects and prefer such agents to ones governing the session - Make PolkitAgentSession use the thread-default GMainContext - otherwise it won't work in spawned threads - (finally) use PolkitAgentTextListener in pkexec(1) if authorization via authentication is possible but no authentication agent was found Signed-off-by: David Zeuthen <davidz@redhat.com>
Diffstat (limited to 'src/programs/pkexec.c')
-rw-r--r--src/programs/pkexec.c46
1 files changed, 44 insertions, 2 deletions
diff --git a/src/programs/pkexec.c b/src/programs/pkexec.c
index 4a3d55d..f4480ff 100644
--- a/src/programs/pkexec.c
+++ b/src/programs/pkexec.c
@@ -43,6 +43,8 @@
#include <stdarg.h>
#include <polkit/polkit.h>
+#define POLKIT_AGENT_I_KNOW_API_IS_SUBJECT_TO_CHANGE
+#include <polkitagent/polkitagent.h>
static gchar *original_user_name = NULL;
static gchar *original_cwd = NULL;
@@ -361,6 +363,7 @@ validate_environment_variable (const gchar *key,
return ret;
}
+
/* ---------------------------------------------------------------------------------------------------- */
int
@@ -417,6 +420,7 @@ main (int argc, char *argv[])
gchar *opt_user;
pid_t pid_of_caller;
uid_t uid_of_caller;
+ gpointer local_agent_handle;
ret = 127;
authority = NULL;
@@ -428,6 +432,7 @@ main (int argc, char *argv[])
path = NULL;
command_line = NULL;
opt_user = NULL;
+ local_agent_handle = NULL;
/* check for correct invocation */
if (geteuid () != 0)
@@ -642,6 +647,7 @@ main (int argc, char *argv[])
action_id = find_action_for_path (authority, path);
g_assert (action_id != NULL);
+ try_again:
error = NULL;
result = polkit_authority_check_authorization_sync (authority,
subject,
@@ -664,8 +670,40 @@ main (int argc, char *argv[])
}
else if (polkit_authorization_result_get_is_challenge (result))
{
- g_printerr ("Error executing command as another user: No authentication agent was found.\n");
- goto out;
+ if (local_agent_handle == NULL)
+ {
+ PolkitAgentListener *listener;
+ error = NULL;
+ /* this will fail if we can't find a controlling terminal */
+ listener = polkit_agent_text_listener_new (NULL, &error);
+ if (listener == NULL)
+ {
+ g_printerr ("Error creating textual authentication agent: %s\n", error->message);
+ g_error_free (error);
+ goto out;
+ }
+ local_agent_handle = polkit_agent_listener_register (listener,
+ POLKIT_AGENT_REGISTER_FLAGS_RUN_IN_THREAD,
+ subject,
+ NULL, /* object_path */
+ NULL, /* GCancellable */
+ &error);
+ g_object_unref (listener);
+ if (local_agent_handle == NULL)
+ {
+ g_printerr ("Error registering local authentication agent: %s\n", error->message);
+ g_error_free (error);
+ goto out;
+ }
+ g_object_unref (result);
+ result = NULL;
+ goto try_again;
+ }
+ else
+ {
+ g_printerr ("Error executing command as another user.\n");
+ goto out;
+ }
}
else
{
@@ -802,6 +840,10 @@ main (int argc, char *argv[])
g_assert_not_reached ();
out:
+ /* if applicable, nuke the local authentication agent */
+ if (local_agent_handle != NULL)
+ polkit_agent_listener_unregister (local_agent_handle);
+
if (result != NULL)
g_object_unref (result);