]> jfr.im git - solanum.git/blob - ircd/bandbi.c
Avoid show_iline_prefix showing leftovers (#266)
[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: %s",
108 strerror(errno));
109 return 1;
110 }
111
112 rb_helper_run(bandb_helper);
113 return 0;
114 }
115
116 void
117 bandb_add(bandb_type type, struct Client *source_p, const char *mask1,
118 const char *mask2, const char *reason, const char *oper_reason, int perm)
119 {
120 if(bandb_helper == NULL)
121 return;
122
123 static char buf[BUFSIZE];
124
125 snprintf(buf, sizeof(buf), "%c %s ", bandb_add_letter[type], mask1);
126
127 if(!EmptyString(mask2))
128 rb_snprintf_append(buf, sizeof(buf), "%s ", mask2);
129
130 rb_snprintf_append(buf, sizeof(buf), "%s %ld %d :%s",
131 get_oper_name(source_p), (long int)rb_current_time(), perm, reason);
132
133 if(!EmptyString(oper_reason))
134 rb_snprintf_append(buf, sizeof(buf), "|%s", oper_reason);
135
136 rb_helper_write(bandb_helper, "%s", buf);
137 }
138
139 static char bandb_del_letter[LAST_BANDB_TYPE] = {
140 'k', 'd', 'x', 'r'
141 };
142
143 void
144 bandb_del(bandb_type type, const char *mask1, const char *mask2)
145 {
146 if(bandb_helper == NULL)
147 return;
148
149 static char buf[BUFSIZE];
150
151 buf[0] = '\0';
152
153 rb_snprintf_append(buf, sizeof(buf), "%c %s", bandb_del_letter[type], mask1);
154
155 if(!EmptyString(mask2))
156 rb_snprintf_append(buf, sizeof(buf), " %s", mask2);
157
158 rb_helper_write(bandb_helper, "%s", buf);
159 }
160
161 static void
162 bandb_handle_ban(char *parv[], int parc)
163 {
164 struct ConfItem *aconf;
165 char *p;
166 int para = 1;
167
168 aconf = make_conf();
169 aconf->port = 0;
170
171 if(parv[0][0] == 'K')
172 aconf->user = rb_strdup(parv[para++]);
173
174 aconf->host = rb_strdup(parv[para++]);
175 aconf->info.oper = operhash_add(parv[para++]);
176
177 switch (parv[0][0])
178 {
179 case 'K':
180 aconf->status = CONF_KILL;
181 break;
182
183 case 'D':
184 aconf->status = CONF_DLINE;
185 break;
186
187 case 'X':
188 aconf->status = CONF_XLINE;
189 break;
190
191 case 'R':
192 if(IsChannelName(aconf->host))
193 aconf->status = CONF_RESV_CHANNEL;
194 else
195 aconf->status = CONF_RESV_NICK;
196
197 break;
198 }
199
200 if((p = strchr(parv[para], '|')))
201 {
202 *p++ = '\0';
203 aconf->spasswd = rb_strdup(p);
204 }
205
206 aconf->passwd = rb_strdup(parv[para]);
207
208 rb_dlinkAddAlloc(aconf, &bandb_pending);
209 }
210
211 static int
212 bandb_check_kline(struct ConfItem *aconf)
213 {
214 struct rb_sockaddr_storage daddr;
215 struct ConfItem *kconf = NULL;
216 int aftype;
217 const char *p;
218
219 aftype = parse_netmask(aconf->host, &daddr, NULL);
220
221 if(aftype != HM_HOST)
222 {
223 if(aftype == HM_IPV6)
224 aftype = AF_INET6;
225 else
226 aftype = AF_INET;
227
228 kconf = find_conf_by_address(aconf->host, NULL, NULL, (struct sockaddr *)&daddr,
229 CONF_KILL, aftype, aconf->user, NULL);
230 }
231 else
232 kconf = find_conf_by_address(aconf->host, NULL, NULL, NULL, CONF_KILL, 0, aconf->user, NULL);
233
234 if(kconf && ((kconf->flags & CONF_FLAGS_TEMPORARY) == 0))
235 return 0;
236
237 for(p = aconf->user; *p; p++)
238 {
239 if(!IsUserChar(*p) && !IsKWildChar(*p))
240 return 0;
241 }
242
243 for(p = aconf->host; *p; p++)
244 {
245 if(!IsHostChar(*p) && !IsKWildChar(*p))
246 return 0;
247 }
248
249 return 1;
250 }
251
252 static int
253 bandb_check_dline(struct ConfItem *aconf)
254 {
255 struct rb_sockaddr_storage daddr;
256 int bits;
257
258 if(!parse_netmask(aconf->host, &daddr, &bits))
259 return 0;
260
261 return 1;
262 }
263
264 static int
265 bandb_check_xline(struct ConfItem *aconf)
266 {
267 struct ConfItem *xconf;
268 /* XXX perhaps convert spaces to \s? -- jilles */
269
270 xconf = find_xline_mask(aconf->host);
271 if(xconf != NULL && !(xconf->flags & CONF_FLAGS_TEMPORARY))
272 return 0;
273
274 return 1;
275 }
276
277 static int
278 bandb_check_resv_channel(struct ConfItem *aconf)
279 {
280 const char *p;
281
282 if(hash_find_resv(aconf->host) || strlen(aconf->host) > CHANNELLEN)
283 return 0;
284
285 for(p = aconf->host; *p; p++)
286 {
287 if(!IsChanChar(*p))
288 return 0;
289 }
290
291 return 1;
292 }
293
294 static int
295 bandb_check_resv_nick(struct ConfItem *aconf)
296 {
297 if(!clean_resv_nick(aconf->host))
298 return 0;
299
300 if(find_nick_resv(aconf->host))
301 return 0;
302
303 return 1;
304 }
305
306 static void
307 bandb_handle_clear(void)
308 {
309 rb_dlink_node *ptr, *next_ptr;
310
311 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, bandb_pending.head)
312 {
313 free_conf(ptr->data);
314 rb_dlinkDestroy(ptr, &bandb_pending);
315 }
316 }
317
318 static void
319 bandb_handle_finish(void)
320 {
321 struct ConfItem *aconf;
322 rb_dlink_node *ptr, *next_ptr;
323
324 clear_out_address_conf(AC_BANDB);
325 clear_s_newconf_bans();
326
327 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, bandb_pending.head)
328 {
329 aconf = ptr->data;
330
331 rb_dlinkDestroy(ptr, &bandb_pending);
332
333 switch (aconf->status)
334 {
335 case CONF_KILL:
336 if(bandb_check_kline(aconf))
337 add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf);
338 else
339 free_conf(aconf);
340
341 break;
342
343 case CONF_DLINE:
344 if(bandb_check_dline(aconf))
345 add_conf_by_address(aconf->host, CONF_DLINE, aconf->user, NULL, aconf);
346 else
347 free_conf(aconf);
348
349 break;
350
351 case CONF_XLINE:
352 if(bandb_check_xline(aconf))
353 rb_dlinkAddAlloc(aconf, &xline_conf_list);
354 else
355 free_conf(aconf);
356
357 break;
358
359 case CONF_RESV_CHANNEL:
360 if(bandb_check_resv_channel(aconf))
361 add_to_resv_hash(aconf->host, aconf);
362 else
363 free_conf(aconf);
364
365 break;
366
367 case CONF_RESV_NICK:
368 if(bandb_check_resv_nick(aconf))
369 rb_dlinkAddAlloc(aconf, &resv_conf_list);
370 else
371 free_conf(aconf);
372
373 break;
374 }
375 }
376
377 check_banned_lines();
378 }
379
380 static void
381 bandb_handle_failure(rb_helper *helper, char **parv, int parc)
382 {
383 if(server_state_foreground)
384 fprintf(stderr, "bandb - bandb failure: %s\n", parv[1]);
385
386 ilog(L_MAIN, "bandb - bandb failure: %s", parv[1]);
387 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "bandb - bandb failure: %s", parv[1]);
388 exit(1);
389 }
390
391 static void
392 bandb_parse(rb_helper *helper)
393 {
394 static char buf[READBUF_SIZE];
395 char *parv[MAXPARA];
396 int len, parc;
397
398 while((len = rb_helper_read(helper, buf, sizeof(buf))))
399 {
400 parc = rb_string_to_array(buf, parv, sizeof(parv));
401
402 if(parc < 1)
403 continue;
404
405 switch (parv[0][0])
406 {
407 case '!':
408 bandb_handle_failure(helper, parv, parc);
409 break;
410 case 'K':
411 case 'D':
412 case 'X':
413 case 'R':
414 bandb_handle_ban(parv, parc);
415 break;
416
417 case 'C':
418 bandb_handle_clear();
419 break;
420 case 'F':
421 bandb_handle_finish();
422 break;
423 }
424 }
425 }
426
427 void
428 bandb_rehash_bans(void)
429 {
430 if(bandb_helper != NULL)
431 rb_helper_write(bandb_helper, "L");
432 }
433
434 static void
435 bandb_restart_cb(rb_helper *helper)
436 {
437 ilog(L_MAIN, "bandb - bandb_restart_cb called, bandb helper died?");
438 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
439 "bandb - bandb_restart_cb called, bandb helper died?");
440 if(helper != NULL)
441 {
442 rb_helper_close(helper);
443 bandb_helper = NULL;
444 }
445 start_bandb();
446 return;
447 }