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/>.
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"
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
;
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
,
45 struct dcerpc_binding
*,
51 bvec
->allocated
= bvec
->allocated
* 2;
57 NTSTATUS
dcerpc_binding_vector_new(TALLOC_CTX
*mem_ctx
,
58 struct dcerpc_binding_vector
**pbvec
)
60 struct dcerpc_binding_vector
*bvec
;
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
);
71 status
= NT_STATUS_NO_MEMORY
;
75 bvec
->bindings
= talloc_zero_array(bvec
,
76 struct dcerpc_binding
*,
78 if (bvec
->bindings
== NULL
) {
79 status
= NT_STATUS_NO_MEMORY
;
86 *pbvec
= talloc_move(mem_ctx
, &bvec
);
88 status
= NT_STATUS_OK
;
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
;
103 for (i
= 0; i
< ep_count
; i
++) {
104 struct dcerpc_binding
*b
;
105 enum dcerpc_transport_t transport
;
108 status
= dcerpc_parse_binding(bvec
->bindings
,
109 iface
->endpoints
->names
[i
],
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
) {
122 status
= dcerpc_binding_set_abstract_syntax(b
, &iface
->syntax_id
);
123 if (!NT_STATUS_IS_OK(status
)) {
125 return NT_STATUS_UNSUCCESSFUL
;
128 unc
= talloc_asprintf(b
, "\\\\%s", lp_netbios_name());
131 return NT_STATUS_NO_MEMORY
;
134 status
= dcerpc_binding_set_string_option(b
, "host", unc
);
136 if (!NT_STATUS_IS_OK(status
)) {
138 return NT_STATUS_NO_MEMORY
;
141 ok
= binding_vector_realloc(bvec
);
144 return NT_STATUS_NO_MEMORY
;
147 bvec
->bindings
[bvec
->count
] = b
;
154 NTSTATUS
dcerpc_binding_vector_add_port(const struct ndr_interface_table
*iface
,
155 struct dcerpc_binding_vector
*bvec
,
159 uint32_t ep_count
= iface
->endpoints
->count
;
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
],
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
) {
184 status
= dcerpc_binding_set_abstract_syntax(b
, &iface
->syntax_id
);
185 if (!NT_STATUS_IS_OK(status
)) {
187 return NT_STATUS_UNSUCCESSFUL
;
190 status
= dcerpc_binding_set_string_option(b
, "host", host
);
191 if (!NT_STATUS_IS_OK(status
)) {
193 return NT_STATUS_UNSUCCESSFUL
;
196 status
= dcerpc_binding_set_string_option(b
, "endpoint", port
);
197 if (!NT_STATUS_IS_OK(status
)) {
199 return NT_STATUS_UNSUCCESSFUL
;
202 ok
= binding_vector_realloc(bvec
);
205 return NT_STATUS_NO_MEMORY
;
208 bvec
->bindings
[bvec
->count
] = b
;
217 NTSTATUS
dcerpc_binding_vector_add_unix(const struct ndr_interface_table
*iface
,
218 struct dcerpc_binding_vector
*bvec
,
221 uint32_t ep_count
= iface
->endpoints
->count
;
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
],
234 if (!NT_STATUS_IS_OK(status
)) {
235 return NT_STATUS_UNSUCCESSFUL
;
238 transport
= dcerpc_binding_get_transport(b
);
239 if (transport
!= NCALRPC
) {
244 status
= dcerpc_binding_set_abstract_syntax(b
, &iface
->syntax_id
);
245 if (!NT_STATUS_IS_OK(status
)) {
247 return NT_STATUS_UNSUCCESSFUL
;
250 endpoint
= talloc_asprintf(b
,
254 if (endpoint
== NULL
) {
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
)) {
263 return NT_STATUS_UNSUCCESSFUL
;
266 ok
= binding_vector_realloc(bvec
);
269 return NT_STATUS_NO_MEMORY
;
272 bvec
->bindings
[bvec
->count
] = b
;
281 NTSTATUS
dcerpc_binding_vector_replace_iface(const struct ndr_interface_table
*iface
,
282 struct dcerpc_binding_vector
*v
)
286 for (i
= 0; i
< v
->count
; i
++) {
287 struct dcerpc_binding
*b
= v
->bindings
[i
];
290 status
= dcerpc_binding_set_abstract_syntax(b
,
292 if (!NT_STATUS_IS_OK(status
)) {
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
;
306 v
= talloc(mem_ctx
, struct dcerpc_binding_vector
);
311 v
->bindings
= talloc_array(v
, struct dcerpc_binding
*, bvec
->allocated
);
312 if (v
->bindings
== 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
]);
328 v
->count
= bvec
->count
;
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
,
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
;
351 uint32_t result
= EPMAPPER_STATUS_OK
;
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
;
373 rc
= tsocket_address_inet_from_strings(tmp_ctx
,
379 return NT_STATUS_NO_MEMORY
;
382 status
= rpcint_binding_handle(tmp_ctx
,
385 get_session_info_system(),
388 if (!NT_STATUS_IS_OK(status
)) {
389 DEBUG(1, ("dcerpc_ep_register: Could not connect to "
390 "epmapper (%s)", nt_errstr(status
)));
393 } else if (epmd_mode
== RPC_SERVICE_MODE_EXTERNAL
) {
394 /* Connect to the endpoint mapper locally */
395 ncalrpc_sock
= talloc_asprintf(tmp_ctx
,
399 if (ncalrpc_sock
== NULL
) {
400 status
= NT_STATUS_NO_MEMORY
;
404 status
= rpc_pipe_open_ncalrpc(tmp_ctx
,
408 if (!NT_STATUS_IS_OK(status
)) {
412 status
= rpccli_ncalrpc_bind_data(cli
, &auth
);
413 if (!NT_STATUS_IS_OK(status
)) {
414 DEBUG(0, ("Failed to initialize anonymous bind.\n"));
418 status
= rpc_pipe_bind(cli
, auth
);
419 if (!NT_STATUS_IS_OK(status
)) {
420 DEBUG(2, ("Failed to bind ncalrpc socket.\n"));
424 h
= cli
->binding_handle
;
426 status
= NT_STATUS_INVALID_PARAMETER
;
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
;
443 status
= dcerpc_binding_set_abstract_syntax(map_binding
,
445 if (!NT_STATUS_IS_OK(status
)) {
449 map_tower
= talloc_zero(entries
, struct epm_twr_t
);
450 if (map_tower
== NULL
) {
451 status
= NT_STATUS_NO_MEMORY
;
455 status
= dcerpc_binding_build_tower(entries
,
458 if (!NT_STATUS_IS_OK(status
)) {
462 TALLOC_FREE(map_binding
);
464 entries
[i
].tower
= map_tower
;
465 if (annotation
== NULL
) {
466 entries
[i
].annotation
= talloc_strdup(entries
, "");
468 entries
[i
].annotation
= talloc_strndup(entries
,
470 EPM_MAX_ANNOTATION_SIZE
);
472 if (entries
[i
].annotation
== NULL
) {
473 status
= NT_STATUS_NO_MEMORY
;
477 if (object_guid
!= NULL
) {
478 entries
[i
].object
= *object_guid
;
480 ZERO_STRUCT(entries
[i
].object
);
485 status
= dcerpc_epm_Delete(h
,
491 status
= dcerpc_epm_Insert(h
,
498 if (!NT_STATUS_IS_OK(status
)) {
499 DEBUG(0, ("dcerpc_ep_register: Could not insert tower (%s)\n",
503 if (result
!= EPMAPPER_STATUS_OK
) {
504 DEBUG(0, ("dcerpc_ep_register: Could not insert tower (0x%.8x)\n",
506 status
= NT_STATUS_UNSUCCESSFUL
;
511 *pbh
= talloc_move(mem_ctx
, &h
);
512 talloc_steal(*pbh
, cli
);
516 talloc_free(tmp_ctx
);
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
,
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
,
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
,
575 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */