s3-rpc_server: Implement an endpoint monitor loop.
[Samba/bjacke.git] / source3 / librpc / rpc / dcerpc_ep.c
blob1fce63acd212105cb1696827153155c9e0e67788
1 /*
2 * Endpoint Mapper Functions
3 * DCERPC local endpoint mapper client routines
4 * Copyright (c) 2010 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"
26 #define EPM_MAX_ANNOTATION_SIZE 64
28 NTSTATUS dcerpc_binding_vector_create(TALLOC_CTX *mem_ctx,
29 const struct ndr_interface_table *iface,
30 uint16_t port,
31 const char *ncalrpc,
32 struct dcerpc_binding_vector **pbvec)
34 struct dcerpc_binding_vector *bvec;
35 uint32_t ep_count;
36 uint32_t count = 0;
37 uint32_t i;
38 NTSTATUS status;
39 TALLOC_CTX *tmp_ctx;
41 tmp_ctx = talloc_stackframe();
42 if (tmp_ctx == NULL) {
43 return NT_STATUS_NO_MEMORY;
46 ep_count = iface->endpoints->count;
48 bvec = talloc_zero(tmp_ctx, struct dcerpc_binding_vector);
49 if (bvec == NULL) {
50 status = NT_STATUS_NO_MEMORY;
51 goto done;
54 bvec->bindings = talloc_zero_array(bvec, struct dcerpc_binding, ep_count);
55 if (bvec->bindings == NULL) {
56 status = NT_STATUS_NO_MEMORY;
57 goto done;
60 for (i = 0; i < ep_count; i++) {
61 struct dcerpc_binding *b;
63 b = talloc_zero(bvec->bindings, struct dcerpc_binding);
64 if (b == NULL) {
65 status = NT_STATUS_NO_MEMORY;
66 goto done;
69 status = dcerpc_parse_binding(b, iface->endpoints->names[i], &b);
70 if (!NT_STATUS_IS_OK(status)) {
71 status = NT_STATUS_UNSUCCESSFUL;
72 goto done;
75 b->object = iface->syntax_id;
77 switch (b->transport) {
78 case NCACN_NP:
79 b->host = talloc_asprintf(b, "\\\\%s", global_myname());
80 if (b->host == NULL) {
81 status = NT_STATUS_NO_MEMORY;
82 goto done;
84 break;
85 case NCACN_IP_TCP:
86 if (port == 0) {
87 talloc_free(b);
88 continue;
91 b->endpoint = talloc_asprintf(b, "%u", port);
92 if (b->endpoint == NULL) {
93 status = NT_STATUS_NO_MEMORY;
94 goto done;
97 break;
98 case NCALRPC:
99 if (ncalrpc == NULL) {
100 talloc_free(b);
101 continue;
104 b->endpoint = talloc_asprintf(b,
105 "%s/%s",
106 lp_ncalrpc_dir(),
107 ncalrpc);
108 if (b->endpoint == NULL) {
109 status = NT_STATUS_NO_MEMORY;
110 goto done;
112 break;
113 default:
114 talloc_free(b);
115 continue;
118 bvec->bindings[count] = *b;
119 count++;
122 bvec->count = count;
124 *pbvec = talloc_move(mem_ctx, &bvec);
126 status = NT_STATUS_OK;
127 done:
128 talloc_free(tmp_ctx);
130 return status;
133 static NTSTATUS ep_register(TALLOC_CTX *mem_ctx,
134 const struct ndr_interface_table *iface,
135 const struct dcerpc_binding_vector *bind_vec,
136 const struct GUID *object_guid,
137 const char *annotation,
138 uint32_t replace,
139 uint32_t unregister,
140 struct dcerpc_binding_handle **pbh)
142 struct rpc_pipe_client *cli = NULL;
143 struct dcerpc_binding_handle *h;
144 struct pipe_auth_data *auth;
145 const char *ncalrpc_sock;
146 const char *rpcsrv_type;
147 struct epm_entry_t *entries;
148 uint32_t num_ents, i;
149 TALLOC_CTX *tmp_ctx;
150 uint32_t result = EPMAPPER_STATUS_OK;
151 NTSTATUS status;
153 if (iface == NULL) {
154 return NT_STATUS_INVALID_PARAMETER;
157 if (bind_vec == NULL || bind_vec->count == 0) {
158 return NT_STATUS_INVALID_PARAMETER;
161 tmp_ctx = talloc_stackframe();
162 if (tmp_ctx == NULL) {
163 return NT_STATUS_NO_MEMORY;
166 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
167 "rpc_server", "epmapper",
168 "none");
170 if (StrCaseCmp(rpcsrv_type, "embedded") == 0) {
171 static struct client_address client_id;
173 strlcpy(client_id.addr, "localhost", sizeof(client_id.addr));
174 client_id.name = "localhost";
176 status = rpcint_binding_handle(tmp_ctx,
177 &ndr_table_epmapper,
178 &client_id,
179 get_session_info_system(),
180 server_messaging_context(),
181 &h);
182 if (!NT_STATUS_IS_OK(status)) {
183 DEBUG(1, ("dcerpc_ep_register: Could not connect to "
184 "epmapper (%s)", nt_errstr(status)));
185 goto done;
187 } else if (StrCaseCmp(rpcsrv_type, "daemon") == 0) {
188 /* Connect to the endpoint mapper locally */
189 ncalrpc_sock = talloc_asprintf(tmp_ctx,
190 "%s/%s",
191 lp_ncalrpc_dir(),
192 "EPMAPPER");
193 if (ncalrpc_sock == NULL) {
194 status = NT_STATUS_NO_MEMORY;
195 goto done;
198 status = rpc_pipe_open_ncalrpc(tmp_ctx,
199 ncalrpc_sock,
200 &ndr_table_epmapper.syntax_id,
201 &cli);
202 if (!NT_STATUS_IS_OK(status)) {
203 goto done;
206 status = rpccli_ncalrpc_bind_data(cli, &auth);
207 if (!NT_STATUS_IS_OK(status)) {
208 DEBUG(0, ("Failed to initialize anonymous bind.\n"));
209 goto done;
212 status = rpc_pipe_bind(cli, auth);
213 if (!NT_STATUS_IS_OK(status)) {
214 DEBUG(2, ("Failed to bind ncalrpc socket.\n"));
215 goto done;
218 h = cli->binding_handle;
219 } else {
220 status = NT_STATUS_INVALID_PARAMETER;
221 goto done;
224 num_ents = bind_vec->count;
225 entries = talloc_array(tmp_ctx, struct epm_entry_t, num_ents);
227 for (i = 0; i < num_ents; i++) {
228 struct dcerpc_binding *map_binding = &bind_vec->bindings[i];
229 struct epm_twr_t *map_tower;
231 map_tower = talloc_zero(entries, struct epm_twr_t);
232 if (map_tower == NULL) {
233 status = NT_STATUS_NO_MEMORY;
234 goto done;
237 status = dcerpc_binding_build_tower(entries,
238 map_binding,
239 &map_tower->tower);
240 if (!NT_STATUS_IS_OK(status)) {
241 goto done;
244 entries[i].tower = map_tower;
245 if (annotation == NULL) {
246 entries[i].annotation = talloc_strdup(entries, "");
247 } else {
248 entries[i].annotation = talloc_strndup(entries,
249 annotation,
250 EPM_MAX_ANNOTATION_SIZE);
252 if (entries[i].annotation == NULL) {
253 status = NT_STATUS_NO_MEMORY;
254 goto done;
257 if (object_guid != NULL) {
258 entries[i].object = *object_guid;
259 } else {
260 entries[i].object = map_binding->object.uuid;
264 if (unregister) {
265 status = dcerpc_epm_Delete(h,
266 tmp_ctx,
267 num_ents,
268 entries,
269 &result);
270 } else {
271 status = dcerpc_epm_Insert(h,
272 tmp_ctx,
273 num_ents,
274 entries,
275 replace,
276 &result);
278 if (!NT_STATUS_IS_OK(status)) {
279 DEBUG(0, ("dcerpc_ep_register: Could not insert tower (%s)\n",
280 nt_errstr(status)));
281 goto done;
283 if (result != EPMAPPER_STATUS_OK) {
284 DEBUG(0, ("dcerpc_ep_register: Could not insert tower (0x%.8x)\n",
285 result));
286 status = NT_STATUS_UNSUCCESSFUL;
287 goto done;
290 if (pbh != NULL) {
291 *pbh = talloc_move(mem_ctx, &h);
292 talloc_steal(*pbh, cli);
295 done:
296 talloc_free(tmp_ctx);
298 return status;
301 NTSTATUS dcerpc_ep_register(TALLOC_CTX *mem_ctx,
302 const struct ndr_interface_table *iface,
303 const struct dcerpc_binding_vector *bind_vec,
304 const struct GUID *object_guid,
305 const char *annotation,
306 struct dcerpc_binding_handle **ph)
308 return ep_register(mem_ctx,
309 iface,
310 bind_vec,
311 object_guid,
312 annotation,
315 ph);
318 NTSTATUS dcerpc_ep_register_noreplace(TALLOC_CTX *mem_ctx,
319 const struct ndr_interface_table *iface,
320 const struct dcerpc_binding_vector *bind_vec,
321 const struct GUID *object_guid,
322 const char *annotation,
323 struct dcerpc_binding_handle **ph)
325 return ep_register(mem_ctx,
326 iface,
327 bind_vec,
328 object_guid,
329 annotation,
332 ph);
335 NTSTATUS dcerpc_ep_unregister(const struct ndr_interface_table *iface,
336 const struct dcerpc_binding_vector *bind_vec,
337 const struct GUID *object_guid)
339 return ep_register(NULL,
340 iface,
341 bind_vec,
342 object_guid,
343 NULL,
346 NULL);
349 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */