From: Stefan Metzmacher Date: Wed, 24 Feb 2021 16:44:12 +0000 (+0100) Subject: smbXsrv_session: smbXsrv_session_remove_channel() should also remove the last channel X-Git-Tag: tevent-0.11.0~1370 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a19180904ea73815e994f3c720613ae0b06099c3;p=thirdparty%2Fsamba.git smbXsrv_session: smbXsrv_session_remove_channel() should also remove the last channel There's nothing special regarding the last channel, as the smb2.session.bind2 test demonstrates. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14449 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison --- diff --git a/selftest/knownfail.d/smb2.session b/selftest/knownfail.d/smb2.session deleted file mode 100644 index e6520ffde4c..00000000000 --- a/selftest/knownfail.d/smb2.session +++ /dev/null @@ -1 +0,0 @@ -^samba3.smb2.session.*.bind2 diff --git a/source3/smbd/smbXsrv_session.c b/source3/smbd/smbXsrv_session.c index 734b2edfe2e..45750565529 100644 --- a/source3/smbd/smbXsrv_session.c +++ b/source3/smbd/smbXsrv_session.c @@ -1219,6 +1219,9 @@ static int smbXsrv_session_destructor(struct smbXsrv_session *session) { NTSTATUS status; + DBG_DEBUG("destructing session(%llu)\n", + (unsigned long long)session->global->session_wire_id); + status = smbXsrv_session_clear_and_logoff(session); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("smbXsrv_session_destructor: " @@ -1556,6 +1559,8 @@ NTSTATUS smbXsrv_session_create_auth(struct smbXsrv_session *session, return NT_STATUS_OK; } +static void smbXsrv_session_remove_channel_done(struct tevent_req *subreq); + NTSTATUS smbXsrv_session_remove_channel(struct smbXsrv_session *session, struct smbXsrv_connection *xconn) { @@ -1572,12 +1577,6 @@ NTSTATUS smbXsrv_session_remove_channel(struct smbXsrv_session *session, if (!NT_STATUS_IS_OK(status)) { c = NULL; } - if (session->global->num_channels <= 1) { - /* - * The last channel is treated different - */ - c = NULL; - } if (a != NULL) { smbXsrv_session_auth0_destructor(a); @@ -1595,6 +1594,30 @@ NTSTATUS smbXsrv_session_remove_channel(struct smbXsrv_session *session, } ARRAY_DEL_ELEMENT(global->channels, n, global->num_channels); global->num_channels--; + if (global->num_channels == 0) { + struct smbXsrv_client *client = session->client; + struct tevent_req *subreq = NULL; + + /* + * This is garanteed to set + * session->status = NT_STATUS_USER_SESSION_DELETED + * even if NULL is returned. + */ + subreq = smb2srv_session_shutdown_send(session, + client->raw_ev_ctx, + session, + NULL); + if (subreq == NULL) { + status = NT_STATUS_NO_MEMORY; + DBG_ERR("smb2srv_session_shutdown_send(%llu) failed: %s\n", + (unsigned long long)session->global->session_wire_id, + nt_errstr(status)); + return status; + } + tevent_req_set_callback(subreq, + smbXsrv_session_remove_channel_done, + session); + } need_update = true; } @@ -1605,6 +1628,31 @@ NTSTATUS smbXsrv_session_remove_channel(struct smbXsrv_session *session, return smbXsrv_session_update(session); } +static void smbXsrv_session_remove_channel_done(struct tevent_req *subreq) +{ + struct smbXsrv_session *session = + tevent_req_callback_data(subreq, + struct smbXsrv_session); + NTSTATUS status; + + status = smb2srv_session_shutdown_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + DBG_ERR("smb2srv_session_shutdown_recv(%llu) failed: %s\n", + (unsigned long long)session->global->session_wire_id, + nt_errstr(status)); + } + + status = smbXsrv_session_logoff(session); + if (!NT_STATUS_IS_OK(status)) { + DBG_ERR("smbXsrv_session_logoff(%llu) failed: %s\n", + (unsigned long long)session->global->session_wire_id, + nt_errstr(status)); + } + + TALLOC_FREE(session); +} + struct smb2srv_session_shutdown_state { struct tevent_queue *wait_queue; };