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
oliver@167
     1
#!/bin/env python
oliver@167
     2
# -*- coding: utf-8 -*-
oliver@167
     3
oliver@167
     4
# ------------------------------------------------------------
oliver@167
     5
# cygwin command
oliver@167
     6
# 
oliver@167
     7
# executes a cygwin command inside the opensecurity project
oliver@167
     8
#
oliver@167
     9
# Autor: Mihai Bartha, <mihai.bartha@ait.ac.at>
oliver@167
    10
#        Oliver Maurhart, <oliver.maurhart@ait.ac.at>
oliver@167
    11
#
oliver@240
    12
# Copyright 2013-2014 X-Net and AIT Austrian Institute of Technology
oliver@167
    13
# 
oliver@167
    14
# 
oliver@240
    15
#     X-Net Services GmbH
oliver@240
    16
#     Elisabethstrasse 1
oliver@240
    17
#     4020 Linz
oliver@240
    18
#     AUSTRIA
oliver@240
    19
#     https://www.x-net.at
oliver@240
    20
# 
oliver@240
    21
#     AIT Austrian Institute of Technology
oliver@240
    22
#     Donau City Strasse 1
oliver@240
    23
#     1220 Wien
oliver@240
    24
#     AUSTRIA
oliver@240
    25
#     http://www.ait.ac.at
oliver@240
    26
# 
oliver@240
    27
# 
oliver@240
    28
# Licensed under the Apache License, Version 2.0 (the "License");
oliver@240
    29
# you may not use this file except in compliance with the License.
oliver@240
    30
# You may obtain a copy of the License at
oliver@240
    31
# 
oliver@240
    32
#    http://www.apache.org/licenses/LICENSE-2.0
oliver@240
    33
# 
oliver@240
    34
# Unless required by applicable law or agreed to in writing, software
oliver@240
    35
# distributed under the License is distributed on an "AS IS" BASIS,
oliver@240
    36
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
oliver@240
    37
# See the License for the specific language governing permissions and
oliver@240
    38
# limitations under the License.
oliver@167
    39
# ------------------------------------------------------------
oliver@167
    40
oliver@167
    41
oliver@167
    42
# ------------------------------------------------------------
oliver@167
    43
# imports
oliver@167
    44
oliver@167
    45
import os
oliver@167
    46
import subprocess
oliver@167
    47
import sys
oliver@167
    48
import _winreg
oliver@167
    49
from subprocess import Popen, PIPE, STARTUPINFO, _subprocess
oliver@167
    50
import threading
oliver@167
    51
oliver@167
    52
# local
oliver@167
    53
from environment import Environment
oliver@167
    54
from opensecurity_util import logger, setupLogger, OpenSecurityException
oliver@167
    55
import time
oliver@167
    56
oliver@167
    57
oliver@167
    58
# ------------------------------------------------------------
oliver@167
    59
# code
oliver@167
    60
oliver@167
    61
def once(theClass):
oliver@167
    62
    """get the path to our local cygwin installment"""
oliver@167
    63
    home_drive = os.path.expandvars("%HOMEDRIVE%") + os.sep
BarthaM@212
    64
    e = Environment('OpenSecurity')
oliver@167
    65
    path_hint = [ 
BarthaM@212
    66
        os.path.abspath(os.path.join(e.prefix_path, 'cygwin')), 
BarthaM@212
    67
        os.path.abspath(os.path.join(e.prefix_path, 'cygwin64')), 
oliver@167
    68
        os.path.abspath(os.path.join(home_drive, 'cygwin')),
oliver@167
    69
        os.path.abspath(os.path.join(home_drive, 'cygwin64'))
oliver@167
    70
    ]
oliver@167
    71
    path_valid = [ p for p in path_hint if os.path.exists(p) ]
oliver@167
    72
    theClass.cygwin_root = path_valid[0]
oliver@167
    73
    theClass.cygwin_bin = os.path.join(theClass.cygwin_root, 'bin') + os.path.sep
