finish proxy

This commit is contained in:
speyrefitte
2014-07-25 18:15:42 +02:00
parent 9abd493e4a
commit 3f854bd18b
10 changed files with 311 additions and 72 deletions

View File

@@ -19,7 +19,7 @@
# #
""" """
RDP proxy recorder and spyer RDP proxy recorder and spy function
Proxy RDP protocol Proxy RDP protocol
""" """
@@ -29,8 +29,10 @@ sys.path.insert(1, os.path.join(sys.path[0], '..'))
from rdpy.base import log, error from rdpy.base import log, error
from rdpy.protocol.rdp import rdp from rdpy.protocol.rdp import rdp
from rdpy.network.proxy import IProxyClient
from twisted.internet import reactor from twisted.internet import reactor
clientMacro = None from PyQt4 import QtCore, QtGui
class ProxyServer(rdp.RDPServerObserver): class ProxyServer(rdp.RDPServerObserver):
""" """
Server side of proxy Server side of proxy
@@ -49,10 +51,8 @@ class ProxyServer(rdp.RDPServerObserver):
Event throw by client when it's ready Event throw by client when it's ready
@param client: ProxyClient @param client: ProxyClient
""" """
global clientMacro
self._client = client self._client = client
clientMacro = client self._controller.setColorDepth(self._client.getColorDepth())
self._controller.setColorDepth(self._client._controller.getColorDepth())
def onReady(self): def onReady(self):
""" """
@@ -62,18 +62,18 @@ class ProxyServer(rdp.RDPServerObserver):
domain, username, password = self._controller.getCredentials() domain, username, password = self._controller.getCredentials()
if self._credentialProvider.isAdmin(domain, username, password): if self._credentialProvider.isAdmin(domain, username, password):
self.clientConnected(ProxyClient(clientMacro._controller, self)) self.clientConnected(AdminGUI(self))
return return
try: try:
ip, port, domain, username, password = self._credentialProvider.getCredentials(domain, username, password) dstIp, dstPort, dstDomain, dstUsername, dstPassword = self._credentialProvider.getCredentials(domain, username, password)
except error.InvalidExpectedDataException as e: except error.InvalidExpectedDataException as e:
log.info(e.message) log.info(e.message)
self._controller.close() #self._controller.close()
return return
width, height = self._controller.getScreen() width, height = self._controller.getScreen()
reactor.connectTCP(ip, port, ProxyClientFactory(self, width, height)) reactor.connectTCP(dstIp, dstPort, ProxyClientFactory(self, width, height, dstDomain, dstUsername, dstPassword, "%s/%s -> %s %s/%s"%(domain, username, dstIp, dstDomain, dstUsername)))
def onKeyEventScancode(self, code, isPressed): def onKeyEventScancode(self, code, isPressed):
""" """
@@ -85,7 +85,7 @@ class ProxyServer(rdp.RDPServerObserver):
if self._client is None: if self._client is None:
return return
self._client._controller.sendKeyEventScancode(code, isPressed) self._client.sendKeyEventScancode(code, isPressed)
def onKeyEventUnicode(self, code, isPressed): def onKeyEventUnicode(self, code, isPressed):
""" """
@@ -97,7 +97,7 @@ class ProxyServer(rdp.RDPServerObserver):
if self._client is None: if self._client is None:
return return
self._client._controller.sendKeyEventUnicode(code, isPressed) self._client.sendKeyEventUnicode(code, isPressed)
def onPointerEvent(self, x, y, button, isPressed): def onPointerEvent(self, x, y, button, isPressed):
""" """
@@ -111,9 +111,9 @@ class ProxyServer(rdp.RDPServerObserver):
if self._client is None: if self._client is None:
return return
self._client._controller.sendPointerEvent(x, y, button, isPressed) self._client.sendPointerEvent(x, y, button, isPressed)
class ProxyClient(rdp.RDPClientObserver): class ProxyClient(rdp.RDPClientObserver, IProxyClient):
""" """
Client side of proxy Client side of proxy
""" """
@@ -121,10 +121,34 @@ class ProxyClient(rdp.RDPClientObserver):
""" """
@param controller: RDPClientObserver @param controller: RDPClientObserver
@param server: ProxyServer @param server: ProxyServer
@param name: name of session
""" """
rdp.RDPClientObserver.__init__(self, controller) rdp.RDPClientObserver.__init__(self, controller)
self._server = server self._server = server
def getColorDepth(self):
"""
@return: color depth of session (15,16,24,32)
"""
return self._controller.getColorDepth()
def sendKeyEventScancode(self, code, isPressed):
"""
Send key event with scan code
@param code: scan code
@param isPressed: True if keyboard key is pressed
"""
self._controller.sendKeyEventScancode(code, isPressed)
def sendPointerEvent(self, x, y, button, isPressed):
"""
Send Pointer event
@param x: x position
@param y: y position
@param button: mouse button 1|2|3
"""
self._controller.sendPointerEvent(x, y, button, isPressed)
def onReady(self): def onReady(self):
""" """
Event use to signal that RDP stack is ready Event use to signal that RDP stack is ready
@@ -150,12 +174,15 @@ class ProxyClient(rdp.RDPClientObserver):
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 ProxyServerFactory(rdp.ServerFactory): class ProxyServerFactory(rdp.ServerFactory):
"""
Factory on listening events
"""
def __init__(self, credentialProvider): def __init__(self, credentialProvider):
""" """
@param config: rdp-proxy configuration @param config: rdp-proxy configuration
@param credentialProvider: CredentialProvider @param credentialProvider: CredentialProvider
""" """
rdp.ServerFactory.__init__(self, "/home/sylvain/dev/certificate/rdpy.key", "/home/sylvain/dev/certificate/rdpy.crt", 16) rdp.ServerFactory.__init__(self, "/home/speyrefitte/dev/certificate/rdpy.key", "/home/speyrefitte/dev/certificate/rdpy.crt", 16)
self._credentialProvider = credentialProvider self._credentialProvider = credentialProvider
def buildObserver(self, controller): def buildObserver(self, controller):
@@ -175,27 +202,144 @@ class ProxyServerFactory(rdp.ServerFactory):
pass pass
class ProxyClientFactory(rdp.ClientFactory): class ProxyClientFactory(rdp.ClientFactory):
def __init__(self, server, width, height): """
Factory for proxy client
"""
_CLIENT_PROXY_ = {}
def __init__(self, server, width, height, domain, username, password, name):
"""
@param server: ProxyServer
@param width: screen width
@param height: screen height
@param domain: domain session
@param username: username session
@param password: password session
"""
self._server = server self._server = server
self._width = width self._width = width
self._height = height self._height = height
self._domain = domain
self._username = username
self._password = password
self._name = name
def buildObserver(self, controller): def buildObserver(self, controller):
"""
Implement rdp.ClientFactory
Build observer (ProxyClient)
@param controller: rdp.RDPClientController
"""
#set screen resolution
controller.setScreen(self._width, self._height) controller.setScreen(self._width, self._height)
return ProxyClient(controller, self._server) #set credential
controller.setDomain(self._domain)
controller.setUsername(self._username)
controller.setPassword(self._password)
proxy = ProxyClient(controller, self._server)
ProxyClientFactory._CLIENT_PROXY_[self._name] = proxy
return proxy
def startedConnecting(self, connector): def startedConnecting(self, connector):
pass pass
def clientConnectionLost(self, connector, reason): def clientConnectionLost(self, connector, reason):
pass if ProxyClientFactory._CLIENT_PROXY_.has_key(self._name):
del ProxyClientFactory._CLIENT_PROXY_[self._name]
def clientConnectionFailed(self, connector, reason): def clientConnectionFailed(self, connector, reason):
if ProxyClientFactory._CLIENT_PROXY_.has_key(self._name):
del ProxyClientFactory._CLIENT_PROXY_[self._name]
class CredentialProvider(object):
"""
Credential provider for proxy
"""
def __init__(self, config):
"""
@param config: rdp proxy config
"""
self._config = config
def getCredentials(self, domain, username, password):
"""
@param condig: rdp config
@param domain: domain to check
@param username: username in domain
@param password: password in domain
@return: (ip, port, domain, username, password) or None if error
"""
if not self._config['domain'].has_key(domain):
raise error.InvalidExpectedDataException("Unknown domain %s"%(domain))
for user in self._config['domain'][domain]:
if user['username'] == username and user['password'] == password:
return str(user['credentials']['ip']), user['credentials']['port'], str(user['credentials']['domain']), str(user['credentials']['username']), str(user['credentials']['password'])
raise error.InvalidExpectedDataException("Unknown credential %s\%s"%(domain, username))
def isAdmin(self, domain, username, password):
"""
@return: True if credential match admin credential
"""
return self._config['admin']['domain'] == domain and self._config['admin']['username'] == username and self._config['admin']['password'] == password
class AdminGUI(IProxyClient):
"""
Simple Administration GUI
"""
def __init__(self, server):
"""
@param server: ProxyServer
@param colorDepth: color depth use to generate screen
"""
self._server = server
self._colorDepth = self._server._controller.getColorDepth()
self._activeSessions = [ (x, y) for x, y in ProxyClientFactory._CLIENT_PROXY_.iteritems() ]
self._current = 0
self.display()
def getColorDepth(self):
return self._colorDepth
def sendKeyEventScancode(self, code, isPressed):
#enter key
if code == 28:
clientController = self._activeSessions[self._current][1]._controller
self._server.clientConnected(ProxyClient(clientController, self._server))
#force refresh for new admin screen
width, height = self._server._controller.getScreen()
clientController.sendRefreshOrder(0, 0, width, height)
def sendPointerEvent(self, x, y, button, isPressed):
pass pass
def display(self):
"""
Draw GUI that list active session
"""
i = 0
for name, session in self._activeSessions:
screen = QtGui.QImage(200, 20, QtGui.QImage.Format_RGB16)
if i == self._current:
screen.fill(QtCore.Qt.darkGray)
else:
screen.fill(QtCore.Qt.black)
with QtGui.QPainter(screen) as qp:
if i == self._current:
qp.setPen(QtCore.Qt.black)
else:
qp.setPen(QtCore.Qt.gray)
qp.setFont(QtGui.QFont('arial', 12))
qp.drawText(screen.rect(), QtCore.Qt.AlignCenter, name)
ptr = screen.bits()
ptr.setsize(screen.byteCount())
self._server._controller.sendUpdate(0, i*25, 199, 19, 200, 20, self._colorDepth, False, ptr.asstring())
i+= 1
def help(): def help():
""" """
Print help in consoe Print help in console
""" """
print "Usage: rdpy-rdpproxy -f config_file_path listen_port" print "Usage: rdpy-rdpproxy -f config_file_path listen_port"
@@ -223,37 +367,6 @@ def loadConfig(configFilePath):
return config return config
class CredentialProvider(object):
"""
Credential provider for proxy
"""
def __init__(self, config):
"""
@param config: rdp proxy config
"""
self._config = config
def getCredentials(self, domain, username, password):
"""
@param condig: rdp config
@param domain: domain to check
@param username: username in domain
@param password: password in domain
@return: (ip, port, domain, username, password) or None if error
"""
if not self._config['domain'].has_key(domain):
raise error.InvalidExpectedDataException("Unknown domain %s"%(domain))
for user in self._config['domain'][domain]:
if user['username'] == username and user['password'] == password:
return user['credentials']['ip'], user['credentials']['port'], user['credentials']['domain'], user['credentials']['username'], user['credentials']['password']
raise error.InvalidExpectedDataException("Unknown credential %s\%s"%(domain, username))
def isAdmin(self, domain, username, password):
"""
@return: True if credential match admin credential
"""
return self._config['admin']['domain'] == domain and self._config['admin']['username'] == username and self._config['admin']['password'] == password
if __name__ == '__main__': if __name__ == '__main__':
configFilePath = None configFilePath = None
try: try:
@@ -278,5 +391,8 @@ if __name__ == '__main__':
log.error("Bad configuration file") log.error("Bad configuration file")
sys.exit() sys.exit()
#use to init font
app = QtGui.QApplication(sys.argv)
reactor.listenTCP(int(args[0]), ProxyServerFactory(CredentialProvider(config))) reactor.listenTCP(int(args[0]), ProxyServerFactory(CredentialProvider(config)))
reactor.run() reactor.run()

View File

@@ -25,7 +25,7 @@ RDPY use Layer Protocol design (like twisted)
from rdpy.base.error import CallPureVirtualFuntion from rdpy.base.error import CallPureVirtualFuntion
class StreamListener(object): class IStreamListener(object):
""" """
Interface use to inform that we can handle receive stream Interface use to inform that we can handle receive stream
""" """
@@ -36,9 +36,9 @@ class StreamListener(object):
default is to pass data to presentation layer default is to pass data to presentation layer
@param s: raw Stream receive from transport layer @param s: raw Stream receive from transport layer
""" """
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "recv", "StreamListener")) raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "recv", "IStreamListener"))
class StreamSender(object): class IStreamSender(object):
""" """
Interface use to show stream sender capability Interface use to show stream sender capability
""" """
@@ -47,7 +47,7 @@ class StreamSender(object):
Send Stream on layer 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", "StreamSender")) raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "send", "IStreamSender"))
class Layer(object): class Layer(object):
""" """
@@ -82,7 +82,7 @@ class Layer(object):
if not self._transport is None: if not self._transport is None:
self._transport.close() self._transport.close()
class LayerAutomata(Layer, StreamListener): class LayerAutomata(Layer, IStreamListener):
""" """
Layer with automata state Layer with automata state
we can set next recv function used for Stream packet we can set next recv function used for Stream packet
@@ -111,7 +111,7 @@ from twisted.internet import protocol
#first that handle stream #first that handle stream
from type import Stream from type import Stream
class RawLayer(protocol.Protocol, LayerAutomata, StreamSender): class RawLayer(protocol.Protocol, LayerAutomata, IStreamSender):
""" """
Inherit from protocol twisted class Inherit from protocol twisted class
allow this protocol to wait until expected size of packet allow this protocol to wait until expected size of packet

