minor changes, reformat etc.

This commit is contained in:
Shikhar Bhushan
2010-03-01 23:36:12 +01:00
parent 7106eed7a5
commit 8ec5055615
33 changed files with 470 additions and 388 deletions

View File

@@ -67,16 +67,16 @@ public interface Config {
List<Factory.Named<MAC>> getMACFactories();
/**
* Retrieve the {@link net.schmizz.sshj.transport.random.Random} factory.
* Retrieve the {@link Random} factory.
*
* @return the {@link net.schmizz.sshj.transport.random.Random} factory
* @return the {@link Random} factory
*/
Factory<Random> getRandomFactory();
/**
* Retrieve the list of named factories for {@link net.schmizz.sshj.signature.Signature}
* Retrieve the list of named factories for {@link Signature}
*
* @return a list of named {@link net.schmizz.sshj.signature.Signature} factories
* @return a list of named {@link Signature} factories
*/
List<Factory.Named<Signature>> getSignatureFactories();
@@ -87,49 +87,49 @@ public interface Config {
String getVersion();
/**
* Set the named factories for {@link net.schmizz.sshj.transport.cipher.Cipher}.
* Set the named factories for {@link Cipher}.
*
* @param cipherFactories a list of named factories
*/
void setCipherFactories(List<Factory.Named<Cipher>> cipherFactories);
/**
* Set the named factories for {@link net.schmizz.sshj.transport.compression.Compression}.
* Set the named factories for {@link Compression}.
*
* @param compressionFactories a list of named factories
*/
void setCompressionFactories(List<Factory.Named<Compression>> compressionFactories);
/**
* Set the named factories for {@link net.schmizz.sshj.userauth.keyprovider.FileKeyProvider}.
* Set the named factories for {@link FileKeyProvider}.
*
* @param fileKeyProviderFactories a list of named factories
*/
void setFileKeyProviderFactories(List<Factory.Named<FileKeyProvider>> fileKeyProviderFactories);
/**
* Set the named factories for {@link net.schmizz.sshj.transport.kex.KeyExchange}.
* Set the named factories for {@link KeyExchange}.
*
* @param kexFactories a list of named factories
*/
void setKeyExchangeFactories(List<Factory.Named<KeyExchange>> kexFactories);
/**
* Set the named factories for {@link net.schmizz.sshj.transport.mac.MAC}.
* Set the named factories for {@link MAC}.
*
* @param macFactories a list of named factories
*/
void setMACFactories(List<Factory.Named<MAC>> macFactories);
/**
* Set the factory for {@link net.schmizz.sshj.transport.random.Random}.
* Set the factory for {@link Random}.
*
* @param randomFactory the factory
*/
void setRandomFactory(Factory<Random> randomFactory);
/**
* Set the named factories for {@link net.schmizz.sshj.signature.Signature}.
* Set the named factories for {@link Signature}.
*
* @param signatureFactories a list of named factories
*/

View File

@@ -99,8 +99,7 @@ import java.util.List;
* <p/>
* {@link #startSession()} caters to the most typical use case of starting a {@code session} channel and executing a
* remote command, starting a subsystem, etc. If you wish to request X11 forwarding for some session, first {@link
* #registerX11Forwarder(net.schmizz.sshj.connection.channel.forwarded.ConnectListener) register} a {@link
* net.schmizz.sshj.connection.channel.forwarded.ConnectListener} for {@code x11} channels.
* #registerX11Forwarder(ConnectListener) register} a {@link ConnectListener} for {@code x11} channels.
* <p/>
* {@link #newLocalPortForwarder Local} and {@link #getRemotePortForwarder() remote} port forwarding is possible. There
* are also utility method for easily creating {@link #newSCPFileTransfer SCP} and {@link #newSFTPClient() SFTP}
@@ -127,7 +126,9 @@ import java.util.List;
* Where a password or passphrase is required, if you're extra-paranoid use the {@code char[]} based method. The {@code
* char[]} will be blanked out after use.
*/
public class SSHClient extends SocketClient implements SessionFactory {
public class SSHClient
extends SocketClient
implements SessionFactory {
/** Default port for SSH */
public static final int DEFAULT_PORT = 22;
@@ -180,7 +181,7 @@ public class SSHClient extends SocketClient implements SessionFactory {
* @param port the port for which the {@code fingerprint} applies
* @param fingerprint expected fingerprint in colon-delimited format (16 octets in hex delimited by a colon)
*
* @see net.schmizz.sshj.common.SecurityUtils#getFingerprint
* @see SecurityUtils#getFingerprint
*/
public void addHostKeyVerifier(final String host, final int port, final String fingerprint) {
addHostKeyVerifier(new HostKeyVerifier() {
@@ -199,7 +200,8 @@ public class SSHClient extends SocketClient implements SessionFactory {
* @throws UserAuthException in case of authentication failure
* @throws TransportException if there was a transport-layer error
*/
public void auth(String username, AuthMethod... methods) throws UserAuthException, TransportException {
public void auth(String username, AuthMethod... methods)
throws UserAuthException, TransportException {
assert isConnected();
auth(username, Arrays.<AuthMethod>asList(methods));
}
@@ -213,7 +215,8 @@ public class SSHClient extends SocketClient implements SessionFactory {
* @throws UserAuthException in case of authentication failure
* @throws TransportException if there was a transport-layer error
*/
public void auth(String username, Iterable<AuthMethod> methods) throws UserAuthException, TransportException {
public void auth(String username, Iterable<AuthMethod> methods)
throws UserAuthException, TransportException {
assert isConnected();
auth.authenticate(username, conn, methods);
}
@@ -228,7 +231,8 @@ public class SSHClient extends SocketClient implements SessionFactory {
* @throws UserAuthException in case of authentication failure
* @throws TransportException if there was a transport-layer error
*/
public void authPassword(String username, char[] password) throws UserAuthException, TransportException {
public void authPassword(String username, char[] password)
throws UserAuthException, TransportException {
authPassword(username, PasswordUtils.createOneOff(password));
}
@@ -236,12 +240,13 @@ public class SSHClient extends SocketClient implements SessionFactory {
* Authenticate {@code username} using the {@code "password"} authentication method.
*
* @param username user to authenticate
* @param pfinder the {@link net.schmizz.sshj.userauth.password.PasswordFinder} to use for authentication
* @param pfinder the {@link PasswordFinder} to use for authentication
*
* @throws UserAuthException in case of authentication failure
* @throws TransportException if there was a transport-layer error
*/
public void authPassword(String username, PasswordFinder pfinder) throws UserAuthException, TransportException {
public void authPassword(String username, PasswordFinder pfinder)
throws UserAuthException, TransportException {
auth(username, new AuthPassword(pfinder));
}
@@ -254,7 +259,8 @@ public class SSHClient extends SocketClient implements SessionFactory {
* @throws UserAuthException in case of authentication failure
* @throws TransportException if there was a transport-layer error
*/
public void authPassword(String username, String password) throws UserAuthException, TransportException {
public void authPassword(String username, String password)
throws UserAuthException, TransportException {
authPassword(username, password.toCharArray());
}
@@ -269,7 +275,8 @@ public class SSHClient extends SocketClient implements SessionFactory {
* @throws UserAuthException in case of authentication failure
* @throws TransportException if there was a transport-layer error
*/
public void authPublickey(String username) throws UserAuthException, TransportException {
public void authPublickey(String username)
throws UserAuthException, TransportException {
String base = System.getProperty("user.home") + File.separator + ".ssh" + File.separator;
authPublickey(username, base + "id_rsa", base + "id_dsa");
}
@@ -287,7 +294,8 @@ public class SSHClient extends SocketClient implements SessionFactory {
* @throws UserAuthException in case of authentication failure
* @throws TransportException if there was a transport-layer error
*/
public void authPublickey(String username, Iterable<KeyProvider> keyProviders) throws UserAuthException,
public void authPublickey(String username, Iterable<KeyProvider> keyProviders)
throws UserAuthException,
TransportException {
List<AuthMethod> am = new LinkedList<AuthMethod>();
for (KeyProvider kp : keyProviders)
@@ -308,7 +316,8 @@ public class SSHClient extends SocketClient implements SessionFactory {
* @throws UserAuthException in case of authentication failure
* @throws TransportException if there was a transport-layer error
*/
public void authPublickey(String username, KeyProvider... keyProviders) throws UserAuthException,
public void authPublickey(String username, KeyProvider... keyProviders)
throws UserAuthException,
TransportException {
authPublickey(username, Arrays.<KeyProvider>asList(keyProviders));
}
@@ -329,7 +338,8 @@ public class SSHClient extends SocketClient implements SessionFactory {
* @throws UserAuthException in case of authentication failure
* @throws TransportException if there was a transport-layer error
*/
public void authPublickey(String username, String... locations) throws UserAuthException, TransportException {
public void authPublickey(String username, String... locations)
throws UserAuthException, TransportException {
List<KeyProvider> keyProviders = new LinkedList<KeyProvider>();
for (String loc : locations)
try {
@@ -349,7 +359,8 @@ public class SSHClient extends SocketClient implements SessionFactory {
* cleanup is done and the thread spawned by the transport layer for dealing with incoming packets is stopped.
*/
@Override
public void disconnect() throws IOException {
public void disconnect()
throws IOException {
assert isConnected();
trans.disconnect();
super.disconnect();
@@ -411,7 +422,7 @@ public class SSHClient extends SocketClient implements SessionFactory {
/**
* Returns a {@link KeyProvider} instance created from a location on the file system where an <em>unencrypted</em>
* private key file (does not require a passphrase) can be found. Simply calls {@link #loadKeys(String,
* PasswordFinder)} with the {@link net.schmizz.sshj.userauth.password.PasswordFinder} argument as {@code null}.
* PasswordFinder)} with the {@link PasswordFinder} argument as {@code null}.
*
* @param location the location for the key file
*
@@ -421,26 +432,27 @@ public class SSHClient extends SocketClient implements SessionFactory {
* BouncyCastle is not in the classpath
* @throws IOException if the key file format is not known, if the file could not be read, etc.
*/
public KeyProvider loadKeys(String location) throws IOException {
public KeyProvider loadKeys(String location)
throws IOException {
return loadKeys(location, (PasswordFinder) null);
}
/**
* Utility function for createing a {@link KeyProvider} instance from given location on the file system. Creates a
* one-off {@link PasswordFinder} using {@link net.schmizz.sshj.userauth.password.PasswordUtils#createOneOff(char[])},
* and calls {@link #loadKeys(String,PasswordFinder)}.
* one-off {@link PasswordFinder} using {@link PasswordUtils#createOneOff(char[])}, and calls {@link
* #loadKeys(String,PasswordFinder)}.
*
* @param location location of the key file
* @param passphrase passphrase as a char-array
*
* @return the key provider ready for use in authentication
*
* @throws net.schmizz.sshj.common.SSHException
* if there was no suitable key provider available for the file format; typically because
* @throws SSHException if there was no suitable key provider available for the file format; typically because
* BouncyCastle is not in the classpath
* @throws IOException if the key file format is not known, if the file could not be read, etc.
*/
public KeyProvider loadKeys(String location, char[] passphrase) throws IOException {
public KeyProvider loadKeys(String location, char[] passphrase)
throws IOException {
return loadKeys(location, PasswordUtils.createOneOff(passphrase));
}
@@ -459,7 +471,8 @@ public class SSHClient extends SocketClient implements SessionFactory {
* BouncyCastle is not in the classpath
* @throws IOException if the key file format is not known, if the file could not be read, etc.
*/
public KeyProvider loadKeys(String location, PasswordFinder passwordFinder) throws IOException {
public KeyProvider loadKeys(String location, PasswordFinder passwordFinder)
throws IOException {
File loc = new File(location);
FileKeyProvider.Format format = KeyProviderUtil.detectKeyFileFormat(loc);
FileKeyProvider fkp = Factory.Named.Util.create(trans.getConfig().getFileKeyProviderFactories(), format
@@ -482,7 +495,8 @@ public class SSHClient extends SocketClient implements SessionFactory {
*
* @throws IOException if the key file format is not known, if the file could not be read etc.
*/
public KeyProvider loadKeys(String location, String passphrase) throws IOException {
public KeyProvider loadKeys(String location, String passphrase)
throws IOException {
return loadKeys(location, passphrase.toCharArray());
}
@@ -495,7 +509,8 @@ public class SSHClient extends SocketClient implements SessionFactory {
*
* @throws IOException if there is an error loading from <em>both</em> locations
*/
public void loadKnownHosts() throws IOException {
public void loadKnownHosts()
throws IOException {
boolean loaded = false;
final File sshDir = OpenSSHKnownHosts.detectSSHDir();
if (sshDir != null) {
@@ -515,7 +530,8 @@ public class SSHClient extends SocketClient implements SessionFactory {
*
* @throws IOException if there is an error loading from any of these locations
*/
public void loadKnownHosts(File location) throws IOException {
public void loadKnownHosts(File location)
throws IOException {
addHostKeyVerifier(new OpenSSHKnownHosts(location));
}
@@ -526,7 +542,7 @@ public class SSHClient extends SocketClient implements SessionFactory {
* The returned forwarder's {@link LocalPortForwarder#listen() listen()} method should be called to actually start
* listening, this method just creates an instance.
*
* @param address defines where the {@link net.schmizz.sshj.connection.channel.direct.LocalPortForwarder} listens
* @param address defines where the {@link LocalPortForwarder} listens
* @param host hostname to which the server will forward
* @param port the port at {@code hostname} to which the server wil forward
*
@@ -534,7 +550,8 @@ public class SSHClient extends SocketClient implements SessionFactory {
*
* @throws IOException if there is an error opening a local server socket
*/
public LocalPortForwarder newLocalPortForwarder(SocketAddress address, String host, int port) throws IOException {
public LocalPortForwarder newLocalPortForwarder(SocketAddress address, String host, int port)
throws IOException {
return new LocalPortForwarder(getServerSocketFactory(), conn, address, host, port);
}
@@ -549,8 +566,8 @@ public class SSHClient extends SocketClient implements SessionFactory {
* @param listener the {@link ConnectListener} that should be delegated the responsibility of handling forwarded
* {@link X11Channel} 's
*
* @return an {@link net.schmizz.sshj.connection.channel.forwarded.X11Forwarder} that allows to {@link
* X11Forwarder#stop() stop acting} on X11 requests from server
* @return an {@link X11Forwarder} that allows to {@link X11Forwarder#stop() stop acting} on X11 requests from
* server
*/
public X11Forwarder registerX11Forwarder(ConnectListener listener) {
X11Forwarder x11f = new X11Forwarder(conn, listener);
@@ -570,7 +587,8 @@ public class SSHClient extends SocketClient implements SessionFactory {
* @throws IOException if there is an error starting the {@code sftp} subsystem
* @see StatefulSFTPClient
*/
public SFTPClient newSFTPClient() throws IOException {
public SFTPClient newSFTPClient()
throws IOException {
assert isConnected() && isAuthenticated();
return new SFTPClient(this);
}
@@ -580,11 +598,13 @@ public class SSHClient extends SocketClient implements SessionFactory {
*
* @throws TransportException if an error occurs during key exchange
*/
public void rekey() throws TransportException {
public void rekey()
throws TransportException {
doKex();
}
public Session startSession() throws ConnectionException, TransportException {
public Session startSession()
throws ConnectionException, TransportException {
assert isConnected() && isAuthenticated();
SessionChannel sess = new SessionChannel(conn);
sess.open();
@@ -602,7 +622,8 @@ public class SSHClient extends SocketClient implements SessionFactory {
* @throws ClassNotFoundException if {@code JZlib} is not in classpath
* @throws TransportException if an error occurs during renegotiation
*/
public void useCompression() throws ClassNotFoundException, TransportException {
public void useCompression()
throws ClassNotFoundException, TransportException {
trans.getConfig().setCompressionFactories(Arrays.asList(
new DelayedZlibCompression.Factory(),
new ZlibCompression.Factory(),
@@ -613,7 +634,8 @@ public class SSHClient extends SocketClient implements SessionFactory {
/** On connection establishment, also initialize the SSH transport via {@link Transport#init} and {@link #doKex()}. */
@Override
protected void onConnect() throws IOException {
protected void onConnect()
throws IOException {
super.onConnect();
trans.init(getRemoteHostname(), getRemotePort(), getInputStream(), getOutputStream());
doKex();
@@ -624,7 +646,8 @@ public class SSHClient extends SocketClient implements SessionFactory {
*
* @throws TransportException if error during kex
*/
protected void doKex() throws TransportException {
protected void doKex()
throws TransportException {
assert trans.isRunning();
long start = System.currentTimeMillis();

View File

@@ -21,7 +21,8 @@ import net.schmizz.sshj.common.SSHPacketHandler;
import net.schmizz.sshj.transport.TransportException;
/** Represents a service running on top of the SSH {@link net.schmizz.sshj.transport.Transport transport layer}. */
public interface Service extends SSHPacketHandler, ErrorNotifiable {
public interface Service
extends SSHPacketHandler, ErrorNotifiable {
/** @return The assigned name for this SSH service. */
String getName();
@@ -34,17 +35,20 @@ public interface Service extends SSHPacketHandler, ErrorNotifiable {
*
* @throws SSHException if the packet is unexpected and may represent a disruption
*/
void notifyUnimplemented(long seqNum) throws SSHException;
void notifyUnimplemented(long seqNum)
throws SSHException;
/**
* Request and install this service with the associated transport. Implementations should aim to make this method
* idempotent by first checking the {@link net.schmizz.sshj.transport.Transport#getService() currently active
* idempotent by first checking the {@link net.schmizz.sshj.transport.Transport#getService()} currently active
* service}.
*
* @throws TransportException if there is an error sending the service request
*/
void request() throws TransportException;
void request()
throws TransportException;
void notifyDisconnect() throws SSHException;
void notifyDisconnect()
throws SSHException;
}

View File

@@ -48,12 +48,33 @@ import java.util.Arrays;
public class Buffer<T extends Buffer<T>> {
public static class BufferException extends SSHRuntimeException {
public static class BufferException
extends SSHRuntimeException {
public BufferException(String message) {
super(message);
}
}
public static class PlainBuffer
extends Buffer<PlainBuffer> {
public PlainBuffer() {
super();
}
public PlainBuffer(Buffer<?> from) {
super(from);
}
public PlainBuffer(byte[] b) {
super(b);
}
public PlainBuffer(int size) {
super(size);
}
}
/** The default size for a {@code Buffer} (256 bytes) */
public static final int DEFAULT_SIZE = 256;
@@ -473,18 +494,22 @@ public class Buffer<T extends Buffer<T>> {
public T putPublicKey(PublicKey key) {
KeyType type = KeyType.fromKey(key);
switch (type) {
case RSA:
case RSA: {
final RSAPublicKey rsaKey = (RSAPublicKey) key;
putString(type.toString()) // ssh-rsa
.putMPInt(((RSAPublicKey) key).getPublicExponent()) // e
.putMPInt(((RSAPublicKey) key).getModulus()); // n
.putMPInt(rsaKey.getPublicExponent()) // e
.putMPInt(rsaKey.getModulus()); // n
break;
case DSA:
}
case DSA: {
final DSAPublicKey dsaKey = (DSAPublicKey) key;
putString(type.toString()) // ssh-dss
.putMPInt(((DSAPublicKey) key).getParams().getP()) // p
.putMPInt(((DSAPublicKey) key).getParams().getQ()) // q
.putMPInt(((DSAPublicKey) key).getParams().getG()) // g
.putMPInt(((DSAPublicKey) key).getY()); // y
.putMPInt(dsaKey.getParams().getP()) // p
.putMPInt(dsaKey.getParams().getQ()) // q
.putMPInt(dsaKey.getParams().getG()) // g
.putMPInt(dsaKey.getY()); // y
break;
}
default:
assert false;
}
@@ -492,7 +517,8 @@ public class Buffer<T extends Buffer<T>> {
}
public T putSignature(String sigFormat, byte[] sigData) {
return putString(new PlainBuffer().putString(sigFormat).putBytes(sigData).getCompactData());
final byte[] sig = new PlainBuffer().putString(sigFormat).putBytes(sigData).getCompactData();
return putString(sig);
}
/**
@@ -509,23 +535,4 @@ public class Buffer<T extends Buffer<T>> {
return "Buffer [rpos=" + rpos + ", wpos=" + wpos + ", size=" + data.length + "]";
}
public static class PlainBuffer extends Buffer<PlainBuffer> {
public PlainBuffer() {
super();
}
public PlainBuffer(Buffer<?> from) {
super(from);
}
public PlainBuffer(byte[] b) {
super(b);
}
public PlainBuffer(int size) {
super(size);
}
}
}

View File

@@ -51,7 +51,8 @@ public interface Factory<T> {
*
* @param <T> type of object created by this factory
*/
interface Named<T> extends Factory<T> {
interface Named<T>
extends Factory<T> {
/** Utility functions */
public static class Util {

View File

@@ -43,7 +43,8 @@ import java.io.IOException;
* Most exceptions in {@code org.apache.commons.net.ssh} are instances of this class. An {@link SSHException} is itself
* an {@link IOException} and can be caught like that if this level of granularity is not desired.
*/
public class SSHException extends IOException {
public class SSHException
extends IOException {
public static final ExceptionChainer<SSHException> chainer = new ExceptionChainer<SSHException>() {

View File

@@ -37,7 +37,8 @@ package net.schmizz.sshj.common;
import java.util.Arrays;
public class SSHPacket extends Buffer<SSHPacket> {
public class SSHPacket
extends Buffer<SSHPacket> {
public SSHPacket() {
super();

View File

@@ -30,6 +30,7 @@ public interface SSHPacketHandler {
*
* @throws SSHException if there is a non-recoverable error
*/
void handle(Message msg, SSHPacket buf) throws SSHException;
void handle(Message msg, SSHPacket buf)
throws SSHException;
}

View File

@@ -36,7 +36,8 @@
package net.schmizz.sshj.common;
/** Represents unrecoverable exceptions in the {@code org.apache.commons.net.ssh} package. */
public class SSHRuntimeException extends RuntimeException {
public class SSHRuntimeException
extends RuntimeException {
public SSHRuntimeException() {
this(null, null);

View File

@@ -52,11 +52,14 @@ import java.security.NoSuchProviderException;
import java.security.PublicKey;
import java.security.Signature;
// TODO refactor
/** Static utility method relating to security facilities. */
public class SecurityUtils {
private static class BouncyCastleRegistration {
public void run() throws Exception {
public void run()
throws Exception {
if (java.security.Security.getProvider(BOUNCY_CASTLE) == null) {
LOG.info("Trying to register BouncyCastle as a JCE provider");
java.security.Security.addProvider(new BouncyCastleProvider());
@@ -83,8 +86,8 @@ public class SecurityUtils {
private static Boolean registerBouncyCastle;
private static boolean registrationDone;
public static synchronized Cipher getCipher(String transformation) throws NoSuchAlgorithmException,
NoSuchPaddingException, NoSuchProviderException {
public static synchronized Cipher getCipher(String transformation)
throws NoSuchAlgorithmException, NoSuchPaddingException, NoSuchProviderException {
register();
if (getSecurityProvider() == null)
return Cipher.getInstance(transformation);
@@ -127,8 +130,8 @@ public class SecurityUtils {
* @throws NoSuchAlgorithmException
* @throws NoSuchProviderException
*/
public static synchronized KeyAgreement getKeyAgreement(String algorithm) throws NoSuchAlgorithmException,
NoSuchProviderException {
public static synchronized KeyAgreement getKeyAgreement(String algorithm)
throws NoSuchAlgorithmException, NoSuchProviderException {
register();
if (getSecurityProvider() == null)
return KeyAgreement.getInstance(algorithm);
@@ -146,8 +149,8 @@ public class SecurityUtils {
* @throws NoSuchAlgorithmException
* @throws NoSuchProviderException
*/
public static synchronized KeyFactory getKeyFactory(String algorithm) throws NoSuchAlgorithmException,
NoSuchProviderException {
public static synchronized KeyFactory getKeyFactory(String algorithm)
throws NoSuchAlgorithmException, NoSuchProviderException {
register();
if (getSecurityProvider() == null)
return KeyFactory.getInstance(algorithm);
@@ -165,8 +168,8 @@ public class SecurityUtils {
* @throws NoSuchAlgorithmException
* @throws NoSuchProviderException
*/
public static synchronized KeyPairGenerator getKeyPairGenerator(String algorithm) throws NoSuchAlgorithmException,
NoSuchProviderException {
public static synchronized KeyPairGenerator getKeyPairGenerator(String algorithm)
throws NoSuchAlgorithmException, NoSuchProviderException {
register();
if (getSecurityProvider() == null)
return KeyPairGenerator.getInstance(algorithm);
@@ -184,7 +187,8 @@ public class SecurityUtils {
* @throws NoSuchAlgorithmException
* @throws NoSuchProviderException
*/
public static synchronized Mac getMAC(String algorithm) throws NoSuchAlgorithmException, NoSuchProviderException {
public static synchronized Mac getMAC(String algorithm)
throws NoSuchAlgorithmException, NoSuchProviderException {
register();
if (getSecurityProvider() == null)
return Mac.getInstance(algorithm);
@@ -202,8 +206,8 @@ public class SecurityUtils {
* @throws NoSuchAlgorithmException
* @throws NoSuchProviderException
*/
public static synchronized MessageDigest getMessageDigest(String algorithm) throws NoSuchAlgorithmException,
NoSuchProviderException {
public static synchronized MessageDigest getMessageDigest(String algorithm)
throws NoSuchAlgorithmException, NoSuchProviderException {
register();
if (getSecurityProvider() == null)
return MessageDigest.getInstance(algorithm);
@@ -221,8 +225,8 @@ public class SecurityUtils {
return securityProvider;
}
public static synchronized Signature getSignature(String algorithm) throws NoSuchAlgorithmException,
NoSuchProviderException {
public static synchronized Signature getSignature(String algorithm)
throws NoSuchAlgorithmException, NoSuchProviderException {
register();
if (getSecurityProvider() == null)
return Signature.getInstance(algorithm);

View File

@@ -24,7 +24,8 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
public class StreamCopier extends Thread {
public class StreamCopier
extends Thread {
private static final Logger LOG = LoggerFactory.getLogger(StreamCopier.class);
@@ -41,7 +42,8 @@ public class StreamCopier extends Thread {
};
}
public static long copy(InputStream in, OutputStream out, int bufSize, boolean keepFlushing) throws IOException {
public static long copy(InputStream in, OutputStream out, int bufSize, boolean keepFlushing)
throws IOException {
long count = 0;
final long startTime = System.currentTimeMillis();
@@ -64,7 +66,8 @@ public class StreamCopier extends Thread {
return count;
}
public static String copyStreamToString(InputStream stream) throws IOException {
public static String copyStreamToString(InputStream stream)
throws IOException {
final StringBuilder sb = new StringBuilder();
int read;
while ((read = stream.read()) != -1)

View File

@@ -12,26 +12,6 @@
* 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.
*
* This file may incorporate work covered by the following copyright and
* permission notice:
*
* 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 net.schmizz.sshj.connection;
@@ -43,16 +23,14 @@ import net.schmizz.sshj.connection.channel.forwarded.ForwardedChannelOpener;
import net.schmizz.sshj.transport.Transport;
import net.schmizz.sshj.transport.TransportException;
/**
* Connection layer of the SSH protocol.
*
* @see rfc4254
*/
/** Connection layer of the SSH protocol. Refer to RFC 254. */
public interface Connection {
/**
* Attach a {@link net.schmizz.sshj.connection.channel.Channel} to this connection. A channel must be attached to
* the connection if it is to receive any channel-specific data that is received.
*
* @param chan
*/
void attach(Channel chan);
@@ -60,24 +38,45 @@ public interface Connection {
* Attach a {@link net.schmizz.sshj.connection.channel.forwarded.ForwardedChannelOpener} to this connection, which
* will be delegated opening of any {@code CHANNEL_OPEN} packets {@link net.schmizz.sshj.connection.channel.forwarded.ForwardedChannelOpener#getChannelType()
* for which it is responsible}.
*
* @param opener
*/
void attach(ForwardedChannelOpener opener);
/** Forget an attached {@link Channel}. */
/**
* Forget an attached {@link Channel}.
*
* @param chan
*/
void forget(Channel chan);
/** Forget an attached {@link net.schmizz.sshj.connection.channel.forwarded.ForwardedChannelOpener}. */
/**
* Forget an attached {@link net.schmizz.sshj.connection.channel.forwarded.ForwardedChannelOpener}.
*
* @param handler
*/
void forget(ForwardedChannelOpener handler);
/** Returns an attached {@link Channel} of specified channel-id, or {@code null} if no such channel was attached */
/**
* Returns an attached {@link Channel} of specified channel-id, or {@code null} if no such channel was attached
*
* @param id
*/
Channel get(int id);
/** Wait for the situation that no channels are attached (e.g., got closed). */
void join() throws InterruptedException;
/**
* Wait for the situation that no channels are attached (e.g., got closed).
*
* @throws InterruptedException
*/
void join()
throws InterruptedException;
/**
* Returns an attached {@link net.schmizz.sshj.connection.channel.forwarded.ForwardedChannelOpener} of specified
* channel-type, or {@code null} if no such channel was attached
* @param chanType channel type
*
* @return an attached {@link ForwardedChannelOpener} of specified channel-type, or {@code null} if no such channel
* was attached
*/
ForwardedChannelOpener get(String chanType);
@@ -97,7 +96,8 @@ public interface Connection {
* @throws TransportException if there is an error sending the request
*/
public Future<SSHPacket, ConnectionException> sendGlobalRequest(String name, boolean wantReply,
byte[] specifics) throws TransportException;
byte[] specifics)
throws TransportException;
/**
* Send a {@code SSH_MSG_OPEN_FAILURE} for specified {@code Reason} and {@code message}.
@@ -108,7 +108,8 @@ public interface Connection {
*
* @throws TransportException
*/
void sendOpenFailure(int recipient, OpenFailException.Reason reason, String message) throws TransportException;
void sendOpenFailure(int recipient, OpenFailException.Reason reason, String message)
throws TransportException;
/**
* Get the maximum packet size for the local window this connection recommends to any {@link Channel}'s that ask for

View File

@@ -12,26 +12,6 @@
* 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.
*
* This file may incorporate work covered by the following copyright and
* permission notice:
*
* 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 net.schmizz.sshj.connection;
@@ -40,7 +20,8 @@ import net.schmizz.sshj.common.DisconnectReason;
import net.schmizz.sshj.common.SSHException;
/** Connection-layer exception. */
public class ConnectionException extends SSHException {
public class ConnectionException
extends SSHException {
public static final ExceptionChainer<ConnectionException> chainer = new ExceptionChainer<ConnectionException>() {
public ConnectionException chain(Throwable t) {

View File

@@ -37,7 +37,9 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
/** {@link Connection} implementation. */
public class ConnectionImpl extends AbstractService implements Connection {
public class ConnectionImpl
extends AbstractService
implements Connection {
private final Object internalSynchronizer = new Object();
@@ -93,7 +95,8 @@ public class ConnectionImpl extends AbstractService implements Connection {
openers.put(opener.getChannelType(), opener);
}
private Channel getChannel(SSHPacket buffer) throws ConnectionException {
private Channel getChannel(SSHPacket buffer)
throws ConnectionException {
int recipient = buffer.readInt();
Channel channel = get(recipient);
if (channel != null)
@@ -106,7 +109,8 @@ public class ConnectionImpl extends AbstractService implements Connection {
}
@Override
public void handle(Message msg, SSHPacket buf) throws SSHException {
public void handle(Message msg, SSHPacket buf)
throws SSHException {
if (msg.in(91, 100))
getChannel(buf).handle(msg, buf);
@@ -162,7 +166,8 @@ public class ConnectionImpl extends AbstractService implements Connection {
this.windowSize = windowSize;
}
public void join() throws InterruptedException {
public void join()
throws InterruptedException {
synchronized (internalSynchronizer) {
while (!channels.isEmpty())
internalSynchronizer.wait();
@@ -174,10 +179,12 @@ public class ConnectionImpl extends AbstractService implements Connection {
}
public Future<SSHPacket, ConnectionException> sendGlobalRequest(String name, boolean wantReply,
byte[] specifics) throws TransportException {
byte[] specifics)
throws TransportException {
synchronized (globalReqFutures) {
log.info("Making global request for `{}`", name);
trans.write(new SSHPacket(Message.GLOBAL_REQUEST).putString(name).putBoolean(wantReply).putRawBytes(specifics));
trans.write(new SSHPacket(Message.GLOBAL_REQUEST).putString(name)
.putBoolean(wantReply).putRawBytes(specifics));
Future<SSHPacket, ConnectionException> future = null;
if (wantReply) {
@@ -188,7 +195,8 @@ public class ConnectionImpl extends AbstractService implements Connection {
}
}
private void gotGlobalReqResponse(SSHPacket response) throws ConnectionException {
private void gotGlobalReqResponse(SSHPacket response)
throws ConnectionException {
synchronized (globalReqFutures) {
Future<SSHPacket, ConnectionException> gr = globalReqFutures.poll();
if (gr == null)
@@ -201,7 +209,8 @@ public class ConnectionImpl extends AbstractService implements Connection {
}
}
private void gotChannelOpen(SSHPacket buf) throws ConnectionException, TransportException {
private void gotChannelOpen(SSHPacket buf)
throws ConnectionException, TransportException {
final String type = buf.readString();
log.debug("Received CHANNEL_OPEN for `{}` channel", type);
if (openers.containsKey(type))
@@ -212,17 +221,19 @@ public class ConnectionImpl extends AbstractService implements Connection {
}
}
public void sendOpenFailure(int recipient, Reason reason, String message) throws TransportException {
trans.write(new SSHPacket(Message.CHANNEL_OPEN_FAILURE) //
.putInt(recipient) //
.putInt(reason.getCode()) //
public void sendOpenFailure(int recipient, Reason reason, String message)
throws TransportException {
trans.write(new SSHPacket(Message.CHANNEL_OPEN_FAILURE)
.putInt(recipient)
.putInt(reason.getCode())
.putString(message));
}
@Override
public void notifyDisconnect() throws SSHException {
public void notifyDisconnect()
throws SSHException {
super.notifyDisconnect();
// wh'about them futures?
FutureUtils.alertAll(new ConnectionException("Disconnected."), globalReqFutures);
for (Channel chan : channels.values())
chan.close();
}

View File

@@ -58,7 +58,8 @@ import java.util.Queue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
public abstract class AbstractChannel implements Channel {
public abstract class AbstractChannel
implements Channel {
/** Logger */
protected final Logger log;
@@ -164,7 +165,8 @@ public abstract class AbstractChannel implements Channel {
return type;
}
public void handle(Message msg, SSHPacket buf) throws ConnectionException, TransportException {
public void handle(Message msg, SSHPacket buf)
throws ConnectionException, TransportException {
switch (msg) {
case CHANNEL_DATA:
@@ -205,7 +207,8 @@ public abstract class AbstractChannel implements Channel {
}
}
private void gotClose() throws TransportException {
private void gotClose()
throws TransportException {
log.info("Got close");
try {
closeAllStreams();
@@ -236,7 +239,8 @@ public abstract class AbstractChannel implements Channel {
this.autoExpand = autoExpand;
}
public void close() throws ConnectionException, TransportException {
public void close()
throws ConnectionException, TransportException {
lock.lock();
try {
try {
@@ -251,7 +255,8 @@ public abstract class AbstractChannel implements Channel {
}
}
protected synchronized void sendClose() throws TransportException {
protected synchronized void sendClose()
throws TransportException {
try {
if (!closeRequested) {
log.info("Sending close");
@@ -271,7 +276,8 @@ public abstract class AbstractChannel implements Channel {
}
}
private void gotChannelRequest(SSHPacket buf) throws ConnectionException, TransportException {
private void gotChannelRequest(SSHPacket buf)
throws ConnectionException, TransportException {
final String reqType = buf.readString();
buf.readBoolean(); // We don't care about the 'want-reply' value
log.info("Got chan request for `{}`", reqType);
@@ -289,15 +295,18 @@ public abstract class AbstractChannel implements Channel {
close.set();
}
protected void gotExtendedData(int dataTypeCode, SSHPacket buf) throws ConnectionException, TransportException {
protected void gotExtendedData(int dataTypeCode, SSHPacket buf)
throws ConnectionException, TransportException {
throw new ConnectionException(DisconnectReason.PROTOCOL_ERROR, "Extended data not supported on " + type
+ " channel");
}
protected void gotUnknown(Message msg, SSHPacket buf) throws ConnectionException, TransportException {
protected void gotUnknown(Message msg, SSHPacket buf)
throws ConnectionException, TransportException {
}
protected void handleRequest(String reqType, SSHPacket buf) throws ConnectionException, TransportException {
protected void handleRequest(String reqType, SSHPacket buf)
throws ConnectionException, TransportException {
trans.write(newBuffer(Message.CHANNEL_FAILURE));
}
@@ -305,7 +314,8 @@ public abstract class AbstractChannel implements Channel {
return new SSHPacket(cmd).putInt(recipient);
}
protected void receiveInto(ChannelInputStream stream, SSHPacket buf) throws ConnectionException, TransportException {
protected void receiveInto(ChannelInputStream stream, SSHPacket buf)
throws ConnectionException, TransportException {
final int len = buf.readInt();
if (len < 0 || len > getLocalMaxPacketSize() || len != buf.available())
throw new ConnectionException(DisconnectReason.PROTOCOL_ERROR, "Bad item length: " + len);
@@ -315,7 +325,8 @@ public abstract class AbstractChannel implements Channel {
}
protected synchronized Event<ConnectionException> sendChannelRequest(String reqType, boolean wantReply,
Buffer.PlainBuffer reqSpecific) throws TransportException {
Buffer.PlainBuffer reqSpecific)
throws TransportException {
log.info("Sending channel request for `{}`", reqType);
trans.write(
newBuffer(Message.CHANNEL_REQUEST)
@@ -332,7 +343,8 @@ public abstract class AbstractChannel implements Channel {
return responseEvent;
}
private synchronized void gotResponse(boolean success) throws ConnectionException {
private synchronized void gotResponse(boolean success)
throws ConnectionException {
final Event<ConnectionException> responseEvent = chanReqResponseEvents.poll();
if (responseEvent != null) {
if (success)
@@ -345,7 +357,8 @@ public abstract class AbstractChannel implements Channel {
"Received response to channel request when none was requested");
}
private synchronized void gotEOF() throws TransportException {
private synchronized void gotEOF()
throws TransportException {
log.info("Got EOF");
eofGot = true;
eofInputStreams();
@@ -358,7 +371,8 @@ public abstract class AbstractChannel implements Channel {
in.eof();
}
public synchronized void sendEOF() throws TransportException {
public synchronized void sendEOF()
throws TransportException {
try {
if (!closeRequested && !eofSent) {
log.info("Sending EOF");

View File

@@ -12,26 +12,6 @@
* 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.
*
* This file may incorporate work covered by the following copyright and
* permission notice:
*
* 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 net.schmizz.sshj.connection.channel;
@@ -45,10 +25,12 @@ import java.io.InputStream;
import java.io.OutputStream;
/** A channel is the basic medium for application-layer data on top of an SSH transport. */
public interface Channel extends Closeable, SSHPacketHandler, ErrorNotifiable {
public interface Channel
extends Closeable, SSHPacketHandler, ErrorNotifiable {
/** Direct channels are those that are initiated by us. */
interface Direct extends Channel {
interface Direct
extends Channel {
/**
* Request opening this channel from remote end.
*
@@ -57,19 +39,22 @@ public interface Channel extends Closeable, SSHPacketHandler, ErrorNotifiable {
* other connection-layer error
* @throws TransportException error writing packets etc.
*/
void open() throws OpenFailException, ConnectionException, TransportException;
void open()
throws OpenFailException, ConnectionException, TransportException;
}
/** Forwarded channels are those that are initiated by the server. */
interface Forwarded extends Channel {
interface Forwarded
extends Channel {
/**
* Confirm {@code CHANNEL_OPEN} request.
*
* @throws TransportException error sending confirmation packet
*/
void confirm() throws TransportException;
void confirm()
throws TransportException;
/** Returns the IP of where the forwarded connection originates. */
String getOriginatorIP();
@@ -85,13 +70,15 @@ public interface Channel extends Closeable, SSHPacketHandler, ErrorNotifiable {
*
* @throws TransportException error sending rejection packet
*/
void reject(OpenFailException.Reason reason, String message) throws TransportException;
void reject(OpenFailException.Reason reason, String message)
throws TransportException;
}
/** Close this channel. */
void close() throws TransportException, ConnectionException;
void close()
throws TransportException, ConnectionException;
/**
* Returns whether auto-expansion of local window is set.
@@ -103,38 +90,41 @@ public interface Channel extends Closeable, SSHPacketHandler, ErrorNotifiable {
/** Returns the channel ID */
int getID();
/** Returns the {@code InputStream} for this channel. */
/** @return the {@code InputStream} for this channel. */
InputStream getInputStream();
/** Returns the maximum packet size that we have specified. */
/** @return the maximum packet size that we have specified. */
int getLocalMaxPacketSize();
/** Returns the current local window size. */
/** @return the current local window size. */
int getLocalWinSize();
/** Returns an {@code OutputStream} for this channel. */
/** @return an {@code OutputStream} for this channel. */
OutputStream getOutputStream();
/** Returns the channel ID at the remote end. */
/** @return the channel ID at the remote end. */
int getRecipient();
/** Returns the maximum packet size as specified by the remote end. */
/** @return the maximum packet size as specified by the remote end. */
int getRemoteMaxPacketSize();
/** Returns the current remote window size. */
/** @return the current remote window size. */
int getRemoteWinSize();
/** Returns the channel type identifier. */
/** @return the channel type identifier. */
String getType();
/** Returns whether the channel is open. */
/** @return whether the channel is open. */
boolean isOpen();
/**
* Sends an EOF message to the server for this channel; indicating that no more data will be sent by us. The {@code
* OutputStream} for this channel will be closed and no longer usable.
*
* @throws TransportException
*/
void sendEOF() throws TransportException;
void sendEOF()
throws TransportException;
/**
* Set whether local window should automatically expand when data is received, irrespective of whether data has been

View File

@@ -55,7 +55,9 @@ import java.io.InterruptedIOException;
* {@link InputStream} for channels. Can {@link #receive(byte[], int, int) receive} data into its buffer for serving to
* readers.
*/
public final class ChannelInputStream extends InputStream implements ErrorNotifiable {
public final class ChannelInputStream
extends InputStream
implements ErrorNotifiable {
private final Logger log;
@@ -104,14 +106,16 @@ public final class ChannelInputStream extends InputStream implements ErrorNotifi
}
@Override
public int read() throws IOException {
public int read()
throws IOException {
synchronized (b) {
return read(b, 0, 1) == -1 ? -1 : b[0];
}
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
public int read(byte[] b, int off, int len)
throws IOException {
synchronized (buf) {
for (; ;) {
if (buf.available() > 0)
@@ -140,7 +144,8 @@ public final class ChannelInputStream extends InputStream implements ErrorNotifi
return len;
}
public void receive(byte[] data, int offset, int len) throws ConnectionException, TransportException {
public void receive(byte[] data, int offset, int len)
throws ConnectionException, TransportException {
if (eof)
throw new ConnectionException("Getting data on EOF'ed stream");
synchronized (buf) {
@@ -152,12 +157,14 @@ public final class ChannelInputStream extends InputStream implements ErrorNotifi
checkWindow();
}
private void checkWindow() throws TransportException {
private void checkWindow()
throws TransportException {
synchronized (win) {
final int adjustment = win.neededAdjustment();
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).putInt(chan.getRecipient()).putInt(adjustment));
trans.write(new SSHPacket(Message.CHANNEL_WINDOW_ADJUST)
.putInt(chan.getRecipient()).putInt(adjustment));
win.expand(adjustment);
}
}

View File

@@ -49,7 +49,9 @@ import java.io.OutputStream;
* {@link OutputStream} for channels. Buffers data upto the remote window's maximum packet size. Data can also be
* flushed via {@link #flush()} and is also flushed on {@link #close()}.
*/
public final class ChannelOutputStream extends OutputStream implements ErrorNotifiable {
public final class ChannelOutputStream
extends OutputStream
implements ErrorNotifiable {
private final Channel chan;
private Transport trans;
@@ -77,13 +79,15 @@ public final class ChannelOutputStream extends OutputStream implements ErrorNoti
}
@Override
public synchronized void write(int w) throws IOException {
public synchronized void write(int w)
throws IOException {
b[0] = (byte) w;
write(b, 0, 1);
}
@Override
public synchronized void write(byte[] data, int off, int len) throws IOException {
public synchronized void write(byte[] data, int off, int len)
throws IOException {
checkClose();
while (len > 0) {
final int x = Math.min(len, win.getMaxPacketSize() - bufferLength);
@@ -102,7 +106,8 @@ public final class ChannelOutputStream extends OutputStream implements ErrorNoti
this.error = error;
}
private synchronized void checkClose() throws SSHException {
private synchronized void checkClose()
throws SSHException {
if (closed)
if (error != null)
throw error;
@@ -111,7 +116,8 @@ public final class ChannelOutputStream extends OutputStream implements ErrorNoti
}
@Override
public synchronized void close() throws IOException {
public synchronized void close()
throws IOException {
if (!closed)
try {
flush();
@@ -126,7 +132,8 @@ public final class ChannelOutputStream extends OutputStream implements ErrorNoti
}
@Override
public synchronized void flush() throws IOException {
public synchronized void flush()
throws IOException {
checkClose();
if (bufferLength <= 0) // No data to send

View File

@@ -12,35 +12,20 @@
* 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.
*
* This file may incorporate work covered by the following copyright and
* permission notice:
*
* 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 net.schmizz.sshj.connection.channel;
import net.schmizz.sshj.connection.ConnectionException;
public class OpenFailException extends ConnectionException {
public class OpenFailException
extends ConnectionException {
public enum Reason {
UNKNOWN(0), ADMINISTRATIVELY_PROHIBITED(1), CONNECT_FAILED(2), UNKNOWN_CHANNEL_TYPE(3), RESOURCE_SHORTAGE(4);
UNKNOWN(0),
ADMINISTRATIVELY_PROHIBITED(1),
CONNECT_FAILED(2),
UNKNOWN_CHANNEL_TYPE(3),
RESOURCE_SHORTAGE(4);
public static Reason fromInt(int code) {
for (Reason rc : Reason.values())

View File

@@ -68,13 +68,15 @@ public abstract class Window {
}
/** Controls how much data we can send before an adjustment notification from remote end is required. */
public static final class Remote extends Window {
public static final class Remote
extends Window {
public Remote(int chanID, int initialWinSize, int maxPacketSize) {
super(chanID, "remote win", initialWinSize, maxPacketSize);
}
public void waitAndConsume(int howMuch) throws ConnectionException {
public void waitAndConsume(int howMuch)
throws ConnectionException {
synchronized (lock) {
while (size < howMuch) {
log.debug("Waiting, need window space for {} bytes", howMuch);
@@ -91,7 +93,8 @@ public abstract class Window {
}
/** Controls how much data remote end can send before an adjustment notification from us is required. */
public static final class Local extends Window {
public static final class Local
extends Window {
private final int initialSize;
private final int threshold;
@@ -102,7 +105,8 @@ public abstract class Window {
threshold = Math.min(maxPacketSize * 20, initialSize / 4);
}
public int neededAdjustment() throws TransportException {
public int neededAdjustment()
throws TransportException {
synchronized (lock) {
return (size - threshold <= 0) ? (initialSize - size) : 0;
}

View File

@@ -47,7 +47,9 @@ import net.schmizz.sshj.transport.TransportException;
import java.util.concurrent.TimeUnit;
/** Base class for direct channels whose open is initated by the client. */
public abstract class AbstractDirectChannel extends AbstractChannel implements Channel.Direct {
public abstract class AbstractDirectChannel
extends AbstractChannel
implements Channel.Direct {
protected AbstractDirectChannel(String name, Connection conn) {
super(name, conn);
@@ -58,7 +60,8 @@ public abstract class AbstractDirectChannel extends AbstractChannel implements C
conn.attach(this);
}
public void open() throws ConnectionException, TransportException {
public void open()
throws ConnectionException, TransportException {
trans.write(buildOpenReq());
open.await(conn.getTimeout(), TimeUnit.SECONDS);
}
@@ -82,7 +85,8 @@ public abstract class AbstractDirectChannel extends AbstractChannel implements C
}
@Override
protected void gotUnknown(Message cmd, SSHPacket buf) throws ConnectionException, TransportException {
protected void gotUnknown(Message cmd, SSHPacket buf)
throws ConnectionException, TransportException {
switch (cmd) {
case CHANNEL_OPEN_CONFIRMATION:

View File

@@ -51,7 +51,8 @@ import java.net.SocketAddress;
public class LocalPortForwarder {
private class DirectTCPIPChannel extends AbstractDirectChannel {
private class DirectTCPIPChannel
extends AbstractDirectChannel {
private final Socket sock;
@@ -60,13 +61,15 @@ public class LocalPortForwarder {
this.sock = sock;
}
private void start() throws IOException {
private void start()
throws IOException {
sock.setSendBufferSize(getLocalMaxPacketSize());
sock.setReceiveBufferSize(getRemoteMaxPacketSize());
final ErrorCallback closer = StreamCopier.closeOnErrorCallback(this,
new Closeable() {
public void close() throws IOException {
public void close()
throws IOException {
sock.close();
}
});
@@ -102,7 +105,8 @@ public class LocalPortForwarder {
private final String host;
private final int port;
public LocalPortForwarder(Connection conn, SocketAddress listeningAddr, String host, int port) throws IOException {
public LocalPortForwarder(Connection conn, SocketAddress listeningAddr, String host, int port)
throws IOException {
this(ServerSocketFactory.getDefault(), conn, listeningAddr, host, port);
}
@@ -118,7 +122,8 @@ public class LocalPortForwarder {
*
* @throws IOException if there is an error binding on specified {@code listeningAddr}
*/
public LocalPortForwarder(ServerSocketFactory ssf, Connection conn, SocketAddress listeningAddr, String host, int port) throws IOException {
public LocalPortForwarder(ServerSocketFactory ssf, Connection conn, SocketAddress listeningAddr, String host, int port)
throws IOException {
this.conn = conn;
this.host = host;
this.port = port;
@@ -132,7 +137,8 @@ public class LocalPortForwarder {
}
/** Start listening for incoming connections and forward to remote host as a channel. */
public void listen() throws IOException {
public void listen()
throws IOException {
log.info("Listening on {}", ss.getLocalSocketAddress());
Socket sock;
while (true) {

View File

@@ -56,10 +56,12 @@ import java.util.Map;
* @see Shell
* @see Subsystem
*/
public interface Session extends Channel {
public interface Session
extends Channel {
/** Command API. */
interface Command extends Channel {
interface Command
extends Channel {
/**
* Read from the command's {@code stderr} stream into a string (blocking).
@@ -68,7 +70,8 @@ public interface Session extends Channel {
*
* @throws IOException if error reading from the stream
*/
String getErrorAsString() throws IOException;
String getErrorAsString()
throws IOException;
/** Returns the command's {@code stderr} stream. */
InputStream getErrorStream();
@@ -105,7 +108,8 @@ public interface Session extends Channel {
*
* @throws IOException if error reading from the stream
*/
String getOutputAsString() throws IOException;
String getOutputAsString()
throws IOException;
/**
* Send a signal to the remote command.
@@ -114,12 +118,14 @@ public interface Session extends Channel {
*
* @throws TransportException if error sending the signal
*/
void signal(Signal signal) throws TransportException;
void signal(Signal signal)
throws TransportException;
}
/** Shell API. */
interface Shell extends Channel {
interface Shell
extends Channel {
/**
* Whether the client can do local flow control using {@code control-S} and {@code control-Q}.
@@ -139,7 +145,8 @@ public interface Session extends Channel {
*
* @throws TransportException
*/
void changeWindowDimensions(int cols, int rows, int width, int height) throws TransportException;
void changeWindowDimensions(int cols, int rows, int width, int height)
throws TransportException;
/** Returns the shell's {@code stderr} stream. */
InputStream getErrorStream();
@@ -151,12 +158,14 @@ public interface Session extends Channel {
*
* @throws TransportException if error sending the signal
*/
void signal(Signal signal) throws TransportException;
void signal(Signal signal)
throws TransportException;
}
/** Subsystem API. */
interface Subsystem extends Channel {
interface Subsystem
extends Channel {
Integer getExitStatus();
}
@@ -167,7 +176,8 @@ public interface Session extends Channel {
*
* @throws TransportException
*/
void allocateDefaultPTY() throws ConnectionException, TransportException;
void allocateDefaultPTY()
throws ConnectionException, TransportException;
/**
* Allocate a psuedo-terminal for this session.
@@ -197,7 +207,8 @@ public interface Session extends Channel {
* @throws ConnectionException if the request to execute the command failed
* @throws TransportException if there is an error sending the request
*/
Command exec(String command) throws ConnectionException, TransportException;
Command exec(String command)
throws ConnectionException, TransportException;
/**
* Request X11 forwarding.
@@ -209,7 +220,8 @@ public interface Session extends Channel {
* @throws ConnectionException if the request failed
* @throws TransportException if there was an error sending the request
*/
void reqX11Forwarding(String authProto, String authCookie, int screen) throws ConnectionException,
void reqX11Forwarding(String authProto, String authCookie, int screen)
throws ConnectionException,
TransportException;
/**
@@ -221,7 +233,8 @@ public interface Session extends Channel {
* @throws ConnectionException if the request failed
* @throws TransportException if there was an error sending the request
*/
void setEnvVar(String name, String value) throws ConnectionException, TransportException;
void setEnvVar(String name, String value)
throws ConnectionException, TransportException;
/**
* Request a shell.
@@ -231,7 +244,8 @@ public interface Session extends Channel {
* @throws ConnectionException if the request failed
* @throws TransportException if there was an error sending the request
*/
Shell startShell() throws ConnectionException, TransportException;
Shell startShell()
throws ConnectionException, TransportException;
/**
* Request a subsystem.
@@ -243,6 +257,7 @@ public interface Session extends Channel {
* @throws ConnectionException if the request failed
* @throws TransportException if there was an error sending the request
*/
Subsystem startSubsystem(String name) throws ConnectionException, TransportException;
Subsystem startSubsystem(String name)
throws ConnectionException, TransportException;
}

View File

@@ -52,8 +52,9 @@ import java.util.concurrent.TimeUnit;
/** {@link Session} implementation. */
public class
SessionChannel extends AbstractDirectChannel implements Session, Session.Command, Session.Shell,
Session.Subsystem {
SessionChannel
extends AbstractDirectChannel
implements Session, Session.Command, Session.Shell, Session.Subsystem {
private Integer exitStatus;
@@ -69,7 +70,8 @@ public class
super("session", conn);
}
public void allocateDefaultPTY() throws ConnectionException, TransportException {
public void allocateDefaultPTY()
throws ConnectionException, TransportException {
// TODO FIXME (maybe?): These modes were originally copied from what SSHD was doing;
// and then the echo modes were set to 0 to better serve the PTY example.
// Not sure what default PTY modes should be.
@@ -103,7 +105,8 @@ public class
return canDoFlowControl;
}
public void changeWindowDimensions(int cols, int rows, int width, int height) throws TransportException {
public void changeWindowDimensions(int cols, int rows, int width, int height)
throws TransportException {
sendChannelRequest(
"pty-req",
false,
@@ -115,13 +118,16 @@ public class
);
}
public Command exec(String command) throws ConnectionException, TransportException {
public Command exec(String command)
throws ConnectionException, TransportException {
log.info("Will request to exec `{}`", command);
sendChannelRequest("exec", true, new Buffer.PlainBuffer().putString(command)).await(conn.getTimeout(), TimeUnit.SECONDS);
sendChannelRequest("exec", true, new Buffer.PlainBuffer().putString(command))
.await(conn.getTimeout(), TimeUnit.SECONDS);
return this;
}
public String getErrorAsString() throws IOException {
public String getErrorAsString()
throws IOException {
return StreamCopier.copyStreamToString(err);
}
@@ -141,12 +147,14 @@ public class
return exitStatus;
}
public String getOutputAsString() throws IOException {
public String getOutputAsString()
throws IOException {
return StreamCopier.copyStreamToString(getInputStream());
}
@Override
public void handleRequest(String req, SSHPacket buf) throws ConnectionException, TransportException {
public void handleRequest(String req, SSHPacket buf)
throws ConnectionException, TransportException {
if ("xon-xoff".equals(req))
canDoFlowControl = buf.readBoolean();
else if ("exit-status".equals(req))
@@ -160,7 +168,8 @@ public class
super.handleRequest(req, buf);
}
public void reqX11Forwarding(String authProto, String authCookie, int screen) throws ConnectionException,
public void reqX11Forwarding(String authProto, String authCookie, int screen)
throws ConnectionException,
TransportException {
sendChannelRequest(
"x11-req",
@@ -173,22 +182,28 @@ public class
).await(conn.getTimeout(), TimeUnit.SECONDS);
}
public void setEnvVar(String name, String value) throws ConnectionException, TransportException {
sendChannelRequest("env", true, new Buffer.PlainBuffer().putString(name).putString(value)).await(conn.getTimeout(), TimeUnit.SECONDS);
public void setEnvVar(String name, String value)
throws ConnectionException, TransportException {
sendChannelRequest("env", true, new Buffer.PlainBuffer().putString(name).putString(value))
.await(conn.getTimeout(), TimeUnit.SECONDS);
}
public void signal(Signal sig) throws TransportException {
public void signal(Signal sig)
throws TransportException {
sendChannelRequest("signal", false, new Buffer.PlainBuffer().putString(sig.toString()));
}
public Shell startShell() throws ConnectionException, TransportException {
public Shell startShell()
throws ConnectionException, TransportException {
sendChannelRequest("shell", true, null).await(conn.getTimeout(), TimeUnit.SECONDS);
return this;
}
public Subsystem startSubsystem(String name) throws ConnectionException, TransportException {
public Subsystem startSubsystem(String name)
throws ConnectionException, TransportException {
log.info("Will request `{}` subsystem", name);
sendChannelRequest("subsystem", true, new Buffer.PlainBuffer().putString(name)).await(conn.getTimeout(), TimeUnit.SECONDS);
sendChannelRequest("subsystem", true, new Buffer.PlainBuffer().putString(name))
.await(conn.getTimeout(), TimeUnit.SECONDS);
return this;
}
@@ -209,7 +224,8 @@ public class
}
@Override
protected void gotExtendedData(int dataTypeCode, SSHPacket buf) throws ConnectionException, TransportException {
protected void gotExtendedData(int dataTypeCode, SSHPacket buf)
throws ConnectionException, TransportException {
if (dataTypeCode == 1)
receiveInto(err, buf);
else

View File

@@ -30,6 +30,7 @@ public interface SessionFactory {
* @throws SSHException
* @see {@link Session}
*/
Session startSession() throws SSHException;
Session startSession()
throws SSHException;
}

View File

@@ -39,8 +39,21 @@ package net.schmizz.sshj.connection.channel.direct;
/** Various signals that may be sent or received. The signals are from POSIX and simply miss the {@code "SIG_"} prefix. */
public enum Signal {
ABRT("ABRT"), ALRM("ALRM"), FPE("FPE"), HUP("HUP"), ILL("ILL"), INT("INT"), KILL("KILL"), PIPE("PIPE"), QUIT(
"QUIT"), SEGV("SEGV"), TERM("TERM"), USR1("USR1"), USR2("USR2"), UNKNOWN("UNKNOWN");
ABRT("ABRT"),
ALRM("ALRM"),
FPE("FPE"),
HUP("HUP"),
ILL("ILL"),
INT("INT"),
KILL("KILL"),
PIPE("PIPE"),
QUIT(
"QUIT"),
SEGV("SEGV"),
TERM("TERM"),
USR1("USR1"),
USR2("USR2"),
UNKNOWN("UNKNOWN");
/**
* Create from the string representation used when the signal is received as part of an SSH packet.

View File

@@ -43,7 +43,9 @@ import net.schmizz.sshj.connection.channel.OpenFailException.Reason;
import net.schmizz.sshj.transport.TransportException;
/** Base class for forwarded channels whose open is initiated by the server. */
public abstract class AbstractForwardedChannel extends AbstractChannel implements Channel.Forwarded {
public abstract class AbstractForwardedChannel
extends AbstractChannel
implements Channel.Forwarded {
protected final String origIP;
protected final int origPort;
@@ -60,7 +62,8 @@ public abstract class AbstractForwardedChannel extends AbstractChannel implement
init(recipient, remoteWinSize, remoteMaxPacketSize);
}
public void confirm() throws TransportException {
public void confirm()
throws TransportException {
log.info("Confirming `{}` channel #{}", getType(), getID());
// Must ensure channel is attached before confirming, data could start coming in immediately!
conn.attach(this);
@@ -71,7 +74,8 @@ public abstract class AbstractForwardedChannel extends AbstractChannel implement
open.set();
}
public void reject(Reason reason, String message) throws TransportException {
public void reject(Reason reason, String message)
throws TransportException {
log.info("Rejecting `{}` channel: {}", getType(), message);
conn.sendOpenFailure(getRecipient(), reason, message);
}

View File

@@ -12,26 +12,6 @@
* 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.
*
* This file may incorporate work covered by the following copyright and
* permission notice:
*
* 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 net.schmizz.sshj.connection.channel.forwarded;
@@ -47,7 +27,8 @@ import org.slf4j.LoggerFactory;
import java.io.IOException;
/** Base class for {@link net.schmizz.sshj.connection.channel.forwarded.ForwardedChannelOpener}'s. */
public abstract class AbstractForwardedChannelOpener implements ForwardedChannelOpener {
public abstract class AbstractForwardedChannelOpener
implements ForwardedChannelOpener {
protected final Logger log = LoggerFactory.getLogger(getClass());

View File

@@ -24,13 +24,14 @@ public interface ConnectListener {
/**
* Notify this listener of a new forwarded channel. An implementation should firstly {@link
* net.schmizz.sshj.connection.channel.Channel.Forwarded#confirm() confirm} or {@link
* net.schmizz.sshj.connection.channel.Channel.Forwarded#reject() reject} that channel.
* Channel.Forwarded#confirm() confirm} or {@link Channel.Forwarded#reject(net.schmizz.sshj.connection.channel.OpenFailException.Reason,
* String)} reject} that channel.
*
* @param chan the {@link net.schmizz.sshj.connection.channel.Channel.Forwarded forwarded channel}
*
* @throws java.io.IOException
* @throws IOException
*/
void gotConnect(Channel.Forwarded chan) throws IOException;
void gotConnect(Channel.Forwarded chan)
throws IOException;
}

View File

@@ -31,6 +31,7 @@ public interface ForwardedChannelOpener {
* @param buf {@link net.schmizz.sshj.common.SSHPacket} containg the request except for the message identifier and
* channel type field
*/
void handleOpen(SSHPacket buf) throws ConnectionException, TransportException;
void handleOpen(SSHPacket buf)
throws ConnectionException, TransportException;
}

View File

@@ -12,26 +12,6 @@
* 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.
*
* This file may incorporate work covered by the following copyright and
* permission notice:
*
* 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 net.schmizz.sshj.connection.channel.forwarded;
@@ -48,7 +28,8 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
/** Handles remote port forwarding. */
public class RemotePortForwarder extends AbstractForwardedChannelOpener {
public class RemotePortForwarder
extends AbstractForwardedChannelOpener {
/**
* Represents a particular forwarding. From RFC 4254, s. 7.1
@@ -139,14 +120,16 @@ public class RemotePortForwarder extends AbstractForwardedChannelOpener {
}
/** A {@code forwarded-tcpip} channel. */
public static class ForwardedTCPIPChannel extends AbstractForwardedChannel {
public static class ForwardedTCPIPChannel
extends AbstractForwardedChannel {
public static final String TYPE = "forwarded-tcpip";
private final Forward fwd;
public ForwardedTCPIPChannel(Connection conn, int recipient, int remoteWinSize, int remoteMaxPacketSize,
Forward fwd, String origIP, int origPort) throws TransportException {
Forward fwd, String origIP, int origPort)
throws TransportException {
super(TYPE, conn, recipient, remoteWinSize, remoteMaxPacketSize, origIP, origPort);
this.fwd = fwd;
}
@@ -182,7 +165,8 @@ public class RemotePortForwarder extends AbstractForwardedChannelOpener {
* @throws ConnectionException if there is an error requesting the forwarding
* @throws TransportException
*/
public Forward bind(Forward forward, ConnectListener listener) throws ConnectionException, TransportException {
public Forward bind(Forward forward, ConnectListener listener)
throws ConnectionException, TransportException {
SSHPacket reply = req(PF_REQ, forward);
if (forward.port == 0)
forward.port = reply.readInt();
@@ -199,7 +183,8 @@ public class RemotePortForwarder extends AbstractForwardedChannelOpener {
* @throws ConnectionException if there is an error with the cancellation request
* @throws TransportException
*/
public void cancel(Forward forward) throws ConnectionException, TransportException {
public void cancel(Forward forward)
throws ConnectionException, TransportException {
try {
req(PF_CANCEL, forward);
} finally {
@@ -207,8 +192,10 @@ public class RemotePortForwarder extends AbstractForwardedChannelOpener {
}
}
protected SSHPacket req(String reqName, Forward forward) throws ConnectionException, TransportException {
final byte[] specifics = new Buffer.PlainBuffer().putString(forward.address).putInt(forward.port).getCompactData();
protected SSHPacket req(String reqName, Forward forward)
throws ConnectionException, TransportException {
final byte[] specifics = new Buffer.PlainBuffer().putString(forward.address).putInt(forward.port)
.getCompactData();
return conn.sendGlobalRequest(reqName, true, specifics)
.get(conn.getTimeout(), TimeUnit.SECONDS);
}
@@ -222,7 +209,8 @@ public class RemotePortForwarder extends AbstractForwardedChannelOpener {
* Internal API. Creates a {@link ForwardedTCPIPChannel} from the {@code CHANNEL_OPEN} request and calls associated
* {@code ConnectListener} for that forward in a separate thread.
*/
public void handleOpen(SSHPacket buf) throws ConnectionException, TransportException {
public void handleOpen(SSHPacket buf)
throws ConnectionException, TransportException {
final ForwardedTCPIPChannel chan = new ForwardedTCPIPChannel(conn, buf.readInt(), buf.readInt(), buf.readInt(),
new Forward(buf.readString(), buf.readInt()),
buf.readString(), buf.readInt());

View File

@@ -30,7 +30,8 @@ import java.net.SocketAddress;
* A {@link net.schmizz.sshj.connection.channel.forwarded.ConnectListener} that forwards what is received over the
* channel to a socket and vice-versa.
*/
public class SocketForwardingConnectListener implements ConnectListener {
public class SocketForwardingConnectListener
implements ConnectListener {
protected final Logger log = LoggerFactory.getLogger(getClass());
@@ -42,7 +43,8 @@ public class SocketForwardingConnectListener implements ConnectListener {
}
/** On connect, confirm the channel and start forwarding. */
public void gotConnect(Channel.Forwarded chan) throws IOException {
public void gotConnect(Channel.Forwarded chan)
throws IOException {
log.info("New connection from " + chan.getOriginatorIP() + ":" + chan.getOriginatorPort());
final Socket sock = new Socket();
@@ -55,7 +57,8 @@ public class SocketForwardingConnectListener implements ConnectListener {
chan.confirm();
final ErrorCallback closer = StreamCopier.closeOnErrorCallback(chan, new Closeable() {
public void close() throws IOException {
public void close()
throws IOException {
sock.close();
}
});

View File

@@ -24,10 +24,12 @@ import net.schmizz.sshj.transport.TransportException;
* Handles forwarded {@code x11} channels. The actual request to forward X11 should be made from the specific {@link
* net.schmizz.sshj.connection.channel.direct.Session}.
*/
public class X11Forwarder extends AbstractForwardedChannelOpener {
public class X11Forwarder
extends AbstractForwardedChannelOpener {
/** An {@code x11} forwarded channel. */
public static class X11Channel extends AbstractForwardedChannel {
public static class X11Channel
extends AbstractForwardedChannel {
public static final String TYPE = "x11";
@@ -52,7 +54,8 @@ public class X11Forwarder extends AbstractForwardedChannelOpener {
}
/** Internal API */
public void handleOpen(SSHPacket buf) throws ConnectionException, TransportException {
public void handleOpen(SSHPacket buf)
throws ConnectionException, TransportException {
callListener(listener, new X11Channel(conn, buf.readInt(), buf.readInt(), buf.readInt(), buf.readString(), buf
.readInt()));
}