Add TLS support (#14331)

Fixes #14309

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>
This commit is contained in:
Jacob Laursen 2023-02-04 13:08:41 +01:00
parent e392f7f3bf
commit 697b510808
8 changed files with 52 additions and 19 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -16,6 +16,8 @@ import static org.openhab.binding.lgwebos.internal.LGWebOSBindingConstants.*;
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 class LGWebOSHandlerFactory extends BaseThingHandlerFactory {
* 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 class LGWebOSHandlerFactory extends BaseThingHandlerFactory {
@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);

View File

@ -25,11 +25,11 @@ import org.eclipse.jdt.annotation.Nullable;
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 class LGWebOSConfiguration {
return k == null ? "" : k;
}
public int getPort() {
return port;
public boolean getUseTLS() {
return useTLS;
}
public String getMacAddress() {
@ -52,7 +52,7 @@ public class LGWebOSConfiguration {
@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 + "]";
}
}

View File

@ -135,7 +135,7 @@ public class LGWebOSHandler extends BaseThingHandler
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;

View File

@ -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 class LGWebOSTVSocket {
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 class LGWebOSTVSocket {
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 class LGWebOSTVSocket {
@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) {

View File

@ -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'.</description>
</parameter>
<parameter name="useTLS" type="boolean" required="false">
<label>Use TLS</label>
<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.</description>
<advanced>true</advanced>
<default>true</default>
</parameter>
</config-description>
</config-description:config-descriptions>

View File

@ -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}