2 Unix SMB/Netbios implementation.
3 Generic infrstructure for RPC Daemons
4 Copyright (C) Simo Sorce 2010
5 Copyright (C) Andrew Bartlett 2011
6 Copyright (C) Andreas Schneider 2011
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "librpc/rpc/dcesrv_core.h"
24 #include "rpc_server/rpc_pipes.h"
25 #include "rpc_server/rpc_server.h"
26 #include "rpc_server/rpc_config.h"
28 #include "librpc/gen_ndr/netlogon.h"
29 #include "librpc/gen_ndr/auth.h"
30 #include "lib/tsocket/tsocket.h"
31 #include "libcli/named_pipe_auth/npa_tstream.h"
32 #include "../auth/auth_sam_reply.h"
34 #include "rpc_server/rpc_ncacn_np.h"
35 #include "rpc_server/srv_pipe_hnd.h"
36 #include "rpc_server/srv_pipe.h"
39 #define DBGC_CLASS DBGC_RPC_SRV
41 /* Creates a pipes_struct and initializes it with the information
42 * sent from the client */
43 int make_server_pipes_struct(TALLOC_CTX
*mem_ctx
,
44 struct messaging_context
*msg_ctx
,
45 const char *pipe_name
,
46 enum dcerpc_transport_t transport
,
47 const struct tsocket_address
*remote_address
,
48 const struct tsocket_address
*local_address
,
49 struct pipes_struct
**_p
,
52 struct pipes_struct
*p
;
55 ret
= make_base_pipes_struct(mem_ctx
, msg_ctx
, pipe_name
,
57 remote_address
, local_address
, &p
);
67 /* Start listening on the appropriate unix socket and setup all is needed to
68 * dispatch requests to the pipes rpc implementation */
70 struct dcerpc_ncacn_listen_state
{
73 struct tevent_context
*ev_ctx
;
74 struct messaging_context
*msg_ctx
;
75 struct dcesrv_context
*dce_ctx
;
76 struct dcesrv_endpoint
*endpoint
;
77 dcerpc_ncacn_termination_fn termination_fn
;
78 void *termination_data
;
81 static void dcesrv_ncacn_np_listener(struct tevent_context
*ev
,
82 struct tevent_fd
*fde
,
86 NTSTATUS
dcesrv_create_ncacn_np_socket(struct dcesrv_endpoint
*e
, int *out_fd
)
92 char *endpoint_normalized
= NULL
;
95 endpoint
= dcerpc_binding_get_string_option(e
->ep_description
,
97 if (endpoint
== NULL
) {
98 DBG_ERR("Endpoint mandatory for named pipes\n");
99 return NT_STATUS_INVALID_PARAMETER
;
102 /* The endpoint string from IDL can be mixed uppercase and case is
103 * normalized by smbd on connection */
104 endpoint_normalized
= strlower_talloc(talloc_tos(), endpoint
);
105 if (endpoint_normalized
== NULL
) {
106 return NT_STATUS_NO_MEMORY
;
109 /* The endpoint string from IDL can be prefixed by \pipe\ */
110 p
= endpoint_normalized
;
111 if (strncmp(p
, "\\pipe\\", 6) == 0) {
116 * As lp_ncalrpc_dir() should have 0755, but
117 * lp_ncalrpc_dir()/np should have 0700, we need to
118 * create lp_ncalrpc_dir() first.
120 if (!directory_create_or_exist(lp_ncalrpc_dir(), 0755)) {
121 status
= map_nt_error_from_unix_common(errno
);
122 DBG_ERR("Failed to create pipe directory %s - %s\n",
123 lp_ncalrpc_dir(), strerror(errno
));
127 np_dir
= talloc_asprintf(talloc_tos(), "%s/np", lp_ncalrpc_dir());
129 status
= NT_STATUS_NO_MEMORY
;
130 DBG_ERR("Out of memory\n");
134 if (!directory_create_or_exist_strict(np_dir
, geteuid(), 0700)) {
135 status
= map_nt_error_from_unix_common(errno
);
136 DBG_ERR("Failed to create pipe directory %s - %s\n",
137 np_dir
, strerror(errno
));
141 fd
= create_pipe_sock(np_dir
, p
, 0700);
143 status
= map_nt_error_from_unix_common(errno
);
144 DBG_ERR("Failed to create ncacn_np socket! '%s/%s': %s\n",
145 np_dir
, p
, strerror(errno
));
149 DBG_DEBUG("Opened pipe socket fd %d for %s\n", fd
, p
);
153 status
= NT_STATUS_OK
;
156 TALLOC_FREE(endpoint_normalized
);
161 NTSTATUS
dcesrv_setup_ncacn_np_socket(struct tevent_context
*ev_ctx
,
162 struct messaging_context
*msg_ctx
,
163 struct dcesrv_context
*dce_ctx
,
164 struct dcesrv_endpoint
*e
,
165 dcerpc_ncacn_termination_fn term_fn
,
168 struct dcerpc_ncacn_listen_state
*state
;
169 struct tevent_fd
*fde
;
172 const char *endpoint
= NULL
;
174 endpoint
= dcerpc_binding_get_string_option(e
->ep_description
,
176 if (endpoint
== NULL
) {
177 DBG_ERR("Endpoint mandatory for named pipes\n");
178 return NT_STATUS_INVALID_PARAMETER
;
181 /* Alloc in endpoint context. If the endpoint is freed (for example
182 * when forked daemons reinit the dcesrv_context, the tevent_fd
183 * listener will be stopped and the socket closed */
184 state
= talloc_zero(e
, struct dcerpc_ncacn_listen_state
);
186 DBG_ERR("Out of memory\n");
187 return NT_STATUS_NO_MEMORY
;
190 state
->ev_ctx
= ev_ctx
;
191 state
->msg_ctx
= msg_ctx
;
193 state
->dce_ctx
= dce_ctx
;
194 state
->termination_fn
= term_fn
;
195 state
->termination_data
= term_data
;
197 status
= dcesrv_create_ncacn_np_socket(e
, &state
->fd
);
198 if (!NT_STATUS_IS_OK(status
)) {
202 rc
= listen(state
->fd
, 5);
204 status
= map_nt_error_from_unix_common(errno
);
205 DBG_ERR("Failed to listen on ncacn_np socket %s: %s\n",
206 endpoint
, strerror(errno
));
210 DBG_DEBUG("Opened pipe socket fd %d for %s\n",
211 state
->fd
, endpoint
);
214 fde
= tevent_add_fd(ev_ctx
,
215 state
, state
->fd
, TEVENT_FD_READ
,
216 dcesrv_ncacn_np_listener
, state
);
221 status
= map_nt_error_from_unix_common(errno
);
222 DBG_ERR("Failed to add event handler for ncacn_np: %s\n",
227 tevent_fd_set_auto_close(fde
);
232 if (state
->fd
!= -1) {
239 static void dcesrv_ncacn_np_listener(struct tevent_context
*ev
,
240 struct tevent_fd
*fde
,
244 struct dcerpc_ncacn_listen_state
*state
=
245 talloc_get_type_abort(private_data
,
246 struct dcerpc_ncacn_listen_state
);
247 struct samba_sockaddr addr
= {
248 .sa_socklen
= sizeof(struct sockaddr_un
),
251 const char *endpoint
= NULL
;
253 /* TODO: should we have a limit to the number of clients ? */
255 sd
= accept(state
->fd
, &addr
.u
.sa
, &addr
.sa_socklen
);
258 if (errno
!= EINTR
) {
259 DEBUG(6, ("Failed to get a valid socket [%s]\n",
264 smb_set_close_on_exec(sd
);
266 endpoint
= dcerpc_binding_get_string_option(
267 state
->endpoint
->ep_description
, "endpoint");
268 if (endpoint
== NULL
) {
269 DBG_ERR("Failed to get endpoint from binding description\n");
274 DBG_DEBUG("Accepted ncacn_np socket %s (fd: %d)\n",
275 addr
.u
.un
.sun_path
, sd
);
277 dcerpc_ncacn_accept(state
->ev_ctx
,
281 NULL
, /* remote client address */
282 NULL
, /* local server address */
284 state
->termination_fn
,
285 state
->termination_data
);
288 /********************************************************************
289 * Start listening on the tcp/ip socket
290 ********************************************************************/
292 static void dcesrv_ncacn_ip_tcp_listener(struct tevent_context
*ev
,
293 struct tevent_fd
*fde
,
297 NTSTATUS
dcesrv_create_ncacn_ip_tcp_socket(const struct sockaddr_storage
*ifss
,
306 for (i
= lp_rpc_low_port(); i
<= lp_rpc_high_port(); i
++) {
307 fd
= open_socket_in(SOCK_STREAM
,
318 fd
= open_socket_in(SOCK_STREAM
,
325 DBG_ERR("Failed to create socket on port %u!\n", *port
);
326 return NT_STATUS_UNSUCCESSFUL
;
329 DBG_DEBUG("Opened ncacn_ip_tcp socket fd %d for port %u\n", fd
, *port
);
336 NTSTATUS
dcesrv_setup_ncacn_ip_tcp_socket(struct tevent_context
*ev_ctx
,
337 struct messaging_context
*msg_ctx
,
338 struct dcesrv_context
*dce_ctx
,
339 struct dcesrv_endpoint
*e
,
340 const struct sockaddr_storage
*ifss
,
341 dcerpc_ncacn_termination_fn term_fn
,
344 struct dcerpc_ncacn_listen_state
*state
= NULL
;
345 struct tevent_fd
*fde
= NULL
;
346 const char *endpoint
= NULL
;
352 endpoint
= dcerpc_binding_get_string_option(e
->ep_description
,
354 if (endpoint
!= NULL
) {
355 port
= atoi(endpoint
);
358 /* Alloc in endpoint context. If the endpoint is freed (for example
359 * when forked daemons reinit the dcesrv_context, the tevent_fd
360 * listener will be stopped and the socket closed */
361 state
= talloc_zero(e
, struct dcerpc_ncacn_listen_state
);
363 DBG_ERR("Out of memory\n");
364 return NT_STATUS_NO_MEMORY
;
368 state
->ev_ctx
= ev_ctx
;
369 state
->msg_ctx
= msg_ctx
;
371 state
->dce_ctx
= dce_ctx
;
372 state
->termination_fn
= term_fn
;
373 state
->termination_data
= term_data
;
375 status
= dcesrv_create_ncacn_ip_tcp_socket(ifss
, &port
, &state
->fd
);
376 if (!NT_STATUS_IS_OK(status
)) {
380 /* ready to listen */
381 set_socket_options(state
->fd
, "SO_KEEPALIVE");
382 set_socket_options(state
->fd
, lp_socket_options());
384 /* Set server socket to non-blocking for the accept. */
385 rc
= set_blocking(state
->fd
, false);
387 status
= map_nt_error_from_unix_common(errno
);
391 rc
= listen(state
->fd
, SMBD_LISTEN_BACKLOG
);
393 status
= map_nt_error_from_unix_common(errno
);
394 DBG_ERR("Failed to listen on ncacn_ip_tcp socket: %s\n",
399 DBG_DEBUG("Opened socket fd %d for port %u\n",
403 fde
= tevent_add_fd(state
->ev_ctx
,
407 dcesrv_ncacn_ip_tcp_listener
,
413 status
= map_nt_error_from_unix_common(errno
);
414 DBG_ERR("Failed to add event handler for ncacn_ip_tcp: %s\n",
419 tevent_fd_set_auto_close(fde
);
421 /* Set the port in the endpoint */
422 snprintf(port_str
, sizeof(port_str
), "%u", port
);
424 status
= dcerpc_binding_set_string_option(e
->ep_description
,
425 "endpoint", port_str
);
426 if (!NT_STATUS_IS_OK(status
)) {
427 DBG_ERR("Failed to set binding endpoint '%s': %s\n",
428 port_str
, nt_errstr(status
));
435 if (state
->fd
!= -1) {
443 static void dcesrv_ncacn_ip_tcp_listener(struct tevent_context
*ev
,
444 struct tevent_fd
*fde
,
448 struct dcerpc_ncacn_listen_state
*state
=
449 talloc_get_type_abort(private_data
,
450 struct dcerpc_ncacn_listen_state
);
451 struct tsocket_address
*cli_addr
= NULL
;
452 struct tsocket_address
*srv_addr
= NULL
;
453 struct samba_sockaddr addr
= {
454 .sa_socklen
= sizeof(struct sockaddr_storage
),
459 s
= accept(state
->fd
, &addr
.u
.sa
, &addr
.sa_socklen
);
461 if (errno
!= EINTR
) {
462 DBG_ERR("Failed to accept: %s\n", strerror(errno
));
466 smb_set_close_on_exec(s
);
468 rc
= tsocket_address_bsd_from_samba_sockaddr(state
, &addr
, &cli_addr
);
474 rc
= getsockname(s
, &addr
.u
.sa
, &addr
.sa_socklen
);
480 rc
= tsocket_address_bsd_from_samba_sockaddr(state
, &addr
, &srv_addr
);
486 DBG_DEBUG("Accepted ncacn_ip_tcp socket %d\n", s
);
488 dcerpc_ncacn_accept(state
->ev_ctx
,
495 state
->termination_fn
,
496 state
->termination_data
);
499 /********************************************************************
500 * Start listening on the ncalrpc socket
501 ********************************************************************/
503 static void dcesrv_ncalrpc_listener(struct tevent_context
*ev
,
504 struct tevent_fd
*fde
,
508 NTSTATUS
dcesrv_create_ncalrpc_socket(struct dcesrv_endpoint
*e
, int *out_fd
)
511 const char *endpoint
= NULL
;
514 endpoint
= dcerpc_binding_get_string_option(e
->ep_description
,
516 if (endpoint
== NULL
) {
518 * No identifier specified: use DEFAULT or SMBD.
520 * When role is AD DC we run two rpc server instances, the one
521 * started by 'samba' and the one embedded in 'smbd'.
522 * Avoid listening in DEFAULT socket for NCALRPC as both
523 * servers will race to accept connections. In this case smbd
524 * will listen in SMBD socket and rpcint binding handle
525 * implementation will pick the right socket to use.
527 * TODO: DO NOT hardcode this value anywhere else. Rather,
528 * specify no endpoint and let the epmapper worry about it.
530 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
) {
533 endpoint
= "DEFAULT";
535 status
= dcerpc_binding_set_string_option(e
->ep_description
,
538 if (!NT_STATUS_IS_OK(status
)) {
539 DBG_ERR("Failed to set ncalrpc 'endpoint' binding "
540 "string option to '%s': %s\n",
541 endpoint
, nt_errstr(status
));
546 if (!directory_create_or_exist(lp_ncalrpc_dir(), 0755)) {
547 status
= map_nt_error_from_unix_common(errno
);
548 DBG_ERR("Failed to create ncalrpc directory '%s': %s\n",
549 lp_ncalrpc_dir(), strerror(errno
));
553 fd
= create_pipe_sock(lp_ncalrpc_dir(), endpoint
, 0755);
555 status
= map_nt_error_from_unix_common(errno
);
556 DBG_ERR("Failed to create ncalrpc socket '%s/%s': %s\n",
557 lp_ncalrpc_dir(), endpoint
, strerror(errno
));
561 DBG_DEBUG("Opened ncalrpc socket fd '%d' for '%s/%s'\n",
562 fd
, lp_ncalrpc_dir(), endpoint
);
572 NTSTATUS
dcesrv_setup_ncalrpc_socket(struct tevent_context
*ev_ctx
,
573 struct messaging_context
*msg_ctx
,
574 struct dcesrv_context
*dce_ctx
,
575 struct dcesrv_endpoint
*e
,
576 dcerpc_ncacn_termination_fn term_fn
,
577 void *termination_data
)
579 struct dcerpc_ncacn_listen_state
*state
;
580 struct tevent_fd
*fde
;
584 /* Alloc in endpoint context. If the endpoint is freed (for example
585 * when forked daemons reinit the dcesrv_context, the tevent_fd
586 * listener will be stopped and the socket closed */
587 state
= talloc_zero(e
, struct dcerpc_ncacn_listen_state
);
589 DBG_ERR("Out of memory\n");
590 return NT_STATUS_NO_MEMORY
;
594 state
->ev_ctx
= ev_ctx
;
595 state
->msg_ctx
= msg_ctx
;
596 state
->dce_ctx
= dce_ctx
;
598 state
->termination_fn
= term_fn
;
599 state
->termination_data
= termination_data
;
601 status
= dcesrv_create_ncalrpc_socket(e
, &state
->fd
);
602 if (!NT_STATUS_IS_OK(status
)) {
603 DBG_ERR("Failed to create ncalrpc socket: %s\n",
608 rc
= listen(state
->fd
, 5);
610 const char *endpoint
= dcerpc_binding_get_string_option(
611 e
->ep_description
, "endpoint");
612 status
= map_nt_error_from_unix_common(errno
);
613 DBG_ERR("Failed to listen on ncalrpc socket %s: %s\n",
614 endpoint
, strerror(errno
));
618 /* Set server socket to non-blocking for the accept. */
619 rc
= set_blocking(state
->fd
, false);
621 status
= map_nt_error_from_unix_common(errno
);
626 fde
= tevent_add_fd(state
->ev_ctx
,
630 dcesrv_ncalrpc_listener
,
636 status
= map_nt_error_from_unix_common(errno
);
637 DBG_ERR("Failed to add event handler for ncalrpc: %s\n",
642 tevent_fd_set_auto_close(fde
);
646 if (state
->fd
!= -1) {
654 static void dcesrv_ncalrpc_listener(struct tevent_context
*ev
,
655 struct tevent_fd
*fde
,
659 struct dcerpc_ncacn_listen_state
*state
=
660 talloc_get_type_abort(private_data
,
661 struct dcerpc_ncacn_listen_state
);
662 struct tsocket_address
*cli_addr
= NULL
, *srv_addr
= NULL
;
663 struct samba_sockaddr addr
= {
664 .sa_socklen
= sizeof(struct sockaddr_un
),
666 struct samba_sockaddr addr_server
= {
667 .sa_socklen
= sizeof(struct sockaddr_un
),
671 const char *endpoint
= NULL
;
673 sd
= accept(state
->fd
, &addr
.u
.sa
, &addr
.sa_socklen
);
675 if (errno
!= EINTR
) {
676 DBG_ERR("Failed to accept: %s\n", strerror(errno
));
680 smb_set_close_on_exec(sd
);
682 rc
= tsocket_address_bsd_from_samba_sockaddr(state
, &addr
, &cli_addr
);
688 rc
= getsockname(sd
, &addr_server
.u
.sa
, &addr_server
.sa_socklen
);
694 rc
= tsocket_address_bsd_from_samba_sockaddr(state
,
702 endpoint
= dcerpc_binding_get_string_option(
703 state
->endpoint
->ep_description
, "endpoint");
704 if (endpoint
== NULL
) {
705 DBG_ERR("Failed to get endpoint from binding description\n");
710 DBG_DEBUG("Accepted ncalrpc socket %s (fd: %d)\n",
711 addr
.u
.un
.sun_path
, sd
);
713 dcerpc_ncacn_accept(state
->ev_ctx
,
717 cli_addr
, srv_addr
, sd
,
718 state
->termination_fn
,
719 state
->termination_data
);
722 static int dcesrv_connection_destructor(struct dcesrv_connection
*conn
)
724 struct dcerpc_ncacn_conn
*ncacn_conn
= talloc_get_type_abort(
725 conn
->transport
.private_data
,
726 struct dcerpc_ncacn_conn
);
728 if (ncacn_conn
->termination_fn
!= NULL
) {
729 ncacn_conn
->termination_fn(conn
, ncacn_conn
->termination_data
);
735 NTSTATUS
dcerpc_ncacn_conn_init(TALLOC_CTX
*mem_ctx
,
736 struct tevent_context
*ev_ctx
,
737 struct messaging_context
*msg_ctx
,
738 struct dcesrv_context
*dce_ctx
,
739 struct dcesrv_endpoint
*endpoint
,
740 dcerpc_ncacn_termination_fn term_fn
,
741 void *termination_data
,
742 struct dcerpc_ncacn_conn
**out
)
744 struct dcerpc_ncacn_conn
*ncacn_conn
= NULL
;
746 ncacn_conn
= talloc_zero(mem_ctx
, struct dcerpc_ncacn_conn
);
747 if (ncacn_conn
== NULL
) {
748 return NT_STATUS_NO_MEMORY
;
751 ncacn_conn
->ev_ctx
= ev_ctx
;
752 ncacn_conn
->msg_ctx
= msg_ctx
;
753 ncacn_conn
->dce_ctx
= dce_ctx
;
754 ncacn_conn
->endpoint
= endpoint
;
755 ncacn_conn
->sock
= -1;
756 ncacn_conn
->termination_fn
= term_fn
;
757 ncacn_conn
->termination_data
= termination_data
;
764 static void dcesrv_ncacn_np_accept_done(struct tevent_req
*subreq
);
765 static void dcesrv_ncacn_accept_step2(struct dcerpc_ncacn_conn
*ncacn_conn
);
767 static void ncacn_terminate_connection(struct dcerpc_ncacn_conn
*conn
,
770 void dcerpc_ncacn_accept(struct tevent_context
*ev_ctx
,
771 struct messaging_context
*msg_ctx
,
772 struct dcesrv_context
*dce_ctx
,
773 struct dcesrv_endpoint
*e
,
774 struct tsocket_address
*cli_addr
,
775 struct tsocket_address
*srv_addr
,
777 dcerpc_ncacn_termination_fn termination_fn
,
778 void *termination_data
)
780 enum dcerpc_transport_t transport
=
781 dcerpc_binding_get_transport(e
->ep_description
);
782 struct dcerpc_ncacn_conn
*ncacn_conn
;
786 DBG_DEBUG("dcerpc_ncacn_accept\n");
788 status
= dcerpc_ncacn_conn_init(ev_ctx
,
796 if (!NT_STATUS_IS_OK(status
)) {
797 DBG_ERR("Failed to initialize dcerpc_ncacn_connection: %s\n",
803 ncacn_conn
->sock
= s
;
805 if (cli_addr
!= NULL
) {
806 ncacn_conn
->remote_client_addr
= talloc_move(ncacn_conn
, &cli_addr
);
808 if (tsocket_address_is_inet(ncacn_conn
->remote_client_addr
, "ip")) {
809 ncacn_conn
->remote_client_name
=
810 tsocket_address_inet_addr_string(ncacn_conn
->remote_client_addr
,
813 ncacn_conn
->remote_client_name
=
814 tsocket_address_unix_path(ncacn_conn
->remote_client_addr
,
818 if (ncacn_conn
->remote_client_name
== NULL
) {
819 DBG_ERR("Out of memory obtaining remote socket address as a string!\n");
820 ncacn_terminate_connection(ncacn_conn
, "No memory");
826 if (srv_addr
!= NULL
) {
827 ncacn_conn
->local_server_addr
= talloc_move(ncacn_conn
, &srv_addr
);
829 if (tsocket_address_is_inet(ncacn_conn
->local_server_addr
, "ip")) {
830 ncacn_conn
->local_server_name
=
831 tsocket_address_inet_addr_string(ncacn_conn
->local_server_addr
,
834 ncacn_conn
->local_server_name
=
835 tsocket_address_unix_path(ncacn_conn
->local_server_addr
,
838 if (ncacn_conn
->local_server_name
== NULL
) {
839 DBG_ERR("No memory\n");
840 ncacn_terminate_connection(ncacn_conn
, "No memory");
846 rc
= set_blocking(s
, false);
848 DBG_WARNING("Failed to set dcerpc socket to non-blocking\n");
849 ncacn_terminate_connection(ncacn_conn
, strerror(errno
));
855 * As soon as we have tstream_bsd_existing_socket set up it will
856 * take care of closing the socket.
858 rc
= tstream_bsd_existing_socket(ncacn_conn
, s
, &ncacn_conn
->tstream
);
860 DBG_WARNING("Failed to create tstream socket for dcerpc\n");
861 ncacn_terminate_connection(ncacn_conn
, "No memory");
866 if (transport
== NCACN_NP
) {
867 struct tevent_req
*subreq
= NULL
;
868 uint64_t allocation_size
= 4096;
869 uint16_t device_state
= 0xff | 0x0400 | 0x0100;
870 uint16_t file_type
= FILE_TYPE_MESSAGE_MODE_PIPE
;
872 subreq
= tstream_npa_accept_existing_send(ncacn_conn
,
878 if (subreq
== NULL
) {
879 ncacn_terminate_connection(ncacn_conn
, "No memory");
882 tevent_req_set_callback(subreq
, dcesrv_ncacn_np_accept_done
,
887 dcesrv_ncacn_accept_step2(ncacn_conn
);
890 static void dcesrv_ncacn_np_accept_done(struct tevent_req
*subreq
)
892 struct auth_session_info_transport
*session_info_transport
= NULL
;
893 struct dcerpc_ncacn_conn
*ncacn_conn
= NULL
;
897 ncacn_conn
= tevent_req_callback_data(subreq
,
898 struct dcerpc_ncacn_conn
);
900 ret
= tstream_npa_accept_existing_recv(subreq
, &error
, ncacn_conn
,
901 &ncacn_conn
->tstream
,
902 &ncacn_conn
->remote_client_addr
,
903 &ncacn_conn
->remote_client_name
,
904 &ncacn_conn
->local_server_addr
,
905 &ncacn_conn
->local_server_name
,
906 &session_info_transport
);
907 ncacn_conn
->session_info
= talloc_move(ncacn_conn
,
908 &session_info_transport
->session_info
);
912 DBG_ERR("Failed to accept named pipe connection: %s\n",
914 ncacn_terminate_connection(ncacn_conn
, strerror(errno
));
918 dcesrv_ncacn_accept_step2(ncacn_conn
);
921 static void dcesrv_ncacn_accept_step2(struct dcerpc_ncacn_conn
*ncacn_conn
)
923 char *pipe_name
= NULL
;
928 enum dcerpc_transport_t transport
= dcerpc_binding_get_transport(
929 ncacn_conn
->endpoint
->ep_description
);
930 const char *endpoint
= dcerpc_binding_get_string_option(
931 ncacn_conn
->endpoint
->ep_description
, "endpoint");
932 struct dcesrv_connection
*dcesrv_conn
= NULL
;
937 pipe_name
= tsocket_address_string(ncacn_conn
->remote_client_addr
,
939 if (pipe_name
== NULL
) {
940 DBG_ERR("No memory\n");
941 ncacn_terminate_connection(ncacn_conn
, "No memory");
947 rc
= getpeereid(ncacn_conn
->sock
, &uid
, &gid
);
949 DEBUG(2, ("Failed to get ncalrpc connecting "
950 "uid - %s!\n", strerror(errno
)));
952 if (uid
== sec_initial_uid()) {
953 TALLOC_FREE(ncacn_conn
->remote_client_addr
);
955 rc
= tsocket_address_unix_from_path(ncacn_conn
,
956 AS_SYSTEM_MAGIC_PATH_TOKEN
,
957 &ncacn_conn
->remote_client_addr
);
959 DBG_ERR("No memory\n");
960 ncacn_terminate_connection(ncacn_conn
, "No memory");
964 TALLOC_FREE(ncacn_conn
->remote_client_name
);
965 ncacn_conn
->remote_client_name
966 = tsocket_address_unix_path(ncacn_conn
->remote_client_addr
,
968 if (ncacn_conn
->remote_client_name
== NULL
) {
969 DBG_ERR("No memory\n");
970 ncacn_terminate_connection(ncacn_conn
, "No memory");
978 pipe_name
= talloc_strdup(ncacn_conn
, endpoint
);
979 if (pipe_name
== NULL
) {
980 DBG_ERR("No memory\n");
981 ncacn_terminate_connection(ncacn_conn
, "No memory");
986 DBG_ERR("unknown dcerpc transport: %u!\n", transport
);
987 ncacn_terminate_connection(ncacn_conn
,
988 "Unknown DCE/RPC transport");
992 if (ncacn_conn
->session_info
== NULL
) {
993 status
= make_session_info_anonymous(ncacn_conn
,
994 &ncacn_conn
->session_info
);
995 if (!NT_STATUS_IS_OK(status
)) {
996 DBG_ERR("Failed to create anonymous session info: "
997 "%s\n", nt_errstr(status
));
998 ncacn_terminate_connection(ncacn_conn
,
1004 rc
= make_server_pipes_struct(ncacn_conn
,
1005 ncacn_conn
->msg_ctx
,
1008 ncacn_conn
->remote_client_addr
,
1009 ncacn_conn
->local_server_addr
,
1013 DBG_ERR("Failed to create pipe struct: %s",
1014 strerror(sys_errno
));
1015 ncacn_terminate_connection(ncacn_conn
, strerror(sys_errno
));
1020 * This fills in dcesrv_conn->endpoint with the endpoint
1021 * associated with the socket. From this point on we know
1022 * which (group of) services we are handling, but not the
1023 * specific interface.
1025 status
= dcesrv_endpoint_connect(ncacn_conn
->dce_ctx
,
1027 ncacn_conn
->endpoint
,
1028 ncacn_conn
->session_info
,
1030 DCESRV_CALL_STATE_FLAG_MAY_ASYNC
,
1032 if (!NT_STATUS_IS_OK(status
)) {
1033 DBG_ERR("Failed to connect to endpoint: %s\n",
1035 ncacn_terminate_connection(ncacn_conn
, nt_errstr(status
));
1038 talloc_set_destructor(dcesrv_conn
, dcesrv_connection_destructor
);
1040 dcesrv_conn
->transport
.private_data
= ncacn_conn
;
1041 dcesrv_conn
->transport
.report_output_data
=
1042 dcesrv_sock_report_output_data
;
1043 dcesrv_conn
->transport
.terminate_connection
=
1044 dcesrv_transport_terminate_connection
;
1045 dcesrv_conn
->send_queue
= tevent_queue_create(dcesrv_conn
,
1046 "dcesrv send queue");
1047 if (dcesrv_conn
->send_queue
== NULL
) {
1048 status
= NT_STATUS_NO_MEMORY
;
1049 DBG_ERR("Failed to create send queue: %s\n",
1051 ncacn_terminate_connection(ncacn_conn
, nt_errstr(status
));
1055 dcesrv_conn
->stream
= talloc_move(dcesrv_conn
, &ncacn_conn
->tstream
);
1056 dcesrv_conn
->local_address
= ncacn_conn
->local_server_addr
;
1057 dcesrv_conn
->remote_address
= ncacn_conn
->remote_client_addr
;
1058 status
= dcesrv_connection_loop_start(dcesrv_conn
);
1059 if (!NT_STATUS_IS_OK(status
)) {
1060 DBG_ERR("Failed to start dcesrv_connection loop: %s\n",
1062 ncacn_terminate_connection(ncacn_conn
, nt_errstr(status
));
1064 DBG_DEBUG("dcerpc_ncacn_accept done\n");
1069 NTSTATUS
dcesrv_auth_gensec_prepare(TALLOC_CTX
*mem_ctx
,
1070 struct dcesrv_call_state
*call
,
1071 struct gensec_security
**out
)
1073 struct gensec_security
*gensec
= NULL
;
1077 return NT_STATUS_INVALID_PARAMETER
;
1080 status
= auth_generic_prepare(mem_ctx
,
1081 call
->conn
->remote_address
,
1082 call
->conn
->local_address
,
1085 if (!NT_STATUS_IS_OK(status
)) {
1086 DBG_ERR("Failed to prepare gensec: %s\n", nt_errstr(status
));
1092 return NT_STATUS_OK
;
1095 void dcesrv_log_successful_authz(struct dcesrv_call_state
*call
)
1097 TALLOC_CTX
*frame
= talloc_stackframe();
1098 struct auth4_context
*auth4_context
= NULL
;
1099 struct dcesrv_auth
*auth
= call
->auth_state
;
1100 enum dcerpc_transport_t transport
= dcerpc_binding_get_transport(
1101 call
->conn
->endpoint
->ep_description
);
1102 const char *auth_type
= derpc_transport_string_by_transport(transport
);
1103 const char *transport_protection
= AUTHZ_TRANSPORT_PROTECTION_NONE
;
1106 if (frame
== NULL
) {
1107 DBG_ERR("No memory");
1111 if (transport
== NCACN_NP
) {
1112 transport_protection
= AUTHZ_TRANSPORT_PROTECTION_SMB
;
1116 status
= make_auth4_context(frame
, &auth4_context
);
1118 if (!NT_STATUS_IS_OK(status
)) {
1119 DBG_ERR("Unable to make auth context for authz log.\n");
1125 * Log the authorization to this RPC interface. This
1126 * covered ncacn_np pass-through auth, and anonymous
1127 * DCE/RPC (eg epmapper, netlogon etc)
1129 log_successful_authz_event(auth4_context
->msg_ctx
,
1130 auth4_context
->lp_ctx
,
1131 call
->conn
->remote_address
,
1132 call
->conn
->local_address
,
1135 transport_protection
,
1136 auth
->session_info
);
1138 auth
->auth_audited
= true;
1143 static NTSTATUS
dcesrv_assoc_group_new(struct dcesrv_call_state
*call
,
1144 uint32_t assoc_group_id
)
1146 struct dcesrv_connection
*conn
= call
->conn
;
1147 struct dcesrv_context
*dce_ctx
= conn
->dce_ctx
;
1148 const struct dcesrv_endpoint
*endpoint
= conn
->endpoint
;
1149 enum dcerpc_transport_t transport
=
1150 dcerpc_binding_get_transport(endpoint
->ep_description
);
1151 struct dcesrv_assoc_group
*assoc_group
= NULL
;
1153 assoc_group
= talloc_zero(conn
, struct dcesrv_assoc_group
);
1154 if (assoc_group
== NULL
) {
1155 return NT_STATUS_NO_MEMORY
;
1158 assoc_group
->transport
= transport
;
1159 assoc_group
->id
= assoc_group_id
;
1160 assoc_group
->dce_ctx
= dce_ctx
;
1162 call
->conn
->assoc_group
= assoc_group
;
1164 return NT_STATUS_OK
;
1167 NTSTATUS
dcesrv_assoc_group_find(struct dcesrv_call_state
*call
)
1169 uint32_t assoc_group_id
= call
->pkt
.u
.bind
.assoc_group_id
;
1171 /* If not requested by client create a new association group */
1172 if (assoc_group_id
== 0) {
1173 assoc_group_id
= 0x53F0;
1176 return dcesrv_assoc_group_new(call
, assoc_group_id
);
1179 void dcesrv_transport_terminate_connection(struct dcesrv_connection
*dce_conn
,
1182 struct dcerpc_ncacn_conn
*ncacn_conn
= talloc_get_type_abort(
1183 dce_conn
->transport
.private_data
,
1184 struct dcerpc_ncacn_conn
);
1186 ncacn_terminate_connection(ncacn_conn
, reason
);
1189 static void ncacn_terminate_connection(struct dcerpc_ncacn_conn
*conn
,
1192 if (reason
== NULL
) {
1193 reason
= "Unknown reason";
1196 DBG_NOTICE("Terminating connection - '%s'\n", reason
);
1201 NTSTATUS
dcesrv_endpoint_by_ncacn_np_name(struct dcesrv_context
*dce_ctx
,
1202 const char *pipe_name
,
1203 struct dcesrv_endpoint
**out
)
1205 struct dcesrv_endpoint
*e
= NULL
;
1207 for (e
= dce_ctx
->endpoint_list
; e
; e
= e
->next
) {
1208 enum dcerpc_transport_t transport
=
1209 dcerpc_binding_get_transport(e
->ep_description
);
1210 const char *endpoint
= NULL
;
1212 if (transport
!= NCACN_NP
) {
1216 endpoint
= dcerpc_binding_get_string_option(e
->ep_description
,
1218 if (endpoint
== NULL
) {
1222 if (strncmp(endpoint
, "\\pipe\\", 6) == 0) {
1226 if (strequal(endpoint
, pipe_name
)) {
1228 return NT_STATUS_OK
;
1232 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
1235 struct pipes_struct
*dcesrv_get_pipes_struct(struct dcesrv_connection
*conn
)
1237 struct dcerpc_ncacn_conn
*ncacn_conn
= talloc_get_type_abort(
1238 conn
->transport
.private_data
,
1239 struct dcerpc_ncacn_conn
);
1241 return ncacn_conn
->p
;
1244 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */