oliver@87
|
1 |
#!/bin/env python
|
oliver@87
|
2 |
# -*- coding: utf-8 -*-
|
oliver@87
|
3 |
|
oliver@87
|
4 |
# ------------------------------------------------------------
|
oliver@87
|
5 |
# cygwin command
|
oliver@87
|
6 |
#
|
oliver@87
|
7 |
# executes a cygwin command inside the opensecurity project
|
oliver@87
|
8 |
#
|
oliver@87
|
9 |
# Autor: Mihai Bartha, <mihai.bartha@ait.ac.at>
|
oliver@87
|
10 |
# Oliver Maurhart, <oliver.maurhart@ait.ac.at>
|
oliver@87
|
11 |
#
|
oliver@87
|
12 |
# Copyright (C) 2013 AIT Austrian Institute of Technology
|
oliver@87
|
13 |
# AIT Austrian Institute of Technology GmbH
|
oliver@87
|
14 |
# Donau-City-Strasse 1 | 1220 Vienna | Austria
|
oliver@87
|
15 |
# http://www.ait.ac.at
|
oliver@87
|
16 |
#
|
oliver@87
|
17 |
# This program is free software; you can redistribute it and/or
|
oliver@87
|
18 |
# modify it under the terms of the GNU General Public License
|
oliver@87
|
19 |
# as published by the Free Software Foundation version 2.
|
oliver@87
|
20 |
#
|
oliver@87
|
21 |
# This program is distributed in the hope that it will be useful,
|
oliver@87
|
22 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
oliver@87
|
23 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
oliver@87
|
24 |
# GNU General Public License for more details.
|
oliver@87
|
25 |
#
|
oliver@87
|
26 |
# You should have received a copy of the GNU General Public License
|
oliver@87
|
27 |
# along with this program; if not, write to the Free Software
|
oliver@87
|
28 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
oliver@87
|
29 |
# Boston, MA 02110-1301, USA.
|
oliver@87
|
30 |
# ------------------------------------------------------------
|
oliver@87
|
31 |
|
oliver@87
|
32 |
|
oliver@87
|
33 |
# ------------------------------------------------------------
|
oliver@87
|
34 |
# imports
|
oliver@87
|
35 |
|
oliver@87
|
36 |
import os
|
oliver@87
|
37 |
import subprocess
|
oliver@87
|
38 |
import sys
|
oliver@87
|
39 |
import _winreg
|
oliver@87
|
40 |
from subprocess import Popen, PIPE, call, STARTUPINFO, _subprocess
|
oliver@87
|
41 |
import threading
|
oliver@87
|
42 |
# local
|
oliver@87
|
43 |
from environment import Environment
|
oliver@87
|
44 |
from opensecurity_util import logger, setupLogger, OpenSecurityException
|
oliver@87
|
45 |
|
oliver@87
|
46 |
# ------------------------------------------------------------
|
oliver@87
|
47 |
# code
|
oliver@87
|
48 |
|
oliver@87
|
49 |
def once(theClass):
|
oliver@87
|
50 |
"""get the path to our local cygwin installment"""
|
oliver@87
|
51 |
home_drive = os.path.expandvars("%HOMEDRIVE%") + os.sep
|
oliver@87
|
52 |
path_hint = [
|
oliver@87
|
53 |
os.path.abspath(os.path.join(Environment('OpenSecurity').prefix_path, '..', 'cygwin')),
|
oliver@87
|
54 |
os.path.abspath(os.path.join(Environment('OpenSecurity').prefix_path, '..', 'cygwin64')),
|
oliver@87
|
55 |
os.path.abspath(os.path.join(home_drive, 'cygwin')),
|
oliver@87
|
56 |
os.path.abspath(os.path.join(home_drive, 'cygwin64'))
|
oliver@87
|
57 |
]
|
oliver@87
|
58 |
path_valid = [ p for p in path_hint if os.path.exists(p) ]
|
oliver@87
|
59 |
|
oliver@87
|
60 |
theClass.cygwin_root = path_valid[0]
|
oliver@87
|
61 |
theClass.cygwin_bin = os.path.join(theClass.cygwin_root, 'bin') + os.path.sep
|
oliver@87
|
62 |
theClass.cygwin_bash = os.path.join(theClass.cygwin_bin, 'bash.exe')
|
oliver@87
|
63 |
theClass.cygwin_ssh = os.path.join(theClass.cygwin_bin, 'ssh.exe')
|
oliver@87
|
64 |
theClass.cygwin_x11 = os.path.join(theClass.cygwin_bin, 'XWin.exe')
|
oliver@87
|
65 |
theClass.win_cmd = os.environ.get("COMSPEC", "cmd.exe")
|
oliver@87
|
66 |
|
oliver@87
|
67 |
"""get the path to the VirtualBox installation on this system"""
|
oliver@87
|
68 |
try:
|
oliver@87
|
69 |
k = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\Oracle\VirtualBox')
|
oliver@87
|
70 |
theClass.vbox_root = _winreg.QueryValueEx(k, 'InstallDir')[0]
|
oliver@87
|
71 |
theClass.vbox_man = os.path.join(theClass.vbox_root, 'VBoxManage.exe')
|
oliver@87
|
72 |
_winreg.CloseKey(k)
|
oliver@87
|
73 |
except:
|
oliver@87
|
74 |
pass
|
oliver@87
|
75 |
return theClass
|
oliver@87
|
76 |
|
oliver@87
|
77 |
@once
|
oliver@87
|
78 |
class Cygwin(object):
|
oliver@87
|
79 |
cygwin_root = ''
|
oliver@87
|
80 |
cygwin_bin = ''
|
oliver@87
|
81 |
cygwin_bash = ''
|
oliver@87
|
82 |
cygwin_ssh = ''
|
oliver@87
|
83 |
cygwin_x11 = ''
|
oliver@87
|
84 |
vbox_root = ''
|
oliver@87
|
85 |
vbox_man = ''
|
oliver@87
|
86 |
win_cmd = ''
|
oliver@87
|
87 |
"""Some nifty methods working with Cygwin"""
|
oliver@87
|
88 |
|
oliver@87
|
89 |
def __call__(self, command, arguments, wait_return=True, window = False):
|
oliver@87
|
90 |
"""make an instance of this object act as a function"""
|
oliver@87
|
91 |
return self.execute(command, arguments, wait_return, window)
|
oliver@87
|
92 |
|
oliver@87
|
93 |
|
oliver@87
|
94 |
@staticmethod
|
oliver@87
|
95 |
def root():
|
oliver@87
|
96 |
return Cygwin.cygwin_root
|
oliver@87
|
97 |
|
oliver@87
|
98 |
@staticmethod
|
oliver@87
|
99 |
def bin():
|
oliver@87
|
100 |
return Cygwin.cygwin_bin
|
oliver@87
|
101 |
|
oliver@87
|
102 |
@staticmethod
|
oliver@87
|
103 |
def bash():
|
oliver@87
|
104 |
return Cygwin.cygwin_bash
|
oliver@87
|
105 |
|
oliver@87
|
106 |
@staticmethod
|
oliver@87
|
107 |
def ssh():
|
oliver@87
|
108 |
return Cygwin.cygwin_ssh
|
oliver@87
|
109 |
|
oliver@87
|
110 |
@staticmethod
|
oliver@87
|
111 |
def x11():
|
oliver@87
|
112 |
return Cygwin.cygwin_x11
|
oliver@87
|
113 |
|
oliver@87
|
114 |
@staticmethod
|
oliver@87
|
115 |
def vboxman():
|
oliver@87
|
116 |
return Cygwin.vbox_man
|
oliver@87
|
117 |
|
oliver@87
|
118 |
@staticmethod
|
oliver@87
|
119 |
def cmd():
|
oliver@87
|
120 |
return Cygwin.win_cmd
|
oliver@87
|
121 |
|
oliver@87
|
122 |
executeLock = threading.Lock()
|
oliver@87
|
123 |
#executes command on host system
|
oliver@87
|
124 |
@staticmethod
|
oliver@87
|
125 |
def execute(program, arguments, wait_return=True, window = False):
|
oliver@87
|
126 |
_startupinfo = STARTUPINFO()
|
oliver@87
|
127 |
if not window:
|
oliver@87
|
128 |
_startupinfo.dwFlags |= _subprocess.STARTF_USESHOWWINDOW
|
oliver@87
|
129 |
_startupinfo.wShowWindow = _subprocess.SW_HIDE
|
oliver@87
|
130 |
|
oliver@87
|
131 |
#logger.debug('trying to launch: ' + program + ' ' + ''.join(arguments))
|
oliver@87
|
132 |
res_stderr = None
|
oliver@87
|
133 |
try:
|
oliver@87
|
134 |
process = Popen(executable=program, args=' ' + arguments, startupinfo = _startupinfo, stdin=PIPE, stdout=PIPE, stderr=PIPE, shell = False)
|
oliver@87
|
135 |
logger.debug('Launched: ' + program + ' ' + ''.join(arguments))
|
oliver@87
|
136 |
if not wait_return:
|
oliver@87
|
137 |
return [0, 'working in background', '']
|
oliver@87
|
138 |
result = process.wait()
|
oliver@87
|
139 |
res_stdout = process.stdout.read();
|
oliver@87
|
140 |
res_stderr = process.stderr.read();
|
oliver@87
|
141 |
|
oliver@87
|
142 |
except Exception as ex:
|
oliver@87
|
143 |
res_stderr = ''.join(ex.args)
|
oliver@87
|
144 |
result = -1
|
oliver@87
|
145 |
|
oliver@87
|
146 |
if result != 0:
|
oliver@87
|
147 |
logger.error('Failed to execute cygwin command.\n\tcommand=' + program + ' ' + ''.join(arguments) + '\n' + res_stderr)
|
oliver@87
|
148 |
raise OpenSecurityException('Failed to execute cygwin command.\n\tcommand=' + program + ' ' + ''.join(arguments) + '\n' + res_stderr)
|
oliver@87
|
149 |
|
oliver@87
|
150 |
return result, res_stdout, res_stderr
|
oliver@87
|
151 |
|
oliver@87
|
152 |
@staticmethod
|
oliver@87
|
153 |
def vboxExecute(command, wait_return=True, window = False, bash_opts=''):
|
oliver@87
|
154 |
if Cygwin.executeLock.acquire(True):
|
oliver@87
|
155 |
retry = 0
|
oliver@87
|
156 |
while retry < 3:
|
oliver@87
|
157 |
try:
|
oliver@87
|
158 |
result = Cygwin.execute(Cygwin.vbox_man, command, wait_return, window)
|
oliver@87
|
159 |
Cygwin.executeLock.release()
|
oliver@87
|
160 |
return result
|
oliver@87
|
161 |
except OpenSecurityException as inst:
|
oliver@87
|
162 |
retry+=1
|
oliver@87
|
163 |
Cygwin.executeLock.release()
|
oliver@87
|
164 |
raise inst
|
oliver@87
|
165 |
return result
|
oliver@87
|
166 |
|
oliver@87
|
167 |
|
oliver@87
|
168 |
@staticmethod
|
oliver@87
|
169 |
def bashExecute(command, wait_return=True, window = False, bash_opts=''):
|
oliver@87
|
170 |
command = bash_opts + ' -l -c ' + command
|
oliver@87
|
171 |
return Cygwin.execute(Cygwin.cygwin_bash, command, wait_return, window)
|
oliver@87
|
172 |
|
oliver@87
|
173 |
@staticmethod
|
oliver@87
|
174 |
def cmdExecute(command, wait_return=True, window = False, bash_opts=''):
|
oliver@87
|
175 |
command = ' /c ' + command
|
oliver@87
|
176 |
return Cygwin.execute(Cygwin.win_cmd, command, wait_return, window)
|
oliver@87
|
177 |
|
oliver@87
|
178 |
# executes command over ssh on guest vm
|
oliver@87
|
179 |
@staticmethod
|
oliver@87
|
180 |
def sshExecute(command, address, user_name, certificate, wait_return=True, window = False):
|
oliver@87
|
181 |
command = ' -v -i "' + certificate + '" ' + user_name + '@' + address + ' ' + command
|
oliver@87
|
182 |
return Cygwin.execute(Cygwin.cygwin_ssh, command, wait_return, window)
|
oliver@87
|
183 |
|
oliver@87
|
184 |
#machineFolder + '/' + vm_name + '/dvm_key
|
oliver@87
|
185 |
#address = self.getHostOnlyIP(vm_name)
|
oliver@87
|
186 |
#machineFolder = self.getDefaultMachineFolder()
|
oliver@87
|
187 |
#machineFolder = Cygwin.cygwinPath(machineFolder)
|
oliver@87
|
188 |
|
oliver@87
|
189 |
# executes command over ssh on guest vm with X forwarding
|
oliver@87
|
190 |
@staticmethod
|
oliver@87
|
191 |
def sshExecuteX11(command, address, user_name, certificate, wait_return=True):
|
oliver@87
|
192 |
return Cygwin.bashExecute('"DISPLAY=:0.0 /usr/bin/ssh -v -Y -i \\"' + certificate +'\\" ' + user_name + '@' + address + ' ' + command + '\"')
|
oliver@87
|
193 |
|
oliver@87
|
194 |
@staticmethod
|
oliver@87
|
195 |
def is_X11_running():
|
oliver@87
|
196 |
"""check if we can connect to a X11 running instance"""
|
oliver@87
|
197 |
p = Cygwin.bashExecute('"DISPLAY=:0 /usr/bin/xset -q"')
|
oliver@87
|
198 |
return p[0] == 0
|
oliver@87
|
199 |
|
oliver@87
|
200 |
|
oliver@87
|
201 |
@staticmethod
|
oliver@87
|
202 |
def start_X11():
|
oliver@87
|
203 |
"""start X11 in the background (if not already running) on DISPLAY=:0"""
|
oliver@87
|
204 |
# do not start if already running
|
oliver@87
|
205 |
if Cygwin.is_X11_running():
|
oliver@87
|
206 |
return
|
oliver@87
|
207 |
# launch X11 (forget output and return immediately)
|
oliver@87
|
208 |
return Cygwin.execute(Cygwin.cygwin_x11, ':0 -multiwindow', wait_return = False, window = False)
|
oliver@87
|
209 |
|
oliver@87
|
210 |
@staticmethod
|
oliver@87
|
211 |
def cygPath(path):
|
oliver@87
|
212 |
cmd = '"/usr/bin/cygpath -u \\"' + path + '\\""'
|
oliver@87
|
213 |
return Cygwin.bashExecute(cmd)[1].rstrip('\n')
|
oliver@87
|
214 |
|
oliver@87
|
215 |
# start
|
oliver@87
|
216 |
if __name__ == "__main__":
|
oliver@87
|
217 |
logger = setupLogger('Cygwin')
|
oliver@87
|
218 |
c = Cygwin()
|
oliver@87
|
219 |
logger.info(c.root())
|
oliver@87
|
220 |
logger.info(c.bin())
|
oliver@87
|
221 |
logger.info(c.bash())
|
oliver@87
|
222 |
logger.info(c.ssh())
|
oliver@87
|
223 |
|
oliver@87
|
224 |
c.cygPath('C:')
|
oliver@87
|
225 |
c.start_X11()
|
oliver@87
|
226 |
|
oliver@87
|
227 |
|
oliver@87
|
228 |
|
oliver@87
|
229 |
|