Compare commits

..

33 Commits

Author SHA1 Message Date
Shikhar Bhushan
be11cbb848 [maven-release-plugin] prepare release v0.6.0 2011-09-26 12:41:17 +01:00
Shikhar Bhushan
43b0599e1f let's make next release sshj 0.6.0 2011-09-26 12:37:21 +01:00
Shikhar Bhushan
b218186cae Merge pull request #34 from hierynomus/scp-filter-copy
Added upload filter capability to SCPUploadClient
2011-09-26 04:11:24 -07:00
hierynomus
184236c3d5 Added upload filter capability to SCPUploadClient 2011-09-26 11:49:07 +02:00
Shikhar Bhushan
cb1d773659 Merge branch 'master' of github.com:shikhar/sshj 2011-09-14 23:06:05 +01:00
Shikhar Bhushan
378665cb46 update contrib 2011-09-14 23:37:31 +02:00
Shikhar Bhushan
a5272dc413 Merge branch 'master' of github.com:shikhar/sshj 2011-09-14 22:11:29 +01:00
Shikhar Bhushan
60552fd001 Merge pull request #31 from hierynomus/filemode-typemask
Fixed bug in SFTP FileMode for AIX/Unix directory mask
2011-09-14 11:43:59 -07:00
hierynomus
ef082c668a Fixed bug in SFTP FileMode for AIX/Unix directory mask 2011-09-14 11:02:35 +02:00
Shikhar Bhushan
e66386eb1c Local window exhaustion -> ConnectionException 2011-09-07 21:45:44 +01:00
Shikhar Bhushan
0937ec9800 minor 2011-09-07 21:24:49 +01:00
Shikhar Bhushan
4b2f42804e Added version in pom.xml for maven-bundle-plugin 2011-08-29 16:49:49 +01:00
Shikhar Bhushan
01765d24d2 AbstractChannel - no reason for channel request response events to share the same underlying lock object. #27 2011-08-29 16:45:12 +01:00
Shikhar Bhushan
1a2351c5ee AbstractChannel - make chanReqResponseEvents a ConcurrentLinkedQueue, so don't have to have sendChannelRequest() & gotResponse() as synchronized methods. #27 2011-08-29 16:41:27 +01:00
Shikhar Bhushan
1cec011401 chown / chmod / chgrp in StatefulSFTPClient -- these all delegate to setattr which is overriden in StatefulSFTPClient to do cwdification. #28 2011-08-29 16:21:10 +01:00
Shikhar Bhushan
52338c13cb Merge pull request #28 from neilprosser/master
StatefulSFTPClient doesn't cwdify all commands
2011-08-27 04:23:07 -07:00
Neil Prosser
09cf21f61a Some stateful methods that needed cwdifying 2011-08-27 00:30:20 +01:00
Shikhar Bhushan
04c2e7b6b8 Client version string update 2011-07-27 19:52:27 +01:00
Shikhar Bhushan
822f196dd8 update contrib 2011-07-27 19:38:56 +01:00
Shikhar Bhushan
a88a574b10 [maven-release-plugin] prepare for next development iteration 2011-07-27 19:33:32 +01:00
Shikhar Bhushan
5cd6986355 [maven-release-plugin] prepare release v0.5.0 2011-07-27 19:33:26 +01:00
Shikhar Bhushan
b5d206bbcb Merge pull request #22 from iocanel/master
OSGi bundle for sshj
2011-07-25 12:22:43 -07:00
Ioannis Canellos
4eae26c551 OSGi-fied sshj 2011-07-25 06:29:20 -07:00
Shikhar Bhushan
b950f88f52 SSHClient implements Closeable 2011-07-24 20:50:01 +01:00
Shikhar Bhushan
3267860db4 mass auto-format 2011-07-24 20:48:00 +01:00
Shikhar Bhushan
d6eb5a040e Non-final ChannelOutputStream field may be null if we haven't received channel open confirmation or channel open failed. So do null-check. 2011-07-16 10:19:46 +01:00
Shikhar Bhushan
21da5b9f65 update contributor list 2011-07-03 14:50:43 -07:00
Shikhar Bhushan
6b66a952d4 Session#changeWindowDimensions was broken, wrong channel request.
Fix for #21
2011-07-03 10:59:40 +01:00
Shikhar Bhushan
aa4faf3f25 Merge pull request #20 from cloudera/forUpstream
Don't leak PrivateKeyStringResource private keys via toString()
2011-06-23 13:46:37 -07:00
Adar Dembo
4be02450dd Don't leak PrivateKeyStringResource private keys via toString() 2011-06-22 17:52:46 -07:00
Shikhar Bhushan
0cec27c28e Edited README.rst via GitHub 2011-06-20 11:44:56 -07:00
Shikhar Bhushan
4384367a1b point to issue tracker 2011-06-20 11:43:21 -07:00
Shikhar Bhushan
4549648a76 [maven-release-plugin] prepare for next development iteration 2011-06-19 18:32:36 +01:00
75 changed files with 428 additions and 218 deletions

View File

@@ -1,4 +1,8 @@
Shikhar Bhushan <shikhar@schmizz.net>
Cyril Ledru <cledru@keynectis.net>
Incendium <incendium@gmail.com>
Philip Langdale <philipl@cloudera.com>
Philip Langdale <philipl@cloudera.com>
Adar Dembo <adar@cloudera.com>
Ioannis Canellos <iocanel@gmail.com>
Neil Prosser <neil.prosser@gmail.com>
hierynomus <jeroen@hierynomus.com>

View File

@@ -39,6 +39,11 @@ Dependencies
Java 6+. slf4j_ is required. bouncycastle_ is highly recommended and required for using some of the crypto algorithms. jzlib_ is required for using zlib compression.
Bugs, questions
----------------
`Issue tracker <https://github.com/shikhar/sshj/issues>`_
Contributing
------------

29
pom.xml
View File

@@ -5,8 +5,8 @@
<groupId>net.schmizz</groupId>
<artifactId>sshj</artifactId>
<packaging>jar</packaging>
<version>0.4.1</version>
<packaging>bundle</packaging>
<version>0.6.0</version>
<name>sshj</name>
<description>SSHv2 library for Java</description>
@@ -75,6 +75,12 @@
<version>0.9.29</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.0-rc1</version>
<scope>test</scope>
</dependency>
</dependencies>
@@ -160,6 +166,25 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.3.5</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Import-Package>
!net.schmizz.*,
javax.crypto*,
com.jcraft.jzlib*;version="[1.0,2)",
org.slf4j*;version="[1.6,2)",
org.bouncycastle*;version="[1.4,2)",
*
</Import-Package>
<Export-Package>net.schmizz.*</Export-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>

View File

