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