diff options
author | Stefan Metzmacher <metze@samba.org> | 2014-03-16 11:50:39 +0100 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2014-03-25 00:45:28 +0100 |
commit | 5b1d9f7a8277112f467fbcfc8048fbb71374bd9a (patch) | |
tree | e734164008a1d58f91748ae1d3cc588d6d7523da | |
parent | 6260de72213fafc6f931b9dea35ddb95a188d075 (diff) | |
download | samba-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>
-rw-r--r-- | libcli/smb/tstream_smbXcli_np.c | 58 |
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) { |