1 /*
2 * Copyright (c) 2006 Robin Burchell <surreal.w00t@gmail.com>
3 * Rights to this code are as defined in doc/LICENSE.
4 *
5 * Regexp-based AKILL implementation.
6 *
7 */
8
9 /*
10 * @makill regex!here.+ [akill reason]
11 * Matches `nick!user@host realname here' for each client against a given regex, and places akills.
12 * CHECK REGEX USING @RMATCH FIRST!
13 */
14 #include "atheme.h"
15
16 DECLARE_MODULE_V1
17 (
18 "operserv/rakill", false, _modinit, _moddeinit,
19 PACKAGE_STRING,
20 VENDOR_STRING
21 );
22
23 static void os_cmd_rakill(sourceinfo_t *si, int parc, char *parv[]);
24
25 command_t os_rakill = { "RAKILL", N_("Sets a group of AKILLs against users matching a specific regex pattern."), PRIV_MASS_AKILL, 1, os_cmd_rakill, { .path = "oservice/rakill" } };
26
_modinit(module_t * m)27 void _modinit(module_t *m)
28 {
29 service_named_bind_command("operserv", &os_rakill);
30 }
31
_moddeinit(module_unload_intent_t intent)32 void _moddeinit(module_unload_intent_t intent)
33 {
34 service_named_unbind_command("operserv", &os_rakill);
35 }
36
os_cmd_rakill(sourceinfo_t * si,int parc,char * parv[])37 static void os_cmd_rakill(sourceinfo_t *si, int parc, char *parv[])
38 {
39 atheme_regex_t *regex;
40 char usermask[512];
41 unsigned int matches = 0;
42 mowgli_patricia_iteration_state_t state;
43 user_t *u;
44 char *args = parv[0];
45 char *pattern;
46 char *reason;
47 user_t *source;
48 int flags = 0;
49
50 /* make sure they could have done RMATCH */
51 if (!has_priv(si, PRIV_USER_AUSPEX))
52 {
53 command_fail(si, fault_noprivs, STR_NO_PRIVILEGE, PRIV_USER_AUSPEX);
54 return;
55 }
56
57 if (args == NULL)
58 {
59 command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "RAKILL");
60 command_fail(si, fault_needmoreparams, _("Syntax: RAKILL /<regex>/[i] <reason>"));
61 return;
62 }
63
64 pattern = regex_extract(args, &args, &flags);
65 if (pattern == NULL)
66 {
67 command_fail(si, fault_badparams, STR_INVALID_PARAMS, "RAKILL");
68 command_fail(si, fault_badparams, _("Syntax: RAKILL /<regex>/[i] <reason>"));
69 return;
70 }
71
72 reason = args;
73 while (*reason == ' ')
74 reason++;
75 if (*reason == '\0')
76 {
77 command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "RAKILL");
78 command_fail(si, fault_needmoreparams, _("Syntax: RAKILL /<regex>/[i] <reason>"));
79 return;
80 }
81
82 regex = regex_create(pattern, flags);
83 if (regex == NULL)
84 {
85 command_fail(si, fault_badparams, _("The provided regex \2%s\2 is invalid."), pattern);
86 return;
87 }
88
89 source = si->su;
90 /* try to find them on IRC, otherwise use operserv */
91 if (source == NULL)
92 source = si->smu != NULL && MOWGLI_LIST_LENGTH(&si->smu->logins) > 0 ?
93 si->smu->logins.head->data : si->service->me;
94 sprintf(usermask, "%s!%s@%s %s", source->nick, source->user, source->host, source->gecos);
95 if (regex_match(regex, usermask))
96 {
97 regex_destroy(regex);
98 command_fail(si, fault_noprivs, _("The provided regex matches you, refusing RAKILL."));
99 wallops("\2%s\2 attempted to do RAKILL on \2%s\2 matching self",
100 get_oper_name(si), pattern);
101 logcommand(si, CMDLOG_ADMIN, "RAKILL: \2%s\2 (reason: \2%s\2) (refused, matches self)", pattern, reason);
102 return;
103 }
104
105 MOWGLI_PATRICIA_FOREACH(u, &state, userlist)
106 {
107 sprintf(usermask, "%s!%s@%s %s", u->nick, u->user, u->host, u->gecos);
108
109 if (regex_match(regex, usermask))
110 {
111 /* match */
112 command_success_nodata(si, _("\2Match:\2 %s!%s@%s %s - akilling"), u->nick, u->user, u->host, u->gecos);
113 if (! (u->flags & UF_KLINESENT)) {
114 kline_sts("*", "*", u->host, 604800, reason);
115 u->flags |= UF_KLINESENT;
116 }
117 matches++;
118 }
119 }
120
121 regex_destroy(regex);
122 command_success_nodata(si, _("\2%d\2 matches for %s akilled."), matches, pattern);
123 logcommand(si, CMDLOG_ADMIN, "RAKILL: \2%s\2 (reason: \2%s\2) (\2%d\2 matches)", pattern, reason, matches);
124 }
125
126 /* vim:cinoptions=>s,e0,n0,f0,{0,}0,^0,=s,ps,t0,c3,+s,(2s,us,)20,*30,gs,hs
127 * vim:ts=8
128 * vim:sw=8
129 * vim:noexpandtab
130 */
131