aboutsummaryrefslogtreecommitdiff
path: root/modules/pam_lastlog/pam_lastlog.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/pam_lastlog/pam_lastlog.c')
-rw-r--r--modules/pam_lastlog/pam_lastlog.c58
1 files changed, 37 insertions, 21 deletions
diff --git a/modules/pam_lastlog/pam_lastlog.c b/modules/pam_lastlog/pam_lastlog.c
index abd048df..ec515f56 100644
--- a/modules/pam_lastlog/pam_lastlog.c
+++ b/modules/pam_lastlog/pam_lastlog.c
@@ -57,14 +57,13 @@ struct lastlog {
# define PATH_LOGIN_DEFS "/etc/login.defs"
#endif
-/* XXX - time before ignoring lock. Is 1 sec enough? */
-#define LASTLOG_IGNORE_LOCK_TIME 1
-
#define DEFAULT_HOST "" /* "[no.where]" */
#define DEFAULT_TERM "" /* "tt???" */
#define DEFAULT_INACTIVE_DAYS 90
#define MAX_INACTIVE_DAYS 100000
+#define LOCK_RETRIES 3 /* number of file lock retries */
+#define LOCK_RETRY_DELAY 1 /* seconds to wait between lock attempts */
#include <security/pam_modules.h>
#include <security/_pam_macros.h>
@@ -266,6 +265,7 @@ last_login_read(pam_handle_t *pamh, int announce, int last_fd, uid_t uid, time_t
{
struct flock last_lock;
struct lastlog last_login;
+ int lock_retries = LOCK_RETRIES;
int retval = PAM_SUCCESS;
char the_time[256];
char *date = NULL;
@@ -278,11 +278,19 @@ last_login_read(pam_handle_t *pamh, int announce, int last_fd, uid_t uid, time_t
last_lock.l_start = sizeof(last_login) * (off_t) uid;
last_lock.l_len = sizeof(last_login);
- if (fcntl(last_fd, F_SETLK, &last_lock) < 0) {
+ while (fcntl(last_fd, F_SETLK, &last_lock) < 0) {
+ if (0 == --lock_retries) {
+ /* read lock failed, proceed anyway to avoid possible DoS */
+ D(("locking %s failed", _PATH_LASTLOG));
+ pam_syslog(pamh, LOG_INFO,
+ "file %s is locked/read, proceeding anyway",
+ _PATH_LASTLOG);
+ break;
+ }
D(("locking %s failed..(waiting a little)", _PATH_LASTLOG));
- pam_syslog(pamh, LOG_WARNING,
- "file %s is locked/read", _PATH_LASTLOG);
- sleep(LASTLOG_IGNORE_LOCK_TIME);
+ pam_syslog(pamh, LOG_INFO,
+ "file %s is locked/read, retrying", _PATH_LASTLOG);
+ sleep(LOCK_RETRY_DELAY);
}
if (pam_modutil_read(last_fd, (char *) &last_login,
@@ -358,11 +366,11 @@ last_login_read(pam_handle_t *pamh, int announce, int last_fd, uid_t uid, time_t
/* cleanup */
cleanup:
- memset(&last_login, 0, sizeof(last_login));
- _pam_overwrite(date);
- _pam_overwrite(host);
+ pam_overwrite_object(&last_login);
+ pam_overwrite_string(date);
+ pam_overwrite_string(host);
_pam_drop(host);
- _pam_overwrite(line);
+ pam_overwrite_string(line);
_pam_drop(line);
return retval;
@@ -380,6 +388,7 @@ last_login_write(pam_handle_t *pamh, int announce, int last_fd,
int setrlimit_res;
struct flock last_lock;
struct lastlog last_login;
+ int lock_retries = LOCK_RETRIES;
time_t ll_time;
const void *void_remote_host = NULL;
const char *remote_host;
@@ -426,10 +435,17 @@ last_login_write(pam_handle_t *pamh, int announce, int last_fd,
last_lock.l_start = sizeof(last_login) * (off_t) uid;
last_lock.l_len = sizeof(last_login);
- if (fcntl(last_fd, F_SETLK, &last_lock) < 0) {
+ while (fcntl(last_fd, F_SETLK, &last_lock) < 0) {
+ if (0 == --lock_retries) {
+ D(("locking %s failed", _PATH_LASTLOG));
+ pam_syslog(pamh, LOG_ERR,
+ "file %s is locked/write", _PATH_LASTLOG);
+ return PAM_SERVICE_ERR;
+ }
D(("locking %s failed..(waiting a little)", _PATH_LASTLOG));
- pam_syslog(pamh, LOG_WARNING, "file %s is locked/write", _PATH_LASTLOG);
- sleep(LASTLOG_IGNORE_LOCK_TIME);
+ pam_syslog(pamh, LOG_INFO,
+ "file %s is locked/write, retrying", _PATH_LASTLOG);
+ sleep(LOCK_RETRY_DELAY);
}
/*
@@ -486,7 +502,7 @@ last_login_write(pam_handle_t *pamh, int announce, int last_fd,
}
/* cleanup */
- memset(&last_login, 0, sizeof(last_login));
+ pam_overwrite_object(&last_login);
return retval;
}
@@ -573,12 +589,12 @@ last_login_failed(pam_handle_t *pamh, int announce, const char *user, time_t llt
time_t lf_time;
lf_time = utuser.ut_tv.tv_sec;
- tm = localtime_r (&lf_time, &tm_buf);
- strftime (the_time, sizeof (the_time),
- /* TRANSLATORS: "strftime options for date of last login" */
- _(" %a %b %e %H:%M:%S %Z %Y"), tm);
-
- date = the_time;
+ if ((tm = localtime_r (&lf_time, &tm_buf)) != NULL) {
+ strftime (the_time, sizeof (the_time),
+ /* TRANSLATORS: "strftime options for date of last login" */
+ _(" %a %b %e %H:%M:%S %Z %Y"), tm);
+ date = the_time;
+ }
}
/* we want & have the host? */