def rename(newName): ''' Debian renamer Expects new host name on newName Host does not needs to be rebooted after renaming ''' logger.debug('using Debian renamer') with open('/etc/hostname', 'w') as hostname: hostname.write(newName) # Force system new name os.system('/bin/hostname %s' % newName) # add name to "hosts" with open('/etc/hosts', 'r') as hosts: lines = hosts.readlines() with open('/etc/hosts', 'w') as hosts: hosts.write("127.0.1.1\t%s\n" % newName) for l in lines: if l[: 9] == '127.0.1.1': # Skips existing 127.0.1.1. if it already exists continue hosts.write(l) return True
def clientMessageProcessor(self, msg, data): logger.debug('Got message {}'.format(msg)) if self.api is None: logger.info('Rest api not ready') return if msg == ipc.REQ_LOGIN: res = self.api.login(data).split('\t') # third parameter, if exists, sets maxSession duration to this. # First & second parameters are ip & hostname of connection source if len(res) >= 3: self.api.maxSession = int(res[2]) # Third parameter is max session duration msg = ipc.REQ_INFORMATION # Senf information, requested or not, to client on login notification elif msg == ipc.REQ_LOGOUT: self.api.logout(data) self.onLogout(data) elif msg == ipc.REQ_INFORMATION: info = {} if self.api.idle is not None: info['idle'] = self.api.idle if self.api.maxSession is not None: info['maxSession'] = self.api.maxSession self.ipc.sendInformationMessage(info) elif msg == ipc.REQ_TICKET: d = json.loads('data') try: result = self.api.getTicket(d['ticketId'], d['secure']) self.ipc.sendTicketMessage(result) except Exception: logger.exception('Getting ticket') self.ipc.sendTicketMessage({'error': 'invalid ticket'})
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) 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 _request(self, url, data=None): try: if data is None: # Old requests version does not support verify, but they do not checks ssl certificate by default if self.newerRequestLib: r = requests.get(url, verify=VERIFY_CERT) else: logger.debug('Requesting with old') r = requests.get(url) # Always ignore certs?? else: if data == '': data = '{"dummy": true}' # Ensures no proxy rewrites POST as GET because body is empty... if self.newerRequestLib: r = requests.post(url, data=data, headers={'content-type': 'application/json'}, verify=VERIFY_CERT) else: logger.debug('Requesting with old') r = requests.post(url, data=data, headers={'content-type': 'application/json'}) r = json.loads(r.content) # Using instead of r.json() to make compatible with oooold rquests lib versions except requests.exceptions.RequestException as e: raise ConnectionError(e) except Exception as e: raise ConnectionError(exceptionToMessage(e)) ensureResultIsOk(r) return r
def _request(self, url, data=None): try: if data is None: # Old requests version does not support verify, but they do not checks ssl certificate by default if self.newerRequestLib: r = requests.get(url, verify=VERIFY_CERT) else: logger.debug('Requesting with old') r = requests.get(url) # Always ignore certs?? else: if self.newerRequestLib: r = requests.post(url, data=data, headers={'content-type': 'application/json'}, verify=VERIFY_CERT) else: logger.debug('Requesting with old') r = requests.post(url, data=data, headers={'content-type': 'application/json'}) r = json.loads(r.content) # Using instead of r.json() to make compatible with oooold rquests lib versions except requests.exceptions.RequestException as e: raise ConnectionError(e) except Exception as e: raise ConnectionError(exceptionToMessage(e)) ensureResultIsOk(r) return r
def checkIdle(self): if self.maxIdleTime is None: # No idle check return if self.graceTimerShots > 0: self.graceTimerShots -= 1 return idleTime = operations.getIdleDuration() remainingTime = self.maxIdleTime - idleTime if remainingTime > 300: # Reset show Warning dialog if we have more than 5 minutes left self.showIdleWarn = True logger.debug('User has been idle for: {}'.format(idleTime)) if remainingTime <= 0: logger.info( 'User has been idle for too long, notifying Broker that service can be reclaimed' ) self.quit() if self.showIdleWarn is True and remainingTime < 120: # With two minutes, show a warning message self.showIdleWarn = False self.msgDlg.displayMessage( "You have been idle for too long. The session will end if you don't resume operations" )
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 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_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) 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 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 rename(newName): ''' RH, Centos, Fedora Renamer Expects new host name on newName Host does not needs to be rebooted after renaming ''' logger.debug('using RH renamer') with open('/etc/hostname', 'w') as hostname: hostname.write(newName) # Force system new name os.system('/bin/hostname %s' % newName) # add name to "hosts" with open('/etc/hosts', 'r') as hosts: lines = hosts.readlines() with open('/etc/hosts', 'w') as hosts: hosts.write("127.0.1.1\t{}\n".format(newName)) for l in lines: if l[:9] != '127.0.1.1': # Skips existing 127.0.1.1. if it already exists hosts.write(l) with open('/etc/sysconfig/network', 'r') as net: lines = net.readlines() with open('/etc/sysconfig/network', 'w') as net: net.write('HOSTNAME={}\n'.format(newName)) for l in lines: if l[:8] != 'HOSTNAME': net.write(l) return True
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 _request(self, url, data=None): try: if data is None: # Old requests version does not support verify, but they do not checks ssl certificate by default if self.newerRequestLib: r = requests.get(url, verify=VERIFY_CERT) else: logger.debug('Requesting with old') r = requests.get(url) # Always ignore certs?? else: if data == '': data = '{"dummy": true}' # Ensures no proxy rewrites POST as GET because body is empty... if self.newerRequestLib: r = requests.post(url, data=data, headers={'content-type': 'application/json'}, verify=VERIFY_CERT) else: logger.debug('Requesting with old') r = requests.post(url, data=data, headers={'content-type': 'application/json'}) # From versions of requests, content maybe bytes or str. We need str for json.loads content = r.content if not isinstance(content, six.text_type): content = content.decode('utf8') r = json.loads(content) # Using instead of r.json() to make compatible with oooold rquests lib versions except requests.exceptions.RequestException as e: raise ConnectionError(e) except Exception as e: raise ConnectionError(exceptionToMessage(e)) ensureResultIsOk(r) return r
def rename(newName): """ Debian renamer Expects new host name on newName Host does not needs to be rebooted after renaming """ logger.debug("using Debian renamer") with open("/etc/hostname", "w") as hostname: hostname.write(newName) # Force system new name os.system("/bin/hostname %s" % newName) # add name to "hosts" with open("/etc/hosts", "r") as hosts: lines = hosts.readlines() with open("/etc/hosts", "w") as hosts: hosts.write("127.0.1.1\t%s\n" % newName) for l in lines: if l[:9] == "127.0.1.1": # Skips existing 127.0.1.1. if it already exists continue hosts.write(l) return True
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 setReady(self, ipsInfo, hostName=None): logger.debug('Notifying readyness: {}'.format(ipsInfo)) # data = ','.join(['{}={}'.format(v[0], v[1]) for v in ipsInfo]) data = { 'ips': ipsInfo, 'hostname': hostName } return self.postMessage('ready', data)
def cleanupFinishedThreads(self): ''' Cleans up current threads list ''' aliveThreads = [] for t in self.threads: if t.isAlive(): logger.debug('Thread {} is alive'.format(t)) aliveThreads.append(t) self.threads[:] = aliveThreads
def postMessage(self, msg, data, processData=True): logger.debug('Invoking post message {} with data {}'.format(msg, data)) if self.uuid is None: raise ConnectionError('REST api has not been initialized') if processData: data = json.dumps({'data': data}) url = self._getUrl('/'.join([self.uuid, msg])) return self._request(url, data)['result']
def end(self, sessionManager=None) -> None: if not self._initialized: return self._initialized = False logger.debug('Stopping app thread') self._app.stop() self._app.join()
def stop(self): logger.debug('Stopping Server IPC') self.running = False for t in self.threads: t.stop() socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect(('localhost', self.port)) self.serverSocket.close() for t in self.threads: t.join()
def sendRequestMessage(self, msg, data=None): logger.debug('Sending request for msg: {}({}), {}'.format(msg, REV_DICT.get(msg), data)) if data is None: data = b'' if isinstance(data, six.text_type): # Convert to bytes if necessary data = data.encode('utf-8') l = len(data) msg = six.int2byte(msg) + six.int2byte(l & 0xFF) + six.int2byte(l >> 8) + data self.clientSocket.sendall(msg)
def information(self, info): ''' Invoked when received information from service ''' logger.debug('Got information message: {}'.format(info)) if 'idle' in info: idle = int(info['idle']) operations.initIdleDuration(idle) self.maxIdleTime = idle logger.debug('Set screensaver launching to {}'.format(idle)) else: self.maxIdleTime = None
def post_script(self, params): logger.debug('Received script: {}'.format(params)) if 'script' not in params: raise Exception('Invalid script parameters') if 'user' in params: logger.debug('Sending SCRIPT to clients') HTTPServerHandler.service.ipc.sendScriptMessage(params['script']) else: # Execute script at server space, that is, here # as a secondary thread th = ScriptExecutorThread(params['script']) th.start() return 'ok'
def testParameters(self): logger.debug('Testing connection') try: cfg = self._getCfg() api = REST.Api( cfg['host'], cfg['masterKey'], cfg['ssl']) api.test() QtGui.QMessageBox.information( self, 'Test Passed', 'The test was executed successfully', QtGui.QMessageBox.Ok) logger.info('Test was passed successfully') except Exception as e: logger.info('Test error: {}'.format(utils.exceptionToMessage(e))) QtGui.QMessageBox.critical(self, 'Test Error', utils.exceptionToMessage(e), QtGui.QMessageBox.Ok)
def sendMessage(self, msgId, msgData): ''' Notify message to all listening threads ''' logger.debug('Sending message {}({}),{} to all clients'.format(msgId, REV_DICT.get(msgId), msgData)) # Convert to bytes so length is correctly calculated if isinstance(msgData, six.text_type): msgData = msgData.encode('utf8') for t in self.threads: if t.isAlive(): logger.debug('Sending to {}'.format(t)) t.messages.put((msgId, msgData))
def __init__(self): super(self.__class__, self).__init__() # Retries connection for a while for _ in range(10): try: self.ipc = ipc.ClientIPC(IPC_PORT) self.ipc.start() break except Exception: logger.debug('IPC Server is not reachable') self.ipc = None time.sleep(2) self.running = False
def joinDomain(self, name, domain, ou, account, password): ver = operations.getWindowsVersion() ver = ver[0] * 10 + ver[1] logger.debug('Starting joining domain {} with name {} (detected operating version: {})'.format( domain, name, ver)) # If file c:\compat.bin exists, joind domain in two steps instead one # Accepts one step joinDomain, also remember XP is no more supported by # microsoft, but this also must works with it because will do a "multi # step" join if ver >= 60 and store.useOldJoinSystem() is False: self.oneStepJoin(name, domain, ou, account, password) else: logger.info('Using multiple step join because configuration requests to do so') self.multiStepJoin(name, domain, ou, account, password)
def testParameters(self): logger.debug('Testing connection') try: cfg = self._getCfg() api = REST.Api(cfg['host'], cfg['masterKey'], cfg['ssl']) api.test() QtGui.QMessageBox.information( self, 'Test Passed', 'The test was executed successfully', QtGui.QMessageBox.Ok) logger.info('Test was passed successfully') except Exception as e: logger.info('Test error: {}'.format(utils.exceptionToMessage(e))) QtGui.QMessageBox.critical(self, 'Test Error', utils.exceptionToMessage(e), QtGui.QMessageBox.Ok)
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 initIPC(self): # ****************************************** # * Initialize listener IPC & REST threads * # ****************************************** logger.debug('Starting IPC listener at {}'.format(IPC_PORT)) self.ipc = ipc.ServerIPC(IPC_PORT, clientMessageProcessor=self.clientMessageProcessor) self.ipc.start() if self.api.mac in self.knownIps: address = (self.knownIps[self.api.mac], random.randrange(43900, 44000)) logger.info('Starting REST listener at {}'.format(address)) self.httpServer = httpserver.HTTPServerThread(address, self) self.httpServer.start() # And notify it to broker self.api.notifyComm(self.httpServer.getServerUrl())
def initIPC(self): # ****************************************** # * Initialize listener IPC & REST threads * # ****************************************** logger.debug('Starting IPC listener at {}'.format(IPC_PORT)) self.ipc = ipc.ServerIPC(IPC_PORT, clientMessageProcessor=self.clientMessageProcessor) self.ipc.start() if self.api.mac in self.knownIps: address = (self.knownIps[self.api.mac], random.randrange(40000, 44000)) logger.info('Starting REST listener at {}'.format(address)) self.httpServer = httpserver.HTTPServerThread(address, self) self.httpServer.start() # And notify it to broker self.api.notifyComm(self.httpServer.getServerUrl())
def clientMessageProcessor(self, msg, data): logger.debug('Got message {}'.format(msg)) if self.api is None: logger.info('Rest api not ready') return if msg == ipc.REQ_LOGIN: self.api.login(data) elif msg == ipc.REQ_LOGOUT: self.api.logout(data) self.onLogout(data) elif msg == ipc.REQ_INFORMATION: info = {} if self.api.idle is not None: info['idle'] = self.api.idle self.ipc.sendInformationMessage(info)
def receiveBytes(self, number): msg = b'' while self.running and len(msg) < number: try: buf = self.clientSocket.recv(number - len(msg)) if buf == b'': logger.debug('Buf {}, msg {}({})'.format(buf, msg, REV_DICT.get(msg))) self.running = False break msg += buf except socket.timeout: pass if self.running is False: logger.debug('Not running, returning None') return None return msg
def oneStepJoin(self, name, domain, ou, account, password): ''' Ejecutes the join domain in exactly one step ''' currName = operations.getComputerName() # If name is desired, simply execute multiStepJoin, because computer # name will not change if currName.lower() == name.lower(): self.multiStepJoin(name, domain, ou, account, password) else: operations.renameComputer(name) logger.debug('Computer renamed to {} without reboot'.format(name)) operations.joinDomain( domain, ou, account, password, executeInOneStep=True) logger.debug( 'Requested join domain {} without errors'.format(domain)) self.reboot()
def multiStepJoin(self, name, domain, ou, account, password): currName = operations.getComputerName() if currName.lower() == name.lower(): currDomain = operations.getDomainName() logger.debug('Name: "{}" vs "{}", Domain: "{}" vs "{}"'.format(currName.lower(), name.lower(), currDomain.lower(), domain.lower())) if currDomain is not None: logger.info( 'Machine {} is part of domain {}'.format(name, domain)) self.setReady() else: operations.joinDomain( domain, ou, account, password, executeInOneStep=False) else: operations.renameComputer(name) logger.info( 'Rebooting computer got activate new name {}'.format(name)) self.reboot()
def quit(self, logoff=False): global doLogoff logger.debug('Quit invoked') if self.stopped is False: self.stopped = True try: # If we close Client, send Logoff to Broker self.ipc.sendLogout(operations.getCurrentUser()) self.timer.stop() self.ipc.stop() except Exception: # May we have lost connection with server, simply exit in that case pass doLogoff = logoff self.app.quit()
def init(self, ids): ''' Ids is a comma separated values indicating MAC=ip Server returns: uuid, mac Optionally can return an third parameter, that is max "idle" request time ''' logger.debug('Invoking init') url = self._getUrl('init', key=self.masterKey, ids=ids) res = self._request(url)['result'] logger.debug('Got response parameters: {}'.format(res)) self.uuid, self.mac = res[0:2] self.idle = int(res[2]) if self.idle < 30: self.idle = None # No values under 30 seconds are allowed :) return self.uuid
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 init(self, ids): ''' Ids is a comma separated values indicating MAC=ip Server returns: uuid, mac Optionally can return an third parameter, that is max "idle" request time ''' logger.debug('Invoking init') url = self._getUrl('init', key=self.masterKey, ids=ids) res = self._request(url)['result'] logger.debug('Got response parameters: {}'.format(res)) self.uuid, self.mac = res[0:2] # Optional idle parameter try: self.idle = int(res[2]) if self.idle < 30: self.idle = None # No values under 30 seconds are allowed :) except Exception: self.idle = None return self.uuid
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 multiStepJoin(self, name, domain, ou, account, password): currName = operations.getComputerName() if currName.lower() == name.lower(): currDomain = operations.getDomainName() logger.debug('Name: "{}" vs "{}", Domain: "{}" vs "{}"'.format( currName.lower(), name.lower(), currDomain.lower(), domain.lower())) if currDomain is not None: logger.info('Machine {} is part of domain {}'.format( name, domain)) self.setReady() else: operations.joinDomain(domain, ou, account, password, executeInOneStep=False) else: operations.renameComputer(name) logger.info( 'Rebooting computer got activate new name {}'.format(name)) self.reboot()
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 checkIdle(self): if self.maxIdleTime is None: # No idle check return if self.graceTimerShots > 0: self.graceTimerShots -= 1 return idleTime = operations.getIdleDuration() remainingTime = self.maxIdleTime - idleTime if remainingTime > 300: # Reset show Warning dialog if we have more than 5 minutes left self.showIdleWarn = True logger.debug('User has been idle for: {}'.format(idleTime)) if remainingTime <= 0: logger.info('User has been idle for too long, notifying Broker that service can be reclaimed') self.quit() if self.showIdleWarn is True and remainingTime < 120: # With two minutes, show a warning message self.showIdleWarn = False self.msgDlg.displayMessage("You have been idle for too long. The session will end if you don't resume operations")