Techblog

Install ClamAV on Fedora via Yum for sendmail

by RyanWagner on May.12, 2010, under Linux/Unix, SMB, Technical, Understanding Technology

ClamAV installation on fedora is not at all simple or straight forward.  ClamAV support and wiki do not properly document the process so here are the steps you need to complete.

packages to install:

clamav-server

clamav-update

clamav-milter

clamav-milter-sysvinit

Then you need to run the bash script found here:

http://github.com/csmart/naa/blob/master/configure-clamd.sh

In the event that link dies:

#!/bin/bash

# Copyright 2009 "Christopher Smart" <m...@christophersmart.com>
#
# 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 3 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, see <http://www.gnu.org/licenses/>.

#This script is for installing and configuring clam-server (clamd) on Fedora

#Variables
VERSION=0.1
COUNTDOWN_TIMEOUT=5
FEDORA_RELEASE="`cat /etc/fedora-release 2>/dev/null`"
FRESHCLAM_CONF="/etc/freshclam.conf"

#These variables are set later, once we know the user
CLAMD_USER=""
CLAMD_CONFIG=""
CLAMD_SYSCONFIG=""
CLAMD_INIT=""
CLAMD_LOGROTATE=""
CLAMD_PID=""
CLAMD_LOG=""

#These variables are set later, once we know clamav-server version
CLAMD_VERSION=""
CLAMD_CONFIG_TEMPLATE=""
CLAMD_SYSCONFIG_TEMPLATE=""
CLAMD_INIT_TEMPLATE=""
CLAMD_LOGROTATE_TEMPLATE=""

#Functions
countdown() {
	i=$1
	echo "If you do NOT want to proceed, hit CTRL+C within $i seconds..."
	while [ $i -gt 0 ]
	do
		sleep 1
		echo -ne "$i.. "
		let i=i-1
	done
}

#Make this more pretty by adding an extra blank line at the beginning
echo ""

#Print help, if requested
if [ "$1" == "help" -o "$1" == "-help" -o "$1" == "--help" -o "$1" == "-h" -o "$1" == "--h" ]
then
	echo "This script configures clamav-server (clamd) on Fedora."
	echo "Version $VERSION"
	echo ""
	echo "Usage:"
	echo " $0 [option] [username] [port]"
	echo ""
	echo "Options:"
	echo " -c creates an instance, overwriting if already exists."
	echo " -r removes an instance."
	echo ""
	echo "Parameters (optional):"
	echo " [username] pass in the username you want clamd to run as, defaults to 'clamav'."
	echo " [port] pass in the port you want clamd to run on, defaults to '3310'."
	echo ""
	echo "Create example:"
	echo " $0 -c me 3311"
	echo ""
	echo "Remove example:"
	echo " $0 -r me 3311"
	echo ""
	echo "Report bugs to m...@christophersmart.com"
	echo ""
	exit 0
fi

#Check that we're running Fedora
if [ -z "$FEDORA_RELEASE" ]
then
	echo "You don't appear to be running Fedora, sorry!"
	echo "Exiting."
	echo ""
	exit 1
fi

#We're running Fedora, so make sure we're root
if [ $EUID -ne 0 ]
then
	echo "You must run this as root. Prepend sudo, or run:"
	echo "su -c '$0 [option] [username] [port]'"
	echo ""
	echo "Exiting."
	echo ""
	exit 1
else
	echo "You appear to be running `echo $FEDORA_RELEASE`, excellent."
	echo ""
fi

#Set clamd user and port
if [ "$1" != "-c" -a "$1" != "-r" ]
then
	CLAMD_USER="clamav"
	CLAMD_PORT="3310"
else
	if [ -z "$2" ]
	then
		CLAMD_USER="clamav"
	else
		CLAMD_USER="$2"
	fi

	if [ -z "$3" ]
	then
		CLAMD_PORT="3310"
	else
		CLAMD_PORT="$3"
	fi
fi

