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