diff options
author | Andreas Schneider <asn@samba.org> | 2010-10-04 17:58:33 +0200 |
---|---|---|
committer | Andreas Schneider <asn@cryptomilk.org> | 2011-02-02 12:44:20 +0100 |
commit | 658c05b939e0a96cb385bf2808b01595ae838f06 (patch) | |
tree | 92abaee01a6c65aeccf787e05d555fa353026bcc /source3 | |
parent | 6747b89b3ce0e234c6129696825c59b68cada8cd (diff) | |
download | samba-658c05b939e0a96cb385bf2808b01595ae838f06.tar.gz samba-658c05b939e0a96cb385bf2808b01595ae838f06.tar.bz2 samba-658c05b939e0a96cb385bf2808b01595ae838f06.zip |
s3-epmapper: Added epm_Map function from Samba4.
Diffstat (limited to 'source3')
-rw-r--r-- | source3/rpc_server/srv_epmapper.c | 81 |
1 files changed, 77 insertions, 4 deletions
diff --git a/source3/rpc_server/srv_epmapper.c b/source3/rpc_server/srv_epmapper.c index cbaaad1c5b..5f9674bdc8 100644 --- a/source3/rpc_server/srv_epmapper.c +++ b/source3/rpc_server/srv_epmapper.c @@ -25,6 +25,12 @@ typedef uint32_t error_status_t; +/* An endpoint combined with an interface description */ +struct dcesrv_ep_iface { + const char *name; + struct epm_tower ep; +}; + /* A rpc service interface like samr, lsarpc or netlogon */ struct dcesrv_iface { const char *name; @@ -133,7 +139,7 @@ static uint32_t build_ep_list(TALLOC_CTX *mem_ctx, struct dcesrv_endpoint *endpoint_list, struct dcesrv_ep_iface **peps) { - struct dcesrv_ep_iface *eps; + struct dcesrv_ep_iface *eps = NULL; struct dcesrv_endpoint *d; uint32_t total = 0; NTSTATUS status; @@ -375,16 +381,83 @@ error_status_t _epm_Lookup(struct pipes_struct *p, return EPMAPPER_STATUS_CANT_PERFORM_OP; } - /* + * epm_Map + * * Apply some algorithm (using the fields in the map_tower) to an endpoint map * to produce a list of protocol towers. */ error_status_t _epm_Map(struct pipes_struct *p, struct epm_Map *r) { - p->rng_fault_state = true; - return EPMAPPER_STATUS_CANT_PERFORM_OP; + enum dcerpc_transport_t transport; + struct ndr_syntax_id ndr_syntax; + struct dcesrv_ep_iface *eps; + struct epm_floor *floors; + uint32_t count, i; + + count = build_ep_list(p->mem_ctx, endpoint_table, &eps); + + ZERO_STRUCT(*r->out.entry_handle); + r->out.num_towers = talloc(p->mem_ctx, uint32_t); + if (r->out.num_towers == NULL) { + return EPMAPPER_STATUS_NO_MEMORY; + } + + *r->out.num_towers = 1; + r->out.towers = talloc(p->mem_ctx, struct epm_twr_p_t); + if (r->out.towers == NULL) { + return EPMAPPER_STATUS_NO_MEMORY; + } + + r->out.towers->twr = talloc(p->mem_ctx, struct epm_twr_t); + if (r->out.towers->twr == NULL) { + return EPMAPPER_STATUS_NO_MEMORY; + } + + if (r->in.map_tower == NULL || r->in.max_towers == 0 || + r->in.map_tower->tower.num_floors < 3) { + goto failed; + } + + floors = r->in.map_tower->tower.floors; + + dcerpc_floor_get_lhs_data(&r->in.map_tower->tower.floors[1], &ndr_syntax); + + if (floors[1].lhs.protocol != EPM_PROTOCOL_UUID || + !GUID_equal(&ndr_syntax.uuid, &ndr_transfer_syntax.uuid) || + ndr_syntax.if_version != ndr_transfer_syntax.if_version) { + goto failed; + } + + transport = dcerpc_transport_by_tower(&r->in.map_tower->tower); + if (transport == -1) { + DEBUG(2, ("epm_Insert: Client requested unknown transport with levels: ")); + for (i = 2; i < r->in.map_tower->tower.num_floors; i++) { + DEBUG(2, ("%d, ", r->in.map_tower->tower.floors[i].lhs.protocol)); + } + DEBUG(2, ("\n")); + goto failed; + } + + for (i = 0; i < count; i++) { + if (data_blob_cmp(&r->in.map_tower->tower.floors[0].lhs.lhs_data, + &eps[i].ep.floors[0].lhs.lhs_data) != 0 || + transport != dcerpc_transport_by_tower(&eps[i].ep)) { + continue; + } + + r->out.towers->twr->tower = eps[i].ep; + r->out.towers->twr->tower_length = 0; + + return EPMAPPER_STATUS_OK; + } + +failed: + *r->out.num_towers = 0; + r->out.towers->twr = NULL; + + return EPMAPPER_STATUS_NO_MORE_ENTRIES; } /* |