add context value + conditional type and constant type
This commit is contained in:
@@ -5,40 +5,43 @@
|
||||
import struct
|
||||
from copy import deepcopy
|
||||
from StringIO import StringIO
|
||||
from error import InvalidValue, InvalidType
|
||||
from error import InvalidValue, InvalidSize
|
||||
from rdpy.protocol.network.error import InvalidExpectedDataException
|
||||
|
||||
def sizeof(element):
|
||||
'''
|
||||
byte size of type
|
||||
@param element: Type or Tuple(Type | Tuple,)
|
||||
@return: size of element in byte
|
||||
@raise InvalidType: if type is different than tuple of Type inheritance
|
||||
'''
|
||||
if isinstance(element, tuple):
|
||||
size = 0
|
||||
for i in element:
|
||||
size += sizeof(i)
|
||||
return size
|
||||
elif isinstance(element, Type):
|
||||
elif isinstance(element, Type) and element._conditional():
|
||||
return element.__sizeof__()
|
||||
|
||||
raise InvalidType("invalid type for sizeof")
|
||||
return 0
|
||||
|
||||
|
||||
class Type(object):
|
||||
'''
|
||||
root type
|
||||
'''
|
||||
def __init__(self, write_if = lambda:True, read_if = lambda:True):
|
||||
self._write_if = write_if
|
||||
self._read_if = read_if
|
||||
def __init__(self, conditional = lambda:True, optional = False, constant = False):
|
||||
self._conditional = conditional
|
||||
self._optional = optional
|
||||
self._constant = constant
|
||||
self._is_writed = False
|
||||
self._is_readed = False
|
||||
|
||||
def write(self, s):
|
||||
'''
|
||||
interface definition of write function
|
||||
@param s: Stream which will be written
|
||||
'''
|
||||
if not self._write_if():
|
||||
self._is_writed = self._conditional()
|
||||
if not self._is_writed:
|
||||
return
|
||||
self.__write__(s)
|
||||
|
||||
@@ -46,11 +49,15 @@ class Type(object):
|
||||
'''
|
||||
interface definition of read value
|
||||
@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
|
||||
old = deepcopy(self)
|
||||
self.__read__(s)
|
||||
#check constant value
|
||||
if self._constant and old != self:
|
||||
raise InvalidExpectedDataException("const value expected")
|
||||
|
||||
def __sizeof__(self):
|
||||
'''
|
||||
@@ -59,15 +66,14 @@ class Type(object):
|
||||
'''
|
||||
pass
|
||||
|
||||
class ValueType(Type):
|
||||
class CallableValue(object):
|
||||
'''
|
||||
type that wrap an inner type
|
||||
acces with value getter and setter
|
||||
value can be a callable which is call
|
||||
at each access of value
|
||||
'''
|
||||
def __init__(self, value, write_if = lambda:True, read_if = lambda:True):
|
||||
Type.__init__(self, write_if = write_if, read_if = read_if)
|
||||
def __init__(self, value):
|
||||
self._value = None
|
||||
self.value = value
|
||||
|
||||
@@ -102,16 +108,15 @@ class ValueType(Type):
|
||||
def value(self, value):
|
||||
'''
|
||||
setter of value after check it
|
||||
@param value: new value encompass in simpletype object
|
||||
@raise InvalidValue: if value doesn't respect type range
|
||||
@param value: new value encompass in valuetype object
|
||||
'''
|
||||
self.__setValue__(value)
|
||||
|
||||
class SimpleType(ValueType):
|
||||
class SimpleType(Type, CallableValue):
|
||||
'''
|
||||
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
|
||||
@param structFormat: letter that represent type in struct package
|
||||
@@ -122,7 +127,8 @@ class SimpleType(ValueType):
|
||||
self._signed = signed
|
||||
self._typeSize = typeSize
|
||||
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):
|
||||
'''
|
||||
@@ -130,7 +136,7 @@ class SimpleType(ValueType):
|
||||
@return: inner value(python type value)
|
||||
@raise InvalidValue: if value doesn't respect type range
|
||||
'''
|
||||
value = ValueType.__getValue__(self)
|
||||
value = CallableValue.__getValue__(self)
|
||||
if not self.isInRange(value):
|
||||
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):
|
||||
raise InvalidValue("value is out of range for %s"%self.__class__)
|
||||
|
||||
ValueType.__setValue__(self, value)
|
||||
CallableValue.__setValue__(self, value)
|
||||
|
||||
|
||||
def __cmp__(self, other):
|
||||
@@ -299,11 +305,11 @@ class CompositeType(Type):
|
||||
keep ordering declaration of simple 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
|
||||
'''
|
||||
Type.__init__(self, write_if = write_if, read_if = read_if)
|
||||
Type.__init__(self, conditional = conditional, optional = optional, constant = constant)
|
||||
#list of ordoned type
|
||||
self._typeName = []
|
||||
|
||||
@@ -369,15 +375,15 @@ class UInt8(SimpleType):
|
||||
'''
|
||||
unsigned byte
|
||||
'''
|
||||
def __init__(self, value = 0, write_if = lambda:True, read_if = lambda:True):
|
||||
SimpleType.__init__(self, "B", 1, False, value, write_if = write_if, read_if = read_if)
|
||||
def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False):
|
||||
SimpleType.__init__(self, "B", 1, False, value, conditional = conditional, optional = optional, constant = constant)
|
||||
|
||||
class SInt8(SimpleType):
|
||||
'''
|
||||
signed byte
|
||||
'''
|
||||
def __init__(self, value = 0, write_if = lambda:True, read_if = lambda:True):
|
||||
SimpleType.__init__(self, "b", 1, True, value, write_if = write_if, read_if = read_if)
|
||||
def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False):
|
||||
SimpleType.__init__(self, "b", 1, True, value, conditional = conditional, optional = optional, constant = constant)
|
||||
|
||||
|
||||
class UInt16Be(SimpleType):
|
||||
@@ -386,8 +392,8 @@ class UInt16Be(SimpleType):
|
||||
@attention: inner value is in machine representation
|
||||
Big endian is just for read or write in stream
|
||||
'''
|
||||
def __init__(self, value = 0, write_if = lambda:True, read_if = lambda:True):
|
||||
SimpleType.__init__(self, ">H", 2, False, value, write_if = write_if, read_if = read_if)
|
||||
def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False):
|
||||
SimpleType.__init__(self, ">H", 2, False, value, conditional = conditional, optional = optional, constant = constant)
|
||||
|
||||
class UInt16Le(SimpleType):
|
||||
'''
|
||||
@@ -395,8 +401,8 @@ class UInt16Le(SimpleType):
|
||||
@attention: inner value is in machine representation
|
||||
Big endian is just for read or write in stream
|
||||
'''
|
||||
def __init__(self, value = 0, write_if = lambda:True, read_if = lambda:True):
|
||||
SimpleType.__init__(self, "<H", 2, False, value, write_if = write_if, read_if = read_if)
|
||||
def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False):
|
||||
SimpleType.__init__(self, "<H", 2, False, value, conditional = conditional, optional = optional, constant = constant)
|
||||
|
||||
class UInt32Be(SimpleType):
|
||||
'''
|
||||
@@ -404,8 +410,8 @@ class UInt32Be(SimpleType):
|
||||
@attention: inner value is in machine representation
|
||||
Big endian is just for read or write in stream
|
||||
'''
|
||||
def __init__(self, value = 0, write_if = lambda:True, read_if = lambda:True):
|
||||
SimpleType.__init__(self, ">I", 4, False, value, write_if = write_if, read_if = read_if)
|
||||
def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False):
|
||||
SimpleType.__init__(self, ">I", 4, False, value, conditional = conditional, optional = optional, constant = constant)
|
||||
|
||||
class UInt32Le(SimpleType):
|
||||
'''
|
||||
@@ -413,8 +419,8 @@ class UInt32Le(SimpleType):
|
||||
@attention: inner value is in machine representation
|
||||
Big endian is just for read or write in stream
|
||||
'''
|
||||
def __init__(self, value = 0, write_if = lambda:True, read_if = lambda:True):
|
||||
SimpleType.__init__(self, "<I", 4, False, value, write_if = write_if, read_if = read_if)
|
||||
def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False):
|
||||
SimpleType.__init__(self, "<I", 4, False, value, conditional = conditional, optional = optional, constant = constant)
|
||||
|
||||
class SInt32Le(SimpleType):
|
||||
'''
|
||||
@@ -422,8 +428,8 @@ class SInt32Le(SimpleType):
|
||||
@attention: inner value is in machine representation
|
||||
Big endian is just for read or write in stream
|
||||
'''
|
||||
def __init__(self, value = 0, write_if = lambda:True, read_if = lambda:True):
|
||||
SimpleType.__init__(self, "<I", 4, True, value, write_if = write_if, read_if = read_if)
|
||||
def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False):
|
||||
SimpleType.__init__(self, "<I", 4, True, value, conditional = conditional, optional = optional, constant = constant)
|
||||
|
||||
class SInt32Be(SimpleType):
|
||||
'''
|
||||
@@ -431,8 +437,8 @@ class SInt32Be(SimpleType):
|
||||
@attention: inner value is in machine representation
|
||||
Big endian is just for read or write in stream
|
||||
'''
|
||||
def __init__(self, value = 0, write_if = lambda:True, read_if = lambda:True):
|
||||
SimpleType.__init__(self, ">I", 4, True, value, write_if = write_if, read_if = read_if)
|
||||
def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False):
|
||||
SimpleType.__init__(self, ">I", 4, True, value, conditional = conditional, optional = optional, constant = constant)
|
||||
|
||||
class UInt24Be(SimpleType):
|
||||
'''
|
||||
@@ -440,8 +446,8 @@ class UInt24Be(SimpleType):
|
||||
@attention: inner value is in machine representation
|
||||
Big endian is just for read or write in stream
|
||||
'''
|
||||
def __init__(self, value = 0, write_if = lambda:True, read_if = lambda:True):
|
||||
SimpleType.__init__(self, ">I", 3, False, value, write_if = write_if, read_if = read_if)
|
||||
def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False):
|
||||
SimpleType.__init__(self, ">I", 3, False, value, conditional = conditional, optional = optional, constant = constant)
|
||||
|
||||
def __write__(self, s):
|
||||
'''
|
||||
@@ -455,8 +461,8 @@ class UInt24Le(SimpleType):
|
||||
@attention: inner value is in machine representation
|
||||
Big endian is just for read or write in stream
|
||||
'''
|
||||
def __init__(self, value = 0, write_if = lambda:True, read_if = lambda:True):
|
||||
SimpleType.__init__(self, "<I", 3, False, value, write_if = write_if, read_if = read_if)
|
||||
def __init__(self, value = 0, conditional = lambda:True, optional = False, constant = False):
|
||||
SimpleType.__init__(self, "<I", 3, False, value, conditional = conditional, optional = optional, constant = constant)
|
||||
|
||||
def __write__(self, s):
|
||||
'''
|
||||
@@ -466,16 +472,17 @@ class UInt24Le(SimpleType):
|
||||
#don't write first byte
|
||||
s.write(struct.pack("<I", self.value)[1:])
|
||||
|
||||
class String(ValueType):
|
||||
class String(Type, CallableValue):
|
||||
'''
|
||||
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
|
||||
@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):
|
||||
'''
|
||||
@@ -572,6 +579,8 @@ class Stream(StringIO):
|
||||
or iterate over tuple elements
|
||||
@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
|
||||
if isinstance(value, tuple):
|
||||
for element in value:
|
||||
|
||||
@@ -7,15 +7,23 @@ from rdpy.protocol.network.type import CompositeType, UniString, UInt16Le, UInt1
|
||||
from rdpy.utils.const import ConstAttributes, TypeAttributes
|
||||
from rdpy.protocol.network.error import InvalidExpectedDataException
|
||||
|
||||
import gcc
|
||||
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt16Le)
|
||||
class SecurityFlag(object):
|
||||
'''
|
||||
microsoft security flags
|
||||
'''
|
||||
SEC_INFO_PKT = 0x0040
|
||||
SEC_LICENSE_PKT = 0x0080
|
||||
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt32Le)
|
||||
class InfoFlag(object):
|
||||
'''
|
||||
client capabilities informations
|
||||
'''
|
||||
INFO_MOUSE = 0x00000001
|
||||
INFO_DISABLECTRLALTDEL = 0x00000002
|
||||
INFO_AUTOLOGON = 0x00000008
|
||||
@@ -39,6 +47,9 @@ class InfoFlag(object):
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt32Le)
|
||||
class PerfFlag(object):
|
||||
'''
|
||||
network performances flag
|
||||
'''
|
||||
PERF_DISABLE_WALLPAPER = 0x00000001
|
||||
PERF_DISABLE_FULLWINDOWDRAG = 0x00000002
|
||||
PERF_DISABLE_MENUANIMATIONS = 0x00000004
|
||||
@@ -55,29 +66,58 @@ class AfInet(object):
|
||||
AF_INET6 = 0x0017
|
||||
|
||||
class RDPInfo(CompositeType):
|
||||
def __init__(self):
|
||||
'''
|
||||
client informations
|
||||
contains credentials (very important packet)
|
||||
'''
|
||||
def __init__(self, initForWrite, extendedInfoConditional):
|
||||
CompositeType.__init__(self)
|
||||
#code page
|
||||
self.codePage = UInt32Le()
|
||||
self.flag = InfoFlag.INFO_MOUSE | InfoFlag.INFO_UNICODE | InfoFlag.INFO_LOGONERRORS | InfoFlag.INFO_LOGONNOTIFY | InfoFlag.INFO_ENABLEWINDOWSKEY | InfoFlag.INFO_DISABLECTRLALTDEL
|
||||
self.cbDomain = UInt16Le(lambda:sizeof(self.domain) - 2)
|
||||
self.cbUserName = UInt16Le(lambda:sizeof(self.userName) - 2)
|
||||
self.cbPassword = UInt16Le(lambda:sizeof(self.password) - 2)
|
||||
#support flag
|
||||
self.flag = InfoFlag.INFO_MOUSE | InfoFlag.INFO_UNICODE | InfoFlag.INFO_LOGONERRORS | InfoFlag.INFO_LOGONNOTIFY | InfoFlag.INFO_ENABLEWINDOWSKEY | InfoFlag.INFO_DISABLECTRLALTDEL
|
||||
#length of domain unistring less 2 byte null terminate
|
||||
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)
|
||||
#length of working directory unistring less 2 byte null terminate
|
||||
self.cbWorkingDir = UInt16Le(lambda:sizeof(self.workingDir) - 2)
|
||||
self.domain = UniString("coco")
|
||||
self.userName = UniString("lolo")
|
||||
self.password = UniString("toto")
|
||||
self.alternateShell = UniString()
|
||||
self.workingDir = UniString()
|
||||
#to avoid recurcive loop init differ from reading and writing
|
||||
#microsoft domain
|
||||
self.domain = UniString("" if initForWrite else lambda:"\x00" * self.cbDomain.value)
|
||||
#session username
|
||||
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):
|
||||
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
|
||||
#len of adress field
|
||||
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.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
|
||||
|
||||
class GDL(LayerAutomata):
|
||||
@@ -94,8 +134,7 @@ class GDL(LayerAutomata):
|
||||
#set by mcs layer channel init
|
||||
self._channelId = UInt16Be()
|
||||
#logon info send from client to server
|
||||
self._info = RDPInfo()
|
||||
self._extendedInfo = RDPExtendedInfo()
|
||||
self._info = RDPInfo(initForWrite = True, extendedInfoConditional = lambda:self._transport._serverSettings.core.rdpVersion == gcc.Version.RDP_VERSION_5_PLUS)
|
||||
|
||||
def connect(self):
|
||||
'''
|
||||
@@ -111,7 +150,7 @@ class GDL(LayerAutomata):
|
||||
send a logon info packet for RDP version 5 protocol
|
||||
'''
|
||||
#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):
|
||||
securityFlag = UInt16Le()
|
||||
|
||||
25
rdpy/protocol/rdp/lic.py
Normal file
25
rdpy/protocol/rdp/lic.py
Normal 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))
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
'''
|
||||
from rdpy.protocol.network.layer import LayerAutomata
|
||||
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
|
||||
|
||||
@ConstAttributes
|
||||
@@ -39,15 +39,30 @@ class Protocols(object):
|
||||
PROTOCOL_HYBRID = 0x00000002
|
||||
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
|
||||
'''
|
||||
def __init__(self, code = MessageType.X224_TPDU_CONNECTION_REQUEST, messageSize = 0):
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
self.len = UInt8(messageSize + 6)
|
||||
self.code = code
|
||||
self.len = UInt8(lambda:sizeof(self) - 1)
|
||||
self.code = UInt8()
|
||||
self.padding = (UInt16Be(), UInt16Be(), UInt8())
|
||||
#read if there is enought data
|
||||
self.protocolNeg = Negotiation(optional = True)
|
||||
|
||||
class TPDUDataHeader(CompositeType):
|
||||
'''
|
||||
@@ -55,20 +70,22 @@ class TPDUDataHeader(CompositeType):
|
||||
'''
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
self.header = UInt8(2)
|
||||
self.header = UInt8(2, constant = True)
|
||||
self.messageType = MessageType.X224_TPDU_DATA
|
||||
self.separator = UInt8(0x80)
|
||||
self.separator = UInt8(0x80, constant = True)
|
||||
|
||||
class Negotiation(CompositeType):
|
||||
'''
|
||||
negociation request message
|
||||
'''
|
||||
def __init__(self, protocol = Protocols.PROTOCOL_SSL):
|
||||
CompositeType.__init__(self)
|
||||
def __init__(self, optional = False):
|
||||
CompositeType.__init__(self, optional = optional)
|
||||
self.code = UInt8()
|
||||
self.flag = UInt8(0)
|
||||
#always 8
|
||||
self.len = UInt16Le(0x0008)
|
||||
self.protocol = protocol
|
||||
self.len = UInt16Le(0x0008, constant = True)
|
||||
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):
|
||||
'''
|
||||
@@ -81,11 +98,11 @@ class TPDU(LayerAutomata):
|
||||
@param presentation: MCS layer
|
||||
'''
|
||||
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
|
||||
#client requested protocol
|
||||
#client requested selectedProtocol
|
||||
self._requestedProtocol = Protocols.PROTOCOL_SSL
|
||||
#server selected protocol
|
||||
#server selected selectedProtocol
|
||||
self._selectedProtocol = Protocols.PROTOCOL_SSL
|
||||
|
||||
def connect(self):
|
||||
@@ -102,15 +119,24 @@ class TPDU(LayerAutomata):
|
||||
call connect on presentation layer if all is good
|
||||
@param data: Stream that contain connection confirm
|
||||
'''
|
||||
header = TPDUConnectHeader()
|
||||
data.readType(header)
|
||||
if header.code != MessageType.X224_TPDU_CONNECTION_CONFIRM:
|
||||
raise InvalidExpectedDataException("invalid TPDU header code X224_TPDU_CONNECTION_CONFIRM != %d"%header.code)
|
||||
message = TPDUConnectMessage()
|
||||
data.readType(message)
|
||||
if message.code != MessageType.X224_TPDU_CONNECTION_CONFIRM:
|
||||
raise InvalidExpectedDataException("invalid TPDU header code X224_TPDU_CONNECTION_CONFIRM != %d"%message.code)
|
||||
#check presence of negotiation response
|
||||
if data.dataLen() == 8:
|
||||
self.readNeg(data)
|
||||
else:
|
||||
raise NegotiationFailure("server doesn't support SSL")
|
||||
if not message.protocolNeg._is_readed:
|
||||
raise InvalidExpectedDataException("server must support negotiation protocol to use 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)
|
||||
#connection is done send to presentation
|
||||
@@ -136,8 +162,11 @@ class TPDU(LayerAutomata):
|
||||
write connection request message
|
||||
next state is recvConnectionConfirm
|
||||
'''
|
||||
neqReq = (NegociationType.TYPE_RDP_NEG_REQ, Negotiation(self._requestedProtocol))
|
||||
self._transport.send((TPDUConnectHeader(MessageType.X224_TPDU_CONNECTION_REQUEST, sizeof(neqReq)), neqReq))
|
||||
message = TPDUConnectMessage()
|
||||
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)
|
||||
|
||||
def send(self, message):
|
||||
@@ -146,43 +175,6 @@ class TPDU(LayerAutomata):
|
||||
add TPDU header
|
||||
'''
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user