s4-librpc: Ensure we do not call call the decrpc timeout handler during gensec_update()
authorAndrew Bartlett <abartlet@samba.org>
Mon, 9 Jul 2012 04:37:28 +0000 (14:37 +1000)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 18 Jul 2012 07:32:53 +0000 (09:32 +0200)
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

source4/librpc/rpc/dcerpc.h
source4/librpc/rpc/dcerpc_auth.c
source4/librpc/rpc/dcerpc_connect.c

index 359efdabc0fb15a309075b7ddf388613ed382b6c..ef830865e8bfc55604f75feac385b8f3228ea025 100644 (file)
@@ -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 */
index cedcdd1bece08705e3b601757aab09c6d54612bc..d5e56206b0416d01818a5f8c215d241a0cf401f2 100644 (file)
@@ -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);
index 8cf60e63e28b081ffacf1e00378bc6b658ca5be2..821499e9ffaeae4be25961333d47130869f665ee 100644 (file)
@@ -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: {