mirror of
https://github.com/samba-team/samba.git
synced 2025-02-23 09:57:40 +03:00
s3:rpc_client: add dcerpc_binding_handle backend
metze
This commit is contained in:
parent
b34209006f
commit
2c0e296dd7
@ -570,6 +570,7 @@ LIBMSRPC_GEN_OBJ = librpc/gen_ndr/cli_lsa.o \
|
||||
librpc/gen_ndr/cli_drsuapi.o \
|
||||
librpc/gen_ndr/cli_spoolss.o \
|
||||
../librpc/rpc/dcerpc_util.o \
|
||||
../librpc/rpc/binding_handle.o \
|
||||
librpc/rpc/dcerpc_helpers.o \
|
||||
$(LIBNDR_GEN_OBJ) \
|
||||
$(RPCCLIENT_NDR_OBJ)
|
||||
|
@ -104,10 +104,13 @@ struct rpc_cli_transport {
|
||||
void *priv;
|
||||
};
|
||||
|
||||
struct dcerpc_binding_handle;
|
||||
|
||||
struct rpc_pipe_client {
|
||||
struct rpc_pipe_client *prev, *next;
|
||||
|
||||
struct rpc_cli_transport *transport;
|
||||
struct dcerpc_binding_handle *binding_handle;
|
||||
|
||||
struct ndr_syntax_id abstract_syntax;
|
||||
struct ndr_syntax_id transfer_syntax;
|
||||
|
@ -153,4 +153,132 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth,
|
||||
DATA_BLOB *raw_pkt,
|
||||
size_t *pad_len);
|
||||
|
||||
struct dcerpc_binding_handle;
|
||||
struct GUID;
|
||||
struct ndr_interface_table;
|
||||
struct ndr_interface_call;
|
||||
struct ndr_push;
|
||||
struct ndr_pull;
|
||||
struct tevent_context;
|
||||
|
||||
/*
|
||||
* This is just a hack this should never be used in code,
|
||||
* but it's needed to build the compat stubs for now
|
||||
*/
|
||||
struct __do_not_use_dcerpc_pipe {
|
||||
struct dcerpc_binding_handle *binding_handle;
|
||||
};
|
||||
#define dcerpc_pipe __do_not_use_dcerpc_pipe
|
||||
|
||||
|
||||
struct dcerpc_binding_handle_ops {
|
||||
const char *name;
|
||||
|
||||
bool (*is_connected)(struct dcerpc_binding_handle *h);
|
||||
|
||||
struct tevent_req *(*raw_call_send)(TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct dcerpc_binding_handle *h,
|
||||
const struct GUID *object,
|
||||
uint32_t opnum,
|
||||
uint32_t in_flags,
|
||||
const uint8_t *in_data,
|
||||
size_t in_length);
|
||||
NTSTATUS (*raw_call_recv)(struct tevent_req *req,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
uint8_t **out_data,
|
||||
size_t *out_length,
|
||||
uint32_t *out_flags);
|
||||
|
||||
struct tevent_req *(*disconnect_send)(TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct dcerpc_binding_handle *h);
|
||||
NTSTATUS (*disconnect_recv)(struct tevent_req *req);
|
||||
|
||||
/* TODO: remove the following functions */
|
||||
bool (*push_bigendian)(struct dcerpc_binding_handle *h);
|
||||
bool (*ref_alloc)(struct dcerpc_binding_handle *h);
|
||||
bool (*use_ndr64)(struct dcerpc_binding_handle *h);
|
||||
void (*do_ndr_print)(struct dcerpc_binding_handle *h,
|
||||
int ndr_flags,
|
||||
const void *struct_ptr,
|
||||
const struct ndr_interface_call *call);
|
||||
void (*ndr_push_failed)(struct dcerpc_binding_handle *h,
|
||||
NTSTATUS error,
|
||||
const void *struct_ptr,
|
||||
const struct ndr_interface_call *call);
|
||||
void (*ndr_pull_failed)(struct dcerpc_binding_handle *h,
|
||||
NTSTATUS error,
|
||||
const DATA_BLOB *blob,
|
||||
const struct ndr_interface_call *call);
|
||||
NTSTATUS (*ndr_validate_in)(struct dcerpc_binding_handle *h,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const DATA_BLOB *blob,
|
||||
const struct ndr_interface_call *call);
|
||||
NTSTATUS (*ndr_validate_out)(struct dcerpc_binding_handle *h,
|
||||
struct ndr_pull *pull_in,
|
||||
const void *struct_ptr,
|
||||
const struct ndr_interface_call *call);
|
||||
};
|
||||
|
||||
struct dcerpc_binding_handle *_dcerpc_binding_handle_create(TALLOC_CTX *mem_ctx,
|
||||
const struct dcerpc_binding_handle_ops *ops,
|
||||
const struct GUID *object,
|
||||
const struct ndr_interface_table *table,
|
||||
void *pstate,
|
||||
size_t psize,
|
||||
const char *type,
|
||||
const char *location);
|
||||
#define dcerpc_binding_handle_create(mem_ctx, ops, object, table, \
|
||||
state, type, location) \
|
||||
_dcerpc_binding_handle_create(mem_ctx, ops, object, table, \
|
||||
state, sizeof(type), #type, location)
|
||||
|
||||
void *_dcerpc_binding_handle_data(struct dcerpc_binding_handle *h);
|
||||
#define dcerpc_binding_handle_data(_h, _type) \
|
||||
talloc_get_type_abort(_dcerpc_binding_handle_data(_h), _type)
|
||||
|
||||
_DEPRECATED_ void dcerpc_binding_handle_set_ref_alloc(struct dcerpc_binding_handle *h,
|
||||
bool ref_alloc);
|
||||
|
||||
_DEPRECATED_ void dcerpc_binding_handle_set_sync_ev(struct dcerpc_binding_handle *h,
|
||||
struct tevent_context *ev);
|
||||
|
||||
bool dcerpc_binding_handle_is_connected(struct dcerpc_binding_handle *h);
|
||||
|
||||
struct tevent_req *dcerpc_binding_handle_raw_call_send(TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct dcerpc_binding_handle *h,
|
||||
const struct GUID *object,
|
||||
uint32_t opnum,
|
||||
uint32_t in_flags,
|
||||
const uint8_t *in_data,
|
||||
size_t in_length);
|
||||
NTSTATUS dcerpc_binding_handle_raw_call_recv(struct tevent_req *req,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
uint8_t **out_data,
|
||||
size_t *out_length,
|
||||
uint32_t *out_flags);
|
||||
|
||||
struct tevent_req *dcerpc_binding_handle_disconnect_send(TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct dcerpc_binding_handle *h);
|
||||
NTSTATUS dcerpc_binding_handle_disconnect_recv(struct tevent_req *req);
|
||||
|
||||
struct tevent_req *dcerpc_binding_handle_call_send(TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct dcerpc_binding_handle *h,
|
||||
const struct GUID *object,
|
||||
const struct ndr_interface_table *table,
|
||||
uint32_t opnum,
|
||||
TALLOC_CTX *r_mem,
|
||||
void *r_ptr);
|
||||
NTSTATUS dcerpc_binding_handle_call_recv(struct tevent_req *req);
|
||||
NTSTATUS dcerpc_binding_handle_call(struct dcerpc_binding_handle *h,
|
||||
const struct GUID *object,
|
||||
const struct ndr_interface_table *table,
|
||||
uint32_t opnum,
|
||||
TALLOC_CTX *r_mem,
|
||||
void *r_ptr);
|
||||
|
||||
#endif /* __DCERPC_H__ */
|
||||
|
@ -2019,6 +2019,226 @@ bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
|
||||
return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
|
||||
}
|
||||
|
||||
struct rpccli_bh_state {
|
||||
struct rpc_pipe_client *rpc_cli;
|
||||
};
|
||||
|
||||
static bool rpccli_bh_is_connected(struct dcerpc_binding_handle *h)
|
||||
{
|
||||
struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
|
||||
struct rpccli_bh_state);
|
||||
|
||||
return rpccli_is_connected(hs->rpc_cli);
|
||||
}
|
||||
|
||||
struct rpccli_bh_raw_call_state {
|
||||
DATA_BLOB in_data;
|
||||
DATA_BLOB out_data;
|
||||
uint32_t out_flags;
|
||||
};
|
||||
|
||||
static void rpccli_bh_raw_call_done(struct tevent_req *subreq);
|
||||
|
||||
static struct tevent_req *rpccli_bh_raw_call_send(TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct dcerpc_binding_handle *h,
|
||||
const struct GUID *object,
|
||||
uint32_t opnum,
|
||||
uint32_t in_flags,
|
||||
const uint8_t *in_data,
|
||||
size_t in_length)
|
||||
{
|
||||
struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
|
||||
struct rpccli_bh_state);
|
||||
struct tevent_req *req;
|
||||
struct rpccli_bh_raw_call_state *state;
|
||||
bool ok;
|
||||
struct tevent_req *subreq;
|
||||
|
||||
req = tevent_req_create(mem_ctx, &state,
|
||||
struct rpccli_bh_raw_call_state);
|
||||
if (req == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
state->in_data.data = discard_const_p(uint8_t, in_data);
|
||||
state->in_data.length = in_length;
|
||||
|
||||
ok = rpccli_bh_is_connected(h);
|
||||
if (!ok) {
|
||||
tevent_req_nterror(req, NT_STATUS_INVALID_CONNECTION);
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
|
||||
subreq = rpc_api_pipe_req_send(state, ev, hs->rpc_cli,
|
||||
opnum, &state->in_data);
|
||||
if (tevent_req_nomem(subreq, req)) {
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
tevent_req_set_callback(subreq, rpccli_bh_raw_call_done, req);
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
static void rpccli_bh_raw_call_done(struct tevent_req *subreq)
|
||||
{
|
||||
struct tevent_req *req =
|
||||
tevent_req_callback_data(subreq,
|
||||
struct tevent_req);
|
||||
struct rpccli_bh_raw_call_state *state =
|
||||
tevent_req_data(req,
|
||||
struct rpccli_bh_raw_call_state);
|
||||
NTSTATUS status;
|
||||
|
||||
state->out_flags = 0;
|
||||
|
||||
/* TODO: support bigendian responses */
|
||||
|
||||
status = rpc_api_pipe_req_recv(subreq, state, &state->out_data);
|
||||
TALLOC_FREE(subreq);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
tevent_req_nterror(req, status);
|
||||
return;
|
||||
}
|
||||
|
||||
tevent_req_done(req);
|
||||
}
|
||||
|
||||
static NTSTATUS rpccli_bh_raw_call_recv(struct tevent_req *req,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
uint8_t **out_data,
|
||||
size_t *out_length,
|
||||
uint32_t *out_flags)
|
||||
{
|
||||
struct rpccli_bh_raw_call_state *state =
|
||||
tevent_req_data(req,
|
||||
struct rpccli_bh_raw_call_state);
|
||||
NTSTATUS status;
|
||||
|
||||
if (tevent_req_is_nterror(req, &status)) {
|
||||
tevent_req_received(req);
|
||||
return status;
|
||||
}
|
||||
|
||||
*out_data = talloc_move(mem_ctx, &state->out_data.data);
|
||||
*out_length = state->out_data.length;
|
||||
*out_flags = state->out_flags;
|
||||
tevent_req_received(req);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
struct rpccli_bh_disconnect_state {
|
||||
uint8_t _dummy;
|
||||
};
|
||||
|
||||
static struct tevent_req *rpccli_bh_disconnect_send(TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct dcerpc_binding_handle *h)
|
||||
{
|
||||
struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
|
||||
struct rpccli_bh_state);
|
||||
struct tevent_req *req;
|
||||
struct rpccli_bh_disconnect_state *state;
|
||||
bool ok;
|
||||
|
||||
req = tevent_req_create(mem_ctx, &state,
|
||||
struct rpccli_bh_disconnect_state);
|
||||
if (req == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ok = rpccli_bh_is_connected(h);
|
||||
if (!ok) {
|
||||
tevent_req_nterror(req, NT_STATUS_INVALID_CONNECTION);
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: do a real async disconnect ...
|
||||
*
|
||||
* For now the caller needs to free rpc_cli
|
||||
*/
|
||||
hs->rpc_cli = NULL;
|
||||
|
||||
tevent_req_done(req);
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
|
||||
static NTSTATUS rpccli_bh_disconnect_recv(struct tevent_req *req)
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
if (tevent_req_is_nterror(req, &status)) {
|
||||
tevent_req_received(req);
|
||||
return status;
|
||||
}
|
||||
|
||||
tevent_req_received(req);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static bool rpccli_bh_ref_alloc(struct dcerpc_binding_handle *h)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void rpccli_bh_do_ndr_print(struct dcerpc_binding_handle *h,
|
||||
int ndr_flags,
|
||||
const void *_struct_ptr,
|
||||
const struct ndr_interface_call *call)
|
||||
{
|
||||
void *struct_ptr = discard_const(_struct_ptr);
|
||||
|
||||
if (DEBUGLEVEL < 10) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ndr_flags & NDR_IN) {
|
||||
ndr_print_function_debug(call->ndr_print,
|
||||
call->name,
|
||||
ndr_flags,
|
||||
struct_ptr);
|
||||
}
|
||||
if (ndr_flags & NDR_OUT) {
|
||||
ndr_print_function_debug(call->ndr_print,
|
||||
call->name,
|
||||
ndr_flags,
|
||||
struct_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct dcerpc_binding_handle_ops rpccli_bh_ops = {
|
||||
.name = "rpccli",
|
||||
.is_connected = rpccli_bh_is_connected,
|
||||
.raw_call_send = rpccli_bh_raw_call_send,
|
||||
.raw_call_recv = rpccli_bh_raw_call_recv,
|
||||
.disconnect_send = rpccli_bh_disconnect_send,
|
||||
.disconnect_recv = rpccli_bh_disconnect_recv,
|
||||
|
||||
.ref_alloc = rpccli_bh_ref_alloc,
|
||||
.do_ndr_print = rpccli_bh_do_ndr_print,
|
||||
};
|
||||
|
||||
/* initialise a rpc_pipe_client binding handle */
|
||||
static struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c)
|
||||
{
|
||||
struct dcerpc_binding_handle *h;
|
||||
struct rpccli_bh_state *hs;
|
||||
|
||||
h = dcerpc_binding_handle_create(c,
|
||||
&rpccli_bh_ops,
|
||||
NULL,
|
||||
NULL, /* TODO */
|
||||
&hs,
|
||||
struct rpccli_bh_state,
|
||||
__location__);
|
||||
if (h == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
hs->rpc_cli = c;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16])
|
||||
{
|
||||
struct auth_ntlmssp_state *a = NULL;
|
||||
@ -2261,6 +2481,12 @@ static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
|
||||
|
||||
result->transport->transport = NCACN_IP_TCP;
|
||||
|
||||
result->binding_handle = rpccli_bh_create(result);
|
||||
if (result->binding_handle == NULL) {
|
||||
TALLOC_FREE(result);
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
*presult = result;
|
||||
return NT_STATUS_OK;
|
||||
|
||||
@ -2478,6 +2704,12 @@ NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
|
||||
|
||||
result->transport->transport = NCALRPC;
|
||||
|
||||
result->binding_handle = rpccli_bh_create(result);
|
||||
if (result->binding_handle == NULL) {
|
||||
TALLOC_FREE(result);
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
*presult = result;
|
||||
return NT_STATUS_OK;
|
||||
|
||||
@ -2566,6 +2798,12 @@ static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
|
||||
DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
|
||||
talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
|
||||
|
||||
result->binding_handle = rpccli_bh_create(result);
|
||||
if (result->binding_handle == NULL) {
|
||||
TALLOC_FREE(result);
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
*presult = result;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
@ -2625,6 +2863,12 @@ NTSTATUS rpc_pipe_open_local(TALLOC_CTX *mem_ctx,
|
||||
|
||||
result->transport->transport = NCACN_INTERNAL;
|
||||
|
||||
result->binding_handle = rpccli_bh_create(result);
|
||||
if (result->binding_handle == NULL) {
|
||||
TALLOC_FREE(result);
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
*presult = result;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user