Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support optional Endpoint Name #1652

Merged
merged 2 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import org.eclipse.leshan.client.LeshanClient;
import org.eclipse.leshan.client.LeshanClientBuilder;
import org.eclipse.leshan.client.endpoint.LwM2mClientEndpointsProvider;
import org.eclipse.leshan.client.engine.DefaultClientEndpointNameProvider;
import org.eclipse.leshan.client.engine.DefaultRegistrationEngineFactory;
import org.eclipse.leshan.client.object.LwM2mTestObject;
import org.eclipse.leshan.client.object.Oscore;
Expand Down Expand Up @@ -323,7 +324,8 @@ protected DtlsConnectorConfig.Builder createRootDtlsConnectorConfigBuilder(
endpointsProvider.add(new JavaCoapsTcpClientEndpointsProvider());

// Create client
LeshanClientBuilder builder = new LeshanClientBuilder(cli.main.endpoint);
LeshanClientBuilder builder = new LeshanClientBuilder(
new DefaultClientEndpointNameProvider(cli.main.endpoint, cli.main.endpointNameMode));
builder.setObjects(enablers);
builder.setEndpointsProviders(
endpointsProvider.toArray(new LwM2mClientEndpointsProvider[endpointsProvider.size()]));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@

import org.eclipse.californium.core.coap.CoAP;
import org.eclipse.californium.scandium.dtls.cipher.CipherSuite;
import org.eclipse.leshan.client.engine.DefaultClientEndpointNameProvider;
import org.eclipse.leshan.client.engine.DefaultClientEndpointNameProvider.Mode;
import org.eclipse.leshan.core.CertificateUsage;
import org.eclipse.leshan.core.endpoint.Protocol;
import org.eclipse.leshan.core.node.LwM2mPath;
Expand Down Expand Up @@ -173,6 +175,13 @@ public static class GeneralSection {
converter = ResourcePathConverter.class)

public Map<LwM2mPath, String> factoryBootstrap;

@Option(names = { "-nm", "--endpoint-name-mode" },
description = { //
"Can be used to set if client should or should not send client endpoint name during registration or bootstrap.", //
"Default : ${DEFAULT-VALUE}.",//
})
public DefaultClientEndpointNameProvider.Mode endpointNameMode = Mode.ALWAYS;
}

/* ********************************** Location Section ******************************** */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,15 @@
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;

import org.eclipse.leshan.core.ResponseCode;
import org.eclipse.leshan.core.endpoint.Protocol;
import org.eclipse.leshan.core.link.LinkParseException;
import org.eclipse.leshan.core.request.ReadRequest;
import org.eclipse.leshan.core.request.exception.RequestCanceledException;
import org.eclipse.leshan.core.response.ErrorCallback;
import org.eclipse.leshan.core.response.ReadResponse;
import org.eclipse.leshan.core.response.ResponseCallback;
import org.eclipse.leshan.integration.tests.util.Failure;
import org.eclipse.leshan.integration.tests.util.LeshanTestClient;
import org.eclipse.leshan.integration.tests.util.LeshanTestClientBuilder;
import org.eclipse.leshan.integration.tests.util.LeshanTestServer;
Expand Down Expand Up @@ -289,4 +291,22 @@ public void register_with_additional_attributes(Protocol protocol, String client
assertThat(registration.getAdditionalRegistrationAttributes())
.containsExactlyEntriesOf(expectedAdditionalAttributes);
}

