2 # -*- coding: utf-8 -*-
4 # ------------------------------------------------------------
7 # executes a cygwin command inside the opensecurity project
9 # Autor: Mihai Bartha, <mihai.bartha@ait.ac.at>
10 # Oliver Maurhart, <oliver.maurhart@ait.ac.at>
12 # Copyright 2013-2014 X-Net and AIT Austrian Institute of Technology
19 # https://www.x-net.at
21 # AIT Austrian Institute of Technology
22 # Donau City Strasse 1
25 # http://www.ait.ac.at
28 # Licensed under the Apache License, Version 2.0 (the "License");
29 # you may not use this file except in compliance with the License.
30 # You may obtain a copy of the License at
32 # http://www.apache.org/licenses/LICENSE-2.0
34 # Unless required by applicable law or agreed to in writing, software
35 # distributed under the License is distributed on an "AS IS" BASIS,
36 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
37 # See the License for the specific language governing permissions and
38 # limitations under the License.
39 # ------------------------------------------------------------
42 # ------------------------------------------------------------
49 from subprocess import Popen, PIPE, STARTUPINFO, _subprocess
53 from environment import Environment
54 from opensecurity_util import logger, setupLogger, OpenSecurityException
58 # ------------------------------------------------------------
62 """get the path to our local cygwin installment"""
63 home_drive = os.path.expandvars("%HOMEDRIVE%") + os.sep
64 e = Environment('OpenSecurity')
66 os.path.abspath(os.path.join(e.prefix_path, 'cygwin')),
67 os.path.abspath(os.path.join(e.prefix_path, 'cygwin64')),
68 os.path.abspath(os.path.join(home_drive, 'cygwin')),
69 os.path.abspath(os.path.join(home_drive, 'cygwin64'))
71 path_valid = [ p for p in path_hint if os.path.exists(p) ]
72 theClass.cygwin_root = path_valid[0]
73 theClass.cygwin_bin = os.path.join(theClass.cygwin_root, 'bin') + os.path.sep
74 theClass.cygwin_bash = os.path.join(theClass.cygwin_bin, 'bash.exe')
75 theClass.cygwin_ssh = os.path.join(theClass.cygwin_bin, 'ssh.exe')
76 theClass.cygwin_scp = os.path.join(theClass.cygwin_bin, 'scp.exe')
77 theClass.cygwin_rsync = os.path.join(theClass.cygwin_bin, 'rsync.exe')
78 theClass.cygwin_x11 = os.path.join(theClass.cygwin_bin, 'XWin.exe')
79 theClass.win_cmd = os.environ.get("COMSPEC", "cmd.exe")
80 """get the path to the VirtualBox installation on this system"""
81 theClass.vbox_root = theClass.getRegEntry('SOFTWARE\Oracle\VirtualBox', 'InstallDir')[0]
82 theClass.vbox_man = os.path.join(theClass.vbox_root, 'VBoxManage.exe')
83 #theClass.user_home = os.path.expanduser("~")
84 theClass.user_home = os.environ['APPDATA']#os.path.expandvars("%APPDATA%")
85 theClass.allow_exec = True
103 """Some nifty methods working with Cygwin"""
105 def __call__(self, command, arguments, wait_return=True, window = False):
106 """make an instance of this object act as a function"""
107 return self.execute(command, arguments, wait_return, window)
110 def getRegEntry(key, value):
112 k = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, key)
113 value = _winreg.QueryValueEx(k, value)
122 return Cygwin.cygwin_root
126 return Cygwin.cygwin_bin
130 return Cygwin.cygwin_bash
134 return Cygwin.cygwin_ssh
138 return Cygwin.cygwin_scp
142 return Cygwin.cygwin_rsync
146 return Cygwin.cygwin_x11
150 return Cygwin.vbox_man
154 return Cygwin.win_cmd
158 return Cygwin.user_home
162 Cygwin.allow_exec = True
166 Cygwin.allow_exec = False
168 executeLock = threading.Lock()
169 #executes command on host system
171 def execute(program, arguments, wait_return=True, window = False, stdin = PIPE, stdout = PIPE, stderr = PIPE):
172 if not Cygwin.allow_exec:
173 logger.error('Execution cancelled by system (shutting down).')
174 raise OpenSecurityException('Execution cancelled by system (shutting down).')
176 _startupinfo = STARTUPINFO()
178 _startupinfo.dwFlags |= _subprocess.STARTF_USESHOWWINDOW
179 _startupinfo.wShowWindow = _subprocess.SW_HIDE
180 #logger.debug('trying to launch: ' + program + ' ' + ''.join(arguments))
182 result, res_stdout, res_stderr = None, None, None
184 # quote the executable otherwise we run into troubles
185 # when the path contains spaces and additional arguments
186 # are presented as well.
187 # special: invoking bash as login shell here with
188 # an unquoted command does not execute /etc/profile
189 args = '"' + program + '" ' + arguments
190 logger.debug('Launching: ' + program + ' ' + ''.join(arguments))
191 process = Popen(args, startupinfo = _startupinfo, stdin = stdin, stdout = stdout, stderr = stderr, shell = False)
193 return [0, 'working in background', '']
195 res_stdout, res_stderr = process.communicate()
196 result = process.returncode
197 logger.debug('Finished: ' + program + ' ' + ''.join(arguments))
199 except Exception as ex:
200 res_stderr = ''.join(str(ex.args))
204 logger.error('Command failed:' + ''.join(res_stderr))
205 raise OpenSecurityException('Command failed:' + ''.join(res_stderr))
207 return result, res_stdout, res_stderr
210 def vboxExecute(command, wait_return=True, window = False, bash_opts='', try_count = 3):
213 while retry < try_count:
214 if Cygwin.executeLock.acquire(True):
216 result = Cygwin.execute(Cygwin.vbox_man, command, wait_return, window)
217 except Exception as ex:
218 Cygwin.executeLock.release()
219 if (retry+1) == try_count:
222 Cygwin.executeLock.release()
225 raise OpenSecurityException('Command max retry reached: ' + ''.join(command))
229 def bashExecute(command, wait_return=True, window = False, bash_opts='', stdin = PIPE, stdout = PIPE, stderr = PIPE):
230 # for some reason, the '-l' is ignored when started via python
231 # so the same behavior is triggered by calling /etc/profile
233 command = bash_opts + ' -l -c "' + command + '"'
234 return Cygwin.execute(Cygwin.cygwin_bash, command, wait_return, window, stdin = stdin, stdout = stdout, stderr = stderr)
237 def cmdExecute(command, wait_return=True, window = False):
238 command = ' /c ' + command
239 return Cygwin.execute(Cygwin.win_cmd, command, wait_return, window)
241 # executes command over ssh on guest vm
243 def sshExecute(command, address, user_name, certificate, wait_return=True, window = False):
244 if command == None or address == None or user_name == None or certificate == None:
245 raise OpenSecurityException('Invalid parameter value')
246 command = ' -v -o StrictHostKeyChecking=no -i "' + certificate + '" ' + user_name + '@' + address + ' ' + command
247 return Cygwin.execute(Cygwin.cygwin_ssh, command, wait_return, window)
249 # executes command over ssh on guest vm
251 def sshBackgroundExecute(command, address, user_name, certificate, wait_return=True, window = False):
252 command = ' -f -v -o StrictHostKeyChecking=no -i "' + certificate + '" ' + user_name + '@' + address + ' ' + command
253 return Cygwin.execute(Cygwin.cygwin_ssh, command, wait_return, window)
255 #machineFolder + '/' + vm_name + '/dvm_key
256 #address = self.getHostOnlyIP(vm_name)
257 #machineFolder = self.getDefaultMachineFolder()
258 #machineFolder = Cygwin.cygwinPath(machineFolder)
260 # executes command over ssh on guest vm with X forwarding
262 def sshExecuteX11(command, address, user_name, certificate, wait_return=True):
263 return Cygwin.bashExecute('DISPLAY=:0.0 ssh -Y -o StrictHostKeyChecking=no -i \\\"' + certificate +'\\\" ' + user_name + '@' + address + ' ' + command + '')
266 def is_X11_running():
267 """check if we can connect to a X11 running instance"""
268 p = Cygwin.bashExecute('xset -display :0 q', wait_return = True, window = False)
273 """start X11 in the background (if not already running) on DISPLAY=:0
275 If there is already a X11 running then exit silently, calling this
276 method as often as needed.
278 Popen('"' + Cygwin.cygwin_x11 + '" :0 -multiwindow -resize -silent-dup-error')
279 return (0, None, None)
283 cmd = 'cygpath -u \'' + path + '\''
284 return Cygwin.bashExecute(cmd)[1].rstrip('\n')
292 if __name__ == "__main__":
293 logger = setupLogger('Cygwin')
295 logger.info(c.root())
297 logger.info(c.bash())
300 logger.info(c.home())
303 #tasklist /v /fo list /fi "IMAGENAME eq explorer.exe"
313 #print (Cygwin.is_X11_running())
314 #print (Cygwin.is_X11_running())
315 #new_sdvm = 'SecurityDVM0'
316 #new_ip = Cygwin.vboxExecute('guestproperty get ' + new_sdvm + ' /VirtualBox/GuestInfo/Net/0/V4/IP')[1]
317 #new_ip = new_ip[new_ip.index(':')+1:].strip()
319 #result = Cygwin.bashExecute('DISPLAY=:0.0 xhost '+new_ip)
320 #browser = '/usr/bin/midori '
321 #print(Cygwin.sshExecuteX11(browser, new_ip, 'osecuser', '/cygdrive/c/Users/BarthaM/VirtualBox VMs' + '/' + new_sdvm + '/dvm_key'))
323 #print(Cygwin.bashExecute('echo $PATH')[1])
324 #print(Cygwin.cygPath('C:'))
325 #print('C:\\Program Files\\OpenSecurity: ' + c.cygPath('C:\\Program Files\\OpenSecurity'))