tests/krb5: Fix method for creating invalid length zeroed checksum
[Samba.git] / source3 / rpc_server / rpc_server.c
blob9e57bc345595ce77c6834fe8660de9819865b43d
1 /*
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/>.
22 #include "includes.h"
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"
27 #include "rpc_dce.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"
33 #include "auth.h"
34 #include "rpc_server/rpc_ncacn_np.h"
35 #include "rpc_server/srv_pipe_hnd.h"
36 #include "rpc_server/srv_pipe.h"
38 #undef DBGC_CLASS
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,
50 int *perrno)
52 struct pipes_struct *p;
53 int ret;
55 ret = make_base_pipes_struct(mem_ctx, msg_ctx, pipe_name,
56 transport,
57 remote_address, local_address, &p);
58 if (ret) {
59 *perrno = ret;
60 return -1;
63 *_p = p;
64 return 0;
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 {
71 int fd;
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,
83 uint16_t flags,
84 void *private_data);
86 NTSTATUS dcesrv_create_ncacn_np_socket(struct dcesrv_endpoint *e, int *out_fd)
88 char *np_dir = NULL;
89 int fd = -1;
90 NTSTATUS status;
91 const char *endpoint;
92 char *endpoint_normalized = NULL;
93 char *p = NULL;
95 endpoint = dcerpc_binding_get_string_option(e->ep_description,
96 "endpoint");
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) {
112 p += 6;
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));
124 goto out;
127 np_dir = talloc_asprintf(talloc_tos(), "%s/np", lp_ncalrpc_dir());
128 if (!np_dir) {
129 status = NT_STATUS_NO_MEMORY;
130 DBG_ERR("Out of memory\n");
131 goto out;
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));
138 goto out;
141 fd = create_pipe_sock(np_dir, p, 0700);
142 if (fd == -1) {
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));
146 goto out;
149 DBG_DEBUG("Opened pipe socket fd %d for %s\n", fd, p);
151 *out_fd = fd;
153 status = NT_STATUS_OK;
155 out:
156 TALLOC_FREE(endpoint_normalized);
157 TALLOC_FREE(np_dir);
158 return status;
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,
166 void *term_data)
168 struct dcerpc_ncacn_listen_state *state;
169 struct tevent_fd *fde;
170 int rc;
171 NTSTATUS status;
172 const char *endpoint = NULL;
174 endpoint = dcerpc_binding_get_string_option(e->ep_description,
175 "endpoint");
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);
185 if (state == NULL) {
186 DBG_ERR("Out of memory\n");
187 return NT_STATUS_NO_MEMORY;
189 state->fd = -1;
190 state->ev_ctx = ev_ctx;
191 state->msg_ctx = msg_ctx;
192 state->endpoint = e;
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)) {
199 goto out;
202 rc = listen(state->fd, 5);
203 if (rc < 0) {
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));
207 goto out;
210 DBG_DEBUG("Opened pipe socket fd %d for %s\n",
211 state->fd, endpoint);
213 errno = 0;
214 fde = tevent_add_fd(ev_ctx,
215 state, state->fd, TEVENT_FD_READ,
216 dcesrv_ncacn_np_listener, state);
217 if (fde == NULL) {
218 if (errno == 0) {
219 errno = ENOMEM;
221 status = map_nt_error_from_unix_common(errno);
222 DBG_ERR("Failed to add event handler for ncacn_np: %s\n",
223 strerror(errno));
224 goto out;
227 tevent_fd_set_auto_close(fde);
229 return NT_STATUS_OK;
231 out:
232 if (state->fd != -1) {
233 close(state->fd);
235 TALLOC_FREE(state);
236 return status;
239 static void dcesrv_ncacn_np_listener(struct tevent_context *ev,
240 struct tevent_fd *fde,
241 uint16_t flags,
242 void *private_data)
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),
250 int sd = -1;
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);
257 if (sd == -1) {
258 if (errno != EINTR) {
259 DEBUG(6, ("Failed to get a valid socket [%s]\n",
260 strerror(errno)));
262 return;
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");
270 close(sd);
271 return;
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,
278 state->msg_ctx,
279 state->dce_ctx,
280 state->endpoint,
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,
294 uint16_t flags,
295 void *private_data);
297 NTSTATUS dcesrv_create_ncacn_ip_tcp_socket(const struct sockaddr_storage *ifss,
298 uint16_t *port,
299 int *out_fd)
301 int fd = -1;
303 if (*port == 0) {
304 uint16_t i;
306 for (i = lp_rpc_low_port(); i <= lp_rpc_high_port(); i++) {
307 fd = open_socket_in(SOCK_STREAM,
310 ifss,
311 false);
312 if (fd >= 0) {
313 *port = i;
314 break;
317 } else {
318 fd = open_socket_in(SOCK_STREAM,
319 *port,
321 ifss,
322 true);
324 if (fd == -1) {
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);
331 *out_fd = fd;
333 return NT_STATUS_OK;
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,
342 void *term_data)
344 struct dcerpc_ncacn_listen_state *state = NULL;
345 struct tevent_fd *fde = NULL;
346 const char *endpoint = NULL;
347 uint16_t port = 0;
348 char port_str[6];
349 int rc;
350 NTSTATUS status;
352 endpoint = dcerpc_binding_get_string_option(e->ep_description,
353 "endpoint");
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);
362 if (state == NULL) {
363 DBG_ERR("Out of memory\n");
364 return NT_STATUS_NO_MEMORY;
367 state->fd = -1;
368 state->ev_ctx = ev_ctx;
369 state->msg_ctx = msg_ctx;
370 state->endpoint = e;
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)) {
377 goto out;
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);
386 if (rc < 0) {
387 status = map_nt_error_from_unix_common(errno);
388 goto out;
391 rc = listen(state->fd, SMBD_LISTEN_BACKLOG);
392 if (rc == -1) {
393 status = map_nt_error_from_unix_common(errno);
394 DBG_ERR("Failed to listen on ncacn_ip_tcp socket: %s\n",
395 strerror(errno));
396 goto out;
399 DBG_DEBUG("Opened socket fd %d for port %u\n",
400 state->fd, port);
402 errno = 0;
403 fde = tevent_add_fd(state->ev_ctx,
404 state,
405 state->fd,
406 TEVENT_FD_READ,
407 dcesrv_ncacn_ip_tcp_listener,
408 state);
409 if (fde == NULL) {
410 if (errno == 0) {
411 errno = ENOMEM;
413 status = map_nt_error_from_unix_common(errno);
414 DBG_ERR("Failed to add event handler for ncacn_ip_tcp: %s\n",
415 strerror(errno));
416 goto out;
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));
429 goto out;
432 return NT_STATUS_OK;
434 out:
435 if (state->fd != -1) {
436 close(state->fd);
438 TALLOC_FREE(state);
440 return status;
443 static void dcesrv_ncacn_ip_tcp_listener(struct tevent_context *ev,
444 struct tevent_fd *fde,
445 uint16_t flags,
446 void *private_data)
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),
456 int s = -1;
457 int rc;
459 s = accept(state->fd, &addr.u.sa, &addr.sa_socklen);
460 if (s == -1) {
461 if (errno != EINTR) {
462 DBG_ERR("Failed to accept: %s\n", strerror(errno));
464 return;
466 smb_set_close_on_exec(s);
468 rc = tsocket_address_bsd_from_samba_sockaddr(state, &addr, &cli_addr);
469 if (rc < 0) {
470 close(s);
471 return;
474 rc = getsockname(s, &addr.u.sa, &addr.sa_socklen);
475 if (rc < 0) {
476 close(s);
477 return;
480 rc = tsocket_address_bsd_from_samba_sockaddr(state, &addr, &srv_addr);
481 if (rc < 0) {
482 close(s);
483 return;
486 DBG_DEBUG("Accepted ncacn_ip_tcp socket %d\n", s);
488 dcerpc_ncacn_accept(state->ev_ctx,
489 state->msg_ctx,
490 state->dce_ctx,
491 state->endpoint,
492 cli_addr,
493 srv_addr,
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,
505 uint16_t flags,
506 void *private_data);
508 NTSTATUS dcesrv_create_ncalrpc_socket(struct dcesrv_endpoint *e, int *out_fd)
510 int fd = -1;
511 const char *endpoint = NULL;
512 NTSTATUS status;
514 endpoint = dcerpc_binding_get_string_option(e->ep_description,
515 "endpoint");
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) {
531 endpoint = "SMBD";
532 } else {
533 endpoint = "DEFAULT";
535 status = dcerpc_binding_set_string_option(e->ep_description,
536 "endpoint",
537 endpoint);
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));
542 return 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));
550 goto out;
553 fd = create_pipe_sock(lp_ncalrpc_dir(), endpoint, 0755);
554 if (fd == -1) {
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));
558 goto out;
561 DBG_DEBUG("Opened ncalrpc socket fd '%d' for '%s/%s'\n",
562 fd, lp_ncalrpc_dir(), endpoint);
564 *out_fd = fd;
566 return NT_STATUS_OK;
568 out:
569 return status;
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;
581 int rc;
582 NTSTATUS status;
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);
588 if (state == NULL) {
589 DBG_ERR("Out of memory\n");
590 return NT_STATUS_NO_MEMORY;
593 state->fd = -1;
594 state->ev_ctx = ev_ctx;
595 state->msg_ctx = msg_ctx;
596 state->dce_ctx = dce_ctx;
597 state->endpoint = e;
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",
604 nt_errstr(status));
605 goto out;
608 rc = listen(state->fd, 5);
609 if (rc < 0) {
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));
615 goto out;
618 /* Set server socket to non-blocking for the accept. */
619 rc = set_blocking(state->fd, false);
620 if (rc < 0) {
621 status = map_nt_error_from_unix_common(errno);
622 goto out;
625 errno = 0;
626 fde = tevent_add_fd(state->ev_ctx,
627 state,
628 state->fd,
629 TEVENT_FD_READ,
630 dcesrv_ncalrpc_listener,
631 state);
632 if (fde == NULL) {
633 if (errno == 0) {
634 errno = ENOMEM;
636 status = map_nt_error_from_unix_common(errno);
637 DBG_ERR("Failed to add event handler for ncalrpc: %s\n",
638 strerror(errno));
639 goto out;
642 tevent_fd_set_auto_close(fde);
644 return NT_STATUS_OK;
645 out:
646 if (state->fd != -1) {
647 close(state->fd);
649 TALLOC_FREE(state);
651 return status;
654 static void dcesrv_ncalrpc_listener(struct tevent_context *ev,
655 struct tevent_fd *fde,
656 uint16_t flags,
657 void *private_data)
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),
669 int sd = -1;
670 int rc;
671 const char *endpoint = NULL;
673 sd = accept(state->fd, &addr.u.sa, &addr.sa_socklen);
674 if (sd == -1) {
675 if (errno != EINTR) {
676 DBG_ERR("Failed to accept: %s\n", strerror(errno));
678 return;
680 smb_set_close_on_exec(sd);
682 rc = tsocket_address_bsd_from_samba_sockaddr(state, &addr, &cli_addr);
683 if (rc < 0) {
684 close(sd);
685 return;
688 rc = getsockname(sd, &addr_server.u.sa, &addr_server.sa_socklen);
689 if (rc < 0) {
690 close(sd);
691 return;
694 rc = tsocket_address_bsd_from_samba_sockaddr(state,
695 &addr_server,
696 &srv_addr);
697 if (rc < 0) {
698 close(sd);
699 return;
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");
706 close(sd);
707 return;
710 DBG_DEBUG("Accepted ncalrpc socket %s (fd: %d)\n",
711 addr.u.un.sun_path, sd);
713 dcerpc_ncacn_accept(state->ev_ctx,
714 state->msg_ctx,
715 state->dce_ctx,
716 state->endpoint,
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);
732 return 0;
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;
759 *out = ncacn_conn;
761 return NT_STATUS_OK;
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,
768 const char *reason);
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,
776 int s,
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;
783 NTSTATUS status;
784 int rc;
786 DBG_DEBUG("dcerpc_ncacn_accept\n");
788 status = dcerpc_ncacn_conn_init(ev_ctx,
789 ev_ctx,
790 msg_ctx,
791 dce_ctx,
793 termination_fn,
794 termination_data,
795 &ncacn_conn);
796 if (!NT_STATUS_IS_OK(status)) {
797 DBG_ERR("Failed to initialize dcerpc_ncacn_connection: %s\n",
798 nt_errstr(status));
799 close(s);
800 return;
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,
811 ncacn_conn);
812 } else {
813 ncacn_conn->remote_client_name =
814 tsocket_address_unix_path(ncacn_conn->remote_client_addr,
815 ncacn_conn);
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");
821 close(s);
822 return;
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,
832 ncacn_conn);
833 } else {
834 ncacn_conn->local_server_name =
835 tsocket_address_unix_path(ncacn_conn->local_server_addr,
836 ncacn_conn);
838 if (ncacn_conn->local_server_name == NULL) {
839 DBG_ERR("No memory\n");
840 ncacn_terminate_connection(ncacn_conn, "No memory");
841 close(s);
842 return;
846 rc = set_blocking(s, false);
847 if (rc < 0) {
848 DBG_WARNING("Failed to set dcerpc socket to non-blocking\n");
849 ncacn_terminate_connection(ncacn_conn, strerror(errno));
850 close(s);
851 return;
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);
859 if (rc < 0) {
860 DBG_WARNING("Failed to create tstream socket for dcerpc\n");
861 ncacn_terminate_connection(ncacn_conn, "No memory");
862 close(s);
863 return;
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,
873 ncacn_conn->ev_ctx,
874 ncacn_conn->tstream,
875 file_type,
876 device_state,
877 allocation_size);
878 if (subreq == NULL) {
879 ncacn_terminate_connection(ncacn_conn, "No memory");
880 return;
882 tevent_req_set_callback(subreq, dcesrv_ncacn_np_accept_done,
883 ncacn_conn);
884 return;
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;
894 int error;
895 int ret;
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);
910 TALLOC_FREE(subreq);
911 if (ret != 0) {
912 DBG_ERR("Failed to accept named pipe connection: %s\n",
913 strerror(error));
914 ncacn_terminate_connection(ncacn_conn, strerror(errno));
915 return;
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;
924 uid_t uid;
925 gid_t gid;
926 int rc;
927 int sys_errno;
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;
933 NTSTATUS status;
935 switch (transport) {
936 case NCACN_IP_TCP:
937 pipe_name = tsocket_address_string(ncacn_conn->remote_client_addr,
938 ncacn_conn);
939 if (pipe_name == NULL) {
940 DBG_ERR("No memory\n");
941 ncacn_terminate_connection(ncacn_conn, "No memory");
942 return;
945 break;
946 case NCALRPC:
947 rc = getpeereid(ncacn_conn->sock, &uid, &gid);
948 if (rc < 0) {
949 DEBUG(2, ("Failed to get ncalrpc connecting "
950 "uid - %s!\n", strerror(errno)));
951 } else {
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);
958 if (rc < 0) {
959 DBG_ERR("No memory\n");
960 ncacn_terminate_connection(ncacn_conn, "No memory");
961 return;
964 TALLOC_FREE(ncacn_conn->remote_client_name);
965 ncacn_conn->remote_client_name
966 = tsocket_address_unix_path(ncacn_conn->remote_client_addr,
967 ncacn_conn);
968 if (ncacn_conn->remote_client_name == NULL) {
969 DBG_ERR("No memory\n");
970 ncacn_terminate_connection(ncacn_conn, "No memory");
971 return;
976 FALL_THROUGH;
977 case NCACN_NP:
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");
982 return;
984 break;
985 default:
986 DBG_ERR("unknown dcerpc transport: %u!\n", transport);
987 ncacn_terminate_connection(ncacn_conn,
988 "Unknown DCE/RPC transport");
989 return;
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,
999 nt_errstr(status));
1000 return;
1004 rc = make_server_pipes_struct(ncacn_conn,
1005 ncacn_conn->msg_ctx,
1006 pipe_name,
1007 transport,
1008 ncacn_conn->remote_client_addr,
1009 ncacn_conn->local_server_addr,
1010 &ncacn_conn->p,
1011 &sys_errno);
1012 if (rc < 0) {
1013 DBG_ERR("Failed to create pipe struct: %s",
1014 strerror(sys_errno));
1015 ncacn_terminate_connection(ncacn_conn, strerror(sys_errno));
1016 return;
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,
1026 ncacn_conn,
1027 ncacn_conn->endpoint,
1028 ncacn_conn->session_info,
1029 ncacn_conn->ev_ctx,
1030 DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
1031 &dcesrv_conn);
1032 if (!NT_STATUS_IS_OK(status)) {
1033 DBG_ERR("Failed to connect to endpoint: %s\n",
1034 nt_errstr(status));
1035 ncacn_terminate_connection(ncacn_conn, nt_errstr(status));
1036 return;
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",
1050 nt_errstr(status));
1051 ncacn_terminate_connection(ncacn_conn, nt_errstr(status));
1052 return;
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",
1061 nt_errstr(status));
1062 ncacn_terminate_connection(ncacn_conn, nt_errstr(status));
1064 DBG_DEBUG("dcerpc_ncacn_accept done\n");
1066 return;
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;
1074 NTSTATUS status;
1076 if (out == NULL) {
1077 return NT_STATUS_INVALID_PARAMETER;
1080 status = auth_generic_prepare(mem_ctx,
1081 call->conn->remote_address,
1082 call->conn->local_address,
1083 "DCE/RPC",
1084 &gensec);
1085 if (!NT_STATUS_IS_OK(status)) {
1086 DBG_ERR("Failed to prepare gensec: %s\n", nt_errstr(status));
1087 return status;
1090 *out = gensec;
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;
1104 NTSTATUS status;
1106 if (frame == NULL) {
1107 DBG_ERR("No memory");
1108 return;
1111 if (transport == NCACN_NP) {
1112 transport_protection = AUTHZ_TRANSPORT_PROTECTION_SMB;
1115 become_root();
1116 status = make_auth4_context(frame, &auth4_context);
1117 unbecome_root();
1118 if (!NT_STATUS_IS_OK(status)) {
1119 DBG_ERR("Unable to make auth context for authz log.\n");
1120 TALLOC_FREE(frame);
1121 return;
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,
1133 "DCE/RPC",
1134 auth_type,
1135 transport_protection,
1136 auth->session_info);
1138 auth->auth_audited = true;
1140 TALLOC_FREE(frame);
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,
1180 const char *reason)
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,
1190 const char *reason)
1192 if (reason == NULL) {
1193 reason = "Unknown reason";
1196 DBG_NOTICE("Terminating connection - '%s'\n", reason);
1198 talloc_free(conn);
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) {
1213 continue;
1216 endpoint = dcerpc_binding_get_string_option(e->ep_description,
1217 "endpoint");
1218 if (endpoint == NULL) {
1219 continue;
1222 if (strncmp(endpoint, "\\pipe\\", 6) == 0) {
1223 endpoint += 6;
1226 if (strequal(endpoint, pipe_name)) {
1227 *out = e;
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: */