diff options
author | David Zeuthen <davidz@redhat.com> | 2012-05-25 12:40:42 -0400 |
---|---|---|
committer | David Zeuthen <davidz@redhat.com> | 2012-05-25 12:40:42 -0400 |
commit | 8e0383cb9972f5b3b86e64f9b015f53671ce0323 (patch) | |
tree | 4696f1d0071ed0abe27287a14907a42f7af9d147 | |
parent | e5dafb816bcefdceb617e32fbfb527f865c8879c (diff) | |
download | polkit-8e0383cb9972f5b3b86e64f9b015f53671ce0323.tar.gz |
Run polkitd as an unprivileged user
There's really no reason to run all this code as uid 0.
Signed-off-by: David Zeuthen <davidz@redhat.com>
-rw-r--r-- | configure.ac | 25 | ||||
-rw-r--r-- | data/Makefile.am | 21 | ||||
-rw-r--r-- | data/org.freedesktop.PolicyKit1.conf.in (renamed from data/org.freedesktop.PolicyKit1.conf) | 4 | ||||
-rw-r--r-- | docs/man/polkit.xml | 17 | ||||
-rw-r--r-- | docs/man/polkitd.xml | 6 | ||||
-rw-r--r-- | src/polkitbackend/Makefile.am | 4 | ||||
-rw-r--r-- | src/polkitbackend/polkitd.c | 73 |
7 files changed, 136 insertions, 14 deletions
diff --git a/configure.ac b/configure.ac index d9559cc..b26b333 100644 --- a/configure.ac +++ b/configure.ac @@ -194,6 +194,20 @@ fi AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$systemdsystemunitdir"]) dnl --------------------------------------------------------------------------- +dnl - User for running polkitd +dnl --------------------------------------------------------------------------- + +AC_ARG_WITH(polkitd_user, AS_HELP_STRING([--with-polkitd-user=<user>],[User for running polkitd (polkitd)])) + +if test -z "$with_polkitd_user" ; then + POLKITD_USER=polkitd +else + POLKITD_USER=$with_polkitd_user +fi +AC_SUBST(POLKITD_USER) +AC_DEFINE_UNQUOTED(POLKITD_USER,"$POLKITD_USER", [User for running polkitd]) + +dnl --------------------------------------------------------------------------- dnl - Select which authentication framework to use dnl --------------------------------------------------------------------------- @@ -496,7 +510,8 @@ echo " Authentication framework: ${POLKIT_AUTHFW} Session tracking: ${SESSION_TRACKING} PAM support: ${have_pam} - systemdsystemunitdir: ${systemdsystemunitdir}" + systemdsystemunitdir: ${systemdsystemunitdir} + polkitd user: ${POLKITD_USER}" if test "$have_pam" = yes ; then echo " @@ -522,10 +537,10 @@ echo "NOTE: The file ${bindir}/pkexec must be owned by root and" echo " have mode 4755 (setuid root binary)" echo -echo "NOTE: The directory ${sysconfdir}/polkit-1/rules.d" -echo " should have mode 700" +echo "NOTE: The directory ${sysconfdir}/polkit-1/rules.d must be owned" +echo " by user '$POLKITD_USER' and have mode 700" echo -echo "NOTE: The directory ${datadir}/polkit-1/rules.d" -echo " should have mode 700" +echo "NOTE: The directory ${datadir}/polkit-1/rules.d must be owned" +echo " by user '$POLKITD_USER' and have mode 700" echo diff --git a/data/Makefile.am b/data/Makefile.am index 6623286..b2d0cde 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -4,6 +4,8 @@ NULL = libprivdir = $(prefix)/lib/polkit-1 +# ---------------------------------------------------------------------------------------------------- + servicedir = $(datadir)/dbus-1/system-services service_in_files = org.freedesktop.PolicyKit1.service.in service_DATA = $(service_in_files:.service.in=.service) @@ -11,17 +13,28 @@ service_DATA = $(service_in_files:.service.in=.service) $(service_DATA): $(service_in_files) Makefile @sed -e "s|\@libprivdir\@|$(libprivdir)|" $< > $@ +# ---------------------------------------------------------------------------------------------------- + dbusconfdir = $(sysconfdir)/dbus-1/system.d -dbusconf_DATA = org.freedesktop.PolicyKit1.conf +dbusconf_in_files = org.freedesktop.PolicyKit1.conf.in +dbusconf_DATA = $(dbusconf_in_files:.conf.in=.conf) + +$(dbusconf_DATA): $(dbusconf_in_files) Makefile + @sed -e "s|\@polkitd_user\@|$(POLKITD_USER)|" $< > $@ + +# ---------------------------------------------------------------------------------------------------- if POLKIT_AUTHFW_PAM pamdir = $(sysconfdir)/pam.d pam_DATA = polkit-1 endif +# ---------------------------------------------------------------------------------------------------- + pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = polkit-gobject-1.pc polkit-backend-1.pc polkit-agent-1.pc +# ---------------------------------------------------------------------------------------------------- systemdservice_in_files = polkit.service.in @@ -32,16 +45,18 @@ $(systemdservice_DATA): $(systemdservice_in_files) Makefile @sed -e "s|\@libprivdir\@|$(libprivdir)|" $< > $@ endif +# ---------------------------------------------------------------------------------------------------- + CLEANFILES = $(BUILT_SOURCES) EXTRA_DIST = \ org.freedesktop.PolicyKit1.Authority.xml \ org.freedesktop.PolicyKit1.AuthenticationAgent.xml \ $(service_in_files) \ + $(dbusconf_in_files) \ $(systemdservice_in_files) \ - $(dbusconf_DATA) \ $(NULL) clean-local : - rm -f *~ $(service_DATA) $(systemdservice_DATA) + rm -f *~ $(service_DATA) $(dbusconf_DATA) $(systemdservice_DATA) diff --git a/data/org.freedesktop.PolicyKit1.conf b/data/org.freedesktop.PolicyKit1.conf.in index c8ef513..c749207 100644 --- a/data/org.freedesktop.PolicyKit1.conf +++ b/data/org.freedesktop.PolicyKit1.conf.in @@ -4,7 +4,7 @@ "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> <busconfig> - <policy user="root"> + <policy user="@polkitd_user@"> <allow own="org.freedesktop.PolicyKit1"/> </policy> @@ -13,7 +13,7 @@ </policy> <!-- Allow uid 0 to send messages on the org.freedesktop.PolicyKit1.AuthenticationAgent interface --> - <policy user="root"> + <policy user="@polkitd_user@"> <allow send_interface="org.freedesktop.PolicyKit1.AuthenticationAgent"/> </policy> diff --git a/docs/man/polkit.xml b/docs/man/polkit.xml index bd39299..b19b92c 100644 --- a/docs/man/polkit.xml +++ b/docs/man/polkit.xml @@ -31,7 +31,16 @@ untrusted. For every request from a subject, the mechanism needs to determine if the request is authorized or if it should refuse to service the subject. Using the polkit APIs, a mechanism can - offload this decision to a trusted party: The polkit Authority. + offload this decision to a trusted party: The polkit authority. + </para> + + <para> + The polkit authority is implemented as an system daemon, + <link linkend="polkitd.8"><citerefentry><refentrytitle>polkitd</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>, + which itself has little privilege as it is running as the + <emphasis>polkitd</emphasis> system user. Mechanisms, subjects + and authentication agents communicate with the authority using + the system message bus. </para> <para> @@ -204,7 +213,7 @@ System Context | | <refsect1 id="polkit-declaring-actions"><title>DECLARING ACTIONS</title> <para> - A mechanism need to declare a set of <quote>ACTIONS</quote> in + A mechanism need to declare a set of <emphasis>actions</emphasis> in order to use polkit. Actions correspond to operations that clients can request the mechanism to carry out and are defined in XML files that the mechanism installs into the <filename @@ -591,7 +600,9 @@ System Context | | The <function>spawn()</function> method should be used sparingly as helpers may take a very long or indeterminate amount of time to complete and no other authorization check can be handled - while the helper is running. + while the helper is running. Note that the spawned programs + will run as the unprivileged <emphasis>polkitd</emphasis> system + user. </para> <para> diff --git a/docs/man/polkitd.xml b/docs/man/polkitd.xml index 879da2d..5fee8d4 100644 --- a/docs/man/polkitd.xml +++ b/docs/man/polkitd.xml @@ -41,6 +41,12 @@ </para> <para> + <command>polkitd</command> must be started with superuser + privileges but drops privileges early by switching to the + unprivileged <emphasis>polkitd</emphasis> system user. + </para> + + <para> See the <link linkend="polkit.8"><citerefentry><refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum></citerefentry></link> man page for more information. diff --git a/src/polkitbackend/Makefile.am b/src/polkitbackend/Makefile.am index a173125..9f430d0 100644 --- a/src/polkitbackend/Makefile.am +++ b/src/polkitbackend/Makefile.am @@ -103,8 +103,10 @@ dist-hook : clean-local : rm -f *~ $(BUILT_SOURCES) -install-exec-hook: +install-data-hook: mkdir -p $(DESTDIR)$(sysconfdir)/polkit-1/rules.d -chmod 700 $(DESTDIR)$(sysconfdir)/polkit-1/rules.d + -chown $(POLKITD_USER) $(DESTDIR)$(sysconfdir)/polkit-1/rules.d mkdir -p $(DESTDIR)$(datadir)/polkit-1/rules.d -chmod 700 $(DESTDIR)$(datadir)/polkit-1/rules.d + -chown $(POLKITD_USER) $(DESTDIR)$(datadir)/polkit-1/rules.d diff --git a/src/polkitbackend/polkitd.c b/src/polkitbackend/polkitd.c index 0bb3f32..6a1bfb0 100644 --- a/src/polkitbackend/polkitd.c +++ b/src/polkitbackend/polkitd.c @@ -25,6 +25,9 @@ #include <glib-unix.h> +#include <pwd.h> +#include <grp.h> + #include <polkit/polkit.h> #include <polkitbackend/polkitbackend.h> @@ -94,6 +97,63 @@ on_sigint (gpointer user_data) return FALSE; } +static gboolean +become_user (const gchar *user, + GError **error) +{ + gboolean ret = FALSE; + struct passwd *pw; + + g_return_val_if_fail (user != NULL, FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + pw = getpwnam (user); + if (pw == NULL) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Error calling getpwnam(): %m"); + goto out; + } + + if (setgroups (0, NULL) != 0) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Error clearing groups: %m"); + goto out; + } + if (initgroups (pw->pw_name, pw->pw_gid) != 0) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Error initializing groups: %m"); + goto out; + } + + setregid (pw->pw_gid, pw->pw_gid); + setreuid (pw->pw_uid, pw->pw_uid); + if ((geteuid () != pw->pw_uid) || (getuid () != pw->pw_uid) || + (getegid () != pw->pw_gid) || (getgid () != pw->pw_gid)) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Error becoming real+effective uid %d and gid %d: %m", + (int) pw->pw_uid, (int) pw->pw_gid); + goto out; + } + + if (chdir (pw->pw_dir) != 0) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Error changing to home directory %s: %m", + pw->pw_dir); + goto out; + } + + + ret = TRUE; + + out: + return ret; +} + int main (int argc, char **argv) @@ -142,6 +202,19 @@ main (int argc, } } + error = NULL; + if (!become_user (POLKITD_USER, &error)) + { + g_printerr ("Error switcing to user %s: %s\n", + POLKITD_USER, error->message); + g_clear_error (&error); + goto out; + } + + g_print ("Successfully changed to user %s\n", POLKITD_USER); + + if (g_getenv ("PATH") == NULL) + g_setenv ("PATH", "/usr/bin:/bin:/usr/sbin:/sbin", TRUE); loop = g_main_loop_new (NULL, FALSE); |