source: trunk/dnsbl/dnsbl.cgi@ 69

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

/trunk/dnsbl

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