s3-rpc_server: Create a common ncacn listen state.
[mat/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 "registry/reg_parse_prs.h"
26 #include "lib/tsocket/tsocket.h"
27 #include "libcli/named_pipe_auth/npa_tstream.h"
28 #include "../auth/auth_sam_reply.h"
29
30 /* Creates a pipes_struct and initializes it with the information
31  * sent from the client */
32 static int make_server_pipes_struct(TALLOC_CTX *mem_ctx,
33                                     const char *pipe_name,
34                                     const struct ndr_syntax_id id,
35                                     const char *client_address,
36                                     struct auth_session_info_transport *session_info,
37                                     struct pipes_struct **_p,
38                                     int *perrno)
39 {
40         struct netr_SamInfo3 *info3;
41         struct auth_user_info_dc *auth_user_info_dc;
42         struct pipes_struct *p;
43         NTSTATUS status;
44         bool ok;
45
46         p = talloc_zero(mem_ctx, struct pipes_struct);
47         if (!p) {
48                 *perrno = ENOMEM;
49                 return -1;
50         }
51         p->syntax = id;
52
53         p->mem_ctx = talloc_named(p, 0, "pipe %s %p", pipe_name, p);
54         if (!p->mem_ctx) {
55                 TALLOC_FREE(p);
56                 *perrno = ENOMEM;
57                 return -1;
58         }
59
60         ok = init_pipe_handles(p, &id);
61         if (!ok) {
62                 DEBUG(1, ("Failed to init handles\n"));
63                 TALLOC_FREE(p);
64                 *perrno = EINVAL;
65                 return -1;
66         }
67
68
69         data_blob_free(&p->in_data.data);
70         data_blob_free(&p->in_data.pdu);
71
72         p->endian = RPC_LITTLE_ENDIAN;
73
74         /* Fake up an auth_user_info_dc for now, to make an info3, to make the server_info structure */
75         auth_user_info_dc = talloc_zero(p, struct auth_user_info_dc);
76         if (!auth_user_info_dc) {
77                 TALLOC_FREE(p);
78                 *perrno = ENOMEM;
79                 return -1;
80         }
81
82         auth_user_info_dc->num_sids = session_info->security_token->num_sids;
83         auth_user_info_dc->sids = session_info->security_token->sids;
84         auth_user_info_dc->info = session_info->info;
85         auth_user_info_dc->user_session_key = session_info->session_key;
86
87         /* This creates the input structure that make_server_info_info3 is looking for */
88         status = auth_convert_user_info_dc_saminfo3(p, auth_user_info_dc,
89                                                     &info3);
90
91         if (!NT_STATUS_IS_OK(status)) {
92                 DEBUG(1, ("Failed to convert auth_user_info_dc into netr_SamInfo3\n"));
93                 TALLOC_FREE(p);
94                 *perrno = EINVAL;
95                 return -1;
96         }
97
98         status = make_server_info_info3(p,
99                                         info3->base.account_name.string,
100                                         info3->base.domain.string,
101                                         &p->server_info, info3);
102         if (!NT_STATUS_IS_OK(status)) {
103                 DEBUG(1, ("Failed to init server info\n"));
104                 TALLOC_FREE(p);
105                 *perrno = EINVAL;
106                 return -1;
107         }
108
109         /*
110          * Some internal functions need a local token to determine access to
111          * resoutrces.
112          */
113         status = create_local_token(p->server_info);
114         if (!NT_STATUS_IS_OK(status)) {
115                 DEBUG(1, ("Failed to init local auth token\n"));
116                 TALLOC_FREE(p);
117                 *perrno = EINVAL;
118                 return -1;
119         }
120
121         /* Now override the server_info->security_token with the exact
122          * security_token we were given from the other side,
123          * regardless of what we just calculated */
124         p->server_info->security_token = talloc_move(p->server_info, &session_info->security_token);
125
126         /* Also set the session key to the correct value */
127         p->server_info->user_session_key = session_info->session_key;
128         p->server_info->user_session_key.data = talloc_move(p->server_info, &session_info->session_key.data);
129
130         p->client_id = talloc_zero(p, struct client_address);
131         if (!p->client_id) {
132                 TALLOC_FREE(p);
133                 *perrno = ENOMEM;
134                 return -1;
135         }
136         strlcpy(p->client_id->addr,
137                 client_address, sizeof(p->client_id->addr));
138         p->client_id->name = talloc_strdup(p->client_id, client_address);
139         if (p->client_id->name == NULL) {
140                 TALLOC_FREE(p);
141                 *perrno = ENOMEM;
142                 return -1;
143         }
144
145         talloc_set_destructor(p, close_internal_rpc_pipe_hnd);
146
147         *_p = p;
148         return 0;
149 }
150
151 /* Add some helper functions to wrap the common ncacn packet reading functions
152  * until we can share more dcerpc code */
153 struct dcerpc_ncacn_read_packet_state {
154         struct ncacn_packet *pkt;
155         DATA_BLOB buffer;
156 };
157
158 static void dcerpc_ncacn_read_packet_done(struct tevent_req *subreq);
159
160 static struct tevent_req *dcerpc_ncacn_read_packet_send(TALLOC_CTX *mem_ctx,
161                                         struct tevent_context *ev,
162                                         struct tstream_context *tstream)
163 {
164         struct dcerpc_ncacn_read_packet_state *state;
165         struct tevent_req *req, *subreq;
166
167         req = tevent_req_create(mem_ctx, &state,
168                                 struct dcerpc_ncacn_read_packet_state);
169         if (!req) {
170                 return NULL;
171         }
172         ZERO_STRUCTP(state);
173
174         subreq = dcerpc_read_ncacn_packet_send(state, ev, tstream);
175         if (!subreq) {
176                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
177                 tevent_req_post(req, ev);
178                 return req;
179         }
180         tevent_req_set_callback(subreq, dcerpc_ncacn_read_packet_done, req);
181
182         return req;
183 }
184
185 static void dcerpc_ncacn_read_packet_done(struct tevent_req *subreq)
186 {
187         struct tevent_req *req =
188                 tevent_req_callback_data(subreq, struct tevent_req);
189         struct dcerpc_ncacn_read_packet_state *state =
190                 tevent_req_data(req, struct dcerpc_ncacn_read_packet_state);
191         NTSTATUS status;
192
193         status = dcerpc_read_ncacn_packet_recv(subreq, state,
194                                                 &state->pkt,
195                                                 &state->buffer);
196         TALLOC_FREE(subreq);
197         if (!NT_STATUS_IS_OK(status)) {
198                 DEBUG(3, ("Failed to receive dceprc packet!\n"));
199                 tevent_req_nterror(req, status);
200                 return;
201         }
202
203         tevent_req_done(req);
204 }
205
206 static NTSTATUS dcerpc_ncacn_read_packet_recv(struct tevent_req *req,
207                                                 TALLOC_CTX *mem_ctx,
208                                                 DATA_BLOB *buffer)
209 {
210         struct dcerpc_ncacn_read_packet_state *state =
211                 tevent_req_data(req, struct dcerpc_ncacn_read_packet_state);
212         NTSTATUS status;
213
214         if (tevent_req_is_nterror(req, &status)) {
215                 tevent_req_received(req);
216                 return status;
217         }
218
219         buffer->data = talloc_move(mem_ctx, &state->buffer.data);
220         buffer->length = state->buffer.length;
221
222         tevent_req_received(req);
223         return NT_STATUS_OK;
224 }
225
226
227
228 /* Start listening on the appropriate unix socket and setup all is needed to
229  * dispatch requests to the pipes rpc implementation */
230
231 struct dcerpc_ncacn_listen_state {
232         int fd;
233         union {
234                 char *name;
235                 uint16_t port;
236         } ep;
237 };
238
239 static void named_pipe_listener(struct tevent_context *ev,
240                                 struct tevent_fd *fde,
241                                 uint16_t flags,
242                                 void *private_data);
243
244 bool setup_named_pipe_socket(const char *pipe_name,
245                              struct tevent_context *ev_ctx)
246 {
247         struct dcerpc_ncacn_listen_state *state;
248         struct tevent_fd *fde;
249         char *np_dir;
250
251         state = talloc(ev_ctx, struct dcerpc_ncacn_listen_state);
252         if (!state) {
253                 DEBUG(0, ("Out of memory\n"));
254                 return false;
255         }
256         state->ep.name = talloc_strdup(state, pipe_name);
257         if (state->ep.name == NULL) {
258                 DEBUG(0, ("Out of memory\n"));
259                 goto out;
260         }
261         state->fd = -1;
262
263         np_dir = talloc_asprintf(state, "%s/np", lp_ncalrpc_dir());
264         if (!np_dir) {
265                 DEBUG(0, ("Out of memory\n"));
266                 goto out;
267         }
268
269         if (!directory_create_or_exist(np_dir, geteuid(), 0700)) {
270                 DEBUG(0, ("Failed to create pipe directory %s - %s\n",
271                           np_dir, strerror(errno)));
272                 goto out;
273         }
274
275         state->fd = create_pipe_sock(np_dir, pipe_name, 0700);
276         if (state->fd == -1) {
277                 DEBUG(0, ("Failed to create pipe socket! [%s/%s]\n",
278                           np_dir, pipe_name));
279                 goto out;
280         }
281
282         DEBUG(10, ("Openened pipe socket fd %d for %s\n",
283                    state->fd, pipe_name));
284
285         fde = tevent_add_fd(ev_ctx,
286                             state, state->fd, TEVENT_FD_READ,
287                             named_pipe_listener, state);
288         if (!fde) {
289                 DEBUG(0, ("Failed to add event handler!\n"));
290                 goto out;
291         }
292
293         tevent_fd_set_auto_close(fde);
294         return true;
295
296 out:
297         if (state->fd != -1) {
298                 close(state->fd);
299         }
300         TALLOC_FREE(state);
301         return false;
302 }
303
304 static void named_pipe_accept_function(const char *pipe_name, int fd);
305
306 static void named_pipe_listener(struct tevent_context *ev,
307                                 struct tevent_fd *fde,
308                                 uint16_t flags,
309                                 void *private_data)
310 {
311         struct dcerpc_ncacn_listen_state *state =
312                         talloc_get_type_abort(private_data,
313                                               struct dcerpc_ncacn_listen_state);
314         struct sockaddr_un sunaddr;
315         socklen_t len;
316         int sd = -1;
317
318         /* TODO: should we have a limit to the number of clients ? */
319
320         len = sizeof(sunaddr);
321
322         while (sd == -1) {
323                 sd = accept(state->fd,
324                             (struct sockaddr *)(void *)&sunaddr, &len);
325                 if (errno != EINTR) break;
326         }
327
328         if (sd == -1) {
329                 DEBUG(6, ("Failed to get a valid socket [%s]\n",
330                           strerror(errno)));
331                 return;
332         }
333
334         DEBUG(6, ("Accepted socket %d\n", sd));
335
336         named_pipe_accept_function(state->ep.name, sd);
337 }
338
339
340 /* This is the core of the rpc server.
341  * Accepts connections from clients and process requests using the appropriate
342  * dispatcher table. */
343
344 struct named_pipe_client {
345         const char *pipe_name;
346         struct ndr_syntax_id pipe_id;
347
348         struct tevent_context *ev;
349         struct messaging_context *msg_ctx;
350
351         uint16_t file_type;
352         uint16_t device_state;
353         uint64_t allocation_size;
354
355         struct tstream_context *tstream;
356
357         struct tsocket_address *client;
358         char *client_name;
359         struct tsocket_address *server;
360         char *server_name;
361         struct auth_session_info_transport *session_info;
362
363         struct pipes_struct *p;
364
365         struct tevent_queue *write_queue;
366
367         struct iovec *iov;
368         size_t count;
369 };
370
371 static void named_pipe_accept_done(struct tevent_req *subreq);
372
373 static void named_pipe_accept_function(const char *pipe_name, int fd)
374 {
375         struct ndr_syntax_id syntax;
376         struct named_pipe_client *npc;
377         struct tstream_context *plain;
378         struct tevent_req *subreq;
379         bool ok;
380         int ret;
381
382         ok = is_known_pipename(pipe_name, &syntax);
383         if (!ok) {
384                 DEBUG(1, ("Unknown pipe [%s]\n", pipe_name));
385                 close(fd);
386                 return;
387         }
388
389         npc = talloc_zero(NULL, struct named_pipe_client);
390         if (!npc) {
391                 DEBUG(0, ("Out of memory!\n"));
392                 close(fd);
393                 return;
394         }
395         npc->pipe_name = pipe_name;
396         npc->pipe_id = syntax;
397         npc->ev = server_event_context();
398         npc->msg_ctx = server_messaging_context();
399
400         /* make sure socket is in NON blocking state */
401         ret = set_blocking(fd, false);
402         if (ret != 0) {
403                 DEBUG(2, ("Failed to make socket non-blocking\n"));
404                 TALLOC_FREE(npc);
405                 close(fd);
406                 return;
407         }
408
409         ret = tstream_bsd_existing_socket(npc, fd, &plain);
410         if (ret != 0) {
411                 DEBUG(2, ("Failed to create tstream socket\n"));
412                 TALLOC_FREE(npc);
413                 close(fd);
414                 return;
415         }
416
417         npc->file_type = FILE_TYPE_MESSAGE_MODE_PIPE;
418         npc->device_state = 0xff | 0x0400 | 0x0100;
419         npc->allocation_size = 4096;
420
421         subreq = tstream_npa_accept_existing_send(npc, npc->ev, plain,
422                                                   npc->file_type,
423                                                   npc->device_state,
424                                                   npc->allocation_size);
425         if (!subreq) {
426                 DEBUG(2, ("Failed to start async accept procedure\n"));
427                 TALLOC_FREE(npc);
428                 close(fd);
429                 return;
430         }
431         tevent_req_set_callback(subreq, named_pipe_accept_done, npc);
432 }
433
434 static void named_pipe_packet_process(struct tevent_req *subreq);
435 static void named_pipe_packet_done(struct tevent_req *subreq);
436
437 static void named_pipe_accept_done(struct tevent_req *subreq)
438 {
439         struct named_pipe_client *npc =
440                 tevent_req_callback_data(subreq, struct named_pipe_client);
441         const char *cli_addr;
442         int error;
443         int ret;
444
445         ret = tstream_npa_accept_existing_recv(subreq, &error, npc,
446                                                 &npc->tstream,
447                                                 &npc->client,
448                                                 &npc->client_name,
449                                                 &npc->server,
450                                                 &npc->server_name,
451                                                 &npc->session_info);
452         TALLOC_FREE(subreq);
453         if (ret != 0) {
454                 DEBUG(2, ("Failed to accept named pipe connection! (%s)\n",
455                           strerror(error)));
456                 TALLOC_FREE(npc);
457                 return;
458         }
459
460         if (tsocket_address_is_inet(npc->client, "ip")) {
461                 cli_addr = tsocket_address_inet_addr_string(npc->client,
462                                                             subreq);
463                 if (cli_addr == NULL) {
464                         TALLOC_FREE(npc);
465                         return;
466                 }
467         } else {
468                 cli_addr = "";
469         }
470
471         ret = make_server_pipes_struct(npc,
472                                         npc->pipe_name, npc->pipe_id,
473                                         cli_addr, npc->session_info,
474                                         &npc->p, &error);
475         if (ret != 0) {
476                 DEBUG(2, ("Failed to create pipes_struct! (%s)\n",
477                           strerror(error)));
478                 goto fail;
479         }
480         npc->p->msg_ctx = npc->msg_ctx;
481
482         npc->write_queue = tevent_queue_create(npc, "np_server_write_queue");
483         if (!npc->write_queue) {
484                 DEBUG(2, ("Failed to set up write queue!\n"));
485                 goto fail;
486         }
487
488         /* And now start receaving and processing packets */
489         subreq = dcerpc_ncacn_read_packet_send(npc, npc->ev, npc->tstream);
490         if (!subreq) {
491                 DEBUG(2, ("Failed to start receving packets\n"));
492                 goto fail;
493         }
494         tevent_req_set_callback(subreq, named_pipe_packet_process, npc);
495         return;
496
497 fail:
498         DEBUG(2, ("Fatal error. Terminating client(%s) connection!\n",
499                   npc->client_name));
500         /* terminate client connection */
501         talloc_free(npc);
502         return;
503 }
504
505 static void named_pipe_packet_process(struct tevent_req *subreq)
506 {
507         struct named_pipe_client *npc =
508                 tevent_req_callback_data(subreq, struct named_pipe_client);
509         struct _output_data *out = &npc->p->out_data;
510         DATA_BLOB recv_buffer = data_blob_null;
511         NTSTATUS status;
512         ssize_t data_left;
513         ssize_t data_used;
514         char *data;
515         uint32_t to_send;
516         bool ok;
517
518         status = dcerpc_ncacn_read_packet_recv(subreq, npc, &recv_buffer);
519         TALLOC_FREE(subreq);
520         if (!NT_STATUS_IS_OK(status)) {
521                 goto fail;
522         }
523
524         data_left = recv_buffer.length;
525         data = (char *)recv_buffer.data;
526
527         while (data_left) {
528
529                 data_used = process_incoming_data(npc->p, data, data_left);
530                 if (data_used < 0) {
531                         DEBUG(3, ("Failed to process dceprc request!\n"));
532                         status = NT_STATUS_UNEXPECTED_IO_ERROR;
533                         goto fail;
534                 }
535
536                 data_left -= data_used;
537                 data += data_used;
538         }
539
540         /* Do not leak this buffer, npc is a long lived context */
541         talloc_free(recv_buffer.data);
542
543         /* this is needed because of the way DCERPC Binds work in
544          * the RPC marshalling code */
545         to_send = out->frag.length - out->current_pdu_sent;
546         if (to_send > 0) {
547
548                 DEBUG(10, ("Current_pdu_len = %u, "
549                            "current_pdu_sent = %u "
550                            "Returning %u bytes\n",
551                            (unsigned int)out->frag.length,
552                            (unsigned int)out->current_pdu_sent,
553                            (unsigned int)to_send));
554
555                 npc->iov = talloc_zero(npc, struct iovec);
556                 if (!npc->iov) {
557                         status = NT_STATUS_NO_MEMORY;
558                         goto fail;
559                 }
560                 npc->count = 1;
561
562                 npc->iov[0].iov_base = out->frag.data
563                                         + out->current_pdu_sent;
564                 npc->iov[0].iov_len = to_send;
565
566                 out->current_pdu_sent += to_send;
567         }
568
569         /* this condition is false for bind packets, or when we haven't
570          * yet got a full request, and need to wait for more data from
571          * the client */
572         while (out->data_sent_length < out->rdata.length) {
573
574                 ok = create_next_pdu(npc->p);
575                 if (!ok) {
576                         DEBUG(3, ("Failed to create next PDU!\n"));
577                         status = NT_STATUS_UNEXPECTED_IO_ERROR;
578                         goto fail;
579                 }
580
581                 npc->iov = talloc_realloc(npc, npc->iov,
582                                             struct iovec, npc->count + 1);
583                 if (!npc->iov) {
584                         status = NT_STATUS_NO_MEMORY;
585                         goto fail;
586                 }
587
588                 npc->iov[npc->count].iov_base = out->frag.data;
589                 npc->iov[npc->count].iov_len = out->frag.length;
590
591                 DEBUG(10, ("PDU number: %d, PDU Length: %u\n",
592                            (unsigned int)npc->count,
593                            (unsigned int)npc->iov[npc->count].iov_len));
594                 dump_data(11, (const uint8_t *)npc->iov[npc->count].iov_base,
595                                 npc->iov[npc->count].iov_len);
596                 npc->count++;
597         }
598
599         /* we still don't have a complete request, go back and wait for more
600          * data */
601         if (npc->count == 0) {
602                 /* Wait for the next packet */
603                 subreq = dcerpc_ncacn_read_packet_send(npc, npc->ev, npc->tstream);
604                 if (!subreq) {
605                         DEBUG(2, ("Failed to start receving packets\n"));
606                         status = NT_STATUS_NO_MEMORY;
607                         goto fail;
608                 }
609                 tevent_req_set_callback(subreq, named_pipe_packet_process, npc);
610                 return;
611         }
612
613         DEBUG(10, ("Sending a total of %u bytes\n",
614                    (unsigned int)npc->p->out_data.data_sent_length));
615
616         subreq = tstream_writev_queue_send(npc, npc->ev,
617                                            npc->tstream,
618                                            npc->write_queue,
619                                            npc->iov, npc->count);
620         if (!subreq) {
621                 DEBUG(2, ("Failed to send packet\n"));
622                 status = NT_STATUS_NO_MEMORY;
623                 goto fail;
624         }
625         tevent_req_set_callback(subreq, named_pipe_packet_done, npc);
626         return;
627
628 fail:
629         DEBUG(2, ("Fatal error(%s). "
630                   "Terminating client(%s) connection!\n",
631                   nt_errstr(status), npc->client_name));
632         /* terminate client connection */
633         talloc_free(npc);
634         return;
635 }
636
637 static void named_pipe_packet_done(struct tevent_req *subreq)
638 {
639         struct named_pipe_client *npc =
640                 tevent_req_callback_data(subreq, struct named_pipe_client);
641         int sys_errno;
642         int ret;
643
644         ret = tstream_writev_queue_recv(subreq, &sys_errno);
645         TALLOC_FREE(subreq);
646         if (ret == -1) {
647                 DEBUG(2, ("Writev failed!\n"));
648                 goto fail;
649         }
650
651         /* clear out any data that may have been left around */
652         npc->count = 0;
653         TALLOC_FREE(npc->iov);
654         data_blob_free(&npc->p->in_data.data);
655         data_blob_free(&npc->p->out_data.frag);
656         data_blob_free(&npc->p->out_data.rdata);
657
658         /* Wait for the next packet */
659         subreq = dcerpc_ncacn_read_packet_send(npc, npc->ev, npc->tstream);
660         if (!subreq) {
661                 DEBUG(2, ("Failed to start receving packets\n"));
662                 sys_errno = ENOMEM;
663                 goto fail;
664         }
665         tevent_req_set_callback(subreq, named_pipe_packet_process, npc);
666         return;
667
668 fail:
669         DEBUG(2, ("Fatal error(%s). "
670                   "Terminating client(%s) connection!\n",
671                   strerror(sys_errno), npc->client_name));
672         /* terminate client connection */
673         talloc_free(npc);
674         return;
675  }