refactor gcc function for server side

This commit is contained in:
citronneur
2014-07-17 23:00:39 +02:00
parent a612c11c58
commit c40d2cd600
5 changed files with 137 additions and 78 deletions

View File

@@ -821,7 +821,7 @@ class ArrayType(Type):
But in read mode it can be dynamic But in read mode it can be dynamic
readLen may be dynamic readLen may be dynamic
""" """
def __init__(self, typeFactory, init = None, readLen = UInt8(), conditional = lambda:True, optional = False, constant = False): def __init__(self, typeFactory, init = None, readLen = None, conditional = lambda:True, optional = False, constant = False):
""" """
@param typeFactory: class use to init new element on read @param typeFactory: class use to init new element on read
@param init: init array @param init: init array
@@ -843,10 +843,14 @@ class ArrayType(Type):
@param s: Stream @param s: Stream
""" """
self._array = [] self._array = []
for _ in range(0, self._readLen.value): i = 0
#self._readLen is None means that array will be read until end of stream
while self._readLen is None or i < self._readLen.value:
element = self._typeFactory() element = self._typeFactory()
element._optional = self._readLen is None
s.readType(element) s.readType(element)
self._array.append(element) self._array.append(element)
i += 1
def __write__(self, s): def __write__(self, s):
""" """

View File

@@ -22,7 +22,8 @@ Implement GCC structure use in RDP protocol
http://msdn.microsoft.com/en-us/library/cc240508.aspx http://msdn.microsoft.com/en-us/library/cc240508.aspx
""" """
from rdpy.network.type import UInt8, UInt16Le, UInt32Le, CompositeType, String, UniString, Stream, sizeof from rdpy.network.type import UInt8, UInt16Le, UInt32Le, CompositeType, String, UniString, Stream, sizeof, FactoryType,\
ArrayType
import per import per
from rdpy.network.error import InvalidExpectedDataException from rdpy.network.error import InvalidExpectedDataException
@@ -31,28 +32,24 @@ t124_02_98_oid = ( 0, 0, 20, 124, 0, 1 )
h221_cs_key = "Duca"; h221_cs_key = "Duca";
h221_sc_key = "McDn"; h221_sc_key = "McDn";
class ServerToClientMessage(object): class MessageType(object):
""" """
Server to Client block Server to Client block
GCC conference messages GCC conference messages
@see: http://msdn.microsoft.com/en-us/library/cc240509.aspx @see: http://msdn.microsoft.com/en-us/library/cc240509.aspx
""" """
#server -> client
SC_CORE = 0x0C01 SC_CORE = 0x0C01
SC_SECURITY = 0x0C02 SC_SECURITY = 0x0C02
SC_NET = 0x0C03 SC_NET = 0x0C03
#client -> server
class ClientToServerMessage(object):
"""
Client to Server block
GCC conference messages
@see: http://msdn.microsoft.com/en-us/library/cc240509.aspx
"""
CS_CORE = 0xC001 CS_CORE = 0xC001
CS_SECURITY = 0xC002 CS_SECURITY = 0xC002
CS_NET = 0xC003 CS_NET = 0xC003
CS_CLUSTER = 0xC004 CS_CLUSTER = 0xC004
CS_MONITOR = 0xC005 CS_MONITOR = 0xC005
class ColorDepth(object): class ColorDepth(object):
""" """
Depth color Depth color
@@ -192,12 +189,40 @@ class KeyboardLayout(object):
DUTCH = 0x00000413 DUTCH = 0x00000413
NORWEGIAN = 0x00000414 NORWEGIAN = 0x00000414
class DataBlock(CompositeType):
"""
Block settings
"""
def __init__(self, dataBlock = None):
CompositeType.__init__(self)
self.type = UInt16Le(lambda:self.dataBlock.__class__._TYPE_)
self.length = UInt16Le(lambda:sizeof(self))
class ClientCoreSettings(CompositeType): def DataBlockFactory():
"""
build settings in accordance of type self.type.value
"""
for c in [ClientCoreData, ClientSecurityData, ClientNetworkData, ServerCoreData, ServerNetworkData, ServerSecurityData]:
if self.type.value == c._TYPE_:
return c()
print "WARNING : unknown GCC block type : %s"%self.type.value
#read entire packet
return String(readLen = self.length)
if dataBlock is None:
dataBlock = FactoryType(DataBlockFactory)
elif not "_TYPE_" in dataBlock.__class__.__dict__:
raise InvalidExpectedDataException("Try to send an invalid GCC blocks")
self.dataBlock = dataBlock
class ClientCoreData(CompositeType):
""" """
Class that represent core setting of client Class that represent core setting of client
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx @see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
""" """
_TYPE_ = MessageType.CS_CORE
def __init__(self): def __init__(self):
CompositeType.__init__(self) CompositeType.__init__(self)
self.rdpVersion = UInt32Le(Version.RDP_VERSION_5_PLUS) self.rdpVersion = UInt32Le(Version.RDP_VERSION_5_PLUS)
@@ -223,28 +248,32 @@ class ClientCoreSettings(CompositeType):
self.pad1octet = UInt8() self.pad1octet = UInt8()
self.serverSelectedProtocol = UInt32Le() self.serverSelectedProtocol = UInt32Le()
class ServerCoreSettings(CompositeType): class ServerCoreData(CompositeType):
""" """
Server side core settings structure Server side core settings structure
@see: http://msdn.microsoft.com/en-us/library/cc240517.aspx @see: http://msdn.microsoft.com/en-us/library/cc240517.aspx
""" """
_TYPE_ = MessageType.SC_CORE
def __init__(self): def __init__(self):
CompositeType.__init__(self) CompositeType.__init__(self)
self.rdpVersion = UInt32Le(Version.RDP_VERSION_5_PLUS) self.rdpVersion = UInt32Le(Version.RDP_VERSION_5_PLUS)
self.clientRequestedProtocol = UInt32Le() self.clientRequestedProtocol = UInt32Le()
class ClientSecuritySettings(CompositeType): class ClientSecurityData(CompositeType):
""" """
Client security setting Client security setting
@deprecated: because we use ssl @deprecated: because we use ssl
@see: http://msdn.microsoft.com/en-us/library/cc240511.aspx @see: http://msdn.microsoft.com/en-us/library/cc240511.aspx
""" """
_TYPE_ = MessageType.CS_SECURITY
def __init__(self): def __init__(self):
CompositeType.__init__(self) CompositeType.__init__(self)
self.encryptionMethods = UInt32Le() self.encryptionMethods = UInt32Le()
self.extEncryptionMethods = UInt32Le() self.extEncryptionMethods = UInt32Le()
class ServerSecuritySettings(CompositeType): class ServerSecurityData(CompositeType):
""" """
Server security settings Server security settings
May be ignored because rdpy don't use May be ignored because rdpy don't use
@@ -252,34 +281,71 @@ class ServerSecuritySettings(CompositeType):
@deprecated: because we use SSL @deprecated: because we use SSL
@see: http://msdn.microsoft.com/en-us/library/cc240518.aspx @see: http://msdn.microsoft.com/en-us/library/cc240518.aspx
""" """
_TYPE_ = MessageType.SC_SECURITY
def __init__(self): def __init__(self):
CompositeType.__init__(self) CompositeType.__init__(self)
self.encryptionMethod = UInt32Le() self.encryptionMethod = UInt32Le()
self.encryptionLevel = UInt32Le() self.encryptionLevel = UInt32Le()
class ClientRequestedChannel(CompositeType): class ChannelDef(CompositeType):
""" """
Channels structure share between client and server Channels structure share between client and server
@see: http://msdn.microsoft.com/en-us/library/cc240512.aspx
@see: http://msdn.microsoft.com/en-us/library/cc240513.aspx @see: http://msdn.microsoft.com/en-us/library/cc240513.aspx
""" """
def __init__(self, name = "", options = UInt32Le()): def __init__(self, name = "", options = 0):
CompositeType.__init__(self) CompositeType.__init__(self)
#name of channel #name of channel
self.name = String(name[0:8] + "\x00" * (8 - len(name)), readLen = UInt8(8)) self.name = String(name[0:8] + "\x00" * (8 - len(name)), readLen = UInt8(8))
#unknown #unknown
self.options = options self.options = UInt32Le()
class ClientSettings(object): class ClientNetworkData(CompositeType):
""" """
Class which group all client settings supported by RDPY GCC client network block
All channels asked by client are listed here
@see: http://msdn.microsoft.com/en-us/library/cc240512.aspx
""" """
_TYPE_ = MessageType.CS_NET
def __init__(self): def __init__(self):
self.core = ClientCoreSettings() CompositeType.__init__(self)
#list of ClientRequestedChannel read network gcc packet self.channelCount = UInt32Le()
self.networkChannels = [] self.channelDefArray = ArrayType(ChannelDef, readLen = self.channelCount)
self.security = ClientSecuritySettings()
class ServerNetworkData(CompositeType):
"""
GCC server network block
All channels asked by client are listed here
@see: All channels asked by client are listed here
"""
_TYPE_ = MessageType.SC_NET
def __init__(self):
CompositeType.__init__(self)
self.MCSChannelId = UInt16Le()
self.channelCount = UInt16Le(lambda:len(self.channelIdArray._array))
self.channelIdArray = ArrayType(UInt16Le, readLen = self.channelCount)
self.pad = UInt16Le(conditional = lambda:(self.channelCount.value % 2 == 1))
class Settings(CompositeType):
"""
Class which group all clients settings supported by RDPY
"""
def __init__(self, init = []):
CompositeType.__init__(self)
self.settings = ArrayType(DataBlock, [DataBlock(i) for i in init])
def getBlock(self, messageType):
"""
@param messageType: type of block
@return: specific block of type messageType
"""
for i in self.settings._array:
if i.type.value == messageType:
return i.dataBlock
return None
class ServerSettings(object): class ServerSettings(object):
""" """
@@ -287,12 +353,26 @@ class ServerSettings(object):
""" """
def __init__(self): def __init__(self):
#core settings of server #core settings of server
self.core = ServerCoreSettings() self.core = ServerCoreData()
#unuse security informations #unuse security informations
self.security = ServerSecuritySettings() self.security = ServerSecurityData()
#channel id accepted by server #channel id accepted by server
self.channelsId = [] self.channelsId = []
def clientSettings():
"""
Build settings for client
@return: Settings
"""
return Settings([ClientCoreData(), ClientNetworkData(), ClientSecurityData()])
def serverSettings():
"""
Build settings for server
@return Settings
"""
return Settings([ServerCoreData(), ServerSecurityData(), ServerSecurityData()])
def readConferenceCreateRequest(s): def readConferenceCreateRequest(s):
""" """
Read a response from client Read a response from client
@@ -333,6 +413,9 @@ def readConferenceCreateResponse(s):
per.readChoice(s) per.readChoice(s)
if not per.readOctetStream(s, h221_sc_key, 4): if not per.readOctetStream(s, h221_sc_key, 4):
raise InvalidExpectedDataException("cannot read h221_sc_key") raise InvalidExpectedDataException("cannot read h221_sc_key")
#serverSettings = Settings()
#s.readType(serverSettings)
#return serverSettings
return readServerDataBlocks(s) return readServerDataBlocks(s)
def readServerDataBlocks(s): def readServerDataBlocks(s):
@@ -350,14 +433,14 @@ def readServerDataBlocks(s):
blockLength = UInt16Le() blockLength = UInt16Le()
s.readType((blockType, blockLength)) s.readType((blockType, blockLength))
#read core block #read core block
if blockType.value == ServerToClientMessage.SC_CORE: if blockType.value == MessageType.SC_CORE:
s.readType(settings.core) s.readType(settings.core)
#read network block #read network block
elif blockType.value == ServerToClientMessage.SC_NET: elif blockType.value == MessageType.SC_NET:
settings.channelsId = readServerSecurityData(s) settings.channelsId = readServerSecurityData(s)
#read security block #read security block
#unused in rdpy because use SSL layer #unused in rdpy because use SSL layer
elif blockType.value == ServerToClientMessage.SC_SECURITY: elif blockType.value == MessageType.SC_SECURITY:
s.readType(settings.security) s.readType(settings.security)
else: else:
print "Unknown server block %s"%hex(type) print "Unknown server block %s"%hex(type)
@@ -384,13 +467,12 @@ def readServerSecurityData(s):
channelsId.append(channelId) channelsId.append(channelId)
return channelsId return channelsId
def writeConferenceCreateRequest(settings): def writeConferenceCreateRequest(userData):
""" """
Write conference create request structure Write conference create request structure
@param settings: ClientSettings @param userData: Settings for client
@return: gcc packet @return: GCC packet
""" """
userData = writeClientDataBlocks(settings)
userDataStream = Stream() userDataStream = Stream()
userDataStream.writeType(userData) userDataStream.writeType(userData)
@@ -403,7 +485,7 @@ def writeConferenceCreateRequest(settings):
def writeConferenceCreateResponse(settings): def writeConferenceCreateResponse(settings):
""" """
Write a conference create response packet Write a conference create response packet
@param settings: ServerSettings @param settings: ServerSettingsDataBlock
@return: gcc packet @return: gcc packet
""" """
pass pass
@@ -414,33 +496,6 @@ def writeClientDataBlocks(settings):
and return GCC valid structure and return GCC valid structure
@param settings: ClientSettings @param settings: ClientSettings
""" """
return (writeClientCoreData(settings.core), return (DataBlock(settings.core),
writeClientSecurityData(settings.security), DataBlock(settings.security),
writeClientNetworkData(settings.networkChannels)) DataBlock(settings.network))
def writeClientCoreData(core):
"""
Write client settings in GCC language
@param settings: ClientSettings structure
@return: structure that represent client data blocks
"""
return (UInt16Le(ClientToServerMessage.CS_CORE), UInt16Le(sizeof(core) + 4), core)
def writeClientSecurityData(security):
"""
Write security header block and security structure
@param security: ClientSecuritySettings
@return: GCC client security data
"""
return (UInt16Le(ClientToServerMessage.CS_SECURITY), UInt16Le(sizeof(security) + 4), security)
def writeClientNetworkData(channels):
"""
Write network packet with channels infos
@param channels: list of ClientRequestedChannel
@return: GCC network packet
"""
if len(channels) == 0:
return ()
return (UInt16Le(ClientToServerMessage.CS_NET), UInt16Le(len(channels) * sizeof(ClientRequestedChannel()) + 8), UInt32Le(len(channels)), tuple(channels))

View File

@@ -121,7 +121,7 @@ class MCS(LayerAutomata):
@param presentation: presentation layer @param presentation: presentation layer
""" """
LayerAutomata.__init__(self, mode, presentation) LayerAutomata.__init__(self, mode, presentation)
self._clientSettings = gcc.ClientSettings() self._clientSettings = gcc.clientSettings()
self._serverSettings = gcc.ServerSettings() self._serverSettings = gcc.ServerSettings()
#default user Id #default user Id
self._userId = 1 self._userId = 1
@@ -136,7 +136,7 @@ class MCS(LayerAutomata):
a write connect initial packet a write connect initial packet
""" """
if self._mode == LayerMode.CLIENT: if self._mode == LayerMode.CLIENT:
self._clientSettings.core.serverSelectedProtocol.value = self._transport._selectedProtocol self._clientSettings.getBlock(gcc.MessageType.CS_CORE).serverSelectedProtocol.value = self._transport._selectedProtocol
self.sendConnectInitial() self.sendConnectInitial()
else: else:
self.setNextState(self.recvConnectInitial) self.setNextState(self.recvConnectInitial)

View File

@@ -1259,9 +1259,9 @@ class PDULayer(LayerAutomata, tpkt.FastPathListener):
#init bitmap capability #init bitmap capability
bitmapCapability = self._clientCapabilities[caps.CapsType.CAPSTYPE_BITMAP].capability bitmapCapability = self._clientCapabilities[caps.CapsType.CAPSTYPE_BITMAP].capability
bitmapCapability.preferredBitsPerPixel = self._transport.getGCCClientSettings().core.highColorDepth bitmapCapability.preferredBitsPerPixel = self._transport.getGCCClientSettings().getBlock(gcc.MessageType.CS_CORE).highColorDepth
bitmapCapability.desktopWidth = self._transport.getGCCClientSettings().core.desktopWidth bitmapCapability.desktopWidth = self._transport.getGCCClientSettings().getBlock(gcc.MessageType.CS_CORE).desktopWidth
bitmapCapability.desktopHeight = self._transport.getGCCClientSettings().core.desktopHeight bitmapCapability.desktopHeight = self._transport.getGCCClientSettings().getBlock(gcc.MessageType.CS_CORE).desktopHeight
#init order capability #init order capability
orderCapability = self._clientCapabilities[caps.CapsType.CAPSTYPE_ORDER].capability orderCapability = self._clientCapabilities[caps.CapsType.CAPSTYPE_ORDER].capability
@@ -1270,11 +1270,11 @@ class PDULayer(LayerAutomata, tpkt.FastPathListener):
#init input capability #init input capability
inputCapability = self._clientCapabilities[caps.CapsType.CAPSTYPE_INPUT].capability inputCapability = self._clientCapabilities[caps.CapsType.CAPSTYPE_INPUT].capability
inputCapability.inputFlags.value = caps.InputFlags.INPUT_FLAG_SCANCODES | caps.InputFlags.INPUT_FLAG_MOUSEX | caps.InputFlags.INPUT_FLAG_UNICODE inputCapability.inputFlags.value = caps.InputFlags.INPUT_FLAG_SCANCODES | caps.InputFlags.INPUT_FLAG_MOUSEX | caps.InputFlags.INPUT_FLAG_UNICODE
inputCapability.keyboardLayout = self._transport.getGCCClientSettings().core.kbdLayout inputCapability.keyboardLayout = self._transport.getGCCClientSettings().getBlock(gcc.MessageType.CS_CORE).kbdLayout
inputCapability.keyboardType = self._transport.getGCCClientSettings().core.keyboardType inputCapability.keyboardType = self._transport.getGCCClientSettings().getBlock(gcc.MessageType.CS_CORE).keyboardType
inputCapability.keyboardSubType = self._transport.getGCCClientSettings().core.keyboardSubType inputCapability.keyboardSubType = self._transport.getGCCClientSettings().getBlock(gcc.MessageType.CS_CORE).keyboardSubType
inputCapability.keyboardrFunctionKey = self._transport.getGCCClientSettings().core.keyboardFnKeys inputCapability.keyboardrFunctionKey = self._transport.getGCCClientSettings().getBlock(gcc.MessageType.CS_CORE).keyboardFnKeys
inputCapability.imeFileName = self._transport.getGCCClientSettings().core.imeFileName inputCapability.imeFileName = self._transport.getGCCClientSettings().getBlock(gcc.MessageType.CS_CORE).imeFileName
#make active PDU packet #make active PDU packet
confirmActivePDU = ConfirmActivePDU() confirmActivePDU = ConfirmActivePDU()

View File

@@ -24,7 +24,7 @@ Use to manage RDP stack in twisted
from twisted.internet import protocol from twisted.internet import protocol
from rdpy.network.error import CallPureVirtualFuntion, InvalidValue from rdpy.network.error import CallPureVirtualFuntion, InvalidValue
from rdpy.network.layer import LayerMode from rdpy.network.layer import LayerMode
import tpkt, tpdu, mcs, pdu import tpkt, tpdu, mcs, pdu, gcc
class RDPClientController(pdu.PDUClientListener): class RDPClientController(pdu.PDUClientListener):
""" """
@@ -68,8 +68,8 @@ class RDPClientController(pdu.PDUClientListener):
@param height: height in pixel of screen @param height: height in pixel of screen
""" """
#set screen definition in MCS layer #set screen definition in MCS layer
self._mcsLayer._clientSettings.core.desktopHeight.value = height self._mcsLayer._clientSettings.getBlock(gcc.MessageType.CS_CORE).desktopHeight.value = height
self._mcsLayer._clientSettings.core.desktopWidth.value = width self._mcsLayer._clientSettings.getBlock(gcc.MessageType.CS_CORE).desktopWidth.value = width
def setUsername(self, username): def setUsername(self, username):
""" """