summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomas Mraz <tm@t8m.info>2009-02-27 14:29:39 +0000
committerTomas Mraz <tm@t8m.info>2009-02-27 14:29:39 +0000
commit42f4743cc3ca046833afcaeec01f9793d74bbfb4 (patch)
treeb969c921b0a5a924b09cf4d34ac74b01b309425c
parent5891c5508e3b9ba699a6a6ba3dae9221a45528e5 (diff)
Relevant BUGIDs:
Purpose of commit: new feature Commit summary: --------------- 2009-02-27 Tomas Mraz <t8m@centrum.cz> * modules/pam_mkhomedir/pam_mkhomedir.c(create_homedir): Replace signal() with sigaction(). * modules/pam_namespace/pam_namespace.c(inst_init, cleanup_tmpdirs): Likewise. * modules/pam_unix/pam_unix_acct.c(_unix_run_verify_binary): Likewise. * modules/pam_unix/pam_unix_passwd.c(_unix_run_update_binary): Likewise. * modules/pam_unix/passverify.c(su_sighandler): Likewise. * modules/pam_unix/support.c(_unix_run_helper_binary): Likewise. * modules/pam_tally2/Makefile.am: Link the pam_tally2 app to libpam for auxiliary functions. * modules/pam_tally2/pam_tally2.8.xml: Drop non-existing no_reset option. Document new serialize option. * modules/pam_tally2/pam_tally2.c: Add support for the new serialize option. (_cleanup, tally_set_data, tally_get_data): Add tally file handle to tally PAM data. Needed for fcntl() locking. (get_tally): Use low level file access instead of stdio buffered FILE. If serialize option is used lock the tally file access. (set_tally, tally_bump, tally_reset): Use low level file access instead of stdio buffered FILE. Close the file handle only when it is not owned by PAM data. (pam_sm_authenticate, pam_sm_setcred, pam_sm_acct_mgmt): Pass the tally file handle to tally_set_data(). Get it from tally_get_data(). (main): Use low level file access instead of stdio buffered FILE.
-rw-r--r--ChangeLog29
-rw-r--r--modules/pam_mkhomedir/pam_mkhomedir.c12
-rw-r--r--modules/pam_namespace/pam_namespace.c24
-rw-r--r--modules/pam_tally2/Makefile.am2
-rw-r--r--modules/pam_tally2/pam_tally2.8.xml32
-rw-r--r--modules/pam_tally2/pam_tally2.c216
-rw-r--r--modules/pam_unix/pam_unix_acct.c12
-rw-r--r--modules/pam_unix/pam_unix_passwd.c10
-rw-r--r--modules/pam_unix/passverify.c8
-rw-r--r--modules/pam_unix/support.c10
10 files changed, 239 insertions, 116 deletions
diff --git a/ChangeLog b/ChangeLog
index 513a0d45..5abf28e3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2009-02-27 Tomas Mraz <t8m@centrum.cz>
+
+ * modules/pam_mkhomedir/pam_mkhomedir.c(create_homedir): Replace
+ signal() with sigaction().
+ * modules/pam_namespace/pam_namespace.c(inst_init, cleanup_tmpdirs):
+ Likewise.
+ * modules/pam_unix/pam_unix_acct.c(_unix_run_verify_binary): Likewise.
+ * modules/pam_unix/pam_unix_passwd.c(_unix_run_update_binary):
+ Likewise.
+ * modules/pam_unix/passverify.c(su_sighandler): Likewise.
+ * modules/pam_unix/support.c(_unix_run_helper_binary): Likewise.
+
+ * modules/pam_tally2/Makefile.am: Link the pam_tally2 app to libpam
+ for auxiliary functions.
+ * modules/pam_tally2/pam_tally2.8.xml: Drop non-existing no_reset
+ option. Document new serialize option.
+ * modules/pam_tally2/pam_tally2.c: Add support for the new serialize
+ option.
+ (_cleanup, tally_set_data, tally_get_data): Add tally file handle to
+ tally PAM data. Needed for fcntl() locking.
+ (get_tally): Use low level file access instead of stdio buffered FILE.
+ If serialize option is used lock the tally file access.
+ (set_tally, tally_bump, tally_reset): Use low level file access instead
+ of stdio buffered FILE. Close the file handle only when it is not owned
+ by PAM data.
+ (pam_sm_authenticate, pam_sm_setcred, pam_sm_acct_mgmt): Pass the tally
+ file handle to tally_set_data(). Get it from tally_get_data().
+ (main): Use low level file access instead of stdio buffered FILE.
+
2009-02-26 Tomas Mraz <t8m@centrum.cz>
* xtests/Makefile.am: Add tst-pam_unix4.
diff --git a/modules/pam_mkhomedir/pam_mkhomedir.c b/modules/pam_mkhomedir/pam_mkhomedir.c
index a0c389c5..1beb2d9f 100644
--- a/modules/pam_mkhomedir/pam_mkhomedir.c
+++ b/modules/pam_mkhomedir/pam_mkhomedir.c
@@ -104,7 +104,7 @@ create_homedir (pam_handle_t *pamh, int ctrl,
const struct passwd *pwd)
{
int retval, child;
- void (*sighandler)(int) = NULL;
+ struct sigaction newsa, oldsa;
/* Mention what is happening, if the notification fails that is OK */
if (!(ctrl & MKHOMEDIR_QUIET))
@@ -118,8 +118,10 @@ create_homedir (pam_handle_t *pamh, int ctrl,
* the application to receive a signal it is not expecting - which
* may kill the application or worse.
*/
- sighandler = signal(SIGCHLD, SIG_DFL);
-
+ memset(&newsa, '\0', sizeof(newsa));
+ newsa.sa_handler = SIG_DFL;
+ sigaction(SIGCHLD, &newsa, &oldsa);
+
if (ctrl & MKHOMEDIR_DEBUG) {
pam_syslog(pamh, LOG_DEBUG, "Executing mkhomedir_helper.");
}
@@ -166,9 +168,7 @@ create_homedir (pam_handle_t *pamh, int ctrl,
retval = PAM_SYSTEM_ERR;
}
- if (sighandler != SIG_ERR) {
- (void) signal(SIGCHLD, sighandler); /* restore old signal handler */
- }
+ sigaction(SIGCHLD, &oldsa, NULL); /* restore old signal handler */
if (ctrl & MKHOMEDIR_DEBUG) {
pam_syslog(pamh, LOG_DEBUG, "mkhomedir_helper returned %d", retval);
diff --git a/modules/pam_namespace/pam_namespace.c b/modules/pam_namespace/pam_namespace.c
index 89bc3686..7d668d9e 100644
--- a/modules/pam_namespace/pam_namespace.c
+++ b/modules/pam_namespace/pam_namespace.c
@@ -1157,15 +1157,15 @@ static int inst_init(const struct polydir_s *polyptr, const char *ipath,
struct instance_data *idata, int newdir)
{
pid_t rc, pid;
- sighandler_t osighand = NULL;
+ struct sigaction newsa, oldsa;
int status;
const char *init_script = NAMESPACE_INIT_SCRIPT;
- osighand = signal(SIGCHLD, SIG_DFL);
- if (osighand == SIG_ERR) {
+ memset(&newsa, '\0', sizeof(newsa));
+ newsa.sa_handler = SIG_DFL;
+ if (sigaction(SIGCHLD, &newsa, &oldsa) == -1) {
pam_syslog(idata->pamh, LOG_ERR, "Cannot set signal value");
- rc = PAM_SESSION_ERR;
- goto out;
+ return PAM_SESSION_ERR;
}
if ((polyptr->flags & POLYDIR_ISCRIPT) && polyptr->init_script)
@@ -1214,7 +1214,7 @@ static int inst_init(const struct polydir_s *polyptr, const char *ipath,
}
rc = PAM_SUCCESS;
out:
- (void) signal(SIGCHLD, osighand);
+ (void) sigaction(SIGCHLD, &oldsa, NULL);
return rc;
}
@@ -1594,14 +1594,14 @@ static int cleanup_tmpdirs(struct instance_data *idata)
{
struct polydir_s *pptr;
pid_t rc, pid;
- sighandler_t osighand = NULL;
+ struct sigaction newsa, oldsa;
int status;
- osighand = signal(SIGCHLD, SIG_DFL);
- if (osighand == SIG_ERR) {
+ memset(&newsa, '\0', sizeof(newsa));
+ newsa.sa_handler = SIG_DFL;
+ if (sigaction(SIGCHLD, &newsa, &oldsa) == -1) {
pam_syslog(idata->pamh, LOG_ERR, "Cannot set signal value");
- rc = PAM_SESSION_ERR;
- goto out;
+ return PAM_SESSION_ERR;
}
for (pptr = idata->polydirs_ptr; pptr; pptr = pptr->next) {
@@ -1639,7 +1639,7 @@ static int cleanup_tmpdirs(struct instance_data *idata)
rc = PAM_SUCCESS;
out:
- signal(SIGCHLD, osighand);
+ sigaction(SIGCHLD, &oldsa, NULL);
return rc;
}
diff --git a/modules/pam_tally2/Makefile.am b/modules/pam_tally2/Makefile.am
index 6f843e1f..06cdf554 100644
--- a/modules/pam_tally2/Makefile.am
+++ b/modules/pam_tally2/Makefile.am
@@ -25,7 +25,7 @@ if HAVE_VERSIONING
pam_tally2_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
endif
-pam_tally2_LDADD = $(LIBAUDIT)
+pam_tally2_LDADD = -L$(top_builddir)/libpam -lpam $(LIBAUDIT)
securelib_LTLIBRARIES = pam_tally2.la
sbin_PROGRAMS = pam_tally2
diff --git a/modules/pam_tally2/pam_tally2.8.xml b/modules/pam_tally2/pam_tally2.8.xml
index a7a3fc47..255fcea4 100644
--- a/modules/pam_tally2/pam_tally2.8.xml
+++ b/modules/pam_tally2/pam_tally2.8.xml
@@ -43,6 +43,9 @@
root_unlock_time=<replaceable>n</replaceable>
</arg>
<arg choice="opt">
+ serialize
+ </arg>
+ <arg choice="opt">
audit
</arg>
<arg choice="opt">
@@ -246,16 +249,6 @@
</varlistentry>
<varlistentry>
<term>
- <option>no_reset</option>
- </term>
- <listitem>
- <para>
- Don't reset count on successful entry, only decrement.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>
<option>even_deny_root</option>
</term>
<listitem>
@@ -278,6 +271,23 @@
</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>
+ <option>serialize</option>
+ </term>
+ <listitem>
+ <para>
+ Serialize access to the tally file using locks. This option might
+ be used only for non-multithreaded services because it depends on
+ the fcntl locking of the tally file. Also it is a good idea to use
+ this option only in such configurations where the time between auth
+ phase and account or setcred phase is not dependent on the
+ authenticating client. Otherwise the authenticating client will be
+ able to prevent simultaneous authentications by the same user by
+ simply artificially prolonging the time the file record lock is held.
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
</listitem>
</varlistentry>
@@ -431,7 +441,7 @@ session optional pam_mail.so standard
<refsect1 id='pam_tally2-author'>
<title>AUTHOR</title>
<para>
- pam_tally was written by Tim Baverstock and Tomas Mraz.
+ pam_tally2 was written by Tim Baverstock and Tomas Mraz.
</para>
</refsect1>
diff --git a/modules/pam_tally2/pam_tally2.c b/modules/pam_tally2/pam_tally2.c
index faa6942e..3490aa15 100644
--- a/modules/pam_tally2/pam_tally2.c
+++ b/modules/pam_tally2/pam_tally2.c
@@ -63,6 +63,9 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <signal.h>
#include "tallylog.h"
#ifndef TRUE
@@ -87,9 +90,9 @@
/* #define PAM_SM_SESSION */
/* #define PAM_SM_PASSWORD */
-#include <security/pam_modutil.h>
#include <security/pam_ext.h>
#endif
+#include <security/pam_modutil.h>
#include <security/pam_modules.h>
/*---------------------------------------------------------------------*/
@@ -120,7 +123,9 @@ struct tally_options {
#define OPT_QUIET 040
#define OPT_AUDIT 0100
#define OPT_NOLOGNOTICE 0400
+#define OPT_SERIALIZE 01000
+#define MAX_LOCK_WAITING_TIME 10
/*---------------------------------------------------------------------*/
@@ -188,6 +193,9 @@ tally_parse_args(pam_handle_t *pamh, struct tally_options *opts,
else if ( ! strcmp( *argv, "magic_root" ) ) {
opts->ctrl |= OPT_MAGIC_ROOT;
}
+ else if ( ! strcmp( *argv, "serialize" ) ) {
+ opts->ctrl |= OPT_SERIALIZE;
+ }
else if ( ! strcmp( *argv, "even_deny_root_account" ) ||
! strcmp( *argv, "even_deny_root" ) ) {
log_phase_no_auth(pamh, phase, *argv);
@@ -291,34 +299,44 @@ pam_get_uid(pam_handle_t *pamh, uid_t *uid, const char **userp, struct tally_opt
#ifndef MAIN
+struct tally_data {
+ time_t time;
+ int tfile;
+};
+
static void
-_cleanup(pam_handle_t *pamh UNUSED, void *data, int error_status UNUSED)
+_cleanup(pam_handle_t *pamh UNUSED, void *void_data, int error_status UNUSED)
{
+ struct tally_data *data = void_data;
+ if (data->tfile != -1)
+ close(data->tfile);
free(data);
}
-
static void
-tally_set_data( pam_handle_t *pamh, time_t oldtime )
+tally_set_data( pam_handle_t *pamh, time_t oldtime, int tfile )
{
- time_t *data;
+ struct tally_data *data;
- if ( (data=malloc(sizeof(time_t))) != NULL ) {
- *data = oldtime;
+ if ( (data=malloc(sizeof(*data))) != NULL ) {
+ data->time = oldtime;
+ data->tfile = tfile;
pam_set_data(pamh, MODULE_NAME, (void *)data, _cleanup);
}
}
static int
-tally_get_data( pam_handle_t *pamh, time_t *oldtime )
+tally_get_data( pam_handle_t *pamh, time_t *oldtime, int *tfile )
{
int rv;
- const void *data;
-
- rv = pam_get_data(pamh, MODULE_NAME, &data);
- if ( rv == PAM_SUCCESS && data != NULL && oldtime != NULL ) {
- *oldtime = *(const time_t *)data;
- pam_set_data(pamh, MODULE_NAME, NULL, NULL);
+ const void *void_data;
+ const struct tally_data *data;
+
+ rv = pam_get_data(pamh, MODULE_NAME, &void_data);
+ if ( rv == PAM_SUCCESS && void_data != NULL && oldtime != NULL ) {
+ data = void_data;
+ *oldtime = data->time;
+ *tfile = data->tfile;
}
else {
rv = -1;
@@ -334,36 +352,44 @@ tally_get_data( pam_handle_t *pamh, time_t *oldtime )
/* If on entry tallyfile doesn't exist, creation is attempted. */
+static void
+alarm_handler(int sig UNUSED)
+{ /* we just need to ignore it */
+}
+
static int
get_tally(pam_handle_t *pamh, uid_t uid, const char *filename,
- FILE **tfile, struct tallylog *tally)
+ int *tfile, struct tallylog *tally, unsigned int ctrl)
{
struct stat fileinfo;
int lstat_ret;
+ void *void_tally = tally;
+ int preopened = 0;
+
+ if (*tfile != -1) {
+ preopened = 1;
+ goto skip_open;
+ }
lstat_ret = lstat(filename, &fileinfo);
if (lstat_ret) {
- int save_errno;
- int oldmask = umask(077);
- *tfile=fopen(filename, "a");
- save_errno = errno;
+ *tfile=open(filename, O_APPEND|O_CREAT, 0700);
/* Create file, or append-open in pathological case. */
- umask(oldmask);
- if ( !*tfile ) {
+ if (*tfile == -1) {
#ifndef MAIN
- if (save_errno == EACCES) {
+ if (errno == EACCES) {
return PAM_IGNORE; /* called with insufficient access rights */
}
#endif
- errno = save_errno;
pam_syslog(pamh, LOG_ALERT, "Couldn't create %s: %m", filename);
return PAM_AUTH_ERR;
}
- lstat_ret = fstat(fileno(*tfile),&fileinfo);
- fclose(*tfile);
- *tfile = NULL;
+ lstat_ret = fstat(*tfile, &fileinfo);
+ close(*tfile);
}
+ *tfile = -1;
+
if ( lstat_ret ) {
pam_syslog(pamh, LOG_ALERT, "Couldn't stat %s", filename);
return PAM_AUTH_ERR;
@@ -378,7 +404,7 @@ get_tally(pam_handle_t *pamh, uid_t uid, const char *filename,
return PAM_AUTH_ERR;
}
- if (!(*tfile = fopen(filename, "r+"))) {
+ if ((*tfile = open(filename, O_RDWR)) == -1) {
#ifndef MAIN
if (errno == EACCES) /* called with insufficient access rights */
return PAM_IGNORE;
@@ -388,16 +414,46 @@ get_tally(pam_handle_t *pamh, uid_t uid, const char *filename,
return PAM_AUTH_ERR;
}
- if (fseeko(*tfile, (off_t)uid*(off_t)sizeof(*tally), SEEK_SET)) {
- pam_syslog(pamh, LOG_ALERT, "fseek failed for %s: %m", filename);
- fclose(*tfile);
- *tfile = NULL;
+skip_open:
+ if (lseek(*tfile, (off_t)uid*(off_t)sizeof(*tally), SEEK_SET) == (off_t)-1) {
+ pam_syslog(pamh, LOG_ALERT, "lseek failed for %s: %m", filename);
+ if (!preopened) {
+ close(*tfile);
+ *tfile = -1;
+ }
return PAM_AUTH_ERR;
}
+ if (!preopened && (ctrl & OPT_SERIALIZE)) {
+ /* this code is not thread safe as it uses fcntl locks and alarm()
+ so never use serialize with multithreaded services */
+ struct sigaction newsa, oldsa;
+ unsigned int oldalarm;
+ int rv;
+
+ memset(&newsa, '\0', sizeof(newsa));
+ newsa.sa_handler = alarm_handler;
+ sigaction(SIGALRM, &newsa, &oldsa);
+ oldalarm = alarm(MAX_LOCK_WAITING_TIME);
+
+ rv = lockf(*tfile, F_LOCK, sizeof(*tally));
+ /* lock failure is not fatal, we attempt to read the tally anyway */
+
+ /* reinstate the eventual old alarm handler */
+ if (rv == -1 && errno == EINTR) {
+ if (oldalarm > MAX_LOCK_WAITING_TIME) {
+ oldalarm -= MAX_LOCK_WAITING_TIME;
+ } else if (oldalarm > 0) {
+ oldalarm = 1;
+ }
+ }
+ sigaction(SIGALRM, &oldsa, NULL);
+ alarm(oldalarm);
+ }
+
if (fileinfo.st_size < (off_t)(uid+1)*(off_t)sizeof(*tally)) {
memset(tally, 0, sizeof(*tally));
- } else if (fread(tally, sizeof(*tally), 1, *tfile) == 0) {
+ } else if (pam_modutil_read(*tfile, void_tally, sizeof(*tally)) != sizeof(*tally)) {
memset(tally, 0, sizeof(*tally));
/* Shouldn't happen */
}
@@ -409,29 +465,28 @@ get_tally(pam_handle_t *pamh, uid_t uid, const char *filename,
/*---------------------------------------------------------------------*/
-/* --- Support function: update and close tallyfile with tally!=TALLY_HI --- */
+/* --- Support function: update tallyfile with tally!=TALLY_HI --- */
static int
set_tally(pam_handle_t *pamh, uid_t uid,
- const char *filename, FILE **tfile, struct tallylog *tally)
+ const char *filename, int *tfile, struct tallylog *tally)
{
+ void *void_tally = tally;
if (tally->fail_cnt != TALLY_HI) {
- if (fseeko(*tfile, (off_t)uid * sizeof(*tally), SEEK_SET)) {
- pam_syslog(pamh, LOG_ALERT, "fseek failed for %s: %m", filename);
+ if (lseek(*tfile, (off_t)uid * sizeof(*tally), SEEK_SET) == (off_t)-1) {
+ pam_syslog(pamh, LOG_ALERT, "lseek failed for %s: %m", filename);
return PAM_AUTH_ERR;
}
- if (fwrite(tally, sizeof(*tally), 1, *tfile) == 0) {
- pam_syslog(pamh, LOG_ALERT, "update (fwrite) failed for %s: %m", filename);
+ if (pam_modutil_write(*tfile, void_tally, sizeof(*tally)) != sizeof(*tally)) {
+ pam_syslog(pamh, LOG_ALERT, "update (write) failed for %s: %m", filename);
return PAM_AUTH_ERR;
}
}
- if (fclose(*tfile)) {
- *tfile = NULL;
- pam_syslog(pamh, LOG_ALERT, "update (fclose) failed for %s: %m", filename);
+ if (fsync(*tfile)) {
+ pam_syslog(pamh, LOG_ALERT, "update (fsync) failed for %s: %m", filename);
return PAM_AUTH_ERR;
}
- *tfile=NULL;
return PAM_SUCCESS;
}
@@ -566,20 +621,21 @@ cleanup:
static int
tally_bump (int inc, time_t *oldtime, pam_handle_t *pamh,
- uid_t uid, const char *user, struct tally_options *opts)
+ uid_t uid, const char *user, struct tally_options *opts, int *tfile)
{
struct tallylog tally;
tally_t oldcnt;
- FILE *tfile = NULL;
const void *remote_host = NULL;
int i, rv;
tally.fail_cnt = 0; /* !TALLY_HI --> Log opened for update */
- i = get_tally(pamh, uid, opts->filename, &tfile, &tally);
+ i = get_tally(pamh, uid, opts->filename, tfile, &tally, opts->ctrl);
if (i != PAM_SUCCESS) {
- if (tfile)
- fclose(tfile);
+ if (*tfile != -1) {
+ close(*tfile);
+ *tfile = -1;
+ }
RETURN_ERROR(i);
}
@@ -617,23 +673,28 @@ tally_bump (int inc, time_t *oldtime, pam_handle_t *pamh,
rv = tally_check(oldcnt, *oldtime, pamh, uid, user, opts, &tally);
- i = set_tally(pamh, uid, opts->filename, &tfile, &tally);
+ i = set_tally(pamh, uid, opts->filename, tfile, &tally);
if (i != PAM_SUCCESS) {
- if (tfile)
- fclose(tfile);
+ if (*tfile != -1) {
+ close(*tfile);
+ *tfile = -1;
+ }
if (rv == PAM_SUCCESS)
RETURN_ERROR( i );
/* fallthrough */
+ } else if (!(opts->ctrl & OPT_SERIALIZE)) {
+ close(*tfile);
+ *tfile = -1;
}
return rv;
}
static int
-tally_reset (pam_handle_t *pamh, uid_t uid, struct tally_options *opts)
+tally_reset (pam_handle_t *pamh, uid_t uid, struct tally_options *opts, int old_tfile)
{
struct tallylog tally;
- FILE *tfile = NULL;
+ int tfile = old_tfile;
int i;
/* resets only if not magic root */
@@ -644,10 +705,10 @@ tally_reset (pam_handle_t *pamh, uid_t uid, struct tally_options *opts)
tally.fail_cnt = 0; /* !TALLY_HI --> Log opened for update */
- i=get_tally(pamh, uid, opts->filename, &tfile, &tally);
+ i=get_tally(pamh, uid, opts->filename, &tfile, &tally, opts->ctrl);
if (i != PAM_SUCCESS) {
- if (tfile)
- fclose(tfile);
+ if (tfile != old_tfile) /* the descriptor is not owned by pam data */
+ close(tfile);
RETURN_ERROR(i);
}
@@ -655,11 +716,14 @@ tally_reset (pam_handle_t *pamh, uid_t uid, struct tally_options *opts)
i=set_tally(pamh, uid, opts->filename, &tfile, &tally);
if (i != PAM_SUCCESS) {
- if (tfile)
- fclose(tfile);
+ if (tfile != old_tfile) /* the descriptor is not owned by pam data */
+ close(tfile);
RETURN_ERROR(i);
}
+ if (tfile != old_tfile)
+ close(tfile);
+
return PAM_SUCCESS;
}
@@ -672,7 +736,7 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags UNUSED,
int argc, const char **argv)
{
int
- rv;
+ rv, tfile = -1;
time_t
oldtime = 0;
struct tally_options
@@ -693,9 +757,9 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags UNUSED,
if (rv != PAM_SUCCESS)
RETURN_ERROR(rv);
- rv = tally_bump(1, &oldtime, pamh, uid, user, opts);
+ rv = tally_bump(1, &oldtime, pamh, uid, user, opts, &tfile);
- tally_set_data(pamh, oldtime);
+ tally_set_data(pamh, oldtime, tfile);
return rv;
}
@@ -705,7 +769,7 @@ pam_sm_setcred(pam_handle_t *pamh, int flags UNUSED,
int argc, const char **argv)
{
int
- rv;
+ rv, tfile = -1;
time_t
oldtime = 0;
struct tally_options
@@ -723,11 +787,15 @@ pam_sm_setcred(pam_handle_t *pamh, int flags UNUSED,
if ( rv != PAM_SUCCESS )
RETURN_ERROR( rv );
- if ( tally_get_data(pamh, &oldtime) != 0 )
+ if ( tally_get_data(pamh, &oldtime, &tfile) != 0 )
/* no data found */
return PAM_SUCCESS;
- return tally_reset(pamh, uid, opts);
+ rv = tally_reset(pamh, uid, opts, tfile);
+
+ pam_set_data(pamh, MODULE_NAME, NULL, NULL);
+
+ return rv;
}
/*---------------------------------------------------------------------*/
@@ -741,7 +809,7 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int flags UNUSED,
int argc, const char **argv)
{
int
- rv;
+ rv, tfile = -1;
time_t
oldtime = 0;
struct tally_options
@@ -759,11 +827,15 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int flags UNUSED,
if ( rv != PAM_SUCCESS )
RETURN_ERROR( rv );
- if ( tally_get_data(pamh, &oldtime) != 0 )
+ if ( tally_get_data(pamh, &oldtime, &tfile) != 0 )
/* no data found */
return PAM_SUCCESS;
- return tally_reset(pamh, uid, opts);
+ rv = tally_reset(pamh, uid, opts, tfile);
+
+ pam_set_data(pamh, MODULE_NAME, NULL, NULL);
+
+ return rv;
}
/*-----------------------------------------------------------------------*/
@@ -895,7 +967,7 @@ main( int argc UNUSED, char **argv )
if ( cline_user ) {
uid_t uid;
- FILE *tfile=0;
+ int tfile = -1;
struct tally_options opts;
int i;
@@ -907,10 +979,10 @@ main( int argc UNUSED, char **argv )
exit(1);
}
- i=get_tally(NULL, uid, cline_filename, &tfile, &tally);
+ i=get_tally(NULL, uid, cline_filename, &tfile, &tally, 0);
if ( i != PAM_SUCCESS ) {
- if (tfile)
- fclose(tfile);
+ if (tfile != -1)
+ close(tfile);
fprintf(stderr, "%s: %s\n", *argv, pam_errors(i));
exit(1);
}
@@ -934,13 +1006,13 @@ main( int argc UNUSED, char **argv )
tally.fail_cnt = cline_reset;
}
i=set_tally(NULL, uid, cline_filename, &tfile, &tally);
+ close(tfile);
if (i != PAM_SUCCESS) {
- if (tfile) fclose(tfile);
fprintf(stderr,"%s: %s\n",*argv,pam_errors(i));
exit(1);
}
} else {
- fclose(tfile);
+ close(tfile);
}
}
else /* !cline_user (ie, operate on all users) */ {
diff --git a/modules/pam_unix/pam_unix_acct.c b/modules/pam_unix/pam_unix_acct.c
index 40ff3c06..f8698337 100644
--- a/modules/pam_unix/pam_unix_acct.c
+++ b/modules/pam_unix/pam_unix_acct.c
@@ -65,7 +65,7 @@ int _unix_run_verify_binary(pam_handle_t *pamh, unsigned int ctrl,
const char *user, int *daysleft)
{
int retval=0, child, fds[2];
- void (*sighandler)(int) = NULL;
+ struct sigaction newsa, oldsa;
D(("running verify_binary"));
/* create a pipe for the messages */
@@ -85,7 +85,9 @@ int _unix_run_verify_binary(pam_handle_t *pamh, unsigned int ctrl,
* The "noreap" module argument is provided so that the admin can
* override this behavior.
*/
- sighandler = signal(SIGCHLD, SIG_DFL);
+ memset(&newsa, '\0', sizeof(newsa));
+ newsa.sa_handler = SIG_DFL;
+ sigaction(SIGCHLD, &newsa, &oldsa);
}
/* fork */
@@ -158,9 +160,11 @@ int _unix_run_verify_binary(pam_handle_t *pamh, unsigned int ctrl,
}
close(fds[0]);
}
- if (sighandler != SIG_ERR) {
- (void) signal(SIGCHLD, sighandler); /* restore old signal handler */
+
+ if (off(UNIX_NOREAP, ctrl)) {
+ sigaction(SIGCHLD, &oldsa, NULL); /* restore old signal handler */
}
+
D(("Returning %d",retval));
return retval;
}
diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c
index b8da9913..9386d87f 100644
--- a/modules/pam_unix/pam_unix_passwd.c
+++ b/modules/pam_unix/pam_unix_passwd.c
@@ -139,7 +139,7 @@ static int _unix_run_update_binary(pam_handle_t *pamh, unsigned int ctrl, const
const char *fromwhat, const char *towhat, int remember)
{
int retval, child, fds[2];
- void (*sighandler)(int) = NULL;
+ struct sigaction newsa, oldsa;
D(("called."));
/* create a pipe for the password */
@@ -157,7 +157,9 @@ static int _unix_run_update_binary(pam_handle_t *pamh, unsigned int ctrl, const
* The "noreap" module argument is provided so that the admin can
* override this behavior.
*/
- sighandler = signal(SIGCHLD, SIG_DFL);
+ memset(&newsa, '\0', sizeof(newsa));
+ newsa.sa_handler = SIG_DFL;
+ sigaction(SIGCHLD, &newsa, &oldsa);
}
/* fork */
@@ -236,8 +238,8 @@ static int _unix_run_update_binary(pam_handle_t *pamh, unsigned int ctrl, const
retval = PAM_AUTH_ERR;
}
- if (sighandler != SIG_ERR) {
- (void) signal(SIGCHLD, sighandler); /* restore old signal handler */
+ if (off(UNIX_NOREAP, ctrl)) {
+ sigaction(SIGCHLD, &oldsa, NULL); /* restore old signal handler */
}
return retval;
diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c
index 360bd90b..234e86dd 100644
--- a/modules/pam_unix/passverify.c
+++ b/modules/pam_unix/passverify.c
@@ -994,8 +994,12 @@ su_sighandler(int sig)
{
#ifndef SA_RESETHAND
/* emulate the behaviour of the SA_RESETHAND flag */
- if ( sig == SIGILL || sig == SIGTRAP || sig == SIGBUS || sig = SIGSERV )
- signal(sig, SIG_DFL);
+ 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);
diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c
index faec20dc..6e1bd454 100644
--- a/modules/pam_unix/support.c
+++ b/modules/pam_unix/support.c
@@ -408,7 +408,7 @@ static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd,
unsigned int ctrl, const char *user)
{
int retval, child, fds[2];
- void (*sighandler)(int) = NULL;
+ struct sigaction newsa, oldsa;
D(("called."));
/* create a pipe for the password */
@@ -426,7 +426,9 @@ static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd,
* The "noreap" module argument is provided so that the admin can
* override this behavior.
*/
- sighandler = signal(SIGCHLD, SIG_DFL);
+ memset(&newsa, '\0', sizeof(newsa));
+ newsa.sa_handler = SIG_DFL;
+ sigaction(SIGCHLD, &newsa, &oldsa);
}
/* fork */
@@ -497,8 +499,8 @@ static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd,
retval = PAM_AUTH_ERR;
}
- if (sighandler != SIG_ERR) {
- (void) signal(SIGCHLD, sighandler); /* restore old signal handler */
+ if (off(UNIX_NOREAP, ctrl)) {
+ sigaction(SIGCHLD, &oldsa, NULL); /* restore old signal handler */
}
D(("returning %d", retval));