OpenSecurity/bin/cygwin.py
author Bartha Mihai <mihai.bartha@ait.ac.at>
Tue, 13 Jan 2015 18:26:41 +0100
changeset 252 824ae4324f57
parent 240 d7ef04254e9c
permissions -rwxr-xr-x
changed settings restore functionality for the browser.
Needs addition of rsync on VM and setup
     1 #!/bin/env python
     2 # -*- coding: utf-8 -*-
     3 
     4 # ------------------------------------------------------------
     5 # cygwin command
     6 # 
     7 # executes a cygwin command inside the opensecurity project
     8 #
     9 # Autor: Mihai Bartha, <mihai.bartha@ait.ac.at>
    10 #        Oliver Maurhart, <oliver.maurhart@ait.ac.at>
    11 #
    12 # Copyright 2013-2014 X-Net and AIT Austrian Institute of Technology
    13 # 
    14 # 
    15 #     X-Net Services GmbH
    16 #     Elisabethstrasse 1
    17 #     4020 Linz
    18 #     AUSTRIA
    19 #     https://www.x-net.at
    20 # 
    21 #     AIT Austrian Institute of Technology
    22 #     Donau City Strasse 1
    23 #     1220 Wien
    24 #     AUSTRIA
    25 #     http://www.ait.ac.at
    26 # 
    27 # 
    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
    31 # 
    32 #    http://www.apache.org/licenses/LICENSE-2.0
    33 # 
    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 # ------------------------------------------------------------
    40 
    41 
    42 # ------------------------------------------------------------
    43 # imports
    44 
    45 import os
    46 import subprocess
    47 import sys
    48 import _winreg
    49 from subprocess import Popen, PIPE, STARTUPINFO, _subprocess
    50 import threading
    51 
    52 # local
    53 from environment import Environment
    54 from opensecurity_util import logger, setupLogger, OpenSecurityException
    55 import time
    56 
    57 
    58 # ------------------------------------------------------------
    59 # code
    60 
    61 def once(theClass):
    62     """get the path to our local cygwin installment"""
    63     home_drive = os.path.expandvars("%HOMEDRIVE%") + os.sep
    64     e = Environment('OpenSecurity')
    65     path_hint = [ 
    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'))
    70     ]
    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 
    86     return theClass
    87 
    88             
    89 @once
    90 class Cygwin(object):
    91     cygwin_root = ''
    92     cygwin_bin = ''
    93     cygwin_bash = ''
    94     cygwin_ssh = ''
    95     cygwin_x11 = ''
    96     cygwin_scp = ''
    97     cygwin_rsync = ''
    98     vbox_root = ''
    99     vbox_man = ''
   100     win_cmd = ''
   101     user_home = ''
   102     allow_exec = True 
   103     """Some nifty methods working with Cygwin"""
   104     
   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)
   108 
   109     @staticmethod
   110     def getRegEntry(key, value):
   111         try:
   112             k = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, key)
   113             value = _winreg.QueryValueEx(k, value)
   114             _winreg.CloseKey(k)
   115             return value
   116         except:
   117             pass
   118     
   119             
   120     @staticmethod
   121     def root():
   122         return Cygwin.cygwin_root
   123 
   124     @staticmethod
   125     def bin():
   126         return Cygwin.cygwin_bin
   127     
   128     @staticmethod
   129     def bash():
   130         return Cygwin.cygwin_bash
   131     
   132     @staticmethod    
   133     def ssh():
   134         return Cygwin.cygwin_ssh
   135     
   136     @staticmethod    
   137     def scp():
   138         return Cygwin.cygwin_scp
   139     
   140     @staticmethod    
   141     def rsync():
   142         return Cygwin.cygwin_rsync
   143 
   144     @staticmethod    
   145     def x11():
   146         return Cygwin.cygwin_x11
   147     
   148     @staticmethod
   149     def vboxman():
   150         return Cygwin.vbox_man
   151     
   152     @staticmethod
   153     def cmd():
   154         return Cygwin.win_cmd
   155     
   156     @staticmethod
   157     def home():
   158         return Cygwin.user_home
   159     
   160     @staticmethod
   161     def allowExec():
   162         Cygwin.allow_exec = True
   163     
   164     @staticmethod
   165     def denyExec():
   166         Cygwin.allow_exec = False
   167     
   168     executeLock = threading.Lock()
   169     #executes command on host system
   170     @staticmethod
   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).')
   175             
   176         _startupinfo = STARTUPINFO()
   177         if not window:
   178             _startupinfo.dwFlags |= _subprocess.STARTF_USESHOWWINDOW
   179             _startupinfo.wShowWindow = _subprocess.SW_HIDE
   180             #logger.debug('trying to launch: ' + program + ' ' + ''.join(arguments))
   181         
   182         result, res_stdout, res_stderr = None, None, None
   183         try:
   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)
   192             if not wait_return:
   193                 return [0, 'working in background', '']
   194             
   195             res_stdout, res_stderr = process.communicate()
   196             result = process.returncode
   197             logger.debug('Finished: ' + program + ' ' + ''.join(arguments))
   198 
   199         except Exception as ex:
   200             res_stderr = ''.join(str(ex.args))
   201             result = 1 
   202     
   203         if result != 0:
   204             logger.error('Command failed:' + ''.join(res_stderr))
   205             raise OpenSecurityException('Command failed:' + ''.join(res_stderr))
   206         
   207         return result, res_stdout, res_stderr
   208     
   209     @staticmethod
   210     def vboxExecute(command, wait_return=True, window = False, bash_opts='', try_count = 3):
   211         retry = 0
   212         result = None
   213         while retry < try_count:
   214             if Cygwin.executeLock.acquire(True):
   215                 try:
   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:
   220                         raise ex
   221                 else:
   222                     Cygwin.executeLock.release()
   223                     return result
   224             retry+=1
   225         raise OpenSecurityException('Command max retry reached: ' + ''.join(command))
   226 
   227 
   228     @staticmethod
   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 
   232         # directly
   233         command = bash_opts + ' -l -c "'  + command + '"'
   234         return Cygwin.execute(Cygwin.cygwin_bash, command, wait_return, window, stdin = stdin, stdout = stdout, stderr = stderr)
   235     
   236     @staticmethod
   237     def cmdExecute(command, wait_return=True, window = False):
   238         command = ' /c ' + command 
   239         return Cygwin.execute(Cygwin.win_cmd, command, wait_return, window)
   240 
   241     # executes command over ssh on guest vm
   242     @staticmethod
   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)
   248 
   249     # executes command over ssh on guest vm
   250     @staticmethod
   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)
   254     
   255     #machineFolder + '/' + vm_name + '/dvm_key
   256     #address = self.getHostOnlyIP(vm_name)
   257     #machineFolder = self.getDefaultMachineFolder()
   258     #machineFolder = Cygwin.cygwinPath(machineFolder)
   259     
   260     # executes command over ssh on guest vm with X forwarding
   261     @staticmethod
   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 + '')
   264 
   265     @staticmethod
   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) 
   269         return p[0] == 0
   270         
   271     @staticmethod
   272     def start_X11():
   273         """start X11 in the background (if not already running) on DISPLAY=:0
   274         
   275         If there is already a X11 running then exit silently, calling this
   276         method as often as needed.
   277         """
   278         Popen('"' + Cygwin.cygwin_x11 + '" :0 -multiwindow -resize -silent-dup-error')
   279         return (0, None, None)
   280     
   281     @staticmethod    
   282     def cygPath(path):
   283         cmd = 'cygpath -u \'' + path + '\''
   284         return Cygwin.bashExecute(cmd)[1].rstrip('\n')
   285     
   286 # start
   287 import os
   288 import win32api
   289 import win32con
   290 import win32security
   291 
   292 if __name__ == "__main__":
   293     logger = setupLogger('Cygwin')
   294     c = Cygwin()
   295     logger.info(c.root())
   296     logger.info(c.bin())
   297     logger.info(c.bash())
   298     logger.info(c.ssh())
   299     logger.info(c.x11())
   300     logger.info(c.home())   
   301     
   302     #PSEXEC -i -s -d CMD
   303     #tasklist /v /fo list /fi "IMAGENAME eq explorer.exe"
   304     
   305     #runner = XRunner()
   306     #runner.start()
   307     
   308     #Cygwin.start_X11()
   309             
   310     #time.sleep(500)
   311     
   312     #Cygwin.start_X11()
   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()
   318     #new_ip = '+'
   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'))
   322             
   323     #print(Cygwin.bashExecute('echo $PATH')[1])
   324     #print(Cygwin.cygPath('C:'))
   325     #print('C:\\Program Files\\OpenSecurity: ' + c.cygPath('C:\\Program Files\\OpenSecurity'))
   326     
   327     sys.exit(0)
   328