]> jfr.im git - solanum.git/blame - ircd/reject.c
ircd/listener: return a fatal TLS alert for early rejected TLS clients
[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;
642c73dd 61 bool ssl;
43946961
JT
62} delay_t;
63
64typedef struct _throttle
65{
66 rb_dlink_node node;
67 time_t last;
68 int count;
69} throttle_t;
70
71unsigned long
72delay_exit_length(void)
73{
74 return rb_dlink_list_length(&delay_exit);
75}
54ac8b60 76
a9536f75
EK
77static void
78reject_free(reject_t *rdata)
79{
80 struct ConfItem *aconf = rdata->aconf;
81
82 if (aconf)
83 deref_conf(aconf);
84
85 rb_free(rdata);
86}
87
54ac8b60
VY
88static void
89reject_exit(void *unused)
90{
a9536f75 91 static char dynamic_reason[BUFSIZE];
54ac8b60 92 rb_dlink_node *ptr, *ptr_next;
43946961
JT
93 delay_t *ddata;
94 static const char *errbuf = "ERROR :Closing Link: (*** Banned (cache))\r\n";
55abcbb2 95
642c73dd
AJ
96 static const unsigned char ssldeniederrcode[] = {
97 // SSLv3.0 Fatal Alert: Access Denied
98 0x15, 0x03, 0x00, 0x00, 0x02, 0x02, 0x31
99 };
100
54ac8b60
VY
101 RB_DLINK_FOREACH_SAFE(ptr, ptr_next, delay_exit.head)
102 {
43946961
JT
103 ddata = ptr->data;
104
642c73dd 105 if (ddata->ssl)
a9536f75 106 {
642c73dd 107 rb_write(ddata->F, ssldeniederrcode, sizeof(ssldeniederrcode));
a9536f75 108 }
642c73dd 109 else
a9536f75 110 {
642c73dd
AJ
111 *dynamic_reason = '\0';
112
113 if (ddata->aconf)
114 snprintf(dynamic_reason, sizeof dynamic_reason, form_str(ERR_YOUREBANNEDCREEP) "\r\n",
115 me.name, "*", get_user_ban_reason(ddata->aconf));
116 else if (ddata->reason)
117 snprintf(dynamic_reason, sizeof dynamic_reason, ":%s 465 %s :%s\r\n",
118 me.name, "*", ddata->reason);
119
120 if (*dynamic_reason)
121 rb_write(ddata->F, dynamic_reason, strlen(dynamic_reason));
122
123 rb_write(ddata->F, errbuf, strlen(errbuf));
a9536f75
EK
124 }
125
642c73dd
AJ
126 if (ddata->aconf)
127 deref_conf(ddata->aconf);
128
43946961
JT
129 rb_close(ddata->F);
130 rb_free(ddata);
54ac8b60
VY
131 }
132
43946961
JT
133 delay_exit.head = delay_exit.tail = NULL;
134 delay_exit.length = 0;
54ac8b60
VY
135}
136
137static void
138reject_expires(void *unused)
139{
140 rb_dlink_node *ptr, *next;
0240b419 141 rb_patricia_node_t *pnode;
43946961 142 reject_t *rdata;
55abcbb2 143
54ac8b60
VY
144 RB_DLINK_FOREACH_SAFE(ptr, next, reject_list.head)
145 {
146 pnode = ptr->data;
55abcbb2 147 rdata = pnode->data;
54ac8b60
VY
148
149 if(rdata->time + ConfigFileEntry.reject_duration > rb_current_time())
150 continue;
151
152 rb_dlinkDelete(ptr, &reject_list);
a9536f75 153 reject_free(rdata);
0240b419 154 rb_patricia_remove(reject_tree, pnode);
54ac8b60
VY
155 }
156}
157
158void
159init_reject(void)
160{
0240b419 161 reject_tree = rb_new_patricia(PATRICIA_BITS);
43946961 162 throttle_tree = rb_new_patricia(PATRICIA_BITS);
54ac8b60
VY
163 rb_event_add("reject_exit", reject_exit, NULL, DELAYED_EXIT_TIME);
164 rb_event_add("reject_expires", reject_expires, NULL, 60);
43946961 165 rb_event_add("throttle_expires", throttle_expires, NULL, 10);
54ac8b60
VY
166}
167
ae09cb7d
JT
168unsigned long
169throttle_size(void)
170{
16ef24cf
JT
171 unsigned long count;
172 rb_dlink_node *ptr;
173 rb_patricia_node_t *pnode;
174 throttle_t *t;
175
176 count = 0;
177 RB_DLINK_FOREACH(ptr, throttle_list.head)
178 {
179 pnode = ptr->data;
180 t = pnode->data;
181 if (t->count > ConfigFileEntry.throttle_count)
182 count++;
183 }
184
185 return count;
ae09cb7d 186}
54ac8b60
VY
187
188void
a9536f75 189add_reject(struct Client *client_p, const char *mask1, const char *mask2, struct ConfItem *aconf, const char *reason)
54ac8b60 190{
0240b419 191 rb_patricia_node_t *pnode;
43946961 192 reject_t *rdata;
54ac8b60
VY
193 uint32_t hashv;
194
195 /* Reject is disabled */
43946961 196 if(ConfigFileEntry.reject_after_count == 0 || ConfigFileEntry.reject_duration == 0)
54ac8b60
VY
197 return;
198
199 hashv = 0;
200 if (mask1 != NULL)
43946961 201 hashv ^= fnv_hash_upper((const unsigned char *)mask1, 32);
54ac8b60 202 if (mask2 != NULL)
43946961 203 hashv ^= fnv_hash_upper((const unsigned char *)mask2, 32);
54ac8b60 204
0240b419 205 if((pnode = rb_match_ip(reject_tree, (struct sockaddr *)&client_p->localClient->ip)) != NULL)
54ac8b60
VY
206 {
207 rdata = pnode->data;
208 rdata->time = rb_current_time();
209 rdata->count++;
210 }
211 else
212 {
213 int bitlen = 32;
43946961 214 if(GET_SS_FAMILY(&client_p->localClient->ip) == AF_INET6)
54ac8b60 215 bitlen = 128;
54ac8b60 216 pnode = make_and_lookup_ip(reject_tree, (struct sockaddr *)&client_p->localClient->ip, bitlen);
43946961 217 pnode->data = rdata = rb_malloc(sizeof(reject_t));
54ac8b60
VY
218 rb_dlinkAddTail(pnode, &rdata->rnode, &reject_list);
219 rdata->time = rb_current_time();
220 rdata->count = 1;
a9536f75
EK
221 rdata->aconf = NULL;
222 rdata->reason = NULL;
54ac8b60
VY
223 }
224 rdata->mask_hashv = hashv;
a9536f75
EK
225
226 if (aconf != NULL && aconf != rdata->aconf && (aconf->status & CONF_KILL) && aconf->passwd)
227 {
228 if (rdata->aconf != NULL)
229 deref_conf(rdata->aconf);
230 aconf->clients++;
231 rdata->aconf = aconf;
232 }
233 else if (reason != NULL)
234 {
235 if (rdata->aconf != NULL)
236 deref_conf(rdata->aconf);
237 rdata->aconf = NULL;
238 rdata->reason = reason;
239 }
54ac8b60
VY
240}
241
242int
642c73dd 243check_reject(rb_fde_t *F, struct sockaddr *addr, bool ssl)
54ac8b60 244{
0240b419 245 rb_patricia_node_t *pnode;
43946961
JT
246 reject_t *rdata;
247 delay_t *ddata;
6cd12661 248
54ac8b60 249 /* Reject is disabled */
6cd12661 250 if (ConfigFileEntry.reject_after_count == 0 || ConfigFileEntry.reject_duration == 0)
54ac8b60 251 return 0;
55abcbb2 252
43946961 253 pnode = rb_match_ip(reject_tree, addr);
6cd12661
EK
254 if (pnode == NULL)
255 return 0;
256
257 rdata = pnode->data;
258 rdata->time = rb_current_time();
259
260 if (rdata->count <= (unsigned long)ConfigFileEntry.reject_after_count)
261 return 0;
262
263 if (rdata->aconf != NULL && rdata->aconf->status & CONF_ILLEGAL)
54ac8b60 264 {
6cd12661
EK
265 rb_dlinkDelete(&rdata->rnode, &reject_list);
266 reject_free(rdata);
267 rb_patricia_remove(reject_tree, pnode);
268 return 0;
269 }
54ac8b60 270
6cd12661
EK
271 ddata = rb_malloc(sizeof(delay_t));
272 ServerStats.is_rej++;
273 rb_setselect(F, RB_SELECT_WRITE | RB_SELECT_READ, NULL, NULL);
274 if (rdata->aconf)
275 {
276 ddata->aconf = rdata->aconf;
277 ddata->aconf->clients++;
278 ddata->reason = NULL;
55abcbb2 279 }
6cd12661
EK
280 else if (rdata->reason)
281 {
282 ddata->reason = rdata->reason;
283 ddata->aconf = NULL;
284 }
285 else
286 {
287 ddata->aconf = NULL;
288 ddata->reason = NULL;
289 }
290 ddata->F = F;
642c73dd 291 ddata->ssl = ssl;
6cd12661
EK
292 rb_dlinkAdd(ddata, &ddata->node, &delay_exit);
293 return 1;
54ac8b60
VY
294}
295
83235e9e
JT
296int
297is_reject_ip(struct sockaddr *addr)
298{
299 rb_patricia_node_t *pnode;
300 reject_t *rdata;
301 int duration;
302
303 /* Reject is disabled */
304 if(ConfigFileEntry.reject_after_count == 0 || ConfigFileEntry.reject_duration == 0)
305 return 0;
55abcbb2 306
83235e9e
JT
307 pnode = rb_match_ip(reject_tree, addr);
308 if(pnode != NULL)
309 {
310 rdata = pnode->data;
311
312 if(rdata->count > (unsigned long)ConfigFileEntry.reject_after_count)
313 {
314 duration = rdata->time + ConfigFileEntry.reject_duration - rb_current_time();
315 return duration > 0 ? duration : 1;
316 }
55abcbb2 317 }
83235e9e
JT
318 return 0;
319}
320
55abcbb2 321void
54ac8b60
VY
322flush_reject(void)
323{
324 rb_dlink_node *ptr, *next;
0240b419 325 rb_patricia_node_t *pnode;
43946961 326 reject_t *rdata;
55abcbb2 327
54ac8b60
VY
328 RB_DLINK_FOREACH_SAFE(ptr, next, reject_list.head)
329 {
330 pnode = ptr->data;
331 rdata = pnode->data;
332 rb_dlinkDelete(ptr, &reject_list);
a9536f75 333 reject_free(rdata);
0240b419 334 rb_patricia_remove(reject_tree, pnode);
54ac8b60
VY
335 }
336}
337
55abcbb2 338int
54ac8b60
VY
339remove_reject_ip(const char *ip)
340{
0240b419 341 rb_patricia_node_t *pnode;
55abcbb2 342
54ac8b60 343 /* Reject is disabled */
43946961 344 if(ConfigFileEntry.reject_after_count == 0 || ConfigFileEntry.reject_duration == 0)
54ac8b60
VY
345 return -1;
346
0240b419 347 if((pnode = rb_match_string(reject_tree, ip)) != NULL)
54ac8b60 348 {
43946961 349 reject_t *rdata = pnode->data;
54ac8b60 350 rb_dlinkDelete(&rdata->rnode, &reject_list);
a9536f75 351 reject_free(rdata);
0240b419 352 rb_patricia_remove(reject_tree, pnode);
54ac8b60
VY
353 return 1;
354 }
355 return 0;
356}
357
358int
359remove_reject_mask(const char *mask1, const char *mask2)
360{
361 rb_dlink_node *ptr, *next;
0240b419 362 rb_patricia_node_t *pnode;
43946961 363 reject_t *rdata;
54ac8b60
VY
364 uint32_t hashv;
365 int n = 0;
55abcbb2 366
54ac8b60
VY
367 hashv = 0;
368 if (mask1 != NULL)
43946961 369 hashv ^= fnv_hash_upper((const unsigned char *)mask1, 32);
54ac8b60 370 if (mask2 != NULL)
43946961 371 hashv ^= fnv_hash_upper((const unsigned char *)mask2, 32);
54ac8b60
VY
372 RB_DLINK_FOREACH_SAFE(ptr, next, reject_list.head)
373 {
374 pnode = ptr->data;
375 rdata = pnode->data;
376 if (rdata->mask_hashv == hashv)
377 {
378 rb_dlinkDelete(ptr, &reject_list);
a9536f75 379 reject_free(rdata);
0240b419 380 rb_patricia_remove(reject_tree, pnode);
54ac8b60
VY
381 n++;
382 }
383 }
384 return n;
385}
386
54ac8b60 387int
43946961 388throttle_add(struct sockaddr *addr)
54ac8b60 389{
43946961 390 throttle_t *t;
0240b419 391 rb_patricia_node_t *pnode;
54ac8b60 392
43946961 393 if((pnode = rb_match_ip(throttle_tree, addr)) != NULL)
54ac8b60 394 {
43946961
JT
395 t = pnode->data;
396
397 if(t->count > ConfigFileEntry.throttle_count)
ae09cb7d
JT
398 {
399 ServerStats.is_thr++;
400 return 1;
401 }
43946961
JT
402 /* Stop penalizing them after they've been throttled */
403 t->last = rb_current_time();
404 t->count++;
405
406 } else {
54ac8b60 407 int bitlen = 32;
43946961 408 if(GET_SS_FAMILY(addr) == AF_INET6)
54ac8b60 409 bitlen = 128;
55abcbb2 410 t = rb_malloc(sizeof(throttle_t));
43946961
JT
411 t->last = rb_current_time();
412 t->count = 1;
413 pnode = make_and_lookup_ip(throttle_tree, addr, bitlen);
414 pnode->data = t;
55abcbb2
KB
415 rb_dlinkAdd(pnode, &t->node, &throttle_list);
416 }
54ac8b60
VY
417 return 0;
418}
419
83235e9e
JT
420int
421is_throttle_ip(struct sockaddr *addr)
422{
423 throttle_t *t;
424 rb_patricia_node_t *pnode;
425 int duration;
426
427 if((pnode = rb_match_ip(throttle_tree, addr)) != NULL)
428 {
429 t = pnode->data;
430 if(t->count > ConfigFileEntry.throttle_count)
431 {
432 duration = t->last + ConfigFileEntry.throttle_duration - rb_current_time();
433 return duration > 0 ? duration : 1;
434 }
435 }
436 return 0;
437}
438
55abcbb2 439void
995f300e
JT
440flush_throttle(void)
441{
442 rb_dlink_node *ptr, *next;
443 rb_patricia_node_t *pnode;
444 throttle_t *t;
55abcbb2 445
995f300e
JT
446 RB_DLINK_FOREACH_SAFE(ptr, next, throttle_list.head)
447 {
448 pnode = ptr->data;
55abcbb2 449 t = pnode->data;
995f300e
JT
450
451 rb_dlinkDelete(ptr, &throttle_list);
452 rb_free(t);
453 rb_patricia_remove(throttle_tree, pnode);
454 }
455}
456
43946961
JT
457static void
458throttle_expires(void *unused)
54ac8b60 459{
43946961 460 rb_dlink_node *ptr, *next;
0240b419 461 rb_patricia_node_t *pnode;
43946961 462 throttle_t *t;
55abcbb2 463
43946961 464 RB_DLINK_FOREACH_SAFE(ptr, next, throttle_list.head)
54ac8b60 465 {
43946961 466 pnode = ptr->data;
55abcbb2 467 t = pnode->data;
43946961
JT
468
469 if(t->last + ConfigFileEntry.throttle_duration > rb_current_time())
470 continue;
471
472 rb_dlinkDelete(ptr, &throttle_list);
473 rb_free(t);
474 rb_patricia_remove(throttle_tree, pnode);
54ac8b60 475 }
54ac8b60 476}
43946961 477