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
;
62 struct dcesrv_ep_entry_list
{
63 struct dcesrv_ep_entry_list
*next
, *prev
;
66 struct epm_entry_t
*entries
;
70 struct dcesrv_ep_iface
*e
;
74 static struct dcesrv_endpoint
*endpoint_table
;
77 * Check if the UUID and if_version match to an interface.
79 static bool interface_match(const struct dcesrv_iface
*if1
,
80 const struct dcesrv_iface
*if2
)
82 return GUID_equal(&if1
->syntax_id
.uuid
, &if2
->syntax_id
.uuid
);
86 * Find the interface operations on an endpoint.
88 static const struct dcesrv_iface
*find_interface(const struct dcesrv_endpoint
*endpoint
,
89 const struct dcesrv_iface
*iface
)
91 struct dcesrv_iface_list
*iflist
;
93 for (iflist
= endpoint
->iface_list
; iflist
; iflist
= iflist
->next
) {
94 if (interface_match(iflist
->iface
, iface
)) {
103 * See if a uuid and if_version match to an interface
105 static bool interface_match_by_uuid(const struct dcesrv_iface
*iface
,
106 const struct GUID
*uuid
)
108 return GUID_equal(&iface
->syntax_id
.uuid
, uuid
);
111 static struct dcesrv_iface_list
*find_interface_list(const struct dcesrv_endpoint
*endpoint
,
112 const struct dcesrv_iface
*iface
)
114 struct dcesrv_iface_list
*iflist
;
116 for (iflist
= endpoint
->iface_list
; iflist
; iflist
= iflist
->next
) {
117 if (interface_match(iflist
->iface
, iface
)) {
126 * Check if two endpoints match.
128 static bool endpoints_match(const struct dcerpc_binding
*ep1
,
129 const struct dcerpc_binding
*ep2
)
131 if (ep1
->transport
!= ep2
->transport
) {
135 if (!ep1
->endpoint
|| !ep2
->endpoint
) {
136 return ep1
->endpoint
== ep2
->endpoint
;
139 if (!strequal(ep1
->endpoint
, ep2
->endpoint
)) {
146 static struct dcesrv_endpoint
*find_endpoint(struct dcesrv_endpoint
*endpoint_list
,
147 struct dcerpc_binding
*ep_description
) {
148 struct dcesrv_endpoint
*ep
;
150 for (ep
= endpoint_list
; ep
!= NULL
; ep
= ep
->next
) {
151 if (endpoints_match(ep
->ep_description
, ep_description
)) {
160 * Build a list of all interfaces handled by all endpoint servers.
162 static uint32_t build_ep_list(TALLOC_CTX
*mem_ctx
,
163 struct dcesrv_endpoint
*endpoint_list
,
164 const struct GUID
*uuid
,
165 const char *srv_addr
,
166 struct dcesrv_ep_iface
**peps
)
168 struct dcesrv_ep_iface
*eps
= NULL
;
169 struct dcesrv_endpoint
*d
;
175 for (d
= endpoint_list
; d
!= NULL
; d
= d
->next
) {
176 struct dcesrv_iface_list
*iface
;
177 struct dcerpc_binding
*description
;
179 for (iface
= d
->iface_list
; iface
!= NULL
; iface
= iface
->next
) {
180 if (uuid
&& !interface_match_by_uuid(iface
->iface
, uuid
)) {
184 eps
= talloc_realloc(mem_ctx
,
186 struct dcesrv_ep_iface
,
191 eps
[total
].name
= talloc_strdup(eps
,
193 eps
[total
].syntax_id
= iface
->iface
->syntax_id
;
195 description
= d
->ep_description
;
196 description
->object
= iface
->iface
->syntax_id
;
197 if (description
->transport
== NCACN_IP_TCP
&&
199 strequal(description
->host
, "0.0.0.0")) {
200 description
->host
= srv_addr
;
203 status
= dcerpc_binding_build_tower(eps
,
206 if (NT_STATUS_IS_ERR(status
)) {
207 DEBUG(1, ("Unable to build tower for %s\n",
208 iface
->iface
->name
));
220 static bool is_priviledged_pipe(struct auth_serversupplied_info
*info
) {
221 /* If the user is not root, or has the system token, fail */
222 if ((info
->utok
.uid
!= sec_initial_uid()) &&
223 !security_token_is_system(info
->security_token
)) {
230 bool srv_epmapper_delete_endpoints(struct pipes_struct
*p
)
233 struct dcesrv_ep_entry_list
*el
;
234 error_status_t result
;
236 if (p
->ep_entries
== NULL
) {
240 for (el
= p
->ep_entries
;
242 el
= p
->ep_entries
) {
243 r
.in
.num_ents
= el
->num_ents
;
244 r
.in
.entries
= el
->entries
;
246 DEBUG(10, ("Delete_endpoints for: %s\n",
247 el
->entries
[0].annotation
));
249 result
= _epm_Delete(p
, &r
);
250 if (result
!= EPMAPPER_STATUS_OK
) {
254 DLIST_REMOVE(p
->ep_entries
, el
);
261 void srv_epmapper_cleanup(void)
263 struct dcesrv_endpoint
*ep
;
265 for (ep
= endpoint_table
;
267 ep
= endpoint_table
) {
268 DLIST_REMOVE(endpoint_table
, ep
);
276 * Add the specified entries to an endpoint map.
278 error_status_t
_epm_Insert(struct pipes_struct
*p
,
279 struct epm_Insert
*r
)
286 /* If this is not a priviledged users, return */
287 if (p
->transport
!= NCALRPC
||
288 !is_priviledged_pipe(p
->session_info
)) {
289 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
292 tmp_ctx
= talloc_stackframe();
293 if (tmp_ctx
== NULL
) {
294 return EPMAPPER_STATUS_NO_MEMORY
;
297 DEBUG(3, ("_epm_Insert: Trying to add %u new entries.\n",
300 for (i
= 0; i
< r
->in
.num_ents
; i
++) {
301 struct dcerpc_binding
*b
= NULL
;
302 struct dcesrv_endpoint
*ep
;
303 struct dcesrv_iface_list
*iflist
;
304 struct dcesrv_iface
*iface
;
307 status
= dcerpc_binding_from_tower(tmp_ctx
,
308 &r
->in
.entries
[i
].tower
->tower
,
310 if (!NT_STATUS_IS_OK(status
)) {
311 rc
= EPMAPPER_STATUS_NO_MEMORY
;
315 DEBUG(3, ("_epm_Insert: Adding transport %s for %s\n",
316 derpc_transport_string_by_transport(b
->transport
),
317 r
->in
.entries
[i
].annotation
));
319 /* Check if the entry already exits */
320 ep
= find_endpoint(endpoint_table
, b
);
322 /* No entry found, create it */
323 ep
= talloc_zero(NULL
, struct dcesrv_endpoint
);
325 rc
= EPMAPPER_STATUS_CANT_PERFORM_OP
;
330 ep
->ep_description
= talloc_steal(ep
, b
);
333 /* TODO Replace the entry if the replace flag is set */
335 /* Create an interface */
336 iface
= talloc(tmp_ctx
, struct dcesrv_iface
);
338 rc
= EPMAPPER_STATUS_NO_MEMORY
;
342 iface
->name
= talloc_strdup(iface
, r
->in
.entries
[i
].annotation
);
343 if (iface
->name
== NULL
) {
344 rc
= EPMAPPER_STATUS_NO_MEMORY
;
347 iface
->syntax_id
= b
->object
;
350 * Check if the rpc service is alrady registered on the
353 if (find_interface(ep
, iface
) != NULL
) {
354 DEBUG(0, ("dcesrv_interface_register: interface '%s' "
355 "already registered on endpoint\n",
357 /* FIXME wrong error code? */
358 rc
= EPMAPPER_STATUS_OK
;
362 /* Create an entry for the interface */
363 iflist
= talloc(ep
, struct dcesrv_iface_list
);
364 if (iflist
== NULL
) {
365 rc
= EPMAPPER_STATUS_NO_MEMORY
;
368 iflist
->iface
= talloc_move(iflist
, &iface
);
370 /* Finally add the interface on the endpoint */
371 DLIST_ADD(ep
->iface_list
, iflist
);
373 /* If it's a new endpoint add it to the endpoint_table */
375 DLIST_ADD(endpoint_table
, ep
);
379 if (r
->in
.num_ents
> 0) {
380 struct dcesrv_ep_entry_list
*el
;
382 el
= talloc_zero(p
->mem_ctx
, struct dcesrv_ep_entry_list
);
384 rc
= EPMAPPER_STATUS_NO_MEMORY
;
387 el
->num_ents
= r
->in
.num_ents
;
388 el
->entries
= talloc_move(el
, &r
->in
.entries
);
390 DLIST_ADD(p
->ep_entries
, el
);
393 rc
= EPMAPPER_STATUS_OK
;
395 talloc_free(tmp_ctx
);
404 * Delete the specified entries from an endpoint map.
406 error_status_t
_epm_Delete(struct pipes_struct
*p
,
407 struct epm_Delete
*r
)
414 DEBUG(3, ("_epm_Delete: Trying to delete %u entries.\n",
417 /* If this is not a priviledged users, return */
418 if (p
->transport
!= NCALRPC
||
419 !is_priviledged_pipe(p
->session_info
)) {
420 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
423 tmp_ctx
= talloc_stackframe();
424 if (tmp_ctx
== NULL
) {
425 return EPMAPPER_STATUS_NO_MEMORY
;
428 for (i
= 0; i
< r
->in
.num_ents
; i
++) {
429 struct dcerpc_binding
*b
= NULL
;
430 struct dcesrv_endpoint
*ep
;
431 struct dcesrv_iface iface
;
432 struct dcesrv_iface_list
*iflist
;
434 status
= dcerpc_binding_from_tower(tmp_ctx
,
435 &r
->in
.entries
[i
].tower
->tower
,
437 if (!NT_STATUS_IS_OK(status
)) {
438 rc
= EPMAPPER_STATUS_NO_MEMORY
;
442 DEBUG(3, ("_epm_Delete: Deleting transport '%s' for '%s'\n",
443 derpc_transport_string_by_transport(b
->transport
),
444 r
->in
.entries
[i
].annotation
));
446 ep
= find_endpoint(endpoint_table
, b
);
448 rc
= EPMAPPER_STATUS_OK
;
452 iface
.name
= r
->in
.entries
[i
].annotation
;
453 iface
.syntax_id
= b
->object
;
455 iflist
= find_interface_list(ep
, &iface
);
456 if (iflist
== NULL
) {
457 DEBUG(0, ("_epm_Delete: No interfaces left, delete endpoint\n"));
458 DLIST_REMOVE(endpoint_table
, ep
);
461 rc
= EPMAPPER_STATUS_OK
;
465 DLIST_REMOVE(ep
->iface_list
, iflist
);
467 if (ep
->iface_list
== NULL
) {
468 DEBUG(0, ("_epm_Delete: No interfaces left, delete endpoint\n"));
469 DLIST_REMOVE(endpoint_table
, ep
);
472 rc
= EPMAPPER_STATUS_OK
;
478 rc
= EPMAPPER_STATUS_OK
;
480 talloc_free(tmp_ctx
);
489 * Lookup entries in an endpoint map.
491 error_status_t
_epm_Lookup(struct pipes_struct
*p
,
492 struct epm_Lookup
*r
)
494 struct policy_handle
*entry_handle
;
499 uint32_t num_ents
= 0;
504 *r
->out
.num_ents
= 0;
505 r
->out
.entries
= NULL
;
507 tmp_ctx
= talloc_stackframe();
508 if (tmp_ctx
== NULL
) {
509 return EPMAPPER_STATUS_NO_MEMORY
;
512 DEBUG(3, ("_epm_Lookup: Trying to lookup max. %u entries.\n",
515 if (r
->in
.entry_handle
== NULL
||
516 policy_handle_empty(r
->in
.entry_handle
)) {
519 DEBUG(5, ("_epm_Lookup: No entry_handle found, creating it.\n"));
521 eps
= talloc_zero(tmp_ctx
, struct rpc_eps
);
523 rc
= EPMAPPER_STATUS_NO_MEMORY
;
527 if (r
->in
.object
== NULL
|| GUID_all_zero(r
->in
.object
)) {
533 switch (r
->in
.inquiry_type
) {
534 case RPC_C_EP_ALL_ELTS
:
536 * Return all elements from the endpoint map. The
537 * interface_id, vers_option, and object parameters MUST
540 eps
->count
= build_ep_list(eps
,
543 p
->server_id
== NULL
? NULL
: p
->server_id
->addr
,
546 case RPC_C_EP_MATCH_BY_IF
:
548 * Return endpoint map elements that contain the
549 * interface identifier specified by the interface_id
550 * and vers_option values.
552 * RPC_C_EP_MATCH_BY_IF and RPC_C_EP_MATCH_BY_BOTH
553 * need both the same endpoint list. There is a second
554 * check for the inquiry_type below which differentiates
557 case RPC_C_EP_MATCH_BY_BOTH
:
559 * Return endpoint map elements that contain the
560 * interface identifier and object UUID specified by
561 * interface_id, vers_option, and object.
563 eps
->count
= build_ep_list(eps
,
565 &r
->in
.interface_id
->uuid
,
566 p
->server_id
== NULL
? NULL
: p
->server_id
->addr
,
569 case RPC_C_EP_MATCH_BY_OBJ
:
571 * Return endpoint map elements that contain the object
572 * UUID specified by object.
574 eps
->count
= build_ep_list(eps
,
577 p
->server_id
== NULL
? NULL
: p
->server_id
->addr
,
581 rc
= EPMAPPER_STATUS_CANT_PERFORM_OP
;
585 if (eps
->count
== 0) {
586 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
590 ok
= create_policy_hnd(p
, r
->out
.entry_handle
, eps
);
592 rc
= EPMAPPER_STATUS_NO_MEMORY
;
596 ok
= find_policy_by_hnd(p
, r
->out
.entry_handle
, (void **)(void*) &eps
);
598 rc
= EPMAPPER_STATUS_NO_MEMORY
;
601 entry_handle
= r
->out
.entry_handle
;
603 DEBUG(5, ("_epm_Lookup: Trying to find entry_handle.\n"));
605 ok
= find_policy_by_hnd(p
, r
->in
.entry_handle
, (void **)(void*) &eps
);
607 rc
= EPMAPPER_STATUS_NO_MEMORY
;
610 entry_handle
= r
->in
.entry_handle
;
613 if (eps
== NULL
|| eps
->e
== NULL
) {
614 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
618 /* return the next N elements */
619 count
= r
->in
.max_ents
;
620 if (count
> eps
->count
) {
624 DEBUG(3, ("_epm_Lookup: Find %u entries\n", count
));
627 close_policy_hnd(p
, entry_handle
);
628 ZERO_STRUCTP(r
->out
.entry_handle
);
630 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
634 r
->out
.entries
= talloc_array(p
->mem_ctx
, struct epm_entry_t
, count
);
635 if (r
->out
.entries
== NULL
) {
636 rc
= EPMAPPER_STATUS_NO_MEMORY
;
640 for (i
= 0; i
< count
; i
++) {
643 switch (r
->in
.inquiry_type
) {
644 case RPC_C_EP_ALL_ELTS
:
646 * Return all elements from the endpoint map. The
647 * interface_id, vers_option, and object parameters MUST
652 case RPC_C_EP_MATCH_BY_IF
:
654 * Return endpoint map elements that contain the
655 * interface identifier specified by the interface_id
656 * and vers_option values.
658 if (GUID_equal(&r
->in
.interface_id
->uuid
,
659 &eps
->e
[i
].syntax_id
.uuid
)) {
663 case RPC_C_EP_MATCH_BY_OBJ
:
665 * Return endpoint map elements that contain the object
666 * UUID specified by object.
668 if (GUID_equal(r
->in
.object
,
669 &eps
->e
[i
].syntax_id
.uuid
)) {
673 case RPC_C_EP_MATCH_BY_BOTH
:
675 * Return endpoint map elements that contain the
676 * interface identifier and object UUID specified by
677 * interface_id, vers_option, and object.
679 if (GUID_equal(&r
->in
.interface_id
->uuid
,
680 &eps
->e
[i
].syntax_id
.uuid
) &&
681 GUID_equal(r
->in
.object
, &eps
->e
[i
].syntax_id
.uuid
)) {
686 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
690 if (r
->in
.inquiry_type
== RPC_C_EP_MATCH_BY_IF
||
691 r
->in
.inquiry_type
== RPC_C_EP_MATCH_BY_OBJ
) {
692 /* Check inteface version */
695 switch (r
->in
.vers_option
) {
698 * Return endpoint map elements that
699 * contain the specified interface UUID,
700 * regardless of the version numbers.
704 case RPC_C_VERS_COMPATIBLE
:
706 * Return the endpoint map elements that
707 * contain the same major versions of
708 * the specified interface UUID and a
709 * minor version greater than or equal
710 * to the minor version of the specified
713 if (r
->in
.interface_id
->vers_major
==
714 (eps
->e
[i
].syntax_id
.if_version
>> 16) &&
715 r
->in
.interface_id
->vers_minor
<=
716 (eps
->e
[i
].syntax_id
.if_version
&& 0xFFFF)) {
720 case RPC_C_VERS_EXACT
:
722 * Return endpoint map elements that
723 * contain the specified version of the
724 * specified interface UUID.
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)) {
734 case RPC_C_VERS_MAJOR_ONLY
:
736 * Return endpoint map elements that
737 * contain the same version of the
738 * specified interface UUID and ignore
741 if (r
->in
.interface_id
->vers_major
==
742 (eps
->e
[i
].syntax_id
.if_version
>> 16)) {
747 case RPC_C_VERS_UPTO
:
749 * Return endpoint map elements that
750 * contain a version of the specified
751 * interface UUID less than or equal to
752 * the specified major and minor
755 if (r
->in
.interface_id
->vers_major
>
756 eps
->e
[i
].syntax_id
.if_version
>> 16) {
759 if (r
->in
.interface_id
->vers_major
==
760 (eps
->e
[i
].syntax_id
.if_version
>> 16) &&
761 r
->in
.interface_id
->vers_minor
>=
762 (eps
->e
[i
].syntax_id
.if_version
&& 0xFFFF)) {
768 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
774 ZERO_STRUCT(r
->out
.entries
[num_ents
].object
);
776 DEBUG(10, ("_epm_Lookup: Adding tower for '%s'\n",
778 r
->out
.entries
[num_ents
].annotation
= talloc_strdup(r
->out
.entries
,
780 r
->out
.entries
[num_ents
].tower
= talloc(r
->out
.entries
,
782 if (r
->out
.entries
[num_ents
].tower
== NULL
) {
783 rc
= EPMAPPER_STATUS_NO_MEMORY
;
786 r
->out
.entries
[num_ents
].tower
->tower
.floors
= talloc_move(r
->out
.entries
[num_ents
].tower
, &eps
->e
[i
].ep
.floors
);
787 r
->out
.entries
[num_ents
].tower
->tower
.num_floors
= eps
->e
[i
].ep
.num_floors
;
788 r
->out
.entries
[num_ents
].tower
->tower_length
= 0;
794 *r
->out
.num_ents
= num_ents
;
798 if (eps
->count
== 0) {
799 close_policy_hnd(p
, entry_handle
);
800 ZERO_STRUCTP(r
->out
.entry_handle
);
801 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
805 rc
= EPMAPPER_STATUS_OK
;
807 talloc_free(tmp_ctx
);
815 * Apply some algorithm (using the fields in the map_tower) to an endpoint map
816 * to produce a list of protocol towers.
818 error_status_t
_epm_Map(struct pipes_struct
*p
,
821 struct policy_handle
*entry_handle
;
822 enum dcerpc_transport_t transport
;
823 struct ndr_syntax_id ifid
;
824 struct epm_floor
*floors
;
829 uint32_t num_towers
= 0;
830 uint32_t num_floors
= 0;
834 *r
->out
.num_towers
= 0;
835 r
->out
.towers
= NULL
;
837 if (r
->in
.map_tower
== NULL
|| r
->in
.max_towers
== 0 ||
838 r
->in
.map_tower
->tower
.num_floors
< 3) {
839 return EPMAPPER_STATUS_NO_MORE_ENTRIES
;
842 tmp_ctx
= talloc_stackframe();
843 if (tmp_ctx
== NULL
) {
844 return EPMAPPER_STATUS_NO_MEMORY
;
847 ZERO_STRUCTP(r
->out
.entry_handle
);
849 DEBUG(3, ("_epm_Map: Trying to map max. %u towers.\n",
853 * A tower has normally up to 6 floors
855 * +-----------------------------------------------------------------+
856 * | Floor 1 | Provides the RPC interface identifier. (e.g. UUID for |
858 * +---------+-------------------------------------------------------+
859 * | Floor 2 | Transfer syntax (NDR endcoded) |
860 * +---------+-------------------------------------------------------+
861 * | Floor 3 | RPC protocol identifier (ncacn_tcp_ip, ncacn_np, ...) |
862 * +---------+-------------------------------------------------------+
863 * | Floor 4 | Port address (e.g. TCP Port: 49156) |
864 * +---------+-------------------------------------------------------+
865 * | Floor 5 | Transport (e.g. IP:192.168.51.10) |
866 * +---------+-------------------------------------------------------+
867 * | Floor 6 | Routing |
868 * +---------+-------------------------------------------------------+
870 num_floors
= r
->in
.map_tower
->tower
.num_floors
;
871 floors
= r
->in
.map_tower
->tower
.floors
;
873 /* We accept NDR as the transfer syntax */
874 dcerpc_floor_get_lhs_data(&floors
[1], &ifid
);
876 if (floors
[1].lhs
.protocol
!= EPM_PROTOCOL_UUID
||
877 !GUID_equal(&ifid
.uuid
, &ndr_transfer_syntax
.uuid
) ||
878 ifid
.if_version
!= ndr_transfer_syntax
.if_version
) {
879 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
883 /* We only talk to sane transports */
884 transport
= dcerpc_transport_by_tower(&r
->in
.map_tower
->tower
);
885 if (transport
== NCA_UNKNOWN
) {
886 DEBUG(2, ("epm_Map: Client requested unknown transport with"
888 for (i
= 2; i
< r
->in
.map_tower
->tower
.num_floors
; i
++) {
889 DEBUG(2, ("%d, ", r
->in
.map_tower
->tower
.floors
[i
].lhs
.protocol
));
892 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
896 if (r
->in
.entry_handle
== NULL
||
897 policy_handle_empty(r
->in
.entry_handle
)) {
900 DEBUG(5, ("_epm_Map: No entry_handle found, creating it.\n"));
902 eps
= talloc_zero(tmp_ctx
, struct rpc_eps
);
904 rc
= EPMAPPER_STATUS_NO_MEMORY
;
913 * Apply some algorithm (using the fields in the map_tower)
914 * to an endpoint map to produce a list of protocol towers.
916 * The following code is the mysterious "some algorithm"!
919 /* Filter by object id if one was given. */
920 if (r
->in
.object
== NULL
|| GUID_all_zero(r
->in
.object
)) {
926 eps
->count
= build_ep_list(eps
,
929 p
->server_id
== NULL
? NULL
: p
->server_id
->addr
,
931 if (eps
->count
== 0) {
932 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
936 /* Filter out endpoints which match the interface. */
938 struct rpc_eps
*teps
;
941 teps
= talloc_zero(tmp_ctx
, struct rpc_eps
);
943 rc
= EPMAPPER_STATUS_NO_MEMORY
;
947 for (i
= 0; i
< eps
->count
; i
++) {
948 if (data_blob_cmp(&r
->in
.map_tower
->tower
.floors
[0].lhs
.lhs_data
,
949 &eps
->e
[i
].ep
.floors
[0].lhs
.lhs_data
) != 0 ||
950 transport
!= dcerpc_transport_by_tower(&eps
->e
[i
].ep
)) {
954 teps
->e
= talloc_realloc(tmp_ctx
,
956 struct dcesrv_ep_iface
,
958 if (teps
->e
== NULL
) {
962 teps
->e
[total
].ep
.floors
= talloc_move(teps
, &eps
->e
[i
].ep
.floors
);
963 teps
->e
[total
].ep
.num_floors
= eps
->e
[i
].ep
.num_floors
;
964 teps
->e
[total
].name
= talloc_move(teps
, &eps
->e
[i
].name
);
965 teps
->e
[total
].syntax_id
= eps
->e
[i
].syntax_id
;
974 /* end of "some algorithm" */
976 ok
= create_policy_hnd(p
, r
->out
.entry_handle
, eps
);
978 rc
= EPMAPPER_STATUS_NO_MEMORY
;
982 ok
= find_policy_by_hnd(p
, r
->out
.entry_handle
, (void **)(void*) &eps
);
984 rc
= EPMAPPER_STATUS_NO_MEMORY
;
987 entry_handle
= r
->out
.entry_handle
;
989 DEBUG(5, ("_epm_Map: Trying to find entry_handle.\n"));
991 ok
= find_policy_by_hnd(p
, r
->in
.entry_handle
, (void **)(void*) &eps
);
993 rc
= EPMAPPER_STATUS_NO_MEMORY
;
996 entry_handle
= r
->in
.entry_handle
;
999 if (eps
== NULL
|| eps
->e
== NULL
) {
1000 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
1004 /* return the next N elements */
1005 count
= r
->in
.max_towers
;
1006 if (count
> eps
->count
) {
1011 close_policy_hnd(p
, entry_handle
);
1012 ZERO_STRUCTP(r
->out
.entry_handle
);
1014 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
1018 r
->out
.towers
= talloc_array(p
->mem_ctx
, struct epm_twr_p_t
, count
);
1019 if (r
->out
.towers
== NULL
) {
1020 rc
= EPMAPPER_STATUS_NO_MEMORY
;
1024 for (i
= 0; i
< count
; i
++) {
1025 DEBUG(5, ("_epm_Map: Map tower for '%s'\n",
1028 r
->out
.towers
[num_towers
].twr
= talloc(r
->out
.towers
,
1030 if (r
->out
.towers
[num_towers
].twr
== NULL
) {
1031 rc
= EPMAPPER_STATUS_NO_MEMORY
;
1034 r
->out
.towers
[num_towers
].twr
->tower
.floors
= talloc_move(r
->out
.towers
[num_towers
].twr
, &eps
->e
[i
].ep
.floors
);
1035 r
->out
.towers
[num_towers
].twr
->tower
.num_floors
= eps
->e
[i
].ep
.num_floors
;
1036 r
->out
.towers
[num_towers
].twr
->tower_length
= 0;
1041 *r
->out
.num_towers
= num_towers
;
1043 eps
->count
-= count
;
1045 if (eps
->count
== 0) {
1046 close_policy_hnd(p
, entry_handle
);
1047 ZERO_STRUCTP(r
->out
.entry_handle
);
1050 rc
= EPMAPPER_STATUS_OK
;
1052 talloc_free(tmp_ctx
);
1058 * epm_LookupHandleFree
1060 error_status_t
_epm_LookupHandleFree(struct pipes_struct
*p
,
1061 struct epm_LookupHandleFree
*r
)
1063 if (r
->in
.entry_handle
== NULL
) {
1064 return EPMAPPER_STATUS_OK
;
1067 if (is_valid_policy_hnd(r
->in
.entry_handle
)) {
1068 close_policy_hnd(p
, r
->in
.entry_handle
);
1071 r
->out
.entry_handle
= r
->in
.entry_handle
;
1073 return EPMAPPER_STATUS_OK
;
1080 * A client implementation SHOULD NOT call this method. These extensions do not
1081 * provide an alternative method.
1083 error_status_t
_epm_InqObject(struct pipes_struct
*p
,
1084 struct epm_InqObject
*r
)
1086 p
->rng_fault_state
= true;
1087 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
1094 * A client implementation SHOULD NOT call this method. These extensions do not
1095 * provide an alternative method.
1097 error_status_t
_epm_MgmtDelete(struct pipes_struct
*p
,
1098 struct epm_MgmtDelete
*r
)
1100 p
->rng_fault_state
= true;
1101 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
1108 error_status_t
_epm_MapAuth(struct pipes_struct
*p
,
1109 struct epm_MapAuth
*r
)
1111 p
->rng_fault_state
= true;
1112 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
1115 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */