summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/librpc/idl/epmapper.idl2
-rw-r--r--source4/rpc_server/dcerpc_server.c1
-rw-r--r--source4/rpc_server/epmapper/rpc_epmapper.c233
-rw-r--r--source4/rpc_server/handles.c2
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);