From 88dd500bb36abf8cfa2fa7079e4371bade932931 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 23 Sep 2013 20:51:30 +0200 Subject: [PATCH 01/18] s3:smb2_server: don't rely on the SMB2_HDR_FLAG_SIGNED if signing is required Windows (at least the test suites) may skip the SMB2_HDR_FLAG_SIGNED in a reauth session setup, but still provide a valid signature. Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit 4a7b792bc6d463a3aa4e1150a271ed6b929276cc) --- source3/smbd/smb2_server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index 1e4beda..9c4e187 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -1970,7 +1970,7 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req) if (req->do_encryption) { signing_required = false; - } else if (flags & SMB2_HDR_FLAG_SIGNED) { + } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) { DATA_BLOB signing_key; if (x == NULL) { -- 1.9.1 From 955cb39290e458490d4c88cf0d069117228d62e4 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 25 Sep 2013 23:18:56 +0200 Subject: [PATCH 02/18] smbd:smb2: fix error code when the header says the request is signed but we don't have a sesseion I.e. when the request is a session setup. We replied with ACCESS_DENIED, but windows expects USER_SESSION_DELETED Signed-off-by: Michael Adam Reviewed-by: Stefan Metzmacher Autobuild-User(master): Stefan Metzmacher Autobuild-Date(master): Wed Oct 2 22:07:44 CEST 2013 on sn-devel-104 (cherry picked from commit c3a5fecdc1ff0320f4979fa21aa636aacaac8abe) --- source3/smbd/smb2_server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index 9c4e187..a4e149f 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -1975,7 +1975,7 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req) if (x == NULL) { return smbd_smb2_request_error( - req, NT_STATUS_ACCESS_DENIED); + req, NT_STATUS_USER_SESSION_DELETED); } signing_key = x->global->channels[0].signing_key; -- 1.9.1 From b53656dd23a63759a42c8197ef2c8f068fdd8f3e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 1 May 2015 20:04:55 +0200 Subject: [PATCH 03/18] s3:smbd: add a smbd_notify_cancel_by_map() helper function Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison (cherry picked from commit 2c47fb16089602a42f62124520e58bdcd8c7d053) --- 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 4842d6f..cb9f873 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -350,6 +350,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. *****************************************************************************/ @@ -369,9 +380,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) @@ -389,9 +398,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 5d39c3933a209c017b3f93f5b975426028fd5754 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 1 May 2015 20:02:38 +0200 Subject: [PATCH 04/18] s3:smbd: use STATUS_NOTIFY_CLEANUP when closing a smb2 directory handle Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison (cherry picked from commit a5981d137461e5715c92a4fb4cdeaa650f34e999) --- selftest/knownfail | 1 - source3/smbd/close.c | 15 +++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/selftest/knownfail b/selftest/knownfail index 8d11dfe..104ddbd 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -187,7 +187,6 @@ ^samba3.smb2.create.open ^samba3.smb2.create.leading-slash ^samba3.smb2.notify.valid-req -^samba3.smb2.notify.dir ^samba3.smb2.notify.rec ^samba3.smb2.durable-open.lock-lease ^samba3.smb2.durable-open.reopen4 diff --git a/source3/smbd/close.c b/source3/smbd/close.c index f341c72..3f4af6d 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 bbfb61be49eb4a67a78f57891bfa24d56db50650 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 1 May 2015 20:02:38 +0200 Subject: [PATCH 05/18] s3:smbd: use STATUS_NOTIFY_CLEANUP on smb2 logoff (explicit and implicit) and tdis Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison (cherry picked from commit 5169e9b20c69092d04b596f48ca0e69a46af438f) --- source3/smbd/notify.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index cb9f873..c90561c 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -354,8 +354,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 3b7e3e0a3b482428aa49579c0a956765f5ff4c3e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 1 May 2015 20:19:42 +0200 Subject: [PATCH 06/18] s4:torture/smb2: verify STATUS_NOTIFY_CLEANUP return value Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison (cherry picked from commit 4bfa6b024e530694741c7c07171fa09762578389) --- 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 a737661..c47c2c2 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 61ed47a455a9e7c4483a3a06754df6f7c1d48643 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 1 May 2015 20:20:50 +0200 Subject: [PATCH 07/18] s4:torture/smb2: add smb2.notify.close test Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison (cherry picked from commit 44f9e1052de81a0a3052997e7e19a01813fbec43) --- 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 c47c2c2..16a58bb 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 */ @@ -2068,6 +2137,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 8ce24575417ddf12f74e013eb2bd3883357c0fd9 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 1 May 2015 20:20:50 +0200 Subject: [PATCH 08/18] 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 Reviewed-by: Jeremy Allison (cherry picked from commit a8ec77e86b17213eeb6a51a835639d79e9486223) --- 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 16a58bb..6031d16 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; @@ -2139,6 +2220,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 8056640f6fef28fc00b026f477440de48c5d34b6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 2 May 2015 09:57:03 +0200 Subject: [PATCH 09/18] s4:torture/smb2: add smb2.notify.session-reconnect test Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison (cherry picked from commit f435c89d61385272bf5b79f82f6e1373908d2b94) --- 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 6031d16..d8b32c7 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 */ @@ -2220,6 +2300,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 0ed2db0a31d7b842d529e90ab66ae7acb5247e3a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 2 May 2015 16:09:40 +0200 Subject: [PATCH 10/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. Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison (similar to commit 7fea42110596e8e9da0155d726aaa72223107fbd) --- source3/smbd/smbXsrv_session.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/source3/smbd/smbXsrv_session.c b/source3/smbd/smbXsrv_session.c index 017880c..5391fc6 100644 --- a/source3/smbd/smbXsrv_session.c +++ b/source3/smbd/smbXsrv_session.c @@ -1062,6 +1062,25 @@ NTSTATUS smb2srv_session_close_previous_recv(struct tevent_req *req) static int smbXsrv_session_destructor(struct smbXsrv_session *session) { NTSTATUS status; + struct smbd_smb2_request *preq = NULL; + + if (session->connection != NULL) { + preq = session->connection->sconn->smb2.requests; + } + + for (; 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 5334be5113f57f85afd58b5eb42ea6ea4c5b0825 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 2 May 2015 16:17:34 +0200 Subject: [PATCH 11/18] 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 Reviewed-by: Jeremy Allison (similar to commit b6c34a07760141bda3e78624d62eb556bb70da65) --- source3/smbd/smbXsrv_session.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/source3/smbd/smbXsrv_session.c b/source3/smbd/smbXsrv_session.c index 5391fc6..362cff8 100644 --- a/source3/smbd/smbXsrv_session.c +++ b/source3/smbd/smbXsrv_session.c @@ -1473,6 +1473,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 smbd_smb2_request *preq = NULL; NTSTATUS status; val = dbwrap_record_get_value(local_rec); @@ -1489,6 +1490,25 @@ 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->connection != NULL) { + preq = session->connection->sconn->smb2.requests; + } + + for (; 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 9521e252de314de3a43772abdca584b02b55a26f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 2 May 2015 09:57:03 +0200 Subject: [PATCH 12/18] s3:smbXsrv_session: add smb2srv_session_shutdown_send/recv helper functions Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison (similar to commit 4fceb4531ccd6bb1fd6ebd7b6eb5b894959bc010) --- source3/smbd/globals.h | 5 ++ source3/smbd/smbXsrv_session.c | 107 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 0942e46..66358fb 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -394,6 +394,11 @@ NTSTATUS smbXsrv_session_create(struct smbXsrv_connection *conn, NTTIME now, struct smbXsrv_session **_session); NTSTATUS smbXsrv_session_update(struct smbXsrv_session *session); +struct tevent_req *smb2srv_session_shutdown_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct smbXsrv_session *session, + struct smbd_smb2_request *current_req); +NTSTATUS smb2srv_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 362cff8..a2ebfb1 100644 --- a/source3/smbd/smbXsrv_session.c +++ b/source3/smbd/smbXsrv_session.c @@ -38,6 +38,7 @@ #include "serverid.h" #include "lib/util/tevent_ntstatus.h" #include "msg_channel.h" +#include "lib/smbd_tevent_queue.h" struct smbXsrv_session_table { struct { @@ -1300,6 +1301,112 @@ NTSTATUS smbXsrv_session_update(struct smbXsrv_session *session) return NT_STATUS_OK; } +struct smb2srv_session_shutdown_state { + struct tevent_queue *wait_queue; +}; + +static void smb2srv_session_shutdown_wait_done(struct tevent_req *subreq); + +struct tevent_req *smb2srv_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 smb2srv_session_shutdown_state *state; + struct tevent_req *subreq; + struct smbd_smb2_request *preq = 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 smb2srv_session_shutdown_state); + if (req == NULL) { + return NULL; + } + + state->wait_queue = tevent_queue_create(state, "smb2srv_session_shutdown_queue"); + if (tevent_req_nomem(state->wait_queue, req)) { + return tevent_req_post(req, ev); + } + + if (session->connection != NULL) { + preq = session->connection->sconn->smb2.requests; + } + + for (; 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 = smbd_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 = smbd_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, smb2srv_session_shutdown_wait_done, req); + + return req; +} + +static void smb2srv_session_shutdown_wait_done(struct tevent_req *subreq) +{ + struct tevent_req *req = + tevent_req_callback_data(subreq, + struct tevent_req); + + smbd_tevent_queue_wait_recv(subreq); + TALLOC_FREE(subreq); + + tevent_req_done(req); +} + +NTSTATUS smb2srv_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 ad3eacf37abc51c9b2b300d4ccb4c87e201989eb Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 2 May 2015 16:13:27 +0200 Subject: [PATCH 13/18] 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 Reviewed-by: Jeremy Allison (similar to commit cc9d52e10f4f1b192171e03674061d4e8e6bcc84) --- 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 a2ebfb1..097d6ec 100644 --- a/source3/smbd/smbXsrv_session.c +++ b/source3/smbd/smbXsrv_session.c @@ -228,6 +228,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_connection *conn = @@ -331,20 +333,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 = smb2srv_session_shutdown_send(session, conn->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", + "smb2srv_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); @@ -358,6 +362,33 @@ next: tevent_req_set_callback(subreq, smbXsrv_session_close_loop, conn); } +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 = smb2srv_session_shutdown_recv(subreq); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("smbXsrv_session_close_loop: " + "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)) { + 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 86b8121fb5d95b2b952a7a4e4d4cff909f4f01d3 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 2 May 2015 16:20:06 +0200 Subject: [PATCH 14/18] s3:smb2_sesssetup: let smbd_smb2_logoff_* use smbXsrv_session_shutdown_* Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison (similar to commit 95057fe375348b918cb2ca58109f4c110a4a5f77) --- 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 a82d696..00ef993 100644 --- a/source3/smbd/smb2_sesssetup.c +++ b/source3/smbd/smb2_sesssetup.c @@ -28,7 +28,6 @@ #include "../lib/tsocket/tsocket.h" #include "../libcli/security/security.h" #include "../lib/util/tevent_ntstatus.h" -#include "lib/smbd_tevent_queue.h" static struct tevent_req *smbd_smb2_session_setup_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -828,94 +827,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; 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 = smb2req->sconn->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 = smbd_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 = smbd_tevent_queue_wait_send(state, ev, state->wait_queue); + subreq = smb2srv_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; - smbd_tevent_queue_wait_recv(subreq); + status = smb2srv_session_shutdown_recv(subreq); + if (tevent_req_nterror(req, status)) { + return; + } TALLOC_FREE(subreq); /* -- 1.9.1 From 9358b676d0fbe5c3404cf2bca6af2a500f4b077e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 2 May 2015 16:27:26 +0200 Subject: [PATCH 15/18] s3:smb2_sesssetup: always assign smb2req->session when a session was created. Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison (cherry picked from commit 8f0d4d1132b74615dc6198ab736590dec52effda) --- 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 00ef993..825f685 100644 --- a/source3/smbd/smb2_sesssetup.c +++ b/source3/smbd/smb2_sesssetup.c @@ -362,7 +362,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; } @@ -540,6 +539,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 { status = smb2srv_session_lookup(state->smb2req->sconn->conn, state->in_session_id, now, -- 1.9.1 From 70ac715b8133e37b01e3f42bd677b256a7b68f2c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher 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. Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison (cherry picked from commit 50aeb6b38b14d6c26229834ece3c32eb50f9e56a) --- 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 825f685..cfad834 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)) { @@ -755,6 +755,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 = smb2srv_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 = smb2srv_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 d3e0aa1d06bacb575de250e42f754fd1052d0eac Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 2 May 2015 16:29:03 +0200 Subject: [PATCH 17/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_*(). Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison (similar to commit 5871d3da871349cba058bb91218ae58107cf05c8) --- source3/smbd/smb2_sesssetup.c | 59 ------------------------------------------- 1 file changed, 59 deletions(-) diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c index cfad834..9f34a09 100644 --- a/source3/smbd/smb2_sesssetup.c +++ b/source3/smbd/smb2_sesssetup.c @@ -442,53 +442,11 @@ 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) -{ - /* - * if state->session is not NULL, - * we remove the session on failure - */ - TALLOC_FREE(state->session); - 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); -/************************************************************************ - 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, @@ -530,8 +488,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->sconn->conn, @@ -558,11 +514,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->session->connection->remote_address, @@ -617,8 +568,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 */ - TALLOC_FREE(state->pp_self_ref); tevent_req_nterror(req, status); return; } @@ -657,8 +606,6 @@ static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq) if (tevent_req_nterror(req, status)) { return; } - /* we want to keep the session */ - TALLOC_FREE(state->pp_self_ref); tevent_req_done(req); return; } @@ -673,8 +620,6 @@ static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq) return; } - /* we want to keep the session */ - TALLOC_FREE(state->pp_self_ref); tevent_req_done(req); return; } @@ -704,8 +649,6 @@ static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq) if (tevent_req_nterror(req, status)) { return; } - /* we want to keep the session */ - TALLOC_FREE(state->pp_self_ref); tevent_req_done(req); return; } @@ -720,8 +663,6 @@ static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq) return; } - /* we want to keep the session */ - TALLOC_FREE(state->pp_self_ref); tevent_req_done(req); return; } -- 1.9.1 From 4bdd0b8150b4fc43e7e262e0a93ccb9749b64f5d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 1 May 2015 20:26:41 +0200 Subject: [PATCH 18/18] s3:selftest: run smb2.notify with --signing=required This reproduces a bug withe implicit canceled requests. Bug: https://bugzilla.samba.org/show_bug.cgi?id=11182 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison (similar to commit c49ad3f89530d078fdd6ffcd1a6dc8c38be9169b) --- source3/selftest/tests.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index 85d67d6..27883d3 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -358,6 +358,9 @@ for t in tests: # test the dirsort module. plansmbtorture4testsuite(t, "s3dc", '//$SERVER_IP/tmpsort -U$USERNAME%$PASSWORD') plansmbtorture4testsuite(t, "plugin_s4_dc", '//$SERVER/tmp -U$USERNAME%$PASSWORD') + elif t == "smb2.notify": + plansmbtorture4testsuite(t, "s3dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD --signing=required') + plansmbtorture4testsuite(t, "plugin_s4_dc", '//$SERVER/tmp -U$USERNAME%$PASSWORD --signing=required') else: plansmbtorture4testsuite(t, "s3dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD') plansmbtorture4testsuite(t, "plugin_s4_dc", '//$SERVER/tmp -U$USERNAME%$PASSWORD') -- 1.9.1