@TestAllTransportLayer
public void register_without_sending_endpoint(Protocol protocol, String clientEndpointProvider,
String serverEndpointProvider) throws InterruptedException, LinkParseException {

client = givenClient.dontSendEndpointName().build();

// Check client is not registered
assertThat(client).isNotRegisteredAt(server);

// Start it and wait for registration failure
client.start();
Failure failure = client.waitForRegistrationFailureTo(server);
assertThat(failure).failedWith(ResponseCode.FORBIDDEN);

// Check we are registered with the expected attributes
assertThat(client).isNotRegisteredAt(server);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
import org.eclipse.leshan.core.response.ReadResponse;
import org.eclipse.leshan.core.util.TestLwM2mId;
import org.eclipse.leshan.integration.tests.util.BootstrapRequestChecker;
import org.eclipse.leshan.integration.tests.util.Failure;
import org.eclipse.leshan.integration.tests.util.LeshanTestBootstrapServer;
import org.eclipse.leshan.integration.tests.util.LeshanTestBootstrapServerBuilder;
import org.eclipse.leshan.integration.tests.util.LeshanTestClient;
Expand Down Expand Up @@ -157,6 +158,29 @@ public void bootstrap(Protocol givenProtocol, String givenClientEndpointProvider
assertThat(client).isRegisteredAt(server);
}

@TestAllTransportLayer
public void bootstrap_without_endpoint_name(Protocol givenProtocol, String givenClientEndpointProvider,
String givenServerEndpointProvider, String givenBootstrapServerEndpointProvider)
throws InvalidConfigurationException {
// Create and start bootstrap server
bootstrapServer = givenBootstrapServer.build();
bootstrapServer.start();

// Create Client and check it is not already registered
client = givenClient.connectingTo(bootstrapServer).dontSendEndpointName().build();

// Add config for this client
bootstrapServer.getConfigStore().add(client.getEndpointName(), //
givenBootstrapConfig() //
.adding(givenProtocol, bootstrapServer) //
.build());

// Start it and wait for registration
client.start();
Failure cause = client.waitForBootstrapFailure(bootstrapServer, 2, TimeUnit.SECONDS);
assertThat(cause).failedWith(ResponseCode.BAD_REQUEST);
}

@TestAllTransportLayer
public void bootstrap_tlv_only(Protocol givenProtocol, String givenClientEndpointProvider,
String givenServerEndpointProvider, String givenBootstrapServerEndpointProvider)
Expand Down Expand Up @@ -501,8 +525,8 @@ public void bootstrap_create_2_bsserver(Protocol givenProtocol, String givenClie
client.start();

// ensure bootstrap session failed because of invalid state
Exception cause = client.waitForBootstrapFailure(bootstrapServer, 2, TimeUnit.SECONDS);
assertThat(cause).isExactlyInstanceOf(InvalidStateException.class);
Failure cause = client.waitForBootstrapFailure(bootstrapServer, 2, TimeUnit.SECONDS);
assertThat(cause).failedWith(InvalidStateException.class);
BootstrapFailureCause failure = bootstrapServer.waitForBootstrapFailure(1, TimeUnit.SECONDS);
assertThat(failure).isEqualTo(BootstrapFailureCause.FINISH_FAILED);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@

import org.eclipse.leshan.bsserver.InvalidConfigurationException;
import org.eclipse.leshan.core.CertificateUsage;
import org.eclipse.leshan.core.ResponseCode;
import org.eclipse.leshan.core.endpoint.Protocol;
import org.eclipse.leshan.integration.tests.util.Credentials;
import org.eclipse.leshan.integration.tests.util.Failure;
import org.eclipse.leshan.integration.tests.util.LeshanTestBootstrapServer;
import org.eclipse.leshan.integration.tests.util.LeshanTestBootstrapServerBuilder;
import org.eclipse.leshan.integration.tests.util.LeshanTestClient;
Expand Down Expand Up @@ -118,6 +120,41 @@ public void bootstrap_using_psk() throws NonUniqueSecurityInfoException, Invalid
assertThat(client).isRegisteredAt(server);
}

@Test
public void bootstrap_using_psk_without_endpointname()
throws NonUniqueSecurityInfoException, InvalidConfigurationException {
// Create DM Server without security & start it
server = givenServer.using(Protocol.COAP).build();
server.start();

// Create and start bootstrap server
bootstrapServer = givenBootstrapServer.using(Protocol.COAPS).build();
bootstrapServer.start();

// Create Client and check it is not already registered
client = givenClient.connectingTo(bootstrapServer).named(GOOD_PSK_ID).sendEndpointNameIfNecessary()
.using(Protocol.COAPS).usingPsk(GOOD_PSK_ID, GOOD_PSK_KEY).build();
assertThat(client).isNotRegisteredAt(server);

// Add client credentials to the server
bootstrapServer.getEditableSecurityStore()
.add(SecurityInfo.newPreSharedKeyInfo(client.getEndpointName(), GOOD_PSK_ID, GOOD_PSK_KEY));

// Add config for this client
bootstrapServer.getConfigStore().add(client.getEndpointName(), //
givenBootstrapConfig() //
.adding(Protocol.COAPS, bootstrapServer, GOOD_PSK_ID, GOOD_PSK_KEY) //
.adding(Protocol.COAP, server) //
.build());

// Start it and wait for registration
client.start();
server.waitForNewRegistrationOf(client);

// check the client is registered
assertThat(client).isRegisteredAt(server);
}

@Test
public void bootstrap_failed_using_bad_psk() throws InvalidConfigurationException, NonUniqueSecurityInfoException {
// Create DM Server without security & start it
Expand Down Expand Up @@ -185,6 +222,42 @@ public void bootstrap_using_rpk() throws NonUniqueSecurityInfoException, Invalid
assertThat(client).isRegisteredAt(server);
}

@Test
public void bootstrap_using_rpk_without_endpoint()
throws NonUniqueSecurityInfoException, InvalidConfigurationException {
// Create DM Server without security & start it
server = givenServer.using(Protocol.COAP).build();
server.start();

// Create and start bootstrap server
bootstrapServer = givenBootstrapServer.using(Protocol.COAPS).using(serverPublicKey, serverPrivateKey).build();
bootstrapServer.start();

// Create Client and check it is not already registered
client = givenClient.connectingTo(bootstrapServer).using(Protocol.COAPS) //
.dontSendEndpointName()//
.using(clientPublicKey, clientPrivateKey)//
.trusting(serverPublicKey).build();

assertThat(client).isNotRegisteredAt(server);

// Add client credentials to the server
bootstrapServer.getEditableSecurityStore()
.add(SecurityInfo.newRawPublicKeyInfo(client.getEndpointName(), clientPublicKey));

// Add config for this client
bootstrapServer.getConfigStore().add(client.getEndpointName(), //
givenBootstrapConfig() //
.adding(Protocol.COAPS, bootstrapServer, clientPublicKey, clientPrivateKey, serverPublicKey) //
.adding(Protocol.COAP, server) //
.build());

// Start it and wait for registration
client.start();
Failure cause = client.waitForBootstrapFailure(bootstrapServer, 2, TimeUnit.SECONDS);
assertThat(cause).failedWith(ResponseCode.BAD_REQUEST);
}

@Test
public void bootstrap_using_x509()
throws NonUniqueSecurityInfoException, InvalidConfigurationException, CertificateEncodingException {
Expand Down Expand Up @@ -225,6 +298,47 @@ public void bootstrap_using_x509()
assertThat(client).isRegisteredAt(server);
}

@Test
public void bootstrap_using_x509_without_endpoint()
throws NonUniqueSecurityInfoException, InvalidConfigurationException, CertificateEncodingException {

// Create DM Server without security & start it
server = givenServer.using(Protocol.COAP).build();
server.start();

// Create and start bootstrap server
bootstrapServer = givenBootstrapServer.using(Protocol.COAPS)
.using(serverX509CertSignedByRoot, serverPrivateKeyFromCert)//
.trusting(trustedCertificatesByServer).build();
bootstrapServer.start();

// Create Client and check it is not already registered
client = givenClient.connectingTo(bootstrapServer).using(Protocol.COAPS) //
.sendEndpointNameIfNecessary() // by default LeshanClientTest is using CN of certificate
.using(clientX509CertSignedByRoot, clientPrivateKeyFromCert)//
.trusting(serverX509CertSignedByRoot).build();

assertThat(client).isNotRegisteredAt(server);

// Add client credentials to the server
bootstrapServer.getEditableSecurityStore().add(SecurityInfo.newX509CertInfo(client.getEndpointName()));

// Add config for this client
bootstrapServer.getConfigStore().add(client.getEndpointName(), //
givenBootstrapConfig() //
.adding(Protocol.COAPS, bootstrapServer, clientX509CertSignedByRoot, clientPrivateKeyFromCert,
serverX509CertSignedByRoot) //
.adding(Protocol.COAP, server) //
.build());

// Start it and wait for registration
client.start();
server.waitForNewRegistrationOf(client);

// check the client is registered
assertThat(client).isRegisteredAt(server);
}

@Test
public void bootstrap_using_x509_with_sni()
throws NonUniqueSecurityInfoException, InvalidConfigurationException, CertificateEncodingException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,4 +216,42 @@ public void bootstrapViaOscoreToUnsecuredServer()
// check the client is registered
assertThat(client).isRegisteredAt(server);
}

