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()
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))
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)
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))
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'
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
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))
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)
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)
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)
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)
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()
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)
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()
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))
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))
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'
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')
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))
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))
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
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))
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'
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
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')
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))
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()
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'
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))
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()
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
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
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
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()
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
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))
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()
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)
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()
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()
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
def log_error(self, fmt, *args): logger.error('HTTP ' + fmt % args)
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()
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()
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()
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))