Example #1
0
 def run(self) -> None:
     try:
         logger.debug('Executing script: {}'.format(self.script))
         exec(self.script, globals(), None)  # pylint: disable=exec-used
     except Exception as e:
         logger.error('Error executing script: {}'.format(e))
         logger.exception()
Example #2
0
    def do_POST(self):
        path = self.path.split('?')[0][1:].split('/')
        if path[0] != HTTPServerHandler.uuid:
            self.sendJsonError(403, 'Forbidden')
            return

        if len(path) != 2:
            self.sendJsonError(400, 'Invalid request')
            return

        try:
            HTTPServerHandler.lock.acquire()
            length = int(self.headers.getheader('content-length'))
            content = self.rfile.read(length)
            print(length, ">>", content, '<<')
            params = json.loads(content)

            operation = getattr(self, 'post_' + path[1])
            result = operation(params)  # Protect not POST methods
        except AttributeError:
            self.sendJsonError(404, 'Method not found')
            return
        except Exception as e:
            logger.error('Got exception executing POST {}: {}'.format(
                path[1], utils.toUnicode(e.message)))
            self.sendJsonError(500, str(e))
            return
        finally:
            HTTPServerHandler.lock.release()

        self.send_response(200)
        self.send_header('Content-type', 'application/json')
        self.end_headers()
        # Send the html message
        self.wfile.write(json.dumps(result))
Example #3
0
    def stop(self) -> None:
        """
        Stop the daemon
        """
        # Get the pid from the pidfile
        try:
            pf = open(self.pidfile, 'r')
            pid = int(pf.read().strip())
            pf.close()
        except IOError:
            message = "pidfile {} does not exist. Daemon not running?\n".format(
                self.pidfile)
            logger.error(message)
            # sys.stderr.write(message)
            return  # not an error in a restart

        # Try killing the daemon process
        try:
            cnt = 10
            while cnt:
                cnt -= 1
                os.kill(pid, SIGTERM)
                time.sleep(1)

            if not cnt:
                os.kill(pid, SIGKILL)
        except OSError as err:
            if err.errno == 3:  # No such process
                if os.path.exists(self.pidfile):
                    os.remove(self.pidfile)
            else:
                sys.stderr.write('Error: {}'.format(err))
                sys.exit(1)
Example #4
0
    def run(self):
        self.running = True

        self.serverSocket.bind(('localhost', self.port))
        self.serverSocket.setblocking(1)
        self.serverSocket.listen(4)

        while True:
            try:
                (clientSocket, address) = self.serverSocket.accept()
                # Stop processing if thread is mean to stop
                if self.running is False:
                    break
                logger.debug('Got connection from {}'.format(address))

                self.cleanupFinishedThreads()  # House keeping

                logger.debug('Starting new thread, current: {}'.format(
                    self.threads))
                t = ClientProcessor(self, clientSocket)
                self.threads.append(t)
                t.start()
            except Exception as e:
                logger.error(
                    'Got an exception on Server ipc thread: {}'.format(e))
Example #5
0
    def preConnect(self, user, protocol):
        logger.debug('Pre connect invoked')
        if protocol != 'rdp':  # If connection is not using rdp, skip adding user
            return 'ok'
        # Well known SSID for Remote Desktop Users
        REMOTE_USERS_SID = 'S-1-5-32-555'

        p = win32security.GetBinarySid(REMOTE_USERS_SID)
        groupName = win32security.LookupAccountSid(None, p)[0]

        useraAlreadyInGroup = False
        resumeHandle = 0
        while True:
            users, _, resumeHandle = win32net.NetLocalGroupGetMembers(None, groupName, 1, resumeHandle, 32768)
            if user in [u['name'] for u in users]:
                useraAlreadyInGroup = True
                break
            if resumeHandle == 0:
                break

        if useraAlreadyInGroup is False:
            logger.debug('User not in group, adding it')
            self._user = user
            try:
                userSSID = win32security.LookupAccountName(None, user)[0]
                win32net.NetLocalGroupAddMembers(None, groupName, 0, [{'sid': userSSID}])
            except Exception as e:
                logger.error('Exception adding user to Remote Desktop Users: {}'.format(e))
        else:
            self._user = None
            logger.debug('User {} already in group'.format(user))

        return 'ok'
Example #6
0
    def run(self):
        self.running = True

        while self.running:
            try:
                msg = b''
                # We look for magic message header
                while self.running:  # Wait for MAGIC
                    try:
                        buf = self.clientSocket.recv(len(MAGIC) - len(msg))
                        if buf == b'':
                            self.running = False
                            break
                        msg += buf
                        if len(msg) != len(MAGIC):
                            continue  # Do not have message
                        if msg != MAGIC:  # Skip first byte an continue searchong
                            msg = msg[1:]
                            continue
                        break
                    except socket.timeout:  # Timeout is here so we can get stop thread
                        continue

                if self.running is False:
                    break

                # Now we get message basic data (msg + datalen)
                msg = bytearray(self.receiveBytes(3))

                # We have the magic header, here comes the message itself
                if msg is None:
                    continue

                msgId = msg[0]
                dataLen = msg[1] + (msg[2] << 8)
                if msgId not in VALID_MESSAGES:
                    raise Exception('Invalid message id: {}'.format(msgId))

                data = self.receiveBytes(dataLen)
                if data is None:
                    continue

                self.messages.put((msgId, data))
                self.messageReceived()

            except socket.error as e:
                if e.errno == errno.EINTR:
                    time.sleep(1)  #
                    continue  # Ignore interrupted system call
                logger.error('Communication with server got an error: {}'.format(toUnicode(e.strerror)))
                # self.running = False
                return
            except Exception as e:
                tb = traceback.format_exc()
                logger.error('Error: {}, trace: {}'.format(e, tb))

        try:
            self.clientSocket.close()
        except Exception:
            pass  # If can't close, nothing happens, just end thread
Example #7
0
    def do_POST(self):
        path = self.path.split('?')[0][1:].split('/')
        if path[0] != HTTPServerHandler.uuid:
            self.sendJsonError(403, 'Forbidden')
            return

        if len(path) != 2:
            self.sendJsonError(400, 'Invalid request')
            return

        try:
            HTTPServerHandler.lock.acquire()
            length = int(self.headers.getheader('content-length'))
            content = self.rfile.read(length)
            print(length, ">>", content, '<<')
            params = json.loads(content)

            operation = getattr(self, 'post_' + path[1])
            result = operation(params)  # Protect not POST methods
        except AttributeError:
            self.sendJsonError(404, 'Method not found')
            return
        except Exception as e:
            logger.error('Got exception executing POST {}: {}'.format(path[1], utils.toUnicode(e.message)))
            self.sendJsonError(500, str(e))
            return
        finally:
            HTTPServerHandler.lock.release()

        self.send_response(200)
        self.send_header('Content-type', 'application/json')
        self.end_headers()
        # Send the html message
        self.wfile.write(json.dumps(result))
Example #8
0
    def start(self):
        """
        Start the daemon
        """
        logger.debug('Starting daemon')
        # Check for a pidfile to see if the daemon already runs
        try:
            pf = open(self.pidfile, 'r')
            pid = int(pf.read().strip())
            pf.close()
        except IOError:
            pid = None

        if pid:
            message = "pidfile {} already exist. Daemon already running?\n".format(
                pid)
            logger.error(message)
            sys.stderr.write(message)
            sys.exit(1)

        # Start the daemon
        self.daemonize()
        try:
            self.run()
        except Exception as e:
            logger.error('Exception running process: {}'.format(e))

        if os.path.exists(self.pidfile):
            os.remove(self.pidfile)
