add string readlen arg to avoid recurcive loop

This commit is contained in:
speyrefitte
2013-12-10 12:06:23 +01:00
parent e32def4f50
commit fcf853e823
6 changed files with 238 additions and 47 deletions

View File

@@ -5,12 +5,15 @@
import struct import struct
from copy import deepcopy from copy import deepcopy
from StringIO import StringIO from StringIO import StringIO
from error import InvalidValue, InvalidSize from error import InvalidValue
from rdpy.protocol.network.error import InvalidExpectedDataException from rdpy.protocol.network.error import InvalidExpectedDataException
def sizeof(element): def sizeof(element):
''' '''
byte size of type byte size of type
sum sizeof of tuple element
and count only element that condition
is true at sizeof call
@param element: Type or Tuple(Type | Tuple,) @param element: Type or Tuple(Type | Tuple,)
@return: size of element in byte @return: size of element in byte
''' '''
@@ -26,18 +29,31 @@ def sizeof(element):
class Type(object): class Type(object):
''' '''
root type root type object inheritance
record conditional optional of constant
mechanism
''' '''
def __init__(self, conditional = lambda:True, optional = False, constant = False): def __init__(self, conditional = lambda:True, optional = False, constant = False):
'''
constructor of any type object
@param conditional : function call before read or write type
@param optional: boolean check before read if there is still data in stream
@param constant: if true check any changement of object during reading
'''
self._conditional = conditional self._conditional = conditional
self._optional = optional self._optional = optional
self._constant = constant self._constant = constant
self._is_writed = False #use to record read state
#if type is optional and not present during read
#this boolean stay false
self._is_readed = False self._is_readed = False
#use to know if type was written
self._is_writed = False
def write(self, s): def write(self, s):
''' '''
interface definition of write function write type into stream if conditional is true
and call private
@param s: Stream which will be written @param s: Stream which will be written
''' '''
self._is_writed = self._conditional() self._is_writed = self._conditional()
@@ -47,7 +63,8 @@ class Type(object):
def read(self, s): def read(self, s):
''' '''
interface definition of read value read type from stream s if conditional
is true and check constantness
@param s: Stream @param s: Stream
''' '''
self._is_readed = self._conditional() self._is_readed = self._conditional()
@@ -58,6 +75,20 @@ class Type(object):
#check constant value #check constant value
if self._constant and old != self: if self._constant and old != self:
raise InvalidExpectedDataException("const value expected") raise InvalidExpectedDataException("const value expected")
def __read__(self, s):
'''
interface definition of private read funtion
@param s: Stream
'''
pass
def __write__(self, s):
'''
interface definition of private write funtion
@param s: Stream
'''
pass
def __sizeof__(self): def __sizeof__(self):
''' '''
@@ -68,27 +99,33 @@ class Type(object):
class CallableValue(object): class CallableValue(object):
''' '''
type that wrap an inner type wrap access of callable value.
acces with value getter and setter When use getter value is call.
value can be a callable which is call Constant value can also be wrap
at each access of value and will be transformed into callable value(lambda function)
''' '''
def __init__(self, value): def __init__(self, value):
'''
construtor
@param value: value will be wrapped (constant | lambda | function)
'''
self._value = None self._value = None
self.value = value self.value = value
def __getValue__(self): def __getValue__(self):
''' '''
shortcut to access inner value can be overwritten to add specific check before
call lambda value self.value is call
@return: inner value(python type value) @return: result of callbale value
''' '''
return self._value() return self._value()
def __setValue__(self, value): def __setValue__(self, value):
''' '''
setter of value wrap in lambda value can be overwritten to add specific check before
@param value: new value encompass in valuetype object self.value = value is call
check if value is callable and if not transform it
@param value: new value wrapped if constant -> lambda function
''' '''
value_callable = lambda:value value_callable = lambda:value
if callable(value): if callable(value):
@@ -100,7 +137,8 @@ class CallableValue(object):
def value(self): def value(self):
''' '''
shortcut to access inner value shortcut to access inner value
@return: inner value(python type value) main getter of value
@return: result of callable value
''' '''
return self.__getValue__() return self.__getValue__()
@@ -108,6 +146,7 @@ class CallableValue(object):
def value(self, value): def value(self, value):
''' '''
setter of value after check it setter of value after check it
main setter of value
@param value: new value encompass in valuetype object @param value: new value encompass in valuetype object
''' '''
self.__setValue__(value) self.__setValue__(value)
@@ -122,7 +161,10 @@ class SimpleType(Type, CallableValue):
@param structFormat: letter that represent type in struct package @param structFormat: letter that represent type in struct package
@param typeSize: size in byte of type @param typeSize: size in byte of type
@param signed: true if type represent a signed type @param signed: true if type represent a signed type
@param value: value recorded in this object @param value: value recorded in this object (can be callable value which be call when is acces usefull with closure)
@param conditional : function call before read or write type
@param optional: boolean check before read if there is still data in stream
@param constant: if true check any changement of object during reading
''' '''
self._signed = signed self._signed = signed
self._typeSize = typeSize self._typeSize = typeSize
@@ -132,8 +174,10 @@ class SimpleType(Type, CallableValue):
def __getValue__(self): def __getValue__(self):
''' '''
shortcut to access inner value CallableValue overwrite
@return: inner value(python type value) check mask type of value
use CallableValue access
@return: python value wrap into type
@raise InvalidValue: if value doesn't respect type range @raise InvalidValue: if value doesn't respect type range
''' '''
value = CallableValue.__getValue__(self) value = CallableValue.__getValue__(self)
@@ -147,8 +191,9 @@ class SimpleType(Type, CallableValue):
def __setValue__(self, value): def __setValue__(self, value):
''' '''
setter of value after check it CallableValue overwrite
@param value: new value encompass in simpletype object check mask type of value
@param value: new value encompass in object (respect python type | lambda | function)
@raise InvalidValue: if value doesn't respect type range @raise InvalidValue: if value doesn't respect type range
''' '''
#check static value range #check static value range
@@ -304,6 +349,9 @@ class CompositeType(Type):
''' '''
keep ordering declaration of simple type keep ordering declaration of simple type
in list and transparent for other type in list and transparent for other type
@param conditional : function call before read or write type
@param optional: boolean check before read if there is still data in stream
@param constant: if true check any changement of object during reading
''' '''
def __init__(self, conditional = lambda:True, optional = False, constant = False): def __init__(self, conditional = lambda:True, optional = False, constant = False):
''' '''
@@ -376,6 +424,13 @@ class UInt8(SimpleType):
unsigned byte unsigned byte
''' '''
def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False): def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False):
'''
constructor
@param value: python value wrap
@param conditional : function call before read or write type
@param optional: boolean check before read if there is still data in stream
@param constant: if true check any changement of object during reading
'''
SimpleType.__init__(self, "B", 1, False, value, conditional = conditional, optional = optional, constant = constant) SimpleType.__init__(self, "B", 1, False, value, conditional = conditional, optional = optional, constant = constant)
class SInt8(SimpleType): class SInt8(SimpleType):
@@ -383,6 +438,12 @@ class SInt8(SimpleType):
signed byte signed byte
''' '''
def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False): def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False):
'''
constructor
@param conditional : function call before read or write type
@param optional: boolean check before read if there is still data in stream
@param constant: if true check any changement of object during reading
'''
SimpleType.__init__(self, "b", 1, True, value, conditional = conditional, optional = optional, constant = constant) SimpleType.__init__(self, "b", 1, True, value, conditional = conditional, optional = optional, constant = constant)
@@ -393,6 +454,12 @@ class UInt16Be(SimpleType):
Big endian is just for read or write in stream Big endian is just for read or write in stream
''' '''
def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False): def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False):
'''
constructor
@param conditional : function call before read or write type
@param optional: boolean check before read if there is still data in stream
@param constant: if true check any changement of object during reading
'''
SimpleType.__init__(self, ">H", 2, False, value, conditional = conditional, optional = optional, constant = constant) SimpleType.__init__(self, ">H", 2, False, value, conditional = conditional, optional = optional, constant = constant)
class UInt16Le(SimpleType): class UInt16Le(SimpleType):
@@ -402,6 +469,12 @@ class UInt16Le(SimpleType):
Big endian is just for read or write in stream Big endian is just for read or write in stream
''' '''
def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False): def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False):
'''
constructor
@param conditional : function call before read or write type
@param optional: boolean check before read if there is still data in stream
@param constant: if true check any changement of object during reading
'''
SimpleType.__init__(self, "<H", 2, False, value, conditional = conditional, optional = optional, constant = constant) SimpleType.__init__(self, "<H", 2, False, value, conditional = conditional, optional = optional, constant = constant)
class UInt32Be(SimpleType): class UInt32Be(SimpleType):
@@ -411,6 +484,12 @@ class UInt32Be(SimpleType):
Big endian is just for read or write in stream Big endian is just for read or write in stream
''' '''
def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False): def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False):
'''
constructor
@param conditional : function call before read or write type
@param optional: boolean check before read if there is still data in stream
@param constant: if true check any changement of object during reading
'''
SimpleType.__init__(self, ">I", 4, False, value, conditional = conditional, optional = optional, constant = constant) SimpleType.__init__(self, ">I", 4, False, value, conditional = conditional, optional = optional, constant = constant)
class UInt32Le(SimpleType): class UInt32Le(SimpleType):
@@ -420,6 +499,12 @@ class UInt32Le(SimpleType):
Big endian is just for read or write in stream Big endian is just for read or write in stream
''' '''
def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False): def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False):
'''
constructor
@param conditional : function call before read or write type
@param optional: boolean check before read if there is still data in stream
@param constant: if true check any changement of object during reading
'''
SimpleType.__init__(self, "<I", 4, False, value, conditional = conditional, optional = optional, constant = constant) SimpleType.__init__(self, "<I", 4, False, value, conditional = conditional, optional = optional, constant = constant)
class SInt32Le(SimpleType): class SInt32Le(SimpleType):
@@ -429,6 +514,12 @@ class SInt32Le(SimpleType):
Big endian is just for read or write in stream Big endian is just for read or write in stream
''' '''
def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False): def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False):
'''
constructor
@param conditional : function call before read or write type
@param optional: boolean check before read if there is still data in stream
@param constant: if true check any changement of object during reading
'''
SimpleType.__init__(self, "<I", 4, True, value, conditional = conditional, optional = optional, constant = constant) SimpleType.__init__(self, "<I", 4, True, value, conditional = conditional, optional = optional, constant = constant)
class SInt32Be(SimpleType): class SInt32Be(SimpleType):
@@ -438,6 +529,12 @@ class SInt32Be(SimpleType):
Big endian is just for read or write in stream Big endian is just for read or write in stream
''' '''
def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False): def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False):
'''
constructor
@param conditional : function call before read or write type
@param optional: boolean check before read if there is still data in stream
@param constant: if true check any changement of object during reading
'''
SimpleType.__init__(self, ">I", 4, True, value, conditional = conditional, optional = optional, constant = constant) SimpleType.__init__(self, ">I", 4, True, value, conditional = conditional, optional = optional, constant = constant)
class UInt24Be(SimpleType): class UInt24Be(SimpleType):
@@ -447,6 +544,12 @@ class UInt24Be(SimpleType):
Big endian is just for read or write in stream Big endian is just for read or write in stream
''' '''
def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False): def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False):
'''
constructor
@param conditional : function call before read or write type
@param optional: boolean check before read if there is still data in stream
@param constant: if true check any changement of object during reading
'''
SimpleType.__init__(self, ">I", 3, False, value, conditional = conditional, optional = optional, constant = constant) SimpleType.__init__(self, ">I", 3, False, value, conditional = conditional, optional = optional, constant = constant)
def __write__(self, s): def __write__(self, s):
@@ -462,6 +565,12 @@ class UInt24Le(SimpleType):
Big endian is just for read or write in stream Big endian is just for read or write in stream
''' '''
def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False): def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False):
'''
constructor
@param conditional : function call before read or write type
@param optional: boolean check before read if there is still data in stream
@param constant: if true check any changement of object during reading
'''
SimpleType.__init__(self, "<I", 3, False, value, conditional = conditional, optional = optional, constant = constant) SimpleType.__init__(self, "<I", 3, False, value, conditional = conditional, optional = optional, constant = constant)
def __write__(self, s): def __write__(self, s):
@@ -476,13 +585,19 @@ class String(Type, CallableValue):
''' '''
String network type String network type
''' '''
def __init__(self, value = "", conditional = lambda:True, optional = False, constant = False): def __init__(self, value = "", readLen = UInt32Le(), conditional = lambda:True, optional = False, constant = False):
''' '''
constructor with new string constructor with new string
@param value: python string use for inner value @param value: python string use for inner value
@param readLen: length use to read in stream (SimpleType) if 0 read entire stream
@param conditional : function call before read or write type
@param optional: boolean check before read if there is still data in stream
@param constant: if true check any changement of object during reading
''' '''
Type.__init__(self, conditional = conditional, optional = optional, constant = constant) Type.__init__(self, conditional = conditional, optional = optional, constant = constant)
CallableValue.__init__(self, value) CallableValue.__init__(self, value)
#type use to know read length
self._readLen = readLen
def __eq__(self, other): def __eq__(self, other):
''' '''
@@ -519,10 +634,10 @@ class String(Type, CallableValue):
else read the len of inner string else read the len of inner string
@param s: Stream @param s: Stream
''' '''
if len(self.value) == 0: if self._readLen.value == 0:
self.value = s.getvalue() self.value = s.getvalue()
else: else:
self.value = s.read(len(self.value)) self.value = s.read(self._readLen.value)
def __sizeof__(self): def __sizeof__(self):
''' '''
@@ -579,13 +694,16 @@ class Stream(StringIO):
or iterate over tuple elements or iterate over tuple elements
@param value: (tuple | Type) object @param value: (tuple | Type) object
''' '''
if sizeof(value) > self.dataLen() and not value._optional:
raise InvalidSize("stream is too short to read non optional value")
#read each tuple #read each tuple
if isinstance(value, tuple): if isinstance(value, tuple):
for element in value: for element in value:
self.readType(element) self.readType(element)
return return
#optional value not present
if self.dataLen() == 0 and value._optional:
return
value.read(self) value.read(self)
def readNextType(self, t): def readNextType(self, t):

