]> jfr.im git - solanum.git/blob - ircd/bandbi.c
Add a comment explaining match_arrange_stars
[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 if(aftype == HM_IPV6)
230 aftype = AF_INET6;
231 else
232 aftype = AF_INET;
233
234 kconf = find_conf_by_address(aconf->host, NULL, NULL, (struct sockaddr *)&daddr,
235 CONF_KILL, aftype, aconf->user, NULL);
236 }
237 else
238 kconf = find_conf_by_address(aconf->host, NULL, NULL, NULL, CONF_KILL, 0, aconf->user, NULL);
239
240 if(kconf && ((kconf->flags & CONF_FLAGS_TEMPORARY) == 0))
241 return 0;
242
243 for(p = aconf->user; *p; p++)
244 {
245 if(!IsUserChar(*p) && !IsKWildChar(*p))
246 return 0;
247 }
248
249 for(p = aconf->host; *p; p++)
250 {
251 if(!IsHostChar(*p) && !IsKWildChar(*p))
252 return 0;
253 }
254
255 return 1;
256 }
257
258 static int
259 bandb_check_dline(struct ConfItem *aconf)
260 {
261 struct rb_sockaddr_storage daddr;
262 int bits;
263
264 if(!parse_netmask(aconf->host, &daddr, &bits))
265 return 0;
266
267 return 1;
268 }
269
270 static int
271 bandb_check_xline(struct ConfItem *aconf)
272 {
273 struct ConfItem *xconf;
274 /* XXX perhaps convert spaces to \s? -- jilles */
275
276 xconf = find_xline_mask(aconf->host);
277 if(xconf != NULL && !(xconf->flags & CONF_FLAGS_TEMPORARY))
278 return 0;
279
280 return 1;
281 }
282
283 static int
284 bandb_check_resv_channel(struct ConfItem *aconf)
285 {
286 const char *p;
287
288 if(hash_find_resv(aconf->host) || strlen(aconf->host) > CHANNELLEN)
289 return 0;
290
291 for(p = aconf->host; *p; p++)
292 {
293 if(!IsChanChar(*p))
294 return 0;
295 }
296
297 return 1;
298 }
299
300 static int
301 bandb_check_resv_nick(struct ConfItem *aconf)
302 {
303 if(!clean_resv_nick(aconf->host))
304 return 0;
305
306 if(find_nick_resv(aconf->host))
307 return 0;
308
309 return 1;
310 }
311
312 static void
313 bandb_handle_clear(void)
314 {
315 rb_dlink_node *ptr, *next_ptr;
316
317 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, bandb_pending.head)
318 {
319 free_conf(ptr->data);
320 rb_dlinkDestroy(ptr, &bandb_pending);
321 }
322 }
323
324 static void
325 bandb_handle_finish(void)
326 {
327 struct ConfItem *aconf;
328 rb_dlink_node *ptr, *next_ptr;
329
330 clear_out_address_conf(AC_BANDB);
331 clear_s_newconf_bans();
332
333 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, bandb_pending.head)
334 {
335 aconf = ptr->data;
336
337 rb_dlinkDestroy(ptr, &bandb_pending);
338
339 switch (aconf->status)
340 {
341 case CONF_KILL:
342 if(bandb_check_kline(aconf))
343 add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf);
344 else
345 free_conf(aconf);
346
347 break;
348
349 case CONF_DLINE:
350 if(bandb_check_dline(aconf))
351 add_conf_by_address(aconf->host, CONF_DLINE, aconf->user, NULL, aconf);
352 else
353 free_conf(aconf);
354
355 break;
356
357 case CONF_XLINE:
358 if(bandb_check_xline(aconf))
359 rb_dlinkAddAlloc(aconf, &xline_conf_list);
360 else
361 free_conf(aconf);
362
363 break;
364
365 case CONF_RESV_CHANNEL:
366 if(bandb_check_resv_channel(aconf))
367 add_to_resv_hash(aconf->host, aconf);
368 else
369 free_conf(aconf);
370
371 break;
372
373 case CONF_RESV_NICK:
374 if(bandb_check_resv_nick(aconf))
375 rb_dlinkAddAlloc(aconf, &resv_conf_list);
376 else
377 free_conf(aconf);
378
379 break;
380 }
381 }
382
383 check_banned_lines();
384 }
385
386 static void
387 bandb_handle_failure(rb_helper *helper, char **parv, int parc)
388 {
389 if(server_state_foreground)
390 fprintf(stderr, "bandb - bandb failure: %s\n", parv[1]);
391
392 ilog(L_MAIN, "bandb - bandb failure: %s", parv[1]);
393 sendto_realops_snomask(SNO_GENERAL, L_ALL, "bandb - bandb failure: %s", parv[1]);
394 exit(1);
395 }
396
397 static void
398 bandb_parse(rb_helper *helper)
399 {
400 static char buf[READBUF_SIZE];
401 char *parv[MAXPARA];
402 int len, parc;
403
404 while((len = rb_helper_read(helper, buf, sizeof(buf))))
405 {
406 parc = rb_string_to_array(buf, parv, sizeof(parv));
407
408 if(parc < 1)
409 continue;
410
411 switch (parv[0][0])
412 {
413 case '!':
414 bandb_handle_failure(helper, parv, parc);
415 break;
416 case 'K':
417 case 'D':
418 case 'X':
419 case 'R':
420 bandb_handle_ban(parv, parc);
421 break;
422
423 case 'C':
424 bandb_handle_clear();
425 break;
426 case 'F':
427 bandb_handle_finish();
428 break;
429 }
430 }
431 }
432
433 void
434 bandb_rehash_bans(void)
435 {
436 if(bandb_helper != NULL)
437 rb_helper_write(bandb_helper, "L");
438 }
439
440 static void
441 bandb_restart_cb(rb_helper *helper)
442 {
443 ilog(L_MAIN, "bandb - bandb_restart_cb called, bandb helper died?");
444 sendto_realops_snomask(SNO_GENERAL, L_ALL,
445 "bandb - bandb_restart_cb called, bandb helper died?");
446 if(helper != NULL)
447 {
448 rb_helper_close(helper);
449 bandb_helper = NULL;
450 }
451 start_bandb();
452 return;
453 }