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_endpoint {
55 struct dcesrv_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_endpoint *endpoint_table;
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_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)) {
105 * See if a uuid and if_version match to an interface
107 static bool interface_match_by_uuid(const struct dcesrv_iface *iface,
108 const struct GUID *uuid)
110 return GUID_equal(&iface->syntax_id.uuid, uuid);
113 static struct dcesrv_iface_list *find_interface_list(const struct dcesrv_endpoint *endpoint,
114 const struct dcesrv_iface *iface)
116 struct dcesrv_iface_list *iflist;
118 for (iflist = endpoint->iface_list; iflist; iflist = iflist->next) {
119 if (interface_match(iflist->iface, iface)) {
128 * Check if two endpoints match.
130 static bool endpoints_match(const struct dcerpc_binding *ep1,
131 const struct dcerpc_binding *ep2)
133 if (ep1->transport != ep2->transport) {
137 if (!ep1->endpoint || !ep2->endpoint) {
138 return ep1->endpoint == ep2->endpoint;
141 if (!strequal(ep1->endpoint, ep2->endpoint)) {
145 if (!ep1->host || !ep2->host) {
146 return ep1->endpoint == ep2->endpoint;
149 if (!strequal(ep1->host, ep2->host)) {
156 static struct dcesrv_endpoint *find_endpoint(struct dcesrv_endpoint *endpoint_list,
157 struct dcerpc_binding *ep_description) {
158 struct dcesrv_endpoint *ep;
160 for (ep = endpoint_list; ep != NULL; ep = ep->next) {
161 if (endpoints_match(ep->ep_description, ep_description)) {
170 * Build a list of all interfaces handled by all endpoint servers.
172 static uint32_t build_ep_list(TALLOC_CTX *mem_ctx,
173 struct dcesrv_endpoint *endpoint_list,
174 const struct GUID *uuid,
175 const char *srv_addr,
176 struct dcesrv_ep_iface **peps)
178 struct dcesrv_ep_iface *eps = NULL;
179 struct dcesrv_endpoint *d;
185 for (d = endpoint_list; d != NULL; d = d->next) {
186 struct dcesrv_iface_list *iface;
187 struct dcerpc_binding *description;
189 for (iface = d->iface_list; iface != NULL; iface = iface->next) {
190 if (uuid && !interface_match_by_uuid(iface->iface, uuid)) {
194 eps = talloc_realloc(mem_ctx,
196 struct dcesrv_ep_iface,
201 eps[total].name = talloc_strdup(eps,
203 eps[total].syntax_id = iface->iface->syntax_id;
205 description = dcerpc_binding_dup(mem_ctx, d->ep_description);
206 if (description == NULL) {
209 description->object = iface->iface->syntax_id;
210 if (description->transport == NCACN_IP_TCP &&
212 (strcmp(description->host, "0.0.0.0") == 0 ||
213 strcmp(description->host, "::") == 0)) {
214 description->host = srv_addr;
217 status = dcerpc_binding_build_tower(eps,
220 TALLOC_FREE(description);
221 if (NT_STATUS_IS_ERR(status)) {
222 DEBUG(1, ("Unable to build tower for %s\n",
223 iface->iface->name));
235 static bool is_priviledged_pipe(struct auth_serversupplied_info *info) {
236 /* If the user is not root, or has the system token, fail */
237 if ((info->utok.uid != sec_initial_uid()) &&
238 !security_token_is_system(info->security_token)) {
245 bool srv_epmapper_delete_endpoints(struct pipes_struct *p)
248 struct dcesrv_ep_entry_list *el = p->ep_entries;
249 error_status_t result;
252 struct dcesrv_ep_entry_list *next = el->next;
254 r.in.num_ents = el->num_ents;
255 r.in.entries = el->entries;
257 DEBUG(10, ("Delete_endpoints for: %s\n",
258 el->entries[0].annotation));
260 result = _epm_Delete(p, &r);
261 if (result != EPMAPPER_STATUS_OK) {
265 DLIST_REMOVE(p->ep_entries, el);
274 void srv_epmapper_cleanup(void)
276 struct dcesrv_endpoint *ep = endpoint_table;
279 struct dcesrv_endpoint *next = ep->next;
281 DLIST_REMOVE(endpoint_table, ep);
291 * Add the specified entries to an endpoint map.
293 error_status_t _epm_Insert(struct pipes_struct *p,
294 struct epm_Insert *r)
300 struct dcerpc_binding *b;
301 struct dcesrv_endpoint *ep;
302 struct dcesrv_iface_list *iflist;
303 struct dcesrv_iface *iface;
306 /* If this is not a priviledged users, return */
307 if (p->transport != NCALRPC ||
308 !is_priviledged_pipe(p->session_info)) {
309 return EPMAPPER_STATUS_CANT_PERFORM_OP;
312 tmp_ctx = talloc_stackframe();
313 if (tmp_ctx == NULL) {
314 return EPMAPPER_STATUS_NO_MEMORY;
317 DEBUG(3, ("_epm_Insert: Trying to add %u new entries.\n",
320 for (i = 0; i < r->in.num_ents; i++) {
324 status = dcerpc_binding_from_tower(tmp_ctx,
325 &r->in.entries[i].tower->tower,
327 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) {
328 rc = EPMAPPER_STATUS_NO_MEMORY;
331 if (!NT_STATUS_IS_OK(status)) {
332 rc = EPMAPPER_STATUS_CANT_PERFORM_OP;
336 DEBUG(3, ("_epm_Insert: Adding transport %s for %s\n",
337 derpc_transport_string_by_transport(b->transport),
338 r->in.entries[i].annotation));
340 /* Check if the entry already exits */
341 ep = find_endpoint(endpoint_table, b);
343 /* No entry found, create it */
344 ep = talloc_zero(NULL, struct dcesrv_endpoint);
346 rc = EPMAPPER_STATUS_NO_MEMORY;
351 ep->ep_description = talloc_steal(ep, b);
354 /* TODO Replace the entry if the replace flag is set */
356 /* Create an interface */
357 iface = talloc(tmp_ctx, struct dcesrv_iface);
359 rc = EPMAPPER_STATUS_NO_MEMORY;
363 iface->name = talloc_strdup(iface, r->in.entries[i].annotation);
364 if (iface->name == NULL) {
365 rc = EPMAPPER_STATUS_NO_MEMORY;
368 iface->syntax_id = b->object;
371 * Check if the rpc service is alrady registered on the
374 if (find_interface(ep, iface) != NULL) {
375 DEBUG(0, ("dcesrv_interface_register: interface '%s' "
376 "already registered on endpoint\n",
378 /* FIXME wrong error code? */
379 rc = EPMAPPER_STATUS_OK;
383 /* Create an entry for the interface */
384 iflist = talloc(ep, struct dcesrv_iface_list);
385 if (iflist == NULL) {
386 rc = EPMAPPER_STATUS_NO_MEMORY;
389 iflist->iface = talloc_move(iflist, &iface);
391 /* Finally add the interface on the endpoint */
392 DLIST_ADD(ep->iface_list, iflist);
394 /* If it's a new endpoint add it to the endpoint_table */
396 DLIST_ADD(endpoint_table, ep);
400 if (r->in.num_ents > 0) {
401 struct dcesrv_ep_entry_list *el;
403 el = talloc_zero(p, struct dcesrv_ep_entry_list);
405 rc = EPMAPPER_STATUS_NO_MEMORY;
408 el->num_ents = r->in.num_ents;
409 el->entries = talloc_move(el, &r->in.entries);
411 DLIST_ADD(p->ep_entries, el);
414 rc = EPMAPPER_STATUS_OK;
416 talloc_free(tmp_ctx);
425 * Delete the specified entries from an endpoint map.
427 error_status_t _epm_Delete(struct pipes_struct *p,
428 struct epm_Delete *r)
434 struct dcerpc_binding *b;
435 struct dcesrv_endpoint *ep;
436 struct dcesrv_iface iface;
437 struct dcesrv_iface_list *iflist;
439 DEBUG(3, ("_epm_Delete: Trying to delete %u entries.\n",
442 /* If this is not a priviledged users, return */
443 if (p->transport != NCALRPC ||
444 !is_priviledged_pipe(p->session_info)) {
445 return EPMAPPER_STATUS_CANT_PERFORM_OP;
448 tmp_ctx = talloc_stackframe();
449 if (tmp_ctx == NULL) {
450 return EPMAPPER_STATUS_NO_MEMORY;
453 for (i = 0; i < r->in.num_ents; i++) {
456 status = dcerpc_binding_from_tower(tmp_ctx,
457 &r->in.entries[i].tower->tower,
459 if (!NT_STATUS_IS_OK(status)) {
460 rc = EPMAPPER_STATUS_NO_MEMORY;
464 DEBUG(3, ("_epm_Delete: Deleting transport '%s' for '%s'\n",
465 derpc_transport_string_by_transport(b->transport),
466 r->in.entries[i].annotation));
468 ep = find_endpoint(endpoint_table, b);
470 rc = EPMAPPER_STATUS_OK;
474 iface.name = r->in.entries[i].annotation;
475 iface.syntax_id = b->object;
477 iflist = find_interface_list(ep, &iface);
478 if (iflist == NULL) {
479 DEBUG(0, ("_epm_Delete: No interfaces left, delete endpoint\n"));
480 DLIST_REMOVE(endpoint_table, ep);
483 rc = EPMAPPER_STATUS_OK;
487 DLIST_REMOVE(ep->iface_list, iflist);
489 if (ep->iface_list == NULL) {
490 DEBUG(0, ("_epm_Delete: No interfaces left, delete endpoint\n"));
491 DLIST_REMOVE(endpoint_table, ep);
494 rc = EPMAPPER_STATUS_OK;
500 rc = EPMAPPER_STATUS_OK;
502 talloc_free(tmp_ctx);
511 * Lookup entries in an endpoint map.
513 error_status_t _epm_Lookup(struct pipes_struct *p,
514 struct epm_Lookup *r)
516 struct policy_handle *entry_handle;
521 uint32_t num_ents = 0;
526 *r->out.num_ents = 0;
527 r->out.entries = NULL;
529 tmp_ctx = talloc_stackframe();
530 if (tmp_ctx == NULL) {
531 return EPMAPPER_STATUS_NO_MEMORY;
534 DEBUG(5, ("_epm_Lookup: Trying to lookup max. %u entries.\n",
537 if (r->in.entry_handle == NULL ||
538 policy_handle_empty(r->in.entry_handle)) {
540 char *srv_addr = NULL;
542 DEBUG(7, ("_epm_Lookup: No entry_handle found, creating it.\n"));
544 eps = talloc_zero(tmp_ctx, struct rpc_eps);
546 rc = EPMAPPER_STATUS_NO_MEMORY;
550 if (r->in.object == NULL || GUID_all_zero(r->in.object)) {
556 if (p->local_address != NULL) {
557 srv_addr = tsocket_address_inet_addr_string(p->local_address,
561 switch (r->in.inquiry_type) {
562 case RPC_C_EP_ALL_ELTS:
564 * Return all elements from the endpoint map. The
565 * interface_id, vers_option, and object parameters MUST
568 eps->count = build_ep_list(eps,
574 case RPC_C_EP_MATCH_BY_IF:
576 * Return endpoint map elements that contain the
577 * interface identifier specified by the interface_id
578 * and vers_option values.
580 * RPC_C_EP_MATCH_BY_IF and RPC_C_EP_MATCH_BY_BOTH
581 * need both the same endpoint list. There is a second
582 * check for the inquiry_type below which differentiates
585 case RPC_C_EP_MATCH_BY_BOTH:
587 * Return endpoint map elements that contain the
588 * interface identifier and object UUID specified by
589 * interface_id, vers_option, and object.
591 eps->count = build_ep_list(eps,
593 &r->in.interface_id->uuid,
597 case RPC_C_EP_MATCH_BY_OBJ:
599 * Return endpoint map elements that contain the object
600 * UUID specified by object.
602 eps->count = build_ep_list(eps,
609 rc = EPMAPPER_STATUS_CANT_PERFORM_OP;
613 if (eps->count == 0) {
614 rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
618 ok = create_policy_hnd(p, r->out.entry_handle, eps);
620 rc = EPMAPPER_STATUS_NO_MEMORY;
624 ok = find_policy_by_hnd(p, r->out.entry_handle, (void **)(void*) &eps);
626 rc = EPMAPPER_STATUS_NO_MEMORY;
629 entry_handle = r->out.entry_handle;
631 DEBUG(7, ("_epm_Lookup: Trying to find entry_handle.\n"));
633 ok = find_policy_by_hnd(p, r->in.entry_handle, (void **)(void*) &eps);
635 rc = EPMAPPER_STATUS_NO_MEMORY;
638 entry_handle = r->in.entry_handle;
641 if (eps == NULL || eps->e == NULL) {
642 rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
646 /* return the next N elements */
647 count = r->in.max_ents;
648 if (count > eps->count) {
652 DEBUG(5, ("_epm_Lookup: Find %u entries\n", count));
655 close_policy_hnd(p, entry_handle);
656 ZERO_STRUCTP(r->out.entry_handle);
658 rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
662 r->out.entries = talloc_array(p->mem_ctx, struct epm_entry_t, count);
663 if (r->out.entries == NULL) {
664 rc = EPMAPPER_STATUS_NO_MEMORY;
668 for (i = 0; i < count; i++) {
671 switch (r->in.inquiry_type) {
672 case RPC_C_EP_ALL_ELTS:
674 * Return all elements from the endpoint map. The
675 * interface_id, vers_option, and object parameters MUST
680 case RPC_C_EP_MATCH_BY_IF:
682 * Return endpoint map elements that contain the
683 * interface identifier specified by the interface_id
684 * and vers_option values.
686 if (GUID_equal(&r->in.interface_id->uuid,
687 &eps->e[i].syntax_id.uuid)) {
691 case RPC_C_EP_MATCH_BY_OBJ:
693 * Return endpoint map elements that contain the object
694 * UUID specified by object.
696 if (GUID_equal(r->in.object,
697 &eps->e[i].syntax_id.uuid)) {
701 case RPC_C_EP_MATCH_BY_BOTH:
703 * Return endpoint map elements that contain the
704 * interface identifier and object UUID specified by
705 * interface_id, vers_option, and object.
707 if (GUID_equal(&r->in.interface_id->uuid,
708 &eps->e[i].syntax_id.uuid) &&
709 GUID_equal(r->in.object, &eps->e[i].syntax_id.uuid)) {
714 return EPMAPPER_STATUS_CANT_PERFORM_OP;
718 if (r->in.inquiry_type == RPC_C_EP_MATCH_BY_IF ||
719 r->in.inquiry_type == RPC_C_EP_MATCH_BY_OBJ) {
720 /* Check inteface version */
723 switch (r->in.vers_option) {
726 * Return endpoint map elements that
727 * contain the specified interface UUID,
728 * regardless of the version numbers.
732 case RPC_C_VERS_COMPATIBLE:
734 * Return the endpoint map elements that
735 * contain the same major versions of
736 * the specified interface UUID and a
737 * minor version greater than or equal
738 * to the minor version of the specified
741 if (r->in.interface_id->vers_major ==
742 (eps->e[i].syntax_id.if_version >> 16) &&
743 r->in.interface_id->vers_minor <=
744 (eps->e[i].syntax_id.if_version && 0xFFFF)) {
748 case RPC_C_VERS_EXACT:
750 * Return endpoint map elements that
751 * contain the specified version of the
752 * specified interface UUID.
754 if (r->in.interface_id->vers_major ==
755 (eps->e[i].syntax_id.if_version >> 16) &&
756 r->in.interface_id->vers_minor ==
757 (eps->e[i].syntax_id.if_version && 0xFFFF)) {
762 case RPC_C_VERS_MAJOR_ONLY:
764 * Return endpoint map elements that
765 * contain the same version of the
766 * specified interface UUID and ignore
769 if (r->in.interface_id->vers_major ==
770 (eps->e[i].syntax_id.if_version >> 16)) {
775 case RPC_C_VERS_UPTO:
777 * Return endpoint map elements that
778 * contain a version of the specified
779 * interface UUID less than or equal to
780 * the specified major and minor
783 if (r->in.interface_id->vers_major >
784 eps->e[i].syntax_id.if_version >> 16) {
787 if (r->in.interface_id->vers_major ==
788 (eps->e[i].syntax_id.if_version >> 16) &&
789 r->in.interface_id->vers_minor >=
790 (eps->e[i].syntax_id.if_version && 0xFFFF)) {
796 return EPMAPPER_STATUS_CANT_PERFORM_OP;
802 ZERO_STRUCT(r->out.entries[num_ents].object);
804 DEBUG(10, ("_epm_Lookup: Adding tower for '%s'\n",
806 r->out.entries[num_ents].annotation = talloc_strdup(r->out.entries,
808 r->out.entries[num_ents].tower = talloc(r->out.entries,
810 if (r->out.entries[num_ents].tower == NULL) {
811 rc = EPMAPPER_STATUS_NO_MEMORY;
814 r->out.entries[num_ents].tower->tower.floors = talloc_move(r->out.entries[num_ents].tower, &eps->e[i].ep.floors);
815 r->out.entries[num_ents].tower->tower.num_floors = eps->e[i].ep.num_floors;
816 r->out.entries[num_ents].tower->tower_length = 0;
822 *r->out.num_ents = num_ents;
826 if (eps->count == 0) {
827 close_policy_hnd(p, entry_handle);
828 ZERO_STRUCTP(r->out.entry_handle);
829 rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
833 rc = EPMAPPER_STATUS_OK;
835 talloc_free(tmp_ctx);
843 * Apply some algorithm (using the fields in the map_tower) to an endpoint map
844 * to produce a list of protocol towers.
846 error_status_t _epm_Map(struct pipes_struct *p,
849 struct policy_handle *entry_handle;
850 enum dcerpc_transport_t transport;
851 struct ndr_syntax_id ifid;
852 struct epm_floor *floors;
857 uint32_t num_towers = 0;
858 uint32_t num_floors = 0;
862 *r->out.num_towers = 0;
863 r->out.towers = NULL;
865 if (r->in.map_tower == NULL || r->in.max_towers == 0 ||
866 r->in.map_tower->tower.num_floors < 3) {
867 return EPMAPPER_STATUS_NO_MORE_ENTRIES;
870 tmp_ctx = talloc_stackframe();
871 if (tmp_ctx == NULL) {
872 return EPMAPPER_STATUS_NO_MEMORY;
875 ZERO_STRUCTP(r->out.entry_handle);
877 DEBUG(5, ("_epm_Map: Trying to map max. %u towers.\n",
881 * A tower has normally up to 6 floors
883 * +-----------------------------------------------------------------+
884 * | Floor 1 | Provides the RPC interface identifier. (e.g. UUID for |
886 * +---------+-------------------------------------------------------+
887 * | Floor 2 | Transfer syntax (NDR endcoded) |
888 * +---------+-------------------------------------------------------+
889 * | Floor 3 | RPC protocol identifier (ncacn_tcp_ip, ncacn_np, ...) |
890 * +---------+-------------------------------------------------------+
891 * | Floor 4 | Port address (e.g. TCP Port: 49156) |
892 * +---------+-------------------------------------------------------+
893 * | Floor 5 | Transport (e.g. IP:192.168.51.10) |
894 * +---------+-------------------------------------------------------+
895 * | Floor 6 | Routing |
896 * +---------+-------------------------------------------------------+
898 num_floors = r->in.map_tower->tower.num_floors;
899 floors = r->in.map_tower->tower.floors;
901 /* We accept NDR as the transfer syntax */
902 dcerpc_floor_get_lhs_data(&floors[1], &ifid);
904 if (floors[1].lhs.protocol != EPM_PROTOCOL_UUID ||
905 !GUID_equal(&ifid.uuid, &ndr_transfer_syntax.uuid) ||
906 ifid.if_version != ndr_transfer_syntax.if_version) {
907 rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
911 /* We only talk to sane transports */
912 transport = dcerpc_transport_by_tower(&r->in.map_tower->tower);
913 if (transport == NCA_UNKNOWN) {
914 DEBUG(2, ("epm_Map: Client requested unknown transport with"
916 for (i = 2; i < r->in.map_tower->tower.num_floors; i++) {
917 DEBUG(2, ("%d, ", r->in.map_tower->tower.floors[i].lhs.protocol));
920 rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
924 if (r->in.entry_handle == NULL ||
925 policy_handle_empty(r->in.entry_handle)) {
927 char *srv_addr = NULL;
929 DEBUG(7, ("_epm_Map: No entry_handle found, creating it.\n"));
931 eps = talloc_zero(tmp_ctx, struct rpc_eps);
933 rc = EPMAPPER_STATUS_NO_MEMORY;
942 * Apply some algorithm (using the fields in the map_tower)
943 * to an endpoint map to produce a list of protocol towers.
945 * The following code is the mysterious "some algorithm"!
948 /* Filter by object id if one was given. */
949 if (r->in.object == NULL || GUID_all_zero(r->in.object)) {
955 if (p->local_address != NULL) {
956 srv_addr = tsocket_address_inet_addr_string(p->local_address,
960 eps->count = build_ep_list(eps,
965 if (eps->count == 0) {
966 rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
970 /* Filter out endpoints which match the interface. */
972 struct rpc_eps *teps;
975 teps = talloc_zero(tmp_ctx, struct rpc_eps);
977 rc = EPMAPPER_STATUS_NO_MEMORY;
981 for (i = 0; i < eps->count; i++) {
982 if (data_blob_cmp(&r->in.map_tower->tower.floors[0].lhs.lhs_data,
983 &eps->e[i].ep.floors[0].lhs.lhs_data) != 0 ||
984 transport != dcerpc_transport_by_tower(&eps->e[i].ep)) {
988 teps->e = talloc_realloc(tmp_ctx,
990 struct dcesrv_ep_iface,
992 if (teps->e == NULL) {
996 teps->e[total].ep.floors = talloc_move(teps, &eps->e[i].ep.floors);
997 teps->e[total].ep.num_floors = eps->e[i].ep.num_floors;
998 teps->e[total].name = talloc_move(teps, &eps->e[i].name);
999 teps->e[total].syntax_id = eps->e[i].syntax_id;
1004 teps->count = total;
1008 /* end of "some algorithm" */
1010 ok = create_policy_hnd(p, r->out.entry_handle, eps);
1012 rc = EPMAPPER_STATUS_NO_MEMORY;
1016 ok = find_policy_by_hnd(p, r->out.entry_handle, (void **)(void*) &eps);
1018 rc = EPMAPPER_STATUS_NO_MEMORY;
1021 entry_handle = r->out.entry_handle;
1023 DEBUG(7, ("_epm_Map: Trying to find entry_handle.\n"));
1025 ok = find_policy_by_hnd(p, r->in.entry_handle, (void **)(void*) &eps);
1027 rc = EPMAPPER_STATUS_NO_MEMORY;
1030 entry_handle = r->in.entry_handle;
1033 if (eps == NULL || eps->e == NULL) {
1034 rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
1038 /* return the next N elements */
1039 count = r->in.max_towers;
1040 if (count > eps->count) {
1045 close_policy_hnd(p, entry_handle);
1046 ZERO_STRUCTP(r->out.entry_handle);
1048 rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
1052 r->out.towers = talloc_array(p->mem_ctx, struct epm_twr_p_t, count);
1053 if (r->out.towers == NULL) {
1054 rc = EPMAPPER_STATUS_NO_MEMORY;
1058 for (i = 0; i < count; i++) {
1059 DEBUG(7, ("_epm_Map: Map tower for '%s'\n",
1062 r->out.towers[num_towers].twr = talloc(r->out.towers,
1064 if (r->out.towers[num_towers].twr == NULL) {
1065 rc = EPMAPPER_STATUS_NO_MEMORY;
1068 r->out.towers[num_towers].twr->tower.floors = talloc_move(r->out.towers[num_towers].twr, &eps->e[i].ep.floors);
1069 r->out.towers[num_towers].twr->tower.num_floors = eps->e[i].ep.num_floors;
1070 r->out.towers[num_towers].twr->tower_length = 0;
1075 *r->out.num_towers = num_towers;
1077 eps->count -= count;
1079 if (eps->count == 0) {
1080 close_policy_hnd(p, entry_handle);
1081 ZERO_STRUCTP(r->out.entry_handle);
1084 rc = EPMAPPER_STATUS_OK;
1086 talloc_free(tmp_ctx);
1092 * epm_LookupHandleFree
1094 error_status_t _epm_LookupHandleFree(struct pipes_struct *p,
1095 struct epm_LookupHandleFree *r)
1097 if (r->in.entry_handle == NULL) {
1098 return EPMAPPER_STATUS_OK;
1101 if (is_valid_policy_hnd(r->in.entry_handle)) {
1102 close_policy_hnd(p, r->in.entry_handle);
1105 r->out.entry_handle = r->in.entry_handle;
1107 return EPMAPPER_STATUS_OK;
1114 * A client implementation SHOULD NOT call this method. These extensions do not
1115 * provide an alternative method.
1117 error_status_t _epm_InqObject(struct pipes_struct *p,
1118 struct epm_InqObject *r)
1120 p->rng_fault_state = true;
1121 return EPMAPPER_STATUS_CANT_PERFORM_OP;
1128 * A client implementation SHOULD NOT call this method. These extensions do not
1129 * provide an alternative method.
1131 error_status_t _epm_MgmtDelete(struct pipes_struct *p,
1132 struct epm_MgmtDelete *r)
1134 p->rng_fault_state = true;
1135 return EPMAPPER_STATUS_CANT_PERFORM_OP;
1142 error_status_t _epm_MapAuth(struct pipes_struct *p,
1143 struct epm_MapAuth *r)
1145 p->rng_fault_state = true;
1146 return EPMAPPER_STATUS_CANT_PERFORM_OP;
1149 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */