#include #include #include #include #include "str_defs.h" #include "utmp_defs.h" struct faillog { short fail_cnt; /* failures since last success */ short fail_max; /* failures before turning account off */ char fail_line[12]; /* last failure occured here */ time_t fail_time; /* last failure occured then */ /* * If nonzero, the account will be re-enabled if there are no * failures for fail_locktime seconds since last failure. */ long fail_locktime; }; #ifndef NV_PATH_FAILLOG #define NV_PATH_FAILLOG "/var/log/faillog" #endif #define FL_SIZE sizeof(struct faillog) #define SC(A,B) str_copynz(A, B, sizeof(A)) /* OK==0 failure; 1 good password; -1 only check if return is nonzero login is disabled !!! */ int faillog_do(unsigned int uid, char *line, int OK) /*EXTRACT_INCL*/{ struct faillog fl; off_t offset = uid * FL_SIZE; int fd, ret=0; time_t now; fd = open(NV_PATH_FAILLOG, O_RDWR); if (fd<0) return 0; if (lseek(fd,offset,SEEK_SET) ==offset && read(fd,&fl,FL_SIZE)==FL_SIZE) { switch (OK) { case 1: fl.fail_cnt = 0; break; case 0: if (fl.fail_max == 0 || fl.fail_cnt <= fl.fail_max) fl.fail_cnt += 1; } } else byte_zero(&fl, FL_SIZE); now = time(0); if (fl.fail_locktime && fl.fail_time && (now < fl.fail_time || /* barery failed */ now - fl.fail_time > fl.fail_locktime)) fl.fail_cnt = 0; /* unlock account */ if (fl.fail_max > 0 && fl.fail_cnt > fl.fail_max) ret = -1; /* disable logging */ fl.fail_time = now; SC(fl.fail_line, line); if (lseek(fd, offset, SEEK_SET) ==offset) SAFE_IO(write, fd, &fl, FL_SIZE); fsync(fd); close(fd); return (OK==1) ? 0 : ret; }