bug fix on server side, add log engine, change lib to core
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -2,7 +2,7 @@
|
||||
.project
|
||||
.pydevproject
|
||||
README.md~
|
||||
lib/build/*
|
||||
rdpy/core/tmp/*
|
||||
*.so
|
||||
*.os
|
||||
.sconsign.dblite
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
import sys, os
|
||||
# Change path so we find rdpy
|
||||
sys.path.insert(1, os.path.join(sys.path[0], '..'))
|
||||
import unittest, rdpy.tests.network.type, rdpy.tests.network.const, rdpy.tests.network.layer
|
||||
|
||||
def headerTest(name):
|
||||
print "*"*70
|
||||
print name
|
||||
print "*"*70
|
||||
|
||||
if __name__ == '__main__':
|
||||
headerTest("Test case rdpy.test.network.type.TypeCase")
|
||||
suite = unittest.TestLoader().loadTestsFromTestCase(rdpy.tests.network.type.TypeCase)
|
||||
unittest.TextTestRunner(verbosity=2).run(suite)
|
||||
|
||||
headerTest("Test case rdpy.test.network.const.ConstCase")
|
||||
suite = unittest.TestLoader().loadTestsFromTestCase(rdpy.tests.network.const.ConstCase)
|
||||
unittest.TextTestRunner(verbosity=2).run(suite)
|
||||
|
||||
headerTest("Test case rdpy.test.network.type.layer.LayerCase")
|
||||
suite = unittest.TestLoader().loadTestsFromTestCase(rdpy.tests.network.layer.LayerCase)
|
||||
unittest.TextTestRunner(verbosity=2).run(suite)
|
||||
|
||||
57
rdpy/base/log.py
Normal file
57
rdpy/base/log.py
Normal file
@@ -0,0 +1,57 @@
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
"""
|
||||
Log engine in RDPY
|
||||
Actually very basic log engine
|
||||
"""
|
||||
|
||||
class Level(object):
|
||||
"""
|
||||
Level log
|
||||
"""
|
||||
DEBUG = 0
|
||||
INFO = 1
|
||||
WARNING = 2
|
||||
ERROR = 3
|
||||
|
||||
_LOG_LEVEL = Level.DEBUG
|
||||
|
||||
def log(message):
|
||||
print message
|
||||
|
||||
def error(message):
|
||||
if _LOG_LEVEL > Level.ERROR:
|
||||
return
|
||||
log("ERROR : %s"%message)
|
||||
|
||||
def warning(message):
|
||||
if _LOG_LEVEL > Level.WARNING:
|
||||
return
|
||||
log("WARNING : %s"%message)
|
||||
|
||||
def info(message):
|
||||
if _LOG_LEVEL > Level.INFO:
|
||||
return
|
||||
log("INFO : %s"%message)
|
||||
|
||||
def debug(message):
|
||||
if _LOG_LEVEL > Level.DEBUG:
|
||||
return
|
||||
log("DEBUG : %s"%message)
|
||||
@@ -2,7 +2,7 @@ import os
|
||||
import sipconfig
|
||||
|
||||
script_dir = os.path.dirname(os.path.realpath(Dir("#/Sconstruct").abspath))
|
||||
build_dir = os.path.join(script_dir, "build")
|
||||
tmp_dir = os.path.join(script_dir, "tmp")
|
||||
src_dir = os.path.join(script_dir, "src")
|
||||
sip_dir = os.path.join(script_dir, "sip")
|
||||
|
||||
@@ -14,11 +14,11 @@ def build_sip(target, source, env):
|
||||
os.system(" ".join([config.sip_bin, "-c", os.path.dirname(str(target[0])), str(source[0])]))
|
||||
|
||||
def build_module(name, install_dir, env):
|
||||
targetName = os.path.join(build_dir, name, "%s.so"%name)
|
||||
targetName = os.path.join(tmp_dir, name, "%s.so"%name)
|
||||
|
||||
sources = [Glob(os.path.join(src_dir, name,'*.c')), os.path.join(build_dir, name, "sip%scmodule.c"%name)]
|
||||
sources = [Glob(os.path.join(src_dir, name,'*.c')), os.path.join(tmp_dir, name, "sip%scmodule.c"%name)]
|
||||
|
||||
env.Sip(os.path.join(build_dir, name, "sip%scmodule.c"%name), os.path.join(sip_dir, "%s.sip"%name))
|
||||
env.Sip(os.path.join(tmp_dir, name, "sip%scmodule.c"%name), os.path.join(sip_dir, "%s.sip"%name))
|
||||
|
||||
#sources.append(sip)
|
||||
lib = env.SharedLibrary(target = targetName, source = sources, SHLIBPREFIX='')
|
||||
@@ -31,6 +31,6 @@ def build_module(name, install_dir, env):
|
||||
env = Environment()
|
||||
env.Append(BUILDERS = {'Sip' : Builder(action = build_sip)})
|
||||
env.Append(CPPPATH = ["/usr/include/python2.7"]);
|
||||
env.VariantDir('build', 'src', duplicate=0)
|
||||
build_module("rle", os.path.join(script_dir, "..", "rdpy", "ui"), env)
|
||||
env.VariantDir('tmp', 'src', duplicate=0)
|
||||
build_module("rle", script_dir, env)
|
||||
|
||||
@@ -23,7 +23,7 @@ Join RDPY design with twisted design
|
||||
RDPY use Layer Protocol design (like twisted)
|
||||
"""
|
||||
|
||||
from rdpy.network.error import CallPureVirtualFuntion
|
||||
from rdpy.base.error import CallPureVirtualFuntion
|
||||
|
||||
class LayerMode(object):
|
||||
NONE = 0
|
||||
|
||||
@@ -27,8 +27,8 @@ We are in python we can use that!
|
||||
import struct
|
||||
from copy import deepcopy
|
||||
from StringIO import StringIO
|
||||
from error import InvalidValue
|
||||
from rdpy.network.error import InvalidExpectedDataException, InvalidSize, CallPureVirtualFuntion
|
||||
from rdpy.base.error import InvalidExpectedDataException, InvalidSize, CallPureVirtualFuntion, InvalidValue
|
||||
import rdpy.base.log as log
|
||||
|
||||
def sizeof(element):
|
||||
"""
|
||||
@@ -432,7 +432,7 @@ class CompositeType(Type):
|
||||
raise InvalidSize("Impossible to read type %s : read length is too small"%(self.__class__))
|
||||
|
||||
except Exception as e:
|
||||
print "Error during read %s::%s"%(self.__class__, name)
|
||||
log.error("Error during read %s::%s"%(self.__class__, name))
|
||||
#roll back already read
|
||||
for tmpName in self._typeName:
|
||||
if tmpName == name:
|
||||
@@ -440,7 +440,7 @@ class CompositeType(Type):
|
||||
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__
|
||||
log.warning("still have correct data in packet %s, read it as padding"%self.__class__)
|
||||
s.read(self._readLen.value - readLen)
|
||||
|
||||
def __write__(self, s):
|
||||
@@ -452,7 +452,7 @@ class CompositeType(Type):
|
||||
try:
|
||||
s.writeType(self.__dict__[name])
|
||||
except Exception as e:
|
||||
print "Error during write %s::%s"%(self.__class__, name)
|
||||
log.error("Error during write %s::%s"%(self.__class__, name))
|
||||
raise e
|
||||
|
||||
def __sizeof__(self):
|
||||
@@ -949,16 +949,4 @@ def CheckValueOnRead(cls):
|
||||
if self != old:
|
||||
raise InvalidValue("CheckValueOnRead %s != %s"%(self, old))
|
||||
cls.read = read
|
||||
return cls
|
||||
|
||||
def hexDump(src, length=16):
|
||||
'''
|
||||
print hex representation of str
|
||||
@param src: string
|
||||
'''
|
||||
FILTER = ''.join([(len(repr(chr(x))) == 3) and chr(x) or '.' for x in range(256)])
|
||||
for c in xrange(0, len(src), length):
|
||||
chars = src[c:c+length]
|
||||
hexa = ' '.join(["%02x" % ord(x) for x in chars])
|
||||
printable = ''.join(["%s" % ((ord(x) <= 127 and FILTER[ord(x)]) or '.') for x in chars])
|
||||
print "%04x %-*s %s" % (c, length*3, hexa, printable)
|
||||
return cls
|
||||
@@ -23,7 +23,7 @@ ASN.1 standard
|
||||
"""
|
||||
|
||||
from rdpy.network.type import UInt8, UInt16Be, UInt32Be, String
|
||||
from rdpy.network.error import InvalidExpectedDataException, InvalidSize
|
||||
from rdpy.base.error import InvalidExpectedDataException, InvalidSize
|
||||
|
||||
class BerPc(object):
|
||||
BER_PC_MASK = 0x20
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
# 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
|
||||
from rdpy.base.error import InvalidExpectedDataException
|
||||
import rdpy.base.log as log
|
||||
|
||||
"""
|
||||
Definition of structure use for capabilities nego
|
||||
@@ -237,7 +238,7 @@ class Capability(CompositeType):
|
||||
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)
|
||||
log.debug("unknown Capability type : %s"%hex(self.capabilitySetType.value))
|
||||
#read entire packet
|
||||
return String(readLen = self.lengthCapability - 4)
|
||||
|
||||
|
||||
@@ -23,8 +23,9 @@ http://msdn.microsoft.com/en-us/library/cc240508.aspx
|
||||
"""
|
||||
|
||||
from rdpy.network.type import UInt8, UInt16Le, UInt32Le, CompositeType, String, Stream, sizeof, FactoryType, ArrayType
|
||||
import per
|
||||
from rdpy.network.error import InvalidExpectedDataException
|
||||
import per, mcs
|
||||
from rdpy.base.error import InvalidExpectedDataException
|
||||
import rdpy.base.log as log
|
||||
|
||||
t124_02_98_oid = ( 0, 0, 20, 124, 0, 1 )
|
||||
|
||||
@@ -204,7 +205,7 @@ class DataBlock(CompositeType):
|
||||
for c in [ClientCoreData, ClientSecurityData, ClientNetworkData, ServerCoreData, ServerNetworkData, ServerSecurityData]:
|
||||
if self.type.value == c._TYPE_:
|
||||
return c(readLen = self.length - 4)
|
||||
print "WARNING : unknown GCC block type : %s"%hex(self.type.value)
|
||||
log.debug("unknown GCC block type : %s"%hex(self.type.value))
|
||||
#read entire packet
|
||||
return String(readLen = self.length - 4)
|
||||
|
||||
@@ -285,8 +286,7 @@ class ServerSecurityData(CompositeType):
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.encryptionMethod = UInt32Le()
|
||||
self.encryptionLevel = UInt32Le()
|
||||
|
||||
self.encryptionLevel = UInt32Le()
|
||||
|
||||
class ChannelDef(CompositeType):
|
||||
"""
|
||||
@@ -310,7 +310,7 @@ class ClientNetworkData(CompositeType):
|
||||
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.channelCount = UInt32Le()
|
||||
self.channelCount = UInt32Le(lambda:len(self.channelDefArray._array))
|
||||
self.channelDefArray = ArrayType(ChannelDef, readLen = self.channelCount)
|
||||
|
||||
class ServerNetworkData(CompositeType):
|
||||
@@ -323,7 +323,7 @@ class ServerNetworkData(CompositeType):
|
||||
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.MCSChannelId = UInt16Le()
|
||||
self.MCSChannelId = UInt16Le(mcs.Channel.MCS_GLOBAL_CHANNEL)
|
||||
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))
|
||||
|
||||
@@ -23,7 +23,8 @@ RDP extended license
|
||||
"""
|
||||
|
||||
from rdpy.network.type import CompositeType, UInt8, UInt16Le, UInt32Le, String, sizeof, FactoryType, ArrayType
|
||||
from rdpy.network.error import InvalidExpectedDataException
|
||||
from rdpy.base.error import InvalidExpectedDataException
|
||||
import rdpy.base.log as log
|
||||
|
||||
class MessageType(object):
|
||||
"""
|
||||
@@ -193,7 +194,7 @@ class LicPacket(CompositeType):
|
||||
for c in [LicensingErrorMessage, ServerLicenseRequest, ClientNewLicenseRequest]:
|
||||
if self.bMsgtype.value == c._MESSAGE_TYPE_:
|
||||
return c()
|
||||
print "WARNING : unknown license message : %s"%self.bMsgtype.value
|
||||
log.debug("unknown license message : %s"%self.bMsgtype.value)
|
||||
return String()
|
||||
|
||||
if message is None:
|
||||
|
||||
@@ -26,8 +26,9 @@ 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, UInt16Le
|
||||
from rdpy.network.error import InvalidExpectedDataException, InvalidValue, InvalidSize
|
||||
from rdpy.base.error import InvalidExpectedDataException, InvalidValue, InvalidSize
|
||||
from rdpy.protocol.rdp.ber import writeLength
|
||||
import rdpy.base.log as log
|
||||
|
||||
import ber, gcc, per
|
||||
|
||||
@@ -115,10 +116,11 @@ class MCS(LayerAutomata):
|
||||
return self._mcs._serverSettings
|
||||
|
||||
|
||||
def __init__(self, mode, presentation):
|
||||
def __init__(self, mode, presentation, virtualChannels = []):
|
||||
"""
|
||||
@param mode: mode of MCS layer
|
||||
@param presentation: presentation layer
|
||||
@param virtualChannels: list additional channels like rdpsnd... [tuple(mcs.ChannelDef, layer)]
|
||||
"""
|
||||
LayerAutomata.__init__(self, mode, presentation)
|
||||
self._clientSettings = gcc.clientSettings()
|
||||
@@ -126,7 +128,13 @@ class MCS(LayerAutomata):
|
||||
#default user Id
|
||||
self._userId = 1 + Channel.MCS_USERCHANNEL_BASE
|
||||
#list of channel use in this layer and connection state
|
||||
self._channelIds = {Channel.MCS_GLOBAL_CHANNEL: presentation}
|
||||
self._channels = {Channel.MCS_GLOBAL_CHANNEL: presentation}
|
||||
#virtual channels
|
||||
self._virtualChannels = virtualChannels
|
||||
#nb join and confirm channel
|
||||
self._nbJoinAndConfirmChannel = 0
|
||||
self._isGlobalChannelRequested = False
|
||||
self._isUserChannelRequested = False
|
||||
#use to record already requested channel
|
||||
self._channelIdsRequested = {}
|
||||
|
||||
@@ -137,7 +145,12 @@ class MCS(LayerAutomata):
|
||||
"""
|
||||
if self._mode == LayerMode.CLIENT:
|
||||
self._clientSettings.getBlock(gcc.MessageType.CS_CORE).serverSelectedProtocol.value = self._transport._selectedProtocol
|
||||
#ask for virtual channel
|
||||
self._clientSettings.getBlock(gcc.MessageType.CS_NET).channelDefArray._array = [x for (x, _) in self._virtualChannels]
|
||||
#send connect initial
|
||||
self.sendConnectInitial()
|
||||
#next wait response
|
||||
self.setNextState(self.recvConnectResponse)
|
||||
else:
|
||||
self._serverSettings.getBlock(gcc.MessageType.SC_CORE).clientRequestedProtocol.value = self._transport._requestedProtocol
|
||||
self.setNextState(self.recvConnectInitial)
|
||||
@@ -147,21 +160,41 @@ class MCS(LayerAutomata):
|
||||
Send sendChannelJoinRequest message on next disconnect channel
|
||||
client automata function
|
||||
"""
|
||||
for (channelId, layer) in self._channelIds.iteritems():
|
||||
#for each disconnect channel send a request
|
||||
if not self._channelIdsRequested.has_key(channelId):
|
||||
self.sendChannelJoinRequest(channelId)
|
||||
self.setNextState(self.recvChannelJoinConfirm)
|
||||
return
|
||||
|
||||
self.setNextState(self.recvChannelJoinConfirm)
|
||||
#global channel
|
||||
if not self._isGlobalChannelRequested:
|
||||
self.sendChannelJoinRequest(Channel.MCS_GLOBAL_CHANNEL)
|
||||
self._isGlobalChannelRequested = True
|
||||
return
|
||||
|
||||
#user channel
|
||||
if not self._isUserChannelRequested:
|
||||
self.sendChannelJoinRequest(self._userId)
|
||||
self._isUserChannelRequested = True
|
||||
return
|
||||
|
||||
#static virtual channel
|
||||
if self._nbJoinAndConfirmChannel < self._serverSettings.getBlock(gcc.MessageType.SC_NET).channelCount.value:
|
||||
channelId = self._serverSettings.getBlock(gcc.MessageType.SC_NET).channelIdArray._array[self._nbJoinAndConfirmChannel]
|
||||
self._nbJoinAndConfirmChannel += 1
|
||||
self.sendChannelJoinRequest(channelId)
|
||||
return
|
||||
|
||||
self.allChannelConnected()
|
||||
|
||||
def allChannelConnected(self):
|
||||
"""
|
||||
All channels are connected to MCS layer
|
||||
Send connect to upper channel
|
||||
And prepare MCS layer to receive data
|
||||
"""
|
||||
#connection is done
|
||||
self.setNextState(self.recvData)
|
||||
#try connection on all requested channel
|
||||
for (channelId, layer) in self._channelIds.iteritems():
|
||||
if self._channelIdsRequested[channelId] and not layer is None:
|
||||
#use proxy for each channel
|
||||
layer._transport = MCS.MCSProxySender(self, channelId)
|
||||
layer.connect()
|
||||
for (channelId, layer) in self._channels.iteritems():
|
||||
#use proxy for each channel
|
||||
layer._transport = MCS.MCSProxySender(self, channelId)
|
||||
layer.connect()
|
||||
|
||||
def sendConnectInitial(self):
|
||||
"""
|
||||
@@ -178,8 +211,6 @@ class MCS(LayerAutomata):
|
||||
self.writeDomainParams(0xffff, 0xfc17, 0xffff, 0xffff),
|
||||
ber.writeOctetstring(ccReqStream.getvalue()))
|
||||
self._transport.send((ber.writeApplicationTag(Message.MCS_TYPE_CONNECT_INITIAL, sizeof(tmp)), tmp))
|
||||
#we must receive a connect response
|
||||
self.setNextState(self.recvConnectResponse)
|
||||
|
||||
def sendConnectResponse(self):
|
||||
"""
|
||||
@@ -194,8 +225,6 @@ class MCS(LayerAutomata):
|
||||
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
|
||||
@@ -217,7 +246,7 @@ class MCS(LayerAutomata):
|
||||
Send attach user confirm
|
||||
server automata function
|
||||
"""
|
||||
self._transport.send((self.writeMCSPDUHeader(UInt8(DomainMCSPDU.ATTACH_USER_CONFIRM)),
|
||||
self._transport.send((self.writeMCSPDUHeader(UInt8(DomainMCSPDU.ATTACH_USER_CONFIRM), 2),
|
||||
per.writeEnumerates(0),
|
||||
per.writeInteger16(self._userId, Channel.MCS_USERCHANNEL_BASE)))
|
||||
|
||||
@@ -237,7 +266,7 @@ class MCS(LayerAutomata):
|
||||
@param channelId: id of channel
|
||||
@param confirm: connection state
|
||||
"""
|
||||
self._transport.send((self.writeMCSPDUHeader(UInt8(DomainMCSPDU.CHANNEL_JOIN_CONFIRM)),
|
||||
self._transport.send((self.writeMCSPDUHeader(UInt8(DomainMCSPDU.CHANNEL_JOIN_CONFIRM), 2),
|
||||
per.writeEnumerates(int(confirm)),
|
||||
per.writeInteger16(self._userId, Channel.MCS_USERCHANNEL_BASE),
|
||||
per.writeInteger16(channelId),
|
||||
@@ -276,6 +305,7 @@ class MCS(LayerAutomata):
|
||||
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()
|
||||
self.setNextState(self.recvErectDomainRequest)
|
||||
|
||||
def recvConnectResponse(self, data):
|
||||
"""
|
||||
@@ -350,10 +380,6 @@ class MCS(LayerAutomata):
|
||||
|
||||
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] = None
|
||||
|
||||
self.connectNextChannel()
|
||||
|
||||
def recvChannelJoinRequest(self, data):
|
||||
@@ -374,7 +400,12 @@ class MCS(LayerAutomata):
|
||||
raise InvalidExpectedDataException("Invalid MCS User Id")
|
||||
|
||||
channelId = per.readInteger16(data)
|
||||
self.sendChannelJoinConfirm(channelId, channelId in self._channelIds.keys() or channelId == self._userId)
|
||||
#TODO check if it's a virtual channel too
|
||||
#actually algo support virtual channel but not RDPY
|
||||
self.sendChannelJoinConfirm(channelId, channelId in self._channels.keys() or channelId == self._userId)
|
||||
self._nbJoinAndConfirmChannel += 1
|
||||
if self._nbJoinAndConfirmChannel == self._serverSettings.getBlock(gcc.MessageType.SC_NET).channelCount.value + 2:
|
||||
self.allChannelConnected()
|
||||
|
||||
def recvChannelJoinConfirm(self, data):
|
||||
"""
|
||||
@@ -395,8 +426,16 @@ class MCS(LayerAutomata):
|
||||
raise InvalidExpectedDataException("Invalid MCS User Id")
|
||||
|
||||
channelId = per.readInteger16(data)
|
||||
#save state of channel
|
||||
self._channelIdsRequested[channelId] = (confirm == 0)
|
||||
#must confirm global channel and user channel
|
||||
if (confirm != 0) and (channelId == Channel.MCS_GLOBAL_CHANNEL or channelId == self._userId):
|
||||
raise InvalidExpectedDataException("Server must confirm static channel")
|
||||
|
||||
if confirm ==0:
|
||||
serverNet = self._serverSettings.getBlock(gcc.MessageType.SC_NET)
|
||||
for i in range(0, serverNet.channelCount.value):
|
||||
if channelId == serverNet.channelIdArray._array[i].value:
|
||||
self._channels[channelId] = self._virtualChannels[i][1]
|
||||
|
||||
self.connectNextChannel()
|
||||
|
||||
def recvData(self, data):
|
||||
@@ -408,7 +447,7 @@ class MCS(LayerAutomata):
|
||||
data.readType(opcode)
|
||||
|
||||
if self.readMCSPDUHeader(opcode.value, DomainMCSPDU.DISCONNECT_PROVIDER_ULTIMATUM):
|
||||
print "INFO : MCS DISCONNECT_PROVIDER_ULTIMATUM"
|
||||
log.info("MCS DISCONNECT_PROVIDER_ULTIMATUM")
|
||||
self._transport.close()
|
||||
return
|
||||
|
||||
@@ -424,16 +463,11 @@ class MCS(LayerAutomata):
|
||||
per.readLength(data)
|
||||
|
||||
#channel id doesn't match a requested layer
|
||||
if not self._channelIdsRequested.has_key(channelId):
|
||||
print "ERROR : receive data for an unrequested layer"
|
||||
if not self._channels.has_key(channelId):
|
||||
log.error("receive data for an unconnected layer")
|
||||
return
|
||||
|
||||
#channel id math an unconnected layer
|
||||
if not self._channelIdsRequested[channelId]:
|
||||
print "ERROR : receive data for an unconnected layer"
|
||||
return
|
||||
|
||||
self._channelIds[channelId].recv(data)
|
||||
|
||||
self._channels[channelId].recv(data)
|
||||
|
||||
def writeDomainParams(self, maxChannels, maxUsers, maxTokens, maxPduSize):
|
||||
"""
|
||||
|
||||
@@ -25,8 +25,8 @@ 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, String, UInt8, UInt16Le, UInt32Le, sizeof, ArrayType, FactoryType
|
||||
from rdpy.network.error import InvalidExpectedDataException, CallPureVirtualFuntion, InvalidType
|
||||
|
||||
from rdpy.base.error import InvalidExpectedDataException, CallPureVirtualFuntion, InvalidType
|
||||
import rdpy.base.log as log
|
||||
import gcc, lic, caps, tpkt
|
||||
|
||||
class SecurityFlag(object):
|
||||
@@ -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"%hex(self.shareControlHeader.pduType.value)
|
||||
log.debug("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"%hex(self.shareDataHeader.pduType2.value)
|
||||
log.debug("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"%hex(self.messageType.value)
|
||||
log.debug("unknown slow path input : %s"%hex(self.messageType.value))
|
||||
return String()
|
||||
|
||||
if messageData is None:
|
||||
@@ -1219,7 +1219,7 @@ class PDULayer(LayerAutomata, tpkt.FastPathListener):
|
||||
if ErrorInfo._MESSAGES_.has_key(dataPDU.pduData.errorInfo):
|
||||
message = ErrorInfo._MESSAGES_[dataPDU.pduData.errorInfo]
|
||||
|
||||
print "Error INFO PDU : %s"%message
|
||||
log.error("INFO PDU : %s"%message)
|
||||
elif dataPDU.shareDataHeader.pduType2.value == PDUType2.PDUTYPE2_SHUTDOWN_DENIED:
|
||||
#may be an event to ask to user
|
||||
self._transport.close()
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
'''
|
||||
|
||||
from rdpy.network.type import UInt8, UInt16Be, UInt32Be, String
|
||||
from rdpy.network.error import InvalidValue, InvalidExpectedDataException
|
||||
from rdpy.base.error import InvalidValue, InvalidExpectedDataException
|
||||
|
||||
def readLength(s):
|
||||
'''
|
||||
|
||||
@@ -22,8 +22,9 @@ Use to manage RDP stack in twisted
|
||||
"""
|
||||
|
||||
from twisted.internet import protocol
|
||||
from rdpy.network.error import CallPureVirtualFuntion, InvalidValue
|
||||
from rdpy.base.error import CallPureVirtualFuntion, InvalidValue
|
||||
from rdpy.network.layer import LayerMode
|
||||
import rdpy.base.log as log
|
||||
import tpkt, tpdu, mcs, pdu, gcc
|
||||
|
||||
class RDPClientController(pdu.PDUClientListener):
|
||||
@@ -153,7 +154,7 @@ class RDPClientController(pdu.PDUClientListener):
|
||||
self._pduLayer.sendInputEvents([event])
|
||||
|
||||
except InvalidValue:
|
||||
print "try send pointer event with incorrect position"
|
||||
log.info("try send pointer event with incorrect position")
|
||||
|
||||
def sendKeyEventScancode(self, code, isPressed):
|
||||
"""
|
||||
@@ -176,7 +177,7 @@ class RDPClientController(pdu.PDUClientListener):
|
||||
self._pduLayer.sendInputEvents([event])
|
||||
|
||||
except InvalidValue:
|
||||
print "try send bad key event"
|
||||
log.info("try send bad key event")
|
||||
|
||||
def sendKeyEventUnicode(self, code, isPressed):
|
||||
"""
|
||||
@@ -197,7 +198,7 @@ class RDPClientController(pdu.PDUClientListener):
|
||||
self._pduLayer.sendInputEvents([event])
|
||||
|
||||
except InvalidValue:
|
||||
print "try send bad key event"
|
||||
log.info("try send bad key event")
|
||||
|
||||
def close(self):
|
||||
"""
|
||||
|
||||
@@ -26,7 +26,7 @@ RDP basic security is not supported by RDPY (because is not a true security laye
|
||||
|
||||
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.base.error import InvalidExpectedDataException
|
||||
|
||||
class MessageType(object):
|
||||
"""
|
||||
|
||||
@@ -24,7 +24,7 @@ Use to build correct size packet and handle slow path and fast path mode
|
||||
"""
|
||||
from rdpy.network.layer import RawLayer, LayerMode
|
||||
from rdpy.network.type import UInt8, UInt16Be, sizeof
|
||||
from rdpy.network.error import CallPureVirtualFuntion
|
||||
from rdpy.base.error import CallPureVirtualFuntion
|
||||
|
||||
class FastPathListener(object):
|
||||
"""
|
||||
|
||||
@@ -29,7 +29,7 @@ Implement Remote FrameBuffer protocol use in VNC client and server
|
||||
from twisted.internet import protocol
|
||||
from rdpy.network.layer import RawLayer, LayerMode
|
||||
from rdpy.network.type import UInt8, UInt16Be, UInt32Be, SInt32Be, String, CompositeType
|
||||
from rdpy.network.error import InvalidValue, CallPureVirtualFuntion, InvalidType
|
||||
from rdpy.base.error import InvalidValue, CallPureVirtualFuntion, InvalidType
|
||||
|
||||
class ProtocolVersion(object):
|
||||
"""
|
||||
|
||||
@@ -26,8 +26,14 @@ QRemoteDesktop is a widget use for render in rdpy
|
||||
from PyQt4 import QtGui, QtCore
|
||||
from rdpy.protocol.rfb.rfb import RFBClientObserver
|
||||
from rdpy.protocol.rdp.rdp import RDPClientObserver
|
||||
from rdpy.network.error import CallPureVirtualFuntion
|
||||
import rle
|
||||
from rdpy.base.error import CallPureVirtualFuntion
|
||||
|
||||
import rdpy.base.log as log
|
||||
|
||||
try:
|
||||
import rdpy.core.rle as rle
|
||||
except:
|
||||
log.error("Please build core package before using RLE algorithm : scons -C rdpy/core install")
|
||||
|
||||
|
||||
class QAdaptor(object):
|
||||
@@ -97,7 +103,7 @@ class RFBClientQt(RFBClientObserver, QAdaptor):
|
||||
if pixelFormat.BitsPerPixel.value == 32 and pixelFormat.RedShift.value == 16:
|
||||
imageFormat = QtGui.QImage.Format_RGB32
|
||||
else:
|
||||
print "Receive image in bad format"
|
||||
log.error("Receive image in bad format")
|
||||
return
|
||||
|
||||
image = QtGui.QImage(data, width, height, imageFormat)
|
||||
@@ -218,7 +224,7 @@ class RDPClientQt(RDPClientObserver, QAdaptor):
|
||||
else:
|
||||
image = QtGui.QImage(data, width, height, QtGui.QImage.Format_RGB32)
|
||||
else:
|
||||
print "Receive image in bad format"
|
||||
log.error("Receive image in bad format")
|
||||
return
|
||||
|
||||
#if image need to be cut
|
||||
@@ -290,8 +296,6 @@ class QRemoteDesktop(QtGui.QWidget):
|
||||
Call when mouse move
|
||||
@param event: QMouseEvent
|
||||
"""
|
||||
if self._adaptor is None:
|
||||
print "No adaptor to send mouse move event"
|
||||
self._adaptor.sendMouseEvent(event, False)
|
||||
|
||||
def mousePressEvent(self, event):
|
||||
|
||||
@@ -2,19 +2,19 @@
|
||||
@author: sylvain
|
||||
'''
|
||||
import unittest
|
||||
import rdpy.network.const
|
||||
import rdpy.base.const
|
||||
import rdpy.network.type
|
||||
|
||||
class ConstCase(unittest.TestCase):
|
||||
'''
|
||||
represent test case for all classes and function
|
||||
present in rdpy.network.const
|
||||
present in rdpy.base.const
|
||||
'''
|
||||
def test_type_attributes(self):
|
||||
'''
|
||||
test if type attributes decorator works
|
||||
'''
|
||||
@rdpy.network.const.TypeAttributes(rdpy.network.type.UInt16Le)
|
||||
@rdpy.base.const.TypeAttributes(rdpy.network.type.UInt16Le)
|
||||
class Test:
|
||||
MEMBER_1 = 1
|
||||
MEMBER_2 = 2
|
||||
@@ -26,7 +26,7 @@ class ConstCase(unittest.TestCase):
|
||||
'''
|
||||
test if get on const class member generate new object each
|
||||
'''
|
||||
@rdpy.network.const.ConstAttributes
|
||||
@rdpy.base.const.ConstAttributes
|
||||
class Test:
|
||||
MEMBER_1 = 1
|
||||
MEMBER_2 = 2
|
||||
@@ -26,17 +26,6 @@ class LayerCase(unittest.TestCase):
|
||||
|
||||
self.assertRaises(LayerCase.LayerCaseException, rdpy.network.layer.Layer(presentation = TestConnect()).connect)
|
||||
|
||||
def test_layer_receive_event(self):
|
||||
'''
|
||||
test if recv event is send from transport to presentation
|
||||
'''
|
||||
class TestConnect(rdpy.network.layer.Layer):
|
||||
def recv(self, s):
|
||||
if s == "message":
|
||||
raise LayerCase.LayerCaseException()
|
||||
|
||||
self.assertRaises(LayerCase.LayerCaseException, rdpy.network.layer.Layer(presentation = TestConnect()).recv, "message")
|
||||
|
||||
def test_layer_automata_more_than_expected(self):
|
||||
'''
|
||||
test layer automata mechanism if data received is more than expected
|
||||
@@ -331,20 +331,4 @@ class TypeCase(unittest.TestCase):
|
||||
except Exception:
|
||||
self.assertEqual(s.readLen(), 0, "invalid stream roll back operation")
|
||||
return
|
||||
self.assertTrue(False, "Constant constraint fail")
|
||||
|
||||
def test_stream_composite_type_force_read_length_optional(self):
|
||||
'''
|
||||
test where type have readLen forced and have optional subtype which have
|
||||
length greater than last subtype of composite type
|
||||
'''
|
||||
class TestType(rdpy.network.type.CompositeType):
|
||||
def __init__(self, readLen = None):
|
||||
rdpy.network.type.CompositeType.__init__(self, readLen = readLen)
|
||||
self.t1 = rdpy.network.type.UInt32Le(0, optional = True)
|
||||
self.t2 = rdpy.network.type.UInt16Le(0, optional = True)
|
||||
|
||||
s = rdpy.network.type.Stream("\x00\x00\x00\x00\x00\x00\x00")
|
||||
t = TestType(readLen = rdpy.network.type.UInt8(2))
|
||||
s.readType(t)
|
||||
self.assertTrue(not t.t1._is_readed and t.t2._is_readed, "Invalid optional reading when length is forced")
|
||||
self.assertTrue(False, "Constant constraint fail")
|
||||
Reference in New Issue
Block a user