s3:libsmb: allow store_cldap_reply() to work with a ipv6 response
[samba.git] / source3 / modules / vfs_virusfilter_utils.c
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
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 #include "modules/vfs_virusfilter_common.h"
21 #include "modules/vfs_virusfilter_utils.h"
22
23 struct iovec;
24
25 #include "lib/util/iov_buf.h"
26 #include <tevent.h>
27 #include "lib/tsocket/tsocket.h"
28 #include "source3/lib/substitute.h"
29
30 int virusfilter_debug_class = DBGC_VFS;
31
32 /* ====================================================================== */
33
34 char *virusfilter_string_sub(
35         TALLOC_CTX *mem_ctx,
36         connection_struct *conn,
37         const char *str)
38 {
39         const struct loadparm_substitution *lp_sub =
40                 loadparm_s3_global_substitution();
41
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);
50 }
51
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)
56 {
57         int result;
58
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;
66         }
67
68         /*
69          * For now, do not handle EXDEV as poking around violates
70          * stackability. Return -1, simply refuse access.
71          */
72         return -1;
73 }
74
75 /* Line-based socket I/O
76  * ======================================================================
77  */
78
79 struct virusfilter_io_handle *virusfilter_io_new(
80         TALLOC_CTX *mem_ctx,
81         int connect_timeout,
82         int io_timeout)
83 {
84         struct virusfilter_io_handle *io_h = talloc_zero(mem_ctx,
85                                                 struct virusfilter_io_handle);
86
87         if (io_h == NULL) {
88                 return NULL;
89         }
90
91         io_h->stream = NULL;
92         io_h->r_len = 0;
93
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);
98
99         return io_h;
100 }
101
102 int virusfilter_io_set_connect_timeout(
103         struct virusfilter_io_handle *io_h,
104         int timeout)
105 {
106         int timeout_old = io_h->connect_timeout;
107
108         /* timeout <= 0 means infinite */
109         io_h->connect_timeout = (timeout > 0) ? timeout : -1;
110
111         return timeout_old;
112 }
113
114 int virusfilter_io_set_io_timeout(
115         struct virusfilter_io_handle *io_h,
116         int timeout)
117 {
118         int timeout_old = io_h->io_timeout;
119
120         /* timeout <= 0 means infinite */
121         io_h->io_timeout = (timeout > 0) ? timeout : -1;
122
123         return timeout_old;
124 }
125
126 void virusfilter_io_set_writel_eol(
127         struct virusfilter_io_handle *io_h,
128         const char *eol,
129         int eol_size)
130 {
131         if (eol_size < 1 || eol_size > VIRUSFILTER_IO_EOL_SIZE) {
132                 return;
133         }
134
135         memcpy(io_h->w_eol, eol, eol_size);
136         io_h->w_eol_size = eol_size;
137 }
138
139 void virusfilter_io_set_readl_eol(
140         struct virusfilter_io_handle *io_h,
141         const char *eol,
142         int eol_size)
143 {
144         if (eol_size < 1 || eol_size > VIRUSFILTER_IO_EOL_SIZE) {
145                 return;
146         }
147
148         memcpy(io_h->r_eol, eol, eol_size);
149         io_h->r_eol_size = eol_size;
150 }
151
152 bool virusfilter_io_connect_path(
153         struct virusfilter_io_handle *io_h,
154         const char *path)
155 {
156         struct sockaddr_un addr;
157         NTSTATUS status;
158         int socket, ret;
159         size_t len;
160         bool ok;
161
162         ZERO_STRUCT(addr);
163         addr.sun_family = AF_UNIX;
164
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;
169         }
170
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;
177         }
178
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;
185         }
186
187         ok = smb_set_close_on_exec(socket);
188         if (!ok) {
189                 close(socket);
190                 io_h->stream = NULL;
191                 return false;
192         }
193
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;
201         }
202
203         return true;
204 }
205
206 static void disconnect_done(struct tevent_req *req)
207 {
208         uint64_t *perr = tevent_req_callback_data(req, uint64_t);
209         int ret;
210         int err_ret;
211
212         ret = tstream_disconnect_recv(req, &err_ret);
213         TALLOC_FREE(req);
214         if (ret == -1) {
215                 *perr = err_ret;
216         }
217 }
218
219 bool virusfilter_io_disconnect(
220         struct virusfilter_io_handle *io_h)
221 {
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();
227
228         if (io_h->stream == NULL) {
229                 io_h->r_len = 0;
230                 TALLOC_FREE(frame);
231                 return VIRUSFILTER_RESULT_OK;
232         }
233
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;
239         }
240
241         /* Error return - must be talloc'ed. */
242         perror = talloc_zero(frame, uint64_t);
243         if (perror == NULL) {
244                 goto fail;
245         }
246
247         req = tstream_disconnect_send(io_h, ev, io_h->stream);
248
249         /* Callback when disconnect is done. */
250         tevent_req_set_callback(req, disconnect_done, perror);
251
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;
258         }
259
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;
265         }
266
267         /* Emit debug error if failed. */
268         if (*perror != 0) {
269                 DBG_DEBUG("Error %s\n", strerror((int)*perror));
270                 goto fail;
271         }
272
273         /* Here we know we disconnected. */
274
275         io_h->stream = NULL;
276         io_h->r_len = 0;
277
278         fail:
279                 TALLOC_FREE(frame);
280                 return ok;
281 }
282
283 static void writev_done(struct tevent_req *req)
284 {
285         uint64_t *perr = tevent_req_callback_data(req, uint64_t);
286         int ret;
287         int err_ret;
288
289         ret = tstream_writev_recv(req, &err_ret);
290         TALLOC_FREE(req);
291         if (ret == -1) {
292                 *perr = err_ret;
293         }
294 }
295
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 ****************************************************************************/
301
302 bool write_data_iov_timeout(
303         struct tstream_context *stream,
304         const struct iovec *iov,
305         size_t iovcnt,
306         int ms_timeout)
307 {
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();
313
314         ev = tevent_context_init(frame);
315         if (ev == NULL) {
316                 DBG_ERR("Failed to setup event context.\n");
317                 goto fail;
318         }
319
320         /* Error return - must be talloc'ed. */
321         perror = talloc_zero(frame, uint64_t);
322         if (perror == NULL) {
323                 goto fail;
324         }
325
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;
331         }
332
333         /* Callback when *all* data sent. */
334         tevent_req_set_callback(req, writev_done, perror);
335
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;
342         }
343
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;
349         }
350
351         /* Done with req - freed by the callback. */
352         req = NULL;
353
354         /* Emit debug error if failed. */
355         if (*perror != 0) {
356                 DBG_DEBUG("Error %s\n", strerror((int)*perror));
357                 goto fail;
358         }
359
360         /* Here we know we correctly wrote all data. */
361         TALLOC_FREE(frame);
362         return true;
363
364   fail:
365         TALLOC_FREE(frame);
366         return false;
367 }
368
369 bool virusfilter_io_write(
370         struct virusfilter_io_handle *io_h,
371         const char *data,
372         size_t data_size)
373 {
374         struct iovec iov;
375
376         if (data_size == 0) {
377                 return VIRUSFILTER_RESULT_OK;
378         }
379
380         iov.iov_base = discard_const_p(void, data);
381         iov.iov_len = data_size;
382
383         return write_data_iov_timeout(io_h->stream, &iov, 1, io_h->io_timeout);
384 }
385
386 bool virusfilter_io_writel(
387         struct virusfilter_io_handle *io_h,
388         const char *data,
389         size_t data_size)
390 {
391         bool ok;
392
393         ok = virusfilter_io_write(io_h, data, data_size);
394         if (!ok) {
395                 return ok;
396         }
397
398         return virusfilter_io_write(io_h, io_h->w_eol, io_h->w_eol_size);
399 }
400
401 bool PRINTF_ATTRIBUTE(2, 3) virusfilter_io_writefl(
402         struct virusfilter_io_handle *io_h,
403         const char *data_fmt, ...)
404 {
405         va_list ap;
406         char data[VIRUSFILTER_IO_BUFFER_SIZE + VIRUSFILTER_IO_EOL_SIZE];
407         int data_size;
408
409         va_start(ap, data_fmt);
410         data_size = vsnprintf(data, VIRUSFILTER_IO_BUFFER_SIZE, data_fmt, ap);
411         va_end(ap);
412
413         if (unlikely (data_size < 0)) {
414                 DBG_ERR("vsnprintf failed: %s\n", strerror(errno));
415                 return false;
416         }
417
418         memcpy(data + data_size, io_h->w_eol, io_h->w_eol_size);
419         data_size += io_h->w_eol_size;
420
421         return virusfilter_io_write(io_h, data, data_size);
422 }
423
424 bool PRINTF_ATTRIBUTE(2, 0) virusfilter_io_vwritefl(
425         struct virusfilter_io_handle *io_h,
426         const char *data_fmt, va_list ap)
427 {
428         char data[VIRUSFILTER_IO_BUFFER_SIZE + VIRUSFILTER_IO_EOL_SIZE];
429         int data_size;
430
431         data_size = vsnprintf(data, VIRUSFILTER_IO_BUFFER_SIZE, data_fmt, ap);
432
433         if (unlikely (data_size < 0)) {
434                 DBG_ERR("vsnprintf failed: %s\n", strerror(errno));
435                 return false;
436         }
437
438         memcpy(data + data_size, io_h->w_eol, io_h->w_eol_size);
439         data_size += io_h->w_eol_size;
440
441         return virusfilter_io_write(io_h, data, data_size);
442 }
443
444 bool virusfilter_io_writev(
445         struct virusfilter_io_handle *io_h, ...)
446 {
447         va_list ap;
448         struct iovec iov[VIRUSFILTER_IO_IOV_MAX], *iov_p;
449         int iov_n;
450
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++)
455         {
456                 iov_p->iov_base = va_arg(ap, void *);
457                 if (iov_p->iov_base == NULL) {
458                         break;
459                 }
460                 iov_p->iov_len = va_arg(ap, int);
461         }
462         va_end(ap);
463
464         return write_data_iov_timeout(io_h->stream, iov, iov_n,
465                 io_h->io_timeout);
466 }
467
468 bool virusfilter_io_writevl(
469         struct virusfilter_io_handle *io_h, ...)
470 {
471         va_list ap;
472         struct iovec iov[VIRUSFILTER_IO_IOV_MAX + 1], *iov_p;
473         int iov_n;
474
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++)
478         {
479                 iov_p->iov_base = va_arg(ap, void *);
480                 if (iov_p->iov_base == NULL) {
481                         break;
482                 }
483                 iov_p->iov_len = va_arg(ap, int);
484         }
485         va_end(ap);
486
487         iov_p->iov_base = io_h->r_eol;
488         iov_p->iov_len = io_h->r_eol_size;
489         iov_n++;
490
491         return write_data_iov_timeout(io_h->stream, iov, iov_n,
492                 io_h->io_timeout);
493 }
494
495 static bool return_existing_line(TALLOC_CTX *ctx,
496                                 struct virusfilter_io_handle *io_h,
497                                 char **read_line)
498 {
499         size_t read_line_len = 0;
500         char *end_p = NULL;
501         char *eol = NULL;
502
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;
507         }
508         end_p = eol + io_h->r_eol_size;
509
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;
517         }
518
519         /*
520          * Copy the remaining buffer over the line
521          * we returned.
522          */
523         memmove(io_h->r_buffer,
524                 end_p,
525                 io_h->r_len - (end_p - io_h->r_buffer));
526
527         /* And reduce the size left in the buffer. */
528         io_h->r_len -= (end_p - io_h->r_buffer);
529         return true;
530 }
531
532 static void readv_done(struct tevent_req *req)
533 {
534         uint64_t *perr = tevent_req_callback_data(req, uint64_t);
535         int ret;
536         int err_ret;
537
538         ret = tstream_readv_recv(req, &err_ret);
539         TALLOC_FREE(req);
540         if (ret == -1) {
541                 *perr = err_ret;
542         }
543 }
544
545 bool virusfilter_io_readl(TALLOC_CTX *ctx,
546                         struct virusfilter_io_handle *io_h,
547                         char **read_line)
548 {
549         struct tevent_context *ev = NULL;
550         bool ok = false;
551         uint64_t *perror = NULL;
552         TALLOC_CTX *frame = talloc_stackframe();
553
554         /* Search for an existing complete line. */
555         ok = return_existing_line(ctx, io_h, read_line);
556         if (ok) {
557                 goto finish;
558         }
559
560         /*
561          * No complete line in the buffer. We must read more
562          * from the server.
563          */
564         ev = tevent_context_init(frame);
565         if (ev == NULL) {
566                 DBG_ERR("Failed to setup event context.\n");
567                 goto finish;
568         }
569
570         /* Error return - must be talloc'ed. */
571         perror = talloc_zero(frame, uint64_t);
572         if (perror == NULL) {
573                 goto finish;
574         }
575
576         for (;;) {
577                 ssize_t pending = 0;
578                 size_t read_size = 0;
579                 struct iovec iov;
580                 struct tevent_req *req = NULL;
581
582                 /*
583                  * How much can we read ?
584                  */
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;
590                 }
591
592                 read_size = pending;
593                 /* Must read at least one byte. */
594                 read_size = MIN(read_size, 1);
595
596                 /* And max remaining buffer space. */
597                 read_size = MAX(read_size,
598                                 (sizeof(io_h->r_buffer) - io_h->r_len));
599
600                 if (read_size == 0) {
601                         /* Buffer is full with no EOL. Error out. */
602                         DBG_ERR("Line buffer full.\n");
603                         goto finish;
604                 }
605
606                 iov.iov_base = io_h->r_buffer + io_h->r_len;
607                 iov.iov_len = read_size;
608
609                 /* Read the data. */
610                 req = tstream_readv_send(frame,
611                                         ev,
612                                         io_h->stream,
613                                         &iov,
614                                         1);
615                 if (req == NULL) {
616                         DBG_ERR("out of memory.\n");
617                         goto finish;
618                 }
619
620                 /* Callback when *all* data read. */
621                 tevent_req_set_callback(req, readv_done, perror);
622
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;
629                 }
630
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;
636                 }
637
638                 /* Done with req - freed by the callback. */
639                 req = NULL;
640
641                 /*
642                  * Emit debug error if failed.
643                  * EPIPE may be success so, don't exit.
644                  */
645                 if (*perror != 0 && *perror != EPIPE) {
646                         DBG_DEBUG("Error %s\n", strerror((int)*perror));
647                         errno = (int)*perror;
648                         goto finish;
649                 }
650
651                 /*
652                  * We read read_size bytes. Extend the usable
653                  * buffer length.
654                  */
655                 io_h->r_len += read_size;
656
657                 /* Paranoia... */
658                 SMB_ASSERT(io_h->r_len <= sizeof(io_h->r_buffer));
659
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;
664                 }
665                 /* No eol - keep reading. */
666         }
667
668   finish:
669
670         TALLOC_FREE(frame);
671         return ok;
672 }
673
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, ...)
678 {
679         bool ok;
680
681         if (fmt) {
682                 va_list ap;
683
684                 va_start(ap, fmt);
685                 ok = virusfilter_io_vwritefl(io_h, fmt, ap);
686                 va_end(ap);
687
688                 if (!ok) {
689                         return ok;
690                 }
691         }
692
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;
697         }
698         if (io_h->r_len == 0) { /* EOF */
699                 DBG_ERR("virusfilter_io_readl EOF\n");
700                 return false;
701         }
702
703         return true;
704 }
705
706 struct virusfilter_cache *virusfilter_cache_new(
707         TALLOC_CTX *ctx,
708         int entry_limit,
709         time_t time_limit)
710 {
711         struct virusfilter_cache *cache;
712
713         if (time_limit == 0) {
714                 return NULL;
715         }
716
717         cache = talloc_zero(ctx, struct virusfilter_cache);
718         if (cache == NULL) {
719                 DBG_ERR("talloc_zero failed.\n");
720                 return NULL;
721         }
722
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;
729         }
730         cache->ctx = ctx;
731         cache->time_limit = time_limit;
732
733         return cache;
734 }
735
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)
742 {
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;
747
748         if (fname == NULL || directory == NULL) {
749                 TALLOC_FREE(report);
750                 return false;
751         }
752
753         fname = talloc_asprintf(talloc_tos(), "%s/%s", directory, fname);
754
755         if (fname == NULL) {
756                 TALLOC_FREE(report);
757                 return false;
758         }
759
760         fname_len = strlen(fname);
761
762         if (cache_e == NULL|| cache->time_limit == 0) {
763                 TALLOC_FREE(report);
764                 return false;
765         }
766
767         cache_e->result = result;
768         if (report != NULL) {
769                 cache_e->report = talloc_steal(cache_e, report);
770         }
771         if (cache->time_limit > 0) {
772                 cache_e->time = time(NULL);
773         }
774
775         memcache_add_talloc(cache->cache,
776                             VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC,
777                             data_blob_const(fname, fname_len), &cache_e);
778
779         return true;
780 }
781
782 bool virusfilter_cache_entry_rename(
783         struct virusfilter_cache *cache,
784         const char *directory,
785         char *old_fname,
786         char *new_fname)
787 {
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;
792
793         if (old_fname == NULL || new_fname == NULL || directory == NULL) {
794                 return false;
795         }
796
797         old_fname = talloc_asprintf(talloc_tos(), "%s/%s", directory, old_fname);
798         new_fname = talloc_asprintf(talloc_tos(), "%s/%s", directory, new_fname);
799
800         if (old_fname == NULL || new_fname == NULL) {
801                 TALLOC_FREE(old_fname);
802                 TALLOC_FREE(new_fname);
803                 return false;
804         }
805
806         old_fname_len = strlen(old_fname);
807         new_fname_len = strlen(new_fname);
808
809         old_data = memcache_lookup_talloc(
810                                 cache->cache,
811                                 VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC,
812                                 data_blob_const(old_fname, old_fname_len));
813
814         if (old_data == NULL) {
815                 return false;
816         }
817
818         new_data = talloc_memdup(cache->ctx, old_data,
819                                  sizeof(struct virusfilter_cache_entry));
820         if (new_data == NULL) {
821                 return false;
822         }
823         new_data->report = talloc_strdup(new_data, old_data->report);
824
825         memcache_add_talloc(cache->cache,
826                         VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC,
827                         data_blob_const(new_fname, new_fname_len), &new_data);
828
829         memcache_delete(cache->cache, VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC,
830                         data_blob_const(old_fname, old_fname_len));
831
832         return true;
833 }
834
835 void virusfilter_cache_purge(struct virusfilter_cache *cache)
836 {
837         memcache_flush(cache->cache, VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC);
838 }
839
840 struct virusfilter_cache_entry *virusfilter_cache_get(
841         struct virusfilter_cache *cache,
842         const char *directory,
843         const char *fname)
844 {
845         int fname_len = 0;
846         struct virusfilter_cache_entry *cache_e = NULL;
847         struct virusfilter_cache_entry *data = NULL;
848
849         if (fname == NULL || directory == NULL) {
850                 return 0;
851         }
852
853         fname = talloc_asprintf(talloc_tos(), "%s/%s", directory, fname);
854
855         if (fname == NULL) {
856                 return 0;
857         }
858
859         fname_len = strlen(fname);
860
861         data = memcache_lookup_talloc(cache->cache,
862                                       VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC,
863                                       data_blob_const(fname, fname_len));
864
865         if (data == NULL) {
866                 return cache_e;
867         }
868
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;
875                 }
876         }
877         cache_e = talloc_memdup(cache->ctx, data,
878                                sizeof(struct virusfilter_cache_entry));
879         if (cache_e == NULL) {
880                 return NULL;
881         }
882         if (data->report != NULL) {
883                 cache_e->report = talloc_strdup(cache_e, data->report);
884         } else {
885                 cache_e->report = NULL;
886         }
887
888         return cache_e;
889 }
890
891 void virusfilter_cache_remove(struct virusfilter_cache *cache,
892         const char *directory,
893         const char *fname)
894 {
895         DBG_DEBUG("Purging cache entry: %s/%s\n", directory, fname);
896
897         if (fname == NULL || directory == NULL) {
898                 return;
899         }
900
901         fname = talloc_asprintf(talloc_tos(), "%s/%s", directory, fname);
902
903         if (fname == NULL) {
904                 return;
905         }
906
907         memcache_delete(cache->cache, VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC,
908                         data_blob_const(fname, strlen(fname)));
909 }
910
911 void virusfilter_cache_entry_free(struct virusfilter_cache_entry *cache_e)
912 {
913         if (cache_e != NULL) {
914                 TALLOC_FREE(cache_e->report);
915                 cache_e->report = NULL;
916         }
917         TALLOC_FREE(cache_e);
918 }
919
920 /* Shell scripting
921  * ======================================================================
922  */
923
924 int virusfilter_env_set(
925         TALLOC_CTX *mem_ctx,
926         char **env_list,
927         const char *name,
928         const char *value)
929 {
930         char *env_new;
931         int ret;
932
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;
937         }
938
939         ret = strv_add(mem_ctx, env_list, env_new);
940
941         TALLOC_FREE(env_new);
942
943         return ret;
944 }
945
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)
951 {
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;
958
959         server_addr_p = tsocket_address_inet_addr_string(
960                                 conn->sconn->local_address, talloc_tos());
961
962         if (server_addr_p != NULL) {
963                 ret = strncmp("::ffff:", server_addr_p, 7);
964                 if (ret == 0) {
965                         server_addr_p += 7;
966                 }
967                 virusfilter_env_set(mem_ctx, env_list, "VIRUSFILTER_SERVER_IP",
968                                     server_addr_p);
969         }
970         TALLOC_FREE(server_addr_p);
971
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);
980
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);
985
986         client_addr_p = tsocket_address_inet_addr_string(
987                                 conn->sconn->remote_address, talloc_tos());
988
989         if (client_addr_p != NULL) {
990                 ret = strncmp("::ffff:", client_addr_p, 7);
991                 if (ret == 0) {
992                         client_addr_p += 7;
993                 }
994                 virusfilter_env_set(mem_ctx, env_list, "VIRUSFILTER_CLIENT_IP",
995                                     client_addr_p);
996         }
997         TALLOC_FREE(client_addr_p);
998
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());
1004
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());
1009
1010         return 0;
1011 }
1012
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)
1020 {
1021         int ret;
1022
1023         if (conn != NULL) {
1024                 ret = virusfilter_shell_set_conn_env(mem_ctx, env_list, conn);
1025                 if (ret == -1) {
1026                         return -1;
1027                 }
1028         }
1029
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));
1035         }
1036 }