]> jfr.im git - irc/rqf/shadowircd.git/blob - src/bandbi.c
5c9933e26b483e28374eec3c6828037ba785c973
[irc/rqf/shadowircd.git] / src / bandbi.c
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 */
49 #include "operhash.h"
50
51 static char bandb_add_letter[LAST_BANDB_TYPE] = {
52 'K', 'D', 'X', 'R'
53 };
54
55 rb_dlink_list bandb_pending;
56
57 static rb_helper *bandb_helper;
58 static int start_bandb(void);
59
60 static void bandb_parse(rb_helper *);
61 static void bandb_restart_cb(rb_helper *);
62 static char *bandb_path;
63
64 void
65 init_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
75 static int
76 start_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
85 rb_setenv("BANDB_DPATH", ConfigFileEntry.dpath, 1);
86 if(bandb_path == NULL)
87 {
88 rb_snprintf(fullpath, sizeof(fullpath), "%s/bandb%s", PKGLIBEXECDIR, suffix);
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,
98 "Unable to execute bandb%s in %s or %s/bin",
99 suffix, PKGLIBEXECDIR, ConfigFileEntry.dpath);
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
121 void
122 bandb_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
141 static char bandb_del_letter[LAST_BANDB_TYPE] = {
142 'k', 'd', 'x', 'r'
143 };
144
145 void
146 bandb_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
160 static void
161 bandb_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++]);
174 aconf->info.oper = operhash_add(parv[para++]);
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
210 static int
211 bandb_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
253 static int
254 bandb_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
266 static int
267 bandb_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
279 static int
280 bandb_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
296 static int
297 bandb_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
308 static void
309 bandb_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
320 static void
321 bandb_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
382 static void
383 bandb_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
393 static void
394 bandb_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
428 void
429 bandb_rehash_bans(void)
430 {
431 if(bandb_helper != NULL)
432 rb_helper_write(bandb_helper, "L");
433 }
434
435 static void
436 bandb_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 }