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