aboutsummaryrefslogtreecommitdiff
path: root/riemann.fmi.uni-sofia.bg/programs/nlogin-0.3-pre/faillog_do.c
blob: 84e2f83a9cc703a95c45357ec369ad99abb5b57e (plain)
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;
}