source: trunk/uribl/URIdb.pm@ 98

Last change on this file since 98 was 98, checked in by Kris Deugau, 3 days ago

/trunk/uribl

Bump version slightly and add octet value 16, for "High-risk domains" to
export. Note this is not exposed in the UI.

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