summaryrefslogtreecommitdiff
path: root/source4/librpc
diff options
context:
space:
mode:
Diffstat (limited to 'source4/librpc')
-rw-r--r--source4/librpc/rpc/dcerpc.c232
-rw-r--r--source4/librpc/rpc/dcerpc_auth.c48
2 files changed, 169 insertions, 111 deletions
diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c
index 3243644721..c1f27cc263 100644
--- a/source4/librpc/rpc/dcerpc.c
+++ b/source4/librpc/rpc/dcerpc.c
@@ -1072,65 +1072,6 @@ static void dcerpc_recv_data(struct dcecli_connection *conn, DATA_BLOB *blob, NT
}
/*
- Receive a bind reply from the transport
-*/
-static void dcerpc_bind_recv_handler(struct rpc_request *req,
- DATA_BLOB *raw_packet, struct ncacn_packet *pkt)
-{
- struct composite_context *c;
- struct dcecli_connection *conn;
-
- c = talloc_get_type(req->async.private_data, struct composite_context);
-
- if (pkt->ptype == DCERPC_PKT_BIND_NAK) {
- DEBUG(2,("dcerpc: bind_nak reason %d\n",
- pkt->u.bind_nak.reject_reason));
- composite_error(c, dcerpc_map_reason(pkt->u.bind_nak.
- reject_reason));
- return;
- }
-
- if ((pkt->ptype != DCERPC_PKT_BIND_ACK) ||
- (pkt->u.bind_ack.num_results == 0) ||
- (pkt->u.bind_ack.ctx_list[0].result != 0)) {
- req->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
- composite_error(c, NT_STATUS_NET_WRITE_FAULT);
- return;
- }
-
- conn = req->p->conn;
-
- conn->srv_max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
- conn->srv_max_recv_frag = pkt->u.bind_ack.max_recv_frag;
-
- if ((req->p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) &&
- (pkt->pfc_flags & DCERPC_PFC_FLAG_CONC_MPX)) {
- conn->flags |= DCERPC_CONCURRENT_MULTIPLEX;
- }
-
- if ((req->p->binding->flags & DCERPC_HEADER_SIGNING) &&
- (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN)) {
- conn->flags |= DCERPC_HEADER_SIGNING;
- }
-
- /* the bind_ack might contain a reply set of credentials */
- if (conn->security_state.auth_info && pkt->u.bind_ack.auth_info.length) {
- NTSTATUS status;
- uint32_t auth_length;
- status = dcerpc_pull_auth_trailer(pkt, conn, &pkt->u.bind_ack.auth_info,
- conn->security_state.auth_info, &auth_length, true);
- if (!NT_STATUS_IS_OK(status)) {
- composite_error(c, status);
- return;
- }
- }
-
- req->p->assoc_group_id = pkt->u.bind_ack.assoc_group_id;
-
- composite_done(c);
-}
-
-/*
handle timeouts of individual dcerpc requests
*/
static void dcerpc_timeout_handler(struct tevent_context *ev, struct tevent_timer *te,
@@ -1151,23 +1092,35 @@ static void dcerpc_timeout_handler(struct tevent_context *ev, struct tevent_time
dcerpc_connection_dead(req->p->conn, NT_STATUS_IO_TIMEOUT);
}
-/*
- send a async dcerpc bind request
-*/
-struct composite_context *dcerpc_bind_send(struct dcerpc_pipe *p,
- TALLOC_CTX *mem_ctx,
- const struct ndr_syntax_id *syntax,
- const struct ndr_syntax_id *transfer_syntax)
+struct dcerpc_bind_state {
+ struct dcerpc_pipe *p;
+};
+
+static void dcerpc_bind_fail_handler(struct rpc_request *subreq);
+static void dcerpc_bind_recv_handler(struct rpc_request *subreq,
+ DATA_BLOB *raw_packet,
+ struct ncacn_packet *pkt);
+
+struct tevent_req *dcerpc_bind_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct dcerpc_pipe *p,
+ const struct ndr_syntax_id *syntax,
+ const struct ndr_syntax_id *transfer_syntax)
{
- struct composite_context *c;
+ struct tevent_req *req;
+ struct dcerpc_bind_state *state;
struct ncacn_packet pkt;
DATA_BLOB blob;
- struct rpc_request *req;
+ NTSTATUS status;
+ struct rpc_request *subreq;
- c = composite_create(mem_ctx,p->conn->event_ctx);
- if (c == NULL) return NULL;
+ req = tevent_req_create(mem_ctx, &state,
+ struct dcerpc_bind_state);
+ if (req == NULL) {
+ return NULL;
+ }
- c->private_data = p;
+ state->p = p;
p->syntax = *syntax;
p->transfer_syntax = *transfer_syntax;
@@ -1192,7 +1145,9 @@ struct composite_context *dcerpc_bind_send(struct dcerpc_pipe *p,
pkt.u.bind.assoc_group_id = p->binding->assoc_group_id;
pkt.u.bind.num_contexts = 1;
pkt.u.bind.ctx_list = talloc_array(mem_ctx, struct dcerpc_ctx_list, 1);
- if (composite_nomem(pkt.u.bind.ctx_list, c)) return c;
+ if (tevent_req_nomem(pkt.u.bind.ctx_list, req)) {
+ return tevent_req_post(req, ev);
+ }
pkt.u.bind.ctx_list[0].context_id = p->context_id;
pkt.u.bind.ctx_list[0].num_transfer_syntaxes = 1;
pkt.u.bind.ctx_list[0].abstract_syntax = p->syntax;
@@ -1200,9 +1155,11 @@ struct composite_context *dcerpc_bind_send(struct dcerpc_pipe *p,
pkt.u.bind.auth_info = data_blob(NULL, 0);
/* construct the NDR form of the packet */
- c->status = ncacn_push_auth(&blob, c, &pkt,
- p->conn->security_state.auth_info);
- if (!composite_is_ok(c)) return c;
+ status = ncacn_push_auth(&blob, state, &pkt,
+ p->conn->security_state.auth_info);
+ if (tevent_req_nterror(req, status)) {
+ return tevent_req_post(req, ev);
+ }
p->conn->transport.recv_data = dcerpc_recv_data;
@@ -1210,37 +1167,114 @@ struct composite_context *dcerpc_bind_send(struct dcerpc_pipe *p,
* we allocate a dcerpc_request so we can be in the same
* request queue as normal requests
*/
- req = talloc_zero(c, struct rpc_request);
- if (composite_nomem(req, c)) return c;
+ subreq = talloc_zero(state, struct rpc_request);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
- req->state = RPC_REQUEST_PENDING;
- req->call_id = pkt.call_id;
- req->async.private_data = c;
- req->async.callback = dcerpc_composite_fail;
- req->p = p;
- req->recv_handler = dcerpc_bind_recv_handler;
- DLIST_ADD_END(p->conn->pending, req, struct rpc_request *);
- talloc_set_destructor(req, dcerpc_req_dequeue);
+ subreq->state = RPC_REQUEST_PENDING;
+ subreq->call_id = pkt.call_id;
+ subreq->async.private_data = req;
+ subreq->async.callback = dcerpc_bind_fail_handler;
+ subreq->p = p;
+ subreq->recv_handler = dcerpc_bind_recv_handler;
+ DLIST_ADD_END(p->conn->pending, subreq, struct rpc_request *);
+ talloc_set_destructor(subreq, dcerpc_req_dequeue);
+
+ status = p->conn->transport.send_request(p->conn, &blob, true);
+ if (tevent_req_nterror(req, status)) {
+ return tevent_req_post(req, ev);
+ }
- c->status = p->conn->transport.send_request(p->conn, &blob,
- true);
- if (!composite_is_ok(c)) return c;
+ tevent_add_timer(ev, subreq,
+ timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
+ dcerpc_timeout_handler, subreq);
- tevent_add_timer(c->event_ctx, req,
- timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
- dcerpc_timeout_handler, req);
+ return req;
+}
- return c;
+static void dcerpc_bind_fail_handler(struct rpc_request *subreq)
+{
+ struct tevent_req *req =
+ talloc_get_type_abort(subreq->async.private_data,
+ struct tevent_req);
+ NTSTATUS status = subreq->status;
+
+ TALLOC_FREE(subreq);
+
+ tevent_req_nterror(req, status);
}
-/*
- recv side of async dcerpc bind request
-*/
-NTSTATUS dcerpc_bind_recv(struct composite_context *ctx)
+static void dcerpc_bind_recv_handler(struct rpc_request *subreq,
+ DATA_BLOB *raw_packet,
+ struct ncacn_packet *pkt)
{
- NTSTATUS result = composite_wait(ctx);
- talloc_free(ctx);
- return result;
+ struct tevent_req *req =
+ talloc_get_type_abort(subreq->async.private_data,
+ struct tevent_req);
+ struct dcerpc_bind_state *state =
+ tevent_req_data(req,
+ struct dcerpc_bind_state);
+ struct dcecli_connection *conn = state->p->conn;
+ NTSTATUS status;
+
+ /*
+ * Note that pkt is allocated under raw_packet->data,
+ * while raw_packet->data is a child of subreq.
+ */
+ talloc_steal(state, raw_packet->data);
+ TALLOC_FREE(subreq);
+
+ if (pkt->ptype == DCERPC_PKT_BIND_NAK) {
+ status = dcerpc_map_reason(pkt->u.bind_nak.reject_reason);
+
+ DEBUG(2,("dcerpc: bind_nak reason %d - %s\n",
+ pkt->u.bind_nak.reject_reason, nt_errstr(status)));
+
+ tevent_req_nterror(req, status);
+ return;
+ }
+
+ if ((pkt->ptype != DCERPC_PKT_BIND_ACK) ||
+ (pkt->u.bind_ack.num_results == 0) ||
+ (pkt->u.bind_ack.ctx_list[0].result != 0)) {
+ state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
+ tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
+ return;
+ }
+
+ conn->srv_max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
+ conn->srv_max_recv_frag = pkt->u.bind_ack.max_recv_frag;
+
+ if ((state->p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) &&
+ (pkt->pfc_flags & DCERPC_PFC_FLAG_CONC_MPX)) {
+ conn->flags |= DCERPC_CONCURRENT_MULTIPLEX;
+ }
+
+ if ((state->p->binding->flags & DCERPC_HEADER_SIGNING) &&
+ (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN)) {
+ conn->flags |= DCERPC_HEADER_SIGNING;
+ }
+
+ /* the bind_ack might contain a reply set of credentials */
+ if (conn->security_state.auth_info && pkt->u.bind_ack.auth_info.length) {
+ uint32_t auth_length;
+
+ status = dcerpc_pull_auth_trailer(pkt, conn, &pkt->u.bind_ack.auth_info,
+ conn->security_state.auth_info, &auth_length, true);
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
+ }
+
+ state->p->assoc_group_id = pkt->u.bind_ack.assoc_group_id;
+
+ tevent_req_done(req);
+}
+
+NTSTATUS dcerpc_bind_recv(struct tevent_req *req)
+{
+ return tevent_req_simple_recv_ntstatus(req);
}
/*
diff --git a/source4/librpc/rpc/dcerpc_auth.c b/source4/librpc/rpc/dcerpc_auth.c
index b3f4f2fdb0..7af85aaab1 100644
--- a/source4/librpc/rpc/dcerpc_auth.c
+++ b/source4/librpc/rpc/dcerpc_auth.c
@@ -22,6 +22,7 @@
*/
#include "includes.h"
+#include <tevent.h>
#include "libcli/composite/composite.h"
#include "auth/gensec/gensec.h"
#include "librpc/rpc/dcerpc.h"
@@ -52,6 +53,8 @@ static NTSTATUS dcerpc_init_syntaxes(const struct ndr_interface_table *table,
/*
Send request to do a non-authenticated dcerpc bind
*/
+static void dcerpc_bind_auth_none_done(struct tevent_req *subreq);
+
struct composite_context *dcerpc_bind_auth_none_send(TALLOC_CTX *mem_ctx,
struct dcerpc_pipe *p,
const struct ndr_interface_table *table)
@@ -60,6 +63,7 @@ struct composite_context *dcerpc_bind_auth_none_send(TALLOC_CTX *mem_ctx,
struct ndr_syntax_id transfer_syntax;
struct composite_context *c;
+ struct tevent_req *subreq;
c = composite_create(mem_ctx, p->conn->event_ctx);
if (c == NULL) return NULL;
@@ -73,19 +77,35 @@ struct composite_context *dcerpc_bind_auth_none_send(TALLOC_CTX *mem_ctx,
return c;
}
- /* c was only allocated as a container for a possible error */
- talloc_free(c);
+ subreq = dcerpc_bind_send(mem_ctx, p->conn->event_ctx, p,
+ &syntax, &transfer_syntax);
+ if (composite_nomem(subreq, c)) return c;
+ tevent_req_set_callback(subreq, dcerpc_bind_auth_none_done, c);
- return dcerpc_bind_send(p, mem_ctx, &syntax, &transfer_syntax);
+ return c;
}
+static void dcerpc_bind_auth_none_done(struct tevent_req *subreq)
+{
+ struct composite_context *ctx =
+ tevent_req_callback_data(subreq,
+ struct composite_context);
+
+ ctx->status = dcerpc_bind_recv(subreq);
+ TALLOC_FREE(subreq);
+ if (!composite_is_ok(ctx)) return;
+
+ composite_done(ctx);
+}
/*
Receive result of a non-authenticated dcerpc bind
*/
NTSTATUS dcerpc_bind_auth_none_recv(struct composite_context *ctx)
{
- return dcerpc_bind_recv(ctx);
+ NTSTATUS result = composite_wait(ctx);
+ TALLOC_FREE(ctx);
+ return result;
}
@@ -191,14 +211,16 @@ static void bind_auth_recv_alter(struct composite_context *creq)
}
-static void bind_auth_recv_bindreply(struct composite_context *creq)
+static void bind_auth_recv_bindreply(struct tevent_req *subreq)
{
- struct composite_context *c = talloc_get_type(creq->async.private_data,
- struct composite_context);
+ 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);
- c->status = dcerpc_bind_recv(creq);
+ c->status = dcerpc_bind_recv(subreq);
+ TALLOC_FREE(subreq);
if (!composite_is_ok(c)) return;
if (!state->more_processing) {
@@ -232,9 +254,10 @@ struct composite_context *dcerpc_bind_auth_send(TALLOC_CTX *mem_ctx,
uint8_t auth_type, uint8_t auth_level,
const char *service)
{
- struct composite_context *c, *creq;
+ struct composite_context *c;
struct bind_auth_state *state;
struct dcecli_security *sec;
+ struct tevent_req *subreq;
struct ndr_syntax_id syntax, transfer_syntax;
@@ -355,12 +378,13 @@ struct composite_context *dcerpc_bind_auth_send(TALLOC_CTX *mem_ctx,
/* The first request always is a dcerpc_bind. The subsequent ones
* depend on gensec results */
- creq = dcerpc_bind_send(p, state, &syntax, &transfer_syntax);
+ subreq = dcerpc_bind_send(state, p->conn->event_ctx, p,
+ &syntax, &transfer_syntax);
data_blob_free(&state->credentials);
sec->auth_info->credentials = data_blob(NULL, 0);
- if (composite_nomem(creq, c)) return c;
+ if (composite_nomem(subreq, c)) return c;
+ tevent_req_set_callback(subreq, bind_auth_recv_bindreply, c);
- composite_continue(c, creq, bind_auth_recv_bindreply, c);
return c;
}