Compare commits
7 Commits
bd7c708bf3
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1e2cf2ef88 | ||
|
|
040ac6185d | ||
|
|
0f30de7d20 | ||
|
|
a23ae25a1f | ||
|
|
763ed2e3ee | ||
|
|
11d66a4818 | ||
|
|
9b99365f80 |
@@ -181,6 +181,11 @@ class MyRDPFactory(rdp.ClientFactory):
|
||||
@param isCompress: use RLE compression
|
||||
@param data: bitmap data
|
||||
"""
|
||||
|
||||
def onSessionReady(self):
|
||||
"""
|
||||
@summary: Windows session is ready
|
||||
"""
|
||||
|
||||
def onClose(self):
|
||||
"""
|
||||
|
||||
@@ -172,7 +172,7 @@ class RDPClientQtFactory(rdp.ClientFactory):
|
||||
connector.connect()
|
||||
return
|
||||
|
||||
QtGui.QMessageBox.warning(self._w, "Warning", "Lost connection : %s"%reason)
|
||||
log.info("Lost connection : %s"%reason)
|
||||
reactor.stop()
|
||||
app.exit()
|
||||
|
||||
@@ -182,7 +182,7 @@ class RDPClientQtFactory(rdp.ClientFactory):
|
||||
@param connector: twisted connector use for rdp connection (use reconnect to restart connection)
|
||||
@param reason: str use to advertise reason of lost connection
|
||||
"""
|
||||
QtGui.QMessageBox.warning(self._w, "Warning", "Connection failed : %s"%reason)
|
||||
log.info("Connection failed : %s"%reason)
|
||||
reactor.stop()
|
||||
app.exit()
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ class HoneyPotServer(rdp.RDPServerObserver):
|
||||
def onClose(self):
|
||||
""" HoneyPot """
|
||||
|
||||
def onKeyEventScancode(self, code, isPressed):
|
||||
def onKeyEventScancode(self, code, isPressed, isExtended):
|
||||
""" HoneyPot """
|
||||
|
||||
def onKeyEventUnicode(self, code, isPressed):
|
||||
|
||||
@@ -92,16 +92,17 @@ class ProxyServer(rdp.RDPServerObserver):
|
||||
return
|
||||
self._client._controller.close()
|
||||
|
||||
def onKeyEventScancode(self, code, isPressed):
|
||||
def onKeyEventScancode(self, code, isPressed, isExtended):
|
||||
"""
|
||||
@summary: Event call when a keyboard event is catch in scan code format
|
||||
@param code: {int} scan code of key
|
||||
@param isPressed: {bool} True if key is down
|
||||
@param code: {integer} scan code of key
|
||||
@param isPressed: {boolean} True if key is down
|
||||
@param isExtended: {boolean} True if a special key
|
||||
@see: rdp.RDPServerObserver.onKeyEventScancode
|
||||
"""
|
||||
if self._client is None:
|
||||
return
|
||||
self._client._controller.sendKeyEventScancode(code, isPressed)
|
||||
self._client._controller.sendKeyEventScancode(code, isPressed, isExtended)
|
||||
self._rss.keyScancode(code, isPressed)
|
||||
|
||||
def onKeyEventUnicode(self, code, isPressed):
|
||||
@@ -178,6 +179,13 @@ class ProxyClient(rdp.RDPClientObserver):
|
||||
#maybe color depth change
|
||||
self._server._controller.setColorDepth(self._controller.getColorDepth())
|
||||
|
||||
def onSessionReady(self):
|
||||
"""
|
||||
@summary: Windows session is ready
|
||||
@see: rdp.RDPClientObserver.onSessionReady
|
||||
"""
|
||||
pass
|
||||
|
||||
def onClose(self):
|
||||
"""
|
||||
@summary: Event inform that stack is close
|
||||
|
||||
@@ -136,6 +136,13 @@ class RDPScreenShotFactory(rdp.ClientFactory):
|
||||
"""
|
||||
log.info("connected %s"%addr)
|
||||
|
||||
def onSessionReady(self):
|
||||
"""
|
||||
@summary: Windows session is ready
|
||||
@see: rdp.RDPClientObserver.onSessionReady
|
||||
"""
|
||||
pass
|
||||
|
||||
def onClose(self):
|
||||
"""
|
||||
@summary: callback use when RDP stack is closed
|
||||
|
||||
@@ -477,7 +477,7 @@ class CompositeType(Type):
|
||||
raise e
|
||||
|
||||
if not self._readLen is None and readLen < self._readLen.value:
|
||||
log.debug("Still have correct data in packet %s, read it as padding"%self.__class__)
|
||||
log.debug("Still have correct data in packet %s, read %s bytes as padding"%(self.__class__, self._readLen.value - readLen))
|
||||
s.read(self._readLen.value - readLen)
|
||||
|
||||
def __write__(self, s):
|
||||
|
||||
@@ -234,7 +234,7 @@ class LicPacket(CompositeType):
|
||||
if self.bMsgtype.value == c._MESSAGE_TYPE_:
|
||||
return c(readLen = self.wMsgSize - 4)
|
||||
log.debug("unknown license message : %s"%self.bMsgtype.value)
|
||||
return String()
|
||||
return String(readLen = self.wMsgSize - 4)
|
||||
|
||||
if message is None:
|
||||
message = FactoryType(LicensingMessageFactory)
|
||||
|
||||
@@ -202,6 +202,16 @@ class Display(object):
|
||||
SUPPRESS_DISPLAY_UPDATES = 0x00
|
||||
ALLOW_DISPLAY_UPDATES = 0x01
|
||||
|
||||
class ToogleFlag(object):
|
||||
"""
|
||||
@summary: Use to known state of keyboard
|
||||
@see: https://msdn.microsoft.com/en-us/library/cc240588.aspx
|
||||
"""
|
||||
TS_SYNC_SCROLL_LOCK = 0x00000001
|
||||
TS_SYNC_NUM_LOCK = 0x00000002
|
||||
TS_SYNC_CAPS_LOCK = 0x00000004
|
||||
TS_SYNC_KANA_LOCK = 0x00000008
|
||||
|
||||
class ErrorInfo(object):
|
||||
"""
|
||||
@summary: Error code use in Error info PDU
|
||||
@@ -413,8 +423,6 @@ class ErrorInfo(object):
|
||||
ERRINFO_VCDATATOOLONG : "The size of a received Virtual Channel PDU (section 2.2.6.1) exceeds the chunking size specified in the Virtual Channel Capability Set (section 2.2.7.1.10).",
|
||||
}
|
||||
|
||||
|
||||
|
||||
class ShareControlHeader(CompositeType):
|
||||
"""
|
||||
@summary: PDU share control header
|
||||
@@ -461,10 +469,10 @@ class PDU(CompositeType):
|
||||
"""
|
||||
for c in [DemandActivePDU, ConfirmActivePDU, DataPDU, DeactiveAllPDU]:
|
||||
if self.shareControlHeader.pduType.value == c._PDUTYPE_:
|
||||
return c()
|
||||
return c(readLen = CallableValue(self.shareControlHeader.totalLength.value - sizeof(self.shareControlHeader)))
|
||||
log.debug("unknown PDU type : %s"%hex(self.shareControlHeader.pduType.value))
|
||||
#read entire packet
|
||||
return String()
|
||||
return String(readLen = CallableValue(self.shareControlHeader.totalLength.value - sizeof(self.shareControlHeader)))
|
||||
|
||||
if pduMessage is None:
|
||||
pduMessage = FactoryType(PDUMessageFactory)
|
||||
@@ -481,8 +489,8 @@ class DemandActivePDU(CompositeType):
|
||||
#may declare the PDU type
|
||||
_PDUTYPE_ = PDUType.PDUTYPE_DEMANDACTIVEPDU
|
||||
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.shareId = UInt32Le()
|
||||
self.lengthSourceDescriptor = UInt16Le(lambda:sizeof(self.sourceDescriptor))
|
||||
self.lengthCombinedCapabilities = UInt16Le(lambda:(sizeof(self.numberCapabilities) + sizeof(self.pad2Octets) + sizeof(self.capabilitySets)))
|
||||
@@ -500,8 +508,8 @@ class ConfirmActivePDU(CompositeType):
|
||||
#may declare the PDU type
|
||||
_PDUTYPE_ = PDUType.PDUTYPE_CONFIRMACTIVEPDU
|
||||
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.shareId = UInt32Le()
|
||||
self.originatorId = UInt16Le(0x03EA, constant = True)
|
||||
self.lengthSourceDescriptor = UInt16Le(lambda:sizeof(self.sourceDescriptor))
|
||||
@@ -519,10 +527,10 @@ class DeactiveAllPDU(CompositeType):
|
||||
#may declare the PDU type
|
||||
_PDUTYPE_ = PDUType.PDUTYPE_DEACTIVATEALLPDU
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, readLen = None):
|
||||
#in old version this packet is empty i don't know
|
||||
#and not specified
|
||||
CompositeType.__init__(self, optional = True)
|
||||
CompositeType.__init__(self, optional = True, readLen = readLen)
|
||||
self.shareId = UInt32Le()
|
||||
self.lengthSourceDescriptor = UInt16Le(lambda:sizeof(self.sourceDescriptor))
|
||||
self.sourceDescriptor = String("rdpy", readLen = self.lengthSourceDescriptor)
|
||||
@@ -534,19 +542,19 @@ class DataPDU(CompositeType):
|
||||
#may declare the PDU type
|
||||
_PDUTYPE_ = PDUType.PDUTYPE_DATAPDU
|
||||
|
||||
def __init__(self, pduData = None, shareId = 0):
|
||||
CompositeType.__init__(self)
|
||||
def __init__(self, pduData = None, shareId = 0, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.shareDataHeader = ShareDataHeader(lambda:sizeof(self), lambda:self.pduData.__class__._PDUTYPE2_, shareId)
|
||||
|
||||
def PDUDataFactory():
|
||||
"""
|
||||
@summary: Create object in accordance self.shareDataHeader.pduType2 value
|
||||
"""
|
||||
for c in [UpdateDataPDU, SynchronizeDataPDU, ControlDataPDU, ErrorInfoDataPDU, FontListDataPDU, FontMapDataPDU, PersistentListPDU, ClientInputEventPDU, ShutdownDeniedPDU, ShutdownRequestPDU, SupressOutputDataPDU]:
|
||||
for c in [UpdateDataPDU, SynchronizeDataPDU, ControlDataPDU, ErrorInfoDataPDU, FontListDataPDU, FontMapDataPDU, PersistentListPDU, ClientInputEventPDU, ShutdownDeniedPDU, ShutdownRequestPDU, SupressOutputDataPDU, SaveSessionInfoPDU]:
|
||||
if self.shareDataHeader.pduType2.value == c._PDUTYPE2_:
|
||||
return c()
|
||||
return c(readLen = CallableValue(readLen.value - sizeof(self.shareDataHeader)))
|
||||
log.debug("unknown PDU data type : %s"%hex(self.shareDataHeader.pduType2.value))
|
||||
return String()
|
||||
return String(readLen = CallableValue(readLen.value - sizeof(self.shareDataHeader)))
|
||||
|
||||
if pduData is None:
|
||||
pduData = FactoryType(PDUDataFactory)
|
||||
@@ -655,8 +663,8 @@ class PersistentListPDU(CompositeType):
|
||||
"""
|
||||
_PDUTYPE2_ = PDUType2.PDUTYPE2_BITMAPCACHE_PERSISTENT_LIST
|
||||
|
||||
def __init__(self, userId = 0, shareId = 0):
|
||||
CompositeType.__init__(self)
|
||||
def __init__(self, userId = 0, shareId = 0, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.numEntriesCache0 = UInt16Le()
|
||||
self.numEntriesCache1 = UInt16Le()
|
||||
self.numEntriesCache2 = UInt16Le()
|
||||
@@ -679,8 +687,8 @@ class ClientInputEventPDU(CompositeType):
|
||||
"""
|
||||
_PDUTYPE2_ = PDUType2.PDUTYPE2_INPUT
|
||||
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.numEvents = UInt16Le(lambda:len(self.slowPathInputEvents._array))
|
||||
self.pad2Octets = UInt16Le()
|
||||
self.slowPathInputEvents = ArrayType(SlowPathInputEvent, readLen = self.numEvents)
|
||||
@@ -691,8 +699,8 @@ class ShutdownRequestPDU(CompositeType):
|
||||
client -> server
|
||||
"""
|
||||
_PDUTYPE2_ = PDUType2.PDUTYPE2_SHUTDOWN_REQUEST
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
|
||||
class ShutdownDeniedPDU(CompositeType):
|
||||
"""
|
||||
@@ -700,8 +708,8 @@ class ShutdownDeniedPDU(CompositeType):
|
||||
server -> client
|
||||
"""
|
||||
_PDUTYPE2_ = PDUType2.PDUTYPE2_SHUTDOWN_DENIED
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
|
||||
class InclusiveRectangle(CompositeType):
|
||||
"""
|
||||
@@ -761,9 +769,9 @@ class UpdateDataPDU(CompositeType):
|
||||
"""
|
||||
for c in [BitmapUpdateDataPDU]:
|
||||
if self.updateType.value == c._UPDATE_TYPE_:
|
||||
return c()
|
||||
return c(readLen = CallableValue(readLen.value - 2))
|
||||
log.debug("unknown PDU update data type : %s"%hex(self.updateType.value))
|
||||
return String()
|
||||
return String(readLen = CallableValue(readLen.value - 2))
|
||||
|
||||
if updateData is None:
|
||||
updateData = FactoryType(UpdateDataFactory, conditional = lambda:(self.updateType.value != UpdateType.UPDATETYPE_SYNCHRONIZE))
|
||||
@@ -771,7 +779,19 @@ class UpdateDataPDU(CompositeType):
|
||||
raise InvalidExpectedDataException("Try to send an invalid data update PDU")
|
||||
|
||||
self.updateData = updateData
|
||||
|
||||
|
||||
class SaveSessionInfoPDU(CompositeType):
|
||||
"""
|
||||
@see: https://msdn.microsoft.com/en-us/library/cc240636.aspx
|
||||
"""
|
||||
_PDUTYPE2_ = PDUType2.PDUTYPE2_SAVE_SESSION_INFO
|
||||
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.infoType = UInt32Le()
|
||||
#TODO parse info data
|
||||
self.infoData = String()
|
||||
|
||||
class FastPathUpdatePDU(CompositeType):
|
||||
"""
|
||||
@summary: Fast path update PDU packet
|
||||
@@ -789,9 +809,9 @@ class FastPathUpdatePDU(CompositeType):
|
||||
"""
|
||||
for c in [FastPathBitmapUpdateDataPDU]:
|
||||
if (self.updateHeader.value & 0xf) == c._FASTPATH_UPDATE_TYPE_:
|
||||
return c()
|
||||
return c(readLen = self.size)
|
||||
log.debug("unknown Fast Path PDU update data type : %s"%hex(self.updateHeader.value & 0xf))
|
||||
return String()
|
||||
return String(readLen = self.size)
|
||||
|
||||
if updateData is None:
|
||||
updateData = FactoryType(UpdateDataFactory)
|
||||
@@ -821,8 +841,8 @@ class OrderUpdateDataPDU(CompositeType):
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc241571.aspx
|
||||
@todo: not implemented yet but need it
|
||||
"""
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.pad2OctetsA = UInt16Le()
|
||||
self.numberOrders = UInt16Le(lambda:len(self.orderData._array))
|
||||
self.pad2OctetsB = UInt16Le()
|
||||
@@ -882,8 +902,8 @@ class FastPathBitmapUpdateDataPDU(CompositeType):
|
||||
"""
|
||||
_FASTPATH_UPDATE_TYPE_ = FastPathUpdateType.FASTPATH_UPDATETYPE_BITMAP
|
||||
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
def __init__(self, readLen = None):
|
||||
CompositeType.__init__(self, readLen = readLen)
|
||||
self.header = UInt16Le(FastPathUpdateType.FASTPATH_UPDATETYPE_BITMAP, constant = True)
|
||||
self.numberRectangles = UInt16Le(lambda:len(self.rectangles._array))
|
||||
self.rectangles = ArrayType(BitmapData, readLen = self.numberRectangles)
|
||||
@@ -899,11 +919,10 @@ class SlowPathInputEvent(CompositeType):
|
||||
self.messageType = UInt16Le(lambda:self.slowPathInputData.__class__._INPUT_MESSAGE_TYPE_)
|
||||
|
||||
def SlowPathInputDataFactory():
|
||||
for c in [PointerEvent, ScancodeKeyEvent, UnicodeKeyEvent]:
|
||||
for c in [PointerEvent, ScancodeKeyEvent, UnicodeKeyEvent, SynchronizeEvent]:
|
||||
if self.messageType.value == c._INPUT_MESSAGE_TYPE_:
|
||||
return c()
|
||||
log.debug("unknown slow path input : %s"%hex(self.messageType.value))
|
||||
return String()
|
||||
raise InvalidExpectedDataException("unknown slow path input : %s"%hex(self.messageType.value))
|
||||
|
||||
if messageData is None:
|
||||
messageData = FactoryType(SlowPathInputDataFactory)
|
||||
@@ -911,7 +930,19 @@ class SlowPathInputEvent(CompositeType):
|
||||
raise InvalidExpectedDataException("try to send an invalid Slow Path Input Event")
|
||||
|
||||
self.slowPathInputData = messageData
|
||||
|
||||
|
||||
class SynchronizeEvent(CompositeType):
|
||||
"""
|
||||
@summary: Synchronize keyboard
|
||||
@see: https://msdn.microsoft.com/en-us/library/cc240588.aspx
|
||||
"""
|
||||
_INPUT_MESSAGE_TYPE_ = InputMessageType.INPUT_EVENT_SYNC
|
||||
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
self.pad2Octets = UInt16Le()
|
||||
self.toggleFlags = UInt32Le()
|
||||
|
||||
class PointerEvent(CompositeType):
|
||||
"""
|
||||
@summary: Event use to communicate mouse position
|
||||
|
||||
@@ -25,6 +25,7 @@ In this layer are managed all mains bitmap update orders end user inputs
|
||||
|
||||
from rdpy.core.layer import LayerAutomata
|
||||
from rdpy.core.error import CallPureVirtualFuntion
|
||||
from rdpy.core.type import ArrayType
|
||||
import rdpy.core.log as log
|
||||
import rdpy.protocol.rdp.tpkt as tpkt
|
||||
import data, caps
|
||||
@@ -39,6 +40,13 @@ class PDUClientListener(object):
|
||||
"""
|
||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onReady", "PDUClientListener"))
|
||||
|
||||
def onSessionReady(self):
|
||||
"""
|
||||
@summary: Event call when Windows session is ready
|
||||
"""
|
||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onSessionReady", "PDUClientListener"))
|
||||
|
||||
|
||||
def onUpdate(self, rectangles):
|
||||
"""
|
||||
@summary: call when a bitmap data is received from update PDU
|
||||
@@ -259,15 +267,16 @@ class Client(PDULayer):
|
||||
@summary: Main receive function after connection sequence
|
||||
@param s: Stream from transport layer
|
||||
"""
|
||||
pdu = data.PDU()
|
||||
s.readType(pdu)
|
||||
if pdu.shareControlHeader.pduType.value == data.PDUType.PDUTYPE_DATAPDU:
|
||||
self.readDataPDU(pdu.pduMessage)
|
||||
elif pdu.shareControlHeader.pduType.value == data.PDUType.PDUTYPE_DEACTIVATEALLPDU:
|
||||
#use in deactivation-reactivation sequence
|
||||
#next state is either a capabilities re exchange or disconnection
|
||||
#http://msdn.microsoft.com/en-us/library/cc240454.aspx
|
||||
self.setNextState(self.recvDemandActivePDU)
|
||||
pdus = ArrayType(data.PDU)
|
||||
s.readType(pdus)
|
||||
for pdu in pdus:
|
||||
if pdu.shareControlHeader.pduType.value == data.PDUType.PDUTYPE_DATAPDU:
|
||||
self.readDataPDU(pdu.pduMessage)
|
||||
elif pdu.shareControlHeader.pduType.value == data.PDUType.PDUTYPE_DEACTIVATEALLPDU:
|
||||
#use in deactivation-reactivation sequence
|
||||
#next state is either a capabilities re exchange or disconnection
|
||||
#http://msdn.microsoft.com/en-us/library/cc240454.aspx
|
||||
self.setNextState(self.recvDemandActivePDU)
|
||||
|
||||
def recvFastPath(self, secFlag, fastPathS):
|
||||
"""
|
||||
@@ -276,11 +285,12 @@ class Client(PDULayer):
|
||||
@param fastPathS: {Stream} that contain fast path data
|
||||
@param secFlag: {SecFlags}
|
||||
"""
|
||||
fastPathPDU = data.FastPathUpdatePDU()
|
||||
fastPathS.readType(fastPathPDU)
|
||||
if fastPathPDU.updateHeader.value == data.FastPathUpdateType.FASTPATH_UPDATETYPE_BITMAP:
|
||||
self._listener.onUpdate(fastPathPDU.updateData.rectangles._array)
|
||||
|
||||
updates = ArrayType(data.FastPathUpdatePDU)
|
||||
fastPathS.readType(updates)
|
||||
for update in updates:
|
||||
if update.updateHeader.value == data.FastPathUpdateType.FASTPATH_UPDATETYPE_BITMAP:
|
||||
self._listener.onUpdate(update.updateData.rectangles._array)
|
||||
|
||||
def readDataPDU(self, dataPDU):
|
||||
"""
|
||||
@summary: read a data PDU object
|
||||
@@ -298,6 +308,9 @@ class Client(PDULayer):
|
||||
elif dataPDU.shareDataHeader.pduType2.value == data.PDUType2.PDUTYPE2_SHUTDOWN_DENIED:
|
||||
#may be an event to ask to user
|
||||
self._transport.close()
|
||||
elif dataPDU.shareDataHeader.pduType2.value == data.PDUType2.PDUTYPE2_SAVE_SESSION_INFO:
|
||||
#handle session event
|
||||
self._listener.onSessionReady()
|
||||
elif dataPDU.shareDataHeader.pduType2.value == data.PDUType2.PDUTYPE2_UPDATE:
|
||||
self.readUpdateDataPDU(dataPDU.pduData)
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ class RDPClientController(pdu.layer.PDUClientListener):
|
||||
def setUsername(self, username):
|
||||
"""
|
||||
@summary: Set the username for session
|
||||
@param username: username of session
|
||||
@param username: {string} username of session
|
||||
"""
|
||||
#username in PDU info packet
|
||||
self._secLayer._info.userName.value = username
|
||||
@@ -109,7 +109,7 @@ class RDPClientController(pdu.layer.PDUClientListener):
|
||||
def setPassword(self, password):
|
||||
"""
|
||||
@summary: Set password for session
|
||||
@param password: password of session
|
||||
@param password: {string} password of session
|
||||
"""
|
||||
self.setAutologon()
|
||||
self._secLayer._info.password.value = password
|
||||
@@ -117,7 +117,7 @@ class RDPClientController(pdu.layer.PDUClientListener):
|
||||
def setDomain(self, domain):
|
||||
"""
|
||||
@summary: Set the windows domain of session
|
||||
@param domain: domain of session
|
||||
@param domain: {string} domain of session
|
||||
"""
|
||||
self._secLayer._info.domain.value = domain
|
||||
|
||||
@@ -127,6 +127,13 @@ class RDPClientController(pdu.layer.PDUClientListener):
|
||||
"""
|
||||
self._secLayer._info.flag |= sec.InfoFlag.INFO_AUTOLOGON
|
||||
|
||||
def setAlternateShell(self, appName):
|
||||
"""
|
||||
@summary: set application name of app which start at the begining of session
|
||||
@param appName: {string} application name
|
||||
"""
|
||||
self._secLayer._info.alternateShell.value = appName
|
||||
|
||||
def setKeyboardLayout(self, layout):
|
||||
"""
|
||||
@summary: keyboard layout
|
||||
@@ -192,6 +199,15 @@ class RDPClientController(pdu.layer.PDUClientListener):
|
||||
for observer in self._clientObserver:
|
||||
observer.onReady()
|
||||
|
||||
def onSessionReady(self):
|
||||
"""
|
||||
@summary: Call when Windows session is ready (connected)
|
||||
"""
|
||||
self._isReady = True
|
||||
#signal all listener
|
||||
for observer in self._clientObserver:
|
||||
observer.onSessionReady()
|
||||
|
||||
def onClose(self):
|
||||
"""
|
||||
@summary: Event call when RDP stack is closed
|
||||
@@ -269,11 +285,12 @@ class RDPClientController(pdu.layer.PDUClientListener):
|
||||
except InvalidValue:
|
||||
log.info("try send wheel event with incorrect position")
|
||||
|
||||
def sendKeyEventScancode(self, code, isPressed):
|
||||
def sendKeyEventScancode(self, code, isPressed, extended = False):
|
||||
"""
|
||||
@summary: Send a scan code to RDP stack
|
||||
@param code: scan code
|
||||
@param isPressed: True if key is pressed and false if it's released
|
||||
@param extended: {boolean} extended scancode like ctr or win button
|
||||
"""
|
||||
if not self._isReady:
|
||||
return
|
||||
@@ -281,11 +298,12 @@ class RDPClientController(pdu.layer.PDUClientListener):
|
||||
try:
|
||||
event = pdu.data.ScancodeKeyEvent()
|
||||
event.keyCode.value = code
|
||||
if isPressed:
|
||||
event.keyboardFlags.value |= pdu.data.KeyboardFlag.KBDFLAGS_DOWN
|
||||
else:
|
||||
if not isPressed:
|
||||
event.keyboardFlags.value |= pdu.data.KeyboardFlag.KBDFLAGS_RELEASE
|
||||
|
||||
if extended:
|
||||
event.keyboardFlags.value |= pdu.data.KeyboardFlag.KBDFLAGS_EXTENDED
|
||||
|
||||
#send event
|
||||
self._pduLayer.sendInputEvents([event])
|
||||
|
||||
@@ -478,7 +496,7 @@ class RDPServerController(pdu.layer.PDUServerListener):
|
||||
for event in slowPathInputEvents:
|
||||
#scan code
|
||||
if event.messageType.value == pdu.data.InputMessageType.INPUT_EVENT_SCANCODE:
|
||||
observer.onKeyEventScancode(event.slowPathInputData.keyCode.value, not (event.slowPathInputData.keyboardFlags.value & pdu.data.KeyboardFlag.KBDFLAGS_RELEASE))
|
||||
observer.onKeyEventScancode(event.slowPathInputData.keyCode.value, not (event.slowPathInputData.keyboardFlags.value & pdu.data.KeyboardFlag.KBDFLAGS_RELEASE), bool(event.slowPathInputData.keyboardFlags.value & pdu.data.KeyboardFlag.KBDFLAGS_EXTENDED))
|
||||
#unicode
|
||||
elif event.messageType.value == pdu.data.InputMessageType.INPUT_EVENT_UNICODE:
|
||||
observer.onKeyEventUnicode(event.slowPathInputData.unicode.value, not (event.slowPathInputData.keyboardFlags.value & pdu.data.KeyboardFlag.KBDFLAGS_RELEASE))
|
||||
@@ -607,6 +625,12 @@ class RDPClientObserver(object):
|
||||
"""
|
||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onReady", "RDPClientObserver"))
|
||||
|
||||
def onSessionReady(self):
|
||||
"""
|
||||
@summary: Windows session is ready
|
||||
"""
|
||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onSessionReady", "RDPClientObserver"))
|
||||
|
||||
def onClose(self):
|
||||
"""
|
||||
@summary: Stack is closes
|
||||
@@ -652,11 +676,12 @@ class RDPServerObserver(object):
|
||||
"""
|
||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onClose", "RDPClientObserver"))
|
||||
|
||||
def onKeyEventScancode(self, code, isPressed):
|
||||
def onKeyEventScancode(self, code, isPressed, isExtended):
|
||||
"""
|
||||
@summary: Event call when a keyboard event is catch in scan code format
|
||||
@param code: scan code of key
|
||||
@param isPressed: True if key is down
|
||||
@param code: {integer} scan code of key
|
||||
@param isPressed: {boolean} True if key is down
|
||||
@param isExtended: {boolean} True if a special key
|
||||
"""
|
||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onKeyEventScanCode", "RDPServerObserver"))
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ RDP Standard security layer
|
||||
import sha, md5
|
||||
import lic, tpkt
|
||||
from t125 import gcc, mcs
|
||||
from rdpy.core.type import CompositeType, CallableValue, Stream, UInt32Le, UInt16Le, String, sizeof, UInt8
|
||||
from rdpy.core.type import CompositeType, CallableValue, Stream, UInt32Le, UInt16Le, String, sizeof
|
||||
from rdpy.core.layer import LayerAutomata, IStreamSender
|
||||
from rdpy.core.error import InvalidExpectedDataException
|
||||
from rdpy.core import log
|
||||
@@ -56,6 +56,7 @@ class SecurityFlag(object):
|
||||
class InfoFlag(object):
|
||||
"""
|
||||
Client capabilities informations
|
||||
@see: https://msdn.microsoft.com/en-us/library/cc240475.aspx
|
||||
"""
|
||||
INFO_MOUSE = 0x00000001
|
||||
INFO_DISABLECTRLALTDEL = 0x00000002
|
||||
@@ -80,6 +81,7 @@ class InfoFlag(object):
|
||||
class PerfFlag(object):
|
||||
"""
|
||||
Network performances flag
|
||||
@see: https://msdn.microsoft.com/en-us/library/cc240476.aspx
|
||||
"""
|
||||
PERF_DISABLE_WALLPAPER = 0x00000001
|
||||
PERF_DISABLE_FULLWINDOWDRAG = 0x00000002
|
||||
@@ -323,7 +325,7 @@ class RDPInfo(CompositeType):
|
||||
#code page
|
||||
self.codePage = UInt32Le()
|
||||
#support flag
|
||||
self.flag = UInt32Le(InfoFlag.INFO_MOUSE | InfoFlag.INFO_UNICODE | InfoFlag.INFO_LOGONNOTIFY | InfoFlag.INFO_LOGONERRORS | InfoFlag.INFO_DISABLECTRLALTDEL)
|
||||
self.flag = UInt32Le(InfoFlag.INFO_MOUSE | InfoFlag.INFO_UNICODE | InfoFlag.INFO_LOGONNOTIFY | InfoFlag.INFO_LOGONERRORS | InfoFlag.INFO_DISABLECTRLALTDEL | InfoFlag.INFO_ENABLEWINDOWSKEY)
|
||||
self.cbDomain = UInt16Le(lambda:sizeof(self.domain) - 2)
|
||||
self.cbUserName = UInt16Le(lambda:sizeof(self.userName) - 2)
|
||||
self.cbPassword = UInt16Le(lambda:sizeof(self.password) - 2)
|
||||
|
||||
@@ -27,7 +27,6 @@ It exist channel for file system order, audio channel, clipboard etc...
|
||||
from rdpy.core.layer import LayerAutomata, IStreamSender, Layer
|
||||
from rdpy.core.type import sizeof, Stream, UInt8, UInt16Le, String
|
||||
from rdpy.core.error import InvalidExpectedDataException, InvalidValue, InvalidSize, CallPureVirtualFuntion
|
||||
from ber import writeLength
|
||||
import rdpy.core.log as log
|
||||
|
||||
import ber, gcc, per
|
||||
@@ -255,7 +254,7 @@ class MCSLayer(LayerAutomata):
|
||||
domainParam = (ber.writeInteger(maxChannels), ber.writeInteger(maxUsers), ber.writeInteger(maxTokens),
|
||||
ber.writeInteger(1), ber.writeInteger(0), ber.writeInteger(1),
|
||||
ber.writeInteger(maxPduSize), ber.writeInteger(2))
|
||||
return (ber.writeUniversalTag(ber.Tag.BER_TAG_SEQUENCE, True), writeLength(sizeof(domainParam)), domainParam)
|
||||
return (ber.writeUniversalTag(ber.Tag.BER_TAG_SEQUENCE, True), ber.writeLength(sizeof(domainParam)), domainParam)
|
||||
|
||||
def writeMCSPDUHeader(self, mcsPdu, options = 0):
|
||||
"""
|
||||
|
||||
@@ -303,7 +303,7 @@ class RDPClientQt(RDPClientObserver, QAdaptor):
|
||||
@param isCompress: {bool} use RLE compression
|
||||
@param data: {str} bitmap data
|
||||
"""
|
||||
image = RDPBitmapToQtImage(width, height, bitsPerPixel, isCompress, data);
|
||||
image = RDPBitmapToQtImage(width, height, bitsPerPixel, isCompress, data)
|
||||
#if image need to be cut
|
||||
#For bit alignement server may send more than image pixel
|
||||
self._widget.notifyImage(destLeft, destTop, image, destRight - destLeft + 1, destBottom - destTop + 1)
|
||||
@@ -311,12 +311,21 @@ class RDPClientQt(RDPClientObserver, QAdaptor):
|
||||
def onReady(self):
|
||||
"""
|
||||
@summary: Call when stack is ready
|
||||
@see: rdp.RDPClientObserver.onReady
|
||||
"""
|
||||
#do something maybe a loader
|
||||
|
||||
def onSessionReady(self):
|
||||
"""
|
||||
@summary: Windows session is ready
|
||||
@see: rdp.RDPClientObserver.onSessionReady
|
||||
"""
|
||||
pass
|
||||
|
||||
def onClose(self):
|
||||
"""
|
||||
@summary: Call when stack is close
|
||||
@see: rdp.RDPClientObserver.onClose
|
||||
"""
|
||||
#do something maybe a message
|
||||
|
||||
@@ -336,12 +345,6 @@ class QRemoteDesktop(QtGui.QWidget):
|
||||
self._adaptor = adaptor
|
||||
#set correct size
|
||||
self.resize(width, height)
|
||||
#refresh stack of image
|
||||
#because we can update image only in paint
|
||||
#event function. When protocol receive image
|
||||
#we will stock into refresh list
|
||||
#and in paint event paint list of all refresh images
|
||||
self._refresh = []
|
||||
#bind mouse event
|
||||
self.setMouseTracking(True)
|
||||
#buffer image
|
||||
@@ -354,8 +357,9 @@ class QRemoteDesktop(QtGui.QWidget):
|
||||
@param y: y position of new image
|
||||
@param qimage: new QImage
|
||||
"""
|
||||
#save in refresh list (order is important)
|
||||
self._refresh.append((x, y, qimage, width, height))
|
||||
#fill buffer image
|
||||
with QtGui.QPainter(self._buffer) as qp:
|
||||
qp.drawImage(x, y, qimage, 0, 0, width, height)
|
||||
#force update
|
||||
self.update()
|
||||
|
||||
@@ -373,16 +377,9 @@ class QRemoteDesktop(QtGui.QWidget):
|
||||
@summary: Call when Qt renderer engine estimate that is needed
|
||||
@param e: QEvent
|
||||
"""
|
||||
#fill buffer image
|
||||
with QtGui.QPainter(self._buffer) as qp:
|
||||
#draw image
|
||||
for (x, y, image, width, height) in self._refresh:
|
||||
qp.drawImage(x, y, image, 0, 0, width, height)
|
||||
#draw in widget
|
||||
with QtGui.QPainter(self) as qp:
|
||||
qp.drawImage(0, 0, self._buffer)
|
||||
|
||||
self._refresh = []
|
||||
|
||||
def mouseMoveEvent(self, event):
|
||||
"""
|
||||
|
||||
2
setup.py
2
setup.py
@@ -4,7 +4,7 @@ import setuptools
|
||||
from distutils.core import setup, Extension
|
||||
|
||||
setup(name='rdpy',
|
||||
version='1.3.1',
|
||||
version='1.3.2',
|
||||
description='Remote Desktop Protocol in Python',
|
||||
long_description="""
|
||||
RDPY is a pure Python implementation of the Microsoft RDP (Remote Desktop Protocol) protocol (Client and Server side). RDPY is built over the event driven network engine Twisted.
|
||||
|
||||
Reference in New Issue
Block a user