]> jfr.im git - solanum.git/blob - ircd/bandbi.c
librb: remove unnecessary NULL from the end of rb_string_to_array output
[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 #include "stdinc.h"
32 #include "rb_lib.h"
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 */
47 #include "operhash.h"
48
49 static void
50 bandb_handle_failure(rb_helper *helper, char **parv, int parc) __attribute__((noreturn));
51
52 static char bandb_add_letter[LAST_BANDB_TYPE] = {
53 'K', 'D', 'X', 'R'
54 };
55
56 rb_dlink_list bandb_pending;
57
58 static rb_helper *bandb_helper;
59 static int start_bandb(void);
60
61 static void bandb_parse(rb_helper *);
62 static void bandb_restart_cb(rb_helper *);
63 static char *bandb_path;
64
65 void
66 init_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
76 static int
77 start_bandb(void)
78 {
79 char fullpath[PATH_MAX + 1];
80 #ifdef _WIN32
81 const char *suffix = ".exe";
82 #else
83 const char *suffix = "";
84 #endif
85
86 rb_setenv("BANDB_DBPATH", ircd_paths[IRCD_PATH_BANDB], 1);
87 if(bandb_path == NULL)
88 {
89 snprintf(fullpath, sizeof(fullpath), "%s%cbandb%s", ircd_paths[IRCD_PATH_LIBEXEC], RB_PATH_SEPARATOR, suffix);
90
91 if(access(fullpath, X_OK) == -1)
92 {
93 snprintf(fullpath, sizeof(fullpath), "%s%cbin%cbandb%s",
94 ConfigFileEntry.dpath, RB_PATH_SEPARATOR, RB_PATH_SEPARATOR, suffix);
95
96 if(access(fullpath, X_OK) == -1)
97 {
98 ilog(L_MAIN,
99 "Unable to execute bandb%s in %s or %s/bin",
100 suffix, ircd_paths[IRCD_PATH_LIBEXEC], ConfigFileEntry.dpath);
101 return 0;
102 }
103 }
104 bandb_path = rb_strdup(fullpath);
105 }
106
107
108 bandb_helper = rb_helper_start("bandb", bandb_path, bandb_parse, bandb_restart_cb);
109
110 if(bandb_helper == NULL)
111 {
112 ilog(L_MAIN, "Unable to start bandb: %s", strerror(errno));
113 sendto_realops_snomask(SNO_GENERAL, L_ALL, "Unable to start bandb: %s",
114 strerror(errno));
115 return 1;
116 }
117
118 rb_helper_run(bandb_helper);
119 return 0;
120 }
121
122 void
123 bandb_add(bandb_type type, struct Client *source_p, const char *mask1,
124 const char *mask2, const char *reason, const char *oper_reason, int perm)
125 {
126 if(bandb_helper == NULL)
127 return;
128
129 static char buf[BUFSIZE];
130
131 snprintf(buf, sizeof(buf), "%c %s ", bandb_add_letter[type], mask1);
132
133 if(!EmptyString(mask2))
134 rb_snprintf_append(buf, sizeof(buf), "%s ", mask2);
135
136 rb_snprintf_append(buf, sizeof(buf), "%s %ld %d :%s",
137 get_oper_name(source_p), (long int)rb_current_time(), perm, reason);
138
139 if(!EmptyString(oper_reason))
140 rb_snprintf_append(buf, sizeof(buf), "|%s", oper_reason);
141
142 rb_helper_write(bandb_helper, "%s", buf);
143 }
144
145 static char bandb_del_letter[LAST_BANDB_TYPE] = {
146 'k', 'd', 'x', 'r'
147 };
148
149 void
150 bandb_del(bandb_type type, const char *mask1, const char *mask2)
151 {
152 if(bandb_helper == NULL)
153 return;
154
155 static char buf[BUFSIZE];
156
157 buf[0] = '\0';
158
159 rb_snprintf_append(buf, sizeof(buf), "%c %s", bandb_del_letter[type], mask1);
160
161 if(!EmptyString(mask2))
162 rb_snprintf_append(buf, sizeof(buf), " %s", mask2);
163
164 rb_helper_write(bandb_helper, "%s", buf);
165 }
166
167 static void
168 bandb_handle_ban(char *parv[], int parc)
169 {
170 struct ConfItem *aconf;
171 char *p;
172 int para = 1;
173
174 aconf = make_conf();
175 aconf->port = 0;
176
177 if(parv[0][0] == 'K')
178 aconf->user = rb_strdup(parv[para++]);
179
180 aconf->host = rb_strdup(parv[para++]);
181 aconf->info.oper = operhash_add(parv[para++]);
182
183 switch (parv[0][0])
184 {
185 case 'K':
186 aconf->status = CONF_KILL;
187 break;
188
189 case 'D':
190 aconf->status = CONF_DLINE;
191 break;
192
193 case 'X':
194 aconf->status = CONF_XLINE;
195 break;
196
197 case 'R':
198 if(IsChannelName(aconf->host))
199 aconf->status = CONF_RESV_CHANNEL;
200 else
201 aconf->status = CONF_RESV_NICK;
202
203 break;
204 }
205
206 if((p = strchr(parv[para], '|')))
207 {
208 *p++ = '\0';
209 aconf->spasswd = rb_strdup(p);
210 }
211
212 aconf->passwd = rb_strdup(parv[para]);
213
214 rb_dlinkAddAlloc(aconf, &bandb_pending);
215 }
216
217 static int
218 bandb_check_kline(struct ConfItem *aconf)
219 {
220 struct rb_sockaddr_storage daddr;
221 struct ConfItem *kconf = NULL;
222 int aftype;
223 const char *p;
224
225 aftype = parse_netmask(aconf->host, &daddr, NULL);
226
227 if(aftype != HM_HOST)
228 {
229 #ifdef RB_IPV6
230 if(aftype == HM_IPV6)
231 aftype = AF_INET6;
232 else
233 #endif
234 aftype = AF_INET;
235
236 kconf = find_conf_by_address(aconf->host, NULL, NULL, (struct sockaddr *)&daddr,
237 CONF_KILL, aftype, aconf->user, NULL);
238 }
239 else
240 kconf = find_conf_by_address(aconf->host, NULL, NULL, NULL, CONF_KILL, 0, aconf->user, NULL);
241
242 if(kconf && ((kconf->flags & CONF_FLAGS_TEMPORARY) == 0))
243 return 0;
244
245 for(p = aconf->user; *p; p++)
246 {
247 if(!IsUserChar(*p) && !IsKWildChar(*p))
248 return 0;
249 }
250
251 for(p = aconf->host; *p; p++)
252 {
253 if(!IsHostChar(*p) && !IsKWildChar(*p))
254 return 0;
255 }
256
257 return 1;
258 }
259
260 static int
261 bandb_check_dline(struct ConfItem *aconf)
262 {
263 struct rb_sockaddr_storage daddr;
264 int bits;
265
266 if(!parse_netmask(aconf->host, &daddr, &bits))
267 return 0;
268
269 return 1;
270 }
271
272 static int
273 bandb_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
285 static int
286 bandb_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
302 static int
303 bandb_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
314 static void
315 bandb_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
326 static void
327 bandb_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
388 static void
389 bandb_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]);
393
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
399 static void
400 bandb_parse(rb_helper *helper)
401 {
402 static char buf[READBUF_SIZE];
403 char *parv[MAXPARA];
404 int len, parc;
405
406 while((len = rb_helper_read(helper, buf, sizeof(buf))))
407 {
408 parc = rb_string_to_array(buf, parv, sizeof(parv));
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 break;
428 case 'F':
429 bandb_handle_finish();
430 break;
431 }
432 }
433 }
434
435 void
436 bandb_rehash_bans(void)
437 {
438 if(bandb_helper != NULL)
439 rb_helper_write(bandb_helper, "L");
440 }
441
442 static void
443 bandb_restart_cb(rb_helper *helper)
444 {
445 ilog(L_MAIN, "bandb - bandb_restart_cb called, bandb helper died?");
446 sendto_realops_snomask(SNO_GENERAL, L_ALL,
447 "bandb - bandb_restart_cb called, bandb helper died?");
448 if(helper != NULL)
449 {
450 rb_helper_close(helper);
451 bandb_helper = NULL;
452 }
453 start_bandb();
454 return;
455 }