]> jfr.im git - solanum.git/blame - ircd/reject.c
librb mbedTLS: der_pubkey is used out of scope
[solanum.git] / ircd / reject.c
CommitLineData
54ac8b60
VY
1/*
2 * ircd-ratbox: A slightly useful ircd
3 * reject.c: reject users with prejudice
4 *
5 * Copyright (C) 2003 Aaron Sethman <androsyn@ratbox.org>
6 * Copyright (C) 2003-2005 ircd-ratbox development team
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
43946961 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
54ac8b60 21 * USA
54ac8b60
VY
22 */
23
24#include "stdinc.h"
54ac8b60
VY
25#include "client.h"
26#include "s_conf.h"
27#include "reject.h"
28#include "s_stats.h"
43946961
JT
29#include "ircd.h"
30#include "send.h"
31#include "numeric.h"
32#include "parse.h"
33#include "hostmask.h"
34#include "match.h"
54ac8b60
VY
35#include "hash.h"
36
0240b419 37static rb_patricia_tree_t *reject_tree;
43946961 38static rb_dlink_list delay_exit;
54ac8b60 39static rb_dlink_list reject_list;
43946961
JT
40static rb_dlink_list throttle_list;
41static rb_patricia_tree_t *throttle_tree;
42static void throttle_expires(void *unused);
54ac8b60 43
54ac8b60 44
43946961 45typedef struct _reject_data
54ac8b60
VY
46{
47 rb_dlink_node rnode;
a9536f75
EK
48 struct ConfItem *aconf;
49 const char *reason;
54ac8b60
VY
50 time_t time;
51 unsigned int count;
52 uint32_t mask_hashv;
43946961
JT
53} reject_t;
54
55typedef struct _delay_data
56{
57 rb_dlink_node node;
58 rb_fde_t *F;
a9536f75
EK
59 struct ConfItem *aconf;
60 const char *reason;
43946961
JT
61} delay_t;
62
63typedef struct _throttle
64{
65 rb_dlink_node node;
66 time_t last;
67 int count;
68} throttle_t;
69
70unsigned long
71delay_exit_length(void)
72{
73 return rb_dlink_list_length(&delay_exit);
74}
54ac8b60 75
a9536f75
EK
76static void
77reject_free(reject_t *rdata)
78{
79 struct ConfItem *aconf = rdata->aconf;
80
81 if (aconf)
82 deref_conf(aconf);
83
84 rb_free(rdata);
85}
86
54ac8b60
VY
87static void
88reject_exit(void *unused)
89{
a9536f75 90 static char dynamic_reason[BUFSIZE];
54ac8b60 91 rb_dlink_node *ptr, *ptr_next;
43946961
JT
92 delay_t *ddata;
93 static const char *errbuf = "ERROR :Closing Link: (*** Banned (cache))\r\n";
55abcbb2 94
54ac8b60
VY
95 RB_DLINK_FOREACH_SAFE(ptr, ptr_next, delay_exit.head)
96 {
43946961
JT
97 ddata = ptr->data;
98
a9536f75
EK
99 *dynamic_reason = '\0';
100
101 if (ddata->aconf)
102 {
103 snprintf(dynamic_reason, BUFSIZE, form_str(ERR_YOUREBANNEDCREEP) "\r\n",
104 me.name, "*", get_user_ban_reason(ddata->aconf));
105 rb_write(ddata->F, dynamic_reason, strlen(dynamic_reason));
106
107 deref_conf(ddata->aconf);
108 }
109 else if (ddata->reason)
110 {
111 snprintf(dynamic_reason, BUFSIZE, ":%s 465 %s :%s\r\n",
112 me.name, "*", ddata->reason);
113 rb_write(ddata->F, dynamic_reason, strlen(dynamic_reason));
114 }
115
55abcbb2 116 rb_write(ddata->F, errbuf, strlen(errbuf));
43946961
JT
117 rb_close(ddata->F);
118 rb_free(ddata);
54ac8b60
VY
119 }
120
43946961
JT
121 delay_exit.head = delay_exit.tail = NULL;
122 delay_exit.length = 0;
54ac8b60
VY
123}
124
125static void
126reject_expires(void *unused)
127{
128 rb_dlink_node *ptr, *next;
0240b419 129 rb_patricia_node_t *pnode;
43946961 130 reject_t *rdata;
55abcbb2 131
54ac8b60
VY
132 RB_DLINK_FOREACH_SAFE(ptr, next, reject_list.head)
133 {
134 pnode = ptr->data;
55abcbb2 135 rdata = pnode->data;
54ac8b60
VY
136
137 if(rdata->time + ConfigFileEntry.reject_duration > rb_current_time())
138 continue;
139
140 rb_dlinkDelete(ptr, &reject_list);
a9536f75 141 reject_free(rdata);
0240b419 142 rb_patricia_remove(reject_tree, pnode);
54ac8b60
VY
143 }
144}
145
146void
147init_reject(void)
148{
0240b419 149 reject_tree = rb_new_patricia(PATRICIA_BITS);
43946961 150 throttle_tree = rb_new_patricia(PATRICIA_BITS);
54ac8b60
VY
151 rb_event_add("reject_exit", reject_exit, NULL, DELAYED_EXIT_TIME);
152 rb_event_add("reject_expires", reject_expires, NULL, 60);
43946961 153 rb_event_add("throttle_expires", throttle_expires, NULL, 10);
54ac8b60
VY
154}
155
ae09cb7d
JT
156unsigned long
157throttle_size(void)
158{
16ef24cf
JT
159 unsigned long count;
160 rb_dlink_node *ptr;
161 rb_patricia_node_t *pnode;
162 throttle_t *t;
163
164 count = 0;
165 RB_DLINK_FOREACH(ptr, throttle_list.head)
166 {
167 pnode = ptr->data;
168 t = pnode->data;
169 if (t->count > ConfigFileEntry.throttle_count)
170 count++;
171 }
172
173 return count;
ae09cb7d 174}
54ac8b60
VY
175
176void
a9536f75 177add_reject(struct Client *client_p, const char *mask1, const char *mask2, struct ConfItem *aconf, const char *reason)
54ac8b60 178{
0240b419 179 rb_patricia_node_t *pnode;
43946961 180 reject_t *rdata;
54ac8b60
VY
181 uint32_t hashv;
182
183 /* Reject is disabled */
43946961 184 if(ConfigFileEntry.reject_after_count == 0 || ConfigFileEntry.reject_duration == 0)
54ac8b60
VY
185 return;
186
187 hashv = 0;
188 if (mask1 != NULL)
43946961 189 hashv ^= fnv_hash_upper((const unsigned char *)mask1, 32);
54ac8b60 190 if (mask2 != NULL)
43946961 191 hashv ^= fnv_hash_upper((const unsigned char *)mask2, 32);
54ac8b60 192
0240b419 193 if((pnode = rb_match_ip(reject_tree, (struct sockaddr *)&client_p->localClient->ip)) != NULL)
54ac8b60
VY
194 {
195 rdata = pnode->data;
196 rdata->time = rb_current_time();
197 rdata->count++;
198 }
199 else
200 {
201 int bitlen = 32;
43946961 202 if(GET_SS_FAMILY(&client_p->localClient->ip) == AF_INET6)
54ac8b60 203 bitlen = 128;
54ac8b60 204 pnode = make_and_lookup_ip(reject_tree, (struct sockaddr *)&client_p->localClient->ip, bitlen);
43946961 205 pnode->data = rdata = rb_malloc(sizeof(reject_t));
54ac8b60
VY
206 rb_dlinkAddTail(pnode, &rdata->rnode, &reject_list);
207 rdata->time = rb_current_time();
208 rdata->count = 1;
a9536f75
EK
209 rdata->aconf = NULL;
210 rdata->reason = NULL;
54ac8b60
VY
211 }
212 rdata->mask_hashv = hashv;
a9536f75
EK
213
214 if (aconf != NULL && aconf != rdata->aconf && (aconf->status & CONF_KILL) && aconf->passwd)
215 {
216 if (rdata->aconf != NULL)
217 deref_conf(rdata->aconf);
218 aconf->clients++;
219 rdata->aconf = aconf;
220 }
221 else if (reason != NULL)
222 {
223 if (rdata->aconf != NULL)
224 deref_conf(rdata->aconf);
225 rdata->aconf = NULL;
226 rdata->reason = reason;
227 }
54ac8b60
VY
228}
229
230int
43946961 231check_reject(rb_fde_t *F, struct sockaddr *addr)
54ac8b60 232{
0240b419 233 rb_patricia_node_t *pnode;
43946961
JT
234 reject_t *rdata;
235 delay_t *ddata;
6cd12661 236
54ac8b60 237 /* Reject is disabled */
6cd12661 238 if (ConfigFileEntry.reject_after_count == 0 || ConfigFileEntry.reject_duration == 0)
54ac8b60 239 return 0;
55abcbb2 240
43946961 241 pnode = rb_match_ip(reject_tree, addr);
6cd12661
EK
242 if (pnode == NULL)
243 return 0;
244
245 rdata = pnode->data;
246 rdata->time = rb_current_time();
247
248 if (rdata->count <= (unsigned long)ConfigFileEntry.reject_after_count)
249 return 0;
250
251 if (rdata->aconf != NULL && rdata->aconf->status & CONF_ILLEGAL)
54ac8b60 252 {
6cd12661
EK
253 rb_dlinkDelete(&rdata->rnode, &reject_list);
254 reject_free(rdata);
255 rb_patricia_remove(reject_tree, pnode);
256 return 0;
257 }
54ac8b60 258
6cd12661
EK
259 ddata = rb_malloc(sizeof(delay_t));
260 ServerStats.is_rej++;
261 rb_setselect(F, RB_SELECT_WRITE | RB_SELECT_READ, NULL, NULL);
262 if (rdata->aconf)
263 {
264 ddata->aconf = rdata->aconf;
265 ddata->aconf->clients++;
266 ddata->reason = NULL;
55abcbb2 267 }
6cd12661
EK
268 else if (rdata->reason)
269 {
270 ddata->reason = rdata->reason;
271 ddata->aconf = NULL;
272 }
273 else
274 {
275 ddata->aconf = NULL;
276 ddata->reason = NULL;
277 }
278 ddata->F = F;
279 rb_dlinkAdd(ddata, &ddata->node, &delay_exit);
280 return 1;
54ac8b60
VY
281}
282
83235e9e
JT
283int
284is_reject_ip(struct sockaddr *addr)
285{
286 rb_patricia_node_t *pnode;
287 reject_t *rdata;
288 int duration;
289
290 /* Reject is disabled */
291 if(ConfigFileEntry.reject_after_count == 0 || ConfigFileEntry.reject_duration == 0)
292 return 0;
55abcbb2 293
83235e9e
JT
294 pnode = rb_match_ip(reject_tree, addr);
295 if(pnode != NULL)
296 {
297 rdata = pnode->data;
298
299 if(rdata->count > (unsigned long)ConfigFileEntry.reject_after_count)
300 {
301 duration = rdata->time + ConfigFileEntry.reject_duration - rb_current_time();
302 return duration > 0 ? duration : 1;
303 }
55abcbb2 304 }
83235e9e
JT
305 return 0;
306}
307
55abcbb2 308void
54ac8b60
VY
309flush_reject(void)
310{
311 rb_dlink_node *ptr, *next;
0240b419 312 rb_patricia_node_t *pnode;
43946961 313 reject_t *rdata;
55abcbb2 314
54ac8b60
VY
315 RB_DLINK_FOREACH_SAFE(ptr, next, reject_list.head)
316 {
317 pnode = ptr->data;
318 rdata = pnode->data;
319 rb_dlinkDelete(ptr, &reject_list);
a9536f75 320 reject_free(rdata);
0240b419 321 rb_patricia_remove(reject_tree, pnode);
54ac8b60
VY
322 }
323}
324
55abcbb2 325int
54ac8b60
VY
326remove_reject_ip(const char *ip)
327{
0240b419 328 rb_patricia_node_t *pnode;
55abcbb2 329
54ac8b60 330 /* Reject is disabled */
43946961 331 if(ConfigFileEntry.reject_after_count == 0 || ConfigFileEntry.reject_duration == 0)
54ac8b60
VY
332 return -1;
333
0240b419 334 if((pnode = rb_match_string(reject_tree, ip)) != NULL)
54ac8b60 335 {
43946961 336 reject_t *rdata = pnode->data;
54ac8b60 337 rb_dlinkDelete(&rdata->rnode, &reject_list);
a9536f75 338 reject_free(rdata);
0240b419 339 rb_patricia_remove(reject_tree, pnode);
54ac8b60
VY
340 return 1;
341 }
342 return 0;
343}
344
345int
346remove_reject_mask(const char *mask1, const char *mask2)
347{
348 rb_dlink_node *ptr, *next;
0240b419 349 rb_patricia_node_t *pnode;
43946961 350 reject_t *rdata;
54ac8b60
VY
351 uint32_t hashv;
352 int n = 0;
55abcbb2 353
54ac8b60
VY
354 hashv = 0;
355 if (mask1 != NULL)
43946961 356 hashv ^= fnv_hash_upper((const unsigned char *)mask1, 32);
54ac8b60 357 if (mask2 != NULL)
43946961 358 hashv ^= fnv_hash_upper((const unsigned char *)mask2, 32);
54ac8b60
VY
359 RB_DLINK_FOREACH_SAFE(ptr, next, reject_list.head)
360 {
361 pnode = ptr->data;
362 rdata = pnode->data;
363 if (rdata->mask_hashv == hashv)
364 {
365 rb_dlinkDelete(ptr, &reject_list);
a9536f75 366 reject_free(rdata);
0240b419 367 rb_patricia_remove(reject_tree, pnode);
54ac8b60
VY
368 n++;
369 }
370 }
371 return n;
372}
373
54ac8b60 374int
43946961 375throttle_add(struct sockaddr *addr)
54ac8b60 376{
43946961 377 throttle_t *t;
0240b419 378 rb_patricia_node_t *pnode;
54ac8b60 379
43946961 380 if((pnode = rb_match_ip(throttle_tree, addr)) != NULL)
54ac8b60 381 {
43946961
JT
382 t = pnode->data;
383
384 if(t->count > ConfigFileEntry.throttle_count)
ae09cb7d
JT
385 {
386 ServerStats.is_thr++;
387 return 1;
388 }
43946961
JT
389 /* Stop penalizing them after they've been throttled */
390 t->last = rb_current_time();
391 t->count++;
392
393 } else {
54ac8b60 394 int bitlen = 32;
43946961 395 if(GET_SS_FAMILY(addr) == AF_INET6)
54ac8b60 396 bitlen = 128;
55abcbb2 397 t = rb_malloc(sizeof(throttle_t));
43946961
JT
398 t->last = rb_current_time();
399 t->count = 1;
400 pnode = make_and_lookup_ip(throttle_tree, addr, bitlen);
401 pnode->data = t;
55abcbb2
KB
402 rb_dlinkAdd(pnode, &t->node, &throttle_list);
403 }
54ac8b60
VY
404 return 0;
405}
406
83235e9e
JT
407int
408is_throttle_ip(struct sockaddr *addr)
409{
410 throttle_t *t;
411 rb_patricia_node_t *pnode;
412 int duration;
413
414 if((pnode = rb_match_ip(throttle_tree, addr)) != NULL)
415 {
416 t = pnode->data;
417 if(t->count > ConfigFileEntry.throttle_count)
418 {
419 duration = t->last + ConfigFileEntry.throttle_duration - rb_current_time();
420 return duration > 0 ? duration : 1;
421 }
422 }
423 return 0;
424}
425
55abcbb2 426void
995f300e
JT
427flush_throttle(void)
428{
429 rb_dlink_node *ptr, *next;
430 rb_patricia_node_t *pnode;
431 throttle_t *t;
55abcbb2 432
995f300e
JT
433 RB_DLINK_FOREACH_SAFE(ptr, next, throttle_list.head)
434 {
435 pnode = ptr->data;
55abcbb2 436 t = pnode->data;
995f300e
JT
437
438 rb_dlinkDelete(ptr, &throttle_list);
439 rb_free(t);
440 rb_patricia_remove(throttle_tree, pnode);
441 }
442}
443
43946961
JT
444static void
445throttle_expires(void *unused)
54ac8b60 446{
43946961 447 rb_dlink_node *ptr, *next;
0240b419 448 rb_patricia_node_t *pnode;
43946961 449 throttle_t *t;
55abcbb2 450
43946961 451 RB_DLINK_FOREACH_SAFE(ptr, next, throttle_list.head)
54ac8b60 452 {
43946961 453 pnode = ptr->data;
55abcbb2 454 t = pnode->data;
43946961
JT
455
456 if(t->last + ConfigFileEntry.throttle_duration > rb_current_time())
457 continue;
458
459 rb_dlinkDelete(ptr, &throttle_list);
460 rb_free(t);
461 rb_patricia_remove(throttle_tree, pnode);
54ac8b60 462 }
54ac8b60 463}
43946961 464