]> jfr.im git - solanum.git/blame - modules/m_resv.c
BAN: Reject bans with insufficient non-wildcard characters.
[solanum.git] / modules / m_resv.c
CommitLineData
212380e3
AC
1/*
2 * ircd-ratbox: A slightly useful ircd.
3 * m_resv.c: Reserves(jupes) a nickname or channel.
4 *
5 * Copyright (C) 2001-2002 Hybrid Development Team
6 * Copyright (C) 2002-2005 ircd-ratbox development team
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 * USA
22 *
8bbeb278 23 * $Id$
212380e3
AC
24 */
25
26#include "stdinc.h"
27#include "client.h"
28#include "channel.h"
29#include "ircd.h"
30#include "numeric.h"
31#include "s_serv.h"
32#include "send.h"
33#include "msg.h"
34#include "parse.h"
35#include "modules.h"
36#include "s_conf.h"
37#include "s_newconf.h"
38#include "hash.h"
4016731b 39#include "logger.h"
8bbeb278 40#include "bandbi.h"
27f616dd 41#include "operhash.h"
212380e3
AC
42
43static int mo_resv(struct Client *, struct Client *, int, const char **);
44static int ms_resv(struct Client *, struct Client *, int, const char **);
45static int me_resv(struct Client *, struct Client *, int, const char **);
46static int mo_unresv(struct Client *, struct Client *, int, const char **);
47static int ms_unresv(struct Client *, struct Client *, int, const char **);
48static int me_unresv(struct Client *, struct Client *, int, const char **);
49
50struct Message resv_msgtab = {
51 "RESV", 0, 0, 0, MFLG_SLOW | MFLG_UNREG,
52 {mg_ignore, mg_not_oper, {ms_resv, 4}, {ms_resv, 4}, {me_resv, 5}, {mo_resv, 3}}
53};
8bbeb278 54
212380e3
AC
55struct Message unresv_msgtab = {
56 "UNRESV", 0, 0, 0, MFLG_SLOW | MFLG_UNREG,
57 {mg_ignore, mg_not_oper, {ms_unresv, 3}, {ms_unresv, 3}, {me_unresv, 2}, {mo_unresv, 2}}
58};
59
8bbeb278
AC
60mapi_clist_av1 resv_clist[] = { &resv_msgtab, &unresv_msgtab, NULL };
61
62DECLARE_MODULE_AV1(resv, NULL, NULL, resv_clist, NULL, NULL, "$Revision$");
212380e3
AC
63
64static void parse_resv(struct Client *source_p, const char *name,
8bbeb278 65 const char *reason, int temp_time);
212380e3 66static void propagate_resv(struct Client *source_p, const char *target,
8bbeb278
AC
67 int temp_time, const char *name, const char *reason);
68static void cluster_resv(struct Client *source_p, int temp_time,
69 const char *name, const char *reason);
212380e3
AC
70
71static void handle_remote_unresv(struct Client *source_p, const char *name);
72static void remove_resv(struct Client *source_p, const char *name);
43d4d72c 73static void resv_chan_forcepart(const char *name, const char *reason, int temp_time);
212380e3
AC
74
75/*
76 * mo_resv()
8bbeb278 77 * parv[0] = sender prefix
212380e3
AC
78 * parv[1] = channel/nick to forbid
79 * parv[2] = reason
80 */
81static int
82mo_resv(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
83{
84 const char *name;
85 const char *reason;
86 const char *target_server = NULL;
87 int temp_time;
88 int loc = 1;
89
1ebe6ffc
JT
90 if(!IsOperResv(source_p))
91 {
8bbeb278 92 sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "resv");
1ebe6ffc
JT
93 return 0;
94 }
95
212380e3
AC
96 /* RESV [time] <name> [ON <server>] :<reason> */
97
98 if((temp_time = valid_temp_time(parv[loc])) >= 0)
99 loc++;
100 /* we just set temp_time to -1! */
101 else
102 temp_time = 0;
103
104 name = parv[loc];
105 loc++;
106
8bbeb278 107 if((parc >= loc + 2) && (irccmp(parv[loc], "ON") == 0))
212380e3
AC
108 {
109 if(!IsOperRemoteBan(source_p))
110 {
111 sendto_one(source_p, form_str(ERR_NOPRIVS),
8bbeb278 112 me.name, source_p->name, "remoteban");
212380e3
AC
113 return 0;
114 }
115
8bbeb278 116 target_server = parv[loc + 1];
212380e3
AC
117 loc += 2;
118 }
119
120 if(parc <= loc || EmptyString(parv[loc]))
121 {
8bbeb278 122 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, source_p->name, "RESV");
212380e3
AC
123 return 0;
124 }
125
126 reason = parv[loc];
127
128 /* remote resv.. */
129 if(target_server)
130 {
131 propagate_resv(source_p, target_server, temp_time, name, reason);
132
133 if(match(target_server, me.name) == 0)
134 return 0;
135 }
5b96d9a6 136 else if(rb_dlink_list_length(&cluster_conf_list) > 0)
212380e3
AC
137 cluster_resv(source_p, temp_time, name, reason);
138
139 parse_resv(source_p, name, reason, temp_time);
140
141 return 0;
142}
143
144/* ms_resv()
8bbeb278 145 * parv[0] = sender prefix
212380e3
AC
146 * parv[1] = target server
147 * parv[2] = channel/nick to forbid
148 * parv[3] = reason
149 */
150static int
8bbeb278 151ms_resv(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
212380e3 152{
8bbeb278
AC
153 /* parv[0] parv[1] parv[2] parv[3]
154 * oper target server resv reason
212380e3
AC
155 */
156 propagate_resv(source_p, parv[1], 0, parv[2], parv[3]);
157
158 if(!match(parv[1], me.name))
159 return 0;
160
161 if(!IsPerson(source_p))
162 return 0;
163
164 parse_resv(source_p, parv[2], parv[3], 0);
165 return 0;
166}
167
168static int
8bbeb278 169me_resv(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
212380e3
AC
170{
171 /* time name 0 :reason */
172 if(!IsPerson(source_p))
173 return 0;
174
175 parse_resv(source_p, parv[2], parv[4], atoi(parv[1]));
176 return 0;
177}
178
179/* parse_resv()
180 *
181 * inputs - source_p if error messages wanted
182 * - thing to resv
183 * - reason for resv
184 * outputs -
185 * side effects - will parse the resv and create it if valid
186 */
187static void
8bbeb278 188parse_resv(struct Client *source_p, const char *name, const char *reason, int temp_time)
212380e3
AC
189{
190 struct ConfItem *aconf;
191
8bbeb278 192 if(!MyClient(source_p) &&
212380e3 193 !find_shared_conf(source_p->username, source_p->host,
8bbeb278
AC
194 source_p->servptr->name,
195 (temp_time > 0) ? SHARED_TRESV : SHARED_PRESV))
212380e3
AC
196 return;
197
198 if(IsChannelName(name))
199 {
200 if(hash_find_resv(name))
201 {
202 sendto_one_notice(source_p,
8bbeb278 203 ":A RESV has already been placed on channel: %s", name);
212380e3
AC
204 return;
205 }
206
207 if(strlen(name) > CHANNELLEN)
208 {
8bbeb278 209 sendto_one_notice(source_p, ":Invalid RESV length: %s", name);
b0f30fa1
JT
210 return;
211 }
212380e3
AC
212
213 if(strchr(reason, '"'))
214 {
8bbeb278 215 sendto_one_notice(source_p, ":Invalid character '\"' in comment");
212380e3
AC
216 return;
217 }
218
219 aconf = make_conf();
220 aconf->status = CONF_RESV_CHANNEL;
221 aconf->port = 0;
b52c2949 222 aconf->created = rb_current_time();
23959371 223 aconf->host = rb_strdup(name);
47a03750 224 aconf->passwd = rb_strdup(reason);
27f616dd 225 aconf->info.oper = operhash_add(get_oper_name(source_p));
23959371 226 add_to_resv_hash(aconf->host, aconf);
43d4d72c 227 resv_chan_forcepart(aconf->host, aconf->passwd, temp_time);
212380e3
AC
228
229 if(temp_time > 0)
230 {
e3354945 231 aconf->hold = rb_current_time() + temp_time;
212380e3
AC
232
233 sendto_realops_snomask(SNO_GENERAL, L_ALL,
8bbeb278
AC
234 "%s added temporary %d min. RESV for [%s] [%s]",
235 get_oper_name(source_p), temp_time / 60,
236 name, reason);
212380e3 237 ilog(L_KLINE, "R %s %d %s %s",
8bbeb278 238 get_oper_name(source_p), temp_time / 60, name, reason);
212380e3 239 sendto_one_notice(source_p, ":Added temporary %d min. RESV [%s]",
8bbeb278 240 temp_time / 60, name);
212380e3
AC
241 }
242 else
00c036b1
AC
243 {
244 sendto_realops_snomask(SNO_GENERAL, L_ALL,
245 "%s added RESV for [%s] [%s]",
246 get_oper_name(source_p), name, reason);
247 ilog(L_KLINE, "R %s 0 %s %s",
248 get_oper_name(source_p), name, reason);
249 sendto_one_notice(source_p, ":Added RESV [%s]", name);
250
23959371 251 bandb_add(BANDB_RESV, source_p, aconf->host, NULL, aconf->passwd, NULL, 0);
00c036b1 252 }
212380e3
AC
253 }
254 else if(clean_resv_nick(name))
255 {
8bbeb278 256 if(strlen(name) > NICKLEN * 2)
212380e3 257 {
8bbeb278 258 sendto_one_notice(source_p, ":Invalid RESV length: %s", name);
212380e3
AC
259 return;
260 }
261
262 if(strchr(reason, '"'))
263 {
8bbeb278 264 sendto_one_notice(source_p, ":Invalid character '\"' in comment");
212380e3
AC
265 return;
266 }
267
268 if(!valid_wild_card_simple(name))
269 {
270 sendto_one_notice(source_p,
8bbeb278
AC
271 ":Please include at least %d non-wildcard "
272 "characters with the resv",
273 ConfigFileEntry.min_nonwildcard_simple);
212380e3
AC
274 return;
275 }
276
0fdb2570 277 if(find_nick_resv_mask(name))
212380e3
AC
278 {
279 sendto_one_notice(source_p,
8bbeb278 280 ":A RESV has already been placed on nick: %s", name);
212380e3
AC
281 return;
282 }
283
284 aconf = make_conf();
285 aconf->status = CONF_RESV_NICK;
286 aconf->port = 0;
b52c2949 287 aconf->created = rb_current_time();
23959371 288 aconf->host = rb_strdup(name);
47a03750 289 aconf->passwd = rb_strdup(reason);
27f616dd 290 aconf->info.oper = operhash_add(get_oper_name(source_p));
7018b86a 291 rb_dlinkAddAlloc(aconf, &resv_conf_list);
212380e3
AC
292
293 if(temp_time > 0)
294 {
e3354945 295 aconf->hold = rb_current_time() + temp_time;
212380e3
AC
296
297 sendto_realops_snomask(SNO_GENERAL, L_ALL,
8bbeb278
AC
298 "%s added temporary %d min. RESV for [%s] [%s]",
299 get_oper_name(source_p), temp_time / 60,
300 name, reason);
212380e3 301 ilog(L_KLINE, "R %s %d %s %s",
8bbeb278 302 get_oper_name(source_p), temp_time / 60, name, reason);
212380e3 303 sendto_one_notice(source_p, ":Added temporary %d min. RESV [%s]",
8bbeb278 304 temp_time / 60, name);
212380e3
AC
305 }
306 else
00c036b1
AC
307 {
308 sendto_realops_snomask(SNO_GENERAL, L_ALL,
309 "%s added RESV for [%s] [%s]",
310 get_oper_name(source_p), name, reason);
311 ilog(L_KLINE, "R %s 0 %s %s",
312 get_oper_name(source_p), name, reason);
313 sendto_one_notice(source_p, ":Added RESV [%s]", name);
314
23959371 315 bandb_add(BANDB_RESV, source_p, aconf->host, NULL, aconf->passwd, NULL, 0);
00c036b1 316 }
212380e3
AC
317 }
318 else
8bbeb278 319 sendto_one_notice(source_p, ":You have specified an invalid resv: [%s]", name);
212380e3
AC
320}
321
8bbeb278 322static void
212380e3 323propagate_resv(struct Client *source_p, const char *target,
8bbeb278 324 int temp_time, const char *name, const char *reason)
212380e3
AC
325{
326 if(!temp_time)
327 {
328 sendto_match_servs(source_p, target,
8bbeb278 329 CAP_CLUSTER, NOCAPS, "RESV %s %s :%s", target, name, reason);
212380e3 330 sendto_match_servs(source_p, target,
8bbeb278
AC
331 CAP_ENCAP, CAP_CLUSTER,
332 "ENCAP %s RESV %d %s 0 :%s", target, temp_time, name, reason);
212380e3
AC
333 }
334 else
335 sendto_match_servs(source_p, target,
8bbeb278
AC
336 CAP_ENCAP, NOCAPS,
337 "ENCAP %s RESV %d %s 0 :%s", target, temp_time, name, reason);
212380e3
AC
338}
339
340static void
8bbeb278 341cluster_resv(struct Client *source_p, int temp_time, const char *name, const char *reason)
212380e3
AC
342{
343 struct remote_conf *shared_p;
5b96d9a6 344 rb_dlink_node *ptr;
212380e3 345
5b96d9a6 346 RB_DLINK_FOREACH(ptr, cluster_conf_list.head)
212380e3
AC
347 {
348 shared_p = ptr->data;
349
350 /* old protocol cant handle temps, and we dont really want
351 * to convert them to perm.. --fl
352 */
353 if(!temp_time)
354 {
355 if(!(shared_p->flags & SHARED_PRESV))
356 continue;
357
358 sendto_match_servs(source_p, shared_p->server,
8bbeb278
AC
359 CAP_CLUSTER, NOCAPS,
360 "RESV %s %s :%s", shared_p->server, name, reason);
212380e3 361 sendto_match_servs(source_p, shared_p->server,
8bbeb278
AC
362 CAP_ENCAP, CAP_CLUSTER,
363 "ENCAP %s RESV 0 %s 0 :%s",
364 shared_p->server, name, reason);
212380e3
AC
365 }
366 else if(shared_p->flags & SHARED_TRESV)
367 sendto_match_servs(source_p, shared_p->server,
8bbeb278
AC
368 CAP_ENCAP, NOCAPS,
369 "ENCAP %s RESV %d %s 0 :%s",
370 shared_p->server, temp_time, name, reason);
212380e3
AC
371 }
372}
373
374
375/*
376 * mo_unresv()
8bbeb278 377 * parv[0] = sender prefix
212380e3
AC
378 * parv[1] = channel/nick to unforbid
379 */
380static int
381mo_unresv(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
382{
1ebe6ffc
JT
383 if(!IsOperResv(source_p))
384 {
8bbeb278 385 sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "resv");
1ebe6ffc
JT
386 return 0;
387 }
388
212380e3
AC
389 if((parc == 4) && (irccmp(parv[2], "ON") == 0))
390 {
391 if(!IsOperRemoteBan(source_p))
392 {
393 sendto_one(source_p, form_str(ERR_NOPRIVS),
8bbeb278 394 me.name, source_p->name, "remoteban");
212380e3
AC
395 return 0;
396 }
397
8bbeb278 398 propagate_generic(source_p, "UNRESV", parv[3], CAP_CLUSTER, "%s", parv[1]);
212380e3
AC
399
400 if(match(parv[3], me.name) == 0)
401 return 0;
402 }
5b96d9a6 403 else if(rb_dlink_list_length(&cluster_conf_list) > 0)
8bbeb278 404 cluster_generic(source_p, "UNRESV", SHARED_UNRESV, CAP_CLUSTER, "%s", parv[1]);
212380e3 405
212380e3
AC
406 remove_resv(source_p, parv[1]);
407 return 0;
408}
409
410/* ms_unresv()
8bbeb278 411 * parv[0] = sender prefix
212380e3
AC
412 * parv[1] = target server
413 * parv[2] = resv to remove
414 */
415static int
416ms_unresv(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
417{
8bbeb278
AC
418 /* parv[0] parv[1] parv[2]
419 * oper target server resv to remove
212380e3 420 */
8bbeb278 421 propagate_generic(source_p, "UNRESV", parv[1], CAP_CLUSTER, "%s", parv[2]);
212380e3
AC
422
423 if(!match(parv[1], me.name))
424 return 0;
425
426 if(!IsPerson(source_p))
427 return 0;
428
429 handle_remote_unresv(source_p, parv[2]);
430 return 0;
431}
432
433static int
434me_unresv(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
435{
436 /* name */
437 if(!IsPerson(source_p))
438 return 0;
439
440 handle_remote_unresv(source_p, parv[1]);
441 return 0;
442}
443
444static void
445handle_remote_unresv(struct Client *source_p, const char *name)
446{
447 if(!find_shared_conf(source_p->username, source_p->host,
8bbeb278 448 source_p->servptr->name, SHARED_UNRESV))
212380e3
AC
449 return;
450
212380e3
AC
451 remove_resv(source_p, name);
452
453 return;
454}
455
1328da86
JT
456static void
457remove_resv(struct Client *source_p, const char *name)
212380e3
AC
458{
459 struct ConfItem *aconf = NULL;
460
461 if(IsChannelName(name))
462 {
463 if((aconf = hash_find_resv(name)) == NULL)
1328da86
JT
464 {
465 sendto_one_notice(source_p, ":No RESV for %s", name);
466 return;
467 }
212380e3 468
a990586f
JT
469 sendto_one_notice(source_p, ":RESV for [%s] is removed", name);
470 ilog(L_KLINE, "UR %s %s", get_oper_name(source_p), name);
212380e3 471 if(!aconf->hold)
1a9ea263 472 {
8bbeb278 473 bandb_del(BANDB_RESV, aconf->host, NULL);
1a9ea263
JT
474 sendto_realops_snomask(SNO_GENERAL, L_ALL,
475 "%s has removed the RESV for: [%s]",
476 get_oper_name(source_p), name);
1a9ea263 477 }
1328da86
JT
478 else
479 {
1328da86 480 sendto_realops_snomask(SNO_GENERAL, L_ALL,
a990586f 481 "%s has removed the temporary RESV for: [%s]",
8bbeb278 482 get_oper_name(source_p), name);
1328da86 483 }
212380e3 484 del_from_resv_hash(name, aconf);
212380e3
AC
485 }
486 else
487 {
5b96d9a6 488 rb_dlink_node *ptr;
212380e3 489
5b96d9a6 490 RB_DLINK_FOREACH(ptr, resv_conf_list.head)
212380e3
AC
491 {
492 aconf = ptr->data;
493
23959371 494 if(irccmp(aconf->host, name))
212380e3
AC
495 aconf = NULL;
496 else
497 break;
498 }
499
500 if(aconf == NULL)
1328da86
JT
501 {
502 sendto_one_notice(source_p, ":No RESV for %s", name);
503 return;
504 }
212380e3 505
212380e3 506 if(!aconf->hold)
8bbeb278 507 bandb_del(BANDB_RESV, aconf->host, NULL);
1328da86
JT
508 else
509 {
510 sendto_one_notice(source_p, ":RESV for [%s] is removed", name);
511 sendto_realops_snomask(SNO_GENERAL, L_ALL,
8bbeb278
AC
512 "%s has removed the RESV for: [%s]",
513 get_oper_name(source_p), name);
1328da86
JT
514 ilog(L_KLINE, "UR %s %s", get_oper_name(source_p), name);
515 }
212380e3 516 /* already have ptr from the loop above.. */
555ac41f 517 rb_dlinkDestroy(ptr, &resv_conf_list);
212380e3 518 }
1328da86 519 free_conf(aconf);
212380e3 520
1328da86 521 return;
212380e3 522}
43d4d72c
JT
523
524static void
525resv_chan_forcepart(const char *name, const char *reason, int temp_time)
526{
527 rb_dlink_node *ptr;
528 rb_dlink_node *next_ptr;
529 struct Channel *chptr;
530 struct membership *msptr;
531 struct Client *target_p;
532
533 if(!ConfigChannel.resv_forcepart)
534 return;
535
536 /* for each user on our server in the channel list
537 * send them a PART, and notify opers.
538 */
539 chptr = find_channel(name);
540 if(chptr != NULL)
541 {
542 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->locmembers.head)
543 {
544 msptr = ptr->data;
545 target_p = msptr->client_p;
546
547 if(IsExemptResv(target_p))
548 continue;
549
550 sendto_server(target_p, chptr, CAP_TS6, NOCAPS,
551 ":%s PART %s", target_p->id, chptr->chname);
552
553 sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s :%s",
554 target_p->name, target_p->username,
555 target_p->host, chptr->chname, target_p->name);
556
557 remove_user_from_channel(msptr);
558
559 /* notify opers & user they were removed from the channel */
560 sendto_realops_snomask(SNO_GENERAL, L_ALL,
561 "Forced PART for %s!%s@%s from %s (%s)",
562 target_p->name, target_p->username,
563 target_p->host, name, reason);
564
565 if(temp_time > 0)
566 sendto_one_notice(target_p, ":*** Channel %s is temporarily unavailable on this server.",
567 name);
568 else
569 sendto_one_notice(target_p, ":*** Channel %s is no longer available on this server.",
570 name);
571 }
572 }
573}