2 Unix SMB/CIFS implementation.
4 Endpoint server for the epmapper pipe
6 Copyright (C) 2010-2011 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/>.
24 #include "../libcli/security/security.h"
25 #include "../lib/tsocket/tsocket.h"
26 #include "librpc/gen_ndr/srv_epmapper.h"
27 #include "srv_epmapper.h"
30 typedef uint32_t error_status_t;
32 /* An endpoint combined with an interface description */
33 struct dcesrv_ep_iface {
35 struct ndr_syntax_id syntax_id;
39 /* A rpc service interface like samr, lsarpc or netlogon */
42 struct ndr_syntax_id syntax_id;
45 struct dcesrv_iface_list {
46 struct dcesrv_iface_list *next, *prev;
47 struct dcesrv_iface *iface;
51 * An endpoint can serve multiple rpc services interfaces.
52 * For example \\pipe\netlogon can be used by lsarpc and netlogon.
54 struct dcesrv_epm_endpoint {
55 struct dcesrv_epm_endpoint *next, *prev;
57 /* The type and the location of the endpoint */
58 struct dcerpc_binding *ep_description;
60 /* A list of rpc services able to connect to the endpoint */
61 struct dcesrv_iface_list *iface_list;
64 struct dcesrv_ep_entry_list {
65 struct dcesrv_ep_entry_list *next, *prev;
68 struct epm_entry_t *entries;
72 struct dcesrv_ep_iface *e;
76 static struct dcesrv_epm_endpoint *endpoint_table = NULL;
79 * Check if the UUID and if_version match to an interface.
81 static bool interface_match(const struct dcesrv_iface *if1,
82 const struct dcesrv_iface *if2)
84 return GUID_equal(&if1->syntax_id.uuid, &if2->syntax_id.uuid);
88 * Find the interface operations on an endpoint.
90 static const struct dcesrv_iface *find_interface(const struct dcesrv_epm_endpoint *endpoint,
91 const struct dcesrv_iface *iface)
93 struct dcesrv_iface_list *iflist;
95 for (iflist = endpoint->iface_list; iflist; iflist = iflist->next) {
96 if (interface_match(iflist->iface, iface)) {
106 * See if a uuid and if_version match to an interface
108 static bool interface_match_by_uuid(const struct dcesrv_iface *iface,
109 const struct GUID *uuid)
111 return GUID_equal(&iface->syntax_id.uuid, uuid);
115 static struct dcesrv_iface_list *find_interface_list(const struct dcesrv_epm_endpoint *endpoint,
116 const struct dcesrv_iface *iface)
118 struct dcesrv_iface_list *iflist;
120 for (iflist = endpoint->iface_list; iflist; iflist = iflist->next) {
121 if (interface_match(iflist->iface, iface)) {
130 * Check if two endpoints match.
132 static bool endpoints_match(const struct dcerpc_binding *b1,
133 const struct dcerpc_binding *b2)
135 enum dcerpc_transport_t t1;
138 enum dcerpc_transport_t t2;
142 t1 = dcerpc_binding_get_transport(b1);
143 ep1 = dcerpc_binding_get_string_option(b1, "endpoint");
144 h1 = dcerpc_binding_get_string_option(b1, "host");
146 t2 = dcerpc_binding_get_transport(b2);
147 ep2 = dcerpc_binding_get_string_option(b2, "endpoint");
148 h2 = dcerpc_binding_get_string_option(b2, "host");
163 if (!strequal(ep1, ep2)) {
177 if (!strequal(h1, h2)) {
185 static struct dcesrv_epm_endpoint *find_endpoint(struct dcesrv_epm_endpoint *endpoint_list,
186 struct dcerpc_binding *ep_description) {
187 struct dcesrv_epm_endpoint *ep = NULL;
189 for (ep = endpoint_list; ep != NULL; ep = ep->next) {
190 if (endpoints_match(ep->ep_description, ep_description)) {
199 * Build a list of all interfaces handled by all endpoint servers.
201 static uint32_t build_ep_list(TALLOC_CTX *mem_ctx,
202 struct dcesrv_epm_endpoint *endpoint_list,
203 const struct GUID *uuid,
204 const char *srv_addr,
205 struct dcesrv_ep_iface **peps)
207 struct dcesrv_ep_iface *eps = NULL;
208 struct dcesrv_epm_endpoint *d = NULL;
214 for (d = endpoint_list; d != NULL; d = d->next) {
215 struct dcesrv_iface_list *iface;
216 struct dcerpc_binding *description;
218 for (iface = d->iface_list; iface != NULL; iface = iface->next) {
219 enum dcerpc_transport_t transport;
220 const char *host = NULL;
221 const char *host_addr = NULL;
225 * Windows ignores the object uuid by default. There is
226 * one corner case. It is checked for the mgmt
227 * interface, which we do not implement here yet.
229 if (uuid && !interface_match_by_uuid(iface->iface, uuid)) {
234 eps = talloc_realloc(mem_ctx,
236 struct dcesrv_ep_iface,
241 eps[total].name = talloc_strdup(eps,
243 if (eps[total].name == NULL) {
246 eps[total].syntax_id = iface->iface->syntax_id;
248 description = dcerpc_binding_dup(mem_ctx, d->ep_description);
249 if (description == NULL) {
253 status = dcerpc_binding_set_abstract_syntax(description,
254 &iface->iface->syntax_id);
255 if (!NT_STATUS_IS_OK(status)) {
259 transport = dcerpc_binding_get_transport(description);
260 host = dcerpc_binding_get_string_option(description, "host");
262 if (transport == NCACN_IP_TCP) {
264 host_addr = srv_addr;
265 } else if (!is_ipaddress_v4(host)) {
266 host_addr = srv_addr;
267 } else if (strcmp(host, "0.0.0.0") == 0) {
268 host_addr = srv_addr;
272 if (host_addr != NULL) {
273 status = dcerpc_binding_set_string_option(description,
276 if (!NT_STATUS_IS_OK(status)) {
281 status = dcerpc_binding_build_tower(eps,
284 TALLOC_FREE(description);
285 if (NT_STATUS_IS_ERR(status)) {
286 DEBUG(1, ("Unable to build tower for %s\n",
287 iface->iface->name));
299 static bool is_privileged_pipe(struct auth_session_info *info) {
300 /* If the user is not root, or has the system token, fail */
301 if ((info->unix_token->uid != sec_initial_uid()) &&
302 !security_token_is_system(info->security_token)) {
309 void srv_epmapper_delete_endpoints(struct pipes_struct *p, void *private_data)
312 struct dcesrv_ep_entry_list *el = p->ep_entries;
313 error_status_t result;
316 struct dcesrv_ep_entry_list *next = el->next;
318 r.in.num_ents = el->num_ents;
319 r.in.entries = el->entries;
321 DEBUG(10, ("Delete_endpoints for: %s\n",
322 el->entries[0].annotation));
324 result = _epm_Delete(p, &r);
325 if (result != EPMAPPER_STATUS_OK) {
326 DBG_ERR("Failed to delete endpoint maps\n");
330 DLIST_REMOVE(p->ep_entries, el);
337 void srv_epmapper_cleanup(void)
339 struct dcesrv_epm_endpoint *ep = endpoint_table;
342 struct dcesrv_epm_endpoint *next = ep->next;
344 DLIST_REMOVE(endpoint_table, ep);
354 * Add the specified entries to an endpoint map.
356 error_status_t _epm_Insert(struct pipes_struct *p,
357 struct epm_Insert *r)
363 struct dcerpc_binding *b;
364 struct dcesrv_epm_endpoint *ep = NULL;
365 struct dcesrv_iface_list *iflist;
366 struct dcesrv_iface *iface;
369 /* If this is not a privileged users, return */
370 if (p->transport != NCALRPC ||
371 !is_privileged_pipe(p->session_info)) {
372 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
373 return EPMAPPER_STATUS_CANT_PERFORM_OP;
376 tmp_ctx = talloc_stackframe();
377 if (tmp_ctx == NULL) {
378 return EPMAPPER_STATUS_NO_MEMORY;
381 DEBUG(3, ("_epm_Insert: Trying to add %u new entries.\n",
384 for (i = 0; i < r->in.num_ents; i++) {
385 enum dcerpc_transport_t transport;
389 status = dcerpc_binding_from_tower(tmp_ctx,
390 &r->in.entries[i].tower->tower,
392 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) {
393 rc = EPMAPPER_STATUS_NO_MEMORY;
396 if (!NT_STATUS_IS_OK(status)) {
397 rc = EPMAPPER_STATUS_CANT_PERFORM_OP;
401 transport = dcerpc_binding_get_transport(b);
402 DEBUG(3, ("_epm_Insert: Adding transport %s for %s\n",
403 derpc_transport_string_by_transport(transport),
404 r->in.entries[i].annotation));
406 /* Check if the entry already exits */
407 ep = find_endpoint(endpoint_table, b);
409 /* No entry found, create it */
410 ep = talloc_zero(NULL, struct dcesrv_epm_endpoint);
412 rc = EPMAPPER_STATUS_NO_MEMORY;
417 ep->ep_description = talloc_steal(ep, b);
420 /* TODO Replace the entry if the replace flag is set */
422 /* Create an interface */
423 iface = talloc(tmp_ctx, struct dcesrv_iface);
425 rc = EPMAPPER_STATUS_NO_MEMORY;
429 iface->name = talloc_strdup(iface, r->in.entries[i].annotation);
430 if (iface->name == NULL) {
431 rc = EPMAPPER_STATUS_NO_MEMORY;
434 iface->syntax_id = dcerpc_binding_get_abstract_syntax(b);
437 * Check if the rpc service is alrady registered on the
440 if (find_interface(ep, iface) != NULL) {
441 DEBUG(8, ("dcesrv_interface_register: interface '%s' "
442 "already registered on endpoint\n",
444 /* FIXME wrong error code? */
445 rc = EPMAPPER_STATUS_OK;
449 /* Create an entry for the interface */
450 iflist = talloc(ep, struct dcesrv_iface_list);
451 if (iflist == NULL) {
452 rc = EPMAPPER_STATUS_NO_MEMORY;
455 iflist->iface = talloc_move(iflist, &iface);
457 /* Finally add the interface on the endpoint */
458 DLIST_ADD(ep->iface_list, iflist);
460 /* If it's a new endpoint add it to the endpoint_table */
462 DLIST_ADD(endpoint_table, ep);
466 if (r->in.num_ents > 0) {
467 struct dcesrv_ep_entry_list *el;
469 el = talloc_zero(p, struct dcesrv_ep_entry_list);
471 rc = EPMAPPER_STATUS_NO_MEMORY;
474 el->num_ents = r->in.num_ents;
475 el->entries = talloc_move(el, &r->in.entries);
477 DLIST_ADD(p->ep_entries, el);
480 rc = EPMAPPER_STATUS_OK;
482 talloc_free(tmp_ctx);
491 * Delete the specified entries from an endpoint map.
493 error_status_t _epm_Delete(struct pipes_struct *p,
494 struct epm_Delete *r)
500 struct dcerpc_binding *b;
501 struct dcesrv_epm_endpoint *ep = NULL;
502 struct dcesrv_iface iface;
503 struct dcesrv_iface_list *iflist;
505 DEBUG(3, ("_epm_Delete: Trying to delete %u entries.\n",
508 /* If this is not a privileged users, return */
509 if (p->transport != NCALRPC ||
510 !is_privileged_pipe(p->session_info)) {
511 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
512 return EPMAPPER_STATUS_CANT_PERFORM_OP;
515 tmp_ctx = talloc_stackframe();
516 if (tmp_ctx == NULL) {
517 return EPMAPPER_STATUS_NO_MEMORY;
520 for (i = 0; i < r->in.num_ents; i++) {
521 enum dcerpc_transport_t transport;
525 status = dcerpc_binding_from_tower(tmp_ctx,
526 &r->in.entries[i].tower->tower,
528 if (!NT_STATUS_IS_OK(status)) {
529 rc = EPMAPPER_STATUS_NO_MEMORY;
533 transport = dcerpc_binding_get_transport(b);
534 DEBUG(3, ("_epm_Delete: Deleting transport '%s' for '%s'\n",
535 derpc_transport_string_by_transport(transport),
536 r->in.entries[i].annotation));
538 ep = find_endpoint(endpoint_table, b);
540 rc = EPMAPPER_STATUS_OK;
544 iface.name = r->in.entries[i].annotation;
545 iface.syntax_id = dcerpc_binding_get_abstract_syntax(b);
547 iflist = find_interface_list(ep, &iface);
548 if (iflist == NULL) {
549 DEBUG(0, ("_epm_Delete: No interfaces left, delete endpoint\n"));
550 DLIST_REMOVE(endpoint_table, ep);
553 rc = EPMAPPER_STATUS_OK;
557 DLIST_REMOVE(ep->iface_list, iflist);
559 if (ep->iface_list == NULL) {
560 DEBUG(0, ("_epm_Delete: No interfaces left, delete endpoint\n"));
561 DLIST_REMOVE(endpoint_table, ep);
564 rc = EPMAPPER_STATUS_OK;
570 rc = EPMAPPER_STATUS_OK;
572 talloc_free(tmp_ctx);
581 * Lookup entries in an endpoint map.
583 error_status_t _epm_Lookup(struct pipes_struct *p,
584 struct epm_Lookup *r)
586 struct policy_handle *entry_handle;
591 uint32_t num_ents = 0;
596 *r->out.num_ents = 0;
597 r->out.entries = NULL;
599 tmp_ctx = talloc_stackframe();
600 if (tmp_ctx == NULL) {
601 return EPMAPPER_STATUS_NO_MEMORY;
604 DEBUG(5, ("_epm_Lookup: Trying to lookup max. %u entries.\n",
607 if (r->in.entry_handle == NULL ||
608 ndr_policy_handle_empty(r->in.entry_handle)) {
609 char *srv_addr = NULL;
611 DEBUG(7, ("_epm_Lookup: No entry_handle found, creating it.\n"));
613 eps = talloc_zero(tmp_ctx, struct rpc_eps);
615 rc = EPMAPPER_STATUS_NO_MEMORY;
619 if (p->local_address != NULL &&
620 tsocket_address_is_inet(p->local_address, "ipv4"))
622 srv_addr = tsocket_address_inet_addr_string(p->local_address,
626 switch (r->in.inquiry_type) {
627 case RPC_C_EP_ALL_ELTS:
629 * Return all elements from the endpoint map. The
630 * interface_id, vers_option, and object parameters MUST
633 eps->count = build_ep_list(eps,
639 case RPC_C_EP_MATCH_BY_IF:
641 * Return endpoint map elements that contain the
642 * interface identifier specified by the interface_id
643 * and vers_option values.
645 * RPC_C_EP_MATCH_BY_IF and RPC_C_EP_MATCH_BY_BOTH
646 * need both the same endpoint list. There is a second
647 * check for the inquiry_type below which differentiates
650 case RPC_C_EP_MATCH_BY_BOTH:
652 * Return endpoint map elements that contain the
653 * interface identifier and object UUID specified by
654 * interface_id, vers_option, and object.
656 eps->count = build_ep_list(eps,
658 &r->in.interface_id->uuid,
662 case RPC_C_EP_MATCH_BY_OBJ:
664 * Return endpoint map elements that contain the object
665 * UUID specified by object.
667 eps->count = build_ep_list(eps,
674 rc = EPMAPPER_STATUS_CANT_PERFORM_OP;
678 if (eps->count == 0) {
679 rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
683 ok = create_policy_hnd(p, r->out.entry_handle, eps);
685 rc = EPMAPPER_STATUS_NO_MEMORY;
689 ok = find_policy_by_hnd(p, r->out.entry_handle, (void **)(void*) &eps);
691 rc = EPMAPPER_STATUS_NO_MEMORY;
694 entry_handle = r->out.entry_handle;
696 DEBUG(7, ("_epm_Lookup: Trying to find entry_handle.\n"));
698 ok = find_policy_by_hnd(p, r->in.entry_handle, (void **)(void*) &eps);
700 rc = EPMAPPER_STATUS_NO_MEMORY;
703 entry_handle = r->in.entry_handle;
706 if (eps == NULL || eps->e == NULL) {
707 rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
711 /* return the next N elements */
712 count = r->in.max_ents;
713 if (count > eps->count) {
717 DEBUG(5, ("_epm_Lookup: Find %u entries\n", count));
720 close_policy_hnd(p, entry_handle);
721 ZERO_STRUCTP(r->out.entry_handle);
723 rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
727 r->out.entries = talloc_array(p->mem_ctx, struct epm_entry_t, count);
728 if (r->out.entries == NULL) {
729 rc = EPMAPPER_STATUS_NO_MEMORY;
733 for (i = 0; i < count; i++) {
736 switch (r->in.inquiry_type) {
737 case RPC_C_EP_ALL_ELTS:
739 * Return all elements from the endpoint map. The
740 * interface_id, vers_option, and object parameters MUST
745 case RPC_C_EP_MATCH_BY_IF:
747 * Return endpoint map elements that contain the
748 * interface identifier specified by the interface_id
749 * and vers_option values.
751 if (GUID_equal(&r->in.interface_id->uuid,
752 &eps->e[i].syntax_id.uuid)) {
756 case RPC_C_EP_MATCH_BY_OBJ:
758 * Return endpoint map elements that contain the object
759 * UUID specified by object.
761 if (GUID_equal(r->in.object,
762 &eps->e[i].syntax_id.uuid)) {
766 case RPC_C_EP_MATCH_BY_BOTH:
768 * Return endpoint map elements that contain the
769 * interface identifier and object UUID specified by
770 * interface_id, vers_option, and object.
772 if (GUID_equal(&r->in.interface_id->uuid,
773 &eps->e[i].syntax_id.uuid) &&
774 GUID_equal(r->in.object, &eps->e[i].syntax_id.uuid)) {
779 return EPMAPPER_STATUS_CANT_PERFORM_OP;
783 if (r->in.inquiry_type == RPC_C_EP_MATCH_BY_IF ||
784 r->in.inquiry_type == RPC_C_EP_MATCH_BY_OBJ) {
785 /* Check interface version */
788 switch (r->in.vers_option) {
791 * Return endpoint map elements that
792 * contain the specified interface UUID,
793 * regardless of the version numbers.
797 case RPC_C_VERS_COMPATIBLE:
799 * Return the endpoint map elements that
800 * contain the same major versions of
801 * the specified interface UUID and a
802 * minor version greater than or equal
803 * to the minor version of the specified
806 if (r->in.interface_id->vers_major ==
807 (eps->e[i].syntax_id.if_version >> 16) &&
808 r->in.interface_id->vers_minor <=
809 (eps->e[i].syntax_id.if_version & 0xFFFF)) {
813 case RPC_C_VERS_EXACT:
815 * Return endpoint map elements that
816 * contain the specified version of the
817 * specified interface UUID.
819 if (r->in.interface_id->vers_major ==
820 (eps->e[i].syntax_id.if_version >> 16) &&
821 r->in.interface_id->vers_minor ==
822 (eps->e[i].syntax_id.if_version & 0xFFFF)) {
827 case RPC_C_VERS_MAJOR_ONLY:
829 * Return endpoint map elements that
830 * contain the same version of the
831 * specified interface UUID and ignore
834 if (r->in.interface_id->vers_major ==
835 (eps->e[i].syntax_id.if_version >> 16)) {
840 case RPC_C_VERS_UPTO:
842 * Return endpoint map elements that
843 * contain a version of the specified
844 * interface UUID less than or equal to
845 * the specified major and minor
848 if (r->in.interface_id->vers_major >
849 eps->e[i].syntax_id.if_version >> 16) {
852 if (r->in.interface_id->vers_major ==
853 (eps->e[i].syntax_id.if_version >> 16) &&
854 r->in.interface_id->vers_minor >=
855 (eps->e[i].syntax_id.if_version & 0xFFFF)) {
861 return EPMAPPER_STATUS_CANT_PERFORM_OP;
867 ZERO_STRUCT(r->out.entries[num_ents].object);
869 DEBUG(10, ("_epm_Lookup: Adding tower for '%s'\n",
871 r->out.entries[num_ents].annotation = talloc_strdup(r->out.entries,
873 r->out.entries[num_ents].tower = talloc(r->out.entries,
875 if (r->out.entries[num_ents].tower == NULL) {
876 rc = EPMAPPER_STATUS_NO_MEMORY;
879 r->out.entries[num_ents].tower->tower.floors = talloc_move(r->out.entries[num_ents].tower, &eps->e[i].ep.floors);
880 r->out.entries[num_ents].tower->tower.num_floors = eps->e[i].ep.num_floors;
881 r->out.entries[num_ents].tower->tower_length = 0;
887 *r->out.num_ents = num_ents;
891 if (eps->count == 0) {
892 close_policy_hnd(p, entry_handle);
893 ZERO_STRUCTP(r->out.entry_handle);
894 rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
898 rc = EPMAPPER_STATUS_OK;
900 talloc_free(tmp_ctx);
908 * Apply some algorithm (using the fields in the map_tower) to an endpoint map
909 * to produce a list of protocol towers.
911 error_status_t _epm_Map(struct pipes_struct *p,
914 struct policy_handle *entry_handle;
915 enum dcerpc_transport_t transport;
916 struct ndr_syntax_id ifid;
917 struct epm_floor *floors;
922 uint32_t num_towers = 0;
926 *r->out.num_towers = 0;
927 r->out.towers = NULL;
929 if (r->in.map_tower == NULL || r->in.max_towers == 0 ||
930 r->in.map_tower->tower.num_floors < 3) {
931 return EPMAPPER_STATUS_NO_MORE_ENTRIES;
934 tmp_ctx = talloc_stackframe();
935 if (tmp_ctx == NULL) {
936 return EPMAPPER_STATUS_NO_MEMORY;
939 ZERO_STRUCTP(r->out.entry_handle);
941 DEBUG(5, ("_epm_Map: Trying to map max. %u towers.\n",
945 * A tower has normally up to 6 floors
947 * +-----------------------------------------------------------------+
948 * | Floor 1 | Provides the RPC interface identifier. (e.g. UUID for |
950 * +---------+-------------------------------------------------------+
951 * | Floor 2 | Transfer syntax (NDR endcoded) |
952 * +---------+-------------------------------------------------------+
953 * | Floor 3 | RPC protocol identifier (ncacn_tcp_ip, ncacn_np, ...) |
954 * +---------+-------------------------------------------------------+
955 * | Floor 4 | Port address (e.g. TCP Port: 49156) |
956 * +---------+-------------------------------------------------------+
957 * | Floor 5 | Transport (e.g. IP:192.168.51.10) |
958 * +---------+-------------------------------------------------------+
959 * | Floor 6 | Routing |
960 * +---------+-------------------------------------------------------+
962 floors = r->in.map_tower->tower.floors;
964 /* We accept NDR as the transfer syntax */
965 dcerpc_floor_get_lhs_data(&floors[1], &ifid);
967 if (floors[1].lhs.protocol != EPM_PROTOCOL_UUID ||
968 !GUID_equal(&ifid.uuid, &ndr_transfer_syntax_ndr.uuid) ||
969 ifid.if_version != ndr_transfer_syntax_ndr.if_version) {
970 rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
974 /* We only talk to sane transports */
975 transport = dcerpc_transport_by_tower(&r->in.map_tower->tower);
976 if (transport == NCA_UNKNOWN) {
977 DEBUG(2, ("epm_Map: Client requested unknown transport with"
979 for (i = 2; i < r->in.map_tower->tower.num_floors; i++) {
980 DEBUG(2, ("%d, ", r->in.map_tower->tower.floors[i].lhs.protocol));
983 rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
987 if (r->in.entry_handle == NULL ||
988 ndr_policy_handle_empty(r->in.entry_handle)) {
990 char *srv_addr = NULL;
992 DEBUG(7, ("_epm_Map: No entry_handle found, creating it.\n"));
994 eps = talloc_zero(tmp_ctx, struct rpc_eps);
996 rc = EPMAPPER_STATUS_NO_MEMORY;
1005 * Apply some algorithm (using the fields in the map_tower)
1006 * to an endpoint map to produce a list of protocol towers.
1008 * The following code is the mysterious "some algorithm"!
1011 /* Filter by object id if one was given. */
1012 if (r->in.object == NULL || GUID_all_zero(r->in.object)) {
1018 if (p->local_address != NULL &&
1019 tsocket_address_is_inet(p->local_address, "ipv4"))
1021 srv_addr = tsocket_address_inet_addr_string(p->local_address,
1025 eps->count = build_ep_list(eps,
1030 if (eps->count == 0) {
1031 rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
1035 /* Filter out endpoints which match the interface. */
1037 struct rpc_eps *teps;
1040 teps = talloc_zero(tmp_ctx, struct rpc_eps);
1042 rc = EPMAPPER_STATUS_NO_MEMORY;
1046 for (i = 0; i < eps->count; i++) {
1047 if (data_blob_cmp(&r->in.map_tower->tower.floors[0].lhs.lhs_data,
1048 &eps->e[i].ep.floors[0].lhs.lhs_data) != 0 ||
1049 transport != dcerpc_transport_by_tower(&eps->e[i].ep)) {
1053 teps->e = talloc_realloc(tmp_ctx,
1055 struct dcesrv_ep_iface,
1057 if (teps->e == NULL) {
1061 teps->e[total].ep.floors = talloc_move(teps, &eps->e[i].ep.floors);
1062 teps->e[total].ep.num_floors = eps->e[i].ep.num_floors;
1063 teps->e[total].name = talloc_move(teps, &eps->e[i].name);
1064 teps->e[total].syntax_id = eps->e[i].syntax_id;
1069 teps->count = total;
1073 /* end of "some algorithm" */
1075 ok = create_policy_hnd(p, r->out.entry_handle, eps);
1077 rc = EPMAPPER_STATUS_NO_MEMORY;
1081 ok = find_policy_by_hnd(p, r->out.entry_handle, (void **)(void*) &eps);
1083 rc = EPMAPPER_STATUS_NO_MEMORY;
1086 entry_handle = r->out.entry_handle;
1088 DEBUG(7, ("_epm_Map: Trying to find entry_handle.\n"));
1090 ok = find_policy_by_hnd(p, r->in.entry_handle, (void **)(void*) &eps);
1092 rc = EPMAPPER_STATUS_NO_MEMORY;
1095 entry_handle = r->in.entry_handle;
1098 if (eps == NULL || eps->e == NULL) {
1099 rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
1103 /* return the next N elements */
1104 count = r->in.max_towers;
1105 if (count > eps->count) {
1110 close_policy_hnd(p, entry_handle);
1111 ZERO_STRUCTP(r->out.entry_handle);
1113 rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
1117 r->out.towers = talloc_array(p->mem_ctx, struct epm_twr_p_t, count);
1118 if (r->out.towers == NULL) {
1119 rc = EPMAPPER_STATUS_NO_MEMORY;
1123 for (i = 0; i < count; i++) {
1124 DEBUG(7, ("_epm_Map: Map tower for '%s'\n",
1127 r->out.towers[num_towers].twr = talloc(r->out.towers,
1129 if (r->out.towers[num_towers].twr == NULL) {
1130 rc = EPMAPPER_STATUS_NO_MEMORY;
1133 r->out.towers[num_towers].twr->tower.floors = talloc_move(r->out.towers[num_towers].twr, &eps->e[i].ep.floors);
1134 r->out.towers[num_towers].twr->tower.num_floors = eps->e[i].ep.num_floors;
1135 r->out.towers[num_towers].twr->tower_length = 0;
1140 *r->out.num_towers = num_towers;
1142 eps->count -= count;
1144 if (eps->count == 0) {
1145 close_policy_hnd(p, entry_handle);
1146 ZERO_STRUCTP(r->out.entry_handle);
1149 rc = EPMAPPER_STATUS_OK;
1151 talloc_free(tmp_ctx);
1157 * epm_LookupHandleFree
1159 error_status_t _epm_LookupHandleFree(struct pipes_struct *p,
1160 struct epm_LookupHandleFree *r)
1162 if (r->in.entry_handle == NULL) {
1163 return EPMAPPER_STATUS_OK;
1166 if (is_valid_policy_hnd(r->in.entry_handle)) {
1167 close_policy_hnd(p, r->in.entry_handle);
1170 r->out.entry_handle = r->in.entry_handle;
1172 return EPMAPPER_STATUS_OK;
1179 * A client implementation SHOULD NOT call this method. These extensions do not
1180 * provide an alternative method.
1182 error_status_t _epm_InqObject(struct pipes_struct *p,
1183 struct epm_InqObject *r)
1185 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1186 return EPMAPPER_STATUS_CANT_PERFORM_OP;
1193 * A client implementation SHOULD NOT call this method. These extensions do not
1194 * provide an alternative method.
1196 error_status_t _epm_MgmtDelete(struct pipes_struct *p,
1197 struct epm_MgmtDelete *r)
1199 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1200 return EPMAPPER_STATUS_CANT_PERFORM_OP;
1207 error_status_t _epm_MapAuth(struct pipes_struct *p,
1208 struct epm_MapAuth *r)
1210 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1211 return EPMAPPER_STATUS_CANT_PERFORM_OP;
1214 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */