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/01 15:20:24 UTC
mina-sshd git commit: [SSHD-330] Handshake fails (wrong shared
secret) 1 out of 256 times
Repository: mina-sshd
Updated Branches:
refs/heads/master a6e2bf9e4 -> df8324bcf
[SSHD-330] Handshake fails (wrong shared secret) 1 out of 256 times
* Improved AbstractDH#stripLeadingZeros to clone the array only if 1st byte is non-zero
Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/df8324bc
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/df8324bc
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/df8324bc
Branch: refs/heads/master
Commit: df8324bcfef82c7dcee2b4e2f0e2bb34aa5a4add
Parents: a6e2bf9
Author: Lyor Goldstein <lg...@vmware.com>
Authored: Wed Jul 1 16:20:05 2015 +0300
Committer: Lyor Goldstein <lg...@vmware.com>
Committed: Wed Jul 1 16:20:05 2015 +0300
----------------------------------------------------------------------
.../org/apache/sshd/common/kex/AbstractDH.java | 41 ++-
.../auth/password/PasswordAuthenticator.java | 2 +-
.../server/subsystem/sftp/SftpSubsystem.java | 314 ++++++++++---------
.../apache/sshd/common/kex/AbstractDHTest.java | 67 ++++
4 files changed, 258 insertions(+), 166 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/df8324bc/sshd-core/src/main/java/org/apache/sshd/common/kex/AbstractDH.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/kex/AbstractDH.java b/sshd-core/src/main/java/org/apache/sshd/common/kex/AbstractDH.java
index 4f2b565..d2a3092 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/kex/AbstractDH.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/kex/AbstractDH.java
@@ -21,10 +21,10 @@ package org.apache.sshd.common.kex;
import java.math.BigInteger;
import org.apache.sshd.common.digest.Digest;
+import org.apache.sshd.common.util.GenericUtils;
/**
* Base class for the Diffie-Hellman key agreement.
- *
*/
public abstract class AbstractDH {
@@ -51,18 +51,33 @@ public abstract class AbstractDH {
public abstract Digest getHash() throws Exception;
- // The shared secret returned by KeyAgreement.generateSecret() is
- // a byte array, which can (by chance, roughly 1 out of 256 times)
- // begin with zero byte (some JCE providers might strip this, though).
- // In SSH, the shared secret is an integer, so we need to strip
- // the leading zero(es).
- protected static byte[] stripLeadingZeroes(byte[] x) {
- int i = 0;
- while ((i < x.length - 1) && (x[i] == 0)) {
- i++;
+ /**
+ * The shared secret returned by {@link javax.crypto.KeyAgreement#generateSecret()}
+ * is a byte array, which can (by chance, roughly 1 out of 256 times) begin
+ * with zero byte (some JCE providers might strip this, though). In SSH,
+ * the shared secret is an integer, so we need to strip the leading zero(es).
+ * @param x The original array
+ * @return An (possibly) sub-array guaranteed to start with a non-zero byte
+ * @see <A HREF="https://issues.apache.org/jira/browse/SSHD-330">SSHD-330</A>
+ * @throws IllegalArgumentException If all zeroes array
+ */
+ public static byte[] stripLeadingZeroes(byte[] x) {
+ int length = GenericUtils.length(x);
+ for (int i = 0; i < x.length; i++) {
+ if (x[i] == 0) {
+ continue;
+ }
+
+ if (i == 0) { // 1st byte is non-zero so nothing to do
+ return x;
+ }
+
+ byte[] ret = new byte[length - i];
+ System.arraycopy(x, i, ret, 0, ret.length);
+ return ret;
}
- byte[] ret = new byte[x.length - i];
- System.arraycopy(x, i, ret, 0, ret.length);
- return ret;
+
+ // all zeroes
+ throw new IllegalArgumentException("No non-zero values in generated secret");
}
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/df8324bc/sshd-core/src/main/java/org/apache/sshd/server/auth/password/PasswordAuthenticator.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/auth/password/PasswordAuthenticator.java b/sshd-core/src/main/java/org/apache/sshd/server/auth/password/PasswordAuthenticator.java
index 8139bef..20bdef6 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/auth/password/PasswordAuthenticator.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/auth/password/PasswordAuthenticator.java
@@ -29,7 +29,7 @@ public interface PasswordAuthenticator {
* Check the validity of a password.
* @param username The username credential
* @param password The provided password
- * @param session The {@link ServerSession} attemtpting the authentication
+ * @param session The {@link ServerSession} attempting the authentication
* @return {@code true} indicating if authentication succeeded
*/
boolean authenticate(String username, String password, ServerSession session);
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/df8324bc/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 c6baa5c..c3a3efa 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
@@ -28,7 +28,6 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
@@ -230,22 +229,22 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
options.add(StandardOpenOption.WRITE);
}
switch (flags & SSH_FXF_ACCESS_DISPOSITION) {
- case SSH_FXF_CREATE_NEW:
- options.add(StandardOpenOption.CREATE_NEW);
- break;
- case SSH_FXF_CREATE_TRUNCATE:
- options.add(StandardOpenOption.CREATE);
- options.add(StandardOpenOption.TRUNCATE_EXISTING);
- break;
- case SSH_FXF_OPEN_EXISTING:
- break;
- case SSH_FXF_OPEN_OR_CREATE:
- options.add(StandardOpenOption.CREATE);
- break;
- case SSH_FXF_TRUNCATE_EXISTING:
- options.add(StandardOpenOption.TRUNCATE_EXISTING);
- break;
- default: // ignored
+ case SSH_FXF_CREATE_NEW:
+ options.add(StandardOpenOption.CREATE_NEW);
+ break;
+ case SSH_FXF_CREATE_TRUNCATE:
+ options.add(StandardOpenOption.CREATE);
+ options.add(StandardOpenOption.TRUNCATE_EXISTING);
+ break;
+ case SSH_FXF_OPEN_EXISTING:
+ break;
+ case SSH_FXF_OPEN_OR_CREATE:
+ options.add(StandardOpenOption.CREATE);
+ break;
+ case SSH_FXF_TRUNCATE_EXISTING:
+ options.add(StandardOpenOption.TRUNCATE_EXISTING);
+ break;
+ default: // ignored
}
if ((flags & SSH_FXF_APPEND_DATA) != 0) {
options.add(StandardOpenOption.APPEND);
@@ -465,7 +464,7 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
int id = buffer.getInt();
if (log.isDebugEnabled()) {
log.debug("process(length={}, type={}, id={})",
- new Object[] { Integer.valueOf(length), Integer.valueOf(type), Integer.valueOf(id) });
+ Integer.valueOf(length), Integer.valueOf(type), Integer.valueOf(id));
}
switch (type) {
@@ -547,27 +546,28 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
protected void doExtended(Buffer buffer, int id) throws IOException {
String extension = buffer.getString();
switch (extension) {
- case "text-seek":
- doTextSeek(buffer, id);
- break;
- case "version-select":
- doVersionSelect(buffer, id);
- break;
- default:
- log.info("Received unsupported SSH_FXP_EXTENDED({})", extension);
- sendStatus(id, SSH_FX_OP_UNSUPPORTED, "Command SSH_FXP_EXTENDED(" + extension + ") is unsupported or not implemented");
- break;
+ case "text-seek":
+ doTextSeek(buffer, id);
+ break;
+ case "version-select":
+ doVersionSelect(buffer, id);
+ break;
+ default:
+ log.info("Received unsupported SSH_FXP_EXTENDED({})", extension);
+ sendStatus(id, SSH_FX_OP_UNSUPPORTED, "Command SSH_FXP_EXTENDED(" + extension + ") is unsupported or not implemented");
+ break;
}
}
protected void doTextSeek(Buffer buffer, int id) throws IOException {
String handle = buffer.getString();
long line = buffer.getLong();
+ Handle h = handles.get(handle);
if (log.isDebugEnabled()) {
- log.debug("Received SSH_FXP_EXTENDED(text-seek) (handle={}, line={})", handle, Long.valueOf(line));
+ log.debug("Received SSH_FXP_EXTENDED(text-seek) (handle={}[{}], line={})", handle, h, Long.valueOf(line));
}
- // TODO : implement text-seek
+ // TODO : implement text-seek - see https://tools.ietf.org/html/draft-ietf-secsh-filexfer-03#section-6.3
sendStatus(id, SSH_FX_OP_UNSUPPORTED, "Command SSH_FXP_EXTENDED(text-seek) is unsupported or not implemented");
}
@@ -642,17 +642,18 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
long length = buffer.getLong();
int mask = buffer.getInt();
- if (log.isDebugEnabled()) {
- log.debug("Received SSH_FXP_BLOCK (handle={}, offset={}, length={}, mask=0x{})",
- new Object[] { handle, Long.valueOf(offset), Long.valueOf(length), Integer.toHexString(mask) });
- }
-
try {
Handle p = handles.get(handle);
+ if (log.isDebugEnabled()) {
+ log.debug("Received SSH_FXP_BLOCK (handle={}[{}], offset={}, length={}, mask=0x{})",
+ handle, p, Long.valueOf(offset), Long.valueOf(length), Integer.toHexString(mask));
+ }
+
if (!(p instanceof FileHandle)) {
sendStatus(id, SSH_FX_INVALID_HANDLE, handle);
return;
}
+
FileHandle fileHandle = (FileHandle) p;
fileHandle.lock(offset, length, mask);
sendStatus(id, SSH_FX_OK, "");
@@ -665,17 +666,18 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
String handle = buffer.getString();
long offset = buffer.getLong();
long length = buffer.getLong();
- if (log.isDebugEnabled()) {
- log.debug("Received SSH_FXP_UNBLOCK (handle={}, offset={}, length={})",
- new Object[] { handle, Long.valueOf(offset), Long.valueOf(length) });
- }
-
try {
Handle p = handles.get(handle);
+ if (log.isDebugEnabled()) {
+ log.debug("Received SSH_FXP_UNBLOCK (handle={}[{}], offset={}, length={})",
+ handle, p, Long.valueOf(offset), Long.valueOf(length));
+ }
+
if (!(p instanceof FileHandle)) {
sendStatus(id, SSH_FX_INVALID_HANDLE, handle);
return;
}
+
FileHandle fileHandle = (FileHandle) p;
boolean found = fileHandle.unlock(offset, length);
sendStatus(id, found ? SSH_FX_OK : SSH_FX_NO_MATCHING_BYTE_RANGE_LOCK, "");
@@ -690,7 +692,7 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
boolean symLink = buffer.getBoolean();
if (log.isDebugEnabled()) {
log.debug("Received SSH_FXP_LINK (linkpath={}, targetpath={}, symlink={})",
- new Object[] { linkpath, targetpath, Boolean.valueOf(symLink) });
+ linkpath, targetpath, Boolean.valueOf(symLink));
}
try {
@@ -748,8 +750,9 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
}
if (log.isDebugEnabled()) {
log.debug("Received SSH_FXP_RENAME (oldPath={}, newPath={}, flags=0x{})",
- new Object[] { oldPath, newPath, Integer.toHexString(flags) });
+ oldPath, newPath, Integer.toHexString(flags));
}
+
try {
List<CopyOption> opts = new ArrayList<>();
if ((flags & SSH_FXP_RENAME_ATOMIC) != 0) {
@@ -774,7 +777,7 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
flags = buffer.getInt();
}
if (log.isDebugEnabled()) {
- log.debug("Received SSH_FXP_STAT (path={}, flags={})", path, "0x" + Integer.toHexString(flags));
+ log.debug("Received SSH_FXP_STAT (path={}, flags=0x{})", path, Integer.toHexString(flags));
}
try {
Path p = resolveFile(path);
@@ -877,7 +880,7 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
String path = buffer.getString();
Map<String, Object> attrs = readAttrs(buffer);
- log.debug("Received SSH_FXP_MKDIR (path={})", path);
+ log.debug("Received SSH_FXP_MKDIR (path={}, attrs={})", path, attrs);
// attrs
try {
Path p = resolveFile(path);
@@ -927,8 +930,9 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
protected void doReadDir(Buffer buffer, int id) throws IOException {
String handle = buffer.getString();
- log.debug("Received SSH_FXP_READDIR (handle={})", handle);
Handle p = handles.get(handle);
+ log.debug("Received SSH_FXP_READDIR (handle={}[{}])", handle, p);
+
try {
if (!(p instanceof DirectoryHandle)) {
sendStatus(id, SSH_FX_INVALID_HANDLE, handle);
@@ -1041,7 +1045,7 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
flags = buffer.getInt();
}
if (log.isDebugEnabled()) {
- log.debug("Received SSH_FXP_FSTAT (handle={}, flags={})", handle, "0x" + Integer.toHexString(flags));
+ log.debug("Received SSH_FXP_FSTAT (handle={}, flags=0x{})", handle, Integer.toHexString(flags));
}
try {
Handle p = handles.get(handle);
@@ -1062,7 +1066,7 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
flags = buffer.getInt();
}
if (log.isDebugEnabled()) {
- log.debug("Received SSH_FXP_LSTAT (path={}, flags={})", path, "0x" + Integer.toHexString(flags));
+ log.debug("Received SSH_FXP_LSTAT (path={}, flags=0x{})", path, Integer.toHexString(flags));
}
try {
Path p = resolveFile(path);
@@ -1077,19 +1081,23 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
long offset = buffer.getLong();
int length = buffer.getInt();
if (length < 0) {
- throw new IllegalStateException();
+ throw new IllegalStateException("Bad length (" + length + ") for writing to " + handle);
}
- if (buffer.available() < length) {
- throw new BufferUnderflowException();
+
+ int remaining = buffer.available();
+ if (remaining < length) {
+ throw new IllegalStateException("Not enough buffer data for writing to " + handle + ": required=" + length + ", available=" + remaining);
}
+
byte[] data = buffer.array();
int doff = buffer.rpos();
- if (log.isDebugEnabled()) {
- log.debug("Received SSH_FXP_WRITE (handle={}, offset={}, data=byte[{}])",
- new Object[] { handle, Long.valueOf(offset), Integer.valueOf(length) });
- }
try {
Handle p = handles.get(handle);
+ if (log.isDebugEnabled()) {
+ log.debug("Received SSH_FXP_WRITE (handle={}[{}], offset={}, data=byte[{}])",
+ handle, p, Long.valueOf(offset), Integer.valueOf(length));
+ }
+
if (!(p instanceof FileHandle)) {
sendStatus(id, SSH_FX_INVALID_HANDLE, handle);
} else {
@@ -1106,12 +1114,13 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
String handle = buffer.getString();
long offset = buffer.getLong();
int len = buffer.getInt();
- if (log.isDebugEnabled()) {
- log.debug("Received SSH_FXP_READ (handle={}, offset={}, length={})",
- new Object[]{handle, Long.valueOf(offset), Integer.valueOf(len) });
- }
try {
Handle p = handles.get(handle);
+ if (log.isDebugEnabled()) {
+ log.debug("Received SSH_FXP_READ (handle={}[{}], offset={}, length={})",
+ handle, p, Long.valueOf(offset), Integer.valueOf(len));
+ }
+
if (!(p instanceof FileHandle)) {
sendStatus(id, SSH_FX_INVALID_HANDLE, handle);
} else {
@@ -1138,9 +1147,9 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
protected void doClose(Buffer buffer, int id) throws IOException {
String handle = buffer.getString();
- log.debug("Received SSH_FXP_CLOSE (handle={})", handle);
try {
Handle h = handles.get(handle);
+ log.debug("Received SSH_FXP_CLOSE (handle={}[{}])", handle, h);
if (h == null) {
sendStatus(id, SSH_FX_INVALID_HANDLE, handle, "");
} else {
@@ -1154,9 +1163,10 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
}
protected void doOpen(Buffer buffer, int id) throws IOException {
+ int curHandleCount = handles.size();
int maxHandleCount = FactoryManagerUtils.getIntProperty(session, MAX_OPEN_HANDLES_PER_SESSION, Integer.MAX_VALUE);
- if (handles.size() > maxHandleCount) {
- sendStatus(id, SSH_FX_FAILURE, "Too many open handles");
+ if (curHandleCount > maxHandleCount) {
+ sendStatus(id, SSH_FX_FAILURE, "Too many open handles: current=" + curHandleCount + ", max.=" + maxHandleCount);
return;
}
@@ -1170,16 +1180,16 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
int flags = pflags;
pflags = 0;
switch (flags & (SSH_FXF_READ | SSH_FXF_WRITE)) {
- case SSH_FXF_READ:
- access |= ACE4_READ_DATA | ACE4_READ_ATTRIBUTES;
- break;
- case SSH_FXF_WRITE:
- access |= ACE4_WRITE_DATA | ACE4_WRITE_ATTRIBUTES;
- break;
- default:
- access |= ACE4_READ_DATA | ACE4_READ_ATTRIBUTES;
- access |= ACE4_WRITE_DATA | ACE4_WRITE_ATTRIBUTES;
- break;
+ case SSH_FXF_READ:
+ access |= ACE4_READ_DATA | ACE4_READ_ATTRIBUTES;
+ break;
+ case SSH_FXF_WRITE:
+ access |= ACE4_WRITE_DATA | ACE4_WRITE_ATTRIBUTES;
+ break;
+ default:
+ access |= ACE4_READ_DATA | ACE4_READ_ATTRIBUTES;
+ access |= ACE4_WRITE_DATA | ACE4_WRITE_ATTRIBUTES;
+ break;
}
if ((flags & SSH_FXF_APPEND) != 0) {
access |= ACE4_APPEND_DATA;
@@ -1204,7 +1214,7 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
Map<String, Object> attrs = readAttrs(buffer);
if (log.isDebugEnabled()) {
log.debug("Received SSH_FXP_OPEN (path={}, access=0x{}, pflags=0x{}, attrs={})",
- new Object[]{path, Integer.toHexString(access), Integer.toHexString(pflags), attrs});
+ path, Integer.toHexString(access), Integer.toHexString(pflags), attrs);
}
try {
Path file = resolveFile(path);
@@ -1493,34 +1503,34 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
if (perms != null) {
for (PosixFilePermission p : perms) {
switch (p) {
- case OWNER_READ:
- pf |= S_IRUSR;
- break;
- case OWNER_WRITE:
- pf |= S_IWUSR;
- break;
- case OWNER_EXECUTE:
- pf |= S_IXUSR;
- break;
- case GROUP_READ:
- pf |= S_IRGRP;
- break;
- case GROUP_WRITE:
- pf |= S_IWGRP;
- break;
- case GROUP_EXECUTE:
- pf |= S_IXGRP;
- break;
- case OTHERS_READ:
- pf |= S_IROTH;
- break;
- case OTHERS_WRITE:
- pf |= S_IWOTH;
- break;
- case OTHERS_EXECUTE:
- pf |= S_IXOTH;
- break;
- default: // ignored
+ case OWNER_READ:
+ pf |= S_IRUSR;
+ break;
+ case OWNER_WRITE:
+ pf |= S_IWUSR;
+ break;
+ case OWNER_EXECUTE:
+ pf |= S_IXUSR;
+ break;
+ case GROUP_READ:
+ pf |= S_IRGRP;
+ break;
+ case GROUP_WRITE:
+ pf |= S_IWGRP;
+ break;
+ case GROUP_EXECUTE:
+ pf |= S_IXGRP;
+ break;
+ case OTHERS_READ:
+ pf |= S_IROTH;
+ break;
+ case OTHERS_WRITE:
+ pf |= S_IWOTH;
+ break;
+ case OTHERS_EXECUTE:
+ pf |= S_IXOTH;
+ break;
+ default: // ignored
}
}
}
@@ -1715,47 +1725,47 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
String view = null;
Object value = attributes.get(attribute);
switch (attribute) {
- case "size": {
- long newSize = ((Number) value).longValue();
- try (FileChannel channel = FileChannel.open(file, StandardOpenOption.WRITE)) {
- channel.truncate(newSize);
- }
- continue;
- }
- case "uid":
- view = "unix";
- break;
- case "gid":
- view = "unix";
- break;
- case "owner":
- view = "posix";
- value = toUser(file, (UserPrincipal) value);
- break;
- case "group":
- view = "posix";
- value = toGroup(file, (GroupPrincipal) value);
- break;
- case "permissions":
- if (OsUtils.isWin32()) {
- @SuppressWarnings("unchecked")
- Collection<PosixFilePermission> perms = (Collection<PosixFilePermission>) value;
- IoUtils.setPermissionsToFile(file.toFile(), perms);
+ case "size": {
+ long newSize = ((Number) value).longValue();
+ try (FileChannel channel = FileChannel.open(file, StandardOpenOption.WRITE)) {
+ channel.truncate(newSize);
+ }
continue;
}
- view = "posix";
- break;
-
- case "creationTime":
- view = "basic";
- break;
- case "lastModifiedTime":
- view = "basic";
- break;
- case "lastAccessTime":
- view = "basic";
- break;
- default: // ignored
+ case "uid":
+ view = "unix";
+ break;
+ case "gid":
+ view = "unix";
+ break;
+ case "owner":
+ view = "posix";
+ value = toUser(file, (UserPrincipal) value);
+ break;
+ case "group":
+ view = "posix";
+ value = toGroup(file, (GroupPrincipal) value);
+ break;
+ case "permissions":
+ if (OsUtils.isWin32()) {
+ @SuppressWarnings("unchecked")
+ Collection<PosixFilePermission> perms = (Collection<PosixFilePermission>) value;
+ IoUtils.setPermissionsToFile(file.toFile(), perms);
+ continue;
+ }
+ view = "posix";
+ break;
+
+ case "creationTime":
+ view = "basic";
+ break;
+ case "lastModifiedTime":
+ view = "basic";
+ break;
+ case "lastAccessTime":
+ view = "basic";
+ break;
+ default: // ignored
}
if (view != null && value != null) {
try {
@@ -1873,19 +1883,19 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
if (version >= SFTP_V4) {
byte type = buffer.getByte();
switch (type) {
- case SSH_FILEXFER_TYPE_REGULAR:
- attrs.put("isRegular", Boolean.TRUE);
- break;
- case SSH_FILEXFER_TYPE_DIRECTORY:
- attrs.put("isDirectory", Boolean.TRUE);
- break;
- case SSH_FILEXFER_TYPE_SYMLINK:
- attrs.put("isSymbolicLink", Boolean.TRUE);
- break;
- case SSH_FILEXFER_TYPE_UNKNOWN:
- attrs.put("isOther", Boolean.TRUE);
- break;
- default: // ignored
+ case SSH_FILEXFER_TYPE_REGULAR:
+ attrs.put("isRegular", Boolean.TRUE);
+ break;
+ case SSH_FILEXFER_TYPE_DIRECTORY:
+ attrs.put("isDirectory", Boolean.TRUE);
+ break;
+ case SSH_FILEXFER_TYPE_SYMLINK:
+ attrs.put("isSymbolicLink", Boolean.TRUE);
+ break;
+ case SSH_FILEXFER_TYPE_UNKNOWN:
+ attrs.put("isOther", Boolean.TRUE);
+ break;
+ default: // ignored
}
}
if ((flags & SSH_FILEXFER_ATTR_SIZE) != 0) {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/df8324bc/sshd-core/src/test/java/org/apache/sshd/common/kex/AbstractDHTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/kex/AbstractDHTest.java b/sshd-core/src/test/java/org/apache/sshd/common/kex/AbstractDHTest.java
new file mode 100644
index 0000000..22b61c2
--- /dev/null
+++ b/sshd-core/src/test/java/org/apache/sshd/common/kex/AbstractDHTest.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.kex;
+
+import java.util.Arrays;
+
+import org.apache.sshd.util.BaseTestSupport;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class AbstractDHTest extends BaseTestSupport {
+ public AbstractDHTest() {
+ super();
+ }
+
+ @Test
+ public void testStripLeadingZeroes() {
+ byte[] data = { 3, 7, 7, 3, 4, 7 };
+ for (int index = 1; index <= data.length; index++) {
+ assertSame("Unexpected sub-array generation for " + Arrays.toString(data), data, AbstractDH.stripLeadingZeroes(data));
+ if (index < data.length) {
+ data[index] = 0;
+ }
+ }
+
+ Arrays.fill(data, (byte) 0);
+ try {
+ byte[] stripped = AbstractDH.stripLeadingZeroes(data);
+ fail("Unexpected success for all zeroes data: " + Arrays.toString(stripped));
+ } catch(IllegalArgumentException expected) {
+ // ignored
+ }
+
+ for (int index = data.length - 1; index > 0; index--) {
+ data[index] = (byte) index;
+
+ byte[] stripped = AbstractDH.stripLeadingZeroes(data);
+ String ds = Arrays.toString(data), ss = Arrays.toString(stripped);
+ assertEquals("Mismatched stripped (" + ss + ") length for " + ds, data.length - index, stripped.length);
+ for (int i=index, j=0; j < stripped.length; i++, j++) {
+ if (data[i] != stripped[j]) {
+ fail("Mismatched values at stripped index = " + j + ": data=" + ds + ", stripped=" + ss);
+ }
+ }
+ }
+
+ }
+}