1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <sys/types.h>
#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;
}
|