53
rdpy/network/proxy.py Normal file
View File

@@ -0,0 +1,53 @@
#
# Copyright (c) 2014 Sylvain Peyrefitte
#
# This file is part of rdpy.
#
# rdpy is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
Proxy Interface
client -> ProxyServer | ProxyClient -> server
"""
from rdpy.base.error import CallPureVirtualFuntion
class IProxyClient(object):
"""
Proxy interface for client side
"""
def getColorDepth(self):
"""
@return: color depth of session (15,16,24,32)
"""
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onUpdate", "IProxyClient"))
def sendKeyEventScancode(self, code, isPressed):
"""
Send key event with scan code
@param code: scan code
@param isPressed: True if keyboard key is pressed
"""
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onUpdate", "IProxyClient"))
def sendPointerEvent(self, x, y, button, isPressed):
"""
Send Pointer event
@param x: x position
@param y: y position
@param button: mouse button 1|2|3
"""
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onUpdate", "IProxyClient"))

View File

@@ -24,7 +24,7 @@ Each channel have a particular role.
The main channel is the graphical channel. The main channel is the graphical channel.
It exist channel for file system order, audio channel, clipboard etc... It exist channel for file system order, audio channel, clipboard etc...
""" """
from rdpy.network.layer import LayerAutomata, StreamSender, Layer from rdpy.network.layer import LayerAutomata, IStreamSender, Layer
from rdpy.network.type import sizeof, Stream, UInt8, UInt16Le, String from rdpy.network.type import sizeof, Stream, UInt8, UInt16Le, String
from rdpy.base.error import InvalidExpectedDataException, InvalidValue, InvalidSize from rdpy.base.error import InvalidExpectedDataException, InvalidValue, InvalidSize
from rdpy.protocol.rdp.ber import writeLength from rdpy.protocol.rdp.ber import writeLength
@@ -65,7 +65,7 @@ class MCSLayer(LayerAutomata):
the main layer of RDP protocol the main layer of RDP protocol
is why he can do everything and more! is why he can do everything and more!
""" """
class MCSProxySender(Layer, StreamSender): class MCSProxySender(Layer, IStreamSender):
""" """
Proxy use to set as transport layer for upper channel Proxy use to set as transport layer for upper channel
use to abstract channel id for presentation layer use to abstract channel id for presentation layer

View File

@@ -260,6 +260,14 @@ class FastPathOutputCompression(object):
""" """
FASTPATH_OUTPUT_COMPRESSION_USED = 0x2 FASTPATH_OUTPUT_COMPRESSION_USED = 0x2
class Display(object):
"""
Use in supress output PDU
@see: http://msdn.microsoft.com/en-us/library/cc240648.aspx
"""
SUPPRESS_DISPLAY_UPDATES = 0x00
ALLOW_DISPLAY_UPDATES = 0x01
class ErrorInfo(object): class ErrorInfo(object):
""" """
Error code use in Error info PDU Error code use in Error info PDU
@@ -638,7 +646,7 @@ class DataPDU(CompositeType):
""" """
Create object in accordance self.shareDataHeader.pduType2 value Create object in accordance self.shareDataHeader.pduType2 value
""" """
for c in [UpdateDataPDU, SynchronizeDataPDU, ControlDataPDU, ErrorInfoDataPDU, FontListDataPDU, FontMapDataPDU, PersistentListPDU, ClientInputEventPDU, ShutdownDeniedPDU, ShutdownRequestPDU]: for c in [UpdateDataPDU, SynchronizeDataPDU, ControlDataPDU, ErrorInfoDataPDU, FontListDataPDU, FontMapDataPDU, PersistentListPDU, ClientInputEventPDU, ShutdownDeniedPDU, ShutdownRequestPDU, SuppressOutputDataPDU]:
if self.shareDataHeader.pduType2.value == c._PDUTYPE2_: if self.shareDataHeader.pduType2.value == c._PDUTYPE2_:
return c() return c()
log.debug("unknown PDU data type : %s"%hex(self.shareDataHeader.pduType2.value)) log.debug("unknown PDU data type : %s"%hex(self.shareDataHeader.pduType2.value))
@@ -799,6 +807,41 @@ class ShutdownDeniedPDU(CompositeType):
def __init__(self): def __init__(self):
CompositeType.__init__(self) CompositeType.__init__(self)
class InclusiveRectangle(CompositeType):
"""
@see: http://msdn.microsoft.com/en-us/library/cc240643.aspx
"""
def __init__(self, conditional = lambda:True):
CompositeType.__init__(self)
self.left = UInt16Le()
self.top = UInt16Le()
self.right = UInt16Le()
self.bottom = UInt16Le()
class SuppressOutputDataPDU(CompositeType):
"""
@see: http://msdn.microsoft.com/en-us/library/cc240648.aspx
"""
_PDUTYPE2_ = PDUType2.PDUTYPE2_SUPPRESS_OUTPUT
def __init__(self, readLen = None):
CompositeType.__init__(self, readLen = readLen)
self.allowDisplayUpdates = UInt8()
self.pad3Octets = (UInt8(), UInt8(), UInt8())
self.desktopRect = InclusiveRectangle(conditional = lambda:(self.allowDisplayUpdates.value == Display.ALLOW_DISPLAY_UPDATES))
class RefreshRectPDU(CompositeType):
"""
@see: http://msdn.microsoft.com/en-us/library/cc240646.aspx
"""
_PDUTYPE2_ = PDUType2.PDUTYPE2_REFRESH_RECT
def __init__(self, readLen = None):
CompositeType.__init__(self, readLen = readLen)
self.numberOfAreas = UInt8(lambda:len(self.areasToRefresh._array))
self.pad3Octets = (UInt8(), UInt8(), UInt8())
self.areasToRefresh = ArrayType(InclusiveRectangle, readLen = self.numberOfAreas)
class UpdateDataPDU(CompositeType): class UpdateDataPDU(CompositeType):
""" """
Update data PDU use by server to inform update image or palet Update data PDU use by server to inform update image or palet

View File

@@ -124,7 +124,7 @@ class PDULayer(LayerAutomata):
""" """
self.sendPDU(data.DataPDU(pduData, self._shareId)) self.sendPDU(data.DataPDU(pduData, self._shareId))
class Client(PDULayer, tpkt.FastPathListener): class Client(PDULayer, tpkt.IFastPathListener):
""" """
Client automata of PDU layer Client automata of PDU layer
""" """
@@ -159,7 +159,7 @@ class Client(PDULayer, tpkt.FastPathListener):
def setFastPathSender(self, fastPathSender): def setFastPathSender(self, fastPathSender):
""" """
@param fastPathSender: tpkt.FastPathSender @param fastPathSender: tpkt.FastPathSender
@note: implement tpkt.FastPathListener @note: implement tpkt.IFastPathListener
""" """
self._fastPathSender = fastPathSender self._fastPathSender = fastPathSender
@@ -301,7 +301,7 @@ class Client(PDULayer, tpkt.FastPathListener):
def recvFastPath(self, fastPathS): def recvFastPath(self, fastPathS):
""" """
Implement FastPathListener interface Implement IFastPathListener interface
Fast path is needed by RDP 8.0 Fast path is needed by RDP 8.0
@param fastPathS: Stream that contain fast path data @param fastPathS: Stream that contain fast path data
""" """
@@ -410,7 +410,7 @@ class Client(PDULayer, tpkt.FastPathListener):
pdu.slowPathInputEvents._array = [data.SlowPathInputEvent(x) for x in pointerEvents] pdu.slowPathInputEvents._array = [data.SlowPathInputEvent(x) for x in pointerEvents]
self.sendDataPDU(pdu) self.sendDataPDU(pdu)
class Server(PDULayer, tpkt.FastPathListener): class Server(PDULayer, tpkt.IFastPathListener):
""" """
Server Automata of PDU layer Server Automata of PDU layer
""" """
@@ -433,7 +433,7 @@ class Server(PDULayer, tpkt.FastPathListener):
def setFastPathSender(self, fastPathSender): def setFastPathSender(self, fastPathSender):
""" """
@param fastPathSender: tpkt.FastPathSender @param fastPathSender: tpkt.FastPathSender
@note: implement tpkt.FastPathListener @note: implement tpkt.IFastPathListener
""" """
self._fastPathSender = fastPathSender self._fastPathSender = fastPathSender
@@ -577,7 +577,7 @@ class Server(PDULayer, tpkt.FastPathListener):
def recvFastPath(self, fastPathS): def recvFastPath(self, fastPathS):
""" """
Implement FastPathListener interface Implement IFastPathListener interface
Fast path is needed by RDP 8.0 Fast path is needed by RDP 8.0
@param fastPathS: Stream that contain fast path data @param fastPathS: Stream that contain fast path data
""" """

View File

@@ -213,6 +213,23 @@ class RDPClientController(pdu.layer.PDUClientListener):
except InvalidValue: except InvalidValue:
log.info("try send bad key event") log.info("try send bad key event")
def sendRefreshOrder(self, left, top, right, bottom):
"""
Force server to resend a particular zone
@param left: left coordinate
@param top: top coordinate
@param right: right coordinate
@param bottom: bottom coordinate
"""
refreshPDU = pdu.data.RefreshRectPDU()
rect = pdu.data.InclusiveRectangle()
rect.left.value = left
rect.top.value = top
rect.right.value = right
rect.bottom.value = bottom
refreshPDU.areasToRefresh._array.append(rect)
self._pduLayer.sendDataPDU(refreshPDU)
def close(self): def close(self):
""" """
Close protocol stack Close protocol stack
@@ -279,6 +296,12 @@ class RDPServerController(pdu.layer.PDUServerListener):
""" """
return (self.getDomain(), self.getUsername(), self.getPassword()) return (self.getDomain(), self.getUsername(), self.getPassword())
def getColorDepth(self):
"""
@return: color depth define by server
"""
return self._colorDepth
def getScreen(self): def getScreen(self):
""" """
@return: tuple(width, height) of client asked screen @return: tuple(width, height) of client asked screen
@@ -299,6 +322,9 @@ class RDPServerController(pdu.layer.PDUServerListener):
if PDU stack is already connected send a deactive-reactive sequence if PDU stack is already connected send a deactive-reactive sequence
@param colorDepth: depth of session (15, 16, 24) @param colorDepth: depth of session (15, 16, 24)
""" """
self._colorDepth = colorDepth
if self._pduLayer._serverCapabilities[pdu.caps.CapsType.CAPSTYPE_BITMAP].capability.preferredBitsPerPixel.value == colorDepth:
return
self._pduLayer._serverCapabilities[pdu.caps.CapsType.CAPSTYPE_BITMAP].capability.preferredBitsPerPixel.value = colorDepth self._pduLayer._serverCapabilities[pdu.caps.CapsType.CAPSTYPE_BITMAP].capability.preferredBitsPerPixel.value = colorDepth
if self._isReady: if self._isReady:
#restart connection sequence #restart connection sequence

View File

@@ -24,7 +24,7 @@ This layer have main goal to negociate SSL transport
RDP basic security is not supported by RDPY (because is not a true security layer...) RDP basic security is not supported by RDPY (because is not a true security layer...)
""" """
from rdpy.network.layer import LayerAutomata, StreamSender from rdpy.network.layer import LayerAutomata, IStreamSender
from rdpy.network.type import UInt8, UInt16Le, UInt16Be, UInt32Le, CompositeType, sizeof from rdpy.network.type import UInt8, UInt16Le, UInt16Be, UInt32Le, CompositeType, sizeof
from rdpy.base.error import InvalidExpectedDataException from rdpy.base.error import InvalidExpectedDataException
@@ -107,7 +107,7 @@ class Negotiation(CompositeType):
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, StreamSender): class TPDULayer(LayerAutomata, IStreamSender):
""" """
TPDU layer management TPDU layer management
there is an connection automata there is an connection automata

View File

@@ -34,7 +34,7 @@ class Action(object):
FASTPATH_ACTION_FASTPATH = 0x0 FASTPATH_ACTION_FASTPATH = 0x0
FASTPATH_ACTION_X224 = 0x3 FASTPATH_ACTION_X224 = 0x3
class FastPathListener(object): class IFastPathListener(object):
""" """
Fast path packet listener Fast path packet listener
Usually PDU layer Usually PDU layer
@@ -48,11 +48,11 @@ class FastPathListener(object):
def setFastPathSender(self, fastPathSender): def setFastPathSender(self, fastPathSender):
""" """
@param fastPathSender: FastPathSender @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 FastPathSender(object): class IFastPathSender(object):
""" """
Fast path send capability Fast path send capability
""" """
@@ -60,9 +60,9 @@ class FastPathSender(object):
""" """
@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", "FastPathSender")) raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "sendFastPath", "IFastPathSender"))
class TPKT(RawLayer, FastPathSender): class TPKT(RawLayer, IFastPathSender):
""" """
TPKT layer in RDP protocol stack TPKT layer in RDP protocol stack
This layer only handle size of packet and determine if is a fast path packet This layer only handle size of packet and determine if is a fast path packet
@@ -70,7 +70,7 @@ class TPKT(RawLayer, FastPathSender):
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 TPDU layer
@param fastPathListener: FastPathListener @param fastPathListener: IFastPathListener
""" """
RawLayer.__init__(self, presentation) RawLayer.__init__(self, presentation)
#last packet version read from header #last packet version read from header

View File

@@ -299,6 +299,7 @@ class QRemoteDesktop(QtGui.QWidget):
#draw in widget #draw in widget
with QtGui.QPainter(self) as qp: with QtGui.QPainter(self) as qp:
qp.drawImage(0, 0, self._buffer) qp.drawImage(0, 0, self._buffer)
self._refresh = [] self._refresh = []
def mouseMoveEvent(self, event): def mouseMoveEvent(self, event):