diff --git a/.gitignore b/.gitignore index 166b8f6..b845296 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,11 @@ ogagent_*_all.deb ogagent_*_amd64.buildinfo ogagent_*_amd64.changes ogagent_*_amd64.build +OGAgentSetup-*.exe +bin src/about_dialog_ui.py src/message_dialog_ui.py src/OGAgent_rc.py +src/dist +src/build +windows/VERSION diff --git a/src/OGAgent.spec b/src/OGAgent.spec new file mode 100755 index 0000000..d40bd22 --- /dev/null +++ b/src/OGAgent.spec @@ -0,0 +1,96 @@ +# -*- mode: python ; coding: utf-8 -*- + + +ogausr_a = Analysis( + ['OGAgentUser.py'], + pathex=[], + binaries=[], + datas=[ +# ('cfg', 'cfg'), ## add the entire directory + ], + hiddenimports=['win32timezone', 'socketserver', 'http.server', 'urllib'], + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + noarchive=False, + optimize=0, +) +ogasvc_a = Analysis( + ['opengnsys\\windows\\OGAgentService.py'], + pathex=[], + binaries=[], + datas=[], + hiddenimports=['win32timezone', 'socketserver', 'http.server', 'urllib'], + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + noarchive=False, + optimize=0, +) + +MERGE( + (ogausr_a, 'OGAgentUser', 'OGAgentUser'), ## class, py name, exe name + (ogasvc_a, 'OGAgentService', 'OGAgentService') +) + +ogausr_pyz = PYZ(ogausr_a.pure) +ogasvc_pyz = PYZ(ogasvc_a.pure) + +ogausr_exe = EXE( + ogausr_pyz, + ogausr_a.scripts, + [], + exclude_binaries=True, + name='OGAgentUser', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + console=False, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch=None, + codesign_identity=None, + entitlements_file=None, + icon=['img\\oga.ico'], +) +ogasvc_exe = EXE( + ogasvc_pyz, + ogasvc_a.scripts, + [], + exclude_binaries=True, + name='OGAgentService', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + console=True, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch=None, + codesign_identity=None, + entitlements_file=None, + icon=['img\\oga.ico'], + manifest='OGAgent.manifest', +) + +dist_name = 'OGAgent' +coll = COLLECT( + ogausr_exe, + ogausr_a.binaries, + ogausr_a.datas, + + ogasvc_exe, + ogasvc_a.binaries, + ogasvc_a.datas, + + strip=False, + upx=True, + upx_exclude=[], + name=dist_name, +) + +import shutil +shutil.copytree ('cfg', '{}/{}/cfg'.format(DISTPATH, dist_name)) diff --git a/src/opengnsys/config.py b/src/opengnsys/config.py index 7ffe046..4228b39 100644 --- a/src/opengnsys/config.py +++ b/src/opengnsys/config.py @@ -32,7 +32,7 @@ # pylint: disable=unused-wildcard-import, wildcard-import -from configparser import SafeConfigParser +from configparser import ConfigParser config = None @@ -45,7 +45,7 @@ def readConfig(client=False): This is this way so we can protect ogagent.cfg against reading for non admin users on all platforms. """ - cfg = SafeConfigParser() + cfg = ConfigParser() if client is True: fname = 'ogclient.cfg' else: diff --git a/src/opengnsys/httpserver.py b/src/opengnsys/httpserver.py index 69c4317..dd55507 100644 --- a/src/opengnsys/httpserver.py +++ b/src/opengnsys/httpserver.py @@ -57,7 +57,8 @@ class HTTPServerHandler(BaseHTTPRequestHandler): return def sendJsonResponse(self, data): - self.send_response(200) + try: self.send_response(200) + except Exception as e: logger.warn (str(e)) data = json.dumps(data) self.send_header('Content-type', 'application/json') self.send_header('Content-Length', str(len(data))) @@ -132,7 +133,9 @@ class HTTPServerThread(threading.Thread): self.certFile = createSelfSignedCert() self.server = HTTPThreadingServer(address, HTTPServerHandler) - self.server.socket = ssl.wrap_socket(self.server.socket, certfile=self.certFile, server_side=True) + context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + context.load_cert_chain(certfile=self.certFile) + self.server.socket = context.wrap_socket(self.server.socket, server_side=True) logger.debug('Initialized HTTPS Server thread on {}'.format(address)) diff --git a/src/opengnsys/modules/server/OpenGnSys/__init__.py b/src/opengnsys/modules/server/OpenGnSys/__init__.py index 73182b6..15e5344 100644 --- a/src/opengnsys/modules/server/OpenGnSys/__init__.py +++ b/src/opengnsys/modules/server/OpenGnSys/__init__.py @@ -65,7 +65,7 @@ def check_secret(fnc): else: raise Exception('Unauthorized operation') except Exception as e: - logger.error(e) + logger.error(str(e)) raise Exception(e) return wrapper @@ -83,7 +83,7 @@ def execution_level(level): else: raise Exception('Unauthorized operation') except Exception as e: - logger.error(e) + logger.error(str(e)) raise Exception(e) return wrapper diff --git a/src/opengnsys/utils.py b/src/opengnsys/utils.py index 36bef63..c54b4b7 100644 --- a/src/opengnsys/utils.py +++ b/src/opengnsys/utils.py @@ -61,7 +61,7 @@ def exceptionToMessage(e): if isinstance(arg, Exception): msg = msg + exceptionToMessage(arg) else: - msg = msg + toUnicode(arg) + '. ' + msg = msg + str(arg) + '. ' return msg diff --git a/src/opengnsys/windows/OGAgentService.py b/src/opengnsys/windows/OGAgentService.py index 71716d7..d42c144 100644 --- a/src/opengnsys/windows/OGAgentService.py +++ b/src/opengnsys/windows/OGAgentService.py @@ -120,5 +120,9 @@ class OGAgentSvc(win32serviceutil.ServiceFramework, CommonService): if __name__ == '__main__': - - win32serviceutil.HandleCommandLine(OGAgentSvc) + if len(sys.argv) == 1: + servicemanager.Initialize() + servicemanager.PrepareToHostSingle(OGAgentSvc) + servicemanager.StartServiceCtrlDispatcher() + else: + win32serviceutil.HandleCommandLine(OGAgentSvc) diff --git a/src/opengnsys/windows/log.py b/src/opengnsys/windows/log.py index 745fd03..c37b9e8 100644 --- a/src/opengnsys/windows/log.py +++ b/src/opengnsys/windows/log.py @@ -47,7 +47,7 @@ class LocalLogger(object): logging.basicConfig( filename=os.path.join(tempfile.gettempdir(), 'opengnsys.log'), filemode='a', - format='%(levelname)s %(asctime)s %(message)s', + format='%(levelname)s %(asctime)s (%(threadName)s) %(message)s', level=logging.DEBUG ) self.logger = logging.getLogger('opengnsys') @@ -58,7 +58,7 @@ class LocalLogger(object): # our loglevels are 10000 (other), 20000 (debug), .... # logging levels are 10 (debug), 20 (info) # OTHER = logging.NOTSET - self.logger.log(level / 1000 - 10, message) + self.logger.log(int(level / 1000 - 10), message) if level < INFO or self.serviceLogger is False: # Only information and above will be on event log return diff --git a/src/opengnsys/windows/operations.py b/src/opengnsys/windows/operations.py index 82b6522..c6f0e11 100644 --- a/src/opengnsys/windows/operations.py +++ b/src/opengnsys/windows/operations.py @@ -64,7 +64,7 @@ def getNetworkInfo(): ip: ip of the interface ''' obj = win32com.client.Dispatch("WbemScripting.SWbemLocator") - wmobj = obj.ConnectServer("localhost", "root\cimv2") + wmobj = obj.ConnectServer("localhost", "root\\cimv2") adapters = wmobj.ExecQuery("Select * from Win32_NetworkAdapterConfiguration where IpEnabled=True") try: for obj in adapters: @@ -102,12 +102,12 @@ def getWindowsVersion(): ''' Returns Windows version. ''' - import _winreg - reg = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion') + import winreg + reg = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion') try: - data = '{} {}'.format(_winreg.QueryValueEx(reg, 'ProductName')[0], _winreg.QueryValueEx(reg, 'ReleaseId')[0]) + data = '{} {}'.format(winreg.QueryValueEx(reg, 'ProductName')[0], winreg.QueryValueEx(reg, 'ReleaseId')[0]) except Exception: - data = '{} {}'.format(_winreg.QueryValueEx(reg, 'ProductName')[0], _winreg.QueryValueEx(reg, 'CurrentBuildNumber')[0]) + data = '{} {}'.format(winreg.QueryValueEx(reg, 'ProductName')[0], winreg.QueryValueEx(reg, 'CurrentBuildNumber')[0]) reg.Close() return data diff --git a/src/requirements.txt b/src/requirements.txt index abedc7c..1efaa2f 100644 --- a/src/requirements.txt +++ b/src/requirements.txt @@ -1,3 +1,7 @@ -netifaces +#netifaces <--- este es solo para macos... +pywin32 +pyqt6 requests -urllib3 +six +pycryptodome +pyinstaller diff --git a/src/setup.py b/src/setup.py deleted file mode 100644 index a3b7f43..0000000 --- a/src/setup.py +++ /dev/null @@ -1,139 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (c) 2014 Virtual Cable S.L. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# * Neither the name of Virtual Cable S.L. nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -""" -@author: Adolfo Gómez, dkmaster at dkmon dot com -@author: Ramón M. Gómez, ramongomez at us dot es -""" - -# ModuleFinder can't handle runtime changes to __path__, but win32com uses them -try: - # py2exe 0.6.4 introduced a replacement modulefinder. - # This means we have to add package paths there, not to the built-in - # one. If this new modulefinder gets integrated into Python, then - # we might be able to revert this some day. - # if this doesn't work, try import modulefinder - try: - import py2exe.mf as modulefinder - except ImportError: - import modulefinder - import win32com - import sys - for p in win32com.__path__[1:]: - modulefinder.AddPackagePath("win32com", p) - for extra in ["win32com.shell"]: # ,"win32com.mapi" - __import__(extra) - m = sys.modules[extra] - for p in m.__path__[1:]: - modulefinder.AddPackagePath(extra, p) -except ImportError: - # no build path setup, no worries. - pass - -import os -from distutils.core import setup -import py2exe -import sys - -# update.sh changes this value -VERSION='1.3.0' - -sys.argv.append('py2exe') - - -def get_requests_cert_file(): - """Add Python requests or certifi .pem file for installers.""" - import requests - f = os.path.join(os.path.dirname(requests.__file__), 'cacert.pem') - if not os.path.exists(f): - import certifi - f = os.path.join(os.path.dirname(certifi.__file__), 'cacert.pem') - return f - - -class Target: - - def __init__(self, **kw): - self.__dict__.update(kw) - # for the versioninfo resources - self.version = VERSION - self.name = 'OGAgentService' - self.description = 'OpenGnsys Agent Service' - self.author = 'Adolfo Gomez' - self.url = 'https://opengnsys.es/' - self.company_name = "OpenGnsys Project" - self.copyright = "(c) 2014 VirtualCable S.L.U." - self.name = "OpenGnsys Agent" - -# Now you need to pass arguments to setup -# windows is a list of scripts that have their own UI and -# thus don't need to run in a console. - - -ogaservice = Target( - description='OpenGnsys Agent Service', - modules=['opengnsys.windows.OGAgentService'], - icon_resources=[(0, 'img\\oga.ico'), (1, 'img\\oga.ico')], - cmdline_style='pywin32' -) - -# Some test_modules are hidden to py2exe by six, we ensure that they appear on "includes" -HIDDEN_BY_SIX = ['SocketServer', 'SimpleHTTPServer', 'urllib'] - -setup( - windows=[ - { - 'script': 'OGAgentUser-qt4.py', - 'icon_resources': [(0, 'img\\oga.ico'), (1, 'img\\oga.ico')] - }, - ], - console=[ - { - 'script': 'OGAServiceHelper.py' - } - ], - service=[ogaservice], - data_files=[('', [get_requests_cert_file()]), ('cfg', ['cfg/ogagent.cfg', 'cfg/ogclient.cfg'])], - options={ - 'py2exe': { - 'bundle_files': 3, - 'compressed': True, - 'optimize': 2, - 'includes': ['sip', 'PyQt4', 'win32com.shell', 'requests', 'encodings', 'encodings.utf_8'] + HIDDEN_BY_SIX, - 'excludes': ['doctest', 'unittest'], - 'dll_excludes': ['msvcp90.dll'], - 'dist_dir': '..\\bin', - } - }, - name='OpenGnsys Agent', - version=VERSION, - description='OpenGnsys Agent', - author='Adolfo Gomez', - author_email='agomez@virtualcable.es', - zipfile='OGAgent.zip', -) diff --git a/src/update.sh b/src/update.sh index 3f39fed..ebe4791 100755 --- a/src/update.sh +++ b/src/update.sh @@ -32,7 +32,6 @@ function update_version { if [[ -r VERSION ]]; then V="$(cat VERSION)" sed -i "s/Version [^<]*/Version $V/" about-dialog.ui - sed -i "s/^VERSION='.*'$/VERSION='$V'/" setup.py sed -i "s/^VERSION='.*'$/VERSION='$V'/" opengnsys/__init__.py else echo 'src/VERSION: No such file or directory' diff --git a/windows/ogagent.nsi b/windows/ogagent.nsi index a08dbbc..f07b02d 100644 --- a/windows/ogagent.nsi +++ b/windows/ogagent.nsi @@ -88,8 +88,8 @@ Section -Main SEC0000 SetShellVarContext all SetOutPath $INSTDIR SetOverwrite on - File /r bin\*.* - File vcredist_x86.exe + File /r src\dist\OGAgent\*.* + File windows\setup\VC_redist.x64.exe File src\VERSION WriteRegStr HKLM "${REGKEY}\Components" Main 1 SectionEnd @@ -111,7 +111,7 @@ Section -post SEC0001 WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Run" OGAgentTool $INSTDIR\OGAgentUser.exe WriteRegDWORD HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" NoModify 1 WriteRegDWORD HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" NoRepair 1 - ExecWait '"$INSTDIR\vcredist_x86.exe" /passive /norestart' + ExecWait '"$INSTDIR\VC_redist.x64.exe" /passive /norestart' # Add the application to the firewall exception list - All Networks - All IP Version - Enabled # SimpleFC::AddApplication "OpenGnsys Agent Service" "$INSTDIR\OGAgentService.exe" 0 2 "" 1 # SimpleFC::AdvAddRule [name] [description] [protocol] [direction] @@ -128,8 +128,6 @@ Section -post SEC0001 WriteRegDWORD HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Power" HiberbootEnabled 0 # Install service nsExec::Exec /OEM "$INSTDIR\OGAgentService.exe --startup auto install" # Add service after installation - # Update recovery options - nsExec::Exec /OEM "$INSTDIR\OGAServiceHelper.exe" Exec "net start ogagent" Exec "$INSTDIR\OGAgentUser.exe" SectionEnd diff --git a/windows/py2exe-wine-linux.sh b/windows/py2exe-wine-linux.sh deleted file mode 100755 index 68229b0..0000000 --- a/windows/py2exe-wine-linux.sh +++ /dev/null @@ -1,67 +0,0 @@ -#!/bin/sh - -# We need: -# * Wine (32 bit) -# * winetricks (in some distributions) - -export WINEARCH=win32 WINEPREFIX=$PWD/wine WINEDEBUG=fixme-all -WINE=wine - -download() { - mkdir downloads - # Get needed software - cd downloads - wget -nd https://www.python.org/ftp/python/2.7.17/python-2.7.17.msi -O python-2.7.msi - wget -nd https://download.microsoft.com/download/7/9/6/796EF2E4-801B-4FC4-AB28-B59FBF6D907B/VCForPython27.msi - wget -nd https://bootstrap.pypa.io/get-pip.py - wget -nd https://sourceforge.net/projects/pyqt/files/PyQt4/PyQt-4.11.4/PyQt4-4.11.4-gpl-Py2.7-Qt4.8.7-x32.exe/download -O pyqt-install.exe - wget -nd https://prdownloads.sourceforge.net/nsis/nsis-3.05-setup.exe?download -O nsis-install.exe - wget -nd http://nsis.sourceforge.net/mediawiki/images/d/d7/NSIS_Simple_Firewall_Plugin_1.20.zip - cd .. -} - -install_python() { - if which winetricks &>/dev/null; then - echo "Setting up wine prefix (using winetricks)" - winetricks - fi - - cd downloads - echo "Installing python" - $WINE msiexec /qn /i python-2.7.msi - echo "Installing vc for python" - $WINE msiexec /qn /i VCForPython27.msi - - echo "Installing pyqt (needs X)" - $WINE pyqt-install.exe - echo "Installing nsis (needs X?)" - $WINE nsis-install.exe - - cd .. -} - -setup_pip() { - echo "Seting up pip..." - $WINE C:\\Python27\\python -m pip install --upgrade pip -} - -install_packages() { - echo "Installing pywin32" - $WINE C:\\Python27\\python -m pip install pywin32 - echo "Installing py2exe" - $WINE C:\\Python27\\python -m pip install py2exe_py2 - echo "Installing required packages" - $WINE C:\\Python27\\python -m pip install requests six - # Using easy_install instead of pip to install pycrypto - $WINE C:\\Python27\\Scripts\\easy_install http://www.voidspace.org.uk/python/pycrypto-2.6.1/pycrypto-2.6.1.win32-py2.7.exe - # Copy nsis required NSIS_Simple_Firewall_Plugin_1 - echo "Copying simple firewall plugin for nsis installer" - unzip -o downloads/NSIS_Simple_Firewall_Plugin_1.20.zip SimpleFC.dll -d $WINEPREFIX/drive_c/Program\ Files/NSIS/Plugins/x86-ansi/ - unzip -o downloads/NSIS_Simple_Firewall_Plugin_1.20.zip SimpleFC.dll -d $WINEPREFIX/drive_c/Program\ Files/NSIS/Plugins/x86-unicode/ -} - -download -install_python -setup_pip -install_packages -