From 16b9aba7a536f0e459cc5fdc56c2011fd8e1dbd5 Mon Sep 17 00:00:00 2001 From: citronneur Date: Sun, 20 Jul 2014 21:06:29 +0200 Subject: [PATCH] finish MCS server side begin pdu and lic --- rdpy/protocol/rdp/lic.py | 10 ++++++ rdpy/protocol/rdp/mcs.py | 10 ++++-- rdpy/protocol/rdp/pdu.py | 78 +++++++++++++++++++++++++++++----------- 3 files changed, 74 insertions(+), 24 deletions(-) diff --git a/rdpy/protocol/rdp/lic.py b/rdpy/protocol/rdp/lic.py index c882437..2c39032 100644 --- a/rdpy/protocol/rdp/lic.py +++ b/rdpy/protocol/rdp/lic.py @@ -204,6 +204,16 @@ class LicPacket(CompositeType): self.licensingMessage = message +def createValidClientLicensingErrorMessage(): + """ + Create a licensing error message that accept client + server automata message + """ + message = LicensingErrorMessage() + message.dwErrorCode.value = ErrorCode.STATUS_VALID_CLIENT + message.dwStateTransition.value = StateTransition.ST_NO_TRANSITION + return LicPacket(message = message) + def createNewLicenseRequest(serverLicenseRequest): """ Create new license request in response to server license request diff --git a/rdpy/protocol/rdp/mcs.py b/rdpy/protocol/rdp/mcs.py index b84f9ee..b3922c2 100644 --- a/rdpy/protocol/rdp/mcs.py +++ b/rdpy/protocol/rdp/mcs.py @@ -450,9 +450,13 @@ class MCS(LayerAutomata): log.info("MCS DISCONNECT_PROVIDER_ULTIMATUM") self._transport.close() return - - elif not self.readMCSPDUHeader(opcode.value, DomainMCSPDU.SEND_DATA_INDICATION): - raise InvalidExpectedDataException("Invalid expected MCS opcode") + + #client case + elif self._mode == LayerMode.CLIENT and not self.readMCSPDUHeader(opcode.value, DomainMCSPDU.SEND_DATA_INDICATION): + raise InvalidExpectedDataException("Invalid expected MCS opcode for server to client communication") + + elif self._mode == LayerMode.SERVER and not self.readMCSPDUHeader(opcode.value, DomainMCSPDU.SEND_DATA_REQUEST): + raise InvalidExpectedDataException("Invalid expected MCS opcode for client to server communication") #server user id per.readInteger16(data, Channel.MCS_USERCHANNEL_BASE) diff --git a/rdpy/protocol/rdp/pdu.py b/rdpy/protocol/rdp/pdu.py index b2257a6..28f48b5 100644 --- a/rdpy/protocol/rdp/pdu.py +++ b/rdpy/protocol/rdp/pdu.py @@ -491,13 +491,13 @@ class RDPInfo(CompositeType): self.cbAlternateShell = UInt16Le(lambda:sizeof(self.alternateShell) - 2) self.cbWorkingDir = UInt16Le(lambda:sizeof(self.workingDir) - 2) #microsoft domain - self.domain = String(readLen = UInt16Le(lambda:self.cbDomain.value - 2), unicode = True) - self.userName = String(readLen = UInt16Le(lambda:self.cbUserName.value - 2), unicode = True) - self.password = String(readLen = UInt16Le(lambda:self.cbPassword.value - 2), unicode = True) + self.domain = String(readLen = UInt16Le(lambda:self.cbDomain.value + 2), unicode = True) + self.userName = String(readLen = UInt16Le(lambda:self.cbUserName.value + 2), unicode = True) + self.password = String(readLen = UInt16Le(lambda:self.cbPassword.value + 2), unicode = True) #shell execute at start of session - self.alternateShell = String(readLen = UInt16Le(lambda:self.cbAlternateShell.value - 2), unicode = True) + self.alternateShell = String(readLen = UInt16Le(lambda:self.cbAlternateShell.value + 2), unicode = True) #working directory for session - self.workingDir = String(readLen = UInt16Le(lambda:self.cbWorkingDir.value - 2), unicode = True) + self.workingDir = String(readLen = UInt16Le(lambda:self.cbWorkingDir.value + 2), unicode = True) self.extendedInfo = RDPExtendedInfo(conditional = extendedInfoConditional) class RDPExtendedInfo(CompositeType): @@ -1065,16 +1065,19 @@ class PDULayer(LayerAutomata, tpkt.FastPathListener): caps.CapsType.CAPSTYPE_SOUND : caps.Capability(caps.CapsType.CAPSTYPE_SOUND, caps.SoundCapability()) } #share id between client and server - self._shareId = 0 + self._shareId = 0x103EA def connect(self): """ Connect event in client mode send logon info Next state receive license PDU - """ - self.sendInfoPkt() - #next state is license info PDU - self.setNextState(self.recvLicenceInfo) + """ + if self._mode == LayerMode.CLIENT: + self.sendInfoPkt() + #next state is license info PDU + self.setNextState(self.recvLicenceInfo) + else: + self.setNextState(self.recvInfoPkt) def close(self): """ @@ -1082,24 +1085,35 @@ class PDULayer(LayerAutomata, tpkt.FastPathListener): """ self.sendDataPDU(ShutdownRequestPDU()) - def sendInfoPkt(self): + def recvInfoPkt(self, data): """ - Send a logon info packet + Receive info packet from client + Client credential + @param data: Stream """ - #always send extended info because rdpy only accept RDP version 5 and more - self._transport.send((UInt16Le(SecurityFlag.SEC_INFO_PKT), UInt16Le(), self._info)) + securityFlag = UInt16Le() + securityFlagHi = UInt16Le() + data.readType((securityFlag, securityFlagHi)) + + if not (securityFlag.value & SecurityFlag.SEC_INFO_PKT): + raise InvalidExpectedDataException("Waiting info packet") + + data.readType(self._info) + #next state send error license + self.sendLicensingErrorMessage() + self.sendDemandActivePDU() def recvLicenceInfo(self, data): """ Read license info packet and check if is a valid client info @param data: Stream """ - #license preambule + #packet preambule securityFlag = UInt16Le() securityFlagHi = UInt16Le() data.readType((securityFlag, securityFlagHi)) - if securityFlag.value & SecurityFlag.SEC_LICENSE_PKT != SecurityFlag.SEC_LICENSE_PKT: + if not (securityFlag.value & SecurityFlag.SEC_LICENSE_PKT): raise InvalidExpectedDataException("Waiting license packet") validClientPdu = lic.LicPacket() @@ -1134,6 +1148,9 @@ class PDULayer(LayerAutomata, tpkt.FastPathListener): self._serverCapabilities[cap.capabilitySetType] = cap self.sendConfirmActivePDU() + #send synchronize + self.sendClientFinalizeSynchronizePDU() + self.setNextState(self.recvServerSynchronizePDU) def recvServerSynchronizePDU(self, data): """ @@ -1197,7 +1214,6 @@ class PDULayer(LayerAutomata, tpkt.FastPathListener): #http://msdn.microsoft.com/en-us/library/cc240454.aspx self.setNextState(self.recvDemandActivePDU) - def recvFastPath(self, fastPathData): """ Implement FastPathListener interface @@ -1235,6 +1251,30 @@ class PDULayer(LayerAutomata, tpkt.FastPathListener): if updateDataPDU.updateType.value == UpdateType.UPDATETYPE_BITMAP: self._clientListener.onUpdate(updateDataPDU.updateData.rectangles._array) + def sendInfoPkt(self): + """ + Send a logon info packet + client automata message + """ + self._transport.send((UInt16Le(SecurityFlag.SEC_INFO_PKT), UInt16Le(), self._info)) + + def sendLicensingErrorMessage(self): + """ + Send a licensing error message + server automata message + """ + self._transport.send((UInt16Le(SecurityFlag.SEC_LICENSE_PKT), UInt16Le(), lic.createValidClientLicensingErrorMessage())) + + def sendDemandActivePDU(self): + """ + Send server capabilities + server automata PDU + """ + demandActivePDU = DemandActivePDU() + demandActivePDU.shareId.value = self._shareId + demandActivePDU.capabilitySets._array = self._serverCapabilities.values() + self.sendPDU(demandActivePDU) + def sendPDU(self, pduMessage): """ Send a PDU message to transport layer @@ -1281,8 +1321,6 @@ class PDULayer(LayerAutomata, tpkt.FastPathListener): confirmActivePDU.shareId.value = self._shareId confirmActivePDU.capabilitySets._array = self._clientCapabilities.values() self.sendPDU(confirmActivePDU) - #send synchronize - self.sendClientFinalizeSynchronizePDU() def sendClientFinalizeSynchronizePDU(self): """ @@ -1305,8 +1343,6 @@ class PDULayer(LayerAutomata, tpkt.FastPathListener): fontListPDU = FontListDataPDU() self.sendDataPDU(fontListPDU) - self.setNextState(self.recvServerSynchronizePDU) - def sendInputEvents(self, pointerEvents): """ send client input events