oliver@167
    74
    theClass.cygwin_bash = os.path.join(theClass.cygwin_bin, 'bash.exe')
oliver@167
    75
    theClass.cygwin_ssh = os.path.join(theClass.cygwin_bin, 'ssh.exe')
oliver@167
    76
    theClass.cygwin_scp = os.path.join(theClass.cygwin_bin, 'scp.exe')
mihai@252
    77
    theClass.cygwin_rsync = os.path.join(theClass.cygwin_bin, 'rsync.exe')
oliver@167
    78
    theClass.cygwin_x11 = os.path.join(theClass.cygwin_bin, 'XWin.exe')
oliver@167
    79
    theClass.win_cmd = os.environ.get("COMSPEC", "cmd.exe") 
oliver@167
    80
    """get the path to the VirtualBox installation on this system"""
oliver@167
    81
    theClass.vbox_root = theClass.getRegEntry('SOFTWARE\Oracle\VirtualBox', 'InstallDir')[0]  
oliver@167
    82
    theClass.vbox_man = os.path.join(theClass.vbox_root, 'VBoxManage.exe')
oliver@167
    83
    #theClass.user_home = os.path.expanduser("~")
oliver@167
    84
    theClass.user_home = os.environ['APPDATA']#os.path.expandvars("%APPDATA%")
BarthaM@219
    85
    theClass.allow_exec = True 
oliver@167
    86
    return theClass
oliver@167
    87
oliver@167
    88
            
oliver@167
    89
@once
oliver@167
    90
class Cygwin(object):
oliver@167
    91
    cygwin_root = ''
oliver@167
    92
    cygwin_bin = ''
oliver@167
    93
    cygwin_bash = ''
oliver@167
    94
    cygwin_ssh = ''
oliver@167
    95
    cygwin_x11 = ''
oliver@167
    96
    cygwin_scp = ''
mihai@252
    97
    cygwin_rsync = ''
oliver@167
    98
    vbox_root = ''
oliver@167
    99
    vbox_man = ''
oliver@167
   100
    win_cmd = ''
oliver@167
   101
    user_home = ''
BarthaM@219
   102
    allow_exec = True 
oliver@167
   103
    """Some nifty methods working with Cygwin"""
oliver@167
   104
    
oliver@167
   105
    def __call__(self, command, arguments, wait_return=True, window = False):
oliver@167
   106
        """make an instance of this object act as a function"""
oliver@167
   107
        return self.execute(command, arguments, wait_return, window)
oliver@167
   108
oliver@167
   109
    @staticmethod
oliver@167
   110
    def getRegEntry(key, value):
oliver@167
   111
        try:
oliver@167
   112
            k = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, key)
oliver@167
   113
            value = _winreg.QueryValueEx(k, value)
oliver@167
   114
            _winreg.CloseKey(k)
oliver@167
   115
            return value
oliver@167
   116
        except:
oliver@167
   117
            pass
oliver@167
   118
    
oliver@167
   119
            
oliver@167
   120
    @staticmethod
oliver@167
   121
    def root():
oliver@167
   122
        return Cygwin.cygwin_root
oliver@167
   123
oliver@167
   124
    @staticmethod
oliver@167
   125
    def bin():
oliver@167
   126
        return Cygwin.cygwin_bin
oliver@167
   127
    
oliver@167
   128
    @staticmethod
oliver@167
   129
    def bash():
oliver@167
   130
        return Cygwin.cygwin_bash
oliver@167
   131
    
oliver@167
   132
    @staticmethod    
oliver@167
   133
    def ssh():
oliver@167
   134
        return Cygwin.cygwin_ssh
oliver@167
   135
    
oliver@167
   136
    @staticmethod    
oliver@167
   137
    def scp():
oliver@167
   138
        return Cygwin.cygwin_scp
mihai@252
   139
    
mihai@252
   140
    @staticmethod    
mihai@252
   141
    def rsync():
mihai@252
   142
        return Cygwin.cygwin_rsync
oliver@167
   143
oliver@167
   144
    @staticmethod    
oliver@167
   145
    def x11():
oliver@167
   146
        return Cygwin.cygwin_x11
oliver@167
   147
    
oliver@167
   148
    @staticmethod
oliver@167
   149
    def vboxman():
oliver@167
   150
        return Cygwin.vbox_man
oliver@167
   151
    
oliver@167
   152
    @staticmethod
oliver@167
   153
    def cmd():
oliver@167
   154
        return Cygwin.win_cmd
oliver@167
   155
    
oliver@167
   156
    @staticmethod
oliver@167
   157
    def home():
oliver@167
   158
        return Cygwin.user_home
oliver@167
   159
    
BarthaM@219
   160
    @staticmethod
BarthaM@219
   161
    def allowExec():
BarthaM@219
   162
        Cygwin.allow_exec = True
BarthaM@219
   163
    
BarthaM@219
   164
    @staticmethod
BarthaM@219
   165
    def denyExec():
BarthaM@219
   166
        Cygwin.allow_exec = False
BarthaM@219
   167
    
oliver@167
   168
    executeLock = threading.Lock()
oliver@167
   169
    #executes command on host system
oliver@167
   170
    @staticmethod
oliver@167
   171
    def execute(program, arguments, wait_return=True, window = False, stdin = PIPE, stdout = PIPE, stderr = PIPE):
BarthaM@219
   172
        if not Cygwin.allow_exec:
BarthaM@219
   173
            logger.error('Execution cancelled by system (shutting down).')
BarthaM@219
   174
            raise OpenSecurityException('Execution cancelled by system (shutting down).')
BarthaM@219
   175
            
oliver@167
   176
        _startupinfo = STARTUPINFO()
oliver@167
   177
        if not window:
oliver@167
   178
            _startupinfo.dwFlags |= _subprocess.STARTF_USESHOWWINDOW
oliver@167
   179
            _startupinfo.wShowWindow = _subprocess.SW_HIDE
oliver@167
   180
            #logger.debug('trying to launch: ' + program + ' ' + ''.join(arguments))
oliver@167
   181
        
BarthaM@212
   182
        result, res_stdout, res_stderr = None, None, None
oliver@167
   183
        try:
oliver@167
   184
            # quote the executable otherwise we run into troubles
BarthaM@218
   185
            # when the path contains spaces and additional arguments
oliver@167
   186
            # are presented as well.
oliver@167
   187
            # special: invoking bash as login shell here with
oliver@167
   188
            # an unquoted command does not execute /etc/profile
oliver@167
   189
            args = '"' + program + '" ' + arguments
oliver@169
   190
            logger.debug('Launching: ' + program + ' ' + ''.join(arguments))
oliver@167
   191
            process = Popen(args, startupinfo = _startupinfo, stdin = stdin, stdout = stdout, stderr = stderr, shell = False)
oliver@167
   192
            if not wait_return:
oliver@167
   193
                return [0, 'working in background', '']
BarthaM@212
   194
            
oliver@167
   195
            res_stdout, res_stderr = process.communicate()
oliver@167
   196
            result = process.returncode
oliver@169
   197
            logger.debug('Finished: ' + program + ' ' + ''.join(arguments))
oliver@167
   198
oliver@167
   199
        except Exception as ex:
oliver@167
   200
            res_stderr = ''.join(str(ex.args))
oliver@167
   201
            result = 1 
BarthaM@218
   202
    
BarthaM@218
   203
        if result != 0:
BarthaM@218
   204
            logger.error('Command failed:' + ''.join(res_stderr))
BarthaM@218
   205
            raise OpenSecurityException('Command failed:' + ''.join(res_stderr))
BarthaM@218
   206
        
oliver@167
   207
        return result, res_stdout, res_stderr
oliver@167
   208
    
oliver@167
   209
    @staticmethod
BarthaM@212
   210
    def vboxExecute(command, wait_return=True, window = False, bash_opts='', try_count = 3):
