s3:rpc_server: make use of make_session_info_anonymous()
[Samba.git] / source3 / rpc_server / rpc_server.c
bloba2bcf8545c0ef0f9dd5dfc6cc83b0555c7e0bab8
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;
219 smb_set_close_on_exec(sd);
221 DEBUG(6, ("Accepted socket %d\n", sd));
223 named_pipe_accept_function(state->ev_ctx,
224 state->msg_ctx,
225 state->ep.name,
226 sd, NULL, 0);
230 /* This is the core of the rpc server.
231 * Accepts connections from clients and process requests using the appropriate
232 * dispatcher table. */
234 static int named_pipe_destructor(struct named_pipe_client *npc)
236 if (npc->term_fn) {
237 npc->term_fn(npc->private_data);
239 return 0;
242 struct named_pipe_client *named_pipe_client_init(TALLOC_CTX *mem_ctx,
243 struct tevent_context *ev_ctx,
244 struct messaging_context *msg_ctx,
245 const char *pipe_name,
246 named_pipe_termination_fn *term_fn,
247 uint16_t file_type,
248 uint16_t device_state,
249 uint64_t allocation_size,
250 void *private_data)
252 struct named_pipe_client *npc;
254 npc = talloc_zero(mem_ctx, struct named_pipe_client);
255 if (npc == NULL) {
256 DEBUG(0, ("Out of memory!\n"));
257 return NULL;
259 talloc_set_destructor(npc, named_pipe_destructor);
261 npc->pipe_name = talloc_strdup(npc, pipe_name);
262 if (npc->pipe_name == NULL) {
263 DEBUG(0, ("Out of memory!\n"));
264 talloc_free(npc);
265 return NULL;
268 npc->ev = ev_ctx;
269 npc->msg_ctx = msg_ctx;
270 npc->term_fn = term_fn;
271 npc->private_data = private_data;
273 npc->file_type = file_type;
274 npc->device_state = device_state;
275 npc->allocation_size = allocation_size;
277 return npc;
280 static void named_pipe_accept_done(struct tevent_req *subreq);
282 void named_pipe_accept_function(struct tevent_context *ev_ctx,
283 struct messaging_context *msg_ctx,
284 const char *pipe_name, int fd,
285 named_pipe_termination_fn *term_fn,
286 void *private_data)
288 struct named_pipe_client *npc;
289 struct tstream_context *plain;
290 struct tevent_req *subreq;
291 int ret;
293 npc = talloc_zero(ev_ctx, struct named_pipe_client);
294 if (!npc) {
295 DEBUG(0, ("Out of memory!\n"));
296 close(fd);
297 return;
300 npc->pipe_name = talloc_strdup(npc, pipe_name);
301 if (npc->pipe_name == NULL) {
302 DEBUG(0, ("Out of memory!\n"));
303 TALLOC_FREE(npc);
304 close(fd);
305 return;
307 npc->ev = ev_ctx;
308 npc->msg_ctx = msg_ctx;
309 npc->term_fn = term_fn;
310 npc->private_data = private_data;
312 talloc_set_destructor(npc, named_pipe_destructor);
314 /* make sure socket is in NON blocking state */
315 ret = set_blocking(fd, false);
316 if (ret != 0) {
317 DEBUG(2, ("Failed to make socket non-blocking\n"));
318 TALLOC_FREE(npc);
319 close(fd);
320 return;
323 ret = tstream_bsd_existing_socket(npc, fd, &plain);
324 if (ret != 0) {
325 DEBUG(2, ("Failed to create tstream socket\n"));
326 TALLOC_FREE(npc);
327 close(fd);
328 return;
331 npc->file_type = FILE_TYPE_MESSAGE_MODE_PIPE;
332 npc->device_state = 0xff | 0x0400 | 0x0100;
333 npc->allocation_size = 4096;
335 subreq = tstream_npa_accept_existing_send(npc, npc->ev, plain,
336 npc->file_type,
337 npc->device_state,
338 npc->allocation_size);
339 if (!subreq) {
340 DEBUG(2, ("Failed to start async accept procedure\n"));
341 TALLOC_FREE(npc);
342 close(fd);
343 return;
345 tevent_req_set_callback(subreq, named_pipe_accept_done, npc);
348 static void named_pipe_packet_done(struct tevent_req *subreq);
350 static void named_pipe_accept_done(struct tevent_req *subreq)
352 struct auth_session_info_transport *session_info_transport;
353 struct named_pipe_client *npc =
354 tevent_req_callback_data(subreq, struct named_pipe_client);
355 int error;
356 int ret;
358 ret = tstream_npa_accept_existing_recv(subreq, &error, npc,
359 &npc->tstream,
360 &npc->remote_client_addr,
361 &npc->remote_client_name,
362 &npc->local_server_addr,
363 &npc->local_server_name,
364 &session_info_transport);
366 npc->session_info = talloc_move(npc, &session_info_transport->session_info);
368 TALLOC_FREE(subreq);
369 if (ret != 0) {
370 DEBUG(2, ("Failed to accept named pipe connection! (%s)\n",
371 strerror(error)));
372 TALLOC_FREE(npc);
373 return;
376 ret = make_server_pipes_struct(npc,
377 npc->msg_ctx,
378 npc->pipe_name, NCACN_NP,
379 npc->remote_client_addr,
380 npc->local_server_addr,
381 npc->session_info,
382 &npc->p, &error);
383 if (ret != 0) {
384 DEBUG(2, ("Failed to create pipes_struct! (%s)\n",
385 strerror(error)));
386 goto fail;
389 npc->write_queue = tevent_queue_create(npc, "np_server_write_queue");
390 if (!npc->write_queue) {
391 DEBUG(2, ("Failed to set up write queue!\n"));
392 goto fail;
395 /* And now start receiving and processing packets */
396 subreq = dcerpc_read_ncacn_packet_send(npc, npc->ev, npc->tstream);
397 if (!subreq) {
398 DEBUG(2, ("Failed to start receving packets\n"));
399 goto fail;
401 tevent_req_set_callback(subreq, named_pipe_packet_process, npc);
402 return;
404 fail:
405 DEBUG(2, ("Fatal error. Terminating client(%s) connection!\n",
406 npc->remote_client_name));
407 /* terminate client connection */
408 talloc_free(npc);
409 return;
412 void named_pipe_packet_process(struct tevent_req *subreq)
414 struct named_pipe_client *npc =
415 tevent_req_callback_data(subreq, struct named_pipe_client);
416 struct _output_data *out = &npc->p->out_data;
417 DATA_BLOB recv_buffer = data_blob_null;
418 struct ncacn_packet *pkt;
419 NTSTATUS status;
420 uint32_t to_send;
421 size_t i;
422 bool ok;
424 status = dcerpc_read_ncacn_packet_recv(subreq, npc, &pkt, &recv_buffer);
425 TALLOC_FREE(subreq);
426 if (!NT_STATUS_IS_OK(status)) {
427 goto fail;
430 /* dcerpc_read_ncacn_packet_recv() returns a full PDU */
431 npc->p->in_data.pdu_needed_len = 0;
432 npc->p->in_data.pdu = recv_buffer;
433 if (dcerpc_get_endian_flag(&recv_buffer) & DCERPC_DREP_LE) {
434 npc->p->endian = RPC_LITTLE_ENDIAN;
435 } else {
436 npc->p->endian = RPC_BIG_ENDIAN;
438 DEBUG(10, ("PDU is in %s Endian format!\n",
439 npc->p->endian ? "Big" : "Little"));
440 process_complete_pdu(npc->p, pkt);
442 /* reset pipe state and free PDU */
443 npc->p->in_data.pdu.length = 0;
444 talloc_free(recv_buffer.data);
445 talloc_free(pkt);
447 /* this is needed because of the way DCERPC Binds work in
448 * the RPC marshalling code */
449 to_send = out->frag.length - out->current_pdu_sent;
450 if (to_send > 0) {
452 npc->iov = talloc_zero(npc, struct iovec);
453 if (!npc->iov) {
454 status = NT_STATUS_NO_MEMORY;
455 goto fail;
457 npc->count = 1;
459 npc->iov[0].iov_base = out->frag.data
460 + out->current_pdu_sent;
461 npc->iov[0].iov_len = to_send;
463 out->current_pdu_sent += to_send;
466 /* this condition is false for bind packets, or when we haven't
467 * yet got a full request, and need to wait for more data from
468 * the client */
469 while (out->data_sent_length < out->rdata.length) {
471 ok = create_next_pdu(npc->p);
472 if (!ok) {
473 DEBUG(3, ("Failed to create next PDU!\n"));
474 status = NT_STATUS_UNEXPECTED_IO_ERROR;
475 goto fail;
478 npc->iov = talloc_realloc(npc, npc->iov,
479 struct iovec, npc->count + 1);
480 if (!npc->iov) {
481 status = NT_STATUS_NO_MEMORY;
482 goto fail;
485 npc->iov[npc->count].iov_base = out->frag.data;
486 npc->iov[npc->count].iov_len = out->frag.length;
488 npc->count++;
491 /* we still don't have a complete request, go back and wait for more
492 * data */
493 if (npc->count == 0) {
494 /* Wait for the next packet */
495 subreq = dcerpc_read_ncacn_packet_send(npc, npc->ev, npc->tstream);
496 if (!subreq) {
497 DEBUG(2, ("Failed to start receving packets\n"));
498 status = NT_STATUS_NO_MEMORY;
499 goto fail;
501 tevent_req_set_callback(subreq, named_pipe_packet_process, npc);
502 return;
505 DEBUG(10, ("Sending %u fragments in a total of %u bytes\n",
506 (unsigned int)npc->count,
507 (unsigned int)npc->p->out_data.data_sent_length));
509 for (i = 0; i < npc->count; i++) {
510 DEBUG(10, ("Sending PDU number: %d, PDU Length: %u\n",
511 (unsigned int)i,
512 (unsigned int)npc->iov[i].iov_len));
513 dump_data(11, (const uint8_t *)npc->iov[i].iov_base,
514 npc->iov[i].iov_len);
516 subreq = tstream_writev_queue_send(npc,
517 npc->ev,
518 npc->tstream,
519 npc->write_queue,
520 (npc->iov + i),
522 if (!subreq) {
523 DEBUG(2, ("Failed to send packet\n"));
524 status = NT_STATUS_NO_MEMORY;
525 goto fail;
527 tevent_req_set_callback(subreq, named_pipe_packet_done, npc);
530 return;
532 fail:
533 DEBUG(2, ("Fatal error(%s). "
534 "Terminating client(%s) connection!\n",
535 nt_errstr(status), npc->remote_client_name));
536 /* terminate client connection */
537 talloc_free(npc);
538 return;
541 static void named_pipe_packet_done(struct tevent_req *subreq)
543 struct named_pipe_client *npc =
544 tevent_req_callback_data(subreq, struct named_pipe_client);
545 int sys_errno;
546 int ret;
548 ret = tstream_writev_queue_recv(subreq, &sys_errno);
549 TALLOC_FREE(subreq);
550 if (ret == -1) {
551 DEBUG(2, ("Writev failed!\n"));
552 goto fail;
555 if (tevent_queue_length(npc->write_queue) > 0) {
556 return;
559 if (npc->p->fault_state != 0) {
560 DEBUG(2, ("Disconnect after fault\n"));
561 sys_errno = EINVAL;
562 goto fail;
565 /* clear out any data that may have been left around */
566 npc->count = 0;
567 TALLOC_FREE(npc->iov);
568 data_blob_free(&npc->p->in_data.data);
569 data_blob_free(&npc->p->out_data.frag);
570 data_blob_free(&npc->p->out_data.rdata);
572 talloc_free_children(npc->p->mem_ctx);
574 /* Wait for the next packet */
575 subreq = dcerpc_read_ncacn_packet_send(npc, npc->ev, npc->tstream);
576 if (!subreq) {
577 DEBUG(2, ("Failed to start receving packets\n"));
578 sys_errno = ENOMEM;
579 goto fail;
581 tevent_req_set_callback(subreq, named_pipe_packet_process, npc);
582 return;
584 fail:
585 DEBUG(2, ("Fatal error(%s). "
586 "Terminating client(%s) connection!\n",
587 strerror(sys_errno), npc->remote_client_name));
588 /* terminate client connection */
589 talloc_free(npc);
590 return;
593 /********************************************************************
594 * Start listening on the tcp/ip socket
595 ********************************************************************/
597 static void dcerpc_ncacn_tcpip_listener(struct tevent_context *ev,
598 struct tevent_fd *fde,
599 uint16_t flags,
600 void *private_data);
602 int create_tcpip_socket(const struct sockaddr_storage *ifss, uint16_t *port)
604 int fd = -1;
606 if (*port == 0) {
607 uint16_t i;
609 for (i = lp_rpc_low_port(); i <= lp_rpc_high_port(); i++) {
610 fd = open_socket_in(SOCK_STREAM,
613 ifss,
614 false);
615 if (fd >= 0) {
616 *port = i;
617 break;
620 } else {
621 fd = open_socket_in(SOCK_STREAM,
622 *port,
624 ifss,
625 true);
627 if (fd == -1) {
628 DEBUG(0, ("Failed to create socket on port %u!\n", *port));
629 return -1;
632 DEBUG(10, ("Opened tcpip socket fd %d for port %u\n", fd, *port));
634 return fd;
637 uint16_t setup_dcerpc_ncacn_tcpip_socket(struct tevent_context *ev_ctx,
638 struct messaging_context *msg_ctx,
639 const struct sockaddr_storage *ifss,
640 uint16_t port)
642 struct dcerpc_ncacn_listen_state *state;
643 struct tevent_fd *fde;
644 int rc;
646 state = talloc(ev_ctx, struct dcerpc_ncacn_listen_state);
647 if (state == NULL) {
648 DEBUG(0, ("setup_dcerpc_ncacn_tcpip_socket: Out of memory\n"));
649 return 0;
652 state->fd = -1;
653 state->ep.port = port;
654 state->disconnect_fn = NULL;
656 state->fd = create_tcpip_socket(ifss, &state->ep.port);
657 if (state->fd == -1) {
658 goto out;
661 state->ev_ctx = ev_ctx;
662 state->msg_ctx = msg_ctx;
664 /* ready to listen */
665 set_socket_options(state->fd, "SO_KEEPALIVE");
666 set_socket_options(state->fd, lp_socket_options());
668 /* Set server socket to non-blocking for the accept. */
669 set_blocking(state->fd, false);
671 rc = listen(state->fd, SMBD_LISTEN_BACKLOG);
672 if (rc == -1) {
673 DEBUG(0,("setup_tcpip_socket: listen - %s\n", strerror(errno)));
674 goto out;
677 DEBUG(10, ("setup_tcpip_socket: openened socket fd %d for port %u\n",
678 state->fd, state->ep.port));
680 fde = tevent_add_fd(state->ev_ctx,
681 state,
682 state->fd,
683 TEVENT_FD_READ,
684 dcerpc_ncacn_tcpip_listener,
685 state);
686 if (fde == NULL) {
687 DEBUG(0, ("setup_tcpip_socket: Failed to add event handler!\n"));
688 goto out;
691 tevent_fd_set_auto_close(fde);
693 return state->ep.port;
694 out:
695 if (state->fd != -1) {
696 close(state->fd);
698 TALLOC_FREE(state);
700 return 0;
703 static void dcerpc_ncacn_tcpip_listener(struct tevent_context *ev,
704 struct tevent_fd *fde,
705 uint16_t flags,
706 void *private_data)
708 struct dcerpc_ncacn_listen_state *state =
709 talloc_get_type_abort(private_data,
710 struct dcerpc_ncacn_listen_state);
711 struct tsocket_address *cli_addr = NULL;
712 struct tsocket_address *srv_addr = NULL;
713 struct sockaddr_storage addr;
714 socklen_t in_addrlen = sizeof(addr);
715 int s = -1;
716 int rc;
718 s = accept(state->fd, (struct sockaddr *)(void *) &addr, &in_addrlen);
719 if (s == -1) {
720 if (errno != EINTR) {
721 DEBUG(0,("tcpip_listener accept: %s\n",
722 strerror(errno)));
724 return;
726 smb_set_close_on_exec(s);
728 rc = tsocket_address_bsd_from_sockaddr(state,
729 (struct sockaddr *)(void *) &addr,
730 in_addrlen,
731 &cli_addr);
732 if (rc < 0) {
733 close(s);
734 return;
737 rc = getsockname(s, (struct sockaddr *)(void *) &addr, &in_addrlen);
738 if (rc < 0) {
739 close(s);
740 return;
743 rc = tsocket_address_bsd_from_sockaddr(state,
744 (struct sockaddr *)(void *) &addr,
745 in_addrlen,
746 &srv_addr);
747 if (rc < 0) {
748 close(s);
749 return;
752 DEBUG(6, ("tcpip_listener: Accepted socket %d\n", s));
754 dcerpc_ncacn_accept(state->ev_ctx,
755 state->msg_ctx,
756 NCACN_IP_TCP,
757 NULL,
758 cli_addr,
759 srv_addr,
761 NULL);
764 /********************************************************************
765 * Start listening on the ncalrpc socket
766 ********************************************************************/
768 static void dcerpc_ncalrpc_listener(struct tevent_context *ev,
769 struct tevent_fd *fde,
770 uint16_t flags,
771 void *private_data);
773 int create_dcerpc_ncalrpc_socket(const char *name)
775 int fd = -1;
777 if (name == NULL) {
778 name = "DEFAULT";
781 if (!directory_create_or_exist(lp_ncalrpc_dir(), 0755)) {
782 DEBUG(0, ("Failed to create ncalrpc directory %s - %s\n",
783 lp_ncalrpc_dir(), strerror(errno)));
784 return -1;
787 fd = create_pipe_sock(lp_ncalrpc_dir(), name, 0755);
788 if (fd == -1) {
789 DEBUG(0, ("Failed to create ncalrpc socket! [%s/%s]\n",
790 lp_ncalrpc_dir(), name));
791 return -1;
794 DEBUG(10, ("Opened ncalrpc socket fd %d for %s\n", fd, name));
796 return fd;
799 bool setup_dcerpc_ncalrpc_socket(struct tevent_context *ev_ctx,
800 struct messaging_context *msg_ctx,
801 const char *name,
802 dcerpc_ncacn_disconnect_fn fn)
804 struct dcerpc_ncacn_listen_state *state;
805 struct tevent_fd *fde;
806 int rc;
808 state = talloc(ev_ctx, struct dcerpc_ncacn_listen_state);
809 if (state == NULL) {
810 DEBUG(0, ("Out of memory\n"));
811 return false;
814 state->fd = -1;
815 state->disconnect_fn = fn;
817 if (name == NULL) {
818 name = "DEFAULT";
821 state->ep.name = talloc_strdup(state, name);
822 if (state->ep.name == NULL) {
823 DEBUG(0, ("Out of memory\n"));
824 talloc_free(state);
825 return false;
828 state->fd = create_dcerpc_ncalrpc_socket(name);
829 if (state->fd == -1) {
830 goto out;
833 rc = listen(state->fd, 5);
834 if (rc < 0) {
835 DEBUG(0, ("Failed to listen on ncalrpc socket %s: %s\n",
836 name, strerror(errno)));
837 goto out;
840 state->ev_ctx = ev_ctx;
841 state->msg_ctx = msg_ctx;
843 /* Set server socket to non-blocking for the accept. */
844 set_blocking(state->fd, false);
846 fde = tevent_add_fd(state->ev_ctx,
847 state,
848 state->fd,
849 TEVENT_FD_READ,
850 dcerpc_ncalrpc_listener,
851 state);
852 if (fde == NULL) {
853 DEBUG(0, ("Failed to add event handler for ncalrpc!\n"));
854 goto out;
857 tevent_fd_set_auto_close(fde);
859 return true;
860 out:
861 if (state->fd != -1) {
862 close(state->fd);
864 TALLOC_FREE(state);
866 return 0;
869 static void dcerpc_ncalrpc_listener(struct tevent_context *ev,
870 struct tevent_fd *fde,
871 uint16_t flags,
872 void *private_data)
874 struct dcerpc_ncacn_listen_state *state =
875 talloc_get_type_abort(private_data,
876 struct dcerpc_ncacn_listen_state);
877 struct tsocket_address *cli_addr = NULL, *srv_addr = NULL;
878 struct sockaddr_un sunaddr;
879 struct sockaddr *addr = (struct sockaddr *)(void *)&sunaddr;
880 socklen_t len = sizeof(sunaddr);
881 struct sockaddr_un sunaddr_server;
882 struct sockaddr *addr_server = (struct sockaddr *)(void *)&sunaddr_server;
883 socklen_t len_server = sizeof(sunaddr_server);
884 int sd = -1;
885 int rc;
887 ZERO_STRUCT(sunaddr);
888 ZERO_STRUCT(sunaddr_server);
890 sd = accept(state->fd, addr, &len);
891 if (sd == -1) {
892 if (errno != EINTR) {
893 DEBUG(0, ("ncalrpc accept() failed: %s\n", strerror(errno)));
895 return;
897 smb_set_close_on_exec(sd);
899 rc = tsocket_address_bsd_from_sockaddr(state,
900 addr, len,
901 &cli_addr);
902 if (rc < 0) {
903 close(sd);
904 return;
907 rc = getsockname(sd, addr_server, &len_server);
908 if (rc < 0) {
909 close(sd);
910 return;
913 rc = tsocket_address_bsd_from_sockaddr(state,
914 addr_server,
915 len_server,
916 &srv_addr);
917 if (rc < 0) {
918 close(sd);
919 return;
922 DEBUG(10, ("Accepted ncalrpc socket %s (fd: %d)\n",
923 sunaddr.sun_path, sd));
925 dcerpc_ncacn_accept(state->ev_ctx,
926 state->msg_ctx,
927 NCALRPC,
928 state->ep.name,
929 cli_addr, srv_addr, sd,
930 state->disconnect_fn);
933 struct dcerpc_ncacn_conn {
934 enum dcerpc_transport_t transport;
936 int sock;
938 struct pipes_struct *p;
939 dcerpc_ncacn_disconnect_fn disconnect_fn;
941 struct tevent_context *ev_ctx;
942 struct messaging_context *msg_ctx;
944 struct tstream_context *tstream;
945 struct tevent_queue *send_queue;
947 struct tsocket_address *remote_client_addr;
948 char *remote_client_name;
949 struct tsocket_address *local_server_addr;
950 char *local_server_name;
951 struct auth_session_info *session_info;
953 struct iovec *iov;
954 size_t count;
957 static void dcerpc_ncacn_packet_process(struct tevent_req *subreq);
958 static void dcerpc_ncacn_packet_done(struct tevent_req *subreq);
960 void dcerpc_ncacn_accept(struct tevent_context *ev_ctx,
961 struct messaging_context *msg_ctx,
962 enum dcerpc_transport_t transport,
963 const char *name,
964 struct tsocket_address *cli_addr,
965 struct tsocket_address *srv_addr,
966 int s,
967 dcerpc_ncacn_disconnect_fn fn) {
968 struct dcerpc_ncacn_conn *ncacn_conn;
969 struct tevent_req *subreq;
970 char *pipe_name;
971 NTSTATUS status;
972 int sys_errno;
973 uid_t uid;
974 gid_t gid;
975 int rc;
977 DEBUG(10, ("dcerpc_ncacn_accept\n"));
979 ncacn_conn = talloc_zero(ev_ctx, struct dcerpc_ncacn_conn);
980 if (ncacn_conn == NULL) {
981 DEBUG(0, ("Out of memory!\n"));
982 close(s);
983 return;
986 ncacn_conn->transport = transport;
987 ncacn_conn->ev_ctx = ev_ctx;
988 ncacn_conn->msg_ctx = msg_ctx;
989 ncacn_conn->sock = s;
990 ncacn_conn->disconnect_fn = fn;
992 ncacn_conn->remote_client_addr = talloc_move(ncacn_conn, &cli_addr);
993 if (tsocket_address_is_inet(ncacn_conn->remote_client_addr, "ip")) {
994 ncacn_conn->remote_client_name =
995 tsocket_address_inet_addr_string(ncacn_conn->remote_client_addr,
996 ncacn_conn);
997 } else {
998 ncacn_conn->remote_client_name =
999 tsocket_address_unix_path(ncacn_conn->remote_client_addr,
1000 ncacn_conn);
1002 if (ncacn_conn->remote_client_name == NULL) {
1003 DEBUG(0, ("Out of memory obtaining remote socket address as a string!\n"));
1004 talloc_free(ncacn_conn);
1005 close(s);
1006 return;
1009 if (srv_addr != NULL) {
1010 ncacn_conn->local_server_addr = talloc_move(ncacn_conn, &srv_addr);
1012 if (tsocket_address_is_inet(ncacn_conn->local_server_addr, "ip")) {
1013 ncacn_conn->local_server_name =
1014 tsocket_address_inet_addr_string(ncacn_conn->local_server_addr,
1015 ncacn_conn);
1016 } else {
1017 ncacn_conn->local_server_name =
1018 tsocket_address_unix_path(ncacn_conn->local_server_addr,
1019 ncacn_conn);
1021 if (ncacn_conn->local_server_name == NULL) {
1022 DEBUG(0, ("Out of memory obtaining local socket address as a string!\n"));
1023 talloc_free(ncacn_conn);
1024 close(s);
1025 return;
1029 switch (transport) {
1030 case NCACN_IP_TCP:
1031 pipe_name = tsocket_address_string(ncacn_conn->remote_client_addr,
1032 ncacn_conn);
1033 if (pipe_name == NULL) {
1034 close(s);
1035 talloc_free(ncacn_conn);
1036 return;
1039 break;
1040 case NCALRPC:
1041 rc = getpeereid(s, &uid, &gid);
1042 if (rc < 0) {
1043 DEBUG(2, ("Failed to get ncalrpc connecting "
1044 "uid - %s!\n", strerror(errno)));
1045 } else {
1046 if (uid == sec_initial_uid()) {
1047 TALLOC_FREE(ncacn_conn->remote_client_addr);
1049 rc = tsocket_address_unix_from_path(ncacn_conn,
1050 AS_SYSTEM_MAGIC_PATH_TOKEN,
1051 &ncacn_conn->remote_client_addr);
1052 if (rc < 0) {
1053 DEBUG(0, ("Out of memory building magic ncalrpc_as_system path!\n"));
1054 talloc_free(ncacn_conn);
1055 close(s);
1056 return;
1059 TALLOC_FREE(ncacn_conn->remote_client_name);
1060 ncacn_conn->remote_client_name
1061 = tsocket_address_unix_path(ncacn_conn->remote_client_addr,
1062 ncacn_conn);
1063 if (ncacn_conn->remote_client_name == NULL) {
1064 DEBUG(0, ("Out of memory getting magic ncalrpc_as_system string!\n"));
1065 talloc_free(ncacn_conn);
1066 close(s);
1067 return;
1072 FALL_THROUGH;
1073 case NCACN_NP:
1074 pipe_name = talloc_strdup(ncacn_conn,
1075 name);
1076 if (pipe_name == NULL) {
1077 close(s);
1078 talloc_free(ncacn_conn);
1079 return;
1081 break;
1082 default:
1083 DEBUG(0, ("unknown dcerpc transport: %u!\n",
1084 transport));
1085 talloc_free(ncacn_conn);
1086 close(s);
1087 return;
1090 rc = set_blocking(s, false);
1091 if (rc < 0) {
1092 DEBUG(2, ("Failed to set dcerpc socket to non-blocking\n"));
1093 talloc_free(ncacn_conn);
1094 close(s);
1095 return;
1099 * As soon as we have tstream_bsd_existing_socket set up it will
1100 * take care of closing the socket.
1102 rc = tstream_bsd_existing_socket(ncacn_conn, s, &ncacn_conn->tstream);
1103 if (rc < 0) {
1104 DEBUG(2, ("Failed to create tstream socket for dcerpc\n"));
1105 talloc_free(ncacn_conn);
1106 close(s);
1107 return;
1110 if (ncacn_conn->session_info == NULL) {
1111 status = make_session_info_anonymous(ncacn_conn,
1112 &ncacn_conn->session_info);
1113 if (!NT_STATUS_IS_OK(status)) {
1114 DEBUG(2, ("Failed to create "
1115 "make_session_info_anonymous - %s\n",
1116 nt_errstr(status)));
1117 talloc_free(ncacn_conn);
1118 return;
1122 rc = make_server_pipes_struct(ncacn_conn,
1123 ncacn_conn->msg_ctx,
1124 pipe_name,
1125 ncacn_conn->transport,
1126 ncacn_conn->remote_client_addr,
1127 ncacn_conn->local_server_addr,
1128 ncacn_conn->session_info,
1129 &ncacn_conn->p,
1130 &sys_errno);
1131 if (rc < 0) {
1132 DEBUG(2, ("Failed to create pipe struct - %s",
1133 strerror(sys_errno)));
1134 talloc_free(ncacn_conn);
1135 return;
1138 ncacn_conn->send_queue = tevent_queue_create(ncacn_conn,
1139 "dcerpc send queue");
1140 if (ncacn_conn->send_queue == NULL) {
1141 DEBUG(0, ("Out of memory building dcerpc send queue!\n"));
1142 talloc_free(ncacn_conn);
1143 return;
1146 subreq = dcerpc_read_ncacn_packet_send(ncacn_conn,
1147 ncacn_conn->ev_ctx,
1148 ncacn_conn->tstream);
1149 if (subreq == NULL) {
1150 DEBUG(2, ("Failed to send ncacn packet\n"));
1151 talloc_free(ncacn_conn);
1152 return;
1155 tevent_req_set_callback(subreq, dcerpc_ncacn_packet_process, ncacn_conn);
1157 DEBUG(10, ("dcerpc_ncacn_accept done\n"));
1159 return;
1162 static void dcerpc_ncacn_packet_process(struct tevent_req *subreq)
1164 struct dcerpc_ncacn_conn *ncacn_conn =
1165 tevent_req_callback_data(subreq, struct dcerpc_ncacn_conn);
1167 struct _output_data *out = &ncacn_conn->p->out_data;
1168 DATA_BLOB recv_buffer = data_blob_null;
1169 struct ncacn_packet *pkt;
1170 uint32_t to_send;
1171 NTSTATUS status;
1172 bool ok;
1174 status = dcerpc_read_ncacn_packet_recv(subreq, ncacn_conn, &pkt, &recv_buffer);
1175 TALLOC_FREE(subreq);
1176 if (!NT_STATUS_IS_OK(status)) {
1177 if (ncacn_conn->disconnect_fn != NULL) {
1178 ok = ncacn_conn->disconnect_fn(ncacn_conn->p);
1179 if (!ok) {
1180 DEBUG(3, ("Failed to call disconnect function\n"));
1183 goto fail;
1186 /* dcerpc_read_ncacn_packet_recv() returns a full PDU */
1187 ncacn_conn->p->in_data.pdu_needed_len = 0;
1188 ncacn_conn->p->in_data.pdu = recv_buffer;
1189 if (dcerpc_get_endian_flag(&recv_buffer) & DCERPC_DREP_LE) {
1190 ncacn_conn->p->endian = RPC_LITTLE_ENDIAN;
1191 } else {
1192 ncacn_conn->p->endian = RPC_BIG_ENDIAN;
1194 DEBUG(10, ("PDU is in %s Endian format!\n",
1195 ncacn_conn->p->endian ? "Big" : "Little"));
1196 process_complete_pdu(ncacn_conn->p, pkt);
1198 /* reset pipe state and free PDU */
1199 ncacn_conn->p->in_data.pdu.length = 0;
1200 talloc_free(recv_buffer.data);
1201 talloc_free(pkt);
1204 * This is needed because of the way DCERPC binds work in the RPC
1205 * marshalling code
1207 to_send = out->frag.length - out->current_pdu_sent;
1208 if (to_send > 0) {
1210 DEBUG(10, ("Current_pdu_len = %u, "
1211 "current_pdu_sent = %u "
1212 "Returning %u bytes\n",
1213 (unsigned int)out->frag.length,
1214 (unsigned int)out->current_pdu_sent,
1215 (unsigned int)to_send));
1217 ncacn_conn->iov = talloc_zero(ncacn_conn, struct iovec);
1218 if (ncacn_conn->iov == NULL) {
1219 status = NT_STATUS_NO_MEMORY;
1220 DEBUG(3, ("Out of memory!\n"));
1221 goto fail;
1223 ncacn_conn->count = 1;
1225 ncacn_conn->iov[0].iov_base = out->frag.data
1226 + out->current_pdu_sent;
1227 ncacn_conn->iov[0].iov_len = to_send;
1229 out->current_pdu_sent += to_send;
1233 * This condition is false for bind packets, or when we haven't yet got
1234 * a full request, and need to wait for more data from the client
1236 while (out->data_sent_length < out->rdata.length) {
1237 ok = create_next_pdu(ncacn_conn->p);
1238 if (!ok) {
1239 DEBUG(3, ("Failed to create next PDU!\n"));
1240 status = NT_STATUS_UNEXPECTED_IO_ERROR;
1241 goto fail;
1244 ncacn_conn->iov = talloc_realloc(ncacn_conn,
1245 ncacn_conn->iov,
1246 struct iovec,
1247 ncacn_conn->count + 1);
1248 if (ncacn_conn->iov == NULL) {
1249 DEBUG(3, ("Out of memory!\n"));
1250 status = NT_STATUS_NO_MEMORY;
1251 goto fail;
1254 ncacn_conn->iov[ncacn_conn->count].iov_base = out->frag.data;
1255 ncacn_conn->iov[ncacn_conn->count].iov_len = out->frag.length;
1257 DEBUG(10, ("PDU number: %d, PDU Length: %u\n",
1258 (unsigned int) ncacn_conn->count,
1259 (unsigned int) ncacn_conn->iov[ncacn_conn->count].iov_len));
1260 dump_data(11, (const uint8_t *) ncacn_conn->iov[ncacn_conn->count].iov_base,
1261 ncacn_conn->iov[ncacn_conn->count].iov_len);
1262 ncacn_conn->count++;
1266 * We still don't have a complete request, go back and wait for more
1267 * data.
1269 if (ncacn_conn->count == 0) {
1270 /* Wait for the next packet */
1271 subreq = dcerpc_read_ncacn_packet_send(ncacn_conn,
1272 ncacn_conn->ev_ctx,
1273 ncacn_conn->tstream);
1274 if (subreq == NULL) {
1275 DEBUG(2, ("Failed to start receving packets\n"));
1276 status = NT_STATUS_NO_MEMORY;
1277 goto fail;
1279 tevent_req_set_callback(subreq, dcerpc_ncacn_packet_process, ncacn_conn);
1280 return;
1283 DEBUG(10, ("Sending a total of %u bytes\n",
1284 (unsigned int)ncacn_conn->p->out_data.data_sent_length));
1286 subreq = tstream_writev_queue_send(ncacn_conn,
1287 ncacn_conn->ev_ctx,
1288 ncacn_conn->tstream,
1289 ncacn_conn->send_queue,
1290 ncacn_conn->iov,
1291 ncacn_conn->count);
1292 if (subreq == NULL) {
1293 DEBUG(2, ("Failed to send packet\n"));
1294 status = NT_STATUS_NO_MEMORY;
1295 goto fail;
1298 tevent_req_set_callback(subreq, dcerpc_ncacn_packet_done, ncacn_conn);
1299 return;
1301 fail:
1302 DEBUG(3, ("Terminating client(%s) connection! - '%s'\n",
1303 ncacn_conn->remote_client_name, nt_errstr(status)));
1305 /* Terminate client connection */
1306 talloc_free(ncacn_conn);
1307 return;
1310 static void dcerpc_ncacn_packet_done(struct tevent_req *subreq)
1312 struct dcerpc_ncacn_conn *ncacn_conn =
1313 tevent_req_callback_data(subreq, struct dcerpc_ncacn_conn);
1314 NTSTATUS status = NT_STATUS_OK;
1315 int sys_errno;
1316 int rc;
1318 rc = tstream_writev_queue_recv(subreq, &sys_errno);
1319 TALLOC_FREE(subreq);
1320 if (rc < 0) {
1321 DEBUG(2, ("Writev failed!\n"));
1322 status = map_nt_error_from_unix(sys_errno);
1323 goto fail;
1326 if (ncacn_conn->p->fault_state != 0) {
1327 DEBUG(2, ("Disconnect after fault\n"));
1328 sys_errno = EINVAL;
1329 goto fail;
1332 /* clear out any data that may have been left around */
1333 ncacn_conn->count = 0;
1334 TALLOC_FREE(ncacn_conn->iov);
1335 data_blob_free(&ncacn_conn->p->in_data.data);
1336 data_blob_free(&ncacn_conn->p->out_data.frag);
1337 data_blob_free(&ncacn_conn->p->out_data.rdata);
1339 talloc_free_children(ncacn_conn->p->mem_ctx);
1341 /* Wait for the next packet */
1342 subreq = dcerpc_read_ncacn_packet_send(ncacn_conn,
1343 ncacn_conn->ev_ctx,
1344 ncacn_conn->tstream);
1345 if (subreq == NULL) {
1346 DEBUG(2, ("Failed to start receving packets\n"));
1347 status = NT_STATUS_NO_MEMORY;
1348 goto fail;
1351 tevent_req_set_callback(subreq, dcerpc_ncacn_packet_process, ncacn_conn);
1352 return;
1354 fail:
1355 DEBUG(3, ("Terminating client(%s) connection! - '%s'\n",
1356 ncacn_conn->remote_client_name, nt_errstr(status)));
1358 /* Terminate client connection */
1359 talloc_free(ncacn_conn);
1360 return;
1363 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */