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"
25 #include "lib/util/iov_buf.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(
36 connection_struct
*conn
,
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
,
46 conn
->session_info
->unix_token
->gid
,
47 conn
->session_info
->unix_info
->sanitized_username
,
48 conn
->session_info
->info
->domain_name
,
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
)
59 result
= SMB_VFS_NEXT_RENAMEAT(vfs_h
,
64 if (result
== 0 || errno
!= EXDEV
) {
69 * For now, do not handle EXDEV as poking around violates
70 * stackability. Return -1, simply refuse access.
75 /* Line-based socket I/O
76 * ======================================================================
79 struct virusfilter_io_handle
*virusfilter_io_new(
84 struct virusfilter_io_handle
*io_h
= talloc_zero(mem_ctx
,
85 struct virusfilter_io_handle
);
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);
102 int virusfilter_io_set_connect_timeout(
103 struct virusfilter_io_handle
*io_h
,
106 int timeout_old
= io_h
->connect_timeout
;
108 /* timeout <= 0 means infinite */
109 io_h
->connect_timeout
= (timeout
> 0) ? timeout
: -1;
114 int virusfilter_io_set_io_timeout(
115 struct virusfilter_io_handle
*io_h
,
118 int timeout_old
= io_h
->io_timeout
;
120 /* timeout <= 0 means infinite */
121 io_h
->io_timeout
= (timeout
> 0) ? timeout
: -1;
126 void virusfilter_io_set_writel_eol(
127 struct virusfilter_io_handle
*io_h
,
131 if (eol_size
< 1 || eol_size
> VIRUSFILTER_IO_EOL_SIZE
) {
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
,
144 if (eol_size
< 1 || eol_size
> VIRUSFILTER_IO_EOL_SIZE
) {
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
,
156 struct sockaddr_un 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
)) {
171 status
= open_socket_out((struct sockaddr_storage
*)&addr
, 0,
172 io_h
->connect_timeout
,
174 if (!NT_STATUS_IS_OK(status
)) {
179 /* We must not block */
180 ret
= set_blocking(socket
, false);
187 ok
= smb_set_close_on_exec(socket
);
194 ret
= tstream_bsd_existing_socket(io_h
, socket
, &io_h
->stream
);
197 DBG_ERR("Could not convert socket to tstream: %s.\n",
206 static void disconnect_done(struct tevent_req
*req
)
208 uint64_t *perr
= tevent_req_callback_data(req
, uint64_t);
212 ret
= tstream_disconnect_recv(req
, &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
;
226 TALLOC_CTX
*frame
= talloc_stackframe();
228 if (io_h
->stream
== NULL
) {
231 return VIRUSFILTER_RESULT_OK
;
234 ev
= tevent_context_init(frame
);
236 DBG_ERR("Failed to setup event context.\n");
241 /* Error return - must be talloc'ed. */
242 perror
= talloc_zero(frame
, uint64_t);
243 if (perror
== NULL
) {
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
);
253 ok
= tevent_req_set_endtime(req
, ev
, timeval_current_ofs_msec(
254 io_h
->connect_timeout
));
256 DBG_ERR("Can't set endtime\n");
260 /* Loop waiting for req to finish. */
261 ok
= tevent_req_poll(req
, ev
);
263 DBG_ERR("tevent_req_poll failed\n");
267 /* Emit debug error if failed. */
269 DBG_DEBUG("Error %s\n", strerror((int)*perror
));
273 /* Here we know we disconnected. */
283 static void writev_done(struct tevent_req
*req
)
285 uint64_t *perr
= tevent_req_callback_data(req
, uint64_t);
289 ret
= tstream_writev_recv(req
, &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
300 ****************************************************************************/
302 bool write_data_iov_timeout(
303 struct tstream_context
*stream
,
304 const struct iovec
*iov
,
308 struct tevent_context
*ev
= NULL
;
309 struct tevent_req
*req
= NULL
;
310 uint64_t *perror
= NULL
;
312 TALLOC_CTX
*frame
= talloc_stackframe();
314 ev
= tevent_context_init(frame
);
316 DBG_ERR("Failed to setup event context.\n");
320 /* Error return - must be talloc'ed. */
321 perror
= talloc_zero(frame
, uint64_t);
322 if (perror
== NULL
) {
327 req
= tstream_writev_send(frame
, ev
, stream
, iov
, iovcnt
);
329 DBG_ERR("Out of memory.\n");
333 /* Callback when *all* data sent. */
334 tevent_req_set_callback(req
, writev_done
, perror
);
337 ok
= tevent_req_set_endtime(req
, ev
,
338 timeval_current_ofs_msec(ms_timeout
));
340 DBG_ERR("Can't set endtime\n");
344 /* Loop waiting for req to finish. */
345 ok
= tevent_req_poll(req
, ev
);
347 DBG_ERR("tevent_req_poll failed\n");
351 /* Done with req - freed by the callback. */
354 /* Emit debug error if failed. */
356 DBG_DEBUG("Error %s\n", strerror((int)*perror
));
360 /* Here we know we correctly wrote all data. */
369 bool virusfilter_io_write(
370 struct virusfilter_io_handle
*io_h
,
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
,
393 ok
= virusfilter_io_write(io_h
, data
, data_size
);
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
, ...)
406 char data
[VIRUSFILTER_IO_BUFFER_SIZE
+ VIRUSFILTER_IO_EOL_SIZE
];
409 va_start(ap
, data_fmt
);
410 data_size
= vsnprintf(data
, VIRUSFILTER_IO_BUFFER_SIZE
, data_fmt
, ap
);
413 if (unlikely (data_size
< 0)) {
414 DBG_ERR("vsnprintf failed: %s\n", strerror(errno
));
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
];
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
));
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
, ...)
448 struct iovec iov
[VIRUSFILTER_IO_IOV_MAX
], *iov_p
;
452 for (iov_p
= iov
, iov_n
= 0;
453 iov_n
< VIRUSFILTER_IO_IOV_MAX
;
456 iov_p
->iov_base
= va_arg(ap
, void *);
457 if (iov_p
->iov_base
== NULL
) {
460 iov_p
->iov_len
= va_arg(ap
, int);
464 return write_data_iov_timeout(io_h
->stream
, iov
, iov_n
,
468 bool virusfilter_io_writevl(
469 struct virusfilter_io_handle
*io_h
, ...)
472 struct iovec iov
[VIRUSFILTER_IO_IOV_MAX
+ 1], *iov_p
;
476 for (iov_p
= iov
, iov_n
= 0; iov_n
< VIRUSFILTER_IO_IOV_MAX
;
479 iov_p
->iov_base
= va_arg(ap
, void *);
480 if (iov_p
->iov_base
== NULL
) {
483 iov_p
->iov_len
= va_arg(ap
, int);
487 iov_p
->iov_base
= io_h
->r_eol
;
488 iov_p
->iov_len
= io_h
->r_eol_size
;
491 return write_data_iov_timeout(io_h
->stream
, iov
, iov_n
,
495 static bool return_existing_line(TALLOC_CTX
*ctx
,
496 struct virusfilter_io_handle
*io_h
,
499 size_t read_line_len
= 0;
503 eol
= memmem(io_h
->r_buffer
, io_h
->r_len
,
504 io_h
->r_eol
, io_h
->r_eol_size
);
508 end_p
= eol
+ io_h
->r_eol_size
;
511 read_line_len
= strlen(io_h
->r_buffer
) + 1;
512 *read_line
= talloc_memdup(ctx
,
515 if (*read_line
== NULL
) {
520 * Copy the remaining buffer over the line
523 memmove(io_h
->r_buffer
,
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
);
532 static void readv_done(struct tevent_req
*req
)
534 uint64_t *perr
= tevent_req_callback_data(req
, uint64_t);
538 ret
= tstream_readv_recv(req
, &err_ret
);
545 bool virusfilter_io_readl(TALLOC_CTX
*ctx
,
546 struct virusfilter_io_handle
*io_h
,
549 struct tevent_context
*ev
= NULL
;
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
);
561 * No complete line in the buffer. We must read more
564 ev
= tevent_context_init(frame
);
566 DBG_ERR("Failed to setup event context.\n");
570 /* Error return - must be talloc'ed. */
571 perror
= talloc_zero(frame
, uint64_t);
572 if (perror
== NULL
) {
578 size_t read_size
= 0;
580 struct tevent_req
*req
= NULL
;
583 * How much can we read ?
585 pending
= tstream_pending_bytes(io_h
->stream
);
587 DBG_ERR("tstream_pending_bytes failed (%s).\n",
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");
606 iov
.iov_base
= io_h
->r_buffer
+ io_h
->r_len
;
607 iov
.iov_len
= read_size
;
610 req
= tstream_readv_send(frame
,
616 DBG_ERR("out of memory.\n");
620 /* Callback when *all* data read. */
621 tevent_req_set_callback(req
, readv_done
, perror
);
624 ok
= tevent_req_set_endtime(req
, ev
,
625 timeval_current_ofs_msec(io_h
->io_timeout
));
627 DBG_ERR("can't set endtime\n");
631 /* Loop waiting for req to finish. */
632 ok
= tevent_req_poll(req
, ev
);
634 DBG_ERR("tevent_req_poll failed\n");
638 /* Done with req - freed by the callback. */
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
;
652 * We read read_size bytes. Extend the usable
655 io_h
->r_len
+= read_size
;
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
);
665 /* No eol - keep reading. */
674 bool PRINTF_ATTRIBUTE(3, 4) virusfilter_io_writefl_readl(
675 struct virusfilter_io_handle
*io_h
,
677 const char *fmt
, ...)
685 ok
= virusfilter_io_vwritefl(io_h
, fmt
, ap
);
693 ok
= virusfilter_io_readl(talloc_tos(), io_h
, read_line
);
695 DBG_ERR("virusfilter_io_readl not OK: %d\n", ok
);
698 if (io_h
->r_len
== 0) { /* EOF */
699 DBG_ERR("virusfilter_io_readl EOF\n");
706 struct virusfilter_cache
*virusfilter_cache_new(
711 struct virusfilter_cache
*cache
;
713 if (time_limit
== 0) {
717 cache
= talloc_zero(ctx
, struct virusfilter_cache
);
719 DBG_ERR("talloc_zero failed.\n");
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");
731 cache
->time_limit
= time_limit
;
736 bool virusfilter_cache_entry_add(
737 struct virusfilter_cache
*cache
,
738 const char *directory
,
740 virusfilter_result result
,
743 int blob_size
= sizeof(struct virusfilter_cache_entry
);
744 struct virusfilter_cache_entry
*cache_e
=
745 talloc_zero_size(NULL
, blob_size
);
748 if (fname
== NULL
|| directory
== NULL
) {
753 fname
= talloc_asprintf(talloc_tos(), "%s/%s", directory
, fname
);
760 fname_len
= strlen(fname
);
762 if (cache_e
== NULL
|| cache
->time_limit
== 0) {
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
);
782 bool virusfilter_cache_entry_rename(
783 struct virusfilter_cache
*cache
,
784 const char *directory
,
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
) {
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
);
806 old_fname_len
= strlen(old_fname
);
807 new_fname_len
= strlen(new_fname
);
809 old_data
= memcache_lookup_talloc(
811 VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC
,
812 data_blob_const(old_fname
, old_fname_len
));
814 if (old_data
== NULL
) {
818 new_data
= talloc_memdup(cache
->ctx
, old_data
,
819 sizeof(struct virusfilter_cache_entry
));
820 if (new_data
== NULL
) {
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
));
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
,
846 struct virusfilter_cache_entry
*cache_e
= NULL
;
847 struct virusfilter_cache_entry
*data
= NULL
;
849 if (fname
== NULL
|| directory
== NULL
) {
853 fname
= talloc_asprintf(talloc_tos(), "%s/%s", directory
, fname
);
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
));
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",
873 virusfilter_cache_remove(cache
, directory
, fname
);
877 cache_e
= talloc_memdup(cache
->ctx
, data
,
878 sizeof(struct virusfilter_cache_entry
));
879 if (cache_e
== NULL
) {
882 if (data
->report
!= NULL
) {
883 cache_e
->report
= talloc_strdup(cache_e
, data
->report
);
885 cache_e
->report
= NULL
;
891 void virusfilter_cache_remove(struct virusfilter_cache
*cache
,
892 const char *directory
,
895 DBG_DEBUG("Purging cache entry: %s/%s\n", directory
, fname
);
897 if (fname
== NULL
|| directory
== NULL
) {
901 fname
= talloc_asprintf(talloc_tos(), "%s/%s", directory
, fname
);
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
);
921 * ======================================================================
924 int virusfilter_env_set(
933 env_new
= talloc_asprintf(mem_ctx
, "%s=%s", name
, value
);
934 if (env_new
== NULL
) {
935 DBG_ERR("talloc_asprintf failed\n");
939 ret
= strv_add(mem_ctx
, env_list
, env_new
);
941 TALLOC_FREE(env_new
);
946 /* virusfilter_env version Samba's *_sub_advanced() in substitute.c */
947 int virusfilter_shell_set_conn_env(
950 connection_struct
*conn
)
952 int snum
= SNUM(conn
);
955 const char *local_machine_name
= get_local_machine_name();
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);
967 virusfilter_env_set(mem_ctx
, env_list
, "VIRUSFILTER_SERVER_IP",
970 TALLOC_FREE(server_addr_p
);
972 virusfilter_env_set(mem_ctx
, env_list
, "VIRUSFILTER_SERVER_NAME",
974 virusfilter_env_set(mem_ctx
, env_list
,
975 "VIRUSFILTER_SERVER_NETBIOS_NAME",
977 slprintf(pidstr
,sizeof(pidstr
)-1, "%ld", (long)getpid());
978 virusfilter_env_set(mem_ctx
, env_list
, "VIRUSFILTER_SERVER_PID",
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);
994 virusfilter_env_set(mem_ctx
, env_list
, "VIRUSFILTER_CLIENT_IP",
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());
1013 /* Wrapper to Samba's smbrun() in smbrun.c */
1014 int virusfilter_shell_run(
1015 TALLOC_CTX
*mem_ctx
,
1018 connection_struct
*conn
,
1024 ret
= virusfilter_shell_set_conn_env(mem_ctx
, env_list
, conn
);
1031 return smbrun(cmd
, NULL
, strv_to_env(talloc_tos(), *env_list
));
1033 return smbrun_no_sanitize(cmd
, NULL
, strv_to_env(talloc_tos(),