The branch, master has been updated
       via  d41d9f8d29a docs: document serverid command
       via  3b954ccbaab net: add `net tdb smbXsrv wipedbs` alias for `net 
serverid wipedbs`
       via  ebf53bcaa89 net: handle replay records in `net serverid wipedbs`
       via  fdb3e0206f1 smbd: return replay-cache records in 
smbXsrv_open_global_traverse()
       via  6a8bf702bb0 smbd: reformat smbXsrv_open_global_traverse() function 
pointer args
       via  26ee6686079 smbd: also delete replay cache record in 
smbXsrv_open_cleanup()
       via  20c63692661 smbd: make create-replay cache disk backed
       via  de1b2b0d07e libndr: add support for unions to 
ndr_pull_struct_blob_noalloc() and ndr_push_struct_into_fixed_blob()
       via  9b5b63870f7 smbd: implement session check from MS-SMB2 3.3.5.9 
Receiving an SMB2 CREATE Request
       via  990322a48aa smbd: Add session_global_id and tcon_global_id to 
smbXsrv_open_global0
       via  9f9409a80ac smbd: add smbXsrv_tcon to smbXsrv_open
       via  e6134129791 smbd: add smbXsrv_session to smbXsrv_open
       via  3cd4018b7e4 smbd: add and use smbXsrv_open_replay_cache_key_buf
       via  7e8aa812a5d smbd: make the replay cache record an index on the 
global open table
       via  81fb4a77122 smbd: invert logic when handling pending create in 
smb2srv_open_lookup_replay_cache()
       via  09e859756bb smbd: move create_action to smbXsrv_open_global0
       via  f6e7d85e632 smbd: simplify create-replay
       via  f149ab455d0 smbd: move DH2Q context processing to its own function
       via  f97751a110e smbd: add some debugging to 
smbXsrv_open_[lookup|set]_replay_cache()
       via  c63d63e36ab smbd: move create_action handling to 
smbd_smb2_create_after_exec()
       via  93c1f55917e smbd: simplify create_action handling
       via  45aa16a77a5 smbtorture: add test smb2.replay.replay-twice-durable
       via  cd672d1e2b7 smbtorture: add test 
smb2.replay.durable-reconnect-replay3
       via  8695f2af60f smbtorture: add test 
smb2.replay.durable-reconnect-replay2
       via  12d5201d8ee smbtorture: add test 
smb2.replay.durable-reconnect-replay1
       via  06d13da577a smbd: fix include order in smbXsrv_open.c
       via  e5806227fd8 s3/dbwrap_watch: avoid leaking backend db handle in 
traverses
      from  a4dff82e453 s3:utils: Allow ROLE_IPA_DC to allow to use Kerberos in 
gensec

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit d41d9f8d29ae66d90fab35b4f3f840cf0ea07d42
Author: Ralph Boehme <s...@samba.org>
Date:   Fri Jul 11 14:29:38 2025 +0200

    docs: document serverid command
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>
    
    Autobuild-User(master): Ralph Böhme <s...@samba.org>
    Autobuild-Date(master): Tue Aug  5 16:03:56 UTC 2025 on atb-devel-224

commit 3b954ccbaab39f7ce3223eb6a28b0e9fde67d007
Author: Ralph Boehme <s...@samba.org>
Date:   Sun Jun 29 18:04:41 2025 +0200

    net: add `net tdb smbXsrv wipedbs` alias for `net serverid wipedbs`
    
    `net serverid` is imho not the right place for the wipedbs functionality. 
Add
    it as an alias to `net tdb`. It works pretty opaque and unless you run
    
     # net tdb smbXsrv wipedbs --help
     Usage:
     net serverid wipedbs [--test] [--verbose]
     Example:
     net serverid wipedbs -v
    
    the use won't notice it is an alias.
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit ebf53bcaa893914c49417d382a6b6384cbbaee50
Author: Ralph Boehme <s...@samba.org>
Date:   Sat Jul 26 15:27:41 2025 +0200

    net: handle replay records in `net serverid wipedbs`
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit fdb3e0206f1a46a81ed93b91cdb8f51ec6ab1c63
Author: Ralph Boehme <s...@samba.org>
Date:   Fri Jul 11 06:30:15 2025 +0200

    smbd: return replay-cache records in smbXsrv_open_global_traverse()
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit 6a8bf702bb0bd63df18849545de88936db169989
Author: Ralph Boehme <s...@samba.org>
Date:   Tue Jun 17 16:13:52 2025 +0200

    smbd: reformat smbXsrv_open_global_traverse() function pointer args
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit 26ee66860795d2a9bdf0763517b84fba0bbe8c30
Author: Ralph Boehme <s...@samba.org>
Date:   Tue Jun 17 16:59:07 2025 +0200

    smbd: also delete replay cache record in smbXsrv_open_cleanup()
    
    Add and use smbXsrv_replay_cleanup() to delete replay cache records. Another
    external caller comes later, hence adding this as a public function.
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit 20c636926617b7232464b1ddb29018dd637a8bd1
Author: Ralph Boehme <s...@samba.org>
Date:   Sat Jul 26 15:05:45 2025 +0200

    smbd: make create-replay cache disk backed
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit de1b2b0d07ef32ff8b9ab4fbf2bec51b227256ec
Author: Ralph Boehme <s...@samba.org>
Date:   Fri Jul 11 06:02:13 2025 +0200

    libndr: add support for unions to ndr_pull_struct_blob_noalloc() and 
ndr_push_struct_into_fixed_blob()
    
    The union switch value is stored by ndr_token_store() which uses talloc to
    manage ndr.switch_list. Preallocate a ndr_token array and ndr_token_list on 
the
    stack of size ndr_token_list.fixed_alloc_count and optionally use that in
    ndr_token_store().
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit 9b5b63870f7f0e0a5f89f14515529a9fdbfdb879
Author: Ralph Boehme <s...@samba.org>
Date:   Thu Jul 10 16:48:22 2025 +0200

    smbd: implement session check from MS-SMB2 3.3.5.9 Receiving an SMB2 CREATE 
Request
    
    If the server implements the SMB 3.x dialect family and all of the 
following conditions are TRUE, the
    server MUST look up an Open in GlobalOpenTable where Open.IsReplayEligible 
is TRUE and
    Open.CreateGuid matches the CreateGuid in the 
SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2
    create context and Open.ClientGuid matches the ClientGuid of the connection 
that received this
    request:
    
    ...
    
    If an Open is found, the server MUST perform the following:
    
    ...
    
    If Open.Session.SessionId is not equal to the current Session.SessionId, 
the server MUST fail
    the request with STATUS_DUPLICATE_OBJECTID.
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit 990322a48aa7d25b3ee126273186dba54d05a85d
Author: Ralph Boehme <s...@samba.org>
Date:   Thu Jul 10 13:10:42 2025 +0200

    smbd: Add session_global_id and tcon_global_id to smbXsrv_open_global0
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit 9f9409a80ac4acdccfef08b13cd59d0f5dc38f8f
Author: Ralph Boehme <s...@samba.org>
Date:   Fri Jul 11 06:49:54 2025 +0200

    smbd: add smbXsrv_tcon to smbXsrv_open
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit e61341297910f034c5fafa1662c2712147c737c2
Author: Ralph Boehme <s...@samba.org>
Date:   Sat Jun 28 08:55:25 2025 +0200

    smbd: add smbXsrv_session to smbXsrv_open
    
    From "MS-SMB2 3.3.1.10 Per Open":
    
      Open.Session: A reference to the authenticated session, as specified in 
section
      3.3.1.8, over which this open was performed. If the open is not attached 
to a
      session at this time, this value MUST be NULL.
    
    Needed to implement:
    
      3.3.5.9 Receiving an SMB2 CREATE Request
    
      If the server implements the SMB 3.x dialect family and all of the 
following
      conditions are TRUE, the server MUST look up an Open in GlobalOpenTable 
where
      Open.IsReplayEligible is TRUE and Open.CreateGuid matches the CreateGuid 
in
      the SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 create context and 
Open.ClientGuid
      matches the ClientGuid of the connection that received this request:
    
      ...
    
      If an Open is found, the server MUST perform the following:
    
      ..
    
      If Open.Session.SessionId is not equal to the current Session.SessionId, 
