read server capabilities

This commit is contained in:
speyrefitte
2013-12-12 17:23:52 +01:00
parent fcf853e823
commit 9b6b9654ee
4 changed files with 235 additions and 13 deletions

View File

@@ -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):
'''

View File

@@ -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)

View File

@@ -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

View File

@@ -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()