add context value + conditional type and constant type

This commit is contained in:
speyrefitte
2013-12-06 16:53:41 +01:00
parent 65d1ef89f5
commit e32def4f50
4 changed files with 189 additions and 124 deletions

View File

@@ -5,40 +5,43 @@
import struct import struct
from copy import deepcopy from copy import deepcopy
from StringIO import StringIO from StringIO import StringIO
from error import InvalidValue, InvalidType from error import InvalidValue, InvalidSize
from rdpy.protocol.network.error import InvalidExpectedDataException
def sizeof(element): def sizeof(element):
''' '''
byte size of type byte size of type
@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
@raise InvalidType: if type is different than tuple of Type inheritance
''' '''
if isinstance(element, tuple): if isinstance(element, tuple):
size = 0 size = 0
for i in element: for i in element:
size += sizeof(i) size += sizeof(i)
return size return size
elif isinstance(element, Type): elif isinstance(element, Type) and element._conditional():
return element.__sizeof__() return element.__sizeof__()
return 0
raise InvalidType("invalid type for sizeof")
class Type(object): class Type(object):
''' '''
root type root type
''' '''
def __init__(self, write_if = lambda:True, read_if = lambda:True): def __init__(self, conditional = lambda:True, optional = False, constant = False):
self._write_if = write_if self._conditional = conditional
self._read_if = read_if self._optional = optional
self._constant = constant
self._is_writed = False
self._is_readed = False
def write(self, s): def write(self, s):
''' '''
interface definition of write function interface definition of write function
@param s: Stream which will be written @param s: Stream which will be written
''' '''
if not self._write_if(): self._is_writed = self._conditional()
if not self._is_writed:
return return
self.__write__(s) self.__write__(s)
@@ -46,11 +49,15 @@ class Type(object):
''' '''
interface definition of read value interface definition of read value
@param s: Stream @param s: Stream
@return: Type read from Stream s
''' '''
if not self._read_if(): self._is_readed = self._conditional()
if not self._is_readed:
return return
old = deepcopy(self)
self.__read__(s) self.__read__(s)
#check constant value
if self._constant and old != self:
raise InvalidExpectedDataException("const value expected")
def __sizeof__(self): def __sizeof__(self):
''' '''
@@ -59,15 +66,14 @@ class Type(object):
''' '''
pass pass
class ValueType(Type): class CallableValue(object):
''' '''
type that wrap an inner type type that wrap an inner type
acces with value getter and setter acces with value getter and setter
value can be a callable which is call value can be a callable which is call
at each access of value at each access of value
''' '''
def __init__(self, value, write_if = lambda:True, read_if = lambda:True): def __init__(self, value):
Type.__init__(self, write_if = write_if, read_if = read_if)
self._value = None self._value = None
self.value = value self.value = value
@@ -102,16 +108,15 @@ class ValueType(Type):
def value(self, value): def value(self, value):
''' '''
setter of value after check it setter of value after check it
@param value: new value encompass in simpletype object @param value: new value encompass in valuetype object
@raise InvalidValue: if value doesn't respect type range
''' '''
self.__setValue__(value) self.__setValue__(value)
class SimpleType(ValueType): class SimpleType(Type, CallableValue):
''' '''
simple type simple type
''' '''
def __init__(self, structFormat, typeSize, signed, value, write_if = lambda:True, read_if = lambda:True): def __init__(self, structFormat, typeSize, signed, value, conditional = lambda:True, optional = False, constant = False):
''' '''
constructor of simple type constructor of simple type
@param structFormat: letter that represent type in struct package @param structFormat: letter that represent type in struct package
@@ -122,7 +127,8 @@ class SimpleType(ValueType):
self._signed = signed self._signed = signed
self._typeSize = typeSize self._typeSize = typeSize
self._structFormat = structFormat self._structFormat = structFormat
ValueType.__init__(self, value, write_if = write_if, read_if = read_if) Type.__init__(self, conditional = conditional, optional = optional, constant = constant)
CallableValue.__init__(self, value)
def __getValue__(self): def __getValue__(self):
''' '''
@@ -130,7 +136,7 @@ class SimpleType(ValueType):
@return: inner value(python type value) @return: inner value(python type value)
@raise InvalidValue: if value doesn't respect type range @raise InvalidValue: if value doesn't respect type range
''' '''
value = ValueType.__getValue__(self) value = CallableValue.__getValue__(self)
if not self.isInRange(value): if not self.isInRange(value):
raise InvalidValue("value is out of range for %s"%self.__class__) raise InvalidValue("value is out of range for %s"%self.__class__)
@@ -149,7 +155,7 @@ class SimpleType(ValueType):
if not callable(value) and not self.isInRange(value): if not callable(value) and not self.isInRange(value):
raise InvalidValue("value is out of range for %s"%self.__class__) raise InvalidValue("value is out of range for %s"%self.__class__)
ValueType.__setValue__(self, value) CallableValue.__setValue__(self, value)
def __cmp__(self, other): def __cmp__(self, other):
@@ -299,11 +305,11 @@ 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
''' '''
def __init__(self, write_if = lambda:True, read_if = lambda:True): def __init__(self, conditional = lambda:True, optional = False, constant = False):
''' '''
init list of simple value init list of simple value
''' '''
Type.__init__(self, write_if = write_if, read_if = read_if) Type.__init__(self, conditional = conditional, optional = optional, constant = constant)
#list of ordoned type #list of ordoned type
self._typeName = [] self._typeName = []
@@ -369,15 +375,15 @@ class UInt8(SimpleType):
''' '''
unsigned byte unsigned byte
''' '''
def __init__(self, value = 0, write_if = lambda:True, read_if = lambda:True): def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False):
SimpleType.__init__(self, "B", 1, False, value, write_if = write_if, read_if = read_if) SimpleType.__init__(self, "B", 1, False, value, conditional = conditional, optional = optional, constant = constant)
class SInt8(SimpleType): class SInt8(SimpleType):
''' '''
signed byte signed byte
''' '''
def __init__(self, value = 0, write_if = lambda:True, read_if = lambda:True): def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False):
SimpleType.__init__(self, "b", 1, True, value, write_if = write_if, read_if = read_if) SimpleType.__init__(self, "b", 1, True, value, conditional = conditional, optional = optional, constant = constant)
class UInt16Be(SimpleType): class UInt16Be(SimpleType):
@@ -386,8 +392,8 @@ class UInt16Be(SimpleType):
@attention: inner value is in machine representation @attention: inner value is in machine representation
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, write_if = lambda:True, read_if = lambda:True): def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False):
SimpleType.__init__(self, ">H", 2, False, value, write_if = write_if, read_if = read_if) SimpleType.__init__(self, ">H", 2, False, value, conditional = conditional, optional = optional, constant = constant)
class UInt16Le(SimpleType): class UInt16Le(SimpleType):
''' '''
@@ -395,8 +401,8 @@ class UInt16Le(SimpleType):
@attention: inner value is in machine representation @attention: inner value is in machine representation
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, write_if = lambda:True, read_if = lambda:True): def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False):
SimpleType.__init__(self, "<H", 2, False, value, write_if = write_if, read_if = read_if) SimpleType.__init__(self, "<H", 2, False, value, conditional = conditional, optional = optional, constant = constant)
class UInt32Be(SimpleType): class UInt32Be(SimpleType):
''' '''
@@ -404,8 +410,8 @@ class UInt32Be(SimpleType):
@attention: inner value is in machine representation @attention: inner value is in machine representation
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, write_if = lambda:True, read_if = lambda:True): def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False):
SimpleType.__init__(self, ">I", 4, False, value, write_if = write_if, read_if = read_if) SimpleType.__init__(self, ">I", 4, False, value, conditional = conditional, optional = optional, constant = constant)
class UInt32Le(SimpleType): class UInt32Le(SimpleType):
''' '''
@@ -413,8 +419,8 @@ class UInt32Le(SimpleType):
@attention: inner value is in machine representation @attention: inner value is in machine representation
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, write_if = lambda:True, read_if = lambda:True): def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False):
SimpleType.__init__(self, "<I", 4, False, value, write_if = write_if, read_if = read_if) SimpleType.__init__(self, "<I", 4, False, value, conditional = conditional, optional = optional, constant = constant)
class SInt32Le(SimpleType): class SInt32Le(SimpleType):
''' '''
@@ -422,8 +428,8 @@ class SInt32Le(SimpleType):
@attention: inner value is in machine representation @attention: inner value is in machine representation
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, write_if = lambda:True, read_if = lambda:True): def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False):
SimpleType.__init__(self, "<I", 4, True, value, write_if = write_if, read_if = read_if) SimpleType.__init__(self, "<I", 4, True, value, conditional = conditional, optional = optional, constant = constant)
class SInt32Be(SimpleType): class SInt32Be(SimpleType):
''' '''
@@ -431,8 +437,8 @@ class SInt32Be(SimpleType):
@attention: inner value is in machine representation @attention: inner value is in machine representation
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, write_if = lambda:True, read_if = lambda:True): def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False):
SimpleType.__init__(self, ">I", 4, True, value, write_if = write_if, read_if = read_if) SimpleType.__init__(self, ">I", 4, True, value, conditional = conditional, optional = optional, constant = constant)
class UInt24Be(SimpleType): class UInt24Be(SimpleType):
''' '''
@@ -440,8 +446,8 @@ class UInt24Be(SimpleType):
@attention: inner value is in machine representation @attention: inner value is in machine representation
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, write_if = lambda:True, read_if = lambda:True): def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False):
SimpleType.__init__(self, ">I", 3, False, value, write_if = write_if, read_if = read_if) SimpleType.__init__(self, ">I", 3, False, value, conditional = conditional, optional = optional, constant = constant)
def __write__(self, s): def __write__(self, s):
''' '''
@@ -455,8 +461,8 @@ class UInt24Le(SimpleType):
@attention: inner value is in machine representation @attention: inner value is in machine representation
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, write_if = lambda:True, read_if = lambda:True): def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False):
SimpleType.__init__(self, "<I", 3, False, value, write_if = write_if, read_if = read_if) SimpleType.__init__(self, "<I", 3, False, value, conditional = conditional, optional = optional, constant = constant)
def __write__(self, s): def __write__(self, s):
''' '''
@@ -466,16 +472,17 @@ class UInt24Le(SimpleType):
#don't write first byte #don't write first byte
s.write(struct.pack("<I", self.value)[1:]) s.write(struct.pack("<I", self.value)[1:])
class String(ValueType): class String(Type, CallableValue):
''' '''
String network type String network type
''' '''
def __init__(self, value = "", write_if = lambda:True, read_if = lambda:True): def __init__(self, value = "", 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
''' '''
ValueType.__init__(self, value, write_if = write_if, read_if = read_if) Type.__init__(self, conditional = conditional, optional = optional, constant = constant)
CallableValue.__init__(self, value)
def __eq__(self, other): def __eq__(self, other):
''' '''
@@ -572,6 +579,8 @@ 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:

View File

@@ -7,15 +7,23 @@ from rdpy.protocol.network.type import CompositeType, UniString, UInt16Le, UInt1
from rdpy.utils.const import ConstAttributes, TypeAttributes from rdpy.utils.const import ConstAttributes, TypeAttributes
from rdpy.protocol.network.error import InvalidExpectedDataException from rdpy.protocol.network.error import InvalidExpectedDataException
import gcc
@ConstAttributes @ConstAttributes
@TypeAttributes(UInt16Le) @TypeAttributes(UInt16Le)
class SecurityFlag(object): class SecurityFlag(object):
'''
microsoft security flags
'''
SEC_INFO_PKT = 0x0040 SEC_INFO_PKT = 0x0040
SEC_LICENSE_PKT = 0x0080 SEC_LICENSE_PKT = 0x0080
@ConstAttributes @ConstAttributes
@TypeAttributes(UInt32Le) @TypeAttributes(UInt32Le)
class InfoFlag(object): class InfoFlag(object):
'''
client capabilities informations
'''
INFO_MOUSE = 0x00000001 INFO_MOUSE = 0x00000001
INFO_DISABLECTRLALTDEL = 0x00000002 INFO_DISABLECTRLALTDEL = 0x00000002
INFO_AUTOLOGON = 0x00000008 INFO_AUTOLOGON = 0x00000008
@@ -39,6 +47,9 @@ class InfoFlag(object):
@ConstAttributes @ConstAttributes
@TypeAttributes(UInt32Le) @TypeAttributes(UInt32Le)
class PerfFlag(object): class PerfFlag(object):
'''
network performances flag
'''
PERF_DISABLE_WALLPAPER = 0x00000001 PERF_DISABLE_WALLPAPER = 0x00000001
PERF_DISABLE_FULLWINDOWDRAG = 0x00000002 PERF_DISABLE_FULLWINDOWDRAG = 0x00000002
PERF_DISABLE_MENUANIMATIONS = 0x00000004 PERF_DISABLE_MENUANIMATIONS = 0x00000004
@@ -55,29 +66,58 @@ class AfInet(object):
AF_INET6 = 0x0017 AF_INET6 = 0x0017
class RDPInfo(CompositeType): class RDPInfo(CompositeType):
def __init__(self): '''
client informations
contains credentials (very important packet)
'''
def __init__(self, initForWrite, extendedInfoConditional):
CompositeType.__init__(self) CompositeType.__init__(self)
#code page
self.codePage = UInt32Le() self.codePage = UInt32Le()
self.flag = InfoFlag.INFO_MOUSE | InfoFlag.INFO_UNICODE | InfoFlag.INFO_LOGONERRORS | InfoFlag.INFO_LOGONNOTIFY | InfoFlag.INFO_ENABLEWINDOWSKEY | InfoFlag.INFO_DISABLECTRLALTDEL #support flag
self.cbDomain = UInt16Le(lambda:sizeof(self.domain) - 2) self.flag = InfoFlag.INFO_MOUSE | InfoFlag.INFO_UNICODE | InfoFlag.INFO_LOGONERRORS | InfoFlag.INFO_LOGONNOTIFY | InfoFlag.INFO_ENABLEWINDOWSKEY | InfoFlag.INFO_DISABLECTRLALTDEL
self.cbUserName = UInt16Le(lambda:sizeof(self.userName) - 2) #length of domain unistring less 2 byte null terminate
self.cbPassword = UInt16Le(lambda:sizeof(self.password) - 2) self.cbDomain = UInt16Le(lambda:sizeof(self.domain) - 2)
#length of username unistring less 2 byte null terminate
self.cbUserName = UInt16Le(lambda:sizeof(self.userName) - 2)
#length of password unistring less 2 byte null terminate
self.cbPassword = UInt16Le(lambda:sizeof(self.password) - 2)
#length of alternateshell unistring less 2 byte null terminate
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
self.cbWorkingDir = UInt16Le(lambda:sizeof(self.workingDir) - 2) self.cbWorkingDir = UInt16Le(lambda:sizeof(self.workingDir) - 2)
self.domain = UniString("coco") #to avoid recurcive loop init differ from reading and writing
self.userName = UniString("lolo") #microsoft domain
self.password = UniString("toto") self.domain = UniString("" if initForWrite else lambda:"\x00" * self.cbDomain.value)
self.alternateShell = UniString() #session username
self.workingDir = UniString() self.userName = UniString("" if initForWrite else lambda:"\x00" * self.cbUserName.value)
#associate password
self.password = UniString("" if initForWrite else lambda:"\x00" * self.cbPassword.value)
#shell execute at start of session
self.alternateShell = UniString("" if initForWrite else lambda:"\x00" * self.cbAlternateShell.value)
#working directory for session
self.workingDir = UniString("" if initForWrite else lambda:"\x00" * self.cbWorkingDir.value)
#more client informations
self.extendedInfo = RDPExtendedInfo(initForWrite, conditional = extendedInfoConditional)
class RDPExtendedInfo(CompositeType): class RDPExtendedInfo(CompositeType):
def __init__(self): '''
CompositeType.__init__(self) add more client informations
use for performance flag!!!
'''
def __init__(self, initForWrite, conditional):
CompositeType.__init__(self, conditional = conditional)
#is an ip v4 or v6 adresse
self.clientAddressFamily = AfInet.AF_INET self.clientAddressFamily = AfInet.AF_INET
#len of adress field
self.cbClientAddress = UInt16Le(lambda:sizeof(self.clientAddress)) self.cbClientAddress = UInt16Le(lambda:sizeof(self.clientAddress))
self.clientAddress = UniString("192.168.135.10") #adress of client
self.clientAddress = UniString("" if initForWrite else lambda:"\x00" * self.cbClientAddress.value)
#len of client directory
self.cbClientDir = UInt16Le(lambda:sizeof(self.clientDir)) self.cbClientDir = UInt16Le(lambda:sizeof(self.clientDir))
self.clientDir = UniString("c:\\") #self client directory
self.clientDir = UniString("" if initForWrite else lambda:"\x00" * self.cbClientDir.value)
#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
class GDL(LayerAutomata): class GDL(LayerAutomata):
@@ -94,8 +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() self._info = RDPInfo(initForWrite = True, extendedInfoConditional = lambda:self._transport._serverSettings.core.rdpVersion == gcc.Version.RDP_VERSION_5_PLUS)
self._extendedInfo = RDPExtendedInfo()
def connect(self): def connect(self):
''' '''
@@ -111,7 +150,7 @@ class GDL(LayerAutomata):
send a logon info packet for RDP version 5 protocol send a logon info packet for RDP version 5 protocol
''' '''
#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._extendedInfo)) self._transport.send(self._channelId, (SecurityFlag.SEC_INFO_PKT, UInt16Le(), self._info))
def recvLicenceInfo(self, data): def recvLicenceInfo(self, data):
securityFlag = UInt16Le() securityFlag = UInt16Le()

25
rdpy/protocol/rdp/lic.py Normal file
View File

@@ -0,0 +1,25 @@
'''
@author: sylvain
'''
from rdpy.protocol.network.type import CompositeType, UInt8, UInt16Le, sizeof
from rdpy.utils.const import ConstAttributes, TypeAttributes
@ConstAttributes
@TypeAttributes(UInt8)
class MessageType(object):
LICENSE_REQUEST = 0x01
PLATFORM_CHALLENGE = 0x02
NEW_LICENSE = 0x03
UPGRADE_LICENSE = 0x04
LICENSE_INFO = 0x12
NEW_LICENSE_REQUEST = 0x13
PLATFORM_CHALLENGE_RESPONSE = 0x15
ERROR_ALERT = 0xFF
class LicPacket(CompositeType):
def __init__(self):
#preambule
self.bMsgtype = UInt8()
self.flag = UInt8()
self.wMsgSize = UInt16Le(lambda: sizeof(self))

View File

@@ -3,7 +3,7 @@
''' '''
from rdpy.protocol.network.layer import LayerAutomata from rdpy.protocol.network.layer import LayerAutomata
from rdpy.protocol.network.type import UInt8, UInt16Le, UInt16Be, UInt32Le, CompositeType, sizeof from rdpy.protocol.network.type import UInt8, UInt16Le, UInt16Be, UInt32Le, CompositeType, sizeof
from rdpy.protocol.network.error import InvalidExpectedDataException, NegotiationFailure from rdpy.protocol.network.error import InvalidExpectedDataException
from rdpy.utils.const import ConstAttributes, TypeAttributes from rdpy.utils.const import ConstAttributes, TypeAttributes
@ConstAttributes @ConstAttributes
@@ -39,15 +39,30 @@ class Protocols(object):
PROTOCOL_HYBRID = 0x00000002 PROTOCOL_HYBRID = 0x00000002
PROTOCOL_HYBRID_EX = 0x00000008 PROTOCOL_HYBRID_EX = 0x00000008
class TPDUConnectHeader(CompositeType): @ConstAttributes
@TypeAttributes(UInt32Le)
class NegotiationFailureCode(object):
'''
protocol negotiation failure code
'''
SSL_REQUIRED_BY_SERVER = 0x00000001
SSL_NOT_ALLOWED_BY_SERVER = 0x00000002
SSL_CERT_NOT_ON_SERVER = 0x00000003
INCONSISTENT_FLAGS = 0x00000004
HYBRID_REQUIRED_BY_SERVER = 0x00000005
SSL_WITH_USER_AUTH_REQUIRED_BY_SERVER = 0x00000006
class TPDUConnectMessage(CompositeType):
''' '''
header of TPDU connection messages header of TPDU connection messages
''' '''
def __init__(self, code = MessageType.X224_TPDU_CONNECTION_REQUEST, messageSize = 0): def __init__(self):
CompositeType.__init__(self) CompositeType.__init__(self)
self.len = UInt8(messageSize + 6) self.len = UInt8(lambda:sizeof(self) - 1)
self.code = code self.code = UInt8()
self.padding = (UInt16Be(), UInt16Be(), UInt8()) self.padding = (UInt16Be(), UInt16Be(), UInt8())
#read if there is enought data
self.protocolNeg = Negotiation(optional = True)
class TPDUDataHeader(CompositeType): class TPDUDataHeader(CompositeType):
''' '''
@@ -55,20 +70,22 @@ class TPDUDataHeader(CompositeType):
''' '''
def __init__(self): def __init__(self):
CompositeType.__init__(self) CompositeType.__init__(self)
self.header = UInt8(2) self.header = UInt8(2, constant = True)
self.messageType = MessageType.X224_TPDU_DATA self.messageType = MessageType.X224_TPDU_DATA
self.separator = UInt8(0x80) self.separator = UInt8(0x80, constant = True)
class Negotiation(CompositeType): class Negotiation(CompositeType):
''' '''
negociation request message negociation request message
''' '''
def __init__(self, protocol = Protocols.PROTOCOL_SSL): def __init__(self, optional = False):
CompositeType.__init__(self) CompositeType.__init__(self, optional = optional)
self.code = UInt8()
self.flag = UInt8(0) self.flag = UInt8(0)
#always 8 #always 8
self.len = UInt16Le(0x0008) self.len = UInt16Le(0x0008, constant = True)
self.protocol = protocol self.selectedProtocol = UInt32Le(conditional = lambda: self.code == NegociationType.TYPE_RDP_NEG_RSP)
self.failureCode = UInt32Le(conditional = lambda: self.code == NegociationType.TYPE_RDP_NEG_FAILURE)
class TPDU(LayerAutomata): class TPDU(LayerAutomata):
''' '''
@@ -81,11 +98,11 @@ class TPDU(LayerAutomata):
@param presentation: MCS layer @param presentation: MCS layer
''' '''
LayerAutomata.__init__(self, presentation) LayerAutomata.__init__(self, presentation)
#default protocol is SSl because is the only supported #default selectedProtocol is SSl because is the only supported
#in this version of RDPY #in this version of RDPY
#client requested protocol #client requested selectedProtocol
self._requestedProtocol = Protocols.PROTOCOL_SSL self._requestedProtocol = Protocols.PROTOCOL_SSL
#server selected protocol #server selected selectedProtocol
self._selectedProtocol = Protocols.PROTOCOL_SSL self._selectedProtocol = Protocols.PROTOCOL_SSL
def connect(self): def connect(self):
@@ -102,15 +119,24 @@ class TPDU(LayerAutomata):
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
''' '''
header = TPDUConnectHeader() message = TPDUConnectMessage()
data.readType(header) data.readType(message)
if header.code != MessageType.X224_TPDU_CONNECTION_CONFIRM: if message.code != MessageType.X224_TPDU_CONNECTION_CONFIRM:
raise InvalidExpectedDataException("invalid TPDU header code X224_TPDU_CONNECTION_CONFIRM != %d"%header.code) raise InvalidExpectedDataException("invalid TPDU header code X224_TPDU_CONNECTION_CONFIRM != %d"%message.code)
#check presence of negotiation response #check presence of negotiation response
if data.dataLen() == 8: if not message.protocolNeg._is_readed:
self.readNeg(data) raise InvalidExpectedDataException("server must support negotiation protocol to use SSL")
else:
raise NegotiationFailure("server doesn't support SSL") if message.protocolNeg.failureCode._is_readed:
raise InvalidExpectedDataException("negotiation failure code %x"%message.protocolNeg.failureCode.value)
self._selectedProtocol = message.protocolNeg.selectedProtocol
if self._selectedProtocol != Protocols.PROTOCOL_SSL:
raise InvalidExpectedDataException("only ssl protocol is supported in RDPY version")
#_transport is TPKT and transport is TCP layer of twisted
self._transport.transport.startTLS(ClientTLSContext())
self.setNextState(self.recvData) self.setNextState(self.recvData)
#connection is done send to presentation #connection is done send to presentation
@@ -136,8 +162,11 @@ class TPDU(LayerAutomata):
write connection request message write connection request message
next state is recvConnectionConfirm next state is recvConnectionConfirm
''' '''
neqReq = (NegociationType.TYPE_RDP_NEG_REQ, Negotiation(self._requestedProtocol)) message = TPDUConnectMessage()
self._transport.send((TPDUConnectHeader(MessageType.X224_TPDU_CONNECTION_REQUEST, sizeof(neqReq)), neqReq)) message.code = MessageType.X224_TPDU_CONNECTION_REQUEST
message.protocolNeg.code = NegociationType.TYPE_RDP_NEG_REQ
message.protocolNeg.selectedProtocol = self._requestedProtocol
self._transport.send(message)
self.setNextState(self.recvConnectionConfirm) self.setNextState(self.recvConnectionConfirm)
def send(self, message): def send(self, message):
@@ -146,43 +175,6 @@ class TPDU(LayerAutomata):
add TPDU header add TPDU header
''' '''
self._transport.send((TPDUDataHeader(), message)) self._transport.send((TPDUDataHeader(), message))
def readNeg(self, data):
'''
read negotiation response
'''
code = UInt8()
data.readType(code)
if code == NegociationType.TYPE_RDP_NEG_FAILURE:
self.readNegFailure(data)
elif code == NegociationType.TYPE_RDP_NEG_RSP:
self.readNegResp(data)
else:
raise InvalidExpectedDataException("bad protocol negotiation response code")
def readNegFailure(self, data):
'''
read negotiation failure packet
'''
print "Negotiation failure"
def readNegResp(self, data):
'''
read negotiation response packet
'''
negResp = Negotiation()
data.readType(negResp)
if negResp.len != UInt16Le(0x0008):
raise InvalidExpectedDataException("invalid size of negotiation response")
self._selectedProtocol = negResp.protocol
if self._selectedProtocol == self._requestedProtocol and self._selectedProtocol == Protocols.PROTOCOL_SSL:
#_transport is TPKT and transport is TCP layer of twisted
self._transport.transport.startTLS(ClientTLSContext())
else:
raise NegotiationFailure("protocol negociation failure")
#open ssl needed #open ssl needed