the
      server MUST fail the request with STATUS_DUPLICATE_OBJECTID.
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit 3cd4018b7e49201065f16a62568ea47849c3fc60
Author: Ralph Boehme <s...@samba.org>
Date:   Sat Jul 26 14:49:10 2025 +0200

    smbd: add and use smbXsrv_open_replay_cache_key_buf
    
    No change in behaviour.
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit 7e8aa812a5deec7ef5afc5a457acdeb35a5f7dab
Author: Ralph Boehme <s...@samba.org>
Date:   Thu Jul 10 16:31:16 2025 +0200

    smbd: make the replay cache record an index on the global open table
    
    Store only the open_global record key as is in the replay-cache record, 
making
    it an index into the global open table. Then in the replay code, use the new
    function smbXsrv_open_global_lookup() to get at the open records.
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit 81fb4a7712203a63787ebad85002c7728708fda6
Author: Ralph Boehme <s...@samba.org>
Date:   Sat Jul 12 08:27:38 2025 +0200

    smbd: invert logic when handling pending create in 
smb2srv_open_lookup_replay_cache()
    
    No change in behaviour.
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit 09e859756bb6fc9deee403212503fb4a567d1382
Author: Ralph Boehme <s...@samba.org>
Date:   Thu Jul 10 15:51:12 2025 +0200

    smbd: move create_action to smbXsrv_open_global0
    
    In preperation for making create replay disk backed.
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit f6e7d85e632c7e5ef63cefe7dc3be2e83978e269
Author: Ralph Boehme <s...@samba.org>
Date:   Thu Jul 10 15:33:48 2025 +0200

    smbd: simplify create-replay
    
    Just check state->open_was_deferred and skip calling
    smb2srv_open_lookup_replay_cache() if it is set.
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit f149ab455d01ccdb7c29d58ce86a894db807d4c5
Author: Ralph Boehme <s...@samba.org>
Date:   Thu Jul 10 14:38:53 2025 +0200

    smbd: move DH2Q context processing to its own function
    
    The DH2Q processing code is getting a bit bloated, move it to it's own
    function. This also simplifies a coming change where I'll add an early out.
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit f97751a110e093e301d24e734d64a2a638dd7c8a
Author: Ralph Boehme <s...@samba.org>
Date:   Sat Jun 14 19:13:44 2025 +0200

    smbd: add some debugging to smbXsrv_open_[lookup|set]_replay_cache()
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit c63d63e36ab83be9a2d4a4df41f59bf7ae1af06a
Author: Ralph Boehme <s...@samba.org>
Date:   Sat Jun 14 15:41:38 2025 +0200

    smbd: move create_action handling to smbd_smb2_create_after_exec()
    
    This ensures op->create_action is set when we're calling 
smbXsrv_open_update()
    and fixes create_action handling for create replays.
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit 93c1f55917ee0500b3c9fc169063cb3a5a492983
Author: Ralph Boehme <s...@samba.org>
Date:   Tue Jul 8 14:47:24 2025 +0200

    smbd: simplify create_action handling
    
    (state->info == FILE_WAS_OVERWRITTEN) can only happen when returning
    SMB_VFS_CREATE_FILE(), not for a Durable Handle reconnect or Replay, hence 
we
    can move the check and adjustment of state->info to smbd_smb2_create_send()
    after the call to SMB_VFS_CREATE_FILE().
    
    This nicely simplifies the logic in smbd_smb2_create_finish() where we can 
now
    just set state->op->create_action and state->out_create_action to the value 
of
    state->info.
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit 45aa16a77a55600cf972dcc11f2f003cd991ed73
Author: Ralph Boehme <s...@samba.org>
Date:   Mon Jun 30 16:45:35 2025 +0200

    smbtorture: add test smb2.replay.replay-twice-durable
    
    This verifies a second replay on a durable handle, after the handle has
    already been used, is "ignored" and handled as a normal open.
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit cd672d1e2b7325a3734a69929f013adde46e7d2c
Author: Ralph Boehme <s...@samba.org>
Date:   Mon Jun 30 12:17:24 2025 +0200

    smbtorture: add test smb2.replay.durable-reconnect-replay3
    
    This verifies a CREATE replay on a second connection with 
