1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-24 13:57:43 +03:00

added a basic dcerpc endpoint mapper to Samba4. Currently only

implements the epm_Lookup() call, I'll add the other important calls
soon. I was rather pleased to find that epm_Lookup() worked first
time, which is particularly surprising given its complexity.

This required quite a bit of new infrastructure:

  * a generic way of handling dcerpc policy handles in the rpc server

  * added type checked varients of talloc. These are much less error
    prone. I'd like to move to using these for nearly all uses of
    talloc.

  * added more dcerpc fault handling code, and translation from
    NTSTATUS to a dcerpc fault code

  * added data_blob_talloc_zero() for allocating an initially zero
    blob

  * added a endpoint enumeration hook in the dcerpc endpoint server
    operations
(This used to be commit 3f85f9b782dc17417baf1ca557fcae22f5b6a83a)
This commit is contained in:
Andrew Tridgell 2003-12-13 02:20:40 +00:00
parent f7065cc0a5
commit 340d9b71f9
14 changed files with 562 additions and 39 deletions

View File

@ -285,7 +285,9 @@ SMBD_NTVFS_OBJ = ntvfs/ntvfs_base.o ntvfs/ntvfs_util.o \
ntvfs/ntvfs_generic.o @NTVFS_STATIC@
SMBD_RPC_OBJ = rpc_server/dcerpc_server.o \
rpc_server/echo/rpc_echo.o
rpc_server/handles.o \
rpc_server/echo/rpc_echo.o \
rpc_server/epmapper/rpc_epmapper.o
SMBD_OBJ_SRV = smbd/connection.o \
smbd/session.o \

View File

@ -46,6 +46,11 @@ char *talloc_vasprintf_append(TALLOC_CTX *t, char *, const char *, va_list ap)
char *talloc_asprintf_append(TALLOC_CTX *t, char *, const char *, ...)
PRINTF_ATTRIBUTE(3, 4);
/* useful macros for creating type checked pointers */
#define talloc_p(ctx, type) (type *)talloc(ctx, sizeof(type));
#define talloc_array_p(ctx, type, count) (type *)talloc_realloc_array(ctx, NULL, sizeof(type), count)
#define talloc_realloc_p(ctx, p, type, count) (type *)talloc_realloc_array(ctx, p, sizeof(type), count)
/** @} */
#endif /* ndef _TALLOC_H_ */

View File

@ -87,6 +87,18 @@ DATA_BLOB data_blob_talloc(TALLOC_CTX *mem_ctx, const void *p, size_t length)
return ret;
}
/*******************************************************************
construct a zero data blob, using supplied TALLOC_CTX.
use this sparingly as it initialises data - better to initialise
yourself if you want specific data in the blob
*******************************************************************/
DATA_BLOB data_blob_talloc_zero(TALLOC_CTX *mem_ctx, size_t length)
{
DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, length);
data_blob_clear(&blob);
return blob;
}
/*******************************************************************
free a data blob
*******************************************************************/

View File

