Igor Gariev (gariev) wrote in changelog,
Igor Gariev
gariev
changelog

[livejournal] r18319: LJSUP-7811: Whitelist for sysban

Committer: gariev
LJSUP-7811: Whitelist for sysban

U   trunk/cgi-bin/sysban.pl
Modified: trunk/cgi-bin/sysban.pl
===================================================================
--- trunk/cgi-bin/sysban.pl	2011-02-16 08:22:06 UTC (rev 18318)
+++ trunk/cgi-bin/sysban.pl	2011-02-16 08:51:42 UTC (rev 18319)
@@ -393,18 +393,71 @@
     # bail early if the ban already exists
     return "This is already banned"
         if !$opts->{skipexisting} && LJ::sysban_check($what, $value);
+    
+    my $ip_regexp = qr/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/;
+    my $ip_to_str = sub { return pack("C4",split(/\./, $_[0])); }; 
 
     my $validate = {
         'ip' => sub {
             my $ip = shift;
 
+            return "Format: xxx.xxx.xxx.xxx (ip address)" 
+                unless $ip =~ /^$ip_regexp$/;
+
             while (my ($ip_re, $reason) = each %LJ::UNBANNABLE_IPS) {
                 next unless $ip =~ $ip_re;
                 return "Cannot ban IP $ip: " . LJ::ehtml($reason);
             }
+            
+            ## LJ::sysban_populate() doesn't return notes, so select them from DB
+            my $dbh = LJ::get_db_reader()
+                or die "Can't connect to db reader";
+            my $whitelist = $dbh->selectall_arrayref(
+                "
+                    SELECT * 
+                    FROM sysban 
+                    WHERE what = 'ip_whitelist' 
+                        AND status = 'active'
+                        AND NOW() > bandate
+                        AND (NOW() < banuntil
+                           OR banuntil = 0
+                           OR banuntil IS NULL)
+                ",
+                {Slice => {}}
+            );
+            
+            my $matched_wl;
+            foreach my $wl (@$whitelist) {
+                my $mask = $wl->{value}; ## see ip_whitelist below for possible formats
+                if ($mask =~ /^$ip_regexp$/) {
+                    if ($mask eq $ip) {
+                        $matched_wl = $wl;
+                        last;
+                    } 
+                } elsif (my ($start_ip, $end_ip) = $mask =~ /^($ip_regexp)-($ip_regexp)$/) {
+                    if (    $ip_to_str->($start_ip) le $ip_to_str->($ip) && 
+                            $ip_to_str->($ip) le $ip_to_str->($end_ip)) 
+                    {
+                        $matched_wl = $wl;
+                        last;
+                    }
+                } elsif ($mask =~ m!^$ip_regexp/(\d+)!) {
+                    my $netmask = Net::Netmask->new($mask);
+                    if ($netmask->match($ip)) {
+                        $matched_wl = $wl;
+                        last;
+                    }
+                } else {
+                    # hm...
+                }
+            }
 
-            return $ip =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/ ?
-                0 : "Format: xxx.xxx.xxx.xxx (ip address)";
+            if ($matched_wl) {
+                return "Can't bap ip address $ip: ip_whitelist #$matched_wl->{banid} matched ($matched_wl->{note})";
+            }     
+            
+            ## everything is ok
+            return 0;
         },
         'uniq' => sub {
             my $uniq = shift;
@@ -444,6 +497,18 @@
             my $num = shift;
             return $num =~ /\d{10}/ ? 0 : 'Format: 10 digit MSISDN';
         },
+
+        'ip_whitelist' => sub {
+            my $mask = shift;
+            $mask =~ s/\s+//g;
+            
+            ## allowed formats: exact IP address, range IP1-IP2, subnet: IP/num
+            if ($mask =~ /^$ip_regexp$/ || $mask =~ /^$ip_regexp-$ip_regexp$/ || $mask =~ m!^$ip_regexp/\d+$!) {
+                return 0;
+            } else {
+                return "Format: xxx.xxx.xxx.xxx (exact IP address), or xxx.xxx.xxx.xxx-yyy.yyy.yyy.yyy (IP range) or xxx.xxx.xxx.xxx/yyy (subnet)";
+            }
+        }, 
     };
 
     # aliases to handlers above

Tags: gariev, livejournal, pl
Subscribe

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 0 comments