ports/115752: [PATCH] By ftp /proftpd added support for clamav
Vladimir Korkodinov
viper at perm.raid.ru
Thu Aug 23 11:30:02 UTC 2007
>Number: 115752
>Category: ports
>Synopsis: [PATCH] By ftp /proftpd added support for clamav
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-ports-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: update
>Submitter-Id: current-users
>Arrival-Date: Thu Aug 23 11:30:01 GMT 2007
>Closed-Date:
>Last-Modified:
>Originator: Vladimir Korkodinov
>Release: CURRENT
>Organization:
>Environment:
FreeBSD xxxx 7.0-CURRENT FreeBSD 7.0-CURRENT #11: Thu Aug 23 14:52:33 YEKST 2007 viper at xxxx:/usr/obj/usr/src/sys/viper i386
>Description:
Trying to add to the port support clamav.
Used mod_clamav (http://www.uglyboxindustries.com/mod_clamav.html) with the minor revisions
>How-To-Repeat:
>Fix:
Apply patch
Patch attached with submission follows:
diff -ruN proftpd.orig/Makefile proftpd/Makefile
--- proftpd.orig/Makefile 2007-07-25 03:34:34.000000000 +0600
+++ proftpd/Makefile 2007-08-23 15:32:15.000000000 +0600
@@ -70,7 +70,8 @@
QUOTATAB_RADIUS "include mod_quotatab_radius" off \
BAN "include mod_ban (Requires CTRLS)" off \
NLS "Use nls (builds mod_lang)" off \
- CYRFIX "Use patch for fix cyrillic encoding" off
+ CYRFIX "Use patch for fix cyrillic encoding" off \
+ CLAMAV "Use patch for support clamav " off
MODULES?=
LIBDIRS?=
@@ -210,6 +211,14 @@
.endif
.endif
+.if defined(WITH_CLAMAV)
+USE_CLAMAV= yes
+MODULES:=${MODULES}:mod_clamav
+LIB_DEPENDS+= clamav.2:${PORTSDIR}/security/clamav
+INCLUDEDIRS:=${INCLUDEDIRS}:${LOCALBASE}/include
+LIBDIRS:=${LIBDIRS}:${LOCALBASE}/lib
+.endif
+
# mod_ifsession should be the last item in the modules list
.if !defined(WITHOUT_IFSESSION)
MODULES:=${MODULES}:mod_ifsession
diff -ruN proftpd.orig/files/patch-contrib-mod_clamav.c proftpd/files/patch-contrib-mod_clamav.c
--- proftpd.orig/files/patch-contrib-mod_clamav.c 1970-01-01 05:00:00.000000000 +0500
+++ proftpd/files/patch-contrib-mod_clamav.c 2007-08-23 17:01:53.000000000 +0600
@@ -0,0 +1,272 @@
+--- modules/mod_clamav.c.orig 2007-08-23 16:59:20.000000000 +0600
++++ modules/mod_clamav.c 2007-08-23 17:01:21.000000000 +0600
+@@ -0,0 +1,269 @@
++/*
++ * mod_clamav - ClamAV virus scanning module for ProFTPD
++ * Copyright (c) 2005-2006, Joseph Benden <joe at thrallingpenguin.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * Furthermore, Joseph Benden gives permission to link this program with
++ * ClamAV, and distribute the resulting executable, without including the
++ * source code for ClamAV in the source distribution.
++ *
++ * ClamAV is available at http://www.clamav.net/
++ * Non-official SuSE RPM packages for both ClamAV and ProFTPD are available
++ * at http://www.ispservices.com/
++ *
++ * Thanks to TJ Saunders for his helpful comments and suggestions!
++ *
++ * DO NOT EDIT THE LINE BELOW
++ */
++#include "conf.h"
++#include "privs.h"
++#include "clamav.h"
++
++#define MOD_CLAMAV_VERSION "mod_clamav/0.5"
++module clamav_module;
++static int clamd_sockd = 0;
++int clamavd_session_start(int sockd);
++
++/**
++ * Read the returned information from Clamavd.
++ */
++int clamavd_result(int sockd, int warnClient, const char *filename) {
++ int infected = 0, waserror = 0, ret;
++ char buff[4096], *pt;
++ FILE *fd = 0;
++
++ if((fd=fdopen(dup(sockd), "r")) == NULL) {
++ pr_log_pri(PR_LOG_ERR, MOD_CLAMAV_VERSION ": error: Cant open descriptor for reading: %d", errno);
++ return -1;
++ }
++
++ if(fgets(buff, sizeof(buff), fd)) {
++ if(strstr(buff, "FOUND\n")) {
++ ++infected;
++ pr_log_pri(PR_LOG_ERR, MOD_CLAMAV_VERSION ": warning: %s", buff);
++ /* Delete the upload */
++ if(warnClient)
++ pr_response_add_err(R_DUP,"%s", buff);
++ pt = strrchr(buff, ':');
++ *pt = 0;
++ if((ret=pr_fsio_unlink(filename))!=0) {
++ pr_log_pri(PR_LOG_ERR, MOD_CLAMAV_VERSION ": notice: unlink() failed: %d", errno);
++ }
++ } else if(strstr(buff, "ERROR\n")) {
++ pr_log_pri(PR_LOG_ERR, MOD_CLAMAV_VERSION ": error: %s", buff);
++ waserror = 1;
++ }
++ }
++ fclose(fd);
++ return infected ? infected : (waserror ? -1 : 0);
++}
++
++/**
++ * Start a session with Clamavd.
++ */
++int clamavd_session_start(int sockd) {
++ if(write(sockd, "SESSION\n", 8) <= 0) {
++ pr_log_pri(PR_LOG_ERR, MOD_CLAMAV_VERSION ": error: Clamd didn't accept the session request.");
++ return -1;
++ }
++ return 0;
++}
++
++/**
++ * End session.
++ */
++int clamavd_session_stop(int sockd) {
++ if(write(sockd, "END\n", 4) <= 0) {
++ pr_log_pri(PR_LOG_ERR, MOD_CLAMAV_VERSION ": error: Clamd didn't accept the session end request.");
++ return -1;
++ }
++ return 0;
++}
++
++/**
++ * Request Clamavd to perform a scan.
++ */
++int clamavd_scan(int sockd, const char *fullpath, int warnClient, const char *filename) {
++ char *scancmd = NULL;
++
++ scancmd = calloc(strlen(fullpath) + 20, sizeof(char));
++ sprintf(scancmd, "SCAN %s\n", fullpath);
++
++ if(write(sockd, scancmd, strlen(scancmd)) <= 0) {
++ pr_log_pri(PR_LOG_ERR, MOD_CLAMAV_VERSION ": error: Cant write to the ClamAVd socket: %d", errno);
++ free(scancmd);
++ return -1;
++ }
++
++ free(scancmd);
++ return clamavd_result(sockd, warnClient, filename);
++}
++
++/**
++ * Connect a socket to ClamAVd.
++ */
++int clamavd_connect(char *clamhost) {
++ struct sockaddr_un server;
++ int sockd;
++
++ PRIVS_ROOT;
++ memset((char*)&server, 0, sizeof(server));
++
++ /* Local Socket */
++ server.sun_family = AF_UNIX;
++ strncpy(server.sun_path, clamhost, sizeof(server.sun_path));
++
++ if((sockd=socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
++ PRIVS_RELINQUISH;
++ pr_log_pri(PR_LOG_ERR, MOD_CLAMAV_VERSION ": error: Cannot create socket connection to ClamAVd: %d", errno);
++ return -1;
++ }
++
++ if(connect(sockd, (struct sockaddr *)&server, sizeof(struct sockaddr_un)) < 0) {
++ close(sockd);
++ PRIVS_RELINQUISH;
++ pr_log_pri(PR_LOG_ERR, MOD_CLAMAV_VERSION ": error: Cannot connect to ClamAVd: (%d) %s", errno, clamhost);
++ return -1;
++ }
++ PRIVS_RELINQUISH;
++
++ return sockd;
++}
++
++MODRET clamav_scan(cmd_rec *cmd) {
++ config_rec *c = NULL;
++ int ret, infected = 0;
++ char fullpath[4096];
++
++ c = find_config(CURRENT_CONF, CONF_PARAM, "ClamAV", FALSE);
++
++ if(!c || !*(int*)(c->argv[0]))
++ return DECLINED(cmd);
++
++ /* hold on to the ClamWarn configuration option */
++ c = find_config(CURRENT_CONF, CONF_PARAM, "ClamWarn", TRUE);
++
++ /* Figure out the full path */
++ if(session.chroot_path) {
++// sstrncpy(fullpath, strcmp(pr_fs_getvwd(), "/") ?
++// pdircat(cmd->tmp_pool, session.chroot_path, pr_fs_getvwd(), NULL) :
++// session.chroot_path, 4096);
++ sstrncpy(fullpath, session.chroot_path,(strlen(session.chroot_path)>4096) ?
++ 4096:4096-strlen (session.chroot_path));
++ sstrcat(fullpath, "/", 4096 - strlen(fullpath));
++ } else {
++// sstrncpy(fullpath, pr_fs_getcwd(), 4096);
++ sstrncpy(fullpath, "/", 1);
++ }
++
++ sstrcat(fullpath, cmd->arg, 4096 - strlen(fullpath));
++
++ /* scan it! */
++ if((ret=clamavd_scan(clamd_sockd, fullpath, (c ? *(int*)(c->argv[0]) : 0), cmd->arg)) >= 0) {
++ infected += ret;
++ }
++
++ if(infected) {
++ return ERROR(cmd);
++ }
++
++ if(c && *(int*)(c->argv[0]))
++ pr_response_add(R_226,"File passed ClamAV virus scanner.");
++
++ return DECLINED(cmd);
++}
++
++MODRET set_clamav(cmd_rec *cmd) {
++ int bool = -1;
++ config_rec *c = NULL;
++
++ CHECK_ARGS(cmd, 1);
++ CHECK_CONF(cmd, CONF_ROOT|CONF_ANON|CONF_LIMIT|CONF_VIRTUAL|CONF_GLOBAL);
++ if((bool = get_boolean(cmd,1)) == -1)
++ CONF_ERROR(cmd, "requires a boolean value");
++
++ c = add_config_param(cmd->argv[0], 1, NULL);
++ c->argv[0] = pcalloc(c->pool, sizeof(int));
++ *((int *) c->argv[0]) = bool;
++ c->flags |= CF_MERGEDOWN;
++ return HANDLED(cmd);
++}
++
++MODRET set_clamavd_local_socket(cmd_rec *cmd) {
++ CHECK_ARGS(cmd, 1);
++ CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
++
++ add_config_param_str("ClamLocalSocket", 1, cmd->argv[1]);
++ return HANDLED(cmd);
++}
++
++static void clamav_shutdown(const void *event_data, void *user_data) {
++ pr_log_pri(PR_LOG_INFO, MOD_CLAMAV_VERSION ": info: disconnected from Clamd.");
++ if(clamd_sockd) {
++ clamavd_session_stop(clamd_sockd);
++ close(clamd_sockd);
++ }
++}
++
++static int clamav_sess_init(void) {
++ char *local_socket = NULL;
++
++ clamd_sockd = 0;
++
++ local_socket = (char*)get_param_ptr(main_server->conf, "ClamLocalSocket", FALSE);
++ if(!local_socket) {
++ pr_log_pri(PR_LOG_INFO, MOD_CLAMAV_VERSION ": warning: No local socket was specified.");
++ return 0;
++ }
++
++ if((clamd_sockd = clamavd_connect(local_socket)) < 0) {
++ pr_log_pri(PR_LOG_ERR, MOD_CLAMAV_VERSION ": Cannot connect to ClamAVd.");
++ return 0;
++ }
++
++ clamavd_session_start(clamd_sockd);
++
++ pr_event_register(&clamav_module, "core.exit", clamav_shutdown, NULL);
++
++ return 0;
++}
++
++static conftable clamav_conftab[] = {
++ { "ClamAV", set_clamav, NULL },
++ { "ClamWarn", set_clamav, NULL },
++ { "ClamLocalSocket", set_clamavd_local_socket, NULL },
++ { NULL }
++};
++
++static cmdtable clamav_cmdtab[] = {
++ { POST_CMD, C_STOR, G_NONE, clamav_scan, TRUE, FALSE },
++ { POST_CMD, C_STOU, G_NONE, clamav_scan, TRUE, FALSE },
++ { POST_CMD, C_APPE, G_NONE, clamav_scan, TRUE, FALSE },
++ { 0, NULL }
++};
++
++module clamav_module = {
++ NULL,
++ NULL,
++ 0x20, /* api ver */
++ "clamav",
++ clamav_conftab,
++ clamav_cmdtab,
++ NULL, /* auth function table */
++ NULL, /* init function */
++ clamav_sess_init /* session init function */
++};
++
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-ports-bugs
mailing list