148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood/* 248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Please refer to the LICENSE.txt for licensing details. 448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodpackage ch.ethz.ssh2; 648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport java.io.CharArrayWriter; 848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport java.io.File; 948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport java.io.FileReader; 1048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport java.io.IOException; 1148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport java.net.InetSocketAddress; 1248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport java.net.SocketTimeoutException; 1348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport java.security.SecureRandom; 1448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport java.util.List; 1548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport java.util.Vector; 1648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 1748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport ch.ethz.ssh2.auth.AuthenticationManager; 1848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport ch.ethz.ssh2.channel.ChannelManager; 1948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport ch.ethz.ssh2.crypto.CryptoWishList; 2048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport ch.ethz.ssh2.crypto.cipher.BlockCipherFactory; 2148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport ch.ethz.ssh2.crypto.digest.MAC; 2248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport ch.ethz.ssh2.packets.PacketIgnore; 2348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport ch.ethz.ssh2.transport.KexManager; 2448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport ch.ethz.ssh2.transport.TransportManager; 2548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport ch.ethz.ssh2.util.TimeoutService; 2648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport ch.ethz.ssh2.util.TimeoutService.TimeoutToken; 2748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 2848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood/** 2948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * A <code>Connection</code> is used to establish an encrypted TCP/IP 3048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * connection to a SSH-2 server. 3148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 3248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Typically, one 3348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <ol> 3448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <li>creates a {@link #Connection(String) Connection} object.</li> 3548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <li>calls the {@link #connect() connect()} method.</li> 3648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <li>calls some of the authentication methods (e.g., {@link #authenticateWithPublicKey(String, File, String) authenticateWithPublicKey()}).</li> 3748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <li>calls one or several times the {@link #openSession() openSession()} method.</li> 3848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <li>finally, one must close the connection and release resources with the {@link #close() close()} method.</li> 3948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * </ol> 4048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 4148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @author Christian Plattner 4248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @version $Id: Connection.java 37 2011-05-28 22:31:46Z dkocher@sudo.ch $ 4348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 4448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 4548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodpublic class Connection 4648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood{ 4748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 4848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * The identifier presented to the SSH-2 server. 4948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 5048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood private String identification = "Ganymed-" + Version.getSpecification(); 5148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 5248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* Will be used to generate all random data needed for the current connection. 5348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Note: SecureRandom.nextBytes() is thread safe. 5448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 5548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 5648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood private SecureRandom generator; 5748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 5848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 5948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Unless you know what you are doing, you will never need this. 6048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 6148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @return The list of supported cipher algorithms by this implementation. 6248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 6348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public static synchronized String[] getAvailableCiphers() 6448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 6548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return BlockCipherFactory.getDefaultCipherList(); 6648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 6748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 6848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 6948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Unless you know what you are doing, you will never need this. 7048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 7148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @return The list of supported MAC algorthims by this implementation. 7248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 7348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public static synchronized String[] getAvailableMACs() 7448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 7548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return MAC.getMacList(); 7648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 7748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 7848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 7948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Unless you know what you are doing, you will never need this. 8048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 8148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @return The list of supported server host key algorthims by this implementation. 8248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 8348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public static synchronized String[] getAvailableServerHostKeyAlgorithms() 8448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 8548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return KexManager.getDefaultServerHostkeyAlgorithmList(); 8648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 8748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 8848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood private AuthenticationManager am; 8948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 9048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood private boolean authenticated = false; 9148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood private ChannelManager cm; 9248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 9348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood private CryptoWishList cryptoWishList = new CryptoWishList(); 9448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 9548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood private DHGexParameters dhgexpara = new DHGexParameters(); 9648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 9748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood private final String hostname; 9848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 9948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood private final int port; 10048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 10148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood private TransportManager tm; 10248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 10348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood private boolean tcpNoDelay = false; 10448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 10548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood private ProxyData proxyData = null; 10648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 10748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood private List<ConnectionMonitor> connectionMonitors = new Vector<ConnectionMonitor>(); 10848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 10948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 11048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Prepares a fresh <code>Connection</code> object which can then be used 11148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * to establish a connection to the specified SSH-2 server. 11248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 11348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Same as {@link #Connection(String, int) Connection(hostname, 22)}. 11448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 11548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param hostname the hostname of the SSH-2 server. 11648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 11748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public Connection(String hostname) 11848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 11948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood this(hostname, 22); 12048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 12148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 12248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 12348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Prepares a fresh <code>Connection</code> object which can then be used 12448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * to establish a connection to the specified SSH-2 server. 12548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 12648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param hostname 12748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * the host where we later want to connect to. 12848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param port 12948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * port on the server, normally 22. 13048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 13148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public Connection(String hostname, int port) 13248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 13348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood this.hostname = hostname; 13448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood this.port = port; 13548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 13648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 13748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public Connection(String hostname, int port, String identification) 13848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 13948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood this.hostname = hostname; 14048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood this.port = port; 14148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood this.identification = identification; 14248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 14348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 14448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 14548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * After a successful connect, one has to authenticate oneself. This method 14648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * is based on DSA (it uses DSA to sign a challenge sent by the server). 14748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 14848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * If the authentication phase is complete, <code>true</code> will be 14948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * returned. If the server does not accept the request (or if further 15048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * authentication steps are needed), <code>false</code> is returned and 15148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * one can retry either by using this or any other authentication method 15248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * (use the <code>getRemainingAuthMethods</code> method to get a list of 15348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * the remaining possible methods). 15448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 15548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param user 15648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * A <code>String</code> holding the username. 15748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param pem 15848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * A <code>String</code> containing the DSA private key of the 15948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * user in OpenSSH key format (PEM, you can't miss the 16048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * "-----BEGIN DSA PRIVATE KEY-----" tag). The string may contain 16148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * linefeeds. 16248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param password 16348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * If the PEM string is 3DES encrypted ("DES-EDE3-CBC"), then you 16448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * must specify the password. Otherwise, this argument will be 16548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * ignored and can be set to <code>null</code>. 16648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 16748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @return whether the connection is now authenticated. 16848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @throws IOException 16948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 17048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @deprecated You should use one of the {@link #authenticateWithPublicKey(String, File, String) authenticateWithPublicKey()} 17148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * methods, this method is just a wrapper for it and will 17248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * disappear in future builds. 17348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 17448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 17548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized boolean authenticateWithDSA(String user, String pem, String password) throws IOException 17648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 17748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (tm == null) 17848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalStateException("Connection is not established!"); 17948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 18048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (authenticated) 18148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalStateException("Connection is already authenticated!"); 18248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 18348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (am == null) 18448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood am = new AuthenticationManager(tm); 18548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 18648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (cm == null) 18748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood cm = new ChannelManager(tm); 18848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 18948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (user == null) 19048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalArgumentException("user argument is null"); 19148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 19248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (pem == null) 19348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalArgumentException("pem argument is null"); 19448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 19548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood authenticated = am.authenticatePublicKey(user, pem.toCharArray(), password, getOrCreateSecureRND()); 19648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 19748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return authenticated; 19848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 19948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 20048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 20148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * A wrapper that calls {@link #authenticateWithKeyboardInteractive(String, String[], InteractiveCallback) 20248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * authenticateWithKeyboardInteractivewith} a <code>null</code> submethod list. 20348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 20448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param user 20548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * A <code>String</code> holding the username. 20648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param cb 20748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * An <code>InteractiveCallback</code> which will be used to 20848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * determine the responses to the questions asked by the server. 20948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @return whether the connection is now authenticated. 21048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @throws IOException 21148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 21248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized boolean authenticateWithKeyboardInteractive(String user, InteractiveCallback cb) 21348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throws IOException 21448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 21548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return authenticateWithKeyboardInteractive(user, null, cb); 21648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 21748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 21848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 21948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * After a successful connect, one has to authenticate oneself. This method 22048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * is based on "keyboard-interactive", specified in 22148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * draft-ietf-secsh-auth-kbdinteract-XX. Basically, you have to define a 22248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * callback object which will be feeded with challenges generated by the 22348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * server. Answers are then sent back to the server. It is possible that the 22448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * callback will be called several times during the invocation of this 22548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * method (e.g., if the server replies to the callback's answer(s) with 22648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * another challenge...) 22748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 22848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * If the authentication phase is complete, <code>true</code> will be 22948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * returned. If the server does not accept the request (or if further 23048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * authentication steps are needed), <code>false</code> is returned and 23148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * one can retry either by using this or any other authentication method 23248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * (use the <code>getRemainingAuthMethods</code> method to get a list of 23348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * the remaining possible methods). 23448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 23548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Note: some SSH servers advertise "keyboard-interactive", however, any 23648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * interactive request will be denied (without having sent any challenge to 23748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * the client). 23848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 23948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param user 24048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * A <code>String</code> holding the username. 24148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param submethods 24248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * An array of submethod names, see 24348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * draft-ietf-secsh-auth-kbdinteract-XX. May be <code>null</code> 24448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * to indicate an empty list. 24548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param cb 24648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * An <code>InteractiveCallback</code> which will be used to 24748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * determine the responses to the questions asked by the server. 24848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 24948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @return whether the connection is now authenticated. 25048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @throws IOException 25148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 25248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized boolean authenticateWithKeyboardInteractive(String user, String[] submethods, 25348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood InteractiveCallback cb) throws IOException 25448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 25548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (cb == null) 25648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalArgumentException("Callback may not ne NULL!"); 25748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 25848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (tm == null) 25948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalStateException("Connection is not established!"); 26048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 26148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (authenticated) 26248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalStateException("Connection is already authenticated!"); 26348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 26448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (am == null) 26548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood am = new AuthenticationManager(tm); 26648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 26748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (cm == null) 26848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood cm = new ChannelManager(tm); 26948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 27048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (user == null) 27148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalArgumentException("user argument is null"); 27248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 27348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood authenticated = am.authenticateInteractive(user, submethods, cb); 27448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 27548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return authenticated; 27648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 27748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 27848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 27948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * After a successful connect, one has to authenticate oneself. This method 28048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * sends username and password to the server. 28148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 28248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * If the authentication phase is complete, <code>true</code> will be 28348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * returned. If the server does not accept the request (or if further 28448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * authentication steps are needed), <code>false</code> is returned and 28548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * one can retry either by using this or any other authentication method 28648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * (use the <code>getRemainingAuthMethods</code> method to get a list of 28748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * the remaining possible methods). 28848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 28948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Note: if this method fails, then please double-check that it is actually 29048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * offered by the server (use {@link #getRemainingAuthMethods(String) getRemainingAuthMethods()}. 29148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 29248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Often, password authentication is disabled, but users are not aware of it. 29348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Many servers only offer "publickey" and "keyboard-interactive". However, 29448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * even though "keyboard-interactive" *feels* like password authentication 29548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * (e.g., when using the putty or openssh clients) it is *not* the same mechanism. 29648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 29748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param user 29848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param password 29948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @return if the connection is now authenticated. 30048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @throws IOException 30148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 30248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized boolean authenticateWithPassword(String user, String password) throws IOException 30348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 30448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (tm == null) 30548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalStateException("Connection is not established!"); 30648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 30748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (authenticated) 30848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalStateException("Connection is already authenticated!"); 30948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 31048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (am == null) 31148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood am = new AuthenticationManager(tm); 31248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 31348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (cm == null) 31448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood cm = new ChannelManager(tm); 31548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 31648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (user == null) 31748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalArgumentException("user argument is null"); 31848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 31948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (password == null) 32048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalArgumentException("password argument is null"); 32148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 32248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood authenticated = am.authenticatePassword(user, password); 32348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 32448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return authenticated; 32548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 32648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 32748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 32848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * After a successful connect, one has to authenticate oneself. 32948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * This method can be used to explicitly use the special "none" 33048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * authentication method (where only a username has to be specified). 33148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 33248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Note 1: The "none" method may always be tried by clients, however as by 33348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * the specs, the server will not explicitly announce it. In other words, 33448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * the "none" token will never show up in the list returned by 33548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * {@link #getRemainingAuthMethods(String)}. 33648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 33748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Note 2: no matter which one of the authenticateWithXXX() methods 33848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * you call, the library will always issue exactly one initial "none" 33948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * authentication request to retrieve the initially allowed list of 34048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * authentication methods by the server. Please read RFC 4252 for the 34148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * details. 34248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 34348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * If the authentication phase is complete, <code>true</code> will be 34448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * returned. If further authentication steps are needed, <code>false</code> 34548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * is returned and one can retry by any other authentication method 34648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * (use the <code>getRemainingAuthMethods</code> method to get a list of 34748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * the remaining possible methods). 34848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 34948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param user 35048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @return if the connection is now authenticated. 35148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @throws IOException 35248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 35348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized boolean authenticateWithNone(String user) throws IOException 35448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 35548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (tm == null) 35648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalStateException("Connection is not established!"); 35748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 35848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (authenticated) 35948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalStateException("Connection is already authenticated!"); 36048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 36148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (am == null) 36248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood am = new AuthenticationManager(tm); 36348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 36448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (cm == null) 36548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood cm = new ChannelManager(tm); 36648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 36748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (user == null) 36848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalArgumentException("user argument is null"); 36948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 37048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* Trigger the sending of the PacketUserauthRequestNone packet */ 37148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* (if not already done) */ 37248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 37348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood authenticated = am.authenticateNone(user); 37448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 37548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return authenticated; 37648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 37748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 37848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 37948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * After a successful connect, one has to authenticate oneself. 38048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * The authentication method "publickey" works by signing a challenge 38148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * sent by the server. The signature is either DSA or RSA based - it 38248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * just depends on the type of private key you specify, either a DSA 38348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * or RSA private key in PEM format. And yes, this is may seem to be a 38448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * little confusing, the method is called "publickey" in the SSH-2 protocol 38548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * specification, however since we need to generate a signature, you 38648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * actually have to supply a private key =). 38748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 38848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * The private key contained in the PEM file may also be encrypted ("Proc-Type: 4,ENCRYPTED"). 38948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * The library supports DES-CBC and DES-EDE3-CBC encryption, as well 39048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * as the more exotic PEM encrpytions AES-128-CBC, AES-192-CBC and AES-256-CBC. 39148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 39248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * If the authentication phase is complete, <code>true</code> will be 39348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * returned. If the server does not accept the request (or if further 39448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * authentication steps are needed), <code>false</code> is returned and 39548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * one can retry either by using this or any other authentication method 39648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * (use the <code>getRemainingAuthMethods</code> method to get a list of 39748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * the remaining possible methods). 39848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 39948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * NOTE PUTTY USERS: Event though your key file may start with "-----BEGIN..." 40048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * it is not in the expected format. You have to convert it to the OpenSSH 40148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * key format by using the "puttygen" tool (can be downloaded from the Putty 40248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * website). Simply load your key and then use the "Conversions/Export OpenSSH key" 40348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * functionality to get a proper PEM file. 40448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 40548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param user 40648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * A <code>String</code> holding the username. 40748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param pemPrivateKey 40848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * A <code>char[]</code> containing a DSA or RSA private key of the 40948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * user in OpenSSH key format (PEM, you can't miss the 41048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * "-----BEGIN DSA PRIVATE KEY-----" or "-----BEGIN RSA PRIVATE KEY-----" 41148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * tag). The char array may contain linebreaks/linefeeds. 41248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param password 41348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * If the PEM structure is encrypted ("Proc-Type: 4,ENCRYPTED") then 41448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * you must specify a password. Otherwise, this argument will be ignored 41548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * and can be set to <code>null</code>. 41648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 41748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @return whether the connection is now authenticated. 41848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @throws IOException 41948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 42048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized boolean authenticateWithPublicKey(String user, char[] pemPrivateKey, String password) 42148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throws IOException 42248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 42348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (tm == null) 42448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalStateException("Connection is not established!"); 42548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 42648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (authenticated) 42748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalStateException("Connection is already authenticated!"); 42848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 42948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (am == null) 43048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood am = new AuthenticationManager(tm); 43148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 43248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (cm == null) 43348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood cm = new ChannelManager(tm); 43448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 43548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (user == null) 43648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalArgumentException("user argument is null"); 43748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 43848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (pemPrivateKey == null) 43948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalArgumentException("pemPrivateKey argument is null"); 44048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 44148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood authenticated = am.authenticatePublicKey(user, pemPrivateKey, password, getOrCreateSecureRND()); 44248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 44348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return authenticated; 44448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 44548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 44648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 44748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * A convenience wrapper function which reads in a private key (PEM format, either DSA or RSA) 44848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * and then calls <code>authenticateWithPublicKey(String, char[], String)</code>. 44948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 45048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * NOTE PUTTY USERS: Event though your key file may start with "-----BEGIN..." 45148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * it is not in the expected format. You have to convert it to the OpenSSH 45248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * key format by using the "puttygen" tool (can be downloaded from the Putty 45348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * website). Simply load your key and then use the "Conversions/Export OpenSSH key" 45448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * functionality to get a proper PEM file. 45548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 45648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param user 45748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * A <code>String</code> holding the username. 45848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param pemFile 45948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * A <code>File</code> object pointing to a file containing a DSA or RSA 46048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * private key of the user in OpenSSH key format (PEM, you can't miss the 46148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * "-----BEGIN DSA PRIVATE KEY-----" or "-----BEGIN RSA PRIVATE KEY-----" 46248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * tag). 46348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param password 46448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * If the PEM file is encrypted then you must specify the password. 46548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Otherwise, this argument will be ignored and can be set to <code>null</code>. 46648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 46748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @return whether the connection is now authenticated. 46848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @throws IOException 46948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 47048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized boolean authenticateWithPublicKey(String user, File pemFile, String password) 47148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throws IOException 47248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 47348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (pemFile == null) 47448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalArgumentException("pemFile argument is null"); 47548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 47648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood char[] buff = new char[256]; 47748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 47848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood CharArrayWriter cw = new CharArrayWriter(); 47948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 48048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood FileReader fr = new FileReader(pemFile); 48148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 48248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood while (true) 48348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 48448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int len = fr.read(buff); 48548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (len < 0) 48648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood break; 48748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood cw.write(buff, 0, len); 48848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 48948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 49048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood fr.close(); 49148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 49248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return authenticateWithPublicKey(user, cw.toCharArray(), password); 49348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 49448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 49548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 49648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Add a {@link ConnectionMonitor} to this connection. Can be invoked at any time, 49748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * but it is best to add connection monitors before invoking 49848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <code>connect()</code> to avoid glitches (e.g., you add a connection monitor after 49948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * a successful connect(), but the connection has died in the mean time. Then, 50048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * your connection monitor won't be notified.) 50148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 50248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * You can add as many monitors as you like. 50348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 50448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @see ConnectionMonitor 50548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 50648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param cmon An object implementing the <code>ConnectionMonitor</code> interface. 50748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 50848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized void addConnectionMonitor(ConnectionMonitor cmon) 50948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 51048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (cmon == null) 51148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalArgumentException("cmon argument is null"); 51248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 51348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood connectionMonitors.add(cmon); 51448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 51548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (tm != null) 51648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood tm.setConnectionMonitors(connectionMonitors); 51748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 51848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 51948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 52048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Close the connection to the SSH-2 server. All assigned sessions will be 52148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * closed, too. Can be called at any time. Don't forget to call this once 52248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * you don't need a connection anymore - otherwise the receiver thread may 52348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * run forever. 52448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 52548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized void close() 52648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 52748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood Throwable t = new Throwable("Closed due to user request."); 52848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood close(t, false); 52948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 53048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 53148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public void close(Throwable t, boolean hard) 53248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 53348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (cm != null) 53448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood cm.closeAllChannels(); 53548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 53648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (tm != null) 53748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 53848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood tm.close(t, hard == false); 53948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood tm = null; 54048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 54148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood am = null; 54248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood cm = null; 54348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood authenticated = false; 54448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 54548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 54648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 54748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Same as {@link #connect(ServerHostKeyVerifier, int, int) connect(null, 0, 0)}. 54848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 54948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @return see comments for the {@link #connect(ServerHostKeyVerifier, int, int) connect(ServerHostKeyVerifier, int, int)} method. 55048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @throws IOException 55148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 55248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized ConnectionInfo connect() throws IOException 55348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 55448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return connect(null, 0, 0); 55548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 55648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 55748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 55848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Same as {@link #connect(ServerHostKeyVerifier, int, int) connect(verifier, 0, 0)}. 55948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 56048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @return see comments for the {@link #connect(ServerHostKeyVerifier, int, int) connect(ServerHostKeyVerifier, int, int)} method. 56148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @throws IOException 56248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 56348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized ConnectionInfo connect(ServerHostKeyVerifier verifier) throws IOException 56448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 56548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return connect(verifier, 0, 0); 56648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 56748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 56848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 56948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Connect to the SSH-2 server and, as soon as the server has presented its 57048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * host key, use the {@link ServerHostKeyVerifier#verifyServerHostKey(String, 57148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * int, String, byte[]) ServerHostKeyVerifier.verifyServerHostKey()} 57248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * method of the <code>verifier</code> to ask for permission to proceed. 57348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * If <code>verifier</code> is <code>null</code>, then any host key will be 57448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * accepted - this is NOT recommended, since it makes man-in-the-middle attackes 57548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * VERY easy (somebody could put a proxy SSH server between you and the real server). 57648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 57748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Note: The verifier will be called before doing any crypto calculations 57848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * (i.e., diffie-hellman). Therefore, if you don't like the presented host key then 57948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * no CPU cycles are wasted (and the evil server has less information about us). 58048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 58148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * However, it is still possible that the server presented a fake host key: the server 58248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * cheated (typically a sign for a man-in-the-middle attack) and is not able to generate 58348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * a signature that matches its host key. Don't worry, the library will detect such 58448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * a scenario later when checking the signature (the signature cannot be checked before 58548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * having completed the diffie-hellman exchange). 58648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 58748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Note 2: The {@link ServerHostKeyVerifier#verifyServerHostKey(String, 58848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * int, String, byte[]) ServerHostKeyVerifier.verifyServerHostKey()} method 58948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * will *NOT* be called from the current thread, the call is being made from a 59048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * background thread (there is a background dispatcher thread for every 59148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * established connection). 59248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 59348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Note 3: This method will block as long as the key exchange of the underlying connection 59448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * has not been completed (and you have not specified any timeouts). 59548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 59648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Note 4: If you want to re-use a connection object that was successfully connected, 59748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * then you must call the {@link #close()} method before invoking <code>connect()</code> again. 59848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 59948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param verifier 60048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * An object that implements the 60148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * {@link ServerHostKeyVerifier} interface. Pass <code>null</code> 60248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * to accept any server host key - NOT recommended. 60348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 60448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param connectTimeout 60548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Connect the underlying TCP socket to the server with the given timeout 60648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * value (non-negative, in milliseconds). Zero means no timeout. If a proxy is being 60748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * used (see {@link #setProxyData(ProxyData)}), then this timeout is used for the 60848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * connection establishment to the proxy. 60948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 61048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param kexTimeout 61148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Timeout for complete connection establishment (non-negative, 61248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * in milliseconds). Zero means no timeout. The timeout counts from the 61348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * moment you invoke the connect() method and is cancelled as soon as the 61448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * first key-exchange round has finished. It is possible that 61548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * the timeout event will be fired during the invocation of the 61648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <code>verifier</code> callback, but it will only have an effect after 61748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * the <code>verifier</code> returns. 61848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 61948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @return A {@link ConnectionInfo} object containing the details of 62048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * the established connection. 62148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 62248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @throws IOException 62348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * If any problem occurs, e.g., the server's host key is not 62448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * accepted by the <code>verifier</code> or there is problem during 62548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * the initial crypto setup (e.g., the signature sent by the server is wrong). 62648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 62748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * In case of a timeout (either connectTimeout or kexTimeout) 62848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * a SocketTimeoutException is thrown. 62948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 63048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * An exception may also be thrown if the connection was already successfully 63148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * connected (no matter if the connection broke in the mean time) and you invoke 63248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <code>connect()</code> again without having called {@link #close()} first. 63348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 63448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * If a HTTP proxy is being used and the proxy refuses the connection, 63548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * then a {@link HTTPProxyException} may be thrown, which 63648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * contains the details returned by the proxy. If the proxy is buggy and does 63748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * not return a proper HTTP response, then a normal IOException is thrown instead. 63848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 63948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized ConnectionInfo connect(ServerHostKeyVerifier verifier, int connectTimeout, int kexTimeout) 64048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throws IOException 64148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 64248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood final class TimeoutState 64348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 64448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood boolean isCancelled = false; 64548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood boolean timeoutSocketClosed = false; 64648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 64748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 64848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (tm != null) 64948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IOException("Connection to " + hostname + " is already in connected state!"); 65048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 65148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (connectTimeout < 0) 65248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalArgumentException("connectTimeout must be non-negative!"); 65348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 65448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (kexTimeout < 0) 65548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalArgumentException("kexTimeout must be non-negative!"); 65648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 65748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood final TimeoutState state = new TimeoutState(); 65848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 65948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood tm = new TransportManager(hostname, port); 66048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood tm.setSoTimeout(connectTimeout); 66148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood tm.setConnectionMonitors(connectionMonitors); 66248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 66348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* Make sure that the runnable below will observe the new value of "tm" 66448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * and "state" (the runnable will be executed in a different thread, which 66548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * may be already running, that is why we need a memory barrier here). 66648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * See also the comment in Channel.java if you 66748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * are interested in the details. 66848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 66948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * OKOK, this is paranoid since adding the runnable to the todo list 67048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * of the TimeoutService will ensure that all writes have been flushed 67148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * before the Runnable reads anything 67248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * (there is a synchronized block in TimeoutService.addTimeoutHandler). 67348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 67448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 67548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood synchronized (tm) 67648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 67748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* We could actually synchronize on anything. */ 67848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 67948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 68048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood try 68148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 68248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood TimeoutToken token = null; 68348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 68448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (kexTimeout > 0) 68548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 68648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood final Runnable timeoutHandler = new Runnable() 68748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 68848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public void run() 68948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 69048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood synchronized (state) 69148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 69248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (state.isCancelled) 69348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return; 69448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood state.timeoutSocketClosed = true; 69548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood tm.close(new SocketTimeoutException("The connect timeout expired"), false); 69648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 69748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 69848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood }; 69948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 70048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood long timeoutHorizont = System.currentTimeMillis() + kexTimeout; 70148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 70248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood token = TimeoutService.addTimeoutHandler(timeoutHorizont, timeoutHandler); 70348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 70448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 70548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood try 70648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 70748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood tm.initialize(identification, cryptoWishList, verifier, dhgexpara, connectTimeout, 70848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood getOrCreateSecureRND(), proxyData); 70948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 71048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood catch (SocketTimeoutException se) 71148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 71248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw (SocketTimeoutException) new SocketTimeoutException( 71348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood "The connect() operation on the socket timed out.").initCause(se); 71448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 71548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 71648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood tm.setTcpNoDelay(tcpNoDelay); 71748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 71848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* Wait until first KEX has finished */ 71948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 72048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood ConnectionInfo ci = tm.getConnectionInfo(1); 72148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 72248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* Now try to cancel the timeout, if needed */ 72348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 72448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (token != null) 72548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 72648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood TimeoutService.cancelTimeoutHandler(token); 72748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 72848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* Were we too late? */ 72948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 73048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood synchronized (state) 73148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 73248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (state.timeoutSocketClosed) 73348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IOException("This exception will be replaced by the one below =)"); 73448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* Just in case the "cancelTimeoutHandler" invocation came just a little bit 73548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * too late but the handler did not enter the semaphore yet - we can 73648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * still stop it. 73748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 73848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood state.isCancelled = true; 73948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 74048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 74148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 74248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return ci; 74348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 74448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood catch (SocketTimeoutException ste) 74548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 74648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw ste; 74748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 74848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood catch (IOException e1) 74948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 75048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* This will also invoke any registered connection monitors */ 75148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood close(new Throwable("There was a problem during connect."), false); 75248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 75348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood synchronized (state) 75448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 75548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* Show a clean exception, not something like "the socket is closed!?!" */ 75648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (state.timeoutSocketClosed) 75748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new SocketTimeoutException("The kexTimeout (" + kexTimeout + " ms) expired."); 75848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 75948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 76048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* Do not wrap a HTTPProxyException */ 76148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (e1 instanceof HTTPProxyException) 76248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw e1; 76348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 76448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw (IOException) new IOException("There was a problem while connecting to " + hostname + ":" + port) 76548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood .initCause(e1); 76648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 76748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 76848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 76948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 77048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Creates a new {@link LocalPortForwarder}. 77148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * A <code>LocalPortForwarder</code> forwards TCP/IP connections that arrive at a local 77248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * port via the secure tunnel to another host (which may or may not be 77348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * identical to the remote SSH-2 server). 77448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 77548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * This method must only be called after one has passed successfully the authentication step. 77648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * There is no limit on the number of concurrent forwardings. 77748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 77848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param local_port the local port the LocalPortForwarder shall bind to. 77948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param host_to_connect target address (IP or hostname) 78048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param port_to_connect target port 78148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @return A {@link LocalPortForwarder} object. 78248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @throws IOException 78348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 78448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized LocalPortForwarder createLocalPortForwarder(int local_port, String host_to_connect, 78548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int port_to_connect) throws IOException 78648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 78748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (tm == null) 78848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalStateException("Cannot forward ports, you need to establish a connection first."); 78948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 79048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (!authenticated) 79148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalStateException("Cannot forward ports, connection is not authenticated."); 79248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 79348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return new LocalPortForwarder(cm, local_port, host_to_connect, port_to_connect); 79448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 79548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 79648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 79748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Creates a new {@link LocalPortForwarder}. 79848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * A <code>LocalPortForwarder</code> forwards TCP/IP connections that arrive at a local 79948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * port via the secure tunnel to another host (which may or may not be 80048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * identical to the remote SSH-2 server). 80148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 80248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * This method must only be called after one has passed successfully the authentication step. 80348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * There is no limit on the number of concurrent forwardings. 80448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 80548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param addr specifies the InetSocketAddress where the local socket shall be bound to. 80648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param host_to_connect target address (IP or hostname) 80748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param port_to_connect target port 80848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @return A {@link LocalPortForwarder} object. 80948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @throws IOException 81048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 81148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized LocalPortForwarder createLocalPortForwarder(InetSocketAddress addr, String host_to_connect, 81248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int port_to_connect) throws IOException 81348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 81448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (tm == null) 81548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalStateException("Cannot forward ports, you need to establish a connection first."); 81648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 81748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (!authenticated) 81848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalStateException("Cannot forward ports, connection is not authenticated."); 81948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 82048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return new LocalPortForwarder(cm, addr, host_to_connect, port_to_connect); 82148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 82248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 82348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 82448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Creates a new {@link LocalStreamForwarder}. 82548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * A <code>LocalStreamForwarder</code> manages an Input/Outputstream pair 82648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * that is being forwarded via the secure tunnel into a TCP/IP connection to another host 82748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * (which may or may not be identical to the remote SSH-2 server). 82848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 82948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param host_to_connect 83048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param port_to_connect 83148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @return A {@link LocalStreamForwarder} object. 83248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @throws IOException 83348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 83448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized LocalStreamForwarder createLocalStreamForwarder(String host_to_connect, int port_to_connect) 83548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throws IOException 83648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 83748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (tm == null) 83848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalStateException("Cannot forward, you need to establish a connection first."); 83948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 84048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (!authenticated) 84148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalStateException("Cannot forward, connection is not authenticated."); 84248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 84348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return new LocalStreamForwarder(cm, host_to_connect, port_to_connect); 84448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 84548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 84648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 84748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Create a very basic {@link SCPClient} that can be used to copy 84848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * files from/to the SSH-2 server. 84948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 85048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Works only after one has passed successfully the authentication step. 85148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * There is no limit on the number of concurrent SCP clients. 85248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 85348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Note: This factory method will probably disappear in the future. 85448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 85548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @return A {@link SCPClient} object. 85648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @throws IOException 85748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 85848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized SCPClient createSCPClient() throws IOException 85948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 86048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (tm == null) 86148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalStateException("Cannot create SCP client, you need to establish a connection first."); 86248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 86348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (!authenticated) 86448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalStateException("Cannot create SCP client, connection is not authenticated."); 86548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 86648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return new SCPClient(this); 86748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 86848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 86948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 87048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Force an asynchronous key re-exchange (the call does not block). The 87148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * latest values set for MAC, Cipher and DH group exchange parameters will 87248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * be used. If a key exchange is currently in progress, then this method has 87348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * the only effect that the so far specified parameters will be used for the 87448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * next (server driven) key exchange. 87548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 87648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Note: This implementation will never start a key exchange (other than the initial one) 87748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * unless you or the SSH-2 server ask for it. 87848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 87948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @throws IOException 88048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * In case of any failure behind the scenes. 88148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 88248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized void forceKeyExchange() throws IOException 88348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 88448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (tm == null) 88548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalStateException("You need to establish a connection first."); 88648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 88748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood tm.forceKeyExchange(cryptoWishList, dhgexpara); 88848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 88948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 89048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 89148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Returns the hostname that was passed to the constructor. 89248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 89348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @return the hostname 89448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 89548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized String getHostname() 89648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 89748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return hostname; 89848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 89948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 90048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 90148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Returns the port that was passed to the constructor. 90248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 90348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @return the TCP port 90448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 90548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized int getPort() 90648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 90748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return port; 90848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 90948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 91048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 91148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Returns a {@link ConnectionInfo} object containing the details of 91248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * the connection. Can be called as soon as the connection has been 91348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * established (successfully connected). 91448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 91548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @return A {@link ConnectionInfo} object. 91648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @throws IOException 91748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * In case of any failure behind the scenes. 91848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 91948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized ConnectionInfo getConnectionInfo() throws IOException 92048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 92148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (tm == null) 92248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalStateException( 92348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood "Cannot get details of connection, you need to establish a connection first."); 92448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return tm.getConnectionInfo(1); 92548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 92648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 92748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 92848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * After a successful connect, one has to authenticate oneself. This method 92948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * can be used to tell which authentication methods are supported by the 93048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * server at a certain stage of the authentication process (for the given 93148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * username). 93248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 93348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Note 1: the username will only be used if no authentication step was done 93448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * so far (it will be used to ask the server for a list of possible 93548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * authentication methods by sending the initial "none" request). Otherwise, 93648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * this method ignores the user name and returns a cached method list 93748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * (which is based on the information contained in the last negative server response). 93848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 93948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Note 2: the server may return method names that are not supported by this 94048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * implementation. 94148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 94248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * After a successful authentication, this method must not be called 94348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * anymore. 94448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 94548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param user 94648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * A <code>String</code> holding the username. 94748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 94848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @return a (possibly emtpy) array holding authentication method names. 94948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @throws IOException 95048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 95148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized String[] getRemainingAuthMethods(String user) throws IOException 95248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 95348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (user == null) 95448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalArgumentException("user argument may not be NULL!"); 95548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 95648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (tm == null) 95748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalStateException("Connection is not established!"); 95848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 95948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (authenticated) 96048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalStateException("Connection is already authenticated!"); 96148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 96248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (am == null) 96348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood am = new AuthenticationManager(tm); 96448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 96548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (cm == null) 96648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood cm = new ChannelManager(tm); 96748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 96848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return am.getRemainingMethods(user); 96948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 97048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 97148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 97248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Determines if the authentication phase is complete. Can be called at any 97348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * time. 97448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 97548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @return <code>true</code> if no further authentication steps are 97648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * needed. 97748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 97848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized boolean isAuthenticationComplete() 97948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 98048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return authenticated; 98148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 98248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 98348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 98448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Returns true if there was at least one failed authentication request and 98548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * the last failed authentication request was marked with "partial success" 98648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * by the server. This is only needed in the rare case of SSH-2 server setups 98748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * that cannot be satisfied with a single successful authentication request 98848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * (i.e., multiple authentication steps are needed.) 98948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 99048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * If you are interested in the details, then have a look at RFC4252. 99148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 99248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @return if the there was a failed authentication step and the last one 99348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * was marked as a "partial success". 99448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 99548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized boolean isAuthenticationPartialSuccess() 99648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 99748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (am == null) 99848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return false; 99948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 100048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return am.getPartialSuccess(); 100148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 100248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 100348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 100448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Checks if a specified authentication method is available. This method is 100548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * actually just a wrapper for {@link #getRemainingAuthMethods(String) 100648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * getRemainingAuthMethods()}. 100748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 100848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param user 100948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * A <code>String</code> holding the username. 101048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param method 101148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * An authentication method name (e.g., "publickey", "password", 101248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * "keyboard-interactive") as specified by the SSH-2 standard. 101348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @return if the specified authentication method is currently available. 101448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @throws IOException 101548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 101648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized boolean isAuthMethodAvailable(String user, String method) throws IOException 101748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 101848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (method == null) 101948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalArgumentException("method argument may not be NULL!"); 102048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 102148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood String methods[] = getRemainingAuthMethods(user); 102248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 102348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood for (int i = 0; i < methods.length; i++) 102448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 102548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (methods[i].compareTo(method) == 0) 102648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return true; 102748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 102848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 102948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return false; 103048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 103148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 103248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood private SecureRandom getOrCreateSecureRND() 103348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 103448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (generator == null) 103548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood generator = new SecureRandom(); 103648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 103748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return generator; 103848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 103948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 104048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 104148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Open a new {@link Session} on this connection. Works only after one has passed 104248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * successfully the authentication step. There is no limit on the number of 104348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * concurrent sessions. 104448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 104548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @return A {@link Session} object. 104648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @throws IOException 104748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 104848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized Session openSession() throws IOException 104948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 105048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (tm == null) 105148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalStateException("Cannot open session, you need to establish a connection first."); 105248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 105348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (!authenticated) 105448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalStateException("Cannot open session, connection is not authenticated."); 105548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 105648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return new Session(cm, getOrCreateSecureRND()); 105748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 105848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 105948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 106048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Send an SSH_MSG_IGNORE packet. This method will generate a random data attribute 106148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * (length between 0 (invlusive) and 16 (exclusive) bytes, contents are random bytes). 106248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 106348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * This method must only be called once the connection is established. 106448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 106548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @throws IOException 106648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 106748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized void sendIgnorePacket() throws IOException 106848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 106948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood SecureRandom rnd = getOrCreateSecureRND(); 107048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 107148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood byte[] data = new byte[rnd.nextInt(16)]; 107248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood rnd.nextBytes(data); 107348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 107448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood sendIgnorePacket(data); 107548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 107648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 107748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 107848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Send an SSH_MSG_IGNORE packet with the given data attribute. 107948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 108048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * This method must only be called once the connection is established. 108148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 108248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @throws IOException 108348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 108448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized void sendIgnorePacket(byte[] data) throws IOException 108548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 108648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (data == null) 108748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalArgumentException("data argument must not be null."); 108848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 108948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (tm == null) 109048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalStateException( 109148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood "Cannot send SSH_MSG_IGNORE packet, you need to establish a connection first."); 109248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 109348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood PacketIgnore pi = new PacketIgnore(); 109448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood pi.setData(data); 109548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 109648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood tm.sendMessage(pi.getPayload()); 109748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 109848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 109948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 110048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Removes duplicates from a String array, keeps only first occurence 110148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * of each element. Does not destroy order of elements; can handle nulls. 110248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Uses a very efficient O(N^2) algorithm =) 110348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 110448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param list a String array. 110548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @return a cleaned String array. 110648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 110748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood private String[] removeDuplicates(String[] list) 110848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 110948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if ((list == null) || (list.length < 2)) 111048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return list; 111148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 111248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood String[] list2 = new String[list.length]; 111348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 111448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int count = 0; 111548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 111648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood for (int i = 0; i < list.length; i++) 111748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 111848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood boolean duplicate = false; 111948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 112048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood String element = list[i]; 112148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 112248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood for (int j = 0; j < count; j++) 112348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 112448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (((element == null) && (list2[j] == null)) || ((element != null) && (element.equals(list2[j])))) 112548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 112648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood duplicate = true; 112748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood break; 112848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 112948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 113048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 113148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (duplicate) 113248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood continue; 113348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 113448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood list2[count++] = list[i]; 113548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 113648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 113748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (count == list2.length) 113848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return list2; 113948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 114048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood String[] tmp = new String[count]; 114148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood System.arraycopy(list2, 0, tmp, 0, count); 114248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 114348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return tmp; 114448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 114548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 114648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 114748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Unless you know what you are doing, you will never need this. 114848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 114948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param ciphers 115048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 115148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized void setClient2ServerCiphers(String[] ciphers) 115248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 115348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if ((ciphers == null) || (ciphers.length == 0)) 115448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalArgumentException(); 115548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood ciphers = removeDuplicates(ciphers); 115648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood BlockCipherFactory.checkCipherList(ciphers); 115748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood cryptoWishList.c2s_enc_algos = ciphers; 115848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 115948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 116048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 116148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Unless you know what you are doing, you will never need this. 116248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 116348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param macs 116448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 116548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized void setClient2ServerMACs(String[] macs) 116648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 116748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if ((macs == null) || (macs.length == 0)) 116848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalArgumentException(); 116948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood macs = removeDuplicates(macs); 117048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood MAC.checkMacList(macs); 117148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood cryptoWishList.c2s_mac_algos = macs; 117248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 117348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 117448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 117548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Sets the parameters for the diffie-hellman group exchange. Unless you 117648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * know what you are doing, you will never need this. Default values are 117748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * defined in the {@link DHGexParameters} class. 117848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 117948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param dgp {@link DHGexParameters}, non null. 118048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 118148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 118248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized void setDHGexParameters(DHGexParameters dgp) 118348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 118448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (dgp == null) 118548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalArgumentException(); 118648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 118748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood dhgexpara = dgp; 118848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 118948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 119048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 119148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Unless you know what you are doing, you will never need this. 119248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 119348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param ciphers 119448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 119548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized void setServer2ClientCiphers(String[] ciphers) 119648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 119748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if ((ciphers == null) || (ciphers.length == 0)) 119848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalArgumentException(); 119948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood ciphers = removeDuplicates(ciphers); 120048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood BlockCipherFactory.checkCipherList(ciphers); 120148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood cryptoWishList.s2c_enc_algos = ciphers; 120248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 120348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 120448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 120548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Unless you know what you are doing, you will never need this. 120648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 120748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param macs 120848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 120948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized void setServer2ClientMACs(String[] macs) 121048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 121148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if ((macs == null) || (macs.length == 0)) 121248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalArgumentException(); 121348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 121448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood macs = removeDuplicates(macs); 121548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood MAC.checkMacList(macs); 121648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood cryptoWishList.s2c_mac_algos = macs; 121748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 121848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 121948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 122048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Define the set of allowed server host key algorithms to be used for 122148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * the following key exchange operations. 122248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 122348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Unless you know what you are doing, you will never need this. 122448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 122548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param algos An array of allowed server host key algorithms. 122648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * SSH-2 defines <code>ssh-dss</code> and <code>ssh-rsa</code>. 122748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * The entries of the array must be ordered after preference, i.e., 122848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * the entry at index 0 is the most preferred one. You must specify 122948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * at least one entry. 123048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 123148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized void setServerHostKeyAlgorithms(String[] algos) 123248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 123348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if ((algos == null) || (algos.length == 0)) 123448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalArgumentException(); 123548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 123648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood algos = removeDuplicates(algos); 123748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood KexManager.checkServerHostkeyAlgorithmsList(algos); 123848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood cryptoWishList.serverHostKeyAlgorithms = algos; 123948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 124048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 124148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 124248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Enable/disable TCP_NODELAY (disable/enable Nagle's algorithm) on the underlying socket. 124348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 124448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Can be called at any time. If the connection has not yet been established 124548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * then the passed value will be stored and set after the socket has been set up. 124648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * The default value that will be used is <code>false</code>. 124748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 124848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param enable the argument passed to the <code>Socket.setTCPNoDelay()</code> method. 124948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @throws IOException 125048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 125148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized void setTCPNoDelay(boolean enable) throws IOException 125248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 125348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood tcpNoDelay = enable; 125448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 125548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (tm != null) 125648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood tm.setTcpNoDelay(enable); 125748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 125848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 125948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 126048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Used to tell the library that the connection shall be established through a proxy server. 126148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * It only makes sense to call this method before calling the {@link #connect() connect()} 126248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * method. 126348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 126448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * At the moment, only HTTP proxies are supported. 126548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 126648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Note: This method can be called any number of times. The {@link #connect() connect()} 126748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * method will use the value set in the last preceding invocation of this method. 126848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 126948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @see HTTPProxyData 127048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 127148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param proxyData Connection information about the proxy. If <code>null</code>, then 127248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * no proxy will be used (non surprisingly, this is also the default). 127348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 127448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized void setProxyData(ProxyData proxyData) 127548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 127648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood this.proxyData = proxyData; 127748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 127848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 127948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 128048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Request a remote port forwarding. 128148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * If successful, then forwarded connections will be redirected to the given target address. 128248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * You can cancle a requested remote port forwarding by calling 128348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * {@link #cancelRemotePortForwarding(int) cancelRemotePortForwarding()}. 128448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 128548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * A call of this method will block until the peer either agreed or disagreed to your request- 128648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 128748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Note 1: this method typically fails if you 128848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <ul> 128948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <li>pass a port number for which the used remote user has not enough permissions (i.e., port 129048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * < 1024)</li> 129148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <li>or pass a port number that is already in use on the remote server</li> 129248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <li>or if remote port forwarding is disabled on the server.</li> 129348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * </ul> 129448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 129548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Note 2: (from the openssh man page): By default, the listening socket on the server will be 129648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * bound to the loopback interface only. This may be overriden by specifying a bind address. 129748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Specifying a remote bind address will only succeed if the server's <b>GatewayPorts</b> option 129848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * is enabled (see sshd_config(5)). 129948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 130048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param bindAddress address to bind to on the server: 130148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <ul> 130248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <li>"" means that connections are to be accepted on all protocol families 130348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * supported by the SSH implementation</li> 130448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <li>"0.0.0.0" means to listen on all IPv4 addresses</li> 130548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <li>"::" means to listen on all IPv6 addresses</li> 130648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <li>"localhost" means to listen on all protocol families supported by the SSH 130748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * implementation on loopback addresses only, [RFC3330] and RFC3513]</li> 130848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <li>"127.0.0.1" and "::1" indicate listening on the loopback interfaces for 130948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * IPv4 and IPv6 respectively</li> 131048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * </ul> 131148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param bindPort port number to bind on the server (must be > 0) 131248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param targetAddress the target address (IP or hostname) 131348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param targetPort the target port 131448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @throws IOException 131548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 131648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized void requestRemotePortForwarding(String bindAddress, int bindPort, String targetAddress, 131748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int targetPort) throws IOException 131848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 131948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (tm == null) 132048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalStateException("You need to establish a connection first."); 132148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 132248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (!authenticated) 132348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalStateException("The connection is not authenticated."); 132448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 132548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if ((bindAddress == null) || (targetAddress == null) || (bindPort <= 0) || (targetPort <= 0)) 132648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalArgumentException(); 132748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 132848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood cm.requestGlobalForward(bindAddress, bindPort, targetAddress, targetPort); 132948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 133048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 133148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 133248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Cancel an earlier requested remote port forwarding. 133348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Currently active forwardings will not be affected (e.g., disrupted). 133448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Note that further connection forwarding requests may be received until 133548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * this method has returned. 133648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 133748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param bindPort the allocated port number on the server 133848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @throws IOException if the remote side refuses the cancel request or another low 133948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * level error occurs (e.g., the underlying connection is closed) 134048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 134148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized void cancelRemotePortForwarding(int bindPort) throws IOException 134248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 134348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (tm == null) 134448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalStateException("You need to establish a connection first."); 134548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 134648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (!authenticated) 134748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalStateException("The connection is not authenticated."); 134848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 134948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood cm.requestCancelGlobalForward(bindPort); 135048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 135148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 135248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 135348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Provide your own instance of SecureRandom. Can be used, e.g., if you 135448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * want to seed the used SecureRandom generator manually. 135548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * <p> 135648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * The SecureRandom instance is used during key exchanges, public key authentication, 135748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * x11 cookie generation and the like. 135848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 135948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @param rnd a SecureRandom instance 136048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 136148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public synchronized void setSecureRandom(SecureRandom rnd) 136248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 136348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (rnd == null) 136448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalArgumentException(); 136548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 136648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood this.generator = rnd; 136748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 136848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood} 1369