From 16749e9e96738c88fdefa496a9e7a127740d0282 Mon Sep 17 00:00:00 2001 From: UnfamiliarLegacy <74633542+UnfamiliarLegacy@users.noreply.github.com> Date: Mon, 13 Feb 2023 03:32:34 +0100 Subject: [PATCH 1/2] Update jetty and drop javax.websocket-api --- G-Earth/pom.xml | 5 +- .../proxy/nitro/websocket/NitroSession.java | 2 +- .../nitro/websocket/NitroWebsocketClient.java | 3 +- .../nitro/websocket/NitroWebsocketServer.java | 111 +++++++++--------- .../nitro/NitroPacketHandler.java | 14 ++- 5 files changed, 74 insertions(+), 61 deletions(-) diff --git a/G-Earth/pom.xml b/G-Earth/pom.xml index 53526ad..3c4a4ff 100644 --- a/G-Earth/pom.xml +++ b/G-Earth/pom.xml @@ -10,7 +10,7 @@ 1.8 - 9.4.48.v20220622 + 9.4.50.v20221201 1.3.5 @@ -238,14 +238,11 @@ maven-artifact 3.6.3 - - javax.websocket javax.websocket-api 1.1 - org.eclipse.jetty jetty-server diff --git a/G-Earth/src/main/java/gearth/protocol/connection/proxy/nitro/websocket/NitroSession.java b/G-Earth/src/main/java/gearth/protocol/connection/proxy/nitro/websocket/NitroSession.java index f85854e..d7f4665 100644 --- a/G-Earth/src/main/java/gearth/protocol/connection/proxy/nitro/websocket/NitroSession.java +++ b/G-Earth/src/main/java/gearth/protocol/connection/proxy/nitro/websocket/NitroSession.java @@ -1,6 +1,6 @@ package gearth.protocol.connection.proxy.nitro.websocket; -import javax.websocket.Session; +import org.eclipse.jetty.websocket.api.Session; public interface NitroSession { diff --git a/G-Earth/src/main/java/gearth/protocol/connection/proxy/nitro/websocket/NitroWebsocketClient.java b/G-Earth/src/main/java/gearth/protocol/connection/proxy/nitro/websocket/NitroWebsocketClient.java index d003c31..7ebfc7d 100644 --- a/G-Earth/src/main/java/gearth/protocol/connection/proxy/nitro/websocket/NitroWebsocketClient.java +++ b/G-Earth/src/main/java/gearth/protocol/connection/proxy/nitro/websocket/NitroWebsocketClient.java @@ -50,6 +50,7 @@ public class NitroWebsocketClient implements NitroSession { activeSession = (JsrSession) session; activeSession.setMaxBinaryMessageBufferSize(NitroConstants.WEBSOCKET_BUFFER_SIZE); + activeSession.setMaxTextMessageBufferSize(NitroConstants.WEBSOCKET_BUFFER_SIZE); // Set proper headers to spoof being a real client. final Map> headers = new HashMap<>(activeSession.getUpgradeRequest().getHeaders()); @@ -94,7 +95,7 @@ public class NitroWebsocketClient implements NitroSession { } @Override - public Session getSession() { + public org.eclipse.jetty.websocket.api.Session getSession() { return activeSession; } diff --git a/G-Earth/src/main/java/gearth/protocol/connection/proxy/nitro/websocket/NitroWebsocketServer.java b/G-Earth/src/main/java/gearth/protocol/connection/proxy/nitro/websocket/NitroWebsocketServer.java index 3df6cb7..5ed19c1 100644 --- a/G-Earth/src/main/java/gearth/protocol/connection/proxy/nitro/websocket/NitroWebsocketServer.java +++ b/G-Earth/src/main/java/gearth/protocol/connection/proxy/nitro/websocket/NitroWebsocketServer.java @@ -5,17 +5,21 @@ import gearth.protocol.HMessage; import gearth.protocol.connection.proxy.nitro.NitroConstants; import gearth.protocol.packethandler.PacketHandler; import gearth.protocol.packethandler.nitro.NitroPacketHandler; -import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; -import org.eclipse.jetty.websocket.jsr356.JsrExtension; +import org.eclipse.jetty.websocket.api.Session; +import org.eclipse.jetty.websocket.api.WebSocketListener; +import org.eclipse.jetty.websocket.client.ClientUpgradeRequest; +import org.eclipse.jetty.websocket.client.WebSocketClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.websocket.*; import java.io.IOException; import java.net.URI; -import java.util.*; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Map; -public class NitroWebsocketServer extends Endpoint implements NitroSession { +public class NitroWebsocketServer implements WebSocketListener, NitroSession { private static final Logger logger = LoggerFactory.getLogger(NitroWebsocketServer.class); @@ -39,66 +43,34 @@ public class NitroWebsocketServer extends Endpoint implements NitroSession { public void connect(String websocketUrl, Map> clientHeaders) throws IOException { try { - logger.info("Connecting to origin websocket at {}", websocketUrl); + logger.info("Building origin websocket connection ({})", websocketUrl); - ClientEndpointConfig.Builder builder = ClientEndpointConfig.Builder.create(); + final WebSocketClient client = new WebSocketClient(); - builder.extensions(Collections.singletonList(new JsrExtension(new ExtensionConfig("permessage-deflate;client_max_window_bits")))); + client.setMaxBinaryMessageBufferSize(NitroConstants.WEBSOCKET_BUFFER_SIZE); + client.setMaxTextMessageBufferSize(NitroConstants.WEBSOCKET_BUFFER_SIZE); - builder.configurator(new ClientEndpointConfig.Configurator() { - @Override - public void beforeRequest(Map> headers) { - clientHeaders.forEach((key, value) -> { - if (SKIP_HEADERS.contains(key)) { - return; - } + final ClientUpgradeRequest request = new ClientUpgradeRequest(); - headers.remove(key); - headers.put(key, value); - }); + clientHeaders.forEach((key, value) -> { + if (SKIP_HEADERS.contains(key)) { + return; } + + request.setHeader(key, value); }); - ClientEndpointConfig config = builder.build(); + logger.info("Connecting to origin websocket at {}", websocketUrl); - ContainerProvider.getWebSocketContainer().connectToServer(this, config, URI.create(websocketUrl)); + client.start(); + client.connect(this, URI.create(websocketUrl), request); logger.info("Connected to origin websocket"); - } catch (DeploymentException e) { - throw new IOException("Failed to deploy websocket client", e); + } catch (Exception e) { + throw new IOException("Failed to start websocket client to origin " + websocketUrl, e); } } - @Override - public void onOpen(Session session, EndpointConfig config) { - this.activeSession = session; - this.activeSession.setMaxBinaryMessageBufferSize(NitroConstants.WEBSOCKET_BUFFER_SIZE); - this.activeSession.addMessageHandler(new MessageHandler.Whole() { - @Override - public void onMessage(byte[] message) { - try { - packetHandler.act(message); - } catch (IOException e) { - e.printStackTrace(); - } - } - }); - } - - @Override - public void onClose(Session session, CloseReason closeReason) { - // Hotel closed connection. - client.shutdownProxy(); - } - - @Override - public void onError(Session session, Throwable throwable) { - throwable.printStackTrace(); - - // Shutdown. - client.shutdownProxy(); - } - @Override public Session getSession() { return activeSession; @@ -118,10 +90,43 @@ public class NitroWebsocketServer extends Endpoint implements NitroSession { try { activeSession.close(); - } catch (IOException e) { + } catch (Exception e) { e.printStackTrace(); } finally { activeSession = null; } } + + @Override + public void onWebSocketBinary(byte[] bytes, int i, int i1) { + try { + packetHandler.act(bytes); + } catch (IOException e) { + logger.error("Failed to handle packet", e); + } + } + + @Override + public void onWebSocketText(String s) { + logger.warn("Received text message from hotel"); + } + + @Override + public void onWebSocketClose(int i, String s) { + // Hotel closed connection. + client.shutdownProxy(); + } + + @Override + public void onWebSocketConnect(org.eclipse.jetty.websocket.api.Session session) { + activeSession = session; + } + + @Override + public void onWebSocketError(Throwable throwable) { + throwable.printStackTrace(); + + // Shutdown. + client.shutdownProxy(); + } } diff --git a/G-Earth/src/main/java/gearth/protocol/packethandler/nitro/NitroPacketHandler.java b/G-Earth/src/main/java/gearth/protocol/packethandler/nitro/NitroPacketHandler.java index d8b69b0..fc72f34 100644 --- a/G-Earth/src/main/java/gearth/protocol/packethandler/nitro/NitroPacketHandler.java +++ b/G-Earth/src/main/java/gearth/protocol/packethandler/nitro/NitroPacketHandler.java @@ -6,13 +6,17 @@ import gearth.protocol.connection.proxy.nitro.websocket.NitroSession; import gearth.protocol.packethandler.PacketHandler; import gearth.protocol.packethandler.PayloadBuffer; import gearth.services.extension_handler.ExtensionHandler; +import org.eclipse.jetty.websocket.api.Session; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import javax.websocket.Session; import java.io.IOException; import java.nio.ByteBuffer; public class NitroPacketHandler extends PacketHandler { + private static final Logger logger = LoggerFactory.getLogger(NitroPacketHandler.class); + private final HMessage.Direction direction; private final NitroSession session; private final PayloadBuffer payloadBuffer; @@ -39,7 +43,13 @@ public class NitroPacketHandler extends PacketHandler { buffer = buffer.clone(); } - localSession.getAsyncRemote().sendBinary(ByteBuffer.wrap(buffer)); + try { + localSession.getRemote().sendBytes(ByteBuffer.wrap(buffer)); + } catch (IOException e) { + logger.error("Error sending packet to nitro client", e); + return false; + } + return true; } From 8a880a13df643a7b23eb1e0987cead6a7c014367 Mon Sep 17 00:00:00 2001 From: UnfamiliarLegacy <74633542+UnfamiliarLegacy@users.noreply.github.com> Date: Mon, 13 Feb 2023 05:03:56 +0100 Subject: [PATCH 2/2] Allow untrusted SSL certificates for Nitro --- .../nitro/websocket/NitroWebsocketServer.java | 55 +++++++++++++++++-- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/G-Earth/src/main/java/gearth/protocol/connection/proxy/nitro/websocket/NitroWebsocketServer.java b/G-Earth/src/main/java/gearth/protocol/connection/proxy/nitro/websocket/NitroWebsocketServer.java index 5ed19c1..37ca63d 100644 --- a/G-Earth/src/main/java/gearth/protocol/connection/proxy/nitro/websocket/NitroWebsocketServer.java +++ b/G-Earth/src/main/java/gearth/protocol/connection/proxy/nitro/websocket/NitroWebsocketServer.java @@ -5,6 +5,8 @@ import gearth.protocol.HMessage; import gearth.protocol.connection.proxy.nitro.NitroConstants; import gearth.protocol.packethandler.PacketHandler; import gearth.protocol.packethandler.nitro.NitroPacketHandler; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.WebSocketListener; import org.eclipse.jetty.websocket.client.ClientUpgradeRequest; @@ -12,8 +14,13 @@ import org.eclipse.jetty.websocket.client.WebSocketClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; import java.io.IOException; import java.net.URI; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.HashSet; import java.util.List; @@ -45,10 +52,7 @@ public class NitroWebsocketServer implements WebSocketListener, NitroSession { try { logger.info("Building origin websocket connection ({})", websocketUrl); - final WebSocketClient client = new WebSocketClient(); - - client.setMaxBinaryMessageBufferSize(NitroConstants.WEBSOCKET_BUFFER_SIZE); - client.setMaxTextMessageBufferSize(NitroConstants.WEBSOCKET_BUFFER_SIZE); + final WebSocketClient client = createWebSocketClient(); final ClientUpgradeRequest request = new ClientUpgradeRequest(); @@ -129,4 +133,47 @@ public class NitroWebsocketServer implements WebSocketListener, NitroSession { // Shutdown. client.shutdownProxy(); } + + private SSLContext createSSLContext() { + final TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() { + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + + @Override + public void checkClientTrusted(X509Certificate[] certs, String authType) { + } + + @Override + public void checkServerTrusted(X509Certificate[] certs, String authType) { + } + }}; + + try { + final SSLContext sslContext = SSLContext.getInstance("TLS"); + + sslContext.init(null, trustAllCerts, new SecureRandom()); + + return sslContext; + } catch (Exception e) { + throw new RuntimeException("Failed to setup ssl context", e); + } + } + + private HttpClient createHttpClient() { + final SslContextFactory.Client factory = new SslContextFactory.Client(); + + factory.setSslContext(createSSLContext()); + + return new HttpClient(factory); + } + + private WebSocketClient createWebSocketClient() { + final WebSocketClient client = new WebSocketClient(createHttpClient()); + + client.setMaxBinaryMessageBufferSize(NitroConstants.WEBSOCKET_BUFFER_SIZE); + client.setMaxTextMessageBufferSize(NitroConstants.WEBSOCKET_BUFFER_SIZE); + + return client; + } }