425 lines
13 KiB
Python
425 lines
13 KiB
Python
'''
|
|
@author sylvain
|
|
@summary gcc language
|
|
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
|
|
'''
|
|
from rdpy.network.const import ConstAttributes, TypeAttributes
|
|
from rdpy.network.type import UInt8, UInt16Le, UInt32Le, CompositeType, String, UniString, Stream, sizeof
|
|
import per
|
|
from rdpy.network.error import InvalidExpectedDataException
|
|
|
|
t124_02_98_oid = ( 0, 0, 20, 124, 0, 1 )
|
|
h221_cs_key = "Duca";
|
|
h221_sc_key = "McDn";
|
|
|
|
@ConstAttributes
|
|
@TypeAttributes(UInt16Le)
|
|
class ServerToClientMessage(object):
|
|
'''
|
|
Server to Client block
|
|
gcc conference messages
|
|
@see: http://msdn.microsoft.com/en-us/library/cc240509.aspx
|
|
'''
|
|
SC_CORE = 0x0C01
|
|
SC_SECURITY = 0x0C02
|
|
SC_NET = 0x0C03
|
|
|
|
@ConstAttributes
|
|
@TypeAttributes(UInt16Le)
|
|
class ClientToServerMessage(object):
|
|
'''
|
|
Client to Server block
|
|
gcc conference messages
|
|
@see: http://msdn.microsoft.com/en-us/library/cc240509.aspx
|
|
'''
|
|
CS_CORE = 0xC001
|
|
CS_SECURITY = 0xC002
|
|
CS_NET = 0xC003
|
|
CS_CLUSTER = 0xC004
|
|
CS_MONITOR = 0xC005
|
|
|
|
@ConstAttributes
|
|
@TypeAttributes(UInt16Le)
|
|
class ColorDepth(object):
|
|
'''
|
|
depth color
|
|
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
|
|
'''
|
|
RNS_UD_COLOR_8BPP = 0xCA01
|
|
RNS_UD_COLOR_16BPP_555 = 0xCA02
|
|
RNS_UD_COLOR_16BPP_565 = 0xCA03
|
|
RNS_UD_COLOR_24BPP = 0xCA04
|
|
|
|
@ConstAttributes
|
|
@TypeAttributes(UInt16Le)
|
|
class HighColor(object):
|
|
'''
|
|
high color of client
|
|
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
|
|
'''
|
|
HIGH_COLOR_4BPP = 0x0004
|
|
HIGH_COLOR_8BPP = 0x0008
|
|
HIGH_COLOR_15BPP = 0x000f
|
|
HIGH_COLOR_16BPP = 0x0010
|
|
HIGH_COLOR_24BPP = 0x0018
|
|
|
|
@ConstAttributes
|
|
@TypeAttributes(UInt16Le)
|
|
class Support(object):
|
|
'''
|
|
support depth flag
|
|
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
|
|
'''
|
|
RNS_UD_24BPP_SUPPORT = 0x0001
|
|
RNS_UD_16BPP_SUPPORT = 0x0002
|
|
RNS_UD_15BPP_SUPPORT = 0x0004
|
|
RNS_UD_32BPP_SUPPORT = 0x0008
|
|
|
|
@ConstAttributes
|
|
@TypeAttributes(UInt16Le)
|
|
class CapabilityFlags(object):
|
|
'''
|
|
for more details on each flags click above
|
|
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
|
|
'''
|
|
RNS_UD_CS_SUPPORT_ERRINFO_PDU = 0x0001
|
|
RNS_UD_CS_WANT_32BPP_SESSION = 0x0002
|
|
RNS_UD_CS_SUPPORT_STATUSINFO_PDU = 0x0004
|
|
RNS_UD_CS_STRONG_ASYMMETRIC_KEYS = 0x0008
|
|
RN_UD_CS_UNUSED = 0x0010
|
|
RNS_UD_CS_VALID_CONNECTION_TYPE = 0x0020
|
|
RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU = 0x0040
|
|
RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT = 0x0080
|
|
RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL = 0x0100
|
|
RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE = 0x0200
|
|
RNS_UD_CS_SUPPORT_HEARTBEAT_PDU = 0x0400
|
|
|
|
@ConstAttributes
|
|
@TypeAttributes(UInt8)
|
|
class ConnectionType(object):
|
|
'''
|
|
this information is correct if
|
|
RNS_UD_CS_VALID_CONNECTION_TYPE flag is set on capabilityFlag
|
|
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
|
|
'''
|
|
CONNECTION_TYPE_MODEM = 0x01
|
|
CONNECTION_TYPE_BROADBAND_LOW = 0x02
|
|
CONNECTION_TYPE_SATELLITE = 0x03
|
|
CONNECTION_TYPE_BROADBAND_HIGH = 0x04
|
|
CONNECTION_TYPE_WAN = 0x05
|
|
CONNECTION_TYPE_LAN = 0x06
|
|
CONNECTION_TYPE_AUTODETECT = 0x07
|
|
|
|
@ConstAttributes
|
|
@TypeAttributes(UInt32Le)
|
|
class Version(object):
|
|
'''
|
|
supported version of RDP
|
|
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
|
|
'''
|
|
RDP_VERSION_4 = 0x00080001
|
|
RDP_VERSION_5_PLUS = 0x00080004
|
|
|
|
@ConstAttributes
|
|
@TypeAttributes(UInt16Le)
|
|
class Sequence(object):
|
|
RNS_UD_SAS_DEL = 0xAA03
|
|
|
|
@ConstAttributes
|
|
@TypeAttributes(UInt32Le)
|
|
class Encryption(object):
|
|
'''
|
|
encryption method supported
|
|
@deprecated: because rdpy use ssl but need to send to server...
|
|
@see: http://msdn.microsoft.com/en-us/library/cc240511.aspx
|
|
'''
|
|
ENCRYPTION_FLAG_40BIT = 0x00000001
|
|
ENCRYPTION_FLAG_128BIT = 0x00000002
|
|
ENCRYPTION_FLAG_56BIT = 0x00000008
|
|
FIPS_ENCRYPTION_FLAG = 0x00000010
|
|
|
|
@ConstAttributes
|
|
@TypeAttributes(UInt32Le)
|
|
class ChannelOptions(object):
|
|
'''
|
|
channel options
|
|
@see: http://msdn.microsoft.com/en-us/library/cc240513.aspx
|
|
'''
|
|
CHANNEL_OPTION_INITIALIZED = 0x80000000
|
|
CHANNEL_OPTION_ENCRYPT_RDP = 0x40000000
|
|
CHANNEL_OPTION_ENCRYPT_SC = 0x20000000
|
|
CHANNEL_OPTION_ENCRYPT_CS = 0x10000000
|
|
CHANNEL_OPTION_PRI_HIGH = 0x08000000
|
|
CHANNEL_OPTION_PRI_MED = 0x04000000
|
|
CHANNEL_OPTION_PRI_LOW = 0x02000000
|
|
CHANNEL_OPTION_COMPRESS_RDP = 0x00800000
|
|
CHANNEL_OPTION_COMPRESS = 0x00400000
|
|
CHANNEL_OPTION_SHOW_PROTOCOL = 0x00200000
|
|
REMOTE_CONTROL_PERSISTENT = 0x00100000
|
|
|
|
@ConstAttributes
|
|
@TypeAttributes(UInt32Le)
|
|
class KeyboardType(object):
|
|
'''
|
|
Keyboard type
|
|
IBM_101_102_KEYS is the most common keyboard type
|
|
'''
|
|
IBM_PC_XT_83_KEY = 0x00000001
|
|
OLIVETTI = 0x00000002
|
|
IBM_PC_AT_84_KEY = 0x00000003
|
|
IBM_101_102_KEYS = 0x00000004
|
|
NOKIA_1050 = 0x00000005
|
|
NOKIA_9140 = 0x00000006
|
|
JAPANESE = 0x00000007
|
|
|
|
@ConstAttributes
|
|
@TypeAttributes(UInt32Le)
|
|
class KeyboardLayout(object):
|
|
'''
|
|
Keyboard layout definition
|
|
@see: http://technet.microsoft.com/en-us/library/cc766503%28WS.10%29.aspx
|
|
'''
|
|
ARABIC = 0x00000401
|
|
BULGARIAN = 0x00000402
|
|
CHINESE_US_KEYBOARD = 0x00000404
|
|
CZECH = 0x00000405
|
|
DANISH = 0x00000406
|
|
GERMAN = 0x00000407
|
|
GREEK = 0x00000408
|
|
US = 0x00000409
|
|
SPANISH = 0x0000040a
|
|
FINNISH = 0x0000040b
|
|
FRENCH = 0x0000040c
|
|
HEBREW = 0x0000040d
|
|
HUNGARIAN = 0x0000040e
|
|
ICELANDIC = 0x0000040f
|
|
ITALIAN = 0x00000410
|
|
JAPANESE = 0x00000411
|
|
KOREAN = 0x00000412
|
|
DUTCH = 0x00000413
|
|
NORWEGIAN = 0x00000414
|
|
|
|
|
|
class ClientCoreSettings(CompositeType):
|
|
'''
|
|
class that represent core setting of client
|
|
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
|
|
'''
|
|
def __init__(self):
|
|
CompositeType.__init__(self)
|
|
self.rdpVersion = Version.RDP_VERSION_5_PLUS
|
|
self.desktopWidth = UInt16Le(1280)
|
|
self.desktopHeight = UInt16Le(1024)
|
|
self.colorDepth = ColorDepth.RNS_UD_COLOR_8BPP
|
|
self.sasSequence = Sequence.RNS_UD_SAS_DEL
|
|
self.kbdLayout = KeyboardLayout.FRENCH
|
|
self.clientBuild = UInt32Le(3790)
|
|
self.clientName = UniString("rdpy" + "\x00"*11, readLen = UInt8(30))
|
|
self.keyboardType = KeyboardType.IBM_101_102_KEYS
|
|
self.keyboardSubType = UInt32Le(0)
|
|
self.keyboardFnKeys = UInt32Le(12)
|
|
self.imeFileName = String("\x00"*64, readLen = UInt8(64))
|
|
self.postBeta2ColorDepth = ColorDepth.RNS_UD_COLOR_8BPP
|
|
self.clientProductId = UInt16Le(1)
|
|
self.serialNumber = UInt32Le(0)
|
|
self.highColorDepth = HighColor.HIGH_COLOR_24BPP
|
|
self.supportedColorDepths = Support.RNS_UD_24BPP_SUPPORT | Support.RNS_UD_16BPP_SUPPORT | Support.RNS_UD_15BPP_SUPPORT
|
|
self.earlyCapabilityFlags = CapabilityFlags.RNS_UD_CS_SUPPORT_ERRINFO_PDU
|
|
self.clientDigProductId = String("\x00"*64, readLen = UInt8(64))
|
|
self.connectionType = UInt8()
|
|
self.pad1octet = UInt8()
|
|
self.serverSelectedProtocol = UInt32Le()
|
|
|
|
class ServerCoreSettings(CompositeType):
|
|
'''
|
|
server side core settings structure
|
|
@see: http://msdn.microsoft.com/en-us/library/cc240517.aspx
|
|
'''
|
|
def __init__(self):
|
|
CompositeType.__init__(self)
|
|
self.rdpVersion = Version.RDP_VERSION_5_PLUS
|
|
self.clientRequestedProtocol = UInt32Le()
|
|
|
|
class ClientSecuritySettings(CompositeType):
|
|
'''
|
|
client security setting
|
|
@deprecated: because we use ssl
|
|
@see: http://msdn.microsoft.com/en-us/library/cc240511.aspx
|
|
'''
|
|
def __init__(self):
|
|
CompositeType.__init__(self)
|
|
self.encryptionMethods = UInt32Le()
|
|
self.extEncryptionMethods = UInt32Le()
|
|
|
|
class ServerSecuritySettings(CompositeType):
|
|
'''
|
|
server security settings
|
|
may be ignore because rdpy don't use
|
|
RDP security level
|
|
@deprecated: because we use ssl
|
|
@see: http://msdn.microsoft.com/en-us/library/cc240518.aspx
|
|
'''
|
|
def __init__(self):
|
|
CompositeType.__init__(self)
|
|
self.encryptionMethod = UInt32Le()
|
|
self.encryptionLevel = UInt32Le()
|
|
|
|
|
|
class ClientRequestedChannel(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()):
|
|
CompositeType.__init__(self)
|
|
#name of channel
|
|
self.name = String(name[0:8] + "\x00" * (8 - len(name)), readLen = UInt8(8))
|
|
#unknown
|
|
self.options = options
|
|
|
|
class ClientSettings(object):
|
|
'''
|
|
class which group all client settings supported by RDPY
|
|
'''
|
|
def __init__(self):
|
|
self.core = ClientCoreSettings()
|
|
#list of ClientRequestedChannel read network gcc packet
|
|
self.networkChannels = []
|
|
self.security = ClientSecuritySettings()
|
|
|
|
class ServerSettings(object):
|
|
'''
|
|
server settings
|
|
'''
|
|
def __init__(self):
|
|
#core settings of server
|
|
self.core = ServerCoreSettings()
|
|
#unuse security informations
|
|
self.security = ServerSecuritySettings()
|
|
#channel id accepted by server
|
|
self.channelsId = []
|
|
|
|
def writeConferenceCreateRequest(settings):
|
|
'''
|
|
write conference create request structure
|
|
@param settings: ClientSettings
|
|
@return: struct that represent
|
|
'''
|
|
userData = writeClientDataBlocks(settings)
|
|
userDataStream = Stream()
|
|
userDataStream.writeType(userData)
|
|
|
|
return (per.writeChoice(0), per.writeObjectIdentifier(t124_02_98_oid),
|
|
per.writeLength(len(userDataStream.getvalue()) + 14), per.writeChoice(0),
|
|
per.writeSelection(0x08), per.writeNumericString("1", 1), per.writePadding(1),
|
|
per.writeNumberOfSet(1), per.writeChoice(0xc0),
|
|
per.writeOctetStream(h221_cs_key, 4), per.writeOctetStream(userDataStream.getvalue()))
|
|
|
|
def readConferenceCreateResponse(s):
|
|
'''
|
|
read response from server
|
|
and return server settings read from this response
|
|
@param s: Stream
|
|
@return: ServerSettings
|
|
'''
|
|
per.readChoice(s)
|
|
per.readObjectIdentifier(s, t124_02_98_oid)
|
|
per.readLength(s)
|
|
per.readChoice(s)
|
|
per.readInteger16(s, 1001)
|
|
per.readInteger(s)
|
|
per.readEnumerates(s)
|
|
per.readNumberOfSet(s)
|
|
per.readChoice(s)
|
|
if not per.readOctetStream(s, h221_sc_key, 4):
|
|
raise InvalidExpectedDataException("cannot read h221_sc_key")
|
|
return readServerDataBlocks(s)
|
|
|
|
|
|
def writeClientDataBlocks(settings):
|
|
'''
|
|
write all blocks for client
|
|
and return gcc valid structure
|
|
@param settings: ClientSettings
|
|
'''
|
|
return (writeClientCoreData(settings.core),
|
|
writeClientSecurityData(settings.security),
|
|
writeClientNetworkData(settings.networkChannels))
|
|
|
|
def readServerDataBlocks(s):
|
|
'''
|
|
read gcc server data blocks
|
|
and return result in Server Settings object
|
|
@param s: Stream
|
|
@return: ServerSettings
|
|
'''
|
|
settings = ServerSettings()
|
|
length = per.readLength(s)
|
|
while length > 0:
|
|
marker = s.readLen()
|
|
blockType = UInt16Le()
|
|
blockLength = UInt16Le()
|
|
s.readType((blockType, blockLength))
|
|
#read core block
|
|
if blockType == ServerToClientMessage.SC_CORE:
|
|
s.readType(settings.core)
|
|
#read network block
|
|
elif blockType == ServerToClientMessage.SC_NET:
|
|
settings.channelsId = readServerSecurityData(s)
|
|
#read security block
|
|
#unused in rdpy because use SSL layer
|
|
elif blockType == ServerToClientMessage.SC_SECURITY:
|
|
s.readType(settings.security)
|
|
else:
|
|
print "Unknow server block %s"%hex(type)
|
|
length -= blockLength.value
|
|
s.seek(marker + blockLength.value)
|
|
|
|
return settings
|
|
|
|
def writeClientCoreData(core):
|
|
'''
|
|
write client settings in GCC language
|
|
@param settings: ClientSettings structure
|
|
@return: structure that represent client data blocks
|
|
'''
|
|
return (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 (ClientToServerMessage.CS_SECURITY, UInt16Le(sizeof(security) + 4), security)
|
|
|
|
def writeClientNetworkData(channels):
|
|
'''
|
|
write network packet whith channels infos
|
|
@param channels: list of ClientRequestedChannel
|
|
@return: gcc network packet
|
|
'''
|
|
if len(channels) == 0:
|
|
return ()
|
|
return (ClientToServerMessage.CS_NET, UInt16Le(len(channels) * sizeof(ClientRequestedChannel()) + 8), UInt32Le(len(channels)), tuple(channels))
|
|
|
|
def readServerSecurityData(s):
|
|
'''
|
|
read server security and fill it in settings
|
|
read all channels accepted by server by server
|
|
@param s: Stream
|
|
@return: list of channel id selected by server
|
|
@see: http://msdn.microsoft.com/en-us/library/cc240522.aspx
|
|
'''
|
|
channelsId = []
|
|
channelId = UInt16Le()
|
|
numberOfChannels = UInt16Le()
|
|
s.readType((channelId, numberOfChannels))
|
|
for i in range(0, numberOfChannels.value):
|
|
channelId = UInt16Le()
|
|
s.readType(channelId)
|
|
channelsId.append(channelId)
|
|
return channelsId
|
|
|