2 Samba-VirusFilter VFS modules
4 Copyright (C) 2010-2016 SATOH Fumiyasu @ OSS Technology Corp., Japan
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 /* Default values for standard "extra" configuration variables */
22 #ifdef CLAMAV_DEFAULT_SOCKET_PATH
23 # define VIRUSFILTER_DEFAULT_SOCKET_PATH CLAMAV_DEFAULT_SOCKET_PATH
25 # define VIRUSFILTER_DEFAULT_SOCKET_PATH "/var/run/clamav/clamd.ctl"
28 #include "modules/vfs_virusfilter_common.h"
29 #include "modules/vfs_virusfilter_utils.h"
31 static int virusfilter_clamav_connect(struct vfs_handle_struct
*handle
,
32 struct virusfilter_config
*config
,
37 /* To use clamd "zXXXX" commands */
38 virusfilter_io_set_writel_eol(config
->io_h
, "\0", 1);
39 virusfilter_io_set_readl_eol(config
->io_h
, "\0", 1);
44 static virusfilter_result
virusfilter_clamav_scan_init(
45 struct virusfilter_config
*config
)
47 struct virusfilter_io_handle
*io_h
= config
->io_h
;
50 DBG_INFO("clamd: Connecting to socket: %s\n",
54 ok
= virusfilter_io_connect_path(io_h
, config
->socket_path
);
58 DBG_ERR("clamd: Connecting to socket failed: %s: %s\n",
59 config
->socket_path
, strerror(errno
));
60 return VIRUSFILTER_RESULT_ERROR
;
63 DBG_INFO("clamd: Connected\n");
65 return VIRUSFILTER_RESULT_OK
;
68 static void virusfilter_clamav_scan_end(
69 struct virusfilter_config
*config
)
71 struct virusfilter_io_handle
*io_h
= config
->io_h
;
73 DBG_INFO("clamd: Disconnecting\n");
75 virusfilter_io_disconnect(io_h
);
78 static virusfilter_result
virusfilter_clamav_scan(
79 struct vfs_handle_struct
*handle
,
80 struct virusfilter_config
*config
,
81 const struct files_struct
*fsp
,
84 char *cwd_fname
= fsp
->conn
->cwd_fsp
->fsp_name
->base_name
;
85 const char *fname
= fsp
->fsp_name
->base_name
;
86 size_t filepath_len
= strlen(cwd_fname
) + 1 /* slash */ + strlen(fname
);
87 struct virusfilter_io_handle
*io_h
= config
->io_h
;
88 virusfilter_result result
= VIRUSFILTER_RESULT_CLEAN
;
91 char *reply_msg
= NULL
;
95 DBG_INFO("Scanning file: %s/%s\n", cwd_fname
, fname
);
97 ok
= virusfilter_io_writefl_readl(io_h
, &reply
, "zSCAN %s/%s",
100 DBG_ERR("clamd: zSCAN: I/O error: %s\n", strerror(errno
));
101 result
= VIRUSFILTER_RESULT_ERROR
;
102 report
= talloc_asprintf(talloc_tos(),
103 "Scanner I/O error: %s\n",
105 goto virusfilter_clamav_scan_return
;
108 if (reply
[filepath_len
] != ':' ||
109 reply
[filepath_len
+1] != ' ')
111 DBG_ERR("clamd: zSCAN: Invalid reply: %s\n",
113 result
= VIRUSFILTER_RESULT_ERROR
;
114 report
= talloc_asprintf(talloc_tos(),
115 "Scanner communication error");
116 goto virusfilter_clamav_scan_return
;
118 reply_msg
= reply
+ filepath_len
+ 2;
120 reply_token
= strrchr(reply
, ' ');
122 if (reply_token
== NULL
) {
123 DBG_ERR("clamd: zSCAN: Invalid reply: %s\n",
125 result
= VIRUSFILTER_RESULT_ERROR
;
126 report
= talloc_asprintf(talloc_tos(),
127 "Scanner communication error");
128 goto virusfilter_clamav_scan_return
;
133 if (strcmp(reply_token
, "OK") == 0) {
136 result
= VIRUSFILTER_RESULT_CLEAN
;
137 report
= talloc_asprintf(talloc_tos(), "Clean");
138 } else if (strcmp(reply_token
, "FOUND") == 0) {
140 /* <FILEPATH>: <REPORT> FOUND */
141 result
= VIRUSFILTER_RESULT_INFECTED
;
142 report
= talloc_strdup(talloc_tos(), reply_msg
);
143 } else if (strcmp(reply_token
, "ERROR") == 0) {
145 /* <FILEPATH>: <REPORT> ERROR */
146 DBG_ERR("clamd: zSCAN: Error: %s\n", reply_msg
);
147 result
= VIRUSFILTER_RESULT_ERROR
;
148 report
= talloc_asprintf(talloc_tos(),
149 "Scanner error: %s\t", reply_msg
);
151 DBG_ERR("clamd: zSCAN: Invalid reply: %s\n", reply_token
);
152 result
= VIRUSFILTER_RESULT_ERROR
;
153 report
= talloc_asprintf(talloc_tos(),
154 "Scanner communication error");
157 virusfilter_clamav_scan_return
:
159 if (report
== NULL
) {
160 *reportp
= talloc_asprintf(talloc_tos(),
161 "Scanner report memory error");
169 static struct virusfilter_backend_fns virusfilter_backend_clamav
= {
170 .connect
= virusfilter_clamav_connect
,
172 .scan_init
= virusfilter_clamav_scan_init
,
173 .scan
= virusfilter_clamav_scan
,
174 .scan_end
= virusfilter_clamav_scan_end
,
177 int virusfilter_clamav_init(struct virusfilter_config
*config
)
179 struct virusfilter_backend
*backend
= NULL
;
181 if (config
->socket_path
== NULL
) {
182 config
->socket_path
= VIRUSFILTER_DEFAULT_SOCKET_PATH
;
185 backend
= talloc_zero(config
, struct virusfilter_backend
);
186 if (backend
== NULL
) {
190 backend
->fns
= &virusfilter_backend_clamav
;
191 backend
->name
= "clamav";
193 config
->backend
= backend
;