]> jfr.im git - solanum.git/blob - modules/core/m_ban.c
ban: Fix build breakage.
[solanum.git] / modules / core / m_ban.c
1 /*
2 * charybdis: An advanced ircd.
3 * m_ban.c: Propagates network bans across servers.
4 *
5 * Copyright (C) 2010 Jilles Tjoelker
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * 1.Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
13 * 2.Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
21 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
26 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include "stdinc.h"
31 #include "send.h"
32 #include "channel.h"
33 #include "client.h"
34 #include "common.h"
35 #include "config.h"
36 #include "ircd.h"
37 #include "match.h"
38 #include "s_conf.h"
39 #include "s_newconf.h"
40 #include "msg.h"
41 #include "modules.h"
42 #include "hash.h"
43 #include "s_serv.h"
44 #include "operhash.h"
45 #include "reject.h"
46 #include "hostmask.h"
47 #include "logger.h"
48
49 static int m_ban(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]);
50 static int ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]);
51
52 struct Message ban_msgtab = {
53 "BAN", 0, 0, 0, MFLG_SLOW,
54 {mg_unreg, {m_ban, 0}, {ms_ban, 9}, {ms_ban, 9}, mg_ignore, {m_ban, 0}}
55 };
56
57 mapi_clist_av1 ban_clist[] = { &ban_msgtab, NULL };
58 DECLARE_MODULE_AV1(ban, NULL, NULL, ban_clist, NULL, NULL, "$Revision: 1349 $");
59
60 static int
61 m_ban(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
62 {
63 sendto_one_notice(source_p, ":The BAN command is not user-accessible.");
64 sendto_one_notice(source_p, ":To ban a user from a channel, see /QUOTE HELP CMODE");
65 if (IsOper(source_p))
66 sendto_one_notice(source_p, ":To ban a user from a server or from the network, see /QUOTE HELP KLINE");
67 return 0;
68 }
69
70 /* ms_ban()
71 *
72 * parv[1] - type
73 * parv[2] - username mask or *
74 * parv[3] - hostname mask
75 * parv[4] - creation TS
76 * parv[5] - duration (relative to creation)
77 * parv[6] - lifetime (relative to creation)
78 * parv[7] - oper or *
79 * parv[8] - reason (possibly with |operreason)
80 */
81 static int
82 ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
83 {
84 rb_dlink_node *ptr;
85 struct ConfItem *aconf;
86 unsigned int ntype;
87 const char *oper, *stype;
88 time_t now, created, hold, lifetime;
89 char *p;
90 int act;
91 int valid;
92
93 now = rb_current_time();
94 if (strlen(parv[1]) != 1)
95 {
96 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
97 "Unknown BAN type %s from %s",
98 parv[1], source_p->name);
99 return 0;
100 }
101 switch (parv[1][0])
102 {
103 case 'K':
104 ntype = CONF_KILL;
105 stype = "K-Line";
106 break;
107 case 'X':
108 ntype = CONF_XLINE;
109 stype = "X-Line";
110 break;
111 case 'R':
112 ntype = IsChannelName(parv[3]) ? CONF_RESV_CHANNEL :
113 CONF_RESV_NICK;
114 stype = "RESV";
115 break;
116 default:
117 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
118 "Unknown BAN type %s from %s",
119 parv[1], source_p->name);
120 return 0;
121 }
122 created = atol(parv[4]);
123 hold = created + atoi(parv[5]);
124 lifetime = created + atoi(parv[6]);
125 if (!strcmp(parv[7], "*"))
126 oper = IsServer(source_p) ? source_p->name : get_oper_name(source_p);
127 else
128 oper = parv[7];
129 ptr = find_prop_ban(ntype, parv[2], parv[3]);
130 if (ptr != NULL)
131 {
132 /* We already know about this ban mask. */
133 aconf = ptr->data;
134 if (aconf->created > created ||
135 (aconf->created == created &&
136 aconf->lifetime >= lifetime))
137 {
138 if (IsPerson(source_p))
139 sendto_one_notice(source_p,
140 ":Your %s [%s%s%s] has been superseded",
141 stype,
142 aconf->user ? aconf->user : "",
143 aconf->user ? "@" : "",
144 aconf->host);
145 return 0;
146 }
147 /* act indicates if something happened (from the oper's
148 * point of view). This is the case if the ban was
149 * previously active (not deleted) or if the new ban
150 * is not a removal and not already expired.
151 */
152 act = !(aconf->status & CONF_ILLEGAL) || (hold != created &&
153 hold > now);
154 if (lifetime > aconf->lifetime)
155 aconf->lifetime = lifetime;
156 /* already expired, hmm */
157 if (aconf->lifetime <= now)
158 return 0;
159 /* Deactivate, it will be reactivated later if appropriate. */
160 deactivate_conf(aconf, ptr, now);
161 rb_free(aconf->user);
162 aconf->user = NULL;
163 rb_free(aconf->host);
164 aconf->host = NULL;
165 operhash_delete(aconf->info.oper);
166 aconf->info.oper = NULL;
167 rb_free(aconf->passwd);
168 aconf->passwd = NULL;
169 rb_free(aconf->spasswd);
170 aconf->spasswd = NULL;
171 }
172 else
173 {
174 /* New ban mask. */
175 aconf = make_conf();
176 aconf->status = CONF_ILLEGAL | ntype;
177 aconf->lifetime = lifetime;
178 rb_dlinkAddAlloc(aconf, &prop_bans);
179 act = hold != created && hold > now;
180 }
181 aconf->flags &= ~CONF_FLAGS_MYOPER;
182 aconf->flags |= CONF_FLAGS_TEMPORARY;
183 aconf->user = ntype == CONF_KILL ? rb_strdup(parv[2]) : NULL;
184 aconf->host = rb_strdup(parv[3]);
185 aconf->info.oper = operhash_add(oper);
186 aconf->created = created;
187 aconf->hold = hold;
188 if (ntype != CONF_KILL || (p = strchr(parv[parc - 1], '|')) == NULL)
189 aconf->passwd = rb_strdup(parv[parc - 1]);
190 else
191 {
192 aconf->passwd = rb_strndup(parv[parc - 1], p - parv[parc - 1] + 1);
193 aconf->spasswd = rb_strdup(p + 1);
194 }
195 /* The ban is fully filled in and in the prop_bans list
196 * but still deactivated. Now determine if it should be activated
197 * and send the server notices.
198 */
199 /* We only reject *@* and the like here.
200 * Otherwise malformed bans are fairly harmless and can be removed.
201 */
202 switch (ntype)
203 {
204 case CONF_KILL:
205 valid = valid_wild_card(aconf->user, aconf->host);
206 break;
207 case CONF_RESV_CHANNEL:
208 valid = 1;
209 break;
210 default:
211 valid = valid_wild_card_simple(aconf->host);
212 break;
213 }
214 if (act && hold != created && !valid)
215 {
216 sendto_realops_snomask(SNO_GENERAL, L_ALL,
217 "Ignoring global %d min. %s from %s%s%s for [%s%s%s]: too few non-wildcard characters",
218 (int)((hold - now) / 60),
219 stype,
220 IsServer(source_p) ? source_p->name : get_oper_name(source_p),
221 strcmp(parv[7], "*") ? " on behalf of " : "",
222 strcmp(parv[7], "*") ? parv[7] : "",
223 aconf->user ? aconf->user : "",
224 aconf->user ? "@" : "",
225 aconf->host);
226 if(IsPerson(source_p))
227 sendto_one_notice(source_p,
228 ":Your %s [%s%s%s] has too few non-wildcard characters",
229 stype,
230 aconf->user ? aconf->user : "",
231 aconf->user ? "@" : "",
232 aconf->host);
233 /* Propagate it, but do not apply it locally. */
234 }
235 else if (act && hold != created)
236 {
237 /* Keep the notices in sync with modules/m_kline.c etc. */
238 sendto_realops_snomask(SNO_GENERAL, L_ALL,
239 "%s added global %d min. %s%s%s for [%s%s%s] [%s]",
240 IsServer(source_p) ? source_p->name : get_oper_name(source_p),
241 (int)((hold - now) / 60),
242 stype,
243 strcmp(parv[7], "*") ? " from " : "",
244 strcmp(parv[7], "*") ? parv[7] : "",
245 aconf->user ? aconf->user : "",
246 aconf->user ? "@" : "",
247 aconf->host,
248 parv[parc - 1]);
249 ilog(L_KLINE, "%s %s %d %s%s%s %s", parv[1],
250 IsServer(source_p) ? source_p->name : get_oper_name(source_p),
251 (int)((hold - now) / 60),
252 aconf->user ? aconf->user : "",
253 aconf->user ? " " : "",
254 aconf->host,
255 parv[parc - 1]);
256 aconf->status &= ~CONF_ILLEGAL;
257 }
258 else if (act)
259 {
260 sendto_realops_snomask(SNO_GENERAL, L_ALL,
261 "%s has removed the global %s for: [%s%s%s]%s%s",
262 IsServer(source_p) ? source_p->name : get_oper_name(source_p),
263 stype,
264 aconf->user ? aconf->user : "",
265 aconf->user ? "@" : "",
266 aconf->host,
267 strcmp(parv[7], "*") ? " on behalf of " : "",
268 strcmp(parv[7], "*") ? parv[7] : "");
269 ilog(L_KLINE, "U%s %s %s%s %s", parv[1],
270 IsServer(source_p) ? source_p->name : get_oper_name(source_p),
271 aconf->user ? aconf->user : "",
272 aconf->user ? " " : "",
273 aconf->host);
274 }
275 /* If CONF_ILLEGAL is still set at this point, remove entries from the
276 * reject cache (for klines and xlines).
277 * If CONF_ILLEGAL is not set, add the ban to the type-specific data
278 * structure and take action on matched clients/channels.
279 */
280 switch (ntype)
281 {
282 case CONF_KILL:
283 if (aconf->status & CONF_ILLEGAL)
284 remove_reject_mask(aconf->user, aconf->host);
285 else
286 {
287 add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf);
288 if(ConfigFileEntry.kline_delay ||
289 (IsServer(source_p) &&
290 !HasSentEob(source_p)))
291 {
292 if(kline_queued == 0)
293 {
294 rb_event_addonce("check_klines", check_klines_event, NULL,
295 ConfigFileEntry.kline_delay ?
296 ConfigFileEntry.kline_delay : 1);
297 kline_queued = 1;
298 }
299 }
300 else
301 check_klines();
302 }
303 break;
304 case CONF_XLINE:
305 if (aconf->status & CONF_ILLEGAL)
306 remove_reject_mask(aconf->host, NULL);
307 else
308 {
309 rb_dlinkAddAlloc(aconf, &xline_conf_list);
310 check_xlines();
311 }
312 break;
313 case CONF_RESV_CHANNEL:
314 if (!(aconf->status & CONF_ILLEGAL))
315 {
316 add_to_resv_hash(aconf->host, aconf);
317 resv_chan_forcepart(aconf->host, aconf->passwd, hold - now);
318 }
319 break;
320 case CONF_RESV_NICK:
321 if (!(aconf->status & CONF_ILLEGAL))
322 rb_dlinkAddAlloc(aconf, &resv_conf_list);
323 break;
324 }
325 sendto_server(client_p, NULL, CAP_BAN|CAP_TS6, NOCAPS,
326 ":%s BAN %s %s %s %s %s %s %s :%s",
327 source_p->id,
328 parv[1],
329 parv[2],
330 parv[3],
331 parv[4],
332 parv[5],
333 parv[6],
334 parv[7],
335 parv[parc - 1]);
336 return 0;
337 }