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: */