Example #9
0
    def run(self):
        self.running = True

        while self.running:
            try:
                msg = b''
                # We look for magic message header
                while self.running:  # Wait for MAGIC
                    try:
                        buf = self.clientSocket.recv(len(MAGIC) - len(msg))
                        if buf == b'':
                            self.running = False
                            break
                        msg += buf
                        if len(msg) != len(MAGIC):
                            continue  # Do not have message
                        if msg != MAGIC:  # Skip first byte an continue searchong
                            msg = msg[1:]
                            continue
                        break
                    except socket.timeout:  # Timeout is here so we can get stop thread
                        continue

                if self.running is False:
                    break

                # Now we get message basic data (msg + datalen)
                msg = bytearray(self.receiveBytes(3))

                # We have the magic header, here comes the message itself
                if msg is None:
                    continue

                msgId = msg[0]
                dataLen = msg[1] + (msg[2] << 8)
                if msgId not in VALID_MESSAGES:
                    raise Exception('Invalid message id: {}'.format(msgId))

                data = self.receiveBytes(dataLen)
                if data is None:
                    continue

                self.messages.put((msgId, data))
                self.messageReceived()

            except socket.error as e:
                if e.errno == errno.EINTR:
                    time.sleep(1)  #
                    continue  # Ignore interrupted system call
                logger.error('Communication with server got an error: {}'.format(toUnicode(e.strerror)))
                # self.running = False
                return
            except Exception as e:
                tb = traceback.format_exc()
                logger.error('Error: {}, trace: {}'.format(e, tb))

        try:
            self.clientSocket.close()
        except Exception:
            pass  # If can't close, nothing happens, just end thread
Example #10
0
    def do_GET(self):
        # Very simple path & params splitter
        path = self.path.split('?')[0][1:].split('/')
        try:
            params = dict(
                (v.split('=') for v in self.path.split('?')[1].split('&')))
        except Exception:
            params = {}

        if path[0] != HTTPServerHandler.uuid:
            self.sendJsonError(403, 'Forbidden')
            return

        if len(path) != 2:
            self.sendJsonResponse(
                "UDS Actor has been running for {} seconds".format(
                    time.time() - startTime))
            return

        try:
            operation = getattr(self, 'get_' + path[1])
            result = operation(params)  # Protect not POST methods
        except AttributeError:
            self.sendJsonError(404, 'Method not found')
            return
        except Exception as e:
            logger.error('Got exception executing GET {}: {}'.format(
                path[1], utils.toUnicode(e.message)))
            self.sendJsonError(500, str(e))
            return

        self.sendJsonResponse(result)
Example #11
0
    def do_POST(self):
        path = self.path.split('?')[0][1:].split('/')
        if path[0] != HTTPServerHandler.uuid:
            self.sendJsonError(403, 'Forbidden')
            return

        if len(path) != 2:
            self.sendJsonError(400, 'Invalid request')
            return

        try:
            HTTPServerHandler.lock.acquire()
            length = int(self.headers.get('content-length'))
            content = self.rfile.read(length).decode('utf8')
            logger.debug('length: {}, content >>{}<<'.format(length, content))
            params = json.loads(content)

            operation = getattr(self, 'post_' + path[1])
            result = operation(params)  # Protect not POST methods
        except AttributeError:
            self.sendJsonError(404, 'Method not found')
            return
        except Exception as e:
            logger.error('Got exception executing POST {}: {}'.format(
                path[1], utils.toUnicode(e.message)))
            self.sendJsonError(500, str(e))
            return
        finally:
            HTTPServerHandler.lock.release()

        self.sendJsonResponse(result)
Example #12
0
    def start(self):
        """
        Start the daemon
        """
        logger.debug('Starting daemon')
        # Check for a pidfile to see if the daemon already runs
        try:
            pf = open(self.pidfile, 'r')
            pid = int(pf.read().strip())
            pf.close()
        except IOError:
            pid = None

        if pid:
            message = "pidfile {} already exist. Daemon already running?\n".format(pid)
            logger.error(message)
            sys.stderr.write(message)
            sys.exit(1)

        # Start the daemon
        self.daemonize()
        try:
            self.run()
        except Exception as e:
            logger.error('Exception running process: {}'.format(e))

        if os.path.exists(self.pidfile):
            os.remove(self.pidfile)
Example #13
0
    def run(self):
        if self.ipc is None:
            return
        self.running = True

        # Wait a bit so we ensure IPC thread is running...
        time.sleep(2)

        while self.running and self.ipc.running:
            try:
                msg = self.ipc.getMessage()
                if msg is None:
                    break
                msgId, data = msg
                logger.debug('Got Message on User Space: {}:{}'.format(msgId, data))
                if msgId == ipc.MSG_MESSAGE:
                    self.displayMessage.emit(QtCore.QString.fromUtf8(data))
                elif msgId == ipc.MSG_LOGOFF:
                    self.logoff.emit()
                elif msgId == ipc.MSG_SCRIPT:
                    self.script.emit(QtCore.QString.fromUtf8(data))
                elif msgId == ipc.MSG_INFORMATION:
                    self.information.emit(pickle.loads(data))
            except Exception as e:
                try:
                    logger.error('Got error on IPC thread {}'.format(utils.exceptionToMessage(e)))
                except:
                    logger.error('Got error on IPC thread (an unicode error??)')

        if self.ipc.running is False and self.running is True:
            logger.warn('Lost connection with Service, closing program')

        self.exit.emit()
Example #14
0
    def do_GET(self):
        # Very simple path & params splitter
        path = self.path.split('?')[0][1:].split('/')
        try:
            params = dict((v.split('=') for v in self.path.split('?')[1].split('&')))
        except Exception:
            params = {}

        if path[0] != HTTPServerHandler.uuid:
            self.sendJsonError(403, 'Forbidden')
            return

        if len(path) != 2:
            self.sendJsonResponse("UDS Actor has been running for {} seconds".format(time.time() - startTime))
            return

        try:
            operation = getattr(self, 'get_' + path[1])
            result = operation(params)  # Protect not POST methods
        except AttributeError:
            self.sendJsonError(404, 'Method not found')
            return
        except Exception as e:
            logger.error('Got exception executing GET {}: {}'.format(path[1], utils.toUnicode(e.message)))
            self.sendJsonError(500, str(e))
            return

        self.sendJsonResponse(result)
Example #15
0
    def endAPI(self):
        if self.api is not None:
            try:
                self.api.notifyComm(None)
            except Exception:
                logger.error('Couln\'t remove comms url from broker')

        self.notifyStop()
Example #16
0
    def endAPI(self):
        if self.api is not None:
            try:
                self.api.notifyComm(None)
            except Exception:
                logger.error('Couln\'t remove comms url from broker')

        self.notifyStop()
Example #17
0
 def endAPI(self):
     if self.api is not None:
         try:
             if self.loggedIn:
                 self.loggedIn = False
                 self.api.logout('service_stopped')
             self.api.notifyComm(None)
         except Exception as e:
             logger.error('Couln\'t remove comms url from broker: {}'.format(e))
Example #18
0
 def endAPI(self):
     if self.api is not None:
         try:
             if self.loggedIn:
                 self.loggedIn = False
                 self.api.logout('service_stopped')
             self.api.notifyComm(None)
         except Exception as e:
             logger.error(
                 'Couln\'t remove comms url from broker: {}'.format(e))
