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