Proxy works only in one direction + bug fix in deactive-reactive sequence input are available

This commit is contained in:
speyrefitte
2014-07-23 18:15:01 +02:00
parent c71c4f46f4
commit 4aa9d8c389
6 changed files with 238 additions and 49 deletions

View File

@@ -1,7 +1,29 @@
#!/usr/bin/python
'''
@author: sylvain
'''
#
# 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/>.
#
"""
RDP proxy recorder and spyer
Proxy RDP protocol
With admin account you can watch all currently session
For special session you can record
"""
import sys, os
# Change path so we find rdpy
@@ -11,23 +33,71 @@ from rdpy.protocol.rdp import rdp
from twisted.internet import reactor
class ProxyServer(rdp.RDPServerObserver):
"""
Server side of proxy
"""
def __init__(self, controller):
"""
@param controller: RDPServerController
"""
rdp.RDPServerObserver.__init__(self, controller)
self._client = None
def onReady(self):
reactor.connectTCP("wav-glw-013", 3389, ProxyClientFactory(self))
"""
Event use to inform state of server stack
Use to connect client
"""
width, height = self._controller.getScreen()
reactor.connectTCP("wav-glw-013", 3389, ProxyClientFactory(self, width, height))
def clientConnected(self, client):
print "ok"
"""
Event throw by client when it's ready
@param client: ProxyClient
"""
self._client = client
self._controller.setColorDepth(self._client._controller.getColorDepth())
class ProxyClient(rdp.RDPClientObserver):
"""
Client side of proxy
"""
def __init__(self, controller, server):
"""
@param controller: RDPClientObserver
@param server: ProxyServer
"""
rdp.RDPClientObserver.__init__(self, controller)
self._server = server
def onReady(self):
"""
Event use to signal that RDP stack is ready
Inform proxy server that i'm connected
implement RDPClientObserver
"""
self._server.clientConnected(self)
def onUpdate(self, destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, isCompress, data):
pass
"""
Event use to inform bitmap update
implement RDPClientObserver
@param destLeft: xmin position
@param destTop: ymin position
@param destRight: xmax position because RDP can send bitmap with padding
@param destBottom: ymax position because RDP can send bitmap with padding
@param width: width of bitmap
@param height: height of bitmap
@param bitsPerPixel: number of bit per pixel
@param isCompress: use RLE compression
@param data: bitmap data
"""
self._server._controller.sendUpdate(destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, isCompress, data)
class ProxyServerFactory(rdp.ServerFactory):
def __init__(self):
rdp.ServerFactory.__init__(self, "/home/speyrefitte/dev/certificate/rdpy.key", "/home/speyrefitte/dev/certificate/rdpy.crt")
rdp.ServerFactory.__init__(self, "/home/speyrefitte/dev/certificate/rdpy.key", "/home/speyrefitte/dev/certificate/rdpy.crt", 16)
def buildObserver(self, controller):
return ProxyServer(controller)
@@ -42,10 +112,13 @@ class ProxyServerFactory(rdp.ServerFactory):
pass
class ProxyClientFactory(rdp.ClientFactory):
def __init__(self, server):
def __init__(self, server, width, height):
self._server = server
self._width = width
self._height = height
def buildObserver(self, controller):
controller.setScreen(self._width, self._height)
return ProxyClient(controller, self._server)
def startedConnecting(self, connector):

View File

@@ -240,8 +240,8 @@ class ClientCoreData(CompositeType):
self.postBeta2ColorDepth = UInt16Le(ColorDepth.RNS_UD_COLOR_8BPP)
self.clientProductId = UInt16Le(1)
self.serialNumber = UInt32Le(0)
self.highColorDepth = UInt16Le(HighColor.HIGH_COLOR_24BPP)
self.supportedColorDepths = UInt16Le(Support.RNS_UD_32BPP_SUPPORT | Support.RNS_UD_24BPP_SUPPORT | Support.RNS_UD_16BPP_SUPPORT)
self.highColorDepth = UInt16Le(HighColor.HIGH_COLOR_15BPP)
self.supportedColorDepths = UInt16Le(Support.RNS_UD_15BPP_SUPPORT)
self.earlyCapabilityFlags = UInt16Le(CapabilityFlags.RNS_UD_CS_SUPPORT_ERRINFO_PDU)
self.clientDigProductId = String("\x00"*64, readLen = UInt8(64))
self.connectionType = UInt8()