Example #19
0
    def preConnect(self, user, protocol):
        logger.debug('Pre connect invoked')
        if protocol != 'rdp':  # If connection is not using rdp, skip adding user
            return 'ok'
        # Well known SSID for Remote Desktop Users
        REMOTE_USERS_SID = 'S-1-5-32-555'

        p = win32security.GetBinarySid(REMOTE_USERS_SID)
        groupName = win32security.LookupAccountSid(None, p)[0]

        useraAlreadyInGroup = False
        resumeHandle = 0
        while True:
            users, _, resumeHandle = win32net.NetLocalGroupGetMembers(
                None, groupName, 1, resumeHandle, 32768)
            if user.lower() in [u['name'].lower() for u in users]:
                useraAlreadyInGroup = True
                break
            if resumeHandle == 0:
                break

        if useraAlreadyInGroup is False:
            logger.debug('User not in group, adding it')
            self._user = user
            try:
                userSSID = win32security.LookupAccountName(None, user)[0]
                win32net.NetLocalGroupAddMembers(None, groupName, 0,
                                                 [{
                                                     'sid': userSSID
                                                 }])
            except Exception as e:
                logger.error(
                    'Exception adding user to Remote Desktop Users: {}'.format(
                        e))
        else:
            self._user = None
            logger.debug('User {} already in group'.format(user))

        # Now try to run pre connect command
        try:
            pre_cmd = store.preApplication()
            if os.path.isfile(pre_cmd):
                if (os.stat(pre_cmd).st_mode & stat.S_IXUSR) != 0:
                    subprocess.call([pre_cmd, user, protocol])
                else:
                    logger.info(
                        'PRECONNECT file exists but it it is not executable (needs execution permission by root)'
                    )
            else:
                logger.info('PRECONNECT file not found & not executed')
        except Exception as e:
            # Ignore output of execution command
            logger.error('Executing preconnect command give')

        return 'ok'
Example #20
0
 def endIPC(self):
     # Remove IPC threads
     if self.ipc is not None:
         try:
             self.ipc.stop()
         except Exception:
             logger.error('Couln\'t stop ipc server')
     if self.httpServer is not None:
         try:
             self.httpServer.stop()
         except Exception:
             logger.error('Couln\'t stop REST server')
Example #21
0
 def endIPC(self):
     # Remove IPC threads
     if self.ipc is not None:
         try:
             self.ipc.stop()
         except Exception:
             logger.error('Couln\'t stop ipc server')
     if self.httpServer is not None:
         try:
             self.httpServer.stop()
         except Exception:
             logger.error('Couln\'t stop REST server')
Example #22
0
def joinDomain(domain, ou, account, password, executeInOneStep=False):
    '''
    Joins machine to a windows domain
    :param domain: Domain to join to
    :param ou: Ou that will hold machine
    :param account: Account used to join domain
    :param password: Password of account used to join domain
    :param executeInOneStep: If true, means that this machine has been renamed and wants to add NETSETUP_JOIN_WITH_NEW_NAME to request so we can do rename/join in one step.
    '''
    # If account do not have domain, include it
    if '@' not in account and '\\' not in account:
        if '.' in domain:
            account = account + '@' + domain
        else:
            account = domain + '\\' + account

    # Do log
    flags = NETSETUP_ACCT_CREATE | NETSETUP_DOMAIN_JOIN_IF_JOINED | NETSETUP_JOIN_DOMAIN

    if executeInOneStep:
        flags |= NETSETUP_JOIN_WITH_NEW_NAME

    flags = DWORD(flags)

    domain = LPCWSTR(domain)

    # Must be in format "ou=.., ..., dc=...,"
    ou = LPCWSTR(ou) if ou is not None and ou != '' else None
    account = LPCWSTR(account)
    password = LPCWSTR(password)

    res = ctypes.windll.netapi32.NetJoinDomain(None, domain, ou, account,
                                               password, flags)
    # Machine found in another ou, use it and warn this on log
    if res == 2224:
        flags = DWORD(NETSETUP_DOMAIN_JOIN_IF_JOINED | NETSETUP_JOIN_DOMAIN)
        res = ctypes.windll.netapi32.NetJoinDomain(None, domain, None, account,
                                                   password, flags)
    if res != 0:
        # Log the error
        error = getErrorMessage(res)
        if res == 1355:
            error = "DC Is not reachable"
        logger.error('Error joining domain: {}, {}'.format(error, res))
        raise Exception(
            'Error joining domain {}, with credentials {}/*****{}: {}, {}'.
            format(domain, account,
                   ', under OU {}'.format(ou) if ou is not None else '', res,
                   error))
Example #23
0
    def onLogout(self, user):
        logger.debug('Windows onLogout invoked: {}, {}'.format(user, self._user))
        try:
            REMOTE_USERS_SID = 'S-1-5-32-555'
            p = win32security.GetBinarySid(REMOTE_USERS_SID)
            groupName = win32security.LookupAccountSid(None, p)[0]
        except Exception:
            logger.error('Exception getting Windows Group')
            return

        if self._user is not None:
            try:
                win32net.NetLocalGroupDelMembers(None, groupName, [self._user])
            except Exception as e:
                logger.error('Exception removing user from Remote Desktop Users: {}'.format(e))
Example #24
0
def getIdleDuration():
    try:
        lastInputInfo = LASTINPUTINFO()
        lastInputInfo.cbSize = ctypes.sizeof(lastInputInfo)
        if ctypes.windll.user32.GetLastInputInfo(ctypes.byref(lastInputInfo)) == 0:
            return 0
        # if lastInputInfo.dwTime > 1000000000:  # Value toooo high, nonsense...
        #    return 0
        millis = ctypes.windll.kernel32.GetTickCount() - lastInputInfo.dwTime  # @UndefinedVariable
        if millis < 0 or millis > 1000000000:
            return 0
        return millis / 1000.0
    except Exception as e:
        logger.error('Getting idle duration: {}'.format(e))
        return 0
Example #25
0
    def onLogout(self, user):
        logger.debug('Windows onLogout invoked: {}, {}'.format(user, self._user))
        try:
            REMOTE_USERS_SID = 'S-1-5-32-555'
            p = win32security.GetBinarySid(REMOTE_USERS_SID)
            groupName = win32security.LookupAccountSid(None, p)[0]
        except Exception:
            logger.error('Exception getting Windows Group')
            return

        if self._user is not None:
            try:
                win32net.NetLocalGroupDelMembers(None, groupName, [self._user])
            except Exception as e:
                logger.error('Exception removing user from Remote Desktop Users: {}'.format(e))
Example #26
0
    def daemonize(self):
        """
        do the UNIX double-fork magic, see Stevens' "Advanced
        Programming in the UNIX Environment" for details (ISBN 0201563177)
        http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
        """
        try:
            pid = os.fork()
            if pid > 0:
                # exit first parent
                sys.exit(0)
        except OSError as e:
            logger.error("fork #1 error: {}".format(e))
            sys.stderr.write("fork #1 failed: {}\n".format(e))
            sys.exit(1)

        # decouple from parent environment
        os.chdir("/")
        os.setsid()
        os.umask(0)

        # do second fork
        try:
            pid = os.fork()
            if pid > 0:
                # exit from second parent
                sys.exit(0)
        except OSError as e:
            logger.error("fork #2 error: {}".format(e))
            sys.stderr.write("fork #2 failed: {}\n".format(e))
            sys.exit(1)

        # redirect standard file descriptors
        sys.stdout.flush()
        sys.stderr.flush()
        si = open(self.stdin, 'r')
        so = open(self.stdout, 'a+')
        se = open(self.stderr, 'a+', 0)
        os.dup2(si.fileno(), sys.stdin.fileno())
        os.dup2(so.fileno(), sys.stdout.fileno())
        os.dup2(se.fileno(), sys.stderr.fileno())

        # write pidfile
        atexit.register(self.delpid)
        pid = str(os.getpid())
        with open(self.pidfile, 'w+') as f:
            f.write("{}\n".format(pid))
