]> jfr.im git - solanum.git/blob - ircd/bandbi.c
Unify helper snotes and make netwide.
[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
81 rb_setenv("BANDB_DBPATH", ircd_paths[IRCD_PATH_BANDB], 1);
82 if(bandb_path == NULL)
83 {
84 snprintf(fullpath, sizeof(fullpath), "%s/bandb", ircd_paths[IRCD_PATH_LIBEXEC]);
85
86 if(access(fullpath, X_OK) == -1)
87 {
88 snprintf(fullpath, sizeof(fullpath), "%s/bin/bandb", ConfigFileEntry.dpath);
89
90 if(access(fullpath, X_OK) == -1)
91 {
92 ilog(L_MAIN,
93 "Unable to execute bandb in %s or %s/bin",
94 ircd_paths[IRCD_PATH_LIBEXEC], ConfigFileEntry.dpath);
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));
107 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Unable to start bandb helper: %s",
108 strerror(errno));
109 return 1;
110 }
111
112 ilog(L_MAIN, "bandb helper started");
113 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "bandb helper started");
114 rb_helper_run(bandb_helper);
115 return 0;
116 }
117
118 void
119 bandb_add(bandb_type type, struct Client *source_p, const char *mask1,
120 const char *mask2, const char *reason, const char *oper_reason, int perm)
121 {
122 if(bandb_helper == NULL)
123 return;
124
125 static char buf[BUFSIZE];
126
127 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 if(bandb_helper == NULL)
149 return;
150
151 static char buf[BUFSIZE];
152
153 buf[0] = '\0';
154
155 rb_snprintf_append(buf, sizeof(buf), "%c %s", bandb_del_letter[type], mask1);
156
157 if(!EmptyString(mask2))
158 rb_snprintf_append(buf, sizeof(buf), " %s", mask2);
159
160 rb_helper_write(bandb_helper, "%s", buf);
161 }
162
163 static void
164 bandb_handle_ban(char *parv[], int parc)
165 {
166 struct ConfItem *aconf;
167 char *p;
168 int para = 1;
169
170 aconf = make_conf();
171 aconf->port = 0;
172
173 if(parv[0][0] == 'K')
174 aconf->user = rb_strdup(parv[para++]);
175
176 aconf->host = rb_strdup(parv[para++]);
177 aconf->info.oper = operhash_add(parv[para++]);
178
179 switch (parv[0][0])
180 {
181 case 'K':
182 aconf->status = CONF_KILL;
183 break;
184
185 case 'D':
186 aconf->status = CONF_DLINE;
187 break;
188
189 case 'X':
190 aconf->status = CONF_XLINE;
191 break;
192
193 case 'R':
194 if(IsChannelName(aconf->host))
195 aconf->status = CONF_RESV_CHANNEL;
196 else
197 aconf->status = CONF_RESV_NICK;
198
199 break;
200 }
201
202 if((p = strchr(parv[para], '|')))
203 {
204 *p++ = '\0';
205 aconf->spasswd = rb_strdup(p);
206 }
207
208 aconf->passwd = rb_strdup(parv[para]);
209
210 rb_dlinkAddAlloc(aconf, &bandb_pending);
211 }
212
213 static int
214 bandb_check_kline(struct ConfItem *aconf)
215 {
216 struct rb_sockaddr_storage daddr;
217 struct ConfItem *kconf = NULL;
218 int aftype;
219 const char *p;
220
221 aftype = parse_netmask(aconf->host, &daddr, NULL);
222
223 if(aftype != HM_HOST)
224 {
225 if(aftype == HM_IPV6)
226 aftype = AF_INET6;
227 else
228 aftype = AF_INET;
229
230 kconf = find_conf_by_address(aconf->host, NULL, NULL, (struct sockaddr *)&daddr,
231 CONF_KILL, aftype, aconf->user, NULL);
232 }
233 else
234 kconf = find_conf_by_address(aconf->host, NULL, NULL, NULL, CONF_KILL, 0, aconf->user, NULL);
235
236 if(kconf && ((kconf->flags & CONF_FLAGS_TEMPORARY) == 0))
237 return 0;
238
239 for(p = aconf->user; *p; p++)
240 {
241 if(!IsUserChar(*p) && !IsKWildChar(*p))
242 return 0;
243 }
244
245 for(p = aconf->host; *p; p++)
246 {
247 if(!IsHostChar(*p) && !IsKWildChar(*p))
248 return 0;
249 }
250
251 return 1;
252 }
253
254 static int
255 bandb_check_dline(struct ConfItem *aconf)
256 {
257 struct rb_sockaddr_storage daddr;
258 int bits;
259
260 if(!parse_netmask(aconf->host, &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(AC_BANDB);
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_NETWIDE, "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];
398 int len, parc;
399
400 while((len = rb_helper_read(helper, buf, sizeof(buf))))
401 {
402 parc = rb_string_to_array(buf, parv, sizeof(parv));
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 break;
422 case 'F':
423 bandb_handle_finish();
424 break;
425 }
426 }
427 }
428
429 void
430 bandb_rehash_bans(void)
431 {
432 if(bandb_helper != NULL)
433 rb_helper_write(bandb_helper, "L");
434 }
435
436 static void
437 bandb_restart_cb(rb_helper *helper)
438 {
439 ilog(L_MAIN, "bandb helper died - attempting to restart");
440 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
441 "bandb helper died - attempting to restart");
442 if(helper != NULL)
443 {
444 rb_helper_close(helper);
445 bandb_helper = NULL;
446 }
447 start_bandb();
448 return;
449 }