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 "librpc/gen_ndr/srv_epmapper.h"
26 #include "srv_epmapper.h"
29 typedef uint32_t error_status_t
;
31 /* An endpoint combined with an interface description */
32 struct dcesrv_ep_iface
{
34 struct ndr_syntax_id syntax_id
;
38 /* A rpc service interface like samr, lsarpc or netlogon */
41 struct ndr_syntax_id syntax_id
;
44 struct dcesrv_iface_list
{
45 struct dcesrv_iface_list
*next
, *prev
;
46 struct dcesrv_iface
*iface
;
50 * An endpoint can serve multiple rpc services interfaces.
51 * For example \\pipe\netlogon can be used by lsarpc and netlogon.
53 struct dcesrv_endpoint
{
54 struct dcesrv_endpoint
*next
, *prev
;
56 /* The type and the location of the endpoint */
57 struct dcerpc_binding
*ep_description
;
59 /* A list of rpc services able to connect to the endpoint */
60 struct dcesrv_iface_list
*iface_list
;
63 struct dcesrv_ep_entry_list
{
64 struct dcesrv_ep_entry_list
*next
, *prev
;
67 struct epm_entry_t
*entries
;
71 struct dcesrv_ep_iface
*e
;
75 static struct dcesrv_endpoint
*endpoint_table
;
78 * Check if the UUID and if_version match to an interface.
80 static bool interface_match(const struct dcesrv_iface
*if1
,
81 const struct dcesrv_iface
*if2
)
83 return GUID_equal(&if1
->syntax_id
.uuid
, &if2
->syntax_id
.uuid
);
87 * Find the interface operations on an endpoint.
89 static const struct dcesrv_iface
*find_interface(const struct dcesrv_endpoint
*endpoint
,
90 const struct dcesrv_iface
*iface
)
92 struct dcesrv_iface_list
*iflist
;
94 for (iflist
= endpoint
->iface_list
; iflist
; iflist
= iflist
->next
) {
95 if (interface_match(iflist
->iface
, iface
)) {
104 * See if a uuid and if_version match to an interface
106 static bool interface_match_by_uuid(const struct dcesrv_iface
*iface
,
107 const struct GUID
*uuid
)
109 return GUID_equal(&iface
->syntax_id
.uuid
, uuid
);
112 static struct dcesrv_iface_list
*find_interface_list(const struct dcesrv_endpoint
*endpoint
,
113 const struct dcesrv_iface
*iface
)
115 struct dcesrv_iface_list
*iflist
;
117 for (iflist
= endpoint
->iface_list
; iflist
; iflist
= iflist
->next
) {
118 if (interface_match(iflist
->iface
, iface
)) {
127 * Check if two endpoints match.
129 static bool endpoints_match(const struct dcerpc_binding
*ep1
,
130 const struct dcerpc_binding
*ep2
)
132 if (ep1
->transport
!= ep2
->transport
) {
136 if (!ep1
->endpoint
|| !ep2
->endpoint
) {
137 return ep1
->endpoint
== ep2
->endpoint
;
140 if (!strequal(ep1
->endpoint
, ep2
->endpoint
)) {
147 static struct dcesrv_endpoint
*find_endpoint(struct dcesrv_endpoint
*endpoint_list
,
148 struct dcerpc_binding
*ep_description
) {
149 struct dcesrv_endpoint
*ep
;
151 for (ep
= endpoint_list
; ep
!= NULL
; ep
= ep
->next
) {
152 if (endpoints_match(ep
->ep_description
, ep_description
)) {
161 * Build a list of all interfaces handled by all endpoint servers.
163 static uint32_t build_ep_list(TALLOC_CTX
*mem_ctx
,
164 struct dcesrv_endpoint
*endpoint_list
,
165 const struct GUID
*uuid
,
166 const char *srv_addr
,
167 struct dcesrv_ep_iface
**peps
)
169 struct dcesrv_ep_iface
*eps
= NULL
;
170 struct dcesrv_endpoint
*d
;
176 for (d
= endpoint_list
; d
!= NULL
; d
= d
->next
) {
177 struct dcesrv_iface_list
*iface
;
178 struct dcerpc_binding
*description
;
180 for (iface
= d
->iface_list
; iface
!= NULL
; iface
= iface
->next
) {
181 if (uuid
&& !interface_match_by_uuid(iface
->iface
, uuid
)) {
185 eps
= talloc_realloc(mem_ctx
,
187 struct dcesrv_ep_iface
,
192 eps
[total
].name
= talloc_strdup(eps
,
194 eps
[total
].syntax_id
= iface
->iface
->syntax_id
;
196 description
= dcerpc_binding_dup(mem_ctx
, d
->ep_description
);
197 if (description
== NULL
) {
200 description
->object
= iface
->iface
->syntax_id
;
201 if (description
->transport
== NCACN_IP_TCP
&&
203 (strcmp(description
->host
, "0.0.0.0") == 0 ||
204 strcmp(description
->host
, "::") == 0)) {
205 description
->host
= srv_addr
;
208 status
= dcerpc_binding_build_tower(eps
,
211 TALLOC_FREE(description
);
212 if (NT_STATUS_IS_ERR(status
)) {
213 DEBUG(1, ("Unable to build tower for %s\n",
214 iface
->iface
->name
));
226 static bool is_priviledged_pipe(struct auth_serversupplied_info
*info
) {
227 /* If the user is not root, or has the system token, fail */
228 if ((info
->utok
.uid
!= sec_initial_uid()) &&
229 !security_token_is_system(info
->security_token
)) {
236 bool srv_epmapper_delete_endpoints(struct pipes_struct
*p
)
239 struct dcesrv_ep_entry_list
*el
= p
->ep_entries
;
240 error_status_t result
;
243 struct dcesrv_ep_entry_list
*next
= el
->next
;
245 r
.in
.num_ents
= el
->num_ents
;
246 r
.in
.entries
= el
->entries
;
248 DEBUG(10, ("Delete_endpoints for: %s\n",
249 el
->entries
[0].annotation
));
251 result
= _epm_Delete(p
, &r
);
252 if (result
!= EPMAPPER_STATUS_OK
) {
256 DLIST_REMOVE(p
->ep_entries
, el
);
265 void srv_epmapper_cleanup(void)
267 struct dcesrv_endpoint
*ep
= endpoint_table
;
270 struct dcesrv_endpoint
*next
= ep
->next
;
272 DLIST_REMOVE(endpoint_table
, ep
);
282 * Add the specified entries to an endpoint map.
284 error_status_t
_epm_Insert(struct pipes_struct
*p
,
285 struct epm_Insert
*r
)
291 struct dcerpc_binding
*b
;
292 struct dcesrv_endpoint
*ep
;
293 struct dcesrv_iface_list
*iflist
;
294 struct dcesrv_iface
*iface
;
297 /* If this is not a priviledged users, return */
298 if (p
->transport
!= NCALRPC
||
299 !is_priviledged_pipe(p
->session_info
)) {
300 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
303 tmp_ctx
= talloc_stackframe();
304 if (tmp_ctx
== NULL
) {
305 return EPMAPPER_STATUS_NO_MEMORY
;
308 DEBUG(3, ("_epm_Insert: Trying to add %u new entries.\n",
311 for (i
= 0; i
< r
->in
.num_ents
; i
++) {
315 status
= dcerpc_binding_from_tower(tmp_ctx
,
316 &r
->in
.entries
[i
].tower
->tower
,
318 if (NT_STATUS_EQUAL(status
, NT_STATUS_NO_MEMORY
)) {
319 rc
= EPMAPPER_STATUS_NO_MEMORY
;
322 if (!NT_STATUS_IS_OK(status
)) {
323 rc
= EPMAPPER_STATUS_CANT_PERFORM_OP
;
327 DEBUG(3, ("_epm_Insert: Adding transport %s for %s\n",
328 derpc_transport_string_by_transport(b
->transport
),
329 r
->in
.entries
[i
].annotation
));
331 /* Check if the entry already exits */
332 ep
= find_endpoint(endpoint_table
, b
);
334 /* No entry found, create it */
335 ep
= talloc_zero(NULL
, struct dcesrv_endpoint
);
337 rc
= EPMAPPER_STATUS_NO_MEMORY
;
342 ep
->ep_description
= talloc_steal(ep
, b
);
345 /* TODO Replace the entry if the replace flag is set */
347 /* Create an interface */
348 iface
= talloc(tmp_ctx
, struct dcesrv_iface
);
350 rc
= EPMAPPER_STATUS_NO_MEMORY
;
354 iface
->name
= talloc_strdup(iface
, r
->in
.entries
[i
].annotation
);
355 if (iface
->name
== NULL
) {
356 rc
= EPMAPPER_STATUS_NO_MEMORY
;
359 iface
->syntax_id
= b
->object
;
362 * Check if the rpc service is alrady registered on the
365 if (find_interface(ep
, iface
) != NULL
) {
366 DEBUG(0, ("dcesrv_interface_register: interface '%s' "
367 "already registered on endpoint\n",
369 /* FIXME wrong error code? */
370 rc
= EPMAPPER_STATUS_OK
;
374 /* Create an entry for the interface */
375 iflist
= talloc(ep
, struct dcesrv_iface_list
);
376 if (iflist
== NULL
) {
377 rc
= EPMAPPER_STATUS_NO_MEMORY
;
380 iflist
->iface
= talloc_move(iflist
, &iface
);
382 /* Finally add the interface on the endpoint */
383 DLIST_ADD(ep
->iface_list
, iflist
);
385 /* If it's a new endpoint add it to the endpoint_table */
387 DLIST_ADD(endpoint_table
, ep
);
391 if (r
->in
.num_ents
> 0) {
392 struct dcesrv_ep_entry_list
*el
;
394 el
= talloc_zero(p
, struct dcesrv_ep_entry_list
);
396 rc
= EPMAPPER_STATUS_NO_MEMORY
;
399 el
->num_ents
= r
->in
.num_ents
;
400 el
->entries
= talloc_move(el
, &r
->in
.entries
);
402 DLIST_ADD(p
->ep_entries
, el
);
405 rc
= EPMAPPER_STATUS_OK
;
407 talloc_free(tmp_ctx
);
416 * Delete the specified entries from an endpoint map.
418 error_status_t
_epm_Delete(struct pipes_struct
*p
,
419 struct epm_Delete
*r
)
425 struct dcerpc_binding
*b
;
426 struct dcesrv_endpoint
*ep
;
427 struct dcesrv_iface iface
;
428 struct dcesrv_iface_list
*iflist
;
430 DEBUG(3, ("_epm_Delete: Trying to delete %u entries.\n",
433 /* If this is not a priviledged users, return */
434 if (p
->transport
!= NCALRPC
||
435 !is_priviledged_pipe(p
->session_info
)) {
436 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
439 tmp_ctx
= talloc_stackframe();
440 if (tmp_ctx
== NULL
) {
441 return EPMAPPER_STATUS_NO_MEMORY
;
444 for (i
= 0; i
< r
->in
.num_ents
; i
++) {
447 status
= dcerpc_binding_from_tower(tmp_ctx
,
448 &r
->in
.entries
[i
].tower
->tower
,
450 if (!NT_STATUS_IS_OK(status
)) {
451 rc
= EPMAPPER_STATUS_NO_MEMORY
;
455 DEBUG(3, ("_epm_Delete: Deleting transport '%s' for '%s'\n",
456 derpc_transport_string_by_transport(b
->transport
),
457 r
->in
.entries
[i
].annotation
));
459 ep
= find_endpoint(endpoint_table
, b
);
461 rc
= EPMAPPER_STATUS_OK
;
465 iface
.name
= r
->in
.entries
[i
].annotation
;
466 iface
.syntax_id
= b
->object
;
468 iflist
= find_interface_list(ep
, &iface
);
469 if (iflist
== NULL
) {
470 DEBUG(0, ("_epm_Delete: No interfaces left, delete endpoint\n"));
471 DLIST_REMOVE(endpoint_table
, ep
);
474 rc
= EPMAPPER_STATUS_OK
;
478 DLIST_REMOVE(ep
->iface_list
, iflist
);
480 if (ep
->iface_list
== NULL
) {
481 DEBUG(0, ("_epm_Delete: No interfaces left, delete endpoint\n"));
482 DLIST_REMOVE(endpoint_table
, ep
);
485 rc
= EPMAPPER_STATUS_OK
;
491 rc
= EPMAPPER_STATUS_OK
;
493 talloc_free(tmp_ctx
);
502 * Lookup entries in an endpoint map.
504 error_status_t
_epm_Lookup(struct pipes_struct
*p
,
505 struct epm_Lookup
*r
)
507 struct policy_handle
*entry_handle
;
512 uint32_t num_ents
= 0;
517 *r
->out
.num_ents
= 0;
518 r
->out
.entries
= NULL
;
520 tmp_ctx
= talloc_stackframe();
521 if (tmp_ctx
== NULL
) {
522 return EPMAPPER_STATUS_NO_MEMORY
;
525 DEBUG(3, ("_epm_Lookup: Trying to lookup max. %u entries.\n",
528 if (r
->in
.entry_handle
== NULL
||
529 policy_handle_empty(r
->in
.entry_handle
)) {
532 DEBUG(5, ("_epm_Lookup: No entry_handle found, creating it.\n"));
534 eps
= talloc_zero(tmp_ctx
, struct rpc_eps
);
536 rc
= EPMAPPER_STATUS_NO_MEMORY
;
540 if (r
->in
.object
== NULL
|| GUID_all_zero(r
->in
.object
)) {
546 switch (r
->in
.inquiry_type
) {
547 case RPC_C_EP_ALL_ELTS
:
549 * Return all elements from the endpoint map. The
550 * interface_id, vers_option, and object parameters MUST
553 eps
->count
= build_ep_list(eps
,
556 p
->server_id
== NULL
? NULL
: p
->server_id
->addr
,
559 case RPC_C_EP_MATCH_BY_IF
:
561 * Return endpoint map elements that contain the
562 * interface identifier specified by the interface_id
563 * and vers_option values.
565 * RPC_C_EP_MATCH_BY_IF and RPC_C_EP_MATCH_BY_BOTH
566 * need both the same endpoint list. There is a second
567 * check for the inquiry_type below which differentiates
570 case RPC_C_EP_MATCH_BY_BOTH
:
572 * Return endpoint map elements that contain the
573 * interface identifier and object UUID specified by
574 * interface_id, vers_option, and object.
576 eps
->count
= build_ep_list(eps
,
578 &r
->in
.interface_id
->uuid
,
579 p
->server_id
== NULL
? NULL
: p
->server_id
->addr
,
582 case RPC_C_EP_MATCH_BY_OBJ
:
584 * Return endpoint map elements that contain the object
585 * UUID specified by object.
587 eps
->count
= build_ep_list(eps
,
590 p
->server_id
== NULL
? NULL
: p
->server_id
->addr
,
594 rc
= EPMAPPER_STATUS_CANT_PERFORM_OP
;
598 if (eps
->count
== 0) {
599 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
603 ok
= create_policy_hnd(p
, r
->out
.entry_handle
, eps
);
605 rc
= EPMAPPER_STATUS_NO_MEMORY
;
609 ok
= find_policy_by_hnd(p
, r
->out
.entry_handle
, (void **)(void*) &eps
);
611 rc
= EPMAPPER_STATUS_NO_MEMORY
;
614 entry_handle
= r
->out
.entry_handle
;
616 DEBUG(5, ("_epm_Lookup: Trying to find entry_handle.\n"));
618 ok
= find_policy_by_hnd(p
, r
->in
.entry_handle
, (void **)(void*) &eps
);
620 rc
= EPMAPPER_STATUS_NO_MEMORY
;
623 entry_handle
= r
->in
.entry_handle
;
626 if (eps
== NULL
|| eps
->e
== NULL
) {
627 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
631 /* return the next N elements */
632 count
= r
->in
.max_ents
;
633 if (count
> eps
->count
) {
637 DEBUG(3, ("_epm_Lookup: Find %u entries\n", count
));
640 close_policy_hnd(p
, entry_handle
);
641 ZERO_STRUCTP(r
->out
.entry_handle
);
643 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
647 r
->out
.entries
= talloc_array(p
->mem_ctx
, struct epm_entry_t
, count
);
648 if (r
->out
.entries
== NULL
) {
649 rc
= EPMAPPER_STATUS_NO_MEMORY
;
653 for (i
= 0; i
< count
; i
++) {
656 switch (r
->in
.inquiry_type
) {
657 case RPC_C_EP_ALL_ELTS
:
659 * Return all elements from the endpoint map. The
660 * interface_id, vers_option, and object parameters MUST
665 case RPC_C_EP_MATCH_BY_IF
:
667 * Return endpoint map elements that contain the
668 * interface identifier specified by the interface_id
669 * and vers_option values.
671 if (GUID_equal(&r
->in
.interface_id
->uuid
,
672 &eps
->e
[i
].syntax_id
.uuid
)) {
676 case RPC_C_EP_MATCH_BY_OBJ
:
678 * Return endpoint map elements that contain the object
679 * UUID specified by object.
681 if (GUID_equal(r
->in
.object
,
682 &eps
->e
[i
].syntax_id
.uuid
)) {
686 case RPC_C_EP_MATCH_BY_BOTH
:
688 * Return endpoint map elements that contain the
689 * interface identifier and object UUID specified by
690 * interface_id, vers_option, and object.
692 if (GUID_equal(&r
->in
.interface_id
->uuid
,
693 &eps
->e
[i
].syntax_id
.uuid
) &&
694 GUID_equal(r
->in
.object
, &eps
->e
[i
].syntax_id
.uuid
)) {
699 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
703 if (r
->in
.inquiry_type
== RPC_C_EP_MATCH_BY_IF
||
704 r
->in
.inquiry_type
== RPC_C_EP_MATCH_BY_OBJ
) {
705 /* Check inteface version */
708 switch (r
->in
.vers_option
) {
711 * Return endpoint map elements that
712 * contain the specified interface UUID,
713 * regardless of the version numbers.
717 case RPC_C_VERS_COMPATIBLE
:
719 * Return the endpoint map elements that
720 * contain the same major versions of
721 * the specified interface UUID and a
722 * minor version greater than or equal
723 * to the minor version of the specified
726 if (r
->in
.interface_id
->vers_major
==
727 (eps
->e
[i
].syntax_id
.if_version
>> 16) &&
728 r
->in
.interface_id
->vers_minor
<=
729 (eps
->e
[i
].syntax_id
.if_version
&& 0xFFFF)) {
733 case RPC_C_VERS_EXACT
:
735 * Return endpoint map elements that
736 * contain the specified version of the
737 * specified interface UUID.
739 if (r
->in
.interface_id
->vers_major
==
740 (eps
->e
[i
].syntax_id
.if_version
>> 16) &&
741 r
->in
.interface_id
->vers_minor
==
742 (eps
->e
[i
].syntax_id
.if_version
&& 0xFFFF)) {
747 case RPC_C_VERS_MAJOR_ONLY
:
749 * Return endpoint map elements that
750 * contain the same version of the
751 * specified interface UUID and ignore
754 if (r
->in
.interface_id
->vers_major
==
755 (eps
->e
[i
].syntax_id
.if_version
>> 16)) {
760 case RPC_C_VERS_UPTO
:
762 * Return endpoint map elements that
763 * contain a version of the specified
764 * interface UUID less than or equal to
765 * the specified major and minor
768 if (r
->in
.interface_id
->vers_major
>
769 eps
->e
[i
].syntax_id
.if_version
>> 16) {
772 if (r
->in
.interface_id
->vers_major
==
773 (eps
->e
[i
].syntax_id
.if_version
>> 16) &&
774 r
->in
.interface_id
->vers_minor
>=
775 (eps
->e
[i
].syntax_id
.if_version
&& 0xFFFF)) {
781 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
787 ZERO_STRUCT(r
->out
.entries
[num_ents
].object
);
789 DEBUG(10, ("_epm_Lookup: Adding tower for '%s'\n",
791 r
->out
.entries
[num_ents
].annotation
= talloc_strdup(r
->out
.entries
,
793 r
->out
.entries
[num_ents
].tower
= talloc(r
->out
.entries
,
795 if (r
->out
.entries
[num_ents
].tower
== NULL
) {
796 rc
= EPMAPPER_STATUS_NO_MEMORY
;
799 r
->out
.entries
[num_ents
].tower
->tower
.floors
= talloc_move(r
->out
.entries
[num_ents
].tower
, &eps
->e
[i
].ep
.floors
);
800 r
->out
.entries
[num_ents
].tower
->tower
.num_floors
= eps
->e
[i
].ep
.num_floors
;
801 r
->out
.entries
[num_ents
].tower
->tower_length
= 0;
807 *r
->out
.num_ents
= num_ents
;
811 if (eps
->count
== 0) {
812 close_policy_hnd(p
, entry_handle
);
813 ZERO_STRUCTP(r
->out
.entry_handle
);
814 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
818 rc
= EPMAPPER_STATUS_OK
;
820 talloc_free(tmp_ctx
);
828 * Apply some algorithm (using the fields in the map_tower) to an endpoint map
829 * to produce a list of protocol towers.
831 error_status_t
_epm_Map(struct pipes_struct
*p
,
834 struct policy_handle
*entry_handle
;
835 enum dcerpc_transport_t transport
;
836 struct ndr_syntax_id ifid
;
837 struct epm_floor
*floors
;
842 uint32_t num_towers
= 0;
843 uint32_t num_floors
= 0;
847 *r
->out
.num_towers
= 0;
848 r
->out
.towers
= NULL
;
850 if (r
->in
.map_tower
== NULL
|| r
->in
.max_towers
== 0 ||
851 r
->in
.map_tower
->tower
.num_floors
< 3) {
852 return EPMAPPER_STATUS_NO_MORE_ENTRIES
;
855 tmp_ctx
= talloc_stackframe();
856 if (tmp_ctx
== NULL
) {
857 return EPMAPPER_STATUS_NO_MEMORY
;
860 ZERO_STRUCTP(r
->out
.entry_handle
);
862 DEBUG(3, ("_epm_Map: Trying to map max. %u towers.\n",
866 * A tower has normally up to 6 floors
868 * +-----------------------------------------------------------------+
869 * | Floor 1 | Provides the RPC interface identifier. (e.g. UUID for |
871 * +---------+-------------------------------------------------------+
872 * | Floor 2 | Transfer syntax (NDR endcoded) |
873 * +---------+-------------------------------------------------------+
874 * | Floor 3 | RPC protocol identifier (ncacn_tcp_ip, ncacn_np, ...) |
875 * +---------+-------------------------------------------------------+
876 * | Floor 4 | Port address (e.g. TCP Port: 49156) |
877 * +---------+-------------------------------------------------------+
878 * | Floor 5 | Transport (e.g. IP:192.168.51.10) |
879 * +---------+-------------------------------------------------------+
880 * | Floor 6 | Routing |
881 * +---------+-------------------------------------------------------+
883 num_floors
= r
->in
.map_tower
->tower
.num_floors
;
884 floors
= r
->in
.map_tower
->tower
.floors
;
886 /* We accept NDR as the transfer syntax */
887 dcerpc_floor_get_lhs_data(&floors
[1], &ifid
);
889 if (floors
[1].lhs
.protocol
!= EPM_PROTOCOL_UUID
||
890 !GUID_equal(&ifid
.uuid
, &ndr_transfer_syntax
.uuid
) ||
891 ifid
.if_version
!= ndr_transfer_syntax
.if_version
) {
892 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
896 /* We only talk to sane transports */
897 transport
= dcerpc_transport_by_tower(&r
->in
.map_tower
->tower
);
898 if (transport
== NCA_UNKNOWN
) {
899 DEBUG(2, ("epm_Map: Client requested unknown transport with"
901 for (i
= 2; i
< r
->in
.map_tower
->tower
.num_floors
; i
++) {
902 DEBUG(2, ("%d, ", r
->in
.map_tower
->tower
.floors
[i
].lhs
.protocol
));
905 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
909 if (r
->in
.entry_handle
== NULL
||
910 policy_handle_empty(r
->in
.entry_handle
)) {
913 DEBUG(5, ("_epm_Map: No entry_handle found, creating it.\n"));
915 eps
= talloc_zero(tmp_ctx
, struct rpc_eps
);
917 rc
= EPMAPPER_STATUS_NO_MEMORY
;
926 * Apply some algorithm (using the fields in the map_tower)
927 * to an endpoint map to produce a list of protocol towers.
929 * The following code is the mysterious "some algorithm"!
932 /* Filter by object id if one was given. */
933 if (r
->in
.object
== NULL
|| GUID_all_zero(r
->in
.object
)) {
939 eps
->count
= build_ep_list(eps
,
942 p
->server_id
== NULL
? NULL
: p
->server_id
->addr
,
944 if (eps
->count
== 0) {
945 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
949 /* Filter out endpoints which match the interface. */
951 struct rpc_eps
*teps
;
954 teps
= talloc_zero(tmp_ctx
, struct rpc_eps
);
956 rc
= EPMAPPER_STATUS_NO_MEMORY
;
960 for (i
= 0; i
< eps
->count
; i
++) {
961 if (data_blob_cmp(&r
->in
.map_tower
->tower
.floors
[0].lhs
.lhs_data
,
962 &eps
->e
[i
].ep
.floors
[0].lhs
.lhs_data
) != 0 ||
963 transport
!= dcerpc_transport_by_tower(&eps
->e
[i
].ep
)) {
967 teps
->e
= talloc_realloc(tmp_ctx
,
969 struct dcesrv_ep_iface
,
971 if (teps
->e
== NULL
) {
975 teps
->e
[total
].ep
.floors
= talloc_move(teps
, &eps
->e
[i
].ep
.floors
);
976 teps
->e
[total
].ep
.num_floors
= eps
->e
[i
].ep
.num_floors
;
977 teps
->e
[total
].name
= talloc_move(teps
, &eps
->e
[i
].name
);
978 teps
->e
[total
].syntax_id
= eps
->e
[i
].syntax_id
;
987 /* end of "some algorithm" */
989 ok
= create_policy_hnd(p
, r
->out
.entry_handle
, eps
);
991 rc
= EPMAPPER_STATUS_NO_MEMORY
;
995 ok
= find_policy_by_hnd(p
, r
->out
.entry_handle
, (void **)(void*) &eps
);
997 rc
= EPMAPPER_STATUS_NO_MEMORY
;
1000 entry_handle
= r
->out
.entry_handle
;
1002 DEBUG(5, ("_epm_Map: Trying to find entry_handle.\n"));
1004 ok
= find_policy_by_hnd(p
, r
->in
.entry_handle
, (void **)(void*) &eps
);
1006 rc
= EPMAPPER_STATUS_NO_MEMORY
;
1009 entry_handle
= r
->in
.entry_handle
;
1012 if (eps
== NULL
|| eps
->e
== NULL
) {
1013 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
1017 /* return the next N elements */
1018 count
= r
->in
.max_towers
;
1019 if (count
> eps
->count
) {
1024 close_policy_hnd(p
, entry_handle
);
1025 ZERO_STRUCTP(r
->out
.entry_handle
);
1027 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
1031 r
->out
.towers
= talloc_array(p
->mem_ctx
, struct epm_twr_p_t
, count
);
1032 if (r
->out
.towers
== NULL
) {
1033 rc
= EPMAPPER_STATUS_NO_MEMORY
;
1037 for (i
= 0; i
< count
; i
++) {
1038 DEBUG(5, ("_epm_Map: Map tower for '%s'\n",
1041 r
->out
.towers
[num_towers
].twr
= talloc(r
->out
.towers
,
1043 if (r
->out
.towers
[num_towers
].twr
== NULL
) {
1044 rc
= EPMAPPER_STATUS_NO_MEMORY
;
1047 r
->out
.towers
[num_towers
].twr
->tower
.floors
= talloc_move(r
->out
.towers
[num_towers
].twr
, &eps
->e
[i
].ep
.floors
);
1048 r
->out
.towers
[num_towers
].twr
->tower
.num_floors
= eps
->e
[i
].ep
.num_floors
;
1049 r
->out
.towers
[num_towers
].twr
->tower_length
= 0;
1054 *r
->out
.num_towers
= num_towers
;
1056 eps
->count
-= count
;
1058 if (eps
->count
== 0) {
1059 close_policy_hnd(p
, entry_handle
);
1060 ZERO_STRUCTP(r
->out
.entry_handle
);
1063 rc
= EPMAPPER_STATUS_OK
;
1065 talloc_free(tmp_ctx
);
1071 * epm_LookupHandleFree
1073 error_status_t
_epm_LookupHandleFree(struct pipes_struct
*p
,
1074 struct epm_LookupHandleFree
*r
)
1076 if (r
->in
.entry_handle
== NULL
) {
1077 return EPMAPPER_STATUS_OK
;
1080 if (is_valid_policy_hnd(r
->in
.entry_handle
)) {
1081 close_policy_hnd(p
, r
->in
.entry_handle
);
1084 r
->out
.entry_handle
= r
->in
.entry_handle
;
1086 return EPMAPPER_STATUS_OK
;
1093 * A client implementation SHOULD NOT call this method. These extensions do not
1094 * provide an alternative method.
1096 error_status_t
_epm_InqObject(struct pipes_struct
*p
,
1097 struct epm_InqObject
*r
)
1099 p
->rng_fault_state
= true;
1100 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
1107 * A client implementation SHOULD NOT call this method. These extensions do not
1108 * provide an alternative method.
1110 error_status_t
_epm_MgmtDelete(struct pipes_struct
*p
,
1111 struct epm_MgmtDelete
*r
)
1113 p
->rng_fault_state
= true;
1114 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
1121 error_status_t
_epm_MapAuth(struct pipes_struct
*p
,
1122 struct epm_MapAuth
*r
)
1124 p
->rng_fault_state
= true;
1125 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
1128 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */