From 299201843cddc9bf1a369a06d7eafaac258bb9dd Mon Sep 17 00:00:00 2001 From: Simon Bernard Date: Wed, 9 Oct 2024 12:04:38 +0200 Subject: [PATCH] Authorizer checks client do not change endpoint during same registration See: https://github.com/eclipse-leshan/leshan/issues/1415 --- .../registration/RegistrationHandler.java | 14 ++++++---- .../request/DefaultUplinkRequestReceiver.java | 12 ++++----- .../leshan/server/security/Authorizer.java | 5 +++- .../server/security/DefaultAuthorizer.java | 27 ++++++++++++++++++- .../leshan/server/send/SendHandler.java | 3 ++- .../registration/RegistrationHandlerTest.java | 9 ++++--- 6 files changed, 53 insertions(+), 17 deletions(-) diff --git a/leshan-lwm2m-server/src/main/java/org/eclipse/leshan/server/registration/RegistrationHandler.java b/leshan-lwm2m-server/src/main/java/org/eclipse/leshan/server/registration/RegistrationHandler.java index 9e0fc47f52..74bfa1da52 100644 --- a/leshan-lwm2m-server/src/main/java/org/eclipse/leshan/server/registration/RegistrationHandler.java +++ b/leshan-lwm2m-server/src/main/java/org/eclipse/leshan/server/registration/RegistrationHandler.java @@ -98,7 +98,8 @@ public SendableResponse register(LwM2mPeer sender, RegisterReq Registration registrationToApproved = builder.build(); // We check if the client get authorization. - Authorization authorization = authorizer.isAuthorized(registerRequest, registrationToApproved, sender); + Authorization authorization = authorizer.isAuthorized(registerRequest, registrationToApproved, sender, + endpointUsed); if (authorization.isDeclined()) { return new SendableResponse<>(RegisterResponse.forbidden(null)); } @@ -134,7 +135,8 @@ public void run() { return new SendableResponse<>(RegisterResponse.success(approvedRegistration.getId()), whenSent); } - public SendableResponse update(LwM2mPeer sender, UpdateRequest updateRequest) { + public SendableResponse update(LwM2mPeer sender, UpdateRequest updateRequest, + EndpointUri endpointUsed) { // We check if there is a registration to update Registration currentRegistration = registrationService.getById(updateRequest.getRegistrationId()); @@ -143,7 +145,7 @@ public SendableResponse update(LwM2mPeer sender, UpdateRequest u } // We check if the client get authorization. - Authorization authorization = authorizer.isAuthorized(updateRequest, currentRegistration, sender); + Authorization authorization = authorizer.isAuthorized(updateRequest, currentRegistration, sender, endpointUsed); if (authorization.isDeclined()) { return new SendableResponse<>(UpdateResponse.badRequest("forbidden")); } @@ -183,7 +185,8 @@ public void run() { } } - public SendableResponse deregister(LwM2mPeer sender, DeregisterRequest deregisterRequest) { + public SendableResponse deregister(LwM2mPeer sender, DeregisterRequest deregisterRequest, + EndpointUri endpointUsed) { // We check if there is a registration to remove Registration currentRegistration = registrationService.getById(deregisterRequest.getRegistrationId()); @@ -192,7 +195,8 @@ public SendableResponse deregister(LwM2mPeer sender, Deregis } // We check if the client get authorization. - Authorization authorization = authorizer.isAuthorized(deregisterRequest, currentRegistration, sender); + Authorization authorization = authorizer.isAuthorized(deregisterRequest, currentRegistration, sender, + endpointUsed); if (authorization.isDeclined()) { return new SendableResponse<>(DeregisterResponse.badRequest("forbidden")); } diff --git a/leshan-lwm2m-server/src/main/java/org/eclipse/leshan/server/request/DefaultUplinkRequestReceiver.java b/leshan-lwm2m-server/src/main/java/org/eclipse/leshan/server/request/DefaultUplinkRequestReceiver.java index a95ea939b2..646d864ac2 100644 --- a/leshan-lwm2m-server/src/main/java/org/eclipse/leshan/server/request/DefaultUplinkRequestReceiver.java +++ b/leshan-lwm2m-server/src/main/java/org/eclipse/leshan/server/request/DefaultUplinkRequestReceiver.java @@ -62,34 +62,34 @@ public class RequestHandler implements UplinkDeviceMana private final LwM2mPeer sender; private final ClientProfile senderProfile; - private final EndpointUri endpoint; + private final EndpointUri endpointUri; private SendableResponse response; public RequestHandler(LwM2mPeer sender, ClientProfile clientProfile, EndpointUri serverEndpointUri) { this.sender = sender; this.senderProfile = clientProfile; - this.endpoint = serverEndpointUri; + this.endpointUri = serverEndpointUri; } @Override public void visit(RegisterRequest request) { - response = registrationHandler.register(sender, request, endpoint); + response = registrationHandler.register(sender, request, endpointUri); } @Override public void visit(UpdateRequest request) { - response = registrationHandler.update(sender, request); + response = registrationHandler.update(sender, request, endpointUri); } @Override public void visit(DeregisterRequest request) { - response = registrationHandler.deregister(sender, request); + response = registrationHandler.deregister(sender, request, endpointUri); } @Override public void visit(SendRequest request) { - response = sendHandler.handleSend(sender, senderProfile.getRegistration(), request); + response = sendHandler.handleSend(sender, senderProfile.getRegistration(), request, endpointUri); } @SuppressWarnings("unchecked") diff --git a/leshan-lwm2m-server/src/main/java/org/eclipse/leshan/server/security/Authorizer.java b/leshan-lwm2m-server/src/main/java/org/eclipse/leshan/server/security/Authorizer.java index 44b2253e2f..437215ca13 100644 --- a/leshan-lwm2m-server/src/main/java/org/eclipse/leshan/server/security/Authorizer.java +++ b/leshan-lwm2m-server/src/main/java/org/eclipse/leshan/server/security/Authorizer.java @@ -16,6 +16,7 @@ package org.eclipse.leshan.server.security; import org.eclipse.leshan.core.ResponseCode; +import org.eclipse.leshan.core.endpoint.EndpointUri; import org.eclipse.leshan.core.peer.LwM2mPeer; import org.eclipse.leshan.core.request.UplinkRequest; import org.eclipse.leshan.server.registration.Registration; @@ -42,8 +43,10 @@ public interface Authorizer { * For register request this is the registration which will be created
* For update request this is the registration before the update was done. * @param sender the {@link LwM2mPeer} which sent the request. + * @param endpointUri the endpoint URI which receive the request. * * @return an {@link Authorization} status. */ - Authorization isAuthorized(UplinkRequest request, Registration registration, LwM2mPeer sender); + Authorization isAuthorized(UplinkRequest request, Registration registration, LwM2mPeer sender, + EndpointUri endpointUri); } diff --git a/leshan-lwm2m-server/src/main/java/org/eclipse/leshan/server/security/DefaultAuthorizer.java b/leshan-lwm2m-server/src/main/java/org/eclipse/leshan/server/security/DefaultAuthorizer.java index ef2e04e412..6d434cacb8 100644 --- a/leshan-lwm2m-server/src/main/java/org/eclipse/leshan/server/security/DefaultAuthorizer.java +++ b/leshan-lwm2m-server/src/main/java/org/eclipse/leshan/server/security/DefaultAuthorizer.java @@ -15,7 +15,9 @@ *******************************************************************************/ package org.eclipse.leshan.server.security; +import org.eclipse.leshan.core.endpoint.EndpointUri; import org.eclipse.leshan.core.peer.LwM2mPeer; +import org.eclipse.leshan.core.request.RegisterRequest; import org.eclipse.leshan.core.request.UplinkRequest; import org.eclipse.leshan.server.registration.Registration; import org.eclipse.leshan.servers.security.Authorization; @@ -45,8 +47,31 @@ public DefaultAuthorizer(SecurityStore store, SecurityChecker checker) { } @Override - public Authorization isAuthorized(UplinkRequest request, Registration registration, LwM2mPeer sender) { + public Authorization isAuthorized(UplinkRequest request, Registration registration, LwM2mPeer sender, + EndpointUri endpointUri) { + if (!checkEndpointUri(request, registration, sender, endpointUri)) { + return Authorization.declined(); + } + + return checkIdentity(request, registration, sender, endpointUri); + } + + protected boolean checkEndpointUri(UplinkRequest request, Registration registration, LwM2mPeer sender, + EndpointUri endpointUri) { + if (!(request instanceof RegisterRequest)) { + // we do not allow to client to switch to another server endpoint within same registration + if (registration.getEndpointUri().equals(endpointUri)) { + return true; + } else { + return false; + } + } + return true; + } + + protected Authorization checkIdentity(UplinkRequest request, Registration registration, LwM2mPeer sender, + EndpointUri endpointUri) { // do we have security information for this client? SecurityInfo expectedSecurityInfo = null; if (securityStore != null) diff --git a/leshan-lwm2m-server/src/main/java/org/eclipse/leshan/server/send/SendHandler.java b/leshan-lwm2m-server/src/main/java/org/eclipse/leshan/server/send/SendHandler.java index db07b0a9ec..278308352c 100644 --- a/leshan-lwm2m-server/src/main/java/org/eclipse/leshan/server/send/SendHandler.java +++ b/leshan-lwm2m-server/src/main/java/org/eclipse/leshan/server/send/SendHandler.java @@ -19,6 +19,7 @@ import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; +import org.eclipse.leshan.core.endpoint.EndpointUri; import org.eclipse.leshan.core.node.LwM2mNode; import org.eclipse.leshan.core.node.LwM2mPath; import org.eclipse.leshan.core.node.TimestampedLwM2mNodes; @@ -64,7 +65,7 @@ public void removeListener(SendListener listener) { } public SendableResponse handleSend(LwM2mPeer sender, Registration registration, - final SendRequest request) { + final SendRequest request, EndpointUri serverEndpointUri) { // try to update registration if needed final Registration updatedRegistration; diff --git a/leshan-lwm2m-server/src/test/java/org/eclipse/leshan/server/registration/RegistrationHandlerTest.java b/leshan-lwm2m-server/src/test/java/org/eclipse/leshan/server/registration/RegistrationHandlerTest.java index 1a5721d5d7..93734bbde8 100644 --- a/leshan-lwm2m-server/src/test/java/org/eclipse/leshan/server/registration/RegistrationHandlerTest.java +++ b/leshan-lwm2m-server/src/test/java/org/eclipse/leshan/server/registration/RegistrationHandlerTest.java @@ -76,7 +76,8 @@ public void test_application_data_from_authorizer() { authorizer.willReturn(Authorization.approved(updatedAppData)); // handle UPDATE request - registrationHandler.update(givenIdentity(), givenUpdateRequestWithID(registration.getId())); + registrationHandler.update(givenIdentity(), givenUpdateRequestWithID(registration.getId()), + givenServerEndpointUri()); // check result registration = registrationStore.getRegistrationByEndpoint("myEndpoint"); @@ -105,7 +106,8 @@ public void test_update_without_application_data_from_authorizer() { authorizer.willReturn(Authorization.approved()); // handle UPDATE request - registrationHandler.update(givenIdentity(), givenUpdateRequestWithID(registration.getId())); + registrationHandler.update(givenIdentity(), givenUpdateRequestWithID(registration.getId()), + givenServerEndpointUri()); // check result registration = registrationStore.getRegistrationByEndpoint("myEndpoint"); @@ -142,7 +144,8 @@ public void willReturn(Authorization authorization) { } @Override - public Authorization isAuthorized(UplinkRequest request, Registration registration, LwM2mPeer sender) { + public Authorization isAuthorized(UplinkRequest request, Registration registration, LwM2mPeer sender, + EndpointUri endpointUri) { return autorization; } }