2 * charybdis: A slightly useful ircd.
3 * blacklist.c: Manages DNS blacklist entries and lookups
5 * Copyright (C) 2006-2011 charybdis development team
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
11 * 1. Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * 3. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
34 /* Originally written for charybdis circa 2006 (by nenolod?).
35 * Tweaked for authd. Some functions and structs renamed. Public/private
36 * interfaces have been shifted around. Some code has been cleaned up too.
37 * -- Elizafox 24 March 2016
47 #define SELF_PID (blacklist_provider.id)
55 /* Blacklist accepted IP types */
59 /* A configured DNSBL */
62 char host
[IRCD_RES_HOSTLEN
+ 1];
63 char reason
[BUFSIZE
]; /* Reason template (ircd fills in the blanks) */
64 uint8_t iptype
; /* IP types supported */
65 rb_dlink_list filters
; /* Filters for queries */
67 bool delete; /* If true delete when no clients */
68 int refcount
; /* When 0 and delete is set, remove this blacklist */
71 time_t lastwarning
; /* Last warning about garbage replies sent */
74 /* A lookup in progress for a particular DNSBL for a particular client */
75 struct blacklist_lookup
77 struct blacklist
*bl
; /* Blacklist we're checking */
78 struct auth_client
*auth
; /* Client */
79 struct dns_query
*query
; /* DNS query pointer */
84 /* A blacklist filter */
85 struct blacklist_filter
87 filter_t type
; /* Type of filter */
88 char filter
[HOSTIPLEN
]; /* The filter itself */
93 /* Blacklist user data attached to auth_client instance */
96 rb_dlink_list queries
; /* Blacklist queries in flight */
99 /* public interfaces */
100 static void blacklists_destroy(void);
102 static bool blacklists_start(struct auth_client
*);
103 static void blacklists_cancel(struct auth_client
*);
105 /* private interfaces */
106 static void unref_blacklist(struct blacklist
*);
107 static struct blacklist
*new_blacklist(const char *, const char *, uint8_t, rb_dlink_list
*);
108 static struct blacklist
*find_blacklist(const char *);
109 static bool blacklist_check_reply(struct blacklist_lookup
*, const char *);
110 static void blacklist_dns_callback(const char *, bool, query_type
, void *);
111 static void initiate_blacklist_dnsquery(struct blacklist
*, struct auth_client
*);
114 static rb_dlink_list blacklist_list
= { NULL
, NULL
, 0 };
115 static int blacklist_timeout
= BLACKLIST_TIMEOUT_DEFAULT
;
117 /* private interfaces */
120 unref_blacklist(struct blacklist
*bl
)
122 rb_dlink_node
*ptr
, *nptr
;
125 if (bl
->delete && bl
->refcount
<= 0)
127 RB_DLINK_FOREACH_SAFE(ptr
, nptr
, bl
->filters
.head
)
129 rb_dlinkDelete(ptr
, &bl
->filters
);
133 rb_dlinkFindDestroy(bl
, &blacklist_list
);
138 static struct blacklist
*
139 new_blacklist(const char *name
, const char *reason
, uint8_t iptype
, rb_dlink_list
*filters
)
141 struct blacklist
*bl
;
143 if (name
== NULL
|| reason
== NULL
|| iptype
== 0)
146 if((bl
= find_blacklist(name
)) == NULL
)
148 bl
= rb_malloc(sizeof(struct blacklist
));
149 rb_dlinkAddAlloc(bl
, &blacklist_list
);
154 rb_strlcpy(bl
->host
, name
, IRCD_RES_HOSTLEN
+ 1);
155 rb_strlcpy(bl
->reason
, reason
, BUFSIZE
);
158 rb_dlinkMoveList(filters
, &bl
->filters
);
165 static struct blacklist
*
166 find_blacklist(const char *name
)
170 RB_DLINK_FOREACH(ptr
, blacklist_list
.head
)
172 struct blacklist
*bl
= (struct blacklist
*)ptr
->data
;
174 if (!strcasecmp(bl
->host
, name
))
182 blacklist_check_reply(struct blacklist_lookup
*bllookup
, const char *ipaddr
)
184 struct blacklist
*bl
= bllookup
->bl
;
185 const char *lastoctet
;
188 /* No filters and entry found - thus positive match */
189 if (!rb_dlink_list_length(&bl
->filters
))
192 /* Below will prolly have to change if IPv6 address replies are sent back */
193 if ((lastoctet
= strrchr(ipaddr
, '.')) == NULL
|| *(++lastoctet
) == '\0')
196 RB_DLINK_FOREACH(ptr
, bl
->filters
.head
)
198 struct blacklist_filter
*filter
= ptr
->data
;
201 if (filter
->type
== FILTER_ALL
)
203 else if (filter
->type
== FILTER_LAST
)
207 warn_opers(L_CRIT
, "Blacklist: Unknown blacklist filter type (host %s): %d",
208 bl
->host
, filter
->type
);
209 exit(EX_PROVIDER_ERROR
);
212 if (strcmp(cmpstr
, filter
->filter
) == 0)
219 if (bl
->lastwarning
+ 3600 < rb_current_time())
221 warn_opers(L_WARN
, "Garbage/undecipherable reply received from blacklist %s (reply %s)",
223 bl
->lastwarning
= rb_current_time();
230 blacklist_dns_callback(const char *result
, bool status
, query_type type
, void *data
)
232 struct blacklist_lookup
*bllookup
= (struct blacklist_lookup
*)data
;
233 struct blacklist_user
*bluser
;
234 struct blacklist
*bl
;
235 struct auth_client
*auth
;
237 lrb_assert(bllookup
!= NULL
);
238 lrb_assert(bllookup
->auth
!= NULL
);
241 auth
= bllookup
->auth
;
243 if((bluser
= get_provider_data(auth
, SELF_PID
)) == NULL
)
246 if (result
!= NULL
&& status
&& blacklist_check_reply(bllookup
, result
))
248 /* Match found, so proceed no further */
250 blacklists_cancel(auth
);
251 reject_client(auth
, SELF_PID
, bl
->host
, bl
->reason
);
256 cancel_query(bllookup
->query
); /* Ignore future responses */
257 rb_dlinkDelete(&bllookup
->node
, &bluser
->queries
);
260 if(!rb_dlink_list_length(&bluser
->queries
))
263 notice_client(auth
->cid
, "*** IP not found in DNS blacklist%s",
264 rb_dlink_list_length(&blacklist_list
) > 1 ? "s" : "");
266 set_provider_data(auth
, SELF_PID
, NULL
);
267 set_provider_timeout_absolute(auth
, SELF_PID
, 0);
268 provider_done(auth
, SELF_PID
);
270 auth_client_unref(auth
);
275 initiate_blacklist_dnsquery(struct blacklist
*bl
, struct auth_client
*auth
)
277 struct blacklist_lookup
*bllookup
= rb_malloc(sizeof(struct blacklist_lookup
));
278 struct blacklist_user
*bluser
= get_provider_data(auth
, SELF_PID
);
279 char buf
[IRCD_RES_HOSTLEN
+ 1];
283 bllookup
->auth
= auth
;
285 aftype
= GET_SS_FAMILY(&auth
->c_addr
);
286 if((aftype
== AF_INET
&& (bl
->iptype
& IPTYPE_IPV4
) == 0) ||
287 (aftype
== AF_INET6
&& (bl
->iptype
& IPTYPE_IPV6
) == 0))
288 /* Incorrect blacklist type for this IP... */
294 build_rdns(buf
, sizeof(buf
), &auth
->c_addr
, bl
->host
);
296 bllookup
->query
= lookup_ip(buf
, AF_INET
, blacklist_dns_callback
, bllookup
);
298 rb_dlinkAdd(bllookup
, &bllookup
->node
, &bluser
->queries
);
303 lookup_all_blacklists(struct auth_client
*auth
)
305 struct blacklist_user
*bluser
= get_provider_data(auth
, SELF_PID
);
308 notice_client(auth
->cid
, "*** Checking your IP against DNS blacklist%s",
309 rb_dlink_list_length(&blacklist_list
) > 1 ? "s" : "");
311 RB_DLINK_FOREACH(ptr
, blacklist_list
.head
)
313 struct blacklist
*bl
= (struct blacklist
*)ptr
->data
;
316 initiate_blacklist_dnsquery(bl
, auth
);
319 set_provider_timeout_relative(auth
, SELF_PID
, blacklist_timeout
);
323 delete_blacklist(struct blacklist
*bl
)
325 if (bl
->refcount
> 0)
329 rb_dlinkFindDestroy(bl
, &blacklist_list
);
335 delete_all_blacklists(void)
337 rb_dlink_node
*ptr
, *nptr
;
339 RB_DLINK_FOREACH_SAFE(ptr
, nptr
, blacklist_list
.head
)
341 delete_blacklist(ptr
->data
);
345 /* public interfaces */
347 blacklists_start(struct auth_client
*auth
)
349 uint32_t rdns_pid
, ident_pid
;
351 lrb_assert(get_provider_data(auth
, SELF_PID
) == NULL
);
353 if(!rb_dlink_list_length(&blacklist_list
))
354 /* Nothing to do... */
357 auth_client_ref(auth
);
359 set_provider_data(auth
, SELF_PID
, rb_malloc(sizeof(struct blacklist_user
)));
361 if((!get_provider_id("rdns", &rdns_pid
) || is_provider_done(auth
, rdns_pid
)) &&
362 (!get_provider_id("ident", &ident_pid
) || is_provider_done(auth
, ident_pid
)))
364 /* Start the lookup if ident and rdns are finished, or not loaded. */
365 lookup_all_blacklists(auth
);
368 set_provider_running(auth
, SELF_PID
);
372 /* This is called every time a provider is completed as long as we are marked not done */
374 blacklists_initiate(struct auth_client
*auth
, uint32_t provider
)
376 struct blacklist_user
*bluser
= get_provider_data(auth
, SELF_PID
);
377 uint32_t rdns_pid
, ident_pid
;
379 lrb_assert(provider
!= SELF_PID
);
380 lrb_assert(!is_provider_done(auth
, SELF_PID
));
381 lrb_assert(rb_dlink_list_length(&blacklist_list
) > 0);
383 if(bluser
== NULL
|| rb_dlink_list_length(&bluser
->queries
))
386 else if((!get_provider_id("rdns", &rdns_pid
) || is_provider_done(auth
, rdns_pid
)) &&
387 (!get_provider_id("ident", &ident_pid
) || is_provider_done(auth
, ident_pid
)))
388 /* Don't start until ident and rdns are finished (or not loaded) */
391 lookup_all_blacklists(auth
);
395 blacklists_cancel(struct auth_client
*auth
)
397 rb_dlink_node
*ptr
, *nptr
;
398 struct blacklist_user
*bluser
= get_provider_data(auth
, SELF_PID
);
403 if(rb_dlink_list_length(&bluser
->queries
))
405 notice_client(auth
->cid
, "*** Aborting DNS blacklist queries");
407 RB_DLINK_FOREACH_SAFE(ptr
, nptr
, bluser
->queries
.head
)
409 struct blacklist_lookup
*bllookup
= ptr
->data
;
411 cancel_query(bllookup
->query
);
412 unref_blacklist(bllookup
->bl
);
414 rb_dlinkDelete(&bllookup
->node
, &bluser
->queries
);
420 set_provider_data(auth
, SELF_PID
, NULL
);
421 set_provider_timeout_absolute(auth
, SELF_PID
, 0);
422 provider_done(auth
, SELF_PID
);
424 auth_client_unref(auth
);
428 blacklists_destroy(void)
430 rb_dictionary_iter iter
;
431 struct auth_client
*auth
;
433 RB_DICTIONARY_FOREACH(auth
, &iter
, auth_clients
)
435 blacklists_cancel(auth
);
436 /* auth is now invalid as we have no reference */
439 delete_all_blacklists();
443 add_conf_blacklist(const char *key
, int parc
, const char **parv
)
445 rb_dlink_list filters
= { NULL
, NULL
, 0 };
446 char *tmp
, *elemlist
= rb_strdup(parv
[2]);
452 for(char *elem
= rb_strtok_r(elemlist
, ",", &tmp
); elem
; elem
= rb_strtok_r(NULL
, ",", &tmp
))
454 struct blacklist_filter
*filter
= rb_malloc(sizeof(struct blacklist_filter
));
456 filter_t type
= FILTER_LAST
;
458 /* Check blacklist filter type and for validity */
459 for(char *c
= elem
; *c
!= '\0'; c
++)
465 warn_opers(L_CRIT
, "Blacklist: addr_conf_blacklist got a bad filter (too many octets)");
466 exit(EX_PROVIDER_ERROR
);
471 else if(!isdigit(*c
))
473 warn_opers(L_CRIT
, "Blacklist: addr_conf_blacklist got a bad filter (invalid character in blacklist filter: %c)",
475 exit(EX_PROVIDER_ERROR
);
479 if(dot_c
> 0 && dot_c
< 3)
481 warn_opers(L_CRIT
, "Blacklist: addr_conf_blacklist got a bad filter (insufficient octets)");
482 exit(EX_PROVIDER_ERROR
);
486 rb_strlcpy(filter
->filter
, elem
, sizeof(filter
->filter
));
487 rb_dlinkAdd(filter
, &filter
->node
, &filters
);
493 iptype
= atoi(parv
[1]) & 0x3;
494 if(new_blacklist(parv
[0], parv
[3], iptype
, &filters
) == NULL
)
496 warn_opers(L_CRIT
, "Blacklist: addr_conf_blacklist got a malformed blacklist");
497 exit(EX_PROVIDER_ERROR
);
502 del_conf_blacklist(const char *key
, int parc
, const char **parv
)
504 struct blacklist
*bl
= find_blacklist(parv
[0]);
507 /* Not fatal for now... */
508 warn_opers(L_WARN
, "Blacklist: tried to remove nonexistent blacklist %s", parv
[0]);
512 delete_blacklist(bl
);
516 del_conf_blacklist_all(const char *key
, int parc
, const char **parv
)
518 delete_all_blacklists();
522 add_conf_blacklist_timeout(const char *key
, int parc
, const char **parv
)
524 int timeout
= atoi(parv
[0]);
528 warn_opers(L_CRIT
, "Blacklist: blacklist timeout < 0 (value: %d)", timeout
);
529 exit(EX_PROVIDER_ERROR
);
532 blacklist_timeout
= timeout
;
537 blacklist_stats(uint32_t rid
, char letter
)
541 RB_DLINK_FOREACH(ptr
, blacklist_list
.head
)
543 struct blacklist
*bl
= ptr
->data
;
548 stats_result(rid
, letter
, "%s %hhu %u", bl
->host
, bl
->iptype
, bl
->hits
);
551 stats_done(rid
, letter
);
555 struct auth_opts_handler blacklist_options
[] =
557 { "rbl", 4, add_conf_blacklist
},
558 { "rbl_del", 1, del_conf_blacklist
},
559 { "rbl_del_all", 0, del_conf_blacklist_all
},
560 { "rbl_timeout", 1, add_conf_blacklist_timeout
},
564 struct auth_provider blacklist_provider
=
568 .destroy
= blacklists_destroy
,
569 .start
= blacklists_start
,
570 .cancel
= blacklists_cancel
,
571 .timeout
= blacklists_cancel
,
572 .completed
= blacklists_initiate
,
573 .opt_handlers
= blacklist_options
,
574 /* .stats_handler = { 'B', blacklist_stats }, */