1.1 --- a/OpenSecurity/bin/vmmanager.pyw Mon Jun 02 17:08:11 2014 +0100
1.2 +++ b/OpenSecurity/bin/vmmanager.pyw Wed Jun 04 16:42:37 2014 +0100
1.3 @@ -24,6 +24,7 @@
1.4 import win32api
1.5 import win32con
1.6 import win32security
1.7 +import win32wnet
1.8 import urllib
1.9 import urllib2
1.10 DEBUG = True
1.11 @@ -70,6 +71,7 @@
1.12 _instance = None
1.13 machineFolder = ''
1.14 rsdHandler = None
1.15 + hostonlyIFs = None
1.16 browsingManager = None
1.17 status_message = 'Starting up...'
1.18
1.19 @@ -78,7 +80,7 @@
1.20
1.21 self.systemProperties = self.getSystemProperties()
1.22 self.machineFolder = self.systemProperties["Default machine folder"]
1.23 -
1.24 + self.hostonlyIFs = self.getHostOnlyIFs()
1.25 # only proceed if we have a working background environment
1.26 if self.backend_ok():
1.27 self.cleanup()
1.28 @@ -93,6 +95,27 @@
1.29 VMManager._instance = VMManager()
1.30 return VMManager._instance
1.31
1.32 + #list the hostonly IFs exposed by the VBox host
1.33 + @staticmethod
1.34 + def getHostOnlyIFs():
1.35 + result = Cygwin.vboxExecute('list hostonlyifs')[1]
1.36 + if result=='':
1.37 + return None
1.38 + props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split(':', 1) for line in result.strip().splitlines()))
1.39 + return props
1.40 +
1.41 + # return hosty system properties
1.42 + @staticmethod
1.43 + def getSystemProperties():
1.44 + result = Cygwin.checkResult(Cygwin.vboxExecute('list systemproperties'))
1.45 + if result[1]=='':
1.46 + return None
1.47 + props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split(':', 1) for line in result[1].strip().splitlines()))
1.48 + return props
1.49 +
1.50 + # return the folder containing the guest VMs
1.51 + def getMachineFolder(self):
1.52 + return self.machineFolder
1.53
1.54 def backend_ok(self):
1.55
1.56 @@ -145,33 +168,15 @@
1.57
1.58 def cleanup(self):
1.59 self.stop()
1.60 - drives = self.getNetworkDrives()
1.61 - for drive in drives.keys():
1.62 - try:
1.63 - result = urllib2.urlopen('http://127.0.0.1:8090/netumount?'+'drive_letter='+drive).readline()
1.64 - except urllib2.URLError:
1.65 - logger.info("Network drive disconnect skipped. OpenSecurity Tray client not started yet.")
1.66 + ip = self.getHostOnlyIP(None)
1.67 + try:
1.68 + result = urllib2.urlopen('http://127.0.0.1:8090/netcleanup?'+'hostonly_ip='+ip).readline()
1.69 + except urllib2.URLError:
1.70 + logger.info("Network drive cleanup all skipped. OpenSecurity Tray client not started yet.")
1.71
1.72 - #TODO://continue here
1.73 - #self.removeSnapshots('SecurityDVM')
1.74 -
1.75 for vm in self.listSDVM():
1.76 self.poweroffVM(vm)
1.77 self.removeVM(vm)
1.78 -
1.79 -
1.80 -
1.81 - # return hosty system properties
1.82 - def getSystemProperties(self):
1.83 - result = Cygwin.checkResult(Cygwin.vboxExecute('list systemproperties'))
1.84 - if result[1]=='':
1.85 - return None
1.86 - props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split(':', 1) for line in result[1].strip().splitlines()))
1.87 - return props
1.88 -
1.89 - # return the folder containing the guest VMs
1.90 - def getMachineFolder(self):
1.91 - return self.machineFolder
1.92
1.93 # list all existing VMs registered with VBox
1.94 def listVM(self):
1.95 @@ -474,21 +479,12 @@
1.96 logger.info('Powering off ' + vm_name)
1.97 return Cygwin.checkResult(Cygwin.vboxExecute('controlvm ' + vm_name + ' poweroff'))
1.98
1.99 - #list the hostonly IFs exposed by the VBox host
1.100 - @staticmethod
1.101 - def getHostOnlyIFs():
1.102 - result = Cygwin.vboxExecute('list hostonlyifs')[1]
1.103 - if result=='':
1.104 - return None
1.105 - props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split(':', 1) for line in result.strip().splitlines()))
1.106 - return props
1.107 -
1.108 - # return the hostOnly IP for a running guest or the host
1.109 - @staticmethod
1.110 - def getHostOnlyIP(vm_name):
1.111 + # return the hostOnly IP for a running guest or the host
1.112 + def getHostOnlyIP(self, vm_name):
1.113 if vm_name == None:
1.114 logger.info('Getting hostOnly IP address for Host')
1.115 - return VMManager.getHostOnlyIFs()['IPAddress']
1.116 + #TODO:// optimise to store on init local variable and return that value (avoid calling list hostonlyifs)
1.117 + return self.hostonlyIFs['IPAddress']
1.118 else:
1.119 logger.info('Getting hostOnly IP address ' + vm_name)
1.120 result = Cygwin.checkResult(Cygwin.vboxExecute('guestproperty get ' + vm_name + ' /VirtualBox/GuestInfo/Net/0/V4/IP'))
1.121 @@ -535,7 +531,7 @@
1.122 # wait for machine to come up
1.123 def waitStartup(self, vm_name, timeout_ms = 30000):
1.124 Cygwin.checkResult(Cygwin.vboxExecute('guestproperty wait ' + vm_name + ' SDVMStarted --timeout ' + str(timeout_ms) + ' --fail-on-timeout'))
1.125 - return VMManager.getHostOnlyIP(vm_name)
1.126 + return self.getHostOnlyIP(vm_name)
1.127
1.128 # wait for machine to shutdown
1.129 def waitShutdown(self, vm_name):
1.130 @@ -548,50 +544,29 @@
1.131 result = Cygwin.checkResult(Cygwin.cmdExecute('dir ' + path + ' | FIND ".."'))
1.132 return string.find(result[1], 'DIR',)
1.133
1.134 - def getNetworkDrives(self):
1.135 - ip = VMManager.getHostOnlyIP(None)
1.136 - ip = ip[:ip.rindex('.')]
1.137 - drives = dict()
1.138 - result = Cygwin.checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE'))
1.139 -
1.140 - #logger.info( result[1] )
1.141 - for line in result[1].splitlines():
1.142 - if ip in line:
1.143 - parts = line.split()
1.144 - drives[parts[1]] = parts[2]
1.145 -
1.146 - return drives
1.147 -
1.148 - def getNetworkDrive(self, vm_name):
1.149 - ip = self.getHostOnlyIP(vm_name)
1.150 - if ip == None:
1.151 - return None
1.152 - result = Cygwin.checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE'))
1.153 - for line in result[1].splitlines():
1.154 - if line != None and ip in line:
1.155 - parts = line.split()
1.156 - return parts[1]
1.157 -
1.158 def genNetworkDrive(self):
1.159 - network_drives = self.getNetworkDrives()
1.160 - logger.info("Used network drive letters: "+ str(network_drives.keys()).strip('[]') )
1.161 logical_drives = VMManager.getLogicalDrives()
1.162 logger.info("Used logical drive letters: "+ str(logical_drives).strip('[]') )
1.163 drives = list(map(chr, range(68, 91)))
1.164 for drive in drives:
1.165 - if drive+':' not in network_drives and drive not in logical_drives:
1.166 - return drive+':'
1.167 + if drive not in logical_drives:
1.168 + return drive
1.169
1.170 @staticmethod
1.171 def getLogicalDrives():
1.172 drive_bitmask = ctypes.cdll.kernel32.GetLogicalDrives()
1.173 - return list(itertools.compress(string.ascii_uppercase, map(lambda x:ord(x) - ord('0'), bin(drive_bitmask)[:1:-1])))
1.174 + drives = list(itertools.compress(string.ascii_uppercase, map(lambda x:ord(x) - ord('0'), bin(drive_bitmask)[:1:-1])))
1.175 + return drives
1.176
1.177 @staticmethod
1.178 def getDriveType(drive):
1.179 return ctypes.cdll.kernel32.GetDriveTypeW(u"%s:\\"%drive)
1.180
1.181 @staticmethod
1.182 + def getNetworkPath(drive):
1.183 + return win32wnet.WNetGetConnection(drive+':')
1.184 +
1.185 + @staticmethod
1.186 def getVolumeInfo(drive):
1.187 volumeNameBuffer = ctypes.create_unicode_buffer(1024)
1.188 fileSystemNameBuffer = ctypes.create_unicode_buffer(1024)
1.189 @@ -600,7 +575,6 @@
1.190 file_system_flags = None
1.191
1.192 rc = ctypes.cdll.kernel32.GetVolumeInformationW(
1.193 - #ctypes.c_wchar_p("F:\\"),
1.194 u"%s:\\"%drive,
1.195 volumeNameBuffer,
1.196 ctypes.sizeof(volumeNameBuffer),
1.197 @@ -610,9 +584,38 @@
1.198 fileSystemNameBuffer,
1.199 ctypes.sizeof(fileSystemNameBuffer)
1.200 )
1.201 -
1.202 return volumeNameBuffer.value, fileSystemNameBuffer.value
1.203
1.204 + def getNetworkDrive(self, vm_name):
1.205 + ip = self.getHostOnlyIP(vm_name)
1.206 + if ip == None:
1.207 + logger.error("Failed getting hostonly IP for " + vm_name)
1.208 + return None
1.209 + logger.info("Got IP address for " + vm_name + ': ' + ip)
1.210 + for drive in VMManager.getLogicalDrives():
1.211 + #if is a network drive
1.212 + if VMManager.getDriveType(drive) == 4:
1.213 + network_path = VMManager.getNetworkPath(drive)
1.214 + if ip in network_path:
1.215 + return drive
1.216 + return None
1.217 +
1.218 + def getNetworkDrives(self):
1.219 + ip = self.getHostOnlyIP(None)
1.220 + if ip == None:
1.221 + logger.error("Failed getting hostonly IP for system")
1.222 + return None
1.223 + logger.info("Got IP address for system: " + ip)
1.224 + ip = ip[:ip.rindex('.')]
1.225 + network_drives = dict()
1.226 + for drive in VMManager.getLogicalDrives():
1.227 + #if is a network drive
1.228 + if VMManager.getDriveType(drive) == 4:
1.229 + network_path = VMManager.getNetworkPath(drive)
1.230 + if ip in network_path:
1.231 + network_drives[drive] = network_path
1.232 + return network_drives
1.233 +
1.234 # handles browsing request
1.235 def handleBrowsingRequest(self):
1.236 handler = BrowsingHandler(self)
1.237 @@ -670,10 +673,6 @@
1.238 def run(self):
1.239 #browser = '\\\"/usr/bin/chromium; pidof dbus-launch | xargs kill\\\"'
1.240 browser = '\\\"/usr/bin/chromium\\\"'
1.241 - #if not Cygwin.is_X11_running():
1.242 - # self.vmm.browsingManager.restart.set()
1.243 - # return
1.244 -
1.245 try:
1.246 self.vmm.browsingManager.started.wait()
1.247 result = Cygwin.checkResult(Cygwin.sshExecuteX11(browser, self.vmm.browsingManager.ip_addr, 'osecuser', Cygwin.cygPath(self.vmm.getMachineFolder()) + '/' + self.vmm.browsingManager.vm_name + '/dvm_key'))
1.248 @@ -691,7 +690,7 @@
1.249 restart = None
1.250 ip_addr = None
1.251 vm_name = None
1.252 - drive = None
1.253 + net_resource = None
1.254 appDataDir = None
1.255
1.256 def __init__(self, vmmanager):
1.257 @@ -709,14 +708,14 @@
1.258 self.restart.clear()
1.259 self.started.clear()
1.260
1.261 - if self.drive == None:
1.262 - logger.info("Missing browsing SDVM's network drive letter. Skipping disconnect")
1.263 + if self.net_resource == None:
1.264 + logger.info("Missing browsing SDVM's network share. Skipping disconnect")
1.265 else:
1.266 try:
1.267 - browsing_vm = urllib2.urlopen('http://127.0.0.1:8090/netumount?'+'drive_letter='+self.drive).readline()
1.268 - self.drive = None
1.269 + browsing_vm = urllib2.urlopen('http://127.0.0.1:8090/netumount?'+'net_resource='+self.net_resource).readline()
1.270 + self.net_resource = None
1.271 except urllib2.URLError:
1.272 - logger.error("Network drive disconnect failed. OpenSecurity Tray client not running.")
1.273 + logger.error("Network share disconnect failed. OpenSecurity Tray client not running.")
1.274 continue
1.275
1.276 self.ip_addr = None
1.277 @@ -738,19 +737,12 @@
1.278 else:
1.279 logger.info("Got IP address for " + self.vm_name + ' ' + self.ip_addr)
1.280
1.281 - self.drive = self.vmm.genNetworkDrive()
1.282 - if self.drive == None:
1.283 - logger.error("Failed to assign Network drive letter")
1.284 - continue
1.285 - else:
1.286 - logger.info("Assigned drive " + self.drive + " to " + self.vm_name)
1.287 -
1.288 try:
1.289 - net_resource = '\\\\' + self.ip_addr + '\\Download'
1.290 - result = urllib2.urlopen('http://127.0.0.1:8090/netmount?'+'drive_letter='+self.drive+'&net_resource='+net_resource).readline()
1.291 + self.net_resource = '\\\\' + self.ip_addr + '\\Download'
1.292 + result = urllib2.urlopen('http://127.0.0.1:8090/netmount?'+'net_resource='+self.net_resource).readline()
1.293 except urllib2.URLError:
1.294 logger.error("Network drive connect failed. OpenSecurity Tray client not running.")
1.295 - self.drive = None
1.296 + self.net_resource = None
1.297 continue
1.298
1.299 user = self.vmm.getActiveUserName()
1.300 @@ -802,19 +794,27 @@
1.301 self.running = False
1.302
1.303 def run(self):
1.304 - self.existingRSDs = self.vmm.getExistingRSDs()
1.305 +
1.306 + self.existingRSDs = dict()
1.307 self.attachedRSDs = self.vmm.getAttachedRSDs()
1.308
1.309 while self.running:
1.310 tmp_rsds = self.vmm.getExistingRSDs()
1.311 + if tmp_rsds.keys() == self.existingRSDs.keys():
1.312 + logger.debug("Nothing's changed. sleep(3)")
1.313 + time.sleep(3)
1.314 + continue
1.315 +
1.316 + logger.info("Something's changed")
1.317 for vm_name in self.attachedRSDs.keys():
1.318 if self.attachedRSDs[vm_name] not in tmp_rsds.values():
1.319 - drive = self.vmm.getNetworkDrive(vm_name)
1.320 + ip = self.vmm.getHostOnlyIP(vm_name)
1.321 + if ip == None:
1.322 + logger.error("Failed getting hostonly IP for " + vm_name)
1.323 + continue
1.324 try:
1.325 - if drive != None:
1.326 - result = urllib2.urlopen('http://127.0.0.1:8090/netumount?'+'drive_letter='+drive).readline()
1.327 - else:
1.328 - logger.error("Error getting SDVM's network drive letter.")
1.329 + net_resource = '\\\\' + ip + '\\USB'
1.330 + result = urllib2.urlopen('http://127.0.0.1:8090/netumount?'+'net_resource='+net_resource).readline()
1.331 except urllib2.URLError:
1.332 logger.error("Network drive disconnect failed. OpenSecurity Tray client not running.")
1.333 continue
1.334 @@ -824,22 +824,11 @@
1.335 del self.attachedRSDs[vm_name]
1.336 self.vmm.poweroffVM(vm_name)
1.337 self.vmm.removeVM(vm_name)
1.338 - break
1.339 + #break
1.340
1.341 - if tmp_rsds.keys() == self.existingRSDs.keys():
1.342 - logger.debug("Nothing's changed. sleep(3)")
1.343 - time.sleep(3)
1.344 - continue
1.345 -
1.346 - logger.info("Something's changed")
1.347 - self.existingRSDs = tmp_rsds
1.348 -
1.349 - #create new vm for attached device if any
1.350 - #self.attachedRSDs = self.vmm.getAttachedRSDs()
1.351 - #self.connectedRSDs = self.vmm.getExistingRSDs()
1.352 -
1.353 + #create new vms for new devices if any
1.354 new_ip = None
1.355 - for new_device in self.existingRSDs.values():
1.356 + for new_device in tmp_rsds.values():
1.357 if (self.attachedRSDs and False) or (new_device not in self.attachedRSDs.values()):
1.358 new_sdvm = self.vmm.newSDVM()
1.359 self.vmm.storageAttach(new_sdvm)
1.360 @@ -860,18 +849,16 @@
1.361 self.vmm.poweroffVM(new_sdvm)
1.362 self.vmm.removeVM(new_sdvm)
1.363 continue
1.364 - drive = self.vmm.genNetworkDrive()
1.365 - if drive == None:
1.366 - logger.error("Error getting drive letter for network drive.")
1.367 - continue
1.368 try:
1.369 net_resource = '\\\\' + new_ip + '\\USB'
1.370 - result = urllib2.urlopen('http://127.0.0.1:8090/netmount?'+'drive_letter='+drive+'&net_resource='+net_resource).readline()
1.371 + result = urllib2.urlopen('http://127.0.0.1:8090/netmount?'+'net_resource='+net_resource).readline()
1.372 except urllib2.URLError:
1.373 logger.error("Network drive connect failed (tray client not accessible). Cleaning up.")
1.374 self.vmm.poweroffVM(new_sdvm)
1.375 self.vmm.removeVM(new_sdvm)
1.376 continue
1.377 +
1.378 + self.existingRSDs = tmp_rsds
1.379
1.380
1.381 if __name__ == '__main__':
1.382 @@ -891,6 +878,7 @@
1.383 print drives
1.384 print VMManager.getDriveType("E")
1.385 print VMManager.getVolumeInfo("E")
1.386 + print VMManager.getNetworkPath("E")
1.387
1.388 #vmm.backupFile()
1.389 #for device in devices.values():