Squashed commit of the following:

commit 0ddbd1a7117e207b8aa87079568a056691d5eb32
Author: acab <acab@1337ness.(none)>
Date:   Thu Nov 27 17:18:04 2008 +0100

    to be committed

commit 51f8010a275717b8a56a3ab22d49755899819518
Author: acab <acab@1337ness.(none)>
Date:   Thu Nov 27 15:18:40 2008 +0100

    mangle body

commit cd38463f4739f4a7778b6bf294cfb2166024656e
Author: acab <acab@1337ness.(none)>
Date:   Thu Nov 27 14:43:39 2008 +0100

    parse clamd result

commit 7b8a39495e59ac745342455f8e9aab09951d1041
Author: acab <acab@1337ness.(none)>
Date:   Thu Nov 27 03:19:45 2008 +0100

    handle calloc shifts

commit a58b732af99f9e3f18d2327e977432f1117028ee
Author: acab <acab@1337ness.(none)>
Date:   Thu Nov 27 02:07:19 2008 +0100

    spam added, local is b0rked

commit 22604b4b037cfdbc92d6b29986652e2f004bd1f3
Author: acab <acab@albe.digitalfuture.it>
Date:   Wed Nov 26 19:44:59 2008 +0100

    free/close stuff

commit 33a02aed984981d3e80ca4930a482f702624f08f
Author: aCaB <acab@digitalfuture.it>
Date:   Wed Nov 26 03:11:29 2008 +0100

    skeleton ready

commit 4630d9902ee74b6137abf6526c6a9ad3e41fc597
Author: aCaB <acab@digitalfuture.it>
Date:   Tue Nov 25 22:59:41 2008 +0100

    need to rebase

commit 083f5f98aecfce2763870f20ae97643d5683613a
Author: aCaB <acab@digitalfuture.it>
Date:   Tue Nov 25 22:45:11 2008 +0100

    in body()

commit 08f040f67de1264810953415c0a47c95ec9acff0
Author: aCaB <acab@digitalfuture.it>
Date:   Tue Nov 25 19:51:15 2008 +0100

    clamfi

commit bc08fe8f72580b8be81791a7c03ec38952781af7
Author: aCaB <acab@digitalfuture.it>
Date:   Tue Nov 25 16:47:17 2008 +0100

    adding milter

commit 34dcebd9294a059f2c45ec9d1817bdb75f423cb3
Author: aCaB <acab@digitalfuture.it>
Date:   Tue Nov 25 00:35:11 2008 +0100

    netcode works, fix to cfgparser

commit 3cc0997d907e817954328c60e43cdcca0667d6f3
Author: aCaB <acab@digitalfuture.it>
Date:   Mon Nov 24 23:46:05 2008 +0100

    socket probe

commit 0c3bbd6d03f8df931cb114b07150cd0b7dcd0aff
Author: aCaB <acab@digitalfuture.it>
Date:   Mon Nov 24 19:02:06 2008 +0100

    nonblock started

commit a1193ff0de0d0a3d9212d833110236b1329c1f2e
Author: aCaB <acab@digitalfuture.it>
Date:   Mon Nov 24 11:17:41 2008 +0100

    legacy options

commit 90519c59ff8a4f44fceaf84e8c40116254c73045
Author: aCaB <acab@digitalfuture.it>
Date:   Sun Nov 23 19:41:26 2008 +0100

    sockets pool

commit 897b0c5f82503530ba3fbb2fcc3a9c007488e90a
Author: aCaB <acab@digitalfuture.it>
Date:   Sun Nov 23 01:02:59 2008 +0100

    Logging done

commit 4cf3a218756271c74782a1649f728e1c6e977ae5
Author: aCaB <acab@digitalfuture.it>
Date:   Sat Nov 22 23:31:34 2008 +0100

    Config done

commit 93b271579f680286c697476c00d8eec7effb2fc4
Author: aCaB <acab@digitalfuture.it>
Date:   Sat Nov 22 22:50:42 2008 +0100

    Sanitise config file options

commit bf5e81b8561b258daaef134894761fa80d44f5b1
Author: aCaB <acab@digitalfuture.it>
Date:   Sat Nov 22 20:25:06 2008 +0100

    cfgparser hacks to allow for milter own conf

commit 8924e93b2567a1f378c2177b4011b67631b49cc1
Author: aCaB <acab@digitalfuture.it>
Date:   Sat Nov 22 19:03:45 2008 +0100

    command line parser

commit d2180e370f75948b6ce12f89979bda9e92ccd5f8
Author: aCaB <acab@digitalfuture.it>
Date:   Sat Nov 22 16:36:37 2008 +0100

    restart from scratch

commit 249d6cdbddbea622c949753aafbf48e526e0ef4d
Author: aCaB <acab@digitalfuture.it>
Date:   Sun Nov 16 19:39:12 2008 +0100

    more diversion

commit b948990103867b59c749da88d6384128c1e5e6d3
Author: aCaB <acab@digitalfuture.it>
Date:   Sun Nov 16 17:31:42 2008 +0100

    milter separation (milter)

commit 6dc259a5d4f8f6e4428953055510382160ef8df4
Author: aCaB <acab@digitalfuture.it>
Date:   Sun Nov 16 17:23:14 2008 +0100

    milter separation

git-svn-id: file:///var/lib/svn/clamav-devel/branches/milter-v2.0@4486 77e5149b-7576-45b1-b177-96237e5ba77b
remotes/push_mirror/0.95
aCaB 17 years ago
parent 88651f7c42
commit c6385428e2
  1. 10
      clamav-milter/Makefile.am
  2. 45
      clamav-milter/Makefile.in
  3. 7180
      clamav-milter/clamav-milter.c
  4. 6951
      clamav-milter/clamav-milter.ref.c
  5. 215
      clamav-milter/clamfi.c
  6. 11
      clamav-milter/clamfi.h
  7. 324
      clamav-milter/connpool.c
  8. 48
      clamav-milter/connpool.h
  9. 274
      clamav-milter/netcode.c
  10. 13
      clamav-milter/netcode.h
  11. 2
      clamconf/clamconf.c
  12. 2
      clamd/clamd.c
  13. 2
      clamdscan/client.c
  14. 166
      etc/clamav-milter.conf
  15. 6
      freshclam/freshclam.c
  16. 2
      freshclam/manager.c
  17. 2
      freshclam/notify.c
  18. 65
      shared/cfgparser.c
  19. 6
      shared/cfgparser.h
  20. 2
      shared/misc.c

@ -31,8 +31,14 @@ clamav_milter_SOURCES = \
$(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 \
$(top_srcdir)/shared/options.c \
$(top_srcdir)/shared/options.h \
connpool.c \
connpool.h \
netcode.c \
netcode.h \
clamfi.c \
clamfi.h \
clamav-milter.c
man_MANS = $(top_builddir)/docs/man/clamav-milter.8

@ -76,14 +76,18 @@ 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
$(top_srcdir)/shared/misc.h $(top_srcdir)/shared/options.c \
$(top_srcdir)/shared/options.h connpool.c connpool.h netcode.c \
netcode.h clamfi.c clamfi.h clamav-milter.c
@BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@am_clamav_milter_OBJECTS = \
@BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ cfgparser.$(OBJEXT) \
@BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ output.$(OBJEXT) \
@BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ getopt.$(OBJEXT) \
@BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ misc.$(OBJEXT) \
@BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ network.$(OBJEXT) \
@BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ options.$(OBJEXT) \
@BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ connpool.$(OBJEXT) \
@BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ netcode.$(OBJEXT) \
@BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ clamfi.$(OBJEXT) \
@BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ clamav-milter.$(OBJEXT)
clamav_milter_OBJECTS = $(am_clamav_milter_OBJECTS)
clamav_milter_LDADD = $(LDADD)
@ -273,8 +277,14 @@ top_srcdir = @top_srcdir@
@BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ $(top_srcdir)/shared/getopt.h \
@BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ $(top_srcdir)/shared/misc.c \
@BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ $(top_srcdir)/shared/misc.h \
@BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ $(top_srcdir)/shared/network.c \
@BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ $(top_srcdir)/shared/network.h \
@BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ $(top_srcdir)/shared/options.c \
@BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ $(top_srcdir)/shared/options.h \
@BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ connpool.c \
@BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ connpool.h \
@BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ netcode.c \
@BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ netcode.h \
@BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ clamfi.c \
@BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ clamfi.h \
@BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ clamav-milter.c
@BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@man_MANS = $(top_builddir)/docs/man/clamav-milter.8
@ -370,9 +380,12 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfgparser.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clamav-milter.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clamfi.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connpool.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/network.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netcode.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/options.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/output.Po@am__quote@
.c.o:
@ -452,19 +465,19 @@ misc.obj: $(top_srcdir)/shared/misc.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@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
@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
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/network.Tpo $(DEPDIR)/network.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/shared/network.c' object='network.o' libtool=no @AMDEPBACKSLASH@
options.o: $(top_srcdir)/shared/options.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT options.o -MD -MP -MF $(DEPDIR)/options.Tpo -c -o options.o `test -f '$(top_srcdir)/shared/options.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/options.c
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/options.Tpo $(DEPDIR)/options.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/shared/options.c' object='options.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@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
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o options.o `test -f '$(top_srcdir)/shared/options.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/options.c
network.obj: $(top_srcdir)/shared/network.c
@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`
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/network.Tpo $(DEPDIR)/network.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/shared/network.c' object='network.obj' libtool=no @AMDEPBACKSLASH@
options.obj: $(top_srcdir)/shared/options.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT options.obj -MD -MP -MF $(DEPDIR)/options.Tpo -c -o options.obj `if test -f '$(top_srcdir)/shared/options.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/options.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/options.c'; fi`
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/options.Tpo $(DEPDIR)/options.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/shared/options.c' object='options.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@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`
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o options.obj `if test -f '$(top_srcdir)/shared/options.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/options.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/options.c'; fi`
mostlyclean-libtool:
-rm -f *.lo

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,215 @@
/*
* Copyright (C)2008 Sourcefire, Inc.
*
* Author: aCaB <acab@clamav.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*/
#if HAVE_CONFIG_H
#include "clamav-config.h"
#endif
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <libmilter/mfapi.h>
#include "shared/output.h"
#include "connpool.h"
#include "netcode.h"
uint64_t maxfilesize;
#define CLAMFIBUFSZ 1424
struct CLAMFI {
char buffer[CLAMFIBUFSZ];
int local;
int main;
int alt;
unsigned int altsz;
unsigned int bufsz;
};
#define FREECF freecf(ctx, cf)
static void freecf(SMFICTX *ctx, struct CLAMFI *cf) {
close(cf->main);
close(cf->alt);
smfi_setpriv(ctx, NULL);
free(cf);
}
static sfsistat sendchunk(struct CLAMFI *cf, unsigned char *bodyp, size_t len, SMFICTX *ctx) {
if(cf->altsz > maxfilesize)
return SMFIS_CONTINUE; /* FIXME: SMFIS_SKIP needs negotiation (only for _body() */
if(cf->altsz + len > maxfilesize)
len = maxfilesize - cf->altsz;
if(cf->local) {
while(len) {
int n = write(cf->alt, bodyp, len);
if (n==-1) {
logg("!clamfi_body: Failed to write temporary file\n");
FREECF;
return SMFIS_TEMPFAIL;
}
len -= n;
bodyp += n;
}
} else {
int sendfailed = 0;
if(len < CLAMFIBUFSZ - cf->bufsz) {
memcpy(&cf->buffer[cf->bufsz], bodyp, len);
cf->bufsz += len;
} else if(len < CLAMFIBUFSZ) {
memcpy(&cf->buffer[cf->bufsz], bodyp, CLAMFIBUFSZ - cf->bufsz);
sendfailed = nc_send(cf->alt, cf->buffer, CLAMFIBUFSZ);
len -= (CLAMFIBUFSZ - cf->bufsz);
memcpy(cf->buffer, &bodyp[CLAMFIBUFSZ - cf->bufsz], len);
cf->bufsz = len;
} else {
sendfailed = nc_send(cf->alt, cf->buffer, cf->bufsz);
sendfailed += nc_send(cf->alt, bodyp, len);
cf->bufsz = 0;
}
if(sendfailed) {
logg("!clamfi_body: Streaming failed\n");
FREECF;
return SMFIS_TEMPFAIL;
}
}
cf->altsz += len;
return SMFIS_CONTINUE;
}
sfsistat clamfi_body(SMFICTX *ctx, unsigned char *bodyp, size_t len) {
struct CLAMFI *cf;
if(!(cf = (struct CLAMFI *)smfi_getpriv(ctx))) {
sfsistat ret;
cf = (struct CLAMFI *)malloc(sizeof(*cf));
if(!cf) {
logg("!clamfi_body: Failed to allocate CLAMFI struct\n");
return SMFIS_TEMPFAIL;
}
cf->altsz = 0;
cf->bufsz = 0;
if(nc_connect_rand(&cf->main, &cf->alt, &cf->local)) {
logg("!clamfi_body: Failed to initiate streaming/fdpassing\n");
free(cf);
return SMFIS_TEMPFAIL;
}
smfi_setpriv(ctx, (void *)cf);
if((ret = sendchunk(cf, (unsigned char *)"From clamav-milter\n", 19, ctx)) != SMFIS_CONTINUE)
return ret;
}
return sendchunk(cf, bodyp, len, ctx);
}
sfsistat clamfi_eom(SMFICTX *ctx) {
struct CLAMFI *cf;
char *reply;
int len, ret;
if(!(cf = (struct CLAMFI *)smfi_getpriv(ctx)))
return SMFIS_CONTINUE; /* whatever */
if(cf->local) {
struct iovec iov[1];
struct msghdr msg;
struct cmsghdr *cmsg;
unsigned char fdbuf[CMSG_SPACE(sizeof(int))];
char dummy[]="";
if(nc_send(cf->main, "nFILDES\n", 8)) {
logg("!clamfi_eom: FD scan request failed\n");
FREECF;
return SMFIS_TEMPFAIL;
}
lseek(cf->alt, 0, SEEK_SET);
iov[0].iov_base = dummy;
iov[0].iov_len = 1;
memset(&msg, 0, sizeof(msg));
msg.msg_control = fdbuf;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_controllen = CMSG_LEN(sizeof(int));
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
*(int *)CMSG_DATA(cmsg) = cf->alt;
if(sendmsg(cf->main, &msg, 0) == -1) {
/* FIXME: nonblock code needed (?) */
logg("!clamfi_eom: FD send failed\n");
FREECF;
return SMFIS_TEMPFAIL;
}
} else {
if(cf->bufsz && nc_send(cf->alt, cf->buffer, cf->bufsz)) {
logg("!clamfi_eom: Flushing failed\n");
FREECF;
return SMFIS_TEMPFAIL;
}
close(cf->alt);
}
reply = nc_recv(cf->main);
if(cf->local) close(cf->alt);
close(cf->main);
close(cf->alt);
smfi_setpriv(ctx, NULL);
free(cf);
if(!reply) {
logg("!clamfi_eom: no reply to scan request\n");
return SMFIS_TEMPFAIL;
}
len = strlen(reply);
if(len>5 && !strcmp(reply + len - 5, ": OK\n"))
ret = SMFIS_ACCEPT;
else if (len>7 && !strcmp(reply + len - 7, " FOUND\n"))
ret = SMFIS_REJECT;
else {
logg("!clamfi_eom: unknown reply from clamd\n");
ret = SMFIS_TEMPFAIL;
}
free(reply);
return ret;
}
/*
* Local Variables:
* mode: c
* c-basic-offset: 4
* tab-width: 8
* End:
* vim: set cindent smartindent autoindent softtabstop=4 shiftwidth=4 tabstop=8:
*/

@ -0,0 +1,11 @@
#ifndef _CLAMFI_H
#define _CLAMFI_H
#include <libmilter/mfapi.h>
uint64_t maxfilesize;
sfsistat clamfi_body(SMFICTX *ctx, unsigned char *bodyp, size_t len);
sfsistat clamfi_eom(SMFICTX *ctx);
#endif

@ -0,0 +1,324 @@
/*
* Copyright (C)2008 Sourcefire, Inc.
*
* Author: aCaB <acab@clamav.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*/
#if HAVE_CONFIG_H
#include "clamav-config.h"
#endif
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netdb.h>
#include <unistd.h>
#include <time.h>
#include "shared/cfgparser.h"
#include "shared/output.h"
#include "connpool.h"
#include "netcode.h"
#ifdef HAVE_GETADDRINFO
#define SETGAI(k, v) {(k)->gai = (void *)(v);} while(0)
#define FREESRV(k) { if((k).gai) freeaddrinfo((k).gai); else if((k).server) free((k).server); } while(0)
#else
#include <netdb.h>
#define SETGAI
#define FREESRV(k) { if ((k).server) free((k).server); } while(0)
#endif
struct CPOOL *cp = NULL;
static int cpool_addunix(char *path) {
struct sockaddr_un *srv;
struct CP_ENTRY *cpe = &cp->pool[cp->entries-1];
if(strlen(path)<2 || *path!='/') {
logg("!Unix clamd socket must be an absolute path\n");
return 1;
}
if(!(srv = (struct sockaddr_un *)malloc(sizeof(*srv)))) {
logg("!Out of memory allocating unix socket space\n");
return 1;
}
srv->sun_family = AF_UNIX;
strncpy(srv->sun_path, path, sizeof(srv->sun_path));
srv->sun_path[sizeof(srv->sun_path)-1]='\0';
cpe->type = 0;
cpe->dead = 1;
cpe->local = 1;
cpe->last_poll = 0;
cpe->server = (struct sockaddr *)srv;
cpe->socklen = sizeof(*srv);
SETGAI(cpe, NULL);
if(!cp->local_cpe) cp->local_cpe = cpe;
logg("*Local socket unix:%s added to the pool (slot %d)\n", srv->sun_path, cp->entries);
return 0;
}
static int islocal(struct sockaddr *sa, socklen_t addrlen) {
int s = socket(sa->sa_family, SOCK_STREAM, 0);
int ret;
if (!s) return 0;
ret = (bind(s, sa, addrlen) == 0);
close(s);
return ret;
}
#ifdef HAVE_GETADDRINFO
static int cpool_addtcp(char *addr, char *port) {
struct addrinfo hints, *res, *res2;;
struct CP_ENTRY *cpe = (struct CP_ENTRY *)&cp->pool[cp->entries-1];
memset(&hints, 0, sizeof(hints));
#ifdef SUPPORT_IPv6
hints.ai_family = AF_UNSPEC;
#else
hints.ai_family = AF_INET;
#endif
hints.ai_socktype = SOCK_STREAM;
if(getaddrinfo(addr, port ? port : "3310", &hints, &res)) {
logg("^Can't resolve hostname %s\n", addr ? addr : "");
return 1;
}
cpe->type = 1;
cpe->dead = 1;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_PASSIVE;
hints.ai_socktype = SOCK_STREAM;
#ifdef SUPPORT_IPv6
hints.ai_family = AF_UNSPEC;
#else
hints.ai_family = AF_INET;
#endif
if(!getaddrinfo(addr, NULL, &hints, &res2)) {
cpe->local = islocal(res2->ai_addr, res2->ai_addrlen);
freeaddrinfo(res2);
} else cpe->local = 0;
cpe->last_poll = 0;
cpe->server = res->ai_addr;
cpe->socklen = res->ai_addrlen;
SETGAI(cpe, res);
logg("*%s socket tcp:%s:%s added to the pool (slot %d)\n", cpe->local ? "Local" : "Remote", addr ? addr : "localhost", port ? port : "3310", cp->entries);
return 0;
}
#else
static int cpool_addtcp(char *addr, char *port) {
struct sockaddr_in *srv;
struct CP_ENTRY *cpe = (struct CP_ENTRY *)&cp->pool[cp->entries-1];
int nport = 3310;
if(port) {
nport = atoi(port);
if (nport<=0 || nport>65535) {
logg("!Bad port for clamd socket (%d)\n", nport);
return 1;
}
}
if(!(srv = malloc(sizeof(*srv)))) {
logg("!Out of memory allocating unix socket space\n");
return 1;
}
srv->sin_family = AF_INET;
if (addr) {
struct hostent *h;
if(!(h=gethostbyname(addr))) {
logg("^Can't resolve tcp socket hostname %s\n", addr);
free(srv);
return 1;
}
memcpy(&srv->sin_addr.s_addr, h->h_addr_list[0], 4);
} else {
srv->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
}
cpe->type = 1;
cpe->dead = 1;
srv->sin_port = htons(INADDR_ANY);
cpe->local = islocal(srv, sizeof(srv));
srv->sin_port = htons(nport);
cpe->last_poll = 0;
cpe->server = (struct sockaddr *)srv;
cpe->socklen = sizeof(*srv);
logg("*%s socket tcp:%s:%u added to the pool (slot %d)\n", cpe->local ? "Local" : "Remote", addr ? addr : "localhost", nport, cp->entries);
return 0;
}
#endif
int addslot(void) {
struct CP_ENTRY *cpe;
if(!(cpe = realloc(cp->pool, (cp->entries + 1) * sizeof(struct CP_ENTRY)))) {
logg("!Out of memory while initializing the connection pool\n");
cpool_free();
return 1;
}
if(cp->local_cpe)
cp->local_cpe = (struct CP_ENTRY *)((char *)cp->local_cpe + ((char *)cpe - (char *)cp->pool));
memset(&cpe[cp->entries], 0, sizeof(*cpe));
cp->pool = cpe;
cp->entries++;
return 0;
}
void cpool_probe(void) {
unsigned int i, dead=0;
struct CP_ENTRY *cpe = cp->pool;
time_t lastpoll = time(NULL) - 5*60;
for(i=1; i<=cp->entries; i++) {
if(cpe->dead && lastpoll > cpe->last_poll) {
nc_ping_entry(cpe);
logg("*Probe for slot %u returned: %s\n", i, cpe->dead ? "failed" : "success");
}
dead += cpe->dead;
cpe++;
}
cp->alive = cp->entries - dead;
if(!cp->alive)
logg("^No clamd server appears to be available, trying again in 5 minutes.\n");
}
void cpool_init(struct cfgstruct *copt) {
const struct cfgstruct *cpt;
int failed = 0;
if(!(cp=calloc(sizeof(*cp), 1))) {
logg("!Out of memory while initializing the connection pool");
return;
}
cp->local_cpe = NULL;
if((cpt = cfgopt(copt, "ClamdSocket"))->enabled) {
while(cpt) {
char *socktype = cpt->strarg;
if(addslot()) return;
if(!strncasecmp(socktype, "unix:", 5)) {
failed = cpool_addunix(socktype+5);
} else if(!strncasecmp(socktype, "tcp:", 4)) {
char *port = strrchr(socktype+4, ':');
if(port) {
*port='\0';
port++;
}
failed = cpool_addtcp(socktype+4, port);
} else {
logg("!Failed to parse ClamdSocket directive '%s'\n", socktype);
failed = 1;
}
if(failed) break;
cpt = (struct cfgstruct *) cpt->nextarg;
}
if(failed) {
cpool_free();
return;
}
}
#ifdef MILTER_LEGACY
if((cpt = cfgopt(copt, "LocalSocket"))->enabled) {
if(addslot()) return;
if(cpool_addunix(cpt->strarg)) {
cpool_free();
return;
}
}
if((cpt = cfgopt(copt, "TCPSocket"))->enabled) {
char *addr = NULL;
char port[5];
if(addslot()) return;
snprintf(port, 5, "%d", cpt->numarg);
port[5] = 0;
if((cpt = cfgopt(copt, "TCPAddr"))->enabled)
addr = cpt->strarg;
if(cpool_addtcp(addr, port)) {
cpool_free();
return;
}
}
#endif
if(!cp->entries) {
logg("!No ClamdSocket specified\n");
cpool_free();
return;
}
cpool_probe();
srand(time(NULL)); /* FIXME: naive ? */
}
void cpool_free(void) {
unsigned int i;
for(i=0; i<cp->entries; i++)
FREESRV(cp->pool[i]);
free(cp->pool);
free(cp);
}
struct CP_ENTRY *cpool_get_rand(void) {
unsigned int start, i;
struct CP_ENTRY *cpe;
if(!cp->alive) {
logg("!No sockets are alive. Probe forced...\n");
/* FIXME: yeah, actually do force smthng here */
return NULL;
}
start = rand() % cp->entries;
for(i=0; i<cp->entries; i++) {
cpe = &cp->pool[(i+start) % cp->entries];
if(cpe->dead) continue;
if(cpe->local && cp->local_cpe && !cp->local_cpe->dead)
return cp->local_cpe;
return cpe;
}
return NULL;
}
/*
* Local Variables:
* mode: c
* c-basic-offset: 4
* tab-width: 8
* End:
* vim: set cindent smartindent autoindent softtabstop=4 shiftwidth=4 tabstop=8:
*/

@ -0,0 +1,48 @@
#ifndef _CONNPOOL_H
#define _CONNPOOL_H
#if HAVE_CONFIG_H
#include "clamav-config.h"
#endif
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include "shared/cfgparser.h"
struct CP_ENTRY {
uint8_t type;
uint8_t dead;
uint8_t local;
time_t last_poll;
struct sockaddr *server;
socklen_t socklen;
#ifdef HAVE_GETADDRINFO
void *gai;
#endif
};
struct CPOOL {
unsigned int entries;
unsigned int alive;
struct CP_ENTRY *local_cpe;
struct CP_ENTRY *pool;
};
void cpool_init(struct cfgstruct *copt);
void cpool_free(void);
struct CP_ENTRY *cpool_get_rand(void);
extern struct CPOOL *cp;
#endif
/*
* Local Variables:
* mode: c
* c-basic-offset: 4
* tab-width: 8
* End:
* vim: set cindent smartindent autoindent softtabstop=4 shiftwidth=4 tabstop=8:
*/

@ -0,0 +1,274 @@
/*
* Copyright (C)2008 Sourcefire, Inc.
*
* Author: aCaB <acab@clamav.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*/
#if HAVE_CONFIG_H
#include "clamav-config.h"
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/select.h>
#include <time.h>
#include <errno.h>
#include "shared/output.h"
#include "netcode.h"
/* FIXME: for connect and send */
#define TIMEOUT 60
/* for recv */
long readtimeout;
int nc_socket(struct CP_ENTRY *cpe) {
int flags, s = socket(cpe->server->sa_family, SOCK_STREAM, 0);
if (s == -1) return -1;
flags = fcntl(s, F_GETFL, 0);
if (flags == -1) {
close(s);
return -1;
}
flags |= O_NONBLOCK;
if (fcntl(s, F_SETFL, flags) == -1) {
close(s);
return -1;
}
return s;
}
int nc_connect(int s, struct CP_ENTRY *cpe) {
time_t timeout = time(NULL) + TIMEOUT;
int res = connect(s, cpe->server, cpe->socklen);
struct timeval tv;
if (!res) return 0;
if (errno != EINPROGRESS) {
close(s);
return -1;
}
tv.tv_sec = TIMEOUT;
tv.tv_usec = 0;
while(1) {
fd_set fds;
int s_err;
socklen_t s_len = sizeof(s_err);
FD_ZERO(&fds);
FD_SET(s, &fds);
res = select(s+1, NULL, &fds, NULL, &tv);
if(res < 1) {
time_t now;
if (res == -1 && errno == EINTR && ((now = time(NULL)) < timeout)) {
tv.tv_sec = timeout - now;
tv.tv_usec = 0;
continue;
}
close(s);
return -1;
}
if (getsockopt(s, SOL_SOCKET, SO_ERROR, &s_err, &s_len) || s_err) {
logg("!getsockopt failed: %s\n", strerror(s_err));
close(s);
return -1;
}
return 0;
}
}
int nc_send(int s, const void *buf, size_t len) {
while(len) {
int res = send(s, buf, len, 0);
time_t timeout = time(NULL) + TIMEOUT;
struct timeval tv;
if(res!=-1) {
len-=res;
buf+=res;
timeout = time(NULL) + TIMEOUT;
continue;
}
if(errno != EAGAIN && errno != EWOULDBLOCK) {
close(s);
return 1;
}
tv.tv_sec = TIMEOUT;
tv.tv_usec = 0;
while(1) {
fd_set fds;
int s_err;
socklen_t s_len = sizeof(s_err);
FD_ZERO(&fds);
FD_SET(s, &fds);
res = select(s+1, NULL, &fds, NULL, &tv);
if(res < 1) {
time_t now;
if (res == -1 && errno == EINTR && ((now = time(NULL)) < timeout)) {
tv.tv_sec = timeout - now;
tv.tv_usec = 0;
continue;
}
close(s);
return 1;
}
if (getsockopt(s, SOL_SOCKET, SO_ERROR, &s_err, &s_len)) {
close(s);
return 1;
}
len-=s_len;
buf+=s_len;
break;
}
}
return 0;
}
char *nc_recv(int s) {
char buf[BUFSIZ], *ret=NULL;
time_t timeout = time(NULL) + readtimeout;
struct timeval tv;
fd_set fds;
int res;
tv.tv_sec = readtimeout;
tv.tv_usec = 0;
FD_ZERO(&fds);
FD_SET(s, &fds);
while(1) {
res = select(s+1, &fds, NULL, NULL, &tv);
if(res<1) {
time_t now;
if (res == -1 && errno == EINTR && ((now = time(NULL)) < timeout)) {
tv.tv_sec = timeout - now;
tv.tv_usec = 0;
continue;
}
close(s);
return NULL;
}
break;
}
/* FIXME: check for EOL@EObuf ? */
res = recv(s, buf, sizeof(buf), 0);
if (res==-1 || !(ret = (char *)malloc(res+1))) {
close(s);
return NULL;
}
memcpy(ret, buf, res);
ret[res]='\0';
return ret;
}
int nc_connect_entry(struct CP_ENTRY *cpe) {
int s = nc_socket(cpe);
if(s==-1) return -1;
return nc_connect(s, cpe) ? -1 : s;
}
void nc_ping_entry(struct CP_ENTRY *cpe) {
int s = nc_connect_entry(cpe);
char *reply;
if (s!=-1 && !nc_send(s, "nPING\n", 6) && (reply = nc_recv(s))) {
cpe->dead = strcmp(reply, "PONG\n")!=0;
free(reply);
close(s);
} else cpe->dead = 1;
}
int nc_connect_rand(int *main, int *alt, int *local) {
struct CP_ENTRY *cpe = cpool_get_rand();
if(!cpe) return 1;
*local = cpe->local;
if ((*main = nc_connect_entry(cpe)) == -1) return 1; /* FIXME : this should be delayed till eom if local */
if(*local) {
char tmpn[] = "/tmp/clamav-milter-XXXXXX";
if((*alt = mkstemp(tmpn))==-1) { /* FIXME */
logg("!Failed to create temporary file\n");
close(*main);
return 1;
}
unlink(tmpn);
} else {
char *reply=NULL, *port;
int nport;
struct CP_ENTRY new_cpe;
union {
struct sockaddr_in sa4;
struct sockaddr_in6 sa6;
} sa;
if(nc_send(*main, "nSTREAM\n", 8) || !(reply = nc_recv(*main)) || !(port = strstr(reply, "PORT"))) {
logg("!Failed to communicate with clamd\n");
if(reply) free(reply);
close(*main);
return 1;
}
port+=5;
sscanf(port, "%d", &nport);
free(reply);
if(cpe->server->sa_family == AF_INET && cpe->socklen == sizeof(struct sockaddr_in)) {
memcpy(&sa, cpe->server, sizeof(struct sockaddr_in));
sa.sa4.sin_port = htons(nport);
new_cpe.socklen = sizeof(struct sockaddr_in);
} else if(cpe->server->sa_family == AF_INET6 && cpe->socklen == sizeof(struct sockaddr_in6)) {
memcpy(&sa, cpe->server, sizeof(struct sockaddr_in6));
sa.sa6.sin6_port = htons(nport);
new_cpe.socklen = sizeof(struct sockaddr_in6);
} else {
logg("!WTF WHY AM I DOING HERE???");
close(*main);
return 1;
}
new_cpe.server = (struct sockaddr *)&sa;
if ((*alt = nc_connect_entry(&new_cpe)) == -1) {
logg("!Failed to communicate with clamd for streaming\n");
close(*main);
return 1;
}
}
return 0;
}
/*
* Local Variables:
* mode: c
* c-basic-offset: 4
* tab-width: 8
* End:
* vim: set cindent smartindent autoindent softtabstop=4 shiftwidth=4 tabstop=8:
*/

@ -0,0 +1,13 @@
#ifndef _NETCODE_H
#define _NETCODE_H
#include "connpool.h"
void nc_ping_entry(struct CP_ENTRY *cpe);
int nc_connect_rand(int *main, int *alt, int *local);
int nc_send(int s, const void *buf, size_t len);
char *nc_recv(int s);
extern long readtimeout;
#endif

@ -84,7 +84,7 @@ static void printcfg(const char *cfgfile, int nondef)
unsigned short cfgowner = 0;
if(!(cfg = getcfg(cfgfile, 1))) {
if(!(cfg = getcfg(cfgfile, 1, OPT_FRESHCLAM|OPT_CLAMD))) {
printf("Can't parse %s\n", cfgfile);
return;
}

@ -157,7 +157,7 @@ int main(int argc, char **argv)
else
cfgfile = CONFDIR"/clamd.conf";
if((copt = getcfg(cfgfile, 1)) == NULL) {
if((copt = getcfg(cfgfile, 1, OPT_CLAMD)) == NULL) {
fprintf(stderr, "ERROR: Can't open/parse the config file %s\n", cfgfile);
opt_free(opt);
return 1;

@ -271,7 +271,7 @@ static int dconnect(const struct optstruct *opt, int *is_unix)
if(!clamav_conf)
clamav_conf = DEFAULT_CFG;
if((copt = getcfg(clamav_conf, 1)) == NULL) {
if((copt = getcfg(clamav_conf, 1, OPT_CLAMD)) == NULL) {
logg("^Can't parse the configuration file.\n");
return -1;
}

@ -0,0 +1,166 @@
##
## Example config file for the clamav-milter
## /* FIXME : NOT DONE YET */ Please read the clamav-milter.conf(5) manual before editing this file.
##
# 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
# Remove stale socket after unclean shutdown.
# Default: yes
#FixStaleSocket yes
# Maximum number of threads running at the same time.
# Default: 10
##MaxThreads 20
# Run as another user (clamav-milter must be started by root for this option to work)
# Default: don't drop privileges
##User clamav
# Initialize supplementary group access (clamd must be started by root).
# Default: no
##AllowSupplementaryGroups no
# 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
##
## 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
# WARNING: The following options are deprecated and may go away soon.
# Please use ClamdSocket instead!
# Default: disabled
#LocalSocket
#TCPSocket
#TCPAddr
##
## 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
# Also log clean files. Useful in debugging but drastically increases the
# log size.
# Default: no
##LogClean yes
# Use system logger (can work together with LogFile).
# Default: no
##LogSyslog yes
# Specify the type of syslog messages - please refer to 'man syslog'
# for facility names.
# Default: LOG_LOCAL6
##LogFacility LOG_MAIL
# Enable verbose logging.
# Default: no
##LogVerbose yes
##
## Limits
##
# Files larger than this value won't be scanned.
# Default: 25M
##MaxFileSize 150M
# WARNING: The following two options are deprecated and may go away soon.
# Please use MaxFile size instead!
# For compatibility reasons the minimum value among MaxFileSize,
# MaxScanSize and StreamMaxLength will be used.
#MaxScanSize
#StreamMaxLength
##
## Deprecated options
##
# The following deprecated options are only kept for compatibility
# reaosns and may go away soon. These do not affect clamav-milter
# in any way, except for a small warning emitted on startup.
#ArchiveBlockEncrypted
#DatabaseDirectory
#Debug
#DetectBrokenExecutables
#LeaveTemporaryFiles
#MailFollowURLs
#MaxRecursion
#MaxFiles
#PhishingSignatures
#PidFile
#ScanArchive
#ScanHTML
#ScanMail
#ScanOLE2
#ScanPE
#TemporaryDirectory

@ -253,11 +253,11 @@ int main(int argc, char **argv)
/* parse the config file */
if((cfgfile = opt_arg(opt, "config-file"))) {
copt = getcfg(cfgfile, 1);
copt = getcfg(cfgfile, 1, OPT_FRESHCLAM);
} else {
/* TODO: force strict permissions on freshclam.conf */
if((copt = getcfg((cfgfile = CONFDIR"/freshclam.conf"), 1)) == NULL)
copt = getcfg((cfgfile = CONFDIR"/clamd.conf"), 1);
if((copt = getcfg((cfgfile = CONFDIR"/freshclam.conf"), 1, OPT_FRESHCLAM)) == NULL)
copt = getcfg((cfgfile = CONFDIR"/clamd.conf"), 1, OPT_FRESHCLAM);
}
if(!copt) {

@ -560,7 +560,7 @@ int submitstats(const char *clamdcfg, const struct cfgstruct *copt)
country = cpt->strarg;
}
if(!(clamdopt = getcfg(clamdcfg, 1))) {
if(!(clamdopt = getcfg(clamdcfg, 1, OPT_CLAMD))) {
logg("!SubmitDetectionStats: Can't open or parse configuration file %s\n", clamdcfg);
return 56;
}

@ -70,7 +70,7 @@ int notify(const char *cfgfile)
const char *socktype;
if((copt = getcfg(cfgfile, 1)) == NULL) {
if((copt = getcfg(cfgfile, 1, OPT_CLAMD)) == NULL) {
logg("^Clamd was NOT notified: Can't find or parse configuration file %s\n", cfgfile);
return 1;
}

@ -35,14 +35,14 @@
#include "libclamav/str.h"
struct cfgoption cfg_options[] = {
{"LogFile", OPT_QUOTESTR, -1, NULL, 0, OPT_CLAMD},
{"LogFileUnlock", OPT_BOOL, 0, NULL, 0, OPT_CLAMD},
{"LogFileMaxSize", OPT_COMPSIZE, 1048576, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM},
{"LogTime", OPT_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM},
{"LogClean", OPT_BOOL, 0, NULL, 0, OPT_CLAMD},
{"LogVerbose", OPT_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM},
{"LogSyslog", OPT_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM},
{"LogFacility", OPT_QUOTESTR, -1, "LOG_LOCAL6", 0, OPT_CLAMD | OPT_FRESHCLAM},
{"LogFile", OPT_QUOTESTR, -1, NULL, 0, OPT_CLAMD | OPT_MILTER},
{"LogFileUnlock", OPT_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_MILTER},
{"LogFileMaxSize", OPT_COMPSIZE, 1048576, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_MILTER},
{"LogTime", OPT_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_MILTER},
{"LogClean", OPT_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_MILTER},
{"LogVerbose", OPT_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_MILTER},
{"LogSyslog", OPT_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_MILTER},
{"LogFacility", OPT_QUOTESTR, -1, "LOG_LOCAL6", 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_MILTER},
{"PidFile", OPT_QUOTESTR, -1, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM},
{"TemporaryDirectory", OPT_QUOTESTR, -1, NULL, 0, OPT_CLAMD},
{"ScanPE", OPT_BOOL, 1, NULL, 0, OPT_CLAMD},
@ -72,7 +72,7 @@ struct cfgoption cfg_options[] = {
{"ScanPDF", OPT_BOOL, 1, NULL, 0, OPT_CLAMD},
{"ScanArchive", OPT_BOOL, 1, NULL, 0, OPT_CLAMD},
{"MaxScanSize", OPT_COMPSIZE, -1, NULL, 0, OPT_CLAMD},
{"MaxFileSize", OPT_COMPSIZE, -1, NULL, 0, OPT_CLAMD},
{"MaxFileSize", OPT_COMPSIZE, -1, NULL, 0, OPT_CLAMD | OPT_MILTER},
{"MaxRecursion", OPT_NUM, -1, NULL, 0, OPT_CLAMD},
{"MaxFiles", OPT_NUM, -1, NULL, 0, OPT_CLAMD},
{"ArchiveBlockEncrypted", OPT_BOOL, 0, NULL, 0, OPT_CLAMD},
@ -84,20 +84,20 @@ struct cfgoption cfg_options[] = {
{"StreamMaxLength", OPT_COMPSIZE, 10485760, NULL, 0, OPT_CLAMD},
{"StreamMinPort", OPT_NUM, 1024, NULL, 0, OPT_CLAMD},
{"StreamMaxPort", OPT_NUM, 2048, NULL, 0, OPT_CLAMD},
{"MaxThreads", OPT_NUM, 10, NULL, 0, OPT_CLAMD},
{"ReadTimeout", OPT_NUM, 120, NULL, 0, OPT_CLAMD},
{"MaxThreads", OPT_NUM, 10, NULL, 0, OPT_CLAMD | OPT_MILTER},
{"ReadTimeout", OPT_NUM, 120, NULL, 0, OPT_CLAMD | OPT_MILTER},
{"IdleTimeout", OPT_NUM, 30, NULL, 0, OPT_CLAMD},
{"MaxDirectoryRecursion", OPT_NUM, 15, NULL, 0, OPT_CLAMD},
{"ExcludePath", OPT_QUOTESTR, -1, NULL, 1, OPT_CLAMD},
{"FollowDirectorySymlinks", OPT_BOOL, 0, NULL, 0, OPT_CLAMD},
{"FollowFileSymlinks", OPT_BOOL, 0, NULL, 0, OPT_CLAMD},
{"ExitOnOOM", OPT_BOOL, 0, NULL, 0, OPT_CLAMD},
{"Foreground", OPT_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM},
{"Foreground", OPT_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_MILTER},
{"Debug", OPT_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM},
{"LeaveTemporaryFiles", OPT_BOOL, 0, NULL, 0, OPT_CLAMD},
{"FixStaleSocket", OPT_BOOL, 1, NULL, 0, OPT_CLAMD},
{"User", OPT_QUOTESTR, -1, NULL, 0, OPT_CLAMD},
{"AllowSupplementaryGroups", OPT_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM},
{"FixStaleSocket", OPT_BOOL, 1, NULL, 0, OPT_CLAMD | OPT_MILTER},
{"User", OPT_QUOTESTR, -1, NULL, 0, OPT_CLAMD | OPT_MILTER},
{"AllowSupplementaryGroups", OPT_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_MILTER},
{"SelfCheck", OPT_NUM, 1800, NULL, 0, OPT_CLAMD},
{"VirusEvent", OPT_FULLSTR, -1, NULL, 0, OPT_CLAMD},
{"ClamukoScanOnAccess", OPT_BOOL, -1, NULL, 0, OPT_CLAMD},
@ -135,19 +135,46 @@ struct cfgoption cfg_options[] = {
/* Deprecated options */
{"MailMaxRecursion", OPT_NUM, 64, NULL, 0, OPT_CLAMD | OPT_DEPRECATED},
{"ArchiveMaxFileSize", OPT_COMPSIZE, 10485760, NULL, 0, OPT_CLAMD | OPT_DEPRECATED},
{"ArchiveMaxScanSize", OPT_COMPSIZE, 10485760, NULL, 0, OPT_CLAMD | OPT_DEPRECATED},
{"ArchiveMaxRecursion", OPT_NUM, 8, NULL, 0, OPT_CLAMD | OPT_DEPRECATED},
{"ArchiveMaxFiles", OPT_NUM, 1000, NULL, 0, OPT_CLAMD | OPT_DEPRECATED},
{"ArchiveMaxCompressionRatio", OPT_NUM, 250, NULL, 0, OPT_CLAMD | OPT_DEPRECATED},
{"ArchiveBlockMax", OPT_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_DEPRECATED},
{"ArchiveLimitMemoryUsage", OPT_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_DEPRECATED },
/* Milter specific options */
{"ClamdSocket", OPT_QUOTESTR, -1, NULL, 1, OPT_MILTER},
{"MilterSocket", OPT_QUOTESTR, -1, NULL, 1, OPT_MILTER},
/* Deprecated milter options */
{"ArchiveBlockEncrypted", OPT_BOOL, 0, NULL, 0, OPT_MILTER | OPT_DEPRECATED},
{"DatabaseDirectory", OPT_QUOTESTR, -1, DATADIR, 0, OPT_MILTER | OPT_DEPRECATED},
{"Debug", OPT_BOOL, 0, NULL, 0, OPT_MILTER | OPT_DEPRECATED},
{"DetectBrokenExecutables", OPT_BOOL, 0, NULL, 0, OPT_MILTER | OPT_DEPRECATED},
{"LeaveTemporaryFiles", OPT_BOOL, 0, NULL, 0, OPT_MILTER | OPT_DEPRECATED},
{"LocalSocket", OPT_QUOTESTR, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED},
{"MailFollowURLs", OPT_BOOL, 0, NULL, 0, OPT_MILTER | OPT_DEPRECATED},
{"MaxScanSize", OPT_COMPSIZE, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED},
{"MaxFiles", OPT_NUM, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED},
{"MaxRecursion", OPT_NUM, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED},
{"PhishingSignatures", OPT_BOOL, 1, NULL, 0, OPT_MILTER | OPT_DEPRECATED},
{"PidFile", OPT_QUOTESTR, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED},
{"ScanArchive", OPT_BOOL, 1, NULL, 0, OPT_MILTER | OPT_DEPRECATED},
{"ScanHTML", OPT_BOOL, 1, NULL, 0, OPT_MILTER | OPT_DEPRECATED},
{"ScanMail", OPT_BOOL, 1, NULL, 0, OPT_MILTER | OPT_DEPRECATED},
{"ScanOLE2", OPT_BOOL, 1, NULL, 0, OPT_MILTER | OPT_DEPRECATED},
{"ScanPE", OPT_BOOL, 1, NULL, 0, OPT_MILTER | OPT_DEPRECATED},
{"StreamMaxLength", OPT_COMPSIZE, 10485760, NULL, OPT_MILTER | OPT_DEPRECATED},
{"TCPAddr", OPT_QUOTESTR, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED},
{"TCPSocket", OPT_NUM, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED},
{"TemporaryDirectory", OPT_QUOTESTR, -1, NULL, 0, OPT_MILTER | OPT_DEPRECATED},
{NULL, 0, 0, NULL, 0, 0}
};
static int regcfg(struct cfgstruct **copt, const char *optname, char *strarg, int numarg, short multiple);
struct cfgstruct *getcfg(const char *cfgfile, int verbose)
struct cfgstruct *getcfg(const char *cfgfile, int verbose, int toolmask)
{
char buff[LINE_LENGTH], *name, *arg, *c;
FILE *fs;
@ -161,7 +188,7 @@ struct cfgstruct *getcfg(const char *cfgfile, int verbose)
if(!pt->name)
break;
if(regcfg(&copt, pt->name, pt->strarg ? strdup(pt->strarg) : NULL, pt->numarg, pt->multiple) < 0) {
if((pt->owner & toolmask) && regcfg(&copt, pt->name, pt->strarg ? strdup(pt->strarg) : NULL, pt->numarg, pt->multiple) < 0) {
fprintf(stderr, "ERROR: Can't register new options (not enough memory)\n");
freecfg(copt);
return NULL;
@ -194,7 +221,7 @@ struct cfgstruct *getcfg(const char *cfgfile, int verbose)
for(i = 0; ; i++) {
pt = &cfg_options[i];
if(pt->name) {
if(!strcmp(name, pt->name)) {
if((pt->owner & toolmask) && !strcmp(name, pt->name)) {
found = 1;
if(pt->owner & OPT_DEPRECATED) {
fprintf(stderr, "WARNING: Ignoring deprecated option %s at line %u\n", pt->name, line);

@ -29,9 +29,11 @@
#define OPT_FULLSTR 5 /* string argument, but get a full line */
#define OPT_QUOTESTR 6 /* string argument, (space delimited unless the argument starts with ' or ". If the argument starts with a quote character, then the argument data is what appears between the starting quote character and the matching ending quote character.) */
/* don't share bits! */
#define OPT_CLAMD 1
#define OPT_FRESHCLAM 2
#define OPT_DEPRECATED 4
#define OPT_MILTER 4
#define OPT_DEPRECATED 16
struct cfgoption {
const char *name;
@ -54,7 +56,7 @@ struct cfgstruct {
extern struct cfgoption cfg_options[];
struct cfgstruct *getcfg(const char *cfgfile, int verbose);
struct cfgstruct *getcfg(const char *cfgfile, int verbose, int toolmask);
const struct cfgstruct *cfgopt(const struct cfgstruct *copt, const char *optname);
void freecfg(struct cfgstruct *copt);

@ -75,7 +75,7 @@ char *freshdbdir(void)
/* try to find fresh directory */
dbdir = cl_retdbdir();
if((copt = getcfg(CONFDIR"/freshclam.conf", 0))) {
if((copt = getcfg(CONFDIR"/freshclam.conf", 0, OPT_FRESHCLAM))) {
if((cpt = cfgopt(copt, "DatabaseDirectory"))->enabled || (cpt = cfgopt(copt, "DataDirectory"))->enabled) {
if(strcmp(dbdir, cpt->strarg)) {
char *daily = (char *) malloc(strlen(cpt->strarg) + strlen(dbdir) + 30);

Loading…
Cancel
Save