selftest split $PERL into multiple arguments for Test::More check
[Samba.git] / source3 / rpc_server / rpc_server.c
blob1e1e707860ad10f713a590bfae54404377c5dc6b
1 /*
2 Unix SMB/Netbios implementation.
3 Generic infrstructure for RPC Daemons
4 Copyright (C) Simo Sorce 2010
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "rpc_server/rpc_server.h"
22 #include "rpc_dce.h"
23 #include "librpc/gen_ndr/netlogon.h"
24 #include "librpc/gen_ndr/auth.h"
25 #include "registry/reg_parse_prs.h"
26 #include "lib/tsocket/tsocket.h"
27 #include "libcli/named_pipe_auth/npa_tstream.h"
28 #include "../auth/auth_sam_reply.h"
30 #define SERVER_TCP_LOW_PORT 1024
31 #define SERVER_TCP_HIGH_PORT 1300
33 static NTSTATUS auth_anonymous_session_info(TALLOC_CTX *mem_ctx,
34 struct auth_session_info_transport **session_info)
36 struct auth_session_info_transport *i;
37 struct auth_serversupplied_info *s;
38 struct auth_user_info_dc *u;
39 union netr_Validation val;
40 NTSTATUS status;
42 i = talloc_zero(mem_ctx, struct auth_session_info_transport);
43 if (i == NULL) {
44 return NT_STATUS_NO_MEMORY;
47 status = make_server_info_guest(i, &s);
48 if (!NT_STATUS_IS_OK(status)) {
49 return status;
52 i->security_token = s->security_token;
53 i->session_key = s->user_session_key;
55 val.sam3 = s->info3;
57 status = make_user_info_dc_netlogon_validation(mem_ctx,
58 "",
60 &val,
61 &u);
62 if (!NT_STATUS_IS_OK(status)) {
63 DEBUG(0, ("conversion of info3 into user_info_dc failed!\n"));
64 return status;
66 i->info = talloc_move(i, &u->info);
67 talloc_free(u);
69 *session_info = i;
71 return NT_STATUS_OK;
74 /* Creates a pipes_struct and initializes it with the information
75 * sent from the client */
76 static int make_server_pipes_struct(TALLOC_CTX *mem_ctx,
77 const char *pipe_name,
78 const struct ndr_syntax_id id,
79 const char *client_address,
80 struct auth_session_info_transport *session_info,
81 struct pipes_struct **_p,
82 int *perrno)
84 struct netr_SamInfo3 *info3;
85 struct auth_user_info_dc *auth_user_info_dc;
86 struct pipes_struct *p;
87 NTSTATUS status;
88 bool ok;
90 p = talloc_zero(mem_ctx, struct pipes_struct);
91 if (!p) {
92 *perrno = ENOMEM;
93 return -1;
95 p->syntax = id;
97 p->mem_ctx = talloc_named(p, 0, "pipe %s %p", pipe_name, p);
98 if (!p->mem_ctx) {
99 TALLOC_FREE(p);
100 *perrno = ENOMEM;
101 return -1;
104 ok = init_pipe_handles(p, &id);
105 if (!ok) {
106 DEBUG(1, ("Failed to init handles\n"));
107 TALLOC_FREE(p);
108 *perrno = EINVAL;
109 return -1;
113 data_blob_free(&p->in_data.data);
114 data_blob_free(&p->in_data.pdu);
116 p->endian = RPC_LITTLE_ENDIAN;
118 /* Fake up an auth_user_info_dc for now, to make an info3, to make the server_info structure */
119 auth_user_info_dc = talloc_zero(p, struct auth_user_info_dc);
120 if (!auth_user_info_dc) {
121 TALLOC_FREE(p);
122 *perrno = ENOMEM;
123 return -1;
126 auth_user_info_dc->num_sids = session_info->security_token->num_sids;
127 auth_user_info_dc->sids = session_info->security_token->sids;
128 auth_user_info_dc->info = session_info->info;
129 auth_user_info_dc->user_session_key = session_info->session_key;
131 /* This creates the input structure that make_server_info_info3 is looking for */
132 status = auth_convert_user_info_dc_saminfo3(p, auth_user_info_dc,
133 &info3);
135 if (!NT_STATUS_IS_OK(status)) {
136 DEBUG(1, ("Failed to convert auth_user_info_dc into netr_SamInfo3\n"));
137 TALLOC_FREE(p);
138 *perrno = EINVAL;
139 return -1;
142 status = make_server_info_info3(p,
143 info3->base.account_name.string,
144 info3->base.domain.string,
145 &p->server_info, info3);
146 if (!NT_STATUS_IS_OK(status)) {
147 DEBUG(1, ("Failed to init server info\n"));
148 TALLOC_FREE(p);
149 *perrno = EINVAL;
150 return -1;
154 * Some internal functions need a local token to determine access to
155 * resoutrces.
157 status = create_local_token(p->server_info);
158 if (!NT_STATUS_IS_OK(status)) {
159 DEBUG(1, ("Failed to init local auth token\n"));
160 TALLOC_FREE(p);
161 *perrno = EINVAL;
162 return -1;
165 /* Now override the server_info->security_token with the exact
166 * security_token we were given from the other side,
167 * regardless of what we just calculated */
168 p->server_info->security_token = talloc_move(p->server_info, &session_info->security_token);
170 /* Also set the session key to the correct value */
171 p->server_info->user_session_key = session_info->session_key;
172 p->server_info->user_session_key.data = talloc_move(p->server_info, &session_info->session_key.data);
174 p->client_id = talloc_zero(p, struct client_address);
175 if (!p->client_id) {
176 TALLOC_FREE(p);
177 *perrno = ENOMEM;
178 return -1;
180 strlcpy(p->client_id->addr,
181 client_address, sizeof(p->client_id->addr));
182 p->client_id->name = talloc_strdup(p->client_id, client_address);
183 if (p->client_id->name == NULL) {
184 TALLOC_FREE(p);
185 *perrno = ENOMEM;
186 return -1;
189 talloc_set_destructor(p, close_internal_rpc_pipe_hnd);
191 *_p = p;
192 return 0;
195 /* Add some helper functions to wrap the common ncacn packet reading functions
196 * until we can share more dcerpc code */
197 struct dcerpc_ncacn_read_packet_state {
198 struct ncacn_packet *pkt;
199 DATA_BLOB buffer;
202 static void dcerpc_ncacn_read_packet_done(struct tevent_req *subreq);
204 static struct tevent_req *dcerpc_ncacn_read_packet_send(TALLOC_CTX *mem_ctx,
205 struct tevent_context *ev,
206 struct tstream_context *tstream)
208 struct dcerpc_ncacn_read_packet_state *state;
209 struct tevent_req *req, *subreq;
211 req = tevent_req_create(mem_ctx, &state,
212 struct dcerpc_ncacn_read_packet_state);
213 if (!req) {
214 return NULL;
216 ZERO_STRUCTP(state);
218 subreq = dcerpc_read_ncacn_packet_send(state, ev, tstream);
219 if (!subreq) {
220 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
221 tevent_req_post(req, ev);
222 return req;
224 tevent_req_set_callback(subreq, dcerpc_ncacn_read_packet_done, req);
226 return req;
229 static void dcerpc_ncacn_read_packet_done(struct tevent_req *subreq)
231 struct tevent_req *req =
232 tevent_req_callback_data(subreq, struct tevent_req);
233 struct dcerpc_ncacn_read_packet_state *state =
234 tevent_req_data(req, struct dcerpc_ncacn_read_packet_state);
235 NTSTATUS status;
237 status = dcerpc_read_ncacn_packet_recv(subreq, state,
238 &state->pkt,
239 &state->buffer);
240 TALLOC_FREE(subreq);
241 if (!NT_STATUS_IS_OK(status)) {
242 DEBUG(3, ("Failed to receive dceprc packet!\n"));
243 tevent_req_nterror(req, status);
244 return;
247 tevent_req_done(req);
250 static NTSTATUS dcerpc_ncacn_read_packet_recv(struct tevent_req *req,
251 TALLOC_CTX *mem_ctx,
252 DATA_BLOB *buffer)
254 struct dcerpc_ncacn_read_packet_state *state =
255 tevent_req_data(req, struct dcerpc_ncacn_read_packet_state);
256 NTSTATUS status;
258 if (tevent_req_is_nterror(req, &status)) {
259 tevent_req_received(req);
260 return status;
263 buffer->data = talloc_move(mem_ctx, &state->buffer.data);
264 buffer->length = state->buffer.length;
266 tevent_req_received(req);
267 return NT_STATUS_OK;
272 /* Start listening on the appropriate unix socket and setup all is needed to
273 * dispatch requests to the pipes rpc implementation */
275 struct dcerpc_ncacn_listen_state {
276 struct ndr_syntax_id syntax_id;
278 int fd;
279 union {
280 char *name;
281 uint16_t port;
282 } ep;
284 struct tevent_context *ev_ctx;
285 struct messaging_context *msg_ctx;
288 static void named_pipe_listener(struct tevent_context *ev,
289 struct tevent_fd *fde,
290 uint16_t flags,
291 void *private_data);
293 bool setup_named_pipe_socket(const char *pipe_name,
294 struct tevent_context *ev_ctx)
296 struct dcerpc_ncacn_listen_state *state;
297 struct tevent_fd *fde;
298 char *np_dir;
300 state = talloc(ev_ctx, struct dcerpc_ncacn_listen_state);
301 if (!state) {
302 DEBUG(0, ("Out of memory\n"));
303 return false;
305 state->ep.name = talloc_strdup(state, pipe_name);
306 if (state->ep.name == NULL) {
307 DEBUG(0, ("Out of memory\n"));
308 goto out;
310 state->fd = -1;
312 np_dir = talloc_asprintf(state, "%s/np", lp_ncalrpc_dir());
313 if (!np_dir) {
314 DEBUG(0, ("Out of memory\n"));
315 goto out;
318 if (!directory_create_or_exist(np_dir, geteuid(), 0700)) {
319 DEBUG(0, ("Failed to create pipe directory %s - %s\n",
320 np_dir, strerror(errno)));
321 goto out;
324 state->fd = create_pipe_sock(np_dir, pipe_name, 0700);
325 if (state->fd == -1) {
326 DEBUG(0, ("Failed to create pipe socket! [%s/%s]\n",
327 np_dir, pipe_name));
328 goto out;
331 DEBUG(10, ("Openened pipe socket fd %d for %s\n",
332 state->fd, pipe_name));
334 fde = tevent_add_fd(ev_ctx,
335 state, state->fd, TEVENT_FD_READ,
336 named_pipe_listener, state);
337 if (!fde) {
338 DEBUG(0, ("Failed to add event handler!\n"));
339 goto out;
342 tevent_fd_set_auto_close(fde);
343 return true;
345 out:
346 if (state->fd != -1) {
347 close(state->fd);
349 TALLOC_FREE(state);
350 return false;
353 static void named_pipe_accept_function(const char *pipe_name, int fd);
355 static void named_pipe_listener(struct tevent_context *ev,
356 struct tevent_fd *fde,
357 uint16_t flags,
358 void *private_data)
360 struct dcerpc_ncacn_listen_state *state =
361 talloc_get_type_abort(private_data,
362 struct dcerpc_ncacn_listen_state);
363 struct sockaddr_un sunaddr;
364 socklen_t len;
365 int sd = -1;
367 /* TODO: should we have a limit to the number of clients ? */
369 len = sizeof(sunaddr);
371 while (sd == -1) {
372 sd = accept(state->fd,
373 (struct sockaddr *)(void *)&sunaddr, &len);
374 if (errno != EINTR) break;
377 if (sd == -1) {
378 DEBUG(6, ("Failed to get a valid socket [%s]\n",
379 strerror(errno)));
380 return;
383 DEBUG(6, ("Accepted socket %d\n", sd));
385 named_pipe_accept_function(state->ep.name, sd);
389 /* This is the core of the rpc server.
390 * Accepts connections from clients and process requests using the appropriate
391 * dispatcher table. */
393 struct named_pipe_client {
394 const char *pipe_name;
395 struct ndr_syntax_id pipe_id;
397 struct tevent_context *ev;
398 struct messaging_context *msg_ctx;
400 uint16_t file_type;
401 uint16_t device_state;
402 uint64_t allocation_size;
404 struct tstream_context *tstream;
406 struct tsocket_address *client;
407 char *client_name;
408 struct tsocket_address *server;
409 char *server_name;
410 struct auth_session_info_transport *session_info;
412 struct pipes_struct *p;
414 struct tevent_queue *write_queue;
416 struct iovec *iov;
417 size_t count;
420 static void named_pipe_accept_done(struct tevent_req *subreq);
422 static void named_pipe_accept_function(const char *pipe_name, int fd)
424 struct ndr_syntax_id syntax;
425 struct named_pipe_client *npc;
426 struct tstream_context *plain;
427 struct tevent_req *subreq;
428 bool ok;
429 int ret;
431 ok = is_known_pipename(pipe_name, &syntax);
432 if (!ok) {
433 DEBUG(1, ("Unknown pipe [%s]\n", pipe_name));
434 close(fd);
435 return;
438 npc = talloc_zero(NULL, struct named_pipe_client);
439 if (!npc) {
440 DEBUG(0, ("Out of memory!\n"));
441 close(fd);
442 return;
444 npc->pipe_name = pipe_name;
445 npc->pipe_id = syntax;
446 npc->ev = server_event_context();
447 npc->msg_ctx = server_messaging_context();
449 /* make sure socket is in NON blocking state */
450 ret = set_blocking(fd, false);
451 if (ret != 0) {
452 DEBUG(2, ("Failed to make socket non-blocking\n"));
453 TALLOC_FREE(npc);
454 close(fd);
455 return;
458 ret = tstream_bsd_existing_socket(npc, fd, &plain);
459 if (ret != 0) {
460 DEBUG(2, ("Failed to create tstream socket\n"));
461 TALLOC_FREE(npc);
462 close(fd);
463 return;
466 npc->file_type = FILE_TYPE_MESSAGE_MODE_PIPE;
467 npc->device_state = 0xff | 0x0400 | 0x0100;
468 npc->allocation_size = 4096;
470 subreq = tstream_npa_accept_existing_send(npc, npc->ev, plain,
471 npc->file_type,
472 npc->device_state,
473 npc->allocation_size);
474 if (!subreq) {
475 DEBUG(2, ("Failed to start async accept procedure\n"));
476 TALLOC_FREE(npc);
477 close(fd);
478 return;
480 tevent_req_set_callback(subreq, named_pipe_accept_done, npc);
483 static void named_pipe_packet_process(struct tevent_req *subreq);
484 static void named_pipe_packet_done(struct tevent_req *subreq);
486 static void named_pipe_accept_done(struct tevent_req *subreq)
488 struct named_pipe_client *npc =
489 tevent_req_callback_data(subreq, struct named_pipe_client);
490 const char *cli_addr;
491 int error;
492 int ret;
494 ret = tstream_npa_accept_existing_recv(subreq, &error, npc,
495 &npc->tstream,
496 &npc->client,
497 &npc->client_name,
498 &npc->server,
499 &npc->server_name,
500 &npc->session_info);
501 TALLOC_FREE(subreq);
502 if (ret != 0) {
503 DEBUG(2, ("Failed to accept named pipe connection! (%s)\n",
504 strerror(error)));
505 TALLOC_FREE(npc);
506 return;
509 if (tsocket_address_is_inet(npc->client, "ip")) {
510 cli_addr = tsocket_address_inet_addr_string(npc->client,
511 subreq);
512 if (cli_addr == NULL) {
513 TALLOC_FREE(npc);
514 return;
516 } else {
517 cli_addr = "";
520 ret = make_server_pipes_struct(npc,
521 npc->pipe_name, npc->pipe_id,
522 cli_addr, npc->session_info,
523 &npc->p, &error);
524 if (ret != 0) {
525 DEBUG(2, ("Failed to create pipes_struct! (%s)\n",
526 strerror(error)));
527 goto fail;
529 npc->p->msg_ctx = npc->msg_ctx;
531 npc->write_queue = tevent_queue_create(npc, "np_server_write_queue");
532 if (!npc->write_queue) {
533 DEBUG(2, ("Failed to set up write queue!\n"));
534 goto fail;
537 /* And now start receaving and processing packets */
538 subreq = dcerpc_ncacn_read_packet_send(npc, npc->ev, npc->tstream);
539 if (!subreq) {
540 DEBUG(2, ("Failed to start receving packets\n"));
541 goto fail;
543 tevent_req_set_callback(subreq, named_pipe_packet_process, npc);
544 return;
546 fail:
547 DEBUG(2, ("Fatal error. Terminating client(%s) connection!\n",
548 npc->client_name));
549 /* terminate client connection */
550 talloc_free(npc);
551 return;
554 static void named_pipe_packet_process(struct tevent_req *subreq)
556 struct named_pipe_client *npc =
557 tevent_req_callback_data(subreq, struct named_pipe_client);
558 struct _output_data *out = &npc->p->out_data;
559 DATA_BLOB recv_buffer = data_blob_null;
560 NTSTATUS status;
561 ssize_t data_left;
562 ssize_t data_used;
563 char *data;
564 uint32_t to_send;
565 bool ok;
567 status = dcerpc_ncacn_read_packet_recv(subreq, npc, &recv_buffer);
568 TALLOC_FREE(subreq);
569 if (!NT_STATUS_IS_OK(status)) {
570 goto fail;
573 data_left = recv_buffer.length;
574 data = (char *)recv_buffer.data;
576 while (data_left) {
578 data_used = process_incoming_data(npc->p, data, data_left);
579 if (data_used < 0) {
580 DEBUG(3, ("Failed to process dceprc request!\n"));
581 status = NT_STATUS_UNEXPECTED_IO_ERROR;
582 goto fail;
585 data_left -= data_used;
586 data += data_used;
589 /* Do not leak this buffer, npc is a long lived context */
590 talloc_free(recv_buffer.data);
592 /* this is needed because of the way DCERPC Binds work in
593 * the RPC marshalling code */
594 to_send = out->frag.length - out->current_pdu_sent;
595 if (to_send > 0) {
597 DEBUG(10, ("Current_pdu_len = %u, "
598 "current_pdu_sent = %u "
599 "Returning %u bytes\n",
600 (unsigned int)out->frag.length,
601 (unsigned int)out->current_pdu_sent,
602 (unsigned int)to_send));
604 npc->iov = talloc_zero(npc, struct iovec);
605 if (!npc->iov) {
606 status = NT_STATUS_NO_MEMORY;
607 goto fail;
609 npc->count = 1;
611 npc->iov[0].iov_base = out->frag.data
612 + out->current_pdu_sent;
613 npc->iov[0].iov_len = to_send;
615 out->current_pdu_sent += to_send;
618 /* this condition is false for bind packets, or when we haven't
619 * yet got a full request, and need to wait for more data from
620 * the client */
621 while (out->data_sent_length < out->rdata.length) {
623 ok = create_next_pdu(npc->p);
624 if (!ok) {
625 DEBUG(3, ("Failed to create next PDU!\n"));
626 status = NT_STATUS_UNEXPECTED_IO_ERROR;
627 goto fail;
630 npc->iov = talloc_realloc(npc, npc->iov,
631 struct iovec, npc->count + 1);
632 if (!npc->iov) {
633 status = NT_STATUS_NO_MEMORY;
634 goto fail;
637 npc->iov[npc->count].iov_base = out->frag.data;
638 npc->iov[npc->count].iov_len = out->frag.length;
640 DEBUG(10, ("PDU number: %d, PDU Length: %u\n",
641 (unsigned int)npc->count,
642 (unsigned int)npc->iov[npc->count].iov_len));
643 dump_data(11, (const uint8_t *)npc->iov[npc->count].iov_base,
644 npc->iov[npc->count].iov_len);
645 npc->count++;
648 /* we still don't have a complete request, go back and wait for more
649 * data */
650 if (npc->count == 0) {
651 /* Wait for the next packet */
652 subreq = dcerpc_ncacn_read_packet_send(npc, npc->ev, npc->tstream);
653 if (!subreq) {
654 DEBUG(2, ("Failed to start receving packets\n"));
655 status = NT_STATUS_NO_MEMORY;
656 goto fail;
658 tevent_req_set_callback(subreq, named_pipe_packet_process, npc);
659 return;
662 DEBUG(10, ("Sending a total of %u bytes\n",
663 (unsigned int)npc->p->out_data.data_sent_length));
665 subreq = tstream_writev_queue_send(npc, npc->ev,
666 npc->tstream,
667 npc->write_queue,
668 npc->iov, npc->count);
669 if (!subreq) {
670 DEBUG(2, ("Failed to send packet\n"));
671 status = NT_STATUS_NO_MEMORY;
672 goto fail;
674 tevent_req_set_callback(subreq, named_pipe_packet_done, npc);
675 return;
677 fail:
678 DEBUG(2, ("Fatal error(%s). "
679 "Terminating client(%s) connection!\n",
680 nt_errstr(status), npc->client_name));
681 /* terminate client connection */
682 talloc_free(npc);
683 return;
686 static void named_pipe_packet_done(struct tevent_req *subreq)
688 struct named_pipe_client *npc =
689 tevent_req_callback_data(subreq, struct named_pipe_client);
690 int sys_errno;
691 int ret;
693 ret = tstream_writev_queue_recv(subreq, &sys_errno);
694 TALLOC_FREE(subreq);
695 if (ret == -1) {
696 DEBUG(2, ("Writev failed!\n"));
697 goto fail;
700 /* clear out any data that may have been left around */
701 npc->count = 0;
702 TALLOC_FREE(npc->iov);
703 data_blob_free(&npc->p->in_data.data);
704 data_blob_free(&npc->p->out_data.frag);
705 data_blob_free(&npc->p->out_data.rdata);
707 /* Wait for the next packet */
708 subreq = dcerpc_ncacn_read_packet_send(npc, npc->ev, npc->tstream);
709 if (!subreq) {
710 DEBUG(2, ("Failed to start receving packets\n"));
711 sys_errno = ENOMEM;
712 goto fail;
714 tevent_req_set_callback(subreq, named_pipe_packet_process, npc);
715 return;
717 fail:
718 DEBUG(2, ("Fatal error(%s). "
719 "Terminating client(%s) connection!\n",
720 strerror(sys_errno), npc->client_name));
721 /* terminate client connection */
722 talloc_free(npc);
723 return;
726 /********************************************************************
727 * Start listening on the tcp/ip socket
728 ********************************************************************/
730 static void dcerpc_ncacn_tcpip_listener(struct tevent_context *ev,
731 struct tevent_fd *fde,
732 uint16_t flags,
733 void *private_data);
735 uint16_t setup_dcerpc_ncacn_tcpip_socket(struct tevent_context *ev_ctx,
736 struct messaging_context *msg_ctx,
737 struct ndr_syntax_id syntax_id,
738 const struct sockaddr_storage *ifss,
739 uint16_t port)
741 struct dcerpc_ncacn_listen_state *state;
742 struct tevent_fd *fde;
743 int rc;
745 state = talloc(ev_ctx, struct dcerpc_ncacn_listen_state);
746 if (state == NULL) {
747 DEBUG(0, ("setup_dcerpc_ncacn_tcpip_socket: Out of memory\n"));
748 return false;
751 state->syntax_id = syntax_id;
752 state->fd = -1;
753 state->ep.port = port;
755 if (state->ep.port == 0) {
756 uint16_t i;
758 for (i = SERVER_TCP_LOW_PORT; i <= SERVER_TCP_HIGH_PORT; i++) {
759 state->fd = open_socket_in(SOCK_STREAM,
762 ifss,
763 false);
764 if (state->fd > 0) {
765 state->ep.port = i;
766 break;
769 } else {
770 state->fd = open_socket_in(SOCK_STREAM,
771 state->ep.port,
773 ifss,
774 true);
776 if (state->fd == -1) {
777 DEBUG(0, ("setup_dcerpc_ncacn_tcpip_socket: Failed to create "
778 "socket on port %u!\n", state->ep.port));
779 goto out;
782 state->ev_ctx = ev_ctx;
783 state->msg_ctx = msg_ctx;
785 /* ready to listen */
786 set_socket_options(state->fd, "SO_KEEPALIVE");
787 set_socket_options(state->fd, lp_socket_options());
789 /* Set server socket to non-blocking for the accept. */
790 set_blocking(state->fd, false);
792 rc = listen(state->fd, SMBD_LISTEN_BACKLOG);
793 if (rc == -1) {
794 DEBUG(0,("setup_tcpip_socket: listen - %s\n", strerror(errno)));
795 goto out;
798 DEBUG(10, ("setup_tcpip_socket: openened socket fd %d for port %u\n",
799 state->fd, state->ep.port));
801 fde = tevent_add_fd(state->ev_ctx,
802 state,
803 state->fd,
804 TEVENT_FD_READ,
805 dcerpc_ncacn_tcpip_listener,
806 state);
807 if (fde == NULL) {
808 DEBUG(0, ("setup_tcpip_socket: Failed to add event handler!\n"));
809 goto out;
812 tevent_fd_set_auto_close(fde);
814 return state->ep.port;
815 out:
816 if (state->fd != -1) {
817 close(state->fd);
819 TALLOC_FREE(state);
821 return 0;
824 static void dcerpc_ncacn_accept(struct tevent_context *ev_ctx,
825 struct messaging_context *msg_ctx,
826 struct ndr_syntax_id syntax_id,
827 enum dcerpc_transport_t transport,
828 const char *name,
829 uint16_t port,
830 struct tsocket_address *cli_addr,
831 int s);
833 static void dcerpc_ncacn_tcpip_listener(struct tevent_context *ev,
834 struct tevent_fd *fde,
835 uint16_t flags,
836 void *private_data)
838 struct dcerpc_ncacn_listen_state *state =
839 talloc_get_type_abort(private_data,
840 struct dcerpc_ncacn_listen_state);
841 struct tsocket_address *cli_addr;
842 struct sockaddr_storage addr;
843 socklen_t in_addrlen = sizeof(addr);
844 int s = -1;
845 int rc;
847 while (s == -1) {
848 s = accept(state->fd, (struct sockaddr *)(void *) &addr, &in_addrlen);
849 if (s == -1 && errno != EINTR) {
850 break;
854 if (s == -1) {
855 DEBUG(0,("tcpip_listener accept: %s\n",
856 strerror(errno)));
857 return;
860 rc = tsocket_address_bsd_from_sockaddr(state,
861 (struct sockaddr *)(void *) &addr,
862 in_addrlen,
863 &cli_addr);
864 if (rc < 0) {
865 close(s);
866 return;
869 DEBUG(6, ("tcpip_listener: Accepted socket %d\n", s));
871 dcerpc_ncacn_accept(state->ev_ctx,
872 state->msg_ctx,
873 state->syntax_id,
874 NCACN_IP_TCP,
875 NULL,
876 state->ep.port,
877 cli_addr,
881 struct dcerpc_ncacn_conn {
882 struct ndr_syntax_id syntax_id;
884 enum dcerpc_transport_t transport;
886 union {
887 const char *name;
888 uint16_t port;
889 } ep;
891 int sock;
893 struct pipes_struct *p;
895 struct tevent_context *ev_ctx;
896 struct messaging_context *msg_ctx;
898 struct tstream_context *tstream;
899 struct tevent_queue *send_queue;
901 struct tsocket_address *client;
902 char *client_name;
903 struct tsocket_address *server;
904 char *server_name;
905 struct auth_session_info_transport *session_info;
907 struct iovec *iov;
908 size_t count;
911 static void dcerpc_ncacn_packet_process(struct tevent_req *subreq);
912 static void dcerpc_ncacn_packet_done(struct tevent_req *subreq);
914 static void dcerpc_ncacn_accept(struct tevent_context *ev_ctx,
915 struct messaging_context *msg_ctx,
916 struct ndr_syntax_id syntax_id,
917 enum dcerpc_transport_t transport,
918 const char *name,
919 uint16_t port,
920 struct tsocket_address *cli_addr,
921 int s) {
922 struct dcerpc_ncacn_conn *ncacn_conn;
923 struct tevent_req *subreq;
924 const char *cli_str;
925 char *pipe_name;
926 NTSTATUS status;
927 int sys_errno;
928 int rc;
930 DEBUG(5, ("dcerpc_ncacn_accept\n"));
932 ncacn_conn = talloc_zero(ev_ctx, struct dcerpc_ncacn_conn);
933 if (ncacn_conn == NULL) {
934 DEBUG(0, ("dcerpc_ncacn_accept: Out of memory!\n"));
935 close(s);
936 return;
939 switch (transport) {
940 case NCACN_IP_TCP:
941 ncacn_conn->ep.port = port;
942 break;
943 case NCALRPC:
944 case NCACN_NP:
945 ncacn_conn->ep.name = talloc_strdup(ncacn_conn, name);
946 break;
947 default:
948 DEBUG(0, ("dcerpc_ncacn_accept_function: "
949 "unknown transport: %u!\n", transport));
950 talloc_free(ncacn_conn);
951 close(s);
952 return;
954 ncacn_conn->transport = transport;
955 ncacn_conn->syntax_id = syntax_id;
956 ncacn_conn->ev_ctx = ev_ctx;
957 ncacn_conn->msg_ctx = msg_ctx;
958 ncacn_conn->sock = s;
960 ncacn_conn->client = talloc_move(ncacn_conn, &cli_addr);
962 rc = set_blocking(s, false);
963 if (rc < 0) {
964 DEBUG(2, ("dcerpc_ncacn_accept: Failed to set socket to "
965 "non-blocking\n"));
966 talloc_free(ncacn_conn);
967 close(s);
968 return;
972 * As soon as we have tstream_bsd_existing_socket set up it will take
973 * care closing the socket.
975 rc = tstream_bsd_existing_socket(ncacn_conn, s, &ncacn_conn->tstream);
976 if (rc < 0) {
977 DEBUG(2, ("dcerpc_ncacn_accept: Failed to create tstream "
978 "socket\n"));
979 talloc_free(ncacn_conn);
980 close(s);
981 return;
984 switch(ncacn_conn->transport) {
985 case NCACN_IP_TCP:
986 pipe_name = tsocket_address_string(ncacn_conn->client,
987 ncacn_conn);
988 break;
989 case NCALRPC:
990 pipe_name = talloc_strdup(ncacn_conn,
991 ncacn_conn->ep.name);
992 break;
993 default:
994 talloc_free(ncacn_conn);
995 return;
998 if (tsocket_address_is_inet(ncacn_conn->client, "ip")) {
999 cli_str = tsocket_address_inet_addr_string(ncacn_conn->client,
1000 ncacn_conn);
1001 if (cli_str == NULL) {
1002 talloc_free(ncacn_conn);
1003 return;
1005 } else {
1006 cli_str = "";
1009 if (ncacn_conn->session_info == NULL) {
1010 status = auth_anonymous_session_info(ncacn_conn,
1011 &ncacn_conn->session_info);
1012 if (!NT_STATUS_IS_OK(status)) {
1013 DEBUG(2, ("dcerpc_ncacn_accept: Failed to create "
1014 "auth_anonymous_session_info - %s\n",
1015 nt_errstr(status)));
1016 talloc_free(ncacn_conn);
1017 return;
1021 rc = make_server_pipes_struct(ncacn_conn,
1022 pipe_name,
1023 ncacn_conn->syntax_id,
1024 cli_str,
1025 ncacn_conn->session_info,
1026 &ncacn_conn->p,
1027 &sys_errno);
1028 if (rc < 0) {
1029 DEBUG(2, ("dcerpc_ncacn_accept: Failed to create pipe "
1030 "struct - %s", strerror(sys_errno)));
1031 talloc_free(ncacn_conn);
1032 return;
1035 ncacn_conn->send_queue = tevent_queue_create(ncacn_conn,
1036 "dcerpc_tcpip_accept_function");
1037 if (ncacn_conn->send_queue == NULL) {
1038 DEBUG(0, ("dcerpc_ncacn_accept_function: Out of memory!\n"));
1039 talloc_free(ncacn_conn);
1040 return;
1043 subreq = dcerpc_ncacn_read_packet_send(ncacn_conn,
1044 ncacn_conn->ev_ctx,
1045 ncacn_conn->tstream);
1046 if (subreq == NULL) {
1047 DEBUG(2, ("dcerpc_ncacn_accept: Failed to send ncacn "
1048 "packet\n"));
1049 talloc_free(ncacn_conn);
1050 return;
1053 tevent_req_set_callback(subreq, dcerpc_ncacn_packet_process, ncacn_conn);
1055 DEBUG(5, ("dcerpc_ncacn_accept done\n"));
1057 return;
1060 static void dcerpc_ncacn_packet_process(struct tevent_req *subreq)
1062 struct dcerpc_ncacn_conn *ncacn_conn =
1063 tevent_req_callback_data(subreq, struct dcerpc_ncacn_conn);
1065 struct _output_data *out = &ncacn_conn->p->out_data;
1066 DATA_BLOB recv_buffer = data_blob_null;
1067 ssize_t data_left;
1068 ssize_t data_used;
1069 uint32_t to_send;
1070 char *data;
1071 NTSTATUS status;
1072 bool ok;
1074 status = dcerpc_ncacn_read_packet_recv(subreq, ncacn_conn, &recv_buffer);
1075 TALLOC_FREE(subreq);
1076 if (!NT_STATUS_IS_OK(status)) {
1077 goto fail;
1080 data_left = recv_buffer.length;
1081 data = (char *) recv_buffer.data;
1083 while (data_left) {
1084 data_used = process_incoming_data(ncacn_conn->p, data, data_left);
1085 if (data_used < 0) {
1086 DEBUG(3, ("Failed to process dcerpc request!\n"));
1087 status = NT_STATUS_UNEXPECTED_IO_ERROR;
1088 goto fail;
1091 data_left -= data_used;
1092 data += data_used;
1095 /* Do not leak this buffer */
1096 talloc_free(recv_buffer.data);
1099 * This is needed because of the way DCERPC binds work in the RPC
1100 * marshalling code
1102 to_send = out->frag.length - out->current_pdu_sent;
1103 if (to_send > 0) {
1105 DEBUG(10, ("Current_pdu_len = %u, "
1106 "current_pdu_sent = %u "
1107 "Returning %u bytes\n",
1108 (unsigned int)out->frag.length,
1109 (unsigned int)out->current_pdu_sent,
1110 (unsigned int)to_send));
1112 ncacn_conn->iov = talloc_zero(ncacn_conn, struct iovec);
1113 if (ncacn_conn->iov == NULL) {
1114 status = NT_STATUS_NO_MEMORY;
1115 goto fail;
1117 ncacn_conn->count = 1;
1119 ncacn_conn->iov[0].iov_base = out->frag.data
1120 + out->current_pdu_sent;
1121 ncacn_conn->iov[0].iov_len = to_send;
1123 out->current_pdu_sent += to_send;
1127 * This condition is false for bind packets, or when we haven't yet got
1128 * a full request, and need to wait for more data from the client
1130 while (out->data_sent_length < out->rdata.length) {
1131 ok = create_next_pdu(ncacn_conn->p);
1132 if (!ok) {
1133 DEBUG(3, ("Failed to create next PDU!\n"));
1134 status = NT_STATUS_UNEXPECTED_IO_ERROR;
1135 goto fail;
1138 ncacn_conn->iov = talloc_realloc(ncacn_conn,
1139 ncacn_conn->iov,
1140 struct iovec,
1141 ncacn_conn->count + 1);
1142 if (ncacn_conn->iov == NULL) {
1143 status = NT_STATUS_NO_MEMORY;
1144 goto fail;
1147 ncacn_conn->iov[ncacn_conn->count].iov_base = out->frag.data;
1148 ncacn_conn->iov[ncacn_conn->count].iov_len = out->frag.length;
1150 DEBUG(10, ("PDU number: %d, PDU Length: %u\n",
1151 (unsigned int) ncacn_conn->count,
1152 (unsigned int) ncacn_conn->iov[ncacn_conn->count].iov_len));
1153 dump_data(11, (const uint8_t *) ncacn_conn->iov[ncacn_conn->count].iov_base,
1154 ncacn_conn->iov[ncacn_conn->count].iov_len);
1155 ncacn_conn->count++;
1159 * We still don't have a complete request, go back and wait for more
1160 * data.
1162 if (ncacn_conn->count == 0) {
1163 /* Wait for the next packet */
1164 subreq = dcerpc_ncacn_read_packet_send(ncacn_conn,
1165 ncacn_conn->ev_ctx,
1166 ncacn_conn->tstream);
1167 if (subreq == NULL) {
1168 DEBUG(2, ("Failed to start receving packets\n"));
1169 status = NT_STATUS_NO_MEMORY;
1170 goto fail;
1172 tevent_req_set_callback(subreq, dcerpc_ncacn_packet_process, ncacn_conn);
1173 return;
1176 DEBUG(10, ("Sending a total of %u bytes\n",
1177 (unsigned int)ncacn_conn->p->out_data.data_sent_length));
1179 subreq = tstream_writev_queue_send(ncacn_conn,
1180 ncacn_conn->ev_ctx,
1181 ncacn_conn->tstream,
1182 ncacn_conn->send_queue,
1183 ncacn_conn->iov,
1184 ncacn_conn->count);
1185 if (subreq == NULL) {
1186 DEBUG(2, ("Failed to send packet\n"));
1187 status = NT_STATUS_NO_MEMORY;
1188 goto fail;
1191 tevent_req_set_callback(subreq, dcerpc_ncacn_packet_done, ncacn_conn);
1192 return;
1194 fail:
1195 DEBUG(2, ("Fatal error(%s). "
1196 "Terminating client(%s) connection!\n",
1197 nt_errstr(status), ncacn_conn->client_name));
1199 /* Terminate client connection */
1200 talloc_free(ncacn_conn);
1201 return;
1204 static void dcerpc_ncacn_packet_done(struct tevent_req *subreq)
1206 struct dcerpc_ncacn_conn *ncacn_conn =
1207 tevent_req_callback_data(subreq, struct dcerpc_ncacn_conn);
1208 int sys_errno;
1209 int rc;
1211 rc = tstream_writev_queue_recv(subreq, &sys_errno);
1212 TALLOC_FREE(subreq);
1213 if (rc < 0) {
1214 DEBUG(2, ("Writev failed!\n"));
1215 goto fail;
1218 /* clear out any data that may have been left around */
1219 ncacn_conn->count = 0;
1220 TALLOC_FREE(ncacn_conn->iov);
1221 data_blob_free(&ncacn_conn->p->in_data.data);
1222 data_blob_free(&ncacn_conn->p->out_data.frag);
1223 data_blob_free(&ncacn_conn->p->out_data.rdata);
1225 /* Wait for the next packet */
1226 subreq = dcerpc_ncacn_read_packet_send(ncacn_conn,
1227 ncacn_conn->ev_ctx,
1228 ncacn_conn->tstream);
1229 if (subreq == NULL) {
1230 DEBUG(2, ("Failed to start receving packets\n"));
1231 sys_errno = ENOMEM;
1232 goto fail;
1235 tevent_req_set_callback(subreq, dcerpc_ncacn_packet_process, ncacn_conn);
1236 return;
1238 fail:
1239 DEBUG(2, ("Fatal error(%s). Terminating client(%s) connection!\n",
1240 strerror(sys_errno), ncacn_conn->client_name));
1242 /* Terminate client connection */
1243 talloc_free(ncacn_conn);
1244 return;
1247 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */