refactor gcc function for server side
This commit is contained in:
@@ -821,7 +821,7 @@ class ArrayType(Type):
|
||||
But in read mode it can 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 init: init array
|
||||
@@ -843,10 +843,14 @@ class ArrayType(Type):
|
||||
@param s: Stream
|
||||
"""
|
||||
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._optional = self._readLen is None
|
||||
s.readType(element)
|
||||
self._array.append(element)
|
||||
i += 1
|
||||
|
||||
def __write__(self, s):
|
||||
"""
|
||||
|
||||
@@ -22,7 +22,8 @@ Implement GCC structure use in RDP protocol
|
||||
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
|
||||
from rdpy.network.error import InvalidExpectedDataException
|
||||
|
||||
@@ -31,27 +32,23 @@ t124_02_98_oid = ( 0, 0, 20, 124, 0, 1 )
|
||||
h221_cs_key = "Duca";
|
||||
h221_sc_key = "McDn";
|
||||
|
||||
class ServerToClientMessage(object):
|
||||
class MessageType(object):
|
||||
"""
|
||||
Server to Client block
|
||||
GCC conference messages
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240509.aspx
|
||||
"""
|
||||
#server -> client
|
||||
SC_CORE = 0x0C01
|
||||
SC_SECURITY = 0x0C02
|
||||
SC_NET = 0x0C03
|
||||
|
||||
class ClientToServerMessage(object):
|
||||
"""
|
||||
Client to Server block
|
||||
GCC conference messages
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240509.aspx
|
||||
"""
|
||||
#client -> server
|
||||
CS_CORE = 0xC001
|
||||
CS_SECURITY = 0xC002
|
||||
CS_NET = 0xC003
|
||||
CS_CLUSTER = 0xC004
|
||||
CS_MONITOR = 0xC005
|
||||
|
||||
|
||||
class ColorDepth(object):
|
||||
"""
|
||||
@@ -192,12 +189,40 @@ class KeyboardLayout(object):
|
||||
DUTCH = 0x00000413
|
||||
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))
|
||||
|
||||
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 ClientCoreSettings(CompositeType):
|
||||
class ClientCoreData(CompositeType):
|
||||
"""
|
||||
Class that represent core setting of client
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
|
||||
"""
|
||||
_TYPE_ = MessageType.CS_CORE
|
||||
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
self.rdpVersion = UInt32Le(Version.RDP_VERSION_5_PLUS)
|
||||
@@ -223,28 +248,32 @@ class ClientCoreSettings(CompositeType):
|
||||
self.pad1octet = UInt8()
|
||||
self.serverSelectedProtocol = UInt32Le()
|
||||
|
||||
class ServerCoreSettings(CompositeType):
|
||||
class ServerCoreData(CompositeType):
|
||||
"""
|
||||
Server side core settings structure
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240517.aspx
|
||||
"""
|
||||
_TYPE_ = MessageType.SC_CORE
|
||||
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
self.rdpVersion = UInt32Le(Version.RDP_VERSION_5_PLUS)
|
||||
self.clientRequestedProtocol = UInt32Le()
|
||||
|
||||
class ClientSecuritySettings(CompositeType):
|
||||
class ClientSecurityData(CompositeType):
|
||||
"""
|
||||
Client security setting
|
||||
@deprecated: because we use ssl
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240511.aspx
|
||||
"""
|
||||
_TYPE_ = MessageType.CS_SECURITY
|
||||
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
self.encryptionMethods = UInt32Le()
|
||||
self.extEncryptionMethods = UInt32Le()
|
||||
|
||||
class ServerSecuritySettings(CompositeType):
|
||||
class ServerSecurityData(CompositeType):
|
||||
"""
|
||||
Server security settings
|
||||
May be ignored because rdpy don't use
|
||||
@@ -252,34 +281,71 @@ class ServerSecuritySettings(CompositeType):
|
||||
@deprecated: because we use SSL
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240518.aspx
|
||||
"""
|
||||
_TYPE_ = MessageType.SC_SECURITY
|
||||
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
self.encryptionMethod = UInt32Le()
|
||||
self.encryptionLevel = UInt32Le()
|
||||
|
||||
|
||||
class ClientRequestedChannel(CompositeType):
|
||||
class ChannelDef(CompositeType):
|
||||
"""
|
||||
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
|
||||
"""
|
||||
def __init__(self, name = "", options = UInt32Le()):
|
||||
def __init__(self, name = "", options = 0):
|
||||
CompositeType.__init__(self)
|
||||
#name of channel
|
||||
self.name = String(name[0:8] + "\x00" * (8 - len(name)), readLen = UInt8(8))
|
||||
#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):
|
||||
self.core = ClientCoreSettings()
|
||||
#list of ClientRequestedChannel read network gcc packet
|
||||
self.networkChannels = []
|
||||
self.security = ClientSecuritySettings()
|
||||
CompositeType.__init__(self)
|
||||
self.channelCount = UInt32Le()
|
||||
self.channelDefArray = ArrayType(ChannelDef, readLen = self.channelCount)
|
||||
|
||||
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):
|
||||
"""
|
||||
@@ -287,12 +353,26 @@ class ServerSettings(object):
|
||||
"""
|
||||
def __init__(self):
|
||||
#core settings of server
|
||||
self.core = ServerCoreSettings()
|
||||
self.core = ServerCoreData()
|
||||
#unuse security informations
|
||||
self.security = ServerSecuritySettings()
|
||||
self.security = ServerSecurityData()
|
||||
#channel id accepted by server
|
||||
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):
|
||||
"""
|
||||
Read a response from client
|
||||
@@ -333,6 +413,9 @@ def readConferenceCreateResponse(s):
|
||||
per.readChoice(s)
|
||||
if not per.readOctetStream(s, h221_sc_key, 4):
|
||||
raise InvalidExpectedDataException("cannot read h221_sc_key")
|
||||
#serverSettings = Settings()
|
||||
#s.readType(serverSettings)
|
||||
#return serverSettings
|
||||
return readServerDataBlocks(s)
|
||||
|
||||
def readServerDataBlocks(s):
|
||||
@@ -350,14 +433,14 @@ def readServerDataBlocks(s):
|
||||
blockLength = UInt16Le()
|
||||
s.readType((blockType, blockLength))
|
||||
#read core block
|
||||
if blockType.value == ServerToClientMessage.SC_CORE:
|
||||
if blockType.value == MessageType.SC_CORE:
|
||||
s.readType(settings.core)
|
||||
#read network block
|
||||
elif blockType.value == ServerToClientMessage.SC_NET:
|
||||
elif blockType.value == MessageType.SC_NET:
|
||||
settings.channelsId = readServerSecurityData(s)
|
||||
#read security block
|
||||
#unused in rdpy because use SSL layer
|
||||
elif blockType.value == ServerToClientMessage.SC_SECURITY:
|
||||
elif blockType.value == MessageType.SC_SECURITY:
|
||||
s.readType(settings.security)
|
||||
else:
|
||||
print "Unknown server block %s"%hex(type)
|
||||
@@ -384,13 +467,12 @@ def readServerSecurityData(s):
|
||||
channelsId.append(channelId)
|
||||
return channelsId
|
||||
|
||||
def writeConferenceCreateRequest(settings):
|
||||
def writeConferenceCreateRequest(userData):
|
||||
"""
|
||||
Write conference create request structure
|
||||
@param settings: ClientSettings
|
||||
@return: gcc packet
|
||||
@param userData: Settings for client
|
||||
@return: GCC packet
|
||||
"""
|
||||
userData = writeClientDataBlocks(settings)
|
||||
userDataStream = Stream()
|
||||
userDataStream.writeType(userData)
|
||||
|
||||
@@ -403,7 +485,7 @@ def writeConferenceCreateRequest(settings):
|
||||
def writeConferenceCreateResponse(settings):
|
||||
"""
|
||||
Write a conference create response packet
|
||||
@param settings: ServerSettings
|
||||
@param settings: ServerSettingsDataBlock
|
||||
@return: gcc packet
|
||||
"""
|
||||
pass
|
||||
@@ -414,33 +496,6 @@ def writeClientDataBlocks(settings):
|
||||
and return GCC valid structure
|
||||
@param settings: ClientSettings
|
||||
"""
|
||||
return (writeClientCoreData(settings.core),
|
||||
writeClientSecurityData(settings.security),
|
||||
writeClientNetworkData(settings.networkChannels))
|
||||
|
||||
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))
|
||||
|
||||
return (DataBlock(settings.core),
|
||||
DataBlock(settings.security),
|
||||
DataBlock(settings.network))
|
||||
@@ -121,7 +121,7 @@ class MCS(LayerAutomata):
|
||||
@param presentation: presentation layer
|
||||
"""
|
||||
LayerAutomata.__init__(self, mode, presentation)
|
||||
self._clientSettings = gcc.ClientSettings()
|
||||
self._clientSettings = gcc.clientSettings()
|
||||
self._serverSettings = gcc.ServerSettings()
|
||||
#default user Id
|
||||
self._userId = 1
|
||||
@@ -136,7 +136,7 @@ class MCS(LayerAutomata):
|
||||
a write connect initial packet
|
||||
"""
|
||||
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()
|
||||
else:
|
||||
self.setNextState(self.recvConnectInitial)
|
||||
|
||||
@@ -1259,9 +1259,9 @@ class PDULayer(LayerAutomata, tpkt.FastPathListener):
|
||||
|
||||
#init bitmap capability
|
||||
bitmapCapability = self._clientCapabilities[caps.CapsType.CAPSTYPE_BITMAP].capability
|
||||
bitmapCapability.preferredBitsPerPixel = self._transport.getGCCClientSettings().core.highColorDepth
|
||||
bitmapCapability.desktopWidth = self._transport.getGCCClientSettings().core.desktopWidth
|
||||
bitmapCapability.desktopHeight = self._transport.getGCCClientSettings().core.desktopHeight
|
||||
bitmapCapability.preferredBitsPerPixel = self._transport.getGCCClientSettings().getBlock(gcc.MessageType.CS_CORE).highColorDepth
|
||||
bitmapCapability.desktopWidth = self._transport.getGCCClientSettings().getBlock(gcc.MessageType.CS_CORE).desktopWidth
|
||||
bitmapCapability.desktopHeight = self._transport.getGCCClientSettings().getBlock(gcc.MessageType.CS_CORE).desktopHeight
|
||||
|
||||
#init order capability
|
||||
orderCapability = self._clientCapabilities[caps.CapsType.CAPSTYPE_ORDER].capability
|
||||
@@ -1270,11 +1270,11 @@ class PDULayer(LayerAutomata, tpkt.FastPathListener):
|
||||
#init 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.keyboardLayout = self._transport.getGCCClientSettings().core.kbdLayout
|
||||
inputCapability.keyboardType = self._transport.getGCCClientSettings().core.keyboardType
|
||||
inputCapability.keyboardSubType = self._transport.getGCCClientSettings().core.keyboardSubType
|
||||
inputCapability.keyboardrFunctionKey = self._transport.getGCCClientSettings().core.keyboardFnKeys
|
||||
inputCapability.imeFileName = self._transport.getGCCClientSettings().core.imeFileName
|
||||
inputCapability.keyboardLayout = self._transport.getGCCClientSettings().getBlock(gcc.MessageType.CS_CORE).kbdLayout
|
||||
inputCapability.keyboardType = self._transport.getGCCClientSettings().getBlock(gcc.MessageType.CS_CORE).keyboardType
|
||||
inputCapability.keyboardSubType = self._transport.getGCCClientSettings().getBlock(gcc.MessageType.CS_CORE).keyboardSubType
|
||||
inputCapability.keyboardrFunctionKey = self._transport.getGCCClientSettings().getBlock(gcc.MessageType.CS_CORE).keyboardFnKeys
|
||||
inputCapability.imeFileName = self._transport.getGCCClientSettings().getBlock(gcc.MessageType.CS_CORE).imeFileName
|
||||
|
||||
#make active PDU packet
|
||||
confirmActivePDU = ConfirmActivePDU()
|
||||
|
||||
@@ -24,7 +24,7 @@ Use to manage RDP stack in twisted
|
||||
from twisted.internet import protocol
|
||||
from rdpy.network.error import CallPureVirtualFuntion, InvalidValue
|
||||
from rdpy.network.layer import LayerMode
|
||||
import tpkt, tpdu, mcs, pdu
|
||||
import tpkt, tpdu, mcs, pdu, gcc
|
||||
|
||||
class RDPClientController(pdu.PDUClientListener):
|
||||
"""
|
||||
@@ -68,8 +68,8 @@ class RDPClientController(pdu.PDUClientListener):
|
||||
@param height: height in pixel of screen
|
||||
"""
|
||||
#set screen definition in MCS layer
|
||||
self._mcsLayer._clientSettings.core.desktopHeight.value = height
|
||||
self._mcsLayer._clientSettings.core.desktopWidth.value = width
|
||||
self._mcsLayer._clientSettings.getBlock(gcc.MessageType.CS_CORE).desktopHeight.value = height
|
||||
self._mcsLayer._clientSettings.getBlock(gcc.MessageType.CS_CORE).desktopWidth.value = width
|
||||
|
||||
def setUsername(self, username):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user