@ -22,17 +22,6 @@
#include "includes.h"
/* see if a range of memory is all zero. Used to prevent dumping of zero elements */
static int all_zero(const char *ptr, unsigned size)
{
int i;
if (!ptr) return 1;
for (i=0;i<size;i++) {
if (ptr[i]) return 0;
}
return 1;
}
/* encode a buffer of bytes into a escaped string */
static char *encode_bytes(TALLOC_CTX *mem_ctx, const char *ptr, unsigned len)
{

View File

@ -48,12 +48,13 @@
**/
/**
* If you want testing for memory corruption, link with dmalloc or use
* Insure++. It doesn't seem useful to duplicate them here.
* If you want testing for memory corruption use valgrind
**/
#include "includes.h"
#define MAX_TALLOC_SIZE 0x10000000
struct talloc_chunk {
struct talloc_chunk *next;
size_t size;
@ -188,8 +189,14 @@ void *talloc_realloc(TALLOC_CTX *t, void *ptr, size_t size)
void *new_ptr;
/* size zero is equivalent to free() */
if (!t || size == 0)
if (!t) {
return NULL;
}
if (size == 0) {
talloc_free(t, ptr);
return NULL;
}
/* realloc(NULL) is equavalent to malloc() */
if (ptr == NULL)
@ -470,6 +477,39 @@ void talloc_get_allocation(TALLOC_CTX *t,
}
/*
free a lump from a pool. Use sparingly please.
*/
void talloc_free(TALLOC_CTX *ctx, void *ptr)
{
struct talloc_chunk *tc;
if (!ptr || !ctx->list) return;
/* as a special case, see if its the first element in the
list */
if (ctx->list->ptr == ptr) {
ctx->total_alloc_size -= ctx->list->size;
ctx->list = ctx->list->next;
free(ptr);
return;
}
/* find it in the context */
for (tc=ctx->list; tc->next; tc=tc->next) {
if (tc->next->ptr == ptr) break;
}
if (tc->next) {
ctx->total_alloc_size -= tc->next->size;
tc->next = tc->next->next;
} else {
DEBUG(0,("Attempt to free non-allocated chunk in context '%s'\n",
ctx->name));
}
}
/*
move a lump of memory from one talloc context to another
return the ptr on success, or NULL if it could not be found
@ -511,5 +551,16 @@ const void *talloc_steal(TALLOC_CTX *old_ctx, TALLOC_CTX *new_ctx, const void *p
return ptr;
}
/*
realloc an array, checking for integer overflow in the array size
*/
void *talloc_realloc_array(TALLOC_CTX *ctx, void *ptr, size_t el_size, unsigned count)
{
if (count == 0 ||
count >= MAX_TALLOC_SIZE/el_size) {
return NULL;
}
return talloc_realloc(ctx, ptr, el_size * count);
}
/** @} */

View File

@ -1009,3 +1009,17 @@ void dump_data_pw(const char *msg, const uchar * data, size_t len)
}
#endif
}
/* see if a range of memory is all zero. A NULL pointer is considered
to be all zero */
BOOL all_zero(const char *ptr, unsigned size)
{
int i;
if (!ptr) return True;
for (i=0;i<size;i++) {
if (ptr[i]) return False;
}
return True;
}

View File

@ -82,9 +82,10 @@ interface dcerpc
} dcerpc_response;
const int DCERPC_FAULT_OP_RNG_ERROR = 0x1c010002;
const int DCERPC_FAULT_NDR = 0x000006f7;
const int DCERPC_FAULT_OTHER = 0x00000001;
const int DCERPC_FAULT_OP_RNG_ERROR = 0x1c010002;
const int DCERPC_FAULT_NDR = 0x000006f7;
const int DCERPC_FAULT_CONTEXT_MISMATCH = 0x1c00001a;
const int DCERPC_FAULT_OTHER = 0x00000001;
/* we return this fault when we haven't yet run the test
to see what fault w2k3 returns in this case */

View File

