diff options
-rw-r--r-- | source4/librpc/idl/epmapper.idl | 2 | ||||
-rw-r--r-- | source4/rpc_server/dcerpc_server.c | 1 | ||||
-rw-r--r-- | source4/rpc_server/epmapper/rpc_epmapper.c | 233 | ||||
-rw-r--r-- | source4/rpc_server/handles.c | 2 |
4 files changed, 170 insertions, 68 deletions
diff --git a/source4/librpc/idl/epmapper.idl b/source4/librpc/idl/epmapper.idl index 250129f84d..59c542255d 100644 --- a/source4/librpc/idl/epmapper.idl +++ b/source4/librpc/idl/epmapper.idl @@ -123,6 +123,8 @@ interface epmapper /**********************/ /* Function 0x03 */ + const int EPMAPPER_MAP_FAILED = 0x16c9a0d6; + typedef struct { epm_twr_t *twr; } epm_twr_p_t; diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c index e2a6ab0132..35661d913e 100644 --- a/source4/rpc_server/dcerpc_server.c +++ b/source4/rpc_server/dcerpc_server.c @@ -105,6 +105,7 @@ NTSTATUS dcesrv_endpoint_connect(struct server_context *smb, (*p)->ndr = NULL; (*p)->dispatch = NULL; (*p)->handles = NULL; + (*p)->next_handle = 0; /* make sure the endpoint server likes the connection */ status = ops->connect(*p); diff --git a/source4/rpc_server/epmapper/rpc_epmapper.c b/source4/rpc_server/epmapper/rpc_epmapper.c index 945823c013..c5bd2ffa45 100644 --- a/source4/rpc_server/epmapper/rpc_epmapper.c +++ b/source4/rpc_server/epmapper/rpc_epmapper.c @@ -26,14 +26,104 @@ /* handle types for this module */ enum handle_types {HTYPE_LOOKUP}; + +/* + simple routine to compare a GUID string to a GUID structure +*/ +static int guid_cmp(TALLOC_CTX *mem_ctx, const GUID *guid, const char *uuid_str) +{ + const char *s = GUID_string(mem_ctx, guid); + if (!s || strcasecmp(s, uuid_str)) { + return -1; + } + return 0; +} + +/* + fill a protocol tower +*/ +static BOOL fill_protocol_tower(TALLOC_CTX *mem_ctx, struct epm_towers *twr, + struct dcesrv_ep_iface *e) +{ + twr->num_floors = 5; + twr->floors = talloc_array_p(mem_ctx, struct epm_floor, 5); + if (!twr->floors) { + return False; + } + + twr->floors[0].lhs.protocol = EPM_PROTOCOL_UUID; + GUID_from_string(e->uuid, &twr->floors[0].lhs.info.uuid.uuid); + twr->floors[0].lhs.info.uuid.version = e->if_version; + twr->floors[0].rhs.rhs_data = data_blob_talloc_zero(mem_ctx, 2); + + /* encoded with NDR ... */ + twr->floors[1].lhs.protocol = EPM_PROTOCOL_UUID; + GUID_from_string(NDR_GUID, &twr->floors[1].lhs.info.uuid.uuid); + twr->floors[1].lhs.info.uuid.version = NDR_GUID_VERSION; + twr->floors[1].rhs.rhs_data = data_blob_talloc_zero(mem_ctx, 2); + + /* on an RPC connection ... */ + twr->floors[2].lhs.protocol = EPM_PROTOCOL_RPC_C; + twr->floors[2].lhs.info.lhs_data = data_blob(NULL, 0); + twr->floors[2].rhs.rhs_data = data_blob_talloc_zero(mem_ctx, 2); + + /* on a SMB pipe ... */ + twr->floors[3].lhs.protocol = EPM_PROTOCOL_SMB; + twr->floors[3].lhs.info.lhs_data = data_blob(NULL, 0); + twr->floors[3].rhs.rhs_data.data = talloc_asprintf(mem_ctx, "\\PIPE\\%s", + e->endpoint.info.smb_pipe); + twr->floors[3].rhs.rhs_data.length = strlen(twr->floors[3].rhs.rhs_data.data); + + /* on an NetBIOS link ... */ + twr->floors[4].lhs.protocol = EPM_PROTOCOL_NETBIOS; + twr->floors[4].lhs.info.lhs_data = data_blob(NULL, 0); + twr->floors[4].rhs.rhs_data.data = talloc_asprintf(mem_ctx, "\\\\%s", + lp_netbios_name()); + twr->floors[4].rhs.rhs_data.length = strlen(twr->floors[4].rhs.rhs_data.data); + + return True; +} + + +/* + build a list of all interfaces handled by all endpoint servers +*/ +static uint32 build_ep_list(TALLOC_CTX *mem_ctx, + struct dce_endpoint *endpoint_list, + struct dcesrv_ep_iface **eps) +{ + struct dce_endpoint *d; + uint32 total = 0; + + (*eps) = NULL; + + for (d=endpoint_list; d; d=d->next) { + struct dcesrv_ep_iface *e; + int count = d->endpoint_ops->lookup_endpoints(mem_ctx, &e); + if (count > 0) { + (*eps) = talloc_realloc_p(mem_ctx, *eps, + struct dcesrv_ep_iface, + total + count); + if (!*eps) { + return 0; + } + memcpy((*eps) + total, e, sizeof(*e) * count); + total += count; + } + } + + return total; +} + + static NTSTATUS epm_Insert(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, - struct epm_Lookup *r) + struct epm_Insert *r) { return NT_STATUS_NOT_IMPLEMENTED; } static NTSTATUS epm_Delete(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, - struct epm_Lookup *r) + struct epm_Delete *r) { return NT_STATUS_NOT_IMPLEMENTED; } @@ -64,31 +154,13 @@ static NTSTATUS epm_Lookup(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, if (!eps) { /* this is the first call - fill the list. Subsequent calls will feed from this list, stored in the handle */ - struct dce_endpoint *d; - struct dcesrv_ep_iface *e; - eps = talloc_p(h->mem_ctx, struct rpc_eps); if (!eps) { return NT_STATUS_NO_MEMORY; } - eps->count = 0; - eps->e = NULL; h->data = eps; - - for (d=dce->smb->dcesrv.endpoint_list; d; d=d->next) { - int count = d->endpoint_ops->lookup_endpoints(h->mem_ctx, &e); - if (count > 0) { - eps->e = talloc_realloc_p(h->mem_ctx, - eps->e, - struct dcesrv_ep_iface, - eps->count + count); - if (!eps->e) { - return NT_STATUS_NO_MEMORY; - } - memcpy(eps->e + eps->count, e, sizeof(*e) * count); - eps->count += count; - } - } + + eps->count = build_ep_list(h->mem_ctx, dce->smb->dcesrv.endpoint_list, &eps->e); } /* return the next N elements */ @@ -112,52 +184,16 @@ static NTSTATUS epm_Lookup(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, } for (i=0;i<num_ents;i++) { - struct epm_twr_t *t; - struct epm_towers *twr; - ZERO_STRUCT(r->out.entries[i].object); r->out.entries[i].annotation = ""; - t = talloc_p(mem_ctx, struct epm_twr_t); - if (!twr) { + r->out.entries[i].tower = talloc_p(mem_ctx, struct epm_twr_t); + if (!r->out.entries[i].tower) { return NT_STATUS_NO_MEMORY; } - r->out.entries[i].tower = t; - twr = &t->towers; - twr->num_floors = 5; - twr->floors = talloc_array_p(mem_ctx, struct epm_floor, 5); - if (!twr->floors) { + + if (!fill_protocol_tower(mem_ctx, &r->out.entries[i].tower->towers, &eps->e[i])) { return NT_STATUS_NO_MEMORY; } - - twr->floors[0].lhs.protocol = EPM_PROTOCOL_UUID; - GUID_from_string(eps->e[i].uuid, &twr->floors[0].lhs.info.uuid.uuid); - twr->floors[0].lhs.info.uuid.version = eps->e[i].if_version; - twr->floors[0].rhs.rhs_data = data_blob_talloc_zero(mem_ctx, 2); - - /* encoded with NDR ... */ - twr->floors[1].lhs.protocol = EPM_PROTOCOL_UUID; - GUID_from_string(NDR_GUID, &twr->floors[1].lhs.info.uuid.uuid); - twr->floors[1].lhs.info.uuid.version = NDR_GUID_VERSION; - twr->floors[1].rhs.rhs_data = data_blob_talloc_zero(mem_ctx, 2); - - /* on an RPC connection ... */ - twr->floors[2].lhs.protocol = EPM_PROTOCOL_RPC_C; - twr->floors[2].lhs.info.lhs_data = data_blob(NULL, 0); - twr->floors[2].rhs.rhs_data = data_blob_talloc_zero(mem_ctx, 2); - - /* on a SMB pipe ... */ - twr->floors[3].lhs.protocol = EPM_PROTOCOL_SMB; - twr->floors[3].lhs.info.lhs_data = data_blob(NULL, 0); - twr->floors[3].rhs.rhs_data.data = talloc_asprintf(mem_ctx, "\\PIPE\\%s", - eps->e[i].endpoint.info.smb_pipe); - twr->floors[3].rhs.rhs_data.length = strlen(twr->floors[3].rhs.rhs_data.data); - - /* on an NetBIOS link ... */ - twr->floors[4].lhs.protocol = EPM_PROTOCOL_NETBIOS; - twr->floors[4].lhs.info.lhs_data = data_blob(NULL, 0); - twr->floors[4].rhs.rhs_data.data = talloc_asprintf(mem_ctx, "\\\\%s", - lp_netbios_name()); - twr->floors[4].rhs.rhs_data.length = strlen(twr->floors[4].rhs.rhs_data.data); } eps->count -= num_ents; @@ -172,25 +208,88 @@ static NTSTATUS epm_Lookup(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, a generic protocol tower */ static NTSTATUS epm_Map(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, - struct epm_Lookup *r) + struct epm_Map *r) { - return NT_STATUS_NOT_IMPLEMENTED; + uint32 count; + int i; + struct dcesrv_ep_iface *eps; + struct epm_floor *floors; + + count = build_ep_list(mem_ctx, dce->smb->dcesrv.endpoint_list, &eps); + + ZERO_STRUCTP(r->out.entry_handle); + r->out.num_towers = 1; + r->out.status = 0; + r->out.towers = talloc_p(mem_ctx, struct epm_twr_p_t); + if (!r->out.towers) { + return NT_STATUS_NO_MEMORY; + } + r->out.towers->twr = talloc_p(mem_ctx, struct epm_twr_t); + if (!r->out.towers->twr) { + return NT_STATUS_NO_MEMORY; + } + + if (!r->in.map_tower || r->in.max_towers == 0 || + r->in.map_tower->towers.num_floors != 5) { + goto failed; + } + + floors = r->in.map_tower->towers.floors; + + if (floors[0].lhs.protocol != EPM_PROTOCOL_UUID || + floors[1].lhs.protocol != EPM_PROTOCOL_UUID || + guid_cmp(mem_ctx, &floors[1].lhs.info.uuid.uuid, NDR_GUID) != 0 || + floors[1].lhs.info.uuid.version != NDR_GUID_VERSION || + floors[2].lhs.protocol != EPM_PROTOCOL_RPC_C) { + goto failed; + } + + for (i=0;i<count;i++) { + if (guid_cmp(mem_ctx, &floors[0].lhs.info.uuid.uuid, eps[i].uuid) != 0 || + floors[0].lhs.info.uuid.version != eps[i].if_version) { + continue; + } + switch (eps[i].endpoint.type) { + case ENDPOINT_SMB: + if (floors[3].lhs.protocol != EPM_PROTOCOL_SMB || + floors[4].lhs.protocol != EPM_PROTOCOL_NETBIOS) { + continue; + } + break; + case ENDPOINT_TCP: + if (floors[3].lhs.protocol != EPM_PROTOCOL_TCP || + floors[4].lhs.protocol != EPM_PROTOCOL_IP) { + continue; + } + break; + } + fill_protocol_tower(mem_ctx, &r->out.towers->twr->towers, &eps[i]); + return NT_STATUS_OK; + } + + +failed: + r->out.num_towers = 0; + r->out.status = EPMAPPER_MAP_FAILED; + r->out.towers->twr = NULL; + + return NT_STATUS_OK; } static NTSTATUS epm_LookupHandleFree(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, - struct epm_Lookup *r) + struct epm_LookupHandleFree *r) { return NT_STATUS_NOT_IMPLEMENTED; } static NTSTATUS epm_InqObject(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, - struct epm_Lookup *r) + struct epm_InqObject *r) { return NT_STATUS_NOT_IMPLEMENTED; } static NTSTATUS epm_MgmtDelete(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, - struct epm_Lookup *r) + struct epm_MgmtDelete *r) { return NT_STATUS_NOT_IMPLEMENTED; } diff --git a/source4/rpc_server/handles.c b/source4/rpc_server/handles.c index 16e4175184..6b7d422267 100644 --- a/source4/rpc_server/handles.c +++ b/source4/rpc_server/handles.c @@ -49,8 +49,8 @@ struct dcesrv_handle *dcesrv_handle_new(struct dcesrv_state *dce, /* TODO: check for wraparound here */ SIVAL(&h->wire_handle.data, 12, random()); - SIVAL(&h->wire_handle.data, 16, dce->next_handle); dce->next_handle++; + SIVAL(&h->wire_handle.data, 16, dce->next_handle); DLIST_ADD(dce->handles, h); |