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
)) {
106 * See if a uuid and if_version match to an interface
108 static bool interface_match_by_uuid(const struct dcesrv_iface
*iface
,
109 const struct GUID
*uuid
)
111 return GUID_equal(&iface
->syntax_id
.uuid
, uuid
);
115 static struct dcesrv_iface_list
*find_interface_list(const struct dcesrv_endpoint
*endpoint
,
116 const struct dcesrv_iface
*iface
)
118 struct dcesrv_iface_list
*iflist
;
120 for (iflist
= endpoint
->iface_list
; iflist
; iflist
= iflist
->next
) {
121 if (interface_match(iflist
->iface
, iface
)) {
130 * Check if two endpoints match.
132 static bool endpoints_match(const struct dcerpc_binding
*b1
,
133 const struct dcerpc_binding
*b2
)
135 enum dcerpc_transport_t t1
;
138 enum dcerpc_transport_t t2
;
142 t1
= dcerpc_binding_get_transport(b1
);
143 ep1
= dcerpc_binding_get_string_option(b1
, "endpoint");
144 h1
= dcerpc_binding_get_string_option(b1
, "host");
146 t2
= dcerpc_binding_get_transport(b2
);
147 ep2
= dcerpc_binding_get_string_option(b2
, "endpoint");
148 h2
= dcerpc_binding_get_string_option(b2
, "host");
163 if (!strequal(ep1
, ep2
)) {
177 if (!strequal(h1
, h2
)) {
185 static struct dcesrv_endpoint
*find_endpoint(struct dcesrv_endpoint
*endpoint_list
,
186 struct dcerpc_binding
*ep_description
) {
187 struct dcesrv_endpoint
*ep
;
189 for (ep
= endpoint_list
; ep
!= NULL
; ep
= ep
->next
) {
190 if (endpoints_match(ep
->ep_description
, ep_description
)) {
199 * Build a list of all interfaces handled by all endpoint servers.
201 static uint32_t build_ep_list(TALLOC_CTX
*mem_ctx
,
202 struct dcesrv_endpoint
*endpoint_list
,
203 const struct GUID
*uuid
,
204 const char *srv_addr
,
205 struct dcesrv_ep_iface
**peps
)
207 struct dcesrv_ep_iface
*eps
= NULL
;
208 struct dcesrv_endpoint
*d
;
214 for (d
= endpoint_list
; d
!= NULL
; d
= d
->next
) {
215 struct dcesrv_iface_list
*iface
;
216 struct dcerpc_binding
*description
;
218 for (iface
= d
->iface_list
; iface
!= NULL
; iface
= iface
->next
) {
219 enum dcerpc_transport_t transport
;
220 const char *host
= NULL
;
221 const char *host_addr
= NULL
;
225 * Windows ignores the object uuid by default. There is
226 * one corner case. It is checked for the mgmt
227 * interface, which we do not implement here yet.
229 if (uuid
&& !interface_match_by_uuid(iface
->iface
, uuid
)) {
234 eps
= talloc_realloc(mem_ctx
,
236 struct dcesrv_ep_iface
,
241 eps
[total
].name
= talloc_strdup(eps
,
243 if (eps
[total
].name
== NULL
) {
246 eps
[total
].syntax_id
= iface
->iface
->syntax_id
;
248 description
= dcerpc_binding_dup(mem_ctx
, d
->ep_description
);
249 if (description
== NULL
) {
253 status
= dcerpc_binding_set_abstract_syntax(description
,
254 &iface
->iface
->syntax_id
);
255 if (!NT_STATUS_IS_OK(status
)) {
259 transport
= dcerpc_binding_get_transport(description
);
260 host
= dcerpc_binding_get_string_option(description
, "host");
262 if (transport
== NCACN_IP_TCP
) {
264 host_addr
= srv_addr
;
265 } else if (!is_ipaddress_v4(host
)) {
266 host_addr
= srv_addr
;
267 } else if (strcmp(host
, "0.0.0.0") == 0) {
268 host_addr
= srv_addr
;
272 if (host_addr
!= NULL
) {
273 status
= dcerpc_binding_set_string_option(description
,
276 if (!NT_STATUS_IS_OK(status
)) {
281 status
= dcerpc_binding_build_tower(eps
,
284 TALLOC_FREE(description
);
285 if (NT_STATUS_IS_ERR(status
)) {
286 DEBUG(1, ("Unable to build tower for %s\n",
287 iface
->iface
->name
));
299 static bool is_privileged_pipe(struct auth_session_info
*info
) {
300 /* If the user is not root, or has the system token, fail */
301 if ((info
->unix_token
->uid
!= sec_initial_uid()) &&
302 !security_token_is_system(info
->security_token
)) {
309 bool srv_epmapper_delete_endpoints(struct pipes_struct
*p
)
312 struct dcesrv_ep_entry_list
*el
= p
->ep_entries
;
313 error_status_t result
;
316 struct dcesrv_ep_entry_list
*next
= el
->next
;
318 r
.in
.num_ents
= el
->num_ents
;
319 r
.in
.entries
= el
->entries
;
321 DEBUG(10, ("Delete_endpoints for: %s\n",
322 el
->entries
[0].annotation
));
324 result
= _epm_Delete(p
, &r
);
325 if (result
!= EPMAPPER_STATUS_OK
) {
329 DLIST_REMOVE(p
->ep_entries
, el
);
338 void srv_epmapper_cleanup(void)
340 struct dcesrv_endpoint
*ep
= endpoint_table
;
343 struct dcesrv_endpoint
*next
= ep
->next
;
345 DLIST_REMOVE(endpoint_table
, ep
);
355 * Add the specified entries to an endpoint map.
357 error_status_t
_epm_Insert(struct pipes_struct
*p
,
358 struct epm_Insert
*r
)
364 struct dcerpc_binding
*b
;
365 struct dcesrv_endpoint
*ep
;
366 struct dcesrv_iface_list
*iflist
;
367 struct dcesrv_iface
*iface
;
370 /* If this is not a privileged users, return */
371 if (p
->transport
!= NCALRPC
||
372 !is_privileged_pipe(p
->session_info
)) {
373 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
374 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
377 tmp_ctx
= talloc_stackframe();
378 if (tmp_ctx
== NULL
) {
379 return EPMAPPER_STATUS_NO_MEMORY
;
382 DEBUG(3, ("_epm_Insert: Trying to add %u new entries.\n",
385 for (i
= 0; i
< r
->in
.num_ents
; i
++) {
386 enum dcerpc_transport_t transport
;
390 status
= dcerpc_binding_from_tower(tmp_ctx
,
391 &r
->in
.entries
[i
].tower
->tower
,
393 if (NT_STATUS_EQUAL(status
, NT_STATUS_NO_MEMORY
)) {
394 rc
= EPMAPPER_STATUS_NO_MEMORY
;
397 if (!NT_STATUS_IS_OK(status
)) {
398 rc
= EPMAPPER_STATUS_CANT_PERFORM_OP
;
402 transport
= dcerpc_binding_get_transport(b
);
403 DEBUG(3, ("_epm_Insert: Adding transport %s for %s\n",
404 derpc_transport_string_by_transport(transport
),
405 r
->in
.entries
[i
].annotation
));
407 /* Check if the entry already exits */
408 ep
= find_endpoint(endpoint_table
, b
);
410 /* No entry found, create it */
411 ep
= talloc_zero(NULL
, struct dcesrv_endpoint
);
413 rc
= EPMAPPER_STATUS_NO_MEMORY
;
418 ep
->ep_description
= talloc_steal(ep
, b
);
421 /* TODO Replace the entry if the replace flag is set */
423 /* Create an interface */
424 iface
= talloc(tmp_ctx
, struct dcesrv_iface
);
426 rc
= EPMAPPER_STATUS_NO_MEMORY
;
430 iface
->name
= talloc_strdup(iface
, r
->in
.entries
[i
].annotation
);
431 if (iface
->name
== NULL
) {
432 rc
= EPMAPPER_STATUS_NO_MEMORY
;
435 iface
->syntax_id
= dcerpc_binding_get_abstract_syntax(b
);
438 * Check if the rpc service is alrady registered on the
441 if (find_interface(ep
, iface
) != NULL
) {
442 DEBUG(8, ("dcesrv_interface_register: interface '%s' "
443 "already registered on endpoint\n",
445 /* FIXME wrong error code? */
446 rc
= EPMAPPER_STATUS_OK
;
450 /* Create an entry for the interface */
451 iflist
= talloc(ep
, struct dcesrv_iface_list
);
452 if (iflist
== NULL
) {
453 rc
= EPMAPPER_STATUS_NO_MEMORY
;
456 iflist
->iface
= talloc_move(iflist
, &iface
);
458 /* Finally add the interface on the endpoint */
459 DLIST_ADD(ep
->iface_list
, iflist
);
461 /* If it's a new endpoint add it to the endpoint_table */
463 DLIST_ADD(endpoint_table
, ep
);
467 if (r
->in
.num_ents
> 0) {
468 struct dcesrv_ep_entry_list
*el
;
470 el
= talloc_zero(p
, struct dcesrv_ep_entry_list
);
472 rc
= EPMAPPER_STATUS_NO_MEMORY
;
475 el
->num_ents
= r
->in
.num_ents
;
476 el
->entries
= talloc_move(el
, &r
->in
.entries
);
478 DLIST_ADD(p
->ep_entries
, el
);
481 rc
= EPMAPPER_STATUS_OK
;
483 talloc_free(tmp_ctx
);
492 * Delete the specified entries from an endpoint map.
494 error_status_t
_epm_Delete(struct pipes_struct
*p
,
495 struct epm_Delete
*r
)
501 struct dcerpc_binding
*b
;
502 struct dcesrv_endpoint
*ep
;
503 struct dcesrv_iface iface
;
504 struct dcesrv_iface_list
*iflist
;
506 DEBUG(3, ("_epm_Delete: Trying to delete %u entries.\n",
509 /* If this is not a privileged users, return */
510 if (p
->transport
!= NCALRPC
||
511 !is_privileged_pipe(p
->session_info
)) {
512 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
513 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
516 tmp_ctx
= talloc_stackframe();
517 if (tmp_ctx
== NULL
) {
518 return EPMAPPER_STATUS_NO_MEMORY
;
521 for (i
= 0; i
< r
->in
.num_ents
; i
++) {
522 enum dcerpc_transport_t transport
;
526 status
= dcerpc_binding_from_tower(tmp_ctx
,
527 &r
->in
.entries
[i
].tower
->tower
,
529 if (!NT_STATUS_IS_OK(status
)) {
530 rc
= EPMAPPER_STATUS_NO_MEMORY
;
534 transport
= dcerpc_binding_get_transport(b
);
535 DEBUG(3, ("_epm_Delete: Deleting transport '%s' for '%s'\n",
536 derpc_transport_string_by_transport(transport
),
537 r
->in
.entries
[i
].annotation
));
539 ep
= find_endpoint(endpoint_table
, b
);
541 rc
= EPMAPPER_STATUS_OK
;
545 iface
.name
= r
->in
.entries
[i
].annotation
;
546 iface
.syntax_id
= dcerpc_binding_get_abstract_syntax(b
);
548 iflist
= find_interface_list(ep
, &iface
);
549 if (iflist
== NULL
) {
550 DEBUG(0, ("_epm_Delete: No interfaces left, delete endpoint\n"));
551 DLIST_REMOVE(endpoint_table
, ep
);
554 rc
= EPMAPPER_STATUS_OK
;
558 DLIST_REMOVE(ep
->iface_list
, iflist
);
560 if (ep
->iface_list
== NULL
) {
561 DEBUG(0, ("_epm_Delete: No interfaces left, delete endpoint\n"));
562 DLIST_REMOVE(endpoint_table
, ep
);
565 rc
= EPMAPPER_STATUS_OK
;
571 rc
= EPMAPPER_STATUS_OK
;
573 talloc_free(tmp_ctx
);
582 * Lookup entries in an endpoint map.
584 error_status_t
_epm_Lookup(struct pipes_struct
*p
,
585 struct epm_Lookup
*r
)
587 struct policy_handle
*entry_handle
;
592 uint32_t num_ents
= 0;
597 *r
->out
.num_ents
= 0;
598 r
->out
.entries
= NULL
;
600 tmp_ctx
= talloc_stackframe();
601 if (tmp_ctx
== NULL
) {
602 return EPMAPPER_STATUS_NO_MEMORY
;
605 DEBUG(5, ("_epm_Lookup: Trying to lookup max. %u entries.\n",
608 if (r
->in
.entry_handle
== NULL
||
609 ndr_policy_handle_empty(r
->in
.entry_handle
)) {
610 char *srv_addr
= NULL
;
612 DEBUG(7, ("_epm_Lookup: No entry_handle found, creating it.\n"));
614 eps
= talloc_zero(tmp_ctx
, struct rpc_eps
);
616 rc
= EPMAPPER_STATUS_NO_MEMORY
;
620 if (p
->local_address
!= NULL
&&
621 tsocket_address_is_inet(p
->local_address
, "ipv4"))
623 srv_addr
= tsocket_address_inet_addr_string(p
->local_address
,
627 switch (r
->in
.inquiry_type
) {
628 case RPC_C_EP_ALL_ELTS
:
630 * Return all elements from the endpoint map. The
631 * interface_id, vers_option, and object parameters MUST
634 eps
->count
= build_ep_list(eps
,
640 case RPC_C_EP_MATCH_BY_IF
:
642 * Return endpoint map elements that contain the
643 * interface identifier specified by the interface_id
644 * and vers_option values.
646 * RPC_C_EP_MATCH_BY_IF and RPC_C_EP_MATCH_BY_BOTH
647 * need both the same endpoint list. There is a second
648 * check for the inquiry_type below which differentiates
651 case RPC_C_EP_MATCH_BY_BOTH
:
653 * Return endpoint map elements that contain the
654 * interface identifier and object UUID specified by
655 * interface_id, vers_option, and object.
657 eps
->count
= build_ep_list(eps
,
659 &r
->in
.interface_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 eps
->count
= build_ep_list(eps
,
675 rc
= EPMAPPER_STATUS_CANT_PERFORM_OP
;
679 if (eps
->count
== 0) {
680 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
684 ok
= create_policy_hnd(p
, r
->out
.entry_handle
, eps
);
686 rc
= EPMAPPER_STATUS_NO_MEMORY
;
690 ok
= find_policy_by_hnd(p
, r
->out
.entry_handle
, (void **)(void*) &eps
);
692 rc
= EPMAPPER_STATUS_NO_MEMORY
;
695 entry_handle
= r
->out
.entry_handle
;
697 DEBUG(7, ("_epm_Lookup: Trying to find entry_handle.\n"));
699 ok
= find_policy_by_hnd(p
, r
->in
.entry_handle
, (void **)(void*) &eps
);
701 rc
= EPMAPPER_STATUS_NO_MEMORY
;
704 entry_handle
= r
->in
.entry_handle
;
707 if (eps
== NULL
|| eps
->e
== NULL
) {
708 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
712 /* return the next N elements */
713 count
= r
->in
.max_ents
;
714 if (count
> eps
->count
) {
718 DEBUG(5, ("_epm_Lookup: Find %u entries\n", count
));
721 close_policy_hnd(p
, entry_handle
);
722 ZERO_STRUCTP(r
->out
.entry_handle
);
724 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
728 r
->out
.entries
= talloc_array(p
->mem_ctx
, struct epm_entry_t
, count
);
729 if (r
->out
.entries
== NULL
) {
730 rc
= EPMAPPER_STATUS_NO_MEMORY
;
734 for (i
= 0; i
< count
; i
++) {
737 switch (r
->in
.inquiry_type
) {
738 case RPC_C_EP_ALL_ELTS
:
740 * Return all elements from the endpoint map. The
741 * interface_id, vers_option, and object parameters MUST
746 case RPC_C_EP_MATCH_BY_IF
:
748 * Return endpoint map elements that contain the
749 * interface identifier specified by the interface_id
750 * and vers_option values.
752 if (GUID_equal(&r
->in
.interface_id
->uuid
,
753 &eps
->e
[i
].syntax_id
.uuid
)) {
757 case RPC_C_EP_MATCH_BY_OBJ
:
759 * Return endpoint map elements that contain the object
760 * UUID specified by object.
762 if (GUID_equal(r
->in
.object
,
763 &eps
->e
[i
].syntax_id
.uuid
)) {
767 case RPC_C_EP_MATCH_BY_BOTH
:
769 * Return endpoint map elements that contain the
770 * interface identifier and object UUID specified by
771 * interface_id, vers_option, and object.
773 if (GUID_equal(&r
->in
.interface_id
->uuid
,
774 &eps
->e
[i
].syntax_id
.uuid
) &&
775 GUID_equal(r
->in
.object
, &eps
->e
[i
].syntax_id
.uuid
)) {
780 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
784 if (r
->in
.inquiry_type
== RPC_C_EP_MATCH_BY_IF
||
785 r
->in
.inquiry_type
== RPC_C_EP_MATCH_BY_OBJ
) {
786 /* Check interface version */
789 switch (r
->in
.vers_option
) {
792 * Return endpoint map elements that
793 * contain the specified interface UUID,
794 * regardless of the version numbers.
798 case RPC_C_VERS_COMPATIBLE
:
800 * Return the endpoint map elements that
801 * contain the same major versions of
802 * the specified interface UUID and a
803 * minor version greater than or equal
804 * to the minor version of the specified
807 if (r
->in
.interface_id
->vers_major
==
808 (eps
->e
[i
].syntax_id
.if_version
>> 16) &&
809 r
->in
.interface_id
->vers_minor
<=
810 (eps
->e
[i
].syntax_id
.if_version
& 0xFFFF)) {
814 case RPC_C_VERS_EXACT
:
816 * Return endpoint map elements that
817 * contain the specified version of the
818 * specified interface UUID.
820 if (r
->in
.interface_id
->vers_major
==
821 (eps
->e
[i
].syntax_id
.if_version
>> 16) &&
822 r
->in
.interface_id
->vers_minor
==
823 (eps
->e
[i
].syntax_id
.if_version
& 0xFFFF)) {
828 case RPC_C_VERS_MAJOR_ONLY
:
830 * Return endpoint map elements that
831 * contain the same version of the
832 * specified interface UUID and ignore
835 if (r
->in
.interface_id
->vers_major
==
836 (eps
->e
[i
].syntax_id
.if_version
>> 16)) {
841 case RPC_C_VERS_UPTO
:
843 * Return endpoint map elements that
844 * contain a version of the specified
845 * interface UUID less than or equal to
846 * the specified major and minor
849 if (r
->in
.interface_id
->vers_major
>
850 eps
->e
[i
].syntax_id
.if_version
>> 16) {
853 if (r
->in
.interface_id
->vers_major
==
854 (eps
->e
[i
].syntax_id
.if_version
>> 16) &&
855 r
->in
.interface_id
->vers_minor
>=
856 (eps
->e
[i
].syntax_id
.if_version
& 0xFFFF)) {
862 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
868 ZERO_STRUCT(r
->out
.entries
[num_ents
].object
);
870 DEBUG(10, ("_epm_Lookup: Adding tower for '%s'\n",
872 r
->out
.entries
[num_ents
].annotation
= talloc_strdup(r
->out
.entries
,
874 r
->out
.entries
[num_ents
].tower
= talloc(r
->out
.entries
,
876 if (r
->out
.entries
[num_ents
].tower
== NULL
) {
877 rc
= EPMAPPER_STATUS_NO_MEMORY
;
880 r
->out
.entries
[num_ents
].tower
->tower
.floors
= talloc_move(r
->out
.entries
[num_ents
].tower
, &eps
->e
[i
].ep
.floors
);
881 r
->out
.entries
[num_ents
].tower
->tower
.num_floors
= eps
->e
[i
].ep
.num_floors
;
882 r
->out
.entries
[num_ents
].tower
->tower_length
= 0;
888 *r
->out
.num_ents
= num_ents
;
892 if (eps
->count
== 0) {
893 close_policy_hnd(p
, entry_handle
);
894 ZERO_STRUCTP(r
->out
.entry_handle
);
895 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
899 rc
= EPMAPPER_STATUS_OK
;
901 talloc_free(tmp_ctx
);
909 * Apply some algorithm (using the fields in the map_tower) to an endpoint map
910 * to produce a list of protocol towers.
912 error_status_t
_epm_Map(struct pipes_struct
*p
,
915 struct policy_handle
*entry_handle
;
916 enum dcerpc_transport_t transport
;
917 struct ndr_syntax_id ifid
;
918 struct epm_floor
*floors
;
923 uint32_t num_towers
= 0;
927 *r
->out
.num_towers
= 0;
928 r
->out
.towers
= NULL
;
930 if (r
->in
.map_tower
== NULL
|| r
->in
.max_towers
== 0 ||
931 r
->in
.map_tower
->tower
.num_floors
< 3) {
932 return EPMAPPER_STATUS_NO_MORE_ENTRIES
;
935 tmp_ctx
= talloc_stackframe();
936 if (tmp_ctx
== NULL
) {
937 return EPMAPPER_STATUS_NO_MEMORY
;
940 ZERO_STRUCTP(r
->out
.entry_handle
);
942 DEBUG(5, ("_epm_Map: Trying to map max. %u towers.\n",
946 * A tower has normally up to 6 floors
948 * +-----------------------------------------------------------------+
949 * | Floor 1 | Provides the RPC interface identifier. (e.g. UUID for |
951 * +---------+-------------------------------------------------------+
952 * | Floor 2 | Transfer syntax (NDR endcoded) |
953 * +---------+-------------------------------------------------------+
954 * | Floor 3 | RPC protocol identifier (ncacn_tcp_ip, ncacn_np, ...) |
955 * +---------+-------------------------------------------------------+
956 * | Floor 4 | Port address (e.g. TCP Port: 49156) |
957 * +---------+-------------------------------------------------------+
958 * | Floor 5 | Transport (e.g. IP:192.168.51.10) |
959 * +---------+-------------------------------------------------------+
960 * | Floor 6 | Routing |
961 * +---------+-------------------------------------------------------+
963 floors
= r
->in
.map_tower
->tower
.floors
;
965 /* We accept NDR as the transfer syntax */
966 dcerpc_floor_get_lhs_data(&floors
[1], &ifid
);
968 if (floors
[1].lhs
.protocol
!= EPM_PROTOCOL_UUID
||
969 !GUID_equal(&ifid
.uuid
, &ndr_transfer_syntax_ndr
.uuid
) ||
970 ifid
.if_version
!= ndr_transfer_syntax_ndr
.if_version
) {
971 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
975 /* We only talk to sane transports */
976 transport
= dcerpc_transport_by_tower(&r
->in
.map_tower
->tower
);
977 if (transport
== NCA_UNKNOWN
) {
978 DEBUG(2, ("epm_Map: Client requested unknown transport with"
980 for (i
= 2; i
< r
->in
.map_tower
->tower
.num_floors
; i
++) {
981 DEBUG(2, ("%d, ", r
->in
.map_tower
->tower
.floors
[i
].lhs
.protocol
));
984 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
988 if (r
->in
.entry_handle
== NULL
||
989 ndr_policy_handle_empty(r
->in
.entry_handle
)) {
991 char *srv_addr
= NULL
;
993 DEBUG(7, ("_epm_Map: No entry_handle found, creating it.\n"));
995 eps
= talloc_zero(tmp_ctx
, struct rpc_eps
);
997 rc
= EPMAPPER_STATUS_NO_MEMORY
;
1006 * Apply some algorithm (using the fields in the map_tower)
1007 * to an endpoint map to produce a list of protocol towers.
1009 * The following code is the mysterious "some algorithm"!
1012 /* Filter by object id if one was given. */
1013 if (r
->in
.object
== NULL
|| GUID_all_zero(r
->in
.object
)) {
1019 if (p
->local_address
!= NULL
&&
1020 tsocket_address_is_inet(p
->local_address
, "ipv4"))
1022 srv_addr
= tsocket_address_inet_addr_string(p
->local_address
,
1026 eps
->count
= build_ep_list(eps
,
1031 if (eps
->count
== 0) {
1032 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
1036 /* Filter out endpoints which match the interface. */
1038 struct rpc_eps
*teps
;
1041 teps
= talloc_zero(tmp_ctx
, struct rpc_eps
);
1043 rc
= EPMAPPER_STATUS_NO_MEMORY
;
1047 for (i
= 0; i
< eps
->count
; i
++) {
1048 if (data_blob_cmp(&r
->in
.map_tower
->tower
.floors
[0].lhs
.lhs_data
,
1049 &eps
->e
[i
].ep
.floors
[0].lhs
.lhs_data
) != 0 ||
1050 transport
!= dcerpc_transport_by_tower(&eps
->e
[i
].ep
)) {
1054 teps
->e
= talloc_realloc(tmp_ctx
,
1056 struct dcesrv_ep_iface
,
1058 if (teps
->e
== NULL
) {
1062 teps
->e
[total
].ep
.floors
= talloc_move(teps
, &eps
->e
[i
].ep
.floors
);
1063 teps
->e
[total
].ep
.num_floors
= eps
->e
[i
].ep
.num_floors
;
1064 teps
->e
[total
].name
= talloc_move(teps
, &eps
->e
[i
].name
);
1065 teps
->e
[total
].syntax_id
= eps
->e
[i
].syntax_id
;
1070 teps
->count
= total
;
1074 /* end of "some algorithm" */
1076 ok
= create_policy_hnd(p
, r
->out
.entry_handle
, eps
);
1078 rc
= EPMAPPER_STATUS_NO_MEMORY
;
1082 ok
= find_policy_by_hnd(p
, r
->out
.entry_handle
, (void **)(void*) &eps
);
1084 rc
= EPMAPPER_STATUS_NO_MEMORY
;
1087 entry_handle
= r
->out
.entry_handle
;
1089 DEBUG(7, ("_epm_Map: Trying to find entry_handle.\n"));
1091 ok
= find_policy_by_hnd(p
, r
->in
.entry_handle
, (void **)(void*) &eps
);
1093 rc
= EPMAPPER_STATUS_NO_MEMORY
;
1096 entry_handle
= r
->in
.entry_handle
;
1099 if (eps
== NULL
|| eps
->e
== NULL
) {
1100 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
1104 /* return the next N elements */
1105 count
= r
->in
.max_towers
;
1106 if (count
> eps
->count
) {
1111 close_policy_hnd(p
, entry_handle
);
1112 ZERO_STRUCTP(r
->out
.entry_handle
);
1114 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
1118 r
->out
.towers
= talloc_array(p
->mem_ctx
, struct epm_twr_p_t
, count
);
1119 if (r
->out
.towers
== NULL
) {
1120 rc
= EPMAPPER_STATUS_NO_MEMORY
;
1124 for (i
= 0; i
< count
; i
++) {
1125 DEBUG(7, ("_epm_Map: Map tower for '%s'\n",
1128 r
->out
.towers
[num_towers
].twr
= talloc(r
->out
.towers
,
1130 if (r
->out
.towers
[num_towers
].twr
== NULL
) {
1131 rc
= EPMAPPER_STATUS_NO_MEMORY
;
1134 r
->out
.towers
[num_towers
].twr
->tower
.floors
= talloc_move(r
->out
.towers
[num_towers
].twr
, &eps
->e
[i
].ep
.floors
);
1135 r
->out
.towers
[num_towers
].twr
->tower
.num_floors
= eps
->e
[i
].ep
.num_floors
;
1136 r
->out
.towers
[num_towers
].twr
->tower_length
= 0;
1141 *r
->out
.num_towers
= num_towers
;
1143 eps
->count
-= count
;
1145 if (eps
->count
== 0) {
1146 close_policy_hnd(p
, entry_handle
);
1147 ZERO_STRUCTP(r
->out
.entry_handle
);
1150 rc
= EPMAPPER_STATUS_OK
;
1152 talloc_free(tmp_ctx
);
1158 * epm_LookupHandleFree
1160 error_status_t
_epm_LookupHandleFree(struct pipes_struct
*p
,
1161 struct epm_LookupHandleFree
*r
)
1163 if (r
->in
.entry_handle
== NULL
) {
1164 return EPMAPPER_STATUS_OK
;
1167 if (is_valid_policy_hnd(r
->in
.entry_handle
)) {
1168 close_policy_hnd(p
, r
->in
.entry_handle
);
1171 r
->out
.entry_handle
= r
->in
.entry_handle
;
1173 return EPMAPPER_STATUS_OK
;
1180 * A client implementation SHOULD NOT call this method. These extensions do not
1181 * provide an alternative method.
1183 error_status_t
_epm_InqObject(struct pipes_struct
*p
,
1184 struct epm_InqObject
*r
)
1186 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1187 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
1194 * A client implementation SHOULD NOT call this method. These extensions do not
1195 * provide an alternative method.
1197 error_status_t
_epm_MgmtDelete(struct pipes_struct
*p
,
1198 struct epm_MgmtDelete
*r
)
1200 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1201 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
1208 error_status_t
_epm_MapAuth(struct pipes_struct
*p
,
1209 struct epm_MapAuth
*r
)
1211 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1212 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
1215 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */