LCOV - code coverage report
Current view: top level - source3/modules - vfs_virusfilter_clamav.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 0 82 0.0 %
Date: 2024-04-21 15:09:00 Functions: 0 5 0.0 %

          Line data    Source code
       1             : /*
       2             :    Samba-VirusFilter VFS modules
       3             :    ClamAV clamd support
       4             :    Copyright (C) 2010-2016 SATOH Fumiyasu @ OSS Technology Corp., Japan
       5             : 
       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.
      10             : 
      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.
      15             : 
      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/>.
      18             : */
      19             : 
      20             : /* Default values for standard "extra" configuration variables */
      21             : 
      22             : #ifdef CLAMAV_DEFAULT_SOCKET_PATH
      23             : #  define VIRUSFILTER_DEFAULT_SOCKET_PATH       CLAMAV_DEFAULT_SOCKET_PATH
      24             : #else
      25             : #  define VIRUSFILTER_DEFAULT_SOCKET_PATH       "/var/run/clamav/clamd.ctl"
      26             : #endif
      27             : 
      28             : #include "modules/vfs_virusfilter_common.h"
      29             : #include "modules/vfs_virusfilter_utils.h"
      30             : 
      31           0 : static int virusfilter_clamav_connect(struct vfs_handle_struct *handle,
      32             :                                       struct virusfilter_config *config,
      33             :                                       const char *svc,
      34             :                                       const char *user)
      35             : {
      36             : 
      37             :         /* To use clamd "zXXXX" commands */
      38           0 :         virusfilter_io_set_writel_eol(config->io_h, "\0", 1);
      39           0 :         virusfilter_io_set_readl_eol(config->io_h, "\0", 1);
      40             : 
      41           0 :         return 0;
      42             : }
      43             : 
      44           0 : static virusfilter_result virusfilter_clamav_scan_init(
      45             :         struct virusfilter_config *config)
      46             : {
      47           0 :         struct virusfilter_io_handle *io_h = config->io_h;
      48             :         bool ok;
      49             : 
      50           0 :         DBG_INFO("clamd: Connecting to socket: %s\n",
      51             :                  config->socket_path);
      52             : 
      53           0 :         become_root();
      54           0 :         ok = virusfilter_io_connect_path(io_h, config->socket_path);
      55           0 :         unbecome_root();
      56             : 
      57           0 :         if (!ok) {
      58           0 :                 DBG_ERR("clamd: Connecting to socket failed: %s: %s\n",
      59             :                         config->socket_path, strerror(errno));
      60           0 :                 return VIRUSFILTER_RESULT_ERROR;
      61             :         }
      62             : 
      63           0 :         DBG_INFO("clamd: Connected\n");
      64             : 
      65           0 :         return VIRUSFILTER_RESULT_OK;
      66             : }
      67             : 
      68           0 : static void virusfilter_clamav_scan_end(
      69             :         struct virusfilter_config *config)
      70             : {
      71           0 :         struct virusfilter_io_handle *io_h = config->io_h;
      72             : 
      73           0 :         DBG_INFO("clamd: Disconnecting\n");
      74             : 
      75           0 :         virusfilter_io_disconnect(io_h);
      76           0 : }
      77             : 
      78           0 : static virusfilter_result virusfilter_clamav_scan(
      79             :         struct vfs_handle_struct *handle,
      80             :         struct virusfilter_config *config,
      81             :         const struct files_struct *fsp,
      82             :         char **reportp)
      83             : {
      84           0 :         char *cwd_fname = fsp->conn->cwd_fsp->fsp_name->base_name;
      85           0 :         const char *fname = fsp->fsp_name->base_name;
      86           0 :         size_t filepath_len = strlen(cwd_fname) + 1 /* slash */ + strlen(fname);
      87           0 :         struct virusfilter_io_handle *io_h = config->io_h;
      88           0 :         virusfilter_result result = VIRUSFILTER_RESULT_CLEAN;
      89           0 :         char *report = NULL;
      90           0 :         char *reply = NULL;
      91           0 :         char *reply_msg = NULL;
      92             :         char *reply_token;
      93             :         bool ok;
      94             : 
      95           0 :         DBG_INFO("Scanning file: %s/%s\n", cwd_fname, fname);
      96             : 
      97           0 :         ok = virusfilter_io_writefl_readl(io_h, &reply, "zSCAN %s/%s",
      98             :                                           cwd_fname, fname);
      99           0 :         if (!ok) {
     100           0 :                 DBG_ERR("clamd: zSCAN: I/O error: %s\n", strerror(errno));
     101           0 :                 result = VIRUSFILTER_RESULT_ERROR;
     102           0 :                 report = talloc_asprintf(talloc_tos(),
     103             :                                          "Scanner I/O error: %s\n",
     104           0 :                                          strerror(errno));
     105           0 :                 goto virusfilter_clamav_scan_return;
     106             :         }
     107             : 
     108           0 :         if (reply[filepath_len] != ':' ||
     109           0 :             reply[filepath_len+1] != ' ')
     110             :         {
     111           0 :                 DBG_ERR("clamd: zSCAN: Invalid reply: %s\n",
     112             :                         reply);
     113           0 :                 result = VIRUSFILTER_RESULT_ERROR;
     114           0 :                 report = talloc_asprintf(talloc_tos(),
     115             :                                          "Scanner communication error");
     116           0 :                 goto virusfilter_clamav_scan_return;
     117             :         }
     118           0 :         reply_msg = reply + filepath_len + 2;
     119             : 
     120           0 :         reply_token = strrchr(reply, ' ');
     121             : 
     122           0 :         if (reply_token == NULL) {
     123           0 :                 DBG_ERR("clamd: zSCAN: Invalid reply: %s\n",
     124             :                         reply);
     125           0 :                 result = VIRUSFILTER_RESULT_ERROR;
     126           0 :                 report = talloc_asprintf(talloc_tos(),
     127             :                                          "Scanner communication error");
     128           0 :                 goto virusfilter_clamav_scan_return;
     129             :         }
     130           0 :         *reply_token = '\0';
     131           0 :         reply_token++;
     132             : 
     133           0 :         if (strcmp(reply_token, "OK") == 0) {
     134             : 
     135             :                 /* <FILEPATH>: OK */
     136           0 :                 result = VIRUSFILTER_RESULT_CLEAN;
     137           0 :                 report = talloc_asprintf(talloc_tos(), "Clean");
     138           0 :         } else if (strcmp(reply_token, "FOUND") == 0) {
     139             : 
     140             :                 /* <FILEPATH>: <REPORT> FOUND */
     141           0 :                 result = VIRUSFILTER_RESULT_INFECTED;
     142           0 :                 report = talloc_strdup(talloc_tos(), reply_msg);
     143           0 :         } else if (strcmp(reply_token, "ERROR") == 0) {
     144             : 
     145             :                 /* <FILEPATH>: <REPORT> ERROR */
     146           0 :                 DBG_ERR("clamd: zSCAN: Error: %s\n", reply_msg);
     147           0 :                 result = VIRUSFILTER_RESULT_ERROR;
     148           0 :                 report = talloc_asprintf(talloc_tos(),
     149             :                                          "Scanner error: %s\t", reply_msg);
     150             :         } else {
     151           0 :                 DBG_ERR("clamd: zSCAN: Invalid reply: %s\n", reply_token);
     152           0 :                 result = VIRUSFILTER_RESULT_ERROR;
     153           0 :                 report = talloc_asprintf(talloc_tos(),
     154             :                                          "Scanner communication error");
     155             :         }
     156             : 
     157           0 : virusfilter_clamav_scan_return:
     158           0 :         TALLOC_FREE(reply);
     159           0 :         if (report == NULL) {
     160           0 :                 *reportp = talloc_asprintf(talloc_tos(),
     161             :                                            "Scanner report memory error");
     162             :         } else {
     163           0 :                 *reportp = report;
     164             :         }
     165             : 
     166           0 :         return result;
     167             : }
     168             : 
     169             : static struct virusfilter_backend_fns virusfilter_backend_clamav = {
     170             :         .connect = virusfilter_clamav_connect,
     171             :         .disconnect = NULL,
     172             :         .scan_init = virusfilter_clamav_scan_init,
     173             :         .scan = virusfilter_clamav_scan,
     174             :         .scan_end = virusfilter_clamav_scan_end,
     175             : };
     176             : 
     177           0 : int virusfilter_clamav_init(struct virusfilter_config *config)
     178             : {
     179           0 :         struct virusfilter_backend *backend = NULL;
     180             : 
     181           0 :         if (config->socket_path == NULL) {
     182           0 :                 config->socket_path = VIRUSFILTER_DEFAULT_SOCKET_PATH;
     183             :         }
     184             : 
     185           0 :         backend = talloc_zero(config, struct virusfilter_backend);
     186           0 :         if (backend == NULL) {
     187           0 :                 return -1;
     188             :         }
     189             : 
     190           0 :         backend->fns = &virusfilter_backend_clamav;
     191           0 :         backend->name = "clamav";
     192             : 
     193           0 :         config->backend = backend;
     194           0 :         return 0;
     195             : }

Generated by: LCOV version 1.14