The branch, master has been updated
via ff9178b6b4a smbd: return EACCESS when Durable Handle is reconnected
with different user
via 0ad4cb03936 smbtorture: DH reconnect with different user must fail
with NT_STATUS_ACCESS_DENIED
via ff9bb28eeb8 s3/scavenger: call smbXsrv_open_cleanup() before
share_mode_cleanup_disconnected()
via aa52db96cee smbtorture: add test
smb2.durable-v2-open.reconnect-twice
via 6f7a4a87feb smbd: DH reconnect hardening
via f23e94a885b smbd: compare Open.ClientGuid against Client.ClientGuid
in DH reconnect
via c98e5f8a2ad smbd: only call scavenger_schedule_disconnected() if
smbXsrv_open_close() succeeded
via 15c6b767f93 smbd: free smbXsrv_open if SMB_VFS_DURABLE_RECONNECT()
failed
via 8ff9000d646 smbtorture: add a DH reconnect test that demonstrates
the open record clobbering problem
via 028a583920f s3/scavenger: raise debug level to 1 for cleanup
failures
via 095b5aca3d1 s3/scavenger: support more then one Durable Handle per
file
via 9e03f1d13b1 smbd: NDR_PRINT_DEBUG the vfs_default_durable_cookie in
all relevant places
from dfd0ea70b9e third_party/waf: Explicit standard GNU directory
command line options are not honoured
https://git.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit ff9178b6b4ad2aff651e7897aed5cf4fe7e37c20
Author: Ralph Boehme <[email protected]>
Date: Fri Nov 8 08:38:05 2024 +0100
smbd: return EACCESS when Durable Handle is reconnected with different user
MS-SMB2 3.3.5.9.7 Handling the SMB2_CREATE_DURABLE_HANDLE_RECONNECT Create
Context
10. If the user represented by Session.SecurityContext is not the same user
denoted by Open.DurableOwner, the server MUST fail the request with
STATUS_ACCESS_DENIED and proceed as specified in "Failed Open Handling"
BUG: https://bugzilla.samba.org/show_bug.cgi?id=11122
Signed-off-by: Ralph Boehme <[email protected]>
Reviewed-by: Stefan Metzmacher <[email protected]>
Autobuild-User(master): Ralph Böhme <[email protected]>
Autobuild-Date(master): Fri Jun 6 17:15:45 UTC 2025 on atb-devel-224
commit 0ad4cb039364b8754b5b26f97f9364693ec1b1c4
Author: Ralph Boehme <[email protected]>
Date: Fri Nov 8 11:25:21 2024 +0100
smbtorture: DH reconnect with different user must fail with
NT_STATUS_ACCESS_DENIED
BUG: https://bugzilla.samba.org/show_bug.cgi?id=11122
Pair-Programmed-With: Stefan Metzmacher <[email protected]>
Signed-off-by: Ralph Boehme <[email protected]>
Signed-off-by: Stefan Metzmacher <[email protected]>
commit ff9bb28eeb8534ddae138030e1df3f3059f9063f
Author: Ralph Boehme <[email protected]>
Date: Mon Mar 25 15:53:15 2024 +0100
s3/scavenger: call smbXsrv_open_cleanup() before
share_mode_cleanup_disconnected()
This ensures smbXsrv_open_cleanup(), which checks durable_timeout_msec,
will detect
a repeated DH disconnect that has reset the durable_timeout_msec.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15750
Pair-Programmed-With: Stefan Metzmacher <[email protected]>
Signed-off-by: Ralph Boehme <[email protected]>
Signed-off-by: Stefan Metzmacher <[email protected]>
commit aa52db96ceeb0fa2dfbbdc2eafa6b50e32a6d18a
Author: Ralph Boehme <[email protected]>
Date: Mon Mar 25 16:01:55 2024 +0100
smbtorture: add test smb2.durable-v2-open.reconnect-twice
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15750
Signed-off-by: Ralph Boehme <[email protected]>
Reviewed-by: Stefan Metzmacher <[email protected]>
commit 6f7a4a87feb3dd324ce6aa65b5451ef102032c00
Author: Ralph Boehme <[email protected]>
Date: Tue Nov 19 17:45:35 2024 +0100
smbd: DH reconnect hardening
Verify the smbXsrv_open_global0 is marked as disconnected. This is
similarily
checked in SMB_VFS_RECONNECT() for the share_mode_entry and that catches the
problem most of the times. But to be consistent we need this check also in
smb2srv_open_recreate_fn().
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15649
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15651
Signed-off-by: Ralph Boehme <[email protected]>
Reviewed-by: Stefan Metzmacher <[email protected]>
commit f23e94a885b746266e217a0410a3ef088520f0c8
Author: Ralph Boehme <[email protected]>
Date: Wed Feb 26 15:28:53 2025 +0100
smbd: compare Open.ClientGuid against Client.ClientGuid in DH reconnect
This implements the check from MS-SMB2 3.3.5.9.7 "Handling the
SMB2_CREATE_DURABLE_HANDLE_RECONNECT Create Context".
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15649
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15651
Signed-off-by: Ralph Boehme <[email protected]>
Reviewed-by: Stefan Metzmacher <[email protected]>
commit c98e5f8a2addaabcd6cbfce94a87e30590e6198f
Author: Ralph Boehme <[email protected]>
Date: Tue Nov 19 20:00:49 2024 +0100
smbd: only call scavenger_schedule_disconnected() if smbXsrv_open_close()
succeeded
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15649
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15651
Signed-off-by: Ralph Boehme <[email protected]>
Reviewed-by: Stefan Metzmacher <[email protected]>
commit 15c6b767f937867957c15790ff3fda886f1b347c
Author: Ralph Boehme <[email protected]>
Date: Wed Feb 26 16:29:18 2025 +0100
smbd: free smbXsrv_open if SMB_VFS_DURABLE_RECONNECT() failed
Otherwise we leave "op" around which ultimately leads to
smbXsrv_open_close()
being called from its destructor smbXsrv_open_destructor() that is triggerd
by
its tree disconnect (or logoff, or ...) and this would clobber the open
record.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15649
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15651
Signed-off-by: Ralph Boehme <[email protected]>
Reviewed-by: Stefan Metzmacher <[email protected]>
commit 8ff9000d64647348e89375e1f071e7ac3c4092dd
Author: Ralph Boehme <[email protected]>
Date: Mon Nov 18 18:16:59 2024 +0100
smbtorture: add a DH reconnect test that demonstrates the open record
clobbering problem
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15649
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15651
Signed-off-by: Ralph Boehme <[email protected]>
Reviewed-by: Stefan Metzmacher <[email protected]>
commit 028a583920fe417919f97c236b5bd8508cc719b1
Author: Ralph Boehme <[email protected]>
Date: Fri Jun 6 15:45:43 2025 +0200
s3/scavenger: raise debug level to 1 for cleanup failures
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15649
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15651
Signed-off-by: Ralph Boehme <[email protected]>
Reviewed-by: Stefan Metzmacher <[email protected]>
commit 095b5aca3d1678ce1229a2905a78250eed3cfb7b
Author: Ralph Boehme <[email protected]>
Date: Thu Nov 7 15:41:18 2024 +0100
s3/scavenger: support more then one Durable Handle per file
Best viewed with git show --patience.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15649
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15651
Pair-Programmed-With: Stefan Metzmacher <[email protected]>
Signed-off-by: Ralph Boehme <[email protected]>
Signed-off-by: Stefan Metzmacher <[email protected]>
commit 9e03f1d13b184b73d323355889be82ae545c0496
Author: Ralph Boehme <[email protected]>
Date: Fri Jun 6 17:01:22 2025 +0200
smbd: NDR_PRINT_DEBUG the vfs_default_durable_cookie in all relevant places
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15649
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15651
Signed-off-by: Ralph Boehme <[email protected]>
Reviewed-by: Stefan Metzmacher <[email protected]>
-----------------------------------------------------------------------
Summary of changes:
source3/selftest/tests.py | 3 +-
source3/smbd/close.c | 2 +-
source3/smbd/durable.c | 20 +++
source3/smbd/scavenger.c | 150 +++++++----------------
source3/smbd/smb2_create.c | 6 +
source3/smbd/smbXsrv_open.c | 32 +++--
source3/smbd/smbXsrv_open.h | 2 +
source4/torture/smb2/durable_open.c | 217 +++++++++++++++++++++++++++++++++
source4/torture/smb2/durable_v2_open.c | 110 +++++++++++++++++
9 files changed, 429 insertions(+), 113 deletions(-)
Changeset truncated at 500 lines:
diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index cedcf97e994..008c444681c 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -1239,7 +1239,8 @@ for t in tests:
elif t == "rpc.mdssvc":
plansmbtorture4testsuite(t, "fileserver", '//$SERVER_IP/tmp
-U$USERNAME%$PASSWORD')
elif t == "smb2.durable-open" or t == "smb2.durable-v2-open" or t ==
"smb2.replay" or t == "smb2.durable-v2-delay":
- plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/durable
-U$USERNAME%$PASSWORD')
+ creds = " --option=torture:user2name=user1
--option=torture:user2password=$PASSWORD"
+ plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/durable
-U$USERNAME%$PASSWORD' + creds)
plansmbtorture4testsuite(t, "ad_dc", '//$SERVER_IP/durable
-U$USERNAME%$PASSWORD')
elif t == "base.rw1":
plansmbtorture4testsuite(t, "nt4_dc_smb1", '//$SERVER_IP/tmp
-U$USERNAME%$PASSWORD')
diff --git a/source3/smbd/close.c b/source3/smbd/close.c
index e0fc4618209..ce04056fc34 100644
--- a/source3/smbd/close.c
+++ b/source3/smbd/close.c
@@ -892,7 +892,6 @@ static NTSTATUS close_normal_file(struct smb_request *req,
files_struct *fsp,
"proceeding with normal close\n",
fsp_str_dbg(fsp), nt_errstr(tmp)));
}
- scavenger_schedule_disconnected(fsp);
} else {
DEBUG(1, ("Failed to disconnect durable handle for "
"file %s: %s - proceeding with normal "
@@ -912,6 +911,7 @@ static NTSTATUS close_normal_file(struct smb_request *req,
files_struct *fsp,
DEBUG(10, ("%s disconnected durable handle for file %s\n",
conn->session_info->unix_info->unix_name,
fsp_str_dbg(fsp)));
+ scavenger_schedule_disconnected(fsp);
return NT_STATUS_OK;
}
diff --git a/source3/smbd/durable.c b/source3/smbd/durable.c
index 8e35e32538d..c13c8382f0f 100644
--- a/source3/smbd/durable.c
+++ b/source3/smbd/durable.c
@@ -117,6 +117,11 @@ NTSTATUS vfs_default_durable_cookie(struct files_struct
*fsp,
cookie.stat_info.st_ex_blocks = fsp->fsp_name->st.st_ex_blocks;
cookie.stat_info.st_ex_flags = fsp->fsp_name->st.st_ex_flags;
+ if (CHECK_DEBUGLVL(DBGLVL_DEBUG)) {
+ DBG_DEBUG("Fresh cookie\n");
+ NDR_PRINT_DEBUG(vfs_default_durable_cookie, &cookie);
+ }
+
ndr_err = ndr_push_struct_blob(cookie_blob, mem_ctx, &cookie,
(ndr_push_flags_fn_t)ndr_push_vfs_default_durable_cookie);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
@@ -182,6 +187,11 @@ NTSTATUS vfs_default_durable_disconnect(struct
files_struct *fsp,
return status;
}
+ if (CHECK_DEBUGLVL(DBGLVL_DEBUG)) {
+ DBG_DEBUG("Old cookie\n");
+ NDR_PRINT_DEBUG(vfs_default_durable_cookie, &cookie);
+ }
+
if (strcmp(cookie.magic, VFS_DEFAULT_DURABLE_COOKIE_MAGIC) != 0) {
return NT_STATUS_INVALID_PARAMETER;
}
@@ -279,6 +289,11 @@ NTSTATUS vfs_default_durable_disconnect(struct
files_struct *fsp,
return status;
}
+ if (CHECK_DEBUGLVL(DBGLVL_DEBUG)) {
+ DBG_DEBUG("New cookie\n");
+ NDR_PRINT_DEBUG(vfs_default_durable_cookie, &cookie);
+ }
+
status = fd_close(fsp);
if (!NT_STATUS_IS_OK(status)) {
data_blob_free(&new_cookie_blob);
@@ -817,6 +832,11 @@ NTSTATUS vfs_default_durable_reconnect(struct
connection_struct *conn,
return status;
}
+ if (CHECK_DEBUGLVL(DBGLVL_DEBUG)) {
+ DBG_DEBUG("Cookie:\n");
+ NDR_PRINT_DEBUG(vfs_default_durable_cookie, &state.cookie);
+ }
+
if (strcmp(state.cookie.magic, VFS_DEFAULT_DURABLE_COOKIE_MAGIC) != 0) {
return NT_STATUS_INVALID_PARAMETER;
}
diff --git a/source3/smbd/scavenger.c b/source3/smbd/scavenger.c
index 40b2fe55dcc..2e04df662ef 100644
--- a/source3/smbd/scavenger.c
+++ b/source3/smbd/scavenger.c
@@ -472,27 +472,10 @@ struct cleanup_disconnected_state {
struct file_id fid;
struct share_mode_lock *lck;
uint64_t open_persistent_id;
- size_t num_disconnected;
- bool found_connected;
+ struct share_mode_entry e;
};
-static bool cleanup_disconnected_lease(struct share_mode_entry *e,
- void *private_data)
-{
- struct cleanup_disconnected_state *state = private_data;
- NTSTATUS status;
-
- status = leases_db_del(&e->client_guid, &e->lease_key, &state->fid);
-
- if (!NT_STATUS_IS_OK(status)) {
- DBG_DEBUG("leases_db_del failed: %s\n",
- nt_errstr(status));
- }
-
- return false;
-}
-
-static bool share_mode_find_connected_fn(
+static bool cleanup_disconnected_share_mode_entry_fn(
struct share_mode_entry *e,
bool *modified,
void *private_data)
@@ -500,53 +483,10 @@ static bool share_mode_find_connected_fn(
struct cleanup_disconnected_state *state = private_data;
bool disconnected;
- disconnected = server_id_is_disconnected(&e->pid);
- if (!disconnected) {
- char *name = share_mode_filename(talloc_tos(), state->lck);
- struct file_id_buf tmp1;
- struct server_id_buf tmp2;
- DBG_INFO("file (file-id='%s', servicepath='%s', name='%s') "
- "is used by server %s ==> do not cleanup\n",
- file_id_str_buf(state->fid, &tmp1),
- share_mode_servicepath(state->lck),
- name,
- server_id_str_buf(e->pid, &tmp2));
- TALLOC_FREE(name);
- state->found_connected = true;
- return true;
- }
-
- if (state->open_persistent_id != e->share_file_id) {
- char *name = share_mode_filename(talloc_tos(), state->lck);
- struct file_id_buf tmp;
- DBG_INFO("entry for file "
- "(file-id='%s', servicepath='%s', name='%s') "
- "has share_file_id %"PRIu64" but expected "
- "%"PRIu64"==> do not cleanup\n",
- file_id_str_buf(state->fid, &tmp),
- share_mode_servicepath(state->lck),
- name,
- e->share_file_id,
- state->open_persistent_id);
- TALLOC_FREE(name);
- state->found_connected = true;
- return true;
+ if (e->share_file_id != state->open_persistent_id) {
+ return false;
}
- state->num_disconnected += 1;
-
- return false;
-}
-
-static bool cleanup_disconnected_share_mode_entry_fn(
- struct share_mode_entry *e,
- bool *modified,
- void *private_data)
-{
- struct cleanup_disconnected_state *state = private_data;
-
- bool disconnected;
-
disconnected = server_id_is_disconnected(&e->pid);
if (!disconnected) {
char *name = share_mode_filename(talloc_tos(), state->lck);
@@ -567,7 +507,9 @@ static bool cleanup_disconnected_share_mode_entry_fn(
* the indication to delete the entry.
*/
e->stale = true;
- return false;
+ state->e = *e;
+
+ return true;
}
static bool share_mode_cleanup_disconnected(
@@ -581,44 +523,20 @@ static bool share_mode_cleanup_disconnected(
TALLOC_CTX *frame = talloc_stackframe();
char *name = NULL;
struct file_id_buf idbuf;
+ NTSTATUS status;
bool ok;
state.lck = get_existing_share_mode_lock(frame, fid);
if (state.lck == NULL) {
- DBG_INFO("Could not fetch share mode entry for %s\n",
+ DBG_WARNING("Could not fetch share mode entry for %s\n",
file_id_str_buf(fid, &idbuf));
goto done;
}
name = share_mode_filename(frame, state.lck);
- ok = share_mode_forall_entries(
- state.lck, share_mode_find_connected_fn, &state);
- if (!ok) {
- DBG_DEBUG("share_mode_forall_entries failed\n");
- goto done;
- }
- if (state.found_connected) {
- DBG_DEBUG("Found connected entry\n");
- goto done;
- }
-
- ok = share_mode_forall_leases(
- state.lck, cleanup_disconnected_lease, &state);
- if (!ok) {
- DBG_DEBUG("failed to clean up leases associated "
- "with file (file-id='%s', servicepath='%s', "
- "name='%s') and open_persistent_id %"PRIu64" "
- "==> do not cleanup\n",
- file_id_str_buf(fid, &idbuf),
- share_mode_servicepath(state.lck),
- name,
- open_persistent_id);
- goto done;
- }
-
ok = brl_cleanup_disconnected(fid, open_persistent_id);
if (!ok) {
- DBG_DEBUG("failed to clean up byte range locks associated "
+ DBG_WARNING("failed to clean up byte range locks associated "
"with file (file-id='%s', servicepath='%s', "
"name='%s') and open_persistent_id %"PRIu64" "
"==> do not cleanup\n",
@@ -629,10 +547,9 @@ static bool share_mode_cleanup_disconnected(
goto done;
}
- DBG_DEBUG("cleaning up %zu entries for file "
+ DBG_DEBUG("cleaning up entry for file "
"(file-id='%s', servicepath='%s', name='%s') "
"from open_persistent_id %"PRIu64"\n",
- state.num_disconnected,
file_id_str_buf(fid, &idbuf),
share_mode_servicepath(state.lck),
name,
@@ -641,11 +558,10 @@ static bool share_mode_cleanup_disconnected(
ok = share_mode_forall_entries(
state.lck, cleanup_disconnected_share_mode_entry_fn, &state);
if (!ok) {
- DBG_DEBUG("failed to clean up %zu entries associated "
+ DBG_WARNING("failed to clean up entry associated "
"with file (file-id='%s', servicepath='%s', "
"name='%s') and open_persistent_id %"PRIu64" "
"==> do not cleanup\n",
- state.num_disconnected,
file_id_str_buf(fid, &idbuf),
share_mode_servicepath(state.lck),
name,
@@ -653,6 +569,30 @@ static bool share_mode_cleanup_disconnected(
goto done;
}
+ if (state.e.stale && (state.e.op_type == LEASE_OPLOCK)) {
+ status = remove_lease_if_stale(state.lck,
+ &state.e.client_guid,
+ &state.e.lease_key);
+ if (!NT_STATUS_IS_OK(status)) {
+ struct GUID_txt_buf gbuf;
+
+ DBG_WARNING("Failed to clean up lease associated "
+ "with file (file-id='%s', servicepath='%s',
"
+ "name='%s', open_persistent_id=%" PRIu64
+ "client_guid=%s, "
+ "lease_key=%"PRIx64"/%"PRIx64"): %s\n",
+ file_id_str_buf(fid, &idbuf),
+ share_mode_servicepath(state.lck),
+ name,
+ open_persistent_id,
+ GUID_buf_string(&state.e.client_guid,
&gbuf),
+ state.e.lease_key.data[0],
+ state.e.lease_key.data[1],
+ nt_errstr(status));
+ goto done;
+ }
+ }
+
ret = true;
done:
talloc_free(frame);
@@ -673,6 +613,16 @@ static void scavenger_timer(struct tevent_context *ev,
file_id_str_buf(ctx->msg.file_id, &idbuf),
timeval_string(talloc_tos(), &t, true));
+ status = smbXsrv_open_cleanup(ctx->msg.open_persistent_id);
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_WARNING("Failed to cleanup open global for file %s open "
+ "%"PRIu64": %s\n",
+ file_id_str_buf(ctx->msg.file_id, &idbuf),
+ ctx->msg.open_persistent_id,
+ nt_errstr(status));
+ return;
+ }
+
ok = share_mode_cleanup_disconnected(ctx->msg.file_id,
ctx->msg.open_persistent_id);
if (!ok) {
@@ -682,14 +632,6 @@ static void scavenger_timer(struct tevent_context *ev,
ctx->msg.open_persistent_id);
}
- status = smbXsrv_open_cleanup(ctx->msg.open_persistent_id);
- if (!NT_STATUS_IS_OK(status)) {
- DBG_WARNING("Failed to cleanup open global for file %s open "
- "%"PRIu64": %s\n",
- file_id_str_buf(ctx->msg.file_id, &idbuf),
- ctx->msg.open_persistent_id,
- nt_errstr(status));
- }
}
static void scavenger_add_timer(struct smbd_scavenger_state *state,
diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c
index 78da998e169..6f4f3ed47de 100644
--- a/source3/smbd/smb2_create.c
+++ b/source3/smbd/smb2_create.c
@@ -1096,11 +1096,16 @@ static struct tevent_req
*smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
if (state->do_durable_reconnect) {
DATA_BLOB new_cookie = data_blob_null;
NTTIME now = timeval_to_nttime(&smb2req->request_time);
+ const struct smb2_lease_key *lease_key = NULL;
+ if (state->lease_ptr != NULL) {
+ lease_key = &state->lease_ptr->lease_key;
+ }
status = smb2srv_open_recreate(smb2req->xconn,
smb1req->conn->session_info,
state->persistent_id,
state->create_guid,
+ lease_key,
now,
&state->op);
if (tevent_req_nterror(req, status)) {
@@ -1135,6 +1140,7 @@ static struct tevent_req
*smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
nt_errstr(status),
nt_errstr(return_status));
+ TALLOC_FREE(state->op);
tevent_req_nterror(req, return_status);
return tevent_req_post(req, state->ev);
}
diff --git a/source3/smbd/smbXsrv_open.c b/source3/smbd/smbXsrv_open.c
index 6fd64a028c9..c939bbd39c3 100644
--- a/source3/smbd/smbXsrv_open.c
+++ b/source3/smbd/smbXsrv_open.c
@@ -35,6 +35,7 @@
#include "source3/include/util_tdb.h"
#include "lib/util/idtree_random.h"
#include "lib/util/time_basic.h"
+#include "../librpc/gen_ndr/ndr_smb2_lease_struct.h"
struct smbXsrv_open_table {
struct {
@@ -282,10 +283,10 @@ static NTSTATUS smbXsrv_open_global_verify_record(
*_global0 = global0;
if (server_id_is_disconnected(&global0->server_id)) {
- return NT_STATUS_OK;
+ return NT_STATUS_REMOTE_DISCONNECT;
}
if (serverid_exists(&global0->server_id)) {
- return NT_STATUS_OK;
+ return NT_STATUS_OBJECTID_EXISTS;
}
DBG_WARNING("smbd %s did not clean up record %s\n",
@@ -367,7 +368,7 @@ static void smbXsrv_open_global_allocate_fn(
state->status = smbXsrv_open_global_verify_record(
key, oldval, talloc_tos(), &tmp_global0);
- if (NT_STATUS_IS_OK(state->status)) {
+ if (!NT_STATUS_EQUAL(state->status, NT_STATUS_NOT_FOUND)) {
/*
* Found an existing record
*/
@@ -1159,7 +1160,9 @@ NTSTATUS smb2srv_open_lookup_replay_cache(struct
smbXsrv_connection *conn,
struct smb2srv_open_recreate_state {
struct smbXsrv_open *op;
+ const struct GUID *client_guid;
const struct GUID *create_guid;
+ const struct smb2_lease_key *lease_key;
struct security_token *current_token;
struct server_id me;
@@ -1172,10 +1175,11 @@ static void smb2srv_open_recreate_fn(
struct smb2srv_open_recreate_state *state = private_data;
TDB_DATA key = dbwrap_record_get_key(rec);
struct smbXsrv_open_global0 *global = NULL;
+ struct GUID_txt_buf buf1, buf2;
state->status = smbXsrv_open_global_verify_record(
key, oldval, state->op, &state->op->global);
- if (!NT_STATUS_IS_OK(state->status)) {
+ if (!NT_STATUS_EQUAL(state->status, NT_STATUS_REMOTE_DISCONNECT)) {
DBG_WARNING("smbXsrv_open_global_verify_record for %s "
"failed: %s\n",
tdb_data_dbg(key),
@@ -1184,6 +1188,16 @@ static void smb2srv_open_recreate_fn(
}
global = state->op->global;
+ if (state->lease_key != NULL &&
+ !GUID_equal(&global->client_guid, state->client_guid))
+ {
+ DBG_NOTICE("client guid: %s != %s in %s\n",
+ GUID_buf_string(&global->client_guid, &buf1),
+ GUID_buf_string(state->client_guid, &buf2),
+ tdb_data_dbg(key));
+ goto not_found;
+ }
+
/*
* If the provided create_guid is NULL, this means that
* the reconnect request was a v1 request. In that case
@@ -1192,7 +1206,6 @@ static void smb2srv_open_recreate_fn(
*/
if ((state->create_guid != NULL) &&
!GUID_equal(&global->create_guid, state->create_guid)) {
- struct GUID_txt_buf buf1, buf2;
DBG_NOTICE("%s != %s in %s\n",
GUID_buf_string(&global->create_guid, &buf1),
GUID_buf_string(state->create_guid, &buf2),
@@ -1206,7 +1219,8 @@ static void smb2srv_open_recreate_fn(
DBG_NOTICE("global owner %s not in our token in %s\n",
dom_sid_str_buf(&global->open_owner, &buf),
tdb_data_dbg(key));
- goto not_found;
+ state->status = NT_STATUS_ACCESS_DENIED;
+ return;
}
if (!global->durable) {
@@ -1237,12 +1251,15 @@ NTSTATUS smb2srv_open_recreate(struct
smbXsrv_connection *conn,
struct auth_session_info *session_info,
uint64_t persistent_id,
const struct GUID *create_guid,
+ const struct smb2_lease_key *lease_key,
NTTIME now,
struct smbXsrv_open **_open)
{
struct smbXsrv_open_table *table = conn->client->open_table;
struct smb2srv_open_recreate_state state = {
+ .client_guid = &conn->client->global->client_guid,
.create_guid = create_guid,
+ .lease_key = lease_key,
.me = messaging_server_id(conn->client->msg_ctx),
};
struct smbXsrv_open_global_key_buf key_buf;
@@ -1459,7 +1476,7 @@ static void smbXsrv_open_cleanup_fn(
}
if (!delete_open) {
- state->status = NT_STATUS_OK;
+ state->status = NT_STATUS_CANNOT_DELETE;
return;
}
do_delete:
@@ -1478,6 +1495,7 @@ do_delete:
"deleted record from %s\n",
state->global_id,
dbwrap_name(dbwrap_record_get_db(rec)));
+ state->status = NT_STATUS_OK;
}
NTSTATUS smbXsrv_open_cleanup(uint64_t persistent_id)
diff --git a/source3/smbd/smbXsrv_open.h b/source3/smbd/smbXsrv_open.h
index 02576501237..58e585888e2 100644
--- a/source3/smbd/smbXsrv_open.h
+++ b/source3/smbd/smbXsrv_open.h
@@ -58,10 +58,12 @@ NTSTATUS smb2srv_open_lookup_replay_cache(struct
smbXsrv_connection *conn,
const char *name,
NTTIME now,
struct smbXsrv_open **_open);
+struct smb2_lease_key;
NTSTATUS smb2srv_open_recreate(struct smbXsrv_connection *conn,
struct auth_session_info *session_info,
uint64_t persistent_id,
const struct GUID *create_guid,
+ const struct smb2_lease_key *lease_key,
NTTIME now,
struct smbXsrv_open **_open);
diff --git a/source4/torture/smb2/durable_open.c
b/source4/torture/smb2/durable_open.c
index b730fab3c29..2c5bc2224e6 100644
--- a/source4/torture/smb2/durable_open.c
+++ b/source4/torture/smb2/durable_open.c
@@ -26,7 +26,11 @@
#include "../libcli/smb/smbXcli_base.h"
--
Samba Shared Repository