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/>.
23 #include "../libcli/security/security.h"
24 #include "librpc/gen_ndr/ndr_epmapper.h"
25 #include "librpc/gen_ndr/srv_epmapper.h"
27 typedef uint32_t error_status_t;
29 /* An endpoint combined with an interface description */
30 struct dcesrv_ep_iface {
32 struct ndr_syntax_id syntax_id;
36 /* A rpc service interface like samr, lsarpc or netlogon */
39 struct ndr_syntax_id syntax_id;
42 struct dcesrv_iface_list {
43 struct dcesrv_iface_list *next, *prev;
44 struct dcesrv_iface *iface;
48 * An endpoint can serve multiple rpc services interfaces.
49 * For example \\pipe\netlogon can be used by lsarpc and netlogon.
51 struct dcesrv_endpoint {
52 struct dcesrv_endpoint *next, *prev;
54 /* The type and the location of the endpoint */
55 struct dcerpc_binding *ep_description;
57 /* A list of rpc services able to connect to the endpoint */
58 struct dcesrv_iface_list *iface_list;
62 struct dcesrv_ep_iface *e;
66 static struct dcesrv_endpoint *endpoint_table;
69 * Check if the UUID and if_version match to an interface.
71 static bool interface_match(const struct dcesrv_iface *if1,
72 const struct dcesrv_iface *if2)
74 return GUID_equal(&if1->syntax_id.uuid, &if2->syntax_id.uuid);
78 * Find the interface operations on an endpoint.
80 static const struct dcesrv_iface *find_interface(const struct dcesrv_endpoint *endpoint,
81 const struct dcesrv_iface *iface)
83 struct dcesrv_iface_list *iflist;
85 for (iflist = endpoint->iface_list; iflist; iflist = iflist->next) {
86 if (interface_match(iflist->iface, iface)) {
95 * See if a uuid and if_version match to an interface
97 static bool interface_match_by_uuid(const struct dcesrv_iface *iface,
98 const struct GUID *uuid)
100 return GUID_equal(&iface->syntax_id.uuid, uuid);
103 static struct dcesrv_iface_list *find_interface_list(const struct dcesrv_endpoint *endpoint,
104 const struct dcesrv_iface *iface)
106 struct dcesrv_iface_list *iflist;
108 for (iflist = endpoint->iface_list; iflist; iflist = iflist->next) {
109 if (interface_match(iflist->iface, iface)) {
118 * Check if two endpoints match.
120 static bool endpoints_match(const struct dcerpc_binding *ep1,
121 const struct dcerpc_binding *ep2)
123 if (ep1->transport != ep2->transport) {
127 if (!ep1->endpoint || !ep2->endpoint) {
128 return ep1->endpoint == ep2->endpoint;
131 if (!strequal(ep1->endpoint, ep2->endpoint)) {
138 static struct dcesrv_endpoint *find_endpoint(struct dcesrv_endpoint *endpoint_list,
139 struct dcerpc_binding *ep_description) {
140 struct dcesrv_endpoint *ep;
142 for (ep = endpoint_list; ep != NULL; ep = ep->next) {
143 if (endpoints_match(ep->ep_description, ep_description)) {
152 * Build a list of all interfaces handled by all endpoint servers.
154 static uint32_t build_ep_list(TALLOC_CTX *mem_ctx,
155 struct dcesrv_endpoint *endpoint_list,
156 const struct GUID *uuid,
157 struct dcesrv_ep_iface **peps)
159 struct dcesrv_ep_iface *eps = NULL;
160 struct dcesrv_endpoint *d;
166 for (d = endpoint_list; d != NULL; d = d->next) {
167 struct dcesrv_iface_list *iface;
168 struct dcerpc_binding *description;
170 for (iface = d->iface_list; iface != NULL; iface = iface->next) {
171 if (uuid && !interface_match_by_uuid(iface->iface, uuid)) {
175 eps = talloc_realloc(mem_ctx,
177 struct dcesrv_ep_iface,
182 eps[total].name = talloc_strdup(eps,
184 eps[total].syntax_id = iface->iface->syntax_id;
186 description = d->ep_description;
187 description->object = iface->iface->syntax_id;
189 status = dcerpc_binding_build_tower(eps,
192 if (NT_STATUS_IS_ERR(status)) {
193 DEBUG(1, ("Unable to build tower for %s\n",
194 iface->iface->name));
206 static bool is_priviledged_pipe(struct auth_serversupplied_info *info) {
207 /* If the user is not root, or has the system token, fail */
208 if ((info->utok.uid != sec_initial_uid()) &&
209 !security_token_is_system(info->security_token)) {
219 * Add the specified entries to an endpoint map.
221 error_status_t _epm_Insert(struct pipes_struct *p,
222 struct epm_Insert *r)
229 /* If this is not a priviledged users, return */
230 if (!is_priviledged_pipe(p->server_info)) {
231 return EPMAPPER_STATUS_CANT_PERFORM_OP;
234 tmp_ctx = talloc_stackframe();
235 if (tmp_ctx == NULL) {
236 return EPMAPPER_STATUS_NO_MEMORY;
239 DEBUG(3, ("_epm_Insert: Trying to add %u new entries.\n",
242 for (i = 0; i < r->in.num_ents; i++) {
243 struct dcerpc_binding *b = NULL;
244 struct dcesrv_endpoint *ep;
245 struct dcesrv_iface_list *iflist;
246 struct dcesrv_iface *iface;
249 status = dcerpc_binding_from_tower(tmp_ctx,
250 &r->in.entries[i].tower->tower,
252 if (!NT_STATUS_IS_OK(status)) {
253 rc = EPMAPPER_STATUS_NO_MEMORY;
257 DEBUG(3, ("_epm_Insert: Adding transport %s for %s\n",
258 derpc_transport_string_by_transport(b->transport),
259 r->in.entries[i].annotation));
261 /* Check if the entry already exits */
262 ep = find_endpoint(endpoint_table, b);
264 /* No entry found, create it */
265 ep = talloc_zero(NULL, struct dcesrv_endpoint);
267 rc = EPMAPPER_STATUS_CANT_PERFORM_OP;
272 ep->ep_description = talloc_steal(ep, b);
275 /* TODO Replace the entry if the replace flag is set */
277 /* Create an interface */
278 iface = talloc(tmp_ctx, struct dcesrv_iface);
280 rc = EPMAPPER_STATUS_NO_MEMORY;
284 iface->name = talloc_strdup(iface, r->in.entries[i].annotation);
285 if (iface->name == NULL) {
286 rc = EPMAPPER_STATUS_NO_MEMORY;
289 iface->syntax_id = b->object;
292 * Check if the rpc service is alrady registered on the
295 if (find_interface(ep, iface) != NULL) {
296 DEBUG(0, ("dcesrv_interface_register: interface '%s' "
297 "already registered on endpoint\n",
299 /* FIXME wrong error code? */
300 rc = EPMAPPER_STATUS_OK;
304 /* Create an entry for the interface */
305 iflist = talloc(ep, struct dcesrv_iface_list);
306 if (iflist == NULL) {
307 rc = EPMAPPER_STATUS_NO_MEMORY;
310 iflist->iface = talloc_move(iflist, &iface);
312 /* Finally add the interface on the endpoint */
313 DLIST_ADD(ep->iface_list, iflist);
315 /* If it's a new endpoint add it to the endpoint_table */
317 DLIST_ADD(endpoint_table, ep);
321 rc = EPMAPPER_STATUS_OK;
323 talloc_free(tmp_ctx);
332 * Delete the specified entries from an endpoint map.
334 error_status_t _epm_Delete(struct pipes_struct *p,
335 struct epm_Delete *r)
342 DEBUG(3, ("_epm_Delete: Trying to delete %u entries.\n",
345 /* If this is not a priviledged users, return */
346 if (!is_priviledged_pipe(p->server_info)) {
347 return EPMAPPER_STATUS_CANT_PERFORM_OP;
350 tmp_ctx = talloc_stackframe();
351 if (tmp_ctx == NULL) {
352 return EPMAPPER_STATUS_NO_MEMORY;
355 for (i = 0; i < r->in.num_ents; i++) {
356 struct dcerpc_binding *b = NULL;
357 struct dcesrv_endpoint *ep;
358 struct dcesrv_iface iface;
359 struct dcesrv_iface_list *iflist;
361 status = dcerpc_binding_from_tower(tmp_ctx,
362 &r->in.entries[i].tower->tower,
364 if (!NT_STATUS_IS_OK(status)) {
365 rc = EPMAPPER_STATUS_NO_MEMORY;
369 DEBUG(3, ("_epm_Delete: Deleting transport '%s' for '%s'\n",
370 derpc_transport_string_by_transport(b->transport),
371 r->in.entries[i].annotation));
373 ep = find_endpoint(endpoint_table, b);
375 rc = EPMAPPER_STATUS_OK;
379 iface.name = r->in.entries[i].annotation;
380 iface.syntax_id = b->object;
382 iflist = find_interface_list(ep, &iface);
383 if (iflist == NULL) {
384 DEBUG(0, ("_epm_Delete: No interfaces left, delete endpoint\n"));
385 DLIST_REMOVE(endpoint_table, ep);
388 rc = EPMAPPER_STATUS_OK;
392 DLIST_REMOVE(ep->iface_list, iflist);
394 if (ep->iface_list == NULL) {
395 DEBUG(0, ("_epm_Delete: No interfaces left, delete endpoint\n"));
396 DLIST_REMOVE(endpoint_table, ep);
399 rc = EPMAPPER_STATUS_OK;
405 rc = EPMAPPER_STATUS_OK;
407 talloc_free(tmp_ctx);
416 * Lookup entries in an endpoint map.
418 error_status_t _epm_Lookup(struct pipes_struct *p,
419 struct epm_Lookup *r)
421 struct policy_handle *entry_handle;
426 uint32_t num_ents = 0;
431 *r->out.num_ents = 0;
432 r->out.entries = NULL;
434 tmp_ctx = talloc_stackframe();
435 if (tmp_ctx == NULL) {
436 return EPMAPPER_STATUS_NO_MEMORY;
439 DEBUG(3, ("_epm_Lookup: Trying to lookup max. %u entries.\n",
442 if (r->in.entry_handle == NULL ||
443 policy_handle_empty(r->in.entry_handle)) {
446 DEBUG(5, ("_epm_Lookup: No entry_handle found, creating it.\n"));
448 eps = talloc_zero(tmp_ctx, struct rpc_eps);
450 rc = EPMAPPER_STATUS_NO_MEMORY;
454 if (r->in.object == NULL || GUID_all_zero(r->in.object)) {
460 switch (r->in.inquiry_type) {
461 case RPC_C_EP_ALL_ELTS:
463 * Return all elements from the endpoint map. The
464 * interface_id, vers_option, and object parameters MUST
467 eps->count = build_ep_list(eps,
472 case RPC_C_EP_MATCH_BY_IF:
474 * Return endpoint map elements that contain the
475 * interface identifier specified by the interface_id
476 * and vers_option values.
478 * RPC_C_EP_MATCH_BY_IF and RPC_C_EP_MATCH_BY_BOTH
479 * need both the same endpoint list. There is a second
480 * check for the inquiry_type below which differentiates
483 case RPC_C_EP_MATCH_BY_BOTH:
485 * Return endpoint map elements that contain the
486 * interface identifier and object UUID specified by
487 * interface_id, vers_option, and object.
489 eps->count = build_ep_list(eps,
491 &r->in.interface_id->uuid,
494 case RPC_C_EP_MATCH_BY_OBJ:
496 * Return endpoint map elements that contain the object
497 * UUID specified by object.
499 eps->count = build_ep_list(eps,
505 rc = EPMAPPER_STATUS_CANT_PERFORM_OP;
509 if (eps->count == 0) {
510 rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
514 ok = create_policy_hnd(p, r->out.entry_handle, eps);
516 rc = EPMAPPER_STATUS_NO_MEMORY;
520 ok = find_policy_by_hnd(p, r->out.entry_handle, (void **)(void*) &eps);
522 rc = EPMAPPER_STATUS_NO_MEMORY;
525 entry_handle = r->out.entry_handle;
527 DEBUG(5, ("_epm_Lookup: Trying to find entry_handle.\n"));
529 ok = find_policy_by_hnd(p, r->in.entry_handle, (void **)(void*) &eps);
531 rc = EPMAPPER_STATUS_NO_MEMORY;
534 entry_handle = r->in.entry_handle;
537 if (eps == NULL || eps->e == NULL) {
538 rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
542 /* return the next N elements */
543 count = r->in.max_ents;
544 if (count > eps->count) {
548 DEBUG(3, ("_epm_Lookup: Find %u entries\n", count));
551 close_policy_hnd(p, entry_handle);
552 ZERO_STRUCTP(r->out.entry_handle);
554 rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
558 r->out.entries = talloc_array(p->mem_ctx, struct epm_entry_t, count);
559 if (r->out.entries == NULL) {
560 rc = EPMAPPER_STATUS_NO_MEMORY;
564 for (i = 0; i < count; i++) {
567 switch (r->in.inquiry_type) {
568 case RPC_C_EP_ALL_ELTS:
570 * Return all elements from the endpoint map. The
571 * interface_id, vers_option, and object parameters MUST
576 case RPC_C_EP_MATCH_BY_IF:
578 * Return endpoint map elements that contain the
579 * interface identifier specified by the interface_id
580 * and vers_option values.
582 if (GUID_equal(&r->in.interface_id->uuid,
583 &eps->e[i].syntax_id.uuid)) {
587 case RPC_C_EP_MATCH_BY_OBJ:
589 * Return endpoint map elements that contain the object
590 * UUID specified by object.
592 if (GUID_equal(r->in.object,
593 &eps->e[i].syntax_id.uuid)) {
597 case RPC_C_EP_MATCH_BY_BOTH:
599 * Return endpoint map elements that contain the
600 * interface identifier and object UUID specified by
601 * interface_id, vers_option, and object.
603 if (GUID_equal(&r->in.interface_id->uuid,
604 &eps->e[i].syntax_id.uuid) &&
605 GUID_equal(r->in.object, &eps->e[i].syntax_id.uuid)) {
610 return EPMAPPER_STATUS_CANT_PERFORM_OP;
614 if (r->in.inquiry_type == RPC_C_EP_MATCH_BY_IF ||
615 r->in.inquiry_type == RPC_C_EP_MATCH_BY_OBJ) {
616 /* Check inteface version */
619 switch (r->in.vers_option) {
622 * Return endpoint map elements that
623 * contain the specified interface UUID,
624 * regardless of the version numbers.
628 case RPC_C_VERS_COMPATIBLE:
630 * Return the endpoint map elements that
631 * contain the same major versions of
632 * the specified interface UUID and a
633 * minor version greater than or equal
634 * to the minor version of the specified
637 if (r->in.interface_id->vers_major ==
638 (eps->e[i].syntax_id.if_version >> 16) &&
639 r->in.interface_id->vers_minor <=
640 (eps->e[i].syntax_id.if_version && 0xFFFF)) {
644 case RPC_C_VERS_EXACT:
646 * Return endpoint map elements that
647 * contain the specified version of the
648 * specified interface UUID.
650 if (r->in.interface_id->vers_major ==
651 (eps->e[i].syntax_id.if_version >> 16) &&
652 r->in.interface_id->vers_minor ==
653 (eps->e[i].syntax_id.if_version && 0xFFFF)) {
658 case RPC_C_VERS_MAJOR_ONLY:
660 * Return endpoint map elements that
661 * contain the same version of the
662 * specified interface UUID and ignore
665 if (r->in.interface_id->vers_major ==
666 (eps->e[i].syntax_id.if_version >> 16)) {
671 case RPC_C_VERS_UPTO:
673 * Return endpoint map elements that
674 * contain a version of the specified
675 * interface UUID less than or equal to
676 * the specified major and minor
679 if (r->in.interface_id->vers_major >
680 eps->e[i].syntax_id.if_version >> 16) {
683 if (r->in.interface_id->vers_major ==
684 (eps->e[i].syntax_id.if_version >> 16) &&
685 r->in.interface_id->vers_minor >=
686 (eps->e[i].syntax_id.if_version && 0xFFFF)) {
692 return EPMAPPER_STATUS_CANT_PERFORM_OP;
698 ZERO_STRUCT(r->out.entries[num_ents].object);
700 DEBUG(10, ("_epm_Lookup: Adding tower for '%s'\n",
702 r->out.entries[num_ents].annotation = talloc_strdup(r->out.entries,
704 r->out.entries[num_ents].tower = talloc(r->out.entries,
706 if (r->out.entries[num_ents].tower == NULL) {
707 rc = EPMAPPER_STATUS_NO_MEMORY;
710 r->out.entries[num_ents].tower->tower.floors = talloc_move(r->out.entries[num_ents].tower, &eps->e[i].ep.floors);
711 r->out.entries[num_ents].tower->tower.num_floors = eps->e[i].ep.num_floors;
712 r->out.entries[num_ents].tower->tower_length = 0;
718 *r->out.num_ents = num_ents;
722 if (eps->count == 0) {
723 close_policy_hnd(p, entry_handle);
724 ZERO_STRUCTP(r->out.entry_handle);
725 rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
729 rc = EPMAPPER_STATUS_OK;
731 talloc_free(tmp_ctx);
739 * Apply some algorithm (using the fields in the map_tower) to an endpoint map
740 * to produce a list of protocol towers.
742 error_status_t _epm_Map(struct pipes_struct *p,
745 struct policy_handle *entry_handle;
746 enum dcerpc_transport_t transport;
747 struct ndr_syntax_id ifid;
748 struct epm_floor *floors;
753 uint32_t num_towers = 0;
754 uint32_t num_floors = 0;
758 *r->out.num_towers = 0;
759 r->out.towers = NULL;
761 if (r->in.map_tower == NULL || r->in.max_towers == 0 ||
762 r->in.map_tower->tower.num_floors < 3) {
763 return EPMAPPER_STATUS_NO_MORE_ENTRIES;
766 tmp_ctx = talloc_stackframe();
767 if (tmp_ctx == NULL) {
768 return EPMAPPER_STATUS_NO_MEMORY;
771 ZERO_STRUCTP(r->out.entry_handle);
773 DEBUG(3, ("_epm_Map: Trying to map max. %u towers.\n",
777 * A tower has normally up to 6 floors
779 * +-----------------------------------------------------------------+
780 * | Floor 1 | Provides the RPC interface identifier. (e.g. UUID for |
782 * +---------+-------------------------------------------------------+
783 * | Floor 2 | Transfer syntax (NDR endcoded) |
784 * +---------+-------------------------------------------------------+
785 * | Floor 3 | RPC protocol identifier (ncacn_tcp_ip, ncacn_np, ...) |
786 * +---------+-------------------------------------------------------+
787 * | Floor 4 | Port address (e.g. TCP Port: 49156) |
788 * +---------+-------------------------------------------------------+
789 * | Floor 5 | Transport (e.g. IP:192.168.51.10) |
790 * +---------+-------------------------------------------------------+
791 * | Floor 6 | Routing |
792 * +---------+-------------------------------------------------------+
794 num_floors = r->in.map_tower->tower.num_floors;
795 floors = r->in.map_tower->tower.floors;
797 /* We accept NDR as the transfer syntax */
798 dcerpc_floor_get_lhs_data(&floors[1], &ifid);
800 if (floors[1].lhs.protocol != EPM_PROTOCOL_UUID ||
801 !GUID_equal(&ifid.uuid, &ndr_transfer_syntax.uuid) ||
802 ifid.if_version != ndr_transfer_syntax.if_version) {
803 rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
807 /* We only talk to sane transports */
808 transport = dcerpc_transport_by_tower(&r->in.map_tower->tower);
809 if (transport == NCA_UNKNOWN) {
810 DEBUG(2, ("epm_Map: Client requested unknown transport with"
812 for (i = 2; i < r->in.map_tower->tower.num_floors; i++) {
813 DEBUG(2, ("%d, ", r->in.map_tower->tower.floors[i].lhs.protocol));
816 rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
820 if (r->in.entry_handle == NULL ||
821 policy_handle_empty(r->in.entry_handle)) {
824 DEBUG(5, ("_epm_Map: No entry_handle found, creating it.\n"));
826 eps = talloc_zero(tmp_ctx, struct rpc_eps);
828 rc = EPMAPPER_STATUS_NO_MEMORY;
837 * Apply some algorithm (using the fields in the map_tower)
838 * to an endpoint map to produce a list of protocol towers.
840 * The following code is the mysterious "some algorithm"!
843 /* Filter by object id if one was given. */
844 if (r->in.object == NULL || GUID_all_zero(r->in.object)) {
850 eps->count = build_ep_list(eps,
854 if (eps->count == 0) {
855 rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
859 /* Filter out endpoints which match the interface. */
861 struct rpc_eps *teps;
864 teps = talloc_zero(tmp_ctx, struct rpc_eps);
866 rc = EPMAPPER_STATUS_NO_MEMORY;
870 for (i = 0; i < eps->count; i++) {
871 if (data_blob_cmp(&r->in.map_tower->tower.floors[0].lhs.lhs_data,
872 &eps->e[i].ep.floors[0].lhs.lhs_data) != 0 ||
873 transport != dcerpc_transport_by_tower(&eps->e[i].ep)) {
877 teps->e = talloc_realloc(tmp_ctx,
879 struct dcesrv_ep_iface,
881 if (teps->e == NULL) {
885 teps->e[total].ep.floors = talloc_move(teps, &eps->e[i].ep.floors);
886 teps->e[total].ep.num_floors = eps->e[i].ep.num_floors;
887 teps->e[total].name = talloc_move(teps, &eps->e[i].name);
888 teps->e[total].syntax_id = eps->e[i].syntax_id;
897 /* end of "some algorithm" */
899 ok = create_policy_hnd(p, r->out.entry_handle, eps);
901 rc = EPMAPPER_STATUS_NO_MEMORY;
905 ok = find_policy_by_hnd(p, r->out.entry_handle, (void **)(void*) &eps);
907 rc = EPMAPPER_STATUS_NO_MEMORY;
910 entry_handle = r->out.entry_handle;
912 DEBUG(5, ("_epm_Map: Trying to find entry_handle.\n"));
914 ok = find_policy_by_hnd(p, r->in.entry_handle, (void **)(void*) &eps);
916 rc = EPMAPPER_STATUS_NO_MEMORY;
919 entry_handle = r->in.entry_handle;
922 if (eps == NULL || eps->e == NULL) {
923 rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
927 /* return the next N elements */
928 count = r->in.max_towers;
929 if (count > eps->count) {
934 close_policy_hnd(p, entry_handle);
935 ZERO_STRUCTP(r->out.entry_handle);
937 rc = EPMAPPER_STATUS_NO_MORE_ENTRIES;
941 r->out.towers = talloc_array(p->mem_ctx, struct epm_twr_p_t, count);
942 if (r->out.towers == NULL) {
943 rc = EPMAPPER_STATUS_NO_MEMORY;
947 for (i = 0; i < count; i++) {
948 DEBUG(5, ("_epm_Map: Map tower for '%s'\n",
951 r->out.towers[num_towers].twr = talloc(r->out.towers,
953 if (r->out.towers[num_towers].twr == NULL) {
954 rc = EPMAPPER_STATUS_NO_MEMORY;
957 r->out.towers[num_towers].twr->tower.floors = talloc_move(r->out.towers[num_towers].twr, &eps->e[i].ep.floors);
958 r->out.towers[num_towers].twr->tower.num_floors = eps->e[i].ep.num_floors;
959 r->out.towers[num_towers].twr->tower_length = 0;
964 *r->out.num_towers = num_towers;
968 if (eps->count == 0) {
969 close_policy_hnd(p, entry_handle);
970 ZERO_STRUCTP(r->out.entry_handle);
973 rc = EPMAPPER_STATUS_OK;
975 talloc_free(tmp_ctx);
981 * epm_LookupHandleFree
983 error_status_t _epm_LookupHandleFree(struct pipes_struct *p,
984 struct epm_LookupHandleFree *r)
986 if (r->in.entry_handle == NULL) {
987 return EPMAPPER_STATUS_OK;
990 if (is_valid_policy_hnd(r->in.entry_handle)) {
991 close_policy_hnd(p, r->in.entry_handle);
994 r->out.entry_handle = r->in.entry_handle;
996 return EPMAPPER_STATUS_OK;
1003 * A client implementation SHOULD NOT call this method. These extensions do not
1004 * provide an alternative method.
1006 error_status_t _epm_InqObject(struct pipes_struct *p,
1007 struct epm_InqObject *r)
1009 p->rng_fault_state = true;
1010 return EPMAPPER_STATUS_CANT_PERFORM_OP;
1017 * A client implementation SHOULD NOT call this method. These extensions do not
1018 * provide an alternative method.
1020 error_status_t _epm_MgmtDelete(struct pipes_struct *p,
1021 struct epm_MgmtDelete *r)
1023 p->rng_fault_state = true;
1024 return EPMAPPER_STATUS_CANT_PERFORM_OP;
1031 error_status_t _epm_MapAuth(struct pipes_struct *p,
1032 struct epm_MapAuth *r)
1034 p->rng_fault_state = true;
1035 return EPMAPPER_STATUS_CANT_PERFORM_OP;
1038 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */