python: models: rename argument ldb to samdb
[samba.git] / source3 / modules / vfs_virusfilter_utils.c
blobb4677799c50b77e9e744a3a4ed3c2b9036c18831
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"
28 #include "source3/lib/substitute.h"
30 int virusfilter_debug_class = DBGC_VFS;
32 /* ====================================================================== */
34 char *virusfilter_string_sub(
35 TALLOC_CTX *mem_ctx,
36 connection_struct *conn,
37 const char *str)
39 const struct loadparm_substitution *lp_sub =
40 loadparm_s3_global_substitution();
42 return talloc_sub_full(mem_ctx,
43 lp_servicename(mem_ctx, lp_sub, SNUM(conn)),
44 conn->session_info->unix_info->unix_name,
45 conn->connectpath,
46 conn->session_info->unix_token->gid,
47 conn->session_info->unix_info->sanitized_username,
48 conn->session_info->info->domain_name,
49 str);
52 int virusfilter_vfs_next_move(
53 struct vfs_handle_struct *vfs_h,
54 const struct smb_filename *smb_fname_src,
55 const struct smb_filename *smb_fname_dst)
57 int result;
59 result = SMB_VFS_NEXT_RENAMEAT(vfs_h,
60 vfs_h->conn->cwd_fsp,
61 smb_fname_src,
62 vfs_h->conn->cwd_fsp,
63 smb_fname_dst);
64 if (result == 0 || errno != EXDEV) {
65 return result;
69 * For now, do not handle EXDEV as poking around violates
70 * stackability. Return -1, simply refuse access.
72 return -1;
75 /* Line-based socket I/O
76 * ======================================================================
79 struct virusfilter_io_handle *virusfilter_io_new(
80 TALLOC_CTX *mem_ctx,
81 int connect_timeout,
82 int io_timeout)
84 struct virusfilter_io_handle *io_h = talloc_zero(mem_ctx,
85 struct virusfilter_io_handle);
87 if (io_h == NULL) {
88 return NULL;
91 io_h->stream = NULL;
92 io_h->r_len = 0;
94 virusfilter_io_set_connect_timeout(io_h, connect_timeout);
95 virusfilter_io_set_io_timeout(io_h, io_timeout);
96 virusfilter_io_set_writel_eol(io_h, "\x0A", 1);
97 virusfilter_io_set_readl_eol(io_h, "\x0A", 1);
99 return io_h;
102 int virusfilter_io_set_connect_timeout(
103 struct virusfilter_io_handle *io_h,
104 int timeout)
106 int timeout_old = io_h->connect_timeout;
108 /* timeout <= 0 means infinite */
109 io_h->connect_timeout = (timeout > 0) ? timeout : -1;
111 return timeout_old;
114 int virusfilter_io_set_io_timeout(
115 struct virusfilter_io_handle *io_h,
116 int timeout)
118 int timeout_old = io_h->io_timeout;
120 /* timeout <= 0 means infinite */
121 io_h->io_timeout = (timeout > 0) ? timeout : -1;
123 return timeout_old;
126 void virusfilter_io_set_writel_eol(
127 struct virusfilter_io_handle *io_h,
128 const char *eol,
129 int eol_size)
131 if (eol_size < 1 || eol_size > VIRUSFILTER_IO_EOL_SIZE) {
132 return;
135 memcpy(io_h->w_eol, eol, eol_size);
136 io_h->w_eol_size = eol_size;
139 void virusfilter_io_set_readl_eol(
140 struct virusfilter_io_handle *io_h,
141 const char *eol,
142 int eol_size)
144 if (eol_size < 1 || eol_size > VIRUSFILTER_IO_EOL_SIZE) {
145 return;
148 memcpy(io_h->r_eol, eol, eol_size);
149 io_h->r_eol_size = eol_size;
152 bool virusfilter_io_connect_path(
153 struct virusfilter_io_handle *io_h,
154 const char *path)
156 struct sockaddr_un addr;
157 NTSTATUS status;
158 int socket, ret;
159 size_t len;
160 bool ok;
162 ZERO_STRUCT(addr);
163 addr.sun_family = AF_UNIX;
165 len = strlcpy(addr.sun_path, path, sizeof(addr.sun_path));
166 if (len >= sizeof(addr.sun_path)) {
167 io_h->stream = NULL;
168 return false;
171 status = open_socket_out((struct sockaddr_storage *)&addr, 0,
172 io_h->connect_timeout,
173 &socket);
174 if (!NT_STATUS_IS_OK(status)) {
175 io_h->stream = NULL;
176 return false;
179 /* We must not block */
180 ret = set_blocking(socket, false);
181 if (ret == -1) {
182 close(socket);
183 io_h->stream = NULL;
184 return false;
187 ok = smb_set_close_on_exec(socket);
188 if (!ok) {
189 close(socket);
190 io_h->stream = NULL;
191 return false;
194 ret = tstream_bsd_existing_socket(io_h, socket, &io_h->stream);
195 if (ret == -1) {
196 close(socket);
197 DBG_ERR("Could not convert socket to tstream: %s.\n",
198 strerror(errno));
199 io_h->stream = NULL;
200 return false;
203 return true;
206 static void disconnect_done(struct tevent_req *req)
208 uint64_t *perr = tevent_req_callback_data(req, uint64_t);
209 int ret;
210 int err_ret;
212 ret = tstream_disconnect_recv(req, &err_ret);
213 TALLOC_FREE(req);
214 if (ret == -1) {
215 *perr = err_ret;
219 bool virusfilter_io_disconnect(
220 struct virusfilter_io_handle *io_h)
222 struct tevent_req *req;
223 struct tevent_context *ev;
224 uint64_t *perror = NULL;
225 bool ok = true;
226 TALLOC_CTX *frame = talloc_stackframe();
228 if (io_h->stream == NULL) {
229 io_h->r_len = 0;
230 TALLOC_FREE(frame);
231 return VIRUSFILTER_RESULT_OK;
234 ev = tevent_context_init(frame);
235 if (ev == NULL) {
236 DBG_ERR("Failed to setup event context.\n");
237 ok = false;
238 goto fail;
241 /* Error return - must be talloc'ed. */
242 perror = talloc_zero(frame, uint64_t);
243 if (perror == NULL) {
244 goto fail;
247 req = tstream_disconnect_send(io_h, ev, io_h->stream);
249 /* Callback when disconnect is done. */
250 tevent_req_set_callback(req, disconnect_done, perror);
252 /* Set timeout. */
253 ok = tevent_req_set_endtime(req, ev, timeval_current_ofs_msec(
254 io_h->connect_timeout));
255 if (!ok) {
256 DBG_ERR("Can't set endtime\n");
257 goto fail;
260 /* Loop waiting for req to finish. */
261 ok = tevent_req_poll(req, ev);
262 if (!ok) {
263 DBG_ERR("tevent_req_poll failed\n");
264 goto fail;
267 /* Emit debug error if failed. */
268 if (*perror != 0) {
269 DBG_DEBUG("Error %s\n", strerror((int)*perror));
270 goto fail;
273 /* Here we know we disconnected. */
275 io_h->stream = NULL;
276 io_h->r_len = 0;
278 fail:
279 TALLOC_FREE(frame);
280 return ok;
283 static void writev_done(struct tevent_req *req)
285 uint64_t *perr = tevent_req_callback_data(req, uint64_t);
286 int ret;
287 int err_ret;
289 ret = tstream_writev_recv(req, &err_ret);
290 TALLOC_FREE(req);
291 if (ret == -1) {
292 *perr = err_ret;
296 /****************************************************************************
297 Write all data from an iov array, with msec timeout (per write)
298 NB. This can be called with a non-socket fd, don't add dependencies
299 on socket calls.
300 ****************************************************************************/
302 bool write_data_iov_timeout(
303 struct tstream_context *stream,
304 const struct iovec *iov,
305 size_t iovcnt,
306 int ms_timeout)
308 struct tevent_context *ev = NULL;
309 struct tevent_req *req = NULL;
310 uint64_t *perror = NULL;
311 bool ok = false;
312 TALLOC_CTX *frame = talloc_stackframe();
314 ev = tevent_context_init(frame);
315 if (ev == NULL) {
316 DBG_ERR("Failed to setup event context.\n");
317 goto fail;
320 /* Error return - must be talloc'ed. */
321 perror = talloc_zero(frame, uint64_t);
322 if (perror == NULL) {
323 goto fail;
326 /* Send the data. */
327 req = tstream_writev_send(frame, ev, stream, iov, iovcnt);
328 if (req == NULL) {
329 DBG_ERR("Out of memory.\n");
330 goto fail;
333 /* Callback when *all* data sent. */
334 tevent_req_set_callback(req, writev_done, perror);
336 /* Set timeout. */
337 ok = tevent_req_set_endtime(req, ev,
338 timeval_current_ofs_msec(ms_timeout));
339 if (!ok) {
340 DBG_ERR("Can't set endtime\n");
341 goto fail;
344 /* Loop waiting for req to finish. */
345 ok = tevent_req_poll(req, ev);
346 if (!ok) {
347 DBG_ERR("tevent_req_poll failed\n");
348 goto fail;
351 /* Done with req - freed by the callback. */
352 req = NULL;
354 /* Emit debug error if failed. */
355 if (*perror != 0) {
356 DBG_DEBUG("Error %s\n", strerror((int)*perror));
357 goto fail;
360 /* Here we know we correctly wrote all data. */
361 TALLOC_FREE(frame);
362 return true;
364 fail:
365 TALLOC_FREE(frame);
366 return false;
369 bool virusfilter_io_write(
370 struct virusfilter_io_handle *io_h,
371 const char *data,
372 size_t data_size)
374 struct iovec iov;
376 if (data_size == 0) {
377 return VIRUSFILTER_RESULT_OK;
380 iov.iov_base = discard_const_p(void, data);
381 iov.iov_len = data_size;
383 return write_data_iov_timeout(io_h->stream, &iov, 1, io_h->io_timeout);
386 bool virusfilter_io_writel(
387 struct virusfilter_io_handle *io_h,
388 const char *data,
389 size_t data_size)
391 bool ok;
393 ok = virusfilter_io_write(io_h, data, data_size);
394 if (!ok) {
395 return ok;
398 return virusfilter_io_write(io_h, io_h->w_eol, io_h->w_eol_size);
401 bool PRINTF_ATTRIBUTE(2, 3) virusfilter_io_writefl(
402 struct virusfilter_io_handle *io_h,
403 const char *data_fmt, ...)
405 va_list ap;
406 char data[VIRUSFILTER_IO_BUFFER_SIZE + VIRUSFILTER_IO_EOL_SIZE];
407 int data_size;
409 va_start(ap, data_fmt);
410 data_size = vsnprintf(data, VIRUSFILTER_IO_BUFFER_SIZE, data_fmt, ap);
411 va_end(ap);
413 if (unlikely (data_size < 0)) {
414 DBG_ERR("vsnprintf failed: %s\n", strerror(errno));
415 return false;
418 memcpy(data + data_size, io_h->w_eol, io_h->w_eol_size);
419 data_size += io_h->w_eol_size;
421 return virusfilter_io_write(io_h, data, data_size);
424 bool PRINTF_ATTRIBUTE(2, 0) virusfilter_io_vwritefl(
425 struct virusfilter_io_handle *io_h,
426 const char *data_fmt, va_list ap)
428 char data[VIRUSFILTER_IO_BUFFER_SIZE + VIRUSFILTER_IO_EOL_SIZE];
429 int data_size;
431 data_size = vsnprintf(data, VIRUSFILTER_IO_BUFFER_SIZE, data_fmt, ap);
433 if (unlikely (data_size < 0)) {
434 DBG_ERR("vsnprintf failed: %s\n", strerror(errno));
435 return false;
438 memcpy(data + data_size, io_h->w_eol, io_h->w_eol_size);
439 data_size += io_h->w_eol_size;
441 return virusfilter_io_write(io_h, data, data_size);
444 bool virusfilter_io_writev(
445 struct virusfilter_io_handle *io_h, ...)
447 va_list ap;
448 struct iovec iov[VIRUSFILTER_IO_IOV_MAX], *iov_p;
449 int iov_n;
451 va_start(ap, io_h);
452 for (iov_p = iov, iov_n = 0;
453 iov_n < VIRUSFILTER_IO_IOV_MAX;
454 iov_p++, iov_n++)
456 iov_p->iov_base = va_arg(ap, void *);
457 if (iov_p->iov_base == NULL) {
458 break;
460 iov_p->iov_len = va_arg(ap, int);
462 va_end(ap);
464 return write_data_iov_timeout(io_h->stream, iov, iov_n,
465 io_h->io_timeout);
468 bool virusfilter_io_writevl(
469 struct virusfilter_io_handle *io_h, ...)
471 va_list ap;
472 struct iovec iov[VIRUSFILTER_IO_IOV_MAX + 1], *iov_p;
473 int iov_n;
475 va_start(ap, io_h);
476 for (iov_p = iov, iov_n = 0; iov_n < VIRUSFILTER_IO_IOV_MAX;
477 iov_p++, iov_n++)
479 iov_p->iov_base = va_arg(ap, void *);
480 if (iov_p->iov_base == NULL) {
481 break;
483 iov_p->iov_len = va_arg(ap, int);
485 va_end(ap);
487 iov_p->iov_base = io_h->r_eol;
488 iov_p->iov_len = io_h->r_eol_size;
489 iov_n++;
491 return write_data_iov_timeout(io_h->stream, iov, iov_n,
492 io_h->io_timeout);
495 static bool return_existing_line(TALLOC_CTX *ctx,
496 struct virusfilter_io_handle *io_h,
497 char **read_line)
499 size_t read_line_len = 0;
500 char *end_p = NULL;
501 char *eol = NULL;
503 eol = memmem(io_h->r_buffer, io_h->r_len,
504 io_h->r_eol, io_h->r_eol_size);
505 if (eol == NULL) {
506 return false;
508 end_p = eol + io_h->r_eol_size;
510 *eol = '\0';
511 read_line_len = strlen(io_h->r_buffer) + 1;
512 *read_line = talloc_memdup(ctx,
513 io_h->r_buffer,
514 read_line_len);
515 if (*read_line == NULL) {
516 return false;
520 * Copy the remaining buffer over the line
521 * we returned.
523 memmove(io_h->r_buffer,
524 end_p,
525 io_h->r_len - (end_p - io_h->r_buffer));
527 /* And reduce the size left in the buffer. */
528 io_h->r_len -= (end_p - io_h->r_buffer);
529 return true;
532 static void readv_done(struct tevent_req *req)
534 uint64_t *perr = tevent_req_callback_data(req, uint64_t);
535 int ret;
536 int err_ret;
538 ret = tstream_readv_recv(req, &err_ret);
539 TALLOC_FREE(req);
540 if (ret == -1) {
541 *perr = err_ret;
545 bool virusfilter_io_readl(TALLOC_CTX *ctx,
546 struct virusfilter_io_handle *io_h,
547 char **read_line)
549 struct tevent_context *ev = NULL;
550 bool ok = false;
551 uint64_t *perror = NULL;
552 TALLOC_CTX *frame = talloc_stackframe();
554 /* Search for an existing complete line. */
555 ok = return_existing_line(ctx, io_h, read_line);
556 if (ok) {
557 goto finish;
561 * No complete line in the buffer. We must read more
562 * from the server.
564 ev = tevent_context_init(frame);
565 if (ev == NULL) {
566 DBG_ERR("Failed to setup event context.\n");
567 goto finish;
570 /* Error return - must be talloc'ed. */
571 perror = talloc_zero(frame, uint64_t);
572 if (perror == NULL) {
573 goto finish;
576 for (;;) {
577 ssize_t pending = 0;
578 size_t read_size = 0;
579 struct iovec iov;
580 struct tevent_req *req = NULL;
583 * How much can we read ?
585 pending = tstream_pending_bytes(io_h->stream);
586 if (pending < 0) {
587 DBG_ERR("tstream_pending_bytes failed (%s).\n",
588 strerror(errno));
589 goto finish;
592 read_size = pending;
593 /* Must read at least one byte. */
594 read_size = MIN(read_size, 1);
596 /* And max remaining buffer space. */
597 read_size = MAX(read_size,
598 (sizeof(io_h->r_buffer) - io_h->r_len));
600 if (read_size == 0) {
601 /* Buffer is full with no EOL. Error out. */
602 DBG_ERR("Line buffer full.\n");
603 goto finish;
606 iov.iov_base = io_h->r_buffer + io_h->r_len;
607 iov.iov_len = read_size;
609 /* Read the data. */
610 req = tstream_readv_send(frame,
612 io_h->stream,
613 &iov,
615 if (req == NULL) {
616 DBG_ERR("out of memory.\n");
617 goto finish;
620 /* Callback when *all* data read. */
621 tevent_req_set_callback(req, readv_done, perror);
623 /* Set timeout. */
624 ok = tevent_req_set_endtime(req, ev,
625 timeval_current_ofs_msec(io_h->io_timeout));
626 if (!ok) {
627 DBG_ERR("can't set endtime\n");
628 goto finish;
631 /* Loop waiting for req to finish. */
632 ok = tevent_req_poll(req, ev);
633 if (!ok) {
634 DBG_ERR("tevent_req_poll failed\n");
635 goto finish;
638 /* Done with req - freed by the callback. */
639 req = NULL;
642 * Emit debug error if failed.
643 * EPIPE may be success so, don't exit.
645 if (*perror != 0 && *perror != EPIPE) {
646 DBG_DEBUG("Error %s\n", strerror((int)*perror));
647 errno = (int)*perror;
648 goto finish;
652 * We read read_size bytes. Extend the usable
653 * buffer length.
655 io_h->r_len += read_size;
657 /* Paranoia... */
658 SMB_ASSERT(io_h->r_len <= sizeof(io_h->r_buffer));
660 /* Exit if we have a line to return. */
661 ok = return_existing_line(ctx, io_h, read_line);
662 if (ok) {
663 goto finish;
665 /* No eol - keep reading. */
668 finish:
670 TALLOC_FREE(frame);
671 return ok;
674 bool PRINTF_ATTRIBUTE(3, 4) virusfilter_io_writefl_readl(
675 struct virusfilter_io_handle *io_h,
676 char **read_line,
677 const char *fmt, ...)
679 bool ok;
681 if (fmt) {
682 va_list ap;
684 va_start(ap, fmt);
685 ok = virusfilter_io_vwritefl(io_h, fmt, ap);
686 va_end(ap);
688 if (!ok) {
689 return ok;
693 ok = virusfilter_io_readl(talloc_tos(), io_h, read_line);
694 if (!ok) {
695 DBG_ERR("virusfilter_io_readl not OK: %d\n", ok);
696 return false;
698 if (io_h->r_len == 0) { /* EOF */
699 DBG_ERR("virusfilter_io_readl EOF\n");
700 return false;
703 return true;
706 struct virusfilter_cache *virusfilter_cache_new(
707 TALLOC_CTX *ctx,
708 int entry_limit,
709 time_t time_limit)
711 struct virusfilter_cache *cache;
713 if (time_limit == 0) {
714 return NULL;
717 cache = talloc_zero(ctx, struct virusfilter_cache);
718 if (cache == NULL) {
719 DBG_ERR("talloc_zero failed.\n");
720 return NULL;
723 cache->cache = memcache_init(cache->ctx, entry_limit *
724 (sizeof(struct virusfilter_cache_entry)
725 + VIRUSFILTER_CACHE_BUFFER_SIZE));
726 if (cache->cache == NULL) {
727 DBG_ERR("memcache_init failed.\n");
728 return NULL;
730 cache->ctx = ctx;
731 cache->time_limit = time_limit;
733 return cache;
736 bool virusfilter_cache_entry_add(
737 struct virusfilter_cache *cache,
738 const char *directory,
739 const char *fname,
740 virusfilter_result result,
741 char *report)
743 int blob_size = sizeof(struct virusfilter_cache_entry);
744 struct virusfilter_cache_entry *cache_e =
745 talloc_zero_size(NULL, blob_size);
746 int fname_len = 0;
748 if (fname == NULL || directory == NULL) {
749 TALLOC_FREE(report);
750 return false;
753 fname = talloc_asprintf(talloc_tos(), "%s/%s", directory, fname);
755 if (fname == NULL) {
756 TALLOC_FREE(report);
757 return false;
760 fname_len = strlen(fname);
762 if (cache_e == NULL|| cache->time_limit == 0) {
763 TALLOC_FREE(report);
764 return false;
767 cache_e->result = result;
768 if (report != NULL) {
769 cache_e->report = talloc_steal(cache_e, report);
771 if (cache->time_limit > 0) {
772 cache_e->time = time(NULL);
775 memcache_add_talloc(cache->cache,
776 VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC,
777 data_blob_const(fname, fname_len), &cache_e);
779 return true;
782 bool virusfilter_cache_entry_rename(
783 struct virusfilter_cache *cache,
784 const char *directory,
785 char *old_fname,
786 char *new_fname)
788 int old_fname_len = 0;
789 int new_fname_len = 0;
790 struct virusfilter_cache_entry *new_data = NULL;
791 struct virusfilter_cache_entry *old_data = NULL;
793 if (old_fname == NULL || new_fname == NULL || directory == NULL) {
794 return false;
797 old_fname = talloc_asprintf(talloc_tos(), "%s/%s", directory, old_fname);
798 new_fname = talloc_asprintf(talloc_tos(), "%s/%s", directory, new_fname);
800 if (old_fname == NULL || new_fname == NULL) {
801 TALLOC_FREE(old_fname);
802 TALLOC_FREE(new_fname);
803 return false;
806 old_fname_len = strlen(old_fname);
807 new_fname_len = strlen(new_fname);
809 old_data = memcache_lookup_talloc(
810 cache->cache,
811 VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC,
812 data_blob_const(old_fname, old_fname_len));
814 if (old_data == NULL) {
815 return false;
818 new_data = talloc_memdup(cache->ctx, old_data,
819 sizeof(struct virusfilter_cache_entry));
820 if (new_data == NULL) {
821 return false;
823 new_data->report = talloc_strdup(new_data, old_data->report);
825 memcache_add_talloc(cache->cache,
826 VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC,
827 data_blob_const(new_fname, new_fname_len), &new_data);
829 memcache_delete(cache->cache, VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC,
830 data_blob_const(old_fname, old_fname_len));
832 return true;
835 void virusfilter_cache_purge(struct virusfilter_cache *cache)
837 memcache_flush(cache->cache, VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC);
840 struct virusfilter_cache_entry *virusfilter_cache_get(
841 struct virusfilter_cache *cache,
842 const char *directory,
843 const char *fname)
845 int fname_len = 0;
846 struct virusfilter_cache_entry *cache_e = NULL;
847 struct virusfilter_cache_entry *data = NULL;
849 if (fname == NULL || directory == NULL) {
850 return 0;
853 fname = talloc_asprintf(talloc_tos(), "%s/%s", directory, fname);
855 if (fname == NULL) {
856 return 0;
859 fname_len = strlen(fname);
861 data = memcache_lookup_talloc(cache->cache,
862 VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC,
863 data_blob_const(fname, fname_len));
865 if (data == NULL) {
866 return cache_e;
869 if (cache->time_limit > 0) {
870 if (time(NULL) - data->time > cache->time_limit) {
871 DBG_DEBUG("Cache entry is too old: %s\n",
872 fname);
873 virusfilter_cache_remove(cache, directory, fname);
874 return cache_e;
877 cache_e = talloc_memdup(cache->ctx, data,
878 sizeof(struct virusfilter_cache_entry));
879 if (cache_e == NULL) {
880 return NULL;
882 if (data->report != NULL) {
883 cache_e->report = talloc_strdup(cache_e, data->report);
884 } else {
885 cache_e->report = NULL;
888 return cache_e;
891 void virusfilter_cache_remove(struct virusfilter_cache *cache,
892 const char *directory,
893 const char *fname)
895 DBG_DEBUG("Purging cache entry: %s/%s\n", directory, fname);
897 if (fname == NULL || directory == NULL) {
898 return;
901 fname = talloc_asprintf(talloc_tos(), "%s/%s", directory, fname);
903 if (fname == NULL) {
904 return;
907 memcache_delete(cache->cache, VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC,
908 data_blob_const(fname, strlen(fname)));
911 void virusfilter_cache_entry_free(struct virusfilter_cache_entry *cache_e)
913 if (cache_e != NULL) {
914 TALLOC_FREE(cache_e->report);
915 cache_e->report = NULL;
917 TALLOC_FREE(cache_e);
920 /* Shell scripting
921 * ======================================================================
924 int virusfilter_env_set(
925 TALLOC_CTX *mem_ctx,
926 char **env_list,
927 const char *name,
928 const char *value)
930 char *env_new;
931 int ret;
933 env_new = talloc_asprintf(mem_ctx, "%s=%s", name, value);
934 if (env_new == NULL) {
935 DBG_ERR("talloc_asprintf failed\n");
936 return -1;
939 ret = strv_add(mem_ctx, env_list, env_new);
941 TALLOC_FREE(env_new);
943 return ret;
946 /* virusfilter_env version Samba's *_sub_advanced() in substitute.c */
947 int virusfilter_shell_set_conn_env(
948 TALLOC_CTX *mem_ctx,
949 char **env_list,
950 connection_struct *conn)
952 int snum = SNUM(conn);
953 char *server_addr_p;
954 char *client_addr_p;
955 const char *local_machine_name = get_local_machine_name();
956 fstring pidstr;
957 int ret;
959 server_addr_p = tsocket_address_inet_addr_string(
960 conn->sconn->local_address, talloc_tos());
962 if (server_addr_p != NULL) {
963 ret = strncmp("::ffff:", server_addr_p, 7);
964 if (ret == 0) {
965 server_addr_p += 7;
967 virusfilter_env_set(mem_ctx, env_list, "VIRUSFILTER_SERVER_IP",
968 server_addr_p);
970 TALLOC_FREE(server_addr_p);
972 virusfilter_env_set(mem_ctx, env_list, "VIRUSFILTER_SERVER_NAME",
973 myhostname());
974 virusfilter_env_set(mem_ctx, env_list,
975 "VIRUSFILTER_SERVER_NETBIOS_NAME",
976 local_machine_name);
977 slprintf(pidstr,sizeof(pidstr)-1, "%ld", (long)getpid());
978 virusfilter_env_set(mem_ctx, env_list, "VIRUSFILTER_SERVER_PID",
979 pidstr);
981 virusfilter_env_set(mem_ctx, env_list, "VIRUSFILTER_SERVICE_NAME",
982 lp_const_servicename(snum));
983 virusfilter_env_set(mem_ctx, env_list, "VIRUSFILTER_SERVICE_PATH",
984 conn->cwd_fsp->fsp_name->base_name);
986 client_addr_p = tsocket_address_inet_addr_string(
987 conn->sconn->remote_address, talloc_tos());
989 if (client_addr_p != NULL) {
990 ret = strncmp("::ffff:", client_addr_p, 7);
991 if (ret == 0) {
992 client_addr_p += 7;
994 virusfilter_env_set(mem_ctx, env_list, "VIRUSFILTER_CLIENT_IP",
995 client_addr_p);
997 TALLOC_FREE(client_addr_p);
999 virusfilter_env_set(mem_ctx, env_list, "VIRUSFILTER_CLIENT_NAME",
1000 conn->sconn->remote_hostname);
1001 virusfilter_env_set(mem_ctx, env_list,
1002 "VIRUSFILTER_CLIENT_NETBIOS_NAME",
1003 get_remote_machine_name());
1005 virusfilter_env_set(mem_ctx, env_list, "VIRUSFILTER_USER_NAME",
1006 get_current_username());
1007 virusfilter_env_set(mem_ctx, env_list, "VIRUSFILTER_USER_DOMAIN",
1008 get_current_user_info_domain());
1010 return 0;
1013 /* Wrapper to Samba's smbrun() in smbrun.c */
1014 int virusfilter_shell_run(
1015 TALLOC_CTX *mem_ctx,
1016 const char *cmd,
1017 char **env_list,
1018 connection_struct *conn,
1019 bool sanitize)
1021 int ret;
1023 if (conn != NULL) {
1024 ret = virusfilter_shell_set_conn_env(mem_ctx, env_list, conn);
1025 if (ret == -1) {
1026 return -1;
1030 if (sanitize) {
1031 return smbrun(cmd, NULL, strv_to_env(talloc_tos(), *env_list));
1032 } else {
1033 return smbrun_no_sanitize(cmd, NULL, strv_to_env(talloc_tos(),
1034 *env_list));