#!/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 = ; 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 = )) { # 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 # # # ... # # # so that it can be treated seperately without affecting the rest of the # file if (grep(m!^\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, "\n"; push @root_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;