]> jfr.im git - solanum.git/blame - ircd/bandbi.c
extensions/helpops: implement DEHELPER command
[solanum.git] / ircd / bandbi.c
CommitLineData
83595e60
AC
1/* src/bandbi.c
2 * An interface to the ban db.
3 *
4 * Copyright (C) 2006 Lee Hardy <lee -at- leeh.co.uk>
5 * Copyright (C) 2006 ircd-ratbox development team
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * 1.Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
13 * 2.Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3.The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
28 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 * $Id$
32 */
33#include "stdinc.h"
34#include "ratbox_lib.h"
35#include "client.h"
36#include "s_conf.h"
37#include "logger.h"
38#include "match.h"
39#include "bandbi.h"
40#include "parse.h"
41#include "channel.h"
42#include "hostmask.h"
43#include "hash.h"
44#include "s_newconf.h"
45#include "reject.h"
46#include "send.h"
47#include "ircd.h"
48#include "msg.h" /* XXX: MAXPARA */
27f616dd 49#include "operhash.h"
83595e60
AC
50
51static char bandb_add_letter[LAST_BANDB_TYPE] = {
52 'K', 'D', 'X', 'R'
53};
54
55rb_dlink_list bandb_pending;
56
57static rb_helper *bandb_helper;
58static int start_bandb(void);
59
60static void bandb_parse(rb_helper *);
61static void bandb_restart_cb(rb_helper *);
62static char *bandb_path;
63
64void
65init_bandb(void)
66{
67 if(start_bandb())
68 {
69 ilog(L_MAIN, "Unable to start bandb helper: %s", strerror(errno));
70 exit(0);
71 }
72}
73
74
75static int
76start_bandb(void)
77{
78 char fullpath[PATH_MAX + 1];
79#ifdef _WIN32
80 const char *suffix = ".exe";
81#else
82 const char *suffix = "";
83#endif
84
96b8a6ed 85 rb_setenv("BANDB_DBPATH", PKGLOCALSTATEDIR "/ban.db", 1);
83595e60
AC
86 if(bandb_path == NULL)
87 {
c74836dc 88 rb_snprintf(fullpath, sizeof(fullpath), "%s/bandb%s", PKGLIBEXECDIR, suffix);
83595e60
AC
89
90 if(access(fullpath, X_OK) == -1)
91 {
92 rb_snprintf(fullpath, sizeof(fullpath), "%s/bin/bandb%s",
93 ConfigFileEntry.dpath, suffix);
94
95 if(access(fullpath, X_OK) == -1)
96 {
97 ilog(L_MAIN,
c74836dc
NPB
98 "Unable to execute bandb%s in %s or %s/bin",
99 suffix, PKGLIBEXECDIR, ConfigFileEntry.dpath);
83595e60
AC
100 return 0;
101 }
102 }
103 bandb_path = rb_strdup(fullpath);
104 }
105
106
107 bandb_helper = rb_helper_start("bandb", bandb_path, bandb_parse, bandb_restart_cb);
108
109 if(bandb_helper == NULL)
110 {
111 ilog(L_MAIN, "Unable to start bandb: %s", strerror(errno));
112 sendto_realops_snomask(SNO_GENERAL, L_ALL, "Unable to start bandb: %s",
113 strerror(errno));
114 return 1;
115 }
116
117 rb_helper_run(bandb_helper);
118 return 0;
119}
120
121void
122bandb_add(bandb_type type, struct Client *source_p, const char *mask1,
123 const char *mask2, const char *reason, const char *oper_reason, int perm)
124{
c8729b08
KB
125 if(bandb_helper == NULL)
126 return;
127
83595e60
AC
128 static char buf[BUFSIZE];
129
130 rb_snprintf(buf, sizeof(buf), "%c %s ", bandb_add_letter[type], mask1);
131
132 if(!EmptyString(mask2))
133 rb_snprintf_append(buf, sizeof(buf), "%s ", mask2);
134
135 rb_snprintf_append(buf, sizeof(buf), "%s %ld %d :%s",
136 get_oper_name(source_p), (long int)rb_current_time(), perm, reason);
137
138 if(!EmptyString(oper_reason))
139 rb_snprintf_append(buf, sizeof(buf), "|%s", oper_reason);
140
141 rb_helper_write(bandb_helper, "%s", buf);
142}
143
144static char bandb_del_letter[LAST_BANDB_TYPE] = {
145 'k', 'd', 'x', 'r'
146};
147
148void
149bandb_del(bandb_type type, const char *mask1, const char *mask2)
150{
c8729b08
KB
151 if(bandb_helper == NULL)
152 return;
153
83595e60
AC
154 static char buf[BUFSIZE];
155
156 buf[0] = '\0';
157
158 rb_snprintf_append(buf, sizeof(buf), "%c %s", bandb_del_letter[type], mask1);
159
160 if(!EmptyString(mask2))
161 rb_snprintf_append(buf, sizeof(buf), " %s", mask2);
162
163 rb_helper_write(bandb_helper, "%s", buf);
164}
165
166static void
167bandb_handle_ban(char *parv[], int parc)
168{
169 struct ConfItem *aconf;
170 char *p;
171 int para = 1;
172
173 aconf = make_conf();
174 aconf->port = 0;
175
176 if(parv[0][0] == 'K')
177 aconf->user = rb_strdup(parv[para++]);
178
179 aconf->host = rb_strdup(parv[para++]);
27f616dd 180 aconf->info.oper = operhash_add(parv[para++]);
83595e60
AC
181
182 switch (parv[0][0])
183 {
184 case 'K':
185 aconf->status = CONF_KILL;
186 break;
187
188 case 'D':
189 aconf->status = CONF_DLINE;
190 break;
191
192 case 'X':
193 aconf->status = CONF_XLINE;
194 break;
195
196 case 'R':
197 if(IsChannelName(aconf->host))
198 aconf->status = CONF_RESV_CHANNEL;
199 else
200 aconf->status = CONF_RESV_NICK;
201
202 break;
203 }
204
205 if((p = strchr(parv[para], '|')))
206 {
207 *p++ = '\0';
208 aconf->spasswd = rb_strdup(p);
209 }
210
211 aconf->passwd = rb_strdup(parv[para]);
212
213 rb_dlinkAddAlloc(aconf, &bandb_pending);
214}
215
216static int
217bandb_check_kline(struct ConfItem *aconf)
218{
219 struct rb_sockaddr_storage daddr;
220 struct ConfItem *kconf = NULL;
221 int aftype;
222 const char *p;
223
29c92cf9 224 aftype = parse_netmask(aconf->host, &daddr, NULL);
83595e60
AC
225
226 if(aftype != HM_HOST)
227 {
228#ifdef RB_IPV6
229 if(aftype == HM_IPV6)
230 aftype = AF_INET6;
231 else
232#endif
233 aftype = AF_INET;
234
235 kconf = find_conf_by_address(aconf->host, NULL, NULL, (struct sockaddr *)&daddr,
236 CONF_KILL, aftype, aconf->user, NULL);
237 }
238 else
239 kconf = find_conf_by_address(aconf->host, NULL, NULL, NULL, CONF_KILL, 0, aconf->user, NULL);
240
241 if(kconf && ((kconf->flags & CONF_FLAGS_TEMPORARY) == 0))
242 return 0;
243
244 for(p = aconf->user; *p; p++)
245 {
246 if(!IsUserChar(*p) && !IsKWildChar(*p))
247 return 0;
248 }
249
250 for(p = aconf->host; *p; p++)
251 {
252 if(!IsHostChar(*p) && !IsKWildChar(*p))
253 return 0;
254 }
255
256 return 1;
257}
258
259static int
260bandb_check_dline(struct ConfItem *aconf)
261{
262 struct rb_sockaddr_storage daddr;
83595e60
AC
263 int bits;
264
29c92cf9 265 if(!parse_netmask(aconf->host, &daddr, &bits))
83595e60
AC
266 return 0;
267
268 return 1;
269}
270
271static int
272bandb_check_xline(struct ConfItem *aconf)
273{
274 struct ConfItem *xconf;
275 /* XXX perhaps convert spaces to \s? -- jilles */
276
277 xconf = find_xline_mask(aconf->host);
278 if(xconf != NULL && !(xconf->flags & CONF_FLAGS_TEMPORARY))
279 return 0;
280
281 return 1;
282}
283
284static int
285bandb_check_resv_channel(struct ConfItem *aconf)
286{
287 const char *p;
288
289 if(hash_find_resv(aconf->host) || strlen(aconf->host) > CHANNELLEN)
290 return 0;
291
292 for(p = aconf->host; *p; p++)
293 {
294 if(!IsChanChar(*p))
295 return 0;
296 }
297
298 return 1;
299}
300
301static int
302bandb_check_resv_nick(struct ConfItem *aconf)
303{
304 if(!clean_resv_nick(aconf->host))
305 return 0;
306
307 if(find_nick_resv(aconf->host))
308 return 0;
309
310 return 1;
311}
312
313static void
314bandb_handle_clear(void)
315{
316 rb_dlink_node *ptr, *next_ptr;
317
318 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, bandb_pending.head)
319 {
320 free_conf(ptr->data);
321 rb_dlinkDestroy(ptr, &bandb_pending);
322 }
323}
324
325static void
326bandb_handle_finish(void)
327{
328 struct ConfItem *aconf;
329 rb_dlink_node *ptr, *next_ptr;
330
331 clear_out_address_conf_bans();
332 clear_s_newconf_bans();
333
334 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, bandb_pending.head)
335 {
336 aconf = ptr->data;
337
338 rb_dlinkDestroy(ptr, &bandb_pending);
339
340 switch (aconf->status)
341 {
342 case CONF_KILL:
343 if(bandb_check_kline(aconf))
344 add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf);
345 else
346 free_conf(aconf);
347
348 break;
349
350 case CONF_DLINE:
351 if(bandb_check_dline(aconf))
352 add_conf_by_address(aconf->host, CONF_DLINE, aconf->user, NULL, aconf);
353 else
354 free_conf(aconf);
355
356 break;
357
358 case CONF_XLINE:
359 if(bandb_check_xline(aconf))
360 rb_dlinkAddAlloc(aconf, &xline_conf_list);
361 else
362 free_conf(aconf);
363
364 break;
365
366 case CONF_RESV_CHANNEL:
367 if(bandb_check_resv_channel(aconf))
368 add_to_resv_hash(aconf->host, aconf);
369 else
370 free_conf(aconf);
371
372 break;
373
374 case CONF_RESV_NICK:
375 if(bandb_check_resv_nick(aconf))
376 rb_dlinkAddAlloc(aconf, &resv_conf_list);
377 else
378 free_conf(aconf);
379
380 break;
381 }
382 }
383
384 check_banned_lines();
385}
386
387static void
388bandb_handle_failure(rb_helper *helper, char **parv, int parc)
389{
390 if(server_state_foreground)
391 fprintf(stderr, "bandb - bandb failure: %s\n", parv[1]);
55abcbb2 392
83595e60
AC
393 ilog(L_MAIN, "bandb - bandb failure: %s", parv[1]);
394 sendto_realops_snomask(SNO_GENERAL, L_ALL, "bandb - bandb failure: %s", parv[1]);
395 exit(1);
396}
397
398static void
399bandb_parse(rb_helper *helper)
400{
401 static char buf[READBUF_SIZE];
402 char *parv[MAXPARA + 1];
403 int len, parc;
404
405 while((len = rb_helper_read(helper, buf, sizeof(buf))))
406 {
407 parc = rb_string_to_array(buf, parv, MAXPARA);
408
409 if(parc < 1)
410 continue;
411
412 switch (parv[0][0])
413 {
414 case '!':
415 bandb_handle_failure(helper, parv, parc);
416 break;
417 case 'K':
418 case 'D':
419 case 'X':
420 case 'R':
421 bandb_handle_ban(parv, parc);
422 break;
423
424 case 'C':
425 bandb_handle_clear();
624d7791 426 break;
83595e60
AC
427 case 'F':
428 bandb_handle_finish();
429 break;
430 }
431 }
432}
433
434void
435bandb_rehash_bans(void)
436{
437 if(bandb_helper != NULL)
438 rb_helper_write(bandb_helper, "L");
439}
440
441static void
442bandb_restart_cb(rb_helper *helper)
443{
444 ilog(L_MAIN, "bandb - bandb_restart_cb called, bandb helper died?");
445 sendto_realops_snomask(SNO_GENERAL, L_ALL,
446 "bandb - bandb_restart_cb called, bandb helper died?");
447 if(helper != NULL)
448 {
449 rb_helper_close(helper);
450 bandb_helper = NULL;
451 }
452 start_bandb();
453 return;
454}