bug fix on proxy + add comments

This commit is contained in:
speyrefitte
2014-08-01 17:47:49 +02:00
parent 9af647ab09
commit 17b57ddd4f
11 changed files with 677 additions and 517 deletions

View File

@@ -33,11 +33,15 @@ from rdpy.protocol.rdp import rdp
class RDPClientQtFactory(rdp.ClientFactory): class RDPClientQtFactory(rdp.ClientFactory):
""" """
Factory create a RDP GUI client @summary: Factory create a RDP GUI client
""" """
def __init__(self, width, height, username, password, domain): def __init__(self, width, height, username, password, domain):
""" """
init client with correct definition @param width: width of client
@param heigth: heigth of client
@param username: username present to the server
@param password: password present to the server
@param domain: microsoft domain
""" """
self._width = width self._width = width
self._height = height self._height = height
@@ -46,10 +50,13 @@ class RDPClientQtFactory(rdp.ClientFactory):
self._domain = domain self._domain = domain
self._w = None self._w = None
def buildObserver(self, controller): def buildObserver(self, controller, addr):
""" """
Build RFB observer @summary: Build RFB observer
We use a RDPClientQt as RDP observer
@param controller: build factory and needed by observer @param controller: build factory and needed by observer
@param addr: destination address
@return: RDPClientQt
""" """
#create client observer #create client observer
client = RDPClientQt(controller, self._width, self._height) client = RDPClientQt(controller, self._width, self._height)
@@ -70,7 +77,7 @@ class RDPClientQtFactory(rdp.ClientFactory):
def clientConnectionLost(self, connector, reason): def clientConnectionLost(self, connector, reason):
""" """
Connection lost event @summary: Connection lost event
@param connector: twisted connector use for rdp connection (use reconnect to restart connection) @param connector: twisted connector use for rdp connection (use reconnect to restart connection)
@param reason: str use to advertise reason of lost connection @param reason: str use to advertise reason of lost connection
""" """
@@ -80,7 +87,7 @@ class RDPClientQtFactory(rdp.ClientFactory):
def clientConnectionFailed(self, connector, reason): def clientConnectionFailed(self, connector, reason):
""" """
Connection failed event @summary: Connection failed event
@param connector: twisted connector use for rdp connection (use reconnect to restart connection) @param connector: twisted connector use for rdp connection (use reconnect to restart connection)
@param reason: str use to advertise reason of lost connection @param reason: str use to advertise reason of lost connection
""" """

View File

