libndr: Avoid assigning duplicate versions to symbols
[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    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 "librpc/rpc/dcesrv_core.h"
24 #include "rpc_server/rpc_pipes.h"
25 #include "rpc_server/rpc_server.h"
26 #include "rpc_server/rpc_config.h"
27 #include "rpc_dce.h"
28 #include "librpc/gen_ndr/netlogon.h"
29 #include "librpc/gen_ndr/auth.h"
30 #include "lib/tsocket/tsocket.h"
31 #include "libcli/named_pipe_auth/npa_tstream.h"
32 #include "../auth/auth_sam_reply.h"
33 #include "auth.h"
34 #include "rpc_server/rpc_ncacn_np.h"
35 #include "rpc_server/srv_pipe_hnd.h"
36 #include "rpc_server/srv_pipe.h"
37
38 #undef DBGC_CLASS
39 #define DBGC_CLASS DBGC_RPC_SRV
40
41 /* Creates a pipes_struct and initializes it with the information
42  * sent from the client */
43 int make_server_pipes_struct(TALLOC_CTX *mem_ctx,
44                              struct messaging_context *msg_ctx,
45                              const char *pipe_name,
46                              enum dcerpc_transport_t transport,
47                              const struct tsocket_address *remote_address,
48                              const struct tsocket_address *local_address,
49                              struct pipes_struct **_p,
50                              int *perrno)
51 {
52         struct pipes_struct *p;
53         int ret;
54
55         ret = make_base_pipes_struct(mem_ctx, msg_ctx, pipe_name,
56                                      transport,
57                                      remote_address, local_address, &p);
58         if (ret) {
59                 *perrno = ret;
60                 return -1;
61         }
62
63         *_p = p;
64         return 0;
65 }
66
67 /* Start listening on the appropriate unix socket and setup all is needed to
68  * dispatch requests to the pipes rpc implementation */
69
70 struct dcerpc_ncacn_listen_state {
71         int fd;
72
73         struct tevent_context *ev_ctx;
74         struct messaging_context *msg_ctx;
75         struct dcesrv_context *dce_ctx;
76         struct dcesrv_endpoint *endpoint;
77         dcerpc_ncacn_termination_fn termination_fn;
78         void *termination_data;
79 };
80
81 static void dcesrv_ncacn_np_listener(struct tevent_context *ev,
82                                      struct tevent_fd *fde,
83                                      uint16_t flags,
84                                      void *private_data);
85
86 NTSTATUS dcesrv_create_ncacn_np_socket(struct dcesrv_endpoint *e, int *out_fd)
87 {
88         char *np_dir = NULL;
89         int fd = -1;
90         NTSTATUS status;
91         const char *endpoint;
92         char *endpoint_normalized = NULL;
93         char *p = NULL;
94
95         endpoint = dcerpc_binding_get_string_option(e->ep_description,
96                                                     "endpoint");
97         if (endpoint == NULL) {
98                 DBG_ERR("Endpoint mandatory for named pipes\n");
99                 return NT_STATUS_INVALID_PARAMETER;
100         }
101
102         /* The endpoint string from IDL can be mixed uppercase and case is
103          * normalized by smbd on connection */
104         endpoint_normalized = strlower_talloc(talloc_tos(), endpoint);
105         if (endpoint_normalized == NULL) {
106                 return NT_STATUS_NO_MEMORY;
107         }
108
109         /* The endpoint string from IDL can be prefixed by \pipe\ */
110         p = endpoint_normalized;
111         if (strncmp(p, "\\pipe\\", 6) == 0) {
112                 p += 6;
113         }
114
115         /*
116          * As lp_ncalrpc_dir() should have 0755, but
117          * lp_ncalrpc_dir()/np should have 0700, we need to
118          * create lp_ncalrpc_dir() first.
119          */
120         if (!directory_create_or_exist(lp_ncalrpc_dir(), 0755)) {
121                 status = map_nt_error_from_unix_common(errno);
122                 DBG_ERR("Failed to create pipe directory %s - %s\n",
123                         lp_ncalrpc_dir(), strerror(errno));
124                 goto out;
125         }
126
127         np_dir = talloc_asprintf(talloc_tos(), "%s/np", lp_ncalrpc_dir());
128         if (!np_dir) {
129                 status = NT_STATUS_NO_MEMORY;
130                 DBG_ERR("Out of memory\n");
131                 goto out;
132         }
133
134         if (!directory_create_or_exist_strict(np_dir, geteuid(), 0700)) {
135                 status = map_nt_error_from_unix_common(errno);
136                 DBG_ERR("Failed to create pipe directory %s - %s\n",
137                         np_dir, strerror(errno));
138                 goto out;
139         }
140
141         fd = create_pipe_sock(np_dir, p, 0700);
142         if (fd == -1) {
143                 status = map_nt_error_from_unix_common(errno);
144                 DBG_ERR("Failed to create ncacn_np socket! '%s/%s': %s\n",
145                         np_dir, p, strerror(errno));
146                 goto out;
147         }
148
149         DBG_DEBUG("Opened pipe socket fd %d for %s\n", fd, p);
150
151         *out_fd = fd;
152
153         status = NT_STATUS_OK;
154
155 out:
156         TALLOC_FREE(endpoint_normalized);
157         TALLOC_FREE(np_dir);
158         return status;
159 }
160
161 NTSTATUS dcesrv_setup_ncacn_np_socket(struct tevent_context *ev_ctx,
162                                       struct messaging_context *msg_ctx,
163                                       struct dcesrv_context *dce_ctx,
164                                       struct dcesrv_endpoint *e,
165                                       dcerpc_ncacn_termination_fn term_fn,
166                                       void *term_data)
167 {
168         struct dcerpc_ncacn_listen_state *state;
169         struct tevent_fd *fde;
170         int rc;
171         NTSTATUS status;
172         const char *endpoint = NULL;
173
174         endpoint = dcerpc_binding_get_string_option(e->ep_description,
175                                                     "endpoint");
176         if (endpoint == NULL) {
177                 DBG_ERR("Endpoint mandatory for named pipes\n");
178                 return NT_STATUS_INVALID_PARAMETER;
179         }
180
181         /* Alloc in endpoint context. If the endpoint is freed (for example
182          * when forked daemons reinit the dcesrv_context, the tevent_fd
183          * listener will be stopped and the socket closed */
184         state = talloc_zero(e, struct dcerpc_ncacn_listen_state);
185         if (state == NULL) {
186                 DBG_ERR("Out of memory\n");
187                 return NT_STATUS_NO_MEMORY;
188         }
189         state->fd = -1;
190         state->ev_ctx = ev_ctx;
191         state->msg_ctx = msg_ctx;
192         state->endpoint = e;
193         state->dce_ctx = dce_ctx;
194         state->termination_fn = term_fn;
195         state->termination_data = term_data;
196
197         status = dcesrv_create_ncacn_np_socket(e, &state->fd);
198         if (!NT_STATUS_IS_OK(status)) {
199                 goto out;
200         }
201
202         rc = listen(state->fd, 5);
203         if (rc < 0) {
204                 status = map_nt_error_from_unix_common(errno);
205                 DBG_ERR("Failed to listen on ncacn_np socket %s: %s\n",
206                         endpoint, strerror(errno));
207                 goto out;
208         }
209
210         DBG_DEBUG("Opened pipe socket fd %d for %s\n",
211                   state->fd, endpoint);
212
213         errno = 0;
214         fde = tevent_add_fd(ev_ctx,
215                             state, state->fd, TEVENT_FD_READ,
216                             dcesrv_ncacn_np_listener, state);
217         if (fde == NULL) {
218                 if (errno == 0) {
219                         errno = ENOMEM;
220                 }
221                 status = map_nt_error_from_unix_common(errno);
222                 DBG_ERR("Failed to add event handler for ncacn_np: %s\n",
223                         strerror(errno));
224                 goto out;
225         }
226
227         tevent_fd_set_auto_close(fde);
228
229         return NT_STATUS_OK;
230
231 out:
232         if (state->fd != -1) {
233                 close(state->fd);
234         }
235         TALLOC_FREE(state);
236         return status;
237 }
238
239 static void dcesrv_ncacn_np_listener(struct tevent_context *ev,
240                                      struct tevent_fd *fde,
241                                      uint16_t flags,
242                                      void *private_data)
243 {
244         struct dcerpc_ncacn_listen_state *state =
245                         talloc_get_type_abort(private_data,
246                                               struct dcerpc_ncacn_listen_state);
247         struct samba_sockaddr addr = {
248                 .sa_socklen = sizeof(struct sockaddr_un),
249         };
250         int sd = -1;
251         const char *endpoint = NULL;
252
253         /* TODO: should we have a limit to the number of clients ? */
254
255         sd = accept(state->fd, &addr.u.sa, &addr.sa_socklen);
256
257         if (sd == -1) {
258                 if (errno != EINTR) {
259                         DEBUG(6, ("Failed to get a valid socket [%s]\n",
260                                   strerror(errno)));
261                 }
262                 return;
263         }
264         smb_set_close_on_exec(sd);
265
266         endpoint = dcerpc_binding_get_string_option(
267                         state->endpoint->ep_description, "endpoint");
268         if (endpoint == NULL) {
269                 DBG_ERR("Failed to get endpoint from binding description\n");
270                 close(sd);
271                 return;
272         }
273
274         DBG_DEBUG("Accepted ncacn_np socket %s (fd: %d)\n",
275                    addr.u.un.sun_path, sd);
276
277         dcerpc_ncacn_accept(state->ev_ctx,
278                             state->msg_ctx,
279                             state->dce_ctx,
280                             state->endpoint,
281                             NULL, /* remote client address */
282                             NULL, /* local server address */
283                             sd,
284                             state->termination_fn,
285                             state->termination_data);
286 }
287
288 /********************************************************************
289  * Start listening on the tcp/ip socket
290  ********************************************************************/
291
292 static void dcesrv_ncacn_ip_tcp_listener(struct tevent_context *ev,
293                                          struct tevent_fd *fde,
294                                          uint16_t flags,
295                                          void *private_data);
296
297 NTSTATUS dcesrv_create_ncacn_ip_tcp_socket(const struct sockaddr_storage *ifss,
298                                            uint16_t *port,
299                                            int *out_fd)
300 {
301         int fd = -1;
302
303         if (*port == 0) {
304                 uint16_t i;
305
306                 for (i = lp_rpc_low_port(); i <= lp_rpc_high_port(); i++) {
307                         fd = open_socket_in(SOCK_STREAM,
308                                             i,
309                                             0,
310                                             ifss,
311                                             false);
312                         if (fd >= 0) {
313                                 *port = i;
314                                 break;
315                         }
316                 }
317         } else {
318                 fd = open_socket_in(SOCK_STREAM,
319                                     *port,
320                                     0,
321                                     ifss,
322                                     true);
323         }
324         if (fd == -1) {
325                 DBG_ERR("Failed to create socket on port %u!\n", *port);
326                 return NT_STATUS_UNSUCCESSFUL;
327         }
328
329         DBG_DEBUG("Opened ncacn_ip_tcp socket fd %d for port %u\n", fd, *port);
330
331         *out_fd = fd;
332
333         return NT_STATUS_OK;
334 }
335
336 NTSTATUS dcesrv_setup_ncacn_ip_tcp_socket(struct tevent_context *ev_ctx,
337                                           struct messaging_context *msg_ctx,
338                                           struct dcesrv_context *dce_ctx,
339                                           struct dcesrv_endpoint *e,
340                                           const struct sockaddr_storage *ifss,
341                                           dcerpc_ncacn_termination_fn term_fn,
342                                           void *term_data)
343 {
344         struct dcerpc_ncacn_listen_state *state = NULL;
345         struct tevent_fd *fde = NULL;
346         const char *endpoint = NULL;
347         uint16_t port = 0;
348         char port_str[6];
349         int rc;
350         NTSTATUS status;
351
352         endpoint = dcerpc_binding_get_string_option(e->ep_description,
353                                                     "endpoint");
354         if (endpoint != NULL) {
355                 port = atoi(endpoint);
356         }
357
358         /* Alloc in endpoint context. If the endpoint is freed (for example
359          * when forked daemons reinit the dcesrv_context, the tevent_fd
360          * listener will be stopped and the socket closed */
361         state = talloc_zero(e, struct dcerpc_ncacn_listen_state);
362         if (state == NULL) {
363                 DBG_ERR("Out of memory\n");
364                 return NT_STATUS_NO_MEMORY;
365         }
366
367         state->fd = -1;
368         state->ev_ctx = ev_ctx;
369         state->msg_ctx = msg_ctx;
370         state->endpoint = e;
371         state->dce_ctx = dce_ctx;
372         state->termination_fn = term_fn;
373         state->termination_data = term_data;
374
375         status = dcesrv_create_ncacn_ip_tcp_socket(ifss, &port, &state->fd);
376         if (!NT_STATUS_IS_OK(status)) {
377                 goto out;
378         }
379
380         /* ready to listen */
381         set_socket_options(state->fd, "SO_KEEPALIVE");
382         set_socket_options(state->fd, lp_socket_options());
383
384         /* Set server socket to non-blocking for the accept. */
385         rc = set_blocking(state->fd, false);
386         if (rc < 0) {
387                 status = map_nt_error_from_unix_common(errno);
388                 goto out;
389         }
390
391         rc = listen(state->fd, SMBD_LISTEN_BACKLOG);
392         if (rc == -1) {
393                 status = map_nt_error_from_unix_common(errno);
394                 DBG_ERR("Failed to listen on ncacn_ip_tcp socket: %s\n",
395                         strerror(errno));
396                 goto out;
397         }
398
399         DBG_DEBUG("Opened socket fd %d for port %u\n",
400                   state->fd, port);
401
402         errno = 0;
403         fde = tevent_add_fd(state->ev_ctx,
404                             state,
405                             state->fd,
406                             TEVENT_FD_READ,
407                             dcesrv_ncacn_ip_tcp_listener,
408                             state);
409         if (fde == NULL) {
410                 if (errno == 0) {
411                         errno = ENOMEM;
412                 }
413                 status = map_nt_error_from_unix_common(errno);
414                 DBG_ERR("Failed to add event handler for ncacn_ip_tcp: %s\n",
415                         strerror(errno));
416                 goto out;
417         }
418
419         tevent_fd_set_auto_close(fde);
420
421         /* Set the port in the endpoint */
422         snprintf(port_str, sizeof(port_str), "%u", port);
423
424         status = dcerpc_binding_set_string_option(e->ep_description,
425                                                   "endpoint", port_str);
426         if (!NT_STATUS_IS_OK(status)) {
427                 DBG_ERR("Failed to set binding endpoint '%s': %s\n",
428                         port_str, nt_errstr(status));
429                 goto out;
430         }
431
432         return NT_STATUS_OK;
433
434 out:
435         if (state->fd != -1) {
436                 close(state->fd);
437         }
438         TALLOC_FREE(state);
439
440         return status;
441 }
442
443 static void dcesrv_ncacn_ip_tcp_listener(struct tevent_context *ev,
444                                          struct tevent_fd *fde,
445                                          uint16_t flags,
446                                          void *private_data)
447 {
448         struct dcerpc_ncacn_listen_state *state =
449                 talloc_get_type_abort(private_data,
450                                       struct dcerpc_ncacn_listen_state);
451         struct tsocket_address *cli_addr = NULL;
452         struct tsocket_address *srv_addr = NULL;
453         struct samba_sockaddr addr = {
454                 .sa_socklen = sizeof(struct sockaddr_storage),
455         };
456         int s = -1;
457         int rc;
458
459         s = accept(state->fd, &addr.u.sa, &addr.sa_socklen);
460         if (s == -1) {
461                 if (errno != EINTR) {
462                         DBG_ERR("Failed to accept: %s\n", strerror(errno));
463                 }
464                 return;
465         }
466         smb_set_close_on_exec(s);
467
468         rc = tsocket_address_bsd_from_samba_sockaddr(state, &addr, &cli_addr);
469         if (rc < 0) {
470                 close(s);
471                 return;
472         }
473
474         rc = getsockname(s, &addr.u.sa, &addr.sa_socklen);
475         if (rc < 0) {
476                 close(s);
477                 return;
478         }
479
480         rc = tsocket_address_bsd_from_samba_sockaddr(state, &addr, &srv_addr);
481         if (rc < 0) {
482                 close(s);
483                 return;
484         }
485
486         DBG_DEBUG("Accepted ncacn_ip_tcp socket %d\n", s);
487
488         dcerpc_ncacn_accept(state->ev_ctx,
489                             state->msg_ctx,
490                             state->dce_ctx,
491                             state->endpoint,
492                             cli_addr,
493                             srv_addr,
494                             s,
495                             state->termination_fn,
496                             state->termination_data);
497 }
498
499 /********************************************************************
500  * Start listening on the ncalrpc socket
501  ********************************************************************/
502
503 static void dcesrv_ncalrpc_listener(struct tevent_context *ev,
504                                     struct tevent_fd *fde,
505                                     uint16_t flags,
506                                     void *private_data);
507
508 NTSTATUS dcesrv_create_ncalrpc_socket(struct dcesrv_endpoint *e, int *out_fd)
509 {
510         int fd = -1;
511         const char *endpoint = NULL;
512         NTSTATUS status;
513
514         endpoint = dcerpc_binding_get_string_option(e->ep_description,
515                                                     "endpoint");
516         if (endpoint == NULL) {
517                 /*
518                  * No identifier specified: use DEFAULT or SMBD.
519                  *
520                  * When role is AD DC we run two rpc server instances, the one
521                  * started by 'samba' and the one embedded in 'smbd'.
522                  * Avoid listening in DEFAULT socket for NCALRPC as both
523                  * servers will race to accept connections. In this case smbd
524                  * will listen in SMBD socket and rpcint binding handle
525                  * implementation will pick the right socket to use.
526                  *
527                  * TODO: DO NOT hardcode this value anywhere else. Rather,
528                  * specify no endpoint and let the epmapper worry about it.
529                  */
530                 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
531                         endpoint = "SMBD";
532                 } else {
533                         endpoint = "DEFAULT";
534                 }
535                 status = dcerpc_binding_set_string_option(e->ep_description,
536                                                           "endpoint",
537                                                           endpoint);
538                 if (!NT_STATUS_IS_OK(status)) {
539                         DBG_ERR("Failed to set ncalrpc 'endpoint' binding "
540                                 "string option to '%s': %s\n",
541                                 endpoint, nt_errstr(status));
542                         return status;
543                 }
544         }
545
546         if (!directory_create_or_exist(lp_ncalrpc_dir(), 0755)) {
547                 status = map_nt_error_from_unix_common(errno);
548                 DBG_ERR("Failed to create ncalrpc directory '%s': %s\n",
549                         lp_ncalrpc_dir(), strerror(errno));
550                 goto out;
551         }
552
553         fd = create_pipe_sock(lp_ncalrpc_dir(), endpoint, 0755);
554         if (fd == -1) {
555                 status = map_nt_error_from_unix_common(errno);
556                 DBG_ERR("Failed to create ncalrpc socket '%s/%s': %s\n",
557                         lp_ncalrpc_dir(), endpoint, strerror(errno));
558                 goto out;
559         }
560
561         DBG_DEBUG("Opened ncalrpc socket fd '%d' for '%s/%s'\n",
562                   fd, lp_ncalrpc_dir(), endpoint);
563
564         *out_fd = fd;
565
566         return NT_STATUS_OK;
567
568 out:
569         return status;
570 }
571
572 NTSTATUS dcesrv_setup_ncalrpc_socket(struct tevent_context *ev_ctx,
573                                      struct messaging_context *msg_ctx,
574                                      struct dcesrv_context *dce_ctx,
575                                      struct dcesrv_endpoint *e,
576                                      dcerpc_ncacn_termination_fn term_fn,
577                                      void *termination_data)
578 {
579         struct dcerpc_ncacn_listen_state *state;
580         struct tevent_fd *fde;
581         int rc;
582         NTSTATUS status;
583
584         /* Alloc in endpoint context. If the endpoint is freed (for example
585          * when forked daemons reinit the dcesrv_context, the tevent_fd
586          * listener will be stopped and the socket closed */
587         state = talloc_zero(e, struct dcerpc_ncacn_listen_state);
588         if (state == NULL) {
589                 DBG_ERR("Out of memory\n");
590                 return NT_STATUS_NO_MEMORY;
591         }
592
593         state->fd = -1;
594         state->ev_ctx = ev_ctx;
595         state->msg_ctx = msg_ctx;
596         state->dce_ctx = dce_ctx;
597         state->endpoint = e;
598         state->termination_fn = term_fn;
599         state->termination_data = termination_data;
600
601         status = dcesrv_create_ncalrpc_socket(e, &state->fd);
602         if (!NT_STATUS_IS_OK(status)) {
603                 DBG_ERR("Failed to create ncalrpc socket: %s\n",
604                         nt_errstr(status));
605                 goto out;
606         }
607
608         rc = listen(state->fd, 5);
609         if (rc < 0) {
610                 const char *endpoint = dcerpc_binding_get_string_option(
611                                 e->ep_description, "endpoint");
612                 status = map_nt_error_from_unix_common(errno);
613                 DBG_ERR("Failed to listen on ncalrpc socket %s: %s\n",
614                         endpoint, strerror(errno));
615                 goto out;
616         }
617
618         /* Set server socket to non-blocking for the accept. */
619         rc = set_blocking(state->fd, false);
620         if (rc < 0) {
621                 status = map_nt_error_from_unix_common(errno);
622                 goto out;
623         }
624
625         errno = 0;
626         fde = tevent_add_fd(state->ev_ctx,
627                             state,
628                             state->fd,
629                             TEVENT_FD_READ,
630                             dcesrv_ncalrpc_listener,
631                             state);
632         if (fde == NULL) {
633                 if (errno == 0) {
634                         errno = ENOMEM;
635                 }
636                 status = map_nt_error_from_unix_common(errno);
637                 DBG_ERR("Failed to add event handler for ncalrpc: %s\n",
638                         strerror(errno));
639                 goto out;
640         }
641
642         tevent_fd_set_auto_close(fde);
643
644         return NT_STATUS_OK;
645 out:
646         if (state->fd != -1) {
647                 close(state->fd);
648         }
649         TALLOC_FREE(state);
650
651         return status;
652 }
653
654 static void dcesrv_ncalrpc_listener(struct tevent_context *ev,
655                                         struct tevent_fd *fde,
656                                         uint16_t flags,
657                                         void *private_data)
658 {
659         struct dcerpc_ncacn_listen_state *state =
660                 talloc_get_type_abort(private_data,
661                                       struct dcerpc_ncacn_listen_state);
662         struct tsocket_address *cli_addr = NULL, *srv_addr = NULL;
663         struct samba_sockaddr addr = {
664                 .sa_socklen = sizeof(struct sockaddr_un),
665         };
666         struct samba_sockaddr addr_server = {
667                 .sa_socklen = sizeof(struct sockaddr_un),
668         };
669         int sd = -1;
670         int rc;
671         const char *endpoint = NULL;
672
673         sd = accept(state->fd, &addr.u.sa, &addr.sa_socklen);
674         if (sd == -1) {
675                 if (errno != EINTR) {
676                         DBG_ERR("Failed to accept: %s\n", strerror(errno));
677                 }
678                 return;
679         }
680         smb_set_close_on_exec(sd);
681
682         rc = tsocket_address_bsd_from_samba_sockaddr(state, &addr, &cli_addr);
683         if (rc < 0) {
684                 close(sd);
685                 return;
686         }
687
688         rc = getsockname(sd, &addr_server.u.sa, &addr_server.sa_socklen);
689         if (rc < 0) {
690                 close(sd);
691                 return;
692         }
693
694         rc = tsocket_address_bsd_from_samba_sockaddr(state,
695                                                      &addr_server,
696                                                      &srv_addr);
697         if (rc < 0) {
698                 close(sd);
699                 return;
700         }
701
702         endpoint = dcerpc_binding_get_string_option(
703                         state->endpoint->ep_description, "endpoint");
704         if (endpoint == NULL) {
705                 DBG_ERR("Failed to get endpoint from binding description\n");
706                 close(sd);
707                 return;
708         }
709
710         DBG_DEBUG("Accepted ncalrpc socket %s (fd: %d)\n",
711                    addr.u.un.sun_path, sd);
712
713         dcerpc_ncacn_accept(state->ev_ctx,
714                             state->msg_ctx,
715                             state->dce_ctx,
716                             state->endpoint,
717                             cli_addr, srv_addr, sd,
718                             state->termination_fn,
719                             state->termination_data);
720 }
721
722 static int dcesrv_connection_destructor(struct dcesrv_connection *conn)
723 {
724         struct dcerpc_ncacn_conn *ncacn_conn = talloc_get_type_abort(
725                         conn->transport.private_data,
726                         struct dcerpc_ncacn_conn);
727
728         if (ncacn_conn->termination_fn != NULL) {
729                 ncacn_conn->termination_fn(conn, ncacn_conn->termination_data);
730         }
731
732         return 0;
733 }
734
735 NTSTATUS dcerpc_ncacn_conn_init(TALLOC_CTX *mem_ctx,
736                                 struct tevent_context *ev_ctx,
737                                 struct messaging_context *msg_ctx,
738                                 struct dcesrv_context *dce_ctx,
739                                 struct dcesrv_endpoint *endpoint,
740                                 dcerpc_ncacn_termination_fn term_fn,
741                                 void *termination_data,
742                                 struct dcerpc_ncacn_conn **out)
743 {
744         struct dcerpc_ncacn_conn *ncacn_conn = NULL;
745
746         ncacn_conn = talloc_zero(mem_ctx, struct dcerpc_ncacn_conn);
747         if (ncacn_conn == NULL) {
748                 return NT_STATUS_NO_MEMORY;
749         }
750
751         ncacn_conn->ev_ctx = ev_ctx;
752         ncacn_conn->msg_ctx = msg_ctx;
753         ncacn_conn->dce_ctx = dce_ctx;
754         ncacn_conn->endpoint = endpoint;
755         ncacn_conn->sock = -1;
756         ncacn_conn->termination_fn = term_fn;
757         ncacn_conn->termination_data = termination_data;
758
759         *out = ncacn_conn;
760
761         return NT_STATUS_OK;
762 }
763
764 static void dcesrv_ncacn_np_accept_done(struct tevent_req *subreq);
765 static void dcesrv_ncacn_accept_step2(struct dcerpc_ncacn_conn *ncacn_conn);
766
767 static void ncacn_terminate_connection(struct dcerpc_ncacn_conn *conn,
768                                        const char *reason);
769
770 void dcerpc_ncacn_accept(struct tevent_context *ev_ctx,
771                          struct messaging_context *msg_ctx,
772                          struct dcesrv_context *dce_ctx,
773                          struct dcesrv_endpoint *e,
774                          struct tsocket_address *cli_addr,
775                          struct tsocket_address *srv_addr,
776                          int s,
777                          dcerpc_ncacn_termination_fn termination_fn,
778                          void *termination_data)
779 {
780         enum dcerpc_transport_t transport =
781                 dcerpc_binding_get_transport(e->ep_description);
782         struct dcerpc_ncacn_conn *ncacn_conn;
783         NTSTATUS status;
784         int rc;
785
786         DBG_DEBUG("dcerpc_ncacn_accept\n");
787
788         status = dcerpc_ncacn_conn_init(ev_ctx,
789                                         ev_ctx,
790                                         msg_ctx,
791                                         dce_ctx,
792                                         e,
793                                         termination_fn,
794                                         termination_data,
795                                         &ncacn_conn);
796         if (!NT_STATUS_IS_OK(status)) {
797                 DBG_ERR("Failed to initialize dcerpc_ncacn_connection: %s\n",
798                         nt_errstr(status));
799                 close(s);
800                 return;
801         }
802
803         ncacn_conn->sock = s;
804
805         if (cli_addr != NULL) {
806                 ncacn_conn->remote_client_addr = talloc_move(ncacn_conn, &cli_addr);
807
808                 if (tsocket_address_is_inet(ncacn_conn->remote_client_addr, "ip")) {
809                         ncacn_conn->remote_client_name =
810                                 tsocket_address_inet_addr_string(ncacn_conn->remote_client_addr,
811                                                                  ncacn_conn);
812                 } else {
813                         ncacn_conn->remote_client_name =
814                                 tsocket_address_unix_path(ncacn_conn->remote_client_addr,
815                                                           ncacn_conn);
816                 }
817
818                 if (ncacn_conn->remote_client_name == NULL) {
819                         DBG_ERR("Out of memory obtaining remote socket address as a string!\n");
820                         ncacn_terminate_connection(ncacn_conn, "No memory");
821                         close(s);
822                         return;
823                 }
824         }
825
826         if (srv_addr != NULL) {
827                 ncacn_conn->local_server_addr = talloc_move(ncacn_conn, &srv_addr);
828
829                 if (tsocket_address_is_inet(ncacn_conn->local_server_addr, "ip")) {
830                         ncacn_conn->local_server_name =
831                                 tsocket_address_inet_addr_string(ncacn_conn->local_server_addr,
832                                                                  ncacn_conn);
833                 } else {
834                         ncacn_conn->local_server_name =
835                                 tsocket_address_unix_path(ncacn_conn->local_server_addr,
836                                                           ncacn_conn);
837                 }
838                 if (ncacn_conn->local_server_name == NULL) {
839                         DBG_ERR("No memory\n");
840                         ncacn_terminate_connection(ncacn_conn, "No memory");
841                         close(s);
842                         return;
843                 }
844         }
845
846         rc = set_blocking(s, false);
847         if (rc < 0) {
848                 DBG_WARNING("Failed to set dcerpc socket to non-blocking\n");
849                 ncacn_terminate_connection(ncacn_conn, strerror(errno));
850                 close(s);
851                 return;
852         }
853
854         /*
855          * As soon as we have tstream_bsd_existing_socket set up it will
856          * take care of closing the socket.
857          */
858         rc = tstream_bsd_existing_socket(ncacn_conn, s, &ncacn_conn->tstream);
859         if (rc < 0) {
860                 DBG_WARNING("Failed to create tstream socket for dcerpc\n");
861                 ncacn_terminate_connection(ncacn_conn, "No memory");
862                 close(s);
863                 return;
864         }
865
866         if (transport == NCACN_NP) {
867                 struct tevent_req *subreq = NULL;
868                 uint64_t allocation_size = 4096;
869                 uint16_t device_state = 0xff | 0x0400 | 0x0100;
870                 uint16_t file_type = FILE_TYPE_MESSAGE_MODE_PIPE;
871
872                 subreq = tstream_npa_accept_existing_send(ncacn_conn,
873                                                           ncacn_conn->ev_ctx,
874                                                           ncacn_conn->tstream,
875                                                           file_type,
876                                                           device_state,
877                                                           allocation_size);
878                 if (subreq == NULL) {
879                         ncacn_terminate_connection(ncacn_conn, "No memory");
880                         return;
881                 }
882                 tevent_req_set_callback(subreq, dcesrv_ncacn_np_accept_done,
883                                         ncacn_conn);
884                 return;
885         }
886
887         dcesrv_ncacn_accept_step2(ncacn_conn);
888 }
889
890 static void dcesrv_ncacn_np_accept_done(struct tevent_req *subreq)
891 {
892         struct auth_session_info_transport *session_info_transport = NULL;
893         struct dcerpc_ncacn_conn *ncacn_conn = NULL;
894         int error;
895         int ret;
896
897         ncacn_conn = tevent_req_callback_data(subreq,
898                                               struct dcerpc_ncacn_conn);
899
900         ret = tstream_npa_accept_existing_recv(subreq, &error, ncacn_conn,
901                                                &ncacn_conn->tstream,
902                                                &ncacn_conn->remote_client_addr,
903                                                &ncacn_conn->remote_client_name,
904                                                &ncacn_conn->local_server_addr,
905                                                &ncacn_conn->local_server_name,
906                                                &session_info_transport);
907         ncacn_conn->session_info = talloc_move(ncacn_conn,
908                         &session_info_transport->session_info);
909
910         TALLOC_FREE(subreq);
911         if (ret != 0) {
912                 DBG_ERR("Failed to accept named pipe connection: %s\n",
913                         strerror(error));
914                 ncacn_terminate_connection(ncacn_conn, strerror(errno));
915                 return;
916         }
917
918         dcesrv_ncacn_accept_step2(ncacn_conn);
919 }
920
921 static void dcesrv_ncacn_accept_step2(struct dcerpc_ncacn_conn *ncacn_conn)
922 {
923         char *pipe_name = NULL;
924         uid_t uid;
925         gid_t gid;
926         int rc;
927         int sys_errno;
928         enum dcerpc_transport_t transport = dcerpc_binding_get_transport(
929                         ncacn_conn->endpoint->ep_description);
930         const char *endpoint = dcerpc_binding_get_string_option(
931                         ncacn_conn->endpoint->ep_description, "endpoint");
932         struct dcesrv_connection *dcesrv_conn = NULL;
933         NTSTATUS status;
934
935         switch (transport) {
936                 case NCACN_IP_TCP:
937                         pipe_name = tsocket_address_string(ncacn_conn->remote_client_addr,
938                                                            ncacn_conn);
939                         if (pipe_name == NULL) {
940                                 DBG_ERR("No memory\n");
941                                 ncacn_terminate_connection(ncacn_conn, "No memory");
942                                 return;
943                         }
944
945                         break;
946                 case NCALRPC:
947                         rc = getpeereid(ncacn_conn->sock, &uid, &gid);
948                         if (rc < 0) {
949                                 DEBUG(2, ("Failed to get ncalrpc connecting "
950                                           "uid - %s!\n", strerror(errno)));
951                         } else {
952                                 if (uid == sec_initial_uid()) {
953                                         TALLOC_FREE(ncacn_conn->remote_client_addr);
954
955                                         rc = tsocket_address_unix_from_path(ncacn_conn,
956                                                                             AS_SYSTEM_MAGIC_PATH_TOKEN,
957                                                                             &ncacn_conn->remote_client_addr);
958                                         if (rc < 0) {
959                                                 DBG_ERR("No memory\n");
960                                                 ncacn_terminate_connection(ncacn_conn, "No memory");
961                                                 return;
962                                         }
963
964                                         TALLOC_FREE(ncacn_conn->remote_client_name);
965                                         ncacn_conn->remote_client_name
966                                                 = tsocket_address_unix_path(ncacn_conn->remote_client_addr,
967                                                                             ncacn_conn);
968                                         if (ncacn_conn->remote_client_name == NULL) {
969                                                 DBG_ERR("No memory\n");
970                                                 ncacn_terminate_connection(ncacn_conn, "No memory");
971                                                 return;
972                                         }
973                                 }
974                         }
975
976                         FALL_THROUGH;
977                 case NCACN_NP:
978                         pipe_name = talloc_strdup(ncacn_conn, endpoint);
979                         if (pipe_name == NULL) {
980                                 DBG_ERR("No memory\n");
981                                 ncacn_terminate_connection(ncacn_conn, "No memory");
982                                 return;
983                         }
984                         break;
985                 default:
986                         DBG_ERR("unknown dcerpc transport: %u!\n", transport);
987                         ncacn_terminate_connection(ncacn_conn,
988                                         "Unknown DCE/RPC transport");
989                         return;
990         }
991
992         if (ncacn_conn->session_info == NULL) {
993                 status = make_session_info_anonymous(ncacn_conn,
994                                                      &ncacn_conn->session_info);
995                 if (!NT_STATUS_IS_OK(status)) {
996                         DBG_ERR("Failed to create anonymous session info: "
997                                 "%s\n", nt_errstr(status));
998                         ncacn_terminate_connection(ncacn_conn,
999                                 nt_errstr(status));
1000                         return;
1001                 }
1002         }
1003
1004         rc = make_server_pipes_struct(ncacn_conn,
1005                                       ncacn_conn->msg_ctx,
1006                                       pipe_name,
1007                                       transport,
1008                                       ncacn_conn->remote_client_addr,
1009                                       ncacn_conn->local_server_addr,
1010                                       &ncacn_conn->p,
1011                                       &sys_errno);
1012         if (rc < 0) {
1013                 DBG_ERR("Failed to create pipe struct: %s",
1014                         strerror(sys_errno));
1015                 ncacn_terminate_connection(ncacn_conn, strerror(sys_errno));
1016                 return;
1017         }
1018
1019         /*
1020          * This fills in dcesrv_conn->endpoint with the endpoint
1021          * associated with the socket.  From this point on we know
1022          * which (group of) services we are handling, but not the
1023          * specific interface.
1024          */
1025         status = dcesrv_endpoint_connect(ncacn_conn->dce_ctx,
1026                                          ncacn_conn,
1027                                          ncacn_conn->endpoint,
1028                                          ncacn_conn->session_info,
1029                                          ncacn_conn->ev_ctx,
1030                                          DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
1031                                          &dcesrv_conn);
1032         if (!NT_STATUS_IS_OK(status)) {
1033                 DBG_ERR("Failed to connect to endpoint: %s\n",
1034                         nt_errstr(status));
1035                 ncacn_terminate_connection(ncacn_conn, nt_errstr(status));
1036                 return;
1037         }
1038         talloc_set_destructor(dcesrv_conn, dcesrv_connection_destructor);
1039
1040         dcesrv_conn->transport.private_data = ncacn_conn;
1041         dcesrv_conn->transport.report_output_data =
1042                 dcesrv_sock_report_output_data;
1043         dcesrv_conn->transport.terminate_connection =
1044                 dcesrv_transport_terminate_connection;
1045         dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn,
1046                                                       "dcesrv send queue");
1047         if (dcesrv_conn->send_queue == NULL) {
1048                 status = NT_STATUS_NO_MEMORY;
1049                 DBG_ERR("Failed to create send queue: %s\n",
1050                         nt_errstr(status));
1051                 ncacn_terminate_connection(ncacn_conn, nt_errstr(status));
1052                 return;
1053         }
1054
1055         dcesrv_conn->stream = talloc_move(dcesrv_conn, &ncacn_conn->tstream);
1056         dcesrv_conn->local_address = ncacn_conn->local_server_addr;
1057         dcesrv_conn->remote_address = ncacn_conn->remote_client_addr;
1058         status = dcesrv_connection_loop_start(dcesrv_conn);
1059         if (!NT_STATUS_IS_OK(status)) {
1060                 DBG_ERR("Failed to start dcesrv_connection loop: %s\n",
1061                                 nt_errstr(status));
1062                 ncacn_terminate_connection(ncacn_conn, nt_errstr(status));
1063         }
1064         DBG_DEBUG("dcerpc_ncacn_accept done\n");
1065
1066         return;
1067 }
1068
1069 NTSTATUS dcesrv_auth_gensec_prepare(TALLOC_CTX *mem_ctx,
1070                                     struct dcesrv_call_state *call,
1071                                     struct gensec_security **out)
1072 {
1073         struct gensec_security *gensec = NULL;
1074         NTSTATUS status;
1075
1076         if (out == NULL) {
1077                 return NT_STATUS_INVALID_PARAMETER;
1078         }
1079
1080         status = auth_generic_prepare(mem_ctx,
1081                                       call->conn->remote_address,
1082                                       call->conn->local_address,
1083                                       "DCE/RPC",
1084                                       &gensec);
1085         if (!NT_STATUS_IS_OK(status)) {
1086                 DBG_ERR("Failed to prepare gensec: %s\n", nt_errstr(status));
1087                 return status;
1088         }
1089
1090         *out = gensec;
1091
1092         return NT_STATUS_OK;
1093 }
1094
1095 void dcesrv_log_successful_authz(struct dcesrv_call_state *call)
1096 {
1097         TALLOC_CTX *frame = talloc_stackframe();
1098         struct auth4_context *auth4_context = NULL;
1099         struct dcesrv_auth *auth = call->auth_state;
1100         enum dcerpc_transport_t transport = dcerpc_binding_get_transport(
1101                         call->conn->endpoint->ep_description);
1102         const char *auth_type = derpc_transport_string_by_transport(transport);
1103         const char *transport_protection = AUTHZ_TRANSPORT_PROTECTION_NONE;
1104         NTSTATUS status;
1105
1106         if (frame == NULL) {
1107                 DBG_ERR("No memory");
1108                 return;
1109         }
1110
1111         if (transport == NCACN_NP) {
1112                 transport_protection = AUTHZ_TRANSPORT_PROTECTION_SMB;
1113         }
1114
1115         become_root();
1116         status = make_auth4_context(frame, &auth4_context);
1117         unbecome_root();
1118         if (!NT_STATUS_IS_OK(status)) {
1119                 DBG_ERR("Unable to make auth context for authz log.\n");
1120                 TALLOC_FREE(frame);
1121                 return;
1122         }
1123
1124         /*
1125          * Log the authorization to this RPC interface.  This
1126          * covered ncacn_np pass-through auth, and anonymous
1127          * DCE/RPC (eg epmapper, netlogon etc)
1128          */
1129         log_successful_authz_event(auth4_context->msg_ctx,
1130                                    auth4_context->lp_ctx,
1131                                    call->conn->remote_address,
1132                                    call->conn->local_address,
1133                                    "DCE/RPC",
1134                                    auth_type,
1135                                    transport_protection,
1136                                    auth->session_info);
1137
1138         auth->auth_audited = true;
1139
1140         TALLOC_FREE(frame);
1141 }
1142
1143 static NTSTATUS dcesrv_assoc_group_new(struct dcesrv_call_state *call,
1144                                        uint32_t assoc_group_id)
1145 {
1146         struct dcesrv_connection *conn = call->conn;
1147         struct dcesrv_context *dce_ctx = conn->dce_ctx;
1148         const struct dcesrv_endpoint *endpoint = conn->endpoint;
1149         enum dcerpc_transport_t transport =
1150                 dcerpc_binding_get_transport(endpoint->ep_description);
1151         struct dcesrv_assoc_group *assoc_group = NULL;
1152
1153         assoc_group = talloc_zero(conn, struct dcesrv_assoc_group);
1154         if (assoc_group == NULL) {
1155                 return NT_STATUS_NO_MEMORY;
1156         }
1157
1158         assoc_group->transport = transport;
1159         assoc_group->id = assoc_group_id;
1160         assoc_group->dce_ctx = dce_ctx;
1161
1162         call->conn->assoc_group = assoc_group;
1163
1164         return NT_STATUS_OK;
1165 }
1166
1167 NTSTATUS dcesrv_assoc_group_find(struct dcesrv_call_state *call)
1168 {
1169         uint32_t assoc_group_id = call->pkt.u.bind.assoc_group_id;
1170
1171         /* If not requested by client create a new association group */
1172         if (assoc_group_id == 0) {
1173                 assoc_group_id = 0x53F0;
1174         }
1175
1176         return dcesrv_assoc_group_new(call, assoc_group_id);
1177 }
1178
1179 void dcesrv_transport_terminate_connection(struct dcesrv_connection *dce_conn,
1180                                            const char *reason)
1181 {
1182        struct dcerpc_ncacn_conn *ncacn_conn = talloc_get_type_abort(
1183                        dce_conn->transport.private_data,
1184                        struct dcerpc_ncacn_conn);
1185
1186        ncacn_terminate_connection(ncacn_conn, reason);
1187 }
1188
1189 static void ncacn_terminate_connection(struct dcerpc_ncacn_conn *conn,
1190                                        const char *reason)
1191 {
1192        if (reason == NULL) {
1193                reason = "Unknown reason";
1194        }
1195
1196        DBG_NOTICE("Terminating connection - '%s'\n", reason);
1197
1198        talloc_free(conn);
1199 }
1200
1201 NTSTATUS dcesrv_endpoint_by_ncacn_np_name(struct dcesrv_context *dce_ctx,
1202                                           const char *pipe_name,
1203                                           struct dcesrv_endpoint **out)
1204 {
1205         struct dcesrv_endpoint *e = NULL;
1206
1207         for (e = dce_ctx->endpoint_list; e; e = e->next) {
1208                 enum dcerpc_transport_t transport =
1209                         dcerpc_binding_get_transport(e->ep_description);
1210                 const char *endpoint = NULL;
1211
1212                 if (transport != NCACN_NP) {
1213                         continue;
1214                 }
1215
1216                 endpoint = dcerpc_binding_get_string_option(e->ep_description,
1217                                                             "endpoint");
1218                 if (endpoint == NULL) {
1219                         continue;
1220                 }
1221
1222                 if (strncmp(endpoint, "\\pipe\\", 6) == 0) {
1223                         endpoint += 6;
1224                 }
1225
1226                 if (strequal(endpoint, pipe_name)) {
1227                         *out = e;
1228                         return NT_STATUS_OK;
1229                 }
1230         }
1231
1232         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1233 }
1234
1235 struct pipes_struct *dcesrv_get_pipes_struct(struct dcesrv_connection *conn)
1236 {
1237         struct dcerpc_ncacn_conn *ncacn_conn = talloc_get_type_abort(
1238                         conn->transport.private_data,
1239                         struct dcerpc_ncacn_conn);
1240
1241         return ncacn_conn->p;
1242 }
1243
1244 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */