add context value + conditional type and constant type
This commit is contained in:
@@ -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:
|
||||||
|
|||||||
@@ -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
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.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
|
||||||
|
|||||||
Reference in New Issue
Block a user