talloc: version 2.1.10
[Samba.git] / source3 / rpc_server / rpc_server.c
blob81cc6756891e73dc896b3bca3f4cf1aa97fbfddc
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 "rpc_server/rpc_pipes.h"
24 #include "rpc_server/rpc_server.h"
25 #include "rpc_server/rpc_config.h"
26 #include "rpc_dce.h"
27 #include "librpc/gen_ndr/netlogon.h"
28 #include "librpc/gen_ndr/auth.h"
29 #include "lib/tsocket/tsocket.h"
30 #include "libcli/named_pipe_auth/npa_tstream.h"
31 #include "../auth/auth_sam_reply.h"
32 #include "auth.h"
33 #include "rpc_server/rpc_ncacn_np.h"
34 #include "rpc_server/srv_pipe_hnd.h"
35 #include "rpc_server/srv_pipe.h"
37 /* Creates a pipes_struct and initializes it with the information
38 * sent from the client */
39 int make_server_pipes_struct(TALLOC_CTX *mem_ctx,
40 struct messaging_context *msg_ctx,
41 const char *pipe_name,
42 enum dcerpc_transport_t transport,
43 const struct tsocket_address *remote_address,
44 const struct tsocket_address *local_address,
45 struct auth_session_info *session_info,
46 struct pipes_struct **_p,
47 int *perrno)
49 struct pipes_struct *p;
50 int ret;
52 ret = make_base_pipes_struct(mem_ctx, msg_ctx, pipe_name,
53 transport, RPC_LITTLE_ENDIAN,
54 remote_address, local_address, &p);
55 if (ret) {
56 *perrno = ret;
57 return -1;
60 if (session_info->unix_token && session_info->unix_info && session_info->security_token) {
61 /* Don't call create_local_token(), we already have the full details here */
62 p->session_info = talloc_steal(p, session_info);
64 } else {
65 DEBUG(0, ("Supplied session_info in make_server_pipes_struct was incomplete!"));
66 *perrno = EINVAL;
67 return -1;
70 *_p = p;
71 return 0;
74 /* Start listening on the appropriate unix socket and setup all is needed to
75 * dispatch requests to the pipes rpc implementation */
77 struct dcerpc_ncacn_listen_state {
78 struct ndr_syntax_id syntax_id;
80 int fd;
81 union {
82 char *name;
83 uint16_t port;
84 } ep;
86 struct tevent_context *ev_ctx;
87 struct messaging_context *msg_ctx;
88 dcerpc_ncacn_disconnect_fn disconnect_fn;
91 static void named_pipe_listener(struct tevent_context *ev,
92 struct tevent_fd *fde,
93 uint16_t flags,
94 void *private_data);
96 int create_named_pipe_socket(const char *pipe_name)
98 char *np_dir = NULL;
99 int fd = -1;
102 * As lp_ncalrpc_dir() should have 0755, but
103 * lp_ncalrpc_dir()/np should have 0700, we need to
104 * create lp_ncalrpc_dir() first.
106 if (!directory_create_or_exist(lp_ncalrpc_dir(), 0755)) {
107 DEBUG(0, ("Failed to create pipe directory %s - %s\n",
108 lp_ncalrpc_dir(), strerror(errno)));
109 goto out;
112 np_dir = talloc_asprintf(talloc_tos(), "%s/np", lp_ncalrpc_dir());
113 if (!np_dir) {
114 DEBUG(0, ("Out of memory\n"));
115 goto out;
118 if (!directory_create_or_exist_strict(np_dir, geteuid(), 0700)) {
119 DEBUG(0, ("Failed to create pipe directory %s - %s\n",
120 np_dir, strerror(errno)));
121 goto out;
124 fd = create_pipe_sock(np_dir, pipe_name, 0700);
125 if (fd == -1) {
126 DEBUG(0, ("Failed to create pipe socket! [%s/%s]\n",
127 np_dir, pipe_name));
128 goto out;
131 DEBUG(10, ("Opened pipe socket fd %d for %s\n", fd, pipe_name));
133 out:
134 talloc_free(np_dir);
135 return fd;
138 bool setup_named_pipe_socket(const char *pipe_name,
139 struct tevent_context *ev_ctx,
140 struct messaging_context *msg_ctx)
142 struct dcerpc_ncacn_listen_state *state;
143 struct tevent_fd *fde;
144 int rc;
146 state = talloc(ev_ctx, struct dcerpc_ncacn_listen_state);
147 if (!state) {
148 DEBUG(0, ("Out of memory\n"));
149 return false;
151 state->ep.name = talloc_strdup(state, pipe_name);
152 if (state->ep.name == NULL) {
153 DEBUG(0, ("Out of memory\n"));
154 goto out;
156 state->fd = create_named_pipe_socket(pipe_name);
157 if (state->fd == -1) {
158 goto out;
161 rc = listen(state->fd, 5);
162 if (rc < 0) {
163 DEBUG(0, ("Failed to listen on pipe socket %s: %s\n",
164 pipe_name, strerror(errno)));
165 goto out;
168 state->ev_ctx = ev_ctx;
169 state->msg_ctx = msg_ctx;
171 DEBUG(10, ("Opened pipe socket fd %d for %s\n",
172 state->fd, pipe_name));
174 fde = tevent_add_fd(ev_ctx,
175 state, state->fd, TEVENT_FD_READ,
176 named_pipe_listener, state);
177 if (!fde) {
178 DEBUG(0, ("Failed to add event handler!\n"));
179 goto out;
182 tevent_fd_set_auto_close(fde);
183 return true;
185 out:
186 if (state->fd != -1) {
187 close(state->fd);
189 TALLOC_FREE(state);
190 return false;
193 static void named_pipe_listener(struct tevent_context *ev,
194 struct tevent_fd *fde,
195 uint16_t flags,
196 void *private_data)
198 struct dcerpc_ncacn_listen_state *state =
199 talloc_get_type_abort(private_data,
200 struct dcerpc_ncacn_listen_state);
201 struct sockaddr_un sunaddr;
202 socklen_t len;
203 int sd = -1;
205 /* TODO: should we have a limit to the number of clients ? */
207 len = sizeof(sunaddr);
209 sd = accept(state->fd,
210 (struct sockaddr *)(void *)&sunaddr, &len);
212 if (sd == -1) {
213 if (errno != EINTR) {
214 DEBUG(6, ("Failed to get a valid socket [%s]\n",
215 strerror(errno)));
217 return;
220 DEBUG(6, ("Accepted socket %d\n", sd));
222 named_pipe_accept_function(state->ev_ctx,
223 state->msg_ctx,
224 state->ep.name,
225 sd, NULL, 0);
229 /* This is the core of the rpc server.
230 * Accepts connections from clients and process requests using the appropriate
231 * dispatcher table. */
233 static int named_pipe_destructor(struct named_pipe_client *npc)
235 if (npc->term_fn) {
236 npc->term_fn(npc->private_data);
238 return 0;
241 struct named_pipe_client *named_pipe_client_init(TALLOC_CTX *mem_ctx,
242 struct tevent_context *ev_ctx,
243 struct messaging_context *msg_ctx,
244 const char *pipe_name,
245 named_pipe_termination_fn *term_fn,
246 uint16_t file_type,
247 uint16_t device_state,
248 uint64_t allocation_size,
249 void *private_data)
251 struct named_pipe_client *npc;
253 npc = talloc_zero(mem_ctx, struct named_pipe_client);
254 if (npc == NULL) {
255 DEBUG(0, ("Out of memory!\n"));
256 return NULL;
258 talloc_set_destructor(npc, named_pipe_destructor);
260 npc->pipe_name = talloc_strdup(npc, pipe_name);
261 if (npc->pipe_name == NULL) {
262 DEBUG(0, ("Out of memory!\n"));
263 talloc_free(npc);
264 return NULL;
267 npc->ev = ev_ctx;
268 npc->msg_ctx = msg_ctx;
269 npc->term_fn = term_fn;
270 npc->private_data = private_data;
272 npc->file_type = file_type;
273 npc->device_state = device_state;
274 npc->allocation_size = allocation_size;
276 return npc;
279 static void named_pipe_accept_done(struct tevent_req *subreq);
281 void named_pipe_accept_function(struct tevent_context *ev_ctx,
282 struct messaging_context *msg_ctx,
283 const char *pipe_name, int fd,
284 named_pipe_termination_fn *term_fn,
285 void *private_data)
287 struct named_pipe_client *npc;
288 struct tstream_context *plain;
289 struct tevent_req *subreq;
290 int ret;
292 npc = talloc_zero(ev_ctx, struct named_pipe_client);
293 if (!npc) {
294 DEBUG(0, ("Out of memory!\n"));
295 close(fd);
296 return;
299 npc->pipe_name = talloc_strdup(npc, pipe_name);
300 if (npc->pipe_name == NULL) {
301 DEBUG(0, ("Out of memory!\n"));
302 TALLOC_FREE(npc);
303 close(fd);
304 return;
306 npc->ev = ev_ctx;
307 npc->msg_ctx = msg_ctx;
308 npc->term_fn = term_fn;
309 npc->private_data = private_data;
311 talloc_set_destructor(npc, named_pipe_destructor);
313 /* make sure socket is in NON blocking state */
314 ret = set_blocking(fd, false);
315 if (ret != 0) {
316 DEBUG(2, ("Failed to make socket non-blocking\n"));
317 TALLOC_FREE(npc);
318 close(fd);
319 return;
322 ret = tstream_bsd_existing_socket(npc, fd, &plain);
323 if (ret != 0) {
324 DEBUG(2, ("Failed to create tstream socket\n"));
325 TALLOC_FREE(npc);
326 close(fd);
327 return;
330 npc->file_type = FILE_TYPE_MESSAGE_MODE_PIPE;
331 npc->device_state = 0xff | 0x0400 | 0x0100;
332 npc->allocation_size = 4096;
334 subreq = tstream_npa_accept_existing_send(npc, npc->ev, plain,
335 npc->file_type,
336 npc->device_state,
337 npc->allocation_size);
338 if (!subreq) {
339 DEBUG(2, ("Failed to start async accept procedure\n"));
340 TALLOC_FREE(npc);
341 close(fd);
342 return;
344 tevent_req_set_callback(subreq, named_pipe_accept_done, npc);
347 static void named_pipe_packet_done(struct tevent_req *subreq);
349 static void named_pipe_accept_done(struct tevent_req *subreq)
351 struct auth_session_info_transport *session_info_transport;
352 struct named_pipe_client *npc =
353 tevent_req_callback_data(subreq, struct named_pipe_client);
354 int error;
355 int ret;
357 ret = tstream_npa_accept_existing_recv(subreq, &error, npc,
358 &npc->tstream,
359 &npc->remote_client_addr,
360 &npc->remote_client_name,
361 &npc->local_server_addr,
362 &npc->local_server_name,
363 &session_info_transport);
365 npc->session_info = talloc_move(npc, &session_info_transport->session_info);
367 TALLOC_FREE(subreq);
368 if (ret != 0) {
369 DEBUG(2, ("Failed to accept named pipe connection! (%s)\n",
370 strerror(error)));
371 TALLOC_FREE(npc);
372 return;
375 ret = make_server_pipes_struct(npc,
376 npc->msg_ctx,
377 npc->pipe_name, NCACN_NP,
378 npc->remote_client_addr,
379 npc->local_server_addr,
380 npc->session_info,
381 &npc->p, &error);
382 if (ret != 0) {
383 DEBUG(2, ("Failed to create pipes_struct! (%s)\n",
384 strerror(error)));
385 goto fail;
388 npc->write_queue = tevent_queue_create(npc, "np_server_write_queue");
389 if (!npc->write_queue) {
390 DEBUG(2, ("Failed to set up write queue!\n"));
391 goto fail;
394 /* And now start receiving and processing packets */
395 subreq = dcerpc_read_ncacn_packet_send(npc, npc->ev, npc->tstream);
396 if (!subreq) {
397 DEBUG(2, ("Failed to start receving packets\n"));
398 goto fail;
400 tevent_req_set_callback(subreq, named_pipe_packet_process, npc);
401 return;
403 fail:
404 DEBUG(2, ("Fatal error. Terminating client(%s) connection!\n",
405 npc->remote_client_name));
406 /* terminate client connection */
407 talloc_free(npc);
408 return;
411 void named_pipe_packet_process(struct tevent_req *subreq)
413 struct named_pipe_client *npc =
414 tevent_req_callback_data(subreq, struct named_pipe_client);
415 struct _output_data *out = &npc->p->out_data;
416 DATA_BLOB recv_buffer = data_blob_null;
417 struct ncacn_packet *pkt;
418 NTSTATUS status;
419 uint32_t to_send;
420 size_t i;
421 bool ok;
423 status = dcerpc_read_ncacn_packet_recv(subreq, npc, &pkt, &recv_buffer);
424 TALLOC_FREE(subreq);
425 if (!NT_STATUS_IS_OK(status)) {
426 goto fail;
429 /* dcerpc_read_ncacn_packet_recv() returns a full PDU */
430 npc->p->in_data.pdu_needed_len = 0;
431 npc->p->in_data.pdu = recv_buffer;
432 if (dcerpc_get_endian_flag(&recv_buffer) & DCERPC_DREP_LE) {
433 npc->p->endian = RPC_LITTLE_ENDIAN;
434 } else {
435 npc->p->endian = RPC_BIG_ENDIAN;
437 DEBUG(10, ("PDU is in %s Endian format!\n",
438 npc->p->endian ? "Big" : "Little"));
439 process_complete_pdu(npc->p, pkt);
441 /* reset pipe state and free PDU */
442 npc->p->in_data.pdu.length = 0;
443 talloc_free(recv_buffer.data);
444 talloc_free(pkt);
446 /* this is needed because of the way DCERPC Binds work in
447 * the RPC marshalling code */
448 to_send = out->frag.length - out->current_pdu_sent;
449 if (to_send > 0) {
451 npc->iov = talloc_zero(npc, struct iovec);
452 if (!npc->iov) {
453 status = NT_STATUS_NO_MEMORY;
454 goto fail;
456 npc->count = 1;
458 npc->iov[0].iov_base = out->frag.data
459 + out->current_pdu_sent;
460 npc->iov[0].iov_len = to_send;
462 out->current_pdu_sent += to_send;
465 /* this condition is false for bind packets, or when we haven't
466 * yet got a full request, and need to wait for more data from
467 * the client */
468 while (out->data_sent_length < out->rdata.length) {
470 ok = create_next_pdu(npc->p);
471 if (!ok) {
472 DEBUG(3, ("Failed to create next PDU!\n"));
473 status = NT_STATUS_UNEXPECTED_IO_ERROR;
474 goto fail;
477 npc->iov = talloc_realloc(npc, npc->iov,
478 struct iovec, npc->count + 1);
479 if (!npc->iov) {
480 status = NT_STATUS_NO_MEMORY;
481 goto fail;
484 npc->iov[npc->count].iov_base = out->frag.data;
485 npc->iov[npc->count].iov_len = out->frag.length;
487 npc->count++;
490 /* we still don't have a complete request, go back and wait for more
491 * data */
492 if (npc->count == 0) {
493 /* Wait for the next packet */
494 subreq = dcerpc_read_ncacn_packet_send(npc, npc->ev, npc->tstream);
495 if (!subreq) {
496 DEBUG(2, ("Failed to start receving packets\n"));
497 status = NT_STATUS_NO_MEMORY;
498 goto fail;
500 tevent_req_set_callback(subreq, named_pipe_packet_process, npc);
501 return;
504 DEBUG(10, ("Sending %u fragments in a total of %u bytes\n",
505 (unsigned int)npc->count,
506 (unsigned int)npc->p->out_data.data_sent_length));
508 for (i = 0; i < npc->count; i++) {
509 DEBUG(10, ("Sending PDU number: %d, PDU Length: %u\n",
510 (unsigned int)i,
511 (unsigned int)npc->iov[i].iov_len));
512 dump_data(11, (const uint8_t *)npc->iov[i].iov_base,
513 npc->iov[i].iov_len);
515 subreq = tstream_writev_queue_send(npc,
516 npc->ev,
517 npc->tstream,
518 npc->write_queue,
519 (npc->iov + i),
521 if (!subreq) {
522 DEBUG(2, ("Failed to send packet\n"));
523 status = NT_STATUS_NO_MEMORY;
524 goto fail;
526 tevent_req_set_callback(subreq, named_pipe_packet_done, npc);
529 return;
531 fail:
532 DEBUG(2, ("Fatal error(%s). "
533 "Terminating client(%s) connection!\n",
534 nt_errstr(status), npc->remote_client_name));
535 /* terminate client connection */
536 talloc_free(npc);
537 return;
540 static void named_pipe_packet_done(struct tevent_req *subreq)
542 struct named_pipe_client *npc =
543 tevent_req_callback_data(subreq, struct named_pipe_client);
544 int sys_errno;
545 int ret;
547 ret = tstream_writev_queue_recv(subreq, &sys_errno);
548 TALLOC_FREE(subreq);
549 if (ret == -1) {
550 DEBUG(2, ("Writev failed!\n"));
551 goto fail;
554 if (tevent_queue_length(npc->write_queue) > 0) {
555 return;
558 if (npc->p->fault_state != 0) {
559 DEBUG(2, ("Disconnect after fault\n"));
560 sys_errno = EINVAL;
561 goto fail;
564 /* clear out any data that may have been left around */
565 npc->count = 0;
566 TALLOC_FREE(npc->iov);
567 data_blob_free(&npc->p->in_data.data);
568 data_blob_free(&npc->p->out_data.frag);
569 data_blob_free(&npc->p->out_data.rdata);
571 talloc_free_children(npc->p->mem_ctx);
573 /* Wait for the next packet */
574 subreq = dcerpc_read_ncacn_packet_send(npc, npc->ev, npc->tstream);
575 if (!subreq) {
576 DEBUG(2, ("Failed to start receving packets\n"));
577 sys_errno = ENOMEM;
578 goto fail;
580 tevent_req_set_callback(subreq, named_pipe_packet_process, npc);
581 return;
583 fail:
584 DEBUG(2, ("Fatal error(%s). "
585 "Terminating client(%s) connection!\n",
586 strerror(sys_errno), npc->remote_client_name));
587 /* terminate client connection */
588 talloc_free(npc);
589 return;
592 /********************************************************************
593 * Start listening on the tcp/ip socket
594 ********************************************************************/
596 static void dcerpc_ncacn_tcpip_listener(struct tevent_context *ev,
597 struct tevent_fd *fde,
598 uint16_t flags,
599 void *private_data);
601 int create_tcpip_socket(const struct sockaddr_storage *ifss, uint16_t *port)
603 int fd = -1;
605 if (*port == 0) {
606 uint16_t i;
608 for (i = lp_rpc_low_port(); i <= lp_rpc_high_port(); i++) {
609 fd = open_socket_in(SOCK_STREAM,
612 ifss,
613 false);
614 if (fd >= 0) {
615 *port = i;
616 break;
619 } else {
620 fd = open_socket_in(SOCK_STREAM,
621 *port,
623 ifss,
624 true);
626 if (fd == -1) {
627 DEBUG(0, ("Failed to create socket on port %u!\n", *port));
628 return -1;
631 DEBUG(10, ("Opened tcpip socket fd %d for port %u\n", fd, *port));
633 return fd;
636 uint16_t setup_dcerpc_ncacn_tcpip_socket(struct tevent_context *ev_ctx,
637 struct messaging_context *msg_ctx,
638 const struct sockaddr_storage *ifss,
639 uint16_t port)
641 struct dcerpc_ncacn_listen_state *state;
642 struct tevent_fd *fde;
643 int rc;
645 state = talloc(ev_ctx, struct dcerpc_ncacn_listen_state);
646 if (state == NULL) {
647 DEBUG(0, ("setup_dcerpc_ncacn_tcpip_socket: Out of memory\n"));
648 return 0;
651 state->fd = -1;
652 state->ep.port = port;
653 state->disconnect_fn = NULL;
655 state->fd = create_tcpip_socket(ifss, &state->ep.port);
656 if (state->fd == -1) {
657 goto out;
660 state->ev_ctx = ev_ctx;
661 state->msg_ctx = msg_ctx;
663 /* ready to listen */
664 set_socket_options(state->fd, "SO_KEEPALIVE");
665 set_socket_options(state->fd, lp_socket_options());
667 /* Set server socket to non-blocking for the accept. */
668 set_blocking(state->fd, false);
670 rc = listen(state->fd, SMBD_LISTEN_BACKLOG);
671 if (rc == -1) {
672 DEBUG(0,("setup_tcpip_socket: listen - %s\n", strerror(errno)));
673 goto out;
676 DEBUG(10, ("setup_tcpip_socket: openened socket fd %d for port %u\n",
677 state->fd, state->ep.port));
679 fde = tevent_add_fd(state->ev_ctx,
680 state,
681 state->fd,
682 TEVENT_FD_READ,
683 dcerpc_ncacn_tcpip_listener,
684 state);
685 if (fde == NULL) {
686 DEBUG(0, ("setup_tcpip_socket: Failed to add event handler!\n"));
687 goto out;
690 tevent_fd_set_auto_close(fde);
692 return state->ep.port;
693 out:
694 if (state->fd != -1) {
695 close(state->fd);
697 TALLOC_FREE(state);
699 return 0;
702 static void dcerpc_ncacn_tcpip_listener(struct tevent_context *ev,
703 struct tevent_fd *fde,
704 uint16_t flags,
705 void *private_data)
707 struct dcerpc_ncacn_listen_state *state =
708 talloc_get_type_abort(private_data,
709 struct dcerpc_ncacn_listen_state);
710 struct tsocket_address *cli_addr = NULL;
711 struct tsocket_address *srv_addr = NULL;
712 struct sockaddr_storage addr;
713 socklen_t in_addrlen = sizeof(addr);
714 int s = -1;
715 int rc;
717 s = accept(state->fd, (struct sockaddr *)(void *) &addr, &in_addrlen);
718 if (s == -1) {
719 if (errno != EINTR) {
720 DEBUG(0,("tcpip_listener accept: %s\n",
721 strerror(errno)));
723 return;
726 rc = tsocket_address_bsd_from_sockaddr(state,
727 (struct sockaddr *)(void *) &addr,
728 in_addrlen,
729 &cli_addr);
730 if (rc < 0) {
731 close(s);
732 return;
735 rc = getsockname(s, (struct sockaddr *)(void *) &addr, &in_addrlen);
736 if (rc < 0) {
737 close(s);
738 return;
741 rc = tsocket_address_bsd_from_sockaddr(state,
742 (struct sockaddr *)(void *) &addr,
743 in_addrlen,
744 &srv_addr);
745 if (rc < 0) {
746 close(s);
747 return;
750 DEBUG(6, ("tcpip_listener: Accepted socket %d\n", s));
752 dcerpc_ncacn_accept(state->ev_ctx,
753 state->msg_ctx,
754 NCACN_IP_TCP,
755 NULL,
756 cli_addr,
757 srv_addr,
759 NULL);
762 /********************************************************************
763 * Start listening on the ncalrpc socket
764 ********************************************************************/
766 static void dcerpc_ncalrpc_listener(struct tevent_context *ev,
767 struct tevent_fd *fde,
768 uint16_t flags,
769 void *private_data);
771 int create_dcerpc_ncalrpc_socket(const char *name)
773 int fd = -1;
775 if (name == NULL) {
776 name = "DEFAULT";
779 if (!directory_create_or_exist(lp_ncalrpc_dir(), 0755)) {
780 DEBUG(0, ("Failed to create ncalrpc directory %s - %s\n",
781 lp_ncalrpc_dir(), strerror(errno)));
782 return -1;
785 fd = create_pipe_sock(lp_ncalrpc_dir(), name, 0755);
786 if (fd == -1) {
787 DEBUG(0, ("Failed to create ncalrpc socket! [%s/%s]\n",
788 lp_ncalrpc_dir(), name));
789 return -1;
792 DEBUG(10, ("Opened ncalrpc socket fd %d for %s\n", fd, name));
794 return fd;
797 bool setup_dcerpc_ncalrpc_socket(struct tevent_context *ev_ctx,
798 struct messaging_context *msg_ctx,
799 const char *name,
800 dcerpc_ncacn_disconnect_fn fn)
802 struct dcerpc_ncacn_listen_state *state;
803 struct tevent_fd *fde;
804 int rc;
806 state = talloc(ev_ctx, struct dcerpc_ncacn_listen_state);
807 if (state == NULL) {
808 DEBUG(0, ("Out of memory\n"));
809 return false;
812 state->fd = -1;
813 state->disconnect_fn = fn;
815 if (name == NULL) {
816 name = "DEFAULT";
819 state->ep.name = talloc_strdup(state, name);
820 if (state->ep.name == NULL) {
821 DEBUG(0, ("Out of memory\n"));
822 talloc_free(state);
823 return false;
826 state->fd = create_dcerpc_ncalrpc_socket(name);
827 if (state->fd == -1) {
828 goto out;
831 rc = listen(state->fd, 5);
832 if (rc < 0) {
833 DEBUG(0, ("Failed to listen on ncalrpc socket %s: %s\n",
834 name, strerror(errno)));
835 goto out;
838 state->ev_ctx = ev_ctx;
839 state->msg_ctx = msg_ctx;
841 /* Set server socket to non-blocking for the accept. */
842 set_blocking(state->fd, false);
844 fde = tevent_add_fd(state->ev_ctx,
845 state,
846 state->fd,
847 TEVENT_FD_READ,
848 dcerpc_ncalrpc_listener,
849 state);
850 if (fde == NULL) {
851 DEBUG(0, ("Failed to add event handler for ncalrpc!\n"));
852 goto out;
855 tevent_fd_set_auto_close(fde);
857 return true;
858 out:
859 if (state->fd != -1) {
860 close(state->fd);
862 TALLOC_FREE(state);
864 return 0;
867 static void dcerpc_ncalrpc_listener(struct tevent_context *ev,
868 struct tevent_fd *fde,
869 uint16_t flags,
870 void *private_data)
872 struct dcerpc_ncacn_listen_state *state =
873 talloc_get_type_abort(private_data,
874 struct dcerpc_ncacn_listen_state);
875 struct tsocket_address *cli_addr = NULL, *srv_addr = NULL;
876 struct sockaddr_un sunaddr;
877 struct sockaddr *addr = (struct sockaddr *)(void *)&sunaddr;
878 socklen_t len = sizeof(sunaddr);
879 struct sockaddr_un sunaddr_server;
880 struct sockaddr *addr_server = (struct sockaddr *)(void *)&sunaddr_server;
881 socklen_t len_server = sizeof(sunaddr_server);
882 int sd = -1;
883 int rc;
885 ZERO_STRUCT(sunaddr);
886 ZERO_STRUCT(sunaddr_server);
888 sd = accept(state->fd, addr, &len);
889 if (sd == -1) {
890 if (errno != EINTR) {
891 DEBUG(0, ("ncalrpc accept() failed: %s\n", strerror(errno)));
893 return;
896 rc = tsocket_address_bsd_from_sockaddr(state,
897 addr, len,
898 &cli_addr);
899 if (rc < 0) {
900 close(sd);
901 return;
904 rc = getsockname(sd, addr_server, &len_server);
905 if (rc < 0) {
906 close(sd);
907 return;
910 rc = tsocket_address_bsd_from_sockaddr(state,
911 addr_server,
912 len_server,
913 &srv_addr);
914 if (rc < 0) {
915 close(sd);
916 return;
919 DEBUG(10, ("Accepted ncalrpc socket %s (fd: %d)\n",
920 sunaddr.sun_path, sd));
922 dcerpc_ncacn_accept(state->ev_ctx,
923 state->msg_ctx,
924 NCALRPC,
925 state->ep.name,
926 cli_addr, srv_addr, sd,
927 state->disconnect_fn);
930 struct dcerpc_ncacn_conn {
931 enum dcerpc_transport_t transport;
933 int sock;
935 struct pipes_struct *p;
936 dcerpc_ncacn_disconnect_fn disconnect_fn;
938 struct tevent_context *ev_ctx;
939 struct messaging_context *msg_ctx;
941 struct tstream_context *tstream;
942 struct tevent_queue *send_queue;
944 struct tsocket_address *remote_client_addr;
945 char *remote_client_name;
946 struct tsocket_address *local_server_addr;
947 char *local_server_name;
948 struct auth_session_info *session_info;
950 struct iovec *iov;
951 size_t count;
954 static void dcerpc_ncacn_packet_process(struct tevent_req *subreq);
955 static void dcerpc_ncacn_packet_done(struct tevent_req *subreq);
957 void dcerpc_ncacn_accept(struct tevent_context *ev_ctx,
958 struct messaging_context *msg_ctx,
959 enum dcerpc_transport_t transport,
960 const char *name,
961 struct tsocket_address *cli_addr,
962 struct tsocket_address *srv_addr,
963 int s,
964 dcerpc_ncacn_disconnect_fn fn) {
965 struct dcerpc_ncacn_conn *ncacn_conn;
966 struct tevent_req *subreq;
967 char *pipe_name;
968 NTSTATUS status;
969 int sys_errno;
970 uid_t uid;
971 gid_t gid;
972 int rc;
974 DEBUG(10, ("dcerpc_ncacn_accept\n"));
976 ncacn_conn = talloc_zero(ev_ctx, struct dcerpc_ncacn_conn);
977 if (ncacn_conn == NULL) {
978 DEBUG(0, ("Out of memory!\n"));
979 close(s);
980 return;
983 ncacn_conn->transport = transport;
984 ncacn_conn->ev_ctx = ev_ctx;
985 ncacn_conn->msg_ctx = msg_ctx;
986 ncacn_conn->sock = s;
987 ncacn_conn->disconnect_fn = fn;
989 ncacn_conn->remote_client_addr = talloc_move(ncacn_conn, &cli_addr);
990 if (tsocket_address_is_inet(ncacn_conn->remote_client_addr, "ip")) {
991 ncacn_conn->remote_client_name =
992 tsocket_address_inet_addr_string(ncacn_conn->remote_client_addr,
993 ncacn_conn);
994 } else {
995 ncacn_conn->remote_client_name =
996 tsocket_address_unix_path(ncacn_conn->remote_client_addr,
997 ncacn_conn);
999 if (ncacn_conn->remote_client_name == NULL) {
1000 DEBUG(0, ("Out of memory obtaining remote socket address as a string!\n"));
1001 talloc_free(ncacn_conn);
1002 close(s);
1003 return;
1006 if (srv_addr != NULL) {
1007 ncacn_conn->local_server_addr = talloc_move(ncacn_conn, &srv_addr);
1009 if (tsocket_address_is_inet(ncacn_conn->local_server_addr, "ip")) {
1010 ncacn_conn->local_server_name =
1011 tsocket_address_inet_addr_string(ncacn_conn->local_server_addr,
1012 ncacn_conn);
1013 } else {
1014 ncacn_conn->local_server_name =
1015 tsocket_address_unix_path(ncacn_conn->local_server_addr,
1016 ncacn_conn);
1018 if (ncacn_conn->local_server_name == NULL) {
1019 DEBUG(0, ("Out of memory obtaining local socket address as a string!\n"));
1020 talloc_free(ncacn_conn);
1021 close(s);
1022 return;
1026 switch (transport) {
1027 case NCACN_IP_TCP:
1028 pipe_name = tsocket_address_string(ncacn_conn->remote_client_addr,
1029 ncacn_conn);
1030 if (pipe_name == NULL) {
1031 close(s);
1032 talloc_free(ncacn_conn);
1033 return;
1036 break;
1037 case NCALRPC:
1038 rc = getpeereid(s, &uid, &gid);
1039 if (rc < 0) {
1040 DEBUG(2, ("Failed to get ncalrpc connecting "
1041 "uid - %s!\n", strerror(errno)));
1042 } else {
1043 if (uid == sec_initial_uid()) {
1044 TALLOC_FREE(ncacn_conn->remote_client_addr);
1046 rc = tsocket_address_unix_from_path(ncacn_conn,
1047 "/root/ncalrpc_as_system",
1048 &ncacn_conn->remote_client_addr);
1049 if (rc < 0) {
1050 DEBUG(0, ("Out of memory building magic ncalrpc_as_system path!\n"));
1051 talloc_free(ncacn_conn);
1052 close(s);
1053 return;
1056 TALLOC_FREE(ncacn_conn->remote_client_name);
1057 ncacn_conn->remote_client_name
1058 = tsocket_address_unix_path(ncacn_conn->remote_client_addr,
1059 ncacn_conn);
1060 if (ncacn_conn->remote_client_name == NULL) {
1061 DEBUG(0, ("Out of memory getting magic ncalrpc_as_system string!\n"));
1062 talloc_free(ncacn_conn);
1063 close(s);
1064 return;
1068 /* FALL TROUGH */
1069 case NCACN_NP:
1070 pipe_name = talloc_strdup(ncacn_conn,
1071 name);
1072 if (pipe_name == NULL) {
1073 close(s);
1074 talloc_free(ncacn_conn);
1075 return;
1077 break;
1078 default:
1079 DEBUG(0, ("unknown dcerpc transport: %u!\n",
1080 transport));
1081 talloc_free(ncacn_conn);
1082 close(s);
1083 return;
1086 rc = set_blocking(s, false);
1087 if (rc < 0) {
1088 DEBUG(2, ("Failed to set dcerpc socket to non-blocking\n"));
1089 talloc_free(ncacn_conn);
1090 close(s);
1091 return;
1095 * As soon as we have tstream_bsd_existing_socket set up it will
1096 * take care of closing the socket.
1098 rc = tstream_bsd_existing_socket(ncacn_conn, s, &ncacn_conn->tstream);
1099 if (rc < 0) {
1100 DEBUG(2, ("Failed to create tstream socket for dcerpc\n"));
1101 talloc_free(ncacn_conn);
1102 close(s);
1103 return;
1106 if (ncacn_conn->session_info == NULL) {
1108 * TODO: use auth_anonymous_session_info() here?
1110 status = make_session_info_guest(ncacn_conn,
1111 &ncacn_conn->session_info);
1112 if (!NT_STATUS_IS_OK(status)) {
1113 DEBUG(2, ("Failed to create "
1114 "make_session_info_guest - %s\n",
1115 nt_errstr(status)));
1116 talloc_free(ncacn_conn);
1117 return;
1121 rc = make_server_pipes_struct(ncacn_conn,
1122 ncacn_conn->msg_ctx,
1123 pipe_name,
1124 ncacn_conn->transport,
1125 ncacn_conn->remote_client_addr,
1126 ncacn_conn->local_server_addr,
1127 ncacn_conn->session_info,
1128 &ncacn_conn->p,
1129 &sys_errno);
1130 if (rc < 0) {
1131 DEBUG(2, ("Failed to create pipe struct - %s",
1132 strerror(sys_errno)));
1133 talloc_free(ncacn_conn);
1134 return;
1137 ncacn_conn->send_queue = tevent_queue_create(ncacn_conn,
1138 "dcerpc send queue");
1139 if (ncacn_conn->send_queue == NULL) {
1140 DEBUG(0, ("Out of memory building dcerpc send queue!\n"));
1141 talloc_free(ncacn_conn);
1142 return;
1145 subreq = dcerpc_read_ncacn_packet_send(ncacn_conn,
1146 ncacn_conn->ev_ctx,
1147 ncacn_conn->tstream);
1148 if (subreq == NULL) {
1149 DEBUG(2, ("Failed to send ncacn packet\n"));
1150 talloc_free(ncacn_conn);
1151 return;
1154 tevent_req_set_callback(subreq, dcerpc_ncacn_packet_process, ncacn_conn);
1156 DEBUG(10, ("dcerpc_ncacn_accept done\n"));
1158 return;
1161 static void dcerpc_ncacn_packet_process(struct tevent_req *subreq)
1163 struct dcerpc_ncacn_conn *ncacn_conn =
1164 tevent_req_callback_data(subreq, struct dcerpc_ncacn_conn);
1166 struct _output_data *out = &ncacn_conn->p->out_data;
1167 DATA_BLOB recv_buffer = data_blob_null;
1168 struct ncacn_packet *pkt;
1169 uint32_t to_send;
1170 NTSTATUS status;
1171 bool ok;
1173 status = dcerpc_read_ncacn_packet_recv(subreq, ncacn_conn, &pkt, &recv_buffer);
1174 TALLOC_FREE(subreq);
1175 if (!NT_STATUS_IS_OK(status)) {
1176 if (ncacn_conn->disconnect_fn != NULL) {
1177 ok = ncacn_conn->disconnect_fn(ncacn_conn->p);
1178 if (!ok) {
1179 DEBUG(3, ("Failed to call disconnect function\n"));
1182 goto fail;
1185 /* dcerpc_read_ncacn_packet_recv() returns a full PDU */
1186 ncacn_conn->p->in_data.pdu_needed_len = 0;
1187 ncacn_conn->p->in_data.pdu = recv_buffer;
1188 if (dcerpc_get_endian_flag(&recv_buffer) & DCERPC_DREP_LE) {
1189 ncacn_conn->p->endian = RPC_LITTLE_ENDIAN;
1190 } else {
1191 ncacn_conn->p->endian = RPC_BIG_ENDIAN;
1193 DEBUG(10, ("PDU is in %s Endian format!\n",
1194 ncacn_conn->p->endian ? "Big" : "Little"));
1195 process_complete_pdu(ncacn_conn->p, pkt);
1197 /* reset pipe state and free PDU */
1198 ncacn_conn->p->in_data.pdu.length = 0;
1199 talloc_free(recv_buffer.data);
1200 talloc_free(pkt);
1203 * This is needed because of the way DCERPC binds work in the RPC
1204 * marshalling code
1206 to_send = out->frag.length - out->current_pdu_sent;
1207 if (to_send > 0) {
1209 DEBUG(10, ("Current_pdu_len = %u, "
1210 "current_pdu_sent = %u "
1211 "Returning %u bytes\n",
1212 (unsigned int)out->frag.length,
1213 (unsigned int)out->current_pdu_sent,
1214 (unsigned int)to_send));
1216 ncacn_conn->iov = talloc_zero(ncacn_conn, struct iovec);
1217 if (ncacn_conn->iov == NULL) {
1218 status = NT_STATUS_NO_MEMORY;
1219 DEBUG(3, ("Out of memory!\n"));
1220 goto fail;
1222 ncacn_conn->count = 1;
1224 ncacn_conn->iov[0].iov_base = out->frag.data
1225 + out->current_pdu_sent;
1226 ncacn_conn->iov[0].iov_len = to_send;
1228 out->current_pdu_sent += to_send;
1232 * This condition is false for bind packets, or when we haven't yet got
1233 * a full request, and need to wait for more data from the client
1235 while (out->data_sent_length < out->rdata.length) {
1236 ok = create_next_pdu(ncacn_conn->p);
1237 if (!ok) {
1238 DEBUG(3, ("Failed to create next PDU!\n"));
1239 status = NT_STATUS_UNEXPECTED_IO_ERROR;
1240 goto fail;
1243 ncacn_conn->iov = talloc_realloc(ncacn_conn,
1244 ncacn_conn->iov,
1245 struct iovec,
1246 ncacn_conn->count + 1);
1247 if (ncacn_conn->iov == NULL) {
1248 DEBUG(3, ("Out of memory!\n"));
1249 status = NT_STATUS_NO_MEMORY;
1250 goto fail;
1253 ncacn_conn->iov[ncacn_conn->count].iov_base = out->frag.data;
1254 ncacn_conn->iov[ncacn_conn->count].iov_len = out->frag.length;
1256 DEBUG(10, ("PDU number: %d, PDU Length: %u\n",
1257 (unsigned int) ncacn_conn->count,
1258 (unsigned int) ncacn_conn->iov[ncacn_conn->count].iov_len));
1259 dump_data(11, (const uint8_t *) ncacn_conn->iov[ncacn_conn->count].iov_base,
1260 ncacn_conn->iov[ncacn_conn->count].iov_len);
1261 ncacn_conn->count++;
1265 * We still don't have a complete request, go back and wait for more
1266 * data.
1268 if (ncacn_conn->count == 0) {
1269 /* Wait for the next packet */
1270 subreq = dcerpc_read_ncacn_packet_send(ncacn_conn,
1271 ncacn_conn->ev_ctx,
1272 ncacn_conn->tstream);
1273 if (subreq == NULL) {
1274 DEBUG(2, ("Failed to start receving packets\n"));
1275 status = NT_STATUS_NO_MEMORY;
1276 goto fail;
1278 tevent_req_set_callback(subreq, dcerpc_ncacn_packet_process, ncacn_conn);
1279 return;
1282 DEBUG(10, ("Sending a total of %u bytes\n",
1283 (unsigned int)ncacn_conn->p->out_data.data_sent_length));
1285 subreq = tstream_writev_queue_send(ncacn_conn,
1286 ncacn_conn->ev_ctx,
1287 ncacn_conn->tstream,
1288 ncacn_conn->send_queue,
1289 ncacn_conn->iov,
1290 ncacn_conn->count);
1291 if (subreq == NULL) {
1292 DEBUG(2, ("Failed to send packet\n"));
1293 status = NT_STATUS_NO_MEMORY;
1294 goto fail;
1297 tevent_req_set_callback(subreq, dcerpc_ncacn_packet_done, ncacn_conn);
1298 return;
1300 fail:
1301 DEBUG(3, ("Terminating client(%s) connection! - '%s'\n",
1302 ncacn_conn->remote_client_name, nt_errstr(status)));
1304 /* Terminate client connection */
1305 talloc_free(ncacn_conn);
1306 return;
1309 static void dcerpc_ncacn_packet_done(struct tevent_req *subreq)
1311 struct dcerpc_ncacn_conn *ncacn_conn =
1312 tevent_req_callback_data(subreq, struct dcerpc_ncacn_conn);
1313 NTSTATUS status = NT_STATUS_OK;
1314 int sys_errno;
1315 int rc;
1317 rc = tstream_writev_queue_recv(subreq, &sys_errno);
1318 TALLOC_FREE(subreq);
1319 if (rc < 0) {
1320 DEBUG(2, ("Writev failed!\n"));
1321 status = map_nt_error_from_unix(sys_errno);
1322 goto fail;
1325 if (ncacn_conn->p->fault_state != 0) {
1326 DEBUG(2, ("Disconnect after fault\n"));
1327 sys_errno = EINVAL;
1328 goto fail;
1331 /* clear out any data that may have been left around */
1332 ncacn_conn->count = 0;
1333 TALLOC_FREE(ncacn_conn->iov);
1334 data_blob_free(&ncacn_conn->p->in_data.data);
1335 data_blob_free(&ncacn_conn->p->out_data.frag);
1336 data_blob_free(&ncacn_conn->p->out_data.rdata);
1338 talloc_free_children(ncacn_conn->p->mem_ctx);
1340 /* Wait for the next packet */
1341 subreq = dcerpc_read_ncacn_packet_send(ncacn_conn,
1342 ncacn_conn->ev_ctx,
1343 ncacn_conn->tstream);
1344 if (subreq == NULL) {
1345 DEBUG(2, ("Failed to start receving packets\n"));
1346 status = NT_STATUS_NO_MEMORY;
1347 goto fail;
1350 tevent_req_set_callback(subreq, dcerpc_ncacn_packet_process, ncacn_conn);
1351 return;
1353 fail:
1354 DEBUG(3, ("Terminating client(%s) connection! - '%s'\n",
1355 ncacn_conn->remote_client_name, nt_errstr(status)));
1357 /* Terminate client connection */
1358 talloc_free(ncacn_conn);
1359 return;
1362 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */