public HostnameRewritingObjectOutputStream(OutputStream out, String hostname)
throws IOException {
super(out);
this.hostname = hostname;
}
@Override
public PutField putFields() throws IOException {
return new PutFieldProxy(super.putFields(), hostname);
}
private static class PutFieldProxy extends ObjectOutputStream.PutField {
private final PutField delegate;
private final String hostname;
public PutFieldProxy(ObjectOutputStream.PutField delegate, String hostname) {
this.delegate = delegate;
this.hostname = hostname;
}
@Override
public void put(String name, boolean val) {
delegate.put(name, val);
}
@Override
public void put(String name, byte val) {
delegate.put(name, val);
}
@Override
public void put(String name, char val) {
delegate.put(name, val);
}
@Override
public void put(String name, short val) {
delegate.put(name, val);
}
@Override
public void put(String name, int val) {
delegate.put(name, val);
}
@Override
public void put(String name, long val) {
delegate.put(name, val);
}
@Override
public void put(String name, float val) {
delegate.put(name, val);
}
@Override
public void put(String name, double val) {
delegate.put(name, val);
}
@Override
public void put(String name, Object val) {
if ("hostname".equals(name)) {
delegate.put(name, hostname);
} else {
delegate.put(name, val);
}
}
@SuppressWarnings("deprecation")
@Override
public void write(ObjectOutput out) throws IOException {
delegate.write(out);
}
}
}
public static InetAddress getLoopbackAddress() {
try {
Method method = InetAddress.class.getMethod("getLoopbackAddress");
return (InetAddress) method.invoke(null);
} catch (Exception ignore) {
// Ignored.
}
try {
return InetAddress.getLocalHost();
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
}
public static InetSocketAddress getLoopbackAsHostname(String hostname, int port)
throws Exception {
InetSocketAddress addr = new InetSocketAddress(getLoopbackAddress(), port);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
HostnameRewritingObjectOutputStream oos = new HostnameRewritingObjectOutputStream(baos, hostname);
oos.writeObject(addr);
oos.close();
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
return (InetSocketAddress) ois.readObject();
}
public static void main(String[] args) throws Exception {
SSLContext context = SSLContext.getDefault();
SSLServerSocket server = (SSLServerSocket) context.getServerSocketFactory().createServerSocket();
InetAddress host = getLoopbackAddress();
server.bind(new InetSocketAddress(host, 0));
int port = server.getLocalPort();
SSLSocket client = (SSLSocket) context.getSocketFactory().createSocket();
SSLParameters paras = client.getSSLParameters();
paras.setEndpointIdentificationAlgorithm("HTTPS");
client.setSSLParameters(paras);
InetSocketAddress add = getLoopbackAsHostname("unmatched.example.com", port);
client.connect(add);
System.out.println("connect is finished");
SSLSocket serverPipe = (SSLSocket) server.accept();
System.out.println(serverPipe);
}