Example #27
0
    def preConnect(self, user, protocol):
        logger.debug('Pre connect invoked')
        if protocol != 'rdp':  # If connection is not using rdp, skip adding user
            return 'ok'
        # Well known SSID for Remote Desktop Users
        REMOTE_USERS_SID = 'S-1-5-32-555'

        p = win32security.GetBinarySid(REMOTE_USERS_SID)
        groupName = win32security.LookupAccountSid(None, p)[0]

        useraAlreadyInGroup = False
        resumeHandle = 0
        while True:
            users, _, resumeHandle = win32net.NetLocalGroupGetMembers(None, groupName, 1, resumeHandle, 32768)
            if user.lower() in [u['name'].lower() for u in users]:
                useraAlreadyInGroup = True
                break
            if resumeHandle == 0:
                break

        if useraAlreadyInGroup is False:
            logger.debug('User not in group, adding it')
            self._user = user
            try:
                userSSID = win32security.LookupAccountName(None, user)[0]
                win32net.NetLocalGroupAddMembers(None, groupName, 0, [{'sid': userSSID}])
            except Exception as e:
                logger.error('Exception adding user to Remote Desktop Users: {}'.format(e))
        else:
            self._user = None
            logger.debug('User {} already in group'.format(user))

        # Now try to run pre connect command
        try:
            pre_cmd = store.preApplication()
            if os.path.isfile(pre_cmd):
                if (os.stat(pre_cmd).st_mode & stat.S_IXUSR) != 0:
                    subprocess.call([pre_cmd, user, protocol])
                else:
                    logger.info('PRECONNECT file exists but it it is not executable (needs execution permission by root)')
            else:
                logger.info('PRECONNECT file not found & not executed')
        except Exception as e:
            # Ignore output of execution command
            logger.error('Executing preconnect command give')

        return 'ok'
Example #28
0
    def daemonize(self):
        """
        do the UNIX double-fork magic, see Stevens' "Advanced
        Programming in the UNIX Environment" for details (ISBN 0201563177)
        http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
        """
        try:
            pid = os.fork()
            if pid > 0:
                # exit first parent
                sys.exit(0)
        except OSError as e:
            logger.error("fork #1 error: {}".format(e))
            sys.stderr.write("fork #1 failed: {}\n".format(e))
            sys.exit(1)

        # decouple from parent environment
        os.chdir("/")
        os.setsid()
        os.umask(0)

        # do second fork
        try:
            pid = os.fork()
            if pid > 0:
                # exit from second parent
                sys.exit(0)
        except OSError as e:
            logger.error("fork #2 error: {}".format(e))
            sys.stderr.write("fork #2 failed: {}\n".format(e))
            sys.exit(1)

        # redirect standard file descriptors
        sys.stdout.flush()
        sys.stderr.flush()
        si = open(self.stdin, 'r')
        so = open(self.stdout, 'a+')
        se = open(self.stderr, 'a+', 0)
        os.dup2(si.fileno(), sys.stdin.fileno())
        os.dup2(so.fileno(), sys.stdout.fileno())
        os.dup2(se.fileno(), sys.stderr.fileno())

        # write pidfile
        atexit.register(self.delpid)
        pid = str(os.getpid())
        with open(self.pidfile, 'w+') as f:
            f.write("{}\n".format(pid))
Example #29
0
def getIdleDuration():
    try:
        lastInputInfo = LASTINPUTINFO()
        lastInputInfo.cbSize = ctypes.sizeof(lastInputInfo)
        if ctypes.windll.user32.GetLastInputInfo(
                ctypes.byref(lastInputInfo)) == 0:
            return 0
        # if lastInputInfo.dwTime > 1000000000:  # Value toooo high, nonsense...
        #    return 0
        millis = ctypes.windll.kernel32.GetTickCount(
        ) - lastInputInfo.dwTime  # @UndefinedVariable
        if millis < 0 or millis > 1000000000:
            return 0
        return millis / 1000.0
    except Exception as e:
        logger.error('Getting idle duration: {}'.format(e))
        return 0
Example #30
0
    def preConnect(self, user, protocol):
        '''
        Invoked when received a PRE Connection request via REST
        '''
        # Execute script in /etc/udsactor/post after interacting with broker, if no reboot is requested ofc
        # This will be executed only when machine gets "ready"
        try:

            if os.path.isfile(PRECONNECT_CMD):
                if (os.stat(PRECONNECT_CMD).st_mode & stat.S_IXUSR) != 0:
                    subprocess.call([PRECONNECT_CMD, user, protocol])
                else:
                    logger.info('PRECONNECT file exists but it it is not executable (needs execution permission by root)')
            else:
                logger.info('PRECONNECT file not found & not executed')
        except Exception as e:
            # Ignore output of execution command
            logger.error('Executing preconnect command give')
Example #31
0
def joinDomain(domain, ou, account, password, executeInOneStep=False):
    '''
    Joins machine to a windows domain
    :param domain: Domain to join to
    :param ou: Ou that will hold machine
    :param account: Account used to join domain
    :param password: Password of account used to join domain
    :param executeInOneStep: If true, means that this machine has been renamed and wants to add NETSETUP_JOIN_WITH_NEW_NAME to request so we can do rename/join in one step.
    '''
    # If account do not have domain, include it
    if '@' not in account and '\\' not in account:
        if '.' in domain:
            account = account + '@' + domain
        else:
            account = domain + '\\' + account

    # Do log
    flags = NETSETUP_ACCT_CREATE | NETSETUP_DOMAIN_JOIN_IF_JOINED | NETSETUP_JOIN_DOMAIN

    if executeInOneStep:
        flags |= NETSETUP_JOIN_WITH_NEW_NAME

    flags = DWORD(flags)

    domain = LPCWSTR(domain)

    # Must be in format "ou=.., ..., dc=...,"
    ou = LPCWSTR(ou) if ou is not None and ou != '' else None
    account = LPCWSTR(account)
    password = LPCWSTR(password)

    res = ctypes.windll.netapi32.NetJoinDomain(None, domain, ou, account, password, flags)
    # Machine found in another ou, use it and warn this on log
    if res == 2224:
        flags = DWORD(NETSETUP_DOMAIN_JOIN_IF_JOINED | NETSETUP_JOIN_DOMAIN)
        res = ctypes.windll.netapi32.NetJoinDomain(None, domain, None, account, password, flags)
    if res != 0:
        # Log the error
        error = getErrorMessage(res)
        if res == 1355:
            error = "DC Is not reachable"
        logger.error('Error joining domain: {}, {}'.format(error, res))
        raise Exception('Error joining domain {}, with credentials {}/*****{}: {}, {}'.format(domain, account, ', under OU {}'.format(ou) if ou is not None else '', res, error))
Example #32
0
    def start(self) -> None:
        """
        Start the daemon
        """
        logger.debug('Starting daemon')
        # Check for a pidfile to see if the daemon already runs
        if os.path.exists(self.pidfile):
            message = "pidfile {} already exist. Daemon already running?\n".format(
                self.pidfile)
            logger.error(message)
            sys.stderr.write(message)
            sys.exit(1)

        # Start the daemon
        self.daemonize()
        try:
            self.run()
        except Exception as e:
            logger.error('Exception running process: {}'.format(e))

        self.removePidFile()
Example #33
0
    def preConnect(self, user, protocol):
        logger.debug('Pre connect invoked')
        if protocol != 'rdp':  # If connection is not using rdp, skip adding user
            return 'ok'
        # Well known SSID for Remote Desktop Users
        REMOTE_USERS_SID = 'S-1-5-32-555'

        p = win32security.GetBinarySid(REMOTE_USERS_SID)
        groupName = win32security.LookupAccountSid(None, p)[0]

        useraAlreadyInGroup = False
        resumeHandle = 0
        while True:
            users, _, resumeHandle = win32net.NetLocalGroupGetMembers(
                None, groupName, 1, resumeHandle, 32768)
            if user.lower() in [u['name'].lower() for u in users]:
                useraAlreadyInGroup = True
                break
            if resumeHandle == 0:
                break

        if useraAlreadyInGroup is False:
            logger.debug('User not in group, adding it')
            self._user = user
            try:
                userSSID = win32security.LookupAccountName(None, user)[0]
                win32net.NetLocalGroupAddMembers(None, groupName, 0,
                                                 [{
                                                     'sid': userSSID
                                                 }])
            except Exception as e:
                logger.error(
                    'Exception adding user to Remote Desktop Users: {}'.format(
                        e))
        else:
            self._user = None
            logger.debug('User {} already in group'.format(user))

        return 'ok'
