123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804 |
- /*
- * 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 <ctype.h>
- #include <stdarg.h>
- #include <stdio.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/time.h>
- #include <sys/resource.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 */
- #ifndef _PATH_BTMP
- # define _PATH_BTMP "/var/log/btmp"
- #endif
- #ifndef PATH_LOGIN_DEFS
- # 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
- #include <security/pam_modules.h>
- #include <security/_pam_macros.h>
- #include <security/pam_modutil.h>
- #include <security/pam_ext.h>
- #include "pam_inline.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 */
- #define LASTLOG_BTMP 0200 /* display failed login info from btmp */
- #define LASTLOG_UPDATE 0400 /* update the lastlog and wtmp files (default) */
- #define LASTLOG_UNLIMITED 01000 /* unlimited file size (ignore 'fsize' limit) */
- static int
- _pam_auth_parse(pam_handle_t *pamh, int flags, int argc, const char **argv,
- time_t *inactive)
- {
- int ctrl = 0;
- *inactive = DEFAULT_INACTIVE_DAYS;
- /* does the application require quiet? */
- if (flags & PAM_SILENT) {
- ctrl |= LASTLOG_QUIET;
- }
- /* step through arguments */
- for (; argc-- > 0; ++argv) {
- const char *str;
- char *ep = NULL;
- long l;
- if (!strcmp(*argv,"debug")) {
- ctrl |= LASTLOG_DEBUG;
- } else if (!strcmp(*argv,"silent")) {
- ctrl |= LASTLOG_QUIET;
- } else if ((str = pam_str_skip_prefix(*argv, "inactive=")) != NULL) {
- l = strtol(str, &ep, 10);
- if (ep != str && l > 0 && l < MAX_INACTIVE_DAYS)
- *inactive = l;
- else {
- pam_syslog(pamh, LOG_ERR, "bad option value: %s", *argv);
- }
- } else {
- pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv);
- }
- }
- D(("ctrl = %o", ctrl));
- return ctrl;
- }
- static int
- _pam_session_parse(pam_handle_t *pamh, int flags, int argc, const char **argv)
- {
- int ctrl=(LASTLOG_DATE|LASTLOG_HOST|LASTLOG_LINE|LASTLOG_WTMP|LASTLOG_UPDATE);
- /* 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 if (!strcmp(*argv,"noupdate")) {
- ctrl &= ~(LASTLOG_WTMP|LASTLOG_UPDATE);
- } else if (!strcmp(*argv,"showfailed")) {
- ctrl |= LASTLOG_BTMP;
- } else if (!strcmp(*argv,"unlimited")) {
- ctrl |= LASTLOG_UNLIMITED;
- } else {
- pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv);
- }
- }
- /* does the application require quiet? */
- if (flags & PAM_SILENT) {
- ctrl |= LASTLOG_QUIET;
- ctrl &= ~LASTLOG_BTMP;
- }
- 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;
- const char *str;
- 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;
- }
- /* strip leading "/dev/" from tty. */
- str = pam_str_skip_prefix(terminal_line, "/dev/");
- if (str != NULL)
- terminal_line = str;
- D(("terminal = %s", terminal_line));
- return terminal_line;
- }
- #define MAX_UID_VALUE 0xFFFFFFFFUL
- static uid_t
- get_lastlog_uid_max(pam_handle_t *pamh)
- {
- uid_t uid_max = MAX_UID_VALUE;
- unsigned long ul;
- char *s, *ep;
- s = pam_modutil_search_key(pamh, PATH_LOGIN_DEFS, "LASTLOG_UID_MAX");
- if (s == NULL)
- return uid_max;
- ep = s + strlen(s);
- while (ep > s && isspace(*(--ep))) {
- *ep = '\0';
- }
- errno = 0;
- ul = strtoul(s, &ep, 10);
- if (!(ul >= MAX_UID_VALUE
- || (uid_t)ul >= MAX_UID_VALUE
- || (errno != 0 && ul == 0)
- || s == ep
- || *ep != '\0')) {
- uid_max = (uid_t)ul;
- }
- free(s);
- return uid_max;
- }
- static int
- last_login_open(pam_handle_t *pamh, int announce, uid_t uid)
- {
- int last_fd;
- /* obtain the last login date and all the relevant info */
- last_fd = open(_PATH_LASTLOG, announce&LASTLOG_UPDATE ? O_RDWR : O_RDONLY);
- if (last_fd < 0) {
- if (errno == ENOENT && (announce & LASTLOG_UPDATE)) {
- 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 -1;
- }
- pam_syslog(pamh, LOG_NOTICE,
- "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 -1;
- }
- }
- 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));
- close(last_fd);
- return -1;
- }
- return last_fd;
- }
- static int
- last_login_read(pam_handle_t *pamh, int announce, int last_fd, uid_t uid, time_t *lltime)
- {
- 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 */
- *lltime = last_login.ll_time;
- 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;
- if ((tm = localtime_r (&ll_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? */
- 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_CRIT, "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_CRIT, "out of memory");
- retval = PAM_BUF_ERR;
- goto cleanup;
- }
- }
- if (date != NULL || host != NULL || line != NULL)
- /* 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)
- {
- static struct rlimit no_limit = {
- RLIM_INFINITY,
- RLIM_INFINITY
- };
- struct rlimit old_limit;
- int setrlimit_res;
- 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;
- }
- 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 */
- 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 */
- 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 */
- 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);
- }
- /*
- * Failing to set the 'fsize' limit is not a fatal error. We try to write
- * lastlog anyway, under the risk of dying due to a SIGXFSZ.
- */
- D(("setting limit for 'fsize'"));
- if ((announce & LASTLOG_UNLIMITED) == 0) { /* don't set to unlimited */
- setrlimit_res = -1;
- } else if (getrlimit(RLIMIT_FSIZE, &old_limit) == 0) {
- if (old_limit.rlim_cur == RLIM_INFINITY) { /* already unlimited */
- setrlimit_res = -1;
- } else {
- setrlimit_res = setrlimit(RLIMIT_FSIZE, &no_limit);
- if (setrlimit_res != 0)
- pam_syslog(pamh, LOG_WARNING, "Could not set limit for 'fsize': %m");
- }
- } else {
- setrlimit_res = -1;
- if (errno == EINVAL) {
- pam_syslog(pamh, LOG_INFO, "Limit for 'fsize' not supported: %m");
- } else {
- pam_syslog(pamh, LOG_WARNING, "Could not get limit for 'fsize': %m");
- }
- }
- 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;
- }
- /*
- * Failing to restore the 'fsize' limit is a fatal error.
- */
- D(("restoring limit for 'fsize'"));
- if (setrlimit_res == 0) {
- setrlimit_res = setrlimit(RLIMIT_FSIZE, &old_limit);
- if (setrlimit_res != 0) {
- pam_syslog(pamh, LOG_ERR, "Could not restore limit for 'fsize': %m");
- 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, time_t *lltime)
- {
- int retval;
- int last_fd;
- if (uid > get_lastlog_uid_max(pamh)) {
- return PAM_SUCCESS;
- }
- /* obtain the last login date and all the relevant info */
- last_fd = last_login_open(pamh, announce, uid);
- if (last_fd < 0) {
- return PAM_SERVICE_ERR;
- }
- retval = last_login_read(pamh, announce, last_fd, uid, lltime);
- if (retval != PAM_SUCCESS)
- {
- close(last_fd);
- D(("error while reading lastlog file"));
- return retval;
- }
- if (announce & LASTLOG_UPDATE) {
- retval = last_login_write(pamh, announce, last_fd, uid, user);
- }
- close(last_fd);
- D(("all done with last login"));
- return retval;
- }
- static int
- last_login_failed(pam_handle_t *pamh, int announce, const char *user, time_t lltime)
- {
- int retval;
- int fd;
- struct utmp ut;
- struct utmp utuser;
- int failed = 0;
- char the_time[256];
- char *date = NULL;
- char *host = NULL;
- char *line = NULL;
- if (strlen(user) > UT_NAMESIZE) {
- pam_syslog(pamh, LOG_WARNING, "username too long, output might be inaccurate");
- }
- /* obtain the failed login attempt records from btmp */
- fd = open(_PATH_BTMP, O_RDONLY);
- if (fd < 0) {
- int save_errno = errno;
- pam_syslog(pamh, LOG_ERR, "unable to open %s: %m", _PATH_BTMP);
- D(("unable to open %s file", _PATH_BTMP));
- if (save_errno == ENOENT)
- return PAM_SUCCESS;
- else
- return PAM_SERVICE_ERR;
- }
- while ((retval=pam_modutil_read(fd, (void *)&ut,
- sizeof(ut))) == sizeof(ut)) {
- if (ut.ut_tv.tv_sec >= lltime && strncmp(ut.ut_user, user, UT_NAMESIZE) == 0) {
- memcpy(&utuser, &ut, sizeof(utuser));
- failed++;
- }
- }
- if (retval != 0)
- pam_syslog(pamh, LOG_ERR, "corruption detected in %s", _PATH_BTMP);
- retval = PAM_SUCCESS;
- if (failed) {
- /* we want the date? */
- if (announce & LASTLOG_DATE) {
- struct tm *tm, tm_buf;
- 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;
- }
- /* we want & have the host? */
- if ((announce & LASTLOG_HOST)
- && (utuser.ut_host[0] != '\0')) {
- /* TRANSLATORS: " from <host>" */
- if (asprintf(&host, _(" from %.*s"), UT_HOSTSIZE,
- utuser.ut_host) < 0) {
- pam_syslog(pamh, LOG_CRIT, "out of memory");
- retval = PAM_BUF_ERR;
- goto cleanup;
- }
- }
- /* we want and have the terminal? */
- if ((announce & LASTLOG_LINE)
- && (utuser.ut_line[0] != '\0')) {
- /* TRANSLATORS: " on <terminal>" */
- if (asprintf(&line, _(" on %.*s"), UT_LINESIZE,
- utuser.ut_line) < 0) {
- pam_syslog(pamh, LOG_CRIT, "out of memory");
- retval = PAM_BUF_ERR;
- goto cleanup;
- }
- }
- if (line != NULL || date != NULL || host != NULL) {
- /* TRANSLATORS: "Last failed login: <date> from <host> on <terminal>" */
- pam_info(pamh, _("Last failed login:%s%s%s"),
- date ? date : "",
- host ? host : "",
- line ? line : "");
- }
- _pam_drop(line);
- #if defined HAVE_DNGETTEXT && defined ENABLE_NLS
- retval = asprintf (&line, dngettext(PACKAGE,
- "There was %d failed login attempt since the last successful login.",
- "There were %d failed login attempts since the last successful login.",
- failed),
- failed);
- #else
- if (failed == 1)
- retval = asprintf(&line,
- _("There was %d failed login attempt since the last successful login."),
- failed);
- else
- retval = asprintf(&line,
- /* TRANSLATORS: only used if dngettext is not supported */
- _("There were %d failed login attempts since the last successful login."),
- failed);
- #endif
- if (retval >= 0)
- retval = pam_info(pamh, "%s", line);
- else {
- retval = PAM_BUF_ERR;
- line = NULL;
- }
- }
- cleanup:
- free(host);
- free(line);
- close(fd);
- D(("all done with btmp"));
- return retval;
- }
- /* --- authentication (locking out inactive users) functions --- */
- int
- pam_sm_authenticate(pam_handle_t *pamh, int flags,
- int argc, const char **argv)
- {
- int retval, ctrl;
- const char *user = NULL;
- const struct passwd *pwd;
- uid_t uid;
- time_t lltime = 0;
- time_t inactive_days = 0;
- int last_fd;
- /*
- * Lock out the user if he did not login recently enough.
- */
- ctrl = _pam_auth_parse(pamh, flags, argc, argv, &inactive_days);
- /* which user? */
- if (pam_get_user(pamh, &user, NULL) != PAM_SUCCESS) {
- pam_syslog(pamh, LOG_NOTICE, "cannot determine user name");
- return PAM_USER_UNKNOWN;
- }
- /* what uid? */
- pwd = pam_modutil_getpwnam (pamh, user);
- if (pwd == NULL) {
- pam_syslog(pamh, LOG_NOTICE, "user unknown");
- return PAM_USER_UNKNOWN;
- }
- uid = pwd->pw_uid;
- pwd = NULL; /* tidy up */
- if (uid == 0 || uid > get_lastlog_uid_max(pamh))
- return PAM_SUCCESS;
- /* obtain the last login date and all the relevant info */
- last_fd = last_login_open(pamh, ctrl, uid);
- if (last_fd < 0) {
- return PAM_IGNORE;
- }
- retval = last_login_read(pamh, ctrl|LASTLOG_QUIET, last_fd, uid, &lltime);
- close(last_fd);
- if (retval != PAM_SUCCESS) {
- D(("error while reading lastlog file"));
- return PAM_IGNORE;
- }
- if (lltime == 0) { /* user never logged in before */
- if (ctrl & LASTLOG_DEBUG)
- pam_syslog(pamh, LOG_DEBUG, "user never logged in - pass");
- return PAM_SUCCESS;
- }
- lltime = (time(NULL) - lltime) / (24*60*60);
- if (lltime > inactive_days) {
- pam_syslog(pamh, LOG_INFO, "user %s inactive for %ld days - denied",
- user, (long) lltime);
- return PAM_AUTH_ERR;
- }
- return PAM_SUCCESS;
- }
- int
- pam_sm_setcred(pam_handle_t *pamh UNUSED, int flags UNUSED,
- int argc UNUSED, const char **argv UNUSED)
- {
- return PAM_SUCCESS;
- }
- int
- pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
- int argc, const char **argv)
- {
- return pam_sm_authenticate(pamh, flags, argc, argv);
- }
- /* --- session management functions --- */
- 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;
- time_t lltime = 0;
- /*
- * 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_session_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, &lltime);
- if ((ctrl & LASTLOG_BTMP) && retval == PAM_SUCCESS) {
- retval = last_login_failed(pamh, ctrl, user, lltime);
- }
- /* indicate success or failure */
- uid = -1; /* forget this */
- return retval;
- }
- int
- pam_sm_close_session (pam_handle_t *pamh, int flags,
- int argc, const char **argv)
- {
- const char *terminal_line;
- if (!(_pam_session_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;
- }
- /* end of module definition */
|