diff --git a/bin/rdpy-rdpclient.py b/bin/rdpy-rdpclient.py index 33fe370..e1e7adb 100755 --- a/bin/rdpy-rdpclient.py +++ b/bin/rdpy-rdpclient.py @@ -21,261 +21,23 @@ example of use rdpy as rdp client """ -import sys, os, getopt, socket +import sys +import asyncio -from PyQt5 import QtWidgets -from rdpy.ui.qt4 import RDPClientQt -from rdpy.model.error import RDPSecurityNegoFail -from rdpy.model import rss -from rdpy.core import rdp +from rdpy.core import tpkt, x224 +from rdpy.model.type import UInt8 -import rdpy.model.log as log -log._LOG_LEVEL = log.Level.INFO - - -class RDPClientQtRecorder(RDPClientQt): - """ - @summary: Widget with record session - """ - def __init__(self, controller, width, height, rssRecorder): - """ - @param controller: {RDPClientController} RDP controller - @param width: {int} width of widget - @param height: {int} height of widget - @param rssRecorder: {rss.FileRecorder} - """ - RDPClientQt.__init__(self, controller, width, height) - self._screensize = width, height - self._rssRecorder = rssRecorder - - def onUpdate(self, destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, isCompress, data): - """ - @summary: Notify bitmap update - @param destLeft: {int} xmin position - @param destTop: {int} ymin position - @param destRight: {int} xmax position because RDP can send bitmap with padding - @param destBottom: {int} ymax position because RDP can send bitmap with padding - @param width: {int} width of bitmap - @param height: {int} height of bitmap - @param bitsPerPixel: {int} number of bit per pixel - @param isCompress: {bool} use RLE compression - @param data: {str} bitmap data - """ - #record update - self._rssRecorder.update(destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, rss.UpdateFormat.BMP if isCompress else rss.UpdateFormat.RAW, data) - RDPClientQt.onUpdate(self, destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, isCompress, data) - - def onReady(self): - """ - @summary: Call when stack is ready - """ - self._rssRecorder.screen(self._screensize[0], self._screensize[1], self._controller.getColorDepth()) - RDPClientQt.onReady(self) - - def onClose(self): - """ - @summary: Call when stack is close - """ - self._rssRecorder.close() - RDPClientQt.onClose(self) - - def closeEvent(self, e): - """ - @summary: Convert Qt close widget event into close stack event - @param e: QCloseEvent - """ - self._rssRecorder.close() - RDPClientQt.closeEvent(self, e) - - -class RDPClientQtFactory(rdp.ClientFactory): - """ - @summary: Factory create a RDP GUI client - """ - def __init__(self, width, height, username, password, domain, fullscreen, keyboardLayout, optimized, security, recodedPath): - """ - @param width: {integer} width of client - @param heigth: {integer} heigth of client - @param username: {str} username present to the server - @param password: {str} password present to the server - @param domain: {str} microsoft domain - @param fullscreen: {bool} show widget in fullscreen mode - @param keyboardLayout: {str} (fr|en) keyboard layout - @param optimized: {bool} enable optimized session orders - @param security: {str} (ssl | rdp | nego) - @param recodedPath: {str | None} Rss file Path - """ - self._width = width - self._height = height - self._username = username - self._passwod = password - self._domain = domain - self._fullscreen = fullscreen - self._keyboardLayout = keyboardLayout - self._optimized = optimized - self._nego = security == "nego" - self._recodedPath = recodedPath - if self._nego: - #compute start nego nla need credentials - if username != "" and password != "": - self._security = rdp.SecurityLevel.RDP_LEVEL_NLA - else: - self._security = rdp.SecurityLevel.RDP_LEVEL_SSL - else: - self._security = security - self._w = None - - def buildObserver(self, controller, addr): - """ - @summary: Build RFB observer - We use a RDPClientQt as RDP observer - @param controller: build factory and needed by observer - @param addr: destination address - @return: RDPClientQt - """ - #create client observer - if self._recodedPath is None: - self._client = RDPClientQt(controller, self._width, self._height) - else: - self._client = RDPClientQtRecorder(controller, self._width, self._height, rss.createRecorder(self._recodedPath)) - #create qt widget - self._w = self._client.getWidget() - self._w.setWindowTitle('rdpy-rdpclient') - if self._fullscreen: - self._w.showFullScreen() - else: - self._w.show() - - controller.setUsername(self._username) - controller.setPassword(self._passwod) - controller.setDomain(self._domain) - controller.setKeyboardLayout(self._keyboardLayout) - controller.setHostname(socket.gethostname()) - if self._optimized: - controller.setPerformanceSession() - controller.setSecurityLevel(self._security) - - return self._client - - def clientConnectionLost(self, connector, reason): - """ - @summary: Connection lost event - @param connector: twisted connector use for rdp connection (use reconnect to restart connection) - @param reason: str use to advertise reason of lost connection - """ - #try reconnect with basic RDP security - if reason.type == RDPSecurityNegoFail and self._nego: - #stop nego - log.info("due to security nego error back to standard RDP security layer") - self._nego = False - self._security = rdp.SecurityLevel.RDP_LEVEL_RDP - self._client._widget.hide() - connector.connect() - return - - log.info("Lost connection : %s"%reason) - reactor.stop() - app.exit() - - def clientConnectionFailed(self, connector, reason): - """ - @summary: Connection failed event - @param connector: twisted connector use for rdp connection (use reconnect to restart connection) - @param reason: str use to advertise reason of lost connection - """ - log.info("Connection failed : %s"%reason) - reactor.stop() - app.exit() - -def autoDetectKeyboardLayout(): - """ - @summary: try to auto detect keyboard layout - """ - try: - if os.name == 'posix': - from subprocess import check_output - result = check_output(["setxkbmap", "-print"]) - if 'azerty' in result: - return "fr" - elif os.name == 'nt': - import win32api, win32con, win32process - from ctypes import windll - w = windll.user32.GetForegroundWindow() - tid = windll.user32.GetWindowThreadProcessId(w, 0) - result = windll.user32.GetKeyboardLayout(tid) - log.info(result) - if result == 0x40c040c: - return "fr" - except Exception as e: - log.info("failed to auto detect keyboard layout " + str(e)) - pass - return "en" - -def help(): - print(""" - Usage: rdpy-rdpclient [options] ip[:port]" - \t-u: user name - \t-p: password - \t-d: domain - \t-w: width of screen [default : 1024] - \t-l: height of screen [default : 800] - \t-f: enable full screen mode [default : False] - \t-k: keyboard layout [en|fr] [default : en] - \t-o: optimized session (disable costly effect) [default : False] - \t-r: rss_filepath Recorded Session Scenario [default : None] - """) - if __name__ == '__main__': - - #default script argument - username = "" - password = "" - domain = "" - width = 1024 - height = 800 - fullscreen = False - optimized = False - recodedPath = None - keyboardLayout = autoDetectKeyboardLayout() - try: - opts, args = getopt.getopt(sys.argv[1:], "hfou:p:d:w:l:k:r:") - except getopt.GetoptError: - help() - for opt, arg in opts: - if opt == "-h": - help() - sys.exit() - elif opt == "-u": - username = arg - elif opt == "-p": - password = arg - elif opt == "-d": - domain = arg - elif opt == "-w": - width = int(arg) - elif opt == "-l": - height = int(arg) - elif opt == "-f": - fullscreen = True - elif opt == "-o": - optimized = True - elif opt == "-k": - keyboardLayout = arg - elif opt == "-r": - recodedPath = arg - - if ':' in args[0]: - ip, port = args[0].split(':') - else: - ip, port = args[0], "3389" - - #create application - app = QtWidgets.QApplication(sys.argv) - - if fullscreen: - width = QtWidgets.QDesktopWidget().screenGeometry().width() - height = QtWidgets.QDesktopWidget().screenGeometry().height() - - log.info("keyboard layout set to %s"%keyboardLayout) - sys.exit(app.exec_()) \ No newline at end of file + #sys.exit(app.exec_()) + + async def tcp_echo_client(message): + reader, writer = await asyncio.open_connection( + '127.0.0.1', 33389) + + x224_layer = await x224.connect(tpkt.Tpkt(reader, writer)) + await x224_layer.write(UInt8(8)) + await asyncio.sleep(1000) + print("foooooooooooooooooooo") + + asyncio.run(tcp_echo_client('Hello World!')) \ No newline at end of file diff --git a/rdpy/core/lic.py b/rdpy/core/lic.py index d67f6d2..1aca35a 100644 --- a/rdpy/core/lic.py +++ b/rdpy/core/lic.py @@ -272,7 +272,7 @@ class LicenseManager(object): @return true when license automata is finish """ licPacket = LicPacket() - s.readType(licPacket) + s.read_type(licPacket) #end of automata if licPacket.bMsgtype.value == MessageType.ERROR_ALERT and licPacket.licensingMessage.dwErrorCode.value == ErrorCode.STATUS_VALID_CLIENT and licPacket.licensingMessage.dwStateTransition.value == StateTransition.ST_NO_TRANSITION: @@ -308,7 +308,7 @@ class LicenseManager(object): else: s = Stream(licenseRequest.serverCertificate.blobData.value) serverCertificate = gcc.ServerCertificate() - s.readType(serverCertificate) + s.read_type(serverCertificate) #generate crypto values clientRandom = rsa.random(256) @@ -340,7 +340,7 @@ class LicenseManager(object): #generate hwid s = Stream() - s.writeType((UInt32Le(2), String(self._hostname + self._username + "\x00" * 16))) + s.write_type((UInt32Le(2), String(self._hostname + self._username + "\x00" * 16))) hwid = s.getvalue()[:20] message = ClientPLatformChallengeResponse() diff --git a/rdpy/core/nla/cssp.py b/rdpy/core/nla/cssp.py index f064142..b05fa15 100644 --- a/rdpy/core/nla/cssp.py +++ b/rdpy/core/nla/cssp.py @@ -27,6 +27,7 @@ import pyasn1.codec.der.encoder as der_encoder import pyasn1.codec.der.decoder as der_decoder import pyasn1.codec.ber.encoder as ber_encoder +from rdpy.core.nla import sspi from rdpy.model.type import Stream from rdpy.security import x509 from rdpy.model import error @@ -113,21 +114,22 @@ class OpenSSLRSAPublicKey(univ.Sequence): namedtype.NamedType('publicExponent', univ.Integer()), ) -def encodeDERTRequest(negoTypes = [], authInfo = None, pubKeyAuth = None): + +def encode_der_trequest(nego_types=[], auth_info=None, pub_key_auth=None): """ @summary: create TSRequest from list of Type - @param negoTypes: {list(Type)} - @param authInfo: {str} authentication info TSCredentials encrypted with authentication protocol - @param pubKeyAuth: {str} public key encrypted with authentication protocol + @param nego_types: {list(Type)} + @param auth_info: {str} authentication info TSCredentials encrypted with authentication protocol + @param pub_key_auth: {str} public key encrypted with authentication protocol @return: {str} TRequest der encoded """ negoData = NegoData().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1)) #fill nego data tokens i = 0 - for negoType in negoTypes: + for negoType in nego_types: s = Stream() - s.writeType(negoType) + s.write_type(negoType) negoToken = NegoToken() negoToken.setComponentByPosition(0, s.getvalue()) negoData.setComponentByPosition(i, negoToken) @@ -139,21 +141,23 @@ def encodeDERTRequest(negoTypes = [], authInfo = None, pubKeyAuth = None): if i > 0: request.setComponentByName("negoTokens", negoData) - if not authInfo is None: - request.setComponentByName("authInfo", univ.OctetString(authInfo).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 2))) + if not auth_info is None: + request.setComponentByName("authInfo", univ.OctetString(auth_info).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 2))) - if not pubKeyAuth is None: - request.setComponentByName("pubKeyAuth", univ.OctetString(pubKeyAuth).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 3))) + if not pub_key_auth is None: + request.setComponentByName("pubKeyAuth", univ.OctetString(pub_key_auth).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 3))) return der_encoder.encode(request) -def decodeDERTRequest(s): + +def decode_der_trequest(s): """ @summary: Decode the stream as @param s: {str} """ return der_decoder.decode(s, asn1Spec=TSRequest())[0] + def getNegoTokens(tRequest): negoData = tRequest.getComponentByName("negoTokens") return [Stream(negoData.getComponentByPosition(i).getComponentByPosition(0).asOctets()) for i in range(len(negoData))] @@ -173,117 +177,53 @@ def encodeDERTCredentials(domain, username, password): return der_encoder.encode(credentials) -class CSSP: + +async def connect(reader, writer, authentication_protocol: sspi.IAuthenticationProtocol): """ - @summary: Handle CSSP connection - Proxy class for authentication """ - def __init__(self, layer, authenticationProtocol): - """ - @param layer: {type.Layer.RawLayer} - @param authenticationProtocol: {sspi.IAuthenticationProtocol} - """ - self._layer = layer - self._authenticationProtocol = authenticationProtocol - #IGenericSecurityService - self._interface = None - #function call at the end of nego - self._callback = None - - def setFactory(self, factory): - """ - @summary: Call by RawLayer Factory - @param param: RawLayerClientFactory or RawLayerFactory - """ - self._layer.setFactory(factory) - - def dataReceived(self, data): - """ - @summary: Inherit from twisted.protocol class - main event of received data - @param data: string data receive from twisted - """ - self._layer.dataReceived(data) - - def connectionLost(self, reason): - """ - @summary: Call from twisted engine when protocol is closed - @param reason: str represent reason of close connection - """ - self._layer._factory.connectionLost(self, reason) - - def connectionMade(self): - """ - @summary: install proxy - """ - self._layer.transport = self - self._layer.getDescriptor = lambda:self.transport - self._layer.connectionMade() - - def write(self, data): - """ - @summary: write data on transport layer - @param data: {str} - """ - self.transport.write(data) - - def startTLS(self, sslContext): - """ - @summary: start TLS protocol - @param sslContext: {ssl.ClientContextFactory | ssl.DefaultOpenSSLContextFactory} context use for TLS protocol - """ - self.transport.startTLS(sslContext) - - def startNLA(self, sslContext, callback = None): - """ - @summary: start NLA authentication - @param sslContext: {ssl.ClientContextFactory | ssl.DefaultOpenSSLContextFactory} context use for TLS protocol - @param callback: {function} function call when cssp layer is read - """ - self._callback = callback - self.startTLS(sslContext) - #send negotiate message - self.transport.write(encodeDERTRequest( negoTypes = [ self._authenticationProtocol.getNegotiateMessage() ] )) - #next state is receive a challenge - self.dataReceived = self.recvChallenge - - def recvChallenge(self, data): - """ - @summary: second state in cssp automata - @param data : {str} all data available on buffer - """ - request = decodeDERTRequest(data) - message, self._interface = self._authenticationProtocol.getAuthenticateMessage(getNegoTokens(request)[0]) - #get back public key - #convert from der to ber... - pubKeyDer = crypto.dump_privatekey(crypto.FILETYPE_ASN1, self.transport.protocol._tlsConnection.get_peer_certificate().get_pubkey()) - pubKey = der_decoder.decode(pubKeyDer, asn1Spec=OpenSSLRSAPublicKey())[0] - - rsa = x509.RSAPublicKey() - rsa.setComponentByName("modulus", univ.Integer(pubKey.getComponentByName('modulus')._value)) - rsa.setComponentByName("publicExponent", univ.Integer(pubKey.getComponentByName('publicExponent')._value)) - self._pubKeyBer = ber_encoder.encode(rsa) - - #send authenticate message with public key encoded - self.transport.write(encodeDERTRequest( negoTypes = [ message ], pubKeyAuth = self._interface.GSS_WrapEx(self._pubKeyBer))) - #next step is received public key incremented by one - self.dataReceived = self.recvPubKeyInc - - def recvPubKeyInc(self, data): - """ - @summary: the server send the pubKeyBer + 1 - @param data : {str} all data available on buffer - """ - request = decodeDERTRequest(data) - pubKeyInc = self._interface.GSS_UnWrapEx(getPubKeyAuth(request)) - #check pubKeyInc = self._pubKeyBer + 1 - if not (self._pubKeyBer[1:] == pubKeyInc[1:] and ord(self._pubKeyBer[0]) + 1 == ord(pubKeyInc[0])): - raise error.InvalidExpectedDataException("CSSP : Invalid public key increment") - - domain, user, password = self._authenticationProtocol.getEncodedCredentials() - #send credentials - self.transport.write(encodeDERTRequest( authInfo = self._interface.GSS_WrapEx(encodeDERTCredentials(domain, user, password)))) - #reset state back to normal state - self.dataReceived = lambda x: self.__class__.dataReceived(self, x) - if not self._callback is None: - self._callback() \ No newline at end of file + + # send negotiate message + writer.write(encode_der_trequest(nego_types=[authentication_protocol.getNegotiateMessage()])) + await writer.drain() + print("toto") + trequest = decode_der_trequest(await reader.read(1500)) + print("yahoo") + message, interface = authentication_protocol.getAuthenticateMessage(getNegoTokens(trequest)[0]) + +def recvChallenge(self, data): + """ + @summary: second state in cssp automata + @param data : {str} all data available on buffer + """ + request = decode_der_trequest(data) + message, self._interface = self._authenticationProtocol.getAuthenticateMessage(getNegoTokens(request)[0]) + #get back public key + #convert from der to ber... + pubKeyDer = crypto.dump_privatekey(crypto.FILETYPE_ASN1, self.transport.protocol._tlsConnection.get_peer_certificate().get_pubkey()) + pubKey = der_decoder.decode(pubKeyDer, asn1Spec=OpenSSLRSAPublicKey())[0] + + rsa = x509.RSAPublicKey() + rsa.setComponentByName("modulus", univ.Integer(pubKey.getComponentByName('modulus')._value)) + rsa.setComponentByName("publicExponent", univ.Integer(pubKey.getComponentByName('publicExponent')._value)) + self._pubKeyBer = ber_encoder.encode(rsa) + + #send authenticate message with public key encoded + self.transport.write(encode_der_trequest(nego_types= [message], pub_key_auth= self._interface.GSS_WrapEx(self._pubKeyBer))) + #next step is received public key incremented by one + self.dataReceived = self.recvPubKeyInc + +def recvPubKeyInc(self, data): + """ + @summary: the server send the pubKeyBer + 1 + @param data : {str} all data available on buffer + """ + request = decode_der_trequest(data) + pubKeyInc = self._interface.GSS_UnWrapEx(getPubKeyAuth(request)) + #check pubKeyInc = self._pubKeyBer + 1 + if not (self._pubKeyBer[1:] == pubKeyInc[1:] and ord(self._pubKeyBer[0]) + 1 == ord(pubKeyInc[0])): + raise error.InvalidExpectedDataException("CSSP : Invalid public key increment") + + domain, user, password = self._authenticationProtocol.getEncodedCredentials() + #send credentials + self.transport.write(encode_der_trequest( + auth_info= self._interface.GSS_WrapEx(encodeDERTCredentials(domain, user, password)))) diff --git a/rdpy/core/nla/ntlm.py b/rdpy/core/nla/ntlm.py index 633bf3e..ebc5afc 100644 --- a/rdpy/core/nla/ntlm.py +++ b/rdpy/core/nla/ntlm.py @@ -203,7 +203,7 @@ class ChallengeMessage(CompositeType): s = Stream(self.getTargetInfo()) while(True): avPair = AvPair() - s.readType(avPair) + s.read_type(avPair) if avPair.AvId.value == AvId.MsvAvEOL: return result result[avPair.AvId.value] = avPair.Value.value @@ -469,7 +469,7 @@ def MAC(handle, SigningKey, SeqNum, Message): #write the SeqNum s = Stream() - s.writeType(signature.SeqNum) + s.write_type(signature.SeqNum) signature.Checksum.value = rc4.crypt(handle, HMAC_MD5(SigningKey, s.getvalue() + Message)[:8]) @@ -485,7 +485,7 @@ def MIC(ExportedSessionKey, negotiateMessage, challengeMessage, authenticateMess @see: https://msdn.microsoft.com/en-us/library/cc236676.aspx """ s = Stream() - s.writeType((negotiateMessage, challengeMessage, authenticateMessage)) + s.write_type((negotiateMessage, challengeMessage, authenticateMessage)) return HMAC_MD5(ExportedSessionKey, s.getvalue()) class NTLMv2(sspi.IAuthenticationProtocol): @@ -530,7 +530,7 @@ class NTLMv2(sspi.IAuthenticationProtocol): @see: https://msdn.microsoft.com/en-us/library/cc236676.aspx """ self._challengeMessage = ChallengeMessage() - s.readType(self._challengeMessage) + s.read_type(self._challengeMessage) ServerChallenge = self._challengeMessage.ServerChallenge.value ClientChallenge = random(64) @@ -608,7 +608,7 @@ class NTLMv2SecurityInterface(sspi.IGenericSecurityService): signature = MAC(self._encryptHandle, self._signingKey, self._seqNum, data) self._seqNum += 1 s = Stream() - s.writeType(signature) + s.write_type(signature) return s.getvalue() + encryptedData def GSS_UnWrapEx(self, data): @@ -619,7 +619,7 @@ class NTLMv2SecurityInterface(sspi.IGenericSecurityService): signature = MessageSignatureEx() message = String() s = Stream(data) - s.readType((signature, message)) + s.read_type((signature, message)) #decrypt message plaintextMessage = rc4.crypt(self._decryptHandle, message.value) @@ -627,7 +627,7 @@ class NTLMv2SecurityInterface(sspi.IGenericSecurityService): #recompute checksum t = Stream() - t.writeType(signature.SeqNum) + t.write_type(signature.SeqNum) verify = HMAC_MD5(self._verifyKey, t.getvalue() + plaintextMessage)[:8] if verify != checksum: raise error.InvalidExpectedDataException("NTLMv2SecurityInterface : Invalid checksum") diff --git a/rdpy/core/pdu/layer.py b/rdpy/core/pdu/layer.py index 52cd4b9..5202b89 100644 --- a/rdpy/core/pdu/layer.py +++ b/rdpy/core/pdu/layer.py @@ -176,7 +176,7 @@ class Client(PDULayer): @param s: Stream """ pdu = data.PDU() - s.readType(pdu) + s.read_type(pdu) if pdu.shareControlHeader.pduType.value != data.PDUType.PDUTYPE_DEMANDACTIVEPDU: #not a blocking error because in deactive reactive sequence @@ -204,7 +204,7 @@ class Client(PDULayer): @param s: Stream from transport layer """ pdu = data.PDU() - s.readType(pdu) + s.read_type(pdu) if pdu.shareControlHeader.pduType.value != data.PDUType.PDUTYPE_DATAPDU or pdu.pduMessage.shareDataHeader.pduType2.value != data.PDUType2.PDUTYPE2_SYNCHRONIZE: #not a blocking error because in deactive reactive sequence #input can be send too but ignored @@ -220,7 +220,7 @@ class Client(PDULayer): @param s: Stream from transport layer """ pdu = data.PDU() - s.readType(pdu) + s.read_type(pdu) if pdu.shareControlHeader.pduType.value != data.PDUType.PDUTYPE_DATAPDU or pdu.pduMessage.shareDataHeader.pduType2.value != data.PDUType2.PDUTYPE2_CONTROL or pdu.pduMessage.pduData.action.value != data.Action.CTRLACTION_COOPERATE: #not a blocking error because in deactive reactive sequence #input can be send too but ignored @@ -236,7 +236,7 @@ class Client(PDULayer): @param s: Stream from transport layer """ pdu = data.PDU() - s.readType(pdu) + s.read_type(pdu) if pdu.shareControlHeader.pduType.value != data.PDUType.PDUTYPE_DATAPDU or pdu.pduMessage.shareDataHeader.pduType2.value != data.PDUType2.PDUTYPE2_CONTROL or pdu.pduMessage.pduData.action.value != data.Action.CTRLACTION_GRANTED_CONTROL: #not a blocking error because in deactive reactive sequence #input can be send too but ignored @@ -252,7 +252,7 @@ class Client(PDULayer): @param s: Stream from transport layer """ pdu = data.PDU() - s.readType(pdu) + s.read_type(pdu) if pdu.shareControlHeader.pduType.value != data.PDUType.PDUTYPE_DATAPDU or pdu.pduMessage.shareDataHeader.pduType2.value != data.PDUType2.PDUTYPE2_FONTMAP: #not a blocking error because in deactive reactive sequence #input can be send too but ignored @@ -269,7 +269,7 @@ class Client(PDULayer): @param s: Stream from transport layer """ pdus = ArrayType(data.PDU) - s.readType(pdus) + s.read_type(pdus) for pdu in pdus: if pdu.shareControlHeader.pduType.value == data.PDUType.PDUTYPE_DATAPDU: self.readDataPDU(pdu.pduMessage) @@ -287,7 +287,7 @@ class Client(PDULayer): @param secFlag: {SecFlags} """ updates = ArrayType(data.FastPathUpdatePDU) - fastPathS.readType(updates) + fastPathS.read_type(updates) for update in updates: if update.updateHeader.value == data.FastPathUpdateType.FASTPATH_UPDATETYPE_BITMAP: self._listener.onUpdate(update.updateData.rectangles._array) @@ -419,7 +419,7 @@ class Server(PDULayer): @param s: Stream """ pdu = data.PDU() - s.readType(pdu) + s.read_type(pdu) if pdu.shareControlHeader.pduType.value != data.PDUType.PDUTYPE_CONFIRMACTIVEPDU: #not a blocking error because in deactive reactive sequence @@ -445,7 +445,7 @@ class Server(PDULayer): @param s: Stream from transport layer """ pdu = data.PDU() - s.readType(pdu) + s.read_type(pdu) if pdu.shareControlHeader.pduType.value != data.PDUType.PDUTYPE_DATAPDU or pdu.pduMessage.shareDataHeader.pduType2.value != data.PDUType2.PDUTYPE2_SYNCHRONIZE: #not a blocking error because in deactive reactive sequence #input can be send too but ignored @@ -460,7 +460,7 @@ class Server(PDULayer): @param s: Stream from transport layer """ pdu = data.PDU() - s.readType(pdu) + s.read_type(pdu) if pdu.shareControlHeader.pduType.value != data.PDUType.PDUTYPE_DATAPDU or pdu.pduMessage.shareDataHeader.pduType2.value != data.PDUType2.PDUTYPE2_CONTROL or pdu.pduMessage.pduData.action.value != data.Action.CTRLACTION_COOPERATE: #not a blocking error because in deactive reactive sequence #input can be send too but ignored @@ -475,7 +475,7 @@ class Server(PDULayer): @param s: Stream from transport layer """ pdu = data.PDU() - s.readType(pdu) + s.read_type(pdu) if pdu.shareControlHeader.pduType.value != data.PDUType.PDUTYPE_DATAPDU or pdu.pduMessage.shareDataHeader.pduType2.value != data.PDUType2.PDUTYPE2_CONTROL or pdu.pduMessage.pduData.action.value != data.Action.CTRLACTION_REQUEST_CONTROL: #not a blocking error because in deactive reactive sequence #input can be send too but ignored @@ -491,7 +491,7 @@ class Server(PDULayer): @param s: Stream from transport layer """ pdu = data.PDU() - s.readType(pdu) + s.read_type(pdu) if pdu.shareControlHeader.pduType.value != data.PDUType.PDUTYPE_DATAPDU or pdu.pduMessage.shareDataHeader.pduType2.value != data.PDUType2.PDUTYPE2_FONTLIST: #not a blocking error because in deactive reactive sequence #input can be send but ignored @@ -510,7 +510,7 @@ class Server(PDULayer): @param s: Stream from transport layer """ pdu = data.PDU() - s.readType(pdu) + s.read_type(pdu) if pdu.shareControlHeader.pduType.value == data.PDUType.PDUTYPE_DATAPDU: self.readDataPDU(pdu.pduMessage) diff --git a/rdpy/core/sec.py b/rdpy/core/sec.py index 9ce66db..1a924cb 100644 --- a/rdpy/core/sec.py +++ b/rdpy/core/sec.py @@ -167,7 +167,7 @@ def macData(macSaltKey, data): #encode length dataLength = Stream() - dataLength.writeType(UInt32Le(len(data))) + dataLength.write_type(UInt32Le(len(data))) sha1Digest.update(macSaltKey) sha1Digest.update("\x36" * 40) @@ -195,10 +195,10 @@ def macSaltedData(macSaltKey, data, encryptionCount): #encode length dataLengthS = Stream() - dataLengthS.writeType(UInt32Le(len(data))) + dataLengthS.write_type(UInt32Le(len(data))) encryptionCountS = Stream() - encryptionCountS.writeType(UInt32Le(encryptionCount)) + encryptionCountS.write_type(UInt32Le(encryptionCount)) sha1Digest.update(macSaltKey) sha1Digest.update("\x36" * 40) @@ -412,7 +412,7 @@ class SecLayer(LayerAutomata, IStreamSender, tpkt.IFastPathListener, tpkt.IFastP signature = String(readLen = CallableValue(8)) encryptedPayload = String() - s.readType((signature, encryptedPayload)) + s.read_type((signature, encryptedPayload)) decrypted = rc4.crypt(self._decryptRc4, encryptedPayload.value) #ckeck signature @@ -444,7 +444,7 @@ class SecLayer(LayerAutomata, IStreamSender, tpkt.IFastPathListener, tpkt.IFastP self._nbEncryptedPacket += 1 s = Stream() - s.writeType(data) + s.write_type(data) if saltedMacGeneration: return (String(macSaltedData(self._macKey, s.getvalue(), self._nbEncryptedPacket - 1)[:8]), String(rc4.crypt(self._encryptRc4, s.getvalue()))) @@ -463,7 +463,7 @@ class SecLayer(LayerAutomata, IStreamSender, tpkt.IFastPathListener, tpkt.IFastP securityFlag = UInt16Le() securityFlagHi = UInt16Le() - data.readType((securityFlag, securityFlagHi)) + data.read_type((securityFlag, securityFlagHi)) if securityFlag.value & SecurityFlag.SEC_ENCRYPT: data = self.readEncryptedPayload(data, securityFlag.value & SecurityFlag.SEC_SECURE_CHECKSUM) @@ -631,7 +631,7 @@ class Client(SecLayer): #packet preambule securityFlag = UInt16Le() securityFlagHi = UInt16Le() - s.readType((securityFlag, securityFlagHi)) + s.read_type((securityFlag, securityFlagHi)) if not (securityFlag.value & SecurityFlag.SEC_LICENSE_PKT): raise InvalidExpectedDataException("waiting license packet") @@ -680,13 +680,13 @@ class Server(SecLayer): #packet preambule securityFlag = UInt16Le() securityFlagHi = UInt16Le() - s.readType((securityFlag, securityFlagHi)) + s.read_type((securityFlag, securityFlagHi)) if not (securityFlag.value & SecurityFlag.SEC_EXCHANGE_PKT): raise InvalidExpectedDataException("waiting client random") message = ClientSecurityExchangePDU() - s.readType(message) + s.read_type(message) clientRandom = rsa.decrypt(message.encryptedClientRandom.value[::-1], self._rsaPrivateKey)[::-1] self._macKey, self._initialEncryptKey, self._initialDecrytKey = generateKeys( clientRandom, @@ -711,7 +711,7 @@ class Server(SecLayer): """ securityFlag = UInt16Le() securityFlagHi = UInt16Le() - s.readType((securityFlag, securityFlagHi)) + s.read_type((securityFlag, securityFlagHi)) if not (securityFlag.value & SecurityFlag.SEC_INFO_PKT): raise InvalidExpectedDataException("Waiting info packet") @@ -719,7 +719,7 @@ class Server(SecLayer): if securityFlag.value & SecurityFlag.SEC_ENCRYPT: s = self.readEncryptedPayload(s, securityFlag.value & SecurityFlag.SEC_SECURE_CHECKSUM) - s.readType(self._info) + s.read_type(self._info) #next state send error license self.sendLicensingErrorMessage() #reinit state diff --git a/rdpy/core/t125/ber.py b/rdpy/core/t125/ber.py index 3081236..a69969a 100644 --- a/rdpy/core/t125/ber.py +++ b/rdpy/core/t125/ber.py @@ -69,7 +69,7 @@ def readLength(s): """ size = None length = UInt8() - s.readType(length) + s.read_type(length) byte = length.value if byte & 0x80: byte &= ~0x80 @@ -79,7 +79,7 @@ def readLength(s): size = UInt16Be() else: raise InvalidExpectedDataException("BER length may be 1 or 2") - s.readType(size) + s.read_type(size) else: size = length return size.value @@ -103,7 +103,7 @@ def readUniversalTag(s, tag, pc): @return: true if tag is correctly read """ byte = UInt8() - s.readType(byte) + s.read_type(byte) return byte.value == ((Class.BER_CLASS_UNIV | berPC(pc)) | (Tag.BER_TAG_MASK & tag)) def writeUniversalTag(tag, pc): @@ -123,11 +123,11 @@ def readApplicationTag(s, tag): @return: length of application packet """ byte = UInt8() - s.readType(byte) + s.read_type(byte) if tag.value > 30: if byte.value != ((Class.BER_CLASS_APPL | BerPc.BER_CONSTRUCT) | Tag.BER_TAG_MASK): raise InvalidExpectedDataException() - s.readType(byte) + s.read_type(byte) if byte.value != tag.value: raise InvalidExpectedDataException("bad tag") else: @@ -159,7 +159,7 @@ def readBoolean(s): if size != 1: raise InvalidExpectedDataException("bad boolean size") b = UInt8() - s.readType(b) + s.read_type(b) return bool(b.value) def writeBoolean(b): @@ -186,21 +186,21 @@ def readInteger(s): if size == 1: integer = UInt8() - s.readType(integer) + s.read_type(integer) return integer.value elif size == 2: integer = UInt16Be() - s.readType(integer) + s.read_type(integer) return integer.value elif size == 3: integer1 = UInt8() integer2 = UInt16Be() - s.readType(integer1) - s.readType(integer2) + s.read_type(integer1) + s.read_type(integer2) return integer2.value + (integer1.value << 16) elif size == 4: integer = UInt32Be() - s.readType(integer) + s.read_type(integer) return integer.value else: raise InvalidExpectedDataException("Wrong integer size") @@ -248,7 +248,7 @@ def readEnumerated(s): if readLength(s) != 1: raise InvalidSize("enumerate size is wrong") enumer = UInt8() - s.readType(enumer) + s.read_type(enumer) return enumer.value def writeEnumerated(enumerated): diff --git a/rdpy/core/t125/gcc.py b/rdpy/core/t125/gcc.py index 20721bf..8eb88cb 100644 --- a/rdpy/core/t125/gcc.py +++ b/rdpy/core/t125/gcc.py @@ -371,12 +371,12 @@ class ProprietaryServerCertificate(CompositeType): @summary: compute hash """ s = Stream() - s.writeType(UInt32Le(self.__class__._TYPE_)) - s.writeType(self.dwSigAlgId) - s.writeType(self.dwKeyAlgId) - s.writeType(self.wPublicKeyBlobType) - s.writeType(self.wPublicKeyBlobLen) - s.writeType(self.PublicKeyBlob) + s.write_type(UInt32Le(self.__class__._TYPE_)) + s.write_type(self.dwSigAlgId) + s.write_type(self.dwKeyAlgId) + s.write_type(self.wPublicKeyBlobType) + s.write_type(self.wPublicKeyBlobLen) + s.write_type(self.PublicKeyBlob) md5Digest = md5.new() md5Digest.update(s.getvalue()) @@ -555,7 +555,7 @@ def readConferenceCreateRequest(s): per.readOctetStream(s, h221_cs_key, 4) length = per.readLength(s) clientSettings = Settings(readLen = CallableValue(length)) - s.readType(clientSettings) + s.read_type(clientSettings) return clientSettings def readConferenceCreateResponse(s): @@ -579,7 +579,7 @@ def readConferenceCreateResponse(s): length = per.readLength(s) serverSettings = Settings(readLen = CallableValue(length)) - s.readType(serverSettings) + s.read_type(serverSettings) return serverSettings def writeConferenceCreateRequest(userData): @@ -589,7 +589,7 @@ def writeConferenceCreateRequest(userData): @return: GCC packet """ userDataStream = Stream() - userDataStream.writeType(userData) + userDataStream.write_type(userData) return (per.writeChoice(0), per.writeObjectIdentifier(t124_02_98_oid), per.writeLength(len(userDataStream.getvalue()) + 14), per.writeChoice(0), @@ -604,7 +604,7 @@ def writeConferenceCreateResponse(serverData): @return: gcc packet """ serverDataStream = Stream() - serverDataStream.writeType(serverData) + serverDataStream.write_type(serverData) return (per.writeChoice(0), per.writeObjectIdentifier(t124_02_98_oid), per.writeLength(len(serverDataStream.getvalue()) + 14), per.writeChoice(0x14), diff --git a/rdpy/core/t125/mcs.py b/rdpy/core/t125/mcs.py index 6837e90..4c4a4e3 100644 --- a/rdpy/core/t125/mcs.py +++ b/rdpy/core/t125/mcs.py @@ -216,7 +216,7 @@ class MCSLayer(LayerAutomata): @param data: {Stream} """ opcode = UInt8() - data.readType(opcode) + data.read_type(opcode) if self.readMCSPDUHeader(opcode.value, DomainMCSPDU.DISCONNECT_PROVIDER_ULTIMATUM): log.info("MCS DISCONNECT_PROVIDER_ULTIMATUM") @@ -367,7 +367,7 @@ class Client(MCSLayer): if not ber.readUniversalTag(data, ber.Tag.BER_TAG_OCTET_STRING, False): raise InvalidExpectedDataException("invalid expected BER tag") gccRequestLength = ber.readLength(data) - if data.dataLen() != gccRequestLength: + if data.data_len() != gccRequestLength: raise InvalidSize("bad size of GCC request") self._serverSettings = gcc.readConferenceCreateResponse(data) @@ -385,7 +385,7 @@ class Client(MCSLayer): @param data: {Stream} """ opcode = UInt8() - data.readType(opcode) + data.read_type(opcode) if not self.readMCSPDUHeader(opcode.value, DomainMCSPDU.ATTACH_USER_CONFIRM): raise InvalidExpectedDataException("Invalid MCS PDU : ATTACH_USER_CONFIRM expected") @@ -404,7 +404,7 @@ class Client(MCSLayer): @param data: {Stream} """ opcode = UInt8() - data.readType(opcode) + data.read_type(opcode) if not self.readMCSPDUHeader(opcode.value, DomainMCSPDU.CHANNEL_JOIN_CONFIRM): raise InvalidExpectedDataException("Invalid MCS PDU : CHANNEL_JOIN_CONFIRM expected") @@ -435,7 +435,7 @@ class Client(MCSLayer): """ ccReq = gcc.writeConferenceCreateRequest(self._clientSettings) ccReqStream = Stream() - ccReqStream.writeType(ccReq) + ccReqStream.write_type(ccReq) tmp = (ber.writeOctetstring("\x01"), ber.writeOctetstring("\x01"), ber.writeBoolean(True), self.writeDomainParams(34, 2, 0, 0xffff), @@ -536,7 +536,7 @@ class Server(MCSLayer): @param data: {Stream} """ opcode = UInt8() - data.readType(opcode) + data.read_type(opcode) if not self.readMCSPDUHeader(opcode.value, DomainMCSPDU.ERECT_DOMAIN_REQUEST): raise InvalidExpectedDataException("Invalid MCS PDU : ERECT_DOMAIN_REQUEST expected") @@ -554,7 +554,7 @@ class Server(MCSLayer): @param data: {Stream} """ opcode = UInt8() - data.readType(opcode) + data.read_type(opcode) if not self.readMCSPDUHeader(opcode.value, DomainMCSPDU.ATTACH_USER_REQUEST): raise InvalidExpectedDataException("Invalid MCS PDU : ATTACH_USER_REQUEST expected") @@ -570,7 +570,7 @@ class Server(MCSLayer): """ opcode = UInt8() - data.readType(opcode) + data.read_type(opcode) if not self.readMCSPDUHeader(opcode.value, DomainMCSPDU.CHANNEL_JOIN_REQUEST): raise InvalidExpectedDataException("Invalid MCS PDU : CHANNEL_JOIN_REQUEST expected") @@ -593,7 +593,7 @@ class Server(MCSLayer): """ ccReq = gcc.writeConferenceCreateResponse(self._serverSettings) ccReqStream = Stream() - ccReqStream.writeType(ccReq) + ccReqStream.write_type(ccReq) tmp = (ber.writeEnumerated(0), ber.writeInteger(0), self.writeDomainParams(22, 3, 0, 0xfff8), ber.writeOctetstring(ccReqStream.getvalue())) diff --git a/rdpy/core/t125/per.py b/rdpy/core/t125/per.py index 1f07295..f762908 100644 --- a/rdpy/core/t125/per.py +++ b/rdpy/core/t125/per.py @@ -31,12 +31,12 @@ def readLength(s): @return: int python """ byte = UInt8() - s.readType(byte) + s.read_type(byte) size = 0 if byte.value & 0x80: byte.value &= ~0x80 size = byte.value << 8 - s.readType(byte) + s.read_type(byte) size += byte.value else: size = byte.value @@ -60,7 +60,7 @@ def readChoice(s): @return: int that represent choice """ choice = UInt8() - s.readType(choice) + s.read_type(choice) return choice.value def writeChoice(choice): @@ -78,7 +78,7 @@ def readSelection(s): @return: int that represent selection """ choice = UInt8() - s.readType(choice) + s.read_type(choice) return choice.value def writeSelection(selection): @@ -96,7 +96,7 @@ def readNumberOfSet(s): @return: int that represent numberOfSet """ choice = UInt8() - s.readType(choice) + s.read_type(choice) return choice.value def writeNumberOfSet(numberOfSet): @@ -114,7 +114,7 @@ def readEnumerates(s): @return: int that represent enumerate """ choice = UInt8() - s.readType(choice) + s.read_type(choice) return choice.value def writeEnumerates(enumer): @@ -142,7 +142,7 @@ def readInteger(s): result = UInt32Be() else: raise InvalidValue("invalid integer size %d"%size) - s.readType(result) + s.read_type(result) return result.value def writeInteger(value): @@ -166,7 +166,7 @@ def readInteger16(s, minimum = 0): @return: int or long python value """ result = UInt16Be() - s.readType(result) + s.read_type(result) return result.value + minimum def writeInteger16(value, minimum = 0): @@ -190,16 +190,16 @@ def readObjectIdentifier(s, oid): raise InvalidValue("size of stream oid is wrong %d != 5"%size) a_oid = [0, 0, 0, 0, 0, 0] t12 = UInt8() - s.readType(t12) + s.read_type(t12) a_oid[0] = t12.value >> 4 a_oid[1] = t12.value & 0x0f - s.readType(t12) + s.read_type(t12) a_oid[2] = t12.value - s.readType(t12) + s.read_type(t12) a_oid[3] = t12.value - s.readType(t12) + s.read_type(t12) a_oid[4] = t12.value - s.readType(t12) + s.read_type(t12) a_oid[5] = t12.value if list(oid) != a_oid: @@ -279,7 +279,7 @@ def readOctetStream(s, octetStream, minValue = 0): raise InvalidValue("incompatible size %d != %d"(len(octetStream), size)) for i in range(0, size): c = UInt8() - s.readType(c) + s.read_type(c) if ord(octetStream[i]) != c.value: return False diff --git a/rdpy/core/tpkt.py b/rdpy/core/tpkt.py index 9207bbc..bdc493d 100644 --- a/rdpy/core/tpkt.py +++ b/rdpy/core/tpkt.py @@ -22,8 +22,12 @@ Transport packet layer implementation Use to build correct size packet and handle slow path and fast path mode """ +import asyncio +import ssl + +from rdpy.core.nla import cssp, ntlm from rdpy.model.layer import RawLayer -from rdpy.model.type import UInt8, UInt16Be, sizeof +from rdpy.model.type import UInt8, UInt16Be, sizeof, Stream from rdpy.model.error import CallPureVirtualFuntion @@ -34,104 +38,27 @@ class Action(object): """ FASTPATH_ACTION_FASTPATH = 0x0 FASTPATH_ACTION_X224 = 0x3 - + + class SecFlags(object): """ @see: http://msdn.microsoft.com/en-us/library/cc240621.aspx """ - #hihi 'secure' checksum but private key is public !!! FASTPATH_OUTPUT_SECURE_CHECKSUM = 0x1 FASTPATH_OUTPUT_ENCRYPTED = 0x2 -class IFastPathListener(object): - """ - @summary: Fast path packet listener - Usually X224 layer - """ - def recvFastPath(self, secFlag, fastPathS): - """ - @summary: Call when fast path packet is received - @param secFlag: {SecFlags} - @param fastPathS: {Stream} - """ - raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "recvFastPath", "IFastPathListener")) - - def initFastPath(self, fastPathSender): - """ - @summary: initialize stack - @param fastPathSender: {IFastPathSender} - """ - self.setFastPathSender(fastPathSender) - fastPathSender.setFastPathListener(self) - - def setFastPathSender(self, fastPathSender): - """ - @param fastPathSender : {IFastPathSender} - """ - raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "setFastPathSender", "IFastPathListener")) - -class IFastPathSender(object): - """ - @summary: Fast path send capability - """ - def sendFastPath(self, secFlag, fastPathS): - """ - @summary: Send fastPathS Type as fast path packet - @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")) - - def initFastPath(self, fastPathListener): - """ - @summary: initialize stack - @param fastPathListener: {IFastPathListener} - """ - self.setFastPathListener(fastPathListener) - fastPathListener.setFastPathSender(self) - - def setFastPathListener(self, fastPathListener): - """ - @param fastPathListener: {IFastPathListener} - """ - raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "setFastPathListener", "IFastPathSender")) -class TPKT(RawLayer, IFastPathSender): +class Tpkt: """ @summary: TPKT layer in RDP protocol stack represent the Raw Layer in stack (first layer) This layer only handle size of packet and determine if is a fast path packet """ - def __init__(self, presentation): - """ - @param presentation: {Layer} presentation layer, in RDP case is x224 layer - """ - RawLayer.__init__(self, presentation) - #length may be coded on more than 1 bytes - self._lastShortLength = UInt8() - #fast path listener - self._fastPathListener = None - #last secure flag - self._secFlag = 0 - - def setFastPathListener(self, fastPathListener): - """ - @param fastPathListener : {IFastPathListener} - @note: implement IFastPathSender - """ - self._fastPathListener = fastPathListener - - def connect(self): - """ - @summary: Call when transport layer connection - is made (inherit from RawLayer) - """ - #header is on two bytes - self.expect(2, self.readHeader) - #no connection automata on this layer - if not self._presentation is None: - self._presentation.connect() - + + def __init__(self, reader, writer): + self.reader = reader + self.writer = writer + def readHeader(self, data): """ @summary: Read header of TPKT packet @@ -139,17 +66,17 @@ class TPKT(RawLayer, IFastPathSender): """ #first read packet version version = UInt8() - data.readType(version) + data.read_type(version) #classic packet if version.value == Action.FASTPATH_ACTION_X224: #padding - data.readType(UInt8()) + data.read_type(UInt8()) #read end header self.expect(2, self.readExtendedHeader) else: #is fast path packet self._secFlag = ((version.value >> 6) & 0x3) - data.readType(self._lastShortLength) + data.read_type(self._lastShortLength) if self._lastShortLength.value & 0x80: #size is 1 byte more self.expect(1, self.readExtendedFastPathHeader) @@ -164,7 +91,7 @@ class TPKT(RawLayer, IFastPathSender): """ #next state is read data size = UInt16Be() - data.readType(size) + data.read_type(size) self.expect(size.value - 4, self.readData) def readExtendedFastPathHeader(self, data): @@ -173,7 +100,7 @@ class TPKT(RawLayer, IFastPathSender): @param data: {Stream} from twisted layer """ leftPart = UInt8() - data.readType(leftPart) + data.read_type(leftPart) self._lastShortLength.value &= ~0x80 packetSize = (self._lastShortLength.value << 8) + leftPart.value #next state is fast patn data @@ -196,13 +123,32 @@ class TPKT(RawLayer, IFastPathSender): self._presentation.recv(data) self.expect(2, self.readHeader) - def send(self, message): + async def write(self, message): """ @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)) - + s = Stream() + s.write_type((UInt8(Action.FASTPATH_ACTION_X224), UInt8(0), UInt16Be(sizeof(message) + 4), message)) + self.writer.write(s.getvalue()) + await self.writer.drain() + + async def read(self): + """ + Read an entire payload from the reader stream + """ + header = Stream(await self.reader.readexactly(2)) + action = UInt8() + header.read_type(action) + if action.value == Action.FASTPATH_ACTION_X224: + # read padding + header.read_type(UInt8()) + + size = UInt16Be() + Stream(await self.reader.readexactly(2)).read_type(size) + return Stream(await self.reader.readexactly(size.value - 4)) + + def sendFastPath(self, secFlag, fastPathS): """ @param fastPathS: {Type | Tuple} type transform to stream and send as fastpath @@ -210,16 +156,20 @@ class TPKT(RawLayer, IFastPathSender): """ RawLayer.send(self, (UInt8(Action.FASTPATH_ACTION_FASTPATH | ((secFlag & 0x3) << 6)), UInt16Be((sizeof(fastPathS) + 3) | 0x8000), fastPathS)) - def startTLS(self, sslContext): + async def start_tls(self): """ - @summary: start TLS protocol - @param sslContext: {ssl.ClientContextFactory | ssl.DefaultOpenSSLContextFactory} context use for TLS protocol + Start TLS protocol """ - self.transport.startTLS(sslContext) + ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + ssl_ctx.check_hostname = False + ssl_ctx.verify_mode = ssl.VerifyMode.CERT_NONE + reader, writer = await asyncio.open_connection(sock=self.writer.transport._sock, ssl=ssl_ctx, server_hostname="") + return Tpkt(reader, writer) - def startNLA(self, sslContext, callback): + async def start_nla(self): """ - @summary: use to start NLA (NTLM over SSL) protocol - must be called after startTLS function + use to start NLA (NTLM over SSL) protocol + must be called after startTLS function """ - self.transport.startNLA(sslContext, callback) \ No newline at end of file + tpkt = await self.start_tls() + await cssp.connect(tpkt.reader, tpkt.writer, ntlm.NTLMv2("", "sylvain", "sylvain")) diff --git a/rdpy/core/x224.py b/rdpy/core/x224.py index 2e4a4f5..5e3ecba 100644 --- a/rdpy/core/x224.py +++ b/rdpy/core/x224.py @@ -23,6 +23,7 @@ Implement transport PDU layer This layer have main goal to negociate SSL transport RDP basic security is supported only on client side """ +from rdpy.core import tpkt from rdpy.model import log from rdpy.model.layer import LayerAutomata, IStreamSender @@ -67,7 +68,8 @@ class NegotiationFailureCode(object): INCONSISTENT_FLAGS = 0x00000004 HYBRID_REQUIRED_BY_SERVER = 0x00000005 SSL_WITH_USER_AUTH_REQUIRED_BY_SERVER = 0x00000006 - + + class ClientConnectionRequestPDU(CompositeType): """ @summary: Connection request @@ -83,6 +85,7 @@ class ClientConnectionRequestPDU(CompositeType): #read if there is enough data self.protocolNeg = Negotiation(optional = True) + class ServerConnectionConfirm(CompositeType): """ @summary: Server response @@ -95,7 +98,8 @@ class ServerConnectionConfirm(CompositeType): self.padding = (UInt16Be(), UInt16Be(), UInt8()) #read if there is enough data self.protocolNeg = Negotiation(optional = True) - + + class X224DataHeader(CompositeType): """ @summary: Header send when x224 exchange application data @@ -105,7 +109,8 @@ class X224DataHeader(CompositeType): self.header = UInt8(2) self.messageType = UInt8(MessageType.X224_TPDU_DATA, constant = True) self.separator = UInt8(0x80, constant = True) - + + class Negotiation(CompositeType): """ @summary: Negociate request message @@ -122,117 +127,90 @@ class Negotiation(CompositeType): self.selectedProtocol = UInt32Le(conditional = lambda: (self.code.value != NegociationType.TYPE_RDP_NEG_FAILURE)) self.failureCode = UInt32Le(conditional = lambda: (self.code.value == NegociationType.TYPE_RDP_NEG_FAILURE)) -class X224Layer(LayerAutomata, IStreamSender): + +class X224: """ @summary: x224 layer management there is an connection automata """ - def __init__(self, presentation): + def __init__(self, tpkt: tpkt.Tpkt): """ - @param presentation: upper layer, MCS layer in RDP case + @param tpkt: TPKT layer """ - LayerAutomata.__init__(self, presentation) - #client requested selectedProtocol - self._requestedProtocol = Protocols.PROTOCOL_SSL | Protocols.PROTOCOL_HYBRID - #server selected selectedProtocol - self._selectedProtocol = Protocols.PROTOCOL_SSL + self.tpkt = tpkt - def recvData(self, data): + async def read(self): """ @summary: Read data header from packet And pass to presentation layer @param data: Stream """ header = X224DataHeader() - data.readType(header) - self._presentation.recv(data) + payload = await self.tpkt.read() + payload.read_type(header) + return payload - def send(self, message): + async def write(self, message): """ - @summary: Write message packet for TPDU layer - Add TPDU header - @param message: network.Type message + @summary: Write message packet for TPDU layer + Add TPDU header + @param message: """ - self._transport.send((X224DataHeader(), message)) - -class Client(X224Layer): - """ - @summary: Client automata of TPDU layer - """ - def __init__(self, presentation): - """ - @param presentation: upper layer, MCS layer in RDP case - """ - X224Layer.__init__(self, presentation) - - def connect(self): - """ - @summary: Connection request for client send a connection request packet - """ - self.sendConnectionRequest() - - def sendConnectionRequest(self): - """ - @summary: Write connection request message - Next state is recvConnectionConfirm - @see: http://msdn.microsoft.com/en-us/library/cc240500.aspx - """ - message = ClientConnectionRequestPDU() - message.protocolNeg.code.value = NegociationType.TYPE_RDP_NEG_REQ - message.protocolNeg.selectedProtocol.value = self._requestedProtocol - self._transport.send(message) - self.setNextState(self.recvConnectionConfirm) - - def recvConnectionConfirm(self, data): - """ - @summary: Receive connection confirm message - Next state is recvData - Call connect on presentation layer if all is good - @param data: Stream that contain connection confirm - @see: response -> http://msdn.microsoft.com/en-us/library/cc240506.aspx - @see: failure ->http://msdn.microsoft.com/en-us/library/cc240507.aspx - """ - message = ServerConnectionConfirm() - data.readType(message) - - if message.protocolNeg.failureCode._is_readed: - raise RDPSecurityNegoFail("negotiation failure code %x"%message.protocolNeg.failureCode.value) - - #check presence of negotiation response - if message.protocolNeg._is_readed: - self._selectedProtocol = message.protocolNeg.selectedProtocol.value - else: - self._selectedProtocol = Protocols.PROTOCOL_RDP - - #NLA protocol doesn't support in actual version of RDPY - if self._selectedProtocol in [ Protocols.PROTOCOL_HYBRID_EX ]: - raise InvalidExpectedDataException("RDPY doesn't support PROTOCOL_HYBRID_EX security Layer") - - #now i'm ready to receive data - self.setNextState(self.recvData) - - if self._selectedProtocol == Protocols.PROTOCOL_RDP: - log.warning("*" * 43) - log.warning("*" + " " * 10 + "RDP Security selected" + " " * 10 + "*") - log.warning("*" * 43) - #connection is done send to presentation - self._presentation.connect() - - elif self._selectedProtocol == Protocols.PROTOCOL_SSL: - log.info("*" * 43) - log.info("*" + " " * 10 + "SSL Security selected" + " " * 10 + "*") - log.info("*" * 43) - self._transport.startTLS(ClientTLSContext()) - #connection is done send to presentation - self._presentation.connect() - - elif self._selectedProtocol == Protocols.PROTOCOL_HYBRID: - log.info("*" * 43) - log.info("*" + " " * 10 + "NLA Security selected" + " " * 10 + "*") - log.info("*" * 43) - self._transport.startNLA(ClientTLSContext(), lambda:self._presentation.connect()) + await self.tpkt.write((X224DataHeader(), message)) -class Server(X224Layer): + +async def connect(tpkt: tpkt.Tpkt) -> X224: + """ + @summary: Write connection request message + Next state is recvConnectionConfirm + @see: http://msdn.microsoft.com/en-us/library/cc240500.aspx + """ + message = ClientConnectionRequestPDU() + message.protocolNeg.code.value = NegociationType.TYPE_RDP_NEG_REQ + message.protocolNeg.selectedProtocol.value = Protocols.PROTOCOL_HYBRID | Protocols.PROTOCOL_SSL + await tpkt.write(message) + selected_protocol = await read_connection_confirm(await tpkt.read()) + if selected_protocol in [Protocols.PROTOCOL_HYBRID_EX]: + raise InvalidExpectedDataException("RDPY doesn't support PROTOCOL_HYBRID_EX security Layer") + + if selected_protocol == Protocols.PROTOCOL_RDP: + log.warning("*" * 43) + log.warning("*" + " " * 10 + "RDP Security selected" + " " * 10 + "*") + log.warning("*" * 43) + return X224(tpkt) + elif selected_protocol == Protocols.PROTOCOL_SSL: + log.info("*" * 43) + log.info("*" + " " * 10 + "SSL Security selected" + " " * 10 + "*") + log.info("*" * 43) + return X224(await tpkt.start_tls()) + elif selected_protocol == Protocols.PROTOCOL_HYBRID: + log.info("*" * 43) + log.info("*" + " " * 10 + "NLA Security selected" + " " * 10 + "*") + log.info("*" * 43) + return X224(await tpkt.start_nla()) + + +async def read_connection_confirm(data) -> int: + """ + Read connection confirm and return the negotiated protocol + :ivar data: Stream that contain connection confirm + :see: response -> https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/b2975bdc-6d56-49ee-9c57-f2ff3a0b6817 + :see: failure -> https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/1b3920e7-0116-4345-bc45-f2c4ad012761 + """ + message = ServerConnectionConfirm() + data.read_type(message) + + if message.protocolNeg.failureCode._is_readed: + raise RDPSecurityNegoFail("negotiation failure code %x"%message.protocolNeg.failureCode.value) + + # check presence of negotiation response + if message.protocolNeg._is_readed: + return message.protocolNeg.selectedProtocol.value + else: + return Protocols.PROTOCOL_RDP + + +class Server(X224): """ @summary: Server automata of X224 layer """ @@ -263,7 +241,7 @@ class Server(X224Layer): @see : http://msdn.microsoft.com/en-us/library/cc240470.aspx """ message = ClientConnectionRequestPDU() - data.readType(message) + data.read_type(message) if not message.protocolNeg._is_readed: self._requestedProtocol = Protocols.PROTOCOL_RDP diff --git a/rdpy/model/layer.py b/rdpy/model/layer.py index 89fab12..e514d3d 100644 --- a/rdpy/model/layer.py +++ b/rdpy/model/layer.py @@ -256,5 +256,5 @@ class RawLayer(asyncio.Protocol, LayerAutomata, IStreamSender): @param message: (tuple | Type) """ s = Stream() - s.writeType(message) + s.write_type(message) self.transport.write(s.getvalue()) \ No newline at end of file diff --git a/rdpy/model/rss.py b/rdpy/model/rss.py index 543327d..ff7c2c8 100644 --- a/rdpy/model/rss.py +++ b/rdpy/model/rss.py @@ -177,7 +177,7 @@ class FileRecorder(object): self._lastEventTimer = now s = Stream() - s.writeType(e) + s.write_type(e) self._file.write(s.getvalue()) @@ -276,10 +276,10 @@ class FileReader(object): """ @summary: read next event and return it """ - if self._s.dataLen() == 0: + if self._s.data_len() == 0: return None e = Event() - self._s.readType(e) + self._s.read_type(e) return e def createRecorder(path): diff --git a/rdpy/model/type.py b/rdpy/model/type.py index 1cb85dc..0a7f435 100644 --- a/rdpy/model/type.py +++ b/rdpy/model/type.py @@ -47,12 +47,13 @@ def sizeof(element): return element.__sizeof__() return 0 -class Type(object): + +class Type: """ @summary: Root type object inheritance Record conditional optional of constant mechanism """ - def __init__(self, conditional = lambda:True, optional = False, constant = False): + def __init__(self, conditional=lambda:True, optional=False, constant=False): """ @param conditional : Callable object Read and Write operation depend on return of this function @@ -63,11 +64,11 @@ class Type(object): self._conditional = conditional self._optional = optional self._constant = constant - #use to record read state - #if type is optional and not present during read - #this boolean stay false + # use to record read state + # if type is optional and not present during read + # this boolean stay false self._is_readed = False - #use to know if type was written + # use to know if type was written self._is_writed = False def write(self, s): @@ -93,18 +94,18 @@ class Type(object): if not self._is_readed: return - #not constant mode direct reading + # not constant mode direct reading if not self._constant: self.__read__(s) return - #constant mode + # constant mode old = deepcopy(self) self.__read__(s) - #check constant value + # check constant value if old != self: - #rollback read value - s.pos -= sizeof(self) + # rollback read value + s.seek(-sizeof(self), 1) raise InvalidExpectedDataException("%s const value expected %s != %s"%(self.__class__, old.value, self.value)) def __read__(self, s): @@ -127,8 +128,9 @@ class Type(object): @return: size in byte of type """ raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "__sizeof__", "Type")) - -class CallableValue(object): + + +class CallableValue: """ @summary: Expression evaluate when is get or set Ex: Type contain length of array and array @@ -181,6 +183,7 @@ class CallableValue(object): """ self.__setValue__(value) + class SimpleType(Type, CallableValue): """ @summary: Non composite type @@ -257,7 +260,7 @@ class SimpleType(Type, CallableValue): @param s: Stream that will be read @raise InvalidSize: if there is not enough data in stream """ - if s.dataLen() < self._typeSize: + if s.data_len() < self._typeSize: raise InvalidSize("Stream is too small to read expected SimpleType") self.value = struct.unpack(self._structFormat, s.read(self._typeSize))[0] @@ -267,7 +270,7 @@ class SimpleType(Type, CallableValue): Because in Python all numbers are Int long or float Cache result in self._mask field """ - if not self.__dict__.has_key("_mask"): + if "_mask" not in self.__dict__.keys(): mask = 0xff for _ in range(1, self._typeSize): mask = mask << 8 | 0xff @@ -292,7 +295,7 @@ class SimpleType(Type, CallableValue): """ return self._typeSize - def __cmp__(self, other): + def __eq__(self, other): """ @summary: Compare two simple type Call inner value compare operator @@ -302,7 +305,19 @@ class SimpleType(Type, CallableValue): """ if not isinstance(other, SimpleType): other = self.__class__(other) - return self.value.__cmp__(other.value) + return self.value.__eq__(other.value) + + def __ne__(self, other): + """ + @summary: Compare two simple type + Call inner value compare operator + @param other: SimpleType value or try to build same type as self + around value + @return: python value compare + """ + if not isinstance(other, SimpleType): + other = self.__class__(other) + return self.value.__ne__(other.value) def __invert__(self): """ @@ -458,7 +473,7 @@ class CompositeType(Type): readLen = 0 for name in self._typeName: try: - s.readType(self.__dict__[name]) + s.read_type(self.__dict__[name]) readLen += sizeof(self.__dict__[name]) #read is ok but read out of bound if not self._readLen is None and readLen > self._readLen.value: @@ -474,7 +489,7 @@ class CompositeType(Type): for tmpName in self._typeName: if tmpName == name: break - s.pos -= sizeof(self.__dict__[tmpName]) + s.seek(-sizeof(self.__dict__[tmpName]), 1) raise e if not self._readLen is None and readLen < self._readLen.value: @@ -489,7 +504,7 @@ class CompositeType(Type): """ for name in self._typeName: try: - s.writeType(self.__dict__[name]) + s.write_type(self.__dict__[name]) except Exception as e: log.error("Error during write %s::%s"%(self.__class__, name)) raise e @@ -736,13 +751,14 @@ class UInt24Le(SimpleType): @param s: Stream """ self.value = struct.unpack(self._structFormat, s.read(self._typeSize) + '\x00')[0] - + + class String(Type, CallableValue): """ @summary: String type Leaf in Type tree """ - def __init__(self, value = "", readLen = None, conditional = lambda:True, optional = False, constant = False, unicode = False, until = None): + def __init__(self, value=b"", readLen = None, encoding=None, conditional=lambda:True, optional=False, constant=False, until=None): """ @param value: python string use for inner value @param readLen: length use to read in stream (SimpleType) if 0 read entire stream @@ -754,20 +770,24 @@ class String(Type, CallableValue): @param unicode: Encode and decode value as unicode @param until: read until sequence is readed or write sequence at the end of string """ - Type.__init__(self, conditional = conditional, optional = optional, constant = constant) + Type.__init__(self, conditional=conditional, optional=optional, constant=constant) CallableValue.__init__(self, value) #type use to know read length self._readLen = readLen - self._unicode = unicode + self._encoding = encoding self._until = until - def __cmp__(self, other): + def __eq__(self, other): """ - @summary: call raw compare value - @param other: other String parameter - @return: if two inner value are equals + """ - return cmp(self.value, other.value) + return self.value.__eq__(other.value) + + def __ne__(self, other): + """ + + """ + return self.value.__ne__(other.value) def __hash__(self): """ @@ -796,9 +816,9 @@ class String(Type, CallableValue): toWrite += self._until if self._unicode: - s.write(encodeUnicode(self.value)) + s.write(bytes(self.value.encode("utf-16le"), "utf-16le")) else: - s.write(self.value) + s.write(bytes(self.value, "ascii")) def __read__(self, s): """ @@ -809,16 +829,16 @@ class String(Type, CallableValue): """ if self._readLen is None: if self._until is None: - self.value = s.getvalue()[s.pos:] + self.value = s.getvalue()[s.tell():] else: self.value = "" - while self.value[-len(self._until):] != self._until and s.dataLen() != 0: + while self.value[-len(self._until):] != self._until and s.data_len() != 0: self.value += s.read(1) else: self.value = s.read(self._readLen.value) if self._unicode: - self.value = decodeUnicode(self.value) + self.value = self.value.decode("utf-16le") def __sizeof__(self): """ @@ -858,33 +878,33 @@ class Stream(BytesIO): """ @summary: Stream use to read all types """ - def dataLen(self): + def data_len(self) -> int: """ - @return: not yet read length + :returns: not yet read length """ - return self.len - self.pos + return len(self.getvalue()) - self.tell() - def readLen(self): + def read_len(self) -> int: """ - @summary: compute already read size - @return: read size of stream + Compute already read size + :returns: read size of stream """ - return self.pos + return self.seek() - def readType(self, value): + def read_type(self, value: Type): """ - @summary: call specific read on type object - or iterate over tuple elements - rollback read if error occurred during read value - @param value: (tuple | Type) object + Call specific read on type object + or iterate over tuple elements + rollback read if error occurred during read value + :ivar tuple | Type object """ - #read each tuple + # read each tuple if isinstance(value, tuple) or isinstance(value, list): for element in value: try: - self.readType(element) + self.read_type(element) except Exception as e: - #rollback already readed elements + # rollback already readed elements for tmpElement in value: if tmpElement == element: break @@ -892,8 +912,8 @@ class Stream(BytesIO): raise e return - #optional value not present - if self.dataLen() == 0 and value._optional: + # optional value not present + if self.data_len() == 0 and value._optional: return value.read(self) @@ -903,22 +923,24 @@ class Stream(BytesIO): @summary: read next type but didn't consume it @param t: Type element """ - self.readType(t) + self.read_type(t) self.pos -= sizeof(t) - def writeType(self, value): + def write_type(self, value: Type): """ - @summary: Call specific write on type object - or iterate over tuple element - @param value: (tuple | Type) + Call specific write on type object + or iterate over tuple element + + :ivar Type: Type to write """ - #write each element of tuple + # write each element of tuple if isinstance(value, tuple) or isinstance(value, list): for element in value: - self.writeType(element) + self.write_type(element) return value.write(self) - + + class ArrayType(Type): """ @summary: Factory af n element @@ -952,7 +974,7 @@ class ArrayType(Type): while self._readLen is None or i < self._readLen.value: element = self._typeFactory() element._optional = self._readLen is None - s.readType(element) + s.read_type(element) if not element._is_readed: break self._array.append(element) @@ -963,7 +985,7 @@ class ArrayType(Type): @summary: Just write array @param s: Stream """ - s.writeType(self._array) + s.write_type(self._array) def __getitem__(self, item): """ @@ -1005,7 +1027,7 @@ class FactoryType(Type): @param s: Stream """ self._value = self._factory() - s.readType(self._value) + s.read_type(self._value) def __write__(self, s): """ @@ -1013,7 +1035,7 @@ class FactoryType(Type): @param s: Stream """ self._value = self._factory() - s.writeType(self._value) + s.write_type(self._value) def __getattr__(self, name): """ diff --git a/test/test_core_layer.py b/test/test_core_layer.py index b24d5ea..04e7a78 100644 --- a/test/test_core_layer.py +++ b/test/test_core_layer.py @@ -56,7 +56,7 @@ class LayerTest(unittest.TestCase): """ class TestAutomata(rdpy.core.layer.RawLayer): def expectedCallBack(self, data): - if data.dataLen() == 4: + if data.data_len() == 4: raise LayerTest.LayerCaseException() t = TestAutomata() @@ -69,7 +69,7 @@ class LayerTest(unittest.TestCase): """ class TestAutomata(rdpy.core.layer.RawLayer): def expectedCallBack(self, data): - if data.dataLen() == 4: + if data.data_len() == 4: raise LayerTest.LayerCaseException() t = TestAutomata() diff --git a/test/test_core_type.py b/test/test_core_type.py index 1ca9064..e1ecd73 100644 --- a/test/test_core_type.py +++ b/test/test_core_type.py @@ -56,7 +56,7 @@ class TypeTest(unittest.TestCase): def __write__(self, s): raise Exception() s = rdpy.core.type.Stream() - self.assertRaises(Exception, s.writeType, TestType(conditional = lambda:True)) + self.assertRaises(Exception, s.write_type, TestType(conditional = lambda:True)) @unittest.expectedFailure def test_type_write_conditional_false(self): @@ -67,7 +67,7 @@ class TypeTest(unittest.TestCase): def __write__(self, s): raise Exception() s = rdpy.core.type.Stream() - self.assertRaises(Exception, s.writeType, TestType(conditional = lambda:False)) + self.assertRaises(Exception, s.write_type, TestType(conditional = lambda:False)) def test_type_read_conditional_true(self): """ @@ -77,7 +77,7 @@ class TypeTest(unittest.TestCase): def __read__(self, s): raise Exception() s = rdpy.core.type.Stream() - self.assertRaises(Exception, s.readType, TestType(conditional = lambda:True)) + self.assertRaises(Exception, s.read_type, TestType(conditional = lambda:True)) @unittest.expectedFailure def test_type_read_conditional_false(self): @@ -88,7 +88,7 @@ class TypeTest(unittest.TestCase): def __read__(self, s): raise Exception() s = rdpy.core.type.Stream() - self.assertRaises(Exception, s.readType, TestType(conditional = lambda:False)) + self.assertRaises(Exception, s.read_type, TestType(conditional = lambda:False)) def test_sizeof_conditional_true(self): @@ -138,7 +138,7 @@ class TypeTest(unittest.TestCase): @summary: test write uint8 in stream """ s = rdpy.core.type.Stream() - s.writeType(rdpy.core.type.UInt8(1)) + s.write_type(rdpy.core.type.UInt8(1)) self.assertEqual(''.join(s.buflist), '\x01', "invalid stream write") def test_stream_write_uint16Le_type(self): @@ -146,7 +146,7 @@ class TypeTest(unittest.TestCase): @summary: test write UInt16Le in stream """ s = rdpy.core.type.Stream() - s.writeType(rdpy.core.type.UInt16Le(1)) + s.write_type(rdpy.core.type.UInt16Le(1)) self.assertEqual(''.join(s.buflist), '\x01\x00', "invalid stream write") def test_stream_write_uint16Be_type(self): @@ -154,7 +154,7 @@ class TypeTest(unittest.TestCase): @summary: test write UInt16Be in stream """ s = rdpy.core.type.Stream() - s.writeType(rdpy.core.type.UInt16Be(1)) + s.write_type(rdpy.core.type.UInt16Be(1)) self.assertEqual(''.join(s.buflist), '\x00\x01', "invalid stream write") def test_stream_write_uint24Le_type(self): @@ -162,7 +162,7 @@ class TypeTest(unittest.TestCase): @summary: test write UInt24Le in stream """ s = rdpy.core.type.Stream() - s.writeType(rdpy.core.type.UInt24Le(1)) + s.write_type(rdpy.core.type.UInt24Le(1)) self.assertEqual(''.join(s.buflist), '\x01\x00\x00', "invalid stream write") def test_stream_write_uint24Be_type(self): @@ -170,7 +170,7 @@ class TypeTest(unittest.TestCase): @summary: test write uint24Be in stream """ s = rdpy.core.type.Stream() - s.writeType(rdpy.core.type.UInt24Be(1)) + s.write_type(rdpy.core.type.UInt24Be(1)) self.assertEqual(''.join(s.buflist), '\x00\x00\x01', "invalid stream write") def test_stream_write_uint32Le_type(self): @@ -178,7 +178,7 @@ class TypeTest(unittest.TestCase): @summary: test write UInt32Le in stream """ s = rdpy.core.type.Stream() - s.writeType(rdpy.core.type.UInt32Le(1)) + s.write_type(rdpy.core.type.UInt32Le(1)) self.assertEqual(''.join(s.buflist), '\x01\x00\x00\x00', "invalid stream write") def test_stream_write_uint32Be_type(self): @@ -186,7 +186,7 @@ class TypeTest(unittest.TestCase): @summary: test write UInt32Be in stream """ s = rdpy.core.type.Stream() - s.writeType(rdpy.core.type.UInt32Be(1)) + s.write_type(rdpy.core.type.UInt32Be(1)) self.assertEqual(''.join(s.buflist), '\x00\x00\x00\x01', "invalid stream write") def test_stream_read_uint8_type(self): @@ -195,9 +195,9 @@ class TypeTest(unittest.TestCase): """ s = rdpy.core.type.Stream('\x01') t = rdpy.core.type.UInt8() - s.readType(t) + s.read_type(t) self.assertEqual(t.value, 1, "invalid stream read value") - self.assertEqual(s.dataLen(), 0, "not read all stream") + self.assertEqual(s.data_len(), 0, "not read all stream") def test_stream_read_uint16Le_type(self): """ @@ -205,9 +205,9 @@ class TypeTest(unittest.TestCase): """ s = rdpy.core.type.Stream('\x01\x00') t = rdpy.core.type.UInt16Le() - s.readType(t) + s.read_type(t) self.assertEqual(t.value, 1, "invalid stream read value") - self.assertEqual(s.dataLen(), 0, "not read all stream") + self.assertEqual(s.data_len(), 0, "not read all stream") def test_stream_read_uint16Be_type(self): """ @@ -215,9 +215,9 @@ class TypeTest(unittest.TestCase): """ s = rdpy.core.type.Stream('\x00\x01') t = rdpy.core.type.UInt16Be() - s.readType(t) + s.read_type(t) self.assertEqual(t.value, 1, "invalid stream read value") - self.assertEqual(s.dataLen(), 0, "not read all stream") + self.assertEqual(s.data_len(), 0, "not read all stream") def test_stream_read_uint24Le_type(self): """ @@ -225,9 +225,9 @@ class TypeTest(unittest.TestCase): """ s = rdpy.core.type.Stream('\x01\x00\x00') t = rdpy.core.type.UInt24Le() - s.readType(t) + s.read_type(t) self.assertEqual(t.value, 1, "invalid stream read value") - self.assertEqual(s.dataLen(), 0, "not read all stream") + self.assertEqual(s.data_len(), 0, "not read all stream") def test_stream_read_uint24Be_type(self): """ @@ -235,9 +235,9 @@ class TypeTest(unittest.TestCase): """ s = rdpy.core.type.Stream('\x00\x00\x01') t = rdpy.core.type.UInt24Be() - s.readType(t) + s.read_type(t) self.assertEqual(t.value, 1, "invalid stream read") - self.assertEqual(s.dataLen(), 0, "not read all stream") + self.assertEqual(s.data_len(), 0, "not read all stream") def test_stream_read_uint32Le_type(self): """ @@ -245,9 +245,9 @@ class TypeTest(unittest.TestCase): """ s = rdpy.core.type.Stream('\x01\x00\x00\x00') t = rdpy.core.type.UInt32Le() - s.readType(t) + s.read_type(t) self.assertEqual(t.value, 1, "invalid stream read value") - self.assertEqual(s.dataLen(), 0, "not read all stream") + self.assertEqual(s.data_len(), 0, "not read all stream") def test_stream_read_uint32Be_type(self): """ @@ -255,9 +255,9 @@ class TypeTest(unittest.TestCase): """ s = rdpy.core.type.Stream('\x00\x00\x00\x01') t = rdpy.core.type.UInt32Be() - s.readType(t) + s.read_type(t) self.assertEqual(t.value, 1, "invalid stream read") - self.assertEqual(s.dataLen(), 0, "not read all stream") + self.assertEqual(s.data_len(), 0, "not read all stream") def test_stream_read_optional_singletype(self): """ @@ -267,7 +267,7 @@ class TypeTest(unittest.TestCase): t = rdpy.core.type.SimpleType("I", 4, False, 0, optional = True) #empty stream s1 = rdpy.core.type.Stream() - s1.readType(t) + s1.read_type(t) self.assertEqual(t.value, 0, "invalid stream read optional value") def test_stream_read_conditional_singletype_false(self): @@ -277,7 +277,7 @@ class TypeTest(unittest.TestCase): #unsigned int case t = rdpy.core.type.SimpleType("I", 4, False, 0, conditional = lambda:False) s1 = rdpy.core.type.Stream("\x01\x00\x00\x00") - s1.readType(t) + s1.read_type(t) self.assertEqual(t.value, 0, "invalid stream read conditional value") def test_stream_read_conditional_singletype_true(self): @@ -287,7 +287,7 @@ class TypeTest(unittest.TestCase): #unsigned int case t = rdpy.core.type.SimpleType("I", 4, False, 0, conditional = lambda:True) s1 = rdpy.core.type.Stream("\x01\x00\x00\x00") - s1.readType(t) + s1.read_type(t) self.assertEqual(t.value, 1, "invalid stream read conditional value") def test_stream_read_rollback_constant_constraint(self): @@ -302,9 +302,9 @@ class TypeTest(unittest.TestCase): s = rdpy.core.type.Stream("\x00\x00\x00\x00\x00\x00\x00\x00") try: - s.readType(TestComposite()) + s.read_type(TestComposite()) except Exception: - self.assertEqual(s.readLen(), 0, "invalid stream roll back operation") + self.assertEqual(s.read_len(), 0, "invalid stream roll back operation") return self.assertTrue(False, "Constant constraint fail") @@ -327,9 +327,9 @@ class TypeTest(unittest.TestCase): s = rdpy.core.type.Stream("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") try: - s.readType(TestComposite()) + s.read_type(TestComposite()) except Exception: - self.assertEqual(s.readLen(), 0, "invalid stream roll back operation") + self.assertEqual(s.read_len(), 0, "invalid stream roll back operation") return self.assertTrue(False, "Constant constraint fail") @@ -352,9 +352,9 @@ class TypeTest(unittest.TestCase): s = rdpy.core.type.Stream("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") try: - s.readType(TestComposite()) + s.read_type(TestComposite()) except Exception: - self.assertEqual(s.readLen(), 0, "invalid stream roll back operation") + self.assertEqual(s.read_len(), 0, "invalid stream roll back operation") return self.assertTrue(False, "Constant constraint fail") @@ -369,8 +369,8 @@ class TypeTest(unittest.TestCase): rdpy.core.type.CompositeType.__init__(self, readLen = readLen) self.padding = rdpy.core.type.UInt32Le(0) s = rdpy.core.type.Stream("\x00" * 10) - s.readType(TestReadLength(rdpy.core.type.UInt8(10))) - self.assertEqual(s.dataLen(), 0, "invalid stream read trash data as padding") + s.read_type(TestReadLength(rdpy.core.type.UInt8(10))) + self.assertEqual(s.data_len(), 0, "invalid stream read trash data as padding") def test_stream_read_with_static_length_inferior(self): """ @@ -383,7 +383,7 @@ class TypeTest(unittest.TestCase): rdpy.core.type.CompositeType.__init__(self, readLen = readLen) self.padding = rdpy.core.type.UInt32Le(0) s = rdpy.core.type.Stream("\x00" * 10) - self.assertRaises(InvalidSize, s.readType, TestReadLength(rdpy.core.type.UInt8(2))) + self.assertRaises(InvalidSize, s.read_type, TestReadLength(rdpy.core.type.UInt8(2))) def test_stream_read_string(self): """ diff --git a/test/test_protocol_rdp_ber.py b/test/test_protocol_rdp_ber.py index 7e13b1f..105e66d 100644 --- a/test/test_protocol_rdp_ber.py +++ b/test/test_protocol_rdp_ber.py @@ -40,7 +40,7 @@ class BERTest(unittest.TestCase): @summary: test readLength function in ber module """ s1 = type.Stream() - s1.writeType(type.UInt8(0x1a)) + s1.write_type(type.UInt8(0x1a)) s1.pos = 0 l1 = ber.readLength(s1) @@ -48,7 +48,7 @@ class BERTest(unittest.TestCase): self.assertTrue(l1 == 0x1a, "readLength fail in small format") s2 = type.Stream() - s2.writeType((type.UInt8(0x81),type.UInt8(0xab))) + s2.write_type((type.UInt8(0x81), type.UInt8(0xab))) s2.pos = 0 l2 = ber.readLength(s2) @@ -56,7 +56,7 @@ class BERTest(unittest.TestCase): self.assertTrue(l2 == 0xab, "readLength fail in big format of size 1") s3 = type.Stream() - s3.writeType((type.UInt8(0x82),type.UInt16Be(0xabab))) + s3.write_type((type.UInt8(0x82), type.UInt16Be(0xabab))) s3.pos = 0 l3 = ber.readLength(s3) diff --git a/test/test_protocol_rdp_cssp_ntlm.py b/test/test_protocol_rdp_cssp_ntlm.py index 263b2f8..05fd2bb 100644 --- a/test/test_protocol_rdp_cssp_ntlm.py +++ b/test/test_protocol_rdp_cssp_ntlm.py @@ -73,25 +73,25 @@ class TestCsspNtlm(unittest.TestCase): @summary: test generate ntlmv2 over cssp authentication protocol """ def testCSSPNTLMAuthentication(self): - negotiate_data_request = cssp.decodeDERTRequest(peer0_0.decode('base64')) - challenge_data_request = cssp.decodeDERTRequest(peer1_0.decode('base64')) - authenticate_data_request = cssp.decodeDERTRequest(peer0_1.decode('base64')) + negotiate_data_request = cssp.decode_der_trequest(peer0_0.decode('base64')) + challenge_data_request = cssp.decode_der_trequest(peer1_0.decode('base64')) + authenticate_data_request = cssp.decode_der_trequest(peer0_1.decode('base64')) negotiate_data = cssp.getNegoTokens(negotiate_data_request)[0] challenge_data = cssp.getNegoTokens(challenge_data_request)[0] authenticate_data = cssp.getNegoTokens(authenticate_data_request)[0] negotiate = ntlm.NegotiateMessage() - negotiate_data.readType(negotiate) + negotiate_data.read_type(negotiate) challenge = ntlm.ChallengeMessage() - challenge_data.readType(challenge) + challenge_data.read_type(challenge) ServerChallenge = challenge.ServerChallenge.value ServerName = challenge.getTargetInfo() authenticate = ntlm.AuthenticateMessage() - authenticate_data.readType(authenticate) + authenticate_data.read_type(authenticate) NtChallengeResponseTemp = authenticate.getNtChallengeResponse() NTProofStr = NtChallengeResponseTemp[:16] diff --git a/test/test_protocol_rdp_lic.py b/test/test_protocol_rdp_lic.py index e48850f..fb4105b 100644 --- a/test/test_protocol_rdp_lic.py +++ b/test/test_protocol_rdp_lic.py @@ -91,7 +91,7 @@ class TestLic(unittest.TestCase): def test_valid_client_licensing_error_message(self): l = lic.LicenseManager(None) s = type.Stream() - s.writeType(lic.createValidClientLicensingErrorMessage()) + s.write_type(lic.createValidClientLicensingErrorMessage()) #reinit position s.pos = 0 @@ -105,9 +105,9 @@ class TestLic(unittest.TestCase): if flag != sec.SecurityFlag.SEC_LICENSE_PKT: return s = type.Stream() - s.writeType(message) + s.write_type(message) s.pos = 0 - s.readType(lic.LicPacket(lic.ClientNewLicenseRequest())) + s.read_type(lic.LicPacket(lic.ClientNewLicenseRequest())) self._state = True def getGCCServerSettings(self): class A: diff --git a/test/test_protocol_rdp_per.py b/test/test_protocol_rdp_per.py index 9b336fb..5ab0fdb 100644 --- a/test/test_protocol_rdp_per.py +++ b/test/test_protocol_rdp_per.py @@ -40,7 +40,7 @@ class PERTest(unittest.TestCase): @summary: test readLength function in per module """ s1 = type.Stream() - s1.writeType(type.UInt8(0x1a)) + s1.write_type(type.UInt8(0x1a)) s1.pos = 0 l1 = per.readLength(s1) @@ -48,7 +48,7 @@ class PERTest(unittest.TestCase): self.assertTrue(l1 == 0x1a, "readLength fail in small format") s2 = type.Stream() - s2.writeType(type.UInt16Be(0x1abc | 0x8000)) + s2.write_type(type.UInt16Be(0x1abc | 0x8000)) s2.pos = 0 l2 = per.readLength(s2) @@ -78,7 +78,7 @@ class PERTest(unittest.TestCase): for t in [type.UInt8, type.UInt16Be, type.UInt32Be]: v = t(3) s = type.Stream() - s.writeType((per.writeLength(type.sizeof(v)), v)) + s.write_type((per.writeLength(type.sizeof(v)), v)) s.pos = 0 self.assertTrue(per.readInteger(s) == 3, "invalid readLength for type %s" % t) @@ -86,7 +86,7 @@ class PERTest(unittest.TestCase): #error case for l in [0, 3, 5]: s = type.Stream() - s.writeType(per.writeLength(l)) + s.write_type(per.writeLength(l)) s.pos = 0 self.assertRaises(error.InvalidValue, per.readInteger, s) diff --git a/test/test_protocol_rdp_tpkt.py b/test/test_protocol_rdp_tpkt.py index ab5fe76..e1822ad 100644 --- a/test/test_protocol_rdp_tpkt.py +++ b/test/test_protocol_rdp_tpkt.py @@ -60,13 +60,13 @@ class TPKTTest(unittest.TestCase): def connect(self): pass def recv(self, data): - data.readType(type.String("test_tpkt_layer_recv", constant = True)) + data.read_type(type.String("test_tpkt_layer_recv", constant = True)) raise TPKTTest.TPKT_PASS() message = type.String("test_tpkt_layer_recv") s = type.Stream() - s.writeType((type.UInt8(tpkt.Action.FASTPATH_ACTION_X224), type.UInt8(), type.UInt16Be(type.sizeof(message) + 4), message)) + s.write_type((type.UInt8(tpkt.Action.FASTPATH_ACTION_X224), type.UInt8(), type.UInt16Be(type.sizeof(message) + 4), message)) layer = tpkt.TPKT(Presentation()) layer.connect() @@ -80,13 +80,13 @@ class TPKTTest(unittest.TestCase): def setFastPathSender(self, fastPathSender): pass def recvFastPath(self, secFlag, fastPathS): - fastPathS.readType(type.String("test_tpkt_layer_recv_fastpath", constant = True)) + fastPathS.read_type(type.String("test_tpkt_layer_recv_fastpath", constant = True)) raise TPKTTest.TPKT_PASS() message = type.String("test_tpkt_layer_recv_fastpath") s = type.Stream() - s.writeType((type.UInt8(tpkt.Action.FASTPATH_ACTION_FASTPATH), type.UInt8(type.sizeof(message) + 2), message)) + s.write_type((type.UInt8(tpkt.Action.FASTPATH_ACTION_FASTPATH), type.UInt8(type.sizeof(message) + 2), message)) layer = tpkt.TPKT(None) layer.initFastPath(FastPathLayer()) @@ -101,13 +101,13 @@ class TPKTTest(unittest.TestCase): def setFastPathSender(self, fastPathSender): pass def recvFastPath(self, secflag, fastPathS): - fastPathS.readType(type.String("test_tpkt_layer_recv_fastpath_ext_length", constant = True)) + fastPathS.read_type(type.String("test_tpkt_layer_recv_fastpath_ext_length", constant = True)) raise TPKTTest.TPKT_PASS() message = type.String("test_tpkt_layer_recv_fastpath_ext_length") s = type.Stream() - s.writeType((type.UInt8(tpkt.Action.FASTPATH_ACTION_FASTPATH), type.UInt16Be((type.sizeof(message) + 3) | 0x8000), message)) + s.write_type((type.UInt8(tpkt.Action.FASTPATH_ACTION_FASTPATH), type.UInt16Be((type.sizeof(message) + 3) | 0x8000), message)) layer = tpkt.TPKT(None) layer.initFastPath(FastPathLayer()) diff --git a/test/test_protocol_rdp_x224.py b/test/test_protocol_rdp_x224.py index d6e33db..a60de79 100644 --- a/test/test_protocol_rdp_x224.py +++ b/test/test_protocol_rdp_x224.py @@ -53,12 +53,12 @@ class X224Test(unittest.TestCase): """ class Presentation(object): def recv(self, data): - data.readType(type.String('test_x224_layer_recvData', constant = True)) + data.read_type(type.String('test_x224_layer_recvData', constant = True)) raise X224Test.X224_PASS() layer = x224.X224Layer(Presentation()) s = type.Stream() - s.writeType((x224.X224DataHeader(), type.String('test_x224_layer_recvData'))) + s.write_type((x224.X224DataHeader(), type.String('test_x224_layer_recvData'))) #reinit position s.pos = 0 @@ -71,10 +71,10 @@ class X224Test(unittest.TestCase): class Transport(object): def send(self, data): s = type.Stream() - s.writeType(data) + s.write_type(data) s.pos = 0 - s.readType(x224.X224DataHeader()) - s.readType(type.String('test_x224_layer_send', constant = True)) + s.read_type(x224.X224DataHeader()) + s.read_type(type.String('test_x224_layer_send', constant = True)) raise X224Test.X224_PASS() layer = x224.X224Layer(None) @@ -89,10 +89,10 @@ class X224Test(unittest.TestCase): class Transport(object): def send(self, data): s = type.Stream() - s.writeType(data) + s.write_type(data) s.pos = 0 t = x224.ClientConnectionRequestPDU() - s.readType(t) + s.read_type(t) if t.protocolNeg.code != x224.NegociationType.TYPE_RDP_NEG_REQ: raise X224Test.X224_FAIL() @@ -115,7 +115,7 @@ class X224Test(unittest.TestCase): message = x224.ServerConnectionConfirm() message.protocolNeg.code.value = x224.NegociationType.TYPE_RDP_NEG_FAILURE s = type.Stream() - s.writeType(message) + s.write_type(message) s.pos = 0 layer = x224.Client(None) self.assertRaises(error.RDPSecurityNegoFail, layer.recvConnectionConfirm, s) @@ -145,7 +145,7 @@ class X224Test(unittest.TestCase): message.protocolNeg.selectedProtocol.value = x224.Protocols.PROTOCOL_SSL s = type.Stream() - s.writeType(message) + s.write_type(message) s.pos = 0 layer = x224.Client(Presentation()) layer._transport = Transport() @@ -175,7 +175,7 @@ class X224Test(unittest.TestCase): message = x224.ClientConnectionRequestPDU() message.protocolNeg.selectedProtocol.value = x224.Protocols.PROTOCOL_HYBRID s = type.Stream() - s.writeType(message) + s.write_type(message) s.pos = 0 layer = x224.Server(None, "key", "cert", True) @@ -217,7 +217,7 @@ class X224Test(unittest.TestCase): message = x224.ClientConnectionRequestPDU() message.protocolNeg.selectedProtocol.value = x224.Protocols.PROTOCOL_SSL | x224.Protocols.PROTOCOL_RDP s = type.Stream() - s.writeType(message) + s.write_type(message) s.pos = 0 layer = x224.Server(Presentation(), "key", "cert")