Example #34
0
    def run(self):
        self.running = True

        self.serverSocket.bind(('localhost', self.port))
        self.serverSocket.setblocking(1)
        self.serverSocket.listen(4)

        while True:
            try:
                (clientSocket, address) = self.serverSocket.accept()
                # Stop processing if thread is mean to stop
                if self.running is False:
                    break
                logger.debug('Got connection from {}'.format(address))

                self.cleanupFinishedThreads()  # House keeping

                logger.debug('Starting new thread, current: {}'.format(self.threads))
                t = ClientProcessor(self, clientSocket)
                self.threads.append(t)
                t.start()
            except Exception as e:
                logger.error('Got an exception on Server ipc thread: {}'.format(e))
Example #35
0
    def run(self):
        if self.ipc is None:
            return
        self.running = True

        # Wait a bit so we ensure IPC thread is running...
        time.sleep(2)

        while self.running and self.ipc.running:
            try:
                msg = self.ipc.getMessage()
                if msg is None:
                    break
                msgId, data = msg
                logger.debug('Got Message on User Space: {}:{}'.format(
                    msgId, data))
                if msgId == ipc.MSG_MESSAGE:
                    self.displayMessage.emit(QtCore.QString.fromUtf8(data))
                elif msgId == ipc.MSG_LOGOFF:
                    self.logoff.emit()
                elif msgId == ipc.MSG_SCRIPT:
                    self.script.emit(QtCore.QString.fromUtf8(data))
                elif msgId == ipc.MSG_INFORMATION:
                    self.information.emit(pickle.loads(data))
            except Exception as e:
                try:
                    logger.error('Got error on IPC thread {}'.format(
                        utils.exceptionToMessage(e)))
                except:
                    logger.error(
                        'Got error on IPC thread (an unicode error??)')

        if self.ipc.running is False and self.running is True:
            logger.warn('Lost connection with Service, closing program')

        self.exit.emit()
Example #36
0
    def execute(self, cmdLine, section):
        cmd = shlex.split(cmdLine, posix=False)

        if os.path.isfile(cmd[0]):
            if (os.stat(cmd[0]).st_mode & stat.S_IXUSR) != 0:
                try:
                    res = subprocess.check_call(cmd)
                except Exception as e:
                    logger.error('Got exception executing: {} - {}'.format(cmdLine, e))
                    return False
                logger.info('Result of executing cmd was {}'.format(res))
                return True
            else:
                logger.error('{} file exists but it it is not executable (needs execution permission by admin/root)'.format(section))
        else:
            logger.error('{} file not found & not executed'.format(section))

        return False
Example #37
0
    def interactWithBroker(self):
        '''
        Returns True to continue to main loop, false to stop & exit service
        '''
        # If no configuration is found, stop service
        if cfg is None:
            logger.fatal('No configuration found, stopping service')
            return False

        self.api = REST.Api(cfg['host'], cfg['masterKey'], cfg['ssl'])

        # Wait for Broker to be ready
        counter = 0
        while self.isAlive:
            try:
                # getNetworkInfo is a generator function
                netInfo = tuple(operations.getNetworkInfo())
                self.knownIps = dict(((i.mac, i.ip) for i in netInfo))
                ids = ','.join([i.mac for i in netInfo])
                if ids == '':
                    # Wait for any network interface to be ready
                    logger.debug('No valid network interfaces found, retrying in a while...')
                    raise Exception()
                logger.debug('Ids: {}'.format(ids))
                self.api.init(ids)
                # Set remote logger to notify log info to broker
                logger.setRemoteLogger(self.api)

                break
            except REST.InvalidKeyError:
                logger.fatal('Can\'t sync with broker: Invalid broker Master Key')
                return False
            except REST.UnmanagedHostError:
                # Maybe interface that is registered with broker is not enabled already?
                # Right now, we thing that the interface connected to broker is
                # the interface that broker will know, let's see how this works
                logger.fatal('This host is not managed by UDS Broker (ids: {})'.format(ids))
                return False  # On unmanaged hosts, there is no reason right now to continue running
            except Exception as e:
                logger.debug('Exception on network info: retrying')
                # Any other error is expectable and recoverable, so let's wait a bit and retry again
                # but, if too many errors, will log it (one every minute, for
                # example)
                counter += 1
                if counter % 60 == 0:  # Every 5 minutes, raise a log
                    logger.info('Trying to inititialize connection with broker (last error: {})'.format(exceptionToMessage(e)))
                # Wait a bit before next check
                self.doWait(5000)

        # Now try to run the "runonce" element
        runOnce = store.runApplication()
        if runOnce is not None:
            if self.execute(runOnce, 'RunOnce') is True:
                # operations.reboot()
                return False

        # Broker connection is initialized, now get information about what to
        # do
        counter = 0
        while self.isAlive:
            try:
                logger.debug('Requesting information of what to do now')
                info = self.api.information()
                data = info.split('\r')
                if len(data) != 2:
                    logger.error('The format of the information message is not correct (got {})'.format(info))
                    raise Exception
                params = data[1].split('\t')
                if data[0] == 'rename':
                    try:
                        if len(params) == 1:  # Simple rename
                            logger.debug('Renaming computer to {}'.format(params[0]))
                            self.rename(params[0])
                        # Rename with change password for an user
                        elif len(params) == 4:
                            logger.debug('Renaming computer to {}'.format(params))
                            self.rename(params[0], params[1], params[2], params[3])
                        else:
                            logger.error('Got invalid parameter for rename operation: {}'.format(params))
                            return False
                        break
                    except Exception as e:
                        logger.error('Error at computer renaming stage: {}'.format(e.message))
                        return None  # Will retry complete broker connection if this point is reached
                elif data[0] == 'domain':
                    if len(params) != 5:
                        logger.error('Got invalid parameters for domain message: {}'.format(params))
                        return False  # Stop running service
                    self.joinDomain(params[0], params[1], params[2], params[3], params[4])
                    break
                else:
                    logger.error('Unrecognized action sent from broker: {}'.format(data[0]))
                    return False  # Stop running service
            except REST.UserServiceNotFoundError:
                logger.error('The host has lost the sync state with broker! (host uuid changed?)')
                return False
            except Exception as err:
                if counter % 60 == 0:
                    logger.warn('Too many retries in progress, though still trying (last error: {})'.format(exceptionToMessage(err)))
                counter += 1
                # Any other error is expectable and recoverable, so let's wait
                # a bit and retry again
                # Wait a bit before next check
                self.doWait(5000)

        if self.rebootRequested:
            try:
                operations.reboot()
            except Exception as e:
                logger.error('Exception on reboot: {}'.format(e.message))
            return False  # Stops service

        return True
Example #38
0
    def run(self):
        self.running = True
        self.clientSocket.setblocking(0)

        state = None
        recv_msg = None
        recv_data = None
        while self.running:
            try:
                counter = 1024
                while counter > 0:  # So we process at least the incoming queue every XX bytes readed
                    counter -= 1
                    b = self.clientSocket.recv(1)
                    if b == b'':
                        # Client disconnected
                        self.running = False
                        break
                    buf = six.byte2int(
                        b)  # Empty buffer, this is set as non-blocking
                    if state is None:
                        if buf in VALID_REQUESTS:
                            logger.debug('State set to {}'.format(buf))
                            state = buf
                            recv_msg = buf
                            continue  # Get next byte
                        else:
                            logger.debug('Got unexpected data {}'.format(buf))
                    elif state in VALID_REQUESTS:
                        logger.debug('First length byte is {}'.format(buf))
                        msg_len = buf
                        state = ST_SECOND_BYTE
                        continue
                    elif state == ST_SECOND_BYTE:
                        msg_len += buf << 8
                        logger.debug(
                            'Second length byte is {}, len is {}'.format(
                                buf, msg_len))
                        if msg_len == 0:
                            self.processRequest(recv_msg, None)
                            state = None
                            break
                        state = ST_RECEIVING
                        recv_data = b''
                        continue
                    elif state == ST_RECEIVING:
                        recv_data += six.int2byte(buf)
                        msg_len -= 1
                        if msg_len == 0:
                            self.processRequest(recv_msg, recv_data)
                            recv_data = None
                            state = None
                            break
                    else:
                        logger.debug(
                            'Got invalid message from request: {}, state: {}'.
                            format(buf, state))
            except socket.error as e:
                # If no data is present, no problem at all, pass to check messages
                pass
            except Exception as e:
                tb = traceback.format_exc()
                logger.error('Error: {}, trace: {}'.format(e, tb))

            if self.running is False:
                break

            try:
                msg = self.messages.get(block=True, timeout=1)
            except six.moves.queue.Empty:  # No message got in time @UndefinedVariable
                continue

            logger.debug('Got message {}={}'.format(msg, REV_DICT.get(msg)))

            try:
                m = msg[1] if msg[1] is not None else b''
                l = len(m)
                data = MAGIC + six.int2byte(
                    msg[0]) + six.int2byte(l & 0xFF) + six.int2byte(l >> 8) + m
                try:
                    self.clientSocket.sendall(data)
                except socket.error as e:
                    # Send data error
                    logger.debug(
                        'Socket connection is no more available: {}'.format(
                            e.args))
                    self.running = False
            except Exception as e:
                logger.error('Invalid message in queue: {}'.format(e))

        logger.debug('Client processor stopped')
        try:
            self.clientSocket.close()
        except Exception:
            pass  # If can't close, nothing happens, just end thread
Example #39
0
    def SvcDoRun(self):  # pylint: disable=too-many-statements, too-many-branches
        '''
        Main service loop
        '''
        try:
            initCfg()

            logger.debug('running SvcDoRun')
            servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
                                  servicemanager.PYS_SERVICE_STARTED,
                                  (self._svc_name_, ''))

            # call the CoInitialize to allow the registration to run in an other
            # thread
            logger.debug('Initializing com...')
            pythoncom.CoInitialize()

            # ********************************************************
            # * Ask brokers what to do before proceding to main loop *
            # ********************************************************
            while True:
                brokerConnected = self.interactWithBroker()
                if brokerConnected is False:
                    logger.debug('Interact with broker returned false, stopping service after a while')
                    self.notifyStop()
                    win32event.WaitForSingleObject(self.hWaitStop, 5000)
                    return
                elif brokerConnected is True:
                    break

                # If brokerConnected returns None, repeat the cycle
                self.doWait(16000)  # Wait for a looong while

            if self.interactWithBroker() is False:
                logger.debug('Interact with broker returned false, stopping service after a while')
                self.notifyStop()
                win32event.WaitForSingleObject(self.hWaitStop, 5000)
                return

            if self.isAlive is False:
                logger.debug('The service is not alive after broker interaction, stopping it')
                self.notifyStop()
                return

            if self.rebootRequested is True:
                logger.debug('Reboot has been requested, stopping service')
                self.notifyStop()
                return

            self.initIPC()
        except Exception:  # Any init exception wil be caught, service must be then restarted
            logger.exception()
            logger.debug('Exiting service with failure status')
            os._exit(-1)  # pylint: disable=protected-access

        # ********************************
        # * Registers SENS subscriptions *
        # ********************************
        logevent('Registering ISensLogon')
        subscription_guid = '{41099152-498E-11E4-8FD3-10FEED05884B}'
        sl = SensLogon(self)
        subscription_interface = pythoncom.WrapObject(sl)

        event_system = win32com.client.Dispatch(PROGID_EventSystem)

        event_subscription = win32com.client.Dispatch(PROGID_EventSubscription)
        event_subscription.EventClassID = SENSGUID_EVENTCLASS_LOGON
        event_subscription.PublisherID = SENSGUID_PUBLISHER
        event_subscription.SubscriptionName = 'UDS Actor subscription'
        event_subscription.SubscriptionID = subscription_guid
        event_subscription.SubscriberInterface = subscription_interface

        event_system.Store(PROGID_EventSubscription, event_subscription)

        logger.debug('Registered SENS, running main loop')

        # Execute script in c:\\windows\\post-uds.bat after interacting with broker, if no reboot is requested ofc
        # This will be executed only when machine gets "ready"
        try:
            if os.path.isfile(POST_CMD):
                subprocess.call([POST_CMD, ])
            else:
                logger.info('POST file not found & not executed')
        except Exception as e:
            # Ignore output of execution command
            logger.error('Executing post command give')

        # *********************
        # * Main Service loop *
        # *********************
        # Counter used to check ip changes only once every 10 seconds, for
        # example
        counter = 0
        while self.isAlive:
            counter += 1
            # Process SENS messages, This will be a bit asyncronous (1 second
            # delay)
            pythoncom.PumpWaitingMessages()
            if counter >= 15:  # Once every 15 seconds
                counter = 0
                try:
                    self.checkIpsChanged()
                except Exception as e:
                    logger.error('Error checking ip change: {}'.format(e))
            # In milliseconds, will break
            win32event.WaitForSingleObject(self.hWaitStop, 1000)

        logger.debug('Exited main loop, deregistering SENS')

        # *******************************************
        # * Remove SENS subscription before exiting *
        # *******************************************
        event_system.Remove(
            PROGID_EventSubscription, "SubscriptionID == " + subscription_guid)

        self.endIPC()  # Ends IPC servers
        self.endAPI()  # And deinitializes REST api if needed

        self.notifyStop()
Example #40
0
    def run(self):
        self.running = True
        self.clientSocket.setblocking(0)

        state = None
        recv_msg = None
        recv_data = None
        while self.running:
            try:
                counter = 1024
                while counter > 0:  # So we process at least the incoming queue every XX bytes readed
                    counter -= 1
                    b = self.clientSocket.recv(1)
                    if b == b'':
                        # Client disconnected
                        self.running = False
                        break
                    buf = six.byte2int(b)  # Empty buffer, this is set as non-blocking
                    if state is None:
                        if buf in (REQ_INFORMATION, REQ_LOGIN, REQ_LOGOUT):
                            logger.debug('State set to {}'.format(buf))
                            state = buf
                            recv_msg = buf
                            continue  # Get next byte
                        else:
                            logger.debug('Got unexpected data {}'.format(buf))
                    elif state in (REQ_INFORMATION, REQ_LOGIN, REQ_LOGOUT):
                        logger.debug('First length byte is {}'.format(buf))
                        msg_len = buf
                        state = ST_SECOND_BYTE
                        continue
                    elif state == ST_SECOND_BYTE:
                        msg_len += buf << 8
                        logger.debug('Second length byte is {}, len is {}'.format(buf, msg_len))
                        if msg_len == 0:
                            self.processRequest(recv_msg, None)
                            state = None
                            break
                        state = ST_RECEIVING
                        recv_data = b''
                        continue
                    elif state == ST_RECEIVING:
                        recv_data += six.int2byte(buf)
                        msg_len -= 1
                        if msg_len == 0:
                            self.processRequest(recv_msg, recv_data)
                            recv_data = None
                            state = None
                            break
                    else:
                        logger.debug('Got invalid message from request: {}, state: {}'.format(buf, state))
            except socket.error as e:
                # If no data is present, no problem at all, pass to check messages
                pass
            except Exception as e:
                tb = traceback.format_exc()
                logger.error('Error: {}, trace: {}'.format(e, tb))

            if self.running is False:
                break

            try:
                msg = self.messages.get(block=True, timeout=1)
            except six.moves.queue.Empty:  # No message got in time @UndefinedVariable
                continue

            logger.debug('Got message {}={}'.format(msg, REV_DICT.get(msg)))

            try:
                m = msg[1] if msg[1] is not None else b''
                l = len(m)
                data = MAGIC + six.int2byte(msg[0]) + six.int2byte(l & 0xFF) + six.int2byte(l >> 8) + m
                try:
                    self.clientSocket.sendall(data)
                except socket.error as e:
                    # Send data error
                    logger.debug('Socket connection is no more available: {}'.format(e.args))
                    self.running = False
            except Exception as e:
                logger.error('Invalid message in queue: {}'.format(e))

        logger.debug('Client processor stopped')
        try:
            self.clientSocket.close()
        except Exception:
            pass  # If can't close, nothing happens, just end thread
