Line data Source code
1 : /* s3 compat server functions auto-generated by pidl */
2 : #include "bin/default/librpc/gen_ndr/ndr_echo.h"
3 : #include "bin/default/librpc/gen_ndr/ndr_echo_scompat.h"
4 : #include <librpc/rpc/dcesrv_core.h>
5 : #include <rpc_server/rpc_config.h>
6 : #include <rpc_server/rpc_server.h>
7 : #include <util/debug.h>
8 :
9 : enum s3compat_rpc_dispatch {
10 : S3COMPAT_RPC_DISPATCH_EXTERNAL = 0x00000001,
11 : S3COMPAT_RPC_DISPATCH_INTERNAL = 0x00000002,
12 : };
13 :
14 : /* rpcecho - dcerpc server boilerplate generated by pidl */
15 2 : static NTSTATUS rpcecho__op_bind(struct dcesrv_connection_context *context, const struct dcesrv_interface *iface)
16 : {
17 2 : struct pipes_struct *p = NULL;
18 :
19 : /* Retrieve pipes struct */
20 2 : p = dcesrv_get_pipes_struct(context->conn);
21 2 : p->pipe_bound = true;
22 : #ifdef DCESRV_INTERFACE_RPCECHO_BIND
23 : return DCESRV_INTERFACE_RPCECHO_BIND(context,iface);
24 : #else
25 2 : return NT_STATUS_OK;
26 : #endif
27 : }
28 :
29 2 : static void rpcecho__op_unbind(struct dcesrv_connection_context *context, const struct dcesrv_interface *iface)
30 : {
31 : #ifdef DCESRV_INTERFACE_RPCECHO_UNBIND
32 : DCESRV_INTERFACE_RPCECHO_UNBIND(context, iface);
33 : #else
34 2 : return;
35 : #endif
36 : }
37 :
38 44 : NTSTATUS rpcecho__op_ndr_pull(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_pull *pull, void **r)
39 : {
40 : enum ndr_err_code ndr_err;
41 44 : uint16_t opnum = dce_call->pkt.u.request.opnum;
42 :
43 44 : dce_call->fault_code = 0;
44 :
45 44 : if (opnum >= ndr_table_rpcecho.num_calls) {
46 0 : dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
47 0 : return NT_STATUS_NET_WRITE_FAULT;
48 : }
49 :
50 44 : *r = talloc_named(mem_ctx, ndr_table_rpcecho.calls[opnum].struct_size, "struct %s", ndr_table_rpcecho.calls[opnum].name);
51 44 : NT_STATUS_HAVE_NO_MEMORY(*r);
52 :
53 : /* unravel the NDR for the packet */
54 44 : ndr_err = ndr_table_rpcecho.calls[opnum].ndr_pull(pull, NDR_IN, *r);
55 44 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
56 0 : dce_call->fault_code = DCERPC_FAULT_NDR;
57 0 : return NT_STATUS_NET_WRITE_FAULT;
58 : }
59 :
60 44 : return NT_STATUS_OK;
61 : }
62 :
63 44 : static NTSTATUS rpcecho__op_dispatch_internal(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r, enum s3compat_rpc_dispatch dispatch)
64 : {
65 44 : uint16_t opnum = dce_call->pkt.u.request.opnum;
66 44 : struct pipes_struct *p = NULL;
67 44 : struct auth_session_info *pipe_session_info = NULL;
68 44 : NTSTATUS status = NT_STATUS_OK;
69 44 : bool impersonated = false;
70 :
71 : /* Retrieve pipes struct */
72 44 : p = dcesrv_get_pipes_struct(dce_call->conn);
73 : /* Update pipes struct opnum */
74 44 : p->opnum = opnum;
75 44 : p->dce_call = dce_call;
76 44 : p->mem_ctx = mem_ctx;
77 : /* Update pipes struct session info */
78 44 : pipe_session_info = p->session_info;
79 44 : p->session_info = dce_call->auth_state->session_info;
80 44 : p->auth.auth_type = dce_call->auth_state->auth_type;
81 44 : p->auth.auth_level = dce_call->auth_state->auth_level;
82 44 : p->auth.auth_context_id = dce_call->auth_state->auth_context_id;
83 : /* Reset pipes struct fault state */
84 44 : p->fault_state = 0;
85 :
86 : /* Impersonate */
87 44 : if (dispatch == S3COMPAT_RPC_DISPATCH_EXTERNAL) {
88 44 : impersonated = become_authenticated_pipe_user(p->session_info);
89 44 : if (!impersonated) {
90 0 : dce_call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
91 0 : status = NT_STATUS_NET_WRITE_FAULT;
92 0 : goto fail;
93 : }
94 : }
95 :
96 44 : switch (opnum) {
97 28 : case 0: { /* echo_AddOne */
98 28 : struct echo_AddOne *r2 = (struct echo_AddOne *)r;
99 28 : if (DEBUGLEVEL >= 10) {
100 0 : NDR_PRINT_FUNCTION_DEBUG(echo_AddOne, NDR_IN, r2);
101 : }
102 28 : NDR_ZERO_STRUCT(r2->out);
103 28 : r2->out.out_data = talloc_zero(r2, uint32_t);
104 28 : if (r2->out.out_data == NULL) {
105 0 : status = NT_STATUS_NO_MEMORY;
106 0 : p->fault_state = DCERPC_FAULT_CANT_PERFORM;
107 0 : goto fail;
108 : }
109 :
110 28 : _echo_AddOne(p, r2);
111 28 : break;
112 : }
113 2 : case 1: { /* echo_EchoData */
114 2 : struct echo_EchoData *r2 = (struct echo_EchoData *)r;
115 2 : if (DEBUGLEVEL >= 10) {
116 0 : NDR_PRINT_FUNCTION_DEBUG(echo_EchoData, NDR_IN, r2);
117 : }
118 2 : NDR_ZERO_STRUCT(r2->out);
119 2 : r2->out.out_data = talloc_zero_array(r2, uint8_t, r2->in.len);
120 2 : if (r2->out.out_data == NULL) {
121 0 : status = NT_STATUS_NO_MEMORY;
122 0 : p->fault_state = DCERPC_FAULT_CANT_PERFORM;
123 0 : goto fail;
124 : }
125 :
126 2 : _echo_EchoData(p, r2);
127 2 : break;
128 : }
129 2 : case 2: { /* echo_SinkData */
130 2 : struct echo_SinkData *r2 = (struct echo_SinkData *)r;
131 2 : if (DEBUGLEVEL >= 10) {
132 0 : NDR_PRINT_FUNCTION_DEBUG(echo_SinkData, NDR_IN, r2);
133 : }
134 2 : _echo_SinkData(p, r2);
135 2 : break;
136 : }
137 2 : case 3: { /* echo_SourceData */
138 2 : struct echo_SourceData *r2 = (struct echo_SourceData *)r;
139 2 : if (DEBUGLEVEL >= 10) {
140 0 : NDR_PRINT_FUNCTION_DEBUG(echo_SourceData, NDR_IN, r2);
141 : }
142 2 : NDR_ZERO_STRUCT(r2->out);
143 2 : r2->out.data = talloc_zero_array(r2, uint8_t, r2->in.len);
144 2 : if (r2->out.data == NULL) {
145 0 : status = NT_STATUS_NO_MEMORY;
146 0 : p->fault_state = DCERPC_FAULT_CANT_PERFORM;
147 0 : goto fail;
148 : }
149 :
150 2 : _echo_SourceData(p, r2);
151 2 : break;
152 : }
153 2 : case 4: { /* echo_TestCall */
154 2 : struct echo_TestCall *r2 = (struct echo_TestCall *)r;
155 2 : if (DEBUGLEVEL >= 10) {
156 0 : NDR_PRINT_FUNCTION_DEBUG(echo_TestCall, NDR_IN, r2);
157 : }
158 2 : NDR_ZERO_STRUCT(r2->out);
159 2 : r2->out.s2 = talloc_zero(r2, const char *);
160 2 : if (r2->out.s2 == NULL) {
161 0 : status = NT_STATUS_NO_MEMORY;
162 0 : p->fault_state = DCERPC_FAULT_CANT_PERFORM;
163 0 : goto fail;
164 : }
165 :
166 2 : _echo_TestCall(p, r2);
167 2 : break;
168 : }
169 2 : case 5: { /* echo_TestCall2 */
170 2 : struct echo_TestCall2 *r2 = (struct echo_TestCall2 *)r;
171 2 : if (DEBUGLEVEL >= 10) {
172 0 : NDR_PRINT_FUNCTION_DEBUG(echo_TestCall2, NDR_IN, r2);
173 : }
174 2 : NDR_ZERO_STRUCT(r2->out);
175 2 : r2->out.info = talloc_zero(r2, union echo_Info);
176 2 : if (r2->out.info == NULL) {
177 0 : status = NT_STATUS_NO_MEMORY;
178 0 : p->fault_state = DCERPC_FAULT_CANT_PERFORM;
179 0 : goto fail;
180 : }
181 :
182 2 : r2->out.result = _echo_TestCall2(p, r2);
183 2 : break;
184 : }
185 0 : case 6: { /* echo_TestSleep */
186 0 : struct echo_TestSleep *r2 = (struct echo_TestSleep *)r;
187 0 : if (DEBUGLEVEL >= 10) {
188 0 : NDR_PRINT_FUNCTION_DEBUG(echo_TestSleep, NDR_IN, r2);
189 : }
190 0 : r2->out.result = _echo_TestSleep(p, r2);
191 0 : break;
192 : }
193 2 : case 7: { /* echo_TestEnum */
194 2 : struct echo_TestEnum *r2 = (struct echo_TestEnum *)r;
195 2 : if (DEBUGLEVEL >= 10) {
196 0 : NDR_PRINT_FUNCTION_DEBUG(echo_TestEnum, NDR_IN, r2);
197 : }
198 2 : NDR_ZERO_STRUCT(r2->out);
199 2 : r2->out.foo1 = r2->in.foo1;
200 2 : r2->out.foo2 = r2->in.foo2;
201 2 : r2->out.foo3 = r2->in.foo3;
202 2 : _echo_TestEnum(p, r2);
203 2 : break;
204 : }
205 2 : case 8: { /* echo_TestSurrounding */
206 2 : struct echo_TestSurrounding *r2 = (struct echo_TestSurrounding *)r;
207 2 : if (DEBUGLEVEL >= 10) {
208 0 : NDR_PRINT_FUNCTION_DEBUG(echo_TestSurrounding, NDR_IN, r2);
209 : }
210 2 : NDR_ZERO_STRUCT(r2->out);
211 2 : r2->out.data = r2->in.data;
212 2 : _echo_TestSurrounding(p, r2);
213 2 : break;
214 : }
215 2 : case 9: { /* echo_TestDoublePointer */
216 2 : struct echo_TestDoublePointer *r2 = (struct echo_TestDoublePointer *)r;
217 2 : if (DEBUGLEVEL >= 10) {
218 0 : NDR_PRINT_FUNCTION_DEBUG(echo_TestDoublePointer, NDR_IN, r2);
219 : }
220 2 : r2->out.result = _echo_TestDoublePointer(p, r2);
221 2 : break;
222 : }
223 0 : default:
224 0 : dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
225 0 : break;
226 : }
227 :
228 44 : fail:
229 : /* Unimpersonate */
230 44 : if (impersonated) {
231 44 : unbecome_authenticated_pipe_user();
232 : }
233 :
234 44 : p->dce_call = NULL;
235 44 : p->mem_ctx = NULL;
236 : /* Restore session info */
237 44 : p->session_info = pipe_session_info;
238 44 : p->auth.auth_type = 0;
239 44 : p->auth.auth_level = 0;
240 44 : p->auth.auth_context_id = 0;
241 : /* Check pipes struct fault state */
242 44 : if (p->fault_state != 0) {
243 10 : dce_call->fault_code = p->fault_state;
244 : }
245 44 : if (dce_call->fault_code != 0) {
246 10 : status = NT_STATUS_NET_WRITE_FAULT;
247 : }
248 :
249 44 : return status;
250 : }
251 :
252 44 : NTSTATUS rpcecho__op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
253 : {
254 44 : return rpcecho__op_dispatch_internal(dce_call, mem_ctx, r, S3COMPAT_RPC_DISPATCH_EXTERNAL);
255 : }
256 :
257 34 : NTSTATUS rpcecho__op_reply(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
258 : {
259 34 : uint16_t opnum = dce_call->pkt.u.request.opnum;
260 :
261 34 : switch (opnum) {
262 28 : case 0: { /* echo_AddOne */
263 28 : struct echo_AddOne *r2 = (struct echo_AddOne *)r;
264 28 : if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
265 0 : DEBUG(5,("function echo_AddOne replied async\n"));
266 : }
267 28 : if (DEBUGLEVEL >= 10 && dce_call->fault_code == 0) {
268 0 : NDR_PRINT_FUNCTION_DEBUG(echo_AddOne, NDR_OUT | NDR_SET_VALUES, r2);
269 : }
270 28 : if (dce_call->fault_code != 0) {
271 0 : DBG_WARNING("dcerpc_fault %s in echo_AddOne\n", dcerpc_errstr(mem_ctx, dce_call->fault_code));
272 : }
273 28 : break;
274 : }
275 2 : case 1: { /* echo_EchoData */
276 2 : struct echo_EchoData *r2 = (struct echo_EchoData *)r;
277 2 : if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
278 0 : DEBUG(5,("function echo_EchoData replied async\n"));
279 : }
280 2 : if (DEBUGLEVEL >= 10 && dce_call->fault_code == 0) {
281 0 : NDR_PRINT_FUNCTION_DEBUG(echo_EchoData, NDR_OUT | NDR_SET_VALUES, r2);
282 : }
283 2 : if (dce_call->fault_code != 0) {
284 0 : DBG_WARNING("dcerpc_fault %s in echo_EchoData\n", dcerpc_errstr(mem_ctx, dce_call->fault_code));
285 : }
286 2 : break;
287 : }
288 2 : case 2: { /* echo_SinkData */
289 2 : struct echo_SinkData *r2 = (struct echo_SinkData *)r;
290 2 : if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
291 0 : DEBUG(5,("function echo_SinkData replied async\n"));
292 : }
293 2 : if (DEBUGLEVEL >= 10 && dce_call->fault_code == 0) {
294 0 : NDR_PRINT_FUNCTION_DEBUG(echo_SinkData, NDR_OUT | NDR_SET_VALUES, r2);
295 : }
296 2 : if (dce_call->fault_code != 0) {
297 0 : DBG_WARNING("dcerpc_fault %s in echo_SinkData\n", dcerpc_errstr(mem_ctx, dce_call->fault_code));
298 : }
299 2 : break;
300 : }
301 2 : case 3: { /* echo_SourceData */
302 2 : struct echo_SourceData *r2 = (struct echo_SourceData *)r;
303 2 : if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
304 0 : DEBUG(5,("function echo_SourceData replied async\n"));
305 : }
306 2 : if (DEBUGLEVEL >= 10 && dce_call->fault_code == 0) {
307 0 : NDR_PRINT_FUNCTION_DEBUG(echo_SourceData, NDR_OUT | NDR_SET_VALUES, r2);
308 : }
309 2 : if (dce_call->fault_code != 0) {
310 0 : DBG_WARNING("dcerpc_fault %s in echo_SourceData\n", dcerpc_errstr(mem_ctx, dce_call->fault_code));
311 : }
312 2 : break;
313 : }
314 0 : case 4: { /* echo_TestCall */
315 0 : struct echo_TestCall *r2 = (struct echo_TestCall *)r;
316 0 : if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
317 0 : DEBUG(5,("function echo_TestCall replied async\n"));
318 : }
319 0 : if (DEBUGLEVEL >= 10 && dce_call->fault_code == 0) {
320 0 : NDR_PRINT_FUNCTION_DEBUG(echo_TestCall, NDR_OUT | NDR_SET_VALUES, r2);
321 : }
322 0 : if (dce_call->fault_code != 0) {
323 0 : DBG_WARNING("dcerpc_fault %s in echo_TestCall\n", dcerpc_errstr(mem_ctx, dce_call->fault_code));
324 : }
325 0 : break;
326 : }
327 0 : case 5: { /* echo_TestCall2 */
328 0 : struct echo_TestCall2 *r2 = (struct echo_TestCall2 *)r;
329 0 : if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
330 0 : DEBUG(5,("function echo_TestCall2 replied async\n"));
331 : }
332 0 : if (DEBUGLEVEL >= 10 && dce_call->fault_code == 0) {
333 0 : NDR_PRINT_FUNCTION_DEBUG(echo_TestCall2, NDR_OUT | NDR_SET_VALUES, r2);
334 : }
335 0 : if (dce_call->fault_code != 0) {
336 0 : DBG_WARNING("dcerpc_fault %s in echo_TestCall2\n", dcerpc_errstr(mem_ctx, dce_call->fault_code));
337 : }
338 0 : break;
339 : }
340 0 : case 6: { /* echo_TestSleep */
341 0 : struct echo_TestSleep *r2 = (struct echo_TestSleep *)r;
342 0 : if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
343 0 : DEBUG(5,("function echo_TestSleep replied async\n"));
344 : }
345 0 : if (DEBUGLEVEL >= 10 && dce_call->fault_code == 0) {
346 0 : NDR_PRINT_FUNCTION_DEBUG(echo_TestSleep, NDR_OUT | NDR_SET_VALUES, r2);
347 : }
348 0 : if (dce_call->fault_code != 0) {
349 0 : DBG_WARNING("dcerpc_fault %s in echo_TestSleep\n", dcerpc_errstr(mem_ctx, dce_call->fault_code));
350 : }
351 0 : break;
352 : }
353 0 : case 7: { /* echo_TestEnum */
354 0 : struct echo_TestEnum *r2 = (struct echo_TestEnum *)r;
355 0 : if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
356 0 : DEBUG(5,("function echo_TestEnum replied async\n"));
357 : }
358 0 : if (DEBUGLEVEL >= 10 && dce_call->fault_code == 0) {
359 0 : NDR_PRINT_FUNCTION_DEBUG(echo_TestEnum, NDR_OUT | NDR_SET_VALUES, r2);
360 : }
361 0 : if (dce_call->fault_code != 0) {
362 0 : DBG_WARNING("dcerpc_fault %s in echo_TestEnum\n", dcerpc_errstr(mem_ctx, dce_call->fault_code));
363 : }
364 0 : break;
365 : }
366 0 : case 8: { /* echo_TestSurrounding */
367 0 : struct echo_TestSurrounding *r2 = (struct echo_TestSurrounding *)r;
368 0 : if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
369 0 : DEBUG(5,("function echo_TestSurrounding replied async\n"));
370 : }
371 0 : if (DEBUGLEVEL >= 10 && dce_call->fault_code == 0) {
372 0 : NDR_PRINT_FUNCTION_DEBUG(echo_TestSurrounding, NDR_OUT | NDR_SET_VALUES, r2);
373 : }
374 0 : if (dce_call->fault_code != 0) {
375 0 : DBG_WARNING("dcerpc_fault %s in echo_TestSurrounding\n", dcerpc_errstr(mem_ctx, dce_call->fault_code));
376 : }
377 0 : break;
378 : }
379 0 : case 9: { /* echo_TestDoublePointer */
380 0 : struct echo_TestDoublePointer *r2 = (struct echo_TestDoublePointer *)r;
381 0 : if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
382 0 : DEBUG(5,("function echo_TestDoublePointer replied async\n"));
383 : }
384 0 : if (DEBUGLEVEL >= 10 && dce_call->fault_code == 0) {
385 0 : NDR_PRINT_FUNCTION_DEBUG(echo_TestDoublePointer, NDR_OUT | NDR_SET_VALUES, r2);
386 : }
387 0 : if (dce_call->fault_code != 0) {
388 0 : DBG_WARNING("dcerpc_fault %s in echo_TestDoublePointer\n", dcerpc_errstr(mem_ctx, dce_call->fault_code));
389 : }
390 0 : break;
391 : }
392 0 : default:
393 0 : dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
394 0 : break;
395 : }
396 :
397 34 : if (dce_call->fault_code != 0) {
398 0 : return NT_STATUS_NET_WRITE_FAULT;
399 : }
400 :
401 34 : return NT_STATUS_OK;
402 : }
403 :
404 34 : NTSTATUS rpcecho__op_ndr_push(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_push *push, const void *r)
405 : {
406 : enum ndr_err_code ndr_err;
407 34 : uint16_t opnum = dce_call->pkt.u.request.opnum;
408 :
409 34 : ndr_err = ndr_table_rpcecho.calls[opnum].ndr_push(push, NDR_OUT, r);
410 34 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
411 0 : dce_call->fault_code = DCERPC_FAULT_NDR;
412 0 : return NT_STATUS_NET_WRITE_FAULT;
413 : }
414 :
415 34 : return NT_STATUS_OK;
416 : }
417 :
418 0 : NTSTATUS rpcecho__op_local(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
419 : {
420 0 : return rpcecho__op_dispatch_internal(dce_call, mem_ctx, r, S3COMPAT_RPC_DISPATCH_INTERNAL);
421 : }
422 :
423 : static const struct dcesrv_interface dcesrv_rpcecho_interface = {
424 : .name = "rpcecho",
425 : .syntax_id = {{0x60a15ec5,0x4de8,0x11d7,{0xa6,0x37},{0x00,0x50,0x56,0xa2,0x01,0x82}},1.0},
426 : .bind = rpcecho__op_bind,
427 : .unbind = rpcecho__op_unbind,
428 : .ndr_pull = rpcecho__op_ndr_pull,
429 : .dispatch = rpcecho__op_dispatch,
430 : .reply = rpcecho__op_reply,
431 : .ndr_push = rpcecho__op_ndr_push,
432 : .local = rpcecho__op_local,
433 : #ifdef DCESRV_INTERFACE_RPCECHO_FLAGS
434 : .flags = DCESRV_INTERFACE_RPCECHO_FLAGS
435 : #else
436 : .flags = 0
437 : #endif
438 : };
439 :
440 84 : static NTSTATUS rpcecho__check_register_in_endpoint(const char *name, struct dcerpc_binding *binding) {
441 84 : enum dcerpc_transport_t transport = dcerpc_binding_get_transport(binding);
442 : NTSTATUS status;
443 :
444 : /* If service is disabled, do not register */
445 84 : if (rpc_service_mode(name) == RPC_SERVICE_MODE_DISABLED) {
446 0 : return NT_STATUS_NOT_IMPLEMENTED;
447 : }
448 :
449 : /* If service is embedded, register only for ncacn_np
450 : * see 8466b3c85e4b835e57e41776853093f4a0edc8b8
451 : */
452 84 : if (rpc_service_mode(name) == RPC_SERVICE_MODE_EMBEDDED && (transport != NCACN_NP && transport != NCALRPC)) {
453 28 : DBG_INFO("Interface 'rpcecho' not registered in endpoint '%s' as service is embedded\n", name);
454 28 : return NT_STATUS_NOT_SUPPORTED;
455 : }
456 :
457 : /*
458 : * If rpc service is external then change the default ncalrpc endpoint,
459 : * otherwise if the rpc daemon running this service is configured in
460 : * fork mode the forked process will race with main smbd to accept the
461 : * connections in the default ncalrpc socket, and the forked process
462 : * may not have the requested interface registered.
463 : * For example, in the ad_member test environment:
464 : *
465 : * rpc_server:lsarpc = external
466 : * rpc_server:samr = external
467 : * rpc_server:netlogon = disabled
468 : * rpc_daemon:lsasd = fork
469 : *
470 : * With these settings both, the main smbd and all the preforked lsasd
471 : * processes would be listening in the default ncalrpc socket if it is
472 : * not changed. If a client connection is accepted by one of the lsasd
473 : * worker processes and the client asks for an interface not registered
474 : * in these processes (winreg for example) it will get an error.
475 : */
476 56 : if (rpc_service_mode(name) == RPC_SERVICE_MODE_EXTERNAL && transport == NCALRPC) {
477 0 : status = dcerpc_binding_set_string_option(binding, "endpoint", "RPCECHO");
478 0 : if (!NT_STATUS_IS_OK(status)) {
479 0 : return status;
480 : }
481 : }
482 :
483 56 : return NT_STATUS_OK;
484 : }
485 :
486 28 : static NTSTATUS rpcecho__op_init_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server)
487 : {
488 : uint32_t i;
489 : NTSTATUS ret;
490 : struct dcerpc_binding *binding;
491 28 : struct dcerpc_binding *binding2 = NULL;
492 :
493 : #ifdef DCESRV_INTERFACE_RPCECHO_NCACN_NP_SECONDARY_ENDPOINT
494 : const char *ncacn_np_secondary_endpoint = DCESRV_INTERFACE_RPCECHO_NCACN_NP_SECONDARY_ENDPOINT;
495 : #else
496 28 : const char *ncacn_np_secondary_endpoint = NULL;
497 : #endif
498 :
499 112 : for (i=0;i<ndr_table_rpcecho.endpoints->count;i++) {
500 84 : const char *name = ndr_table_rpcecho.endpoints->names[i];
501 :
502 84 : ret = dcerpc_parse_binding(dce_ctx, name, &binding);
503 84 : if (NT_STATUS_IS_ERR(ret)) {
504 0 : DBG_ERR("Failed to parse binding string '%s'\n", name);
505 0 : return ret;
506 : }
507 :
508 84 : ret = rpcecho__check_register_in_endpoint("rpcecho", binding);
509 84 : if (NT_STATUS_IS_ERR(ret)) {
510 28 : talloc_free(binding);
511 28 : continue;
512 : }
513 :
514 56 : if (ncacn_np_secondary_endpoint != NULL) {
515 0 : ret = dcerpc_parse_binding(dce_ctx, ncacn_np_secondary_endpoint, &binding2);
516 0 : if (NT_STATUS_IS_ERR(ret)) {
517 0 : DBG_ERR("Failed to parse 2nd binding string '%s'\n", ncacn_np_secondary_endpoint);
518 0 : TALLOC_FREE(binding);
519 0 : return ret;
520 : }
521 : }
522 :
523 56 : ret = dcesrv_interface_register_b(dce_ctx, binding, binding2, &dcesrv_rpcecho_interface, NULL);
524 56 : TALLOC_FREE(binding);
525 56 : TALLOC_FREE(binding2);
526 56 : if (!NT_STATUS_IS_OK(ret)) {
527 0 : DBG_ERR("Failed to register endpoint '%s'\n",name);
528 0 : return ret;
529 : }
530 : }
531 :
532 28 : return NT_STATUS_OK;
533 : }
534 :
535 19 : static NTSTATUS rpcecho__op_shutdown_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server)
536 : {
537 19 : return NT_STATUS_OK;
538 : }
539 :
540 0 : static bool rpcecho__op_interface_by_uuid(struct dcesrv_interface *iface, const struct GUID *uuid, uint32_t if_version)
541 : {
542 0 : if (dcesrv_rpcecho_interface.syntax_id.if_version == if_version && GUID_equal(&dcesrv_rpcecho_interface.syntax_id.uuid, uuid)) {
543 0 : memcpy(iface,&dcesrv_rpcecho_interface, sizeof(*iface));
544 0 : return true;
545 : }
546 :
547 0 : return false;
548 : }
549 :
550 0 : static bool rpcecho__op_interface_by_name(struct dcesrv_interface *iface, const char *name)
551 : {
552 0 : if (strcmp(dcesrv_rpcecho_interface.name, name)==0) {
553 0 : memcpy(iface, &dcesrv_rpcecho_interface, sizeof(*iface));
554 0 : return true;
555 : }
556 :
557 0 : return false;
558 : }
559 :
560 : static const struct dcesrv_endpoint_server rpcecho_ep_server = {
561 : /* fill in our name */
562 : .name = "rpcecho",
563 :
564 : /* Initialization flag */
565 : .initialized = false,
566 :
567 : /* fill in all the operations */
568 : #ifdef DCESRV_INTERFACE_RPCECHO_INIT_SERVER
569 : .init_server = DCESRV_INTERFACE_RPCECHO_INIT_SERVER,
570 : #else
571 : .init_server = rpcecho__op_init_server,
572 : #endif
573 : #ifdef DCESRV_INTERFACE_RPCECHO_SHUTDOWN_SERVER
574 : .shutdown_server = DCESRV_INTERFACE_RPCECHO_SHUTDOWN_SERVER,
575 : #else
576 : .shutdown_server = rpcecho__op_shutdown_server,
577 : #endif
578 : .interface_by_uuid = rpcecho__op_interface_by_uuid,
579 : .interface_by_name = rpcecho__op_interface_by_name
580 : };
581 :
582 60 : const struct dcesrv_endpoint_server *rpcecho_get_ep_server(void)
583 : {
584 60 : return &rpcecho_ep_server;
585 : }
|