oliver@167
   211
        retry = 0
oliver@167
   212
        result = None
BarthaM@212
   213
        while retry < try_count:
oliver@167
   214
            if Cygwin.executeLock.acquire(True):
BarthaM@218
   215
                try:
BarthaM@218
   216
                    result = Cygwin.execute(Cygwin.vbox_man, command, wait_return, window)
BarthaM@218
   217
                except Exception as ex:
BarthaM@218
   218
                    Cygwin.executeLock.release()
BarthaM@218
   219
                    if (retry+1) == try_count:
BarthaM@218
   220
                        raise ex
BarthaM@218
   221
                else:
BarthaM@218
   222
                    Cygwin.executeLock.release()
oliver@167
   223
                    return result
BarthaM@218
   224
            retry+=1
BarthaM@218
   225
        raise OpenSecurityException('Command max retry reached: ' + ''.join(command))
oliver@167
   226
oliver@167
   227
oliver@167
   228
    @staticmethod
oliver@167
   229
    def bashExecute(command, wait_return=True, window = False, bash_opts='', stdin = PIPE, stdout = PIPE, stderr = PIPE):
oliver@167
   230
        # for some reason, the '-l' is ignored when started via python
oliver@167
   231
        # so the same behavior is triggered by calling /etc/profile 
oliver@167
   232
        # directly
oliver@167
   233
        command = bash_opts + ' -l -c "'  + command + '"'
oliver@167
   234
        return Cygwin.execute(Cygwin.cygwin_bash, command, wait_return, window, stdin = stdin, stdout = stdout, stderr = stderr)
oliver@167
   235
    
oliver@167
   236
    @staticmethod
oliver@167
   237
    def cmdExecute(command, wait_return=True, window = False):
oliver@167
   238
        command = ' /c ' + command 
oliver@167
   239
        return Cygwin.execute(Cygwin.win_cmd, command, wait_return, window)
oliver@167
   240
oliver@167
   241
    # executes command over ssh on guest vm
oliver@167
   242
    @staticmethod
oliver@167
   243
    def sshExecute(command, address, user_name, certificate, wait_return=True, window = False):
BarthaM@218
   244
        if command == None or address == None or user_name == None or certificate == None:
BarthaM@218
   245
            raise OpenSecurityException('Invalid parameter value')
oliver@167
   246
        command = ' -v -o StrictHostKeyChecking=no -i "' + certificate + '" ' + user_name + '@' + address + ' ' + command        
oliver@167
   247
        return Cygwin.execute(Cygwin.cygwin_ssh, command, wait_return, window)
BarthaM@212
   248
BarthaM@212
   249
    # executes command over ssh on guest vm
oliver@167
   250
    @staticmethod
oliver@167
   251
    def sshBackgroundExecute(command, address, user_name, certificate, wait_return=True, window = False):
oliver@167
   252
        command = ' -f -v -o StrictHostKeyChecking=no -i "' + certificate + '" ' + user_name + '@' + address + ' ' + command        
oliver@167
   253
        return Cygwin.execute(Cygwin.cygwin_ssh, command, wait_return, window)
oliver@167
   254
    
oliver@167
   255
    #machineFolder + '/' + vm_name + '/dvm_key
oliver@167
   256
    #address = self.getHostOnlyIP(vm_name)
oliver@167
   257
    #machineFolder = self.getDefaultMachineFolder()
oliver@167
   258
    #machineFolder = Cygwin.cygwinPath(machineFolder)
oliver@167
   259
    
oliver@167
   260
    # executes command over ssh on guest vm with X forwarding
oliver@167
   261
    @staticmethod
oliver@167
   262
    def sshExecuteX11(command, address, user_name, certificate, wait_return=True):
oliver@167
   263
        return Cygwin.bashExecute('DISPLAY=:0.0 ssh -Y -o StrictHostKeyChecking=no -i \\\"' + certificate +'\\\" ' + user_name + '@' + address + ' ' + command + '')
