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"
29 int virusfilter_debug_class
= DBGC_VFS
;
31 /* ====================================================================== */
33 char *virusfilter_string_sub(
35 connection_struct
*conn
,
38 return talloc_sub_advanced(mem_ctx
,
39 lp_servicename(mem_ctx
, SNUM(conn
)),
40 conn
->session_info
->unix_info
->unix_name
,
42 conn
->session_info
->unix_token
->gid
,
43 conn
->session_info
->unix_info
->sanitized_username
,
44 conn
->session_info
->info
->domain_name
,
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
)
55 result
= SMB_VFS_NEXT_RENAME(vfs_h
, smb_fname_src
, smb_fname_dst
);
56 if (result
== 0 || errno
!= EXDEV
) {
61 * For now, do not handle EXDEV as poking around violates
62 * stackability. Return -1, simply refuse access.
67 /* Line-based socket I/O
68 * ======================================================================
71 struct virusfilter_io_handle
*virusfilter_io_new(
76 struct virusfilter_io_handle
*io_h
= talloc_zero(mem_ctx
,
77 struct virusfilter_io_handle
);
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);
94 int virusfilter_io_set_connect_timeout(
95 struct virusfilter_io_handle
*io_h
,
98 int timeout_old
= io_h
->connect_timeout
;
100 /* timeout <= 0 means infinite */
101 io_h
->connect_timeout
= (timeout
> 0) ? timeout
: -1;
106 int virusfilter_io_set_io_timeout(
107 struct virusfilter_io_handle
*io_h
,
110 int timeout_old
= io_h
->io_timeout
;
112 /* timeout <= 0 means infinite */
113 io_h
->io_timeout
= (timeout
> 0) ? timeout
: -1;
118 void virusfilter_io_set_writel_eol(
119 struct virusfilter_io_handle
*io_h
,
123 if (eol_size
< 1 || eol_size
> VIRUSFILTER_IO_EOL_SIZE
) {
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
,
136 if (eol_size
< 1 || eol_size
> VIRUSFILTER_IO_EOL_SIZE
) {
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
,
148 struct sockaddr_un addr
;
150 int socket
, bes_result
, flags
, ret
;
154 addr
.sun_family
= AF_UNIX
;
156 len
= strlcpy(addr
.sun_path
, path
, sizeof(addr
.sun_path
));
157 if (len
>= sizeof(addr
.sun_path
)) {
162 status
= open_socket_out((struct sockaddr_storage
*)&addr
, 0,
163 io_h
->connect_timeout
,
165 if (!NT_STATUS_IS_OK(status
)) {
170 /* We must not block */
171 flags
= fcntl(socket
, F_GETFL
);
173 /* Handle error by ignoring */;
175 DBG_WARNING("Could not get flags on socket (%s).\n",
178 flags
|= SOCK_NONBLOCK
;
179 ret
= fcntl(socket
, F_SETFL
, flags
);
181 /* Handle error by ignoring for now */
182 DBG_WARNING("Could not set flags on socket: %s.\n",
186 bes_result
= tstream_bsd_existing_socket(io_h
, socket
, &io_h
->stream
);
187 if (bes_result
< 0) {
188 DBG_ERR("Could not convert socket to tstream: %s.\n",
197 static void disconnect_done(struct tevent_req
*req
)
199 uint64_t *perr
= tevent_req_callback_data(req
, uint64_t);
203 ret
= tstream_disconnect_recv(req
, &err_ret
);
210 bool virusfilter_io_disconnect(
211 struct virusfilter_io_handle
*io_h
)
213 struct tevent_req
*req
;
214 struct tevent_context
*ev
;
215 uint64_t *perror
= NULL
;
217 TALLOC_CTX
*frame
= talloc_stackframe();
219 if (io_h
->stream
== NULL
) {
222 return VIRUSFILTER_RESULT_OK
;
225 ev
= tevent_context_init(frame
);
227 DBG_ERR("Failed to setup event context.\n");
232 /* Error return - must be talloc'ed. */
233 perror
= talloc_zero(frame
, uint64_t);
234 if (perror
== NULL
) {
238 req
= tstream_disconnect_send(io_h
, ev
, io_h
->stream
);
240 /* Callback when disconnect is done. */
241 tevent_req_set_callback(req
, disconnect_done
, perror
);
244 ok
= tevent_req_set_endtime(req
, ev
, timeval_current_ofs_msec(
245 io_h
->connect_timeout
));
247 DBG_ERR("Can't set endtime\n");
251 /* Loop waiting for req to finish. */
252 ok
= tevent_req_poll(req
, ev
);
254 DBG_ERR("tevent_req_poll failed\n");
258 /* Emit debug error if failed. */
260 DBG_DEBUG("Error %s\n", strerror((int)*perror
));
264 /* Here we know we disconnected. */
274 static void writev_done(struct tevent_req
*req
)
276 uint64_t *perr
= tevent_req_callback_data(req
, uint64_t);
280 ret
= tstream_writev_recv(req
, &err_ret
);
287 /****************************************************************************
288 Write all data from an iov array, with msec timeout (per write)
289 NB. This can be called with a non-socket fd, don't add dependencies
291 ****************************************************************************/
293 bool write_data_iov_timeout(
294 struct tstream_context
*stream
,
295 const struct iovec
*iov
,
299 struct tevent_context
*ev
= NULL
;
300 struct tevent_req
*req
= NULL
;
301 uint64_t *perror
= NULL
;
303 TALLOC_CTX
*frame
= talloc_stackframe();
305 ev
= tevent_context_init(frame
);
307 DBG_ERR("Failed to setup event context.\n");
311 /* Error return - must be talloc'ed. */
312 perror
= talloc_zero(frame
, uint64_t);
313 if (perror
== NULL
) {
318 req
= tstream_writev_send(frame
, ev
, stream
, iov
, iovcnt
);
320 DBG_ERR("Out of memory.\n");
324 /* Callback when *all* data sent. */
325 tevent_req_set_callback(req
, writev_done
, perror
);
328 ok
= tevent_req_set_endtime(req
, ev
,
329 timeval_current_ofs_msec(ms_timeout
));
331 DBG_ERR("Can't set endtime\n");
335 /* Loop waiting for req to finish. */
336 ok
= tevent_req_poll(req
, ev
);
338 DBG_ERR("tevent_req_poll failed\n");
342 /* Done with req - freed by the callback. */
345 /* Emit debug error if failed. */
347 DBG_DEBUG("Error %s\n", strerror((int)*perror
));
351 /* Here we know we correctly wrote all data. */
360 bool virusfilter_io_write(
361 struct virusfilter_io_handle
*io_h
,
367 if (data_size
== 0) {
368 return VIRUSFILTER_RESULT_OK
;
371 iov
.iov_base
= discard_const_p(void, data
);
372 iov
.iov_len
= data_size
;
374 return write_data_iov_timeout(io_h
->stream
, &iov
, 1, io_h
->io_timeout
);
377 bool virusfilter_io_writel(
378 struct virusfilter_io_handle
*io_h
,
384 ok
= virusfilter_io_write(io_h
, data
, data_size
);
389 return virusfilter_io_write(io_h
, io_h
->w_eol
, io_h
->w_eol_size
);
392 bool virusfilter_io_writefl(
393 struct virusfilter_io_handle
*io_h
,
394 const char *data_fmt
, ...)
397 char data
[VIRUSFILTER_IO_BUFFER_SIZE
+ VIRUSFILTER_IO_EOL_SIZE
];
400 va_start(ap
, data_fmt
);
401 data_size
= vsnprintf(data
, VIRUSFILTER_IO_BUFFER_SIZE
, data_fmt
, ap
);
404 if (unlikely (data_size
< 0)) {
405 DBG_ERR("vsnprintf failed: %s\n", strerror(errno
));
409 memcpy(data
+ data_size
, io_h
->w_eol
, io_h
->w_eol_size
);
410 data_size
+= io_h
->w_eol_size
;
412 return virusfilter_io_write(io_h
, data
, data_size
);
415 bool virusfilter_io_vwritefl(
416 struct virusfilter_io_handle
*io_h
,
417 const char *data_fmt
, va_list ap
)
419 char data
[VIRUSFILTER_IO_BUFFER_SIZE
+ VIRUSFILTER_IO_EOL_SIZE
];
422 data_size
= vsnprintf(data
, VIRUSFILTER_IO_BUFFER_SIZE
, data_fmt
, ap
);
424 if (unlikely (data_size
< 0)) {
425 DBG_ERR("vsnprintf failed: %s\n", strerror(errno
));
429 memcpy(data
+ data_size
, io_h
->w_eol
, io_h
->w_eol_size
);
430 data_size
+= io_h
->w_eol_size
;
432 return virusfilter_io_write(io_h
, data
, data_size
);
435 bool virusfilter_io_writev(
436 struct virusfilter_io_handle
*io_h
, ...)
439 struct iovec iov
[VIRUSFILTER_IO_IOV_MAX
], *iov_p
;
443 for (iov_p
= iov
, iov_n
= 0;
444 iov_n
< VIRUSFILTER_IO_IOV_MAX
;
447 iov_p
->iov_base
= va_arg(ap
, void *);
448 if (iov_p
->iov_base
== NULL
) {
451 iov_p
->iov_len
= va_arg(ap
, int);
455 return write_data_iov_timeout(io_h
->stream
, iov
, iov_n
,
459 bool virusfilter_io_writevl(
460 struct virusfilter_io_handle
*io_h
, ...)
463 struct iovec iov
[VIRUSFILTER_IO_IOV_MAX
+ 1], *iov_p
;
467 for (iov_p
= iov
, iov_n
= 0; iov_n
< VIRUSFILTER_IO_IOV_MAX
;
470 iov_p
->iov_base
= va_arg(ap
, void *);
471 if (iov_p
->iov_base
== NULL
) {
474 iov_p
->iov_len
= va_arg(ap
, int);
478 iov_p
->iov_base
= io_h
->r_eol
;
479 iov_p
->iov_len
= io_h
->r_eol_size
;
482 return write_data_iov_timeout(io_h
->stream
, iov
, iov_n
,
486 static bool return_existing_line(TALLOC_CTX
*ctx
,
487 struct virusfilter_io_handle
*io_h
,
490 size_t read_line_len
= 0;
494 eol
= memmem(io_h
->r_buffer
, io_h
->r_len
,
495 io_h
->r_eol
, io_h
->r_eol_size
);
499 end_p
= eol
+ io_h
->r_eol_size
;
502 read_line_len
= strlen(io_h
->r_buffer
) + 1;
503 *read_line
= talloc_memdup(ctx
,
506 if (*read_line
== NULL
) {
511 * Copy the remaining buffer over the line
514 memmove(io_h
->r_buffer
,
516 io_h
->r_len
- (end_p
- io_h
->r_buffer
));
518 /* And reduce the size left in the buffer. */
519 io_h
->r_len
-= (end_p
- io_h
->r_buffer
);
523 static void readv_done(struct tevent_req
*req
)
525 uint64_t *perr
= tevent_req_callback_data(req
, uint64_t);
529 ret
= tstream_readv_recv(req
, &err_ret
);
536 bool virusfilter_io_readl(TALLOC_CTX
*ctx
,
537 struct virusfilter_io_handle
*io_h
,
540 struct tevent_context
*ev
= NULL
;
542 uint64_t *perror
= NULL
;
543 TALLOC_CTX
*frame
= talloc_stackframe();
545 /* Search for an existing complete line. */
546 ok
= return_existing_line(ctx
, io_h
, read_line
);
552 * No complete line in the buffer. We must read more
555 ev
= tevent_context_init(frame
);
557 DBG_ERR("Failed to setup event context.\n");
561 /* Error return - must be talloc'ed. */
562 perror
= talloc_zero(frame
, uint64_t);
563 if (perror
== NULL
) {
569 size_t read_size
= 0;
571 struct tevent_req
*req
= NULL
;
574 * How much can we read ?
576 pending
= tstream_pending_bytes(io_h
->stream
);
578 DBG_ERR("tstream_pending_bytes failed (%s).\n",
584 /* Must read at least one byte. */
585 read_size
= MIN(read_size
, 1);
587 /* And max remaining buffer space. */
588 read_size
= MAX(read_size
,
589 (sizeof(io_h
->r_buffer
) - io_h
->r_len
));
591 if (read_size
== 0) {
592 /* Buffer is full with no EOL. Error out. */
593 DBG_ERR("Line buffer full.\n");
597 iov
.iov_base
= io_h
->r_buffer
+ io_h
->r_len
;
598 iov
.iov_len
= read_size
;
601 req
= tstream_readv_send(frame
,
607 DBG_ERR("out of memory.\n");
611 /* Callback when *all* data read. */
612 tevent_req_set_callback(req
, readv_done
, perror
);
615 ok
= tevent_req_set_endtime(req
, ev
,
616 timeval_current_ofs_msec(io_h
->io_timeout
));
618 DBG_ERR("can't set endtime\n");
622 /* Loop waiting for req to finish. */
623 ok
= tevent_req_poll(req
, ev
);
625 DBG_ERR("tevent_req_poll failed\n");
629 /* Done with req - freed by the callback. */
633 * Emit debug error if failed.
634 * EPIPE may be success so, don't exit.
636 if (*perror
!= 0 && *perror
!= EPIPE
) {
637 DBG_DEBUG("Error %s\n", strerror((int)*perror
));
638 errno
= (int)*perror
;
643 * We read read_size bytes. Extend the useable
646 io_h
->r_len
+= read_size
;
649 SMB_ASSERT(io_h
->r_len
<= sizeof(io_h
->r_buffer
));
651 /* Exit if we have a line to return. */
652 ok
= return_existing_line(ctx
, io_h
, read_line
);
656 /* No eol - keep reading. */
665 bool virusfilter_io_writefl_readl(
666 struct virusfilter_io_handle
*io_h
,
668 const char *fmt
, ...)
676 ok
= virusfilter_io_vwritefl(io_h
, fmt
, ap
);
684 ok
= virusfilter_io_readl(talloc_tos(), io_h
, read_line
);
686 DBG_ERR("virusfilter_io_readl not OK: %d\n", ok
);
689 if (io_h
->r_len
== 0) { /* EOF */
690 DBG_ERR("virusfilter_io_readl EOF\n");
697 struct virusfilter_cache
*virusfilter_cache_new(
702 struct virusfilter_cache
*cache
;
704 if (time_limit
== 0) {
708 cache
= talloc_zero(ctx
, struct virusfilter_cache
);
710 DBG_ERR("talloc_zero failed.\n");
714 cache
->cache
= memcache_init(cache
->ctx
, entry_limit
*
715 (sizeof(struct virusfilter_cache_entry
)
716 + VIRUSFILTER_CACHE_BUFFER_SIZE
));
717 if (cache
->cache
== NULL
) {
718 DBG_ERR("memcache_init failed.\n");
722 cache
->time_limit
= time_limit
;
727 bool virusfilter_cache_entry_add(
728 struct virusfilter_cache
*cache
,
729 const char *directory
,
731 virusfilter_result result
,
734 int blob_size
= sizeof(struct virusfilter_cache_entry
);
735 struct virusfilter_cache_entry
*cache_e
=
736 talloc_zero_size(NULL
, blob_size
);
739 if (fname
== NULL
|| directory
== NULL
) {
744 fname
= talloc_asprintf(talloc_tos(), "%s/%s", directory
, fname
);
751 fname_len
= strlen(fname
);
753 if (cache_e
== NULL
|| cache
->time_limit
== 0) {
758 cache_e
->result
= result
;
759 if (report
!= NULL
) {
760 cache_e
->report
= talloc_steal(cache_e
, report
);
762 if (cache
->time_limit
> 0) {
763 cache_e
->time
= time(NULL
);
766 memcache_add_talloc(cache
->cache
,
767 VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC
,
768 data_blob_const(fname
, fname_len
), &cache_e
);
773 bool virusfilter_cache_entry_rename(
774 struct virusfilter_cache
*cache
,
775 const char *directory
,
779 int old_fname_len
= 0;
780 int new_fname_len
= 0;
781 struct virusfilter_cache_entry
*new_data
= NULL
;
782 struct virusfilter_cache_entry
*old_data
= NULL
;
784 if (old_fname
== NULL
|| new_fname
== NULL
|| directory
== NULL
) {
788 old_fname
= talloc_asprintf(talloc_tos(), "%s/%s", directory
, old_fname
);
789 new_fname
= talloc_asprintf(talloc_tos(), "%s/%s", directory
, new_fname
);
791 if (old_fname
== NULL
|| new_fname
== NULL
) {
792 TALLOC_FREE(old_fname
);
793 TALLOC_FREE(new_fname
);
797 old_fname_len
= strlen(old_fname
);
798 new_fname_len
= strlen(new_fname
);
800 old_data
= memcache_lookup_talloc(
802 VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC
,
803 data_blob_const(old_fname
, old_fname_len
));
805 if (old_data
== NULL
) {
809 new_data
= talloc_memdup(cache
->ctx
, old_data
,
810 sizeof(struct virusfilter_cache_entry
));
811 if (new_data
== NULL
) {
814 new_data
->report
= talloc_strdup(new_data
, old_data
->report
);
816 memcache_add_talloc(cache
->cache
,
817 VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC
,
818 data_blob_const(new_fname
, new_fname_len
), &new_data
);
820 memcache_delete(cache
->cache
, VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC
,
821 data_blob_const(old_fname
, old_fname_len
));
826 void virusfilter_cache_purge(struct virusfilter_cache
*cache
)
828 memcache_flush(cache
->cache
, VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC
);
831 struct virusfilter_cache_entry
*virusfilter_cache_get(
832 struct virusfilter_cache
*cache
,
833 const char *directory
,
837 struct virusfilter_cache_entry
*cache_e
= NULL
;
838 struct virusfilter_cache_entry
*data
= NULL
;
840 if (fname
== NULL
|| directory
== NULL
) {
844 fname
= talloc_asprintf(talloc_tos(), "%s/%s", directory
, fname
);
850 fname_len
= strlen(fname
);
852 data
= memcache_lookup_talloc(cache
->cache
,
853 VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC
,
854 data_blob_const(fname
, fname_len
));
860 if (cache
->time_limit
> 0) {
861 if (time(NULL
) - data
->time
> cache
->time_limit
) {
862 DBG_DEBUG("Cache entry is too old: %s\n",
864 virusfilter_cache_remove(cache
, directory
, fname
);
868 cache_e
= talloc_memdup(cache
->ctx
, data
,
869 sizeof(struct virusfilter_cache_entry
));
870 if (cache_e
== NULL
) {
873 if (data
->report
!= NULL
) {
874 cache_e
->report
= talloc_strdup(cache_e
, data
->report
);
876 cache_e
->report
= NULL
;
882 void virusfilter_cache_remove(struct virusfilter_cache
*cache
,
883 const char *directory
,
886 DBG_DEBUG("Purging cache entry: %s/%s\n", directory
, fname
);
888 if (fname
== NULL
|| directory
== NULL
) {
892 fname
= talloc_asprintf(talloc_tos(), "%s/%s", directory
, fname
);
898 memcache_delete(cache
->cache
, VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC
,
899 data_blob_const(fname
, strlen(fname
)));
902 void virusfilter_cache_entry_free(struct virusfilter_cache_entry
*cache_e
)
904 if (cache_e
!= NULL
) {
905 TALLOC_FREE(cache_e
->report
);
906 cache_e
->report
= NULL
;
908 TALLOC_FREE(cache_e
);
912 * ======================================================================
915 int virusfilter_env_set(
924 env_new
= talloc_asprintf(mem_ctx
, "%s=%s", name
, value
);
925 if (env_new
== NULL
) {
926 DBG_ERR("talloc_asprintf failed\n");
930 ret
= strv_add(mem_ctx
, env_list
, env_new
);
932 TALLOC_FREE(env_new
);
937 /* virusfilter_env version Samba's *_sub_advanced() in substitute.c */
938 int virusfilter_shell_set_conn_env(
941 connection_struct
*conn
)
943 int snum
= SNUM(conn
);
946 const char *local_machine_name
= get_local_machine_name();
950 if (local_machine_name
== NULL
|| *local_machine_name
== '\0') {
951 local_machine_name
= lp_netbios_name();
954 server_addr_p
= tsocket_address_inet_addr_string(
955 conn
->sconn
->local_address
, talloc_tos());
957 if (server_addr_p
!= NULL
) {
958 ret
= strncmp("::ffff:", server_addr_p
, 7);
962 virusfilter_env_set(mem_ctx
, env_list
, "VIRUSFILTER_SERVER_IP",
965 TALLOC_FREE(server_addr_p
);
967 virusfilter_env_set(mem_ctx
, env_list
, "VIRUSFILTER_SERVER_NAME",
969 virusfilter_env_set(mem_ctx
, env_list
,
970 "VIRUSFILTER_SERVER_NETBIOS_NAME",
972 slprintf(pidstr
,sizeof(pidstr
)-1, "%ld", (long)getpid());
973 virusfilter_env_set(mem_ctx
, env_list
, "VIRUSFILTER_SERVER_PID",
976 virusfilter_env_set(mem_ctx
, env_list
, "VIRUSFILTER_SERVICE_NAME",
977 lp_const_servicename(snum
));
978 virusfilter_env_set(mem_ctx
, env_list
, "VIRUSFILTER_SERVICE_PATH",
979 conn
->cwd_fname
->base_name
);
981 client_addr_p
= tsocket_address_inet_addr_string(
982 conn
->sconn
->remote_address
, talloc_tos());
984 if (client_addr_p
!= NULL
) {
985 ret
= strncmp("::ffff:", client_addr_p
, 7);
989 virusfilter_env_set(mem_ctx
, env_list
, "VIRUSFILTER_CLIENT_IP",
992 TALLOC_FREE(client_addr_p
);
994 virusfilter_env_set(mem_ctx
, env_list
, "VIRUSFILTER_CLIENT_NAME",
995 conn
->sconn
->remote_hostname
);
996 virusfilter_env_set(mem_ctx
, env_list
,
997 "VIRUSFILTER_CLIENT_NETBIOS_NAME",
998 get_remote_machine_name());
1000 virusfilter_env_set(mem_ctx
, env_list
, "VIRUSFILTER_USER_NAME",
1001 get_current_username());
1002 virusfilter_env_set(mem_ctx
, env_list
, "VIRUSFILTER_USER_DOMAIN",
1003 current_user_info
.domain
);
1008 /* Wrapper to Samba's smbrun() in smbrun.c */
1009 int virusfilter_shell_run(
1010 TALLOC_CTX
*mem_ctx
,
1013 connection_struct
*conn
,
1019 ret
= virusfilter_shell_set_conn_env(mem_ctx
, env_list
, conn
);
1026 return smbrun(cmd
, NULL
, strv_to_env(talloc_tos(), *env_list
));
1028 return smbrun_no_sanitize(cmd
, NULL
, strv_to_env(talloc_tos(),