com.sshtools.javardp.layers.Transport Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of rdp Show documentation
Show all versions of rdp Show documentation
Swing RDP component based on ProperJavaRDP with some modifications to allow multiple sessions within the same runtime, and to fix some bugs and inconsistencies with newer Windows versions.
The newest version!
package com.sshtools.javardp.layers;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.LinkedList;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.X509TrustManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.sshtools.javardp.HexDump;
import com.sshtools.javardp.Packet;
import com.sshtools.javardp.RdesktopException;
import com.sshtools.javardp.SecurityType;
import com.sshtools.javardp.State;
import com.sshtools.javardp.io.IO;
import com.sshtools.javardp.io.IOSocket;
import com.sshtools.javardp.io.SocketIO;
import com.sshtools.javardp.layers.nla.NLA;
public class Transport implements Layer {
static Logger logger = LoggerFactory.getLogger(Transport.class);
public static final String[] CIPHERS = { "SSL_RSA_WITH_RC4_128_MD5", "SSL_RSA_WITH_RC4_128_SHA",
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA", "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", "SSL_RSA_WITH_3DES_EDE_CBC_SHA",
"SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA", "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA", "SSL_RSA_WITH_DES_CBC_SHA",
"SSL_DHE_RSA_WITH_DES_CBC_SHA", "SSL_DHE_DSS_WITH_DES_CBC_SHA", "SSL_RSA_EXPORT_WITH_RC4_40_MD5",
"SSL_RSA_EXPORT_WITH_DES40_CBC_SHA", "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA" };
private State state;
private DataInputStream in = null;
private IO io;
private DataOutputStream out = null;
private ISO iso;
public Transport(State state, ISO iso) {
this.state = state;
this.iso = iso;
}
public void sendPacket(Packet buffer) throws IOException {
byte[] packet = new byte[buffer.getEnd()];
buffer.copyToByteArray(packet, 0, 0, packet.length);
if (state.getOptions().isDebugHexdump())
HexDump.encode(packet, "SEND"/* System.out */);
out.write(packet);
out.flush();
}
public State getState() {
return state;
}
public DataInputStream getIn() {
return in;
}
public IO getIo() {
return io;
}
public DataOutputStream getOut() {
return out;
}
public void connect(IO io) throws IOException {
this.io = io;
this.in = new DataInputStream(new BufferedInputStream(io.getInputStream()));
this.out = new DataOutputStream(new BufferedOutputStream(io.getOutputStream()));
}
public void startSsl() throws IOException, RdesktopException {
try {
this.io = this.negotiateSSL(this.io);
this.in = new DataInputStream(this.io.getInputStream());
this.out = new DataOutputStream(this.io.getOutputStream());
logger.info("SSL handshake completed.");
} catch (Exception e) {
throw new RdesktopException("SSL negotiation failed: " + e.getMessage(), e);
}
if (state.getSecurityType() == SecurityType.HYBRID) {
/* Start CredSSP! */
NLA nla = new NLA(state, this);
nla.start();
}
}
/**
* Receive a specified number of bytes from the server, and store in a
* packet
*
* @param p Packet to append data to, null results in a new packet being
* created
* @param length Length of data to read
* @return Packet containing read data, appended to original data if
* provided
* @throws IOException on error
*/
public Packet receivePacket(Packet p, int length) throws IOException {
if (logger.isDebugEnabled())
logger.debug("receivePacket");
Packet buffer = null;
byte[] packet = new byte[length];
try {
in.readFully(packet, 0, length);
} catch (IOException ioe) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("I/O error reading packet. Expected up to %d bytes.", length));
HexDump.encode(packet, "Packet payload (read so far) contains");
}
throw ioe;
}
if (state.getOptions().isDebugHexdump())
HexDump.encode(packet, "RECEIVE" /* System.out */);
if (p == null) {
buffer = new Packet(length);
buffer.copyFromByteArray(packet, 0, 0, packet.length);
buffer.markEnd(length);
buffer.setStart(buffer.getPosition());
} else {
buffer = new Packet((p.getEnd() - p.getStart()) + length);
buffer.copyFromPacket(p, p.getStart(), 0, p.getEnd());
buffer.copyFromByteArray(packet, 0, p.getEnd(), packet.length);
buffer.markEnd(p.size() + packet.length);
buffer.setPosition(p.getPosition());
buffer.setStart(0);
}
return buffer;
}
protected IO negotiateSSL(IO io) throws Exception {
Socket socket = new IOSocket(io);
X509TrustManager tm = state.getOptions().getTrustManager() == null ? createDefaultTrustManager()
: state.getOptions().getTrustManager();
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, new X509TrustManager[] { tm }, null);
SSLSocketFactory socketFactory = sc.getSocketFactory();
logger.info("Initialising SSL");
SSLSocket sslSocket = (SSLSocket) socketFactory.createSocket(socket, socket.getInetAddress().getHostName(),
socket.getPort(), true);
sslSocket.setEnabledCipherSuites(CIPHERS);
logger.info("Starting SSL handshake");
sslSocket.startHandshake();
logger.info("Completed SSL handshake");
return new SocketIO(sslSocket);
}
private X509TrustManager createDefaultTrustManager() {
return new X509TrustManager() {
LinkedList listCert = new LinkedList<>();
@Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
throw new UnsupportedOperationException();
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
X509Certificate[] arrayOfX509Certificate;
int j = (arrayOfX509Certificate = chain).length;
for (int i = 0; i < j; i++) {
X509Certificate x509Certificate = arrayOfX509Certificate[i];
this.listCert.add(x509Certificate);
}
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return this.listCert.toArray(new X509Certificate[this.listCert.size()]);
}
};
}
public boolean isConnected() {
return io != null;
}
public void disconnect() {
if (io == null)
return;
if (in != null) {
try {
in.close();
} catch (IOException ioe) {
}
}
if (out != null) {
try {
out.close();
} catch (IOException ioe) {
}
}
if (io != null) {
try {
io.closeIO();
} catch (IOException ioe) {
} finally {
io = null;
}
}
}
@Override
public ISO getParent() {
return iso;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy