code refactoring
This commit is contained in:
@@ -45,7 +45,9 @@ def decode(src, width, height, colorType):
|
||||
insertMix = False
|
||||
fom_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:
|
||||
#compute orders
|
||||
@@ -107,7 +109,10 @@ def decode(src, width, height, colorType):
|
||||
raise InvalidExpectedDataException("In RLE decompression height must be greater than 0")
|
||||
x = 0
|
||||
height -= 1
|
||||
#prevline = line
|
||||
prevline = line
|
||||
line = width * height * typeSize
|
||||
|
||||
|
||||
return dst
|
||||
|
||||
|
||||
@@ -21,6 +21,16 @@
|
||||
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):
|
||||
"""
|
||||
Raise when invalid value type occurred
|
||||
|
||||
@@ -23,88 +23,94 @@ Join RDPY design with twisted design
|
||||
RDPY use Layer Protocol design (like twisted)
|
||||
"""
|
||||
|
||||
from rdpy.network.error import CallPureVirtualFuntion
|
||||
|
||||
class LayerMode(object):
|
||||
NONE = 0
|
||||
SERVER = 1
|
||||
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):
|
||||
'''
|
||||
Network abstraction for protocol
|
||||
Try as possible to divide user protocol in layer
|
||||
default implementation is a transparent layer
|
||||
'''
|
||||
def __init__(self, mode = LayerMode.NONE, presentation = None):
|
||||
'''
|
||||
Constructor
|
||||
@param presentation: Layer which handled connect and recv messages
|
||||
'''
|
||||
"""
|
||||
A simple double linked list with presentation and transport layer
|
||||
and a subset of event (connect and close)
|
||||
"""
|
||||
def __init__(self, mode, presentation = None):
|
||||
"""
|
||||
@param mode: LayerMode use
|
||||
@param presentation: presentation layer
|
||||
"""
|
||||
#presentation layer higher layer in model
|
||||
self._presentation = presentation
|
||||
#transport layer under layer in model
|
||||
self._transport = None
|
||||
#register layer mode
|
||||
#network layer mode
|
||||
self._mode = mode
|
||||
#auto set transport layer of own presentation layer
|
||||
if not self._presentation is None:
|
||||
self._presentation._transport = self
|
||||
|
||||
def connect(self):
|
||||
'''
|
||||
call when transport layer is connected
|
||||
"""
|
||||
Call when transport layer is connected
|
||||
default is send connect event to presentation layer
|
||||
'''
|
||||
"""
|
||||
if not self._presentation is None:
|
||||
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):
|
||||
'''
|
||||
close layer and send close signal
|
||||
to transport layer
|
||||
'''
|
||||
"""
|
||||
Close layer event
|
||||
default is sent to transport layer
|
||||
"""
|
||||
if not self._transport is None:
|
||||
self._transport.close()
|
||||
|
||||
class LayerAutomata(Layer):
|
||||
'''
|
||||
layer with automata state
|
||||
we can set next recv function used
|
||||
'''
|
||||
class LayerAutomata(Layer, StreamListener):
|
||||
"""
|
||||
Layer with automata state
|
||||
we can set next recv function used for Stream packet
|
||||
"""
|
||||
def __init__(self, mode, presentation = None):
|
||||
'''
|
||||
Constructor
|
||||
"""
|
||||
@param mode: LayerMode use
|
||||
@param presentation: presentation Layer
|
||||
'''
|
||||
"""
|
||||
#call parent constructor
|
||||
Layer.__init__(self, mode, presentation)
|
||||
|
||||
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
|
||||
@param callback: a callable object that can
|
||||
receive Layer, Stream parameters
|
||||
'''
|
||||
"""
|
||||
if callback is None:
|
||||
callback = self.__class__.recv
|
||||
|
||||
@@ -115,16 +121,17 @@ from twisted.internet import protocol
|
||||
#first that handle stream
|
||||
from type import Stream
|
||||
|
||||
class RawLayer(protocol.Protocol, LayerAutomata):
|
||||
'''
|
||||
class RawLayer(protocol.Protocol, LayerAutomata, StreamSender):
|
||||
"""
|
||||
Inherit from protocol twisted class
|
||||
allow this protocol to wait until expected size of packet
|
||||
and use Layer automata to call next automata state
|
||||
'''
|
||||
"""
|
||||
def __init__(self, mode, presentation = None):
|
||||
'''
|
||||
Constructor
|
||||
'''
|
||||
"""
|
||||
@param mode: LayerMode use
|
||||
@param presentation: presentation layer in layer list
|
||||
"""
|
||||
#call parent automata
|
||||
LayerAutomata.__init__(self, mode, presentation)
|
||||
#data buffer received from twisted network layer
|
||||
@@ -133,11 +140,11 @@ class RawLayer(protocol.Protocol, LayerAutomata):
|
||||
self._expectedLen = 0
|
||||
|
||||
def dataReceived(self, data):
|
||||
'''
|
||||
inherit from protocol class
|
||||
"""
|
||||
Inherit from protocol class
|
||||
main event of received data
|
||||
@param data: string data receive from twisted
|
||||
'''
|
||||
"""
|
||||
#add in buffer
|
||||
self._buffer += data
|
||||
#while buffer have expected size call local callback
|
||||
@@ -150,29 +157,29 @@ class RawLayer(protocol.Protocol, LayerAutomata):
|
||||
self.recv(expectedData)
|
||||
|
||||
def connectionMade(self):
|
||||
'''
|
||||
"""
|
||||
inherit from twisted protocol
|
||||
'''
|
||||
"""
|
||||
#join two scheme
|
||||
self.connect()
|
||||
|
||||
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
|
||||
@param expectedLen: in bytes len use to call nextstate
|
||||
@param callback: callback call when expectedlen bytes is received
|
||||
'''
|
||||
@param expectedLen: in bytes length use to call next state
|
||||
@param callback: callback call when expected length bytes is received
|
||||
"""
|
||||
self._expectedLen = expectedLen
|
||||
#default callback is recv from LayerAutomata
|
||||
self.setNextState(callback)
|
||||
|
||||
def send(self, message):
|
||||
'''
|
||||
send stream on tcp layer
|
||||
"""
|
||||
Send Stream on TCP layer
|
||||
format message into raw stream understood by transport layer
|
||||
@param message: (tuple | Type)
|
||||
'''
|
||||
"""
|
||||
s = Stream()
|
||||
s.writeType(message)
|
||||
self.transport.write(s.getvalue())
|
||||
@@ -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.const import ConstAttributes, TypeAttributes
|
||||
from rdpy.network.error import InvalidExpectedDataException, InvalidSize
|
||||
@@ -35,24 +56,24 @@ class Tag(object):
|
||||
BER_TAG_SEQUENCE_OF = 0x10
|
||||
|
||||
def berPC(pc):
|
||||
'''
|
||||
return BER_CONSTRUCT if true
|
||||
"""
|
||||
Return BER_CONSTRUCT if true
|
||||
BER_PRIMITIVE if false
|
||||
@param pc: boolean
|
||||
@return: BerPc value
|
||||
'''
|
||||
"""
|
||||
if pc:
|
||||
return BerPc.BER_CONSTRUCT
|
||||
else:
|
||||
return BerPc.BER_PRIMITIVE
|
||||
|
||||
def readLength(s):
|
||||
'''
|
||||
read length of ber structure
|
||||
"""
|
||||
Read length of BER structure
|
||||
length be on 1 2 or 3 bytes
|
||||
@param s: stream
|
||||
@return: int or python long
|
||||
'''
|
||||
@return: int or Python long
|
||||
"""
|
||||
size = None
|
||||
length = UInt8()
|
||||
s.readType(length)
|
||||
@@ -64,50 +85,50 @@ def readLength(s):
|
||||
elif byte == 2:
|
||||
size = UInt16Be()
|
||||
else:
|
||||
raise InvalidExpectedDataException("ber length may be 1 or 2")
|
||||
raise InvalidExpectedDataException("BER length may be 1 or 2")
|
||||
s.readType(size)
|
||||
else:
|
||||
size = length
|
||||
return size.value
|
||||
|
||||
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
|
||||
@return: UInt8 or (UInt8(0x82), UInt16Be)
|
||||
'''
|
||||
"""
|
||||
if size > 0x7f:
|
||||
return (UInt8(0x82), UInt16Be(size))
|
||||
else:
|
||||
return UInt8(size)
|
||||
|
||||
def readUniversalTag(s, tag, pc):
|
||||
'''
|
||||
read tag of ber packet
|
||||
"""
|
||||
Read tag of BER packet
|
||||
@param tag: Tag class attributes
|
||||
@param pc: boolean
|
||||
@return: true if tag is correctly read
|
||||
'''
|
||||
"""
|
||||
byte = UInt8()
|
||||
s.readType(byte)
|
||||
return byte == ((Class.BER_CLASS_UNIV | berPC(pc)) | (Tag.BER_TAG_MASK & tag))
|
||||
|
||||
def writeUniversalTag(tag, pc):
|
||||
'''
|
||||
return universal tag byte
|
||||
"""
|
||||
Return universal tag byte
|
||||
@param tag: tag class attributes
|
||||
@param pc: boolean
|
||||
@return: UInt8
|
||||
'''
|
||||
"""
|
||||
return ((Class.BER_CLASS_UNIV | berPC(pc)) | (Tag.BER_TAG_MASK & tag))
|
||||
|
||||
def readApplicationTag(s, tag):
|
||||
'''
|
||||
read application tag
|
||||
"""
|
||||
Read application tag
|
||||
@param s: stream
|
||||
@param tag: tag class attributes
|
||||
@return: length of application packet
|
||||
'''
|
||||
"""
|
||||
byte = UInt8()
|
||||
s.readType(byte)
|
||||
if tag > UInt8(30):
|
||||
@@ -123,22 +144,22 @@ def readApplicationTag(s, tag):
|
||||
return readLength(s)
|
||||
|
||||
def writeApplicationTag(tag, size):
|
||||
'''
|
||||
return struct that represent ber application tag
|
||||
"""
|
||||
Return structure that represent BER application tag
|
||||
@param tag: UINt8
|
||||
@param size: size to rest of packet
|
||||
'''
|
||||
"""
|
||||
if tag > UInt8(30):
|
||||
return (((Class.BER_CLASS_APPL | BerPc.BER_CONSTRUCT) | Tag.BER_TAG_MASK), tag, writeLength(size))
|
||||
else:
|
||||
return (((Class.BER_CLASS_APPL | BerPc.BER_CONSTRUCT) | (Tag.BER_TAG_MASK & tag)), writeLength(size))
|
||||
|
||||
def readBoolean(s):
|
||||
'''
|
||||
return boolean
|
||||
"""
|
||||
Return boolean
|
||||
@param s: stream
|
||||
@return: boolean
|
||||
'''
|
||||
"""
|
||||
if not readUniversalTag(s, Tag.BER_TAG_BOOLEAN, False):
|
||||
raise InvalidExpectedDataException("bad boolean tag")
|
||||
size = readLength(s)
|
||||
@@ -149,24 +170,24 @@ def readBoolean(s):
|
||||
return bool(b.value)
|
||||
|
||||
def writeBoolean(b):
|
||||
'''
|
||||
return structure that represent boolean in ber specification
|
||||
"""
|
||||
Return structure that represent boolean in BER specification
|
||||
@param b: boolean
|
||||
@return: ber boolean structure
|
||||
'''
|
||||
@return: BER boolean structure
|
||||
"""
|
||||
boolean = UInt8(0)
|
||||
if b:
|
||||
boolean = UInt8(0xff)
|
||||
return (writeUniversalTag(Tag.BER_TAG_BOOLEAN, False), writeLength(1), boolean)
|
||||
|
||||
def readInteger(s):
|
||||
'''
|
||||
read integer structure from stream
|
||||
"""
|
||||
Read integer structure from stream
|
||||
@param s: stream
|
||||
@return: int or long python
|
||||
'''
|
||||
"""
|
||||
if not readUniversalTag(s, Tag.BER_TAG_INTEGER, False):
|
||||
raise InvalidExpectedDataException("bad integer tag")
|
||||
raise InvalidExpectedDataException("Bad integer tag")
|
||||
|
||||
size = readLength(s)
|
||||
|
||||
@@ -189,14 +210,14 @@ def readInteger(s):
|
||||
s.readType(integer)
|
||||
return integer.value
|
||||
else:
|
||||
raise InvalidExpectedDataException("wrong integer size")
|
||||
raise InvalidExpectedDataException("Wrong integer size")
|
||||
|
||||
def writeInteger(value):
|
||||
'''
|
||||
write integer value
|
||||
"""
|
||||
Write integer value
|
||||
@param param: int or python long
|
||||
@return ber interger structure
|
||||
'''
|
||||
@return: BER integer structure
|
||||
"""
|
||||
if value <= 0xff:
|
||||
return (writeUniversalTag(Tag.BER_TAG_INTEGER, False), writeLength(1), UInt8(value))
|
||||
elif value <= 0xffff:
|
||||
@@ -205,30 +226,30 @@ def writeInteger(value):
|
||||
return (writeUniversalTag(Tag.BER_TAG_INTEGER, False), writeLength(4), UInt32Be(value))
|
||||
|
||||
def readOctetString(s):
|
||||
'''
|
||||
read ber string structure
|
||||
"""
|
||||
Read BER string structure
|
||||
@param s: stream
|
||||
@return: String
|
||||
'''
|
||||
"""
|
||||
if not readUniversalTag(s, Tag.BER_TAG_OCTET_STRING, False):
|
||||
raise InvalidExpectedDataException("unexpected ber tag")
|
||||
raise InvalidExpectedDataException("Unexpected BER tag")
|
||||
size = readLength(s)
|
||||
return String(s.read(size.value))
|
||||
|
||||
def writeOctetstring(value):
|
||||
'''
|
||||
write string in ber representation
|
||||
"""
|
||||
Write string in ber representation
|
||||
@param value: string
|
||||
@return: string ber structure
|
||||
'''
|
||||
"""
|
||||
return (writeUniversalTag(Tag.BER_TAG_OCTET_STRING, False), writeLength(len(value)), String(value))
|
||||
|
||||
def readEnumerated(s):
|
||||
'''
|
||||
read enumerated structure
|
||||
"""
|
||||
Read enumerated structure
|
||||
@param s: Stream
|
||||
@return: int or long
|
||||
'''
|
||||
"""
|
||||
if not readUniversalTag(s, Tag.BER_TAG_ENUMERATED, False):
|
||||
raise InvalidExpectedDataException("invalid ber tag")
|
||||
if readLength(s) != 1:
|
||||
|
||||
@@ -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.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.error import InvalidExpectedDataException, InvalidValue, InvalidSize
|
||||
from rdpy.protocol.rdp.ber import writeLength
|
||||
@@ -13,18 +36,18 @@ import ber, gcc, per
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt8)
|
||||
class Message(object):
|
||||
'''
|
||||
message type
|
||||
'''
|
||||
"""
|
||||
Message type
|
||||
"""
|
||||
MCS_TYPE_CONNECT_INITIAL = 0x65
|
||||
MCS_TYPE_CONNECT_RESPONSE = 0x66
|
||||
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt8)
|
||||
class DomainMCSPDU:
|
||||
'''
|
||||
domain mcs pdu header
|
||||
'''
|
||||
"""
|
||||
Domain MCS PDU header
|
||||
"""
|
||||
ERECT_DOMAIN_REQUEST = 1
|
||||
DISCONNECT_PROVIDER_ULTIMATUM = 8
|
||||
ATTACH_USER_REQUEST = 10
|
||||
@@ -37,27 +60,28 @@ class DomainMCSPDU:
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt16Be)
|
||||
class Channel:
|
||||
"""
|
||||
Channel id of main channels use in RDP
|
||||
"""
|
||||
MCS_GLOBAL_CHANNEL = 1003
|
||||
MCS_USERCHANNEL_BASE = 1001
|
||||
|
||||
class MCS(LayerAutomata):
|
||||
'''
|
||||
"""
|
||||
Multi Channel Service layer
|
||||
the main layer of RDP protocol
|
||||
is why he can do everything and more!
|
||||
'''
|
||||
|
||||
class MCSProxySender(Layer):
|
||||
'''
|
||||
Proxy use to set as trnsport layer for upper channel
|
||||
"""
|
||||
class MCSProxySender(StreamSender):
|
||||
"""
|
||||
Proxy use to set as transport layer for upper channel
|
||||
use to abstract channel id for presentation layer
|
||||
'''
|
||||
"""
|
||||
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
|
||||
'''
|
||||
"""
|
||||
self._mcs = mcs
|
||||
self._channelId = channelId
|
||||
|
||||
@@ -94,11 +118,10 @@ class MCS(LayerAutomata):
|
||||
|
||||
|
||||
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
|
||||
'''
|
||||
"""
|
||||
LayerAutomata.__init__(self, mode, presentation)
|
||||
self._clientSettings = gcc.ClientSettings()
|
||||
self._serverSettings = gcc.ServerSettings()
|
||||
@@ -110,17 +133,17 @@ class MCS(LayerAutomata):
|
||||
self._channelIdsRequest = {}
|
||||
|
||||
def connect(self):
|
||||
'''
|
||||
connection send for client mode
|
||||
"""
|
||||
Connection send for client mode
|
||||
a write connect initial packet
|
||||
'''
|
||||
"""
|
||||
self._clientSettings.core.serverSelectedProtocol = self._transport._selectedProtocol
|
||||
self.sendConnectInitial()
|
||||
|
||||
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 each unconnect channel send a request
|
||||
if not self._channelIdsRequest.has_key(channelId):
|
||||
@@ -138,9 +161,9 @@ class MCS(LayerAutomata):
|
||||
layer.connect()
|
||||
|
||||
def sendConnectInitial(self):
|
||||
'''
|
||||
send connect initial packet
|
||||
'''
|
||||
"""
|
||||
Send connect initial packet
|
||||
"""
|
||||
ccReq = gcc.writeConferenceCreateRequest(self._clientSettings)
|
||||
ccReqStream = Stream()
|
||||
ccReqStream.writeType(ccReq)
|
||||
@@ -155,28 +178,28 @@ class MCS(LayerAutomata):
|
||||
self.setNextState(self.recvConnectResponse)
|
||||
|
||||
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)))
|
||||
|
||||
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))
|
||||
|
||||
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))
|
||||
|
||||
def recvConnectResponse(self, data):
|
||||
'''
|
||||
receive mcs connect response from server
|
||||
"""
|
||||
receive MCS connect response from server
|
||||
@param data: Stream
|
||||
'''
|
||||
"""
|
||||
ber.readApplicationTag(data, Message.MCS_TYPE_CONNECT_RESPONSE)
|
||||
ber.readEnumerated(data)
|
||||
ber.readInteger(data)
|
||||
@@ -196,10 +219,10 @@ class MCS(LayerAutomata):
|
||||
self.setNextState(self.recvAttachUserConfirm)
|
||||
|
||||
def recvAttachUserConfirm(self, data):
|
||||
'''
|
||||
receive an attach user confirm
|
||||
"""
|
||||
Receive an attach user confirm
|
||||
@param data: Stream
|
||||
'''
|
||||
"""
|
||||
opcode = UInt8()
|
||||
confirm = UInt8()
|
||||
data.readType((opcode, confirm))
|
||||
@@ -217,10 +240,10 @@ class MCS(LayerAutomata):
|
||||
self.connectNextChannel()
|
||||
|
||||
def recvChannelJoinConfirm(self, data):
|
||||
'''
|
||||
receive a channel join confirm from server
|
||||
"""
|
||||
Receive a channel join confirm from server
|
||||
@param data: Stream
|
||||
'''
|
||||
"""
|
||||
opcode = UInt8()
|
||||
confirm = UInt8()
|
||||
data.readType((opcode, confirm))
|
||||
@@ -239,10 +262,10 @@ class MCS(LayerAutomata):
|
||||
self.connectNextChannel()
|
||||
|
||||
def recvData(self, data):
|
||||
'''
|
||||
main receive method
|
||||
"""
|
||||
Main receive method
|
||||
@param data: Stream
|
||||
'''
|
||||
"""
|
||||
opcode = UInt8()
|
||||
data.readType(opcode)
|
||||
|
||||
@@ -278,51 +301,52 @@ class MCS(LayerAutomata):
|
||||
self._channelIds[channelId].recv(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
|
||||
'''
|
||||
"""
|
||||
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):
|
||||
'''
|
||||
write a special domain param structure
|
||||
"""
|
||||
Write a special domain parameter structure
|
||||
use in connection sequence
|
||||
@param maxChannels: number of mcs channel use
|
||||
@param maxUsers: number of mcs user used (1)
|
||||
@param maxChannels: number of MCS channel use
|
||||
@param maxUsers: number of MCS user used (1)
|
||||
@param maxTokens: unknown
|
||||
@param maxPduSize: unknown
|
||||
@return: domain param structure
|
||||
'''
|
||||
@return: domain parameter structure
|
||||
"""
|
||||
domainParam = (ber.writeInteger(maxChannels), ber.writeInteger(maxUsers), ber.writeInteger(maxTokens),
|
||||
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 writeMCSPDUHeader(self, mcsPdu, options = 0):
|
||||
'''
|
||||
write mcs pdu header
|
||||
@param mcsPdu: pdu code
|
||||
"""
|
||||
Write MCS PDU header
|
||||
@param mcsPdu: PDU code
|
||||
@param options: option contains in header
|
||||
@return: UInt8
|
||||
'''
|
||||
"""
|
||||
return (mcsPdu << 2) | options
|
||||
|
||||
def readMCSPDUHeader(self, opcode, mcsPdu):
|
||||
'''
|
||||
read mcsPdu header and return options parameter
|
||||
"""
|
||||
Read mcsPdu header and return options parameter
|
||||
@param opcode: UInt8 opcode
|
||||
@param mcsPdu: mcsPdu will be checked
|
||||
@return: true if opcode is correct
|
||||
'''
|
||||
"""
|
||||
return (opcode >> 2) == mcsPdu
|
||||
|
||||
def readDomainParams(self, s):
|
||||
'''
|
||||
read domain params structure
|
||||
"""
|
||||
Read domain parameters structure
|
||||
@return: (max_channels, max_users, max_tokens, max_pdu_size)
|
||||
'''
|
||||
"""
|
||||
if not ber.readUniversalTag(s, ber.Tag.BER_TAG_SEQUENCE, True):
|
||||
raise InvalidValue("bad BER tags")
|
||||
ber.readLength(s)#length
|
||||
|
||||
@@ -2,16 +2,12 @@
|
||||
@author: citronneur
|
||||
'''
|
||||
|
||||
from rdpy.network.layer import LayerAutomata, LayerMode
|
||||
from rdpy.network.type import CompositeType, UniString, String, UInt8, UInt16Le, UInt32Le, sizeof, ArrayType,\
|
||||
FactoryType
|
||||
from rdpy.network.layer import LayerAutomata
|
||||
from rdpy.network.type import CompositeType, UniString, String, UInt8, UInt16Le, UInt32Le, sizeof, ArrayType, FactoryType
|
||||
from rdpy.network.const import ConstAttributes, TypeAttributes
|
||||
from rdpy.network.error import InvalidExpectedDataException, ErrorReportedFromPeer
|
||||
|
||||
import gcc
|
||||
import lic
|
||||
import caps
|
||||
import rdp
|
||||
import gcc, lic, caps
|
||||
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt16Le)
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
@author: sylvain
|
||||
'''
|
||||
from twisted.internet import protocol
|
||||
import tpkt, tpdu, mcs, pdu
|
||||
from rdpy.network.layer import LayerMode
|
||||
import tpkt, tpdu, mcs, pdu
|
||||
|
||||
class RDPController(object):
|
||||
"""
|
||||
|
||||
@@ -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...)
|
||||
"""
|
||||
|
||||
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.error import InvalidExpectedDataException
|
||||
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.failureCode = UInt32Le(conditional = lambda: self.code == NegociationType.TYPE_RDP_NEG_FAILURE)
|
||||
|
||||
class TPDU(LayerAutomata):
|
||||
class TPDU(LayerAutomata, StreamSender):
|
||||
"""
|
||||
TPDU layer management
|
||||
there is an connection automata
|
||||
@@ -223,7 +223,7 @@ class TPDU(LayerAutomata):
|
||||
"""
|
||||
header = TPDUDataHeader()
|
||||
data.readType(header)
|
||||
LayerAutomata.recv(self, data)
|
||||
self._presentation.recv(data)
|
||||
|
||||
def sendConnectionRequest(self):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user