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