oliver@167: #!/bin/env python oliver@167: # -*- coding: utf-8 -*- oliver@167: oliver@167: # ------------------------------------------------------------ oliver@167: # cygwin command oliver@167: # oliver@167: # executes a cygwin command inside the opensecurity project oliver@167: # oliver@167: # Autor: Mihai Bartha, oliver@167: # Oliver Maurhart, oliver@167: # oliver@240: # Copyright 2013-2014 X-Net and AIT Austrian Institute of Technology oliver@167: # oliver@167: # oliver@240: # X-Net Services GmbH oliver@240: # Elisabethstrasse 1 oliver@240: # 4020 Linz oliver@240: # AUSTRIA oliver@240: # https://www.x-net.at oliver@240: # oliver@240: # AIT Austrian Institute of Technology oliver@240: # Donau City Strasse 1 oliver@240: # 1220 Wien oliver@240: # AUSTRIA oliver@240: # http://www.ait.ac.at oliver@240: # oliver@240: # oliver@240: # Licensed under the Apache License, Version 2.0 (the "License"); oliver@240: # you may not use this file except in compliance with the License. oliver@240: # You may obtain a copy of the License at oliver@240: # oliver@240: # http://www.apache.org/licenses/LICENSE-2.0 oliver@240: # oliver@240: # Unless required by applicable law or agreed to in writing, software oliver@240: # distributed under the License is distributed on an "AS IS" BASIS, oliver@240: # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. oliver@240: # See the License for the specific language governing permissions and oliver@240: # limitations under the License. oliver@167: # ------------------------------------------------------------ oliver@167: oliver@167: oliver@167: # ------------------------------------------------------------ oliver@167: # imports oliver@167: oliver@167: import os oliver@167: import subprocess oliver@167: import sys oliver@167: import _winreg oliver@167: from subprocess import Popen, PIPE, STARTUPINFO, _subprocess oliver@167: import threading oliver@167: oliver@167: # local oliver@167: from environment import Environment oliver@167: from opensecurity_util import logger, setupLogger, OpenSecurityException oliver@167: import time oliver@167: oliver@167: oliver@167: # ------------------------------------------------------------ oliver@167: # code oliver@167: oliver@167: def once(theClass): oliver@167: """get the path to our local cygwin installment""" oliver@167: home_drive = os.path.expandvars("%HOMEDRIVE%") + os.sep BarthaM@212: e = Environment('OpenSecurity') oliver@167: path_hint = [ BarthaM@212: os.path.abspath(os.path.join(e.prefix_path, 'cygwin')), BarthaM@212: os.path.abspath(os.path.join(e.prefix_path, 'cygwin64')), oliver@167: os.path.abspath(os.path.join(home_drive, 'cygwin')), oliver@167: os.path.abspath(os.path.join(home_drive, 'cygwin64')) oliver@167: ] oliver@167: path_valid = [ p for p in path_hint if os.path.exists(p) ] oliver@167: theClass.cygwin_root = path_valid[0] oliver@167: theClass.cygwin_bin = os.path.join(theClass.cygwin_root, 'bin') + os.path.sep oliver@167: theClass.cygwin_bash = os.path.join(theClass.cygwin_bin, 'bash.exe') oliver@167: theClass.cygwin_ssh = os.path.join(theClass.cygwin_bin, 'ssh.exe') oliver@167: theClass.cygwin_scp = os.path.join(theClass.cygwin_bin, 'scp.exe') mihai@252: theClass.cygwin_rsync = os.path.join(theClass.cygwin_bin, 'rsync.exe') oliver@167: theClass.cygwin_x11 = os.path.join(theClass.cygwin_bin, 'XWin.exe') oliver@167: theClass.win_cmd = os.environ.get("COMSPEC", "cmd.exe") oliver@167: """get the path to the VirtualBox installation on this system""" oliver@167: theClass.vbox_root = theClass.getRegEntry('SOFTWARE\Oracle\VirtualBox', 'InstallDir')[0] oliver@167: theClass.vbox_man = os.path.join(theClass.vbox_root, 'VBoxManage.exe') oliver@167: #theClass.user_home = os.path.expanduser("~") oliver@167: theClass.user_home = os.environ['APPDATA']#os.path.expandvars("%APPDATA%") BarthaM@219: theClass.allow_exec = True oliver@167: return theClass oliver@167: oliver@167: oliver@167: @once oliver@167: class Cygwin(object): oliver@167: cygwin_root = '' oliver@167: cygwin_bin = '' oliver@167: cygwin_bash = '' oliver@167: cygwin_ssh = '' oliver@167: cygwin_x11 = '' oliver@167: cygwin_scp = '' mihai@252: cygwin_rsync = '' oliver@167: vbox_root = '' oliver@167: vbox_man = '' oliver@167: win_cmd = '' oliver@167: user_home = '' BarthaM@219: allow_exec = True oliver@167: """Some nifty methods working with Cygwin""" oliver@167: oliver@167: def __call__(self, command, arguments, wait_return=True, window = False): oliver@167: """make an instance of this object act as a function""" oliver@167: return self.execute(command, arguments, wait_return, window) oliver@167: oliver@167: @staticmethod oliver@167: def getRegEntry(key, value): oliver@167: try: oliver@167: k = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, key) oliver@167: value = _winreg.QueryValueEx(k, value) oliver@167: _winreg.CloseKey(k) oliver@167: return value oliver@167: except: oliver@167: pass oliver@167: oliver@167: oliver@167: @staticmethod oliver@167: def root(): oliver@167: return Cygwin.cygwin_root oliver@167: oliver@167: @staticmethod oliver@167: def bin(): oliver@167: return Cygwin.cygwin_bin oliver@167: oliver@167: @staticmethod oliver@167: def bash(): oliver@167: return Cygwin.cygwin_bash oliver@167: oliver@167: @staticmethod oliver@167: def ssh(): oliver@167: return Cygwin.cygwin_ssh oliver@167: oliver@167: @staticmethod oliver@167: def scp(): oliver@167: return Cygwin.cygwin_scp mihai@252: mihai@252: @staticmethod mihai@252: def rsync(): mihai@252: return Cygwin.cygwin_rsync oliver@167: oliver@167: @staticmethod oliver@167: def x11(): oliver@167: return Cygwin.cygwin_x11 oliver@167: oliver@167: @staticmethod oliver@167: def vboxman(): oliver@167: return Cygwin.vbox_man oliver@167: oliver@167: @staticmethod oliver@167: def cmd(): oliver@167: return Cygwin.win_cmd oliver@167: oliver@167: @staticmethod oliver@167: def home(): oliver@167: return Cygwin.user_home oliver@167: BarthaM@219: @staticmethod BarthaM@219: def allowExec(): BarthaM@219: Cygwin.allow_exec = True BarthaM@219: BarthaM@219: @staticmethod BarthaM@219: def denyExec(): BarthaM@219: Cygwin.allow_exec = False BarthaM@219: oliver@167: executeLock = threading.Lock() oliver@167: #executes command on host system oliver@167: @staticmethod oliver@167: def execute(program, arguments, wait_return=True, window = False, stdin = PIPE, stdout = PIPE, stderr = PIPE): BarthaM@219: if not Cygwin.allow_exec: BarthaM@219: logger.error('Execution cancelled by system (shutting down).') BarthaM@219: raise OpenSecurityException('Execution cancelled by system (shutting down).') BarthaM@219: oliver@167: _startupinfo = STARTUPINFO() oliver@167: if not window: oliver@167: _startupinfo.dwFlags |= _subprocess.STARTF_USESHOWWINDOW oliver@167: _startupinfo.wShowWindow = _subprocess.SW_HIDE oliver@167: #logger.debug('trying to launch: ' + program + ' ' + ''.join(arguments)) oliver@167: BarthaM@212: result, res_stdout, res_stderr = None, None, None oliver@167: try: oliver@167: # quote the executable otherwise we run into troubles BarthaM@218: # when the path contains spaces and additional arguments oliver@167: # are presented as well. oliver@167: # special: invoking bash as login shell here with oliver@167: # an unquoted command does not execute /etc/profile oliver@167: args = '"' + program + '" ' + arguments oliver@169: logger.debug('Launching: ' + program + ' ' + ''.join(arguments)) oliver@167: process = Popen(args, startupinfo = _startupinfo, stdin = stdin, stdout = stdout, stderr = stderr, shell = False) oliver@167: if not wait_return: oliver@167: return [0, 'working in background', ''] BarthaM@212: oliver@167: res_stdout, res_stderr = process.communicate() oliver@167: result = process.returncode oliver@169: logger.debug('Finished: ' + program + ' ' + ''.join(arguments)) oliver@167: oliver@167: except Exception as ex: oliver@167: res_stderr = ''.join(str(ex.args)) oliver@167: result = 1 BarthaM@218: BarthaM@218: if result != 0: BarthaM@218: logger.error('Command failed:' + ''.join(res_stderr)) BarthaM@218: raise OpenSecurityException('Command failed:' + ''.join(res_stderr)) BarthaM@218: oliver@167: return result, res_stdout, res_stderr oliver@167: oliver@167: @staticmethod BarthaM@212: def vboxExecute(command, wait_return=True, window = False, bash_opts='', try_count = 3): oliver@167: retry = 0 oliver@167: result = None BarthaM@212: while retry < try_count: oliver@167: if Cygwin.executeLock.acquire(True): BarthaM@218: try: BarthaM@218: result = Cygwin.execute(Cygwin.vbox_man, command, wait_return, window) BarthaM@218: except Exception as ex: BarthaM@218: Cygwin.executeLock.release() BarthaM@218: if (retry+1) == try_count: BarthaM@218: raise ex BarthaM@218: else: BarthaM@218: Cygwin.executeLock.release() oliver@167: return result BarthaM@218: retry+=1 BarthaM@218: raise OpenSecurityException('Command max retry reached: ' + ''.join(command)) oliver@167: oliver@167: oliver@167: @staticmethod oliver@167: def bashExecute(command, wait_return=True, window = False, bash_opts='', stdin = PIPE, stdout = PIPE, stderr = PIPE): oliver@167: # for some reason, the '-l' is ignored when started via python oliver@167: # so the same behavior is triggered by calling /etc/profile oliver@167: # directly oliver@167: command = bash_opts + ' -l -c "' + command + '"' oliver@167: return Cygwin.execute(Cygwin.cygwin_bash, command, wait_return, window, stdin = stdin, stdout = stdout, stderr = stderr) oliver@167: oliver@167: @staticmethod oliver@167: def cmdExecute(command, wait_return=True, window = False): oliver@167: command = ' /c ' + command oliver@167: return Cygwin.execute(Cygwin.win_cmd, command, wait_return, window) oliver@167: oliver@167: # executes command over ssh on guest vm oliver@167: @staticmethod oliver@167: def sshExecute(command, address, user_name, certificate, wait_return=True, window = False): BarthaM@218: if command == None or address == None or user_name == None or certificate == None: BarthaM@218: raise OpenSecurityException('Invalid parameter value') oliver@167: command = ' -v -o StrictHostKeyChecking=no -i "' + certificate + '" ' + user_name + '@' + address + ' ' + command oliver@167: return Cygwin.execute(Cygwin.cygwin_ssh, command, wait_return, window) BarthaM@212: BarthaM@212: # executes command over ssh on guest vm oliver@167: @staticmethod oliver@167: def sshBackgroundExecute(command, address, user_name, certificate, wait_return=True, window = False): oliver@167: command = ' -f -v -o StrictHostKeyChecking=no -i "' + certificate + '" ' + user_name + '@' + address + ' ' + command oliver@167: return Cygwin.execute(Cygwin.cygwin_ssh, command, wait_return, window) oliver@167: oliver@167: #machineFolder + '/' + vm_name + '/dvm_key oliver@167: #address = self.getHostOnlyIP(vm_name) oliver@167: #machineFolder = self.getDefaultMachineFolder() oliver@167: #machineFolder = Cygwin.cygwinPath(machineFolder) oliver@167: oliver@167: # executes command over ssh on guest vm with X forwarding oliver@167: @staticmethod oliver@167: def sshExecuteX11(command, address, user_name, certificate, wait_return=True): oliver@167: return Cygwin.bashExecute('DISPLAY=:0.0 ssh -Y -o StrictHostKeyChecking=no -i \\\"' + certificate +'\\\" ' + user_name + '@' + address + ' ' + command + '') oliver@167: oliver@167: @staticmethod oliver@167: def is_X11_running(): oliver@167: """check if we can connect to a X11 running instance""" oliver@167: p = Cygwin.bashExecute('xset -display :0 q', wait_return = True, window = False) oliver@167: return p[0] == 0 oliver@167: oliver@167: @staticmethod oliver@167: def start_X11(): oliver@167: """start X11 in the background (if not already running) on DISPLAY=:0 oliver@167: oliver@167: If there is already a X11 running then exit silently, calling this oliver@167: method as often as needed. oliver@167: """ oliver@167: Popen('"' + Cygwin.cygwin_x11 + '" :0 -multiwindow -resize -silent-dup-error') oliver@167: return (0, None, None) oliver@167: oliver@167: @staticmethod oliver@167: def cygPath(path): oliver@167: cmd = 'cygpath -u \'' + path + '\'' oliver@167: return Cygwin.bashExecute(cmd)[1].rstrip('\n') oliver@167: oliver@167: # start oliver@167: import os oliver@167: import win32api oliver@167: import win32con oliver@167: import win32security oliver@167: oliver@167: if __name__ == "__main__": oliver@167: logger = setupLogger('Cygwin') oliver@167: c = Cygwin() BarthaM@212: logger.info(c.root()) BarthaM@212: logger.info(c.bin()) BarthaM@212: logger.info(c.bash()) BarthaM@212: logger.info(c.ssh()) BarthaM@212: logger.info(c.x11()) BarthaM@212: logger.info(c.home()) oliver@167: oliver@167: #PSEXEC -i -s -d CMD oliver@167: #tasklist /v /fo list /fi "IMAGENAME eq explorer.exe" oliver@167: oliver@167: #runner = XRunner() oliver@167: #runner.start() oliver@167: oliver@167: #Cygwin.start_X11() oliver@167: oliver@167: #time.sleep(500) oliver@167: oliver@167: #Cygwin.start_X11() oliver@167: #print (Cygwin.is_X11_running()) oliver@167: #print (Cygwin.is_X11_running()) oliver@167: #new_sdvm = 'SecurityDVM0' oliver@167: #new_ip = Cygwin.vboxExecute('guestproperty get ' + new_sdvm + ' /VirtualBox/GuestInfo/Net/0/V4/IP')[1] oliver@167: #new_ip = new_ip[new_ip.index(':')+1:].strip() oliver@167: #new_ip = '+' oliver@167: #result = Cygwin.bashExecute('DISPLAY=:0.0 xhost '+new_ip) oliver@167: #browser = '/usr/bin/midori ' oliver@167: #print(Cygwin.sshExecuteX11(browser, new_ip, 'osecuser', '/cygdrive/c/Users/BarthaM/VirtualBox VMs' + '/' + new_sdvm + '/dvm_key')) oliver@167: oliver@167: #print(Cygwin.bashExecute('echo $PATH')[1]) oliver@167: #print(Cygwin.cygPath('C:')) oliver@167: #print('C:\\Program Files\\OpenSecurity: ' + c.cygPath('C:\\Program Files\\OpenSecurity')) oliver@167: oliver@167: sys.exit(0) oliver@167: