source: trunk/dnsbl/dnsbl.cgi@ 66

Last change on this file since 66 was 66, checked in by Kris Deugau, 6 years ago

/trunk/dnsbl

Add exclusion flagging and block-comment handling to IP list tools. Exclusion
flags can be set or unset on each submit; netblock comments can be added,
updated, or removed (or at least "set empty") on each submit.

Note this is focused on the CIDR (rbldnsd) export format, and may produce
excitingly weird results with the default "classful"/tinydns mode.

  • Property svn:executable set to *
  • Property svn:keywords set to Date Rev Author Id
File size: 7.2 KB
Line 
1#!/usr/bin/perl
2# Main add-IP-to-list CGI
3##
4# $Id: dnsbl.cgi 66 2018-01-05 23:06:47Z kdeugau $
5# Copyright 2009-2011,2014 Kris Deugau <kdeugau@deepnet.cx>
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation, either version 3 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19##
20
21use strict;
22use warnings;
23no warnings qw(uninitialized);
24use CGI::Carp qw (fatalsToBrowser);
25use CGI::Simple;
26use HTML::Template;
27use Net::DNS;
28
29use DNSBL;
30use DNSBLweb;
31
32# Set up the CGI object...
33my $q = new CGI::Simple;
34# ... and get query-string params as well as POST params if necessary
35$q->parse_query_string;
36
37my %webvar;
38# This is probably excessive fiddling, but it puts the parameters somewhere my fingers know about...
39foreach ($q->param()) {
40 $webvar{$_} = $q->param($_);
41}
42
43my $dnsbl = new DNSBL;
44# here be drag'ns, should theoretically be $DNSBL::maxlvl, but we
45# only have up to level 4 in the report HTML/template
46my $maxlvl = 4;
47
48# try to be friendly to non-US-ASCII characters. Still need to find what
49# difference from RH<->Debian is still at fault.
50print $q->header(-charset=>'utf8');
51
52# default DB info - all other settings should be loaded from the DB.
53my $dbhost = "localhost";
54my $dbname = "dnsbl";
55my $dbuser = "dnsbl";
56my $dbpass = "spambgone";
57
58# Load a config ref containing DB host, name, user, and pass info based on
59# from the server name + full script web path. This allows us to host
60# multiple instances without having to duplicate the code.
61# This file is a Perl fragment to be processed inline.
62my $cfgname = $ENV{SERVER_NAME}.$ENV{REQUEST_URI};
63$cfgname =~ s|[./-]|_|g;
64$cfgname =~ s|_dnsbl_cgi.*||;
65$cfgname =~ s|_$||;
66if (-e "/etc/dnsbl/$cfgname.conf") {
67 my $cfg = `cat /etc/dnsbl/$cfgname.conf`;
68 ($cfg) = ($cfg =~ /^(.+)$/s); # avoid warnings, failures, and general nastiness with taint mode
69 eval $cfg;
70}
71
72my $dbh = $dnsbl->connect($dbhost, $dbname, $dbuser, $dbpass);
73
74my $page;
75my $templatedir = $ENV{SCRIPT_FILENAME};
76$templatedir =~ s/\w+\.cgi//;
77$templatedir .= "templates";
78$ENV{HTML_TEMPLATE_ROOT} = $templatedir;
79
80my %config;
81my $sth = $dbh->prepare("SELECT key,value FROM misc");
82$sth->execute;
83while (my ($key,$value) = $sth->fetchrow_array) {
84 $config{$key} = $value;
85}
86
87# decide which page to spit out...
88if (!$webvar{page}) {
89 $page = HTML::Template->new(filename => "index.tmpl");
90} else {
91 $page = HTML::Template->new(filename => "$webvar{page}.tmpl");
92}
93
94$page->param(pgtitle => $config{pgtitle}) if defined($config{pgtitle});
95$page->param(pgcomment => $config{pgcomment}) if defined($config{pgcomment});
96
97if ($webvar{page} eq 'report') {
98 my $dnsblsiteroot = $ENV{REQUEST_URI};
99 $dnsblsiteroot =~ s|/dnsbl\.cgi\?.+|/|;
100 $page->param(dnsblsiteroot => $dnsblsiteroot);
101
102 $webvar{ip} =~ s/^\s*//;
103 $webvar{ip} =~ s/\s*$//;
104 $page->param(ip => $webvar{ip});
105
106##fixme
107# at some point this may need to be tweaked for Net::DNS's 1.x calling convention when they drop support for the older one
108 #my @ptr = rr($webvar{ip});
109 #$page->param(revinfo => join(',',@ptr));
110 my $res = new Net::DNS::Resolver;
111 $res->tcp_timeout(2); # make me adjustable!
112 $res->udp_timeout(2); # make me adjustable!
113 my $query = $res->query($webvar{ip}, "PTR");
114 if ($query) {
115 my @rdata;
116 foreach my $rr ($query->answer) {
117 my ($host,$ttl,$class,$type,$data) =
118 ($rr->string =~ /^([0-9a-zA-Z_.-]+)\s+(\d+)\s+([A-Za-z]+)\s+([A-Za-z]+)\s+(.+)$/s);
119 push @rdata, $data;
120 }
121 $page->param(revinfo => join(', ',@rdata));
122 } else {
123 $page->param(revinfo => "DNS error: ".$res->errorstring);
124 }
125
126 my $ipinfo = $dnsbl->ipexists($webvar{ip});
127 $page->param(nreports => $ipinfo->[0]) if $ipinfo;
128 $page->param(ipexclude => $ipinfo->[1]) if $ipinfo;
129 # extract and list the entire tree the IP is part of
130 $page->param(browsebits =>
131 DNSBLweb::retlvl($dbh, $dnsbl, 0, ip => $webvar{ip}, block => $dnsbl->getcontainer($webvar{ip},0) ));
132 for (my $i=0; $i <= $maxlvl; $i++) {
133 my ($block,$comment,$org) = $dnsbl->getcontainer($webvar{ip},$i);
134 if ($block) {
135 $page->param("comment$i" => $comment);
136 my ($bcl,$bal,$bwl) = $dnsbl->islisted($block);
137 $page->param("autob$i" => $bcl);
138 $page->param("flag$i" => ($bwl ? 'exclude' : ($bal ? 'b1list' : '')) );
139 $page->param("excl$i" => $bwl);
140 my ($ol) = $dnsbl->islisted($org);
141 $page->param("listorg$i" => $ol);
142 $page->param("block$i" => $block);
143 $page->param("org$i" => $org);
144 }
145 }
146} elsif ($webvar{page} eq 'dbreport') {
147 my $dnsblsiteroot = $ENV{REQUEST_URI};
148 $dnsblsiteroot =~ s|/dnsbl\.cgi\?.+|/|;
149 $page->param(dnsblsiteroot => $dnsblsiteroot);
150
151 my $err = '';
152
153 $webvar{ip} =~ s/^\s*//;
154 $webvar{ip} =~ s/\s*$//;
155
156 # basic algo: for each listing level, add the org and block if not already present.
157 # escape the loop if we check a level with no block entered.
158
159 # there are still error checks that should probably be done. changes in block
160 # level/parenting should also Just Work(TM), rather than requiring setparents.pl
161 # or setparents-full.pl
162 for (my $i = 0; $i <= $maxlvl; $i++) {
163 my $orgn = "org$i";
164 my $blockn = "block$i";
165 my $commentn = "comment$i";
166 my $excln = "exclude$i";
167 $webvar{$orgn} =~ s/^\s*//;
168 $webvar{$orgn} =~ s/\s*$//;
169 $webvar{$blockn} =~ s/^\s*//;
170 $webvar{$blockn} =~ s/\s*$//;
171 $webvar{$commentn} =~ s/^\s*//;
172 $webvar{$commentn} =~ s/\s*$//;
173 $webvar{$excln} =~ s/on/1/;
174 my $orgid = $dnsbl->orgexists($webvar{$orgn});
175 if (!$orgid) {
176 $orgid = $dnsbl->addorg($webvar{$orgn});
177 $page->param($orgn => $webvar{$orgn});
178 }
179 if ($webvar{$blockn} =~ /-/) {
180 my $tmp = new NetAddr::IP $webvar{$blockn};
181 if (!$tmp) {
182 # Don't need to autofind ranges that are already CIDR-matched
183 $err .= "Autofinding CIDR block containing $webvar{ip} for range '$webvar{$blockn}': ";
184 my ($s,$f) = split /[\s-]+/, $webvar{$blockn};
185 my $cidr = $dnsbl->range2cidr($s, $f, $webvar{ip});
186 $err .= "$cidr<br>\n";
187 $webvar{$blockn} = $cidr;
188 }
189 }
190 if (!$dnsbl->blockexists($webvar{$blockn})) {
191 my $ret = $dnsbl->addblock($webvar{$blockn}, $orgid, $i, $webvar{$excln});
192 $err .= "error adding $webvar{$blockn}: $ret<br>\n" if $ret;
193 $page->param($blockn => $webvar{$blockn});
194 } else {
195 my $ret = $dnsbl->updateblock($webvar{$blockn}, $orgid, $i, $webvar{$excln}, $webvar{$commentn});
196 $err .= "error updating $webvar{$blockn}: $ret<br>\n" if $ret;
197 }
198 last unless $webvar{"block".($i+1)};
199 }
200
201 my $count = $dnsbl->report($webvar{ip}, $webvar{excludeip});
202
203 $page->param(ip => $webvar{ip});
204 $page->param(err => $err);
205
206 $page->param(browsebits =>
207 DNSBLweb::retlvl($dbh, $dnsbl, 0, ip => $webvar{ip}, block => $dnsbl->getcontainer($webvar{ip},0) ));
208}
209
210print $page->output;
Note: See TracBrowser for help on using the repository browser.