1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +03:00

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>
This commit is contained in:
Stefan Metzmacher 2014-03-16 11:50:39 +01:00 committed by Andrew Bartlett
parent 6260de7221
commit 5b1d9f7a82

View File

@ -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)
{