oliver@167
   264
oliver@167
   265
    @staticmethod
oliver@167
   266
    def is_X11_running():
oliver@167
   267
        """check if we can connect to a X11 running instance"""
oliver@167
   268
        p = Cygwin.bashExecute('xset -display :0 q', wait_return = True, window = False) 
oliver@167
   269
        return p[0] == 0
oliver@167
   270
        
oliver@167
   271
    @staticmethod
oliver@167
   272
    def start_X11():
oliver@167
   273
        """start X11 in the background (if not already running) on DISPLAY=:0
oliver@167
   274
        
oliver@167
   275
        If there is already a X11 running then exit silently, calling this
oliver@167
   276
        method as often as needed.
oliver@167
   277
        """
oliver@167
   278
        Popen('"' + Cygwin.cygwin_x11 + '" :0 -multiwindow -resize -silent-dup-error')
oliver@167
   279
        return (0, None, None)
oliver@167
   280
    
oliver@167
   281
    @staticmethod    
oliver@167
   282
    def cygPath(path):
oliver@167
   283
        cmd = 'cygpath -u \'' + path + '\''
oliver@167
   284
        return Cygwin.bashExecute(cmd)[1].rstrip('\n')
oliver@167
   285
    
oliver@167
   286
# start
oliver@167
   287
import os
oliver@167
   288
import win32api
oliver@167
   289
import win32con
oliver@167
   290
import win32security
oliver@167
   291
oliver@167
   292
if __name__ == "__main__":
oliver@167
   293
    logger = setupLogger('Cygwin')
oliver@167
   294
    c = Cygwin()
BarthaM@212
   295
    logger.info(c.root())
BarthaM@212
   296
    logger.info(c.bin())
BarthaM@212
   297
    logger.info(c.bash())
BarthaM@212
   298
    logger.info(c.ssh())
BarthaM@212
   299
    logger.info(c.x11())
BarthaM@212
   300
    logger.info(c.home())   
oliver@167
   301
    
oliver@167
   302
    #PSEXEC -i -s -d CMD
oliver@167
   303
    #tasklist /v /fo list /fi "IMAGENAME eq explorer.exe"
oliver@167
   304
    
oliver@167
   305
    #runner = XRunner()
oliver@167
   306
    #runner.start()
oliver@167
   307
    
oliver@167
   308
    #Cygwin.start_X11()
oliver@167
   309
            
oliver@167
   310
    #time.sleep(500)
oliver@167
   311
    
oliver@167
   312
    #Cygwin.start_X11()
oliver@167
   313
    #print (Cygwin.is_X11_running())
oliver@167
   314
    #print (Cygwin.is_X11_running())
oliver@167
   315
    #new_sdvm = 'SecurityDVM0'
oliver@167
   316
    #new_ip = Cygwin.vboxExecute('guestproperty get ' + new_sdvm + ' /VirtualBox/GuestInfo/Net/0/V4/IP')[1]
oliver@167
   317
    #new_ip = new_ip[new_ip.index(':')+1:].strip()
oliver@167
   318
    #new_ip = '+'
oliver@167
   319
    #result = Cygwin.bashExecute('DISPLAY=:0.0 xhost '+new_ip)
oliver@167
   320
    #browser = '/usr/bin/midori '
oliver@167
   321
    #print(Cygwin.sshExecuteX11(browser, new_ip, 'osecuser', '/cygdrive/c/Users/BarthaM/VirtualBox VMs' + '/' + new_sdvm + '/dvm_key'))
oliver@167
   322
            
oliver@167
   323
    #print(Cygwin.bashExecute('echo $PATH')[1])
oliver@167
   324
    #print(Cygwin.cygPath('C:'))
oliver@167
   325
    #print('C:\\Program Files\\OpenSecurity: ' + c.cygPath('C:\\Program Files\\OpenSecurity'))
oliver@167
   326
    
oliver@167
   327
    sys.exit(0)
oliver@167
   328