2 * Unix SMB/CIFS implementation.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 #include "source3/include/includes.h"
21 #include "lib/async_req/async_sock.h"
22 #include "librpc/gen_ndr/ndr_named_pipe_auth.h"
23 #include "libcli/named_pipe_auth/npa_tstream.h"
24 #include "libcli/named_pipe_auth/tstream_u32_read.h"
25 #include "lib/util/tevent_unix.h"
26 #include "auth/auth_util.h"
31 * Connect to a local named pipe by connecting to
32 * samba-dcerpcd. Start samba-dcerpcd if it isn't
36 extern bool override_logfile
;
38 struct np_sock_connect_state
{
39 struct tevent_context
*ev
;
40 struct samba_sockaddr addr
;
41 const struct named_pipe_auth_req
*npa_req
;
42 struct named_pipe_auth_rep
*npa_rep
;
48 struct tevent_req
*subreq
;
49 struct tstream_context
*transport
;
50 struct tstream_context
*npa_stream
;
53 static void np_sock_connect_cleanup(
54 struct tevent_req
*req
, enum tevent_req_state req_state
);
55 static void np_sock_connect_before(void *private_data
);
56 static void np_sock_connect_after(void *private_data
);
57 static void np_sock_connect_connected(struct tevent_req
*subreq
);
58 static void np_sock_connect_written(struct tevent_req
*subreq
);
59 static void np_sock_connect_read_done(struct tevent_req
*subreq
);
61 static struct tevent_req
*np_sock_connect_send(
63 struct tevent_context
*ev
,
65 const struct named_pipe_auth_req
*npa_req
)
67 struct tevent_req
*req
= NULL
;
68 struct np_sock_connect_state
*state
= NULL
;
73 req
= tevent_req_create(mem_ctx
, &state
, struct np_sock_connect_state
);
78 state
->npa_req
= npa_req
;
80 state
->addr
.u
.un
.sun_family
= AF_UNIX
;
82 state
->npa_rep
= talloc_zero(state
, struct named_pipe_auth_rep
);
83 if (tevent_req_nomem(state
->npa_rep
, req
)) {
84 return tevent_req_post(req
, ev
);
87 tevent_req_set_cleanup_fn(req
, np_sock_connect_cleanup
);
89 state
->addr
.sa_socklen
= sizeof(struct sockaddr_un
);
90 len
= strlcpy(state
->addr
.u
.un
.sun_path
,
92 sizeof(state
->addr
.u
.un
.sun_path
));
93 if (len
>= sizeof(state
->addr
.u
.un
.sun_path
)) {
94 tevent_req_error(req
, ENAMETOOLONG
);
95 return tevent_req_post(req
, ev
);
98 state
->sock
= socket(AF_UNIX
, SOCK_STREAM
, 0);
99 if (state
->sock
== -1) {
100 tevent_req_error(req
, errno
);
101 return tevent_req_post(req
, ev
);
104 ret
= set_blocking(state
->sock
, false);
106 tevent_req_error(req
, errno
);
107 return tevent_req_post(req
, ev
);
109 ok
= set_close_on_exec(state
->sock
);
111 tevent_req_error(req
, errno
);
112 return tevent_req_post(req
, ev
);
115 state
->subreq
= async_connect_send(
120 state
->addr
.sa_socklen
,
121 np_sock_connect_before
,
122 np_sock_connect_after
,
124 if (tevent_req_nomem(state
->subreq
, req
)) {
125 return tevent_req_post(req
, ev
);
127 tevent_req_set_callback(state
->subreq
, np_sock_connect_connected
, req
);
132 static void np_sock_connect_cleanup(
133 struct tevent_req
*req
, enum tevent_req_state req_state
)
135 struct np_sock_connect_state
*state
= tevent_req_data(
136 req
, struct np_sock_connect_state
);
138 TALLOC_FREE(state
->subreq
);
139 TALLOC_FREE(state
->transport
);
141 if (state
->sock
!= -1) {
147 static void np_sock_connect_before(void *private_data
)
152 static void np_sock_connect_after(void *private_data
)
157 static void np_sock_connect_connected(struct tevent_req
*subreq
)
159 struct tevent_req
*req
= tevent_req_callback_data(
160 subreq
, struct tevent_req
);
161 struct np_sock_connect_state
*state
= tevent_req_data(
162 req
, struct np_sock_connect_state
);
163 enum ndr_err_code ndr_err
;
166 SMB_ASSERT(subreq
== state
->subreq
);
168 ret
= async_connect_recv(subreq
, &err
);
170 state
->subreq
= NULL
;
172 DBG_DEBUG("async_connect_recv returned %s\n", strerror(err
));
173 tevent_req_error(req
, err
);
177 ret
= tstream_bsd_existing_socket(
178 state
, state
->sock
, &state
->transport
);
181 DBG_DEBUG("tstream_bsd_existing_socket failed: %s\n",
183 tevent_req_error(req
, err
);
188 ndr_err
= ndr_push_struct_blob(
192 (ndr_push_flags_fn_t
)ndr_push_named_pipe_auth_req
);
193 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
194 DBG_DEBUG("ndr_push_struct_blob failed: %s\n",
195 ndr_errstr(ndr_err
));
196 tevent_req_error(req
, ndr_map_error2errno(ndr_err
));
199 state
->iov
= (struct iovec
) {
200 .iov_base
= state
->npa_blob
.data
,
201 .iov_len
= state
->npa_blob
.length
,
204 subreq
= tstream_writev_send(
205 state
, state
->ev
, state
->transport
, &state
->iov
, 1);
206 if (tevent_req_nomem(subreq
, req
)) {
209 tevent_req_set_callback(subreq
, np_sock_connect_written
, req
);
212 static void np_sock_connect_written(struct tevent_req
*subreq
)
214 struct tevent_req
*req
= tevent_req_callback_data(
215 subreq
, struct tevent_req
);
216 struct np_sock_connect_state
*state
= tevent_req_data(
217 req
, struct np_sock_connect_state
);
220 ret
= tstream_writev_recv(subreq
, &err
);
223 DBG_DEBUG("tstream_writev_recv returned %s\n", strerror(err
));
224 tevent_req_error(req
, err
);
228 subreq
= tstream_u32_read_send(
229 state
, state
->ev
, 0x00FFFFFF, state
->transport
);
230 if (tevent_req_nomem(subreq
, req
)) {
233 tevent_req_set_callback(subreq
, np_sock_connect_read_done
, req
);
236 static void np_sock_connect_read_done(struct tevent_req
*subreq
)
238 struct tevent_req
*req
= tevent_req_callback_data(
239 subreq
, struct tevent_req
);
240 struct np_sock_connect_state
*state
= tevent_req_data(
241 req
, struct np_sock_connect_state
);
244 enum ndr_err_code ndr_err
;
246 ret
= tstream_u32_read_recv(subreq
, state
, &in
.data
, &in
.length
);
248 if (tevent_req_error(req
, ret
)) {
252 ndr_err
= ndr_pull_struct_blob_all(
256 (ndr_pull_flags_fn_t
)ndr_pull_named_pipe_auth_rep
);
257 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
258 DBG_DEBUG("ndr_pull_named_pipe_auth_rep failed: %s\n",
259 ndr_errstr(ndr_err
));
260 tevent_req_error(req
, ndr_map_error2errno(ndr_err
));
263 if (state
->npa_rep
->level
!= 5) {
264 DBG_DEBUG("npa level = %"PRIu32
", expected 5\n",
265 state
->npa_rep
->level
);
266 tevent_req_error(req
, EIO
);
270 ret
= tstream_npa_existing_stream(
273 state
->npa_rep
->info
.info5
.file_type
,
277 DBG_DEBUG("tstream_npa_existing_stream failed: %s\n",
279 tevent_req_error(req
, ret
);
283 tevent_req_done(req
);
286 static int np_sock_connect_recv(
287 struct tevent_req
*req
,
289 struct tstream_context
**stream
)
291 struct np_sock_connect_state
*state
= tevent_req_data(
292 req
, struct np_sock_connect_state
);
295 if (tevent_req_is_unix_error(req
, &err
)) {
296 tevent_req_received(req
);
299 *stream
= talloc_move(mem_ctx
, &state
->npa_stream
);
300 tevent_req_received(req
);
304 struct start_rpc_host_state
{
306 struct tevent_req
*read_ready_req
;
309 static void start_rpc_host_cleanup(
310 struct tevent_req
*req
, enum tevent_req_state req_state
);
311 static void start_rpc_host_ready(struct tevent_req
*subreq
);
314 * Start samba-dcerpcd and wait for it to report ready.
316 static struct tevent_req
*start_rpc_host_send(
317 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
)
319 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
320 struct start_rpc_host_state
*state
= NULL
;
322 int ready_fds
[2] = { -1, -1 };
327 req
= tevent_req_create(
328 mem_ctx
, &state
, struct start_rpc_host_state
);
333 ret
= pipe(ready_fds
);
336 DBG_DEBUG("pipe() failed: %s\n", strerror(ret
));
340 ok
= smb_set_close_on_exec(ready_fds
[0]);
343 DBG_DEBUG("smb_set_close_on_exec failed: %s\n",
348 argv
= str_list_make_empty(mem_ctx
);
350 &argv
, "%s/samba-dcerpcd", get_dyn_SAMBA_LIBEXECDIR());
351 if (!is_default_dyn_CONFIGFILE()) {
353 &argv
, "--configfile=%s", get_dyn_CONFIGFILE());
355 str_list_add_printf(&argv
, "--libexec-rpcds");
356 str_list_add_printf(&argv
, "--ready-signal-fd=%d", ready_fds
[1]);
357 str_list_add_printf(&argv
, "--np-helper");
359 &argv
, "--debuglevel=%d", debuglevel_get_class(DBGC_RPC_SRV
));
360 if (!is_default_dyn_LOGFILEBASE()) {
362 &argv
, "--log-basename=%s", get_dyn_LOGFILEBASE());
370 ret
= posix_spawn(&pid
, argv
[0], NULL
, NULL
, argv
, environ
);
373 DBG_DEBUG("posix_spawn() failed: %s\n", strerror(ret
));
377 state
->ready_fd
= ready_fds
[0];
379 tevent_req_set_cleanup_fn(req
, start_rpc_host_cleanup
);
384 subreq
= read_packet_send(state
, ev
, state
->ready_fd
, 1, NULL
, NULL
);
385 if (tevent_req_nomem(subreq
, req
)) {
386 return tevent_req_post(req
, ev
);
388 tevent_req_set_callback(subreq
, start_rpc_host_ready
, req
);
392 if (ready_fds
[0] == -1) {
396 if (ready_fds
[1] == -1) {
400 tevent_req_error(req
, ret
);
401 return tevent_req_post(req
, ev
);
404 static void start_rpc_host_cleanup(
405 struct tevent_req
*req
, enum tevent_req_state req_state
)
407 struct start_rpc_host_state
*state
= tevent_req_data(
408 req
, struct start_rpc_host_state
);
410 if (state
->ready_fd
!= -1) {
411 close(state
->ready_fd
);
412 state
->ready_fd
= -1;
416 static void start_rpc_host_ready(struct tevent_req
*subreq
)
418 struct tevent_req
*req
= tevent_req_callback_data(
419 subreq
, struct tevent_req
);
420 struct start_rpc_host_state
*state
= tevent_req_data(
421 req
, struct start_rpc_host_state
);
426 nread
= read_packet_recv(subreq
, state
, &buf
, &err
);
429 tevent_req_error(req
, err
);
433 close(state
->ready_fd
);
434 state
->ready_fd
= -1;
436 tevent_req_done(req
);
439 static int start_rpc_host_recv(struct tevent_req
*req
)
441 return tevent_req_simple_recv_unix(req
);
444 struct local_np_connect_state
{
445 struct tevent_context
*ev
;
446 const char *socketpath
;
447 struct named_pipe_auth_req
*npa_req
;
448 struct tstream_context
*npa_stream
;
451 static void local_np_connect_connected(struct tevent_req
*subreq
);
452 static void local_np_connect_started(struct tevent_req
*subreq
);
453 static void local_np_connect_retried(struct tevent_req
*subreq
);
456 * @brief Async connect to a local named pipe RPC interface
458 * Start "samba-dcerpcd" on demand if it does not exist
460 * @param[in] mem_ctx The memory context to use.
461 * @param[in] ev The tevent context to use.
463 * @param[in] pipename The raw pipename to connect to without path
464 * @param[in] remote_client_name The client name to transmit
465 * @param[in] remote_client_addr The client addr to transmit
466 * @param[in] local_server_name The server name to transmit
467 * @param[in] local_server_addr The server addr to transmit
468 * @param[in] session_info The authorization info to use
469 * @param[in] need_idle_server Does this need to be an exclusive server?
470 * @return The tevent_req that was started
473 struct tevent_req
*local_np_connect_send(
475 struct tevent_context
*ev
,
476 const char *pipename
,
477 enum dcerpc_transport_t transport
,
478 const char *remote_client_name
,
479 const struct tsocket_address
*remote_client_addr
,
480 const char *local_server_name
,
481 const struct tsocket_address
*local_server_addr
,
482 const struct auth_session_info
*session_info
,
483 bool need_idle_server
)
485 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
486 struct local_np_connect_state
*state
= NULL
;
487 struct named_pipe_auth_req_info5
*i5
= NULL
;
488 const char *socket_dir
= NULL
;
489 char *lower_case_pipename
= NULL
;
491 req
= tevent_req_create(
492 mem_ctx
, &state
, struct local_np_connect_state
);
498 socket_dir
= lp_parm_const_string(
499 GLOBAL_SECTION_SNUM
, "external_rpc_pipe", "socket_dir",
501 if (socket_dir
== NULL
) {
502 DBG_DEBUG("external_rpc_pipe:socket_dir not set\n");
503 tevent_req_error(req
, EINVAL
);
504 return tevent_req_post(req
, ev
);
507 lower_case_pipename
= strlower_talloc(state
, pipename
);
508 if (tevent_req_nomem(lower_case_pipename
, req
)) {
509 return tevent_req_post(req
, ev
);
512 state
->socketpath
= talloc_asprintf(
513 state
, "%s/np/%s", socket_dir
, lower_case_pipename
);
514 if (tevent_req_nomem(state
->socketpath
, req
)) {
515 return tevent_req_post(req
, ev
);
517 TALLOC_FREE(lower_case_pipename
);
519 state
->npa_req
= talloc_zero(state
, struct named_pipe_auth_req
);
520 if (tevent_req_nomem(state
->npa_req
, req
)) {
521 return tevent_req_post(req
, ev
);
523 state
->npa_req
->level
= 5;
525 i5
= &state
->npa_req
->info
.info5
;
527 i5
->transport
= transport
;
529 /* we don't have "int" in IDL, make sure we don't overflow */
530 SMB_ASSERT(i5
->transport
== transport
);
532 if (remote_client_name
== NULL
) {
533 remote_client_name
= get_myname(state
->npa_req
);
534 if (remote_client_name
== NULL
) {
535 tevent_req_error(req
, errno
);
536 return tevent_req_post(req
, ev
);
539 i5
->remote_client_name
= remote_client_name
;
541 if (remote_client_addr
== NULL
) {
542 struct tsocket_address
*addr
= NULL
;
543 int ret
= tsocket_address_inet_from_strings(
544 state
->npa_req
, "ip", NULL
, 0, &addr
);
546 tevent_req_error(req
, errno
);
547 return tevent_req_post(req
, ev
);
549 remote_client_addr
= addr
;
551 i5
->remote_client_addr
= tsocket_address_inet_addr_string(
552 remote_client_addr
, state
->npa_req
);
553 if (i5
->remote_client_addr
== NULL
) {
554 tevent_req_error(req
, errno
);
555 return tevent_req_post(req
, ev
);
557 i5
->remote_client_port
= tsocket_address_inet_port(remote_client_addr
);
559 if (local_server_name
== NULL
) {
560 local_server_name
= remote_client_name
;
562 i5
->local_server_name
= local_server_name
;
564 if (local_server_addr
== NULL
) {
565 struct tsocket_address
*addr
= NULL
;
566 int ret
= tsocket_address_inet_from_strings(
567 state
->npa_req
, "ip", NULL
, 0, &addr
);
569 tevent_req_error(req
, errno
);
570 return tevent_req_post(req
, ev
);
572 local_server_addr
= addr
;
574 i5
->local_server_addr
= tsocket_address_inet_addr_string(
575 local_server_addr
, state
->npa_req
);
576 if (i5
->local_server_addr
== NULL
) {
577 tevent_req_error(req
, errno
);
578 return tevent_req_post(req
, ev
);
580 i5
->local_server_port
= tsocket_address_inet_port(local_server_addr
);
582 i5
->session_info
= talloc_zero(
583 state
->npa_req
, struct auth_session_info_transport
);
584 if (tevent_req_nomem(i5
->session_info
, req
)) {
585 return tevent_req_post(req
, ev
);
588 i5
->session_info
->session_info
= copy_session_info(
589 i5
->session_info
, session_info
);
590 if (tevent_req_nomem(i5
->session_info
->session_info
, req
)) {
591 return tevent_req_post(req
, ev
);
594 i5
->need_idle_server
= need_idle_server
;
596 subreq
= np_sock_connect_send(
597 state
, state
->ev
, state
->socketpath
, state
->npa_req
);
598 if (tevent_req_nomem(subreq
, req
)) {
599 return tevent_req_post(req
, ev
);
601 tevent_req_set_callback(subreq
, local_np_connect_connected
, req
);
606 static void local_np_connect_connected(struct tevent_req
*subreq
)
608 struct tevent_req
*req
= tevent_req_callback_data(
609 subreq
, struct tevent_req
);
610 struct local_np_connect_state
*state
= tevent_req_data(
611 req
, struct local_np_connect_state
);
614 ret
= np_sock_connect_recv(subreq
, state
, &state
->npa_stream
);
618 tevent_req_done(req
);
622 DBG_DEBUG("np_sock_connect failed: %s\n", strerror(ret
));
624 if (!lp_rpc_start_on_demand_helpers()) {
626 * samba-dcerpcd should already be started in
627 * daemon/standalone mode when "rpc start on demand
628 * helpers = false". We are prohibited from starting
629 * on demand as a named-pipe helper.
631 DBG_ERR("Can't connect to a running samba-dcerpcd. smb.conf "
632 "config prohibits starting as named pipe helper as "
633 "the [global] section contains "
634 "\"rpc start on demand helpers = false\".\n");
635 tevent_req_error(req
, ret
);
640 * samba-dcerpcd isn't running. We need to start it.
641 * Note if it doesn't start we treat this as a fatal
642 * error for connecting to the named pipe and don't
643 * keep trying to restart for this connection.
645 subreq
= start_rpc_host_send(state
, state
->ev
);
646 if (tevent_req_nomem(subreq
, req
)) {
649 tevent_req_set_callback(subreq
, local_np_connect_started
, req
);
652 static void local_np_connect_started(struct tevent_req
*subreq
)
654 struct tevent_req
*req
= tevent_req_callback_data(
655 subreq
, struct tevent_req
);
656 struct local_np_connect_state
*state
= tevent_req_data(
657 req
, struct local_np_connect_state
);
660 ret
= start_rpc_host_recv(subreq
);
662 if (tevent_req_error(req
, ret
)) {
663 DBG_DEBUG("start_rpc_host_recv failed: %s\n",
668 subreq
= np_sock_connect_send(
669 state
, state
->ev
, state
->socketpath
, state
->npa_req
);
670 if (tevent_req_nomem(subreq
, req
)) {
673 tevent_req_set_callback(subreq
, local_np_connect_retried
, req
);
676 static void local_np_connect_retried(struct tevent_req
*subreq
)
678 struct tevent_req
*req
= tevent_req_callback_data(
679 subreq
, struct tevent_req
);
680 struct local_np_connect_state
*state
= tevent_req_data(
681 req
, struct local_np_connect_state
);
684 ret
= np_sock_connect_recv(subreq
, state
, &state
->npa_stream
);
686 if (tevent_req_error(req
, ret
)) {
689 tevent_req_done(req
);
693 * @brief Receive handle to a local named pipe RPC interface
695 * @param[in] req The tevent_req that started the operation
696 * @param[in] ev The tevent context to use.
697 * @param[in] mem_ctx The memory context to put pstream on
698 * @param[out] pstream The established connection to the RPC server
703 int local_np_connect_recv(
704 struct tevent_req
*req
,
706 struct tstream_context
**pstream
)
708 struct local_np_connect_state
*state
= tevent_req_data(
709 req
, struct local_np_connect_state
);
712 if (tevent_req_is_unix_error(req
, &err
)) {
713 tevent_req_received(req
);
717 *pstream
= talloc_move(mem_ctx
, &state
->npa_stream
);
722 * @brief Sync connect to a local named pipe RPC interface
724 * Start "samba-dcerpcd" on demand if it does not exist
726 * @param[in] pipename The raw pipename to connect to without path
727 * @param[in] remote_client_name The client name to transmit
728 * @param[in] remote_client_addr The client addr to transmit
729 * @param[in] local_server_name The server name to transmit
730 * @param[in] local_server_addr The server addr to transmit
731 * @param[in] session_info The authorization info to use
732 * @param[in] need_idle_server Does this need to be an exclusive server?
733 * @param[in] mem_ctx The memory context to use.
734 * @param[out] pstream The established connection to the RPC server
738 int local_np_connect(
739 const char *pipename
,
740 enum dcerpc_transport_t transport
,
741 const char *remote_client_name
,
742 const struct tsocket_address
*remote_client_addr
,
743 const char *local_server_name
,
744 const struct tsocket_address
*local_server_addr
,
745 const struct auth_session_info
*session_info
,
746 bool need_idle_server
,
748 struct tstream_context
**pstream
)
750 struct tevent_context
*ev
= NULL
;
751 struct tevent_req
*req
= NULL
;
754 ev
= samba_tevent_context_init(mem_ctx
);
758 req
= local_np_connect_send(
772 if (!tevent_req_poll_unix(req
, ev
, &ret
)) {
775 ret
= local_np_connect_recv(req
, mem_ctx
, pstream
);