diff options
author | Andrew Bartlett <abartlet@samba.org> | 2012-07-09 14:37:28 +1000 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2012-07-18 09:32:53 +0200 |
commit | 02a356ea775a3ba589cb50af3c861ab86aaffa0b (patch) | |
tree | 315544ffb45cc6f2c5ccc2ef59500e057fd0855a | |
parent | fc36ebfa7861cf7e86aa3c2110a6ab213424e8c1 (diff) | |
download | samba-02a356ea775a3ba589cb50af3c861ab86aaffa0b.tar.gz samba-02a356ea775a3ba589cb50af3c861ab86aaffa0b.tar.bz2 samba-02a356ea775a3ba589cb50af3c861ab86aaffa0b.zip |
s4-librpc: Ensure we do not call call the decrpc timeout handler during gensec_update()
This avoids a situation where we could destroy pointers on the stack due to
a nested event loop.
This is certainly not a final, generic solution, but it is a minimal change
while we work to make gensec and gensec_gssapi async.
Andrew Bartlett
-rw-r--r-- | source4/librpc/rpc/dcerpc.h | 8 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc_auth.c | 17 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc_connect.c | 19 |
3 files changed, 39 insertions, 5 deletions
diff --git a/source4/librpc/rpc/dcerpc.h b/source4/librpc/rpc/dcerpc.h index 359efdabc0..ef830865e8 100644 --- a/source4/librpc/rpc/dcerpc.h +++ b/source4/librpc/rpc/dcerpc.h @@ -124,6 +124,14 @@ struct dcerpc_pipe { /** timeout for individual rpc requests, in seconds */ uint32_t request_timeout; + + /* + * Set for the timeout in dcerpc_pipe_connect_b_send(), to + * allow the timeout not to destory the stack during a nested + * event loop caused by gensec_update() + */ + bool inhibit_timeout_processing; + bool timed_out; }; /* default timeout for all rpc requests, in seconds */ diff --git a/source4/librpc/rpc/dcerpc_auth.c b/source4/librpc/rpc/dcerpc_auth.c index cedcdd1bec..d5e56206b0 100644 --- a/source4/librpc/rpc/dcerpc_auth.c +++ b/source4/librpc/rpc/dcerpc_auth.c @@ -151,10 +151,19 @@ static void bind_auth_next_step(struct composite_context *c) * it doesn't like that either */ + state->pipe->inhibit_timeout_processing = true; + state->pipe->timed_out = false; + c->status = gensec_update(sec->generic_state, state, state->pipe->conn->event_ctx, sec->auth_info->credentials, &state->credentials); + if (state->pipe->timed_out) { + composite_error(c, NT_STATUS_IO_TIMEOUT); + return; + } + state->pipe->inhibit_timeout_processing = false; + data_blob_free(&sec->auth_info->credentials); if (NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { @@ -358,10 +367,18 @@ struct composite_context *dcerpc_bind_auth_send(TALLOC_CTX *mem_ctx, * it doesn't like that either */ + state->pipe->inhibit_timeout_processing = true; + state->pipe->timed_out = false; c->status = gensec_update(sec->generic_state, state, p->conn->event_ctx, sec->auth_info->credentials, &state->credentials); + if (state->pipe->timed_out) { + composite_error(c, NT_STATUS_IO_TIMEOUT); + return c; + } + state->pipe->inhibit_timeout_processing = false; + if (!NT_STATUS_IS_OK(c->status) && !NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { composite_error(c, c->status); diff --git a/source4/librpc/rpc/dcerpc_connect.c b/source4/librpc/rpc/dcerpc_connect.c index 8cf60e63e2..821499e9ff 100644 --- a/source4/librpc/rpc/dcerpc_connect.c +++ b/source4/librpc/rpc/dcerpc_connect.c @@ -716,8 +716,14 @@ static void continue_pipe_auth(struct composite_context *ctx) static void dcerpc_connect_timeout_handler(struct tevent_context *ev, struct tevent_timer *te, struct timeval t, void *private_data) { - struct composite_context *c = talloc_get_type(private_data, struct composite_context); - composite_error(c, NT_STATUS_IO_TIMEOUT); + struct composite_context *c = talloc_get_type(private_data, + struct composite_context); + struct pipe_connect_state *s = talloc_get_type(c->private_data, struct pipe_connect_state); + if (!s->pipe->inhibit_timeout_processing) { + composite_error(c, NT_STATUS_IO_TIMEOUT); + } else { + s->pipe->timed_out = true; + } } /* @@ -757,9 +763,12 @@ _PUBLIC_ struct composite_context* dcerpc_pipe_connect_b_send(TALLOC_CTX *parent s->credentials = credentials; s->lp_ctx = lp_ctx; - tevent_add_timer(c->event_ctx, c, - timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0), - dcerpc_connect_timeout_handler, c); + s->pipe->timed_out = false; + s->pipe->inhibit_timeout_processing = false; + + tevent_add_timer(c->event_ctx, s, + timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0), + dcerpc_connect_timeout_handler, s); switch (s->binding->transport) { case NCA_UNKNOWN: { |