@ -96,28 +96,28 @@ NTSTATUS dcerpc_epm_map_tcp_port(const char *server,
twr.towers.floors[0].lhs.protocol = EPM_PROTOCOL_UUID;
GUID_from_string(uuid, &twr.towers.floors[0].lhs.info.uuid.uuid);
twr.towers.floors[0].lhs.info.uuid.version = version;
twr.towers.floors[0].rhs.rhs_data = data_blob_talloc(p->mem_ctx, NULL, 2);
twr.towers.floors[0].rhs.rhs_data = data_blob_talloc_zero(p->mem_ctx, 2);
/* encoded with NDR ... */
twr.towers.floors[1].lhs.protocol = EPM_PROTOCOL_UUID;
GUID_from_string(NDR_GUID, &twr.towers.floors[1].lhs.info.uuid.uuid);
twr.towers.floors[1].lhs.info.uuid.version = NDR_GUID_VERSION;
twr.towers.floors[1].rhs.rhs_data = data_blob_talloc(p->mem_ctx, NULL, 2);
twr.towers.floors[1].rhs.rhs_data = data_blob_talloc_zero(p->mem_ctx, 2);
/* on an RPC connection ... */
twr.towers.floors[2].lhs.protocol = EPM_PROTOCOL_RPC_C;
twr.towers.floors[2].lhs.info.lhs_data = data_blob(NULL, 0);
twr.towers.floors[2].rhs.rhs_data = data_blob_talloc(p->mem_ctx, NULL, 2);
twr.towers.floors[2].rhs.rhs_data = data_blob_talloc_zero(p->mem_ctx, 2);
/* on a TCP port ... */
twr.towers.floors[3].lhs.protocol = EPM_PROTOCOL_TCP;
twr.towers.floors[3].lhs.info.lhs_data = data_blob(NULL, 0);
twr.towers.floors[3].rhs.rhs_data = data_blob_talloc(p->mem_ctx, NULL, 2);
twr.towers.floors[3].rhs.rhs_data = data_blob_talloc_zero(p->mem_ctx, 2);
/* on an IP link ... */
twr.towers.floors[4].lhs.protocol = EPM_PROTOCOL_IP;
twr.towers.floors[4].lhs.info.lhs_data = data_blob(NULL, 0);
twr.towers.floors[4].rhs.rhs_data = data_blob_talloc(p->mem_ctx, NULL, 4);
twr.towers.floors[4].rhs.rhs_data = data_blob_talloc_zero(p->mem_ctx, 4);
/* with some nice pretty paper around it of course */
r.in.object = &guid;

View File

@ -89,12 +89,13 @@ NTSTATUS dcesrv_endpoint_connect(struct server_context *smb,
return NT_STATUS_NO_MEMORY;
}
*p = talloc(mem_ctx, sizeof(struct dcesrv_state));
*p = talloc_p(mem_ctx, struct dcesrv_state);
if (! *p) {
talloc_destroy(mem_ctx);
return NT_STATUS_NO_MEMORY;
}
(*p)->smb = smb;
(*p)->mem_ctx = mem_ctx;
(*p)->endpoint = *endpoint;
(*p)->ops = ops;
@ -103,6 +104,7 @@ NTSTATUS dcesrv_endpoint_connect(struct server_context *smb,
(*p)->cli_max_recv_frag = 0;
(*p)->ndr = NULL;
(*p)->dispatch = NULL;
(*p)->handles = NULL;
/* make sure the endpoint server likes the connection */
status = ops->connect(*p);
@ -121,6 +123,14 @@ NTSTATUS dcesrv_endpoint_connect(struct server_context *smb,
void dcesrv_endpoint_disconnect(struct dcesrv_state *p)
{
p->ops->disconnect(p);
/* destroy any handles */
while (p->handles) {
TALLOC_CTX *m = p->handles->mem_ctx;
DLIST_REMOVE(p->handles, p->handles);
talloc_destroy(m);
}
talloc_destroy(p->mem_ctx);
}
@ -161,7 +171,7 @@ static NTSTATUS dcesrv_fault(struct dcesrv_call_state *call, uint32 fault_code)
return status;
}
rep = talloc(call->mem_ctx, sizeof(*rep));
rep = talloc_p(call->mem_ctx, struct dcesrv_call_reply);
if (!rep) {
return NT_STATUS_NO_MEMORY;
}
@ -175,6 +185,22 @@ static NTSTATUS dcesrv_fault(struct dcesrv_call_state *call, uint32 fault_code)
}
/*
return a dcerpc fault from a ntstatus code
*/
static NTSTATUS dcesrv_fault_nt(struct dcesrv_call_state *call, NTSTATUS status)
{
uint32 fault_code = DCERPC_FAULT_OTHER;
/* TODO: we need to expand this table to include more mappings */
if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
fault_code = DCERPC_FAULT_CONTEXT_MISMATCH;
}
return dcesrv_fault(call, fault_code);
}
/*
return a dcerpc bind_nak
*/
@ -210,7 +236,7 @@ static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32 reason)
return status;
}
rep = talloc(call->mem_ctx, sizeof(*rep));
rep = talloc_p(call->mem_ctx, struct dcesrv_call_reply);
if (!rep) {
return NT_STATUS_NO_MEMORY;
}
@ -290,7 +316,7 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
pkt.u.bind_ack.secondary_address = "";
}
pkt.u.bind_ack.num_results = 1;
pkt.u.bind_ack.ctx_list = talloc(call->mem_ctx, sizeof(struct dcerpc_ack_ctx));
pkt.u.bind_ack.ctx_list = talloc_p(call->mem_ctx, struct dcerpc_ack_ctx);
if (!pkt.u.bind_ack.ctx_list) {
return NT_STATUS_NO_MEMORY;
}
@ -312,7 +338,7 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
return status;
}
rep = talloc(call->mem_ctx, sizeof(*rep));
rep = talloc_p(call->mem_ctx, struct dcesrv_call_reply);
if (!rep) {
return NT_STATUS_NO_MEMORY;
}
@ -363,7 +389,7 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
/* call the dispatch function */
status = call->dce->dispatch[opnum](call->dce, call->mem_ctx, r);
if (!NT_STATUS_IS_OK(status)) {
return dcesrv_fault(call, DCERPC_FAULT_NDR);
return dcesrv_fault_nt(call, status);
}
/* form the reply NDR */
@ -384,7 +410,7 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
struct dcesrv_call_reply *rep;
struct dcerpc_packet pkt;
rep = talloc(call->mem_ctx, sizeof(*rep));
rep = talloc_p(call->mem_ctx, struct dcesrv_call_reply);
if (!rep) {
return NT_STATUS_NO_MEMORY;
}
@ -455,7 +481,7 @@ NTSTATUS dcesrv_input(struct dcesrv_state *dce, const DATA_BLOB *data)
if (!mem_ctx) {
return NT_STATUS_NO_MEMORY;
}
call = talloc(mem_ctx, sizeof(*call));
call = talloc_p(mem_ctx, struct dcesrv_call_state);
if (!call) {
talloc_destroy(mem_ctx);
return NT_STATUS_NO_MEMORY;
@ -612,11 +638,33 @@ BOOL dcesrv_table_query(const struct dcerpc_interface_table *table,
}
/*
a useful function for implementing the lookup_endpoints op
*/
int dcesrv_lookup_endpoints(const struct dcerpc_interface_table *table,
TALLOC_CTX *mem_ctx,
struct dcesrv_ep_iface **e)
{
*e = talloc_p(mem_ctx, struct dcesrv_ep_iface);
if (! *e) {
return -1;
}
(*e)->uuid = table->uuid;
(*e)->if_version = table->if_version;
(*e)->endpoint.type = ENDPOINT_SMB;
(*e)->endpoint.info.smb_pipe = table->endpoints->names[0];
return 1;
}
/*
initialise the dcerpc server subsystem
*/
BOOL dcesrv_init(struct server_context *smb)
{
rpc_echo_init(smb);
rpc_epmapper_init(smb);
return True;
}

View File

@ -23,7 +23,8 @@
enum endpoint_type {ENDPOINT_SMB, ENDPOINT_TCP};
/* a description of a single dcerpc endpoint */
/* a description of a single dcerpc endpoint. Not as flexible as a full epm tower,
but much easier to work with */
struct dcesrv_endpoint {
enum endpoint_type type;
union {
@ -32,6 +33,13 @@ struct dcesrv_endpoint {
} info;
};
/* a endpoint combined with an interface description */
struct dcesrv_ep_iface {
struct dcesrv_endpoint endpoint;
const char *uuid;
uint32 if_version;
};
struct dcesrv_state;
/* the dispatch functions for an interface take this form */
@ -50,8 +58,20 @@ struct dcesrv_call_state {
} *replies;
};
/* a dcerpc handle in internal format */
struct dcesrv_handle {
struct dcesrv_handle *next, *prev;
struct policy_handle wire_handle;
TALLOC_CTX *mem_ctx;
void *data;
};
/* the state associated with a dcerpc server connection */
struct dcesrv_state {
/* the top level context for this server */
struct server_context *smb;
TALLOC_CTX *mem_ctx;
/* the endpoint that was opened */
@ -75,6 +95,11 @@ struct dcesrv_state {
/* private data for the endpoint server */
void *private;
/* current rpc handles - this is really the wrong scope for
them, but it will do for now */
uint32 next_handle;
struct dcesrv_handle *handles;
};
@ -92,6 +117,10 @@ struct dcesrv_endpoint_ops {
/* disconnect() is called when the endpoint is disconnected */
void (*disconnect)(struct dcesrv_state *);
/* this function is used to ask an endpoint server for a list
of endpoints it wants to handle */
int (*lookup_endpoints)(TALLOC_CTX *mem_ctx, struct dcesrv_ep_iface **);
};

View File

@ -163,11 +163,17 @@ static void op_disconnect(struct dcesrv_state *dce)
}
static int op_lookup_endpoints(TALLOC_CTX *mem_ctx, struct dcesrv_ep_iface **e)
{
return dcesrv_lookup_endpoints(&dcerpc_table_rpcecho, mem_ctx, e);
}
static const struct dcesrv_endpoint_ops rpc_echo_ops = {
op_query_endpoint,
op_set_interface,
op_connect,
op_disconnect
op_disconnect,
op_lookup_endpoints
};
/*

View File

@ -0,0 +1,274 @@
/*
Unix SMB/CIFS implementation.
endpoint server for the epmapper pipe
Copyright (C) Andrew Tridgell 2003
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
/* handle types for this module */
enum handle_types {HTYPE_LOOKUP};
static NTSTATUS epm_Insert(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx,
struct epm_Lookup *r)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
static NTSTATUS epm_Delete(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx,
struct epm_Lookup *r)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
/*
implement epm_Lookup. This call is used to enumerate the interfaces
available on a rpc server
*/
static NTSTATUS epm_Lookup(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx,
struct epm_Lookup *r)
{
struct dcesrv_handle *h;
struct rpc_eps {
uint32 count;
struct dcesrv_ep_iface *e;
} *eps;
uint32 num_ents;
int i;
h = dcesrv_handle_fetch(dce, r->in.entry_handle, HTYPE_LOOKUP);
if (!h) {
return NT_STATUS_INVALID_HANDLE;
}
eps = h->data;
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;
}
}
}
/* return the next N elements */
num_ents = r->in.max_ents;
if (num_ents > eps->count) {
num_ents = eps->count;
}
*r->out.entry_handle = h->wire_handle;
r->out.num_ents = num_ents;
r->out.status = 0;
if (num_ents == 0) {
r->out.entries = NULL;
return NT_STATUS_OK;
}
r->out.entries = talloc_array_p(mem_ctx, struct epm_entry_t, num_ents);
if (!r->out.entries) {
return NT_STATUS_NO_MEMORY;
}
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) {
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) {
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;
eps->e += num_ents;
return NT_STATUS_OK;
}
/*
implement epm_Map. This is used to find the specific endpoint to talk to given
a generic protocol tower
*/
static NTSTATUS epm_Map(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx,
struct epm_Lookup *r)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
static NTSTATUS epm_LookupHandleFree(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx,
struct epm_Lookup *r)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
static NTSTATUS epm_InqObject(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx,
struct epm_Lookup *r)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
static NTSTATUS epm_MgmtDelete(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx,
struct epm_Lookup *r)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
/**************************************************************************
all the code below this point is boilerplate that will be auto-generated
***************************************************************************/
static const dcesrv_dispatch_fn_t dispatch_table[] = {
(dcesrv_dispatch_fn_t)epm_Insert,
(dcesrv_dispatch_fn_t)epm_Delete,
(dcesrv_dispatch_fn_t)epm_Lookup,
(dcesrv_dispatch_fn_t)epm_Map,
(dcesrv_dispatch_fn_t)epm_LookupHandleFree,
(dcesrv_dispatch_fn_t)epm_InqObject,
(dcesrv_dispatch_fn_t)epm_MgmtDelete
};
/*
return True if we want to handle the given endpoint
*/
static BOOL op_query_endpoint(const struct dcesrv_endpoint *ep)
{
return dcesrv_table_query(&dcerpc_table_epmapper, ep);
}
/*
setup for a particular rpc interface
*/
static BOOL op_set_interface(struct dcesrv_state *dce, const char *uuid, uint32 if_version)
{
if (strcasecmp(uuid, dcerpc_table_epmapper.uuid) != 0 ||
if_version != dcerpc_table_epmapper.if_version) {
DEBUG(2,("Attempt to use unknown interface %s/%d\n", uuid, if_version));
return False;
}
dce->ndr = &dcerpc_table_epmapper;
dce->dispatch = dispatch_table;
return True;
}
/* op_connect is called when a connection is made to an endpoint */
static NTSTATUS op_connect(struct dcesrv_state *dce)
{
return NT_STATUS_OK;
}
static void op_disconnect(struct dcesrv_state *dce)
{
/* nothing to do */
}
static int op_lookup_endpoints(TALLOC_CTX *mem_ctx, struct dcesrv_ep_iface **e)
{
return dcesrv_lookup_endpoints(&dcerpc_table_epmapper, mem_ctx, e);
}
static const struct dcesrv_endpoint_ops rpc_epmapper_ops = {
op_query_endpoint,
op_set_interface,
op_connect,
op_disconnect,
op_lookup_endpoints
};
/*
register with the dcerpc server
*/
void rpc_epmapper_init(struct server_context *smb)
{
if (!dcesrv_endpoint_register(smb, &rpc_epmapper_ops)) {
DEBUG(1,("Failed to register epmapper endpoint\n"));
}
}

