]> jfr.im git - irc/rqf/shadowircd.git/blame - modules/m_kline.c
Fix --disable-balloc.
[irc/rqf/shadowircd.git] / modules / m_kline.c
CommitLineData
212380e3 1/*
2 * ircd-ratbox: A slightly useful ircd.
3 * m_kline.c: Bans/unbans a user.
4 *
5 * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6 * Copyright (C) 1996-2002 Hybrid Development Team
7 * Copyright (C) 2002-2005 ircd-ratbox development team
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 * USA
23 *
d8a4c5f6 24 * $Id$
212380e3 25 */
26
27#include "stdinc.h"
212380e3 28#include "channel.h"
29#include "class.h"
30#include "client.h"
31#include "common.h"
13ae2f4b 32#include "match.h"
212380e3 33#include "ircd.h"
34#include "hostmask.h"
35#include "numeric.h"
212380e3 36#include "s_conf.h"
37#include "s_newconf.h"
d3455e2c 38#include "logger.h"
212380e3 39#include "send.h"
40#include "hash.h"
41#include "s_serv.h"
42#include "msg.h"
43#include "parse.h"
44#include "modules.h"
35f6f850 45#include "reject.h"
d8a4c5f6 46#include "bandbi.h"
a0f4c418 47#include "operhash.h"
212380e3 48
49static int mo_kline(struct Client *, struct Client *, int, const char **);
50static int ms_kline(struct Client *, struct Client *, int, const char **);
51static int me_kline(struct Client *, struct Client *, int, const char **);
52static int mo_unkline(struct Client *, struct Client *, int, const char **);
53static int ms_unkline(struct Client *, struct Client *, int, const char **);
54static int me_unkline(struct Client *, struct Client *, int, const char **);
55
56struct Message kline_msgtab = {
57 "KLINE", 0, 0, 0, MFLG_SLOW,
58 {mg_unreg, mg_not_oper, {ms_kline, 5}, {ms_kline, 5}, {me_kline, 5}, {mo_kline, 3}}
59};
60
61struct Message unkline_msgtab = {
62 "UNKLINE", 0, 0, 0, MFLG_SLOW,
63 {mg_unreg, mg_not_oper, {ms_unkline, 4}, {ms_unkline, 4}, {me_unkline, 3}, {mo_unkline, 2}}
64};
65
66mapi_clist_av1 kline_clist[] = { &kline_msgtab, &unkline_msgtab, NULL };
d8a4c5f6
WP
67
68DECLARE_MODULE_AV1(kline, NULL, NULL, kline_clist, NULL, NULL, "$Revision$");
212380e3 69
70/* Local function prototypes */
71static int find_user_host(struct Client *source_p, const char *userhost, char *user, char *host);
72static int valid_comment(struct Client *source_p, char *comment);
73static int valid_user_host(struct Client *source_p, const char *user, const char *host);
74static int valid_wild_card(struct Client *source_p, const char *user, const char *host);
75
76static void handle_remote_kline(struct Client *source_p, int tkline_time,
d8a4c5f6 77 const char *user, const char *host, const char *reason);
212380e3 78static void apply_kline(struct Client *source_p, struct ConfItem *aconf,
ce60772d 79 const char *reason, const char *oper_reason);
212380e3 80static void apply_tkline(struct Client *source_p, struct ConfItem *aconf,
ce60772d 81 const char *, const char *, int);
212380e3 82static int already_placed_kline(struct Client *, const char *, const char *, int);
83
d8a4c5f6 84static void handle_remote_unkline(struct Client *source_p, const char *user, const char *host);
40a1d446 85static void remove_permkline_match(struct Client *, struct ConfItem *);
4c171a9c 86static int remove_temp_kline(struct Client *, struct ConfItem *);
212380e3 87
88/* mo_kline()
89 *
90 * parv[1] - temp time or user@host
91 * parv[2] - user@host, "ON", or reason
92 * parv[3] - "ON", reason, or server to target
93 * parv[4] - server to target, or reason
94 * parv[5] - reason
95 */
96static int
d8a4c5f6 97mo_kline(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
212380e3 98{
d8a4c5f6 99 char def[] = "No Reason";
212380e3 100 char user[USERLEN + 2];
101 char host[HOSTLEN + 2];
d8a4c5f6 102 char *reason = def;
212380e3 103 char *oper_reason;
212380e3 104 const char *target_server = NULL;
105 struct ConfItem *aconf;
106 int tkline_time = 0;
107 int loc = 1;
108
109 if(!IsOperK(source_p))
110 {
d8a4c5f6 111 sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "kline");
212380e3 112 return 0;
113 }
114
115 if((tkline_time = valid_temp_time(parv[loc])) >= 0)
116 loc++;
117 /* we just set tkline_time to -1! */
118 else
119 tkline_time = 0;
120
121 if(find_user_host(source_p, parv[loc], user, host) == 0)
122 return 0;
123
124 loc++;
125
d8a4c5f6 126 if(parc >= loc + 2 && !irccmp(parv[loc], "ON"))
212380e3 127 {
128 if(!IsOperRemoteBan(source_p))
129 {
130 sendto_one(source_p, form_str(ERR_NOPRIVS),
d8a4c5f6 131 me.name, source_p->name, "remoteban");
212380e3 132 return 0;
133 }
134
d8a4c5f6 135 target_server = parv[loc + 1];
212380e3 136 loc += 2;
137 }
138
139 if(parc <= loc || EmptyString(parv[loc]))
140 {
141 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
142 me.name, source_p->name, "KLINE");
143 return 0;
144 }
145
146 reason = LOCAL_COPY(parv[loc]);
147
148 if(target_server != NULL)
149 {
150 propagate_generic(source_p, "KLINE", target_server, CAP_KLN,
d8a4c5f6 151 "%d %s %s :%s", tkline_time, user, host, reason);
212380e3 152
153 /* If we are sending it somewhere that doesnt include us, stop */
154 if(!match(target_server, me.name))
155 return 0;
156 }
157 /* if we have cluster servers, send it to them.. */
08d11e34 158 else if(rb_dlink_list_length(&cluster_conf_list) > 0)
d8a4c5f6 159 cluster_generic(source_p, "KLINE",
212380e3 160 (tkline_time > 0) ? SHARED_TKLINE : SHARED_PKLINE, CAP_KLN,
d8a4c5f6 161 "%lu %s %s :%s", tkline_time, user, host, reason);
212380e3 162
d8a4c5f6
WP
163 if(!valid_user_host(source_p, user, host) ||
164 !valid_wild_card(source_p, user, host) || !valid_comment(source_p, reason))
212380e3 165 return 0;
166
167 if(already_placed_kline(source_p, user, host, tkline_time))
168 return 0;
169
4362b282 170 rb_set_time();
212380e3 171 aconf = make_conf();
172 aconf->status = CONF_KILL;
ce60772d 173 aconf->created = rb_current_time();
62d28946
VY
174 aconf->host = rb_strdup(host);
175 aconf->user = rb_strdup(user);
212380e3 176 aconf->port = 0;
157c1f04 177 aconf->passwd = rb_strdup(reason);
a0f4c418 178 aconf->info.oper = operhash_add(get_oper_name(source_p));
212380e3 179
180 /* Look for an oper reason */
181 if((oper_reason = strchr(reason, '|')) != NULL)
182 {
183 *oper_reason = '\0';
184 oper_reason++;
185
186 if(!EmptyString(oper_reason))
62d28946 187 aconf->spasswd = rb_strdup(oper_reason);
212380e3 188 }
189
190 if(tkline_time > 0)
ce60772d 191 apply_tkline(source_p, aconf, reason, oper_reason, tkline_time);
212380e3 192 else
ce60772d 193 apply_kline(source_p, aconf, reason, oper_reason);
212380e3 194
195 if(ConfigFileEntry.kline_delay)
196 {
197 if(kline_queued == 0)
198 {
bfccb2c0 199 rb_event_addonce("check_klines", check_klines_event, NULL,
d8a4c5f6 200 ConfigFileEntry.kline_delay);
212380e3 201 kline_queued = 1;
202 }
203 }
204 else
205 check_klines();
206
207 return 0;
208}
209
210/* ms_kline()
211 *
212 * parv[1] - server targeted at
213 * parv[2] - tkline time (0 if perm)
214 * parv[3] - user
215 * parv[4] - host
216 * parv[5] - reason
217 */
218static int
219ms_kline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
220{
221 int tkline_time = atoi(parv[2]);
222
223 /* 1.5-3 and earlier contains a bug that allows remote klines to be
224 * sent with an empty reason field. This is a protocol violation,
225 * but its not worth dropping the link over.. --anfl
226 */
227 if(parc < 6 || EmptyString(parv[5]))
228 return 0;
229
230 propagate_generic(source_p, "KLINE", parv[1], CAP_KLN,
d8a4c5f6 231 "%d %s %s :%s", tkline_time, parv[3], parv[4], parv[5]);
212380e3 232
233 if(!match(parv[1], me.name))
234 return 0;
235
236 if(!IsPerson(source_p))
237 return 0;
238
239 handle_remote_kline(source_p, tkline_time, parv[3], parv[4], parv[5]);
240 return 0;
241}
242
243static int
244me_kline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
245{
246 /* <tkline_time> <user> <host> :<reason> */
247 if(!IsPerson(source_p))
248 return 0;
249
250 handle_remote_kline(source_p, atoi(parv[1]), parv[2], parv[3], parv[4]);
251 return 0;
252}
253
254static void
255handle_remote_kline(struct Client *source_p, int tkline_time,
d8a4c5f6 256 const char *user, const char *host, const char *kreason)
212380e3 257{
212380e3 258 char *reason = LOCAL_COPY(kreason);
259 struct ConfItem *aconf = NULL;
260 char *oper_reason;
261
262 if(!find_shared_conf(source_p->username, source_p->host,
d8a4c5f6
WP
263 source_p->servptr->name,
264 (tkline_time > 0) ? SHARED_TKLINE : SHARED_PKLINE))
212380e3 265 return;
266
267 if(!valid_user_host(source_p, user, host) ||
d8a4c5f6 268 !valid_wild_card(source_p, user, host) || !valid_comment(source_p, reason))
212380e3 269 return;
270
271 if(already_placed_kline(source_p, user, host, tkline_time))
272 return;
273
274 aconf = make_conf();
275
276 aconf->status = CONF_KILL;
ce60772d 277 aconf->created = rb_current_time();
62d28946
VY
278 aconf->user = rb_strdup(user);
279 aconf->host = rb_strdup(host);
157c1f04 280 aconf->passwd = rb_strdup(reason);
a0f4c418 281 aconf->info.oper = operhash_add(get_oper_name(source_p));
212380e3 282
283 /* Look for an oper reason */
284 if((oper_reason = strchr(reason, '|')) != NULL)
285 {
286 *oper_reason = '\0';
287 oper_reason++;
288
289 if(!EmptyString(oper_reason))
62d28946 290 aconf->spasswd = rb_strdup(oper_reason);
212380e3 291 }
292
212380e3 293 if(tkline_time > 0)
ce60772d 294 apply_tkline(source_p, aconf, reason, oper_reason, tkline_time);
212380e3 295 else
ce60772d 296 apply_kline(source_p, aconf, reason, oper_reason);
212380e3 297
298 if(ConfigFileEntry.kline_delay)
299 {
300 if(kline_queued == 0)
301 {
bfccb2c0 302 rb_event_addonce("check_klines", check_klines_event, NULL,
d8a4c5f6 303 ConfigFileEntry.kline_delay);
212380e3 304 kline_queued = 1;
305 }
306 }
307 else
308 check_klines();
309
310 return;
311}
312
313/* mo_unkline()
314 *
315 * parv[1] - kline to remove
316 * parv[2] - optional "ON"
317 * parv[3] - optional target server
318 */
319static int
320mo_unkline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
321{
322 const char *user;
323 char *host;
324 char splat[] = "*";
325 char *h = LOCAL_COPY(parv[1]);
40a1d446 326 struct ConfItem *aconf;
212380e3 327
328 if(!IsOperUnkline(source_p))
329 {
d8a4c5f6 330 sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "unkline");
212380e3 331 return 0;
332 }
333
334 if((host = strchr(h, '@')) || *h == '*' || strchr(h, '.') || strchr(h, ':'))
335 {
336 /* Explicit user@host mask given */
337
338 if(host) /* Found user@host */
339 {
340 *host++ = '\0';
341
342 /* check for @host */
343 if(*h)
344 user = h;
345 else
346 user = splat;
347
348 /* check for user@ */
349 if(!*host)
350 host = splat;
351 }
352 else
353 {
354 user = splat; /* no @ found, assume its *@somehost */
355 host = h;
356 }
357 }
358 else
359 {
5366977b 360 sendto_one_notice(source_p, ":Invalid parameters");
212380e3 361 return 0;
362 }
363
364 /* possible remote kline.. */
365 if((parc > 3) && (irccmp(parv[2], "ON") == 0))
366 {
367 if(!IsOperRemoteBan(source_p))
368 {
369 sendto_one(source_p, form_str(ERR_NOPRIVS),
d8a4c5f6 370 me.name, source_p->name, "remoteban");
212380e3 371 return 0;
372 }
373
d8a4c5f6 374 propagate_generic(source_p, "UNKLINE", parv[3], CAP_UNKLN, "%s %s", user, host);
212380e3 375
376 if(match(parv[3], me.name) == 0)
377 return 0;
378 }
08d11e34 379 else if(rb_dlink_list_length(&cluster_conf_list) > 0)
212380e3 380 cluster_generic(source_p, "UNKLINE", SHARED_UNKLINE, CAP_UNKLN,
381 "%s %s", user, host);
382
40a1d446
JT
383 aconf = find_exact_conf_by_address(host, CONF_KILL, user);
384 if(aconf == NULL)
385 {
386 sendto_one_notice(source_p, ":No K-Line for %s@%s", user, host);
387 return 0;
388 }
389
4c171a9c 390 if(remove_temp_kline(source_p, aconf))
212380e3 391 return 0;
212380e3 392
40a1d446 393 remove_permkline_match(source_p, aconf);
212380e3 394
395 return 0;
396}
397
398/* ms_unkline()
399 *
400 * parv[1] - target server
401 * parv[2] - user to unkline
402 * parv[3] - host to unkline
403 */
404static int
405ms_unkline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
406{
d8a4c5f6
WP
407 /* parv[0] parv[1] parv[2] parv[3]
408 * oper target server user host */
409 propagate_generic(source_p, "UNKLINE", parv[1], CAP_UNKLN, "%s %s", parv[2], parv[3]);
212380e3 410
411 if(!match(parv[1], me.name))
412 return 0;
413
414 if(!IsPerson(source_p))
415 return 0;
416
417 handle_remote_unkline(source_p, parv[2], parv[3]);
418 return 0;
419}
420
421static int
422me_unkline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
423{
424 /* user host */
425 if(!IsPerson(source_p))
426 return 0;
427
428 handle_remote_unkline(source_p, parv[1], parv[2]);
429 return 0;
430}
431
432static void
433handle_remote_unkline(struct Client *source_p, const char *user, const char *host)
434{
40a1d446
JT
435 struct ConfItem *aconf;
436
212380e3 437 if(!find_shared_conf(source_p->username, source_p->host,
d8a4c5f6 438 source_p->servptr->name, SHARED_UNKLINE))
212380e3 439 return;
440
40a1d446
JT
441 aconf = find_exact_conf_by_address(host, CONF_KILL, user);
442 if(aconf == NULL)
443 {
444 sendto_one_notice(source_p, ":No K-Line for %s@%s", user, host);
445 return;
446 }
447
4c171a9c 448 if(remove_temp_kline(source_p, aconf))
212380e3 449 return;
212380e3 450
40a1d446 451 remove_permkline_match(source_p, aconf);
212380e3 452}
453
454/* apply_kline()
455 *
456 * inputs -
457 * output - NONE
458 * side effects - kline as given, is added to the hashtable
459 * and conf file
460 */
461static void
462apply_kline(struct Client *source_p, struct ConfItem *aconf,
ce60772d 463 const char *reason, const char *oper_reason)
212380e3 464{
969a1ae6 465 add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf);
d8a4c5f6
WP
466 bandb_add(BANDB_KLINE, source_p, aconf->user, aconf->host,
467 reason, EmptyString(oper_reason) ? NULL : oper_reason, 0);
d63447bf
WP
468
469 /* no oper reason.. */
470 if(EmptyString(oper_reason))
471 {
472 sendto_realops_snomask(SNO_GENERAL, L_ALL,
473 "%s added K-Line for [%s@%s] [%s]",
474 get_oper_name(source_p), aconf->user, aconf->host, reason);
475 ilog(L_KLINE, "K %s 0 %s %s %s",
476 get_oper_name(source_p), aconf->user, aconf->host, reason);
477 }
478 else
479 {
480 sendto_realops_snomask(SNO_GENERAL, L_ALL,
481 "%s added K-Line for [%s@%s] [%s|%s]",
482 get_oper_name(source_p), aconf->user, aconf->host,
483 reason, oper_reason);
484 ilog(L_KLINE, "K %s 0 %s %s %s|%s",
485 get_oper_name(source_p), aconf->user, aconf->host, reason, oper_reason);
486 }
487
488 sendto_one_notice(source_p, ":Added K-Line [%s@%s]",
489 aconf->user, aconf->host);
212380e3 490}
491
492/* apply_tkline()
493 *
494 * inputs -
495 * output - NONE
496 * side effects - tkline as given is placed
497 */
498static void
499apply_tkline(struct Client *source_p, struct ConfItem *aconf,
ce60772d 500 const char *reason, const char *oper_reason, int tkline_time)
212380e3 501{
9f6bbe3c 502 aconf->hold = rb_current_time() + tkline_time;
212380e3 503 add_temp_kline(aconf);
504
505 /* no oper reason.. */
506 if(EmptyString(oper_reason))
507 {
508 sendto_realops_snomask(SNO_GENERAL, L_ALL,
d8a4c5f6
WP
509 "%s added temporary %d min. K-Line for [%s@%s] [%s]",
510 get_oper_name(source_p), tkline_time / 60,
511 aconf->user, aconf->host, reason);
212380e3 512 ilog(L_KLINE, "K %s %d %s %s %s",
d8a4c5f6 513 get_oper_name(source_p), tkline_time / 60, aconf->user, aconf->host, reason);
212380e3 514 }
515 else
516 {
517 sendto_realops_snomask(SNO_GENERAL, L_ALL,
d8a4c5f6
WP
518 "%s added temporary %d min. K-Line for [%s@%s] [%s|%s]",
519 get_oper_name(source_p), tkline_time / 60,
520 aconf->user, aconf->host, reason, oper_reason);
212380e3 521 ilog(L_KLINE, "K %s %d %s %s %s|%s",
d8a4c5f6
WP
522 get_oper_name(source_p), tkline_time / 60,
523 aconf->user, aconf->host, reason, oper_reason);
212380e3 524 }
525
526 sendto_one_notice(source_p, ":Added temporary %d min. K-Line [%s@%s]",
527 tkline_time / 60, aconf->user, aconf->host);
528}
529
530/* find_user_host()
531 *
532 * inputs - client placing kline, user@host, user buffer, host buffer
533 * output - 0 if not ok to kline, 1 to kline i.e. if valid user host
534 * side effects -
535 */
536static int
537find_user_host(struct Client *source_p, const char *userhost, char *luser, char *lhost)
538{
539 char *hostp;
540
541 hostp = strchr(userhost, '@');
d8a4c5f6 542
212380e3 543 if(hostp != NULL) /* I'm a little user@host */
544 {
545 *(hostp++) = '\0'; /* short and squat */
546 if(*userhost)
907468c4 547 rb_strlcpy(luser, userhost, USERLEN + 1); /* here is my user */
212380e3 548 else
549 strcpy(luser, "*");
550 if(*hostp)
907468c4 551 rb_strlcpy(lhost, hostp, HOSTLEN + 1); /* here is my host */
212380e3 552 else
553 strcpy(lhost, "*");
d8a4c5f6 554 }
212380e3 555 else
556 {
557 /* no '@', no '.', so its not a user@host or host, therefore
558 * its a nick, which support was removed for.
559 */
560 if(strchr(userhost, '.') == NULL && strchr(userhost, ':') == NULL)
1dc9ac1d
JT
561 {
562 sendto_one_notice(source_p, ":K-Line must be a user@host or host");
212380e3 563 return 0;
1dc9ac1d 564 }
212380e3 565
566 luser[0] = '*'; /* no @ found, assume its *@somehost */
567 luser[1] = '\0';
907468c4 568 rb_strlcpy(lhost, userhost, HOSTLEN + 1);
212380e3 569 }
570
571 return 1;
572}
573
574/* valid_user_host()
575 *
576 * inputs - user buffer, host buffer
577 * output - 0 if invalid, 1 if valid
578 * side effects -
579 */
580static int
581valid_user_host(struct Client *source_p, const char *luser, const char *lhost)
582{
d8a4c5f6
WP
583 /* # is invalid, as are '!' (n!u@h kline) and '@' (u@@h kline) */
584 if(strchr(lhost, '#') || strchr(luser, '#') || strchr(luser, '!') || strchr(lhost, '@'))
212380e3 585 {
586 sendto_one_notice(source_p, ":Invalid K-Line");
587 return 0;
588 }
589
590 return 1;
591}
592
593/* valid_wild_card()
594 *
595 * input - user buffer, host buffer
596 * output - 0 if invalid, 1 if valid
597 * side effects -
598 */
599static int
600valid_wild_card(struct Client *source_p, const char *luser, const char *lhost)
601{
602 const char *p;
603 char tmpch;
604 int nonwild = 0;
88a2a148 605 int bitlen;
212380e3 606
598ebb42 607 /* user has no wildcards, always accept -- jilles */
d8a4c5f6 608 if(!strchr(luser, '?') && !strchr(luser, '*'))
598ebb42 609 return 1;
610
212380e3 611 /* check there are enough non wildcard chars */
612 p = luser;
d8a4c5f6 613 while((tmpch = *p++))
212380e3 614 {
615 if(!IsKWildChar(tmpch))
616 {
617 /* found enough chars, return */
618 if(++nonwild >= ConfigFileEntry.min_nonwildcard)
619 return 1;
620 }
621 }
622
623 /* try host, as user didnt contain enough */
88a2a148 624 /* special case for cidr masks -- jilles */
d8a4c5f6 625 if((p = strrchr(lhost, '/')) != NULL && IsDigit(p[1]))
212380e3 626 {
88a2a148 627 bitlen = atoi(p + 1);
628 /* much like non-cidr for ipv6, rather arbitrary for ipv4 */
d8a4c5f6
WP
629 if(bitlen > 0
630 && bitlen >=
631 (strchr(lhost, ':') ? 4 * (ConfigFileEntry.min_nonwildcard - nonwild) : 6 -
632 2 * nonwild))
88a2a148 633 return 1;
634 }
635 else
636 {
637 p = lhost;
d8a4c5f6 638 while((tmpch = *p++))
88a2a148 639 {
640 if(!IsKWildChar(tmpch))
641 if(++nonwild >= ConfigFileEntry.min_nonwildcard)
642 return 1;
643 }
212380e3 644 }
645
646 sendto_one_notice(source_p,
d8a4c5f6
WP
647 ":Please include at least %d non-wildcard "
648 "characters with the user@host", ConfigFileEntry.min_nonwildcard);
212380e3 649 return 0;
650}
651
652/*
653 * valid_comment
654 * inputs - pointer to client
655 * - pointer to comment
656 * output - 0 if no valid comment, 1 if valid
657 * side effects - NONE
658 */
659static int
660valid_comment(struct Client *source_p, char *comment)
661{
662 if(strchr(comment, '"'))
663 {
664 sendto_one_notice(source_p, ":Invalid character '\"' in comment");
665 return 0;
666 }
667
61569b65 668 if(strlen(comment) > BANREASONLEN)
669 comment[BANREASONLEN] = '\0';
212380e3 670
671 return 1;
672}
673
674/* already_placed_kline()
675 *
676 * inputs - source to notify, user@host to check, tkline time
677 * outputs - 1 if a perm kline or a tkline when a tkline is being
678 * set exists, else 0
679 * side effects - notifies source_p kline exists
680 */
681/* Note: This currently works if the new K-line is a special case of an
682 * existing K-line, but not the other way round. To do that we would
683 * have to walk the hash and check every existing K-line. -A1kmm.
684 */
685static int
686already_placed_kline(struct Client *source_p, const char *luser, const char *lhost, int tkline)
687{
df7a3250 688 const char *reason, *p;
3ea5fee7 689 struct rb_sockaddr_storage iphost, *piphost;
212380e3 690 struct ConfItem *aconf;
d8a4c5f6 691 int t, bits;
df7a3250
JT
692
693 aconf = find_exact_conf_by_address(lhost, CONF_KILL, luser);
d8a4c5f6 694 if(aconf == NULL && ConfigFileEntry.non_redundant_klines)
212380e3 695 {
df7a3250 696 bits = 0;
d8a4c5f6 697 if((t = parse_netmask(lhost, (struct sockaddr *) &iphost, &bits)) != HM_HOST)
212380e3 698 {
2c2e0aa9 699#ifdef RB_IPV6
212380e3 700 if(t == HM_IPV6)
701 t = AF_INET6;
702 else
703#endif
704 t = AF_INET;
d8a4c5f6 705
212380e3 706 piphost = &iphost;
707 }
708 else
709 piphost = NULL;
710
d8a4c5f6
WP
711 aconf = find_conf_by_address(lhost, NULL, NULL, (struct sockaddr *) piphost,
712 CONF_KILL, t, luser, NULL);
713 if(aconf != NULL)
212380e3 714 {
df7a3250
JT
715 /* The above was really a lookup of a single IP,
716 * so check if the new kline is wider than the
717 * existing one.
718 * -- jilles
719 */
720 p = strchr(aconf->host, '/');
d8a4c5f6 721 if(bits > 0 && (p == NULL || bits < atoi(p + 1)))
df7a3250
JT
722 aconf = NULL;
723 }
724 }
d8a4c5f6 725 if(aconf != NULL)
df7a3250
JT
726 {
727 /* setting a tkline, or existing one is perm */
728 if(tkline || ((aconf->flags & CONF_FLAGS_TEMPORARY) == 0))
729 {
730 reason = aconf->passwd ? aconf->passwd : "<No Reason>";
731
732 sendto_one_notice(source_p,
733 ":[%s@%s] already K-Lined by [%s@%s] - %s",
d8a4c5f6 734 luser, lhost, aconf->user, aconf->host, reason);
df7a3250 735 return 1;
212380e3 736 }
737 }
738
739 return 0;
740}
741
742/* remove_permkline_match()
743 *
744 * hunts for a permanent kline, and removes it.
745 */
746static void
40a1d446 747remove_permkline_match(struct Client *source_p, struct ConfItem *aconf)
212380e3 748{
d8a4c5f6 749 sendto_one_notice(source_p, ":K-Line for [%s@%s] is removed", aconf->user, aconf->host);
212380e3 750
751 sendto_realops_snomask(SNO_GENERAL, L_ALL,
d8a4c5f6
WP
752 "%s has removed the K-Line for: [%s@%s]",
753 get_oper_name(source_p), aconf->user, aconf->host);
212380e3 754
d8a4c5f6 755 ilog(L_KLINE, "UK %s %s %s", get_oper_name(source_p), aconf->user, aconf->host);
40a1d446 756
21c9d815 757 remove_reject_mask(aconf->user, aconf->host);
d8a4c5f6 758 bandb_del(BANDB_KLINE, aconf->user, aconf->host);
40a1d446
JT
759 delete_one_address_conf(aconf->host, aconf);
760
212380e3 761 return;
762}
763
212380e3 764/* remove_temp_kline()
765 *
766 * inputs - username, hostname to unkline
767 * outputs -
768 * side effects - tries to unkline anything that matches
769 */
770static int
4c171a9c 771remove_temp_kline(struct Client *source_p, struct ConfItem *aconf)
212380e3 772{
08d11e34 773 rb_dlink_node *ptr;
212380e3 774 int i;
775
d8a4c5f6 776 for(i = 0; i < LAST_TEMP_TYPE; i++)
212380e3 777 {
08d11e34 778 RB_DLINK_FOREACH(ptr, temp_klines[i].head)
212380e3 779 {
d8a4c5f6 780 if(aconf == ptr->data)
212380e3 781 {
4c171a9c 782 sendto_one_notice(source_p,
d8a4c5f6
WP
783 ":Un-klined [%s@%s] from temporary k-lines",
784 aconf->user, aconf->host);
4c171a9c 785 sendto_realops_snomask(SNO_GENERAL, L_ALL,
d8a4c5f6
WP
786 "%s has removed the temporary K-Line for: [%s@%s]",
787 get_oper_name(source_p), aconf->user,
788 aconf->host);
4c171a9c
JT
789
790 ilog(L_KLINE, "UK %s %s %s",
d8a4c5f6 791 get_oper_name(source_p), aconf->user, aconf->host);
9f6c3353 792 rb_dlinkDestroy(ptr, &temp_klines[i]);
21c9d815 793 remove_reject_mask(aconf->user, aconf->host);
40a1d446
JT
794 delete_one_address_conf(aconf->host, aconf);
795 return YES;
212380e3 796 }
212380e3 797 }
798 }
799
800 return NO;
801}