finish RDP basic security layer client side, start server side
This commit is contained in:
@@ -149,10 +149,16 @@ def extractRSAKey(certificate):
|
||||
@return: (modulus, public exponent)
|
||||
"""
|
||||
#http://www.alvestrand.no/objectid/1.2.840.113549.1.1.1.html
|
||||
#if certificate.getComponentByName('tbsCertificate').getComponentByName('subjectPublicKeyInfo').getComponentByName('algorithm').getComponentByName('algorithm')._value != (1, 2, 840, 113549, 1, 1, 1):
|
||||
#disable check because nobody respect
|
||||
#if certificate.getComponentByName('tbsCertificate').getComponentByName('subjectPublicKeyInfo').getComponentByName('algorithm').getComponentByName('algorithm')._value != (1, 3, 14, 3, 2, 15):
|
||||
# raise InvalidExpectedDataException("Certificate doesn't contain RSA public key")
|
||||
|
||||
rsaKey = decoder.decode(encoder.encode(certificate.getComponentByName('tbsCertificate').getComponentByName('subjectPublicKeyInfo').getComponentByName('subjectPublicKey'))[3:], asn1Spec=RSAPublicKey())[0]
|
||||
#extract binary data
|
||||
l = 0L
|
||||
for b in certificate.getComponentByName('tbsCertificate').getComponentByName('subjectPublicKeyInfo').getComponentByName('subjectPublicKey'):
|
||||
l = (l << 1) | b
|
||||
|
||||
rsaKey = decoder.decode(hex(l)[2:-1].decode('hex'), asn1Spec=RSAPublicKey())[0]
|
||||
return rsaKey.getComponentByName('modulus')._value , rsaKey.getComponentByName('publicExponent')._value
|
||||
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ http://msdn.microsoft.com/en-us/library/cc240508.aspx
|
||||
from rdpy.core.type import UInt8, UInt16Le, UInt32Le, CompositeType, String, Stream, sizeof, FactoryType, ArrayType
|
||||
import per, mcs
|
||||
from rdpy.core.error import InvalidExpectedDataException
|
||||
import rdpy.core.log as log
|
||||
from rdpy.core import log, x509
|
||||
|
||||
t124_02_98_oid = ( 0, 0, 20, 124, 0, 1 )
|
||||
|
||||
@@ -123,7 +123,7 @@ class Version(object):
|
||||
class Sequence(object):
|
||||
RNS_UD_SAS_DEL = 0xAA03
|
||||
|
||||
class Encryption(object):
|
||||
class EncryptionMethod(object):
|
||||
"""
|
||||
@summary: Encryption methods supported
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240511.aspx
|
||||
@@ -132,6 +132,17 @@ class Encryption(object):
|
||||
ENCRYPTION_FLAG_128BIT = 0x00000002
|
||||
ENCRYPTION_FLAG_56BIT = 0x00000008
|
||||
FIPS_ENCRYPTION_FLAG = 0x00000010
|
||||
|
||||
class EncryptionLevel(object):
|
||||
"""
|
||||
@summary: level of 'security'
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240518.aspx
|
||||
"""
|
||||
ENCRYPTION_LEVEL_NONE = 0x00000000
|
||||
ENCRYPTION_LEVEL_LOW = 0x00000000
|
||||
ENCRYPTION_LEVEL_CLIENT_COMPATIBLE = 0x00000000
|
||||
ENCRYPTION_LEVEL_HIGH = 0x00000000
|
||||
ENCRYPTION_LEVEL_FIPS = 0x00000000
|
||||
|
||||
class ChannelOptions(object):
|
||||
"""
|
||||
@@ -206,7 +217,7 @@ class DataBlock(CompositeType):
|
||||
|
||||
def DataBlockFactory():
|
||||
"""
|
||||
build settings in accordance of type self.type.value
|
||||
@summary: build settings in accordance of type self.type.value
|
||||
"""
|
||||
for c in [ClientCoreData, ClientSecurityData, ClientNetworkData, ServerCoreData, ServerNetworkData, ServerSecurityData]:
|
||||
if self.type.value == c._TYPE_:
|
||||
@@ -224,7 +235,7 @@ class DataBlock(CompositeType):
|
||||
|
||||
class ClientCoreData(CompositeType):
|
||||
"""
|
||||
Class that represent core setting of client
|
||||
@summary: Class that represent core setting of client
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
|
||||
"""
|
||||
_TYPE_ = MessageType.CS_CORE
|
||||
@@ -256,7 +267,7 @@ class ClientCoreData(CompositeType):
|
||||
|
||||
class ServerCoreData(CompositeType):
|
||||
"""
|
||||
Server side core settings structure
|
||||
@summary: Server side core settings structure
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240517.aspx
|
||||
"""
|
||||
_TYPE_ = MessageType.SC_CORE
|
||||
@@ -268,19 +279,19 @@ class ServerCoreData(CompositeType):
|
||||
|
||||
class ClientSecurityData(CompositeType):
|
||||
"""
|
||||
Client security setting
|
||||
@summary: Client security setting
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240511.aspx
|
||||
"""
|
||||
_TYPE_ = MessageType.CS_SECURITY
|
||||
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.encryptionMethods = UInt32Le(Encryption.ENCRYPTION_FLAG_40BIT)
|
||||
self.encryptionMethods = UInt32Le(EncryptionMethod.ENCRYPTION_FLAG_40BIT | EncryptionMethod.ENCRYPTION_FLAG_56BIT | EncryptionMethod.ENCRYPTION_FLAG_128BIT)
|
||||
self.extEncryptionMethods = UInt32Le()
|
||||
|
||||
class ServerSecurityData(CompositeType):
|
||||
"""
|
||||
Server security settings
|
||||
@summary: Server security settings
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240518.aspx
|
||||
"""
|
||||
_TYPE_ = MessageType.SC_SECURITY
|
||||
@@ -314,6 +325,17 @@ class ServerCertificate(CompositeType):
|
||||
|
||||
self.certData = FactoryType(CertificateFactory)
|
||||
|
||||
def bin2bn(b):
|
||||
"""
|
||||
@summary: convert binary string to bignum
|
||||
@param b: {str} binary string
|
||||
@return: {long} bignum
|
||||
"""
|
||||
l = 0L
|
||||
for ch in b:
|
||||
l = (l<<8) | ord(ch)
|
||||
return l
|
||||
|
||||
class ProprietaryServerCertificate(CompositeType):
|
||||
"""
|
||||
@summary: microsoft proprietary certificate
|
||||
@@ -331,6 +353,13 @@ class ProprietaryServerCertificate(CompositeType):
|
||||
self.wSignatureBlobType = UInt16Le(0x0008, constant = True)
|
||||
self.wSignatureBlobLen = UInt16Le(lambda:sizeof(self.SignatureBlob))
|
||||
self.SignatureBlob = String(readLen = self.wSignatureBlobLen)
|
||||
|
||||
def getPublicKey(self):
|
||||
"""
|
||||
@return: {Tuple} (modulus, publicExponent)
|
||||
"""
|
||||
#reverse because bignum in little endian
|
||||
return bin2bn(self.PublicKeyBlob.modulus.value[::-1]), self.PublicKeyBlob.pubExp.value
|
||||
|
||||
class CertBlob(CompositeType):
|
||||
"""
|
||||
@@ -355,6 +384,13 @@ class X509CertificateChain(CompositeType):
|
||||
self.CertBlobArray = ArrayType(CertBlob, readLen = self.NumCertBlobs)
|
||||
self.padding = String(readLen = UInt8(lambda:(8 + 4 * self.NumCertBlobs.value)))
|
||||
|
||||
def getPublicKey(self):
|
||||
"""
|
||||
@return: {Tuple} (modulus, publicExponent)
|
||||
"""
|
||||
#last certifcate contain publi key
|
||||
return x509.extractRSAKey(x509.load(self.CertBlobArray[-1].abCert.value))
|
||||
|
||||
class RSAPublicKey(CompositeType):
|
||||
"""
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240520.aspx
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
from rdpy.core.type import CompositeType, UInt8, UInt16Le, UInt32Le, String, sizeof, FactoryType, ArrayType, Stream
|
||||
from rdpy.core.error import InvalidExpectedDataException
|
||||
import rdpy.core.log as log
|
||||
import rc4, sec, gcc
|
||||
from rdpy.core import x509
|
||||
import sec, gcc
|
||||
from rdpy.core import x509, rc4
|
||||
|
||||
class MessageType(object):
|
||||
"""
|
||||
|
||||
@@ -26,7 +26,7 @@ It exist channel for file system order, audio channel, clipboard etc...
|
||||
"""
|
||||
from rdpy.core.layer import LayerAutomata, IStreamSender, Layer
|
||||
from rdpy.core.type import sizeof, Stream, UInt8, UInt16Le, String
|
||||
from rdpy.core.error import InvalidExpectedDataException, InvalidValue, InvalidSize
|
||||
from rdpy.core.error import InvalidExpectedDataException, InvalidValue, InvalidSize, CallPureVirtualFuntion
|
||||
from rdpy.protocol.rdp.ber import writeLength
|
||||
import rdpy.core.log as log
|
||||
|
||||
@@ -58,6 +58,38 @@ class Channel:
|
||||
"""
|
||||
MCS_GLOBAL_CHANNEL = 1003
|
||||
MCS_USERCHANNEL_BASE = 1001
|
||||
|
||||
class IGCCConfig(object):
|
||||
"""
|
||||
@summary: Channel information
|
||||
"""
|
||||
def getUserId(self):
|
||||
"""
|
||||
@return: {integer} mcs user id
|
||||
@see: mcs.IGCCConfig
|
||||
"""
|
||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "getUserId", "IGCCConfig"))
|
||||
|
||||
def getChannelId(self):
|
||||
"""
|
||||
@return: {integer} return channel id of proxy
|
||||
@see: mcs.IGCCConfig
|
||||
"""
|
||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "getChannelId", "IGCCConfig"))
|
||||
|
||||
def getGCCClientSettings(self):
|
||||
"""
|
||||
@return: {gcc.Settings} mcs layer gcc client settings
|
||||
@see: mcs.IGCCConfig
|
||||
"""
|
||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "getGCCClientSettings", "IGCCConfig"))
|
||||
|
||||
def getGCCServerSettings(self):
|
||||
"""
|
||||
@return: {gcc.Settings} mcs layer gcc server settings
|
||||
@see: mcs.IGCCConfig
|
||||
"""
|
||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "getGCCServerSettings", "IGCCConfig"))
|
||||
|
||||
class MCSLayer(LayerAutomata):
|
||||
"""
|
||||
@@ -65,16 +97,16 @@ class MCSLayer(LayerAutomata):
|
||||
the main layer of RDP protocol
|
||||
is why he can do everything and more!
|
||||
"""
|
||||
class MCSProxySender(Layer, IStreamSender):
|
||||
class MCSProxySender(Layer, IStreamSender, IGCCConfig):
|
||||
"""
|
||||
@summary: Proxy use to set as transport layer for upper channel
|
||||
use to abstract channel id for presentation layer
|
||||
"""
|
||||
def __init__(self, presentation, mcs, channelId):
|
||||
"""
|
||||
@param presentation: presentation layer
|
||||
@param mcs: MCS layer use as proxy
|
||||
@param channelId: channel id for presentation layer
|
||||
@param presentation: {Layer} presentation layer
|
||||
@param mcs: {MCSLayer} MCS layer use as proxy
|
||||
@param channelId: {integer} channel id for presentation layer
|
||||
"""
|
||||
Layer.__init__(self, presentation)
|
||||
self._mcs = mcs
|
||||
@@ -84,6 +116,7 @@ class MCSLayer(LayerAutomata):
|
||||
"""
|
||||
@summary: A send proxy function, use channel id and specific
|
||||
send function of MCS layer
|
||||
@param data: {type.Type | Tuple}
|
||||
"""
|
||||
self._mcs.send(self._channelId, data)
|
||||
|
||||
@@ -95,35 +128,39 @@ class MCSLayer(LayerAutomata):
|
||||
|
||||
def getUserId(self):
|
||||
"""
|
||||
@return: mcs user id
|
||||
@return: {integer} mcs user id
|
||||
@see: mcs.IGCCConfig
|
||||
"""
|
||||
return self._mcs._userId
|
||||
|
||||
def getChannelId(self):
|
||||
"""
|
||||
@return: return channel id of proxy
|
||||
@return: {integer} return channel id of proxy
|
||||
@see: mcs.IGCCConfig
|
||||
"""
|
||||
return self._channelId
|
||||
|
||||
def getGCCClientSettings(self):
|
||||
"""
|
||||
@return: mcs layer gcc client settings
|
||||
@return: {gcc.Settings} mcs layer gcc client settings
|
||||
@see: mcs.IGCCConfig
|
||||
"""
|
||||
return self._mcs._clientSettings
|
||||
|
||||
def getGCCServerSettings(self):
|
||||
"""
|
||||
@return: mcs layer gcc server settings
|
||||
@return: {gcc.Settings} mcs layer gcc server settings
|
||||
@see: mcs.IGCCConfig
|
||||
"""
|
||||
return self._mcs._serverSettings
|
||||
|
||||
|
||||
def __init__(self, presentation, receiveOpcode, sendOpcode, virtualChannels = []):
|
||||
"""
|
||||
@param presentation: presentation layer
|
||||
@param virtualChannels: list additional channels like rdpsnd... [tuple(mcs.ChannelDef, layer)]
|
||||
@param receiveOpcode: opcode check when receive data
|
||||
@param sendOpcode: opcode use when send data
|
||||
@param presentation: {Layer} presentation layer
|
||||
@param virtualChannels: {Array(Layer]} list additional channels like rdpsnd... [tuple(mcs.ChannelDef, layer)]
|
||||
@param receiveOpcode: {integer} opcode check when receive data
|
||||
@param sendOpcode: {integer} opcode use when send data
|
||||
"""
|
||||
LayerAutomata.__init__(self, presentation)
|
||||
self._clientSettings = gcc.clientSettings()
|
||||
@@ -163,8 +200,8 @@ class MCSLayer(LayerAutomata):
|
||||
def send(self, channelId, data):
|
||||
"""
|
||||
@summary: Specific send function for channelId
|
||||
@param channelId: Channel use to send
|
||||
@param data: message to send
|
||||
@param channelId: {integer} Channel use to send
|
||||
@param data: {type.type | tuple} message to send
|
||||
"""
|
||||
self._transport.send((self.writeMCSPDUHeader(UInt8(self._sendOpcode)),
|
||||
per.writeInteger16(self._userId, Channel.MCS_USERCHANNEL_BASE),
|
||||
@@ -175,7 +212,7 @@ class MCSLayer(LayerAutomata):
|
||||
def recvData(self, data):
|
||||
"""
|
||||
@summary: Main receive method
|
||||
@param data: Stream
|
||||
@param data: {Stream}
|
||||
"""
|
||||
opcode = UInt8()
|
||||
data.readType(opcode)
|
||||
@@ -208,11 +245,11 @@ class MCSLayer(LayerAutomata):
|
||||
"""
|
||||
@summary: Write a special domain parameter structure
|
||||
use in connection sequence
|
||||
@param maxChannels: number of MCS channel use
|
||||
@param maxUsers: number of MCS user used (1)
|
||||
@param maxTokens: unknown
|
||||
@param maxPduSize: unknown
|
||||
@return: domain parameter structure
|
||||
@param maxChannels: {integer} number of MCS channel use
|
||||
@param maxUsers: {integer} number of MCS user used (1)
|
||||
@param maxTokens: {integer} unknown
|
||||
@param maxPduSize: {integer} unknown
|
||||
@return: {Tuple(type)} domain parameter structure
|
||||
"""
|
||||
domainParam = (ber.writeInteger(maxChannels), ber.writeInteger(maxUsers), ber.writeInteger(maxTokens),
|
||||
ber.writeInteger(1), ber.writeInteger(0), ber.writeInteger(1),
|
||||
@@ -222,25 +259,26 @@ class MCSLayer(LayerAutomata):
|
||||
def writeMCSPDUHeader(self, mcsPdu, options = 0):
|
||||
"""
|
||||
@summary: Write MCS PDU header
|
||||
@param mcsPdu: PDU code
|
||||
@param options: option contains in header
|
||||
@return: UInt8
|
||||
@param mcsPdu: {integer} PDU code
|
||||
@param options: {integer} option contains in header
|
||||
@return: {integer}
|
||||
"""
|
||||
return (mcsPdu << 2) | options
|
||||
|
||||
def readMCSPDUHeader(self, opcode, mcsPdu):
|
||||
"""
|
||||
@summary: Read mcsPdu header and return options parameter
|
||||
@param opcode: opcode
|
||||
@param mcsPdu: mcsPdu will be checked
|
||||
@return: true if opcode is correct
|
||||
@param opcode: {integer} opcode
|
||||
@param mcsPdu: {integer} mcsPdu will be checked
|
||||
@return: {boolean} true if opcode is correct
|
||||
"""
|
||||
return (opcode >> 2) == mcsPdu
|
||||
|
||||
def readDomainParams(self, s):
|
||||
"""
|
||||
@summary: Read domain parameters structure
|
||||
@return: (max_channels, max_users, max_tokens, max_pdu_size)
|
||||
@param s: {Stream}
|
||||
@return: {Tuple} (max_channels, max_users, max_tokens, max_pdu_size)
|
||||
"""
|
||||
if not ber.readUniversalTag(s, ber.Tag.BER_TAG_SEQUENCE, True):
|
||||
raise InvalidValue("bad BER tags")
|
||||
@@ -261,8 +299,8 @@ class Client(MCSLayer):
|
||||
"""
|
||||
def __init__(self, presentation, virtualChannels = []):
|
||||
"""
|
||||
@param presentation: presentation layer
|
||||
@param virtualChannels: list additional channels like rdpsnd... [tuple(mcs.ChannelDef, layer)]
|
||||
@param presentation: {Layer} presentation layer
|
||||
@param virtualChannels: {Array(Layer)} list additional channels like rdpsnd... [tuple(mcs.ChannelDef, layer)]
|
||||
"""
|
||||
MCSLayer.__init__(self, presentation, DomainMCSPDU.SEND_DATA_INDICATION, DomainMCSPDU.SEND_DATA_REQUEST, virtualChannels)
|
||||
#use to know state of static channel
|
||||
@@ -277,9 +315,9 @@ class Client(MCSLayer):
|
||||
Send ConnectInitial
|
||||
Wait ConnectResponse
|
||||
"""
|
||||
self._clientSettings.getBlock(gcc.MessageType.CS_CORE).serverSelectedProtocol.value = self._transport._selectedProtocol
|
||||
self._clientSettings.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]
|
||||
self._clientSettings.CS_NET.channelDefArray._array = [x for (x, _) in self._virtualChannels]
|
||||
#send connect initial
|
||||
self.sendConnectInitial()
|
||||
#next wait response
|
||||
@@ -319,7 +357,7 @@ class Client(MCSLayer):
|
||||
Send Erect domain Request
|
||||
Send Attach User Request
|
||||
Wait Attach User Confirm
|
||||
@param data: Stream
|
||||
@param data: {Stream}
|
||||
"""
|
||||
ber.readApplicationTag(data, UInt8(Message.MCS_TYPE_CONNECT_RESPONSE))
|
||||
ber.readEnumerated(data)
|
||||
@@ -343,7 +381,7 @@ class Client(MCSLayer):
|
||||
"""
|
||||
@summary: Receive an attach user confirm
|
||||
Send Connect Channel
|
||||
@param data: Stream
|
||||
@param data: {Stream}
|
||||
"""
|
||||
opcode = UInt8()
|
||||
data.readType(opcode)
|
||||
@@ -362,7 +400,7 @@ class Client(MCSLayer):
|
||||
"""
|
||||
@summary: Receive a channel join confirm from server
|
||||
client automata function
|
||||
@param data: Stream
|
||||
@param data: {Stream}
|
||||
"""
|
||||
opcode = UInt8()
|
||||
data.readType(opcode)
|
||||
@@ -423,7 +461,7 @@ class Client(MCSLayer):
|
||||
"""
|
||||
@summary: Send a formated Channel join request from client to server
|
||||
client automata function
|
||||
@param channelId: id of channel requested
|
||||
@param channelId: {integer} id of channel requested
|
||||
"""
|
||||
self._transport.send((self.writeMCSPDUHeader(UInt8(DomainMCSPDU.CHANNEL_JOIN_REQUEST)),
|
||||
per.writeInteger16(self._userId, Channel.MCS_USERCHANNEL_BASE),
|
||||
@@ -435,8 +473,8 @@ class Server(MCSLayer):
|
||||
"""
|
||||
def __init__(self, presentation, virtualChannels = []):
|
||||
"""
|
||||
@param presentation: presentation layer
|
||||
@param virtualChannels: list additional channels like rdpsnd... [tuple(mcs.ChannelDef, layer)]
|
||||
@param presentation: {Layer} presentation layer
|
||||
@param virtualChannels: {List(Layer)} list additional channels like rdpsnd... [tuple(mcs.ChannelDef, layer)]
|
||||
"""
|
||||
MCSLayer.__init__(self, presentation, DomainMCSPDU.SEND_DATA_REQUEST, DomainMCSPDU.SEND_DATA_INDICATION, virtualChannels)
|
||||
#nb channel requested
|
||||
@@ -447,7 +485,12 @@ class Server(MCSLayer):
|
||||
@summary: Connect message for server automata
|
||||
Wait Connect Initial
|
||||
"""
|
||||
self._serverSettings.getBlock(gcc.MessageType.SC_CORE).clientRequestedProtocol.value = self._transport._requestedProtocol
|
||||
#basic rdp security layer
|
||||
if self._transport._selectedProtocol == 0:
|
||||
self._serverSettings.SC_SECURITY.encryptionMethod.value = gcc.EncryptionMethod.ENCRYPTION_FLAG_128BIT
|
||||
self._serverSettings.SC_SECURITY.encryptionLevel = gcc.EncryptionLevel.ENCRYPTION_LEVEL_HIGH
|
||||
|
||||
self._serverSettings.SC_CORE.clientRequestedProtocol.value = self._transport._requestedProtocol
|
||||
self.setNextState(self.recvConnectInitial)
|
||||
|
||||
def recvConnectInitial(self, data):
|
||||
@@ -455,7 +498,7 @@ class Server(MCSLayer):
|
||||
@summary: Receive MCS connect initial from client
|
||||
Send Connect Response
|
||||
Wait Erect Domain Request
|
||||
@param data: Stream
|
||||
@param data: {Stream}
|
||||
"""
|
||||
ber.readApplicationTag(data, UInt8(Message.MCS_TYPE_CONNECT_INITIAL))
|
||||
ber.readOctetString(data)
|
||||
@@ -485,7 +528,7 @@ class Server(MCSLayer):
|
||||
"""
|
||||
@summary: Receive erect domain request
|
||||
Wait Attach User Request
|
||||
@param data: Stream
|
||||
@param data: {Stream}
|
||||
"""
|
||||
opcode = UInt8()
|
||||
data.readType(opcode)
|
||||
@@ -503,7 +546,7 @@ class Server(MCSLayer):
|
||||
@summary: Receive Attach user request
|
||||
Send Attach User Confirm
|
||||
Wait Channel Join Request
|
||||
@param data: Stream
|
||||
@param data: {Stream}
|
||||
"""
|
||||
opcode = UInt8()
|
||||
data.readType(opcode)
|
||||
@@ -518,7 +561,7 @@ class Server(MCSLayer):
|
||||
"""
|
||||
@summary: Receive for each client channel a request
|
||||
Send Channel Join Confirm or Connect upper layer when all channel are joined
|
||||
@param data: Stream
|
||||
@param data: {Stream}
|
||||
|
||||
"""
|
||||
opcode = UInt8()
|
||||
@@ -562,8 +605,8 @@ class Server(MCSLayer):
|
||||
def sendChannelJoinConfirm(self, channelId, confirm):
|
||||
"""
|
||||
@summary: Send a confirm channel (or not) to client
|
||||
@param channelId: id of channel
|
||||
@param confirm: connection state
|
||||
@param channelId: {integer} id of channel
|
||||
@param confirm: {boolean} connection state
|
||||
"""
|
||||
self._transport.send((self.writeMCSPDUHeader(UInt8(DomainMCSPDU.CHANNEL_JOIN_CONFIRM), 2),
|
||||
per.writeEnumerates(int(confirm)),
|
||||
|
||||
@@ -359,12 +359,12 @@ class PointerCapability(CompositeType):
|
||||
"""
|
||||
_TYPE_ = CapsType.CAPSTYPE_POINTER
|
||||
|
||||
def __init__(self, readLen = None):
|
||||
def __init__(self, isServer = False, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.colorPointerFlag = UInt16Le()
|
||||
self.colorPointerCacheSize = UInt16Le(20)
|
||||
#old version of rdp doesn't support ...
|
||||
#self.pointerCacheSize = UInt16Le()
|
||||
self.pointerCacheSize = UInt16Le(conditional = lambda:isServer)
|
||||
|
||||
class InputCapability(CompositeType):
|
||||
"""
|
||||
|
||||
@@ -26,7 +26,6 @@ In this layer are managed all mains bitmap update orders end user inputs
|
||||
from rdpy.core.layer import LayerAutomata
|
||||
from rdpy.core.error import CallPureVirtualFuntion
|
||||
import rdpy.core.log as log
|
||||
import rdpy.protocol.rdp.gcc as gcc
|
||||
import rdpy.protocol.rdp.tpkt as tpkt
|
||||
import data, caps
|
||||
|
||||
@@ -82,7 +81,7 @@ class PDULayer(LayerAutomata, tpkt.IFastPathListener):
|
||||
caps.CapsType.CAPSTYPE_GENERAL : caps.Capability(caps.GeneralCapability()),
|
||||
caps.CapsType.CAPSTYPE_BITMAP : caps.Capability(caps.BitmapCapability()),
|
||||
caps.CapsType.CAPSTYPE_ORDER : caps.Capability(caps.OrderCapability()),
|
||||
caps.CapsType.CAPSTYPE_POINTER : caps.Capability(caps.PointerCapability()),
|
||||
caps.CapsType.CAPSTYPE_POINTER : caps.Capability(caps.PointerCapability(isServer = True)),
|
||||
caps.CapsType.CAPSTYPE_INPUT : caps.Capability(caps.InputCapability()),
|
||||
caps.CapsType.CAPSTYPE_VIRTUALCHANNEL : caps.Capability(caps.VirtualChannelCapability()),
|
||||
caps.CapsType.CAPSTYPE_FONT : caps.Capability(caps.FontCapability()),
|
||||
@@ -120,7 +119,7 @@ class PDULayer(LayerAutomata, tpkt.IFastPathListener):
|
||||
@summary: Send a PDU data to transport layer
|
||||
@param pduMessage: PDU message
|
||||
"""
|
||||
self._transport.send(data.PDU(self._transport._transport.getUserId(), pduMessage))
|
||||
self._transport.send(data.PDU(self._transport.getUserId(), pduMessage))
|
||||
|
||||
def sendDataPDU(self, pduData):
|
||||
"""
|
||||
@@ -144,7 +143,7 @@ class Client(PDULayer):
|
||||
"""
|
||||
@summary: Connect message in client automata
|
||||
"""
|
||||
self._gccCore = self._transport._transport.getGCCClientSettings().CS_CORE
|
||||
self._gccCore = self._transport.getGCCClientSettings().CS_CORE
|
||||
self.setNextState(self.recvDemandActivePDU)
|
||||
#check if client support fast path message
|
||||
self._clientFastPathSupported = False
|
||||
@@ -299,7 +298,7 @@ class Client(PDULayer):
|
||||
"""
|
||||
@summary: Read an update data PDU data
|
||||
dispatch update data
|
||||
@param: UpdateDataPDU object
|
||||
@param: {UpdateDataPDU} object
|
||||
"""
|
||||
if updateDataPDU.updateType.value == data.UpdateType.UPDATETYPE_BITMAP:
|
||||
self._listener.onUpdate(updateDataPDU.updateData.rectangles._array)
|
||||
@@ -345,7 +344,7 @@ class Client(PDULayer):
|
||||
"""
|
||||
@summary: send a synchronize PDU from client to server
|
||||
"""
|
||||
synchronizePDU = data.SynchronizeDataPDU(self._transport._transport.getChannelId())
|
||||
synchronizePDU = data.SynchronizeDataPDU(self._transport.getChannelId())
|
||||
self.sendDataPDU(synchronizePDU)
|
||||
|
||||
#ask for cooperation
|
||||
@@ -364,7 +363,7 @@ class Client(PDULayer):
|
||||
|
||||
def sendInputEvents(self, pointerEvents):
|
||||
"""
|
||||
send client input events
|
||||
@summary: send client input events
|
||||
@param pointerEvents: list of pointer events
|
||||
"""
|
||||
pdu = data.ClientInputEventPDU()
|
||||
@@ -373,7 +372,7 @@ class Client(PDULayer):
|
||||
|
||||
class Server(PDULayer):
|
||||
"""
|
||||
Server Automata of PDU layer
|
||||
@summary: Server Automata of PDU layer
|
||||
"""
|
||||
def __init__(self, listener):
|
||||
"""
|
||||
@@ -386,14 +385,14 @@ class Server(PDULayer):
|
||||
|
||||
def connect(self):
|
||||
"""
|
||||
Connect message for server automata
|
||||
@summary: Connect message for server automata
|
||||
"""
|
||||
self.sendDemandActivePDU()
|
||||
self.setNextState(self.recvConfirmActivePDU)
|
||||
|
||||
def recvConfirmActivePDU(self, s):
|
||||
"""
|
||||
Receive confirm active PDU from client
|
||||
@summary: Receive confirm active PDU from client
|
||||
Capabilities exchange
|
||||
Wait Client Synchronize PDU
|
||||
@param s: Stream
|
||||
@@ -417,7 +416,7 @@ class Server(PDULayer):
|
||||
|
||||
def recvClientSynchronizePDU(self, s):
|
||||
"""
|
||||
Receive from client
|
||||
@summary: Receive from client
|
||||
Wait Control Cooperate PDU
|
||||
@param s: Stream from transport layer
|
||||
"""
|
||||
@@ -432,7 +431,7 @@ class Server(PDULayer):
|
||||
|
||||
def recvClientControlCooperatePDU(self, s):
|
||||
"""
|
||||
Receive control cooperate PDU from client
|
||||
@summary: Receive control cooperate PDU from client
|
||||
Wait Control Request PDU
|
||||
@param s: Stream from transport layer
|
||||
"""
|
||||
@@ -447,7 +446,7 @@ class Server(PDULayer):
|
||||
|
||||
def recvClientControlRequestPDU(self, s):
|
||||
"""
|
||||
Receive last control PDU the request control PDU from client
|
||||
@summary: Receive last control PDU the request control PDU from client
|
||||
Wait Font List PDU
|
||||
@param s: Stream from transport layer
|
||||
"""
|
||||
@@ -462,7 +461,7 @@ class Server(PDULayer):
|
||||
|
||||
def recvClientFontListPDU(self, s):
|
||||
"""
|
||||
Last synchronize packet from client to server
|
||||
@summary: Last synchronize packet from client to server
|
||||
Send Server Finalize PDUs
|
||||
Wait any PDU
|
||||
@param s: Stream from transport layer
|
||||
@@ -483,7 +482,7 @@ class Server(PDULayer):
|
||||
|
||||
def recvPDU(self, s):
|
||||
"""
|
||||
Main receive function after connection sequence
|
||||
@summary: Main receive function after connection sequence
|
||||
@param s: Stream from transport layer
|
||||
"""
|
||||
pdu = data.PDU()
|
||||
@@ -493,24 +492,25 @@ class Server(PDULayer):
|
||||
|
||||
def readDataPDU(self, dataPDU):
|
||||
"""
|
||||
read a data PDU object
|
||||
@summary: read a data PDU object
|
||||
@param dataPDU: DataPDU object
|
||||
"""
|
||||
if dataPDU.shareDataHeader.pduType2.value == data.PDUType2.PDUTYPE2_SET_ERROR_INFO_PDU:
|
||||
errorMessage = "Unknown code %s"%hex(dataPDU.pduData.errorInfo.value)
|
||||
if data.ErrorInfo._MESSAGES_.has_key(dataPDU.pduData.errorInfo):
|
||||
errorMessage = data.ErrorInfo._MESSAGES_[dataPDU.pduData.errorInfo]
|
||||
|
||||
log.error("INFO PDU : %s"%errorMessage)
|
||||
|
||||
elif dataPDU.shareDataHeader.pduType2.value == data.PDUType2.PDUTYPE2_INPUT:
|
||||
self._listener.onSlowPathInput(dataPDU.pduData.slowPathInputEvents._array)
|
||||
|
||||
elif dataPDU.shareDataHeader.pduType2.value == data.PDUType2.PDUTYPE2_SHUTDOWN_REQUEST:
|
||||
log.debug("Receive Shutdown Request")
|
||||
self._transport.close()
|
||||
|
||||
def recvFastPath(self, fastPathS):
|
||||
"""
|
||||
Implement IFastPathListener interface
|
||||
@summary: Implement IFastPathListener interface
|
||||
Fast path is needed by RDP 8.0
|
||||
@param fastPathS: Stream that contain fast path data
|
||||
"""
|
||||
@@ -536,9 +536,9 @@ class Server(PDULayer):
|
||||
|
||||
def sendServerFinalizeSynchronizePDU(self):
|
||||
"""
|
||||
Send last synchronize packet from server to client
|
||||
@summary: Send last synchronize packet from server to client
|
||||
"""
|
||||
synchronizePDU = data.SynchronizeDataPDU(self._transport._transport.getChannelId())
|
||||
synchronizePDU = data.SynchronizeDataPDU(self._transport.getChannelId())
|
||||
self.sendDataPDU(synchronizePDU)
|
||||
|
||||
#ask for cooperation
|
||||
@@ -557,7 +557,7 @@ class Server(PDULayer):
|
||||
|
||||
def sendPDU(self, pduMessage):
|
||||
"""
|
||||
Send a PDU data to transport layer
|
||||
@summary: Send a PDU data to transport layer
|
||||
@param pduMessage: PDU message
|
||||
"""
|
||||
PDULayer.sendPDU(self, pduMessage)
|
||||
@@ -568,7 +568,7 @@ class Server(PDULayer):
|
||||
|
||||
def sendBitmapUpdatePDU(self, bitmapDatas):
|
||||
"""
|
||||
Send bitmap update data
|
||||
@summary: Send bitmap update data
|
||||
@param bitmapDatas: List of data.BitmapData
|
||||
"""
|
||||
#check bitmap header for client that want it (very old client)
|
||||
|
||||
@@ -342,7 +342,10 @@ class RDPServerController(pdu.layer.PDUServerListener):
|
||||
#transport pdu layer
|
||||
self._x224Layer = x224.Server(self._mcsLayer, privateKeyFileName, certificateFileName)
|
||||
#transport packet (protocol layer)
|
||||
self._tpktLayer = tpkt.TPKT(self._x224Layer, self._pduLayer)
|
||||
self._tpktLayer = tpkt.TPKT(self._x224Layer)
|
||||
#fastpath stack
|
||||
self._pduLayer.initFastPath(self._secLayer)
|
||||
self._secLayer.initFastPath(self._tpktLayer)
|
||||
#set color depth of session
|
||||
self.setColorDepth(colorDepth)
|
||||
|
||||
|
||||
@@ -21,12 +21,12 @@
|
||||
Some use full methods for security in RDP
|
||||
"""
|
||||
|
||||
import sha, md5, rsa, rc4
|
||||
import gcc, lic, tpkt
|
||||
import sha, md5, rsa
|
||||
import gcc, lic, tpkt, mcs
|
||||
from rdpy.core.type import CompositeType, Stream, UInt32Le, UInt16Le, String, sizeof, UInt8
|
||||
from rdpy.core.layer import LayerAutomata, IStreamSender
|
||||
from rdpy.core.error import InvalidExpectedDataException
|
||||
from rdpy.core import log, x509
|
||||
from rdpy.core import log, x509, rc4
|
||||
|
||||
class SecurityFlag(object):
|
||||
"""
|
||||
@@ -235,13 +235,13 @@ def generateKeys(clientRandom, serverRandom, method):
|
||||
initialSecondKey128 = finalHash(sessionKey[32:48], clientRandom, serverRandom)
|
||||
|
||||
#generate valid key
|
||||
if method == gcc.Encryption.ENCRYPTION_FLAG_40BIT:
|
||||
if method == gcc.EncryptionMethod.ENCRYPTION_FLAG_40BIT:
|
||||
return gen40bits(macKey128), gen40bits(initialFirstKey128), gen40bits(initialSecondKey128)
|
||||
|
||||
elif method == gcc.Encryption.ENCRYPTION_FLAG_56BIT:
|
||||
elif method == gcc.EncryptionMethod.ENCRYPTION_FLAG_56BIT:
|
||||
return gen56bits(macKey128), gen56bits(initialFirstKey128), gen56bits(initialSecondKey128)
|
||||
|
||||
elif method == gcc.Encryption.ENCRYPTION_FLAG_128BIT:
|
||||
elif method == gcc.EncryptionMethod.ENCRYPTION_FLAG_128BIT:
|
||||
return macKey128, initialFirstKey128, initialSecondKey128
|
||||
|
||||
raise InvalidExpectedDataException("Bad encryption method")
|
||||
@@ -255,28 +255,17 @@ def updateKey(initialKey, currentKey, method):
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240792.aspx
|
||||
"""
|
||||
#generate valid key
|
||||
if method == gcc.Encryption.ENCRYPTION_FLAG_40BIT:
|
||||
if method == gcc.EncryptionMethod.ENCRYPTION_FLAG_40BIT:
|
||||
tempKey128 = tempKey(initialKey[:8], currentKey[:8])
|
||||
return gen40bits(rc4.crypt(rc4.RC4Key(tempKey128[:8]), tempKey128[:8]))
|
||||
|
||||
elif method == gcc.Encryption.ENCRYPTION_FLAG_56BIT:
|
||||
elif method == gcc.EncryptionMethod.ENCRYPTION_FLAG_56BIT:
|
||||
tempKey128 = tempKey(initialKey[:8], currentKey[:8])
|
||||
return gen56bits(rc4.crypt(rc4.RC4Key(tempKey128[:8]), tempKey128[:8]))
|
||||
|
||||
elif method == gcc.Encryption.ENCRYPTION_FLAG_128BIT:
|
||||
elif method == gcc.EncryptionMethod.ENCRYPTION_FLAG_128BIT:
|
||||
tempKey128 = tempKey(initialKey, currentKey)
|
||||
return rc4.crypt(rc4.RC4Key(tempKey128), tempKey128)
|
||||
|
||||
def bin2bn(b):
|
||||
"""
|
||||
@summary: convert binary string to bignum
|
||||
@param b: {str} binary string
|
||||
@return: {long} bignum
|
||||
"""
|
||||
l = 0L
|
||||
for ch in b:
|
||||
l = (l<<8) | ord(ch)
|
||||
return l
|
||||
|
||||
class ClientSecurityExchangePDU(CompositeType):
|
||||
"""
|
||||
@@ -332,7 +321,7 @@ class RDPExtendedInfo(CompositeType):
|
||||
self.clientSessionId = UInt32Le()
|
||||
self.performanceFlags = UInt32Le()
|
||||
|
||||
class SecLayer(LayerAutomata, IStreamSender, tpkt.IFastPathListener, tpkt.IFastPathSender):
|
||||
class SecLayer(LayerAutomata, IStreamSender, tpkt.IFastPathListener, tpkt.IFastPathSender, mcs.IGCCConfig):
|
||||
"""
|
||||
@summary: Standard RDP security layer
|
||||
This layer is Transparent as possible for upper layer
|
||||
@@ -347,7 +336,7 @@ class SecLayer(LayerAutomata, IStreamSender, tpkt.IFastPathListener, tpkt.IFastP
|
||||
self._fastPathPresentation = None
|
||||
|
||||
#credentials
|
||||
self._info = RDPInfo(extendedInfoConditional = lambda:(self._transport.getGCCServerSettings().SC_CORE.rdpVersion.value == gcc.Version.RDP_VERSION_5_PLUS))
|
||||
self._info = RDPInfo(extendedInfoConditional = lambda:(self.getGCCServerSettings().SC_CORE.rdpVersion.value == gcc.Version.RDP_VERSION_5_PLUS))
|
||||
|
||||
#True if classic encryption is enable
|
||||
self._enableEncryption = False
|
||||
@@ -378,7 +367,7 @@ class SecLayer(LayerAutomata, IStreamSender, tpkt.IFastPathListener, tpkt.IFastP
|
||||
if self._nbDecryptedPacket == 4096:
|
||||
log.info("update decrypt key")
|
||||
self._currentDecrytKey = updateKey( self._initialDecrytKey, self._currentDecrytKey,
|
||||
self._transport.getGCCServerSettings().SC_SECURITY.encryptionMethod.value)
|
||||
self.getGCCServerSettings().SC_SECURITY.encryptionMethod.value)
|
||||
self._decryptRc4 = rc4.RC4Key(self._currentDecrytKey)
|
||||
self._nbDecryptedPacket = 0
|
||||
|
||||
@@ -405,7 +394,7 @@ class SecLayer(LayerAutomata, IStreamSender, tpkt.IFastPathListener, tpkt.IFastP
|
||||
if self._nbEncryptedPacket == 4096:
|
||||
log.info("update encrypt key")
|
||||
self._currentEncryptKey = updateKey( self._initialEncryptKey, self._currentEncryptKey,
|
||||
self._transport.getGCCServerSettings().SC_SECURITY.encryptionMethod.value)
|
||||
self.getGCCServerSettings().SC_SECURITY.encryptionMethod.value)
|
||||
self._encryptRc4 = rc4.RC4Key(self._currentEncryptKey)
|
||||
self._nbEncryptedPacket = 0
|
||||
|
||||
@@ -491,6 +480,34 @@ class SecLayer(LayerAutomata, IStreamSender, tpkt.IFastPathListener, tpkt.IFastP
|
||||
@param fastPathSender: {tpkt.FastPathSender}
|
||||
"""
|
||||
self._fastPathTransport = fastPathSender
|
||||
|
||||
def getUserId(self):
|
||||
"""
|
||||
@return: {integer} mcs user id
|
||||
@see: mcs.IGCCConfig
|
||||
"""
|
||||
return self._transport.getUserId()
|
||||
|
||||
def getChannelId(self):
|
||||
"""
|
||||
@return: {integer} return channel id of proxy
|
||||
@see: mcs.IGCCConfig
|
||||
"""
|
||||
return self._transport.getChannelId()
|
||||
|
||||
def getGCCClientSettings(self):
|
||||
"""
|
||||
@return: {gcc.Settings} mcs layer gcc client settings
|
||||
@see: mcs.IGCCConfig
|
||||
"""
|
||||
return self._transport.getGCCClientSettings()
|
||||
|
||||
def getGCCServerSettings(self):
|
||||
"""
|
||||
@return: {gcc.Settings} mcs layer gcc server settings
|
||||
@see: mcs.IGCCConfig
|
||||
"""
|
||||
return self._transport.getGCCServerSettings()
|
||||
|
||||
class Client(SecLayer):
|
||||
"""
|
||||
@@ -502,41 +519,20 @@ class Client(SecLayer):
|
||||
|
||||
def connect(self):
|
||||
"""
|
||||
@summary: send client random
|
||||
@summary: send client random if needed and send info packet
|
||||
"""
|
||||
|
||||
self._enableEncryption = self._transport.getGCCClientSettings().CS_CORE.serverSelectedProtocol == 0
|
||||
self._enableEncryption = self.getGCCClientSettings().CS_CORE.serverSelectedProtocol == 0
|
||||
|
||||
if self._enableEncryption:
|
||||
#generate client random
|
||||
clientRandom = rsa.randnum.read_random_bits(256)
|
||||
self._macKey, self._initialDecrytKey, self._initialEncryptKey = generateKeys( clientRandom,
|
||||
self._transport.getGCCServerSettings().SC_SECURITY.serverRandom.value,
|
||||
self._transport.getGCCServerSettings().SC_SECURITY.encryptionMethod.value)
|
||||
#initialize keys
|
||||
self._currentDecrytKey = self._initialDecrytKey
|
||||
self._currentEncryptKey = self._initialEncryptKey
|
||||
self._decryptRc4 = rc4.RC4Key(self._currentDecrytKey)
|
||||
self._encryptRc4 = rc4.RC4Key(self._currentEncryptKey)
|
||||
|
||||
#send client random encrypted with
|
||||
certificate = self._transport.getGCCServerSettings().SC_SECURITY.serverCertificate.certData._value
|
||||
if isinstance(certificate, gcc.ProprietaryServerCertificate):
|
||||
modulus = bin2bn(certificate.PublicKeyBlob.modulus.value[::-1])
|
||||
publicExponent = certificate.PublicKeyBlob.pubExp.value
|
||||
elif isinstance(certificate, gcc.X509CertificateChain):
|
||||
modulus, publicExponent = x509.extractRSAKey(x509.load(certificate.CertBlobArray[-1].abCert.value))
|
||||
else:
|
||||
raise InvalidExpectedDataException("unknown certificate type")
|
||||
|
||||
#reverse because bignum in little endian
|
||||
serverPublicKey = rsa.PublicKey(modulus, publicExponent)
|
||||
|
||||
message = ClientSecurityExchangePDU()
|
||||
#reverse because bignum in little endian
|
||||
message.encryptedClientRandom.value = rsa.encrypt(clientRandom[::-1], serverPublicKey)[::-1]
|
||||
self.sendFlagged(SecurityFlag.SEC_EXCHANGE_PKT, message)
|
||||
self.sendClientRandom()
|
||||
|
||||
self.sendInfoPkt()
|
||||
|
||||
def sendInfoPkt(self):
|
||||
"""
|
||||
@summary: send information packet (with credentials)
|
||||
next state -> recvLicenceInfo
|
||||
"""
|
||||
secFlag = SecurityFlag.SEC_INFO_PKT
|
||||
if self._enableEncryption:
|
||||
secFlag |= SecurityFlag.SEC_ENCRYPT
|
||||
@@ -544,6 +540,29 @@ class Client(SecLayer):
|
||||
|
||||
self.setNextState(self.recvLicenceInfo)
|
||||
|
||||
def sendClientRandom(self):
|
||||
"""
|
||||
@summary: generate and send client random and init session keys
|
||||
"""
|
||||
#generate client random
|
||||
clientRandom = rsa.randnum.read_random_bits(256)
|
||||
self._macKey, self._initialDecrytKey, self._initialEncryptKey = generateKeys( clientRandom,
|
||||
self.getGCCServerSettings().SC_SECURITY.serverRandom.value,
|
||||
self.getGCCServerSettings().SC_SECURITY.encryptionMethod.value)
|
||||
#initialize keys
|
||||
self._currentDecrytKey = self._initialDecrytKey
|
||||
self._currentEncryptKey = self._initialEncryptKey
|
||||
self._decryptRc4 = rc4.RC4Key(self._currentDecrytKey)
|
||||
self._encryptRc4 = rc4.RC4Key(self._currentEncryptKey)
|
||||
|
||||
#send client random encrypted with
|
||||
modulus, publicExponent = self.getGCCServerSettings().SC_SECURITY.serverCertificate.certData.getPublicKey()
|
||||
serverPublicKey = rsa.PublicKey(modulus, publicExponent)
|
||||
message = ClientSecurityExchangePDU()
|
||||
#reverse because bignum in little endian
|
||||
message.encryptedClientRandom.value = rsa.encrypt(clientRandom[::-1], serverPublicKey)[::-1]
|
||||
self.sendFlagged(SecurityFlag.SEC_EXCHANGE_PKT, message)
|
||||
|
||||
def recvLicenceInfo(self, s):
|
||||
"""
|
||||
@summary: Read license info packet and check if is a valid client info
|
||||
@@ -574,7 +593,20 @@ class Server(SecLayer):
|
||||
"""
|
||||
@summary: init automata to wait info packet
|
||||
"""
|
||||
self.setNextState(self.recvInfoPkt)
|
||||
self._enableEncryption = self.getGCCClientSettings().CS_CORE.serverSelectedProtocol == 0
|
||||
if self._enableEncryption:
|
||||
self.setNextState(self.recvClientRandom)
|
||||
else:
|
||||
self.setNextState(self.recvInfoPkt)
|
||||
|
||||
def recvClientRandom(self, s):
|
||||
"""
|
||||
@summary: receive client random and generate session keys
|
||||
@param s: {Stream}
|
||||
"""
|
||||
message = ClientSecurityExchangePDU()
|
||||
s.readType(message)
|
||||
|
||||
|
||||
def recvInfoPkt(self, s):
|
||||
"""
|
||||
|
||||
@@ -76,8 +76,8 @@ class IFastPathSender(object):
|
||||
def sendFastPath(self, secFlag, fastPathS):
|
||||
"""
|
||||
@summary: Send fastPathS Type as fast path packet
|
||||
@param secFlag: {SecFlags}
|
||||
@param fastPathS: type transform to stream and send as fastpath
|
||||
@param secFlag: {integer} Security flag for fastpath packet
|
||||
@param fastPathS: {Type | Tuple} type transform to stream and send as fastpath
|
||||
"""
|
||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "sendFastPath", "IFastPathSender"))
|
||||
|
||||
@@ -103,7 +103,7 @@ class TPKT(RawLayer, IFastPathSender):
|
||||
"""
|
||||
def __init__(self, presentation):
|
||||
"""
|
||||
@param presentation: presentation layer, in RDP case is x224 layer
|
||||
@param presentation: {Layer} presentation layer, in RDP case is x224 layer
|
||||
"""
|
||||
RawLayer.__init__(self, presentation)
|
||||
#length may be coded on more than 1 bytes
|
||||
@@ -133,8 +133,8 @@ class TPKT(RawLayer, IFastPathSender):
|
||||
|
||||
def readHeader(self, data):
|
||||
"""
|
||||
Read header of TPKT packet
|
||||
@param data: Stream received from twisted layer
|
||||
@summary: Read header of TPKT packet
|
||||
@param data: {Stream} received from twisted layer
|
||||
"""
|
||||
#first read packet version
|
||||
version = UInt8()
|
||||
@@ -158,8 +158,8 @@ class TPKT(RawLayer, IFastPathSender):
|
||||
|
||||
def readExtendedHeader(self, data):
|
||||
"""
|
||||
Header may be on 4 bytes
|
||||
@param data: Stream from twisted layer
|
||||
@summary: Header may be on 4 bytes
|
||||
@param data: {Stream} from twisted layer
|
||||
"""
|
||||
#next state is read data
|
||||
size = UInt16Be()
|
||||
@@ -168,8 +168,8 @@ class TPKT(RawLayer, IFastPathSender):
|
||||
|
||||
def readExtendedFastPathHeader(self, data):
|
||||
"""
|
||||
Fast path header may be on 1 byte more
|
||||
@param data: Stream from twisted layer
|
||||
@summary: Fast path header may be on 1 byte more
|
||||
@param data: {Stream} from twisted layer
|
||||
"""
|
||||
leftPart = UInt8()
|
||||
data.readType(leftPart)
|
||||
@@ -180,16 +180,16 @@ class TPKT(RawLayer, IFastPathSender):
|
||||
|
||||
def readFastPath(self, data):
|
||||
"""
|
||||
Fast path data
|
||||
@param data: Stream from twisted layer
|
||||
@summary: Fast path data
|
||||
@param data: {Stream} from twisted layer
|
||||
"""
|
||||
self._fastPathListener.recvFastPath(self._secFlag, data)
|
||||
self.expect(2, self.readHeader)
|
||||
|
||||
def readData(self, data):
|
||||
"""
|
||||
Read classic TPKT packet, last state in tpkt automata
|
||||
@param data: Stream with correct size
|
||||
@summary: Read classic TPKT packet, last state in tpkt automata
|
||||
@param data: {Stream} with correct size
|
||||
"""
|
||||
#next state is pass to
|
||||
self._presentation.recv(data)
|
||||
@@ -197,14 +197,14 @@ class TPKT(RawLayer, IFastPathSender):
|
||||
|
||||
def send(self, message):
|
||||
"""
|
||||
Send encompassed data
|
||||
@param message: network.Type message to send
|
||||
@summary: Send encompassed data
|
||||
@param message: {network.Type} message to send
|
||||
"""
|
||||
RawLayer.send(self, (UInt8(Action.FASTPATH_ACTION_X224), UInt8(0), UInt16Be(sizeof(message) + 4), message))
|
||||
|
||||
def sendFastPath(self, secFlag, fastPathS):
|
||||
"""
|
||||
@param fastPathS: type transform to stream and send as fastpath
|
||||
@param secFlag: {SecFlags}
|
||||
@param secFlag: {integer} Security flag for fastpath packet
|
||||
"""
|
||||
RawLayer.send(self, (UInt8(Action.FASTPATH_ACTION_FASTPATH | secFlag), UInt16Be((sizeof(fastPathS) + 3) | 0x8000), fastPathS))
|
||||
@@ -130,9 +130,8 @@ class X224Layer(LayerAutomata, IStreamSender):
|
||||
@param presentation: upper layer, MCS layer in RDP case
|
||||
"""
|
||||
LayerAutomata.__init__(self, presentation)
|
||||
#default selectedProtocol is SSl
|
||||
#client requested selectedProtocol
|
||||
self._requestedProtocol = Protocols.PROTOCOL_RDP
|
||||
self._requestedProtocol = Protocols.PROTOCOL_RDP | Protocols.PROTOCOL_SSL
|
||||
#server selected selectedProtocol
|
||||
self._selectedProtocol = Protocols.PROTOCOL_SSL
|
||||
|
||||
|
||||
Reference in New Issue
Block a user