#Variables for config files, now that we know the user
CLAMD_CONFIG="/etc/clamd.d/$CLAMD_USER.conf"
CLAMD_INIT="/etc/init.d/clamd.$CLAMD_USER"
CLAMD_LOGROTATE="/etc/logrotate.d/clamd-$CLAMD_USER"
CLAMD_PID="/var/run/clamd.$CLAMD_USER"
CLAMD_LOG="/var/log/clamd.$CLAMD_USER"
CLAMD_SYSCONFIG="/etc/sysconfig/clamd.$CLAMD_USER"
CLAMD_CHKCONFIG="/sbin/chkconfig clamd.$CLAMD_USER"

#Removing existing instance of clamd for specified user, if told to do so
if [ "$1" == "-r" ]
then
	echo "**WARNING** Removing clamd instance for user '$CLAMD_USER'."
	countdown $COUNTDOWN_TIMEOUT
	echo ""
	echo "OK then, proceeding.."
	echo ""

	#Check to see if there's a configuration for that user already
	if [ ! -e $CLAMD_CONFIG ]
	then
		echo "No clamd instance found for user '$CLAMD_USER'."
		echo "Exiting."
		echo ""
		exit 1
	fi	

	#Stop and disable daemon
	$CLAMD_INIT stop &>/dev/null
	if [ $? -ne 0 ]
	then
		echo "Could not stop service, sorry."
		echo ""
		echo "Instance of clamd for user '$CLAMD_USER' NOT removed."
		echo "Exiting."
		echo ""
		exit 1
	fi

	#Turn off daemon
	$CLAMD_CHKCONFIG off &>/dev/null

	#Remove configs and logs, etc
	rm -f $CLAMD_CONFIG 2>/dev/null
	rm -f $CLAMD_INIT 2>/dev/null
	rm -f $CLAMD_LOGROTATE 2>/dev/null
	rm -rf $CLAMD_PID 2>/dev/null
	rm -f $CLAMD_LOG 2>/dev/null
	rm -f $CLAMD_SYSCONFIG 2>/dev/null
	unlink /usr/sbin/clamd.$CLAMD_USER 2>/dev/null

	#Remove user?
	if [ -n "`id $CLAMD_USER 2>/dev/null`" ]
	then
		#User exists, so ask if it should be removed
		echo -e "**WARNING** DO YOU WANT TO REMOVE THE USER FROM THE SYSTEM? (y/N): \c "
		read answer
		echo ""
		if [ "$answer" == "y" -o "$answer" == "Y" ]
		then
			#Remove user and confirm success
			echo "OK, removing user '$CLAMD_USER' from the system."
			userdel -r $CLAMD_USER 2>/dev/null
			if [ $? -eq 0 -o $? -eq 12 ]
			then
				echo "User removed successfully."
				echo ""
			else
				echo "**WARNING** Could not remove clamd user from the system. Perform manually."
				echo ""
			fi
		else
			echo "OK, user will NOT be removed."
			echo ""
		fi
	else
		echo "User does not exist in the system, not removing."
		echo ""
	fi
	echo "Instance of clamd for user '$CLAMD_USER' has been successfully removed."
	echo ""
	exit 0
fi

#Creating
echo "Configuring clamd to run as user '$CLAMD_USER' on port '$CLAMD_PORT'."
echo ""
countdown $COUNTDOWN_TIMEOUT
echo ""
echo "OK then, proceeding.."
echo ""

#Checking to see if required packages are installed or not
echo "Checking for required packages.."
if [ -n "`rpm -qa |grep clamav`" -a "`rpm -qa |grep clamav-update`" -a "`rpm -qa |grep clamav-server`" ]
then
	echo "Required packages already installed."
	echo ""
else

	#Install required packages
	echo "Installing required clamav packages.."
	echo ""
	yum -yq install clamav clamav-server clamav-update
	echo ""

	#Check that the install was successful (or already installed)
	if [ -n "`rpm -qa |grep clamav`" -a "`rpm -qa |grep clamav-update`" -a "`rpm -qa |grep clamav-server`" ]
	then
		echo "Packages successfully installed."
		echo ""
	else
		echo "Problem installing required packages, sorry."
		echo ""
		echo "Instance of clamd for user '$CLAMD_USER' NOT created successfully."
		echo "Exiting."
		echo ""
		exit 1
	fi
fi

#Get version of clamd, now that it's installed
CLAMD_VERSION="`rpm -qa |grep clamav-server |awk -F "-" {'print $3'} 2>/dev/null`"

