Ejemplo n.º 1
0
 def guiField(self, value):
     vals = []
     for v in self._values:
         vals.append({'id': v[0], 'text': _(v[1])})
     return gui.ChoiceField(label=_(self._label),
                            rdonly=False,
                            values=vals,
                            defvalue=value,
                            tooltip=_(self._label))
Ejemplo n.º 2
0
class ListReportUsers(ListReport):
    filename = 'users.pdf'

    def initialize(self, values):
        if values:
            auth = Authenticator.objects.get(uuid=self.authenticator.value)
            self.filename = auth.name + '.pdf'

    authenticator = gui.ChoiceField(
        label=_("Authenticator"),
        order=1,
        tooltip=_('Authenticator from where to list users'),
        required=True)

    name = _('Users list')  # Report name
    description = _('List users of platform')  # Report description
    uuid = '8cd1cfa6-ed48-11e4-83e5-10feed05884b'

    def initGui(self):
        logger.debug('Initializing gui')
        vals = [
            gui.choiceItem(v.uuid, v.name)
            for v in Authenticator.objects.all()
        ]

        self.authenticator.setValues(vals)

    def generate(self):
        auth = Authenticator.objects.get(uuid=self.authenticator.value)
        users = auth.users.order_by('name')

        return self.templateAsPDF(
            'uds/reports/lists/users.html',
            dct={
                'users': users,
                'auth': auth.name,
            },
            header=ugettext('Users List for {}').format(auth.name),
            water=ugettext('UDS Report of users in {}').format(auth.name))
Ejemplo n.º 3
0
class ListReportUsers(ListReport):
    filename = 'users.pdf'

    def initialize(self, values):
        if values:
            auth = Authenticator.objects.get(uuid=self.authenticator.value)
            self.filename = auth.name + '.pdf'

    authenticator = gui.ChoiceField(
        label=_("Authenticator"),
        order=1,
        tooltip=_('Authenticator from where to list users'),
        required=True)

    name = _('Users list')  # Report name
    description = _('List users of platform')  # Report description
    uuid = '8cd1cfa6-ed48-11e4-83e5-10feed05884b'

    def initGui(self):
        logger.debug('Initializing gui')
        vals = [
            gui.choiceItem(v.uuid, v.name)
            for v in Authenticator.objects.all()
        ]

        self.authenticator.setValues(vals)

    def generate(self):
        auth = Authenticator.objects.get(uuid=self.authenticator.value)
        users = auth.users.order_by('name')

        output = StringIO.StringIO()

        report = UsersReport(queryset=users)
        report.title = _('Users List for {}').format(auth.name)
        report.generate_by(PDFGenerator, filename=output)
        return output.getvalue()
Ejemplo n.º 4
0
class BaseRDPTransport(Transport):
    """
    Provides access via RDP to service.
    This transport can use an domain. If username processed by authenticator contains '@', it will split it and left-@-part will be username, and right password
    """
    iconFile = 'rdp.png'
    protocol = protocols.RDP

    useEmptyCreds = gui.CheckBoxField(
        label=_('Empty creds'),
        order=11,
        tooltip=_('If checked, the credentials used to connect will be emtpy'),
        tab=gui.CREDENTIALS_TAB)
    fixedName = gui.TextField(
        label=_('Username'),
        order=12,
        tooltip=_(
            'If not empty, this username will be always used as credential'),
        tab=gui.CREDENTIALS_TAB)
    fixedPassword = gui.PasswordField(
        label=_('Password'),
        order=13,
        tooltip=_(
            'If not empty, this password will be always used as credential'),
        tab=gui.CREDENTIALS_TAB)
    withoutDomain = gui.CheckBoxField(
        label=_('Without Domain'),
        order=14,
        tooltip=
        _('If checked, the domain part will always be emptied (to connect to xrdp for example is needed)'
          ),
        tab=gui.CREDENTIALS_TAB)
    fixedDomain = gui.TextField(
        label=_('Domain'),
        order=15,
        tooltip=
        _('If not empty, this domain will be always used as credential (used as DOMAIN\\user)'
          ),
        tab=gui.CREDENTIALS_TAB)

    allowSmartcards = gui.CheckBoxField(
        label=_('Allow Smartcards'),
        order=20,
        tooltip=_(
            'If checked, this transport will allow the use of smartcards'),
        tab=gui.PARAMETERS_TAB)
    allowPrinters = gui.CheckBoxField(
        label=_('Allow Printers'),
        order=21,
        tooltip=_(
            'If checked, this transport will allow the use of user printers'),
        tab=gui.PARAMETERS_TAB)
    allowDrives = gui.ChoiceField(
        label=_('Allow Drives'),
        order=22,
        tooltip=_('Local drives redirection allowed'),
        defvalue='false',
        values=[
            {
                'id': 'false',
                'text': 'None'
            },
            {
                'id': 'dynamic',
                'text': 'Only PnP drives'
            },
            {
                'id': 'true',
                'text': 'All drives'
            },
        ],
        tab=gui.PARAMETERS_TAB)

    allowSerials = gui.CheckBoxField(
        label=_('Allow Serials'),
        order=23,
        tooltip=_(
            'If checked, this transport will allow the use of user serial ports'
        ),
        tab=gui.PARAMETERS_TAB)
    allowClipboard = gui.CheckBoxField(
        label=_('Enable clipboard'),
        order=24,
        tooltip=_('If checked, copy-paste functions will be allowed'),
        tab=gui.PARAMETERS_TAB,
        defvalue=gui.TRUE)
    allowAudio = gui.CheckBoxField(
        label=_('Enable sound'),
        order=25,
        tooltip=_('If checked, sound will be redirected.'),
        tab=gui.PARAMETERS_TAB,
        defvalue=gui.TRUE)
    credssp = gui.CheckBoxField(
        label=_('Credssp Support'),
        order=26,
        tooltip=_('If checked, will enable Credentials Provider Support)'),
        tab=gui.PARAMETERS_TAB,
        defvalue=gui.TRUE)

    screenSize = gui.ChoiceField(label=_('Screen Size'),
                                 order=30,
                                 tooltip=_('Screen size for this transport'),
                                 defvalue='-1x-1',
                                 values=[
                                     {
                                         'id': '640x480',
                                         'text': '640x480'
                                     },
                                     {
                                         'id': '800x600',
                                         'text': '800x600'
                                     },
                                     {
                                         'id': '1024x768',
                                         'text': '1024x768'
                                     },
                                     {
                                         'id': '1366x768',
                                         'text': '1366x768'
                                     },
                                     {
                                         'id': '1920x1080',
                                         'text': '1920x1080'
                                     },
                                     {
                                         'id': '-1x-1',
                                         'text': 'Full screen'
                                     },
                                 ],
                                 tab=gui.DISPLAY_TAB)

    colorDepth = gui.ChoiceField(label=_('Color depth'),
                                 order=31,
                                 tooltip=_('Color depth for this connection'),
                                 defvalue='24',
                                 values=[
                                     {
                                         'id': '8',
                                         'text': '8'
                                     },
                                     {
                                         'id': '16',
                                         'text': '16'
                                     },
                                     {
                                         'id': '24',
                                         'text': '24'
                                     },
                                     {
                                         'id': '32',
                                         'text': '32'
                                     },
                                 ],
                                 tab=gui.DISPLAY_TAB)

    wallpaper = gui.CheckBoxField(
        label=_('Wallpaper/theme'),
        order=32,
        tooltip=
        _('If checked, the wallpaper and themes will be shown on machine (better user experience, more bandwidth)'
          ),
        tab=gui.DISPLAY_TAB)
    multimon = gui.CheckBoxField(
        label=_('Multiple monitors'),
        order=33,
        tooltip=
        _('If checked, all client monitors will be used for displaying (only works on windows clients)'
          ),
        tab=gui.DISPLAY_TAB)
    aero = gui.CheckBoxField(
        label=_('Allow Desk.Comp.'),
        order=34,
        tooltip=_('If checked, desktop composition will be allowed'),
        tab=gui.DISPLAY_TAB)
    smooth = gui.CheckBoxField(
        label=_('Font Smoothing'),
        order=35,
        tooltip=_('If checked, fonts smoothing will be allowed'),
        tab=gui.DISPLAY_TAB)
    showConnectionBar = gui.CheckBoxField(
        label=_('Connection Bar'),
        order=36,
        tooltip=_(
            'If checked, connection bar will be shown (only on Windows clients)'
        ),
        tab=gui.DISPLAY_TAB,
        defvalue=gui.TRUE)

    multimedia = gui.CheckBoxField(
        label=_('Multimedia sync'),
        order=40,
        tooltip=
        _('If checked. Linux client will use multimedia parameter for xfreerdp'
          ),
        tab='Linux Client')
    alsa = gui.CheckBoxField(
        label=_('Use Alsa'),
        order=41,
        tooltip=
        _('If checked, Linux client will try to use ALSA, otherwise Pulse will be used'
          ),
        tab='Linux Client')
    redirectHome = gui.CheckBoxField(
        label=_('Redirect home folder'),
        order=42,
        tooltip=_(
            'If checked, Linux client will try to redirect /home local folder'
        ),
        tab='Linux Client',
        defvalue=gui.FALSE)
    printerString = gui.TextField(
        label=_('Printer string'),
        order=43,
        tooltip=
        _('If printer is checked, the printer string used with xfreerdp client'
          ),
        tab='Linux Client')
    smartcardString = gui.TextField(
        label=_('Smartcard string'),
        order=44,
        tooltip=
        _('If smartcard is checked, the smartcard string used with xfreerdp client'
          ),
        tab='Linux Client')
    customParameters = gui.TextField(
        label=_('Custom parameters'),
        order=45,
        tooltip=
        _('If not empty, extra parameter to include for Linux Client (for example /usb:id,dev:054c:0268, or aything compatible with your xfreerdp client)'
          ),
        tab='Linux Client')

    def isAvailableFor(self, userService, ip):
        """
        Checks if the transport is available for the requested destination ip
        Override this in yours transports
        """
        logger.debug('Checking availability for {0}'.format(ip))
        ready = self.cache.get(ip)
        if ready is None:
            # Check again for ready
            if self.testServer(userService, ip, '3389') is True:
                self.cache.put(ip, 'Y', READY_CACHE_TIMEOUT)
                return True
            else:
                self.cache.put(ip, 'N', READY_CACHE_TIMEOUT)
        return ready == 'Y'

    def processedUser(self, userService, userName):
        v = self.processUserPassword(userService, userName, '')
        return v['username']

    def processUserPassword(self, service, user, password):
        username = user.getUsernameForAuth()

        if self.fixedName.value != '':
            username = self.fixedName.value

        proc = username.split('@')
        if len(proc) > 1:
            domain = proc[1]
        else:
            domain = ''
        username = proc[0]

        if self.fixedPassword.value != '':
            password = self.fixedPassword.value
        if self.fixedDomain.value != '':
            domain = self.fixedDomain.value
        if self.useEmptyCreds.isTrue():
            username, password, domain = '', '', ''

        if self.withoutDomain.isTrue():
            domain = ''

        if domain != '':  # If has domain
            if '.' in domain:  # Dotter domain form
                username = username + '@' + domain
                domain = ''
            else:  # In case of a NETBIOS domain (not recomended), join it so processUserPassword can deal with it
                username = domain + '\\' + username
                domain = ''

        # Temporal "fix" to check if we do something on processUserPassword

        # Fix username/password acording to os manager
        username, password = service.processUserPassword(username, password)

        # Recover domain name if needed
        if '\\' in username:
            username, domain = username.split('\\')

        return {
            'protocol': self.protocol,
            'username': username,
            'password': password,
            'domain': domain
        }

    def getConnectionInfo(self, service, user, password):
        return self.processUserPassword(service, user, password)

    def getScript(self, scriptName, osName, params) -> Tuple[str, str, dict]:
        # Reads script
        scriptName = scriptName.format(osName)
        with open(os.path.join(os.path.dirname(__file__), scriptName)) as f:
            script = f.read()
        # Reads signature
        with open(
                os.path.join(os.path.dirname(__file__),
                             scriptName + '.signature')) as f:
            signature = f.read()
        return script, signature, params
Ejemplo n.º 5
0
class WindowsOsManager(osmanagers.OSManager):
    typeName = _('Windows Basic OS Manager')
    typeType = 'WindowsManager'
    typeDescription = _(
        'Os Manager to control windows machines without domain.')
    iconFile = 'wosmanager.png'
    servicesType = (serviceTypes.VDI, )

    onLogout = gui.ChoiceField(
        label=_('Logout Action'),
        order=10,
        rdonly=True,
        tooltip=_('What to do when user logs out from service'),
        values=[
            {
                'id': 'keep',
                'text': ugettext_lazy('Keep service assigned')
            },
            {
                'id': 'remove',
                'text': ugettext_lazy('Remove service')
            },
            {
                'id':
                'keep-always',
                'text':
                ugettext_lazy('Keep service assigned even on new publication')
            },
        ],
        defvalue='keep')

    idle = gui.NumericField(
        label=_("Max.Idle time"),
        length=4,
        defvalue=-1,
        rdonly=False,
        order=11,
        tooltip=
        _('Maximum idle time (in seconds) before session is automatically closed to the user (<= 0 means no max. idle time)'
          ),
        required=True)

    @staticmethod
    def validateLen(length):
        try:
            length = int(length)
        except Exception:
            raise osmanagers.OSManager.ValidationException(
                _('Length must be numeric!!'))
        if length > 6 or length < 1:
            raise osmanagers.OSManager.ValidationException(
                _('Length must be betwen 1 and 6'))
        return length

    def __setProcessUnusedMachines(self):
        self.processUnusedMachines = self._onLogout == 'remove'

    def __init__(self, environment, values):
        super(WindowsOsManager, self).__init__(environment, values)
        if values is not None:
            self._onLogout = values['onLogout']
            self._idle = int(values['idle'])
        else:
            self._onLogout = ''
            self._idle = -1

        self.__setProcessUnusedMachines()

    def isRemovableOnLogout(self, userService):
        '''
        Says if a machine is removable on logout
        '''
        if userService.in_use == False:
            if (self._onLogout
                    == 'remove') or (not userService.isValidPublication()
                                     and self._onLogout == 'keep'):
                return True

        return False

    def release(self, service):
        pass

    def getName(self, service):
        """
        gets name from deployed
        """
        return service.getName()

    def infoVal(self, service):
        return 'rename:' + self.getName(service)

    def infoValue(self, service):
        return 'rename\r' + self.getName(service)

    def notifyIp(self, uid, service, data):
        si = service.getInstance()

        ip = ''
        # Notifies IP to deployed
        for p in data['ips']:
            if p[0].lower() == uid.lower():
                si.setIp(p[1])
                ip = p[1]
                break

        self.logKnownIp(service, ip)
        service.updateData(si)

    def doLog(self, service, data, origin=log.OSMANAGER):
        # Stores a log associated with this service
        try:
            msg, level = data.split('\t')
            try:
                level = int(level)
            except Exception:
                logger.debug('Do not understand level {}'.format(level))
                level = log.INFO

            log.doLog(service, level, msg, origin)
        except Exception:
            logger.exception('WindowsOs Manager message log: ')
            log.doLog(service, log.ERROR, "do not understand {0}".format(data),
                      origin)

    # default "ready received" does nothing
    def readyReceived(self, userService, data):
        pass

    def process(self, userService, msg, data, options=None):
        """
        We understand this messages:
        * msg = info, data = None. Get information about name of machine (or domain, in derived WinDomainOsManager class) (old method)
        * msg = information, data = None. Get information about name of machine (or domain, in derived WinDomainOsManager class) (new method)
        * msg = logon, data = Username, Informs that the username has logged in inside the machine
        * msg = logoff, data = Username, Informs that the username has logged out of the machine
        * msg = ready, data = None, Informs machine ready to be used
        """
        logger.info(
            "Invoked WindowsOsManager for {0} with params: {1},{2}".format(
                userService, msg, data))

        if msg in ('ready', 'ip'):
            if not isinstance(
                    data, dict
            ):  # Old actors, previous to 2.5, convert it information..
                data = {
                    'ips': [v.split('=') for v in data.split(',')],
                    'hostname': userService.friendly_name
                }

        # We get from storage the name for this userService. If no name, we try to assign a new one
        ret = "ok"
        notifyReady = False
        doRemove = False
        state = userService.os_state
        if msg == "info":
            ret = self.infoVal(userService)
            state = State.PREPARING
        elif msg == "information":
            ret = self.infoValue(userService)
            state = State.PREPARING
        elif msg == "log":
            self.doLog(userService, data, log.ACTOR)
        elif msg == "logon" or msg == 'login':
            if '\\' not in data:
                self.loggedIn(userService, data)
            userService.setInUse(True)
            # We get the userService logged hostname & ip and returns this
            ip, hostname = userService.getConnectionSource()
            deadLine = userService.deployed_service.getDeadline()
            if userService.getProperty('actor_version', '0.0.0') >= '2.0.0':
                ret = "{0}\t{1}\t{2}".format(
                    ip, hostname, 0 if deadLine is None else deadLine)
            else:
                ret = "{0}\t{1}".format(ip, hostname)
        elif msg == "logoff" or msg == 'logout':
            self.loggedOut(userService, data)
            doRemove = self.isRemovableOnLogout(userService)
        elif msg == "ip":
            # This ocurss on main loop inside machine, so userService is usable
            state = State.USABLE
            self.notifyIp(userService.unique_id, userService, data)
        elif msg == "ready":
            self.toReady(userService)
            state = State.USABLE
            notifyReady = True
            self.notifyIp(userService.unique_id, userService, data)
            self.readyReceived(userService, data)

        userService.setOsState(state)

        # If notifyReady is not true, save state, let UserServiceManager do it for us else
        if doRemove is True:
            userService.release()
        else:
            if notifyReady is False:
                userService.save(update_fields=[
                    'in_use', 'in_use_date', 'os_state', 'state', 'data'
                ])
            else:
                logger.debug('Notifying ready')
                UserServiceManager.manager().notifyReadyFromOsManager(
                    userService, '')
        logger.debug('Returning {} to {} message'.format(ret, msg))
        if options is not None and options.get('scramble', True) is False:
            return ret
        return scrambleMsg(ret)

    def processUserPassword(self, service, username, password):
        if service.getProperty('sso_available') == '1':
            # Generate a ticket, store it and return username with no password
            domain = ''
            if '@' in username:
                username, domain = username.split('@')
            elif '\\' in username:
                username, domain = username.split('\\')

            creds = {
                'username': username,
                'password': password,
                'domain': domain
            }
            ticket = TicketStore.create(
                creds, validator=None,
                validity=300)  # , owner=SECURE_OWNER, secure=True)
            return ticket, ''
        else:
            return osmanagers.OSManager.processUserPassword(
                self, service, username, password)

    def processUnused(self, userService):
        """
        This will be invoked for every assigned and unused user service that has been in this state at least 1/2 of Globalconfig.CHECK_UNUSED_TIME
        This function can update userService values. Normal operation will be remove machines if this state is not valid
        """
        if self.isRemovableOnLogout(userService):
            userService.remove()

    def isPersistent(self):
        return self._onLogout == 'keep-always'

    def checkState(self, service):
        logger.debug('Checking state for service {0}'.format(service))
        return State.RUNNING

    def maxIdle(self):
        """
        On production environments, will return no idle for non removable machines
        """
        if self._idle <= 0:  # or (settings.DEBUG is False and self._onLogout != 'remove'):
            return None

        return self._idle

    def marshal(self):
        """
        Serializes the os manager data so we can store it in database
        """
        return '\t'.join(['v2', self._onLogout,
                          str(self._idle)]).encode('utf8')

    def unmarshal(self, s):
        data = s.decode('utf8').split('\t')
        try:
            if data[0] == 'v1':
                self._onLogout = data[1]
                self._idle = -1
            elif data[0] == 'v2':
                self._onLogout, self._idle = data[1], int(data[2])
        except Exception:
            logger.exception(
                'Exception unmarshalling. Some values left as default ones')

        self.__setProcessUnusedMachines()

    def valuesDict(self):
        return {'onLogout': self._onLogout, 'idle': self._idle}
