adopt pbuild patch

This commit is contained in:
Dmitry Fedorov 2015-01-21 14:01:39 +03:00
parent 3fd7089081
commit 2920bf9f9d
17 changed files with 3610 additions and 52 deletions

View file

@ -1,11 +0,0 @@
--- Linux-PAM-0.99.3.0/modules/pam_console/Makefile.am.pbuild-rh 2005-12-15 23:07:37.000000000 +0100
+++ Linux-PAM-0.99.3.0/modules/pam_console/Makefile.am 2006-01-28 00:26:20.000000000 +0100
@@ -57,6 +57,8 @@
pam_console_la_CFLAGS = $(AM_CFLAGS)
pam_console_apply_CFLAGS = $(AM_CFLAGS)
+configfile.tab.h: configfile.tab.c
+
configfile.tab.c: configfile.y
$(YACC) $(BISON_OPTS) -o $@ -p _pc_yy $<
sh $(srcdir)/sed-static $@

1730
pam-1.1.1-faillock.patch Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,435 @@
From 0d29e379601819c7f7ed8de18b54de803a9f4049 Mon Sep 17 00:00:00 2001
From: Tomas Mraz <tmraz@fedoraproject.org>
Date: Fri, 5 Sep 2014 09:09:37 +0200
Subject: [PATCH] Add grantor field to audit records of libpam.
The grantor field gives audit trail of PAM modules which granted access
for successful return from libpam calls. In case of failed return
the grantor field is set to '?'.
libpam/pam_account.c (pam_acct_mgmt): Remove _pam_auditlog() call.
libpam/pam_auth.c (pam_authenticate, pam_setcred): Likewise.
libpam/pam_password.c (pam_chauthtok): Likewise.
libpam/pam_session.c (pam_open_session, pam_close_session): Likewise.
libpam/pam_audit.c (_pam_audit_writelog): Add grantors parameter,
add grantor= field to the message if grantors is set.
(_pam_list_grantors): New function creating the string with grantors list.
(_pam_auditlog): Add struct handler pointer parameter, call _pam_list_grantors()
to list the grantors from the handler list.
(_pam_audit_end): Add NULL handler parameter to _pam_auditlog() call.
(pam_modutil_audit_write): Add NULL grantors parameter to _pam_audit_writelog().
libpam/pam_dispatch.c (_pam_dispatch_aux): Set h->grantor where appropriate.
(_pam_clear_grantors): New function to clear grantor field of handler.
(_pam_dispatch): Call _pam_clear_grantors() before executing the stack.
Call _pam_auditlog() when appropriate.
libpam/pam_handlers.c (extract_modulename): Do not allow empty module name
or just "?" to avoid confusing audit trail.
(_pam_add_handler): Test for NULL return from extract_modulename().
Clear grantor field of handler.
libpam/pam_private.h: Add grantor field to struct handler, add handler pointer
parameter to _pam_auditlog().
---
libpam/pam_account.c | 4 ---
libpam/pam_audit.c | 84 +++++++++++++++++++++++++++++++++++++++++++--------
libpam/pam_auth.c | 8 -----
libpam/pam_dispatch.c | 41 ++++++++++++++++++++-----
libpam/pam_handlers.c | 14 +++++++--
libpam/pam_password.c | 4 ---
libpam/pam_private.h | 3 +-
libpam/pam_session.c | 7 -----
8 files changed, 119 insertions(+), 46 deletions(-)
diff --git a/libpam/pam_account.c b/libpam/pam_account.c
index 572acc4..3a4fb1f 100644
--- a/libpam/pam_account.c
+++ b/libpam/pam_account.c
@@ -19,9 +19,5 @@ int pam_acct_mgmt(pam_handle_t *pamh, int flags)
retval = _pam_dispatch(pamh, flags, PAM_ACCOUNT);
-#ifdef HAVE_LIBAUDIT
- retval = _pam_auditlog(pamh, PAM_ACCOUNT, retval, flags);
-#endif
-
return retval;
}
diff --git a/libpam/pam_audit.c b/libpam/pam_audit.c
index 531746a..24fb799 100644
--- a/libpam/pam_audit.c
+++ b/libpam/pam_audit.c
@@ -6,12 +6,12 @@
Authors:
Steve Grubb <sgrubb@redhat.com> */
-#include <stdio.h>
-#include <syslog.h>
#include "pam_private.h"
#include "pam_modutil_private.h"
#ifdef HAVE_LIBAUDIT
+#include <stdio.h>
+#include <syslog.h>
#include <libaudit.h>
#include <pwd.h>
#include <netdb.h>
@@ -25,17 +25,24 @@
static int
_pam_audit_writelog(pam_handle_t *pamh, int audit_fd, int type,
- const char *message, int retval)
+ const char *message, const char *grantors, int retval)
{
static int old_errno = -1;
- int rc;
- char buf[32];
+ int rc = -ENOMEM;
+ char *buf;
+ const char *grantors_field = " grantors=";
- snprintf(buf, sizeof(buf), "PAM:%s", message);
+ if (grantors == NULL) {
+ grantors = "";
+ grantors_field = "";
+ }
- rc = audit_log_acct_message (audit_fd, type, NULL, buf,
- (retval != PAM_USER_UNKNOWN && pamh->user) ? pamh->user : "?",
- -1, pamh->rhost, NULL, pamh->tty, retval == PAM_SUCCESS );
+ if (asprintf(&buf, "PAM:%s%s%s", message, grantors_field, grantors) >= 0) {
+ rc = audit_log_acct_message(audit_fd, type, NULL, buf,
+ (retval != PAM_USER_UNKNOWN && pamh->user) ? pamh->user : "?",
+ -1, pamh->rhost, NULL, pamh->tty, retval == PAM_SUCCESS);
+ free(buf);
+ }
/* libaudit sets errno to his own negative error code. This can be
an official errno number, but must not. It can also be a audit
@@ -78,12 +85,54 @@ _pam_audit_open(pam_handle_t *pamh)
return audit_fd;
}
+static int
+_pam_list_grantors(struct handler *hlist, int retval, char **list)
+{
+ *list = NULL;
+
+ if (retval == PAM_SUCCESS) {
+ struct handler *h;
+ char *p = NULL;
+ size_t len = 0;
+
+ for (h = hlist; h != NULL; h = h->next) {
+ if (h->grantor) {
+ len += strlen(h->mod_name) + 1;
+ }
+ }
+
+ if (len == 0) {
+ return 0;
+ }
+
+ *list = malloc(len);
+ if (*list == NULL) {
+ return -1;
+ }
+
+ for (h = hlist; h != NULL; h = h->next) {
+ if (h->grantor) {
+ if (p == NULL) {
+ p = *list;
+ } else {
+ p = stpcpy(p, ",");
+ }
+
+ p = stpcpy(p, h->mod_name);
+ }
+ }
+ }
+
+ return 0;
+}
+
int
-_pam_auditlog(pam_handle_t *pamh, int action, int retval, int flags)
+_pam_auditlog(pam_handle_t *pamh, int action, int retval, int flags, struct handler *h)
{
const char *message;
int type;
int audit_fd;
+ char *grantors;
if ((audit_fd=_pam_audit_open(pamh)) == -1) {
return PAM_SYSTEM_ERR;
@@ -134,8 +183,17 @@ _pam_auditlog(pam_handle_t *pamh, int action, int retval, int flags)
retval = PAM_SYSTEM_ERR;
}
- if (_pam_audit_writelog(pamh, audit_fd, type, message, retval) < 0)
+ if (_pam_list_grantors(h, retval, &grantors) < 0) {
+ /* allocation failure */
+ pam_syslog(pamh, LOG_CRIT, "_pam_list_grantors() failed: %m");
retval = PAM_SYSTEM_ERR;
+ }
+
+ if (_pam_audit_writelog(pamh, audit_fd, type, message,
+ grantors ? grantors : "?", retval) < 0)
+ retval = PAM_SYSTEM_ERR;
+
+ free(grantors);
audit_close(audit_fd);
return retval;
@@ -149,7 +207,7 @@ _pam_audit_end(pam_handle_t *pamh, int status UNUSED)
* stacks having been run. Assume that this is sshd faking
* things for an unknown user.
*/
- _pam_auditlog(pamh, _PAM_ACTION_DONE, PAM_USER_UNKNOWN, 0);
+ _pam_auditlog(pamh, _PAM_ACTION_DONE, PAM_USER_UNKNOWN, 0, NULL);
}
return 0;
@@ -168,7 +226,7 @@ pam_modutil_audit_write(pam_handle_t *pamh, int type,
return retval;
}
- rc = _pam_audit_writelog(pamh, audit_fd, type, message, retval);
+ rc = _pam_audit_writelog(pamh, audit_fd, type, message, NULL, retval);
audit_close(audit_fd);
diff --git a/libpam/pam_auth.c b/libpam/pam_auth.c
index 5984fa5..1e7bc6e 100644
--- a/libpam/pam_auth.c
+++ b/libpam/pam_auth.c
@@ -45,10 +45,6 @@ int pam_authenticate(pam_handle_t *pamh, int flags)
prelude_send_alert(pamh, retval);
#endif
-#ifdef HAVE_LIBAUDIT
- retval = _pam_auditlog(pamh, PAM_AUTHENTICATE, retval, flags);
-#endif
-
return retval;
}
@@ -71,10 +67,6 @@ int pam_setcred(pam_handle_t *pamh, int flags)
retval = _pam_dispatch(pamh, flags, PAM_SETCRED);
-#ifdef HAVE_LIBAUDIT
- retval = _pam_auditlog(pamh, PAM_SETCRED, retval, flags);
-#endif
-
D(("pam_setcred exit"));
return retval;
diff --git a/libpam/pam_dispatch.c b/libpam/pam_dispatch.c
index eb52c82..cf632e8 100644
--- a/libpam/pam_dispatch.c
+++ b/libpam/pam_dispatch.c
@@ -217,8 +217,14 @@ static int _pam_dispatch_aux(pam_handle_t *pamh, int flags, struct handler *h,
status = retval;
}
}
- if ( impression == _PAM_POSITIVE && action == _PAM_ACTION_DONE ) {
- goto decision_made;
+ if ( impression == _PAM_POSITIVE ) {
+ if ( retval == PAM_SUCCESS ) {
+ h->grantor = 1;
+ }
+
+ if ( action == _PAM_ACTION_DONE ) {
+ goto decision_made;
+ }
}
break;
@@ -262,6 +268,9 @@ static int _pam_dispatch_aux(pam_handle_t *pamh, int flags, struct handler *h,
|| (impression == _PAM_POSITIVE
&& status == PAM_SUCCESS) ) {
if ( retval != PAM_IGNORE || cached_retval == retval ) {
+ if ( impression == _PAM_UNDEF && retval == PAM_SUCCESS ) {
+ h->grantor = 1;
+ }
impression = _PAM_POSITIVE;
status = retval;
}
@@ -308,6 +317,13 @@ decision_made: /* by getting here we have made a decision */
return status;
}
+static void _pam_clear_grantors(struct handler *h)
+{
+ for (; h != NULL; h = h->next) {
+ h->grantor = 0;
+ }
+}
+
/*
* This function translates the module dispatch request into a pointer
* to the stack of modules that will actually be run. the
@@ -318,21 +334,21 @@ decision_made: /* by getting here we have made a decision */
int _pam_dispatch(pam_handle_t *pamh, int flags, int choice)
{
struct handler *h = NULL;
- int retval, use_cached_chain;
+ int retval = PAM_SYSTEM_ERR, use_cached_chain;
_pam_boolean resumed;
IF_NO_PAMH("_pam_dispatch", pamh, PAM_SYSTEM_ERR);
if (__PAM_FROM_MODULE(pamh)) {
D(("called from a module!?"));
- return PAM_SYSTEM_ERR;
+ goto end;
}
/* Load all modules, resolve all symbols */
if ((retval = _pam_init_handlers(pamh)) != PAM_SUCCESS) {
pam_syslog(pamh, LOG_ERR, "unable to dispatch function");
- return retval;
+ goto end;
}
use_cached_chain = _PAM_PLEASE_FREEZE;
@@ -360,7 +376,8 @@ int _pam_dispatch(pam_handle_t *pamh, int flags, int choice)
break;
default:
pam_syslog(pamh, LOG_ERR, "undefined fn choice; %d", choice);
- return PAM_ABORT;
+ retval = PAM_ABORT;
+ goto end;
}
if (h == NULL) { /* there was no handlers.conf... entry; will use
@@ -393,11 +410,13 @@ int _pam_dispatch(pam_handle_t *pamh, int flags, int choice)
pam_syslog(pamh, LOG_ERR,
"application failed to re-exec stack [%d:%d]",
pamh->former.choice, choice);
- return PAM_ABORT;
+ retval = PAM_ABORT;
+ goto end;
}
resumed = PAM_TRUE;
} else {
resumed = PAM_FALSE;
+ _pam_clear_grantors(h);
}
__PAM_TO_MODULE(pamh);
@@ -417,5 +436,13 @@ int _pam_dispatch(pam_handle_t *pamh, int flags, int choice)
pamh->former.choice = PAM_NOT_STACKED;
}
+end:
+
+#ifdef HAVE_LIBAUDIT
+ if (choice != PAM_CHAUTHTOK || flags & PAM_UPDATE_AUTHTOK || retval != PAM_SUCCESS) {
+ retval = _pam_auditlog(pamh, choice, retval, flags, h);
+ }
+#endif
+
return retval;
}
diff --git a/libpam/pam_handlers.c b/libpam/pam_handlers.c
index 02714f7..df3a1d9 100644
--- a/libpam/pam_handlers.c
+++ b/libpam/pam_handlers.c
@@ -611,6 +611,12 @@ extract_modulename(const char *mod_path)
if (dot)
*dot = '\0';
+ if (*retval == '\0' || strcmp(retval, "?") == 0) {
+ /* do not allow empty module name or "?" to avoid confusing audit trail */
+ _pam_drop(retval);
+ return NULL;
+ }
+
return retval;
}
@@ -888,7 +894,9 @@ int _pam_add_handler(pam_handle_t *pamh
(*handler_p)->cached_retval_p = &((*handler_p)->cached_retval);
(*handler_p)->argc = argc;
(*handler_p)->argv = argv; /* not a copy */
- (*handler_p)->mod_name = extract_modulename(mod_path);
+ if (((*handler_p)->mod_name = extract_modulename(mod_path)) == NULL)
+ return PAM_ABORT;
+ (*handler_p)->grantor = 0;
(*handler_p)->next = NULL;
/* some of the modules have a second calling function */
@@ -920,7 +928,9 @@ int _pam_add_handler(pam_handle_t *pamh
} else {
(*handler_p2)->argv = NULL; /* no arguments */
}
- (*handler_p2)->mod_name = extract_modulename(mod_path);
+ if (((*handler_p2)->mod_name = extract_modulename(mod_path)) == NULL)
+ return PAM_ABORT;
+ (*handler_p2)->grantor = 0;
(*handler_p2)->next = NULL;
}
diff --git a/libpam/pam_password.c b/libpam/pam_password.c
index 75db5e5..592e01f 100644
--- a/libpam/pam_password.c
+++ b/libpam/pam_password.c
@@ -57,9 +57,5 @@ int pam_chauthtok(pam_handle_t *pamh, int flags)
D(("will resume when ready", retval));
}
-#ifdef HAVE_LIBAUDIT
- retval = _pam_auditlog(pamh, PAM_CHAUTHTOK, retval, flags);
-#endif
-
return retval;
}
diff --git a/libpam/pam_private.h b/libpam/pam_private.h
index 134dc72..d93283c 100644
--- a/libpam/pam_private.h
+++ b/libpam/pam_private.h
@@ -55,6 +55,7 @@ struct handler {
struct handler *next;
char *mod_name;
int stack_level;
+ int grantor;
};
#define PAM_HT_MODULE 0
@@ -316,7 +317,7 @@ if ((pamh) == NULL) { \
do { (pamh)->caller_is = _PAM_CALLED_FROM_APP; } while (0)
#ifdef HAVE_LIBAUDIT
-extern int _pam_auditlog(pam_handle_t *pamh, int action, int retval, int flags);
+extern int _pam_auditlog(pam_handle_t *pamh, int action, int retval, int flags, struct handler *h);
extern int _pam_audit_end(pam_handle_t *pamh, int pam_status);
#endif
diff --git a/libpam/pam_session.c b/libpam/pam_session.c
index 512153f..cb393c1 100644
--- a/libpam/pam_session.c
+++ b/libpam/pam_session.c
@@ -22,9 +22,6 @@ int pam_open_session(pam_handle_t *pamh, int flags)
}
retval = _pam_dispatch(pamh, flags, PAM_OPEN_SESSION);
-#ifdef HAVE_LIBAUDIT
- retval = _pam_auditlog(pamh, PAM_OPEN_SESSION, retval, flags);
-#endif
return retval;
}
@@ -43,10 +40,6 @@ int pam_close_session(pam_handle_t *pamh, int flags)
retval = _pam_dispatch(pamh, flags, PAM_CLOSE_SESSION);
-#ifdef HAVE_LIBAUDIT
- retval = _pam_auditlog(pamh, PAM_CLOSE_SESSION, retval, flags);
-#endif
-
return retval;
}
--
1.8.3.1

View file

@ -0,0 +1,53 @@
--- a/modules/pam_faillock/main.c.audit-user-mgmt 2014-10-17 12:09:12.928490104 +0200
+++ b/modules/pam_faillock/main.c 2014-10-17 12:09:43.001169008 +0200
@@ -127,7 +127,6 @@ do_user(struct options *opts, const char
}
if (opts->reset) {
#ifdef HAVE_LIBAUDIT
- char buf[64];
int audit_fd;
#endif
@@ -141,10 +140,8 @@ do_user(struct options *opts, const char
if ((audit_fd=audit_open()) >= 0) {
if (pwd != NULL) {
- snprintf(buf, sizeof(buf), "faillock reset uid=%u",
- pwd->pw_uid);
- audit_log_user_message(audit_fd, AUDIT_USER_ACCT,
- buf, NULL, NULL, NULL, rv == 0);
+ audit_log_acct_message(audit_fd, AUDIT_USER_MGMT, NULL,
+ "faillock-reset", NULL, pwd->pw_uid, NULL, NULL, NULL, rv == 0);
}
close(audit_fd);
}
--- a/modules/pam_tally2/pam_tally2.c.audit-user-mgmt 2013-06-18 16:11:21.000000000 +0200
+++ b/modules/pam_tally2/pam_tally2.c 2014-10-17 12:09:12.965490940 +0200
@@ -997,9 +997,9 @@ main( int argc UNUSED, char **argv )
#ifdef HAVE_LIBAUDIT
char buf[64];
int audit_fd = audit_open();
- snprintf(buf, sizeof(buf), "pam_tally2 uid=%u reset=%hu", uid, cline_reset);
- audit_log_user_message(audit_fd, AUDIT_USER_ACCT,
- buf, NULL, NULL, ttyname(STDIN_FILENO), 1);
+ snprintf(buf, sizeof(buf), "pam_tally2 reset=%hu", cline_reset);
+ audit_log_acct_message(audit_fd, AUDIT_USER_MGMT, NULL,
+ buf, NULL, uid, NULL, NULL, ttyname(STDIN_FILENO), 1);
if (audit_fd >=0)
close(audit_fd);
#endif
@@ -1040,11 +1040,10 @@ main( int argc UNUSED, char **argv )
}
else if ( !cline_reset ) {
#ifdef HAVE_LIBAUDIT
- char buf[64];
int audit_fd = audit_open();
- snprintf(buf, sizeof(buf), "pam_tally2 uid=all reset=0");
- audit_log_user_message(audit_fd, AUDIT_USER_ACCT,
- buf, NULL, NULL, ttyname(STDIN_FILENO), 1);
+ audit_log_acct_message(audit_fd, AUDIT_USER_MGMT, NULL,
+ "pam_tally2-reset-all-accts reset=0", "*", -1,
+ NULL, NULL, ttyname(STDIN_FILENO), 1);
if (audit_fd >=0)
close(audit_fd);
#endif

View file

@ -0,0 +1,21 @@
diff -up Linux-PAM-1.1.8/modules/pam_selinux/pam_selinux.c.canonicalize Linux-PAM-1.1.8/modules/pam_selinux/pam_selinux.c
--- Linux-PAM-1.1.8/modules/pam_selinux/pam_selinux.c.canonicalize 2013-06-18 16:11:21.000000000 +0200
+++ Linux-PAM-1.1.8/modules/pam_selinux/pam_selinux.c 2014-03-06 12:03:54.429639972 +0100
@@ -491,12 +491,17 @@ compute_exec_context(pam_handle_t *pamh,
char *level = NULL;
security_context_t *contextlist = NULL;
int num_contexts = 0;
+ const struct passwd *pwd;
if (!(username = get_item(pamh, PAM_USER))) {
pam_syslog(pamh, LOG_ERR, "Cannot obtain the user name");
return PAM_USER_UNKNOWN;
}
+ if ((pwd = pam_modutil_getpwnam(pamh, username)) != NULL) {
+ username = pwd->pw_name;
+ } /* ignore error and keep using original username */
+
/* compute execute context */
#ifdef HAVE_GETSEUSER
if (!(service = get_item(pamh, PAM_SERVICE))) {

108
pam-1.1.8-full-relro.patch Normal file
View file

@ -0,0 +1,108 @@
diff -up Linux-PAM-1.1.8/modules/pam_console/Makefile.am.relro Linux-PAM-1.1.8/modules/pam_console/Makefile.am
--- Linux-PAM-1.1.8/modules/pam_console/Makefile.am.relro 2014-08-13 16:02:49.000000000 +0200
+++ Linux-PAM-1.1.8/modules/pam_console/Makefile.am 2014-09-10 17:14:33.245554314 +0200
@@ -33,6 +33,8 @@ pam_console_la_LIBADD = -L$(top_builddir
pam_console_apply_LDADD = -L$(top_builddir)/libpam -lpam
+pam_console_apply_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@
+
securelib_LTLIBRARIES = pam_console.la
sbin_PROGRAMS = pam_console_apply
@@ -47,7 +49,7 @@ pam_console_apply_SOURCES = pam_console_
configfile.c configfile.h hashtable.c hashtable.h hashtable_private.h
pam_console_la_CFLAGS = $(AM_CFLAGS)
-pam_console_apply_CFLAGS = $(AM_CFLAGS)
+pam_console_apply_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@
configfile.tab.c: configfile.y
$(YACC) $(BISON_OPTS) -o $@ -p _pc_yy $<
diff -up Linux-PAM-1.1.8/modules/pam_faillock/Makefile.am.relro Linux-PAM-1.1.8/modules/pam_faillock/Makefile.am
--- Linux-PAM-1.1.8/modules/pam_faillock/Makefile.am.relro 2014-08-13 16:02:49.000000000 +0200
+++ Linux-PAM-1.1.8/modules/pam_faillock/Makefile.am 2014-09-10 17:16:11.102808189 +0200
@@ -19,7 +19,7 @@ secureconfdir = $(SCONFIGDIR)
noinst_HEADERS = faillock.h
-faillock_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include
+faillock_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include @PIE_CFLAGS@
pam_faillock_la_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include
pam_faillock_la_LDFLAGS = -no-undefined -avoid-version -module
@@ -28,6 +28,7 @@ if HAVE_VERSIONING
pam_faillock_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
endif
+faillock_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@
faillock_LDADD = -L$(top_builddir)/libpam -lpam $(LIBAUDIT)
securelib_LTLIBRARIES = pam_faillock.la
diff -up Linux-PAM-1.1.8/modules/pam_filter/upperLOWER/Makefile.am.relro Linux-PAM-1.1.8/modules/pam_filter/upperLOWER/Makefile.am
--- Linux-PAM-1.1.8/modules/pam_filter/upperLOWER/Makefile.am.relro 2014-09-10 17:17:20.273401344 +0200
+++ Linux-PAM-1.1.8/modules/pam_filter/upperLOWER/Makefile.am 2014-09-10 17:17:07.857115369 +0200
@@ -9,7 +9,7 @@ securelibfilterdir = $(SECUREDIR)/pam_fi
AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
-I$(srcdir)/.. @PIE_CFLAGS@
-AM_LDFLAGS = @PIE_LDFLAGS@
+AM_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@
LDADD = $(top_builddir)/libpam/libpam.la
securelibfilter_PROGRAMS = upperLOWER
diff -up Linux-PAM-1.1.8/modules/pam_mkhomedir/Makefile.am.relro Linux-PAM-1.1.8/modules/pam_mkhomedir/Makefile.am
--- Linux-PAM-1.1.8/modules/pam_mkhomedir/Makefile.am.relro 2013-06-18 16:11:21.000000000 +0200
+++ Linux-PAM-1.1.8/modules/pam_mkhomedir/Makefile.am 2014-09-10 17:18:42.922304935 +0200
@@ -30,6 +30,8 @@ endif
sbin_PROGRAMS = mkhomedir_helper
mkhomedir_helper_SOURCES = mkhomedir_helper.c
+mkhomedir_helper_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@
+mkhomedir_helper_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@
mkhomedir_helper_LDADD = $(top_builddir)/libpam/libpam.la
if ENABLE_REGENERATE_MAN
diff -up Linux-PAM-1.1.8/modules/pam_tally2/Makefile.am.relro Linux-PAM-1.1.8/modules/pam_tally2/Makefile.am
--- Linux-PAM-1.1.8/modules/pam_tally2/Makefile.am.relro 2013-06-18 16:11:21.000000000 +0200
+++ Linux-PAM-1.1.8/modules/pam_tally2/Makefile.am 2014-09-10 17:22:04.339944040 +0200
@@ -26,6 +26,8 @@ if HAVE_VERSIONING
pam_tally2_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
endif
+pam_tally2_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@
+pam_tally2_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@
pam_tally2_LDADD = $(top_builddir)/libpam/libpam.la $(LIBAUDIT)
securelib_LTLIBRARIES = pam_tally2.la
diff -up Linux-PAM-1.1.8/modules/pam_timestamp/Makefile.am.relro Linux-PAM-1.1.8/modules/pam_timestamp/Makefile.am
--- Linux-PAM-1.1.8/modules/pam_timestamp/Makefile.am.relro 2013-06-18 16:11:21.000000000 +0200
+++ Linux-PAM-1.1.8/modules/pam_timestamp/Makefile.am 2014-08-13 16:02:49.906688139 +0200
@@ -36,7 +36,7 @@ pam_timestamp_la_CFLAGS = $(AM_CFLAGS)
pam_timestamp_check_SOURCES = pam_timestamp_check.c
pam_timestamp_check_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@
pam_timestamp_check_LDADD = $(top_builddir)/libpam/libpam.la
-pam_timestamp_check_LDFLAGS = @PIE_LDFLAGS@
+pam_timestamp_check_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@
hmacfile_SOURCES = hmacfile.c hmacsha1.c sha1.c
hmacfile_LDADD = $(top_builddir)/libpam/libpam.la
diff -up Linux-PAM-1.1.8/modules/pam_unix/Makefile.am.relro Linux-PAM-1.1.8/modules/pam_unix/Makefile.am
--- Linux-PAM-1.1.8/modules/pam_unix/Makefile.am.relro 2013-06-18 16:11:21.000000000 +0200
+++ Linux-PAM-1.1.8/modules/pam_unix/Makefile.am 2014-08-13 16:02:49.906688139 +0200
@@ -55,13 +55,13 @@ bigcrypt_LDADD = @LIBCRYPT@
unix_chkpwd_SOURCES = unix_chkpwd.c md5_good.c md5_broken.c bigcrypt.c \
passverify.c
unix_chkpwd_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@ -DHELPER_COMPILE=\"unix_chkpwd\"
-unix_chkpwd_LDFLAGS = @PIE_LDFLAGS@
+unix_chkpwd_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@
unix_chkpwd_LDADD = @LIBCRYPT@ @LIBSELINUX@ @LIBAUDIT@
unix_update_SOURCES = unix_update.c md5_good.c md5_broken.c bigcrypt.c \
passverify.c
unix_update_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@ -DHELPER_COMPILE=\"unix_update\"
-unix_update_LDFLAGS = @PIE_LDFLAGS@
+unix_update_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@
unix_update_LDADD = @LIBCRYPT@ @LIBSELINUX@
if ENABLE_REGENERATE_MAN

View file

@ -0,0 +1,37 @@
diff -up Linux-PAM-1.1.8/modules/pam_lastlog/pam_lastlog.c.uninitialized Linux-PAM-1.1.8/modules/pam_lastlog/pam_lastlog.c
--- Linux-PAM-1.1.8/modules/pam_lastlog/pam_lastlog.c.uninitialized 2013-06-18 16:11:21.000000000 +0200
+++ Linux-PAM-1.1.8/modules/pam_lastlog/pam_lastlog.c 2014-08-25 16:44:24.365174752 +0200
@@ -350,6 +350,8 @@ last_login_write(pam_handle_t *pamh, int
return PAM_SERVICE_ERR;
}
+ memset(&last_login, 0, sizeof(last_login));
+
/* set this login date */
D(("set the most recent login time"));
(void) time(&ll_time); /* set the time */
@@ -364,14 +366,12 @@ last_login_write(pam_handle_t *pamh, int
}
/* copy to last_login */
- last_login.ll_host[0] = '\0';
strncat(last_login.ll_host, remote_host, sizeof(last_login.ll_host)-1);
/* set the terminal line */
terminal_line = get_tty(pamh);
/* copy to last_login */
- last_login.ll_line[0] = '\0';
strncat(last_login.ll_line, terminal_line, sizeof(last_login.ll_line)-1);
terminal_line = NULL;
@@ -628,7 +628,8 @@ pam_sm_authenticate(pam_handle_t *pamh,
lltime = (time(NULL) - lltime) / (24*60*60);
if (lltime > inactive_days) {
- pam_syslog(pamh, LOG_INFO, "user %s inactive for %d days - denied", user, lltime);
+ pam_syslog(pamh, LOG_INFO, "user %s inactive for %ld days - denied",
+ user, (long) lltime);
return PAM_AUTH_ERR;
}

View file

@ -0,0 +1,41 @@
diff -up Linux-PAM-1.1.8/modules/pam_limits/pam_limits.c.check-process Linux-PAM-1.1.8/modules/pam_limits/pam_limits.c
--- Linux-PAM-1.1.8/modules/pam_limits/pam_limits.c.check-process 2013-06-18 16:11:21.000000000 +0200
+++ Linux-PAM-1.1.8/modules/pam_limits/pam_limits.c 2014-09-10 16:39:36.263256066 +0200
@@ -27,6 +27,7 @@
#include <errno.h>
#include <syslog.h>
#include <stdarg.h>
+#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/resource.h>
@@ -269,16 +270,27 @@ check_logins (pam_handle_t *pamh, const
continue;
}
if (!pl->flag_numsyslogins) {
+ char user[sizeof(ut->UT_USER) + 1];
+ user[0] = '\0';
+ strncat(user, ut->UT_USER, sizeof(ut->UT_USER));
+
if (((pl->login_limit_def == LIMITS_DEF_USER)
|| (pl->login_limit_def == LIMITS_DEF_GROUP)
|| (pl->login_limit_def == LIMITS_DEF_DEFAULT))
- && strncmp(name, ut->UT_USER, sizeof(ut->UT_USER)) != 0) {
+ && strcmp(name, user) != 0) {
continue;
}
if ((pl->login_limit_def == LIMITS_DEF_ALLGROUP)
- && !pam_modutil_user_in_group_nam_nam(pamh, ut->UT_USER, pl->login_group)) {
+ && !pam_modutil_user_in_group_nam_nam(pamh, user, pl->login_group)) {
continue;
}
+ if (kill(ut->ut_pid, 0) == -1 && errno == ESRCH) {
+ /* process does not exist anymore */
+ pam_syslog(pamh, LOG_WARNING,
+ "Stale utmp entry (pid %d) for '%s' ignored",
+ ut->ut_pid, user);
+ continue;
+ }
}
if (++count > limit) {
break;

View file

@ -0,0 +1,54 @@
diff -up Linux-PAM-1.1.8/modules/pam_limits/limits.conf.docfix Linux-PAM-1.1.8/modules/pam_limits/limits.conf
--- Linux-PAM-1.1.8/modules/pam_limits/limits.conf.docfix 2014-07-14 14:58:05.000000000 +0200
+++ Linux-PAM-1.1.8/modules/pam_limits/limits.conf 2014-09-10 16:42:51.254747161 +0200
@@ -32,7 +32,7 @@
# - data - max data size (KB)
# - fsize - maximum filesize (KB)
# - memlock - max locked-in-memory address space (KB)
-# - nofile - max number of open files
+# - nofile - max number of open file descriptors
# - rss - max resident set size (KB)
# - stack - max stack size (KB)
# - cpu - max CPU time (MIN)
diff -up Linux-PAM-1.1.8/modules/pam_limits/limits.conf.5.xml.docfix Linux-PAM-1.1.8/modules/pam_limits/limits.conf.5.xml
--- Linux-PAM-1.1.8/modules/pam_limits/limits.conf.5.xml.docfix 2013-06-18 16:11:21.000000000 +0200
+++ Linux-PAM-1.1.8/modules/pam_limits/limits.conf.5.xml 2014-09-10 16:44:01.624367933 +0200
@@ -178,7 +178,7 @@
<varlistentry>
<term><option>nofile</option></term>
<listitem>
- <para>maximum number of open files</para>
+ <para>maximum number of open file descriptors</para>
</listitem>
</varlistentry>
<varlistentry>
@@ -214,14 +214,17 @@
<varlistentry>
<term><option>maxlogins</option></term>
<listitem>
- <para>maximum number of logins for this user except
- for this with <emphasis>uid=0</emphasis></para>
+ <para>maximum number of logins for this user (this limit does
+ not apply to user with <emphasis>uid=0</emphasis>)</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>maxsyslogins</option></term>
<listitem>
- <para>maximum number of all logins on system</para>
+ <para>maximum number of all logins on system; user is not
+ allowed to log-in if total number of all users' logins is
+ greater than specified number (this limit does not apply to
+ user with <emphasis>uid=0</emphasis>)</para>
</listitem>
</varlistentry>
<varlistentry>
@@ -292,7 +295,7 @@
permanent; existing only for the duration of the session.
One exception is the <emphasis>maxlogin</emphasis> option, this one
is system wide. But there is a race, concurrent logins at the same
- time will not always be detect as such but only counted as one.
+ time will not always be detected as such but only counted as one.
</para>
<para>
In the <emphasis>limits</emphasis> configuration file, the

View file

@ -0,0 +1,151 @@
diff -up Linux-PAM-1.1.8/modules/pam_loginuid/pam_loginuid.c.container Linux-PAM-1.1.8/modules/pam_loginuid/pam_loginuid.c
--- Linux-PAM-1.1.8/modules/pam_loginuid/pam_loginuid.c.container 2013-06-18 16:11:21.000000000 +0200
+++ Linux-PAM-1.1.8/modules/pam_loginuid/pam_loginuid.c 2014-01-27 17:24:53.000000000 +0100
@@ -47,25 +47,56 @@
/*
* This function writes the loginuid to the /proc system. It returns
- * 0 on success and 1 on failure.
+ * PAM_SUCCESS on success,
+ * PAM_IGNORE when /proc/self/loginuid does not exist,
+ * PAM_SESSION_ERR in case of any other error.
*/
static int set_loginuid(pam_handle_t *pamh, uid_t uid)
{
- int fd, count, rc = 0;
- char loginuid[24];
+ int fd, count, rc = PAM_SESSION_ERR;
+ char loginuid[24], buf[24];
+ static const char host_uid_map[] = " 0 0 4294967295\n";
+ char uid_map[sizeof(host_uid_map)];
+
+ /* loginuid in user namespaces currently isn't writable and in some
+ case, not even readable, so consider any failure as ignorable (but try
+ anyway, in case we hit a kernel which supports it). */
+ fd = open("/proc/self/uid_map", O_RDONLY);
+ if (fd >= 0) {
+ count = pam_modutil_read(fd, uid_map, sizeof(uid_map));
+ if (strncmp(uid_map, host_uid_map, count) != 0)
+ rc = PAM_IGNORE;
+ close(fd);
+ }
- count = snprintf(loginuid, sizeof(loginuid), "%lu", (unsigned long)uid);
- fd = open("/proc/self/loginuid", O_NOFOLLOW|O_WRONLY|O_TRUNC);
+ fd = open("/proc/self/loginuid", O_NOFOLLOW|O_RDWR);
if (fd < 0) {
- if (errno != ENOENT) {
- rc = 1;
- pam_syslog(pamh, LOG_ERR,
- "Cannot open /proc/self/loginuid: %m");
+ if (errno == ENOENT) {
+ rc = PAM_IGNORE;
+ }
+ if (rc != PAM_IGNORE) {
+ pam_syslog(pamh, LOG_ERR, "Cannot open %s: %m",
+ "/proc/self/loginuid");
}
return rc;
}
- if (pam_modutil_write(fd, loginuid, count) != count)
- rc = 1;
+
+ count = snprintf(loginuid, sizeof(loginuid), "%lu", (unsigned long)uid);
+ if (pam_modutil_read(fd, buf, sizeof(buf)) == count &&
+ memcmp(buf, loginuid, count) == 0) {
+ rc = PAM_SUCCESS;
+ goto done; /* already correct */
+ }
+ if (lseek(fd, 0, SEEK_SET) == 0 && ftruncate(fd, 0) == 0 &&
+ pam_modutil_write(fd, loginuid, count) == count) {
+ rc = PAM_SUCCESS;
+ } else {
+ if (rc != PAM_IGNORE) {
+ pam_syslog(pamh, LOG_ERR, "Error writing %s: %m",
+ "/proc/self/loginuid");
+ }
+ }
+ done:
close(fd);
return rc;
}
@@ -165,6 +196,7 @@ _pam_loginuid(pam_handle_t *pamh, int fl
{
const char *user = NULL;
struct passwd *pwd;
+ int ret;
#ifdef HAVE_LIBAUDIT
int require_auditd = 0;
#endif
@@ -183,9 +215,14 @@ _pam_loginuid(pam_handle_t *pamh, int fl
return PAM_SESSION_ERR;
}
- if (set_loginuid(pamh, pwd->pw_uid)) {
- pam_syslog(pamh, LOG_ERR, "set_loginuid failed\n");
- return PAM_SESSION_ERR;
+ ret = set_loginuid(pamh, pwd->pw_uid);
+ switch (ret) {
+ case PAM_SUCCESS:
+ case PAM_IGNORE:
+ break;
+ default:
+ pam_syslog(pamh, LOG_ERR, "set_loginuid failed");
+ return ret;
}
#ifdef HAVE_LIBAUDIT
@@ -195,11 +232,12 @@ _pam_loginuid(pam_handle_t *pamh, int fl
argv++;
}
- if (require_auditd)
- return check_auditd();
- else
+ if (require_auditd) {
+ int rc = check_auditd();
+ return rc != PAM_SUCCESS ? rc : ret;
+ } else
#endif
- return PAM_SUCCESS;
+ return ret;
}
/*
diff -up Linux-PAM-1.1.8/modules/pam_loginuid/pam_loginuid.8.xml.container Linux-PAM-1.1.8/modules/pam_loginuid/pam_loginuid.8.xml
--- Linux-PAM-1.1.8/modules/pam_loginuid/pam_loginuid.8.xml.container 2013-06-18 16:11:21.000000000 +0200
+++ Linux-PAM-1.1.8/modules/pam_loginuid/pam_loginuid.8.xml 2014-05-22 11:33:14.000000000 +0200
@@ -69,14 +69,31 @@
<para>
<variablelist>
<varlistentry>
+ <term>PAM_SUCCESS</term>
+ <listitem>
+ <para>
+ The loginuid value is set and auditd is running if check requested.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>PAM_IGNORE</term>
+ <listitem>
+ <para>
+ The /proc/self/loginuid file is not present on the system or the
+ login process runs inside uid namespace and kernel does not support
+ overwriting loginuid.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
<term>PAM_SESSION_ERR</term>
<listitem>
<para>
- An error occurred during session management.
+ Any other error prevented setting loginuid or auditd is not running.
</para>
</listitem>
</varlistentry>
-
</variablelist>
</para>
</refsect1>

View file

@ -0,0 +1,22 @@
diff -up Linux-PAM-1.1.8/modules/pam_userdb/pam_userdb.8.xml.dbsuffix Linux-PAM-1.1.8/modules/pam_userdb/pam_userdb.8.xml
--- Linux-PAM-1.1.8/modules/pam_userdb/pam_userdb.8.xml.dbsuffix 2013-06-18 16:11:21.000000000 +0200
+++ Linux-PAM-1.1.8/modules/pam_userdb/pam_userdb.8.xml 2014-09-10 16:28:19.916678273 +0200
@@ -89,7 +89,8 @@
Use the <filename>/path/database</filename> database for
performing lookup. There is no default; the module will
return <emphasis remap='B'>PAM_IGNORE</emphasis> if no
- database is provided.
+ database is provided. Note that the path to the database file
+ should be specified without the <filename>.db</filename> suffix.
</para>
</listitem>
</varlistentry>
@@ -260,7 +261,7 @@
<refsect1 id='pam_userdb-examples'>
<title>EXAMPLES</title>
<programlisting>
-auth sufficient pam_userdb.so icase db=/etc/dbtest.db
+auth sufficient pam_userdb.so icase db=/etc/dbtest
</programlisting>
</refsect1>

View file

@ -0,0 +1,50 @@
diff --git a/modules/pam_pwhistory/opasswd.c b/modules/pam_pwhistory/opasswd.c
index 836d713..c36628e 100644
--- a/modules/pam_pwhistory/opasswd.c
+++ b/modules/pam_pwhistory/opasswd.c
@@ -82,10 +82,15 @@ parse_entry (char *line, opwd *data)
{
const char delimiters[] = ":";
char *endptr;
+ char *count;
data->user = strsep (&line, delimiters);
data->uid = strsep (&line, delimiters);
- data->count = strtol (strsep (&line, delimiters), &endptr, 10);
+ count = strsep (&line, delimiters);
+ if (data->user == NULL || data->uid == NULL || count == NULL)
+ return 1;
+
+ data->count = strtol (count, &endptr, 10);
if (endptr != NULL && *endptr != '\0')
return 1;
diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c
index 4840bb2..7f7bc49 100644
--- a/modules/pam_unix/passverify.c
+++ b/modules/pam_unix/passverify.c
@@ -639,11 +639,23 @@ save_old_password(pam_handle_t *pamh, const char *forwho, const char *oldpass,
continue;
buf[strlen(buf) - 1] = '\0';
s_luser = strtok_r(buf, ":", &sptr);
+ if (s_luser == NULL) {
+ found = 0;
+ continue;
+ }
s_uid = strtok_r(NULL, ":", &sptr);
+ if (s_uid == NULL) {
+ found = 0;
+ continue;
+ }
s_npas = strtok_r(NULL, ":", &sptr);
+ if (s_npas == NULL) {
+ found = 0;
+ continue;
+ }
s_pas = strtok_r(NULL, ":", &sptr);
npas = strtol(s_npas, NULL, 10) + 1;
- while (npas > howmany) {
+ while (npas > howmany && s_pas != NULL) {
s_pas = strpbrk(s_pas, ",");
if (s_pas != NULL)
s_pas++;

11
pam-1.1.8-pbuild.patch Normal file
View file

@ -0,0 +1,11 @@
diff -ur Linux-PAM-1.1.8.old/modules/pam_console/Makefile.am Linux-PAM-1.1.8/modules/pam_console/Makefile.am
--- Linux-PAM-1.1.8.old/modules/pam_console/Makefile.am 2015-01-21 13:49:13.000000000 +0300
+++ Linux-PAM-1.1.8/modules/pam_console/Makefile.am 2015-01-21 13:54:33.000000000 +0300
@@ -51,6 +51,7 @@
pam_console_la_CFLAGS = $(AM_CFLAGS)
pam_console_apply_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@
+configfile.tab.h: configfile.tab.c
configfile.tab.c: configfile.y
$(YACC) $(BISON_OPTS) -o $@ -p _pc_yy $<
sh $(srcdir)/sed-static $@

View file

@ -0,0 +1,813 @@
diff --git a/modules/pam_pwhistory/Makefile.am b/modules/pam_pwhistory/Makefile.am
index 4bb4d6d..9157b91 100644
--- a/modules/pam_pwhistory/Makefile.am
+++ b/modules/pam_pwhistory/Makefile.am
@@ -1,5 +1,6 @@
#
# Copyright (c) 2008, 2009 Thorsten Kukuk <kukuk@suse.de>
+# Copyright (c) 2013 Red Hat, Inc.
#
CLEANFILES = *~
@@ -9,25 +10,34 @@ EXTRA_DIST = README $(MANS) $(XMLS) tst-pam_pwhistory
TESTS = tst-pam_pwhistory
-man_MANS = pam_pwhistory.8
+man_MANS = pam_pwhistory.8 pwhistory_helper.8
-XMLS = README.xml pam_pwhistory.8.xml
+XMLS = README.xml pam_pwhistory.8.xml pwhistory_helper.8.xml
securelibdir = $(SECUREDIR)
secureconfdir = $(SCONFIGDIR)
-AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include
-AM_LDFLAGS = -no-undefined -avoid-version -module
+AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
+ -DPWHISTORY_HELPER=\"$(sbindir)/pwhistory_helper\"
+
+pam_pwhistory_la_LDFLAGS = -no-undefined -avoid-version -module
if HAVE_VERSIONING
- AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
+ pam_pwhistory_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
endif
noinst_HEADERS = opasswd.h
securelib_LTLIBRARIES = pam_pwhistory.la
-pam_pwhistory_la_LIBADD = $(top_builddir)/libpam/libpam.la @LIBCRYPT@
+pam_pwhistory_la_CFLAGS = $(AM_CFLAGS)
+pam_pwhistory_la_LIBADD = $(top_builddir)/libpam/libpam.la @LIBCRYPT@ @LIBSELINUX@
pam_pwhistory_la_SOURCES = pam_pwhistory.c opasswd.c
+sbin_PROGRAMS = pwhistory_helper
+pwhistory_helper_CFLAGS = $(AM_CFLAGS) -DHELPER_COMPILE=\"pwhistory_helper\" @PIE_CFLAGS@
+pwhistory_helper_SOURCES = pwhistory_helper.c opasswd.c
+pwhistory_helper_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@
+pwhistory_helper_LDADD = $(top_builddir)/libpam/libpam.la @LIBCRYPT@
+
if ENABLE_REGENERATE_MAN
noinst_DATA = README
README: pam_pwhistory.8.xml
diff --git a/modules/pam_pwhistory/opasswd.c b/modules/pam_pwhistory/opasswd.c
index 836d713..e319ff3 100644
--- a/modules/pam_pwhistory/opasswd.c
+++ b/modules/pam_pwhistory/opasswd.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2008 Thorsten Kukuk <kukuk@suse.de>
+ * Copyright (c) 2013 Red Hat, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -38,6 +39,7 @@
#endif
#include <pwd.h>
+#include <shadow.h>
#include <time.h>
#include <ctype.h>
#include <errno.h>
@@ -47,6 +49,7 @@
#include <string.h>
#include <stdlib.h>
#include <syslog.h>
+#include <stdarg.h>
#include <sys/stat.h>
#if defined (HAVE_XCRYPT_H)
@@ -55,7 +58,14 @@
#include <crypt.h>
#endif
+#ifdef HELPER_COMPILE
+#define pam_modutil_getpwnam(h,n) getpwnam(n)
+#define pam_modutil_getspnam(h,n) getspnam(n)
+#define pam_syslog(h,a,...) helper_log_err(a,__VA_ARGS__)
+#else
+#include <security/pam_modutil.h>
#include <security/pam_ext.h>
+#endif
#include <security/pam_modules.h>
#include "opasswd.h"
@@ -76,6 +86,19 @@ typedef struct {
char *old_passwords;
} opwd;
+#ifdef HELPER_COMPILE
+void
+helper_log_err(int err, const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ openlog(HELPER_COMPILE, LOG_CONS | LOG_PID, LOG_AUTHPRIV);
+ vsyslog(err, format, args);
+ va_end(args);
+ closelog();
+}
+#endif
static int
parse_entry (char *line, opwd *data)
@@ -112,8 +135,8 @@ compare_password(const char *newpass, const char *oldpass)
}
/* Check, if the new password is already in the opasswd file. */
-int
-check_old_pass (pam_handle_t *pamh, const char *user,
+PAMH_ARG_DECL(int
+check_old_pass, const char *user,
const char *newpass, int debug)
{
int retval = PAM_SUCCESS;
@@ -123,6 +146,11 @@ check_old_pass (pam_handle_t *pamh, const char *user,
opwd entry;
int found = 0;
+#ifndef HELPER_COMPILE
+ if (SELINUX_ENABLED)
+ return PAM_PWHISTORY_RUN_HELPER;
+#endif
+
if ((oldpf = fopen (OLD_PASSWORDS_FILE, "r")) == NULL)
{
if (errno != ENOENT)
@@ -208,9 +236,9 @@ check_old_pass (pam_handle_t *pamh, const char *user,
return retval;
}
-int
-save_old_pass (pam_handle_t *pamh, const char *user, uid_t uid,
- const char *oldpass, int howmany, int debug UNUSED)
+PAMH_ARG_DECL(int
+save_old_pass, const char *user,
+ int howmany, int debug UNUSED)
{
char opasswd_tmp[] = TMP_PASSWORDS_FILE;
struct stat opasswd_stat;
@@ -221,10 +249,35 @@ save_old_pass (pam_handle_t *pamh, const char *user, uid_t uid,
char *buf = NULL;
size_t buflen = 0;
int found = 0;
+ struct passwd *pwd;
+ const char *oldpass;
+
+ pwd = pam_modutil_getpwnam (pamh, user);
+ if (pwd == NULL)
+ return PAM_USER_UNKNOWN;
if (howmany <= 0)
return PAM_SUCCESS;
+#ifndef HELPER_COMPILE
+ if (SELINUX_ENABLED)
+ return PAM_PWHISTORY_RUN_HELPER;
+#endif
+
+ if ((strcmp(pwd->pw_passwd, "x") == 0) ||
+ ((pwd->pw_passwd[0] == '#') &&
+ (pwd->pw_passwd[1] == '#') &&
+ (strcmp(pwd->pw_name, pwd->pw_passwd + 2) == 0)))
+ {
+ struct spwd *spw = pam_modutil_getspnam (pamh, user);
+
+ if (spw == NULL)
+ return PAM_USER_UNKNOWN;
+ oldpass = spw->sp_pwdp;
+ }
+ else
+ oldpass = pwd->pw_passwd;
+
if (oldpass == NULL || *oldpass == '\0')
return PAM_SUCCESS;
@@ -447,7 +500,7 @@ save_old_pass (pam_handle_t *pamh, const char *user, uid_t uid,
{
char *out;
- if (asprintf (&out, "%s:%d:1:%s\n", user, uid, oldpass) < 0)
+ if (asprintf (&out, "%s:%d:1:%s\n", user, pwd->pw_uid, oldpass) < 0)
{
retval = PAM_AUTHTOK_ERR;
if (oldpf)
diff --git a/modules/pam_pwhistory/opasswd.h b/modules/pam_pwhistory/opasswd.h
index db3e656..1b08699 100644
--- a/modules/pam_pwhistory/opasswd.h
+++ b/modules/pam_pwhistory/opasswd.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2008 Thorsten Kukuk <kukuk@suse.de>
+ * Copyright (c) 2013 Red Hat, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -36,10 +37,32 @@
#ifndef __OPASSWD_H__
#define __OPASSWD_H__
-extern int check_old_pass (pam_handle_t *pamh, const char *user,
- const char *newpass, int debug);
-extern int save_old_pass (pam_handle_t *pamh, const char *user,
- uid_t uid, const char *oldpass,
- int howmany, int debug);
+#define PAM_PWHISTORY_RUN_HELPER PAM_CRED_INSUFFICIENT
+
+#ifdef WITH_SELINUX
+#include <selinux/selinux.h>
+#define SELINUX_ENABLED is_selinux_enabled()>0
+#else
+#define SELINUX_ENABLED 0
+#endif
+
+#ifdef HELPER_COMPILE
+#define PAMH_ARG_DECL(fname, ...) fname(__VA_ARGS__)
+#define PAMH_ARG(...) __VA_ARGS__
+#else
+#define PAMH_ARG_DECL(fname, ...) fname(pam_handle_t *pamh, __VA_ARGS__)
+#define PAMH_ARG(...) pamh, __VA_ARGS__
+#endif
+
+#ifdef HELPER_COMPILE
+void
+helper_log_err(int err, const char *format, ...);
+#endif
+
+PAMH_ARG_DECL(int
+check_old_pass, const char *user, const char *newpass, int debug);
+
+PAMH_ARG_DECL(int
+save_old_pass, const char *user, int howmany, int debug);
#endif /* __OPASSWD_H__ */
diff --git a/modules/pam_pwhistory/pam_pwhistory.c b/modules/pam_pwhistory/pam_pwhistory.c
index 654edd3..d6c5c47 100644
--- a/modules/pam_pwhistory/pam_pwhistory.c
+++ b/modules/pam_pwhistory/pam_pwhistory.c
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2008, 2012 Thorsten Kukuk
* Author: Thorsten Kukuk <kukuk@thkukuk.de>
+ * Copyright (c) 2013 Red Hat, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -46,10 +47,14 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <shadow.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <fcntl.h>
#include <security/pam_modules.h>
#include <security/pam_modutil.h>
@@ -59,6 +64,7 @@
#include "opasswd.h"
#define DEFAULT_BUFLEN 2048
+#define MAX_FD_NO 20000
struct options_t {
int debug;
@@ -102,6 +108,184 @@ parse_option (pam_handle_t *pamh, const char *argv, options_t *options)
pam_syslog (pamh, LOG_ERR, "pam_pwhistory: unknown option: %s", argv);
}
+static int
+run_save_helper(pam_handle_t *pamh, const char *user,
+ int howmany, int debug)
+{
+ int retval, child;
+ struct sigaction newsa, oldsa;
+
+ memset(&newsa, '\0', sizeof(newsa));
+ newsa.sa_handler = SIG_DFL;
+ sigaction(SIGCHLD, &newsa, &oldsa);
+
+ child = fork();
+ if (child == 0)
+ {
+ int i = 0;
+ struct rlimit rlim;
+ int dummyfds[2];
+ static char *envp[] = { NULL };
+ char *args[] = { NULL, NULL, NULL, NULL, NULL, NULL };
+
+ /* replace std file descriptors with a dummy pipe */
+ if (pipe2(dummyfds, O_NONBLOCK) == 0)
+ {
+ dup2(dummyfds[0], STDIN_FILENO);
+ dup2(dummyfds[1], STDOUT_FILENO);
+ dup2(dummyfds[1], STDERR_FILENO);
+ }
+
+ if (getrlimit(RLIMIT_NOFILE,&rlim) == 0)
+ {
+ if (rlim.rlim_max >= MAX_FD_NO)
+ rlim.rlim_max = MAX_FD_NO;
+ for (i = STDERR_FILENO + 1; i < (int)rlim.rlim_max; i++)
+ {
+ if (i != dummyfds[0])
+ close(i);
+ }
+ }
+
+ /* exec binary helper */
+ args[0] = strdup(PWHISTORY_HELPER);
+ args[1] = strdup("save");
+ args[2] = x_strdup(user);
+ asprintf(&args[3], "%d", howmany);
+ asprintf(&args[4], "%d", debug);
+
+ execve(args[0], args, envp);
+
+ _exit(PAM_SYSTEM_ERR);
+ }
+ else if (child > 0)
+ {
+ /* wait for child */
+ int rc = 0;
+ rc = waitpid(child, &retval, 0); /* wait for helper to complete */
+ if (rc < 0)
+ {
+ pam_syslog(pamh, LOG_ERR, "pwhistory_helper save waitpid returned %d: %m", rc);
+ retval = PAM_SYSTEM_ERR;
+ }
+ else if (!WIFEXITED(retval))
+ {
+ pam_syslog(pamh, LOG_ERR, "pwhistory_helper save abnormal exit: %d", retval);
+ retval = PAM_SYSTEM_ERR;
+ }
+ else
+ {
+ retval = WEXITSTATUS(retval);
+ }
+ }
+ else
+ {
+ retval = PAM_SYSTEM_ERR;
+ }
+
+ sigaction(SIGCHLD, &oldsa, NULL); /* restore old signal handler */
+
+ return retval;
+}
+
+static int
+run_check_helper(pam_handle_t *pamh, const char *user,
+ const char *newpass, int debug)
+{
+ int retval, child, fds[2];
+ struct sigaction newsa, oldsa;
+
+ /* create a pipe for the password */
+ if (pipe(fds) != 0)
+ return PAM_SYSTEM_ERR;
+
+ memset(&newsa, '\0', sizeof(newsa));
+ newsa.sa_handler = SIG_DFL;
+ sigaction(SIGCHLD, &newsa, &oldsa);
+
+ child = fork();
+ if (child == 0)
+ {
+ int i = 0;
+ struct rlimit rlim;
+ int dummyfds[2];
+ static char *envp[] = { NULL };
+ char *args[] = { NULL, NULL, NULL, NULL, NULL };
+
+ /* reopen stdin as pipe */
+ dup2(fds[0], STDIN_FILENO);
+
+ /* replace std file descriptors with a dummy pipe */
+ if (pipe2(dummyfds, O_NONBLOCK) == 0)
+ {
+ dup2(dummyfds[1], STDOUT_FILENO);
+ dup2(dummyfds[1], STDERR_FILENO);
+ }
+
+ if (getrlimit(RLIMIT_NOFILE,&rlim) == 0)
+ {
+ if (rlim.rlim_max >= MAX_FD_NO)
+ rlim.rlim_max = MAX_FD_NO;
+ for (i = STDERR_FILENO + 1; i < (int)rlim.rlim_max; i++)
+ {
+ if (i != dummyfds[0])
+ close(i);
+ }
+ }
+
+ /* exec binary helper */
+ args[0] = strdup(PWHISTORY_HELPER);
+ args[1] = strdup("check");
+ args[2] = x_strdup(user);
+ asprintf(&args[3], "%d", debug);
+
+ execve(args[0], args, envp);
+
+ _exit(PAM_SYSTEM_ERR);
+ }
+ else if (child > 0)
+ {
+ /* wait for child */
+ int rc = 0;
+ if (newpass == NULL)
+ newpass = "";
+
+ /* send the password to the child */
+ if (write(fds[1], newpass, strlen(newpass)+1) == -1)
+ {
+ pam_syslog(pamh, LOG_ERR, "Cannot send password to helper: %m");
+ retval = PAM_SYSTEM_ERR;
+ }
+ newpass = NULL;
+ close(fds[0]); /* close here to avoid possible SIGPIPE above */
+ close(fds[1]);
+ rc = waitpid(child, &retval, 0); /* wait for helper to complete */
+ if (rc < 0)
+ {
+ pam_syslog(pamh, LOG_ERR, "pwhistory_helper check waitpid returned %d: %m", rc);
+ retval = PAM_SYSTEM_ERR;
+ }
+ else if (!WIFEXITED(retval))
+ {
+ pam_syslog(pamh, LOG_ERR, "pwhistory_helper check abnormal exit: %d", retval);
+ retval = PAM_SYSTEM_ERR;
+ }
+ else
+ {
+ retval = WEXITSTATUS(retval);
+ }
+ }
+ else
+ {
+ close(fds[0]);
+ close(fds[1]);
+ retval = PAM_SYSTEM_ERR;
+ }
+
+ sigaction(SIGCHLD, &oldsa, NULL); /* restore old signal handler */
+
+ return retval;
+}
/* This module saves the current crypted password in /etc/security/opasswd
and then compares the new password with all entries in this file. */
@@ -109,7 +293,6 @@ parse_option (pam_handle_t *pamh, const char *argv, options_t *options)
PAM_EXTERN int
pam_sm_chauthtok (pam_handle_t *pamh, int flags, int argc, const char **argv)
{
- struct passwd *pwd;
const char *newpass;
const char *user;
int retval, tries;
@@ -154,31 +337,13 @@ pam_sm_chauthtok (pam_handle_t *pamh, int flags, int argc, const char **argv)
return PAM_SUCCESS;
}
- pwd = pam_modutil_getpwnam (pamh, user);
- if (pwd == NULL)
- return PAM_USER_UNKNOWN;
+ retval = save_old_pass (pamh, user, options.remember, options.debug);
- if ((strcmp(pwd->pw_passwd, "x") == 0) ||
- ((pwd->pw_passwd[0] == '#') &&
- (pwd->pw_passwd[1] == '#') &&
- (strcmp(pwd->pw_name, pwd->pw_passwd + 2) == 0)))
- {
- struct spwd *spw = pam_modutil_getspnam (pamh, user);
- if (spw == NULL)
- return PAM_USER_UNKNOWN;
+ if (retval == PAM_PWHISTORY_RUN_HELPER)
+ retval = run_save_helper(pamh, user, options.remember, options.debug);
- retval = save_old_pass (pamh, user, pwd->pw_uid, spw->sp_pwdp,
- options.remember, options.debug);
- if (retval != PAM_SUCCESS)
- return retval;
- }
- else
- {
- retval = save_old_pass (pamh, user, pwd->pw_uid, pwd->pw_passwd,
- options.remember, options.debug);
- if (retval != PAM_SUCCESS)
- return retval;
- }
+ if (retval != PAM_SUCCESS)
+ return retval;
newpass = NULL;
tries = 0;
@@ -207,8 +372,11 @@ pam_sm_chauthtok (pam_handle_t *pamh, int flags, int argc, const char **argv)
if (options.debug)
pam_syslog (pamh, LOG_DEBUG, "check against old password file");
- if (check_old_pass (pamh, user, newpass,
- options.debug) != PAM_SUCCESS)
+ retval = check_old_pass (pamh, user, newpass, options.debug);
+ if (retval == PAM_PWHISTORY_RUN_HELPER)
+ retval = run_check_helper(pamh, user, newpass, options.debug);
+
+ if (retval != PAM_SUCCESS)
{
if (getuid() || options.enforce_for_root ||
(flags & PAM_CHANGE_EXPIRED_AUTHTOK))
diff --git a/modules/pam_pwhistory/pwhistory_helper.8.xml b/modules/pam_pwhistory/pwhistory_helper.8.xml
new file mode 100644
index 0000000..a030176
--- /dev/null
+++ b/modules/pam_pwhistory/pwhistory_helper.8.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding='UTF-8'?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
+
+<refentry id="pwhistory_helper">
+
+ <refmeta>
+ <refentrytitle>pwhistory_helper</refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo class="sectdesc">Linux-PAM Manual</refmiscinfo>
+ </refmeta>
+
+ <refnamediv id="pwhistory_helper-name">
+ <refname>pwhistory_helper</refname>
+ <refpurpose>Helper binary that transfers password hashes from passwd or shadow to opasswd</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis id="pwhistory_helper-cmdsynopsis">
+ <command>pwhistory_helper</command>
+ <arg choice="opt">
+ ...
+ </arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1 id="pwhistory_helper-description">
+
+ <title>DESCRIPTION</title>
+
+ <para>
+ <emphasis>pwhistory_helper</emphasis> is a helper program for the
+ <emphasis>pam_pwhistory</emphasis> module that transfers password hashes
+ from passwd or shadow file to the opasswd file and checks a password
+ supplied by user against the existing hashes in the opasswd file.
+ </para>
+
+ <para>
+ The purpose of the helper is to enable tighter confinement of
+ login and password changing services. The helper is thus called only
+ when SELinux is enabled on the system.
+ </para>
+
+ <para>
+ The interface of the helper - command line options, and input/output
+ data format are internal to the <emphasis>pam_pwhistory</emphasis>
+ module and it should not be called directly from applications.
+ </para>
+ </refsect1>
+
+ <refsect1 id='pwhistory_helper-see_also'>
+ <title>SEE ALSO</title>
+ <para>
+ <citerefentry>
+ <refentrytitle>pam_pwhistory</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>
+ </para>
+ </refsect1>
+
+ <refsect1 id='pwhistory_helper-author'>
+ <title>AUTHOR</title>
+ <para>
+ Written by Tomas Mraz based on the code originally in
+ <emphasis>pam_pwhistory and pam_unix</emphasis> modules.
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/modules/pam_pwhistory/pwhistory_helper.c b/modules/pam_pwhistory/pwhistory_helper.c
new file mode 100644
index 0000000..b07ab81
--- /dev/null
+++ b/modules/pam_pwhistory/pwhistory_helper.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2013 Red Hat, Inc.
+ * Author: Tomas Mraz <tmraz@redhat.com>
+ *
+ * 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.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include <security/_pam_types.h>
+#include <security/_pam_macros.h>
+#include "opasswd.h"
+
+#define MAXPASS 200
+
+static void
+su_sighandler(int sig)
+{
+#ifndef SA_RESETHAND
+ /* emulate the behaviour of the SA_RESETHAND flag */
+ if ( sig == SIGILL || sig == SIGTRAP || sig == SIGBUS || sig = SIGSERV ) {
+ struct sigaction sa;
+ memset(&sa, '\0', sizeof(sa));
+ sa.sa_handler = SIG_DFL;
+ sigaction(sig, &sa, NULL);
+ }
+#endif
+ if (sig > 0) {
+ _exit(sig);
+ }
+}
+
+static void
+setup_signals(void)
+{
+ struct sigaction action; /* posix signal structure */
+
+ /*
+ * Setup signal handlers
+ */
+ (void) memset((void *) &action, 0, sizeof(action));
+ action.sa_handler = su_sighandler;
+#ifdef SA_RESETHAND
+ action.sa_flags = SA_RESETHAND;
+#endif
+ (void) sigaction(SIGILL, &action, NULL);
+ (void) sigaction(SIGTRAP, &action, NULL);
+ (void) sigaction(SIGBUS, &action, NULL);
+ (void) sigaction(SIGSEGV, &action, NULL);
+ action.sa_handler = SIG_IGN;
+ action.sa_flags = 0;
+ (void) sigaction(SIGTERM, &action, NULL);
+ (void) sigaction(SIGHUP, &action, NULL);
+ (void) sigaction(SIGINT, &action, NULL);
+ (void) sigaction(SIGQUIT, &action, NULL);
+}
+
+static int
+read_passwords(int fd, int npass, char **passwords)
+{
+ int rbytes = 0;
+ int offset = 0;
+ int i = 0;
+ char *pptr;
+ while (npass > 0)
+ {
+ rbytes = read(fd, passwords[i]+offset, MAXPASS-offset);
+
+ if (rbytes < 0)
+ {
+ if (errno == EINTR) continue;
+ break;
+ }
+ if (rbytes == 0)
+ break;
+
+ while (npass > 0 && (pptr=memchr(passwords[i]+offset, '\0', rbytes))
+ != NULL)
+ {
+ rbytes -= pptr - (passwords[i]+offset) + 1;
+ i++;
+ offset = 0;
+ npass--;
+ if (rbytes > 0)
+ {
+ if (npass > 0)
+ memcpy(passwords[i], pptr+1, rbytes);
+ memset(pptr+1, '\0', rbytes);
+ }
+ }
+ offset += rbytes;
+ }
+
+ /* clear up */
+ if (offset > 0 && npass > 0)
+ memset(passwords[i], '\0', offset);
+
+ return i;
+}
+
+
+static int
+check_history(const char *user, const char *debug)
+{
+ char pass[MAXPASS + 1];
+ char *passwords[] = { pass };
+ int npass;
+ int dbg = atoi(debug); /* no need to be too fancy here */
+ int retval;
+
+ /* read the password from stdin (a pipe from the pam_pwhistory module) */
+ npass = read_passwords(STDIN_FILENO, 1, passwords);
+
+ if (npass != 1)
+ { /* is it a valid password? */
+ helper_log_err(LOG_DEBUG, "no password supplied");
+ return PAM_AUTHTOK_ERR;
+ }
+
+ retval = check_old_pass(user, pass, dbg);
+
+ memset(pass, '\0', MAXPASS); /* clear memory of the password */
+
+ return retval;
+}
+
+static int
+save_history(const char *user, const char *howmany, const char *debug)
+{
+ int num = atoi(howmany);
+ int dbg = atoi(debug); /* no need to be too fancy here */
+ int retval;
+
+ retval = save_old_pass(user, num, dbg);
+
+ return retval;
+}
+
+int
+main(int argc, char *argv[])
+{
+ const char *option;
+ const char *user;
+
+ /*
+ * Catch or ignore as many signal as possible.
+ */
+ setup_signals();
+
+ /*
+ * we establish that this program is running with non-tty stdin.
+ * this is to discourage casual use.
+ */
+
+ if (isatty(STDIN_FILENO) || argc < 4)
+ {
+ fprintf(stderr,
+ "This binary is not designed for running in this way.\n");
+ sleep(10); /* this should discourage/annoy the user */
+ return PAM_SYSTEM_ERR;
+ }
+
+ option = argv[1];
+ user = argv[2];
+
+ if (strcmp(option, "check") == 0 && argc == 4)
+ return check_history(user, argv[3]);
+ else if (strcmp(option, "save") == 0 && argc == 5)
+ return save_history(user, argv[3], argv[4]);
+
+ return PAM_SYSTEM_ERR;
+}
+

View file

@ -1,24 +1,37 @@
diff -pruN a/modules/pam_userdb/pam_userdb.c b/modules/pam_userdb/pam_userdb.c From 57a1e2b274d0a6376d92ada9926e5c5741e7da20 Mon Sep 17 00:00:00 2001
--- a/modules/pam_userdb/pam_userdb.c 2011-06-21 16:04:56.000000000 +0700 From: "Dmitry V. Levin" <ldv@altlinux.org>
+++ b/modules/pam_userdb/pam_userdb.c 2014-08-28 17:41:35.243954732 +0700 Date: Fri, 24 Jan 2014 22:18:32 +0000
@@ -214,24 +214,23 @@ user_lookup (pam_handle_t *pamh, const c Subject: [PATCH] pam_userdb: fix password hash comparison
/* crypt(3) password storage */
char *cryptpw; Starting with commit Linux-PAM-0-77-28-g0b3e583 that introduced hashed
- char salt[2]; passwords support in pam_userdb, hashes are compared case-insensitively.
This bug leads to accepting hashes for completely different passwords in
addition to those that should be accepted.
- if (data.dsize != 13) { Additionally, commit Linux-PAM-1_1_6-13-ge2a8187 that added support for
+ if (data.dsize < 13) { modern password hashes with different lengths and settings, did not
compare = -2; update the hash comparison accordingly, which leads to accepting
} else if (ctrl & PAM_ICASE_ARG) { computed hashes longer than stored hashes when the latter is a prefix
compare = -2; of the former.
* modules/pam_userdb/pam_userdb.c (user_lookup): Reject the computed
hash whose length differs from the stored hash length.
Compare computed and stored hashes case-sensitively.
Fixes CVE-2013-7041.
Bug-Debian: http://bugs.debian.org/731368
---
modules/pam_userdb/pam_userdb.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/modules/pam_userdb/pam_userdb.c b/modules/pam_userdb/pam_userdb.c
index de8b5b1..ff040e6 100644
--- a/modules/pam_userdb/pam_userdb.c
+++ b/modules/pam_userdb/pam_userdb.c
@@ -222,12 +222,15 @@ user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode,
} else { } else {
- salt[0] = *data.dptr; cryptpw = crypt (pass, data.dptr);
- salt[1] = *(data.dptr + 1);
+ cryptpw = crypt (pass, data.dptr);
- cryptpw = crypt (pass, salt);
-
- if (cryptpw) { - if (cryptpw) {
- compare = strncasecmp (data.dptr, cryptpw, data.dsize); - compare = strncasecmp (data.dptr, cryptpw, data.dsize);
+ if (cryptpw && strlen(cryptpw) == (size_t)data.dsize) { + if (cryptpw && strlen(cryptpw) == (size_t)data.dsize) {
@ -34,3 +47,6 @@ diff -pruN a/modules/pam_userdb/pam_userdb.c b/modules/pam_userdb/pam_userdb.c
} }
}; };
--
1.8.3.1

View file

@ -1,3 +1,24 @@
From 9dcead87e6d7f66d34e7a56d11a30daca367dffb Mon Sep 17 00:00:00 2001
From: "Dmitry V. Levin" <ldv@altlinux.org>
Date: Wed, 26 Mar 2014 22:17:23 +0000
Subject: [PATCH] pam_timestamp: fix potential directory traversal issue
(ticket #27)
pam_timestamp uses values of PAM_RUSER and PAM_TTY as components of
the timestamp pathname it creates, so extra care should be taken to
avoid potential directory traversal issues.
* modules/pam_timestamp/pam_timestamp.c (check_tty): Treat
"." and ".." tty values as invalid.
(get_ruser): Treat "." and ".." ruser values, as well as any ruser
value containing '/', as invalid.
Fixes CVE-2014-2583.
Reported-by: Sebastian Krahmer <krahmer@suse.de>
---
modules/pam_timestamp/pam_timestamp.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/modules/pam_timestamp/pam_timestamp.c b/modules/pam_timestamp/pam_timestamp.c diff --git a/modules/pam_timestamp/pam_timestamp.c b/modules/pam_timestamp/pam_timestamp.c
index 5193733..b3f08b1 100644 index 5193733..b3f08b1 100644
@ -30,4 +51,6 @@ index 5193733..b3f08b1 100644
} }
if (ruser == NULL || strlen(ruser) >= ruserbuflen) { if (ruser == NULL || strlen(ruser) >= ruserbuflen) {
*ruserbuf = '\0'; *ruserbuf = '\0';
--
1.8.3.1

View file

@ -19,7 +19,7 @@ Epoch: 1
Summary: A security tool which provides authentication for applications Summary: A security tool which provides authentication for applications
Name: pam Name: pam
Version: 1.1.8 Version: 1.1.8
Release: 3 Release: 22
# The library is BSD licensed with option to relicense as GPLv2+ - this option is redundant # 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+, # as the BSD license allows that anyway. pam_timestamp and pam_console modules are GPLv2+,
License: BSD and GPLv2+ License: BSD and GPLv2+
@ -51,8 +51,20 @@ Patch9: pam-1.1.6-noflex.patch
Patch10: pam-1.1.3-nouserenv.patch Patch10: pam-1.1.3-nouserenv.patch
Patch11: pam-1.1.3-console-abstract.patch Patch11: pam-1.1.3-console-abstract.patch
Patch13: pam-1.1.5-limits-user.patch Patch13: pam-1.1.5-limits-user.patch
Patch14: pam-1.1.1-faillock.patch
Patch22: pam-1.1.7-unix-build.patch Patch22: pam-1.1.7-unix-build.patch
Patch32: pam-1.1.7-tty-audit-init.patch Patch32: pam-1.1.7-tty-audit-init.patch
Patch33: pam-1.1.8-audit-grantor.patch
Patch34: pam-1.1.8-audit-user-mgmt.patch
Patch35: pam-1.1.8-canonicalize-username.patch
Patch36: pam-1.1.8-full-relro.patch
Patch37: pam-1.1.8-lastlog-uninitialized.patch
Patch38: pam-1.1.8-limits-check-process.patch
Patch39: pam-1.1.8-limits-docfix.patch
Patch40: pam-1.1.8-loginuid-container.patch
Patch41: pam-1.1.8-man-dbsuffix.patch
Patch42: pam-1.1.8-opasswd-tolerant.patch
Patch43: pam-1.1.8-pwhistory-helper.patch
# ROSA specific sources/patches # ROSA specific sources/patches
# (fl) fix infinite loop # (fl) fix infinite loop
@ -64,8 +76,6 @@ Patch508: Linux-PAM-0.99.3.0-pamtimestampadm.patch
##Patch512: Linux-PAM-1.1.1-xauth-groups.patch ##Patch512: Linux-PAM-1.1.1-xauth-groups.patch
# (tv/blino) add defaults for nice/rtprio in /etc/security/limits.conf # (tv/blino) add defaults for nice/rtprio in /etc/security/limits.conf
Patch517: Linux-PAM-0.99.3.0-enable_rt.patch Patch517: Linux-PAM-0.99.3.0-enable_rt.patch
# (blino) fix parallel build (pam_console)
Patch521: Linux-PAM-0.99.3.0-pbuild-rh.patch
Patch700: pam_fix_static_pam_console.patch Patch700: pam_fix_static_pam_console.patch
# (fc) do not output error when no file is in /etc/security/console.perms.d/ # (fc) do not output error when no file is in /etc/security/console.perms.d/
@ -75,8 +85,10 @@ Patch702: Linux-PAM-1.1.4-add-now-missing-nis-constant.patch
# (akdengi> add user to default group users which need for Samba # (akdengi> add user to default group users which need for Samba
Patch801: Linux-PAM-1.1.4-group_add_users.patch Patch801: Linux-PAM-1.1.4-group_add_users.patch
#Patch802: pam-CVE-2014-2583.patch Patch802: pam-CVE-2014-2583.patch
#Patch803: pam-CVE-2013-7041.patch Patch803: pam-CVE-2013-7041.patch
Patch804: pam-1.1.8-pbuild.patch
BuildRequires: selinux-devel >= 2.1.6-7 BuildRequires: selinux-devel >= 2.1.6-7
BuildRequires: bison BuildRequires: bison
@ -169,23 +181,23 @@ mv pam-redhat-%{pam_redhat_version}/* modules
install -m644 %{SOURCE501} %{SOURCE502} modules/pam_tty_audit/ install -m644 %{SOURCE501} %{SOURCE502} modules/pam_tty_audit/
mkdir -p doc/txts #mkdir -p doc/txts
for readme in modules/pam_*/README ; do #for readme in modules/pam_*/README ; do
cp -f ${readme} doc/txts/README.`dirname ${readme} | sed -e 's|^modules/||'` # cp -f ${readme} doc/txts/README.`dirname ${readme} | sed -e 's|^modules/||'`
done #done
#libtoolize -cf #libtoolize -cf
autoreconf -ifs -I m4 autoreconf -i
%build %build
export BROWSER=""
CFLAGS="$RPM_OPT_FLAGS -fPIC -I%{_includedir}/db_nss -D_GNU_SOURCE" \
%configure2_5x \ %configure2_5x \
--sbindir=/sbin \ --sbindir=/sbin \
--libdir=/%{_lib} \ --libdir=/%{_lib} \
--includedir=%{_includedir}/security \ --includedir=%{_includedir}/security \
--with-db-uniquename=_nss \ --with-db-uniquename=_nss \
--docdir=%{_docdir}/%{name} \ --docdir=%{_docdir}/%{name} \
--disable-static \
--disable-prelude \
--enable-selinux \ --enable-selinux \
--enable-audit --enable-audit
%make %make
@ -229,16 +241,11 @@ cp -f %{buildroot}/etc/pam.d/system-auth %{buildroot}/etc/pam.d/system-auth-defa
%find_lang Linux-PAM %find_lang Linux-PAM
%check %check
# (blino) we don't want to test if SE Linux is built, it's disabled
# Make sure every module subdirectory gave us a module. Yes, this is hackish.
for dir in modules/pam_* ; do for dir in modules/pam_* ; do
#if [ -d ${dir} ] && [[ "${dir}" != "modules/pam_selinux" ]] && [[ "${dir}" != "modules/pam_sepermit" ]]; then
# [[ "${dir}" = "modules/pam_tally" ]] && continue
if ! ls -1 %{buildroot}/%{_lib}/security/`basename ${dir}`*.so ; then if ! ls -1 %{buildroot}/%{_lib}/security/`basename ${dir}`*.so ; then
echo ERROR `basename ${dir}` did not build a module. echo ERROR `basename ${dir}` did not build a module.
exit 1 exit 1
fi fi
#fi
done done
# Check for module problems. Specifically, check that every module we just # Check for module problems. Specifically, check that every module we just
@ -262,9 +269,6 @@ fi
if [ ! -a /var/log/tallylog ] ; then if [ ! -a /var/log/tallylog ] ; then
install -m 600 /dev/null /var/log/tallylog install -m 600 /dev/null /var/log/tallylog
fi fi
#if [ -f /etc/login.defs ] && ! grep -q USE_TCB /etc/login.defs; then
# /usr/sbin/set_tcb --auto --migrate
#fi
%files -f Linux-PAM.lang %files -f Linux-PAM.lang
%doc NEWS %doc NEWS