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 \
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_ */
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
*******************************************************************/
#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)
{
**/
/**
- * 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;
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)
}
+/*
+ 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
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);
+}
/** @} */
}
#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;
+}
+
} 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 */
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;
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;
(*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);
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);
}
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;
}
}
+/*
+ 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
*/
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;
}
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;
}
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;
}
/* 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 */
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;
}
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;
}
+/*
+ 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;
}
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 {
} 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 */
} *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 */
/* 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;
};
/* 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 **);
};
}
+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
};
/*
--- /dev/null
+/*
+ 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"));
+ }
+}
--- /dev/null
+/*
+ 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;
+}
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) {
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) {
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) {