code refactoring + integrate rdesktop code for bitmap decompression

This commit is contained in:
speyrefitte
2014-06-30 18:04:51 +02:00
parent cbb9976866
commit c53841ac57
13 changed files with 1083 additions and 1023 deletions

View File

@@ -53,7 +53,7 @@ class RDPClientQtFactory(rdp.ClientFactory):
#create qt widget
self._w = client.getWidget()
self._w.resize(self._width, self._height)
self._w.setWindowTitle('rdpyclient-rdp')
self._w.setWindowTitle('rdpy-rdpclient')
self._w.show()
return client

View File

@@ -46,7 +46,7 @@ class RFBClientQtFactory(rfb.ClientFactory):
#create qt widget
self._w = client.getWidget()
self._w.resize(1024, 800)
self._w.setWindowTitle('rdpyclient-vnc')
self._w.setWindowTitle('rdpy-vncclient')
self._w.show()
return client

View File

@@ -4,6 +4,5 @@
#include "../../src/rle/rle.h"
%End
int rle_decode_uint8(void* output, int width, int height, char* input, int size);
int rle_decode_uint16(void* output, int width, int height, char* input, int size);
int rle_decode_uint24(void* output, int width, int height, char* input, int size);
int bitmap_decompress(void * output, int width, int height, char * input, int size, int Bpp);

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,6 @@
#ifndef _RLE_H_
#define _RLE_H_
int rle_decode_uint8(char* output, int width, int height, char* input, int size);
int rle_decode_uint16(char* output, int width, int height, char* input, int size);
int rle_decode_uint24(char* output, int width, int height, char* input, int size);
int bitmap_decompress(char * output, int width, int height, char * input, int size, int Bpp);
#endif

View File

@@ -1,35 +0,0 @@
#ifndef _RLE_M_H_
#define _RLE_M_H_
#include "rle.h"
#define CVAL(p) ((unsigned char)(*(p++)))
#if defined(B_ENDIAN)
#define EIK0 1
#define EIK1 0
#else
#define EIK0 0
#define EIK1 1
#endif
#define REPEAT(statement) \
{ \
while ((count > 0) && (x < width)) \
{ \
statement; \
count--; \
x++; \
} \
}
#define MASK_UPDATE \
{ \
mixmask <<= 1; \
if ((mixmask & 0xff) == 0) \
{ \
mask = fom_mask ? fom_mask : CVAL(input); \
mixmask = 1; \
} \
}
#endif

View File

