diff options
author | David Zeuthen <davidz@redhat.com> | 2012-04-11 13:15:48 -0400 |
---|---|---|
committer | David Zeuthen <davidz@redhat.com> | 2012-04-11 15:45:17 -0400 |
commit | bda0fc1de3361fc6f377d041ce2088118048fdf7 (patch) | |
tree | 382c1020b2aff311e7e9aa866130b45d692a6031 | |
parent | 4aa6dd28476e12a5265d71b6bc19c730f1036785 (diff) | |
download | polkit-bda0fc1de3361fc6f377d041ce2088118048fdf7.tar.gz |
Add pkttyagent(1) helper
This came up while working on
https://bugzilla.redhat.com/show_bug.cgi?id=804088
and is useful for example if it's not suitable or appropriate to link
against the polkit libraries.
Signed-off-by: David Zeuthen <davidz@redhat.com>
-rw-r--r-- | docs/man/Makefile.am | 2 | ||||
-rw-r--r-- | docs/man/pkaction.xml | 3 | ||||
-rw-r--r-- | docs/man/pkcheck.xml | 3 | ||||
-rw-r--r-- | docs/man/pkexec.xml | 3 | ||||
-rw-r--r-- | docs/man/pkttyagent.xml | 154 | ||||
-rw-r--r-- | docs/man/polkit.xml | 15 | ||||
-rw-r--r-- | docs/polkit/Makefile.am | 1 | ||||
-rw-r--r-- | docs/polkit/polkit-1-docs.xml | 1 | ||||
-rw-r--r-- | src/polkitbackend/polkitbackendinteractiveauthority.c | 7 | ||||
-rw-r--r-- | src/programs/Makefile.am | 16 | ||||
-rw-r--r-- | src/programs/pkttyagent.c | 235 |
11 files changed, 439 insertions, 1 deletions
diff --git a/docs/man/Makefile.am b/docs/man/Makefile.am index 076608b..b71c1d2 100644 --- a/docs/man/Makefile.am +++ b/docs/man/Makefile.am @@ -10,6 +10,7 @@ man_MANS = \ pkexec.1 \ pkcheck.1 \ pkaction.1 \ + pkttyagent.1 \ $(NULL) %.8 %.1 : %.xml @@ -24,6 +25,7 @@ EXTRA_DIST = \ pkexec.xml \ pkcheck.xml \ pkaction.xml \ + pkttyagent.xml \ $(NULL) clean-local: diff --git a/docs/man/pkaction.xml b/docs/man/pkaction.xml index ba91e9a..24c156f 100644 --- a/docs/man/pkaction.xml +++ b/docs/man/pkaction.xml @@ -100,6 +100,9 @@ </citerefentry>, <citerefentry> <refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>pkttyagent</refentrytitle><manvolnum>1</manvolnum> </citerefentry> </para> </refsect1> diff --git a/docs/man/pkcheck.xml b/docs/man/pkcheck.xml index bb5866d..6b8a874 100644 --- a/docs/man/pkcheck.xml +++ b/docs/man/pkcheck.xml @@ -213,6 +213,9 @@ KEY3=VALUE3 </citerefentry>, <citerefentry> <refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>pkttyagent</refentrytitle><manvolnum>1</manvolnum> </citerefentry> </para> </refsect1> diff --git a/docs/man/pkexec.xml b/docs/man/pkexec.xml index 8196511..1734033 100644 --- a/docs/man/pkexec.xml +++ b/docs/man/pkexec.xml @@ -283,6 +283,9 @@ </citerefentry>, <citerefentry> <refentrytitle>pkcheck</refentrytitle><manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>pkttyagent</refentrytitle><manvolnum>1</manvolnum> </citerefentry> </para> </refsect1> diff --git a/docs/man/pkttyagent.xml b/docs/man/pkttyagent.xml new file mode 100644 index 0000000..f0f328e --- /dev/null +++ b/docs/man/pkttyagent.xml @@ -0,0 +1,154 @@ +<?xml version="1.0"?> +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" + "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [ +<!ENTITY version SYSTEM "../version.xml"> +]> +<refentry id="pkttyagent.1" xmlns:xi="http://www.w3.org/2003/XInclude"> + <refentryinfo> + <title>pkttyagent</title> + <date>May 2009</date> + <productname>polkit</productname> + </refentryinfo> + + <refmeta> + <refentrytitle>pkttyagent</refentrytitle> + <manvolnum>1</manvolnum> + <refmiscinfo class="version"></refmiscinfo> + </refmeta> + + <refnamediv> + <refname>pkttyagent</refname> + <refpurpose>Textual authentication helper</refpurpose> + </refnamediv> + + <refsynopsisdiv> + <cmdsynopsis> + <command>pkttyagent</command> + <arg><option>--version</option></arg> + <arg><option>--help</option></arg> + </cmdsynopsis> + + <cmdsynopsis> + <command>pkttyagent</command> + + <group> + <arg choice="plain"> + <option>--process</option> + <group choice="req"> + <arg choice="plain"> + <replaceable>pid</replaceable> + </arg> + <arg choice="plain"> + <replaceable>pid,pid-start-time</replaceable> + </arg> + </group> + </arg> + <arg choice="plain"> + <option>--system-bus-name</option> + <replaceable>busname</replaceable> + </arg> + </group> + + <group> + <arg choice="plain"> + <option>--notify-fd</option> + <replaceable>fd</replaceable> + </arg> + </group> + + </cmdsynopsis> + + </refsynopsisdiv> + + <refsect1 id="pkttyagent-descsription"> + <title>DESCRIPTION</title> + <para> + <command>pkttyagent</command> is used to start a textual + authentication agent for the subject specified by either + <option>--process</option> or + <option>--system-bus-name</option>. If neither of these options + are given, the parent process is used. + </para> + <para> + To get notified when the authentication agent has been + registered either listen to the <link + linkend="eggdbus-signal-org.freedesktop.PolicyKit1.Authority::Changed">Changed</link> + D-Bus signal or use <option>--notify-fd</option> to pass the + number of a file descriptor that has been passed to the + program. This file descriptor will then be closed when the + authentication agent has been successfully registered. + </para> + </refsect1> + + <refsect1 id="pkttyagent-return-value"> + <title>RETURN VALUE</title> + <para> + If the authentication agent could not be registered, + <command>pkttyagent</command> exits with an exit code of + 127. Diagnostic messages are printed on standard error. + </para> + <para> + If one or more of the options passed are malformed, + <command>pkttyagent</command> exits with an exit code of 126. If + stdin is a tty, then this manual page is also shown. + </para> + <para> + If the authentication agent was successfully registered, + <command>pkttyagent</command> will keep running, interacting + with the user as needed. When its services are no longer needed, + the process can be killed. + </para> + </refsect1> + + <refsect1 id="pkttyagent-notes"> + <title>NOTES</title> + <para> + Since process identifiers can be recycled, the caller should + always use <replaceable>pid,pid-start-time</replaceable> when + using the <option>--process</option> option. The value of + <replaceable>pid-start-time</replaceable> can be determined by + consulting e.g. the + <citerefentry> + <refentrytitle>proc</refentrytitle><manvolnum>5</manvolnum> + </citerefentry> + file system depending on the operating system. If only <replaceable>pid</replaceable> + is passed to the <option>--process</option> option, then <command>pkttyagent</command> + will look up the start time itself but note that this may be racy. + </para> + </refsect1> + + <refsect1 id="pkttyagent-author"><title>AUTHOR</title> + <para> + Written by David Zeuthen <email>davidz@redhat.com</email> with + a lot of help from many others. + </para> + </refsect1> + + <refsect1 id="pkttyagent-bugs"> + <title>BUGS</title> + <para> + Please send bug reports to either the distribution or the + polkit-devel mailing list, + see the link <ulink url="http://lists.freedesktop.org/mailman/listinfo/polkit-devel"/> + on how to subscribe. + </para> + </refsect1> + + <refsect1 id="pkttyagent-see-also"> + <title>SEE ALSO</title> + <para> + <citerefentry> + <refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>pkaction</refentrytitle><manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>pkcheck</refentrytitle><manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum> + </citerefentry> + </para> + </refsect1> +</refentry> diff --git a/docs/man/polkit.xml b/docs/man/polkit.xml index ae67f7c..188c514 100644 --- a/docs/man/polkit.xml +++ b/docs/man/polkit.xml @@ -223,6 +223,18 @@ System Context | | implemention for systems without a <literal>root</literal> account. </para> + + <para> + Applications that do not run under a desktop environment (for + example, if launched from a + <citerefentry><refentrytitle>ssh</refentrytitle><manvolnum>1</manvolnum></citerefentry> + login) may not have have an authentication agent associated with + them. Such applications may use the <link + linkend="PolkitAgentTextListener-struct">PolkitAgentTextListener</link> + type or the + <citerefentry><refentrytitle>pkttyagent</refentrytitle><manvolnum>1</manvolnum></citerefentry> + helper so the user can authenticate using a textual interface. + </para> </refsect1> <refsect1 id="polkit-declaring-actions"><title>DECLARING ACTIONS</title> @@ -469,6 +481,9 @@ System Context | | <citerefentry> <refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum> </citerefentry>, + <citerefentry> + <refentrytitle>pkttyagent</refentrytitle><manvolnum>1</manvolnum> + </citerefentry> </para> </refsect1> </refentry> diff --git a/docs/polkit/Makefile.am b/docs/polkit/Makefile.am index 370fb56..fd7123f 100644 --- a/docs/polkit/Makefile.am +++ b/docs/polkit/Makefile.am @@ -65,6 +65,7 @@ content_files = \ ../man/pkcheck.xml \ ../man/pkaction.xml \ ../man/pkexec.xml \ + ../man/pkttyagent.xml \ $(NULL) # Images to copy into HTML directory diff --git a/docs/polkit/polkit-1-docs.xml b/docs/polkit/polkit-1-docs.xml index 38a69a4..4fc8a99 100644 --- a/docs/polkit/polkit-1-docs.xml +++ b/docs/polkit/polkit-1-docs.xml @@ -112,6 +112,7 @@ <xi:include href="../man/pkaction.xml"/> <xi:include href="../man/pkexec.xml"/> <xi:include href="../man/pklocalauthority.xml"/> + <xi:include href="../man/pkttyagent.xml"/> </part> <chapter id="polkit-hierarchy"> diff --git a/src/polkitbackend/polkitbackendinteractiveauthority.c b/src/polkitbackend/polkitbackendinteractiveauthority.c index 99c4782..f523782 100644 --- a/src/polkitbackend/polkitbackendinteractiveauthority.c +++ b/src/polkitbackend/polkitbackendinteractiveauthority.c @@ -2329,6 +2329,9 @@ polkit_backend_interactive_authority_register_authentication_agent (PolkitBacken caller_cmdline, object_path, locale); + + g_signal_emit_by_name (authority, "changed"); + ret = TRUE; out: @@ -2487,6 +2490,8 @@ polkit_backend_interactive_authority_unregister_authentication_agent (PolkitBack /* this frees agent... */ g_hash_table_remove (priv->hash_scope_to_authentication_agent, agent->scope); + g_signal_emit_by_name (authority, "changed"); + ret = TRUE; out: @@ -2635,6 +2640,8 @@ polkit_backend_interactive_authority_system_bus_name_owner_changed (PolkitBacken /* this works because we have exactly one agent per session */ /* this frees agent... */ g_hash_table_remove (priv->hash_scope_to_authentication_agent, agent->scope); + + g_signal_emit_by_name (authority, "changed"); } /* cancel all authentication sessions initiated by the process owning the vanished name */ diff --git a/src/programs/Makefile.am b/src/programs/Makefile.am index c260dee..bc1b5a8 100644 --- a/src/programs/Makefile.am +++ b/src/programs/Makefile.am @@ -17,7 +17,7 @@ INCLUDES = \ # ---------------------------------------------------------------------------------------------------- -bin_PROGRAMS = pkexec pkcheck pkaction +bin_PROGRAMS = pkexec pkcheck pkaction pkttyagent # ---------------------------------------------------------------------------------------------------- @@ -50,6 +50,20 @@ pkcheck_LDADD = \ # ---------------------------------------------------------------------------------------------------- +pkttyagent_SOURCES = pkttyagent.c + +pkttyagent_CFLAGS = \ + $(GLIB_CFLAGS) \ + $(NULL) + +pkttyagent_LDADD = \ + $(GLIB_LIBS) \ + $(top_builddir)/src/polkit/libpolkit-gobject-1.la \ + $(top_builddir)/src/polkitagent/libpolkit-agent-1.la \ + $(NULL) + +# ---------------------------------------------------------------------------------------------------- + pkaction_SOURCES = pkaction.c pkaction_CFLAGS = \ diff --git a/src/programs/pkttyagent.c b/src/programs/pkttyagent.c new file mode 100644 index 0000000..1c170f4 --- /dev/null +++ b/src/programs/pkttyagent.c @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2009-2012 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: David Zeuthen <davidz@redhat.com> + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <stdio.h> +#include <polkit/polkit.h> +#define POLKIT_AGENT_I_KNOW_API_IS_SUBJECT_TO_CHANGE +#include <polkitagent/polkitagent.h> + +static void +usage (int argc, char *argv[]) +{ + GError *error; + + error = NULL; + if (!g_spawn_command_line_sync ("man pkttyagent", + NULL, + NULL, + NULL, + &error)) + { + g_printerr ("Cannot show manual page: %s (%s, %d)\n", + error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); + } +} + + +int +main (int argc, char *argv[]) +{ + gboolean opt_show_help = FALSE; + gboolean opt_show_version = FALSE; + PolkitAuthority *authority = NULL; + PolkitSubject *subject = NULL; + gpointer local_agent_handle = NULL; + PolkitAgentListener *listener = NULL; + GError *error; + GMainLoop *loop = NULL; + guint n; + guint ret = 126; + gint notify_fd = -1; + + g_type_init (); + + for (n = 1; n < (guint) argc; n++) + { + if (g_strcmp0 (argv[n], "--help") == 0) + { + opt_show_help = TRUE; + } + else if (g_strcmp0 (argv[n], "--version") == 0) + { + opt_show_version = TRUE; + } + else if (g_strcmp0 (argv[n], "--notify-fd") == 0) + { + n++; + if (n >= (guint) argc) + { + usage (argc, argv); + goto out; + } + + if (sscanf (argv[n], "%i", ¬ify_fd) != 1) + { + usage (argc, argv); + goto out; + } + } + else if (g_strcmp0 (argv[n], "--process") == 0 || g_strcmp0 (argv[n], "-p") == 0) + { + gint pid; + guint64 pid_start_time; + + n++; + if (n >= (guint) argc) + { + usage (argc, argv); + goto out; + } + + if (sscanf (argv[n], "%i,%" G_GUINT64_FORMAT, &pid, &pid_start_time) == 2) + { + subject = polkit_unix_process_new_full (pid, pid_start_time); + } + else if (sscanf (argv[n], "%i", &pid) == 1) + { + subject = polkit_unix_process_new (pid); + } + else + { + usage (argc, argv); + goto out; + } + } + else if (g_strcmp0 (argv[n], "--system-bus-name") == 0 || g_strcmp0 (argv[n], "-s") == 0) + { + n++; + if (n >= (guint) argc) + { + usage (argc, argv); + goto out; + } + + subject = polkit_system_bus_name_new (argv[n]); + } + else + { + break; + } + } + + if (opt_show_help) + { + usage (argc, argv); + ret = 0; + goto out; + } + else if (opt_show_version) + { + g_print ("pkttyagent version %s\n", PACKAGE_VERSION); + ret = 0; + goto out; + } + + /* Use parent process, if no subject has been specified */ + if (subject == NULL) + { + pid_t pid_of_caller; + pid_of_caller = getppid (); + if (pid_of_caller == 1) + { + /* getppid() can return 1 if the parent died (meaning that we are reaped + * by /sbin/init); In that case we simpy bail. + */ + g_printerr ("Refusing to render service to dead parents.\n"); + goto out; + } + + subject = polkit_unix_process_new_for_owner (pid_of_caller, + 0, /* 0 means "look up start-time in /proc" */ + getuid ()); + /* really double-check the invariants guaranteed by the PolkitUnixProcess class */ + g_assert (subject != NULL); + g_assert (polkit_unix_process_get_pid (POLKIT_UNIX_PROCESS (subject)) == pid_of_caller); + g_assert (polkit_unix_process_get_uid (POLKIT_UNIX_PROCESS (subject)) >= 0); + g_assert (polkit_unix_process_get_start_time (POLKIT_UNIX_PROCESS (subject)) > 0); + } + + error = NULL; + authority = polkit_authority_get_sync (NULL /* GCancellable* */, &error); + if (authority == NULL) + { + g_printerr ("Error getting authority: %s (%s, %d)\n", + error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); + ret = 127; + goto out; + } + + 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 (%s, %d)\n", + error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); + ret = 127; + 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 authentication agent: %s (%s, %d)\n", + error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); + goto out; + } + + if (notify_fd != -1) + { + if (close (notify_fd) != 0) + { + g_printerr ("Error closing notify-fd %d: %m\n", notify_fd); + goto out; + } + } + + loop = g_main_loop_new (NULL, FALSE); + g_main_loop_run (loop); + + out: + if (loop != NULL) + g_main_loop_unref (loop); + + if (local_agent_handle != NULL) + polkit_agent_listener_unregister (local_agent_handle); + + if (subject != NULL) + g_object_unref (subject); + + if (authority != NULL) + g_object_unref (authority); + + return ret; +} |