This is an automated email from the ASF dual-hosted git repository.
ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-vfs.git
The following commit(s) were added to refs/heads/master by this push:
new b1030e6 VFS-590 VFS-617 Proceed with moveTo operation if the exec
channel for… (#75)
b1030e6 is described below
commit b1030e61013b55cacff82a2354b1c9b3456fd2a7
Author: Alex Pearce <[email protected]>
AuthorDate: Mon Dec 23 18:06:27 2019 +0000
VFS-590 VFS-617 Proceed with moveTo operation if the exec channel for… (#75)
* VFS-590 VFS-617 Proceed with moveTo operation if the exec channel for
permission checks is closed
* VFS-590 VFS-617 Apache license headers
* VFS-590 VFS-617 Fix merge conflict
* VFS-590 VFS-617 Test read, write, delete and rename on sftp closed exec
channel
* VFS-590 VFS-617 Clean execdisabled initialization
Co-authored-by: sauerbraten <[email protected]>
---
.../commons/vfs2/provider/sftp/SftpFileObject.java | 7 +
.../commons/vfs2/provider/sftp/SftpFileSystem.java | 33 ++
.../provider/sftp/UserIsOwnerPosixPermissions.java | 29 +
.../test/java/org/apache/commons/vfs2/RunTest.java | 2 +-
...Case.java => AbstractSftpProviderTestCase.java} | 199 ++-----
.../SftpProviderClosedExecChannelTestCase.java | 47 ++
.../test/SftpProviderStreamProxyModeTestCase.java | 104 ++++
.../provider/sftp/test/SftpProviderTestCase.java | 650 +--------------------
8 files changed, 292 insertions(+), 779 deletions(-)
diff --git
a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileObject.java
b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileObject.java
index 27645b7..5c24502 100644
---
a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileObject.java
+++
b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileObject.java
@@ -228,6 +228,13 @@ public class SftpFileObject extends
AbstractFileObject<SftpFileSystem> {
statSelf();
boolean isInGroup = false;
if (checkIds) {
+ if(getAbstractFileSystem().isExecDisabled()) {
+ // Exec is disabled, so we won't be able to ascertain the
current user's UID and GID.
+ // Return "always-true" permissions as a workaround, knowing
that the SFTP server won't
+ // let us perform unauthorized actions anyway.
+ return new UserIsOwnerPosixPermissions(attrs.getPermissions());
+ }
+
for (final int groupId : getAbstractFileSystem().getGroupsIds()) {
if (groupId == attrs.getGId()) {
isInGroup = true;
diff --git
a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileSystem.java
b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileSystem.java
index e8c204f..a33f510 100644
---
a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileSystem.java
+++
b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileSystem.java
@@ -21,6 +21,8 @@ import java.io.InputStreamReader;
import java.util.Collection;
import java.util.Objects;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.commons.vfs2.Capability;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
@@ -40,6 +42,8 @@ import com.jcraft.jsch.SftpException;
*/
public class SftpFileSystem extends AbstractFileSystem {
+ private static final Log LOG = LogFactory.getLog(SftpFileSystem.class);
+
private static final int UNIDENTIFED = -1;
private static final int SLEEP_MILLIS = 100;
@@ -76,12 +80,18 @@ public class SftpFileSystem extends AbstractFileSystem {
*/
private volatile int[] groupsIds;
+ /**
+ * Some SFTP-only servers disable the exec channel. When exec is disabled,
things like getUId() will always fail.
+ */
+ private final boolean execDisabled;
+
protected SftpFileSystem(final GenericFileName rootName, final Session
session,
final FileSystemOptions fileSystemOptions) {
super(rootName, null, fileSystemOptions);
this.session = Objects.requireNonNull(session, "session");
this.connectTimeoutMillis = SftpFileSystemConfigBuilder.getInstance()
.getConnectTimeoutMillis(fileSystemOptions);
+ this.execDisabled = detectExecDisabled();
}
@Override
@@ -315,4 +325,27 @@ public class SftpFileSystem extends AbstractFileSystem {
}
return channel.getExitStatus();
}
+
+ /**
+ * @see SftpFileSystem#execDisabled
+ */
+ public boolean isExecDisabled() {
+ return execDisabled;
+ }
+
+ /**
+ * Some SFTP-only servers disable the exec channel.
+ *
+ * Attempt to detect this by calling getUid.
+ */
+ private boolean detectExecDisabled() {
+ try {
+ getUId();
+ return false;
+ } catch(JSchException | IOException e) {
+ LOG.debug("Cannot get UID, assuming no exec channel is present",
e);
+ return true;
+ }
+ }
+
}
diff --git
a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/UserIsOwnerPosixPermissions.java
b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/UserIsOwnerPosixPermissions.java
new file mode 100644
index 0000000..c986e20
--- /dev/null
+++
b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/UserIsOwnerPosixPermissions.java
@@ -0,0 +1,29 @@
+/*
+ * 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.commons.vfs2.provider.sftp;
+
+import org.apache.commons.vfs2.util.PosixPermissions;
+
+/**
+ * Pretends that the current user is always the owner and in the same group.
+ */
+public class UserIsOwnerPosixPermissions extends PosixPermissions {
+
+ public UserIsOwnerPosixPermissions(final int permissions) {
+ super(permissions, true, true);
+ }
+}
\ No newline at end of file
diff --git a/commons-vfs2/src/test/java/org/apache/commons/vfs2/RunTest.java
b/commons-vfs2/src/test/java/org/apache/commons/vfs2/RunTest.java
index a1c794d..740de96 100644
--- a/commons-vfs2/src/test/java/org/apache/commons/vfs2/RunTest.java
+++ b/commons-vfs2/src/test/java/org/apache/commons/vfs2/RunTest.java
@@ -49,7 +49,7 @@ public class RunTest {
// UrlProviderTestCase.suite(),
// ResourceProviderTestCase.suite(),
// HttpProviderTestCase.suite(),
- // SftpProviderTestCase.suite(),
+ // AbstractSftpProviderTestCase.suite(),
// JarProviderTestCase.suite(),
// NestedJarTestCase.suite(),
// ZipProviderTestCase.suite(),
diff --git
a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderTestCase.java
b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/sftp/test/AbstractSftpProviderTestCase.java
similarity index 78%
copy from
commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderTestCase.java
copy to
commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/sftp/test/AbstractSftpProviderTestCase.java
index 35aec44..51a30af 100644
---
a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderTestCase.java
+++
b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/sftp/test/AbstractSftpProviderTestCase.java
@@ -24,7 +24,6 @@ import java.io.OutputStream;
import java.io.PrintStream;
import java.net.InetSocketAddress;
import java.net.Socket;
-import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;
@@ -39,12 +38,8 @@ import org.apache.commons.vfs2.impl.DefaultFileSystemManager;
import org.apache.commons.vfs2.provider.sftp.SftpFileProvider;
import org.apache.commons.vfs2.provider.sftp.SftpFileSystem;
import org.apache.commons.vfs2.provider.sftp.SftpFileSystemConfigBuilder;
-import org.apache.commons.vfs2.provider.sftp.SftpStreamProxy;
import org.apache.commons.vfs2.provider.sftp.TrustEveryoneUserInfo;
import org.apache.commons.vfs2.test.AbstractProviderTestConfig;
-import org.apache.commons.vfs2.test.PermissionsTests;
-import org.apache.commons.vfs2.test.ProviderReadTests;
-import org.apache.commons.vfs2.test.ProviderTestConfig;
import org.apache.commons.vfs2.test.ProviderTestSuite;
import org.apache.commons.vfs2.util.FreeSocketPortUtil;
import org.apache.ftpserver.ftplet.FtpException;
@@ -73,22 +68,18 @@ import org.apache.sshd.server.sftp.SftpSubsystem;
import com.jcraft.jsch.SftpATTRS;
import com.jcraft.jsch.TestIdentityRepositoryFactory;
-import junit.extensions.TestSetup;
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
/**
* Tests cases for the SFTP provider.
* <p>
* Starts and stops an embedded Apache SSHd (MINA) server.
* </p>
*/
-public class SftpProviderTestCase extends AbstractProviderTestConfig {
+abstract class AbstractSftpProviderTestCase extends AbstractProviderTestConfig
{
/**
* The underlying file system
*/
- private SftpFileSystem fileSystem;
+ protected SftpFileSystem fileSystem;
/**
* Implements FileSystemFactory because SSHd does not know about users and
home directories.
@@ -165,16 +156,16 @@ public class SftpProviderTestCase extends
AbstractProviderTestConfig {
// private static final String DEFAULT_PWD = "testtest";
- private static String ConnectionUri;
+ protected static String ConnectionUri;
private static SshServer Server;
private static final String TEST_URI = "test.sftp.uri";
- /** True if we are testing the SFTP stream proxy */
- private final boolean streamProxyMode;
-
- private static String getSystemTestUriOverride() {
+ /**
+ * True if we are testing the SFTP stream proxy
+ */
+ protected static String getSystemTestUriOverride() {
return System.getProperty(TEST_URI);
}
@@ -184,14 +175,13 @@ public class SftpProviderTestCase extends
AbstractProviderTestConfig {
* @throws FtpException
* @throws IOException
*/
- private static void setUpClass() throws FtpException, IOException {
- SocketPort = FreeSocketPortUtil.findFreeLocalPort();
- // Use %40 for @ in a URL
- ConnectionUri = String.format("sftp://%s@localhost:%d", DEFAULT_USER,
SocketPort);
-
+ private static void setUpClass(final boolean isExecChannelClosed) throws
IOException {
if (Server != null) {
return;
}
+ SocketPort = FreeSocketPortUtil.findFreeLocalPort();
+ // Use %40 for @ in a URL
+ ConnectionUri = String.format("sftp://%s@localhost:%d", DEFAULT_USER,
SocketPort);
// System.setProperty("vfs.sftp.sshdir", getTestDirectory() +
"/../vfs.sftp.sshdir");
final String tmpDir = System.getProperty("java.io.tmpdir");
Server = SshServer.setUpDefaultServer();
@@ -246,7 +236,7 @@ public class SftpProviderTestCase extends
AbstractProviderTestConfig {
}
});
// Allows the execution of commands
- Server.setCommandFactory(new ScpCommandFactory(new
TestCommandFactory()));
+ Server.setCommandFactory(new ScpCommandFactory(new
TestCommandFactory(isExecChannelClosed)));
// HACK Start
// How do we really do simple user to directory matching?
Server.setFileSystemFactory(new TestFileSystemFactory());
@@ -259,10 +249,20 @@ public class SftpProviderTestCase extends
AbstractProviderTestConfig {
// HACK End
}
- static private class BaseProviderTestSuite extends ProviderTestSuite {
+ static class SftpProviderTestSuite extends ProviderTestSuite {
+ private final boolean isExecChannelClosed;
- public BaseProviderTestSuite(final ProviderTestConfig providerConfig)
throws Exception {
+ public SftpProviderTestSuite(final AbstractSftpProviderTestCase
providerConfig) throws Exception {
super(providerConfig);
+ this.isExecChannelClosed = providerConfig.isExecChannelClosed();
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ if (getSystemTestUriOverride() == null) {
+ setUpClass(isExecChannelClosed);
+ }
+ super.setUp();
}
@Override
@@ -273,61 +273,13 @@ public class SftpProviderTestCase extends
AbstractProviderTestConfig {
for (final AbstractSession session : Server.getActiveSessions()) {
session.close(true);
}
+ tearDownClass();
super.tearDown();
}
}
- /**
- * Creates the test suite for the ftp file system.
- */
- public static Test suite() throws Exception {
- // The test suite to be returned
- final TestSuite suite = new TestSuite();
-
- // --- Standard VFS test suite
- final SftpProviderTestCase standardTestCase = new
SftpProviderTestCase(false);
- final ProviderTestSuite sftpSuite = new
BaseProviderTestSuite(standardTestCase);
-
- // VFS-405: set/get permissions
- sftpSuite.addTests(PermissionsTests.class);
-
- suite.addTest(sftpSuite);
-
- // --- VFS-440: stream proxy test suite
- // We override the addBaseTests method so that only
- // one test is run (we just test that the input/output are correctly
forwarded, and
- // hence if the reading test succeeds/fails the other will also
succeed/fail)
- final SftpProviderTestCase streamProxyTestCase = new
SftpProviderTestCase(true);
- final ProviderTestSuite sftpStreamSuite = new
BaseProviderTestSuite(streamProxyTestCase) {
- @Override
- protected void addBaseTests() throws Exception {
- // Just tries to read
- addTests(ProviderReadTests.class);
- }
- };
- suite.addTest(sftpStreamSuite);
-
- // Decorate the test suite to set up the Sftp server
- final TestSetup setup = new TestSetup(suite) {
- @Override
- protected void setUp() throws Exception {
- if (getSystemTestUriOverride() == null) {
- setUpClass();
- }
- super.setUp();
- }
-
- @Override
- protected void tearDown() throws Exception {
- // Close SFTP server if needed
- tearDownClass();
- super.tearDown();
- }
- };
-
- return setup;
- }
+ protected abstract boolean isExecChannelClosed();
/**
* Stops the embedded Apache SSHd Server (MINA).
@@ -337,13 +289,10 @@ public class SftpProviderTestCase extends
AbstractProviderTestConfig {
private static void tearDownClass() throws InterruptedException {
if (Server != null) {
Server.stop();
+ Server = null;
}
}
- public SftpProviderTestCase(final boolean streamProxyMode) {
- this.streamProxyMode = streamProxyMode;
- }
-
/**
* Returns the base folder for tests.
*/
@@ -359,37 +308,6 @@ public class SftpProviderTestCase extends
AbstractProviderTestConfig {
builder.setStrictHostKeyChecking(fileSystemOptions, "no");
builder.setUserInfo(fileSystemOptions, new TrustEveryoneUserInfo());
builder.setIdentityRepositoryFactory(fileSystemOptions, new
TestIdentityRepositoryFactory());
-
- if (streamProxyMode) {
- final FileSystemOptions proxyOptions = (FileSystemOptions)
fileSystemOptions.clone();
-
- final URI parsedURI = new URI(uri);
- final String userInfo = parsedURI.getUserInfo();
- final String[] userFields = userInfo == null ? null :
userInfo.split(":", 2);
-
- builder.setProxyType(fileSystemOptions,
SftpFileSystemConfigBuilder.PROXY_STREAM);
- if (userFields != null) {
- if (userFields.length > 0) {
- builder.setProxyUser(fileSystemOptions, userFields[0]);
- }
- if (userFields.length > 1) {
- builder.setProxyPassword(fileSystemOptions, userFields[1]);
- }
- }
- builder.setProxyHost(fileSystemOptions, parsedURI.getHost());
- builder.setProxyPort(fileSystemOptions, parsedURI.getPort());
- builder.setProxyCommand(fileSystemOptions,
SftpStreamProxy.NETCAT_COMMAND);
- builder.setProxyOptions(fileSystemOptions, proxyOptions);
- builder.setProxyPassword(fileSystemOptions,
parsedURI.getAuthority());
-
- // Set up the new URI
- if (userInfo == null) {
- uri = String.format("sftp://localhost:%d",
parsedURI.getPort());
- } else {
- uri = String.format("sftp://%s@localhost:%d", userInfo,
parsedURI.getPort());
- }
- }
-
final FileObject fileObject = manager.resolveFile(uri,
fileSystemOptions);
this.fileSystem = (SftpFileSystem) fileObject.getFileSystem();
return fileObject;
@@ -406,14 +324,19 @@ public class SftpProviderTestCase extends
AbstractProviderTestConfig {
/**
* The command factory for the SSH server: Handles these commands
* <p>
- * <li>{@code id -u} (permissions test)</li>
- * <li>{@code id -G} (permission tests)</li>
- * <li>{@code nc -q 0 localhost port} (Stream proxy tests)</li>
+ * <li><code>id -u</code> (permissions test)</li>
+ * <li><code>id -G</code> (permission tests)</li>
+ * <li><code>nc -q 0 localhost port</code> (Stream proxy tests)</li>
* </p>
*/
private static class TestCommandFactory extends ScpCommandFactory {
public static final Pattern NETCAT_COMMAND = Pattern.compile("nc -q 0
localhost (\\d+)");
+ private final boolean isExecChannelClosed;
+
+ public TestCommandFactory(final boolean isExecChannelClosed) {
+ this.isExecChannelClosed = isExecChannelClosed;
+ }
@Override
public Command createCommand(final String command) {
@@ -448,7 +371,11 @@ public class SftpProviderTestCase extends
AbstractProviderTestConfig {
public void start(final Environment env) throws IOException {
int code = 0;
if (command.equals("id -G") || command.equals("id -u")) {
- new PrintStream(out).println(0);
+ if (isExecChannelClosed) {
+ throw new IOException();
+ } else {
+ new PrintStream(out).println(0);
+ }
} else if (NETCAT_COMMAND.matcher(command).matches()) {
final Matcher matcher =
NETCAT_COMMAND.matcher(command);
matcher.matches();
@@ -499,7 +426,7 @@ public class SftpProviderTestCase extends
AbstractProviderTestConfig {
* broken. The integer argument is 0 if everything went
well.
*/
private static void connect(final String name, final InputStream in, final
OutputStream out,
- final ExitCallback callback) {
+ final ExitCallback callback) {
final Thread thread = new Thread((Runnable) () -> {
int code = 0;
try {
@@ -571,30 +498,30 @@ public class SftpProviderTestCase extends
AbstractProviderTestConfig {
final int id = buffer.getInt();
switch (type) {
- case SSH_FXP_SETSTAT:
- case SSH_FXP_FSETSTAT: {
- // Get the path
- final String path = buffer.getString();
- // Get the permission
- final SftpAttrs attrs = new SftpAttrs(buffer);
- permissions.put(path, attrs.permissions);
- // System.err.format("Setting [%s] permission to %o%n", path,
attrs.permissions);
- break;
- }
+ case SSH_FXP_SETSTAT:
+ case SSH_FXP_FSETSTAT: {
+ // Get the path
+ final String path = buffer.getString();
+ // Get the permission
+ final SftpAttrs attrs = new SftpAttrs(buffer);
+ permissions.put(path, attrs.permissions);
+ // System.err.format("Setting [%s] permission to %o%n",
path, attrs.permissions);
+ break;
+ }
- case SSH_FXP_REMOVE: {
- // Remove cached attributes
- final String path = buffer.getString();
- permissions.remove(path);
- // System.err.format("Removing [%s] permission cache%n", path);
- break;
- }
+ case SSH_FXP_REMOVE: {
+ // Remove cached attributes
+ final String path = buffer.getString();
+ permissions.remove(path);
+ // System.err.format("Removing [%s] permission cache%n",
path);
+ break;
+ }
- case SSH_FXP_INIT: {
- // Just grab the version here
- this._version = id;
- break;
- }
+ case SSH_FXP_INIT: {
+ // Just grab the version here
+ this._version = id;
+ break;
+ }
}
buffer.rpos(rpos);
diff --git
a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderClosedExecChannelTestCase.java
b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderClosedExecChannelTestCase.java
new file mode 100644
index 0000000..b6e21f3
--- /dev/null
+++
b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderClosedExecChannelTestCase.java
@@ -0,0 +1,47 @@
+/*
+ * 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.commons.vfs2.provider.sftp.test;
+
+import org.apache.commons.vfs2.test.*;
+
+import junit.framework.Test;
+
+public class SftpProviderClosedExecChannelTestCase extends
AbstractSftpProviderTestCase {
+ @Override
+ protected boolean isExecChannelClosed() {
+ return true;
+ }
+
+ /**
+ * Creates the test suite for the sftp file system.
+ */
+ public static Test suite() throws Exception {
+ final SftpProviderTestSuite suite = new SftpProviderTestSuite(new
SftpProviderClosedExecChannelTestCase()){
+ @Override
+ protected void addBaseTests() throws Exception {
+ addTests(ProviderReadTests.class);
+ addTests(ProviderWriteTests.class);
+ addTests(ProviderDeleteTests.class);
+ addTests(ProviderRenameTests.class);
+ addTests(NamingTests.class);
+ // VFS-405: set/get permissions
+ addTests(PermissionsTests.class);
+ }
+ };
+ return suite;
+ }
+}
diff --git
a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderStreamProxyModeTestCase.java
b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderStreamProxyModeTestCase.java
new file mode 100644
index 0000000..db525e5
--- /dev/null
+++
b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderStreamProxyModeTestCase.java
@@ -0,0 +1,104 @@
+/*
+ * 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.commons.vfs2.provider.sftp.test;
+
+import java.net.URI;
+
+import org.apache.commons.vfs2.FileObject;
+import org.apache.commons.vfs2.FileSystemManager;
+import org.apache.commons.vfs2.FileSystemOptions;
+import org.apache.commons.vfs2.provider.sftp.SftpFileSystem;
+import org.apache.commons.vfs2.provider.sftp.SftpFileSystemConfigBuilder;
+import org.apache.commons.vfs2.provider.sftp.SftpStreamProxy;
+import org.apache.commons.vfs2.provider.sftp.TrustEveryoneUserInfo;
+import org.apache.commons.vfs2.test.PermissionsTests;
+import org.apache.commons.vfs2.test.ProviderReadTests;
+
+import com.jcraft.jsch.TestIdentityRepositoryFactory;
+
+import junit.framework.Test;
+
+public class SftpProviderStreamProxyModeTestCase extends
AbstractSftpProviderTestCase {
+ @Override
+ protected boolean isExecChannelClosed() {
+ return false;
+ }
+
+ // --- VFS-440: stream proxy test suite
+ // We override the addBaseTests method so that only
+ // one test is run (we just test that the input/output are correctly
forwarded, and
+ // hence if the reading test succeeds/fails the other will also
succeed/fail)
+ public static Test suite() throws Exception {
+ final SftpProviderTestSuite suite = new SftpProviderTestSuite(new
SftpProviderStreamProxyModeTestCase()) {
+ @Override
+ protected void addBaseTests() throws Exception {
+ // Just tries to read
+ addTests(ProviderReadTests.class);
+ // VFS-405: set/get permissions
+ addTests(PermissionsTests.class);
+ }
+ };
+ return suite;
+ }
+
+ @Override
+ public FileObject getBaseTestFolder(final FileSystemManager manager)
throws Exception {
+ String uri = getSystemTestUriOverride();
+ if (uri == null) {
+ uri = ConnectionUri;
+ }
+
+ final FileSystemOptions fileSystemOptions = new FileSystemOptions();
+ final SftpFileSystemConfigBuilder builder =
SftpFileSystemConfigBuilder.getInstance();
+ builder.setStrictHostKeyChecking(fileSystemOptions, "no");
+ builder.setUserInfo(fileSystemOptions, new TrustEveryoneUserInfo());
+ builder.setIdentityRepositoryFactory(fileSystemOptions, new
TestIdentityRepositoryFactory());
+
+ final FileSystemOptions proxyOptions = (FileSystemOptions)
fileSystemOptions.clone();
+
+ final URI parsedURI = new URI(uri);
+ final String userInfo = parsedURI.getUserInfo();
+ final String[] userFields = userInfo == null ? null :
userInfo.split(":", 2);
+
+ builder.setProxyType(fileSystemOptions,
SftpFileSystemConfigBuilder.PROXY_STREAM);
+ if (userFields != null) {
+ if (userFields.length > 0) {
+ builder.setProxyUser(fileSystemOptions, userFields[0]);
+ }
+ if (userFields.length > 1) {
+ builder.setProxyPassword(fileSystemOptions, userFields[1]);
+ }
+ }
+ builder.setProxyHost(fileSystemOptions, parsedURI.getHost());
+ builder.setProxyPort(fileSystemOptions, parsedURI.getPort());
+ builder.setProxyCommand(fileSystemOptions,
SftpStreamProxy.NETCAT_COMMAND);
+ builder.setProxyOptions(fileSystemOptions, proxyOptions);
+ builder.setProxyPassword(fileSystemOptions, parsedURI.getAuthority());
+
+ // Set up the new URI
+ if (userInfo == null) {
+ uri = String.format("sftp://localhost:%d", parsedURI.getPort());
+ } else {
+ uri = String.format("sftp://%s@localhost:%d", userInfo,
parsedURI.getPort());
+ }
+
+
+ final FileObject fileObject = manager.resolveFile(uri,
fileSystemOptions);
+ this.fileSystem = (SftpFileSystem) fileObject.getFileSystem();
+ return fileObject;
+ }
+}
diff --git
a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderTestCase.java
b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderTestCase.java
index 35aec44..e837066 100644
---
a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderTestCase.java
+++
b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderTestCase.java
@@ -16,658 +16,24 @@
*/
package org.apache.commons.vfs2.provider.sftp.test;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.TreeMap;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.apache.commons.AbstractVfsTestCase;
-import org.apache.commons.vfs2.FileObject;
-import org.apache.commons.vfs2.FileSystemManager;
-import org.apache.commons.vfs2.FileSystemOptions;
-import org.apache.commons.vfs2.impl.DefaultFileSystemManager;
-import org.apache.commons.vfs2.provider.sftp.SftpFileProvider;
-import org.apache.commons.vfs2.provider.sftp.SftpFileSystem;
-import org.apache.commons.vfs2.provider.sftp.SftpFileSystemConfigBuilder;
-import org.apache.commons.vfs2.provider.sftp.SftpStreamProxy;
-import org.apache.commons.vfs2.provider.sftp.TrustEveryoneUserInfo;
-import org.apache.commons.vfs2.test.AbstractProviderTestConfig;
import org.apache.commons.vfs2.test.PermissionsTests;
-import org.apache.commons.vfs2.test.ProviderReadTests;
-import org.apache.commons.vfs2.test.ProviderTestConfig;
-import org.apache.commons.vfs2.test.ProviderTestSuite;
-import org.apache.commons.vfs2.util.FreeSocketPortUtil;
-import org.apache.ftpserver.ftplet.FtpException;
-import org.apache.sshd.SshServer;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.Session;
-import org.apache.sshd.common.SshException;
-import org.apache.sshd.common.session.AbstractSession;
-import org.apache.sshd.common.util.Buffer;
-import org.apache.sshd.common.util.SecurityUtils;
-import org.apache.sshd.server.Command;
-import org.apache.sshd.server.Environment;
-import org.apache.sshd.server.ExitCallback;
-import org.apache.sshd.server.FileSystemFactory;
-import org.apache.sshd.server.FileSystemView;
-import org.apache.sshd.server.ForwardingFilter;
-import org.apache.sshd.server.SshFile;
-import org.apache.sshd.server.auth.UserAuthNone;
-import org.apache.sshd.server.command.ScpCommandFactory;
-import org.apache.sshd.server.filesystem.NativeSshFile;
-import org.apache.sshd.server.keyprovider.PEMGeneratorHostKeyProvider;
-import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
-import org.apache.sshd.server.session.ServerSession;
-import org.apache.sshd.server.sftp.SftpSubsystem;
-
-import com.jcraft.jsch.SftpATTRS;
-import com.jcraft.jsch.TestIdentityRepositoryFactory;
-import junit.extensions.TestSetup;
import junit.framework.Test;
-import junit.framework.TestSuite;
-
-/**
- * Tests cases for the SFTP provider.
- * <p>
- * Starts and stops an embedded Apache SSHd (MINA) server.
- * </p>
- */
-public class SftpProviderTestCase extends AbstractProviderTestConfig {
-
- /**
- * The underlying file system
- */
- private SftpFileSystem fileSystem;
-
- /**
- * Implements FileSystemFactory because SSHd does not know about users and
home directories.
- */
- static final class TestFileSystemFactory implements FileSystemFactory {
- /**
- * Accepts only the known test user.
- */
- @Override
- public FileSystemView createFileSystemView(final Session session)
throws IOException {
- final String userName = session.getUsername();
- if (!DEFAULT_USER.equals(userName)) {
- return null;
- }
- return new
TestFileSystemView(AbstractVfsTestCase.getTestDirectory(), userName);
- }
- }
-
- /**
- * Implements FileSystemView because SSHd does not know about users and
home directories.
- */
- static final class TestFileSystemView implements FileSystemView {
- private final String homeDirStr;
-
- private final String userName;
-
- // private boolean caseInsensitive;
-
- public TestFileSystemView(final String homeDirStr, final String
userName) {
- this.homeDirStr = new File(homeDirStr).getAbsolutePath();
- this.userName = userName;
- }
-
- @Override
- public SshFile getFile(final SshFile baseDir, final String file) {
- return this.getFile(baseDir.getAbsolutePath(), file);
- }
-
- @Override
- public SshFile getFile(final String file) {
- return this.getFile(homeDirStr, file);
- }
-
- protected SshFile getFile(final String dir, final String file) {
- final String home =
removePrefix(NativeSshFile.normalizeSeparateChar(homeDirStr));
- String userFileName =
removePrefix(NativeSshFile.normalizeSeparateChar(file));
- final File sshFile = userFileName.startsWith(home) ? new
File(userFileName) : new File(home, userFileName);
- userFileName =
removePrefix(NativeSshFile.normalizeSeparateChar(sshFile.getAbsolutePath()));
- return new TestNativeSshFile(userFileName, sshFile, userName);
- }
-
- private String removePrefix(final String s) {
- final int index = s.indexOf('/');
- if (index < 1) {
- return s;
- }
- return s.substring(index);
- }
- }
-
- /**
- * Extends NativeSshFile because its constructor is protected and I do not
want to create a whole NativeSshFile
- * implementation for testing.
- */
- static class TestNativeSshFile extends NativeSshFile {
- TestNativeSshFile(final String fileName, final File file, final String
userName) {
- super(fileName, file, userName);
- }
- }
-
- private static int SocketPort;
-
- private static final String DEFAULT_USER = "testtest";
-
- // private static final String DEFAULT_PWD = "testtest";
-
- private static String ConnectionUri;
- private static SshServer Server;
-
- private static final String TEST_URI = "test.sftp.uri";
-
- /** True if we are testing the SFTP stream proxy */
- private final boolean streamProxyMode;
-
- private static String getSystemTestUriOverride() {
- return System.getProperty(TEST_URI);
- }
-
- /**
- * Creates and starts an embedded Apache SSHd Server (MINA).
- *
- * @throws FtpException
- * @throws IOException
- */
- private static void setUpClass() throws FtpException, IOException {
- SocketPort = FreeSocketPortUtil.findFreeLocalPort();
- // Use %40 for @ in a URL
- ConnectionUri = String.format("sftp://%s@localhost:%d", DEFAULT_USER,
SocketPort);
-
- if (Server != null) {
- return;
- }
- // System.setProperty("vfs.sftp.sshdir", getTestDirectory() +
"/../vfs.sftp.sshdir");
- final String tmpDir = System.getProperty("java.io.tmpdir");
- Server = SshServer.setUpDefaultServer();
- Server.setPort(SocketPort);
- if (SecurityUtils.isBouncyCastleRegistered()) {
- // A temporary file will hold the key
- final File keyFile = File.createTempFile("key", ".pem", new
File(tmpDir));
- keyFile.deleteOnExit();
- // It has to be deleted in order to be generated
- keyFile.delete();
-
- final PEMGeneratorHostKeyProvider keyProvider = new
PEMGeneratorHostKeyProvider(keyFile.getAbsolutePath());
- Server.setKeyPairProvider(keyProvider);
- } else {
- Server.setKeyPairProvider(new
SimpleGeneratorHostKeyProvider(tmpDir + "/key.ser"));
- }
- final List<NamedFactory<Command>> list = new ArrayList<>(1);
- list.add(new NamedFactory<Command>() {
-
- @Override
- public String getName() {
- return "sftp";
- }
-
- @Override
- public Command create() {
- return new MySftpSubsystem();
- }
- });
- Server.setSubsystemFactories(list);
- Server.setPasswordAuthenticator((username, password, session) ->
username != null && username.equals(password));
- Server.setPublickeyAuthenticator((username, key, session) -> true);
- Server.setForwardingFilter(new ForwardingFilter() {
- @Override
- public boolean canConnect(final InetSocketAddress address, final
ServerSession session) {
- return true;
- }
-
- @Override
- public boolean canForwardAgent(final ServerSession session) {
- return true;
- }
-
- @Override
- public boolean canForwardX11(final ServerSession session) {
- return true;
- }
-
- @Override
- public boolean canListen(final InetSocketAddress address, final
ServerSession session) {
- return true;
- }
- });
- // Allows the execution of commands
- Server.setCommandFactory(new ScpCommandFactory(new
TestCommandFactory()));
- // HACK Start
- // How do we really do simple user to directory matching?
- Server.setFileSystemFactory(new TestFileSystemFactory());
- // HACK End
- Server.start();
- // HACK Start
- // How do we really do simple security?
- // Do this after we start the server to simplify this set up code.
- Server.getUserAuthFactories().add(new UserAuthNone.Factory());
- // HACK End
- }
-
- static private class BaseProviderTestSuite extends ProviderTestSuite {
-
- public BaseProviderTestSuite(final ProviderTestConfig providerConfig)
throws Exception {
- super(providerConfig);
- }
-
- @Override
- protected void tearDown() throws Exception {
- // Close all active sessions
- // Note that it should be done by super.tearDown()
- // while closing
- for (final AbstractSession session : Server.getActiveSessions()) {
- session.close(true);
- }
- super.tearDown();
- }
+public class SftpProviderTestCase extends AbstractSftpProviderTestCase {
+ @Override
+ protected boolean isExecChannelClosed() {
+ return false;
}
/**
- * Creates the test suite for the ftp file system.
+ * Creates the test suite for the sftp file system.
*/
public static Test suite() throws Exception {
- // The test suite to be returned
- final TestSuite suite = new TestSuite();
-
- // --- Standard VFS test suite
- final SftpProviderTestCase standardTestCase = new
SftpProviderTestCase(false);
- final ProviderTestSuite sftpSuite = new
BaseProviderTestSuite(standardTestCase);
-
+ final SftpProviderTestSuite suite = new SftpProviderTestSuite(new
SftpProviderTestCase());
// VFS-405: set/get permissions
- sftpSuite.addTests(PermissionsTests.class);
-
- suite.addTest(sftpSuite);
-
- // --- VFS-440: stream proxy test suite
- // We override the addBaseTests method so that only
- // one test is run (we just test that the input/output are correctly
forwarded, and
- // hence if the reading test succeeds/fails the other will also
succeed/fail)
- final SftpProviderTestCase streamProxyTestCase = new
SftpProviderTestCase(true);
- final ProviderTestSuite sftpStreamSuite = new
BaseProviderTestSuite(streamProxyTestCase) {
- @Override
- protected void addBaseTests() throws Exception {
- // Just tries to read
- addTests(ProviderReadTests.class);
- }
- };
- suite.addTest(sftpStreamSuite);
-
- // Decorate the test suite to set up the Sftp server
- final TestSetup setup = new TestSetup(suite) {
- @Override
- protected void setUp() throws Exception {
- if (getSystemTestUriOverride() == null) {
- setUpClass();
- }
- super.setUp();
- }
-
- @Override
- protected void tearDown() throws Exception {
- // Close SFTP server if needed
- tearDownClass();
- super.tearDown();
- }
- };
-
- return setup;
- }
-
- /**
- * Stops the embedded Apache SSHd Server (MINA).
- *
- * @throws InterruptedException
- */
- private static void tearDownClass() throws InterruptedException {
- if (Server != null) {
- Server.stop();
- }
- }
-
- public SftpProviderTestCase(final boolean streamProxyMode) {
- this.streamProxyMode = streamProxyMode;
- }
-
- /**
- * Returns the base folder for tests.
- */
- @Override
- public FileObject getBaseTestFolder(final FileSystemManager manager)
throws Exception {
- String uri = getSystemTestUriOverride();
- if (uri == null) {
- uri = ConnectionUri;
- }
-
- final FileSystemOptions fileSystemOptions = new FileSystemOptions();
- final SftpFileSystemConfigBuilder builder =
SftpFileSystemConfigBuilder.getInstance();
- builder.setStrictHostKeyChecking(fileSystemOptions, "no");
- builder.setUserInfo(fileSystemOptions, new TrustEveryoneUserInfo());
- builder.setIdentityRepositoryFactory(fileSystemOptions, new
TestIdentityRepositoryFactory());
-
- if (streamProxyMode) {
- final FileSystemOptions proxyOptions = (FileSystemOptions)
fileSystemOptions.clone();
-
- final URI parsedURI = new URI(uri);
- final String userInfo = parsedURI.getUserInfo();
- final String[] userFields = userInfo == null ? null :
userInfo.split(":", 2);
-
- builder.setProxyType(fileSystemOptions,
SftpFileSystemConfigBuilder.PROXY_STREAM);
- if (userFields != null) {
- if (userFields.length > 0) {
- builder.setProxyUser(fileSystemOptions, userFields[0]);
- }
- if (userFields.length > 1) {
- builder.setProxyPassword(fileSystemOptions, userFields[1]);
- }
- }
- builder.setProxyHost(fileSystemOptions, parsedURI.getHost());
- builder.setProxyPort(fileSystemOptions, parsedURI.getPort());
- builder.setProxyCommand(fileSystemOptions,
SftpStreamProxy.NETCAT_COMMAND);
- builder.setProxyOptions(fileSystemOptions, proxyOptions);
- builder.setProxyPassword(fileSystemOptions,
parsedURI.getAuthority());
-
- // Set up the new URI
- if (userInfo == null) {
- uri = String.format("sftp://localhost:%d",
parsedURI.getPort());
- } else {
- uri = String.format("sftp://%s@localhost:%d", userInfo,
parsedURI.getPort());
- }
- }
-
- final FileObject fileObject = manager.resolveFile(uri,
fileSystemOptions);
- this.fileSystem = (SftpFileSystem) fileObject.getFileSystem();
- return fileObject;
- }
-
- /**
- * Prepares the file system manager.
- */
- @Override
- public void prepare(final DefaultFileSystemManager manager) throws
Exception {
- manager.addProvider("sftp", new SftpFileProvider());
- }
-
- /**
- * The command factory for the SSH server: Handles these commands
- * <p>
- * <li>{@code id -u} (permissions test)</li>
- * <li>{@code id -G} (permission tests)</li>
- * <li>{@code nc -q 0 localhost port} (Stream proxy tests)</li>
- * </p>
- */
- private static class TestCommandFactory extends ScpCommandFactory {
-
- public static final Pattern NETCAT_COMMAND = Pattern.compile("nc -q 0
localhost (\\d+)");
-
- @Override
- public Command createCommand(final String command) {
- return new Command() {
- public ExitCallback callback = null;
- public OutputStream out = null;
- public OutputStream err = null;
- public InputStream in = null;
-
- @Override
- public void setInputStream(final InputStream in) {
- this.in = in;
- }
-
- @Override
- public void setOutputStream(final OutputStream out) {
- this.out = out;
- }
-
- @Override
- public void setErrorStream(final OutputStream err) {
- this.err = err;
- }
-
- @Override
- public void setExitCallback(final ExitCallback callback) {
- this.callback = callback;
-
- }
-
- @Override
- public void start(final Environment env) throws IOException {
- int code = 0;
- if (command.equals("id -G") || command.equals("id -u")) {
- new PrintStream(out).println(0);
- } else if (NETCAT_COMMAND.matcher(command).matches()) {
- final Matcher matcher =
NETCAT_COMMAND.matcher(command);
- matcher.matches();
- final int port = Integer.parseInt(matcher.group(1));
-
- final Socket socket = new Socket((String) null, port);
-
- if (out != null) {
- connect("from nc", socket.getInputStream(), out,
null);
- }
-
- if (in != null) {
- connect("to nc", in, socket.getOutputStream(),
callback);
- }
-
- return;
-
- } else {
- if (err != null) {
- new PrintStream(err).format("Unknown command
%s%n", command);
- }
- code = -1;
- }
-
- if (out != null) {
- out.flush();
- }
- if (err != null) {
- err.flush();
- }
- callback.onExit(code);
- }
-
- @Override
- public void destroy() {
- }
- };
- }
- }
-
- /**
- * Creates a pipe thread that connects an input to an output
- *
- * @param name The name of the thread (for debugging purposes)
- * @param in The input stream
- * @param out The output stream
- * @param callback An object whose method {@linkplain
ExitCallback#onExit(int)} will be called when the pipe is
- * broken. The integer argument is 0 if everything went
well.
- */
- private static void connect(final String name, final InputStream in, final
OutputStream out,
- final ExitCallback callback) {
- final Thread thread = new Thread((Runnable) () -> {
- int code = 0;
- try {
- final byte buffer[] = new byte[1024];
- int len;
- while ((len = in.read(buffer, 0, buffer.length)) != -1) {
- out.write(buffer, 0, len);
- out.flush();
- }
- } catch (final SshException ex1) {
- // Nothing to do, this occurs when the connection
- // is closed on the remote side
- } catch (final IOException ex2) {
- if (!ex2.getMessage().equals("Pipe closed")) {
- code = -1;
- }
- }
- if (callback != null) {
- callback.onExit(code);
- }
- }, name);
- thread.setDaemon(true);
- thread.start();
- }
-
- private static class SftpAttrs {
- int flags = 0;
- private int uid;
- long size = 0;
- private int gid;
- private int atime;
- private int permissions;
- private int mtime;
- private String[] extended;
-
- private SftpAttrs(final Buffer buf) {
- int flags = 0;
- flags = buf.getInt();
-
- if ((flags & SftpATTRS.SSH_FILEXFER_ATTR_SIZE) != 0) {
- size = buf.getLong();
- }
- if ((flags & SftpATTRS.SSH_FILEXFER_ATTR_UIDGID) != 0) {
- uid = buf.getInt();
- gid = buf.getInt();
- }
- if ((flags & SftpATTRS.SSH_FILEXFER_ATTR_PERMISSIONS) != 0) {
- permissions = buf.getInt();
- }
- if ((flags & SftpATTRS.SSH_FILEXFER_ATTR_ACMODTIME) != 0) {
- atime = buf.getInt();
- }
- if ((flags & SftpATTRS.SSH_FILEXFER_ATTR_ACMODTIME) != 0) {
- mtime = buf.getInt();
- }
-
- }
- }
-
- private static class MySftpSubsystem extends SftpSubsystem {
- TreeMap<String, Integer> permissions = new TreeMap<>();
- private int _version;
-
- @Override
- protected void process(final Buffer buffer) throws IOException {
- final int rpos = buffer.rpos();
- final int length = buffer.getInt();
- final int type = buffer.getByte();
- final int id = buffer.getInt();
-
- switch (type) {
- case SSH_FXP_SETSTAT:
- case SSH_FXP_FSETSTAT: {
- // Get the path
- final String path = buffer.getString();
- // Get the permission
- final SftpAttrs attrs = new SftpAttrs(buffer);
- permissions.put(path, attrs.permissions);
- // System.err.format("Setting [%s] permission to %o%n", path,
attrs.permissions);
- break;
- }
-
- case SSH_FXP_REMOVE: {
- // Remove cached attributes
- final String path = buffer.getString();
- permissions.remove(path);
- // System.err.format("Removing [%s] permission cache%n", path);
- break;
- }
-
- case SSH_FXP_INIT: {
- // Just grab the version here
- this._version = id;
- break;
- }
- }
-
- buffer.rpos(rpos);
- super.process(buffer);
-
- }
-
- @Override
- protected void writeAttrs(final Buffer buffer, final SshFile file,
final int flags) throws IOException {
- if (!file.doesExist()) {
- throw new FileNotFoundException(file.getAbsolutePath());
- }
-
- int p = 0;
-
- final Integer cached = permissions.get(file.getAbsolutePath());
- if (cached != null) {
- // Use cached permissions
- // System.err.format("Using cached [%s] permission of %o%n",
file.getAbsolutePath(), cached);
- p |= cached;
- } else {
- // Use permissions from Java file
- if (file.isReadable()) {
- p |= S_IRUSR;
- }
- if (file.isWritable()) {
- p |= S_IWUSR;
- }
- if (file.isExecutable()) {
- p |= S_IXUSR;
- }
- }
-
- if (_version >= 4) {
- final long size = file.getSize();
- // String username = session.getUsername();
- final long lastModif = file.getLastModified();
- if (file.isFile()) {
- buffer.putInt(SSH_FILEXFER_ATTR_PERMISSIONS);
- buffer.putByte((byte) SSH_FILEXFER_TYPE_REGULAR);
- buffer.putInt(p);
- } else if (file.isDirectory()) {
- buffer.putInt(SSH_FILEXFER_ATTR_PERMISSIONS);
- buffer.putByte((byte) SSH_FILEXFER_TYPE_DIRECTORY);
- buffer.putInt(p);
- } else {
- buffer.putInt(0);
- buffer.putByte((byte) SSH_FILEXFER_TYPE_UNKNOWN);
- }
- } else {
- if (file.isFile()) {
- p |= 0100000;
- }
- if (file.isDirectory()) {
- p |= 0040000;
- }
-
- if (file.isFile()) {
- buffer.putInt(SSH_FILEXFER_ATTR_SIZE |
SSH_FILEXFER_ATTR_PERMISSIONS | SSH_FILEXFER_ATTR_ACMODTIME);
- buffer.putLong(file.getSize());
- buffer.putInt(p);
- buffer.putInt(file.getLastModified() / 1000);
- buffer.putInt(file.getLastModified() / 1000);
- } else if (file.isDirectory()) {
- buffer.putInt(SSH_FILEXFER_ATTR_PERMISSIONS |
SSH_FILEXFER_ATTR_ACMODTIME);
- buffer.putInt(p);
- buffer.putInt(file.getLastModified() / 1000);
- buffer.putInt(file.getLastModified() / 1000);
- } else {
- buffer.putInt(0);
- }
- }
- }
-
+ suite.addTests(PermissionsTests.class);
+ return suite;
}
}