source: trunk/uribl/URIdb.pm@ 89

Last change on this file since 89 was 89, checked in by Kris Deugau, 13 days ago

/trunk/uribl

Tweak handling of the blzone value; use it as a full base domain rather
than something anchored to .dnsbl

  • Property svn:keywords set to Date Rev Author Id
File size: 7.2 KB
Line 
1# URIdb
2# Functions for interacting with the URI database
3##
4# $Id: URIdb.pm 89 2025-09-16 19:00:35Z kdeugau $
5# Copyright 2010,2025 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
21package URIdb;
22
23use strict;
24use warnings;
25use Exporter;
26
27use DBI;
28use NetAddr::IP;
29
30use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
31
32$VERSION = 2.0;
33@ISA = qw(Exporter);
34@EXPORT_OK = qw( $dbh );
35
36@EXPORT = qw( $dbh );
37
38%EXPORT_TAGS = ( ALL => [qw(
39 )]
40 );
41
42## "constants"
43
44# 8 bits available
45# 128 is per-IP shitlist
46# 2 is IP hitlist
47# 1 not available so we don't $self->shoot(foot)
48our %status = (
49 0 => "Don't list",
50 2 => "Black",
51 4 => "Grey",
52 8 => "Abused URL shortener/redirector"
53);
54
55# variables
56our $dbh;
57
58our $err;
59our $errstr;
60
61# basic object subs
62sub new {
63 my $this = shift;
64 my $class = ref($this) || $this;
65 my %args = @_;
66
67 # Prepopulate a basic config. Note some of these *will* cause errors if left unset.
68 my %defconfig = (
69 dbhost => "localhost",
70 dbname => "dnsbl",
71 dbuser => "dnsbl",
72 dbpass => "spambgone",
73 );
74
75 my %siteconfig;
76 my $dbhost;
77 my $dbname;
78 my $dbuser;
79 my $dbpass;
80 if (defined($args{configfile})) {
81 if (-e $args{configfile} && -f $args{configfile}) {
82 my $ret = eval `cat $args{configfile}`;
83 unless ($ret) {
84 if ($@) { $errstr = "couldn't parse $args{configfile}: $@\n"; return; }
85 if (!defined($ret)) { $errstr = "couldn't load $args{configfile}: $!\n"; return; }
86 if (!$ret) { $errstr = "couldn't load $args{configfile}\n"; return; }
87 }
88 # crossload legacy variables, but prefer new %siteconfig values
89 $siteconfig{dbhost} = $dbhost if !$siteconfig{dbhost} && $dbhost;
90 $siteconfig{dbname} = $dbname if !$siteconfig{dbname} && $dbname;
91 $siteconfig{dbuser} = $dbuser if !$siteconfig{dbuser} && $dbuser;
92 $siteconfig{dbpass} = $dbpass if !$siteconfig{dbpass} && $dbpass;
93 }
94 }
95
96 # Assemble the object. Apply configuration hashes in order of precedence.
97 my $self = {
98 # Hardcoded defaults
99 %defconfig,
100 # Default config file OR caller-specified one, loaded above
101 %siteconfig,
102 # Caller-specified arguments
103 %args
104 };
105 bless $self, $class;
106
107 return $self;
108}
109
110sub DESTROY {
111 my $self = shift;
112 $self->dbclose() if $dbh;
113}
114
115# JIC someone wants to close the db but not finish the script
116sub dbclose {
117 $dbh->rollback;
118 $dbh->disconnect;
119}
120
121## specific object subs:
122
123sub connect {
124 my $self = shift;
125 ## want to NOT autocommit everything, it's unlikely we'll step on our own toes but...
126 $dbh = DBI->connect("DBI:Pg:host=$self->{dbhost};dbname=$self->{dbname}", $self->{dbuser}, $self->{dbpass}, {
127 AutoCommit => 0,
128 PrintError => 1
129 })
130 or die "database inaccessible: ".$DBI::errstr;
131 my $sth = $dbh->prepare("SELECT key,value FROM misc");
132 $sth->execute;
133 while (my ($key,$value) = $sth->fetchrow_array) {
134 $self->{misc}{$key} = $value;
135 }
136 $self->{misc}{blzone} = 'uribl.company.com' if !$self->{misc}{blzone};
137 return $dbh;
138}
139
140
141# report a URI to the db
142# increments a hit counter iff the reported URI exists, otherwise it adds it
143# requires the uri.
144# can accept the listing level and a comment
145sub report {
146 my $self = shift;
147 my $uri = shift;
148 my $list = shift || 2;
149 my $comment = shift || '';
150
151 my $sth;
152 my $rows = 0;
153 $sth = $dbh->prepare("SELECT count FROM urilist WHERE uri=?");
154 $sth->execute($uri) or die "eep? ".$dbh->errstr."\n";
155 $rows = $sth->rows;
156 if ($rows == 0) {
157 $sth = $dbh->prepare("INSERT INTO urilist (uri,list,comment) VALUES (?,?,?)");
158 $sth->execute($uri,$list,$comment) or die "couldn't add $uri: ".$dbh->errstr."\n";
159 } elsif ($rows == 1) {
160 $sth = $dbh->prepare("UPDATE urilist SET count=count+1 WHERE uri=?");
161 $sth->execute($uri) or die "couldn't update listing for $uri: ".$dbh->errstr."\n";
162 } else {
163 die "db corrupt: found $rows matches on $uri\n";
164 }
165 $dbh->commit;
166 return $rows;
167} # end report()
168
169
170sub exists {
171 my $self = shift;
172 my $checkme = shift;
173
174 my $sth = $dbh->prepare("SELECT count(*) FROM urilist WHERE uri=?");
175 $sth->execute($checkme);
176 my ($count) = $sth->fetchrow_array;
177 return $count;
178}
179
180
181# Write the data straight to a DNS server's files.
182# Takes a server type and open filehandle.
183sub export {
184 my $self = shift;
185 my $target = shift;
186 my $blfh = shift;
187
188 my $sth;
189
190##fixme: should probably rejig this key to point to a FQDN rather than a "something that will get published under .dnsbl"
191 my $blzone = ($self->{misc}{blzone} ? $self->{misc}{blzone} : 'uri.dnsbl');
192 my $bladmin = ($self->{misc}{bladmin} ? $self->{misc}{bladmin} : 'systems.company.com');
193 my $blttl = ($self->{misc}{ttl} ? $self->{misc}{ttl} : '900');
194##fixme: should probably add some configuration strings for the nameserver value
195
196 if ($target eq 'rbldnsd') {
197 print $blfh "\$SOA 900 $blzone $bladmin 0 1200 600 600 900\n".
198 "\$NS 3600 127.0.0.1\n".
199 "\$TTL $blttl\n";
200 print $blfh ":127.0.0.2:Domain found in reported missed-spam, no legitimate root or www content\n";
201 $sth = $dbh->prepare("SELECT uri FROM urilist WHERE list=2");
202 $sth->execute;
203 while (my ($uri) = $sth->fetchrow_array) {
204 print $blfh ".$uri\n";
205 }
206 print $blfh ":127.0.0.4:Domain seen repeatedly in reported missed-spam, some legitimate root or www content\n";
207 $sth = $dbh->prepare("SELECT uri FROM urilist WHERE list=4");
208 $sth->execute;
209 while (my ($uri) = $sth->fetchrow_array) {
210 print $blfh ".$uri\n";
211 }
212 print $blfh ":127.0.0.8:Abused URL-shortener or redirector domain\n";
213 $sth = $dbh->prepare("SELECT uri FROM urilist WHERE list=8");
214 $sth->execute;
215 while (my ($uri) = $sth->fetchrow_array) {
216 print $blfh ".$uri\n";
217 }
218 } elsif ($target eq 'tinydns') {
219 print $blfh "Z$blzone:$blzone:$bladmin::600:600:600:600\n";
220 print $blfh "\&$blzone:127.0.0.1::900\n";
221 $sth = $dbh->prepare("SELECT uri FROM urilist WHERE list=2");
222 $sth->execute;
223 while (my ($uri) = $sth->fetchrow_array) {
224 print $blfh "'$uri.$blzone:Domain found in reported missed-spam, no legitimate root or www content:900::\n".
225 "+$uri.$blzone:127.0.0.2:900::\n";
226 }
227 $sth = $dbh->prepare("SELECT uri FROM urilist WHERE list=4");
228 $sth->execute;
229 while (my ($uri) = $sth->fetchrow_array) {
230 print $blfh "'$uri.$blzone:Domain seen repeatedly in reported missed-spam, some legitimate root or www content:900::\n".
231 "+$uri.$blzone:127.0.0.4:900::\n";
232 }
233 $sth = $dbh->prepare("SELECT uri FROM urilist WHERE list=8");
234 $sth->execute;
235 while (my ($uri) = $sth->fetchrow_array) {
236 print $blfh "'$uri.$blzone:Abused URL-shortener or redirector domain:900::\n".
237 "+$uri.$blzone:127.0.0.8:900::\n";
238 }
239 } elsif ($target eq 'bind') {
240 } else {
241 }
242 return;
243} # end export()
244
245
246# make Perl happy
2471;
Note: See TracBrowser for help on using the repository browser.