@@ -19,8 +19,14 @@
# #
""" """
RDP proxy recorder and spy function RDP proxy with spy capabilities
Proxy RDP protocol ---------------------------
Client RDP -> | ProxyServer | ProxyClient | -> Server RDP
---------------------------
| ProxyAdmin |
------------
^
Admin ----------------------|
""" """
import sys, os, getopt, json import sys, os, getopt, json
@@ -35,7 +41,7 @@ from PyQt4 import QtCore, QtGui
class ProxyServer(rdp.RDPServerObserver): class ProxyServer(rdp.RDPServerObserver):
""" """
Server side of proxy @summary: Server side of proxy
""" """
def __init__(self, controller, credentialProvider): def __init__(self, controller, credentialProvider):
""" """
@@ -48,42 +54,65 @@ class ProxyServer(rdp.RDPServerObserver):
self._window = None self._window = None
def showSelectView(self, machines): def showSelectView(self, machines):
self._machines = dict([("%s:%s"%(ip, port), (ip, port)) for ip, port in machines]) """
@summary: Show select sever view to the client
@param machines: [(ip, port)]
"""
self._machines = machines
width, height = self._controller.getScreen() width, height = self._controller.getScreen()
self._window = view.Window(width, height, QtGui.QColor(24, 93, 123)) self._window = view.Window(width, height, QtGui.QColor(8, 24, 66))
self._window.addView(view.Anchor(width / 2 - 250, 100, view.Label("Please select following server", 500, 50, QtGui.QFont('arial', 18, QtGui.QFont.Bold), backgroundColor = QtGui.QColor(24, 93, 123))))
self._window.addView(view.Anchor(width / 2 - 250, 150, view.List(self._machines.keys(), 500, 500, self.onSelectMachine, QtGui.QColor(24, 93, 123))), True) self._window.addView(view.Anchor(width / 2 - 250, 100, view.Label("Please select following server",
self._window.update(view.RDPRenderer(self._controller, self._controller.getColorDepth()), True) 500, 50, QtGui.QFont('arial', 18, QtGui.QFont.Bold),
backgroundColor = QtGui.QColor(8, 24, 66))))
self._window.addView(view.Anchor(width / 2 - 250, 150, view.List(["%s:%s"%(ip, port) for ip, port in machines],
500, 500, self.onSelectMachine,
QtGui.QColor(8, 24, 66))), True)
self._window.update(view.RDPRenderer(self._controller), True)
def onSelectMachine(self, machine): def onSelectMachine(self, index):
ip, port = self._machines[machine] """
@summary: Callback of view.List in Select server view
@param: machine str name of machine selected
@param: index in list
"""
ip, port = self._machines[index]
width, height = self._controller.getScreen() width, height = self._controller.getScreen()
domain, username, password = self._controller.getCredentials() domain, username, password = self._controller.getCredentials()
reactor.connectTCP(ip, port, ProxyClientFactory(self, width, height, domain, username, password, "%s\\%s on %s:%s"%(domain, username, ip, port))) reactor.connectTCP(ip, port, ProxyClientFactory(self, width, height, domain, username, password))
def clientConnected(self, client): def clientConnected(self, client):
""" """
Event throw by client when it's ready @summary: Event throw by client when it's ready
@param client: ProxyClient @param client: ProxyClient
""" """
self._client = client self._client = client
#need to reevaluate color depth
self._controller.setColorDepth(self._client._controller.getColorDepth()) self._controller.setColorDepth(self._client._controller.getColorDepth())
def showErrorMessage(self, message): def showMessage(self, message):
""" """
Print a message to the client @summary: Print a message to the client
@param message: string @param message: string
""" """
width, height = self._controller.getScreen() width, height = self._controller.getScreen()
popup = view.Window(width, height, QtGui.QColor(24, 93, 123))
popup.addView(view.Anchor(width / 2 - 250, height / 2 - 25, view.Label(message, 500, 50, QtGui.QFont('arial', 18, QtGui.QFont.Bold), backgroundColor = QtGui.QColor(24, 93, 123)))) popup = view.Window(width, height, QtGui.QColor(8, 24, 66))
popup.update(view.RDPRenderer(self._controller, self._controller.getColorDepth()), True) popup.addView(view.Anchor(width / 2 - 250, height / 2 - 25,
view.Label(message, 500, 50,
QtGui.QFont('arial', 18, QtGui.QFont.Bold),
backgroundColor = QtGui.QColor(8, 24, 66))))
popup.update(view.RDPRenderer(self._controller), True)
def onReady(self): def onReady(self):
""" """
Event use to inform state of server stack @summary: Event use to inform state of server stack
Use to connect client First time this event is called is when human client is connected
On ready is not launch only after connection sequence but after a reactivation sequence too Second time is after color depth nego, because color depth nego
restart a connection sequence
Use to connect proxy client or show available server
@see: rdp.RDPServerObserver.onReady
""" """
if self._client is None: if self._client is None:
#try a connection #try a connection
@@ -91,11 +120,13 @@ class ProxyServer(rdp.RDPServerObserver):
machines = self._credentialProvider.getProxyPass(domain, username) machines = self._credentialProvider.getProxyPass(domain, username)
if len(machines) == 0: if len(machines) == 0:
self.showErrorMessage("No servers attach to account %s\\%s"%(domain, username)) self.showMessage("No servers attach to account %s\\%s"%(domain, username))
elif len(machines) == 1: elif len(machines) == 1:
ip, port = machines[0] ip, port = machines[0]
width, height = self._controller.getScreen() width, height = self._controller.getScreen()
reactor.connectTCP(ip, port, ProxyClientFactory(self, width, height, domain, username, password, "%s\\%s on %s:%s"%(domain, username, ip, port))) reactor.connectTCP(ip, port, ProxyClientFactory(self, width, height,
domain, username, password,
"%s\\%s on %s:%s"%(domain, username, ip, port)))
else: else:
self.showSelectView(machines) self.showSelectView(machines)
else: else:
@@ -105,31 +136,35 @@ class ProxyServer(rdp.RDPServerObserver):
def onClose(self): def onClose(self):
""" """
Call when client close connection @summary: Call when human client close connection
@see: rdp.RDPServerObserver.onClose
""" """
if self._client is None: if self._client is None:
return return
#close proxy client
self._client._controller.close() self._client._controller.close()
def onKeyEventScancode(self, code, isPressed): def onKeyEventScancode(self, code, isPressed):
""" """
Event call when a keyboard event is catch in scan code format @summary: Event call when a keyboard event is catch in scan code format
@param code: scan code of key @param code: scan code of key
@param isPressed: True if key is down @param isPressed: True if key is down
@see: rdp.RDPServerObserver.onKeyEventScancode
""" """
#no client connected #no client connected
if not self._client is None: if not self._client is None:
self._client._controller.sendKeyEventScancode(code, isPressed) self._client._controller.sendKeyEventScancode(code, isPressed)
elif not self._window is None and isPressed: elif not self._window is None and isPressed:
self._window.keyEvent(code) self._window.keyEvent(code)
self._window.update(view.RDPRenderer(self._controller, self._controller.getColorDepth())) self._window.update(view.RDPRenderer(self._controller))
def onKeyEventUnicode(self, code, isPressed): def onKeyEventUnicode(self, code, isPressed):
""" """
Event call when a keyboard event is catch in unicode format @summary: Event call when a keyboard event is catch in unicode format
@param code: unicode of key @param code: unicode of key
@param isPressed: True if key is down @param isPressed: True if key is down
@see: rdp.RDPServerObserver.onKeyEventUnicode
""" """
#no client connected domain #no client connected domain
if self._client is None: if self._client is None:
@@ -138,11 +173,12 @@ class ProxyServer(rdp.RDPServerObserver):
def onPointerEvent(self, x, y, button, isPressed): def onPointerEvent(self, x, y, button, isPressed):
""" """
Event call on mouse event @summary: Event call on mouse event
@param x: x position @param x: x position
@param y: y position @param y: y position
@param button: 1, 2 or 3 button @param button: 1, 2 or 3 button
@param isPressed: True if mouse button is pressed @param isPressed: True if mouse button is pressed
@see: rdp.RDPServerObserver.onPointerEvent
""" """
#no client connected #no client connected
if self._client is None: if self._client is None:
@@ -151,33 +187,36 @@ class ProxyServer(rdp.RDPServerObserver):
class ProxyServerFactory(rdp.ServerFactory): class ProxyServerFactory(rdp.ServerFactory):
""" """
Factory on listening events @summary: Factory on listening events
""" """
def __init__(self, credentialProvider, privateKeyFilePath, certificateFilePath): def __init__(self, credentialProvider, privateKeyFilePath, certificateFilePath):
""" """
@param config: rdp-proxy configuration
@param credentialProvider: CredentialProvider @param credentialProvider: CredentialProvider
@param privateKeyFilePath: file contain server private key
@param certificateFilePath: file contain server certificate
""" """
rdp.ServerFactory.__init__(self, privateKeyFilePath, certificateFilePath, 16) rdp.ServerFactory.__init__(self, privateKeyFilePath, certificateFilePath, 16)
self._credentialProvider = credentialProvider self._credentialProvider = credentialProvider
def buildObserver(self, controller): def buildObserver(self, controller, addr):
""" """
Implement rdp.ServerFactory
@param controller: rdp.RDPServerController @param controller: rdp.RDPServerController
@param addr: destination address
@see: rdp.ServerFactory.buildObserver
""" """
return ProxyServer(controller, self._credentialProvider) return ProxyServer(controller, self._credentialProvider)
class ProxyClient(rdp.RDPClientObserver): class ProxyClient(rdp.RDPClientObserver):
""" """
Client side of proxy @summary: Client side of proxy
""" """
_CONNECTED_ = {} _CONNECTED_ = []
def __init__(self, controller, server, name): def __init__(self, controller, server, name = None):
""" """
@param controller: RDPClientObserver @param controller: rdp.RDPClientController
@param server: ProxyServer @param server: ProxyServer
@param name: name of session @param name: name of session None if you don't
want to spy this session
""" """
rdp.RDPClientObserver.__init__(self, controller) rdp.RDPClientObserver.__init__(self, controller)
self._server = server self._server = server
@@ -185,25 +224,24 @@ class ProxyClient(rdp.RDPClientObserver):
def onReady(self): def onReady(self):
""" """
Event use to signal that RDP stack is ready @summary: Event use to signal that RDP stack is ready
Inform proxy server that i'm connected Inform ProxyServer that i'm connected
implement RDPClientObserver @see: rdp.RDPClientObserver.onReady
""" """
ProxyClient._CONNECTED_[self._name] = self if not self._name is None:
ProxyClient._CONNECTED_.append(self)
self._server.clientConnected(self) self._server.clientConnected(self)
def onClose(self): def onClose(self):
""" """
Stack is closes @summary: Event inform that stack is close
@see: rdp.RDPClientObserver.onClose
""" """
if ProxyClient._CONNECTED_.has_key(self._name): ProxyClient._CONNECTED_.remove(self)
del ProxyClient._CONNECTED_[self._name]
self._server._controller.close()
def onUpdate(self, destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, isCompress, data): def onUpdate(self, destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, isCompress, data):
""" """
Event use to inform bitmap update @summary: Event use to inform bitmap update
implement RDPClientObserver
@param destLeft: xmin position @param destLeft: xmin position
@param destTop: ymin position @param destTop: ymin position
@param destRight: xmax position because RDP can send bitmap with padding @param destRight: xmax position because RDP can send bitmap with padding
@@ -213,14 +251,15 @@ class ProxyClient(rdp.RDPClientObserver):
@param bitsPerPixel: number of bit per pixel @param bitsPerPixel: number of bit per pixel
@param isCompress: use RLE compression @param isCompress: use RLE compression
@param data: bitmap data @param data: bitmap data
@see: rdp.RDPClientObserver.onUpdate
""" """
self._server._controller.sendUpdate(destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, isCompress, data) self._server._controller.sendUpdate(destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, isCompress, data)
class ProxyClientFactory(rdp.ClientFactory): class ProxyClientFactory(rdp.ClientFactory):
""" """
Factory for proxy client @summary: Factory for proxy client
""" """
def __init__(self, server, width, height, domain, username, password, name): def __init__(self, server, width, height, domain, username, password):
""" """
@param server: ProxyServer @param server: ProxyServer
@param width: screen width @param width: screen width
@@ -228,7 +267,6 @@ class ProxyClientFactory(rdp.ClientFactory):
@param domain: domain session @param domain: domain session
@param username: username session @param username: username session
@param password: password session @param password: password session
@param name: name of session
""" """
self._controller = server self._controller = server
self._width = width self._width = width
@@ -236,13 +274,14 @@ class ProxyClientFactory(rdp.ClientFactory):
self._domain = domain self._domain = domain
self._username = username self._username = username
self._password = password self._password = password
self._name = name
def buildObserver(self, controller): def buildObserver(self, controller, addr):
""" """
Implement rdp.ClientFactory @summary: Build observer
Build observer (ProxyClient)
@param controller: rdp.RDPClientController @param controller: rdp.RDPClientController
@param addr: destination address
@see: rdp.ClientFactory.buildObserver
@return: ProxyClient
""" """
#set screen resolution #set screen resolution
controller.setScreen(self._width, self._height) controller.setScreen(self._width, self._height)
@@ -250,7 +289,7 @@ class ProxyClientFactory(rdp.ClientFactory):
controller.setDomain(self._domain) controller.setDomain(self._domain)
controller.setUsername(self._username) controller.setUsername(self._username)
controller.setPassword(self._password) controller.setPassword(self._password)
proxy = ProxyClient(controller, self._controller, self._name) proxy = ProxyClient(controller, self._controller, "%s\\%s on %s"%(self._domain, self._username, addr))
return proxy return proxy
def startedConnecting(self, connector): def startedConnecting(self, connector):
@@ -265,18 +304,14 @@ class ProxyClientFactory(rdp.ClientFactory):
class ProxyAdmin(rdp.RDPServerObserver): class ProxyAdmin(rdp.RDPServerObserver):
""" """
Use to manage client side of admin session @summary: Use to manage admin session
Add GUI to select which session to see Add GUI to select which session to see
And manage see session Just escape key is authorized during spy session
Just escape key is authorized during spy session To switch from spy state to admin state
""" """
class State(object): class State(object):
""" GUI = 0 #->list of active session
GUI state -> list of active session SPY = 1 #->watch active session
SPY state -> watch active session
"""
GUI = 0
SPY = 1
def __init__(self, controller): def __init__(self, controller):
""" """
@@ -289,21 +324,32 @@ class ProxyAdmin(rdp.RDPServerObserver):
def initView(self): def initView(self):
""" """
Init GUI view @summary: Initialize Admin GUI view
""" """
self._sessions = list(ProxyClient._CONNECTED_) #copy at t time
width, height = self._controller.getScreen() width, height = self._controller.getScreen()
self._window = view.Window(width, height, QtGui.QColor(24, 93, 123)) self._window = view.Window(width, height, QtGui.QColor(8, 24, 66))
self._window.addView(view.Anchor(width / 2 - 250, 100, view.Label("Please select following session", 500, 50, QtGui.QFont('arial', 18, QtGui.QFont.Bold), backgroundColor = QtGui.QColor(24, 93, 123))))
self._window.addView(view.Anchor(width / 2 - 250, 150, view.List(ProxyClient._CONNECTED_.keys(), 500, 500, self.onSelect, QtGui.QColor(24, 93, 123))), True)
self._window.addView(view.Anchor(width / 2 - 250, 100, view.Label("Please select following session",
500, 50, QtGui.QFont('arial', 18, QtGui.QFont.Bold),
backgroundColor = QtGui.QColor(8, 24, 66))))
self._window.addView(view.Anchor(width / 2 - 250, 150, view.List([p._name for p in self._sessions],
500, 500, self.onSelect,
QtGui.QColor(8, 24, 66))), True)
def clientConnected(self, client):
pass
def onReady(self): def onReady(self):
""" """
Stack is ready and connected @summary: Stack is ready and connected
May be called after an setColorDepth too May be called after an setColorDepth too
@see: rdp.RDPServerObserver.onReady
""" """
if self._state == ProxyAdmin.State.GUI: if self._state == ProxyAdmin.State.GUI:
self.initView() self.initView()
self._window.update(view.RDPRenderer(self._controller, self._controller.getColorDepth()), True) self._window.update(view.RDPRenderer(self._controller), True)
elif self._state == ProxyAdmin.State.SPY: elif self._state == ProxyAdmin.State.SPY:
#refresh client #refresh client
width, height = self._controller.getScreen() width, height = self._controller.getScreen()
@@ -311,21 +357,24 @@ class ProxyAdmin(rdp.RDPServerObserver):
def onClose(self): def onClose(self):
""" """
Stack is closes @summary: Stack is close
@see: rdp.RDPServerObserver.onClose
""" """
pass pass
def onKeyEventScancode(self, code, isPressed): def onKeyEventScancode(self, code, isPressed):
""" """
Event call when a keyboard event is catch in scan code format @summary: Event call when a keyboard event
is catch in scan code format
@param code: scan code of key @param code: scan code of key
@param isPressed: True if key is down @param isPressed: True if key is down
@see: rdp.RDPServerObserver.onKeyEventScancode
""" """
if self._state == ProxyAdmin.State.GUI: if self._state == ProxyAdmin.State.GUI:
if not isPressed: if not isPressed:
return return
self._window.keyEvent(code) self._window.keyEvent(code)
self._window.update(view.RDPRenderer(self._controller, self._controller.getColorDepth())) self._window.update(view.RDPRenderer(self._controller))
elif code == 1: elif code == 1:
#escape button refresh GUI #escape button refresh GUI
self._state = ProxyAdmin.State.GUI self._state = ProxyAdmin.State.GUI
@@ -334,38 +383,39 @@ class ProxyAdmin(rdp.RDPServerObserver):
def onKeyEventUnicode(self, code, isPressed): def onKeyEventUnicode(self, code, isPressed):
""" """
Event call when a keyboard event is catch in unicode format @summary: Event call when a keyboard event is catch in unicode format
In admin mode is forbidden Admin GUI add filter for this event
@param code: unicode of key @param code: unicode of key
@param isPressed: True if key is down @param isPressed: True if key is down
@see: rdp.RDPServerObserver.onKeyEventUnicode
""" """
pass pass
def onPointerEvent(self, x, y, button, isPressed): def onPointerEvent(self, x, y, button, isPressed):
""" """
Event call on mouse event @summary: Event call on mouse event
In admin mode is forbidden Admin GUI add filter for this event
@param x: x position @param x: x position
@param y: y position @param y: y position
@param button: 1, 2 or 3 button @param button: 1, 2 or 3 button
@param isPressed: True if mouse button is pressed @param isPressed: True if mouse button is pressed
@see: rdp.RDPServerObserver.onPointerEvent
""" """
pass pass
def onSelect(self, name): def onSelect(self, index):
""" """
Call back of list view @summary: Callback of list view of active session
@param name: name selected by user Connect to select session
@param index: index in sessions array
""" """
if not ProxyClient._CONNECTED_.has_key(name):
return
self._state = ProxyAdmin.State.SPY self._state = ProxyAdmin.State.SPY
self._spy = ProxyClient(ProxyClient._CONNECTED_[name]._controller, self, "Admin") self._spy = ProxyClient(self._sessions[index]._controller, self)
self._controller.setColorDepth(self._spy._controller.getColorDepth()) self._controller.setColorDepth(self._spy._controller.getColorDepth())
class ProxyAdminFactory(rdp.ServerFactory): class ProxyAdminFactory(rdp.ServerFactory):
""" """
Factory for admin @summary: Factory for admin session
""" """
def __init__(self, privateKeyFilePath, certificateFilePath): def __init__(self, privateKeyFilePath, certificateFilePath):
""" """
@@ -374,16 +424,19 @@ class ProxyAdminFactory(rdp.ServerFactory):
""" """
rdp.ServerFactory.__init__(self, privateKeyFilePath, certificateFilePath, 16) rdp.ServerFactory.__init__(self, privateKeyFilePath, certificateFilePath, 16)
def buildObserver(self, controller): def buildObserver(self, controller, addr):
""" """
Implement rdp.ServerFactory @summary: Build ProxyAdmin
@param controller: rdp.RDPServerController @param controller: rdp.RDPServerController
@param addr: destination address
@return: ProxyAdmin
@see: rdp.ServerFactory.buildObserver
""" """
return ProxyAdmin(controller) return ProxyAdmin(controller)
class CredentialProvider(object): class CredentialProvider(object):
""" """
Credential provider for proxy @summary: Credential provider for proxy
""" """
def __init__(self, config): def __init__(self, config):
""" """
@@ -392,12 +445,19 @@ class CredentialProvider(object):
self._config = config self._config = config
def getAccount(self, domain, username): def getAccount(self, domain, username):
"""
@summary: Find account that match domain::username in config file
@param domain: Windows domain
@param username: username for session
@return: [(unicode(ip), port] or None if not found
"""
if not self._config.has_key(domain) or not self._config[domain].has_key(username): if not self._config.has_key(domain) or not self._config[domain].has_key(username):
return None return None
return self._config[domain][username] return self._config[domain][username]
def getProxyPass(self, domain, username): def getProxyPass(self, domain, username):
""" """
@summary: Find list of server available for thi account
@param domain: domain to check @param domain: domain to check
@param username: username in domain @param username: username in domain
@return: [(ip, port)] @return: [(ip, port)]
@@ -409,13 +469,13 @@ class CredentialProvider(object):
def help(): def help():
""" """
Print help in console @summary: Print help in console
""" """
print "Usage: rdpy-rdpproxy -f credential_file_path -k private_key_file_path -c certificate_file_path listen_port" print "Usage: rdpy-rdpproxy -f credential_file_path -k private_key_file_path -c certificate_file_path listen_port"
def loadConfig(configFilePath): def loadConfig(configFilePath):
""" """
Load and check config file @summary: Load and check config file
@param configFilePath: config file path @param configFilePath: config file path
""" """
if not os.path.isfile(configFilePath): if not os.path.isfile(configFilePath):