previous_session_id
    set is working correctly.
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit 8695f2af60fa2245a11e0efd69ca63b2e0cc7bd1
Author: Ralph Boehme <s...@samba.org>
Date:   Mon Jun 30 10:19:14 2025 +0200

    smbtorture: add test smb2.replay.durable-reconnect-replay2
    
    This verifies a replay on a new connection with a new sesssion fails
    with NT_STATUS_DUPLICATE_OBJECTID.
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit 12d5201d8eebf2d6834c7a36f5797ed9d5fce102
Author: Ralph Boehme <s...@samba.org>
Date:   Tue Jun 17 17:56:07 2025 +0200

    smbtorture: add test smb2.replay.durable-reconnect-replay1
    
    This verifies CREATE replay is working on a new connection.
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit 06d13da577ae95eada1e63eaa203a1a9394bd4d4
Author: Ralph Boehme <s...@samba.org>
Date:   Tue Jun 17 16:26:46 2025 +0200

    smbd: fix include order in smbXsrv_open.c
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit e5806227fd8d2fabf203b6060bd9ad9bde7380e1
Author: Ralph Boehme <s...@samba.org>
Date:   Mon Jun 23 10:17:32 2025 +0200

    s3/dbwrap_watch: avoid leaking backend db handle in traverses
    
    Currently in a traverse callback dbwrap_record_get_db() returns the backend 
db
    handle.
    
    Signed-off-by: Ralph Boehme <s...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

-----------------------------------------------------------------------

Summary of changes:
 docs-xml/manpages/net.8.xml       |  36 +++
 librpc/ndr/libndr.h               |   1 +
 librpc/ndr/ndr.c                  |  26 ++-
 source3/lib/dbwrap/dbwrap_watch.c |   6 +-
 source3/librpc/idl/smbXsrv.idl    |  17 +-
 source3/smbd/files.c              |   3 +-
 source3/smbd/smb2_create.c        | 272 +++++++++++++----------
 source3/smbd/smbXsrv_open.c       | 428 +++++++++++++++++++++++------------
 source3/smbd/smbXsrv_open.h       |  16 +-
 source3/utils/net_proto.h         |   2 +
 source3/utils/net_serverid.c      | 244 ++++++++++++++++++--
 source3/utils/net_tdb.c           |  24 ++
 source4/torture/smb2/replay.c     | 455 ++++++++++++++++++++++++++++++++++++++
 13 files changed, 1242 insertions(+), 288 deletions(-)


Changeset truncated at 500 lines:

diff --git a/docs-xml/manpages/net.8.xml b/docs-xml/manpages/net.8.xml
index a2cdcac1e9c..d9293d0bb34 100644
--- a/docs-xml/manpages/net.8.xml
+++ b/docs-xml/manpages/net.8.xml
@@ -3141,6 +3141,13 @@ Dump the locking table of a certain global lock.
                </itemizedlist>
 
        </refsect3>
+
+       <refsect3>
+               <title>tdb smbXsrv wipedbs</title>
+               <para>Clean stale entries from smbXsrv databases.</para>
+               <para>An alias for <command>net serverid wipedbs</command>.
+               </para>
+       </refsect3>
 </refsect2>
 
 <refsect2>
@@ -3752,6 +3759,35 @@ net witness force-response   Force an AsyncNotify 
response based on json input (
 
 </refsect3>
 
+</refsect2>
+
+<refsect2>
+  <title>serverid</title>
+  <para>Check existence of a serverid and clean stale entries from fileserver
+  state databases.</para>
+  <para>The following commands are implemented:
+  <simplelist>
+    <member>net serverid exists          Check existence of a serverid</member>
+    <member>net serverid wipedbs         Clean stale entries from fileserver 
state databases</member>
+  </simplelist>
+  </para>
+
+<refsect3>
+  <title>serverid exists &lt;serverid&gt;</title>
+  <para>Checks if a serverid exits.</para>
+</refsect3>
+
+<refsect3>
+  <title>serverid wipedbs</title>
+  <para>Clean stale entries from fileserver state databases</para>
+  <para>Options for wipedbs:</para>
+  <para>        --test</para>
+  <para>            Only check for stale entries and log them</para>
+  <para>        --verbose</para>
+  <para>            Produce verbose logging</para>
+</refsect3>
+
+
 </refsect2>
 
 <refsect2>
diff --git a/librpc/ndr/libndr.h b/librpc/ndr/libndr.h
index 344f08b20a1..7ee706c6085 100644
--- a/librpc/ndr/libndr.h
+++ b/librpc/ndr/libndr.h
@@ -44,6 +44,7 @@ struct ndr_token;
 struct ndr_token_list {
        struct ndr_token *tokens;
        uint32_t count;
+       uint32_t fixed_alloc_count;
 };
 
 struct ndr_compression_state;
diff --git a/librpc/ndr/ndr.c b/librpc/ndr/ndr.c
index 082bacc2fa6..fc08b6661f8 100644
--- a/librpc/ndr/ndr.c
+++ b/librpc/ndr/ndr.c
@@ -48,6 +48,11 @@
  */
 #define NDR_TOKEN_MAX_LIST_SIZE 65535
 
+/*
+ * An arbitrary limit used by the fixed-size pull/push functions
+ */
+#define NDR_FIXED_SIZE_MARSHALL_MAX_TOKENS 10
+
 size_t ndr_token_max_list_size(void) {
        return NDR_TOKEN_MAX_LIST_SIZE;
 };
@@ -1081,6 +1086,12 @@ _PUBLIC_ enum ndr_err_code ndr_token_store(TALLOC_CTX 
*mem_ctx,
                         const void *key,
                         uint32_t value)
 {
+       if (list->fixed_alloc_count != 0) {
+               if (list->count >= list->fixed_alloc_count) {
+                       return NDR_ERR_RANGE;
+               }
+               goto store;
+       }
        if (list->tokens == NULL) {
                list->tokens = talloc_array(mem_ctx, struct ndr_token, 10);
                if (list->tokens == NULL) {
@@ -1115,6 +1126,7 @@ _PUBLIC_ enum ndr_err_code ndr_token_store(TALLOC_CTX 
*mem_ctx,
                        list->tokens = new_tokens;
                }
        }
+store:
        list->tokens[list->count].key = key;
        list->tokens[list->count].value = value;
        list->count++;
@@ -1511,10 +1523,16 @@ _PUBLIC_ enum ndr_err_code 
ndr_pull_struct_blob_noalloc(const uint8_t *buf,
         * This allows us to keep the safety of the PIDL-generated
         * code without the talloc() overhead.
         */
+       struct ndr_token tokens[NDR_FIXED_SIZE_MARSHALL_MAX_TOKENS];
+       struct ndr_token_list switch_list = {
+               .tokens = tokens,
+               .fixed_alloc_count = ARRAY_SIZE(tokens),
+       };
        struct ndr_pull ndr = {
                .data = discard_const_p(uint8_t, buf),
                .data_size = buflen,
                .current_mem_ctx = (void *)-1,
+               .switch_list = switch_list,
        };
 
        NDR_CHECK(fn(&ndr, NDR_SCALARS|NDR_BUFFERS, p));
@@ -1632,10 +1650,16 @@ _PUBLIC_ enum ndr_err_code 
ndr_push_struct_blob(DATA_BLOB *blob, TALLOC_CTX *mem
 _PUBLIC_ enum ndr_err_code ndr_push_struct_into_fixed_blob(
        DATA_BLOB *blob, const void *p, ndr_push_flags_fn_t fn)
 {
+       struct ndr_token tokens[NDR_FIXED_SIZE_MARSHALL_MAX_TOKENS];
+       struct ndr_token_list switch_list = {
+               .tokens = tokens,
+               .fixed_alloc_count = ARRAY_SIZE(tokens),
+       };
        struct ndr_push ndr = {
                .data = blob->data,
                .alloc_size = blob->length,
-               .fixed_buf_size = true
+               .fixed_buf_size = true,
+               .switch_list = switch_list,
        };
 
        NDR_CHECK(fn(&ndr, NDR_SCALARS|NDR_BUFFERS, p));
diff --git a/source3/lib/dbwrap/dbwrap_watch.c 
b/source3/lib/dbwrap/dbwrap_watch.c
index df931192c21..e62aba91090 100644
--- a/source3/lib/dbwrap/dbwrap_watch.c
+++ b/source3/lib/dbwrap/dbwrap_watch.c
@@ -653,6 +653,7 @@ static NTSTATUS dbwrap_watched_delete(struct db_record *rec)
 }
 
 struct dbwrap_watched_traverse_state {
+       struct db_context *db;
        int (*fn)(struct db_record *rec, void *private_data);
        void *private_data;
 };
@@ -672,6 +673,7 @@ static int dbwrap_watched_traverse_fn(struct db_record *rec,
                return 0;
        }
        prec.value_valid = true;
+       prec.db = state->db;
 
        return state->fn(&prec, state->private_data);
 }
@@ -684,7 +686,7 @@ static int dbwrap_watched_traverse(struct db_context *db,
        struct db_watched_ctx *ctx = talloc_get_type_abort(
                db->private_data, struct db_watched_ctx);
        struct dbwrap_watched_traverse_state state = {
-               .fn = fn, .private_data = private_data };
+               .db = db, .fn = fn, .private_data = private_data };
        NTSTATUS status;
        int ret;
 
@@ -704,7 +706,7 @@ static int dbwrap_watched_traverse_read(struct db_context 
*db,
        struct db_watched_ctx *ctx = talloc_get_type_abort(
                db->private_data, struct db_watched_ctx);
        struct dbwrap_watched_traverse_state state = {
-               .fn = fn, .private_data = private_data };
+               .db = db, .fn = fn, .private_data = private_data };
        NTSTATUS status;
        int ret;
 
diff --git a/source3/librpc/idl/smbXsrv.idl b/source3/librpc/idl/smbXsrv.idl
index 9aaa836cd7a..af7335e1d2a 100644
--- a/source3/librpc/idl/smbXsrv.idl
+++ b/source3/librpc/idl/smbXsrv.idl
@@ -422,6 +422,8 @@ interface smbXsrv
 
        typedef struct {
                server_id                               server_id;
+               hyper                                   session_global_id;
+               uint32                                  tcon_global_id;
                uint32                                  open_global_id;
                hyper                                   open_persistent_id;
                hyper                                   open_volatile_id;
@@ -430,6 +432,7 @@ interface smbXsrv
                GUID                                    create_guid;
                GUID                                    client_guid;
                GUID                                    app_instance_id;
+               uint32                                  create_action;
                /*
                 * TODO: for durable/resilient/persistent handles we need more
                 *       things here. See [MS-SMB2] 3.3.1.10 Per Open
@@ -473,11 +476,12 @@ interface smbXsrv
                [ignore] smbXsrv_open_table             *table;
                uint32                                  local_id;
                [ref] smbXsrv_open_global0              *global;
+               smbXsrv_session                         *session;
+               smbXsrv_tcon                            *tcon;
                NTSTATUS                                status;
                NTTIME                                  idle_time;
                [ignore] files_struct                   *compat;
                smbXsrv_open_flags                      flags;
-               uint32                                  create_action;
                hyper                                   request_count;
                hyper                                   pre_request_count;
        } smbXsrv_open;
@@ -493,10 +497,13 @@ interface smbXsrv
                [switch_is(version)] smbXsrv_openU      info;
        } smbXsrv_openB;
 
-       const uint32 SMBXSRV_OPEN_REPLAY_CACHE_FIXED_SIZE = 28;
+       const uint32 SMBXSRV_OPEN_REPLAY_CACHE_KEY_FIXED_SIZE = 32;
        typedef [public] struct {
-               GUID                                    holder_req_guid;
-               NTTIME                                  idle_time;
-               uint32                                  local_id;
+               GUID                                    client_guid;
+               GUID                                    create_guid;
+       } smbXsrv_open_replay_cache_key;
+
+       typedef [public] struct {
+               DATA_BLOB                               open_global_key;
        } smbXsrv_open_replay_cache;
 }
diff --git a/source3/smbd/files.c b/source3/smbd/files.c
index 73c20b68004..4cc203d8a1a 100644
--- a/source3/smbd/files.c
+++ b/source3/smbd/files.c
@@ -120,7 +120,8 @@ NTSTATUS fsp_bind_smb(struct files_struct *fsp, struct 
smb_request *req)
        now = timeval_to_nttime(&fsp->open_time);
 
        status = smbXsrv_open_create(req->xconn,
-                                    fsp->conn->session_info,
+                                    req->session,
+                                    fsp->conn->tcon,
                                     now,
                                     &op);
        if (!NT_STATUS_IS_OK(status)) {
diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c
index 12e87ec7b6f..f8f63e85287 100644
--- a/source3/smbd/smb2_create.c
+++ b/source3/smbd/smb2_create.c
@@ -682,6 +682,7 @@ struct smbd_smb2_create_state {
        struct deferred_open_record *open_rec;
        files_struct *result;
        bool replay_operation;
+       bool replay_reconnect;
        uint8_t in_oplock_level;
        uint32_t in_create_disposition;
        uint32_t in_create_options;
@@ -1078,11 +1079,12 @@ static struct tevent_req 
*smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
         * there is nothing else to do), durable_reconnect or
         * new open.
         */
-       if (state->replay_operation) {
+       if (state->replay_operation && !state->replay_reconnect) {
+               SMB_ASSERT(state->op != NULL);
                state->result = state->op->compat;
                state->result->op = state->op;
                state->update_open = false;
-               state->info = state->op->create_action;
+               state->info = state->op->global->create_action;
 
                smbd_smb2_create_after_exec(req);
                if (!tevent_req_is_in_progress(req)) {
@@ -1093,16 +1095,23 @@ static struct tevent_req 
*smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
                return req;
        }
 
-       if (state->do_durable_reconnect) {
+       if (state->do_durable_reconnect || state->replay_reconnect) {
                DATA_BLOB new_cookie = data_blob_null;
                NTTIME now = timeval_to_nttime(&smb2req->request_time);
                const struct smb2_lease_key *lease_key = NULL;
 
+               /*
+                * Assert a replay on a multichannel connection doesn't end up
+                * here.
+                */
+               SMB_ASSERT(state->op == NULL);
+
                if (state->lease_ptr != NULL) {
                        lease_key = &state->lease_ptr->lease_key;
                }
                status = smb2srv_open_recreate(smb2req->xconn,
-                                              smb1req->conn->session_info,
+                                              smb2req->session,
+                                              smb2req->tcon,
                                               state->persistent_id,
                                               state->create_guid,
                                               lease_key,
@@ -1167,7 +1176,11 @@ static struct tevent_req 
*smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
 
                state->update_open = true;
 
-               state->info = FILE_WAS_OPENED;
+               if (!state->replay_reconnect) {
+                       state->info = FILE_WAS_OPENED;
+               } else {
+                       state->info = state->op->global->create_action;
+               }
 
                smbd_smb2_create_after_exec(req);
                if (!tevent_req_is_in_progress(req)) {
@@ -1325,6 +1338,12 @@ static struct tevent_req 
*smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
        }
        state->op = state->result->op;
 
+       if ((state->in_create_disposition == FILE_SUPERSEDE) &&
+           (state->info == FILE_WAS_OVERWRITTEN))
+       {
+               state->info = FILE_WAS_SUPERSEDED;
+       }
+
        smbd_smb2_create_after_exec(req);
        if (!tevent_req_is_in_progress(req)) {
                return tevent_req_post(req, state->ev);
@@ -1359,6 +1378,135 @@ static void smbd_smb2_create_purge_replay_cache(struct 
tevent_req *req,
        state->purge_create_guid = NULL;
 }
 
+static void smbd_smb2_cc_before_exec_dhc2q(struct tevent_req *req)
+{
+       struct smbd_smb2_create_state *state = tevent_req_data(
+               req, struct smbd_smb2_create_state);
+       struct smbd_smb2_request *smb2req = state->smb2req;
+       const uint8_t *p = state->dh2q->data.data;
+       NTTIME now = timeval_to_nttime(&smb2req->request_time);
+       uint32_t durable_v2_timeout = 0;
+       DATA_BLOB create_guid_blob;
+       const uint8_t *hdr = NULL;
+       uint32_t flags;
+       NTSTATUS status;
+
+       if (state->dh2q->data.length != 32) {
+               tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
+       }
+
+       if (state->dhnq != NULL) {
+               tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
+       }
+
+       durable_v2_timeout = IVAL(p, 0);
+       create_guid_blob = data_blob_const(p + 16, 16);
+
+       status = GUID_from_ndr_blob(&create_guid_blob,
+                                   &state->_create_guid);
+       if (tevent_req_nterror(req, status)) {
+               return;
+       }
+       state->create_guid = &state->_create_guid;
+
+       /*
+        * we need to store the create_guid later
+        */
+       state->update_open = true;
+
+       /*
+        * And we need to create a cache for replaying the
+        * create.
+        */
+       state->need_replay_cache = true;
+
+       /*
+        * durable handle v2 request processed below
+        */
+       state->durable_requested = true;
+       state->durable_timeout_msec = MIN(durable_v2_timeout, 300*1000);
+       if (state->durable_timeout_msec == 0) {
+               /*
+                * Set the timeout to 1 min as default.
+                *
+                * This matches Windows 2012.
+                */
+               state->durable_timeout_msec = (60*1000);
+       }
+
+       /*
+        * Check for replay operation.
+        * Only consider it when we have dh2q.
+        * If we do not have a replay operation, verify that
+        * the create_guid is not cached for replay.
+        */
+       hdr = SMBD_SMB2_IN_HDR_PTR(smb2req);
+       flags = IVAL(hdr, SMB2_HDR_FLAGS);
+       state->replay_operation = flags & SMB2_HDR_FLAG_REPLAY_OPERATION;
+
+       if (state->open_was_deferred) {
+               /*
+                * When processing a redispatched deferred open, we have the
+                * following state:
+                * - no OPEN record
+                * - RC record with global_file_id=0 (pending open state)
+                *
+                * We just skip calling smb2srv_open_lookup_replay_cache() as
+                * - we already have a RC record
+                * - it would fail with NT_STATUS_FILE_NOT_AVAILABLE which is
+                *   not what we want in this "internal replay" case
+                *
+                * So we just set replay_operation to false and move on.
+                */
+               state->replay_operation = false;
+               return;
+       }
+
+       status = smb2srv_open_lookup_replay_cache(smb2req->xconn,
+                                                 smb2req->session,
+                                                 *state->create_guid,
+                                                 state->fname,
+                                                 now,
+                                                 &state->persistent_id,
+                                                 &state->op);
+       if (NT_STATUS_EQUAL(status, NT_STATUS_FWP_RESERVED)) {
+               /*
+                * We've reserved the replay_cache record
+                * for ourself, indicating we're still
+                * in progress.
+                *
+                * It means the smbd_smb2_create_cleanup()
+                * may need to call smbXsrv_open_purge_replay_cache()
+                * in order to cleanup.
+                */
+               SMB_ASSERT(state->op == NULL);
+               state->_purge_create_guid = state->_create_guid;
+               state->purge_create_guid = &state->_purge_create_guid;
+               state->replay_operation = false;
+       } else if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_NOT_AVAILABLE)) {
+               tevent_req_nterror(req, status);
+               return;
+       } else if (NT_STATUS_EQUAL(status, NT_STATUS_HANDLE_NO_LONGER_VALID)) {
+               state->replay_reconnect = true;
+       } else if (tevent_req_nterror(req, status)) {
+               DBG_WARNING("smb2srv_open_lookup_replay_cache "
+                           "failed: %s\n", nt_errstr(status));
+               return;
+       } else if (!state->replay_operation) {
+               /*
+                * If a create without replay operation flag
+                * is sent but with a create_guid that is
+                * currently in the replay cache -- fail.
+                */
+               (void)tevent_req_nterror(req, NT_STATUS_DUPLICATE_OBJECTID);
+               return;
+       }
+
+       return;
+}
+
 static void smbd_smb2_create_before_exec(struct tevent_req *req)
 {
        struct smbd_smb2_create_state *state = tevent_req_data(
@@ -1444,105 +1592,8 @@ static void smbd_smb2_create_before_exec(struct 
tevent_req *req)
        }
 
        if (state->dh2q != NULL) {
-               const uint8_t *p = state->dh2q->data.data;
-               NTTIME now = timeval_to_nttime(&smb2req->request_time);
-               uint32_t durable_v2_timeout = 0;
-               DATA_BLOB create_guid_blob;
-               const uint8_t *hdr;
-               uint32_t flags;
-
-               if (state->dh2q->data.length != 32) {
-                       tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
-                       return;
-               }
-
-               if (state->dhnq != NULL) {
-                       tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
-                       return;
-               }
-
-               durable_v2_timeout = IVAL(p, 0);
-               create_guid_blob = data_blob_const(p + 16, 16);
-
-               status = GUID_from_ndr_blob(&create_guid_blob,
-                                           &state->_create_guid);
-               if (tevent_req_nterror(req, status)) {
-                       return;
-               }
-               state->create_guid = &state->_create_guid;
-
-               /*
-                * we need to store the create_guid later
-                */
-               state->update_open = true;
-
-               /*
-                * And we need to create a cache for replaying the
-                * create.
-                */
-               state->need_replay_cache = true;
-


-- 
Samba Shared Repository

Reply via email to