]> jfr.im git - solanum.git/blame - modules/core/m_ban.c
config.h delenda est
[solanum.git] / modules / core / m_ban.c
CommitLineData
431a1a27
JT
1/*
2 * charybdis: An advanced ircd.
3 * m_ban.c: Propagates network bans across servers.
55abcbb2 4 *
431a1a27
JT
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"
dca9e552 32#include "channel.h"
431a1a27
JT
33#include "client.h"
34#include "common.h"
9b8e9eb3 35#include "defaults.h"
431a1a27
JT
36#include "ircd.h"
37#include "match.h"
38#include "s_conf.h"
5c2b9eaf 39#include "s_newconf.h"
431a1a27
JT
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"
77d3d2db 47#include "logger.h"
431a1a27 48
eeabf33a
EM
49static const char ban_desc[] = "Provides the TS6 BAN command for propagating network-wide bans";
50
3c7d6fcc
EM
51static void m_ban(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[]);
52static void ms_ban(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[]);
431a1a27
JT
53
54struct Message ban_msgtab = {
7baa37a9 55 "BAN", 0, 0, 0, 0,
02e655ae 56 {mg_unreg, {m_ban, 0}, {ms_ban, 9}, {ms_ban, 9}, mg_ignore, {m_ban, 0}}
431a1a27
JT
57};
58
59mapi_clist_av1 ban_clist[] = { &ban_msgtab, NULL };
eeabf33a 60
65ca483f 61DECLARE_MODULE_AV2(ban, NULL, NULL, ban_clist, NULL, NULL, NULL, NULL, ban_desc);
431a1a27 62
3c7d6fcc 63static void
428ca87b 64m_ban(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
02e655ae
JT
65{
66 sendto_one_notice(source_p, ":The BAN command is not user-accessible.");
67 sendto_one_notice(source_p, ":To ban a user from a channel, see /QUOTE HELP CMODE");
68 if (IsOper(source_p))
69 sendto_one_notice(source_p, ":To ban a user from a server or from the network, see /QUOTE HELP KLINE");
02e655ae
JT
70}
71
431a1a27
JT
72/* ms_ban()
73 *
cedb7d05
JT
74 * parv[1] - type
75 * parv[2] - username mask or *
76 * parv[3] - hostname mask
77 * parv[4] - creation TS
78 * parv[5] - duration (relative to creation)
79 * parv[6] - lifetime (relative to creation)
80 * parv[7] - oper or *
81 * parv[8] - reason (possibly with |operreason)
431a1a27 82 */
3c7d6fcc 83static void
428ca87b 84ms_ban(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
431a1a27
JT
85{
86 rb_dlink_node *ptr;
87 struct ConfItem *aconf;
88 unsigned int ntype;
89 const char *oper, *stype;
2a17ae54 90 time_t now, created, hold, lifetime;
431a1a27
JT
91 char *p;
92 int act;
dca9e552 93 int valid;
431a1a27 94
2a17ae54 95 now = rb_current_time();
cedb7d05 96 if (strlen(parv[1]) != 1)
431a1a27
JT
97 {
98 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
99 "Unknown BAN type %s from %s",
cedb7d05 100 parv[1], source_p->name);
3c7d6fcc 101 return;
431a1a27 102 }
cedb7d05 103 switch (parv[1][0])
431a1a27
JT
104 {
105 case 'K':
106 ntype = CONF_KILL;
107 stype = "K-Line";
108 break;
3cbbfb25
JT
109 case 'X':
110 ntype = CONF_XLINE;
111 stype = "X-Line";
112 break;
dca9e552
JT
113 case 'R':
114 ntype = IsChannelName(parv[3]) ? CONF_RESV_CHANNEL :
115 CONF_RESV_NICK;
116 stype = "RESV";
117 break;
431a1a27
JT
118 default:
119 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
120 "Unknown BAN type %s from %s",
cedb7d05 121 parv[1], source_p->name);
3c7d6fcc 122 return;
431a1a27 123 }
cedb7d05
JT
124 created = atol(parv[4]);
125 hold = created + atoi(parv[5]);
126 lifetime = created + atoi(parv[6]);
127 if (!strcmp(parv[7], "*"))
431a1a27
JT
128 oper = IsServer(source_p) ? source_p->name : get_oper_name(source_p);
129 else
cedb7d05
JT
130 oper = parv[7];
131 ptr = find_prop_ban(ntype, parv[2], parv[3]);
431a1a27
JT
132 if (ptr != NULL)
133 {
a0ce140e 134 /* We already know about this ban mask. */
431a1a27 135 aconf = ptr->data;
6229f9f8
JT
136 if (aconf->created > created ||
137 (aconf->created == created &&
138 aconf->lifetime >= lifetime))
431a1a27
JT
139 {
140 if (IsPerson(source_p))
141 sendto_one_notice(source_p,
142 ":Your %s [%s%s%s] has been superseded",
143 stype,
144 aconf->user ? aconf->user : "",
145 aconf->user ? "@" : "",
146 aconf->host);
3c7d6fcc 147 return;
431a1a27 148 }
a0ce140e
JT
149 /* act indicates if something happened (from the oper's
150 * point of view). This is the case if the ban was
151 * previously active (not deleted) or if the new ban
152 * is not a removal and not already expired.
153 */
cedb7d05 154 act = !(aconf->status & CONF_ILLEGAL) || (hold != created &&
2a17ae54 155 hold > now);
431a1a27
JT
156 if (lifetime > aconf->lifetime)
157 aconf->lifetime = lifetime;
158 /* already expired, hmm */
2a17ae54 159 if (aconf->lifetime <= now)
3c7d6fcc 160 return;
a0ce140e 161 /* Deactivate, it will be reactivated later if appropriate. */
2a17ae54 162 deactivate_conf(aconf, ptr, now);
431a1a27
JT
163 rb_free(aconf->user);
164 aconf->user = NULL;
165 rb_free(aconf->host);
166 aconf->host = NULL;
167 operhash_delete(aconf->info.oper);
168 aconf->info.oper = NULL;
169 rb_free(aconf->passwd);
170 aconf->passwd = NULL;
171 rb_free(aconf->spasswd);
172 aconf->spasswd = NULL;
173 }
174 else
175 {
a0ce140e 176 /* New ban mask. */
431a1a27
JT
177 aconf = make_conf();
178 aconf->status = CONF_ILLEGAL | ntype;
179 aconf->lifetime = lifetime;
180 rb_dlinkAddAlloc(aconf, &prop_bans);
2a17ae54 181 act = hold != created && hold > now;
431a1a27
JT
182 }
183 aconf->flags &= ~CONF_FLAGS_MYOPER;
184 aconf->flags |= CONF_FLAGS_TEMPORARY;
cedb7d05
JT
185 aconf->user = ntype == CONF_KILL ? rb_strdup(parv[2]) : NULL;
186 aconf->host = rb_strdup(parv[3]);
431a1a27
JT
187 aconf->info.oper = operhash_add(oper);
188 aconf->created = created;
189 aconf->hold = hold;
f89191ac 190 if (ntype != CONF_KILL || (p = strchr(parv[parc - 1], '|')) == NULL)
431a1a27
JT
191 aconf->passwd = rb_strdup(parv[parc - 1]);
192 else
193 {
194 aconf->passwd = rb_strndup(parv[parc - 1], p - parv[parc - 1] + 1);
195 aconf->spasswd = rb_strdup(p + 1);
196 }
a0ce140e
JT
197 /* The ban is fully filled in and in the prop_bans list
198 * but still deactivated. Now determine if it should be activated
199 * and send the server notices.
200 */
201 /* We only reject *@* and the like here.
202 * Otherwise malformed bans are fairly harmless and can be removed.
203 */
dca9e552
JT
204 switch (ntype)
205 {
206 case CONF_KILL:
207 valid = valid_wild_card(aconf->user, aconf->host);
208 break;
209 case CONF_RESV_CHANNEL:
210 valid = 1;
211 break;
212 default:
213 valid = valid_wild_card_simple(aconf->host);
214 break;
215 }
216 if (act && hold != created && !valid)
5c2b9eaf
JT
217 {
218 sendto_realops_snomask(SNO_GENERAL, L_ALL,
219 "Ignoring global %d min. %s from %s%s%s for [%s%s%s]: too few non-wildcard characters",
2a17ae54 220 (int)((hold - now) / 60),
5c2b9eaf
JT
221 stype,
222 IsServer(source_p) ? source_p->name : get_oper_name(source_p),
223 strcmp(parv[7], "*") ? " on behalf of " : "",
224 strcmp(parv[7], "*") ? parv[7] : "",
225 aconf->user ? aconf->user : "",
226 aconf->user ? "@" : "",
227 aconf->host);
228 if(IsPerson(source_p))
229 sendto_one_notice(source_p,
230 ":Your %s [%s%s%s] has too few non-wildcard characters",
231 stype,
232 aconf->user ? aconf->user : "",
233 aconf->user ? "@" : "",
234 aconf->host);
235 /* Propagate it, but do not apply it locally. */
236 }
237 else if (act && hold != created)
431a1a27
JT
238 {
239 /* Keep the notices in sync with modules/m_kline.c etc. */
240 sendto_realops_snomask(SNO_GENERAL, L_ALL,
241 "%s added global %d min. %s%s%s for [%s%s%s] [%s]",
242 IsServer(source_p) ? source_p->name : get_oper_name(source_p),
2a17ae54 243 (int)((hold - now) / 60),
431a1a27 244 stype,
cedb7d05
JT
245 strcmp(parv[7], "*") ? " from " : "",
246 strcmp(parv[7], "*") ? parv[7] : "",
431a1a27
JT
247 aconf->user ? aconf->user : "",
248 aconf->user ? "@" : "",
249 aconf->host,
250 parv[parc - 1]);
3cbbfb25 251 ilog(L_KLINE, "%s %s %d %s%s%s %s", parv[1],
431a1a27 252 IsServer(source_p) ? source_p->name : get_oper_name(source_p),
2a17ae54 253 (int)((hold - now) / 60),
3cbbfb25
JT
254 aconf->user ? aconf->user : "",
255 aconf->user ? " " : "",
256 aconf->host,
431a1a27 257 parv[parc - 1]);
cedb7d05 258 aconf->status &= ~CONF_ILLEGAL;
431a1a27
JT
259 }
260 else if (act)
261 {
262 sendto_realops_snomask(SNO_GENERAL, L_ALL,
263 "%s has removed the global %s for: [%s%s%s]%s%s",
264 IsServer(source_p) ? source_p->name : get_oper_name(source_p),
265 stype,
266 aconf->user ? aconf->user : "",
267 aconf->user ? "@" : "",
268 aconf->host,
cedb7d05
JT
269 strcmp(parv[7], "*") ? " on behalf of " : "",
270 strcmp(parv[7], "*") ? parv[7] : "");
3cbbfb25 271 ilog(L_KLINE, "U%s %s %s%s %s", parv[1],
431a1a27 272 IsServer(source_p) ? source_p->name : get_oper_name(source_p),
3cbbfb25
JT
273 aconf->user ? aconf->user : "",
274 aconf->user ? " " : "",
275 aconf->host);
431a1a27 276 }
a0ce140e
JT
277 /* If CONF_ILLEGAL is still set at this point, remove entries from the
278 * reject cache (for klines and xlines).
279 * If CONF_ILLEGAL is not set, add the ban to the type-specific data
280 * structure and take action on matched clients/channels.
281 */
431a1a27
JT
282 switch (ntype)
283 {
284 case CONF_KILL:
285 if (aconf->status & CONF_ILLEGAL)
286 remove_reject_mask(aconf->user, aconf->host);
287 else
288 {
289 add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf);
290 if(ConfigFileEntry.kline_delay ||
291 (IsServer(source_p) &&
292 !HasSentEob(source_p)))
293 {
294 if(kline_queued == 0)
295 {
296 rb_event_addonce("check_klines", check_klines_event, NULL,
8db50c03
KB
297 ConfigFileEntry.kline_delay ?
298 ConfigFileEntry.kline_delay : 1);
431a1a27
JT
299 kline_queued = 1;
300 }
301 }
302 else
303 check_klines();
304 }
305 break;
3cbbfb25
JT
306 case CONF_XLINE:
307 if (aconf->status & CONF_ILLEGAL)
308 remove_reject_mask(aconf->host, NULL);
309 else
310 {
311 rb_dlinkAddAlloc(aconf, &xline_conf_list);
312 check_xlines();
313 }
314 break;
dca9e552
JT
315 case CONF_RESV_CHANNEL:
316 if (!(aconf->status & CONF_ILLEGAL))
317 {
318 add_to_resv_hash(aconf->host, aconf);
2a17ae54 319 resv_chan_forcepart(aconf->host, aconf->passwd, hold - now);
dca9e552
JT
320 }
321 break;
322 case CONF_RESV_NICK:
323 if (!(aconf->status & CONF_ILLEGAL))
324 rb_dlinkAddAlloc(aconf, &resv_conf_list);
325 break;
431a1a27 326 }
9470d75a 327 sendto_server(client_p, NULL, CAP_BAN|CAP_TS6, NOCAPS,
cedb7d05 328 ":%s BAN %s %s %s %s %s %s %s :%s",
431a1a27
JT
329 source_p->id,
330 parv[1],
331 parv[2],
332 parv[3],
333 parv[4],
334 parv[5],
335 parv[6],
336 parv[7],
431a1a27 337 parv[parc - 1]);
431a1a27 338}