#Variables for template files now that we know the version of clamav-server installed
CLAMD_CONFIG_TEMPLATE="/usr/share/doc/clamav-server-$CLAMD_VERSION/clamd.conf"
CLAMD_SYSCONFIG_TEMPLATE="/usr/share/doc/clamav-server-$CLAMD_VERSION/clamd.sysconfig"
CLAMD_INIT_TEMPLATE="/usr/share/doc/clamav-server-$CLAMD_VERSION/clamd.init"
CLAMD_LOGROTATE_TEMPLATE="/usr/share/doc/clamav-server-$CLAMD_VERSION/clamd.logrotate"

#Create clamav user if doesn't exist
#This should be the user who wants to talk to clamd, else user clamav must have read (and possibly write) access on the files.
echo "Checking for clamav user, '$CLAMD_USER'.."

if [ -z "`id $CLAMD_USER 2>/dev/null`" ]
then
	useradd $CLAMD_USER -r -c "User for clamd" -d /dev/null -M -s /sbin/nologin 2>/dev/null
	if [ $? -ne 0 ]
	then
		echo "Unable to create new clamd user, '$CLAMD_USER', sorry."
		echo ""
		echo "Instance of clamd for user '$CLAMD_USER' NOT created successfully."
		echo "Exiting."
		echo ""
		exit 1
	else
		echo "Created new user."
		echo ""
	fi
else
	echo "User already exists, not creating."
	echo ""
fi

#Copy and configure clamd configuration file
echo "Configuring clamd to do all the right things.."

#Check that ALL required template files exist before continuing
if [ ! -e "$CLAMD_CONFIG_TEMPLATE" -o  ! -e "$CLAMD_SYSCONFIG_TEMPLATE" -o ! -e "$CLAMD_INIT_TEMPLATE" -o ! -e "$CLAMD_LOGROTATE_TEMPLATE" ]
then
	echo "Could not find required template files under /usr/share/doc/clamav-server-$CLAMD_VERSION/, sorry."
	echo ""
	echo "Instance of clamd for user '$CLAMD_USER' NOT created successfully."
	echo "Exiting."
	echo ""
	exit 1
fi

#Check to see if an instance of clamd for user already exists
if [ -e $CLAMD_CONFIG ]
then
	echo "Instance of clamd already exists, clobbering.."
	#Stop existing daemon to enable new one
	/etc/init.d/clamd.$CLAMD_USER stop &>/dev/null
	#Remove existing config because 'cp' is aliased with -i and we don't want a prompt
	rm -f $CLAMD_CONFIG 2>/dev/null
fi

#Check to see if the port is already in use, if so, increment by one until we find something that's free
PORT_INUSE=0
while [ -n "`netstat -ltn |grep ":$CLAMD_PORT"`" ]
do
	CLAMD_PORT=$(($CLAMD_PORT+1))

	PORT_INUSE=1
done
if [ $PORT_INUSE == 1 ]
then
	echo "Port was already in use, using '$CLAMD_PORT' instead."
fi

#Make sure directory exists, which it should if clamav-server is installed (but you never know)
mkdir -p /etc/clamd.d 2>/dev/null

#Copy over the template file
cp -f $CLAMD_CONFIG_TEMPLATE $CLAMD_CONFIG 2>/dev/null
sed -i 's/clamd.<SERVICE>/clamd.'$CLAMD_USER'/' $CLAMD_CONFIG
sed -i 's/^Example/#Example/' $CLAMD_CONFIG
sed -i 's/^#LogFile/LogFile/' $CLAMD_CONFIG
sed -i 's/^#PidFile/PidFile/' $CLAMD_CONFIG
sed -i 's/^LocalSocket/#LocalSocket/' $CLAMD_CONFIG
sed -i 's/^#TCPSocket\ 3310/TCPSocket\ '$CLAMD_PORT'/' $CLAMD_CONFIG
sed -i 's/^#TCPAddr/TCPAddr/' $CLAMD_CONFIG
sed -i 's/<USER>/'$CLAMD_USER'/' $CLAMD_CONFIG
echo "Done."
echo ""