@@ -28,17 +28,15 @@ import struct
from copy import deepcopy
from StringIO import StringIO
from error import InvalidValue
from rdpy.network.error import InvalidExpectedDataException, InvalidSize
from rdpy.network.error import InvalidExpectedDataException, InvalidSize, CallPureVirtualFuntion
def sizeof(element):
'''
byte size of type
sum sizeof of tuple element
and count only element that condition
is true at sizeof call
"""
Byte size of type sum sizeof of tuple element
And count only element that condition is true at sizeof call
@param element: Type or Tuple(Type | Tuple,)
@return: size of element in byte
'''
"""
if isinstance(element, tuple) or isinstance(element, list):
size = 0
for i in element:
@@ -50,18 +48,16 @@ def sizeof(element):
class Type(object):
'''
root type object inheritance
record conditional optional of constant
mechanism
'''
"""
Root type object inheritance
Record conditional optional of constant mechanism
"""
def __init__(self, conditional = lambda:True, optional = False, constant = False):
'''
constructor of any type object
"""
@param conditional : function call before read or write type
@param optional: boolean check before read if there is still data in stream
@param constant: if true check any changement of object during reading
'''
@param constant: if true check any modification of object during reading
"""
self._conditional = conditional
self._optional = optional
self._constant = constant
@@ -73,22 +69,22 @@ class Type(object):
self._is_writed = False
def write(self, s):
'''
write type into stream if conditional is true
and call private
"""
Write type into stream if conditional is true
Call virtual __write__ method
@param s: Stream which will be written
'''
"""
self._is_writed = self._conditional()
if not self._is_writed:
return
self.__write__(s)
def read(self, s):
'''
read type from stream s if conditional
is true and check constantness
"""
Read type from stream s if conditional is true
Check constantness
@param s: Stream
'''
"""
self._is_readed = self._conditional()
if not self._is_readed:
return
@@ -108,56 +104,54 @@ class Type(object):
raise InvalidExpectedDataException("%s const value expected %s != %s"%(self.__class__, old.value, self.value))
def __read__(self, s):
'''
interface definition of private read funtion
"""
Interface definition of private read function
@param s: Stream
'''
pass
"""
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "__read__", "Type"))
def __write__(self, s):
'''
interface definition of private write funtion
"""
Interface definition of private write function
@param s: Stream
'''
pass
"""
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "__write__", "Type"))
def __sizeof__(self):
'''
return size of type use for sizeof function
"""
Return size of type use for sizeof function
@return: size in byte of type
'''
pass
"""
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "__sizeof__", "Type"))
class CallableValue(object):
'''
wrap access of callable value.
"""
Wrap access of callable value.
When use getter value is call.
Constant value can also be wrap
and will be transformed into callable value(lambda function)
'''
Constant value can also be wrap and will be transformed into callable value(lambda function)
"""
def __init__(self, value):
'''
construtor
"""
@param value: value will be wrapped (constant | lambda | function)
'''
"""
self._value = None
self.value = value
def __getValue__(self):
'''
can be overwritten to add specific check before
"""
Can be overwritten to add specific check before
self.value is call
@return: result of callbale value
'''
@return: result of callable value
"""
return self._value()
def __setValue__(self, value):
'''
can be overwritten to add specific check before
"""
Can be overwritten to add specific check before
self.value = value is call
check if value is callable and if not transform it
Check if value is callable and if not transform it
@param value: new value wrapped if constant -> lambda function
'''
"""
value_callable = lambda:value
if callable(value):
value_callable = value
@@ -166,37 +160,34 @@ class CallableValue(object):
@property
def value(self):
'''
shortcut to access inner value
main getter of value
"""
Shortcut to access inner value main getter of value
@return: result of callable value
'''
"""
return self.__getValue__()
@value.setter
def value(self, value):
'''
setter of value after check it
main setter of value
@param value: new value encompass in valuetype object
'''
"""
Setter of value after check it main setter of value
@param value: new value encompass in value type object
"""
self.__setValue__(value)
class SimpleType(Type, CallableValue):
'''
simple type
'''
"""
Simple type
"""
def __init__(self, structFormat, typeSize, signed, value, conditional = lambda:True, optional = False, constant = False):
'''
constructor of simple type
"""
@param structFormat: letter that represent type in struct package
@param typeSize: size in byte of type
@param signed: true if type represent a signed type
@param value: value recorded in this object (can be callable value which be call when is acces usefull with closure)
@param value: value recorded in this object (can be callable value which be call when is access useful with closure)
@param conditional : function call before read or write type
@param optional: boolean check before read if there is still data in stream
@param constant: if true check any changement of object during reading
'''
@param constant: if true check any modification of object during reading
"""
self._signed = signed
self._typeSize = typeSize
self._structFormat = structFormat
@@ -204,13 +195,12 @@ class SimpleType(Type, CallableValue):
CallableValue.__init__(self, value)
def __getValue__(self):
'''
CallableValue overwrite
check mask type of value
"""
CallableValue overwrite check mask type of value
use CallableValue access
@return: python value wrap into type
@return: Python value wrap into type
@raise InvalidValue: if value doesn't respect type range
'''
"""
value = CallableValue.__getValue__(self)
if not self.isInRange(value):
raise InvalidValue("value is out of range for %s"%self.__class__)
@@ -221,12 +211,12 @@ class SimpleType(Type, CallableValue):
return value & self.mask()
def __setValue__(self, value):
'''
"""
CallableValue overwrite
check mask type of value
@param value: new value encompass in object (respect python type | lambda | function)
Check mask type of value
@param value: new value encompass in object (respect Python type | lambda | function)
@raise InvalidValue: if value doesn't respect type range
'''
"""
#check static value range
if not callable(value) and not self.isInRange(value):
raise InvalidValue("value is out of range for %s"%self.__class__)
@@ -235,40 +225,40 @@ class SimpleType(Type, CallableValue):
def __cmp__(self, other):
'''
compare inner value
magic function of python use for any compare operators
"""
Compare inner value
Magic function of Python use for any compare operators
@param other: SimpleType value which will be compared with self value
or try to construct same type as self around other value
@return: python value compare
'''
@return: Python value compare
"""
if not isinstance(other, SimpleType):
other = self.__class__(other)
return self.value.__cmp__(other.value)
def __write__(self, s):
'''
write value in stream s
use struct package to pack value
"""
Write value in stream s
Use Struct package to pack value
@param s: Stream which will be written
'''
"""
s.write(struct.pack(self._structFormat, self.value))
def __read__(self, s):
'''
read inner value from stream
use struct package
"""
Read inner value from stream
Use struct package
@param s: Stream
'''
"""
if s.dataLen() < self._typeSize:
raise InvalidSize("Stream is too small to read expected data")
self.value = struct.unpack(self._structFormat, s.read(self._typeSize))[0]
def mask(self):
'''
compute bit mask for type
because in python all numbers are int long or float
'''
"""
Compute bit mask for type
Because in Python all numbers are Int long or float
"""
if not self.__dict__.has_key("_mask"):
mask = 0xff
for i in range(1, self._typeSize):
@@ -277,106 +267,106 @@ class SimpleType(Type, CallableValue):
return self._mask
def isInRange(self, value):
'''
check if value is in mask range
@param value: python value
"""
Check if value is in mask range
@param value: Python value
@return: true if value is in type range
'''
"""
if self._signed:
return not (value < -(self.mask() >> 1) or value > (self.mask() >> 1))
else:
return not (value < 0 or value > self.mask())
def __sizeof__(self):
'''
return size of type
"""
Return size of type
@return: typeSize pass in constructor
'''
"""
return self._typeSize
def __invert__(self):
'''
implement not operator
"""
Implement not operator
@return: __class__ value
'''
"""
invert = ~self.value
if not self._signed:
invert &= self.mask()
return self.__class__(invert)
def __add__(self, other):
'''
implement addition operator
"""
Implement addition operator
@param other: SimpleType value or try to construct same type as self
around other value
@return: self.__class__ object with add result
@raise InvalidValue: if new value is out of bound
'''
"""
if not isinstance(other, SimpleType):
other = self.__class__(other)
return self.__class__(self.value.__add__(other.value))
def __sub__(self, other):
'''
implement sub operator
"""
Implement sub operator
@param other: SimpleType value or try to construct same type as self
around other value
@return: self.__class__ object with sub result
@raise InvalidValue: if new value is out of bound
'''
"""
if not isinstance(other, SimpleType):
other = self.__class__(other)
return self.__class__(self.value.__sub__(other.value))
def __and__(self, other):
'''
implement bitwise and operator
"""
Implement bitwise and operator
@param other: SimpleType value or try to construct same type as self
around other value
@return: self.__class__ object with and result
'''
"""
if not isinstance(other, SimpleType):
other = self.__class__(other)
return self.__class__(self.value.__and__(other.value))
def __or__(self, other):
'''
"""
implement bitwise or operator
@param other: SimpleType value or try to construct same type as self
around other value
@return: self.__class__ object with or result
'''
"""
if not isinstance(other, SimpleType):
other = self.__class__(other)
return self.__class__(self.value.__or__(other.value))
def __xor__(self, other):
'''
implement bitwise xor operator
"""
Implement bitwise xor operator
@param other: SimpleType value or try to construct same type as self
around other value
@return: self.__class__ object with or result
'''
"""
if not isinstance(other, SimpleType):
other = self.__class__(other)
return self.__class__(self.value.__xor__(other.value))
def __lshift__(self, other):
'''
left shift operator
@param other: python int
"""
Left shift operator
@param other: Python Int
@return: self.__class__ object with or result
'''
"""
if not isinstance(other, SimpleType):
other = self.__class__(other)
return self.__class__(self.value.__lshift__(other.value))
def __rshift__(self, other):
'''
left shift operator
"""
Left shift operator
@param other: python int
@return: self.__class__ object with or result
'''
"""
if not isinstance(other, SimpleType):
other = self.__class__(other)
return self.__class__(self.value.__rshift__(other.value))

View File

@@ -1,7 +1,7 @@
'''
@author sylvain
@summary gcc language
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
@see: http://msdn.microsoft.com/en-us/library/cc240508.aspx
'''
from rdpy.network.const import ConstAttributes, TypeAttributes
from rdpy.network.type import UInt8, UInt16Le, UInt32Le, CompositeType, String, UniString, Stream, sizeof

View File

@@ -18,14 +18,12 @@
#
"""
Implement Multi Channel Service
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, LayerMode, StreamSender
from rdpy.network.type import sizeof, Stream, UInt8, UInt16Be
from rdpy.network.error import InvalidExpectedDataException, InvalidValue, InvalidSize
@@ -33,8 +31,6 @@ from rdpy.protocol.rdp.ber import writeLength
import ber, gcc, per
@ConstAttributes
@TypeAttributes(UInt8)
class Message(object):
"""
Message type
@@ -42,8 +38,6 @@ class Message(object):
MCS_TYPE_CONNECT_INITIAL = 0x65
MCS_TYPE_CONNECT_RESPONSE = 0x66
@ConstAttributes
@TypeAttributes(UInt8)
class DomainMCSPDU:
"""
Domain MCS PDU header
@@ -57,8 +51,6 @@ class DomainMCSPDU:
SEND_DATA_REQUEST = 25
SEND_DATA_INDICATION = 26
@ConstAttributes
@TypeAttributes(UInt16Be)
class Channel:
"""
Channel id of main channels use in RDP
@@ -126,7 +118,7 @@ class MCS(LayerAutomata):
self._clientSettings = gcc.ClientSettings()
self._serverSettings = gcc.ServerSettings()
#default user Id
self._userId = UInt16Be(1)
self._userId = 1
#list of channel use in this layer and connection state
self._channelIds = {Channel.MCS_GLOBAL_CHANNEL: presentation}
#use to record already requested channel
@@ -137,7 +129,7 @@ class MCS(LayerAutomata):
Connection send for client mode
a write connect initial packet
"""
self._clientSettings.core.serverSelectedProtocol = self._transport._selectedProtocol
self._clientSettings.core.serverSelectedProtocol.value = self._transport._selectedProtocol
self.sendConnectInitial()
def connectNextChannel(self):
@@ -173,7 +165,7 @@ class MCS(LayerAutomata):
self.writeDomainParams(1, 1, 1, 0x420),
self.writeDomainParams(0xffff, 0xfc17, 0xffff, 0xffff),
ber.writeOctetstring(ccReqStream.getvalue()))
self._transport.send((ber.writeApplicationTag(Message.MCS_TYPE_CONNECT_INITIAL, sizeof(tmp)), tmp))
self._transport.send((ber.writeApplicationTag(UInt8(Message.MCS_TYPE_CONNECT_INITIAL), sizeof(tmp)), tmp))
#we must receive a connect response
self.setNextState(self.recvConnectResponse)
@@ -181,26 +173,26 @@ class MCS(LayerAutomata):
"""
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(UInt8(DomainMCSPDU.ERECT_DOMAIN_REQUEST)), per.writeInteger(0), per.writeInteger(0)))
def sendAttachUserRequest(self):
"""
Send a formated attach user request for RDP connection
"""
self._transport.send(self.writeMCSPDUHeader(DomainMCSPDU.ATTACH_USER_REQUEST))
self._transport.send(self.writeMCSPDUHeader(UInt8(DomainMCSPDU.ATTACH_USER_REQUEST)))
def sendChannelJoinRequest(self, channelId):
"""
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(UInt8(DomainMCSPDU.CHANNEL_JOIN_REQUEST)), UInt16Be(self._userId), UInt16Be(channelId)))
def recvConnectResponse(self, data):
"""
receive MCS connect response from server
@param data: Stream
"""
ber.readApplicationTag(data, Message.MCS_TYPE_CONNECT_RESPONSE)
ber.readApplicationTag(data, UInt8(Message.MCS_TYPE_CONNECT_RESPONSE))
ber.readEnumerated(data)
ber.readInteger(data)
self.readDomainParams(data)
@@ -225,13 +217,15 @@ class MCS(LayerAutomata):
"""
opcode = UInt8()
confirm = UInt8()
userId = UInt16Be()
data.readType((opcode, confirm))
if not self.readMCSPDUHeader(opcode, DomainMCSPDU.ATTACH_USER_CONFIRM):
if not self.readMCSPDUHeader(opcode.value, DomainMCSPDU.ATTACH_USER_CONFIRM):
raise InvalidExpectedDataException("invalid MCS PDU")
if confirm != 0:
raise Exception("server reject user")
if opcode & UInt8(2) == UInt8(2):
data.readType(self._userId)
data.readType(userId)
self._userId = userId.value
#build channel list because we have user id
#add default channel + channels accepted by gcc connection sequence
@@ -247,7 +241,7 @@ class MCS(LayerAutomata):
opcode = UInt8()
confirm = UInt8()
data.readType((opcode, confirm))
if not self.readMCSPDUHeader(opcode, DomainMCSPDU.CHANNEL_JOIN_CONFIRM):
if not self.readMCSPDUHeader(opcode.value, DomainMCSPDU.CHANNEL_JOIN_CONFIRM):
raise InvalidExpectedDataException("invalid MCS PDU")
userId = UInt16Be()
channelId = UInt16Be()
@@ -269,11 +263,11 @@ class MCS(LayerAutomata):
opcode = UInt8()
data.readType(opcode)
if self.readMCSPDUHeader(opcode, DomainMCSPDU.DISCONNECT_PROVIDER_ULTIMATUM):
if self.readMCSPDUHeader(opcode.value, DomainMCSPDU.DISCONNECT_PROVIDER_ULTIMATUM):
print "receive DISCONNECT_PROVIDER_ULTIMATUM"
self.close()
elif not self.readMCSPDUHeader(opcode, DomainMCSPDU.SEND_DATA_INDICATION):
elif not self.readMCSPDUHeader(opcode.value, DomainMCSPDU.SEND_DATA_INDICATION):
raise InvalidExpectedDataException("invalid expected mcs opcode")
userId = UInt16Be()
@@ -306,7 +300,7 @@ class MCS(LayerAutomata):
@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))
self._transport.send((self.writeMCSPDUHeader(UInt8(DomainMCSPDU.SEND_DATA_REQUEST)), UInt16Be(self._userId), UInt16Be(channelId), UInt8(0x70), UInt16Be(sizeof(data)) | UInt16Be(0x8000), data))
def writeDomainParams(self, maxChannels, maxUsers, maxTokens, maxPduSize):
@@ -336,7 +330,7 @@ class MCS(LayerAutomata):
def readMCSPDUHeader(self, opcode, mcsPdu):
"""
Read mcsPdu header and return options parameter
@param opcode: UInt8 opcode
@param opcode: opcode
@param mcsPdu: mcsPdu will be checked
@return: true if opcode is correct
"""

View File

@@ -1,6 +1,27 @@
'''
@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 the main graphic layer
In this layer are managed all mains bitmap update orders end user inputs
"""
from rdpy.network.layer import LayerAutomata
from rdpy.network.type import CompositeType, UniString, String, UInt8, UInt16Le, UInt32Le, sizeof, ArrayType, FactoryType
@@ -12,18 +33,18 @@ import gcc, lic, caps
@ConstAttributes
@TypeAttributes(UInt16Le)
class SecurityFlag(object):
'''
microsoft security flags
'''
"""
Microsoft security flags
"""
SEC_INFO_PKT = 0x0040
SEC_LICENSE_PKT = 0x0080
@ConstAttributes
@TypeAttributes(UInt32Le)
class InfoFlag(object):
'''
client capabilities informations
'''
"""
Client capabilities informations
"""
INFO_MOUSE = 0x00000001
INFO_DISABLECTRLALTDEL = 0x00000002
INFO_AUTOLOGON = 0x00000008
@@ -47,9 +68,9 @@ class InfoFlag(object):
@ConstAttributes
@TypeAttributes(UInt32Le)
class PerfFlag(object):
'''
network performances flag
'''
"""
Network performances flag
"""
PERF_DISABLE_WALLPAPER = 0x00000001
PERF_DISABLE_FULLWINDOWDRAG = 0x00000002
PERF_DISABLE_MENUANIMATIONS = 0x00000004
@@ -62,16 +83,19 @@ class PerfFlag(object):
@ConstAttributes
@TypeAttributes(UInt16Le)
class AfInet(object):
"""
IPv4 or IPv6 adress style
"""
AF_INET = 0x00002
AF_INET6 = 0x0017
@ConstAttributes
@TypeAttributes(UInt16Le)
class PDUType(object):
'''
data pdu type primary index
"""
Data PDU type primary index
@see: http://msdn.microsoft.com/en-us/library/cc240576.aspx
'''
"""
PDUTYPE_DEMANDACTIVEPDU = 0x11
PDUTYPE_CONFIRMACTIVEPDU = 0x13
PDUTYPE_DEACTIVATEALLPDU = 0x16
@@ -81,10 +105,10 @@ class PDUType(object):
@ConstAttributes
@TypeAttributes(UInt8)
class PDUType2(object):
'''
data pdu type secondary index
"""
Data PDU type secondary index
@see: http://msdn.microsoft.com/en-us/library/cc240577.aspx
'''
"""
PDUTYPE2_UPDATE = 0x02
PDUTYPE2_CONTROL = 0x14
PDUTYPE2_POINTER = 0x1B
@@ -113,10 +137,10 @@ class PDUType2(object):
@ConstAttributes
@TypeAttributes(UInt8)
class StreamId(object):
'''
stream priority
"""
Stream priority
@see: http://msdn.microsoft.com/en-us/library/cc240577.aspx
'''
"""
STREAM_UNDEFINED = 0x00
STREAM_LOW = 0x01
STREAM_MED = 0x02
@@ -125,10 +149,10 @@ class StreamId(object):
@ConstAttributes
@TypeAttributes(UInt8)
class CompressionOrder(object):
'''
pdu compression order
"""
PDU compression order
@see: http://msdn.microsoft.com/en-us/library/cc240577.aspx
'''
"""
CompressionTypeMask = 0x0F
PACKET_COMPRESSED = 0x20
PACKET_AT_FRONT = 0x40
@@ -137,10 +161,10 @@ class CompressionOrder(object):
@ConstAttributes
@TypeAttributes(UInt8)
class CompressionType(object):
'''
pdu compression type
"""
PDU compression type
@see: http://msdn.microsoft.com/en-us/library/cc240577.aspx
'''
"""
PACKET_COMPR_TYPE_8K = 0x0
PACKET_COMPR_TYPE_64K = 0x1
PACKET_COMPR_TYPE_RDP6 = 0x2
@@ -149,10 +173,10 @@ class CompressionType(object):
@ConstAttributes
@TypeAttributes(UInt16Le)
class Action(object):
'''
"""
Action flag use in Control PDU packet
@see: http://msdn.microsoft.com/en-us/library/cc240492.aspx
'''
"""
CTRLACTION_REQUEST_CONTROL = 0x0001
CTRLACTION_GRANTED_CONTROL = 0x0002
CTRLACTION_DETACH = 0x0003
@@ -161,30 +185,30 @@ class Action(object):
@ConstAttributes
@TypeAttributes(UInt16Le)
class PersistentKeyListFlag(object):
'''
use to determine the number of persistent key packet
"""
Use to determine the number of persistent key packet
@see: http://msdn.microsoft.com/en-us/library/cc240495.aspx
'''
"""
PERSIST_FIRST_PDU = 0x01
PERSIST_LAST_PDU = 0x02
@ConstAttributes
@TypeAttributes(UInt16Le)
class BitmapFlag(object):
'''
use in bitmap update PDU
"""
Use in bitmap update PDU
@see: http://msdn.microsoft.com/en-us/library/cc240612.aspx
'''
"""
BITMAP_COMPRESSION = 0x0001
NO_BITMAP_COMPRESSION_HDR = 0x0400
@ConstAttributes
@TypeAttributes(UInt16Le)
class UpdateType(object):
'''
use in update pdu to determine which type of update
"""
Use in update PDU to determine which type of update
@see: http://msdn.microsoft.com/en-us/library/cc240608.aspx
'''
"""
UPDATETYPE_ORDERS = 0x0000
UPDATETYPE_BITMAP = 0x0001
UPDATETYPE_PALETTE = 0x0002
@@ -193,10 +217,10 @@ class UpdateType(object):
@ConstAttributes
@TypeAttributes(UInt32Le)
class ErrorInfo(object):
'''
Error code use in Error info pdu
"""
Error code use in Error info PDU
@see: http://msdn.microsoft.com/en-us/library/cc240544.aspx
'''
"""
ERRINFO_RPC_INITIATED_DISCONNECT = 0x00000001
ERRINFO_RPC_INITIATED_LOGOFF = 0x00000002
ERRINFO_IDLE_TIMEOUT = 0x00000003
@@ -404,11 +428,11 @@ class ErrorInfo(object):
}
class RDPInfo(CompositeType):
'''
client informations
contains credentials (very important packet)
"""
Client informations
Contains credentials (very important packet)
@see: http://msdn.microsoft.com/en-us/library/cc240475.aspx
'''
"""
def __init__(self, extendedInfoConditional):
CompositeType.__init__(self)
#code page
@@ -431,10 +455,10 @@ class RDPInfo(CompositeType):
self.extendedInfo = RDPExtendedInfo(conditional = extendedInfoConditional)
class RDPExtendedInfo(CompositeType):
'''
add more client informations
use for performance flag!!!
'''
"""
Add more client informations
Use for performance flag!!!
"""
def __init__(self, conditional):
CompositeType.__init__(self, conditional = conditional)
self.clientAddressFamily = AfInet.AF_INET
@@ -446,10 +470,10 @@ class RDPExtendedInfo(CompositeType):
#self.performanceFlags = PerfFlag.PERF_DISABLE_WALLPAPER | PerfFlag.PERF_DISABLE_MENUANIMATIONS | PerfFlag.PERF_DISABLE_CURSOR_SHADOW
class ShareControlHeader(CompositeType):
'''
"""
PDU share control header
@see: http://msdn.microsoft.com/en-us/library/cc240576.aspx
'''
"""
def __init__(self, totalLength, pduType, userId):
'''
constructor
@@ -462,10 +486,10 @@ class ShareControlHeader(CompositeType):
self.PDUSource = UInt16Le(userId.value + 1001)
class ShareDataHeader(CompositeType):
'''
"""
PDU share data header
@see: http://msdn.microsoft.com/en-us/library/cc240577.aspx
'''
"""
def __init__(self, size, pduType2 = None, userId = UInt16Le(), shareId = UInt32Le()):
CompositeType.__init__(self)
self.shareControlHeader = ShareControlHeader(size, PDUType.PDUTYPE_DATAPDU, userId)
@@ -478,10 +502,10 @@ class ShareDataHeader(CompositeType):
self.compressedLength = UInt16Le()
class DemandActivePDU(CompositeType):
'''
"""
@see: http://msdn.microsoft.com/en-us/library/cc240485.aspx
main use for capabilities exchange server -> client
'''
Main use for capabilities exchange server -> client
"""
def __init__(self, userId = UInt16Le()):
CompositeType.__init__(self)
self.shareControlHeader = ShareControlHeader(lambda:sizeof(self), PDUType.PDUTYPE_DEMANDACTIVEPDU, userId)
@@ -495,10 +519,10 @@ class DemandActivePDU(CompositeType):
self.sessionId = UInt32Le()
class ConfirmActivePDU(CompositeType):
'''
"""
@see: http://msdn.microsoft.com/en-us/library/cc240488.aspx
main use for capabilities confirm client -> sever
'''
Main use for capabilities confirm client -> sever
"""
def __init__(self, userId = UInt16Le()):
CompositeType.__init__(self)
self.shareControlHeader = ShareControlHeader(lambda:sizeof(self), PDUType.PDUTYPE_CONFIRMACTIVEPDU, userId)
@@ -512,21 +536,21 @@ class ConfirmActivePDU(CompositeType):
self.capabilitySets = ArrayType(caps.Capability, readLen = self.numberCapabilities)
class PersistentListEntry(CompositeType):
'''
use to record persistent key in PersistentListPDU
"""
Use to record persistent key in PersistentListPDU
@see: http://msdn.microsoft.com/en-us/library/cc240496.aspx
'''
"""
def __init__(self):
CompositeType.__init__(self)
self.key1 = UInt32Le()
self.key2 = UInt32Le()
class PersistentListPDU(CompositeType):
'''
"""
Use to indicate that bitmap cache was already
fill with some keys from previous session
Fill with some keys from previous session
@see: http://msdn.microsoft.com/en-us/library/cc240495.aspx
'''
"""
def __init__(self, userId = UInt16Le(), shareId = UInt32Le()):
CompositeType.__init__(self)
self.shareDataHeader = ShareDataHeader(lambda:sizeof(self), PDUType2.PDUTYPE2_BITMAPCACHE_PERSISTENT_LIST, userId, shareId)
@@ -546,9 +570,9 @@ class PersistentListPDU(CompositeType):
self.entries = ArrayType(PersistentListEntry, readLen = UInt16Le(lambda:(self.numEntriesCache0 + self.numEntriesCache1 + self.numEntriesCache2 + self.numEntriesCache3 + self.numEntriesCache4)))
class DataPDU(CompositeType):
'''
"""
Generic pdu packet use after connection sequence
'''
"""
def __init__(self, pduType = None, pduData = None, userId = UInt16Le(), shareId = UInt32Le()):
CompositeType.__init__(self)
self.shareDataHeader = ShareDataHeader(lambda:sizeof(self), pduType, userId, shareId)
@@ -576,18 +600,18 @@ class DataPDU(CompositeType):
self.pduData = FactoryType(pduData)
class SynchronizeDataPDU(CompositeType):
'''
"""
@see http://msdn.microsoft.com/en-us/library/cc240490.aspx
'''
"""
def __init__(self, targetUser = UInt16Le()):
CompositeType.__init__(self)
self.messageType = UInt16Le(1, constant = True)
self.targetUser = targetUser
class ControlDataPDU(CompositeType):
'''
"""
@see http://msdn.microsoft.com/en-us/library/cc240492.aspx
'''
"""
def __init__(self, action = None):
CompositeType.__init__(self)
self.action = UInt16Le(action.value, constant = True) if not action is None else UInt16Le()
@@ -595,21 +619,21 @@ class ControlDataPDU(CompositeType):
self.controlId = UInt32Le()
class ErrorInfoDataPDU(CompositeType):
'''
"""
Use to inform error in PDU layer
@see: http://msdn.microsoft.com/en-us/library/cc240544.aspx
'''
"""
def __init__(self, errorInfo = UInt32Le()):
CompositeType.__init__(self)
#use to collect error info pdu
self.errorInfo = errorInfo
class FontListDataPDU(CompositeType):
'''
"""
Use to indicate list of font. Deprecated packet
client -> server
@see: http://msdn.microsoft.com/en-us/library/cc240498.aspx
'''
"""
def __init__(self):
CompositeType.__init__(self)
self.numberFonts = UInt16Le()
@@ -618,11 +642,11 @@ class FontListDataPDU(CompositeType):
self.entrySize = UInt16Le(0x0032)
class FontMapDataPDU(CompositeType):
'''
"""
Use to indicate map of font. Deprecated packet (maybe the same as FontListDataPDU)
server -> client
@see: http://msdn.microsoft.com/en-us/library/cc240498.aspx
'''
"""
def __init__(self):
CompositeType.__init__(self)
self.numberEntries = UInt16Le()
@@ -631,11 +655,11 @@ class FontMapDataPDU(CompositeType):
self.entrySize = UInt16Le(0x0004)
class UpdateDataPDU(CompositeType):
'''
Update data pdu use by server to inform update img or palette
"""
Update data PDU use by server to inform update img or palette
for example
@see: http://msdn.microsoft.com/en-us/library/cc240608.aspx
'''
"""
def __init__(self, updateType = UInt16Le(), updateData = None):
CompositeType.__init__(self)
self.updateType = updateType
@@ -652,20 +676,20 @@ class UpdateDataPDU(CompositeType):
self.updateData = FactoryType(updateData, conditional = lambda:(self.updateType != UpdateType.UPDATETYPE_SYNCHRONIZE))
class BitmapUpdateDataPDU(CompositeType):
'''
"""
PDU use to send raw bitmap compressed or not
@see: http://msdn.microsoft.com/en-us/library/dd306368.aspx
'''
"""
def __init__(self):
CompositeType.__init__(self)
self.numberRectangles = UInt16Le()
self.rectangles = ArrayType(BitmapData, readLen = self.numberRectangles)
class BitmapCompressedDataHeader(CompositeType):
'''
"""
Compressed header of bitmap
@see: http://msdn.microsoft.com/en-us/library/cc240644.aspx
'''
"""
def __init__(self, conditional = lambda:True):
CompositeType.__init__(self, conditional = conditional)
self.cbCompFirstRowSize = UInt16Le(0x0000, constant = True)
@@ -676,9 +700,9 @@ class BitmapCompressedDataHeader(CompositeType):
self.cbUncompressedSize = UInt16Le()
class BitmapData(CompositeType):
'''
"""
Bitmap data here the screen capture
'''
"""
def __init__(self):
CompositeType.__init__(self)
self.destLeft = UInt16Le()
@@ -694,16 +718,15 @@ class BitmapData(CompositeType):
self.bitmapDataStream = String(readLen = UInt16Le(lambda:(self.bitmapLength.value if (self.flags | BitmapFlag.NO_BITMAP_COMPRESSION_HDR) else self.bitmapComprHdr.cbCompMainBodySize.value)))
class PDU(LayerAutomata):
'''
"""
Global channel for mcs that handle session
identification user, licensing management, and capabilities exchange
'''
"""
def __init__(self, mode, controller):
'''
Constructor
"""
@param mode: LayerMode
@param controller: controller use to inform orders
'''
"""
LayerAutomata.__init__(self, mode, None)
#logon info send from client to server
self._info = RDPInfo(extendedInfoConditional = lambda:self._transport.getGCCServerSettings().core.rdpVersion == gcc.Version.RDP_VERSION_5_PLUS)
@@ -745,26 +768,32 @@ class PDU(LayerAutomata):
self._controller = controller
def connect(self):
'''
connect event in client mode send logon info
next state recv licence pdu
'''
"""
Connect event in client mode send logon info
Next state recv licence pdu
"""
self.sendInfoPkt()
#next state is licence info PDU
self.setNextState(self.recvLicenceInfo)
def close(self):
"""
Send PDU close packet and call close method on transport method
"""
self._transport.send(ShareDataHeader(PDUType2.PDUTYPE2_SHUTDOWN_REQUEST, UInt16Le(self._transport.getUserId()), self._shareId))
def sendInfoPkt(self):
'''
send a logon info packet
'''
"""
Send a logon info packet
"""
#always send extended info because rdpy only accept rdp version 5 and more
self._transport.send((SecurityFlag.SEC_INFO_PKT, UInt16Le(), self._info))
def recvLicenceInfo(self, data):
'''
read license info packet and check if is a valid client info
"""
Read license info packet and check if is a valid client info
@param data: Stream
'''
"""
securityFlag = UInt16Le()
securityFlagHi = UInt16Le()
data.readType((securityFlag, securityFlagHi))
@@ -784,11 +813,11 @@ class PDU(LayerAutomata):
self.setNextState(self.recvDemandActivePDU)
def readDataPDU(self, data):
'''
"""
Read a DataPdu struct. If is an error pdu log and close layer
@param data: Stream from transport layer
@return:
'''
"""
#maybe an error message
dataPDU = DataPDU()
data.readType(dataPDU)
@@ -803,13 +832,13 @@ class PDU(LayerAutomata):
def recvDemandActivePDU(self, data):
'''
receive demand active PDU which contains
server capabilities. In this version of RDPY only
restricted group of capabilities are used.
send confirm active PDU
"""
Receive demand active PDU which contains
Server capabilities. In this version of RDPY only
Restricted group of capabilities are used.
Send confirm active PDU
@param data: Stream
'''
"""
demandActivePDU = DemandActivePDU()
data.readType(demandActivePDU)
@@ -821,40 +850,40 @@ class PDU(LayerAutomata):
self.sendConfirmActivePDU()
def recvServerSynchronizePDU(self, data):
'''
receive from server
"""
Receive from server
@param data: Stream from transport layer
'''
"""
dataPDU = self.readDataPDU(data)
if dataPDU.shareDataHeader.pduType2 != PDUType2.PDUTYPE2_SYNCHRONIZE:
raise InvalidExpectedDataException("Error in PDU layer automata : expected synchronizePDU")
self.setNextState(self.recvServerControlCooperatePDU)
def recvServerControlCooperatePDU(self, data):
'''
receive control cooperate pdu from server
"""
Receive control cooperate pdu from server
@param data: Stream from transport layer
'''
"""
dataPDU = self.readDataPDU(data)
if dataPDU.shareDataHeader.pduType2 != PDUType2.PDUTYPE2_CONTROL or dataPDU.pduData._value.action != Action.CTRLACTION_COOPERATE:
raise InvalidExpectedDataException("Error in PDU layer automata : expected controlCooperatePDU")
self.setNextState(self.recvServerControlGrantedPDU)
def recvServerControlGrantedPDU(self, data):
'''
receive last control pdu the granted control pdu
"""
Receive last control pdu the granted control pdu
@param data: Stream from transport layer
'''
"""
dataPDU = self.readDataPDU(data)
if dataPDU.shareDataHeader.pduType2 != PDUType2.PDUTYPE2_CONTROL or dataPDU.pduData._value.action != Action.CTRLACTION_GRANTED_CONTROL:
raise InvalidExpectedDataException("Error in PDU layer automata : expected controlGrantedPDU")
self.setNextState(self.recvServerFontMapPDU)
def recvServerFontMapPDU(self, data):
'''
last useless connection packet from server to client
"""
Last useless connection packet from server to client
@param data: Stream from transport layer
'''
"""
dataPDU = self.readDataPDU(data)
if dataPDU.shareDataHeader.pduType2 != PDUType2.PDUTYPE2_FONTMAP:
raise InvalidExpectedDataException("Error in PDU layer automata : expected fontMapPDU")
@@ -864,19 +893,19 @@ class PDU(LayerAutomata):
self.setNextState(self.recvDataPDU)
def recvDataPDU(self, data):
'''
main receive function after connection sequence
"""
Main receive function after connection sequence
@param data: Stream from transport layer
'''
"""
dataPDU = self.readDataPDU(data)
if dataPDU.shareDataHeader.pduType2 == PDUType2.PDUTYPE2_UPDATE and dataPDU.pduData._value.updateType == UpdateType.UPDATETYPE_BITMAP:
self._controller.recvBitmapUpdateDataPDU(dataPDU.pduData._value.updateData._value)
def sendConfirmActivePDU(self):
'''
send all client capabilities
'''
"""
Send all client capabilities
"""
#init general capability
generalCapability = self._clientCapabilities[caps.CapsType.CAPSTYPE_GENERAL].capability._value
generalCapability.osMajorType = caps.MajorType.OSMAJORTYPE_WINDOWS
@@ -903,7 +932,7 @@ class PDU(LayerAutomata):
inputCapability.imeFileName = self._transport.getGCCClientSettings().core.imeFileName
#make active PDU packet
confirmActivePDU = ConfirmActivePDU(self._transport.getUserId())
confirmActivePDU = ConfirmActivePDU(UInt16Le(self._transport.getUserId()))
confirmActivePDU.shareId = self._shareId
confirmActivePDU.capabilitySets._array = self._clientCapabilities.values()
self._transport.send(confirmActivePDU)
@@ -911,18 +940,18 @@ class PDU(LayerAutomata):
self.sendClientFinalizeSynchronizePDU()
def sendClientFinalizeSynchronizePDU(self):
'''
"""
send a synchronize PDU from client to server
'''
synchronizePDU = DataPDU(PDUType2.PDUTYPE2_SYNCHRONIZE, SynchronizeDataPDU(UInt16Le(self._transport.getChannelId().value)), self._transport.getUserId(), self._shareId)
"""
synchronizePDU = DataPDU(PDUType2.PDUTYPE2_SYNCHRONIZE, SynchronizeDataPDU(UInt16Le(self._transport.getChannelId())), UInt16Le(self._transport.getUserId()), self._shareId)
self._transport.send(synchronizePDU)
#ask for cooperation
controlCooperatePDU = DataPDU(PDUType2.PDUTYPE2_CONTROL, ControlDataPDU(Action.CTRLACTION_COOPERATE), self._transport.getUserId(), self._shareId)
controlCooperatePDU = DataPDU(PDUType2.PDUTYPE2_CONTROL, ControlDataPDU(Action.CTRLACTION_COOPERATE), UInt16Le(self._transport.getUserId()), self._shareId)
self._transport.send(controlCooperatePDU)
#request control
controlRequestPDU = DataPDU(PDUType2.PDUTYPE2_CONTROL, ControlDataPDU(Action.CTRLACTION_REQUEST_CONTROL), self._transport.getUserId(), self._shareId)
controlRequestPDU = DataPDU(PDUType2.PDUTYPE2_CONTROL, ControlDataPDU(Action.CTRLACTION_REQUEST_CONTROL), UInt16Le(self._transport.getUserId()), self._shareId)
self._transport.send(controlRequestPDU)
#send persistent list pdu I don't know why this packet is rejected maybe beacause we made a 0 size bitmapcache capability
@@ -931,7 +960,7 @@ class PDU(LayerAutomata):
#self._transport.send(persistentListPDU)
#deprecated font list pdu
fontListPDU = DataPDU(PDUType2.PDUTYPE2_FONTLIST, FontListDataPDU(), self._transport.getUserId(), self._shareId)
fontListPDU = DataPDU(PDUType2.PDUTYPE2_FONTLIST, FontListDataPDU(), UInt16Le(self._transport.getUserId()), self._shareId)
self._transport.send(fontListPDU)
self.setNextState(self.recvServerSynchronizePDU)

View File

@@ -18,22 +18,19 @@
#
"""
Implement transport pdu layer
Implement transport PDU layer
This layer have main goal to negociate ssl transport
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, 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
@ConstAttributes
@TypeAttributes(UInt8)
class MessageType(object):
"""
message type
Message type
"""
X224_TPDU_CONNECTION_REQUEST = 0xE0
X224_TPDU_CONNECTION_CONFIRM = 0xD0
@@ -41,32 +38,26 @@ class MessageType(object):
X224_TPDU_DATA = 0xF0
X224_TPDU_ERROR = 0x70
@ConstAttributes
@TypeAttributes(UInt8)
class NegociationType(object):
"""
negotiation header
Negotiation header
"""
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
Protocols available for TPDU layer
"""
PROTOCOL_RDP = 0x00000000
PROTOCOL_SSL = 0x00000001
PROTOCOL_HYBRID = 0x00000002
PROTOCOL_HYBRID_EX = 0x00000008
@ConstAttributes
@TypeAttributes(UInt32Le)
class NegotiationFailureCode(object):
"""
protocol negotiation failure code
Protocol negotiation failure code
"""
SSL_REQUIRED_BY_SERVER = 0x00000001
SSL_NOT_ALLOWED_BY_SERVER = 0x00000002
@@ -77,7 +68,7 @@ class NegotiationFailureCode(object):
class TPDUConnectMessage(CompositeType):
"""
header of TPDU connection messages
Header of TPDU connection messages
"""
def __init__(self, code):
"""
@@ -85,24 +76,24 @@ class TPDUConnectMessage(CompositeType):
"""
CompositeType.__init__(self)
self.len = UInt8(lambda:sizeof(self) - 1)
self.code = UInt8(code.value, constant = True)
self.code = UInt8(code, constant = True)
self.padding = (UInt16Be(), UInt16Be(), UInt8())
#read if there is enough data
self.protocolNeg = Negotiation(optional = True)
class TPDUDataHeader(CompositeType):
"""
header send when tpdu exchange application data
Header send when TPDU exchange application data
"""
def __init__(self):
CompositeType.__init__(self)
self.header = UInt8(2, constant = True)
self.messageType = UInt8(MessageType.X224_TPDU_DATA.value, constant = True)
self.messageType = UInt8(MessageType.X224_TPDU_DATA, constant = True)
self.separator = UInt8(0x80, constant = True)
class Negotiation(CompositeType):
"""
negociate request message
Negociate request message
@see: request -> http://msdn.microsoft.com/en-us/library/cc240500.aspx
@see: response -> http://msdn.microsoft.com/en-us/library/cc240506.aspx
@see: failure ->http://msdn.microsoft.com/en-us/library/cc240507.aspx
@@ -113,8 +104,8 @@ class Negotiation(CompositeType):
self.flag = UInt8(0)
#always 8
self.len = UInt16Le(0x0008, constant = True)
self.selectedProtocol = UInt32Le(conditional = lambda: self.code == NegociationType.TYPE_RDP_NEG_RSP)
self.failureCode = UInt32Le(conditional = lambda: self.code == NegociationType.TYPE_RDP_NEG_FAILURE)
self.selectedProtocol = UInt32Le(conditional = lambda: (self.code.value != NegociationType.TYPE_RDP_NEG_FAILURE))
self.failureCode = UInt32Le(conditional = lambda: (self.code.value == NegociationType.TYPE_RDP_NEG_FAILURE))
class TPDU(LayerAutomata, StreamSender):
"""
@@ -134,15 +125,15 @@ class TPDU(LayerAutomata, StreamSender):
#server selected selectedProtocol
self._selectedProtocol = Protocols.PROTOCOL_SSL
#Server mode informations for tls connexion
#Server mode informations for TLS connection
self._serverPrivateKeyFileName = None
self._serverCertificateFileName = None
def initTLSServerInfos(self, privateKeyFileName, certificateFileName):
"""
Init informations for ssl server connexion
Initialize informations for SSL server connection
@param privateKeyFileName: file contain server private key
@param certficiateFileName: file that contain publi key
@param certficiateFileName: file that contain public key
"""
self._serverPrivateKeyFileName = privateKeyFileName
self._serverCertificateFileName = certificateFileName
@@ -176,7 +167,7 @@ class TPDU(LayerAutomata, StreamSender):
if message.protocolNeg.failureCode._is_readed:
raise InvalidExpectedDataException("negotiation failure code %x"%message.protocolNeg.failureCode.value)
self._selectedProtocol = message.protocolNeg.selectedProtocol
self._selectedProtocol = message.protocolNeg.selectedProtocol.value
if self._selectedProtocol != Protocols.PROTOCOL_SSL:
raise InvalidExpectedDataException("only ssl protocol is supported in RDPY version")
@@ -190,8 +181,8 @@ class TPDU(LayerAutomata, StreamSender):
def recvConnectionRequest(self, data):
"""
read connection confirm packet
next state is send connection confirm
Read connection confirm packet
Next state is send connection confirm
@param data: Stream
@see : http://msdn.microsoft.com/en-us/library/cc240470.aspx
"""
@@ -199,16 +190,16 @@ class TPDU(LayerAutomata, StreamSender):
data.readType(message)
if not message.protocolNeg._is_readed or message.protocolNeg.failureCode._is_readed:
raise InvalidExpectedDataException("Too older rdp client")
raise InvalidExpectedDataException("Too older RDP client")
self._requestedProtocol = message.protocolNeg.selectedProtocol
self._requestedProtocol = message.protocolNeg.selectedProtocol.value
if not self._requestedProtocol & Protocols.PROTOCOL_SSL:
#send error message and quit
message = TPDUConnectMessage()
message.code = MessageType.X224_TPDU_CONNECTION_CONFIRM
message.protocolNeg.code = NegociationType.TYPE_RDP_NEG_FAILURE
message.protocolNeg.failureCode = NegotiationFailureCode.SSL_REQUIRED_BY_SERVER
message.code.value = MessageType.X224_TPDU_CONNECTION_CONFIRM
message.protocolNeg.code.value = NegociationType.TYPE_RDP_NEG_FAILURE
message.protocolNeg.failureCode.value = NegotiationFailureCode.SSL_REQUIRED_BY_SERVER
self._transport.send(message)
raise InvalidExpectedDataException("rdpy needs ssl client compliant")
@@ -217,8 +208,8 @@ class TPDU(LayerAutomata, StreamSender):
def recvData(self, data):
"""
read data header from packet
and pass to presentation layer
Read data header from packet
And pass to presentation layer
@param data: Stream
"""
header = TPDUDataHeader()
@@ -227,25 +218,25 @@ class TPDU(LayerAutomata, StreamSender):
def sendConnectionRequest(self):
"""
write connection request message
next state is recvConnectionConfirm
Write connection request message
Next state is recvConnectionConfirm
@see: http://msdn.microsoft.com/en-us/library/cc240500.aspx
"""
message = TPDUConnectMessage(MessageType.X224_TPDU_CONNECTION_REQUEST)
message.protocolNeg.code = NegociationType.TYPE_RDP_NEG_REQ
message.protocolNeg.selectedProtocol = self._requestedProtocol
message.protocolNeg.code.value = NegociationType.TYPE_RDP_NEG_REQ
message.protocolNeg.selectedProtocol.value = self._requestedProtocol
self._transport.send(message)
self.setNextState(self.recvConnectionConfirm)
def sendConnectionConfirm(self):
"""
write connection confirm message
next state is recvData
Write connection confirm message
Next state is recvData
@see : http://msdn.microsoft.com/en-us/library/cc240501.aspx
"""
message = TPDUConnectMessage(MessageType.X224_TPDU_CONNECTION_CONFIRM)
message.protocolNeg.code = NegociationType.TYPE_RDP_NEG_REQ
message.protocolNeg.selectedProtocol = self._selectedProtocol
message.protocolNeg.code.value = NegociationType.TYPE_RDP_NEG_REQ
message.protocolNeg.selectedProtocol.value = self._selectedProtocol
self._transport.send(message)
#_transport is TPKT and transport is TCP layer of twisted
self._transport.transport.startTLS(ServerTLSContext(self._serverPrivateKeyFileName, self._serverCertificateFileName))
@@ -254,8 +245,8 @@ class TPDU(LayerAutomata, StreamSender):
def send(self, message):
"""
write message packet for TPDU layer
add TPDU header
Write message packet for TPDU layer
Add TPDU header
@param message: network.Type message
"""
self._transport.send((TPDUDataHeader(), message))
@@ -294,7 +285,7 @@ class ClientTLSContext(ssl.ClientContextFactory):
class ServerTLSContext(ssl.DefaultOpenSSLContextFactory):
"""
server context factory for open ssl
Server context factory for open ssl
@param privateKeyFileName: Name of a file containing a private key
@param certificateFileName: Name of a file containing a certificate
"""

View File

@@ -32,7 +32,7 @@ class TPKT(RawLayer):
and determine if is a fast path packet
"""
#first byte of classic tpkt header
TPKT_PACKET = UInt8(3)
TPKT_PACKET = 3
def __init__(self, presentation):
"""
@@ -64,7 +64,7 @@ class TPKT(RawLayer):
#first read packet version
data.readType(self._lastPacketVersion)
#classic packet
if self._lastPacketVersion == TPKT.TPKT_PACKET:
if self._lastPacketVersion.value == TPKT.TPKT_PACKET:
#padding
data.readType(UInt8())
#read end header
@@ -122,4 +122,4 @@ class TPKT(RawLayer):
send encompassed data
@param message: network.Type message to send
"""
RawLayer.send(self, (TPKT.TPKT_PACKET, UInt8(0), UInt16Be(sizeof(message) + 4), message))
RawLayer.send(self, (UInt8(TPKT.TPKT_PACKET), UInt8(0), UInt16Be(sizeof(message) + 4), message))