View File

@ -0,0 +1,92 @@
/*
Unix SMB/CIFS implementation.
server side dcerpc handle code
Copyright (C) Andrew Tridgell 2003
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
/*
allocate a new rpc handle
*/
struct dcesrv_handle *dcesrv_handle_new(struct dcesrv_state *dce,
uint8 handle_type)
{
TALLOC_CTX *mem_ctx;
struct dcesrv_handle *h;
mem_ctx = talloc_init("rpc handle type %d\n", handle_type);
if (!mem_ctx) {
return NULL;
}
h = talloc(mem_ctx, sizeof(*h));
if (!h) {
talloc_destroy(mem_ctx);
return NULL;
}
h->mem_ctx = mem_ctx;
h->data = NULL;
memset(h->wire_handle.data, 'H', sizeof(h->wire_handle.data));
strncpy(h->wire_handle.data, dce->ndr->name, 11);
h->wire_handle.data[11] = handle_type;
/* TODO: check for wraparound here */
SIVAL(&h->wire_handle.data, 12, random());
SIVAL(&h->wire_handle.data, 16, dce->next_handle);
dce->next_handle++;
DLIST_ADD(dce->handles, h);
return h;
}
/*
destroy a rpc handle
*/
void dcesrv_handle_destroy(struct dcesrv_state *dce,
struct dcesrv_handle *h)
{
DLIST_REMOVE(dce->handles, h);
talloc_destroy(h->mem_ctx);
}
/*
find an internal handle given a wire handle. If the wire handle is NULL then
allocate a new handle
*/
struct dcesrv_handle *dcesrv_handle_fetch(struct dcesrv_state *dce,
struct policy_handle *p,
uint8 handle_type)
{
struct dcesrv_handle *h;
if (all_zero(p->data, sizeof(p->data))) {
return dcesrv_handle_new(dce, handle_type);
}
for (h=dce->handles; h; h=h->next) {
if (memcmp(h->wire_handle.data, p->data, sizeof(p->data)) == 0) {
return h;
}
}
return NULL;
}