#Copy and configure clamd for log rotation
if [ -d /etc/logrotate.d ]
then
	echo "Configuring log rotation for clamd.."

	#Try to remove existing log rotate config, whether it exists or not because 'cp' is aliased with -i
	rm -f $CLAMD_LOGROTATE 2>/dev/null
	cp -f $CLAMD_LOGROTATE_TEMPLATE $CLAMD_LOGROTATE
	sed -i 's/clamd.<SERVICE>/clamd.'$CLAMD_USER'/' $CLAMD_LOGROTATE
fi
echo "Done."
echo ""

#Configuring clamd under sysconfig
echo "Configuring clamd under syconfig.."

#Try to remove existing config, whether it exists or not because 'cp' is aliased with -i
rm -f $CLAMD_SYSCONFIG 2>/dev/null

#Copy over the template file
cp -f $CLAMD_SYSCONFIG_TEMPLATE $CLAMD_SYSCONFIG 2>/dev/null
sed -i 's/<SERVICE>/'$CLAMD_USER'/' $CLAMD_SYSCONFIG
sed -i 's/^#CLAMD/'CLAMD'/' $CLAMD_SYSCONFIG
echo "Done."
echo ""

#Configuring clamd init script
echo "Configuring clamd init script.."

#Try to remove existing config, whether it exists or not because 'cp' is aliased with -i
rm -f $CLAMD_INIT 2>/dev/null

#Copy over the init script
cp -f $CLAMD_INIT_TEMPLATE $CLAMD_INIT 2>/dev/null
sed -i 's/<SERVICE>/'$CLAMD_USER'/' $CLAMD_INIT
ln -s /usr/sbin/clamd /usr/sbin/clamd.$CLAMD_USER 2>/dev/null
$CLAMD_CHKCONFIG on
#Check that was successful
if [ $? -ne 0 ]
then
	echo "Could not turn service on, sorry."
	echo "Exiting."
	echo ""
	exit 1
fi
echo "Done."
echo ""

#Configure freshclam
echo "Enabling freshclam, the clamav updater.."
sed -i 's/^Example/#Example/' $FRESHCLAM_CONF

#Should we set the proxy too, if in env?
echo "Done."
echo ""

echo "Creating required directories and starting service.."
#Setup logs
touch $CLAMD_LOG
chown $CLAMD_USER:$CLAMD_USER $CLAMD_LOG
chmod 0620 $CLAMD_LOG

#Setup run socket
mkdir $CLAMD_PID 2>/dev/null
chown $CLAMD_USER:$CLAMD_USER $CLAMD_PID/

#Start services
/etc/init.d/clamd.$CLAMD_USER start &>/dev/null
if [ $? -ne 0 ]
then
	echo "Could not start service, sorry."
	echo "Continuing."
	echo ""
fi
echo "Done."
echo ""

#Print summary
echo "The clamd service has been successfully installed and configured with:"
echo "User '$CLAMD_USER' on port '$CLAMD_PORT'."
echo ""
echo 'Have fun!'
echo ""
Now open clamav-milter.conf (/etc/mail/clamav-milter.conf)
comment out:
#Example
Add/Change:
MilterSocket /var/run/clamav-milter/clamav-milter.socket
ClamdSocket unix:/var/run/clamd.clamav/clamd.sock
ClamdSocket tcp:localhost
Now open clamd.conf (/etc/clamd.conf)
comment out:
#User <USER>
Add/Change:
LocalSocket /var/run/clamd.clamav/clamd.sock
Your services are named
THIS INSTALL = OTHER DISTROS
clamd.clamav = clamd
clamav-milter = clamav-milter
In Sendmail you need to edit the m4 file:
add/change:
INPUT_MAIL_FILTER(`clamav-milter',`S=local:/var/run/clamav-milter/clamav-milter.socket,F=T, T=S:4m;R:4m')dnl
define(`ConfINPUT_MAIL_FILTERS', `clamav-milter')dnl
At this point you will need to restart all 3 services (clamd.clamav, clamav-milter, sendmail)
Keep in mind that this process will enable clamav, but by default clamav doesn't do anything.  You will still need to configure clamav, but this process is just like any other distro.

Leave a Reply

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!

Visit our friends!

A few highly recommended friends...