diff --git a/server/src/uds/core/osmanagers/BaseOsManager.py b/server/src/uds/core/osmanagers/BaseOsManager.py index cca8f16d8..deea84883 100644 --- a/server/src/uds/core/osmanagers/BaseOsManager.py +++ b/server/src/uds/core/osmanagers/BaseOsManager.py @@ -116,6 +116,14 @@ class OSManager(Module): ''' pass + @classmethod + def transformsUserOrPasswordForService(cls): + ''' + Helper method that informs if the os manager transforms the username and/or the password. + This is used from DeployedService + ''' + return cls.processUserPassword != OSManager.processUserPassword + def processUserPassword(self, service, username, password): ''' This will be invoked prior to passsing username/password to Transport. diff --git a/server/src/uds/core/transports/BaseTransport.py b/server/src/uds/core/transports/BaseTransport.py index a9336d770..6d26f8f28 100644 --- a/server/src/uds/core/transports/BaseTransport.py +++ b/server/src/uds/core/transports/BaseTransport.py @@ -109,7 +109,7 @@ class Transport(Module): ''' return cls.getConnectionInfo != Transport.getConnectionInfo - def getConnectionInfo(self, userService, user, password): + def getConnectionInfo(self, service, user, password): ''' This method must provide information about connection. We don't have to implement it, but if we wont to allow some types of connections @@ -117,7 +117,7 @@ class Transport(Module): kind of terminals/application will not work Args: - userService: DeployedUserService for witch we are rendering the connection (db model) + userService: DeployedUserService for witch we are rendering the connection (db model), or DeployedService (db model) user: user (dbUser) logged in pass: password used in authentication @@ -125,8 +125,14 @@ class Transport(Module): 'protocol': protocol to use, (there are a few standard defined in 'protocols.py', if yours does not fit those, use your own name 'username': username (transformed if needed to) used to login to service 'password': password (transformed if needed to) used to login to service + 'domain': domain (extracted from username or wherever) that will be used. (Not necesarily an AD domain) + + :note: The provided service can be an user service or an deployed service (parent of user services). + I have implemented processUserPassword in both so in most cases we do not need if the service is + DeployedService or UserService. In case of processUserPassword for an DeployedService, no transformation + is done, because there is no relation at that level between user and service. ''' - return {'protocol': protocols.NONE, 'usename': '', 'password': ''} + return {'protocol': protocols.NONE, 'username': '', 'password': '', 'domain': ''} def renderForHtml(self, userService, id, ip, os, user, password): ''' diff --git a/server/src/uds/core/transports/protocols.py b/server/src/uds/core/transports/protocols.py index 451ad4b2b..ea0b53146 100644 --- a/server/src/uds/core/transports/protocols.py +++ b/server/src/uds/core/transports/protocols.py @@ -41,4 +41,5 @@ REMOTEFX = 'remotefx' HDX = 'hdx' ICA = 'ica' NX = 'nx' -X11 = 'x11' \ No newline at end of file +X11 = 'x11' +OTHER = 'other' \ No newline at end of file diff --git a/server/src/uds/models.py b/server/src/uds/models.py index 5f1439e45..fd253d154 100644 --- a/server/src/uds/models.py +++ b/server/src/uds/models.py @@ -832,6 +832,20 @@ class DeployedService(models.Model): except Exception: return None + def transformsUserOrPasswordForService(self): + return self.osmanager.getType().transformsUserOrPasswordForService() + + def processUserPassword(self, username, password): + ''' + This method is provided for consistency between UserService and DeployedService + There is no posibility to check the username and password that a user will use to + connect to a service at this level, because here there is no relation between both. + + The only function of this method is allow Transport to transform username/password in + getConnectionInfo without knowing if it is requested by a DeployedService or an UserService + ''' + return [username, password] + def setState(self, state, save = True): ''' Updates the state of this object and, optionally, saves it @@ -1280,7 +1294,31 @@ class UserService(models.Model): ''' return self.getEnvironment().storage().get(name) + def transformsUserOrPasswordForService(self): + ''' + If the os manager changes the username or the password, this will return True + ''' + return self.deployed_service.transformsUserOrPasswordForService() + def processUserPassword(self, username, password): + ''' + Before accessing a service by a transport, we can request + the service to "transform" the username & password that the transport + will use to connect to that service. + + This method is here so transport USE it before using the username/password + provided by user or by own transport configuration. + + Args: + username: the username that will be used to connect to service + password: the password that will be used to connect to service + + Return: + An array of two elements, first is transformed username, second is + transformed password. + + :note: This method MUST be invoked by transport before using credentials passed to getHtml. + ''' ds = self.deployed_service serviceInstance = ds.service.getInstance() if serviceInstance.needsManager is False: diff --git a/server/src/uds/transports/RDP/RDPTransport.py b/server/src/uds/transports/RDP/RDPTransport.py index 7310661bc..38e402954 100644 --- a/server/src/uds/transports/RDP/RDPTransport.py +++ b/server/src/uds/transports/RDP/RDPTransport.py @@ -105,6 +105,31 @@ class RDPTransport(Transport): self.cache().put(ip, 'N', READY_CACHE_TIMEOUT) return ready == 'Y' + def getConnectionInfo(self, service, user, password): + from uds.core.transports import protocols + + username = user.getUsernameForAuth() + + proc = username.split('@') + if len(proc) > 1: + domain = proc[1] + else: + domain = '' + + username = proc[0] + if self._fixedName is not '': + username = self._fixedName + if self._fixedPassword is not '': + password = self._fixedPassword + if self._fixedDomain is not '': + domain = self._fixedDomain; + if self._useEmptyCreds is True: + username, password, domain = '','','' + + username, password = service.processUserPassword(username, password) + + return {'protocol': protocols.RDP, 'username': username, 'password': password, 'domain': domain} + def renderForHtml(self, userService, id, ip, os, user, password): # We use helper to keep this clean username = user.getUsernameForAuth()