lib/poll_funcs: free contexts in poll_funcs_state_destructor()
[Samba.git] / source3 / librpc / rpc / dcerpc_ep.c
blob0502557a6621178fe4cf2e381cb278cd85d71d42
1 /*
2 * Endpoint Mapper Functions
3 * DCERPC local endpoint mapper client routines
4 * Copyright (c) 2010-2011 Andreas Schneider.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "librpc/rpc/dcerpc.h"
22 #include "librpc/rpc/dcerpc_ep.h"
23 #include "../librpc/gen_ndr/ndr_epmapper_c.h"
24 #include "rpc_client/cli_pipe.h"
25 #include "auth.h"
26 #include "rpc_server/rpc_ncacn_np.h"
27 #include "../lib/tsocket/tsocket.h"
28 #include "rpc_server/rpc_config.h"
30 #define EPM_MAX_ANNOTATION_SIZE 64
32 struct dcerpc_binding_vector {
33 struct dcerpc_binding **bindings;
34 uint32_t count;
35 uint32_t allocated;
38 static bool binding_vector_realloc(struct dcerpc_binding_vector *bvec)
40 if (bvec->count >= bvec->allocated) {
41 struct dcerpc_binding **tmp;
43 tmp = talloc_realloc(bvec,
44 bvec->bindings,
45 struct dcerpc_binding *,
46 bvec->allocated * 2);
47 if (tmp == NULL) {
48 return false;
50 bvec->bindings = tmp;
51 bvec->allocated = bvec->allocated * 2;
54 return true;
57 NTSTATUS dcerpc_binding_vector_new(TALLOC_CTX *mem_ctx,
58 struct dcerpc_binding_vector **pbvec)
60 struct dcerpc_binding_vector *bvec;
61 NTSTATUS status;
62 TALLOC_CTX *tmp_ctx;
64 tmp_ctx = talloc_stackframe();
65 if (tmp_ctx == NULL) {
66 return NT_STATUS_NO_MEMORY;
69 bvec = talloc_zero(tmp_ctx, struct dcerpc_binding_vector);
70 if (bvec == NULL) {
71 status = NT_STATUS_NO_MEMORY;
72 goto done;
75 bvec->bindings = talloc_zero_array(bvec,
76 struct dcerpc_binding *,
77 4);
78 if (bvec->bindings == NULL) {
79 status = NT_STATUS_NO_MEMORY;
80 goto done;
83 bvec->allocated = 4;
84 bvec->count = 0;
86 *pbvec = talloc_move(mem_ctx, &bvec);
88 status = NT_STATUS_OK;
89 done:
90 talloc_free(tmp_ctx);
92 return status;
95 NTSTATUS dcerpc_binding_vector_add_np_default(const struct ndr_interface_table *iface,
96 struct dcerpc_binding_vector *bvec)
98 uint32_t ep_count = iface->endpoints->count;
99 uint32_t i;
100 NTSTATUS status;
101 bool ok;
103 for (i = 0; i < ep_count; i++) {
104 struct dcerpc_binding *b;
105 enum dcerpc_transport_t transport;
106 char *unc = NULL;
108 status = dcerpc_parse_binding(bvec->bindings,
109 iface->endpoints->names[i],
110 &b);
111 if (!NT_STATUS_IS_OK(status)) {
112 return NT_STATUS_UNSUCCESSFUL;
115 /* Only add the named pipes defined in the iface endpoints */
116 transport = dcerpc_binding_get_transport(b);
117 if (transport != NCACN_NP) {
118 talloc_free(b);
119 continue;
122 status = dcerpc_binding_set_abstract_syntax(b, &iface->syntax_id);
123 if (!NT_STATUS_IS_OK(status)) {
124 talloc_free(b);
125 return NT_STATUS_UNSUCCESSFUL;
128 unc = talloc_asprintf(b, "\\\\%s", lp_netbios_name());
129 if (unc == NULL) {
130 talloc_free(b);
131 return NT_STATUS_NO_MEMORY;
134 status = dcerpc_binding_set_string_option(b, "host", unc);
135 TALLOC_FREE(unc);
136 if (!NT_STATUS_IS_OK(status)) {
137 talloc_free(b);
138 return NT_STATUS_NO_MEMORY;
141 ok = binding_vector_realloc(bvec);
142 if (!ok) {
143 talloc_free(b);
144 return NT_STATUS_NO_MEMORY;
147 bvec->bindings[bvec->count] = b;
148 bvec->count++;
151 return NT_STATUS_OK;
154 NTSTATUS dcerpc_binding_vector_add_port(const struct ndr_interface_table *iface,
155 struct dcerpc_binding_vector *bvec,
156 const char *host,
157 uint16_t _port)
159 uint32_t ep_count = iface->endpoints->count;
160 uint32_t i;
161 NTSTATUS status;
162 bool ok;
163 char port[6];
165 snprintf(port, sizeof(port), "%u", _port);
167 for (i = 0; i < ep_count; i++) {
168 struct dcerpc_binding *b;
169 enum dcerpc_transport_t transport;
171 status = dcerpc_parse_binding(bvec->bindings,
172 iface->endpoints->names[i],
173 &b);
174 if (!NT_STATUS_IS_OK(status)) {
175 return NT_STATUS_UNSUCCESSFUL;
178 transport = dcerpc_binding_get_transport(b);
179 if (transport != NCACN_IP_TCP) {
180 talloc_free(b);
181 continue;
184 status = dcerpc_binding_set_abstract_syntax(b, &iface->syntax_id);
185 if (!NT_STATUS_IS_OK(status)) {
186 talloc_free(b);
187 return NT_STATUS_UNSUCCESSFUL;
190 status = dcerpc_binding_set_string_option(b, "host", host);
191 if (!NT_STATUS_IS_OK(status)) {
192 talloc_free(b);
193 return NT_STATUS_UNSUCCESSFUL;
196 status = dcerpc_binding_set_string_option(b, "endpoint", port);
197 if (!NT_STATUS_IS_OK(status)) {
198 talloc_free(b);
199 return NT_STATUS_UNSUCCESSFUL;
202 ok = binding_vector_realloc(bvec);
203 if (!ok) {
204 talloc_free(b);
205 return NT_STATUS_NO_MEMORY;
208 bvec->bindings[bvec->count] = b;
209 bvec->count++;
211 break;
214 return NT_STATUS_OK;
217 NTSTATUS dcerpc_binding_vector_add_unix(const struct ndr_interface_table *iface,
218 struct dcerpc_binding_vector *bvec,
219 const char *name)
221 uint32_t ep_count = iface->endpoints->count;
222 uint32_t i;
223 NTSTATUS status;
224 bool ok;
226 for (i = 0; i < ep_count; i++) {
227 struct dcerpc_binding *b;
228 enum dcerpc_transport_t transport;
229 char *endpoint = NULL;
231 status = dcerpc_parse_binding(bvec->bindings,
232 iface->endpoints->names[i],
233 &b);
234 if (!NT_STATUS_IS_OK(status)) {
235 return NT_STATUS_UNSUCCESSFUL;
238 transport = dcerpc_binding_get_transport(b);
239 if (transport != NCALRPC) {
240 talloc_free(b);
241 continue;
244 status = dcerpc_binding_set_abstract_syntax(b, &iface->syntax_id);
245 if (!NT_STATUS_IS_OK(status)) {
246 talloc_free(b);
247 return NT_STATUS_UNSUCCESSFUL;
250 endpoint = talloc_asprintf(b,
251 "%s/%s",
252 lp_ncalrpc_dir(),
253 name);
254 if (endpoint == NULL) {
255 talloc_free(b);
256 return NT_STATUS_NO_MEMORY;
259 status = dcerpc_binding_set_string_option(b, "endpoint", endpoint);
260 TALLOC_FREE(endpoint);
261 if (!NT_STATUS_IS_OK(status)) {
262 talloc_free(b);
263 return NT_STATUS_UNSUCCESSFUL;
266 ok = binding_vector_realloc(bvec);
267 if (!ok) {
268 talloc_free(b);
269 return NT_STATUS_NO_MEMORY;
272 bvec->bindings[bvec->count] = b;
273 bvec->count++;
275 break;
278 return NT_STATUS_OK;
281 NTSTATUS dcerpc_binding_vector_replace_iface(const struct ndr_interface_table *iface,
282 struct dcerpc_binding_vector *v)
284 uint32_t i;
286 for (i = 0; i < v->count; i++) {
287 struct dcerpc_binding *b = v->bindings[i];
288 NTSTATUS status;
290 status = dcerpc_binding_set_abstract_syntax(b,
291 &iface->syntax_id);
292 if (!NT_STATUS_IS_OK(status)) {
293 return status;
297 return NT_STATUS_OK;
300 struct dcerpc_binding_vector *dcerpc_binding_vector_dup(TALLOC_CTX *mem_ctx,
301 const struct dcerpc_binding_vector *bvec)
303 struct dcerpc_binding_vector *v;
304 uint32_t i;
306 v = talloc(mem_ctx, struct dcerpc_binding_vector);
307 if (v == NULL) {
308 return NULL;
311 v->bindings = talloc_array(v, struct dcerpc_binding *, bvec->allocated);
312 if (v->bindings == NULL) {
313 talloc_free(v);
314 return NULL;
316 v->allocated = bvec->allocated;
318 for (i = 0; i < bvec->count; i++) {
319 struct dcerpc_binding *b;
321 b = dcerpc_binding_dup(v->bindings, bvec->bindings[i]);
322 if (b == NULL) {
323 talloc_free(v);
324 return NULL;
326 v->bindings[i] = b;
328 v->count = bvec->count;
330 return v;
333 static NTSTATUS ep_register(TALLOC_CTX *mem_ctx,
334 struct messaging_context *msg_ctx,
335 const struct ndr_interface_table *iface,
336 const struct dcerpc_binding_vector *bind_vec,
337 const struct GUID *object_guid,
338 const char *annotation,
339 uint32_t replace,
340 uint32_t unregister,
341 struct dcerpc_binding_handle **pbh)
343 struct rpc_pipe_client *cli = NULL;
344 struct dcerpc_binding_handle *h;
345 struct pipe_auth_data *auth;
346 const char *ncalrpc_sock;
347 enum rpc_service_mode_e epmd_mode;
348 struct epm_entry_t *entries;
349 uint32_t num_ents, i;
350 TALLOC_CTX *tmp_ctx;
351 uint32_t result = EPMAPPER_STATUS_OK;
352 NTSTATUS status;
354 if (iface == NULL) {
355 return NT_STATUS_INVALID_PARAMETER;
358 if (bind_vec == NULL || bind_vec->count == 0) {
359 return NT_STATUS_INVALID_PARAMETER;
362 tmp_ctx = talloc_stackframe();
363 if (tmp_ctx == NULL) {
364 return NT_STATUS_NO_MEMORY;
367 epmd_mode = rpc_epmapper_mode();
369 if (epmd_mode == RPC_SERVICE_MODE_EMBEDDED) {
370 struct tsocket_address *local;
371 int rc;
373 rc = tsocket_address_inet_from_strings(tmp_ctx,
374 "ip",
375 "127.0.0.1",
377 &local);
378 if (rc < 0) {
379 return NT_STATUS_NO_MEMORY;
382 status = rpcint_binding_handle(tmp_ctx,
383 &ndr_table_epmapper,
384 local,
385 get_session_info_system(),
386 msg_ctx,
387 &h);
388 if (!NT_STATUS_IS_OK(status)) {
389 DEBUG(1, ("dcerpc_ep_register: Could not connect to "
390 "epmapper (%s)", nt_errstr(status)));
391 goto done;
393 } else if (epmd_mode == RPC_SERVICE_MODE_EXTERNAL) {
394 /* Connect to the endpoint mapper locally */
395 ncalrpc_sock = talloc_asprintf(tmp_ctx,
396 "%s/%s",
397 lp_ncalrpc_dir(),
398 "EPMAPPER");
399 if (ncalrpc_sock == NULL) {
400 status = NT_STATUS_NO_MEMORY;
401 goto done;
404 status = rpc_pipe_open_ncalrpc(tmp_ctx,
405 ncalrpc_sock,
406 &ndr_table_epmapper,
407 &cli);
408 if (!NT_STATUS_IS_OK(status)) {
409 goto done;
412 status = rpccli_ncalrpc_bind_data(cli, &auth);
413 if (!NT_STATUS_IS_OK(status)) {
414 DEBUG(0, ("Failed to initialize anonymous bind.\n"));
415 goto done;
418 status = rpc_pipe_bind(cli, auth);
419 if (!NT_STATUS_IS_OK(status)) {
420 DEBUG(2, ("Failed to bind ncalrpc socket.\n"));
421 goto done;
424 h = cli->binding_handle;
425 } else {
426 status = NT_STATUS_INVALID_PARAMETER;
427 goto done;
430 num_ents = bind_vec->count;
431 entries = talloc_array(tmp_ctx, struct epm_entry_t, num_ents);
433 for (i = 0; i < num_ents; i++) {
434 struct dcerpc_binding *map_binding;
435 struct epm_twr_t *map_tower;
437 map_binding = dcerpc_binding_dup(entries, bind_vec->bindings[i]);
438 if (map_binding == NULL) {
439 status = NT_STATUS_NO_MEMORY;
440 goto done;
443 status = dcerpc_binding_set_abstract_syntax(map_binding,
444 &iface->syntax_id);
445 if (!NT_STATUS_IS_OK(status)) {
446 goto done;
449 map_tower = talloc_zero(entries, struct epm_twr_t);
450 if (map_tower == NULL) {
451 status = NT_STATUS_NO_MEMORY;
452 goto done;
455 status = dcerpc_binding_build_tower(entries,
456 map_binding,
457 &map_tower->tower);
458 if (!NT_STATUS_IS_OK(status)) {
459 goto done;
462 TALLOC_FREE(map_binding);
464 entries[i].tower = map_tower;
465 if (annotation == NULL) {
466 entries[i].annotation = talloc_strdup(entries, "");
467 } else {
468 entries[i].annotation = talloc_strndup(entries,
469 annotation,
470 EPM_MAX_ANNOTATION_SIZE);
472 if (entries[i].annotation == NULL) {
473 status = NT_STATUS_NO_MEMORY;
474 goto done;
477 if (object_guid != NULL) {
478 entries[i].object = *object_guid;
479 } else {
480 ZERO_STRUCT(entries[i].object);
484 if (unregister) {
485 status = dcerpc_epm_Delete(h,
486 tmp_ctx,
487 num_ents,
488 entries,
489 &result);
490 } else {
491 status = dcerpc_epm_Insert(h,
492 tmp_ctx,
493 num_ents,
494 entries,
495 replace,
496 &result);
498 if (!NT_STATUS_IS_OK(status)) {
499 DEBUG(0, ("dcerpc_ep_register: Could not insert tower (%s)\n",
500 nt_errstr(status)));
501 goto done;
503 if (result != EPMAPPER_STATUS_OK) {
504 DEBUG(0, ("dcerpc_ep_register: Could not insert tower (0x%.8x)\n",
505 result));
506 status = NT_STATUS_UNSUCCESSFUL;
507 goto done;
510 if (pbh != NULL) {
511 *pbh = talloc_move(mem_ctx, &h);
512 talloc_steal(*pbh, cli);
515 done:
516 talloc_free(tmp_ctx);
518 return status;
521 NTSTATUS dcerpc_ep_register(TALLOC_CTX *mem_ctx,
522 struct messaging_context *msg_ctx,
523 const struct ndr_interface_table *iface,
524 const struct dcerpc_binding_vector *bind_vec,
525 const struct GUID *object_guid,
526 const char *annotation,
527 struct dcerpc_binding_handle **ph)
529 return ep_register(mem_ctx,
530 msg_ctx,
531 iface,
532 bind_vec,
533 object_guid,
534 annotation,
537 ph);
540 NTSTATUS dcerpc_ep_register_noreplace(TALLOC_CTX *mem_ctx,
541 struct messaging_context *msg_ctx,
542 const struct ndr_interface_table *iface,
543 const struct dcerpc_binding_vector *bind_vec,
544 const struct GUID *object_guid,
545 const char *annotation,
546 struct dcerpc_binding_handle **ph)
548 return ep_register(mem_ctx,
549 msg_ctx,
550 iface,
551 bind_vec,
552 object_guid,
553 annotation,
556 ph);
559 NTSTATUS dcerpc_ep_unregister(struct messaging_context *msg_ctx,
560 const struct ndr_interface_table *iface,
561 const struct dcerpc_binding_vector *bind_vec,
562 const struct GUID *object_guid)
564 return ep_register(NULL,
565 msg_ctx,
566 iface,
567 bind_vec,
568 object_guid,
569 NULL,
572 NULL);
575 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */