]> jfr.im git - solanum.git/blame - modules/m_xline.c
msg: remove last vestiges of the fakelag system. charybdis has never supported fakelag.
[solanum.git] / modules / m_xline.c
CommitLineData
212380e3 1/* modules/m_xline.c
55abcbb2 2 *
212380e3
AC
3 * Copyright (C) 2002-2003 Lee Hardy <lee@leeh.co.uk>
4 * Copyright (C) 2002-2005 ircd-ratbox development team
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * 1.Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * 2.Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3.The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 *
8bbeb278 30 * $Id$
212380e3
AC
31 */
32
33#include "stdinc.h"
212380e3
AC
34#include "send.h"
35#include "channel.h"
36#include "client.h"
37#include "common.h"
38#include "config.h"
39#include "class.h"
40#include "ircd.h"
41#include "numeric.h"
4016731b 42#include "logger.h"
212380e3
AC
43#include "s_serv.h"
44#include "whowas.h"
4562c604 45#include "match.h"
212380e3
AC
46#include "hash.h"
47#include "msg.h"
48#include "parse.h"
49#include "modules.h"
50#include "s_conf.h"
51#include "s_newconf.h"
35f6f850 52#include "reject.h"
8bbeb278 53#include "bandbi.h"
27f616dd 54#include "operhash.h"
212380e3 55
428ca87b
AC
56static int mo_xline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[]);
57static int ms_xline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[]);
58static int me_xline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[]);
59static int mo_unxline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc,
8bbeb278 60 const char *parv[]);
428ca87b 61static int ms_unxline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc,
8bbeb278 62 const char *parv[]);
428ca87b 63static int me_unxline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc,
8bbeb278 64 const char *parv[]);
212380e3
AC
65
66struct Message xline_msgtab = {
7baa37a9 67 "XLINE", 0, 0, 0, 0,
212380e3
AC
68 {mg_unreg, mg_not_oper, {ms_xline, 5}, {ms_xline, 5}, {me_xline, 5}, {mo_xline, 3}}
69};
8bbeb278 70
212380e3 71struct Message unxline_msgtab = {
7baa37a9 72 "UNXLINE", 0, 0, 0, 0,
212380e3
AC
73 {mg_unreg, mg_not_oper, {ms_unxline, 3}, {ms_unxline, 3}, {me_unxline, 2}, {mo_unxline, 2}}
74};
75
8bbeb278
AC
76mapi_clist_av1 xline_clist[] = { &xline_msgtab, &unxline_msgtab, NULL };
77
78DECLARE_MODULE_AV1(xline, NULL, NULL, xline_clist, NULL, NULL, "$Revision$");
212380e3 79
8bbeb278
AC
80static int valid_xline(struct Client *, const char *, const char *);
81static void apply_xline(struct Client *client_p, const char *name,
3cbbfb25 82 const char *reason, int temp_time, int propagated);
212380e3 83static void propagate_xline(struct Client *source_p, const char *target,
8bbeb278 84 int temp_time, const char *name, const char *type, const char *reason);
212380e3 85static void cluster_xline(struct Client *source_p, int temp_time,
8bbeb278 86 const char *name, const char *reason);
212380e3
AC
87
88static void handle_remote_xline(struct Client *source_p, int temp_time,
89 const char *name, const char *reason);
90static void handle_remote_unxline(struct Client *source_p, const char *name);
91
3cbbfb25
JT
92static void remove_xline(struct Client *source_p, const char *name,
93 int propagated);
212380e3
AC
94
95
96/* m_xline()
97 *
98 * parv[1] - thing to xline
99 * parv[2] - optional type/reason
100 * parv[3] - reason
101 */
102static int
428ca87b 103mo_xline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
212380e3
AC
104{
105 struct ConfItem *aconf;
106 const char *name;
107 const char *reason;
108 const char *target_server = NULL;
109 int temp_time;
110 int loc = 1;
3cbbfb25 111 int propagated = ConfigFileEntry.use_propagated_bans;
212380e3
AC
112
113 if(!IsOperXline(source_p))
114 {
8bbeb278 115 sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "xline");
212380e3
AC
116 return 0;
117 }
118
119 if((temp_time = valid_temp_time(parv[loc])) >= 0)
120 loc++;
121 /* we just set temp_time to -1! */
122 else
123 temp_time = 0;
124
125 name = parv[loc];
126 loc++;
127
128 /* XLINE <gecos> ON <server> :<reason> */
8bbeb278 129 if(parc >= loc + 2 && !irccmp(parv[loc], "ON"))
212380e3
AC
130 {
131 if(!IsOperRemoteBan(source_p))
132 {
133 sendto_one(source_p, form_str(ERR_NOPRIVS),
8bbeb278 134 me.name, source_p->name, "remoteban");
212380e3
AC
135 return 0;
136 }
137
8bbeb278 138 target_server = parv[loc + 1];
212380e3
AC
139 loc += 2;
140 }
141
142 if(parc <= loc || EmptyString(parv[loc]))
143 {
144 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
8bbeb278 145 me.name, source_p->name, "XLINE");
212380e3
AC
146 return 0;
147 }
148
149 reason = parv[loc];
150
151 if(target_server != NULL)
152 {
8bbeb278 153 propagate_xline(source_p, target_server, temp_time, name, "2", reason);
212380e3
AC
154
155 if(!match(target_server, me.name))
156 return 0;
3cbbfb25
JT
157
158 /* Set as local-only. */
159 propagated = 0;
212380e3 160 }
3cbbfb25 161 else if(!propagated && rb_dlink_list_length(&cluster_conf_list) > 0)
8bbeb278 162 cluster_xline(source_p, temp_time, name, reason);
212380e3 163
8bbeb278 164 if((aconf = find_xline_mask(name)) != NULL)
212380e3
AC
165 {
166 sendto_one(source_p, ":%s NOTICE %s :[%s] already X-Lined by [%s] - %s",
23959371 167 me.name, source_p->name, name, aconf->host, aconf->passwd);
212380e3
AC
168 return 0;
169 }
170
8bbeb278 171 if(!valid_xline(source_p, name, reason))
212380e3
AC
172 return 0;
173
3cbbfb25
JT
174 if(propagated && temp_time == 0)
175 {
176 sendto_one_notice(source_p, ":Cannot set a permanent global ban");
177 return 0;
178 }
179
180 apply_xline(source_p, name, reason, temp_time, propagated);
212380e3
AC
181
182 return 0;
183}
184
185/* ms_xline()
186 *
187 * handles a remote xline
188 */
189static int
428ca87b 190ms_xline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
212380e3 191{
8bbeb278
AC
192 /* parv[0] parv[1] parv[2] parv[3] parv[4]
193 * oper target serv xline type reason
212380e3
AC
194 */
195 propagate_xline(source_p, parv[1], 0, parv[2], parv[3], parv[4]);
196
197 if(!IsPerson(source_p))
198 return 0;
199
200 /* destined for me? */
201 if(!match(parv[1], me.name))
202 return 0;
203
204 handle_remote_xline(source_p, 0, parv[2], parv[4]);
205 return 0;
206}
207
208static int
428ca87b 209me_xline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
212380e3
AC
210{
211 /* time name type :reason */
212 if(!IsPerson(source_p))
213 return 0;
214
215 handle_remote_xline(source_p, atoi(parv[1]), parv[2], parv[4]);
216 return 0;
217}
218
219static void
8bbeb278 220handle_remote_xline(struct Client *source_p, int temp_time, const char *name, const char *reason)
212380e3
AC
221{
222 struct ConfItem *aconf;
223
224 if(!find_shared_conf(source_p->username, source_p->host,
8bbeb278
AC
225 source_p->servptr->name,
226 (temp_time > 0) ? SHARED_TXLINE : SHARED_PXLINE))
212380e3
AC
227 return;
228
8bbeb278 229 if(!valid_xline(source_p, name, reason))
212380e3
AC
230 return;
231
232 /* already xlined */
0fdb2570 233 if((aconf = find_xline_mask(name)) != NULL)
212380e3 234 {
23959371 235 sendto_one_notice(source_p, ":[%s] already X-Lined by [%s] - %s", name, aconf->host,
8bbeb278 236 aconf->passwd);
212380e3
AC
237 return;
238 }
239
3cbbfb25 240 apply_xline(source_p, name, reason, temp_time, 0);
212380e3
AC
241}
242
243/* valid_xline()
244 *
8bbeb278 245 * inputs - client xlining, gecos, reason and whether to warn
212380e3
AC
246 * outputs -
247 * side effects - checks the xline for validity, erroring if needed
248 */
249static int
8bbeb278 250valid_xline(struct Client *source_p, const char *gecos, const char *reason)
212380e3
AC
251{
252 if(EmptyString(reason))
253 {
254 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
8bbeb278 255 get_id(&me, source_p), get_id(source_p, source_p), "XLINE");
cc169c94
JT
256 return 0;
257 }
258
212380e3
AC
259 if(!valid_wild_card_simple(gecos))
260 {
261 sendto_one_notice(source_p,
262 ":Please include at least %d non-wildcard "
263 "characters with the xline",
264 ConfigFileEntry.min_nonwildcard_simple);
265 return 0;
266 }
267
268 return 1;
269}
270
271void
3cbbfb25 272apply_xline(struct Client *source_p, const char *name, const char *reason, int temp_time, int propagated)
212380e3
AC
273{
274 struct ConfItem *aconf;
275
276 aconf = make_conf();
277 aconf->status = CONF_XLINE;
b52c2949 278 aconf->created = rb_current_time();
4418166c 279 aconf->host = rb_strdup(name);
8bbeb278 280 aconf->passwd = rb_strdup(reason);
23959371 281 collapse(aconf->host);
212380e3 282
27f616dd
JT
283 aconf->info.oper = operhash_add(get_oper_name(source_p));
284
3cbbfb25
JT
285 if(propagated)
286 {
287 aconf->flags |= CONF_FLAGS_MYOPER | CONF_FLAGS_TEMPORARY;
288 aconf->hold = rb_current_time() + temp_time;
289 aconf->lifetime = aconf->hold;
290
291 replace_old_ban(aconf);
292 rb_dlinkAddAlloc(aconf, &prop_bans);
293
294 sendto_realops_snomask(SNO_GENERAL, L_ALL,
295 "%s added global %d min. X-Line for [%s] [%s]",
296 get_oper_name(source_p), temp_time / 60,
297 aconf->host, reason);
298 ilog(L_KLINE, "X %s %d %s %s",
299 get_oper_name(source_p), temp_time / 60, name, reason);
300 sendto_one_notice(source_p, ":Added global %d min. X-Line [%s]",
301 temp_time / 60, aconf->host);
302 sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS,
303 ":%s BAN X * %s %lu %d %d * :%s",
304 source_p->id, aconf->host,
305 (unsigned long)aconf->created,
306 (int)(aconf->hold - aconf->created),
307 (int)(aconf->lifetime - aconf->created),
308 reason);
309 }
310 else if(temp_time > 0)
212380e3 311 {
8bbeb278 312 aconf->hold = rb_current_time() + temp_time;
212380e3 313
8bbeb278
AC
314 sendto_realops_snomask(SNO_GENERAL, L_ALL,
315 "%s added temporary %d min. X-Line for [%s] [%s]",
316 get_oper_name(source_p), temp_time / 60,
23959371 317 aconf->host, reason);
8bbeb278
AC
318 ilog(L_KLINE, "X %s %d %s %s",
319 get_oper_name(source_p), temp_time / 60, name, reason);
320 sendto_one_notice(source_p, ":Added temporary %d min. X-Line [%s]",
23959371 321 temp_time / 60, aconf->host);
8bbeb278
AC
322 }
323 else
212380e3 324 {
8bbeb278 325 sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s added X-Line for [%s] [%s]",
23959371 326 get_oper_name(source_p), aconf->host, aconf->passwd);
8bbeb278 327 sendto_one_notice(source_p, ":Added X-Line for [%s] [%s]",
23959371 328 aconf->host, aconf->passwd);
8bbeb278 329
23959371 330 bandb_add(BANDB_XLINE, source_p, aconf->host, NULL, aconf->passwd, NULL, 0);
f36d4fdd 331 ilog(L_KLINE, "X %s 0 %s %s", get_oper_name(source_p), name, aconf->passwd);
212380e3 332 }
8bbeb278
AC
333
334 rb_dlinkAddAlloc(aconf, &xline_conf_list);
335 check_xlines();
212380e3
AC
336}
337
8bbeb278 338static void
212380e3 339propagate_xline(struct Client *source_p, const char *target,
8bbeb278 340 int temp_time, const char *name, const char *type, const char *reason)
212380e3
AC
341{
342 if(!temp_time)
343 {
344 sendto_match_servs(source_p, target, CAP_CLUSTER, NOCAPS,
8bbeb278 345 "XLINE %s %s %s :%s", target, name, type, reason);
212380e3 346 sendto_match_servs(source_p, target, CAP_ENCAP, CAP_CLUSTER,
8bbeb278 347 "ENCAP %s XLINE %d %s 2 :%s", target, temp_time, name, reason);
212380e3
AC
348 }
349 else
350 sendto_match_servs(source_p, target, CAP_ENCAP, NOCAPS,
8bbeb278
AC
351 "ENCAP %s XLINE %d %s %s :%s",
352 target, temp_time, name, type, reason);
212380e3 353}
8bbeb278 354
212380e3 355static void
8bbeb278 356cluster_xline(struct Client *source_p, int temp_time, const char *name, const char *reason)
212380e3
AC
357{
358 struct remote_conf *shared_p;
5b96d9a6 359 rb_dlink_node *ptr;
212380e3 360
5b96d9a6 361 RB_DLINK_FOREACH(ptr, cluster_conf_list.head)
212380e3
AC
362 {
363 shared_p = ptr->data;
364
365 /* old protocol cant handle temps, and we dont really want
366 * to convert them to perm.. --fl
367 */
368 if(!temp_time)
369 {
370 if(!(shared_p->flags & SHARED_PXLINE))
371 continue;
372
373 sendto_match_servs(source_p, shared_p->server, CAP_CLUSTER, NOCAPS,
8bbeb278 374 "XLINE %s %s 2 :%s", shared_p->server, name, reason);
212380e3 375 sendto_match_servs(source_p, shared_p->server, CAP_ENCAP, CAP_CLUSTER,
8bbeb278
AC
376 "ENCAP %s XLINE 0 %s 2 :%s",
377 shared_p->server, name, reason);
212380e3
AC
378 }
379 else if(shared_p->flags & SHARED_TXLINE)
380 sendto_match_servs(source_p, shared_p->server, CAP_ENCAP, NOCAPS,
8bbeb278
AC
381 "ENCAP %s XLINE %d %s 2 :%s",
382 shared_p->server, temp_time, name, reason);
212380e3
AC
383 }
384}
385
386/* mo_unxline()
387 *
388 * parv[1] - thing to unxline
389 */
390static int
428ca87b 391mo_unxline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
212380e3 392{
3cbbfb25
JT
393 int propagated = 1;
394
212380e3
AC
395 if(!IsOperXline(source_p))
396 {
8bbeb278 397 sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "xline");
212380e3
AC
398 return 0;
399 }
400
401 if(parc == 4 && !(irccmp(parv[2], "ON")))
402 {
403 if(!IsOperRemoteBan(source_p))
404 {
405 sendto_one(source_p, form_str(ERR_NOPRIVS),
8bbeb278 406 me.name, source_p->name, "remoteban");
212380e3
AC
407 return 0;
408 }
409
8bbeb278 410 propagate_generic(source_p, "UNXLINE", parv[3], CAP_CLUSTER, "%s", parv[1]);
212380e3
AC
411
412 if(match(parv[3], me.name) == 0)
413 return 0;
3cbbfb25
JT
414
415 propagated = 0;
212380e3 416 }
3cbbfb25 417 /* cluster{} moved to remove_xline */
212380e3 418
3cbbfb25 419 remove_xline(source_p, parv[1], propagated);
212380e3
AC
420
421 return 0;
422}
423
424/* ms_unxline()
425 *
426 * handles a remote unxline
427 */
428static int
428ca87b 429ms_unxline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
212380e3 430{
8bbeb278
AC
431 /* parv[0] parv[1] parv[2]
432 * oper target server gecos
212380e3 433 */
8bbeb278 434 propagate_generic(source_p, "UNXLINE", parv[1], CAP_CLUSTER, "%s", parv[2]);
212380e3
AC
435
436 if(!match(parv[1], me.name))
437 return 0;
438
439 if(!IsPerson(source_p))
440 return 0;
441
442 handle_remote_unxline(source_p, parv[2]);
443 return 0;
444}
445
446static int
428ca87b 447me_unxline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
212380e3
AC
448{
449 /* name */
450 if(!IsPerson(source_p))
451 return 0;
452
453 handle_remote_unxline(source_p, parv[1]);
454 return 0;
455}
456
457static void
458handle_remote_unxline(struct Client *source_p, const char *name)
459{
460 if(!find_shared_conf(source_p->username, source_p->host,
8bbeb278 461 source_p->servptr->name, SHARED_UNXLINE))
212380e3
AC
462 return;
463
3cbbfb25 464 remove_xline(source_p, name, 0);
212380e3
AC
465
466 return;
467}
468
60c96e64 469static void
3cbbfb25 470remove_xline(struct Client *source_p, const char *name, int propagated)
212380e3
AC
471{
472 struct ConfItem *aconf;
5b96d9a6 473 rb_dlink_node *ptr;
483987a4 474 time_t now;
212380e3 475
5b96d9a6 476 RB_DLINK_FOREACH(ptr, xline_conf_list.head)
212380e3
AC
477 {
478 aconf = ptr->data;
479
23959371 480 if(!irccmp(aconf->host, name))
212380e3 481 {
3cbbfb25
JT
482 if(aconf->lifetime)
483 {
484 if(!propagated)
485 {
486 sendto_one_notice(source_p, ":Cannot remove global X-Line %s on specific servers", name);
487 return;
488 }
489 ptr = rb_dlinkFind(aconf, &prop_bans);
490 if(ptr == NULL)
491 return;
492 sendto_one_notice(source_p, ":X-Line for [%s] is removed", name);
493 sendto_realops_snomask(SNO_GENERAL, L_ALL,
494 "%s has removed the global X-Line for: [%s]",
495 get_oper_name(source_p), name);
496 ilog(L_KLINE, "UX %s %s", get_oper_name(source_p), name);
483987a4
JT
497 now = rb_current_time();
498 if(aconf->created < now)
499 aconf->created = now;
3cbbfb25
JT
500 else
501 aconf->created++;
502 aconf->hold = aconf->created;
503 operhash_delete(aconf->info.oper);
504 aconf->info.oper = operhash_add(get_oper_name(source_p));
505 aconf->flags |= CONF_FLAGS_MYOPER | CONF_FLAGS_TEMPORARY;
506 sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS,
507 ":%s BAN X * %s %lu %d %d * :*",
508 source_p->id, aconf->host,
509 (unsigned long)aconf->created,
510 0,
511 (int)(aconf->lifetime - aconf->created));
512 remove_reject_mask(aconf->host, NULL);
483987a4 513 deactivate_conf(aconf, ptr, now);
3cbbfb25
JT
514 return;
515 }
1b5d7c2e 516 else if(propagated && rb_dlink_list_length(&cluster_conf_list))
3cbbfb25 517 cluster_generic(source_p, "UNXLINE", SHARED_UNXLINE, CAP_CLUSTER, "%s", name);
8bbeb278 518 if(!aconf->hold)
5408b484 519 {
8bbeb278
AC
520 bandb_del(BANDB_XLINE, aconf->host, NULL);
521
522 sendto_one_notice(source_p, ":X-Line for [%s] is removed", aconf->host);
523 sendto_realops_snomask(SNO_GENERAL, L_ALL,
524 "%s has removed the X-Line for: [%s]",
525 get_oper_name(source_p), aconf->host);
526 ilog(L_KLINE, "UX %s %s", get_oper_name(source_p), aconf->host);
5408b484
JT
527 }
528 else
529 {
8bbeb278 530 sendto_one_notice(source_p, ":X-Line for [%s] is removed", name);
5408b484 531 sendto_realops_snomask(SNO_GENERAL, L_ALL,
8bbeb278
AC
532 "%s has removed the temporary X-Line for: [%s]",
533 get_oper_name(source_p), name);
534 ilog(L_KLINE, "UX %s %s", get_oper_name(source_p), name);
5408b484 535 }
8bbeb278 536
23959371 537 remove_reject_mask(aconf->host, NULL);
212380e3 538 free_conf(aconf);
555ac41f 539 rb_dlinkDestroy(ptr, &xline_conf_list);
60c96e64 540 return;
212380e3
AC
541 }
542 }
543
1b5d7c2e 544 if(propagated && rb_dlink_list_length(&cluster_conf_list))
3cbbfb25
JT
545 cluster_generic(source_p, "UNXLINE", SHARED_UNXLINE, CAP_CLUSTER, "%s", name);
546
8bbeb278 547 sendto_one_notice(source_p, ":No X-Line for %s", name);
5408b484 548
60c96e64 549 return;
212380e3 550}