summaryrefslogtreecommitdiffstats
path: root/libcli/smb
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2014-03-16 11:50:39 +0100
committerAndrew Bartlett <abartlet@samba.org>2014-03-25 00:45:28 +0100
commit5b1d9f7a8277112f467fbcfc8048fbb71374bd9a (patch)
treee734164008a1d58f91748ae1d3cc588d6d7523da /libcli/smb
parent6260de72213fafc6f931b9dea35ddb95a188d075 (diff)
downloadsamba-5b1d9f7a8277112f467fbcfc8048fbb71374bd9a.tar.gz
samba-5b1d9f7a8277112f467fbcfc8048fbb71374bd9a.tar.xz
samba-5b1d9f7a8277112f467fbcfc8048fbb71374bd9a.zip
libcli/smb: add tstream_smbXcli_np_disconnect_cleanup() to handle talloc_free(req)
If the tevent_req of tstream_smbXcli_np_disconnect_* is explicitly or implicitly free'ed, we need to make sure we still deliver the close request to the server! Otherwise the SMB signing sequence gets out of sync. Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Diffstat (limited to 'libcli/smb')
-rw-r--r--libcli/smb/tstream_smbXcli_np.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/libcli/smb/tstream_smbXcli_np.c b/libcli/smb/tstream_smbXcli_np.c
index cbe7f6f83d3..736afb049fe 100644
--- a/libcli/smb/tstream_smbXcli_np.c
+++ b/libcli/smb/tstream_smbXcli_np.c
@@ -1255,9 +1255,12 @@ static int tstream_smbXcli_np_readv_recv(struct tevent_req *req,
struct tstream_smbXcli_np_disconnect_state {
struct tstream_context *stream;
+ struct tevent_req *subreq;
};
static void tstream_smbXcli_np_disconnect_done(struct tevent_req *subreq);
+static void tstream_smbXcli_np_disconnect_cleanup(struct tevent_req *req,
+ enum tevent_req_state req_state);
static struct tevent_req *tstream_smbXcli_np_disconnect_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
@@ -1302,6 +1305,14 @@ static struct tevent_req *tstream_smbXcli_np_disconnect_send(TALLOC_CTX *mem_ctx
return tevent_req_post(req, ev);
}
tevent_req_set_callback(subreq, tstream_smbXcli_np_disconnect_done, req);
+ state->subreq = subreq;
+
+ tevent_req_set_cleanup_fn(req, tstream_smbXcli_np_disconnect_cleanup);
+
+ /*
+ * Make sure we don't send any requests anymore.
+ */
+ cli_nps->conn = NULL;
return req;
}
@@ -1316,6 +1327,8 @@ static void tstream_smbXcli_np_disconnect_done(struct tevent_req *subreq)
tstream_context_data(state->stream, struct tstream_smbXcli_np);
NTSTATUS status;
+ state->subreq = NULL;
+
if (cli_nps->is_smb1) {
status = smb1cli_close_recv(subreq);
} else {
@@ -1334,6 +1347,51 @@ static void tstream_smbXcli_np_disconnect_done(struct tevent_req *subreq)
tevent_req_done(req);
}
+static void tstream_smbXcli_np_disconnect_free(struct tevent_req *subreq);
+
+static void tstream_smbXcli_np_disconnect_cleanup(struct tevent_req *req,
+ enum tevent_req_state req_state)
+{
+ struct tstream_smbXcli_np_disconnect_state *state =
+ tevent_req_data(req, struct tstream_smbXcli_np_disconnect_state);
+ struct tstream_smbXcli_np *cli_nps = NULL;
+
+ if (state->subreq == NULL) {
+ return;
+ }
+
+ cli_nps = tstream_context_data(state->stream, struct tstream_smbXcli_np);
+
+ if (cli_nps->tcon == NULL) {
+ return;
+ }
+
+ /*
+ * We're no longer interested in the result
+ * any more, but need to make sure that the close
+ * request arrives at the server if the smb connection,
+ * session and tcon are still alive.
+ *
+ * We move the low level request to the tcon,
+ * which means that it stays as long as the tcon
+ * is available.
+ */
+ talloc_steal(cli_nps->tcon, state->subreq);
+ tevent_req_set_callback(state->subreq,
+ tstream_smbXcli_np_disconnect_free,
+ NULL);
+ state->subreq = NULL;
+
+ cli_nps->conn = NULL;
+ cli_nps->session = NULL;
+ cli_nps->tcon = NULL;
+}
+
+static void tstream_smbXcli_np_disconnect_free(struct tevent_req *subreq)
+{
+ TALLOC_FREE(subreq);
+}
+
static int tstream_smbXcli_np_disconnect_recv(struct tevent_req *req,
int *perrno)
{