read server capabilities
This commit is contained in:
@@ -17,7 +17,7 @@ def sizeof(element):
|
||||
@param element: Type or Tuple(Type | Tuple,)
|
||||
@return: size of element in byte
|
||||
'''
|
||||
if isinstance(element, tuple):
|
||||
if isinstance(element, tuple) or isinstance(element, list):
|
||||
size = 0
|
||||
for i in element:
|
||||
size += sizeof(i)
|
||||
@@ -96,7 +96,7 @@ class Type(object):
|
||||
@return: size in byte of type
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class CallableValue(object):
|
||||
'''
|
||||
wrap access of callable value.
|
||||
@@ -695,7 +695,7 @@ class Stream(StringIO):
|
||||
@param value: (tuple | Type) object
|
||||
'''
|
||||
#read each tuple
|
||||
if isinstance(value, tuple):
|
||||
if isinstance(value, tuple) or isinstance(value, list):
|
||||
for element in value:
|
||||
self.readType(element)
|
||||
return
|
||||
@@ -721,11 +721,54 @@ class Stream(StringIO):
|
||||
@param value: (tuple | Type)
|
||||
'''
|
||||
#write each element of tuple
|
||||
if isinstance(value, tuple):
|
||||
if isinstance(value, tuple) or isinstance(value, list):
|
||||
for element in value:
|
||||
self.writeType(element)
|
||||
return
|
||||
value.write(self)
|
||||
|
||||
class ArrayType(Type):
|
||||
'''
|
||||
in write mode ArrayType is just list
|
||||
but in read mode it can be dynamic
|
||||
readLen may be dynamic
|
||||
'''
|
||||
def __init__(self, typeFactory, readLen = UInt8(), conditional = lambda:True, optional = False, constant = False):
|
||||
'''
|
||||
constructor
|
||||
@param typeFactory: class use to init new element on read
|
||||
@param readLen: number of element in sequence
|
||||
@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, optional, constant)
|
||||
self._typeFactory = typeFactory
|
||||
self._readLen = readLen
|
||||
self._array = []
|
||||
|
||||
def __read__(self, s):
|
||||
'''
|
||||
create new object and read it
|
||||
@param s: Stream
|
||||
'''
|
||||
for i in range(0, self._readLen.value):
|
||||
element = self._typeFactory()
|
||||
s.readType(element)
|
||||
self._array.append(element)
|
||||
|
||||
def __write__(self, s):
|
||||
'''
|
||||
just write array
|
||||
@param s: Stream
|
||||
'''
|
||||
s.writeType(self._array)
|
||||
|
||||
def __sizeof__(self):
|
||||
'''
|
||||
sizeof inner array
|
||||
'''
|
||||
return sizeof(self._array)
|
||||
|
||||
def CheckValueOnRead(cls):
|
||||
'''
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
'''
|
||||
|
||||
from rdpy.protocol.network.layer import LayerAutomata
|
||||
from rdpy.protocol.network.type import CompositeType, UniString, UInt16Le, UInt16Be, UInt32Le, sizeof
|
||||
from rdpy.protocol.network.type import CompositeType, UniString, String, UInt8, UInt16Le, UInt16Be, UInt32Le, sizeof, ArrayType
|
||||
from rdpy.utils.const import ConstAttributes, TypeAttributes
|
||||
from rdpy.protocol.network.error import InvalidExpectedDataException
|
||||
|
||||
@@ -64,8 +64,53 @@ class PerfFlag(object):
|
||||
@TypeAttributes(UInt16Le)
|
||||
class AfInet(object):
|
||||
AF_INET = 0x00002
|
||||
AF_INET6 = 0x0017
|
||||
AF_INET6 = 0x0017
|
||||
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt16Le)
|
||||
class PDUType(object):
|
||||
PDUTYPE_DEMANDACTIVEPDU = 0x1001
|
||||
PDUTYPE_CONFIRMACTIVEPDU = 0x3001
|
||||
PDUTYPE_DEACTIVATEALLPDU = 0x6001
|
||||
PDUTYPE_DATAPDU = 0x7001
|
||||
PDUTYPE_SERVER_REDIR_PKT = 0xA001
|
||||
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt16Le)
|
||||
class CapsType(object):
|
||||
'''
|
||||
different type of capabilities
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240486.aspx
|
||||
'''
|
||||
CAPSTYPE_GENERAL = 0x0001
|
||||
CAPSTYPE_BITMAP = 0x0002
|
||||
CAPSTYPE_ORDER = 0x0003
|
||||
CAPSTYPE_BITMAPCACHE = 0x0004
|
||||
CAPSTYPE_CONTROL = 0x0005
|
||||
CAPSTYPE_ACTIVATION = 0x0007
|
||||
CAPSTYPE_POINTER = 0x0008
|
||||
CAPSTYPE_SHARE = 0x0009
|
||||
CAPSTYPE_COLORCACHE = 0x000A
|
||||
CAPSTYPE_SOUND = 0x000C
|
||||
CAPSTYPE_INPUT = 0x000D
|
||||
CAPSTYPE_FONT = 0x000E
|
||||
CAPSTYPE_BRUSH = 0x000F
|
||||
CAPSTYPE_GLYPHCACHE = 0x0010
|
||||
CAPSTYPE_OFFSCREENCACHE = 0x0011
|
||||
CAPSTYPE_BITMAPCACHE_HOSTSUPPORT = 0x0012
|
||||
CAPSTYPE_BITMAPCACHE_REV2 = 0x0013
|
||||
CAPSTYPE_VIRTUALCHANNEL = 0x0014
|
||||
CAPSTYPE_DRAWNINEGRIDCACHE = 0x0015
|
||||
CAPSTYPE_DRAWGDIPLUS = 0x0016
|
||||
CAPSTYPE_RAIL = 0x0017
|
||||
CAPSTYPE_WINDOW = 0x0018
|
||||
CAPSETTYPE_COMPDESK = 0x0019
|
||||
CAPSETTYPE_MULTIFRAGMENTUPDATE = 0x001A
|
||||
CAPSETTYPE_LARGE_POINTER = 0x001B
|
||||
CAPSETTYPE_SURFACE_COMMANDS = 0x001C
|
||||
CAPSETTYPE_BITMAP_CODECS = 0x001D
|
||||
CAPSSETTYPE_FRAME_ACKNOWLEDGE = 0x001E
|
||||
|
||||
class RDPInfo(CompositeType):
|
||||
'''
|
||||
client informations
|
||||
@@ -88,15 +133,15 @@ class RDPInfo(CompositeType):
|
||||
#length of working directory unistring less 2 byte null terminate
|
||||
self.cbWorkingDir = UInt16Le(lambda:sizeof(self.workingDir) - 2)
|
||||
#microsoft domain
|
||||
self.domain = UniString(readLen = self.cbDomain)
|
||||
self.domain = UniString(readLen = UInt16Le(lambda:self.cbDomain.value - 2))
|
||||
#session username
|
||||
self.userName = UniString(readLen = self.cbUserName)
|
||||
self.userName = UniString(readLen = UInt16Le(lambda:self.cbUserName.value - 2))
|
||||
#associate password
|
||||
self.password = UniString(readLen = self.cbPassword)
|
||||
self.password = UniString(readLen = UInt16Le(lambda:self.cbPassword.value - 2))
|
||||
#shell execute at start of session
|
||||
self.alternateShell = UniString(readLen = self.cbAlternateShell)
|
||||
self.alternateShell = UniString(readLen = UInt16Le(lambda:self.cbAlternateShell.value - 2))
|
||||
#working directory for session
|
||||
self.workingDir = UniString(readLen = self.cbWorkingDir)
|
||||
self.workingDir = UniString(readLen = UInt16Le(lambda:self.cbWorkingDir.value - 2))
|
||||
#more client informations
|
||||
self.extendedInfo = RDPExtendedInfo(conditional = extendedInfoConditional)
|
||||
|
||||
@@ -120,6 +165,103 @@ class RDPExtendedInfo(CompositeType):
|
||||
#TODO make tiomezone
|
||||
#self.performanceFlags = PerfFlag.PERF_DISABLE_WALLPAPER | PerfFlag.PERF_DISABLE_MENUANIMATIONS | PerfFlag.PERF_DISABLE_CURSOR_SHADOW
|
||||
|
||||
class ShareControlHeader(CompositeType):
|
||||
'''
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240576.aspx
|
||||
'''
|
||||
def __init__(self, totalLength):
|
||||
'''
|
||||
constructor
|
||||
@param totalLength: total length of pdu packet
|
||||
'''
|
||||
CompositeType.__init__(self)
|
||||
#share control header
|
||||
self.totalLength = UInt16Le(totalLength)
|
||||
self.pduType = UInt16Le()
|
||||
self.PDUSource = UInt16Le()
|
||||
|
||||
class Capability(CompositeType):
|
||||
'''
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240486.aspx
|
||||
'''
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
self.capabilitySetType = UInt16Le()
|
||||
self.lengthCapability = UInt16Le(lambda:sizeof(self))
|
||||
self.generalCapability = GeneralCapability(conditional = lambda:self.capabilitySetType == CapsType.CAPSTYPE_GENERAL)
|
||||
self.bitmapCapability = BitmapCapability(conditional = lambda:self.capabilitySetType == CapsType.CAPSTYPE_BITMAP)
|
||||
self.capabilityData = String(readLen = UInt16Le(lambda:self.lengthCapability.value - 4), conditional = lambda:not self.capabilitySetType in [CapsType.CAPSTYPE_GENERAL, CapsType.CAPSTYPE_BITMAP])
|
||||
|
||||
class GeneralCapability(CompositeType):
|
||||
'''
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240549.aspx
|
||||
'''
|
||||
def __init__(self, conditional = lambda:True):
|
||||
CompositeType.__init__(self, conditional = conditional)
|
||||
self.osMajorType = UInt16Le()
|
||||
self.osMinorType = UInt16Le()
|
||||
self.protocolVersion = UInt16Le(0x0200, constant = True)
|
||||
self.pad2octetsA = UInt16Le()
|
||||
self.generalCompressionTypes = UInt16Le(0, constant = True)
|
||||
self.extraFlags = UInt16Le()
|
||||
self.updateCapabilityFlag = UInt16Le(0, constant = True)
|
||||
self.remoteUnshareFlag = UInt16Le(0, constant = True)
|
||||
self.generalCompressionLevel = UInt16Le(0, constant = True)
|
||||
self.refreshRectSupport = UInt8()
|
||||
self.suppressOutputSupport = UInt8()
|
||||
|
||||
class BitmapCapability(CompositeType):
|
||||
'''
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240554.aspx
|
||||
'''
|
||||
def __init__(self, conditional = lambda:True):
|
||||
CompositeType.__init__(self, conditional = conditional)
|
||||
self.preferredBitsPerPixel = UInt16Le()
|
||||
self.receive1BitPerPixel = UInt16Le(0x0001)
|
||||
self.receive4BitsPerPixel = UInt16Le(0x0001)
|
||||
self.receive8BitsPerPixel = UInt16Le(0x0001)
|
||||
self.desktopWidth = UInt16Le()
|
||||
self.desktopHeight = UInt16Le()
|
||||
self.pad2octets = UInt16Le()
|
||||
self.desktopResizeFlag = UInt16Le()
|
||||
self.bitmapCompressionFlag = UInt16Le()
|
||||
self.highColorFlags = UInt8(0)
|
||||
self.drawingFlags = UInt8()
|
||||
self.multipleRectangleSupport = UInt16Le(0x0001, constant = True)
|
||||
self.pad2octetsB = UInt16Le()
|
||||
|
||||
class DemandActivePDU(CompositeType):
|
||||
'''
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240485.aspx
|
||||
'''
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
self.shareControlHeader = ShareControlHeader(lambda:sizeof(self))
|
||||
self.shareId = UInt32Le()
|
||||
self.lengthSourceDescriptor = UInt16Le(lambda:sizeof(self.sourceDescriptor))
|
||||
self.lengthCombinedCapabilities = UInt16Le(lambda:(sizeof(self.numberCapabilities) + sizeof(self.pad2Octets) + sizeof(self.capabilitySets)))
|
||||
self.sourceDescriptor = String("rdpy", readLen = self.lengthSourceDescriptor)
|
||||
self.numberCapabilities = UInt16Le(lambda:len(self.capabilitySets._array))
|
||||
self.pad2Octets = UInt16Le()
|
||||
self.capabilitySets = ArrayType(Capability, readLen = self.numberCapabilities)
|
||||
self.sessionId = UInt32Le()
|
||||
|
||||
class ConfirmActivePDU(CompositeType):
|
||||
'''
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240488.aspx
|
||||
'''
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
self.shareControlHeader = ShareControlHeader(lambda:sizeof(self))
|
||||
self.shareId = UInt32Le()
|
||||
self.originatorId = UInt16Le(0x03EA, constant = True)
|
||||
self.lengthSourceDescriptor = UInt16Le(lambda:sizeof(self.sourceDescriptor))
|
||||
self.lengthCombinedCapabilities = UInt16Le(lambda:(sizeof(self.numberCapabilities) + sizeof(self.pad2Octets) + sizeof(self.capabilitySets)))
|
||||
self.sourceDescriptor = String("rdpy", readLen = self.lengthSourceDescriptor)
|
||||
self.numberCapabilities = UInt16Le(lambda:len(self.capabilitySets._array))
|
||||
self.pad2Octets = UInt16Le()
|
||||
self.capabilitySets = ArrayType(Capability, readLen = self.numberCapabilities)
|
||||
|
||||
class GDL(LayerAutomata):
|
||||
'''
|
||||
Global Display Layer
|
||||
@@ -135,6 +277,10 @@ class GDL(LayerAutomata):
|
||||
self._channelId = UInt16Be()
|
||||
#logon info send from client to server
|
||||
self._info = RDPInfo(extendedInfoConditional = lambda:self._transport._serverSettings.core.rdpVersion == gcc.Version.RDP_VERSION_5_PLUS)
|
||||
#server capabilities
|
||||
self._serverCapabilities = {}
|
||||
#client capabilities
|
||||
self._clientCapabilities = {}
|
||||
|
||||
def connect(self):
|
||||
'''
|
||||
@@ -153,6 +299,10 @@ class GDL(LayerAutomata):
|
||||
self._transport.send(self._channelId, (SecurityFlag.SEC_INFO_PKT, UInt16Le(), self._info))
|
||||
|
||||
def recvLicenceInfo(self, data):
|
||||
'''
|
||||
read license info packet and check if is a valid client info
|
||||
@param data: Stream
|
||||
'''
|
||||
securityFlag = UInt16Le()
|
||||
securityFlagHi = UInt16Le()
|
||||
data.readType((securityFlag, securityFlagHi))
|
||||
@@ -167,4 +317,24 @@ class GDL(LayerAutomata):
|
||||
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")
|
||||
raise InvalidExpectedDataException("server refuse licensing negotiation")
|
||||
|
||||
self.setNextState(self.recvDemandActivePDU)
|
||||
|
||||
def recvDemandActivePDU(self, data):
|
||||
'''
|
||||
receive demand active PDU which contains
|
||||
server capabilities. In this version of RDPY only
|
||||
restricted group of capabilities are used.
|
||||
send confirm active PDU
|
||||
'''
|
||||
demandActivePDU = DemandActivePDU()
|
||||
data.readType(demandActivePDU)
|
||||
|
||||
for cap in demandActivePDU.capabilitySets._array:
|
||||
self._serverCapabilities[cap.capabilitySetType] = cap
|
||||
|
||||
confirmActivePDU = ConfirmActivePDU()
|
||||
confirmActivePDU.capabilitySets._array = self._clientCapabilities.values()
|
||||
|
||||
self._transport.send(self._channelId, confirmActivePDU)
|
||||
@@ -47,6 +47,9 @@ class StateTransition(object):
|
||||
ST_RESEND_LAST_MESSAGE = 0x00000004
|
||||
|
||||
class LicenceBinaryBlob(CompositeType):
|
||||
'''
|
||||
blob use by license manager to echange security data
|
||||
'''
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
self.wBlobType = UInt16Le()
|
||||
@@ -54,6 +57,9 @@ class LicenceBinaryBlob(CompositeType):
|
||||
self.blobData = String(readLen = self.wBlobLen, conditional = lambda:self.wBlobLen.value > 0)
|
||||
|
||||
class LicensingErrorMessage(CompositeType):
|
||||
'''
|
||||
license error message
|
||||
'''
|
||||
def __init__(self, conditional = lambda:True):
|
||||
CompositeType.__init__(self, conditional = conditional)
|
||||
self.dwErrorCode = UInt32Le()
|
||||
@@ -61,6 +67,9 @@ class LicensingErrorMessage(CompositeType):
|
||||
self.blob = LicenceBinaryBlob()
|
||||
|
||||
class LicPacket(CompositeType):
|
||||
'''
|
||||
a license packet
|
||||
'''
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
#preambule
|
||||
|
||||
@@ -11,5 +11,5 @@ if __name__ == '__main__':
|
||||
from twisted.internet import reactor
|
||||
#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.135.71", 3389, rdp.Factory())
|
||||
reactor.connectTCP("192.168.135.182", 3389, rdp.Factory())
|
||||
reactor.run()
|
||||
Reference in New Issue
Block a user