#877: Copy hosts file on OGAgent activation, and some code cleanup.

remotes/github/oglive
Ramón M. Gómez 2018-11-23 13:08:38 +01:00
parent 219fba068c
commit bedce23f28
4 changed files with 68 additions and 34 deletions

View File

@ -284,3 +284,11 @@ def showPopup(title, message):
Displays a message box on user's session (during 1 min). Displays a message box on user's session (during 1 min).
''' '''
return subprocess.call('zenity --info --timeout 60 --title "{}" --text "{}"'.format(title, message), shell=True) return subprocess.call('zenity --info --timeout 60 --title "{}" --text "{}"'.format(title, message), shell=True)
def get_etc_path():
"""
:return:
Returns etc directory path.
"""
return os.sep + 'etc'

View File

@ -253,3 +253,11 @@ def showPopup(title, message):
''' '''
# Show a dialog using AppleSctipt # Show a dialog using AppleSctipt
return subprocess.call('/usr/bin/osascript -e \'display notification "{}" with title "{}"\''.format(message, title), shell=True) return subprocess.call('/usr/bin/osascript -e \'display notification "{}" with title "{}"\''.format(message, title), shell=True)
def get_etc_path():
"""
:return:
Returns etc directory path.
"""
return os.sep + 'etc'

View File