View File

@ -130,15 +130,15 @@ static BOOL test_Map(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
twr->towers.floors[2].lhs.protocol = EPM_PROTOCOL_RPC_C;
twr->towers.floors[2].lhs.info.lhs_data = data_blob(NULL, 0);
twr->towers.floors[2].rhs.rhs_data = data_blob_talloc(p->mem_ctx, NULL, 2);
twr->towers.floors[2].rhs.rhs_data = data_blob_talloc_zero(p->mem_ctx, 2);
twr->towers.floors[3].lhs.protocol = EPM_PROTOCOL_TCP;
twr->towers.floors[3].lhs.info.lhs_data = data_blob(NULL, 0);
twr->towers.floors[3].rhs.rhs_data = data_blob_talloc(p->mem_ctx, NULL, 2);
twr->towers.floors[3].rhs.rhs_data = data_blob_talloc_zero(p->mem_ctx, 2);
twr->towers.floors[4].lhs.protocol = EPM_PROTOCOL_IP;
twr->towers.floors[4].lhs.info.lhs_data = data_blob(NULL, 0);
twr->towers.floors[4].rhs.rhs_data = data_blob_talloc(p->mem_ctx, NULL, 4);
twr->towers.floors[4].rhs.rhs_data = data_blob_talloc_zero(p->mem_ctx, 4);
status = dcerpc_epm_Map(p, mem_ctx, &r);
if (NT_STATUS_IS_OK(status) && r.out.status == 0) {
@ -151,7 +151,7 @@ static BOOL test_Map(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
twr->towers.floors[3].lhs.protocol = EPM_PROTOCOL_HTTP;
twr->towers.floors[3].lhs.info.lhs_data = data_blob(NULL, 0);
twr->towers.floors[3].rhs.rhs_data = data_blob_talloc(p->mem_ctx, NULL, 2);
twr->towers.floors[3].rhs.rhs_data = data_blob_talloc_zero(p->mem_ctx, 2);
status = dcerpc_epm_Map(p, mem_ctx, &r);
if (NT_STATUS_IS_OK(status) && r.out.status == 0) {
@ -164,11 +164,11 @@ static BOOL test_Map(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
twr->towers.floors[3].lhs.protocol = EPM_PROTOCOL_SMB;
twr->towers.floors[3].lhs.info.lhs_data = data_blob(NULL, 0);
twr->towers.floors[3].rhs.rhs_data = data_blob_talloc(p->mem_ctx, NULL, 2);
twr->towers.floors[3].rhs.rhs_data = data_blob_talloc_zero(p->mem_ctx, 2);
twr->towers.floors[4].lhs.protocol = EPM_PROTOCOL_NETBIOS;
twr->towers.floors[4].lhs.info.lhs_data = data_blob(NULL, 0);
twr->towers.floors[4].rhs.rhs_data = data_blob_talloc(p->mem_ctx, NULL, 2);
twr->towers.floors[4].rhs.rhs_data = data_blob_talloc_zero(p->mem_ctx, 2);
status = dcerpc_epm_Map(p, mem_ctx, &r);
if (NT_STATUS_IS_OK(status) && r.out.status == 0) {