From 57f91b402d14dcac846a4e4488aff23825defaef Mon Sep 17 00:00:00 2001 From: Jacob Laursen Date: Sat, 4 Feb 2023 13:08:41 +0100 Subject: [PATCH] Add TLS support (#14331) Fixes #14309 Signed-off-by: Jacob Laursen --- bundles/org.openhab.binding.lgwebos/README.md | 11 ++++---- .../internal/LGWebOSBindingConstants.java | 3 ++ .../internal/LGWebOSHandlerFactory.java | 8 +++--- .../handler/LGWebOSConfiguration.java | 8 +++--- .../internal/handler/LGWebOSHandler.java | 2 +- .../internal/handler/LGWebOSTVSocket.java | 28 ++++++++++++++++--- .../main/resources/OH-INF/config/config.xml | 7 +++++ .../resources/OH-INF/i18n/lgwebos.properties | 4 ++- 8 files changed, 52 insertions(+), 19 deletions(-) diff --git a/bundles/org.openhab.binding.lgwebos/README.md b/bundles/org.openhab.binding.lgwebos/README.md index 1c0b9d1525b4f..51f41c7dff442 100644 --- a/bundles/org.openhab.binding.lgwebos/README.md +++ b/bundles/org.openhab.binding.lgwebos/README.md @@ -36,11 +36,12 @@ WebOS TV has three configuration parameters. Parameters: -| Name | Description | -|------------|-----------------------------------------------------------------------------------------------------| -| host | Hostname or IP address of TV | -| key | Key exchanged with TV after pairing (enter it after you paired the device) | -| macAddress | The MAC address of your TV to turn on via Wake On Lan (WOL). The binding will attempt to detect it. | +| Name | Description | +|------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| host | Hostname or IP address of TV | +| key | Key exchanged with TV after pairing (enter it after you paired the device) | +| macAddress | The MAC address of your TV to turn on via Wake On Lan (WOL). The binding will attempt to detect it. | +| useTLS | Enable Transport Layer Security. This is required by latest firmware versions and should work with older versions as well. In case of compatibility issues it can be disabled. | ### Configuration in .things file diff --git a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/LGWebOSBindingConstants.java b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/LGWebOSBindingConstants.java index a6f982d9c6b81..c033ff8b7f398 100644 --- a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/LGWebOSBindingConstants.java +++ b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/LGWebOSBindingConstants.java @@ -68,4 +68,7 @@ public class LGWebOSBindingConstants { public static final String CHANNEL_MEDIA_STOP = "mediaStop"; public static final String CHANNEL_APP_LAUNCHER = "appLauncher"; public static final String CHANNEL_RCBUTTON = "rcButton"; + + public static final int DEFAULT_WS_PORT = 3000; + public static final int DEFAULT_WSS_PORT = 3001; } diff --git a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/LGWebOSHandlerFactory.java b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/LGWebOSHandlerFactory.java index 85ee23609c8b5..bf9d788088d88 100644 --- a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/LGWebOSHandlerFactory.java +++ b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/LGWebOSHandlerFactory.java @@ -16,6 +16,8 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.websocket.client.WebSocketClient; import org.openhab.binding.lgwebos.internal.handler.LGWebOSHandler; import org.openhab.core.io.net.http.WebSocketFactory; @@ -53,7 +55,8 @@ public LGWebOSHandlerFactory(final @Reference WebSocketFactory webSocketFactory, * Cannot use openHAB's shared web socket client (webSocketFactory.getCommonWebSocketClient()) as we have to * change client settings. */ - this.webSocketClient = webSocketFactory.createWebSocketClient("lgwebos"); + var httpClient = new HttpClient(new SslContextFactory.Client(true)); + this.webSocketClient = new WebSocketClient(httpClient); this.stateDescriptionProvider = stateDescriptionProvider; } @@ -74,9 +77,6 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { @Override protected void activate(ComponentContext componentContext) { super.activate(componentContext); - // LGWebOS TVs only support WEAK cipher suites, thus not using SSL. - // SslContextFactory sslContextFactory = new SslContextFactory(true); - // sslContextFactory.addExcludeProtocols("tls/1.3"); // reduce timeout from default 15sec this.webSocketClient.setConnectTimeout(1000); diff --git a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSConfiguration.java b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSConfiguration.java index e3a40bf9e8cb8..09f125b693fb6 100644 --- a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSConfiguration.java +++ b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSConfiguration.java @@ -25,11 +25,11 @@ public class LGWebOSConfiguration { @Nullable String host; // name has to match LGWebOSBindingConstants.CONFIG_HOST - int port = 3000; // 3001 for TLS @Nullable String key; // name has to match LGWebOSBindingConstants.CONFIG_KEY @Nullable String macAddress; // name has to match LGWebOSBindingConstants.CONFIG_MAC_ADDRESS + boolean useTLS = true; public String getHost() { String h = host; @@ -41,8 +41,8 @@ public String getKey() { return k == null ? "" : k; } - public int getPort() { - return port; + public boolean getUseTLS() { + return useTLS; } public String getMacAddress() { @@ -52,7 +52,7 @@ public String getMacAddress() { @Override public String toString() { - return "WebOSConfiguration [host=" + host + ", port=" + port + ", key.length=" + getKey().length() + return "WebOSConfiguration [host=" + host + ", useTLS=" + useTLS + ", key.length=" + getKey().length() + ", macAddress=" + macAddress + "]"; } } diff --git a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSHandler.java b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSHandler.java index ac7ff8f82baad..c7f326534356b 100644 --- a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSHandler.java +++ b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSHandler.java @@ -135,7 +135,7 @@ public void initialize() { return; } - LGWebOSTVSocket s = new LGWebOSTVSocket(webSocketClient, this, host, c.getPort(), scheduler); + LGWebOSTVSocket s = new LGWebOSTVSocket(webSocketClient, this, host, c.getUseTLS(), scheduler); s.setListener(this); socket = s; diff --git a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSTVSocket.java b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSTVSocket.java index 721a289c88e1e..d14edc8d83ed8 100644 --- a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSTVSocket.java +++ b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSTVSocket.java @@ -116,6 +116,7 @@ public class LGWebOSTVSocket { private final URI destUri; private final LGWebOSTVKeyboardInput keyboardInput; private final ScheduledExecutorService scheduler; + private final Protocol protocol; public enum State { DISCONNECTING, @@ -125,6 +126,19 @@ public enum State { REGISTERED } + private enum Protocol { + WEB_SOCKET("ws", DEFAULT_WS_PORT), + WEB_SOCKET_SECURE("wss", DEFAULT_WSS_PORT); + + private Protocol(String name, int port) { + this.name = name; + this.port = port; + } + + public String name; + public int port; + } + private State state = State.DISCONNECTED; private @Nullable Session session; @@ -140,14 +154,15 @@ public enum State { private @Nullable ScheduledFuture disconnectingJob; - public LGWebOSTVSocket(WebSocketClient client, ConfigProvider config, String host, int port, + public LGWebOSTVSocket(WebSocketClient client, ConfigProvider config, String host, boolean useTLS, ScheduledExecutorService scheduler) { this.config = config; this.client = client; this.keyboardInput = new LGWebOSTVKeyboardInput(this); + this.protocol = useTLS ? Protocol.WEB_SOCKET_SECURE : Protocol.WEB_SOCKET; try { - this.destUri = new URI("ws://" + host + ":" + port); + this.destUri = new URI(protocol.name + "://" + host + ":" + protocol.port); } catch (URISyntaxException e) { throw new IllegalArgumentException("IP address or hostname provided is invalid: " + host); } @@ -916,8 +931,13 @@ public void onError(String errorMessage) { @Override public void onSuccess(@Nullable JsonObject jsonObj) { if (jsonObj != null) { - String socketPath = jsonObj.get("socketPath").getAsString().replace("wss:", "ws:").replace(":3001/", - ":3000/"); + String socketPath = jsonObj.get("socketPath").getAsString(); + if (protocol == Protocol.WEB_SOCKET) { + socketPath = socketPath + .replace(Protocol.WEB_SOCKET_SECURE.name + ":", Protocol.WEB_SOCKET.name + ":") + .replace(":" + Protocol.WEB_SOCKET_SECURE.port + "/", + ":" + Protocol.WEB_SOCKET.port + "/"); + } try { mouseSocket.connect(new URI(socketPath)); } catch (URISyntaxException e) { diff --git a/bundles/org.openhab.binding.lgwebos/src/main/resources/OH-INF/config/config.xml b/bundles/org.openhab.binding.lgwebos/src/main/resources/OH-INF/config/config.xml index 7de1fc2c1a456..52744558ea3b7 100644 --- a/bundles/org.openhab.binding.lgwebos/src/main/resources/OH-INF/config/config.xml +++ b/bundles/org.openhab.binding.lgwebos/src/main/resources/OH-INF/config/config.xml @@ -22,6 +22,13 @@ (WOL) when it receives command ON on channel power. Accepted value is six groups of two hexadecimal digits, separated by hyphens or colons, e.g '3c:cd:93:c2:20:e0'. + + + Enable Transport Layer Security. This is required by latest firmware versions and should work with older + versions as well. In case of compatibility issues it can be disabled. + true + true + diff --git a/bundles/org.openhab.binding.lgwebos/src/main/resources/OH-INF/i18n/lgwebos.properties b/bundles/org.openhab.binding.lgwebos/src/main/resources/OH-INF/i18n/lgwebos.properties index bfb22383f5b1a..54f4f3f7eb8f4 100644 --- a/bundles/org.openhab.binding.lgwebos/src/main/resources/OH-INF/i18n/lgwebos.properties +++ b/bundles/org.openhab.binding.lgwebos/src/main/resources/OH-INF/i18n/lgwebos.properties @@ -16,6 +16,8 @@ thing-type.config.lgwebos.WebOSTV.key.label = Access Key thing-type.config.lgwebos.WebOSTV.key.description = Key exchanged with TV after pairing. thing-type.config.lgwebos.WebOSTV.macAddress.label = MAC Address thing-type.config.lgwebos.WebOSTV.macAddress.description = If MAC Address of TV is entered here, the binding will attempt to power on the device via Wake On Lan (WOL) when it receives command ON on channel power. Accepted value is six groups of two hexadecimal digits, separated by hyphens or colons, e.g '3c:cd:93:c2:20:e0'. +thing-type.config.lgwebos.WebOSTV.useTLS.label = Use TLS +thing-type.config.lgwebos.WebOSTV.useTLS.description = Enable Transport Layer Security. This is required by latest firmware versions and should work with older versions as well. In case of compatibility issues it can be disabled. # channel types @@ -69,7 +71,7 @@ actionShowToastWithIconDesc = Sends a toast message to a WebOS device with custo actionShowToastInputIconLabel = Icon actionShowToastInputIconDesc = The URL to the icon to display -# Thing status descriptions +# thing status descriptions offline.config-error-unknown-host = Missing parameter "host" offline.comm-error-connexion-failed = Connection Failed: {0}