[Pkg-clamav-commits] [SCM] Debian repository for ClamAV branch, debian/unstable, updated. debian/0.94.dfsg.2-1-303-gd86c30a
Michael Tautschnig
mt at debian.org
Sun Mar 8 21:23:53 UTC 2009
The following commit has been merged in the debian/unstable branch:
commit ea86953e5c644f653261362c2978e487252a2b45
Author: Michael Tautschnig <mt at debian.org>
Date: Sun Mar 8 21:42:24 2009 +0100
Merged changes from upstream tarball for 0.95rc1
- contrib directory has been removed entirely
- updated main.cvd, daily.cvd
- some whitespace fixes maybe had been lost during merge
Signed-off-by: Michael Tautschnig <mt at debian.org>
diff --git a/ChangeLog b/ChangeLog
index 1b21e37..0b4f6b5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1214,7 +1214,7 @@ Thu Oct 30 16:47:17 CET 2008 (tk)
Thu Oct 30 13:52:42 CET 2008 (acab)
-----------------------------------
* libclamav/vba_extract.c: get_unicode_name off-by-one - bb#1239
- reported by Moritz Jodeit <moritz*jodeit.org>
+ reported by Moritz Jodeit <moritz*jodeit.org>
Thu Oct 30 13:07:53 EET 2008 (edwin)
------------------------------------
@@ -1870,7 +1870,7 @@ Tue Jul 29 02:44:53 CEST 2008 (acab)
Tue Jul 29 02:18:11 CEST 2008 (acab)
------------------------------------
* libclamav/autoit.c: rely on generic text normalization for
- unicode scripts
+ unicode scripts
* test: add clam.ea05.exe, clam.ea06.exe
Mon Jul 28 21:04:53 CEST 2008 (acab)
diff --git a/NEWS b/NEWS
index a5dcd5a..934d4ab 100644
--- a/NEWS
+++ b/NEWS
@@ -1,8 +1,48 @@
-0.94.2
-------
+0.95rc1
+-------
-This is a bugfix release, please refer to the ChangeLog for a complete
-list of changes.
+ClamAV 0.95rc1 introduces many bugfixes, improvements and additions. To make
+the transition easier, we put various tips and upgrade notes on this page:
+https://wiki.clamav.net/Main/UpgradeNotes095
+
+The following are the key features of this release:
+
+ - New clamav-milter: The program has been redesigned and rewritten from
+ scratch. The most notable difference is that the internal mode has been
+ dropped which means that now a working clamd companion is required.
+ The milter now also has its own configuration file.
+
+ - Clamd extensions: The protocol has been extended to lighten the load
+ that clamd puts on the system, solve limitations of the old protocol,
+ and reduce latency when signature updates are received. Fore more
+ information about the new extensions please see the official
+ documentation and the upgrade notes.
+
+ - Improved API: The API used to program ClamAV's engine (libclamav) has
+ been redesigned to use modern object-oriented techniques and solves
+ various API/ABI compatibility issues between old and new releases.
+ You can find more information in Section 6 of clamdoc.pdf and in
+ the upgrade notes.
+
+ - ClamdTOP: This is a new program that allows system administrators to
+ monitor clamd. It provides information about the items in the clamd's
+ queue, clamd's memory usage, and the version of the signature database,
+ all in real-time and in nice curses-based interface.
+
+ - Memory Pool Allocator: Libclamav now includes its own memory pool
+ allocator based on memory mapping. This new solution replaces the
+ traditional malloc/free system for the copy of the signatures that
+ is kept in memory. As a result, clamd requires much less memory,
+ particularly when signature updates are received and the database is
+ loaded into memory.
+
+ - Unified Option Parser: Prior to version 0.95 each program in ClamAV's
+ suite of programs had its own set of runtime options. The new general
+ parser brings consistency of use and validation to these options across
+ the suite. Some command line switches of clamscan have been renamed
+ (the old ones will still be accepted but will have no effect and will
+ result in warnings), please see clamscan(1) and clamscan --help for
+ the details.
--
The ClamAV team (http://www.clamav.net/team)
diff --git a/README b/README
index 75c8180..ecc75b3 100644
--- a/README
+++ b/README
@@ -2,15 +2,6 @@ Note: This README/NEWS file refers to the source tarball. Some things described
here may not be available in binary packages.
--
-0.94.2
-------
-
-This is a bugfix release, please refer to the ChangeLog for a complete
-list of changes.
-
---
-The ClamAV team (http://www.clamav.net/team)
-
0.95rc1
-------
diff --git a/configure b/configure
index 70b6043..a27c6dd 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.61 for clamav 0.94.2.
+# Generated by GNU Autoconf 2.61 for clamav devel.
#
# Report bugs to <http://bugs.clamav.net/>.
#
@@ -725,8 +725,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='clamav'
PACKAGE_TARNAME='clamav'
-PACKAGE_VERSION='0.94.2'
-PACKAGE_STRING='clamav 0.94.2'
+PACKAGE_VERSION='devel'
+PACKAGE_STRING='clamav devel'
PACKAGE_BUGREPORT='http://bugs.clamav.net/'
ac_unique_file="clamscan/clamscan.c"
@@ -1452,7 +1452,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures clamav 0.94.2 to adapt to many kinds of systems.
+\`configure' configures clamav devel to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1523,7 +1523,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of clamav 0.94.2:";;
+ short | recursive ) echo "Configuration of clamav devel:";;
esac
cat <<\_ACEOF
@@ -1670,7 +1670,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-clamav configure 0.94.2
+clamav configure devel
generated by GNU Autoconf 2.61
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1684,7 +1684,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by clamav $as_me 0.94.2, which was
+It was created by clamav $as_me devel, which was
generated by GNU Autoconf 2.61. Invocation command line was
$ $0 $@
@@ -2694,7 +2694,7 @@ fi
# Define the identity of the package.
PACKAGE='clamav'
- VERSION='0.94.2'
+ VERSION='devel'
# Some tools Automake needs.
@@ -2838,7 +2838,7 @@ cat >>confdefs.h <<\_ACEOF
_ACEOF
-VERSION="0.94.2"
+VERSION="0.95rc1"
cat >>confdefs.h <<_ACEOF
#define VERSION "$VERSION"
@@ -16761,11 +16761,6 @@ fi
LIBCHECK_PREFIX="$basedir"
additional_includedir="$basedir/include"
;;
- */lib | */lib/)
- basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/lib/"'*$,,'`
- LIBGMP_PREFIX="$basedir"
- additional_includedir="$basedir/include"
- ;;
esac
if test "X$additional_includedir" != "X"; then
if test "X$additional_includedir" != "X/usr/include"; then
@@ -25164,7 +25159,7 @@ exec 6>&1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by clamav $as_me 0.94.2, which was
+This file was extended by clamav $as_me devel, which was
generated by GNU Autoconf 2.61. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -25217,7 +25212,7 @@ Report bugs to <bug-autoconf at gnu.org>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
-clamav config.status 0.94.2
+clamav config.status devel
configured by $0, generated by GNU Autoconf 2.61,
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
diff --git a/configure.in b/configure.in
index 99131c3..bca7bc5 100644
--- a/configure.in
+++ b/configure.in
@@ -20,7 +20,7 @@ dnl MA 02110-1301, USA.
AC_PREREQ([2.59])
dnl For a release change [devel] to the real version [0.xy]
dnl also change VERSION below
-AC_INIT([clamav], [0.94.2], [http://bugs.clamav.net/])
+AC_INIT([clamav], [devel], [http://bugs.clamav.net/])
dnl put configure auxiliary into config
AC_CONFIG_AUX_DIR([config])
@@ -39,8 +39,7 @@ dnl the date in the version
AC_DEFINE([PACKAGE], PACKAGE_NAME, [Name of package])
dnl change this on a release
-VERSION="0.94.2"
-dnl VERSION="devel-`date +%Y%m%d`"
+VERSION="0.95rc1"
AC_DEFINE_UNQUOTED([VERSION],"$VERSION",[Version number of package])
LC_CURRENT=6
diff --git a/contrib/clamdwatch/clamdwatch.tar.gz b/contrib/clamdwatch/clamdwatch.tar.gz
deleted file mode 100644
index b327726..0000000
Binary files a/contrib/clamdwatch/clamdwatch.tar.gz and /dev/null differ
diff --git a/contrib/cleanup-partial.pl b/contrib/cleanup-partial.pl
deleted file mode 100755
index 1346f71..0000000
--- a/contrib/cleanup-partial.pl
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/perl
-
-# ---- Settings ----
-# TemporaryDirectory in clamd.conf
-my $TMPDIR='/tmp';
-# How long to wait for next part of RFC1341 message (seconds)
-my $cleanup_interval=3600;
-
-# ---- End of Settings ----
-
-my $partial_dir = "$TMPDIR/clamav-partial";
-# if there is no partial directory, nothing to clean up
-opendir(DIR, $partial_dir) || exit 0;
-
-my $cleanup_threshold = time - $cleanup_interval;
-while(my $file = readdir(DIR)) {
- next unless $file =~ m/^clamav-partial-([0-9]+)_[0-9a-f]{32}-[0-9]+$/;
- my $filetime = $1;
- unlink "$partial_dir/$file" unless $filetime > $cleanup_threshold;
-}
-closedir DIR;
diff --git a/contrib/init/FreeBSD5.2/clamav b/contrib/init/FreeBSD5.2/clamav
deleted file mode 100755
index d138678..0000000
--- a/contrib/init/FreeBSD5.2/clamav
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/bin/sh
-
-# Copyright (C) 2004 Nigel Horne <njh at bandsman.co.uk>
-#
-# 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., 51 Franklin Street, Fifth Floor, Boston,
-# MA 02110-1301, USA.
-#
-# Install into /usr/local/etc/rc.d as /usr/local/etc/rc.d/clamav.sh
-# chmod 755 /usr/local/etc/rc.d/clamav.sh
-#
-# Add lines such as this to /etc/rc.conf:
-# clamd_enable="YES"
-# clamav_milter_enable="YES"
-# clamav_milter_flags="--max-children=2 --dont-wait --timeout=0 -P local:/var/run/clamav/clamav.sock --pidfile=/var/run/clamav/clamav-milter.pid --quarantine-dir=/var/run/clamav/quarantine"
-#
-# Tested with FreeBSD 5.2 and 5.3
-
-# PROVIDE: clamav
-# REQUIRE: NETWORKING
-# KEYWORD: FreeBSD
-
-. /etc/rc.subr
-
-# Don't allow files larger than 20M to be created, to limit DoS
-# Needs to be large enough to extract the signature files
-ulimit -f 20000
-
-name="clamd"
-rcvar="`set_rcvar`"
-command="/usr/local/sbin/${name}"
-
-load_rc_config $name
-run_rc_command "$1"
-
-name="clamav_milter"
-rcvar="`set_rcvar`"
-command="/usr/local/sbin/clamav-milter"
-
-load_rc_config $name
-run_rc_command "$1"
diff --git a/contrib/init/NetBSD2.0/clamav b/contrib/init/NetBSD2.0/clamav
deleted file mode 100755
index a933458..0000000
--- a/contrib/init/NetBSD2.0/clamav
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/bin/sh
-
-# Copyright (C) 2004 Nigel Horne <njh at bandsman.co.uk>
-#
-# 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., 51 Franklin Street, Fifth Floor, Boston,
-# MA 02110-1301, USA.
-#
-# Install into /etc/rc.d as /etc/rc.d/clamav
-# chmod 755 /etc/rc.d/clamav
-#
-# Add lines such as this to /etc/rc.conf:
-# clamd="YES"
-# clamav_milter="YES"
-# clamav_milter_flags="--max-children=2 --dont-wait --timeout=0 -P local:/var/run/clamav/clamav.sock --pidfile=/var/run/clamav/clamav-milter.pid --quarantine-dir=/var/run/clamav/quarantine"
-#
-# Tested with NetBSD 2.0
-
-# PROVIDE: clamav
-# REQUIRE: NETWORKING
-# KEYWORD: NetBSD
-
-. /etc/rc.subr
-
-# Don't allow files larger than 20M to be created, to limit DoS
-# Needs to be large enough to extract the signature files
-ulimit -f 20000
-
-name="clamd"
-command="/usr/local/sbin/${name}"
-
-load_rc_config $name
-run_rc_command "$1"
-
-name="clamav_milter"
-command="/usr/local/sbin/clamav-milter"
-
-load_rc_config $name
-if [ $clamav_milter = YES ]; then
- run_rc_command "$1"
-fi
diff --git a/contrib/init/OpenBSD3.6/README b/contrib/init/OpenBSD3.6/README
deleted file mode 100644
index 617a520..0000000
--- a/contrib/init/OpenBSD3.6/README
+++ /dev/null
@@ -1,9 +0,0 @@
-Edit /etc/rc.local adding the following before the "echo '.'" line, you
-should also call freshclam.
-
-if [ -x /usr/local/sbin/clamd ]; then
- echo -n ' clamd'
- # Don't allow files larger than 20M to be created, to limit DoS
- # Needs to be large enough to extract the signature files
- (ulimit -f 20000 && /usr/local/sbin/clamd)
-fi
diff --git a/contrib/init/RedHat/clamav-milter b/contrib/init/RedHat/clamav-milter
deleted file mode 100755
index 18bf5bf..0000000
--- a/contrib/init/RedHat/clamav-milter
+++ /dev/null
@@ -1,104 +0,0 @@
-#!/bin/sh
-#
-# clamav-milter This script starts and stops the clamav-milter daemon
-#
-# chkconfig: 2345 79 40
-#
-# description: clamav-milter is a daemon which hooks into sendmail and routes \
-# email messages for virus scanning with ClamAV
-# processname: clamav-milter
-# pidfile: /var/lock/subsys/clamav-milter
-
-# Source function library.
-. /etc/rc.d/init.d/functions
-
-# Source networking configuration.
-. /etc/sysconfig/network
-
-# Local clamav-milter config
-CLAMAV_FLAGS=
-test -f /etc/sysconfig/clamav-milter && . /etc/sysconfig/clamav-milter
-
-# Check that networking is up.
-[ ${NETWORKING} = "no" ] && exit 0
-
-[ -x /usr/local/sbin/clamav-milter ] || exit 0
-PATH=$PATH:/usr/bin:/usr/local/sbin:/usr/local/bin
-
-RETVAL=0
-
-# Clamav-milter must have write access to the pid file, /var/run is not suitable
-default_pidfile=
-[ -d /var/run/clamav-milter ] && default_pidfile=/var/run/clamav-milter/clamav-milter.pid
-[ -d /var/clamav ] && default_pidfile=/var/clamav/clamav-milter.pid
-pidfile=${PIDFILE:-$default_pidfile}
-
-lockfile=/var/lock/subsys/clamav-milter
-
-start() {
- echo -n "Starting clamav-milter: "
- # Don't allow files larger than 25M to be created, to limit DoS
- # Needs to be large enough to extract the signature files
- ulimit -f 25600
- if [ ! -z $pidfile ]; then
- CLAMAV_PID=--pidfile=${pidfile}
- PID=`pidofproc -p ${pidfile} clamav-milter`
- else
- CLAMAV_PID=
- PID=`pidofproc clamav-milter`
- fi
- [ -n "$PID" ] && echo " already running!" && return 1
- LANG= daemon clamav-milter $CLAMAV_PID ${CLAMAV_FLAGS}
- RETVAL=$?
- [ ! -z $pidfile -a -f $pidfile ] && sed -i -e 's/-//' $pidfile
- echo
- test $RETVAL -eq 0 && touch ${lockfile}
- return $RETVAL
-}
-
-stop() {
- echo -n "Shutting down clamav-milter: "
- if [ ! -z $pidfile ]; then
- killproc -p ${pidfile} clamav-milter
- else
- killproc clamav-milter
- fi
- RETVAL=$?
- echo
- test $RETVAL -eq 0 && rm -f ${lockfile} ${pidfile}
-}
-
-restart() {
- stop
- start
-}
-
-# See how we were called.
-case "$1" in
- start)
- # Start daemon.
- start
- ;;
- stop)
- # Stop daemon.
- stop
- ;;
- restart|reload)
- restart
- ;;
- condrestart)
- test -f ${lockfile} && $0 restart || :
- ;;
- status)
- if [ ! -z $pidfile ]; then
- status -p ${pidfile} clamav-milter
- else
- status clamav-milter
- fi
- ;;
- *)
- echo "Usage: $0 {start|stop|reload|restart|condrestart|status}"
- exit 1
-esac
-
-exit $?
diff --git a/contrib/init/RedHat/clamd b/contrib/init/RedHat/clamd
deleted file mode 100755
index 3e9a214..0000000
--- a/contrib/init/RedHat/clamd
+++ /dev/null
@@ -1,89 +0,0 @@
-#! /bin/bash
-#
-# crond Start/Stop the clam antivirus daemon.
-#
-# chkconfig: 2345 70 41
-# description: clamd is a standard Linux/UNIX program that scans for Viruses.
-# processname: clamd
-# config: /usr/local/etc/clamd.conf
-# pidfile: /var/lock/subsys/clamd
-
-# Source function library.
-. /etc/init.d/functions
-
-RETVAL=0
-
-# See how we were called.
-
-prog="clamd"
-progdir="/usr/local/sbin"
-
-# Source configuration
-if [ -f /etc/sysconfig/$prog ] ; then
- . /etc/sysconfig/$prog
-fi
-
-start() {
- echo -n $"Starting $prog: "
- # Don't allow files larger than 20M to be created, to limit DoS
- # Needs to be large enough to extract the signature files
- ulimit -f 20000
- LANG= daemon $progdir/$prog
- RETVAL=$?
- echo
- [ $RETVAL -eq 0 ] && touch /var/lock/subsys/clamd
- return $RETVAL
-}
-
-stop() {
- echo -n $"Stopping $prog: "
- # Would be better to send QUIT first, then killproc if that fails
- killproc $prog
- RETVAL=$?
- echo
- [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/clamd
- return $RETVAL
-}
-
-rhstatus() {
- status clamd
-}
-
-restart() {
- stop
- start
-}
-
-reload() {
- echo -n $"Reloading clam daemon configuration: "
- killproc clamd -HUP
- retval=$?
- echo
- return $RETVAL
-}
-
-case "$1" in
- start)
- start
- ;;
- stop)
- stop
- ;;
- restart)
- restart
- ;;
- reload)
- reload
- ;;
- status)
- rhstatus
- ;;
- condrestart)
- [ -f /var/lock/subsys/clamd ] && restart || :
- ;;
- *)
- echo $"Usage: $0 {start|stop|status|reload|restart|condrestart}"
- exit 1
-esac
-
-exit $?
diff --git a/contrib/init/Solaris10/clamav-milter b/contrib/init/Solaris10/clamav-milter
deleted file mode 100644
index 74c8380..0000000
--- a/contrib/init/Solaris10/clamav-milter
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/bin/sh
-
-CONF_FILE=/usr/local/etc/clamd.conf
-RUNDIR=/var/run/clamav
-CLAMAV_MILTER_FLAGS="-l --max-children=2 local:$RUNDIR/clmilter.sock"
-
-if [ ! -f $CONF_FILE ]; then
- exit 0
-fi
-
-if [ ! -d $RUNDIR ]; then
- /usr/bin/mkdir -p -m 700 $RUNDIR
- USER=`fgrep User ${CONF_FILE} | awk '{ print $2 }'`
- if [ x$USER != x ]; then
- chown $USER $RUNDIR
- fi
-fi
-
-case "$1" in
- start)
- /usr/local/sbin/clamav-milter $CLAMAV_MILTER_FLAGS
- ;;
- stop)
- kill `ps -ef | awk '$NF ~ /clamav-milter/ { print $2 }'` > /dev/null 2>&1
- ;;
- *)
- echo "usage: $0 {start|stop}"
-esac
diff --git a/contrib/init/Solaris10/clamd b/contrib/init/Solaris10/clamd
deleted file mode 100755
index 9afa9f2..0000000
--- a/contrib/init/Solaris10/clamd
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/sh
-
-CONF_FILE=/usr/local/etc/clamd.conf
-
-if [ ! -f $CONF_FILE ]; then
- exit 0
-fi
-
-case "$1" in
- start)
- /usr/local/sbin/clamd
- ;;
- stop)
- kill `ps -ef | awk '$NF ~ /clamd/ { print $2 }'` > /dev/null 2>&1
- ;;
- *)
- echo "usage: $0 {start|stop}"
-esac
diff --git a/contrib/init/SuSE/clamd b/contrib/init/SuSE/clamd
deleted file mode 100755
index 2e483ff..0000000
--- a/contrib/init/SuSE/clamd
+++ /dev/null
@@ -1,101 +0,0 @@
-#! /bin/sh
-# v1.2 05-2004, martin fuxa, yeti at email.cz
-#
-### BEGIN INIT INFO
-# Provides: clamd
-# Required-Start:
-# Required-Stop:
-# Default-Start: 2 3 5
-# Default-Stop: 0 1 2 6
-# Description: Control clamav daemon.
-### END INIT INFO
-#
-### HISTORY
-# 2004-05-27 ADD - FreshClam code
-
-# Variables
-PID="/var/run/clamd.pid"
-SBIN="/usr/local/sbin/clamd"
-CONF="/etc/clamav.conf"
-WHAT="Clam AntiVirus"
-
-# START_FRESHCLAM value: 1=true, 0 false
-START_FRESHCLAM=1
-FRESHCLAM_SBIN="/usr/local/bin/freshclam"
-FRESHCLAM_CONF="/etc/freshclam.conf"
-FRESHCLAM_WHAT="FreshClam"
-
-# Source SuSE config
-. /etc/rc.status
-
-test -x $SBIN || exit 5
-test -e $CONF || exit 5
-
-if [ $START_FRESHCLAM = 1 ]
-then
- test -x $FRESHCLAM_SBIN || exit 5
- test -e $FRESHCLAM_CONF || exit 5
-fi
-
-# First reset status of this service
-rc_reset
-
-# Process request
-case "$1" in
- start)
- if [ $START_FRESHCLAM = 1 ]
- then
- echo -n "Starting ${FRESHCLAM_WHAT} ${FRESHCLAM_CONF}"
- startproc $FRESHCLAM_SBIN --daemon --config-file=${FRESHCLAM_CONF}
- rc_status -v
- fi
- echo -n "Starting ${WHAT} ${CONF} "
- ## Start daemon with startproc(8). If this fails
- ## the echo return value is set appropriate.
- startproc $SBIN $CONF
- # Remember status and be verbose
- rc_status -v
- ## start freshclam
-
- ;;
- stop)
- echo -n "Shutting down ${WHAT}"
- ## Stop daemon with killproc(8) and if this fails
- ## set echo the echo return value.
- killproc -TERM $SBIN
- # Remember status and be verbose
- rc_status -v
- if [ $START_FRESHCLAM = 1 ]
- then
- echo -n "Shutting down ${FRESHCLAM_WHAT}"
- killproc -TERM $FRESHCLAM_SBIN
- rc_status -v
- fi
- ;;
- restart)
- ## Stop the service and regardless of whether it was
- ## running or not, start it again.
- $0 stop
- $0 start
- # Remember status and be quiet
- rc_status
- ;;
- status)
- echo -n "Checking for ${WHAT} "
- checkproc $SBIN
- rc_status -v
- if [ $START_FRESHCLAM = 1 ]
- then
- echo -n "Checking for ${FRESHCLAM_WHAT} "
- checkproc $FRESHCLAM_SBIN
- rc_status -v
- fi
- ;;
-
- *)
- echo "Usage: $0 {start|stop|status|restart}"
- exit 1
- ;;
-esac
-rc_exit
-### END
diff --git a/contrib/make-clamav-milter-conf.pl b/contrib/make-clamav-milter-conf.pl
deleted file mode 100644
index 9d6e34c..0000000
--- a/contrib/make-clamav-milter-conf.pl
+++ /dev/null
@@ -1,429 +0,0 @@
-#!/usr/bin/perl
-
-use strict;
-use warnings;
-
-use Getopt::Long qw(:config gnu_getopt);
-
-sub wwarn {
- my $w = shift;
- warn "WARNING: $w\n";
-}
-
-sub tosconf {
- my ($cfg, $v) = @_;
- if($v) {
- my $sep = $v=~/ / ? '"' : '';
- $v = "\n$cfg $sep$v$sep";
- }
- return $v;
-}
-
-my $notify = 0;
-my $black = 0;
-my $report = 0;
-my $debug = 0;
-my $sign = 0;
-my $broad = 0;
-my $forge = 0;
-my $sanity = 1;
-my $blackhole = 0;
-my $quarantine = 0;
-my $rate = 0;
-my $monitor = 0;
-my $oninfected = 'Reject';
-my $onfail = 'Defer';
-my @localnets = ();
-my $whitelist = '';
-my $config = '';
-my $chroot = '';
-my $pidfile = '';
-my $addheader = 1;
-my $tcpclamds = '';
-my $localclamd;
-
-GetOptions (
- "from|a:s" => \$notify,
- "bounce|b" => \$notify,
- "headers|H" => \$notify,
- "postmaster|p=s" => \$notify,
- "postmaster-only|P" => \$notify,
- "template-file|t=s" => \$notify,
- "template-headers|1=s" => \$notify,
- "quiet|q" => sub { $notify = 0 },
- "dont-blacklist|K=s" => \$black,
- "blacklist-time|k=i" => \$black,
- "report-phish|r=s" => \$report,
- "report-phish-false-positives|R=s" => \$report,
- "debug-level|x=i" => \$debug,
- "debug|D" => \$debug,
- "sign|S" => \$sign,
- "signature-file|F=s" => \$sign,
- "broadcast|B=s" => \$broad,
- "detect-forged-local-address|L" => \$forge,
- "dont-sanitise|z" => sub { $sanity = 0 },
- "black-hole-mode|2" => \$blackhole,
- "quarantine|Q=s" => \$quarantine,
- "quarantine-dir|U" => \$quarantine,
- "max-children|m=i" => \$rate,
- "dont-wait|w" => \$rate,
- "timeout|T=i" => \$rate,
- "freshclam-monitor|M=i" => \$monitor,
- "external|e" => sub { },
- "no-check-cf" => sub { },
- "sendmail-cf|0=s" => sub { },
- "advisory|A" => sub { $oninfected='Accept'; },
- "noreject|N" => sub { $oninfected='Blackhole'; },
- "dont-scan-on-error|d" => sub { $onfail = 'Accept'; },
- "ignore|I=s" => \@localnets,
- "local|l" => sub { @localnets = (); },
- "force-scan|f" => sub { @localnets = (); },
- "whitelist-file|W=s" => \$whitelist,
- "config-file|c=s" => \$config,
- "chroot|C=s" => \$chroot,
- "pidfile|i=s" => \$pidfile,
- "noxheader|n" => sub { $addheader = 0},
- "outgoing|o" => sub { push(@localnets, 'localhost'); },
- "server|s=s" => \$tcpclamds,
-) or die "huh?!";
-
-my %clamds = ();
-foreach (split(/:/, $tcpclamds)) {
- $clamds{"tcp:$_:3310"}++;
-}
-
-my $user = '';
-my $supgrp = '';
-my $syslog = '';
-my $facility = '';
-my $tempdir = '';
-my $maxsize = '';
-
-if ($config) {
- my $port = 0;
- my $ip = '';
- my $lsock = '';
- open CFG, "<$chroot/$config" or die "failed to open clamd config file $config";
- while (<CFG>) {
- chomp;
- $port = $1 if /^TCPSocket\s+(.*)$/;
- $ip = $1 if /^TCPAddr\s+(.*)$/;
- $lsock = $1 if /^LocalSocket\s+(.*)$/;
- $user = $1 if /^User\s+(.*)$/;
- $supgrp = $1 if /^AllowSupplementaryGroups\s+(.*)$/;
- $syslog = $1 if /^LogSyslog\s+(.*)$/;
- $facility = $1 if /^LogFacility\s+(.*)$/;
- $tempdir = $1 if /^TemporaryDirectory\s+(.*)$/;
- $maxsize = $1 if /^MaxFileSize\s+(.*)$/;
- }
- close(CFG);
- if ($lsock) {
- $clamds{"unix:$lsock"}++;
- } elsif ($port) {
- if($ip) {
- $clamds{"tcp:$ip:$port"}++;
- } else {
- $clamds{"tcp:localhost:$port"}++;
- }
- }
-}
-
-die "FAIL: No socket provided" unless $ARGV[0];
-die "FAIL: Unable to determine clamd socket\n" unless scalar keys %clamds;
-
-wwarn "Notifications and bounces are no longer supported.
-As a result the following command line options cannot be converted into new config options:
- --from (-a)
- --bounce (-b)
- --headers (-H)
- --postmaster (-p)
- --postmaster-only (-P)
- --template-file (-t)
- --template-headers (-1)
-" if $notify;
-
-wwarn "Temporary blacklisting of ip addresses is no longer supported.
-As a result the following command line options cannot be converted into new config options:
- --dont-blacklist (-K)
- --blacklist-time (-k)
-" if $black;
-
-wwarn "Phising reports are no longer supported.
-As a result the following command line options cannot be converted into new config options:
- --report-phish (-r)
- --report-phish-false-positives (-R)
-" if $report;
-
-wwarn "The options --debug (-D) and --debug-level (-x) are no longer supported.
-Please set LogVerbose to yes instead
-" if $debug;
-
-wwarn "Message scan signatures are no longer supported.
-As a result the following command line options cannot be converted into new config options:
- --sign (-S)
- --signature-file (-F)
-" if $sign;
-
-wwarn "Broadcasting is no longer supported\n" if $broad;
-
-wwarn "Forgery detection is no longer supported\n" if $forge;
-
-wwarn "Please be aware that email addresses are no longer checked for weird characters like '|' and ';'\n" if $sanity;
-
-wwarn "Blackhole mode is no longer available\nIf you have a lot users aliased to /dev/null you may want to whitelist them instead\n" if $blackhole;
-
-wwarn "Quarantine now achieved via native milter support\nPlease read more about it in the example config file\n" if $quarantine;
-
-wwarn "Rate limiting in the milter is no longer supported.
-As a result the following command line options cannot be converted into new config options:
- --max-children (-m)
- --dont-wait (-w)
- --timeout (-T)
-Please make use of the native Sendmail / Postfix rate limiting facilities
-" if $rate;
-
-wwarn "The option --freshclam-monitor (-M) only made sense in internal mode\nPlease configure freshclam to notify clamd about updates instead\n" if $monitor;
-
-wwarn "Your whitelist file path has been preserved, however please be aware that its syntax is changed\nInstead of a full email address you are now allowed to use regexes. See the example clamav-milter.conf file for more info.\n" if $whitelist;
-
-wwarn "Here is the auto generated config file. Please review:\n";
-
-my $mysock = tosconf('MilterSocket', $ARGV[0]);
-$chroot = tosconf('Chroot', $chroot);
-$pidfile = tosconf('PidFile', $pidfile);
-$oninfected = tosconf('OnInfected', $oninfected);
-$onfail = tosconf('OnFail', $onfail);
-$whitelist = tosconf('Whitelist', $whitelist);
-$addheader = $addheader ? "\nAddHeader Yes" : '';
-$user = tosconf('User', $user);
-$supgrp = $supgrp ? "\nAllowSupplementaryGroups Yes" : '';
-if ($syslog =~ /yes/i) {
- $syslog = "LogSyslog yes";
- $facility = tosconf('LogFacility', $facility);
-} else {
- $syslog = '';
- $facility = '';
-}
-$tempdir = tosconf('TemporaryDirectory', $tempdir);
-$maxsize = tosconf('MaxFileSize', $maxsize);
-
-print <<BLOCK1;
-##
-## Example config file for clamav-milter
-## (automatically generated by make-clamav-milter-conf.pl)
-##
-
-# Comment or remove the line below.
-Example
-
-
-##
-## Main options
-##
-
-# Define the interface through which we communicate with sendmail
-# This option is mandatory! Possible formats are:
-# [[unix|local]:]/path/to/file - to specify a unix domain socket
-# inet:port@[hostname|ip-address] - to specify an ipv4 socket
-# inet6:port@[hostname|ip-address] - to specify an ipv6 socket
-#
-# Default: no default
-#MilterSocket /tmp/clamav-milter.socket
-#MilterSocket inet:7357$mysock
-
-# Remove stale socket after unclean shutdown.
-#
-# Default: yes
-#FixStaleSocket yes
-
-# Run as another user (clamav-milter must be started by root for this option to work)
-#
-# Default: unset (don't drop privileges)
-#User clamav$user
-
-# Initialize supplementary group access (clamd must be started by root).
-#
-# Default: no
-#AllowSupplementaryGroups no$supgrp
-
-# Waiting for data from clamd will timeout after this time (seconds).
-# Value of 0 disables the timeout.
-#
-# Default: 120
-#ReadTimeout 300
-
-# Don't fork into background.
-#
-# Default: no
-#Foreground yes
-
-# Chroot to the specified directory.
-# Chrooting is performed just after reading the config file and before dropping privileges.
-#
-# Default: unset (don't chroot)
-#Chroot /newroot$chroot
-
-# This option allows you to save a process identifier of the listening
-# daemon (main thread).
-#
-# Default: disabled
-#PidFile /var/run/clamd.pid$pidfile
-
-# Optional path to the global temporary directory.
-# Default: system specific (usually /tmp or /var/tmp).
-#
-#TemporaryDirectory /var/tmp$tempdir
-
-##
-## Clamd options
-##
-
-# Define the clamd socket to connect to for scanning.
-# If not set (the default), clamav-milter uses internal mode.
-# This option is mandatory! Syntax:
-# ClamdSocket unix:path
-# ClamdSocket tcp:host:port
-# The first syntax specifies a local unix socket (needs an bsolute path) e.g.:
-# ClamdSocket unix:/var/run/clamd/clamd.socket
-# The second syntax specifies a tcp local or remote tcp socket: the
-# host can be a hostname or an ip address; the ":port" field is only required
-# for IPv6 addresses, otherwise it defaults to 3310
-# ClamdSocket tcp:192.168.0.1
-#
-# This option can be repeated several times with different sockets or even
-# with the same socket: clamd servers will be selected in a round-robin fashion.
-#
-# Default: no default
-#ClamdSocket tcp:scanner.mydomain:7357
-BLOCK1
-
-print "ClamdSocket \"$_\"\n" foreach (keys %clamds);
-print <<BLOCK2;
-
-
-##
-## Exclusions
-##
-
-# Messages originating from these hosts/networks will not be scanned
-# This option takes a host(name)/mask pair in CIRD notation and can be
-# repeated several times. If "/mask" is omitted, a host is assumed.
-# To specify a locally orignated, non-smtp, email use the keyword "local"
-#
-# Default: unset (scan everything regardless of the origin)
-#LocalNet local
-#LocalNet 192.168.0.0/24
-#LocalNet 1111:2222:3333::/48
-
-# This option specifies a file which contains a list of POSIX regular
-# expressions. Addresses (sent to or from - see below) matching these regexes
-# will not be scanned. Optionally each line can start with the string "From:"
-# or "To:" (note: no whitespace after the colon) indicating if it is,
-# respectively, the sender or recipient that is to be whitelisted.
-# If the field is missing, "To:" is assumed.
-# Lines starting with #, : or ! are ignored.
-#
-# Default unset (no exclusion applied)
-#Whitelist /etc/whitelisted_addresses$whitelist
-
-
-##
-## Actions
-##
-
-# The following group of options controls the delievery process under
-# different circumstances.
-# The following actions are available:
-# - Accept
-# The message is accepted for delievery
-# - Reject
-# Immediately refuse delievery (a 5xx error is returned to the peer)
-# - Defer
-# Return a temporary failure message (4xx) to the peer
-# - Blackhole (not available for OnFail)
-# Like accept but the message is sent to oblivion
-# - Quarantine (not available for OnFail)
-# Like accept but message is quarantined instead of being deilievered
-# In sendmail the quarantine queue can be examined via mailq -qQ
-# For Postfix this causes the message to be accepted but placed on hold
-#
-# Action to be performed on clean messages (mostly useful for testing)
-# Default Accept
-#OnClean Accept
-
-# Action to be performed on infected messages
-# Default: Quarantine
-#OnInfected Quarantine$oninfected
-
-# Action to be performed on error conditions (this includes failure to
-# allocate data structures, no scanners available, network timeouts,
-# unknown scanner replies and the like)
-# Default Defer
-#OnFail Defer$onfail
-
-# If this option is set to Yes, an "X-Virus-Scanned" and an "X-Virus-Status"
-# headers will be attached to each processed message, possibly replacing
-# existing headers.
-# Default: No
-#AddHeader Yes$addheader
-
-
-##
-## Logging options
-##
-
-# Uncomment this option to enable logging.
-# LogFile must be writable for the user running daemon.
-# A full path is required.
-#
-# Default: disabled
-#LogFile /tmp/clamav-milter.log
-
-# By default the log file is locked for writing - the lock protects against
-# running clamav-milter multiple times.
-# This option disables log file locking.
-#
-# Default: no
-#LogFileUnlock yes
-
-# Maximum size of the log file.
-# Value of 0 disables the limit.
-# You may use 'M' or 'm' for megabytes (1M = 1m = 1048576 bytes)
-# and 'K' or 'k' for kilobytes (1K = 1k = 1024 bytes). To specify the size
-# in bytes just don't use modifiers.
-#
-# Default: 1M
-#LogFileMaxSize 2M
-
-# Log time with each message.
-#
-# Default: no
-#LogTime yes
-
-# Use system logger (can work together with LogFile).
-#
-# Default: no
-#LogSyslog yes$syslog
-
-# Specify the type of syslog messages - please refer to 'man syslog'
-# for facility names.
-#
-# Default: LOG_LOCAL6
-#LogFacility LOG_MAIL$facility
-
-# Enable verbose logging.
-#
-# Default: no
-#LogVerbose yes
-
-
-##
-## Limits
-##
-
-# Messages larger than this value won't be scanned.
-# Default: 25M
-#MaxFileSize 150M$maxsize
-BLOCK2
-
-
diff --git a/contrib/mpoolparse/mpoolparse.pl b/contrib/mpoolparse/mpoolparse.pl
deleted file mode 100644
index 70b1ad8..0000000
--- a/contrib/mpoolparse/mpoolparse.pl
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/perl
-
-use strict;
-use warnings;
-
-my %frags = ();
-
-while (<>) {
- chomp;
- next unless /^LibClamAV Warning: [mc]alloc .* size (\d+) .*$/;
- $frags{$1}++;
-}
-
-foreach (sort {$a<=>$b} (keys(%frags))) {
- print "$_, /* ($frags{$_}) */\n";
-}
-
diff --git a/contrib/old-clamav-milter/INSTALL b/contrib/old-clamav-milter/INSTALL
deleted file mode 100644
index 0f3ead0..0000000
--- a/contrib/old-clamav-milter/INSTALL
+++ /dev/null
@@ -1,439 +0,0 @@
-1. BUILD INSTRUCTIONS
-
-A makefile was supplied with this which should have built the program. If it
-fails please let us know, and here are some hints for building on different
-platforms. You will need to set --enable-milter when running configure for
-the automatic build to work.
-
-Tested OK on Linux/x86 with gcc3.2.
- cc -O3 -pedantic -Wuninitialized -Wall -pipe -mcpu=pentium -march=pentium -fomit-frame-pointer -ffast-math -finline-functions -funroll-loops clamav-milter.c -pthread -lmilter ../libclamav/.libs/libclamav.a ../clamd/cfgfile.o ../clamd/others.o
-
-Compiles OK on Linux/x86 with tcc 0.9.16, but fails to link errors with 'atexit'
- tcc -g -b -lmilter -lpthread clamav-milter.c...
-
-Fails to compile on Linux/x86 with icc6.0 (complains about stdio.h...)
- icc -O3 -tpp7 -xiMKW -ipo -parallel -i_dynamic -w2 clamav-milter.c...
-Fails to build on Linux/x86 with icc7.1 with -ipo (fails on libclamav.a - keeps saying run ranlib). Otherwise it builds and runs OK.
- icc -O2 -tpp7 -xiMKW -parallel -i_dynamic -w2 -march=pentium4 -mcpu=pentium4 clamav-milter.c...
-
-Tested with Electric Fence 2.2.2, and the bounds checking C compiler from
- http://sourceforge.net/projects/boundschecking/
-
-Compiles OK on Linux/ppc (YDL2.3) with gcc2.95.4. Needs -lsmutil to link.
- cc -O3 -pedantic -Wuninitialized -Wall -pipe -fomit-frame-pointer -ffast-math -finline-functions -funroll-loop -pthread -lmilter ../libclamav/.libs/libclamav.a ../clamd/cfgfile.o ../clamd/others.o -lsmutil
-I haven't tested it further on this platform yet.
-YDL3.0 should compile out of the box
-
-Linux/sparc (Gentoo 2004.2) comes with a sendmail that doesn't support MILTER,
-so *before* running "configure --enable-milter", download from
-http://www.sendmail.org/ftp, then:
- cd .../sendmail-source-directory
- sh Build
- make install
- cd libmilter
- make install
-
-Sendmail on MacOS/X (10.1) is provided without a development package so this
-can't be run "out of the box"
-
-Solaris 8 doesn't have milter support so clamav-milter won't work unless you
-rebuild sendmail from source.
-
-FreeBSD4.7 use /usr/local/bin/gcc30. GCC3.0 is an optional extra on
-FreeBSD. It comes with getopt.h which is handy. To link you need
--lgnugetopt
- gcc30 -O3 -DCONFDIR=\"/usr/local/etc\" -I. -I.. -I../clamd -I../libclamav -pedantic -Wuninitialized -Wall -pipe -mcpu=pentium -march=pentium -fomit-frame-pointer -ffast-math -finline-functions -funroll-loops clamav-milter.c -pthread -lmilter ../libclamav/.libs/libclamav.a ../clamd/cfgfile.o ../clamd/others.o -lgnugetopt
-
-FreeBSD4.8: compiles out of the box with either gcc2.95 or gcc3
-
-NetBSD2.0: compiles out of the box
-
-OpenBSD3.4: the supplied sendmail does not come with Milter support.
-Do this *before* running configure (thanks for Per-Olov Sjöhol
-<peo_s at incedo.org> for these instructions).
-
- echo WANT_LIBMILTER=1 > /etc/mk.conf
- cd /usr/src/gnu/usr.sbin/sendmail
- make depend
- make
- make install
- kill -HUP `sed q /var/run/sendmail.pid`
-
-Then do this to make the milter headers available to clamav...
-(the libmilter.a file is already in the right place after the sendmail
-recompiles above)
-
- cd /usr/include
- ln -s ../src/gnu/usr.sbin/sendmail/include/libmilter libmilter
-
-Solaris 9 and FreeBSD5 have milter support in the supplied sendmail, but
-doesn't include libmilter so you can't develop milter applications on it.
-Go to sendmail.org, download the latest sendmail, cd to libmilter and
-"make install" there.
-
-Needs -lresolv on Solaris, for res_close().
-
-If, when building clamav-milter, you see the error
- "undefined reference to smfi_opensocket",
-it means that your sendmail installation is broken. More specifically it means
-that your installed version of libmilter does not agree with your installed
-version of Sendmail. Naturally they must be the same. Check to see if you have
-more than one mfapi.h on your system; if you installed sendmail from source,
-did you remember to install libmilter at the same time? You can ensure that
-your Sendmail is correctly installed if you follow these instructions:
- cd .../sendmail-source-directory
- sh Build
- make install
- cd libmilter
- make install
-
-2. INSTALLATION
-
-Install into /usr/local/sbin/clamav-milter.
-
-Ensure that your sendmail supports milters by running
- /usr/lib/sendmail -d0 < /dev/null | fgrep MILTER
-or
- /usr/sbin/sendmail -d0 < /dev/null | fgrep MILTER
-
-You should see something like:
- MATCHGECOS MILTER MIME7TO8 MIME8TO7 NAMED_BIND NETINET NETINET6
-It doesn't matter exactly what you see, as long as the word MILTER is printed.
-
-If you see no output you MUST upgrade your sendmail.
-
-See http://www.nmt.edu/~wcolburn/sendmail-8.12.5/libmilter/docs/sample.html
-
-2.1 LINUX (RedHat, Fedora, YellowDog etc)
-
-Installations for RedHat Linux and it's derivatives such as YellowDog:
- Ensure that you have the sendmail-devel RPM installed
- Add to /etc/mail/sendmail.mc before the MAILER statement:
- INPUT_MAIL_FILTER(`clamav', `S=local:/var/run/clamav/clmilter.sock, F=, T=S:4m;R:4m;C:30s;E:10m')dnl
- define(`confINPUT_MAIL_FILTERS', `clamav')
-
- Note that the INPUT_MAIL_FILTER line must come before the
- confINPUT_MAIL_FILTERS line.
-
- Don't worry that the file /var/run/clamav/clmilter.sock doesn't exist,
- clamav-milter will create it for you. However you will need
- to create the directory /var/run/clamav (usually owned
- by user clamav, mode 700).
-
- Check entry in /usr/local/etc/clamd.conf of the form:
- LocalSocket /var/run/clamav/clamd.sock
-
- If you already have a filter (such as spamassassin-milter from
- http://savannah.nongnu.org/projects/spamass-milt) add it thus:
- INPUT_MAIL_FILTER(`clamav', `S=local:/var/run/clamav/clmilter.sock, F=, T=S:4m;R:4m')dnl
- INPUT_MAIL_FILTER(`spamassassin', `S=local:/var/run/spamass.sock, F=, T=C:15m;S:4m;R:4m;E:10m')
- define(`confINPUT_MAIL_FILTERS', `spamassassin,clamav')dnl
-
- mkdir /var/run/clamav
- chown clamav /var/run/clamav (if you use User clamav in clamd.conf)
- chmod 700 /var/run/clamav
-
- Where /var/run/spamass.sock is the location of the spamass-milt
- socket file (on some systems it is in /var/run/sendmail/spamass.sock).
-
-2.2 LINUX (Debian)
-
-Installations for Debian Linux:
- As above for RedHat, except that you need the libmilter-dev package:
- apt-get install libmilter-dev
- To use TCPwrappers you need to:
- apt-get install libwrap0-dev
-
-2.3 FreeBSD
-
-Installations for FreeBSD5 (may be true for other BSDs)
- Add to /etc/mail/freebsd.mc:
- INPUT_MAIL_FILTER(`clamav', `S=local:/var/run/clamav/clmilter.sock, F=, T=S:4m;R:4m')dnl
- define(`confINPUT_MAIL_FILTERS', `clamav')
-
- Check entry in /usr/local/etc/clamd.conf of the form:
- LocalSocket /var/run/clamav/clamd.sock
-
- If you already have a filter (such as spamassassin-milter from
- http://savannah.nongnu.org/projects/spamass-milt) add it thus:
- INPUT_MAIL_FILTER(`clamav', `S=local:/var/run/clamav/clmilter.sock, F=, T=S:4m;R:4m')dnl
- INPUT_MAIL_FILTER(`spamassassin', `S=local:/var/run/spamass.sock, F=, T=C:15m;S:4m;R:4m;E:10m')
- define(`confINPUT_MAIL_FILTERS', `spamassassin,clamav')dnl
-
- mkdir /var/run/clamav
- chown clamav /var/run/clamav (if you use User clamav in clamd.conf)
- chmod 700 /var/run/clamav
-
- Where /var/run/spamass.sock is the location of the spamass-milt
- socket file (on some systems it is in /var/run/sendmail/spamass.sock).
-
-FreeBSD5.3 sendmail comes without libmilter support. You can upgrade by
- cd /usr/ports/mail/sendmail
- make install
-
-This may overwrite your existing sendmail configuration, so ensure
-that you back up first.
-
-You should have received a script to install into /etc/rc.d as /etc/rc.d/clamav
-with this software. Add to /etc/rc.conf:
- clamd_enable="YES"
- clamav_milter_enable="YES"
- clamav_milter_flags="--max-children=2 --dont-wait --timeout=0 -P local:/var/run/clamav/clmilter.sock --pidfile=/var/run/clamav/clamav-milter.pid --quarantine-dir=/var/run/clamav/quarantine"
-
-2.4 Solaris 10
-
-Solaris 10 should install out of the box. Edit /etc/mail/cf/cf/main.mc adding
-the line:
- INPUT_MAIL_FILTER(`clamav', `S=local:/var/run/clamav/clamav-milter, F=, T=S:4m;R:4m')dnl
-Then:
- cp /etc/mail/cf/cf/main.cf /etc/mail/main.cf
- /usr/local/sbin/clamav-milter local:/var/run/clamav/clamav-milter
- mkdir /var/run/clamav
- chown clamav /var/run/clamav (if you use User clamav in clamd.conf)
- chmod 700 /var/run/clamav
-
-You should have received a script to install into /etc/init.d as
-/etc/init.d/clamav-milter. Then:
-
- chmod 755 /etc/init.d/clamav-milter
- cd /etc
- ln init.d/clamav-milter rc2.d/S90clamav-milter
- ln init.d/clamav-milter rc0.d/K90clamav-milter
- /etc/init.d/clamav-milter start
- /etc/init.d/sendmail restart
-
-2.5 OpenBSD4.1:
-
-OpenBSD4.1 should install out of the box.
-Edit <your .mc file>, or if you have none: cd into /usr/share/sendmail/cf,
-copy openbsd-proto.mc custom.mc, edit custom.mc adding:
- INPUT_MAIL_FILTER(`clamav', `S=local:/var/run/clamav/clamav-milter, F=, T=S:4m;R:4m')dnl
-Then run
- m4 ../m4/cf.m4 custom.mc >/etc/mail/localhost.cf
-and finally restart sendmail by sending it a SIGHUP
-
-2.6 General Installation Issues
-
-You may find INPUT_MAIL_FILTERS is not needed on your machine, however it
-is recommended by the Sendmail documentation and I recommend going along
-with that.
-
-If you see an unsafe socket error from sendmail, it means that the permissions
-of the /var/run/clamav directory are too open; check you have correctly run
-chown and chmod. It may also mean that clamav-milter hasn't started, run
-ps and check your logs.
-
-The above example shows clamav-milter, clamd and sendmail all on the
-same machine, however using TCP they may reside on different machines,
-indeed clamav-milter is capable of talking to multiple clamds for redundancy
-and load balancing. An alternative load balancer is PEN (http://siag.nu/pen/).
-
-I suggest putting SpamAssassin first since you're more likely to get spam
-than a virus/worm sent to you.
-
-Add to /etc/sysconfig/clamav-milter
- CLAMAV_FLAGS="local:/var/run/clamav/clmilter.sock"
-or if clamd is on a different machine
- CLAMAV_FLAGS="--server=192.168.1.9 local:/var/run/clamav/clmilter.sock"
-
-If you want clamav-milter to listen on TCP for communication with sendmail,
-for example if they are on different machines use inet:<port>.
-On machine A (running sendmail) you would have in sendmail.mc:
- INPUT_MAIL_FILTER(`clamav', `S=inet:3311 at machineb, F=T, T=S:4m;R:4m')dnl
-On machine B (running clamav-milter) you would start up clamav-milter thus:
- clamav-milter inet:3311
-
-You should have received a script to put into /etc/init.d with this software.
-
-You should always start clamd before clamav-milter.
-
-You may also think about the F= entry in sendmail.mc, since it tells sendmail
-what to do with emails if clamav-milter is not running. Setting F=T will tell
-the remote end to resend later (temporary failure), setting F=R will reject
-the email (permanent failure) and setting F= will pass the email through as
-though clamav-milter were not installed, in this case you should warn your
-users that emails are not being scanned. We recommend setting F=T.
-
-You may wish to experiment with the T= entry which governs timeout options. You
-MUST set some type of timeout or a malicious client could cause a Denial of
-Service attack by keeping your clamav-milter threads alive. The types of
-timeout are C (time for clamav-milter to acknowledge to sendmail that it
-has accepted a new connection), S (timeout for sending information from sendmail
-to clamav-milter), R (timeout for sendmail reading a reply from clamav-milter
-when it has been sent some information) and E (timeout for clamav-milter to
-handle the end-of-message request, this needs to be high enough to scan the
-largest file that you will receive since it is at this stage that the file is
-scanned, but short enough to ensure that a DoS can't occur when lots of scans
-are requested). The important entries for clamav-milter are C and E (both
-default to 5 minutes).
-
-WARNING: When running on internal mode (--external is NOT used), clamav-milter
-will need to wait for all connections to stop before it can reload the database
-after running freshclam. It is therefore important that NO timeouts in
-sendmail.cf are set too high or worse still turned off, otherwise clamav-milter
-can wait a long time, perhaps indefinately, while waiting for the system to
-quieten down. The same goes for disabling StreamMaxLength, since receiving a
-very large email to be scanned may take a long time. We advise setting
-StreamMaxLength to 1M.
-
-Don't forget to rebuild sendmail.cf after modifying sendmail.mc. You will
-need to restart sendmail after rebuilding sendmail.cf and starting clamd and
-clamav-milter.
-
-As with all software it is wise to ensure that clamav-milter has the least
-privileges it needs to run. So don't run it as root and don't store the sockets in a directory that can be written by everyone. For example ensure that /var/run
-is owned and writeable only by root and add entries for 'User' and
-'FixStaleSocket' in clamd.conf.
-
-When using UNIX domain sockets via the LocalSocket option of clamd.conf,
-we recommend that you use the --quarantine-dir option since that may improve
-performance.
-
-If you wish to send a warning when a message is blocked, clamav-milter MUST be
-able to call sendmail, for example on a Fedora Linux system:
-
- # ls -lL /usr/lib/sendmail
- -rwxr-sr-x 1 root smmsp 732356 Sep 1 11:16 /usr/lib/sendmail
-
-To test that your clamAV system is now intercepting viruses, visit
-http://www.testvirus.org
-
-If, under heavy strain on Linux, you see the message
- thread_create() failed: 12, abort
-appearing in a log file, you will need to increase the number of threads on
-your system (/proc/sys/kernel/threads-max), or decrease the value of
---max-children.
-
-Clamav-milter performs DNS look ups, if you wish to tweak its timeouts
-see resolv.conf(5).
-
-2.7 Postfix
-
-Clamav-milter has only been designed to work with Sendmail. I understand that
-modern versions of Postfix have milter support, and I've heard that
-Clamav-milter runs with these versions of Postfix, however it is not supported
-with that software and I do not know how much functionality works.
-
-To start clamav-milter:
-
- # clamav-milter --sendmail-cf= --max-children=2 \
- --timeout=0 --pidfile=/var/run/clamav/clamav-milter \
- local:/var/spool/postfix/clamav/clamav-milter
- # chown clamav:postfix /var/spool/postfix/clamav/clamav-milter
- # chmod g+w /var/spool/postfix/clamav/clmilter
-
-In /etc/postfix/main.cf set:
- smtpd_milters = unix:clamav/clamav-milter
- non_smtpd_milters = unix:clamav/clamav-milter
-
-3. CHANGE HISTORY
-
-See ../ChangeLog
-
-4. INTERNATIONALISATION
-
-The .po file was created with the command
- xgettext --msgid-bugs-address=bugs at clamav.net --copyright-holder=njh at bandsman.co.uk -L c -d clamav-milter -k_ clamav-milter.c
-
-If you're interested in helping to translate this program please drop the
-author an e-mail.
-
-5. BUG REPORTS
-
-Please send bug reports and/or comments to Nigel Horne <njh at clamav.net> or
-bugs at clamav.net.
-
-Various tips will go here, for example
- define(`confMILTER_LOG_LEVEL',`22')
-Running in the foreground, valgrind, LogSyslog, LogVerbose, LogFile etc.
-
-5.1. Patches
-
-Patches are welcome, but they must be against the latest CVS version and adhere
-to the coding style of clamav-milter. Coding style is religious, everyone
-believes theirs is great and all others are rubbish.
-
-This is my coding style, live with it. You don't want me in a bad mood because
-I can't read your code when I'm deciding if your code should be incorporated.
-
-Most of this style is based on K&R.
-
-Use the tab key, not space key, to indent.
-
-Except for functions, braces always go on the same line as the condition.
-
-Don't leave to chance, or your knowledge of precedence, use brackets to
-highten the readability.
-
-Choose variable names sensibly, don't use Hungarian style.
-
-The code is ANSI C, not C++, remember that when thinking of comment formats,
-location of declarations, etc.
-
-Patches which use 'goto' will never, ever, be accepted.
-
-Use the design of your code as comments.
-
-Test your patches and document the tests when submitting, e.g. different
-hardware, operating systems, test tools such as valgrind, compilers (gcc, icc,
-Sun's cc).
-
-Function names appear at the start of lines (I use ctags).
-
-Document your changes. If you add, remove, or change functionality you will
-need to update the manual page and possibly the usage message as well.
-
-6. CHROOT JAIL
-
-The instructions will differ for you, but these will give you an idea.
-You will have to do a lot of fiddling if you want notifications to work,
-since clamav-milter calls sendmail to handle the notifications and sendmail
-will run of out the same jail. I've not disabled the notifications, but I
-may in the future - for the moment handling notifications in the jail is an
-excercise for the reader. I've put in a symbolic link to sendmail, but I
-suspect it should be a real copy.
-
- mkdir /var/run/clamav-root
- chown clamav:clamav /var/run/clamav-root
- chmod 750 /var/run/clamav-root
- cd /var/run/clamav-root
- mkdir var
- mkdir var/tmp
- ln -s var/tmp .
- mkdir var/log
- cd var/log
- ln -s ../../../../../var/log/clamav .
- cd ..
- mkdir run
- mkdir run/clamav
- chown clamav:clamav run/clamav
- cd ..
- mkdir usr
- mkdir usr/local
- mkdir usr/local/share
- ln -s ../../../../../../usr/local/share/clamav .
- mkdir usr/lib
- cd usr/lib
- ln -s ../../../../../usr/lib/sendmail .
- cd ../..
- mkdir dev
- cd dev
- mknod null c 1 3
- chown clamav:clamav null
-
-In sendmail.mc:
-INPUT_MAIL_FILTER(`clamav', `S=local:/var/run/clamav-root/var/run/clamav/clmilter.sock, F=T, T=S:4m;R:4m;C:30s;E:10m')dnl
-
-When starting clamav-milter use options such as (notice that the location
-of clmilter.sock is different in sendmail.mc than the location clamav-milter
-expects to see it)
- --chroot=/var/run/clamav-root --max-children=3 -P --pidfile=/var/run/clamav/clamav-milter.pid --blacklist=60 --black-hole-mode local:/var/run/clamav/clmilter.sock
-
-You may need to modify your shutdown script to look for clamav-milter.pid
-in /var/run/clamav-root/var/run/clamav/clamav-milter.pid
-
-7. TODO
-
-There are several ideas marked as TODO in the source code. If anyone has
-any other suggestions please feel free to contact me. To avoid disappointment
-always contact me before undertaking any work.
diff --git a/contrib/old-clamav-milter/Makefile.am b/contrib/old-clamav-milter/Makefile.am
deleted file mode 100644
index 4a9eda3..0000000
--- a/contrib/old-clamav-milter/Makefile.am
+++ /dev/null
@@ -1,48 +0,0 @@
-#
-# Copyright (C) 2003 - 2005 Tomasz Kojm <tkojm at clamav.net>
-#
-# 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., 51 Franklin Street, Fifth Floor, Boston,
-# MA 02110-1301, USA.
-
-# FIXME: check automake for 'and' (&&)
-if BUILD_CLAMD
-if HAVE_MILTER
-
-sbin_PROGRAMS = clamav-milter
-
-clamav_milter_SOURCES = \
- $(top_srcdir)/shared/cfgparser.c \
- $(top_srcdir)/shared/cfgparser.h \
- $(top_srcdir)/shared/output.c \
- $(top_srcdir)/shared/output.h \
- $(top_srcdir)/shared/getopt.c \
- $(top_srcdir)/shared/getopt.h \
- $(top_srcdir)/shared/misc.c \
- $(top_srcdir)/shared/misc.h \
- $(top_srcdir)/shared/network.c \
- $(top_srcdir)/shared/network.h \
- clamav-milter.c
-man_MANS = $(top_builddir)/docs/man/clamav-milter.8
-
-endif
-endif
-
-LIBS = $(top_builddir)/libclamav/libclamav.la @CLAMAV_MILTER_LIBS@ @THREAD_LIBS@
-AM_CPPFLAGS = -I$(top_srcdir)/clamd -I$(top_srcdir)/libclamav -I$(top_srcdir)/shared -I$(top_srcdir)
-EXTRA_DIST = clamav-milter.c INSTALL
-CLEANFILES=*.gcda *.gcno
-CFLAGS=`echo "@CFLAGS@" | sed -e 's/-Werror[^-]//'`
-
-
diff --git a/contrib/old-clamav-milter/Makefile.in b/contrib/old-clamav-milter/Makefile.in
deleted file mode 100644
index ca7c717..0000000
--- a/contrib/old-clamav-milter/Makefile.in
+++ /dev/null
@@ -1,705 +0,0 @@
-# Makefile.in generated by automake 1.10.1 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
- at SET_MAKE@
-
-#
-# Copyright (C) 2003 - 2005 Tomasz Kojm <tkojm at clamav.net>
-#
-# 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., 51 Franklin Street, Fifth Floor, Boston,
-# MA 02110-1301, USA.
-
-VPATH = @srcdir@
-pkgdatadir = $(datadir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-build_triplet = @build@
-host_triplet = @host@
-target_triplet = @target@
- at BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE at sbin_PROGRAMS = \
- at BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ clamav-milter$(EXEEXT)
-subdir = clamav-milter
-DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in INSTALL
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \
- $(top_srcdir)/m4/argz.m4 $(top_srcdir)/m4/fdpassing.m4 \
- $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
- $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltdl.m4 \
- $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
- $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
- $(top_srcdir)/m4/mmap_private.m4 $(top_srcdir)/m4/resolv.m4 \
- $(top_srcdir)/configure.in
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
- $(ACLOCAL_M4)
-mkinstalldirs = $(install_sh) -d
-CONFIG_HEADER = $(top_builddir)/clamav-config.h
-CONFIG_CLEAN_FILES =
-am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)"
-sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
-PROGRAMS = $(sbin_PROGRAMS)
-am__clamav_milter_SOURCES_DIST = $(top_srcdir)/shared/cfgparser.c \
- $(top_srcdir)/shared/cfgparser.h $(top_srcdir)/shared/output.c \
- $(top_srcdir)/shared/output.h $(top_srcdir)/shared/getopt.c \
- $(top_srcdir)/shared/getopt.h $(top_srcdir)/shared/misc.c \
- $(top_srcdir)/shared/misc.h $(top_srcdir)/shared/network.c \
- $(top_srcdir)/shared/network.h clamav-milter.c
- at BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE at am_clamav_milter_OBJECTS = \
- at BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ cfgparser.$(OBJEXT) \
- at BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ output.$(OBJEXT) \
- at BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ getopt.$(OBJEXT) \
- at BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ misc.$(OBJEXT) \
- at BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ network.$(OBJEXT) \
- at BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ clamav-milter.$(OBJEXT)
-clamav_milter_OBJECTS = $(am_clamav_milter_OBJECTS)
-clamav_milter_LDADD = $(LDADD)
-DEFAULT_INCLUDES = -I. at am__isrc@ -I$(top_builddir)
-depcomp = $(SHELL) $(top_srcdir)/config/depcomp
-am__depfiles_maybe = depfiles
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
- --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
- $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-CCLD = $(CC)
-LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
- --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
- $(LDFLAGS) -o $@
-SOURCES = $(clamav_milter_SOURCES)
-DIST_SOURCES = $(am__clamav_milter_SOURCES_DIST)
-man8dir = $(mandir)/man8
-NROFF = nroff
-MANS = $(man_MANS)
-ETAGS = etags
-CTAGS = ctags
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-ACLOCAL = @ACLOCAL@
-AMTAR = @AMTAR@
-AR = @AR@
-ARGZ_H = @ARGZ_H@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-CC = @CC@
-CCDEPMODE = @CCDEPMODE@
-CFGDIR = @CFGDIR@
-CFLAGS = `echo "@CFLAGS@" | sed -e 's/-Werror[^-]//'`
-CHECK_CPPFLAGS = @CHECK_CPPFLAGS@
-CHECK_LIBS = @CHECK_LIBS@
-CLAMAVGROUP = @CLAMAVGROUP@
-CLAMAVUSER = @CLAMAVUSER@
-CLAMAV_MILTER_LIBS = @CLAMAV_MILTER_LIBS@
-CLAMD_LIBS = @CLAMD_LIBS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CYGPATH_W = @CYGPATH_W@
-DBDIR = @DBDIR@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DSYMUTIL = @DSYMUTIL@
-DUMPBIN = @DUMPBIN@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-EXEEXT = @EXEEXT@
-FGREP = @FGREP@
-FRESHCLAM_LIBS = @FRESHCLAM_LIBS@
-GCOV = @GCOV@
-GENHTML = @GENHTML@
-GETENT = @GETENT@
-GPERF = @GPERF@
-GREP = @GREP@
-HAVE_LIBGMP = @HAVE_LIBGMP@
-INCLTDL = @INCLTDL@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-LCOV = @LCOV@
-LD = @LD@
-LDFLAGS = @LDFLAGS@
-LIBADD_DL = @LIBADD_DL@
-LIBADD_DLD_LINK = @LIBADD_DLD_LINK@
-LIBADD_DLOPEN = @LIBADD_DLOPEN@
-LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@
-LIBBZ2 = @LIBBZ2@
-LIBBZ2_PREFIX = @LIBBZ2_PREFIX@
-LIBCLAMAV_LIBS = @LIBCLAMAV_LIBS@
-LIBCLAMAV_VERSION = @LIBCLAMAV_VERSION@
-LIBGMP = @LIBGMP@
-LIBGMP_PREFIX = @LIBGMP_PREFIX@
-LIBLTDL = @LIBLTDL@
-LIBOBJS = @LIBOBJS@
-LIBS = $(top_builddir)/libclamav/libclamav.la @CLAMAV_MILTER_LIBS@ @THREAD_LIBS@
-LIBTOOL = @LIBTOOL@
-LIPO = @LIPO@
-LN_S = @LN_S@
-LTDLDEPS = @LTDLDEPS@
-LTDLINCL = @LTDLINCL@
-LTDLOPEN = @LTDLOPEN@
-LTLIBBZ2 = @LTLIBBZ2@
-LTLIBGMP = @LTLIBGMP@
-LTLIBOBJS = @LTLIBOBJS@
-LT_CONFIG_H = @LT_CONFIG_H@
-LT_DLLOADERS = @LT_DLLOADERS@
-LT_DLPREOPEN = @LT_DLPREOPEN@
-MAINT = @MAINT@
-MAKEINFO = @MAKEINFO@
-MKDIR_P = @MKDIR_P@
-NM = @NM@
-NMEDIT = @NMEDIT@
-OBJDUMP = @OBJDUMP@
-OBJEXT = @OBJEXT@
-OTOOL = @OTOOL@
-OTOOL64 = @OTOOL64@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-RANLIB = @RANLIB@
-SED = @SED@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-STRIP = @STRIP@
-THREAD_LIBS = @THREAD_LIBS@
-TH_SAFE = @TH_SAFE@
-VERSION = @VERSION@
-VERSIONSCRIPTFLAG = @VERSIONSCRIPTFLAG@
-abs_builddir = @abs_builddir@
-abs_srcdir = @abs_srcdir@
-abs_top_builddir = @abs_top_builddir@
-abs_top_srcdir = @abs_top_srcdir@
-ac_ct_CC = @ac_ct_CC@
-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-datadir = @datadir@
-datarootdir = @datarootdir@
-docdir = @docdir@
-dvidir = @dvidir@
-exec_prefix = @exec_prefix@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-libdir = @libdir@
-libexecdir = @libexecdir@
-localedir = @localedir@
-localstatedir = @localstatedir@
-lt_ECHO = @lt_ECHO@
-ltdl_LIBOBJS = @ltdl_LIBOBJS@
-ltdl_LTLIBOBJS = @ltdl_LTLIBOBJS@
-mandir = @mandir@
-mkdir_p = @mkdir_p@
-oldincludedir = @oldincludedir@
-pdfdir = @pdfdir@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-sbindir = @sbindir@
-sendmailprog = @sendmailprog@
-sharedstatedir = @sharedstatedir@
-srcdir = @srcdir@
-sys_symbol_underscore = @sys_symbol_underscore@
-sysconfdir = @sysconfdir@
-target = @target@
-target_alias = @target_alias@
-target_cpu = @target_cpu@
-target_os = @target_os@
-target_vendor = @target_vendor@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
- at BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE at clamav_milter_SOURCES = \
- at BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ $(top_srcdir)/shared/cfgparser.c \
- at BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ $(top_srcdir)/shared/cfgparser.h \
- at BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ $(top_srcdir)/shared/output.c \
- at BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ $(top_srcdir)/shared/output.h \
- at BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ $(top_srcdir)/shared/getopt.c \
- at BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ $(top_srcdir)/shared/getopt.h \
- at BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ $(top_srcdir)/shared/misc.c \
- at BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ $(top_srcdir)/shared/misc.h \
- at BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ $(top_srcdir)/shared/network.c \
- at BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ $(top_srcdir)/shared/network.h \
- at BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ clamav-milter.c
-
- at BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE at man_MANS = $(top_builddir)/docs/man/clamav-milter.8
-AM_CPPFLAGS = -I$(top_srcdir)/clamd -I$(top_srcdir)/libclamav -I$(top_srcdir)/shared -I$(top_srcdir)
-EXTRA_DIST = clamav-milter.c INSTALL
-CLEANFILES = *.gcda *.gcno
-all: all-am
-
-.SUFFIXES:
-.SUFFIXES: .c .lo .o .obj
-$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
- @for dep in $?; do \
- case '$(am__configure_deps)' in \
- *$$dep*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
- && exit 0; \
- exit 1;; \
- esac; \
- done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign clamav-milter/Makefile'; \
- cd $(top_srcdir) && \
- $(AUTOMAKE) --foreign clamav-milter/Makefile
-.PRECIOUS: Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
- @case '$?' in \
- *config.status*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
- *) \
- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
- esac;
-
-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-install-sbinPROGRAMS: $(sbin_PROGRAMS)
- @$(NORMAL_INSTALL)
- test -z "$(sbindir)" || $(MKDIR_P) "$(DESTDIR)$(sbindir)"
- @list='$(sbin_PROGRAMS)'; for p in $$list; do \
- p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
- if test -f $$p \
- || test -f $$p1 \
- ; then \
- f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
- echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(sbinPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(sbindir)/$$f'"; \
- $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(sbinPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(sbindir)/$$f" || exit 1; \
- else :; fi; \
- done
-
-uninstall-sbinPROGRAMS:
- @$(NORMAL_UNINSTALL)
- @list='$(sbin_PROGRAMS)'; for p in $$list; do \
- f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
- echo " rm -f '$(DESTDIR)$(sbindir)/$$f'"; \
- rm -f "$(DESTDIR)$(sbindir)/$$f"; \
- done
-
-clean-sbinPROGRAMS:
- @list='$(sbin_PROGRAMS)'; for p in $$list; do \
- f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
- echo " rm -f $$p $$f"; \
- rm -f $$p $$f ; \
- done
-
-installcheck-sbinPROGRAMS: $(sbin_PROGRAMS)
- bad=0; pid=$$$$; list="$(sbin_PROGRAMS)"; for p in $$list; do \
- case ' $(AM_INSTALLCHECK_STD_OPTIONS_EXEMPT) ' in \
- *" $$p "* | *" $(srcdir)/$$p "*) continue;; \
- esac; \
- f=`echo "$$p" | \
- sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
- for opt in --help --version; do \
- if "$(DESTDIR)$(sbindir)/$$f" $$opt >c$${pid}_.out \
- 2>c$${pid}_.err </dev/null \
- && test -n "`cat c$${pid}_.out`" \
- && test -z "`cat c$${pid}_.err`"; then :; \
- else echo "$$f does not support $$opt" 1>&2; bad=1; fi; \
- done; \
- done; rm -f c$${pid}_.???; exit $$bad
-clamav-milter$(EXEEXT): $(clamav_milter_OBJECTS) $(clamav_milter_DEPENDENCIES)
- @rm -f clamav-milter$(EXEEXT)
- $(LINK) $(clamav_milter_OBJECTS) $(clamav_milter_LDADD) $(LIBS)
-
-mostlyclean-compile:
- -rm -f *.$(OBJEXT)
-
-distclean-compile:
- -rm -f *.tab.c
-
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cfgparser.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/clamav-milter.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/getopt.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/misc.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/network.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/output.Po at am__quote@
-
-.c.o:
- at am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
- at am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@ $(COMPILE) -c $<
-
-.c.obj:
- at am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
- at am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
-
-.c.lo:
- at am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
- at am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
-
-cfgparser.o: $(top_srcdir)/shared/cfgparser.c
- at am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cfgparser.o -MD -MP -MF $(DEPDIR)/cfgparser.Tpo -c -o cfgparser.o `test -f '$(top_srcdir)/shared/cfgparser.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/cfgparser.c
- at am__fastdepCC_TRUE@ mv -f $(DEPDIR)/cfgparser.Tpo $(DEPDIR)/cfgparser.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/shared/cfgparser.c' object='cfgparser.o' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cfgparser.o `test -f '$(top_srcdir)/shared/cfgparser.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/cfgparser.c
-
-cfgparser.obj: $(top_srcdir)/shared/cfgparser.c
- at am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cfgparser.obj -MD -MP -MF $(DEPDIR)/cfgparser.Tpo -c -o cfgparser.obj `if test -f '$(top_srcdir)/shared/cfgparser.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/cfgparser.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/cfgparser.c'; fi`
- at am__fastdepCC_TRUE@ mv -f $(DEPDIR)/cfgparser.Tpo $(DEPDIR)/cfgparser.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/shared/cfgparser.c' object='cfgparser.obj' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cfgparser.obj `if test -f '$(top_srcdir)/shared/cfgparser.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/cfgparser.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/cfgparser.c'; fi`
-
-output.o: $(top_srcdir)/shared/output.c
- at am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT output.o -MD -MP -MF $(DEPDIR)/output.Tpo -c -o output.o `test -f '$(top_srcdir)/shared/output.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/output.c
- at am__fastdepCC_TRUE@ mv -f $(DEPDIR)/output.Tpo $(DEPDIR)/output.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/shared/output.c' object='output.o' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o output.o `test -f '$(top_srcdir)/shared/output.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/output.c
-
-output.obj: $(top_srcdir)/shared/output.c
- at am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT output.obj -MD -MP -MF $(DEPDIR)/output.Tpo -c -o output.obj `if test -f '$(top_srcdir)/shared/output.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/output.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/output.c'; fi`
- at am__fastdepCC_TRUE@ mv -f $(DEPDIR)/output.Tpo $(DEPDIR)/output.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/shared/output.c' object='output.obj' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o output.obj `if test -f '$(top_srcdir)/shared/output.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/output.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/output.c'; fi`
-
-getopt.o: $(top_srcdir)/shared/getopt.c
- at am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT getopt.o -MD -MP -MF $(DEPDIR)/getopt.Tpo -c -o getopt.o `test -f '$(top_srcdir)/shared/getopt.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/getopt.c
- at am__fastdepCC_TRUE@ mv -f $(DEPDIR)/getopt.Tpo $(DEPDIR)/getopt.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/shared/getopt.c' object='getopt.o' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o getopt.o `test -f '$(top_srcdir)/shared/getopt.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/getopt.c
-
-getopt.obj: $(top_srcdir)/shared/getopt.c
- at am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT getopt.obj -MD -MP -MF $(DEPDIR)/getopt.Tpo -c -o getopt.obj `if test -f '$(top_srcdir)/shared/getopt.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/getopt.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/getopt.c'; fi`
- at am__fastdepCC_TRUE@ mv -f $(DEPDIR)/getopt.Tpo $(DEPDIR)/getopt.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/shared/getopt.c' object='getopt.obj' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o getopt.obj `if test -f '$(top_srcdir)/shared/getopt.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/getopt.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/getopt.c'; fi`
-
-misc.o: $(top_srcdir)/shared/misc.c
- at am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT misc.o -MD -MP -MF $(DEPDIR)/misc.Tpo -c -o misc.o `test -f '$(top_srcdir)/shared/misc.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/misc.c
- at am__fastdepCC_TRUE@ mv -f $(DEPDIR)/misc.Tpo $(DEPDIR)/misc.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/shared/misc.c' object='misc.o' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o misc.o `test -f '$(top_srcdir)/shared/misc.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/misc.c
-
-misc.obj: $(top_srcdir)/shared/misc.c
- at am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT misc.obj -MD -MP -MF $(DEPDIR)/misc.Tpo -c -o misc.obj `if test -f '$(top_srcdir)/shared/misc.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/misc.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/misc.c'; fi`
- at am__fastdepCC_TRUE@ mv -f $(DEPDIR)/misc.Tpo $(DEPDIR)/misc.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/shared/misc.c' object='misc.obj' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o misc.obj `if test -f '$(top_srcdir)/shared/misc.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/misc.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/misc.c'; fi`
-
-network.o: $(top_srcdir)/shared/network.c
- at am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT network.o -MD -MP -MF $(DEPDIR)/network.Tpo -c -o network.o `test -f '$(top_srcdir)/shared/network.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/network.c
- at am__fastdepCC_TRUE@ mv -f $(DEPDIR)/network.Tpo $(DEPDIR)/network.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/shared/network.c' object='network.o' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o network.o `test -f '$(top_srcdir)/shared/network.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/network.c
-
-network.obj: $(top_srcdir)/shared/network.c
- at am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT network.obj -MD -MP -MF $(DEPDIR)/network.Tpo -c -o network.obj `if test -f '$(top_srcdir)/shared/network.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/network.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/network.c'; fi`
- at am__fastdepCC_TRUE@ mv -f $(DEPDIR)/network.Tpo $(DEPDIR)/network.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/shared/network.c' object='network.obj' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o network.obj `if test -f '$(top_srcdir)/shared/network.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/network.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/network.c'; fi`
-
-mostlyclean-libtool:
- -rm -f *.lo
-
-clean-libtool:
- -rm -rf .libs _libs
-install-man8: $(man8_MANS) $(man_MANS)
- @$(NORMAL_INSTALL)
- test -z "$(man8dir)" || $(MKDIR_P) "$(DESTDIR)$(man8dir)"
- @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \
- l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
- for i in $$l2; do \
- case "$$i" in \
- *.8*) list="$$list $$i" ;; \
- esac; \
- done; \
- for i in $$list; do \
- if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
- else file=$$i; fi; \
- ext=`echo $$i | sed -e 's/^.*\\.//'`; \
- case "$$ext" in \
- 8*) ;; \
- *) ext='8' ;; \
- esac; \
- inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
- inst=`echo $$inst | sed -e 's/^.*\///'`; \
- inst=`echo $$inst | sed '$(transform)'`.$$ext; \
- echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
- $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst"; \
- done
-uninstall-man8:
- @$(NORMAL_UNINSTALL)
- @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \
- l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
- for i in $$l2; do \
- case "$$i" in \
- *.8*) list="$$list $$i" ;; \
- esac; \
- done; \
- for i in $$list; do \
- ext=`echo $$i | sed -e 's/^.*\\.//'`; \
- case "$$ext" in \
- 8*) ;; \
- *) ext='8' ;; \
- esac; \
- inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
- inst=`echo $$inst | sed -e 's/^.*\///'`; \
- inst=`echo $$inst | sed '$(transform)'`.$$ext; \
- echo " rm -f '$(DESTDIR)$(man8dir)/$$inst'"; \
- rm -f "$(DESTDIR)$(man8dir)/$$inst"; \
- done
-
-ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
- END { if (nonempty) { for (i in files) print i; }; }'`; \
- mkid -fID $$unique
-tags: TAGS
-
-TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
- $(TAGS_FILES) $(LISP)
- tags=; \
- here=`pwd`; \
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
- END { if (nonempty) { for (i in files) print i; }; }'`; \
- if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
- test -n "$$unique" || unique=$$empty_fix; \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- $$tags $$unique; \
- fi
-ctags: CTAGS
-CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
- $(TAGS_FILES) $(LISP)
- tags=; \
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
- END { if (nonempty) { for (i in files) print i; }; }'`; \
- test -z "$(CTAGS_ARGS)$$tags$$unique" \
- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
- $$tags $$unique
-
-GTAGS:
- here=`$(am__cd) $(top_builddir) && pwd` \
- && cd $(top_srcdir) \
- && gtags -i $(GTAGS_ARGS) $$here
-
-distclean-tags:
- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-
-distdir: $(DISTFILES)
- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- list='$(DISTFILES)'; \
- dist_files=`for file in $$list; do echo $$file; done | \
- sed -e "s|^$$srcdirstrip/||;t" \
- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
- case $$dist_files in \
- */*) $(MKDIR_P) `echo "$$dist_files" | \
- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
- sort -u` ;; \
- esac; \
- for file in $$dist_files; do \
- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
- if test -d $$d/$$file; then \
- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
- cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
- fi; \
- cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
- else \
- test -f $(distdir)/$$file \
- || cp -p $$d/$$file $(distdir)/$$file \
- || exit 1; \
- fi; \
- done
-check-am: all-am
-check: check-am
-all-am: Makefile $(PROGRAMS) $(MANS)
-installdirs:
- for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)"; do \
- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
- done
-install: install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-am
-install-strip:
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- `test -z '$(STRIP)' || \
- echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
-mostlyclean-generic:
-
-clean-generic:
- -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
-
-distclean-generic:
- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-
-maintainer-clean-generic:
- @echo "This command is intended for maintainers to use"
- @echo "it deletes files that may require special tools to rebuild."
-clean: clean-am
-
-clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \
- mostlyclean-am
-
-distclean: distclean-am
- -rm -rf ./$(DEPDIR)
- -rm -f Makefile
-distclean-am: clean-am distclean-compile distclean-generic \
- distclean-tags
-
-dvi: dvi-am
-
-dvi-am:
-
-html: html-am
-
-info: info-am
-
-info-am:
-
-install-data-am: install-man
-
-install-dvi: install-dvi-am
-
-install-exec-am: install-sbinPROGRAMS
-
-install-html: install-html-am
-
-install-info: install-info-am
-
-install-man: install-man8
-
-install-pdf: install-pdf-am
-
-install-ps: install-ps-am
-
-installcheck-am: installcheck-sbinPROGRAMS
-
-maintainer-clean: maintainer-clean-am
- -rm -rf ./$(DEPDIR)
- -rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-am
-
-mostlyclean-am: mostlyclean-compile mostlyclean-generic \
- mostlyclean-libtool
-
-pdf: pdf-am
-
-pdf-am:
-
-ps: ps-am
-
-ps-am:
-
-uninstall-am: uninstall-man uninstall-sbinPROGRAMS
-
-uninstall-man: uninstall-man8
-
-.MAKE: install-am install-strip
-
-.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libtool clean-sbinPROGRAMS ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-man8 install-pdf install-pdf-am install-ps \
- install-ps-am install-sbinPROGRAMS install-strip installcheck \
- installcheck-am installcheck-sbinPROGRAMS installdirs \
- maintainer-clean maintainer-clean-generic mostlyclean \
- mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
- pdf pdf-am ps ps-am tags uninstall uninstall-am uninstall-man \
- uninstall-man8 uninstall-sbinPROGRAMS
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
diff --git a/contrib/old-clamav-milter/clamav-milter.c b/contrib/old-clamav-milter/clamav-milter.c
deleted file mode 100644
index dc69995..0000000
--- a/contrib/old-clamav-milter/clamav-milter.c
+++ /dev/null
@@ -1,7039 +0,0 @@
-/*
- * clamav-milter.c
- * .../clamav-milter/clamav-milter.c
- *
- * Copyright (C) 2003-2007 Nigel Horne <njh at bandsman.co.uk>
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- *
- * Install into /usr/local/sbin/clamav-milter
- * See http://www.elandsys.com/resources/sendmail/libmilter/overview.html
- *
- * For installation instructions see the file INSTALL that came with this file
- *
- * NOTE: first character of strings to logg():
- * ! Error
- * ^ Warning
- * * Verbose
- * # Info, but not logged in foreground
- * Default Info
- */
-static char const rcsid[] = "$Id: clamav-milter.c,v 1.312 2007/02/12 22:24:21 njh Exp $";
-
-#if HAVE_CONFIG_H
-#include "clamav-config.h"
-#endif
-
-#include "cfgparser.h"
-#include "target.h"
-#include "str.h"
-#include "../libclamav/others.h"
-#include "output.h"
-#include "clamav.h"
-#include "table.h"
-#include "network.h"
-#include "misc.h"
-
-#include <stdio.h>
-#include <sysexits.h>
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#if HAVE_MEMORY_H
-#include <memory.h>
-#endif
-#if HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#include <sys/wait.h>
-#include <assert.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <net/if.h>
-#include <arpa/inet.h>
-#include <sys/un.h>
-#include <stdarg.h>
-#include <errno.h>
-#if HAVE_LIBMILTER_MFAPI_H
-#include <libmilter/mfapi.h>
-#endif
-#include <pthread.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <pwd.h>
-#include <grp.h>
-#if HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#if HAVE_RESOLV_H
-#include <arpa/nameser.h> /* for HEADER */
-#include <resolv.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <ctype.h>
-
-#if HAVE_MMAP
-#if HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#else /* HAVE_SYS_MMAN_H */
-#undef HAVE_MMAP
-#endif
-#endif
-
-#define NONBLOCK_SELECT_MAX_FAILURES 3
-#define NONBLOCK_MAX_ATTEMPTS 10
-#define CONNECT_TIMEOUT 5 /* Allow 5 seconds to connect */
-
-#ifdef C_LINUX
-#include <sys/sendfile.h> /* FIXME: use sendfile on BSD not Linux */
-#include <libintl.h>
-#include <locale.h>
-
-#define gettext_noop(s) s
-#define _(s) gettext(s)
-#define N_(s) gettext_noop(s)
-
-#else
-
-#define _(s) s
-#define N_(s) s
-
-#endif
-
-#ifdef USE_SYSLOG
-#include <syslog.h>
-#endif
-
-#ifdef WITH_TCPWRAP
-#if HAVE_TCPD_H
-#include <tcpd.h>
-#endif
-
-int allow_severity = LOG_DEBUG;
-int deny_severity = LOG_NOTICE;
-#endif
-
-#ifdef CL_DEBUG
-static char console[] = "/dev/console";
-#endif
-
-#if defined(CL_DEBUG) && defined(C_LINUX)
-#include <sys/resource.h>
-#endif
-
-#define _GNU_SOURCE
-#include <getopt.h>
-
-#ifndef SENDMAIL_BIN
-#define SENDMAIL_BIN "/usr/lib/sendmail"
-#endif
-
-#ifndef HAVE_IN_PORT_T
-typedef unsigned short in_port_t;
-#endif
-
-#ifndef HAVE_IN_ADDR_T
-typedef unsigned int in_addr_t;
-#endif
-
-#ifndef INET6_ADDRSTRLEN
-#ifdef AF_INET6
-#define INET6_ADDRSTRLEN 40
-#else
-#define INET6_ADDRSTRLEN 16
-#endif
-#endif
-
-#ifndef EX_CONFIG /* HP-UX */
-#define EX_CONFIG 78
-#endif
-
-#define VERSION_LENGTH 128
-#define DEFAULT_TIMEOUT 120
-
-#define NTRIES 5 /* How many times we try to connect to a clamd */
-
-/*#define SESSION*/
- /* Keep one command connexion open to clamd, otherwise a new
- * command connexion is created for each new email
- *
- * FIXME: When SESSIONS are open, freshclam can hang when
- * notfying clamd of an update. This is most likely to be a
- * problem with the implementation of SESSIONS on clamd.
- * The problem seems worst on BSD.
- *
- * Note that clamd is buggy and can hang or even crash if you
- * send SESSION command so be aware
- */
-
-/*
- * TODO: optional: xmessage on console when virus stopped (SNMP would be real nice!)
- * Having said that, with LogSysLog you can (on Linux) configure the system
- * to get messages on the system console, see syslog.conf(5), also you
- * can use wall(1) in the VirusEvent entry in clamd.conf
- * TODO: Decide action (bounce, discard, reject etc.) based on the virus
- * found. Those with faked addresses, such as SCO.A want discarding,
- * others could be bounced properly.
- * TODO: Encrypt mails sent to clamd to stop sniffers. Sending by UNIX domain
- * sockets is better
- * TODO: Load balancing, allow local machine to talk via UNIX domain socket.
- * TODO: allow each To: line in the whitelist file to specify a quarantine email
- * address
- * TODO: optionally use zlib to compress data sent to remote hosts
- * TODO: Finish IPv6 support (serverIPs array and SPF are IPv4 only)
- * TODO: Check domainkeys as well as SPF for phish false positives
- */
-
-struct header_node_t {
- char *header;
- struct header_node_t *next;
-};
-
-struct header_list_struct {
- struct header_node_t *first;
- struct header_node_t *last;
-};
-
-typedef struct header_list_struct *header_list_t;
-
-/*
- * Local addresses are those not scanned if --local is not set
- * 127.0.0.0 is not in this table since that's goverend by --outgoing
- * Andy Fiddaman <clam at fiddaman.net> added 169.254.0.0/16
- * (Microsoft default DHCP)
- * TODO: compare this with RFC1918/RFC3330
- */
-#define PACKADDR(a, b, c, d) (((uint32_t)(a) << 24) | ((b) << 16) | ((c) << 8) | (d))
-#define MAKEMASK(bits) ((uint32_t)(0xffffffff << (32 - bits)))
-
-static struct cidr_net { /* don't make this const because of -I flag */
- uint32_t base;
- uint32_t mask;
-} localNets[] = {
- /*{ PACKADDR(127, 0, 0, 0), MAKEMASK(8) }, * 127.0.0.0/8 */
- { PACKADDR(192, 168, 0, 0), MAKEMASK(16) }, /* 192.168.0.0/16 - RFC3330 */
- /*{ PACKADDR(192, 18, 0, 0), MAKEMASK(15) }, * 192.18.0.0/15 - RFC2544 */
- /*{ PACKADDR(192, 0, 2, 0), MAKEMASK(24) }, * 192.0.2.0/24 - RFC3330 */
- { PACKADDR( 10, 0, 0, 0), MAKEMASK(8) }, /* 10.0.0.0/8 */
- { PACKADDR(172, 16, 0, 0), MAKEMASK(12) }, /* 172.16.0.0/12 */
- { PACKADDR(169, 254, 0, 0), MAKEMASK(16) }, /* 169.254.0.0/16 */
- { 0, 0 }, /* space to put eight more via -I addr */
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 }
-};
-#define IFLAG_MAX 8
-
-#ifdef AF_INET6
-typedef struct cidr_net6 {
- struct in6_addr base;
- int preflen;
-} cidr_net6;
-static cidr_net6 localNets6[IFLAG_MAX];
-static int localNets6_cnt;
-#endif
-
-/*
- * Each libmilter thread has one of these
- */
-struct privdata {
- char *from; /* Who sent the message */
- char *subject; /* Original subject */
- char *sender; /* Secretary - often used in mailing lists */
- char **to; /* Who is the message going to */
- char ip[INET6_ADDRSTRLEN]; /* IP address of the other end */
- int numTo; /* Number of people the message is going to */
-#ifndef SESSION
- int cmdSocket; /*
- * Socket to send/get commands e.g. PORT for
- * dataSocket
- */
-#endif
- int dataSocket; /* Socket to send data to clamd */
- char *filename; /* Where to store the message in quarantine */
- u_char *body; /* body of the message if Sflag is set */
- size_t bodyLen; /* number of bytes in body */
- header_list_t headers; /* Message headers */
- long numBytes; /* Number of bytes sent so far */
- char *received; /* keep track of received from */
- const char *rejectCode; /* 550 or 554? */
- unsigned int discard:1; /*
- * looks like the remote end is playing ping
- * pong with us
- */
-#ifdef HAVE_RESOLV_H
- unsigned int spf_ok:1;
-#endif
- int statusCount; /* number of X-Virus-Status headers */
- int serverNumber; /* Index into serverIPs */
-};
-
-#ifdef SESSION
-static int createSession(unsigned int s);
-#else
-static int pingServer(int serverNumber);
-static void *try_server(void *var);
-static int active_servers(int *active);
-struct try_server_struct {
- int sock;
- int rc;
- struct sockaddr_in *server;
- int server_index;
-};
-#endif
-static int findServer(void);
-static sfsistat clamfi_connect(SMFICTX *ctx, char *hostname, _SOCK_ADDR *hostaddr);
-#ifdef CL_DEBUG
-static sfsistat clamfi_helo(SMFICTX *ctx, char *helostring);
-#endif
-static sfsistat clamfi_envfrom(SMFICTX *ctx, char **argv);
-static sfsistat clamfi_envrcpt(SMFICTX *ctx, char **argv);
-static sfsistat clamfi_header(SMFICTX *ctx, char *headerf, char *headerv);
-static sfsistat clamfi_eoh(SMFICTX *ctx);
-static sfsistat clamfi_body(SMFICTX *ctx, u_char *bodyp, size_t len);
-static sfsistat clamfi_eom(SMFICTX *ctx);
-static sfsistat clamfi_abort(SMFICTX *ctx);
-static sfsistat clamfi_close(SMFICTX *ctx);
-static void clamfi_cleanup(SMFICTX *ctx);
-static void clamfi_free(struct privdata *privdata, int keep);
-#ifdef __GNUC__
-static int clamfi_send(struct privdata *privdata, size_t len, const char *format, ...) __attribute__((format(printf, 3,4)));
-#else
-static int clamfi_send(struct privdata *privdata, size_t len, const char *format, ...);
-#endif
-static long clamd_recv(int sock, char *buf, size_t len);
-static off_t updateSigFile(void);
-static header_list_t header_list_new(void);
-static void header_list_free(header_list_t list);
-static void header_list_add(header_list_t list, const char *headerf, const char *headerv);
-static void header_list_print(header_list_t list, FILE *fp);
-static int connect2clamd(struct privdata *privdata);
-static int sendToFrom(struct privdata *privdata);
-static int checkClamd(int log_result);
-static int sendtemplate(SMFICTX *ctx, const char *filename, FILE *sendmail, const char *virusname);
-static int qfile(struct privdata *privdata, const char *sendmailId, const char *virusname);
-static int move(const char *oldfile, const char *newfile);
-static void setsubject(SMFICTX *ctx, const char *virusname);
-/*static int clamfi_gethostbyname(const char *hostname, struct hostent *hp, char *buf, size_t len);*/
-static int add_local_ip(char *address);
-static int isLocalAddr(in_addr_t addr);
-static int isLocal(const char *addr);
-static void clamdIsDown(void);
-static void *watchdog(void *a);
-static int check_and_reload_database(void);
-static void timeoutBlacklist(char *ip_address, int time_of_blacklist, void *v);
-static void quit(void);
-static void broadcast(const char *mess);
-static int loadDatabase(void);
-static int increment_connexions(void);
-static void decrement_connexions(void);
-static void dump_blacklist(char *key, int value, void *v);
-static int nonblock_connect(int sock, const struct sockaddr_in *sin, const char *hostname);
-static int connect_error(int sock, const char *hostname);
-
-#ifdef SESSION
-static pthread_mutex_t version_mutex = PTHREAD_MUTEX_INITIALIZER;
-static char **clamav_versions; /* max_children elements in the array */
-#define clamav_version (clamav_versions[0])
-#else
-static char clamav_version[VERSION_LENGTH + 1];
-#endif
-static int fflag = 0; /* force a scan, whatever */
-static int oflag = 0; /* scan messages from our machine? */
-static int lflag = 0; /* scan messages from our site? */
-static int Iflag = 0; /* Added an IP addr to localNets? */
-static const char *progname; /* our name - usually clamav-milter */
-
-/* Variables for --external */
-static int external = 0; /* scan messages ourself or use clamd? */
-static pthread_mutex_t engine_mutex = PTHREAD_MUTEX_INITIALIZER;
-struct cl_engine *engine = NULL;
-uint64_t maxscansize;
-uint64_t maxfilesize;
-uint32_t maxreclevel;
-uint32_t maxfiles;
-
-static struct cl_stat dbstat;
-static int options = CL_SCAN_STDOPT;
-
-#ifdef BOUNCE
-static int bflag = 0; /*
- * send a failure (bounce) message to the
- * sender. This probably isn't a good idea
- * since most reply addresses will be fake
- *
- * TODO: Perhaps we can have an option to
- * bounce outgoing mail, but not incoming?
- */
-#endif
-static const char *iface; /*
- * Broadcast a message when a virus is found,
- * this allows remote network management
- */
-static int broadcastSock = -1;
-static int pflag = 0; /*
- * Send a warning to the postmaster only,
- * this means user's won't be told when someone
- * sent them a virus
- */
-static int qflag = 0; /*
- * Send no warnings when a virus is found,
- * this means that the only log of viruses
- * found is the syslog, so it's best to
- * enable LogSyslog in clamd.conf
- */
-static int Sflag = 0; /*
- * Add a signature to each message that
- * has been scanned
- */
-static const char *sigFilename; /*
- * File where the scanned message signature
- * can be found
- */
-static char *quarantine; /*
- * If a virus is found in an email redirect
- * it to this account
- */
-static char *quarantine_dir; /*
- * Path to store messages before scanning.
- * Infected ones will be left there.
- */
-static int nflag = 0; /*
- * Don't add X-Virus-Scanned to header. Patch
- * from Dirk Meyer <dirk.meyer at dinoex.sub.org>
- */
-static int rejectmail = 1; /*
- * Send a 550 rejection when a virus is
- * found
- */
-static int hflag = 0; /*
- * Include original message headers in
- * report
- */
-static int cl_error = SMFIS_TEMPFAIL; /*
- * If an error occurs, return
- * this status. Allows messages
- * to be passed through
- * unscanned in the event of
- * an error. Patch from
- * Joe Talbott <josepht at cstone.net>
- */
-static int readTimeout = DEFAULT_TIMEOUT; /*
- * number of seconds to wait for clamd to
- * respond, see ReadTimeout in clamd.conf
- */
-static long streamMaxLength = -1; /* StreamMaxLength from clamd.conf */
-static int logok = 0; /*
- * Add clean items to the log file
- */
-static const char *signature = N_("-- \nScanned by ClamAv - http://www.clamav.net\n");
-static time_t signatureStamp;
-static char *templateFile; /* e-mail to be sent when virus detected */
-static char *templateHeaders; /* headers to be added to the above */
-static const char *tmpdir;
-
-#ifdef CL_DEBUG
-static int debug_level = 0;
-#endif
-
-static pthread_mutex_t n_children_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t n_children_cond = PTHREAD_COND_INITIALIZER;
-static int n_children = 0;
-static int max_children = 0;
-static unsigned int freshclam_monitor = 10; /*
- * how often, in
- * seconds, to scan for
- * database updates
- */
-static int child_timeout = 300; /* number of seconds to wait for
- * a child to die. Set to 0 to
- * wait forever
- */
-static int dont_wait = 0; /*
- * If 1 send retry later to the remote end
- * if max_chilren is exceeded, otherwise we
- * wait for the number to go down
- */
-static int dont_sanitise = 0; /*
- * Don't check for ";" and "|" chars in
- * email addresses.
- */
-static int advisory = 0; /*
- * Run clamav-milter in advisory mode - viruses
- * are flagged rather than deleted. Incompatible
- * with quarantine options
- */
-static int detect_forged_local_address; /*
- * for incoming only mail servers, drop emails
- * claiming to be from us that must be false
- * Requires that -o, -l or -f are NOT given
- */
-static const char *pidFile;
-static struct cfgstruct *copt;
-static const char *localSocket; /* milter->clamd comms */
-static in_port_t tcpSocket; /* milter->clamd comms */
-static char *port = NULL; /* sendmail->milter comms */
-
-static const char *serverHostNames = "127.0.0.1";
-#if HAVE_IN_ADDR_T
-static in_addr_t *serverIPs; /* IPv4 only, in network byte order */
-#else
-static long *serverIPs; /* IPv4 only, in network byte order */
-#endif
-static int numServers; /* number of elements in serverIPs array */
-#ifndef SESSION
-#define RETRY_SECS 300 /* How often to retry a server that's down */
-static time_t *last_failed_pings; /* For servers that are down. NB: not mutexed */
-#endif
-static char *rootdir; /* for chroot */
-
-#ifdef SESSION
-static struct session {
- int sock; /* fd */
- enum { CMDSOCKET_FREE, CMDSOCKET_INUSE, CMDSOCKET_DOWN } status;
-} *sessions; /* max_children elements in the array */
-static pthread_mutex_t sstatus_mutex = PTHREAD_MUTEX_INITIALIZER;
-#endif /*SESSION*/
-
-static pthread_cond_t watchdog_cond = PTHREAD_COND_INITIALIZER;
-
-#ifndef SHUT_RD
-#define SHUT_RD 0
-#endif
-#ifndef SHUT_WR
-#define SHUT_WR 1
-#endif
-
-static const char *postmaster = "postmaster";
-static const char *from = "MAILER-DAEMON";
-static int quitting;
-static int reload; /* reload database when SIGUSR2 is received */
-static const char *report; /* Report Phishing to this address */
-static const char *report_fps; /* Report Phish FPs to this address */
-
-static const char *whitelistFile; /*
- * file containing destination email
- * addresses that we don't scan
- */
-static const char *sendmailCF; /* location of sendmail.cf to verify */
-static int checkCF = 1;
-static const char *pidfile;
-static int black_hole_mode; /*
- * Since sendmail calls its milters before it
- * looks in /etc/aliases we can spend time
- * looking for malware that's going to be
- * thrown away even if the message is clean.
- * Enable this to not scan these messages.
- * Sadly, because these days sendmail -bv
- * only works as root, you can't use this with
- * the User directive, which some won't like
- * which also may contain the real target name
- *
- * smfi_getsymval(ctx, "{rcpt_addr}") only
- * handles virtuser, it doesn't also deref
- * the alias table, so it isn't any help
- */
-
-static table_t *blacklist; /* never freed */
-static int blacklist_time; /* How long to blacklist an IP */
-static pthread_mutex_t blacklist_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-#ifdef CL_DEBUG
-#if __GLIBC__ == 2 && __GLIBC_MINOR__ >= 1
-#define HAVE_BACKTRACE
-#endif
-#endif
-
-static void sigsegv(int sig);
-static void sigusr1(int sig);
-static void sigusr2(int sig);
-
-#ifdef HAVE_BACKTRACE
-#include <execinfo.h>
-
-static void print_trace(void);
-
-#define BACKTRACE_SIZE 200
-
-#endif
-
-static int verifyIncomingSocketName(const char *sockName);
-static int isWhitelisted(const char *emailaddress, int to);
-static int isBlacklisted(const char *ip_address);
-static table_t *mx(const char *host, table_t *t);
-static sfsistat black_hole(const struct privdata *privdata);
-static int useful_header(const char *cmd);
-
-extern short logg_foreground;
-
-#ifdef HAVE_RESOLV_H
-static table_t *resolve(const char *host, table_t *t);
-static int spf(struct privdata *privdata, table_t *prevhosts);
-static void spf_ip(char *ip, int zero, void *v);
-
-pthread_mutex_t res_pool_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-#ifdef HAVE_LRESOLV_R
-res_state res_pool;
-uint8_t *res_pool_state;
-pthread_cond_t res_pool_cond = PTHREAD_COND_INITIALIZER;
-
-static int safe_res_query(const char *d, int c, int t, u_char *a, int l) {
- int i = -1, ret;
-
- pthread_mutex_lock(&res_pool_mutex);
- while(i==-1) {
- int j;
- for(j=0; j<max_children+1; j++) {
- if(!res_pool_state[j]) continue;
- i = j;
- break;
- }
- if(i!=-1) break;
- pthread_cond_wait(&res_pool_cond, &res_pool_mutex);
- }
- res_pool_state[i]=0;
- pthread_mutex_unlock(&res_pool_mutex);
-
- ret = res_nquery(&res_pool[i], d, c, t, a, l);
-
- pthread_mutex_lock(&res_pool_mutex);
- res_pool_state[i]=1;
- pthread_cond_signal(&res_pool_cond);
- pthread_mutex_unlock(&res_pool_mutex);
- return ret;
-}
-
-#else /* !HAVE_LRESOLV_R - non thread safe resolver (old bsd's) */
-
-static int safe_res_query(const char *d, int c, int t, u_char *a, int l) {
- int ret;
- pthread_mutex_lock(&res_pool_mutex);
- ret = res_query(d, c, t, a, l);
- pthread_mutex_unlock(&res_pool_mutex);
- return ret;
-}
-
-#endif /* HAVE_LRESOLV_R */
-
-#endif /* HAVE_RESOLV_H */
-
-static void
-help(void)
-{
- printf("\n\tclamav-milter version %s\n", get_version());
- puts("\tCopyright (C) 2007 Nigel Horne <njh at clamav.net>\n");
-
- puts(_("\t--advisory\t\t-A\tFlag viruses rather than deleting them."));
- puts(_("\t--blacklist-time=SECS\t-k\tTime (in seconds) to blacklist an IP."));
- puts(_("\t--black-hole-mode\t\tDon't scan messages aliased to /dev/null."));
-#ifdef BOUNCE
- puts(_("\t--bounce\t\t-b\tSend a failure message to the sender."));
-#endif
- puts(_("\t--broadcast\t\t-B [IFACE]\tBroadcast to a network manager when a virus is found."));
- puts(_("\t--chroot=DIR\t\t-C DIR\tChroot to dir when starting."));
- puts(_("\t--config-file=FILE\t-c FILE\tRead configuration from FILE."));
- puts(_("\t--debug\t\t\t-D\tPrint debug messages."));
- puts(_("\t--detect-forged-local-address\t-L\tReject mails that claim to be from us."));
- puts(_("\t--dont-blacklist\t-K\tDon't blacklist a given IP."));
- puts(_("\t--dont-scan-on-error\t-d\tPass e-mails through unscanned if a system error occurs."));
- puts(_("\t--dont-wait\t\t\tAsk remote end to resend if max-children exceeded."));
- puts(_("\t--dont-sanitise\t\t\tAllow semicolon and pipe characters in email addresses."));
- puts(_("\t--external\t\t-e\tUse an external scanner (usually clamd)."));
- puts(_("\t--freshclam-monitor=SECS\t-M SECS\tHow often to check for database update."));
- puts(_("\t--from=EMAIL\t\t-a EMAIL\tError messages come from here."));
- puts(_("\t--force-scan\t\t-f\tForce scan all messages (overrides (-o and -l)."));
- puts(_("\t--help\t\t\t-h\tThis message."));
- puts(_("\t--headers\t\t-H\tInclude original message headers in the report."));
- puts(_("\t--ignore IPaddr\t\t-I IPaddr\tAdd IPaddr to LAN IP list (see --local)."));
- puts(_("\t--local\t\t\t-l\tScan messages sent from machines on our LAN."));
- puts(_("\t--max-childen\t\t-m\tMaximum number of concurrent scans."));
- puts(_("\t--outgoing\t\t-o\tScan outgoing messages from this machine."));
- puts(_("\t--noreject\t\t-N\tDon't reject viruses, silently throw them away."));
- puts(_("\t--noxheader\t\t-n\tSuppress X-Virus-Scanned/X-Virus-Status headers."));
- puts(_("\t--pidfile=FILE\t\t-i FILE\tLocation of pidfile."));
- puts(_("\t--postmaster\t\t-p EMAIL\tPostmaster address [default=postmaster]."));
- puts(_("\t--postmaster-only\t-P\tSend notifications only to the postmaster."));
- puts(_("\t--quiet\t\t\t-q\tDon't send e-mail notifications of interceptions."));
- puts(_("\t--quarantine=USER\t-Q EMAIL\tQuarantine e-mail account."));
- puts(_("\t--report-phish=EMAIL\t-r EMAIL\tReport phish to this email address."));
- puts(_("\t--report-phish-false-positives=EMAIL\t-R EMAIL\tReport phish false positves to this email address."));
- puts(_("\t--quarantine-dir=DIR\t-U DIR\tDirectory to store infected emails."));
- puts(_("\t--server=SERVER\t\t-s SERVER\tHostname/IP address of server(s) running clamd (when using TCPsocket)."));
- puts(_("\t--sendmail-cf=FILE\t\tLocation of the sendmail.cf file to verify"));
- puts(_("\t--no-check-cf\t\tSkip verification of sendmail.cf"));
- puts(_("\t--sign\t\t\t-S\tAdd a hard-coded signature to each scanned message."));
- puts(_("\t--signature-file=FILE\t-F FILE\tLocation of signature file."));
- puts(_("\t--template-file=FILE\t-t FILE\tLocation of e-mail template file."));
- puts(_("\t--template-headers=FILE\t\tLocation of e-mail headers for template file."));
- puts(_("\t--timeout=SECS\t\t-T SECS\tTimeout waiting to childen to die."));
- puts(_("\t--whitelist-file=FILE\t-W FILE\tLocation of the file of whitelisted addresses"));
- puts(_("\t--version\t\t-V\tPrint the version number of this software."));
-#ifdef CL_DEBUG
- puts(_("\t--debug-level=n\t\t-x n\tSets the debug level to 'n'."));
-#endif
- puts(_("\nFor more information type \"man clamav-milter\"."));
- puts(_("For bug reports, please refer to http://www.clamav.net/bugs"));
-}
-
-extern char *optarg;
-int
-main(int argc, char **argv)
-{
- int i, Bflag = 0, server = 0;
- char *cfgfile = NULL;
- const char *wont_blacklist = NULL;
- const struct cfgstruct *cpt;
- char version[VERSION_LENGTH + 1];
- pthread_t tid;
- struct rlimit rlim;
-#ifdef CL_DEBUG
- int consolefd;
-#endif
-
- /*
- * The SMFI_VERSION checks are for Sendmail 8.14, which I don't have
- * yet, so I can't verify them
- * Patch from Andy Fiddaman <clam at fiddaman.net>
- */
- struct smfiDesc smfilter = {
- "ClamAv", /* filter name */
- SMFI_VERSION, /* version code -- leave untouched */
- SMFIF_ADDHDRS|SMFIF_CHGHDRS, /* flags - we add and delete headers */
- clamfi_connect, /* connexion callback */
-#ifdef CL_DEBUG
- clamfi_helo, /* HELO filter callback */
-#else
- NULL,
-#endif
- clamfi_envfrom, /* envelope sender filter callback */
- clamfi_envrcpt, /* envelope recipient filter callback */
- clamfi_header, /* header filter callback */
- clamfi_eoh, /* end of header callback */
- clamfi_body, /* body filter callback */
- clamfi_eom, /* end of message callback */
- clamfi_abort, /* message aborted callback */
- clamfi_close, /* connexion cleanup callback */
-#if SMFI_VERSION > 2
- NULL, /* Unrecognised command */
-#endif
-#if SMFI_VERSION > 3
- NULL, /* DATA command callback */
-#endif
-#if SMFI_VERSION >= 0x01000000
- NULL, /* Negotiation callback */
-#endif
- };
-
-#if defined(CL_DEBUG) && defined(C_LINUX)
- rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
- if(setrlimit(RLIMIT_CORE, &rlim) < 0)
- perror("setrlimit");
-#endif
-
- /*
- * Temporarily enter guessed value into version, will
- * be overwritten later by the value returned by clamd
- */
- snprintf(version, sizeof(version) - 1,
- "ClamAV version %s, clamav-milter version %s",
- cl_retver(), get_version());
-
- progname = strrchr(argv[0], '/');
- if(progname)
- progname++;
- else
- progname = "clamav-milter";
-
-#ifdef C_LINUX
- setlocale(LC_ALL, "");
- bindtextdomain(progname, DATADIR"/clamav-milter/locale");
- textdomain(progname);
-#endif
-
- for(;;) {
- int opt_index = 0;
-#ifdef BOUNCE
-#ifdef CL_DEBUG
- const char *args = "a:AbB:c:C:dDefF:I:i:k:K:lLm:M:nNop:PqQ:r:R:hHs:St:T:U:VwW:x:z0:1:2";
-#else
- const char *args = "a:AbB:c:C:dDefF:I:i:k:K:lLm:M:nNop:PqQ:r:R:hHs:St:T:U:VwW:z0:1:2";
-#endif
-#else /*!BOUNCE*/
-#ifdef CL_DEBUG
- const char *args = "a:AB:c:C:dDefF:I:i:k:K:lLm:M:nNop:PqQ:r:R:hHs:St:T:U:VwW:x:z0:1:2";
-#else
- const char *args = "a:AB:c:C:dDefF:I:i:k:K:lLm:M:nNop:PqQ:r:R:hHs:St:T:U:VwW:z0:1:2";
-#endif
-#endif /*BOUNCE*/
-
- static struct option long_options[] = {
- {
- "from", 2, NULL, 'a'
- },
- {
- "advisory", 0, NULL, 'A'
- },
-#ifdef BOUNCE
- {
- "bounce", 0, NULL, 'b'
- },
-#endif
- {
- "broadcast", 2, NULL, 'B'
- },
- {
- "config-file", 1, NULL, 'c'
- },
- {
- "chroot", 1, NULL, 'C'
- },
- {
- "detect-forged-local-address", 0, NULL, 'L'
- },
- {
- "dont-blacklist", 1, NULL, 'K'
- },
- {
- "dont-scan-on-error", 0, NULL, 'd'
- },
- {
- "dont-wait", 0, NULL, 'w'
- },
- {
- "dont-sanitise", 0, NULL, 'z'
- },
- {
- "debug", 0, NULL, 'D'
- },
- {
- "external", 0, NULL, 'e'
- },
- {
- "force-scan", 0, NULL, 'f'
- },
- {
- "headers", 0, NULL, 'H'
- },
- {
- "help", 0, NULL, 'h'
- },
- {
- "ignore", 1, NULL, 'I'
- },
- {
- "pidfile", 1, NULL, 'i'
- },
- {
- "blacklist-time", 1, NULL, 'k'
- },
- {
- "local", 0, NULL, 'l'
- },
- {
- "noreject", 0, NULL, 'N'
- },
- {
- "noxheader", 0, NULL, 'n'
- },
- {
- "outgoing", 0, NULL, 'o'
- },
- {
- "postmaster", 1, NULL, 'p'
- },
- {
- "postmaster-only", 0, NULL, 'P',
- },
- {
- "quiet", 0, NULL, 'q'
- },
- {
- "quarantine", 1, NULL, 'Q',
- },
- {
- "report-phish", 1, NULL, 'r'
- },
- {
- "report-phish-false-positives", 1, NULL, 'R'
- },
- {
- "quarantine-dir", 1, NULL, 'U',
- },
- {
- "max-children", 1, NULL, 'm'
- },
- {
- "freshclam-monitor", 1, NULL, 'M'
- },
- {
- "sendmail-cf", 1, NULL, '0'
- },
- {
- "no-check-cf", 0, &checkCF, 0
- },
- {
- "server", 1, NULL, 's'
- },
- {
- "sign", 0, NULL, 'S'
- },
- {
- "signature-file", 1, NULL, 'F'
- },
- {
- "template-file", 1, NULL, 't'
- },
- {
- "template-headers", 1, NULL, '1'
- },
- {
- "timeout", 1, NULL, 'T'
- },
- {
- "whitelist-file", 1, NULL, 'W'
- },
- {
- "version", 0, NULL, 'V'
- },
- {
- "black-hole-mode", 0, NULL, '2'
- },
-#ifdef CL_DEBUG
- {
- "debug-level", 1, NULL, 'x'
- },
-#endif
- {
- NULL, 0, NULL, '\0'
- }
- };
-
- int ret = getopt_long(argc, argv, args, long_options, &opt_index);
-
- if(ret == -1)
- break;
- else if(ret == 0)
- continue;
-
- switch(ret) {
- case 'a': /* e-mail errors from here */
- /*
- * optarg is optional - if you give --from
- * then the --from is set to the orginal,
- * probably forged, email address
- */
- from = optarg;
- break;
- case 'A':
- advisory++;
- break;
-#ifdef BOUNCE
- case 'b': /* bounce worms/viruses */
- bflag++;
- break;
-#endif
- case 'B': /* broadcast */
- Bflag++;
- if(optarg)
- iface = optarg;
- break;
- case 'c': /* where is clamd.conf? */
- cfgfile = optarg;
- break;
- case 'C': /* chroot */
- rootdir = optarg;
- break;
- case 'd': /* don't scan on error */
- cl_error = SMFIS_ACCEPT;
- break;
- case 'D': /* enable debug messages */
- cl_debug();
- break;
- case 'e': /* use clamd */
- external++;
- break;
- case 'f': /* force the scan */
- fflag++;
- break;
- case 'h':
- help();
- return EX_OK;
- case 'H':
- hflag++;
- break;
- case 'i': /* pidfile */
- pidfile = optarg;
- break;
- case 'k': /* blacklist time */
- blacklist_time = atoi(optarg);
- break;
- case 'K': /* don't black list given IP */
- wont_blacklist = optarg;
- break;
- case 'I': /* --ignore, -I hostname */
- /*
- * Based on patch by jpd at louisiana.edu
- */
- if(Iflag == IFLAG_MAX) {
- fprintf(stderr,
- _("%s: %s, -I may only be given %d times\n"),
- argv[0], optarg, IFLAG_MAX);
- return EX_USAGE;
- }
- if(!add_local_ip(optarg)) {
- fprintf(stderr,
- _("%s: Cannot convert -I%s to IPaddr\n"),
- argv[0], optarg);
- return EX_USAGE;
- }
- Iflag++;
- break;
- case 'l': /* scan mail from the lan */
- lflag++;
- break;
- case 'L': /* detect forged local addresses */
- detect_forged_local_address++;
- break;
- case 'm': /* maximum number of children */
- max_children = atoi(optarg);
- break;
- case 'M': /* how often to monitor for freshclam */
- freshclam_monitor = atoi(optarg);
- break;
- case 'n': /* don't add X-Virus-Scanned */
- nflag++;
- smfilter.xxfi_flags &= ~(SMFIF_ADDHDRS|SMFIF_CHGHDRS);
- break;
- case 'N': /* Do we reject mail or silently drop it */
- rejectmail = 0;
- break;
- case 'o': /* scan outgoing mail */
- oflag++;
- break;
- case 'p': /* postmaster e-mail address */
- postmaster = optarg;
- break;
- case 'P': /* postmaster only */
- pflag++;
- break;
- case 'q': /* send NO notification email */
- qflag++;
- break;
- case 'Q': /* quarantine e-mail address */
- quarantine = optarg;
- smfilter.xxfi_flags |= SMFIF_CHGHDRS|SMFIF_ADDRCPT|SMFIF_DELRCPT;
- break;
- case 'r': /* report phishing here */
- /* e.g. reportphishing at antiphishing.org */
- report = optarg;
- break;
- case 'R': /* report phishing false positives here */
- report_fps = optarg;
- break;
- case 's': /* server running clamd */
- server++;
- serverHostNames = optarg;
- break;
- case 'F': /* signature file */
- sigFilename = optarg;
- signature = NULL;
- /* fall through */
- case 'S': /* sign */
- smfilter.xxfi_flags |= SMFIF_CHGBODY;
- Sflag++;
- break;
- case 't': /* e-mail template file */
- templateFile = optarg;
- break;
- case '1': /* headers for the template file */
- templateHeaders = optarg;
- break;
- case '2':
- black_hole_mode++;
- break;
- case 'T': /* time to wait for child to die */
- child_timeout = atoi(optarg);
- break;
- case 'U': /* quarantine path */
- quarantine_dir = optarg;
- break;
- case 'V':
- puts(version);
- return EX_OK;
- case 'w':
- dont_wait++;
- break;
- case 'W':
- whitelistFile = optarg;
- break;
- case 'z':
- dont_sanitise=1;
- break;
- case '0':
- sendmailCF = optarg;
- break;
-#ifdef CL_DEBUG
- case 'x':
- debug_level = atoi(optarg);
- break;
-#endif
- default:
-#ifdef CL_DEBUG
- fprintf(stderr, "Usage: %s [-b] [-c FILE] [-F FILE] [--max-children=num] [-e] [-l] [-o] [-p address] [-P] [-q] [-Q USER] [-s SERVER] [-S] [-x#] [-U PATH] [-M#] socket-addr\n", argv[0]);
-#else
- fprintf(stderr, "Usage: %s [-b] [-c FILE] [-F FILE] [--max-children=num] [-e] [-l] [-o] [-p address] [-P] [-q] [-Q USER] [-s SERVER] [-S] [-U PATH] [-M#] socket-addr\n", argv[0]);
-#endif
- return EX_USAGE;
- }
- }
-
- /*
- * Check sanity of --external and --server arguments
- */
- if(server && !external) {
- fprintf(stderr,
- "%s: --server can only be used with --external\n",
- argv[0]);
- return EX_USAGE;
- }
-#ifdef SESSION
- if(!external) {
- fprintf(stderr,
- _("%s: SESSIONS mode requires --external\n"), argv[0]);
- return EX_USAGE;
- }
-#endif
-
- /* TODO: support freshclam's daemon notify if --external is not given */
-
- if(optind == argc) {
- fprintf(stderr, _("%s: No socket-addr given\n"), argv[0]);
- return EX_USAGE;
- }
- port = argv[optind];
-
- if(rootdir == NULL) /* FIXME: Handle CHROOT */
- if(checkCF && verifyIncomingSocketName(port) < 0) {
- fprintf(stderr, _("%s: socket-addr (%s) doesn't agree with sendmail.cf\n"), argv[0], port);
- return EX_CONFIG;
- }
-
- if(strncasecmp(port, "inet:", 5) == 0)
- if(!lflag) {
- /*
- * Barmy but true. It seems that clamfi_connect will,
- * in this case, get the IP address of the machine
- * running sendmail, not of the machine sending the
- * mail, so the remote end will be a local address so
- * we must scan by enabling --local
- *
- * TODO: this is probably not needed if the remote
- * machine is localhost, need to check though
- */
- fprintf(stderr, _("%s: when using inet: connexion to sendmail you must enable --local\n"), argv[0]);
- return EX_USAGE;
- }
-
- /*
- * Sanity checks on the clamav configuration file
- */
- if(cfgfile == NULL) {
- cfgfile = cli_malloc(strlen(CONFDIR) + 12); /* leak */
- sprintf(cfgfile, "%s/clamd.conf", CONFDIR);
- }
- if((copt = getcfg(cfgfile, 1, OPT_CLAMD)) == NULL) {
- fprintf(stderr, _("%s: Can't parse the config file %s\n"),
- argv[0], cfgfile);
- return EX_CONFIG;
- }
-
- if(detect_forged_local_address) {
- if(oflag) {
- fprintf(stderr, _("%s: --detect-forged-local-addresses is not compatible with --outgoing\n"), argv[0]);
- return EX_CONFIG;
- }
- if(lflag) {
- fprintf(stderr, _("%s: --detect-forged-local-addresses is not compatible with --local\n"), argv[0]);
- return EX_CONFIG;
- }
- if(fflag) {
- fprintf(stderr, _("%s: --detect-forged-local-addresses is not compatible with --force\n"), argv[0]);
- return EX_CONFIG;
- }
- }
-
- if(Bflag) {
- int on;
-
- broadcastSock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- /*
- * SO_BROADCAST doesn't sent to all NICs on Linux, it only
- * broadcasts on eth0, which is why there's an optional argument
- * to --broadcast to say which NIC to broadcast on. You can use
- * SO_BINDTODEVICE to get around that, but you need to have
- * uid == 0 for that
- */
- on = 1;
- if(setsockopt(broadcastSock, SOL_SOCKET, SO_BROADCAST, (int *)&on, sizeof(on)) < 0) {
- perror("setsockopt");
- return EX_UNAVAILABLE;
- }
- shutdown(broadcastSock, SHUT_RD);
- }
-
- /*
- * Drop privileges
- */
-#ifdef CL_DEBUG
- /* Save the fd for later, open while we can */
- consolefd = open(console, O_WRONLY);
-#endif
-
- if(getuid() == 0) {
- if(iface) {
-#ifdef SO_BINDTODEVICE
- struct ifreq ifr;
-
- memset(&ifr, '\0', sizeof(struct ifreq));
- strncpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name) - 1);
- ifr.ifr_name[sizeof(ifr.ifr_name)-1]='\0';
- if(setsockopt(broadcastSock, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0) {
- perror(iface);
- return EX_CONFIG;
- }
-#else
- fprintf(stderr, _("%s: The iface option to --broadcast is not supported on your operating system\n"), argv[0]);
- return EX_CONFIG;
-#endif
- }
-
- if(((cpt = cfgopt(copt, "User")) != NULL) && cpt->enabled) {
- const struct passwd *user;
-
- if((user = getpwnam(cpt->strarg)) == NULL) {
- fprintf(stderr, _("%s: Can't get information about user %s\n"), argv[0], cpt->strarg);
- return EX_CONFIG;
- }
-
- if(cfgopt(copt, "AllowSupplementaryGroups")->enabled) {
-#ifdef HAVE_INITGROUPS
- if(initgroups(cpt->strarg, user->pw_gid) < 0) {
- perror(cpt->strarg);
- return EX_CONFIG;
- }
-#else
- fprintf(stderr, _("%s: AllowSupplementaryGroups: initgroups not supported.\n"),
- argv[0]);
- return EX_CONFIG;
-#endif
- } else {
-#ifdef HAVE_SETGROUPS
- if(setgroups(1, &user->pw_gid) < 0) {
- perror(cpt->strarg);
- return EX_CONFIG;
- }
-#endif
- }
-
- setgid(user->pw_gid);
-
- if(setuid(user->pw_uid) < 0)
- perror(cpt->strarg);
-#ifdef CL_DEBUG
- else
- printf(_("Running as user %s (UID %d, GID %d)\n"),
- cpt->strarg, (int)user->pw_uid,
- (int)user->pw_gid);
-#endif
-
- /*
- * Note, some O/Ss (e.g. OpenBSD/Fedora Linux) FORCE
- * you to run as root in black-hole-mode because
- * /var/spool/mqueue is mode 700 owned by root!
- * Flames to them, not to me, please.
- */
- if(black_hole_mode && (user->pw_uid != 0)) {
- int are_trusted;
- FILE *sendmail;
- char cmd[128];
-
- /*
- * Determine if we're a "trusted user"
- */
- snprintf(cmd, sizeof(cmd) - 1, "%s -bv root</dev/null 2>&1",
- SENDMAIL_BIN);
-
- sendmail = popen(cmd, "r");
-
- if(sendmail == NULL) {
- perror(SENDMAIL_BIN);
- are_trusted = 0;
- } else {
- int status;
- char buf[BUFSIZ];
-
- while(fgets(buf, sizeof(buf), sendmail) != NULL)
- ;
- /*
- * Can't do
- * switch(WEXITSTATUS(pclose(sendmail)))
- * because that fails to compile on
- * NetBSD2.0
- */
- status = pclose(sendmail);
- switch(WEXITSTATUS(status)) {
- case EX_NOUSER:
- /*
- * No root? But at least
- * we're trusted enough
- * to find out!
- */
- are_trusted = 1;
- break;
- default:
- are_trusted = 0;
- break;
- case EX_OK:
- are_trusted = 1;
- }
- }
- if(!are_trusted) {
- fprintf(stderr, _("%s: You cannot use black hole mode unless %s is a TrustedUser\n"),
- argv[0], cpt->strarg);
- return EX_CONFIG;
- }
- }
- } else
- printf(_("^%s: running as root is not recommended (check \"User\" in %s)\n"), argv[0], cfgfile);
- } else if(iface) {
- fprintf(stderr, _("%s: Only root can set an interface for --broadcast\n"), argv[0]);
- return EX_USAGE;
- }
-
- if(advisory && quarantine) {
- fprintf(stderr, _("%s: Advisory mode doesn't work with quarantine mode\n"), argv[0]);
- return EX_USAGE;
- }
- if(quarantine_dir) {
- struct stat statb;
-
- if(advisory) {
- fprintf(stderr,
- _("%s: Advisory mode doesn't work with quarantine directories\n"),
- argv[0]);
- return EX_USAGE;
- }
- if(strstr(quarantine_dir, "ERROR") != NULL) {
- fprintf(stderr,
- _("%s: the quarantine directory must not contain the string 'ERROR'\n"),
- argv[0]);
- return EX_USAGE;
- }
- if(strstr(quarantine_dir, "FOUND") != NULL) {
- fprintf(stderr,
- _("%s: the quarantine directory must not contain the string 'FOUND'\n"),
- argv[0]);
- return EX_USAGE;
- }
- if(strstr(quarantine_dir, "OK") != NULL) {
- fprintf(stderr,
- _("%s: the quarantine directory must not contain the string 'OK'\n"),
- argv[0]);
- return EX_USAGE;
- }
- if(access(quarantine_dir, W_OK) < 0) {
- perror(quarantine_dir);
- return EX_USAGE;
- }
- if(stat(quarantine_dir, &statb) < 0) {
- perror(quarantine_dir);
- return EX_USAGE;
- }
- /*
- * Quit if the quarantine directory is publically readable
- * or writeable
- */
- if(statb.st_mode & 077) {
- fprintf(stderr, _("%s: insecure quarantine directory %s (mode 0%o)\n"),
- argv[0], quarantine_dir, (int)statb.st_mode & 0777);
- return EX_CONFIG;
- }
- }
-
- if(sigFilename && !updateSigFile())
- return EX_USAGE;
-
- if(templateFile && (access(templateFile, R_OK) < 0)) {
- perror(templateFile);
- return EX_CONFIG;
- }
- if(templateHeaders) {
- if(templateFile == NULL) {
- fputs(("%s: --template-headers requires --template-file\n"),
- stderr);
- return EX_CONFIG;
- }
- if(access(templateHeaders, R_OK) < 0) {
- perror(templateHeaders);
- return EX_CONFIG;
- }
- }
- if(whitelistFile && (access(whitelistFile, R_OK) < 0)) {
- perror(whitelistFile);
- return EX_CONFIG;
- }
-
- /*
- * If the --max-children flag isn't set, see if MaxThreads
- * is set in the config file. Based on an idea by "Richard G. Roberto"
- * <rgr at dedlegend.com>
- */
- if((max_children == 0) && ((cpt = cfgopt(copt, "MaxThreads")) != NULL))
- max_children = cfgopt(copt, "MaxThreads")->numarg;
-
-#ifdef HAVE_LRESOLV_R
- /* allocate a pool of resolvers */
- if(!(res_pool=cli_calloc(max_children+1, sizeof(*res_pool))))
- return EX_OSERR;
- if(!(res_pool_state=cli_malloc(max_children+1)))
- return EX_OSERR;
- memset(res_pool_state, 1, max_children+1);
- for(i = 0; i < max_children+1; i++)
- res_ninit(&res_pool[i]);
-#endif
-
- if((cpt = cfgopt(copt, "ReadTimeout")) != NULL) {
- readTimeout = cpt->numarg;
-
- if(readTimeout < 0) {
- fprintf(stderr, _("%s: ReadTimeout must not be negative in %s\n"),
- argv[0], cfgfile);
- return EX_CONFIG;
- }
- }
-
- if((cpt = cfgopt(copt, "StreamMaxLength")) != NULL) {
- streamMaxLength = (long)cpt->numarg;
- if(streamMaxLength < 0L) {
- fprintf(stderr, _("%s: StreamMaxLength must not be negative in %s\n"),
- argv[0], cfgfile);
- return EX_CONFIG;
- }
- }
-
- if(((cpt = cfgopt(copt, "LogSyslog")) != NULL) && cpt->enabled) {
-#if defined(USE_SYSLOG) && !defined(C_AIX)
- int fac = LOG_LOCAL6;
-#endif
-
- if(cfgopt(copt, "LogVerbose")->enabled) {
- logg_verbose = 1;
-#ifdef CL_DEBUG
-#if ((SENDMAIL_VERSION_A > 8) || ((SENDMAIL_VERSION_A == 8) && (SENDMAIL_VERSION_B >= 13)))
- if(debug_level >= 15)
- smfi_setdbg(6);
-#endif
-#endif
- }
-#if defined(USE_SYSLOG) && !defined(C_AIX)
- logg_syslog = 1;
-
- if(((cpt = cfgopt(copt, "LogFacility")) != NULL) && cpt->enabled)
- if((fac = logg_facility(cpt->strarg)) == -1) {
- fprintf(stderr, "%s: LogFacility: %s: No such facility\n",
- argv[0], cpt->strarg);
- return EX_CONFIG;
- }
- openlog(progname, LOG_CONS|LOG_PID, fac);
-#endif
- } else {
- if(qflag)
- fprintf(stderr, _("%s: (-q && !LogSyslog): warning - all interception message methods are off\n"),
- argv[0]);
-#if defined(USE_SYSLOG) && !defined(C_AIX)
- logg_syslog = 0;
-#endif
- }
- /*
- * Get the outgoing socket details - the way to talk to clamd, unless
- * we're doing the scanning internally
- */
- if(!external) {
-#ifdef C_LINUX
- const char *lang;
-#endif
-
- if(max_children == 0) {
- fprintf(stderr, _("%s: --max-children must be given if --external is not given\n"), argv[0]);
- return EX_CONFIG;
- }
- if(freshclam_monitor <= 0) {
- fprintf(stderr, _("%s: --freshclam_monitor must be at least one second\n"), argv[0]);
- return EX_CONFIG;
- }
-#ifdef C_LINUX
- lang = getenv("LANG");
-
- if(lang && (strstr(lang, "UTF-8") != NULL)) {
- fprintf(stderr, "Your LANG environment variable is set to '%s'\n", lang);
- fprintf(stderr, "This is known to cause problems for some %s installations.\n", argv[0]);
- fputs("If you get failures with temporary files, please try again with LANG unset.\n", stderr);
- }
-#endif
-#if 0
- if(child_timeout) {
- fprintf(stderr, _("%s: --timeout must not be given if --external is not given\n"), argv[0]);
- return EX_CONFIG;
- }
-#endif
- if (cl_init(CL_INIT_DEFAULT)!=CL_SUCCESS) {
- fprintf(stderr, "%s: Failed to initialize libclamav, bailing out.\n", argv[0]);
- return EX_UNAVAILABLE;
- }
- if(loadDatabase() != 0) {
- /*
- * Handle the dont-scan-on-error option, which says
- * that we pass on emails, unscanned, if an error has
- * occurred
- */
- if(cl_error != SMFIS_ACCEPT)
- return EX_CONFIG;
-
- fprintf(stderr, _("%s: No emails will be scanned"),
- argv[0]);
- }
- numServers = 1;
- } else if(((cpt = cfgopt(copt, "LocalSocket")) != NULL) && cpt->enabled) {
-#ifdef SESSION
- struct sockaddr_un sockun;
-#endif
- char *sockname = NULL;
-
- if(cfgopt(copt, "TCPSocket")->enabled) {
- fprintf(stderr, _("%s: You can select one server type only (local/TCP) in %s\n"),
- argv[0], cfgfile);
- return EX_CONFIG;
- }
- if(server) {
- fprintf(stderr, _("%s: You cannot use the --server option when using LocalSocket in %s\n"),
- argv[0], cfgfile);
- return EX_USAGE;
- }
- if(strncasecmp(port, "unix:", 5) == 0)
- sockname = &port[5];
- else if(strncasecmp(port, "local:", 6) == 0)
- sockname = &port[6];
-
- if(sockname && (strcmp(sockname, cpt->strarg) == 0)) {
- fprintf(stderr, _("The connexion from sendmail to %s (%s) must not\n"),
- argv[0], sockname);
- fprintf(stderr, _("be the same as the connexion to clamd (%s) in %s\n"),
- cpt->strarg, cfgfile);
- return EX_CONFIG;
- }
- /*
- * TODO: check --server hasn't been set
- */
- localSocket = cpt->strarg;
-#ifndef SESSION
- if(!pingServer(-1)) {
- fprintf(stderr, _("Can't talk to clamd server via %s\n"),
- localSocket);
- fprintf(stderr, _("Check your entry for LocalSocket in %s\n"),
- cfgfile);
- return EX_CONFIG;
- }
-#endif
- /*if(quarantine_dir == NULL)
- fprintf(stderr, _("When using Localsocket in %s\nyou may improve performance if you use the --quarantine-dir option\n"), cfgfile);*/
-
- umask(077);
-
- serverIPs = (in_addr_t *)cli_malloc(sizeof(in_addr_t));
-#ifdef INADDR_LOOPBACK
- serverIPs[0] = htonl(INADDR_LOOPBACK);
-#else
- serverIPs[0] = inet_addr("127.0.0.1");
-#endif
-
-#ifdef SESSION
- memset((char *)&sockun, 0, sizeof(struct sockaddr_un));
- sockun.sun_family = AF_UNIX;
- strncpy(sockun.sun_path, localSocket, sizeof(sockun.sun_path));
- sockun.sun_path[sizeof(sockun.sun_path)-1]='\0';
-
- sessions = (struct session *)cli_malloc(sizeof(struct session));
- if((sessions[0].sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
- perror(localSocket);
- fprintf(stderr, _("Can't talk to clamd server via %s\n"),
- localSocket);
- fprintf(stderr, _("Check your entry for LocalSocket in %s\n"),
- cfgfile);
- return EX_CONFIG;
- }
- if(connect(sessions[0].sock, (struct sockaddr *)&sockun, sizeof(struct sockaddr_un)) < 0) {
- perror(localSocket);
- return EX_UNAVAILABLE;
- }
- if(send(sessions[0].sock, "SESSION\n", 8, 0) < 8) {
- perror("send");
- fputs(_("!Can't create a clamd session"), stderr);
- return EX_UNAVAILABLE;
- }
- sessions[0].status = CMDSOCKET_FREE;
-#endif
- /*
- * FIXME: Allow connexion to remote servers by TCP/IP whilst
- * connecting to the localserver via a UNIX domain socket
- */
- numServers = 1;
- } else if(((cpt = cfgopt(copt, "TCPSocket")) != NULL) && cpt->enabled) {
- int activeServers;
-
- /*
- * TCPSocket is in fact a port number not a full socket
- */
- if(quarantine_dir) {
- fprintf(stderr, _("%s: --quarantine-dir not supported for TCPSocket - use --quarantine\n"), argv[0]);
- return EX_CONFIG;
- }
-
- tcpSocket = (in_port_t)cpt->numarg;
-
- /*
- * cli_strtok's fieldno counts from 0
- */
- for(;;) {
- char *hostname = cli_strtok(serverHostNames, numServers, ":");
- if(hostname == NULL)
- break;
-#ifdef MAXHOSTNAMELEN
- if(strlen(hostname) > MAXHOSTNAMELEN) {
- fprintf(stderr, _("%s: hostname %s is longer than %d characters\n"),
- argv[0], hostname, MAXHOSTNAMELEN);
- return EX_CONFIG;
- }
-#endif
- numServers++;
- free(hostname);
- }
-
-#ifdef CL_DEBUG
- printf("numServers: %d\n", numServers);
-#endif
-
- serverIPs = (in_addr_t *)cli_malloc(numServers * sizeof(in_addr_t));
- if(serverIPs == NULL)
- return EX_OSERR;
- activeServers = 0;
-
-#ifdef SESSION
- /*
- * We need to know how many connexion to establish to clamd
- */
- if(max_children == 0) {
- fprintf(stderr, _("%s: --max-children must be given in sessions mode\n"), argv[0]);
- return EX_CONFIG;
- }
-#endif
-
- if(numServers > max_children) {
- fprintf(stderr, _("%1$s: --max-children (%2$d) is lower than the number of servers you have (%3$d)\n"),
- argv[0], max_children, numServers);
- return EX_CONFIG;
- }
-
- for(i = 0; i < numServers; i++) {
-#ifdef MAXHOSTNAMELEN
- char hostname[MAXHOSTNAMELEN + 1];
-
- if(cli_strtokbuf(serverHostNames, i, ":", hostname) == NULL)
- break;
-#else
- char *hostname = cli_strtok(serverHostNames, i, ":");
-#endif
-
- /*
- * Translate server's name to IP address
- */
- serverIPs[i] = inet_addr(hostname);
-#ifdef INADDR_NONE
- if(serverIPs[i] == INADDR_NONE) {
-#else
- if(serverIPs[i] == (in_addr_t)-1) {
-#endif
- const struct hostent *h = gethostbyname(hostname);
-
- if(h == NULL) {
- fprintf(stderr, _("%s: Unknown host %s\n"),
- argv[0], hostname);
- return EX_USAGE;
- }
-
- memcpy((char *)&serverIPs[i], h->h_addr, sizeof(serverIPs[i]));
- }
-
-#if defined(NTRIES) && ((NTRIES > 1))
-#ifndef SESSION
-#ifdef INADDR_LOOPBACK
- if(serverIPs[i] == htonl(INADDR_LOOPBACK)) {
-#else
-#if HAVE_IN_ADDR_T
- if(serverIPs[i] == (in_addr_t)inet_addr("127.0.0.1")) {
-#else
- if(serverIPs[i] == (long)inet_addr("127.0.0.1")) {
-#endif
-#endif
- int tries;
-
- /*
- * Fudge to allow clamd to come up on
- * our local machine
- */
- for(tries = 0; tries < NTRIES - 1; tries++) {
- if(pingServer(i))
- break;
- if(checkClamd(1)) /* will try all servers */
- break;
- puts(_("Waiting for clamd to come up"));
- /*
- * something to do as the system starts
- */
- sync();
- sleep(1);
- }
- /* Will try one more time */
- }
-#endif /* NTRIES > 1 */
-
- if(pingServer(i))
- activeServers++;
- else {
- printf(_("Can't talk to clamd server %s on port %d\n"),
- hostname, tcpSocket);
- if(serverIPs[i] == htonl(INADDR_LOOPBACK)) {
- if(cfgopt(copt, "TCPAddr")->enabled)
- printf(_("Check the value for TCPAddr in %s\n"), cfgfile);
- } else
- printf(_("Check the value for TCPAddr in clamd.conf on %s\n"), hostname);
- }
-#endif
-
-#ifndef MAXHOSTNAMELEN
- free(hostname);
-#endif
- }
-#ifdef SESSION
- activeServers = numServers;
-
- sessions = (struct session *)cli_calloc(max_children, sizeof(struct session));
- for(i = 0; i < (int)max_children; i++)
- if(createSession(i) < 0)
- return EX_UNAVAILABLE;
- if(activeServers == 0) {
- fprintf(stderr, _("Check your entry for TCPSocket in %s\n"),
- cfgfile);
- }
-#else
- if(activeServers == 0) {
- fprintf(stderr, _("Check your entry for TCPSocket in %s\n"),
- cfgfile);
- fputs(_("Can't find any clamd server\n"), stderr);
- return EX_CONFIG;
- }
- last_failed_pings = (time_t *)cli_calloc(numServers, sizeof(time_t));
-#endif
- } else {
- fprintf(stderr, _("%s: You must select server type (local/TCP) in %s\n"),
- argv[0], cfgfile);
- return EX_CONFIG;
- }
-
-#ifdef SESSION
- if(!external) {
- if(clamav_versions == NULL) {
- clamav_versions = (char **)cli_malloc(sizeof(char *));
- if(clamav_versions == NULL)
- return EX_TEMPFAIL;
- clamav_version = cli_strdup(version);
- }
- } else {
- unsigned int session;
-
- /*
- * We need to know how many connexions to establish to clamd
- */
- if(max_children == 0) {
- fprintf(stderr, _("%s: --max-children must be given in sessions mode\n"), argv[0]);
- return EX_CONFIG;
- }
-
- clamav_versions = (char **)cli_malloc(max_children * sizeof(char *));
- if(clamav_versions == NULL)
- return EX_TEMPFAIL;
-
- for(session = 0; session < max_children; session++) {
- clamav_versions[session] = cli_strdup(version);
- if(clamav_versions[session] == NULL)
- return EX_TEMPFAIL;
- }
- }
-#else
- strcpy(clamav_version, version);
-#endif
-
- if(((quarantine_dir == NULL) && localSocket) || !external) {
- /* set the temporary dir */
- if((cpt = cfgopt(copt, "TemporaryDirectory")) && cpt->enabled) {
- tmpdir = cpt->strarg;
- /*
- * FIXME: replace this:
- cl_settempdir(tmpdir, (short)(cfgopt(copt, "LeaveTemporaryFiles")->enabled)); *
- * with:
- * cl_engine_set(engine, CL_ENGINE_TMPDIR, cpt->strarg);
- * somewhere...
- */
- } else if((tmpdir = getenv("TMPDIR")) == (char *)NULL)
- if((tmpdir = getenv("TMP")) == (char *)NULL)
- if((tmpdir = getenv("TEMP")) == (char *)NULL)
-#ifdef P_tmpdir
- tmpdir = P_tmpdir;
-#else
- tmpdir = "/tmp";
-#endif
-
- /*
- * TODO: investigate mkdtemp on LINUX and possibly others
- */
- tmpdir = cli_gentemp(NULL);
-
- cli_dbgmsg("Making %s\n", tmpdir);
-
- if(mkdir(tmpdir, 0700)) {
- perror(tmpdir);
- return EX_CANTCREAT;
- }
- } else
- tmpdir = NULL;
-
- if(report) {
- if(!cfgopt(copt, "PhishingSignatures")->enabled) {
- fprintf(stderr, "%s: You have chosen --report-phish, but PhishingSignatures is off in %s\n",
- argv[0], cfgfile);
- return EX_USAGE;
- }
- if((quarantine_dir == NULL) && (tmpdir == NULL)) {
- /*
- * Limitation: doesn't store message in a temporary
- * file, so we won't be able to use mail < file
- */
- fprintf(stderr, "%s: when using --external, --report-phish cannot be used without either LocalSocket or --quarantine-dir\n",
- argv[0]);
- return EX_USAGE;
- }
- if(lflag) {
- /*
- * Naturally, if you attempt to scan the phish you've
- * just reported, it'll be blocked!
- */
- fprintf(stderr, "%s: --report-phish cannot be used with --local\n",
- argv[0]);
- return EX_USAGE;
- }
- }
- if(report_fps)
- if(!cfgopt(copt, "PhishingSignatures")->enabled) {
- fprintf(stderr, "%s: You have chosen --report-phish-false-positives, but PhishingSignatures is off in %s\n",
- argv[0], cfgfile);
- return EX_USAGE;
- }
-
- if(cfgopt(copt, "Foreground")->enabled)
- logg_foreground = 1;
- else {
- logg_foreground = 0;
-#ifdef CL_DEBUG
- printf(_("When debugging it is recommended that you use Foreground mode in %s\n"), cfgfile);
- puts(_("\tso that you can see all of the messages"));
-#endif
-
- switch(fork()) {
- case -1:
- perror("fork");
- return EX_OSERR;
- case 0: /* child */
- break;
- default: /* parent */
- return EX_OK;
- }
- close(0);
- open("/dev/null", O_RDONLY);
-
- /* initialize logger */
- logg_lock = cfgopt(copt, "LogFileUnlock")->enabled;
- logg_time = cfgopt(copt, "LogTime")->enabled;
- logok = cfgopt(copt, "LogClean")->enabled;
- logg_size = cfgopt(copt, "LogFileMaxSize")->numarg;
- logg_verbose = mprintf_verbose = cfgopt(copt, "LogVerbose")->enabled;
-
- if(cfgopt(copt, "Debug")->enabled) /* enable debug messages in libclamav */
- cl_debug();
-
- if((cpt = cfgopt(copt, "LogFile"))->enabled) {
- time_t currtime;
-
- logg_file = cpt->strarg;
- if((strlen(logg_file) < 2) ||
- ((logg_file[0] != '/') && (logg_file[0] != '\\') && (logg_file[1] != ':'))) {
- fprintf(stderr, "ERROR: LogFile requires full path.\n");
- logg_close();
- freecfg(copt);
- return 1;
- }
- time(&currtime);
- close(1);
- if(logg("#ClamAV-milter started at %s", ctime(&currtime))) {
- fprintf(stderr, "ERROR: Problem with internal logger. Please check the permissions on the %s file.\n", logg_file);
- logg_close();
- freecfg(copt);
- return 1;
- }
- } else {
-#ifdef CL_DEBUG
- close(1);
- logg_file = console;
- if(consolefd < 0) {
- perror(console);
- return EX_OSFILE;
- }
- dup(consolefd);
-#else
- int fds[3];
- logg_file = NULL;
- if(chdir("/") < 0)
- perror("/");
- fds[0] = open("/dev/null", O_RDONLY);
- fds[1] = open("/dev/null", O_WRONLY);
- fds[2] = open("/dev/null", O_WRONLY);
- for(i = 0; i <= 2; i++) {
- if(fds[i] == -1 || dup2(fds[i], i) == -1) {
- fprintf(stderr, "ERROR: failed to daemonize.\n");
- logg_close();
- freecfg(copt);
- return 1;
- }
- }
-#endif
- }
-
- dup2(1, 2);
-
-#ifdef CL_DEBUG
- if(consolefd >= 0)
- close(consolefd);
-#endif
-
-#ifdef HAVE_SETPGRP
-#ifdef SETPGRP_VOID
- setpgrp();
-#else
- setpgrp(0,0);
-#endif
-#else
-#ifdef HAVE_SETSID
- setsid();
-#endif
-#endif
- }
-
- if(cfgopt(copt, "Debug")->enabled)
- /*
- * enable debug messages in libclamav, --debug also does this
- */
- cl_debug();
-
- atexit(quit);
-
- if(!external) {
- if(!cfgopt(copt, "ScanMail")->enabled)
- printf(_("%s: ScanMail not defined in %s (needed without --external), enabling\n"),
- argv[0], cfgfile);
-
- options |= CL_SCAN_MAIL; /* no choice */
- /*if(!cfgopt(copt, "ScanRAR")->enabled)
- options |= CL_SCAN_DISABLERAR;*/
- if(cfgopt(copt, "ArchiveBlockEncrypted")->enabled)
- options |= CL_SCAN_BLOCKENCRYPTED;
- if(cfgopt(copt, "ScanPE")->enabled)
- options |= CL_SCAN_PE;
- if(cfgopt(copt, "DetectBrokenExecutables")->enabled)
- options |= CL_SCAN_BLOCKBROKEN;
- if(cfgopt(copt, "MailFollowURLs")->enabled)
- options |= CL_SCAN_MAILURL;
- if(cfgopt(copt, "ScanOLE2")->enabled)
- options |= CL_SCAN_OLE2;
- if(cfgopt(copt, "ScanHTML")->enabled)
- options |= CL_SCAN_HTML;
-
- if(((cpt = cfgopt(copt, "MaxScanSize")) != NULL) && cpt->enabled)
- maxscansize = cpt->numarg;
- else
- maxscansize = 104857600;
- if(((cpt = cfgopt(copt, "MaxFileSize")) != NULL) && cpt->enabled)
- maxfilesize = cpt->numarg;
- else
- maxfilesize = 10485760;
-
- if(getrlimit(RLIMIT_FSIZE, &rlim) == 0) {
- if((rlim.rlim_max < maxfilesize) || (rlim.rlim_max < maxscansize))
- logg("^System limit for file size is lower than maxfilesize or maxscansize\n");
- } else {
- logg("^Cannot obtain resource limits for file size\n");
- }
-
- if(((cpt = cfgopt(copt, "MaxRecursion")) != NULL) && cpt->enabled)
- maxreclevel = cpt->numarg;
- else
- maxreclevel = 8;
-
- if(((cpt = cfgopt(copt, "MaxFiles")) != NULL) && cpt->enabled)
- maxfiles = cpt->numarg;
- else
- maxfiles = 1000;
-
- if(cfgopt(copt, "ScanArchive")->enabled)
- options |= CL_SCAN_ARCHIVE;
- }
-
- pthread_create(&tid, NULL, watchdog, NULL);
-
- if(((cpt = cfgopt(copt, "PidFile")) != NULL) && cpt->enabled)
- pidFile = cpt->strarg;
-
- broadcast(_("Starting clamav-milter"));
-
- if(rootdir) {
- if(getuid() == 0) {
- if(chdir(rootdir) < 0) {
- perror(rootdir);
- logg("!chdir %s failed\n", rootdir);
- return EX_CONFIG;
- }
- if(chroot(rootdir) < 0) {
- perror(rootdir);
- logg("!chroot %s failed\n", rootdir);
- return EX_CONFIG;
- }
- logg("Chrooted to %s\n", rootdir);
- } else {
- logg("!chroot option needs root\n");
- return EX_CONFIG;
- }
- }
-
- if(pidfile) {
- /* save the PID */
- char *p, *q;
- FILE *fd;
- const mode_t old_umask = umask(0006);
-
- if(pidfile[0] != '/') {
- logg(_("!pidfile: '%s' must be a full pathname"),
- pidfile);
-
- return EX_CONFIG;
- }
- p = cli_strdup(pidfile);
- q = strrchr(p, '/');
- *q = '\0';
-
- if(rootdir == NULL)
- if(chdir(p) < 0) /* safety */
- perror(p);
-
- free(p);
-
- if((fd = fopen(pidfile, "w")) == NULL) {
- logg(_("!Can't save PID in file %s\n"), pidfile);
- return EX_CONFIG;
- }
-#ifdef C_LINUX
- /* Ensure that all threads are kill()ed */
- fprintf(fd, "-%d\n", (int)getpgrp());
-#else
- fprintf(fd, "%d\n", (int)getpid());
-#endif
- fclose(fd);
- umask(old_umask);
- } else if(tmpdir) {
- if(rootdir == NULL)
- if(chdir(tmpdir) < 0) { /* safety */
- perror(tmpdir);
- logg("!chdir %s failed\n", tmpdir);
- }
- } else
- if(rootdir == NULL)
-#ifdef P_tmpdir
- if(chdir(P_tmpdir) < 0) {
- perror(P_tmpdir);
- logg("!chdir %s failed\n", P_tmpdir);
- }
-#else
- if(chdir("/tmp") < 0) {
- perror("/tmp");
- logg("!chdir /tmp failed\n", P_tmpdir);
- }
-#endif
-
- if(cfgopt(copt, "FixStaleSocket")->enabled) {
- /*
- * Get the incoming socket details - the way sendmail talks to
- * us
- *
- * TODO: There's a security problem here that'll need fixing if
- * the User entry of clamd.conf is not used
- */
- if(strncasecmp(port, "unix:", 5) == 0) {
- if(unlink(&port[5]) < 0)
- if(errno != ENOENT)
- perror(&port[5]);
- } else if(strncasecmp(port, "local:", 6) == 0) {
- if(unlink(&port[6]) < 0)
- if(errno != ENOENT)
- perror(&port[6]);
- } else if(port[0] == '/') {
- if(unlink(port) < 0)
- if(errno != ENOENT)
- perror(port);
- }
- }
-
- if(smfi_setconn(port) == MI_FAILURE) {
- cli_errmsg("smfi_setconn failure\n");
- return EX_SOFTWARE;
- }
-
- if(smfi_register(smfilter) == MI_FAILURE) {
- fprintf(stderr, "smfi_register failure, ensure that you have linked against the correct version of sendmail\n");
- return EX_UNAVAILABLE;
- }
-
-#if ((SENDMAIL_VERSION_A > 8) || ((SENDMAIL_VERSION_A == 8) && (SENDMAIL_VERSION_B >= 13)))
- if(smfi_opensocket(1) == MI_FAILURE) {
- perror(port);
- fprintf(stderr, "Can't open/create %s\n", port);
- return EX_CONFIG;
- }
-#endif
-
- signal(SIGPIPE, SIG_IGN); /* libmilter probably does this as well */
- signal(SIGXFSZ, SIG_IGN); /* TODO: check if it's safe to call signal() here */
-
-#ifdef SESSION
- pthread_mutex_lock(&version_mutex);
-#endif
- logg(_("Starting %s\n"), clamav_version);
- logg(_("*Debugging is on\n"));
-
-#ifdef HAVE_RESOLV_H
-#if ! defined(HAVE_LRESOLV_R)
- if(!(_res.options&RES_INIT))
- if(res_init() < 0) {
- fprintf(stderr, "%s: Can't initialise the resolver\n",
- argv[0]);
- return EX_UNAVAILABLE;
- }
-#endif
- if(blacklist_time) {
- char name[MAXHOSTNAMELEN + 1];
-
- if(gethostname(name, sizeof(name)) < 0) {
- perror("gethostname");
- return EX_UNAVAILABLE;
- }
-
- blacklist = mx(name, NULL);
- if(blacklist)
- /* We must never blacklist ourself */
- tableInsert(blacklist, "127.0.0.1", 0);
-
- if(wont_blacklist) {
- char *w;
-
- i = 0;
- while((w = cli_strtok(wont_blacklist, i++, ",")) != NULL) {
- (void)tableInsert(blacklist, w, 0);
- free(w);
- }
- }
- tableIterate(blacklist, dump_blacklist, NULL);
- }
-#endif /* HAVE_RESOLV_H */
-
-#ifdef SESSION
- pthread_mutex_unlock(&version_mutex);
-#endif
-
- (void)signal(SIGSEGV, sigsegv);
- if(!logg_foreground)
- (void)signal(SIGUSR1, sigusr1);
- if(!external)
- (void)signal(SIGUSR2, sigusr2);
-
- return smfi_main();
-}
-
-#ifdef SESSION
-/*
- * Use the SESSION command of clamd.
- * Returns -1 for terminal failure, 0 for OK, 1 for nonterminal failure
- * The caller must take care of locking the sessions array
- */
-static int
-createSession(unsigned int s)
-{
- int ret = 0, fd;
- const int serverNumber = s % numServers;
- struct session *session = &sessions[s];
- const struct protoent *proto;
- struct sockaddr_in server;
-
- cli_dbgmsg("createSession session %d, server %d\n", s, serverNumber);
- assert(s < max_children);
-
- memset((char *)&server, 0, sizeof(struct sockaddr_in));
- server.sin_family = AF_INET;
- server.sin_port = (in_port_t)htons(tcpSocket);
-
- server.sin_addr.s_addr = serverIPs[serverNumber];
-
- session->sock = -1;
- proto = getprotobyname("tcp");
- if(proto == NULL) {
- fputs("Unknown prototol tcp, check /etc/protocols\n", stderr);
- fd = ret = -1;
- } else if((fd = socket(AF_INET, SOCK_STREAM, proto->p_proto)) < 0) {
- perror("socket");
- ret = -1;
- } else if(connect(fd, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) < 0) {
- perror("connect");
- ret = 1;
- } else if(send(fd, "SESSION\n", 8, 0) < 8) {
- perror("send");
- ret = 1;
- }
-
- if(ret != 0) {
-#ifdef MAXHOSTNAMELEN
- char hostname[MAXHOSTNAMELEN + 1];
-
- cli_strtokbuf(serverHostNames, serverNumber, ":", hostname);
- if(strcmp(hostname, "127.0.0.1") == 0)
- gethostname(hostname, sizeof(hostname));
-#else
- char *hostname = cli_strtok(serverHostNames, serverNumber, ":");
-#endif
-
- session->status = CMDSOCKET_DOWN;
-
- if(fd >= 0)
- close(fd);
-
- cli_warnmsg(_("Check clamd server %s - it may be down\n"), hostname);
-#ifndef MAXHOSTNAMELEN
- free(hostname);
-#endif
-
- broadcast(_("Check clamd server - it may be down"));
- } else
- session->sock = fd;
-
- return ret;
-}
-
-#else
-
-/*
- * Verify that the server is where we think it is
- * Returns true or false
- *
- * serverNumber counts from 0, but is only used for TCPSocket
- */
-static int
-pingServer(int serverNumber)
-{
- char *ptr;
- int sock;
- long nbytes;
- char buf[128];
-
- if(localSocket) {
- struct sockaddr_un server;
-
- memset((char *)&server, 0, sizeof(struct sockaddr_un));
- server.sun_family = AF_UNIX;
- strncpy(server.sun_path, localSocket, sizeof(server.sun_path));
- server.sun_path[sizeof(server.sun_path)-1]='\0';
-
- if((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
- perror(localSocket);
- return 0;
- }
- checkClamd(1);
- if(connect(sock, (struct sockaddr *)&server, sizeof(struct sockaddr_un)) < 0) {
- perror(localSocket);
- close(sock);
- return 0;
- }
- } else {
- struct sockaddr_in server;
- char *hostname;
-
- memset((char *)&server, 0, sizeof(struct sockaddr_in));
- server.sin_family = AF_INET;
- server.sin_port = (in_port_t)htons(tcpSocket);
-
- assert(serverIPs != NULL);
-#ifdef INADDR_NONE
- assert(serverIPs[0] != INADDR_NONE);
-#else
- assert(serverIPs[0] != (in_addr_t)-1);
-#endif
-
- server.sin_addr.s_addr = serverIPs[serverNumber];
-
- if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- perror("socket");
- return 0;
- }
- hostname = cli_strtok(serverHostNames, serverNumber, ":");
- /*
- * FIXME: use non-blocking connect, once the code is
- * amalgomated
- */
- if(nonblock_connect(sock, &server, hostname) < 0) {
- int is_connected = 0;
-
-#if (!defined(NTRIES)) || ((NTRIES <= 1))
- if(errno == ECONNREFUSED) {
- /*
- * During startup there is a race condition:
- * clamd can start and fork, then rc will start
- * clamav-milter before clamd has run accept(2),
- * so we fail to connect.
- * In case this is the situation here, we wait
- * for a couple of seconds and try again. The
- * sync() is because during startup the machine
- * won't be doing much for most of the time, so
- * we may as well do something constructive!
- */
- sync();
- sleep(2);
- if(nonblock_connect(sock, &server, hostname) >= 0)
- is_connected = 1;
- }
-#endif
- if(!is_connected) {
- if(errno != EINPROGRESS)
- perror(hostname ? hostname : "connect");
- close(sock);
- if(hostname)
- free(hostname);
- return 0;
- }
- }
- if(hostname)
- free(hostname);
- }
-
- /*
- * It would be better to use PING, check for PONG then issue the
- * VERSION command, since that would better validate that we're
- * talking to clamd, however clamd closes the session after
- * sending PONG :-(
- * So this code does not really validate that we're talking to clamd
- * Needs a fix to clamd
- * Also version command is verbose: says "clamd / ClamAV version"
- * instead of "clamAV version"
- */
- cli_dbgmsg("pingServer%d: sending VERSION\n", serverNumber);
- if(send(sock, "VERSION\n", 8, 0) < 8) {
- perror("send");
- return close(sock);
- }
-
- shutdown(sock, SHUT_WR);
-
- nbytes = clamd_recv(sock, buf, sizeof(buf) - 1);
-
- close(sock);
-
- if(nbytes < 0) {
- perror("recv");
- return 0;
- }
- if(nbytes == 0)
- return 0;
-
- buf[nbytes] = '\0';
-
- /* Remove the trailing new line from the reply */
- if((ptr = strchr(buf, '\n')) != NULL)
- *ptr = '\0';
-
- /*
- * No real validation is done here
- *
- * TODO: When connecting to more than one server, give a warning
- * if they're running different versions, or if the virus DBs
- * are out of date (say more than a month old)
- */
- snprintf(clamav_version, sizeof(clamav_version) - 1,
- "%s\n\tclamav-milter version %s",
- buf, get_version());
-
- return 1;
-}
-#endif
-
-/*
- * Find the best server to connect to. No intelligence to this.
- * It is best to weight the order of the servers from most wanted to least
- * wanted
- *
- * Return value is from 0 - index into sessions array
- *
- * If the load balancing fails return the first server in the list, not
- * an error, to be on the safe side
- */
-#ifdef SESSION
-static int
-findServer(void)
-{
- unsigned int i, j;
- struct session *session;
-
- /*
- * FIXME: Sessions code isn't flexible at handling servers
- * appearing and disappearing, e.g. sessions[n_children].sock == -1
- */
- i = 0;
- pthread_mutex_lock(&n_children_mutex);
- assert(n_children > 0);
- assert(n_children <= max_children);
- j = n_children - 1;
- pthread_mutex_unlock(&n_children_mutex);
-
- pthread_mutex_lock(&sstatus_mutex);
- for(; i < max_children; i++) {
- const int sess = (j + i) % max_children;
-
- session = &sessions[sess];
- cli_dbgmsg("findServer: try server %d\n", sess);
- if(session->status == CMDSOCKET_FREE) {
- session->status = CMDSOCKET_INUSE;
- pthread_mutex_unlock(&sstatus_mutex);
- return sess;
- }
- }
- pthread_mutex_unlock(&sstatus_mutex);
-
- /*
- * No session free - wait until one comes available. Only
- * retries once.
- */
- if(pthread_cond_broadcast(&watchdog_cond) < 0)
- perror("pthread_cond_broadcast");
-
- i = 0;
- session = sessions;
- pthread_mutex_lock(&sstatus_mutex);
- for(; i < max_children; i++, session++) {
- cli_dbgmsg("findServer: try server %d\n", i);
- if(session->status == CMDSOCKET_FREE) {
- session->status = CMDSOCKET_INUSE;
- pthread_mutex_unlock(&sstatus_mutex);
- return i;
- }
- }
- pthread_mutex_unlock(&sstatus_mutex);
-
- cli_warnmsg(_("No free clamd sessions\n"));
-
- return -1; /* none available - must fail */
-}
-#else
-/*
- * Return value is from 0 - index into serverIPs
- */
-static int
-findServer(void)
-{
- struct sockaddr_in *servers, *server;
- int maxsock, i, j, active;
- int retval;
- pthread_t *tids;
- struct try_server_struct *socks;
- fd_set rfds;
-
- assert(tcpSocket != 0);
- assert(numServers > 0);
-
- if(numServers == 1)
- return 0;
-
- if(active_servers(&active) <= 1)
- return active;
-
- servers = (struct sockaddr_in *)cli_calloc(numServers, sizeof(struct sockaddr_in));
- if(servers == NULL)
- return 0;
- socks = (struct try_server_struct *)cli_malloc(numServers * sizeof(struct try_server_struct));
-
- if(max_children > 0) {
- assert(n_children > 0);
- assert(n_children <= max_children);
-
- /*
- * Don't worry about no lock - it's doesn't matter if it's
- * not really accurate
- */
- j = n_children - 1; /* look at the next free one */
- if(j < 0)
- j = 0;
- } else
- /*
- * cli_rndnum returns 0..max
- */
- j = cli_rndnum(numServers - 1);
-
- for(i = 0; i < numServers; i++)
- socks[i].sock = -1;
-
- tids = cli_malloc(numServers * sizeof(pthread_t));
-
- for(i = 0, server = servers; i < numServers; i++, server++) {
- int sock;
- int server_index = (i + j) % numServers;
-
- server->sin_family = AF_INET;
- server->sin_port = (in_port_t)htons(tcpSocket);
- server->sin_addr.s_addr = serverIPs[server_index];
-
- logg("*findServer: try server %d\n", server_index);
-
- sock = socks[i].sock = socket(AF_INET, SOCK_STREAM, 0);
-
- if(sock < 0) {
- perror("socket");
- while(i--) {
- pthread_join(tids[i], NULL);
- if(socks[i].sock >= 0)
- close(socks[i].sock);
- }
- free(socks);
- free(servers);
- free(tids);
- return 0; /* Use the first server on failure */
- }
-
- socks[i].server = server;
- socks[i].server_index = server_index;
-
- if(pthread_create(&tids[i], NULL, try_server, &socks[i]) != 0) {
- perror("pthread_create");
- j = i;
- do {
- if (j!=i) pthread_join(tids[i], NULL);
- if(socks[i].sock >= 0)
- close(socks[i].sock);
- } while(--i >= 0);
- free(socks);
- free(servers);
- free(tids);
- return 0; /* Use the first server on failure */
- }
- }
-
- maxsock = -1;
- FD_ZERO(&rfds);
-
- for(i = 0; i < numServers; i++) {
- struct try_server_struct *rc;
-
- pthread_join(tids[i], (void **)&rc);
- assert(rc->sock == socks[i].sock);
- if(rc->rc == 0) {
- close(rc->sock);
- socks[i].sock = -1;
- } else {
- shutdown(rc->sock, SHUT_WR);
- FD_SET(rc->sock, &rfds);
- if(rc->sock > maxsock)
- maxsock = rc->sock;
- }
- }
-
- free(servers);
- free(tids);
-
- if(maxsock == -1) {
- logg(_("^Couldn't establish a connexion to any clamd server\n"));
- retval = 0;
- } else {
- struct timeval tv;
-
- tv.tv_sec = readTimeout ? readTimeout : DEFAULT_TIMEOUT;
- tv.tv_usec = 0;
-
- retval = select(maxsock + 1, &rfds, NULL, NULL, &tv);
- }
-
- if(retval < 0)
- perror("select");
-
- for(i = 0; i < numServers; i++)
- if(socks[i].sock >= 0)
- close(socks[i].sock);
-
- if(retval == 0) {
- free(socks);
- clamdIsDown();
- return 0;
- } else if(retval < 0) {
- free(socks);
- logg(_("^findServer: select failed (maxsock = %d)\n"), maxsock);
- return 0;
- }
-
- for(i = 0; i < numServers; i++)
- if((socks[i].sock >= 0) && (FD_ISSET(socks[i].sock, &rfds))) {
- const int s = (i + j) % numServers;
-
- free(socks);
- logg("*findServer: use server %d\n", s);
- return s;
- }
-
- free(socks);
- logg(_("^findServer: No response from any server\n"));
- return 0;
-}
-
-/*
- * How many servers are up at the moment? If a server is marked as down,
- * don't keep on flooding it with requests to see if it's now back up
- * If only one server is active, let the caller know, which server is the
- * active one
- */
-static int
-active_servers(int *active)
-{
- int server, count;
- time_t now = (time_t)0;
-
- for(count = server = 0; server < numServers; server++)
- if(last_failed_pings[server] == (time_t)0) {
- *active = server;
- count++;
- } else {
- if(now == (time_t)0)
- time(&now);
- if(now - last_failed_pings[server] >= RETRY_SECS)
- /* Try this server again next time */
- last_failed_pings[server] = (time_t)0;
- }
-
- if(count != 1)
- *active = 0;
- return count;
-}
-
-/*
- * Connecting to remote servers can take some time, so let's connect to
- * them in parallel. This routine is started as a thread
- */
-static void *
-try_server(void *var)
-{
- struct try_server_struct *s = (struct try_server_struct *)var;
- int sock = s->sock;
- struct sockaddr *server = (struct sockaddr *)s->server;
- int server_index = s->server_index;
-
- if(last_failed_pings[server_index]) {
- s->rc = 0;
- return var;
- }
-
- logg("*try_server: sock %d\n", sock);
-
- if((connect(sock, server, sizeof(struct sockaddr)) < 0) ||
- (send(sock, "PING\n", 5, 0) < 5)) {
- time(&last_failed_pings[server_index]);
- s->rc = 0;
- } else
- s->rc = 1;
-
- if(s->rc == 0) {
-#ifdef MAXHOSTNAMELEN
- char hostname[MAXHOSTNAMELEN + 1];
-
- cli_strtokbuf(serverHostNames, server_index, ":", hostname);
- if(strcmp(hostname, "127.0.0.1") == 0)
- gethostname(hostname, sizeof(hostname));
-#else
- char *hostname = cli_strtok(serverHostNames, server_index, ":");
-#endif
- perror(hostname);
- logg(_("^Check clamd server %s - it may be down\n"), hostname);
-#ifndef MAXHOSTNAMELEN
- free(hostname);
-#endif
- broadcast(_("Check clamd server - it may be down\n"));
- }
-
- return var;
-}
-#endif
-
-/*
- * Sendmail wants to establish a connexion to us
- * TODO: is it possible (desirable?) to determine if the remote machine has been
- * compromised?
- */
-static sfsistat
-clamfi_connect(SMFICTX *ctx, char *hostname, _SOCK_ADDR *hostaddr)
-{
-#if defined(HAVE_INET_NTOP) || defined(WITH_TCPWRAP)
- char ip[INET6_ADDRSTRLEN];
-#endif
- int t;
- const char *remoteIP;
- struct privdata *privdata;
-
- if(quitting)
- return cl_error;
-
- if(ctx == NULL) {
- logg(_("!clamfi_connect: ctx is null"));
- return cl_error;
- }
- if(hostname == NULL) {
- logg(_("!clamfi_connect: hostname is null"));
- return cl_error;
- }
- if(smfi_getpriv(ctx) != NULL) {
- /* More than one connexion command, "can't happen" */
- cli_warnmsg("clamfi_connect: called more than once\n");
- clamfi_cleanup(ctx);
- return cl_error;
- }
-#ifdef AF_INET6
- if((hostaddr == NULL) ||
- ((hostaddr->sa_family == AF_INET) && (&(((struct sockaddr_in *)(hostaddr))->sin_addr) == NULL)) ||
- ((hostaddr->sa_family == AF_INET6) && (&(((struct sockaddr_in6 *)(hostaddr))->sin6_addr) == NULL)))
-#else
- if((hostaddr == NULL) || (&(((struct sockaddr_in *)(hostaddr))->sin_addr) == NULL))
-#endif
- /*
- * According to the sendmail API hostaddr is NULL if
- * "the type is not supported in the current version". What
- * the documentation doesn't say is the type of what.
- *
- * Possibly the input is not a TCP/IP socket e.g. stdin?
- */
- remoteIP = "127.0.0.1";
- else {
-#ifdef HAVE_INET_NTOP
- switch(hostaddr->sa_family) {
- case AF_INET:
- remoteIP = (const char *)inet_ntop(AF_INET, &((struct sockaddr_in *)(hostaddr))->sin_addr, ip, sizeof(ip));
- break;
-#ifdef AF_INET6
- case AF_INET6:
- remoteIP = (const char *)inet_ntop(AF_INET6, &((struct sockaddr_in6 *)(hostaddr))->sin6_addr, ip, sizeof(ip));
- break;
-#endif
- default:
- logg(_("clamfi_connect: Unexpected sa_family %d\n"),
- hostaddr->sa_family);
- return cl_error;
- }
-
-#else
- remoteIP = inet_ntoa(((struct sockaddr_in *)(hostaddr))->sin_addr);
-#endif
-
- if(remoteIP == NULL) {
- logg(_("clamfi_connect: remoteIP is null"));
- return cl_error;
- }
- }
-
-#ifdef CL_DEBUG
- if(debug_level >= 4) {
- if(hostname[0] == '[')
- logg(_("clamfi_connect: connexion from %s"), remoteIP);
- else
- logg(_("clamfi_connect: connexion from %s [%s]"), hostname, remoteIP);
- }
-#endif
-
-#ifdef WITH_TCPWRAP
- /*
- * Support /etc/hosts.allow and /etc/hosts.deny
- */
- if(strncasecmp(port, "inet:", 5) == 0) {
- const char *hostmail;
- struct hostent hostent;
- char buf[BUFSIZ];
- static pthread_mutex_t wrap_mutex = PTHREAD_MUTEX_INITIALIZER;
-
- /*
- * Using TCP/IP for the sendmail->clamav-milter connexion
- */
- if(((hostmail = smfi_getsymval(ctx, "{if_name}")) == NULL) &&
- ((hostmail = smfi_getsymval(ctx, "j")) == NULL)) {
- logg(_("Can't get sendmail hostname"));
- return cl_error;
- }
- /*
- * Use hostmail for error statements, not hostname, suggestion
- * by Yar Tikhiy <yar at comp.chem.msu.su>
- */
- if(r_gethostbyname(hostmail, &hostent, buf, sizeof(buf)) != 0) {
- logg(_("^Access Denied: Host Unknown (%s)"), hostmail);
- if(hostmail[0] == '[')
- /*
- * A case could be made that it's not clamAV's
- * job to check a system's DNS configuration
- * and let this message through. However I am
- * just too worried about any knock on effects
- * to do that...
- */
- cli_warnmsg(_("Can't find entry for IP address %s in DNS - check your DNS setting\n"),
- hostmail);
- return cl_error;
- }
-
-#ifdef HAVE_INET_NTOP
- if(hostent.h_addr &&
- (inet_ntop(AF_INET, (struct in_addr *)hostent.h_addr, ip, sizeof(ip)) == NULL)) {
- perror(hostent.h_name);
- /*strcpy(ip, (char *)inet_ntoa(*(struct in_addr *)hostent.h_addr));*/
- logg(_("^Access Denied: Can't get IP address for (%s)"), hostent.h_name);
- return cl_error;
- }
-#else
- strncpy(ip, (char *)inet_ntoa(*(struct in_addr *)hostent.h_addr), sizeof(ip));
- ip[sizeof(ip)-1]='\0';
-#endif
-
- /*
- * Ask is this is a allowed name or IP number
- *
- * hosts_ctl uses strtok so it is not thread safe, see
- * hosts_access(3)
- */
- pthread_mutex_lock(&wrap_mutex);
- if(!hosts_ctl(progname, hostent.h_name, ip, STRING_UNKNOWN)) {
- pthread_mutex_unlock(&wrap_mutex);
- logg(_("^Access Denied for %s[%s]"), hostent.h_name, ip);
- return SMFIS_TEMPFAIL;
- }
- pthread_mutex_unlock(&wrap_mutex);
- }
-#endif /*WITH_TCPWRAP*/
-
- if(fflag)
- /*
- * Patch from "Richard G. Roberto" <rgr at dedlegend.com>
- * Always scan whereever the message is from
- */
- return SMFIS_CONTINUE;
-
- if(!oflag)
- if(strcmp(remoteIP, "127.0.0.1") == 0) {
- logg(_("*clamfi_connect: not scanning outgoing messages"));
- return SMFIS_ACCEPT;
- }
-
- if((!lflag) && isLocal(remoteIP)) {
-#ifdef CL_DEBUG
- logg(_("*clamfi_connect: not scanning local messages\n"));
-#endif
- return SMFIS_ACCEPT;
- }
-
-#if defined(HAVE_INET_NTOP) || defined(WITH_TCPWRAP)
- if(detect_forged_local_address && !isLocal(ip)) {
-#else
- if(detect_forged_local_address && !isLocal(remoteIP)) {
-#endif
- char me[MAXHOSTNAMELEN + 1];
-
- if(gethostname(me, sizeof(me) - 1) < 0) {
- logg(_("^clamfi_connect: gethostname failed"));
- return SMFIS_CONTINUE;
- }
- logg("*me '%s' hostname '%s'\n", me, hostname);
- if(strcasecmp(hostname, me) == 0) {
- logg(_("Rejected connexion falsely claiming to be from here\n"));
- smfi_setreply(ctx, "550", "5.7.1", _("You have claimed to be me, but you are not"));
- broadcast(_("Forged local address detected"));
- return SMFIS_REJECT;
- }
- }
- if(isBlacklisted(remoteIP)) {
- char mess[128];
-
- /*
- * TODO: Option to greylist rather than blacklist, by sending
- * a try again code
- * TODO: state *which* virus
- * TODO: add optional list of IP addresses that won't be
- * blacklisted
- */
- logg("Rejected connexion from blacklisted IP %s\n", remoteIP);
-
- snprintf(mess, sizeof(mess), _("%s is blacklisted because your machine is infected with a virus"), remoteIP);
- smfi_setreply(ctx, "550", "5.7.1", mess);
- broadcast(_("Blacklisted IP detected"));
-
- /*
- * Keep them blacklisted
- */
- pthread_mutex_lock(&blacklist_mutex);
- (void)tableUpdate(blacklist, remoteIP, (int)time((time_t *)0));
- pthread_mutex_unlock(&blacklist_mutex);
-
- return SMFIS_REJECT;
- }
-
- if(blacklist_time == 0)
- return SMFIS_CONTINUE; /* allocate privdata per message */
-
- pthread_mutex_lock(&blacklist_mutex);
- t = tableFind(blacklist, remoteIP);
- pthread_mutex_unlock(&blacklist_mutex);
-
- if(t == 0)
- return SMFIS_CONTINUE; /* this IP will never be blacklisted */
-
- privdata = (struct privdata *)cli_calloc(1, sizeof(struct privdata));
- if(privdata == NULL)
- return cl_error;
-
-#ifdef SESSION
- privdata->dataSocket = -1;
-#else
- privdata->dataSocket = privdata->cmdSocket = -1;
-#endif
-
- if(smfi_setpriv(ctx, privdata) == MI_SUCCESS) {
- strcpy(privdata->ip, remoteIP);
- return SMFIS_CONTINUE;
- }
-
- free(privdata);
-
- return cl_error;
-}
-
-/*
- * Since sendmail requires that MAIL FROM is called before RCPT TO, it is
- * safe to assume that this routine is called first, so the n_children
- * handler is put here
- */
-static sfsistat
-clamfi_envfrom(SMFICTX *ctx, char **argv)
-{
- struct privdata *privdata;
- const char *mailaddr = argv[0];
-
- logg("*clamfi_envfrom: %s\n", argv[0]);
-
- if(isWhitelisted(argv[0], 0)) {
- logg(_("*clamfi_envfrom: ignoring whitelisted message"));
- return SMFIS_ACCEPT;
- }
-
- if(strcmp(argv[0], "<>") == 0) {
- mailaddr = smfi_getsymval(ctx, "{mail_addr}");
- if(mailaddr == NULL)
- mailaddr = smfi_getsymval(ctx, "_");
-
- if(mailaddr && *mailaddr)
- cli_dbgmsg("Message from \"%s\" has no from field\n", mailaddr);
- else {
-#if 0
- if(use_syslog)
- syslog(LOG_NOTICE, _("Rejected email with empty from field"));
- smfi_setreply(ctx, "554", "5.7.1", _("You have not said who the email is from"));
- broadcast(_("Reject email with empty from field"));
- clamfi_cleanup(ctx);
- return SMFIS_REJECT;
-#endif
- mailaddr = "<>";
- }
- }
- privdata = smfi_getpriv(ctx);
-
- if(privdata == NULL) {
- privdata = (struct privdata *)cli_calloc(1, sizeof(struct privdata));
- if(privdata == NULL)
- return cl_error;
- if(smfi_setpriv(ctx, privdata) != MI_SUCCESS) {
- free(privdata);
- return cl_error;
- }
- if(!increment_connexions()) {
- smfi_setreply(ctx, "451", "4.3.2", _("AV system temporarily overloaded - please try later"));
- free(privdata);
- smfi_setpriv(ctx, NULL);
- return SMFIS_TEMPFAIL;
- }
- } else {
- /* More than one message on this connexion */
- char ip[INET6_ADDRSTRLEN];
-
- strcpy(ip, privdata->ip);
- if(isBlacklisted(ip)) {
- char mess[80 + INET6_ADDRSTRLEN];
-
- logg("Rejected email from blacklisted IP %s\n", ip);
-
- /*
- * TODO: Option to greylist rather than blacklist, by
- * sending a try again code
- * TODO: state *which* virus
- */
- sprintf(mess, "Your IP (%s) is blacklisted because your machine is infected with a virus", ip);
- smfi_setreply(ctx, "550", "5.7.1", mess);
- broadcast(_("Blacklisted IP detected"));
-
- /*
- * Keep them blacklisted
- */
- pthread_mutex_lock(&blacklist_mutex);
- (void)tableUpdate(blacklist, ip, (int)time((time_t *)0));
- pthread_mutex_unlock(&blacklist_mutex);
-
- return SMFIS_REJECT;
- }
- clamfi_free(privdata, 1);
- strcpy(privdata->ip, ip);
- }
-
-#ifdef SESSION
- privdata->dataSocket = -1;
-#else
- privdata->dataSocket = privdata->cmdSocket = -1;
-#endif
-
- /*
- * Rejection is via 550 until DATA is received. We know that
- * DATA has been sent when either we get a header or the end of
- * header statement
- */
- privdata->rejectCode = "550";
-
- privdata->from = cli_strdup(mailaddr);
-
- if(hflag) {
- privdata->headers = header_list_new();
-
- if(privdata->headers == NULL) {
- clamfi_free(privdata, 1);
- return cl_error;
- }
- }
-
- return SMFIS_CONTINUE;
-}
-
-#ifdef CL_DEBUG
-static sfsistat
-clamfi_helo(SMFICTX *ctx, char *helostring)
-{
- logg("HELO '%s'\n", helostring);
-
- return SMFIS_CONTINUE;
-}
-#endif
-
-static sfsistat
-clamfi_envrcpt(SMFICTX *ctx, char **argv)
-{
- struct privdata *privdata = (struct privdata *)smfi_getpriv(ctx);
- const char *to, *ptr;
-
- logg("*clamfi_envrcpt: %s\n", argv[0]);
-
- if(privdata == NULL) /* sanity check */
- return cl_error;
-
- if(privdata->to == NULL) {
- privdata->to = cli_malloc(sizeof(char *) * 2);
-
- assert(privdata->numTo == 0);
- } else
- privdata->to = cli_realloc(privdata->to, sizeof(char *) * (privdata->numTo + 2));
-
- if(privdata->to == NULL)
- return cl_error;
-
- to = smfi_getsymval(ctx, "{rcpt_addr}");
- if(to == NULL)
- to = argv[0];
-
- for(ptr = to; !dont_sanitise && *ptr; ptr++)
- if(strchr("|;", *ptr) != NULL) {
- smfi_setreply(ctx, "554", "5.7.1", _("Suspicious recipient address blocked"));
- logg("^Suspicious recipient address blocked: '%s'\n", to);
- privdata->to[privdata->numTo] = NULL;
- if(blacklist_time && privdata->ip[0]) {
- logg(_("Will blacklist %s for %d seconds because of cracking attempt\n"),
- privdata->ip, blacklist_time);
- pthread_mutex_lock(&blacklist_mutex);
- (void)tableUpdate(blacklist, privdata->ip,
- (int)time((time_t *)0));
- pthread_mutex_unlock(&blacklist_mutex);
- }
- /*
- * REJECT rejects this recipient, not the entire email
- */
- return SMFIS_REJECT;
- }
-
- privdata->to[privdata->numTo] = cli_strdup(to);
- privdata->to[++privdata->numTo] = NULL;
-
- return SMFIS_CONTINUE;
-}
-
-static sfsistat
-clamfi_header(SMFICTX *ctx, char *headerf, char *headerv)
-{
- struct privdata *privdata = (struct privdata *)smfi_getpriv(ctx);
-
-#ifdef CL_DEBUG
- if(debug_level >= 9)
- logg("*clamfi_header: %s: %s\n", headerf, headerv);
- else
- logg("*clamfi_header: %s\n", headerf);
-#else
- logg("*clamfi_header: %s\n", headerf);
-#endif
-
- /*
- * The DATA instruction from SMTP (RFC2821) must have been sent
- */
- privdata->rejectCode = "554";
-
- if(hflag)
- header_list_add(privdata->headers, headerf, headerv);
- else if((strcasecmp(headerf, "Received") == 0) &&
- (strncasecmp(headerv, "from ", 5) == 0) &&
- (strstr(headerv, "localhost") != 0)) {
- if(privdata->received)
- free(privdata->received);
- privdata->received = cli_strdup(headerv);
- }
-
- if((strcasecmp(headerf, "Message-ID") == 0) &&
- (strncasecmp(headerv, "<MDAEMON", 8) == 0))
- privdata->discard = 1;
- else if((strcasecmp(headerf, "Subject") == 0) && headerv) {
- if(privdata->subject)
- free(privdata->subject);
- if(headerv)
- privdata->subject = cli_strdup(headerv);
- } else if(strcasecmp(headerf, "X-Virus-Status") == 0)
- privdata->statusCount++;
- else if((strcasecmp(headerf, "Sender") == 0) && headerv) {
- if(privdata->sender)
- free(privdata->sender);
- privdata->sender = cli_strdup(headerv);
- }
-#ifdef HAVE_RESOLV_H
- else if((strcasecmp(headerf, "From") == 0) && headerv) {
- /*
- * SPF check against the from header, since the SMTP header
- * may be valid. This is not what the SPF spec says, but I
- * have seen SPF matches on what are clearly phishes, so by
- * checking against the from: header we're less likely to
- * FP a real phish
- */
- if(privdata->from)
- free(privdata->from);
- privdata->from = cli_strdup(headerv);
- }
-#endif
-
- if(!useful_header(headerf)) {
- logg("*Discarded the header\n");
- return SMFIS_CONTINUE;
- }
-
- if(privdata->dataSocket == -1)
- /*
- * First header - make connexion with clamd
- */
- if(!connect2clamd(privdata)) {
- clamfi_cleanup(ctx);
- return cl_error;
- }
-
- if(clamfi_send(privdata, 0, "%s: %s\n", headerf, headerv) <= 0) {
- clamfi_cleanup(ctx);
- return cl_error;
- }
-
- return SMFIS_CONTINUE;
-}
-
-/*
- * At this point DATA will have been received, so we really ought to
- * send 554 back not 550
- */
-static sfsistat
-clamfi_eoh(SMFICTX *ctx)
-{
- struct privdata *privdata = (struct privdata *)smfi_getpriv(ctx);
- char **to;
-
- logg(_("*clamfi_eoh\n"));
-
- /*
- * The DATA instruction from SMTP (RFC2821) must have been sent
- */
- privdata->rejectCode = "554";
-
- if(privdata->dataSocket == -1)
- /*
- * No headers - make connexion with clamd
- */
- if(!connect2clamd(privdata)) {
- clamfi_cleanup(ctx);
- return cl_error;
- }
-
-#if 0
- /* Mailing lists often say our own posts are from us */
- if(detect_forged_local_address && privdata->from &&
- (!privdata->sender) && !isWhitelisted(privdata->from, 1)) {
- char me[MAXHOSTNAMELEN + 1];
- const char *ptr;
-
- if(gethostname(me, sizeof(me) - 1) < 0) {
- if(use_syslog)
- syslog(LOG_WARNING, _("clamfi_eoh: gethostname failed"));
- return SMFIS_CONTINUE;
- }
- ptr = strstr(privdata->from, me);
- if(ptr && (ptr != privdata->from) && (*--ptr == '@')) {
- if(use_syslog)
- syslog(LOG_NOTICE, _("Rejected email falsely claiming to be from %s"), privdata->from);
- smfi_setreply(ctx, "554", "5.7.1", _("You have claimed to be from me, but you are not"));
- broadcast(_("Forged local address detected"));
- clamfi_cleanup(ctx);
- return SMFIS_REJECT;
- }
- }
-#endif
-
- if(clamfi_send(privdata, 1, "\n") != 1) {
- clamfi_cleanup(ctx);
- return cl_error;
- }
-
- if(black_hole_mode) {
- sfsistat rc = black_hole(privdata);
-
- if(rc != SMFIS_CONTINUE) {
- clamfi_cleanup(ctx);
- return rc;
- }
- }
-
- /*
- * See if the e-mail is only going to members of the list
- * of users we don't scan for. If it is, don't scan, otherwise
- * scan
- *
- * scan = false
- * FORALL recipients
- * IF receipient NOT MEMBER OF white address list
- * THEN
- * scan = true
- * FI
- * ENDFOR
- */
- for(to = privdata->to; *to; to++)
- if(!isWhitelisted(*to, 1))
- /*
- * This recipient is not on the whitelist,
- * no need to check any further
- */
- return SMFIS_CONTINUE;
-
- /*
- * Didn't find a recipient who is not on the white list, so all
- * must be on the white list, so just accept the e-mail
- */
- logg(_("*clamfi_enveoh: ignoring whitelisted message"));
- clamfi_cleanup(ctx);
-
- return SMFIS_ACCEPT;
-}
-
-static sfsistat
-clamfi_body(SMFICTX *ctx, u_char *bodyp, size_t len)
-{
- struct privdata *privdata = (struct privdata *)smfi_getpriv(ctx);
- int nbytes;
-
- logg(_("*clamfi_envbody: %lu bytes"), (unsigned long)len);
-
- if(len == 0) /* unlikely */
- return SMFIS_CONTINUE;
-
- if(privdata == NULL) /* sanity check */
- return cl_error;
-
- /*
- * TODO:
- * If not in external mode, call cli_scanbuff here, at least for
- * the first block
- */
- /*
- * Lines starting with From are changed to >From, to
- * avoid FP matches in the scanning code, which will speed it up
- */
- if((len >= 6) && cli_memstr((char *)bodyp, len, "\nFrom ", 6)) {
- const char *ptr = (const char *)bodyp;
- int left = len;
-
- nbytes = 0;
-
- /*
- * FIXME: sending one byte at a time down a socket is
- * inefficient
- */
- do {
- if(*ptr == '\n') {
- /*
- * FIXME: doesn't work if the \nFrom straddles
- * multiple calls to clamfi_body
- */
- if(strncmp(ptr, "\nFrom ", 6) == 0) {
- nbytes += clamfi_send(privdata, 7, "\n>From ");
- ptr += 6;
- left -= 6;
- } else {
- nbytes += clamfi_send(privdata, 1, "\n");
- ptr++;
- left--;
- }
- } else {
- nbytes += clamfi_send(privdata, 1, ptr++);
- left--;
- }
- if(left < 6 && left > 0) {
- nbytes += clamfi_send(privdata, left, ptr);
- break;
- }
- } while(left > 0);
- } else
- nbytes = clamfi_send(privdata, len, (char *)bodyp);
-
- if(streamMaxLength > 0L) {
- if(privdata->numBytes > streamMaxLength) {
- const char *sendmailId = smfi_getsymval(ctx, "i");
-
- if(sendmailId == NULL)
- sendmailId = "Unknown";
- logg(_("%s: Message more than StreamMaxLength (%ld) bytes - not scanned\n"),
- sendmailId, streamMaxLength);
- if(!nflag)
- smfi_addheader(ctx, "X-Virus-Status", _("Not Scanned - StreamMaxLength exceeded"));
-
- return SMFIS_ACCEPT; /* clamfi_close will be called */
- }
- }
- if(nbytes < (int)len) {
- clamfi_cleanup(ctx); /* not needed, but just to be safe */
- return cl_error;
- }
- if(Sflag) {
- if(privdata->body) {
- assert(privdata->bodyLen > 0);
- privdata->body = cli_realloc(privdata->body, privdata->bodyLen + len);
- memcpy(&privdata->body[privdata->bodyLen], bodyp, len);
- privdata->bodyLen += len;
- } else {
- assert(privdata->bodyLen == 0);
- privdata->body = cli_malloc(len);
- memcpy(privdata->body, bodyp, len);
- privdata->bodyLen = len;
- }
- }
- return SMFIS_CONTINUE;
-}
-
-static sfsistat
-clamfi_eom(SMFICTX *ctx)
-{
- int rc = SMFIS_CONTINUE;
- char *ptr;
- const char *sendmailId;
- struct privdata *privdata = (struct privdata *)smfi_getpriv(ctx);
- char mess[128];
-#ifdef SESSION
- struct session *session;
-#endif
-
- logg("*clamfi_eom\n");
-
-#ifdef CL_DEBUG
- assert(privdata != NULL);
-#ifndef SESSION
- assert((privdata->cmdSocket >= 0) || (privdata->filename != NULL));
- assert(!((privdata->cmdSocket >= 0) && (privdata->filename != NULL)));
-#endif
-#endif
-
- if(external) {
- shutdown(privdata->dataSocket, SHUT_WR); /* bug 487 */
- close(privdata->dataSocket);
- privdata->dataSocket = -1;
- }
-
- if(!nflag) {
- /*
- * remove any existing claims that it's virus free so that
- * downstream checkers aren't fooled by a carefully crafted
- * virus.
- */
- int i;
-
- for(i = privdata->statusCount; i > 0; --i)
- if(smfi_chgheader(ctx, "X-Virus-Status", i, NULL) == MI_FAILURE)
- logg(_("^Failed to delete X-Virus-Status header %d\n"), i);
- }
-
- if(!external) {
- const char *virname;
- int ret;
- struct cl_engine *cur_engine;
-
- pthread_mutex_lock(&engine_mutex);
- ret = cl_engine_addref(engine);
- cur_engine = engine; /* avoid races */
- pthread_mutex_unlock(&engine_mutex);
- if(ret != CL_SUCCESS) {
- logg("!cl_engine_addref failed\n");
- clamfi_cleanup(ctx);
- return cl_error;
- }
- switch(cl_scanfile(privdata->filename, &virname, NULL, cur_engine, options)) {
- case CL_CLEAN:
- if(logok)
- logg("#%s: OK\n", privdata->filename);
- strcpy(mess, "OK");
- break;
- case CL_VIRUS:
- snprintf(mess, sizeof(mess), "%s: %s FOUND", privdata->filename, virname);
- logg("#%s\n", mess);
- break;
- default:
- snprintf(mess, sizeof(mess), "%s: ERROR", privdata->filename);
- logg("!%s\n", mess);
- break;
- }
- cl_engine_free(cur_engine); /* drop reference or free */
-
-#ifdef SESSION
- session = NULL;
-#endif
- } else if(privdata->filename) {
- char cmdbuf[1024];
- /*
- * Create socket to talk to clamd.
- */
-#ifndef SESSION
- struct sockaddr_un server;
-#endif
- long nbytes;
-
- snprintf(cmdbuf, sizeof(cmdbuf) - 1, "SCAN %s", privdata->filename);
- cli_dbgmsg("clamfi_eom: SCAN %s\n", privdata->filename);
-
- nbytes = (int)strlen(cmdbuf);
-
-#ifdef SESSION
- session = sessions;
- if(send(session->sock, cmdbuf, nbytes, 0) < nbytes) {
- perror("send");
- clamfi_cleanup(ctx);
- logg(_("failed to send SCAN %s command to clamd\n"), privdata->filename);
- return cl_error;
- }
-#else
- if((privdata->cmdSocket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
- perror("socket");
- clamfi_cleanup(ctx);
- return cl_error;
- }
- memset((char *)&server, 0, sizeof(struct sockaddr_un));
- server.sun_family = AF_UNIX;
- strncpy(server.sun_path, localSocket, sizeof(server.sun_path));
- server.sun_path[sizeof(server.sun_path)-1]='\0';
-
- if(connect(privdata->cmdSocket, (struct sockaddr *)&server, sizeof(struct sockaddr_un)) < 0) {
- perror(localSocket);
- clamfi_cleanup(ctx);
- return cl_error;
- }
- if(send(privdata->cmdSocket, cmdbuf, nbytes, 0) < nbytes) {
- perror("send");
- clamfi_cleanup(ctx);
- logg(_("failed to send SCAN command to clamd\n"));
- return cl_error;
- }
-
- shutdown(privdata->cmdSocket, SHUT_WR);
-#endif
- }
-#ifdef SESSION
- else
- session = &sessions[privdata->serverNumber];
-#endif
-
- sendmailId = smfi_getsymval(ctx, "i");
- if(sendmailId == NULL)
- sendmailId = "Unknown";
-
- if(external) {
- int nbytes;
-#ifdef SESSION
-#ifdef CL_DEBUG
- if(debug_level >= 4)
- cli_dbgmsg(_("Waiting to read status from fd %d\n"),
- session->sock);
-#endif
- nbytes = clamd_recv(session->sock, mess, sizeof(mess) - 1);
-#else
- nbytes = clamd_recv(privdata->cmdSocket, mess, sizeof(mess) - 1);
-#endif
- if(nbytes > 0) {
- mess[nbytes] = '\0';
- if((ptr = strchr(mess, '\n')) != NULL)
- *ptr = '\0';
-
- logg(_("*clamfi_eom: read %s\n"), mess);
- } else {
-#ifdef MAXHOSTNAMELEN
- char hostname[MAXHOSTNAMELEN + 1];
-
- cli_strtokbuf(serverHostNames, privdata->serverNumber, ":", hostname);
- if(strcmp(hostname, "127.0.0.1") == 0)
- gethostname(hostname, sizeof(hostname));
-#else
- char *hostname = cli_strtok(serverHostNames, privdata->serverNumber, ":");
-#endif
- if(privdata->subject)
- logg(_("^%s: clamfi_eom: read nothing from clamd on %s, from %s (%s)\n"),
- sendmailId, hostname, privdata->from,
- privdata->subject);
- else
- logg(_("^%s: clamfi_eom: read nothing from clamd on %s, from %s\n"),
- sendmailId, hostname, privdata->from);
-
- if((!nflag) && (cl_error == SMFIS_ACCEPT))
- smfi_addheader(ctx, "X-Virus-Status", _("Not Scanned - Read timeout exceeded"));
-#ifndef MAXHOSTNAMELEN
- free(hostname);
-#endif
-
-#ifdef CL_DEBUG
- /*
- * Save the file which caused the timeout, for
- * debugging
- */
- if(quarantine_dir) {
- logg(_("Quarantining failed email\n"));
- qfile(privdata, sendmailId, "scanning-timeout");
- }
-#endif
-
- /*
- * TODO: if more than one host has been specified, try
- * another one - setting cl_error to SMFIS_TEMPFAIL
- * helps by forcing a retry
- */
- clamfi_cleanup(ctx);
-
-#ifdef SESSION
- pthread_mutex_lock(&sstatus_mutex);
- session->status = CMDSOCKET_DOWN;
- pthread_mutex_unlock(&sstatus_mutex);
-#endif
- return cl_error;
- }
-
-#ifdef SESSION
- pthread_mutex_lock(&sstatus_mutex);
- if(session->status == CMDSOCKET_INUSE)
- session->status = CMDSOCKET_FREE;
- pthread_mutex_unlock(&sstatus_mutex);
-#else
- close(privdata->cmdSocket);
- privdata->cmdSocket = -1;
-#endif
- }
-
- if(!nflag) {
- char buf[1024];
-
- /*
- * Include the hostname where the scan took place
- */
- if(localSocket || !external) {
-#ifdef MAXHOSTNAMELEN
- char hostname[MAXHOSTNAMELEN + 1];
-#else
- char hostname[65];
-#endif
-
- if(gethostname(hostname, sizeof(hostname)) < 0) {
- const char *j = smfi_getsymval(ctx, "{j}");
-
- if(j)
- strncpy(hostname, j, sizeof(hostname) - 1);
- else
- strcpy(hostname, _("Error determining host"));
- hostname[sizeof(hostname)-1]='\0';
- } else if(strchr(hostname, '.') == NULL) {
- /*
- * Determine fully qualified name
- */
- struct hostent hostent;
-
- if((r_gethostbyname(hostname, &hostent, buf, sizeof(buf)) == 0) && hostent.h_name) {
- strncpy(hostname, hostent.h_name, sizeof(hostname));
- hostname[sizeof(hostname)-1]='\0';
- }
- }
-
-#ifdef SESSION
- pthread_mutex_lock(&version_mutex);
- snprintf(buf, sizeof(buf) - 1, "%s on %s",
- clamav_versions[privdata->serverNumber], hostname);
- pthread_mutex_unlock(&version_mutex);
-#else
- snprintf(buf, sizeof(buf) - 1, "%s on %s",
- clamav_version, hostname);
-#endif
- } else {
-#ifdef MAXHOSTNAMELEN
- char hostname[MAXHOSTNAMELEN + 1];
-
- if(cli_strtokbuf(serverHostNames, privdata->serverNumber, ":", hostname)) {
- if(strcmp(hostname, "127.0.0.1") == 0)
- gethostname(hostname, sizeof(hostname));
-#else
- char *hostname = cli_strtok(serverHostNames, privdata->serverNumber, ":");
- if(hostname) {
-#endif
-
-#ifdef SESSION
- pthread_mutex_lock(&version_mutex);
- snprintf(buf, sizeof(buf) - 1, "%s on %s",
- clamav_versions[privdata->serverNumber], hostname);
- pthread_mutex_unlock(&version_mutex);
-#else
- snprintf(buf, sizeof(buf) - 1, "%s on %s",
- clamav_version, hostname);
-#endif
-#ifndef MAXHOSTNAMELEN
- free(hostname);
-#endif
- } else
- /* sanity check failed - should issue warning */
- strcpy(buf, _("Error determining host"));
- }
- smfi_addheader(ctx, "X-Virus-Scanned", buf);
- }
-
- /*
- * TODO: it would be useful to add a header if mbox.c/FOLLOWURLS was
- * exceeded
- */
-#ifdef HAVE_RESOLV_H
- if((strstr(mess, "FOUND") != NULL) && (strstr(mess, "Phishing") != NULL)) {
- table_t *prevhosts = tableCreate();
-
- if(spf(privdata, prevhosts)) {
- logg(_("%s: Ignoring %s false positive from %s received from %s\n"),
- sendmailId, mess, privdata->from, privdata->ip);
- strcpy(mess, "OK");
- /*
- * Report false positive to ClamAV, works best when
- * clamav-milter has had to create a local copy of
- * the email, e.g. when --quarantine-dir is on
- */
- if(report_fps &&
- (smfi_addrcpt(ctx, report_fps) == MI_FAILURE)) {
- if(privdata->filename) {
- char cmd[1024];
-
- snprintf(cmd, sizeof(cmd) - 1,
- "mail -s \"False Positive: %s\" %s < %s",
- mess, report_fps,
- privdata->filename);
- if(system(cmd) == 0)
- logg(_("#Reported phishing false positive to %s"), report_fps);
- else
- logg(_("^Couldn't report false positive to %s\n"), report_fps);
- } else
- /*
- * Most likely this is because we're
- * attempting to add a recipient on
- * another host
- */
- logg(_("^Can't set phish FP header\n"));
- }
- }
- tableDestroy(prevhosts);
- }
-#endif
- if(strstr(mess, "ERROR") != NULL) {
- if(strstr(mess, "Size limit reached") != NULL) {
- /*
- * Clamd has stopped on StreamMaxLength before us
- */
- logg(_("%s: Message more than StreamMaxLength (%ld) bytes - not scanned"),
- sendmailId, streamMaxLength);
- if(!nflag)
- smfi_addheader(ctx, "X-Virus-Status", _("Not Scanned - StreamMaxLength exceeded"));
- clamfi_cleanup(ctx); /* not needed, but just to be safe */
- return SMFIS_ACCEPT;
- }
- if(!nflag)
- smfi_addheader(ctx, "X-Virus-Status", _("Not Scanned"));
-
- logg("!%s: %s\n", sendmailId, mess);
- rc = cl_error;
- } else if((ptr = strstr(mess, "FOUND")) != NULL) {
- /*
- * FIXME: This will give false positives if the
- * word "FOUND" is in the email, e.g. the
- * quarantine directory is /tmp/VIRUSES-FOUND
- */
- int i;
- char **to, *virusname, *err;
- char reject[1024];
-
- /*
- * Remove the "FOUND" word, and the space before it
- */
- *--ptr = '\0';
-
- /* skip over 'stream/filename: ' at the start */
- if((virusname = strchr(mess, ':')) != NULL)
- virusname = &virusname[2];
- else
- virusname = mess;
-
- if(!nflag) {
- char buf[129];
-
- snprintf(buf, sizeof(buf) - 1, "%s %s", _("Infected with"), virusname);
- smfi_addheader(ctx, "X-Virus-Status", buf);
- }
-
- if(quarantine_dir)
- qfile(privdata, sendmailId, virusname);
-
- /*
- * Setup err as a list of recipients
- */
- err = (char *)cli_malloc(1024);
-
- if(err == NULL) {
- clamfi_cleanup(ctx);
- return cl_error;
- }
-
- /*
- * Use snprintf rather than printf since we don't know
- * the length of privdata->from and may get a buffer
- * overrun
- */
- snprintf(err, 1023, _("Intercepted virus from %s to"),
- privdata->from);
-
- ptr = strchr(err, '\0');
-
- i = 1024;
-
- for(to = privdata->to; *to; to++) {
- /*
- * Re-alloc if we are about run out of buffer
- * space
- *
- * TODO: Only append *to if it's a valid, local
- * email address
- */
- if(&ptr[strlen(*to) + 2] >= &err[i]) {
- i += 1024;
- err = cli_realloc(err, i);
- if(err == NULL) {
- clamfi_cleanup(ctx);
- return cl_error;
- }
- ptr = strchr(err, '\0');
- }
- ptr = cli_strrcpy(ptr, " ");
- ptr = cli_strrcpy(ptr, *to);
- }
- (void)strcpy(ptr, "\n");
-
- /* Include the sendmail queue ID in the log */
- logg("%s: %s %s", sendmailId, mess, err);
- free(err);
-
- if(!qflag) {
- char cmd[128];
- FILE *sendmail;
-
- /*
- * If the oflag is given this sendmail command
- * will cause the mail being generated here to be
- * scanned. So if oflag is given we just put the
- * item in the queue so there's no scanning of two
- * messages at once. It'll still be scanned, but
- * not at the same time as the incoming message
- *
- * FIXME: there is a race condition here when sendmail
- * and clamav-milter run on the same machine. If the
- * system is very overloaded this sendmail can
- * take a long time to start - and may even fail
- * is the LA is > REFUSE_LA. In all the time we're
- * taking to start this sendmail, the sendmail that's
- * started us may timeout waiting for a response and
- * let the virus through (albeit tagged with
- * X-Virus-Status: Infected) because we haven't
- * sent SMFIS_DISCARD or SMFIS_REJECT
- *
- * -i flag, suggested by Michal Jaegermann
- * <michal at harddata.com>
- */
- snprintf(cmd, sizeof(cmd) - 1,
- (oflag || fflag) ? "%s -t -i -odq" : "%s -t -i",
- SENDMAIL_BIN);
-
- cli_dbgmsg("Calling %s\n", cmd);
- sendmail = popen(cmd, "w");
-
- if(sendmail) {
- if(from && from[0])
- fprintf(sendmail, "From: %s\n", from);
- else
- fprintf(sendmail, "From: %s\n", privdata->from);
-#ifdef BOUNCE
- if(bflag && privdata->from) {
- fprintf(sendmail, "To: %s\n", privdata->from);
- fprintf(sendmail, "Cc: %s\n", postmaster);
- } else
-#endif
- fprintf(sendmail, "To: %s\n", postmaster);
-
- if((!pflag) && privdata->to)
- for(to = privdata->to; *to; to++)
- fprintf(sendmail, "Cc: %s\n", *to);
- /*
- * Auto-submitted is still a draft, keep an
- * eye on its format
- */
- fputs("Auto-Submitted: auto-submitted (antivirus notify)\n", sendmail);
- /* "Sergey Y. Afonin" <asy at kraft-s.ru> */
- if((ptr = smfi_getsymval(ctx, "{_}")) != NULL)
- fprintf(sendmail,
- "X-Infected-Received-From: %s\n",
- ptr);
- fputs(_("Subject: Virus intercepted\n"), sendmail);
-
- if(templateHeaders) {
- /*
- * For example, to state the character
- * set of the message:
- * Content-Type: text/plain; charset=koi8-r
- *
- * Based on a suggestion by Denis
- * Eremenko <moonshade at mail.kz>
- */
- FILE *fin = fopen(templateHeaders, "r");
-
- if(fin == NULL) {
- perror(templateHeaders);
- logg(_("!Can't open e-mail template header file %s"),
- templateHeaders);
- } else {
- int c;
- int lastc = EOF;
-
- while((c = getc(fin)) != EOF) {
- putc(c, sendmail);
- lastc = c;
- }
- fclose(fin);
- /*
- * File not new line terminated
- */
- if(lastc != '\n')
- fputs(_("\n"), sendmail);
- }
- }
-
- fputs(_("\n"), sendmail);
-
- if((templateFile == NULL) ||
- (sendtemplate(ctx, templateFile, sendmail, virusname) < 0)) {
- /*
- * Use our own hardcoded template
- */
-#ifdef BOUNCE
- if(bflag)
- fputs(_("A message you sent to\n"), sendmail);
- else if(pflag)
-#else
- if(pflag)
-#endif
- /*
- * The message is only going to
- * the postmaster, so include
- * some useful information
- */
- fprintf(sendmail, _("The message %1$s sent from %2$s to\n"),
- sendmailId, privdata->from);
- else
- fprintf(sendmail, _("A message sent from %s to\n"),
- privdata->from);
-
- for(to = privdata->to; *to; to++)
- fprintf(sendmail, "\t%s\n", *to);
- fprintf(sendmail, _("contained %s and has not been accepted for delivery.\n"), virusname);
-
- if(quarantine_dir != NULL)
- fprintf(sendmail, _("\nThe message in question has been quarantined as %s\n"), privdata->filename);
-
- if(hflag) {
- fprintf(sendmail, _("\nThe message was received by %1$s from %2$s via %3$s\n\n"),
- smfi_getsymval(ctx, "j"), privdata->from,
- smfi_getsymval(ctx, "_"));
- fputs(_("For your information, the original message headers were:\n\n"), sendmail);
- header_list_print(privdata->headers, sendmail);
- } else if(privdata->received)
- /*
- * TODO: parse this to find
- * real infected machine.
- * Need to decide how to find
- * if it's a dynamic IP from a
- * dial up account in which
- * case there may not be much
- * we can do if that DHCP has
- * set the hostname...
- */
- fprintf(sendmail, _("\nThe infected machine is likely to be here:\n%s\t\n"),
- privdata->received);
-
- }
-
- cli_dbgmsg("Waiting for %s to finish\n", cmd);
- if(pclose(sendmail) != 0)
- logg(_("%s: Failed to notify clamAV interception - see dead.letter\n"), sendmailId);
- } else
- logg(_("^Can't execute '%s' to send virus notice"), cmd);
- }
-
- if(report && (quarantine == NULL) && (!advisory) &&
- (strstr(virusname, "Phishing") != NULL)) {
- /*
- * Report phishing to an agency
- */
- for(to = privdata->to; *to; to++) {
- smfi_delrcpt(ctx, *to);
- smfi_addheader(ctx, "X-Original-To", *to);
- }
- if(smfi_addrcpt(ctx, report) == MI_FAILURE) {
- /* It's a remote site */
- if(privdata->filename) {
- char cmd[1024];
-
- snprintf(cmd, sizeof(cmd) - 1,
- "mail -s \"%s\" %s < %s",
- virusname, report,
- privdata->filename);
- if(system(cmd) == 0)
- logg(_("#Reported phishing to %s"), report);
- else
- logg(_("^Couldn't report to %s\n"), report);
- if((!rejectmail) || privdata->discard)
- rc = SMFIS_DISCARD;
- else
- rc = SMFIS_REJECT;
- } else {
- logg(_("^Can't set anti-phish header\n"));
- rc = (privdata->discard) ? SMFIS_DISCARD : SMFIS_REJECT;
- }
- } else {
- setsubject(ctx, "Phishing attempt trapped by ClamAV and redirected");
-
- logg("Redirected phish to %s\n", report);
- }
- } else if(quarantine) {
- for(to = privdata->to; *to; to++) {
- smfi_delrcpt(ctx, *to);
- smfi_addheader(ctx, "X-Original-To", *to);
- }
- /*
- * NOTE: on a closed relay this will not work
- * if the recipient is a remote address
- */
- if(smfi_addrcpt(ctx, quarantine) == MI_FAILURE) {
- logg(_("^Can't set quarantine user %s"), quarantine);
- rc = (privdata->discard) ? SMFIS_DISCARD : SMFIS_REJECT;
- } else {
- if(report &&
- strstr(virusname, "Phishing") != NULL)
- (void)smfi_addrcpt(ctx, report);
- setsubject(ctx, virusname);
-
- logg("Redirected virus to %s", quarantine);
- }
- } else if(advisory)
- setsubject(ctx, virusname);
- else if(rejectmail) {
- if(privdata->discard)
- rc = SMFIS_DISCARD;
- else
- rc = SMFIS_REJECT; /* Delete the e-mail */
- } else
- rc = SMFIS_DISCARD;
-
- if(quarantine_dir) {
- /*
- * Cleanup filename here otherwise clamfi_free() will
- * delete the file that we wish to keep because it
- * is infected
- */
- free(privdata->filename);
- privdata->filename = NULL;
- }
-
- /*
- * Don't drop the message if it's been forwarded to a
- * quarantine email
- */
- snprintf(reject, sizeof(reject) - 1, _("virus %s detected by ClamAV - http://www.clamav.net"), virusname);
- smfi_setreply(ctx, (const char *)privdata->rejectCode, "5.7.1", reject);
- broadcast(mess);
-
- if(blacklist_time && privdata->ip[0]) {
- logg(_("Will blacklist %s for %d seconds because of %s\n"),
- privdata->ip, blacklist_time, virusname);
- pthread_mutex_lock(&blacklist_mutex);
- (void)tableUpdate(blacklist, privdata->ip,
- (int)time((time_t *)0));
- pthread_mutex_unlock(&blacklist_mutex);
- }
- } else if((strstr(mess, "OK") == NULL) && (strstr(mess, "Empty file") == NULL)) {
- if(!nflag)
- smfi_addheader(ctx, "X-Virus-Status", _("Unknown"));
- logg(_("!%s: incorrect message \"%s\" from clamd"),
- sendmailId, mess);
- rc = cl_error;
- } else {
- if(!nflag)
- smfi_addheader(ctx, "X-Virus-Status", _("Clean"));
-
- /* Include the sendmail queue ID in the log */
- if(logok)
- logg(_("%s: clean message from %s\n"),
- sendmailId,
- (privdata->from) ? privdata->from : _("an unknown sender"));
-
- if(privdata->body) {
- /*
- * Add a signature that all has been scanned OK
- *
- * Note that this is simple minded and isn't aware of
- * any MIME segments in the message. In practice
- * this means that the message will only display
- * on users' terminals if the message is
- * plain/text
- */
- off_t len = updateSigFile();
-
- if(len) {
- assert(Sflag != 0);
-
- privdata->body = cli_realloc(privdata->body, privdata->bodyLen + len);
- if(privdata->body) {
- memcpy(&privdata->body[privdata->bodyLen], signature, len);
- smfi_replacebody(ctx, privdata->body, privdata->bodyLen + len);
- }
- }
- }
- }
-
- return rc;
-}
-
-static sfsistat
-clamfi_abort(SMFICTX *ctx)
-{
- logg("*clamfi_abort\n");
-
- clamfi_cleanup(ctx);
- decrement_connexions();
-
- logg("*clamfi_abort returns\n");
-
- return cl_error;
-}
-
-static sfsistat
-clamfi_close(SMFICTX *ctx)
-{
- logg("*clamfi_close\n");
-
- clamfi_cleanup(ctx);
- decrement_connexions();
-
- return SMFIS_CONTINUE;
-}
-
-static void
-clamfi_cleanup(SMFICTX *ctx)
-{
- struct privdata *privdata = (struct privdata *)smfi_getpriv(ctx);
-
- cli_dbgmsg("clamfi_cleanup\n");
-
- if(privdata) {
- clamfi_free(privdata, 0);
- smfi_setpriv(ctx, NULL);
- }
-}
-
-static void
-clamfi_free(struct privdata *privdata, int keep)
-{
- cli_dbgmsg("clamfi_free\n");
-
- if(privdata) {
-#ifdef SESSION
- struct session *session;
-#endif
- if(privdata->body)
- free(privdata->body);
-
- if(privdata->dataSocket >= 0)
- close(privdata->dataSocket);
-
- if(privdata->filename != NULL) {
- /*
- * Don't print an error if the file hasn't been
- * created yet
- */
- if((unlink(privdata->filename) < 0) && (errno != ENOENT)) {
- perror(privdata->filename);
- logg(_("!Can't remove clean file %s"),
- privdata->filename);
- }
- free(privdata->filename);
- }
-
- if(privdata->from) {
-#ifdef CL_DEBUG
- if(debug_level >= 9)
- cli_dbgmsg("Free privdata->from\n");
-#endif
- free(privdata->from);
- }
-
- if(privdata->subject)
- free(privdata->subject);
- if(privdata->sender)
- free(privdata->sender);
-
- if(privdata->to) {
- char **to;
-
- for(to = privdata->to; *to; to++) {
-#ifdef CL_DEBUG
- if(debug_level >= 9)
- cli_dbgmsg("Free *privdata->to\n");
-#endif
- free(*to);
- }
-#ifdef CL_DEBUG
- if(debug_level >= 9)
- cli_dbgmsg("Free privdata->to\n");
-#endif
- free(privdata->to);
- }
-
- if(external) {
-#ifdef SESSION
- session = &sessions[privdata->serverNumber];
- pthread_mutex_lock(&sstatus_mutex);
- if(session->status == CMDSOCKET_INUSE) {
- /*
- * Probably we've got here because
- * StreamMaxLength has been reached
- */
-#if 0
- pthread_mutex_unlock(&sstatus_mutex);
- if(readTimeout) {
- char buf[64];
- const int fd = session->sock;
-
- cli_dbgmsg("clamfi_free: flush server %d fd %d\n",
- privdata->serverNumber, fd);
-
- /*
- * FIXME: whenever this code gets
- * executed, all of the PINGs fail
- * in the next watchdog cycle
- */
- while(clamd_recv(fd, buf, sizeof(buf)) > 0)
- ;
- }
- pthread_mutex_lock(&sstatus_mutex);
-#endif
- /* Force a reset */
- session->status = CMDSOCKET_DOWN;
- }
- pthread_mutex_unlock(&sstatus_mutex);
-#else
- if(privdata->cmdSocket >= 0) {
-#if 0
- char buf[64];
-
- /*
- * Flush the remote end so that clamd doesn't
- * get a SIGPIPE
- */
- if(readTimeout)
- while(clamd_recv(privdata->cmdSocket, buf, sizeof(buf)) > 0)
- ;
-#endif
- close(privdata->cmdSocket);
- }
-#endif
- }
-
- if(privdata->headers)
- header_list_free(privdata->headers);
-
-#ifdef CL_DEBUG
- if(debug_level >= 9)
- cli_dbgmsg("Free privdata\n");
-#endif
- if(privdata->received)
- free(privdata->received);
-
- if(keep) {
- memset(privdata, '\0', sizeof(struct privdata));
-#ifdef SESSION
- privdata->dataSocket = -1;
-#else
- privdata->dataSocket = privdata->cmdSocket = -1;
-#endif
- } else
- free(privdata);
- }
-
- cli_dbgmsg("clamfi_free returns\n");
-}
-
-/*
- * Returns < 0 for failure, otherwise the number of bytes sent
- */
-static int
-clamfi_send(struct privdata *privdata, size_t len, const char *format, ...)
-{
- char output[BUFSIZ];
- const char *ptr;
- int ret = 0;
- assert(format != NULL);
-
- if(len > 0)
- /*
- * It isn't a NUL terminated string. We have a set number of
- * bytes to output.
- */
- ptr = format;
- else {
- va_list argp;
-
- va_start(argp, format);
- vsnprintf(output, sizeof(output) - 1, format, argp);
- va_end(argp);
-
- len = strlen(output);
- ptr = output;
- }
-#ifdef CL_DEBUG
- if(debug_level >= 9) {
- time_t t;
- const struct tm *tm;
-
- time(&t);
- tm = localtime(&t);
-
- cli_dbgmsg("%d:%d:%d clamfi_send: len=%u bufsiz=%u, fd=%d\n",
- tm->tm_hour, tm->tm_min, tm->tm_sec, len,
- sizeof(output), privdata->dataSocket);
- }
-#endif
-
- while(len > 0) {
- const int nbytes = (privdata->filename) ?
- write(privdata->dataSocket, ptr, len) :
- send(privdata->dataSocket, ptr, len, 0);
-
- assert(privdata->dataSocket >= 0);
-
- if(nbytes == -1) {
- if(privdata->filename) {
-#ifdef HAVE_STRERROR_R
- char buf[32];
-
- perror(privdata->filename);
- strerror_r(errno, buf, sizeof(buf));
- logg(_("!write failure (%lu bytes) to %s: %s\n"),
- (unsigned long)len, privdata->filename, buf);
-#else
- perror(privdata->filename);
- logg(_("!write failure (%lu bytes) to %s: %s\n"),
- (unsigned long)len, privdata->filename,
- strerror(errno));
-#endif
- } else {
- if(errno == EINTR)
- continue;
- perror("send");
-#ifdef HAVE_STRERROR_R
- {
- char buf[32];
- strerror_r(errno, buf, sizeof(buf));
- logg(_("!write failure (%lu bytes) to clamd: %s\n"),
- (unsigned long)len, buf);
- }
-#else
- logg(_("!write failure (%lu bytes) to clamd: %s\n"),
- (unsigned long)len, strerror(errno));
-#endif
- checkClamd(1);
- }
-
- return -1;
- }
- ret += nbytes;
- len -= nbytes;
- ptr = &ptr[nbytes];
-
- if(streamMaxLength > 0L) {
- privdata->numBytes += nbytes;
- if(privdata->numBytes >= streamMaxLength)
- break;
- }
- }
- return ret;
-}
-
-/*
- * Like strcpy, but return the END of the destination, allowing a quicker
- * means of adding to the end of a string than strcat
- */
-#if 0
-static char *
-strrcpy(char *dest, const char *source)
-{
- /* Pre assertions */
- assert(dest != NULL);
- assert(source != NULL);
- assert(dest != source);
-
- while((*dest++ = *source++) != '\0')
- ;
- return(--dest);
-}
-#endif
-
-/*
- * Read from clamav - timeout if necessary
- */
-static long
-clamd_recv(int sock, char *buf, size_t len)
-{
- struct timeval tv;
- long ret;
-
- assert(sock >= 0);
-
- if(readTimeout == 0) {
- do
- /* TODO: Needs a test for ssize_t in configure */
- ret = (long)recv(sock, buf, len, 0);
- while((ret < 0) && (errno == EINTR));
-
- return ret;
- }
-
- tv.tv_sec = readTimeout;
- tv.tv_usec = 0;
-
- for(;;) {
- fd_set rfds;
-
- FD_ZERO(&rfds);
- FD_SET(sock, &rfds);
-
- switch(select(sock + 1, &rfds, NULL, NULL, &tv)) {
- case -1:
- if(errno == EINTR)
- /* FIXME: work out time left */
- continue;
- perror("select");
- return -1;
- case 0:
- logg(_("!No data received from clamd in %d seconds\n"), readTimeout);
- return 0;
- }
- break;
- }
-
- do
- ret = recv(sock, buf, len, 0);
- while((ret < 0) && (errno == EINTR));
-
- return ret;
-}
-
-/*
- * Read in the signature file
- */
-static off_t
-updateSigFile(void)
-{
- struct stat statb;
- int fd;
-
- if(sigFilename == NULL)
- /* nothing to read */
- return 0;
-
- if(stat(sigFilename, &statb) < 0) {
- perror(sigFilename);
- logg(_("Can't stat %s"), sigFilename);
- return 0;
- }
-
- if(statb.st_mtime <= signatureStamp)
- return statb.st_size; /* not changed */
-
- fd = open(sigFilename, O_RDONLY);
- if(fd < 0) {
- perror(sigFilename);
- logg(_("Can't open %s"), sigFilename);
- return 0;
- }
-
- signatureStamp = statb.st_mtime;
-
- signature = cli_realloc((void *)signature, statb.st_size);
- if(signature)
- cli_readn(fd, (void *)signature, statb.st_size);
- close(fd);
-
- return statb.st_size;
-}
-
-static header_list_t
-header_list_new(void)
-{
- header_list_t ret;
-
- ret = (header_list_t)cli_malloc(sizeof(struct header_list_struct));
- if(ret) {
- ret->first = NULL;
- ret->last = NULL;
- }
- return ret;
-}
-
-static void
-header_list_free(header_list_t list)
-{
- struct header_node_t *iter;
-
- if(list == NULL)
- return;
-
- iter = list->first;
- while(iter) {
- struct header_node_t *iter2 = iter->next;
- free(iter->header);
- free(iter);
- iter = iter2;
- }
- free(list);
-}
-
-static void
-header_list_add(header_list_t list, const char *headerf, const char *headerv)
-{
- char *header;
- size_t len;
- struct header_node_t *new_node;
-
- if(list == NULL)
- return;
-
- len = (size_t)(strlen(headerf) + strlen(headerv) + 3);
-
- header = (char *)cli_malloc(len);
- if(header == NULL)
- return;
-
- sprintf(header, "%s: %s", headerf, headerv);
- new_node = (struct header_node_t *)cli_malloc(sizeof(struct header_node_t));
- if(new_node == NULL) {
- free(header);
- return;
- }
- new_node->header = header;
- new_node->next = NULL;
- if(list->first == NULL)
- list->first = new_node;
- if(list->last)
- list->last->next = new_node;
-
- list->last = new_node;
-}
-
-static void
-header_list_print(const header_list_t list, FILE *fp)
-{
- const struct header_node_t *iter;
-
- if(list == NULL)
- return;
-
- for(iter = list->first; iter; iter = iter->next) {
- if(strncmp(iter->header, "From ", 5) == 0)
- putc('>', fp);
- fprintf(fp, "%s\n", iter->header);
- }
-}
-
-/*
- * Establish a connexion to clamd
- * Returns success (1) or failure (0)
- */
-static int
-connect2clamd(struct privdata *privdata)
-{
- assert(privdata != NULL);
- assert(privdata->dataSocket == -1);
- assert(privdata->from != NULL);
- assert(privdata->to != NULL);
-
- logg("*connect2clamd\n");
-
- if(quarantine_dir || tmpdir) { /* store message in a temporary file */
- int ntries = 5;
- const char *dir = (tmpdir) ? tmpdir : quarantine_dir;
-
- /*
- * TODO: investigate mkdtemp on LINUX and possibly others
- */
-#ifdef C_AIX
- /*
- * Patch by Andy Feldt <feldt at nhn.ou.edu>, AIX 5.2 sets errno
- * to ENOENT often and sometimes sets errno to 0 (after a
- * database reload) for the mkdir call
- */
- if((mkdir(dir, 0700) < 0) && (errno != EEXIST) && (errno > 0) &&
- (errno != ENOENT)) {
-#else
- if((mkdir(dir, 0700) < 0) && (errno != EEXIST)) {
-#endif
- perror(dir);
- logg(_("mkdir %s failed"), dir);
- return 0;
- }
- privdata->filename = (char *)cli_malloc(strlen(dir) + 12);
-
- if(privdata->filename == NULL)
- return 0;
-
- do {
- sprintf(privdata->filename, "%s/msg.XXXXXX", dir);
-#if defined(C_LINUX) || defined(C_BSD) || defined(HAVE_MKSTEMP) || defined(C_SOLARIS)
- privdata->dataSocket = mkstemp(privdata->filename);
-#else
- if(mktemp(privdata->filename) == NULL) {
- logg(_("mktemp %s failed"), privdata->filename);
- return 0;
- }
- privdata->dataSocket = open(privdata->filename, O_CREAT|O_EXCL|O_WRONLY|O_TRUNC, 0600);
-#endif
- } while((--ntries > 0) && (privdata->dataSocket < 0));
-
- if(privdata->dataSocket < 0) {
- perror(privdata->filename);
- logg(_("Temporary quarantine file %s creation failed"),
- privdata->filename);
- free(privdata->filename);
- privdata->filename = NULL;
- return 0;
- }
- privdata->serverNumber = 0;
- cli_dbgmsg("Saving message to %s to scan later\n", privdata->filename);
- } else { /* communicate to clamd */
- int freeServer, nbytes;
- in_port_t p;
- struct sockaddr_in reply;
- char buf[64];
-
-#ifdef SESSION
- struct session *session;
-#else
- assert(privdata->cmdSocket == -1);
-#endif
-
- /*
- * Create socket to talk to clamd. It will tell us the port to
- * use to send the data. That will require another socket.
- */
- if(localSocket) {
-#ifndef SESSION
- struct sockaddr_un server;
-
- memset((char *)&server, 0, sizeof(struct sockaddr_un));
- server.sun_family = AF_UNIX;
- strncpy(server.sun_path, localSocket, sizeof(server.sun_path));
- server.sun_path[sizeof(server.sun_path)-1]='\0';
-
- if((privdata->cmdSocket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
- perror("socket");
- return 0;
- }
- if(connect(privdata->cmdSocket, (struct sockaddr *)&server, sizeof(struct sockaddr_un)) < 0) {
- perror(localSocket);
- return 0;
- }
- privdata->serverNumber = 0;
-#endif
- freeServer = 0;
- } else { /* TCP/IP */
-#ifdef SESSION
- freeServer = findServer();
- if(freeServer < 0)
- return 0;
- assert(freeServer < (int)max_children);
-#else
- struct sockaddr_in server;
-
- memset((char *)&server, 0, sizeof(struct sockaddr_in));
- server.sin_family = AF_INET;
- server.sin_port = (in_port_t)htons(tcpSocket);
-
- assert(serverIPs != NULL);
-
- freeServer = findServer();
- if(freeServer < 0)
- return 0;
- assert(freeServer < (int)numServers);
-
- server.sin_addr.s_addr = serverIPs[freeServer];
-
- if((privdata->cmdSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- perror("socket");
- return 0;
- }
- if(connect(privdata->cmdSocket, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) < 0) {
- char *hostname = cli_strtok(serverHostNames, freeServer, ":");
-
- perror(hostname ? hostname : "connect");
- close(privdata->cmdSocket);
- privdata->cmdSocket = -1;
- if(hostname)
- free(hostname);
- time(&last_failed_pings[freeServer]);
- return 0;
- }
- last_failed_pings[freeServer] = (time_t)0;
-#endif
- privdata->serverNumber = freeServer;
- }
-
-#ifdef SESSION
- if(serverIPs[freeServer] == (int)inet_addr("127.0.0.1")) {
- privdata->filename = cli_gentemp(NULL);
- if(privdata->filename) {
- cli_dbgmsg("connect2clamd(%d): creating %s\n", freeServer, privdata->filename);
-#ifdef O_TEXT
- privdata->dataSocket = open(privdata->filename, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC|O_TEXT, 0600);
-#else
- privdata->dataSocket = open(privdata->filename, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
-#endif
- if(privdata->dataSocket < 0) {
- perror(privdata->filename);
- free(privdata->filename);
- privdata->filename = NULL;
- } else
- return sendToFrom(privdata);
- }
- }
- cli_dbgmsg("connect2clamd(%d): STREAM\n", freeServer);
-
- session = &sessions[freeServer];
- if((session->sock < 0) || (send(session->sock, "STREAM\n", 7, 0) < 7)) {
- perror("send");
- pthread_mutex_lock(&sstatus_mutex);
- session->status = CMDSOCKET_DOWN;
- pthread_mutex_unlock(&sstatus_mutex);
- logg(_("!failed to send STREAM command clamd server %d"),
- freeServer);
-
- return 0;
- }
-#else
- if(send(privdata->cmdSocket, "STREAM\n", 7, 0) < 7) {
- perror("send");
- logg(_("!failed to send STREAM command clamd"));
- return 0;
- }
- shutdown(privdata->cmdSocket, SHUT_WR);
-#endif
-
- /*
- * Create socket that we'll use to send the data to clamd
- */
- if((privdata->dataSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- perror("socket");
- logg(_("!failed to create TCPSocket to talk to clamd\n"));
- return 0;
- }
-
- shutdown(privdata->dataSocket, SHUT_RD);
-
-#ifdef SESSION
- nbytes = clamd_recv(session->sock, buf, sizeof(buf));
- if(nbytes <= 0) {
- if(nbytes < 0) {
- perror("recv");
- logg(_("!recv failed from clamd getting PORT\n"));
- } else
- logg(_("!EOF from clamd getting PORT\n"));
-
- pthread_mutex_lock(&sstatus_mutex);
- session->status = CMDSOCKET_DOWN;
- return pthread_mutex_unlock(&sstatus_mutex);
- }
-#else
- nbytes = clamd_recv(privdata->cmdSocket, buf, sizeof(buf));
- if(nbytes <= 0) {
- if(nbytes < 0) {
- perror("recv");
- logg(_("!recv failed from clamd getting PORT\n"));
- } else
- logg(_("!EOF from clamd getting PORT\n"));
-
- return 0;
- }
-#endif
- buf[nbytes] = '\0';
-#ifdef CL_DEBUG
- if(debug_level >= 4)
- cli_dbgmsg("Received: %s\n", buf);
-#endif
- if(sscanf(buf, "PORT %hu\n", &p) != 1) {
- logg(_("!Expected port information from clamd, got '%s'\n"),
- buf);
-#ifdef SESSION
- session->status = CMDSOCKET_DOWN;
- pthread_mutex_unlock(&sstatus_mutex);
-#endif
- return 0;
- }
-
- memset((char *)&reply, 0, sizeof(struct sockaddr_in));
- reply.sin_family = AF_INET;
- reply.sin_port = (in_port_t)htons(p);
-
- assert(serverIPs != NULL);
-
- reply.sin_addr.s_addr = serverIPs[freeServer];
-
-#ifdef CL_DEBUG
- if(debug_level >= 4)
-#ifdef SESSION
- cli_dbgmsg(_("Connecting to local port %d - data %d cmd %d\n"),
- p, privdata->dataSocket, session->sock);
-#else
- cli_dbgmsg(_("Connecting to local port %d - data %d cmd %d\n"),
- p, privdata->dataSocket, privdata->cmdSocket);
-#endif
-#endif
-
- if(connect(privdata->dataSocket, (struct sockaddr *)&reply, sizeof(struct sockaddr_in)) < 0) {
- perror("connect");
-
- cli_dbgmsg("Failed to connect to port %d given by clamd\n",
- p);
- /* 0.4 - use better error message */
-#ifdef HAVE_STRERROR_R
- strerror_r(errno, buf, sizeof(buf));
- logg(_("!Failed to connect to port %d given by clamd: %s"),
- p, buf);
-#else
- logg(_("!Failed to connect to port %d given by clamd: %s"), p, strerror(errno));
-#endif
-#ifdef SESSION
- pthread_mutex_lock(&sstatus_mutex);
- session->status = CMDSOCKET_DOWN;
- pthread_mutex_unlock(&sstatus_mutex);
-#endif
- return 0;
- }
- }
-
- if(!sendToFrom(privdata))
- return 0;
-
- cli_dbgmsg("connect2clamd: serverNumber = %d\n", privdata->serverNumber);
-
- return 1;
-}
-
-/*
- * Combine the To and From into one clamfi_send to save bandwidth
- * when sending using TCP/IP to connect to a remote clamd, by band
- * width here I mean number of packets
- */
-static int
-sendToFrom(struct privdata *privdata)
-{
- char **to;
- char *msg;
- int length;
-
- length = strlen(privdata->from) + 34;
- for(to = privdata->to; *to; to++)
- length += strlen(*to) + 5;
-
- msg = cli_malloc(length + 1);
-
- if(msg) {
- sprintf(msg, "Received: by clamav-milter\nFrom: %s\n",
- privdata->from);
-
- for(to = privdata->to; *to; to++) {
- char *eom = strchr(msg, '\0');
-
- sprintf(eom, "To: %s\n", *to);
- }
- if(clamfi_send(privdata, length, msg) != length) {
- free(msg);
- return 0;
- }
- free(msg);
- } else {
- if(clamfi_send(privdata, 0,
- "Received: by clamav-milter\nFrom: %s\n",
- privdata->from) <= 0)
- return 0;
-
- for(to = privdata->to; *to; to++)
- if(clamfi_send(privdata, 0, "To: %s\n", *to) <= 0)
- return 0;
- }
-
- return 1;
-}
-
-/*
- * If possible, check if clamd has died, and, if requested, report if it has
- * Returns true if OK or unknown, otherwise false
- */
-static int
-checkClamd(int log_result)
-{
- pid_t pid;
- int fd, nbytes;
- char buf[9];
-
- if(!localSocket) {
- /* communicating via TCP, is one of the servers localhost? */
- int i, onlocal;
-
- onlocal = 0;
- for(i = 0; i < numServers; i++)
-#ifdef INADDR_LOOPBACK
- if(serverIPs[0] == htonl(INADDR_LOOPBACK)) {
-#else
- if(serverIPs[0] == inet_addr("127.0.0.1")) {
-#endif
- onlocal = 1;
- break;
- }
-
- if(!onlocal) {
- /* No local clamd, use pingServer() to tell */
- for(i = 0; i < numServers; i++)
- if(serverIPs[i] && pingServer(i))
- return 1;
- if(log_result)
- logg(_("!Can't find any clamd server\n"));
- return 0;
- }
- }
-
- if(pidFile == NULL)
- return 1; /* PidFile directive missing from clamd.conf */
-
- fd = open(pidFile, O_RDONLY);
- if(fd < 0) {
- if(log_result) {
- perror(pidFile);
- logg(_("!Can't open %s\n"), pidFile);
- }
- return 1; /* unknown */
- }
- nbytes = read(fd, buf, sizeof(buf) - 1);
- if(nbytes < 0)
- perror(pidFile);
- else
- buf[nbytes] = '\0';
- close(fd);
- pid = atoi(buf);
- if((kill(pid, 0) < 0) && (errno == ESRCH)) {
- if(log_result) {
- perror("clamd");
- logg(_("!Clamd (pid %d) seems to have died\n"), (int)pid);
- }
- return 0; /* down */
- }
- return 1; /* up */
-}
-
-/*
- * Send a templated message about an intercepted message. Very basic for
- * now, just to prove it works, will enhance the flexability later, only
- * supports %v and $sendmail_variables$ at present.
- *
- * TODO: more template features
- * TODO: allow filename to start with a '|' taken to mean the output of
- * a program
- */
-static int
-sendtemplate(SMFICTX *ctx, const char *filename, FILE *sendmail, const char *virusname)
-{
- FILE *fin = fopen(filename, "r");
- struct stat statb;
- char *buf, *ptr /* , *ptr2 */;
- struct privdata *privdata = (struct privdata *)smfi_getpriv(ctx);
-
- if(fin == NULL) {
- perror(filename);
- logg(_("!Can't open e-mail template file %s"), filename);
- return -1;
- }
-
- if(fstat(fileno(fin), &statb) < 0) {
- /* File disappeared in race condition? */
- perror(filename);
- logg(_("!Can't stat e-mail template file %s"), filename);
- fclose(fin);
- return -1;
- }
- buf = cli_malloc(statb.st_size + 1);
- if(buf == NULL) {
- fclose(fin);
- logg(_("!Out of memory"));
- return -1;
- }
- if(fread(buf, sizeof(char), statb.st_size, fin) != (size_t)statb.st_size) {
- perror(filename);
- logg(_("!Error reading e-mail template file %s"),
- filename);
- fclose(fin);
- free(buf);
- return -1;
- }
- fclose(fin);
- buf[statb.st_size] = '\0';
-
- for(ptr = buf; *ptr; ptr++)
- switch(*ptr) {
- case '%': /* clamAV variable */
- switch(*++ptr) {
- case 'v': /* virus name */
- fputs(virusname, sendmail);
- break;
- case '%':
- putc('%', sendmail);
- break;
- case 'h': /* headers */
- if(privdata)
- header_list_print(privdata->headers, sendmail);
- break;
- case '\0':
- putc('%', sendmail);
- --ptr;
- continue;
- default:
- logg(_("!%s: Unknown clamAV variable \"%c\"\n"),
- filename, *ptr);
- break;
- }
- break;
- case '$': /* sendmail string */ {
- const char *val;
- char *end = strchr(++ptr, '$');
-
- if(end == NULL) {
- logg(_("!%s: Unterminated sendmail variable \"%s\"\n"),
- filename, ptr);
- continue;
- }
- *end = '\0';
-
- val = smfi_getsymval(ctx, ptr);
- if(val == NULL) {
- fputs(ptr, sendmail);
- logg(_("!%s: Unknown sendmail variable \"%s\"\n"),
- filename, ptr);
- } else
- fputs(val, sendmail);
- ptr = end;
- break;
- }
- case '\\':
- if(*++ptr == '\0') {
- --ptr;
- continue;
- }
- putc(*ptr, sendmail);
- break;
- default:
- putc(*ptr, sendmail);
- }
-
- free(buf);
-
- return 0;
-}
-
-/*
- * Keep the infected file in quarantine, return success (0) or failure
- *
- * It's quicker if the quarantine directory is on the same filesystem
- * as the temporary directory
- */
-static int
-qfile(struct privdata *privdata, const char *sendmailId, const char *virusname)
-{
- int MM, YY, DD;
- time_t t;
- size_t len;
- char *newname, *ptr;
- const struct tm *tm;
-
- assert(privdata != NULL);
-
- if((privdata->filename == NULL) || (virusname == NULL))
- return -1;
-
- cli_dbgmsg("qfile filename '%s' sendmailId '%s' virusname '%s'\n", privdata->filename, sendmailId, virusname);
-
- len = strlen(quarantine_dir);
-
- newname = cli_malloc(len + strlen(sendmailId) + strlen(virusname) + 10);
-
- if(newname == NULL)
- return -1;
-
- t = time((time_t *)0);
- tm = localtime(&t);
- MM = tm->tm_mon + 1;
- YY = tm->tm_year - 100;
- DD = tm->tm_mday;
-
- sprintf(newname, "%s/%02d%02d%02d", quarantine_dir, YY, MM, DD);
-#ifdef C_AIX
- if((mkdir(newname, 0700) < 0) && (errno != EEXIST) && (errno > 0) &&
- (errno != ENOENT)) {
-#else
- if((mkdir(newname, 0700) < 0) && (errno != EEXIST)) {
-#endif
- perror(newname);
- logg(_("!mkdir %s failed\n"), newname);
- return -1;
- }
- sprintf(newname, "%s/%02d%02d%02d/%s.%s",
- quarantine_dir, YY, MM, DD, sendmailId, virusname);
-
- /*
- * Strip out funnies that may be in the name of the virus, such as '/'
- * that would cause the quarantine to fail to save since the name
- * of the virus is included in the filename
- */
- for(ptr = &newname[len + 8]; *ptr; ptr++) {
-#ifdef C_DARWIN
- *ptr &= '\177';
-#endif
-#if defined(MSDOS) || defined(C_WINDOWS) || defined(C_OS2)
- if(strchr("/*?<>|\\\"+=,;:\t ", *ptr))
-#else
- if(*ptr == '/')
-#endif
- *ptr = '_';
- }
- cli_dbgmsg("qfile move '%s' to '%s'\n", privdata->filename, newname);
-
- if(move(privdata->filename, newname) < 0) {
- logg(_("^Can't rename %1$s to %2$s\n"),
- privdata->filename, newname);
- free(newname);
- return -1;
- }
- free(privdata->filename);
- privdata->filename = newname;
-
- logg(_("Email quarantined as %s\n"), newname);
-
- return 0;
-}
-
-/*
- * Move oldfile to newfile using the fastest possible method
- */
-static int
-move(const char *oldfile, const char *newfile)
-{
- int ret, c;
- FILE *fin, *fout;
-#ifdef C_LINUX
- struct stat statb;
- int in, out;
- off_t offset;
-#endif
-
- ret = rename(oldfile, newfile);
- if(ret >= 0)
- return 0;
-
- if((ret < 0) && (errno != EXDEV)) {
- perror(newfile);
- return -1;
- }
-
-#ifdef C_LINUX /* >= 2.2 */
- in = open(oldfile, O_RDONLY);
- if(in < 0) {
- perror(oldfile);
- return -1;
- }
-
- if(fstat(in, &statb) < 0) {
- perror(oldfile);
- close(in);
- return -1;
- }
- out = open(newfile, O_WRONLY|O_CREAT, 0600);
- if(out < 0) {
- perror(newfile);
- close(in);
- return -1;
- }
- offset = (off_t)0;
- ret = sendfile(out, in, &offset, statb.st_size);
- close(in);
- if(ret < 0) {
- /*
- * Fall back if sendfile fails, which will happen on Linux
- * 2.6 :-(. FreeBSD works correctly, so the ifdef should be
- * fixed
- */
- close(out);
- unlink(newfile);
-
- fin = fopen(oldfile, "r");
- if(fin == NULL)
- return -1;
-
- fout = fopen(newfile, "w");
- if(fout == NULL) {
- fclose(fin);
- return -1;
- }
- while((c = getc(fin)) != EOF)
- putc(c, fout);
-
- fclose(fin);
- fclose(fout);
- } else
- close(out);
-#else
- fin = fopen(oldfile, "r");
- if(fin == NULL)
- return -1;
-
- fout = fopen(newfile, "w");
- if(fout == NULL) {
- fclose(fin);
- return -1;
- }
- while((c = getc(fin)) != EOF)
- putc(c, fout);
-
- fclose(fin);
- fclose(fout);
-#endif
-
- cli_dbgmsg("removing %s\n", oldfile);
-
- return unlink(oldfile);
-}
-
-/*
- * Store the name of the virus in the subject of the e-mail
- */
-static void
-setsubject(SMFICTX *ctx, const char *virusname)
-{
- struct privdata *privdata = (struct privdata *)smfi_getpriv(ctx);
- char subject[128];
-
- if(privdata->subject)
- smfi_addheader(ctx, "X-Original-Subject", privdata->subject);
-
- snprintf(subject, sizeof(subject) - 1, _("[Virus] %s"), virusname);
- if(privdata->subject)
- smfi_chgheader(ctx, "Subject", 1, subject);
- else
- smfi_addheader(ctx, "Subject", subject);
-}
-
-#if 0
-/*
- * TODO: gethostbyname_r is non-standard so different operating
- * systems do it in different ways. Need more examples
- * Perhaps we could use res_search()?
- * Perhaps we could use http://www.chiark.greenend.org.uk/~ian/adns/
- *
- * Returns 0 for success
- */
-static int
-clamfi_gethostbyname(const char *hostname, struct hostent *hp, char *buf, size_t len)
-{
-#if defined(HAVE_GETHOSTBYNAME_R_6)
- /* e.g. Linux */
- struct hostent *hp2;
- int ret = -1;
-
- if((hostname == NULL) || (hp == NULL))
- return -1;
- if(gethostbyname_r(hostname, hp, buf, len, &hp2, &ret) < 0)
- return ret;
-#elif defined(HAVE_GETHOSTBYNAME_R_5)
- /* e.g. BSD, Solaris, Cygwin */
- int ret = -1;
-
- if((hostname == NULL) || (hp == NULL))
- return -1;
- if(gethostbyname_r(hostname, hp, buf, len, &ret) == NULL)
- return ret;
-#elif defined(HAVE_GETHOSTBYNAME_R_3)
- /* e.g. HP/UX, AIX */
- if((hostname == NULL) || (hp == NULL))
- return -1;
- if(gethostbyname_r(hostname, &hp, (struct hostent_data *)buf) < 0)
- return h_errno;
-#else
- /* Single thread the code */
- struct hostent *hp2;
- static pthread_mutex_t hostent_mutex = PTHREAD_MUTEX_INITIALIZER;
-
- if((hostname == NULL) || (hp == NULL))
- return -1;
-
- pthread_mutex_lock(&hostent_mutex);
- if((hp2 = gethostbyname(hostname)) == NULL) {
- pthread_mutex_unlock(&hostent_mutex);
- return h_errno;
- }
- memcpy(hp, hp2, sizeof(struct hostent));
- pthread_mutex_unlock(&hostent_mutex);
-#endif
-
- return 0;
-}
-#endif
-
-/*
- * Handle the -I flag
- */
-static int
-add_local_ip(char *address)
-{
- char *opt, *pref;
- int preflen;
- int retval;
- struct in_addr ignoreIP;
-#ifdef AF_INET6
- struct in6_addr ignoreIP6;
-#endif
-
- opt = cli_strdup(address);
- if(opt == NULL)
- return 0;
-
- pref = strchr(opt, '/'); /* search for "/prefix" */
- if(pref)
- *pref = '\0';
-#ifdef HAVE_INET_NTOP
- /* IPv4 address ? */
- if(inet_pton(AF_INET, opt, &ignoreIP) > 0) {
-#else
- if(inet_aton(address, &ignoreIP)) {
-#endif
- struct cidr_net *net;
-
- for(net = (struct cidr_net *)localNets; net->base; net++)
- ;
- if(pref && *(pref+1))
- preflen = atoi(pref+1);
- else
- preflen = 32;
-
- net->base = ntohl(ignoreIP.s_addr);
- net->mask = MAKEMASK(preflen);
-
- retval = 1;
- }
-
-#ifdef HAVE_INET_NTOP
-#ifdef AF_INET6
- else if(inet_pton(AF_INET6, opt, &ignoreIP6) > 0) {
- /* IPv6 address ? */
- localNets6[localNets6_cnt].base = ignoreIP6;
-
- if(pref && *(pref+1))
- preflen = atoi (pref+1);
- else
- preflen = 128;
- localNets6[localNets6_cnt].preflen = preflen;
- localNets6_cnt++;
-
- retval = 1;
- }
-#endif
-#endif
- else
- retval = 0;
-
- free(opt);
- return retval;
-}
-
-/*
- * Determine if an IPv6 email address is "local". The address is the
- * human readable version. Calls isLocalAddr if the given address is
- * IPv4
- */
-static int
-isLocal(const char *addr)
-{
- struct in_addr ip;
-#ifdef AF_INET6
- struct in6_addr ip6;
-#endif
-
-#ifdef HAVE_INET_NTOP
- if(inet_pton(AF_INET, addr, &ip) > 0)
- return isLocalAddr(ip.s_addr);
-#ifdef AF_INET6
- else if(inet_pton (AF_INET6, addr, &ip6) > 0) {
- int i;
- const cidr_net6 *pnet6 = localNets6;
-
- for (i = 0; i < localNets6_cnt; i++) {
- int match = 1;
- int j;
-
- for(j = 0; match && j < (pnet6->preflen >> 3); j++)
- if(pnet6->base.s6_addr[j] != ip6.s6_addr[j])
- match = 0;
- if(match && (j < 16)) {
- uint8_t mask = (uint8_t)(0xff << (8 - (pnet6->preflen & 7)) & 0xFF);
-
- if((pnet6->base.s6_addr[j] & mask) != (ip6.s6_addr[j] & mask))
- match = 0;
- }
- if(match)
- return 1; /* isLocal */
- pnet6++;
- }
- }
-#endif /* AF_INET6 */
-#endif /* HAVE_INET_NTOP */
- return isLocalAddr(inet_addr(addr));
-}
-
-/*
- * David Champion <dgc at uchicago.edu>
- *
- * Check whether addr is on network by applying netmasks.
- * addr must be a 32-bit integer-packed IPv4 address in network order.
- * For example:
- * struct in_addr IPAddress;
- * isLocal = isLocalAddr(IPAddress.s_addr);
- */
-static int
-isLocalAddr(in_addr_t addr)
-{
- const struct cidr_net *net;
-
- for(net = localNets; net->base; net++)
- if((net->base & net->mask) == (ntohl(addr) & net->mask))
- return 1;
-
- return 0; /* is non-local */
-}
-
-/*
- * Can't connect to any clamd server. This is serious, we need to inform
- * someone. In the absence of SNMP the best way is by e-mail. We
- * don't want to flood so there's a need to restrict to
- * no more than say one message every 15 minutes
- */
-static void
-clamdIsDown(void)
-{
- static time_t lasttime;
- time_t thistime, diff;
- static pthread_mutex_t time_mutex = PTHREAD_MUTEX_INITIALIZER;
-
- logg(_("!No response from any clamd server - your AV system is not scanning emails\n"));
-
- time(&thistime);
- pthread_mutex_lock(&time_mutex);
- diff = thistime - lasttime;
- pthread_mutex_unlock(&time_mutex);
-
- if(diff >= (time_t)(15 * 60)) {
- char cmd[128];
- FILE *sendmail;
-
- snprintf(cmd, sizeof(cmd) - 1, "%s -t -i", SENDMAIL_BIN);
-
- sendmail = popen(cmd, "w");
-
- if(sendmail) {
- fprintf(sendmail, "To: %s\n", postmaster);
- fprintf(sendmail, "From: %s\n", postmaster);
- fputs(_("Subject: ClamAV Down\n"), sendmail);
- fputs("Priority: High\n\n", sendmail);
-
- fputs(_("This is an automatic message\n\n"), sendmail);
-
- if(numServers == 1)
- fputs(_("The clamd program cannot be contacted.\n"), sendmail);
- else
- fputs(_("No clamd server can be contacted.\n"), sendmail);
-
- fputs(_("Emails may not be being scanned, please check your servers.\n"), sendmail);
-
- if(pclose(sendmail) == 0) {
- pthread_mutex_lock(&time_mutex);
- time(&lasttime);
- pthread_mutex_unlock(&time_mutex);
- }
- }
- }
-}
-
-#ifdef SESSION
-/*
- * Thread to monitor the links to clamd sessions. Any marked as being in
- * an error state because of previous I/O errors are restarted, and a heartbeat
- * is sent the others
- *
- * It is woken up when the milter goes idle, when there are no free servers
- * available and once every readTimeout-1 seconds
- *
- * TODO: reload the whiteList file if it's been changed
- *
- * TODO: localSocket support
- */
-static void *
-watchdog(void *a)
-{
- static pthread_mutex_t watchdog_mutex = PTHREAD_MUTEX_INITIALIZER;
-
- while(!quitting) {
- unsigned int i;
- struct timespec ts;
- struct timeval tp;
- struct session *session;
-
- gettimeofday(&tp, NULL);
-
- ts.tv_sec = tp.tv_sec + freshclam_monitor;
- ts.tv_nsec = tp.tv_usec * 1000;
- cli_dbgmsg("watchdog sleeps\n");
- pthread_mutex_lock(&watchdog_mutex);
- /*
- * Sometimes this returns EPIPE which isn't listed as a
- * return value in the Linux man page for pthread_cond_timedwait
- * so I'm not sure why it happens
- */
- switch(pthread_cond_timedwait(&watchdog_cond, &watchdog_mutex, &ts)) {
- case ETIMEDOUT:
- case 0:
- break;
- default:
- perror("pthread_cond_timedwait");
- }
- pthread_mutex_unlock(&watchdog_mutex);
-
- cli_dbgmsg("watchdog wakes\n");
-
- if(check_and_reload_database() != 0) {
- if(cl_error != SMFIS_ACCEPT) {
- smfi_stop();
- return NULL;
- }
- logg(_("!No emails will be scanned"));
- }
-
- i = 0;
- session = sessions;
- pthread_mutex_lock(&sstatus_mutex);
- for(; i < max_children; i++, session++) {
- const int sock = session->sock;
-
- /*
- * Check all free sessions are still usable
- * This could take some time with many free
- * sessions to slow remote servers, so only do this
- * when the system is quiet (not 100% accurate when
- * determining this since n_children isn't locked but
- * that doesn't really matter)
- */
- cli_dbgmsg("watchdog: check server %d\n", i);
- if((n_children == 0) &&
- (session->status == CMDSOCKET_FREE) &&
- (clamav_versions != NULL)) {
- if(send(sock, "VERSION\n", 8, 0) == 8) {
- char buf[81];
- const int nbytes = clamd_recv(sock, buf, sizeof(buf) - 1);
-
- if(nbytes <= 0)
- session->status = CMDSOCKET_DOWN;
- else {
- buf[nbytes] = '\0';
- if(strncmp(buf, "ClamAV ", 7) == 0) {
- /* Remove the trailing new line from the reply */
- char *ptr;
-
- if((ptr = strchr(buf, '\n')) != NULL)
- *ptr = '\0';
- pthread_mutex_lock(&version_mutex);
- if(clamav_versions[i] == NULL)
- clamav_versions[i] = cli_strdup(buf);
- else if(strcmp(buf, clamav_versions[i]) != 0) {
- logg("New version received for server %d: '%s'\n", i, buf);
- free(clamav_versions[i]);
- clamav_versions[i] = cli_strdup(buf);
- }
- pthread_mutex_unlock(&version_mutex);
- } else {
- cli_warnmsg("watchdog: expected \"ClamAV\", got \"%s\"\n", buf);
- session->status = CMDSOCKET_DOWN;
- }
- }
- } else {
- perror("send");
- session->status = CMDSOCKET_DOWN;
- }
-
- if(session->status == CMDSOCKET_DOWN)
- cli_warnmsg("Session %d has gone down\n", i);
- }
- /*
- * Reset all all dead sessions
- */
- if(session->status == CMDSOCKET_DOWN) {
- /*
- * The END command probably won't get through,
- * but let's give it a go anyway
- */
- if(sock >= 0) {
- send(sock, "END\n", 4, 0);
- close(sock);
- }
-
- cli_dbgmsg("Trying to restart session %d\n", i);
- if(createSession(i) == 0) {
- session->status = CMDSOCKET_FREE;
- cli_warnmsg("Session %d restarted OK\n", i);
- }
- }
- }
- for(i = 0; i < max_children; i++)
- if(sessions[i].status != CMDSOCKET_DOWN)
- break;
-
- if(i == max_children)
- clamdIsDown();
- pthread_mutex_unlock(&sstatus_mutex);
-
- /* Garbage collect IP addresses no longer blacklisted */
- if(blacklist) {
- pthread_mutex_lock(&blacklist_mutex);
- tableIterate(blacklist, timeoutBlacklist, NULL);
- pthread_mutex_unlock(&blacklist_mutex);
- }
- }
- cli_dbgmsg("watchdog quits\n");
- return NULL;
-}
-#else /*!SESSION*/
-/*
- * Reload the database from time to time, when using the internal scanner
- *
- * TODO: reload the whiteList file if it's been changed
- */
-/*ARGSUSED*/
-static void *
-watchdog(void *a)
-{
- static pthread_mutex_t watchdog_mutex = PTHREAD_MUTEX_INITIALIZER;
-
- if((!blacklist_time) && external)
- return NULL; /* no need for this thread */
-
- while(!quitting) {
- struct timespec ts;
- struct timeval tp;
-
- gettimeofday(&tp, NULL);
-
- ts.tv_sec = tp.tv_sec + freshclam_monitor;
- ts.tv_nsec = tp.tv_usec * 1000;
- cli_dbgmsg("watchdog sleeps\n");
-
- pthread_mutex_lock(&watchdog_mutex);
- /*
- * Sometimes this returns EPIPE which isn't listed as a
- * return value in the Linux man page for pthread_cond_timedwait
- * so I'm not sure why it happens
- */
- switch(pthread_cond_timedwait(&watchdog_cond, &watchdog_mutex, &ts)) {
- case ETIMEDOUT:
- case 0:
- break;
- default:
- perror("pthread_cond_timedwait");
- }
- pthread_mutex_unlock(&watchdog_mutex);
- cli_dbgmsg("watchdog wakes\n");
-
- /*
- * TODO: sanity check that if n_children == 0, that
- * root->refcount == 0. Unfortunatly root->refcount isn't
- * thread-safe, since it's governed by a mutex that we can't
- * see, and there's no access to it via an approved method
- */
- if(check_and_reload_database() != 0) {
- if(cl_error != SMFIS_ACCEPT) {
- smfi_stop();
- return NULL;
- }
- logg(_("!No emails will be scanned"));
- }
- /* Garbage collect IP addresses no longer blacklisted */
- if(blacklist) {
- pthread_mutex_lock(&blacklist_mutex);
- tableIterate(blacklist, timeoutBlacklist, NULL);
- pthread_mutex_unlock(&blacklist_mutex);
- }
- }
- cli_dbgmsg("watchdog quits\n");
- return NULL;
-}
-#endif
-
-/*
- * Check to see if the database needs to be reloaded
- * Return 0 for success
- */
-static int
-check_and_reload_database(void)
-{
- int rc;
-
- if(external)
- return 0;
-
- if(reload) {
- rc = 1;
- reload = 0;
- } else
- rc = cl_statchkdir(&dbstat);
-
- switch(rc) {
- case 1:
- logg("^Database has changed, loading updated database\n");
- cl_statfree(&dbstat);
- rc = loadDatabase();
- if(rc != 0) {
- logg("!Failed to load updated database\n");
- return rc;
- }
- break;
- case 0:
- logg("*Database has not changed\n");
- break;
- default:
- logg("Database error %d - %s is stopping\n",
- rc, progname);
- return 1;
- }
- return 0; /* all OK */
-}
-
-static void
-timeoutBlacklist(char *ip_address, int time_of_blacklist, void *v)
-{
- if(time_of_blacklist == 0) /* Must not blacklist this IP address */
- return;
- if((time((time_t *)0) - time_of_blacklist) > blacklist_time)
- tableRemove(blacklist, ip_address);
-}
-
-static void
-quit(void)
-{
- quitting++;
-
-#ifdef SESSION
- pthread_mutex_lock(&version_mutex);
-#endif
- logg(_("Stopping %s\n"), clamav_version);
-#ifdef SESSION
- pthread_mutex_unlock(&version_mutex);
-#endif
-
- if(!external) {
- pthread_mutex_lock(&engine_mutex);
- if(engine)
- cl_engine_free(engine);
- pthread_mutex_unlock(&engine_mutex);
- } else {
-#ifdef SESSION
- int i = 0;
- struct session *session = sessions;
-
- pthread_mutex_lock(&sstatus_mutex);
- for(; i < ((localSocket != NULL) ? 1 : (int)max_children); i++) {
- /*
- * Check all free sessions are still usable
- * This could take some time with many free
- * sessions to slow remote servers, so only do this
- * when the system is quiet (not 100% accurate when
- * determining this since n_children isn't locked but
- * that doesn't really matter)
- */
- cli_dbgmsg("quit: close server %d\n", i);
- if(session->status == CMDSOCKET_FREE) {
- const int sock = session->sock;
-
- send(sock, "END\n", 4, 0);
- shutdown(sock, SHUT_WR);
- session->status = CMDSOCKET_DOWN;
- pthread_mutex_unlock(&sstatus_mutex);
- close(sock);
- pthread_mutex_lock(&sstatus_mutex);
- }
- session++;
- }
- pthread_mutex_unlock(&sstatus_mutex);
-#endif
- }
-
- if(tmpdir)
- if(rmdir(tmpdir) < 0)
- perror(tmpdir);
-
- broadcast(_("Stopping clamav-milter"));
-
- if(pidfile)
- if(unlink(pidfile) < 0)
- perror(pidfile);
-
- logg_close();
-}
-
-static void
-broadcast(const char *mess)
-{
- struct sockaddr_in s;
-
- if(broadcastSock < 0)
- return;
-
- memset(&s, '\0', sizeof(struct sockaddr_in));
- s.sin_family = AF_INET;
- s.sin_port = (in_port_t)htons(tcpSocket ? tcpSocket : 3310);
- s.sin_addr.s_addr = htonl(INADDR_BROADCAST);
-
- cli_dbgmsg("broadcast %s to %d\n", mess, broadcastSock);
- if(sendto(broadcastSock, mess, strlen(mess), 0, (struct sockaddr *)&s, sizeof(struct sockaddr_in)) < 0)
- perror("sendto");
-}
-
-/*
- * Load a new database into the internal scanner
- */
-static int
-loadDatabase(void)
-{
- int ret;
- unsigned int signatures, dboptions;
- char *daily;
- struct cl_cvd *d;
- const struct cfgstruct *cpt;
- static const char *dbdir;
-
- assert(!external);
-
- if(dbdir == NULL) {
- /*
- * First time through, find out in which directory the signature
- * databases are
- */
- if((cpt = cfgopt(copt, "DatabaseDirectory")) && cpt->enabled)
- dbdir = cpt->strarg;
- else
- dbdir = cl_retdbdir();
- }
-
- daily = cli_malloc(strlen(dbdir) + 11);
- sprintf(daily, "%s/daily.cvd", dbdir);
- if(access(daily, R_OK) < 0)
- sprintf(daily, "%s/daily.cld", dbdir);
-
-
- cli_dbgmsg("loadDatabase: check %s for updates\n", daily);
-
- d = cl_cvdhead(daily);
-
- if(d) {
- char *ptr;
- time_t t = d->stime;
- char buf[26];
-
- snprintf(clamav_version, VERSION_LENGTH,
- "ClamAV %s/%u/%s", get_version(), d->version,
- cli_ctime(&t, buf, sizeof(buf)));
-
- /* Remove ctime's trailing \n */
- if((ptr = strchr(clamav_version, '\n')) != NULL)
- *ptr = '\0';
-
- cl_cvdfree(d);
- } else
- snprintf(clamav_version, VERSION_LENGTH,
- "ClamAV version %s, clamav-milter version %s",
- cl_retver(), get_version());
-
- free(daily);
-
-#ifdef SESSION
- pthread_mutex_lock(&version_mutex);
- if(clamav_versions == NULL) {
- clamav_versions = (char **)cli_malloc(sizeof(char *));
- if(clamav_versions == NULL) {
- pthread_mutex_unlock(&version_mutex);
- return -1;
- }
- clamav_version = cli_malloc(VERSION_LENGTH + 1);
- if(clamav_version == NULL) {
- free(clamav_versions);
- clamav_versions = NULL;
- pthread_mutex_unlock(&version_mutex);
- return -1;
- }
- }
- pthread_mutex_unlock(&version_mutex);
-#endif
- signatures = 0;
- pthread_mutex_lock(&engine_mutex);
- if(engine) cl_engine_free(engine);
- engine = cl_engine_new();
- if (!engine) {
- logg("!Can't initialize antivirus engine\n");
- pthread_mutex_unlock(&engine_mutex);
- return -1;
- }
- if(!cfgopt(copt, "PhishingSignatures")->enabled) {
- logg("Not loading phishing signatures.\n");
- dboptions = 0;
- } else
- dboptions = CL_DB_PHISHING;
- if((ret = cl_engine_set(engine, CL_ENGINE_MAX_SCANSIZE, &maxscansize))) {
- logg("!cli_engine_set(CL_ENGINE_MAX_SCANSIZE) failed: %s\n", cl_strerror(ret));
- cl_engine_free(engine);
- pthread_mutex_unlock(&engine_mutex);
- return -1;
- }
- if((ret = cl_engine_set(engine, CL_ENGINE_MAX_FILESIZE, &maxfilesize))) {
- logg("!cli_engine_set(CL_ENGINE_MAX_FILESIZE) failed: %s\n", cl_strerror(ret));
- cl_engine_free(engine);
- pthread_mutex_unlock(&engine_mutex);
- return -1;
- }
- ret = cl_load(dbdir, engine, &signatures, dboptions);
- if(ret != CL_SUCCESS) {
- logg("!%s\n", cl_strerror(ret));
- cl_engine_free(engine);
- pthread_mutex_unlock(&engine_mutex);
- return -1;
- }
- ret = cl_engine_compile(engine);
- if(ret != CL_SUCCESS) {
- logg("!Database initialization error: %s\n", cl_strerror(ret));
- cl_engine_free(engine);
- pthread_mutex_unlock(&engine_mutex);
- return -1;
- }
- pthread_mutex_unlock(&engine_mutex);
-#ifdef SESSION
- pthread_mutex_lock(&version_mutex);
-#endif
- logg( _("Loaded %s\n"), clamav_version);
-#ifdef SESSION
- pthread_mutex_unlock(&version_mutex);
-#endif
- logg(_("ClamAV: Protecting against %u viruses\n"), signatures);
- logg("#Database correctly (re)loaded (%u viruses)\n");
- return cl_statinidir(dbdir, &dbstat);
-}
-
-static void
-sigsegv(int sig)
-{
- signal(SIGSEGV, SIG_DFL);
-
-#ifdef HAVE_BACKTRACE
- print_trace();
-#endif
-
- logg("!Segmentation fault :-( Bye.., notify bugs at clamav.net\n");
-
- quitting++;
- smfi_stop();
-}
-
-extern FILE *logg_fd;
-static void
-sigusr1(int sig)
-{
-
- signal(SIGUSR1, sigusr1);
-
- if(!(cfgopt(copt, "LogFile"))->enabled)
- return;
-
- logg("SIGUSR1 caught: re-opening log file\n");
- logg_close();
- logg("*Log file re-opened\n");
- dup2(fileno(logg_fd), 2);
-}
-
-static void
-sigusr2(int sig)
-{
- signal(SIGUSR2, sigusr2);
-
- logg("^SIGUSR2 caught: scheduling database reload\n");
- reload++;
-}
-
-#ifdef HAVE_BACKTRACE
-static void
-print_trace(void)
-{
- void *array[BACKTRACE_SIZE];
- size_t size, i;
- char **strings;
- pid_t pid = getpid();
-
- size = backtrace(array, BACKTRACE_SIZE);
- strings = backtrace_symbols(array, size);
-
- logg("*Backtrace of pid %d:\n", pid);
-
- for(i = 0; i < size; i++)
- logg("bt[%u]: %s", i, strings[i]);
-
- /* TODO: dump the current email */
-
- free(strings);
-}
-#endif
-
-/*
- * Check that the correct port name has been given, i.e. that the
- * input socket to clamav-milter from sendmail, is the same that
- * sendmail has been configured to use as it's output socket
- * Return: <0 invalid
- * =0 valid
- * >0 unknown
- *
- * You wouldn't believe the amount of time I used to waste chasing bug reports
- * from people who's sendmail.cf didn't tally with the arguments given to
- * clamav-milter before I put this check in, which is why bug 726 must
- * never be acted upon.
- *
- * FIXME: return different codes for "the value is wrong" and "sendmail.cf"
- * hasn't been set up, though that's not so easy to work out.
- */
-static int
-verifyIncomingSocketName(const char *sockName)
-{
-#if HAVE_MMAP
- int fd, ret;
- char *ptr;
- size_t size;
- struct stat statb;
-
- if(strncmp(sockName, "inet:", 5) == 0)
- /*
- * clamav-milter is running on a different machine from sendmail
- */
- return 1;
-
- if(sendmailCF)
- fd = open(sendmailCF, O_RDONLY);
- else {
- fd = open("/etc/mail/sendmail.cf", O_RDONLY);
- if(fd < 0)
- fd = open("/etc/sendmail.cf", O_RDONLY);
- }
-
- if(fd < 0)
- return 1;
-
- if(fstat(fd, &statb) < 0) {
- close(fd);
- return 1;
- }
-
- size = statb.st_size;
-
- if(size == 0) {
- close(fd);
- return -1;
- }
-
- ptr = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
- if(ptr == MAP_FAILED) {
- perror("mmap");
- close(fd);
- return -1;
- }
-
- ret = (cli_memstr(ptr, size, sockName, strlen(sockName)) != NULL) ? 1 : -1;
-
- munmap(ptr, size);
- close(fd);
-
- return ret;
-#else /*!HAVE_MMAP*/
- return 1;
-#endif
-}
-
-/*
- * If the given email address is whitelisted don't scan emails to them,
- * the addresses are in angle brackets e.g. <foo at bar.com>.
- *
- * TODO: Allow regular expressions in the addresses
- * TODO: Syntax check the contents of the files
- * TODO: Allow emails of the form "name <address>"
- * TODO: Allow emails not of the form "<address>", i.e. no angle brackets
- * TODO: Assume that if a '@' is missing from the address, that all emails
- * to that domain are to be whitelisted
- */
-static int
-isWhitelisted(const char *emailaddress, int to)
-{
- static table_t *to_whitelist, *from_whitelist; /* never freed */
- table_t *table;
-
- logg("*isWhitelisted %s\n", emailaddress);
-
- /*
- * Don't scan messages to the quarantine email address
- */
- if(quarantine && (strcasecmp(quarantine, emailaddress) == 0))
- return 1;
-
- if((to_whitelist == NULL) && whitelistFile) {
- FILE *fin;
- char buf[BUFSIZ + 1];
-
- fin = fopen(whitelistFile, "r");
-
- if(fin == NULL) {
- perror(whitelistFile);
- logg(_("!Can't open whitelist file %s"), whitelistFile);
- return 0;
- }
- to_whitelist = tableCreate();
- from_whitelist = tableCreate();
-
- if((to_whitelist == NULL) || (from_whitelist == NULL)) {
- logg(_("!Can't create whitelist table"));
- if(to_whitelist) {
- tableDestroy(to_whitelist);
- to_whitelist = NULL;
- } else {
- tableDestroy(from_whitelist);
- from_whitelist = NULL;
- }
- fclose(fin);
- return 0;
- }
-
- while(fgets(buf, sizeof(buf), fin) != NULL) {
- const char *ptr;
-
- /* comment line? */
- switch(buf[0]) {
- case '#':
- case '/':
- case ':':
- continue;
- }
- if(cli_chomp(buf) > 0) {
- if((ptr = strchr(buf, ':')) != NULL) {
- do
- ptr++;
- while(*ptr && isspace(*ptr));
-
- if(*ptr == '\0') {
- logg("*Ignoring bad line '%s'\n",
- buf);
- continue;
- }
- } else
- ptr = buf;
-
- if(strncasecmp(buf, "From:", 5) == 0)
- table = from_whitelist;
- else
- table = to_whitelist;
-
- (void)tableInsert(table, ptr, 1);
- }
- }
- fclose(fin);
- }
- table = (to) ? to_whitelist : from_whitelist;
-
- if(table && (tableFind(table, emailaddress) == 1))
- /*
- * This recipient is on the whitelist
- */
- return 1;
-
- return 0;
-}
-
-/*
- * Blacklist IP addresses that send malware. Often in the phishing world, one
- * phish is quickly followed by another. IP addresses are blacklisted for one
- * minute. We can't blacklist for longer since DHCP means we could hit innocent
- * parties, and in theory malware could go through a smart host and affect
- * innocent parties
- *
- * Note that sites which can't be blacklisted will have their timestamp set
- * to 0, since that can never be less than blacklist_time seconds from now
- */
-static int
-isBlacklisted(const char *ip_address)
-{
- time_t t;
-
- if(blacklist_time == 0)
- /* Blacklisting not being used */
- return 0;
-
- logg("*isBlacklisted %s\n", ip_address);
-
- if(isLocal(ip_address))
- return 0;
-
- pthread_mutex_lock(&blacklist_mutex);
- if(blacklist == NULL) {
- blacklist = tableCreate();
-
- pthread_mutex_unlock(&blacklist_mutex);
-
- if(blacklist == NULL)
- logg(_("!Can't create blacklist table"));
- return 0;
- }
- t = tableFind(blacklist, ip_address);
- pthread_mutex_unlock(&blacklist_mutex);
-
- if(t == (time_t)-1)
- /* IP address is not blacklisted */
- return 0;
-
- if(t == (time_t)0)
- /* IP cannot be blacklisted */
- return 0;
-
- if((time((time_t *)0) - t) <= blacklist_time)
- return 1;
-
- /* timedout: remove the IP from the blacklist */
- pthread_mutex_lock(&blacklist_mutex);
- tableRemove(blacklist, ip_address);
- pthread_mutex_unlock(&blacklist_mutex);
-
- return 0;
-}
-
-#ifdef HAVE_RESOLV_H
-/*
- * Determine our MX peers, they must never be blacklisted
- * See RFC1034 for the definition of the record formats
- *
- * This is only ever called once, which is wrong, but the overheard of calling
- * this from the watchdog isn't worth it
- */
-static table_t *
-mx(const char *host, table_t *t)
-{
- u_char *p, *end;
- const HEADER *hp;
- int len, i;
- union {
- HEADER h;
- u_char u[PACKETSZ];
- } q;
- char buf[BUFSIZ];
-
- if(t == NULL) {
- t = tableCreate();
-
- if(t == NULL)
- return NULL;
- }
-
- len = safe_res_query(host, C_IN, T_MX, (u_char *)&q, sizeof(q));
- if(len < 0)
- return t; /* Host has no MX records */
-
- if((unsigned int)len > sizeof(q))
- return t;
-
- hp = &(q.h);
- p = q.u + HFIXEDSZ;
- end = q.u + len;
-
- for(i = ntohs(hp->qdcount); i--; p += len + QFIXEDSZ)
- if((len = dn_skipname(p, end)) < 0)
- return t;
-
- i = ntohs(hp->ancount);
-
- while((--i >= 0) && (p < end)) {
- in_addr_t addr;
- u_short type, pref;
- u_long ttl; /* unused */
-
- if((len = dn_expand(q.u, end, p, buf, sizeof(buf) - 1)) < 0)
- break;
- p += len;
- GETSHORT(type, p);
- p += INT16SZ;
- GETLONG(ttl, p);
- GETSHORT(len, p);
- if(type != T_MX) {
- p += len;
- continue;
- }
- GETSHORT(pref, p);
- if((len = dn_expand(q.u, end, p, buf, sizeof(buf) - 1)) < 0)
- break;
- p += len;
- addr = inet_addr(buf);
-#ifdef INADDR_NONE
- if(addr != INADDR_NONE) {
-#else
- if(addr != (in_addr_t)-1) {
-#endif
- (void)tableInsert(t, buf, 0);
- } else
- t = resolve(buf, t);
- }
- return t;
-}
-
-/*
- * If the MX record points to a name, we need to resolve that name. This routine
- * does that
- */
-static table_t *
-resolve(const char *host, table_t *t)
-{
- u_char *p, *end;
- const HEADER *hp;
- int len, i;
- union {
- HEADER h;
- u_char u[PACKETSZ];
- } q;
- char buf[BUFSIZ];
-
- if((host == NULL) || (*host == '\0'))
- return t;
-
- len = safe_res_query(host, C_IN, T_A, (u_char *)&q, sizeof(q));
- if(len < 0)
- return t; /* Host has no A records */
-
- if((unsigned int)len > sizeof(q))
- return t;
-
- hp = &(q.h);
- p = q.u + HFIXEDSZ;
- end = q.u + len;
-
- for(i = ntohs(hp->qdcount); i--; p += len + QFIXEDSZ)
- if((len = dn_skipname(p, end)) < 0)
- return t;
-
- i = ntohs(hp->ancount);
-
- while((--i >= 0) && (p < end)) {
- u_short type;
- u_long ttl;
- const char *ip;
- struct in_addr addr;
-
- if((len = dn_expand(q.u, end, p, buf, sizeof(buf) - 1)) < 0)
- return t;
- p += len;
- GETSHORT(type, p);
- p += INT16SZ;
- GETLONG(ttl, p); /* unused */
- GETSHORT(len, p);
- if(type != T_A) {
- p += len;
- continue;
- }
- memcpy(&addr, p, sizeof(struct in_addr));
- p += 4; /* Should check len == 4 */
- ip = inet_ntoa(addr);
- if(ip) {
- if(t == NULL) {
- t = tableCreate();
-
- if(t == NULL)
- return NULL;
- }
- (void)tableInsert(t, ip, 0);
- }
- }
- return t;
-}
-
-/*
- * Validate SPF records to help to stop Phish false positives
- * http://www.openspf.org/SPF_Record_Syntax
- *
- * Currently only handles ip4, a and mx fields in the DNS record
- * Having said that, this is NOT a replacement for spf-milter, it is NOT
- * an SPF system, we ONLY use SPF records to reduce phish false positives
- * TODO: IPv6?
- * TODO: cache queries?
- *
- * INPUT: prevhosts, a list of hosts already searched: stops include loops
- * e.g. mercado.com includes medrcadosw.com which includes mercado.com,
- * causing a loop
- * Return 1 if SPF says this email is from a legitimate source
- * 0 for fail or unknown
- */
-static int
-spf(struct privdata *privdata, table_t *prevhosts)
-{
- char *host, *ptr;
- u_char *p, *end;
- const HEADER *hp;
- int len, i;
- union {
- HEADER h;
- u_char u[PACKETSZ];
- } q;
- char buf[BUFSIZ];
-
- if(privdata->spf_ok)
- return 1;
- if(privdata->ip[0] == '\0')
- return 0;
- if(strcmp(privdata->ip, "127.0.0.1") == 0) {
- /* Loopback always pass SPF */
- privdata->spf_ok = 1;
- return 1;
- }
- if(isLocal(privdata->ip)) {
- /* Local addresses always pass SPF */
- privdata->spf_ok = 1;
- return 1;
- }
-
- if(privdata->from == NULL)
- return 0;
- if((host = strrchr(privdata->from, '@')) == NULL)
- return 0;
-
- host = cli_strdup(++host);
-
- if(host == NULL)
- return 0;
-
- ptr = strchr(host, '>');
-
- if(ptr)
- *ptr = '\0';
-
- logg("*SPF query '%s'\n", host);
- len = safe_res_query(host, C_IN, T_TXT, (u_char *)&q, sizeof(q));
- if(len < 0) {
- free(host);
- return 0; /* Host has no TXT records */
- }
-
- if((unsigned int)len > sizeof(q)) {
- free(host);
- return 0;
- }
-
- hp = &(q.h);
- p = q.u + HFIXEDSZ;
- end = q.u + len;
-
- for(i = ntohs(hp->qdcount); i--; p += len + QFIXEDSZ)
- if((len = dn_skipname(p, end)) < 0) {
- free(host);
- return 0;
- }
-
- i = ntohs(hp->ancount);
-
- while((--i >= 0) && (p < end) && !privdata->spf_ok) {
- u_short type;
- u_long ttl;
- char txt[BUFSIZ];
-
- if((len = dn_expand(q.u, end, p, buf, sizeof(buf) - 1)) < 0) {
- free(host);
- return 0;
- }
- p += len;
- GETSHORT(type, p);
- p += INT16SZ;
- GETLONG(ttl, p); /* unused */
- GETSHORT(len, p);
- if(type != T_TXT) {
- p += len;
- continue;
- }
- strncpy(txt, (const char *)&p[1], sizeof(txt) - 1);
- txt[sizeof(txt)-1]='\0';
- txt[len - 1] = '\0';
- if((strncmp(txt, "v=spf1 ", 7) == 0) || (strncmp(txt, "spf2.0/pra ", 11) == 0)) {
- int j;
- char *record;
- struct in_addr remote_ip; /* IP connecting to us */
-
- logg("*%s(%s): SPF record %s\n",
- host, privdata->ip, txt);
-#ifdef HAVE_INET_NTOP
- /* IPv4 address ? */
- if(inet_pton(AF_INET, privdata->ip, &remote_ip) <= 0) {
- p += len;
- continue;
- }
-#else
- if(inet_aton(privdata->ip, &remote_ip) == 0) {
- p += len;
- continue;
- }
-#endif
-
- j = 1; /* strtok 0 would give the v= part */
- while((record = cli_strtok(txt, j++, " ")) != NULL) {
- if(strncmp(record, "ip4:", 4) == 0) {
- int preflen;
- char *ip, *pref;
- uint32_t mask;
- struct in_addr spf_range; /* acceptable range of IPs */
-
- ip = &record[4];
-
- pref = strchr(ip, '/');
- preflen = 32;
- if(pref) {
- *pref++ = '\0';
- if(*pref)
- preflen = atoi(pref);
- }
-
-#ifdef HAVE_INET_NTOP
- /* IPv4 address ? */
- if(inet_pton(AF_INET, ip, &spf_range) <= 0) {
- free(record);
- continue;
- }
-#else
- if(inet_aton(ip, &spf_range) == 0) {
- free(record);
- continue;
- }
-#endif
- mask = MAKEMASK(preflen);
- if((ntohl(remote_ip.s_addr) & mask) == (ntohl(spf_range.s_addr) & mask)) {
- if(privdata->subject)
- logg("#SPF ip4 pass (%s) %s is valid for %s\n",
- privdata->subject, ip, host);
- else
- logg("#SPF ip4 pass %s is valid for %s\n", ip, host);
- privdata->spf_ok = 1;
- }
- } else if(strcmp(record, "mx") == 0) {
- table_t *t = mx(host, NULL);
-
- if(t) {
- tableIterate(t, spf_ip,
- (void *)privdata);
- tableDestroy(t);
- }
- } else if(strcmp(record, "a") == 0) {
- table_t *t = resolve(host, NULL);
-
- if(t) {
- tableIterate(t, spf_ip,
- (void *)privdata);
- tableDestroy(t);
- }
- } else if(strncmp(record, "a:", 2) == 0) {
- const char *ahost = &record[2];
-
- if(*ahost && (strcmp(ahost, host) != 0)) {
- table_t *t = resolve(ahost, NULL);
-
- if(t) {
- tableIterate(t, spf_ip,
- (void *)privdata);
- tableDestroy(t);
- }
- }
- } else if(strncmp(record, "mx:", 3) == 0) {
- const char *mxhost = &record[3];
-
- if(*mxhost && (strcmp(mxhost, host) != 0)) {
- table_t *t = mx(mxhost, NULL);
-
- if(t) {
- tableIterate(t, spf_ip,
- (void *)privdata);
- tableDestroy(t);
- }
- }
- } else if(strncmp(record, "include:", 8) == 0) {
- const char *inchost = &record[8];
-
- /*
- * Ensure we haven't already looked at
- * the host that's to be included
- */
- if(*inchost &&
- (strcmp(inchost, host) != 0) &&
- (tableFind(prevhosts, inchost) == -1)) {
- char *real_from = privdata->from;
- privdata->from = cli_malloc(strlen(inchost) + 3);
- sprintf(privdata->from, "n@%s", inchost);
- tableInsert(prevhosts, host, 0);
- spf(privdata, prevhosts);
- free(privdata->from);
- privdata->from = real_from;
- }
- }
- free(record);
- if(privdata->spf_ok)
- break;
- }
- }
- p += len;
- }
- free(host);
-
- return privdata->spf_ok;
-}
-
-static void
-spf_ip(char *ip, int zero, void *v)
-{
- struct privdata *privdata = (struct privdata *)v;
-
- if(strcmp(ip, privdata->ip) == 0) {
- if(privdata->subject)
- logg("#SPF mx/a pass (%s) %s\n", privdata->subject, ip);
- else
- logg("#SPF mx/a pass %s\n", ip);
- privdata->spf_ok = 1;
- }
-}
-
-#else /*!HAVE_RESOLV_H */
-static table_t *
-mx(const char *host, table_t *t)
-{
- logg(_("^MX peers will not be immune from being blacklisted"));
-
- if(blacklist == NULL)
- blacklist = tableCreate();
- return NULL;
-}
-#endif /* HAVE_RESOLV_H */
-
-static sfsistat
-black_hole(const struct privdata *privdata)
-{
- int must_scan;
- char **to;
-
- to = privdata->to;
- must_scan = (*to) ? 0 : 1;
-
- for(; *to; to++) {
- pid_t pid, w;
- int pv[2], status;
- FILE *sendmail;
- char buf[BUFSIZ];
-
- logg("*Calling \"%s -bv %s\"\n", SENDMAIL_BIN, *to);
-
- if(pipe(pv) < 0) {
- perror("pipe");
- logg(_("!Can't create pipe\n"));
- must_scan = 1;
- break;
- }
- pid = fork();
- if(pid == 0) {
- close(1);
- close(pv[0]);
- dup2(pv[1], 1);
- close(pv[1]);
-
- /*
- * Avoid calling popen() since *to isn't trusted
- */
- execl(SENDMAIL_BIN, "sendmail", "-bv", *to, NULL);
- perror(SENDMAIL_BIN);
- logg("Can't execl %s\n", SENDMAIL_BIN);
- _exit(errno ? errno : 1);
- }
- if(pid == -1) {
- perror("fork");
- logg(_("!Can't fork\n"));
- close(pv[0]);
- close(pv[1]);
- must_scan = 1;
- break;
- }
- close(pv[1]);
- sendmail = fdopen(pv[0], "r");
-
- if(sendmail == NULL) {
- logg("fdopen failed\n");
- close(pv[0]);
- must_scan = 1;
- break;
- }
-
- while(fgets(buf, sizeof(buf), sendmail) != NULL) {
- if(cli_chomp(buf) == 0)
- continue;
-
- logg("*sendmail output: %s\n", buf);
-
- if(strstr(buf, "... deliverable: mailer ")) {
- const char *p = strstr(buf, ", user ");
-
- if(strcmp(&p[7], "/dev/null") != 0) {
- must_scan = 1;
- break;
- }
- }
- }
- fclose(sendmail);
-
- status = -1;
- do
- w = wait(&status);
- while((w != pid) && (w != -1));
-
- if(w == -1)
- status = -1;
- else
- status = WEXITSTATUS(status);
-
- switch(status) {
- case EX_NOUSER:
- case EX_OK:
- break;
- default:
- logg(_("^Can't execute '%s' to expand '%s' (error %d)\n"),
- SENDMAIL_BIN, *to, WEXITSTATUS(status));
- must_scan = 1;
- }
- if(must_scan)
- break;
- }
- if(!must_scan) {
- /* All recipients map to /dev/null */
- to = privdata->to;
- if(*to)
- logg("Discarded, since all recipients (e.g. \"%s\") are /dev/null\n", *to);
- else
- logg("Discarded, since all recipients are /dev/null\n");
- return SMFIS_DISCARD;
- }
- return SMFIS_CONTINUE;
-}
-
-/* See also libclamav/mbox.c */
-static int
-useful_header(const char *cmd)
-{
- if(strcasecmp(cmd, "From") == 0)
- return 1;
- if(strcasecmp(cmd, "Received") == 0)
- return 1;
- if(strcasecmp(cmd, "Content-Type") == 0)
- return 1;
- if(strcasecmp(cmd, "Content-Transfer-Encoding") == 0)
- return 1;
- if(strcasecmp(cmd, "Content-Disposition") == 0)
- return 1;
- if(strcasecmp(cmd, "De") == 0)
- return 1;
-
- return 0;
-}
-
-static int
-increment_connexions(void)
-{
- if(max_children > 0) {
- int rc = 0;
-
- pthread_mutex_lock(&n_children_mutex);
-
- /*
- * Wait a while since sendmail doesn't like it if we
- * take too long replying. Effectively this means that
- * max_children is more of a hint than a rule
- */
- if(n_children >= max_children) {
- struct timespec timeout;
- struct timeval now;
- struct timezone tz;
-
- logg((dont_wait) ?
- _("hit max-children limit (%u >= %u)\n") :
- _("hit max-children limit (%u >= %u): waiting for some to exit\n"),
- n_children, max_children);
-
- if(dont_wait) {
- pthread_mutex_unlock(&n_children_mutex);
- return 0;
- }
- /*
- * Wait for an amount of time for a child to go
- *
- * Use pthread_cond_timedwait rather than
- * pthread_cond_wait since the sendmail which
- * calls us will have a timeout that we don't
- * want to exceed, stops sendmail getting
- * fidgety.
- *
- * Patch from Damian Menscher
- * <menscher at uiuc.edu> to ensure it wakes up
- * when a child goes away
- */
- gettimeofday(&now, &tz);
- do {
- logg(_("n_children %d: waiting %d seconds for some to exit\n"),
- n_children, child_timeout);
-
- if(child_timeout == 0) {
- pthread_cond_wait(&n_children_cond, &n_children_mutex);
- rc = 0;
- } else {
- timeout.tv_sec = now.tv_sec + child_timeout;
- timeout.tv_nsec = 0;
-
- rc = pthread_cond_timedwait(&n_children_cond, &n_children_mutex, &timeout);
- }
- } while((n_children >= max_children) && (rc != ETIMEDOUT));
- logg(_("Finished waiting, n_children = %d\n"), n_children);
- }
- n_children++;
-
- logg("*>n_children = %d\n", n_children);
- pthread_mutex_unlock(&n_children_mutex);
-
- if(child_timeout && (rc == ETIMEDOUT))
- logg(_("Timeout waiting for a child to die\n"));
- }
-
- return 1;
-}
-
-static void
-decrement_connexions(void)
-{
- if(max_children > 0) {
- pthread_mutex_lock(&n_children_mutex);
- logg("*decrement_connexions: n_children = %d\n", n_children);
- /*
- * Deliberately errs on the side of broadcasting too many times
- */
- if(n_children > 0)
- if(--n_children == 0) {
- logg("*%s is idle\n", progname);
- if(pthread_cond_broadcast(&watchdog_cond) < 0)
- perror("pthread_cond_broadcast");
- }
-#ifdef CL_DEBUG
- logg("*pthread_cond_broadcast\n");
-#endif
- if(pthread_cond_broadcast(&n_children_cond) < 0)
- perror("pthread_cond_broadcast");
- logg("*<n_children = %d\n", n_children);
- pthread_mutex_unlock(&n_children_mutex);
- }
-}
-
-static void
-dump_blacklist(char *key, int value, void *v)
-{
- logg(_("Won't blacklist %s\n"), key);
-}
-
-/*
- * Non-blocking connect, based on an idea by Everton da Silva Marques
- * <everton.marques at gmail.com>
- * FIXME: There are lots of copies of this code :-(
- */
-static int
-nonblock_connect(int sock, const struct sockaddr_in *sin, const char *hostname)
-{
- int select_failures; /* Max. of unexpected select() failures */
- int attempts;
- struct timeval timeout; /* When we should time out */
- int numfd; /* Highest fdset fd plus 1 */
- long flags;
-
- gettimeofday(&timeout, 0); /* store when we started to connect */
-
- if(hostname == NULL)
- hostname = "clamav-milter"; /* It's only used in debug messages */
-
-#ifdef F_GETFL
- flags = fcntl(sock, F_GETFL, 0);
-
- if(flags == -1L)
- logg("^getfl: %s\n", strerror(errno));
- else if(fcntl(sock, F_SETFL, (long)(flags | O_NONBLOCK)) < 0)
- logg("^setfl: %s\n", strerror(errno));
-#else
- flags = -1L;
-#endif
- if(connect(sock, (const struct sockaddr *)sin, sizeof(struct sockaddr_in)) != 0)
- switch(errno) {
- case EALREADY:
- case EINPROGRESS:
- logg("*%s: connect: %s\n", hostname,
- strerror(errno));
- break; /* wait for connection */
- case EISCONN:
- return 0; /* connected */
- default:
- logg("^%s: connect: %s\n", hostname,
- strerror(errno));
-#ifdef F_SETFL
- if(flags != -1L)
- if(fcntl(sock, F_SETFL, flags))
- logg("^f_setfl: %s\n", strerror(errno));
-#endif
- return -1; /* failed */
- }
- else {
-#ifdef F_SETFL
- if(flags != -1L)
- if(fcntl(sock, F_SETFL, flags))
- logg("^f_setfl: %s\n", strerror(errno));
-#endif
- return connect_error(sock, hostname);
- }
-
- numfd = (int)sock + 1;
- select_failures = NONBLOCK_SELECT_MAX_FAILURES;
- attempts = 1;
- timeout.tv_sec += CONNECT_TIMEOUT;
-
- for (;;) {
- int n, t;
- fd_set fds;
- struct timeval now, waittime;
-
- /* Force timeout if we ran out of time */
- gettimeofday(&now, 0);
- t = (now.tv_sec == timeout.tv_sec) ?
- (now.tv_usec > timeout.tv_usec) :
- (now.tv_sec > timeout.tv_sec);
-
- if(t) {
- logg("^%s: connect timeout (%d secs)\n",
- hostname, CONNECT_TIMEOUT);
- break;
- }
-
- /* Calculate how long to wait */
- waittime.tv_sec = timeout.tv_sec - now.tv_sec;
- waittime.tv_usec = timeout.tv_usec - now.tv_usec;
- if(waittime.tv_usec < 0) {
- waittime.tv_sec--;
- waittime.tv_usec += 1000000;
- }
-
- /* Init fds with 'sock' as the only fd */
- FD_ZERO(&fds);
- FD_SET(sock, &fds);
-
- n = select(numfd, 0, &fds, 0, &waittime);
- if(n < 0) {
- logg("^%s: select attempt %d %s\n",
- hostname, select_failures, strerror(errno));
- if(--select_failures >= 0)
- continue; /* not timed-out, try again */
- break; /* failed */
- }
-
- logg("*%s: select = %d\n", hostname, n);
-
- if(n) {
-#ifdef F_SETFL
- if(flags != -1L)
- if(fcntl(sock, F_SETFL, flags))
- logg("^f_setfl: %s\n", strerror(errno));
-#endif
- return connect_error(sock, hostname);
- }
-
- /* timeout */
- if(attempts++ == NONBLOCK_MAX_ATTEMPTS) {
- logg("^timeout connecting to %s\n", hostname);
- break;
- }
- }
-
-#ifdef F_SETFL
- if(flags != -1L)
- if(fcntl(sock, F_SETFL, flags))
- logg("^f_setfl: %s\n", strerror(errno));
-#endif
- return -1; /* failed */
-}
-
-static int
-connect_error(int sock, const char *hostname)
-{
-#ifdef SO_ERROR
- int optval;
- socklen_t optlen = sizeof(optval);
-
- getsockopt(sock, SOL_SOCKET, SO_ERROR, &optval, &optlen);
-
- if(optval) {
- logg("^%s: %s\n", hostname, strerror(optval));
- return -1;
- }
-#endif
- return 0;
-}
diff --git a/contrib/old-clamav-milter/clamav-milter.po b/contrib/old-clamav-milter/clamav-milter.po
deleted file mode 100644
index 4a261b2..0000000
--- a/contrib/old-clamav-milter/clamav-milter.po
+++ /dev/null
@@ -1,1122 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR njh at bandsman.co.uk
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
-#
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: bugs at clamav.net\n"
-"POT-Creation-Date: 2007-10-24 09:05+0100\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
-"Language-Team: LANGUAGE <LL at li.org>\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=CHARSET\n"
-"Content-Transfer-Encoding: 8bit\n"
-
-#: clamav-milter.c:585
-msgid "\t--advisory\t\t-A\tFlag viruses rather than deleting them."
-msgstr ""
-
-#: clamav-milter.c:586
-msgid "\t--blacklist-time=SECS\t-k\tTime (in seconds) to blacklist an IP."
-msgstr ""
-
-#: clamav-milter.c:587
-msgid "\t--black-hole-mode\t\tDon't scan messages aliased to /dev/null."
-msgstr ""
-
-#: clamav-milter.c:589
-msgid "\t--bounce\t\t-b\tSend a failure message to the sender."
-msgstr ""
-
-#: clamav-milter.c:591
-msgid ""
-"\t--broadcast\t\t-B [IFACE]\tBroadcast to a network manager when a virus is "
-"found."
-msgstr ""
-
-#: clamav-milter.c:592
-msgid "\t--chroot=DIR\t\t-C DIR\tChroot to dir when starting."
-msgstr ""
-
-#: clamav-milter.c:593
-msgid "\t--config-file=FILE\t-c FILE\tRead configuration from FILE."
-msgstr ""
-
-#: clamav-milter.c:594
-msgid "\t--debug\t\t\t-D\tPrint debug messages."
-msgstr ""
-
-#: clamav-milter.c:595
-msgid ""
-"\t--detect-forged-local-address\t-L\tReject mails that claim to be from us."
-msgstr ""
-
-#: clamav-milter.c:596
-msgid "\t--dont-blacklist\t-K\tDon't blacklist a given IP."
-msgstr ""
-
-#: clamav-milter.c:597
-msgid ""
-"\t--dont-scan-on-error\t-d\tPass e-mails through unscanned if a system error "
-"occurs."
-msgstr ""
-
-#: clamav-milter.c:598
-msgid "\t--dont-wait\t\t\tAsk remote end to resend if max-children exceeded."
-msgstr ""
-
-#: clamav-milter.c:599
-msgid "\t--external\t\t-e\tUse an external scanner (usually clamd)."
-msgstr ""
-
-#: clamav-milter.c:600
-msgid ""
-"\t--freshclam-monitor=SECS\t-M SECS\tHow often to check for database update."
-msgstr ""
-
-#: clamav-milter.c:601
-msgid "\t--from=EMAIL\t\t-a EMAIL\tError messages come from here."
-msgstr ""
-
-#: clamav-milter.c:602
-msgid "\t--force-scan\t\t-f\tForce scan all messages (overrides (-o and -l)."
-msgstr ""
-
-#: clamav-milter.c:603
-msgid "\t--help\t\t\t-h\tThis message."
-msgstr ""
-
-#: clamav-milter.c:604
-msgid "\t--headers\t\t-H\tInclude original message headers in the report."
-msgstr ""
-
-#: clamav-milter.c:605
-msgid ""
-"\t--ignore IPaddr\t\t-I IPaddr\tAdd IPaddr to LAN IP list (see --local)."
-msgstr ""
-
-#: clamav-milter.c:606
-msgid "\t--local\t\t\t-l\tScan messages sent from machines on our LAN."
-msgstr ""
-
-#: clamav-milter.c:607
-msgid "\t--max-childen\t\t-m\tMaximum number of concurrent scans."
-msgstr ""
-
-#: clamav-milter.c:608
-msgid "\t--outgoing\t\t-o\tScan outgoing messages from this machine."
-msgstr ""
-
-#: clamav-milter.c:609
-msgid "\t--noreject\t\t-N\tDon't reject viruses, silently throw them away."
-msgstr ""
-
-#: clamav-milter.c:610
-msgid "\t--noxheader\t\t-n\tSuppress X-Virus-Scanned/X-Virus-Status headers."
-msgstr ""
-
-#: clamav-milter.c:611
-msgid "\t--pidfile=FILE\t\t-i FILE\tLocation of pidfile."
-msgstr ""
-
-#: clamav-milter.c:612
-msgid "\t--postmaster\t\t-p EMAIL\tPostmaster address [default=postmaster]."
-msgstr ""
-
-#: clamav-milter.c:613
-msgid "\t--postmaster-only\t-P\tSend notifications only to the postmaster."
-msgstr ""
-
-#: clamav-milter.c:614
-msgid "\t--quiet\t\t\t-q\tDon't send e-mail notifications of interceptions."
-msgstr ""
-
-#: clamav-milter.c:615
-msgid "\t--quarantine=USER\t-Q EMAIL\tQuarantine e-mail account."
-msgstr ""
-
-#: clamav-milter.c:616
-msgid "\t--report-phish=EMAIL\t-r EMAIL\tReport phish to this email address."
-msgstr ""
-
-#: clamav-milter.c:617
-msgid ""
-"\t--report-phish-false-positives=EMAIL\t-R EMAIL\tReport phish false "
-"positves to this email address."
-msgstr ""
-
-#: clamav-milter.c:618
-msgid "\t--quarantine-dir=DIR\t-U DIR\tDirectory to store infected emails."
-msgstr ""
-
-#: clamav-milter.c:619
-msgid ""
-"\t--server=SERVER\t\t-s SERVER\tHostname/IP address of server(s) running "
-"clamd (when using TCPsocket)."
-msgstr ""
-
-#: clamav-milter.c:620
-msgid "\t--sendmail-cf=FILE\t\tLocation of the sendmail.cf file to verify"
-msgstr ""
-
-#: clamav-milter.c:621
-msgid "\t--sign\t\t\t-S\tAdd a hard-coded signature to each scanned message."
-msgstr ""
-
-#: clamav-milter.c:622
-msgid "\t--signature-file=FILE\t-F FILE\tLocation of signature file."
-msgstr ""
-
-#: clamav-milter.c:623
-msgid "\t--template-file=FILE\t-t FILE\tLocation of e-mail template file."
-msgstr ""
-
-#: clamav-milter.c:624
-msgid ""
-"\t--template-headers=FILE\t\tLocation of e-mail headers for template file."
-msgstr ""
-
-#: clamav-milter.c:625
-msgid "\t--timeout=SECS\t\t-T SECS\tTimeout waiting to childen to die."
-msgstr ""
-
-#: clamav-milter.c:626
-msgid ""
-"\t--whitelist-file=FILE\t-W FILE\tLocation of the file of whitelisted "
-"addresses"
-msgstr ""
-
-#: clamav-milter.c:627
-msgid "\t--version\t\t-V\tPrint the version number of this software."
-msgstr ""
-
-#: clamav-milter.c:629
-msgid "\t--debug-level=n\t\t-x n\tSets the debug level to 'n'."
-msgstr ""
-
-#: clamav-milter.c:631
-msgid ""
-"\n"
-"For more information type \"man clamav-milter\"."
-msgstr ""
-
-#: clamav-milter.c:632
-msgid "For bug reports, please refer to http://www.clamav.net/bugs"
-msgstr ""
-
-#: clamav-milter.c:931
-#, c-format
-msgid "%s: %s, -I may only be given %d times\n"
-msgstr ""
-
-#: clamav-milter.c:937
-#, c-format
-msgid "%s: Cannot convert -I%s to IPaddr\n"
-msgstr ""
-
-#: clamav-milter.c:1051
-#, c-format
-msgid "%s: SESSIONS mode requires --external\n"
-msgstr ""
-
-#: clamav-milter.c:1059
-#, c-format
-msgid "%s: No socket-addr given\n"
-msgstr ""
-
-#: clamav-milter.c:1066
-#, c-format
-msgid "%s: socket-addr (%s) doesn't agree with sendmail.cf\n"
-msgstr ""
-
-#: clamav-milter.c:1082
-#, c-format
-msgid "%s: when using inet: connexion to sendmail you must enable --local\n"
-msgstr ""
-
-#: clamav-milter.c:1094
-#, c-format
-msgid "%s: Can't parse the config file %s\n"
-msgstr ""
-
-#: clamav-milter.c:1101
-#, c-format
-msgid "%s: --detect-forged-local-addresses is not compatible with --outgoing\n"
-msgstr ""
-
-#: clamav-milter.c:1105
-#, c-format
-msgid "%s: --detect-forged-local-addresses is not compatible with --local\n"
-msgstr ""
-
-#: clamav-milter.c:1109
-#, c-format
-msgid "%s: --detect-forged-local-addresses is not compatible with --force\n"
-msgstr ""
-
-#: clamav-milter.c:1153
-#, c-format
-msgid ""
-"%s: The iface option to --broadcast is not supported on your operating "
-"system\n"
-msgstr ""
-
-#: clamav-milter.c:1162
-#, c-format
-msgid "%s: Can't get information about user %s\n"
-msgstr ""
-
-#: clamav-milter.c:1173
-#, c-format
-msgid "%s: AllowSupplementaryGroups: initgroups not supported.\n"
-msgstr ""
-
-#: clamav-milter.c:1191
-#, c-format
-msgid "Running as user %s (UID %d, GID %d)\n"
-msgstr ""
-
-#: clamav-milter.c:1247
-#, c-format
-msgid "%s: You cannot use black hole mode unless %s is a TrustedUser\n"
-msgstr ""
-
-#: clamav-milter.c:1253
-#, c-format
-msgid "^%s: running as root is not recommended (check \"User\" in %s)\n"
-msgstr ""
-
-#: clamav-milter.c:1255
-#, c-format
-msgid "%s: Only root can set an interface for --broadcast\n"
-msgstr ""
-
-#: clamav-milter.c:1260
-#, c-format
-msgid "%s: Advisory mode doesn't work with quarantine mode\n"
-msgstr ""
-
-#: clamav-milter.c:1268
-#, c-format
-msgid "%s: Advisory mode doesn't work with quarantine directories\n"
-msgstr ""
-
-#: clamav-milter.c:1274
-#, c-format
-msgid "%s: the quarantine directory must not contain the string 'ERROR'\n"
-msgstr ""
-
-#: clamav-milter.c:1280
-#, c-format
-msgid "%s: the quarantine directory must not contain the string 'FOUND'\n"
-msgstr ""
-
-#: clamav-milter.c:1286
-#, c-format
-msgid "%s: the quarantine directory must not contain the string 'OK'\n"
-msgstr ""
-
-#: clamav-milter.c:1303
-#, c-format
-msgid "%s: insecure quarantine directory %s (mode 0%o)\n"
-msgstr ""
-
-#: clamav-milter.c:1344
-#, c-format
-msgid "%s: ReadTimeout must not be negative in %s\n"
-msgstr ""
-
-#: clamav-milter.c:1353
-#, c-format
-msgid "%s: StreamMaxLength must not be negative in %s\n"
-msgstr ""
-
-#: clamav-milter.c:1386
-#, c-format
-msgid ""
-"%s: (-q && !LogSyslog): warning - all interception message methods are off\n"
-msgstr ""
-
-#: clamav-milter.c:1402
-#, c-format
-msgid "%s: --max-children must be given if --external is not given\n"
-msgstr ""
-
-#: clamav-milter.c:1406
-#, c-format
-msgid "%s: --freshclam_monitor must be at least one second\n"
-msgstr ""
-
-#: clamav-milter.c:1420
-#, c-format
-msgid "%s: --timeout must not be given if --external is not given\n"
-msgstr ""
-
-#: clamav-milter.c:1433
-#, c-format
-msgid "%s: No emails will be scanned"
-msgstr ""
-
-#: clamav-milter.c:1444
-#, c-format
-msgid "%s: You can select one server type only (local/TCP) in %s\n"
-msgstr ""
-
-#: clamav-milter.c:1449
-#, c-format
-msgid "%s: You cannot use the --server option when using LocalSocket in %s\n"
-msgstr ""
-
-#: clamav-milter.c:1459
-#, c-format
-msgid "The connexion from sendmail to %s (%s) must not\n"
-msgstr ""
-
-#: clamav-milter.c:1461
-#, c-format
-msgid "be the same as the connexion to clamd (%s) in %s\n"
-msgstr ""
-
-#: clamav-milter.c:1471 clamav-milter.c:1498
-#, c-format
-msgid "Can't talk to clamd server via %s\n"
-msgstr ""
-
-#: clamav-milter.c:1473 clamav-milter.c:1500
-#, c-format
-msgid "Check your entry for LocalSocket in %s\n"
-msgstr ""
-
-#: clamav-milter.c:1510
-msgid "!Can't create a clamd session"
-msgstr ""
-
-#: clamav-milter.c:1527
-#, c-format
-msgid "%s: --quarantine-dir not supported for TCPSocket - use --quarantine\n"
-msgstr ""
-
-#: clamav-milter.c:1542
-#, c-format
-msgid "%s: hostname %s is longer than %d characters\n"
-msgstr ""
-
-#: clamav-milter.c:1561 clamav-milter.c:1694
-#, c-format
-msgid "%s: --max-children must be given in sessions mode\n"
-msgstr ""
-
-#: clamav-milter.c:1567
-#, c-format
-msgid ""
-"%1$s: --max-children (%2$d) is lower than the number of servers you have (%3"
-"$d)\n"
-msgstr ""
-
-#: clamav-milter.c:1594
-#, c-format
-msgid "%s: Unknown host %s\n"
-msgstr ""
-
-#: clamav-milter.c:1624
-msgid "Waiting for clamd to come up\n"
-msgstr ""
-
-#: clamav-milter.c:1638
-#, c-format
-msgid "Can't talk to clamd server %s on port %d\n"
-msgstr ""
-
-#: clamav-milter.c:1642
-#, c-format
-msgid "Check the value for TCPAddr in %s\n"
-msgstr ""
-
-#: clamav-milter.c:1644
-#, c-format
-msgid "Check the value for TCPAddr in clamd.conf on %s\n"
-msgstr ""
-
-#: clamav-milter.c:1660 clamav-milter.c:1668 clamav-milter.c:4773
-msgid "!Can't find any clamd server\n"
-msgstr ""
-
-#: clamav-milter.c:1661 clamav-milter.c:1666
-#, c-format
-msgid "Check your entry for TCPSocket in %s\n"
-msgstr ""
-
-#: clamav-milter.c:1674
-#, c-format
-msgid "%s: You must select server type (local/TCP) in %s\n"
-msgstr ""
-
-#: clamav-milter.c:1777
-#, c-format
-msgid "When debugging it is recommended that you use Foreground mode in %s\n"
-msgstr ""
-
-#: clamav-milter.c:1778
-msgid "\tso that you can see all of the messages"
-msgstr ""
-
-#: clamav-milter.c:1886
-#, c-format
-msgid "%s: ScanMail not defined in %s (needed without --external), enabling\n"
-msgstr ""
-
-#: clamav-milter.c:1946
-msgid "Starting clamav-milter"
-msgstr ""
-
-#: clamav-milter.c:1974
-#, c-format
-msgid "!pidfile: '%s' must be a full pathname"
-msgstr ""
-
-#: clamav-milter.c:1990
-#, c-format
-msgid "!Can't save PID in file %s\n"
-msgstr ""
-
-#: clamav-milter.c:2058
-#, c-format
-msgid "Starting %s\n"
-msgstr ""
-
-#: clamav-milter.c:2059
-msgid "*Debugging is on\n"
-msgstr ""
-
-#: clamav-milter.c:2159
-#, c-format
-msgid "Check clamd server %s - it may be down\n"
-msgstr ""
-
-#: clamav-milter.c:2164
-msgid "Check clamd server - it may be down"
-msgstr ""
-
-#: clamav-milter.c:2374
-msgid "No free clamd sessions\n"
-msgstr ""
-
-#: clamav-milter.c:2495
-msgid "^Couldn't establish a connexion to any clamd server\n"
-msgstr ""
-
-#: clamav-milter.c:2519
-#, c-format
-msgid "^findServer: select failed (maxsock = %d)\n"
-msgstr ""
-
-#: clamav-milter.c:2533
-msgid "^findServer: No response from any server\n"
-msgstr ""
-
-#: clamav-milter.c:2602
-#, c-format
-msgid "^Check clamd server %s - it may be down\n"
-msgstr ""
-
-#: clamav-milter.c:2606
-msgid "Check clamd server - it may be down\n"
-msgstr ""
-
-#: clamav-milter.c:2630
-msgid "!clamfi_connect: ctx is null"
-msgstr ""
-
-#: clamav-milter.c:2634
-msgid "!clamfi_connect: hostname is null"
-msgstr ""
-
-#: clamav-milter.c:2670
-#, c-format
-msgid "clamfi_connect: Unexpected sa_family %d\n"
-msgstr ""
-
-#: clamav-milter.c:2680
-msgid "clamfi_connect: remoteIP is null"
-msgstr ""
-
-#: clamav-milter.c:2688
-#, c-format
-msgid "clamfi_connect: connexion from %s"
-msgstr ""
-
-#: clamav-milter.c:2690
-#, c-format
-msgid "clamfi_connect: connexion from %s [%s]"
-msgstr ""
-
-#: clamav-milter.c:2709
-msgid "Can't get sendmail hostname"
-msgstr ""
-
-#: clamav-milter.c:2717
-#, c-format
-msgid "^Access Denied: Host Unknown (%s)"
-msgstr ""
-
-#: clamav-milter.c:2726
-#, c-format
-msgid "Can't find entry for IP address %s in DNS - check your DNS setting\n"
-msgstr ""
-
-#: clamav-milter.c:2736
-#, c-format
-msgid "^Access Denied: Can't get IP address for (%s)"
-msgstr ""
-
-#: clamav-milter.c:2752
-#, c-format
-msgid "^Access Denied for %s[%s]"
-msgstr ""
-
-#: clamav-milter.c:2768
-msgid "*clamfi_connect: not scanning outgoing messages"
-msgstr ""
-
-#: clamav-milter.c:2774
-msgid "*clamfi_connect: not scanning local messages\n"
-msgstr ""
-
-#: clamav-milter.c:2787
-msgid "^clamfi_connect: gethostname failed"
-msgstr ""
-
-#: clamav-milter.c:2792
-msgid "Rejected connexion falsely claiming to be from here\n"
-msgstr ""
-
-#: clamav-milter.c:2793
-msgid "You have claimed to be me, but you are not"
-msgstr ""
-
-#: clamav-milter.c:2794 clamav-milter.c:3141
-msgid "Forged local address detected"
-msgstr ""
-
-#: clamav-milter.c:2810
-#, c-format
-msgid "%s is blacklisted because your machine is infected with a virus"
-msgstr ""
-
-#: clamav-milter.c:2812 clamav-milter.c:2924
-msgid "Blacklisted IP detected"
-msgstr ""
-
-#: clamav-milter.c:2868
-msgid "*clamfi_envfrom: ignoring whitelisted message"
-msgstr ""
-
-#: clamav-milter.c:2882
-msgid "Rejected email with empty from field"
-msgstr ""
-
-#: clamav-milter.c:2883
-msgid "You have not said who the email is from"
-msgstr ""
-
-#: clamav-milter.c:2884
-msgid "Reject email with empty from field"
-msgstr ""
-
-#: clamav-milter.c:2902
-msgid "AV system temporarily overloaded - please try later"
-msgstr ""
-
-#: clamav-milter.c:2994
-msgid "Suspicious recipient address blocked"
-msgstr ""
-
-#: clamav-milter.c:2998
-#, c-format
-msgid "Will blacklist %s for %d seconds because of cracking attempt\n"
-msgstr ""
-
-#: clamav-milter.c:3108
-msgid "*clamfi_eoh\n"
-msgstr ""
-
-#: clamav-milter.c:3133
-msgid "clamfi_eoh: gethostname failed"
-msgstr ""
-
-#: clamav-milter.c:3139
-#, c-format
-msgid "Rejected email falsely claiming to be from %s"
-msgstr ""
-
-#: clamav-milter.c:3140
-msgid "You have claimed to be from me, but you are not"
-msgstr ""
-
-#: clamav-milter.c:3187
-msgid "*clamfi_enveoh: ignoring whitelisted message"
-msgstr ""
-
-#: clamav-milter.c:3199
-#, c-format
-msgid "*clamfi_envbody: %lu bytes"
-msgstr ""
-
-#: clamav-milter.c:3256
-#, c-format
-msgid "%s: Message more than StreamMaxLength (%ld) bytes - not scanned\n"
-msgstr ""
-
-#: clamav-milter.c:3259 clamav-milter.c:3585
-msgid "Not Scanned - StreamMaxLength exceeded"
-msgstr ""
-
-#: clamav-milter.c:3322
-#, c-format
-msgid "^Failed to delete X-Virus-Status header %d\n"
-msgstr ""
-
-#: clamav-milter.c:3377
-#, c-format
-msgid "failed to send SCAN %s command to clamd\n"
-msgstr ""
-
-#: clamav-milter.c:3398
-msgid "failed to send SCAN command to clamd\n"
-msgstr ""
-
-#: clamav-milter.c:3415
-#, c-format
-msgid "Waiting to read status from fd %d\n"
-msgstr ""
-
-#: clamav-milter.c:3427
-#, c-format
-msgid "*clamfi_eom: read %s\n"
-msgstr ""
-
-#: clamav-milter.c:3445
-#, c-format
-msgid "clamfi_eom: read nothing from clamd on %s\n"
-msgstr ""
-
-#: clamav-milter.c:3490 clamav-milter.c:3537
-msgid "Error determining host"
-msgstr ""
-
-#: clamav-milter.c:3551
-#, c-format
-msgid "%s: Ignoring %s false positive from %s received from %s\n"
-msgstr ""
-
-#: clamav-milter.c:3567
-#, c-format
-msgid "#Reported phishing false positive to %s"
-msgstr ""
-
-#: clamav-milter.c:3569
-#, c-format
-msgid "^Couldn't report false positive to %s\n"
-msgstr ""
-
-#: clamav-milter.c:3571
-msgid "^Can't set phish FP header\n"
-msgstr ""
-
-#: clamav-milter.c:3582
-#, c-format
-msgid "%s: Message more than StreamMaxLength (%ld) bytes - not scanned"
-msgstr ""
-
-#: clamav-milter.c:3590
-msgid "Not Scanned"
-msgstr ""
-
-#: clamav-milter.c:3618
-msgid "Infected with"
-msgstr ""
-
-#: clamav-milter.c:3640
-#, c-format
-msgid "Intercepted virus from %s to"
-msgstr ""
-
-#: clamav-milter.c:3732
-msgid "Subject: Virus intercepted\n"
-msgstr ""
-
-#: clamav-milter.c:3747
-#, c-format
-msgid "!Can't open e-mail template header file %s"
-msgstr ""
-
-#: clamav-milter.c:3762 clamav-milter.c:3766
-msgid "\n"
-msgstr ""
-
-#: clamav-milter.c:3775
-msgid "A message you sent to\n"
-msgstr ""
-
-#: clamav-milter.c:3785
-#, c-format
-msgid "The message %1$s sent from %2$s to\n"
-msgstr ""
-
-#: clamav-milter.c:3788
-#, c-format
-msgid "A message sent from %s to\n"
-msgstr ""
-
-#: clamav-milter.c:3793
-#, c-format
-msgid "contained %s and has not been accepted for delivery.\n"
-msgstr ""
-
-#: clamav-milter.c:3796
-#, c-format
-msgid ""
-"\n"
-"The message in question has been quarantined as %s\n"
-msgstr ""
-
-#: clamav-milter.c:3799
-#, c-format
-msgid ""
-"\n"
-"The message was received by %1$s from %2$s via %3$s\n"
-"\n"
-msgstr ""
-
-#: clamav-milter.c:3802
-msgid ""
-"For your information, the original message headers were:\n"
-"\n"
-msgstr ""
-
-#: clamav-milter.c:3815
-#, c-format
-msgid ""
-"\n"
-"The infected machine is likely to be here:\n"
-"%s\t\n"
-msgstr ""
-
-#: clamav-milter.c:3822
-#, c-format
-msgid "%s: Failed to notify clamAV interception - see dead.letter\n"
-msgstr ""
-
-#: clamav-milter.c:3824
-#, c-format
-msgid "^Can't execute '%s' to send virus notice"
-msgstr ""
-
-#: clamav-milter.c:3846
-#, c-format
-msgid "#Reported phishing to %s"
-msgstr ""
-
-#: clamav-milter.c:3848
-#, c-format
-msgid "^Couldn't report to %s\n"
-msgstr ""
-
-#: clamav-milter.c:3854
-msgid "^Can't set anti-phish header\n"
-msgstr ""
-
-#: clamav-milter.c:3872
-#, c-format
-msgid "^Can't set quarantine user %s"
-msgstr ""
-
-#: clamav-milter.c:3906
-#, c-format
-msgid "virus %s detected by ClamAV - http://www.clamav.net"
-msgstr ""
-
-#: clamav-milter.c:3911
-#, c-format
-msgid "Will blacklist %s for %d seconds because of %s\n"
-msgstr ""
-
-#: clamav-milter.c:3920
-msgid "Unknown"
-msgstr ""
-
-#: clamav-milter.c:3921
-#, c-format
-msgid "!%s: incorrect message \"%s\" from clamd"
-msgstr ""
-
-#: clamav-milter.c:3926
-msgid "Clean"
-msgstr ""
-
-#: clamav-milter.c:3930
-#, c-format
-msgid "%s: clean message from %s\n"
-msgstr ""
-
-#: clamav-milter.c:3932
-msgid "an unknown sender"
-msgstr ""
-
-#: clamav-milter.c:4020
-#, c-format
-msgid "!Can't remove clean file %s"
-msgstr ""
-
-#: clamav-milter.c:4193 clamav-milter.c:4197
-#, c-format
-msgid "!write failure (%lu bytes) to %s: %s\n"
-msgstr ""
-
-#: clamav-milter.c:4209 clamav-milter.c:4213
-#, c-format
-msgid "!write failure (%lu bytes) to clamd: %s\n"
-msgstr ""
-
-#: clamav-milter.c:4290
-#, c-format
-msgid "!No data received from clamd in %d seconds\n"
-msgstr ""
-
-#: clamav-milter.c:4318
-#, c-format
-msgid "Can't stat %s"
-msgstr ""
-
-#: clamav-milter.c:4328
-#, c-format
-msgid "Can't open %s"
-msgstr ""
-
-#: clamav-milter.c:4447
-#, c-format
-msgid "mkdir %s failed"
-msgstr ""
-
-#: clamav-milter.c:4461
-#, c-format
-msgid "mktemp %s failed"
-msgstr ""
-
-#: clamav-milter.c:4470
-#, c-format
-msgid "Temporary quarantine file %s creation failed"
-msgstr ""
-
-#: clamav-milter.c:4581
-#, c-format
-msgid "!failed to send STREAM command clamd server %d"
-msgstr ""
-
-#: clamav-milter.c:4589
-msgid "!failed to send STREAM command clamd"
-msgstr ""
-
-#: clamav-milter.c:4600
-msgid "!failed to create TCPSocket to talk to clamd"
-msgstr ""
-
-#: clamav-milter.c:4611 clamav-milter.c:4624
-msgid "!recv failed from clamd getting PORT"
-msgstr ""
-
-#: clamav-milter.c:4613 clamav-milter.c:4626
-msgid "!EOF from clamd getting PORT"
-msgstr ""
-
-#: clamav-milter.c:4637
-#, c-format
-msgid "!Expected port information from clamd, got '%s'"
-msgstr ""
-
-#: clamav-milter.c:4657 clamav-milter.c:4660
-#, c-format
-msgid "Connecting to local port %d - data %d cmd %d\n"
-msgstr ""
-
-#: clamav-milter.c:4673 clamav-milter.c:4676
-#, c-format
-msgid "!Failed to connect to port %d given by clamd: %s"
-msgstr ""
-
-#: clamav-milter.c:4785
-#, c-format
-msgid "!Can't open %s\n"
-msgstr ""
-
-#: clamav-milter.c:4799
-#, c-format
-msgid "!Clamd (pid %d) seems to have died\n"
-msgstr ""
-
-#: clamav-milter.c:4825
-#, c-format
-msgid "!Can't open e-mail template file %s"
-msgstr ""
-
-#: clamav-milter.c:4832
-#, c-format
-msgid "!Can't stat e-mail template file %s"
-msgstr ""
-
-#: clamav-milter.c:4839
-msgid "!Out of memory"
-msgstr ""
-
-#: clamav-milter.c:4844
-#, c-format
-msgid "!Error reading e-mail template file %s"
-msgstr ""
-
-#: clamav-milter.c:4872
-#, c-format
-msgid "!%s: Unknown clamAV variable \"%c\"\n"
-msgstr ""
-
-#: clamav-milter.c:4882
-#, c-format
-msgid "!%s: Unterminated sendmail variable \"%s\"\n"
-msgstr ""
-
-#: clamav-milter.c:4891
-#, c-format
-msgid "!%s: Unknown sendmail variable \"%s\"\n"
-msgstr ""
-
-#: clamav-milter.c:4957
-#, c-format
-msgid "!mkdir %s failed\n"
-msgstr ""
-
-#: clamav-milter.c:4982
-#, c-format
-msgid "^Can't rename %1$s to %2$s\n"
-msgstr ""
-
-#: clamav-milter.c:4990
-#, c-format
-msgid "Email quarantined as %s\n"
-msgstr ""
-
-#: clamav-milter.c:5098
-#, c-format
-msgid "[Virus] %s"
-msgstr ""
-
-#: clamav-milter.c:5307
-msgid ""
-"!No response from any clamd server - your AV system is not scanning emails\n"
-msgstr ""
-
-#: clamav-milter.c:5325
-msgid "Subject: ClamAV Down\n"
-msgstr ""
-
-#: clamav-milter.c:5328
-msgid ""
-"This is an automatic message\n"
-"\n"
-msgstr ""
-
-#: clamav-milter.c:5331
-msgid "The clamd program cannot be contacted.\n"
-msgstr ""
-
-#: clamav-milter.c:5333
-msgid "No clamd server can be contacted.\n"
-msgstr ""
-
-#: clamav-milter.c:5335
-msgid "Emails may not be being scanned, please check your servers.\n"
-msgstr ""
-
-#: clamav-milter.c:5396 clamav-milter.c:5542
-msgid "!No emails will be scanned"
-msgstr ""
-
-#: clamav-milter.c:5606
-#, c-format
-msgid "Stopping %s\n"
-msgstr ""
-
-#: clamav-milter.c:5654
-msgid "Stopping clamav-milter"
-msgstr ""
-
-#: clamav-milter.c:5802
-#, c-format
-msgid "Loaded %s\n"
-msgstr ""
-
-#: clamav-milter.c:5806
-#, c-format
-msgid "ClamAV: Protecting against %u viruses\n"
-msgstr ""
-
-#: clamav-milter.c:5954
-#, c-format
-msgid "!Can't open whitelist file %s"
-msgstr ""
-
-#: clamav-milter.c:5961
-msgid "!Can't create whitelist table"
-msgstr ""
-
-#: clamav-milter.c:6049
-msgid "!Can't create blacklist table"
-msgstr ""
-
-#: clamav-milter.c:6472
-msgid "^MX peers will not be immune from being blacklisted"
-msgstr ""
-
-#: clamav-milter.c:6498
-msgid "!Can't create pipe\n"
-msgstr ""
-
-#: clamav-milter.c:6519
-msgid "!Can't fork\n"
-msgstr ""
-
-#: clamav-milter.c:6567
-#, c-format
-msgid "^Can't execute '%s' to expand '%s' (error %d)\n"
-msgstr ""
-
-#: clamav-milter.c:6625
-#, c-format
-msgid "hit max-children limit (%u >= %u)\n"
-msgstr ""
-
-#: clamav-milter.c:6626
-#, c-format
-msgid "hit max-children limit (%u >= %u): waiting for some to exit\n"
-msgstr ""
-
-#: clamav-milter.c:6648
-#, c-format
-msgid "n_children %d: waiting %d seconds for some to exit\n"
-msgstr ""
-
-#: clamav-milter.c:6661
-#, c-format
-msgid "Finished waiting, n_children = %d\n"
-msgstr ""
-
-#: clamav-milter.c:6669
-msgid "*Timeout waiting for a child to die\n"
-msgstr ""
-
-#: clamav-milter.c:6703
-#, c-format
-msgid "Won't blacklist %s\n"
-msgstr ""
diff --git a/database/daily.cvd b/database/daily.cvd
index 796637f..6918208 100644
Binary files a/database/daily.cvd and b/database/daily.cvd differ
diff --git a/database/main.cvd b/database/main.cvd
index c9500d0..b751b87 100644
Binary files a/database/main.cvd and b/database/main.cvd differ
diff --git a/docs/html/node56.html b/docs/html/node56.html
index c5ddefa..030eb7b 100644
--- a/docs/html/node56.html
+++ b/docs/html/node56.html
@@ -460,7 +460,6 @@ Donors</A>
<ADDRESS>
Tomasz Kojm
2009-02-25
-
</ADDRESS>
</BODY>
</HTML>
--
Debian repository for ClamAV
More information about the Pkg-clamav-commits
mailing list