@ -37,6 +37,7 @@ import os
import platform import platform
import time import time
import random import random
import shutil
import string import string
import urllib import urllib
@ -65,9 +66,9 @@ class OpenGnSysWorker(ServerWorker):
length = 32 # Random string length length = 32 # Random string length
def checkSecret(self, server): def checkSecret(self, server):
''' """
Checks for received secret key and raise exception if it isn't valid. Checks for received secret key and raise exception if it isn't valid.
''' """
try: try:
if self.random != server.headers['Authorization']: if self.random != server.headers['Authorization']:
raise Exception('Unauthorized operation') raise Exception('Unauthorized operation')
@ -76,9 +77,9 @@ class OpenGnSysWorker(ServerWorker):
raise Exception(e) raise Exception(e)
def onActivation(self): def onActivation(self):
''' """
Sends OGAgent activation notification to OpenGnsys server Sends OGAgent activation notification to OpenGnsys server
''' """
self.cmd = None self.cmd = None
# Ensure cfg has required configuration variables or an exception will be thrown # Ensure cfg has required configuration variables or an exception will be thrown
self.REST = REST(self.service.config.get('opengnsys', 'remote')) self.REST = REST(self.service.config.get('opengnsys', 'remote'))
@ -104,55 +105,64 @@ class OpenGnSysWorker(ServerWorker):
os.remove(os.sep + f) os.remove(os.sep + f)
except OSError: except OSError:
pass pass
# Copy file "HostsFile.FirstOctetOfIPAddress" to "HostsFile", if it exists
# (used in "exam mode" of the University of Seville)
hostsFile = os.path.join(operations.get_etc_path(), 'hosts')
newHostsFile = hostsFile + '.' + self.interface.ip.split('.')[0]
if os.path.isfile(newHostsFile):
shutil.copyfile(newHostsFile, hostsFile)
# Generate random secret to send on activation # Generate random secret to send on activation
self.random = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(self.length)) self.random = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(self.length))
# Send initalization message # Send initialization message
self.REST.sendMessage('ogagent/started', {'mac': self.interface.mac, 'ip': self.interface.ip, 'secret': self.random, 'ostype': operations.osType, 'osversion': operations.osVersion}) self.REST.sendMessage('ogagent/started', {'mac': self.interface.mac, 'ip': self.interface.ip, 'secret': self.random, 'ostype': operations.osType, 'osversion': operations.osVersion})
def onDeactivation(self): def onDeactivation(self):
''' """
Sends OGAgent stopping notification to OpenGnsys server Sends OGAgent stopping notification to OpenGnsys server
''' """
logger.debug('onDeactivation') logger.debug('onDeactivation')
self.REST.sendMessage('ogagent/stopped', {'mac': self.interface.mac, 'ip': self.interface.ip, 'ostype': operations.osType, 'osversion': operations.osVersion}) self.REST.sendMessage('ogagent/stopped', {'mac': self.interface.mac, 'ip': self.interface.ip, 'ostype': operations.osType, 'osversion': operations.osVersion})
def processClientMessage(self, message, data): def processClientMessage(self, message, data):
logger.debug('Got OpenGnsys message from client: {}, data {}'.format(message, data)) logger.debug('Got OpenGnsys message from client: {}, data {}'.format(message, data))
def onLogin(self, userData): def onLogin(self, data):
''' """
Sends session login notification to OpenGnsys server Sends session login notification to OpenGnsys server
''' """
user, sep, language = userData.partition(',') user, sep, language = data.partition(',')
logger.debug('Received login for {} with language {}'.format(user, language)) logger.debug('Received login for {} with language {}'.format(user, language))
self.loggedin = True self.loggedin = True
self.REST.sendMessage('ogagent/loggedin', {'ip': self.interface.ip, 'user': user, 'language': language, 'ostype': operations.osType, 'osversion': operations.osVersion}) self.REST.sendMessage('ogagent/loggedin', {'ip': self.interface.ip, 'user': user, 'language': language, 'ostype': operations.osType, 'osversion': operations.osVersion})
def onLogout(self, user): def onLogout(self, user):
''' """
Sends session logout notification to OpenGnsys server Sends session logout notification to OpenGnsys server
''' """
logger.debug('Received logout for {}'.format(user)) logger.debug('Received logout for {}'.format(user))
self.loggedin = False self.loggedin = False
self.REST.sendMessage('ogagent/loggedout', {'ip': self.interface.ip, 'user': user}) self.REST.sendMessage('ogagent/loggedout', {'ip': self.interface.ip, 'user': user})
def process_ogclient(self, path, getParams, postParams, server): def process_ogclient(self, path, getParams, postParams, server):
''' """
This method can be overriden to provide your own message proccessor, or better you can This method can be overridden to provide your own message processor, or better you can
implement a method that is called exactly as "process_" + path[0] (module name has been removed from path array) and this default processMessage will invoke it implement a method that is called exactly as "process_" + path[0] (module name has been removed from path
array) and this default processMessage will invoke it
* Example: * Example:
Imagine this invocation url (no matter if GET or POST): http://example.com:9999/Sample/mazinger/Z Imagine this invocation url (no matter if GET or POST): http://example.com:9999/Sample/mazinger/Z
The HTTP Server will remove "Sample" from path, parse arguments and invoke this method as this: The HTTP Server will remove "Sample" from path, parse arguments and invoke this method as this:
module.processMessage(["mazinger","Z"], getParams, postParams) module.processMessage(["mazinger","Z"], getParams, postParams)
This method will process "mazinger", and look for a "self" method that is called "process_mazinger", and invoke it this way: This method will process "mazinger", and look for a "self" method that is called "process_mazinger",
and invoke it this way:
return self.process_mazinger(["Z"], getParams, postParams) return self.process_mazinger(["Z"], getParams, postParams)
In the case path is empty (that is, the path is composed only by the module name, like in "http://example.com/Sample", the "process" method In the case path is empty (that is, the path is composed only by the module name, like in
will be invoked directly "http://example.com/Sample", the "process" method will be invoked directly
The methods must return data that can be serialized to json (i.e. Ojects are not serializable to json, basic type are) The methods must return data that can be serialized to json (i.e. Objects are not serializable to json,
''' basic type are)
"""
if not path: if not path:
return "ok" return "ok"
try: try:
@ -162,9 +172,9 @@ class OpenGnSysWorker(ServerWorker):
return operation(path[1:], getParams, postParams) return operation(path[1:], getParams, postParams)
def process_status(self, path, getParams, postParams, server): def process_status(self, path, getParams, postParams, server):
''' """
Returns client status. Returns client status.
''' """
res = {'status': '', 'loggedin': self.loggedin} res = {'status': '', 'loggedin': self.loggedin}
if platform.system() == 'Linux': # GNU/Linux if platform.system() == 'Linux': # GNU/Linux
# Check if it's OpenGnsys Client. # Check if it's OpenGnsys Client.
@ -185,9 +195,9 @@ class OpenGnSysWorker(ServerWorker):
return res return res
def process_reboot(self, path, getParams, postParams, server): def process_reboot(self, path, getParams, postParams, server):
''' """
Launches a system reboot operation. Launches a system reboot operation.
''' """
logger.debug('Received reboot operation') logger.debug('Received reboot operation')
self.checkSecret(server) self.checkSecret(server)
# Rebooting thread. # Rebooting thread.
@ -197,9 +207,9 @@ class OpenGnSysWorker(ServerWorker):
return {'op': 'launched'} return {'op': 'launched'}
def process_poweroff(self, path, getParams, postParams, server): def process_poweroff(self, path, getParams, postParams, server):
''' """
Launches a system power off operation. Launches a system power off operation.
''' """
logger.debug('Received poweroff operation') logger.debug('Received poweroff operation')
self.checkSecret(server) self.checkSecret(server)
# Powering off thread. # Powering off thread.
@ -210,9 +220,9 @@ class OpenGnSysWorker(ServerWorker):
return {'op': 'launched'} return {'op': 'launched'}
def process_script(self, path, getParams, postParams, server): def process_script(self, path, getParams, postParams, server):
''' """
Processes an script execution (script should be encoded in base64) Processes an script execution (script should be encoded in base64)
''' """
logger.debug('Processing script request') logger.debug('Processing script request')
self.checkSecret(server) self.checkSecret(server)
# Decoding script. # Decoding script.
@ -227,19 +237,19 @@ class OpenGnSysWorker(ServerWorker):
return {'op': 'launched'} return {'op': 'launched'}
def process_logoff(self, path, getParams, postParams, server): def process_logoff(self, path, getParams, postParams, server):
''' """
Closes user session. Closes user session.
''' """
logger.debug('Received logoff operation') logger.debug('Received logoff operation')
self.checkSecret(server) self.checkSecret(server)
# Sending log off message to OGAgent client. # Sending log off message to OGAgent client.
self.sendClientMessage('logoff', {}) self.sendClientMessage('logoff', {})
return {'op': 'sended to client'} return {'op': 'sent to client'}
def process_popup(self, path, getParams, postParams, server): def process_popup(self, path, getParams, postParams, server):
''' """
Shows a message popup on the user's session. Shows a message popup on the user's session.
''' """
logger.debug('Received message operation') logger.debug('Received message operation')
self.checkSecret(server) self.checkSecret(server)
# Sending popup message to OGAgent client. # Sending popup message to OGAgent client.

View File

@ -259,3 +259,11 @@ def showPopup(title, message):
Displays a message box on user's session (during 1 min). Displays a message box on user's session (during 1 min).
''' '''
return subprocess.call('mshta "javascript:var sh=new ActiveXObject(\'WScript.Shell\'); sh.Popup( \'{}\', 60, \'{}\', 64); close()"'.format(message.encode('unicode_escape'), title.encode('unicode_escape')), shell=True) return subprocess.call('mshta "javascript:var sh=new ActiveXObject(\'WScript.Shell\'); sh.Popup( \'{}\', 60, \'{}\', 64); close()"'.format(message.encode('unicode_escape'), title.encode('unicode_escape')), shell=True)
def get_etc_path():
"""
:return:
Returns etc directory path.
"""
return os.path.join('C:', os.sep, 'Windows', 'System32', 'drivers', 'etc')