]> jfr.im git - irc/rqf/shadowircd.git/blame - modules/core/m_ban.c
Restore snotes, logs for UNRESV nick.
[irc/rqf/shadowircd.git] / modules / core / m_ban.c
CommitLineData
65b8e002
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"
9b9d818b 32#include "channel.h"
65b8e002
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"
70fd7fc9 39#include "s_newconf.h"
65b8e002
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"
47
48static int ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]);
49
50struct Message ban_msgtab = {
51 "BAN", 0, 0, 0, MFLG_SLOW,
e49d8185 52 {mg_unreg, mg_ignore, {ms_ban, 9}, {ms_ban, 9}, mg_ignore, mg_ignore}
65b8e002
JT
53};
54
55mapi_clist_av1 ban_clist[] = { &ban_msgtab, NULL };
56DECLARE_MODULE_AV1(ban, NULL, NULL, ban_clist, NULL, NULL, "$Revision: 1349 $");
57
58/* ms_ban()
59 *
e49d8185
JT
60 * parv[1] - type
61 * parv[2] - username mask or *
62 * parv[3] - hostname mask
63 * parv[4] - creation TS
64 * parv[5] - duration (relative to creation)
65 * parv[6] - lifetime (relative to creation)
66 * parv[7] - oper or *
67 * parv[8] - reason (possibly with |operreason)
65b8e002
JT
68 */
69static int
70ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
71{
72 rb_dlink_node *ptr;
73 struct ConfItem *aconf;
74 unsigned int ntype;
75 const char *oper, *stype;
76 time_t created, hold, lifetime;
77 char *p;
78 int act;
9b9d818b 79 int valid;
65b8e002 80
e49d8185 81 if (strlen(parv[1]) != 1)
65b8e002
JT
82 {
83 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
84 "Unknown BAN type %s from %s",
e49d8185 85 parv[1], source_p->name);
65b8e002
JT
86 return 0;
87 }
e49d8185 88 switch (parv[1][0])
65b8e002
JT
89 {
90 case 'K':
91 ntype = CONF_KILL;
92 stype = "K-Line";
93 break;
112e8a66
JT
94 case 'X':
95 ntype = CONF_XLINE;
96 stype = "X-Line";
97 break;
9b9d818b
JT
98 case 'R':
99 ntype = IsChannelName(parv[3]) ? CONF_RESV_CHANNEL :
100 CONF_RESV_NICK;
101 stype = "RESV";
102 break;
65b8e002
JT
103 default:
104 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
105 "Unknown BAN type %s from %s",
e49d8185 106 parv[1], source_p->name);
65b8e002
JT
107 return 0;
108 }
e49d8185
JT
109 created = atol(parv[4]);
110 hold = created + atoi(parv[5]);
111 lifetime = created + atoi(parv[6]);
112 if (!strcmp(parv[7], "*"))
65b8e002
JT
113 oper = IsServer(source_p) ? source_p->name : get_oper_name(source_p);
114 else
e49d8185
JT
115 oper = parv[7];
116 ptr = find_prop_ban(ntype, parv[2], parv[3]);
65b8e002
JT
117 if (ptr != NULL)
118 {
119 aconf = ptr->data;
c177d078
JT
120 if (aconf->created > created ||
121 (aconf->created == created &&
122 aconf->lifetime >= lifetime))
65b8e002
JT
123 {
124 if (IsPerson(source_p))
125 sendto_one_notice(source_p,
126 ":Your %s [%s%s%s] has been superseded",
127 stype,
128 aconf->user ? aconf->user : "",
129 aconf->user ? "@" : "",
130 aconf->host);
131 return 0;
132 }
e49d8185
JT
133 act = !(aconf->status & CONF_ILLEGAL) || (hold != created &&
134 hold > rb_current_time());
65b8e002
JT
135 if (lifetime > aconf->lifetime)
136 aconf->lifetime = lifetime;
137 /* already expired, hmm */
138 if (aconf->lifetime <= rb_current_time())
139 return 0;
140 deactivate_conf(aconf, ptr);
141 rb_free(aconf->user);
142 aconf->user = NULL;
143 rb_free(aconf->host);
144 aconf->host = NULL;
145 operhash_delete(aconf->info.oper);
146 aconf->info.oper = NULL;
147 rb_free(aconf->passwd);
148 aconf->passwd = NULL;
149 rb_free(aconf->spasswd);
150 aconf->spasswd = NULL;
151 }
152 else
153 {
154 aconf = make_conf();
155 aconf->status = CONF_ILLEGAL | ntype;
156 aconf->lifetime = lifetime;
157 rb_dlinkAddAlloc(aconf, &prop_bans);
e49d8185 158 act = hold != created && hold > rb_current_time();
65b8e002
JT
159 }
160 aconf->flags &= ~CONF_FLAGS_MYOPER;
161 aconf->flags |= CONF_FLAGS_TEMPORARY;
e49d8185
JT
162 aconf->user = ntype == CONF_KILL ? rb_strdup(parv[2]) : NULL;
163 aconf->host = rb_strdup(parv[3]);
65b8e002
JT
164 aconf->info.oper = operhash_add(oper);
165 aconf->created = created;
166 aconf->hold = hold;
a75522e6 167 if (ntype != CONF_KILL || (p = strchr(parv[parc - 1], '|')) == NULL)
65b8e002
JT
168 aconf->passwd = rb_strdup(parv[parc - 1]);
169 else
170 {
171 aconf->passwd = rb_strndup(parv[parc - 1], p - parv[parc - 1] + 1);
172 aconf->spasswd = rb_strdup(p + 1);
173 }
9b9d818b
JT
174 switch (ntype)
175 {
176 case CONF_KILL:
177 valid = valid_wild_card(aconf->user, aconf->host);
178 break;
179 case CONF_RESV_CHANNEL:
180 valid = 1;
181 break;
182 default:
183 valid = valid_wild_card_simple(aconf->host);
184 break;
185 }
186 if (act && hold != created && !valid)
70fd7fc9
JT
187 {
188 sendto_realops_snomask(SNO_GENERAL, L_ALL,
189 "Ignoring global %d min. %s from %s%s%s for [%s%s%s]: too few non-wildcard characters",
190 (hold - rb_current_time()) / 60,
191 stype,
192 IsServer(source_p) ? source_p->name : get_oper_name(source_p),
193 strcmp(parv[7], "*") ? " on behalf of " : "",
194 strcmp(parv[7], "*") ? parv[7] : "",
195 aconf->user ? aconf->user : "",
196 aconf->user ? "@" : "",
197 aconf->host);
198 if(IsPerson(source_p))
199 sendto_one_notice(source_p,
200 ":Your %s [%s%s%s] has too few non-wildcard characters",
201 stype,
202 aconf->user ? aconf->user : "",
203 aconf->user ? "@" : "",
204 aconf->host);
205 /* Propagate it, but do not apply it locally. */
206 }
207 else if (act && hold != created)
65b8e002
JT
208 {
209 /* Keep the notices in sync with modules/m_kline.c etc. */
210 sendto_realops_snomask(SNO_GENERAL, L_ALL,
211 "%s added global %d min. %s%s%s for [%s%s%s] [%s]",
212 IsServer(source_p) ? source_p->name : get_oper_name(source_p),
213 (hold - rb_current_time()) / 60,
214 stype,
e49d8185
JT
215 strcmp(parv[7], "*") ? " from " : "",
216 strcmp(parv[7], "*") ? parv[7] : "",
65b8e002
JT
217 aconf->user ? aconf->user : "",
218 aconf->user ? "@" : "",
219 aconf->host,
220 parv[parc - 1]);
112e8a66 221 ilog(L_KLINE, "%s %s %d %s%s%s %s", parv[1],
65b8e002
JT
222 IsServer(source_p) ? source_p->name : get_oper_name(source_p),
223 (hold - rb_current_time()) / 60,
112e8a66
JT
224 aconf->user ? aconf->user : "",
225 aconf->user ? " " : "",
226 aconf->host,
65b8e002 227 parv[parc - 1]);
e49d8185 228 aconf->status &= ~CONF_ILLEGAL;
65b8e002
JT
229 }
230 else if (act)
231 {
232 sendto_realops_snomask(SNO_GENERAL, L_ALL,
233 "%s has removed the global %s for: [%s%s%s]%s%s",
234 IsServer(source_p) ? source_p->name : get_oper_name(source_p),
235 stype,
236 aconf->user ? aconf->user : "",
237 aconf->user ? "@" : "",
238 aconf->host,
e49d8185
JT
239 strcmp(parv[7], "*") ? " on behalf of " : "",
240 strcmp(parv[7], "*") ? parv[7] : "");
112e8a66 241 ilog(L_KLINE, "U%s %s %s%s %s", parv[1],
65b8e002 242 IsServer(source_p) ? source_p->name : get_oper_name(source_p),
112e8a66
JT
243 aconf->user ? aconf->user : "",
244 aconf->user ? " " : "",
245 aconf->host);
65b8e002
JT
246 }
247 switch (ntype)
248 {
249 case CONF_KILL:
250 if (aconf->status & CONF_ILLEGAL)
251 remove_reject_mask(aconf->user, aconf->host);
252 else
253 {
254 add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf);
255 if(ConfigFileEntry.kline_delay ||
256 (IsServer(source_p) &&
257 !HasSentEob(source_p)))
258 {
259 if(kline_queued == 0)
260 {
261 rb_event_addonce("check_klines", check_klines_event, NULL,
262 ConfigFileEntry.kline_delay);
263 kline_queued = 1;
264 }
265 }
266 else
267 check_klines();
268 }
269 break;
112e8a66
JT
270 case CONF_XLINE:
271 if (aconf->status & CONF_ILLEGAL)
272 remove_reject_mask(aconf->host, NULL);
273 else
274 {
275 rb_dlinkAddAlloc(aconf, &xline_conf_list);
276 check_xlines();
277 }
278 break;
9b9d818b
JT
279 case CONF_RESV_CHANNEL:
280 if (!(aconf->status & CONF_ILLEGAL))
281 {
282 add_to_resv_hash(aconf->host, aconf);
283 resv_chan_forcepart(aconf->host, aconf->passwd, hold - rb_current_time());
284 }
285 break;
286 case CONF_RESV_NICK:
287 if (!(aconf->status & CONF_ILLEGAL))
288 rb_dlinkAddAlloc(aconf, &resv_conf_list);
289 break;
65b8e002 290 }
05114b16 291 sendto_server(client_p, NULL, CAP_BAN|CAP_TS6, NOCAPS,
e49d8185 292 ":%s BAN %s %s %s %s %s %s %s :%s",
65b8e002
JT
293 source_p->id,
294 parv[1],
295 parv[2],
296 parv[3],
297 parv[4],
298 parv[5],
299 parv[6],
300 parv[7],
65b8e002
JT
301 parv[parc - 1]);
302 return 0;
303}