View File

@@ -18,6 +18,7 @@ class ServerToClientMessage(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
''' '''
SC_CORE = 0x0C01 SC_CORE = 0x0C01
SC_SECURITY = 0x0C02 SC_SECURITY = 0x0C02
@@ -29,6 +30,7 @@ class ClientToServerMessage(object):
''' '''
Client to Server block Client to Server block
gcc conference messages 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
@@ -41,6 +43,7 @@ class ClientToServerMessage(object):
class ColorDepth(object): class ColorDepth(object):
''' '''
depth color depth color
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
''' '''
RNS_UD_COLOR_8BPP = 0xCA01 RNS_UD_COLOR_8BPP = 0xCA01
RNS_UD_COLOR_16BPP_555 = 0xCA02 RNS_UD_COLOR_16BPP_555 = 0xCA02
@@ -52,6 +55,7 @@ class ColorDepth(object):
class HighColor(object): class HighColor(object):
''' '''
high color of client high color of client
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
''' '''
HIGH_COLOR_4BPP = 0x0004 HIGH_COLOR_4BPP = 0x0004
HIGH_COLOR_8BPP = 0x0008 HIGH_COLOR_8BPP = 0x0008
@@ -64,6 +68,7 @@ class HighColor(object):
class Support(object): class Support(object):
''' '''
support depth flag support depth flag
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
''' '''
RNS_UD_24BPP_SUPPORT = 0x0001 RNS_UD_24BPP_SUPPORT = 0x0001
RNS_UD_16BPP_SUPPORT = 0x0002 RNS_UD_16BPP_SUPPORT = 0x0002
@@ -74,8 +79,8 @@ class Support(object):
@TypeAttributes(UInt16Le) @TypeAttributes(UInt16Le)
class CapabilityFlags(object): class CapabilityFlags(object):
''' '''
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
for more details on each flags click above 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_SUPPORT_ERRINFO_PDU = 0x0001
RNS_UD_CS_WANT_32BPP_SESSION = 0x0002 RNS_UD_CS_WANT_32BPP_SESSION = 0x0002
@@ -110,6 +115,7 @@ class ConnectionType(object):
class Version(object): class Version(object):
''' '''
supported version of RDP supported version of RDP
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
''' '''
RDP_VERSION_4 = 0x00080001 RDP_VERSION_4 = 0x00080001
RDP_VERSION_5_PLUS = 0x00080004 RDP_VERSION_5_PLUS = 0x00080004
@@ -125,6 +131,7 @@ class Encryption(object):
''' '''
encryption method supported encryption method supported
@deprecated: because rdpy use ssl but need to send to server... @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_40BIT = 0x00000001
ENCRYPTION_FLAG_128BIT = 0x00000002 ENCRYPTION_FLAG_128BIT = 0x00000002
@@ -153,6 +160,7 @@ class ChannelOptions(object):
class ClientCoreSettings(CompositeType): class ClientCoreSettings(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
''' '''
def __init__(self): def __init__(self):
CompositeType.__init__(self) CompositeType.__init__(self)
@@ -163,18 +171,18 @@ class ClientCoreSettings(CompositeType):
self.sasSequence = Sequence.RNS_UD_SAS_DEL self.sasSequence = Sequence.RNS_UD_SAS_DEL
self.kbdLayout = UInt32Le(0x409) self.kbdLayout = UInt32Le(0x409)
self.clientBuild = UInt32Le(3790) self.clientBuild = UInt32Le(3790)
self.clientName = UniString("rdpy" + "\x00"*11) self.clientName = UniString("rdpy" + "\x00"*11, readLen = UInt8(30))
self.keyboardType = UInt32Le(4) self.keyboardType = UInt32Le(4)
self.keyboardSubType = UInt32Le(0) self.keyboardSubType = UInt32Le(0)
self.keyboardFnKeys = UInt32Le(12) self.keyboardFnKeys = UInt32Le(12)
self.imeFileName = String("\x00"*64) self.imeFileName = String("\x00"*64, readLen = UInt8(64))
self.postBeta2ColorDepth = ColorDepth.RNS_UD_COLOR_8BPP self.postBeta2ColorDepth = ColorDepth.RNS_UD_COLOR_8BPP
self.clientProductId = UInt16Le(1) self.clientProductId = UInt16Le(1)
self.serialNumber = UInt32Le(0) self.serialNumber = UInt32Le(0)
self.highColorDepth = HighColor.HIGH_COLOR_24BPP self.highColorDepth = HighColor.HIGH_COLOR_24BPP
self.supportedColorDepths = Support.RNS_UD_24BPP_SUPPORT | Support.RNS_UD_16BPP_SUPPORT | Support.RNS_UD_15BPP_SUPPORT 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.earlyCapabilityFlags = CapabilityFlags.RNS_UD_CS_SUPPORT_ERRINFO_PDU
self.clientDigProductId = String("\x00"*64) self.clientDigProductId = String("\x00"*64, readLen = UInt8(64))
self.connectionType = UInt8() self.connectionType = UInt8()
self.pad1octet = UInt8() self.pad1octet = UInt8()
self.serverSelectedProtocol = UInt32Le() self.serverSelectedProtocol = UInt32Le()
@@ -182,6 +190,7 @@ class ClientCoreSettings(CompositeType):
class ServerCoreSettings(CompositeType): class ServerCoreSettings(CompositeType):
''' '''
server side core settings structure server side core settings structure
@see: http://msdn.microsoft.com/en-us/library/cc240517.aspx
''' '''
def __init__(self): def __init__(self):
CompositeType.__init__(self) CompositeType.__init__(self)
@@ -192,6 +201,7 @@ class ClientSecuritySettings(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
''' '''
def __init__(self): def __init__(self):
CompositeType.__init__(self) CompositeType.__init__(self)
@@ -204,6 +214,7 @@ class ServerSecuritySettings(CompositeType):
may be ignore because rdpy don't use may be ignore because rdpy don't use
RDP security level RDP security level
@deprecated: because we use ssl @deprecated: because we use ssl
@see: http://msdn.microsoft.com/en-us/library/cc240518.aspx
''' '''
def __init__(self): def __init__(self):
CompositeType.__init__(self) CompositeType.__init__(self)
@@ -215,11 +226,13 @@ class ClientRequestedChannel(CompositeType):
''' '''
channels structure share between channels structure share between
client and server 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 = UInt32Le()):
CompositeType.__init__(self) CompositeType.__init__(self)
#name of channel #name of channel
self.name = String(name[0:8] + "\x00" * (8 - len(name))) self.name = String(name[0:8] + "\x00" * (8 - len(name)), readLen = UInt8(8))
#unknown #unknown
self.options = options self.options = options
@@ -355,6 +368,7 @@ def readServerSecurityData(s):
read all channels accepted by server by server read all channels accepted by server by server
@param s: Stream @param s: Stream
@return: list of channel id selected by server @return: list of channel id selected by server
@see: http://msdn.microsoft.com/en-us/library/cc240522.aspx
''' '''
channelsId = [] channelsId = []
channelId = UInt16Le() channelId = UInt16Le()

View File

@@ -8,6 +8,7 @@ from rdpy.utils.const import ConstAttributes, TypeAttributes
from rdpy.protocol.network.error import InvalidExpectedDataException from rdpy.protocol.network.error import InvalidExpectedDataException
import gcc import gcc
import lic
@ConstAttributes @ConstAttributes
@TypeAttributes(UInt16Le) @TypeAttributes(UInt16Le)
@@ -70,7 +71,7 @@ class RDPInfo(CompositeType):
client informations client informations
contains credentials (very important packet) contains credentials (very important packet)
''' '''
def __init__(self, initForWrite, extendedInfoConditional): def __init__(self, extendedInfoConditional):
CompositeType.__init__(self) CompositeType.__init__(self)
#code page #code page
self.codePage = UInt32Le() self.codePage = UInt32Le()
@@ -86,37 +87,36 @@ class RDPInfo(CompositeType):
self.cbAlternateShell = UInt16Le(lambda:sizeof(self.alternateShell) - 2) self.cbAlternateShell = UInt16Le(lambda:sizeof(self.alternateShell) - 2)
#length of working directory unistring less 2 byte null terminate #length of working directory unistring less 2 byte null terminate
self.cbWorkingDir = UInt16Le(lambda:sizeof(self.workingDir) - 2) self.cbWorkingDir = UInt16Le(lambda:sizeof(self.workingDir) - 2)
#to avoid recurcive loop init differ from reading and writing
#microsoft domain #microsoft domain
self.domain = UniString("" if initForWrite else lambda:"\x00" * self.cbDomain.value) self.domain = UniString(readLen = self.cbDomain)
#session username #session username
self.userName = UniString("" if initForWrite else lambda:"\x00" * self.cbUserName.value) self.userName = UniString(readLen = self.cbUserName)
#associate password #associate password
self.password = UniString("" if initForWrite else lambda:"\x00" * self.cbPassword.value) self.password = UniString(readLen = self.cbPassword)
#shell execute at start of session #shell execute at start of session
self.alternateShell = UniString("" if initForWrite else lambda:"\x00" * self.cbAlternateShell.value) self.alternateShell = UniString(readLen = self.cbAlternateShell)
#working directory for session #working directory for session
self.workingDir = UniString("" if initForWrite else lambda:"\x00" * self.cbWorkingDir.value) self.workingDir = UniString(readLen = self.cbWorkingDir)
#more client informations #more client informations
self.extendedInfo = RDPExtendedInfo(initForWrite, conditional = extendedInfoConditional) self.extendedInfo = RDPExtendedInfo(conditional = extendedInfoConditional)
class RDPExtendedInfo(CompositeType): class RDPExtendedInfo(CompositeType):
''' '''
add more client informations add more client informations
use for performance flag!!! use for performance flag!!!
''' '''
def __init__(self, initForWrite, conditional): def __init__(self, conditional):
CompositeType.__init__(self, conditional = conditional) CompositeType.__init__(self, conditional = conditional)
#is an ip v4 or v6 adresse #is an ip v4 or v6 adresse
self.clientAddressFamily = AfInet.AF_INET self.clientAddressFamily = AfInet.AF_INET
#len of adress field #len of adress field
self.cbClientAddress = UInt16Le(lambda:sizeof(self.clientAddress)) self.cbClientAddress = UInt16Le(lambda:sizeof(self.clientAddress))
#adress of client #adress of client
self.clientAddress = UniString("" if initForWrite else lambda:"\x00" * self.cbClientAddress.value) self.clientAddress = UniString(readLen = self.cbClientAddress)
#len of client directory #len of client directory
self.cbClientDir = UInt16Le(lambda:sizeof(self.clientDir)) self.cbClientDir = UInt16Le(lambda:sizeof(self.clientDir))
#self client directory #self client directory
self.clientDir = UniString("" if initForWrite else lambda:"\x00" * self.cbClientDir.value) self.clientDir = UniString(readLen = self.cbClientDir)
#TODO make tiomezone #TODO make tiomezone
#self.performanceFlags = PerfFlag.PERF_DISABLE_WALLPAPER | PerfFlag.PERF_DISABLE_MENUANIMATIONS | PerfFlag.PERF_DISABLE_CURSOR_SHADOW #self.performanceFlags = PerfFlag.PERF_DISABLE_WALLPAPER | PerfFlag.PERF_DISABLE_MENUANIMATIONS | PerfFlag.PERF_DISABLE_CURSOR_SHADOW
@@ -134,7 +134,7 @@ class GDL(LayerAutomata):
#set by mcs layer channel init #set by mcs layer channel init
self._channelId = UInt16Be() self._channelId = UInt16Be()
#logon info send from client to server #logon info send from client to server
self._info = RDPInfo(initForWrite = True, extendedInfoConditional = lambda:self._transport._serverSettings.core.rdpVersion == gcc.Version.RDP_VERSION_5_PLUS) self._info = RDPInfo(extendedInfoConditional = lambda:self._transport._serverSettings.core.rdpVersion == gcc.Version.RDP_VERSION_5_PLUS)
def connect(self): def connect(self):
''' '''
@@ -147,7 +147,7 @@ class GDL(LayerAutomata):
def sendInfoPkt(self): def sendInfoPkt(self):
''' '''
send a logon info packet for RDP version 5 protocol send a logon info packet
''' '''
#always send extended info because rdpy only accept rdp version 5 and more #always send extended info because rdpy only accept rdp version 5 and more
self._transport.send(self._channelId, (SecurityFlag.SEC_INFO_PKT, UInt16Le(), self._info)) self._transport.send(self._channelId, (SecurityFlag.SEC_INFO_PKT, UInt16Le(), self._info))
@@ -158,4 +158,13 @@ class GDL(LayerAutomata):
data.readType((securityFlag, securityFlagHi)) data.readType((securityFlag, securityFlagHi))
if securityFlag & SecurityFlag.SEC_LICENSE_PKT != SecurityFlag.SEC_LICENSE_PKT: if securityFlag & SecurityFlag.SEC_LICENSE_PKT != SecurityFlag.SEC_LICENSE_PKT:
raise InvalidExpectedDataException("waiting license packet") raise InvalidExpectedDataException("waiting license packet")
validClientPdu = lic.LicPacket()
data.readType(validClientPdu)
if not validClientPdu.errorMessage._is_readed:
raise InvalidExpectedDataException("waiting valid client pdu : rdpy doesn't support licensing neg")
if not (validClientPdu.errorMessage.dwErrorCode == lic.ErrorCode.STATUS_VALID_CLIENT and validClientPdu.errorMessage.dwStateTransition == lic.StateTransition.ST_NO_TRANSITION):
raise InvalidExpectedDataException("server refuse licensing negotiation")

View File

@@ -1,12 +1,15 @@
''' '''
@author: sylvain @author: sylvain
''' '''
from rdpy.protocol.network.type import CompositeType, UInt8, UInt16Le, sizeof from rdpy.protocol.network.type import CompositeType, UInt8, UInt16Le, UInt32Le, String, sizeof
from rdpy.utils.const import ConstAttributes, TypeAttributes from rdpy.utils.const import ConstAttributes, TypeAttributes
@ConstAttributes @ConstAttributes
@TypeAttributes(UInt8) @TypeAttributes(UInt8)
class MessageType(object): class MessageType(object):
'''
License packet message type
'''
LICENSE_REQUEST = 0x01 LICENSE_REQUEST = 0x01
PLATFORM_CHALLENGE = 0x02 PLATFORM_CHALLENGE = 0x02
NEW_LICENSE = 0x03 NEW_LICENSE = 0x03
@@ -15,11 +18,54 @@ class MessageType(object):
NEW_LICENSE_REQUEST = 0x13 NEW_LICENSE_REQUEST = 0x13
PLATFORM_CHALLENGE_RESPONSE = 0x15 PLATFORM_CHALLENGE_RESPONSE = 0x15
ERROR_ALERT = 0xFF ERROR_ALERT = 0xFF
@ConstAttributes
@TypeAttributes(UInt32Le)
class ErrorCode(object):
'''
license error message code
'''
ERR_INVALID_SERVER_CERTIFICATE = 0x00000001
ERR_NO_LICENSE = 0x00000002
ERR_INVALID_SCOPE = 0x00000004
ERR_NO_LICENSE_SERVER = 0x00000006
STATUS_VALID_CLIENT = 0x00000007
ERR_INVALID_CLIENT = 0x00000008
ERR_INVALID_PRODUCTID = 0x0000000B
ERR_INVALID_MESSAGE_LEN = 0x0000000C
ERR_INVALID_MAC = 0x00000003
@ConstAttributes
@TypeAttributes(UInt32Le)
class StateTransition(object):
'''
automata state transition
'''
ST_TOTAL_ABORT = 0x00000001
ST_NO_TRANSITION = 0x00000002
ST_RESET_PHASE_TO_START = 0x00000003
ST_RESEND_LAST_MESSAGE = 0x00000004
class LicenceBinaryBlob(CompositeType):
def __init__(self):
CompositeType.__init__(self)
self.wBlobType = UInt16Le()
self.wBlobLen = UInt16Le(lambda:sizeof(self.blobData))
self.blobData = String(readLen = self.wBlobLen, conditional = lambda:self.wBlobLen.value > 0)
class LicensingErrorMessage(CompositeType):
def __init__(self, conditional = lambda:True):
CompositeType.__init__(self, conditional = conditional)
self.dwErrorCode = UInt32Le()
self.dwStateTransition = UInt32Le()
self.blob = LicenceBinaryBlob()
class LicPacket(CompositeType): class LicPacket(CompositeType):
def __init__(self): def __init__(self):
CompositeType.__init__(self)
#preambule #preambule
self.bMsgtype = UInt8() self.bMsgtype = UInt8()
self.flag = UInt8() self.flag = UInt8()
self.wMsgSize = UInt16Le(lambda: sizeof(self)) self.wMsgSize = UInt16Le(lambda: sizeof(self))
self.errorMessage = LicensingErrorMessage(conditional = lambda:self.bMsgtype == MessageType.ERROR_ALERT)

View File

@@ -77,6 +77,9 @@ class TPDUDataHeader(CompositeType):
class Negotiation(CompositeType): class Negotiation(CompositeType):
''' '''
negociation request message negociation request message
@see: request -> http://msdn.microsoft.com/en-us/library/cc240500.aspx
@see: response -> http://msdn.microsoft.com/en-us/library/cc240506.aspx
@see: failure ->http://msdn.microsoft.com/en-us/library/cc240507.aspx
''' '''
def __init__(self, optional = False): def __init__(self, optional = False):
CompositeType.__init__(self, optional = optional) CompositeType.__init__(self, optional = optional)
@@ -118,6 +121,8 @@ class TPDU(LayerAutomata):
next state is recvData next state is recvData
call connect on presentation layer if all is good call connect on presentation layer if all is good
@param data: Stream that contain connection confirm @param data: Stream that contain connection confirm
@see: response -> http://msdn.microsoft.com/en-us/library/cc240506.aspx
@see: failure ->http://msdn.microsoft.com/en-us/library/cc240507.aspx
''' '''
message = TPDUConnectMessage() message = TPDUConnectMessage()
data.readType(message) data.readType(message)
@@ -161,6 +166,7 @@ class TPDU(LayerAutomata):
''' '''
write connection request message write connection request message
next state is recvConnectionConfirm next state is recvConnectionConfirm
@see: http://msdn.microsoft.com/en-us/library/cc240500.aspx
''' '''
message = TPDUConnectMessage() message = TPDUConnectMessage()
message.code = MessageType.X224_TPDU_CONNECTION_REQUEST message.code = MessageType.X224_TPDU_CONNECTION_REQUEST

View File

@@ -134,8 +134,6 @@ class Rfb(RawLayer):
server imposed security level server imposed security level
''' '''
#TODO!!! #TODO!!!
self._version = data.read_beuint32()
def recvSecurityList(self, data): def recvSecurityList(self, data):
''' '''