rpc_server: Allow to configure the port range for RPC services
[samba.git] / source3 / rpc_server / rpc_server.c
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
7
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.
12
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.
17
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/>.
20 */
21
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"
36
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 *local_address,
44                              const struct tsocket_address *remote_address,
45                              struct auth_session_info *session_info,
46                              struct pipes_struct **_p,
47                              int *perrno)
48 {
49         struct pipes_struct *p;
50         int ret;
51
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;
58         }
59
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);
63
64         } else {
65                 DEBUG(0, ("Supplied session_info in make_server_pipes_struct was incomplete!"));
66                 *perrno = EINVAL;
67                 return -1;
68         }
69
70         *_p = p;
71         return 0;
72 }
73
74 /* Start listening on the appropriate unix socket and setup all is needed to
75  * dispatch requests to the pipes rpc implementation */
76
77 struct dcerpc_ncacn_listen_state {
78         struct ndr_syntax_id syntax_id;
79
80         int fd;
81         union {
82                 char *name;
83                 uint16_t port;
84         } ep;
85
86         struct tevent_context *ev_ctx;
87         struct messaging_context *msg_ctx;
88         dcerpc_ncacn_disconnect_fn disconnect_fn;
89 };
90
91 static void named_pipe_listener(struct tevent_context *ev,
92                                 struct tevent_fd *fde,
93                                 uint16_t flags,
94                                 void *private_data);
95
96 int create_named_pipe_socket(const char *pipe_name)
97 {
98         char *np_dir = NULL;
99         int fd = -1;
100
101         /*
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.
105          */
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;
110         }
111
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;
116         }
117
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;
122         }
123
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;
129         }
130
131         DEBUG(10, ("Openened pipe socket fd %d for %s\n", fd, pipe_name));
132
133 out:
134         talloc_free(np_dir);
135         return fd;
136 }
137
138 bool setup_named_pipe_socket(const char *pipe_name,
139                              struct tevent_context *ev_ctx,
140                              struct messaging_context *msg_ctx)
141 {
142         struct dcerpc_ncacn_listen_state *state;
143         struct tevent_fd *fde;
144         int rc;
145
146         state = talloc(ev_ctx, struct dcerpc_ncacn_listen_state);
147         if (!state) {
148                 DEBUG(0, ("Out of memory\n"));
149                 return false;
150         }
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;
155         }
156         state->fd = create_named_pipe_socket(pipe_name);
157         if (state->fd == -1) {
158                 goto out;
159         }
160
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;
166         }
167
168         state->ev_ctx = ev_ctx;
169         state->msg_ctx = msg_ctx;
170
171         DEBUG(10, ("Openened pipe socket fd %d for %s\n",
172                    state->fd, pipe_name));
173
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;
180         }
181
182         tevent_fd_set_auto_close(fde);
183         return true;
184
185 out:
186         if (state->fd != -1) {
187                 close(state->fd);
188         }
189         TALLOC_FREE(state);
190         return false;
191 }
192
193 static void named_pipe_listener(struct tevent_context *ev,
194                                 struct tevent_fd *fde,
195                                 uint16_t flags,
196                                 void *private_data)
197 {
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;
204
205         /* TODO: should we have a limit to the number of clients ? */
206
207         len = sizeof(sunaddr);
208
209         sd = accept(state->fd,
210                     (struct sockaddr *)(void *)&sunaddr, &len);
211
212         if (sd == -1) {
213                 if (errno != EINTR) {
214                         DEBUG(6, ("Failed to get a valid socket [%s]\n",
215                                   strerror(errno)));
216                 }
217                 return;
218         }
219
220         DEBUG(6, ("Accepted socket %d\n", sd));
221
222         named_pipe_accept_function(state->ev_ctx,
223                                    state->msg_ctx,
224                                    state->ep.name,
225                                    sd, NULL, 0);
226 }
227
228
229 /* This is the core of the rpc server.
230  * Accepts connections from clients and process requests using the appropriate
231  * dispatcher table. */
232
233 static int named_pipe_destructor(struct named_pipe_client *npc)
234 {
235         if (npc->term_fn) {
236                 npc->term_fn(npc->private_data);
237         }
238         return 0;
239 }
240
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)
250 {
251         struct named_pipe_client *npc;
252
253         npc = talloc_zero(mem_ctx, struct named_pipe_client);
254         if (npc == NULL) {
255                 DEBUG(0, ("Out of memory!\n"));
256                 return NULL;
257         }
258         talloc_set_destructor(npc, named_pipe_destructor);
259
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;
265         }
266
267         npc->ev = ev_ctx;
268         npc->msg_ctx = msg_ctx;
269         npc->term_fn = term_fn;
270         npc->private_data = private_data;
271
272         npc->file_type = file_type;
273         npc->device_state = device_state;
274         npc->allocation_size = allocation_size;
275
276         return npc;
277 }
278
279 static void named_pipe_accept_done(struct tevent_req *subreq);
280
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)
286 {
287         struct named_pipe_client *npc;
288         struct tstream_context *plain;
289         struct tevent_req *subreq;
290         int ret;
291
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;
297         }
298
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;
305         }
306         npc->ev = ev_ctx;
307         npc->msg_ctx = msg_ctx;
308         npc->term_fn = term_fn;
309         npc->private_data = private_data;
310
311         talloc_set_destructor(npc, named_pipe_destructor);
312
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;
320         }
321
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;
328         }
329
330         npc->file_type = FILE_TYPE_MESSAGE_MODE_PIPE;
331         npc->device_state = 0xff | 0x0400 | 0x0100;
332         npc->allocation_size = 4096;
333
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;
343         }
344         tevent_req_set_callback(subreq, named_pipe_accept_done, npc);
345 }
346
347 static void named_pipe_packet_done(struct tevent_req *subreq);
348
349 static void named_pipe_accept_done(struct tevent_req *subreq)
350 {
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;
356
357         ret = tstream_npa_accept_existing_recv(subreq, &error, npc,
358                                                 &npc->tstream,
359                                                 &npc->client,
360                                                 &npc->client_name,
361                                                 &npc->server,
362                                                 &npc->server_name,
363                                                 &session_info_transport);
364
365         npc->session_info = talloc_move(npc, &session_info_transport->session_info);
366
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;
373         }
374
375         ret = make_server_pipes_struct(npc,
376                                        npc->msg_ctx,
377                                        npc->pipe_name, NCACN_NP,
378                                        npc->server,
379                                        npc->client,
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;
386         }
387
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;
392         }
393
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;
399         }
400         tevent_req_set_callback(subreq, named_pipe_packet_process, npc);
401         return;
402
403 fail:
404         DEBUG(2, ("Fatal error. Terminating client(%s) connection!\n",
405                   npc->client_name));
406         /* terminate client connection */
407         talloc_free(npc);
408         return;
409 }
410
411 void named_pipe_packet_process(struct tevent_req *subreq)
412 {
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;
422
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;
427         }
428
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;
436         }
437         DEBUG(10, ("PDU is in %s Endian format!\n",
438                    npc->p->endian ? "Big" : "Little"));
439         process_complete_pdu(npc->p, pkt);
440
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);
445
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) {
450
451                 npc->iov = talloc_zero(npc, struct iovec);
452                 if (!npc->iov) {
453                         status = NT_STATUS_NO_MEMORY;
454                         goto fail;
455                 }
456                 npc->count = 1;
457
458                 npc->iov[0].iov_base = out->frag.data
459                                         + out->current_pdu_sent;
460                 npc->iov[0].iov_len = to_send;
461
462                 out->current_pdu_sent += to_send;
463         }
464
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) {
469
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;
475                 }
476
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;
482                 }
483
484                 npc->iov[npc->count].iov_base = out->frag.data;
485                 npc->iov[npc->count].iov_len = out->frag.length;
486
487                 npc->count++;
488         }
489
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;
499                 }
500                 tevent_req_set_callback(subreq, named_pipe_packet_process, npc);
501                 return;
502         }
503
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));
507
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);
514
515                 subreq = tstream_writev_queue_send(npc,
516                                                    npc->ev,
517                                                    npc->tstream,
518                                                    npc->write_queue,
519                                                    (npc->iov + i),
520                                                    1);
521                 if (!subreq) {
522                         DEBUG(2, ("Failed to send packet\n"));
523                         status = NT_STATUS_NO_MEMORY;
524                         goto fail;
525                 }
526                 tevent_req_set_callback(subreq, named_pipe_packet_done, npc);
527         }
528
529         return;
530
531 fail:
532         DEBUG(2, ("Fatal error(%s). "
533                   "Terminating client(%s) connection!\n",
534                   nt_errstr(status), npc->client_name));
535         /* terminate client connection */
536         talloc_free(npc);
537         return;
538 }
539
540 static void named_pipe_packet_done(struct tevent_req *subreq)
541 {
542         struct named_pipe_client *npc =
543                 tevent_req_callback_data(subreq, struct named_pipe_client);
544         int sys_errno;
545         int ret;
546
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;
552         }
553
554         if (tevent_queue_length(npc->write_queue) > 0) {
555                 return;
556         }
557
558         if (npc->p->fault_state != 0) {
559                 DEBUG(2, ("Disconnect after fault\n"));
560                 sys_errno = EINVAL;
561                 goto fail;
562         }
563
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);
570
571         talloc_free_children(npc->p->mem_ctx);
572
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;
579         }
580         tevent_req_set_callback(subreq, named_pipe_packet_process, npc);
581         return;
582
583 fail:
584         DEBUG(2, ("Fatal error(%s). "
585                   "Terminating client(%s) connection!\n",
586                   strerror(sys_errno), npc->client_name));
587         /* terminate client connection */
588         talloc_free(npc);
589         return;
590 }
591
592 /********************************************************************
593  * Start listening on the tcp/ip socket
594  ********************************************************************/
595
596 static void dcerpc_ncacn_tcpip_listener(struct tevent_context *ev,
597                                         struct tevent_fd *fde,
598                                         uint16_t flags,
599                                         void *private_data);
600
601 int create_tcpip_socket(const struct sockaddr_storage *ifss, uint16_t *port)
602 {
603         int fd = -1;
604
605         if (*port == 0) {
606                 uint16_t i;
607
608                 for (i = lp_rpc_low_port(); i <= lp_rpc_high_port(); i++) {
609                         fd = open_socket_in(SOCK_STREAM,
610                                             i,
611                                             0,
612                                             ifss,
613                                             false);
614                         if (fd >= 0) {
615                                 *port = i;
616                                 break;
617                         }
618                 }
619         } else {
620                 fd = open_socket_in(SOCK_STREAM,
621                                     *port,
622                                     0,
623                                     ifss,
624                                     true);
625         }
626         if (fd == -1) {
627                 DEBUG(0, ("Failed to create socket on port %u!\n", *port));
628                 return -1;
629         }
630
631         DEBUG(10, ("Opened tcpip socket fd %d for port %u\n", fd, *port));
632
633         return fd;
634 }
635
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)
640 {
641         struct dcerpc_ncacn_listen_state *state;
642         struct tevent_fd *fde;
643         int rc;
644
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;
649         }
650
651         state->fd = -1;
652         state->ep.port = port;
653         state->disconnect_fn = NULL;
654
655         state->fd = create_tcpip_socket(ifss, &state->ep.port);
656         if (state->fd == -1) {
657                 goto out;
658         }
659
660         state->ev_ctx = ev_ctx;
661         state->msg_ctx = msg_ctx;
662
663         /* ready to listen */
664         set_socket_options(state->fd, "SO_KEEPALIVE");
665         set_socket_options(state->fd, lp_socket_options());
666
667         /* Set server socket to non-blocking for the accept. */
668         set_blocking(state->fd, false);
669
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;
674         }
675
676         DEBUG(10, ("setup_tcpip_socket: openened socket fd %d for port %u\n",
677                    state->fd, state->ep.port));
678
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;
688         }
689
690         tevent_fd_set_auto_close(fde);
691
692         return state->ep.port;
693 out:
694         if (state->fd != -1) {
695                 close(state->fd);
696         }
697         TALLOC_FREE(state);
698
699         return 0;
700 }
701
702 static void dcerpc_ncacn_tcpip_listener(struct tevent_context *ev,
703                                         struct tevent_fd *fde,
704                                         uint16_t flags,
705                                         void *private_data)
706 {
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;
716
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)));
722                 }
723                 return;
724         }
725
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;
733         }
734
735         rc = getsockname(s, (struct sockaddr *)(void *) &addr, &in_addrlen);
736         if (rc < 0) {
737                 close(s);
738                 return;
739         }
740
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;
748         }
749
750         DEBUG(6, ("tcpip_listener: Accepted socket %d\n", s));
751
752         dcerpc_ncacn_accept(state->ev_ctx,
753                             state->msg_ctx,
754                             NCACN_IP_TCP,
755                             NULL,
756                             cli_addr,
757                             srv_addr,
758                             s,
759                             NULL);
760 }
761
762 /********************************************************************
763  * Start listening on the ncalrpc socket
764  ********************************************************************/
765
766 static void dcerpc_ncalrpc_listener(struct tevent_context *ev,
767                                     struct tevent_fd *fde,
768                                     uint16_t flags,
769                                     void *private_data);
770
771 int create_dcerpc_ncalrpc_socket(const char *name)
772 {
773         int fd = -1;
774
775         if (name == NULL) {
776                 name = "DEFAULT";
777         }
778
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;
783         }
784
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;
790         }
791
792         DEBUG(10, ("Openened ncalrpc socket fd %d for %s\n", fd, name));
793
794         return fd;
795 }
796
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)
801 {
802         struct dcerpc_ncacn_listen_state *state;
803         struct tevent_fd *fde;
804         int rc;
805
806         state = talloc(ev_ctx, struct dcerpc_ncacn_listen_state);
807         if (state == NULL) {
808                 DEBUG(0, ("Out of memory\n"));
809                 return false;
810         }
811
812         state->fd = -1;
813         state->disconnect_fn = fn;
814
815         if (name == NULL) {
816                 name = "DEFAULT";
817         }
818
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;
824         }
825
826         state->fd = create_dcerpc_ncalrpc_socket(name);
827         if (state->fd == -1) {
828                 goto out;
829         }
830
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;
836         }
837
838         state->ev_ctx = ev_ctx;
839         state->msg_ctx = msg_ctx;
840
841         /* Set server socket to non-blocking for the accept. */
842         set_blocking(state->fd, false);
843
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;
853         }
854
855         tevent_fd_set_auto_close(fde);
856
857         return true;
858 out:
859         if (state->fd != -1) {
860                 close(state->fd);
861         }
862         TALLOC_FREE(state);
863
864         return 0;
865 }
866
867 static void dcerpc_ncalrpc_listener(struct tevent_context *ev,
868                                         struct tevent_fd *fde,
869                                         uint16_t flags,
870                                         void *private_data)
871 {
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;
876         struct sockaddr_un sunaddr;
877         struct sockaddr *addr = (struct sockaddr *)(void *)&sunaddr;
878         socklen_t len = sizeof(sunaddr);
879         int sd = -1;
880         int rc;
881
882         ZERO_STRUCT(sunaddr);
883
884         sd = accept(state->fd, addr, &len);
885         if (sd == -1) {
886                 if (errno != EINTR) {
887                         DEBUG(0, ("ncalrpc accept() failed: %s\n", strerror(errno)));
888                 }
889                 return;
890         }
891
892         rc = tsocket_address_bsd_from_sockaddr(state,
893                                                addr, len,
894                                                &cli_addr);
895         if (rc < 0) {
896                 close(sd);
897                 return;
898         }
899
900         DEBUG(10, ("Accepted ncalrpc socket %d\n", sd));
901
902         dcerpc_ncacn_accept(state->ev_ctx,
903                             state->msg_ctx,
904                             NCALRPC,
905                             state->ep.name,
906                             cli_addr, NULL, sd,
907                             state->disconnect_fn);
908 }
909
910 struct dcerpc_ncacn_conn {
911         enum dcerpc_transport_t transport;
912
913         int sock;
914
915         struct pipes_struct *p;
916         dcerpc_ncacn_disconnect_fn disconnect_fn;
917
918         struct tevent_context *ev_ctx;
919         struct messaging_context *msg_ctx;
920
921         struct tstream_context *tstream;
922         struct tevent_queue *send_queue;
923
924         struct tsocket_address *client;
925         char *client_name;
926         struct tsocket_address *server;
927         char *server_name;
928         struct auth_session_info *session_info;
929
930         struct iovec *iov;
931         size_t count;
932 };
933
934 static void dcerpc_ncacn_packet_process(struct tevent_req *subreq);
935 static void dcerpc_ncacn_packet_done(struct tevent_req *subreq);
936
937 void dcerpc_ncacn_accept(struct tevent_context *ev_ctx,
938                          struct messaging_context *msg_ctx,
939                          enum dcerpc_transport_t transport,
940                          const char *name,
941                          struct tsocket_address *cli_addr,
942                          struct tsocket_address *srv_addr,
943                          int s,
944                          dcerpc_ncacn_disconnect_fn fn) {
945         struct dcerpc_ncacn_conn *ncacn_conn;
946         struct tevent_req *subreq;
947         char *pipe_name;
948         NTSTATUS status;
949         int sys_errno;
950         uid_t uid;
951         gid_t gid;
952         int rc;
953
954         DEBUG(10, ("dcerpc_ncacn_accept\n"));
955
956         ncacn_conn = talloc_zero(ev_ctx, struct dcerpc_ncacn_conn);
957         if (ncacn_conn == NULL) {
958                 DEBUG(0, ("Out of memory!\n"));
959                 close(s);
960                 return;
961         }
962
963         ncacn_conn->transport = transport;
964         ncacn_conn->ev_ctx = ev_ctx;
965         ncacn_conn->msg_ctx = msg_ctx;
966         ncacn_conn->sock = s;
967         ncacn_conn->disconnect_fn = fn;
968
969         ncacn_conn->client = talloc_move(ncacn_conn, &cli_addr);
970         if (tsocket_address_is_inet(ncacn_conn->client, "ip")) {
971                 ncacn_conn->client_name =
972                         tsocket_address_inet_addr_string(ncacn_conn->client,
973                                                          ncacn_conn);
974         } else {
975                 ncacn_conn->client_name =
976                         tsocket_address_unix_path(ncacn_conn->client,
977                                                   ncacn_conn);
978         }
979         if (ncacn_conn->client_name == NULL) {
980                 DEBUG(0, ("Out of memory!\n"));
981                 talloc_free(ncacn_conn);
982                 close(s);
983                 return;
984         }
985
986         if (srv_addr != NULL) {
987                 ncacn_conn->server = talloc_move(ncacn_conn, &srv_addr);
988
989                 ncacn_conn->server_name =
990                         tsocket_address_inet_addr_string(ncacn_conn->server,
991                                                          ncacn_conn);
992                 if (ncacn_conn->server_name == NULL) {
993                         DEBUG(0, ("Out of memory!\n"));
994                         talloc_free(ncacn_conn);
995                         close(s);
996                         return;
997                 }
998         }
999
1000         switch (transport) {
1001                 case NCACN_IP_TCP:
1002                         pipe_name = tsocket_address_string(ncacn_conn->client,
1003                                                            ncacn_conn);
1004                         if (pipe_name == NULL) {
1005                                 close(s);
1006                                 talloc_free(ncacn_conn);
1007                                 return;
1008                         }
1009
1010                         break;
1011                 case NCALRPC:
1012                         rc = getpeereid(s, &uid, &gid);
1013                         if (rc < 0) {
1014                                 DEBUG(2, ("Failed to get ncalrpc connecting "
1015                                           "uid - %s!\n", strerror(errno)));
1016                         } else {
1017                                 if (uid == sec_initial_uid()) {
1018                                         TALLOC_FREE(ncacn_conn->client);
1019
1020                                         rc = tsocket_address_unix_from_path(ncacn_conn,
1021                                                                             "/root/ncalrpc_as_system",
1022                                                                             &ncacn_conn->client);
1023                                         if (rc < 0) {
1024                                                 DEBUG(0, ("Out of memory!\n"));
1025                                                 talloc_free(ncacn_conn);
1026                                                 close(s);
1027                                                 return;
1028                                         }
1029
1030                                         TALLOC_FREE(ncacn_conn->client_name);
1031                                         ncacn_conn->client_name = tsocket_address_unix_path(ncacn_conn->client,
1032                                                                                             ncacn_conn);
1033                                         if (ncacn_conn->client == NULL) {
1034                                                 DEBUG(0, ("Out of memory!\n"));
1035                                                 talloc_free(ncacn_conn);
1036                                                 close(s);
1037                                                 return;
1038                                         }
1039                                 }
1040                         }
1041                         /* FALL TROUGH */
1042                 case NCACN_NP:
1043                         pipe_name = talloc_strdup(ncacn_conn,
1044                                                   name);
1045                         if (pipe_name == NULL) {
1046                                 close(s);
1047                                 talloc_free(ncacn_conn);
1048                                 return;
1049                         }
1050                         break;
1051                 default:
1052                         DEBUG(0, ("unknown dcerpc transport: %u!\n",
1053                                   transport));
1054                         talloc_free(ncacn_conn);
1055                         close(s);
1056                         return;
1057         }
1058
1059         rc = set_blocking(s, false);
1060         if (rc < 0) {
1061                 DEBUG(2, ("Failed to set dcerpc socket to non-blocking\n"));
1062                 talloc_free(ncacn_conn);
1063                 close(s);
1064                 return;
1065         }
1066
1067         /*
1068          * As soon as we have tstream_bsd_existing_socket set up it will
1069          * take care of closing the socket.
1070          */
1071         rc = tstream_bsd_existing_socket(ncacn_conn, s, &ncacn_conn->tstream);
1072         if (rc < 0) {
1073                 DEBUG(2, ("Failed to create tstream socket for dcerpc\n"));
1074                 talloc_free(ncacn_conn);
1075                 close(s);
1076                 return;
1077         }
1078
1079         if (ncacn_conn->session_info == NULL) {
1080                 /*
1081                  * TODO: use auth_anonymous_session_info() here?
1082                  */
1083                 status = make_session_info_guest(ncacn_conn,
1084                                                  &ncacn_conn->session_info);
1085                 if (!NT_STATUS_IS_OK(status)) {
1086                         DEBUG(2, ("Failed to create "
1087                                   "make_session_info_guest - %s\n",
1088                                   nt_errstr(status)));
1089                         talloc_free(ncacn_conn);
1090                         return;
1091                 }
1092         }
1093
1094         rc = make_server_pipes_struct(ncacn_conn,
1095                                       ncacn_conn->msg_ctx,
1096                                       pipe_name,
1097                                       ncacn_conn->transport,
1098                                       ncacn_conn->server,
1099                                       ncacn_conn->client,
1100                                       ncacn_conn->session_info,
1101                                       &ncacn_conn->p,
1102                                       &sys_errno);
1103         if (rc < 0) {
1104                 DEBUG(2, ("Failed to create pipe struct - %s",
1105                           strerror(sys_errno)));
1106                 talloc_free(ncacn_conn);
1107                 return;
1108         }
1109
1110         ncacn_conn->send_queue = tevent_queue_create(ncacn_conn,
1111                                                         "dcerpc send queue");
1112         if (ncacn_conn->send_queue == NULL) {
1113                 DEBUG(0, ("Out of memory!\n"));
1114                 talloc_free(ncacn_conn);
1115                 return;
1116         }
1117
1118         subreq = dcerpc_read_ncacn_packet_send(ncacn_conn,
1119                                                ncacn_conn->ev_ctx,
1120                                                ncacn_conn->tstream);
1121         if (subreq == NULL) {
1122                 DEBUG(2, ("Failed to send ncacn packet\n"));
1123                 talloc_free(ncacn_conn);
1124                 return;
1125         }
1126
1127         tevent_req_set_callback(subreq, dcerpc_ncacn_packet_process, ncacn_conn);
1128
1129         DEBUG(10, ("dcerpc_ncacn_accept done\n"));
1130
1131         return;
1132 }
1133
1134 static void dcerpc_ncacn_packet_process(struct tevent_req *subreq)
1135 {
1136         struct dcerpc_ncacn_conn *ncacn_conn =
1137                 tevent_req_callback_data(subreq, struct dcerpc_ncacn_conn);
1138
1139         struct _output_data *out = &ncacn_conn->p->out_data;
1140         DATA_BLOB recv_buffer = data_blob_null;
1141         struct ncacn_packet *pkt;
1142         uint32_t to_send;
1143         NTSTATUS status;
1144         bool ok;
1145
1146         status = dcerpc_read_ncacn_packet_recv(subreq, ncacn_conn, &pkt, &recv_buffer);
1147         TALLOC_FREE(subreq);
1148         if (!NT_STATUS_IS_OK(status)) {
1149                 if (ncacn_conn->disconnect_fn != NULL) {
1150                         ok = ncacn_conn->disconnect_fn(ncacn_conn->p);
1151                         if (!ok) {
1152                                 DEBUG(3, ("Failed to call disconnect function\n"));
1153                         }
1154                 }
1155                 goto fail;
1156         }
1157
1158         /* dcerpc_read_ncacn_packet_recv() returns a full PDU */
1159         ncacn_conn->p->in_data.pdu_needed_len = 0;
1160         ncacn_conn->p->in_data.pdu = recv_buffer;
1161         if (dcerpc_get_endian_flag(&recv_buffer) & DCERPC_DREP_LE) {
1162                 ncacn_conn->p->endian = RPC_LITTLE_ENDIAN;
1163         } else {
1164                 ncacn_conn->p->endian = RPC_BIG_ENDIAN;
1165         }
1166         DEBUG(10, ("PDU is in %s Endian format!\n",
1167                    ncacn_conn->p->endian ? "Big" : "Little"));
1168         process_complete_pdu(ncacn_conn->p, pkt);
1169
1170         /* reset pipe state and free PDU */
1171         ncacn_conn->p->in_data.pdu.length = 0;
1172         talloc_free(recv_buffer.data);
1173         talloc_free(pkt);
1174
1175         /*
1176          * This is needed because of the way DCERPC binds work in the RPC
1177          * marshalling code
1178          */
1179         to_send = out->frag.length - out->current_pdu_sent;
1180         if (to_send > 0) {
1181
1182                 DEBUG(10, ("Current_pdu_len = %u, "
1183                            "current_pdu_sent = %u "
1184                            "Returning %u bytes\n",
1185                            (unsigned int)out->frag.length,
1186                            (unsigned int)out->current_pdu_sent,
1187                            (unsigned int)to_send));
1188
1189                 ncacn_conn->iov = talloc_zero(ncacn_conn, struct iovec);
1190                 if (ncacn_conn->iov == NULL) {
1191                         status = NT_STATUS_NO_MEMORY;
1192                         DEBUG(3, ("Out of memory!\n"));
1193                         goto fail;
1194                 }
1195                 ncacn_conn->count = 1;
1196
1197                 ncacn_conn->iov[0].iov_base = out->frag.data
1198                                             + out->current_pdu_sent;
1199                 ncacn_conn->iov[0].iov_len = to_send;
1200
1201                 out->current_pdu_sent += to_send;
1202         }
1203
1204         /*
1205          * This condition is false for bind packets, or when we haven't yet got
1206          * a full request, and need to wait for more data from the client
1207          */
1208         while (out->data_sent_length < out->rdata.length) {
1209                 ok = create_next_pdu(ncacn_conn->p);
1210                 if (!ok) {
1211                         DEBUG(3, ("Failed to create next PDU!\n"));
1212                         status = NT_STATUS_UNEXPECTED_IO_ERROR;
1213                         goto fail;
1214                 }
1215
1216                 ncacn_conn->iov = talloc_realloc(ncacn_conn,
1217                                                  ncacn_conn->iov,
1218                                                  struct iovec,
1219                                                  ncacn_conn->count + 1);
1220                 if (ncacn_conn->iov == NULL) {
1221                         DEBUG(3, ("Out of memory!\n"));
1222                         status = NT_STATUS_NO_MEMORY;
1223                         goto fail;
1224                 }
1225
1226                 ncacn_conn->iov[ncacn_conn->count].iov_base = out->frag.data;
1227                 ncacn_conn->iov[ncacn_conn->count].iov_len = out->frag.length;
1228
1229                 DEBUG(10, ("PDU number: %d, PDU Length: %u\n",
1230                            (unsigned int) ncacn_conn->count,
1231                            (unsigned int) ncacn_conn->iov[ncacn_conn->count].iov_len));
1232                 dump_data(11, (const uint8_t *) ncacn_conn->iov[ncacn_conn->count].iov_base,
1233                               ncacn_conn->iov[ncacn_conn->count].iov_len);
1234                 ncacn_conn->count++;
1235         }
1236
1237         /*
1238          * We still don't have a complete request, go back and wait for more
1239          * data.
1240          */
1241         if (ncacn_conn->count == 0) {
1242                 /* Wait for the next packet */
1243                 subreq = dcerpc_read_ncacn_packet_send(ncacn_conn,
1244                                                        ncacn_conn->ev_ctx,
1245                                                        ncacn_conn->tstream);
1246                 if (subreq == NULL) {
1247                         DEBUG(2, ("Failed to start receving packets\n"));
1248                         status = NT_STATUS_NO_MEMORY;
1249                         goto fail;
1250                 }
1251                 tevent_req_set_callback(subreq, dcerpc_ncacn_packet_process, ncacn_conn);
1252                 return;
1253         }
1254
1255         DEBUG(10, ("Sending a total of %u bytes\n",
1256                    (unsigned int)ncacn_conn->p->out_data.data_sent_length));
1257
1258         subreq = tstream_writev_queue_send(ncacn_conn,
1259                                            ncacn_conn->ev_ctx,
1260                                            ncacn_conn->tstream,
1261                                            ncacn_conn->send_queue,
1262                                            ncacn_conn->iov,
1263                                            ncacn_conn->count);
1264         if (subreq == NULL) {
1265                 DEBUG(2, ("Failed to send packet\n"));
1266                 status = NT_STATUS_NO_MEMORY;
1267                 goto fail;
1268         }
1269
1270         tevent_req_set_callback(subreq, dcerpc_ncacn_packet_done, ncacn_conn);
1271         return;
1272
1273 fail:
1274         DEBUG(3, ("Terminating client(%s) connection! - '%s'\n",
1275                   ncacn_conn->client_name, nt_errstr(status)));
1276
1277         /* Terminate client connection */
1278         talloc_free(ncacn_conn);
1279         return;
1280 }
1281
1282 static void dcerpc_ncacn_packet_done(struct tevent_req *subreq)
1283 {
1284         struct dcerpc_ncacn_conn *ncacn_conn =
1285                 tevent_req_callback_data(subreq, struct dcerpc_ncacn_conn);
1286         NTSTATUS status = NT_STATUS_OK;
1287         int sys_errno;
1288         int rc;
1289
1290         rc = tstream_writev_queue_recv(subreq, &sys_errno);
1291         TALLOC_FREE(subreq);
1292         if (rc < 0) {
1293                 DEBUG(2, ("Writev failed!\n"));
1294                 status = map_nt_error_from_unix(sys_errno);
1295                 goto fail;
1296         }
1297
1298         if (ncacn_conn->p->fault_state != 0) {
1299                 DEBUG(2, ("Disconnect after fault\n"));
1300                 sys_errno = EINVAL;
1301                 goto fail;
1302         }
1303
1304         /* clear out any data that may have been left around */
1305         ncacn_conn->count = 0;
1306         TALLOC_FREE(ncacn_conn->iov);
1307         data_blob_free(&ncacn_conn->p->in_data.data);
1308         data_blob_free(&ncacn_conn->p->out_data.frag);
1309         data_blob_free(&ncacn_conn->p->out_data.rdata);
1310
1311         talloc_free_children(ncacn_conn->p->mem_ctx);
1312
1313         /* Wait for the next packet */
1314         subreq = dcerpc_read_ncacn_packet_send(ncacn_conn,
1315                                                ncacn_conn->ev_ctx,
1316                                                ncacn_conn->tstream);
1317         if (subreq == NULL) {
1318                 DEBUG(2, ("Failed to start receving packets\n"));
1319                 status = NT_STATUS_NO_MEMORY;
1320                 goto fail;
1321         }
1322
1323         tevent_req_set_callback(subreq, dcerpc_ncacn_packet_process, ncacn_conn);
1324         return;
1325
1326 fail:
1327         DEBUG(3, ("Terminating client(%s) connection! - '%s'\n",
1328                   ncacn_conn->client_name, nt_errstr(status)));
1329
1330         /* Terminate client connection */
1331         talloc_free(ncacn_conn);
1332         return;
1333 }
1334
1335 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */