Skip to content

Commit

Permalink
Use Authorizer in SendHandler
Browse files Browse the repository at this point in the history
  • Loading branch information
sbernard31 committed Oct 10, 2024
1 parent 8206237 commit bdfcd4b
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ public LeshanServer(LwM2mServerEndpointsProvider endpointsProvider, Registration
presenceService = createPresenceService(registrationService, awakeTimeProvider,
updateRegistrationOnNotification);
}
this.sendService = createSendHandler(registrationStore, updateRegistrationOnSend);
this.sendService = createSendHandler(registrationStore, authorizer, updateRegistrationOnSend);

// create endpoints
ServerEndpointToolbox toolbox = new ServerEndpointToolbox(decoder, encoder, linkParser,
Expand Down Expand Up @@ -202,8 +202,9 @@ protected PresenceServiceImpl createPresenceService(RegistrationService registra
return presenceService;
}

protected SendHandler createSendHandler(RegistrationStore registrationStore, boolean updateRegistrationOnSend) {
return new SendHandler(registrationStore, updateRegistrationOnSend);
protected SendHandler createSendHandler(RegistrationStore registrationStore, Authorizer authorizer,
boolean updateRegistrationOnSend) {
return new SendHandler(registrationStore, authorizer, updateRegistrationOnSend);
}

protected UplinkDeviceManagementRequestReceiver createRequestReceiver(RegistrationHandler registrationHandler,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@

import org.eclipse.leshan.core.endpoint.EndpointUri;
import org.eclipse.leshan.core.peer.LwM2mPeer;
import org.eclipse.leshan.core.request.DeregisterRequest;
import org.eclipse.leshan.core.request.RegisterRequest;
import org.eclipse.leshan.core.request.UpdateRequest;
import org.eclipse.leshan.core.request.UplinkRequest;
import org.eclipse.leshan.server.registration.Registration;
import org.eclipse.leshan.servers.security.Authorization;
Expand Down Expand Up @@ -72,15 +74,30 @@ protected boolean checkEndpointUri(UplinkRequest<?> request, Registration regist

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)
expectedSecurityInfo = securityStore.getByEndpoint(registration.getEndpoint());

if (securityChecker.checkSecurityInfo(registration.getEndpoint(), sender, expectedSecurityInfo)) {
return Authorization.approved();
if (request instanceof RegisterRequest || request instanceof UpdateRequest
|| request instanceof DeregisterRequest) {

// For Register, Update, DeregisterRequest we check in security store

// do we have security information for this client?
SecurityInfo expectedSecurityInfo = null;
if (securityStore != null)
expectedSecurityInfo = securityStore.getByEndpoint(registration.getEndpoint());

if (securityChecker.checkSecurityInfo(registration.getEndpoint(), sender, expectedSecurityInfo)) {
return Authorization.approved();
} else {
return Authorization.declined();
}
} else {
return Authorization.declined();

// for other we just check this is same identity
if (registration.getClientTransportData().getIdentity().equals(sender.getIdentity())) {
return Authorization.approved();
} else {
return Authorization.declined();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,23 @@
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;

import org.eclipse.leshan.core.ResponseCode;
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;
import org.eclipse.leshan.core.peer.LwM2mPeer;
import org.eclipse.leshan.core.request.SendRequest;
import org.eclipse.leshan.core.request.UpdateRequest;
import org.eclipse.leshan.core.request.exception.InvalidRequestException;
import org.eclipse.leshan.core.response.SendResponse;
import org.eclipse.leshan.core.response.SendableResponse;
import org.eclipse.leshan.server.registration.Registration;
import org.eclipse.leshan.server.registration.RegistrationStore;
import org.eclipse.leshan.server.registration.RegistrationUpdate;
import org.eclipse.leshan.server.registration.UpdatedRegistration;
import org.eclipse.leshan.server.security.Authorizer;
import org.eclipse.leshan.servers.security.Authorization;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -45,12 +49,14 @@ public class SendHandler implements SendService {
private final Logger LOG = LoggerFactory.getLogger(SendHandler.class);

private final RegistrationStore registrationStore;
private final Authorizer authorizer;
private final boolean updateRegistrationOnSend;

private final List<SendListener> listeners = new CopyOnWriteArrayList<>();;

public SendHandler(RegistrationStore registrationStore, boolean updateRegistrationOnSend) {
public SendHandler(RegistrationStore registrationStore, Authorizer authorizer, boolean updateRegistrationOnSend) {
this.registrationStore = registrationStore;
this.authorizer = authorizer;
this.updateRegistrationOnSend = updateRegistrationOnSend;
}

Expand All @@ -67,47 +73,69 @@ public void removeListener(SendListener listener) {
public SendableResponse<SendResponse> handleSend(LwM2mPeer sender, Registration registration,
final SendRequest request, EndpointUri serverEndpointUri) {

// try to update registration if needed
// Try to update registration if needed
final Registration updatedRegistration;
try {
updatedRegistration = updateRegistration(sender, registration);
updatedRegistration = updateRegistration(sender, registration, request, serverEndpointUri);
if (updatedRegistration == null) {
return errorReponse(updatedRegistration, ResponseCode.BAD_REQUEST, "not authorized", null);
}
} catch (Exception e) {
String errMsg = "unable to update registration";
SendableResponse<SendResponse> response = new SendableResponse<>(SendResponse.internalServerError(errMsg),
new Runnable() {
@Override
public void run() {
onError(registration, errMsg, e);
}
});
return response;
return errorReponse(registration, ResponseCode.INTERNAL_SERVER_ERROR, "unable to update registration", e);
}

// Check if send request is allowed
Authorization authorized = authorizer.isAuthorized(request, registration, sender, serverEndpointUri);
if (authorized.isDeclined()) {
return errorReponse(updatedRegistration, ResponseCode.BAD_REQUEST, "not authorized", null);
}

// Send Response to send request on success
// Validate and create Send Response
final SendResponse sendResponse = validateSendRequest(updatedRegistration, request);
SendableResponse<SendResponse> response = new SendableResponse<>(sendResponse, new Runnable() {

@Override
public void run() {
if (sendResponse.isSuccess()) {
fireDataReceived(updatedRegistration, request.getTimestampedNodes(), request);
} else {
onError(updatedRegistration, String.format("Invalid Send Request, server returns %s %s", //
sendResponse.getCode().getName(), //
sendResponse.getErrorMessage() != null ? "because" + sendResponse.getErrorMessage() : ""),
new InvalidRequestException(
sendResponse.getErrorMessage() != null ? sendResponse.getErrorMessage()
: "unknown reason"));
}
}

});
SendableResponse<SendResponse> response;
if (sendResponse.isSuccess()) {
response = new SendableResponse<>(sendResponse, new Runnable() {
@Override
public void run() {
if (sendResponse.isSuccess()) {
fireDataReceived(updatedRegistration, request.getTimestampedNodes(), request);
}
}
});
} else {
response = errorReponse(updatedRegistration, //
sendResponse.getCode(), //
String.format("Invalid Send Request, server returns %s %s", //
sendResponse.getCode().getName(), //
sendResponse.getErrorMessage() != null ? "because" + sendResponse.getErrorMessage() : ""), //
new InvalidRequestException(sendResponse.getErrorMessage() != null ? sendResponse.getErrorMessage()
: "unknown reason"));
}
return response;

}

private Registration updateRegistration(LwM2mPeer sender, final Registration registration) {
/**
* Update registration if needed and allowed by authorizer.
*
* Note that updating registration on send is out of specification and could be a problem for interoperability.
*
* @return the registration or the updated registration or null if not allowed to update.
*/
protected Registration updateRegistration(LwM2mPeer sender, final Registration registration,
final SendRequest request, EndpointUri endpointUri) {
if (updateRegistrationOnSend) {

// check if update is allowed
Authorization authorized = authorizer.isAuthorized(
new UpdateRequest(registration.getId(), null, null, null, null, null), registration, sender,
endpointUri);
if (authorized.isDeclined()) {
return null;
}

// update registration
RegistrationUpdate regUpdate = new RegistrationUpdate(registration.getId(), sender, null, null, null, null,
null, null, null, null, null, null);
UpdatedRegistration updatedRegistration = registrationStore.updateRegistration(regUpdate);
Expand Down Expand Up @@ -156,4 +184,17 @@ protected SendResponse validateSendRequest(Registration registration, SendReques
}
return SendResponse.success();
}

protected SendableResponse<SendResponse> errorReponse(Registration registration, ResponseCode code,
String errorMessage, Exception e) {

SendableResponse<SendResponse> response = new SendableResponse<>(new SendResponse(code, errorMessage),
new Runnable() {
@Override
public void run() {
onError(registration, errorMessage, e);
}
});
return response;
}
}

0 comments on commit bdfcd4b

Please sign in to comment.