package de.tudarmstadt.informatik.hostage.net; import java.io.FileDescriptor; import java.io.IOException; import java.lang.reflect.Field; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.SocketImpl; import javax.net.ServerSocketFactory; import de.tudarmstadt.informatik.hostage.system.PrivilegedPort; import de.tudarmstadt.informatik.hostage.ui.MainActivity; /** * Server Socket Factory using the porthack. * @author Mihai Plasoianu */ public class MyServerSocketFactory extends ServerSocketFactory { /** * This method creates and returns a ServerSocket. A custom SocketImpl is * injected into the ServerSocket. */ @Override public ServerSocket createServerSocket(int port) throws IOException { ServerSocket socket = null; if(port > 1023){ socket = new ServerSocket(); // Set SO_REUSEADDRESS before port is bound socket.setReuseAddress(true); socket.bind(new InetSocketAddress(port)); } else if(MainActivity.porthackInstalled){ FileDescriptor fd = new PrivilegedPort(port).bindAndGetFD(); socket = new ServerSocket(); try { SocketImpl impl = getImpl(socket); injectFD(fd, impl); injectImpl(impl, socket); setBound(socket); } catch (Exception e) { e.printStackTrace(); } } return socket; } /** * Extracts the SocketImpl out of a ServerSocket. */ private SocketImpl getImpl(ServerSocket socket) throws Exception { Field implField = socket.getClass().getDeclaredField("impl"); implField.setAccessible(true); return (SocketImpl) implField.get(socket); } /** * Injects a FileDescriptor into a SocketImpl. */ private void injectFD(FileDescriptor fd, SocketImpl impl) throws Exception { Class plainServerSocketImplClazz = impl.getClass(); Class plainSocketImplClazz = plainServerSocketImplClazz .getSuperclass(); Class socketImplClazz = plainSocketImplClazz.getSuperclass(); Field fdField = socketImplClazz.getDeclaredField("fd"); fdField.setAccessible(true); fdField.set(impl, fd); } /** * Injects a SocketImpl into a ServerSocket. */ private void injectImpl(SocketImpl impl, ServerSocket socket) throws Exception { Field implField = socket.getClass().getDeclaredField("impl"); implField.setAccessible(true); implField.set(socket, impl); } /** * Sets the isBound Field of a ServerSocket to true. */ private void setBound(ServerSocket socket) throws Exception { Field boundField = socket.getClass().getDeclaredField("isBound"); boundField.setAccessible(true); boundField.set(socket, true); } /** * Must override. */ @Override public ServerSocket createServerSocket(int port, int backlog) throws IOException { return createServerSocket(port); } /** * Must override. */ @Override public ServerSocket createServerSocket(int port, int backlog, InetAddress iAddress) throws IOException { return createServerSocket(port); } }