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.c452
1 files changed, 0 insertions, 452 deletions
diff --git a/modules/pam_lastlog/pam_lastlog.c b/modules/pam_lastlog/pam_lastlog.c
deleted file mode 100644
index a75e1ce7..00000000
--- a/modules/pam_lastlog/pam_lastlog.c
+++ /dev/null
@@ -1,452 +0,0 @@
-/* pam_lastlog module */
-
-/*
- * Written by Andrew Morgan <morgan@linux.kernel.org> 1996/3/11
- *
- * This module does the necessary work to display the last login
- * time+date for this user, it then updates this entry for the
- * present (login) service.
- */
-
-#include "config.h"
-
-#include <fcntl.h>
-#include <time.h>
-#include <errno.h>
-#ifdef HAVE_UTMP_H
-# include <utmp.h>
-#else
-# include <lastlog.h>
-#endif
-#include <pwd.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <syslog.h>
-#include <unistd.h>
-
-#if defined(hpux) || defined(sunos) || defined(solaris)
-# ifndef _PATH_LASTLOG
-# define _PATH_LASTLOG "/usr/adm/lastlog"
-# endif /* _PATH_LASTLOG */
-# ifndef UT_HOSTSIZE
-# define UT_HOSTSIZE 16
-# endif /* UT_HOSTSIZE */
-# ifndef UT_LINESIZE
-# define UT_LINESIZE 12
-# endif /* UT_LINESIZE */
-#endif
-#if defined(hpux)
-struct lastlog {
- time_t ll_time;
- char ll_line[UT_LINESIZE];
- char ll_host[UT_HOSTSIZE]; /* same as in utmp */
-};
-#endif /* hpux */
-
-/* XXX - time before ignoring lock. Is 1 sec enough? */
-#define LASTLOG_IGNORE_LOCK_TIME 1
-
-#define DEFAULT_HOST "" /* "[no.where]" */
-#define DEFAULT_TERM "" /* "tt???" */
-
-/*
- * here, we make a definition for the externally accessible function
- * in this file (this definition is required for static a module
- * but strongly encouraged generally) it is used to instruct the
- * modules include file to define the function prototypes.
- */
-
-#define PAM_SM_SESSION
-
-#include <security/pam_modules.h>
-#include <security/_pam_macros.h>
-#include <security/pam_modutil.h>
-#include <security/pam_ext.h>
-
-/* argument parsing */
-
-#define LASTLOG_DATE 01 /* display the date of the last login */
-#define LASTLOG_HOST 02 /* display the last host used (if set) */
-#define LASTLOG_LINE 04 /* display the last terminal used */
-#define LASTLOG_NEVER 010 /* display a welcome message for first login */
-#define LASTLOG_DEBUG 020 /* send info to syslog(3) */
-#define LASTLOG_QUIET 040 /* keep quiet about things */
-#define LASTLOG_WTMP 0100 /* log to wtmp as well as lastlog */
-
-static int
-_pam_parse(pam_handle_t *pamh, int flags, int argc, const char **argv)
-{
- int ctrl=(LASTLOG_DATE|LASTLOG_HOST|LASTLOG_LINE|LASTLOG_WTMP);
-
- /* does the appliction require quiet? */
- if (flags & PAM_SILENT) {
- ctrl |= LASTLOG_QUIET;
- }
-
- /* step through arguments */
- for (; argc-- > 0; ++argv) {
-
- /* generic options */
-
- if (!strcmp(*argv,"debug")) {
- ctrl |= LASTLOG_DEBUG;
- } else if (!strcmp(*argv,"nodate")) {
- ctrl &= ~LASTLOG_DATE;
- } else if (!strcmp(*argv,"noterm")) {
- ctrl &= ~LASTLOG_LINE;
- } else if (!strcmp(*argv,"nohost")) {
- ctrl &= ~LASTLOG_HOST;
- } else if (!strcmp(*argv,"silent")) {
- ctrl |= LASTLOG_QUIET;
- } else if (!strcmp(*argv,"never")) {
- ctrl |= LASTLOG_NEVER;
- } else if (!strcmp(*argv,"nowtmp")) {
- ctrl &= ~LASTLOG_WTMP;
- } else {
- pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv);
- }
- }
-
- D(("ctrl = %o", ctrl));
- return ctrl;
-}
-
-static const char *
-get_tty(pam_handle_t *pamh)
-{
- const void *void_terminal_line = NULL;
- const char *terminal_line;
-
- if (pam_get_item(pamh, PAM_TTY, &void_terminal_line) != PAM_SUCCESS
- || void_terminal_line == NULL) {
- terminal_line = DEFAULT_TERM;
- } else {
- terminal_line = void_terminal_line;
- }
- if (!strncmp("/dev/", terminal_line, 5)) {
- /* strip leading "/dev/" from tty. */
- terminal_line += 5;
- }
- D(("terminal = %s", terminal_line));
- return terminal_line;
-}
-
-static int
-last_login_read(pam_handle_t *pamh, int announce, int last_fd, uid_t uid)
-{
- struct flock last_lock;
- struct lastlog last_login;
- int retval = PAM_SUCCESS;
- char the_time[256];
- char *date = NULL;
- char *host = NULL;
- char *line = NULL;
-
- memset(&last_lock, 0, sizeof(last_lock));
- last_lock.l_type = F_RDLCK;
- last_lock.l_whence = SEEK_SET;
- 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) {
- 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);
- }
-
- if (pam_modutil_read(last_fd, (char *) &last_login,
- sizeof(last_login)) != sizeof(last_login)) {
- memset(&last_login, 0, sizeof(last_login));
- }
-
- last_lock.l_type = F_UNLCK;
- (void) fcntl(last_fd, F_SETLK, &last_lock); /* unlock */
-
- if (!last_login.ll_time) {
- if (announce & LASTLOG_DEBUG) {
- pam_syslog(pamh, LOG_DEBUG,
- "first login for user with uid %lu",
- (unsigned long int)uid);
- }
- }
-
- if (!(announce & LASTLOG_QUIET)) {
-
- if (last_login.ll_time) {
-
- /* we want the date? */
- if (announce & LASTLOG_DATE) {
- struct tm *tm, tm_buf;
- time_t ll_time;
-
- ll_time = last_login.ll_time;
- tm = localtime_r (&ll_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;
- }
-
- /* we want & have the host? */
- if ((announce & LASTLOG_HOST)
- && (last_login.ll_host[0] != '\0')) {
- /* TRANSLATORS: " from <host>" */
- if (asprintf(&host, _(" from %.*s"), UT_HOSTSIZE,
- last_login.ll_host) < 0) {
- pam_syslog(pamh, LOG_ERR, "out of memory");
- retval = PAM_BUF_ERR;
- goto cleanup;
- }
- }
-
- /* we want and have the terminal? */
- if ((announce & LASTLOG_LINE)
- && (last_login.ll_line[0] != '\0')) {
- /* TRANSLATORS: " on <terminal>" */
- if (asprintf(&line, _(" on %.*s"), UT_LINESIZE,
- last_login.ll_line) < 0) {
- pam_syslog(pamh, LOG_ERR, "out of memory");
- retval = PAM_BUF_ERR;
- goto cleanup;
- }
- }
-
- /* TRANSLATORS: "Last login: <date> from <host> on <terminal>" */
- retval = pam_info(pamh, _("Last login:%s%s%s"),
- date ? date : "",
- host ? host : "",
- line ? line : "");
- } else if (announce & LASTLOG_NEVER) {
- D(("this is the first time this user has logged in"));
- retval = pam_info(pamh, "%s", _("Welcome to your new account!"));
- }
- }
-
- /* cleanup */
- cleanup:
- memset(&last_login, 0, sizeof(last_login));
- _pam_overwrite(date);
- _pam_overwrite(host);
- _pam_drop(host);
- _pam_overwrite(line);
- _pam_drop(line);
-
- return retval;
-}
-
-static int
-last_login_write(pam_handle_t *pamh, int announce, int last_fd,
- uid_t uid, const char *user)
-{
- struct flock last_lock;
- struct lastlog last_login;
- time_t ll_time;
- const void *void_remote_host = NULL;
- const char *remote_host;
- const char *terminal_line;
- int retval = PAM_SUCCESS;
-
- /* rewind */
- if (lseek(last_fd, sizeof(last_login) * (off_t) uid, SEEK_SET) < 0) {
- pam_syslog(pamh, LOG_ERR, "failed to lseek %s: %m", _PATH_LASTLOG);
- return PAM_SERVICE_ERR;
- }
-
- /* set this login date */
- D(("set the most recent login time"));
- (void) time(&ll_time); /* set the time */
- last_login.ll_time = ll_time;
-
- /* set the remote host */
- if (pam_get_item(pamh, PAM_RHOST, &void_remote_host) != PAM_SUCCESS
- || void_remote_host == NULL) {
- remote_host = DEFAULT_HOST;
- } else {
- remote_host = void_remote_host;
- }
-
- /* 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;
-
- D(("locking lastlog file"));
-
- /* now we try to lock this file-record exclusively; non-blocking */
- memset(&last_lock, 0, sizeof(last_lock));
- last_lock.l_type = F_WRLCK;
- last_lock.l_whence = SEEK_SET;
- 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) {
- 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);
- }
-
- D(("writing to the lastlog file"));
- if (pam_modutil_write (last_fd, (char *) &last_login,
- sizeof (last_login)) != sizeof(last_login)) {
- pam_syslog(pamh, LOG_ERR, "failed to write %s: %m", _PATH_LASTLOG);
- retval = PAM_SERVICE_ERR;
- }
-
- last_lock.l_type = F_UNLCK;
- (void) fcntl(last_fd, F_SETLK, &last_lock); /* unlock */
- D(("unlocked"));
-
- if (announce & LASTLOG_WTMP) {
- /* write wtmp entry for user */
- logwtmp(last_login.ll_line, user, remote_host);
- }
-
- /* cleanup */
- memset(&last_login, 0, sizeof(last_login));
-
- return retval;
-}
-
-static int
-last_login_date(pam_handle_t *pamh, int announce, uid_t uid, const char *user)
-{
- int retval;
- int last_fd;
-
- /* obtain the last login date and all the relevant info */
- last_fd = open(_PATH_LASTLOG, O_RDWR);
- if (last_fd < 0) {
- if (errno == ENOENT) {
- last_fd = open(_PATH_LASTLOG, O_RDWR|O_CREAT,
- S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
- if (last_fd < 0) {
- pam_syslog(pamh, LOG_ERR,
- "unable to create %s: %m", _PATH_LASTLOG);
- D(("unable to create %s file", _PATH_LASTLOG));
- return PAM_SERVICE_ERR;
- }
- pam_syslog(pamh, LOG_WARNING,
- "file %s created", _PATH_LASTLOG);
- D(("file %s created", _PATH_LASTLOG));
- } else {
- pam_syslog(pamh, LOG_ERR, "unable to open %s: %m", _PATH_LASTLOG);
- D(("unable to open %s file", _PATH_LASTLOG));
- return PAM_SERVICE_ERR;
- }
- }
-
- if (lseek(last_fd, sizeof(struct lastlog) * (off_t) uid, SEEK_SET) < 0) {
- pam_syslog(pamh, LOG_ERR, "failed to lseek %s: %m", _PATH_LASTLOG);
- D(("unable to lseek %s file", _PATH_LASTLOG));
- return PAM_SERVICE_ERR;
- }
-
- retval = last_login_read(pamh, announce, last_fd, uid);
- if (retval != PAM_SUCCESS)
- {
- close(last_fd);
- D(("error while reading lastlog file"));
- return retval;
- }
-
- retval = last_login_write(pamh, announce, last_fd, uid, user);
-
- close(last_fd);
- D(("all done with last login"));
-
- return retval;
-}
-
-/* --- authentication management functions (only) --- */
-
-PAM_EXTERN int
-pam_sm_open_session(pam_handle_t *pamh, int flags,
- int argc, const char **argv)
-{
- int retval, ctrl;
- const void *user;
- const struct passwd *pwd;
- uid_t uid;
-
- /*
- * this module gets the uid of the PAM_USER. Uses it to display
- * last login info and then updates the lastlog for that user.
- */
-
- ctrl = _pam_parse(pamh, flags, argc, argv);
-
- /* which user? */
-
- retval = pam_get_item(pamh, PAM_USER, &user);
- if (retval != PAM_SUCCESS || user == NULL || *(const char *)user == '\0') {
- pam_syslog(pamh, LOG_NOTICE, "user unknown");
- return PAM_USER_UNKNOWN;
- }
-
- /* what uid? */
-
- pwd = pam_modutil_getpwnam (pamh, user);
- if (pwd == NULL) {
- D(("couldn't identify user %s", user));
- return PAM_USER_UNKNOWN;
- }
- uid = pwd->pw_uid;
- pwd = NULL; /* tidy up */
-
- /* process the current login attempt (indicate last) */
-
- retval = last_login_date(pamh, ctrl, uid, user);
-
- /* indicate success or failure */
-
- uid = -1; /* forget this */
-
- return retval;
-}
-
-PAM_EXTERN int
-pam_sm_close_session (pam_handle_t *pamh, int flags,
- int argc, const char **argv)
-{
- const char *terminal_line;
-
- if (!(_pam_parse(pamh, flags, argc, argv) & LASTLOG_WTMP))
- return PAM_SUCCESS;
-
- terminal_line = get_tty(pamh);
-
- /* Wipe out utmp logout entry */
- logwtmp(terminal_line, "", "");
-
- return PAM_SUCCESS;
-}
-
-#ifdef PAM_STATIC
-
-/* static module data */
-
-struct pam_module _pam_lastlog_modstruct = {
- "pam_lastlog",
- NULL,
- NULL,
- NULL,
- pam_sm_open_session,
- pam_sm_close_session,
- NULL,
-};
-
-#endif
-
-/* end of module definition */