@Test
public void bootstrap_via_oscore_to_unsecured_server_without_endpoint()
throws OSException, NonUniqueSecurityInfoException, InvalidConfigurationException {
// Create DM Server without security & start it
server = givenServer.build();
server.start();

// Create and start bootstrap server
bootstrapServer = givenBootstrapServer.with(new InMemorySecurityStore()).build();
bootstrapServer.start();

// Create Client and check it is not already registered
client = givenClient.connectingTo(bootstrapServer) //
.named(new String(getClientOscoreSetting().getSenderId())) //
.sendEndpointNameIfNecessary() //
.using(getBootstrapClientOscoreSetting()).build();
assertThat(client).isNotRegisteredAt(server);

// Add client credentials to the Bootstrap server
bootstrapServer.getEditableSecurityStore()
.add(SecurityInfo.newOscoreInfo(client.getEndpointName(), getBootstrapServerOscoreSetting()));

// Add config for this client
bootstrapServer.getConfigStore().add(client.getEndpointName(), //
givenBootstrapConfig() //
.adding(Protocol.COAP, bootstrapServer,
getOscoreBootstrapObject(getBootstrapClientOscoreSetting())) //
.adding(Protocol.COAP, server) //
.build());

// Start it and wait for registration
client.start();
server.waitForNewRegistrationOf(client);

// check the client is registered
assertThat(client).isRegisteredAt(server);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,34 @@ public void registered_device_with_oscore_to_server_with_oscore()
assertThat(response.isSuccess()).isTrue();
}

