Remove cruft left behind by removed stats_p_hook.
[seven-1.x.git] / modules / m_xline.c
blob17bea23e69ca23d8640a85371b94823464e803f4
1 /* modules/m_xline.c
2 *
3 * Copyright (C) 2002-2003 Lee Hardy <lee@leeh.co.uk>
4 * Copyright (C) 2002-2005 ircd-ratbox development team
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
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.
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.
31 #include "stdinc.h"
32 #include "tools.h"
33 #include "send.h"
34 #include "channel.h"
35 #include "client.h"
36 #include "common.h"
37 #include "config.h"
38 #include "class.h"
39 #include "ircd.h"
40 #include "numeric.h"
41 #include "memory.h"
42 #include "s_log.h"
43 #include "s_serv.h"
44 #include "whowas.h"
45 #include "irc_string.h"
46 #include "sprintf_irc.h"
47 #include "hash.h"
48 #include "msg.h"
49 #include "parse.h"
50 #include "modules.h"
51 #include "s_conf.h"
52 #include "s_newconf.h"
54 static int mo_xline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]);
55 static int ms_xline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]);
56 static int me_xline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]);
57 static int mo_unxline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]);
58 static int ms_unxline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]);
59 static int me_unxline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]);
61 struct Message xline_msgtab = {
62 "XLINE", 0, 0, 0, MFLG_SLOW,
63 {mg_unreg, mg_not_oper, {ms_xline, 5}, {ms_xline, 5}, {me_xline, 5}, {mo_xline, 3}}
65 struct Message unxline_msgtab = {
66 "UNXLINE", 0, 0, 0, MFLG_SLOW,
67 {mg_unreg, mg_not_oper, {ms_unxline, 3}, {ms_unxline, 3}, {me_unxline, 2}, {mo_unxline, 2}}
70 mapi_clist_av1 xline_clist[] = { &xline_msgtab, &unxline_msgtab, NULL };
71 DECLARE_MODULE_AV1(xline, NULL, NULL, xline_clist, NULL, NULL, "$Revision: 125 $");
73 static int valid_xline(struct Client *, const char *, const char *);
74 static void apply_xline(struct Client *client_p, const char *name,
75 const char *reason, int temp_time);
76 static void write_xline(struct Client *source_p, struct ConfItem *aconf);
77 static void propagate_xline(struct Client *source_p, const char *target,
78 int temp_time, const char *name,
79 const char *type, const char *reason);
80 static void cluster_xline(struct Client *source_p, int temp_time,
81 const char *name, const char *reason);
83 static void handle_remote_xline(struct Client *source_p, int temp_time,
84 const char *name, const char *reason);
85 static void handle_remote_unxline(struct Client *source_p, const char *name);
87 static int remove_temp_xline(struct Client *source_p, const char *name);
88 static void remove_xline(struct Client *source_p, const char *gecos);
91 /* m_xline()
93 * parv[1] - thing to xline
94 * parv[2] - optional type/reason
95 * parv[3] - reason
97 static int
98 mo_xline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
100 struct ConfItem *aconf;
101 const char *name;
102 const char *reason;
103 const char *target_server = NULL;
104 int temp_time;
105 int loc = 1;
107 if(!IsOperXline(source_p))
109 sendto_one(source_p, form_str(ERR_NOPRIVS),
110 me.name, source_p->name, "xline");
111 return 0;
114 if((temp_time = valid_temp_time(parv[loc])) >= 0)
115 loc++;
116 /* we just set temp_time to -1! */
117 else
118 temp_time = 0;
120 name = parv[loc];
121 loc++;
123 /* XLINE <gecos> ON <server> :<reason> */
124 if(parc >= loc+2 && !irccmp(parv[loc], "ON"))
126 if(!IsOperRemoteBan(source_p))
128 sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name,
129 "remoteban");
130 return 0;
133 target_server = parv[loc+1];
134 loc += 2;
137 if(parc <= loc || EmptyString(parv[loc]))
139 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
140 me.name, source_p->name, "XLINE");
141 return 0;
144 reason = parv[loc];
146 if(target_server != NULL)
148 propagate_xline(source_p, target_server, temp_time,
149 name, "2", reason);
151 if(!match(target_server, me.name))
152 return 0;
154 else if(dlink_list_length(&cluster_conf_list) > 0)
155 cluster_xline(source_p, temp_time, name, reason);
157 if((aconf = find_xline(name, 0)) != NULL)
159 sendto_one(source_p, ":%s NOTICE %s :[%s] already X-Lined by [%s] - %s",
160 me.name, source_p->name, parv[1], aconf->name, aconf->passwd);
161 return 0;
164 if(!valid_xline(source_p, name, reason))
165 return 0;
167 apply_xline(source_p, name, reason, temp_time);
169 return 0;
172 /* ms_xline()
174 * handles a remote xline
176 static int
177 ms_xline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
179 /* parv[0] parv[1] parv[2] parv[3] parv[4]
180 * oper target serv xline type reason
182 propagate_xline(source_p, parv[1], 0, parv[2], parv[3], parv[4]);
184 if(!IsPerson(source_p))
185 return 0;
187 /* destined for me? */
188 if(!match(parv[1], me.name))
189 return 0;
191 handle_remote_xline(source_p, 0, parv[2], parv[4]);
192 return 0;
195 static int
196 me_xline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
198 /* time name type :reason */
199 if(!IsPerson(source_p))
200 return 0;
202 handle_remote_xline(source_p, atoi(parv[1]), parv[2], parv[4]);
203 return 0;
206 static void
207 handle_remote_xline(struct Client *source_p, int temp_time,
208 const char *name, const char *reason)
210 struct ConfItem *aconf;
213 if (!find_client_shared_conf(source_p, temp_time > 0 ? SHARED_TXLINE : SHARED_PXLINE))
214 return;
215 if(!valid_xline(source_p, name, reason))
216 return;
218 /* already xlined */
219 if((aconf = find_xline(name, 0)) != NULL)
221 sendto_one(source_p, ":%s NOTICE %s :[%s] already X-Lined by [%s] - %s",
222 me.name, source_p->name, name,
223 aconf->name, aconf->passwd);
224 return;
227 apply_xline(source_p, name, reason, temp_time);
230 /* valid_xline()
232 * inputs - client xlining, gecos, reason and whether to warn
233 * outputs -
234 * side effects - checks the xline for validity, erroring if needed
236 static int
237 valid_xline(struct Client *source_p, const char *gecos,
238 const char *reason)
240 if(EmptyString(reason))
242 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
243 get_id(&me, source_p),
244 get_id(source_p, source_p), "XLINE");
245 return 0;
248 if(strchr(reason, ':') != NULL)
250 sendto_one_notice(source_p,
251 ":Invalid character ':' in comment");
252 return 0;
255 if(strchr(reason, '"'))
257 sendto_one_notice(source_p,
258 ":Invalid character '\"' in comment");
259 return 0;
262 if(!valid_wild_card_simple(gecos))
264 sendto_one_notice(source_p,
265 ":Please include at least %d non-wildcard "
266 "characters with the xline",
267 ConfigFileEntry.min_nonwildcard_simple);
268 return 0;
271 return 1;
274 void
275 apply_xline(struct Client *source_p, const char *name, const char *reason,
276 int temp_time)
278 struct ConfItem *aconf;
280 aconf = make_conf();
281 aconf->status = CONF_XLINE;
283 if(strstr(name, "\\s"))
285 char *tmp = LOCAL_COPY(name);
286 char *orig = tmp;
287 char *new = tmp;
289 while(*orig)
291 if(*orig == '\\')
293 if(*(orig + 1) == 's')
295 *new++ = ' ';
296 orig += 2;
298 /* otherwise skip that and the escaped
299 * character after it, so we dont mistake
300 * \\s as \s --fl
302 else
304 *new++ = *orig++;
305 *new++ = *orig++;
308 else
309 *new++ = *orig++;
312 *new = '\0';
313 DupString(aconf->name, tmp);
315 else
316 DupString(aconf->name, name);
318 DupString(aconf->passwd, reason);
319 collapse(aconf->name);
321 if(temp_time > 0)
323 aconf->hold = CurrentTime + temp_time;
325 sendto_realops_snomask(SNO_GENERAL, L_ALL,
326 "%s added temporary %d min. X-Line for [%s] [%s]",
327 get_oper_name(source_p), temp_time / 60,
328 aconf->name, reason);
329 ilog(L_KLINE, "X %s %d %s %s",
330 get_oper_name(source_p), temp_time / 60,
331 name, reason);
332 sendto_one_notice(source_p, ":Added temporary %d min. X-Line [%s]",
333 temp_time / 60, aconf->name);
335 else
337 write_xline(source_p, aconf);
339 sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s added X-Line for [%s] [%s]",
340 get_oper_name(source_p),
341 aconf->name, aconf->passwd);
342 sendto_one_notice(source_p, ":Added X-Line for [%s] [%s]",
343 aconf->name, aconf->passwd);
344 ilog(L_KLINE, "X %s 0 %s %s",
345 get_oper_name(source_p), name, reason);
348 dlinkAddAlloc(aconf, &xline_conf_list);
349 check_xlines();
352 /* write_xline()
354 * inputs - gecos, reason, xline type
355 * outputs - writes an xline to the config
356 * side effects -
358 static void
359 write_xline(struct Client *source_p, struct ConfItem *aconf)
361 char buffer[BUFSIZE * 2];
362 FILE *out;
363 const char *filename;
365 filename = ConfigFileEntry.xlinefile;
367 if((out = fopen(filename, "a")) == NULL)
369 sendto_realops_snomask(SNO_GENERAL, L_ALL, "*** Problem opening %s ", filename);
370 free_conf(aconf);
371 return;
374 ircsprintf(buffer, "\"%s\",\"0\",\"%s\",\"%s\",%ld\n",
375 aconf->name, aconf->passwd,
376 get_oper_name(source_p), CurrentTime);
378 if(fputs(buffer, out) == -1)
380 sendto_realops_snomask(SNO_GENERAL, L_ALL, "*** Problem writing to %s", filename);
381 free_conf(aconf);
382 fclose(out);
383 return;
386 fclose(out);
389 static void
390 propagate_xline(struct Client *source_p, const char *target,
391 int temp_time, const char *name, const char *type,
392 const char *reason)
394 if(!temp_time)
396 sendto_match_servs(source_p, target, CAP_CLUSTER, NOCAPS,
397 "XLINE %s %s %s :%s",
398 target, name, type, reason);
399 sendto_match_servs(source_p, target, CAP_ENCAP, CAP_CLUSTER,
400 "ENCAP %s XLINE %d %s 2 :%s",
401 target, temp_time, name, reason);
403 else
404 sendto_match_servs(source_p, target, CAP_ENCAP, NOCAPS,
405 "ENCAP %s XLINE %d %s %s :%s",
406 target, temp_time, name, type, reason);
409 static void
410 cluster_xline(struct Client *source_p, int temp_time, const char *name,
411 const char *reason)
413 struct remote_conf *shared_p;
414 dlink_node *ptr;
416 DLINK_FOREACH(ptr, cluster_conf_list.head)
418 shared_p = ptr->data;
420 /* old protocol cant handle temps, and we dont really want
421 * to convert them to perm.. --fl
423 if(!temp_time)
425 if(!(shared_p->flags & SHARED_PXLINE))
426 continue;
428 sendto_match_servs(source_p, shared_p->server, CAP_CLUSTER, NOCAPS,
429 "XLINE %s %s 2 :%s",
430 shared_p->server, name, reason);
431 sendto_match_servs(source_p, shared_p->server, CAP_ENCAP, CAP_CLUSTER,
432 "ENCAP %s XLINE 0 %s 2 :%s",
433 shared_p->server, name, reason);
435 else if(shared_p->flags & SHARED_TXLINE)
436 sendto_match_servs(source_p, shared_p->server, CAP_ENCAP, NOCAPS,
437 "ENCAP %s XLINE %d %s 2 :%s",
438 shared_p->server, temp_time, name, reason);
442 /* mo_unxline()
444 * parv[1] - thing to unxline
446 static int
447 mo_unxline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
449 if(!IsOperXline(source_p))
451 sendto_one(source_p, form_str(ERR_NOPRIVS),
452 me.name, source_p->name, "xline");
453 return 0;
456 if(parc == 4 && !(irccmp(parv[2], "ON")))
458 if(!IsOperRemoteBan(source_p))
460 sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name,
461 "remoteban");
462 return 0;
465 propagate_generic(source_p, "UNXLINE", parv[3], CAP_CLUSTER,
466 "%s", parv[1]);
468 if(match(parv[3], me.name) == 0)
469 return 0;
471 else if(dlink_list_length(&cluster_conf_list))
472 cluster_generic(source_p, "UNXLINE", SHARED_UNXLINE, CAP_CLUSTER,
473 "%s", parv[1]);
475 if(remove_temp_xline(source_p, parv[1]))
476 return 0;
478 remove_xline(source_p, parv[1]);
480 return 0;
483 /* ms_unxline()
485 * handles a remote unxline
487 static int
488 ms_unxline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
490 /* parv[0] parv[1] parv[2]
491 * oper target server gecos
493 propagate_generic(source_p, "UNXLINE", parv[1], CAP_CLUSTER,
494 "%s", parv[2]);
496 if(!match(parv[1], me.name))
497 return 0;
499 if(!IsPerson(source_p))
500 return 0;
502 handle_remote_unxline(source_p, parv[2]);
503 return 0;
506 static int
507 me_unxline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
509 /* name */
510 if(!IsPerson(source_p))
511 return 0;
513 handle_remote_unxline(source_p, parv[1]);
514 return 0;
517 static void
518 handle_remote_unxline(struct Client *source_p, const char *name)
520 if (!find_client_shared_conf(source_p, SHARED_UNXLINE))
521 return;
522 if(remove_temp_xline(source_p, name))
523 return;
525 remove_xline(source_p, name);
527 return;
530 static int
531 remove_temp_xline(struct Client *source_p, const char *name)
533 struct ConfItem *aconf;
534 dlink_node *ptr;
536 DLINK_FOREACH(ptr, xline_conf_list.head)
538 aconf = ptr->data;
540 /* only want to check temp ones! */
541 if(!aconf->hold)
542 continue;
544 if(!irccmp(aconf->name, name))
546 sendto_one_notice(source_p,
547 ":X-Line for [%s] is removed",
548 name);
549 sendto_realops_snomask(SNO_GENERAL, L_ALL,
550 "%s has removed the temporary X-Line for: [%s]",
551 get_oper_name(source_p), name);
552 ilog(L_KLINE, "UX %s %s",
553 get_oper_name(source_p), name);
555 free_conf(aconf);
556 dlinkDestroy(ptr, &xline_conf_list);
557 return 1;
561 return 0;
564 /* remove_xline()
566 * inputs - gecos to remove
567 * outputs -
568 * side effects - removes xline from conf, if exists
570 static void
571 remove_xline(struct Client *source_p, const char *huntgecos)
573 FILE *in, *out;
574 char buf[BUFSIZE];
575 char buff[BUFSIZE];
576 char temppath[BUFSIZE];
577 const char *filename;
578 const char *gecos;
579 mode_t oldumask;
580 char *p;
581 int error_on_write = 0;
582 int found_xline = 0;
584 filename = ConfigFileEntry.xlinefile;
585 ircsnprintf(temppath, sizeof(temppath),
586 "%s.tmp", ConfigFileEntry.xlinefile);
588 if((in = fopen(filename, "r")) == NULL)
590 sendto_one_notice(source_p, ":Cannot open %s", filename);
591 return;
594 oldumask = umask(0);
596 if((out = fopen(temppath, "w")) == NULL)
598 sendto_one_notice(source_p, ":Cannot open %s", temppath);
599 fclose(in);
600 umask(oldumask);
601 return;
604 umask(oldumask);
606 while (fgets(buf, sizeof(buf), in))
608 if(error_on_write)
610 if(temppath != NULL)
611 (void) unlink(temppath);
613 break;
616 strlcpy(buff, buf, sizeof(buff));
618 if((p = strchr(buff, '\n')) != NULL)
619 *p = '\0';
621 if((*buff == '\0') || (*buff == '#'))
623 error_on_write = (fputs(buf, out) < 0) ? YES : NO;
624 continue;
627 if((gecos = getfield(buff)) == NULL)
629 error_on_write = (fputs(buf, out) < 0) ? YES : NO;
630 continue;
633 /* matching.. */
634 if(irccmp(gecos, huntgecos) == 0)
635 found_xline++;
636 else
637 error_on_write = (fputs(buf, out) < 0) ? YES : NO;
640 fclose(in);
641 fclose(out);
643 if(error_on_write)
645 sendto_one_notice(source_p,
646 ":Couldn't write temp xline file, aborted");
647 return;
649 else if(found_xline == 0)
651 sendto_one_notice(source_p, ":No X-Line for %s", huntgecos);
653 if(temppath != NULL)
654 (void) unlink(temppath);
655 return;
658 (void) rename(temppath, filename);
659 rehash_bans(0);
661 sendto_one_notice(source_p, ":X-Line for [%s] is removed", huntgecos);
662 sendto_realops_snomask(SNO_GENERAL, L_ALL,
663 "%s has removed the X-Line for: [%s]",
664 get_oper_name(source_p), huntgecos);
665 ilog(L_KLINE, "UX %s %s", get_oper_name(source_p), huntgecos);