PolicyKit: Branch 'wip/js-rule-files'

David Zeuthen david at kemper.freedesktop.org
Fri May 25 09:41:28 PDT 2012


 configure.ac                            |   25 ++++++++--
 data/Makefile.am                        |   21 +++++++--
 data/org.freedesktop.PolicyKit1.conf    |   20 --------
 data/org.freedesktop.PolicyKit1.conf.in |   20 ++++++++
 docs/man/polkit.xml                     |   17 ++++++-
 docs/man/polkitd.xml                    |    6 ++
 src/polkitbackend/Makefile.am           |    4 +
 src/polkitbackend/polkitd.c             |   73 ++++++++++++++++++++++++++++++++
 8 files changed, 154 insertions(+), 32 deletions(-)

New commits:
commit 8e0383cb9972f5b3b86e64f9b015f53671ce0323
Author: David Zeuthen <davidz at redhat.com>
Date:   Fri May 25 12:40:42 2012 -0400

    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 at redhat.com>

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
deleted file mode 100644
index c8ef513..0000000
--- a/data/org.freedesktop.PolicyKit1.conf
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- -->
-
-<!DOCTYPE busconfig PUBLIC
- "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
- "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
-<busconfig>
-  <policy user="root">
-    <allow own="org.freedesktop.PolicyKit1"/>
-  </policy>
-
-  <policy context="default">
-    <allow send_destination="org.freedesktop.PolicyKit1"/>
-  </policy>
-
-  <!-- Allow uid 0 to send messages on the org.freedesktop.PolicyKit1.AuthenticationAgent interface -->
-  <policy user="root">
-    <allow send_interface="org.freedesktop.PolicyKit1.AuthenticationAgent"/>
-  </policy>
-
-</busconfig>
diff --git a/data/org.freedesktop.PolicyKit1.conf.in b/data/org.freedesktop.PolicyKit1.conf.in
new file mode 100644
index 0000000..c749207
--- /dev/null
+++ b/data/org.freedesktop.PolicyKit1.conf.in
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- -->
+
+<!DOCTYPE busconfig PUBLIC
+ "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+  <policy user="@polkitd_user@">
+    <allow own="org.freedesktop.PolicyKit1"/>
+  </policy>
+
+  <policy context="default">
+    <allow send_destination="org.freedesktop.PolicyKit1"/>
+  </policy>
+
+  <!-- Allow uid 0 to send messages on the org.freedesktop.PolicyKit1.AuthenticationAgent interface -->
+  <policy user="@polkitd_user@">
+    <allow send_interface="org.freedesktop.PolicyKit1.AuthenticationAgent"/>
+  </policy>
+
+</busconfig>
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);
 


More information about the hal-commit mailing list