From 0e45b7f2c241bdb9e1f3a7f02ae4f31f0d46d2b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Mr=C3=A1z?= Date: Thu, 29 Oct 2009 15:32:22 +0000 Subject: [PATCH 01/12] - pam_xauth: set the approprate context when creating .xauth files (#531530) --- pam-1.1.0-xauth-context.patch | 92 +++++++++++++++++++++++++++++++++++ pam.spec | 7 ++- 2 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 pam-1.1.0-xauth-context.patch diff --git a/pam-1.1.0-xauth-context.patch b/pam-1.1.0-xauth-context.patch new file mode 100644 index 0000000..91c08ba --- /dev/null +++ b/pam-1.1.0-xauth-context.patch @@ -0,0 +1,92 @@ +diff -up Linux-PAM-1.1.0/modules/pam_xauth/Makefile.am.xauth-context Linux-PAM-1.1.0/modules/pam_xauth/Makefile.am +--- Linux-PAM-1.1.0/modules/pam_xauth/Makefile.am.xauth-context 2006-06-09 18:44:08.000000000 +0200 ++++ Linux-PAM-1.1.0/modules/pam_xauth/Makefile.am 2009-10-29 14:34:18.000000000 +0100 +@@ -16,7 +16,7 @@ secureconfdir = $(SCONFIGDIR) + + AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include + AM_LDFLAGS = -no-undefined -avoid-version -module \ +- -L$(top_builddir)/libpam -lpam ++ -L$(top_builddir)/libpam -lpam @LIBSELINUX@ + if HAVE_VERSIONING + AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map + endif +diff -up Linux-PAM-1.1.0/modules/pam_xauth/pam_xauth.c.xauth-context Linux-PAM-1.1.0/modules/pam_xauth/pam_xauth.c +--- Linux-PAM-1.1.0/modules/pam_xauth/pam_xauth.c.xauth-context 2009-04-09 10:07:29.000000000 +0200 ++++ Linux-PAM-1.1.0/modules/pam_xauth/pam_xauth.c 2009-10-29 16:13:21.000000000 +0100 +@@ -57,6 +57,12 @@ + #include + #include + ++#ifdef WITH_SELINUX ++#include ++#include ++#include ++#endif ++ + #define DATANAME "pam_xauth_cookie_file" + #define XAUTHENV "XAUTHORITY" + #define HOMEENV "HOME" +@@ -461,6 +467,10 @@ pam_sm_open_session (pam_handle_t *pamh, + getuid(), getgid(), + xauth, "-f", cookiefile, "nlist", display, + NULL) == 0) { ++ int save_errno; ++#ifdef WITH_SELINUX ++ security_context_t context = NULL; ++#endif + /* Check that we got a cookie. If not, we get creative. */ + if (((cookie == NULL) || (strlen(cookie) == 0)) && + ((strncmp(display, "localhost:", 10) == 0) || +@@ -545,12 +555,41 @@ pam_sm_open_session (pam_handle_t *pamh, + /* Generate a new file to hold the data. */ + euid = geteuid(); + setfsuid(tpwd->pw_uid); +- fd = mkstemp(xauthority + strlen(XAUTHENV) + 1); ++ ++#ifdef WITH_SELINUX ++ if (is_selinux_enabled() > 0) { ++ struct selabel_handle *ctx = selabel_open(SELABEL_CTX_FILE, NULL, 0); ++ if (ctx != NULL) { ++ if (selabel_lookup(ctx, &context, ++ xauthority + sizeof(XAUTHENV), S_IFREG) != 0) { ++ pam_syslog(pamh, LOG_WARNING, ++ "could not get SELinux label for '%s'", ++ xauthority + sizeof(XAUTHENV)); ++ } ++ selabel_close(ctx); ++ if (setfscreatecon(context)) { ++ pam_syslog(pamh, LOG_WARNING, ++ "setfscreatecon(%s) failed: %m", context); ++ } ++ } ++ } ++ fd = mkstemp(xauthority + sizeof(XAUTHENV)); ++ save_errno = errno; ++ if (context != NULL) { ++ free(context); ++ setfscreatecon(NULL); ++ } ++#else ++ fd = mkstemp(xauthority + sizeof(XAUTHENV)); ++ save_errno = errno; ++#endif ++ + setfsuid(euid); + if (fd == -1) { ++ errno = save_errno; + pam_syslog(pamh, LOG_ERR, + "error creating temporary file `%s': %m", +- xauthority + strlen(XAUTHENV) + 1); ++ xauthority + sizeof(XAUTHENV)); + retval = PAM_SESSION_ERR; + goto cleanup; + } +@@ -563,7 +602,7 @@ pam_sm_open_session (pam_handle_t *pamh, + /* Get a copy of the filename to save as a data item for + * removal at session-close time. */ + free(cookiefile); +- cookiefile = strdup(xauthority + strlen(XAUTHENV) + 1); ++ cookiefile = strdup(xauthority + sizeof(XAUTHENV)); + + /* Save the filename. */ + if (pam_set_data(pamh, DATANAME, cookiefile, cleanup) != PAM_SUCCESS) { diff --git a/pam.spec b/pam.spec index 1676b5a..738acb2 100644 --- a/pam.spec +++ b/pam.spec @@ -3,7 +3,7 @@ Summary: An extensible library which provides authentication for applications Name: pam Version: 1.1.0 -Release: 5%{?dist} +Release: 6%{?dist} # The library is BSD licensed with option to relicense as GPLv2+ - this option is redundant # as the BSD license allows that anyway. pam_timestamp and pam_console modules are GPLv2+, License: BSD and GPLv2+ @@ -26,6 +26,7 @@ Patch2: pam-1.0.91-std-noclose.patch Patch3: pam-1.1.0-cracklib-authtok.patch Patch4: pam-1.1.0-console-nochmod.patch Patch5: pam-1.1.0-notally.patch +Patch6: pam-1.1.0-xauth-context.patch %define _sbindir /sbin %define _moduledir /%{_lib}/security @@ -91,6 +92,7 @@ mv pam-redhat-%{pam_redhat_version}/* modules %patch3 -p1 -b .authtok %patch4 -p1 -b .nochmod %patch5 -p1 -b .notally +%patch6 -p1 -b .xauth-context libtoolize -f autoreconf @@ -323,6 +325,9 @@ fi %doc doc/adg/*.txt doc/adg/html %changelog +* Thu Oct 29 2009 Tomas Mraz 1.1.0-6 +- pam_xauth: set the approprate context when creating .xauth files (#531530) + * Tue Sep 1 2009 Tomas Mraz 1.1.0-5 - do not change permissions with pam_console_apply - drop obsolete pam_tally module and the faillog file (#461258) From 430b952f8e781f57f9b863c7cddbd4112f0bfc7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Mr=C3=A1z?= Date: Mon, 2 Nov 2009 07:56:12 +0000 Subject: [PATCH 02/12] - pam_console: fix memory corruption when executing handlers (patch by Stas Sergeev) and a few more fixes in the handler execution code (#532302) --- pam-1.1.0-console-fixes.patch | 71 +++++++++++++++++++++++++++++++++++ pam.spec | 8 +++- 2 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 pam-1.1.0-console-fixes.patch diff --git a/pam-1.1.0-console-fixes.patch b/pam-1.1.0-console-fixes.patch new file mode 100644 index 0000000..08cd4c6 --- /dev/null +++ b/pam-1.1.0-console-fixes.patch @@ -0,0 +1,71 @@ +diff -up Linux-PAM-1.1.0/modules/pam_console/handlers.c.consolefix Linux-PAM-1.1.0/modules/pam_console/handlers.c +--- Linux-PAM-1.1.0/modules/pam_console/handlers.c.consolefix 2009-11-02 08:45:24.000000000 +0100 ++++ Linux-PAM-1.1.0/modules/pam_console/handlers.c 2009-11-02 08:50:19.000000000 +0100 +@@ -172,13 +172,13 @@ call_exec(struct console_handler *handle + const char *flagptr; + const char **argv; + int i = 0; +- argv = malloc(sizeof(*argv)*nparams+2); +- ++ argv = malloc(sizeof(*argv)*(nparams+2)); ++ + if (argv == NULL) + return; +- ++ + argv[i++] = handler->executable; +- ++ + for (flagptr = handler->flags; *flagptr != '\0'; flagptr += strlen(flagptr)+1) { + switch (testflag(flagptr)) { + case HF_LOGFAIL: +@@ -231,7 +231,7 @@ execute_handler(pam_handle_t *pamh, stru + } + + sighandler = signal(SIGCHLD, SIG_DFL); +- ++ + child = fork(); + switch (child) { + case -1: +@@ -246,30 +246,31 @@ execute_handler(pam_handle_t *pamh, stru + if (!wait_exit) { + switch(fork()) { + case 0: +- exit(0); ++ if(setsid() == -1) { ++ _exit(255); ++ } ++ break; + case -1: +- exit(255); ++ _exit(255); + default: +- if(setsid() == -1) { +- exit(255); +- } ++ _exit(0); + } + } + if (set_uid) { + struct passwd *pw; + pw = getpwnam(user); + if (pw == NULL) +- exit(255); ++ _exit(255); + if (setgid(pw->pw_gid) == -1 || + setuid(pw->pw_uid) == -1) +- exit(255); ++ _exit(255); + } + call_exec(handler, nparams, user, tty); +- exit(255); ++ _exit(255); + default: + break; + } +- ++ + waitpid(child, &rv, 0); + + if (sighandler != SIG_ERR) diff --git a/pam.spec b/pam.spec index 738acb2..2f53461 100644 --- a/pam.spec +++ b/pam.spec @@ -3,7 +3,7 @@ Summary: An extensible library which provides authentication for applications Name: pam Version: 1.1.0 -Release: 6%{?dist} +Release: 7%{?dist} # The library is BSD licensed with option to relicense as GPLv2+ - this option is redundant # as the BSD license allows that anyway. pam_timestamp and pam_console modules are GPLv2+, License: BSD and GPLv2+ @@ -27,6 +27,7 @@ Patch3: pam-1.1.0-cracklib-authtok.patch Patch4: pam-1.1.0-console-nochmod.patch Patch5: pam-1.1.0-notally.patch Patch6: pam-1.1.0-xauth-context.patch +Patch7: pam-1.1.0-console-fixes.patch %define _sbindir /sbin %define _moduledir /%{_lib}/security @@ -93,6 +94,7 @@ mv pam-redhat-%{pam_redhat_version}/* modules %patch4 -p1 -b .nochmod %patch5 -p1 -b .notally %patch6 -p1 -b .xauth-context +%patch7 -p1 -b .console-fixes libtoolize -f autoreconf @@ -325,6 +327,10 @@ fi %doc doc/adg/*.txt doc/adg/html %changelog +* Mon Nov 2 2009 Tomas Mraz 1.1.0-7 +- pam_console: fix memory corruption when executing handlers (patch by + Stas Sergeev) and a few more fixes in the handler execution code (#532302) + * Thu Oct 29 2009 Tomas Mraz 1.1.0-6 - pam_xauth: set the approprate context when creating .xauth files (#531530) From d46efed5ad6f44bab1b3347532a888533001a09d Mon Sep 17 00:00:00 2001 From: Bill Nottingham Date: Wed, 25 Nov 2009 23:30:18 +0000 Subject: [PATCH 03/12] Fix typo that causes a failure to update the common directory. (releng #2781) --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index e5b954d..61ba6fb 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,10 @@ # Makefile for source rpm: pam -# $Id: Makefile,v 1.1 2004/09/09 09:46:06 cvsdist Exp $ +# $Id: Makefile,v 1.2 2007/10/15 19:12:34 notting Exp $ NAME := pam SPECFILE = $(firstword $(wildcard *.spec)) define find-makefile-common -for d in common ../common ../../common ; do if [ -f $$d/Makefile.common ] ; then if [ -f $$d/CVS/Root -a -w $$/Makefile.common ] ; then cd $$d ; cvs -Q update ; fi ; echo "$$d/Makefile.common" ; break ; fi ; done +for d in common ../common ../../common ; do if [ -f $$d/Makefile.common ] ; then if [ -f $$d/CVS/Root -a -w $$d/Makefile.common ] ; then cd $$d ; cvs -Q update ; fi ; echo "$$d/Makefile.common" ; break ; fi ; done endef MAKEFILE_COMMON := $(shell $(find-makefile-common)) From 1802942b8d5a5bf211817431f03e95e7c09ad8ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Mr=C3=A1z?= Date: Thu, 17 Dec 2009 14:29:39 +0000 Subject: [PATCH 04/12] - new upstream version with minor changes --- .cvsignore | 2 +- ...r.bz2.sign => Linux-PAM-1.1.1.tar.bz2.sign | 6 +- pam-1.1.0-cracklib-authtok.patch | 42 --------- pam-1.1.0-xauth-context.patch | 92 ------------------- pam.spec | 13 ++- sources | 2 +- 6 files changed, 11 insertions(+), 146 deletions(-) rename Linux-PAM-1.1.0.tar.bz2.sign => Linux-PAM-1.1.1.tar.bz2.sign (61%) delete mode 100644 pam-1.1.0-cracklib-authtok.patch delete mode 100644 pam-1.1.0-xauth-context.patch diff --git a/.cvsignore b/.cvsignore index 6f0cc08..3c6b5b2 100644 --- a/.cvsignore +++ b/.cvsignore @@ -1,4 +1,4 @@ *.src.rpm *.tar.bz2 pam-redhat-0.99.10-1.tar.bz2 -Linux-PAM-1.1.0.tar.bz2 +Linux-PAM-1.1.1.tar.bz2 diff --git a/Linux-PAM-1.1.0.tar.bz2.sign b/Linux-PAM-1.1.1.tar.bz2.sign similarity index 61% rename from Linux-PAM-1.1.0.tar.bz2.sign rename to Linux-PAM-1.1.1.tar.bz2.sign index b0f1840..fad7920 100644 --- a/Linux-PAM-1.1.0.tar.bz2.sign +++ b/Linux-PAM-1.1.1.tar.bz2.sign @@ -2,7 +2,7 @@ Version: GnuPG v1.4.9 (GNU/Linux) Comment: See http://www.kernel.org/signature.html for info -iD8DBQBKO6X0yGugalF9Dw4RAmz7AKCV6q08/CrmPtHX6geM3zrUpeFIIwCfSO12 -WRW5yU2bG4x+Bb0Ie6ppBbk= -=D3mX +iD8DBQBLKOWYyGugalF9Dw4RAqYlAJ9st1NRPyZjWFD+Pl+7ifeiDcDTAwCfeyt7 +l6BKIgA/0NQzw+md5nFXVy4= +=Kxq6 -----END PGP SIGNATURE----- diff --git a/pam-1.1.0-cracklib-authtok.patch b/pam-1.1.0-cracklib-authtok.patch deleted file mode 100644 index 52c842d..0000000 --- a/pam-1.1.0-cracklib-authtok.patch +++ /dev/null @@ -1,42 +0,0 @@ -Index: modules/pam_cracklib/pam_cracklib.c -=================================================================== -RCS file: /cvsroot/pam/Linux-PAM/modules/pam_cracklib/pam_cracklib.c,v -retrieving revision 1.33 -retrieving revision 1.34 -diff -u -p -r1.33 -r1.34 ---- Linux-PAM/modules/pam_cracklib/pam_cracklib.c 11 Dec 2008 19:41:49 -0000 1.33 -+++ Linux-PAM/modules/pam_cracklib/pam_cracklib.c 21 Jul 2009 13:59:24 -0000 1.34 -@@ -545,7 +545,7 @@ static int _pam_unix_approve_pass(pam_ha - const char *pass_new) - { - const char *msg = NULL; -- const void *user; -+ const char *user; - int retval; - - if (pass_new == NULL || (pass_old && !strcmp(pass_old,pass_new))) { -@@ -556,7 +556,7 @@ static int _pam_unix_approve_pass(pam_ha - return PAM_AUTHTOK_ERR; - } - -- retval = pam_get_item(pamh, PAM_USER, &user); -+ retval = pam_get_user(pamh, &user, NULL); - if (retval != PAM_SUCCESS || user == NULL) { - if (ctrl & PAM_DEBUG_ARG) - pam_syslog(pamh,LOG_ERR,"Can not get username"); -@@ -658,6 +658,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_hand - pam_error (pamh, _("BAD PASSWORD: %s"), crack_msg); - if (getuid() || (flags & PAM_CHANGE_EXPIRED_AUTHTOK)) - { -+ pam_set_item (pamh, PAM_AUTHTOK, NULL); - retval = PAM_AUTHTOK_ERR; - continue; - } -@@ -670,6 +671,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_hand - if (retval != PAM_SUCCESS) { - if (getuid() || (flags & PAM_CHANGE_EXPIRED_AUTHTOK)) - { -+ pam_set_item(pamh, PAM_AUTHTOK, NULL); - retval = PAM_AUTHTOK_ERR; - continue; - } diff --git a/pam-1.1.0-xauth-context.patch b/pam-1.1.0-xauth-context.patch deleted file mode 100644 index 91c08ba..0000000 --- a/pam-1.1.0-xauth-context.patch +++ /dev/null @@ -1,92 +0,0 @@ -diff -up Linux-PAM-1.1.0/modules/pam_xauth/Makefile.am.xauth-context Linux-PAM-1.1.0/modules/pam_xauth/Makefile.am ---- Linux-PAM-1.1.0/modules/pam_xauth/Makefile.am.xauth-context 2006-06-09 18:44:08.000000000 +0200 -+++ Linux-PAM-1.1.0/modules/pam_xauth/Makefile.am 2009-10-29 14:34:18.000000000 +0100 -@@ -16,7 +16,7 @@ secureconfdir = $(SCONFIGDIR) - - AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include - AM_LDFLAGS = -no-undefined -avoid-version -module \ -- -L$(top_builddir)/libpam -lpam -+ -L$(top_builddir)/libpam -lpam @LIBSELINUX@ - if HAVE_VERSIONING - AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map - endif -diff -up Linux-PAM-1.1.0/modules/pam_xauth/pam_xauth.c.xauth-context Linux-PAM-1.1.0/modules/pam_xauth/pam_xauth.c ---- Linux-PAM-1.1.0/modules/pam_xauth/pam_xauth.c.xauth-context 2009-04-09 10:07:29.000000000 +0200 -+++ Linux-PAM-1.1.0/modules/pam_xauth/pam_xauth.c 2009-10-29 16:13:21.000000000 +0100 -@@ -57,6 +57,12 @@ - #include - #include - -+#ifdef WITH_SELINUX -+#include -+#include -+#include -+#endif -+ - #define DATANAME "pam_xauth_cookie_file" - #define XAUTHENV "XAUTHORITY" - #define HOMEENV "HOME" -@@ -461,6 +467,10 @@ pam_sm_open_session (pam_handle_t *pamh, - getuid(), getgid(), - xauth, "-f", cookiefile, "nlist", display, - NULL) == 0) { -+ int save_errno; -+#ifdef WITH_SELINUX -+ security_context_t context = NULL; -+#endif - /* Check that we got a cookie. If not, we get creative. */ - if (((cookie == NULL) || (strlen(cookie) == 0)) && - ((strncmp(display, "localhost:", 10) == 0) || -@@ -545,12 +555,41 @@ pam_sm_open_session (pam_handle_t *pamh, - /* Generate a new file to hold the data. */ - euid = geteuid(); - setfsuid(tpwd->pw_uid); -- fd = mkstemp(xauthority + strlen(XAUTHENV) + 1); -+ -+#ifdef WITH_SELINUX -+ if (is_selinux_enabled() > 0) { -+ struct selabel_handle *ctx = selabel_open(SELABEL_CTX_FILE, NULL, 0); -+ if (ctx != NULL) { -+ if (selabel_lookup(ctx, &context, -+ xauthority + sizeof(XAUTHENV), S_IFREG) != 0) { -+ pam_syslog(pamh, LOG_WARNING, -+ "could not get SELinux label for '%s'", -+ xauthority + sizeof(XAUTHENV)); -+ } -+ selabel_close(ctx); -+ if (setfscreatecon(context)) { -+ pam_syslog(pamh, LOG_WARNING, -+ "setfscreatecon(%s) failed: %m", context); -+ } -+ } -+ } -+ fd = mkstemp(xauthority + sizeof(XAUTHENV)); -+ save_errno = errno; -+ if (context != NULL) { -+ free(context); -+ setfscreatecon(NULL); -+ } -+#else -+ fd = mkstemp(xauthority + sizeof(XAUTHENV)); -+ save_errno = errno; -+#endif -+ - setfsuid(euid); - if (fd == -1) { -+ errno = save_errno; - pam_syslog(pamh, LOG_ERR, - "error creating temporary file `%s': %m", -- xauthority + strlen(XAUTHENV) + 1); -+ xauthority + sizeof(XAUTHENV)); - retval = PAM_SESSION_ERR; - goto cleanup; - } -@@ -563,7 +602,7 @@ pam_sm_open_session (pam_handle_t *pamh, - /* Get a copy of the filename to save as a data item for - * removal at session-close time. */ - free(cookiefile); -- cookiefile = strdup(xauthority + strlen(XAUTHENV) + 1); -+ cookiefile = strdup(xauthority + sizeof(XAUTHENV)); - - /* Save the filename. */ - if (pam_set_data(pamh, DATANAME, cookiefile, cleanup) != PAM_SUCCESS) { diff --git a/pam.spec b/pam.spec index 2f53461..cbc7f0e 100644 --- a/pam.spec +++ b/pam.spec @@ -2,8 +2,8 @@ Summary: An extensible library which provides authentication for applications Name: pam -Version: 1.1.0 -Release: 7%{?dist} +Version: 1.1.1 +Release: 1%{?dist} # The library is BSD licensed with option to relicense as GPLv2+ - this option is redundant # as the BSD license allows that anyway. pam_timestamp and pam_console modules are GPLv2+, License: BSD and GPLv2+ @@ -23,10 +23,8 @@ Source13: config-util.5 Source14: 90-nproc.conf Patch1: pam-1.0.90-redhat-modules.patch Patch2: pam-1.0.91-std-noclose.patch -Patch3: pam-1.1.0-cracklib-authtok.patch Patch4: pam-1.1.0-console-nochmod.patch Patch5: pam-1.1.0-notally.patch -Patch6: pam-1.1.0-xauth-context.patch Patch7: pam-1.1.0-console-fixes.patch %define _sbindir /sbin @@ -90,10 +88,8 @@ mv pam-redhat-%{pam_redhat_version}/* modules %patch1 -p1 -b .redhat-modules %patch2 -p1 -b .std-noclose -%patch3 -p1 -b .authtok %patch4 -p1 -b .nochmod %patch5 -p1 -b .notally -%patch6 -p1 -b .xauth-context %patch7 -p1 -b .console-fixes libtoolize -f @@ -180,7 +176,7 @@ install -m755 -d $RPM_BUILD_ROOT/lib/security for dir in modules/pam_* ; do if [ -d ${dir} ] ; then %if ! %{WITH_SELINUX} - [ ${dir} = "modules/pam_selinux" ] && continue + [ ${dir} = "modules/pam_selinux" ] && continue %endif [ ${dir} = "modules/pam_tally" ] && continue if ! ls -1 $RPM_BUILD_ROOT%{_moduledir}/`basename ${dir}`*.so ; then @@ -327,6 +323,9 @@ fi %doc doc/adg/*.txt doc/adg/html %changelog +* Thu Dec 17 2009 Tomas Mraz 1.1.1-1 +- new upstream version with minor changes + * Mon Nov 2 2009 Tomas Mraz 1.1.0-7 - pam_console: fix memory corruption when executing handlers (patch by Stas Sergeev) and a few more fixes in the handler execution code (#532302) diff --git a/sources b/sources index 1b3568e..8210a75 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ c115640346a987356f6b76ec1d425185 pam-redhat-0.99.10-1.tar.bz2 -9cda791c827dfcd9f2888caf0a64cc4a Linux-PAM-1.1.0.tar.bz2 +9b3d952b173d5b9836cbc7e8de108bee Linux-PAM-1.1.1.tar.bz2 From 68bf40d031ee67a75673f2107133138657d4c8fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Mr=C3=A1z?= Date: Mon, 18 Jan 2010 09:09:31 +0000 Subject: [PATCH 05/12] - fix build with disabled audit and SELinux (#556211, #556212) --- pam.spec | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/pam.spec b/pam.spec index cbc7f0e..ea3690b 100644 --- a/pam.spec +++ b/pam.spec @@ -3,7 +3,7 @@ Summary: An extensible library which provides authentication for applications Name: pam Version: 1.1.1 -Release: 1%{?dist} +Release: 2%{?dist} # The library is BSD licensed with option to relicense as GPLv2+ - this option is redundant # as the BSD license allows that anyway. pam_timestamp and pam_console modules are GPLv2+, License: BSD and GPLv2+ @@ -177,6 +177,10 @@ for dir in modules/pam_* ; do if [ -d ${dir} ] ; then %if ! %{WITH_SELINUX} [ ${dir} = "modules/pam_selinux" ] && continue + [ ${dir} = "modules/pam_sepermit" ] && continue +%endif +%if ! %{WITH_AUDIT} + [ ${dir} = "modules/pam_tty_audit" ] && continue %endif [ ${dir} = "modules/pam_tally" ] && continue if ! ls -1 $RPM_BUILD_ROOT%{_moduledir}/`basename ${dir}`*.so ; then @@ -276,7 +280,9 @@ fi %{_moduledir}/pam_tally2.so %{_moduledir}/pam_time.so %{_moduledir}/pam_timestamp.so +%if %{WITH_AUDIT} %{_moduledir}/pam_tty_audit.so +%endif %{_moduledir}/pam_umask.so %{_moduledir}/pam_unix.so %{_moduledir}/pam_unix_acct.so @@ -301,13 +307,15 @@ fi %dir %{_secconfdir}/namespace.d %attr(755,root,root) %config(noreplace) %{_secconfdir}/namespace.init %config(noreplace) %{_secconfdir}/pam_env.conf -%config(noreplace) %{_secconfdir}/sepermit.conf %config(noreplace) %{_secconfdir}/time.conf %config(noreplace) %{_secconfdir}/opasswd %dir %{_secconfdir}/console.apps %dir %{_secconfdir}/console.perms.d %dir /var/run/console +%if %{WITH_SELINUX} +%config(noreplace) %{_secconfdir}/sepermit.conf %dir /var/run/sepermit +%endif %ghost %verify(not md5 size mtime) /var/log/tallylog %{_mandir}/man5/* %{_mandir}/man8/* @@ -323,6 +331,9 @@ fi %doc doc/adg/*.txt doc/adg/html %changelog +* Mon Jan 18 2010 Tomas Mraz 1.1.1-2 +- fix build with disabled audit and SELinux (#556211, #556212) + * Thu Dec 17 2009 Tomas Mraz 1.1.1-1 - new upstream version with minor changes From 3f424c65d31bf2162ce97c41608cdebe9b19ef9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Mr=C3=A1z?= Date: Fri, 22 Jan 2010 17:49:54 +0000 Subject: [PATCH 06/12] - fix wrong prompt when pam_get_authtok is used for new password --- pam-1.1.1-authtok-prompt.patch | 78 ++++++++++++++++++++++++++++++++++ pam.spec | 7 ++- 2 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 pam-1.1.1-authtok-prompt.patch diff --git a/pam-1.1.1-authtok-prompt.patch b/pam-1.1.1-authtok-prompt.patch new file mode 100644 index 0000000..84574ac --- /dev/null +++ b/pam-1.1.1-authtok-prompt.patch @@ -0,0 +1,78 @@ +Index: libpam/pam_get_authtok.c +=================================================================== +RCS file: /cvsroot/pam/Linux-PAM/libpam/pam_get_authtok.c,v +retrieving revision 1.3 +diff -u -p -r1.3 pam_get_authtok.c +--- libpam/pam_get_authtok.c 10 Nov 2009 15:52:20 -0000 1.3 ++++ libpam/pam_get_authtok.c 22 Jan 2010 17:31:40 -0000 +@@ -81,7 +81,7 @@ pam_get_authtok_internal (pam_handle_t * + char *resp[2] = {NULL, NULL}; + const void *prevauthtok; + const char *authtok_type = ""; +- int ask_twice = 0; /* Password change, ask twice for it */ ++ int chpass = 0; /* Password change, ask twice for it */ + int retval; + + if (authtok == NULL) +@@ -91,8 +91,9 @@ pam_get_authtok_internal (pam_handle_t * + which needs to be verified. */ + if (item == PAM_AUTHTOK && pamh->choice == PAM_CHAUTHTOK) + { ++ chpass = 1; + if (!(flags & PAM_GETAUTHTOK_NOVERIFY)) +- ask_twice = 1; ++ ++chpass; + + authtok_type = get_option (pamh, "authtok_type"); + if (authtok_type == NULL) +@@ -110,11 +111,11 @@ pam_get_authtok_internal (pam_handle_t * + return PAM_SUCCESS; + } + else if (get_option (pamh, "use_first_pass") || +- (ask_twice && get_option (pamh, "use_authtok"))) ++ (chpass && get_option (pamh, "use_authtok"))) + { + if (prevauthtok == NULL) + { +- if (ask_twice) ++ if (chpass) + return PAM_AUTHTOK_ERR; + else + return PAM_AUTH_ERR; +@@ -127,16 +128,16 @@ pam_get_authtok_internal (pam_handle_t * + { + retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp[0], + "%s", prompt); +- if (retval == PAM_SUCCESS && ask_twice && resp[0] != NULL) ++ if (retval == PAM_SUCCESS && chpass > 1 && resp[0] != NULL) + retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp[1], + _("Retype %s"), prompt); + } +- else if (ask_twice) ++ else if (chpass) + { + retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp[0], + PROMPT1, authtok_type, + strlen (authtok_type) > 0?" ":""); +- if (retval == PAM_SUCCESS && ask_twice && resp[0] != NULL) ++ if (retval == PAM_SUCCESS && chpass > 1 && resp[0] != NULL) + retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp[1], + PROMPT2, authtok_type, + strlen (authtok_type) > 0?" ":""); +@@ -146,14 +147,14 @@ pam_get_authtok_internal (pam_handle_t * + PROMPT); + + if (retval != PAM_SUCCESS || resp[0] == NULL || +- (ask_twice && resp[1] == NULL)) ++ (chpass > 1 && resp[1] == NULL)) + { + /* We want to abort the password change */ + pam_error (pamh, _("Password change aborted.")); + return PAM_AUTHTOK_ERR; + } + +- if (ask_twice && strcmp (resp[0], resp[1]) != 0) ++ if (chpass > 1 && strcmp (resp[0], resp[1]) != 0) + { + pam_error (pamh, MISTYPED_PASS); + _pam_overwrite (resp[0]); diff --git a/pam.spec b/pam.spec index ea3690b..16acff6 100644 --- a/pam.spec +++ b/pam.spec @@ -3,7 +3,7 @@ Summary: An extensible library which provides authentication for applications Name: pam Version: 1.1.1 -Release: 2%{?dist} +Release: 3%{?dist} # The library is BSD licensed with option to relicense as GPLv2+ - this option is redundant # as the BSD license allows that anyway. pam_timestamp and pam_console modules are GPLv2+, License: BSD and GPLv2+ @@ -26,6 +26,7 @@ Patch2: pam-1.0.91-std-noclose.patch Patch4: pam-1.1.0-console-nochmod.patch Patch5: pam-1.1.0-notally.patch Patch7: pam-1.1.0-console-fixes.patch +Patch8: pam-1.1.1-authtok-prompt.patch %define _sbindir /sbin %define _moduledir /%{_lib}/security @@ -91,6 +92,7 @@ mv pam-redhat-%{pam_redhat_version}/* modules %patch4 -p1 -b .nochmod %patch5 -p1 -b .notally %patch7 -p1 -b .console-fixes +%patch8 -p0 -b .prompt libtoolize -f autoreconf @@ -331,6 +333,9 @@ fi %doc doc/adg/*.txt doc/adg/html %changelog +* Fri Jan 22 2010 Tomas Mraz 1.1.1-3 +- fix wrong prompt when pam_get_authtok is used for new password + * Mon Jan 18 2010 Tomas Mraz 1.1.1-2 - fix build with disabled audit and SELinux (#556211, #556212) From e3430d85d2599cd466dd9f9334d0f8924e2106c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Mr=C3=A1z?= Date: Mon, 15 Feb 2010 17:25:28 +0000 Subject: [PATCH 07/12] - change the default password hash to sha512 --- pam.spec | 5 ++++- password-auth.pamd | 7 ++----- system-auth.pamd | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pam.spec b/pam.spec index 16acff6..956517b 100644 --- a/pam.spec +++ b/pam.spec @@ -3,7 +3,7 @@ Summary: An extensible library which provides authentication for applications Name: pam Version: 1.1.1 -Release: 3%{?dist} +Release: 4%{?dist} # The library is BSD licensed with option to relicense as GPLv2+ - this option is redundant # as the BSD license allows that anyway. pam_timestamp and pam_console modules are GPLv2+, License: BSD and GPLv2+ @@ -333,6 +333,9 @@ fi %doc doc/adg/*.txt doc/adg/html %changelog +* Mon Feb 15 2010 Tomas Mraz 1.1.1-4 +- change the default password hash to sha512 + * Fri Jan 22 2010 Tomas Mraz 1.1.1-3 - fix wrong prompt when pam_get_authtok is used for new password diff --git a/password-auth.pamd b/password-auth.pamd index fef15f6..aee23d0 100644 --- a/password-auth.pamd +++ b/password-auth.pamd @@ -2,16 +2,13 @@ # This file is auto-generated. # User changes will be destroyed the next time authconfig is run. auth required pam_env.so -auth sufficient pam_unix.so nullok try_first_pass +auth sufficient pam_unix.so try_first_pass nullok auth required pam_deny.so account required pam_unix.so -account sufficient pam_localuser.so -account sufficient pam_succeed_if.so uid < 500 quiet -account required pam_permit.so password requisite pam_cracklib.so try_first_pass retry=3 type= -password sufficient pam_unix.so nullok try_first_pass use_authtok +password sufficient pam_unix.so try_first_pass use_authtok nullok sha512 shadow password required pam_deny.so session optional pam_keyinit.so revoke diff --git a/system-auth.pamd b/system-auth.pamd index afd0e67..aee23d0 100644 --- a/system-auth.pamd +++ b/system-auth.pamd @@ -7,8 +7,8 @@ auth required pam_deny.so account required pam_unix.so -password required pam_cracklib.so try_first_pass retry=3 -password sufficient pam_unix.so try_first_pass use_authtok nullok md5 shadow +password requisite pam_cracklib.so try_first_pass retry=3 type= +password sufficient pam_unix.so try_first_pass use_authtok nullok sha512 shadow password required pam_deny.so session optional pam_keyinit.so revoke From 02519fe95b0ee1be9ba1a76a4832ee16e120a8c7 Mon Sep 17 00:00:00 2001 From: Jesse Keating Date: Wed, 17 Feb 2010 02:18:56 +0000 Subject: [PATCH 08/12] Initialize branch F-13 for pam --- branch | 1 + 1 file changed, 1 insertion(+) create mode 100644 branch diff --git a/branch b/branch new file mode 100644 index 0000000..baa94ef --- /dev/null +++ b/branch @@ -0,0 +1 @@ +F-13 From 4b7a0b2c99993d3f0afec9e8756b809e321989eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Mr=C3=A1z?= Date: Thu, 15 Jul 2010 13:24:33 +0000 Subject: [PATCH 09/12] - do not overwrite tallylog with empty file on upgrade --- pam.spec | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pam.spec b/pam.spec index 956517b..5eb71a1 100644 --- a/pam.spec +++ b/pam.spec @@ -3,7 +3,7 @@ Summary: An extensible library which provides authentication for applications Name: pam Version: 1.1.1 -Release: 4%{?dist} +Release: 5%{?dist} # The library is BSD licensed with option to relicense as GPLv2+ - this option is redundant # as the BSD license allows that anyway. pam_timestamp and pam_console modules are GPLv2+, License: BSD and GPLv2+ @@ -208,7 +208,7 @@ rm -rf $RPM_BUILD_ROOT %post /sbin/ldconfig -if [ ! -a /var/log/tallylog ] ; then +if [ ! -e /var/log/tallylog ] ; then install -m 600 /dev/null /var/log/tallylog fi @@ -333,6 +333,9 @@ fi %doc doc/adg/*.txt doc/adg/html %changelog +* Thu Jul 15 2010 Tomas Mraz 1.1.1-5 +- do not overwrite tallylog with empty file on upgrade + * Mon Feb 15 2010 Tomas Mraz 1.1.1-4 - change the default password hash to sha512 From 400d812d7b33668d9d1afd537a428b16886e50e9 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Thu, 29 Jul 2010 05:26:29 +0000 Subject: [PATCH 10/12] dist-git conversion --- .cvsignore => .gitignore | 0 Makefile | 21 --------------------- branch | 1 - 3 files changed, 22 deletions(-) rename .cvsignore => .gitignore (100%) delete mode 100644 Makefile delete mode 100644 branch diff --git a/.cvsignore b/.gitignore similarity index 100% rename from .cvsignore rename to .gitignore diff --git a/Makefile b/Makefile deleted file mode 100644 index 61ba6fb..0000000 --- a/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# Makefile for source rpm: pam -# $Id: Makefile,v 1.2 2007/10/15 19:12:34 notting Exp $ -NAME := pam -SPECFILE = $(firstword $(wildcard *.spec)) - -define find-makefile-common -for d in common ../common ../../common ; do if [ -f $$d/Makefile.common ] ; then if [ -f $$d/CVS/Root -a -w $$d/Makefile.common ] ; then cd $$d ; cvs -Q update ; fi ; echo "$$d/Makefile.common" ; break ; fi ; done -endef - -MAKEFILE_COMMON := $(shell $(find-makefile-common)) - -ifeq ($(MAKEFILE_COMMON),) -# attempt a checkout -define checkout-makefile-common -test -f CVS/Root && { cvs -Q -d $$(cat CVS/Root) checkout common && echo "common/Makefile.common" ; } || { echo "ERROR: I can't figure out how to checkout the 'common' module." ; exit -1 ; } >&2 -endef - -MAKEFILE_COMMON := $(shell $(checkout-makefile-common)) -endif - -include $(MAKEFILE_COMMON) diff --git a/branch b/branch deleted file mode 100644 index baa94ef..0000000 --- a/branch +++ /dev/null @@ -1 +0,0 @@ -F-13 From f9b1a585eac235cc2836d953f95e89f7321869d4 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Thu, 29 Jul 2010 05:27:04 +0000 Subject: [PATCH 11/12] dist-git conversion --- .cvsignore => .gitignore | 0 Makefile | 21 --------------------- 2 files changed, 21 deletions(-) rename .cvsignore => .gitignore (100%) delete mode 100644 Makefile diff --git a/.cvsignore b/.gitignore similarity index 100% rename from .cvsignore rename to .gitignore diff --git a/Makefile b/Makefile deleted file mode 100644 index 61ba6fb..0000000 --- a/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# Makefile for source rpm: pam -# $Id: Makefile,v 1.2 2007/10/15 19:12:34 notting Exp $ -NAME := pam -SPECFILE = $(firstword $(wildcard *.spec)) - -define find-makefile-common -for d in common ../common ../../common ; do if [ -f $$d/Makefile.common ] ; then if [ -f $$d/CVS/Root -a -w $$d/Makefile.common ] ; then cd $$d ; cvs -Q update ; fi ; echo "$$d/Makefile.common" ; break ; fi ; done -endef - -MAKEFILE_COMMON := $(shell $(find-makefile-common)) - -ifeq ($(MAKEFILE_COMMON),) -# attempt a checkout -define checkout-makefile-common -test -f CVS/Root && { cvs -Q -d $$(cat CVS/Root) checkout common && echo "common/Makefile.common" ; } || { echo "ERROR: I can't figure out how to checkout the 'common' module." ; exit -1 ; } >&2 -endef - -MAKEFILE_COMMON := $(shell $(checkout-makefile-common)) -endif - -include $(MAKEFILE_COMMON) From 57bfa4578ce53e0638e4d9c3c86e33bb5ac82973 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Tue, 2 Nov 2010 13:24:28 +0100 Subject: [PATCH 12/12] - fix insecure dropping of priviledges in pam_xauth, pam_env, and pam_mail - CVE-2010-3316 (#637898), CVE-2010-3435 (#641335) - fix insecure executing of scripts with user supplied environment variables in pam_namespace - CVE-2010-3853 (#643043) --- pam-1.1.1-cve-2010-3853.patch | 37 ++ pam-1.1.1-drop-privs.patch | 814 ++++++++++++++++++++++++++++++++++ pam.spec | 13 +- 3 files changed, 863 insertions(+), 1 deletion(-) create mode 100644 pam-1.1.1-cve-2010-3853.patch create mode 100644 pam-1.1.1-drop-privs.patch diff --git a/pam-1.1.1-cve-2010-3853.patch b/pam-1.1.1-cve-2010-3853.patch new file mode 100644 index 0000000..ee15481 --- /dev/null +++ b/pam-1.1.1-cve-2010-3853.patch @@ -0,0 +1,37 @@ +diff -up Linux-PAM-1.1.1/modules/pam_namespace/pam_namespace.c.execle Linux-PAM-1.1.1/modules/pam_namespace/pam_namespace.c +--- Linux-PAM-1.1.1/modules/pam_namespace/pam_namespace.c.execle 2009-04-09 10:07:19.000000000 +0200 ++++ Linux-PAM-1.1.1/modules/pam_namespace/pam_namespace.c 2010-10-20 10:42:19.000000000 +0200 +@@ -1181,14 +1181,15 @@ static int inst_init(const struct polydi + } else { + pid = fork(); + if (pid == 0) { ++ static char *envp[] = { NULL }; + #ifdef WITH_SELINUX + if (idata->flags & PAMNS_SELINUX_ENABLED) { + if (setexeccon(NULL) < 0) + _exit(1); + } + #endif +- if (execl(init_script, init_script, +- polyptr->dir, ipath, newdir?"1":"0", idata->user, (char *)NULL) < 0) ++ if (execle(init_script, init_script, ++ polyptr->dir, ipath, newdir?"1":"0", idata->user, NULL, envp) < 0) + _exit(1); + } else if (pid > 0) { + while (((rc = waitpid(pid, &status, 0)) == (pid_t)-1) && +@@ -1608,13 +1609,14 @@ static int cleanup_tmpdirs(struct instan + if (pptr->method == TMPDIR && access(pptr->instance_prefix, F_OK) == 0) { + pid = fork(); + if (pid == 0) { ++ static char *envp[] = { NULL }; + #ifdef WITH_SELINUX + if (idata->flags & PAMNS_SELINUX_ENABLED) { + if (setexeccon(NULL) < 0) + _exit(1); + } + #endif +- if (execl("/bin/rm", "/bin/rm", "-rf", pptr->instance_prefix, (char *)NULL) < 0) ++ if (execle("/bin/rm", "/bin/rm", "-rf", pptr->instance_prefix, NULL, envp) < 0) + _exit(1); + } else if (pid > 0) { + while (((rc = waitpid(pid, &status, 0)) == (pid_t)-1) && diff --git a/pam-1.1.1-drop-privs.patch b/pam-1.1.1-drop-privs.patch new file mode 100644 index 0000000..3dd4c2a --- /dev/null +++ b/pam-1.1.1-drop-privs.patch @@ -0,0 +1,814 @@ +diff -up Linux-PAM-1.1.1/libpam/include/security/_pam_dropprivs.h.drop-privs Linux-PAM-1.1.1/libpam/include/security/_pam_dropprivs.h +--- Linux-PAM-1.1.1/libpam/include/security/_pam_dropprivs.h.drop-privs 2010-10-20 15:33:27.000000000 +0200 ++++ Linux-PAM-1.1.1/libpam/include/security/_pam_dropprivs.h 2010-10-20 15:33:27.000000000 +0200 +@@ -0,0 +1,74 @@ ++/* ++ * Copyright (c) 2010 Dmitry V. Levin ++ * ++ * ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, and the entire permission notice in its entirety, ++ * including the disclaimer of warranties. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * ALTERNATIVELY, this product may be distributed under the terms of ++ * the GNU Public License, in which case the provisions of the GPL are ++ * required INSTEAD OF the above restrictions. (This clause is ++ * necessary due to a potential bad interaction between the GPL and ++ * the restrictions contained in a BSD-style copyright.) ++ * ++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED ++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED ++ * OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#ifndef _SECURITY__PAM_DROPPRIVS_H ++#define _SECURITY__PAM_DROPPRIVS_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#include ++ ++struct pam_modutil_privs { ++ gid_t *grplist; ++ int number_of_groups; ++ int allocated; ++ gid_t old_gid; ++ uid_t old_uid; ++ int is_dropped; ++}; ++ ++#define PAM_MODUTIL_NGROUPS 64 ++#define PAM_MODUTIL_DEF_PRIVS(n) \ ++ gid_t n##_grplist[PAM_MODUTIL_NGROUPS]; \ ++ struct pam_modutil_privs n = { n##_grplist, PAM_MODUTIL_NGROUPS, 0, -1, -1, 0 } ++ ++extern int PAM_NONNULL((1,2,3)) ++pam_modutil_drop_priv(pam_handle_t *pamh, ++ struct pam_modutil_privs *p, ++ const struct passwd *pw); ++ ++extern int PAM_NONNULL((1,2)) ++pam_modutil_regain_priv(pam_handle_t *pamh, ++ struct pam_modutil_privs *p); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _SECURITY__PAM_DROPPRIVS_H */ +diff -up Linux-PAM-1.1.1/libpam/Makefile.am.drop-privs Linux-PAM-1.1.1/libpam/Makefile.am +--- Linux-PAM-1.1.1/libpam/Makefile.am.drop-privs 2009-11-04 15:04:49.000000000 +0100 ++++ Linux-PAM-1.1.1/libpam/Makefile.am 2010-10-20 15:46:14.000000000 +0200 +@@ -18,11 +18,15 @@ include_HEADERS = include/security/_pam_ + include/security/pam_ext.h include/security/pam_modutil.h + + noinst_HEADERS = pam_prelude.h pam_private.h pam_tokens.h \ +- pam_modutil_private.h pam_static_modules.h ++ pam_modutil_private.h pam_static_modules.h include/security/_pam_dropprivs.h + + libpam_la_LDFLAGS = -no-undefined -version-info 82:2:82 + libpam_la_LIBADD = @LIBAUDIT@ $(LIBPRELUDE_LIBS) @LIBDL@ + ++noinst_LIBRARIES = libdropprivs.a ++libdropprivs_a_SOURCES = pam_modutil_priv.c ++libdropprivs_a_CFLAGS = $(AM_CFLAGS) -fPIC ++ + if STATIC_MODULES + libpam_la_LIBADD += $(shell ls ../modules/pam_*/*.lo) \ + @LIBDB@ @LIBCRYPT@ @LIBNSL@ @LIBCRACK@ -lutil +@@ -41,4 +45,4 @@ libpam_la_SOURCES = pam_account.c pam_au + pam_vprompt.c pam_syslog.c pam_dynamic.c pam_audit.c \ + pam_modutil_cleanup.c pam_modutil_getpwnam.c pam_modutil_ioloop.c \ + pam_modutil_getgrgid.c pam_modutil_getpwuid.c pam_modutil_getgrnam.c \ +- pam_modutil_getspnam.c pam_modutil_getlogin.c pam_modutil_ingroup.c ++ pam_modutil_getspnam.c pam_modutil_getlogin.c pam_modutil_ingroup.c +diff -up Linux-PAM-1.1.1/libpam/pam_modutil_priv.c.drop-privs Linux-PAM-1.1.1/libpam/pam_modutil_priv.c +--- Linux-PAM-1.1.1/libpam/pam_modutil_priv.c.drop-privs 2010-10-20 15:33:27.000000000 +0200 ++++ Linux-PAM-1.1.1/libpam/pam_modutil_priv.c 2010-10-20 15:33:27.000000000 +0200 +@@ -0,0 +1,171 @@ ++/* ++ * $Id: pam_modutil_priv.c,v 1.1 2010/10/03 21:02:07 ldv Exp $ ++ * ++ * This file provides two functions: ++ * pam_modutil_drop_priv: ++ * temporarily lower process fs privileges by switching to another uid/gid, ++ * pam_modutil_regain_priv: ++ * regain process fs privileges lowered by pam_modutil_drop_priv(). ++ */ ++ ++#include "pam_modutil_private.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* ++ * Two setfsuid() calls in a row are necessary to check ++ * whether setfsuid() succeeded or not. ++ */ ++static int change_uid(uid_t uid, uid_t *save) ++{ ++ uid_t tmp = setfsuid(uid); ++ if (save) ++ *save = tmp; ++ return (uid_t) setfsuid(uid) == uid ? 0 : -1; ++} ++static int change_gid(gid_t gid, gid_t *save) ++{ ++ gid_t tmp = setfsgid(gid); ++ if (save) ++ *save = tmp; ++ return (gid_t) setfsgid(gid) == gid ? 0 : -1; ++} ++ ++static int cleanup(struct pam_modutil_privs *p) ++{ ++ if (p->allocated) { ++ p->allocated = 0; ++ free(p->grplist); ++ } ++ p->grplist = NULL; ++ p->number_of_groups = 0; ++ return -1; ++} ++ ++#define PRIV_MAGIC 0x1004000a ++#define PRIV_MAGIC_DONOTHING 0xdead000a ++ ++int pam_modutil_drop_priv(pam_handle_t *pamh, ++ struct pam_modutil_privs *p, ++ const struct passwd *pw) ++{ ++ int res; ++ ++ if (p->is_dropped) { ++ pam_syslog(pamh, LOG_CRIT, ++ "pam_modutil_drop_priv: called with dropped privileges"); ++ return -1; ++ } ++ ++ /* ++ * If not root, we can do nothing. ++ * If switching to root, we have nothing to do. ++ * That is, in both cases, we do not care. ++ */ ++ if (geteuid() != 0 || pw->pw_uid == 0) { ++ p->is_dropped = PRIV_MAGIC_DONOTHING; ++ return 0; ++ } ++ ++ if (!p->grplist || p->number_of_groups <= 0) { ++ pam_syslog(pamh, LOG_CRIT, ++ "pam_modutil_drop_priv: called without room for supplementary groups"); ++ return -1; ++ } ++ res = getgroups(0, NULL); ++ if (res < 0) { ++ pam_syslog(pamh, LOG_ERR, ++ "pam_modutil_drop_priv: getgroups failed: %m"); ++ return -1; ++ } ++ ++ p->allocated = 0; ++ if (res > p->number_of_groups) { ++ p->grplist = calloc(res, sizeof(gid_t)); ++ if (!p->grplist) { ++ pam_syslog(pamh, LOG_ERR, "out of memory"); ++ return cleanup(p); ++ } ++ p->allocated = 1; ++ p->number_of_groups = res; ++ } ++ ++ res = getgroups(p->number_of_groups, p->grplist); ++ if (res < 0) { ++ pam_syslog(pamh, LOG_ERR, ++ "pam_modutil_drop_priv: getgroups failed: %m"); ++ return cleanup(p); ++ } ++ ++ p->number_of_groups = res; ++ ++ /* ++ * We should care to leave process credentials in consistent state. ++ * That is, e.g. if change_gid() succeeded but change_uid() failed, ++ * we should try to restore old gid. ++ */ ++ if (setgroups(0, NULL)) { ++ pam_syslog(pamh, LOG_ERR, ++ "pam_modutil_drop_priv: setgroups failed: %m"); ++ return cleanup(p); ++ } ++ if (change_gid(pw->pw_gid, &p->old_gid)) { ++ pam_syslog(pamh, LOG_ERR, ++ "pam_modutil_drop_priv: change_gid failed: %m"); ++ (void) setgroups(p->number_of_groups, p->grplist); ++ return cleanup(p); ++ } ++ if (change_uid(pw->pw_uid, &p->old_uid)) { ++ pam_syslog(pamh, LOG_ERR, ++ "pam_modutil_drop_priv: change_uid failed: %m"); ++ (void) change_gid(p->old_gid, NULL); ++ (void) setgroups(p->number_of_groups, p->grplist); ++ return cleanup(p); ++ } ++ ++ p->is_dropped = PRIV_MAGIC; ++ return 0; ++} ++ ++int pam_modutil_regain_priv(pam_handle_t *pamh, ++ struct pam_modutil_privs *p) ++{ ++ switch (p->is_dropped) { ++ case PRIV_MAGIC_DONOTHING: ++ p->is_dropped = 0; ++ return 0; ++ ++ case PRIV_MAGIC: ++ break; ++ ++ default: ++ pam_syslog(pamh, LOG_CRIT, ++ "pam_modutil_regain_priv: called with invalid state"); ++ return -1; ++ } ++ ++ if (change_uid(p->old_uid, NULL)) { ++ pam_syslog(pamh, LOG_ERR, ++ "pam_modutil_regain_priv: change_uid failed: %m"); ++ return cleanup(p); ++ } ++ if (change_gid(p->old_gid, NULL)) { ++ pam_syslog(pamh, LOG_ERR, ++ "pam_modutil_regain_priv: change_gid failed: %m"); ++ return cleanup(p); ++ } ++ if (setgroups(p->number_of_groups, p->grplist)) { ++ pam_syslog(pamh, LOG_ERR, ++ "pam_modutil_regain_priv: setgroups failed: %m"); ++ return cleanup(p); ++ } ++ ++ p->is_dropped = 0; ++ cleanup(p); ++ return 0; ++} +diff -up Linux-PAM-1.1.1/modules/pam_env/Makefile.am.drop-privs Linux-PAM-1.1.1/modules/pam_env/Makefile.am +--- Linux-PAM-1.1.1/modules/pam_env/Makefile.am.drop-privs 2009-06-29 09:24:27.000000000 +0200 ++++ Linux-PAM-1.1.1/modules/pam_env/Makefile.am 2010-10-20 15:33:27.000000000 +0200 +@@ -22,7 +22,7 @@ if HAVE_VERSIONING + endif + + securelib_LTLIBRARIES = pam_env.la +-pam_env_la_LIBADD = -L$(top_builddir)/libpam -lpam ++pam_env_la_LIBADD = -L$(top_builddir)/libpam -ldropprivs -lpam + + secureconf_DATA = pam_env.conf + sysconf_DATA = environment +diff -up Linux-PAM-1.1.1/modules/pam_env/pam_env.c.drop-privs Linux-PAM-1.1.1/modules/pam_env/pam_env.c +--- Linux-PAM-1.1.1/modules/pam_env/pam_env.c.drop-privs 2009-06-29 09:24:27.000000000 +0200 ++++ Linux-PAM-1.1.1/modules/pam_env/pam_env.c 2010-10-20 15:33:27.000000000 +0200 +@@ -10,7 +10,7 @@ + #define DEFAULT_READ_ENVFILE 1 + + #define DEFAULT_USER_ENVFILE ".pam_environment" +-#define DEFAULT_USER_READ_ENVFILE 1 ++#define DEFAULT_USER_READ_ENVFILE 0 + + #include "config.h" + +@@ -42,6 +42,7 @@ + #include + #include + #include ++#include + + /* This little structure makes it easier to keep variables together */ + +@@ -772,13 +773,14 @@ handle_env (pam_handle_t *pamh, int argc + + if(user_readenv && retval == PAM_SUCCESS) { + char *envpath = NULL; +- struct passwd *user_entry; ++ struct passwd *user_entry = NULL; + const char *username; + struct stat statbuf; + + username = _pam_get_item_byname(pamh, "PAM_USER"); + +- user_entry = pam_modutil_getpwnam (pamh, username); ++ if (username) ++ user_entry = pam_modutil_getpwnam (pamh, username); + if (!user_entry) { + pam_syslog(pamh, LOG_ERR, "No such user!?"); + } +@@ -789,7 +791,15 @@ handle_env (pam_handle_t *pamh, int argc + return PAM_BUF_ERR; + } + if (stat(envpath, &statbuf) == 0) { +- retval = _parse_config_file(pamh, envpath); ++ PAM_MODUTIL_DEF_PRIVS(privs); ++ ++ if (pam_modutil_drop_priv(pamh, &privs, user_entry)) { ++ retval = PAM_SESSION_ERR; ++ } else { ++ retval = _parse_config_file(pamh, envpath); ++ if (pam_modutil_regain_priv(pamh, &privs)) ++ retval = PAM_SESSION_ERR; ++ } + if (retval == PAM_IGNORE) + retval = PAM_SUCCESS; + } +diff -up Linux-PAM-1.1.1/modules/pam_env/pam_env.8.xml.drop-privs Linux-PAM-1.1.1/modules/pam_env/pam_env.8.xml +--- Linux-PAM-1.1.1/modules/pam_env/pam_env.8.xml.drop-privs 2009-06-16 09:35:09.000000000 +0200 ++++ Linux-PAM-1.1.1/modules/pam_env/pam_env.8.xml 2010-10-20 15:33:27.000000000 +0200 +@@ -143,7 +143,10 @@ + + + Turns on or off the reading of the user specific environment +- file. 0 is off, 1 is on. By default this option is on. ++ file. 0 is off, 1 is on. By default this option is off as user ++ supplied environment variables in the PAM environment could affect ++ behavior of subsequent modules in the stack without the consent ++ of the system administrator. + + + +diff -up Linux-PAM-1.1.1/modules/pam_mail/Makefile.am.drop-privs Linux-PAM-1.1.1/modules/pam_mail/Makefile.am +--- Linux-PAM-1.1.1/modules/pam_mail/Makefile.am.drop-privs 2009-06-29 09:24:27.000000000 +0200 ++++ Linux-PAM-1.1.1/modules/pam_mail/Makefile.am 2010-10-20 15:33:27.000000000 +0200 +@@ -22,7 +22,7 @@ if HAVE_VERSIONING + endif + + securelib_LTLIBRARIES = pam_mail.la +-pam_mail_la_LIBADD = -L$(top_builddir)/libpam -lpam ++pam_mail_la_LIBADD = -L$(top_builddir)/libpam -ldropprivs -lpam + + if ENABLE_REGENERATE_MAN + noinst_DATA = README +diff -up Linux-PAM-1.1.1/modules/pam_mail/pam_mail.c.drop-privs Linux-PAM-1.1.1/modules/pam_mail/pam_mail.c +--- Linux-PAM-1.1.1/modules/pam_mail/pam_mail.c.drop-privs 2008-09-25 13:53:03.000000000 +0200 ++++ Linux-PAM-1.1.1/modules/pam_mail/pam_mail.c 2010-10-20 15:33:27.000000000 +0200 +@@ -44,6 +44,7 @@ + #include + #include + #include ++#include + + /* argument parsing */ + +@@ -124,29 +125,16 @@ _pam_parse (const pam_handle_t *pamh, in + + static int + get_folder(pam_handle_t *pamh, int ctrl, +- const char *path_mail, char **folder_p, size_t hashcount) ++ const char *path_mail, char **folder_p, size_t hashcount, ++ const struct passwd *pwd) + { + int retval; +- const char *user, *path; ++ const char *path; + char *folder = NULL; +- const struct passwd *pwd = NULL; +- +- retval = pam_get_user(pamh, &user, NULL); +- if (retval != PAM_SUCCESS || user == NULL) { +- pam_syslog(pamh, LOG_ERR, "cannot determine username"); +- retval = PAM_USER_UNKNOWN; +- goto get_folder_cleanup; +- } + + if (ctrl & PAM_NEW_MAIL_DIR) { + path = path_mail; + if (*path == '~') { /* support for $HOME delivery */ +- pwd = pam_modutil_getpwnam(pamh, user); +- if (pwd == NULL) { +- pam_syslog(pamh, LOG_ERR, "user unknown"); +- retval = PAM_USER_UNKNOWN; +- goto get_folder_cleanup; +- } + /* + * "~/xxx" and "~xxx" are treated as same + */ +@@ -168,18 +156,11 @@ get_folder(pam_handle_t *pamh, int ctrl, + + /* put folder together */ + +- hashcount = hashcount < strlen(user) ? hashcount : strlen(user); ++ hashcount = hashcount < strlen(pwd->pw_name) ? ++ hashcount : strlen(pwd->pw_name); + + retval = PAM_BUF_ERR; + if (ctrl & PAM_HOME_MAIL) { +- if (pwd == NULL) { +- pwd = pam_modutil_getpwnam(pamh, user); +- if (pwd == NULL) { +- pam_syslog(pamh, LOG_ERR, "user unknown"); +- retval = PAM_USER_UNKNOWN; +- goto get_folder_cleanup; +- } +- } + if (asprintf(&folder, MAIL_FILE_FORMAT, pwd->pw_dir, "", path) < 0) + goto get_folder_cleanup; + } else { +@@ -192,11 +173,11 @@ get_folder(pam_handle_t *pamh, int ctrl, + + for (i = 0; i < hashcount; i++) { + hash[2 * i] = '/'; +- hash[2 * i + 1] = user[i]; ++ hash[2 * i + 1] = pwd->pw_name[i]; + } + hash[2 * i] = '\0'; + +- rc = asprintf(&folder, MAIL_FILE_FORMAT, path, hash, user); ++ rc = asprintf(&folder, MAIL_FILE_FORMAT, path, hash, pwd->pw_name); + _pam_overwrite(hash); + _pam_drop(hash); + if (rc < 0) +@@ -208,7 +189,6 @@ get_folder(pam_handle_t *pamh, int ctrl, + /* tidy up */ + + get_folder_cleanup: +- user = NULL; + path = NULL; + + *folder_p = folder; +@@ -402,7 +382,9 @@ static int _do_mail(pam_handle_t *pamh, + int retval, ctrl, type; + size_t hashcount; + char *folder = NULL; ++ const char *user; + const char *path_mail = NULL; ++ const struct passwd *pwd = NULL; + + /* + * this module (un)sets the MAIL environment variable, and checks if +@@ -411,9 +393,21 @@ static int _do_mail(pam_handle_t *pamh, + + ctrl = _pam_parse(pamh, flags, argc, argv, &path_mail, &hashcount); + ++ retval = pam_get_user(pamh, &user, NULL); ++ if (retval != PAM_SUCCESS || user == NULL) { ++ pam_syslog(pamh, LOG_ERR, "cannot determine username"); ++ return PAM_USER_UNKNOWN; ++ } ++ ++ pwd = pam_modutil_getpwnam (pamh, user); ++ if (pwd == NULL) { ++ pam_syslog(pamh, LOG_ERR, "user unknown"); ++ return PAM_USER_UNKNOWN; ++ } ++ + /* which folder? */ + +- retval = get_folder(pamh, ctrl, path_mail, &folder, hashcount); ++ retval = get_folder(pamh, ctrl, path_mail, &folder, hashcount, pwd); + if (retval != PAM_SUCCESS) { + D(("failed to find folder")); + return retval; +@@ -450,7 +444,19 @@ static int _do_mail(pam_handle_t *pamh, + + if ((est && !(ctrl & PAM_NO_LOGIN)) + || (!est && (ctrl & PAM_LOGOUT_TOO))) { +- type = get_mail_status(pamh, ctrl, folder); ++ PAM_MODUTIL_DEF_PRIVS(privs); ++ ++ if (pam_modutil_drop_priv(pamh, &privs, pwd)) { ++ retval = PAM_SESSION_ERR; ++ goto do_mail_cleanup; ++ } else { ++ type = get_mail_status(pamh, ctrl, folder); ++ if (pam_modutil_regain_priv(pamh, &privs)) { ++ retval = PAM_SESSION_ERR; ++ goto do_mail_cleanup; ++ } ++ } ++ + if (type != 0) { + retval = report_mail(pamh, ctrl, type, folder); + type = 0; +diff -up Linux-PAM-1.1.1/modules/pam_xauth/Makefile.am.drop-privs Linux-PAM-1.1.1/modules/pam_xauth/Makefile.am +--- Linux-PAM-1.1.1/modules/pam_xauth/Makefile.am.drop-privs 2009-11-04 13:04:53.000000000 +0100 ++++ Linux-PAM-1.1.1/modules/pam_xauth/Makefile.am 2010-10-20 15:33:27.000000000 +0200 +@@ -17,7 +17,7 @@ secureconfdir = $(SCONFIGDIR) + + AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include + AM_LDFLAGS = -no-undefined -avoid-version -module \ +- -L$(top_builddir)/libpam -lpam @LIBSELINUX@ ++ -L$(top_builddir)/libpam -ldropprivs -lpam @LIBSELINUX@ + if HAVE_VERSIONING + AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map + endif +diff -up Linux-PAM-1.1.1/modules/pam_xauth/pam_xauth.c.drop-privs Linux-PAM-1.1.1/modules/pam_xauth/pam_xauth.c +--- Linux-PAM-1.1.1/modules/pam_xauth/pam_xauth.c.drop-privs 2009-11-04 13:04:53.000000000 +0100 ++++ Linux-PAM-1.1.1/modules/pam_xauth/pam_xauth.c 2010-10-20 15:33:27.000000000 +0200 +@@ -35,8 +35,10 @@ + + #include "config.h" + #include +-#include + #include ++#include ++#include ++#include + #include + #include + #include +@@ -56,6 +58,7 @@ + #include + #include + #include ++#include + + #ifdef WITH_SELINUX + #include +@@ -87,7 +90,7 @@ static const char * const xauthpaths[] = + /* Run a given command (with a NULL-terminated argument list), feeding it the + * given input on stdin, and storing any output it generates. */ + static int +-run_coprocess(const char *input, char **output, ++run_coprocess(pam_handle_t *pamh, const char *input, char **output, + uid_t uid, gid_t gid, const char *command, ...) + { + int ipipe[2], opipe[2], i; +@@ -126,9 +129,26 @@ run_coprocess(const char *input, char ** + const char *tmp; + int maxopened; + /* Drop privileges. */ +- setgid(gid); +- setgroups(0, NULL); +- setuid(uid); ++ if (setgid(gid) == -1) ++ { ++ int err = errno; ++ pam_syslog (pamh, LOG_ERR, "setgid(%lu) failed: %m", ++ (unsigned long) getegid ()); ++ _exit (err); ++ } ++ if (setgroups(0, NULL) == -1) ++ { ++ int err = errno; ++ pam_syslog (pamh, LOG_ERR, "setgroups() failed: %m"); ++ _exit (err); ++ } ++ if (setuid(uid) == -1) ++ { ++ int err = errno; ++ pam_syslog (pamh, LOG_ERR, "setuid(%lu) failed: %m", ++ (unsigned long) geteuid ()); ++ _exit (err); ++ } + /* Initialize the argument list. */ + memset(args, 0, sizeof(args)); + /* Set the pipe descriptors up as stdin and stdout, and close +@@ -215,9 +235,11 @@ check_acl(pam_handle_t *pamh, + { + char path[PATH_MAX]; + struct passwd *pwd; +- FILE *fp; +- int i; +- uid_t euid; ++ FILE *fp = NULL; ++ int i, fd = -1, save_errno; ++ struct stat st; ++ PAM_MODUTIL_DEF_PRIVS(privs); ++ + /* Check this user's file. */ + pwd = pam_modutil_getpwnam(pamh, this_user); + if (pwd == NULL) { +@@ -233,11 +255,33 @@ check_acl(pam_handle_t *pamh, + "name of user's home directory is too long"); + return PAM_SESSION_ERR; + } +- euid = geteuid(); +- setfsuid(pwd->pw_uid); +- fp = fopen(path, "r"); +- setfsuid(euid); +- if (fp != NULL) { ++ if (pam_modutil_drop_priv(pamh, &privs, pwd)) ++ return PAM_SESSION_ERR; ++ if (!stat(path, &st)) { ++ if (!S_ISREG(st.st_mode)) ++ errno = EINVAL; ++ else ++ fd = open(path, O_RDONLY | O_NOCTTY); ++ } ++ save_errno = errno; ++ if (pam_modutil_regain_priv(pamh, &privs)) { ++ if (fd >= 0) ++ close(fd); ++ return PAM_SESSION_ERR; ++ } ++ if (fd >= 0) { ++ if (!fstat(fd, &st)) { ++ if (!S_ISREG(st.st_mode)) ++ errno = EINVAL; ++ else ++ fp = fdopen(fd, "r"); ++ } ++ if (!fp) { ++ save_errno = errno; ++ close(fd); ++ } ++ } ++ if (fp) { + char buf[LINE_MAX], *tmp; + /* Scan the file for a list of specs of users to "trust". */ + while (fgets(buf, sizeof(buf), fp) != NULL) { +@@ -268,6 +312,7 @@ check_acl(pam_handle_t *pamh, + return PAM_PERM_DENIED; + } else { + /* Default to okay if the file doesn't exist. */ ++ errno = save_errno; + switch (errno) { + case ENOENT: + if (noent_code == PAM_SUCCESS) { +@@ -305,7 +350,7 @@ pam_sm_open_session (pam_handle_t *pamh, + struct passwd *tpwd, *rpwd; + int fd, i, debug = 0; + int retval = PAM_SUCCESS; +- uid_t systemuser = 499, targetuser = 0, euid; ++ uid_t systemuser = 499, targetuser = 0; + + /* Parse arguments. We don't understand many, so no sense in breaking + * this into a separate function. */ +@@ -463,14 +508,15 @@ pam_sm_open_session (pam_handle_t *pamh, + xauth, "-f", cookiefile, "nlist", display, + (unsigned long) getuid(), (unsigned long) getgid()); + } +- if (run_coprocess(NULL, &cookie, ++ if (run_coprocess(pamh, NULL, &cookie, + getuid(), getgid(), + xauth, "-f", cookiefile, "nlist", display, + NULL) == 0) { +- int save_errno; + #ifdef WITH_SELINUX + security_context_t context = NULL; + #endif ++ PAM_MODUTIL_DEF_PRIVS(privs); ++ + /* Check that we got a cookie. If not, we get creative. */ + if (((cookie == NULL) || (strlen(cookie) == 0)) && + ((strncmp(display, "localhost:", 10) == 0) || +@@ -521,7 +567,7 @@ pam_sm_open_session (pam_handle_t *pamh, + (unsigned long) getuid(), + (unsigned long) getgid()); + } +- run_coprocess(NULL, &cookie, ++ run_coprocess(pamh, NULL, &cookie, + getuid(), getgid(), + xauth, "-f", cookiefile, + "nlist", t, NULL); +@@ -553,9 +599,10 @@ pam_sm_open_session (pam_handle_t *pamh, + } + + /* Generate a new file to hold the data. */ +- euid = geteuid(); +- setfsuid(tpwd->pw_uid); +- ++ if (pam_modutil_drop_priv(pamh, &privs, tpwd)) { ++ retval = PAM_SESSION_ERR; ++ goto cleanup; ++ } + #ifdef WITH_SELINUX + if (is_selinux_enabled() > 0) { + struct selabel_handle *ctx = selabel_open(SELABEL_CTX_FILE, NULL, 0); +@@ -573,31 +620,24 @@ pam_sm_open_session (pam_handle_t *pamh, + } + } + } ++#endif /* WITH_SELINUX */ + fd = mkstemp(xauthority + sizeof(XAUTHENV)); +- save_errno = errno; ++ if (fd < 0) ++ pam_syslog(pamh, LOG_ERR, ++ "error creating temporary file `%s': %m", ++ xauthority + sizeof(XAUTHENV)); ++#ifdef WITH_SELINUX + if (context != NULL) { + free(context); + setfscreatecon(NULL); + } +-#else +- fd = mkstemp(xauthority + sizeof(XAUTHENV)); +- save_errno = errno; +-#endif +- +- setfsuid(euid); +- if (fd == -1) { +- errno = save_errno; +- pam_syslog(pamh, LOG_ERR, +- "error creating temporary file `%s': %m", +- xauthority + sizeof(XAUTHENV)); ++#endif /* WITH_SELINUX */ ++ if (fd >= 0) ++ close(fd); ++ if (pam_modutil_regain_priv(pamh, &privs) || fd < 0) { + retval = PAM_SESSION_ERR; + goto cleanup; + } +- /* Set permissions on the new file and dispose of the +- * descriptor. */ +- if (fchown(fd, tpwd->pw_uid, tpwd->pw_gid) < 0) +- pam_syslog (pamh, LOG_ERR, "fchown: %m"); +- close(fd); + + /* Get a copy of the filename to save as a data item for + * removal at session-close time. */ +@@ -669,7 +709,7 @@ pam_sm_open_session (pam_handle_t *pamh, + (unsigned long) tpwd->pw_uid, + (unsigned long) tpwd->pw_gid); + } +- run_coprocess(cookie, &tmp, ++ run_coprocess(pamh, cookie, &tmp, + tpwd->pw_uid, tpwd->pw_gid, + xauth, "-f", cookiefile, "nmerge", "-", NULL); + +@@ -691,11 +731,21 @@ int + pam_sm_close_session (pam_handle_t *pamh, int flags UNUSED, + int argc, const char **argv) + { +- void *cookiefile; + int i, debug = 0; ++ const char *user; ++ const void *data; ++ const char *cookiefile; ++ struct passwd *tpwd; ++ PAM_MODUTIL_DEF_PRIVS(privs); ++ ++ /* Try to retrieve the name of a file we created when ++ * the session was opened. */ ++ if (pam_get_data(pamh, DATANAME, &data) != PAM_SUCCESS) ++ return PAM_SUCCESS; ++ cookiefile = data; + +- /* Parse arguments. We don't understand many, so no sense in breaking +- * this into a separate function. */ ++ /* Parse arguments. We don't understand many, so ++ * no sense in breaking this into a separate function. */ + for (i = 0; i < argc; i++) { + if (strcmp(argv[i], "debug") == 0) { + debug = 1; +@@ -714,19 +764,26 @@ pam_sm_close_session (pam_handle_t *pamh + argv[i]); + } + +- /* Try to retrieve the name of a file we created when the session was +- * opened. */ +- if (pam_get_data(pamh, DATANAME, (const void**) &cookiefile) == PAM_SUCCESS) { +- /* We'll only try to remove the file once. */ +- if (strlen((char*)cookiefile) > 0) { +- if (debug) { +- pam_syslog(pamh, LOG_DEBUG, "removing `%s'", +- (char*)cookiefile); +- } +- unlink((char*)cookiefile); +- *((char*)cookiefile) = '\0'; +- } ++ if (pam_get_user(pamh, &user, NULL) != PAM_SUCCESS) { ++ pam_syslog(pamh, LOG_ERR, ++ "error determining target user's name"); ++ return PAM_SESSION_ERR; ++ } ++ if (!(tpwd = pam_modutil_getpwnam(pamh, user))) { ++ pam_syslog(pamh, LOG_ERR, ++ "error determining target user's UID"); ++ return PAM_SESSION_ERR; + } ++ ++ if (debug) ++ pam_syslog(pamh, LOG_DEBUG, "removing `%s'", cookiefile); ++ if (pam_modutil_drop_priv(pamh, &privs, tpwd)) ++ return PAM_SESSION_ERR; ++ if (unlink(cookiefile) == -1 && errno != ENOENT) ++ pam_syslog(pamh, LOG_WARNING, "Couldn't remove `%s': %m", cookiefile); ++ if (pam_modutil_regain_priv(pamh, &privs)) ++ return PAM_SESSION_ERR; ++ + return PAM_SUCCESS; + } + diff --git a/pam.spec b/pam.spec index 5eb71a1..c8b2799 100644 --- a/pam.spec +++ b/pam.spec @@ -3,7 +3,7 @@ Summary: An extensible library which provides authentication for applications Name: pam Version: 1.1.1 -Release: 5%{?dist} +Release: 6%{?dist} # The library is BSD licensed with option to relicense as GPLv2+ - this option is redundant # as the BSD license allows that anyway. pam_timestamp and pam_console modules are GPLv2+, License: BSD and GPLv2+ @@ -27,6 +27,9 @@ Patch4: pam-1.1.0-console-nochmod.patch Patch5: pam-1.1.0-notally.patch Patch7: pam-1.1.0-console-fixes.patch Patch8: pam-1.1.1-authtok-prompt.patch +# Fixes CVE-2010-3435 and CVE-2010-3316 +Patch9: pam-1.1.1-drop-privs.patch +Patch10: pam-1.1.1-cve-2010-3853.patch %define _sbindir /sbin %define _moduledir /%{_lib}/security @@ -93,6 +96,8 @@ mv pam-redhat-%{pam_redhat_version}/* modules %patch5 -p1 -b .notally %patch7 -p1 -b .console-fixes %patch8 -p0 -b .prompt +%patch9 -p1 -b .drop-privs +%patch10 -p1 -b .execle libtoolize -f autoreconf @@ -333,6 +338,12 @@ fi %doc doc/adg/*.txt doc/adg/html %changelog +* Tue Nov 2 2010 Tomas Mraz 1.1.1-6 +- fix insecure dropping of priviledges in pam_xauth, pam_env, + and pam_mail - CVE-2010-3316 (#637898), CVE-2010-3435 (#641335) +- fix insecure executing of scripts with user supplied environment + variables in pam_namespace - CVE-2010-3853 (#643043) + * Thu Jul 15 2010 Tomas Mraz 1.1.1-5 - do not overwrite tallylog with empty file on upgrade