From 01362e8994bcb30b050e43e81bda8cad1bba93c0 Mon Sep 17 00:00:00 2001 From: citronneur Date: Mon, 21 Jul 2014 22:38:42 +0200 Subject: [PATCH] finish server side on pdu layer --- rdpy/network/type.py | 6 +-- rdpy/protocol/rdp/lic.py | 13 ++++-- rdpy/protocol/rdp/mcs.py | 3 +- rdpy/protocol/rdp/pdu.py | 98 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 113 insertions(+), 7 deletions(-) diff --git a/rdpy/network/type.py b/rdpy/network/type.py index 40d91cd..259f531 100644 --- a/rdpy/network/type.py +++ b/rdpy/network/type.py @@ -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: - log.warning("still have correct data in packet %s, read it as padding"%self.__class__) + log.debug("still have correct data in packet %s, read it as padding"%self.__class__) s.read(self._readLen.value - readLen) def __write__(self, s): @@ -668,7 +668,7 @@ class String(Type, CallableValue): ''' String network type ''' - def __init__(self, value = "", readLen = UInt32Le(), conditional = lambda:True, optional = False, constant = False, unicode = False): + def __init__(self, value = "", readLen = None, conditional = lambda:True, optional = False, constant = False, unicode = False): ''' constructor with new string @param value: python string use for inner value @@ -722,7 +722,7 @@ class String(Type, CallableValue): else read the length of inner string @param s: Stream """ - if self._readLen.value == 0: + if self._readLen is None: self.value = s.getvalue() else: self.value = s.read(self._readLen.value) diff --git a/rdpy/protocol/rdp/lic.py b/rdpy/protocol/rdp/lic.py index 2c39032..adf6094 100644 --- a/rdpy/protocol/rdp/lic.py +++ b/rdpy/protocol/rdp/lic.py @@ -79,6 +79,13 @@ class BinaryBlobType(object): BB_SCOPE_BLOB = 0x000E BB_CLIENT_USER_NAME_BLOB = 0x000F BB_CLIENT_MACHINE_NAME_BLOB = 0x0010 + +class Preambule(object): + """ + Preambule version + """ + PREAMBLE_VERSION_2_0 = 0x2 + PREAMBLE_VERSION_3_0 = 0x3 class LicenseBinaryBlob(CompositeType): """ @@ -98,8 +105,8 @@ class LicensingErrorMessage(CompositeType): """ _MESSAGE_TYPE_ = MessageType.ERROR_ALERT - def __init__(self, conditional = lambda:True): - CompositeType.__init__(self, conditional = conditional) + def __init__(self): + CompositeType.__init__(self) self.dwErrorCode = UInt32Le() self.dwStateTransition = UInt32Le() self.blob = LicenseBinaryBlob(BinaryBlobType.BB_ERROR_BLOB) @@ -183,7 +190,7 @@ class LicPacket(CompositeType): CompositeType.__init__(self) #preambule self.bMsgtype = UInt8(lambda:self.licensingMessage.__class__._MESSAGE_TYPE_) - self.flag = UInt8() + self.flag = UInt8(Preambule.PREAMBLE_VERSION_3_0) self.wMsgSize = UInt16Le(lambda: sizeof(self)) def LicensingMessageFactory(): diff --git a/rdpy/protocol/rdp/mcs.py b/rdpy/protocol/rdp/mcs.py index b3922c2..0eb3f34 100644 --- a/rdpy/protocol/rdp/mcs.py +++ b/rdpy/protocol/rdp/mcs.py @@ -278,7 +278,8 @@ class MCS(LayerAutomata): @param channelId: Channel use to send @param data: message to send """ - self._transport.send((self.writeMCSPDUHeader(UInt8(DomainMCSPDU.SEND_DATA_REQUEST)), + opcode = DomainMCSPDU.SEND_DATA_REQUEST if self._mode == LayerMode.CLIENT else DomainMCSPDU.SEND_DATA_INDICATION + self._transport.send((self.writeMCSPDUHeader(UInt8(opcode)), per.writeInteger16(self._userId, Channel.MCS_USERCHANNEL_BASE), per.writeInteger16(channelId), UInt8(0x70), diff --git a/rdpy/protocol/rdp/pdu.py b/rdpy/protocol/rdp/pdu.py index 28f48b5..1830f00 100644 --- a/rdpy/protocol/rdp/pdu.py +++ b/rdpy/protocol/rdp/pdu.py @@ -1102,6 +1102,7 @@ class PDULayer(LayerAutomata, tpkt.FastPathListener): #next state send error license self.sendLicensingErrorMessage() self.sendDemandActivePDU() + self.setNextState(self.recvConfirmActivePDU) def recvLicenceInfo(self, data): """ @@ -1152,6 +1153,23 @@ class PDULayer(LayerAutomata, tpkt.FastPathListener): self.sendClientFinalizeSynchronizePDU() self.setNextState(self.recvServerSynchronizePDU) + def recvConfirmActivePDU(self, data): + """ + Receive confirm active PDU from client + Capabilities exchange + @param data: Stream + """ + pdu = PDU() + data.readType(pdu) + + if pdu.shareControlHeader.pduType.value != PDUType.PDUTYPE_CONFIRMACTIVEPDU: + raise InvalidExpectedDataException("Expected Confirm Active PDU from client") + + for cap in pdu.pduMessage.capabilitySets._array: + self._clientCapabilities[cap.capabilitySetType] = cap + + self.setNextState(self.recvClientSynchronizePDU) + def recvServerSynchronizePDU(self, data): """ Receive from server @@ -1199,6 +1217,53 @@ class PDULayer(LayerAutomata, tpkt.FastPathListener): self._clientListener.onReady() self.setNextState(self.recvPDU) + def recvClientSynchronizePDU(self, data): + """ + Receive from client + @param data: Stream from transport layer + """ + pdu = PDU() + data.readType(pdu) + if pdu.shareControlHeader.pduType.value != PDUType.PDUTYPE_DATAPDU or pdu.pduMessage.shareDataHeader.pduType2.value != PDUType2.PDUTYPE2_SYNCHRONIZE: + raise InvalidExpectedDataException("Error in PDU layer automata : expected synchronizePDU") + self.setNextState(self.recvClientControlCooperatePDU) + + def recvClientControlCooperatePDU(self, data): + """ + Receive control cooperate PDU from client + @param data: Stream from transport layer + """ + pdu = PDU() + data.readType(pdu) + if pdu.shareControlHeader.pduType.value != PDUType.PDUTYPE_DATAPDU or pdu.pduMessage.shareDataHeader.pduType2.value != PDUType2.PDUTYPE2_CONTROL or pdu.pduMessage.pduData.action.value != Action.CTRLACTION_COOPERATE: + raise InvalidExpectedDataException("Error in PDU layer automata : expected controlCooperatePDU") + self.setNextState(self.recvClientControlRequestPDU) + + def recvClientControlRequestPDU(self, data): + """ + Receive last control PDU the request control PDU from client + @param data: Stream from transport layer + """ + pdu = PDU() + data.readType(pdu) + if pdu.shareControlHeader.pduType.value != PDUType.PDUTYPE_DATAPDU or pdu.pduMessage.shareDataHeader.pduType2.value != PDUType2.PDUTYPE2_CONTROL or pdu.pduMessage.pduData.action.value != Action.CTRLACTION_REQUEST_CONTROL: + raise InvalidExpectedDataException("Error in PDU layer automata : expected controlGrantedPDU") + self.setNextState(self.recvClientFontListPDU) + + def recvClientFontListPDU(self, data): + """ + Last synchronize packet from client to server + @param data: Stream from transport layer + """ + pdu = PDU() + data.readType(pdu) + if pdu.shareControlHeader.pduType.value != PDUType.PDUTYPE_DATAPDU or pdu.pduMessage.shareDataHeader.pduType2.value != PDUType2.PDUTYPE2_FONTLIST: + raise InvalidExpectedDataException("Error in PDU layer automata : expected fontMapPDU") + + #finalize server + self.sendServerFinalizeSynchronizePDU() + self.setNextState(self.recvPDU) + def recvPDU(self, data): """ Main receive function after connection sequence @@ -1270,6 +1335,18 @@ class PDULayer(LayerAutomata, tpkt.FastPathListener): Send server capabilities server automata PDU """ + #init general capability + generalCapability = self._serverCapabilities[caps.CapsType.CAPSTYPE_GENERAL].capability + generalCapability.osMajorType.value = caps.MajorType.OSMAJORTYPE_WINDOWS + generalCapability.osMinorType.value = caps.MinorType.OSMINORTYPE_WINDOWS_NT + generalCapability.extraFlags.value = caps.GeneralExtraFlag.LONG_CREDENTIALS_SUPPORTED | caps.GeneralExtraFlag.NO_BITMAP_COMPRESSION_HDR | caps.GeneralExtraFlag.FASTPATH_OUTPUT_SUPPORTED + + #init bitmap capability + bitmapCapability = self._serverCapabilities[caps.CapsType.CAPSTYPE_BITMAP].capability + bitmapCapability.preferredBitsPerPixel.value = 16 + bitmapCapability.desktopWidth.value = 800 + bitmapCapability.desktopHeight.value = 600 + demandActivePDU = DemandActivePDU() demandActivePDU.shareId.value = self._shareId demandActivePDU.capabilitySets._array = self._serverCapabilities.values() @@ -1343,6 +1420,27 @@ class PDULayer(LayerAutomata, tpkt.FastPathListener): fontListPDU = FontListDataPDU() self.sendDataPDU(fontListPDU) + def sendServerFinalizeSynchronizePDU(self): + """ + Send last synchronize packet from server to client + """ + synchronizePDU = SynchronizeDataPDU(self._transport.getChannelId()) + self.sendDataPDU(synchronizePDU) + + #ask for cooperation + controlCooperatePDU = ControlDataPDU(Action.CTRLACTION_COOPERATE) + self.sendDataPDU(controlCooperatePDU) + + #request control + controlRequestPDU = ControlDataPDU(Action.CTRLACTION_GRANTED_CONTROL) + self.sendDataPDU(controlRequestPDU) + + #TODO persistent key list http://msdn.microsoft.com/en-us/library/cc240494.aspx + + #deprecated font list pdu + fontMapPDU = FontMapDataPDU() + self.sendDataPDU(fontMapPDU) + def sendInputEvents(self, pointerEvents): """ send client input events