s3-librpc: Leave the epm registration connection open.
[ddiss/samba.git] / source3 / rpc_server / rpc_ep_setup.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *
4  *  SMBD RPC service callbacks
5  *
6  *  Copyright (c) 2011      Andreas Schneider <asn@samba.org>
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
24 #include "../librpc/gen_ndr/srv_epmapper.h"
25 #include "../librpc/gen_ndr/srv_srvsvc.h"
26 #include "../librpc/gen_ndr/srv_winreg.h"
27 #include "../librpc/gen_ndr/srv_dfs.h"
28 #include "../librpc/gen_ndr/srv_dssetup.h"
29 #include "../librpc/gen_ndr/srv_echo.h"
30 #include "../librpc/gen_ndr/srv_eventlog.h"
31 #include "../librpc/gen_ndr/srv_initshutdown.h"
32 #include "../librpc/gen_ndr/srv_lsa.h"
33 #include "../librpc/gen_ndr/srv_netlogon.h"
34 #include "../librpc/gen_ndr/srv_ntsvcs.h"
35 #include "../librpc/gen_ndr/srv_samr.h"
36 #include "../librpc/gen_ndr/srv_spoolss.h"
37 #include "../librpc/gen_ndr/srv_svcctl.h"
38 #include "../librpc/gen_ndr/srv_wkssvc.h"
39
40 #include "printing/nt_printing_migrate.h"
41 #include "rpc_server/eventlog/srv_eventlog_reg.h"
42 #include "rpc_server/svcctl/srv_svcctl_reg.h"
43
44 #include "librpc/rpc/dcerpc_ep.h"
45
46 #include "rpc_server/rpc_ep_setup.h"
47 #include "rpc_server/rpc_server.h"
48 #include "rpc_server/epmapper/srv_epmapper.h"
49
50 struct dcesrv_ep_context {
51         struct tevent_context *ev_ctx;
52         struct messaging_context *msg_ctx;
53 };
54
55 static uint16_t _open_sockets(struct tevent_context *ev_ctx,
56                               struct messaging_context *msg_ctx,
57                               struct ndr_syntax_id syntax_id,
58                               uint16_t port)
59 {
60         uint32_t num_ifs = iface_count();
61         uint32_t i;
62         uint16_t p = 0;
63
64         if (lp_interfaces() && lp_bind_interfaces_only()) {
65                 /*
66                  * We have been given an interfaces line, and been told to only
67                  * bind to those interfaces. Create a socket per interface and
68                  * bind to only these.
69                  */
70
71                 /* Now open a listen socket for each of the interfaces. */
72                 for(i = 0; i < num_ifs; i++) {
73                         const struct sockaddr_storage *ifss =
74                                         iface_n_sockaddr_storage(i);
75
76                         p = setup_dcerpc_ncacn_tcpip_socket(ev_ctx,
77                                                             msg_ctx,
78                                                             syntax_id,
79                                                             ifss,
80                                                             port);
81                         if (p == 0) {
82                                 return 0;
83                         }
84                         port = p;
85                 }
86         } else {
87                 const char *sock_addr = lp_socket_address();
88                 const char *sock_ptr;
89                 char *sock_tok;
90
91                 if (strequal(sock_addr, "0.0.0.0") ||
92                     strequal(sock_addr, "::")) {
93 #if HAVE_IPV6
94                         sock_addr = "::";
95 #else
96                         sock_addr = "0.0.0.0";
97 #endif
98                 }
99
100                 for (sock_ptr = sock_addr;
101                      next_token_talloc(talloc_tos(), &sock_ptr, &sock_tok, " \t,");
102                     ) {
103                         struct sockaddr_storage ss;
104
105                         /* open an incoming socket */
106                         if (!interpret_string_addr(&ss,
107                                                    sock_tok,
108                                                    AI_NUMERICHOST|AI_PASSIVE)) {
109                                 continue;
110                         }
111
112                         p = setup_dcerpc_ncacn_tcpip_socket(ev_ctx,
113                                                             msg_ctx,
114                                                             syntax_id,
115                                                             &ss,
116                                                             port);
117                         if (p == 0) {
118                                 return 0;
119                         }
120                         port = p;
121                 }
122         }
123
124         return p;
125 }
126
127 static NTSTATUS _rpc_ep_unregister(const struct ndr_interface_table *iface)
128 {
129         struct dcerpc_binding_vector *v = NULL;
130         NTSTATUS status;
131
132         status = dcerpc_binding_vector_create(talloc_tos(),
133                                               iface,
134                                               0,
135                                               NULL,
136                                               &v);
137         if (!NT_STATUS_IS_OK(status)) {
138                 return status;
139         }
140
141         status = dcerpc_ep_unregister(iface,
142                                       v,
143                                       &iface->syntax_id.uuid);
144         if (!NT_STATUS_IS_OK(status)) {
145                 return status;
146         }
147
148         return status;
149 }
150
151 static void rpc_ep_setup_register_loop(struct tevent_req *subreq);
152 static NTSTATUS rpc_ep_setup_try_register(TALLOC_CTX *mem_ctx,
153                                           struct tevent_context *ev_ctx,
154                                           struct messaging_context *msg_ctx,
155                                           const struct ndr_interface_table *iface,
156                                           const char *name,
157                                           uint16_t port,
158                                           struct dcerpc_binding_handle **pbh);
159
160 struct rpc_ep_regsiter_state {
161         struct dcerpc_binding_handle *h;
162
163         struct tevent_context *ev_ctx;
164         struct messaging_context *msg_ctx;
165
166         const struct ndr_interface_table *iface;
167
168         const char *ncalrpc;
169         uint16_t port;
170
171         uint32_t wait_time;
172 };
173
174 static NTSTATUS rpc_ep_setup_register(struct tevent_context *ev_ctx,
175                                       struct messaging_context *msg_ctx,
176                                       const struct ndr_interface_table *iface,
177                                       const char *ncalrpc,
178                                       uint16_t port)
179 {
180         struct rpc_ep_regsiter_state *state;
181         struct tevent_req *req;
182
183         state = talloc(ev_ctx, struct rpc_ep_regsiter_state);
184         if (state == NULL) {
185                 return NT_STATUS_NO_MEMORY;
186         }
187
188         state->wait_time = 1;
189         state->ev_ctx = ev_ctx;
190         state->msg_ctx = msg_ctx;
191         state->iface = iface;
192         state->ncalrpc = talloc_strdup(state, ncalrpc);
193         state->port = port;
194
195         req = tevent_wakeup_send(state, ev_ctx, timeval_current_ofs(1, 0));
196         if (tevent_req_nomem(state, req)) {
197                 talloc_free(state);
198                 return NT_STATUS_NO_MEMORY;
199         }
200
201         tevent_req_set_callback(req, rpc_ep_setup_register_loop, state);
202
203         return NT_STATUS_OK;
204 }
205
206 static void rpc_ep_setup_register_loop(struct tevent_req *req)
207 {
208         struct rpc_ep_regsiter_state *state =
209                 tevent_req_callback_data(req, struct rpc_ep_regsiter_state);
210         NTSTATUS status;
211         bool ok;
212
213         ok = tevent_wakeup_recv(req);
214         TALLOC_FREE(req);
215         if (!ok) {
216                 talloc_free(state);
217                 return;
218         }
219
220         status = rpc_ep_setup_try_register(state,
221                                            state->ev_ctx,
222                                            state->msg_ctx,
223                                            state->iface,
224                                            state->ncalrpc,
225                                            state->port,
226                                            &state->h);
227         if (NT_STATUS_IS_OK(status)) {
228                 talloc_free(state);
229                 return;
230         }
231
232         state->wait_time = state->wait_time * 2;
233         if (state->wait_time > 16) {
234                 talloc_free(state);
235                 return;
236         }
237
238         req = tevent_wakeup_send(state,
239                                  state->ev_ctx,
240                                  timeval_current_ofs(state->wait_time, 0));
241         if (tevent_req_nomem(state, req)) {
242                 talloc_free(state);
243                 return;
244         }
245
246         tevent_req_set_callback(req, rpc_ep_setup_register_loop, state);
247         return;
248 }
249
250 static NTSTATUS rpc_ep_setup_try_register(TALLOC_CTX *mem_ctx,
251                                           struct tevent_context *ev_ctx,
252                                           struct messaging_context *msg_ctx,
253                                           const struct ndr_interface_table *iface,
254                                           const char *name,
255                                           uint16_t port,
256                                           struct dcerpc_binding_handle **pbh)
257 {
258         struct dcerpc_binding_vector *v = NULL;
259         NTSTATUS status;
260
261         status = dcerpc_binding_vector_create(mem_ctx,
262                                               iface,
263                                               port,
264                                               name,
265                                               &v);
266         if (!NT_STATUS_IS_OK(status)) {
267                 return status;
268         }
269
270         status = dcerpc_ep_register(mem_ctx,
271                                     iface,
272                                     v,
273                                     &iface->syntax_id.uuid,
274                                     name,
275                                     pbh);
276         talloc_free(v);
277         if (!NT_STATUS_IS_OK(status)) {
278                 return status;
279         }
280
281         return status;
282 }
283
284 static bool epmapper_init_cb(void *ptr)
285 {
286         struct dcesrv_ep_context *ep_ctx =
287                 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
288         uint16_t port;
289
290         port = _open_sockets(ep_ctx->ev_ctx,
291                              ep_ctx->msg_ctx,
292                              ndr_table_epmapper.syntax_id,
293                              135);
294         if (port == 135) {
295                 return true;
296         }
297
298         return false;
299 }
300
301 static bool epmapper_shutdown_cb(void *ptr)
302 {
303         srv_epmapper_cleanup();
304
305         return true;
306 }
307
308 static bool winreg_init_cb(void *ptr)
309 {
310         struct dcesrv_ep_context *ep_ctx =
311                 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
312         struct ndr_syntax_id abstract_syntax = ndr_table_winreg.syntax_id;
313         const char *pipe_name = "winreg";
314         const char *rpcsrv_type;
315         uint16_t port;
316
317         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
318                                            "rpc_server",
319                                            "epmapper",
320                                            "none");
321
322         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
323             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
324                 NTSTATUS status;
325                 bool ok;
326
327                 ok = setup_dcerpc_ncalrpc_socket(ep_ctx->ev_ctx,
328                                                  ep_ctx->msg_ctx,
329                                                  abstract_syntax,
330                                                  pipe_name);
331                 if (!ok) {
332                         return false;
333                 }
334                 port = _open_sockets(ep_ctx->ev_ctx,
335                                      ep_ctx->msg_ctx,
336                                      abstract_syntax,
337                                      0);
338                 if (port == 0) {
339                         return false;
340                 }
341
342                 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
343                                                 ep_ctx->msg_ctx,
344                                                 &ndr_table_winreg,
345                                                 pipe_name,
346                                                 port);
347                 if (!NT_STATUS_IS_OK(status)) {
348                         return false;
349                 }
350         }
351
352         return true;
353 }
354
355 static bool winreg_shutdown_cb(void *ptr)
356 {
357         const char *rpcsrv_type;
358
359         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
360                                            "rpc_server",
361                                            "epmapper",
362                                            "none");
363
364         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
365             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
366                 NTSTATUS status;
367
368                 status = _rpc_ep_unregister(&ndr_table_winreg);
369                 if (!NT_STATUS_IS_OK(status)) {
370                         return false;
371                 }
372         }
373
374         return true;
375 }
376
377 static bool srvsvc_init_cb(void *ptr)
378 {
379         struct dcesrv_ep_context *ep_ctx =
380                 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
381         struct ndr_syntax_id abstract_syntax = ndr_table_srvsvc.syntax_id;
382         const char *pipe_name = "srvsvc";
383         const char *rpcsrv_type;
384         uint16_t port;
385
386         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
387                                            "rpc_server",
388                                            "epmapper",
389                                            "none");
390
391         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
392             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
393                 NTSTATUS status;
394                 bool ok;
395
396                 ok = setup_dcerpc_ncalrpc_socket(ep_ctx->ev_ctx,
397                                                  ep_ctx->msg_ctx,
398                                                  abstract_syntax,
399                                                  pipe_name);
400                 if (!ok) {
401                         return false;
402                 }
403
404                 port = _open_sockets(ep_ctx->ev_ctx,
405                                      ep_ctx->msg_ctx,
406                                      abstract_syntax,
407                                      0);
408                 if (port == 0) {
409                         return false;
410                 }
411
412                 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
413                                           ep_ctx->msg_ctx,
414                                           &ndr_table_srvsvc,
415                                           pipe_name,
416                                           port);
417                 if (!NT_STATUS_IS_OK(status)) {
418                         return false;
419                 }
420         }
421
422         return true;
423 }
424
425 static bool srvsvc_shutdown_cb(void *ptr)
426 {
427         const char *rpcsrv_type;
428
429         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
430                                            "rpc_server",
431                                            "epmapper",
432                                            "none");
433
434         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
435             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
436                 NTSTATUS status;
437
438                 status =_rpc_ep_unregister(&ndr_table_srvsvc);
439                 if (!NT_STATUS_IS_OK(status)) {
440                         return false;
441                 }
442         }
443
444         return true;
445 }
446
447 static bool lsarpc_init_cb(void *ptr)
448 {
449         struct dcesrv_ep_context *ep_ctx =
450                 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
451         struct ndr_syntax_id abstract_syntax = ndr_table_lsarpc.syntax_id;
452         const char *pipe_name = "lsarpc";
453         const char *rpcsrv_type;
454         uint16_t port;
455
456         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
457                                            "rpc_server",
458                                            "epmapper",
459                                            "none");
460
461         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
462             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
463                 NTSTATUS status;
464                 bool ok;
465
466                 ok = setup_dcerpc_ncalrpc_socket(ep_ctx->ev_ctx,
467                                                  ep_ctx->msg_ctx,
468                                                  abstract_syntax,
469                                                  pipe_name);
470                 if (!ok) {
471                         return false;
472                 }
473
474                 port = _open_sockets(ep_ctx->ev_ctx,
475                                      ep_ctx->msg_ctx,
476                                      abstract_syntax,
477                                      0);
478                 if (port == 0) {
479                         return false;
480                 }
481
482                 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
483                                           ep_ctx->msg_ctx,
484                                           &ndr_table_lsarpc,
485                                           pipe_name,
486                                           port);
487                 if (!NT_STATUS_IS_OK(status)) {
488                         return false;
489                 }
490         }
491
492         return true;
493 }
494
495 static bool lsarpc_shutdown_cb(void *ptr)
496 {
497         const char *rpcsrv_type;
498
499         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
500                                            "rpc_server",
501                                            "epmapper",
502                                            "none");
503
504         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
505             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
506                 NTSTATUS status;
507
508                 status = _rpc_ep_unregister(&ndr_table_lsarpc);
509                 if (!NT_STATUS_IS_OK(status)) {
510                         return false;
511                 }
512         }
513
514         return true;
515 }
516
517 static bool samr_init_cb(void *ptr)
518 {
519         struct dcesrv_ep_context *ep_ctx =
520                 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
521         struct ndr_syntax_id abstract_syntax = ndr_table_samr.syntax_id;
522         const char *pipe_name = "samr";
523         const char *rpcsrv_type;
524         uint16_t port;
525
526         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
527                                            "rpc_server",
528                                            "epmapper",
529                                            "none");
530
531         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
532             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
533                 NTSTATUS status;
534                 bool ok;
535
536                 ok = setup_dcerpc_ncalrpc_socket(ep_ctx->ev_ctx,
537                                                  ep_ctx->msg_ctx,
538                                                  abstract_syntax,
539                                                  pipe_name);
540                 if (!ok) {
541                         return false;
542                 }
543
544                 port = _open_sockets(ep_ctx->ev_ctx,
545                                      ep_ctx->msg_ctx,
546                                      abstract_syntax,
547                                      0);
548                 if (port == 0) {
549                         return false;
550                 }
551
552                 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
553                                           ep_ctx->msg_ctx,
554                                           &ndr_table_samr,
555                                           pipe_name,
556                                           port);
557                 if (!NT_STATUS_IS_OK(status)) {
558                         return false;
559                 }
560         }
561
562         return true;
563 }
564
565 static bool samr_shutdown_cb(void *ptr)
566 {
567         const char *rpcsrv_type;
568
569         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
570                                            "rpc_server",
571                                            "epmapper",
572                                            "none");
573
574         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
575             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
576                 NTSTATUS status;
577
578                 status = _rpc_ep_unregister(&ndr_table_samr);
579                 if (!NT_STATUS_IS_OK(status)) {
580                         return false;
581                 }
582         }
583
584         return true;
585 }
586
587 static bool netlogon_init_cb(void *ptr)
588 {
589         struct dcesrv_ep_context *ep_ctx =
590                 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
591         struct ndr_syntax_id abstract_syntax = ndr_table_netlogon.syntax_id;
592         const char *pipe_name = "netlogon";
593         const char *rpcsrv_type;
594         uint16_t port;
595
596         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
597                                            "rpc_server",
598                                            "epmapper",
599                                            "none");
600
601         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
602             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
603                 NTSTATUS status;
604                 bool ok;
605
606                 ok = setup_dcerpc_ncalrpc_socket(ep_ctx->ev_ctx,
607                                                  ep_ctx->msg_ctx,
608                                                  abstract_syntax,
609                                                  pipe_name);
610                 if (!ok) {
611                         return false;
612                 }
613
614                 port = _open_sockets(ep_ctx->ev_ctx,
615                                      ep_ctx->msg_ctx,
616                                      abstract_syntax,
617                                      0);
618                 if (port == 0) {
619                         return false;
620                 }
621
622                 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
623                                           ep_ctx->msg_ctx,
624                                           &ndr_table_netlogon,
625                                           pipe_name,
626                                           port);
627                 if (!NT_STATUS_IS_OK(status)) {
628                         return false;
629                 }
630         }
631
632         return true;
633 }
634
635 static bool netlogon_shutdown_cb(void *ptr)
636 {
637         const char *rpcsrv_type;
638
639         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
640                                            "rpc_server",
641                                            "epmapper",
642                                            "none");
643
644         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
645             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
646                 NTSTATUS status;
647
648                 status = _rpc_ep_unregister(&ndr_table_netlogon);
649                 if (!NT_STATUS_IS_OK(status)) {
650                         return false;
651                 }
652         }
653
654         return true;
655 }
656
657 static bool spoolss_init_cb(void *ptr)
658 {
659         struct dcesrv_ep_context *ep_ctx =
660                 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
661         const char *rpcsrv_type;
662         bool ok;
663
664         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
665                                            "rpc_server",
666                                            "epmapper",
667                                            "none");
668
669         /*
670          * Migrate the printers first.
671          */
672         ok = nt_printing_tdb_migrate(ep_ctx->msg_ctx);
673         if (!ok) {
674                 return false;
675         }
676
677         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
678             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
679                 NTSTATUS status;
680
681                 status =rpc_ep_setup_register(ep_ctx->ev_ctx,
682                                          ep_ctx->msg_ctx,
683                                          &ndr_table_spoolss,
684                                          "spoolss",
685                                          0);
686                 if (!NT_STATUS_IS_OK(status)) {
687                         return false;
688                 }
689         }
690
691         return true;
692 }
693
694 static bool spoolss_shutdown_cb(void *ptr)
695 {
696         const char *rpcsrv_type;
697
698         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
699                                            "rpc_server",
700                                            "epmapper",
701                                            "none");
702
703         srv_spoolss_cleanup();
704
705         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
706             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
707                 NTSTATUS status;
708
709                 status = _rpc_ep_unregister(&ndr_table_spoolss);
710                 if (!NT_STATUS_IS_OK(status)) {
711                         return false;
712                 }
713         }
714
715         return true;
716 }
717
718 static bool svcctl_init_cb(void *ptr)
719 {
720         struct dcesrv_ep_context *ep_ctx =
721                 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
722         const char *rpcsrv_type;
723         bool ok;
724
725         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
726                                            "rpc_server",
727                                            "epmapper",
728                                            "none");
729
730         ok = svcctl_init_winreg(ep_ctx->msg_ctx);
731         if (!ok) {
732                 return false;
733         }
734
735         /* initialize the control hooks */
736         init_service_op_table();
737
738         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
739             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
740                 NTSTATUS status;
741
742                 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
743                                           ep_ctx->msg_ctx,
744                                           &ndr_table_svcctl,
745                                           "svcctl",
746                                           0);
747                 if (!NT_STATUS_IS_OK(status)) {
748                         return false;
749                 }
750         }
751
752         return true;
753 }
754
755 static bool svcctl_shutdown_cb(void *ptr)
756 {
757         const char *rpcsrv_type;
758
759         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
760                                            "rpc_server",
761                                            "epmapper",
762                                            "none");
763         shutdown_service_op_table();
764
765         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
766             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
767                 NTSTATUS status;
768
769                 status = _rpc_ep_unregister(&ndr_table_svcctl);
770                 if (!NT_STATUS_IS_OK(status)) {
771                         return false;
772                 }
773         }
774
775         return true;
776 }
777
778 static bool ntsvcs_init_cb(void *ptr)
779 {
780         struct dcesrv_ep_context *ep_ctx =
781                 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
782         const char *rpcsrv_type;
783
784         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
785                                            "rpc_server",
786                                            "epmapper",
787                                            "none");
788
789         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
790             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
791                 NTSTATUS status;
792
793                 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
794                                           ep_ctx->msg_ctx,
795                                           &ndr_table_ntsvcs,
796                                           "ntsvcs",
797                                           0);
798                 if (!NT_STATUS_IS_OK(status)) {
799                         return false;
800                 }
801         }
802
803         return true;
804 }
805
806 static bool ntsvcs_shutdown_cb(void *ptr)
807 {
808         const char *rpcsrv_type;
809
810         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
811                                            "rpc_server",
812                                            "epmapper",
813                                            "none");
814
815         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
816             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
817                 NTSTATUS status;
818
819                 status = _rpc_ep_unregister(&ndr_table_ntsvcs);
820                 if (!NT_STATUS_IS_OK(status)) {
821                         return false;
822                 }
823         }
824
825         return true;
826 }
827
828 static bool eventlog_init_cb(void *ptr)
829 {
830         struct dcesrv_ep_context *ep_ctx =
831                 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
832         const char *rpcsrv_type;
833         bool ok;
834
835         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
836                                            "rpc_server",
837                                            "epmapper",
838                                            "none");
839
840         ok = eventlog_init_winreg(ep_ctx->msg_ctx);
841         if (!ok) {
842                 return false;
843         }
844
845         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
846             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
847                 NTSTATUS status;
848
849                 status =rpc_ep_setup_register(ep_ctx->ev_ctx,
850                                          ep_ctx->msg_ctx,
851                                          &ndr_table_eventlog,
852                                          "eventlog",
853                                          0);
854                 if (!NT_STATUS_IS_OK(status)) {
855                         return false;
856                 }
857         }
858
859         return true;
860 }
861
862 static bool eventlog_shutdown_cb(void *ptr)
863 {
864         const char *rpcsrv_type;
865
866         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
867                                            "rpc_server",
868                                            "epmapper",
869                                            "none");
870
871         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
872             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
873                 NTSTATUS status;
874
875                 status = _rpc_ep_unregister(&ndr_table_eventlog);
876                 if (!NT_STATUS_IS_OK(status)) {
877                         return false;
878                 }
879         }
880
881         return true;
882 }
883
884 static bool initshutdown_init_cb(void *ptr)
885 {
886         struct dcesrv_ep_context *ep_ctx =
887                 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
888         const char *rpcsrv_type;
889
890         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
891                                            "rpc_server",
892                                            "epmapper",
893                                            "none");
894
895         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
896             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
897                 NTSTATUS status;
898
899                 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
900                                           ep_ctx->msg_ctx,
901                                           &ndr_table_initshutdown,
902                                           "initshutdown",
903                                           0);
904                 if (!NT_STATUS_IS_OK(status)) {
905                         return false;
906                 }
907         }
908
909         return true;
910 }
911
912 static bool initshutdown_shutdown_cb(void *ptr)
913 {
914         const char *rpcsrv_type;
915
916         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
917                                            "rpc_server",
918                                            "epmapper",
919                                            "none");
920
921         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
922             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
923                 NTSTATUS status;
924
925                 status = _rpc_ep_unregister(&ndr_table_initshutdown);
926                 if (!NT_STATUS_IS_OK(status)) {
927                         return false;
928                 }
929         }
930
931         return true;
932 }
933
934 #ifdef DEVELOPER
935 static bool rpcecho_init_cb(void *ptr) {
936         struct dcesrv_ep_context *ep_ctx =
937                 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
938         const char *rpcsrv_type;
939         uint16_t port;
940
941         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
942                                            "rpc_server",
943                                            "epmapper",
944                                            "none");
945
946         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
947             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
948                 NTSTATUS status;
949
950                 port = _open_sockets(ep_ctx->ev_ctx,
951                                      ep_ctx->msg_ctx,
952                                      ndr_table_rpcecho.syntax_id,
953                                      0);
954                 if (port == 0) {
955                         return false;
956                 }
957
958                 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
959                                           ep_ctx->msg_ctx,
960                                           &ndr_table_rpcecho,
961                                           "rpcecho",
962                                           port);
963                 if (!NT_STATUS_IS_OK(status)) {
964                         return false;
965                 }
966         }
967
968         return true;
969 }
970
971 static bool rpcecho_shutdown_cb(void *ptr)
972 {
973         const char *rpcsrv_type;
974
975         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
976                                            "rpc_server",
977                                            "epmapper",
978                                            "none");
979
980         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
981             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
982                 NTSTATUS status;
983
984                 status = _rpc_ep_unregister(&ndr_table_rpcecho);
985                 if (!NT_STATUS_IS_OK(status)) {
986                         return false;
987                 }
988         }
989
990         return true;
991 }
992 #endif
993
994 static bool netdfs_init_cb(void *ptr)
995 {
996         struct dcesrv_ep_context *ep_ctx =
997                 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
998         struct ndr_syntax_id abstract_syntax = ndr_table_netdfs.syntax_id;
999         const char *pipe_name = "netdfs";
1000         const char *rpcsrv_type;
1001         uint16_t port;
1002
1003         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
1004                                            "rpc_server",
1005                                            "epmapper",
1006                                            "none");
1007         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
1008             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
1009                 NTSTATUS status;
1010                 bool ok;
1011
1012                 ok = setup_dcerpc_ncalrpc_socket(ep_ctx->ev_ctx,
1013                                                  ep_ctx->msg_ctx,
1014                                                  abstract_syntax,
1015                                                  pipe_name);
1016                 if (!ok) {
1017                         return false;
1018                 }
1019
1020                 port = _open_sockets(ep_ctx->ev_ctx,
1021                                      ep_ctx->msg_ctx,
1022                                      abstract_syntax,
1023                                      0);
1024                 if (port == 0) {
1025                         return false;
1026                 }
1027
1028                 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
1029                                           ep_ctx->msg_ctx,
1030                                           &ndr_table_netdfs,
1031                                           pipe_name,
1032                                           port);
1033                 if (!NT_STATUS_IS_OK(status)) {
1034                         return false;
1035                 }
1036         }
1037
1038         return true;
1039 }
1040
1041 static bool netdfs_shutdown_cb(void *ptr) {
1042         const char *rpcsrv_type;
1043
1044         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
1045                                            "rpc_server",
1046                                            "epmapper",
1047                                            "none");
1048
1049         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
1050             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
1051                 NTSTATUS status;
1052
1053                 status = _rpc_ep_unregister(&ndr_table_netdfs);
1054                 if (!NT_STATUS_IS_OK(status)) {
1055                         return false;
1056                 }
1057         }
1058
1059         return true;
1060 }
1061
1062 static bool dssetup_init_cb(void *ptr)
1063 {
1064         struct dcesrv_ep_context *ep_ctx =
1065                 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
1066         struct ndr_syntax_id abstract_syntax = ndr_table_dssetup.syntax_id;
1067         const char *pipe_name = "dssetup";
1068         const char *rpcsrv_type;
1069         uint16_t port;
1070
1071         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
1072                                            "rpc_server",
1073                                            "epmapper",
1074                                            "none");
1075
1076         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
1077             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
1078                 NTSTATUS status;
1079                 bool ok;
1080
1081                 ok = setup_dcerpc_ncalrpc_socket(ep_ctx->ev_ctx,
1082                                                  ep_ctx->msg_ctx,
1083                                                  abstract_syntax,
1084                                                  pipe_name);
1085                 if (!ok) {
1086                         return false;
1087                 }
1088
1089                 port = _open_sockets(ep_ctx->ev_ctx,
1090                                      ep_ctx->msg_ctx,
1091                                      abstract_syntax,
1092                                      0);
1093                 if (port == 0) {
1094                         return false;
1095                 }
1096
1097                 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
1098                                           ep_ctx->msg_ctx,
1099                                           &ndr_table_dssetup,
1100                                           "dssetup",
1101                                           port);
1102                 if (!NT_STATUS_IS_OK(status)) {
1103                         return false;
1104                 }
1105         }
1106
1107         return true;
1108 }
1109
1110 static bool dssetup_shutdown_cb(void *ptr) {
1111         const char *rpcsrv_type;
1112
1113         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
1114                                            "rpc_server",
1115                                            "epmapper",
1116                                            "none");
1117
1118         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
1119             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
1120                 NTSTATUS status;
1121
1122                 status = _rpc_ep_unregister(&ndr_table_dssetup);
1123                 if (!NT_STATUS_IS_OK(status)) {
1124                         return false;
1125                 }
1126         }
1127
1128         return true;
1129 }
1130
1131 static bool wkssvc_init_cb(void *ptr)
1132 {
1133         struct dcesrv_ep_context *ep_ctx =
1134                 talloc_get_type_abort(ptr, struct dcesrv_ep_context);
1135         struct ndr_syntax_id abstract_syntax = ndr_table_wkssvc.syntax_id;
1136         const char *pipe_name = "wkssvc";
1137         const char *rpcsrv_type;
1138         uint16_t port;
1139
1140         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
1141                                            "rpc_server",
1142                                            "epmapper",
1143                                            "none");
1144         if (StrCaseCmp(rpcsrv_type, "embedded") == 0 ||
1145             StrCaseCmp(rpcsrv_type, "daemon") == 0) {
1146                 NTSTATUS status;
1147                 bool ok;
1148
1149                 ok = setup_dcerpc_ncalrpc_socket(ep_ctx->ev_ctx,
1150                                                  ep_ctx->msg_ctx,
1151                                                  abstract_syntax,
1152                                                  pipe_name);
1153                 if (!ok) {
1154                         return false;
1155                 }
1156
1157                 port = _open_sockets(ep_ctx->ev_ctx,
1158                                      ep_ctx->msg_ctx,
1159                                      abstract_syntax,
1160                                      0);
1161                 if (port == 0) {
1162                         return false;
1163                 }
1164
1165                 status = rpc_ep_setup_register(ep_ctx->ev_ctx,
1166                                           ep_ctx->msg_ctx,
1167                                           &ndr_table_wkssvc,
1168                                           "wkssvc",
1169                                           port);
1170                 if (!NT_STATUS_IS_OK(status)) {
1171                         return false;
1172                 }
1173         }
1174
1175         return true;
1176 }
1177
1178 static bool wkssvc_shutdown_cb(void *ptr) {
1179         return NT_STATUS_IS_OK(_rpc_ep_unregister(&ndr_table_wkssvc));
1180 }
1181
1182 bool dcesrv_ep_setup(struct tevent_context *ev_ctx,
1183                      struct messaging_context *msg_ctx)
1184 {
1185         struct dcesrv_ep_context *ep_ctx;
1186
1187         struct rpc_srv_callbacks epmapper_cb;
1188
1189         struct rpc_srv_callbacks winreg_cb;
1190         struct rpc_srv_callbacks srvsvc_cb;
1191
1192         struct rpc_srv_callbacks lsarpc_cb;
1193         struct rpc_srv_callbacks samr_cb;
1194         struct rpc_srv_callbacks netlogon_cb;
1195
1196         struct rpc_srv_callbacks spoolss_cb;
1197         struct rpc_srv_callbacks svcctl_cb;
1198         struct rpc_srv_callbacks ntsvcs_cb;
1199         struct rpc_srv_callbacks eventlog_cb;
1200         struct rpc_srv_callbacks initshutdown_cb;
1201         struct rpc_srv_callbacks netdfs_cb;
1202 #ifdef DEVELOPER
1203         struct rpc_srv_callbacks rpcecho_cb;
1204 #endif
1205         struct rpc_srv_callbacks dssetup_cb;
1206         struct rpc_srv_callbacks wkssvc_cb;
1207
1208         const char *rpcsrv_type;
1209
1210         ep_ctx = talloc(ev_ctx, struct dcesrv_ep_context);
1211         if (ep_ctx == NULL) {
1212                 return false;
1213         }
1214
1215         ep_ctx->ev_ctx = ev_ctx;
1216         ep_ctx->msg_ctx = msg_ctx;
1217
1218         /* start endpoint mapper only if enabled */
1219         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
1220                                            "rpc_server",
1221                                            "epmapper",
1222                                            "none");
1223         if (StrCaseCmp(rpcsrv_type, "embedded") == 0) {
1224                 epmapper_cb.init         = epmapper_init_cb;
1225                 epmapper_cb.shutdown     = epmapper_shutdown_cb;
1226                 epmapper_cb.private_data = ep_ctx;
1227
1228                 if (!NT_STATUS_IS_OK(rpc_epmapper_init(&epmapper_cb))) {
1229                         return false;
1230                 }
1231         }
1232
1233         winreg_cb.init         = winreg_init_cb;
1234         winreg_cb.shutdown     = winreg_shutdown_cb;
1235         winreg_cb.private_data = ep_ctx;
1236         if (!NT_STATUS_IS_OK(rpc_winreg_init(&winreg_cb))) {
1237                 return false;
1238         }
1239
1240         srvsvc_cb.init         = srvsvc_init_cb;
1241         srvsvc_cb.shutdown     = srvsvc_shutdown_cb;
1242         srvsvc_cb.private_data = ep_ctx;
1243         if (!NT_STATUS_IS_OK(rpc_srvsvc_init(&srvsvc_cb))) {
1244                 return false;
1245         }
1246
1247
1248         lsarpc_cb.init         = lsarpc_init_cb;
1249         lsarpc_cb.shutdown     = lsarpc_shutdown_cb;
1250         lsarpc_cb.private_data = ep_ctx;
1251         if (!NT_STATUS_IS_OK(rpc_lsarpc_init(&lsarpc_cb))) {
1252                 return false;
1253         }
1254
1255         samr_cb.init         = samr_init_cb;
1256         samr_cb.shutdown     = samr_shutdown_cb;
1257         samr_cb.private_data = ep_ctx;
1258         if (!NT_STATUS_IS_OK(rpc_samr_init(&samr_cb))) {
1259                 return false;
1260         }
1261
1262         netlogon_cb.init         = netlogon_init_cb;
1263         netlogon_cb.shutdown     = netlogon_shutdown_cb;
1264         netlogon_cb.private_data = ep_ctx;
1265         if (!NT_STATUS_IS_OK(rpc_netlogon_init(&netlogon_cb))) {
1266                 return false;
1267         }
1268
1269         spoolss_cb.init         = spoolss_init_cb;
1270         spoolss_cb.shutdown     = spoolss_shutdown_cb;
1271         spoolss_cb.private_data = ep_ctx;
1272         if (!NT_STATUS_IS_OK(rpc_spoolss_init(&spoolss_cb))) {
1273                 return false;
1274         }
1275
1276
1277         svcctl_cb.init         = svcctl_init_cb;
1278         svcctl_cb.shutdown     = svcctl_shutdown_cb;
1279         svcctl_cb.private_data = ep_ctx;
1280         if (!NT_STATUS_IS_OK(rpc_svcctl_init(&svcctl_cb))) {
1281                 return false;
1282         }
1283
1284         ntsvcs_cb.init         = ntsvcs_init_cb;
1285         ntsvcs_cb.shutdown     = ntsvcs_shutdown_cb;
1286         ntsvcs_cb.private_data = ep_ctx;
1287         if (!NT_STATUS_IS_OK(rpc_ntsvcs_init(&ntsvcs_cb))) {
1288                 return false;
1289         }
1290
1291         eventlog_cb.init         = eventlog_init_cb;
1292         eventlog_cb.shutdown     = eventlog_shutdown_cb;
1293         eventlog_cb.private_data = ep_ctx;
1294         if (!NT_STATUS_IS_OK(rpc_eventlog_init(&eventlog_cb))) {
1295                 return false;
1296         }
1297
1298         initshutdown_cb.init         = initshutdown_init_cb;
1299         initshutdown_cb.shutdown     = initshutdown_shutdown_cb;
1300         initshutdown_cb.private_data = ep_ctx;
1301         if (!NT_STATUS_IS_OK(rpc_initshutdown_init(&initshutdown_cb))) {
1302                 return false;
1303         }
1304
1305         netdfs_cb.init         = netdfs_init_cb;
1306         netdfs_cb.shutdown     = netdfs_shutdown_cb;
1307         netdfs_cb.private_data = ep_ctx;
1308         if (!NT_STATUS_IS_OK(rpc_netdfs_init(&netdfs_cb))) {
1309                 return false;
1310         }
1311 #ifdef DEVELOPER
1312
1313         rpcecho_cb.init         = rpcecho_init_cb;
1314         rpcecho_cb.shutdown     = rpcecho_shutdown_cb;
1315         rpcecho_cb.private_data = ep_ctx;
1316         if (!NT_STATUS_IS_OK(rpc_rpcecho_init(&rpcecho_cb))) {
1317                 return false;
1318         }
1319 #endif
1320
1321         dssetup_cb.init         = dssetup_init_cb;
1322         dssetup_cb.shutdown     = dssetup_shutdown_cb;
1323         dssetup_cb.private_data = ep_ctx;
1324         if (!NT_STATUS_IS_OK(rpc_dssetup_init(&dssetup_cb))) {
1325                 return false;
1326         }
1327
1328         wkssvc_cb.init         = wkssvc_init_cb;
1329         wkssvc_cb.shutdown     = wkssvc_shutdown_cb;
1330         wkssvc_cb.private_data = ep_ctx;
1331         if (!NT_STATUS_IS_OK(rpc_wkssvc_init(&wkssvc_cb))) {
1332                 return false;
1333         }
1334
1335         return true;
1336 }
1337
1338 /* vim: set ts=8 sw=8 noet cindent ft=c.doxygen: */