winbindd: cleanup client connection if the client closes the connection
authorUri Simchoni <urisimchoni@gmail.com>
Thu, 25 Jun 2015 05:59:20 +0000 (08:59 +0300)
committerJeremy Allison <jra@samba.org>
Wed, 15 Jul 2015 20:41:13 +0000 (22:41 +0200)
This patch allows for early cleanup of client connections if the client
has given up.
Before this patch, any received request would be processed, and then only
upon transmitting the result to the client would winbindd find out the
client is no longer with us, possibly leading to a situation where the
same client tries over and over and increases the number of client
connections.

This patch monitors the client socket for readability while the request
is being processed, and closes the client connection if the socket
becomes readable. The client is not supposed to be writing anything to
the socket while it is waiting, so readability means either that the client
has closed the connection, or that it has broken the protocol.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=11397

Signed-off-by: Uri Simchoni <urisimchoni@gmail.com>
Reviewed-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/winbindd/winbindd.c

index defc9cca1d93c2392fce645d59d14b0afe7bdaed..a03b5b48b8c2388b4c11aedc4022648e1ee1d45b 100644 (file)
@@ -42,6 +42,7 @@
 #include "source4/lib/messaging/irpc.h"
 #include "source4/lib/messaging/messaging.h"
 #include "lib/param/param.h"
+#include "lib/async_req/async_sock.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_WINBIND
@@ -809,11 +810,15 @@ static void request_finished(struct winbindd_cli_state *state);
 
 static void winbind_client_request_read(struct tevent_req *req);
 static void winbind_client_response_written(struct tevent_req *req);
+static void winbind_client_activity(struct tevent_req *req);
 
 static void request_finished(struct winbindd_cli_state *state)
 {
        struct tevent_req *req;
 
+       /* free client socket monitoring request */
+       TALLOC_FREE(state->io_req);
+
        TALLOC_FREE(state->request);
 
        req = wb_resp_write_send(state, winbind_event_context(),
@@ -966,9 +971,32 @@ static void winbind_client_request_read(struct tevent_req *req)
                remove_client(state);
                return;
        }
+
+       req = wait_for_read_send(state, winbind_event_context(), state->sock);
+       if (req == NULL) {
+               DEBUG(0, ("winbind_client_request_read[%d:%s]:"
+                         " wait_for_read_send failed - removing client\n",
+                         (int)state->pid, state->cmd_name));
+               remove_client(state);
+               return;
+       }
+       tevent_req_set_callback(req, winbind_client_activity, state);
+       state->io_req = req;
+
        process_request(state);
 }
 
+static void winbind_client_activity(struct tevent_req *req)
+{
+       struct winbindd_cli_state *state =
+           tevent_req_callback_data(req, struct winbindd_cli_state);
+       int err;
+
+       wait_for_read_recv(req, &err);
+
+       remove_client(state);
+}
+
 /* Remove a client connection from client connection list */
 
 static void remove_client(struct winbindd_cli_state *state)