From 27490d4289560f3bce96d2c17447d0588fa3d111 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Jacke?= <bjacke@samba.org>
Date: Sat, 30 Dec 2023 20:45:31 +0100
Subject: [PATCH 10/38] vfs_worm: factor out readonly check

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15997
[backported for CVE-2026-2340]

Signed-off-by: Bjoern Jacke <bjacke@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
(cherry picked from commit 58847271e109e9ebe8d053611bd8b25620d5ecbe)
---
 source3/modules/vfs_worm.c | 40 +++++++++++++++++++++++++-------------
 1 file changed, 27 insertions(+), 13 deletions(-)

diff --git a/source3/modules/vfs_worm.c b/source3/modules/vfs_worm.c
index 402705e96e6..f489c540c3a 100644
--- a/source3/modules/vfs_worm.c
+++ b/source3/modules/vfs_worm.c
@@ -57,6 +57,31 @@ static int vfs_worm_connect(struct vfs_handle_struct *handle,
 
 }
 
+static bool is_readonly(vfs_handle_struct *handle,
+			const struct smb_filename *smb_fname)
+{
+	double age;
+	struct worm_config_data *config = NULL;
+
+	SMB_VFS_HANDLE_GET_DATA(handle,
+				config,
+				struct worm_config_data,
+				return true);
+
+	if (!VALID_STAT(smb_fname->st)) {
+		goto out;
+	}
+
+	age = timespec_elapsed(&smb_fname->st.st_ex_ctime);
+
+	if (age > config->grace_period) {
+		return true;
+	}
+
+out:
+	return false;
+}
+
 static NTSTATUS vfs_worm_create_file(vfs_handle_struct *handle,
 				     struct smb_request *req,
 				     struct files_struct *dirfsp,
@@ -77,25 +102,14 @@ static NTSTATUS vfs_worm_create_file(vfs_handle_struct *handle,
 				     const struct smb2_create_blobs *in_context_blobs,
 				     struct smb2_create_blobs *out_context_blobs)
 {
-	bool readonly = false;
 	const uint32_t write_access_flags =
 		FILE_WRITE_DATA | FILE_APPEND_DATA |
 		FILE_WRITE_ATTRIBUTES | DELETE_ACCESS |
 		WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS;
 	NTSTATUS status;
-	struct worm_config_data *config = NULL;
+	bool readonly;
 
-	SMB_VFS_HANDLE_GET_DATA(handle, config,
-				struct worm_config_data,
-				return NT_STATUS_INTERNAL_ERROR);
-
-	if (VALID_STAT(smb_fname->st)) {
-		double age;
-		age = timespec_elapsed(&smb_fname->st.st_ex_ctime);
-		if (age > config->grace_period) {
-			readonly = true;
-		}
-	}
+	readonly = is_readonly(handle, smb_fname);
 
 	if (readonly && (access_mask & write_access_flags)) {
 		return NT_STATUS_ACCESS_DENIED;
-- 
2.43.0