Example #41
0
 def endAPI(self):
     if self.api is not None:
         try:
             self.api.notifyComm(None)
         except Exception as e:
             logger.error('Couln\'t remove comms url from broker: {}'.format(e))
Example #42
0
if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)

    if not QtGui.QSystemTrayIcon.isSystemTrayAvailable():
        # QtGui.QMessageBox.critical(None, "Systray", "I couldn't detect any system tray on this system.")
        sys.exit(1)

    # This is important so our app won't close on message windows
    QtGui.QApplication.setQuitOnLastWindowClosed(False)

    try:
        trayIcon = UDSSystemTray(app)
    except Exception:
        logger.error(
            'UDS Service is not running, or it can\'t contact with UDS Server. User Tools stopped'
        )
        sys.exit(1)

    # Sets a default idle duration, but will not be used unless idle is notified from server
    operations.initIdleDuration(3600 * 10)

    trayIcon.show()

    # Catch kill and logout user :)
    signal.signal(signal.SIGTERM, sigTerm)

    res = app.exec_()

    logger.debug('Exiting')
    trayIcon.quit()
Example #43
0
    if len(sys.argv) == 3 and sys.argv[1] in ('login', 'logout'):
        logger.debug('Running client udsactor')
        client = None
        try:
            client = ipc.ClientIPC(IPC_PORT)
            if 'login' == sys.argv[1]:
                client.sendLogin(sys.argv[2])
                sys.exit(0)
            elif 'logout' == sys.argv[1]:
                client.sendLogout(sys.argv[2])
                sys.exit(0)
            else:
                usage()
        except Exception as e:
            logger.error(e)
    elif len(sys.argv) != 2:
        usage()

    logger.debug('Executing actor')
    daemon = UDSActorSvc()
    if len(sys.argv) == 2:
        if 'start' == sys.argv[1]:
            daemon.start()
        elif 'stop' == sys.argv[1]:
            daemon.stop()
        elif 'restart' == sys.argv[1]:
            daemon.restart()
        else:
            usage()
        sys.exit(0)
Example #44
0
    def run(self):
        cfg = initCfg()  # Gets a local copy of config to get "reboot"

        logger.debug('CFG: {}'.format(cfg))

        if cfg is not None:
            self.rebootMachineAfterOp = cfg.get('reboot', True)
        else:
            self.rebootMachineAfterOp = False

        logger.info('Reboot after is {}'.format(self.rebootMachineAfterOp))

        logger.debug('Running Daemon')
        set_proctitle('UDSActorDaemon')

        # Linux daemon will continue running unless something is requested to
        while True:
            brokerConnected = self.interactWithBroker()
            if brokerConnected is False:
                logger.debug('Interact with broker returned false, stopping service after a while')
                return
            elif brokerConnected is True:
                break

            # If brokerConnected returns None, repeat the cycle
            self.doWait(16000)  # Wait for a looong while

        if self.isAlive is False:
            logger.debug('The service is not alive after broker interaction, stopping it')
            return

        if self.rebootRequested is True:
            logger.debug('Reboot has been requested, stopping service')
            return

        # Execute script in /etc/udsactor/post after interacting with broker, if no reboot is requested ofc
        # This will be executed only when machine gets "ready"
        try:

            if os.path.isfile(POST_CMD):
                if (os.stat(POST_CMD).st_mode & stat.S_IXUSR) != 0:
                    subprocess.call([POST_CMD, ])
                else:
                    logger.info('POST file exists but it it is not executable (needs execution permission by root)')
            else:
                logger.info('POST file not found & not executed')
        except Exception as e:
            # Ignore output of execution command
            logger.error('Executing post command give')

        self.initIPC()

        # *********************
        # * Main Service loop *
        # *********************
        # Counter used to check ip changes only once every 10 seconds, for
        # example
        counter = 0
        while self.isAlive:
            counter += 1
            if counter % 10 == 0:
                self.checkIpsChanged()
            # In milliseconds, will break
            self.doWait(1000)

        self.endIPC()
        self.endAPI()

        self.notifyStop()
Example #45
0

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)

    if not QtGui.QSystemTrayIcon.isSystemTrayAvailable():
        # QtGui.QMessageBox.critical(None, "Systray", "I couldn't detect any system tray on this system.")
        sys.exit(1)

    # This is important so our app won't close on message windows
    QtGui.QApplication.setQuitOnLastWindowClosed(False)

    try:
        trayIcon = UDSSystemTray(app)
    except Exception:
        logger.error('UDS Service is not running. Tool stopped')
        sys.exit(1)

    # Sets a default idle duration, but will not be used unless idle is notified from server
    operations.initIdleDuration(3600 * 10)

    trayIcon.show()

    # Catch kill and logout user :)
    signal.signal(signal.SIGTERM, sigTerm)

    res = app.exec_()

    logger.debug('Exiting')
    trayIcon.quit()
Example #46
0
    def interactWithBroker(self):
        '''
        Returns True to continue to main loop, false to stop & exit service
        '''
        # If no configuration is found, stop service
        if cfg is None:
            logger.fatal('No configuration found, stopping service')
            return False

        self.api = REST.Api(cfg['host'], cfg['masterKey'], cfg['ssl'])

        # Wait for Broker to be ready
        counter = 0
        while self.isAlive:
            try:
                # getNetworkInfo is a generator function
                netInfo = tuple(operations.getNetworkInfo())
                self.knownIps = dict(((i.mac, i.ip) for i in netInfo))
                ids = ','.join([i.mac for i in netInfo])
                if ids == '':
                    # Wait for any network interface to be ready
                    logger.debug('No valid network interfaces found, retrying in a while...')
                    raise Exception()
                logger.debug('Ids: {}'.format(ids))
                self.api.init(ids)
                # Set remote logger to notify log info to broker
                logger.setRemoteLogger(self.api)

                break
            except REST.InvalidKeyError:
                logger.fatal('Can\'t sync with broker: Invalid broker Master Key')
                return False
            except REST.UnmanagedHostError:
                # Maybe interface that is registered with broker is not enabled already?
                # Right now, we thing that the interface connected to broker is
                # the interface that broker will know, let's see how this works
                logger.fatal('This host is not managed by UDS Broker (ids: {})'.format(ids))
                return False  # On unmanaged hosts, there is no reason right now to continue running
            except Exception as e:
                logger.debug('Exception on network info: retrying')
                logger.exception()
                # Any other error is expectable and recoverable, so let's wait a bit and retry again
                # but, if too many errors, will log it (one every minute, for
                # example)
                counter += 1
                if counter % 60 == 0:  # Every 5 minutes, raise a log
                    logger.info('Trying to inititialize connection with broker (last error: {})'.format(exceptionToMessage(e)))
                # Wait a bit before next check
                self.doWait(5000)

        # Broker connection is initialized, now get information about what to
        # do
        counter = 0
        while self.isAlive:
            try:
                logger.debug('Requesting information of what to do now')
                info = self.api.information()
                data = info.split('\r')
                if len(data) != 2:
                    logger.error('The format of the information message is not correct (got {})'.format(info))
                    raise Exception
                params = data[1].split('\t')
                if data[0] == 'rename':
                    try:
                        if len(params) == 1:  # Simple rename
                            logger.debug('Renaming computer to {}'.format(params[0]))
                            self.rename(params[0])
                        # Rename with change password for an user
                        elif len(params) == 4:
                            logger.debug('Renaming computer to {}'.format(params))
                            self.rename(params[0], params[1], params[2], params[3])
                        else:
                            logger.error('Got invalid parameter for rename operation: {}'.format(params))
                            return False
                        break
                    except Exception as e:
                        logger.error('Error at computer renaming stage: {}'.format(e.message))
                        return False
                elif data[0] == 'domain':
                    if len(params) != 5:
                        logger.error('Got invalid parameters for domain message: {}'.format(params))
                        return False
                    self.joinDomain(params[0], params[1], params[2], params[3], params[4])
                    break
                else:
                    logger.error('Unrecognized action sent from broker: {}'.format(data[0]))
                    return False  # Stop running service
            except REST.UserServiceNotFoundError:
                logger.error('The host has lost the sync state with broker! (host uuid changed?)')
                return False
            except Exception:
                if counter % 60 == 0:
                    logger.warn('Too many retries in progress, though still trying (last error: {})'.format(exceptionToMessage(e)))
                counter += 1
                # Any other error is expectable and recoverable, so let's wait
                # a bit and retry again
                # Wait a bit before next check
                self.doWait(5000)

        if self.rebootRequested:
            try:
                operations.reboot()
            except Exception as e:
                logger.error('Exception on reboot: {}'.format(e.message))
            return False  # Stops service

        return True
