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