View File

@@ -372,7 +372,7 @@ class Client(MCSLayer):
if (confirm != 0) and (channelId == Channel.MCS_GLOBAL_CHANNEL or channelId == self._userId):
raise InvalidExpectedDataException("Server must confirm static channel")
if confirm ==0:
if confirm == 0:
serverNet = self._serverSettings.getBlock(gcc.MessageType.SC_NET)
for i in range(0, serverNet.channelCount.value):
if channelId == serverNet.channelIdArray._array[i].value:
@@ -524,7 +524,8 @@ class Server(MCSLayer):
channelId = per.readInteger16(data)
#actually algo support virtual channel but RDPY have no virtual channel
self.sendChannelJoinConfirm(channelId, channelId in self._channels.keys() or channelId == self._userId)
confirm = 0 if channelId in self._channels.keys() or channelId == self._userId else 1
self.sendChannelJoinConfirm(channelId, confirm)
self._nbChannelConfirmed += 1
if self._nbChannelConfirmed == self._serverSettings.getBlock(gcc.MessageType.SC_NET).channelCount.value + 2:
self.allChannelConnected()

View File

@@ -621,7 +621,7 @@ class DeactiveAllPDU(CompositeType):
CompositeType.__init__(self)
self.shareId = UInt32Le()
self.lengthSourceDescriptor = UInt16Le(lambda:sizeof(self.sourceDescriptor))
self.sourceDescriptor = String(readLen = self.lengthSourceDescriptor)
self.sourceDescriptor = String("rdpy", readLen = self.lengthSourceDescriptor)
class DataPDU(CompositeType):
"""
@@ -849,8 +849,9 @@ class FastPathUpdatePDU(CompositeType):
Create correct object in accordance to self.updateHeader field
"""
if (self.updateHeader.value & 0xf) == FastPathUpdateType.FASTPATH_UPDATETYPE_BITMAP:
return (UInt16Le(FastPathUpdateType.FASTPATH_UPDATETYPE_BITMAP, constant = True), BitmapUpdateDataPDU(readLen = self.size))
return (UInt16Le(FastPathUpdateType.FASTPATH_UPDATETYPE_BITMAP, constant = True), BitmapUpdateDataPDU(readLen = self.size - 2))
else:
log.debug("unknown Fast Path PDU update data type : %s"%hex(self.updateHeader.value & 0xf))
return String()
if updateData is None:
@@ -904,7 +905,12 @@ class BitmapCompressedDataHeader(CompositeType):
Compressed header of bitmap
@see: http://msdn.microsoft.com/en-us/library/cc240644.aspx
"""
def __init__(self, conditional = lambda:True):
def __init__(self, bodySize = 0, scanWidth = 0, uncompressedSize = 0, conditional = lambda:True):
"""
@param bodySize: size of image body
@param scanWidth: width of image
@param uncompressedSize: size of uncompressed image
"""
CompositeType.__init__(self, conditional = conditional)
self.cbCompFirstRowSize = UInt16Le(0x0000, constant = True)
#compressed data size
@@ -917,19 +923,29 @@ class BitmapData(CompositeType):
"""
Bitmap data here the screen capture
"""
def __init__(self):
def __init__(self, destLeft = 0, destTop = 0, destRight = 0, destBottom = 0, width = 0, height = 0, bitsPerPixel = 0, bitmapDataStream = ""):
"""
@param destLeft: destination left coordinate
@param destTop: destination top coordinate
@param destRight: destination right coordinate
@param destBottom: destination bottom coordinate
@param width: width of image
@param height: height of image
@param bitsPerPixel: color depth
@param bitmapDataStream: data
"""
CompositeType.__init__(self)
self.destLeft = UInt16Le()
self.destTop = UInt16Le()
self.destRight = UInt16Le()
self.destBottom = UInt16Le()
self.width = UInt16Le()
self.height = UInt16Le()
self.bitsPerPixel = UInt16Le()
self.destLeft = UInt16Le(destLeft)
self.destTop = UInt16Le(destTop)
self.destRight = UInt16Le(destRight)
self.destBottom = UInt16Le(destBottom)
self.width = UInt16Le(width)
self.height = UInt16Le(height)
self.bitsPerPixel = UInt16Le(bitsPerPixel)
self.flags = UInt16Le()
self.bitmapLength = UInt16Le()
self.bitmapComprHdr = BitmapCompressedDataHeader(conditional = lambda:(not (self.flags.value | BitmapFlag.NO_BITMAP_COMPRESSION_HDR)))
self.bitmapDataStream = String(readLen = UInt16Le(lambda:(self.bitmapLength.value if (self.flags.value | BitmapFlag.NO_BITMAP_COMPRESSION_HDR) else self.bitmapComprHdr.cbCompMainBodySize.value)))
self.bitmapLength = UInt16Le(lambda:(sizeof(self.bitmapComprHdr) + sizeof(self.bitmapDataStream)))
self.bitmapComprHdr = BitmapCompressedDataHeader(bodySize = lambda:sizeof(self.bitmapDataStream), scanWidth = lambda:self.width.value, uncompressedSize = lambda:(self.width.value * self.height.value * self.bitsPerPixel.value), conditional = lambda:((self.flags.value | BitmapFlag.BITMAP_COMPRESSION) and not (self.flags.value | BitmapFlag.NO_BITMAP_COMPRESSION_HDR)))
self.bitmapDataStream = String(bitmapDataStream, readLen = UInt16Le(lambda:(self.bitmapLength.value if (self.flags.value | BitmapFlag.NO_BITMAP_COMPRESSION_HDR) else self.bitmapComprHdr.cbCompMainBodySize.value)))
class SlowPathInputEvent(CompositeType):
"""

View File

@@ -107,12 +107,14 @@ class PDULayer(LayerAutomata):
def sendPDU(self, pduMessage):
"""
Send a PDU data to transport layer
@param pduMessage: PDU message
"""
self._transport.send(data.PDU(self._transport.getUserId(), pduMessage))
def sendDataPDU(self, pduData):
"""
Send an PDUData to transport layer
@param pduData: PDU data message
"""
self.sendPDU(data.DataPDU(pduData, self._shareId))
@@ -183,7 +185,10 @@ class Client(PDULayer, tpkt.FastPathListener):
s.readType(pdu)
if pdu.shareControlHeader.pduType.value != data.PDUType.PDUTYPE_DEMANDACTIVEPDU:
raise InvalidExpectedDataException("Expected Demand Active PDU from server")
#not a blocking error because in deactive reactive sequence
#input can be send too but ignored
log.debug("Ignore message type %s during connection sequence"%hex(pdu.shareControlHeader.pduType.value))
return
self._shareId = pdu.pduMessage.shareId.value
@@ -204,7 +209,11 @@ class Client(PDULayer, tpkt.FastPathListener):
pdu = data.PDU()
s.readType(pdu)
if pdu.shareControlHeader.pduType.value != data.PDUType.PDUTYPE_DATAPDU or pdu.pduMessage.shareDataHeader.pduType2.value != data.PDUType2.PDUTYPE2_SYNCHRONIZE:
raise InvalidExpectedDataException("Error in PDU layer automata : expected synchronizePDU")
#not a blocking error because in deactive reactive sequence
#input can be send too but ignored
log.debug("Ignore message type %s during connection sequence"%hex(pdu.shareControlHeader.pduType.value))
return
self.setNextState(self.recvServerControlCooperatePDU)
def recvServerControlCooperatePDU(self, s):
@@ -216,7 +225,11 @@ class Client(PDULayer, tpkt.FastPathListener):
pdu = data.PDU()
s.readType(pdu)
if pdu.shareControlHeader.pduType.value != data.PDUType.PDUTYPE_DATAPDU or pdu.pduMessage.shareDataHeader.pduType2.value != data.PDUType2.PDUTYPE2_CONTROL or pdu.pduMessage.pduData.action.value != data.Action.CTRLACTION_COOPERATE:
raise InvalidExpectedDataException("Error in PDU layer automata : expected controlCooperatePDU")
#not a blocking error because in deactive reactive sequence
#input can be send too but ignored
log.debug("Ignore message type %s during connection sequence"%hex(pdu.shareControlHeader.pduType.value))
return
self.setNextState(self.recvServerControlGrantedPDU)
def recvServerControlGrantedPDU(self, s):
@@ -228,7 +241,11 @@ class Client(PDULayer, tpkt.FastPathListener):
pdu = data.PDU()
s.readType(pdu)
if pdu.shareControlHeader.pduType.value != data.PDUType.PDUTYPE_DATAPDU or pdu.pduMessage.shareDataHeader.pduType2.value != data.PDUType2.PDUTYPE2_CONTROL or pdu.pduMessage.pduData.action.value != data.Action.CTRLACTION_GRANTED_CONTROL:
raise InvalidExpectedDataException("Error in PDU layer automata : expected controlGrantedPDU")
#not a blocking error because in deactive reactive sequence
#input can be send too but ignored
log.debug("Ignore message type %s during connection sequence"%hex(pdu.shareControlHeader.pduType.value))
return
self.setNextState(self.recvServerFontMapPDU)
def recvServerFontMapPDU(self, s):
@@ -240,7 +257,10 @@ class Client(PDULayer, tpkt.FastPathListener):
pdu = data.PDU()
s.readType(pdu)
if pdu.shareControlHeader.pduType.value != data.PDUType.PDUTYPE_DATAPDU or pdu.pduMessage.shareDataHeader.pduType2.value != data.PDUType2.PDUTYPE2_FONTMAP:
raise InvalidExpectedDataException("Error in PDU layer automata : expected fontMapPDU")
#not a blocking error because in deactive reactive sequence
#input can be send too but ignored
log.debug("Ignore message type %s during connection sequence"%hex(pdu.shareControlHeader.pduType.value))
return
self.setNextState(self.recvPDU)
#here i'm connected
@@ -421,7 +441,10 @@ class Server(PDULayer):
s.readType(pdu)
if pdu.shareControlHeader.pduType.value != data.PDUType.PDUTYPE_CONFIRMACTIVEPDU:
raise InvalidExpectedDataException("Expected Confirm Active PDU from client")
#not a blocking error because in deactive reactive sequence
#input can be send too but ignored
log.debug("Ignore message type %s during connection sequence"%hex(pdu.shareControlHeader.pduType.value))
return
for cap in pdu.pduMessage.capabilitySets._array:
self._clientCapabilities[cap.capabilitySetType] = cap
@@ -437,7 +460,10 @@ class Server(PDULayer):
pdu = data.PDU()
s.readType(pdu)
if pdu.shareControlHeader.pduType.value != data.PDUType.PDUTYPE_DATAPDU or pdu.pduMessage.shareDataHeader.pduType2.value != data.PDUType2.PDUTYPE2_SYNCHRONIZE:
raise InvalidExpectedDataException("Error in PDU layer automata : expected synchronizePDU")
#not a blocking error because in deactive reactive sequence
#input can be send too but ignored
log.debug("Ignore message type %s during connection sequence"%hex(pdu.shareControlHeader.pduType.value))
return
self.setNextState(self.recvClientControlCooperatePDU)
def recvClientControlCooperatePDU(self, s):
@@ -449,7 +475,10 @@ class Server(PDULayer):
pdu = data.PDU()
s.readType(pdu)
if pdu.shareControlHeader.pduType.value != data.PDUType.PDUTYPE_DATAPDU or pdu.pduMessage.shareDataHeader.pduType2.value != data.PDUType2.PDUTYPE2_CONTROL or pdu.pduMessage.pduData.action.value != data.Action.CTRLACTION_COOPERATE:
raise InvalidExpectedDataException("Error in PDU layer automata : expected controlCooperatePDU")
#not a blocking error because in deactive reactive sequence
#input can be send too but ignored
log.debug("Ignore message type %s during connection sequence"%hex(pdu.shareControlHeader.pduType.value))
return
self.setNextState(self.recvClientControlRequestPDU)
def recvClientControlRequestPDU(self, s):
@@ -461,7 +490,10 @@ class Server(PDULayer):
pdu = data.PDU()
s.readType(pdu)
if pdu.shareControlHeader.pduType.value != data.PDUType.PDUTYPE_DATAPDU or pdu.pduMessage.shareDataHeader.pduType2.value != data.PDUType2.PDUTYPE2_CONTROL or pdu.pduMessage.pduData.action.value != data.Action.CTRLACTION_REQUEST_CONTROL:
raise InvalidExpectedDataException("Error in PDU layer automata : expected controlGrantedPDU")
#not a blocking error because in deactive reactive sequence
#input can be send too but ignored
log.debug("Ignore message type %s during connection sequence"%hex(pdu.shareControlHeader.pduType.value))
return
self.setNextState(self.recvClientFontListPDU)
def recvClientFontListPDU(self, s):
@@ -474,7 +506,10 @@ class Server(PDULayer):
pdu = data.PDU()
s.readType(pdu)
if pdu.shareControlHeader.pduType.value != data.PDUType.PDUTYPE_DATAPDU or pdu.pduMessage.shareDataHeader.pduType2.value != data.PDUType2.PDUTYPE2_FONTLIST:
raise InvalidExpectedDataException("Error in PDU layer automata : expected fontMapPDU")
#not a blocking error because in deactive reactive sequence
#input can be send but ignored
log.debug("Ignore message type %s during connection sequence"%hex(pdu.shareControlHeader.pduType.value))
return
#finalize server
self.sendServerFinalizeSynchronizePDU()
@@ -519,13 +554,10 @@ class Server(PDULayer):
generalCapability = self._serverCapabilities[caps.CapsType.CAPSTYPE_GENERAL].capability
generalCapability.osMajorType.value = caps.MajorType.OSMAJORTYPE_WINDOWS
generalCapability.osMinorType.value = caps.MinorType.OSMINORTYPE_WINDOWS_NT
generalCapability.extraFlags.value = caps.GeneralExtraFlag.LONG_CREDENTIALS_SUPPORTED | caps.GeneralExtraFlag.NO_BITMAP_COMPRESSION_HDR | caps.GeneralExtraFlag.FASTPATH_OUTPUT_SUPPORTED
generalCapability.extraFlags.value = caps.GeneralExtraFlag.LONG_CREDENTIALS_SUPPORTED | caps.GeneralExtraFlag.NO_BITMAP_COMPRESSION_HDR
#init bitmap capability
bitmapCapability = self._serverCapabilities[caps.CapsType.CAPSTYPE_BITMAP].capability
bitmapCapability.preferredBitsPerPixel.value = 16
bitmapCapability.desktopWidth.value = 800
bitmapCapability.desktopHeight.value = 600
inputCapability = self._serverCapabilities[caps.CapsType.CAPSTYPE_INPUT].capability
inputCapability.inputFlags.value = caps.InputFlags.INPUT_FLAG_SCANCODES | caps.InputFlags.INPUT_FLAG_MOUSEX
demandActivePDU = data.DemandActivePDU()
demandActivePDU.shareId.value = self._shareId
@@ -551,4 +583,28 @@ class Server(PDULayer):
#deprecated font list pdu
fontMapPDU = data.FontMapDataPDU()
self.sendDataPDU(fontMapPDU)
self.sendDataPDU(fontMapPDU)
def sendPDU(self, pduMessage):
"""
Send a PDU data to transport layer
@param pduMessage: PDU message
"""
PDULayer.sendPDU(self, pduMessage)
#restart capabilities exchange in case of deactive reactive sequence
if isinstance(pduMessage, data.DeactiveAllPDU):
self.sendDemandActivePDU()
self.setNextState(self.recvConfirmActivePDU)
def sendBitmapUpdatePDU(self, bitmapDatas):
"""
Send bitmap update data
@param bitmapDatas: List of data.BitmapData
"""
#check bitmap header for client that want it (very old client)
if self._clientCapabilities[caps.CapsType.CAPSTYPE_GENERAL].capability.extraFlags.value & caps.GeneralExtraFlag.NO_BITMAP_COMPRESSION_HDR:
for bitmapData in bitmapDatas:
bitmapData.flags.value |= data.BitmapFlag.NO_BITMAP_COMPRESSION_HDR
updateDataPDU = data.BitmapUpdateDataPDU()
updateDataPDU.rectangles._array = bitmapDatas
self.sendDataPDU(data.UpdateDataPDU(updateDataPDU))

View File

@@ -25,6 +25,7 @@ from twisted.internet import protocol
from rdpy.base.error import CallPureVirtualFuntion, InvalidValue
import pdu.layer
import pdu.data
import pdu.caps
import rdpy.base.log as log
import tpkt, tpdu, mcs, gcc
@@ -45,6 +46,7 @@ class RDPClientController(pdu.layer.PDUClientListener):
self._tpktLayer = tpkt.TPKT(self._tpduLayer, self._pduLayer)
#is pdu layer is ready to send
self._isReady = False
self._sendReady = False
def getProtocol(self):
"""
@@ -52,6 +54,12 @@ class RDPClientController(pdu.layer.PDUClientListener):
In case of RDP TPKT is the Raw layer
"""
return self._tpktLayer
def getColorDepth(self):
"""
@return: color depth set by the server (15, 16, 24)
"""
return self._pduLayer._serverCapabilities[pdu.caps.CapsType.CAPSTYPE_BITMAP].capability.preferredBitsPerPixel.value
def setPerformanceSession(self):
"""
@@ -113,6 +121,9 @@ class RDPClientController(pdu.layer.PDUClientListener):
Call when PDU layer is connected
"""
self._isReady = True
if self._sendReady:
return
self._sendReady = False
#signal all listener
for observer in self._clientObserver:
observer.onReady()
@@ -206,11 +217,14 @@ class RDPServerController(pdu.layer.PDUServerListener):
"""
Controller use in server side mode
"""
def __init__(self, privateKeyFileName, certificateFileName):
def __init__(self, privateKeyFileName, certificateFileName, colorDepth):
"""
@param privateKeyFileName: file contain server private key
@param certficiateFileName: file that contain public key
@param colorDepth: 15, 16, 24
"""
self._isReady = False
self._sendReady = False
#list of observer
self._serverObserver = []
#build RDP protocol stack
@@ -221,8 +235,8 @@ class RDPServerController(pdu.layer.PDUServerListener):
self._tpduLayer = tpdu.Server(self._mcsLayer, privateKeyFileName, certificateFileName)
#transport packet (protocol layer)
self._tpktLayer = tpkt.TPKT(self._tpduLayer, self._pduLayer)
self._isReady = False
#set color depth of session
self.setColorDepth(colorDepth)
def getProtocol(self):
"""
@@ -259,18 +273,40 @@ class RDPServerController(pdu.layer.PDUServerListener):
"""
return (self.getDomain(), self.getUsername(), self.getPassword())
def getScreen(self):
"""
@return: tuple(width, height) of client asked screen
"""
bitmapCap = self._pduLayer._clientCapabilities[pdu.caps.CapsType.CAPSTYPE_BITMAP].capability
return (bitmapCap.desktopWidth.value, bitmapCap.desktopHeight.value)
def addServerObserver(self, observer):
"""
Add observer to RDP protocol
@param observer: new observer to add
"""
self._serverObserver.append(observer)
def setColorDepth(self, colorDepth):
"""
Set color depth of session
if PDU stack is already connected send a deactive-reactive sequence
@param colorDepth: depth of session (15, 16, 24)
"""
self._pduLayer._serverCapabilities[pdu.caps.CapsType.CAPSTYPE_BITMAP].capability.preferredBitsPerPixel.value = colorDepth
if self._isReady:
#restart connection sequence
self._isReady = False
self._pduLayer.sendPDU(pdu.data.DeactiveAllPDU())
def onReady(self):
"""
RDP stack is now ready
"""
self._isReady = True
if self._sendReady:
return
self._sendReady = True
for observer in self._serverObserver:
observer.onReady()
@@ -289,6 +325,11 @@ class RDPServerController(pdu.layer.PDUServerListener):
"""
if not self._isReady:
return
bitmapData = pdu.data.BitmapData(destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, data)
if isCompress:
bitmapData.flags.value = pdu.data.BitmapFlag.BITMAP_COMPRESSION
self._pduLayer.sendBitmapUpdatePDU([bitmapData])
class ClientFactory(protocol.Factory):
"""
@@ -314,20 +355,22 @@ class ServerFactory(protocol.Factory):
"""
Factory of Server RDP protocol
"""
def __init__(self, privateKeyFileName, certificateFileName):
def __init__(self, privateKeyFileName, certificateFileName, colorDepth):
"""
@param privateKeyFileName: file contain server private key
@param certficiateFileName: file that contain publi key
@param certficiateFileName: file that contain public key
@param colorDepth: color depth of session
"""
self._privateKeyFileName = privateKeyFileName
self._certificateFileName = certificateFileName
self._colorDepth = colorDepth
def buildProtocol(self, addr):
"""
Function call from twisted and build rdp protocol stack
@param addr: destination address
"""
controller = RDPServerController(self._privateKeyFileName, self._certificateFileName)
controller = RDPServerController(self._privateKeyFileName, self._certificateFileName, self._colorDepth)
self.buildObserver(controller)
return controller.getProtocol()