? src/bopm.pid ? src/libopm Index: src/config-lexer.l =================================================================== RCS file: /data/cvs/bopm/src/config-lexer.l,v retrieving revision 1.6 diff -u -6 -r1.6 config-lexer.l --- src/config-lexer.l 19 Jun 2003 23:07:57 -0000 1.6 +++ src/config-lexer.l 26 Jun 2003 21:06:49 -0000 @@ -89,12 +89,13 @@ return STRING; } } } +ALERT { return ALERT; } AWAY { return AWAY; } BAN_UNKNOWN { return BAN_UNKNOWN; } BLACKLIST { return BLACKLIST; } CHANNEL { return CHANNEL; } CONNREGEX { return CONNREGEX; } DNS_FDLIMIT { return DNS_FDLIMIT; } @@ -132,12 +133,13 @@ TARGET_STRING { return TARGET_STRING;} TIMEOUT { return TIMEOUT; } TYPE { return TYPE; } USER { return USER; } USERNAME { return USERNAME; } VHOST { return VHOST; } +WHITELIST { return WHITELIST; } HTTP { yylval.number = OPM_TYPE_HTTP; return PROTOCOLTYPE; } Index: src/config-parser.y =================================================================== RCS file: /data/cvs/bopm/src/config-parser.y,v retrieving revision 1.7 diff -u -6 -r1.7 config-parser.y --- src/config-parser.y 22 Jun 2003 13:19:39 -0000 1.7 +++ src/config-parser.y 26 Jun 2003 21:06:49 -0000 @@ -30,12 +30,13 @@ int yydebug=0; void *tmp; /* Variable to temporarily hold nodes before insertion to list */ %} +%token ALERT %token AWAY %token BAN_UNKNOWN %token BLACKLIST %token CHANNEL %token CONNREGEX %token DNS_FDLIMIT @@ -74,12 +75,13 @@ %token TARGET_STRING %token TIMEOUT %token TYPE %token USERNAME %token USER %token VHOST +%token WHITELIST %union { int number; char *string; } @@ -526,12 +528,14 @@ item = MyMalloc(sizeof *item); item->name = DupString(""); item->kline = DupString(""); item->ban_unknown = 0; + item->whitelist = 0; + item->alert = 1; item->type = A_BITMASK; item->reply = list_create(); node = node_create(item); list_add(OpmItem->blacklists, node); @@ -542,14 +546,16 @@ blacklist_items: /* Empty */ | blacklist_items blacklist_item | blacklist_item; blacklist_item: blacklist_name | blacklist_type | + blacklist_whitelist | blacklist_kline | blacklist_ban_unknown | + blacklist_alert | blacklist_reply | error; blacklist_name: NAME '=' STRING ';' { struct BlacklistConf *item = tmp; @@ -570,12 +576,24 @@ if(strcmp("A record bitmask", $3) == 0) item->type = A_BITMASK; else if(strcmp("A record reply", $3) == 0) item->type = A_REPLY; else yyerror("Unknown blacklist type defined"); +}; + +blacklist_whitelist: WHITELIST '=' NUMBER ';' { + struct BlacklistConf *item = tmp; + + item->whitelist = $3; +}; + +blacklist_alert: ALERT '=' NUMBER ';' { + struct BlacklistConf *item = tmp; + + item->alert = $3; }; blacklist_ban_unknown: BAN_UNKNOWN '=' NUMBER ';' { struct BlacklistConf *item = tmp; item->ban_unknown = $3; Index: src/config.h =================================================================== RCS file: /data/cvs/bopm/src/config.h,v retrieving revision 1.9 diff -u -6 -r1.9 config.h --- src/config.h 21 Jun 2003 00:57:28 -0000 1.9 +++ src/config.h 26 Jun 2003 21:06:49 -0000 @@ -101,13 +101,15 @@ struct BlacklistConf { char *name; char *kline; enum BlacklistType type; + int whitelist; int ban_unknown; + int alert; list_t *reply; unsigned int stats_recv; }; struct BlacklistReplyConf { Index: src/dnsbl.c =================================================================== RCS file: /data/cvs/bopm/src/dnsbl.c,v retrieving revision 1.29 diff -u -6 -r1.29 dnsbl.c --- src/dnsbl.c 22 Jun 2003 18:03:41 -0000 1.29 +++ src/dnsbl.c 26 Jun 2003 21:06:49 -0000 @@ -96,17 +96,27 @@ if(res == -1 && fdns_errno != FDNS_ERR_FDLIMIT) { log_printf("DNSBL -> Error sending dns lookup for '%s': %s", lookup, firedns_strerror(fdns_errno)); free(ds); } - else + else { ss->scans++; /* Increase scan count - one for each blacklist */ + if (bl->whitelist) + ss->dnsbl_whitelist_count++; /* Increase whitelist count + * for each whitelist */ + } } } +/* This function gets called when: + * - a positive result was obtained from a blacklist + * - the last result from the whitelist has been received, + * and a previous blacklist result was positive + */ + static void dnsbl_positive(struct scan_struct *ss, struct BlacklistConf *bl, unsigned char type) { char text_type[128]; struct BlacklistReplyConf *item; node_t *p; @@ -142,43 +152,66 @@ } } if(text_type[0] == '\0' && bl->ban_unknown == 0) { if(OPT_DEBUG) - log_printf("DNSBL -> Unknown result from BL zone %s (%d)", bl->name, type); + log_printf("DNSBL -> Unknown result from %s zone %s (%d)", + (bl->whitelist ? "WL" : "BL"), bl->name, type); return; } + /* record stat */ + stats_dnsblrecv(bl); + + /* If this was a positive result from a whitelist, flag this user + * as whitelisted in the scan struct. This will prevent any future + * positive DNSBL blacklist result from klining. + */ + if(bl->whitelist) + ss->dnsbl_whitelisted = 1; /* Mark this user as whitelisted */ + else if(ss->dnsbl_whitelist_count > 0) /* Store data */ + { + ss->dnsbl_positive_bl = bl; + ss->dnsbl_positive_type = type; + return; /* Wait until whitelists have finished */ + } + if(ss->manual_target) { - irc_send("PRIVMSG %s :CHECK -> DNSBL -> %s appears in BL zone %s (%s)", - ss->manual_target->name, ss->ip, bl->name, text_type); + irc_send("PRIVMSG %s :CHECK -> DNSBL -> %s appears in %s zone %s (%s)", + ss->manual_target->name, ss->ip, (bl->whitelist ? "WL" : "BL"), + bl->name, text_type); } else if(!ss->positive) { - /* Only report it if no other scans have found positives yet. */ - scan_positive(ss, (bl->kline[0] ? bl->kline : IRCItem->kline), - text_type); - - irc_send_channels("DNSBL -> %s!%s@%s appears in BL zone %s (%s)", - ss->irc_nick, ss->irc_username, ss->irc_hostname, bl->name, - text_type); - log_printf("DNSBL -> %s!%s@%s appears in BL zone %s (%s)", - ss->irc_nick, ss->irc_username, ss->irc_hostname, bl->name, - text_type); + /* Only report it if no other scans have found positives yet, + * all whitelists are done, and the user has not been whitelisted. */ + if(ss->dnsbl_whitelist_count == 0 && !ss->dnsbl_whitelisted) + { + scan_positive(ss, (bl->kline[0] ? bl->kline : IRCItem->kline), text_type); + + if(bl->alert) + irc_send_channels("DNSBL -> %s!%s@%s appears in %s zone %s (%s)", + ss->irc_nick, ss->irc_username, ss->irc_hostname, + (bl->whitelist ? "WL" : "BL"), bl->name, text_type); + } + + log_printf("DNSBL -> %s!%s@%s appears in %s zone %s (%s)", + ss->irc_nick, ss->irc_username, ss->irc_hostname, + (bl->whitelist ? "WL" : "BL"), bl->name, text_type); } - - /* record stat */ - stats_dnsblrecv(bl); } void dnsbl_result(struct firedns_result *res) { struct dnsbl_scan *ds = res->info; + if(ds->bl->whitelist) + ds->ss->dnsbl_whitelist_count--; /* one less whitelist to wait for */ + if(OPT_DEBUG) log_printf("DNSBL -> Lookup result for %s!%s@%s (%s) %d.%d.%d.%d (error: %d)", ds->ss->irc_nick, ds->ss->irc_username, ds->ss->irc_hostname, res->lookup, @@ -187,15 +220,21 @@ (unsigned char)res->text[2], (unsigned char)res->text[3], fdns_errno); /* Everything is OK */ if(res->text[0] == '\0' && fdns_errno == FDNS_ERR_NXDOMAIN) { + /* If any previous positive blacklist result was blocked, waiting + * for whitelists, handle it now + */ + if(ds->bl->whitelist && ds->ss->dnsbl_whitelist_count == 0 && ds->ss->dnsbl_positive_bl != NULL) + dnsbl_positive(ds->ss, ds->ss->dnsbl_positive_bl, ds->ss->dnsbl_positive_type); + if(ds->ss->manual_target != NULL) - irc_send("PRIVMSG %s :CHECK -> DNSBL -> %s does not appear in BL zone %s", - ds->ss->manual_target->name, ds->ss->ip, + irc_send("PRIVMSG %s :CHECK -> DNSBL -> %s does not appear in %s zone %s", + ds->ss->manual_target->name, ds->ss->ip, (ds->bl->whitelist ? "WL" : "BL"), (strlen(ds->ss->ip) < strlen(res->lookup)) ? (res->lookup + strlen(ds->ss->ip) + 1) : res->lookup); ds->ss->scans--; /* we are done with ss here */ @@ -207,12 +246,18 @@ /* Either an error, or a positive lookup */ if(fdns_errno == FDNS_ERR_NONE) dnsbl_positive(ds->ss, ds->bl, (unsigned char)res->text[3]); else { + /* If any previous positive blacklist result was blocked, waiting + * for whitelists, handle it now + */ + if(ds->bl->whitelist && ds->ss->dnsbl_whitelist_count == 0 && ds->ss->dnsbl_positive_bl != NULL) + dnsbl_positive(ds->ss, ds->ss->dnsbl_positive_bl, ds->ss->dnsbl_positive_type); + log_printf("DNSBL -> Lookup error on %s: %s", res->lookup, firedns_strerror(fdns_errno)); if(fdns_errno != FDNS_ERR_TIMEOUT) irc_send_channels("DNSBL -> Lookup error on %s: %s", res->lookup, firedns_strerror(fdns_errno)); } Index: src/scan.c =================================================================== RCS file: /data/cvs/bopm/src/scan.c,v retrieving revision 1.33 diff -u -6 -r1.33 scan.c --- src/scan.c 22 Jun 2003 17:05:30 -0000 1.33 +++ src/scan.c 26 Jun 2003 21:06:49 -0000 @@ -477,13 +477,18 @@ ss->ip = (char *) DupString(user[3]); ss->proof = (char *) DupString(msg); ss->remote = opm_remote_create(ss->ip); ss->scans = 0; ss->positive = 0; - + + ss->dnsbl_whitelist_count = 0; + ss->dnsbl_whitelisted = 0; + ss->dnsbl_positive_bl = NULL; + ss->dnsbl_positive_type = '\0'; + ss->manual_target = NULL; assert(ss->remote); return ss; } Index: src/scan.h =================================================================== RCS file: /data/cvs/bopm/src/scan.h,v retrieving revision 1.7 diff -u -6 -r1.7 scan.h --- src/scan.h 20 Jun 2003 04:18:38 -0000 1.7 +++ src/scan.h 26 Jun 2003 21:06:49 -0000 @@ -12,13 +12,17 @@ char *ip; char *proof; OPM_REMOTE_T *remote; unsigned short scans; unsigned short positive; - + unsigned short dnsbl_whitelisted; + unsigned short dnsbl_whitelist_count; + unsigned char dnsbl_positive_type; + struct BlacklistConf *dnsbl_positive_bl; + struct ChannelConf *manual_target; }; struct scanner_struct {