code refactoring

This commit is contained in:
speyrefitte
2014-06-24 16:01:04 +02:00
parent aa8c3dee11
commit fadf1ff5c4
8 changed files with 271 additions and 208 deletions

View File

@@ -45,7 +45,9 @@ def decode(src, width, height, colorType):
insertMix = False insertMix = False
fom_mask = 0 fom_mask = 0
mask = 0 mask = 0
dst = Stream("\x00" * (width * height * sizeof(colorType()))) line = 0
typeSize = sizeof(colorType())
dst = Stream("\x00" * (width * height * typeSize))
while src.dataLen() > 0: while src.dataLen() > 0:
#compute orders #compute orders
@@ -107,7 +109,10 @@ def decode(src, width, height, colorType):
raise InvalidExpectedDataException("In RLE decompression height must be greater than 0") raise InvalidExpectedDataException("In RLE decompression height must be greater than 0")
x = 0 x = 0
height -= 1 height -= 1
#prevline = line prevline = line
line = width * height * typeSize
return dst return dst

View File

@@ -21,6 +21,16 @@
All exceptions error use in RDPY All exceptions error use in RDPY
""" """
class CallPureVirtualFuntion(Exception):
"""
Raise when a virtual function is called and not implemented
"""
def __init__(self, message = ""):
"""
@param message: message show when exception is raised
"""
Exception.__init__(self, message)
class InvalidValue(Exception): class InvalidValue(Exception):
""" """
Raise when invalid value type occurred Raise when invalid value type occurred

View File

@@ -23,88 +23,94 @@ Join RDPY design with twisted design
RDPY use Layer Protocol design (like twisted) RDPY use Layer Protocol design (like twisted)
""" """
from rdpy.network.error import CallPureVirtualFuntion
class LayerMode(object): class LayerMode(object):
NONE = 0 NONE = 0
SERVER = 1 SERVER = 1
CLIENT = 2 CLIENT = 2
class StreamListener(object):
"""
Interface use to inform that we can handle receive stream
"""
def recv(self, s):
"""
Signal that data is available for this layer
call by transport layer
default is to pass data to presentation layer
@param s: raw Stream receive from transport layer
"""
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "recv", "StreamListener"))
class StreamSender(object):
"""
Interface use to show stream sender capability
"""
def send(self, data):
'''
Send Stream on layer
@param data: Type or tuple element handle by transport layer
'''
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "send", "StreamSender"))
class Layer(object): class Layer(object):
''' """
Network abstraction for protocol A simple double linked list with presentation and transport layer
Try as possible to divide user protocol in layer and a subset of event (connect and close)
default implementation is a transparent layer """
''' def __init__(self, mode, presentation = None):
def __init__(self, mode = LayerMode.NONE, presentation = None): """
''' @param mode: LayerMode use
Constructor @param presentation: presentation layer
@param presentation: Layer which handled connect and recv messages """
'''
#presentation layer higher layer in model #presentation layer higher layer in model
self._presentation = presentation self._presentation = presentation
#transport layer under layer in model #transport layer under layer in model
self._transport = None self._transport = None
#register layer mode #network layer mode
self._mode = mode self._mode = mode
#auto set transport layer of own presentation layer #auto set transport layer of own presentation layer
if not self._presentation is None: if not self._presentation is None:
self._presentation._transport = self self._presentation._transport = self
def connect(self): def connect(self):
''' """
call when transport layer is connected Call when transport layer is connected
default is send connect event to presentation layer default is send connect event to presentation layer
''' """
if not self._presentation is None: if not self._presentation is None:
self._presentation.connect() self._presentation.connect()
def recv(self, s):
'''
signal that data is available for this layer
call by transport layer
default is to pass data to presentation layer
@param s: raw Stream receive from transport layer
'''
if not self._presentation is None:
self._presentation.recv(s)
def send(self, data):
'''
classical use by presentation layer
write data for this layer
default pass data to transport layer
@param data: Type or tuple element handle by transport layer
'''
if not self._transport is None:
self._transport.send(data)
def close(self): def close(self):
''' """
close layer and send close signal Close layer event
to transport layer default is sent to transport layer
''' """
if not self._transport is None: if not self._transport is None:
self._transport.close() self._transport.close()
class LayerAutomata(Layer): class LayerAutomata(Layer, StreamListener):
''' """
layer with automata state Layer with automata state
we can set next recv function used we can set next recv function used for Stream packet
''' """
def __init__(self, mode, presentation = None): def __init__(self, mode, presentation = None):
''' """
Constructor @param mode: LayerMode use
@param presentation: presentation Layer @param presentation: presentation Layer
''' """
#call parent constructor #call parent constructor
Layer.__init__(self, mode, presentation) Layer.__init__(self, mode, presentation)
def setNextState(self, callback = None): def setNextState(self, callback = None):
''' """
set recv function to next callback or Set receive function to next callback or
current self.recv function if it's None current self.recv function if it's None
@param callback: a callable object that can @param callback: a callable object that can
receive Layer, Stream parameters receive Layer, Stream parameters
''' """
if callback is None: if callback is None:
callback = self.__class__.recv callback = self.__class__.recv
@@ -115,16 +121,17 @@ from twisted.internet import protocol
#first that handle stream #first that handle stream
from type import Stream from type import Stream
class RawLayer(protocol.Protocol, LayerAutomata): class RawLayer(protocol.Protocol, LayerAutomata, StreamSender):
''' """
Inherit from protocol twisted class Inherit from protocol twisted class
allow this protocol to wait until expected size of packet allow this protocol to wait until expected size of packet
and use Layer automata to call next automata state and use Layer automata to call next automata state
''' """
def __init__(self, mode, presentation = None): def __init__(self, mode, presentation = None):
''' """
Constructor @param mode: LayerMode use
''' @param presentation: presentation layer in layer list
"""
#call parent automata #call parent automata
LayerAutomata.__init__(self, mode, presentation) LayerAutomata.__init__(self, mode, presentation)
#data buffer received from twisted network layer #data buffer received from twisted network layer
@@ -133,11 +140,11 @@ class RawLayer(protocol.Protocol, LayerAutomata):
self._expectedLen = 0 self._expectedLen = 0
def dataReceived(self, data): def dataReceived(self, data):
''' """
inherit from protocol class Inherit from protocol class
main event of received data main event of received data
@param data: string data receive from twisted @param data: string data receive from twisted
''' """
#add in buffer #add in buffer
self._buffer += data self._buffer += data
#while buffer have expected size call local callback #while buffer have expected size call local callback
@@ -150,29 +157,29 @@ class RawLayer(protocol.Protocol, LayerAutomata):
self.recv(expectedData) self.recv(expectedData)
def connectionMade(self): def connectionMade(self):
''' """
inherit from twisted protocol inherit from twisted protocol
''' """
#join two scheme #join two scheme
self.connect() self.connect()
def expect(self, expectedLen, callback = None): def expect(self, expectedLen, callback = None):
''' """
configure layer to change next state with callback only Configure layer to change next state with callback only
when expectLen bytes is received from transport layer when expectLen bytes is received from transport layer
@param expectedLen: in bytes len use to call nextstate @param expectedLen: in bytes length use to call next state
@param callback: callback call when expectedlen bytes is received @param callback: callback call when expected length bytes is received
''' """
self._expectedLen = expectedLen self._expectedLen = expectedLen
#default callback is recv from LayerAutomata #default callback is recv from LayerAutomata
self.setNextState(callback) self.setNextState(callback)
def send(self, message): def send(self, message):
''' """
send stream on tcp layer Send Stream on TCP layer
format message into raw stream understood by transport layer format message into raw stream understood by transport layer
@param message: (tuple | Type) @param message: (tuple | Type)
''' """
s = Stream() s = Stream()
s.writeType(message) s.writeType(message)
self.transport.write(s.getvalue()) self.transport.write(s.getvalue())

View File

@@ -1,6 +1,27 @@
''' #
@author: sylvain # Copyright (c) 2014 Sylvain Peyrefitte
''' #
# This file is part of rdpy.
#
# rdpy is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
Basic Encoding Rules use in RDP.
ASN.1 standard
"""
from rdpy.network.type import UInt8, UInt16Be, UInt32Be, String from rdpy.network.type import UInt8, UInt16Be, UInt32Be, String
from rdpy.network.const import ConstAttributes, TypeAttributes from rdpy.network.const import ConstAttributes, TypeAttributes
from rdpy.network.error import InvalidExpectedDataException, InvalidSize from rdpy.network.error import InvalidExpectedDataException, InvalidSize
@@ -35,24 +56,24 @@ class Tag(object):
BER_TAG_SEQUENCE_OF = 0x10 BER_TAG_SEQUENCE_OF = 0x10
def berPC(pc): def berPC(pc):
''' """
return BER_CONSTRUCT if true Return BER_CONSTRUCT if true
BER_PRIMITIVE if false BER_PRIMITIVE if false
@param pc: boolean @param pc: boolean
@return: BerPc value @return: BerPc value
''' """
if pc: if pc:
return BerPc.BER_CONSTRUCT return BerPc.BER_CONSTRUCT
else: else:
return BerPc.BER_PRIMITIVE return BerPc.BER_PRIMITIVE
def readLength(s): def readLength(s):
''' """
read length of ber structure Read length of BER structure
length be on 1 2 or 3 bytes length be on 1 2 or 3 bytes
@param s: stream @param s: stream
@return: int or python long @return: int or Python long
''' """
size = None size = None
length = UInt8() length = UInt8()
s.readType(length) s.readType(length)
@@ -64,50 +85,50 @@ def readLength(s):
elif byte == 2: elif byte == 2:
size = UInt16Be() size = UInt16Be()
else: else:
raise InvalidExpectedDataException("ber length may be 1 or 2") raise InvalidExpectedDataException("BER length may be 1 or 2")
s.readType(size) s.readType(size)
else: else:
size = length size = length
return size.value return size.value
def writeLength(size): def writeLength(size):
''' """
return strcture length as expected in Ber specification Return structure length as expected in BER specification
@param size: int or python long @param size: int or python long
@return: UInt8 or (UInt8(0x82), UInt16Be) @return: UInt8 or (UInt8(0x82), UInt16Be)
''' """
if size > 0x7f: if size > 0x7f:
return (UInt8(0x82), UInt16Be(size)) return (UInt8(0x82), UInt16Be(size))
else: else:
return UInt8(size) return UInt8(size)
def readUniversalTag(s, tag, pc): def readUniversalTag(s, tag, pc):
''' """
read tag of ber packet Read tag of BER packet
@param tag: Tag class attributes @param tag: Tag class attributes
@param pc: boolean @param pc: boolean
@return: true if tag is correctly read @return: true if tag is correctly read
''' """
byte = UInt8() byte = UInt8()
s.readType(byte) s.readType(byte)
return byte == ((Class.BER_CLASS_UNIV | berPC(pc)) | (Tag.BER_TAG_MASK & tag)) return byte == ((Class.BER_CLASS_UNIV | berPC(pc)) | (Tag.BER_TAG_MASK & tag))
def writeUniversalTag(tag, pc): def writeUniversalTag(tag, pc):
''' """
return universal tag byte Return universal tag byte
@param tag: tag class attributes @param tag: tag class attributes
@param pc: boolean @param pc: boolean
@return: UInt8 @return: UInt8
''' """
return ((Class.BER_CLASS_UNIV | berPC(pc)) | (Tag.BER_TAG_MASK & tag)) return ((Class.BER_CLASS_UNIV | berPC(pc)) | (Tag.BER_TAG_MASK & tag))
def readApplicationTag(s, tag): def readApplicationTag(s, tag):
''' """
read application tag Read application tag
@param s: stream @param s: stream
@param tag: tag class attributes @param tag: tag class attributes
@return: length of application packet @return: length of application packet
''' """
byte = UInt8() byte = UInt8()
s.readType(byte) s.readType(byte)
if tag > UInt8(30): if tag > UInt8(30):
@@ -123,22 +144,22 @@ def readApplicationTag(s, tag):
return readLength(s) return readLength(s)
def writeApplicationTag(tag, size): def writeApplicationTag(tag, size):
''' """
return struct that represent ber application tag Return structure that represent BER application tag
@param tag: UINt8 @param tag: UINt8
@param size: size to rest of packet @param size: size to rest of packet
''' """
if tag > UInt8(30): if tag > UInt8(30):
return (((Class.BER_CLASS_APPL | BerPc.BER_CONSTRUCT) | Tag.BER_TAG_MASK), tag, writeLength(size)) return (((Class.BER_CLASS_APPL | BerPc.BER_CONSTRUCT) | Tag.BER_TAG_MASK), tag, writeLength(size))
else: else:
return (((Class.BER_CLASS_APPL | BerPc.BER_CONSTRUCT) | (Tag.BER_TAG_MASK & tag)), writeLength(size)) return (((Class.BER_CLASS_APPL | BerPc.BER_CONSTRUCT) | (Tag.BER_TAG_MASK & tag)), writeLength(size))
def readBoolean(s): def readBoolean(s):
''' """
return boolean Return boolean
@param s: stream @param s: stream
@return: boolean @return: boolean
''' """
if not readUniversalTag(s, Tag.BER_TAG_BOOLEAN, False): if not readUniversalTag(s, Tag.BER_TAG_BOOLEAN, False):
raise InvalidExpectedDataException("bad boolean tag") raise InvalidExpectedDataException("bad boolean tag")
size = readLength(s) size = readLength(s)
@@ -149,24 +170,24 @@ def readBoolean(s):
return bool(b.value) return bool(b.value)
def writeBoolean(b): def writeBoolean(b):
''' """
return structure that represent boolean in ber specification Return structure that represent boolean in BER specification
@param b: boolean @param b: boolean
@return: ber boolean structure @return: BER boolean structure
''' """
boolean = UInt8(0) boolean = UInt8(0)
if b: if b:
boolean = UInt8(0xff) boolean = UInt8(0xff)
return (writeUniversalTag(Tag.BER_TAG_BOOLEAN, False), writeLength(1), boolean) return (writeUniversalTag(Tag.BER_TAG_BOOLEAN, False), writeLength(1), boolean)
def readInteger(s): def readInteger(s):
''' """
read integer structure from stream Read integer structure from stream
@param s: stream @param s: stream
@return: int or long python @return: int or long python
''' """
if not readUniversalTag(s, Tag.BER_TAG_INTEGER, False): if not readUniversalTag(s, Tag.BER_TAG_INTEGER, False):
raise InvalidExpectedDataException("bad integer tag") raise InvalidExpectedDataException("Bad integer tag")
size = readLength(s) size = readLength(s)
@@ -189,14 +210,14 @@ def readInteger(s):
s.readType(integer) s.readType(integer)
return integer.value return integer.value
else: else:
raise InvalidExpectedDataException("wrong integer size") raise InvalidExpectedDataException("Wrong integer size")
def writeInteger(value): def writeInteger(value):
''' """
write integer value Write integer value
@param param: int or python long @param param: int or python long
@return ber interger structure @return: BER integer structure
''' """
if value <= 0xff: if value <= 0xff:
return (writeUniversalTag(Tag.BER_TAG_INTEGER, False), writeLength(1), UInt8(value)) return (writeUniversalTag(Tag.BER_TAG_INTEGER, False), writeLength(1), UInt8(value))
elif value <= 0xffff: elif value <= 0xffff:
@@ -205,30 +226,30 @@ def writeInteger(value):
return (writeUniversalTag(Tag.BER_TAG_INTEGER, False), writeLength(4), UInt32Be(value)) return (writeUniversalTag(Tag.BER_TAG_INTEGER, False), writeLength(4), UInt32Be(value))
def readOctetString(s): def readOctetString(s):
''' """
read ber string structure Read BER string structure
@param s: stream @param s: stream
@return: String @return: String
''' """
if not readUniversalTag(s, Tag.BER_TAG_OCTET_STRING, False): if not readUniversalTag(s, Tag.BER_TAG_OCTET_STRING, False):
raise InvalidExpectedDataException("unexpected ber tag") raise InvalidExpectedDataException("Unexpected BER tag")
size = readLength(s) size = readLength(s)
return String(s.read(size.value)) return String(s.read(size.value))
def writeOctetstring(value): def writeOctetstring(value):
''' """
write string in ber representation Write string in ber representation
@param value: string @param value: string
@return: string ber structure @return: string ber structure
''' """
return (writeUniversalTag(Tag.BER_TAG_OCTET_STRING, False), writeLength(len(value)), String(value)) return (writeUniversalTag(Tag.BER_TAG_OCTET_STRING, False), writeLength(len(value)), String(value))
def readEnumerated(s): def readEnumerated(s):
''' """
read enumerated structure Read enumerated structure
@param s: Stream @param s: Stream
@return: int or long @return: int or long
''' """
if not readUniversalTag(s, Tag.BER_TAG_ENUMERATED, False): if not readUniversalTag(s, Tag.BER_TAG_ENUMERATED, False):
raise InvalidExpectedDataException("invalid ber tag") raise InvalidExpectedDataException("invalid ber tag")
if readLength(s) != 1: if readLength(s) != 1:

View File

@@ -1,9 +1,32 @@
''' #
@author: citronneur # Copyright (c) 2014 Sylvain Peyrefitte
''' #
# This file is part of rdpy.
#
# rdpy is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
Implement Multi Channel Service
Each channel have a particular role.
The main channel is the graphical channel.
It exist channel for file system order, audio channel, clipboard etc...
"""
from rdpy.network.const import ConstAttributes, TypeAttributes from rdpy.network.const import ConstAttributes, TypeAttributes
from rdpy.network.layer import LayerAutomata, Layer, LayerMode from rdpy.network.layer import LayerAutomata, LayerMode, StreamSender
from rdpy.network.type import sizeof, Stream, UInt8, UInt16Be from rdpy.network.type import sizeof, Stream, UInt8, UInt16Be
from rdpy.network.error import InvalidExpectedDataException, InvalidValue, InvalidSize from rdpy.network.error import InvalidExpectedDataException, InvalidValue, InvalidSize
from rdpy.protocol.rdp.ber import writeLength from rdpy.protocol.rdp.ber import writeLength
@@ -13,18 +36,18 @@ import ber, gcc, per
@ConstAttributes @ConstAttributes
@TypeAttributes(UInt8) @TypeAttributes(UInt8)
class Message(object): class Message(object):
''' """
message type Message type
''' """
MCS_TYPE_CONNECT_INITIAL = 0x65 MCS_TYPE_CONNECT_INITIAL = 0x65
MCS_TYPE_CONNECT_RESPONSE = 0x66 MCS_TYPE_CONNECT_RESPONSE = 0x66
@ConstAttributes @ConstAttributes
@TypeAttributes(UInt8) @TypeAttributes(UInt8)
class DomainMCSPDU: class DomainMCSPDU:
''' """
domain mcs pdu header Domain MCS PDU header
''' """
ERECT_DOMAIN_REQUEST = 1 ERECT_DOMAIN_REQUEST = 1
DISCONNECT_PROVIDER_ULTIMATUM = 8 DISCONNECT_PROVIDER_ULTIMATUM = 8
ATTACH_USER_REQUEST = 10 ATTACH_USER_REQUEST = 10
@@ -37,27 +60,28 @@ class DomainMCSPDU:
@ConstAttributes @ConstAttributes
@TypeAttributes(UInt16Be) @TypeAttributes(UInt16Be)
class Channel: class Channel:
"""
Channel id of main channels use in RDP
"""
MCS_GLOBAL_CHANNEL = 1003 MCS_GLOBAL_CHANNEL = 1003
MCS_USERCHANNEL_BASE = 1001 MCS_USERCHANNEL_BASE = 1001
class MCS(LayerAutomata): class MCS(LayerAutomata):
''' """
Multi Channel Service layer Multi Channel Service layer
the main layer of RDP protocol the main layer of RDP protocol
is why he can do everything and more! is why he can do everything and more!
''' """
class MCSProxySender(StreamSender):
class MCSProxySender(Layer): """
''' Proxy use to set as transport layer for upper channel
Proxy use to set as trnsport layer for upper channel
use to abstract channel id for presentation layer use to abstract channel id for presentation layer
''' """
def __init__(self, mcs, channelId): def __init__(self, mcs, channelId):
''' """
ctor @param mcs: MCS layer use as proxy
@param mcs: mcs layer use as proxy
@param channelId: channel id for presentation layer @param channelId: channel id for presentation layer
''' """
self._mcs = mcs self._mcs = mcs
self._channelId = channelId self._channelId = channelId
@@ -94,11 +118,10 @@ class MCS(LayerAutomata):
def __init__(self, mode, presentation): def __init__(self, mode, presentation):
''' """
ctor call base class ctor @param mode: mode of MCS layer
@param mode: mode of mcs layer
@param presentation: presentation layer @param presentation: presentation layer
''' """
LayerAutomata.__init__(self, mode, presentation) LayerAutomata.__init__(self, mode, presentation)
self._clientSettings = gcc.ClientSettings() self._clientSettings = gcc.ClientSettings()
self._serverSettings = gcc.ServerSettings() self._serverSettings = gcc.ServerSettings()
@@ -110,17 +133,17 @@ class MCS(LayerAutomata):
self._channelIdsRequest = {} self._channelIdsRequest = {}
def connect(self): def connect(self):
''' """
connection send for client mode Connection send for client mode
a write connect initial packet a write connect initial packet
''' """
self._clientSettings.core.serverSelectedProtocol = self._transport._selectedProtocol self._clientSettings.core.serverSelectedProtocol = self._transport._selectedProtocol
self.sendConnectInitial() self.sendConnectInitial()
def connectNextChannel(self): def connectNextChannel(self):
''' """
send sendChannelJoinRequest message on next unconnect channel Send sendChannelJoinRequest message on next unconnect channel
''' """
for (channelId, layer) in self._channelIds.iteritems(): for (channelId, layer) in self._channelIds.iteritems():
#for each unconnect channel send a request #for each unconnect channel send a request
if not self._channelIdsRequest.has_key(channelId): if not self._channelIdsRequest.has_key(channelId):
@@ -138,9 +161,9 @@ class MCS(LayerAutomata):
layer.connect() layer.connect()
def sendConnectInitial(self): def sendConnectInitial(self):
''' """
send connect initial packet Send connect initial packet
''' """
ccReq = gcc.writeConferenceCreateRequest(self._clientSettings) ccReq = gcc.writeConferenceCreateRequest(self._clientSettings)
ccReqStream = Stream() ccReqStream = Stream()
ccReqStream.writeType(ccReq) ccReqStream.writeType(ccReq)
@@ -155,28 +178,28 @@ class MCS(LayerAutomata):
self.setNextState(self.recvConnectResponse) self.setNextState(self.recvConnectResponse)
def sendErectDomainRequest(self): def sendErectDomainRequest(self):
''' """
send a formated erect domain request for RDP connection Send a formated erect domain request for RDP connection
''' """
self._transport.send((self.writeMCSPDUHeader(DomainMCSPDU.ERECT_DOMAIN_REQUEST), per.writeInteger(0), per.writeInteger(0))) self._transport.send((self.writeMCSPDUHeader(DomainMCSPDU.ERECT_DOMAIN_REQUEST), per.writeInteger(0), per.writeInteger(0)))
def sendAttachUserRequest(self): def sendAttachUserRequest(self):
''' """
send a formated attach user request for RDP connection Send a formated attach user request for RDP connection
''' """
self._transport.send(self.writeMCSPDUHeader(DomainMCSPDU.ATTACH_USER_REQUEST)) self._transport.send(self.writeMCSPDUHeader(DomainMCSPDU.ATTACH_USER_REQUEST))
def sendChannelJoinRequest(self, channelId): def sendChannelJoinRequest(self, channelId):
''' """
send a formated Channel join request from client to server Send a formated Channel join request from client to server
''' """
self._transport.send((self.writeMCSPDUHeader(DomainMCSPDU.CHANNEL_JOIN_REQUEST), self._userId, channelId)) self._transport.send((self.writeMCSPDUHeader(DomainMCSPDU.CHANNEL_JOIN_REQUEST), self._userId, channelId))
def recvConnectResponse(self, data): def recvConnectResponse(self, data):
''' """
receive mcs connect response from server receive MCS connect response from server
@param data: Stream @param data: Stream
''' """
ber.readApplicationTag(data, Message.MCS_TYPE_CONNECT_RESPONSE) ber.readApplicationTag(data, Message.MCS_TYPE_CONNECT_RESPONSE)
ber.readEnumerated(data) ber.readEnumerated(data)
ber.readInteger(data) ber.readInteger(data)
@@ -196,10 +219,10 @@ class MCS(LayerAutomata):
self.setNextState(self.recvAttachUserConfirm) self.setNextState(self.recvAttachUserConfirm)
def recvAttachUserConfirm(self, data): def recvAttachUserConfirm(self, data):
''' """
receive an attach user confirm Receive an attach user confirm
@param data: Stream @param data: Stream
''' """
opcode = UInt8() opcode = UInt8()
confirm = UInt8() confirm = UInt8()
data.readType((opcode, confirm)) data.readType((opcode, confirm))
@@ -217,10 +240,10 @@ class MCS(LayerAutomata):
self.connectNextChannel() self.connectNextChannel()
def recvChannelJoinConfirm(self, data): def recvChannelJoinConfirm(self, data):
''' """
receive a channel join confirm from server Receive a channel join confirm from server
@param data: Stream @param data: Stream
''' """
opcode = UInt8() opcode = UInt8()
confirm = UInt8() confirm = UInt8()
data.readType((opcode, confirm)) data.readType((opcode, confirm))
@@ -239,10 +262,10 @@ class MCS(LayerAutomata):
self.connectNextChannel() self.connectNextChannel()
def recvData(self, data): def recvData(self, data):
''' """
main receive method Main receive method
@param data: Stream @param data: Stream
''' """
opcode = UInt8() opcode = UInt8()
data.readType(opcode) data.readType(opcode)
@@ -278,51 +301,52 @@ class MCS(LayerAutomata):
self._channelIds[channelId].recv(data) self._channelIds[channelId].recv(data)
def send(self, channelId, data): def send(self, channelId, data):
''' """
specific send function for channelId Specific send function for channelId
@param channelId: Channel use to send
@param data: message to send @param data: message to send
''' """
self._transport.send((self.writeMCSPDUHeader(DomainMCSPDU.SEND_DATA_REQUEST), self._userId, channelId, UInt8(0x70), UInt16Be(sizeof(data)) | UInt16Be(0x8000), data)) self._transport.send((self.writeMCSPDUHeader(DomainMCSPDU.SEND_DATA_REQUEST), self._userId, channelId, UInt8(0x70), UInt16Be(sizeof(data)) | UInt16Be(0x8000), data))
def writeDomainParams(self, maxChannels, maxUsers, maxTokens, maxPduSize): def writeDomainParams(self, maxChannels, maxUsers, maxTokens, maxPduSize):
''' """
write a special domain param structure Write a special domain parameter structure
use in connection sequence use in connection sequence
@param maxChannels: number of mcs channel use @param maxChannels: number of MCS channel use
@param maxUsers: number of mcs user used (1) @param maxUsers: number of MCS user used (1)
@param maxTokens: unknown @param maxTokens: unknown
@param maxPduSize: unknown @param maxPduSize: unknown
@return: domain param structure @return: domain parameter structure
''' """
domainParam = (ber.writeInteger(maxChannels), ber.writeInteger(maxUsers), ber.writeInteger(maxTokens), domainParam = (ber.writeInteger(maxChannels), ber.writeInteger(maxUsers), ber.writeInteger(maxTokens),
ber.writeInteger(1), ber.writeInteger(0), ber.writeInteger(1), ber.writeInteger(1), ber.writeInteger(0), ber.writeInteger(1),
ber.writeInteger(maxPduSize), ber.writeInteger(2)) ber.writeInteger(maxPduSize), ber.writeInteger(2))
return (ber.writeUniversalTag(ber.Tag.BER_TAG_SEQUENCE, True), writeLength(sizeof(domainParam)), domainParam) return (ber.writeUniversalTag(ber.Tag.BER_TAG_SEQUENCE, True), writeLength(sizeof(domainParam)), domainParam)
def writeMCSPDUHeader(self, mcsPdu, options = 0): def writeMCSPDUHeader(self, mcsPdu, options = 0):
''' """
write mcs pdu header Write MCS PDU header
@param mcsPdu: pdu code @param mcsPdu: PDU code
@param options: option contains in header @param options: option contains in header
@return: UInt8 @return: UInt8
''' """
return (mcsPdu << 2) | options return (mcsPdu << 2) | options
def readMCSPDUHeader(self, opcode, mcsPdu): def readMCSPDUHeader(self, opcode, mcsPdu):
''' """
read mcsPdu header and return options parameter Read mcsPdu header and return options parameter
@param opcode: UInt8 opcode @param opcode: UInt8 opcode
@param mcsPdu: mcsPdu will be checked @param mcsPdu: mcsPdu will be checked
@return: true if opcode is correct @return: true if opcode is correct
''' """
return (opcode >> 2) == mcsPdu return (opcode >> 2) == mcsPdu
def readDomainParams(self, s): def readDomainParams(self, s):
''' """
read domain params structure Read domain parameters structure
@return: (max_channels, max_users, max_tokens, max_pdu_size) @return: (max_channels, max_users, max_tokens, max_pdu_size)
''' """
if not ber.readUniversalTag(s, ber.Tag.BER_TAG_SEQUENCE, True): if not ber.readUniversalTag(s, ber.Tag.BER_TAG_SEQUENCE, True):
raise InvalidValue("bad BER tags") raise InvalidValue("bad BER tags")
ber.readLength(s)#length ber.readLength(s)#length

View File

@@ -2,16 +2,12 @@
@author: citronneur @author: citronneur
''' '''
from rdpy.network.layer import LayerAutomata, LayerMode from rdpy.network.layer import LayerAutomata
from rdpy.network.type import CompositeType, UniString, String, UInt8, UInt16Le, UInt32Le, sizeof, ArrayType,\ from rdpy.network.type import CompositeType, UniString, String, UInt8, UInt16Le, UInt32Le, sizeof, ArrayType, FactoryType
FactoryType
from rdpy.network.const import ConstAttributes, TypeAttributes from rdpy.network.const import ConstAttributes, TypeAttributes
from rdpy.network.error import InvalidExpectedDataException, ErrorReportedFromPeer from rdpy.network.error import InvalidExpectedDataException, ErrorReportedFromPeer
import gcc import gcc, lic, caps
import lic
import caps
import rdp
@ConstAttributes @ConstAttributes
@TypeAttributes(UInt16Le) @TypeAttributes(UInt16Le)

View File

@@ -2,8 +2,8 @@
@author: sylvain @author: sylvain
''' '''
from twisted.internet import protocol from twisted.internet import protocol
import tpkt, tpdu, mcs, pdu
from rdpy.network.layer import LayerMode from rdpy.network.layer import LayerMode
import tpkt, tpdu, mcs, pdu
class RDPController(object): class RDPController(object):
""" """

View File

@@ -24,7 +24,7 @@ This layer have main goal to negociate ssl transport
RDP basic security is not supported by RDPY (because is not a true security layer...) RDP basic security is not supported by RDPY (because is not a true security layer...)
""" """
from rdpy.network.layer import LayerAutomata, LayerMode from rdpy.network.layer import LayerAutomata, LayerMode, StreamSender
from rdpy.network.type import UInt8, UInt16Le, UInt16Be, UInt32Le, CompositeType, sizeof from rdpy.network.type import UInt8, UInt16Le, UInt16Be, UInt32Le, CompositeType, sizeof
from rdpy.network.error import InvalidExpectedDataException from rdpy.network.error import InvalidExpectedDataException
from rdpy.network.const import ConstAttributes, TypeAttributes from rdpy.network.const import ConstAttributes, TypeAttributes
@@ -116,7 +116,7 @@ class Negotiation(CompositeType):
self.selectedProtocol = UInt32Le(conditional = lambda: self.code == NegociationType.TYPE_RDP_NEG_RSP) self.selectedProtocol = UInt32Le(conditional = lambda: self.code == NegociationType.TYPE_RDP_NEG_RSP)
self.failureCode = UInt32Le(conditional = lambda: self.code == NegociationType.TYPE_RDP_NEG_FAILURE) self.failureCode = UInt32Le(conditional = lambda: self.code == NegociationType.TYPE_RDP_NEG_FAILURE)
class TPDU(LayerAutomata): class TPDU(LayerAutomata, StreamSender):
""" """
TPDU layer management TPDU layer management
there is an connection automata there is an connection automata
@@ -223,7 +223,7 @@ class TPDU(LayerAutomata):
""" """
header = TPDUDataHeader() header = TPDUDataHeader()
data.readType(header) data.readType(header)
LayerAutomata.recv(self, data) self._presentation.recv(data)
def sendConnectionRequest(self): def sendConnectionRequest(self):
""" """