mirror of
https://github.com/dkmstr/openuds.git
synced 2025-01-05 09:17:54 +03:00
fixing client for windows
This commit is contained in:
parent
633671d12c
commit
0ac3fa1987
@ -34,13 +34,11 @@ import sys
|
||||
import os
|
||||
|
||||
import PyQt5 # pylint: disable=unused-import
|
||||
from PyQt5.QtWidgets import QApplication
|
||||
from PyQt5.QtCore import QTimer
|
||||
|
||||
from udsactor.log import logger, DEBUG
|
||||
from udsactor.client import UDSClientQApp
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
logger.setLevel(DEBUG)
|
||||
|
||||
@ -49,18 +47,21 @@ if __name__ == "__main__":
|
||||
|
||||
logger.info('Started UDS Client Actor')
|
||||
|
||||
QApplication.setQuitOnLastWindowClosed(False)
|
||||
# QApplication.setQuitOnLastWindowClosed(False)
|
||||
|
||||
qApp = UDSClientQApp(sys.argv)
|
||||
|
||||
qApp.init()
|
||||
|
||||
# Crate a timer, so we can check signals from time to time by executing python interpreter
|
||||
# Note: Signals are only checked on python code execution, so we create a
|
||||
timer = QTimer(qApp)
|
||||
timer.start(1000)
|
||||
timer.timeout.connect(lambda *a: None)
|
||||
|
||||
qApp.init()
|
||||
qApp.exec_()
|
||||
|
||||
# On windows, this point will never be reached :)
|
||||
qApp.end()
|
||||
|
||||
logger.debug('Exiting...')
|
||||
|
@ -28,10 +28,11 @@
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
# pylint: disable=invalid-name
|
||||
import threading
|
||||
import time
|
||||
import typing
|
||||
import signal
|
||||
import typing
|
||||
|
||||
from PyQt5.QtWidgets import QApplication, QMessageBox
|
||||
from PyQt5.QtCore import QByteArray, QBuffer, QIODevice, pyqtSignal
|
||||
@ -49,6 +50,7 @@ if typing.TYPE_CHECKING:
|
||||
from . import types
|
||||
from PyQt5.QtGui import QPixmap
|
||||
|
||||
|
||||
class UDSClientQApp(QApplication):
|
||||
_app: 'UDSActorClient'
|
||||
_initialized: bool
|
||||
@ -60,6 +62,9 @@ class UDSClientQApp(QApplication):
|
||||
|
||||
# This will be invoked on session close
|
||||
self.commitDataRequest.connect(self.end) # Will be invoked on session close, to gracely close app
|
||||
self.aboutToQuit.connect(self.end)
|
||||
|
||||
|
||||
self.message.connect(self.showMessage)
|
||||
|
||||
# Execute backgroup thread for actions
|
||||
@ -69,9 +74,13 @@ class UDSClientQApp(QApplication):
|
||||
# Notify loging and mark it
|
||||
logger.debug('Starting APP')
|
||||
self._app.start()
|
||||
|
||||
self.aboutToQuit.connect(lambda: logger.debug('About to quit'))
|
||||
|
||||
self._initialized = True
|
||||
|
||||
def end(self, sessionManager=None) -> None:
|
||||
logger.debug('Stopping App')
|
||||
if not self._initialized:
|
||||
return
|
||||
|
||||
@ -120,12 +129,14 @@ class UDSActorClient(threading.Thread):
|
||||
|
||||
try:
|
||||
# Notify loging and mark it
|
||||
self.api.login(platform.operations.getCurrentUser())
|
||||
if platform.name != 'win32': # On win32, SENS will send login/logouts
|
||||
self.api.login(platform.operations.getCurrentUser())
|
||||
|
||||
while self._running:
|
||||
time.sleep(1.1) # Sleeps between loop iterations
|
||||
|
||||
self.api.logout(platform.operations.getCurrentUser())
|
||||
if platform.name != 'win32': # On win32, SENS will send login/logouts
|
||||
self.api.logout(platform.operations.getCurrentUser())
|
||||
except Exception as e:
|
||||
logger.error('Error on client loop: %s', e)
|
||||
|
||||
@ -154,7 +165,11 @@ class UDSActorClient(threading.Thread):
|
||||
return 'ok'
|
||||
|
||||
def screenshot(self) -> typing.Any:
|
||||
pixmap: QPixmap = self._qApp.primaryScreen().grabWindow(0)
|
||||
'''
|
||||
On windows, an RDP session with minimized screen will render "black screen"
|
||||
So only when user is using RDP connection will return an "actual" screenshot
|
||||
'''
|
||||
pixmap: 'QPixmap' = self._qApp.primaryScreen().grabWindow(0)
|
||||
ba = QByteArray()
|
||||
buffer = QBuffer(ba)
|
||||
buffer.open(QIODevice.WriteOnly)
|
||||
|
@ -28,6 +28,7 @@
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
# pylint: disable=invalid-name
|
||||
import threading
|
||||
import http.server
|
||||
import secrets
|
||||
@ -81,7 +82,8 @@ class HTTPServerHandler(http.server.BaseHTTPRequestHandler):
|
||||
|
||||
try:
|
||||
result = getattr(self, 'method_' + path[1])(params) # last part of path is method
|
||||
except AttributeError:
|
||||
except AttributeError as e:
|
||||
logger.error('Invoked invalid method: %s: %s', path[1], e)
|
||||
self.sendJsonResponse(error='Invalid request', code=400)
|
||||
return
|
||||
except Exception as e:
|
||||
|
@ -28,6 +28,7 @@
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
# pylint: disable=invalid-name
|
||||
import json
|
||||
import typing
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
'''
|
||||
import sys
|
||||
|
||||
name = sys.platform
|
||||
if sys.platform == 'win32':
|
||||
from .windows import operations, store # pylint: disable=unused-import
|
||||
else:
|
||||
|
@ -353,6 +353,7 @@ class CommonService: # pylint: disable=too-many-instance-attributes
|
||||
self._loggedIn = False
|
||||
if self._cfg.own_token:
|
||||
self._api.logout(self._cfg.own_token, username)
|
||||
self.onLogout(username)
|
||||
|
||||
# ****************************************
|
||||
# Methods that CAN BE overriden by actors
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# Copyright (c) 2014-2019 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -29,15 +29,12 @@
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
# _*_ coding: iso-8859-1 _*_
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import typing
|
||||
|
||||
import win32com.client # @UnresolvedImport, pylint: disable=import-error
|
||||
import win32com.server.policy # @UnresolvedImport, pylint: disable=import-error
|
||||
import os
|
||||
|
||||
from udsactor.log import logger
|
||||
from ..log import logger
|
||||
|
||||
# based on python SENS example from
|
||||
# http://timgolden.me.uk/python/win32_how_do_i/track-session-events.html
|
||||
@ -52,6 +49,9 @@ PROGID_EventSubscription = "EventSystem.EventSubscription"
|
||||
|
||||
IID_ISensLogon = "{d597bab3-5b9f-11d1-8dd2-00aa004abd5e}"
|
||||
|
||||
# Not imported at runtime, just for type checking
|
||||
if typing.TYPE_CHECKING:
|
||||
from ..service import CommonService
|
||||
|
||||
class SensLogon(win32com.server.policy.DesignatedWrapPolicy):
|
||||
_com_interfaces_ = [IID_ISensLogon]
|
||||
@ -65,38 +65,19 @@ class SensLogon(win32com.server.policy.DesignatedWrapPolicy):
|
||||
'StopScreenSaver'
|
||||
]
|
||||
|
||||
def __init__(self, service):
|
||||
_service: 'CommonService'
|
||||
|
||||
def __init__(self, service: 'CommonService'): # pylint: disable=super-init-not-called
|
||||
self._wrap_(self)
|
||||
self.service = service
|
||||
self._service = service
|
||||
|
||||
def Logon(self, *args):
|
||||
logger.debug('Logon event: {}'.format(args))
|
||||
if self.service.api is not None and self.service.api.isConnected:
|
||||
try:
|
||||
data = self.service.api.login(args[0])
|
||||
logger.debug('Data received for login: {}'.format(data))
|
||||
data = data.split('\t')
|
||||
if len(data) >= 2:
|
||||
logger.debug('Data is valid: {}'.format(data))
|
||||
windir = os.environ['windir']
|
||||
with open(os.path.join(windir, 'remoteip.txt'), 'w') as f:
|
||||
f.write(data[0])
|
||||
with open(os.path.join(windir, 'remoteh.txt'), 'w') as f:
|
||||
f.write(data[1])
|
||||
except Exception as e:
|
||||
logger.fatal('Error notifying logon to server: {}'.format(e))
|
||||
self._service.login(args[0] or '')
|
||||
|
||||
def Logoff(self, *args):
|
||||
logger.debug('Logoff event: arguments: {}'.format(args))
|
||||
if self.service is not None and self.service.api is not None and self.service.api.isConnected:
|
||||
try:
|
||||
self.service.api.logout(args[0])
|
||||
except Exception as e:
|
||||
logger.fatal('Error notifying logoff to server: {}'.format(e))
|
||||
|
||||
logger.debug('Invoking onLogout: {}'.format(self.service))
|
||||
self.service.onLogout(args[0])
|
||||
logger.debug('Invoked!!')
|
||||
self._service.logout(args[0] or '')
|
||||
|
||||
def StartShell(self, *args):
|
||||
# logevent('StartShell : %s' % [args])
|
||||
|
@ -32,6 +32,7 @@
|
||||
import logging
|
||||
import os
|
||||
import tempfile
|
||||
import typing
|
||||
|
||||
import servicemanager # @UnresolvedImport, pylint: disable=import-error
|
||||
|
||||
@ -42,6 +43,8 @@ class LocalLogger: # pylint: disable=too-few-public-methods
|
||||
linux = False
|
||||
windows = True
|
||||
|
||||
logger: typing.Optional[logging.Logger]
|
||||
|
||||
def __init__(self):
|
||||
# tempdir is different for "user application" and "service"
|
||||
# service wil get c:\windows\temp, while user will get c:\users\XXX\temp
|
||||
@ -50,7 +53,7 @@ class LocalLogger: # pylint: disable=too-few-public-methods
|
||||
filename=os.path.join(tempfile.gettempdir(), 'udsactor.log'),
|
||||
filemode='a',
|
||||
format='%(levelname)s %(asctime)s %(message)s',
|
||||
level=logging.INFO
|
||||
level=logging.DEBUG
|
||||
)
|
||||
except Exception:
|
||||
logging.basicConfig() # basic init
|
||||
@ -63,7 +66,8 @@ class LocalLogger: # pylint: disable=too-few-public-methods
|
||||
# our loglevels are 10000 (other), 20000 (debug), ....
|
||||
# logging levels are 10 (debug), 20 (info)
|
||||
# OTHER = logging.NOTSET
|
||||
self.logger.log(level // 1000 - 10, message)
|
||||
if self.logger:
|
||||
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
|
||||
|
@ -92,7 +92,7 @@ class UDSActorSvc(win32serviceutil.ServiceFramework, CommonService):
|
||||
def doWait(self, miliseconds: int) -> None:
|
||||
win32event.WaitForSingleObject(self._hWaitStop, miliseconds)
|
||||
|
||||
def oneStepJoin(self, name: str, domain: str, ou: str, account: str, password: str) -> None:
|
||||
def oneStepJoin(self, name: str, domain: str, ou: str, account: str, password: str) -> None: # pylint: disable=too-many-arguments
|
||||
'''
|
||||
Ejecutes the join domain in exactly one step
|
||||
'''
|
||||
@ -109,7 +109,7 @@ class UDSActorSvc(win32serviceutil.ServiceFramework, CommonService):
|
||||
logger.debug('Requested join domain {} without errors'.format(domain))
|
||||
self.reboot()
|
||||
|
||||
def multiStepJoin(self, name: str, domain: str, ou: str, account: str, password: str) -> None:
|
||||
def multiStepJoin(self, name: str, domain: str, ou: str, account: str, password: str) -> None: # pylint: disable=too-many-arguments
|
||||
currName = operations.getComputerName()
|
||||
if currName.lower() == name.lower():
|
||||
currDomain = operations.getDomainName()
|
||||
|
Loading…
Reference in New Issue
Block a user