cups/setcupsbroadcasting

186 lines
6.0 KiB
Perl

#!/usr/bin/perl -w
#
# Script to automatically restrict the printer information broadcasting the
# accepting of external broadcasts, and the access to the printers to local
# (eth?) networks
#
#
# Till Kamppeter (till@mandrakesoft.com)
#
# Copyright 2000 MandrakeSoft
#
# This software may be freely redistributed under the terms of the GNU
# General Public License.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# Do not do any changes during the installation
if ($ENV{'DURING_INSTALL'}) {exit 0};
# Read CUPS config file
my $cups_conf = "/etc/cups/cupsd.conf";
if (!(-f $cups_conf)) {die "No CUPS configuration file $cups_conf!"};
open CONF_CUPS, "$cups_conf" or die "Can't open $cups_conf!";
my @cups_conf_content = <CONF_CUPS>;
close CONF_CUPS;
# If it contains at least one "BrowseAddress" line broadcasting is already
# configured and we are done, stop silently here.
grep(/^\s*BrowseAddress[^:]/, @cups_conf_content) and exit 0;
# Read the output of "ifconfig" to look for local networks
my $dev_is_localnet = 0;
my @local_networks = ();
my @local_bcasts = ();
my $current_ip = "";
my $current_mask = "";
my $current_bcast = "";
if (-x "/sbin/ifconfig") {
open IFCONFIG_OUT, "/sbin/ifconfig|" or die "Couldn't run \"ifconfig\"!";
while (defined($readline = <IFCONFIG_OUT>)) {
# New entry ...
if ($readline =~ /^(\S+)\s/) {
$dev = $1;
# ... for a local network?
if ($dev =~ /^eth/) {$dev_is_localnet = 1}
else {$dev_is_localnet = 0};
# delete previous network data
$current_ip = "";
$current_mask = "";
$current_bcast = "";
}
# Are we in an entry for a local network?
if ($dev_is_localnet == 1) {
# Are we in the important line now?
if ($readline =~ /\sinet addr:[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\s/) {
# Rip out the network addresses
if ($readline =~ /\sinet addr:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\s/) {
$current_ip = $1;
}
if ($readline =~ /\sBcast:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\s/) {
$current_bcast = $1;
}
if ($readline =~ /\sMask:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\s/) {
$current_mask = $1;
}
# Is the entry valid?
if (($current_ip ne "") and ($current_mask ne "")) {
# Is there a broadcast address?
if ($current_bcast eq "") {$current_bcast = $current_ip};
# Store broadcast address (or current IP if there is none)
push @local_bcasts, $current_bcast;
# Calculate mask fore access restriction
$current_ip =~ /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/;
($i1, $i2, $i3, $i4) = ($1, $2, $3, $4);
$current_mask =~ /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/;
($m1, $m2, $m3, $m4) = ($1, $2, $3, $4);
$current_net = "";
if ($m1 eq "255") {$current_net = "${current_net}${i1}\."};
if ($m2 eq "255") {$current_net = "$current_net$i2."};
if ($m3 eq "255") {$current_net = "$current_net$i3."};
if ($m4 eq "255") {$current_net = "$current_net$i4"}
else {$current_net = "$current_net*"};
# Store mask
push @local_networks, $current_net;
}
}
}
}
close(IFCONFIG_OUT);
}
# Remove all valid "BrowseAddress" lines
($_ =~ /^\s*BrowseAddress[^:]/ and $_="") foreach @cups_conf_content;
# Insert the new "BrowseAddress" lines
(push @cups_conf_content, "BrowseAddress $_\n") foreach @local_bcasts;
# Delete all "BrowseOrder", "BrowseAllow" and "BrowseDeny" lines from the file
($_ =~ /^\s*BrowseOrder/ and $_="") foreach @cups_conf_content;
($_ =~ /^\s*BrowseAllow/ and $_="") foreach @cups_conf_content;
($_ =~ /^\s*BrowseDeny/ and $_="") foreach @cups_conf_content;
# Add the new "BrowseOrder" and "BrowseDeny" lines
push(@cups_conf_content,"BrowseOrder Deny,Allow\n");
push(@cups_conf_content,"BrowseDeny All\n");
# Add a "BrowseAllow" line for every local network
(push(@cups_conf_content,"BrowseAllow $_\n")) foreach @local_networks;
# Cut out the root location block
#
# <Location />
# ...
# </Location>
#
# so that it can be treated seperately without affecting the rest of the
# file
if (grep(m!^\s*<Location\s+/\s*>!, @cups_conf_content)) {
$root_location_start = -1;
$root_location_end = -1;
# Go through all the lines, bail out when start and end line found
for ($i = 0;
($i <= $#cups_conf_content) and ($root_location_end == -1);
$i++) {
if ($cups_conf_content[$i] =~ m!^\s*<\s*Location\s+/\s*>!) {
# Start line of block
$root_location_start = $i;
} elsif (($cups_conf_content[$i] =~ m!^\s*<\s*/Location\s*>!) and
($root_location_start != -1)) {
# End line of block
$root_location_end = $i;
}
}
# Rip out the block and store it seperately
@root_location =
splice(@cups_conf_content,$root_location_start,
$root_location_end - $root_location_start + 1);
} else {
# If there is no root location block, create one
$root_location_start = $#cups_conf_content + 1;
@root_location = ();
push @root_location, "<Location />\n";
push @root_location, "</Location>\n";
}
# Delete all former "Order", "Allow", and "Deny" lines from the root location
# block
($_ =~ /^\s*Order/ and $_="") foreach @root_location;
($_ =~ /^\s*Allow/ and $_="") foreach @root_location;
($_ =~ /^\s*Deny/ and $_="") foreach @root_location;
# Add the new "Order" and "Deny" lines
splice(@root_location,-1,0,"Order Deny,Allow\n");
splice(@root_location,-1,0,"Deny From All\n");
splice(@root_location,-1,0,"Allow From 127.0.0.1\n");
# Add an "Allow" line for every local network
(splice(@root_location,-1,0,"Allow From $_\n")) foreach @local_networks;
# Put the changed root location block back into the file
splice(@cups_conf_content,$root_location_start,0,@root_location);
# Write back the modified CUPS config file
open CONF_CUPS, ">$cups_conf" or die "Can't open $cups_conf";
print CONF_CUPS @cups_conf_content;
close CONF_CUPS;