Example #47
0
 def log_error(self, fmt, *args):
     logger.error('HTTP ' + fmt % args)
Example #48
0
 def log_error(self, fmt, *args):
     logger.error('HTTP ' + fmt % args)
Example #49
0
        self.app.quit()

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)

    if not QtGui.QSystemTrayIcon.isSystemTrayAvailable():
        # QtGui.QMessageBox.critical(None, "Systray", "I couldn't detect any system tray on this system.")
        sys.exit(1)

    # This is important so our app won't close on message windows
    QtGui.QApplication.setQuitOnLastWindowClosed(False)

    try:
        trayIcon = UDSSystemTray(app)
    except Exception:
        logger.error('UDS Service is not running. Tool stopped')
        sys.exit(1)

    # Sets a default idle duration, but will not be used unless idle is notified from server
    operations.initIdleDuration(3600 * 10)

    trayIcon.show()

    # Catch kill and logout user :)
    signal.signal(signal.SIGTERM, sigTerm)

    res = app.exec_()

    logger.debug('Exiting')
    trayIcon.quit()
Example #50
0
        self.app.quit()

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)

    if not QtGui.QSystemTrayIcon.isSystemTrayAvailable():
        # QtGui.QMessageBox.critical(None, "Systray", "I couldn't detect any system tray on this system.")
        sys.exit(1)

    # This is important so our app won't close on message windows
    QtGui.QApplication.setQuitOnLastWindowClosed(False)

    try:
        trayIcon = UDSSystemTray(app)
    except Exception:
        logger.error('UDS Service is not running, or it can\'t contact with UDS Server. User Tools stopped')
        sys.exit(1)

    # Sets a default idle duration, but will not be used unless idle is notified from server
    operations.initIdleDuration(3600 * 10)

    trayIcon.show()

    # Catch kill and logout user :)
    signal.signal(signal.SIGTERM, sigTerm)

    res = app.exec_()

    logger.debug('Exiting')
    trayIcon.quit()
Example #51
0
    def SvcDoRun(self):
        '''
        Main service loop
        '''
        try:
            initCfg()

            logger.debug('running SvcDoRun')
            servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
                                  servicemanager.PYS_SERVICE_STARTED,
                                  (self._svc_name_, ''))

            # call the CoInitialize to allow the registration to run in an other
            # thread
            logger.debug('Initializing com...')
            pythoncom.CoInitialize()

            # ********************************************************
            # * Ask brokers what to do before proceding to main loop *
            # ********************************************************
            while True:
                brokerConnected = self.interactWithBroker()
                if brokerConnected is False:
                    logger.debug(
                        'Interact with broker returned false, stopping service after a while'
                    )
                    self.notifyStop()
                    win32event.WaitForSingleObject(self.hWaitStop, 5000)
                    return
                elif brokerConnected is True:
                    break

                # If brokerConnected returns None, repeat the cycle
                self.doWait(16000)  # Wait for a looong while

            if self.interactWithBroker() is False:
                logger.debug(
                    'Interact with broker returned false, stopping service after a while'
                )
                self.notifyStop()
                win32event.WaitForSingleObject(self.hWaitStop, 5000)
                return

            if self.isAlive is False:
                logger.debug(
                    'The service is not alive after broker interaction, stopping it'
                )
                self.notifyStop()
                return

            if self.rebootRequested is True:
                logger.debug('Reboot has been requested, stopping service')
                self.notifyStop()
                return

            self.initIPC()
        except Exception:  # Any init exception wil be caught, service must be then restarted
            logger.exception()
            logger.debug('Exiting service with failure status')
            os._exit(-1)  # pylint: disable=protected-access

        # ********************************
        # * Registers SENS subscriptions *
        # ********************************
        logevent('Registering ISensLogon')
        subscription_guid = '{41099152-498E-11E4-8FD3-10FEED05884B}'
        sl = SensLogon(self)
        subscription_interface = pythoncom.WrapObject(sl)

        event_system = win32com.client.Dispatch(PROGID_EventSystem)

        event_subscription = win32com.client.Dispatch(PROGID_EventSubscription)
        event_subscription.EventClassID = SENSGUID_EVENTCLASS_LOGON
        event_subscription.PublisherID = SENSGUID_PUBLISHER
        event_subscription.SubscriptionName = 'UDS Actor subscription'
        event_subscription.SubscriptionID = subscription_guid
        event_subscription.SubscriberInterface = subscription_interface

        event_system.Store(PROGID_EventSubscription, event_subscription)

        logger.debug('Registered SENS, running main loop')

        # Execute script in c:\\windows\\post-uds.bat after interacting with broker, if no reboot is requested ofc
        # This will be executed only when machine gets "ready"
        try:
            if os.path.isfile(POST_CMD):
                subprocess.call([
                    POST_CMD,
                ])
            else:
                logger.info('POST file not found & not executed')
        except Exception as e:
            # Ignore output of execution command
            logger.error('Executing post command give')

        # *********************
        # * Main Service loop *
        # *********************
        # Counter used to check ip changes only once every 10 seconds, for
        # example
        counter = 0
        while self.isAlive:
            counter += 1
            # Process SENS messages, This will be a bit asyncronous (1 second
            # delay)
            pythoncom.PumpWaitingMessages()
            if counter >= 15:  # Once every 15 seconds
                counter = 0
                try:
                    self.checkIpsChanged()
                except Exception as e:
                    logger.error('Error checking ip change: {}'.format(e))
            # In milliseconds, will break
            win32event.WaitForSingleObject(self.hWaitStop, 1000)

        logger.debug('Exited main loop, deregistering SENS')

        # *******************************************
        # * Remove SENS subscription before exiting *
        # *******************************************
        event_system.Remove(PROGID_EventSubscription,
                            "SubscriptionID == " + subscription_guid)

        self.endIPC()  # Ends IPC servers
        self.endAPI()  # And deinitializes REST api if needed

        self.notifyStop()
Example #52
0
 def run(self):
     try:
         logger.debug('Executing script: {}'.format(self.script))
         six.exec_(self.script, globals(), None)
     except Exception as e:
         logger.error('Error executing script: {}'.format(e))