diff --git a/.gitignore b/.gitignore index f49c92f..b6998ff 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .gradle .idea/* out +__pycache__ diff --git a/build.gradle b/build.gradle index eb3fdad..e551d37 100644 --- a/build.gradle +++ b/build.gradle @@ -12,5 +12,9 @@ repositories { } dependencies { + compile 'org.java-websocket:Java-WebSocket:1.4.0' + compile group: 'javax.ws.rs', name: 'javax.ws.rs-api', version: '2.0-m02' + compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.9.8' + compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.8' testCompile group: 'junit', name: 'junit', version: '4.12' } diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..8528898 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +websockets==6.0.0 \ No newline at end of file diff --git a/scripts/proxy.py b/scripts/proxy.py index cc100a7..eec4254 100644 --- a/scripts/proxy.py +++ b/scripts/proxy.py @@ -98,6 +98,7 @@ def send_message(self, metadata, data1, data2): data1_size = len(data1) data2_size = len(data2) metadata_size = len(metadata_bytes) + msg = struct.pack(" requestHeaders; + public int responseCode; + public List responseHeaders; + + + public InterceptedMessage(ByteBuffer buffer) throws IOException { + buffer = buffer.order(ByteOrder.LITTLE_ENDIAN); + + int metadataSize = buffer.getInt(); + int request_content_size = buffer.getInt(); + int response_content_size = buffer.getInt(); + + byte[] metadataBytes = new byte[metadataSize]; + buffer.get(metadataBytes); + + requestBody = new byte[request_content_size]; + buffer.get(requestBody); + + responseBody = new byte[response_content_size]; + buffer.get(responseBody); + + ObjectMapper mapper = new ObjectMapper(); + JsonNode metadata = mapper.readTree(metadataBytes); + requestMethod = metadata.get("request").get("method").asText(); + requestURL = new URL(metadata.get("request").get("url").asText()); + JsonNode headers = metadata.get("request").get("headers"); + requestHeaders = new ArrayList<>(); + for (JsonNode headerNode : headers) { + String[] headerArray = new String[2]; + headerArray[0] = headerNode.get(0).asText(); + headerArray[1] = headerNode.get(1).asText(); + requestHeaders.add(headerArray); + } + + responseCode = metadata.get("response").get("status_code").asInt(); + headers = metadata.get("request").get("headers"); + responseHeaders = new ArrayList<>(); + for (JsonNode headerNode : headers) { + String[] headerArray = new String[2]; + headerArray[0] = headerNode.get(0).asText(); + headerArray[1] = headerNode.get(1).asText(); + responseHeaders.add(headerArray); + } + } + + public ByteBuffer serializedResponseToMitmproxy() throws JsonProcessingException { + int contentLength = responseBody.length; + + // create JSON for metadata. Which is the responseCode and responseHeaders. + // while we're at it, set the Content-Length header + ObjectMapper mapper = new ObjectMapper(); + ObjectNode metadataRoot = mapper.createObjectNode(); + metadataRoot.put("status_code", responseCode); + + ArrayNode headersNode = mapper.createArrayNode(); + List headerNodes = responseHeaders.stream().map((h) -> { + ArrayNode headerPair = mapper.createArrayNode(); + headerPair.add(h[0]); + if (h[0].equals("content-length")) { + headerPair.add(Integer.toString(contentLength)); + } else { + headerPair.add(h[1]); + } + return headerPair; + }).collect(Collectors.toList()); + headersNode.addAll(headerNodes); + metadataRoot.set("headers", headersNode); + + String metadataJson = mapper.writeValueAsString(metadataRoot); + byte[] metadata = metadataJson.getBytes(StandardCharsets.UTF_8); + int metadataLength = metadata.length; + + + ByteBuffer buffer = ByteBuffer.allocate(8 + metadataLength + contentLength); + buffer.order(ByteOrder.LITTLE_ENDIAN); + buffer.putInt(metadataLength); + buffer.putInt(contentLength); + buffer.put(metadata); + buffer.put(responseBody); + + return (ByteBuffer) buffer.rewind(); + } +} \ No newline at end of file diff --git a/src/main/java/MitmproxyJava.java b/src/main/java/MitmproxyJava.java index cfe482d..0b1fd6a 100644 --- a/src/main/java/MitmproxyJava.java +++ b/src/main/java/MitmproxyJava.java @@ -1,14 +1,29 @@ +import org.java_websocket.client.WebSocketClient; +import org.java_websocket.handshake.ServerHandshake; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.URI; +import java.net.URISyntaxException; import java.util.function.Function; public class MitmproxyJava { + private MitmproxyServer server; + public static final int WEBSOCKET_PORT = 8765; + public MitmproxyJava(Function messageInterceptor) throws URISyntaxException { +// InterceptedMessage message = new InterceptedMessage(); +// message.message = "hi from message"; +// messageInterceptor.apply(message); - public MitmproxyJava(Function messageInterceptor) { - InterceptedMessage message = new InterceptedMessage(); - message.message = "hi from message"; - messageInterceptor.apply(message); - + server = new MitmproxyServer(new InetSocketAddress("localhost", WEBSOCKET_PORT)); + server.run(); System.out.println("you started me"); } + + public void stop() throws IOException, InterruptedException { + server.stop(); + } } + diff --git a/src/main/java/MitmproxyServer.java b/src/main/java/MitmproxyServer.java new file mode 100644 index 0000000..cbff9c5 --- /dev/null +++ b/src/main/java/MitmproxyServer.java @@ -0,0 +1,62 @@ +import com.fasterxml.jackson.core.JsonProcessingException; +import org.java_websocket.WebSocket; +import org.java_websocket.handshake.ClientHandshake; +import org.java_websocket.server.WebSocketServer; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; + +public class MitmproxyServer extends WebSocketServer { + + public MitmproxyServer(InetSocketAddress address) { + super(address); + } + + @Override + public void onOpen(WebSocket conn, ClientHandshake handshake) { + // conn.send("Welcome to the server!"); //This method sends a message to the new client + // broadcast( "new connection: " + handshake.getResourceDescriptor() ); //This method sends a message to all clients connected + System.out.println("new connection to " + conn.getRemoteSocketAddress()); + } + + @Override + public void onClose(WebSocket conn, int code, String reason, boolean remote) { + System.out.println("closed " + conn.getRemoteSocketAddress() + " with exit code " + code + " additional info: " + reason); + } + + @Override + public void onMessage(WebSocket conn, String message) { + System.out.println("received message from " + conn.getRemoteSocketAddress() + ": " + message); + } + + @Override + public void onMessage( WebSocket conn, ByteBuffer message ) { + System.out.println("received ByteBuffer from " + conn.getRemoteSocketAddress()); + InterceptedMessage intercepted = null; + try { + intercepted = new InterceptedMessage(message); + } catch (IOException e) { + System.out.println("Could not parse message"); + e.printStackTrace(); + } + System.out.println(intercepted.requestURL.toString()); + try { + conn.send(intercepted.serializedResponseToMitmproxy()); + } catch (JsonProcessingException e) { + System.out.println("Could not encode response to mitmproxy"); + e.printStackTrace(); + } + } + + @Override + public void onError(WebSocket conn, Exception ex) { + System.err.println("an error occured on connection " + conn.getRemoteSocketAddress() + ":" + ex); + } + + @Override + public void onStart() { + System.out.println("server started successfully"); + } +} diff --git a/src/test/java/MitmproxyJavaTest.java b/src/test/java/MitmproxyJavaTest.java index 6de7601..d18af2d 100644 --- a/src/test/java/MitmproxyJavaTest.java +++ b/src/test/java/MitmproxyJavaTest.java @@ -1,5 +1,8 @@ import org.junit.jupiter.api.Test; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; import java.util.function.Function; import static org.junit.jupiter.api.Assertions.*; @@ -7,10 +10,12 @@ public class MitmproxyJavaTest { @Test - public void ConstructorTest() { + public void ConstructorTest() throws URISyntaxException, IOException, InterruptedException { MitmproxyJava proxy = new MitmproxyJava((InterceptedMessage m) -> { - System.out.println(m.message); + System.out.println(m.requestURL.toString()); return new Boolean(true); }); + System.out.println("advanced in test"); + proxy.stop(); } } \ No newline at end of file