add connect response reading
This commit is contained in:
@@ -46,3 +46,13 @@ class InvalidType(Exception):
|
||||
'''
|
||||
Exception.__init__(self, message)
|
||||
|
||||
class InvalidSize(Exception):
|
||||
'''
|
||||
raise when invalid size is present in packet type occured
|
||||
'''
|
||||
def __init__(self, message = ""):
|
||||
'''
|
||||
constructor with message
|
||||
@param message: message show when exception is raised
|
||||
'''
|
||||
Exception.__init__(self, message)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
'''
|
||||
|
||||
import struct
|
||||
from copy import deepcopy
|
||||
from StringIO import StringIO
|
||||
from error import InvalidValue, InvalidType
|
||||
|
||||
@@ -240,6 +241,28 @@ class CompositeType(Type):
|
||||
size += sizeof(self.__dict__[name])
|
||||
return size
|
||||
|
||||
def __eq__(self, other):
|
||||
'''
|
||||
compare each properties which are Type inheritance
|
||||
if one is different then not equal
|
||||
@param other: CompositeType
|
||||
@return: True if each subtype are equals
|
||||
'''
|
||||
if self._typeName != other._typeName:
|
||||
return False
|
||||
for name in self._typeName:
|
||||
if self.__dict__[name] != other.__dict__[name]:
|
||||
return False
|
||||
return True
|
||||
|
||||
def __ne__(self, other):
|
||||
'''
|
||||
return not equal result operator
|
||||
@param other: CompositeType
|
||||
@return: False if each subtype are equals
|
||||
'''
|
||||
return not self.__eq__(other)
|
||||
|
||||
class UInt8(SimpleType):
|
||||
'''
|
||||
unsigned byte
|
||||
@@ -460,15 +483,29 @@ class Stream(StringIO):
|
||||
self.writeType(element)
|
||||
return
|
||||
value.write(self)
|
||||
|
||||
def write_unistr(self, value):
|
||||
for c in value:
|
||||
self.write_uint8(ord(c))
|
||||
self.write_uint8(0)
|
||||
self.write_uint8(0)
|
||||
self.write_uint8(0)
|
||||
|
||||
def CheckValueOnRead(cls):
|
||||
'''
|
||||
wrap read method of class
|
||||
to check value on read
|
||||
if new value is different from old value
|
||||
raise InvalidValue
|
||||
@param cls: class that inherit from Type
|
||||
'''
|
||||
oldRead = cls.read
|
||||
def read(self, s):
|
||||
old = deepcopy(self)
|
||||
oldRead(self, s)
|
||||
if self != old:
|
||||
raise InvalidValue("CheckValueOnRead %s != %s"%(self, old))
|
||||
cls.read = read
|
||||
return cls
|
||||
|
||||
def hexDump(src, length=16):
|
||||
'''
|
||||
print hex representation of sr
|
||||
@param src: string
|
||||
'''
|
||||
FILTER = ''.join([(len(repr(chr(x))) == 3) and chr(x) or '.' for x in range(256)])
|
||||
for c in xrange(0, len(src), length):
|
||||
chars = src[c:c+length]
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
'''
|
||||
from rdpy.protocol.network.type import UInt8, UInt16Be, UInt32Be, String
|
||||
from rdpy.utils.const import ConstAttributes
|
||||
from rdpy.protocol.network.error import InvalidExpectedDataException
|
||||
from rdpy.protocol.network.error import InvalidExpectedDataException,\
|
||||
InvalidSize
|
||||
|
||||
@ConstAttributes
|
||||
class BerPc(object):
|
||||
@@ -228,9 +229,8 @@ def readEnumerated(s):
|
||||
'''
|
||||
if not readUniversalTag(s, Tag.BER_TAG_ENUMERATED, False):
|
||||
raise InvalidExpectedDataException("invalid ber tag")
|
||||
size = readLength(s)
|
||||
if size != UInt32Be(1):
|
||||
raise InvalidExpectedDataException("enumerate size is wrong")
|
||||
if readLength(s) != 1:
|
||||
raise InvalidSize("enumerate size is wrong")
|
||||
enumer = UInt8()
|
||||
s.readType(enumer)
|
||||
return enumer.value
|
||||
|
||||
@@ -2,28 +2,30 @@
|
||||
@author: sylvain
|
||||
'''
|
||||
|
||||
from rdpy.utils.const import ConstAttributes
|
||||
from rdpy.utils.const import ConstAttributes, TypeAttributes
|
||||
from rdpy.protocol.network.layer import LayerAutomata
|
||||
from rdpy.protocol.network.type import sizeof, Stream, UInt8
|
||||
from rdpy.protocol.rdp.ber import writeLength
|
||||
from rdpy.protocol.network.error import InvalidExpectedDataException, InvalidValue, InvalidSize
|
||||
|
||||
import ber, gcc
|
||||
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt8)
|
||||
class Message(object):
|
||||
'''
|
||||
message type
|
||||
'''
|
||||
MCS_TYPE_CONNECT_INITIAL = UInt8(0x65)
|
||||
MCS_TYPE_CONNECT_RESPONSE = UInt8(0x66)
|
||||
MCS_EDRQ = UInt8(1)
|
||||
MCS_DPUM = UInt8(8)
|
||||
MCS_AURQ = UInt8(10)
|
||||
MCS_AUCF = UInt8(11)
|
||||
MCS_CJRQ = UInt8(14)
|
||||
MCS_CJCF = UInt8(15)
|
||||
MCS_SDRQ = UInt8(25)
|
||||
MCS_SDIN = UInt8(26)
|
||||
MCS_TYPE_CONNECT_INITIAL = 0x65
|
||||
MCS_TYPE_CONNECT_RESPONSE = 0x66
|
||||
MCS_EDRQ = 1
|
||||
MCS_DPUM = 8
|
||||
MCS_AURQ = 10
|
||||
MCS_AUCF = 11
|
||||
MCS_CJRQ = 14
|
||||
MCS_CJCF = 15
|
||||
MCS_SDRQ = 25
|
||||
MCS_SDIN = 26
|
||||
|
||||
class Channel:
|
||||
MCS_GLOBAL_CHANNEL = 1003
|
||||
@@ -66,6 +68,8 @@ class MCS(LayerAutomata):
|
||||
self.writeDomainParams(0xffff, 0xfc17, 0xffff, 0xffff),
|
||||
ber.writeOctetstring(ccReqStream.getvalue()))
|
||||
self._transport.send((ber.writeApplicationTag(Message.MCS_TYPE_CONNECT_INITIAL, sizeof(tmp)), tmp))
|
||||
#we must receive a connect response
|
||||
self.setNextState(self.recvConnectResponse)
|
||||
|
||||
def writeDomainParams(self, maxChannels, maxUsers, maxTokens, maxPduSize):
|
||||
'''
|
||||
@@ -81,5 +85,34 @@ class MCS(LayerAutomata):
|
||||
ber.writeInteger(1), ber.writeInteger(0), ber.writeInteger(1),
|
||||
ber.writeInteger(maxPduSize), ber.writeInteger(2))
|
||||
return (ber.writeUniversalTag(ber.Tag.BER_TAG_SEQUENCE, True), writeLength(sizeof(domainParam)), domainParam)
|
||||
|
||||
def readDomainParams(self, s):
|
||||
'''
|
||||
read domain params structure
|
||||
'''
|
||||
if not ber.readUniversalTag(s, ber.Tag.BER_TAG_SEQUENCE, True):
|
||||
raise InvalidValue("bad BER tags")
|
||||
length = ber.readLength(s)
|
||||
max_channels = ber.readInteger(s)
|
||||
max_users = ber.readInteger(s)
|
||||
max_tokens = ber.readInteger(s)
|
||||
ber.readInteger(s)
|
||||
ber.readInteger(s)
|
||||
ber.readInteger(s)
|
||||
max_pdu_size = ber.readInteger(s)
|
||||
ber.readInteger(s)
|
||||
|
||||
def recvConnectResponse(self, data):
|
||||
ber.readApplicationTag(data, Message.MCS_TYPE_CONNECT_RESPONSE)
|
||||
ber.readEnumerated(data)
|
||||
ber.readInteger(data)
|
||||
self.readDomainParams(data)
|
||||
if not ber.readUniversalTag(data, ber.Tag.BER_TAG_OCTET_STRING, False):
|
||||
raise InvalidExpectedDataException("invalid expected tag")
|
||||
gccRequestLength = ber.readLength(data)
|
||||
if data.dataLen() != gccRequestLength:
|
||||
raise InvalidSize("gcc request have ")
|
||||
from rdpy.protocol.network.type import hexDump
|
||||
hexDump(data.getvalue())
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
@author: sylvain
|
||||
'''
|
||||
|
||||
from rdpy.protocol.network.type import UInt8, UInt16Be, UInt32Be, String, Stream
|
||||
from rdpy.protocol.network.type import UInt8, UInt16Be, UInt32Be, String
|
||||
from rdpy.protocol.network.error import InvalidValue, InvalidExpectedDataException
|
||||
|
||||
def readLength(s):
|
||||
|
||||
@@ -4,37 +4,40 @@
|
||||
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.utils.const import ConstAttributes
|
||||
from rdpy.utils.const import ConstAttributes, TypeAttributes
|
||||
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt8)
|
||||
class MessageType(object):
|
||||
'''
|
||||
message type
|
||||
'''
|
||||
X224_TPDU_CONNECTION_REQUEST = UInt8(0xE0)
|
||||
X224_TPDU_CONNECTION_CONFIRM = UInt8(0xD0)
|
||||
X224_TPDU_DISCONNECT_REQUEST = UInt8(0x80)
|
||||
X224_TPDU_DATA = UInt8(0xF0)
|
||||
X224_TPDU_ERROR = UInt8(0x70)
|
||||
X224_TPDU_CONNECTION_REQUEST = 0xE0
|
||||
X224_TPDU_CONNECTION_CONFIRM = 0xD0
|
||||
X224_TPDU_DISCONNECT_REQUEST = 0x80
|
||||
X224_TPDU_DATA = 0xF0
|
||||
X224_TPDU_ERROR = 0x70
|
||||
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt8)
|
||||
class NegociationType(object):
|
||||
'''
|
||||
negotiation header
|
||||
'''
|
||||
TYPE_RDP_NEG_REQ = UInt8(0x01)
|
||||
TYPE_RDP_NEG_RSP = UInt8(0x02)
|
||||
TYPE_RDP_NEG_FAILURE = UInt8(0x03)
|
||||
TYPE_RDP_NEG_REQ = 0x01
|
||||
TYPE_RDP_NEG_RSP = 0x02
|
||||
TYPE_RDP_NEG_FAILURE = 0x03
|
||||
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt32Le)
|
||||
class Protocols(object):
|
||||
'''
|
||||
protocols available for TPDU layer
|
||||
'''
|
||||
PROTOCOL_RDP = UInt32Le(0x00000000)
|
||||
PROTOCOL_SSL = UInt32Le(0x00000001)
|
||||
PROTOCOL_HYBRID = UInt32Le(0x00000002)
|
||||
PROTOCOL_HYBRID_EX = UInt32Le(0x00000008)
|
||||
PROTOCOL_RDP = 0x00000000
|
||||
PROTOCOL_SSL = 0x00000001
|
||||
PROTOCOL_HYBRID = 0x00000002
|
||||
PROTOCOL_HYBRID_EX = 0x00000008
|
||||
|
||||
class TPDUConnectHeader(CompositeType):
|
||||
'''
|
||||
@@ -46,6 +49,15 @@ class TPDUConnectHeader(CompositeType):
|
||||
self.code = code
|
||||
self.padding = (UInt16Be(), UInt16Be(), UInt8())
|
||||
|
||||
class TPDUDataHeader(CompositeType):
|
||||
'''
|
||||
header send when tpdu exchange application data
|
||||
'''
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
self.header = UInt8(2)
|
||||
self.messageType = MessageType.X224_TPDU_DATA
|
||||
self.separator = UInt8(0x80)
|
||||
|
||||
class Negotiation(CompositeType):
|
||||
'''
|
||||
@@ -69,7 +81,6 @@ class TPDU(LayerAutomata):
|
||||
@param presentation: MCS layer
|
||||
'''
|
||||
LayerAutomata.__init__(self, presentation)
|
||||
|
||||
#default protocol is SSl because is the only supported
|
||||
#in this version of RDPY
|
||||
self._protocol = Protocols.PROTOCOL_SSL
|
||||
@@ -103,9 +114,19 @@ class TPDU(LayerAutomata):
|
||||
LayerAutomata.connect(self)
|
||||
|
||||
def recvData(self, data):
|
||||
print "TPDU data"
|
||||
from rdpy.protocol.network.type import hexDump
|
||||
hexDump(data.getvalue())
|
||||
'''
|
||||
read data header from packet
|
||||
and pass to presentation layer
|
||||
@param data: stream
|
||||
'''
|
||||
header = TPDUDataHeader()
|
||||
data.readType(header)
|
||||
if header.messageType == MessageType.X224_TPDU_DATA:
|
||||
LayerAutomata.recv(self, data)
|
||||
elif header.messageType == MessageType.X224_TPDU_ERROR:
|
||||
raise Exception("receive error from tpdu layer")
|
||||
else:
|
||||
raise InvalidExpectedDataException("unknow tpdu code %s"%header.messageType)
|
||||
|
||||
def sendConnectionRequest(self):
|
||||
'''
|
||||
@@ -121,7 +142,7 @@ class TPDU(LayerAutomata):
|
||||
write message packet for TPDU layer
|
||||
add TPDU header
|
||||
'''
|
||||
self._transport.send((UInt8(2), MessageType.X224_TPDU_DATA, UInt8(0x80), message))
|
||||
self._transport.send((TPDUDataHeader(), message))
|
||||
|
||||
def readNeg(self, data):
|
||||
'''
|
||||
|
||||
@@ -3,58 +3,63 @@
|
||||
'''
|
||||
|
||||
from rdpy.protocol.network.type import UInt8, UInt16Be, UInt32Be, SInt32Be, String, CompositeType
|
||||
from rdpy.utils.const import ConstAttributes
|
||||
from rdpy.utils.const import ConstAttributes, TypeAttributes
|
||||
|
||||
@ConstAttributes
|
||||
@TypeAttributes(String)
|
||||
class ProtocolVersion(object):
|
||||
'''
|
||||
different ptotocol version
|
||||
'''
|
||||
UNKNOWN = String()
|
||||
RFB003003 = String("RFB 003.003\n")
|
||||
RFB003007 = String("RFB 003.007\n")
|
||||
RFB003008 = String("RFB 003.008\n")
|
||||
UNKNOWN = ""
|
||||
RFB003003 = "RFB 003.003\n"
|
||||
RFB003007 = "RFB 003.007\n"
|
||||
RFB003008 = "RFB 003.008\n"
|
||||
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt8)
|
||||
class SecurityType(object):
|
||||
'''
|
||||
security type supported
|
||||
(or will be supported)
|
||||
by rdpy
|
||||
'''
|
||||
INVALID = UInt8(0)
|
||||
NONE = UInt8(1)
|
||||
VNC = UInt8(2)
|
||||
INVALID = 0
|
||||
NONE = 1
|
||||
VNC = 2
|
||||
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt32Be)
|
||||
class Pointer(object):
|
||||
'''
|
||||
mouse event code (which button)
|
||||
actually in RFB specification only$
|
||||
three buttons are supported
|
||||
'''
|
||||
BUTTON1 = UInt32Be(0x1)
|
||||
BUTTON2 = UInt32Be(0x2)
|
||||
BUTTON3 = UInt32Be(0x4)
|
||||
BUTTON1 = 0x1
|
||||
BUTTON2 = 0x2
|
||||
BUTTON3 = 0x4
|
||||
|
||||
@ConstAttributes
|
||||
@ConstAttributes
|
||||
@TypeAttributes(SInt32Be)
|
||||
class Encoding(object):
|
||||
'''
|
||||
encoding types
|
||||
'''
|
||||
RAW = SInt32Be(0)
|
||||
RAW = 0
|
||||
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt8)
|
||||
class ClientToServerMessages(object):
|
||||
'''
|
||||
messages types
|
||||
'''
|
||||
PIXEL_FORMAT = UInt8(0)
|
||||
ENCODING = UInt8(2)
|
||||
FRAME_BUFFER_UPDATE_REQUEST = UInt8(3)
|
||||
KEY_EVENT = UInt8(4)
|
||||
POINTER_EVENT = UInt8(5)
|
||||
CUT_TEXT = UInt8(6)
|
||||
PIXEL_FORMAT = 0
|
||||
ENCODING = 2
|
||||
FRAME_BUFFER_UPDATE_REQUEST = 3
|
||||
KEY_EVENT = 4
|
||||
POINTER_EVENT = 5
|
||||
CUT_TEXT = 6
|
||||
|
||||
class PixelFormat(CompositeType):
|
||||
'''
|
||||
|
||||
@@ -33,16 +33,27 @@ class Constant(object):
|
||||
delete is forbidden on constant
|
||||
'''
|
||||
raise Exception("can't delete constant")
|
||||
|
||||
|
||||
def TypeAttributes(typeClass):
|
||||
'''
|
||||
call typeClass ctor on each attributes
|
||||
to uniform atributes type on class
|
||||
@param typeClass: class use to construct each class attributes
|
||||
@return: class decorator
|
||||
'''
|
||||
def wrapper(cls):
|
||||
for c_name, c_value in cls.__dict__.iteritems():
|
||||
if c_name[0] != '_' and not callable(c_value):
|
||||
setattr(cls, c_name, typeClass(c_value))
|
||||
return cls
|
||||
return wrapper
|
||||
|
||||
def ConstAttributes(cls):
|
||||
'''
|
||||
copy on read attributes
|
||||
transform all attributes of class
|
||||
in constant attribute
|
||||
only attributes which are not begining with '_' char
|
||||
and are not callable
|
||||
'''
|
||||
for c_name, c_value in cls.__dict__.iteritems():
|
||||
if c_name[0] != '_' and not callable(c_value):
|
||||
setattr(cls, c_name, Constant(c_value))
|
||||
return cls
|
||||
return TypeAttributes(Constant)(cls)
|
||||
Reference in New Issue
Block a user