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.
51 #include "s_newconf.h"
55 static int mo_xline(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[]);
56 static int ms_xline(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[]);
57 static int me_xline(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[]);
58 static int mo_unxline(struct Client
*client_p
, struct Client
*source_p
, int parc
,
60 static int ms_unxline(struct Client
*client_p
, struct Client
*source_p
, int parc
,
62 static int me_unxline(struct Client
*client_p
, struct Client
*source_p
, int parc
,
65 struct Message xline_msgtab
= {
66 "XLINE", 0, 0, 0, MFLG_SLOW
,
67 {mg_unreg
, mg_not_oper
, {ms_xline
, 5}, {ms_xline
, 5}, {me_xline
, 5}, {mo_xline
, 3}}
70 struct Message unxline_msgtab
= {
71 "UNXLINE", 0, 0, 0, MFLG_SLOW
,
72 {mg_unreg
, mg_not_oper
, {ms_unxline
, 3}, {ms_unxline
, 3}, {me_unxline
, 2}, {mo_unxline
, 2}}
75 mapi_clist_av1 xline_clist
[] = { &xline_msgtab
, &unxline_msgtab
, NULL
};
77 DECLARE_MODULE_AV1(xline
, NULL
, NULL
, xline_clist
, NULL
, NULL
, "$Revision$");
79 static int valid_xline(struct Client
*, const char *, const char *);
80 static void apply_xline(struct Client
*client_p
, const char *name
,
81 const char *reason
, int temp_time
);
82 static void propagate_xline(struct Client
*source_p
, const char *target
,
83 int temp_time
, const char *name
, const char *type
, const char *reason
);
84 static void cluster_xline(struct Client
*source_p
, int temp_time
,
85 const char *name
, const char *reason
);
87 static void handle_remote_xline(struct Client
*source_p
, int temp_time
,
88 const char *name
, const char *reason
);
89 static void handle_remote_unxline(struct Client
*source_p
, const char *name
);
91 static void remove_xline(struct Client
*source_p
, const char *name
);
96 * parv[1] - thing to xline
97 * parv[2] - optional type/reason
101 mo_xline(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
103 struct ConfItem
*aconf
;
106 const char *target_server
= NULL
;
110 if(!IsOperXline(source_p
))
112 sendto_one(source_p
, form_str(ERR_NOPRIVS
), me
.name
, source_p
->name
, "xline");
116 if((temp_time
= valid_temp_time(parv
[loc
])) >= 0)
118 /* we just set temp_time to -1! */
125 /* XLINE <gecos> ON <server> :<reason> */
126 if(parc
>= loc
+ 2 && !irccmp(parv
[loc
], "ON"))
128 if(!IsOperRemoteBan(source_p
))
130 sendto_one(source_p
, form_str(ERR_NOPRIVS
),
131 me
.name
, source_p
->name
, "remoteban");
135 target_server
= parv
[loc
+ 1];
139 if(parc
<= loc
|| EmptyString(parv
[loc
]))
141 sendto_one(source_p
, form_str(ERR_NEEDMOREPARAMS
),
142 me
.name
, source_p
->name
, "XLINE");
148 if(target_server
!= NULL
)
150 propagate_xline(source_p
, target_server
, temp_time
, name
, "2", reason
);
152 if(!match(target_server
, me
.name
))
155 else if(rb_dlink_list_length(&cluster_conf_list
) > 0)
156 cluster_xline(source_p
, temp_time
, name
, reason
);
158 if((aconf
= find_xline_mask(name
)) != NULL
)
160 sendto_one(source_p
, ":%s NOTICE %s :[%s] already X-Lined by [%s] - %s",
161 me
.name
, source_p
->name
, name
, aconf
->host
, aconf
->passwd
);
165 if(!valid_xline(source_p
, name
, reason
))
168 apply_xline(source_p
, name
, reason
, temp_time
);
175 * handles a remote xline
178 ms_xline(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
180 /* parv[0] parv[1] parv[2] parv[3] parv[4]
181 * oper target serv xline type reason
183 propagate_xline(source_p
, parv
[1], 0, parv
[2], parv
[3], parv
[4]);
185 if(!IsPerson(source_p
))
188 /* destined for me? */
189 if(!match(parv
[1], me
.name
))
192 handle_remote_xline(source_p
, 0, parv
[2], parv
[4]);
197 me_xline(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
199 /* time name type :reason */
200 if(!IsPerson(source_p
))
203 handle_remote_xline(source_p
, atoi(parv
[1]), parv
[2], parv
[4]);
208 handle_remote_xline(struct Client
*source_p
, int temp_time
, const char *name
, const char *reason
)
210 struct ConfItem
*aconf
;
212 if(!find_shared_conf(source_p
->username
, source_p
->host
,
213 source_p
->servptr
->name
,
214 (temp_time
> 0) ? SHARED_TXLINE
: SHARED_PXLINE
))
217 if(!valid_xline(source_p
, name
, reason
))
221 if((aconf
= find_xline_mask(name
)) != NULL
)
223 sendto_one_notice(source_p
, ":[%s] already X-Lined by [%s] - %s", name
, aconf
->host
,
228 apply_xline(source_p
, name
, reason
, temp_time
);
233 * inputs - client xlining, gecos, reason and whether to warn
235 * side effects - checks the xline for validity, erroring if needed
238 valid_xline(struct Client
*source_p
, const char *gecos
, const char *reason
)
240 if(EmptyString(reason
))
242 sendto_one(source_p
, form_str(ERR_NEEDMOREPARAMS
),
243 get_id(&me
, source_p
), get_id(source_p
, source_p
), "XLINE");
247 if(strchr(reason
, ':') != NULL
)
249 sendto_one_notice(source_p
, ":Invalid character ':' in comment");
253 if(strchr(reason
, '"'))
255 sendto_one_notice(source_p
, ":Invalid character '\"' in comment");
259 if(!valid_wild_card_simple(gecos
))
261 sendto_one_notice(source_p
,
262 ":Please include at least %d non-wildcard "
263 "characters with the xline",
264 ConfigFileEntry
.min_nonwildcard_simple
);
272 apply_xline(struct Client
*source_p
, const char *name
, const char *reason
, int temp_time
)
274 struct ConfItem
*aconf
;
277 aconf
->status
= CONF_XLINE
;
279 if(strstr(name
, "\\s"))
281 char *tmp
= LOCAL_COPY(name
);
287 if(*orig
== '\\' && *(orig
+ 1) != '\0')
289 if(*(orig
+ 1) == 's')
294 /* otherwise skip that and the escaped
295 * character after it, so we dont mistake
309 aconf
->host
= rb_strdup(tmp
);
312 aconf
->host
= rb_strdup(name
);
314 aconf
->passwd
= rb_strdup(reason
);
315 collapse(aconf
->host
);
319 aconf
->hold
= rb_current_time() + temp_time
;
321 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
322 "%s added temporary %d min. X-Line for [%s] [%s]",
323 get_oper_name(source_p
), temp_time
/ 60,
324 aconf
->host
, reason
);
325 ilog(L_KLINE
, "X %s %d %s %s",
326 get_oper_name(source_p
), temp_time
/ 60, name
, reason
);
327 sendto_one_notice(source_p
, ":Added temporary %d min. X-Line [%s]",
328 temp_time
/ 60, aconf
->host
);
332 sendto_realops_snomask(SNO_GENERAL
, L_ALL
, "%s added X-Line for [%s] [%s]",
333 get_oper_name(source_p
), aconf
->host
, aconf
->passwd
);
334 sendto_one_notice(source_p
, ":Added X-Line for [%s] [%s]",
335 aconf
->host
, aconf
->passwd
);
337 bandb_add(BANDB_XLINE
, source_p
, aconf
->host
, NULL
, aconf
->passwd
, NULL
, 0);
338 ilog(L_KLINE
, "X %s 0 %s %s", get_oper_name(source_p
), name
, aconf
->passwd
);
341 rb_dlinkAddAlloc(aconf
, &xline_conf_list
);
346 propagate_xline(struct Client
*source_p
, const char *target
,
347 int temp_time
, const char *name
, const char *type
, const char *reason
)
351 sendto_match_servs(source_p
, target
, CAP_CLUSTER
, NOCAPS
,
352 "XLINE %s %s %s :%s", target
, name
, type
, reason
);
353 sendto_match_servs(source_p
, target
, CAP_ENCAP
, CAP_CLUSTER
,
354 "ENCAP %s XLINE %d %s 2 :%s", target
, temp_time
, name
, reason
);
357 sendto_match_servs(source_p
, target
, CAP_ENCAP
, NOCAPS
,
358 "ENCAP %s XLINE %d %s %s :%s",
359 target
, temp_time
, name
, type
, reason
);
363 cluster_xline(struct Client
*source_p
, int temp_time
, const char *name
, const char *reason
)
365 struct remote_conf
*shared_p
;
368 RB_DLINK_FOREACH(ptr
, cluster_conf_list
.head
)
370 shared_p
= ptr
->data
;
372 /* old protocol cant handle temps, and we dont really want
373 * to convert them to perm.. --fl
377 if(!(shared_p
->flags
& SHARED_PXLINE
))
380 sendto_match_servs(source_p
, shared_p
->server
, CAP_CLUSTER
, NOCAPS
,
381 "XLINE %s %s 2 :%s", shared_p
->server
, name
, reason
);
382 sendto_match_servs(source_p
, shared_p
->server
, CAP_ENCAP
, CAP_CLUSTER
,
383 "ENCAP %s XLINE 0 %s 2 :%s",
384 shared_p
->server
, name
, reason
);
386 else if(shared_p
->flags
& SHARED_TXLINE
)
387 sendto_match_servs(source_p
, shared_p
->server
, CAP_ENCAP
, NOCAPS
,
388 "ENCAP %s XLINE %d %s 2 :%s",
389 shared_p
->server
, temp_time
, name
, reason
);
395 * parv[1] - thing to unxline
398 mo_unxline(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
400 if(!IsOperXline(source_p
))
402 sendto_one(source_p
, form_str(ERR_NOPRIVS
), me
.name
, source_p
->name
, "xline");
406 if(parc
== 4 && !(irccmp(parv
[2], "ON")))
408 if(!IsOperRemoteBan(source_p
))
410 sendto_one(source_p
, form_str(ERR_NOPRIVS
),
411 me
.name
, source_p
->name
, "remoteban");
415 propagate_generic(source_p
, "UNXLINE", parv
[3], CAP_CLUSTER
, "%s", parv
[1]);
417 if(match(parv
[3], me
.name
) == 0)
420 else if(rb_dlink_list_length(&cluster_conf_list
))
421 cluster_generic(source_p
, "UNXLINE", SHARED_UNXLINE
, CAP_CLUSTER
, "%s", parv
[1]);
423 remove_xline(source_p
, parv
[1]);
430 * handles a remote unxline
433 ms_unxline(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
435 /* parv[0] parv[1] parv[2]
436 * oper target server gecos
438 propagate_generic(source_p
, "UNXLINE", parv
[1], CAP_CLUSTER
, "%s", parv
[2]);
440 if(!match(parv
[1], me
.name
))
443 if(!IsPerson(source_p
))
446 handle_remote_unxline(source_p
, parv
[2]);
451 me_unxline(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
454 if(!IsPerson(source_p
))
457 handle_remote_unxline(source_p
, parv
[1]);
462 handle_remote_unxline(struct Client
*source_p
, const char *name
)
464 if(!find_shared_conf(source_p
->username
, source_p
->host
,
465 source_p
->servptr
->name
, SHARED_UNXLINE
))
468 remove_xline(source_p
, name
);
474 remove_xline(struct Client
*source_p
, const char *name
)
476 struct ConfItem
*aconf
;
479 RB_DLINK_FOREACH(ptr
, xline_conf_list
.head
)
483 if(!irccmp(aconf
->host
, name
))
487 bandb_del(BANDB_XLINE
, aconf
->host
, NULL
);
489 sendto_one_notice(source_p
, ":X-Line for [%s] is removed", aconf
->host
);
490 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
491 "%s has removed the X-Line for: [%s]",
492 get_oper_name(source_p
), aconf
->host
);
493 ilog(L_KLINE
, "UX %s %s", get_oper_name(source_p
), aconf
->host
);
497 sendto_one_notice(source_p
, ":X-Line for [%s] is removed", name
);
498 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
499 "%s has removed the temporary X-Line for: [%s]",
500 get_oper_name(source_p
), name
);
501 ilog(L_KLINE
, "UX %s %s", get_oper_name(source_p
), name
);
504 remove_reject_mask(aconf
->host
, NULL
);
506 rb_dlinkDestroy(ptr
, &xline_conf_list
);
511 sendto_one_notice(source_p
, ":No X-Line for %s", name
);