smbd: check for previous versions in check_any_access_fsp()
authorRalph Boehme <slow@samba.org>
Wed, 20 Dec 2023 14:09:59 +0000 (15:09 +0100)
committerRalph Boehme <slow@samba.org>
Mon, 8 Jan 2024 15:53:36 +0000 (15:53 +0000)
Now that check_any_access_fsp() is broadly used consistently to
restrict access for all modifying operations, we can add a check for
previous versions to check_any_access_fsp() and it gets enforced
consistently.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=13688

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
selftest/knownfail.d/samba3.blackbox.shadow_copy_torture [deleted file]
source3/smbd/smb2_trans2.c

diff --git a/selftest/knownfail.d/samba3.blackbox.shadow_copy_torture b/selftest/knownfail.d/samba3.blackbox.shadow_copy_torture
deleted file mode 100644 (file)
index 16537e5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-^samba3.blackbox.shadow_copy_torture.writing to shadow copy of a file\(fileserver\)
index 22e0f2f30200209cbd03cf90c0909d485fad27fd..6f272dd6c49d0b98019cf47a2cb66b8302eec757 100644 (file)
@@ -82,6 +82,8 @@ NTSTATUS refuse_symlink_fsp(const files_struct *fsp)
 NTSTATUS check_any_access_fsp(struct files_struct *fsp,
                              uint32_t access_requested)
 {
+       const uint32_t ro_access = SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
+       uint32_t ro_access_granted = 0;
        uint32_t access_granted = 0;
        NTSTATUS status;
 
@@ -102,15 +104,31 @@ NTSTATUS check_any_access_fsp(struct files_struct *fsp,
                                                        false,
                                                        mask);
                        if (NT_STATUS_IS_OK(status)) {
-                               break;
+                               access_granted |= mask;
+                               if (fsp->fsp_name->twrp == 0) {
+                                       /*
+                                        * We can only optimize
+                                        * the non-snapshot case
+                                        */
+                                       break;
+                               }
                        }
                        mask <<= 1;
                }
-               access_granted = mask;
        }
        if ((access_granted & access_requested) == 0) {
                return NT_STATUS_ACCESS_DENIED;
        }
+
+       if (fsp->fsp_name->twrp == 0) {
+               return NT_STATUS_OK;
+       }
+
+       ro_access_granted = access_granted & ro_access;
+       if ((ro_access_granted & access_requested) == 0) {
+               return NT_STATUS_MEDIA_WRITE_PROTECTED;
+       }
+
        return NT_STATUS_OK;
 }