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"
27 #include "libcli/security/dom_sid.h"
28 #include "libcli/security/security_token.h"
29 #include "nsswitch/winbind_client.h"
34 * Connect to a local named pipe by connecting to
35 * samba-dcerpcd. Start samba-dcerpcd if it isn't
39 extern bool override_logfile
;
41 struct np_sock_connect_state
{
42 struct tevent_context
*ev
;
43 struct samba_sockaddr addr
;
44 const struct named_pipe_auth_req
*npa_req
;
45 struct named_pipe_auth_rep
*npa_rep
;
51 struct tevent_req
*subreq
;
52 struct tstream_context
*transport
;
53 struct tstream_context
*npa_stream
;
56 static void np_sock_connect_cleanup(
57 struct tevent_req
*req
, enum tevent_req_state req_state
);
58 static void np_sock_connect_before(void *private_data
);
59 static void np_sock_connect_after(void *private_data
);
60 static void np_sock_connect_connected(struct tevent_req
*subreq
);
61 static void np_sock_connect_written(struct tevent_req
*subreq
);
62 static void np_sock_connect_read_done(struct tevent_req
*subreq
);
64 static struct tevent_req
*np_sock_connect_send(
66 struct tevent_context
*ev
,
68 const struct named_pipe_auth_req
*npa_req
)
70 struct tevent_req
*req
= NULL
;
71 struct np_sock_connect_state
*state
= NULL
;
76 req
= tevent_req_create(mem_ctx
, &state
, struct np_sock_connect_state
);
81 state
->npa_req
= npa_req
;
83 state
->addr
.u
.un
.sun_family
= AF_UNIX
;
85 state
->npa_rep
= talloc_zero(state
, struct named_pipe_auth_rep
);
86 if (tevent_req_nomem(state
->npa_rep
, req
)) {
87 return tevent_req_post(req
, ev
);
90 tevent_req_set_cleanup_fn(req
, np_sock_connect_cleanup
);
92 state
->addr
.sa_socklen
= sizeof(struct sockaddr_un
);
93 len
= strlcpy(state
->addr
.u
.un
.sun_path
,
95 sizeof(state
->addr
.u
.un
.sun_path
));
96 if (len
>= sizeof(state
->addr
.u
.un
.sun_path
)) {
97 tevent_req_error(req
, ENAMETOOLONG
);
98 return tevent_req_post(req
, ev
);
101 state
->sock
= socket(AF_UNIX
, SOCK_STREAM
, 0);
102 if (state
->sock
== -1) {
103 tevent_req_error(req
, errno
);
104 return tevent_req_post(req
, ev
);
107 ret
= set_blocking(state
->sock
, true);
109 tevent_req_error(req
, errno
);
110 return tevent_req_post(req
, ev
);
112 ok
= set_close_on_exec(state
->sock
);
114 tevent_req_error(req
, errno
);
115 return tevent_req_post(req
, ev
);
118 state
->subreq
= async_connect_send(
123 state
->addr
.sa_socklen
,
124 np_sock_connect_before
,
125 np_sock_connect_after
,
127 if (tevent_req_nomem(state
->subreq
, req
)) {
128 return tevent_req_post(req
, ev
);
130 tevent_req_set_callback(state
->subreq
, np_sock_connect_connected
, req
);
135 static void np_sock_connect_cleanup(
136 struct tevent_req
*req
, enum tevent_req_state req_state
)
138 struct np_sock_connect_state
*state
= tevent_req_data(
139 req
, struct np_sock_connect_state
);
141 TALLOC_FREE(state
->subreq
);
142 TALLOC_FREE(state
->transport
);
144 if (state
->sock
!= -1) {
150 static void np_sock_connect_before(void *private_data
)
155 static void np_sock_connect_after(void *private_data
)
160 static void np_sock_connect_connected(struct tevent_req
*subreq
)
162 struct tevent_req
*req
= tevent_req_callback_data(
163 subreq
, struct tevent_req
);
164 struct np_sock_connect_state
*state
= tevent_req_data(
165 req
, struct np_sock_connect_state
);
166 enum ndr_err_code ndr_err
;
169 SMB_ASSERT(subreq
== state
->subreq
);
171 ret
= async_connect_recv(subreq
, &err
);
173 state
->subreq
= NULL
;
175 DBG_DEBUG("async_connect_recv returned %s\n", strerror(err
));
176 tevent_req_error(req
, err
);
181 * As a quick workaround for bug 15310 we have done the
182 * connect in blocking mode (see np_sock_connect_send()). The
183 * rest of our code expects a nonblocking socket, activate
184 * this after the connect succeeded.
186 ret
= set_blocking(state
->sock
, false);
188 tevent_req_error(req
, errno
);
192 ret
= tstream_bsd_existing_socket(
193 state
, state
->sock
, &state
->transport
);
196 DBG_DEBUG("tstream_bsd_existing_socket failed: %s\n",
198 tevent_req_error(req
, err
);
203 ndr_err
= ndr_push_struct_blob(
207 (ndr_push_flags_fn_t
)ndr_push_named_pipe_auth_req
);
208 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
209 DBG_DEBUG("ndr_push_struct_blob failed: %s\n",
210 ndr_errstr(ndr_err
));
211 tevent_req_error(req
, ndr_map_error2errno(ndr_err
));
214 state
->iov
= (struct iovec
) {
215 .iov_base
= state
->npa_blob
.data
,
216 .iov_len
= state
->npa_blob
.length
,
219 subreq
= tstream_writev_send(
220 state
, state
->ev
, state
->transport
, &state
->iov
, 1);
221 if (tevent_req_nomem(subreq
, req
)) {
224 tevent_req_set_callback(subreq
, np_sock_connect_written
, req
);
227 static void np_sock_connect_written(struct tevent_req
*subreq
)
229 struct tevent_req
*req
= tevent_req_callback_data(
230 subreq
, struct tevent_req
);
231 struct np_sock_connect_state
*state
= tevent_req_data(
232 req
, struct np_sock_connect_state
);
235 ret
= tstream_writev_recv(subreq
, &err
);
238 DBG_DEBUG("tstream_writev_recv returned %s\n", strerror(err
));
239 tevent_req_error(req
, err
);
243 subreq
= tstream_u32_read_send(
244 state
, state
->ev
, 0x00FFFFFF, state
->transport
);
245 if (tevent_req_nomem(subreq
, req
)) {
248 tevent_req_set_callback(subreq
, np_sock_connect_read_done
, req
);
251 static void np_sock_connect_read_done(struct tevent_req
*subreq
)
253 struct tevent_req
*req
= tevent_req_callback_data(
254 subreq
, struct tevent_req
);
255 struct np_sock_connect_state
*state
= tevent_req_data(
256 req
, struct np_sock_connect_state
);
259 enum ndr_err_code ndr_err
;
261 ret
= tstream_u32_read_recv(subreq
, state
, &in
.data
, &in
.length
);
263 if (tevent_req_error(req
, ret
)) {
267 ndr_err
= ndr_pull_struct_blob_all(
271 (ndr_pull_flags_fn_t
)ndr_pull_named_pipe_auth_rep
);
272 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
273 DBG_DEBUG("ndr_pull_named_pipe_auth_rep failed: %s\n",
274 ndr_errstr(ndr_err
));
275 tevent_req_error(req
, ndr_map_error2errno(ndr_err
));
278 if (state
->npa_rep
->level
!= 8) {
279 DBG_DEBUG("npa level = %" PRIu32
", expected 8\n",
280 state
->npa_rep
->level
);
281 tevent_req_error(req
, EIO
);
285 ret
= tstream_npa_existing_stream(state
,
287 state
->npa_rep
->info
.info8
.file_type
,
291 DBG_DEBUG("tstream_npa_existing_stream failed: %s\n",
293 tevent_req_error(req
, ret
);
297 tevent_req_done(req
);
300 static int np_sock_connect_recv(
301 struct tevent_req
*req
,
303 struct tstream_context
**stream
)
305 struct np_sock_connect_state
*state
= tevent_req_data(
306 req
, struct np_sock_connect_state
);
309 if (tevent_req_is_unix_error(req
, &err
)) {
310 tevent_req_received(req
);
313 *stream
= talloc_move(mem_ctx
, &state
->npa_stream
);
314 tevent_req_received(req
);
318 struct start_rpc_host_state
{
320 struct tevent_req
*read_ready_req
;
323 static void start_rpc_host_cleanup(
324 struct tevent_req
*req
, enum tevent_req_state req_state
);
325 static void start_rpc_host_ready(struct tevent_req
*subreq
);
328 * Start samba-dcerpcd and wait for it to report ready.
330 static struct tevent_req
*start_rpc_host_send(
331 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
)
333 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
334 struct start_rpc_host_state
*state
= NULL
;
336 int ready_fds
[2] = { -1, -1 };
341 req
= tevent_req_create(
342 mem_ctx
, &state
, struct start_rpc_host_state
);
347 ret
= pipe(ready_fds
);
350 DBG_DEBUG("pipe() failed: %s\n", strerror(ret
));
354 ok
= smb_set_close_on_exec(ready_fds
[0]);
357 DBG_DEBUG("smb_set_close_on_exec failed: %s\n",
362 argv
= str_list_make_empty(mem_ctx
);
364 &argv
, "%s/samba-dcerpcd", get_dyn_SAMBA_LIBEXECDIR());
365 if (!is_default_dyn_CONFIGFILE()) {
367 &argv
, "--configfile=%s", get_dyn_CONFIGFILE());
369 str_list_add_printf(&argv
, "--libexec-rpcds");
370 str_list_add_printf(&argv
, "--ready-signal-fd=%d", ready_fds
[1]);
371 str_list_add_printf(&argv
, "--np-helper");
373 &argv
, "--debuglevel=%d", debuglevel_get_class(DBGC_RPC_SRV
));
374 if (!is_default_dyn_LOGFILEBASE()) {
376 &argv
, "--log-basename=%s", get_dyn_LOGFILEBASE());
384 ret
= posix_spawn(&pid
, argv
[0], NULL
, NULL
, argv
, environ
);
387 DBG_DEBUG("posix_spawn() failed: %s\n", strerror(ret
));
391 state
->ready_fd
= ready_fds
[0];
393 tevent_req_set_cleanup_fn(req
, start_rpc_host_cleanup
);
398 subreq
= read_packet_send(state
, ev
, state
->ready_fd
, 1, NULL
, NULL
);
399 if (tevent_req_nomem(subreq
, req
)) {
400 return tevent_req_post(req
, ev
);
402 tevent_req_set_callback(subreq
, start_rpc_host_ready
, req
);
406 if (ready_fds
[0] != -1) {
410 if (ready_fds
[1] != -1) {
414 tevent_req_error(req
, ret
);
415 return tevent_req_post(req
, ev
);
418 static void start_rpc_host_cleanup(
419 struct tevent_req
*req
, enum tevent_req_state req_state
)
421 struct start_rpc_host_state
*state
= tevent_req_data(
422 req
, struct start_rpc_host_state
);
424 if (state
->ready_fd
!= -1) {
425 close(state
->ready_fd
);
426 state
->ready_fd
= -1;
430 static void start_rpc_host_ready(struct tevent_req
*subreq
)
432 struct tevent_req
*req
= tevent_req_callback_data(
433 subreq
, struct tevent_req
);
434 struct start_rpc_host_state
*state
= tevent_req_data(
435 req
, struct start_rpc_host_state
);
440 nread
= read_packet_recv(subreq
, state
, &buf
, &err
);
443 tevent_req_error(req
, err
);
447 close(state
->ready_fd
);
448 state
->ready_fd
= -1;
450 tevent_req_done(req
);
453 static int start_rpc_host_recv(struct tevent_req
*req
)
455 return tevent_req_simple_recv_unix(req
);
458 struct local_np_connect_state
{
459 struct tevent_context
*ev
;
460 const char *socketpath
;
461 struct named_pipe_auth_req
*npa_req
;
462 struct tstream_context
*npa_stream
;
465 static void local_np_connect_connected(struct tevent_req
*subreq
);
466 static void local_np_connect_started(struct tevent_req
*subreq
);
467 static void local_np_connect_retried(struct tevent_req
*subreq
);
470 * @brief Async connect to a local named pipe RPC interface
472 * Start "samba-dcerpcd" on demand if it does not exist
474 * @param[in] mem_ctx The memory context to use.
475 * @param[in] ev The tevent context to use.
477 * @param[in] pipename The raw pipename to connect to without path
478 * @param[in] remote_client_name The client name to transmit
479 * @param[in] remote_client_addr The client addr to transmit
480 * @param[in] local_server_name The server name to transmit
481 * @param[in] local_server_addr The server addr to transmit
482 * @param[in] session_info The authorization info to use
483 * @param[in] need_idle_server Does this need to be an exclusive server?
484 * @return The tevent_req that was started
487 struct tevent_req
*local_np_connect_send(
489 struct tevent_context
*ev
,
490 const char *pipename
,
491 enum dcerpc_transport_t transport
,
492 const char *remote_client_name
,
493 const struct tsocket_address
*remote_client_addr
,
494 const char *local_server_name
,
495 const struct tsocket_address
*local_server_addr
,
496 const struct auth_session_info
*session_info
,
497 bool need_idle_server
)
499 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
500 struct local_np_connect_state
*state
= NULL
;
501 struct named_pipe_auth_req_info8
*i8
= NULL
;
502 const char *socket_dir
= NULL
;
503 char *lower_case_pipename
= NULL
;
504 struct dom_sid npa_sid
= global_sid_Samba_NPA_Flags
;
505 uint32_t npa_flags
= 0;
506 struct security_token
*token
= NULL
;
511 req
= tevent_req_create(
512 mem_ctx
, &state
, struct local_np_connect_state
);
519 security_token_count_flag_sids(session_info
->security_token
,
523 if (num_npa_sids
!= 0) {
524 DBG_ERR("ERROR: %zu NPA Flags SIDs have already been "
525 "detected in the security token!\n",
527 tevent_req_error(req
, EACCES
);
528 return tevent_req_post(req
, ev
);
531 socket_dir
= lp_parm_const_string(
532 GLOBAL_SECTION_SNUM
, "external_rpc_pipe", "socket_dir",
534 if (socket_dir
== NULL
) {
535 DBG_DEBUG("external_rpc_pipe:socket_dir not set\n");
536 tevent_req_error(req
, EINVAL
);
537 return tevent_req_post(req
, ev
);
540 lower_case_pipename
= strlower_talloc(state
, pipename
);
541 if (tevent_req_nomem(lower_case_pipename
, req
)) {
542 return tevent_req_post(req
, ev
);
546 * Ensure we cannot process a path that exits
549 if (ISDOTDOT(lower_case_pipename
) ||
550 (strchr(lower_case_pipename
, '/')!=NULL
))
552 DBG_DEBUG("attempt to connect to invalid pipe pathname %s\n",
553 lower_case_pipename
);
554 tevent_req_error(req
, ENOENT
);
555 return tevent_req_post(req
, ev
);
558 state
->socketpath
= talloc_asprintf(
559 state
, "%s/np/%s", socket_dir
, lower_case_pipename
);
560 if (tevent_req_nomem(state
->socketpath
, req
)) {
561 return tevent_req_post(req
, ev
);
563 TALLOC_FREE(lower_case_pipename
);
565 state
->npa_req
= talloc_zero(state
, struct named_pipe_auth_req
);
566 if (tevent_req_nomem(state
->npa_req
, req
)) {
567 return tevent_req_post(req
, ev
);
569 state
->npa_req
->level
= 8;
571 i8
= &state
->npa_req
->info
.info8
;
573 i8
->transport
= transport
;
575 /* we don't have "int" in IDL, make sure we don't overflow */
576 SMB_ASSERT(i8
->transport
== transport
);
578 if (remote_client_name
== NULL
) {
579 remote_client_name
= get_myname(state
->npa_req
);
580 if (remote_client_name
== NULL
) {
581 tevent_req_error(req
, errno
);
582 return tevent_req_post(req
, ev
);
585 i8
->remote_client_name
= remote_client_name
;
587 if (remote_client_addr
== NULL
) {
588 struct tsocket_address
*addr
= NULL
;
589 int ret
= tsocket_address_inet_from_strings(
590 state
->npa_req
, "ip", NULL
, 0, &addr
);
592 tevent_req_error(req
, errno
);
593 return tevent_req_post(req
, ev
);
595 remote_client_addr
= addr
;
597 i8
->remote_client_addr
=
598 tsocket_address_inet_addr_string(remote_client_addr
,
600 if (i8
->remote_client_addr
== NULL
) {
601 tevent_req_error(req
, errno
);
602 return tevent_req_post(req
, ev
);
604 i8
->remote_client_port
= tsocket_address_inet_port(remote_client_addr
);
606 if (local_server_name
== NULL
) {
607 local_server_name
= remote_client_name
;
609 i8
->local_server_name
= local_server_name
;
611 if (local_server_addr
== NULL
) {
612 struct tsocket_address
*addr
= NULL
;
613 int ret
= tsocket_address_inet_from_strings(
614 state
->npa_req
, "ip", NULL
, 0, &addr
);
616 tevent_req_error(req
, errno
);
617 return tevent_req_post(req
, ev
);
619 local_server_addr
= addr
;
621 i8
->local_server_addr
=
622 tsocket_address_inet_addr_string(local_server_addr
,
624 if (i8
->local_server_addr
== NULL
) {
625 tevent_req_error(req
, errno
);
626 return tevent_req_post(req
, ev
);
628 i8
->local_server_port
= tsocket_address_inet_port(local_server_addr
);
630 i8
->session_info
= talloc_zero(state
->npa_req
,
631 struct auth_session_info_transport
);
632 if (tevent_req_nomem(i8
->session_info
, req
)) {
633 return tevent_req_post(req
, ev
);
636 i8
->session_info
->session_info
=
637 copy_session_info(i8
->session_info
, session_info
);
638 if (tevent_req_nomem(i8
->session_info
->session_info
, req
)) {
639 return tevent_req_post(req
, ev
);
642 if (need_idle_server
) {
643 npa_flags
|= SAMBA_NPA_FLAGS_NEED_IDLE
;
646 ok
= winbind_env_set();
648 npa_flags
|= SAMBA_NPA_FLAGS_WINBIND_OFF
;
651 ok
= sid_append_rid(&npa_sid
, npa_flags
);
653 tevent_req_error(req
, EINVAL
);
654 return tevent_req_post(req
, ev
);
657 token
= i8
->session_info
->session_info
->security_token
;
659 status
= add_sid_to_array_unique(token
,
663 if (!NT_STATUS_IS_OK(status
)) {
665 return tevent_req_post(req
, ev
);
668 subreq
= np_sock_connect_send(
669 state
, state
->ev
, state
->socketpath
, state
->npa_req
);
670 if (tevent_req_nomem(subreq
, req
)) {
671 return tevent_req_post(req
, ev
);
673 tevent_req_set_callback(subreq
, local_np_connect_connected
, req
);
678 static void local_np_connect_connected(struct tevent_req
*subreq
)
680 struct tevent_req
*req
= tevent_req_callback_data(
681 subreq
, struct tevent_req
);
682 struct local_np_connect_state
*state
= tevent_req_data(
683 req
, struct local_np_connect_state
);
686 ret
= np_sock_connect_recv(subreq
, state
, &state
->npa_stream
);
690 tevent_req_done(req
);
694 DBG_DEBUG("np_sock_connect failed: %s\n", strerror(ret
));
696 if (!lp_rpc_start_on_demand_helpers()) {
698 * samba-dcerpcd should already be started in
699 * daemon/standalone mode when "rpc start on demand
700 * helpers = false". We are prohibited from starting
701 * on demand as a named-pipe helper.
703 DBG_ERR("Can't connect to a running samba-dcerpcd. smb.conf "
704 "config prohibits starting as named pipe helper as "
705 "the [global] section contains "
706 "\"rpc start on demand helpers = false\".\n");
707 tevent_req_error(req
, ret
);
712 * samba-dcerpcd isn't running. We need to start it.
713 * Note if it doesn't start we treat this as a fatal
714 * error for connecting to the named pipe and don't
715 * keep trying to restart for this connection.
717 subreq
= start_rpc_host_send(state
, state
->ev
);
718 if (tevent_req_nomem(subreq
, req
)) {
721 tevent_req_set_callback(subreq
, local_np_connect_started
, req
);
724 static void local_np_connect_started(struct tevent_req
*subreq
)
726 struct tevent_req
*req
= tevent_req_callback_data(
727 subreq
, struct tevent_req
);
728 struct local_np_connect_state
*state
= tevent_req_data(
729 req
, struct local_np_connect_state
);
732 ret
= start_rpc_host_recv(subreq
);
734 if (tevent_req_error(req
, ret
)) {
735 DBG_DEBUG("start_rpc_host_recv failed: %s\n",
740 subreq
= np_sock_connect_send(
741 state
, state
->ev
, state
->socketpath
, state
->npa_req
);
742 if (tevent_req_nomem(subreq
, req
)) {
745 tevent_req_set_callback(subreq
, local_np_connect_retried
, req
);
748 static void local_np_connect_retried(struct tevent_req
*subreq
)
750 struct tevent_req
*req
= tevent_req_callback_data(
751 subreq
, struct tevent_req
);
752 struct local_np_connect_state
*state
= tevent_req_data(
753 req
, struct local_np_connect_state
);
756 ret
= np_sock_connect_recv(subreq
, state
, &state
->npa_stream
);
758 if (tevent_req_error(req
, ret
)) {
761 tevent_req_done(req
);
765 * @brief Receive handle to a local named pipe RPC interface
767 * @param[in] req The tevent_req that started the operation
768 * @param[in] ev The tevent context to use.
769 * @param[in] mem_ctx The memory context to put pstream on
770 * @param[out] pstream The established connection to the RPC server
775 int local_np_connect_recv(
776 struct tevent_req
*req
,
778 struct tstream_context
**pstream
)
780 struct local_np_connect_state
*state
= tevent_req_data(
781 req
, struct local_np_connect_state
);
784 if (tevent_req_is_unix_error(req
, &err
)) {
785 tevent_req_received(req
);
789 *pstream
= talloc_move(mem_ctx
, &state
->npa_stream
);
794 * @brief Sync connect to a local named pipe RPC interface
796 * Start "samba-dcerpcd" on demand if it does not exist
798 * @param[in] pipename The raw pipename to connect to without path
799 * @param[in] remote_client_name The client name to transmit
800 * @param[in] remote_client_addr The client addr to transmit
801 * @param[in] local_server_name The server name to transmit
802 * @param[in] local_server_addr The server addr to transmit
803 * @param[in] session_info The authorization info to use
804 * @param[in] need_idle_server Does this need to be an exclusive server?
805 * @param[in] mem_ctx The memory context to use.
806 * @param[out] pstream The established connection to the RPC server
810 int local_np_connect(
811 const char *pipename
,
812 enum dcerpc_transport_t transport
,
813 const char *remote_client_name
,
814 const struct tsocket_address
*remote_client_addr
,
815 const char *local_server_name
,
816 const struct tsocket_address
*local_server_addr
,
817 const struct auth_session_info
*session_info
,
818 bool need_idle_server
,
820 struct tstream_context
**pstream
)
822 struct tevent_context
*ev
= NULL
;
823 struct tevent_req
*req
= NULL
;
826 ev
= samba_tevent_context_init(mem_ctx
);
830 req
= local_np_connect_send(
844 if (!tevent_req_poll_unix(req
, ev
, &ret
)) {
847 ret
= local_np_connect_recv(req
, mem_ctx
, pstream
);