From c2268595eb3e55fb42ee7af4e6ae93670f513a87 Mon Sep 17 00:00:00 2001 From: nick Date: Mon, 12 Feb 2024 13:31:38 +0200 Subject: [PATCH] lwm2m_coap: DTLS Cid Length --- .../src/main/resources/thingsboard.yml | 20 +++ .../lwm2m/AbstractLwM2MIntegrationTest.java | 7 +- .../transport/lwm2m/Lwm2mTestHelper.java | 6 +- .../lwm2m/client/DtlsSessionLogger.java | 81 +++++++++++ .../lwm2m/client/LwM2MTestClient.java | 38 +++-- .../ota/sql/OtaLwM2MIntegrationTest.java | 6 +- .../rpc/AbstractRpcLwM2MIntegrationTest.java | 2 +- .../AbstractSecurityLwM2MIntegrationTest.java | 4 +- ...ityLwM2MIntegrationDtlsCidLength0Test.java | 38 +++++ ...ityLwM2MIntegrationDtlsCidLength3Test.java | 37 +++++ ...LwM2MIntegrationDtlsCidLengthNullTest.java | 38 +++++ ...rityLwM2MIntegrationDtlsCidLengthTest.java | 133 ++++++++++++++++++ ...oSecLwM2MIntegrationDtlsCidLengthTest.java | 48 +++++++ .../PskLwm2mIntegrationDtlsCidLengthTest.java | 46 ++++++ ...oSecLwM2MIntegrationDtlsCidLengthTest.java | 48 +++++++ .../PskLwm2mIntegrationDtlsCidLengthTest.java | 47 +++++++ ...oSecLwM2MIntegrationDtlsCidLengthTest.java | 48 +++++++ .../PskLwm2mIntegrationDtlsCidLengthTest.java | 47 +++++++ .../server/coapserver/TbCoapDtlsSettings.java | 13 ++ .../LwM2MTransportBootstrapService.java | 7 +- .../config/LwM2MTransportServerConfig.java | 4 + .../server/DefaultLwM2mTransportService.java | 18 +-- .../lwm2m/utils/LwM2MTransportUtil.java | 14 ++ 23 files changed, 707 insertions(+), 43 deletions(-) create mode 100644 application/src/test/java/org/thingsboard/server/transport/lwm2m/client/DtlsSessionLogger.java create mode 100644 application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLength0Test.java create mode 100644 application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLength3Test.java create mode 100644 application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLengthNullTest.java create mode 100644 application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLengthTest.java create mode 100644 application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_0/NoSecLwM2MIntegrationDtlsCidLengthTest.java create mode 100644 application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_0/PskLwm2mIntegrationDtlsCidLengthTest.java create mode 100644 application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_3/NoSecLwM2MIntegrationDtlsCidLengthTest.java create mode 100644 application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_3/PskLwm2mIntegrationDtlsCidLengthTest.java create mode 100644 application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_null/NoSecLwM2MIntegrationDtlsCidLengthTest.java create mode 100644 application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_null/PskLwm2mIntegrationDtlsCidLengthTest.java diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 0ddc86c5b7..0d401c5974 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -1019,6 +1019,16 @@ transport: # CoAP DTLS bind port bind_port: "${COAP_DTLS_BIND_PORT:5684}" # Server DTLS credentials + # CoAP DTLS connection ID length. RFC 9146, Connection Identifier for DTLS 1.2 + # Default: off + # Control usage of DTLS connection ID length (CID). + # - 'off' to deactivate it. + # - 'on' to activate Connection ID support (same as CID 0 or more 0). + # - A positive value defines generated CID size in bytes. + # - A value of 0 means we accept using CID but will not generate one for foreign peer (enables support but not for incoming traffic). + # - A value between 0 and <= 4: SingleNodeConnectionIdGenerator is used + # - A value that are > 4: MultiNodeConnectionIdGenerator is used + connection_id_length: "${COAP_DTLS_CONNECTION_ID_LENGTH:}" credentials: # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore) type: "${COAP_DTLS_CREDENTIALS_TYPE:PEM}" @@ -1056,6 +1066,16 @@ transport: dtls: # RFC7925_RETRANSMISSION_TIMEOUT_IN_MILLISECONDS = 9000 retransmission_timeout: "${LWM2M_DTLS_RETRANSMISSION_TIMEOUT_MS:9000}" + # CoAP DTLS connection ID length for LWM2M. RFC 9146, Connection Identifier for DTLS 1.2 + # Default: off + # Control usage of DTLS connection ID length (CID). + # - 'off' to deactivate it. + # - 'on' to activate Connection ID support (same as CID 0 or more 0). + # - A positive value defines generated CID size in bytes. + # - A value of 0 means we accept using CID but will not generate one for foreign peer (enables support but not for incoming traffic). + # - A value between 0 and <= 4: SingleNodeConnectionIdGenerator is used + # - A value that are > 4: MultiNodeConnectionIdGenerator is used + connection_id_length: "${LWM2M_DTLS_CONNECTION_ID_LENGTH:}" server: # LwM2M Server ID id: "${LWM2M_SERVER_ID:123}" diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java index 78f999080d..3d21a191a9 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java @@ -236,7 +236,7 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte getWsClient().waitForReply(); getWsClient().registerWaitForUpdate(); - createNewClient(security, null, coapConfig, false, endpoint); + createNewClient(security, null, coapConfig, false, endpoint, null); deviceId = device.getId().getId().toString(); awaitObserveReadAll(0, deviceId); String msg = getWsClient().waitForUpdate(); @@ -304,14 +304,15 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte this.resources = resources; } - public void createNewClient(Security security, Security securityBs, Configuration coapConfig, boolean isRpc, String endpoint) throws Exception { + public void createNewClient(Security security, Security securityBs, Configuration coapConfig, boolean isRpc, + String endpoint, Integer clientDtlsCidLength) throws Exception { this.clientDestroy(); lwM2MTestClient = new LwM2MTestClient(this.executor, endpoint); try (ServerSocket socket = new ServerSocket(0)) { int clientPort = socket.getLocalPort(); lwM2MTestClient.init(security, securityBs, coapConfig, clientPort, isRpc, - this.defaultLwM2mUplinkMsgHandlerTest, this.clientContextTest, isWriteAttribute); + this.defaultLwM2mUplinkMsgHandlerTest, this.clientContextTest, isWriteAttribute, clientDtlsCidLength); } } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java index 32e1444de6..b2ed3cc297 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java @@ -53,7 +53,7 @@ public class Lwm2mTestHelper { public enum LwM2MClientState { - ON_INIT(1, "onInit"), + ON_INIT(0, "onInit"), ON_BOOTSTRAP_STARTED(1, "onBootstrapStarted"), ON_BOOTSTRAP_SUCCESS(2, "onBootstrapSuccess"), ON_BOOTSTRAP_FAILURE(3, "onBootstrapFailure"), @@ -70,7 +70,9 @@ public class Lwm2mTestHelper { ON_DEREGISTRATION_SUCCESS(13, "onDeregistrationSuccess"), ON_DEREGISTRATION_FAILURE(14, "onDeregistrationFailure"), ON_DEREGISTRATION_TIMEOUT(15, "onDeregistrationTimeout"), - ON_EXPECTED_ERROR(16, "onUnexpectedError"); + ON_EXPECTED_ERROR(16, "onUnexpectedError"), + ON_READ_CONNECTION_ID (17, "onReadConnection"), + ON_WRITE_CONNECTION_ID (18, "onWriteConnection"); public int code; public String type; diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/DtlsSessionLogger.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/DtlsSessionLogger.java new file mode 100644 index 0000000000..d798dbc0d4 --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/DtlsSessionLogger.java @@ -0,0 +1,81 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.transport.lwm2m.client; + +import lombok.extern.slf4j.Slf4j; +import org.eclipse.californium.scandium.dtls.ClientHandshaker; +import org.eclipse.californium.scandium.dtls.DTLSContext; +import org.eclipse.californium.scandium.dtls.HandshakeException; +import org.eclipse.californium.scandium.dtls.Handshaker; +import org.eclipse.californium.scandium.dtls.SessionAdapter; +import org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState; + +import java.util.Map; +import java.util.Set; + +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_READ_CONNECTION_ID; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_WRITE_CONNECTION_ID; + +@Slf4j +public class DtlsSessionLogger extends SessionAdapter { + + private final Set clientStates; + private final Map clientDtlsCid; + + public DtlsSessionLogger(Set clientStates, Map clientDtlsCid) { + this.clientStates = clientStates; + this.clientDtlsCid = clientDtlsCid; + } + + @Override + public void handshakeStarted(Handshaker handshaker) throws HandshakeException { + if (handshaker instanceof ClientHandshaker) { + log.info("DTLS Full Handshake initiated by client : STARTED ..."); + } + } + + @Override + public void contextEstablished(Handshaker handshaker, DTLSContext establishedContext) throws HandshakeException { + if (handshaker instanceof ClientHandshaker) { + log.warn("DTLS initiated by client: SUCCEED, WriteConnectionId: [{}], ReadConnectionId: [{}]", establishedContext.getWriteConnectionId(), establishedContext.getReadConnectionId()); + clientStates.add(ON_WRITE_CONNECTION_ID); + clientStates.add(ON_READ_CONNECTION_ID); + Integer lenWrite = establishedContext.getWriteConnectionId() == null ? null : establishedContext.getWriteConnectionId().getBytes().length; + Integer lenRead = establishedContext.getReadConnectionId() == null ? null : establishedContext.getReadConnectionId().getBytes().length; + clientDtlsCid.put(ON_WRITE_CONNECTION_ID, lenWrite); + clientDtlsCid.put(ON_READ_CONNECTION_ID, lenRead); + } + } + + @Override + public void handshakeFailed(Handshaker handshaker, Throwable error) { + // get cause + String cause; + if (error != null) { + if (error.getMessage() != null) { + cause = error.getMessage(); + } else { + cause = error.getClass().getName(); + } + } else { + cause = "unknown cause"; + } + + if (handshaker instanceof ClientHandshaker) { + log.info("DTLS Full Handshake initiated by client : FAILED ({})", cause); + } + } +} diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java index 339c28067f..c3c1f5ff33 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java @@ -18,7 +18,6 @@ package org.thingsboard.server.transport.lwm2m.client; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.eclipse.californium.elements.config.Configuration; -import org.eclipse.californium.scandium.config.DtlsConfig; import org.eclipse.californium.scandium.config.DtlsConnectorConfig; import org.eclipse.leshan.client.LeshanClient; import org.eclipse.leshan.client.LeshanClientBuilder; @@ -62,11 +61,15 @@ import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; import java.io.IOException; import java.net.InetSocketAddress; import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.concurrent.ScheduledExecutorService; +import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_CONNECTION_ID_LENGTH; +import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY; import static org.eclipse.leshan.core.LwM2mId.ACCESS_CONTROL; import static org.eclipse.leshan.core.LwM2mId.DEVICE; import static org.eclipse.leshan.core.LwM2mId.FIRMWARE; @@ -103,6 +106,7 @@ import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.OBJECT_INST import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.OBJECT_INSTANCE_ID_12; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.TEMPERATURE_SENSOR; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.resources; +import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.setDtlsConnectorConfigCidLength; @Slf4j @@ -119,12 +123,13 @@ public class LwM2MTestClient { private LwM2MLocationParams locationParams; private LwM2mTemperatureSensor lwM2MTemperatureSensor; private Set clientStates; + private Map clientDtlsCid; private LwM2mUplinkMsgHandler defaultLwM2mUplinkMsgHandlerTest; private LwM2mClientContext clientContext; public void init(Security security, Security securityBs,Configuration coapConfig, int port, boolean isRpc, LwM2mUplinkMsgHandler defaultLwM2mUplinkMsgHandler, - LwM2mClientContext clientContext, boolean isWriteAttribute) throws InvalidDDFFileException, IOException { + LwM2mClientContext clientContext, boolean isWriteAttribute, Integer cIdLength) throws InvalidDDFFileException, IOException { Assert.assertNull("client already initialized", leshanClient); this.defaultLwM2mUplinkMsgHandlerTest = defaultLwM2mUplinkMsgHandler; this.clientContext = clientContext; @@ -188,6 +193,10 @@ public class LwM2MTestClient { protected DtlsConnectorConfig.Builder createRootDtlsConnectorConfigBuilder( Configuration configuration) { DtlsConnectorConfig.Builder builder = super.createRootDtlsConnectorConfigBuilder(configuration); + + // Add DTLS Session lifecycle logger + builder.setSessionListener(new DtlsSessionLogger(clientStates, clientDtlsCid)); + return builder; }; }; @@ -213,20 +222,18 @@ public class LwM2MTestClient { // Set some DTLS stuff // These configuration values are always overwritten by CLI therefore set them to transient. - clientCoapConfig.setTransient(DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY); - clientCoapConfig.setTransient(DtlsConfig.DTLS_CONNECTION_ID_LENGTH); + clientCoapConfig.setTransient(DTLS_RECOMMENDED_CIPHER_SUITES_ONLY); + clientCoapConfig.setTransient(DTLS_CONNECTION_ID_LENGTH); boolean supportDeprecatedCiphers = false; - clientCoapConfig.set(DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY, !supportDeprecatedCiphers); - /** - * "Control usage of DTLS connection ID.", // - * "- 'on' to activate Connection ID support (same as -cid 0)", // - * "- 'off' to deactivate it", // - * "- Positive value define the size in byte of CID generated.", // - * "- 0 value means we accept to use CID but will not generated one for foreign peer.", // - * "Default: off" - */ - Integer cid = null; - clientCoapConfig.set(DtlsConfig.DTLS_CONNECTION_ID_LENGTH, cid); + clientCoapConfig.set(DTLS_RECOMMENDED_CIPHER_SUITES_ONLY, !supportDeprecatedCiphers); + + if (cIdLength!= null) { + setDtlsConnectorConfigCidLength(clientCoapConfig, cIdLength); + } + + if (cIdLength!= null) { + setDtlsConnectorConfigCidLength(clientCoapConfig, cIdLength); + } // Set Californium Configuration endpointsBuilder.setConfiguration(clientCoapConfig); @@ -279,6 +286,7 @@ public class LwM2MTestClient { builder.setSharedExecutor(executor); clientStates = new HashSet<>(); + clientDtlsCid = new HashMap<>(); clientStates.add(ON_INIT); leshanClient = builder.build(); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java index 7e812f9846..17518e2ba3 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java @@ -59,7 +59,7 @@ public class OtaLwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { createDeviceProfile(transportConfiguration); LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_WITHOUT_FW_INFO)); final Device device = createDevice(deviceCredentials, this.CLIENT_ENDPOINT_WITHOUT_FW_INFO); - createNewClient(SECURITY_NO_SEC, null, COAP_CONFIG, false, this.CLIENT_ENDPOINT_WITHOUT_FW_INFO); + createNewClient(SECURITY_NO_SEC, null, COAP_CONFIG, false, this.CLIENT_ENDPOINT_WITHOUT_FW_INFO, null); awaitObserveReadAll(0, device.getId().getId().toString()); device.setFirmwareId(createFirmware().getId()); @@ -84,7 +84,7 @@ public class OtaLwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { createDeviceProfile(transportConfiguration); LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_OTA5)); final Device device = createDevice(deviceCredentials, this.CLIENT_ENDPOINT_OTA5); - createNewClient(SECURITY_NO_SEC, null, COAP_CONFIG, false, this.CLIENT_ENDPOINT_OTA5); + createNewClient(SECURITY_NO_SEC, null, COAP_CONFIG, false, this.CLIENT_ENDPOINT_OTA5, null); awaitObserveReadAll(9, device.getId().getId().toString()); device.setFirmwareId(createFirmware().getId()); @@ -114,7 +114,7 @@ public class OtaLwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { createDeviceProfile(transportConfiguration); LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_OTA9)); final Device device = createDevice(deviceCredentials, this.CLIENT_ENDPOINT_OTA9); - createNewClient(SECURITY_NO_SEC, null, COAP_CONFIG, false, this.CLIENT_ENDPOINT_OTA9); + createNewClient(SECURITY_NO_SEC, null, COAP_CONFIG, false, this.CLIENT_ENDPOINT_OTA9, null); awaitObserveReadAll(9, device.getId().getId().toString()); device.setSoftwareId(createSoftware().getId()); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java index 1c83bed8eb..3c5d536dcd 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java @@ -91,7 +91,7 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg private void initRpc () throws Exception { String endpoint = DEVICE_ENDPOINT_RPC_PREF + endpointSequence.incrementAndGet(); - createNewClient(SECURITY_NO_SEC, null, COAP_CONFIG, true, endpoint); + createNewClient(SECURITY_NO_SEC, null, COAP_CONFIG, true, endpoint, null); expectedObjects = ConcurrentHashMap.newKeySet(); expectedObjectIdVers = ConcurrentHashMap.newKeySet(); expectedInstances = ConcurrentHashMap.newKeySet(); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java index f164cb7fe7..b360918a9f 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java @@ -196,7 +196,7 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M boolean isStartLw) throws Exception { createDeviceProfile(transportConfiguration); final Device device = createDevice(deviceCredentials, endpoint); - createNewClient(security, securityBs, coapConfig, true, endpoint); + createNewClient(security, securityBs, coapConfig, true, endpoint, null); lwM2MTestClient.start(isStartLw); if (isAwaitObserveReadAll) { awaitObserveReadAll(0, device.getId().getId().toString()); @@ -244,7 +244,7 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M createDeviceProfile(transportConfiguration); final Device device = createDevice(deviceCredentials, endpoint); String deviceIdStr = device.getId().getId().toString(); - createNewClient(security, securityBs, coapConfig, true, endpoint); + createNewClient(security, securityBs, coapConfig, true, endpoint, null); lwM2MTestClient.start(true); awaitObserveReadAll(0, deviceIdStr); await(awaitAlias) diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLength0Test.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLength0Test.java new file mode 100644 index 0000000000..126dc39197 --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLength0Test.java @@ -0,0 +1,38 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.transport.lwm2m.security.cid; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.test.context.TestPropertySource; +import org.thingsboard.server.dao.service.DaoSqlTest; + + +@TestPropertySource(properties = { + "transport.lwm2m.dtls.connection_id_length=0" +}) + +@DaoSqlTest +@Slf4j +public abstract class AbstractSecurityLwM2MIntegrationDtlsCidLength0Test extends AbstractSecurityLwM2MIntegrationDtlsCidLengthTest { + + + protected void testNoSecDtlsCidLength(Integer dtlsCidLength) throws Exception { + testNoSecDtlsCidLength(dtlsCidLength, 0); + } + protected void testPskDtlsCidLength(Integer dtlsCidLength) throws Exception { + testPskDtlsCidLength(dtlsCidLength, 0); + } +} diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLength3Test.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLength3Test.java new file mode 100644 index 0000000000..d3f6605e11 --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLength3Test.java @@ -0,0 +1,37 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.transport.lwm2m.security.cid; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.test.context.TestPropertySource; +import org.thingsboard.server.dao.service.DaoSqlTest; + + +@TestPropertySource(properties = { + "transport.lwm2m.dtls.connection_id_length=3" +}) + +@DaoSqlTest +@Slf4j +public abstract class AbstractSecurityLwM2MIntegrationDtlsCidLength3Test extends AbstractSecurityLwM2MIntegrationDtlsCidLengthTest { + + protected void testNoSecDtlsCidLength(Integer dtlsCidLength) throws Exception { + testNoSecDtlsCidLength(dtlsCidLength, 3); + } + protected void testPskDtlsCidLength(Integer dtlsCidLength) throws Exception { + testPskDtlsCidLength(dtlsCidLength, 3); + } +} diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLengthNullTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLengthNullTest.java new file mode 100644 index 0000000000..1a63159352 --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLengthNullTest.java @@ -0,0 +1,38 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.transport.lwm2m.security.cid; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.test.context.TestPropertySource; +import org.thingsboard.server.dao.service.DaoSqlTest; + + +@TestPropertySource(properties = { + "transport.lwm2m.dtls.connection_id_length=" +}) + +@DaoSqlTest +@Slf4j +public abstract class AbstractSecurityLwM2MIntegrationDtlsCidLengthNullTest extends AbstractSecurityLwM2MIntegrationDtlsCidLengthTest { + + + protected void testNoSecDtlsCidLength(Integer dtlsCidLength) throws Exception { + testNoSecDtlsCidLength(dtlsCidLength, null); + } + protected void testPskDtlsCidLength(Integer dtlsCidLength) throws Exception { + testPskDtlsCidLength(dtlsCidLength, null); + } +} diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLengthTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLengthTest.java new file mode 100644 index 0000000000..c743308fcd --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLengthTest.java @@ -0,0 +1,133 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.transport.lwm2m.security.cid; + +import lombok.extern.slf4j.Slf4j; +import org.eclipse.californium.elements.config.Configuration; +import org.eclipse.leshan.client.californium.endpoint.CaliforniumClientEndpoint; +import org.eclipse.leshan.client.californium.endpoint.CaliforniumClientEndpointsProvider; +import org.eclipse.leshan.client.object.Security; +import org.eclipse.leshan.core.util.Hex; +import org.junit.Assert; +import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.common.data.device.credentials.lwm2m.AbstractLwM2MClientSecurityCredential; +import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MDeviceCredentials; +import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode; +import org.thingsboard.server.common.data.device.credentials.lwm2m.PSKClientCredential; +import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; +import org.thingsboard.server.dao.service.DaoSqlTest; +import org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState; +import org.thingsboard.server.transport.lwm2m.security.AbstractSecurityLwM2MIntegrationTest; + +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Random; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import static org.awaitility.Awaitility.await; +import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_CONNECTION_ID_LENGTH; +import static org.eclipse.leshan.client.object.Security.psk; +import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.PSK; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_INIT; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_READ_CONNECTION_ID; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_STARTED; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_SUCCESS; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_UPDATE_SUCCESS; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_WRITE_CONNECTION_ID; + +@DaoSqlTest +@Slf4j +public abstract class AbstractSecurityLwM2MIntegrationDtlsCidLengthTest extends AbstractSecurityLwM2MIntegrationTest { + + protected AbstractLwM2MClientSecurityCredential clientCredentials; + protected Security security; + protected Lwm2mDeviceProfileTransportConfiguration transportConfiguration; + protected LwM2MDeviceCredentials deviceCredentials; + protected String clientEndpoint; + protected LwM2MSecurityMode lwM2MSecurityMode; + protected String awaitAlias; + protected final Random randomSuffix = new Random(); + + protected final Set expectedStatusesRegistrationLwm2mDtlsCidSuccess = new HashSet<>(Arrays.asList(ON_INIT, ON_REGISTRATION_STARTED, ON_REGISTRATION_SUCCESS, ON_READ_CONNECTION_ID, ON_WRITE_CONNECTION_ID)); + + + protected void testNoSecDtlsCidLength(Integer dtlsCidLength, Integer serverDtlsCidLength) throws Exception { + initDeviceCredentialsNoSek(); + basicTestConnectionDtlsCidLength(dtlsCidLength, serverDtlsCidLength); + } + protected void testPskDtlsCidLength(Integer dtlsCidLength, Integer serverDtlsCidLength) throws Exception { + initDeviceCredentialsPsk(); + basicTestConnectionDtlsCidLength(dtlsCidLength, serverDtlsCidLength); + } + + protected void initDeviceCredentialsNoSek() { + clientEndpoint = CLIENT_ENDPOINT_NO_SEC + "_" + randomSuffix.nextInt(100); + deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(clientEndpoint)); + } + + protected void initDeviceCredentialsPsk() { + int suf = randomSuffix.nextInt(10); + clientEndpoint = CLIENT_ENDPOINT_PSK + "_" + suf; + String identity = CLIENT_PSK_IDENTITY + "_" + suf; + clientCredentials = new PSKClientCredential(); + clientCredentials.setEndpoint(clientEndpoint); + ((PSKClientCredential)clientCredentials).setIdentity(identity); + clientCredentials.setKey(CLIENT_PSK_KEY); + security = psk(SECURE_URI, + shortServerId, + identity.getBytes(StandardCharsets.UTF_8), + Hex.decodeHex(CLIENT_PSK_KEY.toCharArray())); + deviceCredentials = getDeviceCredentialsSecure(clientCredentials, null, null, PSK, false); + } + + protected void basicTestConnectionDtlsCidLength(Integer clientDtlsCidLength, + Integer serverDtlsCidLength) throws Exception { + createDeviceProfile(transportConfiguration); + final Device device = createDevice(deviceCredentials, clientEndpoint); + device.getId().getId().toString(); + createNewClient(security, null, COAP_CONFIG, true, clientEndpoint, clientDtlsCidLength); + lwM2MTestClient.start(true); + await(awaitAlias) + .atMost(40, TimeUnit.SECONDS) + .until(() -> lwM2MTestClient.getClientStates().contains(ON_UPDATE_SUCCESS)); + Assert.assertTrue(lwM2MTestClient.getClientStates().containsAll(expectedStatusesRegistrationLwm2mSuccess)); + + Configuration clientCoapConfig = ((CaliforniumClientEndpoint)((CaliforniumClientEndpointsProvider)lwM2MTestClient + .getLeshanClient().getEndpointsProvider().toArray()[0]).getEndpoints().toArray()[0]).getCoapEndpoint().getConfig(); + Assert.assertEquals(clientDtlsCidLength, clientCoapConfig.get(DTLS_CONNECTION_ID_LENGTH)); + + if (security.equals(SECURITY_NO_SEC)) { + Assert.assertTrue(lwM2MTestClient.getClientDtlsCid().isEmpty()); + } else { + Assert.assertEquals(2L, lwM2MTestClient.getClientDtlsCid().size()); + Assert.assertTrue(lwM2MTestClient.getClientDtlsCid().keySet().contains(ON_READ_CONNECTION_ID)); + Assert.assertTrue(lwM2MTestClient.getClientDtlsCid().keySet().contains(ON_WRITE_CONNECTION_ID)); + if (serverDtlsCidLength == null) { + Assert.assertNull(lwM2MTestClient.getClientDtlsCid().get(ON_WRITE_CONNECTION_ID)); + Assert.assertNull(lwM2MTestClient.getClientDtlsCid().get(ON_READ_CONNECTION_ID)); + } else { + Assert.assertEquals(clientDtlsCidLength, lwM2MTestClient.getClientDtlsCid().get(ON_READ_CONNECTION_ID)); + if (clientDtlsCidLength == null) { + Assert.assertNull(lwM2MTestClient.getClientDtlsCid().get(ON_READ_CONNECTION_ID)); + } else { + Assert.assertEquals(Integer.valueOf(serverDtlsCidLength), lwM2MTestClient.getClientDtlsCid().get(ON_WRITE_CONNECTION_ID)); + } + } + } + } +} diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_0/NoSecLwM2MIntegrationDtlsCidLengthTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_0/NoSecLwM2MIntegrationDtlsCidLengthTest.java new file mode 100644 index 0000000000..f43ae3af0c --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_0/NoSecLwM2MIntegrationDtlsCidLengthTest.java @@ -0,0 +1,48 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.transport.lwm2m.security.cid.serverDtlsCidLength_0; + +import org.junit.Before; +import org.junit.Test; +import org.thingsboard.server.transport.lwm2m.security.cid.AbstractSecurityLwM2MIntegrationDtlsCidLength0Test; + +import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.NO_SEC; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; + +public class NoSecLwM2MIntegrationDtlsCidLengthTest extends AbstractSecurityLwM2MIntegrationDtlsCidLength0Test { + + @Before + public void setUpNoSecDtlsCidLength() { + security = SECURITY_NO_SEC; + transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(NO_SEC, NONE)); + awaitAlias = "await on client state (NoSec_Lwm2m) DtlsCidLength = 0"; + } + + @Test + public void testWithNoSecConnectLwm2mSuccessClientDtlsCidLength_Null() throws Exception { + testNoSecDtlsCidLength(null); + } + + @Test + public void testWithNoSecConnectLwm2mSuccessClientDtlsCidLength_0() throws Exception { + testNoSecDtlsCidLength(0); + } + + @Test + public void testWithNoSecConnectLwm2mSuccessClientDtlsCidLength_2() throws Exception { + testNoSecDtlsCidLength(2); + } +} diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_0/PskLwm2mIntegrationDtlsCidLengthTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_0/PskLwm2mIntegrationDtlsCidLengthTest.java new file mode 100644 index 0000000000..38010111fa --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_0/PskLwm2mIntegrationDtlsCidLengthTest.java @@ -0,0 +1,46 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.transport.lwm2m.security.cid.serverDtlsCidLength_0; + +import org.junit.Before; +import org.junit.Test; +import org.thingsboard.server.transport.lwm2m.security.cid.AbstractSecurityLwM2MIntegrationDtlsCidLength0Test; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; + +public class PskLwm2mIntegrationDtlsCidLengthTest extends AbstractSecurityLwM2MIntegrationDtlsCidLength0Test { + + @Before + public void createProfileRpc() { + transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(lwM2MSecurityMode, NONE)); + awaitAlias = "await on client state (Psk_Lwm2m) DtlsCidLength = 0"; + } + + @Test + public void testWithPskConnectLwm2mSuccessClientDtlsCidLength_Null() throws Exception { + testPskDtlsCidLength(null); + } + + @Test + public void testWithPskConnectLwm2mSuccessClientDtlsCidLength_0() throws Exception { + testPskDtlsCidLength(0); + } + + @Test + public void testWithPskConnectLwm2mSuccessClientDtlsCidLength_2() throws Exception { + testPskDtlsCidLength(2); + } +} + diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_3/NoSecLwM2MIntegrationDtlsCidLengthTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_3/NoSecLwM2MIntegrationDtlsCidLengthTest.java new file mode 100644 index 0000000000..377ccf420a --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_3/NoSecLwM2MIntegrationDtlsCidLengthTest.java @@ -0,0 +1,48 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.transport.lwm2m.security.cid.serverDtlsCidLength_3; + +import org.junit.Before; +import org.junit.Test; +import org.thingsboard.server.transport.lwm2m.security.cid.AbstractSecurityLwM2MIntegrationDtlsCidLength3Test; + +import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.NO_SEC; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; + +public class NoSecLwM2MIntegrationDtlsCidLengthTest extends AbstractSecurityLwM2MIntegrationDtlsCidLength3Test { + + @Before + public void setUpNoSecDtlsCidLength() { + security = SECURITY_NO_SEC; + transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(NO_SEC, NONE)); + awaitAlias = "await on client state (NoSec_Lwm2m) DtlsCidLength = 3"; + } + + @Test + public void testWithNoSecConnectLwm2mSuccessClientDtlsCidLength_Null() throws Exception { + testNoSecDtlsCidLength(null); + } + + @Test + public void testWithNoSecConnectLwm2mSuccessClientDtlsCidLength_0() throws Exception { + testNoSecDtlsCidLength(0); + } + + @Test + public void testWithNoSecConnectLwm2mSuccessClientDtlsCidLength_2() throws Exception { + testNoSecDtlsCidLength(2); + } +} diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_3/PskLwm2mIntegrationDtlsCidLengthTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_3/PskLwm2mIntegrationDtlsCidLengthTest.java new file mode 100644 index 0000000000..afe436cdbc --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_3/PskLwm2mIntegrationDtlsCidLengthTest.java @@ -0,0 +1,47 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.transport.lwm2m.security.cid.serverDtlsCidLength_3; + +import org.junit.Before; +import org.junit.Test; +import org.thingsboard.server.transport.lwm2m.security.cid.AbstractSecurityLwM2MIntegrationDtlsCidLength3Test; + +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; + +public class PskLwm2mIntegrationDtlsCidLengthTest extends AbstractSecurityLwM2MIntegrationDtlsCidLength3Test { + + @Before + public void createProfileRpc() { + transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(lwM2MSecurityMode, NONE)); + awaitAlias = "await on client state (Psk_Lwm2m) DtlsCidLength = 3"; + } + + @Test + public void testWithPskConnectLwm2mSuccessClientDtlsCidLength_Null() throws Exception { + testPskDtlsCidLength(null); + } + + @Test + public void testWithPskConnectLwm2mSuccessClientDtlsCidLength_0() throws Exception { + testPskDtlsCidLength(0); + } + + @Test + public void testWithPskConnectLwm2mSuccessClientDtlsCidLength_2() throws Exception { + testPskDtlsCidLength(2); + } +} + diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_null/NoSecLwM2MIntegrationDtlsCidLengthTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_null/NoSecLwM2MIntegrationDtlsCidLengthTest.java new file mode 100644 index 0000000000..d5531f6354 --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_null/NoSecLwM2MIntegrationDtlsCidLengthTest.java @@ -0,0 +1,48 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.transport.lwm2m.security.cid.serverDtlsCidLength_null; + +import org.junit.Before; +import org.junit.Test; +import org.thingsboard.server.transport.lwm2m.security.cid.AbstractSecurityLwM2MIntegrationDtlsCidLengthNullTest; + +import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.NO_SEC; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; + +public class NoSecLwM2MIntegrationDtlsCidLengthTest extends AbstractSecurityLwM2MIntegrationDtlsCidLengthNullTest { + + @Before + public void setUpNoSecDtlsCidLength() { + security = SECURITY_NO_SEC; + transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(NO_SEC, NONE)); + awaitAlias = "await on client state (NoSec_Lwm2m) DtlsCidLength = Null"; + } + + @Test + public void testWithNoSecConnectLwm2mSuccessClientDtlsCidLength_Null() throws Exception { + testNoSecDtlsCidLength(null); + } + + @Test + public void testWithNoSecConnectLwm2mSuccessClientDtlsCidLength_0() throws Exception { + testNoSecDtlsCidLength(0); + } + + @Test + public void testWithNoSecConnectLwm2mSuccessClientDtlsCidLength_2() throws Exception { + testNoSecDtlsCidLength(2); + } +} diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_null/PskLwm2mIntegrationDtlsCidLengthTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_null/PskLwm2mIntegrationDtlsCidLengthTest.java new file mode 100644 index 0000000000..5c712f78d6 --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_null/PskLwm2mIntegrationDtlsCidLengthTest.java @@ -0,0 +1,47 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.transport.lwm2m.security.cid.serverDtlsCidLength_null; + +import org.junit.Before; +import org.junit.Test; +import org.thingsboard.server.transport.lwm2m.security.cid.AbstractSecurityLwM2MIntegrationDtlsCidLengthNullTest; + +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; + +public class PskLwm2mIntegrationDtlsCidLengthTest extends AbstractSecurityLwM2MIntegrationDtlsCidLengthNullTest { + + @Before + public void createProfileRpc() { + transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(lwM2MSecurityMode, NONE)); + awaitAlias = "await on client state (Psk_Lwm2m) DtlsCidLength = Null"; + } + + @Test + public void testWithPskConnectLwm2mSuccessClientDtlsCidLength_Null() throws Exception { + testPskDtlsCidLength(null); + } + + @Test + public void testWithPskConnectLwm2mSuccessClientDtlsCidLength_0() throws Exception { + testPskDtlsCidLength(0); + } + + @Test + public void testWithPskConnectLwm2mSuccessClientDtlsCidLength_2() throws Exception { + testPskDtlsCidLength(2); + } +} + diff --git a/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsSettings.java b/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsSettings.java index e9296f70c5..f27131b7ab 100644 --- a/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsSettings.java +++ b/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsSettings.java @@ -41,6 +41,8 @@ import java.util.Collections; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static org.eclipse.californium.elements.config.CertificateAuthenticationMode.WANTED; import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_CLIENT_AUTHENTICATION_MODE; +import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_CONNECTION_ID_LENGTH; +import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_CONNECTION_ID_NODE_ID; import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RETRANSMISSION_TIMEOUT; import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_ROLE; import static org.eclipse.californium.scandium.config.DtlsConfig.DtlsRole.SERVER_ONLY; @@ -59,6 +61,9 @@ public class TbCoapDtlsSettings { @Value("${transport.coap.dtls.retransmission_timeout:9000}") private int dtlsRetransmissionTimeout; + @Value("${transport.coap.dtls.connection_id_length}") + private Integer cIdLength; + @Bean @ConfigurationProperties(prefix = "transport.coap.dtls.credentials") public SslCredentialsConfig coapDtlsCredentials() { @@ -93,6 +98,14 @@ public class TbCoapDtlsSettings { configBuilder.set(DTLS_CLIENT_AUTHENTICATION_MODE, WANTED); configBuilder.set(DTLS_RETRANSMISSION_TIMEOUT, dtlsRetransmissionTimeout, MILLISECONDS); configBuilder.set(DTLS_ROLE, SERVER_ONLY); + configBuilder.set(DTLS_CONNECTION_ID_LENGTH, cIdLength); + if (cIdLength != null) { + if (cIdLength > 4) { + configBuilder.set(DTLS_CONNECTION_ID_NODE_ID, 0); + } else { + configBuilder.set(DTLS_CONNECTION_ID_NODE_ID, null); + } + } configBuilder.setAdvancedCertificateVerifier( new TbCoapDtlsCertificateVerifier( transportService, diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java index d6839ae394..c8e8baa30a 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java @@ -49,6 +49,7 @@ import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RETRANSMIS import static org.thingsboard.server.transport.lwm2m.server.DefaultLwM2mTransportService.PSK_CIPHER_SUITES; import static org.thingsboard.server.transport.lwm2m.server.DefaultLwM2mTransportService.RPK_OR_X509_CIPHER_SUITES; import static org.thingsboard.server.transport.lwm2m.server.LwM2MNetworkConfig.getCoapConfig; +import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.setDtlsConnectorConfigCidLength; @Slf4j @Component @@ -113,15 +114,15 @@ public class LwM2MTransportBootstrapService { serverCoapConfig.setTransient(DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY); serverCoapConfig.set(DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY, serverConfig.isRecommendedCiphers()); serverCoapConfig.setTransient(DtlsConfig.DTLS_CONNECTION_ID_LENGTH); - serverCoapConfig.set(DtlsConfig.DTLS_CONNECTION_ID_LENGTH, 6); serverCoapConfig.set(DTLS_RECOMMENDED_CURVES_ONLY, serverConfig.isRecommendedSupportedGroups()); serverCoapConfig.setTransient(DTLS_RETRANSMISSION_TIMEOUT); serverCoapConfig.set(DTLS_RETRANSMISSION_TIMEOUT, serverConfig.getDtlsRetransmissionTimeout(), MILLISECONDS); - + if (serverConfig.getDtlsCidLength() != null) { + setDtlsConnectorConfigCidLength( serverCoapConfig, serverConfig.getDtlsCidLength()); + } /* Create DTLS Config */ - this.setServerWithCredentials(builder); // Set Californium Configuration diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfig.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfig.java index 4b9ea2e4ac..03c4730313 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfig.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfig.java @@ -42,6 +42,10 @@ public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig { @Value("${transport.lwm2m.dtls.retransmission_timeout:9000}") private int dtlsRetransmissionTimeout; + @Getter + @Value("${transport.lwm2m.dtls.connection_id_length:}") + private Integer dtlsCidLength; + @Getter @Value("${transport.lwm2m.timeout:}") private Long timeout; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java index 27bf6251a9..4bf9859b16 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java @@ -58,6 +58,7 @@ import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_W import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CCM_8; import static org.thingsboard.server.transport.lwm2m.server.LwM2MNetworkConfig.getCoapConfig; import static org.thingsboard.server.transport.lwm2m.server.ota.DefaultLwM2MOtaUpdateService.FIRMWARE_UPDATE_COAP_RESOURCE; +import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.setDtlsConnectorConfigCidLength; @Slf4j @Component @@ -165,21 +166,10 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService { serverCoapConfig.set(DTLS_RETRANSMISSION_TIMEOUT, config.getDtlsRetransmissionTimeout(), MILLISECONDS); serverCoapConfig.set(DTLS_ROLE, SERVER_ONLY); serverCoapConfig.setTransient(DtlsConfig.DTLS_CONNECTION_ID_LENGTH); - /** - * "Control usage of DTLS connection ID.", - * If DTLS_CONNECTION_ID_LENGTH enables the use of a connection id, this node id could be used - * to configure the generation of connection ids specific for node in a multi-node deployment (cluster). - * The value is used as first byte in generated connection ids. - * DTLS connection ID length. disabled, - * 0 enables support without active use of CID.", defaultValue == null, minimumValue == 0); - * "- 'on' to activate Connection ID support ", - * " (same as -cid 6)", - * "- 'off' to deactivate it", - * "- Positive value define the size in byte of CID generated.", - * "- 0 value means we accept to use CID but will not generated one for foreign peer.", - */ - serverCoapConfig.set(DtlsConfig.DTLS_CONNECTION_ID_LENGTH, 6); + if (config.getDtlsCidLength() != null) { + setDtlsConnectorConfigCidLength( serverCoapConfig, config.getDtlsCidLength()); + } /* Create DTLS Config */ this.setServerWithCredentials(builder); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2MTransportUtil.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2MTransportUtil.java index b74a668b6a..db8398cd57 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2MTransportUtil.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2MTransportUtil.java @@ -17,6 +17,7 @@ package org.thingsboard.server.transport.lwm2m.utils; import com.google.gson.JsonElement; import lombok.extern.slf4j.Slf4j; +import org.eclipse.californium.elements.config.Configuration; import org.eclipse.leshan.core.model.LwM2mModel; import org.eclipse.leshan.core.model.ObjectLoader; import org.eclipse.leshan.core.model.ObjectModel; @@ -55,6 +56,8 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_CONNECTION_ID_LENGTH; +import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_CONNECTION_ID_NODE_ID; import static org.eclipse.leshan.core.model.ResourceModel.Type.BOOLEAN; import static org.eclipse.leshan.core.model.ResourceModel.Type.FLOAT; import static org.eclipse.leshan.core.model.ResourceModel.Type.INTEGER; @@ -425,4 +428,15 @@ public class LwM2MTransportUtil { } return newValueStr.equals(oldValueStr); } + + public static void setDtlsConnectorConfigCidLength(Configuration serverCoapConfig, Integer cIdLength) { + serverCoapConfig.setTransient(DTLS_CONNECTION_ID_LENGTH); + serverCoapConfig.setTransient(DTLS_CONNECTION_ID_NODE_ID); + serverCoapConfig.set(DTLS_CONNECTION_ID_LENGTH, cIdLength); + if ( cIdLength > 4) { + serverCoapConfig.set(DTLS_CONNECTION_ID_NODE_ID, 0); + } else { + serverCoapConfig.set(DTLS_CONNECTION_ID_NODE_ID, null); + } + } }