]> jfr.im git - irc/rqf/shadowircd.git/blob - src/bandbi.c
Add is_halfop() and is_owner() and start using them in the new functions.
[irc/rqf/shadowircd.git] / src / 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
50 static char bandb_add_letter[LAST_BANDB_TYPE] = {
51 'K', 'D', 'X', 'R'
52 };
53
54 rb_dlink_list bandb_pending;
55
56 static rb_helper *bandb_helper;
57 static int start_bandb(void);
58
59 static void bandb_parse(rb_helper *);
60 static void bandb_restart_cb(rb_helper *);
61 static char *bandb_path;
62
63 void
64 init_bandb(void)
65 {
66 if(start_bandb())
67 {
68 ilog(L_MAIN, "Unable to start bandb helper: %s", strerror(errno));
69 exit(0);
70 }
71 }
72
73
74 static int
75 start_bandb(void)
76 {
77 char fullpath[PATH_MAX + 1];
78 #ifdef _WIN32
79 const char *suffix = ".exe";
80 #else
81 const char *suffix = "";
82 #endif
83
84 rb_setenv("BANDB_DPATH", ConfigFileEntry.dpath, 1);
85 if(bandb_path == NULL)
86 {
87 rb_snprintf(fullpath, sizeof(fullpath), "%s/bandb%s", BINPATH, suffix);
88
89 if(access(fullpath, X_OK) == -1)
90 {
91 rb_snprintf(fullpath, sizeof(fullpath), "%s/bin/bandb%s",
92 ConfigFileEntry.dpath, suffix);
93
94 if(access(fullpath, X_OK) == -1)
95 {
96 ilog(L_MAIN,
97 "Unable to execute bandb in %s or %s/bin",
98 BINPATH, ConfigFileEntry.dpath);
99 return 0;
100 }
101 }
102 bandb_path = rb_strdup(fullpath);
103 }
104
105
106 bandb_helper = rb_helper_start("bandb", bandb_path, bandb_parse, bandb_restart_cb);
107
108 if(bandb_helper == NULL)
109 {
110 ilog(L_MAIN, "Unable to start bandb: %s", strerror(errno));
111 sendto_realops_snomask(SNO_GENERAL, L_ALL, "Unable to start bandb: %s",
112 strerror(errno));
113 return 1;
114 }
115
116 rb_helper_run(bandb_helper);
117 return 0;
118 }
119
120 void
121 bandb_add(bandb_type type, struct Client *source_p, const char *mask1,
122 const char *mask2, const char *reason, const char *oper_reason, int perm)
123 {
124 static char buf[BUFSIZE];
125
126 rb_snprintf(buf, sizeof(buf), "%c %s ", bandb_add_letter[type], mask1);
127
128 if(!EmptyString(mask2))
129 rb_snprintf_append(buf, sizeof(buf), "%s ", mask2);
130
131 rb_snprintf_append(buf, sizeof(buf), "%s %ld %d :%s",
132 get_oper_name(source_p), (long int)rb_current_time(), perm, reason);
133
134 if(!EmptyString(oper_reason))
135 rb_snprintf_append(buf, sizeof(buf), "|%s", oper_reason);
136
137 rb_helper_write(bandb_helper, "%s", buf);
138 }
139
140 static char bandb_del_letter[LAST_BANDB_TYPE] = {
141 'k', 'd', 'x', 'r'
142 };
143
144 void
145 bandb_del(bandb_type type, const char *mask1, const char *mask2)
146 {
147 static char buf[BUFSIZE];
148
149 buf[0] = '\0';
150
151 rb_snprintf_append(buf, sizeof(buf), "%c %s", bandb_del_letter[type], mask1);
152
153 if(!EmptyString(mask2))
154 rb_snprintf_append(buf, sizeof(buf), " %s", mask2);
155
156 rb_helper_write(bandb_helper, "%s", buf);
157 }
158
159 static void
160 bandb_handle_ban(char *parv[], int parc)
161 {
162 struct ConfItem *aconf;
163 char *p;
164 int para = 1;
165
166 aconf = make_conf();
167 aconf->port = 0;
168
169 if(parv[0][0] == 'K')
170 aconf->user = rb_strdup(parv[para++]);
171
172 aconf->host = rb_strdup(parv[para++]);
173 aconf->passwd = rb_strdup(parv[para++]);
174
175 switch (parv[0][0])
176 {
177 case 'K':
178 aconf->status = CONF_KILL;
179 break;
180
181 case 'D':
182 aconf->status = CONF_DLINE;
183 break;
184
185 case 'X':
186 aconf->status = CONF_XLINE;
187 break;
188
189 case 'R':
190 if(IsChannelName(aconf->host))
191 aconf->status = CONF_RESV_CHANNEL;
192 else
193 aconf->status = CONF_RESV_NICK;
194
195 break;
196 }
197
198 if((p = strchr(parv[para], '|')))
199 {
200 *p++ = '\0';
201 aconf->spasswd = rb_strdup(p);
202 }
203
204 aconf->passwd = rb_strdup(parv[para]);
205
206 rb_dlinkAddAlloc(aconf, &bandb_pending);
207 }
208
209 static int
210 bandb_check_kline(struct ConfItem *aconf)
211 {
212 struct rb_sockaddr_storage daddr;
213 struct ConfItem *kconf = NULL;
214 int aftype;
215 const char *p;
216
217 aftype = parse_netmask(aconf->host, (struct sockaddr *)&daddr, NULL);
218
219 if(aftype != HM_HOST)
220 {
221 #ifdef RB_IPV6
222 if(aftype == HM_IPV6)
223 aftype = AF_INET6;
224 else
225 #endif
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 /* struct ConfItem *dconf; */
257 int bits;
258
259 if(!parse_netmask(aconf->host, (struct sockaddr *)&daddr, &bits))
260 return 0;
261
262 return 1;
263 }
264
265 static int
266 bandb_check_xline(struct ConfItem *aconf)
267 {
268 struct ConfItem *xconf;
269 /* XXX perhaps convert spaces to \s? -- jilles */
270
271 xconf = find_xline_mask(aconf->host);
272 if(xconf != NULL && !(xconf->flags & CONF_FLAGS_TEMPORARY))
273 return 0;
274
275 return 1;
276 }
277
278 static int
279 bandb_check_resv_channel(struct ConfItem *aconf)
280 {
281 const char *p;
282
283 if(hash_find_resv(aconf->host) || strlen(aconf->host) > CHANNELLEN)
284 return 0;
285
286 for(p = aconf->host; *p; p++)
287 {
288 if(!IsChanChar(*p))
289 return 0;
290 }
291
292 return 1;
293 }
294
295 static int
296 bandb_check_resv_nick(struct ConfItem *aconf)
297 {
298 if(!clean_resv_nick(aconf->host))
299 return 0;
300
301 if(find_nick_resv(aconf->host))
302 return 0;
303
304 return 1;
305 }
306
307 static void
308 bandb_handle_clear(void)
309 {
310 rb_dlink_node *ptr, *next_ptr;
311
312 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, bandb_pending.head)
313 {
314 free_conf(ptr->data);
315 rb_dlinkDestroy(ptr, &bandb_pending);
316 }
317 }
318
319 static void
320 bandb_handle_finish(void)
321 {
322 struct ConfItem *aconf;
323 rb_dlink_node *ptr, *next_ptr;
324
325 clear_out_address_conf_bans();
326 clear_s_newconf_bans();
327
328 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, bandb_pending.head)
329 {
330 aconf = ptr->data;
331
332 rb_dlinkDestroy(ptr, &bandb_pending);
333
334 switch (aconf->status)
335 {
336 case CONF_KILL:
337 if(bandb_check_kline(aconf))
338 add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf);
339 else
340 free_conf(aconf);
341
342 break;
343
344 case CONF_DLINE:
345 if(bandb_check_dline(aconf))
346 add_conf_by_address(aconf->host, CONF_DLINE, aconf->user, NULL, aconf);
347 else
348 free_conf(aconf);
349
350 break;
351
352 case CONF_XLINE:
353 if(bandb_check_xline(aconf))
354 rb_dlinkAddAlloc(aconf, &xline_conf_list);
355 else
356 free_conf(aconf);
357
358 break;
359
360 case CONF_RESV_CHANNEL:
361 if(bandb_check_resv_channel(aconf))
362 add_to_resv_hash(aconf->host, aconf);
363 else
364 free_conf(aconf);
365
366 break;
367
368 case CONF_RESV_NICK:
369 if(bandb_check_resv_nick(aconf))
370 rb_dlinkAddAlloc(aconf, &resv_conf_list);
371 else
372 free_conf(aconf);
373
374 break;
375 }
376 }
377
378 check_banned_lines();
379 }
380
381 static void
382 bandb_handle_failure(rb_helper *helper, char **parv, int parc)
383 {
384 if(server_state_foreground)
385 fprintf(stderr, "bandb - bandb failure: %s\n", parv[1]);
386
387 ilog(L_MAIN, "bandb - bandb failure: %s", parv[1]);
388 sendto_realops_snomask(SNO_GENERAL, L_ALL, "bandb - bandb failure: %s", parv[1]);
389 exit(1);
390 }
391
392 static void
393 bandb_parse(rb_helper *helper)
394 {
395 static char buf[READBUF_SIZE];
396 char *parv[MAXPARA + 1];
397 int len, parc;
398
399 while((len = rb_helper_read(helper, buf, sizeof(buf))))
400 {
401 parc = rb_string_to_array(buf, parv, MAXPARA);
402
403 if(parc < 1)
404 continue;
405
406 switch (parv[0][0])
407 {
408 case '!':
409 bandb_handle_failure(helper, parv, parc);
410 break;
411 case 'K':
412 case 'D':
413 case 'X':
414 case 'R':
415 bandb_handle_ban(parv, parc);
416 break;
417
418 case 'C':
419 bandb_handle_clear();
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_ALL,
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 }