]> jfr.im git - solanum.git/blame - ircd/bandbi.c
Support more human friendly k/d/x-line duration format
[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.
83595e60
AC
30 */
31#include "stdinc.h"
fe037171 32#include "rb_lib.h"
83595e60
AC
33#include "client.h"
34#include "s_conf.h"
35#include "logger.h"
36#include "match.h"
37#include "bandbi.h"
38#include "parse.h"
39#include "channel.h"
40#include "hostmask.h"
41#include "hash.h"
42#include "s_newconf.h"
43#include "reject.h"
44#include "send.h"
45#include "ircd.h"
46#include "msg.h" /* XXX: MAXPARA */
27f616dd 47#include "operhash.h"
83595e60 48
2ce25d94
AJ
49static void
50bandb_handle_failure(rb_helper *helper, char **parv, int parc) __attribute__((noreturn));
51
83595e60
AC
52static char bandb_add_letter[LAST_BANDB_TYPE] = {
53 'K', 'D', 'X', 'R'
54};
55
56rb_dlink_list bandb_pending;
57
58static rb_helper *bandb_helper;
59static int start_bandb(void);
60
61static void bandb_parse(rb_helper *);
62static void bandb_restart_cb(rb_helper *);
63static char *bandb_path;
64
65void
66init_bandb(void)
67{
68 if(start_bandb())
69 {
70 ilog(L_MAIN, "Unable to start bandb helper: %s", strerror(errno));
71 exit(0);
72 }
73}
74
75
76static int
77start_bandb(void)
78{
79 char fullpath[PATH_MAX + 1];
83595e60 80
4d8cfacd 81 rb_setenv("BANDB_DBPATH", ircd_paths[IRCD_PATH_BANDB], 1);
83595e60
AC
82 if(bandb_path == NULL)
83 {
8f0c3422 84 snprintf(fullpath, sizeof(fullpath), "%s/bandb", ircd_paths[IRCD_PATH_LIBEXEC]);
83595e60
AC
85
86 if(access(fullpath, X_OK) == -1)
87 {
8f0c3422 88 snprintf(fullpath, sizeof(fullpath), "%s/bin/bandb", ConfigFileEntry.dpath);
83595e60
AC
89
90 if(access(fullpath, X_OK) == -1)
91 {
92 ilog(L_MAIN,
8f0c3422 93 "Unable to execute bandb in %s or %s/bin",
94 ircd_paths[IRCD_PATH_LIBEXEC], ConfigFileEntry.dpath);
83595e60
AC
95 return 0;
96 }
97 }
98 bandb_path = rb_strdup(fullpath);
99 }
100
101
102 bandb_helper = rb_helper_start("bandb", bandb_path, bandb_parse, bandb_restart_cb);
103
104 if(bandb_helper == NULL)
105 {
106 ilog(L_MAIN, "Unable to start bandb: %s", strerror(errno));
a9227555 107 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Unable to start bandb: %s",
83595e60
AC
108 strerror(errno));
109 return 1;
110 }
111
112 rb_helper_run(bandb_helper);
113 return 0;
114}
115
116void
117bandb_add(bandb_type type, struct Client *source_p, const char *mask1,
118 const char *mask2, const char *reason, const char *oper_reason, int perm)
119{
c8729b08
KB
120 if(bandb_helper == NULL)
121 return;
122
83595e60
AC
123 static char buf[BUFSIZE];
124
5203cba5 125 snprintf(buf, sizeof(buf), "%c %s ", bandb_add_letter[type], mask1);
83595e60
AC
126
127 if(!EmptyString(mask2))
128 rb_snprintf_append(buf, sizeof(buf), "%s ", mask2);
129
130 rb_snprintf_append(buf, sizeof(buf), "%s %ld %d :%s",
131 get_oper_name(source_p), (long int)rb_current_time(), perm, reason);
132
133 if(!EmptyString(oper_reason))
134 rb_snprintf_append(buf, sizeof(buf), "|%s", oper_reason);
135
136 rb_helper_write(bandb_helper, "%s", buf);
137}
138
139static char bandb_del_letter[LAST_BANDB_TYPE] = {
140 'k', 'd', 'x', 'r'
141};
142
143void
144bandb_del(bandb_type type, const char *mask1, const char *mask2)
145{
c8729b08
KB
146 if(bandb_helper == NULL)
147 return;
148
83595e60
AC
149 static char buf[BUFSIZE];
150
151 buf[0] = '\0';
152
153 rb_snprintf_append(buf, sizeof(buf), "%c %s", bandb_del_letter[type], mask1);
154
155 if(!EmptyString(mask2))
156 rb_snprintf_append(buf, sizeof(buf), " %s", mask2);
157
158 rb_helper_write(bandb_helper, "%s", buf);
159}
160
161static void
162bandb_handle_ban(char *parv[], int parc)
163{
164 struct ConfItem *aconf;
165 char *p;
166 int para = 1;
167
168 aconf = make_conf();
169 aconf->port = 0;
170
171 if(parv[0][0] == 'K')
172 aconf->user = rb_strdup(parv[para++]);
173
174 aconf->host = rb_strdup(parv[para++]);
27f616dd 175 aconf->info.oper = operhash_add(parv[para++]);
83595e60
AC
176
177 switch (parv[0][0])
178 {
179 case 'K':
180 aconf->status = CONF_KILL;
181 break;
182
183 case 'D':
184 aconf->status = CONF_DLINE;
185 break;
186
187 case 'X':
188 aconf->status = CONF_XLINE;
189 break;
190
191 case 'R':
192 if(IsChannelName(aconf->host))
193 aconf->status = CONF_RESV_CHANNEL;
194 else
195 aconf->status = CONF_RESV_NICK;
196
197 break;
198 }
199
200 if((p = strchr(parv[para], '|')))
201 {
202 *p++ = '\0';
203 aconf->spasswd = rb_strdup(p);
204 }
205
206 aconf->passwd = rb_strdup(parv[para]);
207
208 rb_dlinkAddAlloc(aconf, &bandb_pending);
209}
210
211static int
212bandb_check_kline(struct ConfItem *aconf)
213{
214 struct rb_sockaddr_storage daddr;
215 struct ConfItem *kconf = NULL;
216 int aftype;
217 const char *p;
218
29c92cf9 219 aftype = parse_netmask(aconf->host, &daddr, NULL);
83595e60
AC
220
221 if(aftype != HM_HOST)
222 {
83595e60
AC
223 if(aftype == HM_IPV6)
224 aftype = AF_INET6;
225 else
83595e60
AC
226 aftype = AF_INET;
227
228 kconf = find_conf_by_address(aconf->host, NULL, NULL, (struct sockaddr *)&daddr,
229 CONF_KILL, aftype, aconf->user, NULL);
230 }
231 else
232 kconf = find_conf_by_address(aconf->host, NULL, NULL, NULL, CONF_KILL, 0, aconf->user, NULL);
233
234 if(kconf && ((kconf->flags & CONF_FLAGS_TEMPORARY) == 0))
235 return 0;
236
237 for(p = aconf->user; *p; p++)
238 {
239 if(!IsUserChar(*p) && !IsKWildChar(*p))
240 return 0;
241 }
242
243 for(p = aconf->host; *p; p++)
244 {
245 if(!IsHostChar(*p) && !IsKWildChar(*p))
246 return 0;
247 }
248
249 return 1;
250}
251
252static int
253bandb_check_dline(struct ConfItem *aconf)
254{
255 struct rb_sockaddr_storage daddr;
83595e60
AC
256 int bits;
257
29c92cf9 258 if(!parse_netmask(aconf->host, &daddr, &bits))
83595e60
AC
259 return 0;
260
261 return 1;
262}
263
264static int
265bandb_check_xline(struct ConfItem *aconf)
266{
267 struct ConfItem *xconf;
268 /* XXX perhaps convert spaces to \s? -- jilles */
269
270 xconf = find_xline_mask(aconf->host);
271 if(xconf != NULL && !(xconf->flags & CONF_FLAGS_TEMPORARY))
272 return 0;
273
274 return 1;
275}
276
277static int
278bandb_check_resv_channel(struct ConfItem *aconf)
279{
280 const char *p;
281
282 if(hash_find_resv(aconf->host) || strlen(aconf->host) > CHANNELLEN)
283 return 0;
284
285 for(p = aconf->host; *p; p++)
286 {
287 if(!IsChanChar(*p))
288 return 0;
289 }
290
291 return 1;
292}
293
294static int
295bandb_check_resv_nick(struct ConfItem *aconf)
296{
297 if(!clean_resv_nick(aconf->host))
298 return 0;
299
300 if(find_nick_resv(aconf->host))
301 return 0;
302
303 return 1;
304}
305
306static void
307bandb_handle_clear(void)
308{
309 rb_dlink_node *ptr, *next_ptr;
310
311 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, bandb_pending.head)
312 {
313 free_conf(ptr->data);
314 rb_dlinkDestroy(ptr, &bandb_pending);
315 }
316}
317
318static void
319bandb_handle_finish(void)
320{
321 struct ConfItem *aconf;
322 rb_dlink_node *ptr, *next_ptr;
323
625cbb19 324 clear_out_address_conf(AC_BANDB);
83595e60
AC
325 clear_s_newconf_bans();
326
327 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, bandb_pending.head)
328 {
329 aconf = ptr->data;
330
331 rb_dlinkDestroy(ptr, &bandb_pending);
332
333 switch (aconf->status)
334 {
335 case CONF_KILL:
336 if(bandb_check_kline(aconf))
337 add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf);
338 else
339 free_conf(aconf);
340
341 break;
342
343 case CONF_DLINE:
344 if(bandb_check_dline(aconf))
345 add_conf_by_address(aconf->host, CONF_DLINE, aconf->user, NULL, aconf);
346 else
347 free_conf(aconf);
348
349 break;
350
351 case CONF_XLINE:
352 if(bandb_check_xline(aconf))
353 rb_dlinkAddAlloc(aconf, &xline_conf_list);
354 else
355 free_conf(aconf);
356
357 break;
358
359 case CONF_RESV_CHANNEL:
360 if(bandb_check_resv_channel(aconf))
361 add_to_resv_hash(aconf->host, aconf);
362 else
363 free_conf(aconf);
364
365 break;
366
367 case CONF_RESV_NICK:
368 if(bandb_check_resv_nick(aconf))
369 rb_dlinkAddAlloc(aconf, &resv_conf_list);
370 else
371 free_conf(aconf);
372
373 break;
374 }
375 }
376
377 check_banned_lines();
378}
379
380static void
381bandb_handle_failure(rb_helper *helper, char **parv, int parc)
382{
383 if(server_state_foreground)
384 fprintf(stderr, "bandb - bandb failure: %s\n", parv[1]);
55abcbb2 385
83595e60 386 ilog(L_MAIN, "bandb - bandb failure: %s", parv[1]);
a9227555 387 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "bandb - bandb failure: %s", parv[1]);
83595e60
AC
388 exit(1);
389}
390
391static void
392bandb_parse(rb_helper *helper)
393{
394 static char buf[READBUF_SIZE];
33ded5fc 395 char *parv[MAXPARA];
83595e60
AC
396 int len, parc;
397
398 while((len = rb_helper_read(helper, buf, sizeof(buf))))
399 {
33ded5fc 400 parc = rb_string_to_array(buf, parv, sizeof(parv));
83595e60
AC
401
402 if(parc < 1)
403 continue;
404
405 switch (parv[0][0])
406 {
407 case '!':
408 bandb_handle_failure(helper, parv, parc);
409 break;
410 case 'K':
411 case 'D':
412 case 'X':
413 case 'R':
414 bandb_handle_ban(parv, parc);
415 break;
416
417 case 'C':
418 bandb_handle_clear();
624d7791 419 break;
83595e60
AC
420 case 'F':
421 bandb_handle_finish();
422 break;
423 }
424 }
425}
426
427void
428bandb_rehash_bans(void)
429{
430 if(bandb_helper != NULL)
431 rb_helper_write(bandb_helper, "L");
432}
433
434static void
435bandb_restart_cb(rb_helper *helper)
436{
437 ilog(L_MAIN, "bandb - bandb_restart_cb called, bandb helper died?");
a9227555 438 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
83595e60
AC
439 "bandb - bandb_restart_cb called, bandb helper died?");
440 if(helper != NULL)
441 {
442 rb_helper_close(helper);
443 bandb_helper = NULL;
444 }
445 start_bandb();
446 return;
447}