Forward port a patch by Dianora to add rudimentary spam bot detection to ircu.
[ircu2.10.12-pk.git] / patches / diffs / antispambot.diff
1 Index: ircd/m_join.c
2 ===================================================================
3 --- ircd/m_join.c       (revision 1907)
4 +++ ircd/m_join.c       (working copy)
5 @@ -254,6 +254,7 @@
6        }
7  
8        joinbuf_join(&join, chptr, flags);
9 +      cli_last_join_time(sptr) = CurrentTime;
10        if (flags & CHFL_CHANOP) {
11          struct ModeBuf mbuf;
12         /* Always let the server op him: this is needed on a net with older servers
13 Index: ircd/channel.c
14 ===================================================================
15 --- ircd/channel.c      (revision 1907)
16 +++ ircd/channel.c      (working copy)
17 @@ -3594,6 +3594,69 @@
18    return 0;
19  }
20  
21 +/* check_spambot_warning()
22 + *
23 + * inputs       - Client to check, channel name or NULL if this is a part.
24 + * output       - NONE
25 + * side effects - Updates the client's oper_warn_count_down, warns the
26 + *                IRC operators if necessary, and updates
27 + *                join_leave_countdown as needed.
28 + */
29 +void
30 +check_spambot_warning(struct Client *source_p, const char *name)
31 +{
32 +  time_t t_delta;
33 +  int decrement_count;
34 +
35 +  if (source_p->join_leave_count >= SPAM_NUM)
36 +  {
37 +    if (source_p->oper_warn_count_down > 0)
38 +      source_p->oper_warn_count_down--;
39 +    else
40 +      source_p->oper_warn_count_down = 0;
41 +    if (source_p->oper_warn_count_down == 0)
42 +    {
43 +      /* Its already known as a possible spambot */
44 +      if (name != NULL)
45 +        sendto_opmask_butone(0, SNO_OLDSNO,
46 +                             "User %s (%s@%s) trying to join %s is a possible spambot",
47 +                             cli_name(source_p), cli_username(source_p),
48 +                             cli_sockhost(source_p), name);
49 +      else
50 +        sendto_opmask_butone(0, SNO_OLDSNO,
51 +                             "User %s (%s@%s) is a possible spambot",
52 +                             cli_name(source_p), cli_username(source_p),
53 +                             cli_sockhost(source_p));
54 +
55 +      cli_oper_warn_count_down(source_p) = OPER_SPAM_COUNTDOWN;
56 +    }
57 +  }
58 +  else
59 +  {
60 +    if ((t_delta = (CurrentTime - source_p->last_leave_time)) >
61 +         JOIN_LEAVE_COUNT_EXPIRE_TIME)
62 +    {
63 +      decrement_count = (t_delta / JOIN_LEAVE_COUNT_EXPIRE_TIME);
64 +      if (decrement_count > source_p->join_leave_count)
65 +        source_p->join_leave_count = 0;
66 +      else
67 +        source_p->join_leave_count -= decrement_count;
68 +    }
69 +    else
70 +    {
71 +      if ((CurrentTime - (source_p->last_join_time)) < SPAM_TIME)
72 +      {
73 +        /* oh, its a possible spambot */
74 +        source_p->join_leave_count++;
75 +      }
76 +    }
77 +    if (name != NULL)
78 +      cli_last_join_time(source_p) = CurrentTime;
79 +    else
80 +      cli_last_leave_time(source_p) = CurrentTime;
81 +  }
82 +}
83 +
84  /* Returns TRUE (1) if client is invited, FALSE (0) if not */
85  int IsInvited(struct Client* cptr, const void* chptr)
86  {
87 Index: ircd/m_part.c
88 ===================================================================
89 --- ircd/m_part.c       (revision 1907)
90 +++ ircd/m_part.c       (working copy)
91 @@ -150,6 +150,8 @@
92      if (IsDelayedJoin(member))
93        flags |= CHFL_DELAYED;
94  
95 +    if (!IsOper(sptr))
96 +      check_spambot_warning(sptr, NULL);
97      joinbuf_join(&parts, chptr, flags); /* part client from channel */
98    }
99  
100 Index: include/channel.h
101 ===================================================================
102 --- include/channel.h   (revision 1907)
103 +++ include/channel.h   (working copy)
104 @@ -449,4 +449,40 @@
105  extern int apply_ban(struct Ban **banlist, struct Ban *newban, int free);
106  extern void free_ban(struct Ban *ban);
107  
108 +/* ANTISPAM join/part bot code.
109 + *
110 + * You might want to make these tweakable with an oper command
111 + * Or move them into config.h
112 + *
113 + * - Dianora
114 + */
115 +/* Minimum length of time on a channel that a client has to be on
116 + * before its not considered a possible spam bot.
117 + */
118 +#define MIN_JOIN_LEAVE_TIME  60        
119 +/* So opers don't get overly spammed about spambots, only warn
120 + * every OPER_SPAM_COUNTDOWN times. You could remove this code.
121 + */
122 +#define OPER_SPAM_COUNTDOWN   5 
123 +/* After a client leaves, we zero the counters after this length
124 + * of time. i.e. if a client is well behaved, we simply zero.
125 + */
126 +#define JOIN_LEAVE_COUNT_EXPIRE_TIME 120
127 +
128 +/* These are leftovers from hybrids /quote set, for now I have
129 + * left them in. You can remove as you wish.
130 + */
131 +#define MIN_SPAM_NUM 5
132 +#define MIN_SPAM_TIME 60
133 +/* This is a leftover from hybrids /quote set system.
134 + */
135 +#define MAX_JOIN_LEAVE_COUNT  25
136 +
137 +/* You will really want to tweak these, but these aren't bad if
138 + * they have to be statically defined.
139 + */
140 +#define SPAM_TIME MIN_JOIN_LEAVE_TIME
141 +#define SPAM_NUM  MIN_SPAM_NUM
142 +
143 +extern void check_spambot_warning(struct Client *source_p, const char *name);
144  #endif /* INCLUDED_channel_h */
145 Index: include/client.h
146 ===================================================================
147 --- include/client.h    (revision 1907)
148 +++ include/client.h    (working copy)
149 @@ -258,6 +258,16 @@
150    char cli_name[HOSTLEN + 1];     /**< Unique name of the client, nick or host */
151    char cli_username[USERLEN + 1]; /**< Username determined by ident lookup */
152    char cli_info[REALLEN + 1];     /**< Free form additional client information */
153 +
154 +  /* Anti flooding part, all because of lamers... */
155 +  time_t            last_join_time;   /* when this client last 
156 +                                         joined a channel */
157 +  time_t            last_leave_time;  /* when this client last 
158 +                                       * left a channel */
159 +  int               join_leave_count; /* count of JOIN/LEAVE in less than 
160 +                                         MIN_JOIN_LEAVE_TIME seconds */
161 +  int               oper_warn_count_down; /* warn opers of this possible 
162 +                                             spambot every time this gets to 0 */
163  };
164  
165  /** Magic constant to identify valid Client structures. */
166 @@ -736,5 +746,13 @@
167  extern void client_set_privs(struct Client *client, struct ConfItem *oper);
168  extern int client_report_privs(struct Client* to, struct Client* client);
169  
170 +/* ANTISPAM bot patch
171 + * - Dianora
172 + */
173 +#define cli_last_join_time(cli)                ((cli)->last_join_time)
174 +#define cli_last_leave_time(cli)       ((cli)->last_leave_time)
175 +#define cli_join_leave_count(cli)      ((cli)->join_leave_count)
176 +#define cli_oper_warn_count_down(cli)  ((cli)->oper_warn_count_down)
177 +
178  #endif /* INCLUDED_client_h */
179