From 49c3a7c375148ba49d14d74fdfa2a17d6cf99684 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Wed, 29 Sep 2010 08:58:54 +0200 Subject: [PATCH] polkit: add patch to add shadow support Signed-off-by: Stephan Raue --- .../polkit/patches/polkit-1-shadow.diff | 1967 +++++++++++++++++ 1 file changed, 1967 insertions(+) create mode 100644 packages/security/polkit/patches/polkit-1-shadow.diff diff --git a/packages/security/polkit/patches/polkit-1-shadow.diff b/packages/security/polkit/patches/polkit-1-shadow.diff new file mode 100644 index 0000000000..2b12441e0c --- /dev/null +++ b/packages/security/polkit/patches/polkit-1-shadow.diff @@ -0,0 +1,1967 @@ +diff -Naur polkit-0.96/src/polkitagent/Makefile.am polkit-0.96.patch/src/polkitagent/Makefile.am +--- polkit-0.96/src/polkitagent/Makefile.am 2009-09-13 19:31:29.000000000 +0200 ++++ polkit-0.96.patch/src/polkitagent/Makefile.am 2010-09-28 23:57:21.559875461 +0200 +@@ -68,8 +68,15 @@ + libexec_PROGRAMS = polkit-agent-helper-1 + + polkit_agent_helper_1_SOURCES = \ +- polkitagenthelper.c \ +- $(NULL) ++ polkitagenthelperprivate.c polkitagenthelperprivate.h ++ ++if POLKIT_AUTHFW_PAM ++polkit_agent_helper_1_SOURCES += polkitagenthelper-pam.c ++endif ++if POLKIT_AUTHFW_SHADOW ++polkit_agent_helper_1_SOURCES += polkitagenthelper-shadow.c ++endif ++polkit_agent_helper_1_SOURCES += $(NULL) + + polkit_agent_helper_1_CFLAGS = \ + -D_POLKIT_COMPILATION \ +diff -Naur polkit-0.96/src/polkitagent/Makefile.in polkit-0.96.patch/src/polkitagent/Makefile.in +--- polkit-0.96/src/polkitagent/Makefile.in 2010-01-15 19:53:03.000000000 +0100 ++++ polkit-0.96.patch/src/polkitagent/Makefile.in 2010-09-28 23:57:34.190000422 +0200 +@@ -37,6 +37,8 @@ + build_triplet = @build@ + host_triplet = @host@ + libexec_PROGRAMS = polkit-agent-helper-1$(EXEEXT) ++@POLKIT_AUTHFW_PAM_TRUE@am__append_1 = polkitagenthelper-pam.c ++@POLKIT_AUTHFW_SHADOW_TRUE@am__append_2 = polkitagenthelper-shadow.c + subdir = src/polkitagent + DIST_COMMON = $(libpolkit_agent_1include_HEADERS) \ + $(srcdir)/Makefile.am $(srcdir)/Makefile.in +@@ -93,9 +95,14 @@ + $(libpolkit_agent_1_la_CFLAGS) $(CFLAGS) \ + $(libpolkit_agent_1_la_LDFLAGS) $(LDFLAGS) -o $@ + PROGRAMS = $(libexec_PROGRAMS) ++am__polkit_agent_helper_1_SOURCES_DIST = polkitagenthelperprivate.c \ ++ polkitagenthelperprivate.h polkitagenthelper-pam.c \ ++ polkitagenthelper-shadow.c ++@POLKIT_AUTHFW_PAM_TRUE@am__objects_4 = polkit_agent_helper_1-polkitagenthelper-pam.$(OBJEXT) ++@POLKIT_AUTHFW_SHADOW_TRUE@am__objects_5 = polkit_agent_helper_1-polkitagenthelper-shadow.$(OBJEXT) + am_polkit_agent_helper_1_OBJECTS = \ +- polkit_agent_helper_1-polkitagenthelper.$(OBJEXT) \ +- $(am__objects_1) ++ polkit_agent_helper_1-polkitagenthelperprivate.$(OBJEXT) \ ++ $(am__objects_4) $(am__objects_5) $(am__objects_1) + polkit_agent_helper_1_OBJECTS = $(am_polkit_agent_helper_1_OBJECTS) + polkit_agent_helper_1_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(top_builddir)/src/polkit/libpolkit-gobject-1.la \ +@@ -133,7 +140,7 @@ + SOURCES = $(libpolkit_agent_1_la_SOURCES) \ + $(polkit_agent_helper_1_SOURCES) + DIST_SOURCES = $(libpolkit_agent_1_la_SOURCES) \ +- $(polkit_agent_helper_1_SOURCES) ++ $(am__polkit_agent_helper_1_SOURCES_DIST) + HEADERS = $(libpolkit_agent_1include_HEADERS) + ETAGS = etags + CTAGS = ctags +@@ -361,10 +368,9 @@ + $(NULL) + + libpolkit_agent_1_la_LDFLAGS = -export-symbols-regex '(^polkit_.*)' +-polkit_agent_helper_1_SOURCES = \ +- polkitagenthelper.c \ ++polkit_agent_helper_1_SOURCES = polkitagenthelperprivate.c \ ++ polkitagenthelperprivate.h $(am__append_1) $(am__append_2) \ + $(NULL) +- + polkit_agent_helper_1_CFLAGS = \ + -D_POLKIT_COMPILATION \ + $(GLIB_CFLAGS) \ +@@ -500,7 +506,9 @@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpolkit_agent_1_la-polkitagentlistener.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpolkit_agent_1_la-polkitagentmarshal.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpolkit_agent_1_la-polkitagentsession.Plo@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/polkit_agent_helper_1-polkitagenthelper.Po@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/polkit_agent_helper_1-polkitagenthelper-pam.Po@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/polkit_agent_helper_1-polkitagenthelper-shadow.Po@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/polkit_agent_helper_1-polkitagenthelperprivate.Po@am__quote@ + + .c.o: + @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@@ -550,21 +558,53 @@ + @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + @am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpolkit_agent_1_la_CFLAGS) $(CFLAGS) -c -o libpolkit_agent_1_la-polkitagentlistener.lo `test -f 'polkitagentlistener.c' || echo '$(srcdir)/'`polkitagentlistener.c + +-polkit_agent_helper_1-polkitagenthelper.o: polkitagenthelper.c +-@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(polkit_agent_helper_1_CFLAGS) $(CFLAGS) -MT polkit_agent_helper_1-polkitagenthelper.o -MD -MP -MF $(DEPDIR)/polkit_agent_helper_1-polkitagenthelper.Tpo -c -o polkit_agent_helper_1-polkitagenthelper.o `test -f 'polkitagenthelper.c' || echo '$(srcdir)/'`polkitagenthelper.c +-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/polkit_agent_helper_1-polkitagenthelper.Tpo $(DEPDIR)/polkit_agent_helper_1-polkitagenthelper.Po ++polkit_agent_helper_1-polkitagenthelperprivate.o: polkitagenthelperprivate.c ++@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(polkit_agent_helper_1_CFLAGS) $(CFLAGS) -MT polkit_agent_helper_1-polkitagenthelperprivate.o -MD -MP -MF $(DEPDIR)/polkit_agent_helper_1-polkitagenthelperprivate.Tpo -c -o polkit_agent_helper_1-polkitagenthelperprivate.o `test -f 'polkitagenthelperprivate.c' || echo '$(srcdir)/'`polkitagenthelperprivate.c ++@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/polkit_agent_helper_1-polkitagenthelperprivate.Tpo $(DEPDIR)/polkit_agent_helper_1-polkitagenthelperprivate.Po ++@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='polkitagenthelperprivate.c' object='polkit_agent_helper_1-polkitagenthelperprivate.o' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(polkit_agent_helper_1_CFLAGS) $(CFLAGS) -c -o polkit_agent_helper_1-polkitagenthelperprivate.o `test -f 'polkitagenthelperprivate.c' || echo '$(srcdir)/'`polkitagenthelperprivate.c ++ ++polkit_agent_helper_1-polkitagenthelperprivate.obj: polkitagenthelperprivate.c ++@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(polkit_agent_helper_1_CFLAGS) $(CFLAGS) -MT polkit_agent_helper_1-polkitagenthelperprivate.obj -MD -MP -MF $(DEPDIR)/polkit_agent_helper_1-polkitagenthelperprivate.Tpo -c -o polkit_agent_helper_1-polkitagenthelperprivate.obj `if test -f 'polkitagenthelperprivate.c'; then $(CYGPATH_W) 'polkitagenthelperprivate.c'; else $(CYGPATH_W) '$(srcdir)/polkitagenthelperprivate.c'; fi` ++@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/polkit_agent_helper_1-polkitagenthelperprivate.Tpo $(DEPDIR)/polkit_agent_helper_1-polkitagenthelperprivate.Po ++@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='polkitagenthelperprivate.c' object='polkit_agent_helper_1-polkitagenthelperprivate.obj' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(polkit_agent_helper_1_CFLAGS) $(CFLAGS) -c -o polkit_agent_helper_1-polkitagenthelperprivate.obj `if test -f 'polkitagenthelperprivate.c'; then $(CYGPATH_W) 'polkitagenthelperprivate.c'; else $(CYGPATH_W) '$(srcdir)/polkitagenthelperprivate.c'; fi` ++ ++polkit_agent_helper_1-polkitagenthelper-pam.o: polkitagenthelper-pam.c ++@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(polkit_agent_helper_1_CFLAGS) $(CFLAGS) -MT polkit_agent_helper_1-polkitagenthelper-pam.o -MD -MP -MF $(DEPDIR)/polkit_agent_helper_1-polkitagenthelper-pam.Tpo -c -o polkit_agent_helper_1-polkitagenthelper-pam.o `test -f 'polkitagenthelper-pam.c' || echo '$(srcdir)/'`polkitagenthelper-pam.c ++@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/polkit_agent_helper_1-polkitagenthelper-pam.Tpo $(DEPDIR)/polkit_agent_helper_1-polkitagenthelper-pam.Po ++@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='polkitagenthelper-pam.c' object='polkit_agent_helper_1-polkitagenthelper-pam.o' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(polkit_agent_helper_1_CFLAGS) $(CFLAGS) -c -o polkit_agent_helper_1-polkitagenthelper-pam.o `test -f 'polkitagenthelper-pam.c' || echo '$(srcdir)/'`polkitagenthelper-pam.c ++ ++polkit_agent_helper_1-polkitagenthelper-pam.obj: polkitagenthelper-pam.c ++@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(polkit_agent_helper_1_CFLAGS) $(CFLAGS) -MT polkit_agent_helper_1-polkitagenthelper-pam.obj -MD -MP -MF $(DEPDIR)/polkit_agent_helper_1-polkitagenthelper-pam.Tpo -c -o polkit_agent_helper_1-polkitagenthelper-pam.obj `if test -f 'polkitagenthelper-pam.c'; then $(CYGPATH_W) 'polkitagenthelper-pam.c'; else $(CYGPATH_W) '$(srcdir)/polkitagenthelper-pam.c'; fi` ++@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/polkit_agent_helper_1-polkitagenthelper-pam.Tpo $(DEPDIR)/polkit_agent_helper_1-polkitagenthelper-pam.Po ++@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='polkitagenthelper-pam.c' object='polkit_agent_helper_1-polkitagenthelper-pam.obj' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(polkit_agent_helper_1_CFLAGS) $(CFLAGS) -c -o polkit_agent_helper_1-polkitagenthelper-pam.obj `if test -f 'polkitagenthelper-pam.c'; then $(CYGPATH_W) 'polkitagenthelper-pam.c'; else $(CYGPATH_W) '$(srcdir)/polkitagenthelper-pam.c'; fi` ++ ++polkit_agent_helper_1-polkitagenthelper-shadow.o: polkitagenthelper-shadow.c ++@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(polkit_agent_helper_1_CFLAGS) $(CFLAGS) -MT polkit_agent_helper_1-polkitagenthelper-shadow.o -MD -MP -MF $(DEPDIR)/polkit_agent_helper_1-polkitagenthelper-shadow.Tpo -c -o polkit_agent_helper_1-polkitagenthelper-shadow.o `test -f 'polkitagenthelper-shadow.c' || echo '$(srcdir)/'`polkitagenthelper-shadow.c ++@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/polkit_agent_helper_1-polkitagenthelper-shadow.Tpo $(DEPDIR)/polkit_agent_helper_1-polkitagenthelper-shadow.Po + @am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='polkitagenthelper.c' object='polkit_agent_helper_1-polkitagenthelper.o' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='polkitagenthelper-shadow.c' object='polkit_agent_helper_1-polkitagenthelper-shadow.o' libtool=no @AMDEPBACKSLASH@ + @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(polkit_agent_helper_1_CFLAGS) $(CFLAGS) -c -o polkit_agent_helper_1-polkitagenthelper.o `test -f 'polkitagenthelper.c' || echo '$(srcdir)/'`polkitagenthelper.c ++@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(polkit_agent_helper_1_CFLAGS) $(CFLAGS) -c -o polkit_agent_helper_1-polkitagenthelper-shadow.o `test -f 'polkitagenthelper-shadow.c' || echo '$(srcdir)/'`polkitagenthelper-shadow.c + +-polkit_agent_helper_1-polkitagenthelper.obj: polkitagenthelper.c +-@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(polkit_agent_helper_1_CFLAGS) $(CFLAGS) -MT polkit_agent_helper_1-polkitagenthelper.obj -MD -MP -MF $(DEPDIR)/polkit_agent_helper_1-polkitagenthelper.Tpo -c -o polkit_agent_helper_1-polkitagenthelper.obj `if test -f 'polkitagenthelper.c'; then $(CYGPATH_W) 'polkitagenthelper.c'; else $(CYGPATH_W) '$(srcdir)/polkitagenthelper.c'; fi` +-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/polkit_agent_helper_1-polkitagenthelper.Tpo $(DEPDIR)/polkit_agent_helper_1-polkitagenthelper.Po ++polkit_agent_helper_1-polkitagenthelper-shadow.obj: polkitagenthelper-shadow.c ++@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(polkit_agent_helper_1_CFLAGS) $(CFLAGS) -MT polkit_agent_helper_1-polkitagenthelper-shadow.obj -MD -MP -MF $(DEPDIR)/polkit_agent_helper_1-polkitagenthelper-shadow.Tpo -c -o polkit_agent_helper_1-polkitagenthelper-shadow.obj `if test -f 'polkitagenthelper-shadow.c'; then $(CYGPATH_W) 'polkitagenthelper-shadow.c'; else $(CYGPATH_W) '$(srcdir)/polkitagenthelper-shadow.c'; fi` ++@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/polkit_agent_helper_1-polkitagenthelper-shadow.Tpo $(DEPDIR)/polkit_agent_helper_1-polkitagenthelper-shadow.Po + @am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='polkitagenthelper.c' object='polkit_agent_helper_1-polkitagenthelper.obj' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='polkitagenthelper-shadow.c' object='polkit_agent_helper_1-polkitagenthelper-shadow.obj' libtool=no @AMDEPBACKSLASH@ + @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(polkit_agent_helper_1_CFLAGS) $(CFLAGS) -c -o polkit_agent_helper_1-polkitagenthelper.obj `if test -f 'polkitagenthelper.c'; then $(CYGPATH_W) 'polkitagenthelper.c'; else $(CYGPATH_W) '$(srcdir)/polkitagenthelper.c'; fi` ++@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(polkit_agent_helper_1_CFLAGS) $(CFLAGS) -c -o polkit_agent_helper_1-polkitagenthelper-shadow.obj `if test -f 'polkitagenthelper-shadow.c'; then $(CYGPATH_W) 'polkitagenthelper-shadow.c'; else $(CYGPATH_W) '$(srcdir)/polkitagenthelper-shadow.c'; fi` + + mostlyclean-libtool: + -rm -f *.lo +diff -Naur polkit-0.96/src/polkitagent/polkitagenthelper.c polkit-0.96.patch/src/polkitagent/polkitagenthelper.c +--- polkit-0.96/src/polkitagent/polkitagenthelper.c 2009-10-21 19:07:51.000000000 +0200 ++++ polkit-0.96.patch/src/polkitagent/polkitagenthelper.c 1970-01-01 01:00:00.000000000 +0100 +@@ -1,339 +0,0 @@ +-/* +- * Copyright (C) 2008 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 +- */ +- +-#include "config.h" +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +- +-#ifdef HAVE_SOLARIS +-# define LOG_AUTHPRIV (10<<3) +-#endif +- +-#ifndef HAVE_CLEARENV +-extern char **environ; +- +-static int +-clearenv (void) +-{ +- if (environ != NULL) +- environ[0] = NULL; +- return 0; +-} +-#endif +- +-/* Development aid: define PAH_DEBUG to get debugging output. Do _NOT_ +- * enable this in production builds; it may leak passwords and other +- * sensitive information. +- */ +-#undef PAH_DEBUG +-// #define PAH_DEBUG +- +-static gboolean send_dbus_message (const char *cookie, const char *user); +- +-static int conversation_function (int n, const struct pam_message **msg, struct pam_response **resp, void *data); +- +-int +-main (int argc, char *argv[]) +-{ +- int rc; +- const char *user_to_auth; +- const char *cookie; +- struct pam_conv pam_conversation; +- pam_handle_t *pam_h; +- const void *authed_user; +- +- rc = 0; +- pam_h = NULL; +- +- /* clear the entire environment to avoid attacks using with libraries honoring environment variables */ +- if (clearenv () != 0) +- goto error; +- +- /* set a minimal environment */ +- setenv ("PATH", "/usr/sbin:/usr/bin:/sbin:/bin", 1); +- +- /* check that we are setuid root */ +- if (geteuid () != 0) +- { +- fprintf (stderr, "polkit-agent-helper-1: needs to be setuid root\n"); +- goto error; +- } +- +- openlog ("polkit-agent-helper-1", LOG_CONS | LOG_PID, LOG_AUTHPRIV); +- +- /* check for correct invocation */ +- if (argc != 3) +- { +- syslog (LOG_NOTICE, "inappropriate use of helper, wrong number of arguments [uid=%d]", getuid ()); +- fprintf (stderr, "polkit-agent-helper-1: wrong number of arguments. This incident has been logged.\n"); +- goto error; +- } +- +- user_to_auth = argv[1]; +- cookie = argv[2]; +- +- if (getuid () != 0) +- { +- /* check we're running with a non-tty stdin */ +- if (isatty (STDIN_FILENO) != 0) +- { +- syslog (LOG_NOTICE, "inappropriate use of helper, stdin is a tty [uid=%d]", getuid ()); +- fprintf (stderr, "polkit-agent-helper-1: inappropriate use of helper, stdin is a tty. This incident has been logged.\n"); +- goto error; +- } +- } +- +-#ifdef PAH_DEBUG +- fprintf (stderr, "polkit-agent-helper-1: user to auth is '%s'.\n", user_to_auth); +-#endif /* PAH_DEBUG */ +- +- pam_conversation.conv = conversation_function; +- pam_conversation.appdata_ptr = NULL; +- +- /* start the pam stack */ +- rc = pam_start ("polkit-1", +- user_to_auth, +- &pam_conversation, +- &pam_h); +- if (rc != PAM_SUCCESS) +- { +- fprintf (stderr, "polkit-agent-helper-1: pam_start failed: %s\n", pam_strerror (pam_h, rc)); +- goto error; +- } +- +- /* set the requesting user */ +- rc = pam_set_item (pam_h, PAM_RUSER, user_to_auth); +- if (rc != PAM_SUCCESS) +- { +- fprintf (stderr, "polkit-agent-helper-1: pam_set_item failed: %s\n", pam_strerror (pam_h, rc)); +- goto error; +- } +- +- /* is user really user? */ +- rc = pam_authenticate (pam_h, 0); +- if (rc != PAM_SUCCESS) +- { +- fprintf (stderr, "polkit-agent-helper-1: pam_authenticated failed: %s\n", pam_strerror (pam_h, rc)); +- goto error; +- } +- +- /* permitted access? */ +- rc = pam_acct_mgmt (pam_h, 0); +- if (rc != PAM_SUCCESS) +- { +- fprintf (stderr, "polkit-agent-helper-1: pam_acct_mgmt failed: %s\n", pam_strerror (pam_h, rc)); +- goto error; +- } +- +- /* did we auth the right user? */ +- rc = pam_get_item (pam_h, PAM_USER, &authed_user); +- if (rc != PAM_SUCCESS) +- { +- fprintf (stderr, "polkit-agent-helper-1: pam_get_item failed: %s\n", pam_strerror (pam_h, rc)); +- goto error; +- } +- +- if (strcmp (authed_user, user_to_auth) != 0) +- { +- fprintf (stderr, "polkit-agent-helper-1: Tried to auth user '%s' but we got auth for user '%s' instead", +- user_to_auth, (const char *) authed_user); +- goto error; +- } +- +-#ifdef PAH_DEBUG +- fprintf (stderr, "polkit-agent-helper-1: successfully authenticated user '%s'.\n", user_to_auth); +-#endif /* PAH_DEBUG */ +- +- pam_end (pam_h, rc); +- pam_h = NULL; +- +-#ifdef PAH_DEBUG +- fprintf (stderr, "polkit-agent-helper-1: sending D-Bus message to PolicyKit daemon\n"); +-#endif /* PAH_DEBUG */ +- +- /* now send a D-Bus message to the PolicyKit daemon that +- * includes a) the cookie; and b) the user we authenticated +- */ +- if (!send_dbus_message (cookie, user_to_auth)) +- { +-#ifdef PAH_DEBUG +- fprintf (stderr, "polkit-agent-helper-1: error sending D-Bus message to PolicyKit daemon\n"); +-#endif /* PAH_DEBUG */ +- goto error; +- } +- +-#ifdef PAH_DEBUG +- fprintf (stderr, "polkit-agent-helper-1: successfully sent D-Bus message to PolicyKit daemon\n"); +-#endif /* PAH_DEBUG */ +- +- fprintf (stdout, "SUCCESS\n"); +- fflush (stdout); +- fflush (stderr); +- usleep (10 * 1000); /* since fflush(3) seems buggy */ +- return 0; +- +-error: +- if (pam_h != NULL) +- pam_end (pam_h, rc); +- +- fprintf (stdout, "FAILURE\n"); +- fflush (stdout); +- fflush (stderr); +- usleep (10 * 1000); /* since fflush(3) seems buggy */ +- return 1; +-} +- +-static int +-conversation_function (int n, const struct pam_message **msg, struct pam_response **resp, void *data) +-{ +- struct pam_response *aresp; +- char buf[PAM_MAX_RESP_SIZE]; +- int i; +- +- data = data; +- if (n <= 0 || n > PAM_MAX_NUM_MSG) +- return PAM_CONV_ERR; +- +- if ((aresp = calloc(n, sizeof *aresp)) == NULL) +- return PAM_BUF_ERR; +- +- for (i = 0; i < n; ++i) +- { +- aresp[i].resp_retcode = 0; +- aresp[i].resp = NULL; +- switch (msg[i]->msg_style) +- { +- +- case PAM_PROMPT_ECHO_OFF: +- fprintf (stdout, "PAM_PROMPT_ECHO_OFF "); +- goto conv1; +- +- case PAM_PROMPT_ECHO_ON: +- fprintf (stdout, "PAM_PROMPT_ECHO_ON "); +- conv1: +- fputs (msg[i]->msg, stdout); +- if (strlen (msg[i]->msg) > 0 && msg[i]->msg[strlen (msg[i]->msg) - 1] != '\n') +- fputc ('\n', stdout); +- fflush (stdout); +- +- if (fgets (buf, sizeof buf, stdin) == NULL) +- goto error; +- +- if (strlen (buf) > 0 && +- buf[strlen (buf) - 1] == '\n') +- buf[strlen (buf) - 1] = '\0'; +- +- aresp[i].resp = strdup (buf); +- if (aresp[i].resp == NULL) +- goto error; +- break; +- +- case PAM_ERROR_MSG: +- fprintf (stdout, "PAM_ERROR_MSG "); +- goto conv2; +- +- case PAM_TEXT_INFO: +- fprintf (stdout, "PAM_TEXT_INFO "); +- conv2: +- fputs (msg[i]->msg, stdout); +- if (strlen (msg[i]->msg) > 0 && +- msg[i]->msg[strlen (msg[i]->msg) - 1] != '\n') +- fputc ('\n', stdout); +- fflush (stdout); +- break; +- +- default: +- goto error; +- } +- } +- +- *resp = aresp; +- return PAM_SUCCESS; +- +-error: +- +- for (i = 0; i < n; ++i) +- { +- if (aresp[i].resp != NULL) { +- memset (aresp[i].resp, 0, strlen(aresp[i].resp)); +- free (aresp[i].resp); +- } +- } +- memset (aresp, 0, n * sizeof *aresp); +- *resp = NULL; +- return PAM_CONV_ERR; +-} +- +-static gboolean +-send_dbus_message (const char *cookie, const char *user) +-{ +- PolkitAuthority *authority; +- PolkitIdentity *identity; +- GError *error; +- gboolean ret; +- +- ret = FALSE; +- +- error = NULL; +- +- g_type_init (); +- +- authority = polkit_authority_get (); +- +- identity = polkit_unix_user_new_for_name (user, &error); +- if (identity == NULL) +- { +- g_printerr ("Error constructing identity: %s\n", error->message); +- g_error_free (error); +- goto out; +- } +- +- if (!polkit_authority_authentication_agent_response_sync (authority, +- cookie, +- identity, +- NULL, +- &error)) +- { +- g_printerr ("polkit-agent-helper-1: error response to PolicyKit daemon: %s\n", error->message); +- g_error_free (error); +- goto out; +- } +- +- ret = TRUE; +- +- out: +- +- if (identity != NULL) +- g_object_unref (identity); +- +- if (authority != NULL) +- g_object_unref (authority); +- +- return ret; +-} +diff -Naur polkit-0.96/src/polkitagent/polkitagenthelper-pam.c polkit-0.96.patch/src/polkitagent/polkitagenthelper-pam.c +--- polkit-0.96/src/polkitagent/polkitagenthelper-pam.c 1970-01-01 01:00:00.000000000 +0100 ++++ polkit-0.96.patch/src/polkitagent/polkitagenthelper-pam.c 2010-09-28 23:57:21.559875461 +0200 +@@ -0,0 +1,264 @@ ++/* ++ * Copyright (C) 2008, 2010 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 ++ */ ++ ++#include "config.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include "polkitagenthelperprivate.h" ++ ++static int conversation_function (int n, const struct pam_message **msg, struct pam_response **resp, void *data); ++ ++int ++main (int argc, char *argv[]) ++{ ++ int rc; ++ const char *user_to_auth; ++ const char *cookie; ++ struct pam_conv pam_conversation; ++ pam_handle_t *pam_h; ++ const void *authed_user; ++ ++ rc = 0; ++ pam_h = NULL; ++ ++ /* clear the entire environment to avoid attacks using with libraries honoring environment variables */ ++ if (clearenv () != 0) ++ goto error; ++ ++ /* set a minimal environment */ ++ setenv ("PATH", "/usr/sbin:/usr/bin:/sbin:/bin", 1); ++ ++ /* check that we are setuid root */ ++ if (geteuid () != 0) ++ { ++ fprintf (stderr, "polkit-agent-helper-1: needs to be setuid root\n"); ++ goto error; ++ } ++ ++ openlog ("polkit-agent-helper-1", LOG_CONS | LOG_PID, LOG_AUTHPRIV); ++ ++ /* check for correct invocation */ ++ if (argc != 3) ++ { ++ syslog (LOG_NOTICE, "inappropriate use of helper, wrong number of arguments [uid=%d]", getuid ()); ++ fprintf (stderr, "polkit-agent-helper-1: wrong number of arguments. This incident has been logged.\n"); ++ goto error; ++ } ++ ++ user_to_auth = argv[1]; ++ cookie = argv[2]; ++ ++ if (getuid () != 0) ++ { ++ /* check we're running with a non-tty stdin */ ++ if (isatty (STDIN_FILENO) != 0) ++ { ++ syslog (LOG_NOTICE, "inappropriate use of helper, stdin is a tty [uid=%d]", getuid ()); ++ fprintf (stderr, "polkit-agent-helper-1: inappropriate use of helper, stdin is a tty. This incident has been logged.\n"); ++ goto error; ++ } ++ } ++ ++#ifdef PAH_DEBUG ++ fprintf (stderr, "polkit-agent-helper-1: user to auth is '%s'.\n", user_to_auth); ++#endif /* PAH_DEBUG */ ++ ++ pam_conversation.conv = conversation_function; ++ pam_conversation.appdata_ptr = NULL; ++ ++ /* start the pam stack */ ++ rc = pam_start ("polkit-1", ++ user_to_auth, ++ &pam_conversation, ++ &pam_h); ++ if (rc != PAM_SUCCESS) ++ { ++ fprintf (stderr, "polkit-agent-helper-1: pam_start failed: %s\n", pam_strerror (pam_h, rc)); ++ goto error; ++ } ++ ++ /* set the requesting user */ ++ rc = pam_set_item (pam_h, PAM_RUSER, user_to_auth); ++ if (rc != PAM_SUCCESS) ++ { ++ fprintf (stderr, "polkit-agent-helper-1: pam_set_item failed: %s\n", pam_strerror (pam_h, rc)); ++ goto error; ++ } ++ ++ /* is user really user? */ ++ rc = pam_authenticate (pam_h, 0); ++ if (rc != PAM_SUCCESS) ++ { ++ fprintf (stderr, "polkit-agent-helper-1: pam_authenticated failed: %s\n", pam_strerror (pam_h, rc)); ++ goto error; ++ } ++ ++ /* permitted access? */ ++ rc = pam_acct_mgmt (pam_h, 0); ++ if (rc != PAM_SUCCESS) ++ { ++ fprintf (stderr, "polkit-agent-helper-1: pam_acct_mgmt failed: %s\n", pam_strerror (pam_h, rc)); ++ goto error; ++ } ++ ++ /* did we auth the right user? */ ++ rc = pam_get_item (pam_h, PAM_USER, &authed_user); ++ if (rc != PAM_SUCCESS) ++ { ++ fprintf (stderr, "polkit-agent-helper-1: pam_get_item failed: %s\n", pam_strerror (pam_h, rc)); ++ goto error; ++ } ++ ++ if (strcmp (authed_user, user_to_auth) != 0) ++ { ++ fprintf (stderr, "polkit-agent-helper-1: Tried to auth user '%s' but we got auth for user '%s' instead", ++ user_to_auth, (const char *) authed_user); ++ goto error; ++ } ++ ++#ifdef PAH_DEBUG ++ fprintf (stderr, "polkit-agent-helper-1: successfully authenticated user '%s'.\n", user_to_auth); ++#endif /* PAH_DEBUG */ ++ ++ pam_end (pam_h, rc); ++ pam_h = NULL; ++ ++#ifdef PAH_DEBUG ++ fprintf (stderr, "polkit-agent-helper-1: sending D-Bus message to PolicyKit daemon\n"); ++#endif /* PAH_DEBUG */ ++ ++ /* now send a D-Bus message to the PolicyKit daemon that ++ * includes a) the cookie; and b) the user we authenticated ++ */ ++ if (!send_dbus_message (cookie, user_to_auth)) ++ { ++#ifdef PAH_DEBUG ++ fprintf (stderr, "polkit-agent-helper-1: error sending D-Bus message to PolicyKit daemon\n"); ++#endif /* PAH_DEBUG */ ++ goto error; ++ } ++ ++#ifdef PAH_DEBUG ++ fprintf (stderr, "polkit-agent-helper-1: successfully sent D-Bus message to PolicyKit daemon\n"); ++#endif /* PAH_DEBUG */ ++ ++ fprintf (stdout, "SUCCESS\n"); ++ flush_and_wait(); ++ return 0; ++ ++error: ++ if (pam_h != NULL) ++ pam_end (pam_h, rc); ++ ++ fprintf (stdout, "FAILURE\n"); ++ flush_and_wait(); ++ return 1; ++} ++ ++static int ++conversation_function (int n, const struct pam_message **msg, struct pam_response **resp, void *data) ++{ ++ struct pam_response *aresp; ++ char buf[PAM_MAX_RESP_SIZE]; ++ int i; ++ ++ data = data; ++ if (n <= 0 || n > PAM_MAX_NUM_MSG) ++ return PAM_CONV_ERR; ++ ++ if ((aresp = calloc(n, sizeof *aresp)) == NULL) ++ return PAM_BUF_ERR; ++ ++ for (i = 0; i < n; ++i) ++ { ++ aresp[i].resp_retcode = 0; ++ aresp[i].resp = NULL; ++ switch (msg[i]->msg_style) ++ { ++ ++ case PAM_PROMPT_ECHO_OFF: ++ fprintf (stdout, "PAM_PROMPT_ECHO_OFF "); ++ goto conv1; ++ ++ case PAM_PROMPT_ECHO_ON: ++ fprintf (stdout, "PAM_PROMPT_ECHO_ON "); ++ conv1: ++ fputs (msg[i]->msg, stdout); ++ if (strlen (msg[i]->msg) > 0 && msg[i]->msg[strlen (msg[i]->msg) - 1] != '\n') ++ fputc ('\n', stdout); ++ fflush (stdout); ++ ++ if (fgets (buf, sizeof buf, stdin) == NULL) ++ goto error; ++ ++ if (strlen (buf) > 0 && ++ buf[strlen (buf) - 1] == '\n') ++ buf[strlen (buf) - 1] = '\0'; ++ ++ aresp[i].resp = strdup (buf); ++ if (aresp[i].resp == NULL) ++ goto error; ++ break; ++ ++ case PAM_ERROR_MSG: ++ fprintf (stdout, "PAM_ERROR_MSG "); ++ goto conv2; ++ ++ case PAM_TEXT_INFO: ++ fprintf (stdout, "PAM_TEXT_INFO "); ++ conv2: ++ fputs (msg[i]->msg, stdout); ++ if (strlen (msg[i]->msg) > 0 && ++ msg[i]->msg[strlen (msg[i]->msg) - 1] != '\n') ++ fputc ('\n', stdout); ++ fflush (stdout); ++ break; ++ ++ default: ++ goto error; ++ } ++ } ++ ++ *resp = aresp; ++ return PAM_SUCCESS; ++ ++error: ++ ++ for (i = 0; i < n; ++i) ++ { ++ if (aresp[i].resp != NULL) { ++ memset (aresp[i].resp, 0, strlen(aresp[i].resp)); ++ free (aresp[i].resp); ++ } ++ } ++ memset (aresp, 0, n * sizeof *aresp); ++ *resp = NULL; ++ return PAM_CONV_ERR; ++} ++ +diff -Naur polkit-0.96/src/polkitagent/polkitagenthelperprivate.c polkit-0.96.patch/src/polkitagent/polkitagenthelperprivate.c +--- polkit-0.96/src/polkitagent/polkitagenthelperprivate.c 1970-01-01 01:00:00.000000000 +0100 ++++ polkit-0.96.patch/src/polkitagent/polkitagenthelperprivate.c 2010-09-28 23:57:22.074877607 +0200 +@@ -0,0 +1,97 @@ ++/* ++ * Copyright (C) 2009-2010 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., 51 Franklin Street, Fifth Floor, ++ * Boston, MA 02110-1301, USA. ++ * ++ * Authors: David Zeuthen , ++ * Andrew Psaltis ++ */ ++ ++#include "polkitagenthelperprivate.h" ++#include ++ ++#ifndef HAVE_CLEARENV ++extern char **environ; ++ ++static int ++clearenv (void) ++{ ++ if (environ != NULL) ++ environ[0] = NULL; ++ return 0; ++} ++#endif ++ ++ ++gboolean ++send_dbus_message (const char *cookie, const char *user) ++{ ++ PolkitAuthority *authority; ++ PolkitIdentity *identity; ++ GError *error; ++ gboolean ret; ++ ++ ret = FALSE; ++ ++ error = NULL; ++ ++ g_type_init (); ++ ++ authority = polkit_authority_get (); ++ ++ identity = polkit_unix_user_new_for_name (user, &error); ++ if (identity == NULL) ++ { ++ g_printerr ("Error constructing identity: %s\n", error->message); ++ g_error_free (error); ++ goto out; ++ } ++ ++ if (!polkit_authority_authentication_agent_response_sync (authority, ++ cookie, ++ identity, ++ NULL, ++ &error)) ++ { ++ g_printerr ("polkit-agent-helper-1: error response to PolicyKit daemon: %s\n", error->message); ++ g_error_free (error); ++ goto out; ++ } ++ ++ ret = TRUE; ++ ++ out: ++ ++ if (identity != NULL) ++ g_object_unref (identity); ++ ++ if (authority != NULL) ++ g_object_unref (authority); ++ ++ return ret; ++} ++ ++/* fflush(3) stdin and stdout and wait a little bit. ++ * This replaces the three-line commands at the bottom of ++ * polkit-agent-helper-1's main() function. ++ */ ++void ++flush_and_wait () ++{ ++ fflush (stdout); ++ fflush (stderr); ++ usleep (10 * 1000); /* since fflush(3) seems buggy */ ++} +diff -Naur polkit-0.96/src/polkitagent/polkitagenthelperprivate.h polkit-0.96.patch/src/polkitagent/polkitagenthelperprivate.h +--- polkit-0.96/src/polkitagent/polkitagenthelperprivate.h 1970-01-01 01:00:00.000000000 +0100 ++++ polkit-0.96.patch/src/polkitagent/polkitagenthelperprivate.h 2010-09-28 23:57:22.075877241 +0200 +@@ -0,0 +1,42 @@ ++/* ++ * Copyright (C) 2009-2010 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., 51 Franklin Street, Fifth Floor, ++ * Boston, MA 02110-1301, USA. ++ * ++ * Authors: David Zeuthen , ++ * Andrew Psaltis ++ */ ++#ifndef __POLKIT_AGENT_HELPER_PRIVATE_H ++#define __POLKIT_AGENT_HELPER_PRIVATE_H ++ ++#include ++ ++/* Development aid: define PAH_DEBUG to get debugging output. Do _NOT_ ++ * enable this in production builds; it may leak passwords and other ++ * sensitive information. ++ */ ++#undef PAH_DEBUG ++// #define PAH_DEBUG ++ ++#ifdef HAVE_SOLARIS ++# define LOG_AUTHPRIV (10<<3) ++#endif ++ ++gboolean send_dbus_message (const char *cookie, const char *user); ++ ++void flush_and_wait (); ++ ++#endif /* __POLKIT_AGENT_HELPER_PRIVATE_H */ +diff -Naur polkit-0.96/src/polkitagent/polkitagenthelper-shadow.c polkit-0.96.patch/src/polkitagent/polkitagenthelper-shadow.c +--- polkit-0.96/src/polkitagent/polkitagenthelper-shadow.c 1970-01-01 01:00:00.000000000 +0100 ++++ polkit-0.96.patch/src/polkitagent/polkitagenthelper-shadow.c 2010-09-28 23:57:22.071876889 +0200 +@@ -0,0 +1,189 @@ ++/* ++ * Copyright (C) 2008 Red Hat, Inc. ++ * Copyright (C) 2009-2010 Andrew Psaltis ++ * ++ * 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. ++ * ++ * Authors: Andrew Psaltis , based on ++ * polkitagenthelper.c which was written by ++ * David Zeuthen ++ */ ++ ++#include "config.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include "polkitagenthelperprivate.h" ++ ++ ++extern char *crypt (); ++static int shadow_authenticate (struct spwd *shadow); ++ ++int ++main (int argc, char *argv[]) ++{ ++ struct spwd *shadow; ++ const char *user_to_auth; ++ const char *cookie; ++ time_t tm; ++ ++ /* clear the entire environment to avoid attacks with ++ libraries honoring environment variables */ ++ if (clearenv () != 0) ++ goto error; ++ ++ /* set a minimal environment */ ++ setenv ("PATH", "/usr/sbin:/usr/bin:/sbin:/bin", 1); ++ ++ /* check that we are setuid root */ ++ if (geteuid () != 0) ++ { ++ fprintf (stderr, "polkit-agent-helper-1: needs to be setuid root\n"); ++ goto error; ++ } ++ ++ openlog ("polkit-agent-helper-1", LOG_CONS | LOG_PID, LOG_AUTHPRIV); ++ ++ /* check for correct invocation */ ++ if (argc != 3) ++ { ++ syslog (LOG_NOTICE, "inappropriate use of helper, wrong number of arguments [uid=%d]", getuid ()); ++ fprintf (stderr, "polkit-agent-helper-1: wrong number of arguments. This incident has been logged.\n"); ++ goto error; ++ } ++ ++ if (getuid () != 0) ++ { ++ /* check we're running with a non-tty stdin */ ++ if (isatty (STDIN_FILENO) != 0) ++ { ++ syslog (LOG_NOTICE, "inappropriate use of helper, stdin is a tty [uid=%d]", getuid ()); ++ fprintf (stderr, "polkit-agent-helper-1: inappropriate use of helper, stdin is a tty. This incident has been logged.\n"); ++ goto error; ++ } ++ } ++ ++ user_to_auth = argv[1]; ++ cookie = argv[2]; ++ ++#ifdef PAH_DEBUG ++ fprintf (stderr, "polkit-agent-helper-1: user to auth is '%s'.\n", user_to_auth); ++#endif /* PAH_DEBUG */ ++ ++ /* Ask shadow about the user requesting authentication */ ++ if ((shadow = getspnam (user_to_auth)) == NULL) ++ { ++ syslog (LOG_NOTICE, "shadow file data information request for user %s [uid=%d] failed", user_to_auth, getuid()); ++ fprintf(stderr, "polkit-agent-helper-1: could not get shadow information for%.100s", user_to_auth); ++ goto error; ++ } ++ ++ /* Check the user's identity */ ++ if(!shadow_authenticate (shadow)) ++ { ++ syslog (LOG_NOTICE, "authentication failure [uid=%d] trying to authenticate '%s'", getuid (), user_to_auth); ++ fprintf (stderr, "polkit-agent-helper-1: authentication failure. This incident has been logged.\n"); ++ goto error; ++ } ++ ++ /* Check whether the user's password has expired */ ++ time(&tm); ++ if( shadow->sp_max >= 0 && (shadow->sp_lstchg + shadow->sp_max) * 60 * 60 * 24 <= tm) ++ { ++ syslog (LOG_NOTICE, "password expired for user '%s' [uid=%d] trying to authenticate", user_to_auth, getuid () ); ++ fprintf (stderr, "polkit-agent-helper-1: authorization failure. This incident has been logged.\n"); ++ goto error; ++ } ++ ++ /* Check whether the user's password has aged (and account expired along ++ * with it) ++ */ ++ if( shadow->sp_inact >= 0 && (shadow->sp_lstchg + shadow->sp_max + shadow->sp_inact) * 60 * 60 * 24 <= tm) ++ { ++ syslog (LOG_NOTICE, "password aged for user '%s' [uid=%d] trying to authenticate", user_to_auth, getuid () ); ++ fprintf (stderr, "polkit-agent-helper-1: authorization failure. This incident has been logged.\n"); ++ goto error; ++ } ++ ++ /* Check whether the user's account has expired */ ++ if(shadow->sp_expire >= 0 && shadow->sp_expire * 60 * 60 * 24 <= tm) ++ { ++ syslog (LOG_NOTICE, "account expired for user '%s' [uid=%d] trying to authenticate", user_to_auth, getuid () ); ++ fprintf (stderr, "polkit-agent-helper-1: authorization failure. This incident has been logged.\n"); ++ goto error; ++ } ++ ++#ifdef PAH_DEBUG ++ fprintf (stderr, "polkit-agent-helper-1: sending D-Bus message to PolicyKit daemon\n"); ++#endif /* PAH_DEBUG */ ++ ++ /* now send a D-Bus message to the PolicyKit daemon that ++ * includes a) the cookie; and b) the user we authenticated ++ */ ++ if (!send_dbus_message (cookie, user_to_auth)) ++ { ++#ifdef PAH_DEBUG ++ fprintf (stderr, "polkit-agent-helper-1: error sending D-Bus message to PolicyKit daemon\n"); ++#endif /* PAH_DEBUG */ ++ goto error; ++ } ++ ++#ifdef PAH_DEBUG ++ fprintf (stderr, "polkit-agent-helper-1: successfully sent D-Bus message to PolicyKit daemon\n"); ++#endif /* PAH_DEBUG */ ++ ++ fprintf (stdout, "SUCCESS\n"); ++ flush_and_wait(); ++ return 0; ++ ++error: ++ fprintf (stdout, "FAILURE\n"); ++ flush_and_wait(); ++ return 1; ++} ++ ++static int ++shadow_authenticate(struct spwd *shadow) ++{ ++ /* Speak PAM to the daemon, thanks to David Zeuthen for the idea. */ ++ char passwd[512]; ++ fprintf(stdout, "PAM_PROMPT_ECHO_OFF password:\n"); ++ fflush(stdout); ++ usleep (10 * 1000); /* since fflush(3) seems buggy */ ++ ++ if (fgets (passwd, sizeof (passwd), stdin) == NULL) ++ goto error; ++ ++ if (strlen (passwd) > 0 && passwd[strlen (passwd) - 1] == '\n') ++ passwd[strlen (passwd) - 1] = '\0'; ++ ++ if (strcmp (shadow->sp_pwdp, crypt (passwd, shadow->sp_pwdp)) != 0) ++ goto error; ++ return 1; ++error: ++ return 0; ++} ++ +diff -Naur polkit-0.96/src/programs/pkexec.c polkit-0.96.patch/src/programs/pkexec.c +--- polkit-0.96/src/programs/pkexec.c 2009-12-15 20:04:15.000000000 +0100 ++++ polkit-0.96.patch/src/programs/pkexec.c 2010-09-28 23:57:22.077877347 +0200 +@@ -34,7 +34,11 @@ + #include + #include + #include ++ ++#ifdef POLKIT_AUTHFW_PAM + #include ++#endif /* POLKIT_AUTHFW_PAM */ ++ + #include + #include + +@@ -115,6 +119,7 @@ + + /* ---------------------------------------------------------------------------------------------------- */ + ++#ifdef POLKIT_AUTHFW_PAM + static int + pam_conversation_function (int n, + const struct pam_message **msg, +@@ -167,6 +172,7 @@ + pam_end (pam_h, rc); + return ret; + } ++#endif /* POLKIT_AUTHFW_PAM */ + + /* ---------------------------------------------------------------------------------------------------- */ + +@@ -742,11 +748,13 @@ + * TODO: The question here is whether we should clear the limits before applying them? + * As evident above, neither su(1) (and, for that matter, nor sudo(8)) does this. + */ ++#ifdef POLKIT_AUTHW_PAM + if (!open_session (pw->pw_name)) + { + goto out; + } +- ++#endif /* POLKIT_AUTHFW_PAM */ ++ + /* become the user */ + if (setgroups (0, NULL) != 0) + { +diff -Naur polkit-0.96/src/programs/pkexec.c.orig polkit-0.96.patch/src/programs/pkexec.c.orig +--- polkit-0.96/src/programs/pkexec.c.orig 1970-01-01 01:00:00.000000000 +0100 ++++ polkit-0.96.patch/src/programs/pkexec.c.orig 2009-12-15 20:04:15.000000000 +0100 +@@ -0,0 +1,819 @@ ++/* ++ * Copyright (C) 2008 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 ++ */ ++ ++#ifdef HAVE_CONFIG_H ++# include "config.h" ++#endif ++ ++#define _GNU_SOURCE ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++static gchar *original_user_name = NULL; ++static gchar *original_cwd = NULL; ++static gchar *command_line = NULL; ++static struct passwd *pw; ++ ++#ifndef HAVE_CLEARENV ++extern char **environ; ++ ++static int ++clearenv (void) ++{ ++ if (environ != NULL) ++ environ[0] = NULL; ++ return 0; ++} ++#endif ++ ++static void ++usage (int argc, char *argv[]) ++{ ++ g_printerr ("pkexec --version |\n" ++ " --help |\n" ++ " [--user username] PROGRAM [ARGUMENTS...]\n" ++ "\n" ++ "See the pkexec manual page for more details.\n"); ++} ++ ++/* ---------------------------------------------------------------------------------------------------- */ ++ ++static void ++log_message (gint level, ++ gboolean print_to_stderr, ++ const gchar *format, ++ ...) ++{ ++ static gboolean is_log_open = FALSE; ++ va_list var_args; ++ gchar *s; ++ const gchar *tty; ++ ++ if (!is_log_open) ++ { ++ openlog ("pkexec", ++ LOG_PID, ++ LOG_AUTHPRIV); /* security/authorization messages (private) */ ++ is_log_open = TRUE; ++ } ++ ++ va_start (var_args, format); ++ s = g_strdup_vprintf (format, var_args); ++ va_end (var_args); ++ ++ tty = ttyname (0); ++ if (tty == NULL) ++ tty = "unknown"; ++ ++ /* first complain to syslog */ ++ syslog (level, ++ "%s: %s [USER=%s] [TTY=%s] [CWD=%s] [COMMAND=%s]", ++ original_user_name, ++ s, ++ pw->pw_name, ++ tty, ++ original_cwd, ++ command_line); ++ ++ /* and then on stderr */ ++ if (print_to_stderr) ++ g_printerr ("%s\n", s); ++ ++ g_free (s); ++} ++ ++/* ---------------------------------------------------------------------------------------------------- */ ++ ++static int ++pam_conversation_function (int n, ++ const struct pam_message **msg, ++ struct pam_response **resp, ++ void *data) ++{ ++ g_assert_not_reached (); ++ return PAM_CONV_ERR; ++} ++ ++static gboolean ++open_session (const gchar *user_to_auth) ++{ ++ gboolean ret; ++ gint rc; ++ pam_handle_t *pam_h; ++ struct pam_conv conversation; ++ ++ ret = FALSE; ++ ++ pam_h = NULL; ++ ++ conversation.conv = pam_conversation_function; ++ conversation.appdata_ptr = NULL; ++ ++ /* start the pam stack */ ++ rc = pam_start ("polkit-1", ++ user_to_auth, ++ &conversation, ++ &pam_h); ++ if (rc != PAM_SUCCESS) ++ { ++ g_printerr ("pam_start() failed: %s\n", pam_strerror (pam_h, rc)); ++ goto out; ++ } ++ ++ /* open a session */ ++ rc = pam_open_session (pam_h, ++ 0); /* flags */ ++ if (rc != PAM_SUCCESS) ++ { ++ g_printerr ("pam_open_session() failed: %s\n", pam_strerror (pam_h, rc)); ++ goto out; ++ } ++ ++ ret = TRUE; ++ ++out: ++ if (pam_h != NULL) ++ pam_end (pam_h, rc); ++ return ret; ++} ++ ++/* ---------------------------------------------------------------------------------------------------- */ ++ ++typedef gboolean (*FdCallback) (gint fd, gpointer user_data); ++ ++static gboolean ++set_close_on_exec (gint fd, ++ gpointer user_data) ++{ ++ gint fd_bottom; ++ ++ fd_bottom = GPOINTER_TO_INT (user_data); ++ ++ if (fd >= fd_bottom) ++ { ++ if (fcntl (fd, F_SETFD, FD_CLOEXEC) != 0 && errno != EBADF) ++ { ++ return FALSE; ++ } ++ } ++ ++ return TRUE; ++} ++ ++static gboolean ++fdwalk (FdCallback callback, ++ gpointer user_data) ++{ ++ gint fd; ++ gint max_fd; ++ ++ g_return_val_if_fail (callback != NULL, FALSE); ++ ++ max_fd = sysconf (_SC_OPEN_MAX); ++ for (fd = 0; fd < max_fd; fd++) ++ { ++ if (!callback (fd, user_data)) ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++/* ---------------------------------------------------------------------------------------------------- */ ++ ++static gchar * ++find_action_for_path (PolkitAuthority *authority, ++ const gchar *path) ++{ ++ GList *l; ++ GList *actions; ++ gchar *action_id; ++ GError *error; ++ ++ actions = NULL; ++ action_id = NULL; ++ error = NULL; ++ ++ actions = polkit_authority_enumerate_actions_sync (authority, ++ NULL, ++ &error); ++ if (actions == NULL) ++ { ++ g_warning ("Error enumerating actions: %s", error->message); ++ g_error_free (error); ++ goto out; ++ } ++ ++ for (l = actions; l != NULL; l = l->next) ++ { ++ PolkitActionDescription *action_desc = POLKIT_ACTION_DESCRIPTION (l->data); ++ const gchar *path_for_action; ++ ++ path_for_action = polkit_action_description_get_annotation (action_desc, "org.freedesktop.policykit.exec.path"); ++ if (path_for_action == NULL) ++ continue; ++ ++ if (g_strcmp0 (path_for_action, path) == 0) ++ { ++ action_id = g_strdup (polkit_action_description_get_action_id (action_desc)); ++ goto out; ++ } ++ } ++ ++ out: ++ g_list_foreach (actions, (GFunc) g_object_unref, NULL); ++ g_list_free (actions); ++ ++ /* Fall back to org.freedesktop.policykit.exec */ ++ ++ if (action_id == NULL) ++ action_id = g_strdup ("org.freedesktop.policykit.exec"); ++ ++ return action_id; ++} ++ ++/* ---------------------------------------------------------------------------------------------------- */ ++ ++static gboolean ++is_valid_shell (const gchar *shell) ++{ ++ gboolean ret; ++ gchar *contents; ++ gchar **shells; ++ GError *error; ++ guint n; ++ ++ ret = FALSE; ++ ++ contents = NULL; ++ shells = NULL; ++ ++ error = NULL; ++ if (!g_file_get_contents ("/etc/shells", ++ &contents, ++ NULL, /* gsize *length */ ++ &error)) ++ { ++ g_printerr ("Error getting contents of /etc/shells: %s\n", error->message); ++ g_error_free (error); ++ goto out; ++ } ++ ++ shells = g_strsplit (contents, "\n", 0); ++ for (n = 0; shells != NULL && shells[n] != NULL; n++) ++ { ++ if (g_strcmp0 (shell, shells[n]) == 0) ++ { ++ ret = TRUE; ++ goto out; ++ } ++ } ++ ++ out: ++ g_free (contents); ++ g_strfreev (shells); ++ return ret; ++} ++ ++static gboolean ++validate_environment_variable (const gchar *key, ++ const gchar *value) ++{ ++ gboolean ret; ++ ++ /* Generally we bail if any environment variable value contains ++ * ++ * - '/' characters ++ * - '%' characters ++ * - '..' substrings ++ */ ++ ++ g_return_val_if_fail (key != NULL, FALSE); ++ g_return_val_if_fail (value != NULL, FALSE); ++ ++ ret = FALSE; ++ ++ /* special case $SHELL */ ++ if (g_strcmp0 (key, "SHELL") == 0) ++ { ++ /* check if it's in /etc/shells */ ++ if (!is_valid_shell (value)) ++ { ++ log_message (LOG_CRIT, TRUE, ++ "The value for the SHELL variable was not found the /etc/shells file"); ++ g_printerr ("\n" ++ "This incident has been reported.\n"); ++ goto out; ++ } ++ } ++ else if (strstr (value, "/") != NULL || ++ strstr (value, "%") != NULL || ++ strstr (value, "..") != NULL) ++ { ++ log_message (LOG_CRIT, TRUE, ++ "The value for environment variable %s contains suscipious content", ++ key); ++ g_printerr ("\n" ++ "This incident has been reported.\n"); ++ goto out; ++ } ++ ++ ret = TRUE; ++ ++ out: ++ return ret; ++} ++ ++/* ---------------------------------------------------------------------------------------------------- */ ++ ++int ++main (int argc, char *argv[]) ++{ ++ guint n; ++ guint ret; ++ gint rc; ++ gboolean opt_show_help; ++ gboolean opt_show_version; ++ PolkitAuthority *authority; ++ PolkitAuthorizationResult *result; ++ PolkitSubject *subject; ++ PolkitDetails *details; ++ GError *error; ++ gchar *action_id; ++ gchar **exec_argv; ++ gchar *path; ++ struct passwd pwstruct; ++ gchar pwbuf[8192]; ++ gchar *s; ++ const gchar *environment_variables_to_save[] = { ++ "SHELL", ++ "LANG", ++ "LINGUAS", ++ "LANGUAGE", ++ "LC_COLLATE", ++ "LC_CTYPE", ++ "LC_MESSAGES", ++ "LC_MONETARY", ++ "LC_NUMERIC", ++ "LC_TIME", ++ "LC_ALL", ++ "TERM", ++ "COLORTERM", ++ ++ /* For now, avoiding pretend that running X11 apps as another user in the same session ++ * will ever work... See ++ * ++ * https://bugs.freedesktop.org/show_bug.cgi?id=17970#c26 ++ * ++ * and surrounding comments for a lot of discussion about this. ++ */ ++#if 0 ++ "DESKTOP_STARTUP_ID", ++ "DISPLAY", ++ "XAUTHORITY", ++ "DBUS_SESSION_BUS_ADDRESS", ++ "ORBIT_SOCKETDIR", ++#endif ++ NULL ++ }; ++ GPtrArray *saved_env; ++ gchar *opt_user; ++ pid_t pid_of_caller; ++ uid_t uid_of_caller; ++ struct stat statbuf; ++ ++ ret = 127; ++ authority = NULL; ++ subject = NULL; ++ details = NULL; ++ result = NULL; ++ action_id = NULL; ++ saved_env = NULL; ++ path = NULL; ++ command_line = NULL; ++ opt_user = NULL; ++ ++ /* check for correct invocation */ ++ if (geteuid () != 0) ++ { ++ g_printerr ("pkexec must be setuid root\n"); ++ goto out; ++ } ++ ++ original_user_name = g_strdup (g_get_user_name ()); ++ if (original_user_name == NULL) ++ { ++ g_printerr ("Error getting user name.\n"); ++ goto out; ++ } ++ ++ original_cwd = g_strdup (get_current_dir_name ()); ++ if (original_cwd == NULL) ++ { ++ g_printerr ("Error getting cwd.\n"); ++ goto out; ++ } ++ ++ /* First process options and find the command-line to invoke. Avoid using fancy library routines ++ * that depend on environtment variables since we haven't cleared the environment just yet. ++ */ ++ opt_show_help = FALSE; ++ opt_show_version = FALSE; ++ for (n = 1; n < (guint) argc; n++) ++ { ++ if (strcmp (argv[n], "--help") == 0) ++ { ++ opt_show_help = TRUE; ++ } ++ else if (strcmp (argv[n], "--version") == 0) ++ { ++ opt_show_version = TRUE; ++ } ++ else if (strcmp (argv[n], "--user") == 0 || strcmp (argv[n], "-u") == 0) ++ { ++ n++; ++ if (n >= (guint) argc) ++ { ++ usage (argc, argv); ++ goto out; ++ } ++ ++ opt_user = g_strdup (argv[n]); ++ } ++ else ++ { ++ break; ++ } ++ } ++ ++ if (opt_show_help) ++ { ++ usage (argc, argv); ++ ret = 0; ++ goto out; ++ } ++ else if (opt_show_version) ++ { ++ g_print ("pkexec version %s\n", PACKAGE_VERSION); ++ ret = 0; ++ goto out; ++ } ++ ++ if (opt_user == NULL) ++ opt_user = g_strdup ("root"); ++ ++ /* Now figure out the command-line to run - argv is guaranteed to be NULL-terminated, see ++ * ++ * http://lkml.indiana.edu/hypermail/linux/kernel/0409.2/0287.html ++ * ++ * but do check this is the case. ++ * ++ * We also try to locate the program in the path if a non-absolute path is given. ++ */ ++ g_assert (argv[argc] == NULL); ++ path = g_strdup (argv[n]); ++ if (path == NULL) ++ { ++ usage (argc, argv); ++ goto out; ++ } ++ if (path[0] != '/') ++ { ++ /* g_find_program_in_path() is not suspectible to attacks via the environment */ ++ s = g_find_program_in_path (path); ++ if (s == NULL) ++ { ++ g_printerr ("Cannot run program %s: %s\n", path, strerror (ENOENT)); ++ goto out; ++ } ++ g_free (path); ++ argv[n] = path = s; ++ } ++ if (stat (path, &statbuf) != 0) ++ { ++ g_printerr ("Error getting information about %s: %s\n", path, g_strerror (errno)); ++ goto out; ++ } ++ command_line = g_strjoinv (" ", argv + n); ++ exec_argv = argv + n; ++ ++ /* Look up information about the user we care about - yes, the return ++ * value of this function is a bit funky ++ */ ++ rc = getpwnam_r (opt_user, &pwstruct, pwbuf, sizeof pwbuf, &pw); ++ if (rc == 0 && pw == NULL) ++ { ++ g_printerr ("User `%s' does not exist.\n", opt_user); ++ goto out; ++ } ++ else if (pw == NULL) ++ { ++ g_printerr ("Error getting information for user `%s': %s\n", opt_user, g_strerror (rc)); ++ goto out; ++ } ++ ++ /* now save the environment variables we care about */ ++ saved_env = g_ptr_array_new (); ++ for (n = 0; environment_variables_to_save[n] != NULL; n++) ++ { ++ const gchar *key = environment_variables_to_save[n]; ++ const gchar *value; ++ ++ value = g_getenv (key); ++ if (value == NULL) ++ continue; ++ ++ /* To qualify for the paranoia goldstar - we validate the value of each ++ * environment variable passed through - this is to attempt to avoid ++ * exploits in (potentially broken) programs launched via pkexec(1). ++ */ ++ if (!validate_environment_variable (key, value)) ++ goto out; ++ ++ g_ptr_array_add (saved_env, g_strdup (key)); ++ g_ptr_array_add (saved_env, g_strdup (value)); ++ } ++ ++ /* Nuke the environment to get a well-known and sanitized environment to avoid attacks ++ * via e.g. the DBUS_SYSTEM_BUS_ADDRESS environment variable and similar. ++ */ ++ if (clearenv () != 0) ++ { ++ g_printerr ("Error clearing environment: %s\n", g_strerror (errno)); ++ goto out; ++ } ++ ++ /* Initialize the GLib type system - this is needed to interact with the ++ * PolicyKit daemon ++ */ ++ g_type_init (); ++ ++ /* now check if the program that invoked us is authorized */ ++ 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); get process group leader instead - for example, this ++ * happens when launching via gnome-panel (alt+f2, then 'pkexec gedit'). ++ */ ++ pid_of_caller = getpgrp (); ++ } ++ ++ subject = polkit_unix_process_new (pid_of_caller); ++ if (subject == NULL) ++ { ++ g_printerr ("No such process for pid %d: %s\n", (gint) pid_of_caller, error->message); ++ g_error_free (error); ++ goto out; ++ } ++ ++ /* paranoia: check that the uid of pid_of_caller matches getuid() */ ++ error = NULL; ++ uid_of_caller = polkit_unix_process_get_owner (POLKIT_UNIX_PROCESS (subject), ++ &error); ++ if (error != NULL) ++ { ++ g_printerr ("Error determing pid of caller (pid %d): %s\n", (gint) pid_of_caller, error->message); ++ g_error_free (error); ++ goto out; ++ } ++ if (uid_of_caller != getuid ()) ++ { ++ g_printerr ("User of caller (%d) does not match our uid (%d)\n", uid_of_caller, getuid ()); ++ goto out; ++ } ++ ++ authority = polkit_authority_get (); ++ ++ details = polkit_details_new (); ++ ++ polkit_details_insert (details, "command-line", command_line); ++ s = g_strdup_printf ("%s (%s)", pw->pw_gecos, pw->pw_name); ++ polkit_details_insert (details, "user", s); ++ g_free (s); ++ s = g_strdup_printf ("%d", (gint) pw->pw_uid); ++ polkit_details_insert (details, "uid", s); ++ g_free (s); ++ polkit_details_insert (details, "program", path); ++ ++ action_id = find_action_for_path (authority, path); ++ g_assert (action_id != NULL); ++ ++ error = NULL; ++ result = polkit_authority_check_authorization_sync (authority, ++ subject, ++ action_id, ++ details, ++ POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, ++ NULL, ++ &error); ++ if (result == NULL) ++ { ++ g_printerr ("Error checking for authorization %s: %s\n", ++ action_id, ++ error->message); ++ goto out; ++ } ++ ++ if (polkit_authorization_result_get_is_authorized (result)) ++ { ++ /* do nothing */ ++ } ++ 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; ++ } ++ else ++ { ++ log_message (LOG_WARNING, TRUE, ++ "Error executing command as another user: Not authorized"); ++ g_printerr ("\n" ++ "This incident has been reported.\n"); ++ goto out; ++ } ++ ++ /* Set PATH to a safe list */ ++ g_ptr_array_add (saved_env, g_strdup ("PATH")); ++ if (pw->pw_uid != 0) ++ s = g_strdup_printf ("/usr/bin:/bin:/usr/sbin:/sbin:%s/bin", pw->pw_dir); ++ else ++ s = g_strdup_printf ("/usr/sbin:/usr/bin:/sbin:/bin:%s/bin", pw->pw_dir); ++ g_ptr_array_add (saved_env, s); ++ g_ptr_array_add (saved_env, g_strdup ("LOGNAME")); ++ g_ptr_array_add (saved_env, g_strdup (pw->pw_name)); ++ g_ptr_array_add (saved_env, g_strdup ("USER")); ++ g_ptr_array_add (saved_env, g_strdup (pw->pw_name)); ++ g_ptr_array_add (saved_env, g_strdup ("HOME")); ++ g_ptr_array_add (saved_env, g_strdup (pw->pw_dir)); ++ ++ s = g_strdup_printf ("%d", getuid ()); ++ g_ptr_array_add (saved_env, g_strdup ("PKEXEC_UID")); ++ g_ptr_array_add (saved_env, s); ++ ++ /* set the environment */ ++ for (n = 0; n < saved_env->len - 1; n += 2) ++ { ++ const gchar *key = saved_env->pdata[n]; ++ const gchar *value = saved_env->pdata[n + 1]; ++ ++ if (!g_setenv (key, value, TRUE)) ++ { ++ g_printerr ("Error setting environment variable %s to '%s': %s\n", ++ key, ++ value, ++ g_strerror (errno)); ++ goto out; ++ } ++ } ++ ++ /* set close_on_exec on all file descriptors except stdin, stdout, stderr */ ++ if (!fdwalk (set_close_on_exec, GINT_TO_POINTER (3))) ++ { ++ g_printerr ("Error setting close-on-exec for file desriptors\n"); ++ goto out; ++ } ++ ++ /* if not changing to uid 0, become uid 0 before changing to the user */ ++ if (pw->pw_uid != 0) ++ { ++ setreuid (0, 0); ++ if ((geteuid () != 0) || (getuid () != 0)) ++ { ++ g_printerr ("Error becoming uid 0: %s\n", g_strerror (errno)); ++ goto out; ++ } ++ } ++ ++ /* open session - with PAM enabled, this runs the open_session() part of the PAM ++ * stack - this includes applying limits via pam_limits.so but also other things ++ * requested via the current PAM configuration. ++ * ++ * NOTE NOTE NOTE: pam_limits.so doesn't seem to clear existing limits - e.g. ++ * ++ * $ ulimit -t ++ * unlimited ++ * ++ * $ su - ++ * Password: ++ * # ulimit -t ++ * unlimited ++ * # logout ++ * ++ * $ ulimit -t 1000 ++ * $ ulimit -t ++ * 1000 ++ * $ su - ++ * Password: ++ * # ulimit -t ++ * 1000 ++ * ++ * TODO: The question here is whether we should clear the limits before applying them? ++ * As evident above, neither su(1) (and, for that matter, nor sudo(8)) does this. ++ */ ++ if (!open_session (pw->pw_name)) ++ { ++ goto out; ++ } ++ ++ /* become the user */ ++ if (setgroups (0, NULL) != 0) ++ { ++ g_printerr ("Error setting groups: %s\n", g_strerror (errno)); ++ goto out; ++ } ++ if (initgroups (pw->pw_name, pw->pw_gid) != 0) ++ { ++ g_printerr ("Error initializing groups for %s: %s\n", pw->pw_name, g_strerror (errno)); ++ 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_printerr ("Error becoming real+effective uid %d and gid %d: %s\n", pw->pw_uid, pw->pw_gid, g_strerror (errno)); ++ goto out; ++ } ++ ++ /* change to home directory */ ++ if (chdir (pw->pw_dir) != 0) ++ { ++ g_printerr ("Error changing to home directory %s: %s\n", pw->pw_dir, g_strerror (errno)); ++ goto out; ++ } ++ ++ /* Log the fact that we're executing a command */ ++ log_message (LOG_NOTICE, FALSE, "Executing command"); ++ ++ /* exec the program */ ++ if (execv (path, exec_argv) != 0) ++ { ++ g_printerr ("Error executing %s: %s\n", path, g_strerror (errno)); ++ goto out; ++ } ++ ++ /* if exec doesn't fail, it never returns... */ ++ g_assert_not_reached (); ++ ++ out: ++ if (result != NULL) ++ g_object_unref (result); ++ ++ g_free (action_id); ++ ++ if (details != NULL) ++ g_object_unref (details); ++ ++ if (subject != NULL) ++ g_object_unref (subject); ++ ++ if (authority != NULL) ++ g_object_unref (authority); ++ ++ if (saved_env != NULL) ++ { ++ g_ptr_array_foreach (saved_env, (GFunc) g_free, NULL); ++ g_ptr_array_free (saved_env, TRUE); ++ } ++ ++ g_free (path); ++ g_free (command_line); ++ g_free (opt_user); ++ g_free (original_user_name); ++ g_free (original_cwd); ++ ++ return ret; ++} ++