You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by lg...@apache.org on 2015/07/09 08:53:51 UTC
mina-sshd git commit: [SSHD-523] Add support for 'copy-data' SFTP
extension
Repository: mina-sshd
Updated Branches:
refs/heads/master 5cd057a72 -> 515427faa
[SSHD-523] Add support for 'copy-data' SFTP extension
Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/515427fa
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/515427fa
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/515427fa
Branch: refs/heads/master
Commit: 515427faa988ebe6d6c221b0e7ce3b1369544da5
Parents: 5cd057a
Author: Lyor Goldstein <lg...@vmware.com>
Authored: Thu Jul 9 09:53:40 2015 +0300
Committer: Lyor Goldstein <lg...@vmware.com>
Committed: Thu Jul 9 09:53:40 2015 +0300
----------------------------------------------------------------------
.../agent/local/ChannelAgentForwarding.java | 5 -
.../sshd/client/auth/UserAuthPassword.java | 2 +-
.../sshd/client/auth/UserAuthPublicKey.java | 6 +-
.../channel/PtyCapableChannelSession.java | 8 +-
.../subsystem/sftp/AbstractSftpClient.java | 1 -
.../sshd/client/subsystem/sftp/SftpCommand.java | 29 +++
.../extensions/BuiltinSftpClientExtensions.java | 7 +
.../sftp/extensions/CopyDataExtension.java | 33 +++
.../extensions/impl/CopyDataExtensionImpl.java | 59 ++++++
.../org/apache/sshd/common/channel/PtyMode.java | 21 +-
.../common/subsystem/sftp/SftpConstants.java | 1 +
.../common/util/buffer/ByteArrayBuffer.java | 1 -
.../sshd/server/auth/UserAuthPublicKey.java | 2 +-
.../server/session/ServerUserAuthService.java | 2 +-
.../server/subsystem/sftp/SftpSubsystem.java | 151 ++++++++++++--
.../sshd/client/subsystem/sftp/SftpTest.java | 20 --
.../extensions/CopyDataExtensionImplTest.java | 203 +++++++++++++++++++
.../apache/sshd/deprecated/UserAuthAgent.java | 7 +-
.../sshd/deprecated/UserAuthPassword.java | 2 +-
.../sshd/deprecated/UserAuthPublicKey.java | 6 +-
20 files changed, 497 insertions(+), 69 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/515427fa/sshd-core/src/main/java/org/apache/sshd/agent/local/ChannelAgentForwarding.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/local/ChannelAgentForwarding.java b/sshd-core/src/main/java/org/apache/sshd/agent/local/ChannelAgentForwarding.java
index c5c39ec..82c67f3 100644
--- a/sshd-core/src/main/java/org/apache/sshd/agent/local/ChannelAgentForwarding.java
+++ b/sshd-core/src/main/java/org/apache/sshd/agent/local/ChannelAgentForwarding.java
@@ -37,11 +37,6 @@ import org.apache.sshd.server.channel.AbstractServerChannel;
* The client side channel that will receive requests forwards by the SSH server.
*/
public class ChannelAgentForwarding extends AbstractServerChannel {
-
- private String authSocket;
- private long pool;
- private long handle;
- private Thread thread;
private OutputStream out;
private SshAgent agent;
private AgentClient client;
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/515427fa/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPassword.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPassword.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPassword.java
index 7ca3170..3a43362 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPassword.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPassword.java
@@ -68,7 +68,7 @@ public class UserAuthPassword extends AbstractLoggingBean implements UserAuth {
buffer.putString(session.getUsername());
buffer.putString(service);
buffer.putString("password");
- buffer.putByte((byte) 0);
+ buffer.putBoolean(false);
buffer.putString(current);
session.writePacket(buffer);
return true;
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/515427fa/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPublicKey.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPublicKey.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPublicKey.java
index 4a8b881..712a84a 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPublicKey.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPublicKey.java
@@ -103,7 +103,7 @@ public class UserAuthPublicKey extends AbstractLoggingBean implements UserAuth {
buffer.putString(session.getUsername());
buffer.putString(service);
buffer.putString(UserAuthPublicKeyFactory.NAME);
- buffer.putByte((byte) 0);
+ buffer.putBoolean(false);
buffer.putString(algo);
buffer.putPublicKey(key);
session.writePacket(buffer);
@@ -123,7 +123,7 @@ public class UserAuthPublicKey extends AbstractLoggingBean implements UserAuth {
buffer.putString(session.getUsername());
buffer.putString(service);
buffer.putString(UserAuthPublicKeyFactory.NAME);
- buffer.putByte((byte) 1);
+ buffer.putBoolean(true);
buffer.putString(algo);
buffer.putPublicKey(key);
@@ -133,7 +133,7 @@ public class UserAuthPublicKey extends AbstractLoggingBean implements UserAuth {
bs.putString(session.getUsername());
bs.putString(service);
bs.putString(UserAuthPublicKeyFactory.NAME);
- bs.putByte((byte) 1);
+ bs.putBoolean(true);
bs.putString(algo);
bs.putPublicKey(key);
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/515427fa/sshd-core/src/main/java/org/apache/sshd/client/channel/PtyCapableChannelSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/channel/PtyCapableChannelSession.java b/sshd-core/src/main/java/org/apache/sshd/client/channel/PtyCapableChannelSession.java
index 8c9b3a4..d3eee76 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/channel/PtyCapableChannelSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/channel/PtyCapableChannelSession.java
@@ -23,10 +23,6 @@ import java.util.Collections;
import java.util.EnumMap;
import java.util.LinkedHashMap;
import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.sshd.client.SshClient;
-import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.SshConstants;
import org.apache.sshd.common.channel.PtyMode;
import org.apache.sshd.common.channel.SttySupport;
@@ -225,14 +221,14 @@ public class PtyCapableChannelSession extends ChannelSession {
buffer.putInt(ptyHeight);
buffer.putInt(ptyWidth);
- Buffer modes = new ByteArrayBuffer();
+ Buffer modes = new ByteArrayBuffer(GenericUtils.size(ptyModes) * (1 + (Integer.SIZE / Byte.SIZE)) + Byte.SIZE);
for (Map.Entry<PtyMode,? extends Number> modeEntry : ptyModes.entrySet()) {
PtyMode mode = modeEntry.getKey();
Number value = modeEntry.getValue();
modes.putByte((byte) mode.toInt());
modes.putInt(value.longValue());
}
- modes.putByte((byte) 0);
+ modes.putByte(PtyMode.TTY_OP_END);
buffer.putBytes(modes.getCompactData());
writePacket(buffer);
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/515427fa/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/AbstractSftpClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/AbstractSftpClient.java b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/AbstractSftpClient.java
index 8d9705a..2dd3589 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/AbstractSftpClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/AbstractSftpClient.java
@@ -89,7 +89,6 @@ import static org.apache.sshd.common.subsystem.sftp.SftpConstants.S_IFREG;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.nio.charset.StandardCharsets;
import java.nio.file.attribute.FileTime;
import java.util.ArrayList;
import java.util.Collection;
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/515427fa/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpCommand.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpCommand.java b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpCommand.java
index c0d7edd..4a7f783 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpCommand.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpCommand.java
@@ -32,8 +32,10 @@ import java.util.TreeMap;
import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.NamedResource;
+import org.apache.sshd.common.subsystem.sftp.extensions.ParserUtils;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.ValidateUtils;
+import org.apache.sshd.common.util.buffer.BufferUtils;
import org.apache.sshd.common.util.io.NoCloseInputStream;
/**
@@ -78,6 +80,33 @@ public class SftpCommand implements Channel {
new CommandExecutor() {
@Override
public String getName() {
+ return "info";
+ }
+
+ @Override
+ public boolean executeCommand(String args, BufferedReader stdin, PrintStream stdout, PrintStream stderr) throws Exception {
+ ValidateUtils.checkTrue(GenericUtils.isEmpty(args), "Unexpected arguments: %s", args);
+ SftpClient sftp = getClient();
+ Map<String,byte[]> extensions = sftp.getServerExtensions();
+ Map<String,?> parsed = ParserUtils.parse(null);
+ for (Map.Entry<String,byte[]> ee : extensions.entrySet()) {
+ String name = ee.getKey();
+ byte[] value = ee.getValue();
+ Object info = parsed.get(name);
+
+ stdout.append('\t').append(name).append(": ");
+ if (info == null) {
+ stdout.println(BufferUtils.printHex(value));
+ } else {
+ stdout.println(info);
+ }
+ }
+ return false;
+ }
+ },
+ new CommandExecutor() {
+ @Override
+ public String getName() {
return "version";
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/515427fa/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/extensions/BuiltinSftpClientExtensions.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/extensions/BuiltinSftpClientExtensions.java b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/extensions/BuiltinSftpClientExtensions.java
index 7a23f13..467ef78 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/extensions/BuiltinSftpClientExtensions.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/extensions/BuiltinSftpClientExtensions.java
@@ -28,6 +28,7 @@ import org.apache.sshd.client.subsystem.sftp.RawSftpClient;
import org.apache.sshd.client.subsystem.sftp.SftpClient;
import org.apache.sshd.client.subsystem.sftp.extensions.impl.CheckFileHandleExtensionImpl;
import org.apache.sshd.client.subsystem.sftp.extensions.impl.CheckFileNameExtensionImpl;
+import org.apache.sshd.client.subsystem.sftp.extensions.impl.CopyDataExtensionImpl;
import org.apache.sshd.client.subsystem.sftp.extensions.impl.CopyFileExtensionImpl;
import org.apache.sshd.client.subsystem.sftp.extensions.impl.MD5FileExtensionImpl;
import org.apache.sshd.client.subsystem.sftp.extensions.impl.MD5HandleExtensionImpl;
@@ -45,6 +46,12 @@ public enum BuiltinSftpClientExtensions implements SftpClientExtensionFactory {
return new CopyFileExtensionImpl(client, raw, ParserUtils.supportedExtensions(parsed));
}
},
+ COPY_DATA(SftpConstants.EXT_COPYDATA, CopyDataExtension.class) {
+ @Override // co-variant return
+ public CopyDataExtension create(SftpClient client, RawSftpClient raw, Map<String,byte[]> extensions, Map<String,?> parsed) {
+ return new CopyDataExtensionImpl(client, raw, ParserUtils.supportedExtensions(parsed));
+ }
+ },
MD5_FILE(SftpConstants.EXT_MD5HASH, MD5FileExtension.class) {
@Override // co-variant return
public MD5FileExtension create(SftpClient client, RawSftpClient raw, Map<String,byte[]> extensions, Map<String,?> parsed) {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/515427fa/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/extensions/CopyDataExtension.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/extensions/CopyDataExtension.java b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/extensions/CopyDataExtension.java
new file mode 100644
index 0000000..64025bc
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/extensions/CopyDataExtension.java
@@ -0,0 +1,33 @@
+/*
+ * 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.client.subsystem.sftp.extensions;
+
+import java.io.IOException;
+
+import org.apache.sshd.client.subsystem.sftp.SftpClient.Handle;
+
+/**
+ * Implements the "copy-data" extension
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ * @see <A HREF="http://tools.ietf.org/id/draft-ietf-secsh-filexfer-extensions-00.txt">DRAFT 00 section 7</A>
+ */
+public interface CopyDataExtension extends SftpClientExtension {
+ void copyData(Handle readHandle, long readOffset, long readLength, Handle writeHandle, long writeOffset) throws IOException;
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/515427fa/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/extensions/impl/CopyDataExtensionImpl.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/extensions/impl/CopyDataExtensionImpl.java b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/extensions/impl/CopyDataExtensionImpl.java
new file mode 100644
index 0000000..8d28bbb
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/extensions/impl/CopyDataExtensionImpl.java
@@ -0,0 +1,59 @@
+/*
+ * 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.client.subsystem.sftp.extensions.impl;
+
+import java.io.IOException;
+import java.util.Collection;
+
+import org.apache.sshd.client.subsystem.sftp.RawSftpClient;
+import org.apache.sshd.client.subsystem.sftp.SftpClient;
+import org.apache.sshd.client.subsystem.sftp.SftpClient.Handle;
+import org.apache.sshd.client.subsystem.sftp.extensions.CopyDataExtension;
+import org.apache.sshd.common.subsystem.sftp.SftpConstants;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.buffer.Buffer;
+import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class CopyDataExtensionImpl extends AbstractSftpClientExtension implements CopyDataExtension {
+ public CopyDataExtensionImpl(SftpClient client, RawSftpClient raw, Collection<String> extra) {
+ super(SftpConstants.EXT_COPYDATA, client, raw, extra);
+ }
+
+ @Override
+ public void copyData(Handle readHandle, long readOffset, long readLength, Handle writeHandle, long writeOffset) throws IOException {
+ byte[] srcId = readHandle.getIdentifier(), dstId = writeHandle.getIdentifier();
+ String opcode = getName();
+ Buffer buffer = new ByteArrayBuffer((Integer.SIZE / Byte.SIZE) + GenericUtils.length(opcode)
+ + (Integer.SIZE / Byte.SIZE) + GenericUtils.length(srcId)
+ + (Integer.SIZE / Byte.SIZE) + GenericUtils.length(dstId)
+ + (3 * (Long.SIZE + (Integer.SIZE / Byte.SIZE)))
+ + Byte.SIZE);
+ buffer.putString(opcode);
+ buffer.putBytes(srcId);
+ buffer.putLong(readOffset);
+ buffer.putLong(readLength);
+ buffer.putBytes(dstId);
+ buffer.putLong(writeOffset);
+ sendAndCheckExtendedCommandStatus(buffer);
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/515427fa/sshd-core/src/main/java/org/apache/sshd/common/channel/PtyMode.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/channel/PtyMode.java b/sshd-core/src/main/java/org/apache/sshd/common/channel/PtyMode.java
index 72e40b3..b320482 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/channel/PtyMode.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/channel/PtyMode.java
@@ -18,6 +18,7 @@
*/
package org.apache.sshd.common.channel;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -60,14 +61,18 @@ public enum PtyMode {
return v;
}
- static Map<Integer, PtyMode> commands;
-
- static {
- commands = new HashMap<Integer, PtyMode>();
- for (PtyMode c : PtyMode.values()) {
- commands.put(Integer.valueOf(c.toInt()), c);
- }
- }
+ public static final byte TTY_OP_END = 0x00;
+
+ private static final Map<Integer, PtyMode> commands =
+ Collections.unmodifiableMap(new HashMap<Integer, PtyMode>() {
+ private static final long serialVersionUID = 1L; // we're not serializing it
+
+ {
+ for (PtyMode c : PtyMode.values()) {
+ put(Integer.valueOf(c.toInt()), c);
+ }
+ }
+ });
public static PtyMode fromInt(int b) {
return commands.get(Integer.valueOf(0x00FF & (b + 256)));
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/515427fa/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/SftpConstants.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/SftpConstants.java b/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/SftpConstants.java
index 92be24e..e719de5 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/SftpConstants.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/SftpConstants.java
@@ -236,6 +236,7 @@ public final class SftpConstants {
public static final String EXT_CHKFILE_NAME = "check-file-name";
public static final int MIN_CHKFILE_BLOCKSIZE = 256;
public static final String EXT_CHKFILE_RESPONSE = "check-file";
+ public static final String EXT_COPYDATA = "copy-data";
private SftpConstants() {
throw new UnsupportedOperationException("No instance");
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/515427fa/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/ByteArrayBuffer.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/ByteArrayBuffer.java b/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/ByteArrayBuffer.java
index e41447c..19cc401 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/ByteArrayBuffer.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/ByteArrayBuffer.java
@@ -19,7 +19,6 @@
package org.apache.sshd.common.util.buffer;
-import java.nio.BufferUnderflowException;
import java.nio.charset.Charset;
import org.apache.sshd.common.util.Int2IntFunction;
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/515427fa/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuthPublicKey.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuthPublicKey.java b/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuthPublicKey.java
index fcbc421..8c58463 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuthPublicKey.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuthPublicKey.java
@@ -81,7 +81,7 @@ public class UserAuthPublicKey extends AbstractUserAuth {
buf.putString(username);
buf.putString(service);
buf.putString(UserAuthPublicKeyFactory.NAME);
- buf.putByte((byte) 1);
+ buf.putBoolean(true);
buf.putString(alg);
buffer.rpos(oldPos);
buffer.wpos(oldPos + 4 + len);
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/515427fa/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java
index 7f64dce..39c2d16 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java
@@ -220,7 +220,7 @@ public class ServerUserAuthService extends CloseableUtils.AbstractCloseable impl
}
}
buffer.putString(sb.toString());
- buffer.putByte((byte) 1);
+ buffer.putBoolean(true);
session.writePacket(buffer);
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/515427fa/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java b/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
index 41b9cf3..3f1bb4c 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
@@ -180,7 +180,8 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
SftpConstants.EXT_MD5HASH,
SftpConstants.EXT_MD5HASH_HANDLE,
SftpConstants.EXT_CHKFILE_HANDLE,
- SftpConstants.EXT_CHKFILE_NAME
+ SftpConstants.EXT_CHKFILE_NAME,
+ SftpConstants.EXT_COPYDATA
)));
static {
@@ -691,6 +692,9 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
case SftpConstants.EXT_COPYFILE:
doCopyFile(buffer, id);
break;
+ case SftpConstants.EXT_COPYDATA:
+ doCopyData(buffer, id);
+ break;
case SftpConstants.EXT_MD5HASH:
case SftpConstants.EXT_MD5HASH_HANDLE:
doMD5Hash(buffer, id, extension);
@@ -808,21 +812,29 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
protected void doCheckFileHash(int id, Path file, NamedFactory<? extends Digest> factory,
long startOffset, long length, int blockSize, Buffer buffer)
throws Exception {
+ ValidateUtils.checkTrue(startOffset >= 0L, "Invalid start offset: %d", startOffset);
+ ValidateUtils.checkTrue(length >= 0L, "Invalid length: %d", length);
ValidateUtils.checkTrue((blockSize == 0) || (blockSize >= SftpConstants.MIN_CHKFILE_BLOCKSIZE), "Invalid block size: %d", blockSize);
ValidateUtils.checkNotNull(factory, "No digest factory provided", GenericUtils.EMPTY_OBJECT_ARRAY);
buffer.putString(factory.getName());
long effectiveLength = length;
+ long totalLength = Files.size(file);
if (effectiveLength == 0L) {
- long totalLength = Files.size(file);
- effectiveLength = totalLength - startOffset;
+ effectiveLength = totalLength - startOffset;
+ } else {
+ long maxRead = startOffset + length;
+ if (maxRead > totalLength) {
+ effectiveLength = totalLength - startOffset;
+ }
}
+ ValidateUtils.checkTrue(effectiveLength > 0L, "Non-positive effective hash data length: %d", effectiveLength);
- byte[] workBuf = (blockSize == 0)
+ byte[] digestBuf = (blockSize == 0)
? new byte[Math.min((int) effectiveLength, IoUtils.DEFAULT_COPY_SIZE)]
: new byte[Math.min((int) effectiveLength, blockSize)]
;
- ByteBuffer bb = ByteBuffer.wrap(workBuf);
+ ByteBuffer wb = ByteBuffer.wrap(digestBuf);
try(FileChannel channel = FileChannel.open(file, IoUtils.EMPTY_OPEN_OPTIONS)) {
channel.position(startOffset);
@@ -831,6 +843,11 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
if (blockSize == 0) {
while(effectiveLength > 0L) {
+ int remainLen = Math.min(digestBuf.length, (int) effectiveLength);
+ ByteBuffer bb = wb;
+ if (remainLen < digestBuf.length) {
+ bb = ByteBuffer.wrap(digestBuf, 0, remainLen);
+ }
bb.clear(); // prepare for next read
int readLen = channel.read(bb);
@@ -839,7 +856,7 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
}
effectiveLength -= readLen;
- digest.update(workBuf, 0, readLen);
+ digest.update(digestBuf, 0, readLen);
}
byte[] hashValue = digest.digest();
@@ -851,6 +868,11 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
buffer.putBytes(hashValue);
} else {
for (int count=0; effectiveLength > 0L; count++) {
+ int remainLen = Math.min(digestBuf.length, (int) effectiveLength);
+ ByteBuffer bb = wb;
+ if (remainLen < digestBuf.length) {
+ bb = ByteBuffer.wrap(digestBuf, 0, remainLen);
+ }
bb.clear(); // prepare for next read
int readLen = channel.read(bb);
@@ -859,7 +881,7 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
}
effectiveLength -= readLen;
- digest.update(workBuf, 0, readLen);
+ digest.update(digestBuf, 0, readLen);
byte[] hashValue = digest.digest(); // NOTE: this also resets the hash for the next read
if (log.isTraceEnabled()) {
@@ -935,21 +957,29 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
*
* If both start-offset and length are zero, the entire file should be included
*/
- long effectiveLength = length;
+ long effectiveLength = length, totalSize = Files.size(path);
if ((startOffset == 0L) && (length == 0L)) {
- effectiveLength = Files.size(path);
+ effectiveLength = totalSize;
+ } else {
+ long maxRead = startOffset + effectiveLength;
+ if (maxRead > totalSize) {
+ effectiveLength = totalSize - startOffset;
+ }
}
return doMD5Hash(id, path, startOffset, effectiveLength, quickCheckHash);
}
protected byte[] doMD5Hash(int id, Path path, long startOffset, long length, byte[] quickCheckHash) throws Exception {
+ ValidateUtils.checkTrue(startOffset >= 0L, "Invalid start offset: %d", startOffset);
+ ValidateUtils.checkTrue(length > 0L, "Invalid length: %d", length);
+
Digest digest = BuiltinDigests.md5.create();
digest.init();
long effectiveLength = length;
byte[] digestBuf = new byte[(int) Math.min(effectiveLength, SftpConstants.MD5_QUICK_HASH_SIZE)];
- ByteBuffer bb = ByteBuffer.wrap(digestBuf);
+ ByteBuffer wb = ByteBuffer.wrap(digestBuf);
boolean hashMatches = false;
byte[] hashValue = null;
@@ -968,7 +998,7 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
// TODO consider limiting it - e.g., if the requested effective length is <= than some (configurable) threshold
hashMatches = true;
} else {
- int readLen = channel.read(bb);
+ int readLen = channel.read(wb);
if (readLen < 0) {
throw new EOFException("EOF while read initial buffer from " + path);
}
@@ -1002,6 +1032,11 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
if (hashMatches) {
while(effectiveLength > 0L) {
+ int remainLen = Math.min(digestBuf.length, (int) effectiveLength);
+ ByteBuffer bb = wb;
+ if (remainLen < digestBuf.length) {
+ bb = ByteBuffer.wrap(digestBuf, 0, remainLen);
+ }
bb.clear(); // prepare for next read
int readLen = channel.read(bb);
@@ -1298,6 +1333,96 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
Files.move(o, n, GenericUtils.isEmpty(opts) ? IoUtils.EMPTY_COPY_OPTIONS : opts.toArray(new CopyOption[opts.size()]));
}
+ // see https://tools.ietf.org/html/draft-ietf-secsh-filexfer-extensions-00#section-7
+ protected void doCopyData(Buffer buffer, int id) throws IOException {
+ String readHandle = buffer.getString();
+ long readOffset = buffer.getLong();
+ long readLength = buffer.getLong();
+ String writeHandle = buffer.getString();
+ long writeOffset = buffer.getLong();
+ try {
+ doCopyData(id, readHandle, readOffset, readLength, writeHandle, writeOffset);
+ } catch (IOException | RuntimeException e) {
+ sendStatus(BufferUtils.clear(buffer), id, e);
+ return;
+ }
+
+ sendStatus(BufferUtils.clear(buffer), id, SSH_FX_OK, "");
+ }
+
+ @SuppressWarnings("resource")
+ protected void doCopyData(int id, String readHandle, long readOffset, long readLength, String writeHandle, long writeOffset) throws IOException {
+ boolean inPlaceCopy = readHandle.equals(writeHandle);
+ Handle rh = handles.get(readHandle);
+ Handle wh = inPlaceCopy ? rh : handles.get(writeHandle);
+ if (log.isDebugEnabled()) {
+ log.debug("SSH_FXP_EXTENDED[{}] read={}[{}], read-offset={}, read-length={}, write={}[{}], write-offset={})",
+ SftpConstants.EXT_COPYDATA,
+ readHandle, rh, Long.valueOf(readOffset), Long.valueOf(readLength),
+ writeHandle, wh, Long.valueOf(writeOffset));
+ }
+
+ FileHandle srcHandle = validateHandle(readHandle, rh, FileHandle.class);
+ Path srcPath = srcHandle.getFile();
+ int srcAccess = srcHandle.getAccessMask();
+ if ((srcAccess & ACE4_READ_DATA) != ACE4_READ_DATA) {
+ throw new AccessDeniedException("File not opened for read: " + srcPath);
+ }
+
+ ValidateUtils.checkTrue(readLength >= 0L, "Invalid read length: %d", readLength);
+ ValidateUtils.checkTrue(readOffset >= 0L, "Invalid read offset: %d", readOffset);
+
+ long totalSize = Files.size(srcHandle.getFile());
+ long effectiveLength = readLength;
+ if (effectiveLength == 0L) {
+ effectiveLength = totalSize - readOffset;
+ } else {
+ long maxRead = readOffset + effectiveLength;
+ if (maxRead > totalSize) {
+ effectiveLength = totalSize - readOffset;
+ }
+ }
+ ValidateUtils.checkTrue(effectiveLength > 0L, "Non-positive effective copy data length: %d", effectiveLength);
+
+ FileHandle dstHandle = inPlaceCopy ? srcHandle : validateHandle(writeHandle, wh, FileHandle.class);
+ int dstAccess = dstHandle.getAccessMask();
+ if ((dstAccess & ACE4_WRITE_DATA) != ACE4_WRITE_DATA) {
+ throw new AccessDeniedException("File not opened for write: " + srcHandle);
+ }
+
+ ValidateUtils.checkTrue(writeOffset >= 0L, "Invalid write offset: %d", writeOffset);
+ // check if overlapping ranges as per the draft
+ if (inPlaceCopy) {
+ long maxRead = readOffset + effectiveLength;
+ if (maxRead > totalSize) {
+ maxRead = totalSize;
+ }
+
+ long maxWrite = writeOffset + effectiveLength;
+ if (maxWrite > readOffset) {
+ throw new IllegalArgumentException("Write range end [" + writeOffset + "-" + maxWrite + "]"
+ + " overlaps with read range [" + readOffset + "-" + maxRead + "]");
+ } else if (maxRead > writeOffset) {
+ throw new IllegalArgumentException("Read range end [" + readOffset + "-" + maxRead + "]"
+ + " overlaps with write range [" + writeOffset + "-" + maxWrite + "]");
+ }
+ }
+
+ byte[] copyBuf = new byte[Math.min(IoUtils.DEFAULT_COPY_SIZE, (int) effectiveLength)];
+ while(effectiveLength > 0L) {
+ int remainLength = Math.min(copyBuf.length, (int) effectiveLength);
+ int readLen = srcHandle.read(copyBuf, 0, remainLength, readOffset);
+ if (readLen < 0) {
+ throw new EOFException("Premature EOF while still remaining " + effectiveLength + " bytes");
+ }
+ dstHandle.write(copyBuf, 0, readLen, writeOffset);
+
+ effectiveLength -= readLen;
+ readOffset += readLen;
+ writeOffset += readLen;
+ }
+ }
+
// see https://tools.ietf.org/html/draft-ietf-secsh-filexfer-extensions-00#section-6
protected void doCopyFile(Buffer buffer, int id) throws IOException {
String srcFile = buffer.getString();
@@ -1317,7 +1442,7 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
protected void doCopyFile(int id, String srcFile, String dstFile, boolean overwriteDestination) throws IOException {
if (log.isDebugEnabled()) {
log.debug("SSH_FXP_EXTENDED[{}] (src={}, dst={}, overwrite=0x{})",
- SftpConstants.EXT_COPYFILE, srcFile, dstFile, Boolean.valueOf(overwriteDestination));
+ SftpConstants.EXT_COPYFILE, srcFile, dstFile, Boolean.valueOf(overwriteDestination));
}
doCopyFile(id, srcFile, dstFile,
@@ -2951,6 +3076,8 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
return SSH_FX_LOCK_CONFLICT;
} else if (e instanceof UnsupportedOperationException) {
return SSH_FX_OP_UNSUPPORTED;
+ } else if (e instanceof IllegalArgumentException) {
+ return SSH_FX_INVALID_PARAMETER;
} else {
return SSH_FX_FAILURE;
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/515427fa/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java
index d1e200a..8f37d39 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java
@@ -31,13 +31,10 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.nio.charset.StandardCharsets;
-import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
-import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.List;
@@ -50,38 +47,21 @@ import java.util.concurrent.atomic.AtomicInteger;
import org.apache.sshd.client.SftpException;
import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.session.ClientSession;
-import org.apache.sshd.client.subsystem.sftp.SftpClient.CloseableHandle;
import org.apache.sshd.client.subsystem.sftp.extensions.BuiltinSftpClientExtensions;
import org.apache.sshd.client.subsystem.sftp.extensions.CopyFileExtension;
-import org.apache.sshd.client.subsystem.sftp.extensions.MD5FileExtension;
-import org.apache.sshd.client.subsystem.sftp.extensions.MD5HandleExtension;
import org.apache.sshd.client.subsystem.sftp.extensions.SftpClientExtension;
import org.apache.sshd.common.Factory;
import org.apache.sshd.common.FactoryManager;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.digest.BuiltinDigests;
-import org.apache.sshd.common.digest.Digest;
-import org.apache.sshd.common.file.FileSystemFactory;
-import org.apache.sshd.common.file.root.RootedFileSystemProvider;
import org.apache.sshd.common.random.Random;
-import org.apache.sshd.common.session.Session;
import org.apache.sshd.common.subsystem.sftp.SftpConstants;
import org.apache.sshd.common.subsystem.sftp.extensions.ParserUtils;
import org.apache.sshd.common.subsystem.sftp.extensions.Supported2Parser.Supported2;
import org.apache.sshd.common.subsystem.sftp.extensions.SupportedParser.Supported;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.OsUtils;
-import org.apache.sshd.common.util.buffer.BufferUtils;
import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
import org.apache.sshd.common.util.io.IoUtils;
-import org.apache.sshd.server.Command;
-import org.apache.sshd.server.SshServer;
-import org.apache.sshd.server.command.ScpCommandFactory;
import org.apache.sshd.server.subsystem.sftp.SftpSubsystem;
-import org.apache.sshd.server.subsystem.sftp.SftpSubsystemFactory;
-import org.apache.sshd.util.BaseTestSupport;
-import org.apache.sshd.util.BogusPasswordAuthenticator;
-import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.JSchLogger;
import org.apache.sshd.util.SimpleUserInfo;
import org.apache.sshd.util.Utils;
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/515427fa/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/CopyDataExtensionImplTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/CopyDataExtensionImplTest.java b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/CopyDataExtensionImplTest.java
new file mode 100644
index 0000000..419e326
--- /dev/null
+++ b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/CopyDataExtensionImplTest.java
@@ -0,0 +1,203 @@
+/*
+ * 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.client.subsystem.sftp.extensions;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.sshd.client.SshClient;
+import org.apache.sshd.client.session.ClientSession;
+import org.apache.sshd.client.subsystem.sftp.AbstractSftpClientTestSupport;
+import org.apache.sshd.client.subsystem.sftp.SftpClient;
+import org.apache.sshd.client.subsystem.sftp.SftpClient.CloseableHandle;
+import org.apache.sshd.common.Factory;
+import org.apache.sshd.common.random.Random;
+import org.apache.sshd.common.subsystem.sftp.SftpConstants;
+import org.apache.sshd.common.util.io.IoUtils;
+import org.apache.sshd.util.Utils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@RunWith(Parameterized.class) // see https://github.com/junit-team/junit/wiki/Parameterized-tests
+public class CopyDataExtensionImplTest extends AbstractSftpClientTestSupport {
+ private static final List<Object[]> PARAMETERS =
+ Collections.unmodifiableList(
+ Arrays.<Object[]>asList(
+ new Object[] {
+ Integer.valueOf(IoUtils.DEFAULT_COPY_SIZE),
+ Integer.valueOf(0),
+ Integer.valueOf(IoUtils.DEFAULT_COPY_SIZE),
+ Long.valueOf(0L)
+ },
+ new Object[] {
+ Integer.valueOf(IoUtils.DEFAULT_COPY_SIZE),
+ Integer.valueOf(IoUtils.DEFAULT_COPY_SIZE / 2),
+ Integer.valueOf(IoUtils.DEFAULT_COPY_SIZE / 4),
+ Long.valueOf(0L)
+ },
+ new Object[] {
+ Integer.valueOf(IoUtils.DEFAULT_COPY_SIZE),
+ Integer.valueOf(IoUtils.DEFAULT_COPY_SIZE / 2),
+ Integer.valueOf(IoUtils.DEFAULT_COPY_SIZE / 4),
+ Long.valueOf(IoUtils.DEFAULT_COPY_SIZE / 2)
+ },
+ new Object[] {
+ Integer.valueOf(Byte.MAX_VALUE),
+ Integer.valueOf(Byte.MAX_VALUE / 2),
+ Integer.valueOf(Byte.MAX_VALUE), // attempt to read more than available
+ Long.valueOf(0L)
+ }
+ ));
+
+ @Parameters(name = "size={0}, readOffset={1}, readLength={2}, writeOffset={3}")
+ public static Collection<Object[]> parameters() {
+ return PARAMETERS;
+ }
+
+ private int size, srcOffset, length;
+ private long dstOffset;
+
+ public CopyDataExtensionImplTest(int size, int srcOffset, int length, long dstOffset) throws IOException {
+ this.size = size;
+ this.srcOffset = srcOffset;
+ this.length = length;
+ this.dstOffset = dstOffset;
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ setupServer();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ tearDownServer();
+ }
+
+ @Test
+ public void testCopyDataExtension() throws Exception {
+ testCopyDataExtension(size, srcOffset, length, dstOffset);
+ }
+
+ private void testCopyDataExtension(int dataSize, int readOffset, int readLength, long writeOffset) throws Exception {
+ byte[] seed = (getClass().getName() + "#" + getCurrentTestName()
+ + "-" + dataSize
+ + "-" + readOffset + "/" + readLength + "/" + writeOffset
+ + System.getProperty("line.separator"))
+ .getBytes(StandardCharsets.UTF_8)
+ ;
+ try(ByteArrayOutputStream baos=new ByteArrayOutputStream(dataSize + seed.length)) {
+ while (baos.size() < dataSize) {
+ baos.write(seed);
+ }
+
+ testCopyDataExtension(baos.toByteArray(), readOffset, readLength, writeOffset);
+ }
+ }
+
+ private void testCopyDataExtension(byte[] data, int readOffset, int readLength, long writeOffset) throws Exception {
+ Path targetPath = detectTargetFolder().toPath();
+ Path parentPath = targetPath.getParent();
+ Path lclSftp = Utils.resolve(targetPath, SftpConstants.SFTP_SUBSYSTEM_NAME, getClass().getSimpleName(), getCurrentTestName());
+ Utils.deleteRecursive(lclSftp);
+ LinkOption[] options = IoUtils.getLinkOptions(false);
+ assertHierarchyTargetFolderExists(lclSftp, options);
+
+ String baseName = getCurrentTestName() + "-" + readOffset + "-" + readLength + "-" + writeOffset;
+ Path srcFile = lclSftp.resolve(baseName + "-src.txt");
+ Files.write(srcFile, data, IoUtils.EMPTY_OPEN_OPTIONS);
+ String srcPath = Utils.resolveRelativeRemotePath(parentPath, srcFile);
+
+ Path dstFile = srcFile.getParent().resolve(baseName + "-dst.txt");
+ if (Files.exists(dstFile, options)) {
+ Files.delete(dstFile);
+ }
+ String dstPath = Utils.resolveRelativeRemotePath(parentPath, dstFile);
+
+ try(SshClient client = SshClient.setUpDefaultClient()) {
+ client.start();
+
+ if (writeOffset > 0L) {
+ Factory<? extends Random> factory = client.getRandomFactory();
+ Random randomizer = factory.create();
+ long totalLength = writeOffset + readLength;
+ byte[] workBuf = new byte[(int) Math.min(totalLength, IoUtils.DEFAULT_COPY_SIZE)];
+ try(OutputStream output = Files.newOutputStream(dstFile, IoUtils.EMPTY_OPEN_OPTIONS)) {
+ while(totalLength > 0L) {
+ randomizer.fill(workBuf);
+ output.write(workBuf);
+ totalLength -= workBuf.length;
+ }
+ }
+ }
+
+ try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
+ session.addPasswordIdentity(getCurrentTestName());
+ session.auth().verify(5L, TimeUnit.SECONDS);
+
+ try(SftpClient sftp = session.createSftpClient()) {
+ CopyDataExtension ext = assertExtensionCreated(sftp, CopyDataExtension.class);
+ try(CloseableHandle readHandle = sftp.open(srcPath, SftpClient.OpenMode.Read);
+ CloseableHandle writeHandle = sftp.open(dstPath, SftpClient.OpenMode.Write, SftpClient.OpenMode.Create)) {
+ ext.copyData(readHandle, readOffset, readLength, writeHandle, writeOffset);
+ }
+ }
+ } finally {
+ client.stop();
+ }
+ }
+
+ int available = data.length, required = readOffset + readLength;
+ if (required > available) {
+ required = available;
+ }
+ byte[] expected = new byte[required - readOffset];
+ System.arraycopy(data, readOffset, expected, 0, expected.length);
+
+ byte[] actual = new byte[expected.length];
+ try(FileChannel channel = FileChannel.open(dstFile, IoUtils.EMPTY_OPEN_OPTIONS)) {
+ int readLen = channel.read(ByteBuffer.wrap(actual), writeOffset);
+ assertEquals("Mismatched read data size", expected.length, readLen);
+ }
+ assertArrayEquals("Mismatched copy data", expected, actual);
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/515427fa/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthAgent.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthAgent.java b/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthAgent.java
index e0f0b12..74e1935 100644
--- a/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthAgent.java
+++ b/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthAgent.java
@@ -52,23 +52,20 @@ public class UserAuthAgent extends AbstractUserAuth {
try {
log.debug("Send SSH_MSG_USERAUTH_REQUEST for publickey");
Buffer buffer = session.createBuffer(SshConstants.SSH_MSG_USERAUTH_REQUEST);
- int pos1 = buffer.wpos() - 1;
buffer.putString(session.getUsername());
buffer.putString(service);
buffer.putString(UserAuthPublicKeyFactory.NAME);
- buffer.putByte((byte) 1);
+ buffer.putBoolean(true);
buffer.putString(KeyUtils.getKeyType(key));
- int pos2 = buffer.wpos();
buffer.putPublicKey(key);
-
Buffer bs = new ByteArrayBuffer();
bs.putBytes(session.getKex().getH());
bs.putByte(SshConstants.SSH_MSG_USERAUTH_REQUEST);
bs.putString(session.getUsername());
bs.putString(service);
bs.putString(UserAuthPublicKeyFactory.NAME);
- bs.putByte((byte) 1);
+ bs.putBoolean(true);
bs.putString(KeyUtils.getKeyType(key));
bs.putPublicKey(key);
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/515427fa/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthPassword.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthPassword.java b/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthPassword.java
index 53a77c8..26cefa4 100644
--- a/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthPassword.java
+++ b/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthPassword.java
@@ -45,7 +45,7 @@ public class UserAuthPassword extends AbstractUserAuth {
buffer.putString(session.getUsername());
buffer.putString(service);
buffer.putString("password");
- buffer.putByte((byte) 0);
+ buffer.putBoolean(false);
buffer.putString(password);
session.writePacket(buffer);
return Result.Continued;
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/515427fa/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthPublicKey.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthPublicKey.java b/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthPublicKey.java
index c3fbae7..e90a33a 100644
--- a/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthPublicKey.java
+++ b/sshd-core/src/test/java/org/apache/sshd/deprecated/UserAuthPublicKey.java
@@ -51,14 +51,12 @@ public class UserAuthPublicKey extends AbstractUserAuth {
try {
log.debug("Send SSH_MSG_USERAUTH_REQUEST for publickey");
buffer = session.createBuffer(SshConstants.SSH_MSG_USERAUTH_REQUEST);
- int pos1 = buffer.wpos() - 1;
buffer.putString(session.getUsername());
buffer.putString(service);
buffer.putString(UserAuthPublicKeyFactory.NAME);
- buffer.putByte((byte) 1);
+ buffer.putBoolean(true);
String alg = KeyUtils.getKeyType(key);
buffer.putString(alg);
- int pos2 = buffer.wpos();
buffer.putPublicKey(key.getPublic());
FactoryManager manager = session.getFactoryManager();
@@ -74,7 +72,7 @@ public class UserAuthPublicKey extends AbstractUserAuth {
bs.putString(session.getUsername());
bs.putString(service);
bs.putString(UserAuthPublicKeyFactory.NAME);
- bs.putByte((byte) 1);
+ bs.putBoolean(true);
bs.putString(alg);
bs.putPublicKey(key.getPublic());
verif.update(bs.array(), bs.rpos(), bs.available());