Fix spelling s/Everytime/Every time/
[Samba.git] / source3 / modules / vfs_virusfilter_utils.c
blobf56fc6ed5d8bc04d26d5752c55f6644e0feca923
1 /*
2 Samba-VirusFilter VFS modules
3 Copyright (C) 2010-2016 SATOH Fumiyasu @ OSS Technology Corp., Japan
4 Copyright (C) 2016-2017 Trever L. Adams
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 #include "modules/vfs_virusfilter_common.h"
21 #include "modules/vfs_virusfilter_utils.h"
23 struct iovec;
25 #include "lib/util/iov_buf.h"
26 #include <tevent.h>
27 #include "lib/tsocket/tsocket.h"
29 int virusfilter_debug_class = DBGC_VFS;
31 /* ====================================================================== */
33 char *virusfilter_string_sub(
34 TALLOC_CTX *mem_ctx,
35 connection_struct *conn,
36 const char *str)
38 return talloc_sub_advanced(mem_ctx,
39 lp_servicename(mem_ctx, SNUM(conn)),
40 conn->session_info->unix_info->unix_name,
41 conn->connectpath,
42 conn->session_info->unix_token->gid,
43 conn->session_info->unix_info->sanitized_username,
44 conn->session_info->info->domain_name,
45 str);
48 int virusfilter_vfs_next_move(
49 struct vfs_handle_struct *vfs_h,
50 const struct smb_filename *smb_fname_src,
51 const struct smb_filename *smb_fname_dst)
53 int result;
55 result = SMB_VFS_NEXT_RENAME(vfs_h, smb_fname_src, smb_fname_dst);
56 if (result == 0 || errno != EXDEV) {
57 return result;
61 * For now, do not handle EXDEV as poking around violates
62 * stackability. Return -1, simply refuse access.
64 return -1;
67 /* Line-based socket I/O
68 * ======================================================================
71 struct virusfilter_io_handle *virusfilter_io_new(
72 TALLOC_CTX *mem_ctx,
73 int connect_timeout,
74 int io_timeout)
76 struct virusfilter_io_handle *io_h = talloc_zero(mem_ctx,
77 struct virusfilter_io_handle);
79 if (io_h == NULL) {
80 return NULL;
83 io_h->stream = NULL;
84 io_h->r_len = 0;
86 virusfilter_io_set_connect_timeout(io_h, connect_timeout);
87 virusfilter_io_set_io_timeout(io_h, io_timeout);
88 virusfilter_io_set_writel_eol(io_h, "\x0A", 1);
89 virusfilter_io_set_readl_eol(io_h, "\x0A", 1);
91 return io_h;
94 int virusfilter_io_set_connect_timeout(
95 struct virusfilter_io_handle *io_h,
96 int timeout)
98 int timeout_old = io_h->connect_timeout;
100 /* timeout <= 0 means infinite */
101 io_h->connect_timeout = (timeout > 0) ? timeout : -1;
103 return timeout_old;
106 int virusfilter_io_set_io_timeout(
107 struct virusfilter_io_handle *io_h,
108 int timeout)
110 int timeout_old = io_h->io_timeout;
112 /* timeout <= 0 means infinite */
113 io_h->io_timeout = (timeout > 0) ? timeout : -1;
115 return timeout_old;
118 void virusfilter_io_set_writel_eol(
119 struct virusfilter_io_handle *io_h,
120 const char *eol,
121 int eol_size)
123 if (eol_size < 1 || eol_size > VIRUSFILTER_IO_EOL_SIZE) {
124 return;
127 memcpy(io_h->w_eol, eol, eol_size);
128 io_h->w_eol_size = eol_size;
131 void virusfilter_io_set_readl_eol(
132 struct virusfilter_io_handle *io_h,
133 const char *eol,
134 int eol_size)
136 if (eol_size < 1 || eol_size > VIRUSFILTER_IO_EOL_SIZE) {
137 return;
140 memcpy(io_h->r_eol, eol, eol_size);
141 io_h->r_eol_size = eol_size;
144 bool virusfilter_io_connect_path(
145 struct virusfilter_io_handle *io_h,
146 const char *path)
148 struct sockaddr_un addr;
149 NTSTATUS status;
150 int socket, ret;
151 size_t len;
152 bool ok;
154 ZERO_STRUCT(addr);
155 addr.sun_family = AF_UNIX;
157 len = strlcpy(addr.sun_path, path, sizeof(addr.sun_path));
158 if (len >= sizeof(addr.sun_path)) {
159 io_h->stream = NULL;
160 return false;
163 status = open_socket_out((struct sockaddr_storage *)&addr, 0,
164 io_h->connect_timeout,
165 &socket);
166 if (!NT_STATUS_IS_OK(status)) {
167 io_h->stream = NULL;
168 return false;
171 /* We must not block */
172 ret = set_blocking(socket, false);
173 if (ret == -1) {
174 close(socket);
175 io_h->stream = NULL;
176 return false;
179 ok = smb_set_close_on_exec(socket);
180 if (!ok) {
181 close(socket);
182 io_h->stream = NULL;
183 return false;
186 ret = tstream_bsd_existing_socket(io_h, socket, &io_h->stream);
187 if (ret == -1) {
188 close(socket);
189 DBG_ERR("Could not convert socket to tstream: %s.\n",
190 strerror(errno));
191 io_h->stream = NULL;
192 return false;
195 return true;
198 static void disconnect_done(struct tevent_req *req)
200 uint64_t *perr = tevent_req_callback_data(req, uint64_t);
201 int ret;
202 int err_ret;
204 ret = tstream_disconnect_recv(req, &err_ret);
205 TALLOC_FREE(req);
206 if (ret == -1) {
207 *perr = err_ret;
211 bool virusfilter_io_disconnect(
212 struct virusfilter_io_handle *io_h)
214 struct tevent_req *req;
215 struct tevent_context *ev;
216 uint64_t *perror = NULL;
217 bool ok = true;
218 TALLOC_CTX *frame = talloc_stackframe();
220 if (io_h->stream == NULL) {
221 io_h->r_len = 0;
222 TALLOC_FREE(frame);
223 return VIRUSFILTER_RESULT_OK;
226 ev = tevent_context_init(frame);
227 if (ev == NULL) {
228 DBG_ERR("Failed to setup event context.\n");
229 ok = false;
230 goto fail;
233 /* Error return - must be talloc'ed. */
234 perror = talloc_zero(frame, uint64_t);
235 if (perror == NULL) {
236 goto fail;
239 req = tstream_disconnect_send(io_h, ev, io_h->stream);
241 /* Callback when disconnect is done. */
242 tevent_req_set_callback(req, disconnect_done, perror);
244 /* Set timeout. */
245 ok = tevent_req_set_endtime(req, ev, timeval_current_ofs_msec(
246 io_h->connect_timeout));
247 if (!ok) {
248 DBG_ERR("Can't set endtime\n");
249 goto fail;
252 /* Loop waiting for req to finish. */
253 ok = tevent_req_poll(req, ev);
254 if (!ok) {
255 DBG_ERR("tevent_req_poll failed\n");
256 goto fail;
259 /* Emit debug error if failed. */
260 if (*perror != 0) {
261 DBG_DEBUG("Error %s\n", strerror((int)*perror));
262 goto fail;
265 /* Here we know we disconnected. */
267 io_h->stream = NULL;
268 io_h->r_len = 0;
270 fail:
271 TALLOC_FREE(frame);
272 return ok;
275 static void writev_done(struct tevent_req *req)
277 uint64_t *perr = tevent_req_callback_data(req, uint64_t);
278 int ret;
279 int err_ret;
281 ret = tstream_writev_recv(req, &err_ret);
282 TALLOC_FREE(req);
283 if (ret == -1) {
284 *perr = err_ret;
288 /****************************************************************************
289 Write all data from an iov array, with msec timeout (per write)
290 NB. This can be called with a non-socket fd, don't add dependencies
291 on socket calls.
292 ****************************************************************************/
294 bool write_data_iov_timeout(
295 struct tstream_context *stream,
296 const struct iovec *iov,
297 size_t iovcnt,
298 int ms_timeout)
300 struct tevent_context *ev = NULL;
301 struct tevent_req *req = NULL;
302 uint64_t *perror = NULL;
303 bool ok = false;
304 TALLOC_CTX *frame = talloc_stackframe();
306 ev = tevent_context_init(frame);
307 if (ev == NULL) {
308 DBG_ERR("Failed to setup event context.\n");
309 goto fail;
312 /* Error return - must be talloc'ed. */
313 perror = talloc_zero(frame, uint64_t);
314 if (perror == NULL) {
315 goto fail;
318 /* Send the data. */
319 req = tstream_writev_send(frame, ev, stream, iov, iovcnt);
320 if (req == NULL) {
321 DBG_ERR("Out of memory.\n");
322 goto fail;
325 /* Callback when *all* data sent. */
326 tevent_req_set_callback(req, writev_done, perror);
328 /* Set timeout. */
329 ok = tevent_req_set_endtime(req, ev,
330 timeval_current_ofs_msec(ms_timeout));
331 if (!ok) {
332 DBG_ERR("Can't set endtime\n");
333 goto fail;
336 /* Loop waiting for req to finish. */
337 ok = tevent_req_poll(req, ev);
338 if (!ok) {
339 DBG_ERR("tevent_req_poll failed\n");
340 goto fail;
343 /* Done with req - freed by the callback. */
344 req = NULL;
346 /* Emit debug error if failed. */
347 if (*perror != 0) {
348 DBG_DEBUG("Error %s\n", strerror((int)*perror));
349 goto fail;
352 /* Here we know we correctly wrote all data. */
353 TALLOC_FREE(frame);
354 return true;
356 fail:
357 TALLOC_FREE(frame);
358 return false;
361 bool virusfilter_io_write(
362 struct virusfilter_io_handle *io_h,
363 const char *data,
364 size_t data_size)
366 struct iovec iov;
368 if (data_size == 0) {
369 return VIRUSFILTER_RESULT_OK;
372 iov.iov_base = discard_const_p(void, data);
373 iov.iov_len = data_size;
375 return write_data_iov_timeout(io_h->stream, &iov, 1, io_h->io_timeout);
378 bool virusfilter_io_writel(
379 struct virusfilter_io_handle *io_h,
380 const char *data,
381 size_t data_size)
383 bool ok;
385 ok = virusfilter_io_write(io_h, data, data_size);
386 if (!ok) {
387 return ok;
390 return virusfilter_io_write(io_h, io_h->w_eol, io_h->w_eol_size);
393 bool virusfilter_io_writefl(
394 struct virusfilter_io_handle *io_h,
395 const char *data_fmt, ...)
397 va_list ap;
398 char data[VIRUSFILTER_IO_BUFFER_SIZE + VIRUSFILTER_IO_EOL_SIZE];
399 int data_size;
401 va_start(ap, data_fmt);
402 data_size = vsnprintf(data, VIRUSFILTER_IO_BUFFER_SIZE, data_fmt, ap);
403 va_end(ap);
405 if (unlikely (data_size < 0)) {
406 DBG_ERR("vsnprintf failed: %s\n", strerror(errno));
407 return false;
410 memcpy(data + data_size, io_h->w_eol, io_h->w_eol_size);
411 data_size += io_h->w_eol_size;
413 return virusfilter_io_write(io_h, data, data_size);
416 bool virusfilter_io_vwritefl(
417 struct virusfilter_io_handle *io_h,
418 const char *data_fmt, va_list ap)
420 char data[VIRUSFILTER_IO_BUFFER_SIZE + VIRUSFILTER_IO_EOL_SIZE];
421 int data_size;
423 data_size = vsnprintf(data, VIRUSFILTER_IO_BUFFER_SIZE, data_fmt, ap);
425 if (unlikely (data_size < 0)) {
426 DBG_ERR("vsnprintf failed: %s\n", strerror(errno));
427 return false;
430 memcpy(data + data_size, io_h->w_eol, io_h->w_eol_size);
431 data_size += io_h->w_eol_size;
433 return virusfilter_io_write(io_h, data, data_size);
436 bool virusfilter_io_writev(
437 struct virusfilter_io_handle *io_h, ...)
439 va_list ap;
440 struct iovec iov[VIRUSFILTER_IO_IOV_MAX], *iov_p;
441 int iov_n;
443 va_start(ap, io_h);
444 for (iov_p = iov, iov_n = 0;
445 iov_n < VIRUSFILTER_IO_IOV_MAX;
446 iov_p++, iov_n++)
448 iov_p->iov_base = va_arg(ap, void *);
449 if (iov_p->iov_base == NULL) {
450 break;
452 iov_p->iov_len = va_arg(ap, int);
454 va_end(ap);
456 return write_data_iov_timeout(io_h->stream, iov, iov_n,
457 io_h->io_timeout);
460 bool virusfilter_io_writevl(
461 struct virusfilter_io_handle *io_h, ...)
463 va_list ap;
464 struct iovec iov[VIRUSFILTER_IO_IOV_MAX + 1], *iov_p;
465 int iov_n;
467 va_start(ap, io_h);
468 for (iov_p = iov, iov_n = 0; iov_n < VIRUSFILTER_IO_IOV_MAX;
469 iov_p++, iov_n++)
471 iov_p->iov_base = va_arg(ap, void *);
472 if (iov_p->iov_base == NULL) {
473 break;
475 iov_p->iov_len = va_arg(ap, int);
477 va_end(ap);
479 iov_p->iov_base = io_h->r_eol;
480 iov_p->iov_len = io_h->r_eol_size;
481 iov_n++;
483 return write_data_iov_timeout(io_h->stream, iov, iov_n,
484 io_h->io_timeout);
487 static bool return_existing_line(TALLOC_CTX *ctx,
488 struct virusfilter_io_handle *io_h,
489 char **read_line)
491 size_t read_line_len = 0;
492 char *end_p = NULL;
493 char *eol = NULL;
495 eol = memmem(io_h->r_buffer, io_h->r_len,
496 io_h->r_eol, io_h->r_eol_size);
497 if (eol == NULL) {
498 return false;
500 end_p = eol + io_h->r_eol_size;
502 *eol = '\0';
503 read_line_len = strlen(io_h->r_buffer) + 1;
504 *read_line = talloc_memdup(ctx,
505 io_h->r_buffer,
506 read_line_len);
507 if (*read_line == NULL) {
508 return false;
512 * Copy the remaining buffer over the line
513 * we returned.
515 memmove(io_h->r_buffer,
516 end_p,
517 io_h->r_len - (end_p - io_h->r_buffer));
519 /* And reduce the size left in the buffer. */
520 io_h->r_len -= (end_p - io_h->r_buffer);
521 return true;
524 static void readv_done(struct tevent_req *req)
526 uint64_t *perr = tevent_req_callback_data(req, uint64_t);
527 int ret;
528 int err_ret;
530 ret = tstream_readv_recv(req, &err_ret);
531 TALLOC_FREE(req);
532 if (ret == -1) {
533 *perr = err_ret;
537 bool virusfilter_io_readl(TALLOC_CTX *ctx,
538 struct virusfilter_io_handle *io_h,
539 char **read_line)
541 struct tevent_context *ev = NULL;
542 bool ok = false;
543 uint64_t *perror = NULL;
544 TALLOC_CTX *frame = talloc_stackframe();
546 /* Search for an existing complete line. */
547 ok = return_existing_line(ctx, io_h, read_line);
548 if (ok) {
549 goto finish;
553 * No complete line in the buffer. We must read more
554 * from the server.
556 ev = tevent_context_init(frame);
557 if (ev == NULL) {
558 DBG_ERR("Failed to setup event context.\n");
559 goto finish;
562 /* Error return - must be talloc'ed. */
563 perror = talloc_zero(frame, uint64_t);
564 if (perror == NULL) {
565 goto finish;
568 for (;;) {
569 ssize_t pending = 0;
570 size_t read_size = 0;
571 struct iovec iov;
572 struct tevent_req *req = NULL;
575 * How much can we read ?
577 pending = tstream_pending_bytes(io_h->stream);
578 if (pending < 0) {
579 DBG_ERR("tstream_pending_bytes failed (%s).\n",
580 strerror(errno));
581 goto finish;
584 read_size = pending;
585 /* Must read at least one byte. */
586 read_size = MIN(read_size, 1);
588 /* And max remaining buffer space. */
589 read_size = MAX(read_size,
590 (sizeof(io_h->r_buffer) - io_h->r_len));
592 if (read_size == 0) {
593 /* Buffer is full with no EOL. Error out. */
594 DBG_ERR("Line buffer full.\n");
595 goto finish;
598 iov.iov_base = io_h->r_buffer + io_h->r_len;
599 iov.iov_len = read_size;
601 /* Read the data. */
602 req = tstream_readv_send(frame,
604 io_h->stream,
605 &iov,
607 if (req == NULL) {
608 DBG_ERR("out of memory.\n");
609 goto finish;
612 /* Callback when *all* data read. */
613 tevent_req_set_callback(req, readv_done, perror);
615 /* Set timeout. */
616 ok = tevent_req_set_endtime(req, ev,
617 timeval_current_ofs_msec(io_h->io_timeout));
618 if (!ok) {
619 DBG_ERR("can't set endtime\n");
620 goto finish;
623 /* Loop waiting for req to finish. */
624 ok = tevent_req_poll(req, ev);
625 if (!ok) {
626 DBG_ERR("tevent_req_poll failed\n");
627 goto finish;
630 /* Done with req - freed by the callback. */
631 req = NULL;
634 * Emit debug error if failed.
635 * EPIPE may be success so, don't exit.
637 if (*perror != 0 && *perror != EPIPE) {
638 DBG_DEBUG("Error %s\n", strerror((int)*perror));
639 errno = (int)*perror;
640 goto finish;
644 * We read read_size bytes. Extend the useable
645 * buffer length.
647 io_h->r_len += read_size;
649 /* Paranoia... */
650 SMB_ASSERT(io_h->r_len <= sizeof(io_h->r_buffer));
652 /* Exit if we have a line to return. */
653 ok = return_existing_line(ctx, io_h, read_line);
654 if (ok) {
655 goto finish;
657 /* No eol - keep reading. */
660 finish:
662 TALLOC_FREE(frame);
663 return ok;
666 bool virusfilter_io_writefl_readl(
667 struct virusfilter_io_handle *io_h,
668 char **read_line,
669 const char *fmt, ...)
671 bool ok;
673 if (fmt) {
674 va_list ap;
676 va_start(ap, fmt);
677 ok = virusfilter_io_vwritefl(io_h, fmt, ap);
678 va_end(ap);
680 if (!ok) {
681 return ok;
685 ok = virusfilter_io_readl(talloc_tos(), io_h, read_line);
686 if (!ok) {
687 DBG_ERR("virusfilter_io_readl not OK: %d\n", ok);
688 return false;
690 if (io_h->r_len == 0) { /* EOF */
691 DBG_ERR("virusfilter_io_readl EOF\n");
692 return false;
695 return true;
698 struct virusfilter_cache *virusfilter_cache_new(
699 TALLOC_CTX *ctx,
700 int entry_limit,
701 time_t time_limit)
703 struct virusfilter_cache *cache;
705 if (time_limit == 0) {
706 return NULL;
709 cache = talloc_zero(ctx, struct virusfilter_cache);
710 if (cache == NULL) {
711 DBG_ERR("talloc_zero failed.\n");
712 return NULL;
715 cache->cache = memcache_init(cache->ctx, entry_limit *
716 (sizeof(struct virusfilter_cache_entry)
717 + VIRUSFILTER_CACHE_BUFFER_SIZE));
718 if (cache->cache == NULL) {
719 DBG_ERR("memcache_init failed.\n");
720 return NULL;
722 cache->ctx = ctx;
723 cache->time_limit = time_limit;
725 return cache;
728 bool virusfilter_cache_entry_add(
729 struct virusfilter_cache *cache,
730 const char *directory,
731 const char *fname,
732 virusfilter_result result,
733 char *report)
735 int blob_size = sizeof(struct virusfilter_cache_entry);
736 struct virusfilter_cache_entry *cache_e =
737 talloc_zero_size(NULL, blob_size);
738 int fname_len = 0;
740 if (fname == NULL || directory == NULL) {
741 TALLOC_FREE(report);
742 return false;
745 fname = talloc_asprintf(talloc_tos(), "%s/%s", directory, fname);
747 if (fname == NULL) {
748 TALLOC_FREE(report);
749 return false;
752 fname_len = strlen(fname);
754 if (cache_e == NULL|| cache->time_limit == 0) {
755 TALLOC_FREE(report);
756 return false;
759 cache_e->result = result;
760 if (report != NULL) {
761 cache_e->report = talloc_steal(cache_e, report);
763 if (cache->time_limit > 0) {
764 cache_e->time = time(NULL);
767 memcache_add_talloc(cache->cache,
768 VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC,
769 data_blob_const(fname, fname_len), &cache_e);
771 return true;
774 bool virusfilter_cache_entry_rename(
775 struct virusfilter_cache *cache,
776 const char *directory,
777 char *old_fname,
778 char *new_fname)
780 int old_fname_len = 0;
781 int new_fname_len = 0;
782 struct virusfilter_cache_entry *new_data = NULL;
783 struct virusfilter_cache_entry *old_data = NULL;
785 if (old_fname == NULL || new_fname == NULL || directory == NULL) {
786 return false;
789 old_fname = talloc_asprintf(talloc_tos(), "%s/%s", directory, old_fname);
790 new_fname = talloc_asprintf(talloc_tos(), "%s/%s", directory, new_fname);
792 if (old_fname == NULL || new_fname == NULL) {
793 TALLOC_FREE(old_fname);
794 TALLOC_FREE(new_fname);
795 return false;
798 old_fname_len = strlen(old_fname);
799 new_fname_len = strlen(new_fname);
801 old_data = memcache_lookup_talloc(
802 cache->cache,
803 VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC,
804 data_blob_const(old_fname, old_fname_len));
806 if (old_data == NULL) {
807 return false;
810 new_data = talloc_memdup(cache->ctx, old_data,
811 sizeof(struct virusfilter_cache_entry));
812 if (new_data == NULL) {
813 return false;
815 new_data->report = talloc_strdup(new_data, old_data->report);
817 memcache_add_talloc(cache->cache,
818 VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC,
819 data_blob_const(new_fname, new_fname_len), &new_data);
821 memcache_delete(cache->cache, VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC,
822 data_blob_const(old_fname, old_fname_len));
824 return true;
827 void virusfilter_cache_purge(struct virusfilter_cache *cache)
829 memcache_flush(cache->cache, VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC);
832 struct virusfilter_cache_entry *virusfilter_cache_get(
833 struct virusfilter_cache *cache,
834 const char *directory,
835 const char *fname)
837 int fname_len = 0;
838 struct virusfilter_cache_entry *cache_e = NULL;
839 struct virusfilter_cache_entry *data = NULL;
841 if (fname == NULL || directory == NULL) {
842 return 0;
845 fname = talloc_asprintf(talloc_tos(), "%s/%s", directory, fname);
847 if (fname == NULL) {
848 return 0;
851 fname_len = strlen(fname);
853 data = memcache_lookup_talloc(cache->cache,
854 VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC,
855 data_blob_const(fname, fname_len));
857 if (data == NULL) {
858 return cache_e;
861 if (cache->time_limit > 0) {
862 if (time(NULL) - data->time > cache->time_limit) {
863 DBG_DEBUG("Cache entry is too old: %s\n",
864 fname);
865 virusfilter_cache_remove(cache, directory, fname);
866 return cache_e;
869 cache_e = talloc_memdup(cache->ctx, data,
870 sizeof(struct virusfilter_cache_entry));
871 if (cache_e == NULL) {
872 return NULL;
874 if (data->report != NULL) {
875 cache_e->report = talloc_strdup(cache_e, data->report);
876 } else {
877 cache_e->report = NULL;
880 return cache_e;
883 void virusfilter_cache_remove(struct virusfilter_cache *cache,
884 const char *directory,
885 const char *fname)
887 DBG_DEBUG("Purging cache entry: %s/%s\n", directory, fname);
889 if (fname == NULL || directory == NULL) {
890 return;
893 fname = talloc_asprintf(talloc_tos(), "%s/%s", directory, fname);
895 if (fname == NULL) {
896 return;
899 memcache_delete(cache->cache, VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC,
900 data_blob_const(fname, strlen(fname)));
903 void virusfilter_cache_entry_free(struct virusfilter_cache_entry *cache_e)
905 if (cache_e != NULL) {
906 TALLOC_FREE(cache_e->report);
907 cache_e->report = NULL;
909 TALLOC_FREE(cache_e);
912 /* Shell scripting
913 * ======================================================================
916 int virusfilter_env_set(
917 TALLOC_CTX *mem_ctx,
918 char **env_list,
919 const char *name,
920 const char *value)
922 char *env_new;
923 int ret;
925 env_new = talloc_asprintf(mem_ctx, "%s=%s", name, value);
926 if (env_new == NULL) {
927 DBG_ERR("talloc_asprintf failed\n");
928 return -1;
931 ret = strv_add(mem_ctx, env_list, env_new);
933 TALLOC_FREE(env_new);
935 return ret;
938 /* virusfilter_env version Samba's *_sub_advanced() in substitute.c */
939 int virusfilter_shell_set_conn_env(
940 TALLOC_CTX *mem_ctx,
941 char **env_list,
942 connection_struct *conn)
944 int snum = SNUM(conn);
945 char *server_addr_p;
946 char *client_addr_p;
947 const char *local_machine_name = get_local_machine_name();
948 fstring pidstr;
949 int ret;
951 if (local_machine_name == NULL || *local_machine_name == '\0') {
952 local_machine_name = lp_netbios_name();
955 server_addr_p = tsocket_address_inet_addr_string(
956 conn->sconn->local_address, talloc_tos());
958 if (server_addr_p != NULL) {
959 ret = strncmp("::ffff:", server_addr_p, 7);
960 if (ret == 0) {
961 server_addr_p += 7;
963 virusfilter_env_set(mem_ctx, env_list, "VIRUSFILTER_SERVER_IP",
964 server_addr_p);
966 TALLOC_FREE(server_addr_p);
968 virusfilter_env_set(mem_ctx, env_list, "VIRUSFILTER_SERVER_NAME",
969 myhostname());
970 virusfilter_env_set(mem_ctx, env_list,
971 "VIRUSFILTER_SERVER_NETBIOS_NAME",
972 local_machine_name);
973 slprintf(pidstr,sizeof(pidstr)-1, "%ld", (long)getpid());
974 virusfilter_env_set(mem_ctx, env_list, "VIRUSFILTER_SERVER_PID",
975 pidstr);
977 virusfilter_env_set(mem_ctx, env_list, "VIRUSFILTER_SERVICE_NAME",
978 lp_const_servicename(snum));
979 virusfilter_env_set(mem_ctx, env_list, "VIRUSFILTER_SERVICE_PATH",
980 conn->cwd_fname->base_name);
982 client_addr_p = tsocket_address_inet_addr_string(
983 conn->sconn->remote_address, talloc_tos());
985 if (client_addr_p != NULL) {
986 ret = strncmp("::ffff:", client_addr_p, 7);
987 if (ret == 0) {
988 client_addr_p += 7;
990 virusfilter_env_set(mem_ctx, env_list, "VIRUSFILTER_CLIENT_IP",
991 client_addr_p);
993 TALLOC_FREE(client_addr_p);
995 virusfilter_env_set(mem_ctx, env_list, "VIRUSFILTER_CLIENT_NAME",
996 conn->sconn->remote_hostname);
997 virusfilter_env_set(mem_ctx, env_list,
998 "VIRUSFILTER_CLIENT_NETBIOS_NAME",
999 get_remote_machine_name());
1001 virusfilter_env_set(mem_ctx, env_list, "VIRUSFILTER_USER_NAME",
1002 get_current_username());
1003 virusfilter_env_set(mem_ctx, env_list, "VIRUSFILTER_USER_DOMAIN",
1004 current_user_info.domain);
1006 return 0;
1009 /* Wrapper to Samba's smbrun() in smbrun.c */
1010 int virusfilter_shell_run(
1011 TALLOC_CTX *mem_ctx,
1012 const char *cmd,
1013 char **env_list,
1014 connection_struct *conn,
1015 bool sanitize)
1017 int ret;
1019 if (conn != NULL) {
1020 ret = virusfilter_shell_set_conn_env(mem_ctx, env_list, conn);
1021 if (ret == -1) {
1022 return -1;
1026 if (sanitize) {
1027 return smbrun(cmd, NULL, strv_to_env(talloc_tos(), *env_list));
1028 } else {
1029 return smbrun_no_sanitize(cmd, NULL, strv_to_env(talloc_tos(),
1030 *env_list));