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"
29 #define EPM_MAX_ANNOTATION_SIZE 64
31 static bool binding_vector_realloc(struct dcerpc_binding_vector
*bvec
)
33 if (bvec
->count
>= bvec
->allocated
) {
34 struct dcerpc_binding
*tmp
;
36 tmp
= talloc_realloc(bvec
,
38 struct dcerpc_binding
,
44 bvec
->allocated
= bvec
->allocated
* 2;
50 NTSTATUS
dcerpc_binding_vector_new(TALLOC_CTX
*mem_ctx
,
51 struct dcerpc_binding_vector
**pbvec
)
53 struct dcerpc_binding_vector
*bvec
;
57 tmp_ctx
= talloc_stackframe();
58 if (tmp_ctx
== NULL
) {
59 return NT_STATUS_NO_MEMORY
;
62 bvec
= talloc_zero(tmp_ctx
, struct dcerpc_binding_vector
);
64 status
= NT_STATUS_NO_MEMORY
;
68 bvec
->bindings
= talloc_zero_array(bvec
,
69 struct dcerpc_binding
,
71 if (bvec
->bindings
== NULL
) {
72 status
= NT_STATUS_NO_MEMORY
;
79 *pbvec
= talloc_move(mem_ctx
, &bvec
);
81 status
= NT_STATUS_OK
;
88 NTSTATUS
dcerpc_binding_vector_add_np_default(const struct ndr_interface_table
*iface
,
89 struct dcerpc_binding_vector
*bvec
)
91 uint32_t ep_count
= iface
->endpoints
->count
;
96 for (i
= 0; i
< ep_count
; i
++) {
97 struct dcerpc_binding
*b
;
99 b
= talloc_zero(bvec
->bindings
, struct dcerpc_binding
);
101 return NT_STATUS_NO_MEMORY
;
104 status
= dcerpc_parse_binding(b
, iface
->endpoints
->names
[i
], &b
);
105 if (!NT_STATUS_IS_OK(status
)) {
106 return NT_STATUS_UNSUCCESSFUL
;
109 /* Only add the named pipes defined in the iface endpoints */
110 if (b
->transport
!= NCACN_NP
) {
115 b
->object
= iface
->syntax_id
;
117 b
->host
= talloc_asprintf(b
, "\\\\%s", lp_netbios_name());
118 if (b
->host
== NULL
) {
120 return NT_STATUS_NO_MEMORY
;
123 ok
= binding_vector_realloc(bvec
);
126 return NT_STATUS_NO_MEMORY
;
129 bvec
->bindings
[bvec
->count
] = *b
;
136 NTSTATUS
dcerpc_binding_vector_create(TALLOC_CTX
*mem_ctx
,
137 const struct ndr_interface_table
*iface
,
140 struct dcerpc_binding_vector
**pbvec
)
142 struct dcerpc_binding_vector
*bvec
;
149 tmp_ctx
= talloc_stackframe();
150 if (tmp_ctx
== NULL
) {
151 return NT_STATUS_NO_MEMORY
;
154 ep_count
= iface
->endpoints
->count
;
156 bvec
= talloc_zero(tmp_ctx
, struct dcerpc_binding_vector
);
158 status
= NT_STATUS_NO_MEMORY
;
162 bvec
->bindings
= talloc_zero_array(bvec
, struct dcerpc_binding
, ep_count
);
163 if (bvec
->bindings
== NULL
) {
164 status
= NT_STATUS_NO_MEMORY
;
168 for (i
= 0; i
< ep_count
; i
++) {
169 struct dcerpc_binding
*b
;
171 b
= talloc_zero(bvec
->bindings
, struct dcerpc_binding
);
173 status
= NT_STATUS_NO_MEMORY
;
177 status
= dcerpc_parse_binding(b
, iface
->endpoints
->names
[i
], &b
);
178 if (!NT_STATUS_IS_OK(status
)) {
179 status
= NT_STATUS_UNSUCCESSFUL
;
183 b
->object
= iface
->syntax_id
;
185 switch (b
->transport
) {
187 b
->host
= talloc_asprintf(b
, "\\\\%s", lp_netbios_name());
188 if (b
->host
== NULL
) {
189 status
= NT_STATUS_NO_MEMORY
;
199 b
->endpoint
= talloc_asprintf(b
, "%u", port
);
200 if (b
->endpoint
== NULL
) {
201 status
= NT_STATUS_NO_MEMORY
;
207 if (ncalrpc
== NULL
) {
212 b
->endpoint
= talloc_asprintf(b
,
216 if (b
->endpoint
== NULL
) {
217 status
= NT_STATUS_NO_MEMORY
;
226 bvec
->bindings
[count
] = *b
;
232 *pbvec
= talloc_move(mem_ctx
, &bvec
);
234 status
= NT_STATUS_OK
;
236 talloc_free(tmp_ctx
);
241 static NTSTATUS
ep_register(TALLOC_CTX
*mem_ctx
,
242 struct messaging_context
*msg_ctx
,
243 const struct ndr_interface_table
*iface
,
244 const struct dcerpc_binding_vector
*bind_vec
,
245 const struct GUID
*object_guid
,
246 const char *annotation
,
249 struct dcerpc_binding_handle
**pbh
)
251 struct rpc_pipe_client
*cli
= NULL
;
252 struct dcerpc_binding_handle
*h
;
253 struct pipe_auth_data
*auth
;
254 const char *ncalrpc_sock
;
255 const char *rpcsrv_type
;
256 struct epm_entry_t
*entries
;
257 uint32_t num_ents
, i
;
259 uint32_t result
= EPMAPPER_STATUS_OK
;
263 return NT_STATUS_INVALID_PARAMETER
;
266 if (bind_vec
== NULL
|| bind_vec
->count
== 0) {
267 return NT_STATUS_INVALID_PARAMETER
;
270 tmp_ctx
= talloc_stackframe();
271 if (tmp_ctx
== NULL
) {
272 return NT_STATUS_NO_MEMORY
;
275 rpcsrv_type
= lp_parm_const_string(GLOBAL_SECTION_SNUM
,
276 "rpc_server", "epmapper",
279 if (strcasecmp_m(rpcsrv_type
, "embedded") == 0) {
280 struct tsocket_address
*local
;
283 rc
= tsocket_address_inet_from_strings(tmp_ctx
,
289 return NT_STATUS_NO_MEMORY
;
292 status
= rpcint_binding_handle(tmp_ctx
,
295 get_session_info_system(),
298 if (!NT_STATUS_IS_OK(status
)) {
299 DEBUG(1, ("dcerpc_ep_register: Could not connect to "
300 "epmapper (%s)", nt_errstr(status
)));
303 } else if (strcasecmp_m(rpcsrv_type
, "daemon") == 0) {
304 /* Connect to the endpoint mapper locally */
305 ncalrpc_sock
= talloc_asprintf(tmp_ctx
,
309 if (ncalrpc_sock
== NULL
) {
310 status
= NT_STATUS_NO_MEMORY
;
314 status
= rpc_pipe_open_ncalrpc(tmp_ctx
,
316 &ndr_table_epmapper
.syntax_id
,
318 if (!NT_STATUS_IS_OK(status
)) {
322 status
= rpccli_ncalrpc_bind_data(cli
, &auth
);
323 if (!NT_STATUS_IS_OK(status
)) {
324 DEBUG(0, ("Failed to initialize anonymous bind.\n"));
328 status
= rpc_pipe_bind(cli
, auth
);
329 if (!NT_STATUS_IS_OK(status
)) {
330 DEBUG(2, ("Failed to bind ncalrpc socket.\n"));
334 h
= cli
->binding_handle
;
336 status
= NT_STATUS_INVALID_PARAMETER
;
340 num_ents
= bind_vec
->count
;
341 entries
= talloc_array(tmp_ctx
, struct epm_entry_t
, num_ents
);
343 for (i
= 0; i
< num_ents
; i
++) {
344 struct dcerpc_binding
*map_binding
= &bind_vec
->bindings
[i
];
345 struct epm_twr_t
*map_tower
;
347 map_tower
= talloc_zero(entries
, struct epm_twr_t
);
348 if (map_tower
== NULL
) {
349 status
= NT_STATUS_NO_MEMORY
;
353 status
= dcerpc_binding_build_tower(entries
,
356 if (!NT_STATUS_IS_OK(status
)) {
360 entries
[i
].tower
= map_tower
;
361 if (annotation
== NULL
) {
362 entries
[i
].annotation
= talloc_strdup(entries
, "");
364 entries
[i
].annotation
= talloc_strndup(entries
,
366 EPM_MAX_ANNOTATION_SIZE
);
368 if (entries
[i
].annotation
== NULL
) {
369 status
= NT_STATUS_NO_MEMORY
;
373 if (object_guid
!= NULL
) {
374 entries
[i
].object
= *object_guid
;
376 entries
[i
].object
= map_binding
->object
.uuid
;
381 status
= dcerpc_epm_Delete(h
,
387 status
= dcerpc_epm_Insert(h
,
394 if (!NT_STATUS_IS_OK(status
)) {
395 DEBUG(0, ("dcerpc_ep_register: Could not insert tower (%s)\n",
399 if (result
!= EPMAPPER_STATUS_OK
) {
400 DEBUG(0, ("dcerpc_ep_register: Could not insert tower (0x%.8x)\n",
402 status
= NT_STATUS_UNSUCCESSFUL
;
407 *pbh
= talloc_move(mem_ctx
, &h
);
408 talloc_steal(*pbh
, cli
);
412 talloc_free(tmp_ctx
);
417 NTSTATUS
dcerpc_ep_register(TALLOC_CTX
*mem_ctx
,
418 struct messaging_context
*msg_ctx
,
419 const struct ndr_interface_table
*iface
,
420 const struct dcerpc_binding_vector
*bind_vec
,
421 const struct GUID
*object_guid
,
422 const char *annotation
,
423 struct dcerpc_binding_handle
**ph
)
425 return ep_register(mem_ctx
,
436 NTSTATUS
dcerpc_ep_register_noreplace(TALLOC_CTX
*mem_ctx
,
437 struct messaging_context
*msg_ctx
,
438 const struct ndr_interface_table
*iface
,
439 const struct dcerpc_binding_vector
*bind_vec
,
440 const struct GUID
*object_guid
,
441 const char *annotation
,
442 struct dcerpc_binding_handle
**ph
)
444 return ep_register(mem_ctx
,
455 NTSTATUS
dcerpc_ep_unregister(struct messaging_context
*msg_ctx
,
456 const struct ndr_interface_table
*iface
,
457 const struct dcerpc_binding_vector
*bind_vec
,
458 const struct GUID
*object_guid
)
460 return ep_register(NULL
,
471 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */