[SSHD-265] Provide a file system that can be locked to a dir (eventually user dependant)
Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/d78cbf0f Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/d78cbf0f Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/d78cbf0f Branch: refs/heads/master Commit: d78cbf0fa4dc29508301332973e9a4bacd35f741 Parents: bd33a76 Author: Guillaume Nodet <[email protected]> Authored: Mon Dec 2 22:05:12 2013 +0100 Committer: Guillaume Nodet <[email protected]> Committed: Mon Dec 2 22:05:12 2013 +0100 ---------------------------------------------------------------------- .../file/nativefs/NativeFileSystemView.java | 4 + .../common/file/nativefs/NativeSshFile.java | 4 + .../virtualfs/VirtualFileSystemFactory.java | 75 ++++++++++++++++ .../file/virtualfs/VirtualFileSystemView.java | 63 +++++++++++++ .../common/file/nativefs/NativeSshFileTest.java | 42 +++++++++ .../file/virtualfs/VirtualFileSystemTest.java | 95 ++++++++++++++++++++ 6 files changed, 283 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/d78cbf0f/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeFileSystemView.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeFileSystemView.java b/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeFileSystemView.java index e78b562..69bc2d2 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeFileSystemView.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeFileSystemView.java @@ -72,6 +72,10 @@ public class NativeFileSystemView implements FileSystemView { LOG.debug("Native filesystem view created for user \"{}\" with root \"{}\"", userName, currDir); } + public String getUserName() { + return userName; + } + /** * Get file object. */ http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/d78cbf0f/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeSshFile.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeSshFile.java b/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeSshFile.java index 53d573b..5d2acbe 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeSshFile.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeSshFile.java @@ -87,6 +87,10 @@ public class NativeSshFile implements SshFile { this.userName = userName; } + public File getNativeFile() { + return file; + } + /** * Get full name. */ http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/d78cbf0f/sshd-core/src/main/java/org/apache/sshd/common/file/virtualfs/VirtualFileSystemFactory.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/file/virtualfs/VirtualFileSystemFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/file/virtualfs/VirtualFileSystemFactory.java new file mode 100644 index 0000000..4c99b52 --- /dev/null +++ b/sshd-core/src/main/java/org/apache/sshd/common/file/virtualfs/VirtualFileSystemFactory.java @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.sshd.common.file.virtualfs; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.sshd.common.Session; +import org.apache.sshd.common.file.FileSystemFactory; +import org.apache.sshd.common.file.FileSystemView; + +/** + * SSHd file system factory to reduce the visibility to a physical folder. + */ +public class VirtualFileSystemFactory implements FileSystemFactory { + + private String defaultHomeDir; + private final Map<String, String> homeDirs = new ConcurrentHashMap<String, String>(); + + public VirtualFileSystemFactory() { + } + + public VirtualFileSystemFactory(String defaultHomeDir) { + this.defaultHomeDir = defaultHomeDir; + } + + public void setDefaultHomeDir(String defaultHomeDir) { + this.defaultHomeDir = defaultHomeDir; + } + + public String getDefaultHomeDir() { + return defaultHomeDir; + } + + public void setUserHomeDir(String userName, String userHomeDir) { + homeDirs.put(userName, userHomeDir); + } + + public String getUserHomeDir(String userName) { + return homeDirs.get(userName); + } + + protected String computeRootDir(String userName) { + String homeDir = homeDirs.get(userName); + if (homeDir == null) { + homeDir = defaultHomeDir; + } + if (homeDir == null) { + throw new IllegalStateException("No home directory for user " + userName); + } + return homeDir; + } + + public FileSystemView createFileSystemView(Session session) { + return new VirtualFileSystemView(session.getUsername(), + computeRootDir(session.getUsername())); + } + +} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/d78cbf0f/sshd-core/src/main/java/org/apache/sshd/common/file/virtualfs/VirtualFileSystemView.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/file/virtualfs/VirtualFileSystemView.java b/sshd-core/src/main/java/org/apache/sshd/common/file/virtualfs/VirtualFileSystemView.java new file mode 100644 index 0000000..0c96cf8 --- /dev/null +++ b/sshd-core/src/main/java/org/apache/sshd/common/file/virtualfs/VirtualFileSystemView.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.sshd.common.file.virtualfs; + +import java.io.File; + +import org.apache.sshd.common.file.SshFile; +import org.apache.sshd.common.file.nativefs.NativeFileSystemView; +import org.apache.sshd.common.file.nativefs.NativeSshFile; + +/** + * Virtual file system view reduced to a physical folder + */ +public class VirtualFileSystemView extends NativeFileSystemView { + + private String location; + + public VirtualFileSystemView(String username, String location) { + super(username); + if (location.endsWith("/")) { + location = location.substring(0, location.length() - 1); + } + this.location = location; + } + + @Override + public String getVirtualUserDir() { + return "/"; + } + + @Override + public String getPhysicalUserDir() { + return location; + } + + @Override + protected SshFile getFile(String dir, String file) { + // get actual file object + String location = getPhysicalUserDir(); + String physicalName = NativeSshFile.getPhysicalName(location, dir, file, false); + File fileObj = new File(physicalName); + // strip the root directory and return + String karafFileName = physicalName.substring(location.length()); + return createNativeSshFile(karafFileName, fileObj, getUserName()); + } + +} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/d78cbf0f/sshd-core/src/test/java/org/apache/sshd/common/file/nativefs/NativeSshFileTest.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/test/java/org/apache/sshd/common/file/nativefs/NativeSshFileTest.java b/sshd-core/src/test/java/org/apache/sshd/common/file/nativefs/NativeSshFileTest.java new file mode 100644 index 0000000..a941d85 --- /dev/null +++ b/sshd-core/src/test/java/org/apache/sshd/common/file/nativefs/NativeSshFileTest.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.sshd.common.file.nativefs; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class NativeSshFileTest { + + @Test + public void testResolve() { + assertEquals("/bar", NativeSshFile.getPhysicalName("/", "/foo", "/bar", false)); + assertEquals("/bar", NativeSshFile.getPhysicalName("/", "/", "/bar", false)); + assertEquals("/bar", NativeSshFile.getPhysicalName("/", "/", "bar", false)); + assertEquals("/foo/bar", NativeSshFile.getPhysicalName("/", "/foo", "bar", false)); + assertEquals("/foo/bar", NativeSshFile.getPhysicalName("/", "/foo/xyz", "../bar", false)); + assertEquals("/foo/xyz/bar", NativeSshFile.getPhysicalName("/", "/foo/xyz", "./bar", false)); + + assertEquals("/foo/bar", NativeSshFile.getPhysicalName("/foo", "/", "bar", false)); + assertEquals("/foo/bar", NativeSshFile.getPhysicalName("/foo", "/xyz", "../bar", false)); + assertEquals("/foo/bar", NativeSshFile.getPhysicalName("/foo", "/xyz", "../../bar", false)); + assertEquals("/foo/xyz/bar", NativeSshFile.getPhysicalName("/foo", "/xyz", "./bar", false)); + } + +} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/d78cbf0f/sshd-core/src/test/java/org/apache/sshd/common/file/virtualfs/VirtualFileSystemTest.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/test/java/org/apache/sshd/common/file/virtualfs/VirtualFileSystemTest.java b/sshd-core/src/test/java/org/apache/sshd/common/file/virtualfs/VirtualFileSystemTest.java new file mode 100644 index 0000000..90fb952 --- /dev/null +++ b/sshd-core/src/test/java/org/apache/sshd/common/file/virtualfs/VirtualFileSystemTest.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.sshd.common.file.virtualfs; + +import java.io.File; +import java.io.IOException; + +import org.apache.sshd.SshServer; +import org.apache.sshd.common.AbstractFactoryManager; +import org.apache.sshd.common.file.FileSystemView; +import org.apache.sshd.common.file.SshFile; +import org.apache.sshd.common.file.nativefs.NativeFileSystemFactory; +import org.apache.sshd.common.file.nativefs.NativeSshFile; +import org.apache.sshd.common.session.AbstractSession; +import org.apache.sshd.common.util.Buffer; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class VirtualFileSystemTest { + + @Test + public void testNativeFileSystem() throws IOException { + String homeDir = System.getProperty("user.dir"); + NativeFileSystemFactory vfs = new NativeFileSystemFactory(); + + FileSystemView view = vfs.createFileSystemView(new TestSession()); + + SshFile file = view.getFile("foo"); + String physicalName = ((NativeSshFile) file).getNativeFile().getAbsolutePath(); + assertEquals(homeDir + "/foo", physicalName); + + file = view.getFile(view.getFile("foo"), "../bar"); + physicalName = ((NativeSshFile) file).getNativeFile().getAbsolutePath(); + assertEquals(homeDir + "/bar", physicalName); + + file = view.getFile("../bar"); + physicalName = ((NativeSshFile) file).getNativeFile().getAbsolutePath(); + assertEquals(new File(homeDir, "../bar").getCanonicalPath(), physicalName); + } + + @Test + public void testVirtualFileSystem() { + String homeDir = System.getProperty("user.dir"); + VirtualFileSystemFactory vfs = new VirtualFileSystemFactory(homeDir); + + FileSystemView view = vfs.createFileSystemView(new TestSession()); + + SshFile file = view.getFile("foo"); + String physicalName = ((NativeSshFile) file).getNativeFile().getAbsolutePath(); + assertEquals(homeDir + "/foo", physicalName); + + file = view.getFile(view.getFile("foo"), "../bar"); + physicalName = ((NativeSshFile) file).getNativeFile().getAbsolutePath(); + assertEquals(homeDir + "/bar", physicalName); + + file = view.getFile("../bar"); + physicalName = ((NativeSshFile) file).getNativeFile().getAbsolutePath(); + assertEquals(homeDir + "/bar", physicalName); + } + + static class TestSession extends AbstractSession { + TestSession() { + super(SshServer.setUpDefaultServer(), null); + this.username = "userName"; + } + @Override + protected void handleMessage(Buffer buffer) throws Exception { + } + @Override + protected boolean readIdentification(Buffer buffer) throws IOException { + return false; + } + } + + static class TestFactoryManager extends AbstractFactoryManager { + + } +}
