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"
26 #include "srv_epmapper.h"
28 typedef uint32_t error_status_t
;
30 /* An endpoint combined with an interface description */
31 struct dcesrv_ep_iface
{
33 struct ndr_syntax_id syntax_id
;
37 /* A rpc service interface like samr, lsarpc or netlogon */
40 struct ndr_syntax_id syntax_id
;
43 struct dcesrv_iface_list
{
44 struct dcesrv_iface_list
*next
, *prev
;
45 struct dcesrv_iface
*iface
;
49 * An endpoint can serve multiple rpc services interfaces.
50 * For example \\pipe\netlogon can be used by lsarpc and netlogon.
52 struct dcesrv_endpoint
{
53 struct dcesrv_endpoint
*next
, *prev
;
55 /* The type and the location of the endpoint */
56 struct dcerpc_binding
*ep_description
;
58 /* A list of rpc services able to connect to the endpoint */
59 struct dcesrv_iface_list
*iface_list
;
63 struct dcesrv_ep_iface
*e
;
67 static struct dcesrv_endpoint
*endpoint_table
;
70 * Check if the UUID and if_version match to an interface.
72 static bool interface_match(const struct dcesrv_iface
*if1
,
73 const struct dcesrv_iface
*if2
)
75 return GUID_equal(&if1
->syntax_id
.uuid
, &if2
->syntax_id
.uuid
);
79 * Find the interface operations on an endpoint.
81 static const struct dcesrv_iface
*find_interface(const struct dcesrv_endpoint
*endpoint
,
82 const struct dcesrv_iface
*iface
)
84 struct dcesrv_iface_list
*iflist
;
86 for (iflist
= endpoint
->iface_list
; iflist
; iflist
= iflist
->next
) {
87 if (interface_match(iflist
->iface
, iface
)) {
96 * See if a uuid and if_version match to an interface
98 static bool interface_match_by_uuid(const struct dcesrv_iface
*iface
,
99 const struct GUID
*uuid
)
101 return GUID_equal(&iface
->syntax_id
.uuid
, uuid
);
104 static struct dcesrv_iface_list
*find_interface_list(const struct dcesrv_endpoint
*endpoint
,
105 const struct dcesrv_iface
*iface
)
107 struct dcesrv_iface_list
*iflist
;
109 for (iflist
= endpoint
->iface_list
; iflist
; iflist
= iflist
->next
) {
110 if (interface_match(iflist
->iface
, iface
)) {
119 * Check if two endpoints match.
121 static bool endpoints_match(const struct dcerpc_binding
*ep1
,
122 const struct dcerpc_binding
*ep2
)
124 if (ep1
->transport
!= ep2
->transport
) {
128 if (!ep1
->endpoint
|| !ep2
->endpoint
) {
129 return ep1
->endpoint
== ep2
->endpoint
;
132 if (!strequal(ep1
->endpoint
, ep2
->endpoint
)) {
139 static struct dcesrv_endpoint
*find_endpoint(struct dcesrv_endpoint
*endpoint_list
,
140 struct dcerpc_binding
*ep_description
) {
141 struct dcesrv_endpoint
*ep
;
143 for (ep
= endpoint_list
; ep
!= NULL
; ep
= ep
->next
) {
144 if (endpoints_match(ep
->ep_description
, ep_description
)) {
153 * Build a list of all interfaces handled by all endpoint servers.
155 static uint32_t build_ep_list(TALLOC_CTX
*mem_ctx
,
156 struct dcesrv_endpoint
*endpoint_list
,
157 const struct GUID
*uuid
,
158 const char *srv_addr
,
159 struct dcesrv_ep_iface
**peps
)
161 struct dcesrv_ep_iface
*eps
= NULL
;
162 struct dcesrv_endpoint
*d
;
168 for (d
= endpoint_list
; d
!= NULL
; d
= d
->next
) {
169 struct dcesrv_iface_list
*iface
;
170 struct dcerpc_binding
*description
;
172 for (iface
= d
->iface_list
; iface
!= NULL
; iface
= iface
->next
) {
173 if (uuid
&& !interface_match_by_uuid(iface
->iface
, uuid
)) {
177 eps
= talloc_realloc(mem_ctx
,
179 struct dcesrv_ep_iface
,
184 eps
[total
].name
= talloc_strdup(eps
,
186 eps
[total
].syntax_id
= iface
->iface
->syntax_id
;
188 description
= d
->ep_description
;
189 description
->object
= iface
->iface
->syntax_id
;
190 if (description
->transport
== NCACN_IP_TCP
&&
192 strequal(description
->host
, "0.0.0.0")) {
193 description
->host
= srv_addr
;
196 status
= dcerpc_binding_build_tower(eps
,
199 if (NT_STATUS_IS_ERR(status
)) {
200 DEBUG(1, ("Unable to build tower for %s\n",
201 iface
->iface
->name
));
213 static bool is_priviledged_pipe(struct auth_serversupplied_info
*info
) {
214 /* If the user is not root, or has the system token, fail */
215 if ((info
->utok
.uid
!= sec_initial_uid()) &&
216 !security_token_is_system(info
->security_token
)) {
223 void srv_epmapper_cleanup(void)
225 struct dcesrv_endpoint
*ep
;
227 for (ep
= endpoint_table
;
229 ep
= endpoint_table
) {
230 DLIST_REMOVE(endpoint_table
, ep
);
238 * Add the specified entries to an endpoint map.
240 error_status_t
_epm_Insert(struct pipes_struct
*p
,
241 struct epm_Insert
*r
)
248 /* If this is not a priviledged users, return */
249 if (p
->transport
!= NCALRPC
||
250 !is_priviledged_pipe(p
->session_info
)) {
251 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
254 tmp_ctx
= talloc_stackframe();
255 if (tmp_ctx
== NULL
) {
256 return EPMAPPER_STATUS_NO_MEMORY
;
259 DEBUG(3, ("_epm_Insert: Trying to add %u new entries.\n",
262 for (i
= 0; i
< r
->in
.num_ents
; i
++) {
263 struct dcerpc_binding
*b
= NULL
;
264 struct dcesrv_endpoint
*ep
;
265 struct dcesrv_iface_list
*iflist
;
266 struct dcesrv_iface
*iface
;
269 status
= dcerpc_binding_from_tower(tmp_ctx
,
270 &r
->in
.entries
[i
].tower
->tower
,
272 if (!NT_STATUS_IS_OK(status
)) {
273 rc
= EPMAPPER_STATUS_NO_MEMORY
;
277 DEBUG(3, ("_epm_Insert: Adding transport %s for %s\n",
278 derpc_transport_string_by_transport(b
->transport
),
279 r
->in
.entries
[i
].annotation
));
281 /* Check if the entry already exits */
282 ep
= find_endpoint(endpoint_table
, b
);
284 /* No entry found, create it */
285 ep
= talloc_zero(NULL
, struct dcesrv_endpoint
);
287 rc
= EPMAPPER_STATUS_CANT_PERFORM_OP
;
292 ep
->ep_description
= talloc_steal(ep
, b
);
295 /* TODO Replace the entry if the replace flag is set */
297 /* Create an interface */
298 iface
= talloc(tmp_ctx
, struct dcesrv_iface
);
300 rc
= EPMAPPER_STATUS_NO_MEMORY
;
304 iface
->name
= talloc_strdup(iface
, r
->in
.entries
[i
].annotation
);
305 if (iface
->name
== NULL
) {
306 rc
= EPMAPPER_STATUS_NO_MEMORY
;
309 iface
->syntax_id
= b
->object
;
312 * Check if the rpc service is alrady registered on the
315 if (find_interface(ep
, iface
) != NULL
) {
316 DEBUG(0, ("dcesrv_interface_register: interface '%s' "
317 "already registered on endpoint\n",
319 /* FIXME wrong error code? */
320 rc
= EPMAPPER_STATUS_OK
;
324 /* Create an entry for the interface */
325 iflist
= talloc(ep
, struct dcesrv_iface_list
);
326 if (iflist
== NULL
) {
327 rc
= EPMAPPER_STATUS_NO_MEMORY
;
330 iflist
->iface
= talloc_move(iflist
, &iface
);
332 /* Finally add the interface on the endpoint */
333 DLIST_ADD(ep
->iface_list
, iflist
);
335 /* If it's a new endpoint add it to the endpoint_table */
337 DLIST_ADD(endpoint_table
, ep
);
341 rc
= EPMAPPER_STATUS_OK
;
343 talloc_free(tmp_ctx
);
352 * Delete the specified entries from an endpoint map.
354 error_status_t
_epm_Delete(struct pipes_struct
*p
,
355 struct epm_Delete
*r
)
362 DEBUG(3, ("_epm_Delete: Trying to delete %u entries.\n",
365 /* If this is not a priviledged users, return */
366 if (p
->transport
!= NCALRPC
||
367 !is_priviledged_pipe(p
->session_info
)) {
368 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
371 tmp_ctx
= talloc_stackframe();
372 if (tmp_ctx
== NULL
) {
373 return EPMAPPER_STATUS_NO_MEMORY
;
376 for (i
= 0; i
< r
->in
.num_ents
; i
++) {
377 struct dcerpc_binding
*b
= NULL
;
378 struct dcesrv_endpoint
*ep
;
379 struct dcesrv_iface iface
;
380 struct dcesrv_iface_list
*iflist
;
382 status
= dcerpc_binding_from_tower(tmp_ctx
,
383 &r
->in
.entries
[i
].tower
->tower
,
385 if (!NT_STATUS_IS_OK(status
)) {
386 rc
= EPMAPPER_STATUS_NO_MEMORY
;
390 DEBUG(3, ("_epm_Delete: Deleting transport '%s' for '%s'\n",
391 derpc_transport_string_by_transport(b
->transport
),
392 r
->in
.entries
[i
].annotation
));
394 ep
= find_endpoint(endpoint_table
, b
);
396 rc
= EPMAPPER_STATUS_OK
;
400 iface
.name
= r
->in
.entries
[i
].annotation
;
401 iface
.syntax_id
= b
->object
;
403 iflist
= find_interface_list(ep
, &iface
);
404 if (iflist
== NULL
) {
405 DEBUG(0, ("_epm_Delete: No interfaces left, delete endpoint\n"));
406 DLIST_REMOVE(endpoint_table
, ep
);
409 rc
= EPMAPPER_STATUS_OK
;
413 DLIST_REMOVE(ep
->iface_list
, iflist
);
415 if (ep
->iface_list
== NULL
) {
416 DEBUG(0, ("_epm_Delete: No interfaces left, delete endpoint\n"));
417 DLIST_REMOVE(endpoint_table
, ep
);
420 rc
= EPMAPPER_STATUS_OK
;
426 rc
= EPMAPPER_STATUS_OK
;
428 talloc_free(tmp_ctx
);
437 * Lookup entries in an endpoint map.
439 error_status_t
_epm_Lookup(struct pipes_struct
*p
,
440 struct epm_Lookup
*r
)
442 struct policy_handle
*entry_handle
;
447 uint32_t num_ents
= 0;
452 *r
->out
.num_ents
= 0;
453 r
->out
.entries
= NULL
;
455 tmp_ctx
= talloc_stackframe();
456 if (tmp_ctx
== NULL
) {
457 return EPMAPPER_STATUS_NO_MEMORY
;
460 DEBUG(3, ("_epm_Lookup: Trying to lookup max. %u entries.\n",
463 if (r
->in
.entry_handle
== NULL
||
464 policy_handle_empty(r
->in
.entry_handle
)) {
467 DEBUG(5, ("_epm_Lookup: No entry_handle found, creating it.\n"));
469 eps
= talloc_zero(tmp_ctx
, struct rpc_eps
);
471 rc
= EPMAPPER_STATUS_NO_MEMORY
;
475 if (r
->in
.object
== NULL
|| GUID_all_zero(r
->in
.object
)) {
481 switch (r
->in
.inquiry_type
) {
482 case RPC_C_EP_ALL_ELTS
:
484 * Return all elements from the endpoint map. The
485 * interface_id, vers_option, and object parameters MUST
488 eps
->count
= build_ep_list(eps
,
491 p
->server_id
== NULL
? NULL
: p
->server_id
->addr
,
494 case RPC_C_EP_MATCH_BY_IF
:
496 * Return endpoint map elements that contain the
497 * interface identifier specified by the interface_id
498 * and vers_option values.
500 * RPC_C_EP_MATCH_BY_IF and RPC_C_EP_MATCH_BY_BOTH
501 * need both the same endpoint list. There is a second
502 * check for the inquiry_type below which differentiates
505 case RPC_C_EP_MATCH_BY_BOTH
:
507 * Return endpoint map elements that contain the
508 * interface identifier and object UUID specified by
509 * interface_id, vers_option, and object.
511 eps
->count
= build_ep_list(eps
,
513 &r
->in
.interface_id
->uuid
,
514 p
->server_id
== NULL
? NULL
: p
->server_id
->addr
,
517 case RPC_C_EP_MATCH_BY_OBJ
:
519 * Return endpoint map elements that contain the object
520 * UUID specified by object.
522 eps
->count
= build_ep_list(eps
,
525 p
->server_id
== NULL
? NULL
: p
->server_id
->addr
,
529 rc
= EPMAPPER_STATUS_CANT_PERFORM_OP
;
533 if (eps
->count
== 0) {
534 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
538 ok
= create_policy_hnd(p
, r
->out
.entry_handle
, eps
);
540 rc
= EPMAPPER_STATUS_NO_MEMORY
;
544 ok
= find_policy_by_hnd(p
, r
->out
.entry_handle
, (void **)(void*) &eps
);
546 rc
= EPMAPPER_STATUS_NO_MEMORY
;
549 entry_handle
= r
->out
.entry_handle
;
551 DEBUG(5, ("_epm_Lookup: Trying to find entry_handle.\n"));
553 ok
= find_policy_by_hnd(p
, r
->in
.entry_handle
, (void **)(void*) &eps
);
555 rc
= EPMAPPER_STATUS_NO_MEMORY
;
558 entry_handle
= r
->in
.entry_handle
;
561 if (eps
== NULL
|| eps
->e
== NULL
) {
562 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
566 /* return the next N elements */
567 count
= r
->in
.max_ents
;
568 if (count
> eps
->count
) {
572 DEBUG(3, ("_epm_Lookup: Find %u entries\n", count
));
575 close_policy_hnd(p
, entry_handle
);
576 ZERO_STRUCTP(r
->out
.entry_handle
);
578 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
582 r
->out
.entries
= talloc_array(p
->mem_ctx
, struct epm_entry_t
, count
);
583 if (r
->out
.entries
== NULL
) {
584 rc
= EPMAPPER_STATUS_NO_MEMORY
;
588 for (i
= 0; i
< count
; i
++) {
591 switch (r
->in
.inquiry_type
) {
592 case RPC_C_EP_ALL_ELTS
:
594 * Return all elements from the endpoint map. The
595 * interface_id, vers_option, and object parameters MUST
600 case RPC_C_EP_MATCH_BY_IF
:
602 * Return endpoint map elements that contain the
603 * interface identifier specified by the interface_id
604 * and vers_option values.
606 if (GUID_equal(&r
->in
.interface_id
->uuid
,
607 &eps
->e
[i
].syntax_id
.uuid
)) {
611 case RPC_C_EP_MATCH_BY_OBJ
:
613 * Return endpoint map elements that contain the object
614 * UUID specified by object.
616 if (GUID_equal(r
->in
.object
,
617 &eps
->e
[i
].syntax_id
.uuid
)) {
621 case RPC_C_EP_MATCH_BY_BOTH
:
623 * Return endpoint map elements that contain the
624 * interface identifier and object UUID specified by
625 * interface_id, vers_option, and object.
627 if (GUID_equal(&r
->in
.interface_id
->uuid
,
628 &eps
->e
[i
].syntax_id
.uuid
) &&
629 GUID_equal(r
->in
.object
, &eps
->e
[i
].syntax_id
.uuid
)) {
634 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
638 if (r
->in
.inquiry_type
== RPC_C_EP_MATCH_BY_IF
||
639 r
->in
.inquiry_type
== RPC_C_EP_MATCH_BY_OBJ
) {
640 /* Check inteface version */
643 switch (r
->in
.vers_option
) {
646 * Return endpoint map elements that
647 * contain the specified interface UUID,
648 * regardless of the version numbers.
652 case RPC_C_VERS_COMPATIBLE
:
654 * Return the endpoint map elements that
655 * contain the same major versions of
656 * the specified interface UUID and a
657 * minor version greater than or equal
658 * to the minor version of the specified
661 if (r
->in
.interface_id
->vers_major
==
662 (eps
->e
[i
].syntax_id
.if_version
>> 16) &&
663 r
->in
.interface_id
->vers_minor
<=
664 (eps
->e
[i
].syntax_id
.if_version
&& 0xFFFF)) {
668 case RPC_C_VERS_EXACT
:
670 * Return endpoint map elements that
671 * contain the specified version of the
672 * specified interface UUID.
674 if (r
->in
.interface_id
->vers_major
==
675 (eps
->e
[i
].syntax_id
.if_version
>> 16) &&
676 r
->in
.interface_id
->vers_minor
==
677 (eps
->e
[i
].syntax_id
.if_version
&& 0xFFFF)) {
682 case RPC_C_VERS_MAJOR_ONLY
:
684 * Return endpoint map elements that
685 * contain the same version of the
686 * specified interface UUID and ignore
689 if (r
->in
.interface_id
->vers_major
==
690 (eps
->e
[i
].syntax_id
.if_version
>> 16)) {
695 case RPC_C_VERS_UPTO
:
697 * Return endpoint map elements that
698 * contain a version of the specified
699 * interface UUID less than or equal to
700 * the specified major and minor
703 if (r
->in
.interface_id
->vers_major
>
704 eps
->e
[i
].syntax_id
.if_version
>> 16) {
707 if (r
->in
.interface_id
->vers_major
==
708 (eps
->e
[i
].syntax_id
.if_version
>> 16) &&
709 r
->in
.interface_id
->vers_minor
>=
710 (eps
->e
[i
].syntax_id
.if_version
&& 0xFFFF)) {
716 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
722 ZERO_STRUCT(r
->out
.entries
[num_ents
].object
);
724 DEBUG(10, ("_epm_Lookup: Adding tower for '%s'\n",
726 r
->out
.entries
[num_ents
].annotation
= talloc_strdup(r
->out
.entries
,
728 r
->out
.entries
[num_ents
].tower
= talloc(r
->out
.entries
,
730 if (r
->out
.entries
[num_ents
].tower
== NULL
) {
731 rc
= EPMAPPER_STATUS_NO_MEMORY
;
734 r
->out
.entries
[num_ents
].tower
->tower
.floors
= talloc_move(r
->out
.entries
[num_ents
].tower
, &eps
->e
[i
].ep
.floors
);
735 r
->out
.entries
[num_ents
].tower
->tower
.num_floors
= eps
->e
[i
].ep
.num_floors
;
736 r
->out
.entries
[num_ents
].tower
->tower_length
= 0;
742 *r
->out
.num_ents
= num_ents
;
746 if (eps
->count
== 0) {
747 close_policy_hnd(p
, entry_handle
);
748 ZERO_STRUCTP(r
->out
.entry_handle
);
749 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
753 rc
= EPMAPPER_STATUS_OK
;
755 talloc_free(tmp_ctx
);
763 * Apply some algorithm (using the fields in the map_tower) to an endpoint map
764 * to produce a list of protocol towers.
766 error_status_t
_epm_Map(struct pipes_struct
*p
,
769 struct policy_handle
*entry_handle
;
770 enum dcerpc_transport_t transport
;
771 struct ndr_syntax_id ifid
;
772 struct epm_floor
*floors
;
777 uint32_t num_towers
= 0;
778 uint32_t num_floors
= 0;
782 *r
->out
.num_towers
= 0;
783 r
->out
.towers
= NULL
;
785 if (r
->in
.map_tower
== NULL
|| r
->in
.max_towers
== 0 ||
786 r
->in
.map_tower
->tower
.num_floors
< 3) {
787 return EPMAPPER_STATUS_NO_MORE_ENTRIES
;
790 tmp_ctx
= talloc_stackframe();
791 if (tmp_ctx
== NULL
) {
792 return EPMAPPER_STATUS_NO_MEMORY
;
795 ZERO_STRUCTP(r
->out
.entry_handle
);
797 DEBUG(3, ("_epm_Map: Trying to map max. %u towers.\n",
801 * A tower has normally up to 6 floors
803 * +-----------------------------------------------------------------+
804 * | Floor 1 | Provides the RPC interface identifier. (e.g. UUID for |
806 * +---------+-------------------------------------------------------+
807 * | Floor 2 | Transfer syntax (NDR endcoded) |
808 * +---------+-------------------------------------------------------+
809 * | Floor 3 | RPC protocol identifier (ncacn_tcp_ip, ncacn_np, ...) |
810 * +---------+-------------------------------------------------------+
811 * | Floor 4 | Port address (e.g. TCP Port: 49156) |
812 * +---------+-------------------------------------------------------+
813 * | Floor 5 | Transport (e.g. IP:192.168.51.10) |
814 * +---------+-------------------------------------------------------+
815 * | Floor 6 | Routing |
816 * +---------+-------------------------------------------------------+
818 num_floors
= r
->in
.map_tower
->tower
.num_floors
;
819 floors
= r
->in
.map_tower
->tower
.floors
;
821 /* We accept NDR as the transfer syntax */
822 dcerpc_floor_get_lhs_data(&floors
[1], &ifid
);
824 if (floors
[1].lhs
.protocol
!= EPM_PROTOCOL_UUID
||
825 !GUID_equal(&ifid
.uuid
, &ndr_transfer_syntax
.uuid
) ||
826 ifid
.if_version
!= ndr_transfer_syntax
.if_version
) {
827 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
831 /* We only talk to sane transports */
832 transport
= dcerpc_transport_by_tower(&r
->in
.map_tower
->tower
);
833 if (transport
== NCA_UNKNOWN
) {
834 DEBUG(2, ("epm_Map: Client requested unknown transport with"
836 for (i
= 2; i
< r
->in
.map_tower
->tower
.num_floors
; i
++) {
837 DEBUG(2, ("%d, ", r
->in
.map_tower
->tower
.floors
[i
].lhs
.protocol
));
840 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
844 if (r
->in
.entry_handle
== NULL
||
845 policy_handle_empty(r
->in
.entry_handle
)) {
848 DEBUG(5, ("_epm_Map: No entry_handle found, creating it.\n"));
850 eps
= talloc_zero(tmp_ctx
, struct rpc_eps
);
852 rc
= EPMAPPER_STATUS_NO_MEMORY
;
861 * Apply some algorithm (using the fields in the map_tower)
862 * to an endpoint map to produce a list of protocol towers.
864 * The following code is the mysterious "some algorithm"!
867 /* Filter by object id if one was given. */
868 if (r
->in
.object
== NULL
|| GUID_all_zero(r
->in
.object
)) {
874 eps
->count
= build_ep_list(eps
,
877 p
->server_id
== NULL
? NULL
: p
->server_id
->addr
,
879 if (eps
->count
== 0) {
880 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
884 /* Filter out endpoints which match the interface. */
886 struct rpc_eps
*teps
;
889 teps
= talloc_zero(tmp_ctx
, struct rpc_eps
);
891 rc
= EPMAPPER_STATUS_NO_MEMORY
;
895 for (i
= 0; i
< eps
->count
; i
++) {
896 if (data_blob_cmp(&r
->in
.map_tower
->tower
.floors
[0].lhs
.lhs_data
,
897 &eps
->e
[i
].ep
.floors
[0].lhs
.lhs_data
) != 0 ||
898 transport
!= dcerpc_transport_by_tower(&eps
->e
[i
].ep
)) {
902 teps
->e
= talloc_realloc(tmp_ctx
,
904 struct dcesrv_ep_iface
,
906 if (teps
->e
== NULL
) {
910 teps
->e
[total
].ep
.floors
= talloc_move(teps
, &eps
->e
[i
].ep
.floors
);
911 teps
->e
[total
].ep
.num_floors
= eps
->e
[i
].ep
.num_floors
;
912 teps
->e
[total
].name
= talloc_move(teps
, &eps
->e
[i
].name
);
913 teps
->e
[total
].syntax_id
= eps
->e
[i
].syntax_id
;
922 /* end of "some algorithm" */
924 ok
= create_policy_hnd(p
, r
->out
.entry_handle
, eps
);
926 rc
= EPMAPPER_STATUS_NO_MEMORY
;
930 ok
= find_policy_by_hnd(p
, r
->out
.entry_handle
, (void **)(void*) &eps
);
932 rc
= EPMAPPER_STATUS_NO_MEMORY
;
935 entry_handle
= r
->out
.entry_handle
;
937 DEBUG(5, ("_epm_Map: Trying to find entry_handle.\n"));
939 ok
= find_policy_by_hnd(p
, r
->in
.entry_handle
, (void **)(void*) &eps
);
941 rc
= EPMAPPER_STATUS_NO_MEMORY
;
944 entry_handle
= r
->in
.entry_handle
;
947 if (eps
== NULL
|| eps
->e
== NULL
) {
948 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
952 /* return the next N elements */
953 count
= r
->in
.max_towers
;
954 if (count
> eps
->count
) {
959 close_policy_hnd(p
, entry_handle
);
960 ZERO_STRUCTP(r
->out
.entry_handle
);
962 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
966 r
->out
.towers
= talloc_array(p
->mem_ctx
, struct epm_twr_p_t
, count
);
967 if (r
->out
.towers
== NULL
) {
968 rc
= EPMAPPER_STATUS_NO_MEMORY
;
972 for (i
= 0; i
< count
; i
++) {
973 DEBUG(5, ("_epm_Map: Map tower for '%s'\n",
976 r
->out
.towers
[num_towers
].twr
= talloc(r
->out
.towers
,
978 if (r
->out
.towers
[num_towers
].twr
== NULL
) {
979 rc
= EPMAPPER_STATUS_NO_MEMORY
;
982 r
->out
.towers
[num_towers
].twr
->tower
.floors
= talloc_move(r
->out
.towers
[num_towers
].twr
, &eps
->e
[i
].ep
.floors
);
983 r
->out
.towers
[num_towers
].twr
->tower
.num_floors
= eps
->e
[i
].ep
.num_floors
;
984 r
->out
.towers
[num_towers
].twr
->tower_length
= 0;
989 *r
->out
.num_towers
= num_towers
;
993 if (eps
->count
== 0) {
994 close_policy_hnd(p
, entry_handle
);
995 ZERO_STRUCTP(r
->out
.entry_handle
);
998 rc
= EPMAPPER_STATUS_OK
;
1000 talloc_free(tmp_ctx
);
1006 * epm_LookupHandleFree
1008 error_status_t
_epm_LookupHandleFree(struct pipes_struct
*p
,
1009 struct epm_LookupHandleFree
*r
)
1011 if (r
->in
.entry_handle
== NULL
) {
1012 return EPMAPPER_STATUS_OK
;
1015 if (is_valid_policy_hnd(r
->in
.entry_handle
)) {
1016 close_policy_hnd(p
, r
->in
.entry_handle
);
1019 r
->out
.entry_handle
= r
->in
.entry_handle
;
1021 return EPMAPPER_STATUS_OK
;
1028 * A client implementation SHOULD NOT call this method. These extensions do not
1029 * provide an alternative method.
1031 error_status_t
_epm_InqObject(struct pipes_struct
*p
,
1032 struct epm_InqObject
*r
)
1034 p
->rng_fault_state
= true;
1035 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
1042 * A client implementation SHOULD NOT call this method. These extensions do not
1043 * provide an alternative method.
1045 error_status_t
_epm_MgmtDelete(struct pipes_struct
*p
,
1046 struct epm_MgmtDelete
*r
)
1048 p
->rng_fault_state
= true;
1049 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
1056 error_status_t
_epm_MapAuth(struct pipes_struct
*p
,
1057 struct epm_MapAuth
*r
)
1059 p
->rng_fault_state
= true;
1060 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
1063 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */