On Sat, Jan 17, 2026 at 03:58:28PM -0700, Todd C. Miller wrote: > On Sun, 18 Jan 2026 11:38:06 +1300, Avon Robertson wrote: > > > Is there a base binary that can read file /var/log/failedlogin? > > > > If not, is there a ports package that can read it? > > > > TIA for your replies. > > That file is used by login(1) to report the last failed login but > there isn't a separate program that uses it. One thing to be aware > of is that it the info gets cleared after a successful login occurs. > > I hacked up the failedlogin.c code from login(1) so that a user's > entry can be queried. It will only display something if the user > has had bad login. Maybe this will help. > > For example: > > % sudo ./failedlogin millert > Last unsuccessful login: Sat Jan 17 15:57:38 on tty00 > > - todd > > /* $OpenBSD: failedlogin.c,v 1.19 2021/10/24 21:24:16 deraadt Exp $ > */ > > /* > * Copyright (c) 1996 Todd C. Miller <[email protected]> > * > * Permission to use, copy, modify, and distribute this software for any > * purpose with or without fee is hereby granted, provided that the above > * copyright notice and this permission notice appear in all copies. > * > * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES > * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF > * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR > * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES > * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN > * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF > * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > */ > > /* > * failedlogin.c > * Log to failedlogin file and read from it, reporting the number of > * failed logins since the last good login and when/from where > * the last failed login was. > */ > > #include <sys/stat.h> > #include <sys/time.h> > > #include <err.h> > #include <fcntl.h> > #include <pwd.h> > #include <stdio.h> > #include <string.h> > #include <unistd.h> > #include <utmp.h> > > #define _PATH_FAILEDLOGIN "/var/log/failedlogin" > > struct badlogin { > char bl_line[UT_LINESIZE]; /* tty used */ > char bl_name[UT_NAMESIZE]; /* remote username */ > char bl_host[UT_HOSTSIZE]; /* remote host */ > time_t bl_time; /* time of the login attempt */ > size_t count; /* number of bad logins */ > }; > > /* > * Check the failedlogin file and report about the number of unsuccessful > * logins and info about the last one in lastlogin style. > */ > static int > check_failedlogin(const char *name, uid_t uid) > { > struct badlogin failedlogin; > int fd, was_bad = 0; > > (void)memset(&failedlogin, 0, sizeof(failedlogin)); > > if ((fd = open(_PATH_FAILEDLOGIN, O_RDONLY)) == -1) > err(1, _PATH_FAILEDLOGIN); > (void)lseek(fd, (off_t)uid * sizeof(failedlogin), SEEK_SET); > if (read(fd, &failedlogin, sizeof(failedlogin)) == -1) > err(1, _PATH_FAILEDLOGIN); > if (failedlogin.count > 0 ) { > /* There was a bad login */ > was_bad = 1; > if (failedlogin.count > 1) > (void)printf("There have been %lu unsuccessful " > "login attempts for user %s.\n", > (u_long)failedlogin.count, name); > (void)printf("Last unsuccessful login: %.*s", 24-5, > ctime(&failedlogin.bl_time)); > (void)printf(" on %.*s", > (int)sizeof(failedlogin.bl_line), > failedlogin.bl_line); > if (*failedlogin.bl_host != '\0') { > if (*failedlogin.bl_name != '\0') > (void)printf(" from %.*s@%.*s", > (int)sizeof(failedlogin.bl_name), > failedlogin.bl_name, > (int)sizeof(failedlogin.bl_host), > failedlogin.bl_host); > else > (void)printf(" from %.*s", > (int)sizeof(failedlogin.bl_host), > failedlogin.bl_host); > } > (void)putchar('\n'); > } > (void)close(fd); > > return(was_bad); > } > > int > main(int argc, char *argv[]) > { > int i, ret = 0; > > for (i = 1; i < argc; i++) { > uid_t uid; > const char *name = argv[i]; > int status = uid_from_user(name, &uid); > if (status != 0) { > warnx("unknown user %s", name); > ret = 1; > continue; > } > check_failedlogin(name, uid); > } > > return ret; > }
Thank you very much Todd! Initially, I will use your code to check for attempted logins on my home router. -- aer

