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