2 Unix SMB/CIFS implementation.
4 Endpoint server for the epmapper pipe
6 Copyright (C) 2010 Andreas Schneider <asn@samba.org>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "librpc/gen_ndr/ndr_epmapper.h"
24 #include "librpc/gen_ndr/srv_epmapper.h"
26 typedef uint32_t error_status_t;
28 /* An endpoint combined with an interface description */
29 struct dcesrv_ep_iface {
34 /* A rpc service interface like samr, lsarpc or netlogon */
37 struct ndr_syntax_id syntax_id;
40 struct dcesrv_iface_list {
41 struct dcesrv_iface_list *next, *prev;
42 struct dcesrv_iface *iface;
46 * An endpoint can serve multiple rpc services interfaces.
47 * For example \\pipe\netlogon can be used by lsarpc and netlogon.
49 struct dcesrv_endpoint {
50 struct dcesrv_endpoint *next, *prev;
52 /* The type and the location of the endpoint */
53 struct dcerpc_binding *ep_description;
55 /* A list of rpc services able to connect to the endpoint */
56 struct dcesrv_iface_list *iface_list;
59 struct dcesrv_endpoint *endpoint_table;
62 * Check if the UUID and if_version match to an interface.
64 static bool interface_match(const struct dcesrv_iface *if1,
65 const struct dcesrv_iface *if2)
67 return GUID_equal(&if1->syntax_id.uuid, &if2->syntax_id.uuid);
71 * Find the interface operations on an endpoint.
73 static const struct dcesrv_iface *find_interface(const struct dcesrv_endpoint *endpoint,
74 const struct dcesrv_iface *iface)
76 struct dcesrv_iface_list *iflist;
78 for (iflist = endpoint->iface_list; iflist; iflist = iflist->next) {
79 if (interface_match(iflist->iface, iface)) {
87 static struct dcesrv_iface_list *find_interface_list(const struct dcesrv_endpoint *endpoint,
88 const struct dcesrv_iface *iface)
90 struct dcesrv_iface_list *iflist;
92 for (iflist = endpoint->iface_list; iflist; iflist = iflist->next) {
93 if (interface_match(iflist->iface, iface)) {
102 * Check if two endpoints match.
104 static bool endpoints_match(const struct dcerpc_binding *ep1,
105 const struct dcerpc_binding *ep2)
107 if (ep1->transport != ep2->transport) {
111 if (!ep1->endpoint || !ep2->endpoint) {
112 return ep1->endpoint == ep2->endpoint;
115 if (!strequal(ep1->endpoint, ep2->endpoint)) {
122 static struct dcesrv_endpoint *find_endpoint(struct dcesrv_endpoint *endpoint_list,
123 struct dcerpc_binding *ep_description) {
124 struct dcesrv_endpoint *ep;
126 for (ep = endpoint_list; ep != NULL; ep = ep->next) {
127 if (endpoints_match(ep->ep_description, ep_description)) {
136 * Build a list of all interfaces handled by all endpoint servers.
138 static uint32_t build_ep_list(TALLOC_CTX *mem_ctx,
139 struct dcesrv_endpoint *endpoint_list,
140 struct dcesrv_ep_iface **peps)
142 struct dcesrv_ep_iface *eps = NULL;
143 struct dcesrv_endpoint *d;
149 for (d = endpoint_list; d != NULL; d = d->next) {
150 struct dcesrv_iface_list *iface;
151 struct dcerpc_binding *description;
153 for (iface = d->iface_list; iface != NULL; iface = iface->next) {
154 eps = talloc_realloc(mem_ctx,
156 struct dcesrv_ep_iface,
161 eps[total].name = iface->iface->name;
163 description = d->ep_description;
164 description->object = iface->iface->syntax_id;
166 status = dcerpc_binding_build_tower(eps,
169 if (NT_STATUS_IS_ERR(status)) {
170 DEBUG(1, ("Unable to build tower for %s\n",
171 iface->iface->name));
186 * Add the specified entries to an endpoint map.
188 error_status_t _epm_Insert(struct pipes_struct *p,
189 struct epm_Insert *r)
196 tmp_ctx = talloc_stackframe();
197 if (tmp_ctx == NULL) {
198 return EPMAPPER_STATUS_NO_MEMORY;
201 DEBUG(3, ("_epm_Insert: Trying to add %u new entries.\n",
204 /* TODO Check if we have a priviledged pipe/handle */
206 for (i = 0; i < r->in.num_ents; i++) {
207 struct dcerpc_binding *b = NULL;
208 struct dcesrv_endpoint *ep;
209 struct dcesrv_iface_list *iflist;
210 struct dcesrv_iface *iface;
213 status = dcerpc_binding_from_tower(tmp_ctx,
214 &r->in.entries[i].tower->tower,
216 if (!NT_STATUS_IS_OK(status)) {
217 rc = EPMAPPER_STATUS_NO_MEMORY;
221 DEBUG(3, ("_epm_Insert: Adding transport %s for %s\n",
222 derpc_transport_string_by_transport(b->transport),
223 r->in.entries[i].annotation));
225 /* Check if the entry already exits */
226 ep = find_endpoint(endpoint_table, b);
228 /* No entry found, create it */
229 ep = talloc_zero(NULL, struct dcesrv_endpoint);
231 rc = EPMAPPER_STATUS_CANT_PERFORM_OP;
236 ep->ep_description = talloc_steal(ep, b);
239 /* TODO Replace the entry if the replace flag is set */
241 /* Create an interface */
242 iface = talloc(tmp_ctx, struct dcesrv_iface);
244 rc = EPMAPPER_STATUS_NO_MEMORY;
248 iface->name = talloc_strdup(iface, r->in.entries[i].annotation);
249 if (iface->name == NULL) {
250 rc = EPMAPPER_STATUS_NO_MEMORY;
253 iface->syntax_id = b->object;
256 * Check if the rpc service is alrady registered on the
259 if (find_interface(ep, iface) != NULL) {
260 DEBUG(0, ("dcesrv_interface_register: interface '%s' "
261 "already registered on endpoint\n",
263 /* FIXME wrong error code? */
264 rc = EPMAPPER_STATUS_OK;
268 /* Create an entry for the interface */
269 iflist = talloc(ep, struct dcesrv_iface_list);
270 if (iflist == NULL) {
271 rc = EPMAPPER_STATUS_NO_MEMORY;
274 iflist->iface = talloc_move(iflist, &iface);
276 /* Finally add the interface on the endpoint */
277 DLIST_ADD(ep->iface_list, iflist);
279 /* If it's a new endpoint add it to the endpoint_table */
281 DLIST_ADD(endpoint_table, ep);
285 rc = EPMAPPER_STATUS_OK;
287 talloc_free(tmp_ctx);
296 * Delete the specified entries from an endpoint map.
298 error_status_t _epm_Delete(struct pipes_struct *p,
299 struct epm_Delete *r)
306 DEBUG(3, ("_epm_Delete: Trying to delete %u entries.\n",
309 tmp_ctx = talloc_stackframe();
310 if (tmp_ctx == NULL) {
311 return EPMAPPER_STATUS_NO_MEMORY;
314 /* TODO Check if we have a priviledged pipe/handle */
316 for (i = 0; i < r->in.num_ents; i++) {
317 struct dcerpc_binding *b = NULL;
318 struct dcesrv_endpoint *ep;
319 struct dcesrv_iface iface;
320 struct dcesrv_iface_list *iflist;
322 status = dcerpc_binding_from_tower(tmp_ctx,
323 &r->in.entries[i].tower->tower,
325 if (!NT_STATUS_IS_OK(status)) {
326 rc = EPMAPPER_STATUS_NO_MEMORY;
330 DEBUG(3, ("_epm_Delete: Deleting transport '%s' for '%s'\n",
331 derpc_transport_string_by_transport(b->transport),
332 r->in.entries[i].annotation));
334 ep = find_endpoint(endpoint_table, b);
336 rc = EPMAPPER_STATUS_OK;
340 iface.name = r->in.entries[i].annotation;
341 iface.syntax_id = b->object;
343 iflist = find_interface_list(ep, &iface);
344 if (iflist == NULL) {
345 DEBUG(0, ("_epm_Delete: No interfaces left, delete endpoint\n"));
346 DLIST_REMOVE(endpoint_table, ep);
349 rc = EPMAPPER_STATUS_OK;
353 DLIST_REMOVE(ep->iface_list, iflist);
355 if (ep->iface_list == NULL) {
356 DEBUG(0, ("_epm_Delete: No interfaces left, delete endpoint\n"));
357 DLIST_REMOVE(endpoint_table, ep);
360 rc = EPMAPPER_STATUS_OK;
366 rc = EPMAPPER_STATUS_OK;
368 talloc_free(tmp_ctx);
377 error_status_t _epm_Lookup(struct pipes_struct *p,
378 struct epm_Lookup *r)
380 p->rng_fault_state = true;
381 return EPMAPPER_STATUS_CANT_PERFORM_OP;
387 * Apply some algorithm (using the fields in the map_tower) to an endpoint map
388 * to produce a list of protocol towers.
390 error_status_t _epm_Map(struct pipes_struct *p,
393 enum dcerpc_transport_t transport;
394 struct ndr_syntax_id ndr_syntax;
395 struct dcesrv_ep_iface *eps;
396 struct epm_floor *floors;
399 count = build_ep_list(p->mem_ctx, endpoint_table, &eps);
401 ZERO_STRUCT(*r->out.entry_handle);
402 r->out.num_towers = talloc(p->mem_ctx, uint32_t);
403 if (r->out.num_towers == NULL) {
404 return EPMAPPER_STATUS_NO_MEMORY;
407 *r->out.num_towers = 1;
408 r->out.towers = talloc(p->mem_ctx, struct epm_twr_p_t);
409 if (r->out.towers == NULL) {
410 return EPMAPPER_STATUS_NO_MEMORY;
413 r->out.towers->twr = talloc(p->mem_ctx, struct epm_twr_t);
414 if (r->out.towers->twr == NULL) {
415 return EPMAPPER_STATUS_NO_MEMORY;
418 if (r->in.map_tower == NULL || r->in.max_towers == 0 ||
419 r->in.map_tower->tower.num_floors < 3) {
423 floors = r->in.map_tower->tower.floors;
425 dcerpc_floor_get_lhs_data(&r->in.map_tower->tower.floors[1], &ndr_syntax);
427 if (floors[1].lhs.protocol != EPM_PROTOCOL_UUID ||
428 !GUID_equal(&ndr_syntax.uuid, &ndr_transfer_syntax.uuid) ||
429 ndr_syntax.if_version != ndr_transfer_syntax.if_version) {
433 transport = dcerpc_transport_by_tower(&r->in.map_tower->tower);
434 if (transport == -1) {
435 DEBUG(2, ("epm_Insert: Client requested unknown transport with levels: "));
436 for (i = 2; i < r->in.map_tower->tower.num_floors; i++) {
437 DEBUG(2, ("%d, ", r->in.map_tower->tower.floors[i].lhs.protocol));
443 for (i = 0; i < count; i++) {
444 if (data_blob_cmp(&r->in.map_tower->tower.floors[0].lhs.lhs_data,
445 &eps[i].ep.floors[0].lhs.lhs_data) != 0 ||
446 transport != dcerpc_transport_by_tower(&eps[i].ep)) {
450 r->out.towers->twr->tower = eps[i].ep;
451 r->out.towers->twr->tower_length = 0;
453 return EPMAPPER_STATUS_OK;
457 *r->out.num_towers = 0;
458 r->out.towers->twr = NULL;
460 return EPMAPPER_STATUS_NO_MORE_ENTRIES;
466 error_status_t _epm_LookupHandleFree(struct pipes_struct *p,
467 struct epm_LookupHandleFree *r)
469 p->rng_fault_state = true;
470 return EPMAPPER_STATUS_CANT_PERFORM_OP;
477 error_status_t _epm_InqObject(struct pipes_struct *p,
478 struct epm_InqObject *r)
480 p->rng_fault_state = true;
481 return EPMAPPER_STATUS_CANT_PERFORM_OP;
488 error_status_t _epm_MgmtDelete(struct pipes_struct *p,
489 struct epm_MgmtDelete *r)
491 p->rng_fault_state = true;
492 return EPMAPPER_STATUS_CANT_PERFORM_OP;
499 error_status_t _epm_MapAuth(struct pipes_struct *p,
500 struct epm_MapAuth *r)
502 p->rng_fault_state = true;
503 return EPMAPPER_STATUS_CANT_PERFORM_OP;
506 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */