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_session_info
*info
) {
236 /* If the user is not root, or has the system token, fail */
237 if ((info
->unix_token
->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 p
->rng_fault_state
= true;
310 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
313 tmp_ctx
= talloc_stackframe();
314 if (tmp_ctx
== NULL
) {
315 return EPMAPPER_STATUS_NO_MEMORY
;
318 DEBUG(3, ("_epm_Insert: Trying to add %u new entries.\n",
321 for (i
= 0; i
< r
->in
.num_ents
; i
++) {
325 status
= dcerpc_binding_from_tower(tmp_ctx
,
326 &r
->in
.entries
[i
].tower
->tower
,
328 if (NT_STATUS_EQUAL(status
, NT_STATUS_NO_MEMORY
)) {
329 rc
= EPMAPPER_STATUS_NO_MEMORY
;
332 if (!NT_STATUS_IS_OK(status
)) {
333 rc
= EPMAPPER_STATUS_CANT_PERFORM_OP
;
337 DEBUG(3, ("_epm_Insert: Adding transport %s for %s\n",
338 derpc_transport_string_by_transport(b
->transport
),
339 r
->in
.entries
[i
].annotation
));
341 /* Check if the entry already exits */
342 ep
= find_endpoint(endpoint_table
, b
);
344 /* No entry found, create it */
345 ep
= talloc_zero(NULL
, struct dcesrv_endpoint
);
347 rc
= EPMAPPER_STATUS_NO_MEMORY
;
352 ep
->ep_description
= talloc_steal(ep
, b
);
355 /* TODO Replace the entry if the replace flag is set */
357 /* Create an interface */
358 iface
= talloc(tmp_ctx
, struct dcesrv_iface
);
360 rc
= EPMAPPER_STATUS_NO_MEMORY
;
364 iface
->name
= talloc_strdup(iface
, r
->in
.entries
[i
].annotation
);
365 if (iface
->name
== NULL
) {
366 rc
= EPMAPPER_STATUS_NO_MEMORY
;
369 iface
->syntax_id
= b
->object
;
372 * Check if the rpc service is alrady registered on the
375 if (find_interface(ep
, iface
) != NULL
) {
376 DEBUG(0, ("dcesrv_interface_register: interface '%s' "
377 "already registered on endpoint\n",
379 /* FIXME wrong error code? */
380 rc
= EPMAPPER_STATUS_OK
;
384 /* Create an entry for the interface */
385 iflist
= talloc(ep
, struct dcesrv_iface_list
);
386 if (iflist
== NULL
) {
387 rc
= EPMAPPER_STATUS_NO_MEMORY
;
390 iflist
->iface
= talloc_move(iflist
, &iface
);
392 /* Finally add the interface on the endpoint */
393 DLIST_ADD(ep
->iface_list
, iflist
);
395 /* If it's a new endpoint add it to the endpoint_table */
397 DLIST_ADD(endpoint_table
, ep
);
401 if (r
->in
.num_ents
> 0) {
402 struct dcesrv_ep_entry_list
*el
;
404 el
= talloc_zero(p
, struct dcesrv_ep_entry_list
);
406 rc
= EPMAPPER_STATUS_NO_MEMORY
;
409 el
->num_ents
= r
->in
.num_ents
;
410 el
->entries
= talloc_move(el
, &r
->in
.entries
);
412 DLIST_ADD(p
->ep_entries
, el
);
415 rc
= EPMAPPER_STATUS_OK
;
417 talloc_free(tmp_ctx
);
426 * Delete the specified entries from an endpoint map.
428 error_status_t
_epm_Delete(struct pipes_struct
*p
,
429 struct epm_Delete
*r
)
435 struct dcerpc_binding
*b
;
436 struct dcesrv_endpoint
*ep
;
437 struct dcesrv_iface iface
;
438 struct dcesrv_iface_list
*iflist
;
440 DEBUG(3, ("_epm_Delete: Trying to delete %u entries.\n",
443 /* If this is not a priviledged users, return */
444 if (p
->transport
!= NCALRPC
||
445 !is_priviledged_pipe(p
->session_info
)) {
446 p
->rng_fault_state
= true;
447 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
450 tmp_ctx
= talloc_stackframe();
451 if (tmp_ctx
== NULL
) {
452 return EPMAPPER_STATUS_NO_MEMORY
;
455 for (i
= 0; i
< r
->in
.num_ents
; i
++) {
458 status
= dcerpc_binding_from_tower(tmp_ctx
,
459 &r
->in
.entries
[i
].tower
->tower
,
461 if (!NT_STATUS_IS_OK(status
)) {
462 rc
= EPMAPPER_STATUS_NO_MEMORY
;
466 DEBUG(3, ("_epm_Delete: Deleting transport '%s' for '%s'\n",
467 derpc_transport_string_by_transport(b
->transport
),
468 r
->in
.entries
[i
].annotation
));
470 ep
= find_endpoint(endpoint_table
, b
);
472 rc
= EPMAPPER_STATUS_OK
;
476 iface
.name
= r
->in
.entries
[i
].annotation
;
477 iface
.syntax_id
= b
->object
;
479 iflist
= find_interface_list(ep
, &iface
);
480 if (iflist
== NULL
) {
481 DEBUG(0, ("_epm_Delete: No interfaces left, delete endpoint\n"));
482 DLIST_REMOVE(endpoint_table
, ep
);
485 rc
= EPMAPPER_STATUS_OK
;
489 DLIST_REMOVE(ep
->iface_list
, iflist
);
491 if (ep
->iface_list
== NULL
) {
492 DEBUG(0, ("_epm_Delete: No interfaces left, delete endpoint\n"));
493 DLIST_REMOVE(endpoint_table
, ep
);
496 rc
= EPMAPPER_STATUS_OK
;
502 rc
= EPMAPPER_STATUS_OK
;
504 talloc_free(tmp_ctx
);
513 * Lookup entries in an endpoint map.
515 error_status_t
_epm_Lookup(struct pipes_struct
*p
,
516 struct epm_Lookup
*r
)
518 struct policy_handle
*entry_handle
;
523 uint32_t num_ents
= 0;
528 *r
->out
.num_ents
= 0;
529 r
->out
.entries
= NULL
;
531 tmp_ctx
= talloc_stackframe();
532 if (tmp_ctx
== NULL
) {
533 return EPMAPPER_STATUS_NO_MEMORY
;
536 DEBUG(5, ("_epm_Lookup: Trying to lookup max. %u entries.\n",
539 if (r
->in
.entry_handle
== NULL
||
540 ndr_policy_handle_empty(r
->in
.entry_handle
)) {
541 char *srv_addr
= NULL
;
543 DEBUG(7, ("_epm_Lookup: No entry_handle found, creating it.\n"));
545 eps
= talloc_zero(tmp_ctx
, struct rpc_eps
);
547 rc
= EPMAPPER_STATUS_NO_MEMORY
;
551 if (p
->local_address
!= NULL
) {
552 srv_addr
= tsocket_address_inet_addr_string(p
->local_address
,
556 switch (r
->in
.inquiry_type
) {
557 case RPC_C_EP_ALL_ELTS
:
559 * Return all elements from the endpoint map. The
560 * interface_id, vers_option, and object parameters MUST
563 eps
->count
= build_ep_list(eps
,
569 case RPC_C_EP_MATCH_BY_IF
:
571 * Return endpoint map elements that contain the
572 * interface identifier specified by the interface_id
573 * and vers_option values.
575 * RPC_C_EP_MATCH_BY_IF and RPC_C_EP_MATCH_BY_BOTH
576 * need both the same endpoint list. There is a second
577 * check for the inquiry_type below which differentiates
580 case RPC_C_EP_MATCH_BY_BOTH
:
582 * Return endpoint map elements that contain the
583 * interface identifier and object UUID specified by
584 * interface_id, vers_option, and object.
586 eps
->count
= build_ep_list(eps
,
588 &r
->in
.interface_id
->uuid
,
592 case RPC_C_EP_MATCH_BY_OBJ
:
594 * Return endpoint map elements that contain the object
595 * UUID specified by object.
597 eps
->count
= build_ep_list(eps
,
604 rc
= EPMAPPER_STATUS_CANT_PERFORM_OP
;
608 if (eps
->count
== 0) {
609 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
613 ok
= create_policy_hnd(p
, r
->out
.entry_handle
, eps
);
615 rc
= EPMAPPER_STATUS_NO_MEMORY
;
619 ok
= find_policy_by_hnd(p
, r
->out
.entry_handle
, (void **)(void*) &eps
);
621 rc
= EPMAPPER_STATUS_NO_MEMORY
;
624 entry_handle
= r
->out
.entry_handle
;
626 DEBUG(7, ("_epm_Lookup: Trying to find entry_handle.\n"));
628 ok
= find_policy_by_hnd(p
, r
->in
.entry_handle
, (void **)(void*) &eps
);
630 rc
= EPMAPPER_STATUS_NO_MEMORY
;
633 entry_handle
= r
->in
.entry_handle
;
636 if (eps
== NULL
|| eps
->e
== NULL
) {
637 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
641 /* return the next N elements */
642 count
= r
->in
.max_ents
;
643 if (count
> eps
->count
) {
647 DEBUG(5, ("_epm_Lookup: Find %u entries\n", count
));
650 close_policy_hnd(p
, entry_handle
);
651 ZERO_STRUCTP(r
->out
.entry_handle
);
653 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
657 r
->out
.entries
= talloc_array(p
->mem_ctx
, struct epm_entry_t
, count
);
658 if (r
->out
.entries
== NULL
) {
659 rc
= EPMAPPER_STATUS_NO_MEMORY
;
663 for (i
= 0; i
< count
; i
++) {
666 switch (r
->in
.inquiry_type
) {
667 case RPC_C_EP_ALL_ELTS
:
669 * Return all elements from the endpoint map. The
670 * interface_id, vers_option, and object parameters MUST
675 case RPC_C_EP_MATCH_BY_IF
:
677 * Return endpoint map elements that contain the
678 * interface identifier specified by the interface_id
679 * and vers_option values.
681 if (GUID_equal(&r
->in
.interface_id
->uuid
,
682 &eps
->e
[i
].syntax_id
.uuid
)) {
686 case RPC_C_EP_MATCH_BY_OBJ
:
688 * Return endpoint map elements that contain the object
689 * UUID specified by object.
691 if (GUID_equal(r
->in
.object
,
692 &eps
->e
[i
].syntax_id
.uuid
)) {
696 case RPC_C_EP_MATCH_BY_BOTH
:
698 * Return endpoint map elements that contain the
699 * interface identifier and object UUID specified by
700 * interface_id, vers_option, and object.
702 if (GUID_equal(&r
->in
.interface_id
->uuid
,
703 &eps
->e
[i
].syntax_id
.uuid
) &&
704 GUID_equal(r
->in
.object
, &eps
->e
[i
].syntax_id
.uuid
)) {
709 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
713 if (r
->in
.inquiry_type
== RPC_C_EP_MATCH_BY_IF
||
714 r
->in
.inquiry_type
== RPC_C_EP_MATCH_BY_OBJ
) {
715 /* Check inteface version */
718 switch (r
->in
.vers_option
) {
721 * Return endpoint map elements that
722 * contain the specified interface UUID,
723 * regardless of the version numbers.
727 case RPC_C_VERS_COMPATIBLE
:
729 * Return the endpoint map elements that
730 * contain the same major versions of
731 * the specified interface UUID and a
732 * minor version greater than or equal
733 * to the minor version of the specified
736 if (r
->in
.interface_id
->vers_major
==
737 (eps
->e
[i
].syntax_id
.if_version
>> 16) &&
738 r
->in
.interface_id
->vers_minor
<=
739 (eps
->e
[i
].syntax_id
.if_version
& 0xFFFF)) {
743 case RPC_C_VERS_EXACT
:
745 * Return endpoint map elements that
746 * contain the specified version of the
747 * specified interface UUID.
749 if (r
->in
.interface_id
->vers_major
==
750 (eps
->e
[i
].syntax_id
.if_version
>> 16) &&
751 r
->in
.interface_id
->vers_minor
==
752 (eps
->e
[i
].syntax_id
.if_version
& 0xFFFF)) {
757 case RPC_C_VERS_MAJOR_ONLY
:
759 * Return endpoint map elements that
760 * contain the same version of the
761 * specified interface UUID and ignore
764 if (r
->in
.interface_id
->vers_major
==
765 (eps
->e
[i
].syntax_id
.if_version
>> 16)) {
770 case RPC_C_VERS_UPTO
:
772 * Return endpoint map elements that
773 * contain a version of the specified
774 * interface UUID less than or equal to
775 * the specified major and minor
778 if (r
->in
.interface_id
->vers_major
>
779 eps
->e
[i
].syntax_id
.if_version
>> 16) {
782 if (r
->in
.interface_id
->vers_major
==
783 (eps
->e
[i
].syntax_id
.if_version
>> 16) &&
784 r
->in
.interface_id
->vers_minor
>=
785 (eps
->e
[i
].syntax_id
.if_version
& 0xFFFF)) {
791 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
797 ZERO_STRUCT(r
->out
.entries
[num_ents
].object
);
799 DEBUG(10, ("_epm_Lookup: Adding tower for '%s'\n",
801 r
->out
.entries
[num_ents
].annotation
= talloc_strdup(r
->out
.entries
,
803 r
->out
.entries
[num_ents
].tower
= talloc(r
->out
.entries
,
805 if (r
->out
.entries
[num_ents
].tower
== NULL
) {
806 rc
= EPMAPPER_STATUS_NO_MEMORY
;
809 r
->out
.entries
[num_ents
].tower
->tower
.floors
= talloc_move(r
->out
.entries
[num_ents
].tower
, &eps
->e
[i
].ep
.floors
);
810 r
->out
.entries
[num_ents
].tower
->tower
.num_floors
= eps
->e
[i
].ep
.num_floors
;
811 r
->out
.entries
[num_ents
].tower
->tower_length
= 0;
817 *r
->out
.num_ents
= num_ents
;
821 if (eps
->count
== 0) {
822 close_policy_hnd(p
, entry_handle
);
823 ZERO_STRUCTP(r
->out
.entry_handle
);
824 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
828 rc
= EPMAPPER_STATUS_OK
;
830 talloc_free(tmp_ctx
);
838 * Apply some algorithm (using the fields in the map_tower) to an endpoint map
839 * to produce a list of protocol towers.
841 error_status_t
_epm_Map(struct pipes_struct
*p
,
844 struct policy_handle
*entry_handle
;
845 enum dcerpc_transport_t transport
;
846 struct ndr_syntax_id ifid
;
847 struct epm_floor
*floors
;
852 uint32_t num_towers
= 0;
856 *r
->out
.num_towers
= 0;
857 r
->out
.towers
= NULL
;
859 if (r
->in
.map_tower
== NULL
|| r
->in
.max_towers
== 0 ||
860 r
->in
.map_tower
->tower
.num_floors
< 3) {
861 return EPMAPPER_STATUS_NO_MORE_ENTRIES
;
864 tmp_ctx
= talloc_stackframe();
865 if (tmp_ctx
== NULL
) {
866 return EPMAPPER_STATUS_NO_MEMORY
;
869 ZERO_STRUCTP(r
->out
.entry_handle
);
871 DEBUG(5, ("_epm_Map: Trying to map max. %u towers.\n",
875 * A tower has normally up to 6 floors
877 * +-----------------------------------------------------------------+
878 * | Floor 1 | Provides the RPC interface identifier. (e.g. UUID for |
880 * +---------+-------------------------------------------------------+
881 * | Floor 2 | Transfer syntax (NDR endcoded) |
882 * +---------+-------------------------------------------------------+
883 * | Floor 3 | RPC protocol identifier (ncacn_tcp_ip, ncacn_np, ...) |
884 * +---------+-------------------------------------------------------+
885 * | Floor 4 | Port address (e.g. TCP Port: 49156) |
886 * +---------+-------------------------------------------------------+
887 * | Floor 5 | Transport (e.g. IP:192.168.51.10) |
888 * +---------+-------------------------------------------------------+
889 * | Floor 6 | Routing |
890 * +---------+-------------------------------------------------------+
892 floors
= r
->in
.map_tower
->tower
.floors
;
894 /* We accept NDR as the transfer syntax */
895 dcerpc_floor_get_lhs_data(&floors
[1], &ifid
);
897 if (floors
[1].lhs
.protocol
!= EPM_PROTOCOL_UUID
||
898 !GUID_equal(&ifid
.uuid
, &ndr_transfer_syntax_ndr
.uuid
) ||
899 ifid
.if_version
!= ndr_transfer_syntax_ndr
.if_version
) {
900 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
904 /* We only talk to sane transports */
905 transport
= dcerpc_transport_by_tower(&r
->in
.map_tower
->tower
);
906 if (transport
== NCA_UNKNOWN
) {
907 DEBUG(2, ("epm_Map: Client requested unknown transport with"
909 for (i
= 2; i
< r
->in
.map_tower
->tower
.num_floors
; i
++) {
910 DEBUG(2, ("%d, ", r
->in
.map_tower
->tower
.floors
[i
].lhs
.protocol
));
913 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
917 if (r
->in
.entry_handle
== NULL
||
918 ndr_policy_handle_empty(r
->in
.entry_handle
)) {
920 char *srv_addr
= NULL
;
922 DEBUG(7, ("_epm_Map: No entry_handle found, creating it.\n"));
924 eps
= talloc_zero(tmp_ctx
, struct rpc_eps
);
926 rc
= EPMAPPER_STATUS_NO_MEMORY
;
935 * Apply some algorithm (using the fields in the map_tower)
936 * to an endpoint map to produce a list of protocol towers.
938 * The following code is the mysterious "some algorithm"!
941 /* Filter by object id if one was given. */
942 if (r
->in
.object
== NULL
|| GUID_all_zero(r
->in
.object
)) {
948 if (p
->local_address
!= NULL
) {
949 srv_addr
= tsocket_address_inet_addr_string(p
->local_address
,
953 eps
->count
= build_ep_list(eps
,
958 if (eps
->count
== 0) {
959 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
963 /* Filter out endpoints which match the interface. */
965 struct rpc_eps
*teps
;
968 teps
= talloc_zero(tmp_ctx
, struct rpc_eps
);
970 rc
= EPMAPPER_STATUS_NO_MEMORY
;
974 for (i
= 0; i
< eps
->count
; i
++) {
975 if (data_blob_cmp(&r
->in
.map_tower
->tower
.floors
[0].lhs
.lhs_data
,
976 &eps
->e
[i
].ep
.floors
[0].lhs
.lhs_data
) != 0 ||
977 transport
!= dcerpc_transport_by_tower(&eps
->e
[i
].ep
)) {
981 teps
->e
= talloc_realloc(tmp_ctx
,
983 struct dcesrv_ep_iface
,
985 if (teps
->e
== NULL
) {
989 teps
->e
[total
].ep
.floors
= talloc_move(teps
, &eps
->e
[i
].ep
.floors
);
990 teps
->e
[total
].ep
.num_floors
= eps
->e
[i
].ep
.num_floors
;
991 teps
->e
[total
].name
= talloc_move(teps
, &eps
->e
[i
].name
);
992 teps
->e
[total
].syntax_id
= eps
->e
[i
].syntax_id
;
1001 /* end of "some algorithm" */
1003 ok
= create_policy_hnd(p
, r
->out
.entry_handle
, eps
);
1005 rc
= EPMAPPER_STATUS_NO_MEMORY
;
1009 ok
= find_policy_by_hnd(p
, r
->out
.entry_handle
, (void **)(void*) &eps
);
1011 rc
= EPMAPPER_STATUS_NO_MEMORY
;
1014 entry_handle
= r
->out
.entry_handle
;
1016 DEBUG(7, ("_epm_Map: Trying to find entry_handle.\n"));
1018 ok
= find_policy_by_hnd(p
, r
->in
.entry_handle
, (void **)(void*) &eps
);
1020 rc
= EPMAPPER_STATUS_NO_MEMORY
;
1023 entry_handle
= r
->in
.entry_handle
;
1026 if (eps
== NULL
|| eps
->e
== NULL
) {
1027 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
1031 /* return the next N elements */
1032 count
= r
->in
.max_towers
;
1033 if (count
> eps
->count
) {
1038 close_policy_hnd(p
, entry_handle
);
1039 ZERO_STRUCTP(r
->out
.entry_handle
);
1041 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
1045 r
->out
.towers
= talloc_array(p
->mem_ctx
, struct epm_twr_p_t
, count
);
1046 if (r
->out
.towers
== NULL
) {
1047 rc
= EPMAPPER_STATUS_NO_MEMORY
;
1051 for (i
= 0; i
< count
; i
++) {
1052 DEBUG(7, ("_epm_Map: Map tower for '%s'\n",
1055 r
->out
.towers
[num_towers
].twr
= talloc(r
->out
.towers
,
1057 if (r
->out
.towers
[num_towers
].twr
== NULL
) {
1058 rc
= EPMAPPER_STATUS_NO_MEMORY
;
1061 r
->out
.towers
[num_towers
].twr
->tower
.floors
= talloc_move(r
->out
.towers
[num_towers
].twr
, &eps
->e
[i
].ep
.floors
);
1062 r
->out
.towers
[num_towers
].twr
->tower
.num_floors
= eps
->e
[i
].ep
.num_floors
;
1063 r
->out
.towers
[num_towers
].twr
->tower_length
= 0;
1068 *r
->out
.num_towers
= num_towers
;
1070 eps
->count
-= count
;
1072 if (eps
->count
== 0) {
1073 close_policy_hnd(p
, entry_handle
);
1074 ZERO_STRUCTP(r
->out
.entry_handle
);
1077 rc
= EPMAPPER_STATUS_OK
;
1079 talloc_free(tmp_ctx
);
1085 * epm_LookupHandleFree
1087 error_status_t
_epm_LookupHandleFree(struct pipes_struct
*p
,
1088 struct epm_LookupHandleFree
*r
)
1090 if (r
->in
.entry_handle
== NULL
) {
1091 return EPMAPPER_STATUS_OK
;
1094 if (is_valid_policy_hnd(r
->in
.entry_handle
)) {
1095 close_policy_hnd(p
, r
->in
.entry_handle
);
1098 r
->out
.entry_handle
= r
->in
.entry_handle
;
1100 return EPMAPPER_STATUS_OK
;
1107 * A client implementation SHOULD NOT call this method. These extensions do not
1108 * provide an alternative method.
1110 error_status_t
_epm_InqObject(struct pipes_struct
*p
,
1111 struct epm_InqObject
*r
)
1113 p
->rng_fault_state
= true;
1114 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
1121 * A client implementation SHOULD NOT call this method. These extensions do not
1122 * provide an alternative method.
1124 error_status_t
_epm_MgmtDelete(struct pipes_struct
*p
,
1125 struct epm_MgmtDelete
*r
)
1127 p
->rng_fault_state
= true;
1128 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
1135 error_status_t
_epm_MapAuth(struct pipes_struct
*p
,
1136 struct epm_MapAuth
*r
)
1138 p
->rng_fault_state
= true;
1139 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
1142 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */