lwm2m_coap: DTLS Cid Length

This commit is contained in:
nick 2024-02-12 13:31:38 +02:00
parent 9fa36c7a2d
commit c2268595eb
23 changed files with 707 additions and 43 deletions

View File

@ -1019,6 +1019,16 @@ transport:
# CoAP DTLS bind port # CoAP DTLS bind port
bind_port: "${COAP_DTLS_BIND_PORT:5684}" bind_port: "${COAP_DTLS_BIND_PORT:5684}"
# Server DTLS credentials # 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: credentials:
# Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore) # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore)
type: "${COAP_DTLS_CREDENTIALS_TYPE:PEM}" type: "${COAP_DTLS_CREDENTIALS_TYPE:PEM}"
@ -1056,6 +1066,16 @@ transport:
dtls: dtls:
# RFC7925_RETRANSMISSION_TIMEOUT_IN_MILLISECONDS = 9000 # RFC7925_RETRANSMISSION_TIMEOUT_IN_MILLISECONDS = 9000
retransmission_timeout: "${LWM2M_DTLS_RETRANSMISSION_TIMEOUT_MS: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: server:
# LwM2M Server ID # LwM2M Server ID
id: "${LWM2M_SERVER_ID:123}" id: "${LWM2M_SERVER_ID:123}"

View File

@ -236,7 +236,7 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte
getWsClient().waitForReply(); getWsClient().waitForReply();
getWsClient().registerWaitForUpdate(); getWsClient().registerWaitForUpdate();
createNewClient(security, null, coapConfig, false, endpoint); createNewClient(security, null, coapConfig, false, endpoint, null);
deviceId = device.getId().getId().toString(); deviceId = device.getId().getId().toString();
awaitObserveReadAll(0, deviceId); awaitObserveReadAll(0, deviceId);
String msg = getWsClient().waitForUpdate(); String msg = getWsClient().waitForUpdate();
@ -304,14 +304,15 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte
this.resources = resources; 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(); this.clientDestroy();
lwM2MTestClient = new LwM2MTestClient(this.executor, endpoint); lwM2MTestClient = new LwM2MTestClient(this.executor, endpoint);
try (ServerSocket socket = new ServerSocket(0)) { try (ServerSocket socket = new ServerSocket(0)) {
int clientPort = socket.getLocalPort(); int clientPort = socket.getLocalPort();
lwM2MTestClient.init(security, securityBs, coapConfig, clientPort, isRpc, lwM2MTestClient.init(security, securityBs, coapConfig, clientPort, isRpc,
this.defaultLwM2mUplinkMsgHandlerTest, this.clientContextTest, isWriteAttribute); this.defaultLwM2mUplinkMsgHandlerTest, this.clientContextTest, isWriteAttribute, clientDtlsCidLength);
} }
} }

View File

@ -53,7 +53,7 @@ public class Lwm2mTestHelper {
public enum LwM2MClientState { public enum LwM2MClientState {
ON_INIT(1, "onInit"), ON_INIT(0, "onInit"),
ON_BOOTSTRAP_STARTED(1, "onBootstrapStarted"), ON_BOOTSTRAP_STARTED(1, "onBootstrapStarted"),
ON_BOOTSTRAP_SUCCESS(2, "onBootstrapSuccess"), ON_BOOTSTRAP_SUCCESS(2, "onBootstrapSuccess"),
ON_BOOTSTRAP_FAILURE(3, "onBootstrapFailure"), ON_BOOTSTRAP_FAILURE(3, "onBootstrapFailure"),
@ -70,7 +70,9 @@ public class Lwm2mTestHelper {
ON_DEREGISTRATION_SUCCESS(13, "onDeregistrationSuccess"), ON_DEREGISTRATION_SUCCESS(13, "onDeregistrationSuccess"),
ON_DEREGISTRATION_FAILURE(14, "onDeregistrationFailure"), ON_DEREGISTRATION_FAILURE(14, "onDeregistrationFailure"),
ON_DEREGISTRATION_TIMEOUT(15, "onDeregistrationTimeout"), 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 int code;
public String type; public String type;

View File

@ -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<LwM2MClientState> clientStates;
private final Map<LwM2MClientState, Integer> clientDtlsCid;
public DtlsSessionLogger(Set<LwM2MClientState> clientStates, Map<LwM2MClientState, Integer> 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);
}
}
}

View File

@ -18,7 +18,6 @@ package org.thingsboard.server.transport.lwm2m.client;
import lombok.Data; import lombok.Data;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.eclipse.californium.elements.config.Configuration; import org.eclipse.californium.elements.config.Configuration;
import org.eclipse.californium.scandium.config.DtlsConfig;
import org.eclipse.californium.scandium.config.DtlsConnectorConfig; import org.eclipse.californium.scandium.config.DtlsConnectorConfig;
import org.eclipse.leshan.client.LeshanClient; import org.eclipse.leshan.client.LeshanClient;
import org.eclipse.leshan.client.LeshanClientBuilder; import org.eclipse.leshan.client.LeshanClientBuilder;
@ -62,11 +61,15 @@ import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl;
import java.io.IOException; import java.io.IOException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ScheduledExecutorService; 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.ACCESS_CONTROL;
import static org.eclipse.leshan.core.LwM2mId.DEVICE; import static org.eclipse.leshan.core.LwM2mId.DEVICE;
import static org.eclipse.leshan.core.LwM2mId.FIRMWARE; 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.OBJECT_INSTANCE_ID_12;
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.TEMPERATURE_SENSOR; 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.Lwm2mTestHelper.resources;
import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.setDtlsConnectorConfigCidLength;
@Slf4j @Slf4j
@ -119,12 +123,13 @@ public class LwM2MTestClient {
private LwM2MLocationParams locationParams; private LwM2MLocationParams locationParams;
private LwM2mTemperatureSensor lwM2MTemperatureSensor; private LwM2mTemperatureSensor lwM2MTemperatureSensor;
private Set<LwM2MClientState> clientStates; private Set<LwM2MClientState> clientStates;
private Map<LwM2MClientState, Integer> clientDtlsCid;
private LwM2mUplinkMsgHandler defaultLwM2mUplinkMsgHandlerTest; private LwM2mUplinkMsgHandler defaultLwM2mUplinkMsgHandlerTest;
private LwM2mClientContext clientContext; private LwM2mClientContext clientContext;
public void init(Security security, Security securityBs,Configuration coapConfig, int port, boolean isRpc, public void init(Security security, Security securityBs,Configuration coapConfig, int port, boolean isRpc,
LwM2mUplinkMsgHandler defaultLwM2mUplinkMsgHandler, LwM2mUplinkMsgHandler defaultLwM2mUplinkMsgHandler,
LwM2mClientContext clientContext, boolean isWriteAttribute) throws InvalidDDFFileException, IOException { LwM2mClientContext clientContext, boolean isWriteAttribute, Integer cIdLength) throws InvalidDDFFileException, IOException {
Assert.assertNull("client already initialized", leshanClient); Assert.assertNull("client already initialized", leshanClient);
this.defaultLwM2mUplinkMsgHandlerTest = defaultLwM2mUplinkMsgHandler; this.defaultLwM2mUplinkMsgHandlerTest = defaultLwM2mUplinkMsgHandler;
this.clientContext = clientContext; this.clientContext = clientContext;
@ -188,6 +193,10 @@ public class LwM2MTestClient {
protected DtlsConnectorConfig.Builder createRootDtlsConnectorConfigBuilder( protected DtlsConnectorConfig.Builder createRootDtlsConnectorConfigBuilder(
Configuration configuration) { Configuration configuration) {
DtlsConnectorConfig.Builder builder = super.createRootDtlsConnectorConfigBuilder(configuration); DtlsConnectorConfig.Builder builder = super.createRootDtlsConnectorConfigBuilder(configuration);
// Add DTLS Session lifecycle logger
builder.setSessionListener(new DtlsSessionLogger(clientStates, clientDtlsCid));
return builder; return builder;
}; };
}; };
@ -213,20 +222,18 @@ public class LwM2MTestClient {
// Set some DTLS stuff // Set some DTLS stuff
// These configuration values are always overwritten by CLI therefore set them to transient. // These configuration values are always overwritten by CLI therefore set them to transient.
clientCoapConfig.setTransient(DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY); clientCoapConfig.setTransient(DTLS_RECOMMENDED_CIPHER_SUITES_ONLY);
clientCoapConfig.setTransient(DtlsConfig.DTLS_CONNECTION_ID_LENGTH); clientCoapConfig.setTransient(DTLS_CONNECTION_ID_LENGTH);
boolean supportDeprecatedCiphers = false; boolean supportDeprecatedCiphers = false;
clientCoapConfig.set(DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY, !supportDeprecatedCiphers); clientCoapConfig.set(DTLS_RECOMMENDED_CIPHER_SUITES_ONLY, !supportDeprecatedCiphers);
/**
* "Control usage of DTLS connection ID.", // if (cIdLength!= null) {
* "- 'on' to activate Connection ID support (same as -cid 0)", // setDtlsConnectorConfigCidLength(clientCoapConfig, cIdLength);
* "- '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.", // if (cIdLength!= null) {
* "Default: off" setDtlsConnectorConfigCidLength(clientCoapConfig, cIdLength);
*/ }
Integer cid = null;
clientCoapConfig.set(DtlsConfig.DTLS_CONNECTION_ID_LENGTH, cid);
// Set Californium Configuration // Set Californium Configuration
endpointsBuilder.setConfiguration(clientCoapConfig); endpointsBuilder.setConfiguration(clientCoapConfig);
@ -279,6 +286,7 @@ public class LwM2MTestClient {
builder.setSharedExecutor(executor); builder.setSharedExecutor(executor);
clientStates = new HashSet<>(); clientStates = new HashSet<>();
clientDtlsCid = new HashMap<>();
clientStates.add(ON_INIT); clientStates.add(ON_INIT);
leshanClient = builder.build(); leshanClient = builder.build();

View File

@ -59,7 +59,7 @@ public class OtaLwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest {
createDeviceProfile(transportConfiguration); createDeviceProfile(transportConfiguration);
LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_WITHOUT_FW_INFO)); LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_WITHOUT_FW_INFO));
final Device device = createDevice(deviceCredentials, 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()); awaitObserveReadAll(0, device.getId().getId().toString());
device.setFirmwareId(createFirmware().getId()); device.setFirmwareId(createFirmware().getId());
@ -84,7 +84,7 @@ public class OtaLwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest {
createDeviceProfile(transportConfiguration); createDeviceProfile(transportConfiguration);
LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_OTA5)); LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_OTA5));
final Device device = createDevice(deviceCredentials, 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()); awaitObserveReadAll(9, device.getId().getId().toString());
device.setFirmwareId(createFirmware().getId()); device.setFirmwareId(createFirmware().getId());
@ -114,7 +114,7 @@ public class OtaLwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest {
createDeviceProfile(transportConfiguration); createDeviceProfile(transportConfiguration);
LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_OTA9)); LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_OTA9));
final Device device = createDevice(deviceCredentials, 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()); awaitObserveReadAll(9, device.getId().getId().toString());
device.setSoftwareId(createSoftware().getId()); device.setSoftwareId(createSoftware().getId());

View File

@ -91,7 +91,7 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg
private void initRpc () throws Exception { private void initRpc () throws Exception {
String endpoint = DEVICE_ENDPOINT_RPC_PREF + endpointSequence.incrementAndGet(); 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(); expectedObjects = ConcurrentHashMap.newKeySet();
expectedObjectIdVers = ConcurrentHashMap.newKeySet(); expectedObjectIdVers = ConcurrentHashMap.newKeySet();
expectedInstances = ConcurrentHashMap.newKeySet(); expectedInstances = ConcurrentHashMap.newKeySet();

View File

@ -196,7 +196,7 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M
boolean isStartLw) throws Exception { boolean isStartLw) throws Exception {
createDeviceProfile(transportConfiguration); createDeviceProfile(transportConfiguration);
final Device device = createDevice(deviceCredentials, endpoint); final Device device = createDevice(deviceCredentials, endpoint);
createNewClient(security, securityBs, coapConfig, true, endpoint); createNewClient(security, securityBs, coapConfig, true, endpoint, null);
lwM2MTestClient.start(isStartLw); lwM2MTestClient.start(isStartLw);
if (isAwaitObserveReadAll) { if (isAwaitObserveReadAll) {
awaitObserveReadAll(0, device.getId().getId().toString()); awaitObserveReadAll(0, device.getId().getId().toString());
@ -244,7 +244,7 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M
createDeviceProfile(transportConfiguration); createDeviceProfile(transportConfiguration);
final Device device = createDevice(deviceCredentials, endpoint); final Device device = createDevice(deviceCredentials, endpoint);
String deviceIdStr = device.getId().getId().toString(); String deviceIdStr = device.getId().getId().toString();
createNewClient(security, securityBs, coapConfig, true, endpoint); createNewClient(security, securityBs, coapConfig, true, endpoint, null);
lwM2MTestClient.start(true); lwM2MTestClient.start(true);
awaitObserveReadAll(0, deviceIdStr); awaitObserveReadAll(0, deviceIdStr);
await(awaitAlias) await(awaitAlias)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -41,6 +41,8 @@ import java.util.Collections;
import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.eclipse.californium.elements.config.CertificateAuthenticationMode.WANTED; 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_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_RETRANSMISSION_TIMEOUT;
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_ROLE; import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_ROLE;
import static org.eclipse.californium.scandium.config.DtlsConfig.DtlsRole.SERVER_ONLY; 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}") @Value("${transport.coap.dtls.retransmission_timeout:9000}")
private int dtlsRetransmissionTimeout; private int dtlsRetransmissionTimeout;
@Value("${transport.coap.dtls.connection_id_length}")
private Integer cIdLength;
@Bean @Bean
@ConfigurationProperties(prefix = "transport.coap.dtls.credentials") @ConfigurationProperties(prefix = "transport.coap.dtls.credentials")
public SslCredentialsConfig coapDtlsCredentials() { public SslCredentialsConfig coapDtlsCredentials() {
@ -93,6 +98,14 @@ public class TbCoapDtlsSettings {
configBuilder.set(DTLS_CLIENT_AUTHENTICATION_MODE, WANTED); configBuilder.set(DTLS_CLIENT_AUTHENTICATION_MODE, WANTED);
configBuilder.set(DTLS_RETRANSMISSION_TIMEOUT, dtlsRetransmissionTimeout, MILLISECONDS); configBuilder.set(DTLS_RETRANSMISSION_TIMEOUT, dtlsRetransmissionTimeout, MILLISECONDS);
configBuilder.set(DTLS_ROLE, SERVER_ONLY); 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( configBuilder.setAdvancedCertificateVerifier(
new TbCoapDtlsCertificateVerifier( new TbCoapDtlsCertificateVerifier(
transportService, transportService,

View File

@ -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.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.DefaultLwM2mTransportService.RPK_OR_X509_CIPHER_SUITES;
import static org.thingsboard.server.transport.lwm2m.server.LwM2MNetworkConfig.getCoapConfig; import static org.thingsboard.server.transport.lwm2m.server.LwM2MNetworkConfig.getCoapConfig;
import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.setDtlsConnectorConfigCidLength;
@Slf4j @Slf4j
@Component @Component
@ -113,15 +114,15 @@ public class LwM2MTransportBootstrapService {
serverCoapConfig.setTransient(DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY); serverCoapConfig.setTransient(DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY);
serverCoapConfig.set(DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY, serverConfig.isRecommendedCiphers()); serverCoapConfig.set(DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY, serverConfig.isRecommendedCiphers());
serverCoapConfig.setTransient(DtlsConfig.DTLS_CONNECTION_ID_LENGTH); serverCoapConfig.setTransient(DtlsConfig.DTLS_CONNECTION_ID_LENGTH);
serverCoapConfig.set(DtlsConfig.DTLS_CONNECTION_ID_LENGTH, 6);
serverCoapConfig.set(DTLS_RECOMMENDED_CURVES_ONLY, serverConfig.isRecommendedSupportedGroups()); serverCoapConfig.set(DTLS_RECOMMENDED_CURVES_ONLY, serverConfig.isRecommendedSupportedGroups());
serverCoapConfig.setTransient(DTLS_RETRANSMISSION_TIMEOUT); serverCoapConfig.setTransient(DTLS_RETRANSMISSION_TIMEOUT);
serverCoapConfig.set(DTLS_RETRANSMISSION_TIMEOUT, serverConfig.getDtlsRetransmissionTimeout(), MILLISECONDS); serverCoapConfig.set(DTLS_RETRANSMISSION_TIMEOUT, serverConfig.getDtlsRetransmissionTimeout(), MILLISECONDS);
if (serverConfig.getDtlsCidLength() != null) {
setDtlsConnectorConfigCidLength( serverCoapConfig, serverConfig.getDtlsCidLength());
}
/* Create DTLS Config */ /* Create DTLS Config */
this.setServerWithCredentials(builder); this.setServerWithCredentials(builder);
// Set Californium Configuration // Set Californium Configuration

View File

@ -42,6 +42,10 @@ public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig {
@Value("${transport.lwm2m.dtls.retransmission_timeout:9000}") @Value("${transport.lwm2m.dtls.retransmission_timeout:9000}")
private int dtlsRetransmissionTimeout; private int dtlsRetransmissionTimeout;
@Getter
@Value("${transport.lwm2m.dtls.connection_id_length:}")
private Integer dtlsCidLength;
@Getter @Getter
@Value("${transport.lwm2m.timeout:}") @Value("${transport.lwm2m.timeout:}")
private Long timeout; private Long timeout;

View File

@ -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.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.LwM2MNetworkConfig.getCoapConfig;
import static org.thingsboard.server.transport.lwm2m.server.ota.DefaultLwM2MOtaUpdateService.FIRMWARE_UPDATE_COAP_RESOURCE; 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 @Slf4j
@Component @Component
@ -165,21 +166,10 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService {
serverCoapConfig.set(DTLS_RETRANSMISSION_TIMEOUT, config.getDtlsRetransmissionTimeout(), MILLISECONDS); serverCoapConfig.set(DTLS_RETRANSMISSION_TIMEOUT, config.getDtlsRetransmissionTimeout(), MILLISECONDS);
serverCoapConfig.set(DTLS_ROLE, SERVER_ONLY); serverCoapConfig.set(DTLS_ROLE, SERVER_ONLY);
serverCoapConfig.setTransient(DtlsConfig.DTLS_CONNECTION_ID_LENGTH); 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. <blank> 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 */ /* Create DTLS Config */
this.setServerWithCredentials(builder); this.setServerWithCredentials(builder);

View File

@ -17,6 +17,7 @@ package org.thingsboard.server.transport.lwm2m.utils;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import lombok.extern.slf4j.Slf4j; 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.LwM2mModel;
import org.eclipse.leshan.core.model.ObjectLoader; import org.eclipse.leshan.core.model.ObjectLoader;
import org.eclipse.leshan.core.model.ObjectModel; import org.eclipse.leshan.core.model.ObjectModel;
@ -55,6 +56,8 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; 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.BOOLEAN;
import static org.eclipse.leshan.core.model.ResourceModel.Type.FLOAT; import static org.eclipse.leshan.core.model.ResourceModel.Type.FLOAT;
import static org.eclipse.leshan.core.model.ResourceModel.Type.INTEGER; import static org.eclipse.leshan.core.model.ResourceModel.Type.INTEGER;
@ -425,4 +428,15 @@ public class LwM2MTransportUtil {
} }
return newValueStr.equals(oldValueStr); 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);
}
}
} }