@@ -42,7 +42,7 @@ public class LocalPF {
* google.com:80
*/
ssh.newLocalPortForwarder(new InetSocketAddress("localhost", 8080), "google.com", 80)
.listen();
.listen();
} finally {
ssh.disconnect();

View File

@@ -30,12 +30,12 @@ public class ErrorDeliveryUtil {
}
public static void alertEvents(Throwable x, Event... events) {
for (Event e: events)
for (Event e : events)
e.deliverError(x);
}
public static void alertEvents(Throwable x, Collection<? extends Event> events) {
for (Event e: events)
for (Event e : events)
e.deliverError(x);
}

View File

@@ -18,7 +18,8 @@ package net.schmizz.sshj;
import net.schmizz.sshj.transport.random.JCERandom;
import net.schmizz.sshj.transport.random.SingletonRandomFactory;
public class AndroidConfig extends DefaultConfig {
public class AndroidConfig
extends DefaultConfig {
@Override
protected void initRandomFactory(boolean ignored) {

View File

@@ -31,6 +31,7 @@ import java.util.List;
* {@link Compression}, {@link MAC}, {@link Signature}, {@link Random}, and {@link FileKeyProvider}.
*/
public interface Config {
/**
* Retrieve the list of named factories for {@code Cipher}.
*

View File

@@ -91,7 +91,7 @@ public class DefaultConfig
private final Logger log = LoggerFactory.getLogger(getClass());
private static final String VERSION = "SSHJ_0_4_1";
private static final String VERSION = "SSHJ_0_6_0";
public DefaultConfig() {
setVersion(VERSION);
@@ -137,7 +137,7 @@ public class DefaultConfig
boolean warn = false;
// Ref. https://issues.apache.org/jira/browse/SSHD-24
// "AES256 and AES192 requires unlimited cryptography extension"
for (Iterator<Factory.Named<Cipher>> i = avail.iterator(); i.hasNext();) {
for (Iterator<Factory.Named<Cipher>> i = avail.iterator(); i.hasNext(); ) {
final Factory.Named<Cipher> f = i.next();
try {
final Cipher c = f.create();

View File

@@ -16,7 +16,6 @@
package net.schmizz.sshj;
import net.schmizz.sshj.common.DisconnectReason;
import net.schmizz.sshj.common.Factory;
import net.schmizz.sshj.common.SSHException;
import net.schmizz.sshj.common.SecurityUtils;
@@ -50,7 +49,6 @@ import net.schmizz.sshj.userauth.keyprovider.FileKeyProvider;
import net.schmizz.sshj.userauth.keyprovider.KeyPairWrapper;
import net.schmizz.sshj.userauth.keyprovider.KeyProvider;
import net.schmizz.sshj.userauth.keyprovider.KeyProviderUtil;
import net.schmizz.sshj.userauth.keyprovider.OpenSSHKeyFile;
import net.schmizz.sshj.userauth.method.AuthKeyboardInteractive;
import net.schmizz.sshj.userauth.method.AuthMethod;
import net.schmizz.sshj.userauth.method.AuthPassword;
@@ -63,10 +61,9 @@ import net.schmizz.sshj.xfer.scp.SCPFileTransfer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.net.SocketAddress;
import java.security.KeyPair;
import java.security.PublicKey;
@@ -116,7 +113,7 @@ import java.util.List;
*/
public class SSHClient
extends SocketClient
implements SessionFactory {
implements Closeable, SessionFactory {
/** Default port for SSH */
public static final int DEFAULT_PORT = 22;
@@ -444,7 +441,7 @@ public class SSHClient
/**
* Utility function for createing a {@link KeyProvider} instance from given location on the file system. Creates a
* one-off {@link PasswordFinder} using {@link PasswordUtils#createOneOff(char[])}, and calls {@link
* #loadKeys(String,PasswordFinder)}.
* #loadKeys(String, PasswordFinder)}.
*
* @param location location of the key file
* @param passphrase passphrase as a char-array
@@ -505,8 +502,8 @@ public class SSHClient
}
/**
* Creates a {@link KeyProvider} instance from passed strings. Currently only PKCS8 format
* private key files are supported (OpenSSH uses this format).
* Creates a {@link KeyProvider} instance from passed strings. Currently only PKCS8 format private key files are
* supported (OpenSSH uses this format).
* <p/>
*
* @param privateKey the private key as a string
@@ -691,4 +688,15 @@ public class SSHClient
log.info("Key exchange took {} seconds", (System.currentTimeMillis() - start) / 1000.0);
}
/**
* Same as {@link #disconnect()}.
*
* @throws IOException
*/
@Override
public void close()
throws IOException {
disconnect();
}
}

View File

@@ -32,7 +32,8 @@ public class Base64 {
* @see Base64
* @since 1.3
*/
public static class InputStream extends java.io.FilterInputStream {
public static class InputStream
extends java.io.FilterInputStream {
private final boolean encode; // Encoding or decoding
private int position; // Current position in the buffer
@@ -99,7 +100,8 @@ public class Base64 {
* @since 1.3
*/
@Override
public int read() throws java.io.IOException {
public int read()
throws java.io.IOException {
// Do we need to get data?
if (position < 0)
@@ -197,7 +199,8 @@ public class Base64 {
* @since 1.3
*/
@Override
public int read(byte[] dest, int off, int len) throws java.io.IOException {
public int read(byte[] dest, int off, int len)
throws java.io.IOException {
int i;
int b;
for (i = 0; i < len; i++) {
@@ -222,7 +225,8 @@ public class Base64 {
* @see Base64
* @since 1.3
*/
public static class OutputStream extends java.io.FilterOutputStream {
public static class OutputStream
extends java.io.FilterOutputStream {
private final boolean encode;
private int position;
@@ -289,7 +293,8 @@ public class Base64 {
* @since 1.3
*/
@Override
public void close() throws java.io.IOException {
public void close()
throws java.io.IOException {
// 1. Ensure that pending characters are written
flush();
@@ -308,7 +313,8 @@ public class Base64 {
* @since 2.3
*/
@Override
public void flush() throws java.io.IOException {
public void flush()
throws java.io.IOException {
flushBase64();
super.flush();
}
@@ -318,7 +324,8 @@ public class Base64 {
*
* @throws java.io.IOException if there's an error.
*/
public void flushBase64() throws java.io.IOException {
public void flushBase64()
throws java.io.IOException {
if (position > 0)
if (encode) {
out.write(encode3to4(b4, buffer, position, options));
@@ -346,7 +353,8 @@ public class Base64 {
* @throws java.io.IOException if there's an error flushing
* @since 1.5.1
*/
public void suspendEncoding() throws java.io.IOException {
public void suspendEncoding()
throws java.io.IOException {
flushBase64();
suspendEncoding = true;
} // end suspendEncoding
@@ -361,7 +369,8 @@ public class Base64 {
* @since 1.3
*/
@Override
public void write(byte[] theBytes, int off, int len) throws java.io.IOException {
public void write(byte[] theBytes, int off, int len)
throws java.io.IOException {
// Encoding suspended?
if (suspendEncoding) {
super.out.write(theBytes, off, len);
@@ -383,7 +392,8 @@ public class Base64 {
* @since 1.3
*/
@Override
public void write(int theByte) throws java.io.IOException {
public void write(int theByte)
throws java.io.IOException {
// Encoding suspended?
if (suspendEncoding) {
super.out.write(theByte);
@@ -673,7 +683,8 @@ public class Base64 {
* @throws java.io.IOException If bogus characters exist in source data
* @since 1.3
*/
public static byte[] decode(byte[] source, int off, int len, int options) throws java.io.IOException {
public static byte[] decode(byte[] source, int off, int len, int options)
throws java.io.IOException {
// Lots of error checking and exception throwing
if (source == null)
@@ -725,7 +736,7 @@ public class Base64 {
else
// There's a bad input character in the Base64 stream.
throw new java.io.IOException(String.format("Bad Base64 input character '%c' in array position %d",
source[i], i));
source[i], i));
} // each input character
byte[] out = new byte[outBuffPosn];
@@ -743,7 +754,8 @@ public class Base64 {
* @throws java.io.IOException If there is a problem
* @since 1.4
*/
public static byte[] decode(String s) throws java.io.IOException {
public static byte[] decode(String s)
throws java.io.IOException {
return decode(s, NO_OPTIONS);
}
@@ -759,7 +771,8 @@ public class Base64 {
* @throws NullPointerException if <tt>s</tt> is null
* @since 1.4
*/
public static byte[] decode(String s, int options) throws java.io.IOException {
public static byte[] decode(String s, int options)
throws java.io.IOException {
if (s == null)
throw new NullPointerException("Input string was null.");
@@ -833,7 +846,8 @@ public class Base64 {
* @throws java.io.IOException if there is an error
* @since 2.2
*/
public static void decodeFileToFile(String infile, String outfile) throws java.io.IOException {
public static void decodeFileToFile(String infile, String outfile)
throws java.io.IOException {
byte[] decoded = Base64.decodeFromFile(infile);
java.io.OutputStream out = null;
@@ -864,7 +878,8 @@ public class Base64 {
* @throws java.io.IOException if there is an error
* @since 2.1
*/
public static byte[] decodeFromFile(String filename) throws java.io.IOException {
public static byte[] decodeFromFile(String filename)
throws java.io.IOException {
byte[] decodedData = null;
Base64.InputStream bis = null;
@@ -878,12 +893,12 @@ public class Base64 {
// Check for size of file
if (file.length() > Integer.MAX_VALUE)
throw new java.io.IOException("File is too big for this convenience method (" + file.length()
+ " bytes).");
+ " bytes).");
buffer = new byte[(int) file.length()];
// Open a stream
bis = new Base64.InputStream(new java.io.BufferedInputStream(new java.io.FileInputStream(file)),
Base64.DECODE);
Base64.DECODE);
// Read until done
while ((numBytes = bis.read(buffer, length, 4096)) >= 0)
@@ -918,7 +933,8 @@ public class Base64 {
* @throws java.io.IOException if there is an error
* @since 2.1
*/
public static void decodeToFile(String dataToDecode, String filename) throws java.io.IOException {
public static void decodeToFile(String dataToDecode, String filename)
throws java.io.IOException {
Base64.OutputStream bos = null;
try {
@@ -950,8 +966,9 @@ public class Base64 {
* @throws ClassNotFoundException if the decoded object is of a class that cannot be found by the JVM
* @since 1.5
*/
public static Object decodeToObject(String encodedObject) throws java.io.IOException,
java.lang.ClassNotFoundException {
public static Object decodeToObject(String encodedObject)
throws java.io.IOException,
java.lang.ClassNotFoundException {
// Decode and gunzip if necessary
byte[] objBytes = decode(encodedObject);
@@ -1078,7 +1095,8 @@ public class Base64 {
* @see Base64#DO_BREAK_LINES
* @since 2.0
*/
public static String encodeBytes(byte[] source, int options) throws java.io.IOException {
public static String encodeBytes(byte[] source, int options)
throws java.io.IOException {
return encodeBytes(source, 0, source.length, options);
} // end encodeBytes
@@ -1137,7 +1155,8 @@ public class Base64 {
* @see Base64#DO_BREAK_LINES
* @since 2.0
*/
public static String encodeBytes(byte[] source, int off, int len, int options) throws java.io.IOException {
public static String encodeBytes(byte[] source, int off, int len, int options)
throws java.io.IOException {
byte[] encoded = encodeBytesToBytes(source, off, len, options);
// Return value according to relevant encoding.
@@ -1189,7 +1208,8 @@ public class Base64 {
* @see Base64#DO_BREAK_LINES
* @since 2.3.1
*/
public static byte[] encodeBytesToBytes(byte[] source, int off, int len, int options) throws java.io.IOException {
public static byte[] encodeBytesToBytes(byte[] source, int off, int len, int options)
throws java.io.IOException {
if (source == null)
throw new NullPointerException("Cannot serialize a null array.");
@@ -1302,7 +1322,8 @@ public class Base64 {
* @throws java.io.IOException if there is an error
* @since 2.2
*/
public static void encodeFileToFile(String infile, String outfile) throws java.io.IOException {
public static void encodeFileToFile(String infile, String outfile)
throws java.io.IOException {
String encoded = Base64.encodeFromFile(infile);
java.io.OutputStream out = null;
@@ -1333,7 +1354,8 @@ public class Base64 {
* @throws java.io.IOException if there is an error
* @since 2.1
*/
public static String encodeFromFile(String filename) throws java.io.IOException {
public static String encodeFromFile(String filename)
throws java.io.IOException {
String encodedData = null;
Base64.InputStream bis = null;
@@ -1348,7 +1370,7 @@ public class Base64 {
// Open a stream
bis = new Base64.InputStream(new java.io.BufferedInputStream(new java.io.FileInputStream(file)),
Base64.ENCODE);
Base64.ENCODE);
// Read until done
while ((numBytes = bis.read(buffer, length, 4096)) >= 0)
@@ -1387,7 +1409,8 @@ public class Base64 {
* @throws NullPointerException if serializedObject is null
* @since 1.4
*/
public static String encodeObject(java.io.Serializable serializableObject) throws java.io.IOException {
public static String encodeObject(java.io.Serializable serializableObject)
throws java.io.IOException {
return encodeObject(serializableObject, NO_OPTIONS);
} // end encodeObject
@@ -1420,7 +1443,8 @@ public class Base64 {
* @see Base64#DO_BREAK_LINES
* @since 2.0
*/
public static String encodeObject(java.io.Serializable serializableObject, int options) throws java.io.IOException {
public static String encodeObject(java.io.Serializable serializableObject, int options)
throws java.io.IOException {
if (serializableObject == null)
throw new NullPointerException("Cannot serialize a null object.");
@@ -1481,7 +1505,8 @@ public class Base64 {
* @throws NullPointerException if dataToEncode is null
* @since 2.1
*/
public static void encodeToFile(byte[] dataToEncode, String filename) throws java.io.IOException {
public static void encodeToFile(byte[] dataToEncode, String filename)
throws java.io.IOException {
if (dataToEncode == null)
throw new NullPointerException("Data to encode was null.");

View File

@@ -35,8 +35,6 @@
*/
package net.schmizz.sshj.common;
import java.util.Arrays;
/** Utility functions for byte arrays. */
public class ByteArrayUtils {

View File

@@ -22,6 +22,7 @@ public interface ErrorNotifiable {
/** Utility functions. */
class Util {
/** Notify all {@code notifiables} of given {@code error}. */
public static void alertAll(SSHException error, ErrorNotifiable... notifiables) {
for (ErrorNotifiable notifiable : notifiables)

View File

@@ -32,7 +32,6 @@ public enum KeyType {
/** SSH identifier for RSA keys */
RSA("ssh-rsa") {
@Override
public PublicKey readPubKeyFromBuffer(String type, Buffer<?> buf)
throws GeneralSecurityException {
@@ -64,7 +63,6 @@ public enum KeyType {
/** SSH identifier for DSA keys */
DSA("ssh-dss") {
@Override
public PublicKey readPubKeyFromBuffer(String type, Buffer<?> buf)
throws GeneralSecurityException {
@@ -100,7 +98,6 @@ public enum KeyType {
/** Unrecognized */
UNKNOWN("unknown") {
@Override
public PublicKey readPubKeyFromBuffer(String type, Buffer<?> buf)
throws GeneralSecurityException {

View File

@@ -58,6 +58,7 @@ import java.security.Signature;
public class SecurityUtils {
private static class BouncyCastleRegistration {
public void run()
throws Exception {
if (java.security.Security.getProvider(BOUNCY_CASTLE) == null) {

View File

@@ -89,13 +89,13 @@ public interface Connection {
* @param wantReply whether a reply is requested
* @param specifics {@link SSHPacket} containing fields specific to the request
*
* @return a {@link net.schmizz.concurrent.Promise} for the reply data (in case {@code wantReply} is true) which allows waiting on the
* reply, or {@code null} if a reply is not requested.
* @return a {@link net.schmizz.concurrent.Promise} for the reply data (in case {@code wantReply} is true) which
* allows waiting on the reply, or {@code null} if a reply is not requested.
*
* @throws TransportException if there is an error sending the request
*/
public Promise<SSHPacket, ConnectionException> sendGlobalRequest(String name, boolean wantReply,
byte[] specifics)
byte[] specifics)
throws TransportException;
/**

View File

@@ -35,8 +35,8 @@
*/
package net.schmizz.sshj.connection.channel;
import net.schmizz.concurrent.Event;
import net.schmizz.concurrent.ErrorDeliveryUtil;
import net.schmizz.concurrent.Event;
import net.schmizz.sshj.common.Buffer;
import net.schmizz.sshj.common.ByteArrayUtils;
import net.schmizz.sshj.common.DisconnectReason;
@@ -53,8 +53,8 @@ import org.slf4j.LoggerFactory;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
@@ -76,7 +76,7 @@ public abstract class AbstractChannel
/** Remote recipient ID */
private int recipient;
private final Queue<Event<ConnectionException>> chanReqResponseEvents = new LinkedList<Event<ConnectionException>>();
private final Queue<Event<ConnectionException>> chanReqResponseEvents = new ConcurrentLinkedQueue<Event<ConnectionException>>();
/* The lock used by to create the open & close events */
private final ReentrantLock lock = new ReentrantLock();
@@ -240,7 +240,8 @@ public abstract class AbstractChannel
ErrorDeliveryUtil.alertEvents(error, chanReqResponseEvents);
in.notifyError(error);
out.notifyError(error);
if (out != null)
out.notifyError(error);
finishOff();
}
@@ -312,7 +313,8 @@ public abstract class AbstractChannel
handleRequest(reqType, buf);
}
private void gotWindowAdjustment(SSHPacket buf) throws ConnectionException {
private void gotWindowAdjustment(SSHPacket buf)
throws ConnectionException {
final int howMuch;
try {
howMuch = buf.readUInt32AsInt();
@@ -362,8 +364,8 @@ public abstract class AbstractChannel
stream.receive(buf.array(), buf.rpos(), len);
}
protected synchronized Event<ConnectionException> sendChannelRequest(String reqType, boolean wantReply,
Buffer.PlainBuffer reqSpecific)
protected Event<ConnectionException> sendChannelRequest(String reqType, boolean wantReply,
Buffer.PlainBuffer reqSpecific)
throws TransportException {
log.info("Sending channel request for `{}`", reqType);
trans.write(
@@ -375,13 +377,14 @@ public abstract class AbstractChannel
Event<ConnectionException> responseEvent = null;
if (wantReply) {
responseEvent = new Event<ConnectionException>("chan#" + id + " / " + "chanreq for " + reqType, ConnectionException.chainer, lock);
responseEvent = new Event<ConnectionException>("chan#" + id + " / " + "chanreq for " + reqType,
ConnectionException.chainer);
chanReqResponseEvents.add(responseEvent);
}
return responseEvent;
}
private synchronized void gotResponse(boolean success)
private void gotResponse(boolean success)
throws ConnectionException {
final Event<ConnectionException> responseEvent = chanReqResponseEvents.poll();
if (responseEvent != null) {
@@ -390,9 +393,8 @@ public abstract class AbstractChannel
else
responseEvent.deliverError(new ConnectionException("Request failed"));
} else
throw new ConnectionException(
DisconnectReason.PROTOCOL_ERROR,
"Received response to channel request when none was requested");
throw new ConnectionException(DisconnectReason.PROTOCOL_ERROR,
"Received response to channel request when none was requested");
}
private synchronized void gotEOF()
@@ -428,7 +430,7 @@ public abstract class AbstractChannel
@Override
public String toString() {
return "< " + type + " channel: id=" + id + ", recipient=" + recipient + ", localWin=" + lwin + ", remoteWin="
+ rwin + " >";
+ rwin + " >";
}

View File

@@ -32,6 +32,7 @@ public interface Channel
/** Direct channels are those that are initiated by us. */
interface Direct
extends Channel {
/**
* Request opening this channel from remote end.
*

View File

@@ -116,7 +116,7 @@ public final class ChannelInputStream
public int read(byte[] b, int off, int len)
throws IOException {
synchronized (buf) {
for (; ;) {
for (; ; ) {
if (buf.available() > 0)
break;
if (eof)
@@ -163,7 +163,7 @@ public final class ChannelInputStream
if (adjustment > 0) {
log.info("Sending SSH_MSG_CHANNEL_WINDOW_ADJUST to #{} for {} bytes", chan.getRecipient(), adjustment);
trans.write(new SSHPacket(Message.CHANNEL_WINDOW_ADJUST)
.putUInt32(chan.getRecipient()).putUInt32(adjustment));
.putUInt32(chan.getRecipient()).putUInt32(adjustment));
win.expand(adjustment);
}
}

View File

@@ -43,8 +43,8 @@ public class SocketStreamCopyMonitor
}
public static void monitor(final int frequency, final TimeUnit unit,
final Event<IOException> x, final Event<IOException> y,
final Channel channel, final Socket socket) {
final Event<IOException> x, final Event<IOException> y,
final Channel channel, final Socket socket) {
new SocketStreamCopyMonitor(new Runnable() {
public void run() {
try {

View File

@@ -51,12 +51,13 @@ public abstract class Window {
return size;
}
public void consume(int dec) {
public void consume(int dec)
throws ConnectionException {
synchronized (lock) {
log.debug("Consuming by " + dec + " down to " + size);
size -= dec;
if (size < 0)
throw new SSHRuntimeException("Window consumed to below 0");
throw new ConnectionException("Window consumed to below 0");
}
}
@@ -88,6 +89,14 @@ public abstract class Window {
}
}
public void consume(int howMuch) {
try {
super.consume(howMuch);
} catch (ConnectionException e) {
throw new SSHRuntimeException(e);
}
}
}
/** Controls how much data remote end can send before an adjustment notification from us is required. */

View File

@@ -53,7 +53,7 @@ public class LocalPortForwarder {
.bufSize(getLocalMaxPacketSize())
.spawnDaemon("chan2soc");
SocketStreamCopyMonitor.monitor(5, TimeUnit.SECONDS, soc2chan, chan2soc, this, sock);
}
}
@Override
protected SSHPacket buildOpenReq() {

View File

@@ -82,10 +82,12 @@ public interface Session
throws TransportException;
@Deprecated
String getOutputAsString() throws IOException;
String getOutputAsString()
throws IOException;
@Deprecated
String getErrorAsString() throws IOException;
String getErrorAsString()
throws IOException;
}
@@ -132,6 +134,7 @@ public interface Session
/** Subsystem API. */
interface Subsystem
extends Channel {
Integer getExitStatus();
}

View File

@@ -104,7 +104,7 @@ public class SessionChannel
public void changeWindowDimensions(int cols, int rows, int width, int height)
throws TransportException {
sendChannelRequest(
"pty-req",
"window-change",
false,
new Buffer.PlainBuffer()
.putUInt32(cols)

View File

@@ -69,9 +69,9 @@ public abstract class AbstractForwardedChannel
// Must ensure channel is attached before confirming, data could start coming in immediately!
conn.attach(this);
trans.write(newBuffer(Message.CHANNEL_OPEN_CONFIRMATION)
.putUInt32(getID())
.putUInt32(getLocalWinSize())
.putUInt32(getLocalMaxPacketSize()));
.putUInt32(getID())
.putUInt32(getLocalWinSize())
.putUInt32(getLocalMaxPacketSize()));
open.set();
}

View File

@@ -39,18 +39,18 @@ public class RemotePortForwarder
* address (or domain name) and port on which connections for forwarding
* are to be accepted. Some strings used for 'address to bind' have
* special-case semantics.
* <p/>
*
* o &quot;&quot; means that connections are to be accepted on all protocol
* families supported by the SSH implementation.
* <p/>
*
* o &quot;0.0.0.0&quot; means to listen on all IPv4 addresses.
* <p/>
*
* o &quot;::&quot; means to listen on all IPv6 addresses.
* <p/>
*
* o &quot;localhost&quot; means to listen on all protocol families supported by
* the SSH implementation on loopback addresses only ([RFC3330] and
* [RFC3513]).
* <p/>
*
* o &quot;127.0.0.1&quot; and &quot;::1&quot; indicate listening on the loopback
* interfaces for IPv4 and IPv6, respectively.
* </pre>
@@ -198,9 +198,9 @@ public class RemotePortForwarder
protected SSHPacket req(String reqName, Forward forward)
throws ConnectionException, TransportException {
final byte[] specifics = new Buffer.PlainBuffer().putString(forward.address).putUInt32(forward.port)
.getCompactData();
.getCompactData();
return conn.sendGlobalRequest(reqName, true, specifics)
.retrieve(conn.getTimeout(), TimeUnit.SECONDS);
.retrieve(conn.getTimeout(), TimeUnit.SECONDS);
}
/** @return the active forwards. */
@@ -227,7 +227,7 @@ public class RemotePortForwarder
callListener(listeners.get(chan.getParentForward()), chan);
else
chan.reject(OpenFailException.Reason.ADMINISTRATIVELY_PROHIBITED, "Forwarding was not requested on `"
+ chan.getParentForward() + "`");
+ chan.getParentForward() + "`");
}
}

View File

@@ -74,7 +74,7 @@ public class FileMode {
}
public int getTypeMask() {
return mask & 0770000;
return mask & 0170000;
}
public int getPermissionsMask() {

View File

@@ -57,9 +57,9 @@ public class PacketReader
readIntoBuffer(lenBuf, 0, lenBuf.length);
return (int) (lenBuf[0] << 24 & 0xff000000L
| lenBuf[1] << 16 & 0x00ff0000L
| lenBuf[2] << 8 & 0x0000ff00L
| lenBuf[3] & 0x000000ffL);
| lenBuf[1] << 16 & 0x00ff0000L
| lenBuf[2] << 8 & 0x0000ff00L
| lenBuf[3] & 0x000000ffL);
}
public SFTPPacket<Response> readPacket()
@@ -97,7 +97,7 @@ public class PacketReader
log.debug("Received {} packet", resp.getType());
if (promise == null)
throw new SFTPException("Received [" + resp.readType() + "] response for request-id " + resp.getRequestID()
+ ", no such request was made");
+ ", no such request was made");
else
promise.deliver(resp);
}

View File

@@ -32,7 +32,7 @@ public class RemoteDirectory
throws IOException {
List<RemoteResourceInfo> rri = new LinkedList<RemoteResourceInfo>();
loop:
for (; ;) {
for (; ; ) {
Response res = requester.doRequest(newRequest(PacketType.READDIR));
switch (res.getType()) {

View File

@@ -39,8 +39,8 @@ public class RemoteFile
public FileAttributes fetchAttributes()
throws IOException {
return requester.doRequest(newRequest(PacketType.FSTAT))
.ensurePacketTypeIs(PacketType.ATTRS)
.readFileAttributes();
.ensurePacketTypeIs(PacketType.ATTRS)
.readFileAttributes();
}
public long length()
@@ -74,9 +74,9 @@ public class RemoteFile
public void write(long fileOffset, byte[] data, int off, int len)
throws IOException {
requester.doRequest(newRequest(PacketType.WRITE)
.putUInt64(fileOffset)
.putUInt32(len - off)
.putRawBytes(data, off, len)
.putUInt64(fileOffset)
.putUInt32(len - off)
.putRawBytes(data, off, len)
).ensureStatusPacketIsOK();
}
@@ -87,12 +87,12 @@ public class RemoteFile
public int getOutgoingPacketOverhead() {
return 1 + // packet type
4 + // request id
4 + // next length
handle.length() + // next
8 + // file offset
4 + // data length
4; // packet length
4 + // request id
4 + // next length
handle.length() + // next
8 + // file offset
4 + // data length
4; // packet length
}
public class RemoteFileOutputStream

View File

@@ -51,7 +51,8 @@ public class Response
private final PacketType type;
private final long reqID;
public Response(Buffer<Response> pk, int protocolVersion) throws SFTPException {
public Response(Buffer<Response> pk, int protocolVersion)
throws SFTPException {
super(pk);
this.protocolVersion = protocolVersion;
this.type = readType();
@@ -74,7 +75,8 @@ public class Response
return type;
}
public StatusCode readStatusCode() throws SFTPException {
public StatusCode readStatusCode()
throws SFTPException {
try {
return StatusCode.fromInt(readUInt32AsInt());
} catch (BufferException be) {

View File

@@ -56,7 +56,8 @@ public class SFTPEngine
this(ssh, PathHelper.DEFAULT_PATH_SEPARATOR);
}
public SFTPEngine(SessionFactory ssh, String pathSep) throws SSHException {
public SFTPEngine(SessionFactory ssh, String pathSep)
throws SSHException {
sub = ssh.startSession().startSubsystem("sftp");
out = sub.getOutputStream();
reader = new PacketReader(this);

View File

@@ -15,6 +15,9 @@
*/
package net.schmizz.sshj.sftp;
import net.schmizz.sshj.xfer.LocalDestFile;
import net.schmizz.sshj.xfer.LocalSourceFile;
import java.io.IOException;
import java.util.List;
import java.util.Set;
@@ -178,10 +181,22 @@ public class StatefulSFTPClient
super.get(cwdify(source), dest);
}
@Override
public void get(String source, LocalDestFile dest)
throws IOException {
super.get(cwdify(source), dest);
}
@Override
public void put(String source, String dest)
throws IOException {
super.put(source, cwdify(dest));
}
@Override
public void put(LocalSourceFile source, String dest)
throws IOException {
super.put(source, cwdify(dest));
}
}

View File

@@ -47,7 +47,7 @@ import net.schmizz.sshj.transport.mac.MAC;
* <p/>
* <pre>
* Each packet is in the following format:
* <p/>
*
* uint32 packet_length
* byte padding_length
* byte[n1] payload; n1 = packet_length - padding_length - 1

View File

@@ -88,7 +88,7 @@ final class Decoder
int need;
/* Decoding loop */
for (; ;)
for (; ; )
if (packetLength == -1) // Waiting for beginning of packet
{
@@ -124,7 +124,7 @@ final class Decoder
if (log.isTraceEnabled())
log.trace("Received packet #{}: {}", seq, plain.printHex());
packetHandler.handle(plain.readMessageID(), plain); // Process the decoded packet //
packetHandler.handle(plain.readMessageID(), plain); // Process the decoded packet
inputBuffer.clear();
packetLength = -1;

View File

@@ -92,15 +92,15 @@ public final class NegotiatedAlgorithms {
@Override
public String toString() {
return ("[ " + //
"kex=" + kex + "; " + //
"sig=" + sig + "; " + //
"c2sCipher=" + c2sCipher + "; " + //
"s2cCipher=" + s2cCipher + "; " + //
"c2sMAC=" + c2sMAC + "; " + //
"s2cMAC=" + s2cMAC + "; " + //
"c2sComp=" + c2sComp + "; " + //
"s2cComp=" + s2cComp + //
return ("[ " +
"kex=" + kex + "; " +
"sig=" + sig + "; " +
"c2sCipher=" + c2sCipher + "; " +
"s2cCipher=" + s2cCipher + "; " +
"c2sMAC=" + c2sMAC + "; " +
"s2cMAC=" + s2cMAC + "; " +
"c2sComp=" + c2sComp + "; " +
"s2cComp=" + s2cComp +
" ]");
}

View File

@@ -178,12 +178,14 @@ public interface Transport
*/
void join()
throws TransportException;
/**
* Joins the thread calling this method to the transport's death.
*
* @throws TransportException if the transport dies of an exception
*/
void join(int timeout, TimeUnit unit) throws TransportException;
void join(int timeout, TimeUnit unit)
throws TransportException;
/** Send a disconnection packet with reason as {@link DisconnectReason#BY_APPLICATION}, and closes this transport. */
void disconnect();
@@ -226,9 +228,7 @@ public interface Transport
*/
void setDisconnectListener(DisconnectListener listener);
/**
* @return the current disconnect listener.
*/
/** @return the current disconnect listener. */
DisconnectListener getDisconnectListener();
}

View File

@@ -35,8 +35,8 @@
*/
package net.schmizz.sshj.transport;
import net.schmizz.concurrent.Event;
import net.schmizz.concurrent.ErrorDeliveryUtil;
import net.schmizz.concurrent.Event;
import net.schmizz.sshj.AbstractService;
import net.schmizz.sshj.Config;
import net.schmizz.sshj.Service;
@@ -62,12 +62,14 @@ public final class TransportImpl
private static final class NullService
extends AbstractService {
NullService(Transport trans) {
super("null-service", trans);
}
}
static final class ConnInfo {
final String host;
final int port;
final InputStream in;
@@ -185,11 +187,11 @@ public final class TransportImpl
String ident;
byte[] data = new byte[256];
for (; ;) {
for (; ; ) {
int savedBufPos = buffer.rpos();
int pos = 0;
boolean needLF = false;
for (; ;) {
for (; ; ) {
if (buffer.available() == 0) {
// Need more data, so undo reading and return null
buffer.rpos(savedBufPos);
@@ -217,7 +219,7 @@ public final class TransportImpl
if (!ident.startsWith("SSH-2.0-") && !ident.startsWith("SSH-1.99-"))
throw new TransportException(DisconnectReason.PROTOCOL_VERSION_NOT_SUPPORTED,
"Server does not support SSHv2, identified as: " + ident);
"Server does not support SSHv2, identified as: " + ident);
return ident;
}
@@ -438,9 +440,9 @@ public final class TransportImpl
log.debug("Sending SSH_MSG_DISCONNECT: reason=[{}], msg=[{}]", reason, message);
try {
write(new SSHPacket(Message.DISCONNECT)
.putUInt32(reason.toInt())
.putString(message)
.putString(""));
.putUInt32(reason.toInt())
.putString(message)
.putString(""));
} catch (IOException worthless) {
log.debug("Error writing packet: {}", worthless.toString());
}
@@ -501,7 +503,8 @@ public final class TransportImpl
}
}
private void gotDebug(SSHPacket buf) throws TransportException {
private void gotDebug(SSHPacket buf)
throws TransportException {
try {
final boolean display = buf.readBoolean();
final String message = buf.readString();
@@ -529,7 +532,7 @@ public final class TransportImpl
try {
if (!serviceAccept.hasWaiters())
throw new TransportException(DisconnectReason.PROTOCOL_ERROR,
"Got a service accept notification when none was awaited");
"Got a service accept notification when none was awaited");
serviceAccept.set();
} finally {
serviceAccept.unlock();

View File

@@ -42,6 +42,7 @@ public class AES128CBC
/** Named factory for AES128CBC Cipher */
public static class Factory
implements net.schmizz.sshj.common.Factory.Named<Cipher> {
@Override
public Cipher create() {
return new AES128CBC();

View File

@@ -42,6 +42,7 @@ public class AES128CTR
/** Named factory for AES128CBC Cipher */
public static class Factory
implements net.schmizz.sshj.common.Factory.Named<Cipher> {
@Override
public Cipher create() {
return new AES128CTR();

View File

@@ -42,6 +42,7 @@ public class AES192CBC
/** Named factory for AES192CBC Cipher */
public static class Factory
implements net.schmizz.sshj.common.Factory.Named<Cipher> {
@Override
public Cipher create() {
return new AES192CBC();

View File

@@ -42,6 +42,7 @@ public class AES192CTR
/** Named factory for AES192CTR Cipher */
public static class Factory
implements net.schmizz.sshj.common.Factory.Named<Cipher> {
@Override
public Cipher create() {
return new AES192CTR();

View File

@@ -42,6 +42,7 @@ public class AES256CBC
/** Named factory for AES256CBC Cipher */
public static class Factory
implements net.schmizz.sshj.common.Factory.Named<Cipher> {
@Override
public Cipher create() {
return new AES256CBC();

View File

@@ -42,6 +42,7 @@ public class AES256CTR
/** Named factory for AES256CBC Cipher */
public static class Factory
implements net.schmizz.sshj.common.Factory.Named<Cipher> {
@Override
public Cipher create() {
return new AES256CTR();

View File

@@ -42,6 +42,7 @@ public class BlowfishCBC
/** Named factory for BlowfishCBC Cipher */
public static class Factory
implements net.schmizz.sshj.common.Factory.Named<Cipher> {
@Override
public Cipher create() {
return new BlowfishCBC();

View File

@@ -42,6 +42,7 @@ public class NoneCipher
/** Named factory for the no-op Cipher */
public static class Factory
implements net.schmizz.sshj.common.Factory.Named<Cipher> {
@Override
public Cipher create() {
return new NoneCipher();

View File

@@ -42,6 +42,7 @@ public class TripleDESCBC
/** Named factory for TripleDESCBC Cipher */
public static class Factory
implements net.schmizz.sshj.common.Factory.Named<Cipher> {
@Override
public Cipher create() {
return new TripleDESCBC();

View File

@@ -46,6 +46,7 @@ public class DelayedZlibCompression
/** Named factory for the ZLib Delayed Compression. */
public static class Factory
implements net.schmizz.sshj.common.Factory.Named<Compression> {
@Override
public Compression create() {
return new DelayedZlibCompression();

View File

@@ -42,6 +42,7 @@ public abstract class NoneCompression
/** Named factory for the no-op <code>Compression</code> */
public static class Factory
implements net.schmizz.sshj.common.Factory.Named<Compression> {
@Override
public Compression create() {
return null;

View File

@@ -49,6 +49,7 @@ public class ZlibCompression
/** Named factory for the ZLib Compression. */
public static class Factory
implements net.schmizz.sshj.common.Factory.Named<Compression> {
@Override
public Compression create() {
return new ZlibCompression();
@@ -125,7 +126,7 @@ public class ZlibCompression
return;
default:
throw new TransportException(DisconnectReason.COMPRESSION_ERROR, "uncompress: inflate returned "
+ status);
+ status);
}
}
}

View File

@@ -63,7 +63,8 @@ public class DHG14
}
@Override
protected void initDH(DH dh) throws GeneralSecurityException {
protected void initDH(DH dh)
throws GeneralSecurityException {
dh.init(DHGroupData.P14, DHGroupData.G);
}

View File

@@ -45,18 +45,18 @@ public final class DHGroupData {
public static final BigInteger P1 =
new BigInteger("1797693134862315907708391567937874531978602960487560117064444236841971802161585193" +
"6894783379586492554150218056548598050364644054819923910005079287700335581663922955" +
"3136239076508735759914822574862575007425302077447712589550957937778424442426617334" +
"727629299387668709205606050270810842907692932019128194467627007");
"6894783379586492554150218056548598050364644054819923910005079287700335581663922955" +
"3136239076508735759914822574862575007425302077447712589550957937778424442426617334" +
"727629299387668709205606050270810842907692932019128194467627007");
public static final BigInteger P14 =
new BigInteger("3231700607131100730033891392642382824881794124114023911284200975140074170663435422" +
"2619689417363569347117901737909704191754605873209195028853758986185622153212175412" +
"5149017745202702357960782362488842461894775876411059286460994117232454266225221932" +
"3054091903768052423551912567971587011700105805587765103886184728025797605490356973" +
"2561526167081339361799541336476559160368317896729073178384589680639671900977202194" +
"1686472258710314113364293195361934716365332097170774482279885885653692086452966360" +
"7725026895550592836275112117409697299806841055435958486658329164213621823107899099" +
"9448652468262416972035911852507045361090559");
"2619689417363569347117901737909704191754605873209195028853758986185622153212175412" +
"5149017745202702357960782362488842461894775876411059286460994117232454266225221932" +
"3054091903768052423551912567971587011700105805587765103886184728025797605490356973" +
"2561526167081339361799541336476559160368317896729073178384589680639671900977202194" +
"1686472258710314113364293195361934716365332097170774482279885885653692086452966360" +
"7725026895550592836275112117409697299806841055435958486658329164213621823107899099" +
"9448652468262416972035911852507045361090559");
}

View File

@@ -58,10 +58,9 @@ public class BouncyCastleRandom
}
private final RandomGenerator random;
private final RandomGenerator random = new VMPCRandomGenerator();
public BouncyCastleRandom() {
random = new VMPCRandomGenerator();
byte[] seed = new SecureRandom().generateSeed(8);
random.addSeedMaterial(seed);
}

View File

@@ -58,11 +58,7 @@ public class JCERandom
}
private byte[] tmp = new byte[16];
private SecureRandom random = null;
public JCERandom() {
random = new SecureRandom();
}
private final SecureRandom random = new SecureRandom();
/**
* Fill the given byte-array with random bytes from this PRNG.

View File

@@ -40,6 +40,7 @@ import net.schmizz.sshj.common.Factory;
/** A random factory wrapper that uses a single random instance. The underlying random instance has to be thread safe. */
public class SingletonRandomFactory
implements Random, Factory<Random> {
private final Random random;
public SingletonRandomFactory(Factory<Random> factory) {

View File

@@ -41,7 +41,7 @@ public class ConsoleKnownHostsVerifier
protected boolean hostKeyUnverifiableAction(String hostname, PublicKey key) {
final KeyType type = KeyType.fromKey(key);
console.printf("The authenticity of host '%s' can't be established.\n" +
"%s key fingerprint is %s.\n", hostname, type, SecurityUtils.getFingerprint(key));
"%s key fingerprint is %s.\n", hostname, type, SecurityUtils.getFingerprint(key));
String response = console.readLine("Are you sure you want to continue connecting (yes/no)? ");
while (!(response.equalsIgnoreCase(YES) || response.equalsIgnoreCase(NO))) {
response = console.readLine("Please explicitly enter yes/no: ");
@@ -66,15 +66,15 @@ public class ConsoleKnownHostsVerifier
final String path = getFile().getAbsolutePath();
console.printf(
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" +
"@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @\n" +
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" +
"IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!\n" +
"Someone could be eavesdropping on you right now (man-in-the-middle attack)!\n" +
"It is also possible that the host key has just been changed.\n" +
"The fingerprint for the %s key sent by the remote host is\n" +
"%s.\n" +
"Please contact your system administrator or" +
"add correct host key in %s to get rid of this message.\n",
"@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @\n" +
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" +
"IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!\n" +
"Someone could be eavesdropping on you right now (man-in-the-middle attack)!\n" +
"It is also possible that the host key has just been changed.\n" +
"The fingerprint for the %s key sent by the remote host is\n" +
"%s.\n" +
"Please contact your system administrator or" +
"add correct host key in %s to get rid of this message.\n",
type, fp, path);
return false;
}

View File

@@ -139,11 +139,13 @@ public class UserAuthImpl
case USERAUTH_BANNER: {
banner = buf.readString();
} break;
}
break;
case USERAUTH_SUCCESS: {
authenticated.set();
} break;
}
break;
case USERAUTH_FAILURE: {
allowedMethods.clear();
@@ -154,7 +156,8 @@ public class UserAuthImpl
} else {
authenticated.deliverError(new UserAuthException(currentMethod.getName() + " auth failed"));
}
} break;
}
break;
default: {
log.debug("Asking `{}` method to handle {} packet", currentMethod.getName(), msg);

View File

@@ -75,7 +75,7 @@ public class KeyProviderUtil {
*/
private static FileKeyProvider.Format detectKeyFileFormat(Reader privateKey,
boolean separatePubKey)
throws IOException {
throws IOException {
BufferedReader br = new BufferedReader(privateKey);
String firstLine = br.readLine();
IOUtils.closeQuietly(br);

View File

@@ -83,7 +83,7 @@ public class OpenSSHKeyFile
/**
* Read and store the separate public key provided alongside the private key
*
*
* @param publicKey Public key accessible through a {@code Reader}
*/
private void initPubKey(Reader publicKey) {

View File

@@ -22,18 +22,13 @@ import net.schmizz.sshj.userauth.password.PasswordUtils;
import net.schmizz.sshj.userauth.password.PrivateKeyFileResource;
import net.schmizz.sshj.userauth.password.PrivateKeyStringResource;
import net.schmizz.sshj.userauth.password.Resource;
import org.bouncycastle.openssl.EncryptionException;
import org.bouncycastle.openssl.PEMReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
@@ -44,6 +39,7 @@ public class PKCS8KeyFile
public static class Factory
implements net.schmizz.sshj.common.Factory.Named<FileKeyProvider> {
@Override
public FileKeyProvider create() {
return new PKCS8KeyFile();
@@ -127,7 +123,7 @@ public class PKCS8KeyFile
PEMReader r = null;
Object o = null;
try {
for (; ;) {
for (; ; ) {
// while the PasswordFinder tells us we should retry
try {
r = new PEMReader(resource.getReader(), pFinder);

View File

@@ -51,6 +51,7 @@ public class AuthKeyboardInteractive
}
private static class CharArrWrap {
private final char[] arr;
private CharArrWrap(char[] arr) {

View File

@@ -48,7 +48,7 @@ public abstract class KeyedAuthMethod
// public key as 2 strings: [ key type | key blob ]
reqBuf.putString(KeyType.fromKey(key).toString())
.putString(new Buffer.PlainBuffer().putPublicKey(key).getCompactData());
.putString(new Buffer.PlainBuffer().putPublicKey(key).getCompactData());
return reqBuf;
}
@@ -67,9 +67,10 @@ public abstract class KeyedAuthMethod
throw new UserAuthException("Could not create signature instance for " + kt + " key");
sigger.init(null, key);
sigger.update(new Buffer.PlainBuffer().putString(params.getTransport().getSessionID()) //
.putBuffer(reqBuf) // & rest of the data for sig
.getCompactData());
sigger.update(new Buffer.PlainBuffer()
.putString(params.getTransport().getSessionID())
.putBuffer(reqBuf) // & rest of the data for sig
.getCompactData());
reqBuf.putSignature(kt, sigger.sign());
return reqBuf;
}

View File

@@ -27,7 +27,8 @@ public class AccountResource
}
@Override
public Reader getReader() throws IOException {
public Reader getReader()
throws IOException {
return new StringReader(getDetail());
}
}

View File

@@ -19,14 +19,23 @@ import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
public class PrivateKeyStringResource extends Resource<String> {
public class PrivateKeyStringResource
extends Resource<String> {
public PrivateKeyStringResource(String string) {
super(string);
}
@Override
public Reader getReader() throws IOException {
public Reader getReader()
throws IOException {
return new StringReader(getDetail());
}
@Override
public String toString() {
// If not overridden, the superclass's will return the private key as
// part of the string.
return "[" + getClass().getSimpleName() + "]";
}
}

View File

@@ -26,9 +26,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class FileSystemFile
implements LocalSourceFile, LocalDestFile {

View File

@@ -26,7 +26,7 @@ public interface FileTransfer {
throws IOException;
void upload(LocalSourceFile localFile, String remotePath)
throws IOException;
throws IOException;
void download(String remotePath, LocalDestFile localFile)
throws IOException;

View File

@@ -34,7 +34,8 @@ public interface LocalSourceFile {
*
* @throws IOException
*/
int getPermissions() throws IOException;
int getPermissions()
throws IOException;
boolean isFile();

View File

@@ -19,6 +19,7 @@ import net.schmizz.sshj.common.SSHException;
public class SCPException
extends SSHException {
public SCPException(String message) {
super(message);
}

View File

@@ -15,8 +15,6 @@
*/
package net.schmizz.sshj.xfer.scp;
import java.io.IOException;
import net.schmizz.sshj.connection.channel.direct.SessionFactory;
import net.schmizz.sshj.xfer.AbstractFileTransfer;
import net.schmizz.sshj.xfer.FileSystemFile;
@@ -24,6 +22,8 @@ import net.schmizz.sshj.xfer.FileTransfer;
import net.schmizz.sshj.xfer.LocalDestFile;
import net.schmizz.sshj.xfer.LocalSourceFile;
import java.io.IOException;
public class SCPFileTransfer
extends AbstractFileTransfer
implements FileTransfer {
@@ -43,7 +43,7 @@ public class SCPFileTransfer
}
private SCPEngine newSCPEngine() {
return new SCPEngine(sessionFactory, getTransferListener());
return new SCPEngine(sessionFactory, getTransferListener());
}
@Override
@@ -65,9 +65,9 @@ public class SCPFileTransfer
}
@Override
public void upload(LocalSourceFile localFile, String remotePath)
throws IOException {
newSCPUploadClient().copy(localFile, remotePath);
}
public void upload(LocalSourceFile localFile, String remotePath)
throws IOException {
newSCPUploadClient().copy(localFile, remotePath);
}
}

View File

@@ -16,6 +16,7 @@
package net.schmizz.sshj.xfer.scp;
import net.schmizz.sshj.common.IOUtils;
import net.schmizz.sshj.xfer.LocalFileFilter;
import net.schmizz.sshj.xfer.LocalSourceFile;
import net.schmizz.sshj.xfer.scp.SCPEngine.Arg;
@@ -28,8 +29,9 @@ import java.util.List;
public final class SCPUploadClient {
private final SCPEngine engine;
private LocalFileFilter uploadFilter;
SCPUploadClient(SCPEngine engine) {
SCPUploadClient(SCPEngine engine) {
this.engine = engine;
}
@@ -45,7 +47,11 @@ public final class SCPUploadClient {
return engine.getExitStatus();
}
private synchronized void startCopy(LocalSourceFile sourceFile, String targetPath)
public void setUploadFilter(LocalFileFilter uploadFilter) {
this.uploadFilter = uploadFilter;
}
private synchronized void startCopy(LocalSourceFile sourceFile, String targetPath)
throws IOException {
List<Arg> args = new LinkedList<Arg>();
args.add(Arg.SINK);
@@ -75,7 +81,7 @@ public final class SCPUploadClient {
throws IOException {
preserveTimeIfPossible(f);
engine.sendMessage("D0" + getPermString(f) + " 0 " + f.getName());
for (LocalSourceFile child : f.getChildren(null))
for (LocalSourceFile child : f.getChildren(uploadFilter))
process(child);
engine.sendMessage("E");
}

View File

@@ -50,7 +50,8 @@ public class SmokeTest {
}
@Test
public void authenticated() throws UserAuthException, TransportException {
public void authenticated()
throws UserAuthException, TransportException {
fixture.dummyAuth();
assertTrue(fixture.getClient().isAuthenticated());
}

View File

@@ -116,7 +116,7 @@ public class OpenSSHKeyFileTest {
@Test
public void fromString()
throws IOException, GeneralSecurityException {
throws IOException, GeneralSecurityException {
FileKeyProvider dsa = new OpenSSHKeyFile();
String privateKey = readFile("src/test/resources/id_dsa");
String publicKey = readFile("src/test/resources/id_dsa.pub");
@@ -136,12 +136,11 @@ public class OpenSSHKeyFileTest {
private String readFile(String pathname)
throws IOException {
StringBuilder fileContents = new StringBuilder();
Scanner scanner = new Scanner(new File(pathname));
String lineSeparator = System.getProperty("line.separator");
try {
while(scanner.hasNextLine()) {
while (scanner.hasNextLine()) {
fileContents.append(scanner.nextLine() + lineSeparator);
}
return fileContents.toString();

View File

@@ -0,0 +1,23 @@
package net.schmizz.sshj.sftp;
import org.junit.Test;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertThat;
public class FileModeTest {
@Test
public void shouldDetectDirectoryWithLinuxMask() {
FileMode fileMode = new FileMode(040755);
assertThat(fileMode.toString(), equalTo("[mask=40755]"));
assertThat(fileMode.getType(), equalTo(FileMode.Type.DIRECTORY));
}
@Test
public void shouldDetectDirectoryWithAixUnixMask() {
FileMode fileMode = new FileMode(0240755);
assertThat(fileMode.toString(), equalTo("[mask=240755]"));
assertThat(fileMode.getType(), equalTo(FileMode.Type.DIRECTORY));
}
}

View File

@@ -28,6 +28,7 @@ import static org.junit.Assert.assertEquals;
/** Tests {@link Buffer} functionality */
public class BufferTest {
private Buffer.PlainBuffer posBuf;
private Buffer.PlainBuffer handyBuf;

View File

@@ -29,34 +29,38 @@ import java.security.spec.RSAPublicKeySpec;
public class KeyUtil {
/** Creates a DSA private key. */
public static PrivateKey newDSAPrivateKey(String x, String p, String q, String g) throws GeneralSecurityException {
return SecurityUtils.getKeyFactory("DSA").generatePrivate(new DSAPrivateKeySpec //
(new BigInteger(x, 16), //
new BigInteger(p, 16), //
new BigInteger(q, 16), //
new BigInteger(g, 16)));
public static PrivateKey newDSAPrivateKey(String x, String p, String q, String g)
throws GeneralSecurityException {
return SecurityUtils.getKeyFactory("DSA").generatePrivate(new DSAPrivateKeySpec(new BigInteger(x, 16),
new BigInteger(p, 16),
new BigInteger(q, 16),
new BigInteger(g, 16))
);
}
/** Creates a DSA public key. */
public static PublicKey newDSAPublicKey(String y, String p, String q, String g) throws GeneralSecurityException {
return SecurityUtils.getKeyFactory("DSA").generatePublic(new DSAPublicKeySpec //
(new BigInteger(y, 16), //
new BigInteger(p, 16), //
new BigInteger(q, 16), //
new BigInteger(g, 16)));
public static PublicKey newDSAPublicKey(String y, String p, String q, String g)
throws GeneralSecurityException {
return SecurityUtils.getKeyFactory("DSA").generatePublic(new DSAPublicKeySpec(new BigInteger(y, 16),
new BigInteger(p, 16),
new BigInteger(q, 16),
new BigInteger(g, 16))
);
}
/** Creates an RSA private key. */
public static PrivateKey newRSAPrivateKey(String modulus, String exponent) throws GeneralSecurityException {
return SecurityUtils.getKeyFactory("RSA").generatePrivate(new RSAPrivateKeySpec //
(new BigInteger(modulus, 16), //
new BigInteger(exponent, 16)));
public static PrivateKey newRSAPrivateKey(String modulus, String exponent)
throws GeneralSecurityException {
return SecurityUtils.getKeyFactory("RSA").generatePrivate(new RSAPrivateKeySpec(new BigInteger(modulus, 16),
new BigInteger(exponent, 16))
);
}
/** Creates an RSA public key. */
public static PublicKey newRSAPublicKey(String modulus, String exponent) throws GeneralSecurityException {
return SecurityUtils.getKeyFactory("RSA").generatePublic(new RSAPublicKeySpec //
(new BigInteger(modulus, 16), new BigInteger(exponent, 16)));
public static PublicKey newRSAPublicKey(String modulus, String exponent)
throws GeneralSecurityException {
return SecurityUtils.getKeyFactory("RSA").generatePublic(new RSAPublicKeySpec(new BigInteger(modulus, 16),
new BigInteger(exponent, 16)));
}
}

View File

@@ -0,0 +1,54 @@
package net.schmizz.sshj.xfer.scp;
import net.schmizz.sshj.xfer.FileSystemFile;
import net.schmizz.sshj.xfer.LocalFileFilter;
import net.schmizz.sshj.xfer.LocalSourceFile;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.mockito.verification.VerificationMode;
import java.io.File;
import java.io.IOException;
import static org.mockito.Matchers.endsWith;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isA;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
public class SCPUploadClientTest {
private SCPEngine engine;
private SCPUploadClient scpUploadClient;
@Rule
public TemporaryFolder temp = new TemporaryFolder();
@Before
public void init() {
engine = mock(SCPEngine.class);
scpUploadClient = new SCPUploadClient(engine);
}
@Test
public void shouldOnlySendFilterAcceptedFilesFromDirectory() throws IOException {
scpUploadClient.setUploadFilter(new LocalFileFilter() {
@Override
public boolean accept(LocalSourceFile file) {
return !file.getName().contains("not-");
}
});
File dir = temp.newFolder("filtered-scp-upload");
new File(dir, "not-sent.txt").createNewFile();
new File(dir, "sent.txt").createNewFile();
int copy = scpUploadClient.copy(new FileSystemFile(dir), "/tmp");
verify(engine).startedDir("filtered-scp-upload");
verify(engine).startedFile(eq("sent.txt"), isA(Long.class));
verify(engine, times(1)).startedFile(isA(String.class), isA(Long.class));
}
}