Patches for https://bugzilla.samba.org/show_bug.cgi?id=11182
Stefan (metze) Metzmacher
metze at samba.org
Wed May 6 02:19:34 MDT 2015
Hi Jeremy,
here're the proposed patches for master regarding
https://bugzilla.samba.org/show_bug.cgi?id=11182
The main happens when a session setup with a previous session id
removes the previous session while there's a pending change notify
request.
Please review and push, then I'll prepare backports.
Thanks!
metze
-------------- next part --------------
From 1f562a1066624946f5e71fb6ebfde936ff2e9d10 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 1 May 2015 20:04:55 +0200
Subject: [PATCH 01/17] s3:smbd: add a smbd_notify_cancel_by_map() helper
function
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source3/smbd/notify.c | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c
index 8cb44df..1e86d6a 100644
--- a/source3/smbd/notify.c
+++ b/source3/smbd/notify.c
@@ -375,6 +375,17 @@ static void change_notify_remove_request(struct smbd_server_connection *sconn,
TALLOC_FREE(req);
}
+static void smbd_notify_cancel_by_map(struct notify_mid_map *map)
+{
+ struct smb_request *smbreq = map->req->req;
+ struct smbd_server_connection *sconn = smbreq->sconn;
+ NTSTATUS notify_status = NT_STATUS_CANCELLED;
+
+ change_notify_reply(smbreq, notify_status,
+ 0, NULL, map->req->reply_fn);
+ change_notify_remove_request(sconn, map->req);
+}
+
/****************************************************************************
Delete entries by mid from the change notify pending queue. Always send reply.
*****************************************************************************/
@@ -394,9 +405,7 @@ void remove_pending_change_notify_requests_by_mid(
return;
}
- change_notify_reply(map->req->req,
- NT_STATUS_CANCELLED, 0, NULL, map->req->reply_fn);
- change_notify_remove_request(sconn, map->req);
+ smbd_notify_cancel_by_map(map);
}
void smbd_notify_cancel_by_smbreq(const struct smb_request *smbreq)
@@ -414,9 +423,7 @@ void smbd_notify_cancel_by_smbreq(const struct smb_request *smbreq)
return;
}
- change_notify_reply(map->req->req,
- NT_STATUS_CANCELLED, 0, NULL, map->req->reply_fn);
- change_notify_remove_request(sconn, map->req);
+ smbd_notify_cancel_by_map(map);
}
static struct files_struct *smbd_notify_cancel_deleted_fn(
--
1.9.1
From 3401617d6fce34cf5d2ee2eefb55dc6d1ee84f7d Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 1 May 2015 20:02:38 +0200
Subject: [PATCH 02/17] s3:smbd: use STATUS_NOTIFY_CLEANUP when closing a smb2
directory handle
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
selftest/knownfail | 1 -
source3/smbd/close.c | 15 +++++++++++----
2 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/selftest/knownfail b/selftest/knownfail
index 3262c9c..26aed77 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -189,7 +189,6 @@
^samba3.smb2.create.blob
^samba3.smb2.create.open
^samba3.smb2.notify.valid-req
-^samba3.smb2.notify.dir
^samba3.smb2.notify.rec
^samba3.smb2.durable-open.delete_on_close2
^samba3.smb2.durable-v2-open.app-instance
diff --git a/source3/smbd/close.c b/source3/smbd/close.c
index 09be2e7..0e75bf0 100644
--- a/source3/smbd/close.c
+++ b/source3/smbd/close.c
@@ -1050,6 +1050,13 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
NTSTATUS status1 = NT_STATUS_OK;
const struct security_token *del_nt_token = NULL;
const struct security_unix_token *del_token = NULL;
+ NTSTATUS notify_status;
+
+ if (fsp->conn->sconn->using_smb2) {
+ notify_status = STATUS_NOTIFY_CLEANUP;
+ } else {
+ notify_status = NT_STATUS_OK;
+ }
/*
* NT can set delete_on_close of the last open
@@ -1159,8 +1166,8 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
* now fail as the directory has been deleted.
*/
- if(NT_STATUS_IS_OK(status)) {
- remove_pending_change_notify_requests_by_fid(fsp, NT_STATUS_DELETE_PENDING);
+ if (NT_STATUS_IS_OK(status)) {
+ notify_status = NT_STATUS_DELETE_PENDING;
}
} else {
if (!del_share_mode(lck, fsp)) {
@@ -1169,10 +1176,10 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
}
TALLOC_FREE(lck);
- remove_pending_change_notify_requests_by_fid(
- fsp, NT_STATUS_OK);
}
+ remove_pending_change_notify_requests_by_fid(fsp, notify_status);
+
status1 = fd_close(fsp);
if (!NT_STATUS_IS_OK(status1)) {
--
1.9.1
From e14992a8f907a3ff8eff6fc6739eff24acd95ed8 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 1 May 2015 20:02:38 +0200
Subject: [PATCH 03/17] s3:smbd: use STATUS_NOTIFY_CLEANUP on smb2 logoff
(explicit and implicit) and tdis
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source3/smbd/notify.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c
index 1e86d6a..654d000 100644
--- a/source3/smbd/notify.c
+++ b/source3/smbd/notify.c
@@ -379,8 +379,22 @@ static void smbd_notify_cancel_by_map(struct notify_mid_map *map)
{
struct smb_request *smbreq = map->req->req;
struct smbd_server_connection *sconn = smbreq->sconn;
+ struct smbd_smb2_request *smb2req = smbreq->smb2req;
NTSTATUS notify_status = NT_STATUS_CANCELLED;
+ if (smb2req != NULL) {
+ if (smb2req->session == NULL) {
+ notify_status = STATUS_NOTIFY_CLEANUP;
+ } else if (!NT_STATUS_IS_OK(smb2req->session->status)) {
+ notify_status = STATUS_NOTIFY_CLEANUP;
+ }
+ if (smb2req->tcon == NULL) {
+ notify_status = STATUS_NOTIFY_CLEANUP;
+ } else if (!NT_STATUS_IS_OK(smb2req->tcon->status)) {
+ notify_status = STATUS_NOTIFY_CLEANUP;
+ }
+ }
+
change_notify_reply(smbreq, notify_status,
0, NULL, map->req->reply_fn);
change_notify_remove_request(sconn, map->req);
--
1.9.1
From f946b424894a7be3082de581f33af11fb0ae8058 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 1 May 2015 20:19:42 +0200
Subject: [PATCH 04/17] s4:torture/smb2: verify STATUS_NOTIFY_CLEANUP return
value
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/torture/smb2/notify.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/source4/torture/smb2/notify.c b/source4/torture/smb2/notify.c
index 0f572b6..6c1bf3a 100644
--- a/source4/torture/smb2/notify.c
+++ b/source4/torture/smb2/notify.c
@@ -1309,6 +1309,7 @@ static bool torture_smb2_notify_tree_disconnect_1(
CHECK_STATUS(status, NT_STATUS_OK);
status = smb2_notify_recv(req, torture, &(notify.smb2));
+ CHECK_STATUS(status, STATUS_NOTIFY_CLEANUP);
CHECK_VAL(notify.smb2.out.num_changes, 0);
done:
@@ -1377,6 +1378,7 @@ static bool torture_smb2_notify_ulogoff(struct torture_context *torture,
CHECK_STATUS(status, NT_STATUS_OK);
status = smb2_notify_recv(req, torture, &(notify.smb2));
+ CHECK_STATUS(status, STATUS_NOTIFY_CLEANUP);
CHECK_VAL(notify.smb2.out.num_changes, 0);
done:
--
1.9.1
From 5eb1fc636ab61e67f34de6acabc73d448735e3bb Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 1 May 2015 20:20:50 +0200
Subject: [PATCH 05/17] s4:torture/smb2: add smb2.notify.close test
Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/torture/smb2/notify.c | 70 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 70 insertions(+)
diff --git a/source4/torture/smb2/notify.c b/source4/torture/smb2/notify.c
index 6c1bf3a..d2b3594 100644
--- a/source4/torture/smb2/notify.c
+++ b/source4/torture/smb2/notify.c
@@ -1318,6 +1318,75 @@ done:
}
/*
+ basic testing of change notifies followed by a close
+*/
+
+static bool torture_smb2_notify_close(struct torture_context *torture,
+ struct smb2_tree *tree1)
+{
+ bool ret = true;
+ NTSTATUS status;
+ union smb_notify notify;
+ union smb_open io;
+ struct smb2_handle h1;
+ struct smb2_request *req;
+
+ smb2_deltree(tree1, BASEDIR);
+ smb2_util_rmdir(tree1, BASEDIR);
+
+ torture_comment(torture, "TESTING CHANGE NOTIFY FOLLOWED BY ULOGOFF\n");
+
+ /*
+ get a handle on the directory
+ */
+ ZERO_STRUCT(io.smb2);
+ io.generic.level = RAW_OPEN_SMB2;
+ io.smb2.in.create_flags = 0;
+ io.smb2.in.desired_access = SEC_FILE_ALL;
+ io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+ io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
+ NTCREATEX_SHARE_ACCESS_WRITE;
+ io.smb2.in.alloc_size = 0;
+ io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
+ io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
+ io.smb2.in.security_flags = 0;
+ io.smb2.in.fname = BASEDIR;
+
+ status = smb2_create(tree1, torture, &(io.smb2));
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
+ status = smb2_create(tree1, torture, &(io.smb2));
+ CHECK_STATUS(status, NT_STATUS_OK);
+ h1 = io.smb2.out.file.handle;
+
+ /* ask for a change notify,
+ on file or directory name changes */
+ ZERO_STRUCT(notify.smb2);
+ notify.smb2.level = RAW_NOTIFY_SMB2;
+ notify.smb2.in.buffer_size = 1000;
+ notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
+ notify.smb2.in.file.handle = h1;
+ notify.smb2.in.recursive = true;
+
+ req = smb2_notify_send(tree1, &(notify.smb2));
+
+ WAIT_FOR_ASYNC_RESPONSE(req);
+
+ status = smb2_util_close(tree1, h1);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ status = smb2_notify_recv(req, torture, &(notify.smb2));
+ CHECK_STATUS(status, STATUS_NOTIFY_CLEANUP);
+ CHECK_VAL(notify.smb2.out.num_changes, 0);
+
+done:
+ smb2_deltree(tree1, BASEDIR);
+ return ret;
+}
+
+/*
basic testing of change notifies followed by a ulogoff
*/
@@ -2133,6 +2202,7 @@ struct torture_suite *torture_smb2_notify_init(void)
torture_suite_add_1smb2_test(suite, "tdis", torture_smb2_notify_tree_disconnect);
torture_suite_add_1smb2_test(suite, "tdis1", torture_smb2_notify_tree_disconnect_1);
torture_suite_add_2smb2_test(suite, "mask-change", torture_smb2_notify_mask_change);
+ torture_suite_add_1smb2_test(suite, "close", torture_smb2_notify_close);
torture_suite_add_1smb2_test(suite, "logoff", torture_smb2_notify_ulogoff);
torture_suite_add_1smb2_test(suite, "tree", torture_smb2_notify_tree);
torture_suite_add_2smb2_test(suite, "basedir", torture_smb2_notify_basedir);
--
1.9.1
From 129cc440a8d851e0893ab18236c243e90770e490 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 1 May 2015 20:20:50 +0200
Subject: [PATCH 06/17] s4:torture/smb2: add smb2.notify.invalid-reauth test
An invalid reauth closes the session.
Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/torture/smb2/notify.c | 82 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 82 insertions(+)
diff --git a/source4/torture/smb2/notify.c b/source4/torture/smb2/notify.c
index d2b3594..33df249 100644
--- a/source4/torture/smb2/notify.c
+++ b/source4/torture/smb2/notify.c
@@ -1455,6 +1455,87 @@ done:
return ret;
}
+/*
+ basic testing of change notifies followed by an invalid reauth
+*/
+
+static bool torture_smb2_notify_invalid_reauth(struct torture_context *torture,
+ struct smb2_tree *tree1,
+ struct smb2_tree *tree2)
+{
+ bool ret = true;
+ NTSTATUS status;
+ union smb_notify notify;
+ union smb_open io;
+ struct smb2_handle h1;
+ struct smb2_request *req;
+ struct cli_credentials *invalid_creds;
+
+ smb2_deltree(tree2, BASEDIR);
+ smb2_util_rmdir(tree2, BASEDIR);
+
+ torture_comment(torture, "TESTING CHANGE NOTIFY FOLLOWED BY invalid REAUTH\n");
+
+ /*
+ get a handle on the directory
+ */
+ ZERO_STRUCT(io.smb2);
+ io.generic.level = RAW_OPEN_SMB2;
+ io.smb2.in.create_flags = 0;
+ io.smb2.in.desired_access = SEC_FILE_ALL;
+ io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+ io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
+ NTCREATEX_SHARE_ACCESS_WRITE;
+ io.smb2.in.alloc_size = 0;
+ io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
+ io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
+ io.smb2.in.security_flags = 0;
+ io.smb2.in.fname = BASEDIR;
+
+ status = smb2_create(tree1, torture, &(io.smb2));
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
+ status = smb2_create(tree1, torture, &(io.smb2));
+ CHECK_STATUS(status, NT_STATUS_OK);
+ h1 = io.smb2.out.file.handle;
+
+ /* ask for a change notify,
+ on file or directory name changes */
+ ZERO_STRUCT(notify.smb2);
+ notify.smb2.level = RAW_NOTIFY_SMB2;
+ notify.smb2.in.buffer_size = 1000;
+ notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
+ notify.smb2.in.file.handle = h1;
+ notify.smb2.in.recursive = true;
+
+ req = smb2_notify_send(tree1, &(notify.smb2));
+
+ WAIT_FOR_ASYNC_RESPONSE(req);
+
+ invalid_creds = cli_credentials_init(torture);
+ torture_assert(torture, (invalid_creds != NULL), "talloc error");
+ cli_credentials_set_username(invalid_creds, "__none__invalid__none__", CRED_SPECIFIED);
+ cli_credentials_set_domain(invalid_creds, "__none__invalid__none__", CRED_SPECIFIED);
+ cli_credentials_set_password(invalid_creds, "__none__invalid__none__", CRED_SPECIFIED);
+ cli_credentials_set_realm(invalid_creds, NULL, CRED_SPECIFIED);
+ cli_credentials_set_workstation(invalid_creds, "", CRED_UNINITIALISED);
+
+ status = smb2_session_setup_spnego(tree1->session,
+ invalid_creds,
+ 0 /* previous_session_id */);
+ CHECK_STATUS(status, NT_STATUS_LOGON_FAILURE);
+
+ status = smb2_notify_recv(req, torture, &(notify.smb2));
+ CHECK_STATUS(status, STATUS_NOTIFY_CLEANUP);
+ CHECK_VAL(notify.smb2.out.num_changes, 0);
+
+done:
+ smb2_deltree(tree2, BASEDIR);
+ return ret;
+}
+
static void tcp_dis_handler(struct smb2_transport *t, void *p)
{
struct smb2_tree *tree = (struct smb2_tree *)p;
@@ -2204,6 +2285,7 @@ struct torture_suite *torture_smb2_notify_init(void)
torture_suite_add_2smb2_test(suite, "mask-change", torture_smb2_notify_mask_change);
torture_suite_add_1smb2_test(suite, "close", torture_smb2_notify_close);
torture_suite_add_1smb2_test(suite, "logoff", torture_smb2_notify_ulogoff);
+ torture_suite_add_2smb2_test(suite, "invalid-reauth", torture_smb2_notify_invalid_reauth);
torture_suite_add_1smb2_test(suite, "tree", torture_smb2_notify_tree);
torture_suite_add_2smb2_test(suite, "basedir", torture_smb2_notify_basedir);
torture_suite_add_2smb2_test(suite, "double", torture_smb2_notify_double);
--
1.9.1
From 58983932d7d780e86d56832fafd9eca6b062315e Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Sat, 2 May 2015 09:57:03 +0200
Subject: [PATCH 07/17] s4:torture/smb2: add smb2.notify.session-reconnect test
Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/torture/smb2/notify.c | 81 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 81 insertions(+)
diff --git a/source4/torture/smb2/notify.c b/source4/torture/smb2/notify.c
index 33df249..b804ebc 100644
--- a/source4/torture/smb2/notify.c
+++ b/source4/torture/smb2/notify.c
@@ -1456,6 +1456,86 @@ done:
}
/*
+ basic testing of change notifies followed by a session reconnect
+*/
+
+static bool torture_smb2_notify_session_reconnect(struct torture_context *torture,
+ struct smb2_tree *tree1)
+{
+ bool ret = true;
+ NTSTATUS status;
+ union smb_notify notify;
+ union smb_open io;
+ struct smb2_handle h1;
+ struct smb2_request *req;
+ uint64_t previous_session_id = 0;
+ struct smb2_session *session2 = NULL;
+
+ smb2_deltree(tree1, BASEDIR);
+ smb2_util_rmdir(tree1, BASEDIR);
+
+ torture_comment(torture, "TESTING CHANGE NOTIFY FOLLOWED BY SESSION RECONNECT\n");
+
+ /*
+ get a handle on the directory
+ */
+ ZERO_STRUCT(io.smb2);
+ io.generic.level = RAW_OPEN_SMB2;
+ io.smb2.in.create_flags = 0;
+ io.smb2.in.desired_access = SEC_FILE_ALL;
+ io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+ io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
+ NTCREATEX_SHARE_ACCESS_WRITE;
+ io.smb2.in.alloc_size = 0;
+ io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
+ io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
+ io.smb2.in.security_flags = 0;
+ io.smb2.in.fname = BASEDIR;
+
+ status = smb2_create(tree1, torture, &(io.smb2));
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
+ status = smb2_create(tree1, torture, &(io.smb2));
+ CHECK_STATUS(status, NT_STATUS_OK);
+ h1 = io.smb2.out.file.handle;
+
+ /* ask for a change notify,
+ on file or directory name changes */
+ ZERO_STRUCT(notify.smb2);
+ notify.smb2.level = RAW_NOTIFY_SMB2;
+ notify.smb2.in.buffer_size = 1000;
+ notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
+ notify.smb2.in.file.handle = h1;
+ notify.smb2.in.recursive = true;
+
+ req = smb2_notify_send(tree1, &(notify.smb2));
+
+ WAIT_FOR_ASYNC_RESPONSE(req);
+
+ previous_session_id = smb2cli_session_current_id(tree1->session->smbXcli);
+ torture_assert(torture, torture_smb2_session_setup(torture,
+ tree1->session->transport,
+ previous_session_id,
+ torture, &session2),
+ "session setup with previous_session_id failed");
+
+ status = smb2_notify_recv(req, torture, &(notify.smb2));
+ CHECK_STATUS(status, STATUS_NOTIFY_CLEANUP);
+ CHECK_VAL(notify.smb2.out.num_changes, 0);
+
+ status = smb2_logoff(tree1->session);
+ CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED);
+
+ status = smb2_logoff(session2);
+ CHECK_STATUS(status, NT_STATUS_OK);
+done:
+ smb2_deltree(tree1, BASEDIR);
+ return ret;
+}
+
+/*
basic testing of change notifies followed by an invalid reauth
*/
@@ -2285,6 +2365,7 @@ struct torture_suite *torture_smb2_notify_init(void)
torture_suite_add_2smb2_test(suite, "mask-change", torture_smb2_notify_mask_change);
torture_suite_add_1smb2_test(suite, "close", torture_smb2_notify_close);
torture_suite_add_1smb2_test(suite, "logoff", torture_smb2_notify_ulogoff);
+ torture_suite_add_1smb2_test(suite, "session-reconnect", torture_smb2_notify_session_reconnect);
torture_suite_add_2smb2_test(suite, "invalid-reauth", torture_smb2_notify_invalid_reauth);
torture_suite_add_1smb2_test(suite, "tree", torture_smb2_notify_tree);
torture_suite_add_2smb2_test(suite, "basedir", torture_smb2_notify_basedir);
--
1.9.1
From 69981547f8218af6e431664829060213717f0d4d Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Sat, 2 May 2015 16:09:40 +0200
Subject: [PATCH 08/17] s3:smbXsrv_session: clear smb2req->session of pending
requests in smbXsrv_session_destructor()
This won't be needed typically needed as the caller is supposted to cancel
the requests already, but this makes sure we don't keep dangling pointers.
Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source3/smbd/smbXsrv_session.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/source3/smbd/smbXsrv_session.c b/source3/smbd/smbXsrv_session.c
index a49e246..41625fc 100644
--- a/source3/smbd/smbXsrv_session.c
+++ b/source3/smbd/smbXsrv_session.c
@@ -1066,6 +1066,29 @@ NTSTATUS smb2srv_session_close_previous_recv(struct tevent_req *req)
static int smbXsrv_session_destructor(struct smbXsrv_session *session)
{
NTSTATUS status;
+ struct smbXsrv_connection *xconn = NULL;
+
+ if (session->client != NULL) {
+ xconn = session->client->connections;
+ }
+
+ for (; xconn != NULL; xconn = xconn->next) {
+ struct smbd_smb2_request *preq;
+
+ for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
+ if (preq->session != session) {
+ continue;
+ }
+
+ preq->session = NULL;
+ /*
+ * If we no longer have a session we can't
+ * sign or encrypt replies.
+ */
+ preq->do_signing = false;
+ preq->do_encryption = false;
+ }
+ }
status = smbXsrv_session_logoff(session);
if (!NT_STATUS_IS_OK(status)) {
--
1.9.1
From 7a559800ff4ee892065ad3c155173562998bb779 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Sat, 2 May 2015 16:17:34 +0200
Subject: [PATCH 09/17] s3:smbXsrv_session: clear smb2req->session of pending
requests in smbXsrv_session_logoff_all_callback()
smbXsrv_session_logoff_all_callback() is called when the last transport
connection is gone, which means we won't need to sign any response...
Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source3/smbd/smbXsrv_session.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/source3/smbd/smbXsrv_session.c b/source3/smbd/smbXsrv_session.c
index 41625fc..5ee4bbe 100644
--- a/source3/smbd/smbXsrv_session.c
+++ b/source3/smbd/smbXsrv_session.c
@@ -1503,6 +1503,7 @@ static int smbXsrv_session_logoff_all_callback(struct db_record *local_rec,
TDB_DATA val;
void *ptr = NULL;
struct smbXsrv_session *session = NULL;
+ struct smbXsrv_connection *xconn = NULL;
NTSTATUS status;
val = dbwrap_record_get_value(local_rec);
@@ -1519,6 +1520,28 @@ static int smbXsrv_session_logoff_all_callback(struct db_record *local_rec,
session = talloc_get_type_abort(ptr, struct smbXsrv_session);
session->db_rec = local_rec;
+
+ if (session->client != NULL) {
+ xconn = session->client->connections;
+ }
+ for (; xconn != NULL; xconn = xconn->next) {
+ struct smbd_smb2_request *preq;
+
+ for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
+ if (preq->session != session) {
+ continue;
+ }
+
+ preq->session = NULL;
+ /*
+ * If we no longer have a session we can't
+ * sign or encrypt replies.
+ */
+ preq->do_signing = false;
+ preq->do_encryption = false;
+ }
+ }
+
status = smbXsrv_session_logoff(session);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_IS_OK(state->first_status)) {
--
1.9.1
From c93e311eb941d2ceb3a730b4b015026ed2724863 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Sat, 2 May 2015 09:57:03 +0200
Subject: [PATCH 10/17] s3:smbXsrv_session: add
smbXsrv_session_shutdown_send/recv helper functions
Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source3/smbd/globals.h | 5 ++
source3/smbd/smbXsrv_session.c | 121 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 126 insertions(+)
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index b52c6a9..ca94459 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -537,6 +537,11 @@ struct smbXsrv_channel_global0;
NTSTATUS smbXsrv_session_find_channel(const struct smbXsrv_session *session,
const struct smbXsrv_connection *conn,
struct smbXsrv_channel_global0 **_c);
+struct tevent_req *smbXsrv_session_shutdown_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct smbXsrv_session *session,
+ struct smbd_smb2_request *current_req);
+NTSTATUS smbXsrv_session_shutdown_recv(struct tevent_req *req);
NTSTATUS smbXsrv_session_logoff(struct smbXsrv_session *session);
NTSTATUS smbXsrv_session_logoff_all(struct smbXsrv_connection *conn);
NTSTATUS smb1srv_session_table_init(struct smbXsrv_connection *conn);
diff --git a/source3/smbd/smbXsrv_session.c b/source3/smbd/smbXsrv_session.c
index 5ee4bbe..5b60f8d 100644
--- a/source3/smbd/smbXsrv_session.c
+++ b/source3/smbd/smbXsrv_session.c
@@ -1327,6 +1327,127 @@ NTSTATUS smbXsrv_session_find_channel(const struct smbXsrv_session *session,
return NT_STATUS_USER_SESSION_DELETED;
}
+struct smbXsrv_session_shutdown_state {
+ struct tevent_queue *wait_queue;
+};
+
+static void smbXsrv_session_shutdown_wait_done(struct tevent_req *subreq);
+
+struct tevent_req *smbXsrv_session_shutdown_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct smbXsrv_session *session,
+ struct smbd_smb2_request *current_req)
+{
+ struct tevent_req *req;
+ struct smbXsrv_session_shutdown_state *state;
+ struct tevent_req *subreq;
+ struct smbXsrv_connection *xconn = NULL;
+ size_t len = 0;
+
+ /*
+ * Make sure that no new request will be able to use this session.
+ */
+ session->status = NT_STATUS_USER_SESSION_DELETED;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct smbXsrv_session_shutdown_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ state->wait_queue = tevent_queue_create(state, "smbXsrv_session_shutdown_queue");
+ if (tevent_req_nomem(state->wait_queue, req)) {
+ return tevent_req_post(req, ev);
+ }
+
+ for (xconn = session->client->connections; xconn != NULL; xconn = xconn->next) {
+ struct smbd_smb2_request *preq;
+
+ for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
+ if (preq == current_req) {
+ /* Can't cancel current request. */
+ continue;
+ }
+ if (preq->session != session) {
+ /* Request on different session. */
+ continue;
+ }
+
+ if (!NT_STATUS_IS_OK(xconn->transport.status)) {
+ preq->session = NULL;
+ /*
+ * If we no longer have a session we can't
+ * sign or encrypt replies.
+ */
+ preq->do_signing = false;
+ preq->do_encryption = false;
+
+ if (preq->subreq != NULL) {
+ tevent_req_cancel(preq->subreq);
+ }
+ continue;
+ }
+
+ /*
+ * Never cancel anything in a compound
+ * request. Way too hard to deal with
+ * the result.
+ */
+ if (!preq->compound_related && preq->subreq != NULL) {
+ tevent_req_cancel(preq->subreq);
+ }
+
+ /*
+ * Now wait until the request is finished.
+ *
+ * We don't set a callback, as we just want to block the
+ * wait queue and the talloc_free() of the request will
+ * remove the item from the wait queue.
+ */
+ subreq = tevent_queue_wait_send(preq, ev, state->wait_queue);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ }
+ }
+
+ len = tevent_queue_length(state->wait_queue);
+ if (len == 0) {
+ tevent_req_done(req);
+ return tevent_req_post(req, ev);
+ }
+
+ /*
+ * Now we add our own waiter to the end of the queue,
+ * this way we get notified when all pending requests are finished
+ * and send to the socket.
+ */
+ subreq = tevent_queue_wait_send(state, ev, state->wait_queue);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, smbXsrv_session_shutdown_wait_done, req);
+
+ return req;
+}
+
+static void smbXsrv_session_shutdown_wait_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req =
+ tevent_req_callback_data(subreq,
+ struct tevent_req);
+
+ tevent_queue_wait_recv(subreq);
+ TALLOC_FREE(subreq);
+
+ tevent_req_done(req);
+}
+
+NTSTATUS smbXsrv_session_shutdown_recv(struct tevent_req *req)
+{
+ return tevent_req_simple_recv_ntstatus(req);
+}
+
NTSTATUS smbXsrv_session_logoff(struct smbXsrv_session *session)
{
struct smbXsrv_session_table *table;
--
1.9.1
From 6f28d07079f741e2ca7b33d17d65fc0961be76aa Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <