1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +03:00

* the RPC-ECHO pipe now works in smbd, as long as the data sizes

don't cause fragmented pdus (I'll add fragments shortly)

 * change data_blob_talloc() to not zero memory when the 2nd argument
   is NULL. The zeroing just masks bugs, and can't even allow a DOS
   attack

 * modified pidl to ensure that [ref] arguments to the out side of
   functions are allocated when parsing the in side. This allows rpc
   backends to assume that [ref] variables are all setup. Doesn't work
   correctly for [ref] arrays yet

 * changed DLIST_ADD_END() to take the type instead of a tmp
   variable. This means you don't need to declare a silly tmp variable in
   the caller
This commit is contained in:
Andrew Tridgell 0001-01-01 00:00:00 +00:00
parent 4929c53bc8
commit 46e0a35819
21 changed files with 485 additions and 68 deletions

View File

@ -324,7 +324,6 @@ static NTSTATUS make_auth_context_text_list(struct auth_context **auth_context,
{
auth_methods *list = NULL;
auth_methods *t = NULL;
auth_methods *tmp;
int i;
NTSTATUS nt_status;
@ -358,7 +357,7 @@ static NTSTATUS make_auth_context_text_list(struct auth_context **auth_context,
if (NT_STATUS_IS_OK(builtin_auth_init_functions[i].init(*auth_context, module_params, &t))) {
DEBUG(5,("make_auth_context_text_list: auth method %s has a valid init\n",
*text_list));
DLIST_ADD_END(list, t, tmp);
DLIST_ADD_END(list, t, auth_methods *);
} else {
DEBUG(0,("make_auth_context_text_list: auth method %s did not correctly init\n",
*text_list));

View File

@ -208,7 +208,6 @@ static struct chat_struct *make_pw_chat(char *p)
fstring reply;
struct chat_struct *list = NULL;
struct chat_struct *t;
struct chat_struct *tmp;
while (1) {
t = (struct chat_struct *)malloc(sizeof(*t));
@ -219,7 +218,7 @@ static struct chat_struct *make_pw_chat(char *p)
ZERO_STRUCTP(t);
DLIST_ADD_END(list, t, tmp);
DLIST_ADD_END(list, t, struct chat_struct *);
if (!next_token(&p, prompt, NULL, sizeof(fstring)))
break;

View File

@ -1256,6 +1256,11 @@ sub ParseFunctionPull($)
if (util::has_property($e, "in")) {
ParseFunctionElementPull($e, "in");
}
# we need to allocate any reference output variables, so that
# a dcerpc backend can be sure they are non-null
if (util::has_property($e, "out") && util::has_property($e, "ref")) {
pidl "\tNDR_ALLOC(ndr, r->out.$e->{NAME});\n";
}
}
pidl "\nndr_out:\n";

View File

@ -114,5 +114,4 @@ struct cli_client
#define CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK 0x0004
#define CLI_FULL_CONNECTION_USE_DFS 0x0008
#include "cli_context.h"
#endif /* _CLIENT_H */

View File

@ -42,6 +42,44 @@ struct user_context {
struct user_struct *vuser;
};
/* each backend has to be one one of the following 3 basic types. In
* earlier versions of Samba backends needed to handle all types, now
* we implement them separately. */
enum ntvfs_type {NTVFS_DISK, NTVFS_PRINT, NTVFS_IPC};
/* we need a forward declaration of the ntvfs_ops strucutre to prevent
include recursion */
struct ntvfs_ops;
struct tcon_context {
struct tcon_context *next, *prev;
/* the server context that this was created on */
struct server_context *smb;
/* a talloc context for all data in this structure */
TALLOC_CTX *mem_ctx;
/* a private structure used by the active NTVFS backend */
void *ntvfs_private;
uint16 cnum; /* an index passed over the wire (the TID) */
int service;
enum ntvfs_type type;
BOOL read_only;
BOOL admin_user;
/* the NTVFS operations - see source/ntvfs/ and include/ntvfs.h for details */
struct ntvfs_ops *ntvfs_ops;
/* the reported filesystem type */
char *fs_type;
/* the reported device type */
char *dev_type;
};
/* the context for a single SMB request. This is passed to any request-context
functions */
struct request_context {
@ -343,3 +381,4 @@ struct server_context {
struct model_ops *model_ops;
};

View File

@ -57,16 +57,17 @@ do { \
} while (0)
/* hook into the end of the list - needs a tmp pointer */
#define DLIST_ADD_END(list, p, tmp) \
#define DLIST_ADD_END(list, p, type) \
do { \
if (!(list)) { \
(list) = (p); \
(p)->next = (p)->prev = NULL; \
} else { \
for ((tmp) = (list); (tmp)->next; (tmp) = (tmp)->next) ; \
(tmp)->next = (p); \
type tmp; \
for (tmp = (list); tmp->next; tmp = tmp->next) ; \
tmp->next = (p); \
(p)->next = NULL; \
(p)->prev = (tmp); \
(p)->prev = tmp; \
} \
} while (0)

View File

@ -773,6 +773,11 @@ extern int errno;
#include "librpc/ndr/libndr.h"
#include "librpc/rpc/dcerpc.h"
#include "rpc_server/dcerpc_server.h"
#include "context.h"
#include "ntvfs.h"
#include "cli_context.h"
/* used in net.c */
struct functable {

View File

@ -23,12 +23,6 @@
/* each backend has to be one one of the following 3 basic types. In
* earlier versions of Samba backends needed to handle all types, now
* we implement them separately. */
enum ntvfs_type {NTVFS_DISK, NTVFS_PRINT, NTVFS_IPC};
/* the ntvfs operations structure - contains function pointers to
the backend implementations of each operation */
struct ntvfs_ops {

View File

@ -421,10 +421,7 @@ struct vuid_cache {
#include "smb_acls.h"
#include "enums.h"
#include "events.h"
#include "rpc_server/dcerpc_server.h"
#include "context.h"
#include "smb_interfaces.h"
#include "ntvfs.h"
typedef struct smb_vfs_handle_struct
{
@ -435,34 +432,6 @@ typedef struct smb_vfs_handle_struct
} smb_vfs_handle_struct;
struct tcon_context {
struct tcon_context *next, *prev;
/* the server context that this was created on */
struct server_context *smb;
/* a talloc context for all data in this structure */
TALLOC_CTX *mem_ctx;
/* a private structure used by the active NTVFS backend */
void *ntvfs_private;
uint16 cnum; /* an index passed over the wire (the TID) */
int service;
enum ntvfs_type type;
BOOL read_only;
BOOL admin_user;
/* the NTVFS operations - see source/ntvfs/ and include/ntvfs.h for details */
struct ntvfs_ops *ntvfs_ops;
/* the reported filesystem type */
char *fs_type;
/* the reported device type */
char *dev_type;
};
struct current_user
{
struct tcon_context *conn;

View File

@ -67,12 +67,12 @@ DATA_BLOB data_blob_talloc(TALLOC_CTX *mem_ctx, const void *p, size_t length)
}
if (p == NULL) {
/* note that we do NOT zero memory in this case */
ret.data = talloc(mem_ctx, length);
if (ret.data == NULL) {
smb_panic("data_blob_talloc: talloc_memdup failed.\n");
}
ret.length = length;
memset(ret.data, 0, ret.length);
ret.free = NULL;
return ret;
}

View File

@ -710,7 +710,6 @@ TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern)
TDB_DATA key, next;
TDB_LIST_NODE *list = NULL;
TDB_LIST_NODE *rec = NULL;
TDB_LIST_NODE *tmp = NULL;
for (key = tdb_firstkey(tdb); key.dptr; key = next) {
/* duplicate key string to ensure null-termination */
@ -731,7 +730,7 @@ TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern)
rec->node_key = key;
DLIST_ADD_END(list, rec, tmp);
DLIST_ADD_END(list, rec, TDB_LIST_NODE *);
DEBUG(18, ("checking %s matched pattern %s\n", key_str, pattern));
} else {

View File

@ -81,6 +81,10 @@ interface dcerpc
const int DCERPC_FAULT_OP_RNG_ERROR = 0x1c010002;
/* we return this fault when we haven't yet run the test
to see what fault w2k3 returns in this case */
const int DCERPC_FAULT_TODO = 0x00000042;
typedef struct {
uint32 alloc_hint;
uint16 context_id;

View File

@ -43,7 +43,7 @@ size_t ndr_align_size(uint32 offset, size_t n)
/*
initialise a ndr parse structure from a data blob
*/
struct ndr_pull *ndr_pull_init_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
struct ndr_pull *ndr_pull_init_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
{
struct ndr_pull *ndr;

View File

@ -526,6 +526,11 @@ static NTSTATUS ipc_trans(struct request_context *req, struct smb_trans2 *trans)
return NT_STATUS_INVALID_HANDLE;
}
trans->out.data = data_blob_talloc(req->mem_ctx, NULL, trans->in.max_data);
if (!trans->out.data.data) {
return NT_STATUS_NO_MEMORY;
}
/* pass the data to the dcerpc server. Note that we don't
expect this to fail, and things like NDR faults are not
reported at this stage. Those sorts of errors happen in the

View File

@ -385,7 +385,7 @@ static NTSTATUS make_pdb_context(struct pdb_context **context)
NTSTATUS make_pdb_context_list(struct pdb_context **context, const char **selected)
{
int i = 0;
struct pdb_methods *curmethods, *tmpmethods;
struct pdb_methods *curmethods;
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
if (!NT_STATUS_IS_OK(nt_status = make_pdb_context(context))) {
@ -401,7 +401,7 @@ NTSTATUS make_pdb_context_list(struct pdb_context **context, const char **select
return nt_status;
}
curmethods->parent = *context;
DLIST_ADD_END((*context)->pdb_methods, curmethods, tmpmethods);
DLIST_ADD_END((*context)->pdb_methods, curmethods, struct pdb_methods *);
i++;
}

View File

@ -212,7 +212,7 @@ static BOOL copy_notify2_msg( SPOOLSS_NOTIFY_MSG *to, SPOOLSS_NOTIFY_MSG *from )
static void send_spoolss_notify2_msg(SPOOLSS_NOTIFY_MSG *msg)
{
struct notify_queue *pnqueue, *tmp_ptr;
struct notify_queue *pnqueue;
/*
* Ensure we only have one message unique to each name/type/field/id/flags
@ -262,7 +262,7 @@ to notify_queue_head\n", msg->type, msg->field, msg->printer));
* the messages are sent in the order they were received. JRA.
*/
DLIST_ADD_END(notify_queue_head, pnqueue, tmp_ptr);
DLIST_ADD_END(notify_queue_head, pnqueue, struct notify_queue *);
}
static void send_notify_field_values(const char *printer_name, uint32 type,

View File

@ -30,7 +30,7 @@ static const struct dcesrv_endpoint_ops *find_endpoint(struct server_context *sm
{
struct dce_endpoint *ep;
for (ep=smb->dcesrv.endpoint_list; ep; ep=ep->next) {
if (ep->endpoint_ops->query(endpoint)) {
if (ep->endpoint_ops->query_endpoint(endpoint)) {
return ep->endpoint_ops;
}
}
@ -86,6 +86,7 @@ NTSTATUS dcesrv_endpoint_connect(struct server_context *smb,
(*p)->endpoint = *endpoint;
(*p)->ops = ops;
(*p)->private = NULL;
(*p)->call_list = NULL;
/* make sure the endpoint server likes the connection */
status = ops->connect(*p);
@ -107,23 +108,318 @@ void dcesrv_endpoint_disconnect(struct dcesrv_state *p)
talloc_destroy(p->mem_ctx);
}
/*
return a dcerpc fault
*/
static NTSTATUS dcesrv_fault(struct dcesrv_call_state *call, uint32 fault_code)
{
struct ndr_push *push;
struct dcerpc_packet pkt;
NTSTATUS status;
/* setup a bind_ack */
pkt.rpc_vers = 5;
pkt.rpc_vers_minor = 0;
pkt.drep[0] = 0x10; /* Little endian */
pkt.drep[1] = 0;
pkt.drep[2] = 0;
pkt.drep[3] = 0;
pkt.auth_length = 0;
pkt.call_id = call->pkt.call_id;
pkt.ptype = DCERPC_PKT_FAULT;
pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
pkt.u.fault.alloc_hint = 0;
pkt.u.fault.context_id = 0;
pkt.u.fault.cancel_count = 0;
pkt.u.fault.status = fault_code;
/* now form the NDR for the bind_ack */
push = ndr_push_init_ctx(call->mem_ctx);
if (!push) {
return NT_STATUS_NO_MEMORY;
}
status = ndr_push_dcerpc_packet(push, NDR_SCALARS|NDR_BUFFERS, &pkt);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
call->data = ndr_push_blob(push);
SSVAL(call->data.data, DCERPC_FRAG_LEN_OFFSET, call->data.length);
return NT_STATUS_OK;
}
/*
handle a bind request
*/
static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
{
const char *uuid, *transfer_syntax;
uint32 if_version, transfer_syntax_version;
struct dcerpc_packet pkt;
struct ndr_push *push;
NTSTATUS status;
if (call->pkt.u.bind.num_contexts != 1 ||
call->pkt.u.bind.ctx_list[0].num_transfer_syntaxes < 1) {
return dcesrv_fault(call, DCERPC_FAULT_TODO);
}
if_version = call->pkt.u.bind.ctx_list[0].abstract_syntax.major_version;
uuid = GUID_string(call->mem_ctx, &call->pkt.u.bind.ctx_list[0].abstract_syntax.uuid);
if (!uuid) {
return dcesrv_fault(call, DCERPC_FAULT_TODO);
}
transfer_syntax_version = call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].major_version;
transfer_syntax = GUID_string(call->mem_ctx,
&call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].uuid);
if (!transfer_syntax ||
strcasecmp(NDR_GUID, transfer_syntax) != 0 ||
NDR_GUID_VERSION != transfer_syntax_version) {
/* we only do NDR encoded dcerpc */
return dcesrv_fault(call, DCERPC_FAULT_TODO);
}
if (!call->dce->ops->set_interface(call->dce, uuid, if_version)) {
DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid, if_version));
/* we don't know about that interface */
return dcesrv_fault(call, DCERPC_FAULT_TODO);
}
/* setup a bind_ack */
pkt.rpc_vers = 5;
pkt.rpc_vers_minor = 0;
pkt.drep[0] = 0x10; /* Little endian */
pkt.drep[1] = 0;
pkt.drep[2] = 0;
pkt.drep[3] = 0;
pkt.auth_length = 0;
pkt.call_id = call->pkt.call_id;
pkt.ptype = DCERPC_PKT_BIND_ACK;
pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
pkt.u.bind_ack.max_xmit_frag = 0x2000;
pkt.u.bind_ack.max_recv_frag = 0x2000;
pkt.u.bind_ack.assoc_group_id = call->pkt.u.bind.assoc_group_id;
pkt.u.bind_ack.secondary_address = talloc_asprintf(call->mem_ctx, "\\PIPE\\%s",
call->dce->ndr->name);
pkt.u.bind_ack.num_results = 1;
pkt.u.bind_ack.ctx_list = talloc(call->mem_ctx, sizeof(struct dcerpc_ack_ctx));
if (!pkt.u.bind_ack.ctx_list) {
return NT_STATUS_NO_MEMORY;
}
pkt.u.bind_ack.ctx_list[0].result = 0;
pkt.u.bind_ack.ctx_list[0].reason = 0;
GUID_from_string(uuid, &pkt.u.bind_ack.ctx_list[0].syntax.uuid);
pkt.u.bind_ack.ctx_list[0].syntax.major_version = if_version;
pkt.u.bind_ack.ctx_list[0].syntax.minor_version = 0;
pkt.u.bind_ack.auth_info = data_blob(NULL, 0);
/* now form the NDR for the bind_ack */
push = ndr_push_init_ctx(call->mem_ctx);
if (!push) {
return NT_STATUS_NO_MEMORY;
}
status = ndr_push_dcerpc_packet(push, NDR_SCALARS|NDR_BUFFERS, &pkt);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
call->data = ndr_push_blob(push);
SSVAL(call->data.data, DCERPC_FRAG_LEN_OFFSET, call->data.length);
return NT_STATUS_OK;
}
/*
handle a dcerpc request packet
*/
static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
{
struct ndr_pull *pull;
struct ndr_push *push;
uint16 opnum;
void *r;
NTSTATUS status;
DATA_BLOB stub;
struct dcerpc_packet pkt;
if (call->pkt.pfc_flags != (DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST)) {
/* we don't do fragments in the server yet */
return dcesrv_fault(call, DCERPC_FAULT_TODO);
}
opnum = call->pkt.u.request.opnum;
if (opnum >= call->dce->ndr->num_calls) {
return dcesrv_fault(call, DCERPC_FAULT_OP_RNG_ERROR);
}
pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call->mem_ctx);
if (!pull) {
return NT_STATUS_NO_MEMORY;
}
r = talloc(call->mem_ctx, call->dce->ndr->calls[opnum].struct_size);
if (!r) {
return NT_STATUS_NO_MEMORY;
}
/* unravel the NDR for the packet */
status = call->dce->ndr->calls[opnum].ndr_pull(pull, NDR_IN, r);
if (!NT_STATUS_IS_OK(status)) {
return dcesrv_fault(call, DCERPC_FAULT_TODO);
}
/* 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_TODO);
}
/* form the reply NDR */
push = ndr_push_init_ctx(call->mem_ctx);
if (!push) {
return NT_STATUS_NO_MEMORY;
}
status = call->dce->ndr->calls[opnum].ndr_push(push, NDR_OUT, r);
if (!NT_STATUS_IS_OK(status)) {
return dcesrv_fault(call, DCERPC_FAULT_TODO);
}
stub = ndr_push_blob(push);
/* form the dcerpc response packet */
pkt.rpc_vers = 5;
pkt.rpc_vers_minor = 0;
pkt.drep[0] = 0x10; /* Little endian */
pkt.drep[1] = 0;
pkt.drep[2] = 0;
pkt.drep[3] = 0;
pkt.auth_length = 0;
pkt.call_id = call->pkt.call_id;
pkt.ptype = DCERPC_PKT_RESPONSE;
pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
pkt.u.response.alloc_hint = stub.length;
pkt.u.response.context_id = call->pkt.u.request.context_id;
pkt.u.response.cancel_count = 0;
pkt.u.response.stub_and_verifier = stub;
push = ndr_push_init_ctx(call->mem_ctx);
if (!push) {
return NT_STATUS_NO_MEMORY;
}
status = ndr_push_dcerpc_packet(push, NDR_SCALARS|NDR_BUFFERS, &pkt);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
call->data = ndr_push_blob(push);
SSVAL(call->data.data, DCERPC_FRAG_LEN_OFFSET, call->data.length);
return NT_STATUS_OK;
}
/*
provide some input to a dcerpc endpoint server. This passes data
from a dcerpc client into the server
*/
NTSTATUS dcesrv_input(struct dcesrv_state *p, const DATA_BLOB *data)
NTSTATUS dcesrv_input(struct dcesrv_state *dce, const DATA_BLOB *data)
{
return NT_STATUS_NOT_IMPLEMENTED;
struct ndr_pull *ndr;
TALLOC_CTX *mem_ctx;
NTSTATUS status;
struct dcesrv_call_state *call;
mem_ctx = talloc_init("dcesrv_input");
if (!mem_ctx) {
return NT_STATUS_NO_MEMORY;
}
call = talloc(mem_ctx, sizeof(*call));
if (!call) {
talloc_destroy(mem_ctx);
return NT_STATUS_NO_MEMORY;
}
call->mem_ctx = mem_ctx;
call->dce = dce;
ndr = ndr_pull_init_blob(data, mem_ctx);
if (!ndr) {
talloc_destroy(mem_ctx);
return NT_STATUS_NO_MEMORY;
}
status = ndr_pull_dcerpc_packet(ndr, NDR_SCALARS|NDR_BUFFERS, &call->pkt);
if (!NT_STATUS_IS_OK(status)) {
talloc_destroy(mem_ctx);
return status;
}
/* TODO: at this point we should see if the packet is a
continuation of an existing call, but I'm too lazy for that
right now ... maybe tomorrow */
switch (call->pkt.ptype) {
case DCERPC_PKT_BIND:
status = dcesrv_bind(call);
break;
case DCERPC_PKT_REQUEST:
status = dcesrv_request(call);
break;
default:
status = NT_STATUS_INVALID_PARAMETER;
break;
}
/* if we are going to be sending a reply then add
it to the list of pending calls. We add it to the end to keep the call
list in the order we will answer */
if (NT_STATUS_IS_OK(status)) {
DLIST_ADD_END(dce->call_list, call, struct dcesrv_call_state *);
} else {
talloc_destroy(mem_ctx);
}
return status;
}
/*
retrieve some output from a dcerpc server. The amount of data that
is wanted is in data->length
is wanted is in data->length and data->data is already allocated
to hold that much data.
*/
NTSTATUS dcesrv_output(struct dcesrv_state *p, DATA_BLOB *data)
NTSTATUS dcesrv_output(struct dcesrv_state *dce, DATA_BLOB *data)
{
return NT_STATUS_NOT_IMPLEMENTED;
struct dcesrv_call_state *call;
call = dce->call_list;
if (!call) {
return NT_STATUS_FOOBAR;
}
if (data->length >= call->data.length) {
data->length = call->data.length;
}
memcpy(data->data, call->data.data, data->length);
call->data.length -= data->length;
call->data.data += data->length;
if (call->data.length == 0) {
/* we're done with this call */
DLIST_REMOVE(dce->call_list, call);
talloc_destroy(call->mem_ctx);
}
return NT_STATUS_OK;
}

View File

@ -32,6 +32,19 @@ struct dcesrv_endpoint {
} info;
};
struct dcesrv_state;
/* the dispatch functions for an interface take this form */
typedef NTSTATUS (*dcesrv_dispatch_fn_t)(struct dcesrv_state *, TALLOC_CTX *, void *);
/* the state of an ongoing dcerpc call */
struct dcesrv_call_state {
struct dcesrv_call_state *next, *prev;
struct dcesrv_state *dce;
TALLOC_CTX *mem_ctx;
struct dcerpc_packet pkt;
DATA_BLOB data;
};
/* the state associated with a dcerpc server connection */
struct dcesrv_state {
@ -43,15 +56,29 @@ struct dcesrv_state {
/* endpoint operations provided by the endpoint server */
const struct dcesrv_endpoint_ops *ops;
/* the ndr function table for the chosen interface */
const struct dcerpc_interface_table *ndr;
/* the dispatch table for the chosen interface. Must contain
enough entries for all entries in the ndr table */
const dcesrv_dispatch_fn_t *dispatch;
/* the state of the current calls */
struct dcesrv_call_state *call_list;
/* private data for the endpoint server */
void *private;
};
struct dcesrv_endpoint_ops {
/* the query function is used to ask an endpoint server if it
/* this function is used to ask an endpoint server if it
handles a particular endpoint */
BOOL (*query)(const struct dcesrv_endpoint *);
BOOL (*query_endpoint)(const struct dcesrv_endpoint *);
/* this function sets up the dispatch table for this
connection */
BOOL (*set_interface)(struct dcesrv_state *, const char *, uint32);
/* connect() is called when a connection is made to an endpoint */
NTSTATUS (*connect)(struct dcesrv_state *);

View File

@ -23,20 +23,94 @@
#include "includes.h"
static NTSTATUS echo_AddOne(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, struct echo_AddOne *r)
{
*r->out.v = *r->in.v + 1;
return NT_STATUS_OK;
}
static NTSTATUS echo_EchoData(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, struct echo_EchoData *r)
{
r->out.out_data = talloc(mem_ctx, r->in.len);
if (!r->out.out_data) {
return NT_STATUS_NO_MEMORY;
}
memcpy(r->out.out_data, r->in.in_data, r->in.len);
return NT_STATUS_OK;
}
static NTSTATUS echo_SinkData(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, struct echo_SinkData *r)
{
return NT_STATUS_OK;
}
static NTSTATUS echo_SourceData(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, struct echo_SourceData *r)
{
int i;
r->out.data = talloc(mem_ctx, r->in.len);
if (!r->out.data) {
return NT_STATUS_NO_MEMORY;
}
for (i=0;i<r->in.len;i++) {
r->out.data[i] = i;
}
return NT_STATUS_OK;
}
static NTSTATUS echo_TestCall(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, struct TestCall *r)
{
return NT_STATUS_BAD_NETWORK_NAME;
}
static NTSTATUS echo_TestCall2(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, struct TestCall2 *r)
{
return NT_STATUS_BAD_NETWORK_NAME;
}
/**************************************************************************
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)echo_AddOne,
(dcesrv_dispatch_fn_t)echo_EchoData,
(dcesrv_dispatch_fn_t)echo_SinkData,
(dcesrv_dispatch_fn_t)echo_SourceData,
(dcesrv_dispatch_fn_t)echo_TestCall,
(dcesrv_dispatch_fn_t)echo_TestCall2
};
/*
return True if we want to handle the given endpoint
*/
static BOOL op_query(const struct dcesrv_endpoint *ep)
static BOOL op_query_endpoint(const struct dcesrv_endpoint *ep)
{
return dcesrv_table_query(&dcerpc_table_rpcecho, 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_rpcecho.uuid) != 0 ||
if_version != dcerpc_table_rpcecho.if_version) {
DEBUG(2,("Attempt to use unknown interface %s/%d\n", uuid, if_version));
return False;
}
dce->ndr = &dcerpc_table_rpcecho;
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)
@ -51,7 +125,8 @@ static void op_disconnect(struct dcesrv_state *dce)
static const struct dcesrv_endpoint_ops rpc_echo_ops = {
op_query,
op_query_endpoint,
op_set_interface,
op_connect,
op_disconnect
};

View File

@ -1219,8 +1219,10 @@ static NTSTATUS trans2_backend(struct request_context *req, struct smb_trans2 *t
*/
static NTSTATUS trans_backend(struct request_context *req, struct smb_trans2 *trans)
{
return NT_STATUS_NOT_IMPLEMENTED;
if (!req->conn->ntvfs_ops->trans) {
return NT_STATUS_NOT_IMPLEMENTED;
}
return req->conn->ntvfs_ops->trans(req, trans);
}

View File

@ -710,7 +710,6 @@ TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern)
TDB_DATA key, next;
TDB_LIST_NODE *list = NULL;
TDB_LIST_NODE *rec = NULL;
TDB_LIST_NODE *tmp = NULL;
for (key = tdb_firstkey(tdb); key.dptr; key = next) {
/* duplicate key string to ensure null-termination */
@ -731,7 +730,7 @@ TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern)
rec->node_key = key;
DLIST_ADD_END(list, rec, tmp);
DLIST_ADD_END(list, rec, TDB_LIST_NODE *);
DEBUG(18, ("checking %s matched pattern %s\n", key_str, pattern));
} else {