From 374c54fa703d38423293c5fab58105e95dc58f92 Mon Sep 17 00:00:00 2001 From: Madhawa Perera Date: Thu, 13 Sep 2018 14:37:05 +0530 Subject: [PATCH] make remote control feature mutual ssl compatible Introduced a new UUID to recognized the authenticated device's call back to establish the websocket connetion. When the UI requested to establish a screen sharing session with the device, a new UUID and will be created and stored in the database with the operation REMOTE_CONNECT's payload. Once the device polls the operation, it receives the UUID. Then device will call back the server with that same UUID to establish the websocket connection. --- .../RemoteSessionManagementServiceImpl.java | 137 +++++++++++------- .../remote.session/dto/RemoteSession.java | 13 +- .../RemoteSessionManagementDataHolder.java | 5 + 3 files changed, 101 insertions(+), 54 deletions(-) diff --git a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/RemoteSessionManagementServiceImpl.java b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/RemoteSessionManagementServiceImpl.java index 1274d79214..75fbfdccaf 100644 --- a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/RemoteSessionManagementServiceImpl.java +++ b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/RemoteSessionManagementServiceImpl.java @@ -45,6 +45,7 @@ import java.util.Date; import java.util.HashMap; import java.util.LinkedList; import java.util.List; +import java.util.UUID; import java.util.Map; /** @@ -72,66 +73,89 @@ public class RemoteSessionManagementServiceImpl implements RemoteSessionManageme sessionQueryParamList.add(session.getQueryString()); sessionQueryParam.put(RemoteSessionConstants.QUERY_STRING, sessionQueryParamList); - // Validate the token - OAuthAuthenticator oAuthAuthenticator = RemoteSessionManagementDataHolder.getInstance().getOauthAuthenticator(); - AuthenticationInfo authenticationInfo = oAuthAuthenticator.isAuthenticated(sessionQueryParam); + if (operationId == null) { + // Validate the token + OAuthAuthenticator oAuthAuthenticator = RemoteSessionManagementDataHolder.getInstance().getOauthAuthenticator(); + AuthenticationInfo authenticationInfo = oAuthAuthenticator.isAuthenticated(sessionQueryParam); - if (authenticationInfo != null && authenticationInfo.isAuthenticated()) { - try { - PrivilegedCarbonContext.startTenantFlow(); - PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(authenticationInfo - .getTenantDomain() - , true); - PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(authenticationInfo.getUsername()); - if (deviceId != null && !deviceId.isEmpty() && deviceType != null && !deviceType.isEmpty()) { - DeviceIdentifier deviceIdentifier = new DeviceIdentifier(); - deviceIdentifier.setId(deviceId); - deviceIdentifier.setType(deviceType); + if (authenticationInfo != null && authenticationInfo.isAuthenticated()) { + try { + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(authenticationInfo + .getTenantDomain() + , true); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(authenticationInfo.getUsername()); + if (deviceId != null && !deviceId.isEmpty() && deviceType != null && !deviceType.isEmpty()) { + DeviceIdentifier deviceIdentifier = new DeviceIdentifier(); + deviceIdentifier.setId(deviceId); + deviceIdentifier.setType(deviceType); + + // Check authorization of user for given device + boolean userAuthorized = RemoteSessionManagementDataHolder.getInstance() + .getDeviceAccessAuthorizationService() + .isUserAuthorized(deviceIdentifier, authenticationInfo.getUsername()); + if (userAuthorized) { + // set common settings for session + session.setMaxBinaryMessageBufferSize(RemoteSessionManagementDataHolder.getInstance() + .getMaxMessageBufferSize()); + session.setMaxTextMessageBufferSize(RemoteSessionManagementDataHolder.getInstance() + .getMaxMessageBufferSize()); + session.setMaxIdleTimeout(RemoteSessionManagementDataHolder.getInstance().getMaxIdleTimeout()); - // Check authorization of user for given device - boolean userAuthorized = RemoteSessionManagementDataHolder.getInstance() - .getDeviceAccessAuthorizationService() - .isUserAuthorized(deviceIdentifier, authenticationInfo.getUsername()); - if (userAuthorized) { - // set common settings for session - session.setMaxBinaryMessageBufferSize(RemoteSessionManagementDataHolder.getInstance() - .getMaxMessageBufferSize()); - session.setMaxTextMessageBufferSize(RemoteSessionManagementDataHolder.getInstance() - .getMaxMessageBufferSize()); - session.setMaxIdleTimeout(RemoteSessionManagementDataHolder.getInstance().getMaxIdleTimeout()); + // if session initiated using operation id means request came from device +// if (operationId != null) { +// // create new device session +// initializeDeviceSession(session, authenticationInfo.getTenantDomain(), deviceType, deviceId, +// operationId); +// } else { + // create new client session + initializeClientSession(session, authenticationInfo.getTenantDomain(), deviceType, + deviceId); +// } + log.info("Current remote sessions count: " + RemoteSessionManagementDataHolder.getInstance() + .getSessionMap().size()); - // if session initiated using operation id means request came from device - if (operationId != null) { - // create new device session - initializeDeviceSession(session, authenticationInfo.getTenantDomain(), deviceType, deviceId, - operationId); } else { - // create new client session - initializeClientSession(session, authenticationInfo.getTenantDomain(), deviceType, - deviceId); + throw new RemoteSessionManagementException("Missing device Id or type "); } - log.info("Current remote sessions count: " + RemoteSessionManagementDataHolder.getInstance() - .getSessionMap().size()); - } else { - throw new RemoteSessionManagementException("Missing device Id or type "); + throw new RemoteSessionManagementException("Unauthorized Access for the device Type : " + deviceType + + " , deviceId : " + deviceId); } - } else { - throw new RemoteSessionManagementException("Unauthorized Access for the device Type : " + deviceType - + " , deviceId : " + deviceId); + } catch (OperationManagementException | InvalidDeviceException e) { + throw new RemoteSessionManagementException("Error occurred while adding initial operation for the " + + "device Type : " + deviceType + " , deviceId : " + deviceId); + } catch (DeviceAccessAuthorizationException e) { + throw new RemoteSessionManagementException("Error occurred while device access authorization for the " + + "device Type : " + deviceType + " , " + "deviceId : " + deviceId); + } finally { + PrivilegedCarbonContext.endTenantFlow(); } - } catch (OperationManagementException | InvalidDeviceException e) { - throw new RemoteSessionManagementException("Error occurred while adding initial operation for the " + - "device Type : " + deviceType + " , deviceId : " + deviceId); - } catch (DeviceAccessAuthorizationException e) { - throw new RemoteSessionManagementException("Error occurred while device access authorization for the " + - "device Type : " + deviceType + " , " + "deviceId : " + deviceId); - } finally { - PrivilegedCarbonContext.endTenantFlow(); + + } else { + throw new RemoteSessionManagementException("Invalid token"); } } else { - throw new RemoteSessionManagementException("Invalid token"); + // set common settings for session + session.setMaxBinaryMessageBufferSize(RemoteSessionManagementDataHolder.getInstance() + .getMaxMessageBufferSize()); + session.setMaxTextMessageBufferSize(RemoteSessionManagementDataHolder.getInstance() + .getMaxMessageBufferSize()); + session.setMaxIdleTimeout(RemoteSessionManagementDataHolder.getInstance().getMaxIdleTimeout()); + String uuid = session.getQueryString(); + + if(uuid != null && uuid.isEmpty()){ + log.error("Could not find a UUID related to the remote session"); + } else { + String tenantDomain = RemoteSessionManagementDataHolder.getInstance().getUuidToTenantMap().remove(uuid); + if(tenantDomain == null || tenantDomain.isEmpty()){ + log.error("Invalid UUID, could not create the remote session"); + } else { + // create new device session + initializeDeviceSession(session, tenantDomain, deviceType, deviceId, operationId, uuid); + } + } } } @@ -194,6 +218,7 @@ public class RemoteSessionManagementServiceImpl implements RemoteSessionManageme .getId()); if (remoteSession != null) { //String operationId = remoteSession.getOperationId(); + RemoteSessionManagementDataHolder.getInstance().getUuidToTenantMap().remove(remoteSession.getUuidToValidateDevice()); String deviceKey = remoteSession.getTenantDomain() + "/" + remoteSession.getDeviceType() + "/" + remoteSession.getDeviceId(); RemoteSession lastSession = RemoteSessionManagementDataHolder.getInstance() @@ -239,8 +264,9 @@ public class RemoteSessionManagementServiceImpl implements RemoteSessionManageme private void initializeClientSession(Session session, String tenantDomain, String deviceType, String deviceId) throws RemoteSessionManagementException, OperationManagementException, InvalidDeviceException { + String uuidToValidateDevice = UUID.randomUUID().toString(); RemoteSession clientRemote = new RemoteSession(session, tenantDomain, deviceType, deviceId, RemoteSessionConstants - .CONNECTION_TYPE.CLIENT); + .CONNECTION_TYPE.CLIENT, uuidToValidateDevice); String deviceKey = tenantDomain + "/" + deviceType + "/" + deviceId; // Create new remote control operation to start the session RemoteSession activeSession = RemoteSessionManagementDataHolder.getInstance().getActiveDeviceClientSessionMap @@ -277,6 +303,12 @@ public class RemoteSessionManagementServiceImpl implements RemoteSessionManageme operation.setControl(Operation.Control.NO_REPEAT); JSONObject payload = new JSONObject(); payload.put("serverUrl", RemoteSessionManagementDataHolder.getInstance().getServerUrl()); + payload.put("uuidToValidateDevice", uuidToValidateDevice); + String uuidToTenantMap = RemoteSessionManagementDataHolder.getInstance().getUuidToTenantMap + ().putIfAbsent(uuidToValidateDevice, tenantDomain); + if (log.isDebugEnabled()) { + log.debug("UUID " + uuidToTenantMap + " is generated against the tenant : " + tenantDomain); + } operation.setPayLoad(payload.toString()); String date = new SimpleDateFormat(RemoteSessionConstants.DATE_FORMAT_NOW).format(new Date()); operation.setCreatedTimeStamp(date); @@ -287,6 +319,7 @@ public class RemoteSessionManagementServiceImpl implements RemoteSessionManageme clientRemote.setOperationId(activity.getActivityId().replace(DeviceManagementConstants .OperationAttributes.ACTIVITY, "")); RemoteSessionManagementDataHolder.getInstance().getSessionMap().put(session.getId(), clientRemote); + log.info("Client remote session opened for session id: " + session.getId() + " device Type : " + deviceType + " , " + "deviceId : " + deviceId); } else { @@ -307,7 +340,7 @@ public class RemoteSessionManagementServiceImpl implements RemoteSessionManageme * @throws RemoteSessionManagementException throws when session has errors with accessing device resources */ private void initializeDeviceSession(Session session, String tenantDomain, String deviceType, String deviceId, - String operationId) throws RemoteSessionManagementException { + String operationId, String uuidToValidateDevice) throws RemoteSessionManagementException { String deviceKey = tenantDomain + "/" + deviceType + "/" + deviceId; RemoteSession activeSession = RemoteSessionManagementDataHolder.getInstance() .getActiveDeviceClientSessionMap().get(deviceKey); @@ -317,7 +350,7 @@ public class RemoteSessionManagementServiceImpl implements RemoteSessionManageme if (clientRemote != null) { if (clientRemote.getOperationId().equals(operationId)) { RemoteSession deviceRemote = new RemoteSession(session, tenantDomain, deviceType, deviceId, - RemoteSessionConstants.CONNECTION_TYPE.DEVICE); + RemoteSessionConstants.CONNECTION_TYPE.DEVICE, uuidToValidateDevice); deviceRemote.setOperationId(operationId); deviceRemote.setPeerSession(clientRemote); clientRemote.setPeerSession(deviceRemote); diff --git a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/dto/RemoteSession.java b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/dto/RemoteSession.java index 5b2337c335..79bb31b2f3 100644 --- a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/dto/RemoteSession.java +++ b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/dto/RemoteSession.java @@ -34,7 +34,11 @@ import java.nio.ByteBuffer; public class RemoteSession { private static final Log log = LogFactory.getLog(RemoteSession.class); - private String tenantDomain, operationId, deviceType, deviceId; + private String tenantDomain; + private String operationId; + private String deviceType; + private String deviceId; + private String uuidToValidateDevice; private long lastMessageTimeStamp = System.currentTimeMillis(); private RemoteSession peerSession; private Session mySession; @@ -45,12 +49,13 @@ public class RemoteSession { private RemoteSessionConstants.CONNECTION_TYPE connectionType; public RemoteSession(Session session, String tenantDomain, String deviceType, String deviceId, - RemoteSessionConstants.CONNECTION_TYPE connectionType) { + RemoteSessionConstants.CONNECTION_TYPE connectionType, String uuidToValidateDevice) { this.mySession = session; this.deviceType = deviceType; this.deviceId = deviceId; this.tenantDomain = tenantDomain; this.connectionType = connectionType; + this.uuidToValidateDevice = uuidToValidateDevice; maxMessagesPerSecond = RemoteSessionManagementDataHolder.getInstance().getMaxMessagesPerSecond(); messageAllowance = maxMessagesPerSecond; messageRatePerSecond = (double) maxMessagesPerSecond / 1000; @@ -109,6 +114,10 @@ public class RemoteSession { } } + public String getUuidToValidateDevice() { + return uuidToValidateDevice; + } + public Session getMySession() { return mySession; } diff --git a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/internal/RemoteSessionManagementDataHolder.java b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/internal/RemoteSessionManagementDataHolder.java index ef92860f6f..d1c2f058cd 100644 --- a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/internal/RemoteSessionManagementDataHolder.java +++ b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/internal/RemoteSessionManagementDataHolder.java @@ -43,6 +43,11 @@ public class RemoteSessionManagementDataHolder { private OAuthAuthenticator oAuthAuthenticator; private Map activeDeviceClientSessionMap = new ConcurrentHashMap(); private Map sessionMap = new ConcurrentHashMap(); + private Map uuidToTenantMap = new ConcurrentHashMap<>(); + + public Map getUuidToTenantMap() { + return uuidToTenantMap; + } public static RemoteSessionManagementDataHolder getInstance() { return thisInstance;