]> jfr.im git - solanum.git/blame - modules/m_kline.c
extensions: add AV2 description strings to a few modules
[solanum.git] / modules / m_kline.c
CommitLineData
212380e3
AC
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
212380e3
AC
23 */
24
25#include "stdinc.h"
212380e3
AC
26#include "channel.h"
27#include "class.h"
28#include "client.h"
29#include "common.h"
4562c604 30#include "match.h"
212380e3
AC
31#include "ircd.h"
32#include "hostmask.h"
33#include "numeric.h"
212380e3
AC
34#include "s_conf.h"
35#include "s_newconf.h"
4016731b 36#include "logger.h"
212380e3
AC
37#include "send.h"
38#include "hash.h"
39#include "s_serv.h"
40#include "msg.h"
41#include "parse.h"
42#include "modules.h"
35f6f850 43#include "reject.h"
8bbeb278 44#include "bandbi.h"
27f616dd 45#include "operhash.h"
212380e3 46
428ca87b
AC
47static int mo_kline(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
48static int ms_kline(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
49static int me_kline(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
50static int mo_unkline(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
51static int ms_unkline(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
52static int me_unkline(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
212380e3
AC
53
54struct Message kline_msgtab = {
7baa37a9 55 "KLINE", 0, 0, 0, 0,
212380e3
AC
56 {mg_unreg, mg_not_oper, {ms_kline, 5}, {ms_kline, 5}, {me_kline, 5}, {mo_kline, 3}}
57};
58
59struct Message unkline_msgtab = {
7baa37a9 60 "UNKLINE", 0, 0, 0, 0,
212380e3
AC
61 {mg_unreg, mg_not_oper, {ms_unkline, 4}, {ms_unkline, 4}, {me_unkline, 3}, {mo_unkline, 2}}
62};
63
64mapi_clist_av1 kline_clist[] = { &kline_msgtab, &unkline_msgtab, NULL };
8bbeb278 65
105a4985 66DECLARE_MODULE_AV2(kline, NULL, NULL, kline_clist, NULL, NULL, NULL, NULL, NULL);
212380e3
AC
67
68/* Local function prototypes */
69static int find_user_host(struct Client *source_p, const char *userhost, char *user, char *host);
212380e3 70static int valid_user_host(struct Client *source_p, const char *user, const char *host);
212380e3
AC
71
72static void handle_remote_kline(struct Client *source_p, int tkline_time,
8bbeb278 73 const char *user, const char *host, const char *reason);
212380e3 74static void apply_kline(struct Client *source_p, struct ConfItem *aconf,
b52c2949 75 const char *reason, const char *oper_reason);
212380e3 76static void apply_tkline(struct Client *source_p, struct ConfItem *aconf,
b52c2949 77 const char *, const char *, int);
431a1a27
JT
78static void apply_prop_kline(struct Client *source_p, struct ConfItem *aconf,
79 const char *, const char *, int);
212380e3
AC
80static int already_placed_kline(struct Client *, const char *, const char *, int);
81
8bbeb278 82static void handle_remote_unkline(struct Client *source_p, const char *user, const char *host);
40a1d446 83static void remove_permkline_match(struct Client *, struct ConfItem *);
d922dded 84static int remove_temp_kline(struct Client *, struct ConfItem *);
431a1a27 85static void remove_prop_kline(struct Client *, struct ConfItem *);
212380e3
AC
86
87/* mo_kline()
88 *
89 * parv[1] - temp time or user@host
90 * parv[2] - user@host, "ON", or reason
91 * parv[3] - "ON", reason, or server to target
92 * parv[4] - server to target, or reason
93 * parv[5] - reason
94 */
95static int
428ca87b 96mo_kline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char **parv)
212380e3 97{
8bbeb278 98 char def[] = "No Reason";
212380e3
AC
99 char user[USERLEN + 2];
100 char host[HOSTLEN + 2];
8bbeb278 101 char *reason = def;
212380e3 102 char *oper_reason;
212380e3
AC
103 const char *target_server = NULL;
104 struct ConfItem *aconf;
105 int tkline_time = 0;
106 int loc = 1;
1702b694 107 int propagated = ConfigFileEntry.use_propagated_bans;
212380e3
AC
108
109 if(!IsOperK(source_p))
110 {
8bbeb278 111 sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "kline");
212380e3
AC
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
8bbeb278 126 if(parc >= loc + 2 && !irccmp(parv[loc], "ON"))
212380e3
AC
127 {
128 if(!IsOperRemoteBan(source_p))
129 {
130 sendto_one(source_p, form_str(ERR_NOPRIVS),
8bbeb278 131 me.name, source_p->name, "remoteban");
212380e3
AC
132 return 0;
133 }
134
8bbeb278 135 target_server = parv[loc + 1];
212380e3
AC
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,
8bbeb278 151 "%d %s %s :%s", tkline_time, user, host, reason);
212380e3
AC
152
153 /* If we are sending it somewhere that doesnt include us, stop */
154 if(!match(target_server, me.name))
155 return 0;
431a1a27
JT
156
157 /* Set as local-only. */
158 propagated = 0;
212380e3
AC
159 }
160 /* if we have cluster servers, send it to them.. */
431a1a27 161 else if(!propagated && rb_dlink_list_length(&cluster_conf_list) > 0)
8bbeb278 162 cluster_generic(source_p, "KLINE",
212380e3 163 (tkline_time > 0) ? SHARED_TKLINE : SHARED_PKLINE, CAP_KLN,
8bbeb278 164 "%lu %s %s :%s", tkline_time, user, host, reason);
212380e3 165
9319a2e2 166 if(!valid_user_host(source_p, user, host))
212380e3
AC
167 return 0;
168
5c2b9eaf
JT
169 if(!valid_wild_card(user, host))
170 {
171 sendto_one_notice(source_p,
172 ":Please include at least %d non-wildcard "
173 "characters with the user@host",
174 ConfigFileEntry.min_nonwildcard);
175 return 0;
176 }
177
431a1a27
JT
178 if(propagated && tkline_time == 0)
179 {
180 sendto_one_notice(source_p, ":Cannot set a permanent global ban");
181 return 0;
182 }
183
212380e3
AC
184 if(already_placed_kline(source_p, user, host, tkline_time))
185 return 0;
186
7df5fcfb 187 rb_set_time();
212380e3
AC
188 aconf = make_conf();
189 aconf->status = CONF_KILL;
b52c2949 190 aconf->created = rb_current_time();
47a03750
VY
191 aconf->host = rb_strdup(host);
192 aconf->user = rb_strdup(user);
212380e3 193 aconf->port = 0;
27f616dd 194 aconf->info.oper = operhash_add(get_oper_name(source_p));
212380e3 195
9319a2e2
KB
196 if(strlen(reason) > BANREASONLEN)
197 reason[BANREASONLEN] = '\0';
198
212380e3
AC
199 /* Look for an oper reason */
200 if((oper_reason = strchr(reason, '|')) != NULL)
201 {
202 *oper_reason = '\0';
203 oper_reason++;
204
205 if(!EmptyString(oper_reason))
47a03750 206 aconf->spasswd = rb_strdup(oper_reason);
212380e3 207 }
c935336b 208 aconf->passwd = rb_strdup(reason);
212380e3 209
431a1a27
JT
210 if(propagated)
211 apply_prop_kline(source_p, aconf, reason, oper_reason, tkline_time);
212 else if(tkline_time > 0)
b52c2949 213 apply_tkline(source_p, aconf, reason, oper_reason, tkline_time);
212380e3 214 else
b52c2949 215 apply_kline(source_p, aconf, reason, oper_reason);
212380e3
AC
216
217 if(ConfigFileEntry.kline_delay)
218 {
219 if(kline_queued == 0)
220 {
0e7cb7e6 221 rb_event_addonce("check_klines", check_klines_event, NULL,
8bbeb278 222 ConfigFileEntry.kline_delay);
212380e3
AC
223 kline_queued = 1;
224 }
225 }
226 else
227 check_klines();
228
229 return 0;
230}
231
232/* ms_kline()
233 *
234 * parv[1] - server targeted at
235 * parv[2] - tkline time (0 if perm)
236 * parv[3] - user
237 * parv[4] - host
238 * parv[5] - reason
239 */
240static int
428ca87b 241ms_kline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
212380e3
AC
242{
243 int tkline_time = atoi(parv[2]);
244
245 /* 1.5-3 and earlier contains a bug that allows remote klines to be
246 * sent with an empty reason field. This is a protocol violation,
247 * but its not worth dropping the link over.. --anfl
248 */
249 if(parc < 6 || EmptyString(parv[5]))
250 return 0;
251
252 propagate_generic(source_p, "KLINE", parv[1], CAP_KLN,
8bbeb278 253 "%d %s %s :%s", tkline_time, parv[3], parv[4], parv[5]);
212380e3
AC
254
255 if(!match(parv[1], me.name))
256 return 0;
257
258 if(!IsPerson(source_p))
259 return 0;
260
261 handle_remote_kline(source_p, tkline_time, parv[3], parv[4], parv[5]);
262 return 0;
263}
264
265static int
428ca87b 266me_kline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
212380e3
AC
267{
268 /* <tkline_time> <user> <host> :<reason> */
269 if(!IsPerson(source_p))
270 return 0;
271
272 handle_remote_kline(source_p, atoi(parv[1]), parv[2], parv[3], parv[4]);
273 return 0;
274}
275
276static void
277handle_remote_kline(struct Client *source_p, int tkline_time,
8bbeb278 278 const char *user, const char *host, const char *kreason)
212380e3 279{
212380e3
AC
280 char *reason = LOCAL_COPY(kreason);
281 struct ConfItem *aconf = NULL;
282 char *oper_reason;
283
284 if(!find_shared_conf(source_p->username, source_p->host,
8bbeb278
AC
285 source_p->servptr->name,
286 (tkline_time > 0) ? SHARED_TKLINE : SHARED_PKLINE))
212380e3
AC
287 return;
288
9319a2e2 289 if(!valid_user_host(source_p, user, host))
212380e3
AC
290 return;
291
5c2b9eaf
JT
292 if(!valid_wild_card(user, host))
293 {
294 sendto_one_notice(source_p,
295 ":Please include at least %d non-wildcard "
296 "characters with the user@host",
297 ConfigFileEntry.min_nonwildcard);
803ce385 298 return;
5c2b9eaf
JT
299 }
300
212380e3
AC
301 if(already_placed_kline(source_p, user, host, tkline_time))
302 return;
303
304 aconf = make_conf();
305
306 aconf->status = CONF_KILL;
b52c2949 307 aconf->created = rb_current_time();
47a03750
VY
308 aconf->user = rb_strdup(user);
309 aconf->host = rb_strdup(host);
27f616dd 310 aconf->info.oper = operhash_add(get_oper_name(source_p));
212380e3 311
9319a2e2
KB
312 if(strlen(reason) > BANREASONLEN)
313 reason[BANREASONLEN] = '\0';
314
212380e3
AC
315 /* Look for an oper reason */
316 if((oper_reason = strchr(reason, '|')) != NULL)
317 {
318 *oper_reason = '\0';
319 oper_reason++;
320
321 if(!EmptyString(oper_reason))
47a03750 322 aconf->spasswd = rb_strdup(oper_reason);
212380e3 323 }
c935336b 324 aconf->passwd = rb_strdup(reason);
212380e3 325
212380e3 326 if(tkline_time > 0)
b52c2949 327 apply_tkline(source_p, aconf, reason, oper_reason, tkline_time);
212380e3 328 else
b52c2949 329 apply_kline(source_p, aconf, reason, oper_reason);
212380e3
AC
330
331 if(ConfigFileEntry.kline_delay)
332 {
333 if(kline_queued == 0)
334 {
0e7cb7e6 335 rb_event_addonce("check_klines", check_klines_event, NULL,
8bbeb278 336 ConfigFileEntry.kline_delay);
212380e3
AC
337 kline_queued = 1;
338 }
339 }
340 else
341 check_klines();
342
343 return;
344}
345
346/* mo_unkline()
347 *
348 * parv[1] - kline to remove
349 * parv[2] - optional "ON"
350 * parv[3] - optional target server
351 */
352static int
428ca87b 353mo_unkline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
212380e3
AC
354{
355 const char *user;
356 char *host;
357 char splat[] = "*";
358 char *h = LOCAL_COPY(parv[1]);
40a1d446 359 struct ConfItem *aconf;
431a1a27 360 int propagated = 1;
212380e3
AC
361
362 if(!IsOperUnkline(source_p))
363 {
8bbeb278 364 sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "unkline");
212380e3
AC
365 return 0;
366 }
367
368 if((host = strchr(h, '@')) || *h == '*' || strchr(h, '.') || strchr(h, ':'))
369 {
370 /* Explicit user@host mask given */
371
372 if(host) /* Found user@host */
373 {
374 *host++ = '\0';
375
376 /* check for @host */
377 if(*h)
378 user = h;
379 else
380 user = splat;
381
382 /* check for user@ */
383 if(!*host)
384 host = splat;
385 }
386 else
387 {
388 user = splat; /* no @ found, assume its *@somehost */
389 host = h;
390 }
391 }
392 else
393 {
5366977b 394 sendto_one_notice(source_p, ":Invalid parameters");
212380e3
AC
395 return 0;
396 }
397
398 /* possible remote kline.. */
399 if((parc > 3) && (irccmp(parv[2], "ON") == 0))
400 {
401 if(!IsOperRemoteBan(source_p))
402 {
403 sendto_one(source_p, form_str(ERR_NOPRIVS),
8bbeb278 404 me.name, source_p->name, "remoteban");
212380e3
AC
405 return 0;
406 }
407
8bbeb278 408 propagate_generic(source_p, "UNKLINE", parv[3], CAP_UNKLN, "%s %s", user, host);
212380e3
AC
409
410 if(match(parv[3], me.name) == 0)
411 return 0;
431a1a27
JT
412
413 propagated = 0;
212380e3 414 }
431a1a27
JT
415
416 aconf = find_exact_conf_by_address(host, CONF_KILL, user);
417
418 /* No clustering for removing a propagated kline */
419 if(propagated && (aconf == NULL || !aconf->lifetime) &&
420 rb_dlink_list_length(&cluster_conf_list) > 0)
212380e3
AC
421 cluster_generic(source_p, "UNKLINE", SHARED_UNKLINE, CAP_UNKLN,
422 "%s %s", user, host);
423
40a1d446
JT
424 if(aconf == NULL)
425 {
426 sendto_one_notice(source_p, ":No K-Line for %s@%s", user, host);
427 return 0;
428 }
55abcbb2 429
431a1a27
JT
430 if(aconf->lifetime)
431 {
432 if(propagated)
433 remove_prop_kline(source_p, aconf);
434 else
435 sendto_one_notice(source_p, ":Cannot remove global K-Line %s@%s on specific servers", user, host);
436 return 0;
437 }
40a1d446 438
d922dded 439 if(remove_temp_kline(source_p, aconf))
212380e3 440 return 0;
212380e3 441
40a1d446 442 remove_permkline_match(source_p, aconf);
212380e3
AC
443
444 return 0;
445}
446
447/* ms_unkline()
448 *
449 * parv[1] - target server
450 * parv[2] - user to unkline
451 * parv[3] - host to unkline
452 */
453static int
428ca87b 454ms_unkline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
212380e3 455{
8bbeb278
AC
456 /* parv[0] parv[1] parv[2] parv[3]
457 * oper target server user host */
458 propagate_generic(source_p, "UNKLINE", parv[1], CAP_UNKLN, "%s %s", parv[2], parv[3]);
212380e3
AC
459
460 if(!match(parv[1], me.name))
461 return 0;
462
463 if(!IsPerson(source_p))
464 return 0;
465
466 handle_remote_unkline(source_p, parv[2], parv[3]);
467 return 0;
468}
469
470static int
428ca87b 471me_unkline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
212380e3
AC
472{
473 /* user host */
474 if(!IsPerson(source_p))
475 return 0;
476
477 handle_remote_unkline(source_p, parv[1], parv[2]);
478 return 0;
479}
480
481static void
482handle_remote_unkline(struct Client *source_p, const char *user, const char *host)
483{
40a1d446
JT
484 struct ConfItem *aconf;
485
212380e3 486 if(!find_shared_conf(source_p->username, source_p->host,
8bbeb278 487 source_p->servptr->name, SHARED_UNKLINE))
212380e3
AC
488 return;
489
40a1d446
JT
490 aconf = find_exact_conf_by_address(host, CONF_KILL, user);
491 if(aconf == NULL)
492 {
493 sendto_one_notice(source_p, ":No K-Line for %s@%s", user, host);
494 return;
495 }
431a1a27
JT
496 if(aconf->lifetime)
497 {
498 sendto_one_notice(source_p, ":Cannot remove global K-Line %s@%s on specific servers", user, host);
499 return;
500 }
40a1d446 501
d922dded 502 if(remove_temp_kline(source_p, aconf))
212380e3 503 return;
212380e3 504
40a1d446 505 remove_permkline_match(source_p, aconf);
212380e3
AC
506}
507
508/* apply_kline()
509 *
55abcbb2 510 * inputs -
212380e3
AC
511 * output - NONE
512 * side effects - kline as given, is added to the hashtable
513 * and conf file
514 */
515static void
516apply_kline(struct Client *source_p, struct ConfItem *aconf,
b52c2949 517 const char *reason, const char *oper_reason)
212380e3 518{
40c1fd47 519 add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf);
8bbeb278
AC
520 bandb_add(BANDB_KLINE, source_p, aconf->user, aconf->host,
521 reason, EmptyString(oper_reason) ? NULL : oper_reason, 0);
9964e935
AC
522
523 /* no oper reason.. */
524 if(EmptyString(oper_reason))
525 {
526 sendto_realops_snomask(SNO_GENERAL, L_ALL,
527 "%s added K-Line for [%s@%s] [%s]",
528 get_oper_name(source_p), aconf->user, aconf->host, reason);
529 ilog(L_KLINE, "K %s 0 %s %s %s",
530 get_oper_name(source_p), aconf->user, aconf->host, reason);
531 }
532 else
533 {
534 sendto_realops_snomask(SNO_GENERAL, L_ALL,
535 "%s added K-Line for [%s@%s] [%s|%s]",
536 get_oper_name(source_p), aconf->user, aconf->host,
537 reason, oper_reason);
538 ilog(L_KLINE, "K %s 0 %s %s %s|%s",
539 get_oper_name(source_p), aconf->user, aconf->host, reason, oper_reason);
540 }
541
542 sendto_one_notice(source_p, ":Added K-Line [%s@%s]",
543 aconf->user, aconf->host);
212380e3
AC
544}
545
546/* apply_tkline()
547 *
548 * inputs -
549 * output - NONE
550 * side effects - tkline as given is placed
551 */
552static void
553apply_tkline(struct Client *source_p, struct ConfItem *aconf,
b52c2949 554 const char *reason, const char *oper_reason, int tkline_time)
212380e3 555{
e3354945 556 aconf->hold = rb_current_time() + tkline_time;
212380e3
AC
557 add_temp_kline(aconf);
558
559 /* no oper reason.. */
560 if(EmptyString(oper_reason))
561 {
562 sendto_realops_snomask(SNO_GENERAL, L_ALL,
8bbeb278
AC
563 "%s added temporary %d min. K-Line for [%s@%s] [%s]",
564 get_oper_name(source_p), tkline_time / 60,
565 aconf->user, aconf->host, reason);
212380e3 566 ilog(L_KLINE, "K %s %d %s %s %s",
8bbeb278 567 get_oper_name(source_p), tkline_time / 60, aconf->user, aconf->host, reason);
212380e3
AC
568 }
569 else
570 {
571 sendto_realops_snomask(SNO_GENERAL, L_ALL,
8bbeb278
AC
572 "%s added temporary %d min. K-Line for [%s@%s] [%s|%s]",
573 get_oper_name(source_p), tkline_time / 60,
574 aconf->user, aconf->host, reason, oper_reason);
212380e3 575 ilog(L_KLINE, "K %s %d %s %s %s|%s",
8bbeb278
AC
576 get_oper_name(source_p), tkline_time / 60,
577 aconf->user, aconf->host, reason, oper_reason);
212380e3
AC
578 }
579
580 sendto_one_notice(source_p, ":Added temporary %d min. K-Line [%s@%s]",
581 tkline_time / 60, aconf->user, aconf->host);
582}
583
431a1a27
JT
584static void
585apply_prop_kline(struct Client *source_p, struct ConfItem *aconf,
586 const char *reason, const char *oper_reason, int tkline_time)
587{
431a1a27
JT
588 aconf->flags |= CONF_FLAGS_MYOPER | CONF_FLAGS_TEMPORARY;
589 aconf->hold = rb_current_time() + tkline_time;
590 aconf->lifetime = aconf->hold;
591
3cbbfb25 592 replace_old_ban(aconf);
431a1a27
JT
593
594 rb_dlinkAddAlloc(aconf, &prop_bans);
595 add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf);
596
597 /* no oper reason.. */
598 if(EmptyString(oper_reason))
599 {
600 sendto_realops_snomask(SNO_GENERAL, L_ALL,
601 "%s added global %d min. K-Line for [%s@%s] [%s]",
602 get_oper_name(source_p), tkline_time / 60,
603 aconf->user, aconf->host, reason);
604 ilog(L_KLINE, "K %s %d %s %s %s",
605 get_oper_name(source_p), tkline_time / 60, aconf->user, aconf->host, reason);
606 }
607 else
608 {
609 sendto_realops_snomask(SNO_GENERAL, L_ALL,
610 "%s added global %d min. K-Line for [%s@%s] [%s|%s]",
611 get_oper_name(source_p), tkline_time / 60,
612 aconf->user, aconf->host, reason, oper_reason);
613 ilog(L_KLINE, "K %s %d %s %s %s|%s",
614 get_oper_name(source_p), tkline_time / 60,
615 aconf->user, aconf->host, reason, oper_reason);
616 }
617
618 sendto_one_notice(source_p, ":Added global %d min. K-Line [%s@%s]",
619 tkline_time / 60, aconf->user, aconf->host);
620
621 sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS,
cedb7d05 622 ":%s BAN K %s %s %lu %d %d * :%s%s%s",
431a1a27
JT
623 source_p->id, aconf->user, aconf->host,
624 (unsigned long)aconf->created,
625 (int)(aconf->hold - aconf->created),
626 (int)(aconf->lifetime - aconf->created),
627 reason,
628 oper_reason ? "|" : "",
629 oper_reason ? oper_reason : "");
630}
631
212380e3 632/* find_user_host()
55abcbb2 633 *
212380e3
AC
634 * inputs - client placing kline, user@host, user buffer, host buffer
635 * output - 0 if not ok to kline, 1 to kline i.e. if valid user host
636 * side effects -
637 */
638static int
639find_user_host(struct Client *source_p, const char *userhost, char *luser, char *lhost)
640{
641 char *hostp;
642
643 hostp = strchr(userhost, '@');
8bbeb278 644
212380e3
AC
645 if(hostp != NULL) /* I'm a little user@host */
646 {
647 *(hostp++) = '\0'; /* short and squat */
648 if(*userhost)
f427c8b0 649 rb_strlcpy(luser, userhost, USERLEN + 1); /* here is my user */
212380e3
AC
650 else
651 strcpy(luser, "*");
652 if(*hostp)
f427c8b0 653 rb_strlcpy(lhost, hostp, HOSTLEN + 1); /* here is my host */
212380e3
AC
654 else
655 strcpy(lhost, "*");
8bbeb278 656 }
212380e3
AC
657 else
658 {
659 /* no '@', no '.', so its not a user@host or host, therefore
660 * its a nick, which support was removed for.
661 */
662 if(strchr(userhost, '.') == NULL && strchr(userhost, ':') == NULL)
af0ba24b
JT
663 {
664 sendto_one_notice(source_p, ":K-Line must be a user@host or host");
212380e3 665 return 0;
af0ba24b 666 }
212380e3
AC
667
668 luser[0] = '*'; /* no @ found, assume its *@somehost */
669 luser[1] = '\0';
f427c8b0 670 rb_strlcpy(lhost, userhost, HOSTLEN + 1);
212380e3
AC
671 }
672
2b843a5b
JT
673 /* would break the protocol */
674 if (*luser == ':' || *lhost == ':')
675 {
676 sendto_one_notice(source_p, ":Invalid K-Line");
677 return 0;
678 }
679
212380e3
AC
680 return 1;
681}
682
683/* valid_user_host()
684 *
685 * inputs - user buffer, host buffer
686 * output - 0 if invalid, 1 if valid
687 * side effects -
688 */
689static int
690valid_user_host(struct Client *source_p, const char *luser, const char *lhost)
691{
8bbeb278
AC
692 /* # is invalid, as are '!' (n!u@h kline) and '@' (u@@h kline) */
693 if(strchr(lhost, '#') || strchr(luser, '#') || strchr(luser, '!') || strchr(lhost, '@'))
212380e3
AC
694 {
695 sendto_one_notice(source_p, ":Invalid K-Line");
696 return 0;
697 }
698
699 return 1;
700}
701
212380e3
AC
702/* already_placed_kline()
703 *
704 * inputs - source to notify, user@host to check, tkline time
705 * outputs - 1 if a perm kline or a tkline when a tkline is being
706 * set exists, else 0
707 * side effects - notifies source_p kline exists
708 */
709/* Note: This currently works if the new K-line is a special case of an
710 * existing K-line, but not the other way round. To do that we would
711 * have to walk the hash and check every existing K-line. -A1kmm.
712 */
713static int
714already_placed_kline(struct Client *source_p, const char *luser, const char *lhost, int tkline)
715{
7f27e316 716 const char *reason, *p;
e7046ee5 717 struct rb_sockaddr_storage iphost, *piphost;
212380e3 718 struct ConfItem *aconf;
8bbeb278 719 int t, bits;
7f27e316
JT
720
721 aconf = find_exact_conf_by_address(lhost, CONF_KILL, luser);
8bbeb278 722 if(aconf == NULL && ConfigFileEntry.non_redundant_klines)
212380e3 723 {
7f27e316 724 bits = 0;
29c92cf9 725 if((t = parse_netmask(lhost, &iphost, &bits)) != HM_HOST)
212380e3 726 {
ccda6e3f 727#ifdef RB_IPV6
212380e3
AC
728 if(t == HM_IPV6)
729 t = AF_INET6;
730 else
731#endif
732 t = AF_INET;
8bbeb278 733
212380e3
AC
734 piphost = &iphost;
735 }
736 else
737 piphost = NULL;
738
8bbeb278
AC
739 aconf = find_conf_by_address(lhost, NULL, NULL, (struct sockaddr *) piphost,
740 CONF_KILL, t, luser, NULL);
741 if(aconf != NULL)
212380e3 742 {
7f27e316
JT
743 /* The above was really a lookup of a single IP,
744 * so check if the new kline is wider than the
745 * existing one.
746 * -- jilles
747 */
748 p = strchr(aconf->host, '/');
8bbeb278 749 if(bits > 0 && (p == NULL || bits < atoi(p + 1)))
7f27e316
JT
750 aconf = NULL;
751 }
752 }
8bbeb278 753 if(aconf != NULL)
7f27e316
JT
754 {
755 /* setting a tkline, or existing one is perm */
756 if(tkline || ((aconf->flags & CONF_FLAGS_TEMPORARY) == 0))
757 {
758 reason = aconf->passwd ? aconf->passwd : "<No Reason>";
759
760 sendto_one_notice(source_p,
761 ":[%s@%s] already K-Lined by [%s@%s] - %s",
8bbeb278 762 luser, lhost, aconf->user, aconf->host, reason);
7f27e316 763 return 1;
212380e3
AC
764 }
765 }
766
767 return 0;
768}
769
770/* remove_permkline_match()
771 *
772 * hunts for a permanent kline, and removes it.
773 */
774static void
40a1d446 775remove_permkline_match(struct Client *source_p, struct ConfItem *aconf)
212380e3 776{
8bbeb278 777 sendto_one_notice(source_p, ":K-Line for [%s@%s] is removed", aconf->user, aconf->host);
212380e3
AC
778
779 sendto_realops_snomask(SNO_GENERAL, L_ALL,
8bbeb278
AC
780 "%s has removed the K-Line for: [%s@%s]",
781 get_oper_name(source_p), aconf->user, aconf->host);
212380e3 782
8bbeb278 783 ilog(L_KLINE, "UK %s %s %s", get_oper_name(source_p), aconf->user, aconf->host);
40a1d446 784
54ac8b60 785 remove_reject_mask(aconf->user, aconf->host);
8bbeb278 786 bandb_del(BANDB_KLINE, aconf->user, aconf->host);
40a1d446
JT
787 delete_one_address_conf(aconf->host, aconf);
788
212380e3
AC
789 return;
790}
791
212380e3
AC
792/* remove_temp_kline()
793 *
794 * inputs - username, hostname to unkline
795 * outputs -
796 * side effects - tries to unkline anything that matches
797 */
798static int
d922dded 799remove_temp_kline(struct Client *source_p, struct ConfItem *aconf)
212380e3 800{
5b96d9a6 801 rb_dlink_node *ptr;
212380e3
AC
802 int i;
803
8bbeb278 804 for(i = 0; i < LAST_TEMP_TYPE; i++)
212380e3 805 {
5b96d9a6 806 RB_DLINK_FOREACH(ptr, temp_klines[i].head)
212380e3 807 {
8bbeb278 808 if(aconf == ptr->data)
212380e3 809 {
d922dded 810 sendto_one_notice(source_p,
8bbeb278
AC
811 ":Un-klined [%s@%s] from temporary k-lines",
812 aconf->user, aconf->host);
d922dded 813 sendto_realops_snomask(SNO_GENERAL, L_ALL,
8bbeb278
AC
814 "%s has removed the temporary K-Line for: [%s@%s]",
815 get_oper_name(source_p), aconf->user,
816 aconf->host);
d922dded
JT
817
818 ilog(L_KLINE, "UK %s %s %s",
8bbeb278 819 get_oper_name(source_p), aconf->user, aconf->host);
555ac41f 820 rb_dlinkDestroy(ptr, &temp_klines[i]);
54ac8b60 821 remove_reject_mask(aconf->user, aconf->host);
40a1d446
JT
822 delete_one_address_conf(aconf->host, aconf);
823 return YES;
212380e3 824 }
212380e3
AC
825 }
826 }
827
828 return NO;
829}
431a1a27
JT
830
831static void
832remove_prop_kline(struct Client *source_p, struct ConfItem *aconf)
833{
834 rb_dlink_node *ptr;
483987a4 835 time_t now;
431a1a27
JT
836
837 ptr = rb_dlinkFind(aconf, &prop_bans);
838 if (!ptr)
839 return;
840 sendto_one_notice(source_p,
841 ":Un-klined [%s@%s] from global k-lines",
842 aconf->user, aconf->host);
843 sendto_realops_snomask(SNO_GENERAL, L_ALL,
844 "%s has removed the global K-Line for: [%s@%s]",
845 get_oper_name(source_p), aconf->user,
846 aconf->host);
847
848 ilog(L_KLINE, "UK %s %s %s",
849 get_oper_name(source_p), aconf->user, aconf->host);
483987a4
JT
850 now = rb_current_time();
851 if(aconf->created < now)
852 aconf->created = now;
431a1a27
JT
853 else
854 aconf->created++;
cedb7d05 855 aconf->hold = aconf->created;
431a1a27
JT
856 operhash_delete(aconf->info.oper);
857 aconf->info.oper = operhash_add(get_oper_name(source_p));
858 aconf->flags |= CONF_FLAGS_MYOPER | CONF_FLAGS_TEMPORARY;
859 sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS,
cedb7d05 860 ":%s BAN K %s %s %lu %d %d * :*",
431a1a27
JT
861 source_p->id, aconf->user, aconf->host,
862 (unsigned long)aconf->created,
863 0,
864 (int)(aconf->lifetime - aconf->created));
865 remove_reject_mask(aconf->user, aconf->host);
483987a4 866 deactivate_conf(aconf, ptr, now);
431a1a27 867}