]> jfr.im git - irc/rqf/shadowircd.git/blob - modules/m_kline.c
kline: Fix oper reasons.
[irc/rqf/shadowircd.git] / modules / m_kline.c
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 *
24 * $Id$
25 */
26
27 #include "stdinc.h"
28 #include "channel.h"
29 #include "class.h"
30 #include "client.h"
31 #include "common.h"
32 #include "match.h"
33 #include "ircd.h"
34 #include "hostmask.h"
35 #include "numeric.h"
36 #include "s_conf.h"
37 #include "s_newconf.h"
38 #include "logger.h"
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"
45 #include "reject.h"
46 #include "bandbi.h"
47 #include "operhash.h"
48
49 static int mo_kline(struct Client *, struct Client *, int, const char **);
50 static int ms_kline(struct Client *, struct Client *, int, const char **);
51 static int me_kline(struct Client *, struct Client *, int, const char **);
52 static int mo_unkline(struct Client *, struct Client *, int, const char **);
53 static int ms_unkline(struct Client *, struct Client *, int, const char **);
54 static int me_unkline(struct Client *, struct Client *, int, const char **);
55
56 struct 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
61 struct 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
66 mapi_clist_av1 kline_clist[] = { &kline_msgtab, &unkline_msgtab, NULL };
67
68 DECLARE_MODULE_AV1(kline, NULL, NULL, kline_clist, NULL, NULL, "$Revision$");
69
70 /* Local function prototypes */
71 static int find_user_host(struct Client *source_p, const char *userhost, char *user, char *host);
72 static int valid_comment(struct Client *source_p, char *comment);
73 static int valid_user_host(struct Client *source_p, const char *user, const char *host);
74 static int valid_wild_card(struct Client *source_p, const char *user, const char *host);
75
76 static void handle_remote_kline(struct Client *source_p, int tkline_time,
77 const char *user, const char *host, const char *reason);
78 static void apply_kline(struct Client *source_p, struct ConfItem *aconf,
79 const char *reason, const char *oper_reason);
80 static void apply_tkline(struct Client *source_p, struct ConfItem *aconf,
81 const char *, const char *, int);
82 static int already_placed_kline(struct Client *, const char *, const char *, int);
83
84 static void handle_remote_unkline(struct Client *source_p, const char *user, const char *host);
85 static void remove_permkline_match(struct Client *, struct ConfItem *);
86 static int remove_temp_kline(struct Client *, struct ConfItem *);
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 */
96 static int
97 mo_kline(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
98 {
99 char def[] = "No Reason";
100 char user[USERLEN + 2];
101 char host[HOSTLEN + 2];
102 char *reason = def;
103 char *oper_reason;
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 {
111 sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "kline");
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
126 if(parc >= loc + 2 && !irccmp(parv[loc], "ON"))
127 {
128 if(!IsOperRemoteBan(source_p))
129 {
130 sendto_one(source_p, form_str(ERR_NOPRIVS),
131 me.name, source_p->name, "remoteban");
132 return 0;
133 }
134
135 target_server = parv[loc + 1];
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,
151 "%d %s %s :%s", tkline_time, user, host, reason);
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.. */
158 else if(rb_dlink_list_length(&cluster_conf_list) > 0)
159 cluster_generic(source_p, "KLINE",
160 (tkline_time > 0) ? SHARED_TKLINE : SHARED_PKLINE, CAP_KLN,
161 "%lu %s %s :%s", tkline_time, user, host, reason);
162
163 if(!valid_user_host(source_p, user, host) ||
164 !valid_wild_card(source_p, user, host) || !valid_comment(source_p, reason))
165 return 0;
166
167 if(already_placed_kline(source_p, user, host, tkline_time))
168 return 0;
169
170 rb_set_time();
171 aconf = make_conf();
172 aconf->status = CONF_KILL;
173 aconf->created = rb_current_time();
174 aconf->host = rb_strdup(host);
175 aconf->user = rb_strdup(user);
176 aconf->port = 0;
177 aconf->info.oper = operhash_add(get_oper_name(source_p));
178
179 /* Look for an oper reason */
180 if((oper_reason = strchr(reason, '|')) != NULL)
181 {
182 *oper_reason = '\0';
183 oper_reason++;
184
185 if(!EmptyString(oper_reason))
186 aconf->spasswd = rb_strdup(oper_reason);
187 }
188 aconf->passwd = rb_strdup(reason);
189
190 if(tkline_time > 0)
191 apply_tkline(source_p, aconf, reason, oper_reason, tkline_time);
192 else
193 apply_kline(source_p, aconf, reason, oper_reason);
194
195 if(ConfigFileEntry.kline_delay)
196 {
197 if(kline_queued == 0)
198 {
199 rb_event_addonce("check_klines", check_klines_event, NULL,
200 ConfigFileEntry.kline_delay);
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 */
218 static int
219 ms_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,
231 "%d %s %s :%s", tkline_time, parv[3], parv[4], parv[5]);
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
243 static int
244 me_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
254 static void
255 handle_remote_kline(struct Client *source_p, int tkline_time,
256 const char *user, const char *host, const char *kreason)
257 {
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,
263 source_p->servptr->name,
264 (tkline_time > 0) ? SHARED_TKLINE : SHARED_PKLINE))
265 return;
266
267 if(!valid_user_host(source_p, user, host) ||
268 !valid_wild_card(source_p, user, host) || !valid_comment(source_p, reason))
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;
277 aconf->created = rb_current_time();
278 aconf->user = rb_strdup(user);
279 aconf->host = rb_strdup(host);
280 aconf->info.oper = operhash_add(get_oper_name(source_p));
281
282 /* Look for an oper reason */
283 if((oper_reason = strchr(reason, '|')) != NULL)
284 {
285 *oper_reason = '\0';
286 oper_reason++;
287
288 if(!EmptyString(oper_reason))
289 aconf->spasswd = rb_strdup(oper_reason);
290 }
291 aconf->passwd = rb_strdup(reason);
292
293 if(tkline_time > 0)
294 apply_tkline(source_p, aconf, reason, oper_reason, tkline_time);
295 else
296 apply_kline(source_p, aconf, reason, oper_reason);
297
298 if(ConfigFileEntry.kline_delay)
299 {
300 if(kline_queued == 0)
301 {
302 rb_event_addonce("check_klines", check_klines_event, NULL,
303 ConfigFileEntry.kline_delay);
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 */
319 static int
320 mo_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]);
326 struct ConfItem *aconf;
327
328 if(!IsOperUnkline(source_p))
329 {
330 sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "unkline");
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 {
360 sendto_one_notice(source_p, ":Invalid parameters");
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),
370 me.name, source_p->name, "remoteban");
371 return 0;
372 }
373
374 propagate_generic(source_p, "UNKLINE", parv[3], CAP_UNKLN, "%s %s", user, host);
375
376 if(match(parv[3], me.name) == 0)
377 return 0;
378 }
379 else if(rb_dlink_list_length(&cluster_conf_list) > 0)
380 cluster_generic(source_p, "UNKLINE", SHARED_UNKLINE, CAP_UNKLN,
381 "%s %s", user, host);
382
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
390 if(remove_temp_kline(source_p, aconf))
391 return 0;
392
393 remove_permkline_match(source_p, aconf);
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 */
404 static int
405 ms_unkline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
406 {
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]);
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
421 static int
422 me_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
432 static void
433 handle_remote_unkline(struct Client *source_p, const char *user, const char *host)
434 {
435 struct ConfItem *aconf;
436
437 if(!find_shared_conf(source_p->username, source_p->host,
438 source_p->servptr->name, SHARED_UNKLINE))
439 return;
440
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
448 if(remove_temp_kline(source_p, aconf))
449 return;
450
451 remove_permkline_match(source_p, aconf);
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 */
461 static void
462 apply_kline(struct Client *source_p, struct ConfItem *aconf,
463 const char *reason, const char *oper_reason)
464 {
465 add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf);
466 bandb_add(BANDB_KLINE, source_p, aconf->user, aconf->host,
467 reason, EmptyString(oper_reason) ? NULL : oper_reason, 0);
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);
490 }
491
492 /* apply_tkline()
493 *
494 * inputs -
495 * output - NONE
496 * side effects - tkline as given is placed
497 */
498 static void
499 apply_tkline(struct Client *source_p, struct ConfItem *aconf,
500 const char *reason, const char *oper_reason, int tkline_time)
501 {
502 aconf->hold = rb_current_time() + tkline_time;
503 add_temp_kline(aconf);
504
505 /* no oper reason.. */
506 if(EmptyString(oper_reason))
507 {
508 sendto_realops_snomask(SNO_GENERAL, L_ALL,
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);
512 ilog(L_KLINE, "K %s %d %s %s %s",
513 get_oper_name(source_p), tkline_time / 60, aconf->user, aconf->host, reason);
514 }
515 else
516 {
517 sendto_realops_snomask(SNO_GENERAL, L_ALL,
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);
521 ilog(L_KLINE, "K %s %d %s %s %s|%s",
522 get_oper_name(source_p), tkline_time / 60,
523 aconf->user, aconf->host, reason, oper_reason);
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 */
536 static int
537 find_user_host(struct Client *source_p, const char *userhost, char *luser, char *lhost)
538 {
539 char *hostp;
540
541 hostp = strchr(userhost, '@');
542
543 if(hostp != NULL) /* I'm a little user@host */
544 {
545 *(hostp++) = '\0'; /* short and squat */
546 if(*userhost)
547 rb_strlcpy(luser, userhost, USERLEN + 1); /* here is my user */
548 else
549 strcpy(luser, "*");
550 if(*hostp)
551 rb_strlcpy(lhost, hostp, HOSTLEN + 1); /* here is my host */
552 else
553 strcpy(lhost, "*");
554 }
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)
561 {
562 sendto_one_notice(source_p, ":K-Line must be a user@host or host");
563 return 0;
564 }
565
566 luser[0] = '*'; /* no @ found, assume its *@somehost */
567 luser[1] = '\0';
568 rb_strlcpy(lhost, userhost, HOSTLEN + 1);
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 */
580 static int
581 valid_user_host(struct Client *source_p, const char *luser, const char *lhost)
582 {
583 /* # is invalid, as are '!' (n!u@h kline) and '@' (u@@h kline) */
584 if(strchr(lhost, '#') || strchr(luser, '#') || strchr(luser, '!') || strchr(lhost, '@'))
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 */
599 static int
600 valid_wild_card(struct Client *source_p, const char *luser, const char *lhost)
601 {
602 const char *p;
603 char tmpch;
604 int nonwild = 0;
605 int bitlen;
606
607 /* user has no wildcards, always accept -- jilles */
608 if(!strchr(luser, '?') && !strchr(luser, '*'))
609 return 1;
610
611 /* check there are enough non wildcard chars */
612 p = luser;
613 while((tmpch = *p++))
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 */
624 /* special case for cidr masks -- jilles */
625 if((p = strrchr(lhost, '/')) != NULL && IsDigit(p[1]))
626 {
627 bitlen = atoi(p + 1);
628 /* much like non-cidr for ipv6, rather arbitrary for ipv4 */
629 if(bitlen > 0
630 && bitlen >=
631 (strchr(lhost, ':') ? 4 * (ConfigFileEntry.min_nonwildcard - nonwild) : 6 -
632 2 * nonwild))
633 return 1;
634 }
635 else
636 {
637 p = lhost;
638 while((tmpch = *p++))
639 {
640 if(!IsKWildChar(tmpch))
641 if(++nonwild >= ConfigFileEntry.min_nonwildcard)
642 return 1;
643 }
644 }
645
646 sendto_one_notice(source_p,
647 ":Please include at least %d non-wildcard "
648 "characters with the user@host", ConfigFileEntry.min_nonwildcard);
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 */
659 static int
660 valid_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
668 if(strlen(comment) > BANREASONLEN)
669 comment[BANREASONLEN] = '\0';
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 */
685 static int
686 already_placed_kline(struct Client *source_p, const char *luser, const char *lhost, int tkline)
687 {
688 const char *reason, *p;
689 struct rb_sockaddr_storage iphost, *piphost;
690 struct ConfItem *aconf;
691 int t, bits;
692
693 aconf = find_exact_conf_by_address(lhost, CONF_KILL, luser);
694 if(aconf == NULL && ConfigFileEntry.non_redundant_klines)
695 {
696 bits = 0;
697 if((t = parse_netmask(lhost, (struct sockaddr *) &iphost, &bits)) != HM_HOST)
698 {
699 #ifdef RB_IPV6
700 if(t == HM_IPV6)
701 t = AF_INET6;
702 else
703 #endif
704 t = AF_INET;
705
706 piphost = &iphost;
707 }
708 else
709 piphost = NULL;
710
711 aconf = find_conf_by_address(lhost, NULL, NULL, (struct sockaddr *) piphost,
712 CONF_KILL, t, luser, NULL);
713 if(aconf != NULL)
714 {
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, '/');
721 if(bits > 0 && (p == NULL || bits < atoi(p + 1)))
722 aconf = NULL;
723 }
724 }
725 if(aconf != NULL)
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",
734 luser, lhost, aconf->user, aconf->host, reason);
735 return 1;
736 }
737 }
738
739 return 0;
740 }
741
742 /* remove_permkline_match()
743 *
744 * hunts for a permanent kline, and removes it.
745 */
746 static void
747 remove_permkline_match(struct Client *source_p, struct ConfItem *aconf)
748 {
749 sendto_one_notice(source_p, ":K-Line for [%s@%s] is removed", aconf->user, aconf->host);
750
751 sendto_realops_snomask(SNO_GENERAL, L_ALL,
752 "%s has removed the K-Line for: [%s@%s]",
753 get_oper_name(source_p), aconf->user, aconf->host);
754
755 ilog(L_KLINE, "UK %s %s %s", get_oper_name(source_p), aconf->user, aconf->host);
756
757 remove_reject_mask(aconf->user, aconf->host);
758 bandb_del(BANDB_KLINE, aconf->user, aconf->host);
759 delete_one_address_conf(aconf->host, aconf);
760
761 return;
762 }
763
764 /* remove_temp_kline()
765 *
766 * inputs - username, hostname to unkline
767 * outputs -
768 * side effects - tries to unkline anything that matches
769 */
770 static int
771 remove_temp_kline(struct Client *source_p, struct ConfItem *aconf)
772 {
773 rb_dlink_node *ptr;
774 int i;
775
776 for(i = 0; i < LAST_TEMP_TYPE; i++)
777 {
778 RB_DLINK_FOREACH(ptr, temp_klines[i].head)
779 {
780 if(aconf == ptr->data)
781 {
782 sendto_one_notice(source_p,
783 ":Un-klined [%s@%s] from temporary k-lines",
784 aconf->user, aconf->host);
785 sendto_realops_snomask(SNO_GENERAL, L_ALL,
786 "%s has removed the temporary K-Line for: [%s@%s]",
787 get_oper_name(source_p), aconf->user,
788 aconf->host);
789
790 ilog(L_KLINE, "UK %s %s %s",
791 get_oper_name(source_p), aconf->user, aconf->host);
792 rb_dlinkDestroy(ptr, &temp_klines[i]);
793 remove_reject_mask(aconf->user, aconf->host);
794 delete_one_address_conf(aconf->host, aconf);
795 return YES;
796 }
797 }
798 }
799
800 return NO;
801 }