]> jfr.im git - solanum.git/blob - ircd/bandbi.c
Add .travis.yml
[solanum.git] / ircd / 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_DBPATH", PKGLOCALSTATEDIR "/ban.db", 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 if(bandb_helper == NULL)
126 return;
127
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
144 static char bandb_del_letter[LAST_BANDB_TYPE] = {
145 'k', 'd', 'x', 'r'
146 };
147
148 void
149 bandb_del(bandb_type type, const char *mask1, const char *mask2)
150 {
151 if(bandb_helper == NULL)
152 return;
153
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
166 static void
167 bandb_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++]);
180 aconf->info.oper = operhash_add(parv[para++]);
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
216 static int
217 bandb_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, &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
259 static int
260 bandb_check_dline(struct ConfItem *aconf)
261 {
262 struct rb_sockaddr_storage daddr;
263 int bits;
264
265 if(!parse_netmask(aconf->host, &daddr, &bits))
266 return 0;
267
268 return 1;
269 }
270
271 static int
272 bandb_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
284 static int
285 bandb_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
301 static int
302 bandb_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
313 static void
314 bandb_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
325 static void
326 bandb_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
387 static void
388 bandb_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]);
392
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
398 static void
399 bandb_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();
426 break;
427 case 'F':
428 bandb_handle_finish();
429 break;
430 }
431 }
432 }
433
434 void
435 bandb_rehash_bans(void)
436 {
437 if(bandb_helper != NULL)
438 rb_helper_write(bandb_helper, "L");
439 }
440
441 static void
442 bandb_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 }