View File

@@ -153,16 +153,23 @@ class RDPClientQt(RDPClientObserver, QAdaptor):
if bitsPerPixel == 16:
if isCompress:
image = QtGui.QImage(width, height, QtGui.QImage.Format_RGB16)
data = rle.rle_decode_uint16(image.bits(), width, height, data, len(data))
data = rle.bitmap_decompress(image.bits(), width, height, data, len(data), 2)
else:
image = QtGui.QImage(data, width, height, QtGui.QImage.Format_RGB16)
elif bitsPerPixel == 24:
if isCompress:
image = QtGui.QImage(width, height, QtGui.QImage.Format_RGB888)
data = rle.rle_decode_uint24(image.bits(), width, height, data, len(data))
image = QtGui.QImage(width, height, QtGui.QImage.Format_RGB24)
data = rle.bitmap_decompress(image.bits(), width, height, data, len(data), 3)
else:
image = QtGui.QImage(data, width, height, QtGui.QImage.Format_RGB24)
elif bitsPerPixel == 32:
if isCompress:
image = QtGui.QImage(width, height, QtGui.QImage.Format_RGB32)
data = rle.bitmap_decompress(image.bits(), width, height, data, len(data), 4)
else:
image = QtGui.QImage(data, width, height, QtGui.QImage.Format_RGB32)
else:
print "Receive image in bad format"
return