View File

@@ -24,42 +24,45 @@ Const it's use to create fake object enum in python
from copy import deepcopy from copy import deepcopy
class Constant(object): class Constant(object):
''' """
Constant descriptor that deep copy value on get @summary: Constant descriptor that deep copy value on get
''' """
def __init__(self, value): def __init__(self, value):
''' """
Constructor keep value @param value: value to protect
''' """
self._value = value self._value = value
def __get__(self, obj, objType): def __get__(self, obj, objType):
''' """
on get constant return deep copy of wrapped value @summary: on get constant return deep copy of wrapped value
''' @param obj: unknown
@param objType: unknown
"""
return deepcopy(self._value) return deepcopy(self._value)
def __set__(self, obj, value): def __set__(self, obj, value):
''' """
set is forbidden @summary: Try to set a protect value is forbidden
in python 2.7 this function work only in python 2.7 this function work only
on instanciate object on instanciate object
''' @param obj:
"""
raise Exception("can't assign constant") raise Exception("can't assign constant")
def __delete__(self, obj): def __delete__(self, obj):
''' """
delete is forbidden on constant @summary: delete is forbidden on constant
''' """
raise Exception("can't delete constant") raise Exception("can't delete constant")
def TypeAttributes(typeClass): def TypeAttributes(typeClass):
''' """
call typeClass ctor on each attributes @summary: Call typeClass ctor on each attributes
to uniform atributes type on class to uniform atributes type on class
@param typeClass: class use to construct each class attributes @param typeClass: class use to construct each class attributes
@return: class decorator @return: class decorator
''' """
def wrapper(cls): def wrapper(cls):
for c_name, c_value in cls.__dict__.iteritems(): for c_name, c_value in cls.__dict__.iteritems():
if c_name[0] != '_' and not callable(c_value): if c_name[0] != '_' and not callable(c_value):
@@ -68,11 +71,11 @@ def TypeAttributes(typeClass):
return wrapper return wrapper
def ConstAttributes(cls): def ConstAttributes(cls):
''' """
copy on read attributes @summary: Copy on read attributes
transform all attributes of class transform all attributes of class
in constant attribute in constant attribute
only attributes which are not begining with '_' char only attributes which are not begining with '_' char
and are not callable and are not callable
''' """
return TypeAttributes(Constant)(cls) return TypeAttributes(Constant)(cls)

View File

@@ -23,7 +23,7 @@ All exceptions error use in RDPY
class CallPureVirtualFuntion(Exception): class CallPureVirtualFuntion(Exception):
""" """
Raise when a virtual function is called and not implemented @summary: Raise when a virtual function is called and not implemented
""" """
def __init__(self, message = ""): def __init__(self, message = ""):
""" """
@@ -33,7 +33,7 @@ class CallPureVirtualFuntion(Exception):
class InvalidValue(Exception): class InvalidValue(Exception):
""" """
Raise when invalid value type occurred @summary: Raise when invalid value type occurred
""" """
def __init__(self, message = ""): def __init__(self, message = ""):
""" """
@@ -43,7 +43,7 @@ class InvalidValue(Exception):
class InvalidExpectedDataException(Exception): class InvalidExpectedDataException(Exception):
""" """
Raise when expected data on network is invalid @summary: Raise when expected data on network is invalid
""" """
def __init__(self, message = ""): def __init__(self, message = ""):
""" """
@@ -53,7 +53,7 @@ class InvalidExpectedDataException(Exception):
class NegotiationFailure(Exception): class NegotiationFailure(Exception):
""" """
Raise when negotiation failure in different protocols @summary: Raise when negotiation failure in different protocols
""" """
def __init__(self, message = ""): def __init__(self, message = ""):
""" """
@@ -63,7 +63,7 @@ class NegotiationFailure(Exception):
class InvalidType(Exception): class InvalidType(Exception):
""" """
Raise when invalid value type occured @summary: Raise when invalid value type occured
""" """
def __init__(self, message = ""): def __init__(self, message = ""):
""" """
@@ -73,7 +73,7 @@ class InvalidType(Exception):
class InvalidSize(Exception): class InvalidSize(Exception):
""" """
Raise when invalid size is present in packet type occured @summary: Raise when invalid size is present in packet type occured
""" """
def __init__(self, message = ""): def __init__(self, message = ""):
""" """
@@ -83,7 +83,7 @@ class InvalidSize(Exception):
class ErrorReportedFromPeer(Exception): class ErrorReportedFromPeer(Exception):
""" """
Raise when peer send an error @summary: Raise when peer send an error
""" """
def __init__(self, message = ""): def __init__(self, message = ""):
""" """

View File

@@ -24,7 +24,7 @@ Actually very basic log engine
class Level(object): class Level(object):
""" """
Level log @summary: Level log
""" """
DEBUG = 0 DEBUG = 0
INFO = 1 INFO = 1
@@ -34,24 +34,44 @@ class Level(object):
_LOG_LEVEL = Level.DEBUG _LOG_LEVEL = Level.DEBUG
def log(message): def log(message):
"""
@summary: Main log function
@param message: string to print
"""
print message print message
def error(message): def error(message):
"""
@summary: Log error message
@param message: string to print as error log
"""
if _LOG_LEVEL > Level.ERROR: if _LOG_LEVEL > Level.ERROR:
return return
log("ERROR : %s"%message) log("ERROR : %s"%message)
def warning(message): def warning(message):
"""
@summary: Log warning message
@param message: string to print as warning log
"""
if _LOG_LEVEL > Level.WARNING: if _LOG_LEVEL > Level.WARNING:
return return
log("WARNING : %s"%message) log("WARNING : %s"%message)
def info(message): def info(message):
"""
@summary: Log info message
@param message: string to print as info log
"""
if _LOG_LEVEL > Level.INFO: if _LOG_LEVEL > Level.INFO:
return return
log("INFO : %s"%message) log("INFO : %s"%message)
def debug(message): def debug(message):
"""
@summary: Log debug message
@param message: string to print as debug log
"""
if _LOG_LEVEL > Level.DEBUG: if _LOG_LEVEL > Level.DEBUG:
return return
log("DEBUG : %s"%message) log("DEBUG : %s"%message)

View File

@@ -27,32 +27,30 @@ from rdpy.base.error import CallPureVirtualFuntion
class IStreamListener(object): class IStreamListener(object):
""" """
Interface use to inform that we can handle receive stream @summary: Interface use to inform stream receiver capability
""" """
def recv(self, s): def recv(self, s):
""" """
Signal that data is available for this layer @summary: Signal that data is available
call by transport layer @param s: Stream
default is to pass data to presentation layer
@param s: raw Stream receive from transport layer
""" """
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "recv", "IStreamListener")) raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "recv", "IStreamListener"))
class IStreamSender(object): class IStreamSender(object):
""" """
Interface use to show stream sender capability @summary: Interface use to inform stream sender capability
""" """
def send(self, data): def send(self, data):
''' """
Send Stream on layer @summary: Send Stream on layer
@param data: Type or tuple element handle by transport layer @param data: Type or tuple element handle by transport layer
''' """
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "send", "IStreamSender")) raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "send", "IStreamSender"))
class Layer(object): class Layer(object):
""" """
A simple double linked list with presentation and transport layer @summary: A simple double linked list with presentation and transport layer
and a subset of event (connect and close) and a subset of event (connect and close)
""" """
def __init__(self, presentation = None): def __init__(self, presentation = None):
""" """
@@ -68,24 +66,25 @@ class Layer(object):
def connect(self): def connect(self):
""" """
Call when transport layer is connected @summary: Call when transport layer is connected
default is send connect event to presentation layer default is send connect event to presentation layer
""" """
if not self._presentation is None: if not self._presentation is None:
self._presentation.connect() self._presentation.connect()
def close(self): def close(self):
""" """
Close layer event @summary: Close layer event
default is sent to transport layer default is sent to transport layer
""" """
if not self._transport is None: if not self._transport is None:
self._transport.close() self._transport.close()
class LayerAutomata(Layer, IStreamListener): class LayerAutomata(Layer, IStreamListener):
""" """
Layer with automata state @summary: Layer with automata callback
we can set next recv function used for Stream packet we can set next recv function used for Stream packet
Usefull for event driven engine as twisted
""" """
def __init__(self, presentation = None): def __init__(self, presentation = None):
""" """
@@ -96,10 +95,8 @@ class LayerAutomata(Layer, IStreamListener):
def setNextState(self, callback = None): def setNextState(self, callback = None):
""" """
Set receive function to next callback or @summary: Set the next callback in automata
current self.recv function if it's None @param callback: a callable object
@param callback: a callable object that can
receive Layer, Stream parameters
""" """
if callback is None: if callback is None:
callback = self.__class__.recv callback = self.__class__.recv
@@ -114,11 +111,11 @@ from type import Stream
class RawLayerClientFactory(protocol.ClientFactory): class RawLayerClientFactory(protocol.ClientFactory):
""" """
Abstract class for Raw layer client factory @summary: Abstract class for Raw layer client factory
""" """
def buildProtocol(self, addr): def buildProtocol(self, addr):
""" """
Function call from twisted and build rdp protocol stack @summary: Function call from twisted
@param addr: destination address @param addr: destination address
""" """
rawLayer = self.buildRawLayer(addr) rawLayer = self.buildRawLayer(addr)
@@ -127,24 +124,25 @@ class RawLayerClientFactory(protocol.ClientFactory):
def buildRawLayer(self, addr): def buildRawLayer(self, addr):
""" """
Override this function to build raw layer @summary: Override this function to build raw layer
@param addr: destination address @param addr: destination address
""" """
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "recv", "IStreamListener")) raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "recv", "IStreamListener"))
def connectionLost(self, rawlayer): def connectionLost(self, rawlayer):
""" """
Overirde this method to handle connection lost @summary: Override this method to handle connection lost
@param rawlayer: rawLayer that cause connectionLost event
""" """
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "recv", "IStreamListener")) raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "recv", "IStreamListener"))
class RawLayerServerFactory(protocol.ClientFactory): class RawLayerServerFactory(protocol.ClientFactory):
""" """
Abstract class for Raw layer server factory @summary: Abstract class for Raw layer server factory
""" """
def buildProtocol(self, addr): def buildProtocol(self, addr):
""" """
Function call from twisted and build rdp protocol stack @summary: Function call from twisted
@param addr: destination address @param addr: destination address
""" """
rawLayer = self.buildRawLayer(addr) rawLayer = self.buildRawLayer(addr)
@@ -153,23 +151,24 @@ class RawLayerServerFactory(protocol.ClientFactory):
def buildRawLayer(self, addr): def buildRawLayer(self, addr):
""" """
Override this function to build raw layer @summary: Override this function to build raw layer
@param addr: destination address @param addr: destination address
""" """
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "recv", "IStreamListener")) raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "recv", "IStreamListener"))
def connectionLost(self, rawlayer): def connectionLost(self, rawlayer):
""" """
Overirde this method to handle connection lost @summary: Override this method to handle connection lost
@param rawlayer: rawLayer that cause connectionLost event
""" """
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "recv", "IStreamListener")) raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "recv", "IStreamListener"))
class RawLayer(protocol.Protocol, LayerAutomata, IStreamSender): class RawLayer(protocol.Protocol, LayerAutomata, IStreamSender):
""" """
Inherit from protocol twisted class @summary: Wait event from twisted engine
allow this protocol to wait until expected size of packet And format correct size packet
and use Layer automata to call next automata state And send correct packet to next automata callback
""" """
def __init__(self, presentation = None): def __init__(self, presentation = None):
""" """
@@ -185,15 +184,15 @@ class RawLayer(protocol.Protocol, LayerAutomata, IStreamSender):
def setFactory(self, factory): def setFactory(self, factory):
""" """
Call by RawLayer Factory @summary: Call by RawLayer Factory
@param param: RawLayerClientFactory or RawLayerFactory @param param: RawLayerClientFactory or RawLayerFactory
""" """
self._factory = factory self._factory = factory
def dataReceived(self, data): def dataReceived(self, data):
""" """
Inherit from protocol class @summary: Inherit from twisted.protocol class
main event of received data main event of received data
@param data: string data receive from twisted @param data: string data receive from twisted
""" """
#add in buffer #add in buffer
@@ -209,24 +208,31 @@ class RawLayer(protocol.Protocol, LayerAutomata, IStreamSender):
def connectionMade(self): def connectionMade(self):
""" """
inherit from twisted protocol @summary: inherit from twisted protocol
""" """
#join two scheme #join two scheme
self.connect() self.connect()
def connectionLost(self, reason): def connectionLost(self, reason):
"""
@summary: Call from twisted engine when protocol is closed
@param reason: str represent reason of close connection
"""
self._factory.connectionLost(self) self._factory.connectionLost(self)
def close(self): def close(self):
""" """
Close raw layer @summary: Close raw layer
Use File descriptor directly to not use TLS close
Because is bugged
""" """
FileDescriptor.loseConnection(self.transport) FileDescriptor.loseConnection(self.transport)
def expect(self, expectedLen, callback = None): def expect(self, expectedLen, callback = None):
""" """
Configure layer to change next state with callback only @summary: Set next automata callback,
when expectLen bytes is received from transport layer But this callback will be only called when
data have expectedLen
@param expectedLen: in bytes length use to call next state @param expectedLen: in bytes length use to call next state
@param callback: callback call when expected length bytes is received @param callback: callback call when expected length bytes is received
""" """
@@ -236,8 +242,9 @@ class RawLayer(protocol.Protocol, LayerAutomata, IStreamSender):
def send(self, message): def send(self, message):
""" """
Send Stream on TCP layer @summary: Send Stream on TCP layer
format message into raw stream understood by transport layer write rdpy Stream message to str
And send it to transport layer
@param message: (tuple | Type) @param message: (tuple | Type)
""" """
s = Stream() s = Stream()

File diff suppressed because it is too large Load Diff

View File

@@ -27,7 +27,7 @@ import pdu.layer
import pdu.data import pdu.data
import pdu.caps import pdu.caps
import rdpy.base.log as log import rdpy.base.log as log
import tpkt, tpdu, mcs, gcc import tpkt, x224, mcs, gcc
class RDPClientController(pdu.layer.PDUClientListener): class RDPClientController(pdu.layer.PDUClientListener):
""" """
@@ -41,9 +41,9 @@ class RDPClientController(pdu.layer.PDUClientListener):
#multi channel service #multi channel service
self._mcsLayer = mcs.Client(self._pduLayer) self._mcsLayer = mcs.Client(self._pduLayer)
#transport pdu layer #transport pdu layer
self._tpduLayer = tpdu.Client(self._mcsLayer) self._x224Layer = x224.Client(self._mcsLayer)
#transport packet (protocol layer) #transport packet (protocol layer)
self._tpktLayer = tpkt.TPKT(self._tpduLayer, self._pduLayer) self._tpktLayer = tpkt.TPKT(self._x224Layer, self._pduLayer)
#is pdu layer is ready to send #is pdu layer is ready to send
self._isReady = False self._isReady = False
@@ -268,9 +268,9 @@ class RDPServerController(pdu.layer.PDUServerListener):
#multi channel service #multi channel service
self._mcsLayer = mcs.Server(self._pduLayer) self._mcsLayer = mcs.Server(self._pduLayer)
#transport pdu layer #transport pdu layer
self._tpduLayer = tpdu.Server(self._mcsLayer, privateKeyFileName, certificateFileName) self._x224Layer = x224.Server(self._mcsLayer, privateKeyFileName, certificateFileName)
#transport packet (protocol layer) #transport packet (protocol layer)
self._tpktLayer = tpkt.TPKT(self._tpduLayer, self._pduLayer) self._tpktLayer = tpkt.TPKT(self._x224Layer, self._pduLayer)
#set color depth of session #set color depth of session
self.setColorDepth(colorDepth) self.setColorDepth(colorDepth)
@@ -422,8 +422,8 @@ class ClientFactory(layer.RawLayerClientFactory):
""" """
def connectionLost(self, tpktLayer): def connectionLost(self, tpktLayer):
#retrieve controller #retrieve controller
tpduLayer = tpktLayer._presentation x224Layer = tpktLayer._presentation
mcsLayer = tpduLayer._presentation mcsLayer = x224Layer._presentation
pduLayer = mcsLayer._channels[mcs.Channel.MCS_GLOBAL_CHANNEL] pduLayer = mcsLayer._channels[mcs.Channel.MCS_GLOBAL_CHANNEL]
controller = pduLayer._listener controller = pduLayer._listener
controller.onClose() controller.onClose()
@@ -434,14 +434,14 @@ class ClientFactory(layer.RawLayerClientFactory):
@param addr: destination address @param addr: destination address
""" """
controller = RDPClientController() controller = RDPClientController()
self.buildObserver(controller) self.buildObserver(controller, addr)
controller.getProtocol()._factory = self
return controller.getProtocol() return controller.getProtocol()
def buildObserver(self, controller): def buildObserver(self, controller, addr):
""" """
Build observer use for connection Build observer use for connection
@param controller: RDPClientController @param controller: RDPClientController
@param addr: destination address
""" """
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "buildObserver", "ClientFactory")) raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "buildObserver", "ClientFactory"))
@@ -461,8 +461,8 @@ class ServerFactory(layer.RawLayerServerFactory):
def connectionLost(self, tpktLayer): def connectionLost(self, tpktLayer):
#retrieve controller #retrieve controller
tpduLayer = tpktLayer._presentation x224Layer = tpktLayer._presentation
mcsLayer = tpduLayer._presentation mcsLayer = x224Layer._presentation
pduLayer = mcsLayer._channels[mcs.Channel.MCS_GLOBAL_CHANNEL] pduLayer = mcsLayer._channels[mcs.Channel.MCS_GLOBAL_CHANNEL]
controller = pduLayer._listener controller = pduLayer._listener
controller.onClose() controller.onClose()
@@ -473,14 +473,14 @@ class ServerFactory(layer.RawLayerServerFactory):
@param addr: destination address @param addr: destination address
""" """
controller = RDPServerController(self._privateKeyFileName, self._certificateFileName, self._colorDepth) controller = RDPServerController(self._privateKeyFileName, self._certificateFileName, self._colorDepth)
self.buildObserver(controller) self.buildObserver(controller, addr)
controller.getProtocol()._factory = self
return controller.getProtocol() return controller.getProtocol()
def buildObserver(self, controller): def buildObserver(self, controller, addr):
""" """
Build observer use for connection Build observer use for connection
@param controller: RDP stack controller @param controller: RDP stack controller
@param addr: destination address
""" """
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "buildObserver", "ServerFactory")) raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "buildObserver", "ServerFactory"))

View File

@@ -36,40 +36,43 @@ class Action(object):
class IFastPathListener(object): class IFastPathListener(object):
""" """
Fast path packet listener @summary: Fast path packet listener
Usually PDU layer Usually X224 layer
""" """
def recvFastPath(self, fastPathS): def recvFastPath(self, fastPathS):
""" """
Call when fast path packet is received @summary: Call when fast path packet is received
@param fastPathS: Stream @param fastPathS: Stream
""" """
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "recvFastPath", "recvFastPath")) raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "recvFastPath", "recvFastPath"))
def setFastPathSender(self, fastPathSender): def setFastPathSender(self, fastPathSender):
""" """
@summary: Call to set a fast path sender to listener
@param fastPathSender: IFastPathSender @param fastPathSender: IFastPathSender
""" """
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "setFastPathSender", "recvFastPath")) raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "setFastPathSender", "recvFastPath"))
class IFastPathSender(object): class IFastPathSender(object):
""" """
Fast path send capability @summary: Fast path send capability
""" """
def sendFastPath(self, fastPathS): def sendFastPath(self, fastPathS):
""" """
@summary: Send fastPathS Type as fast path packet
@param fastPathS: type transform to stream and send as fastpath @param fastPathS: type transform to stream and send as fastpath
""" """
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "sendFastPath", "IFastPathSender")) raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "sendFastPath", "IFastPathSender"))
class TPKT(RawLayer, IFastPathSender): class TPKT(RawLayer, IFastPathSender):
""" """
TPKT layer in RDP protocol stack @summary: TPKT layer in RDP protocol stack
This layer only handle size of packet and determine if is a fast path packet represent the Raw Layer in stack (first layer)
This layer only handle size of packet and determine if is a fast path packet
""" """
def __init__(self, presentation, fastPathListener): def __init__(self, presentation, fastPathListener):
""" """
@param presentation: presentation layer, in RDP case is TPDU layer @param presentation: presentation layer, in RDP case is x224 layer
@param fastPathListener: IFastPathListener @param fastPathListener: IFastPathListener
""" """
RawLayer.__init__(self, presentation) RawLayer.__init__(self, presentation)
@@ -84,8 +87,8 @@ class TPKT(RawLayer, IFastPathSender):
def connect(self): def connect(self):
""" """
Call when transport layer connection @summary: Call when transport layer connection
is made (inherit from RawLayer) is made (inherit from RawLayer)
""" """
#header is on two bytes #header is on two bytes
self.expect(2, self.readHeader) self.expect(2, self.readHeader)

View File

@@ -48,7 +48,7 @@ class NegociationType(object):
class Protocols(object): class Protocols(object):
""" """
Protocols available for TPDU layer Protocols available for x224 layer
""" """
PROTOCOL_RDP = 0x00000000 PROTOCOL_RDP = 0x00000000
PROTOCOL_SSL = 0x00000001 PROTOCOL_SSL = 0x00000001
@@ -94,9 +94,9 @@ class ServerConnectionConfirm(CompositeType):
#read if there is enough data #read if there is enough data
self.protocolNeg = Negotiation(optional = True) self.protocolNeg = Negotiation(optional = True)
class TPDUDataHeader(CompositeType): class X224DataHeader(CompositeType):
""" """
Header send when TPDU exchange application data Header send when x224 exchange application data
""" """
def __init__(self): def __init__(self):
CompositeType.__init__(self) CompositeType.__init__(self)
@@ -116,13 +116,13 @@ class Negotiation(CompositeType):
self.code = UInt8() self.code = UInt8()
self.flag = UInt8(0) self.flag = UInt8(0)
#always 8 #always 8
self.len = UInt16Le(0x0008, constant = True)#not constant because freerdp send me random value... self.len = UInt16Le(0x0008, constant = True)
self.selectedProtocol = UInt32Le(conditional = lambda: (self.code.value != NegociationType.TYPE_RDP_NEG_FAILURE)) self.selectedProtocol = UInt32Le(conditional = lambda: (self.code.value != NegociationType.TYPE_RDP_NEG_FAILURE))
self.failureCode = UInt32Le(conditional = lambda: (self.code.value == NegociationType.TYPE_RDP_NEG_FAILURE)) self.failureCode = UInt32Le(conditional = lambda: (self.code.value == NegociationType.TYPE_RDP_NEG_FAILURE))
class TPDULayer(LayerAutomata, IStreamSender): class X224Layer(LayerAutomata, IStreamSender):
""" """
TPDU layer management x224 layer management
there is an connection automata there is an connection automata
""" """
def __init__(self, presentation): def __init__(self, presentation):
@@ -143,7 +143,7 @@ class TPDULayer(LayerAutomata, IStreamSender):
And pass to presentation layer And pass to presentation layer
@param data: Stream @param data: Stream
""" """
header = TPDUDataHeader() header = X224DataHeader()
data.readType(header) data.readType(header)
self._presentation.recv(data) self._presentation.recv(data)
@@ -153,9 +153,9 @@ class TPDULayer(LayerAutomata, IStreamSender):
Add TPDU header Add TPDU header
@param message: network.Type message @param message: network.Type message
""" """
self._transport.send((TPDUDataHeader(), message)) self._transport.send((X224DataHeader(), message))
class Client(TPDULayer): class Client(X224Layer):
""" """
Client automata of TPDU layer Client automata of TPDU layer
""" """
@@ -163,7 +163,7 @@ class Client(TPDULayer):
""" """
@param presentation: upper layer, MCS layer in RDP case @param presentation: upper layer, MCS layer in RDP case
""" """
TPDULayer.__init__(self, presentation) X224Layer.__init__(self, presentation)
def connect(self): def connect(self):
""" """
@@ -216,9 +216,9 @@ class Client(TPDULayer):
#connection is done send to presentation #connection is done send to presentation
self._presentation.connect() self._presentation.connect()
class Server(TPDULayer): class Server(X224Layer):
""" """
Server automata of TPDU layer Server automata of X224 layer
""" """
def __init__(self, presentation, privateKeyFileName, certificateFileName): def __init__(self, presentation, privateKeyFileName, certificateFileName):
""" """
@@ -226,7 +226,7 @@ class Server(TPDULayer):
@param privateKeyFileName: file contain server private key @param privateKeyFileName: file contain server private key
@param certficiateFileName: file that contain public key @param certficiateFileName: file that contain public key
""" """
TPDULayer.__init__(self, presentation) X224Layer.__init__(self, presentation)
#Server mode informations for TLS connection #Server mode informations for TLS connection
self._serverPrivateKeyFileName = privateKeyFileName self._serverPrivateKeyFileName = privateKeyFileName
self._serverCertificateFileName = certificateFileName self._serverCertificateFileName = certificateFileName

View File

@@ -123,7 +123,7 @@ class List(IView):
if len(self._labels) == 0: if len(self._labels) == 0:
return return
if code == KeyCode.ENTER: if code == KeyCode.ENTER:
self._callback(self._labels[self._current]) self._callback(self._current)
elif code == KeyCode.DOWN: elif code == KeyCode.DOWN:
self._current = min(len(self._labels) - 1, self._current + 1) self._current = min(len(self._labels) - 1, self._current + 1)
self._needUpdate = True self._needUpdate = True
@@ -221,14 +221,13 @@ class Label(IView):
qp.drawText(drawArea.rect(), QtCore.Qt.AlignCenter, self._label) qp.drawText(drawArea.rect(), QtCore.Qt.AlignCenter, self._label)
render.drawImage(drawArea) render.drawImage(drawArea)
class RDPRenderer(object): class RDPRenderer(IRender):
def __init__(self, controller, colorDepth): def __init__(self, controller):
""" """
@param server: RDPServerController @param server: RDPServerController
@param colorDepth: color depth
""" """
self._controller = controller self._controller = controller
self._colorDepth = colorDepth self._colorDepth = controller.getColorDepth()
self._dx = 0 self._dx = 0
self._dy = 0 self._dy = 0