summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Zeuthen <davidz@redhat.com>2012-05-25 12:40:42 -0400
committerDavid Zeuthen <davidz@redhat.com>2012-05-25 12:40:42 -0400
commit8e0383cb9972f5b3b86e64f9b015f53671ce0323 (patch)
tree4696f1d0071ed0abe27287a14907a42f7af9d147
parente5dafb816bcefdceb617e32fbfb527f865c8879c (diff)
downloadpolkit-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.ac25
-rw-r--r--data/Makefile.am21
-rw-r--r--data/org.freedesktop.PolicyKit1.conf.in (renamed from data/org.freedesktop.PolicyKit1.conf)4
-rw-r--r--docs/man/polkit.xml17
-rw-r--r--docs/man/polkitd.xml6
-rw-r--r--src/polkitbackend/Makefile.am4
-rw-r--r--src/polkitbackend/polkitd.c73
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);