pdu error handle
This commit is contained in:
@@ -55,4 +55,15 @@ class InvalidSize(Exception):
|
|||||||
constructor with message
|
constructor with message
|
||||||
@param message: message show when exception is raised
|
@param message: message show when exception is raised
|
||||||
'''
|
'''
|
||||||
Exception.__init__(self, message)
|
Exception.__init__(self, message)
|
||||||
|
|
||||||
|
class ErrorReportedFromPeer(Exception):
|
||||||
|
'''
|
||||||
|
raise when peer send an error
|
||||||
|
'''
|
||||||
|
def __init__(self, message = ""):
|
||||||
|
'''
|
||||||
|
constructor with message
|
||||||
|
@param message: message show when exception is raised
|
||||||
|
'''
|
||||||
|
Exception.__init__(self, message)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import struct
|
|||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from StringIO import StringIO
|
from StringIO import StringIO
|
||||||
from error import InvalidValue
|
from error import InvalidValue
|
||||||
from rdpy.network.error import InvalidExpectedDataException
|
from rdpy.network.error import InvalidExpectedDataException, InvalidSize
|
||||||
|
|
||||||
def sizeof(element):
|
def sizeof(element):
|
||||||
'''
|
'''
|
||||||
@@ -70,10 +70,19 @@ class Type(object):
|
|||||||
self._is_readed = self._conditional()
|
self._is_readed = self._conditional()
|
||||||
if not self._is_readed:
|
if not self._is_readed:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
#not constant mode direct reading
|
||||||
|
if not self._constant:
|
||||||
|
self.__read__(s)
|
||||||
|
return
|
||||||
|
|
||||||
|
#constant mode
|
||||||
old = deepcopy(self)
|
old = deepcopy(self)
|
||||||
self.__read__(s)
|
self.__read__(s)
|
||||||
#check constant value
|
#check constant value
|
||||||
if self._constant and old != self:
|
if old != self:
|
||||||
|
#rollback read value
|
||||||
|
s.pos -= sizeof(self)
|
||||||
raise InvalidExpectedDataException("%s const value expected %s != %s"%(self.__class__, old.value, self.value))
|
raise InvalidExpectedDataException("%s const value expected %s != %s"%(self.__class__, old.value, self.value))
|
||||||
|
|
||||||
def __read__(self, s):
|
def __read__(self, s):
|
||||||
@@ -229,7 +238,9 @@ class SimpleType(Type, CallableValue):
|
|||||||
use struct package
|
use struct package
|
||||||
@param s: Stream
|
@param s: Stream
|
||||||
'''
|
'''
|
||||||
self.value = struct.unpack(self._structFormat,s.read(self._typeSize))[0]
|
if s.dataLen() < self._typeSize:
|
||||||
|
raise InvalidSize("Stream is too small to read expected data")
|
||||||
|
self.value = struct.unpack(self._structFormat, s.read(self._typeSize))[0]
|
||||||
|
|
||||||
def mask(self):
|
def mask(self):
|
||||||
'''
|
'''
|
||||||
@@ -381,6 +392,11 @@ class CompositeType(Type):
|
|||||||
s.readType(self.__dict__[name])
|
s.readType(self.__dict__[name])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print "Error during read %s::%s"%(self.__class__, name)
|
print "Error during read %s::%s"%(self.__class__, name)
|
||||||
|
#rollback already readed
|
||||||
|
for tmpName in self._typeName:
|
||||||
|
if tmpName == name:
|
||||||
|
break
|
||||||
|
s.pos -= sizeof(self.__dict__[tmpName])
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
def __write__(self, s):
|
def __write__(self, s):
|
||||||
@@ -720,7 +736,15 @@ class Stream(StringIO):
|
|||||||
#read each tuple
|
#read each tuple
|
||||||
if isinstance(value, tuple) or isinstance(value, list):
|
if isinstance(value, tuple) or isinstance(value, list):
|
||||||
for element in value:
|
for element in value:
|
||||||
self.readType(element)
|
try:
|
||||||
|
self.readType(element)
|
||||||
|
except Exception as e:
|
||||||
|
#rollback already readed elements
|
||||||
|
for tmpElement in value:
|
||||||
|
if tmpElement == element:
|
||||||
|
break
|
||||||
|
self.pos -= sizeof(tmpElement)
|
||||||
|
raise e
|
||||||
return
|
return
|
||||||
|
|
||||||
#optional value not present
|
#optional value not present
|
||||||
@@ -760,6 +784,7 @@ class ArrayType(Type):
|
|||||||
'''
|
'''
|
||||||
constructor
|
constructor
|
||||||
@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 readLen: number of element in sequence
|
@param readLen: number of element in sequence
|
||||||
@param conditional : function call before read or write type
|
@param conditional : function call before read or write type
|
||||||
@param optional: boolean check before read if there is still data in stream
|
@param optional: boolean check before read if there is still data in stream
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
from rdpy.network.layer import LayerAutomata
|
from rdpy.network.layer import LayerAutomata
|
||||||
from rdpy.network.type import CompositeType, UniString, String, UInt8, UInt16Le, UInt16Be, UInt32Le, sizeof, ArrayType
|
from rdpy.network.type import CompositeType, UniString, String, UInt8, UInt16Le, UInt16Be, UInt32Le, sizeof, ArrayType
|
||||||
from rdpy.network.const import ConstAttributes, TypeAttributes
|
from rdpy.network.const import ConstAttributes, TypeAttributes
|
||||||
from rdpy.network.error import InvalidExpectedDataException
|
from rdpy.network.error import InvalidExpectedDataException, ErrorReportedFromPeer
|
||||||
|
|
||||||
import gcc
|
import gcc
|
||||||
import lic
|
import lic
|
||||||
@@ -286,11 +286,150 @@ class OrderEx(object):
|
|||||||
'''
|
'''
|
||||||
ORDERFLAGS_EX_CACHE_BITMAP_REV3_SUPPORT = 0x0002
|
ORDERFLAGS_EX_CACHE_BITMAP_REV3_SUPPORT = 0x0002
|
||||||
ORDERFLAGS_EX_ALTSEC_FRAME_MARKER_SUPPORT = 0x0004
|
ORDERFLAGS_EX_ALTSEC_FRAME_MARKER_SUPPORT = 0x0004
|
||||||
|
|
||||||
|
@ConstAttributes
|
||||||
|
@TypeAttributes(UInt16Le)
|
||||||
|
class Action(object):
|
||||||
|
'''
|
||||||
|
Action flag use in Control PDU packet
|
||||||
|
@see: http://msdn.microsoft.com/en-us/library/cc240492.aspx
|
||||||
|
'''
|
||||||
|
CTRLACTION_REQUEST_CONTROL = 0x0001
|
||||||
|
CTRLACTION_GRANTED_CONTROL = 0x0002
|
||||||
|
CTRLACTION_DETACH = 0x0003
|
||||||
|
CTRLACTION_COOPERATE = 0x0004
|
||||||
|
|
||||||
|
@ConstAttributes
|
||||||
|
@TypeAttributes(UInt16Le)
|
||||||
|
class PersistentKeyListFlag(object):
|
||||||
|
'''
|
||||||
|
use to determine the number of persistent key packet
|
||||||
|
@see: http://msdn.microsoft.com/en-us/library/cc240495.aspx
|
||||||
|
'''
|
||||||
|
PERSIST_FIRST_PDU = 0x01
|
||||||
|
PERSIST_LAST_PDU = 0x02
|
||||||
|
|
||||||
|
@ConstAttributes
|
||||||
|
@TypeAttributes(UInt32Le)
|
||||||
|
class ErrorInfo(object):
|
||||||
|
'''
|
||||||
|
Error code use in Error info pdu
|
||||||
|
@see: http://msdn.microsoft.com/en-us/library/cc240544.aspx
|
||||||
|
'''
|
||||||
|
ERRINFO_RPC_INITIATED_DISCONNECT = 0x00000001
|
||||||
|
ERRINFO_RPC_INITIATED_LOGOFF = 0x00000002
|
||||||
|
ERRINFO_IDLE_TIMEOUT = 0x00000003
|
||||||
|
ERRINFO_LOGON_TIMEOUT = 0x00000004
|
||||||
|
ERRINFO_DISCONNECTED_BY_OTHERCONNECTION = 0x00000005
|
||||||
|
ERRINFO_OUT_OF_MEMORY = 0x00000006
|
||||||
|
ERRINFO_SERVER_DENIED_CONNECTION = 0x00000007
|
||||||
|
ERRINFO_SERVER_INSUFFICIENT_PRIVILEGES = 0x00000009
|
||||||
|
ERRINFO_SERVER_FRESH_CREDENTIALS_REQUIRED = 0x0000000A
|
||||||
|
ERRINFO_RPC_INITIATED_DISCONNECT_BYUSER = 0x0000000B
|
||||||
|
ERRINFO_LOGOFF_BY_USER = 0x0000000C
|
||||||
|
ERRINFO_LICENSE_INTERNAL = 0x00000100
|
||||||
|
ERRINFO_LICENSE_NO_LICENSE_SERVER = 0x00000101
|
||||||
|
ERRINFO_LICENSE_NO_LICENSE = 0x00000102
|
||||||
|
ERRINFO_LICENSE_BAD_CLIENT_MSG = 0x00000103
|
||||||
|
ERRINFO_LICENSE_HWID_DOESNT_MATCH_LICENSE = 0x00000104
|
||||||
|
ERRINFO_LICENSE_BAD_CLIENT_LICENSE = 0x00000105
|
||||||
|
ERRINFO_LICENSE_CANT_FINISH_PROTOCOL = 0x00000106
|
||||||
|
ERRINFO_LICENSE_CLIENT_ENDED_PROTOCOL = 0x00000107
|
||||||
|
ERRINFO_LICENSE_BAD_CLIENT_ENCRYPTION = 0x00000108
|
||||||
|
ERRINFO_LICENSE_CANT_UPGRADE_LICENSE = 0x00000109
|
||||||
|
ERRINFO_LICENSE_NO_REMOTE_CONNECTIONS = 0x0000010A
|
||||||
|
ERRINFO_CB_DESTINATION_NOT_FOUND = 0x0000400
|
||||||
|
ERRINFO_CB_LOADING_DESTINATION = 0x0000402
|
||||||
|
ERRINFO_CB_REDIRECTING_TO_DESTINATION = 0x0000404
|
||||||
|
ERRINFO_CB_SESSION_ONLINE_VM_WAKE = 0x0000405
|
||||||
|
ERRINFO_CB_SESSION_ONLINE_VM_BOOT = 0x0000406
|
||||||
|
ERRINFO_CB_SESSION_ONLINE_VM_NO_DNS = 0x0000407
|
||||||
|
ERRINFO_CB_DESTINATION_POOL_NOT_FREE = 0x0000408
|
||||||
|
ERRINFO_CB_CONNECTION_CANCELLED = 0x0000409
|
||||||
|
ERRINFO_CB_CONNECTION_ERROR_INVALID_SETTINGS = 0x0000410
|
||||||
|
ERRINFO_CB_SESSION_ONLINE_VM_BOOT_TIMEOUT = 0x0000411
|
||||||
|
ERRINFO_CB_SESSION_ONLINE_VM_SESSMON_FAILED = 0x0000412
|
||||||
|
ERRINFO_UNKNOWNPDUTYPE2 = 0x000010C9
|
||||||
|
ERRINFO_UNKNOWNPDUTYPE = 0x000010CA
|
||||||
|
ERRINFO_DATAPDUSEQUENCE = 0x000010CB
|
||||||
|
ERRINFO_CONTROLPDUSEQUENCE = 0x000010CD
|
||||||
|
ERRINFO_INVALIDCONTROLPDUACTION = 0x000010CE
|
||||||
|
ERRINFO_INVALIDINPUTPDUTYPE = 0x000010CF
|
||||||
|
ERRINFO_INVALIDINPUTPDUMOUSE = 0x000010D0
|
||||||
|
ERRINFO_INVALIDREFRESHRECTPDU = 0x000010D1
|
||||||
|
ERRINFO_CREATEUSERDATAFAILED = 0x000010D2
|
||||||
|
ERRINFO_CONNECTFAILED =0x000010D3
|
||||||
|
ERRINFO_CONFIRMACTIVEWRONGSHAREID = 0x000010D4
|
||||||
|
ERRINFO_CONFIRMACTIVEWRONGORIGINATOR = 0x000010D5
|
||||||
|
ERRINFO_PERSISTENTKEYPDUBADLENGTH = 0x000010DA
|
||||||
|
ERRINFO_PERSISTENTKEYPDUILLEGALFIRST = 0x000010DB
|
||||||
|
ERRINFO_PERSISTENTKEYPDUTOOMANYTOTALKEYS = 0x000010DC
|
||||||
|
ERRINFO_PERSISTENTKEYPDUTOOMANYCACHEKEYS = 0x000010DD
|
||||||
|
ERRINFO_INPUTPDUBADLENGTH = 0x000010DE
|
||||||
|
ERRINFO_BITMAPCACHEERRORPDUBADLENGTH = 0x000010DF
|
||||||
|
ERRINFO_SECURITYDATATOOSHORT = 0x000010E0
|
||||||
|
ERRINFO_VCHANNELDATATOOSHORT = 0x000010E1
|
||||||
|
ERRINFO_SHAREDATATOOSHORT = 0x000010E2
|
||||||
|
ERRINFO_BADSUPRESSOUTPUTPDU = 0x000010E3
|
||||||
|
ERRINFO_CONFIRMACTIVEPDUTOOSHORT = 0x000010E5
|
||||||
|
ERRINFO_CAPABILITYSETTOOSMALL = 0x000010E7
|
||||||
|
ERRINFO_CAPABILITYSETTOOLARGE = 0x000010E8
|
||||||
|
ERRINFO_NOCURSORCACHE = 0x000010E9
|
||||||
|
ERRINFO_BADCAPABILITIES = 0x000010EA
|
||||||
|
ERRINFO_VIRTUALCHANNELDECOMPRESSIONERR = 0x000010EC
|
||||||
|
ERRINFO_INVALIDVCCOMPRESSIONTYPE = 0x000010ED
|
||||||
|
ERRINFO_INVALIDCHANNELID = 0x000010EF
|
||||||
|
ERRINFO_VCHANNELSTOOMANY = 0x000010F0
|
||||||
|
ERRINFO_REMOTEAPPSNOTENABLED = 0x000010F3
|
||||||
|
ERRINFO_CACHECAPNOTSET = 0x000010F4
|
||||||
|
ERRINFO_BITMAPCACHEERRORPDUBADLENGTH2 = 0x000010F5
|
||||||
|
ERRINFO_OFFSCRCACHEERRORPDUBADLENGTH = 0x000010F6
|
||||||
|
ERRINFO_DNGCACHEERRORPDUBADLENGTH = 0x000010F7
|
||||||
|
ERRINFO_GDIPLUSPDUBADLENGTH = 0x000010F8
|
||||||
|
ERRINFO_SECURITYDATATOOSHORT2 = 0x00001111
|
||||||
|
ERRINFO_SECURITYDATATOOSHORT3 = 0x00001112
|
||||||
|
ERRINFO_SECURITYDATATOOSHORT4 = 0x00001113
|
||||||
|
ERRINFO_SECURITYDATATOOSHORT5 = 0x00001114
|
||||||
|
ERRINFO_SECURITYDATATOOSHORT6 = 0x00001115
|
||||||
|
ERRINFO_SECURITYDATATOOSHORT7 = 0x00001116
|
||||||
|
ERRINFO_SECURITYDATATOOSHORT8 = 0x00001117
|
||||||
|
ERRINFO_SECURITYDATATOOSHORT9 = 0x00001118
|
||||||
|
ERRINFO_SECURITYDATATOOSHORT10 = 0x00001119
|
||||||
|
ERRINFO_SECURITYDATATOOSHORT11 = 0x0000111A
|
||||||
|
ERRINFO_SECURITYDATATOOSHORT12 = 0x0000111B
|
||||||
|
ERRINFO_SECURITYDATATOOSHORT13 = 0x0000111C
|
||||||
|
ERRINFO_SECURITYDATATOOSHORT14 = 0x0000111D
|
||||||
|
ERRINFO_SECURITYDATATOOSHORT15 = 0x0000111E
|
||||||
|
ERRINFO_SECURITYDATATOOSHORT16 = 0x0000111F
|
||||||
|
ERRINFO_SECURITYDATATOOSHORT17 = 0x00001120
|
||||||
|
ERRINFO_SECURITYDATATOOSHORT18 = 0x00001121
|
||||||
|
ERRINFO_SECURITYDATATOOSHORT19 = 0x00001122
|
||||||
|
ERRINFO_SECURITYDATATOOSHORT20 = 0x00001123
|
||||||
|
ERRINFO_SECURITYDATATOOSHORT21 = 0x00001124
|
||||||
|
ERRINFO_SECURITYDATATOOSHORT22 = 0x00001125
|
||||||
|
ERRINFO_SECURITYDATATOOSHORT23 = 0x00001126
|
||||||
|
ERRINFO_BADMONITORDATA = 0x00001129
|
||||||
|
ERRINFO_VCDECOMPRESSEDREASSEMBLEFAILED = 0x0000112A
|
||||||
|
ERRINFO_VCDATATOOLONG = 0x0000112B
|
||||||
|
ERRINFO_BAD_FRAME_ACK_DATA = 0x0000112C
|
||||||
|
ERRINFO_GRAPHICSMODENOTSUPPORTED = 0x0000112D
|
||||||
|
ERRINFO_GRAPHICSSUBSYSTEMRESETFAILED = 0x0000112E
|
||||||
|
ERRINFO_GRAPHICSSUBSYSTEMFAILED = 0x0000112F
|
||||||
|
ERRINFO_TIMEZONEKEYNAMELENGTHTOOSHORT = 0x00001130
|
||||||
|
ERRINFO_TIMEZONEKEYNAMELENGTHTOOLONG = 0x00001131
|
||||||
|
ERRINFO_DYNAMICDSTDISABLEDFIELDMISSING = 0x00001132
|
||||||
|
ERRINFO_VCDECODINGERROR = 0x00001133
|
||||||
|
ERRINFO_UPDATESESSIONKEYFAILED = 0x00001191
|
||||||
|
ERRINFO_DECRYPTFAILED = 0x00001192
|
||||||
|
ERRINFO_ENCRYPTFAILED = 0x00001193
|
||||||
|
ERRINFO_ENCPKGMISMATCH = 0x00001194
|
||||||
|
ERRINFO_DECRYPTFAILED2 = 0x00001195
|
||||||
|
|
||||||
class RDPInfo(CompositeType):
|
class RDPInfo(CompositeType):
|
||||||
'''
|
'''
|
||||||
client informations
|
client informations
|
||||||
contains credentials (very important packet)
|
contains credentials (very important packet)
|
||||||
|
@see: http://msdn.microsoft.com/en-us/library/cc240475.aspx
|
||||||
'''
|
'''
|
||||||
def __init__(self, extendedInfoConditional):
|
def __init__(self, extendedInfoConditional):
|
||||||
CompositeType.__init__(self)
|
CompositeType.__init__(self)
|
||||||
@@ -333,7 +472,7 @@ class ShareControlHeader(CompositeType):
|
|||||||
PDU share control header
|
PDU share control header
|
||||||
@see: http://msdn.microsoft.com/en-us/library/cc240576.aspx
|
@see: http://msdn.microsoft.com/en-us/library/cc240576.aspx
|
||||||
'''
|
'''
|
||||||
def __init__(self, totalLength, pduType):
|
def __init__(self, totalLength, pduType, userId):
|
||||||
'''
|
'''
|
||||||
constructor
|
constructor
|
||||||
@param totalLength: total length of pdu packet
|
@param totalLength: total length of pdu packet
|
||||||
@@ -342,16 +481,16 @@ class ShareControlHeader(CompositeType):
|
|||||||
#share control header
|
#share control header
|
||||||
self.totalLength = UInt16Le(totalLength)
|
self.totalLength = UInt16Le(totalLength)
|
||||||
self.pduType = UInt16Le(pduType.value, constant = True)
|
self.pduType = UInt16Le(pduType.value, constant = True)
|
||||||
self.PDUSource = UInt16Le()
|
self.PDUSource = UInt16Le(userId.value + 1001)
|
||||||
|
|
||||||
class SharedataHeader(CompositeType):
|
class ShareDataHeader(CompositeType):
|
||||||
'''
|
'''
|
||||||
PDU share data header
|
PDU share data header
|
||||||
@see: http://msdn.microsoft.com/en-us/library/cc240577.aspx
|
@see: http://msdn.microsoft.com/en-us/library/cc240577.aspx
|
||||||
'''
|
'''
|
||||||
def __init__(self, size, pduType, pduType2):
|
def __init__(self, size, pduType2, userId = UInt16Le()):
|
||||||
CompositeType.__init__(self)
|
CompositeType.__init__(self)
|
||||||
self.shareControlHeader = ShareControlHeader(size, pduType)
|
self.shareControlHeader = ShareControlHeader(size, PDUType.PDUTYPE_DATAPDU, userId)
|
||||||
self.shareId = UInt32Le()
|
self.shareId = UInt32Le()
|
||||||
self.pad1 = UInt8()
|
self.pad1 = UInt8()
|
||||||
self.streamId = UInt8()
|
self.streamId = UInt8()
|
||||||
@@ -428,7 +567,7 @@ class OrderCapability(CompositeType):
|
|||||||
self.pad2octetsA = UInt16Le(0)
|
self.pad2octetsA = UInt16Le(0)
|
||||||
self.maximumOrderLevel = UInt16Le(1)
|
self.maximumOrderLevel = UInt16Le(1)
|
||||||
self.numberFonts = UInt16Le(0)
|
self.numberFonts = UInt16Le(0)
|
||||||
self.orderFlags = UInt16Le(OrderFlag.NEGOTIATEORDERSUPPORT)
|
self.orderFlags = OrderFlag.NEGOTIATEORDERSUPPORT
|
||||||
self.orderSupport = ArrayType(UInt8, readLen = UInt8(32))
|
self.orderSupport = ArrayType(UInt8, readLen = UInt8(32))
|
||||||
self.textFlags = UInt16Le()
|
self.textFlags = UInt16Le()
|
||||||
self.orderSupportExFlags = UInt16Le()
|
self.orderSupportExFlags = UInt16Le()
|
||||||
@@ -444,9 +583,9 @@ class DemandActivePDU(CompositeType):
|
|||||||
@see: http://msdn.microsoft.com/en-us/library/cc240485.aspx
|
@see: http://msdn.microsoft.com/en-us/library/cc240485.aspx
|
||||||
main use for capabilities exchange server -> client
|
main use for capabilities exchange server -> client
|
||||||
'''
|
'''
|
||||||
def __init__(self):
|
def __init__(self, userId = UInt16Le()):
|
||||||
CompositeType.__init__(self)
|
CompositeType.__init__(self)
|
||||||
self.shareControlHeader = ShareControlHeader(lambda:sizeof(self), PDUType.PDUTYPE_DEMANDACTIVEPDU)
|
self.shareControlHeader = ShareControlHeader(lambda:sizeof(self), PDUType.PDUTYPE_DEMANDACTIVEPDU, userId)
|
||||||
self.shareId = UInt32Le()
|
self.shareId = UInt32Le()
|
||||||
self.lengthSourceDescriptor = UInt16Le(lambda:sizeof(self.sourceDescriptor))
|
self.lengthSourceDescriptor = UInt16Le(lambda:sizeof(self.sourceDescriptor))
|
||||||
self.lengthCombinedCapabilities = UInt16Le(lambda:(sizeof(self.numberCapabilities) + sizeof(self.pad2Octets) + sizeof(self.capabilitySets)))
|
self.lengthCombinedCapabilities = UInt16Le(lambda:(sizeof(self.numberCapabilities) + sizeof(self.pad2Octets) + sizeof(self.capabilitySets)))
|
||||||
@@ -461,9 +600,9 @@ class ConfirmActivePDU(CompositeType):
|
|||||||
@see: http://msdn.microsoft.com/en-us/library/cc240488.aspx
|
@see: http://msdn.microsoft.com/en-us/library/cc240488.aspx
|
||||||
main use for capabilities confirm client -> sever
|
main use for capabilities confirm client -> sever
|
||||||
'''
|
'''
|
||||||
def __init__(self):
|
def __init__(self, userId = UInt16Le()):
|
||||||
CompositeType.__init__(self)
|
CompositeType.__init__(self)
|
||||||
self.shareControlHeader = ShareControlHeader(lambda:sizeof(self), PDUType.PDUTYPE_CONFIRMACTIVEPDU)
|
self.shareControlHeader = ShareControlHeader(lambda:sizeof(self), PDUType.PDUTYPE_CONFIRMACTIVEPDU, userId)
|
||||||
self.shareId = UInt32Le()
|
self.shareId = UInt32Le()
|
||||||
self.originatorId = UInt16Le(0x03EA, constant = True)
|
self.originatorId = UInt16Le(0x03EA, constant = True)
|
||||||
self.lengthSourceDescriptor = UInt16Le(lambda:sizeof(self.sourceDescriptor))
|
self.lengthSourceDescriptor = UInt16Le(lambda:sizeof(self.sourceDescriptor))
|
||||||
@@ -477,11 +616,68 @@ class SynchronizePDU(CompositeType):
|
|||||||
'''
|
'''
|
||||||
@see http://msdn.microsoft.com/en-us/library/cc240490.aspx
|
@see http://msdn.microsoft.com/en-us/library/cc240490.aspx
|
||||||
'''
|
'''
|
||||||
def __init__(self):
|
def __init__(self, userId = UInt16Le()):
|
||||||
CompositeType.__init__(self)
|
CompositeType.__init__(self)
|
||||||
self.shareControlHeader = SharedataHeader(lambda:sizeof(self), PDUType.PDUTYPE_DATAPDU, PDUType2.PDUTYPE2_SYNCHRONIZE)
|
self.shareControlHeader = ShareDataHeader(lambda:sizeof(self), PDUType2.PDUTYPE2_SYNCHRONIZE, userId)
|
||||||
self.messageType = UInt16Le(1, constant = True)
|
self.messageType = UInt16Le(1, constant = True)
|
||||||
self.targetUser = UInt16Le()
|
self.targetUser = UInt16Le()
|
||||||
|
|
||||||
|
class ControlPDU(CompositeType):
|
||||||
|
'''
|
||||||
|
@see http://msdn.microsoft.com/en-us/library/cc240492.aspx
|
||||||
|
'''
|
||||||
|
def __init__(self, userId = UInt16Le()):
|
||||||
|
CompositeType.__init__(self)
|
||||||
|
self.shareControlHeader = ShareDataHeader(lambda:sizeof(self), PDUType2.PDUTYPE2_CONTROL, userId)
|
||||||
|
self.action = UInt16Le()
|
||||||
|
self.grantId = UInt16Le()
|
||||||
|
self.controlId = UInt32Le()
|
||||||
|
|
||||||
|
class PersistentListEntry(CompositeType):
|
||||||
|
'''
|
||||||
|
use to record persistent key in PersistentListPDU
|
||||||
|
@see: http://msdn.microsoft.com/en-us/library/cc240496.aspx
|
||||||
|
'''
|
||||||
|
def __init__(self):
|
||||||
|
CompositeType.__init__(self)
|
||||||
|
self.key1 = UInt32Le()
|
||||||
|
self.key2 = UInt32Le()
|
||||||
|
|
||||||
|
|
||||||
|
class PersistentListPDU(CompositeType):
|
||||||
|
'''
|
||||||
|
Use to indicate that bitmap cache was already
|
||||||
|
fill with some keys from previous session
|
||||||
|
@see: http://msdn.microsoft.com/en-us/library/cc240495.aspx
|
||||||
|
'''
|
||||||
|
def __init__(self, userId = UInt16Le()):
|
||||||
|
CompositeType.__init__(self)
|
||||||
|
self.shareControlHeader = ShareDataHeader(lambda:sizeof(self), PDUType2.PDUTYPE2_BITMAPCACHE_PERSISTENT_LIST, userId)
|
||||||
|
self.numEntriesCache0 = UInt16Le()
|
||||||
|
self.numEntriesCache1 = UInt16Le()
|
||||||
|
self.numEntriesCache2 = UInt16Le()
|
||||||
|
self.numEntriesCache3 = UInt16Le()
|
||||||
|
self.numEntriesCache4 = UInt16Le()
|
||||||
|
self.totalEntriesCache0 = UInt16Le()
|
||||||
|
self.totalEntriesCache1 = UInt16Le()
|
||||||
|
self.totalEntriesCache2 = UInt16Le()
|
||||||
|
self.totalEntriesCache3 = UInt16Le()
|
||||||
|
self.totalEntriesCache4 = UInt16Le()
|
||||||
|
self.bitMask = UInt8()
|
||||||
|
self.pad2 = UInt8()
|
||||||
|
self.pad3 = UInt16Le()
|
||||||
|
self.entries = ArrayType(PersistentListEntry, readLen = lambda:(self.numEntriesCache0 + self.numEntriesCache1 + self.numEntriesCache2 + self.numEntriesCache3 + self.numEntriesCache4))
|
||||||
|
|
||||||
|
class ErrorInfoPDU(CompositeType):
|
||||||
|
'''
|
||||||
|
Use to inform error in PDU layer
|
||||||
|
@see: http://msdn.microsoft.com/en-us/library/cc240544.aspx
|
||||||
|
'''
|
||||||
|
def __init__(self):
|
||||||
|
CompositeType.__init__(self)
|
||||||
|
self.shareControlHeader = ShareDataHeader(lambda:sizeof(self), PDUType2.PDUTYPE2_SET_ERROR_INFO_PDU)
|
||||||
|
#use to collect error info pdu
|
||||||
|
self.errorInfo = UInt32Le()
|
||||||
|
|
||||||
class PDU(LayerAutomata):
|
class PDU(LayerAutomata):
|
||||||
'''
|
'''
|
||||||
@@ -503,12 +699,17 @@ class PDU(LayerAutomata):
|
|||||||
self._clientCapabilities = {}
|
self._clientCapabilities = {}
|
||||||
#share id between client and server
|
#share id between client and server
|
||||||
self._shareId = UInt32Le()
|
self._shareId = UInt32Le()
|
||||||
|
#mcs user id use for pdu packet
|
||||||
|
self._userId = UInt16Be()
|
||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
'''
|
'''
|
||||||
connect event in client mode send logon info
|
connect event in client mode send logon info
|
||||||
nextstate recv licence pdu
|
nextstate recv licence pdu
|
||||||
'''
|
'''
|
||||||
|
#get user id from mcs layer
|
||||||
|
self._userId = self._transport._userId
|
||||||
|
|
||||||
self.sendInfoPkt()
|
self.sendInfoPkt()
|
||||||
#next state is licence info PDU
|
#next state is licence info PDU
|
||||||
self.setNextState(self.recvLicenceInfo)
|
self.setNextState(self.recvLicenceInfo)
|
||||||
@@ -543,6 +744,21 @@ class PDU(LayerAutomata):
|
|||||||
|
|
||||||
self.setNextState(self.recvDemandActivePDU)
|
self.setNextState(self.recvDemandActivePDU)
|
||||||
|
|
||||||
|
def readPDU(self, data, pdu):
|
||||||
|
'''
|
||||||
|
Try to read expected pdu or try to parse error info pdu
|
||||||
|
'''
|
||||||
|
try:
|
||||||
|
data.readType(pdu)
|
||||||
|
except Exception:
|
||||||
|
#maybe an error message
|
||||||
|
errorInfoPDU = ErrorInfoPDU()
|
||||||
|
try:
|
||||||
|
data.readType(errorInfoPDU)
|
||||||
|
raise ErrorReportedFromPeer("Receive PDU Error info : %s"%hex(errorInfoPDU.errorInfo.value))
|
||||||
|
except:
|
||||||
|
raise InvalidExpectedDataException("Invalid PDU")
|
||||||
|
|
||||||
def recvDemandActivePDU(self, data):
|
def recvDemandActivePDU(self, data):
|
||||||
'''
|
'''
|
||||||
receive demand active PDU which contains
|
receive demand active PDU which contains
|
||||||
@@ -552,13 +768,32 @@ class PDU(LayerAutomata):
|
|||||||
@param data: Stream
|
@param data: Stream
|
||||||
'''
|
'''
|
||||||
demandActivePDU = DemandActivePDU()
|
demandActivePDU = DemandActivePDU()
|
||||||
data.readType(demandActivePDU)
|
self.readPDU(data, demandActivePDU)
|
||||||
|
|
||||||
|
self._shareId = demandActivePDU.shareId
|
||||||
|
|
||||||
for cap in demandActivePDU.capabilitySets._array:
|
for cap in demandActivePDU.capabilitySets._array:
|
||||||
self._serverCapabilities[cap.capabilitySetType] = cap
|
self._serverCapabilities[cap.capabilitySetType] = cap
|
||||||
|
|
||||||
self.sendConfirmActivePDU()
|
self.sendConfirmActivePDU()
|
||||||
|
|
||||||
|
def recvServerFinalizeSynchronizePDU(self, data):
|
||||||
|
'''
|
||||||
|
receive from server
|
||||||
|
'''
|
||||||
|
synchronizePDU = SynchronizePDU()
|
||||||
|
self.readPDU(data, synchronizePDU)
|
||||||
|
|
||||||
|
|
||||||
|
if synchronizePDU.targetUser != self._channelId:
|
||||||
|
raise InvalidExpectedDataException("receive synchronize for an invalide user")
|
||||||
|
|
||||||
|
controlCooparatePDU = ControlPDU(self._userId)
|
||||||
|
self.readPDU(data, controlCooparatePDU)
|
||||||
|
|
||||||
|
if controlCooparatePDU.action != Action.CTRLACTION_COOPERATE:
|
||||||
|
raise InvalidExpectedDataException("receive an invalid cooparate control PDU")
|
||||||
|
|
||||||
def sendConfirmActivePDU(self):
|
def sendConfirmActivePDU(self):
|
||||||
'''
|
'''
|
||||||
send all client capabilities
|
send all client capabilities
|
||||||
@@ -571,7 +806,7 @@ class PDU(LayerAutomata):
|
|||||||
capability.generalCapability.extraFlags = GeneralExtraFlag.LONG_CREDENTIALS_SUPPORTED
|
capability.generalCapability.extraFlags = GeneralExtraFlag.LONG_CREDENTIALS_SUPPORTED
|
||||||
self._clientCapabilities[capability.capabilitySetType] = capability
|
self._clientCapabilities[capability.capabilitySetType] = capability
|
||||||
|
|
||||||
#init general capability
|
#init bitmap capability
|
||||||
capability = Capability()
|
capability = Capability()
|
||||||
capability.capabilitySetType = CapsType.CAPSTYPE_BITMAP
|
capability.capabilitySetType = CapsType.CAPSTYPE_BITMAP
|
||||||
capability.bitmapCapability.preferredBitsPerPixel = self._transport._clientSettings.core.colorDepth
|
capability.bitmapCapability.preferredBitsPerPixel = self._transport._clientSettings.core.colorDepth
|
||||||
@@ -579,18 +814,43 @@ class PDU(LayerAutomata):
|
|||||||
capability.bitmapCapability.desktopHeight = self._transport._clientSettings.core.desktopHeight
|
capability.bitmapCapability.desktopHeight = self._transport._clientSettings.core.desktopHeight
|
||||||
self._clientCapabilities[capability.capabilitySetType] = capability
|
self._clientCapabilities[capability.capabilitySetType] = capability
|
||||||
|
|
||||||
|
#init order capability
|
||||||
|
capability = Capability()
|
||||||
|
capability.capabilitySetType = CapsType.CAPSTYPE_ORDER
|
||||||
|
capability.orderCapability.orderFlags |= OrderFlag.ZEROBOUNDSDELTASSUPPORT
|
||||||
|
capability.orderCapability.orderSupport = [UInt8(0) for i in range (0, 32)]
|
||||||
|
self._clientCapabilities[capability.capabilitySetType] = capability
|
||||||
|
|
||||||
#make active PDU packet
|
#make active PDU packet
|
||||||
confirmActivePDU = ConfirmActivePDU()
|
confirmActivePDU = ConfirmActivePDU(self._userId)
|
||||||
|
confirmActivePDU.shareId = self._shareId
|
||||||
confirmActivePDU.capabilitySets._array = self._clientCapabilities.values()
|
confirmActivePDU.capabilitySets._array = self._clientCapabilities.values()
|
||||||
self._transport.send(self._channelId, confirmActivePDU)
|
self._transport.send(self._channelId, confirmActivePDU)
|
||||||
#send synchronize
|
#send synchronize
|
||||||
self.sendSynchronizePDU()
|
self.sendClientFinalizeSynchronizePDU()
|
||||||
|
|
||||||
def sendSynchronizePDU(self):
|
def sendClientFinalizeSynchronizePDU(self):
|
||||||
'''
|
'''
|
||||||
send a synchronize PDU from client to server
|
send a synchronize PDU from client to server
|
||||||
'''
|
'''
|
||||||
synchronizePDU = SynchronizePDU()
|
synchronizePDU = SynchronizePDU(self._userId)
|
||||||
synchronizePDU.targetUser = self._channelId
|
synchronizePDU.targetUser = self._channelId
|
||||||
self._transport.send(self._channelId, synchronizePDU)
|
self._transport.send(self._channelId, synchronizePDU)
|
||||||
|
|
||||||
|
#ask for cooperation
|
||||||
|
controlCooperatePDU = ControlPDU(self._userId)
|
||||||
|
controlCooperatePDU.action = Action.CTRLACTION_COOPERATE
|
||||||
|
self._transport.send(self._channelId, controlCooperatePDU)
|
||||||
|
|
||||||
|
#request control
|
||||||
|
controlRequestPDU = ControlPDU(self._userId)
|
||||||
|
controlRequestPDU.action = Action.CTRLACTION_REQUEST_CONTROL
|
||||||
|
self._transport.send(self._channelId, controlRequestPDU)
|
||||||
|
|
||||||
|
#send persistent list pdu
|
||||||
|
persistentListPDU = PersistentListPDU(self._userId)
|
||||||
|
persistentListPDU.bitMask = PersistentKeyListFlag.PERSIST_FIRST_PDU | PersistentKeyListFlag.PERSIST_LAST_PDU
|
||||||
|
self._transport.send(self._channelId, persistentListPDU)
|
||||||
|
|
||||||
|
self.setNextState(self.recvServerFinalizeSynchronizePDU)
|
||||||
|
|
||||||
@@ -15,5 +15,5 @@ if __name__ == '__main__':
|
|||||||
from twisted.internet import reactor
|
from twisted.internet import reactor
|
||||||
#reactor.connectTCP("127.0.0.1", 5901, factory.RfbFactory(protocol))
|
#reactor.connectTCP("127.0.0.1", 5901, factory.RfbFactory(protocol))
|
||||||
#reactor.connectTCP("192.168.1.90", 3389, factory.RfbFactory(tpkt.TPKT(tpdu.TPDU(mcs.MCS()))))
|
#reactor.connectTCP("192.168.1.90", 3389, factory.RfbFactory(tpkt.TPKT(tpdu.TPDU(mcs.MCS()))))
|
||||||
reactor.connectTCP("192.168.135.123", 3389, rdp.Factory(LayerMode.CLIENT))
|
reactor.connectTCP("192.168.135.198", 3389, rdp.Factory(LayerMode.CLIENT))
|
||||||
reactor.run()
|
reactor.run()
|
||||||
@@ -264,4 +264,71 @@ class TypeCase(unittest.TestCase):
|
|||||||
s1 = rdpy.network.type.Stream("\x01\x00\x00\x00")
|
s1 = rdpy.network.type.Stream("\x01\x00\x00\x00")
|
||||||
s1.readType(t)
|
s1.readType(t)
|
||||||
self.assertEqual(t.value, 1, "invalid stream read conditional value")
|
self.assertEqual(t.value, 1, "invalid stream read conditional value")
|
||||||
|
|
||||||
|
def test_strem_read_rollback_constant_constraint(self):
|
||||||
|
'''
|
||||||
|
test if constant constraint fail, the reading stream is correctly rollback
|
||||||
|
'''
|
||||||
|
class TestComposite(rdpy.network.type.CompositeType):
|
||||||
|
def __init__(self):
|
||||||
|
rdpy.network.type.CompositeType.__init__(self)
|
||||||
|
self.padding = rdpy.network.type.UInt32Le(0)
|
||||||
|
self.constraint = rdpy.network.type.UInt32Le(1, constant = True)
|
||||||
|
|
||||||
|
s = rdpy.network.type.Stream("\x00\x00\x00\x00\x00\x00\x00\x00")
|
||||||
|
try:
|
||||||
|
s.readType(TestComposite())
|
||||||
|
except Exception:
|
||||||
|
self.assertEqual(s.readLen(), 0, "invalid stream roll back operation")
|
||||||
|
return
|
||||||
|
self.assertTrue(False, "Constant constraint fail")
|
||||||
|
|
||||||
|
def test_strem_read_rollback_constant_constraint_recurcive(self):
|
||||||
|
'''
|
||||||
|
test if constant constraint fail even in recurcive composite type,
|
||||||
|
the reading stream is correctly rollback
|
||||||
|
'''
|
||||||
|
class TestSubComposite(rdpy.network.type.CompositeType):
|
||||||
|
def __init__(self):
|
||||||
|
rdpy.network.type.CompositeType.__init__(self)
|
||||||
|
self.padding = rdpy.network.type.UInt32Le(0)
|
||||||
|
self.constraint = rdpy.network.type.UInt32Le(1, constant = True)
|
||||||
|
|
||||||
|
class TestComposite(rdpy.network.type.CompositeType):
|
||||||
|
def __init__(self):
|
||||||
|
rdpy.network.type.CompositeType.__init__(self)
|
||||||
|
self.padding = rdpy.network.type.UInt32Le(0)
|
||||||
|
self.recurcive = TestSubComposite()
|
||||||
|
|
||||||
|
s = rdpy.network.type.Stream("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
|
||||||
|
try:
|
||||||
|
s.readType(TestComposite())
|
||||||
|
except Exception:
|
||||||
|
self.assertEqual(s.readLen(), 0, "invalid stream roll back operation")
|
||||||
|
return
|
||||||
|
self.assertTrue(False, "Constant constraint fail")
|
||||||
|
|
||||||
|
def test_strem_read_rollback_not_enough_data(self):
|
||||||
|
'''
|
||||||
|
test if constant constraint fail even in recurcive composite type,
|
||||||
|
the reading stream is correctly rollback
|
||||||
|
'''
|
||||||
|
class TestSubComposite(rdpy.network.type.CompositeType):
|
||||||
|
def __init__(self):
|
||||||
|
rdpy.network.type.CompositeType.__init__(self)
|
||||||
|
self.padding = rdpy.network.type.UInt32Le(0)
|
||||||
|
self.constraint = rdpy.network.type.UInt32Le(1)
|
||||||
|
|
||||||
|
class TestComposite(rdpy.network.type.CompositeType):
|
||||||
|
def __init__(self):
|
||||||
|
rdpy.network.type.CompositeType.__init__(self)
|
||||||
|
self.padding = rdpy.network.type.UInt32Le(0)
|
||||||
|
self.recurcive = TestSubComposite()
|
||||||
|
|
||||||
|
s = rdpy.network.type.Stream("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
|
||||||
|
try:
|
||||||
|
s.readType(TestComposite())
|
||||||
|
except Exception:
|
||||||
|
self.assertEqual(s.readLen(), 0, "invalid stream roll back operation")
|
||||||
|
return
|
||||||
|
self.assertTrue(False, "Constant constraint fail")
|
||||||
Reference in New Issue
Block a user