]> jfr.im git - solanum.git/blame - src/bandbi.c
Merge pull request #53 from ShadowNinja/clarify_U+R
[solanum.git] / src / 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
224 aftype = parse_netmask(aconf->host, (struct sockaddr *)&daddr, NULL);
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;
263/* struct ConfItem *dconf; */
264 int bits;
265
266 if(!parse_netmask(aconf->host, (struct sockaddr *)&daddr, &bits))
267 return 0;
268
269 return 1;
270}
271
272static int
273bandb_check_xline(struct ConfItem *aconf)
274{
275 struct ConfItem *xconf;
276 /* XXX perhaps convert spaces to \s? -- jilles */
277
278 xconf = find_xline_mask(aconf->host);
279 if(xconf != NULL && !(xconf->flags & CONF_FLAGS_TEMPORARY))
280 return 0;
281
282 return 1;
283}
284
285static int
286bandb_check_resv_channel(struct ConfItem *aconf)
287{
288 const char *p;
289
290 if(hash_find_resv(aconf->host) || strlen(aconf->host) > CHANNELLEN)
291 return 0;
292
293 for(p = aconf->host; *p; p++)
294 {
295 if(!IsChanChar(*p))
296 return 0;
297 }
298
299 return 1;
300}
301
302static int
303bandb_check_resv_nick(struct ConfItem *aconf)
304{
305 if(!clean_resv_nick(aconf->host))
306 return 0;
307
308 if(find_nick_resv(aconf->host))
309 return 0;
310
311 return 1;
312}
313
314static void
315bandb_handle_clear(void)
316{
317 rb_dlink_node *ptr, *next_ptr;
318
319 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, bandb_pending.head)
320 {
321 free_conf(ptr->data);
322 rb_dlinkDestroy(ptr, &bandb_pending);
323 }
324}
325
326static void
327bandb_handle_finish(void)
328{
329 struct ConfItem *aconf;
330 rb_dlink_node *ptr, *next_ptr;
331
332 clear_out_address_conf_bans();
333 clear_s_newconf_bans();
334
335 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, bandb_pending.head)
336 {
337 aconf = ptr->data;
338
339 rb_dlinkDestroy(ptr, &bandb_pending);
340
341 switch (aconf->status)
342 {
343 case CONF_KILL:
344 if(bandb_check_kline(aconf))
345 add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf);
346 else
347 free_conf(aconf);
348
349 break;
350
351 case CONF_DLINE:
352 if(bandb_check_dline(aconf))
353 add_conf_by_address(aconf->host, CONF_DLINE, aconf->user, NULL, aconf);
354 else
355 free_conf(aconf);
356
357 break;
358
359 case CONF_XLINE:
360 if(bandb_check_xline(aconf))
361 rb_dlinkAddAlloc(aconf, &xline_conf_list);
362 else
363 free_conf(aconf);
364
365 break;
366
367 case CONF_RESV_CHANNEL:
368 if(bandb_check_resv_channel(aconf))
369 add_to_resv_hash(aconf->host, aconf);
370 else
371 free_conf(aconf);
372
373 break;
374
375 case CONF_RESV_NICK:
376 if(bandb_check_resv_nick(aconf))
377 rb_dlinkAddAlloc(aconf, &resv_conf_list);
378 else
379 free_conf(aconf);
380
381 break;
382 }
383 }
384
385 check_banned_lines();
386}
387
388static void
389bandb_handle_failure(rb_helper *helper, char **parv, int parc)
390{
391 if(server_state_foreground)
392 fprintf(stderr, "bandb - bandb failure: %s\n", parv[1]);
55abcbb2 393
83595e60
AC
394 ilog(L_MAIN, "bandb - bandb failure: %s", parv[1]);
395 sendto_realops_snomask(SNO_GENERAL, L_ALL, "bandb - bandb failure: %s", parv[1]);
396 exit(1);
397}
398
399static void
400bandb_parse(rb_helper *helper)
401{
402 static char buf[READBUF_SIZE];
403 char *parv[MAXPARA + 1];
404 int len, parc;
405
406 while((len = rb_helper_read(helper, buf, sizeof(buf))))
407 {
408 parc = rb_string_to_array(buf, parv, MAXPARA);
409
410 if(parc < 1)
411 continue;
412
413 switch (parv[0][0])
414 {
415 case '!':
416 bandb_handle_failure(helper, parv, parc);
417 break;
418 case 'K':
419 case 'D':
420 case 'X':
421 case 'R':
422 bandb_handle_ban(parv, parc);
423 break;
424
425 case 'C':
426 bandb_handle_clear();
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}