add server side for mcs layer
This commit is contained in:
@@ -11,7 +11,7 @@ from rdpy.protocol.rdp import rdp
|
||||
|
||||
class TestServerFactory(rdp.ServerFactory):
|
||||
def __init__(self):
|
||||
rdp.ServerFactory.__init__(self, "/home/sylvain/dev/certificate/rdpy.key", "/home/sylvain/dev/certificate/rdpy.crt")
|
||||
rdp.ServerFactory.__init__(self, "/home/speyrefitte/dev/certificate/rdpy.key", "/home/speyrefitte/dev/certificate/rdpy.crt")
|
||||
def startedConnecting(self, connector):
|
||||
pass
|
||||
|
||||
|
||||
@@ -439,6 +439,9 @@ class CompositeType(Type):
|
||||
break
|
||||
s.pos -= sizeof(self.__dict__[tmpName])
|
||||
raise e
|
||||
if not self._readLen is None and readLen < self._readLen.value:
|
||||
print "WARNING : still have correct data in packet %s, read it as padding"%self.__class__
|
||||
s.read(self._readLen.value - readLen)
|
||||
|
||||
def __write__(self, s):
|
||||
"""
|
||||
@@ -453,10 +456,10 @@ class CompositeType(Type):
|
||||
raise e
|
||||
|
||||
def __sizeof__(self):
|
||||
'''
|
||||
call sizeof on each subtype
|
||||
"""
|
||||
Call sizeof on each sub type
|
||||
@return: sum of sizeof of each public type attributes
|
||||
'''
|
||||
"""
|
||||
size = 0
|
||||
for name in self._typeName:
|
||||
size += sizeof(self.__dict__[name])
|
||||
@@ -665,7 +668,7 @@ class String(Type, CallableValue):
|
||||
'''
|
||||
String network type
|
||||
'''
|
||||
def __init__(self, value = "", readLen = UInt32Le(), conditional = lambda:True, optional = False, constant = False):
|
||||
def __init__(self, value = "", readLen = UInt32Le(), conditional = lambda:True, optional = False, constant = False, unicode = False):
|
||||
'''
|
||||
constructor with new string
|
||||
@param value: python string use for inner value
|
||||
@@ -673,11 +676,13 @@ class String(Type, CallableValue):
|
||||
@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 unicode: Encode and decode value as unicode
|
||||
'''
|
||||
Type.__init__(self, conditional = conditional, optional = optional, constant = constant)
|
||||
CallableValue.__init__(self, value)
|
||||
#type use to know read length
|
||||
self._readLen = readLen
|
||||
self._unicode = unicode
|
||||
|
||||
def __eq__(self, other):
|
||||
'''
|
||||
@@ -702,52 +707,60 @@ class String(Type, CallableValue):
|
||||
return self.value
|
||||
|
||||
def __write__(self, s):
|
||||
'''
|
||||
write the entire raw value
|
||||
"""
|
||||
Write the entire raw value
|
||||
@param s: Stream
|
||||
'''
|
||||
s.write(self.value)
|
||||
"""
|
||||
if self._unicode:
|
||||
s.write(encodeUnicode(self.value))
|
||||
else:
|
||||
s.write(self.value)
|
||||
|
||||
def __read__(self, s):
|
||||
'''
|
||||
read all stream if len of inner value is zero
|
||||
else read the len of inner string
|
||||
"""
|
||||
read all stream if length of inner value is zero
|
||||
else read the length of inner string
|
||||
@param s: Stream
|
||||
'''
|
||||
"""
|
||||
if self._readLen.value == 0:
|
||||
self.value = s.getvalue()
|
||||
else:
|
||||
self.value = s.read(self._readLen.value)
|
||||
|
||||
def __sizeof__(self):
|
||||
'''
|
||||
return len of string
|
||||
@return: len of inner string
|
||||
'''
|
||||
return len(self.value)
|
||||
|
||||
class UniString(String):
|
||||
'''
|
||||
string with unicode representation
|
||||
'''
|
||||
def write(self, s):
|
||||
'''
|
||||
separate each char with null char
|
||||
and end with double null char
|
||||
@param s: Stream
|
||||
'''
|
||||
for c in self.value:
|
||||
s.writeType(UInt8(ord(c)))
|
||||
s.writeType(UInt8(0))
|
||||
s.writeType(UInt16Le(0))
|
||||
if self._unicode:
|
||||
self.value = decodeUnicode(self.value)
|
||||
|
||||
def __sizeof__(self):
|
||||
'''
|
||||
return len of uni string
|
||||
@return: 2*len + 2
|
||||
'''
|
||||
return len(self.value) * 2 + 2
|
||||
"""
|
||||
return length of string
|
||||
@return: length of inner string
|
||||
"""
|
||||
if self._unicode:
|
||||
return 2 * len(self.value) + 2
|
||||
else:
|
||||
return len(self.value)
|
||||
|
||||
def encodeUnicode(s):
|
||||
"""
|
||||
Encode string in unicode
|
||||
@param s: str python
|
||||
@return: unicode string
|
||||
"""
|
||||
return "".join([c + "\x00" for c in s]) + "\x00\x00"
|
||||
|
||||
def decodeUnicode(s):
|
||||
"""
|
||||
Decode Unicode string
|
||||
@param s: unicode string
|
||||
@return: str python
|
||||
"""
|
||||
i = 0
|
||||
r = ""
|
||||
while i < len(s) - 2:
|
||||
if i % 2 == 0:
|
||||
r += s[i]
|
||||
i += 1
|
||||
return r
|
||||
|
||||
class Stream(StringIO):
|
||||
'''
|
||||
@@ -849,6 +862,8 @@ class ArrayType(Type):
|
||||
element = self._typeFactory()
|
||||
element._optional = self._readLen is None
|
||||
s.readType(element)
|
||||
if not element._is_readed:
|
||||
break
|
||||
self._array.append(element)
|
||||
i += 1
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ def readLength(s):
|
||||
length = UInt8()
|
||||
s.readType(length)
|
||||
byte = length.value
|
||||
if (byte & 0x80):
|
||||
if byte & 0x80:
|
||||
byte &= ~0x80
|
||||
if byte == 1:
|
||||
size = UInt8()
|
||||
@@ -166,7 +166,7 @@ def writeBoolean(b):
|
||||
"""
|
||||
Return structure that represent boolean in BER specification
|
||||
@param b: boolean
|
||||
@return: BER boolean structure
|
||||
@return: BER boolean block
|
||||
"""
|
||||
boolean = UInt8(0)
|
||||
if b:
|
||||
@@ -209,7 +209,7 @@ def writeInteger(value):
|
||||
"""
|
||||
Write integer value
|
||||
@param param: INT or Python long
|
||||
@return: BER integer structure
|
||||
@return: BER integer block
|
||||
"""
|
||||
if value <= 0xff:
|
||||
return (writeUniversalTag(Tag.BER_TAG_INTEGER, False), writeLength(1), UInt8(value))
|
||||
@@ -233,7 +233,7 @@ def writeOctetstring(value):
|
||||
"""
|
||||
Write string in BER representation
|
||||
@param value: string
|
||||
@return: string BER structure
|
||||
@return: BER octet string block
|
||||
"""
|
||||
return (writeUniversalTag(Tag.BER_TAG_OCTET_STRING, False), writeLength(len(value)), String(value))
|
||||
|
||||
@@ -250,3 +250,11 @@ def readEnumerated(s):
|
||||
enumer = UInt8()
|
||||
s.readType(enumer)
|
||||
return enumer.value
|
||||
|
||||
def writeEnumerated(enumerated):
|
||||
"""
|
||||
Write enumerated structure
|
||||
@param s: Stream
|
||||
@return: BER enumerated block
|
||||
"""
|
||||
return (writeUniversalTag(Tag.BER_TAG_ENUMERATED, False), writeLength(1), UInt8(enumerated))
|
||||
@@ -16,6 +16,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
from rdpy.network.error import InvalidExpectedDataException
|
||||
|
||||
"""
|
||||
Definition of structure use for capabilities nego
|
||||
@@ -233,43 +234,17 @@ class Capability(CompositeType):
|
||||
"""
|
||||
Closure for capability factory
|
||||
"""
|
||||
if self.capabilitySetType.value == CapsType.CAPSTYPE_GENERAL:
|
||||
return GeneralCapability(readLen = UInt16Le(lambda:self.lengthCapability.value - 4))
|
||||
elif self.capabilitySetType.value == CapsType.CAPSTYPE_BITMAP:
|
||||
return BitmapCapability(readLen = UInt16Le(lambda:self.lengthCapability.value - 4))
|
||||
elif self.capabilitySetType.value == CapsType.CAPSTYPE_ORDER:
|
||||
return OrderCapability(readLen = UInt16Le(lambda:self.lengthCapability.value - 4))
|
||||
elif self.capabilitySetType.value == CapsType.CAPSTYPE_BITMAPCACHE:
|
||||
return BitmapCacheCapability(readLen = UInt16Le(lambda:self.lengthCapability.value - 4))
|
||||
elif self.capabilitySetType.value == CapsType.CAPSTYPE_POINTER:
|
||||
return PointerCapability(readLen = UInt16Le(lambda:self.lengthCapability.value - 4))
|
||||
elif self.capabilitySetType.value == CapsType.CAPSTYPE_INPUT:
|
||||
return InputCapability(readLen = UInt16Le(lambda:self.lengthCapability.value - 4))
|
||||
elif self.capabilitySetType.value == CapsType.CAPSTYPE_BRUSH:
|
||||
return BrushCapability(readLen = UInt16Le(lambda:self.lengthCapability.value - 4))
|
||||
elif self.capabilitySetType.value == CapsType.CAPSTYPE_GLYPHCACHE:
|
||||
return GlyphCapability(readLen = UInt16Le(lambda:self.lengthCapability.value - 4))
|
||||
elif self.capabilitySetType.value == CapsType.CAPSTYPE_OFFSCREENCACHE:
|
||||
return OffscreenBitmapCacheCapability(readLen = UInt16Le(lambda:self.lengthCapability.value - 4))
|
||||
elif self.capabilitySetType.value == CapsType.CAPSTYPE_VIRTUALCHANNEL:
|
||||
return VirtualChannelCapability(readLen = UInt16Le(lambda:self.lengthCapability.value - 4))
|
||||
elif self.capabilitySetType.value == CapsType.CAPSTYPE_SOUND:
|
||||
return SoundCapability(readLen = UInt16Le(lambda:self.lengthCapability.value - 4))
|
||||
elif self.capabilitySetType.value == CapsType.CAPSTYPE_CONTROL:
|
||||
return ControlCapability(readLen = UInt16Le(lambda:self.lengthCapability.value - 4))
|
||||
elif self.capabilitySetType.value == CapsType.CAPSTYPE_ACTIVATION:
|
||||
return WindowActivationCapability(readLen = UInt16Le(lambda:self.lengthCapability.value - 4))
|
||||
elif self.capabilitySetType.value == CapsType.CAPSTYPE_FONT:
|
||||
return FontCapability(readLen = UInt16Le(lambda:self.lengthCapability.value - 4))
|
||||
elif self.capabilitySetType.value == CapsType.CAPSTYPE_COLORCACHE:
|
||||
return ColorCacheCapability(readLen = UInt16Le(lambda:self.lengthCapability.value - 4))
|
||||
elif self.capabilitySetType.value == CapsType.CAPSTYPE_SHARE:
|
||||
return ShareCapability(readLen = UInt16Le(lambda:self.lengthCapability.value - 4))
|
||||
else:
|
||||
return String(readLen = UInt16Le(lambda:self.lengthCapability.value - 4))
|
||||
for c in [GeneralCapability, BitmapCapability, OrderCapability, BitmapCacheCapability, PointerCapability, InputCapability, BrushCapability, GlyphCapability, OffscreenBitmapCacheCapability, VirtualChannelCapability, SoundCapability, ControlCapability, WindowActivationCapability, FontCapability, ColorCacheCapability, ShareCapability]:
|
||||
if self.capabilitySetType.value == c._TYPE_:
|
||||
return c(readLen = self.lengthCapability - 4)
|
||||
print "WARNING : unknown Capability type : %s"%hex(self.capabilitySetType.value)
|
||||
#read entire packet
|
||||
return String(readLen = self.lengthCapability - 4)
|
||||
|
||||
if capability is None:
|
||||
capability = FactoryType(CapabilityFactory)
|
||||
elif not "_TYPE_" in capability.__class__.__dict__:
|
||||
raise InvalidExpectedDataException("Try to send an invalid capability block")
|
||||
|
||||
self.capability = capability
|
||||
|
||||
@@ -280,6 +255,8 @@ class GeneralCapability(CompositeType):
|
||||
server -> client
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240549.aspx
|
||||
"""
|
||||
_TYPE_ = CapsType.CAPSTYPE_GENERAL
|
||||
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.osMajorType = UInt16Le()
|
||||
@@ -301,6 +278,8 @@ class BitmapCapability(CompositeType):
|
||||
server -> client
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240554.aspx
|
||||
"""
|
||||
_TYPE_ = CapsType.CAPSTYPE_BITMAP
|
||||
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.preferredBitsPerPixel = UInt16Le()
|
||||
@@ -324,6 +303,8 @@ class OrderCapability(CompositeType):
|
||||
server -> client
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240556.aspx
|
||||
"""
|
||||
_TYPE_ = CapsType.CAPSTYPE_ORDER
|
||||
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.terminalDescriptor = String("\x00" * 16, readLen = UInt8(16))
|
||||
@@ -350,6 +331,8 @@ class BitmapCacheCapability(CompositeType):
|
||||
client -> server
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240559.aspx
|
||||
"""
|
||||
_TYPE_ = CapsType.CAPSTYPE_BITMAPCACHE
|
||||
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.pad1 = UInt32Le()
|
||||
@@ -373,6 +356,8 @@ class PointerCapability(CompositeType):
|
||||
server -> client
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240562.aspx
|
||||
"""
|
||||
_TYPE_ = CapsType.CAPSTYPE_POINTER
|
||||
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.colorPointerFlag = UInt16Le()
|
||||
@@ -386,6 +371,8 @@ class InputCapability(CompositeType):
|
||||
server -> client
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240563.aspx
|
||||
"""
|
||||
_TYPE_ = CapsType.CAPSTYPE_INPUT
|
||||
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.inputFlags = UInt16Le()
|
||||
@@ -407,6 +394,8 @@ class BrushCapability(CompositeType):
|
||||
client -> server
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240564.aspx
|
||||
"""
|
||||
_TYPE_ = CapsType.CAPSTYPE_BRUSH
|
||||
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.brushSupportLevel = UInt32Le(BrushSupport.BRUSH_DEFAULT)
|
||||
@@ -417,6 +406,8 @@ class GlyphCapability(CompositeType):
|
||||
client -> server
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240565.aspx
|
||||
"""
|
||||
_TYPE_ = CapsType.CAPSTYPE_GLYPHCACHE
|
||||
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.glyphCache = ArrayType(CacheEntry, init = [CacheEntry() for _ in range(0,10)], readLen = UInt8(10))
|
||||
@@ -431,6 +422,8 @@ class OffscreenBitmapCacheCapability(CompositeType):
|
||||
client -> server
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240550.aspx
|
||||
"""
|
||||
_TYPE_ = CapsType.CAPSTYPE_OFFSCREENCACHE
|
||||
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.offscreenSupportLevel = UInt32Le(OffscreenSupportLevel.FALSE)
|
||||
@@ -444,6 +437,8 @@ class VirtualChannelCapability(CompositeType):
|
||||
server -> client
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240551.aspx
|
||||
"""
|
||||
_TYPE_ = CapsType.CAPSTYPE_VIRTUALCHANNEL
|
||||
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.flags = UInt32Le(VirtualChannelCompressionFlag.VCCAPS_NO_COMPR)
|
||||
@@ -455,6 +450,8 @@ class SoundCapability(CompositeType):
|
||||
client -> server
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240552.aspx
|
||||
"""
|
||||
_TYPE_ = CapsType.CAPSTYPE_SOUND
|
||||
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.soundFlags = UInt16Le(SoundFlag.NONE)
|
||||
@@ -465,6 +462,8 @@ class ControlCapability(CompositeType):
|
||||
client -> server but server ignore contents! Thanks krosoft for brandwidth
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240568.aspx
|
||||
"""
|
||||
_TYPE_ = CapsType.CAPSTYPE_CONTROL
|
||||
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.controlFlags = UInt16Le()
|
||||
@@ -477,6 +476,8 @@ class WindowActivationCapability(CompositeType):
|
||||
client -> server but server ignore contents! Thanks krosoft for brandwidth
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240569.aspx
|
||||
"""
|
||||
_TYPE_ = CapsType.CAPSTYPE_ACTIVATION
|
||||
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.helpKeyFlag = UInt16Le()
|
||||
@@ -491,6 +492,8 @@ class FontCapability(CompositeType):
|
||||
server -> client
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240571.aspx
|
||||
"""
|
||||
_TYPE_ = CapsType.CAPSTYPE_FONT
|
||||
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.fontSupportFlags = UInt16Le(0x0001)
|
||||
@@ -502,6 +505,8 @@ class ColorCacheCapability(CompositeType):
|
||||
server -> client
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc241564.aspx
|
||||
"""
|
||||
_TYPE_ = CapsType.CAPSTYPE_COLORCACHE
|
||||
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.colorTableCacheSize = UInt16Le(0x0006)
|
||||
@@ -514,6 +519,8 @@ class ShareCapability(CompositeType):
|
||||
server -> client
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240570.aspx
|
||||
"""
|
||||
_TYPE_ = CapsType.CAPSTYPE_SHARE
|
||||
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.nodeId = UInt16Le()
|
||||
|
||||
@@ -22,8 +22,7 @@ Implement GCC structure use in RDP protocol
|
||||
http://msdn.microsoft.com/en-us/library/cc240508.aspx
|
||||
"""
|
||||
|
||||
from rdpy.network.type import UInt8, UInt16Le, UInt32Le, CompositeType, String, UniString, Stream, sizeof, FactoryType,\
|
||||
ArrayType
|
||||
from rdpy.network.type import UInt8, UInt16Le, UInt32Le, CompositeType, String, Stream, sizeof, FactoryType, ArrayType
|
||||
import per
|
||||
from rdpy.network.error import InvalidExpectedDataException
|
||||
|
||||
@@ -204,10 +203,10 @@ class DataBlock(CompositeType):
|
||||
"""
|
||||
for c in [ClientCoreData, ClientSecurityData, ClientNetworkData, ServerCoreData, ServerNetworkData, ServerSecurityData]:
|
||||
if self.type.value == c._TYPE_:
|
||||
return c()
|
||||
print "WARNING : unknown GCC block type : %s"%self.type.value
|
||||
return c(readLen = self.length - 4)
|
||||
print "WARNING : unknown GCC block type : %s"%hex(self.type.value)
|
||||
#read entire packet
|
||||
return String(readLen = self.length)
|
||||
return String(readLen = self.length - 4)
|
||||
|
||||
if dataBlock is None:
|
||||
dataBlock = FactoryType(DataBlockFactory)
|
||||
@@ -223,8 +222,8 @@ class ClientCoreData(CompositeType):
|
||||
"""
|
||||
_TYPE_ = MessageType.CS_CORE
|
||||
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.rdpVersion = UInt32Le(Version.RDP_VERSION_5_PLUS)
|
||||
self.desktopWidth = UInt16Le(1280)
|
||||
self.desktopHeight = UInt16Le(800)
|
||||
@@ -232,7 +231,7 @@ class ClientCoreData(CompositeType):
|
||||
self.sasSequence = UInt16Le(Sequence.RNS_UD_SAS_DEL)
|
||||
self.kbdLayout = UInt32Le(KeyboardLayout.FRENCH)
|
||||
self.clientBuild = UInt32Le(3790)
|
||||
self.clientName = UniString("rdpy" + "\x00"*11, readLen = UInt8(30))
|
||||
self.clientName = String("rdpy" + "\x00"*11, readLen = UInt8(32), unicode = True)
|
||||
self.keyboardType = UInt32Le(KeyboardType.IBM_101_102_KEYS)
|
||||
self.keyboardSubType = UInt32Le(0)
|
||||
self.keyboardFnKeys = UInt32Le(12)
|
||||
@@ -255,8 +254,8 @@ class ServerCoreData(CompositeType):
|
||||
"""
|
||||
_TYPE_ = MessageType.SC_CORE
|
||||
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.rdpVersion = UInt32Le(Version.RDP_VERSION_5_PLUS)
|
||||
self.clientRequestedProtocol = UInt32Le()
|
||||
|
||||
@@ -268,8 +267,8 @@ class ClientSecurityData(CompositeType):
|
||||
"""
|
||||
_TYPE_ = MessageType.CS_SECURITY
|
||||
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.encryptionMethods = UInt32Le()
|
||||
self.extEncryptionMethods = UInt32Le()
|
||||
|
||||
@@ -283,8 +282,8 @@ class ServerSecurityData(CompositeType):
|
||||
"""
|
||||
_TYPE_ = MessageType.SC_SECURITY
|
||||
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.encryptionMethod = UInt32Le()
|
||||
self.encryptionLevel = UInt32Le()
|
||||
|
||||
@@ -309,8 +308,8 @@ class ClientNetworkData(CompositeType):
|
||||
"""
|
||||
_TYPE_ = MessageType.CS_NET
|
||||
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.channelCount = UInt32Le()
|
||||
self.channelDefArray = ArrayType(ChannelDef, readLen = self.channelCount)
|
||||
|
||||
@@ -322,19 +321,19 @@ class ServerNetworkData(CompositeType):
|
||||
"""
|
||||
_TYPE_ = MessageType.SC_NET
|
||||
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.MCSChannelId = UInt16Le()
|
||||
self.channelCount = UInt16Le(lambda:len(self.channelIdArray._array))
|
||||
self.channelIdArray = ArrayType(UInt16Le, readLen = self.channelCount)
|
||||
self.pad = UInt16Le(conditional = lambda:(self.channelCount.value % 2 == 1))
|
||||
self.pad = UInt16Le(conditional = lambda:((self.channelCount.value % 2) == 1))
|
||||
|
||||
class Settings(CompositeType):
|
||||
"""
|
||||
Class which group all clients settings supported by RDPY
|
||||
"""
|
||||
def __init__(self, init = []):
|
||||
CompositeType.__init__(self)
|
||||
def __init__(self, init = [], readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.settings = ArrayType(DataBlock, [DataBlock(i) for i in init])
|
||||
|
||||
def getBlock(self, messageType):
|
||||
@@ -347,18 +346,6 @@ class Settings(CompositeType):
|
||||
return i.dataBlock
|
||||
return None
|
||||
|
||||
class ServerSettings(object):
|
||||
"""
|
||||
Server settings
|
||||
"""
|
||||
def __init__(self):
|
||||
#core settings of server
|
||||
self.core = ServerCoreData()
|
||||
#unuse security informations
|
||||
self.security = ServerSecurityData()
|
||||
#channel id accepted by server
|
||||
self.channelsId = []
|
||||
|
||||
def clientSettings():
|
||||
"""
|
||||
Build settings for client
|
||||
@@ -371,13 +358,14 @@ def serverSettings():
|
||||
Build settings for server
|
||||
@return Settings
|
||||
"""
|
||||
return Settings([ServerCoreData(), ServerSecurityData(), ServerSecurityData()])
|
||||
return Settings([ServerCoreData(), ServerSecurityData(), ServerNetworkData()])
|
||||
|
||||
def readConferenceCreateRequest(s):
|
||||
"""
|
||||
Read a response from client
|
||||
GCC create request
|
||||
@param s: Stream
|
||||
@param client settings (Settings)
|
||||
"""
|
||||
per.readChoice(s)
|
||||
per.readObjectIdentifier(s, t124_02_98_oid)
|
||||
@@ -394,6 +382,10 @@ def readConferenceCreateRequest(s):
|
||||
raise InvalidExpectedDataException("Invalid choice in readConferenceCreateRequest")
|
||||
|
||||
per.readOctetStream(s, h221_cs_key, 4)
|
||||
length = per.readLength(s)
|
||||
clientSettings = Settings(readLen = UInt32Le(length))
|
||||
s.readType(clientSettings)
|
||||
return clientSettings
|
||||
|
||||
def readConferenceCreateResponse(s):
|
||||
"""
|
||||
@@ -413,59 +405,11 @@ def readConferenceCreateResponse(s):
|
||||
per.readChoice(s)
|
||||
if not per.readOctetStream(s, h221_sc_key, 4):
|
||||
raise InvalidExpectedDataException("cannot read h221_sc_key")
|
||||
#serverSettings = Settings()
|
||||
#s.readType(serverSettings)
|
||||
#return serverSettings
|
||||
return readServerDataBlocks(s)
|
||||
|
||||
def readServerDataBlocks(s):
|
||||
"""
|
||||
Read GCC server data blocks
|
||||
And return result in Server Settings object
|
||||
@param s: Stream
|
||||
@return: ServerSettings
|
||||
"""
|
||||
settings = ServerSettings()
|
||||
length = per.readLength(s)
|
||||
while length > 0:
|
||||
marker = s.readLen()
|
||||
blockType = UInt16Le()
|
||||
blockLength = UInt16Le()
|
||||
s.readType((blockType, blockLength))
|
||||
#read core block
|
||||
if blockType.value == MessageType.SC_CORE:
|
||||
s.readType(settings.core)
|
||||
#read network block
|
||||
elif blockType.value == MessageType.SC_NET:
|
||||
settings.channelsId = readServerSecurityData(s)
|
||||
#read security block
|
||||
#unused in rdpy because use SSL layer
|
||||
elif blockType.value == MessageType.SC_SECURITY:
|
||||
s.readType(settings.security)
|
||||
else:
|
||||
print "Unknown server block %s"%hex(type)
|
||||
length -= blockLength.value
|
||||
s.seek(marker + blockLength.value)
|
||||
|
||||
return settings
|
||||
|
||||
def readServerSecurityData(s):
|
||||
"""
|
||||
Read server security and fill it in settings
|
||||
Read all channels accepted by server by server
|
||||
@param s: Stream
|
||||
@return: list of channel id selected by server
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240522.aspx
|
||||
"""
|
||||
channelsId = []
|
||||
channelId = UInt16Le()
|
||||
numberOfChannels = UInt16Le()
|
||||
s.readType((channelId, numberOfChannels))
|
||||
for _ in range(0, numberOfChannels.value):
|
||||
channelId = UInt16Le()
|
||||
s.readType(channelId)
|
||||
channelsId.append(channelId)
|
||||
return channelsId
|
||||
serverSettings = Settings(readLen = UInt32Le(length))
|
||||
s.readType(serverSettings)
|
||||
return serverSettings
|
||||
|
||||
def writeConferenceCreateRequest(userData):
|
||||
"""
|
||||
@@ -482,20 +426,17 @@ def writeConferenceCreateRequest(userData):
|
||||
per.writeNumberOfSet(1), per.writeChoice(0xc0),
|
||||
per.writeOctetStream(h221_cs_key, 4), per.writeOctetStream(userDataStream.getvalue()))
|
||||
|
||||
def writeConferenceCreateResponse(settings):
|
||||
def writeConferenceCreateResponse(serverData):
|
||||
"""
|
||||
Write a conference create response packet
|
||||
@param settings: ServerSettingsDataBlock
|
||||
@param serverData: Settings for server
|
||||
@return: gcc packet
|
||||
"""
|
||||
pass
|
||||
serverDataStream = Stream()
|
||||
serverDataStream.writeType(serverData)
|
||||
|
||||
def writeClientDataBlocks(settings):
|
||||
"""
|
||||
Write all blocks for client
|
||||
and return GCC valid structure
|
||||
@param settings: ClientSettings
|
||||
"""
|
||||
return (DataBlock(settings.core),
|
||||
DataBlock(settings.security),
|
||||
DataBlock(settings.network))
|
||||
return (per.writeChoice(0), per.writeObjectIdentifier(t124_02_98_oid),
|
||||
per.writeLength(len(serverDataStream.getvalue()) + 14), per.writeChoice(0x14),
|
||||
per.writeInteger16(0x79F3, 1001), per.writeInteger(1), per.writeEnumerates(16),
|
||||
per.writeNumberOfSet(1), per.writeChoice(0xc0),
|
||||
per.writeOctetStream(h221_sc_key, 4), per.writeOctetStream(serverDataStream.getvalue()))
|
||||
@@ -25,7 +25,7 @@ The main channel is the graphical channel.
|
||||
It exist channel for file system order, audio channel, clipboard etc...
|
||||
"""
|
||||
from rdpy.network.layer import LayerAutomata, StreamSender, Layer, LayerMode
|
||||
from rdpy.network.type import sizeof, Stream, UInt8, UInt16Be
|
||||
from rdpy.network.type import sizeof, Stream, UInt8, UInt16Le
|
||||
from rdpy.network.error import InvalidExpectedDataException, InvalidValue, InvalidSize
|
||||
from rdpy.protocol.rdp.ber import writeLength
|
||||
|
||||
@@ -60,7 +60,7 @@ class Channel:
|
||||
|
||||
class MCS(LayerAutomata):
|
||||
"""
|
||||
Multi Channel Service layer
|
||||
Multiple Channel Service layer
|
||||
the main layer of RDP protocol
|
||||
is why he can do everything and more!
|
||||
"""
|
||||
@@ -122,13 +122,13 @@ class MCS(LayerAutomata):
|
||||
"""
|
||||
LayerAutomata.__init__(self, mode, presentation)
|
||||
self._clientSettings = gcc.clientSettings()
|
||||
self._serverSettings = gcc.ServerSettings()
|
||||
self._serverSettings = gcc.serverSettings()
|
||||
#default user Id
|
||||
self._userId = 1
|
||||
self._userId = 1 + Channel.MCS_USERCHANNEL_BASE
|
||||
#list of channel use in this layer and connection state
|
||||
self._channelIds = {Channel.MCS_GLOBAL_CHANNEL: presentation}
|
||||
#use to record already requested channel
|
||||
self._channelIdsRequest = {}
|
||||
self._channelIdsRequested = {}
|
||||
|
||||
def connect(self):
|
||||
"""
|
||||
@@ -143,27 +143,29 @@ class MCS(LayerAutomata):
|
||||
|
||||
def connectNextChannel(self):
|
||||
"""
|
||||
Send sendChannelJoinRequest message on next unconnect channel
|
||||
Send sendChannelJoinRequest message on next disconnect channel
|
||||
client automata function
|
||||
"""
|
||||
for (channelId, layer) in self._channelIds.iteritems():
|
||||
#for each unconnect channel send a request
|
||||
if not self._channelIdsRequest.has_key(channelId):
|
||||
#for each disconnect channel send a request
|
||||
if not self._channelIdsRequested.has_key(channelId):
|
||||
self.sendChannelJoinRequest(channelId)
|
||||
self.setNextState(self.recvChannelJoinConfirm)
|
||||
return
|
||||
|
||||
#connection is done reinit class
|
||||
#connection is done
|
||||
self.setNextState(self.recvData)
|
||||
#try connection on all requested channel
|
||||
for (channelId, layer) in self._channelIds.iteritems():
|
||||
if self._channelIdsRequest[channelId] and not layer is None:
|
||||
#use proxy foreach channell
|
||||
if self._channelIdsRequested[channelId] and not layer is None:
|
||||
#use proxy for each channel
|
||||
layer._transport = MCS.MCSProxySender(self, channelId)
|
||||
layer.connect()
|
||||
|
||||
def sendConnectInitial(self):
|
||||
"""
|
||||
Send connect initial packet
|
||||
client automata function
|
||||
"""
|
||||
ccReq = gcc.writeConferenceCreateRequest(self._clientSettings)
|
||||
ccReqStream = Stream()
|
||||
@@ -179,25 +181,66 @@ class MCS(LayerAutomata):
|
||||
self.setNextState(self.recvConnectResponse)
|
||||
|
||||
def sendConnectResponse(self):
|
||||
pass
|
||||
"""
|
||||
Send connect response
|
||||
server automata function
|
||||
"""
|
||||
ccReq = gcc.writeConferenceCreateResponse(self._serverSettings)
|
||||
ccReqStream = Stream()
|
||||
ccReqStream.writeType(ccReq)
|
||||
|
||||
tmp = (ber.writeEnumerated(0), ber.writeInteger(0), self.writeDomainParams(22, 3, 0, 0xfff8),
|
||||
ber.writeOctetstring(ccReqStream.getvalue()))
|
||||
self._transport.send((ber.writeApplicationTag(Message.MCS_TYPE_CONNECT_RESPONSE, sizeof(tmp)), tmp))
|
||||
|
||||
self.setNextState(self.recvErectDomainRequest)
|
||||
|
||||
def sendErectDomainRequest(self):
|
||||
"""
|
||||
Send a formated erect domain request for RDP connection
|
||||
client automata function
|
||||
"""
|
||||
self._transport.send((self.writeMCSPDUHeader(UInt8(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
|
||||
client automata function
|
||||
"""
|
||||
self._transport.send(self.writeMCSPDUHeader(UInt8(DomainMCSPDU.ATTACH_USER_REQUEST)))
|
||||
|
||||
def sendAttachUserConfirm(self):
|
||||
"""
|
||||
Send attach user confirm
|
||||
server automata function
|
||||
"""
|
||||
self._transport.send((self.writeMCSPDUHeader(UInt8(DomainMCSPDU.ATTACH_USER_CONFIRM)),
|
||||
per.writeEnumerates(0),
|
||||
per.writeInteger16(self._userId, Channel.MCS_USERCHANNEL_BASE)))
|
||||
|
||||
def sendChannelJoinRequest(self, channelId):
|
||||
"""
|
||||
Send a formated Channel join request from client to server
|
||||
client automata function
|
||||
@param channelId: id of channel requested
|
||||
"""
|
||||
self._transport.send((self.writeMCSPDUHeader(UInt8(DomainMCSPDU.CHANNEL_JOIN_REQUEST)), UInt16Be(self._userId), UInt16Be(channelId)))
|
||||
self._transport.send((self.writeMCSPDUHeader(UInt8(DomainMCSPDU.CHANNEL_JOIN_REQUEST)),
|
||||
per.writeInteger16(self._userId, Channel.MCS_USERCHANNEL_BASE),
|
||||
per.writeInteger16(channelId)))
|
||||
|
||||
def sendChannelJoinConfirm(self, channelId, confirm):
|
||||
"""
|
||||
Send a confirm channel (or not) to client
|
||||
@param channelId: id of channel
|
||||
@param confirm: connection state
|
||||
"""
|
||||
self._transport.send((self.writeMCSPDUHeader(UInt8(DomainMCSPDU.CHANNEL_JOIN_CONFIRM)),
|
||||
per.writeEnumerates(int(confirm)),
|
||||
per.writeInteger16(self._userId, Channel.MCS_USERCHANNEL_BASE),
|
||||
per.writeInteger16(channelId),
|
||||
per.writeInteger16(channelId)))
|
||||
|
||||
def send(self, channelId, data):
|
||||
"""
|
||||
@@ -205,11 +248,16 @@ class MCS(LayerAutomata):
|
||||
@param channelId: Channel use to send
|
||||
@param data: message to send
|
||||
"""
|
||||
self._transport.send((self.writeMCSPDUHeader(UInt8(DomainMCSPDU.SEND_DATA_REQUEST)), UInt16Be(self._userId), UInt16Be(channelId), UInt8(0x70), UInt16Be(sizeof(data)) | UInt16Be(0x8000), data))
|
||||
self._transport.send((self.writeMCSPDUHeader(UInt8(DomainMCSPDU.SEND_DATA_REQUEST)),
|
||||
per.writeInteger16(self._userId, Channel.MCS_USERCHANNEL_BASE),
|
||||
per.writeInteger16(channelId),
|
||||
UInt8(0x70),
|
||||
per.writeLength(sizeof(data)), data))
|
||||
|
||||
def recvConnectInitial(self, data):
|
||||
"""
|
||||
Receive MCS connect initial from client
|
||||
server automata function
|
||||
@param data: Stream
|
||||
"""
|
||||
ber.readApplicationTag(data, UInt8(Message.MCS_TYPE_CONNECT_INITIAL))
|
||||
@@ -222,11 +270,16 @@ class MCS(LayerAutomata):
|
||||
self.readDomainParams(data)
|
||||
self.readDomainParams(data)
|
||||
self.readDomainParams(data)
|
||||
gcc.readConferenceCreateRequest(Stream(ber.readOctetString(data)))
|
||||
self._clientSettings = gcc.readConferenceCreateRequest(Stream(ber.readOctetString(data)))
|
||||
|
||||
self._serverSettings.getBlock(gcc.MessageType.SC_NET).channelIdArray._array = [UInt16Le(x + Channel.MCS_GLOBAL_CHANNEL) for x in range(1, len(self._clientSettings.getBlock(gcc.MessageType.CS_NET).channelDefArray._array) + 1)]
|
||||
|
||||
self.sendConnectResponse()
|
||||
|
||||
def recvConnectResponse(self, data):
|
||||
"""
|
||||
Receive MCS connect response from server
|
||||
client automata function
|
||||
@param data: Stream
|
||||
"""
|
||||
ber.readApplicationTag(data, UInt8(Message.MCS_TYPE_CONNECT_RESPONSE))
|
||||
@@ -237,7 +290,7 @@ class MCS(LayerAutomata):
|
||||
raise InvalidExpectedDataException("invalid expected BER tag")
|
||||
gccRequestLength = ber.readLength(data)
|
||||
if data.dataLen() != gccRequestLength:
|
||||
raise InvalidSize("bad size of gcc request")
|
||||
raise InvalidSize("bad size of GCC request")
|
||||
self._serverSettings = gcc.readConferenceCreateResponse(data)
|
||||
|
||||
#send domain request
|
||||
@@ -247,49 +300,102 @@ class MCS(LayerAutomata):
|
||||
#now wait user confirm from server
|
||||
self.setNextState(self.recvAttachUserConfirm)
|
||||
|
||||
def recvAttachUserConfirm(self, data):
|
||||
def recvErectDomainRequest(self, data):
|
||||
"""
|
||||
Receive an attach user confirm
|
||||
Receive erect domain request
|
||||
server automata function
|
||||
@param data: Stream
|
||||
"""
|
||||
opcode = UInt8()
|
||||
confirm = UInt8()
|
||||
userId = UInt16Be()
|
||||
data.readType((opcode, confirm))
|
||||
data.readType(opcode)
|
||||
|
||||
if not self.readMCSPDUHeader(opcode.value, DomainMCSPDU.ERECT_DOMAIN_REQUEST):
|
||||
raise InvalidExpectedDataException("Invalid MCS PDU : ERECT_DOMAIN_REQUEST expected")
|
||||
|
||||
per.readInteger(data)
|
||||
per.readInteger(data)
|
||||
|
||||
self.setNextState(self.recvAttachUserRequest)
|
||||
|
||||
def recvAttachUserRequest(self, data):
|
||||
"""
|
||||
Receive Attach user request
|
||||
server automata function
|
||||
@param data: Stream
|
||||
"""
|
||||
opcode = UInt8()
|
||||
data.readType(opcode)
|
||||
|
||||
if not self.readMCSPDUHeader(opcode.value, DomainMCSPDU.ATTACH_USER_REQUEST):
|
||||
raise InvalidExpectedDataException("Invalid MCS PDU : ATTACH_USER_REQUEST expected")
|
||||
|
||||
self.sendAttachUserConfirm()
|
||||
self.setNextState(self.recvChannelJoinRequest)
|
||||
|
||||
def recvAttachUserConfirm(self, data):
|
||||
"""
|
||||
Receive an attach user confirm
|
||||
client automata function
|
||||
@param data: Stream
|
||||
"""
|
||||
opcode = UInt8()
|
||||
data.readType(opcode)
|
||||
|
||||
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(userId)
|
||||
self._userId = userId.value
|
||||
raise InvalidExpectedDataException("Invalid MCS PDU : ATTACH_USER_CONFIRM expected")
|
||||
|
||||
if per.readEnumerates(data) != 0:
|
||||
raise InvalidExpectedDataException("Server reject user")
|
||||
|
||||
self._userId = per.readInteger16(data, Channel.MCS_USERCHANNEL_BASE)
|
||||
|
||||
#build channel list because we have user id
|
||||
#add default channel + channels accepted by gcc connection sequence
|
||||
self._channelIds[self._userId + Channel.MCS_USERCHANNEL_BASE] = None
|
||||
#add default channel + channels accepted by GCC connection sequence
|
||||
self._channelIds[self._userId] = None
|
||||
|
||||
self.connectNextChannel()
|
||||
|
||||
def recvChannelJoinRequest(self, data):
|
||||
"""
|
||||
Receive for each client channel a request
|
||||
server automata function
|
||||
@param data: Stream
|
||||
|
||||
"""
|
||||
opcode = UInt8()
|
||||
data.readType(opcode)
|
||||
|
||||
if not self.readMCSPDUHeader(opcode.value, DomainMCSPDU.CHANNEL_JOIN_REQUEST):
|
||||
raise InvalidExpectedDataException("Invalid MCS PDU : CHANNEL_JOIN_REQUEST expected")
|
||||
|
||||
userId = per.readInteger16(data, Channel.MCS_USERCHANNEL_BASE)
|
||||
if self._userId != userId:
|
||||
raise InvalidExpectedDataException("Invalid MCS User Id")
|
||||
|
||||
channelId = per.readInteger16(data)
|
||||
self.sendChannelJoinConfirm(channelId, channelId in self._channelIds.keys() or channelId == self._userId)
|
||||
|
||||
def recvChannelJoinConfirm(self, data):
|
||||
"""
|
||||
Receive a channel join confirm from server
|
||||
client automata function
|
||||
@param data: Stream
|
||||
"""
|
||||
opcode = UInt8()
|
||||
confirm = UInt8()
|
||||
data.readType((opcode, confirm))
|
||||
data.readType(opcode)
|
||||
|
||||
if not self.readMCSPDUHeader(opcode.value, DomainMCSPDU.CHANNEL_JOIN_CONFIRM):
|
||||
raise InvalidExpectedDataException("invalid MCS PDU")
|
||||
userId = UInt16Be()
|
||||
channelId = UInt16Be()
|
||||
data.readType((userId, channelId))
|
||||
raise InvalidExpectedDataException("Invalid MCS PDU : CHANNEL_JOIN_CONFIRM expected")
|
||||
|
||||
confirm = per.readEnumerates(data)
|
||||
|
||||
userId = per.readInteger16(data, Channel.MCS_USERCHANNEL_BASE)
|
||||
if self._userId != userId:
|
||||
raise InvalidExpectedDataException("Invalid MCS User Id")
|
||||
|
||||
channelId = per.readInteger16(data)
|
||||
#save state of channel
|
||||
self._channelIdsRequest[channelId] = confirm == 0
|
||||
if confirm == 0:
|
||||
print "server accept channel %d"%channelId.value
|
||||
else:
|
||||
print "server refused channel %d"%channelId.value
|
||||
|
||||
self._channelIdsRequested[channelId] = (confirm == 0)
|
||||
self.connectNextChannel()
|
||||
|
||||
def recvData(self, data):
|
||||
@@ -301,32 +407,29 @@ class MCS(LayerAutomata):
|
||||
data.readType(opcode)
|
||||
|
||||
if self.readMCSPDUHeader(opcode.value, DomainMCSPDU.DISCONNECT_PROVIDER_ULTIMATUM):
|
||||
print "receive DISCONNECT_PROVIDER_ULTIMATUM"
|
||||
self.close()
|
||||
print "INFO : MCS DISCONNECT_PROVIDER_ULTIMATUM"
|
||||
self._transport.close()
|
||||
return
|
||||
|
||||
elif not self.readMCSPDUHeader(opcode.value, DomainMCSPDU.SEND_DATA_INDICATION):
|
||||
raise InvalidExpectedDataException("invalid expected mcs opcode")
|
||||
raise InvalidExpectedDataException("Invalid expected MCS opcode")
|
||||
|
||||
userId = UInt16Be()
|
||||
channelId = UInt16Be()
|
||||
flags = UInt8()
|
||||
length = UInt8()
|
||||
#server user id
|
||||
per.readInteger16(data, Channel.MCS_USERCHANNEL_BASE)
|
||||
|
||||
data.readType((userId, channelId, flags, length))
|
||||
channelId = per.readInteger16(data)
|
||||
|
||||
if length & UInt8(0x80) == UInt8(0x80):
|
||||
lengthP2 = UInt8()
|
||||
data.readType(lengthP2)
|
||||
length = UInt16Be(length.value & 0x7f << 8 | lengthP2.value)
|
||||
per.readEnumerates(data)
|
||||
per.readLength(data)
|
||||
|
||||
#channel id doesn't match a requested layer
|
||||
if not self._channelIdsRequest.has_key(channelId):
|
||||
print "receive data for an unrequested layer"
|
||||
if not self._channelIdsRequested.has_key(channelId):
|
||||
print "ERROR : receive data for an unrequested layer"
|
||||
return
|
||||
|
||||
#channel id math an unconnected layer
|
||||
if not self._channelIdsRequest[channelId]:
|
||||
print "receive data for an unconnected layer"
|
||||
if not self._channelIdsRequested[channelId]:
|
||||
print "ERROR : receive data for an unconnected layer"
|
||||
return
|
||||
|
||||
self._channelIds[channelId].recv(data)
|
||||
|
||||
@@ -24,7 +24,7 @@ In this layer are managed all mains bitmap update orders end user inputs
|
||||
"""
|
||||
|
||||
from rdpy.network.layer import LayerAutomata, LayerMode
|
||||
from rdpy.network.type import CompositeType, UniString, String, UInt8, UInt16Le, UInt32Le, sizeof, ArrayType, FactoryType
|
||||
from rdpy.network.type import CompositeType, String, UInt8, UInt16Le, UInt32Le, sizeof, ArrayType, FactoryType
|
||||
from rdpy.network.error import InvalidExpectedDataException, CallPureVirtualFuntion, InvalidType
|
||||
|
||||
import gcc, lic, caps, tpkt
|
||||
@@ -491,13 +491,13 @@ class RDPInfo(CompositeType):
|
||||
self.cbAlternateShell = UInt16Le(lambda:sizeof(self.alternateShell) - 2)
|
||||
self.cbWorkingDir = UInt16Le(lambda:sizeof(self.workingDir) - 2)
|
||||
#microsoft domain
|
||||
self.domain = UniString(readLen = UInt16Le(lambda:self.cbDomain.value - 2))
|
||||
self.userName = UniString(readLen = UInt16Le(lambda:self.cbUserName.value - 2))
|
||||
self.password = UniString(readLen = UInt16Le(lambda:self.cbPassword.value - 2))
|
||||
self.domain = String(readLen = UInt16Le(lambda:self.cbDomain.value - 2), unicode = True)
|
||||
self.userName = String(readLen = UInt16Le(lambda:self.cbUserName.value - 2), unicode = True)
|
||||
self.password = String(readLen = UInt16Le(lambda:self.cbPassword.value - 2), unicode = True)
|
||||
#shell execute at start of session
|
||||
self.alternateShell = UniString(readLen = UInt16Le(lambda:self.cbAlternateShell.value - 2))
|
||||
self.alternateShell = String(readLen = UInt16Le(lambda:self.cbAlternateShell.value - 2), unicode = True)
|
||||
#working directory for session
|
||||
self.workingDir = UniString(readLen = UInt16Le(lambda:self.cbWorkingDir.value - 2))
|
||||
self.workingDir = String(readLen = UInt16Le(lambda:self.cbWorkingDir.value - 2), unicode = True)
|
||||
self.extendedInfo = RDPExtendedInfo(conditional = extendedInfoConditional)
|
||||
|
||||
class RDPExtendedInfo(CompositeType):
|
||||
@@ -508,9 +508,9 @@ class RDPExtendedInfo(CompositeType):
|
||||
CompositeType.__init__(self, conditional = conditional)
|
||||
self.clientAddressFamily = UInt16Le(AfInet.AF_INET)
|
||||
self.cbClientAddress = UInt16Le(lambda:sizeof(self.clientAddress))
|
||||
self.clientAddress = UniString(readLen = self.cbClientAddress)
|
||||
self.clientAddress = String(readLen = self.cbClientAddress, unicode = True)
|
||||
self.cbClientDir = UInt16Le(lambda:sizeof(self.clientDir))
|
||||
self.clientDir = UniString(readLen = self.cbClientDir)
|
||||
self.clientDir = String(readLen = self.cbClientDir, unicode = True)
|
||||
#TODO make tiomezone
|
||||
self.clientTimeZone = String("\x00" * 172)
|
||||
self.clientSessionId = UInt32Le()
|
||||
@@ -530,7 +530,7 @@ class ShareControlHeader(CompositeType):
|
||||
#share control header
|
||||
self.totalLength = UInt16Le(totalLength)
|
||||
self.pduType = UInt16Le(pduType)
|
||||
self.PDUSource = UInt16Le(userId + 1001)
|
||||
self.PDUSource = UInt16Le(userId)
|
||||
|
||||
class ShareDataHeader(CompositeType):
|
||||
"""
|
||||
@@ -562,7 +562,7 @@ class PDU(CompositeType):
|
||||
for c in [DemandActivePDU, ConfirmActivePDU, DataPDU, DeactiveAllPDU]:
|
||||
if self.shareControlHeader.pduType.value == c._PDUTYPE_:
|
||||
return c()
|
||||
print "WARNING : unknown PDU type : %s"%self.shareControlHeader.pduType.value
|
||||
print "WARNING : unknown PDU type : %s"%hex(self.shareControlHeader.pduType.value)
|
||||
#read entire packet
|
||||
return String()
|
||||
|
||||
@@ -643,7 +643,7 @@ class DataPDU(CompositeType):
|
||||
for c in [UpdateDataPDU, SynchronizeDataPDU, ControlDataPDU, ErrorInfoDataPDU, FontListDataPDU, FontMapDataPDU, PersistentListPDU, ClientInputEventPDU, ShutdownDeniedPDU, ShutdownRequestPDU]:
|
||||
if self.shareDataHeader.pduType2.value == c._PDUTYPE2_:
|
||||
return c()
|
||||
print "WARNING : unknown PDU data type : %s"%self.shareDataHeader.pduType2.value
|
||||
print "WARNING : unknown PDU data type : %s"%hex(self.shareDataHeader.pduType2.value)
|
||||
return String()
|
||||
|
||||
if pduData is None:
|
||||
@@ -936,7 +936,7 @@ class SlowPathInputEvent(CompositeType):
|
||||
for c in [PointerEvent, ScancodeKeyEvent, UnicodeKeyEvent]:
|
||||
if self.messageType.value == c._INPUT_MESSAGE_TYPE_:
|
||||
return c()
|
||||
print "WARNING : unknown slow path input : %s"%self.messageType.value
|
||||
print "WARNING : unknown slow path input : %s"%hex(self.messageType.value)
|
||||
return String()
|
||||
|
||||
if messageData is None:
|
||||
@@ -1037,7 +1037,7 @@ class PDULayer(LayerAutomata, tpkt.FastPathListener):
|
||||
LayerAutomata.__init__(self, mode, None)
|
||||
|
||||
#logon info send from client to server
|
||||
self._info = RDPInfo(extendedInfoConditional = lambda:(self._transport.getGCCServerSettings().core.rdpVersion.value == gcc.Version.RDP_VERSION_5_PLUS))
|
||||
self._info = RDPInfo(extendedInfoConditional = lambda:(self._transport.getGCCServerSettings().getBlock(gcc.MessageType.SC_CORE).rdpVersion.value == gcc.Version.RDP_VERSION_5_PLUS))
|
||||
#server capabilities
|
||||
self._serverCapabilities = {
|
||||
caps.CapsType.CAPSTYPE_GENERAL : caps.Capability(caps.CapsType.CAPSTYPE_GENERAL, caps.GeneralCapability()),
|
||||
|
||||
@@ -15,7 +15,7 @@ def readLength(s):
|
||||
s.readType(byte)
|
||||
size = 0
|
||||
if byte.value & 0x80:
|
||||
byte.value &= 0x80
|
||||
byte.value &= ~0x80
|
||||
size = byte.value << 8
|
||||
s.readType(byte)
|
||||
size += byte.value
|
||||
|
||||
@@ -214,7 +214,7 @@ class RDPServerController(pdu.PDUServerListener):
|
||||
@param privateKeyFileName: file contain server private key
|
||||
@param certficiateFileName: file that contain public key
|
||||
"""
|
||||
self._pduLayer = pdu.PDU(self)
|
||||
self._pduLayer = pdu.PDULayer(self)
|
||||
#multi channel service
|
||||
self._mcsLayer = mcs.MCS(LayerMode.SERVER, self._pduLayer)
|
||||
#transport pdu layer
|
||||
|
||||
@@ -294,4 +294,12 @@ class ServerTLSContext(ssl.DefaultOpenSSLContextFactory):
|
||||
@param certificateFileName: Name of a file containing a certificate
|
||||
"""
|
||||
def __init__(self, privateKeyFileName, certificateFileName):
|
||||
ssl.DefaultOpenSSLContextFactory.__init__(self, privateKeyFileName, certificateFileName, SSL.TLSv1_METHOD)
|
||||
class TPDUSSLContext(SSL.Context):
|
||||
def __init__(self, method):
|
||||
SSL.Context.__init__(method)
|
||||
self.set_options(0x00020000)#SSL_OP_NO_COMPRESSION
|
||||
self.set_options(SSL.OP_DONT_INSERT_EMPTY_FRAGMENTS)
|
||||
self.set_options(SSL.OP_TLS_BLOCK_PADDING_BUG)
|
||||
|
||||
ssl.DefaultOpenSSLContextFactory.__init__(self, privateKeyFileName, certificateFileName, SSL.TLSv1_METHOD, TPDUSSLContext)
|
||||
|
||||
Reference in New Issue
Block a user