@Test
public void registered_device_with_oscore_to_server_with_oscore_without_endpoint_name()
throws NonUniqueSecurityInfoException, InterruptedException {
// Create OSCORE Client
client = givenClient.connectingTo(server) //
.named(new String(getClientOscoreSetting().getSenderId())) //
.dontSendEndpointName() //
.using(getClientOscoreSetting()).build();

// Add client credentials to the server
server.getSecurityStore().add(SecurityInfo.newOscoreInfo(client.getEndpointName(), getServerOscoreSetting()));

// Check client is not registered
assertThat(client).isNotRegisteredAt(server);

// Start it and wait for registration
client.start();
server.waitForNewRegistrationOf(client);

// Check client is well registered
assertThat(client).isRegisteredAt(server);
Registration registration = server.getRegistrationFor(client);

// check we can send request to client.
ReadResponse response = server.send(registration, new ReadRequest(3, 0, 1), 500);
assertThat(response.isSuccess()).isTrue();
}

@Test
public void registered_device_with_oscore_to_server_with_oscore_then_removed_security_info_then_server_fails_to_send_request()
throws NonUniqueSecurityInfoException, InterruptedException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,39 @@ public void registered_device_with_psk_to_server_with_psk(Protocol givenProtocol
assertThat(response.isSuccess()).isTrue();
}

@TestAllTransportLayer
public void registered_device_with_psk_to_server_with_psk_without_endpointname(Protocol givenProtocol,
String givenClientEndpointProvider, String givenServerEndpointProvider)
throws NonUniqueSecurityInfoException, InterruptedException {

// Create PSK server & start it
server = givenServer.build(); // default server support PSK
server.start();

// Create PSK Client
client = givenClient.connectingTo(server).named(GOOD_PSK_ID).dontSendEndpointName()
.usingPsk(GOOD_PSK_ID, GOOD_PSK_KEY).build();

// Add client credentials to the server
server.getSecurityStore()
.add(SecurityInfo.newPreSharedKeyInfo(client.getEndpointName(), GOOD_PSK_ID, GOOD_PSK_KEY));

// Check client is not registered
assertThat(client).isNotRegisteredAt(server);

// Start it and wait for registration
client.start();
server.waitForNewRegistrationOf(client);

// Check client is well registered
assertThat(client).isRegisteredAt(server);
Registration registration = server.getRegistrationFor(client);

// check we can send request to client.
ReadResponse response = server.send(registration, new ReadRequest(3, 0, 1), 500);
assertThat(response.isSuccess()).isTrue();
}

@TestAllTransportLayer
public void register_update_deregister_reregister_device_with_psk_to_server_with_psk(Protocol givenProtocol,
String givenClientEndpointProvider, String givenServerEndpointProvider)
Expand Down
Loading