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 static bool binding_vector_realloc(struct dcerpc_binding_vector
*bvec
)
34 if (bvec
->count
>= bvec
->allocated
) {
35 struct dcerpc_binding
*tmp
;
37 tmp
= talloc_realloc(bvec
,
39 struct dcerpc_binding
,
45 bvec
->allocated
= bvec
->allocated
* 2;
51 NTSTATUS
dcerpc_binding_vector_new(TALLOC_CTX
*mem_ctx
,
52 struct dcerpc_binding_vector
**pbvec
)
54 struct dcerpc_binding_vector
*bvec
;
58 tmp_ctx
= talloc_stackframe();
59 if (tmp_ctx
== NULL
) {
60 return NT_STATUS_NO_MEMORY
;
63 bvec
= talloc_zero(tmp_ctx
, struct dcerpc_binding_vector
);
65 status
= NT_STATUS_NO_MEMORY
;
69 bvec
->bindings
= talloc_zero_array(bvec
,
70 struct dcerpc_binding
,
72 if (bvec
->bindings
== NULL
) {
73 status
= NT_STATUS_NO_MEMORY
;
80 *pbvec
= talloc_move(mem_ctx
, &bvec
);
82 status
= NT_STATUS_OK
;
89 NTSTATUS
dcerpc_binding_vector_add_np_default(const struct ndr_interface_table
*iface
,
90 struct dcerpc_binding_vector
*bvec
)
92 uint32_t ep_count
= iface
->endpoints
->count
;
97 for (i
= 0; i
< ep_count
; i
++) {
98 struct dcerpc_binding
*b
;
100 b
= talloc_zero(bvec
->bindings
, struct dcerpc_binding
);
102 return NT_STATUS_NO_MEMORY
;
105 status
= dcerpc_parse_binding(b
, iface
->endpoints
->names
[i
], &b
);
106 if (!NT_STATUS_IS_OK(status
)) {
107 return NT_STATUS_UNSUCCESSFUL
;
110 /* Only add the named pipes defined in the iface endpoints */
111 if (b
->transport
!= NCACN_NP
) {
116 b
->object
= iface
->syntax_id
;
118 b
->host
= talloc_asprintf(b
, "\\\\%s", lp_netbios_name());
119 if (b
->host
== NULL
) {
121 return NT_STATUS_NO_MEMORY
;
124 ok
= binding_vector_realloc(bvec
);
127 return NT_STATUS_NO_MEMORY
;
130 bvec
->bindings
[bvec
->count
] = *b
;
137 NTSTATUS
dcerpc_binding_vector_add_port(const struct ndr_interface_table
*iface
,
138 struct dcerpc_binding_vector
*bvec
,
142 uint32_t ep_count
= iface
->endpoints
->count
;
147 for (i
= 0; i
< ep_count
; i
++) {
148 struct dcerpc_binding
*b
;
150 b
= talloc_zero(bvec
->bindings
, struct dcerpc_binding
);
152 return NT_STATUS_NO_MEMORY
;
155 status
= dcerpc_parse_binding(b
, iface
->endpoints
->names
[i
], &b
);
156 if (!NT_STATUS_IS_OK(status
)) {
157 return NT_STATUS_UNSUCCESSFUL
;
160 if (b
->transport
!= NCACN_IP_TCP
) {
165 b
->object
= iface
->syntax_id
;
167 b
->host
= talloc_strdup(b
, host
);
168 if (b
->host
== NULL
) {
170 return NT_STATUS_NO_MEMORY
;
173 b
->endpoint
= talloc_asprintf(b
, "%u", port
);
174 if (b
->endpoint
== NULL
) {
176 return NT_STATUS_NO_MEMORY
;
179 ok
= binding_vector_realloc(bvec
);
182 return NT_STATUS_NO_MEMORY
;
185 bvec
->bindings
[bvec
->count
] = *b
;
194 NTSTATUS
dcerpc_binding_vector_add_unix(const struct ndr_interface_table
*iface
,
195 struct dcerpc_binding_vector
*bvec
,
198 uint32_t ep_count
= iface
->endpoints
->count
;
203 for (i
= 0; i
< ep_count
; i
++) {
204 struct dcerpc_binding
*b
;
206 b
= talloc_zero(bvec
->bindings
, struct dcerpc_binding
);
208 return NT_STATUS_NO_MEMORY
;
211 status
= dcerpc_parse_binding(b
, iface
->endpoints
->names
[i
], &b
);
212 if (!NT_STATUS_IS_OK(status
)) {
213 return NT_STATUS_UNSUCCESSFUL
;
216 if (b
->transport
!= NCALRPC
) {
221 b
->object
= iface
->syntax_id
;
223 b
->endpoint
= talloc_asprintf(b
,
227 if (b
->endpoint
== NULL
) {
229 return NT_STATUS_NO_MEMORY
;
232 ok
= binding_vector_realloc(bvec
);
235 return NT_STATUS_NO_MEMORY
;
238 bvec
->bindings
[bvec
->count
] = *b
;
247 NTSTATUS
dcerpc_binding_vector_replace_iface(const struct ndr_interface_table
*iface
,
248 struct dcerpc_binding_vector
*v
)
252 for (i
= 0; i
< v
->count
; i
++) {
253 struct dcerpc_binding
*b
;
255 b
= &(v
->bindings
[i
]);
256 b
->object
= iface
->syntax_id
;
262 struct dcerpc_binding_vector
*dcerpc_binding_vector_dup(TALLOC_CTX
*mem_ctx
,
263 const struct dcerpc_binding_vector
*bvec
)
265 struct dcerpc_binding_vector
*v
;
268 v
= talloc(mem_ctx
, struct dcerpc_binding_vector
);
273 v
->bindings
= talloc_array(v
, struct dcerpc_binding
, bvec
->allocated
);
274 if (v
->bindings
== NULL
) {
278 v
->allocated
= bvec
->allocated
;
280 for (i
= 0; i
< bvec
->count
; i
++) {
281 struct dcerpc_binding
*b
;
283 b
= dcerpc_binding_dup(v
->bindings
, &bvec
->bindings
[i
]);
290 v
->count
= bvec
->count
;
295 static NTSTATUS
ep_register(TALLOC_CTX
*mem_ctx
,
296 struct messaging_context
*msg_ctx
,
297 const struct ndr_interface_table
*iface
,
298 const struct dcerpc_binding_vector
*bind_vec
,
299 const struct GUID
*object_guid
,
300 const char *annotation
,
303 struct dcerpc_binding_handle
**pbh
)
305 struct rpc_pipe_client
*cli
= NULL
;
306 struct dcerpc_binding_handle
*h
;
307 struct pipe_auth_data
*auth
;
308 const char *ncalrpc_sock
;
309 enum rpc_service_mode_e epmd_mode
;
310 struct epm_entry_t
*entries
;
311 uint32_t num_ents
, i
;
313 uint32_t result
= EPMAPPER_STATUS_OK
;
317 return NT_STATUS_INVALID_PARAMETER
;
320 if (bind_vec
== NULL
|| bind_vec
->count
== 0) {
321 return NT_STATUS_INVALID_PARAMETER
;
324 tmp_ctx
= talloc_stackframe();
325 if (tmp_ctx
== NULL
) {
326 return NT_STATUS_NO_MEMORY
;
329 epmd_mode
= rpc_epmapper_mode();
331 if (epmd_mode
== RPC_SERVICE_MODE_EMBEDDED
) {
332 struct tsocket_address
*local
;
335 rc
= tsocket_address_inet_from_strings(tmp_ctx
,
341 return NT_STATUS_NO_MEMORY
;
344 status
= rpcint_binding_handle(tmp_ctx
,
347 get_session_info_system(),
350 if (!NT_STATUS_IS_OK(status
)) {
351 DEBUG(1, ("dcerpc_ep_register: Could not connect to "
352 "epmapper (%s)", nt_errstr(status
)));
355 } else if (epmd_mode
== RPC_SERVICE_MODE_EXTERNAL
) {
356 /* Connect to the endpoint mapper locally */
357 ncalrpc_sock
= talloc_asprintf(tmp_ctx
,
361 if (ncalrpc_sock
== NULL
) {
362 status
= NT_STATUS_NO_MEMORY
;
366 status
= rpc_pipe_open_ncalrpc(tmp_ctx
,
368 &ndr_table_epmapper
.syntax_id
,
370 if (!NT_STATUS_IS_OK(status
)) {
374 status
= rpccli_ncalrpc_bind_data(cli
, &auth
);
375 if (!NT_STATUS_IS_OK(status
)) {
376 DEBUG(0, ("Failed to initialize anonymous bind.\n"));
380 status
= rpc_pipe_bind(cli
, auth
);
381 if (!NT_STATUS_IS_OK(status
)) {
382 DEBUG(2, ("Failed to bind ncalrpc socket.\n"));
386 h
= cli
->binding_handle
;
388 status
= NT_STATUS_INVALID_PARAMETER
;
392 num_ents
= bind_vec
->count
;
393 entries
= talloc_array(tmp_ctx
, struct epm_entry_t
, num_ents
);
395 for (i
= 0; i
< num_ents
; i
++) {
396 struct dcerpc_binding
*map_binding
= &bind_vec
->bindings
[i
];
397 struct epm_twr_t
*map_tower
;
399 map_tower
= talloc_zero(entries
, struct epm_twr_t
);
400 if (map_tower
== NULL
) {
401 status
= NT_STATUS_NO_MEMORY
;
405 status
= dcerpc_binding_build_tower(entries
,
408 if (!NT_STATUS_IS_OK(status
)) {
412 entries
[i
].tower
= map_tower
;
413 if (annotation
== NULL
) {
414 entries
[i
].annotation
= talloc_strdup(entries
, "");
416 entries
[i
].annotation
= talloc_strndup(entries
,
418 EPM_MAX_ANNOTATION_SIZE
);
420 if (entries
[i
].annotation
== NULL
) {
421 status
= NT_STATUS_NO_MEMORY
;
425 if (object_guid
!= NULL
) {
426 entries
[i
].object
= *object_guid
;
428 entries
[i
].object
= map_binding
->object
.uuid
;
433 status
= dcerpc_epm_Delete(h
,
439 status
= dcerpc_epm_Insert(h
,
446 if (!NT_STATUS_IS_OK(status
)) {
447 DEBUG(0, ("dcerpc_ep_register: Could not insert tower (%s)\n",
451 if (result
!= EPMAPPER_STATUS_OK
) {
452 DEBUG(0, ("dcerpc_ep_register: Could not insert tower (0x%.8x)\n",
454 status
= NT_STATUS_UNSUCCESSFUL
;
459 *pbh
= talloc_move(mem_ctx
, &h
);
460 talloc_steal(*pbh
, cli
);
464 talloc_free(tmp_ctx
);
469 NTSTATUS
dcerpc_ep_register(TALLOC_CTX
*mem_ctx
,
470 struct messaging_context
*msg_ctx
,
471 const struct ndr_interface_table
*iface
,
472 const struct dcerpc_binding_vector
*bind_vec
,
473 const struct GUID
*object_guid
,
474 const char *annotation
,
475 struct dcerpc_binding_handle
**ph
)
477 return ep_register(mem_ctx
,
488 NTSTATUS
dcerpc_ep_register_noreplace(TALLOC_CTX
*mem_ctx
,
489 struct messaging_context
*msg_ctx
,
490 const struct ndr_interface_table
*iface
,
491 const struct dcerpc_binding_vector
*bind_vec
,
492 const struct GUID
*object_guid
,
493 const char *annotation
,
494 struct dcerpc_binding_handle
**ph
)
496 return ep_register(mem_ctx
,
507 NTSTATUS
dcerpc_ep_unregister(struct messaging_context
*msg_ctx
,
508 const struct ndr_interface_table
*iface
,
509 const struct dcerpc_binding_vector
*bind_vec
,
510 const struct GUID
*object_guid
)
512 return ep_register(NULL
,
523 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */