return NULL;
}
- c->assoc = dcerpc_association_create(c, 0);
- if (c->assoc == NULL) {
- talloc_free(c);
- return NULL;
- }
- //c->conn = dcerpc_connection_create(c, c->assoc,
c->call_id = 1;
-// c->security_state.sec = dcerpc_security_allocate(c, c->conn,
-// DCERPC_AUTH_TYPE_NONE,
-// DCERPC_AUTH_LEVEL_NONE,
-// NULL);
-// if (c->security_state.sec == NULL) {
-// talloc_free(c);
-// return NULL;
-// }
c->security_state.auth_type = DCERPC_AUTH_TYPE_NONE;
c->security_state.auth_level = DCERPC_AUTH_LEVEL_NONE;
c->security_state.auth_context_id = 0;
return false;
}
+ if (!hs->p->conn->conn) {
+ return false;
+ }
+
return true;
}
struct dcerpc_bh_raw_call_state {
struct tevent_context *ev;
struct dcerpc_binding_handle *h;
+ struct dcerpc_call *call;
DATA_BLOB in_data;
DATA_BLOB out_data;
uint32_t out_flags;
};
-static void dcerpc_bh_raw_call_done(struct rpc_request *subreq);
+static void dcerpc_bh_raw_call_done(struct tevent_req *subreq);
static struct tevent_req *dcerpc_bh_raw_call_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct tevent_req *req;
struct dcerpc_bh_raw_call_state *state;
bool ok;
- struct rpc_request *subreq;
+ struct tevent_req *subreq;
+ bool bigendian = false;
req = tevent_req_create(mem_ctx, &state,
struct dcerpc_bh_raw_call_state);
return tevent_req_post(req, ev);
}
- subreq = dcerpc_request_send(state,
- hs->p,
- object,
- opnum,
- &state->in_data);
+ state->call = dcerpc_call_allocate(state, hs->p->conn->assoc,
+ hs->p->conn->security_state.sec,
+ hs->p->pres);
+ if (tevent_req_nomem(state->call, req)) {
+ return tevent_req_post(req, ev);
+ }
+
+ if (in_flags & LIBNDR_FLAG_BIGENDIAN) {
+ bigendian = true;
+ }
+
+ subreq = dcerpc_do_request_send(state, ev,
+ hs->p->conn->conn,
+ state->call,
+ object,
+ opnum,
+ &state->in_data,
+ bigendian);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
- subreq->async.callback = dcerpc_bh_raw_call_done;
- subreq->async.private_data = req;
+ tevent_req_set_callback(subreq, dcerpc_bh_raw_call_done, req);
return req;
}
-static void dcerpc_bh_raw_call_done(struct rpc_request *subreq)
+static void dcerpc_bh_raw_call_done(struct tevent_req *subreq)
{
struct tevent_req *req =
- talloc_get_type_abort(subreq->async.private_data,
+ tevent_req_callback_data(subreq,
struct tevent_req);
struct dcerpc_bh_raw_call_state *state =
tevent_req_data(req,
struct dcerpc_bh_raw_call_state);
NTSTATUS status;
- uint32_t fault_code;
-
- state->out_flags = 0;
- if (subreq->flags & DCERPC_PULL_BIGENDIAN) {
- state->out_flags |= LIBNDR_FLAG_BIGENDIAN;
- }
-
- fault_code = subreq->fault_code;
+ bool bigendian = false;
- status = dcerpc_request_recv(subreq, state, &state->out_data);
- if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
- status = dcerpc_fault_to_nt_status(fault_code);
+ status = dcerpc_do_request_recv(subreq, state,
+ &state->out_data,
+ &bigendian);
+ TALLOC_FREE(subreq);
+ if (tevent_req_nterror(req, status)) {
+ return;
}
- /*
- * We trigger the callback in the next event run
- * because the code in this file might trigger
- * multiple request callbacks from within a single
- * while loop.
- *
- * In order to avoid segfaults from within
- * dcerpc_connection_dead() we call
- * tevent_req_defer_callback().
- */
- tevent_req_defer_callback(req, state->ev);
-
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
- return;
+ state->out_flags = 0;
+ if (bigendian) {
+ state->out_flags |= LIBNDR_FLAG_BIGENDIAN;
}
tevent_req_done(req);
#include "librpc/rpc/dcerpc.h"
#include "librpc/rpc/dcerpc_proto.h"
#include "param/param.h"
+#include "librpc/rpc/dcerpc_connection.h"
/*
return the rpc syntax and transfer syntax given the pipe uuid and version
struct composite_context *c;
struct tevent_req *subreq;
+ struct dcerpc_call *call;
c = composite_create(mem_ctx, p->conn->event_ctx);
if (c == NULL) return NULL;
+ if (p->conn->security_state.sec != NULL) {
+ composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
+ return c;
+ }
+
+ p->conn->security_state.sec = dcerpc_security_allocate(p->conn,
+ p->conn->conn,
+ DCERPC_AUTH_TYPE_NONE,
+ DCERPC_AUTH_LEVEL_NONE,
+ NULL);
+ if (composite_nomem(p->conn->security_state.sec, c)) return c;
+
c->status = dcerpc_init_syntaxes(p, table,
&syntax, &transfer_syntax);
if (!NT_STATUS_IS_OK(c->status)) {
return c;
}
- subreq = dcerpc_bind_send(mem_ctx, p->conn->event_ctx, p,
- &syntax, &transfer_syntax);
+ p->pres = dcerpc_presentation_allocate(p, p->conn->conn,
+ table, &transfer_syntax);
+ if (composite_nomem(p->pres, c)) return c;
+
+ call = dcerpc_call_allocate(c, p->conn->assoc, NULL, NULL);
+ if (composite_nomem(call, c)) return c;
+
+ subreq = dcerpc_do_bind_send(call, p->conn->event_ctx,
+ p->conn->conn, call,
+ p->conn->security_state.sec,
+ 1, &p->pres);
if (composite_nomem(subreq, c)) return c;
tevent_req_set_callback(subreq, dcerpc_bind_auth_none_done, c);
tevent_req_callback_data(subreq,
struct composite_context);
- ctx->status = dcerpc_bind_recv(subreq);
+ ctx->status = dcerpc_do_bind_recv(subreq);
TALLOC_FREE(subreq);
if (!composite_is_ok(ctx)) return;
struct bind_auth_state {
struct dcerpc_pipe *pipe;
- struct ndr_syntax_id syntax;
- struct ndr_syntax_id transfer_syntax;
- struct dcerpc_auth out_auth_info;
- struct dcerpc_auth in_auth_info;
- bool more_processing; /* Is there anything more to do after the
- * first bind itself received? */
};
-static void bind_auth_next_gensec_done(struct tevent_req *subreq);
-static void bind_auth_recv_alter(struct tevent_req *subreq);
-
-static void bind_auth_next_step(struct composite_context *c)
-{
- struct bind_auth_state *state;
- struct dcecli_security *sec;
- struct tevent_req *subreq;
-
- state = talloc_get_type(c->private_data, struct bind_auth_state);
- sec = &state->pipe->conn->security_state;
-
- if (state->in_auth_info.auth_type != sec->auth_type) {
- composite_error(c, NT_STATUS_RPC_PROTOCOL_ERROR);
- return;
- }
-
- if (state->in_auth_info.auth_level != sec->auth_level) {
- composite_error(c, NT_STATUS_RPC_PROTOCOL_ERROR);
- return;
- }
-
- if (state->in_auth_info.auth_context_id != sec->auth_context_id) {
- composite_error(c, NT_STATUS_RPC_PROTOCOL_ERROR);
- return;
- }
-
- state->out_auth_info = (struct dcerpc_auth) {
- .auth_type = sec->auth_type,
- .auth_level = sec->auth_level,
- .auth_context_id = sec->auth_context_id,
- };
-
- /* The status value here, from GENSEC is vital to the security
- * of the system. Even if the other end accepts, if GENSEC
- * claims 'MORE_PROCESSING_REQUIRED' then you must keep
- * feeding it blobs, or else the remote host/attacker might
- * avoid mutal authentication requirements.
- *
- * Likewise, you must not feed GENSEC too much (after the OK),
- * it doesn't like that either
- */
-
- state->pipe->inhibit_timeout_processing = true;
- state->pipe->timed_out = false;
-
- subreq = gensec_update_send(state,
- state->pipe->conn->event_ctx,
- sec->generic_state,
- state->in_auth_info.credentials);
- if (composite_nomem(subreq, c)) return;
- tevent_req_set_callback(subreq, bind_auth_next_gensec_done, c);
-}
-
-static void bind_auth_next_gensec_done(struct tevent_req *subreq)
-{
- struct composite_context *c =
- tevent_req_callback_data(subreq,
- struct composite_context);
- struct bind_auth_state *state =
- talloc_get_type_abort(c->private_data,
- struct bind_auth_state);
- struct dcerpc_pipe *p = state->pipe;
- struct dcecli_security *sec = &p->conn->security_state;
- bool more_processing = false;
-
- state->pipe->inhibit_timeout_processing = false;
-
- c->status = gensec_update_recv(subreq, state,
- &state->out_auth_info.credentials);
- TALLOC_FREE(subreq);
-
- if (NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- more_processing = true;
- c->status = NT_STATUS_OK;
- }
-
- if (!composite_is_ok(c)) return;
-
- if (!more_processing) {
- if (state->pipe->conn->flags & DCERPC_HEADER_SIGNING) {
- gensec_want_feature(sec->generic_state,
- GENSEC_FEATURE_SIGN_PKT_HEADER);
- }
- }
-
- if (state->out_auth_info.credentials.length == 0) {
- composite_done(c);
- return;
- }
-
- state->in_auth_info = (struct dcerpc_auth) {
- .auth_type = DCERPC_AUTH_TYPE_NONE,
- };
- sec->tmp_auth_info.in = &state->in_auth_info;
- sec->tmp_auth_info.mem = state;
- sec->tmp_auth_info.out = &state->out_auth_info;
-
- if (!more_processing) {
- /* NO reply expected, so just send it */
- c->status = dcerpc_auth3(state->pipe, state);
- if (!composite_is_ok(c)) return;
-
- composite_done(c);
- return;
- }
-
- /* We are demanding a reply, so use a request that will get us one */
-
- subreq = dcerpc_alter_context_send(state, state->pipe->conn->event_ctx,
- state->pipe,
- &state->pipe->syntax,
- &state->pipe->transfer_syntax);
- if (composite_nomem(subreq, c)) return;
- tevent_req_set_callback(subreq, bind_auth_recv_alter, c);
-}
-
-
-static void bind_auth_recv_alter(struct tevent_req *subreq)
-{
- struct composite_context *c =
- tevent_req_callback_data(subreq,
- struct composite_context);
- struct bind_auth_state *state = talloc_get_type(c->private_data,
- struct bind_auth_state);
- struct dcecli_security *sec = &state->pipe->conn->security_state;
-
- ZERO_STRUCT(sec->tmp_auth_info);
-
- c->status = dcerpc_alter_context_recv(subreq);
- TALLOC_FREE(subreq);
- if (!composite_is_ok(c)) return;
-
- bind_auth_next_step(c);
-}
-
-
static void bind_auth_recv_bindreply(struct tevent_req *subreq)
{
struct composite_context *c =
tevent_req_callback_data(subreq,
struct composite_context);
- struct bind_auth_state *state = talloc_get_type(c->private_data,
- struct bind_auth_state);
- struct dcecli_security *sec = &state->pipe->conn->security_state;
- ZERO_STRUCT(sec->tmp_auth_info);
-
- c->status = dcerpc_bind_recv(subreq);
+ c->status = dcerpc_do_bind_recv(subreq);
TALLOC_FREE(subreq);
if (!composite_is_ok(c)) return;
- if (!state->more_processing) {
- /* The first gensec_update has not requested a second run, so
- * we're done here. */
- composite_done(c);
- return;
- }
-
- bind_auth_next_step(c);
+ composite_done(c);
}
struct bind_auth_state *state;
struct dcecli_security *sec;
struct tevent_req *subreq;
+ struct dcerpc_call *call;
+ struct ndr_syntax_id syntax, transfer_syntax;
const char *target_principal = NULL;
/* composite context allocation and setup */
state->pipe = p;
- c->status = dcerpc_init_syntaxes(p, table,
- &state->syntax,
- &state->transfer_syntax);
- if (!composite_is_ok(c)) return c;
+ if (p->conn->security_state.sec != NULL) {
+ composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
+ return c;
+ }
sec = &p->conn->security_state;
return c;
}
- sec->auth_type = auth_type;
- sec->auth_level = auth_level,
- /*
- * We use auth_context_id = 1 as some older
- * Samba versions (<= 4.2.3) use that value hardcoded
- * in a response.
- */
- sec->auth_context_id = 1;
-
- state->out_auth_info = (struct dcerpc_auth) {
- .auth_type = sec->auth_type,
- .auth_level = sec->auth_level,
- .auth_context_id = sec->auth_context_id,
- };
-
- /* The status value here, from GENSEC is vital to the security
- * of the system. Even if the other end accepts, if GENSEC
- * claims 'MORE_PROCESSING_REQUIRED' then you must keep
- * feeding it blobs, or else the remote host/attacker might
- * avoid mutal authentication requirements.
- *
- * Likewise, you must not feed GENSEC too much (after the OK),
- * it doesn't like that either
- */
-
- state->pipe->inhibit_timeout_processing = true;
- state->pipe->timed_out = false;
-
- subreq = gensec_update_send(state,
- p->conn->event_ctx,
- sec->generic_state,
- data_blob_null);
- if (composite_nomem(subreq, c)) return c;
- tevent_req_set_callback(subreq, dcerpc_bind_auth_gensec_done, c);
-
- return c;
-}
-
-static void dcerpc_bind_auth_gensec_done(struct tevent_req *subreq)
-{
- struct composite_context *c =
- tevent_req_callback_data(subreq,
- struct composite_context);
- struct bind_auth_state *state =
- talloc_get_type_abort(c->private_data,
- struct bind_auth_state);
- struct dcerpc_pipe *p = state->pipe;
- struct dcecli_security *sec = &p->conn->security_state;
-
- state->pipe->inhibit_timeout_processing = false;
-
- c->status = gensec_update_recv(subreq, state,
- &state->out_auth_info.credentials);
- TALLOC_FREE(subreq);
- if (!NT_STATUS_IS_OK(c->status) &&
- !NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- composite_error(c, c->status);
- return;
- }
+ sec->sec = dcerpc_security_allocate(p->conn,
+ p->conn->conn,
+ auth_type, auth_level,
+ &sec->generic_state);
+ if (composite_nomem(sec->sec, c)) return c;
- state->more_processing = NT_STATUS_EQUAL(c->status,
- NT_STATUS_MORE_PROCESSING_REQUIRED);
+ c->status = dcerpc_init_syntaxes(p, table,
+ &syntax,
+ &transfer_syntax);
+ if (!composite_is_ok(c)) return c;
- if (state->out_auth_info.credentials.length == 0) {
- composite_done(c);
- return;
- }
+ p->pres = dcerpc_presentation_allocate(p, p->conn->conn,
+ table, &transfer_syntax);
+ if (composite_nomem(p->pres, c)) return c;
- if (gensec_have_feature(sec->generic_state, GENSEC_FEATURE_SIGN_PKT_HEADER)) {
- if (sec->auth_level >= DCERPC_AUTH_LEVEL_PACKET) {
- state->pipe->conn->flags |= DCERPC_PROPOSE_HEADER_SIGNING;
- }
- }
+ call = dcerpc_call_allocate(c, p->conn->assoc, NULL, NULL);
+ if (composite_nomem(call, c)) return c;
- state->in_auth_info = (struct dcerpc_auth) {
- .auth_type = DCERPC_AUTH_TYPE_NONE,
- };
- sec->tmp_auth_info.in = &state->in_auth_info;
- sec->tmp_auth_info.mem = state;
- sec->tmp_auth_info.out = &state->out_auth_info;
-
- /* The first request always is a dcerpc_bind. The subsequent ones
- * depend on gensec results */
- subreq = dcerpc_bind_send(state, p->conn->event_ctx, p,
- &state->syntax, &state->transfer_syntax);
- if (composite_nomem(subreq, c)) return;
+ subreq = dcerpc_do_bind_send(call, p->conn->event_ctx,
+ p->conn->conn, call,
+ p->conn->security_state.sec,
+ 1, &p->pres);
+ if (composite_nomem(subreq, c)) return c;
tevent_req_set_callback(subreq, bind_auth_recv_bindreply, c);
return;