mcs user connection

This commit is contained in:
speyrefitte
2013-10-31 14:50:51 +01:00
parent dec944ed4c
commit 58e18d3179
3 changed files with 133 additions and 27 deletions

View File

@@ -94,9 +94,12 @@ class SimpleType(Type):
'''
compare inner value
magic function of python use for any compare operators
@param other: Type value which will be compared with self value
@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
'''
if not isinstance(other, SimpleType):
other = self.__class__(other)
return self.value.__cmp__(other.value)
def write(self, s):
@@ -159,38 +162,68 @@ class SimpleType(Type):
def __add__(self, other):
'''
implement addition operator
@attention: type overflow are not handle
@param other: SimpleType value
@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
@attention: type overflow are not handle
@param other: SimpleType value
@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
@param other: SimpleType value
@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 and operator
@param other: SimpleType value
@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 __lshift__(self, other):
'''
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
@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))
class CompositeType(Type):

View File

@@ -1,7 +1,7 @@
'''
@author sylvain
@summary gcc language
@contact: http://msdn.microsoft.com/en-us/library/cc240510.aspx
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
'''
from rdpy.utils.const import ConstAttributes, TypeAttributes
from rdpy.protocol.network.type import UInt8, UInt16Le, UInt32Le, CompositeType, String, UniString, Stream, sizeof
@@ -74,7 +74,7 @@ class Support(object):
@TypeAttributes(UInt16Le)
class CapabilityFlags(object):
'''
@contact: http://msdn.microsoft.com/en-us/library/cc240510.aspx
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
for more details on each flags click above
'''
RNS_UD_CS_SUPPORT_ERRINFO_PDU = 0x0001
@@ -95,7 +95,7 @@ class ConnectionType(object):
'''
this information is correct if
RNS_UD_CS_VALID_CONNECTION_TYPE flag is set on capabilityFlag
@contact: http://msdn.microsoft.com/en-us/library/cc240510.aspx
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
'''
CONNECTION_TYPE_MODEM = 0x01
CONNECTION_TYPE_BROADBAND_LOW = 0x02
@@ -130,7 +130,25 @@ class Encryption(object):
ENCRYPTION_FLAG_128BIT = 0x00000002
ENCRYPTION_FLAG_56BIT = 0x00000008
FIPS_ENCRYPTION_FLAG = 0x00000010
@ConstAttributes
@TypeAttributes(UInt32Le)
class ChannelOptions(object):
'''
channel options
@see: http://msdn.microsoft.com/en-us/library/cc240513.aspx
'''
CHANNEL_OPTION_INITIALIZED = 0x80000000
CHANNEL_OPTION_ENCRYPT_RDP = 0x40000000
CHANNEL_OPTION_ENCRYPT_SC = 0x20000000
CHANNEL_OPTION_ENCRYPT_CS = 0x10000000
CHANNEL_OPTION_PRI_HIGH = 0x08000000
CHANNEL_OPTION_PRI_MED = 0x04000000
CHANNEL_OPTION_PRI_LOW = 0x02000000
CHANNEL_OPTION_COMPRESS_RDP = 0x00800000
CHANNEL_OPTION_COMPRESS = 0x00400000
CHANNEL_OPTION_SHOW_PROTOCOL = 0x00200000
REMOTE_CONTROL_PERSISTENT = 0x00100000
class ClientCoreSettings(CompositeType):
'''
@@ -212,7 +230,7 @@ class ClientSettings(object):
def __init__(self):
self.core = ClientCoreSettings()
#list of ClientRequestedChannel read network gcc packet
self.networkChannels = []
self.networkChannels = [ClientRequestedChannel("rdpdr", ChannelOptions.CHANNEL_OPTION_INITIALIZED)]
self.security = ClientSecuritySettings()
class ServerSettings(object):
@@ -271,8 +289,8 @@ def writeClientDataBlocks(settings):
@param settings: ClientSettings
'''
return (writeClientCoreData(settings.core),
writeClientNetworkData(settings.networkChannels),
writeClientSecurityData(settings.security))
writeClientSecurityData(settings.security),
writeClientNetworkData(settings.networkChannels))
def readServerDataBlocks(s):
'''
@@ -295,6 +313,7 @@ def readServerDataBlocks(s):
elif blockType == ServerToClientMessage.SC_NET:
settings.channelsId = readServerSecurityData(s)
#read security block
#unused in rdpy because use SSL layer
elif blockType == ServerToClientMessage.SC_SECURITY:
s.readType(settings.security)
else:
@@ -327,7 +346,7 @@ def writeClientNetworkData(channels):
'''
if len(channels) == 0:
return ()
return (ClientToServerMessage.CS_NET, UInt16Le(len(channels) * sizeof(ClientRequestedChannel()) + 4), UInt32Le(len(channels)), tuple(channels))
return (ClientToServerMessage.CS_NET, UInt16Le(len(channels) * sizeof(ClientRequestedChannel()) + 8), UInt32Le(len(channels)), tuple(channels))
def readServerSecurityData(s):
'''

View File

@@ -4,11 +4,11 @@
from rdpy.utils.const import ConstAttributes, TypeAttributes
from rdpy.protocol.network.layer import LayerAutomata
from rdpy.protocol.network.type import sizeof, Stream, UInt8
from rdpy.protocol.network.type import sizeof, Stream, UInt8, UInt16Be
from rdpy.protocol.rdp.ber import writeLength
from rdpy.protocol.network.error import InvalidExpectedDataException, InvalidValue, InvalidSize
import ber, gcc
import ber, gcc, per
@ConstAttributes
@TypeAttributes(UInt8)
@@ -18,14 +18,16 @@ class Message(object):
'''
MCS_TYPE_CONNECT_INITIAL = 0x65
MCS_TYPE_CONNECT_RESPONSE = 0x66
MCS_EDRQ = 1
MCS_DPUM = 8
MCS_AURQ = 10
MCS_AUCF = 11
MCS_CJRQ = 14
MCS_CJCF = 15
MCS_SDRQ = 25
MCS_SDIN = 26
@ConstAttributes
@TypeAttributes(UInt8)
class DomainMCSPDU:
'''
domain mcs pdu header
'''
ERECT_DOMAIN_REQUEST = 1
ATTACH_USER_REQUEST = 10
ATTACH_USER_CONFIRM = 11
class Channel:
MCS_GLOBAL_CHANNEL = 1003
@@ -37,7 +39,6 @@ class MCS(LayerAutomata):
the main layer of RDP protocol
is why he can do everything and more!
'''
def __init__(self, presentation = None):
'''
ctor call base class ctor
@@ -45,6 +46,8 @@ class MCS(LayerAutomata):
'''
LayerAutomata.__init__(self, presentation)
self._clientSettings = gcc.ClientSettings()
#default user Id
self._userId = UInt16Be(1)
def connect(self):
'''
@@ -71,6 +74,18 @@ class MCS(LayerAutomata):
#we must receive a connect response
self.setNextState(self.recvConnectResponse)
def sendErectDomainRequest(self):
'''
send a formated erect domain request for RDP connection
'''
self._transport.send((self.writeMCSPDUHeader(DomainMCSPDU.ERECT_DOMAIN_REQUEST), per.writeInteger(0), per.writeInteger(0)))
def sendAttachUserRequest(self):
'''
send a formated attach user request for RDP connection
'''
self._transport.send(self.writeMCSPDUHeader(DomainMCSPDU.ATTACH_USER_REQUEST))
def recvConnectResponse(self, data):
'''
receive mcs connect response from server
@@ -81,11 +96,32 @@ class MCS(LayerAutomata):
ber.readInteger(data)
self.readDomainParams(data)
if not ber.readUniversalTag(data, ber.Tag.BER_TAG_OCTET_STRING, False):
raise InvalidExpectedDataException("invalid expected tag")
raise InvalidExpectedDataException("invalid expected ber tag")
gccRequestLength = ber.readLength(data)
if data.dataLen() != gccRequestLength:
raise InvalidSize("bad size of gcc request")
gcc.readConferenceCreateResponse(data)
#send domain request
self.sendErectDomainRequest()
#send attach user request
self.sendAttachUserRequest()
#now wait user confirm from server
self.setNextState(self.recvAttachUserConfirm)
def recvAttachUserConfirm(self, data):
'''
recaive a attach user confirm
@param data: Stream
'''
opcode = UInt8()
confirm = UInt8()
data.readType((opcode, confirm))
if not self.readMCSPDUHeader(opcode, 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)
def writeDomainParams(self, maxChannels, maxUsers, maxTokens, maxPduSize):
'''
@@ -102,6 +138,24 @@ class MCS(LayerAutomata):
ber.writeInteger(maxPduSize), ber.writeInteger(2))
return (ber.writeUniversalTag(ber.Tag.BER_TAG_SEQUENCE, True), writeLength(sizeof(domainParam)), domainParam)
def writeMCSPDUHeader(self, mcsPdu, options = 0):
'''
write mcs pdu header
@param mcsPdu: pdu code
@param options: option contains in header
@return: UInt8
'''
return (mcsPdu << 2) | options
def readMCSPDUHeader(self, opcode, mcsPdu):
'''
read mcsPdu header and return options parameter
@param opcode: UInt8 opcode
@param mcsPdu: mcsPdu will be checked
@return: true if opcode is correct
'''
return (opcode >> 2) == mcsPdu
def readDomainParams(self, s):
'''
read domain params structure