Ejemplo n.º 6
0
class TSNXTransport(Transport):
    """
    Provides access via NX to service.
    This transport can use an domain. If username processed by authenticator contains '@', it will split it and left-@-part will be username, and right password
    """
    typeName = _('NX v3.5')
    typeType = 'TSNXTransport'
    typeDescription = _('NX protocol v3.5. Tunneled connection.')
    iconFile = 'nx.png'
    protocol = protocols.NX
    group = TUNNELED_GROUP

    tunnelServer = gui.TextField(label=_('Tunnel server'), order=1, tooltip=_('IP or Hostname of tunnel server sent to client device ("public" ip) and port. (use HOST:PORT format)'), tab=gui.TUNNEL_TAB)
    tunnelCheckServer = gui.TextField(label=_('Tunnel host check'), order=2, tooltip=_('If not empty, this server will be used to check if service is running before assigning it to user. (use HOST:PORT format)'), tab=gui.TUNNEL_TAB)

    useEmptyCreds = gui.CheckBoxField(label=_('Empty creds'), order=3, tooltip=_('If checked, the credentials used to connect will be emtpy'), tab=gui.CREDENTIALS_TAB)
    fixedName = gui.TextField(label=_('Username'), order=4, tooltip=_('If not empty, this username will be always used as credential'), tab=gui.CREDENTIALS_TAB)
    fixedPassword = gui.PasswordField(label=_('Password'), order=5, tooltip=_('If not empty, this password will be always used as credential'), tab=gui.CREDENTIALS_TAB)
    listenPort = gui.NumericField(label=_('Listening port'), length=5, order=6, tooltip=_('Listening port of NX (ssh) at client machine'), defvalue='22')
    connection = gui.ChoiceField(label=_('Connection'), order=7, tooltip=_('Connection speed for this transport (quality)'),
                                 values=[
                                     {'id': 'modem', 'text': 'modem'},
                                     {'id': 'isdn', 'text': 'isdn'},
                                     {'id': 'adsl', 'text': 'adsl'},
                                     {'id': 'wan', 'text': 'wan'},
                                     {'id': 'lan', 'text': 'lan'},
    ], tab=gui.PARAMETERS_TAB)
    session = gui.ChoiceField(label=_('Session'), order=8, tooltip=_('Desktop session'),
                              values=[
                                  {'id': 'gnome', 'text': 'gnome'},
                                  {'id': 'kde', 'text': 'kde'},
                                  {'id': 'cde', 'text': 'cde'},
    ], tab=gui.PARAMETERS_TAB)
    cacheDisk = gui.ChoiceField(label=_('Disk Cache'), order=9, tooltip=_('Cache size en Mb stored at disk'),
                                values=[
                                    {'id': '0', 'text': '0 Mb'},
                                    {'id': '32', 'text': '32 Mb'},
                                    {'id': '64', 'text': '64 Mb'},
                                    {'id': '128', 'text': '128 Mb'},
                                    {'id': '256', 'text': '256 Mb'},
                                    {'id': '512', 'text': '512 Mb'},
    ], tab=gui.PARAMETERS_TAB)
    cacheMem = gui.ChoiceField(label=_('Memory Cache'), order=10, tooltip=_('Cache size en Mb kept at memory'),
                               values=[
                                   {'id': '4', 'text': '4 Mb'},
                                   {'id': '8', 'text': '8 Mb'},
                                   {'id': '16', 'text': '16 Mb'},
                                   {'id': '32', 'text': '32 Mb'},
                                   {'id': '64', 'text': '64 Mb'},
                                   {'id': '128', 'text': '128 Mb'},
    ], tab=gui.PARAMETERS_TAB)

    def __init__(self, environment, values=None):
        super(TSNXTransport, self).__init__(environment, values)
        if values is not None:
            if values['tunnelServer'].find(':') == -1:
                raise Transport.ValidationException(_('Must use HOST:PORT in Tunnel Server Field'))
            self._tunnelServer = values['tunnelServer']
            self._tunnelCheckServer = values['tunnelCheckServer']
            self._useEmptyCreds = gui.strToBool(values['useEmptyCreds'])
            self._fixedName = values['fixedName']
            self._fixedPassword = values['fixedPassword']
            self._listenPort = values['listenPort']
            self._connection = values['connection']
            self._session = values['session']
            self._cacheDisk = values['cacheDisk']
            self._cacheMem = values['cacheMem']
        else:
            self._tunnelServer = ''
            self._tunnelCheckServer = ''
            self._useEmptyCreds = ''
            self._fixedName = ''
            self._fixedPassword = ''
            self._listenPort = ''
            self._connection = ''
            self._session = ''
            self._cacheDisk = ''
            self._cacheMem = ''

    def marshal(self):
        """
        Serializes the transport data so we can store it in database
        """
        return str.join('\t', ['v1', gui.boolToStr(self._useEmptyCreds), self._fixedName, self._fixedPassword, self._listenPort,
                               self._connection, self._session, self._cacheDisk, self._cacheMem, self._tunnelServer, self._tunnelCheckServer])

    def unmarshal(self, string):
        data = string.split('\t')
        if data[0] == 'v1':
            self._useEmptyCreds = gui.strToBool(data[1])
            self._fixedName, self._fixedPassword, self._listenPort, self._connection, self._session, self._cacheDisk, self._cacheMem, self._tunnelServer, self._tunnelCheckServer = data[2:]

    def valuesDict(self):
        return {
            'useEmptyCreds': gui.boolToStr(self._useEmptyCreds),
            'fixedName': self._fixedName,
            'fixedPassword': self._fixedPassword,
            'listenPort': self._listenPort,
            'connection': self._connection,
            'session': self._session,
            'cacheDisk': self._cacheDisk,
            'cacheMem': self._cacheMem,
            'tunnelServer': self._tunnelServer,
            'tunnelCheckServer': self._tunnelCheckServer
        }

    def isAvailableFor(self, userService, ip):
        """
        Checks if the transport is available for the requested destination ip
        Override this in yours transports
        """
        logger.debug('Checking availability for {0}'.format(ip))
        ready = self.cache.get(ip)
        if ready is None:
            # Check again for readyness
            if self.testServer(userService, ip, self._listenPort) is True:
                self.cache.put(ip, 'Y', READY_CACHE_TIMEOUT)
                return True
            else:
                self.cache.put(ip, 'N', READY_CACHE_TIMEOUT)
        return ready == 'Y'

    def getScript(self, script):
        with open(os.path.join(os.path.dirname(__file__), script)) as f:
            data = f.read()
        return data

    def getUDSTransportScript(self, userService, transport, ip, os, user, password, request):
        prefs = user.prefs('nx')

        username = user.getUsernameForAuth()
        proc = username.split('@')
        username = proc[0]
        if self._fixedName is not '':
            username = self._fixedName
        if self._fixedPassword is not '':
            password = self._fixedPassword
        if self._useEmptyCreds is True:
            username, password = '', ''

        tunpass = ''.join(random.choice(string.letters + string.digits) for _i in range(12))
        tunuser = TicketStore.create(tunpass)

        sshServer = self._tunnelServer
        if ':' not in sshServer:
            sshServer += ':443'

        sshHost, sshPort = sshServer.split(':')

        logger.debug('Username generated: {0}, password: {1}'.format(tunuser, tunpass))

        width, height = CommonPrefs.getWidthHeight(prefs)
        # Fix username/password acording to os manager
        username, password = userService.processUserPassword(username, password)

        m = {
            'ip': ip,
            'tunUser': tunuser,
            'tunPass': tunpass,
            'tunHost': sshHost,
            'tunPort': sshPort,
            'password': password,
            'port': self._listenPort
        }

        r = NXFile(username=username, password=password, width=width, height=height)
        r.host = '{address}'
        r.port = '{port}'
        r.connection = self._connection
        r.desktop = self._session
        r.cachedisk = self._cacheDisk
        r.cachemem = self._cacheMem

        os = {
            OsDetector.Windows: 'windows',
            OsDetector.Linux: 'linux',
            OsDetector.Macintosh: 'macosx'

        }.get(os['OS'])

        if os is None:
            return super(self.__class__, self).getUDSTransportScript(userService, transport, ip, os, user, password, request)

        return self.getScript('scripts/{}/tunnel.py'.format(os)).format(
            r=r,
            m=DictAsObj(m),
        )
Ejemplo n.º 7
0
class LinuxOsManager(osmanagers.OSManager):
    typeName = _('Linux OS Manager')
    typeType = 'LinuxManager'
    typeDescription = _('Os Manager to control Linux virtual machines')
    iconFile = 'losmanager.png'

    servicesType = (serviceTypes.VDI, )

    onLogout = gui.ChoiceField(
        label=_('Logout Action'),
        order=10,
        rdonly=True,
        tooltip=_('What to do when user logs out from service'),
        values=[
            {
                'id': 'keep',
                'text': ugettext_lazy('Keep service assigned')
            },
            {
                'id': 'remove',
                'text': ugettext_lazy('Remove service')
            },
            {
                'id':
                'keep-always',
                'text':
                ugettext_lazy('Keep service assigned even on new publication')
            },
        ],
        defvalue='keep')

    idle = gui.NumericField(
        label=_("Max.Idle time"),
        length=4,
        defvalue=-1,
        rdonly=False,
        order=11,
        tooltip=
        _('Maximum idle time (in seconds) before session is automatically closed to the user (<= 0 means no max idle time).'
          ),
        required=True)

    def __setProcessUnusedMachines(self):
        self.processUnusedMachines = self._onLogout == 'remove'

    def __init__(self, environment, values):
        super(LinuxOsManager, self).__init__(environment, values)
        if values is not None:
            self._onLogout = values['onLogout']
            self._idle = int(values['idle'])
        else:
            self._onLogout = ''
            self._idle = -1

        self.__setProcessUnusedMachines()

    def release(self, service):
        pass

    def isRemovableOnLogout(self, userService):
        '''
        Says if a machine is removable on logout
        '''
        if userService.in_use == False:
            if (self._onLogout
                    == 'remove') or (not userService.isValidPublication()
                                     and self._onLogout == 'keep'):
                return True

        return False

    def getName(self, service):
        """
        gets name from deployed
        """
        return service.getName()

    def infoVal(self, service):
        return 'rename:' + self.getName(service)

    def infoValue(self, service):
        return 'rename\r' + self.getName(service)

    def notifyIp(self, uid, service, data):
        si = service.getInstance()

        ip = ''
        # Notifies IP to deployed
        for p in data['ips']:
            if p[0].lower() == uid.lower():
                si.setIp(p[1])
                ip = p[1]
                break

        self.logKnownIp(service, ip)
        service.updateData(si)

    def doLog(self, service, data, origin=log.OSMANAGER):
        # Stores a log associated with this service
        try:
            msg, level = data.split('\t')
            try:
                level = int(level)
            except Exception:
                logger.debug('Do not understand level {}'.format(level))
                level = log.INFO
            log.doLog(service, level, msg, origin)
        except Exception:
            log.doLog(service, log.ERROR, "do not understand {0}".format(data),
                      origin)

    def process(self, userService, msg, data, options=None):
        """
        We understand this messages:
        * msg = info, data = None. Get information about name of machine (or domain, in derived WinDomainOsManager class), old method
        * msg = information, data = None. Get information about name of machine (or domain, in derived WinDomainOsManager class), new method
        * msg = logon, data = Username, Informs that the username has logged in inside the machine
        * msg = logoff, data = Username, Informs that the username has logged out of the machine
        * msg = ready, data = None, Informs machine ready to be used
        """
        logger.info(
            "Invoked LinuxOsManager for {0} with params: {1},{2}".format(
                userService, msg, data))
        # We get from storage the name for this userService. If no name, we try to assign a new one
        ret = "ok"
        notifyReady = False
        doRemove = False
        state = userService.os_state
        if msg in ('ready', 'ip'):
            if not isinstance(
                    data, dict
            ):  # Old actors, previous to 2.5, convert it information..
                data = {
                    'ips': [v.split('=') for v in data.split(',')],
                    'hostname': userService.friendly_name
                }

        # Old "info" state, will be removed in a near future
        if msg == "info":
            ret = self.infoVal(userService)
            state = State.PREPARING
        elif msg == "information":
            ret = self.infoValue(userService)
            state = State.PREPARING
        elif msg == "log":
            self.doLog(userService, data, log.ACTOR)
        elif msg == "login":
            self.loggedIn(userService, data, False)
            ip, hostname = userService.getConnectionSource()
            deadLine = userService.deployed_service.getDeadline()
            ret = "{0}\t{1}\t{2}".format(ip, hostname,
                                         0 if deadLine is None else deadLine)
        elif msg == "logout":
            self.loggedOut(userService, data, False)
            doRemove = self.isRemovableOnLogout(userService)
        elif msg == "ip":
            # This ocurss on main loop inside machine, so userService is usable
            state = State.USABLE
            self.notifyIp(userService.unique_id, userService, data)
        elif msg == "ready":
            self.toReady(userService)
            state = State.USABLE
            notifyReady = True
            self.notifyIp(userService.unique_id, userService, data)

        userService.setOsState(state)

        # If notifyReady is not true, save state, let UserServiceManager do it for us else
        if doRemove is True:
            userService.release()
        else:
            if notifyReady is False:
                userService.save()
            else:
                UserServiceManager.manager().notifyReadyFromOsManager(
                    userService, '')
        logger.debug('Returning {0}'.format(ret))
        return ret

    def processUnused(self, userService):
        """
        This will be invoked for every assigned and unused user service that has been in this state at least 1/2 of Globalconfig.CHECK_UNUSED_TIME
        This function can update userService values. Normal operation will be remove machines if this state is not valid
        """
        if self.isRemovableOnLogout(userService):
            userService.remove()

    def isPersistent(self):
        return self._onLogout == 'keep-always'

    def checkState(self, service):
        logger.debug('Checking state for service {0}'.format(service))
        return State.RUNNING

    def maxIdle(self):
        """
        On production environments, will return no idle for non removable machines
        """
        if self._idle <= 0:  # or (settings.DEBUG is False and self._onLogout != 'remove'):
            return None

        return self._idle

    def marshal(self):
        """
        Serializes the os manager data so we can store it in database
        """
        return '\t'.join(['v2', self._onLogout,
                          six.text_type(self._idle)]).encode('utf8')

    def unmarshal(self, s):
        data = s.decode('utf8').split('\t')
        if data[0] == 'v1':
            self._onLogout = data[1]
            self._idle = -1
        elif data[0] == 'v2':
            self._onLogout, self._idle = data[1], int(data[2])

        self.__setProcessUnusedMachines()

    def valuesDict(self):
        return {'onLogout': self._onLogout, 'idle': self._idle}
Ejemplo n.º 8
0
class TSNXTransport(Transport):
    '''
    Provides access via RDP to service.
    This transport can use an domain. If username processed by authenticator contains '@', it will split it and left-@-part will be username, and right password
    '''
    typeName = _('NX Transport (tunneled)')
    typeType = 'TSNXTransport'
    typeDescription = _('NX Transport for tunneled connection')
    iconFile = 'nx.png'
    needsJava = True  # If this transport needs java for rendering
    supportedOss = ['Windows', 'Macintosh', 'Linux']
    protocol = protocols.NX

    tunnelServer = gui.TextField(label=_('Tunnel server'), order=1, tooltip=_('IP or Hostname of tunnel server sent to client device ("public" ip) and port. (use HOST:PORT format)'))
    tunnelCheckServer = gui.TextField(label=_('Tunnel host check'), order=2, tooltip=_('If not empty, this server will be used to check if service is running before assigning it to user. (use HOST:PORT format)'))

    useEmptyCreds = gui.CheckBoxField(label=_('Empty creds'), order=3, tooltip=_('If checked, the credentials used to connect will be emtpy'))
    fixedName = gui.TextField(label=_('Username'), order=4, tooltip=_('If not empty, this username will be always used as credential'))
    fixedPassword = gui.PasswordField(label=_('Password'), order=5, tooltip=_('If not empty, this password will be always used as credential'))
    listenPort = gui.NumericField(label=_('Listening port'), length=5, order=6, tooltip=_('Listening port of NX (ssh) at client machine'), defvalue='22')
    connection = gui.ChoiceField(label=_('Connection'), order=7, tooltip=_('Connection speed for this transport (quality)'),
                                 values=[
                                     {'id': 'modem', 'text': 'modem'},
                                     {'id': 'isdn', 'text': 'isdn'},
                                     {'id': 'adsl', 'text': 'adsl'},
                                     {'id': 'wan', 'text': 'wan'},
                                     {'id': 'lan', 'text': 'lan'},
    ])
    session = gui.ChoiceField(label=_('Session'), order=8, tooltip=_('Desktop session'),
                              values=[
                                  {'id': 'gnome', 'text': 'gnome'},
                                  {'id': 'kde', 'text': 'kde'},
                                  {'id': 'cde', 'text': 'cde'},
    ])
    cacheDisk = gui.ChoiceField(label=_('Disk Cache'), order=9, tooltip=_('Cache size en Mb stored at disk'),
                                values=[
                                    {'id': '0', 'text': '0 Mb'},
                                    {'id': '32', 'text': '32 Mb'},
                                    {'id': '64', 'text': '64 Mb'},
                                    {'id': '128', 'text': '128 Mb'},
                                    {'id': '256', 'text': '256 Mb'},
                                    {'id': '512', 'text': '512 Mb'},
    ])
    cacheMem = gui.ChoiceField(label=_('Memory Cache'), order=10, tooltip=_('Cache size en Mb kept at memory'),
                               values=[
                                   {'id': '4', 'text': '4 Mb'},
                                   {'id': '8', 'text': '8 Mb'},
                                   {'id': '16', 'text': '16 Mb'},
                                   {'id': '32', 'text': '32 Mb'},
                                   {'id': '64', 'text': '64 Mb'},
                                   {'id': '128', 'text': '128 Mb'},
    ])

    def __init__(self, environment, values=None):
        super(TSNXTransport, self).__init__(environment, values)
        if values != None:
            if values['tunnelServer'].find(':') == -1:
                raise Transport.ValidationException(_('Must use HOST:PORT in Tunnel Server Field'))
            self._tunnelServer = values['tunnelServer']
            self._tunnelCheckServer = values['tunnelCheckServer']
            self._useEmptyCreds = gui.strToBool(values['useEmptyCreds'])
            self._fixedName = values['fixedName']
            self._fixedPassword = values['fixedPassword']
            self._listenPort = values['listenPort']
            self._connection = values['connection']
            self._session = values['session']
            self._cacheDisk = values['cacheDisk']
            self._cacheMem = values['cacheMem']
        else:
            self._tunnelServer = ''
            self._tunnelCheckServer = ''
            self._useEmptyCreds = ''
            self._fixedName = ''
            self._fixedPassword = ''
            self._listenPort = ''
            self._connection = ''
            self._session = ''
            self._cacheDisk = ''
            self._cacheMem = ''

    def marshal(self):
        '''
        Serializes the transport data so we can store it in database
        '''
        return str.join('\t', [ 'v1', gui.boolToStr(self._useEmptyCreds), self._fixedName, self._fixedPassword, self._listenPort,
                                self._connection, self._session, self._cacheDisk, self._cacheMem, self._tunnelServer, self._tunnelCheckServer ])

    def unmarshal(self, string):
        data = string.split('\t')
        if data[0] == 'v1':
            self._useEmptyCreds = gui.strToBool(data[1])
            self._fixedName, self._fixedPassword, self._listenPort, self._connection, self._session, self._cacheDisk, self._cacheMem, self._tunnelServer, self._tunnelCheckServer = data[2:]

    def valuesDict(self):
        return {
            'useEmptyCreds': gui.boolToStr(self._useEmptyCreds),
            'fixedName': self._fixedName,
            'fixedPassword': self._fixedPassword,
            'listenPort': self._listenPort,
            'connection': self._connection,
            'session': self._session,
            'cacheDisk': self._cacheDisk,
            'cacheMem': self._cacheMem,
            'tunnelServer': self._tunnelServer,
            'tunnelCheckServer': self._tunnelCheckServer
        }

    def isAvailableFor(self, ip):
        '''
        Checks if the transport is available for the requested destination ip
        Override this in yours transports
        '''
        logger.debug('Checking availability for {0}'.format(ip))
        ready = self.cache().get(ip)
        if ready is None:
            # Check again for readyness
            if connection.testServer(ip, self._listenPort) is True:
                self.cache().put(ip, 'Y', READY_CACHE_TIMEOUT)
                return True
            else:
                self.cache().put(ip, 'N', READY_CACHE_TIMEOUT)
        return ready == 'Y'

    def renderForHtml(self, userService, transport, ip, os, user, password):

        prefs = user.prefs('nx')

        username = user.getUsernameForAuth()
        proc = username.split('@')
        username = proc[0]
        if self._fixedName is not '':
            username = self._fixedName
        if self._fixedPassword is not '':
            password = self._fixedPassword
        if self._useEmptyCreds is True:
            username, password = '', ''

        width, height = CommonPrefs.getWidthHeight(prefs)
        cache = Cache('pam')

        tunuser = ''.join(random.choice(string.letters + string.digits) for _i in range(12)) + ("%f" % time.time()).split('.')[1]
        tunpass = ''.join(random.choice(string.letters + string.digits) for _i in range(12))
        cache.put(tunuser, tunpass, 60 * 10)  # Credential valid for ten minutes, and for 1 use only

        sshHost, sshPort = self._tunnelServer.split(':')

        logger.debug('Username generated: {0}, password: {1}'.format(tunuser, tunpass))
        tun = "{0} {1} {2} {3} {4} {5} {6}".format(tunuser, tunpass, sshHost, sshPort, ip, self._listenPort, '9')

        # Extra data
        extra = {
            'width': width,
            'height': height,
            'connection': self._connection,
            'session': self._session,
            'cacheDisk': self._cacheDisk,
            'cacheMem': self._cacheMem,
            'tun': tun
        }

        # Fix username/password acording to os manager
        username, password = userService.processUserPassword(username, password)

        return generateHtmlForNX(self, userService.uuid, transport.uuid, os, username, password, extra)

    def getHtmlComponent(self, theId, os, componentId):
        # We use helper to keep this clean
        return getHtmlComponent(self.__module__, componentId)
Ejemplo n.º 9
0
class HTML5RDPTransport(Transport):
    """
    Provides access via RDP to service.
    This transport can use an domain. If username processed by authenticator contains '@', it will split it and left-@-part will be username, and right password
    """
    typeName = _('HTML5 RDP')
    typeType = 'HTML5RDPTransport'
    typeDescription = _('RDP protocol using HTML5 client')
    iconFile = 'html5.png'

    ownLink = True
    supportedOss = OsDetector.allOss
    protocol = protocols.RDP
    group = TUNNELED_GROUP

    guacamoleServer = gui.TextField(
        label=_('Tunnel Server'),
        order=1,
        tooltip=
        _('Host of the tunnel server (use http/https & port if needed) as accesible from users'
          ),
        defvalue='https://',
        length=64,
        required=True,
        tab=gui.TUNNEL_TAB)
    useEmptyCreds = gui.CheckBoxField(
        label=_('Empty creds'),
        order=2,
        tooltip=_('If checked, the credentials used to connect will be emtpy'),
        tab=gui.CREDENTIALS_TAB)
    fixedName = gui.TextField(
        label=_('Username'),
        order=3,
        tooltip=_(
            'If not empty, this username will be always used as credential'),
        tab=gui.CREDENTIALS_TAB)
    fixedPassword = gui.PasswordField(
        label=_('Password'),
        order=4,
        tooltip=_(
            'If not empty, this password will be always used as credential'),
        tab=gui.CREDENTIALS_TAB)
    withoutDomain = gui.CheckBoxField(
        label=_('Without Domain'),
        order=5,
        tooltip=
        _('If checked, the domain part will always be emptied (to connecto to xrdp for example is needed)'
          ),
        tab=gui.CREDENTIALS_TAB)
    fixedDomain = gui.TextField(
        label=_('Domain'),
        order=6,
        tooltip=
        _('If not empty, this domain will be always used as credential (used as DOMAIN\\user)'
          ),
        tab=gui.CREDENTIALS_TAB)
    wallpaper = gui.CheckBoxField(
        label=_('Show wallpaper'),
        order=20,
        tooltip=
        _('If checked, the wallpaper and themes will be shown on machine (better user experience, more bandwidth)'
          ),
        tab=gui.PARAMETERS_TAB)
    desktopComp = gui.CheckBoxField(
        label=_('Allow Desk.Comp.'),
        order=22,
        tooltip=_('If checked, desktop composition will be allowed'),
        tab=gui.PARAMETERS_TAB)
    smooth = gui.CheckBoxField(
        label=_('Font Smoothing'),
        order=23,
        tooltip=_(
            'If checked, fonts smoothing will be allowed (windows clients only)'
        ),
        tab=gui.PARAMETERS_TAB)
    enableAudio = gui.CheckBoxField(
        label=_('Enable Audio'),
        order=24,
        tooltip=
        _('If checked, the audio will be redirected to client (if client browser supports it)'
          ),
        tab=gui.PARAMETERS_TAB)
    enablePrinting = gui.CheckBoxField(
        label=_('Enable Printing'),
        order=25,
        tooltip=
        _('If checked, the printing will be redirected to client (if client browser supports it)'
          ),
        tab=gui.PARAMETERS_TAB)
    enableFileSharing = gui.CheckBoxField(
        label=_('Enable File Sharing'),
        order=8,
        tooltip=
        _('If checked, the user will be able to upload/download files (if client browser supports it)'
          ),
        tab=gui.PARAMETERS_TAB)
    serverLayout = gui.ChoiceField(
        order=26,
        label=_('Layout'),
        tooltip=_('Keyboards Layout of server'),
        required=True,
        values=[
            gui.choiceItem('-', 'default'),
            gui.choiceItem('en-us-qwerty', _('English (US) keyboard')),
            gui.choiceItem('de-de-qwertz', _('German keyboard (qwertz)')),
            gui.choiceItem('fr-fr-azerty', _('French keyboard (azerty)')),
            gui.choiceItem('it-it-qwerty', _('Italian keyboard')),
            gui.choiceItem('sv-se-qwerty', _('Swedish keyboard')),
            gui.choiceItem('failsafe', _('Failsafe')),
        ],
        defvalue='-',
        tab=gui.PARAMETERS_TAB)
    security = gui.ChoiceField(
        order=27,
        label=_('Security'),
        tooltip=_('Connection security mode for Guacamole RDP connection'),
        required=True,
        values=[
            gui.choiceItem(
                'any', _('Any (Allow the server to choose the type of auth)')),
            gui.choiceItem(
                'rdp',
                _('RDP (Standard RDP encryption. Should be supported by all servers)'
                  )),
            gui.choiceItem(
                'nla',
                _('NLA (Network Layer authentication. Requires VALID username&password, or connection will fail)'
                  )),
            gui.choiceItem('tls',
                           _('TLS (Transport Security Layer encryption)')),
        ],
        defvalue='rdp',
        tab=gui.PARAMETERS_TAB)

    ticketValidity = gui.NumericField(
        length=3,
        label=_('Ticket Validity'),
        defvalue='60',
        order=90,
        tooltip=
        _('Allowed time, in seconds, for HTML5 client to reload data from UDS Broker. The default value of 60 is recommended.'
          ),
        required=True,
        minValue=60,
        tab=gui.ADVANCED_TAB)

    def initialize(self, values):
        if values is None:
            return
        self.guacamoleServer.value = self.guacamoleServer.value.strip()
        if self.guacamoleServer.value[0:4] != 'http':
            raise Transport.ValidationException(
                _('The server must be http or https'))
        if self.useEmptyCreds.isTrue() and self.security.value != 'rdp':
            raise Transport.ValidationException(
                _('Empty credentials (on Credentials tab) is only allowed with Security level (on Parameters tab) set to "RDP"'
                  ))

    # Same check as normal RDP transport
    def isAvailableFor(self, userService, ip):
        """
        Checks if the transport is available for the requested destination ip
        Override this in yours transports
        """
        logger.debug('Checking availability for {0}'.format(ip))
        ready = self.cache.get(ip)
        if ready is None:
            # Check again for readyness
            if self.testServer(userService, ip, '3389') is True:
                self.cache.put(ip, 'Y', READY_CACHE_TIMEOUT)
                return True
            else:
                self.cache.put(ip, 'N', READY_CACHE_TIMEOUT)
        return ready == 'Y'

    def processedUser(self, userService, userName):
        v = self.processUserPassword(userService, userName, '')
        return v['username']

    def processUserPassword(self, service, user, password):
        username = user.getUsernameForAuth()

        if self.fixedName.value != '':
            username = self.fixedName.value

        proc = username.split('@')
        if len(proc) > 1:
            domain = proc[1]
        else:
            domain = ''
        username = proc[0]

        if self.fixedPassword.value != '':
            password = self.fixedPassword.value
        if self.fixedDomain.value != '':
            domain = self.fixedDomain.value
        if self.useEmptyCreds.isTrue():
            username, password, domain = '', '', ''

        if self.withoutDomain.isTrue():
            domain = ''

        if '.' in domain:  # Dotter domain form
            username = username + '@' + domain
            domain = ''

        # Fix username/password acording to os manager
        username, password = service.processUserPassword(username, password)

        return {
            'protocol': self.protocol,
            'username': username,
            'password': password,
            'domain': domain
        }

    def getLink(self, userService, transport, ip, os, user, password, request):
        ci = self.processUserPassword(userService, user, password)
        username, password, domain = ci['username'], ci['password'], ci[
            'domain']

        if domain != '':
            username = domain + '\\' + username

        scrambler = cryptoManager().randomString(32)
        passwordCrypted = cryptoManager().symCrypt(password, scrambler)

        # Build params dict
        params = {
            'protocol': 'rdp',
            'hostname': ip,
            'username': username,
            'password': passwordCrypted,
            'ignore-cert': 'true',
            'security': self.security.value,
            'drive-path': '/share/{}'.format(user.uuid),
            'create-drive-path': 'true'
        }

        if self.enableFileSharing.isTrue():
            params['enable-drive'] = 'true'

        if self.serverLayout.value != '-':
            params['server-layout'] = self.serverLayout.value

        if self.enableAudio.isTrue() is False:
            params['disable-audio'] = 'true'

        if self.enablePrinting.isTrue() is True:
            params['enable-printing'] = 'true'

        if self.wallpaper.isTrue() is True:
            params['enable-wallpaper'] = 'true'

        if self.desktopComp.isTrue() is True:
            params['enable-desktop-composition'] = 'true'

        if self.smooth.isTrue() is True:
            params['enable-font-smoothing'] = 'true'

        logger.debug('RDP Params: {0}'.format(params))

        ticket = TicketStore.create(params, validity=self.ticketValidity.num())

        return HttpResponseRedirect("{}/transport/?{}.{}&{}".format(
            self.guacamoleServer.value, ticket, scrambler,
            request.build_absolute_uri(reverse('Index'))))
Ejemplo n.º 10
0
class UsageByPool(StatsReport):
    filename = 'pools_usage.pdf'
    name = _('Pools usage by users')  # Report name
    description = _('Pools usage by user report')  # Report description
    uuid = '38ec12dc-beaf-11e5-bd0a-10feed05884b'

    # Input fields
    pool = gui.ChoiceField(order=1,
                           label=_('Pool'),
                           tooltip=_('Pool for report'),
                           required=True)

    startDate = gui.DateField(order=2,
                              label=_('Starting date'),
                              tooltip=_('starting date for report'),
                              defvalue=datetime.date.min,
                              required=True)

    endDate = gui.DateField(order=3,
                            label=_('Finish date'),
                            tooltip=_('finish date for report'),
                            defvalue=datetime.date.max,
                            required=True)

    def initialize(self, values):
        pass

    def initGui(self):
        logger.debug('Initializing gui')
        vals = [
            gui.choiceItem(v.uuid, v.name) for v in ServicePool.objects.all()
        ]
        self.pool.setValues(vals)

    def getData(self):
        # Generate the sampling intervals and get dataUsers from db
        start = self.startDate.stamp()
        end = self.endDate.stamp()
        logger.debug(self.pool.value)
        pool = ServicePool.objects.get(uuid=self.pool.value)

        items = events.statsManager().getEvents(
            events.OT_DEPLOYED, (events.ET_LOGIN, events.ET_LOGOUT),
            owner_id=pool.id,
            since=start,
            to=end).order_by('stamp')

        logins = {}
        data = []
        for i in items:
            # if '\\' in i.fld1:
            #    continue

            if i.event_type == events.ET_LOGIN:
                logins[i.fld4] = i.stamp
            else:
                if i.fld4 in logins:
                    stamp = logins[i.fld4]
                    del logins[i.fld4]
                    total = i.stamp - stamp
                    data.append({
                        'name': i.fld4,
                        'date': datetime.datetime.fromtimestamp(stamp),
                        'time': total
                    })

        logger.debug('data')

        return data, pool.name

    def generate(self):
        items, poolName = self.getData()

        output = StringIO.StringIO()

        report = UsersReport(queryset=items)
        report.title = _('Users usage list for {}').format(poolName)
        report.generate_by(PDFGenerator, filename=output)
        return output.getvalue()
Ejemplo n.º 11
0
class NXTransport(Transport):
    """
    Provides access via NX to service.
    This transport can use an domain. If username processed by authenticator contains '@', it will split it and left-@-part will be username, and right password
    """
    typeName = _('NX v3.5')
    typeType = 'NXTransport'
    typeDescription = _('NX Protocol v3.5. Direct connection.')
    iconFile = 'nx.png'
    protocol = protocols.NX

    useEmptyCreds = gui.CheckBoxField(
        label=_('Empty creds'),
        order=1,
        tooltip=_('If checked, the credentials used to connect will be emtpy'),
        tab=gui.CREDENTIALS_TAB)
    fixedName = gui.TextField(
        label=_('Username'),
        order=2,
        tooltip=_(
            'If not empty, this username will be always used as credential'),
        tab=gui.CREDENTIALS_TAB)
    fixedPassword = gui.PasswordField(
        label=_('Password'),
        order=3,
        tooltip=_(
            'If not empty, this password will be always used as credential'),
        tab=gui.CREDENTIALS_TAB)
    listenPort = gui.NumericField(
        label=_('Listening port'),
        length=5,
        order=4,
        tooltip=_('Listening port of NX (ssh) at client machine'),
        defvalue='22')
    connection = gui.ChoiceField(
        label=_('Connection'),
        order=6,
        tooltip=_('Connection speed for this transport (quality)'),
        values=[{
            'id': 'modem',
            'text': 'modem'
        }, {
            'id': 'isdn',
            'text': 'isdn'
        }, {
            'id': 'adsl',
            'text': 'adsl'
        }, {
            'id': 'wan',
            'text': 'wan'
        }, {
            'id': 'lan',
            'text': 'lan'
        }],
        tab=gui.PARAMETERS_TAB)
    session = gui.ChoiceField(label=_('Session'),
                              order=7,
                              tooltip=_('Desktop session'),
                              values=[
                                  {
                                      'id': 'gnome',
                                      'text': 'gnome'
                                  },
                                  {
                                      'id': 'kde',
                                      'text': 'kde'
                                  },
                                  {
                                      'id': 'cde',
                                      'text': 'cde'
                                  },
                              ],
                              tab=gui.PARAMETERS_TAB)
    cacheDisk = gui.ChoiceField(label=_('Disk Cache'),
                                order=8,
                                tooltip=_('Cache size en Mb stored at disk'),
                                values=[
                                    {
                                        'id': '0',
                                        'text': '0 Mb'
                                    },
                                    {
                                        'id': '32',
                                        'text': '32 Mb'
                                    },
                                    {
                                        'id': '64',
                                        'text': '64 Mb'
                                    },
                                    {
                                        'id': '128',
                                        'text': '128 Mb'
                                    },
                                    {
                                        'id': '256',
                                        'text': '256 Mb'
                                    },
                                    {
                                        'id': '512',
                                        'text': '512 Mb'
                                    },
                                ],
                                tab=gui.PARAMETERS_TAB)
    cacheMem = gui.ChoiceField(label=_('Memory Cache'),
                               order=9,
                               tooltip=_('Cache size en Mb kept at memory'),
                               values=[
                                   {
                                       'id': '4',
                                       'text': '4 Mb'
                                   },
                                   {
                                       'id': '8',
                                       'text': '8 Mb'
                                   },
                                   {
                                       'id': '16',
                                       'text': '16 Mb'
                                   },
                                   {
                                       'id': '32',
                                       'text': '32 Mb'
                                   },
                                   {
                                       'id': '64',
                                       'text': '64 Mb'
                                   },
                                   {
                                       'id': '128',
                                       'text': '128 Mb'
                                   },
                               ],
                               tab=gui.PARAMETERS_TAB)

    def __init__(self, environment, values=None):
        super(NXTransport, self).__init__(environment, values)
        if values is not None:
            self._useEmptyCreds = gui.strToBool(values['useEmptyCreds'])
            self._fixedName = values['fixedName']
            self._fixedPassword = values['fixedPassword']
            self._listenPort = values['listenPort']
            self._connection = values['connection']
            self._session = values['session']
            self._cacheDisk = values['cacheDisk']
            self._cacheMem = values['cacheMem']
        else:
            self._useEmptyCreds = ''
            self._fixedName = ''
            self._fixedPassword = ''
            self._listenPort = ''
            self._connection = ''
            self._session = ''
            self._cacheDisk = ''
            self._cacheMem = ''

    def marshal(self):
        """
        Serializes the transport data so we can store it in database
        """
        return str.join('\t', [
            'v1',
            gui.boolToStr(self._useEmptyCreds), self._fixedName,
            self._fixedPassword, self._listenPort, self._connection,
            self._session, self._cacheDisk, self._cacheMem
        ]).encode('utf8')

    def unmarshal(self, val):
        data = val.decode('utf8').split('\t')
        if data[0] == 'v1':
            self._useEmptyCreds = gui.strToBool(data[1])
            self._fixedName, self._fixedPassword, self._listenPort, self._connection, self._session, self._cacheDisk, self._cacheMem = data[
                2:]

    def valuesDict(self):
        return {
            'useEmptyCreds': gui.boolToStr(self._useEmptyCreds),
            'fixedName': self._fixedName,
            'fixedPassword': self._fixedPassword,
            'listenPort': self._listenPort,
            'connection': self._connection,
            'session': self._session,
            'cacheDisk': self._cacheDisk,
            'cacheMem': self._cacheMem
        }

    def isAvailableFor(self, userService, ip):
        """
        Checks if the transport is available for the requested destination ip
        Override this in yours transports
        """
        logger.debug('Checking availability for {0}'.format(ip))
        ready = self.cache.get(ip)
        if ready is None:
            # Check again for readyness
            if self.testServer(userService, ip, self._listenPort) is True:
                self.cache.put(ip, 'Y', READY_CACHE_TIMEOUT)
                return True
            else:
                self.cache.put(ip, 'N', READY_CACHE_TIMEOUT)
        return ready == 'Y'

    def getScript(self, script):
        with open(os.path.join(os.path.dirname(__file__), script)) as f:
            data = f.read()
        return data

    def getUDSTransportScript(self, userService, transport, ip, os, user,
                              password, request):
        prefs = user.prefs('nx')

        username = user.getUsernameForAuth()
        proc = username.split('@')
        username = proc[0]
        if self._fixedName is not '':
            username = self._fixedName
        if self._fixedPassword is not '':
            password = self._fixedPassword
        if self._useEmptyCreds is True:
            username, password = '', ''

        # We have the credentials right now, let os manager

        width, height = CommonPrefs.getWidthHeight(prefs)

        # Fix username/password acording to os manager
        username, password = userService.processUserPassword(
            username, password)

        r = NXFile(username=username,
                   password=password,
                   width=width,
                   height=height)
        r.host = ip
        r.port = self._listenPort
        r.connection = self._connection
        r.desktop = self._session
        r.cachedisk = self._cacheDisk
        r.cachemem = self._cacheMem

        os = {
            OsDetector.Windows: 'windows',
            OsDetector.Linux: 'linux',
            OsDetector.Macintosh: 'macosx'
        }.get(os['OS'])

        if os is None:
            return super(self.__class__,
                         self).getUDSTransportScript(userService, transport,
                                                     ip, os, user, password,
                                                     request)

        return self.getScript('scripts/{}/direct.py'.format(os)).format(r=r)
Ejemplo n.º 12
0
class UsageSummaryByPool(StatsReport):
    filename = 'pools_usage.pdf'
    name = _('Summary of pools usage')  # Report name
    description = _('Generates a report with the summary of a pool usage'
                    )  # Report description
    uuid = '202c6438-30a8-11e7-80e4-77c1e4cb9e09'

    # Input fields
    pool = gui.ChoiceField(order=1,
                           label=_('Pool'),
                           tooltip=_('Pool for report'),
                           required=True)

    startDate = gui.DateField(order=2,
                              label=_('Starting date'),
                              tooltip=_('starting date for report'),
                              defvalue=datetime.date.min,
                              required=True)

    endDate = gui.DateField(order=3,
                            label=_('Finish date'),
                            tooltip=_('finish date for report'),
                            defvalue=datetime.date.max,
                            required=True)

    def initialize(self, values):
        pass

    def initGui(self):
        logger.debug('Initializing gui')
        vals = [
            gui.choiceItem(v.uuid, v.name) for v in ServicePool.objects.all()
        ]
        self.pool.setValues(vals)

    def getPoolData(self, pool):
        start = self.startDate.stamp()
        end = self.endDate.stamp()
        logger.debug(self.pool.value)

        items = events.statsManager().getEvents(
            events.OT_DEPLOYED, (events.ET_LOGIN, events.ET_LOGOUT),
            owner_id=pool.id,
            since=start,
            to=end).order_by('stamp')

        logins = {}
        users = {}
        for i in items:
            # if '\\' in i.fld1:
            #    continue
            username = i.fld4
            if i.event_type == events.ET_LOGIN:
                logins[username] = i.stamp
            else:
                if username in logins:
                    stamp = logins[username]
                    del logins[username]
                    total = i.stamp - stamp
                    if username not in users:
                        users[username] = {'sessions': 0, 'time': 0}
                    users[username]['sessions'] += 1
                    users[username]['time'] += total
                    # data.append({
                    #    'name': i.fld4,
                    #    'date': datetime.datetime.fromtimestamp(stamp),
                    #    'time': total
                    # })

        # Extract different number of users
        data = []
        for k, v in users.items():
            data.append({
                'user':
                k,
                'sessions':
                v['sessions'],
                'hours':
                '{:.2f}'.format(float(v['time']) / 3600),
                'average':
                '{:.2f}'.format(float(v['time']) / 3600 / v['sessions'])
            })

        return data, pool.name

    def getData(self):
        return self.getPoolData(ServicePool.objects.get(uuid=self.pool.value))

    def generate(self):
        items, poolName = self.getData()

        return self.templateAsPDF(
            'uds/reports/stats/pool-usage-summary.html',
            dct={
                'data': items,
                'pool': poolName,
                'beginning': self.startDate.date(),
                'ending': self.endDate.date(),
            },
            header=ugettext('Users usage list for {}').format(poolName),
            water=ugettext('UDS Report of users in {}').format(poolName))
Ejemplo n.º 13
0
class WindowsOsManager(osmanagers.OSManager):
    typeName = _('Windows Basic OS Manager')
    typeType = 'WindowsManager'
    typeDescription = _(
        'Os Manager to control windows machines without domain. (Basically renames machine)'
    )
    iconFile = 'wosmanager.png'

    onLogout = gui.ChoiceField(
        label=_('On Logout'),
        order=10,
        rdonly=True,
        tooltip=_('What to do when user logs out from service'),
        values=[{
            'id': 'keep',
            'text': _('Keep service assigned')
        }, {
            'id': 'remove',
            'text': _('Remove service')
        }],
        defvalue='keep')

    idle = gui.NumericField(
        label=_("Max.Idle time"),
        length=4,
        defvalue=-1,
        rdonly=False,
        order=11,
        tooltip=
        _('Maximum idle time (in seconds) before session is automaticatlly closed to the user (<= 0 means no max. idle time)'
          ),
        required=True)

    @staticmethod
    def validateLen(length):
        try:
            length = int(length)
        except Exception:
            raise osmanagers.OSManager.ValidationException(
                _('Length must be numeric!!'))
        if length > 6 or length < 1:
            raise osmanagers.OSManager.ValidationException(
                _('Length must be betwen 1 and 6'))
        return length

    def __setProcessUnusedMachines(self):
        self.processUnusedMachines = self._onLogout == 'remove'

    def __init__(self, environment, values):
        super(WindowsOsManager, self).__init__(environment, values)
        if values is not None:
            self._onLogout = values['onLogout']
            self._idle = int(values['idle'])
        else:
            self._onLogout = ''
            self._idle = -1

        self.__setProcessUnusedMachines()

    def release(self, service):
        pass

    def getName(self, service):
        '''
        gets name from deployed
        '''
        return service.getName()

    def infoVal(self, service):
        return 'rename:' + self.getName(service)

    def infoValue(self, service):
        return 'rename\r' + self.getName(service)

    def notifyIp(self, uid, service, data):
        si = service.getInstance()

        ip = ''
        # Notifies IP to deployed
        pairs = data.split(',')
        for p in pairs:
            key, val = p.split('=')
            if key.lower() == uid.lower():
                si.setIp(val)
                ip = val
                break

        self.logKnownIp(service, ip)
        service.updateData(si)

    def doLog(self, service, data, origin=log.OSMANAGER):
        # Stores a log associated with this service
        try:
            msg, level = data.split('\t')
            try:
                level = int(level)
            except Exception:
                logger.debug('Do not understand level {}'.format(level))
                level = log.INFO

            log.doLog(service, level, msg, origin)
        except Exception:
            logger.exception('LinuxOs Manager message log: ')
            log.doLog(service, log.ERROR, "do not understand {0}".format(data),
                      origin)

    def process(self, service, msg, data, options):
        '''
        We understand this messages:
        * msg = info, data = None. Get information about name of machine (or domain, in derived WinDomainOsManager class) (old method)
        * msg = information, data = None. Get information about name of machine (or domain, in derived WinDomainOsManager class) (new method)
        * msg = logon, data = Username, Informs that the username has logged in inside the machine
        * msg = logoff, data = Username, Informs that the username has logged out of the machine
        * msg = ready, data = None, Informs machine ready to be used
        '''
        logger.info(
            "Invoked WindowsOsManager for {0} with params: {1},{2}".format(
                service, msg, data))
        # We get from storage the name for this service. If no name, we try to assign a new one
        ret = "ok"
        notifyReady = False
        doRemove = False
        state = service.os_state
        if msg == "info":
            ret = self.infoVal(service)
            state = State.PREPARING
        elif msg == "information":
            ret = self.infoValue(service)
            state = State.PREPARING
        elif msg == "log":
            self.doLog(service, data, log.ACTOR)
        elif msg == "logon" or msg == 'login':
            if '\\' not in data:
                self.loggedIn(service, data, False)
            service.setInUse(True)
            # We get the service logged hostname & ip and returns this
            ip, hostname = service.getConnectionSource()
            ret = "{0}\t{1}".format(ip, hostname)
        elif msg == "logoff" or msg == 'logout':
            self.loggedOut(service, data, False)
            if self._onLogout == 'remove':
                doRemove = True
        elif msg == "ip":
            # This ocurss on main loop inside machine, so service is usable
            state = State.USABLE
            self.notifyIp(service.unique_id, service, data)
        elif msg == "ready":
            state = State.USABLE
            notifyReady = True
            self.notifyIp(service.unique_id, service, data)

        service.setOsState(state)

        # If notifyReady is not true, save state, let UserServiceManager do it for us else
        if doRemove is True:
            service.remove()
        else:
            if notifyReady is False:
                service.save()
            else:
                logger.debug('Notifying ready')
                UserServiceManager.manager().notifyReadyFromOsManager(
                    service, '')
        logger.debug('Returning {} to {} message'.format(ret, msg))
        if options is not None and options.get('scramble', True) is False:
            return ret
        return scrambleMsg(ret)

    def processUnused(self, userService):
        '''
        This will be invoked for every assigned and unused user service that has been in this state at least 1/2 of Globalconfig.CHECK_UNUSED_TIME
        This function can update userService values. Normal operation will be remove machines if this state is not valid
        '''
        if self._onLogout == 'remove':
            userService.remove()

    def checkState(self, service):
        logger.debug('Checking state for service {0}'.format(service))
        return State.RUNNING

    def maxIdle(self):
        '''
        On production environments, will return no idle for non removable machines
        '''
        if self._idle <= 0 or (settings.DEBUG is False
                               and self._onLogout != 'remove'):
            return None

        return self._idle

    def marshal(self):
        '''
        Serializes the os manager data so we can store it in database
        '''
        return '\t'.join(['v2', self._onLogout, six.text_type(self._idle)])

    def unmarshal(self, s):
        data = s.split('\t')
        try:
            if data[0] == 'v1':
                self._onLogout = data[1]
                self._idle = -1
            elif data[0] == 'v2':
                self._onLogout, self._idle = data[1], int(data[2])
        except Exception:
            logger.exception(
                'Exception unmarshalling. Some values left as default ones')

        self.__setProcessUnusedMachines()

    def valuesDict(self):
        return {'onLogout': self._onLogout, 'idle': self._idle}
