From edeaa2b4afcc77f0141b7859ed11c4b803fb7a4e Mon Sep 17 00:00:00 2001 From: Simon Bernard Date: Wed, 31 Mar 2021 17:25:02 +0200 Subject: [PATCH] #992: guess ServerIdentity from Endpoint instead of EndpointContext --- .../CaliforniumEndpointsManager.java | 25 ++++++++++++++-- .../client/californium/LeshanClient.java | 26 ++++++++++------- .../californium/LwM2mClientCoapResource.java | 29 +++++++++++-------- .../client/californium/RootResource.java | 7 +++-- .../bootstrap/BootstrapResource.java | 6 ++-- .../californium/object/ObjectResource.java | 5 ++-- .../engine/DefaultRegistrationEngine.java | 21 +++++++------- .../client/engine/RegistrationEngine.java | 6 ++-- 8 files changed, 77 insertions(+), 48 deletions(-) diff --git a/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/CaliforniumEndpointsManager.java b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/CaliforniumEndpointsManager.java index 969303c8eb..1c003e0118 100644 --- a/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/CaliforniumEndpointsManager.java +++ b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/CaliforniumEndpointsManager.java @@ -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; @@ -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 { @@ -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) diff --git a/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/LeshanClient.java b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/LeshanClient.java index 4674e709da..505f33bceb 100644 --- a/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/LeshanClient.java +++ b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/LeshanClient.java @@ -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(); @@ -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); } }; @@ -185,11 +185,13 @@ 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); } @@ -197,7 +199,8 @@ protected void linkObjectTreeToCoapServer(final CoapServer coapServer, final Reg 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); } @@ -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, diff --git a/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/LwM2mClientCoapResource.java b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/LwM2mClientCoapResource.java index 773f182c44..0b00ce0b1a 100644 --- a/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/LwM2mClientCoapResource.java +++ b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/LwM2mClientCoapResource.java @@ -22,26 +22,33 @@ 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; + } } /** @@ -49,10 +56,8 @@ protected ServerIdentity getServer(Identity identity) { * 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; @@ -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()); } } diff --git a/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/RootResource.java b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/RootResource.java index e26999a3b9..bccd17cafe 100644 --- a/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/RootResource.java +++ b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/RootResource.java @@ -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; diff --git a/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/bootstrap/BootstrapResource.java b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/bootstrap/BootstrapResource.java index 00f99c7a52..33c59dcfcd 100644 --- a/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/bootstrap/BootstrapResource.java +++ b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/bootstrap/BootstrapResource.java @@ -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; @@ -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); } diff --git a/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/object/ObjectResource.java b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/object/ObjectResource.java index c39011af06..f5cdd0fe3c 100644 --- a/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/object/ObjectResource.java +++ b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/object/ObjectResource.java @@ -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; @@ -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; diff --git a/leshan-client-core/src/main/java/org/eclipse/leshan/client/engine/DefaultRegistrationEngine.java b/leshan-client-core/src/main/java/org/eclipse/leshan/client/engine/DefaultRegistrationEngine.java index 8795410fb0..c5bf9700fd 100644 --- a/leshan-client-core/src/main/java/org/eclipse/leshan/client/engine/DefaultRegistrationEngine.java +++ b/leshan-client-core/src/main/java/org/eclipse/leshan/client/engine/DefaultRegistrationEngine.java @@ -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; @@ -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; } /** diff --git a/leshan-client-core/src/main/java/org/eclipse/leshan/client/engine/RegistrationEngine.java b/leshan-client-core/src/main/java/org/eclipse/leshan/client/engine/RegistrationEngine.java index 008e652368..98409ed9d4 100644 --- a/leshan-client-core/src/main/java/org/eclipse/leshan/client/engine/RegistrationEngine.java +++ b/leshan-client-core/src/main/java/org/eclipse/leshan/client/engine/RegistrationEngine.java @@ -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: @@ -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