s3-rpc_server: Remove syntax from pipes_struct.
[nivanova/samba-autobuild/.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
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.
10
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.
15
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/>.
18 */
19
20 #include "includes.h"
21 #include "ntdomain.h"
22 #include "rpc_server/rpc_server.h"
23 #include "rpc_dce.h"
24 #include "librpc/gen_ndr/netlogon.h"
25 #include "librpc/gen_ndr/auth.h"
26 #include "lib/tsocket/tsocket.h"
27 #include "libcli/named_pipe_auth/npa_tstream.h"
28 #include "../auth/auth_sam_reply.h"
29 #include "auth.h"
30 #include "rpc_server/rpc_ncacn_np.h"
31 #include "rpc_server/srv_pipe_hnd.h"
32 #include "rpc_server/srv_pipe.h"
33
34 #define SERVER_TCP_LOW_PORT  1024
35 #define SERVER_TCP_HIGH_PORT 1300
36
37 static NTSTATUS auth_anonymous_session_info(TALLOC_CTX *mem_ctx,
38                                             struct auth_session_info **session_info)
39 {
40         struct auth_session_info *i;
41         struct auth_serversupplied_info *s;
42         struct auth_user_info_dc *u;
43         union netr_Validation val;
44         NTSTATUS status;
45
46         i = talloc_zero(mem_ctx, struct auth_session_info);
47         if (i == NULL) {
48                 return NT_STATUS_NO_MEMORY;
49         }
50
51         status = make_server_info_guest(i, &s);
52         if (!NT_STATUS_IS_OK(status)) {
53                 return status;
54         }
55
56         i->security_token = s->security_token;
57         i->session_key    = s->session_key;
58
59         val.sam3 = s->info3;
60
61         status = make_user_info_dc_netlogon_validation(mem_ctx,
62                                                        "",
63                                                        3,
64                                                        &val,
65                                                        &u);
66         if (!NT_STATUS_IS_OK(status)) {
67                 DEBUG(0, ("conversion of info3 into user_info_dc failed!\n"));
68                 return status;
69         }
70         i->info = talloc_move(i, &u->info);
71         talloc_free(u);
72
73         *session_info = i;
74
75         return NT_STATUS_OK;
76 }
77
78 /* Creates a pipes_struct and initializes it with the information
79  * sent from the client */
80 static int make_server_pipes_struct(TALLOC_CTX *mem_ctx,
81                                     const char *pipe_name,
82                                     enum dcerpc_transport_t transport,
83                                     bool ncalrpc_as_system,
84                                     const char *client_address,
85                                     const char *server_address,
86                                     struct auth_session_info *session_info,
87                                     struct pipes_struct **_p,
88                                     int *perrno)
89 {
90         struct netr_SamInfo3 *info3;
91         struct auth_user_info_dc *auth_user_info_dc;
92         struct pipes_struct *p;
93         struct auth_serversupplied_info *server_info;
94         NTSTATUS status;
95
96         p = talloc_zero(mem_ctx, struct pipes_struct);
97         if (!p) {
98                 *perrno = ENOMEM;
99                 return -1;
100         }
101
102         p->transport = transport;
103         p->ncalrpc_as_system = ncalrpc_as_system;
104
105         p->mem_ctx = talloc_named(p, 0, "pipe %s %p", pipe_name, p);
106         if (!p->mem_ctx) {
107                 TALLOC_FREE(p);
108                 *perrno = ENOMEM;
109                 return -1;
110         }
111
112         data_blob_free(&p->in_data.data);
113         data_blob_free(&p->in_data.pdu);
114
115         p->endian = RPC_LITTLE_ENDIAN;
116
117         /* Fake up an auth_user_info_dc for now, to make an info3, to make the session_info structure */
118         auth_user_info_dc = talloc_zero(p, struct auth_user_info_dc);
119         if (!auth_user_info_dc) {
120                 TALLOC_FREE(p);
121                 *perrno = ENOMEM;
122                 return -1;
123         }
124
125         auth_user_info_dc->num_sids = session_info->security_token->num_sids;
126         auth_user_info_dc->sids = session_info->security_token->sids;
127         auth_user_info_dc->info = session_info->info;
128         auth_user_info_dc->user_session_key = session_info->session_key;
129
130         /* This creates the input structure that make_server_info_info3 is looking for */
131         status = auth_convert_user_info_dc_saminfo3(p, auth_user_info_dc,
132                                                     &info3);
133
134         if (!NT_STATUS_IS_OK(status)) {
135                 DEBUG(1, ("Failed to convert auth_user_info_dc into netr_SamInfo3\n"));
136                 TALLOC_FREE(p);
137                 *perrno = EINVAL;
138                 return -1;
139         }
140
141         status = make_server_info_info3(p,
142                                         info3->base.account_name.string,
143                                         info3->base.domain.string,
144                                         &server_info, info3);
145         if (!NT_STATUS_IS_OK(status)) {
146                 DEBUG(1, ("Failed to init server info\n"));
147                 TALLOC_FREE(p);
148                 *perrno = EINVAL;
149                 return -1;
150         }
151
152         /*
153          * Some internal functions need a local token to determine access to
154          * resoutrces.
155          */
156         status = create_local_token(p, server_info, &session_info->session_key, &p->session_info);
157         talloc_free(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;
163         }
164
165         /* Now override the session_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->session_info->security_token = talloc_move(p->session_info, &session_info->security_token);
169
170         p->client_id = talloc_zero(p, struct client_address);
171         if (!p->client_id) {
172                 TALLOC_FREE(p);
173                 *perrno = ENOMEM;
174                 return -1;
175         }
176         strlcpy(p->client_id->addr,
177                 client_address, sizeof(p->client_id->addr));
178         p->client_id->name = talloc_strdup(p->client_id, client_address);
179         if (p->client_id->name == NULL) {
180                 TALLOC_FREE(p);
181                 *perrno = ENOMEM;
182                 return -1;
183         }
184
185         if (server_address != NULL) {
186                 p->server_id = talloc_zero(p, struct client_address);
187                 if (p->client_id == NULL) {
188                         TALLOC_FREE(p);
189                         *perrno = ENOMEM;
190                         return -1;
191                 }
192
193                 strlcpy(p->server_id->addr,
194                         server_address,
195                         sizeof(p->server_id->addr));
196
197                 p->server_id->name = talloc_strdup(p->server_id,
198                                                    server_address);
199                 if (p->server_id->name == NULL) {
200                         TALLOC_FREE(p);
201                         *perrno = ENOMEM;
202                         return -1;
203                 }
204         }
205
206         talloc_set_destructor(p, close_internal_rpc_pipe_hnd);
207
208         *_p = p;
209         return 0;
210 }
211
212 /* Start listening on the appropriate unix socket and setup all is needed to
213  * dispatch requests to the pipes rpc implementation */
214
215 struct dcerpc_ncacn_listen_state {
216         struct ndr_syntax_id syntax_id;
217
218         int fd;
219         union {
220                 char *name;
221                 uint16_t port;
222         } ep;
223
224         struct tevent_context *ev_ctx;
225         struct messaging_context *msg_ctx;
226         dcerpc_ncacn_disconnect_fn disconnect_fn;
227 };
228
229 static void named_pipe_listener(struct tevent_context *ev,
230                                 struct tevent_fd *fde,
231                                 uint16_t flags,
232                                 void *private_data);
233
234 bool setup_named_pipe_socket(const char *pipe_name,
235                              struct tevent_context *ev_ctx)
236 {
237         struct dcerpc_ncacn_listen_state *state;
238         struct tevent_fd *fde;
239         char *np_dir;
240
241         state = talloc(ev_ctx, struct dcerpc_ncacn_listen_state);
242         if (!state) {
243                 DEBUG(0, ("Out of memory\n"));
244                 return false;
245         }
246         state->ep.name = talloc_strdup(state, pipe_name);
247         if (state->ep.name == NULL) {
248                 DEBUG(0, ("Out of memory\n"));
249                 goto out;
250         }
251         state->fd = -1;
252
253         /*
254          * As lp_ncalrpc_dir() should have 0755, but
255          * lp_ncalrpc_dir()/np should have 0700, we need to
256          * create lp_ncalrpc_dir() first.
257          */
258         if (!directory_create_or_exist(lp_ncalrpc_dir(), geteuid(), 0755)) {
259                 DEBUG(0, ("Failed to create pipe directory %s - %s\n",
260                           lp_ncalrpc_dir(), strerror(errno)));
261                 goto out;
262         }
263
264         np_dir = talloc_asprintf(state, "%s/np", lp_ncalrpc_dir());
265         if (!np_dir) {
266                 DEBUG(0, ("Out of memory\n"));
267                 goto out;
268         }
269
270         if (!directory_create_or_exist(np_dir, geteuid(), 0700)) {
271                 DEBUG(0, ("Failed to create pipe directory %s - %s\n",
272                           np_dir, strerror(errno)));
273                 goto out;
274         }
275
276         state->fd = create_pipe_sock(np_dir, pipe_name, 0700);
277         if (state->fd == -1) {
278                 DEBUG(0, ("Failed to create pipe socket! [%s/%s]\n",
279                           np_dir, pipe_name));
280                 goto out;
281         }
282
283         DEBUG(10, ("Openened pipe socket fd %d for %s\n",
284                    state->fd, pipe_name));
285
286         fde = tevent_add_fd(ev_ctx,
287                             state, state->fd, TEVENT_FD_READ,
288                             named_pipe_listener, state);
289         if (!fde) {
290                 DEBUG(0, ("Failed to add event handler!\n"));
291                 goto out;
292         }
293
294         tevent_fd_set_auto_close(fde);
295         return true;
296
297 out:
298         if (state->fd != -1) {
299                 close(state->fd);
300         }
301         TALLOC_FREE(state);
302         return false;
303 }
304
305 static void named_pipe_accept_function(const char *pipe_name, int fd);
306
307 static void named_pipe_listener(struct tevent_context *ev,
308                                 struct tevent_fd *fde,
309                                 uint16_t flags,
310                                 void *private_data)
311 {
312         struct dcerpc_ncacn_listen_state *state =
313                         talloc_get_type_abort(private_data,
314                                               struct dcerpc_ncacn_listen_state);
315         struct sockaddr_un sunaddr;
316         socklen_t len;
317         int sd = -1;
318
319         /* TODO: should we have a limit to the number of clients ? */
320
321         len = sizeof(sunaddr);
322
323         sd = accept(state->fd,
324                     (struct sockaddr *)(void *)&sunaddr, &len);
325
326         if (sd == -1) {
327                 if (errno != EINTR) {
328                         DEBUG(6, ("Failed to get a valid socket [%s]\n",
329                                   strerror(errno)));
330                 }
331                 return;
332         }
333
334         DEBUG(6, ("Accepted socket %d\n", sd));
335
336         named_pipe_accept_function(state->ep.name, sd);
337 }
338
339
340 /* This is the core of the rpc server.
341  * Accepts connections from clients and process requests using the appropriate
342  * dispatcher table. */
343
344 struct named_pipe_client {
345         const char *pipe_name;
346
347         struct tevent_context *ev;
348         struct messaging_context *msg_ctx;
349
350         uint16_t file_type;
351         uint16_t device_state;
352         uint64_t allocation_size;
353
354         struct tstream_context *tstream;
355
356         struct tsocket_address *client;
357         char *client_name;
358         struct tsocket_address *server;
359         char *server_name;
360         struct auth_session_info *session_info;
361
362         struct pipes_struct *p;
363
364         struct tevent_queue *write_queue;
365
366         struct iovec *iov;
367         size_t count;
368 };
369
370 static void named_pipe_accept_done(struct tevent_req *subreq);
371
372 static void named_pipe_accept_function(const char *pipe_name, int fd)
373 {
374         struct named_pipe_client *npc;
375         struct tstream_context *plain;
376         struct tevent_req *subreq;
377         int ret;
378
379         npc = talloc_zero(NULL, struct named_pipe_client);
380         if (!npc) {
381                 DEBUG(0, ("Out of memory!\n"));
382                 close(fd);
383                 return;
384         }
385         npc->pipe_name = pipe_name;
386         npc->ev = server_event_context();
387         npc->msg_ctx = server_messaging_context();
388
389         /* make sure socket is in NON blocking state */
390         ret = set_blocking(fd, false);
391         if (ret != 0) {
392                 DEBUG(2, ("Failed to make socket non-blocking\n"));
393                 TALLOC_FREE(npc);
394                 close(fd);
395                 return;
396         }
397
398         ret = tstream_bsd_existing_socket(npc, fd, &plain);
399         if (ret != 0) {
400                 DEBUG(2, ("Failed to create tstream socket\n"));
401                 TALLOC_FREE(npc);
402                 close(fd);
403                 return;
404         }
405
406         npc->file_type = FILE_TYPE_MESSAGE_MODE_PIPE;
407         npc->device_state = 0xff | 0x0400 | 0x0100;
408         npc->allocation_size = 4096;
409
410         subreq = tstream_npa_accept_existing_send(npc, npc->ev, plain,
411                                                   npc->file_type,
412                                                   npc->device_state,
413                                                   npc->allocation_size);
414         if (!subreq) {
415                 DEBUG(2, ("Failed to start async accept procedure\n"));
416                 TALLOC_FREE(npc);
417                 close(fd);
418                 return;
419         }
420         tevent_req_set_callback(subreq, named_pipe_accept_done, npc);
421 }
422
423 static void named_pipe_packet_process(struct tevent_req *subreq);
424 static void named_pipe_packet_done(struct tevent_req *subreq);
425
426 static void named_pipe_accept_done(struct tevent_req *subreq)
427 {
428         struct auth_session_info_transport *session_info_transport;
429         struct named_pipe_client *npc =
430                 tevent_req_callback_data(subreq, struct named_pipe_client);
431         const char *cli_addr;
432         int error;
433         int ret;
434
435         ret = tstream_npa_accept_existing_recv(subreq, &error, npc,
436                                                 &npc->tstream,
437                                                 &npc->client,
438                                                 &npc->client_name,
439                                                 &npc->server,
440                                                 &npc->server_name,
441                                                 &session_info_transport);
442
443         npc->session_info = talloc_move(npc, &session_info_transport->session_info);
444
445         TALLOC_FREE(subreq);
446         if (ret != 0) {
447                 DEBUG(2, ("Failed to accept named pipe connection! (%s)\n",
448                           strerror(error)));
449                 TALLOC_FREE(npc);
450                 return;
451         }
452
453         if (tsocket_address_is_inet(npc->client, "ip")) {
454                 cli_addr = tsocket_address_inet_addr_string(npc->client,
455                                                             subreq);
456                 if (cli_addr == NULL) {
457                         TALLOC_FREE(npc);
458                         return;
459                 }
460         } else {
461                 cli_addr = "";
462         }
463
464         ret = make_server_pipes_struct(npc,
465                                        npc->pipe_name, NCACN_NP,
466                                         false, cli_addr, NULL, npc->session_info,
467                                         &npc->p, &error);
468         if (ret != 0) {
469                 DEBUG(2, ("Failed to create pipes_struct! (%s)\n",
470                           strerror(error)));
471                 goto fail;
472         }
473         npc->p->msg_ctx = npc->msg_ctx;
474
475         npc->write_queue = tevent_queue_create(npc, "np_server_write_queue");
476         if (!npc->write_queue) {
477                 DEBUG(2, ("Failed to set up write queue!\n"));
478                 goto fail;
479         }
480
481         /* And now start receiving and processing packets */
482         subreq = dcerpc_read_ncacn_packet_send(npc, npc->ev, npc->tstream);
483         if (!subreq) {
484                 DEBUG(2, ("Failed to start receving packets\n"));
485                 goto fail;
486         }
487         tevent_req_set_callback(subreq, named_pipe_packet_process, npc);
488         return;
489
490 fail:
491         DEBUG(2, ("Fatal error. Terminating client(%s) connection!\n",
492                   npc->client_name));
493         /* terminate client connection */
494         talloc_free(npc);
495         return;
496 }
497
498 static void named_pipe_packet_process(struct tevent_req *subreq)
499 {
500         struct named_pipe_client *npc =
501                 tevent_req_callback_data(subreq, struct named_pipe_client);
502         struct _output_data *out = &npc->p->out_data;
503         DATA_BLOB recv_buffer = data_blob_null;
504         struct ncacn_packet *pkt;
505         NTSTATUS status;
506         ssize_t data_left;
507         ssize_t data_used;
508         char *data;
509         uint32_t to_send;
510         bool ok;
511
512         status = dcerpc_read_ncacn_packet_recv(subreq, npc, &pkt, &recv_buffer);
513         TALLOC_FREE(subreq);
514         if (!NT_STATUS_IS_OK(status)) {
515                 goto fail;
516         }
517
518         data_left = recv_buffer.length;
519         data = (char *)recv_buffer.data;
520
521         while (data_left) {
522
523                 data_used = process_incoming_data(npc->p, data, data_left);
524                 if (data_used < 0) {
525                         DEBUG(3, ("Failed to process dceprc request!\n"));
526                         status = NT_STATUS_UNEXPECTED_IO_ERROR;
527                         goto fail;
528                 }
529
530                 data_left -= data_used;
531                 data += data_used;
532         }
533
534         /* Do not leak this buffer, npc is a long lived context */
535         talloc_free(recv_buffer.data);
536         talloc_free(pkt);
537
538         /* this is needed because of the way DCERPC Binds work in
539          * the RPC marshalling code */
540         to_send = out->frag.length - out->current_pdu_sent;
541         if (to_send > 0) {
542
543                 DEBUG(10, ("Current_pdu_len = %u, "
544                            "current_pdu_sent = %u "
545                            "Returning %u bytes\n",
546                            (unsigned int)out->frag.length,
547                            (unsigned int)out->current_pdu_sent,
548                            (unsigned int)to_send));
549
550                 npc->iov = talloc_zero(npc, struct iovec);
551                 if (!npc->iov) {
552                         status = NT_STATUS_NO_MEMORY;
553                         goto fail;
554                 }
555                 npc->count = 1;
556
557                 npc->iov[0].iov_base = out->frag.data
558                                         + out->current_pdu_sent;
559                 npc->iov[0].iov_len = to_send;
560
561                 out->current_pdu_sent += to_send;
562         }
563
564         /* this condition is false for bind packets, or when we haven't
565          * yet got a full request, and need to wait for more data from
566          * the client */
567         while (out->data_sent_length < out->rdata.length) {
568
569                 ok = create_next_pdu(npc->p);
570                 if (!ok) {
571                         DEBUG(3, ("Failed to create next PDU!\n"));
572                         status = NT_STATUS_UNEXPECTED_IO_ERROR;
573                         goto fail;
574                 }
575
576                 npc->iov = talloc_realloc(npc, npc->iov,
577                                             struct iovec, npc->count + 1);
578                 if (!npc->iov) {
579                         status = NT_STATUS_NO_MEMORY;
580                         goto fail;
581                 }
582
583                 npc->iov[npc->count].iov_base = out->frag.data;
584                 npc->iov[npc->count].iov_len = out->frag.length;
585
586                 DEBUG(10, ("PDU number: %d, PDU Length: %u\n",
587                            (unsigned int)npc->count,
588                            (unsigned int)npc->iov[npc->count].iov_len));
589                 dump_data(11, (const uint8_t *)npc->iov[npc->count].iov_base,
590                                 npc->iov[npc->count].iov_len);
591                 npc->count++;
592         }
593
594         /* we still don't have a complete request, go back and wait for more
595          * data */
596         if (npc->count == 0) {
597                 /* Wait for the next packet */
598                 subreq = dcerpc_read_ncacn_packet_send(npc, npc->ev, npc->tstream);
599                 if (!subreq) {
600                         DEBUG(2, ("Failed to start receving packets\n"));
601                         status = NT_STATUS_NO_MEMORY;
602                         goto fail;
603                 }
604                 tevent_req_set_callback(subreq, named_pipe_packet_process, npc);
605                 return;
606         }
607
608         DEBUG(10, ("Sending a total of %u bytes\n",
609                    (unsigned int)npc->p->out_data.data_sent_length));
610
611         subreq = tstream_writev_queue_send(npc, npc->ev,
612                                            npc->tstream,
613                                            npc->write_queue,
614                                            npc->iov, npc->count);
615         if (!subreq) {
616                 DEBUG(2, ("Failed to send packet\n"));
617                 status = NT_STATUS_NO_MEMORY;
618                 goto fail;
619         }
620         tevent_req_set_callback(subreq, named_pipe_packet_done, npc);
621         return;
622
623 fail:
624         DEBUG(2, ("Fatal error(%s). "
625                   "Terminating client(%s) connection!\n",
626                   nt_errstr(status), npc->client_name));
627         /* terminate client connection */
628         talloc_free(npc);
629         return;
630 }
631
632 static void named_pipe_packet_done(struct tevent_req *subreq)
633 {
634         struct named_pipe_client *npc =
635                 tevent_req_callback_data(subreq, struct named_pipe_client);
636         int sys_errno;
637         int ret;
638
639         ret = tstream_writev_queue_recv(subreq, &sys_errno);
640         TALLOC_FREE(subreq);
641         if (ret == -1) {
642                 DEBUG(2, ("Writev failed!\n"));
643                 goto fail;
644         }
645
646         /* clear out any data that may have been left around */
647         npc->count = 0;
648         TALLOC_FREE(npc->iov);
649         data_blob_free(&npc->p->in_data.data);
650         data_blob_free(&npc->p->out_data.frag);
651         data_blob_free(&npc->p->out_data.rdata);
652
653         /* Wait for the next packet */
654         subreq = dcerpc_read_ncacn_packet_send(npc, npc->ev, npc->tstream);
655         if (!subreq) {
656                 DEBUG(2, ("Failed to start receving packets\n"));
657                 sys_errno = ENOMEM;
658                 goto fail;
659         }
660         tevent_req_set_callback(subreq, named_pipe_packet_process, npc);
661         return;
662
663 fail:
664         DEBUG(2, ("Fatal error(%s). "
665                   "Terminating client(%s) connection!\n",
666                   strerror(sys_errno), npc->client_name));
667         /* terminate client connection */
668         talloc_free(npc);
669         return;
670 }
671
672 static void dcerpc_ncacn_accept(struct tevent_context *ev_ctx,
673                                 struct messaging_context *msg_ctx,
674                                 enum dcerpc_transport_t transport,
675                                 const char *name,
676                                 uint16_t port,
677                                 struct tsocket_address *cli_addr,
678                                 struct tsocket_address *srv_addr,
679                                 int s,
680                                 dcerpc_ncacn_disconnect_fn fn);
681
682 /********************************************************************
683  * Start listening on the tcp/ip socket
684  ********************************************************************/
685
686 static void dcerpc_ncacn_tcpip_listener(struct tevent_context *ev,
687                                         struct tevent_fd *fde,
688                                         uint16_t flags,
689                                         void *private_data);
690
691 uint16_t setup_dcerpc_ncacn_tcpip_socket(struct tevent_context *ev_ctx,
692                                          struct messaging_context *msg_ctx,
693                                          const struct sockaddr_storage *ifss,
694                                          uint16_t port)
695 {
696         struct dcerpc_ncacn_listen_state *state;
697         struct tevent_fd *fde;
698         int rc;
699
700         state = talloc(ev_ctx, struct dcerpc_ncacn_listen_state);
701         if (state == NULL) {
702                 DEBUG(0, ("setup_dcerpc_ncacn_tcpip_socket: Out of memory\n"));
703                 return 0;
704         }
705
706         state->fd = -1;
707         state->ep.port = port;
708         state->disconnect_fn = NULL;
709
710         if (state->ep.port == 0) {
711                 uint16_t i;
712
713                 for (i = SERVER_TCP_LOW_PORT; i <= SERVER_TCP_HIGH_PORT; i++) {
714                         state->fd = open_socket_in(SOCK_STREAM,
715                                                    i,
716                                                    0,
717                                                    ifss,
718                                                    false);
719                         if (state->fd > 0) {
720                                 state->ep.port = i;
721                                 break;
722                         }
723                 }
724         } else {
725                 state->fd = open_socket_in(SOCK_STREAM,
726                                            state->ep.port,
727                                            0,
728                                            ifss,
729                                            true);
730         }
731         if (state->fd == -1) {
732                 DEBUG(0, ("setup_dcerpc_ncacn_tcpip_socket: Failed to create "
733                           "socket on port %u!\n", state->ep.port));
734                 goto out;
735         }
736
737         state->ev_ctx = ev_ctx;
738         state->msg_ctx = msg_ctx;
739
740         /* ready to listen */
741         set_socket_options(state->fd, "SO_KEEPALIVE");
742         set_socket_options(state->fd, lp_socket_options());
743
744         /* Set server socket to non-blocking for the accept. */
745         set_blocking(state->fd, false);
746
747         rc = listen(state->fd, SMBD_LISTEN_BACKLOG);
748         if (rc == -1) {
749                 DEBUG(0,("setup_tcpip_socket: listen - %s\n", strerror(errno)));
750                 goto out;
751         }
752
753         DEBUG(10, ("setup_tcpip_socket: openened socket fd %d for port %u\n",
754                    state->fd, state->ep.port));
755
756         fde = tevent_add_fd(state->ev_ctx,
757                             state,
758                             state->fd,
759                             TEVENT_FD_READ,
760                             dcerpc_ncacn_tcpip_listener,
761                             state);
762         if (fde == NULL) {
763                 DEBUG(0, ("setup_tcpip_socket: Failed to add event handler!\n"));
764                 goto out;
765         }
766
767         tevent_fd_set_auto_close(fde);
768
769         return state->ep.port;
770 out:
771         if (state->fd != -1) {
772                 close(state->fd);
773         }
774         TALLOC_FREE(state);
775
776         return 0;
777 }
778
779 static void dcerpc_ncacn_tcpip_listener(struct tevent_context *ev,
780                                         struct tevent_fd *fde,
781                                         uint16_t flags,
782                                         void *private_data)
783 {
784         struct dcerpc_ncacn_listen_state *state =
785                         talloc_get_type_abort(private_data,
786                                               struct dcerpc_ncacn_listen_state);
787         struct tsocket_address *cli_addr = NULL;
788         struct tsocket_address *srv_addr = NULL;
789         struct sockaddr_storage addr;
790         socklen_t in_addrlen = sizeof(addr);
791         int s = -1;
792         int rc;
793
794         s = accept(state->fd, (struct sockaddr *)(void *) &addr, &in_addrlen);
795         if (s == -1) {
796                 if (errno != EINTR) {
797                         DEBUG(0,("tcpip_listener accept: %s\n",
798                                  strerror(errno)));
799                 }
800                 return;
801         }
802
803         rc = tsocket_address_bsd_from_sockaddr(state,
804                                                (struct sockaddr *)(void *) &addr,
805                                                in_addrlen,
806                                                &cli_addr);
807         if (rc < 0) {
808                 close(s);
809                 return;
810         }
811
812         rc = getsockname(s, (struct sockaddr *)(void *) &addr, &in_addrlen);
813         if (rc < 0) {
814                 close(s);
815                 return;
816         }
817
818         rc = tsocket_address_bsd_from_sockaddr(state,
819                                                (struct sockaddr *)(void *) &addr,
820                                                in_addrlen,
821                                                &srv_addr);
822         if (rc < 0) {
823                 close(s);
824                 return;
825         }
826
827         DEBUG(6, ("tcpip_listener: Accepted socket %d\n", s));
828
829         dcerpc_ncacn_accept(state->ev_ctx,
830                             state->msg_ctx,
831                             NCACN_IP_TCP,
832                             NULL,
833                             state->ep.port,
834                             cli_addr,
835                             srv_addr,
836                             s,
837                             NULL);
838 }
839
840 /********************************************************************
841  * Start listening on the ncalrpc socket
842  ********************************************************************/
843
844 static void dcerpc_ncalrpc_listener(struct tevent_context *ev,
845                                     struct tevent_fd *fde,
846                                     uint16_t flags,
847                                     void *private_data);
848
849 bool setup_dcerpc_ncalrpc_socket(struct tevent_context *ev_ctx,
850                                  struct messaging_context *msg_ctx,
851                                  const char *name,
852                                  dcerpc_ncacn_disconnect_fn fn)
853 {
854         struct dcerpc_ncacn_listen_state *state;
855         struct tevent_fd *fde;
856
857         state = talloc(ev_ctx, struct dcerpc_ncacn_listen_state);
858         if (state == NULL) {
859                 DEBUG(0, ("Out of memory\n"));
860                 return false;
861         }
862
863         state->fd = -1;
864         state->disconnect_fn = fn;
865
866         if (name == NULL) {
867                 name = "DEFAULT";
868         }
869         state->ep.name = talloc_strdup(state, name);
870
871         if (state->ep.name == NULL) {
872                 DEBUG(0, ("Out of memory\n"));
873                 talloc_free(state);
874                 return false;
875         }
876
877         if (!directory_create_or_exist(lp_ncalrpc_dir(), geteuid(), 0755)) {
878                 DEBUG(0, ("Failed to create pipe directory %s - %s\n",
879                           lp_ncalrpc_dir(), strerror(errno)));
880                 goto out;
881         }
882
883         state->fd = create_pipe_sock(lp_ncalrpc_dir(), name, 0755);
884         if (state->fd == -1) {
885                 DEBUG(0, ("Failed to create pipe socket! [%s/%s]\n",
886                           lp_ncalrpc_dir(), name));
887                 goto out;
888         }
889
890         DEBUG(10, ("Openened pipe socket fd %d for %s\n", state->fd, name));
891
892         state->ev_ctx = ev_ctx;
893         state->msg_ctx = msg_ctx;
894
895         /* Set server socket to non-blocking for the accept. */
896         set_blocking(state->fd, false);
897
898         fde = tevent_add_fd(state->ev_ctx,
899                             state,
900                             state->fd,
901                             TEVENT_FD_READ,
902                             dcerpc_ncalrpc_listener,
903                             state);
904         if (fde == NULL) {
905                 DEBUG(0, ("Failed to add event handler for ncalrpc!\n"));
906                 goto out;
907         }
908
909         tevent_fd_set_auto_close(fde);
910
911         return true;
912 out:
913         if (state->fd != -1) {
914                 close(state->fd);
915         }
916         TALLOC_FREE(state);
917
918         return 0;
919 }
920
921 static void dcerpc_ncalrpc_listener(struct tevent_context *ev,
922                                         struct tevent_fd *fde,
923                                         uint16_t flags,
924                                         void *private_data)
925 {
926         struct dcerpc_ncacn_listen_state *state =
927                         talloc_get_type_abort(private_data,
928                                               struct dcerpc_ncacn_listen_state);
929         struct tsocket_address *cli_addr = NULL;
930         struct sockaddr_un sunaddr;
931         struct sockaddr *addr = (struct sockaddr *)(void *)&sunaddr;
932         socklen_t len = sizeof(sunaddr);
933         int sd = -1;
934         int rc;
935
936         ZERO_STRUCT(sunaddr);
937
938         sd = accept(state->fd, addr, &len);
939         if (sd == -1) {
940                 if (errno != EINTR) {
941                         DEBUG(0, ("ncalrpc accept() failed: %s\n", strerror(errno)));
942                 }
943                 return;
944         }
945
946         rc = tsocket_address_bsd_from_sockaddr(state,
947                                                addr, len,
948                                                &cli_addr);
949         if (rc < 0) {
950                 close(sd);
951                 return;
952         }
953
954         DEBUG(10, ("Accepted ncalrpc socket %d\n", sd));
955
956         dcerpc_ncacn_accept(state->ev_ctx,
957                             state->msg_ctx,
958                             NCALRPC,
959                             state->ep.name, 0,
960                             cli_addr, NULL, sd,
961                             state->disconnect_fn);
962 }
963
964 struct dcerpc_ncacn_conn {
965         enum dcerpc_transport_t transport;
966
967         union {
968                 const char *name;
969                 uint16_t port;
970         } ep;
971
972         int sock;
973
974         struct pipes_struct *p;
975         dcerpc_ncacn_disconnect_fn disconnect_fn;
976
977         struct tevent_context *ev_ctx;
978         struct messaging_context *msg_ctx;
979
980         struct tstream_context *tstream;
981         struct tevent_queue *send_queue;
982
983         struct tsocket_address *client;
984         char *client_name;
985         struct tsocket_address *server;
986         char *server_name;
987         struct auth_session_info *session_info;
988
989         struct iovec *iov;
990         size_t count;
991 };
992
993 static void dcerpc_ncacn_packet_process(struct tevent_req *subreq);
994 static void dcerpc_ncacn_packet_done(struct tevent_req *subreq);
995
996 static void dcerpc_ncacn_accept(struct tevent_context *ev_ctx,
997                                 struct messaging_context *msg_ctx,
998                                 enum dcerpc_transport_t transport,
999                                 const char *name,
1000                                 uint16_t port,
1001                                 struct tsocket_address *cli_addr,
1002                                 struct tsocket_address *srv_addr,
1003                                 int s,
1004                                 dcerpc_ncacn_disconnect_fn fn) {
1005         struct dcerpc_ncacn_conn *ncacn_conn;
1006         struct tevent_req *subreq;
1007         const char *cli_str;
1008         const char *srv_str = NULL;
1009         bool system_user = false;
1010         char *pipe_name;
1011         NTSTATUS status;
1012         int sys_errno;
1013         uid_t uid;
1014         int rc;
1015
1016         DEBUG(10, ("dcerpc_ncacn_accept\n"));
1017
1018         ncacn_conn = talloc_zero(ev_ctx, struct dcerpc_ncacn_conn);
1019         if (ncacn_conn == NULL) {
1020                 DEBUG(0, ("Out of memory!\n"));
1021                 close(s);
1022                 return;
1023         }
1024
1025         ncacn_conn->transport = transport;
1026         ncacn_conn->ev_ctx = ev_ctx;
1027         ncacn_conn->msg_ctx = msg_ctx;
1028         ncacn_conn->sock = s;
1029         ncacn_conn->disconnect_fn = fn;
1030
1031         ncacn_conn->client = talloc_move(ncacn_conn, &cli_addr);
1032         if (tsocket_address_is_inet(ncacn_conn->client, "ip")) {
1033                 ncacn_conn->client_name =
1034                         tsocket_address_inet_addr_string(ncacn_conn->client,
1035                                                          ncacn_conn);
1036         } else {
1037                 ncacn_conn->client_name =
1038                         tsocket_address_unix_path(ncacn_conn->client,
1039                                                   ncacn_conn);
1040         }
1041         if (ncacn_conn->client_name == NULL) {
1042                 DEBUG(0, ("Out of memory!\n"));
1043                 talloc_free(ncacn_conn);
1044                 close(s);
1045                 return;
1046         }
1047
1048         if (srv_addr != NULL) {
1049                 ncacn_conn->server = talloc_move(ncacn_conn, &srv_addr);
1050
1051                 ncacn_conn->server_name =
1052                         tsocket_address_inet_addr_string(ncacn_conn->server,
1053                                                          ncacn_conn);
1054                 if (ncacn_conn->server_name == NULL) {
1055                         DEBUG(0, ("Out of memory!\n"));
1056                         talloc_free(ncacn_conn);
1057                         close(s);
1058                         return;
1059                 }
1060         }
1061
1062         switch (transport) {
1063                 case NCACN_IP_TCP:
1064                         ncacn_conn->ep.port = port;
1065
1066                         pipe_name = tsocket_address_string(ncacn_conn->client,
1067                                                            ncacn_conn);
1068                         if (pipe_name == NULL) {
1069                                 close(s);
1070                                 talloc_free(ncacn_conn);
1071                                 return;
1072                         }
1073
1074                         break;
1075                 case NCALRPC:
1076                         rc = sys_getpeereid(s, &uid);
1077                         if (rc < 0) {
1078                                 DEBUG(2, ("Failed to get ncalrpc connecting uid!"));
1079                         } else {
1080                                 if (uid == sec_initial_uid()) {
1081                                         system_user = true;
1082                                 }
1083                         }
1084                 case NCACN_NP:
1085                         ncacn_conn->ep.name = talloc_strdup(ncacn_conn, name);
1086                         if (ncacn_conn->ep.name == NULL) {
1087                                 close(s);
1088                                 talloc_free(ncacn_conn);
1089                                 return;
1090                         }
1091
1092                         pipe_name = talloc_strdup(ncacn_conn,
1093                                                   name);
1094                         if (pipe_name == NULL) {
1095                                 close(s);
1096                                 talloc_free(ncacn_conn);
1097                                 return;
1098                         }
1099                         break;
1100                 default:
1101                         DEBUG(0, ("unknown dcerpc transport: %u!\n",
1102                                   transport));
1103                         talloc_free(ncacn_conn);
1104                         close(s);
1105                         return;
1106         }
1107
1108         rc = set_blocking(s, false);
1109         if (rc < 0) {
1110                 DEBUG(2, ("Failed to set dcerpc socket to non-blocking\n"));
1111                 talloc_free(ncacn_conn);
1112                 close(s);
1113                 return;
1114         }
1115
1116         /*
1117          * As soon as we have tstream_bsd_existing_socket set up it will
1118          * take care of closing the socket.
1119          */
1120         rc = tstream_bsd_existing_socket(ncacn_conn, s, &ncacn_conn->tstream);
1121         if (rc < 0) {
1122                 DEBUG(2, ("Failed to create tstream socket for dcerpc\n"));
1123                 talloc_free(ncacn_conn);
1124                 close(s);
1125                 return;
1126         }
1127
1128         if (tsocket_address_is_inet(ncacn_conn->client, "ip")) {
1129                 cli_str = ncacn_conn->client_name;
1130         } else {
1131                 cli_str = "";
1132         }
1133
1134         if (ncacn_conn->server != NULL) {
1135                 if (tsocket_address_is_inet(ncacn_conn->server, "ip")) {
1136                         srv_str = ncacn_conn->server_name;
1137                 } else {
1138                         srv_str = NULL;
1139                 }
1140         }
1141
1142         if (ncacn_conn->session_info == NULL) {
1143                 status = auth_anonymous_session_info(ncacn_conn,
1144                                                      &ncacn_conn->session_info);
1145                 if (!NT_STATUS_IS_OK(status)) {
1146                         DEBUG(2, ("Failed to create "
1147                                   "auth_anonymous_session_info - %s\n",
1148                                   nt_errstr(status)));
1149                         talloc_free(ncacn_conn);
1150                         return;
1151                 }
1152         }
1153
1154         rc = make_server_pipes_struct(ncacn_conn,
1155                                       pipe_name,
1156                                       ncacn_conn->transport,
1157                                       system_user,
1158                                       cli_str,
1159                                       srv_str,
1160                                       ncacn_conn->session_info,
1161                                       &ncacn_conn->p,
1162                                       &sys_errno);
1163         if (rc < 0) {
1164                 DEBUG(2, ("Failed to create pipe struct - %s",
1165                           strerror(sys_errno)));
1166                 talloc_free(ncacn_conn);
1167                 return;
1168         }
1169
1170         ncacn_conn->send_queue = tevent_queue_create(ncacn_conn,
1171                                                         "dcerpc send queue");
1172         if (ncacn_conn->send_queue == NULL) {
1173                 DEBUG(0, ("Out of memory!\n"));
1174                 talloc_free(ncacn_conn);
1175                 return;
1176         }
1177
1178         subreq = dcerpc_read_ncacn_packet_send(ncacn_conn,
1179                                                ncacn_conn->ev_ctx,
1180                                                ncacn_conn->tstream);
1181         if (subreq == NULL) {
1182                 DEBUG(2, ("Failed to send ncacn packet\n"));
1183                 talloc_free(ncacn_conn);
1184                 return;
1185         }
1186
1187         tevent_req_set_callback(subreq, dcerpc_ncacn_packet_process, ncacn_conn);
1188
1189         DEBUG(10, ("dcerpc_ncacn_accept done\n"));
1190
1191         return;
1192 }
1193
1194 static void dcerpc_ncacn_packet_process(struct tevent_req *subreq)
1195 {
1196         struct dcerpc_ncacn_conn *ncacn_conn =
1197                 tevent_req_callback_data(subreq, struct dcerpc_ncacn_conn);
1198
1199         struct _output_data *out = &ncacn_conn->p->out_data;
1200         DATA_BLOB recv_buffer = data_blob_null;
1201         struct ncacn_packet *pkt;
1202         ssize_t data_left;
1203         ssize_t data_used;
1204         uint32_t to_send;
1205         char *data;
1206         NTSTATUS status;
1207         bool ok;
1208
1209         status = dcerpc_read_ncacn_packet_recv(subreq, ncacn_conn, &pkt, &recv_buffer);
1210         TALLOC_FREE(subreq);
1211         if (!NT_STATUS_IS_OK(status)) {
1212                 if (ncacn_conn->disconnect_fn != NULL) {
1213                         ok = ncacn_conn->disconnect_fn(ncacn_conn->p);
1214                         if (!ok) {
1215                                 DEBUG(3, ("Failed to call disconnect function\n"));
1216                         }
1217                 }
1218                 goto fail;
1219         }
1220
1221         data_left = recv_buffer.length;
1222         data = (char *) recv_buffer.data;
1223
1224         while (data_left) {
1225                 data_used = process_incoming_data(ncacn_conn->p, data, data_left);
1226                 if (data_used < 0) {
1227                         DEBUG(3, ("Failed to process dcerpc request!\n"));
1228                         status = NT_STATUS_UNEXPECTED_IO_ERROR;
1229                         goto fail;
1230                 }
1231
1232                 data_left -= data_used;
1233                 data += data_used;
1234         }
1235
1236         /* Do not leak this buffer */
1237         talloc_free(recv_buffer.data);
1238         talloc_free(pkt);
1239
1240         /*
1241          * This is needed because of the way DCERPC binds work in the RPC
1242          * marshalling code
1243          */
1244         to_send = out->frag.length - out->current_pdu_sent;
1245         if (to_send > 0) {
1246
1247                 DEBUG(10, ("Current_pdu_len = %u, "
1248                            "current_pdu_sent = %u "
1249                            "Returning %u bytes\n",
1250                            (unsigned int)out->frag.length,
1251                            (unsigned int)out->current_pdu_sent,
1252                            (unsigned int)to_send));
1253
1254                 ncacn_conn->iov = talloc_zero(ncacn_conn, struct iovec);
1255                 if (ncacn_conn->iov == NULL) {
1256                         status = NT_STATUS_NO_MEMORY;
1257                         DEBUG(3, ("Out of memory!\n"));
1258                         goto fail;
1259                 }
1260                 ncacn_conn->count = 1;
1261
1262                 ncacn_conn->iov[0].iov_base = out->frag.data
1263                                             + out->current_pdu_sent;
1264                 ncacn_conn->iov[0].iov_len = to_send;
1265
1266                 out->current_pdu_sent += to_send;
1267         }
1268
1269         /*
1270          * This condition is false for bind packets, or when we haven't yet got
1271          * a full request, and need to wait for more data from the client
1272          */
1273         while (out->data_sent_length < out->rdata.length) {
1274                 ok = create_next_pdu(ncacn_conn->p);
1275                 if (!ok) {
1276                         DEBUG(3, ("Failed to create next PDU!\n"));
1277                         status = NT_STATUS_UNEXPECTED_IO_ERROR;
1278                         goto fail;
1279                 }
1280
1281                 ncacn_conn->iov = talloc_realloc(ncacn_conn,
1282                                                  ncacn_conn->iov,
1283                                                  struct iovec,
1284                                                  ncacn_conn->count + 1);
1285                 if (ncacn_conn->iov == NULL) {
1286                         DEBUG(3, ("Out of memory!\n"));
1287                         status = NT_STATUS_NO_MEMORY;
1288                         goto fail;
1289                 }
1290
1291                 ncacn_conn->iov[ncacn_conn->count].iov_base = out->frag.data;
1292                 ncacn_conn->iov[ncacn_conn->count].iov_len = out->frag.length;
1293
1294                 DEBUG(10, ("PDU number: %d, PDU Length: %u\n",
1295                            (unsigned int) ncacn_conn->count,
1296                            (unsigned int) ncacn_conn->iov[ncacn_conn->count].iov_len));
1297                 dump_data(11, (const uint8_t *) ncacn_conn->iov[ncacn_conn->count].iov_base,
1298                               ncacn_conn->iov[ncacn_conn->count].iov_len);
1299                 ncacn_conn->count++;
1300         }
1301
1302         /*
1303          * We still don't have a complete request, go back and wait for more
1304          * data.
1305          */
1306         if (ncacn_conn->count == 0) {
1307                 /* Wait for the next packet */
1308                 subreq = dcerpc_read_ncacn_packet_send(ncacn_conn,
1309                                                        ncacn_conn->ev_ctx,
1310                                                        ncacn_conn->tstream);
1311                 if (subreq == NULL) {
1312                         DEBUG(2, ("Failed to start receving packets\n"));
1313                         status = NT_STATUS_NO_MEMORY;
1314                         goto fail;
1315                 }
1316                 tevent_req_set_callback(subreq, dcerpc_ncacn_packet_process, ncacn_conn);
1317                 return;
1318         }
1319
1320         DEBUG(10, ("Sending a total of %u bytes\n",
1321                    (unsigned int)ncacn_conn->p->out_data.data_sent_length));
1322
1323         subreq = tstream_writev_queue_send(ncacn_conn,
1324                                            ncacn_conn->ev_ctx,
1325                                            ncacn_conn->tstream,
1326                                            ncacn_conn->send_queue,
1327                                            ncacn_conn->iov,
1328                                            ncacn_conn->count);
1329         if (subreq == NULL) {
1330                 DEBUG(2, ("Failed to send packet\n"));
1331                 status = NT_STATUS_NO_MEMORY;
1332                 goto fail;
1333         }
1334
1335         tevent_req_set_callback(subreq, dcerpc_ncacn_packet_done, ncacn_conn);
1336         return;
1337
1338 fail:
1339         DEBUG(3, ("Terminating client(%s) connection! - '%s'\n",
1340                   ncacn_conn->client_name, nt_errstr(status)));
1341
1342         /* Terminate client connection */
1343         talloc_free(ncacn_conn);
1344         return;
1345 }
1346
1347 static void dcerpc_ncacn_packet_done(struct tevent_req *subreq)
1348 {
1349         struct dcerpc_ncacn_conn *ncacn_conn =
1350                 tevent_req_callback_data(subreq, struct dcerpc_ncacn_conn);
1351         NTSTATUS status = NT_STATUS_OK;
1352         int sys_errno;
1353         int rc;
1354
1355         rc = tstream_writev_queue_recv(subreq, &sys_errno);
1356         TALLOC_FREE(subreq);
1357         if (rc < 0) {
1358                 DEBUG(2, ("Writev failed!\n"));
1359                 status = map_nt_error_from_unix(sys_errno);
1360                 goto fail;
1361         }
1362
1363         /* clear out any data that may have been left around */
1364         ncacn_conn->count = 0;
1365         TALLOC_FREE(ncacn_conn->iov);
1366         data_blob_free(&ncacn_conn->p->in_data.data);
1367         data_blob_free(&ncacn_conn->p->out_data.frag);
1368         data_blob_free(&ncacn_conn->p->out_data.rdata);
1369
1370         /* Wait for the next packet */
1371         subreq = dcerpc_read_ncacn_packet_send(ncacn_conn,
1372                                                ncacn_conn->ev_ctx,
1373                                                ncacn_conn->tstream);
1374         if (subreq == NULL) {
1375                 DEBUG(2, ("Failed to start receving packets\n"));
1376                 status = NT_STATUS_NO_MEMORY;
1377                 goto fail;
1378         }
1379
1380         tevent_req_set_callback(subreq, dcerpc_ncacn_packet_process, ncacn_conn);
1381         return;
1382
1383 fail:
1384         DEBUG(3, ("Terminating client(%s) connection! - '%s'\n",
1385                   ncacn_conn->client_name, nt_errstr(status)));
1386
1387         /* Terminate client connection */
1388         talloc_free(ncacn_conn);
1389         return;
1390 }
1391
1392 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */