From cd6759f311fe67e6577acb9e73694aec3fca71a3 Mon Sep 17 00:00:00 2001 From: Colin Kuskie Date: Tue, 14 Feb 2006 22:35:21 +0000 Subject: [PATCH] Modify WebGUI IP fields to use CIDR format instead of a regular expression. Multiple IPs are separated by commas, whitespace is ignored. In groups, that affects the ipFilter field, User::isInGroup. In settings, that affects Settings::debugIp and Session::ErrorHandler::canShowDebug. Fixed a bug in WebGUI::Utility::isInSubnet where Net::Subnets->check needs a scalar. Modified t/User.t to use addresses in CIDR format. --- docs/changelog/6.x.x.txt | 5 ++++ docs/upgrades/upgrade_6.8.6-6.9.0.pl | 34 ++++++++++++++++++++++++++++ lib/WebGUI/Session/ErrorHandler.pm | 12 ++++------ lib/WebGUI/User.pm | 14 ++++-------- lib/WebGUI/Utility.pm | 2 +- lib/WebGUI/i18n/English/WebGUI.pm | 10 ++++---- t/User.t | 4 ++-- 7 files changed, 55 insertions(+), 26 deletions(-) diff --git a/docs/changelog/6.x.x.txt b/docs/changelog/6.x.x.txt index a6ebbdb51..5de6d6bd9 100644 --- a/docs/changelog/6.x.x.txt +++ b/docs/changelog/6.x.x.txt @@ -22,6 +22,11 @@ - fix [ 1410577 ] WebGUI::Session not included - Strengthened security of Captcha validation. - Added Captcha form control type. + - All IPs used by WebGUI (Settings: debugIp and Group: ipFilter) now accept + IP addresses in CIDR format. They also will accept multiple IP addresses + if they are separated by commas. Whitespace is ignored. The upgrade + script will migrate the data automatically, and hoverHelp documentation + has been updated to reflect the changes as well. 6.8.7 - fix [ 1431098 ] op=becomeUser can become non-existent userIds diff --git a/docs/upgrades/upgrade_6.8.6-6.9.0.pl b/docs/upgrades/upgrade_6.8.6-6.9.0.pl index 3a0e924d1..793c1bc5f 100644 --- a/docs/upgrades/upgrade_6.8.6-6.9.0.pl +++ b/docs/upgrades/upgrade_6.8.6-6.9.0.pl @@ -30,6 +30,7 @@ addEMSTables(); updateTemplates(); updateDatabaseLinksAndSQLReport(); addWorkflow(); +ipsToCIDR(); finish($session); # this line required @@ -392,6 +393,39 @@ sub removeFiles { rmtree('../../lib/WebGUI/Asset/Wobject/IndexedSearch'); } +#------------------------------------------------- +sub ipsToCIDR { + print "\tTranslating IP addresses to CIDR format.\n" unless ($quiet); + print "\t\tStarting with Group ipFilters.\n" unless ($quiet); + my $sth = $session->db->read('select groupId, ipFilter from groups'); + while (my $hash = $sth->hashRef) { + next unless $hash->{ipFilter}; + $hash->{ipFilter} =~ s/\s//g; + my @ips = split /;/, $hash->{ipFilter}; + @ips = map { ip2cidr($_) } @ips; + $session->db->write('update groups set ipFilter=? where groupId=?', + [join(',', @ips), $hash->{groupId}]); + } + print "\t\tUpdating debug Ip.\n" unless ($quiet); + $sth = $session->db->read("select * from settings where name='debugIp'"); + while (my $hash = $sth->hashRef) { + next unless $hash->{value}; + my @ips = split /\s+/, $hash->{value}; + @ips = map { ip2cidr($_) } @ips; + $session->db->write('update settings set value=? where name=?', + [join(',', @ips), $hash->{name}]); + } +} + +sub ip2cidr { + my ($ip) = @_; + $ip =~ s/\.$//; + my $bytes = $ip =~ tr/././; + my $new_bytes = 3-$bytes; + my $prefixLength = 32 - 8*$new_bytes; + $ip .= ('.0' x $new_bytes) . "/$prefixLength"; + return $ip; +} # ---- DO NOT EDIT BELOW THIS LINE ---- diff --git a/lib/WebGUI/Session/ErrorHandler.pm b/lib/WebGUI/Session/ErrorHandler.pm index d9ae8a4e7..46bc5c9d8 100644 --- a/lib/WebGUI/Session/ErrorHandler.pm +++ b/lib/WebGUI/Session/ErrorHandler.pm @@ -87,14 +87,10 @@ sub canShowDebug { return 0 unless ($self->session->setting->get("showDebug")); return 0 unless ($self->session->http->getMimeType eq "text/html"); return 1 if ($self->session->setting->get("debugIp") eq ""); - my @ips = split(" ",$self->session->setting->get("debugIp")); - my $ok = 0; - foreach my $ip (@ips) { - if ($self->session->env->get("REMOTE_ADDR") =~ /^$ip/) { - $ok = 1; - last; - } - } + my $ips = $self->session->setting->get("debugIp"); + $ips =~ s/\s+//g; + my @ips = split(",", $ips); + my $ok = WebGUI::Utility::isInSubnet($self->session->env->get("REMOTE_ADDR"), [ @ips] ); return $ok; } diff --git a/lib/WebGUI/User.pm b/lib/WebGUI/User.pm index c8cb3f282..ffa205dc8 100644 --- a/lib/WebGUI/User.pm +++ b/lib/WebGUI/User.pm @@ -258,16 +258,10 @@ sub isInGroup { ### Check IP Address if ($group->get("ipFilter")) { my $ipFilter = $group->get("ipFilter"); - $ipFilter =~ s/\s//g; - $ipFilter =~ s/\./\\\./g; - my @ips = split(";",$ipFilter); - foreach my $ip (@ips) { - if ($self->session->env->get("REMOTE_ADDR") =~ /^$ip/) { - $isInGroup->{$uid}{$gid} = 1; - $self->session->stow->set("isInGroup",$isInGroup); - return 1; - } - } + $ipFilter =~ s/\s+//g; + my @ips = split(",",$ipFilter); + my $ipMatch = WebGUI::Utility::isInSubnet($self->session->env->get("REMOTE_ADDR"), [ @ips ]); + return 1 if $ipMatch; } return 0 if ($uid eq '1'); #Visitor is in no other groups return 1 if ($uid eq '3'); #Admin is in every group diff --git a/lib/WebGUI/Utility.pm b/lib/WebGUI/Utility.pm index 25158e810..dc53ea408 100644 --- a/lib/WebGUI/Utility.pm +++ b/lib/WebGUI/Utility.pm @@ -192,7 +192,7 @@ sub isInSubnet { } my $net = Net::Subnets->new; $net->subnets($subnets); - if ($net->check($ip)) { + if ($net->check(\$ip)) { return 1; } else { return 0; diff --git a/lib/WebGUI/i18n/English/WebGUI.pm b/lib/WebGUI/i18n/English/WebGUI.pm index b344f7d27..d7e45ee80 100644 --- a/lib/WebGUI/i18n/English/WebGUI.pm +++ b/lib/WebGUI/i18n/English/WebGUI.pm @@ -12,8 +12,8 @@ our $I18N = { }, 'debug ip description' => { - message => q|This will limit debugging output to a specific IP address or IP range. To limit the output to anyone in a subnet of 10.0.0.0/24 you'd simply enter 10.0.0. |, - lastUpdated => 0 + message => q|This will limit debugging output to a specific IP address or IP range. Enter the subnet that you want to be able to view debug output in CIDR format. For example: 10.0.0.0/24. Multiple CIDR addresses may be entered, separated by commas.|, + lastUpdated => 1139948380 }, 'debug ip' => { @@ -1760,11 +1760,11 @@ As with any delete operation, you are prompted to be sure you wish to proceed wi }, '857 description' => { - message => q|Specify an IP address or an IP mask to match. If the user's IP address matches, they'll automatically be included in this group. An IP mask is simply the IP address minus an octet or two. You may also specify multiple IP masks separated by semicolons. + message => q|Specify IP addresses in CIDR format. Multiple addresses can be entered if they are separated by commas. Spaces, tabs and carriage returns and newlines will be ignored.

-IP Mask Example: 10.;192.168.;101.42.200.142 +IP Mask Example: 10.0.0.32/27, 192.168.0.1/30

|, - lastUpdated => 1120448672, + lastUpdated => 1139955354, }, '945 description' => { diff --git a/t/User.t b/t/User.t index 37dc07c3c..6ec5a10b8 100644 --- a/t/User.t +++ b/t/User.t @@ -231,9 +231,9 @@ ok ($admin->isInGroup($cm->getId), "Admin is not member of group"); my $origFilter = $cm->ipFilter; -$cm->ipFilter('192.168.0.'); +$cm->ipFilter('192.168.0.0/24'); -is( $cm->ipFilter, "192.168.0.", "ipFilter assignment to local net, 192.168.0."); +is( $cm->ipFilter, "192.168.0.0/24", "ipFilter assignment to local net, 192.168.0.0/24"); ok ($visitor->isInGroup($cm->getId), "Visitor is allowed in via IP");