Skip to content

Commit

Permalink
#992: guess ServerIdentity from Endpoint instead of EndpointContext
Browse files Browse the repository at this point in the history
  • Loading branch information
sbernard31 committed Apr 6, 2021
1 parent a75781b commit edeaa2b
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
import org.eclipse.leshan.client.servers.ServerInfo;
import org.eclipse.leshan.core.CertificateUsage;
import org.eclipse.leshan.core.SecurityMode;
import org.eclipse.leshan.core.californium.EndpointContextUtil;
import org.eclipse.leshan.core.californium.EndpointFactory;
import org.eclipse.leshan.core.request.Identity;
import org.slf4j.Logger;
Expand Down Expand Up @@ -186,8 +185,10 @@ public synchronized ServerIdentity createEndpoint(ServerInfo serverInfo) {
new DomainIssuerCertificateVerifier(serverInfo.serverCertificate));
}

serverIdentity = Identity.x509(serverInfo.getAddress(), EndpointContextUtil.extractCN(
((X509Certificate) serverInfo.serverCertificate).getSubjectX500Principal().getName()));
// TODO We set CN with '*' as we are not able to know the CN for some certificate usage and so this is
// not used anymore to identify a server with x509.
// See : https://github.com/eclipse/leshan/issues/992
serverIdentity = Identity.x509(serverInfo.getAddress(), "*");
filterCipherSuites(newBuilder, dtlsConfigbuilder.getIncompleteConfig().getSupportedCipherSuites(),
false, true);
} else {
Expand Down Expand Up @@ -295,6 +296,24 @@ public synchronized Endpoint getEndpoint(ServerIdentity server) {
return null;
}

public synchronized ServerIdentity getServerIdentity(Endpoint endpoint, InetSocketAddress serverAddress) {
// TODO support multi server

// knowing used CoAP endpoint we should be able to know the server identity because :
// - we create 1 CoAP endpoint by server.
// - the dtls configuration ensure that only server with expected credential is able to talk.
// (see https://github.com/eclipse/leshan/issues/992 for more details)
if (endpoint != null && endpoint.equals(currentEndpoint) && currentEndpoint.isStarted()) {
// For UDP (not secure) endpoint we also check socket address as anybody send data to this kind of endpoint.
if (currentEndpoint.getConnector().getProtocol() == "UDP"
&& !currentServer.getIdentity().getPeerAddress().equals(serverAddress)) {
return null;
}
return currentServer;
}
return null;
}

@Override
public synchronized void start() {
if (started)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,9 @@ public LeshanClient(String endpoint, InetSocketAddress localAddress,
bootstrapHandler, observers, additionalAttributes, bsAdditionalAttributes, sharedExecutor);

coapServer = createCoapServer(coapConfig, sharedExecutor);
coapServer.add(createBootstrapResource(engine, bootstrapHandler));
coapServer.add(createBootstrapResource(engine, endpointsManager, bootstrapHandler));
endpointsManager.setCoapServer(coapServer);
linkObjectTreeToCoapServer(coapServer, engine, objectTree, encoder, decoder);
linkObjectTreeToCoapServer(coapServer, engine, endpointsManager, objectTree, encoder, decoder);
createRegistrationUpdateHandler(engine, endpointsManager, bootstrapHandler, objectTree);

coapApi = new CoapAPI();
Expand Down Expand Up @@ -166,8 +166,8 @@ protected CoapServer createCoapServer(NetworkConfig coapConfig, ScheduledExecuto
@Override
protected Resource createRoot() {
// Use to handle Delete on "/"
return new org.eclipse.leshan.client.californium.RootResource(engine, bootstrapHandler, this,
rootEnabler, encoder, decoder);
return new org.eclipse.leshan.client.californium.RootResource(engine, endpointsManager,
bootstrapHandler, this, rootEnabler, encoder, decoder);
}
};

Expand All @@ -185,19 +185,22 @@ protected Resource createRoot() {
}

protected void linkObjectTreeToCoapServer(final CoapServer coapServer, final RegistrationEngine registrationEngine,
LwM2mObjectTree objectTree, final LwM2mNodeEncoder encoder, final LwM2mNodeDecoder decoder) {
final CaliforniumEndpointsManager endpointsManager, LwM2mObjectTree objectTree,
final LwM2mNodeEncoder encoder, final LwM2mNodeDecoder decoder) {

// Create CoAP resources for each lwm2m Objects.
for (LwM2mObjectEnabler enabler : objectTree.getObjectEnablers().values()) {
CoapResource clientObject = createObjectResource(enabler, registrationEngine, encoder, decoder);
CoapResource clientObject = createObjectResource(enabler, registrationEngine, endpointsManager, encoder,
decoder);
coapServer.add(clientObject);
}

// listen object tree
objectTree.addListener(new ObjectsListenerAdapter() {
@Override
public void objectAdded(LwM2mObjectEnabler object) {
CoapResource clientObject = createObjectResource(object, registrationEngine, encoder, decoder);
CoapResource clientObject = createObjectResource(object, registrationEngine, endpointsManager, encoder,
decoder);
coapServer.add(clientObject);
}

Expand All @@ -213,12 +216,13 @@ public void objectRemoved(LwM2mObjectEnabler object) {
}

protected CoapResource createObjectResource(LwM2mObjectEnabler enabler, RegistrationEngine registrationEngine,
LwM2mNodeEncoder encoder, LwM2mNodeDecoder decoder) {
return new ObjectResource(enabler, registrationEngine, encoder, decoder);
CaliforniumEndpointsManager endpointsManager, LwM2mNodeEncoder encoder, LwM2mNodeDecoder decoder) {
return new ObjectResource(enabler, registrationEngine, endpointsManager, encoder, decoder);
}

protected CoapResource createBootstrapResource(RegistrationEngine engine, BootstrapHandler bootstrapHandler) {
return new BootstrapResource(engine, bootstrapHandler);
protected CoapResource createBootstrapResource(RegistrationEngine registrationEngine,
CaliforniumEndpointsManager endpointsManager, BootstrapHandler bootstrapHandler) {
return new BootstrapResource(registrationEngine, endpointsManager, bootstrapHandler);
}

protected CaliforniumEndpointsManager createEndpointsManager(InetSocketAddress localAddress,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,37 +22,42 @@
import org.eclipse.leshan.client.engine.RegistrationEngine;
import org.eclipse.leshan.client.servers.ServerIdentity;
import org.eclipse.leshan.core.californium.LwM2mCoapResource;
import org.eclipse.leshan.core.request.Identity;

/**
* A Common {@link CoapResource} used to handle LWM2M request with some specific method for LWM2M client.
*/
public class LwM2mClientCoapResource extends LwM2mCoapResource {

protected final CaliforniumEndpointsManager endpointsManager;
protected final RegistrationEngine registrationEngine;

public LwM2mClientCoapResource(String name, RegistrationEngine registrationEngine) {
public LwM2mClientCoapResource(String name, RegistrationEngine registrationEngine,
CaliforniumEndpointsManager endpointsManager) {
super(name);
this.registrationEngine = registrationEngine;
this.endpointsManager = endpointsManager;
}

/**
* @return the server identity of a registered or bootstrap server, return null if this identity does match to any
* server for which we are in communication.
*/
protected ServerIdentity getServer(Identity identity) {
return registrationEngine.getServer(identity);
protected ServerIdentity getServer(CoapExchange exchange) {
ServerIdentity serverIdentity = extractIdentity(exchange);
if (registrationEngine.isAllowedToCommunicate(serverIdentity)) {
return serverIdentity;
} else {
return null;
}
}

/**
* Extract the {@link ServerIdentity} for this exchange. If there is no corresponding server currently in
* communication with this client. Answer with an {@link ResponseCode#INTERNAL_SERVER_ERROR}.
*/
protected ServerIdentity getServerOrRejectRequest(CoapExchange exchange) {
Identity extractedIdentity = extractIdentity(exchange);

// search if we are in communication with this server.
ServerIdentity server = getServer(extractedIdentity);
ServerIdentity server = getServer(exchange);
if (server != null)
return server;

Expand All @@ -61,13 +66,13 @@ protected ServerIdentity getServerOrRejectRequest(CoapExchange exchange) {
}

/**
* Create Leshan {@link Identity} from Californium {@link Exchange}.
* Get Leshan {@link ServerIdentity} from Californium {@link Exchange}.
*
* @param exchange The Californium {@link Exchange} containing the request for which we search sender identity.
* @return The corresponding Leshan {@link Identity}.
* @throws IllegalStateException if we are not able to extract {@link Identity}.
* @return The corresponding Leshan {@link ServerIdentity}.
* @throws IllegalStateException if we are not able to extract {@link ServerIdentity}.
*/
protected Identity extractIdentity(CoapExchange exchange) {
return extractIdentity(exchange.advanced().getRequest().getSourceContext());
protected ServerIdentity extractIdentity(CoapExchange exchange) {
return endpointsManager.getServerIdentity(exchange.advanced().getEndpoint(), exchange.getSourceSocketAddress());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,10 @@ public class RootResource extends LwM2mClientCoapResource {
protected LwM2mNodeEncoder encoder;
protected LwM2mNodeDecoder decoder;

public RootResource(RegistrationEngine registrationEngine, BootstrapHandler bootstrapHandler, CoapServer coapServer,
LwM2mRootEnabler rootEnabler, LwM2mNodeEncoder encoder, LwM2mNodeDecoder decoder) {
super("", registrationEngine);
public RootResource(RegistrationEngine registrationEngine, CaliforniumEndpointsManager endpointsManager,
BootstrapHandler bootstrapHandler, CoapServer coapServer, LwM2mRootEnabler rootEnabler,
LwM2mNodeEncoder encoder, LwM2mNodeDecoder decoder) {
super("", registrationEngine, endpointsManager);
this.bootstrapHandler = bootstrapHandler;
setVisible(false);
this.coapServer = coapServer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.eclipse.californium.core.server.resources.CoapExchange;
import org.eclipse.californium.core.server.resources.Resource;
import org.eclipse.leshan.client.bootstrap.BootstrapHandler;
import org.eclipse.leshan.client.californium.CaliforniumEndpointsManager;
import org.eclipse.leshan.client.californium.LwM2mClientCoapResource;
import org.eclipse.leshan.client.engine.RegistrationEngine;
import org.eclipse.leshan.client.servers.ServerIdentity;
Expand All @@ -39,8 +40,9 @@ public class BootstrapResource extends LwM2mClientCoapResource {

protected BootstrapHandler bootstrapHandler;

public BootstrapResource(RegistrationEngine registrationEngine, BootstrapHandler bootstrapHandler) {
super("bs", registrationEngine);
public BootstrapResource(RegistrationEngine registrationEngine, CaliforniumEndpointsManager endpointsManager,
BootstrapHandler bootstrapHandler) {
super("bs", registrationEngine, endpointsManager);
this.bootstrapHandler = bootstrapHandler;
this.setVisible(false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.eclipse.californium.core.coap.Request;
import org.eclipse.californium.core.server.resources.CoapExchange;
import org.eclipse.californium.core.server.resources.Resource;
import org.eclipse.leshan.client.californium.CaliforniumEndpointsManager;
import org.eclipse.leshan.client.californium.LwM2mClientCoapResource;
import org.eclipse.leshan.client.engine.RegistrationEngine;
import org.eclipse.leshan.client.resource.LwM2mObjectEnabler;
Expand Down Expand Up @@ -81,8 +82,8 @@ public class ObjectResource extends LwM2mClientCoapResource implements ObjectLis
protected final LwM2mNodeDecoder decoder;

public ObjectResource(LwM2mObjectEnabler nodeEnabler, RegistrationEngine registrationEngine,
LwM2mNodeEncoder encoder, LwM2mNodeDecoder decoder) {
super(Integer.toString(nodeEnabler.getId()), registrationEngine);
CaliforniumEndpointsManager endpointsManager, LwM2mNodeEncoder encoder, LwM2mNodeDecoder decoder) {
super(Integer.toString(nodeEnabler.getId()), registrationEngine, endpointsManager);
this.nodeEnabler = nodeEnabler;
this.nodeEnabler.addListener(this);
this.encoder = encoder;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@
import org.eclipse.leshan.core.request.BootstrapRequest;
import org.eclipse.leshan.core.request.ContentFormat;
import org.eclipse.leshan.core.request.DeregisterRequest;
import org.eclipse.leshan.core.request.Identity;
import org.eclipse.leshan.core.request.RegisterRequest;
import org.eclipse.leshan.core.request.UpdateRequest;
import org.eclipse.leshan.core.request.exception.SendFailedException;
Expand Down Expand Up @@ -813,25 +812,25 @@ public ServerIdentity getRegisteredServer(long serverId) {
}

@Override
public ServerIdentity getServer(Identity identity) {
if (identity == null)
return null;
public boolean isAllowedToCommunicate(ServerIdentity foreingPeer) {
if (foreingPeer == null)
return false;
ServerIdentity bootstrapServer = currentBoostrapServer.get();
if (bootstrapServer != null && identity.equals(bootstrapServer.getIdentity())) {
return bootstrapServer;
if (bootstrapServer != null && foreingPeer.equals(bootstrapServer)) {
return true;
} else {
for (ServerIdentity server : registeringServers) {
if (identity.equals(server.getIdentity())) {
return server;
if (foreingPeer.equals(server)) {
return true;
}
}
for (ServerIdentity server : registeredServers.values()) {
if (identity.equals(server.getIdentity())) {
return server;
if (foreingPeer.equals(server)) {
return true;
}
}
}
return null;
return false;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

import org.eclipse.leshan.client.RegistrationUpdate;
import org.eclipse.leshan.client.servers.ServerIdentity;
import org.eclipse.leshan.core.request.Identity;

/**
* Manage the registration life-cycle:
Expand Down Expand Up @@ -71,10 +70,9 @@ public interface RegistrationEngine {
ServerIdentity getRegisteredServer(long serverId);

/**
* @return The registered LWM2M Server or Bootstrap server for the given identity or null if there is no
* corresponding server registered.
* @return true if the given server can currently communicate with the device.
*/
ServerIdentity getServer(Identity identity);
boolean isAllowedToCommunicate(ServerIdentity foreingPeer);

/**
* @return the endpoint name of the LWM2M client
Expand Down

0 comments on commit edeaa2b

Please sign in to comment.