2 * Copyright (C) 2010-2016 SATOH Fumiyasu @ OSS Technology Corp., Japan
3 * Copyright (C) 2016-2017 Trever L. Adams
4 * Copyright (C) 2017 Ralph Boehme <slow@samba.org>
5 * Copyright (C) 2017 Jeremy Allison <jra@samba.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "vfs_virusfilter_common.h"
22 #include "vfs_virusfilter_utils.h"
25 * Default configuration values
26 * ======================================================================
29 #define VIRUSFILTER_DEFAULT_QUARANTINE_PREFIX "virusfilter."
30 #define VIRUSFILTER_DEFAULT_QUARANTINE_SUFFIX ".infected"
31 #define VIRUSFILTER_DEFAULT_RENAME_PREFIX "virusfilter."
32 #define VIRUSFILTER_DEFAULT_RENAME_SUFFIX ".infected"
34 /* ====================================================================== */
36 enum virusfilter_scanner_enum
{
37 VIRUSFILTER_SCANNER_CLAMAV
,
38 VIRUSFILTER_SCANNER_DUMMY
,
39 VIRUSFILTER_SCANNER_FSAV
,
40 VIRUSFILTER_SCANNER_SOPHOS
43 static const struct enum_list scanner_list
[] = {
44 { VIRUSFILTER_SCANNER_CLAMAV
, "clamav" },
45 { VIRUSFILTER_SCANNER_DUMMY
, "dummy" },
46 { VIRUSFILTER_SCANNER_FSAV
, "fsav" },
47 { VIRUSFILTER_SCANNER_SOPHOS
, "sophos" },
51 static const struct enum_list virusfilter_actions
[] = {
52 { VIRUSFILTER_ACTION_QUARANTINE
, "quarantine" },
53 { VIRUSFILTER_ACTION_RENAME
, "rename" },
54 { VIRUSFILTER_ACTION_DELETE
, "delete" },
56 /* alias for "delete" */
57 { VIRUSFILTER_ACTION_DELETE
, "remove" },
59 /* alias for "delete" */
60 { VIRUSFILTER_ACTION_DELETE
, "unlink" },
61 { VIRUSFILTER_ACTION_DO_NOTHING
, "nothing" },
65 static int virusfilter_config_destructor(struct virusfilter_config
*config
)
67 TALLOC_FREE(config
->backend
);
72 * This is adapted from vfs_recycle module.
73 * Caller must have become_root();
75 static bool quarantine_directory_exist(
76 struct vfs_handle_struct
*handle
,
80 struct smb_filename smb_fname
= {
81 .base_name
= discard_const_p(char, dname
)
84 ret
= SMB_VFS_STAT(handle
->conn
, &smb_fname
);
86 return S_ISDIR(smb_fname
.st
.st_ex_mode
);
93 * Create directory tree
94 * @param conn connection
95 * @param dname Directory tree to be created
96 * @return Returns true for success
97 * This is adapted from vfs_recycle module.
98 * Caller must have become_root();
100 static bool quarantine_create_dir(
101 struct vfs_handle_struct
*handle
,
102 struct virusfilter_config
*config
,
107 char *new_dir
= NULL
;
108 char *tmp_str
= NULL
;
110 char *tok_str
= NULL
;
114 char *saveptr
= NULL
;
116 tmp_str
= talloc_strdup(talloc_tos(), dname
);
117 if (tmp_str
== NULL
) {
118 DBG_ERR("virusfilter-vfs: out of memory!\n");
124 len
= strlen(dname
)+1;
125 new_dir
= (char *)talloc_size(talloc_tos(), len
+ 1);
126 if (new_dir
== NULL
) {
127 DBG_ERR("virusfilter-vfs: out of memory!\n");
132 if (dname
[0] == '/') {
134 cat_len
= strlcat(new_dir
, "/", len
+ 1);
135 if (cat_len
>= len
+1) {
140 /* Create directory tree if necessary */
141 for (token
= strtok_r(tok_str
, "/", &saveptr
);
143 token
= strtok_r(NULL
, "/", &saveptr
))
145 cat_len
= strlcat(new_dir
, token
, len
+ 1);
146 if (cat_len
>= len
+1) {
149 ok
= quarantine_directory_exist(handle
, new_dir
);
151 DBG_DEBUG("quarantine: dir %s already exists\n",
154 struct smb_filename
*smb_fname
= NULL
;
156 DBG_INFO("quarantine: creating new dir %s\n", new_dir
);
158 smb_fname
= synthetic_smb_fname(talloc_tos(),
164 if (smb_fname
== NULL
) {
168 ret
= SMB_VFS_NEXT_MKDIRAT(handle
,
169 handle
->conn
->cwd_fsp
,
171 config
->quarantine_dir_mode
);
173 TALLOC_FREE(smb_fname
);
175 DBG_WARNING("quarantine: mkdirat failed for %s "
176 "with error: %s\n", new_dir
,
181 TALLOC_FREE(smb_fname
);
183 cat_len
= strlcat(new_dir
, "/", len
+ 1);
184 if (cat_len
>= len
+ 1) {
191 TALLOC_FREE(tmp_str
);
192 TALLOC_FREE(new_dir
);
196 static int virusfilter_vfs_connect(
197 struct vfs_handle_struct
*handle
,
201 int snum
= SNUM(handle
->conn
);
202 struct virusfilter_config
*config
= NULL
;
203 const char *exclude_files
= NULL
;
204 const char *infected_files
= NULL
;
205 const char *temp_quarantine_dir_mode
= NULL
;
206 const char *infected_file_command
= NULL
;
207 const char *scan_error_command
= NULL
;
208 const char *quarantine_dir
= NULL
;
209 const char *quarantine_prefix
= NULL
;
210 const char *quarantine_suffix
= NULL
;
211 const char *rename_prefix
= NULL
;
212 const char *rename_suffix
= NULL
;
213 const char *socket_path
= NULL
;
216 enum virusfilter_scanner_enum backend
;
217 int connect_timeout
= 0;
222 config
= talloc_zero(handle
, struct virusfilter_config
);
223 if (config
== NULL
) {
224 DBG_ERR("talloc_zero failed\n");
227 talloc_set_destructor(config
, virusfilter_config_destructor
);
229 SMB_VFS_HANDLE_SET_DATA(handle
, config
, NULL
,
230 struct virusfilter_config
, return -1);
232 config
->scan_request_limit
= lp_parm_int(
233 snum
, "virusfilter", "scan request limit", 0);
235 config
->scan_on_open
= lp_parm_bool(
236 snum
, "virusfilter", "scan on open", true);
238 config
->scan_on_close
= lp_parm_bool(
239 snum
, "virusfilter", "scan on close", false);
241 config
->max_nested_scan_archive
= lp_parm_int(
242 snum
, "virusfilter", "max nested scan archive", 1);
244 config
->scan_archive
= lp_parm_bool(
245 snum
, "virusfilter", "scan archive", false);
247 config
->scan_mime
= lp_parm_bool(
248 snum
, "virusfilter", "scan mime", false);
250 config
->max_file_size
= (ssize_t
)lp_parm_ulong(
251 snum
, "virusfilter", "max file size", 100000000L);
253 config
->min_file_size
= (ssize_t
)lp_parm_ulong(
254 snum
, "virusfilter", "min file size", 10);
256 exclude_files
= lp_parm_const_string(
257 snum
, "virusfilter", "exclude files", NULL
);
258 if (exclude_files
!= NULL
) {
259 ok
= set_namearray(config
,
261 &config
->exclude_files
);
263 DBG_ERR("set_namearray failed\n");
268 infected_files
= lp_parm_const_string(
269 snum
, "virusfilter", "infected files", NULL
);
270 if (infected_files
!= NULL
) {
271 ok
= set_namearray(config
,
273 &config
->infected_files
);
275 DBG_ERR("set_namearray failed\n");
280 config
->cache_entry_limit
= lp_parm_int(
281 snum
, "virusfilter", "cache entry limit", 100);
283 config
->cache_time_limit
= lp_parm_int(
284 snum
, "virusfilter", "cache time limit", 10);
286 config
->infected_file_action
= lp_parm_enum(
287 snum
, "virusfilter", "infected file action",
288 virusfilter_actions
, VIRUSFILTER_ACTION_DO_NOTHING
);
290 infected_file_command
= lp_parm_const_string(
291 snum
, "virusfilter", "infected file command", NULL
);
292 if (infected_file_command
!= NULL
) {
293 config
->infected_file_command
= talloc_strdup(
295 infected_file_command
);
296 if (config
->infected_file_command
== NULL
) {
297 DBG_ERR("virusfilter-vfs: out of memory!\n");
301 scan_error_command
= lp_parm_const_string(
302 snum
, "virusfilter", "scan error command", NULL
);
303 if (scan_error_command
!= NULL
) {
304 config
->scan_error_command
= talloc_strdup(config
,
306 if (config
->scan_error_command
== NULL
) {
307 DBG_ERR("virusfilter-vfs: out of memory!\n");
312 config
->block_access_on_error
= lp_parm_bool(
313 snum
, "virusfilter", "block access on error", false);
315 tmp
= talloc_asprintf(config
, "%s/.quarantine",
316 handle
->conn
->connectpath
);
318 quarantine_dir
= lp_parm_const_string(
319 snum
, "virusfilter", "quarantine directory",
320 tmp
? tmp
: "/tmp/.quarantine");
321 if (quarantine_dir
!= NULL
) {
322 config
->quarantine_dir
= talloc_strdup(config
, quarantine_dir
);
323 if (config
->quarantine_dir
== NULL
) {
324 DBG_ERR("virusfilter-vfs: out of memory!\n");
329 if (tmp
!= config
->quarantine_dir
) {
333 temp_quarantine_dir_mode
= lp_parm_const_string(
334 snum
, "virusfilter", "quarantine directory mode", "0755");
335 if (temp_quarantine_dir_mode
!= NULL
) {
336 unsigned int mode
= 0;
337 sscanf(temp_quarantine_dir_mode
, "%o", &mode
);
338 config
->quarantine_dir_mode
= mode
;
341 quarantine_prefix
= lp_parm_const_string(
342 snum
, "virusfilter", "quarantine prefix",
343 VIRUSFILTER_DEFAULT_QUARANTINE_PREFIX
);
344 if (quarantine_prefix
!= NULL
) {
345 config
->quarantine_prefix
= talloc_strdup(config
,
347 if (config
->quarantine_prefix
== NULL
) {
348 DBG_ERR("virusfilter-vfs: out of memory!\n");
353 quarantine_suffix
= lp_parm_const_string(
354 snum
, "virusfilter", "quarantine suffix",
355 VIRUSFILTER_DEFAULT_QUARANTINE_SUFFIX
);
356 if (quarantine_suffix
!= NULL
) {
357 config
->quarantine_suffix
= talloc_strdup(config
,
359 if (config
->quarantine_suffix
== NULL
) {
360 DBG_ERR("virusfilter-vfs: out of memory!\n");
366 * Make sure prefixes and suffixes do not contain directory
369 if (config
->quarantine_prefix
!= NULL
) {
370 sret
= strstr(config
->quarantine_prefix
, "/");
372 DBG_ERR("quarantine prefix must not contain directory "
373 "delimiter(s) such as '/' (%s replaced with %s)\n",
374 config
->quarantine_prefix
,
375 VIRUSFILTER_DEFAULT_QUARANTINE_PREFIX
);
376 config
->quarantine_prefix
=
377 VIRUSFILTER_DEFAULT_QUARANTINE_PREFIX
;
380 if (config
->quarantine_suffix
!= NULL
) {
381 sret
= strstr(config
->quarantine_suffix
, "/");
383 DBG_ERR("quarantine suffix must not contain directory "
384 "delimiter(s) such as '/' (%s replaced with %s)\n",
385 config
->quarantine_suffix
,
386 VIRUSFILTER_DEFAULT_QUARANTINE_SUFFIX
);
387 config
->quarantine_suffix
=
388 VIRUSFILTER_DEFAULT_QUARANTINE_SUFFIX
;
392 config
->quarantine_keep_tree
= lp_parm_bool(
393 snum
, "virusfilter", "quarantine keep tree", true);
395 config
->quarantine_keep_name
= lp_parm_bool(
396 snum
, "virusfilter", "quarantine keep name", true);
398 rename_prefix
= lp_parm_const_string(
399 snum
, "virusfilter", "rename prefix",
400 VIRUSFILTER_DEFAULT_RENAME_PREFIX
);
401 if (rename_prefix
!= NULL
) {
402 config
->rename_prefix
= talloc_strdup(config
, rename_prefix
);
403 if (config
->rename_prefix
== NULL
) {
404 DBG_ERR("virusfilter-vfs: out of memory!\n");
409 rename_suffix
= lp_parm_const_string(
410 snum
, "virusfilter", "rename suffix",
411 VIRUSFILTER_DEFAULT_RENAME_SUFFIX
);
412 if (rename_suffix
!= NULL
) {
413 config
->rename_suffix
= talloc_strdup(config
, rename_suffix
);
414 if (config
->rename_suffix
== NULL
) {
415 DBG_ERR("virusfilter-vfs: out of memory!\n");
421 * Make sure prefixes and suffixes do not contain directory
424 if (config
->rename_prefix
!= NULL
) {
425 sret
= strstr(config
->rename_prefix
, "/");
427 DBG_ERR("rename prefix must not contain directory "
428 "delimiter(s) such as '/' (%s replaced with %s)\n",
429 config
->rename_prefix
,
430 VIRUSFILTER_DEFAULT_RENAME_PREFIX
);
431 config
->rename_prefix
=
432 VIRUSFILTER_DEFAULT_RENAME_PREFIX
;
435 if (config
->rename_suffix
!= NULL
) {
436 sret
= strstr(config
->rename_suffix
, "/");
438 DBG_ERR("rename suffix must not contain directory "
439 "delimiter(s) such as '/' (%s replaced with %s)\n",
440 config
->rename_suffix
,
441 VIRUSFILTER_DEFAULT_RENAME_SUFFIX
);
442 config
->rename_suffix
=
443 VIRUSFILTER_DEFAULT_RENAME_SUFFIX
;
447 config
->infected_open_errno
= lp_parm_int(
448 snum
, "virusfilter", "infected file errno on open", EACCES
);
450 config
->infected_close_errno
= lp_parm_int(
451 snum
, "virusfilter", "infected file errno on close", 0);
453 config
->scan_error_open_errno
= lp_parm_int(
454 snum
, "virusfilter", "scan error errno on open", EACCES
);
456 config
->scan_error_close_errno
= lp_parm_int(
457 snum
, "virusfilter", "scan error errno on close", 0);
459 socket_path
= lp_parm_const_string(
460 snum
, "virusfilter", "socket path", NULL
);
461 if (socket_path
!= NULL
) {
462 config
->socket_path
= talloc_strdup(config
, socket_path
);
463 if (config
->socket_path
== NULL
) {
464 DBG_ERR("virusfilter-vfs: out of memory!\n");
469 /* canonicalize socket_path */
470 if (config
->socket_path
!= NULL
&& config
->socket_path
[0] != '/') {
471 DBG_ERR("socket path must be an absolute path. "
472 "Using backend default\n");
473 config
->socket_path
= NULL
;
475 if (config
->socket_path
!= NULL
) {
476 config
->socket_path
= canonicalize_absolute_path(
477 handle
, config
->socket_path
);
478 if (config
->socket_path
== NULL
) {
484 connect_timeout
= lp_parm_int(snum
, "virusfilter",
485 "connect timeout", 30000);
487 io_timeout
= lp_parm_int(snum
, "virusfilter", "io timeout", 60000);
489 config
->io_h
= virusfilter_io_new(config
, connect_timeout
, io_timeout
);
490 if (config
->io_h
== NULL
) {
491 DBG_ERR("virusfilter_io_new failed\n");
495 if (config
->cache_entry_limit
> 0) {
496 config
->cache
= virusfilter_cache_new(handle
,
497 config
->cache_entry_limit
,
498 config
->cache_time_limit
);
499 if (config
->cache
== NULL
) {
500 DBG_ERR("Initializing cache failed: Cache disabled\n");
506 * Check quarantine directory now to save processing
507 * and becoming root over and over.
509 if (config
->infected_file_action
== VIRUSFILTER_ACTION_QUARANTINE
) {
514 * Do SMB_VFS_NEXT_MKDIR(config->quarantine_dir)
518 dir_exists
= quarantine_directory_exist(handle
,
519 config
->quarantine_dir
);
521 DBG_DEBUG("Creating quarantine directory: %s\n",
522 config
->quarantine_dir
);
523 ok
= quarantine_create_dir(handle
, config
,
524 config
->quarantine_dir
);
528 DBG_ERR("Creating quarantine directory %s "
530 config
->quarantine_dir
,
537 * Now that the frontend options are initialized, load the configured
541 backend
= (enum virusfilter_scanner_enum
)lp_parm_enum(snum
,
546 if (backend
== (enum virusfilter_scanner_enum
)-1) {
547 DBG_ERR("No AV-Scanner configured, "
548 "please set \"virusfilter:scanner\"\n");
553 case VIRUSFILTER_SCANNER_SOPHOS
:
554 ret
= virusfilter_sophos_init(config
);
556 case VIRUSFILTER_SCANNER_FSAV
:
557 ret
= virusfilter_fsav_init(config
);
559 case VIRUSFILTER_SCANNER_CLAMAV
:
560 ret
= virusfilter_clamav_init(config
);
562 case VIRUSFILTER_SCANNER_DUMMY
:
563 ret
= virusfilter_dummy_init(config
);
566 DBG_ERR("Unhandled scanner %d\n", backend
);
570 DBG_ERR("Scanner backend init failed\n");
574 if (config
->backend
->fns
->connect
!= NULL
) {
575 ret
= config
->backend
->fns
->connect(handle
, config
, svc
, user
);
581 return SMB_VFS_NEXT_CONNECT(handle
, svc
, user
);
584 static void virusfilter_vfs_disconnect(struct vfs_handle_struct
*handle
)
586 struct virusfilter_config
*config
= NULL
;
588 SMB_VFS_HANDLE_GET_DATA(handle
, config
,
589 struct virusfilter_config
, return);
591 if (config
->backend
->fns
->disconnect
!= NULL
) {
592 config
->backend
->fns
->disconnect(handle
);
595 virusfilter_io_disconnect(config
->io_h
);
597 SMB_VFS_NEXT_DISCONNECT(handle
);
600 static int virusfilter_set_module_env(TALLOC_CTX
*mem_ctx
,
601 struct virusfilter_config
*config
,
606 ret
= virusfilter_env_set(mem_ctx
, env_list
, "VIRUSFILTER_VERSION",
607 VIRUSFILTER_VERSION
);
611 ret
= virusfilter_env_set(mem_ctx
, env_list
, "VIRUSFILTER_MODULE_NAME",
612 config
->backend
->name
);
617 if (config
->backend
->version
!= 0) {
618 char *version
= NULL
;
620 version
= talloc_asprintf(talloc_tos(), "%u",
621 config
->backend
->version
);
622 if (version
== NULL
) {
625 ret
= virusfilter_env_set(mem_ctx
, env_list
,
626 "VIRUSFILTER_MODULE_VERSION",
628 TALLOC_FREE(version
);
637 static char *quarantine_check_tree(TALLOC_CTX
*mem_ctx
,
638 struct vfs_handle_struct
*handle
,
639 struct virusfilter_config
*config
,
640 const struct smb_filename
*smb_fname
,
644 char *temp_path
= NULL
;
645 char *q_dir_out
= NULL
;
648 temp_path
= talloc_asprintf(talloc_tos(), "%s/%s", q_dir_in
, cwd_fname
);
649 if (temp_path
== NULL
) {
650 DBG_ERR("talloc_asprintf failed\n");
655 ok
= quarantine_directory_exist(handle
, temp_path
);
658 DBG_DEBUG("quarantine: directory [%s] exists\n", temp_path
);
659 q_dir_out
= talloc_move(mem_ctx
, &temp_path
);
663 DBG_DEBUG("quarantine: Creating directory %s\n", temp_path
);
666 ok
= quarantine_create_dir(handle
, config
, temp_path
);
669 DBG_NOTICE("Could not create quarantine directory [%s], "
670 "ignoring for [%s]\n",
671 temp_path
, smb_fname_str_dbg(smb_fname
));
675 q_dir_out
= talloc_move(mem_ctx
, &temp_path
);
678 TALLOC_FREE(temp_path
);
682 static virusfilter_action
infected_file_action_quarantine(
683 struct vfs_handle_struct
*handle
,
684 struct virusfilter_config
*config
,
686 const struct files_struct
*fsp
,
687 const char **filepath_newp
)
689 TALLOC_CTX
*frame
= talloc_stackframe();
690 connection_struct
*conn
= handle
->conn
;
691 char *cwd_fname
= fsp
->conn
->cwd_fsp
->fsp_name
->base_name
;
692 char *fname
= fsp
->fsp_name
->base_name
;
693 const struct smb_filename
*smb_fname
= fsp
->fsp_name
;
694 struct smb_filename
*q_smb_fname
= NULL
;
696 char *q_prefix
= NULL
;
697 char *q_suffix
= NULL
;
698 char *q_filepath
= NULL
;
699 char *dir_name
= NULL
;
700 const char *base_name
= NULL
;
701 char *rand_filename_component
= NULL
;
702 virusfilter_action action
= VIRUSFILTER_ACTION_QUARANTINE
;
707 q_dir
= virusfilter_string_sub(frame
, conn
,
708 config
->quarantine_dir
);
709 q_prefix
= virusfilter_string_sub(frame
, conn
,
710 config
->quarantine_prefix
);
711 q_suffix
= virusfilter_string_sub(frame
, conn
,
712 config
->quarantine_suffix
);
713 if (q_dir
== NULL
|| q_prefix
== NULL
|| q_suffix
== NULL
) {
714 DBG_ERR("Quarantine failed: %s/%s: Cannot allocate "
715 "memory\n", cwd_fname
, fname
);
716 action
= VIRUSFILTER_ACTION_DO_NOTHING
;
720 if (config
->quarantine_keep_name
|| config
->quarantine_keep_tree
) {
721 ok
= parent_dirname(frame
, smb_fname
->base_name
,
722 &dir_name
, &base_name
);
724 DBG_ERR("parent_dirname failed\n");
725 action
= VIRUSFILTER_ACTION_DO_NOTHING
;
729 if (config
->quarantine_keep_tree
) {
732 tree
= quarantine_check_tree(frame
, handle
, config
,
737 * If we can't create the tree, just move it
738 * into the toplevel quarantine dir.
746 /* Get a 16 byte + \0 random filename component. */
747 rand_filename_component
= generate_random_str(frame
, 16);
748 if (rand_filename_component
== NULL
) {
749 DBG_ERR("generate_random_str failed\n");
750 action
= VIRUSFILTER_ACTION_DO_NOTHING
;
754 if (config
->quarantine_keep_name
) {
755 q_filepath
= talloc_asprintf(frame
, "%s/%s%s%s-%s",
758 rand_filename_component
);
760 q_filepath
= talloc_asprintf(frame
, "%s/%s%s",
762 rand_filename_component
);
764 if (q_filepath
== NULL
) {
765 DBG_ERR("talloc_asprintf failed\n");
766 action
= VIRUSFILTER_ACTION_DO_NOTHING
;
770 q_smb_fname
= synthetic_smb_fname(frame
,
772 smb_fname
->stream_name
,
776 if (q_smb_fname
== NULL
) {
777 action
= VIRUSFILTER_ACTION_DO_NOTHING
;
782 ret
= virusfilter_vfs_next_move(handle
, smb_fname
, q_smb_fname
);
788 DBG_ERR("Quarantine [%s/%s] rename to %s failed: %s\n",
789 cwd_fname
, fname
, q_filepath
, strerror(saved_errno
));
791 action
= VIRUSFILTER_ACTION_DO_NOTHING
;
795 *filepath_newp
= talloc_move(mem_ctx
, &q_filepath
);
802 static virusfilter_action
infected_file_action_rename(
803 struct vfs_handle_struct
*handle
,
804 struct virusfilter_config
*config
,
806 const struct files_struct
*fsp
,
807 const char **filepath_newp
)
809 TALLOC_CTX
*frame
= talloc_stackframe();
810 connection_struct
*conn
= handle
->conn
;
811 char *cwd_fname
= fsp
->conn
->cwd_fsp
->fsp_name
->base_name
;
812 char *fname
= fsp
->fsp_name
->base_name
;
813 const struct smb_filename
*smb_fname
= fsp
->fsp_name
;
814 struct smb_filename
*q_smb_fname
= NULL
;
816 char *q_prefix
= NULL
;
817 char *q_suffix
= NULL
;
818 char *q_filepath
= NULL
;
819 const char *base_name
= NULL
;
820 virusfilter_action action
= VIRUSFILTER_ACTION_RENAME
;
825 q_prefix
= virusfilter_string_sub(frame
, conn
,
826 config
->rename_prefix
);
827 q_suffix
= virusfilter_string_sub(frame
, conn
,
828 config
->rename_suffix
);
829 if (q_prefix
== NULL
|| q_suffix
== NULL
) {
830 DBG_ERR("Rename failed: %s/%s: Cannot allocate "
831 "memory\n", cwd_fname
, fname
);
832 action
= VIRUSFILTER_ACTION_DO_NOTHING
;
836 ok
= parent_dirname(frame
, fname
, &q_dir
, &base_name
);
838 DBG_ERR("Rename failed: %s/%s: Cannot allocate "
839 "memory\n", cwd_fname
, fname
);
840 action
= VIRUSFILTER_ACTION_DO_NOTHING
;
845 DBG_ERR("Rename failed: %s/%s: Cannot allocate "
846 "memory\n", cwd_fname
, fname
);
847 action
= VIRUSFILTER_ACTION_DO_NOTHING
;
851 q_filepath
= talloc_asprintf(frame
, "%s/%s%s%s", q_dir
,
852 q_prefix
, base_name
, q_suffix
);
854 q_smb_fname
= synthetic_smb_fname(frame
, q_filepath
,
855 smb_fname
->stream_name
, NULL
,
858 if (q_smb_fname
== NULL
) {
859 action
= VIRUSFILTER_ACTION_DO_NOTHING
;
864 ret
= virusfilter_vfs_next_move(handle
, smb_fname
, q_smb_fname
);
871 DBG_ERR("Rename failed: %s/%s: Rename failed: %s\n",
872 cwd_fname
, fname
, strerror(saved_errno
));
874 action
= VIRUSFILTER_ACTION_DO_NOTHING
;
878 *filepath_newp
= talloc_move(mem_ctx
, &q_filepath
);
885 static virusfilter_action
infected_file_action_delete(
886 struct vfs_handle_struct
*handle
,
887 const struct files_struct
*fsp
)
893 ret
= SMB_VFS_NEXT_UNLINKAT(handle
,
894 handle
->conn
->cwd_fsp
,
902 DBG_ERR("Delete [%s/%s] failed: %s\n",
903 fsp
->conn
->cwd_fsp
->fsp_name
->base_name
,
904 fsp
->fsp_name
->base_name
,
905 strerror(saved_errno
));
907 return VIRUSFILTER_ACTION_DO_NOTHING
;
910 return VIRUSFILTER_ACTION_DELETE
;
913 static virusfilter_action
virusfilter_do_infected_file_action(
914 struct vfs_handle_struct
*handle
,
915 struct virusfilter_config
*config
,
917 const struct files_struct
*fsp
,
918 const char **filepath_newp
)
920 virusfilter_action action
;
922 *filepath_newp
= NULL
;
924 switch (config
->infected_file_action
) {
925 case VIRUSFILTER_ACTION_RENAME
:
926 action
= infected_file_action_rename(handle
, config
, mem_ctx
,
930 case VIRUSFILTER_ACTION_QUARANTINE
:
931 action
= infected_file_action_quarantine(handle
, config
, mem_ctx
,
935 case VIRUSFILTER_ACTION_DELETE
:
936 action
= infected_file_action_delete(handle
, fsp
);
939 case VIRUSFILTER_ACTION_DO_NOTHING
:
941 action
= VIRUSFILTER_ACTION_DO_NOTHING
;
948 static virusfilter_action
virusfilter_treat_infected_file(
949 struct vfs_handle_struct
*handle
,
950 struct virusfilter_config
*config
,
951 const struct files_struct
*fsp
,
955 connection_struct
*conn
= handle
->conn
;
956 char *cwd_fname
= fsp
->conn
->cwd_fsp
->fsp_name
->base_name
;
957 char *fname
= fsp
->fsp_name
->base_name
;
958 TALLOC_CTX
*mem_ctx
= talloc_tos();
960 virusfilter_action action
;
961 const char *action_name
= "UNKNOWN";
962 const char *filepath_q
= NULL
;
963 char *env_list
= NULL
;
964 char *command
= NULL
;
968 action
= virusfilter_do_infected_file_action(handle
, config
, mem_ctx
,
970 for (i
=0; virusfilter_actions
[i
].name
; i
++) {
971 if (virusfilter_actions
[i
].value
== action
) {
972 action_name
= virusfilter_actions
[i
].name
;
976 DBG_WARNING("Infected file action: %s/%s: %s\n", cwd_fname
,
979 if (!config
->infected_file_command
) {
983 ret
= virusfilter_set_module_env(mem_ctx
, config
, &env_list
);
987 ret
= virusfilter_env_set(mem_ctx
, &env_list
,
988 "VIRUSFILTER_INFECTED_SERVICE_FILE_PATH",
993 if (report
!= NULL
) {
994 ret
= virusfilter_env_set(mem_ctx
, &env_list
,
995 "VIRUSFILTER_INFECTED_FILE_REPORT",
1001 ret
= virusfilter_env_set(mem_ctx
, &env_list
,
1002 "VIRUSFILTER_INFECTED_FILE_ACTION",
1007 if (filepath_q
!= NULL
) {
1008 ret
= virusfilter_env_set(mem_ctx
, &env_list
,
1009 "VIRUSFILTER_QUARANTINED_FILE_PATH",
1016 ret
= virusfilter_env_set(mem_ctx
, &env_list
,
1017 "VIRUSFILTER_RESULT_IS_CACHE", "yes");
1023 command
= virusfilter_string_sub(mem_ctx
, conn
,
1024 config
->infected_file_command
);
1025 if (command
== NULL
) {
1026 DBG_ERR("virusfilter_string_sub failed\n");
1030 DBG_NOTICE("Infected file command line: %s/%s: %s\n", cwd_fname
,
1033 command_result
= virusfilter_shell_run(mem_ctx
, command
, &env_list
,
1035 if (command_result
!= 0) {
1036 DBG_ERR("Infected file command failed: %d\n", command_result
);
1039 DBG_DEBUG("Infected file command finished: %d\n", command_result
);
1042 TALLOC_FREE(env_list
);
1043 TALLOC_FREE(command
);
1048 static void virusfilter_treat_scan_error(
1049 struct vfs_handle_struct
*handle
,
1050 struct virusfilter_config
*config
,
1051 const struct files_struct
*fsp
,
1055 connection_struct
*conn
= handle
->conn
;
1056 const char *cwd_fname
= fsp
->conn
->cwd_fsp
->fsp_name
->base_name
;
1057 const char *fname
= fsp
->fsp_name
->base_name
;
1058 TALLOC_CTX
*mem_ctx
= talloc_tos();
1059 char *env_list
= NULL
;
1060 char *command
= NULL
;
1064 if (!config
->scan_error_command
) {
1067 ret
= virusfilter_set_module_env(mem_ctx
, config
, &env_list
);
1071 ret
= virusfilter_env_set(mem_ctx
, &env_list
,
1072 "VIRUSFILTER_SCAN_ERROR_SERVICE_FILE_PATH",
1077 if (report
!= NULL
) {
1078 ret
= virusfilter_env_set(mem_ctx
, &env_list
,
1079 "VIRUSFILTER_SCAN_ERROR_REPORT",
1086 ret
= virusfilter_env_set(mem_ctx
, &env_list
,
1087 "VIRUSFILTER_RESULT_IS_CACHE", "1");
1093 command
= virusfilter_string_sub(mem_ctx
, conn
,
1094 config
->scan_error_command
);
1095 if (command
== NULL
) {
1096 DBG_ERR("virusfilter_string_sub failed\n");
1100 DBG_NOTICE("Scan error command line: %s/%s: %s\n", cwd_fname
,
1103 command_result
= virusfilter_shell_run(mem_ctx
, command
, &env_list
,
1105 if (command_result
!= 0) {
1106 DBG_ERR("Scan error command failed: %d\n", command_result
);
1110 TALLOC_FREE(env_list
);
1111 TALLOC_FREE(command
);
1114 static virusfilter_result
virusfilter_scan(
1115 struct vfs_handle_struct
*handle
,
1116 struct virusfilter_config
*config
,
1117 const struct files_struct
*fsp
)
1119 virusfilter_result scan_result
;
1120 char *scan_report
= NULL
;
1121 const char *fname
= fsp
->fsp_name
->base_name
;
1122 const char *cwd_fname
= fsp
->conn
->cwd_fsp
->fsp_name
->base_name
;
1123 struct virusfilter_cache_entry
*scan_cache_e
= NULL
;
1124 bool is_cache
= false;
1125 virusfilter_action file_action
= VIRUSFILTER_ACTION_DO_NOTHING
;
1126 bool add_scan_cache
= true;
1129 if (config
->cache
) {
1130 DBG_DEBUG("Searching cache entry: fname: %s\n", fname
);
1131 scan_cache_e
= virusfilter_cache_get(config
->cache
,
1133 if (scan_cache_e
!= NULL
) {
1134 DBG_DEBUG("Cache entry found: cached result: %d\n",
1135 scan_cache_e
->result
);
1137 scan_result
= scan_cache_e
->result
;
1138 scan_report
= scan_cache_e
->report
;
1139 goto virusfilter_scan_result_eval
;
1141 DBG_DEBUG("Cache entry not found\n");
1144 if (config
->backend
->fns
->scan_init
!= NULL
) {
1145 scan_result
= config
->backend
->fns
->scan_init(config
);
1146 if (scan_result
!= VIRUSFILTER_RESULT_OK
) {
1147 scan_result
= VIRUSFILTER_RESULT_ERROR
;
1148 scan_report
= talloc_asprintf(
1150 "Initializing scanner failed");
1151 goto virusfilter_scan_result_eval
;
1155 scan_result
= config
->backend
->fns
->scan(handle
, config
, fsp
,
1158 if (config
->backend
->fns
->scan_end
!= NULL
) {
1159 bool scan_end
= true;
1161 if (config
->scan_request_limit
> 0) {
1163 config
->scan_request_count
++;
1164 if (config
->scan_request_count
>=
1165 config
->scan_request_limit
)
1168 config
->scan_request_count
= 0;
1172 config
->backend
->fns
->scan_end(config
);
1176 virusfilter_scan_result_eval
:
1178 switch (scan_result
) {
1179 case VIRUSFILTER_RESULT_CLEAN
:
1180 DBG_INFO("Scan result: Clean: %s/%s\n", cwd_fname
, fname
);
1183 case VIRUSFILTER_RESULT_INFECTED
:
1184 DBG_ERR("Scan result: Infected: %s/%s: %s\n",
1185 cwd_fname
, fname
, scan_report
? scan_report
:
1186 "infected (memory error on report)");
1187 file_action
= virusfilter_treat_infected_file(handle
,
1188 config
, fsp
, scan_report
, is_cache
);
1189 if (file_action
!= VIRUSFILTER_ACTION_DO_NOTHING
) {
1190 add_scan_cache
= false;
1194 case VIRUSFILTER_RESULT_SUSPECTED
:
1195 if (!config
->block_suspected_file
) {
1198 DBG_ERR("Scan result: Suspected: %s/%s: %s\n",
1199 cwd_fname
, fname
, scan_report
? scan_report
:
1200 "suspected infection (memory error on report)");
1201 file_action
= virusfilter_treat_infected_file(handle
,
1202 config
, fsp
, scan_report
, is_cache
);
1203 if (file_action
!= VIRUSFILTER_ACTION_DO_NOTHING
) {
1204 add_scan_cache
= false;
1208 case VIRUSFILTER_RESULT_ERROR
:
1209 DBG_ERR("Scan result: Error: %s/%s: %s\n",
1210 cwd_fname
, fname
, scan_report
? scan_report
:
1211 "error (memory error on report)");
1212 virusfilter_treat_scan_error(handle
, config
, fsp
,
1213 scan_report
, is_cache
);
1214 add_scan_cache
= false;
1218 DBG_ERR("Scan result: Unknown result code %d: %s/%s: %s\n",
1219 scan_result
, cwd_fname
, fname
, scan_report
?
1220 scan_report
: "Unknown (memory error on report)");
1221 virusfilter_treat_scan_error(handle
, config
, fsp
,
1222 scan_report
, is_cache
);
1223 add_scan_cache
= false;
1227 if (config
->cache
) {
1228 if (!is_cache
&& add_scan_cache
) {
1229 DBG_DEBUG("Adding new cache entry: %s, %d\n", fname
,
1231 ok
= virusfilter_cache_entry_add(
1232 config
->cache
, cwd_fname
, fname
,
1233 scan_result
, scan_report
);
1235 DBG_ERR("Cannot create cache entry: "
1236 "virusfilter_cache_entry_new failed\n");
1237 goto virusfilter_scan_return
;
1239 } else if (is_cache
) {
1240 virusfilter_cache_entry_free(scan_cache_e
);
1244 virusfilter_scan_return
:
1248 static int virusfilter_vfs_openat(struct vfs_handle_struct
*handle
,
1249 const struct files_struct
*dirfsp
,
1250 const struct smb_filename
*smb_fname_in
,
1251 struct files_struct
*fsp
,
1252 const struct vfs_open_how
*how
)
1254 TALLOC_CTX
*mem_ctx
= talloc_tos();
1255 struct virusfilter_config
*config
= NULL
;
1256 const char *cwd_fname
= dirfsp
->fsp_name
->base_name
;
1257 virusfilter_result scan_result
;
1258 const char *fname
= fsp
->fsp_name
->base_name
;
1259 char *dir_name
= NULL
;
1260 const char *base_name
= NULL
;
1264 int rename_trap_count
= 0;
1268 struct smb_filename
*smb_fname
= NULL
;
1269 SMB_STRUCT_STAT sbuf
= smb_fname_in
->st
;
1271 SMB_VFS_HANDLE_GET_DATA(handle
, config
,
1272 struct virusfilter_config
, return -1);
1274 if (fsp
->fsp_flags
.is_directory
) {
1275 DBG_INFO("Not scanned: Directory: %s/\n", cwd_fname
);
1276 goto virusfilter_vfs_open_next
;
1279 test_prefix
= strlen(config
->rename_prefix
);
1280 test_suffix
= strlen(config
->rename_suffix
);
1281 if (test_prefix
> 0) {
1282 rename_trap_count
++;
1284 if (test_suffix
> 0) {
1285 rename_trap_count
++;
1288 smb_fname
= cp_smb_filename(mem_ctx
, smb_fname_in
);
1289 if (smb_fname
== NULL
) {
1290 goto virusfilter_vfs_open_fail
;
1293 if (is_named_stream(smb_fname
)) {
1294 DBG_INFO("Not scanned: only file backed streams can be scanned:"
1295 " %s/%s\n", cwd_fname
, fname
);
1296 goto virusfilter_vfs_open_next
;
1299 if (!config
->scan_on_open
) {
1300 DBG_INFO("Not scanned: scan on open is disabled: %s/%s\n",
1302 goto virusfilter_vfs_open_next
;
1305 if (how
->flags
& O_TRUNC
) {
1306 DBG_INFO("Not scanned: Open flags have O_TRUNC: %s/%s\n",
1308 goto virusfilter_vfs_open_next
;
1311 ret
= SMB_VFS_NEXT_FSTAT(handle
, fsp
, &sbuf
);
1315 * Do not return immediately if !(flags & O_CREAT) &&
1317 * Do not do this here or anywhere else. The module is
1318 * stackable and there may be modules below, such as audit
1319 * modules, which should be handled.
1321 goto virusfilter_vfs_open_next
;
1323 ret
= S_ISREG(sbuf
.st_ex_mode
);
1325 DBG_INFO("Not scanned: Directory or special file: %s/%s\n",
1327 goto virusfilter_vfs_open_next
;
1329 if (config
->max_file_size
> 0 &&
1330 sbuf
.st_ex_size
> config
->max_file_size
)
1332 DBG_INFO("Not scanned: file size > max file size: %s/%s\n",
1334 goto virusfilter_vfs_open_next
;
1336 if (config
->min_file_size
> 0 &&
1337 sbuf
.st_ex_size
< config
->min_file_size
)
1339 DBG_INFO("Not scanned: file size < min file size: %s/%s\n",
1341 goto virusfilter_vfs_open_next
;
1344 ok1
= is_in_path(fname
, config
->exclude_files
, false);
1345 if (config
->exclude_files
&& ok1
)
1347 DBG_INFO("Not scanned: exclude files: %s/%s\n",
1349 goto virusfilter_vfs_open_next
;
1352 if (config
->infected_file_action
== VIRUSFILTER_ACTION_QUARANTINE
) {
1353 sret
= strstr_m(fname
, config
->quarantine_dir
);
1355 scan_errno
= config
->infected_open_errno
;
1356 goto virusfilter_vfs_open_fail
;
1360 if (test_prefix
> 0 || test_suffix
> 0) {
1361 ok1
= parent_dirname(mem_ctx
, fname
, &dir_name
, &base_name
);
1364 if (test_prefix
> 0) {
1365 ret
= strncmp(base_name
,
1366 config
->rename_prefix
, test_prefix
);
1371 if (test_suffix
> 0) {
1372 ret
= strcmp(base_name
+ (strlen(base_name
)
1374 config
->rename_suffix
);
1380 TALLOC_FREE(dir_name
);
1382 if ((rename_trap_count
== 2 && test_prefix
&&
1383 test_suffix
) || (rename_trap_count
== 1 &&
1384 (test_prefix
|| test_suffix
)))
1387 config
->infected_open_errno
;
1388 goto virusfilter_vfs_open_fail
;
1393 scan_result
= virusfilter_scan(handle
, config
, fsp
);
1395 switch (scan_result
) {
1396 case VIRUSFILTER_RESULT_CLEAN
:
1398 case VIRUSFILTER_RESULT_INFECTED
:
1399 scan_errno
= config
->infected_open_errno
;
1400 goto virusfilter_vfs_open_fail
;
1401 case VIRUSFILTER_RESULT_ERROR
:
1402 if (config
->block_access_on_error
) {
1403 DBG_INFO("Block access\n");
1404 scan_errno
= config
->scan_error_open_errno
;
1405 goto virusfilter_vfs_open_fail
;
1409 scan_errno
= config
->scan_error_open_errno
;
1410 goto virusfilter_vfs_open_fail
;
1413 TALLOC_FREE(smb_fname
);
1415 virusfilter_vfs_open_next
:
1416 return SMB_VFS_NEXT_OPENAT(handle
, dirfsp
, smb_fname_in
, fsp
, how
);
1418 virusfilter_vfs_open_fail
:
1419 TALLOC_FREE(smb_fname
);
1420 errno
= (scan_errno
!= 0) ? scan_errno
: EACCES
;
1424 static int virusfilter_vfs_close(
1425 struct vfs_handle_struct
*handle
,
1429 * The name of this variable is for consistency. If API changes to
1430 * match _open change to cwd_fname as in virusfilter_vfs_open.
1432 const char *cwd_fname
= handle
->conn
->connectpath
;
1434 struct virusfilter_config
*config
= NULL
;
1435 char *fname
= fsp
->fsp_name
->base_name
;
1436 int close_result
= -1;
1437 int close_errno
= 0;
1438 virusfilter_result scan_result
;
1441 SMB_VFS_HANDLE_GET_DATA(handle
, config
,
1442 struct virusfilter_config
, return -1);
1445 * Must close after scan? It appears not as the scanners are not
1446 * internal and other modules such as greyhole seem to do
1447 * SMB_VFS_NEXT_* functions before processing.
1449 close_result
= SMB_VFS_NEXT_CLOSE(handle
, fsp
);
1450 if (close_result
== -1) {
1451 close_errno
= errno
;
1455 * Return immediately if close_result == -1, and close_errno == EBADF.
1456 * If close failed, file likely doesn't exist, do not try to scan.
1458 if (close_result
== -1 && close_errno
== EBADF
) {
1459 if (fsp
->fsp_flags
.modified
) {
1460 DBG_DEBUG("Removing cache entry (if existent): "
1461 "fname: %s\n", fname
);
1462 virusfilter_cache_remove(config
->cache
,
1465 goto virusfilter_vfs_close_fail
;
1468 if (fsp
->fsp_flags
.is_directory
) {
1469 DBG_INFO("Not scanned: Directory: %s/\n", cwd_fname
);
1470 return close_result
;
1473 if (fsp_is_alternate_stream(fsp
)) {
1474 if (config
->scan_on_open
&& fsp
->fsp_flags
.modified
) {
1475 if (config
->cache
) {
1476 DBG_DEBUG("Removing cache entry (if existent)"
1477 ": fname: %s\n", fname
);
1478 virusfilter_cache_remove(
1483 DBG_INFO("Not scanned: only file backed streams can be scanned:"
1484 " %s/%s\n", cwd_fname
, fname
);
1485 return close_result
;
1488 if (!config
->scan_on_close
) {
1489 if (config
->scan_on_open
&& fsp
->fsp_flags
.modified
) {
1490 if (config
->cache
) {
1491 DBG_DEBUG("Removing cache entry (if existent)"
1492 ": fname: %s\n", fname
);
1493 virusfilter_cache_remove(
1498 DBG_INFO("Not scanned: scan on close is disabled: %s/%s\n",
1500 return close_result
;
1503 if (!fsp
->fsp_flags
.modified
) {
1504 DBG_NOTICE("Not scanned: File not modified: %s/%s\n",
1507 return close_result
;
1510 if (is_in_path(fname
, config
->exclude_files
, false)) {
1511 DBG_INFO("Not scanned: exclude files: %s/%s\n",
1513 return close_result
;
1516 scan_result
= virusfilter_scan(handle
, config
, fsp
);
1518 switch (scan_result
) {
1519 case VIRUSFILTER_RESULT_CLEAN
:
1521 case VIRUSFILTER_RESULT_INFECTED
:
1522 scan_errno
= config
->infected_close_errno
;
1523 goto virusfilter_vfs_close_fail
;
1524 case VIRUSFILTER_RESULT_ERROR
:
1525 if (config
->block_access_on_error
) {
1526 DBG_INFO("Block access\n");
1527 scan_errno
= config
->scan_error_close_errno
;
1528 goto virusfilter_vfs_close_fail
;
1532 scan_errno
= config
->scan_error_close_errno
;
1533 goto virusfilter_vfs_close_fail
;
1536 if (close_errno
!= 0) {
1537 errno
= close_errno
;
1540 return close_result
;
1542 virusfilter_vfs_close_fail
:
1544 errno
= (scan_errno
!= 0) ? scan_errno
: close_errno
;
1546 return close_result
;
1549 static int virusfilter_vfs_unlinkat(struct vfs_handle_struct
*handle
,
1550 struct files_struct
*dirfsp
,
1551 const struct smb_filename
*smb_fname
,
1554 int ret
= SMB_VFS_NEXT_UNLINKAT(handle
,
1558 struct virusfilter_config
*config
= NULL
;
1559 struct smb_filename
*full_fname
= NULL
;
1561 char *cwd_fname
= dirfsp
->fsp_name
->base_name
;
1563 if (ret
!= 0 && errno
!= ENOENT
) {
1567 SMB_VFS_HANDLE_GET_DATA(handle
, config
,
1568 struct virusfilter_config
, return -1);
1570 if (config
->cache
== NULL
) {
1574 full_fname
= full_path_from_dirfsp_atname(talloc_tos(),
1577 if (full_fname
== NULL
) {
1581 fname
= full_fname
->base_name
;
1583 DBG_DEBUG("Removing cache entry (if existent): fname: %s\n", fname
);
1584 virusfilter_cache_remove(config
->cache
, cwd_fname
, fname
);
1586 TALLOC_FREE(full_fname
);
1590 static int virusfilter_vfs_renameat(
1591 struct vfs_handle_struct
*handle
,
1592 files_struct
*srcfsp
,
1593 const struct smb_filename
*smb_fname_src
,
1594 files_struct
*dstfsp
,
1595 const struct smb_filename
*smb_fname_dst
,
1596 const struct vfs_rename_how
*how
)
1598 int ret
= SMB_VFS_NEXT_RENAMEAT(handle
,
1604 struct virusfilter_config
*config
= NULL
;
1606 char *dst_fname
= NULL
;
1607 char *cwd_fname
= handle
->conn
->cwd_fsp
->fsp_name
->base_name
;
1608 struct smb_filename
*full_src
= NULL
;
1609 struct smb_filename
*full_dst
= NULL
;
1615 SMB_VFS_HANDLE_GET_DATA(handle
, config
,
1616 struct virusfilter_config
, return -1);
1618 if (config
->cache
== NULL
) {
1622 full_src
= full_path_from_dirfsp_atname(talloc_tos(),
1625 if (full_src
== NULL
) {
1631 full_dst
= full_path_from_dirfsp_atname(talloc_tos(),
1634 if (full_dst
== NULL
) {
1640 fname
= full_src
->base_name
;
1641 dst_fname
= full_dst
->base_name
;
1643 DBG_DEBUG("Renaming cache entry: fname: %s to: %s\n",
1645 virusfilter_cache_entry_rename(config
->cache
,
1652 TALLOC_FREE(full_src
);
1653 TALLOC_FREE(full_dst
);
1658 /* VFS operations */
1659 static struct vfs_fn_pointers vfs_virusfilter_fns
= {
1660 .connect_fn
= virusfilter_vfs_connect
,
1661 .disconnect_fn
= virusfilter_vfs_disconnect
,
1662 .openat_fn
= virusfilter_vfs_openat
,
1663 .close_fn
= virusfilter_vfs_close
,
1664 .unlinkat_fn
= virusfilter_vfs_unlinkat
,
1665 .renameat_fn
= virusfilter_vfs_renameat
,
1668 NTSTATUS
vfs_virusfilter_init(TALLOC_CTX
*);
1669 NTSTATUS
vfs_virusfilter_init(TALLOC_CTX
*ctx
)
1673 status
= smb_register_vfs(SMB_VFS_INTERFACE_VERSION
,
1675 &vfs_virusfilter_fns
);
1676 if (!NT_STATUS_IS_OK(status
)) {
1680 virusfilter_debug_class
= debug_add_class("virusfilter");
1681 if (virusfilter_debug_class
== -1) {
1682 virusfilter_debug_class
= DBGC_VFS
;
1683 DBG_ERR("Couldn't register custom debugging class!\n");
1685 DBG_DEBUG("Debug class number: %d\n", virusfilter_debug_class
);
1688 DBG_INFO("registered\n");