blob: d1ac1ad548e28dcafdc97b7193d200b888b7dd25 (
plain) (
tree)
|
|
package de.bwlehrpool.bwlp_guac;
import java.io.Closeable;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class VncConnection implements Closeable {
private static final Logger LOGGER = LoggerFactory.getLogger(VncConnection.class);
private final Socket sock;
private final DataOutputStream out;
private final DataInputStream in;
public VncConnection(String host, int port) throws IOException {
sock = new Socket();
sock.connect(new InetSocketAddress(host, port), 1200);
sock.setSoTimeout(1000);
out = new DataOutputStream(sock.getOutputStream());
in = new DataInputStream(sock.getInputStream());
}
/**
* @return Version string on success, null if not RFB
* @throws IOException
*/
public String handshake() throws IOException {
byte[] buffer = new byte[12];
in.readFully(buffer);
if (buffer[0] != 'R' || buffer[1] != 'F' || buffer[2] != 'B')
return null;
out.write("RFB 003.008\n".getBytes());
out.flush();
return new String(buffer).substring(4, 11);
}
public boolean tryLogin(String passwd) throws IOException {
if (passwd == null)
return false; // Paswordless not supported yet (although simpler..)
int numTypes = in.read();
if (numTypes == 0) {
LOGGER.info("VNC Server @ " + sock.getRemoteSocketAddress() + " does not support any auth methods");
printError();
return false;
}
boolean ok = false;
for (int i = 0; i < numTypes; ++i) {
if (in.read() == 2) {
ok = true;
break; // Found "VNC Authentication"
}
}
if (!ok) {
LOGGER.info("VNC Server @ " + sock.getRemoteSocketAddress() + " does not support VNC Authentication");
return false;
}
out.write(2); // Pick passwd auth
// Get challenge data
byte[] challenge = new byte[16];
int ret = in.read(challenge);
if (ret != 16) {
LOGGER.info("Didn't receive challenge from VNC server @ " + sock.getRemoteSocketAddress());
return false;
}
// pad pw to 8 bytes
byte[] pw_bytes = passwd.getBytes();
pw_bytes = Arrays.copyOf(pw_bytes, 8);
// Encrypt
out.write(WeakCrypto.vncEncrypt(pw_bytes, challenge));
// check reply
int securityReply = in.readInt();
if (securityReply != 0) {
LOGGER.info("Security reply = " + securityReply + " for VNC server @ " + sock.getRemoteSocketAddress());
return false;
}
return true;
}
private void printError() {
try {
int len = in.readInt();
byte[] msg = new byte[len];
in.readFully(msg);
LOGGER.info(new String(msg, StandardCharsets.ISO_8859_1));
} catch (IOException e) {
// Nothing, we're already kinda handling an error, so if we can't fetch the
// message, ignore
}
}
@Override
public void close() throws IOException {
try {
in.close();
} catch (Exception e) {
}
try {
out.close();
} catch (Exception e) {
}
try {
sock.close();
} catch (Exception e) {
}
}
}
|