s4:rpc_server: add dcesrv_iface_state_{store,find}_{assoc,conn}() helpers
[samba.git] / source4 / rpc_server / service_rpc.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    smbd-specific dcerpc server code
5
6    Copyright (C) Andrew Tridgell 2003-2005
7    Copyright (C) Stefan (metze) Metzmacher 2004-2005
8    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2004,2007
9    
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "librpc/gen_ndr/ndr_dcerpc.h"
26 #include "auth/auth.h"
27 #include "../lib/util/dlinklist.h"
28 #include "rpc_server/dcerpc_server.h"
29 #include "rpc_server/dcerpc_server_proto.h"
30 #include "system/filesys.h"
31 #include "lib/messaging/irpc.h"
32 #include "system/network.h"
33 #include "lib/socket/netif.h"
34 #include "param/param.h"
35 #include "../lib/tsocket/tsocket.h"
36 #include "librpc/rpc/dcerpc_proto.h"
37 #include "../lib/util/tevent_ntstatus.h"
38 #include "libcli/raw/smb.h"
39 #include "../libcli/named_pipe_auth/npa_tstream.h"
40 #include "smbd/process_model.h"
41
42 /*
43  * Need to run the majority of the RPC endpoints in a single process to allow
44  * for shared handles, and the sharing of ldb contexts.
45  *
46  * However other endpoints are capable of being run in multiple processes
47  * e.g. NETLOGON.
48  *
49  * To support this the process model is manipulated to force those end points
50  * not supporting multiple processes into the single process model. The code
51  * responsible for this is in dcesrv_init_endpoints
52  *
53  */
54 NTSTATUS server_service_rpc_init(TALLOC_CTX *);
55
56 /*
57  * Initialise the rpc endpoints.
58  */
59 static NTSTATUS dcesrv_init_endpoints(struct task_server *task,
60                                       struct dcesrv_context *dce_ctx,
61                                       bool use_single_process)
62 {
63
64         struct dcesrv_endpoint *e;
65         const struct model_ops *model_ops = NULL;
66
67         /*
68          * For those RPC services that run with shared context we need to
69          * ensure that they don't fork a new process on accept (standard_model).
70          * And as there is only one process handling these requests we need
71          * to handle accept errors in a similar manner to the single process
72          * model.
73          *
74          * To do this we override the process model operations with the single
75          * process operations. This is not the most elegant solution, but it is
76          * the least ugly, and is confined to the next block of code.
77          */
78         if (use_single_process == true) {
79                 model_ops = process_model_startup("single");
80                 if (model_ops == NULL) {
81                         DBG_ERR("Unable to load single process model");
82                         return NT_STATUS_INTERNAL_ERROR;
83                 }
84         } else {
85                 model_ops = task->model_ops;
86         }
87
88         for (e = dce_ctx->endpoint_list; e; e = e->next) {
89
90                 enum dcerpc_transport_t transport =
91                     dcerpc_binding_get_transport(e->ep_description);
92
93                 if (transport == NCACN_HTTP) {
94                         /*
95                          * We don't support ncacn_http yet
96                          */
97                         continue;
98                 }
99                 if (e->use_single_process == use_single_process) {
100                         NTSTATUS status;
101                         status = dcesrv_add_ep(dce_ctx,
102                                                task->lp_ctx,
103                                                e,
104                                                task->event_ctx,
105                                                model_ops,
106                                                task->process_context);
107                         if (!NT_STATUS_IS_OK(status)) {
108                                 return status;
109                         }
110                 }
111         }
112         return NT_STATUS_OK;
113 }
114 /*
115  * Initialise the RPC service.
116  * And those end points that can be serviced by multiple processes.
117  * The endpoints that need to be run in a single process are setup in the
118  * post_fork hook.
119 */
120 static NTSTATUS dcesrv_task_init(struct task_server *task)
121 {
122         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
123         struct dcesrv_context *dce_ctx;
124
125         dcerpc_server_init(task->lp_ctx);
126
127         task_server_set_title(task, "task[dcesrv]");
128
129         status = dcesrv_init_context(task->event_ctx,
130                                      task->lp_ctx,
131                                      lpcfg_dcerpc_endpoint_servers(task->lp_ctx),
132                                      &dce_ctx);
133         if (!NT_STATUS_IS_OK(status)) {
134                 return status;
135         }
136
137         /* Make sure the directory for NCALRPC exists */
138         if (!directory_exist(lpcfg_ncalrpc_dir(task->lp_ctx))) {
139                 mkdir(lpcfg_ncalrpc_dir(task->lp_ctx), 0755);
140         }
141         status = dcesrv_init_endpoints(task, dce_ctx, false);
142         if (!NT_STATUS_IS_OK(status)) {
143                 return status;
144         }
145
146         task->private_data = dce_ctx;
147         return NT_STATUS_OK;
148 }
149
150 /*
151  * Initialise the endpoints that need to run in a single process fork.
152  * The endpoint registration is only done for the first process instance.
153  *
154  */
155 static void dcesrv_post_fork(struct task_server *task,
156                              struct process_details *pd)
157 {
158
159         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
160         struct dcesrv_context *dce_ctx;
161
162         if (task->private_data == NULL) {
163                 task_server_terminate(task, "dcerpc: No dcesrv_context", true);
164                 return;
165         }
166         dce_ctx =
167             talloc_get_type_abort(task->private_data, struct dcesrv_context);
168
169         /*
170          * Ensure the single process endpoints are only available to the
171          * first instance.
172          */
173         if (pd->instances == 0) {
174                 status = dcesrv_init_endpoints(task, dce_ctx, true);
175                 if (!NT_STATUS_IS_OK(status)) {
176                         task_server_terminate(
177                             task,
178                             "dcerpc: Failed to initialise end points",
179                             true);
180                         return;
181                 }
182         }
183
184         irpc_add_name(task->msg_ctx, "rpc_server");
185 }
186
187 NTSTATUS server_service_rpc_init(TALLOC_CTX *ctx)
188 {
189         static const struct service_details details = {
190             .inhibit_fork_on_accept = false,
191             .inhibit_pre_fork = false,
192             .task_init = dcesrv_task_init,
193             .post_fork = dcesrv_post_fork};
194         return register_server_service(ctx, "rpc", &details);
195 }