Ejemplo n.º 14
0
class X2GOTransport(Transport):
    '''
    Provides access via RDP to service.
    This transport can use an domain. If username processed by authenticator contains '@', it will split it and left-@-part will be username, and right password
    '''
    typeName = _('X2GO Transport (direct)')
    typeType = 'X2GOTransport'
    typeDescription = _('X2GO Transport for direct connection')
    iconFile = 'x2go.png'
    protocol = protocols.NX

    useEmptyCreds = gui.CheckBoxField(label=_('Empty creds'), order=1, tooltip=_('If checked, the credentials used to connect will be emtpy'))
    fixedName = gui.TextField(label=_('Username'), order=2, tooltip=_('If not empty, this username will be always used as credential'))
    fixedPassword = gui.PasswordField(label=_('Password'), order=3, tooltip=_('If not empty, this password will be always used as credential'))
    listenPort = gui.NumericField(label=_('Listening port'), length=5, order=4, tooltip=_('Listening port of NX (ssh) at client machine'), defvalue='22')
    connection = gui.ChoiceField(label=_('Connection'), order=6, tooltip=_('Connection speed for this transport (quality)'),
                                 values=[
                                     {'id': 'modem', 'text': 'modem'},
                                     {'id': 'isdn', 'text': 'isdn'},
                                     {'id': 'adsl', 'text': 'adsl'},
                                     {'id': 'wan', 'text': 'wan'},
                                     {'id': 'lan', 'text': 'lan'}
    ])
    session = gui.ChoiceField(label=_('Session'), order=7, tooltip=_('Desktop session'),
                              values=[
                                  {'id': 'gnome', 'text': 'gnome'},
                                  {'id': 'kde', 'text': 'kde'},
                                  {'id': 'cde', 'text': 'cde'},
    ])
    cacheDisk = gui.ChoiceField(label=_('Disk Cache'), order=8, tooltip=_('Cache size en Mb stored at disk'),
                                values=[
                                    {'id': '0', 'text': '0 Mb'},
                                    {'id': '32', 'text': '32 Mb'},
                                    {'id': '64', 'text': '64 Mb'},
                                    {'id': '128', 'text': '128 Mb'},
                                    {'id': '256', 'text': '256 Mb'},
                                    {'id': '512', 'text': '512 Mb'},
    ])
    cacheMem = gui.ChoiceField(label=_('Memory Cache'), order=9, tooltip=_('Cache size en Mb kept at memory'),
                               values=[
                                       {'id': '4', 'text': '4 Mb'},
                                       {'id': '8', 'text': '8 Mb'},
                                       {'id': '16', 'text': '16 Mb'},
                                       {'id': '32', 'text': '32 Mb'},
                                       {'id': '64', 'text': '64 Mb'},
                                       {'id': '128', 'text': '128 Mb'},
    ])

    def initialize(self, values):
        if values is None:
            return
        # Just pass over in fact

    def isAvailableFor(self, ip):
        '''
        Checks if the transport is available for the requested destination ip
        Override this in yours transports
        '''
        logger.debug('Checking availability for {0}'.format(ip))
        ready = self.cache().get(ip)
        if ready is None:
            # Check again for readyness
            if connection.testServer(ip, self.listenPort.value) is True:
                self.cache().put(ip, 'Y', READY_CACHE_TIMEOUT)
                return True
            else:
                self.cache().put(ip, 'N', READY_CACHE_TIMEOUT)
        return ready == 'Y'

    def getUDSTransportScript(self, userService, transport, ip, os, user, password, request):
        logger.debug('Getting X2Go Transport info')

        prefs = user.prefs('nx')

        username = user.getUsernameForAuth()
        proc = username.split('@')
        username = proc[0]
        if self.fixedName.value != '':
            username = self.fixedName.value
        if self.fixedPassword.value != '':
            password = self.fixedPassword.value
        if self.useEmptyCreds.isTrue():
            username, password = '', ''

        # We have the credentials right now, let os manager

        width, height = CommonPrefs.getWidthHeight(prefs)

        # Fix username/password acording to os manager
        username, password = userService.processUserPassword(username, password)

        # data
        data = {
            'username': username,
            'password': password,
            'width': width,
            'height': height,
            'port': self.listenPort.value,
            'connection': self.connection.value,
            'session': self.session.value,
            'cacheDisk': self.cacheDisk.value,
            'cacheMem': self.cacheMem.value
        }

        return '''
from PyQt4 import QtCore, QtGui
import six
from uds import osDetector

data = {data}
osname = {os}

QtGui.QMessageBox.critical(parent, 'Notice ' + osDetector.getOs(), six.text_type(data), QtGui.QMessageBox.Ok)
'''.format(data=data, os=os)
Ejemplo n.º 15
0
class BaseX2GOTransport(Transport):
    """
    Provides access via X2GO to service.
    This transport can use an domain. If username processed by authenticator contains '@', it will split it and left-@-part will be username, and right password
    """
    iconFile = 'x2go.png'
    protocol = protocols.X2GO
    supportedOss = (OsDetector.Linux, OsDetector.Windows)

    fixedName = gui.TextField(
        order=2,
        label=_('Username'),
        tooltip=_(
            'If not empty, this username will be always used as credential'),
        tab=gui.CREDENTIALS_TAB)

    fullScreen = gui.CheckBoxField(
        order=10,
        label=_('Show fullscreen'),
        tooltip=_('If checked, viewer will be shown on fullscreen mode-'),
        tab=gui.PARAMETERS_TAB)

    desktopType = gui.ChoiceField(
        label=_('Desktop'),
        order=11,
        tooltip=_('Desktop session'),
        values=[
            {
                'id': 'XFCE',
                'text': 'Xfce'
            },
            {
                'id': 'MATE',
                'text': 'Mate'
            },
            {
                'id': 'LXDE',
                'text': 'Lxde'
            },
            {
                'id': 'GNOME',
                'text': 'Gnome (see docs)'
            },
            {
                'id': 'KDE',
                'text': 'Kde (see docs)'
            },
            # {'id': 'UNITY', 'text': 'Unity (see docs)'},
            {
                'id': 'gnome-session-cinnamon',
                'text': 'Cinnamon 1.4 (see docs)'
            },
            {
                'id': 'gnome-session-cinnamon2d',
                'text': 'Cinnamon 2.2 (see docs)'
            },
            {
                'id': 'UDSVAPP',
                'text': 'UDS vAPP'
            },
        ],
        tab=gui.PARAMETERS_TAB)

    customCmd = gui.TextField(
        order=12,
        label=_('vAPP'),
        tooltip=
        _('If UDS vAPP is selected as "Desktop", the FULL PATH of the app to be executed. If UDS vAPP is not selected, this field will be ignored.'
          ),
        tab=gui.PARAMETERS_TAB)

    sound = gui.CheckBoxField(order=13,
                              label=_('Enable sound'),
                              tooltip=_('If checked, sound will be available'),
                              defvalue=gui.TRUE,
                              tab=gui.PARAMETERS_TAB)

    exports = gui.CheckBoxField(
        order=14,
        label=_('Redirect home folder'),
        tooltip=
        _('If checked, user home folder will be redirected. (On linux, also redirects /media)'
          ),
        defvalue=gui.FALSE,
        tab=gui.PARAMETERS_TAB)

    speed = gui.ChoiceField(label=_('Speed'),
                            order=15,
                            tooltip=_('Connection speed'),
                            defvalue='3',
                            values=[
                                {
                                    'id': '0',
                                    'text': 'MODEM'
                                },
                                {
                                    'id': '1',
                                    'text': 'ISDN'
                                },
                                {
                                    'id': '2',
                                    'text': 'ADSL'
                                },
                                {
                                    'id': '3',
                                    'text': 'WAN'
                                },
                                {
                                    'id': '4',
                                    'text': 'LAN'
                                },
                            ],
                            tab=gui.PARAMETERS_TAB)

    soundType = gui.ChoiceField(label=_('Sound'),
                                order=30,
                                tooltip=_('Sound server'),
                                defvalue='pulse',
                                values=[
                                    {
                                        'id': 'pulse',
                                        'text': 'Pulse'
                                    },
                                    {
                                        'id': 'esd',
                                        'text': 'ESD'
                                    },
                                ],
                                tab=gui.ADVANCED_TAB)

    keyboardLayout = gui.TextField(
        label=_('Keyboard'),
        order=31,
        tooltip=_(
            'Keyboard layout (es, us, fr, ...). Empty value means autodetect.'
        ),
        defvalue='',
        tab=gui.ADVANCED_TAB)
    # 'nopack', '8', '64', '256', '512', '4k', '32k', '64k', '256k', '2m', '16m'
    # '256-rdp', '256-rdp-compressed', '32k-rdp', '32k-rdp-compressed', '64k-rdp'
    # '64k-rdp-compressed', '16m-rdp', '16m-rdp-compressed'
    # 'rfb-hextile', 'rfb-tight', 'rfb-tight-compressed'
    # '8-tight', '64-tight', '256-tight', '512-tight', '4k-tight', '32k-tight'
    # '64k-tight', '256k-tight', '2m-tight', '16m-tight'
    # '8-jpeg-%', '64-jpeg', '256-jpeg', '512-jpeg', '4k-jpeg', '32k-jpeg'
    # '64k-jpeg', '256k-jpeg', '2m-jpeg', '16m-jpeg-%'
    # '8-png-jpeg-%', '64-png-jpeg', '256-png-jpeg', '512-png-jpeg', '4k-png-jpeg'
    # '32k-png-jpeg', '64k-png-jpeg', '256k-png-jpeg', '2m-png-jpeg', '16m-png-jpeg-%'
    # '8-png-%', '64-png', '256-png', '512-png', '4k-png'
    # '32k-png', '64k-png', '256k-png', '2m-png', '16m-png-%'
    # '16m-rgb-%', '16m-rle-%'
    pack = gui.TextField(label=_('Pack'),
                         order=32,
                         tooltip=_('Pack format. Change with care!'),
                         defvalue='16m-jpeg',
                         tab=gui.ADVANCED_TAB)

    quality = gui.NumericField(
        label=_('Quality'),
        order=33,
        tooltip=_('Quality value used on some pack formats.'),
        length=1,
        defvalue='6',
        minValue=1,
        maxValue=9,
        required=True,
        tab=gui.ADVANCED_TAB)

    def isAvailableFor(self, userService, ip):
        """
        Checks if the transport is available for the requested destination ip
        Override this in yours transports
        """
        logger.debug('Checking availability for {0}'.format(ip))
        ready = self.cache.get(ip)
        if ready is None:
            # Check again for ready
            if connection.testServer(ip, '22') is True:
                self.cache.put(ip, 'Y', READY_CACHE_TIMEOUT)
                return True
            else:
                self.cache.put(ip, 'N', READY_CACHE_TIMEOUT)
        return ready == 'Y'

    def processedUser(self, userService, userName):
        v = self.processUserPassword(userService, userName, '')
        return v['username']

    def processUserPassword(self, service, user, password):
        username = user.getUsernameForAuth()

        if self.fixedName.value != '':
            username = self.fixedName.value

        # Fix username/password acording to os manager
        username, password = service.processUserPassword(username, password)

        return {
            'protocol': self.protocol,
            'username': username,
            'password': ''
        }

    def getConnectionInfo(
        self, service, user, password
    ):  # Password is ignored in this transport, auth is done using SSH
        return self.processUserPassword(service, user, password)

    def genKeyPairForSsh(self):
        """
        Generates a key pair for use with x2go
        The private part is used by client
        the public part must be "appended" to authorized_keys if it is not already added.
        If .ssh folder does not exists, it must be created
        if authorized_keys does not exists, it must be created
        On key adition, we can look for every key that has a "UDS@X2GOCLIENT" as comment, so we can remove them before adding new ones

        Windows (tested):
            C:\Program Files (x86)\\x2goclient>x2goclient.exe --session-conf=c:/temp/sessions --session=UDS/test-session --close-disconnect --hide --no-menu
        Linux (tested):
            HOME=[temporal folder, where we create a .x2goclient folder and a sessions inside] pyhoca-cli -P UDS/test-session
        """
        key = paramiko.RSAKey.generate(SSH_KEY_LENGTH)
        privFile = six.StringIO()
        key.write_private_key(privFile)
        priv = privFile.getvalue()

        pub = key.get_base64(
        )  # 'ssh-rsa {} UDS@X2GOCLIENT'.format(key.get_base64())
        return priv, pub

    def getAuthorizeScript(self, user, pubKey):
        return self.getScript('scripts/authorize.py').replace(
            '__USER__', user).replace('__KEY__', pubKey)

    def getAndPushKey(self, user, userService):
        priv, pub = self.genKeyPairForSsh()
        authScript = self.getAuthorizeScript(user, pub)
        userServiceManager().sendScript(userService, authScript)
        return priv, pub

    def getScript(self, script):
        with open(os.path.join(os.path.dirname(__file__), script)) as f:
            data = f.read()
        return data
Ejemplo n.º 16
0
class NXTransport(Transport):
    '''
    Provides access via RDP to service.
    This transport can use an domain. If username processed by authenticator contains '@', it will split it and left-@-part will be username, and right password
    '''
    typeName = _('NX Transport (direct)')
    typeType = 'NXTransport'
    typeDescription = _('NX Transport for direct connection')
    iconFile = 'nx.png'
    needsJava = True  # If this transport needs java for rendering
    protocol = protocols.NX

    useEmptyCreds = gui.CheckBoxField(
        label=_('Empty creds'),
        order=1,
        tooltip=_('If checked, the credentials used to connect will be emtpy'))
    fixedName = gui.TextField(
        label=_('Username'),
        order=2,
        tooltip=_(
            'If not empty, this username will be always used as credential'))
    fixedPassword = gui.PasswordField(
        label=_('Password'),
        order=3,
        tooltip=_(
            'If not empty, this password will be always used as credential'))
    listenPort = gui.NumericField(
        label=_('Listening port'),
        length=5,
        order=4,
        tooltip=_('Listening port of NX (ssh) at client machine'),
        defvalue='22')
    connection = gui.ChoiceField(
        label=_('Connection'),
        order=6,
        tooltip=_('Connection speed for this transport (quality)'),
        values=[{
            'id': 'modem',
            'text': 'modem'
        }, {
            'id': 'isdn',
            'text': 'isdn'
        }, {
            'id': 'adsl',
            'text': 'adsl'
        }, {
            'id': 'wan',
            'text': 'wan'
        }, {
            'id': 'lan',
            'text': 'lan'
        }])
    session = gui.ChoiceField(label=_('Session'),
                              order=7,
                              tooltip=_('Desktop session'),
                              values=[
                                  {
                                      'id': 'gnome',
                                      'text': 'gnome'
                                  },
                                  {
                                      'id': 'kde',
                                      'text': 'kde'
                                  },
                                  {
                                      'id': 'cde',
                                      'text': 'cde'
                                  },
                              ])
    cacheDisk = gui.ChoiceField(label=_('Disk Cache'),
                                order=8,
                                tooltip=_('Cache size en Mb stored at disk'),
                                values=[
                                    {
                                        'id': '0',
                                        'text': '0 Mb'
                                    },
                                    {
                                        'id': '32',
                                        'text': '32 Mb'
                                    },
                                    {
                                        'id': '64',
                                        'text': '64 Mb'
                                    },
                                    {
                                        'id': '128',
                                        'text': '128 Mb'
                                    },
                                    {
                                        'id': '256',
                                        'text': '256 Mb'
                                    },
                                    {
                                        'id': '512',
                                        'text': '512 Mb'
                                    },
                                ])
    cacheMem = gui.ChoiceField(label=_('Memory Cache'),
                               order=9,
                               tooltip=_('Cache size en Mb kept at memory'),
                               values=[
                                   {
                                       'id': '4',
                                       'text': '4 Mb'
                                   },
                                   {
                                       'id': '8',
                                       'text': '8 Mb'
                                   },
                                   {
                                       'id': '16',
                                       'text': '16 Mb'
                                   },
                                   {
                                       'id': '32',
                                       'text': '32 Mb'
                                   },
                                   {
                                       'id': '64',
                                       'text': '64 Mb'
                                   },
                                   {
                                       'id': '128',
                                       'text': '128 Mb'
                                   },
                               ])

    def __init__(self, environment, values=None):
        super(NXTransport, self).__init__(environment, values)
        if values is not None:
            self._useEmptyCreds = gui.strToBool(values['useEmptyCreds'])
            self._fixedName = values['fixedName']
            self._fixedPassword = values['fixedPassword']
            self._listenPort = values['listenPort']
            self._connection = values['connection']
            self._session = values['session']
            self._cacheDisk = values['cacheDisk']
            self._cacheMem = values['cacheMem']
        else:
            self._useEmptyCreds = ''
            self._fixedName = ''
            self._fixedPassword = ''
            self._listenPort = ''
            self._connection = ''
            self._session = ''
            self._cacheDisk = ''
            self._cacheMem = ''

    def marshal(self):
        '''
        Serializes the transport data so we can store it in database
        '''
        return str.join('\t', [
            'v1',
            gui.boolToStr(self._useEmptyCreds), self._fixedName,
            self._fixedPassword, self._listenPort, self._connection,
            self._session, self._cacheDisk, self._cacheMem
        ])

    def unmarshal(self, string):
        data = string.split('\t')
        if data[0] == 'v1':
            self._useEmptyCreds = gui.strToBool(data[1])
            self._fixedName, self._fixedPassword, self._listenPort, self._connection, self._session, self._cacheDisk, self._cacheMem = data[
                2:]

    def valuesDict(self):
        return {
            'useEmptyCreds': gui.boolToStr(self._useEmptyCreds),
            'fixedName': self._fixedName,
            'fixedPassword': self._fixedPassword,
            'listenPort': self._listenPort,
            'connection': self._connection,
            'session': self._session,
            'cacheDisk': self._cacheDisk,
            'cacheMem': self._cacheMem
        }

    def isAvailableFor(self, ip):
        '''
        Checks if the transport is available for the requested destination ip
        Override this in yours transports
        '''
        logger.debug('Checking availability for {0}'.format(ip))
        ready = self.cache().get(ip)
        if ready is None:
            # Check again for readyness
            if connection.testServer(ip, self._listenPort) is True:
                self.cache().put(ip, 'Y', READY_CACHE_TIMEOUT)
                return True
            else:
                self.cache().put(ip, 'N', READY_CACHE_TIMEOUT)
        return ready == 'Y'

    def renderForHtml(self, userService, transport, ip, os, user, password):

        prefs = user.prefs('nx')

        username = user.getUsernameForAuth()
        proc = username.split('@')
        username = proc[0]
        if self._fixedName is not '':
            username = self._fixedName
        if self._fixedPassword is not '':
            password = self._fixedPassword
        if self._useEmptyCreds is True:
            username, password = '', ''

        # We have the credentials right now, let os manager

        width, height = CommonPrefs.getWidthHeight(prefs)

        # Extra data
        extra = {
            'width': width,
            'height': height,
            'port': self._listenPort,
            'connection': self._connection,
            'session': self._session,
            'cacheDisk': self._cacheDisk,
            'cacheMem': self._cacheMem
        }

        # Fix username/password acording to os manager
        username, password = userService.processUserPassword(
            username, password)

        return generateHtmlForNX(self, userService.uuid, transport.uuid, ip,
                                 os, username, password, extra)

    def getHtmlComponent(self, theId, os, componentId):
        # We use helper to keep this clean
        return getHtmlComponent(self.__module__, componentId)