# MailScanner - SMTP E-Mail Virus Scanner # Copyright (C) 2002 Julian Field # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # The author, Julian Field, can be contacted by email at # Jules@JulianField.net # or by paper mail at # Julian Field # Dept of Electronics & Computer Science # University of Southampton # Southampton # SO17 1BJ # United Kingdom # # 07/23/2002 # James A. Pattie (james@pcxperience.com) - updated to only have the # options needed for virus scanning configuration. # Read the configuration file and set globals accordingly. use strict; package Config; my $prefix = '/etc/dansguardian'; # Default values $Config::Debugging = 0; $Config::Sweep = "/usr/local/sophos/bin/sophoswrapper"; $Config::PidFile = "/var/run/virus.pid"; $Config::DefaultConfig = "$prefix/virusscanner.conf"; $Config::QuarantineAction = 'store'; $Config::LocalPostmaster = 'postmaster'; $Config::QuarantineDir = "/var/www/html/dgvirus/quarantine"; $Config::VirusScanner = 'sophos'; $Config::LockType = ''; $Config::SweepTimeout = 300; $Config::CodeStatus = 'supported'; $Config::LockDir = '/tmp'; $Config::SyslogFacility = 'user'; $Config::MailDomain = 'your.domain.com'; $Config::MailServer = '127.0.0.1'; $Config::MailType = 'text/plain'; $Config::DownloadDir = '/tmp/dgvirus'; $Config::StatusGroupedBy = 'uname'; sub ReadConfig { my($Config) = @_; my($key, $value, $whole); local(*CONF); $Config = $Config::DefaultConfig unless defined $Config; open(CONF, $Config) or Log::DieLog("Could not open config file $Config, %s", $!); while(<CONF>) { chomp; s/#.*$//; # Trim comments s/^\s*//g; # Trim leading space # Extract everything after the =\s* for inline signatures /^[^=]*=\s*(.*)$/; $whole = $1; s/\s*$//g; # Trim trailing space next if /^$/; # Ignore comments # This was # ($key, $value) = split(/\s*=\s*/, $_, 2); # The following should be equivalent but with untainting # (we trust the admin to put sensible things in the config file). # -- nwp, 14/01/02 /^(.*?)\s*=\s*(.*)$/; ($key,$value) = ($1,$2); $key = lc($key); $key =~ s/[^a-z]//g; # Delete everything except letters $Config::PidFile = $value if $key =~ /^pid/; $Config::Sweep = $value if $key =~ /^sweep/; $Config::LocalPostmaster = $value if $key =~ /^localpostmaster/; $Config::Debugging = $value if $key =~ /^debug/; $Config::QuarantineAction = $value if $key =~ /^action/; $Config::QuarantineDir = $value if $key =~ /^quarantinedir/; $Config::VirusScanner = lc($value) if $key =~ /^virusscanner$/i; $Config::LockType = lc($value) if $key =~ /^locktype/i; $Config::SweepTimeout = $value if $key =~ /^virusscannertimeout/i; $Config::CodeStatus = $value if $key =~ /^minimumcodestatus/i; $Config::LockDir = $value if $key =~ /^lockfiledir/i; $Config::SyslogFacility = $value if $key =~ /^logfacility$/i; $Config::MailDomain = $value if $key =~ /^maildomain$/i; $Config::MailServer = $value if $key =~ /^mailserver$/i; $Config::MailType = $value if $key =~ /^mailtype$/i; $Config::DownloadDir = $value if $key =~ /^downloaddir$/i; $Config::StatusGroupedBy = $value if $key =~ /^statusinfogroupedby$/i; } close CONF; # Start logging here so we can set the log facility first Log::Start($Config::MailScannerProcessName, $Config::SyslogFacility); Log::InfoLog("Virus Scanner $Config::DGVirusVersion in DansGuardian $Config::DGVersion from MailScanner $Config::MailScannerVersion starting."); # Sanitise values of QuarantineAction $Config::QuarantineAction = 'store' if $Config::QuarantineAction =~ /quar|keep|stor|save/i; $Config::QuarantineAction = 'delete' if $Config::QuarantineAction =~ /dele|wipe/i; # make sure we have a valid MailType Log::DieLog("MailType = '$Config::MailType' is invalid! Needs to be 'text/plain' or 'text/html'.") if ($Config::MailType !~ /^(text\/(plain|html))$/); # make sure we have a valid MailDomain value Log::DieLog("MailDomain = '$Config::MailDomain' is invalid! You need to specify your own mail domain!") if ($Config::MailDomain eq "your.domain.com"); # make sure we have a valid StatusGroupedBy value Log::DieLog("Status Info Grouped By = '$Config::StatusGroupedBy' is invalid! Needs to be 'uname' or 'ip'.") if ($Config::StatusGroupedBy !~ /^(uname|ip)$/); # Remove any trailing slashes from the directory names, they will cause # trouble later if left in. $Config::QuarantineDir =~ s/\/$//; $Config::LockDir =~ s/\/$//; $Config::DownloadDir =~ s/\/$//; # Check to ensure all the directories and files we need actually exist DirExists($Config::QuarantineDir) if ($Config::QuarantineAction eq "store"); DirExists($Config::LockDir); # Check that the script at the start of the "Sweep" command exists my($command); $command = (split(/[,\s]/, $Config::Sweep, 2))[0]; if ($command eq "none") { DieLog("You must specify a virus engine to work with other than none!"); } FileReadable($command); } # # Check a configuration file exists and is readable. # Produce an error if it is not. # sub FileReadable { my($name) = @_; return 1 unless $name; return 1 if -r $name; Log::DieLog("Configuration file $name could not be opened for reading!"); } # Check a directory exists and is writeable. # Produce an error if it is not. # sub DirExists { my($name) = @_; return 1 unless $name; return 1 if -d $name; Log::DieLog("Directory $name does not exist!"); } # Check two files/directories are on the same partition. # Produce an error if it is not. # Can't do this here as it breaks "require" by changing directory. # # Set a Config variable to 0 or 1 depending on its current contents # sub ZeroOrOne { my($current) = @_; return 1 if $current =~ /yes|true|on|1/i; return 0; } 1;