3 * Copyright (C) 2002-2003 Lee Hardy <lee@leeh.co.uk>
4 * Copyright (C) 2002-2005 ircd-ratbox development team
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
10 * 1.Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * 2.Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3.The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
48 #include "s_newconf.h"
53 static const char xline_desc
[] =
54 "Provides management of GECOS bans via (UN)XLINE command";
56 static void mo_xline(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[]);
57 static void ms_xline(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[]);
58 static void me_xline(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[]);
59 static void mo_unxline(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
,
61 static void ms_unxline(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
,
63 static void me_unxline(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
,
66 static bool valid_xline(struct Client
*, const char *, const char *);
67 static void apply_xline(struct Client
*client_p
, const char *name
,
68 const char *reason
, int temp_time
, bool propagated
);
69 static void propagate_xline(struct Client
*source_p
, const char *target
,
70 int temp_time
, const char *name
, const char *type
, const char *reason
);
71 static void cluster_xline(struct Client
*source_p
, int temp_time
,
72 const char *name
, const char *reason
);
74 static void handle_remote_xline(struct Client
*source_p
, int temp_time
,
75 const char *name
, const char *reason
);
76 static void handle_remote_unxline(struct Client
*source_p
, const char *name
);
77 static void remove_xline(struct Client
*source_p
, const char *name
,
80 struct Message xline_msgtab
= {
82 {mg_unreg
, mg_not_oper
, {ms_xline
, 5}, {ms_xline
, 5}, {me_xline
, 5}, {mo_xline
, 3}}
85 struct Message unxline_msgtab
= {
86 "UNXLINE", 0, 0, 0, 0,
87 {mg_unreg
, mg_not_oper
, {ms_unxline
, 3}, {ms_unxline
, 3}, {me_unxline
, 2}, {mo_unxline
, 2}}
90 mapi_clist_av1 xline_clist
[] = { &xline_msgtab
, &unxline_msgtab
, NULL
};
92 DECLARE_MODULE_AV2(xline
, NULL
, NULL
, xline_clist
, NULL
, NULL
, NULL
, NULL
, xline_desc
);
96 * parv[1] - thing to xline
97 * parv[2] - optional type/reason
101 mo_xline(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
103 struct ConfItem
*aconf
;
106 const char *target_server
= NULL
;
109 bool propagated
= ConfigFileEntry
.use_propagated_bans
;
111 if(!IsOperXline(source_p
))
113 sendto_one(source_p
, form_str(ERR_NOPRIVS
), me
.name
, source_p
->name
, "xline");
117 if((temp_time
= valid_temp_time(parv
[loc
])) >= 0)
119 /* we just set temp_time to -1! */
126 /* XLINE <gecos> ON <server> :<reason> */
127 if(parc
>= loc
+ 2 && !irccmp(parv
[loc
], "ON"))
129 if(!IsOperRemoteBan(source_p
))
131 sendto_one(source_p
, form_str(ERR_NOPRIVS
),
132 me
.name
, source_p
->name
, "remoteban");
136 target_server
= parv
[loc
+ 1];
140 if(parc
<= loc
|| EmptyString(parv
[loc
]))
142 sendto_one(source_p
, form_str(ERR_NEEDMOREPARAMS
),
143 me
.name
, source_p
->name
, "XLINE");
149 if(target_server
!= NULL
)
152 sendto_realops_snomask(SNO_GENERAL
, L_NETWIDE
, "%s is adding a temporary %d min. X-Line for [%s] on %s [%s]",
153 get_oper_name(source_p
), temp_time
/ 60, name
, target_server
, reason
);
155 sendto_realops_snomask(SNO_GENERAL
, L_NETWIDE
, "%s is adding a permanent X-Line for [%s] on %s [%s]",
156 get_oper_name(source_p
), name
, target_server
, reason
);
158 propagate_xline(source_p
, target_server
, temp_time
, name
, "2", reason
);
160 if(!match(target_server
, me
.name
))
163 /* Set as local-only. */
166 else if(!propagated
&& rb_dlink_list_length(&cluster_conf_list
) > 0)
167 cluster_xline(source_p
, temp_time
, name
, reason
);
169 if((aconf
= find_xline_mask(name
)) != NULL
)
171 sendto_one(source_p
, ":%s NOTICE %s :[%s] already X-Lined by [%s] - %s",
172 me
.name
, source_p
->name
, name
, aconf
->host
, aconf
->passwd
);
176 if(!valid_xline(source_p
, name
, reason
))
179 if(propagated
&& temp_time
== 0)
181 sendto_one_notice(source_p
, ":Cannot set a permanent global ban");
185 apply_xline(source_p
, name
, reason
, temp_time
, propagated
);
190 * handles a remote xline
193 ms_xline(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
195 /* parv[0] parv[1] parv[2] parv[3] parv[4]
196 * oper target serv xline type reason
198 propagate_xline(source_p
, parv
[1], 0, parv
[2], parv
[3], parv
[4]);
200 if(!IsPerson(source_p
))
203 /* destined for me? */
204 if(!match(parv
[1], me
.name
))
207 handle_remote_xline(source_p
, 0, parv
[2], parv
[4]);
211 me_xline(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
213 /* time name type :reason */
214 if(!IsPerson(source_p
))
217 handle_remote_xline(source_p
, atoi(parv
[1]), parv
[2], parv
[4]);
221 handle_remote_xline(struct Client
*source_p
, int temp_time
, const char *name
, const char *reason
)
223 struct ConfItem
*aconf
;
225 if(!valid_xline(source_p
, name
, reason
))
229 if((aconf
= find_xline_mask(name
)) != NULL
)
231 sendto_one_notice(source_p
, ":[%s] already X-Lined by [%s] - %s", name
, aconf
->host
,
236 apply_xline(source_p
, name
, reason
, temp_time
, false);
241 * inputs - client xlining, gecos, reason and whether to warn
243 * side effects - checks the xline for validity, erroring if needed
246 valid_xline(struct Client
*source_p
, const char *gecos
, const char *reason
)
248 if(EmptyString(reason
))
250 sendto_one(source_p
, form_str(ERR_NEEDMOREPARAMS
),
251 get_id(&me
, source_p
), get_id(source_p
, source_p
), "XLINE");
255 if(!valid_wild_card_simple(gecos
))
257 sendto_one_notice(source_p
,
258 ":Please include at least %d non-wildcard "
259 "characters with the xline",
260 ConfigFileEntry
.min_nonwildcard_simple
);
268 apply_xline(struct Client
*source_p
, const char *name
, const char *reason
, int temp_time
, bool propagated
)
270 struct ConfItem
*aconf
;
273 aconf
->status
= CONF_XLINE
;
274 aconf
->created
= rb_current_time();
275 aconf
->host
= rb_strdup(name
);
276 aconf
->passwd
= rb_strdup(reason
);
277 collapse(aconf
->host
);
279 aconf
->info
.oper
= operhash_add(get_oper_name(source_p
));
283 aconf
->flags
|= CONF_FLAGS_MYOPER
| CONF_FLAGS_TEMPORARY
;
284 aconf
->hold
= rb_current_time() + temp_time
;
285 aconf
->lifetime
= aconf
->hold
;
287 replace_old_ban(aconf
);
290 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
291 "%s added global %d min. X-Line for [%s] [%s]",
292 get_oper_name(source_p
), temp_time
/ 60,
293 aconf
->host
, reason
);
294 ilog(L_KLINE
, "X %s %d %s %s",
295 get_oper_name(source_p
), temp_time
/ 60, name
, reason
);
296 sendto_one_notice(source_p
, ":Added global %d min. X-Line [%s]",
297 temp_time
/ 60, aconf
->host
);
298 sendto_server(NULL
, NULL
, CAP_BAN
|CAP_TS6
, NOCAPS
,
299 ":%s BAN X * %s %lu %d %d * :%s",
300 source_p
->id
, aconf
->host
,
301 (unsigned long)aconf
->created
,
302 (int)(aconf
->hold
- aconf
->created
),
303 (int)(aconf
->lifetime
- aconf
->created
),
306 else if(temp_time
> 0)
308 aconf
->hold
= rb_current_time() + temp_time
;
310 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
311 "%s added temporary %d min. X-Line for [%s] [%s]",
312 get_oper_name(source_p
), temp_time
/ 60,
313 aconf
->host
, reason
);
314 ilog(L_KLINE
, "X %s %d %s %s",
315 get_oper_name(source_p
), temp_time
/ 60, name
, reason
);
316 sendto_one_notice(source_p
, ":Added temporary %d min. X-Line [%s]",
317 temp_time
/ 60, aconf
->host
);
321 sendto_realops_snomask(SNO_GENERAL
, L_ALL
, "%s added X-Line for [%s] [%s]",
322 get_oper_name(source_p
), aconf
->host
, aconf
->passwd
);
323 sendto_one_notice(source_p
, ":Added X-Line for [%s] [%s]",
324 aconf
->host
, aconf
->passwd
);
326 bandb_add(BANDB_XLINE
, source_p
, aconf
->host
, NULL
, aconf
->passwd
, NULL
, 0);
327 ilog(L_KLINE
, "X %s 0 %s %s", get_oper_name(source_p
), name
, aconf
->passwd
);
330 rb_dlinkAddAlloc(aconf
, &xline_conf_list
);
335 propagate_xline(struct Client
*source_p
, const char *target
,
336 int temp_time
, const char *name
, const char *type
, const char *reason
)
340 sendto_match_servs(source_p
, target
, CAP_CLUSTER
, NOCAPS
,
341 "XLINE %s %s %s :%s", target
, name
, type
, reason
);
342 sendto_match_servs(source_p
, target
, CAP_ENCAP
, CAP_CLUSTER
,
343 "ENCAP %s XLINE %d %s 2 :%s", target
, temp_time
, name
, reason
);
346 sendto_match_servs(source_p
, target
, CAP_ENCAP
, NOCAPS
,
347 "ENCAP %s XLINE %d %s %s :%s",
348 target
, temp_time
, name
, type
, reason
);
352 cluster_xline(struct Client
*source_p
, int temp_time
, const char *name
, const char *reason
)
354 struct remote_conf
*shared_p
;
357 RB_DLINK_FOREACH(ptr
, cluster_conf_list
.head
)
359 shared_p
= ptr
->data
;
361 /* old protocol cant handle temps, and we dont really want
362 * to convert them to perm.. --fl
366 if(!(shared_p
->flags
& SHARED_PXLINE
))
369 sendto_match_servs(source_p
, shared_p
->server
, CAP_CLUSTER
, NOCAPS
,
370 "XLINE %s %s 2 :%s", shared_p
->server
, name
, reason
);
371 sendto_match_servs(source_p
, shared_p
->server
, CAP_ENCAP
, CAP_CLUSTER
,
372 "ENCAP %s XLINE 0 %s 2 :%s",
373 shared_p
->server
, name
, reason
);
375 else if(shared_p
->flags
& SHARED_TXLINE
)
376 sendto_match_servs(source_p
, shared_p
->server
, CAP_ENCAP
, NOCAPS
,
377 "ENCAP %s XLINE %d %s 2 :%s",
378 shared_p
->server
, temp_time
, name
, reason
);
384 * parv[1] - thing to unxline
387 mo_unxline(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
389 bool propagated
= true;
391 if(!IsOperXline(source_p
))
393 sendto_one(source_p
, form_str(ERR_NOPRIVS
), me
.name
, source_p
->name
, "xline");
397 if(parc
== 4 && !(irccmp(parv
[2], "ON")))
399 if(!IsOperRemoteBan(source_p
))
401 sendto_one(source_p
, form_str(ERR_NOPRIVS
),
402 me
.name
, source_p
->name
, "remoteban");
406 sendto_realops_snomask(SNO_GENERAL
, L_NETWIDE
, "%s is removing the X-Line for [%s] on %s.",
407 get_oper_name(source_p
), parv
[1], parv
[3]);
409 propagate_generic(source_p
, "UNXLINE", parv
[3], CAP_CLUSTER
, "%s", parv
[1]);
411 if(match(parv
[3], me
.name
) == 0)
416 /* cluster{} moved to remove_xline */
418 remove_xline(source_p
, parv
[1], propagated
);
423 * handles a remote unxline
426 ms_unxline(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
428 /* parv[0] parv[1] parv[2]
429 * oper target server gecos
431 propagate_generic(source_p
, "UNXLINE", parv
[1], CAP_CLUSTER
, "%s", parv
[2]);
433 if(!match(parv
[1], me
.name
))
436 if(!IsPerson(source_p
))
439 handle_remote_unxline(source_p
, parv
[2]);
443 me_unxline(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
446 if(!IsPerson(source_p
))
449 handle_remote_unxline(source_p
, parv
[1]);
453 handle_remote_unxline(struct Client
*source_p
, const char *name
)
455 remove_xline(source_p
, name
, false);
459 remove_xline(struct Client
*source_p
, const char *name
, bool propagated
)
461 struct ConfItem
*aconf
;
465 RB_DLINK_FOREACH(ptr
, xline_conf_list
.head
)
469 if(!irccmp(aconf
->host
, name
))
475 sendto_one_notice(source_p
, ":Cannot remove global X-Line %s on specific servers", name
);
478 if (!lookup_prop_ban(aconf
))
480 sendto_one_notice(source_p
, ":X-Line for [%s] is removed", name
);
481 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
482 "%s has removed the global X-Line for: [%s]",
483 get_oper_name(source_p
), name
);
484 ilog(L_KLINE
, "UX %s %s", get_oper_name(source_p
), name
);
485 now
= rb_current_time();
486 if(aconf
->created
< now
)
487 aconf
->created
= now
;
490 aconf
->hold
= aconf
->created
;
491 operhash_delete(aconf
->info
.oper
);
492 aconf
->info
.oper
= operhash_add(get_oper_name(source_p
));
493 aconf
->flags
|= CONF_FLAGS_MYOPER
| CONF_FLAGS_TEMPORARY
;
494 sendto_server(NULL
, NULL
, CAP_BAN
|CAP_TS6
, NOCAPS
,
495 ":%s BAN X * %s %lu %d %d * :*",
496 source_p
->id
, aconf
->host
,
497 (unsigned long)aconf
->created
,
499 (int)(aconf
->lifetime
- aconf
->created
));
500 remove_reject_mask(aconf
->host
, NULL
);
501 deactivate_conf(aconf
, now
);
504 else if(propagated
&& rb_dlink_list_length(&cluster_conf_list
))
505 cluster_generic(source_p
, "UNXLINE", SHARED_UNXLINE
, CAP_CLUSTER
, "%s", name
);
508 bandb_del(BANDB_XLINE
, aconf
->host
, NULL
);
510 sendto_one_notice(source_p
, ":X-Line for [%s] is removed", aconf
->host
);
511 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
512 "%s has removed the X-Line for: [%s]",
513 get_oper_name(source_p
), aconf
->host
);
514 ilog(L_KLINE
, "UX %s %s", get_oper_name(source_p
), aconf
->host
);
518 sendto_one_notice(source_p
, ":X-Line for [%s] is removed", name
);
519 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
520 "%s has removed the temporary X-Line for: [%s]",
521 get_oper_name(source_p
), name
);
522 ilog(L_KLINE
, "UX %s %s", get_oper_name(source_p
), name
);
525 remove_reject_mask(aconf
->host
, NULL
);
527 rb_dlinkDestroy(ptr
, &xline_conf_list
);
532 if(propagated
&& rb_dlink_list_length(&cluster_conf_list
))
533 cluster_generic(source_p
, "UNXLINE", SHARED_UNXLINE
, CAP_CLUSTER
, "%s", name
);
535 sendto_one_notice(source_p
, ":No X-Line for %s", name
);