From c3f090b1b2aae78b8261f3c98ce0d1e422d9f94b Mon Sep 17 00:00:00 2001 From: Jan Henning Date: Mon, 2 Dec 2024 23:40:30 +0100 Subject: [PATCH 1/3] Relax too-restrictive trashcan folder check The previous code only allowed sibling folders of the root dir (which doesn't actually guarantee anything about them being on the same volume or not). This is too restrictive (e.g. for hiding the folder inside Android's external files dir), so allow children of the root folder, too. --- .../java/org/filesys/smb/server/disk/JavaNIODeviceContext.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/filesys/smb/server/disk/JavaNIODeviceContext.java b/src/main/java/org/filesys/smb/server/disk/JavaNIODeviceContext.java index 7d4d049..f0acf9e 100644 --- a/src/main/java/org/filesys/smb/server/disk/JavaNIODeviceContext.java +++ b/src/main/java/org/filesys/smb/server/disk/JavaNIODeviceContext.java @@ -123,7 +123,8 @@ else if ( m_trashDir.isFile()) throw new DeviceContextException("Trashcan path is not a folder - " + m_trashDir.getAbsolutePath()); // Make sure the trashcan folder is on the same volume as the shared folder, so we can rename deleted files - if ( rootDir.getParent().equalsIgnoreCase( m_trashDir.getParent()) == false) { + if (!m_trashDir.getAbsolutePath().startsWith(rootDir.getAbsolutePath()) + && !rootDir.getParent().equalsIgnoreCase(m_trashDir.getParent())) { // File share and trash folders are not on the same volume throw new DeviceContextException("File share and trash folders must be on the same volume"); From 4d9cccca4419994e28f1710ae60f152f251d5102 Mon Sep 17 00:00:00 2001 From: Jan Henning Date: Tue, 3 Dec 2024 20:19:46 +0100 Subject: [PATCH 2/3] Make overriding the JavaNIODeviceContext easier --- .../smb/server/disk/JavaNIODiskDriver.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/filesys/smb/server/disk/JavaNIODiskDriver.java b/src/main/java/org/filesys/smb/server/disk/JavaNIODiskDriver.java index b25cb62..58604a3 100644 --- a/src/main/java/org/filesys/smb/server/disk/JavaNIODiskDriver.java +++ b/src/main/java/org/filesys/smb/server/disk/JavaNIODiskDriver.java @@ -1025,7 +1025,7 @@ public DeviceContext createContext(String shareName, ConfigElement args) throws DeviceContextException { // Parse the configuration and return the device context for this share - JavaNIODeviceContext ctx = new JavaNIODeviceContext( shareName, args); + JavaNIODeviceContext ctx = createJavaNIODeviceContext(shareName, args); // If the trashcan folder is configured then check if there are any trash files left over from a previous // server run @@ -1063,6 +1063,20 @@ public void run() { return ctx; } + /** + * Provide a new JavaNIODeviceContext for + * createContext Override this method to provide your own class. + * + * @param shareName + * @param args + * @return DeviceContext + * @throws DeviceContextException Error creating the device context + */ + protected JavaNIODeviceContext createJavaNIODeviceContext(String shareName, ConfigElement args) + throws DeviceContextException { + return new JavaNIODeviceContext(shareName, args); + } + /** * Connection opened to this disk device * From 4e922aeb4cf2fbc3d56528ff8e29019b2fb88d1b Mon Sep 17 00:00:00 2001 From: Jan Henning Date: Tue, 3 Dec 2024 20:39:02 +0100 Subject: [PATCH 3/3] Allow overriding the trashcan folder same volume check I know a better method to check for the "same volume" condition, but it's Android-specific. So until somebody can come up with a platform-independendent way of implementing this check properly, allow overriding this method by implementers. --- .../smb/server/disk/JavaNIODeviceContext.java | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/filesys/smb/server/disk/JavaNIODeviceContext.java b/src/main/java/org/filesys/smb/server/disk/JavaNIODeviceContext.java index f0acf9e..e66247a 100644 --- a/src/main/java/org/filesys/smb/server/disk/JavaNIODeviceContext.java +++ b/src/main/java/org/filesys/smb/server/disk/JavaNIODeviceContext.java @@ -123,8 +123,7 @@ else if ( m_trashDir.isFile()) throw new DeviceContextException("Trashcan path is not a folder - " + m_trashDir.getAbsolutePath()); // Make sure the trashcan folder is on the same volume as the shared folder, so we can rename deleted files - if (!m_trashDir.getAbsolutePath().startsWith(rootDir.getAbsolutePath()) - && !rootDir.getParent().equalsIgnoreCase(m_trashDir.getParent())) { + if (!isTrashcanOnSameVolume(rootDir, m_trashDir)) { // File share and trash folders are not on the same volume throw new DeviceContextException("File share and trash folders must be on the same volume"); @@ -170,6 +169,24 @@ else if ( m_trashDir.isFile()) } } + /** + * Validate that the trashcan folder resides on the same volume as the shared + * folder. This is a requirement because we want to be able to move files into + * the trashcan by simply renaming them. + *

+ * The default implementation only uses a simple heuristic, override this method + * to provide a more advanced platform-specific check if required. + * + * @param rootDir The root directory of the shared folder + * @param trashCan The proposed trashcan directory + * @return True if the proposed trashcan directory is acceptable, false to + * signal an error + */ + protected boolean isTrashcanOnSameVolume(File rootDir, File trashCan) { + return trashCan.getAbsolutePath().startsWith(rootDir.getAbsolutePath()) + || rootDir.getParent().equalsIgnoreCase(m_trashDir.getParent()); + } + /** * Check if the trashcan folder is configured *