The Samba-Bugzilla – Attachment 11012 Details for
Bug 11182
Panic triggered by smbd_smb2_request_notify_done() -> smbXsrv_session_find_channel() in smbd
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Work in progress patches (on v4-2-test)
tmp.diff.txt (text/plain), 51.79 KB, created by
Stefan Metzmacher
on 2015-05-03 08:10:16 UTC
(
hide
)
Description:
Work in progress patches (on v4-2-test)
Filename:
MIME Type:
Creator:
Stefan Metzmacher
Created:
2015-05-03 08:10:16 UTC
Size:
51.79 KB
patch
obsolete
>From bc53009bf52f669c288c1962ac6e1635646e14db Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 1 May 2015 20:04:55 +0200 >Subject: [PATCH 01/18] s3:smbd: add a smbd_notify_cancel_by_map() helper > function > >Signed-off-by: Stefan Metzmacher <metze@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 ac1a55c..0a0ae83 100644 >--- a/source3/smbd/notify.c >+++ b/source3/smbd/notify.c >@@ -374,6 +374,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. > *****************************************************************************/ >@@ -393,9 +404,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) >@@ -413,9 +422,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); > } > > /**************************************************************************** >-- >1.9.1 > > >From bbe28ff6f24e08cae19a38d3cb4e14b6f2338461 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 1 May 2015 20:02:38 +0200 >Subject: [PATCH 02/18] s3:smbd: use STATUS_NOTIFY_CLEANUP when closing a smb2 > directory handle > >Signed-off-by: Stefan Metzmacher <metze@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 af7e7fd..8b26630 100644 >--- a/selftest/knownfail >+++ b/selftest/knownfail >@@ -187,7 +187,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 4fbd442f..fc1d380 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 07afb8aedd4cdb7da3d7c15e773b8f3478c91a3e Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 1 May 2015 20:02:38 +0200 >Subject: [PATCH 03/18] s3:smbd: use STATUS_NOTIFY_CLEANUP on smb2 logoff > (explicit and implicit) and tdis > >Signed-off-by: Stefan Metzmacher <metze@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 0a0ae83..0e4969d 100644 >--- a/source3/smbd/notify.c >+++ b/source3/smbd/notify.c >@@ -378,8 +378,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 21b885f9d9a5644151047fb622ea1cbdde095ec3 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 1 May 2015 20:19:42 +0200 >Subject: [PATCH 04/18] s4:torture/smb2: verify STATUS_NOTIFY_CLEANUP return > value > >Signed-off-by: Stefan Metzmacher <metze@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 c721d5f..827f5d5 100644 >--- a/source4/torture/smb2/notify.c >+++ b/source4/torture/smb2/notify.c >@@ -1304,6 +1304,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: >@@ -1372,6 +1373,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 4e5b42e9495b9c4e7565c5df58c17e8756f124b6 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 1 May 2015 20:20:50 +0200 >Subject: [PATCH 05/18] s4:torture/smb2: add smb2.notify.close test > >Signed-off-by: Stefan Metzmacher <metze@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 827f5d5..e9cfeda 100644 >--- a/source4/torture/smb2/notify.c >+++ b/source4/torture/smb2/notify.c >@@ -1313,6 +1313,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 > */ > >@@ -2026,6 +2095,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 f78b497c5788cba9a7cc6187233088891d44b0c5 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 1 May 2015 20:20:50 +0200 >Subject: [PATCH 06/18] s4:torture/smb2: add smb2.notify.invalid-reauth test > >An invalid reauth closes the session. > >Signed-off-by: Stefan Metzmacher <metze@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 e9cfeda..fe496c8 100644 >--- a/source4/torture/smb2/notify.c >+++ b/source4/torture/smb2/notify.c >@@ -1450,6 +1450,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; >@@ -2097,6 +2178,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 7c28c7bf879d8de55116acc4c51f4ecec4526c4e Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 1 May 2015 20:26:41 +0200 >Subject: [PATCH 07/18] HACK try to reproduce > https://bugzilla.samba.org/show_bug.cgi?id=11182 require signing > >--- > selftest/target/Samba3.pm | 1 + > 1 file changed, 1 insertion(+) > >diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm >index d8eb58c..66d0bd6 100755 >--- a/selftest/target/Samba3.pm >+++ b/selftest/target/Samba3.pm >@@ -203,6 +203,7 @@ sub setup_s3dc($$) > domain master = yes > domain logons = yes > lanman auth = yes >+ server signing = required > > rpc_server:epmapper = external > rpc_server:spoolss = external >-- >1.9.1 > > >From 14ba2e3b24ca1d677dc59dc2c7e80b59c7270d12 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 1 May 2015 20:26:41 +0200 >Subject: [PATCH 08/18] HACK try to reproduce > https://bugzilla.samba.org/show_bug.cgi?id=11182 invalid pointer > >--- > source3/smbd/smb2_sesssetup.c | 14 +++++++------- > 1 file changed, 7 insertions(+), 7 deletions(-) > >diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c >index 57f623a..7f0e845 100644 >--- a/source3/smbd/smb2_sesssetup.c >+++ b/source3/smbd/smb2_sesssetup.c >@@ -497,13 +497,13 @@ static int smbd_smb2_session_setup_state_destructor(struct smbd_smb2_session_set > continue; > } > if (preq->session == state->smb2req->session) { >- 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; >+ preq->session += 537; >+ // /* >+ // * If we no longer have a session we can't >+ // * sign or encrypt replies. >+ // */ >+ // preq->do_signing = false; >+ // preq->do_encryption = false; > } > } > >-- >1.9.1 > > >From 567903de4afcaeaff69bc17cc744777a33b382e4 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Sat, 2 May 2015 09:05:32 +0200 >Subject: [PATCH 09/18] Revert "HACK try to reproduce > https://bugzilla.samba.org/show_bug.cgi?id=11182 invalid pointer" > >This reverts commit 14ba2e3b24ca1d677dc59dc2c7e80b59c7270d12. >--- > source3/smbd/smb2_sesssetup.c | 14 +++++++------- > 1 file changed, 7 insertions(+), 7 deletions(-) > >diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c >index 7f0e845..57f623a 100644 >--- a/source3/smbd/smb2_sesssetup.c >+++ b/source3/smbd/smb2_sesssetup.c >@@ -497,13 +497,13 @@ static int smbd_smb2_session_setup_state_destructor(struct smbd_smb2_session_set > continue; > } > if (preq->session == state->smb2req->session) { >- preq->session += 537; >- // /* >- // * If we no longer have a session we can't >- // * sign or encrypt replies. >- // */ >- // preq->do_signing = false; >- // preq->do_encryption = false; >+ 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; > } > } > >-- >1.9.1 > > >From bb21cbcda5adb70717155e00a1930d37779da58e Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Sat, 2 May 2015 09:57:03 +0200 >Subject: [PATCH 10/18] s3:smbXsrv_session: add > smbXsrv_session_shutdown_send/recv helper functions > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source3/smbd/globals.h | 5 ++ > source3/smbd/smbXsrv_session.c | 103 +++++++++++++++++++++++++++++++++++++++++ > source4/torture/smb2/notify.c | 81 ++++++++++++++++++++++++++++++++ > 3 files changed, 189 insertions(+) > >diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h >index eacc5b3..b8c2a82 100644 >--- a/source3/smbd/globals.h >+++ b/source3/smbd/globals.h >@@ -535,6 +535,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 7eca968..431abad 100644 >--- a/source3/smbd/smbXsrv_session.c >+++ b/source3/smbd/smbXsrv_session.c >@@ -1298,6 +1298,109 @@ 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; >+ >+ 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); >+ } >+ >+ /* >+ * Make sure that no new request will be able to use this session. >+ */ >+ session->status = NT_STATUS_USER_SESSION_DELETED; >+ >+ 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; >+ } >+ >+ /* >+ * 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); >+ } >+ } >+ } >+ >+ /* >+ * 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); >+ struct smbXsrv_session_shutdown_state *state = >+ tevent_req_data(req, >+ struct smbXsrv_session_shutdown_state); >+ NTSTATUS status; >+ >+ 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; >diff --git a/source4/torture/smb2/notify.c b/source4/torture/smb2/notify.c >index fe496c8..5589559 100644 >--- a/source4/torture/smb2/notify.c >+++ b/source4/torture/smb2/notify.c >@@ -1451,6 +1451,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 > */ > >@@ -2178,6 +2258,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 ab48440b2787633d2055763673682579adb4f154 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Sat, 2 May 2015 16:09:40 +0200 >Subject: [PATCH 11/18] 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. > >Signed-off-by: Stefan Metzmacher <metze@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 431abad..3bc132b 100644 >--- a/source3/smbd/smbXsrv_session.c >+++ b/source3/smbd/smbXsrv_session.c >@@ -1060,6 +1060,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 d77aca493145cbc69a161fc101d0938584dd64ce Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Sat, 2 May 2015 16:12:15 +0200 >Subject: [PATCH 12/18] isq add smbXsrv_session_shutdown_ > >--- > source3/smbd/smbXsrv_session.c | 40 +++++++++++++++++++++++++++++----------- > 1 file changed, 29 insertions(+), 11 deletions(-) > >diff --git a/source3/smbd/smbXsrv_session.c b/source3/smbd/smbXsrv_session.c >index 3bc132b..b72ae6a 100644 >--- a/source3/smbd/smbXsrv_session.c >+++ b/source3/smbd/smbXsrv_session.c >@@ -1335,10 +1335,16 @@ struct tevent_req *smbXsrv_session_shutdown_send(TALLOC_CTX *mem_ctx, > struct tevent_req *req; > struct smbXsrv_session_shutdown_state *state; > struct tevent_req *subreq; >- struct smbXsrv_connection *xconn; >+ 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); >+ struct smbXsrv_session_shutdown_state); > if (req == NULL) { > return NULL; > } >@@ -1348,11 +1354,6 @@ struct tevent_req *smbXsrv_session_shutdown_send(TALLOC_CTX *mem_ctx, > return tevent_req_post(req, ev); > } > >- /* >- * Make sure that no new request will be able to use this session. >- */ >- session->status = NT_STATUS_USER_SESSION_DELETED; >- > for (xconn = session->client->connections; xconn != NULL; xconn = xconn->next) { > struct smbd_smb2_request *preq; > >@@ -1366,6 +1367,21 @@ struct tevent_req *smbXsrv_session_shutdown_send(TALLOC_CTX *mem_ctx, > 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 >@@ -1389,6 +1405,12 @@ struct tevent_req *smbXsrv_session_shutdown_send(TALLOC_CTX *mem_ctx, > } > } > >+ 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 >@@ -1408,10 +1430,6 @@ static void smbXsrv_session_shutdown_wait_done(struct tevent_req *subreq) > struct tevent_req *req = > tevent_req_callback_data(subreq, > struct tevent_req); >- struct smbXsrv_session_shutdown_state *state = >- tevent_req_data(req, >- struct smbXsrv_session_shutdown_state); >- NTSTATUS status; > > tevent_queue_wait_recv(subreq); > TALLOC_FREE(subreq); >-- >1.9.1 > > >From 968202f14fb42d6b4a5e11aee8990c920b834532 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Sat, 2 May 2015 16:13:27 +0200 >Subject: [PATCH 13/18] TODO s3:smbXsrv_session: cancel pending requests when > we logoff a previous session > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> > >TODO: simple fix before in order to make backports easier > maybe the destructor fix already helps >--- > source3/smbd/smbXsrv_session.c | 45 +++++++++++++++++++++++++++++++++++------- > 1 file changed, 38 insertions(+), 7 deletions(-) > >diff --git a/source3/smbd/smbXsrv_session.c b/source3/smbd/smbXsrv_session.c >index b72ae6a..4b4355e 100644 >--- a/source3/smbd/smbXsrv_session.c >+++ b/source3/smbd/smbXsrv_session.c >@@ -222,6 +222,8 @@ static NTSTATUS smbXsrv_session_table_init(struct smbXsrv_connection *conn, > return NT_STATUS_OK; > } > >+static void smbXsrv_session_close_shutdown_done(struct tevent_req *subreq); >+ > static void smbXsrv_session_close_loop(struct tevent_req *subreq) > { > struct smbXsrv_client *client = >@@ -326,20 +328,22 @@ static void smbXsrv_session_close_loop(struct tevent_req *subreq) > goto next; > } > >- /* >- * TODO: cancel all outstanding requests on the session >- */ >- status = smbXsrv_session_logoff(session); >- if (!NT_STATUS_IS_OK(status)) { >+ subreq = smbXsrv_session_shutdown_send(session, client->ev_ctx, >+ session, NULL); >+ if (subreq == NULL) { >+ status = NT_STATUS_NO_MEMORY; > DEBUG(0, ("smbXsrv_session_close_loop: " >- "smbXsrv_session_logoff(%llu) failed: %s\n", >+ "smbXsrv_session_shutdown_send(%llu) failed: %s\n", > (unsigned long long)session->global->session_wire_id, > nt_errstr(status))); > if (DEBUGLVL(1)) { > NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob); > } >+ goto next; > } >- TALLOC_FREE(session); >+ tevent_req_set_callback(subreq, >+ smbXsrv_session_close_shutdown_done, >+ session); > > next: > TALLOC_FREE(rec); >@@ -355,6 +359,33 @@ next: > tevent_req_set_callback(subreq, smbXsrv_session_close_loop, client); > } > >+static void smbXsrv_session_close_shutdown_done(struct tevent_req *subreq) >+{ >+ struct smbXsrv_session *session = >+ tevent_req_callback_data(subreq, >+ struct smbXsrv_session); >+ NTSTATUS status; >+ >+ status = smbXsrv_session_shutdown_recv(subreq); >+ TALLOC_FREE(subreq); >+ if (!NT_STATUS_IS_OK(status)) { >+ DEBUG(0, ("smbXsrv_session_close_loop: " >+ "smbXsrv_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)) { >+ DEBUG(0, ("smbXsrv_session_close_loop: " >+ "smbXsrv_session_logoff(%llu) failed: %s\n", >+ (unsigned long long)session->global->session_wire_id, >+ nt_errstr(status))); >+ } >+ >+ TALLOC_FREE(session); >+} >+ > struct smb1srv_session_local_allocate_state { > const uint32_t lowest_id; > const uint32_t highest_id; >-- >1.9.1 > > >From 99ed051b51ea14092a3e8be464ecb84acdf6b92d Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Sat, 2 May 2015 16:17:34 +0200 >Subject: [PATCH 14/18] NEEDED? smbXsrv_session_logoff_all_callback() > >destructor cleans up >--- > source3/smbd/smbXsrv_session.c | 46 ++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 46 insertions(+) > >diff --git a/source3/smbd/smbXsrv_session.c b/source3/smbd/smbXsrv_session.c >index 4b4355e..38e0af3 100644 >--- a/source3/smbd/smbXsrv_session.c >+++ b/source3/smbd/smbXsrv_session.c >@@ -1649,6 +1649,8 @@ static int smbXsrv_session_logoff_all_callback(struct db_record *local_rec, > TDB_DATA val; > void *ptr = NULL; > struct smbXsrv_session *session = NULL; >+ struct tevent_context *ev = NULL; >+ struct tevent_req *subreq = NULL; > NTSTATUS status; > > val = dbwrap_record_get_value(local_rec); >@@ -1665,6 +1667,50 @@ 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; >+ >+ ev = samba_tevent_context_init(session); >+ if (ev == NULL) { >+ status = NT_STATUS_NO_MEMORY; >+ if (NT_STATUS_IS_OK(state->first_status)) { >+ state->first_status = status; >+ } >+ state->errors++; >+ return 0; >+ } >+ >+ subreq = smbXsrv_session_shutdown_send(ev, ev, session, NULL); >+ if (subreq == NULL) { >+ TALLOC_FREE(ev); >+ status = NT_STATUS_NO_MEMORY; >+ if (NT_STATUS_IS_OK(state->first_status)) { >+ state->first_status = status; >+ } >+ state->errors++; >+ return 0; >+ } >+ if (tevent_req_is_in_progress(subreq)) { >+ /* >+ * The last transport connection is gone >+ * we don't expect to wait. >+ */ >+ TALLOC_FREE(ev); >+ status = NT_STATUS_INTERNAL_ERROR; >+ if (NT_STATUS_IS_OK(state->first_status)) { >+ state->first_status = status; >+ } >+ state->errors++; >+ return 0; >+ } >+ status = smbXsrv_session_shutdown_recv(subreq); >+ TALLOC_FREE(ev); >+ if (!NT_STATUS_IS_OK(status)) { >+ if (NT_STATUS_IS_OK(state->first_status)) { >+ state->first_status = status; >+ } >+ state->errors++; >+ return 0; >+ } >+ > status = smbXsrv_session_logoff(session); > if (!NT_STATUS_IS_OK(status)) { > if (NT_STATUS_IS_OK(state->first_status)) { >-- >1.9.1 > > >From 52989d4b9cf68ded05a45680d9c2ece9c2a03bd6 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Sat, 2 May 2015 16:20:06 +0200 >Subject: [PATCH 15/18] s3:smb2_sesssetup: let smbd_smb2_logoff_* use > smbXsrv_session_shutdown_* > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source3/smbd/smb2_sesssetup.c | 75 +++++++++---------------------------------- > 1 file changed, 15 insertions(+), 60 deletions(-) > >diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c >index 57f623a..27bcfa4 100644 >--- a/source3/smbd/smb2_sesssetup.c >+++ b/source3/smbd/smb2_sesssetup.c >@@ -855,95 +855,50 @@ static void smbd_smb2_request_logoff_done(struct tevent_req *subreq) > } > } > >-struct smbd_smb2_logout_state { >+struct smbd_smb2_logoff_state { > struct smbd_smb2_request *smb2req; >- struct tevent_queue *wait_queue; > }; > >-static void smbd_smb2_logoff_wait_done(struct tevent_req *subreq); >+static void smbd_smb2_logoff_shutdown_done(struct tevent_req *subreq); > > static struct tevent_req *smbd_smb2_logoff_send(TALLOC_CTX *mem_ctx, > struct tevent_context *ev, > struct smbd_smb2_request *smb2req) > { > struct tevent_req *req; >- struct smbd_smb2_logout_state *state; >+ struct smbd_smb2_logoff_state *state; > struct tevent_req *subreq; >- struct smbd_smb2_request *preq; >- struct smbXsrv_connection *xconn = smb2req->xconn; > > req = tevent_req_create(mem_ctx, &state, >- struct smbd_smb2_logout_state); >+ struct smbd_smb2_logoff_state); > if (req == NULL) { > return NULL; > } > state->smb2req = smb2req; > >- state->wait_queue = tevent_queue_create(state, "logoff_wait_queue"); >- if (tevent_req_nomem(state->wait_queue, req)) { >- return tevent_req_post(req, ev); >- } >- >- /* >- * Make sure that no new request will be able to use this session. >- */ >- smb2req->session->status = NT_STATUS_USER_SESSION_DELETED; >- >- for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) { >- if (preq == smb2req) { >- /* Can't cancel current request. */ >- continue; >- } >- if (preq->session != smb2req->session) { >- /* Request on different session. */ >- 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); >- } >- } >- >- /* >- * 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); >+ subreq = smbXsrv_session_shutdown_send(state, ev, >+ smb2req->session, >+ smb2req); > if (tevent_req_nomem(subreq, req)) { > return tevent_req_post(req, ev); > } >- tevent_req_set_callback(subreq, smbd_smb2_logoff_wait_done, req); >+ tevent_req_set_callback(subreq, smbd_smb2_logoff_shutdown_done, req); > > return req; > } > >-static void smbd_smb2_logoff_wait_done(struct tevent_req *subreq) >+static void smbd_smb2_logoff_shutdown_done(struct tevent_req *subreq) > { > struct tevent_req *req = tevent_req_callback_data( > subreq, struct tevent_req); >- struct smbd_smb2_logout_state *state = tevent_req_data( >- req, struct smbd_smb2_logout_state); >+ struct smbd_smb2_logoff_state *state = tevent_req_data( >+ req, struct smbd_smb2_logoff_state); > NTSTATUS status; > >- tevent_queue_wait_recv(subreq); >+ status = smbXsrv_session_shutdown_recv(subreq); >+ if (tevent_req_nterror(req, status)) { >+ return; >+ } > TALLOC_FREE(subreq); > > /* >-- >1.9.1 > > >From d8e42d079f0c41954685050719e723870e5ad3e8 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Sat, 2 May 2015 16:21:25 +0200 >Subject: [PATCH 16/18] s3:smb2_sesssetup: add > smbd_smb2_session_setup_wrap_send/recv() > >The wrapper calls smbXsrv_session_shutdown_send/recv() in case of an error, >this makes sure a failing reauth shuts down the session like an explicit logoff. > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source3/smbd/smb2_sesssetup.c | 186 ++++++++++++++++++++++++++++++++++++++---- > 1 file changed, 171 insertions(+), 15 deletions(-) > >diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c >index 27bcfa4..e1d4db3 100644 >--- a/source3/smbd/smb2_sesssetup.c >+++ b/source3/smbd/smb2_sesssetup.c >@@ -29,7 +29,7 @@ > #include "../libcli/security/security.h" > #include "../lib/util/tevent_ntstatus.h" > >-static struct tevent_req *smbd_smb2_session_setup_send(TALLOC_CTX *mem_ctx, >+static struct tevent_req *smbd_smb2_session_setup_wrap_send(TALLOC_CTX *mem_ctx, > struct tevent_context *ev, > struct smbd_smb2_request *smb2req, > uint64_t in_session_id, >@@ -37,7 +37,7 @@ static struct tevent_req *smbd_smb2_session_setup_send(TALLOC_CTX *mem_ctx, > uint8_t in_security_mode, > uint64_t in_previous_session_id, > DATA_BLOB in_security_buffer); >-static NTSTATUS smbd_smb2_session_setup_recv(struct tevent_req *req, >+static NTSTATUS smbd_smb2_session_setup_wrap_recv(struct tevent_req *req, > uint16_t *out_session_flags, > TALLOC_CTX *mem_ctx, > DATA_BLOB *out_security_buffer, >@@ -87,14 +87,14 @@ NTSTATUS smbd_smb2_request_process_sesssetup(struct smbd_smb2_request *smb2req) > in_security_buffer.data = SMBD_SMB2_IN_DYN_PTR(smb2req); > in_security_buffer.length = in_security_length; > >- subreq = smbd_smb2_session_setup_send(smb2req, >- smb2req->sconn->ev_ctx, >- smb2req, >- in_session_id, >- in_flags, >- in_security_mode, >- in_previous_session_id, >- in_security_buffer); >+ subreq = smbd_smb2_session_setup_wrap_send(smb2req, >+ smb2req->sconn->ev_ctx, >+ smb2req, >+ in_session_id, >+ in_flags, >+ in_security_mode, >+ in_previous_session_id, >+ in_security_buffer); > if (subreq == NULL) { > return smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY); > } >@@ -118,11 +118,11 @@ static void smbd_smb2_request_sesssetup_done(struct tevent_req *subreq) > NTSTATUS status; > NTSTATUS error; /* transport error */ > >- status = smbd_smb2_session_setup_recv(subreq, >- &out_session_flags, >- smb2req, >- &out_security_buffer, >- &out_session_id); >+ status = smbd_smb2_session_setup_wrap_recv(subreq, >+ &out_session_flags, >+ smb2req, >+ &out_security_buffer, >+ &out_session_id); > TALLOC_FREE(subreq); > if (!NT_STATUS_IS_OK(status) && > !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { >@@ -783,6 +783,162 @@ static NTSTATUS smbd_smb2_session_setup_recv(struct tevent_req *req, > return status; > } > >+struct smbd_smb2_session_setup_wrap_state { >+ struct tevent_context *ev; >+ struct smbd_smb2_request *smb2req; >+ uint64_t in_session_id; >+ uint8_t in_flags; >+ uint8_t in_security_mode; >+ uint64_t in_previous_session_id; >+ DATA_BLOB in_security_buffer; >+ uint16_t out_session_flags; >+ DATA_BLOB out_security_buffer; >+ uint64_t out_session_id; >+ NTSTATUS error; >+}; >+ >+static void smbd_smb2_session_setup_wrap_setup_done(struct tevent_req *subreq); >+static void smbd_smb2_session_setup_wrap_shutdown_done(struct tevent_req *subreq); >+ >+static struct tevent_req *smbd_smb2_session_setup_wrap_send(TALLOC_CTX *mem_ctx, >+ struct tevent_context *ev, >+ struct smbd_smb2_request *smb2req, >+ uint64_t in_session_id, >+ uint8_t in_flags, >+ uint8_t in_security_mode, >+ uint64_t in_previous_session_id, >+ DATA_BLOB in_security_buffer) >+{ >+ struct tevent_req *req; >+ struct smbd_smb2_session_setup_wrap_state *state; >+ struct tevent_req *subreq; >+ >+ req = tevent_req_create(mem_ctx, &state, >+ struct smbd_smb2_session_setup_wrap_state); >+ if (req == NULL) { >+ return NULL; >+ } >+ state->ev = ev; >+ state->smb2req = smb2req; >+ state->in_session_id = in_session_id; >+ state->in_flags = in_flags; >+ state->in_security_mode = in_security_mode; >+ state->in_previous_session_id = in_previous_session_id; >+ state->in_security_buffer = in_security_buffer; >+ >+ subreq = smbd_smb2_session_setup_send(state, state->ev, >+ state->smb2req, >+ state->in_session_id, >+ state->in_flags, >+ state->in_security_mode, >+ state->in_previous_session_id, >+ state->in_security_buffer); >+ if (tevent_req_nomem(subreq, req)) { >+ return tevent_req_post(req, ev); >+ } >+ tevent_req_set_callback(subreq, >+ smbd_smb2_session_setup_wrap_setup_done, req); >+ >+ return req; >+} >+ >+static void smbd_smb2_session_setup_wrap_setup_done(struct tevent_req *subreq) >+{ >+ struct tevent_req *req = >+ tevent_req_callback_data(subreq, >+ struct tevent_req); >+ struct smbd_smb2_session_setup_wrap_state *state = >+ tevent_req_data(req, >+ struct smbd_smb2_session_setup_wrap_state); >+ NTSTATUS status; >+ >+ status = smbd_smb2_session_setup_recv(subreq, >+ &state->out_session_flags, >+ state, >+ &state->out_security_buffer, >+ &state->out_session_id); >+ TALLOC_FREE(subreq); >+ if (NT_STATUS_IS_OK(status)) { >+ tevent_req_done(req); >+ return; >+ } >+ if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { >+ tevent_req_nterror(req, status); >+ return; >+ } >+ >+ if (state->smb2req->session == NULL) { >+ tevent_req_nterror(req, status); >+ return; >+ } >+ >+ state->error = status; >+ >+ subreq = smbXsrv_session_shutdown_send(state, state->ev, >+ state->smb2req->session, >+ state->smb2req); >+ if (tevent_req_nomem(subreq, req)) { >+ return; >+ } >+ tevent_req_set_callback(subreq, >+ smbd_smb2_session_setup_wrap_shutdown_done, >+ req); >+} >+ >+static void smbd_smb2_session_setup_wrap_shutdown_done(struct tevent_req *subreq) >+{ >+ struct tevent_req *req = >+ tevent_req_callback_data(subreq, >+ struct tevent_req); >+ struct smbd_smb2_session_setup_wrap_state *state = >+ tevent_req_data(req, >+ struct smbd_smb2_session_setup_wrap_state); >+ NTSTATUS status; >+ >+ status = smbXsrv_session_shutdown_recv(subreq); >+ TALLOC_FREE(subreq); >+ if (tevent_req_nterror(req, status)) { >+ return; >+ } >+ >+ /* >+ * we may need to sign the response, so we need to keep >+ * the session until the response is sent to the wire. >+ */ >+ talloc_steal(state->smb2req, state->smb2req->session); >+ >+ tevent_req_nterror(req, state->error); >+} >+ >+static NTSTATUS smbd_smb2_session_setup_wrap_recv(struct tevent_req *req, >+ uint16_t *out_session_flags, >+ TALLOC_CTX *mem_ctx, >+ DATA_BLOB *out_security_buffer, >+ uint64_t *out_session_id) >+{ >+ struct smbd_smb2_session_setup_wrap_state *state = >+ tevent_req_data(req, >+ struct smbd_smb2_session_setup_wrap_state); >+ NTSTATUS status; >+ >+ if (tevent_req_is_nterror(req, &status)) { >+ if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { >+ tevent_req_received(req); >+ return nt_status_squash(status); >+ } >+ } else { >+ status = NT_STATUS_OK; >+ } >+ >+ *out_session_flags = state->out_session_flags; >+ *out_security_buffer = state->out_security_buffer; >+ *out_session_id = state->out_session_id; >+ >+ talloc_steal(mem_ctx, out_security_buffer->data); >+ tevent_req_received(req); >+ return status; >+} >+ > static struct tevent_req *smbd_smb2_logoff_send(TALLOC_CTX *mem_ctx, > struct tevent_context *ev, > struct smbd_smb2_request *smb2req); >-- >1.9.1 > > >From eaf662da58ce03b124d290ce4bd6b95692f751c6 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Sat, 2 May 2015 16:27:26 +0200 >Subject: [PATCH 17/18] s3:smb2_sesssetup: always assign smb2req->session when > a session was created. > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source3/smbd/smb2_sesssetup.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > >diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c >index e1d4db3..4b5ece7b 100644 >--- a/source3/smbd/smb2_sesssetup.c >+++ b/source3/smbd/smb2_sesssetup.c >@@ -363,7 +363,6 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session, > * we attach the session to the request > * so that the response can be signed > */ >- smb2req->session = session; > if (!guest) { > smb2req->do_signing = true; > } >@@ -582,6 +581,7 @@ static struct tevent_req *smbd_smb2_session_setup_send(TALLOC_CTX *mem_ctx, > if (tevent_req_nterror(req, status)) { > return tevent_req_post(req, ev); > } >+ smb2req->session = state->session; > } else { > if (smb2req->session == NULL) { > tevent_req_nterror(req, NT_STATUS_USER_SESSION_DELETED); >-- >1.9.1 > > >From ecbdd2da9bf09b8b6e9b8ba5f793d10a7d4ff650 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Sat, 2 May 2015 16:29:03 +0200 >Subject: [PATCH 18/18] s3:smb2_sesssetup: remove unused > smbd_smb2_session_setup_* destructors > >The cleanup of a failing session setup is now handled in >smbd_smb2_session_setup_wrap_*(). > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source3/smbd/smb2_sesssetup.c | 98 ------------------------------------------- > 1 file changed, 98 deletions(-) > >diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c >index 4b5ece7b..86515c1 100644 >--- a/source3/smbd/smb2_sesssetup.c >+++ b/source3/smbd/smb2_sesssetup.c >@@ -443,94 +443,12 @@ struct smbd_smb2_session_setup_state { > uint16_t out_session_flags; > DATA_BLOB out_security_buffer; > uint64_t out_session_id; >- /* The following pointer is owned by state->session. */ >- struct smbd_smb2_session_setup_state **pp_self_ref; > }; > >-static int pp_self_ref_destructor(struct smbd_smb2_session_setup_state **pp_state) >-{ >- (*pp_state)->session = NULL; >- /* >- * To make things clearer, ensure the pp_self_ref >- * pointer is nulled out. We're never going to >- * access this again. >- */ >- (*pp_state)->pp_self_ref = NULL; >- return 0; >-} >- >-static int smbd_smb2_session_setup_state_destructor(struct smbd_smb2_session_setup_state *state) >-{ >- struct smbXsrv_connection *xconn; >- struct smbd_smb2_request *preq; >- >- /* >- * If state->session is not NULL, >- * we move the session from the session table to the request on failure >- * so that the error response can be correctly signed, but the session >- * is then really deleted when the request is done. >- */ >- >- if (state->session == NULL) { >- return 0; >- } >- >- state->session->status = NT_STATUS_USER_SESSION_DELETED; >- state->smb2req->session = talloc_move(state->smb2req, &state->session); >- >- /* >- * We own the session now - we don't need the >- * tag talloced on session that keeps track of session independently. >- */ >- TALLOC_FREE(state->pp_self_ref); >- >- /* >- * We've made this session owned by the current request. >- * Ensure that any outstanding requests don't also refer >- * to it. >- */ >- xconn = state->smb2req->xconn; >- >- for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) { >- if (preq == state->smb2req) { >- continue; >- } >- if (preq->session == state->smb2req->session) { >- 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; >- } >- } >- >- return 0; >-} >- > static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq); > static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq); > static void smbd_smb2_session_setup_auth_return(struct tevent_req *req); > >-/************************************************************************ >- We have to tag the state->session pointer with memory talloc'ed >- on it to ensure it gets NULL'ed out if the underlying struct smbXsrv_session >- is deleted by shutdown whilst this request is in flight. >-************************************************************************/ >- >-static NTSTATUS tag_state_session_ptr(struct smbd_smb2_session_setup_state *state) >-{ >- state->pp_self_ref = talloc_zero(state->session, >- struct smbd_smb2_session_setup_state *); >- if (state->pp_self_ref == NULL) { >- return NT_STATUS_NO_MEMORY; >- } >- *state->pp_self_ref = state; >- talloc_set_destructor(state->pp_self_ref, pp_self_ref_destructor); >- return NT_STATUS_OK; >-} >- > static struct tevent_req *smbd_smb2_session_setup_send(TALLOC_CTX *mem_ctx, > struct tevent_context *ev, > struct smbd_smb2_request *smb2req, >@@ -572,8 +490,6 @@ static struct tevent_req *smbd_smb2_session_setup_send(TALLOC_CTX *mem_ctx, > return tevent_req_post(req, ev); > } > >- talloc_set_destructor(state, smbd_smb2_session_setup_state_destructor); >- > if (state->in_session_id == 0) { > /* create a new session */ > status = smbXsrv_session_create(state->smb2req->xconn, >@@ -604,11 +520,6 @@ static struct tevent_req *smbd_smb2_session_setup_send(TALLOC_CTX *mem_ctx, > } > } > >- status = tag_state_session_ptr(state); >- if (tevent_req_nterror(req, status)) { >- return tevent_req_post(req, ev); >- } >- > if (state->session->gensec == NULL) { > status = auth_generic_prepare(state->session, > state->smb2req->xconn->remote_address, >@@ -663,9 +574,6 @@ static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq) > > if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { > state->out_session_id = state->session->global->session_wire_id; >- /* we want to keep the session */ >- state->session = NULL; >- TALLOC_FREE(state->pp_self_ref); > tevent_req_nterror(req, status); > return; > } >@@ -730,9 +638,6 @@ static void smbd_smb2_session_setup_auth_return(struct tevent_req *req) > if (tevent_req_nterror(req, status)) { > return; > } >- /* we want to keep the session */ >- state->session = NULL; >- TALLOC_FREE(state->pp_self_ref); > tevent_req_done(req); > return; > } >@@ -747,9 +652,6 @@ static void smbd_smb2_session_setup_auth_return(struct tevent_req *req) > return; > } > >- /* we want to keep the session */ >- state->session = NULL; >- TALLOC_FREE(state->pp_self_ref); > tevent_req_done(req); > return; > } >-- >1.9.1 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 11182
:
10995
|
11012
|
11031
|
11037