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)
committerJule Anger <janger@samba.org>
Tue, 16 Jan 2024 09:09:15 +0000 (09:09 +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>
(cherry picked from commit fd4e41144a819b4403340e4a28664ac586722b41)

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 b5d73bdf1fa5573a78b17c5638e32b11928b5188..57ee3512581f615cf969e8abfcc3d7525cea731b 100644 (file)
@@ -80,6 +80,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;
 
@@ -100,15 +102,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;
 }