]> jfr.im git - irc/rqf/shadowircd.git/blame - src/bandbi.c
Fix bandb's interaction with --enable-fhs-paths by storing ban.db in the correct...
[irc/rqf/shadowircd.git] / src / bandbi.c
CommitLineData
2c9a27c4
WP
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 */
a0f4c418 49#include "operhash.h"
2c9a27c4
WP
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
6bdef3d5 85 rb_setenv("BANDB_DBPATH", PKGLOCALSTATEDIR "/ban.db", 1);
2c9a27c4
WP
86 if(bandb_path == NULL)
87 {
e8da6cce 88 rb_snprintf(fullpath, sizeof(fullpath), "%s/bandb%s", PKGLIBEXECDIR, suffix);
2c9a27c4
WP
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,
e8da6cce
NPB
98 "Unable to execute bandb%s in %s or %s/bin",
99 suffix, PKGLIBEXECDIR, ConfigFileEntry.dpath);
2c9a27c4
WP
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{
125 static char buf[BUFSIZE];
126
127 rb_snprintf(buf, sizeof(buf), "%c %s ", bandb_add_letter[type], mask1);
128
129 if(!EmptyString(mask2))
130 rb_snprintf_append(buf, sizeof(buf), "%s ", mask2);
131
132 rb_snprintf_append(buf, sizeof(buf), "%s %ld %d :%s",
133 get_oper_name(source_p), (long int)rb_current_time(), perm, reason);
134
135 if(!EmptyString(oper_reason))
136 rb_snprintf_append(buf, sizeof(buf), "|%s", oper_reason);
137
138 rb_helper_write(bandb_helper, "%s", buf);
139}
140
141static char bandb_del_letter[LAST_BANDB_TYPE] = {
142 'k', 'd', 'x', 'r'
143};
144
145void
146bandb_del(bandb_type type, const char *mask1, const char *mask2)
147{
148 static char buf[BUFSIZE];
149
150 buf[0] = '\0';
151
152 rb_snprintf_append(buf, sizeof(buf), "%c %s", bandb_del_letter[type], mask1);
153
154 if(!EmptyString(mask2))
155 rb_snprintf_append(buf, sizeof(buf), " %s", mask2);
156
157 rb_helper_write(bandb_helper, "%s", buf);
158}
159
160static void
161bandb_handle_ban(char *parv[], int parc)
162{
163 struct ConfItem *aconf;
164 char *p;
165 int para = 1;
166
167 aconf = make_conf();
168 aconf->port = 0;
169
170 if(parv[0][0] == 'K')
171 aconf->user = rb_strdup(parv[para++]);
172
173 aconf->host = rb_strdup(parv[para++]);
a0f4c418 174 aconf->info.oper = operhash_add(parv[para++]);
2c9a27c4
WP
175
176 switch (parv[0][0])
177 {
178 case 'K':
179 aconf->status = CONF_KILL;
180 break;
181
182 case 'D':
183 aconf->status = CONF_DLINE;
184 break;
185
186 case 'X':
187 aconf->status = CONF_XLINE;
188 break;
189
190 case 'R':
191 if(IsChannelName(aconf->host))
192 aconf->status = CONF_RESV_CHANNEL;
193 else
194 aconf->status = CONF_RESV_NICK;
195
196 break;
197 }
198
199 if((p = strchr(parv[para], '|')))
200 {
201 *p++ = '\0';
202 aconf->spasswd = rb_strdup(p);
203 }
204
205 aconf->passwd = rb_strdup(parv[para]);
206
207 rb_dlinkAddAlloc(aconf, &bandb_pending);
208}
209
210static int
211bandb_check_kline(struct ConfItem *aconf)
212{
213 struct rb_sockaddr_storage daddr;
214 struct ConfItem *kconf = NULL;
215 int aftype;
216 const char *p;
217
218 aftype = parse_netmask(aconf->host, (struct sockaddr *)&daddr, NULL);
219
220 if(aftype != HM_HOST)
221 {
222#ifdef RB_IPV6
223 if(aftype == HM_IPV6)
224 aftype = AF_INET6;
225 else
226#endif
227 aftype = AF_INET;
228
229 kconf = find_conf_by_address(aconf->host, NULL, NULL, (struct sockaddr *)&daddr,
230 CONF_KILL, aftype, aconf->user, NULL);
231 }
232 else
233 kconf = find_conf_by_address(aconf->host, NULL, NULL, NULL, CONF_KILL, 0, aconf->user, NULL);
234
235 if(kconf && ((kconf->flags & CONF_FLAGS_TEMPORARY) == 0))
236 return 0;
237
238 for(p = aconf->user; *p; p++)
239 {
240 if(!IsUserChar(*p) && !IsKWildChar(*p))
241 return 0;
242 }
243
244 for(p = aconf->host; *p; p++)
245 {
246 if(!IsHostChar(*p) && !IsKWildChar(*p))
247 return 0;
248 }
249
250 return 1;
251}
252
253static int
254bandb_check_dline(struct ConfItem *aconf)
255{
256 struct rb_sockaddr_storage daddr;
257/* struct ConfItem *dconf; */
258 int bits;
259
260 if(!parse_netmask(aconf->host, (struct sockaddr *)&daddr, &bits))
261 return 0;
262
263 return 1;
264}
265
266static int
267bandb_check_xline(struct ConfItem *aconf)
268{
269 struct ConfItem *xconf;
270 /* XXX perhaps convert spaces to \s? -- jilles */
271
272 xconf = find_xline_mask(aconf->host);
273 if(xconf != NULL && !(xconf->flags & CONF_FLAGS_TEMPORARY))
274 return 0;
275
276 return 1;
277}
278
279static int
280bandb_check_resv_channel(struct ConfItem *aconf)
281{
282 const char *p;
283
284 if(hash_find_resv(aconf->host) || strlen(aconf->host) > CHANNELLEN)
285 return 0;
286
287 for(p = aconf->host; *p; p++)
288 {
289 if(!IsChanChar(*p))
290 return 0;
291 }
292
293 return 1;
294}
295
296static int
297bandb_check_resv_nick(struct ConfItem *aconf)
298{
299 if(!clean_resv_nick(aconf->host))
300 return 0;
301
302 if(find_nick_resv(aconf->host))
303 return 0;
304
305 return 1;
306}
307
308static void
309bandb_handle_clear(void)
310{
311 rb_dlink_node *ptr, *next_ptr;
312
313 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, bandb_pending.head)
314 {
315 free_conf(ptr->data);
316 rb_dlinkDestroy(ptr, &bandb_pending);
317 }
318}
319
320static void
321bandb_handle_finish(void)
322{
323 struct ConfItem *aconf;
324 rb_dlink_node *ptr, *next_ptr;
325
326 clear_out_address_conf_bans();
327 clear_s_newconf_bans();
328
329 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, bandb_pending.head)
330 {
331 aconf = ptr->data;
332
333 rb_dlinkDestroy(ptr, &bandb_pending);
334
335 switch (aconf->status)
336 {
337 case CONF_KILL:
338 if(bandb_check_kline(aconf))
339 add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf);
340 else
341 free_conf(aconf);
342
343 break;
344
345 case CONF_DLINE:
346 if(bandb_check_dline(aconf))
347 add_conf_by_address(aconf->host, CONF_DLINE, aconf->user, NULL, aconf);
348 else
349 free_conf(aconf);
350
351 break;
352
353 case CONF_XLINE:
354 if(bandb_check_xline(aconf))
355 rb_dlinkAddAlloc(aconf, &xline_conf_list);
356 else
357 free_conf(aconf);
358
359 break;
360
361 case CONF_RESV_CHANNEL:
362 if(bandb_check_resv_channel(aconf))
363 add_to_resv_hash(aconf->host, aconf);
364 else
365 free_conf(aconf);
366
367 break;
368
369 case CONF_RESV_NICK:
370 if(bandb_check_resv_nick(aconf))
371 rb_dlinkAddAlloc(aconf, &resv_conf_list);
372 else
373 free_conf(aconf);
374
375 break;
376 }
377 }
378
379 check_banned_lines();
380}
381
382static void
383bandb_handle_failure(rb_helper *helper, char **parv, int parc)
384{
385 if(server_state_foreground)
386 fprintf(stderr, "bandb - bandb failure: %s\n", parv[1]);
387
388 ilog(L_MAIN, "bandb - bandb failure: %s", parv[1]);
389 sendto_realops_snomask(SNO_GENERAL, L_ALL, "bandb - bandb failure: %s", parv[1]);
390 exit(1);
391}
392
393static void
394bandb_parse(rb_helper *helper)
395{
396 static char buf[READBUF_SIZE];
397 char *parv[MAXPARA + 1];
398 int len, parc;
399
400 while((len = rb_helper_read(helper, buf, sizeof(buf))))
401 {
402 parc = rb_string_to_array(buf, parv, MAXPARA);
403
404 if(parc < 1)
405 continue;
406
407 switch (parv[0][0])
408 {
409 case '!':
410 bandb_handle_failure(helper, parv, parc);
411 break;
412 case 'K':
413 case 'D':
414 case 'X':
415 case 'R':
416 bandb_handle_ban(parv, parc);
417 break;
418
419 case 'C':
420 bandb_handle_clear();
421 case 'F':
422 bandb_handle_finish();
423 break;
424 }
425 }
426}
427
428void
429bandb_rehash_bans(void)
430{
431 if(bandb_helper != NULL)
432 rb_helper_write(bandb_helper, "L");
433}
434
435static void
436bandb_restart_cb(rb_helper *helper)
437{
438 ilog(L_MAIN, "bandb - bandb_restart_cb called, bandb helper died?");
439 sendto_realops_snomask(SNO_GENERAL, L_ALL,
440 "bandb - bandb_restart_cb called, bandb helper died?");
441 if(helper != NULL)
442 {
443 rb_helper_close(helper);
444 bandb_helper = NULL;
445 }
446 start_bandb();
447 return;
448}