diff options
Diffstat (limited to 'libmisc/failure.c')
-rw-r--r-- | libmisc/failure.c | 295 |
1 files changed, 0 insertions, 295 deletions
diff --git a/libmisc/failure.c b/libmisc/failure.c deleted file mode 100644 index 1aab299..0000000 --- a/libmisc/failure.c +++ /dev/null @@ -1,295 +0,0 @@ -/* - * SPDX-FileCopyrightText: 1989 - 1994, Julianne Frances Haugh - * SPDX-FileCopyrightText: 1996 - 1998, Marek Michałkiewicz - * SPDX-FileCopyrightText: 2002 - 2005, Tomasz Kłoczko - * SPDX-FileCopyrightText: 2008 - 2010, Nicolas François - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include <config.h> - -#ident "$Id$" - -#include <fcntl.h> -#include <stdio.h> -#include <unistd.h> -#include "defines.h" -#include "faillog.h" -#include "getdef.h" -#include "failure.h" -#define YEAR (365L*DAY) -/* - * failure - make failure entry - * - * failure() creates a new (struct faillog) entry or updates an - * existing one with the current failed login information. - */ -void failure (uid_t uid, const char *tty, struct faillog *fl) -{ - int fd; - off_t offset_uid = (off_t) (sizeof *fl) * uid; - - /* - * Don't do anything if failure logging isn't set up. - */ - - if (access (FAILLOG_FILE, F_OK) != 0) { - return; - } - - fd = open (FAILLOG_FILE, O_RDWR); - if (fd < 0) { - SYSLOG ((LOG_WARN, - "Can't write faillog entry for UID %lu in %s.", - (unsigned long) uid, FAILLOG_FILE)); - return; - } - - /* - * The file is indexed by UID value meaning that shared UID's - * share failure log records. That's OK since they really - * share just about everything else ... - */ - - if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid) - || (read (fd, (char *) fl, sizeof *fl) != (ssize_t) sizeof *fl)) { - /* This is not necessarily a failure. The file is - * initially zero length. - * - * If lseek() or read() failed for any other reason, this - * might reset the counter. But the new failure will be - * logged. - */ - memzero (fl, sizeof *fl); - } - - /* - * Update the record. We increment the failure count to log the - * latest failure. The only concern here is overflow, and we'll - * check for that. The line name and time of day are both - * updated as well. - */ - - if (fl->fail_cnt + 1 > 0) { - fl->fail_cnt++; - } - - strncpy (fl->fail_line, tty, sizeof (fl->fail_line) - 1); - (void) time (&fl->fail_time); - - /* - * Seek back to the correct position in the file and write the - * record out. Ideally we should lock the file in case the same - * account is being logged simultaneously. But the risk doesn't - * seem that great. - */ - - if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid) - || (write (fd, (char *) fl, sizeof *fl) != (ssize_t) sizeof *fl) - || (close (fd) != 0)) { - SYSLOG ((LOG_WARN, - "Can't write faillog entry for UID %lu in %s.", - (unsigned long) uid, FAILLOG_FILE)); - (void) close (fd); - } -} - -static bool too_many_failures (const struct faillog *fl) -{ - time_t now; - - if ((0 == fl->fail_max) || (fl->fail_cnt < fl->fail_max)) { - return false; - } - - if (0 == fl->fail_locktime) { - return true; /* locked until reset manually */ - } - - (void) time (&now); - if ((fl->fail_time + fl->fail_locktime) < now) { - return false; /* enough time since last failure */ - } - - return true; -} - -/* - * failcheck - check for failures > allowable - * - * failcheck() is called AFTER the password has been validated. If the - * account has been "attacked" with too many login failures, failcheck() - * returns 0 to indicate that the login should be denied even though - * the password is valid. - * - * failed indicates if the login failed AFTER the password has been - * validated. - */ - -int failcheck (uid_t uid, struct faillog *fl, bool failed) -{ - int fd; - struct faillog fail; - off_t offset_uid = (off_t) (sizeof *fl) * uid; - - /* - * Suppress the check if the log file isn't there. - */ - - if (access (FAILLOG_FILE, F_OK) != 0) { - return 1; - } - - fd = open (FAILLOG_FILE, failed?O_RDONLY:O_RDWR); - if (fd < 0) { - SYSLOG ((LOG_WARN, - "Can't open the faillog file (%s) to check UID %lu. " - "User access authorized.", - FAILLOG_FILE, (unsigned long) uid)); - return 1; - } - - /* - * Get the record from the file and determine if the user has - * exceeded the failure limit. If "max" is zero, any number - * of failures are permitted. Only when "max" is non-zero and - * "cnt" is greater than or equal to "max" is the account - * considered to be locked. - * - * If read fails, there is no record for this user yet (the - * file is initially zero length and extended by writes), so - * no need to reset the count. - */ - - if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid) - || (read (fd, (char *) fl, sizeof *fl) != (ssize_t) sizeof *fl)) { - (void) close (fd); - return 1; - } - - if (too_many_failures (fl)) { - (void) close (fd); - return 0; - } - - /* - * The record is updated if this is not a failure. The count will - * be reset to zero, but the rest of the information will be left - * in the record in case someone wants to see where the failed - * login originated. - */ - - if (!failed) { - fail = *fl; - fail.fail_cnt = 0; - - if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid) - || (write (fd, (const void *) &fail, sizeof fail) != (ssize_t) sizeof fail) - || (close (fd) != 0)) { - SYSLOG ((LOG_WARN, - "Can't reset faillog entry for UID %lu in %s.", - (unsigned long) uid, FAILLOG_FILE)); - (void) close (fd); - } - } else { - (void) close (fd); - } - - return 1; -} - -/* - * failprint - print line of failure information - * - * failprint takes a (struct faillog) entry and formats it into a - * message which is displayed at login time. - */ - -void failprint (const struct faillog *fail) -{ - struct tm *tp; - char lasttimeb[256]; - char *lasttime = lasttimeb; - time_t NOW; - - if (0 == fail->fail_cnt) { - return; - } - - tp = localtime (&(fail->fail_time)); - (void) time (&NOW); - - /* - * Print all information we have. - */ - (void) strftime (lasttimeb, sizeof lasttimeb, "%c", tp); - - /*@-formatconst@*/ - (void) printf (ngettext ("%d failure since last login.\n" - "Last was %s on %s.\n", - "%d failures since last login.\n" - "Last was %s on %s.\n", - (unsigned long) fail->fail_cnt), - fail->fail_cnt, lasttime, fail->fail_line); - /*@=formatconst@*/ -} - -/* - * failtmp - update the cumulative failure log - * - * failtmp updates the (struct utmp) formatted failure log which - * maintains a record of all login failures. - */ - -void failtmp (const char *username, -#ifdef USE_UTMPX - const struct utmpx *failent -#else /* !USE_UTMPX */ - const struct utmp *failent -#endif /* !USE_UTMPX */ - ) -{ - const char *ftmp; - int fd; - - /* - * Get the name of the failure file. If no file has been defined - * in login.defs, don't do this. - */ - - ftmp = getdef_str ("FTMP_FILE"); - if (NULL == ftmp) { - return; - } - - /* - * Open the file for append. It must already exist for this - * feature to be used. - */ - - if (access (ftmp, F_OK) != 0) { - return; - } - - fd = open (ftmp, O_WRONLY | O_APPEND); - if (-1 == fd) { - SYSLOG ((LOG_WARN, - "Can't append failure of user %s to %s.", - username, ftmp)); - return; - } - - /* - * Append the new failure record and close the log file. - */ - - if ( (write (fd, (const void *) failent, sizeof *failent) != (ssize_t) sizeof *failent) - || (close (fd) != 0)) { - SYSLOG ((LOG_WARN, - "Can't append failure of user %s to %s.", - username, ftmp)); - (void) close (fd); - } -} - |