int failcheck (uid_t uid, struct faillog *fl, int failed) { int fd; struct faillog fail; /* * Suppress the check if the log file isn't there. */ if ((fd = open (FAILLOG_FILE, O_RDWR)) < 0) 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. */ lseek (fd, (off_t) (sizeof *fl) * uid, SEEK_SET); if (read (fd, (char *) fl, sizeof *fl) != sizeof *fl) { close (fd); return 1; } if (too_many_failures (fl)) { 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; lseek (fd, (off_t) sizeof fail * uid, SEEK_SET); write (fd, (char *) &fail, sizeof fail); } close (fd); return 1; }
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; }