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"
28 #include "librpc/rpc/dcesrv_core.h"
29 #include "librpc/gen_ndr/ndr_epmapper.h"
30 #include "librpc/gen_ndr/ndr_epmapper_scompat.h"
31 #include "rpc_server/rpc_server.h"
32 #include "lib/tdb_wrap/tdb_wrap.h"
33 #include "lib/util/util_tdb.h"
34 #include "lib/util/strv.h"
36 static struct tdb_wrap
*epmdb
= NULL
;
38 /* handle types for this module */
39 enum handle_types
{HTYPE_LOOKUP
};
41 typedef uint32_t error_status_t
;
43 /* An endpoint combined with an interface description */
44 struct dcesrv_ep_iface
{
46 struct ndr_syntax_id syntax_id
;
50 /* A rpc service interface like samr, lsarpc or netlogon */
53 struct ndr_syntax_id syntax_id
;
56 struct dcesrv_iface_list
{
57 struct dcesrv_iface_list
*next
, *prev
;
58 struct dcesrv_iface
*iface
;
62 * An endpoint can serve multiple rpc services interfaces.
63 * For example \\pipe\netlogon can be used by lsarpc and netlogon.
65 struct dcesrv_epm_endpoint
{
66 struct dcesrv_epm_endpoint
*next
, *prev
;
68 /* The type and the location of the endpoint */
69 struct dcerpc_binding
*ep_description
;
71 /* A list of rpc services able to connect to the endpoint */
72 struct dcesrv_iface_list
*iface_list
;
76 struct dcesrv_ep_iface
*e
;
80 struct build_ep_list_state
{
81 const struct GUID
*uuid
;
84 struct dcesrv_ep_iface
*ifaces
;
87 static bool build_ep_list_fill_iface(
89 const struct ndr_syntax_id
*syntax_id
,
93 struct dcesrv_ep_iface
*dst
)
95 struct dcesrv_ep_iface iface
= {
96 .syntax_id
= *syntax_id
,
98 struct dcerpc_binding
*binding
= NULL
;
99 enum dcerpc_transport_t transport
;
100 char *name_dup
= NULL
;
101 const char *host_addr
= NULL
;
104 /* copy without const for error path TALLOC_FREE */
105 name_dup
= talloc_strdup(mem_ctx
, name
);
106 if (name_dup
== NULL
) {
109 iface
.name
= name_dup
;
111 status
= dcerpc_parse_binding(mem_ctx
, endpoint
, &binding
);
112 if (!NT_STATUS_IS_OK(status
)) {
113 DBG_DEBUG("dcerpc_parse_binding failed: %s\n",
118 status
= dcerpc_binding_set_abstract_syntax(binding
, syntax_id
);
119 if (!NT_STATUS_IS_OK(status
)) {
120 DBG_DEBUG("dcerpc_binding_set_abstract_syntax failed: %s\n",
125 transport
= dcerpc_binding_get_transport(binding
);
126 if (transport
== NCACN_IP_TCP
) {
127 const char *host
= NULL
;
129 host
= dcerpc_binding_get_string_option(binding
, "host");
131 host_addr
= srv_addr
;
132 } else if (!is_ipaddress_v4(host
)) {
133 host_addr
= srv_addr
;
134 } else if (strcmp(host
, "0.0.0.0") == 0) {
135 host_addr
= srv_addr
;
139 if (host_addr
!= NULL
) {
140 status
= dcerpc_binding_set_string_option(
141 binding
, "host", host_addr
);
142 if (!NT_STATUS_IS_OK(status
)) {
143 DBG_DEBUG("dcerpc_binding_set_string_option "
150 status
= dcerpc_binding_build_tower(mem_ctx
, binding
, &iface
.ep
);
151 TALLOC_FREE(binding
);
152 if (!NT_STATUS_IS_OK(status
)) {
153 DBG_DEBUG("dcerpc_binding_build_tower failed: %s\n",
162 TALLOC_FREE(binding
);
163 TALLOC_FREE(name_dup
);
164 TALLOC_FREE(iface
.ep
.floors
);
168 static int build_ep_list_fn(
169 struct tdb_context
*tdb
,
174 struct build_ep_list_state
*state
= private_data
;
175 struct ndr_syntax_id syntax_id
= { .if_version
= 0 };
176 const char *name
= NULL
;
177 char *endpoints
= NULL
;
178 const char *endpoint
= NULL
;
181 if ((key
.dsize
== 0) || (key
.dptr
[key
.dsize
-1] != '\0') ||
182 (value
.dsize
== 0) || (value
.dptr
[value
.dsize
-1] != '\0')) {
183 DBG_DEBUG("Invalid record\n");
187 ok
= ndr_syntax_id_from_string((char *)key
.dptr
, &syntax_id
);
189 DBG_DEBUG("Invalid interface: %s\n", (char *)key
.dptr
);
193 endpoints
= (char *)value
.dptr
;
194 endpoint
= endpoints
;
197 while ((endpoint
= strv_len_next(endpoints
, value
.dsize
, endpoint
))) {
198 size_t num_ifaces
= talloc_array_length(state
->ifaces
);
199 struct dcesrv_ep_iface
*tmp
= NULL
;
201 if (num_ifaces
+1 < num_ifaces
) {
205 tmp
= talloc_realloc(
208 struct dcesrv_ep_iface
,
215 ok
= build_ep_list_fill_iface(
221 &state
->ifaces
[num_ifaces
]);
223 state
->ifaces
= talloc_realloc(
226 struct dcesrv_ep_iface
,
235 * Build a list of all interfaces handled by all endpoint servers.
237 static uint32_t build_ep_list(TALLOC_CTX
*mem_ctx
,
238 const struct GUID
*uuid
,
239 const char *srv_addr
,
240 struct dcesrv_ep_iface
**peps
)
242 struct build_ep_list_state state
= {
243 .mem_ctx
= mem_ctx
, .uuid
= uuid
, .srv_addr
= srv_addr
,
247 ret
= tdb_traverse_read(epmdb
->tdb
, build_ep_list_fn
, &state
);
249 DBG_DEBUG("tdb_traverse_read failed\n");
253 *peps
= state
.ifaces
;
254 return talloc_array_length(*peps
);
260 * Add the specified entries to an endpoint map.
262 error_status_t
_epm_Insert(struct pipes_struct
*p
,
263 struct epm_Insert
*r
)
265 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
266 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
272 * Delete the specified entries from an endpoint map.
274 error_status_t
_epm_Delete(struct pipes_struct
*p
,
275 struct epm_Delete
*r
)
277 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
278 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
284 * Lookup entries in an endpoint map.
286 error_status_t
_epm_Lookup(struct pipes_struct
*p
,
287 struct epm_Lookup
*r
)
289 struct dcesrv_call_state
*dce_call
= p
->dce_call
;
290 struct dcesrv_connection
*dcesrv_conn
= dce_call
->conn
;
291 struct policy_handle
*entry_handle
;
296 uint32_t num_ents
= 0;
302 *r
->out
.num_ents
= 0;
303 r
->out
.entries
= NULL
;
305 tmp_ctx
= talloc_stackframe();
306 if (tmp_ctx
== NULL
) {
307 return EPMAPPER_STATUS_NO_MEMORY
;
310 DEBUG(5, ("_epm_Lookup: Trying to lookup max. %u entries.\n",
313 if (r
->in
.entry_handle
== NULL
||
314 ndr_policy_handle_empty(r
->in
.entry_handle
)) {
315 const struct tsocket_address
*local_address
=
316 dcesrv_connection_get_local_address(dcesrv_conn
);
317 char *srv_addr
= NULL
;
319 DEBUG(7, ("_epm_Lookup: No entry_handle found, creating it.\n"));
321 eps
= talloc_zero(tmp_ctx
, struct rpc_eps
);
323 rc
= EPMAPPER_STATUS_NO_MEMORY
;
327 if (local_address
!= NULL
&&
328 tsocket_address_is_inet(local_address
, "ipv4"))
330 srv_addr
= tsocket_address_inet_addr_string(
331 local_address
, tmp_ctx
);
334 switch (r
->in
.inquiry_type
) {
335 case RPC_C_EP_ALL_ELTS
:
337 * Return all elements from the endpoint map. The
338 * interface_id, vers_option, and object parameters MUST
341 eps
->count
= build_ep_list(eps
,
346 case RPC_C_EP_MATCH_BY_IF
:
348 * Return endpoint map elements that contain the
349 * interface identifier specified by the interface_id
350 * and vers_option values.
352 * RPC_C_EP_MATCH_BY_IF and RPC_C_EP_MATCH_BY_BOTH
353 * need both the same endpoint list. There is a second
354 * check for the inquiry_type below which differentiates
357 case RPC_C_EP_MATCH_BY_BOTH
:
359 * Return endpoint map elements that contain the
360 * interface identifier and object UUID specified by
361 * interface_id, vers_option, and object.
363 eps
->count
= build_ep_list(eps
,
364 &r
->in
.interface_id
->uuid
,
368 case RPC_C_EP_MATCH_BY_OBJ
:
370 * Return endpoint map elements that contain the object
371 * UUID specified by object.
373 eps
->count
= build_ep_list(eps
,
379 rc
= EPMAPPER_STATUS_CANT_PERFORM_OP
;
383 if (eps
->count
== 0) {
384 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
388 ok
= create_policy_hnd(p
, r
->out
.entry_handle
, HTYPE_LOOKUP
, eps
);
390 rc
= EPMAPPER_STATUS_NO_MEMORY
;
394 eps
= find_policy_by_hnd(p
,
399 if (!NT_STATUS_IS_OK(status
)) {
400 rc
= EPMAPPER_STATUS_NO_MEMORY
;
403 entry_handle
= r
->out
.entry_handle
;
405 DEBUG(7, ("_epm_Lookup: Trying to find entry_handle.\n"));
407 eps
= find_policy_by_hnd(p
,
412 if (!NT_STATUS_IS_OK(status
)) {
413 rc
= EPMAPPER_STATUS_NO_MEMORY
;
416 entry_handle
= r
->in
.entry_handle
;
419 if (eps
== NULL
|| eps
->e
== NULL
) {
420 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
424 /* return the next N elements */
425 count
= r
->in
.max_ents
;
426 if (count
> eps
->count
) {
430 DEBUG(5, ("_epm_Lookup: Find %u entries\n", count
));
433 close_policy_hnd(p
, entry_handle
);
434 ZERO_STRUCTP(r
->out
.entry_handle
);
436 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
440 r
->out
.entries
= talloc_array(p
->mem_ctx
, struct epm_entry_t
, count
);
441 if (r
->out
.entries
== NULL
) {
442 rc
= EPMAPPER_STATUS_NO_MEMORY
;
446 for (i
= 0; i
< count
; i
++) {
449 switch (r
->in
.inquiry_type
) {
450 case RPC_C_EP_ALL_ELTS
:
452 * Return all elements from the endpoint map. The
453 * interface_id, vers_option, and object parameters MUST
458 case RPC_C_EP_MATCH_BY_IF
:
460 * Return endpoint map elements that contain the
461 * interface identifier specified by the interface_id
462 * and vers_option values.
464 if (GUID_equal(&r
->in
.interface_id
->uuid
,
465 &eps
->e
[i
].syntax_id
.uuid
)) {
469 case RPC_C_EP_MATCH_BY_OBJ
:
471 * Return endpoint map elements that contain the object
472 * UUID specified by object.
474 if (GUID_equal(r
->in
.object
,
475 &eps
->e
[i
].syntax_id
.uuid
)) {
479 case RPC_C_EP_MATCH_BY_BOTH
:
481 * Return endpoint map elements that contain the
482 * interface identifier and object UUID specified by
483 * interface_id, vers_option, and object.
485 if (GUID_equal(&r
->in
.interface_id
->uuid
,
486 &eps
->e
[i
].syntax_id
.uuid
) &&
487 GUID_equal(r
->in
.object
, &eps
->e
[i
].syntax_id
.uuid
)) {
492 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
496 if (r
->in
.inquiry_type
== RPC_C_EP_MATCH_BY_IF
||
497 r
->in
.inquiry_type
== RPC_C_EP_MATCH_BY_OBJ
) {
498 /* Check interface version */
501 switch (r
->in
.vers_option
) {
504 * Return endpoint map elements that
505 * contain the specified interface UUID,
506 * regardless of the version numbers.
510 case RPC_C_VERS_COMPATIBLE
:
512 * Return the endpoint map elements that
513 * contain the same major versions of
514 * the specified interface UUID and a
515 * minor version greater than or equal
516 * to the minor version of the specified
519 if (r
->in
.interface_id
->vers_major
==
520 (eps
->e
[i
].syntax_id
.if_version
>> 16) &&
521 r
->in
.interface_id
->vers_minor
<=
522 (eps
->e
[i
].syntax_id
.if_version
& 0xFFFF)) {
526 case RPC_C_VERS_EXACT
:
528 * Return endpoint map elements that
529 * contain the specified version of the
530 * specified interface UUID.
532 if (r
->in
.interface_id
->vers_major
==
533 (eps
->e
[i
].syntax_id
.if_version
>> 16) &&
534 r
->in
.interface_id
->vers_minor
==
535 (eps
->e
[i
].syntax_id
.if_version
& 0xFFFF)) {
540 case RPC_C_VERS_MAJOR_ONLY
:
542 * Return endpoint map elements that
543 * contain the same version of the
544 * specified interface UUID and ignore
547 if (r
->in
.interface_id
->vers_major
==
548 (eps
->e
[i
].syntax_id
.if_version
>> 16)) {
553 case RPC_C_VERS_UPTO
:
555 * Return endpoint map elements that
556 * contain a version of the specified
557 * interface UUID less than or equal to
558 * the specified major and minor
561 if (r
->in
.interface_id
->vers_major
>
562 eps
->e
[i
].syntax_id
.if_version
>> 16) {
565 if (r
->in
.interface_id
->vers_major
==
566 (eps
->e
[i
].syntax_id
.if_version
>> 16) &&
567 r
->in
.interface_id
->vers_minor
>=
568 (eps
->e
[i
].syntax_id
.if_version
& 0xFFFF)) {
574 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
580 ZERO_STRUCT(r
->out
.entries
[num_ents
].object
);
582 DEBUG(10, ("_epm_Lookup: Adding tower for '%s'\n",
584 r
->out
.entries
[num_ents
].annotation
= talloc_strdup(r
->out
.entries
,
586 r
->out
.entries
[num_ents
].tower
= talloc(r
->out
.entries
,
588 if (r
->out
.entries
[num_ents
].tower
== NULL
) {
589 rc
= EPMAPPER_STATUS_NO_MEMORY
;
592 r
->out
.entries
[num_ents
].tower
->tower
.floors
= talloc_move(r
->out
.entries
[num_ents
].tower
, &eps
->e
[i
].ep
.floors
);
593 r
->out
.entries
[num_ents
].tower
->tower
.num_floors
= eps
->e
[i
].ep
.num_floors
;
594 r
->out
.entries
[num_ents
].tower
->tower_length
= 0;
600 *r
->out
.num_ents
= num_ents
;
604 if (eps
->count
== 0) {
605 close_policy_hnd(p
, entry_handle
);
606 ZERO_STRUCTP(r
->out
.entry_handle
);
607 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
611 rc
= EPMAPPER_STATUS_OK
;
613 talloc_free(tmp_ctx
);
618 static struct rpc_eps
*epm_map_get_towers(
620 const struct ndr_syntax_id
*iface
,
621 enum dcerpc_transport_t transport
,
622 const char *local_address
)
624 struct ndr_syntax_id_buf idbuf
;
625 char *iface_string
= ndr_syntax_id_buf_string(iface
, &idbuf
);
626 struct rpc_eps
*eps
= NULL
;
629 char *bindings
= NULL
;
630 char *binding
= NULL
;
635 DBG_DEBUG("Mapping interface %s\n", iface_string
);
637 eps
= talloc_zero(mem_ctx
, struct rpc_eps
);
642 ret
= tdb_fetch_talloc(
643 epmdb
->tdb
, string_term_tdb_data(iface_string
), eps
, &buf
);
645 DBG_DEBUG("Could not find epm entry for %s: %s\n",
650 buflen
= talloc_array_length(buf
);
652 if ((buflen
< 1) || (buf
[buflen
-1] != '\0')) {
653 DBG_DEBUG("epm entry for %s invalid\n", iface_string
);
656 bindings
= (char *)buf
;
658 name
= bindings
; /* name comes first */
659 binding
= name
; /* strv_next will skip name */
661 while ((binding
= strv_next(bindings
, binding
)) != NULL
) {
662 struct dcerpc_binding
*b
= NULL
;
663 enum dcerpc_transport_t found_transport
;
664 struct dcesrv_ep_iface
*tmp
= NULL
, *new_ep
= NULL
;
666 DBG_DEBUG("Found %s for %s\n", binding
, name
);
668 status
= dcerpc_parse_binding(mem_ctx
, binding
, &b
);
669 if (!NT_STATUS_IS_OK(status
)) {
670 DBG_DEBUG("dcerpc_parse_binding() for %s failed: %s\n",
676 found_transport
= dcerpc_binding_get_transport(b
);
677 if (found_transport
!= transport
) {
678 DBG_DEBUG("Transport %d does not match %d\n",
679 (int)found_transport
,
685 if (found_transport
== NCACN_IP_TCP
) {
686 status
= dcerpc_binding_set_string_option(
687 b
, "host", local_address
);
688 if (!NT_STATUS_IS_OK(status
)) {
689 DBG_DEBUG("Could not set host: %s\n",
695 status
= dcerpc_binding_set_abstract_syntax(b
, iface
);
696 if (!NT_STATUS_IS_OK(status
)) {
697 DBG_DEBUG("Could not set abstract syntax: %s\n",
702 tmp
= talloc_realloc(
705 struct dcesrv_ep_iface
,
712 new_ep
= &eps
->e
[eps
->count
];
714 new_ep
->name
= talloc_strdup(eps
->e
, name
);
715 if (new_ep
->name
== NULL
) {
718 new_ep
->syntax_id
= *iface
;
720 status
= dcerpc_binding_build_tower(eps
->e
, b
, &new_ep
->ep
);
721 if (!NT_STATUS_IS_OK(status
)) {
722 DBG_DEBUG("dcerpc_binding_build_tower failed: %s\n",
741 * Apply some algorithm (using the fields in the map_tower) to an endpoint map
742 * to produce a list of protocol towers.
744 error_status_t
_epm_Map(struct pipes_struct
*p
,
747 struct dcesrv_call_state
*dce_call
= p
->dce_call
;
748 struct dcesrv_connection
*dcesrv_conn
= dce_call
->conn
;
749 struct policy_handle
*entry_handle
;
750 enum dcerpc_transport_t transport
;
751 struct ndr_syntax_id ifid
;
752 struct epm_floor
*floors
;
757 uint32_t num_towers
= 0;
762 *r
->out
.num_towers
= 0;
763 r
->out
.towers
= NULL
;
765 if (r
->in
.map_tower
== NULL
|| r
->in
.max_towers
== 0 ||
766 r
->in
.map_tower
->tower
.num_floors
< 3) {
767 return EPMAPPER_STATUS_NO_MORE_ENTRIES
;
770 tmp_ctx
= talloc_stackframe();
772 ZERO_STRUCTP(r
->out
.entry_handle
);
774 DEBUG(5, ("_epm_Map: Trying to map max. %u towers.\n",
778 * A tower has normally up to 6 floors
780 * +-----------------------------------------------------------------+
781 * | Floor 1 | Provides the RPC interface identifier. (e.g. UUID for |
783 * +---------+-------------------------------------------------------+
784 * | Floor 2 | Transfer syntax (NDR encoded) |
785 * +---------+-------------------------------------------------------+
786 * | Floor 3 | RPC protocol identifier (ncacn_tcp_ip, ncacn_np, ...) |
787 * +---------+-------------------------------------------------------+
788 * | Floor 4 | Port address (e.g. TCP Port: 49156) |
789 * +---------+-------------------------------------------------------+
790 * | Floor 5 | Transport (e.g. IP:192.168.51.10) |
791 * +---------+-------------------------------------------------------+
792 * | Floor 6 | Routing |
793 * +---------+-------------------------------------------------------+
795 floors
= r
->in
.map_tower
->tower
.floors
;
797 /* We accept NDR as the transfer syntax */
798 status
= dcerpc_floor_get_uuid_full(&floors
[1], &ifid
);
799 if (!NT_STATUS_IS_OK(status
)) {
800 DBG_DEBUG("dcerpc_floor_get_uuid_full() failed: %s\n",
802 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
806 if (floors
[1].lhs
.protocol
!= EPM_PROTOCOL_UUID
||
807 !ndr_syntax_id_equal(&ifid
, &ndr_transfer_syntax_ndr
)) {
808 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
812 /* We only talk to sane transports */
813 transport
= dcerpc_transport_by_tower(&r
->in
.map_tower
->tower
);
814 if (transport
== NCA_UNKNOWN
) {
815 DEBUG(2, ("epm_Map: Client requested unknown transport with "
817 for (i
= 2; i
< r
->in
.map_tower
->tower
.num_floors
; i
++) {
818 DEBUG(2, ("%d, ", r
->in
.map_tower
->tower
.floors
[i
].lhs
.protocol
));
821 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
825 if (r
->in
.entry_handle
== NULL
||
826 ndr_policy_handle_empty(r
->in
.entry_handle
)) {
827 const struct tsocket_address
*local_addr
=
828 dcesrv_connection_get_local_address(dcesrv_conn
);
829 char *local_address
= NULL
;
830 struct ndr_syntax_id_buf buf
;
831 char *if_string
= NULL
;
833 DEBUG(7, ("_epm_Map: No entry_handle found, creating it.\n"));
835 status
= dcerpc_floor_get_uuid_full(&floors
[0], &ifid
);
836 if (!NT_STATUS_IS_OK(status
)) {
837 DBG_DEBUG("dcerpc_floor_get_uuid_full() failed: %s\n",
839 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
843 if_string
= ndr_syntax_id_buf_string(&ifid
, &buf
);
845 DBG_INFO("Mapping interface %s\n", if_string
);
847 if ((transport
== NCACN_IP_TCP
) &&
848 tsocket_address_is_inet(local_addr
, "ip")) {
850 * We don't have the host ip in the epm
851 * database. For NCACN_IP_TCP, add the IP that
852 * the client connected to.
854 local_address
= tsocket_address_inet_addr_string(
855 local_addr
, tmp_ctx
);
858 eps
= epm_map_get_towers(
859 tmp_ctx
, &ifid
, transport
, local_address
);
861 DBG_DEBUG("No bindings found\n");
862 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
866 ok
= create_policy_hnd(p
, r
->out
.entry_handle
, HTYPE_LOOKUP
, eps
);
868 rc
= EPMAPPER_STATUS_NO_MEMORY
;
872 eps
= find_policy_by_hnd(p
,
877 if (!NT_STATUS_IS_OK(status
)) {
878 rc
= EPMAPPER_STATUS_NO_MEMORY
;
881 entry_handle
= r
->out
.entry_handle
;
883 DEBUG(7, ("_epm_Map: Trying to find entry_handle.\n"));
885 eps
= find_policy_by_hnd(p
,
890 if (!NT_STATUS_IS_OK(status
)) {
891 rc
= EPMAPPER_STATUS_NO_MEMORY
;
894 entry_handle
= r
->in
.entry_handle
;
897 if (eps
== NULL
|| eps
->e
== NULL
) {
898 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
902 /* return the next N elements */
903 count
= r
->in
.max_towers
;
904 if (count
> eps
->count
) {
909 close_policy_hnd(p
, entry_handle
);
910 ZERO_STRUCTP(r
->out
.entry_handle
);
912 rc
= EPMAPPER_STATUS_NO_MORE_ENTRIES
;
916 r
->out
.towers
= talloc_array(p
->mem_ctx
, struct epm_twr_p_t
, count
);
917 if (r
->out
.towers
== NULL
) {
918 rc
= EPMAPPER_STATUS_NO_MEMORY
;
922 for (i
= 0; i
< count
; i
++) {
923 DEBUG(7, ("_epm_Map: Map tower for '%s'\n",
926 r
->out
.towers
[num_towers
].twr
= talloc(r
->out
.towers
,
928 if (r
->out
.towers
[num_towers
].twr
== NULL
) {
929 rc
= EPMAPPER_STATUS_NO_MEMORY
;
932 r
->out
.towers
[num_towers
].twr
->tower
.floors
= talloc_move(r
->out
.towers
[num_towers
].twr
, &eps
->e
[i
].ep
.floors
);
933 r
->out
.towers
[num_towers
].twr
->tower
.num_floors
= eps
->e
[i
].ep
.num_floors
;
934 r
->out
.towers
[num_towers
].twr
->tower_length
= 0;
939 *r
->out
.num_towers
= num_towers
;
943 if (eps
->count
== 0) {
944 close_policy_hnd(p
, entry_handle
);
945 ZERO_STRUCTP(r
->out
.entry_handle
);
948 rc
= EPMAPPER_STATUS_OK
;
950 talloc_free(tmp_ctx
);
956 * epm_LookupHandleFree
958 error_status_t
_epm_LookupHandleFree(struct pipes_struct
*p
,
959 struct epm_LookupHandleFree
*r
)
961 if (r
->in
.entry_handle
== NULL
) {
962 return EPMAPPER_STATUS_OK
;
965 if (is_valid_policy_hnd(r
->in
.entry_handle
)) {
966 close_policy_hnd(p
, r
->in
.entry_handle
);
969 r
->out
.entry_handle
= r
->in
.entry_handle
;
971 return EPMAPPER_STATUS_OK
;
978 * A client implementation SHOULD NOT call this method. These extensions do not
979 * provide an alternative method.
981 error_status_t
_epm_InqObject(struct pipes_struct
*p
,
982 struct epm_InqObject
*r
)
984 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
985 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
992 * A client implementation SHOULD NOT call this method. These extensions do not
993 * provide an alternative method.
995 error_status_t
_epm_MgmtDelete(struct pipes_struct
*p
,
996 struct epm_MgmtDelete
*r
)
998 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
999 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
1006 error_status_t
_epm_MapAuth(struct pipes_struct
*p
,
1007 struct epm_MapAuth
*r
)
1009 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1010 return EPMAPPER_STATUS_CANT_PERFORM_OP
;
1013 static NTSTATUS
epmapper__op_shutdown_server(struct dcesrv_context
*dce_ctx
,
1014 const struct dcesrv_endpoint_server
*ep_server
);
1016 #define DCESRV_INTERFACE_EPMAPPER_SHUTDOWN_SERVER \
1017 epmapper_shutdown_server
1019 static NTSTATUS
epmapper_shutdown_server(struct dcesrv_context
*dce_ctx
,
1020 const struct dcesrv_endpoint_server
*ep_server
)
1022 return epmapper__op_shutdown_server(dce_ctx
, ep_server
);
1025 static NTSTATUS
epmapper__op_init_server(
1026 struct dcesrv_context
*dce_ctx
,
1027 const struct dcesrv_endpoint_server
*ep_server
);
1029 static NTSTATUS
epmapper_init_server(
1030 struct dcesrv_context
*dce_ctx
,
1031 const struct dcesrv_endpoint_server
*ep_server
)
1033 char *epmdb_path
= NULL
;
1036 epmdb_path
= lock_path(dce_ctx
, "epmdb.tdb");
1037 if (epmdb_path
== NULL
) {
1038 return NT_STATUS_NO_MEMORY
;
1041 epmdb
= tdb_wrap_open(
1045 TDB_CLEAR_IF_FIRST
|TDB_INCOMPATIBLE_HASH
,
1048 if (epmdb
== NULL
) {
1049 DBG_DEBUG("Could not open epmdb.tdb: %s\n", strerror(errno
));
1050 return map_nt_error_from_unix(errno
);
1052 TALLOC_FREE(epmdb_path
);
1054 status
= epmapper__op_init_server(dce_ctx
, ep_server
);
1058 #define DCESRV_INTERFACE_EPMAPPER_INIT_SERVER epmapper_init_server
1060 /* include the generated boilerplate */
1061 #include "librpc/gen_ndr/ndr_epmapper_scompat.c"
1063 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */