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