Start python3
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -7,3 +7,5 @@ README.md~
|
||||
dist/*
|
||||
build/*
|
||||
rdpy.egg-info/*
|
||||
*.pyd
|
||||
.idea
|
||||
|
||||
@@ -145,7 +145,7 @@ In a nutshell RDPY can be used as a protocol library with a twisted engine.
|
||||
### Simple RDP Client
|
||||
|
||||
```python
|
||||
from rdpy.protocol.rdp import rdp
|
||||
from rdpy.core import rdp
|
||||
|
||||
class MyRDPFactory(rdp.ClientFactory):
|
||||
|
||||
@@ -201,7 +201,7 @@ reactor.run()
|
||||
|
||||
### Simple RDP Server
|
||||
```python
|
||||
from rdpy.protocol.rdp import rdp
|
||||
from rdpy.core import rdp
|
||||
|
||||
class MyRDPFactory(rdp.ServerFactory):
|
||||
|
||||
|
||||
@@ -23,13 +23,13 @@ example of use rdpy as rdp client
|
||||
|
||||
import sys, os, getopt, socket
|
||||
|
||||
from PyQt4 import QtGui, QtCore
|
||||
from PyQt5 import QtWidgets
|
||||
from rdpy.ui.qt4 import RDPClientQt
|
||||
from rdpy.protocol.rdp import rdp
|
||||
from rdpy.core.error import RDPSecurityNegoFail
|
||||
from rdpy.core import rss
|
||||
from rdpy.model.error import RDPSecurityNegoFail
|
||||
from rdpy.model import rss
|
||||
from rdpy.core import rdp
|
||||
|
||||
import rdpy.core.log as log
|
||||
import rdpy.model.log as log
|
||||
log._LOG_LEVEL = log.Level.INFO
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@ class RDPClientQtRecorder(RDPClientQt):
|
||||
self._rssRecorder.close()
|
||||
RDPClientQt.closeEvent(self, e)
|
||||
|
||||
|
||||
class RDPClientQtFactory(rdp.ClientFactory):
|
||||
"""
|
||||
@summary: Factory create a RDP GUI client
|
||||
@@ -211,7 +212,7 @@ def autoDetectKeyboardLayout():
|
||||
return "en"
|
||||
|
||||
def help():
|
||||
print """
|
||||
print("""
|
||||
Usage: rdpy-rdpclient [options] ip[:port]"
|
||||
\t-u: user name
|
||||
\t-p: password
|
||||
@@ -222,7 +223,7 @@ def help():
|
||||
\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__':
|
||||
|
||||
@@ -270,19 +271,11 @@ if __name__ == '__main__':
|
||||
ip, port = args[0], "3389"
|
||||
|
||||
#create application
|
||||
app = QtGui.QApplication(sys.argv)
|
||||
|
||||
#add qt4 reactor
|
||||
import qt4reactor
|
||||
qt4reactor.install()
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
|
||||
if fullscreen:
|
||||
width = QtGui.QDesktopWidget().screenGeometry().width()
|
||||
height = QtGui.QDesktopWidget().screenGeometry().height()
|
||||
width = QtWidgets.QDesktopWidget().screenGeometry().width()
|
||||
height = QtWidgets.QDesktopWidget().screenGeometry().height()
|
||||
|
||||
log.info("keyboard layout set to %s"%keyboardLayout)
|
||||
|
||||
from twisted.internet import reactor
|
||||
reactor.connectTCP(ip, int(port), RDPClientQtFactory(width, height, username, password, domain, fullscreen, keyboardLayout, optimized, "nego", recodedPath))
|
||||
reactor.runReturn()
|
||||
app.exec_()
|
||||
sys.exit(app.exec_())
|
||||
@@ -22,10 +22,10 @@
|
||||
RDP Honey pot use Rss scenario file to simulate RDP server
|
||||
"""
|
||||
|
||||
import sys, os, getopt, time, datetime
|
||||
import sys, getopt, datetime
|
||||
|
||||
from rdpy.core import log, error, rss
|
||||
from rdpy.protocol.rdp import rdp
|
||||
from rdpy.core import log, rss
|
||||
from rdpy.core import rdp
|
||||
from twisted.internet import reactor
|
||||
|
||||
log._LOG_LEVEL = log.Level.INFO
|
||||
|
||||
@@ -29,13 +29,12 @@ Client RDP -> | ProxyServer | ProxyClient | -> Server RDP
|
||||
-----------------
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import argparse
|
||||
import time
|
||||
|
||||
from rdpy.core import log, error, rss
|
||||
from rdpy.protocol.rdp import rdp
|
||||
from rdpy.core import log, rss
|
||||
from rdpy.core import rdp
|
||||
from twisted.internet import reactor
|
||||
|
||||
log._LOG_LEVEL = log.Level.INFO
|
||||
|
||||
@@ -24,15 +24,13 @@ take screenshot of login page
|
||||
"""
|
||||
|
||||
import getopt
|
||||
import os
|
||||
import sys
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
from rdpy.protocol.rdp import rdp
|
||||
from PyQt4 import QtGui
|
||||
from rdpy.core import rdp
|
||||
from rdpy.ui.qt4 import RDPBitmapToQtImage
|
||||
import rdpy.core.log as log
|
||||
from rdpy.core.error import RDPSecurityNegoFail
|
||||
from twisted.internet import task
|
||||
|
||||
# set log level
|
||||
log._LOG_LEVEL = log.Level.INFO
|
||||
|
||||
15
ext/rle.c
15
ext/rle.c
@@ -939,9 +939,18 @@ static PyMethodDef rle_methods[] =
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
PyMODINIT_FUNC
|
||||
initrle(void)
|
||||
static struct PyModuleDef rle =
|
||||
{
|
||||
(void) Py_InitModule("rle", rle_methods);
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"rle", /* name of module */
|
||||
"", /* module documentation, may be NULL */
|
||||
-1, /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */
|
||||
rle_methods
|
||||
};
|
||||
|
||||
PyMODINIT_FUNC
|
||||
PyInit_rle(void)
|
||||
{
|
||||
(void) PyModule_Create(&rle);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,11 +22,11 @@
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc241880.aspx
|
||||
"""
|
||||
|
||||
from rdpy.core.type import CompositeType, CallableValue, UInt8, UInt16Le, UInt32Le, String, sizeof, FactoryType, ArrayType, Stream
|
||||
from rdpy.core.error import InvalidExpectedDataException
|
||||
import rdpy.core.log as log
|
||||
import sec
|
||||
from t125 import gcc
|
||||
from rdpy.model.type import CompositeType, CallableValue, UInt8, UInt16Le, UInt32Le, String, sizeof, FactoryType, ArrayType, Stream
|
||||
from rdpy.model.error import InvalidExpectedDataException
|
||||
import rdpy.model.log as log
|
||||
from rdpy.core import sec
|
||||
from rdpy.core.t125 import gcc
|
||||
from rdpy.security import rc4
|
||||
from rdpy.security import rsa_wrapper as rsa
|
||||
|
||||
@@ -27,11 +27,9 @@ 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.type import Stream
|
||||
from twisted.internet import protocol
|
||||
from OpenSSL import crypto
|
||||
from rdpy.model.type import Stream
|
||||
from rdpy.security import x509
|
||||
from rdpy.core import error
|
||||
from rdpy.model import error
|
||||
|
||||
class NegoToken(univ.Sequence):
|
||||
componentType = namedtype.NamedTypes(
|
||||
@@ -175,7 +173,7 @@ def encodeDERTCredentials(domain, username, password):
|
||||
|
||||
return der_encoder.encode(credentials)
|
||||
|
||||
class CSSP(protocol.Protocol):
|
||||
class CSSP:
|
||||
"""
|
||||
@summary: Handle CSSP connection
|
||||
Proxy class for authentication
|
||||
@@ -23,12 +23,12 @@
|
||||
"""
|
||||
|
||||
import hashlib, hmac, struct, datetime
|
||||
import sspi
|
||||
from rdpy.core.nla import sspi
|
||||
import rdpy.security.pyDes as pyDes
|
||||
import rdpy.security.rc4 as rc4
|
||||
from rdpy.security.rsa_wrapper import random
|
||||
from rdpy.core.type import CompositeType, CallableValue, String, UInt8, UInt16Le, UInt24Le, UInt32Le, sizeof, Stream
|
||||
from rdpy.core import filetimes, error
|
||||
from rdpy.model.type import CompositeType, CallableValue, String, UInt8, UInt16Le, UInt24Le, UInt32Le, sizeof, Stream
|
||||
from rdpy.model import filetimes, error
|
||||
|
||||
class MajorVersion(object):
|
||||
"""
|
||||
@@ -21,7 +21,7 @@
|
||||
@summary: security service provider interface (Microsoft)
|
||||
"""
|
||||
|
||||
from rdpy.core.error import CallPureVirtualFuntion
|
||||
from rdpy.model.error import CallPureVirtualFuntion
|
||||
|
||||
class IAuthenticationProtocol(object):
|
||||
"""
|
||||
@@ -16,15 +16,16 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
from rdpy.core.error import InvalidExpectedDataException
|
||||
import rdpy.core.log as log
|
||||
from rdpy.model.error import InvalidExpectedDataException
|
||||
import rdpy.model.log as log
|
||||
|
||||
"""
|
||||
Definition of structure use for capabilities nego
|
||||
Use in PDU layer
|
||||
"""
|
||||
|
||||
from rdpy.core.type import CompositeType, CallableValue, String, UInt8, UInt16Le, UInt32Le, sizeof, ArrayType, FactoryType
|
||||
from rdpy.model.type import CompositeType, CallableValue, String, UInt8, UInt16Le, UInt32Le, sizeof, ArrayType, FactoryType
|
||||
|
||||
|
||||
class CapsType(object):
|
||||
"""
|
||||
@@ -22,10 +22,10 @@ Implement the main graphic layer
|
||||
|
||||
In this layer are managed all mains bitmap update orders end user inputs
|
||||
"""
|
||||
from rdpy.core.type import CompositeType, CallableValue, String, UInt8, UInt16Le, UInt32Le, sizeof, ArrayType, FactoryType
|
||||
from rdpy.core.error import InvalidExpectedDataException
|
||||
import rdpy.core.log as log
|
||||
import caps, order
|
||||
from rdpy.model.type import CompositeType, CallableValue, String, UInt8, UInt16Le, UInt32Le, sizeof, ArrayType, FactoryType
|
||||
from rdpy.model.error import InvalidExpectedDataException
|
||||
import rdpy.model.log as log
|
||||
from rdpy.core.pdu import caps, order
|
||||
|
||||
class PDUType(object):
|
||||
"""
|
||||
@@ -23,12 +23,13 @@ Implement the main graphic layer
|
||||
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
|
||||
from rdpy.model.layer import LayerAutomata
|
||||
from rdpy.model.error import CallPureVirtualFuntion
|
||||
from rdpy.model.type import ArrayType
|
||||
import rdpy.model.log as log
|
||||
from rdpy.core import tpkt
|
||||
from rdpy.core.pdu import data, caps
|
||||
|
||||
|
||||
class PDUClientListener(object):
|
||||
"""
|
||||
@@ -21,9 +21,9 @@
|
||||
GDI order structure
|
||||
"""
|
||||
|
||||
from rdpy.core import log
|
||||
from rdpy.core.error import InvalidExpectedDataException
|
||||
from rdpy.core.type import CompositeType, UInt8, String, FactoryType, SInt8, SInt16Le
|
||||
from rdpy.model import log
|
||||
from rdpy.model.error import InvalidExpectedDataException
|
||||
from rdpy.model.type import CompositeType, UInt8, String, FactoryType, SInt8, SInt16Le
|
||||
|
||||
class ControlFlag(object):
|
||||
"""
|
||||
@@ -21,15 +21,19 @@
|
||||
Use to manage RDP stack in twisted
|
||||
"""
|
||||
|
||||
from rdpy.core import layer
|
||||
from rdpy.core.error import CallPureVirtualFuntion, InvalidValue
|
||||
import pdu.layer
|
||||
import pdu.data
|
||||
import pdu.caps
|
||||
import rdpy.core.log as log
|
||||
import tpkt, x224, sec
|
||||
from t125 import mcs, gcc
|
||||
from nla import cssp, ntlm
|
||||
from rdpy.model import layer
|
||||
from rdpy.model.error import CallPureVirtualFuntion, InvalidValue
|
||||
from rdpy.core.pdu.layer import PDUClientListener, PDUServerListener
|
||||
from rdpy.core.pdu import data
|
||||
from rdpy.core.pdu import caps
|
||||
from rdpy.core.pdu import layer as pdu
|
||||
import rdpy.model.log as log
|
||||
import rdpy.core.tpkt as tpkt
|
||||
import rdpy.core.x224 as x224
|
||||
import rdpy.core.sec as sec
|
||||
from rdpy.core.t125 import mcs, gcc
|
||||
from rdpy.core.nla import cssp, ntlm
|
||||
|
||||
|
||||
class SecurityLevel(object):
|
||||
"""
|
||||
@@ -39,7 +43,8 @@ class SecurityLevel(object):
|
||||
RDP_LEVEL_SSL = 1
|
||||
RDP_LEVEL_NLA = 2
|
||||
|
||||
class RDPClientController(pdu.layer.PDUClientListener):
|
||||
|
||||
class RDPClientController(PDUClientListener):
|
||||
"""
|
||||
Manage RDP stack as client
|
||||
"""
|
||||
@@ -47,7 +52,7 @@ class RDPClientController(pdu.layer.PDUClientListener):
|
||||
#list of observer
|
||||
self._clientObserver = []
|
||||
#PDU layer
|
||||
self._pduLayer = pdu.layer.Client(self)
|
||||
self._pduLayer = pdu.Client(self)
|
||||
#secure layer
|
||||
self._secLayer = sec.Client(self._pduLayer)
|
||||
#multi channel service
|
||||
@@ -365,7 +370,8 @@ class RDPClientController(pdu.layer.PDUClientListener):
|
||||
"""
|
||||
self._pduLayer.close()
|
||||
|
||||
class RDPServerController(pdu.layer.PDUServerListener):
|
||||
|
||||
class RDPServerController(PDUServerListener):
|
||||
"""
|
||||
@summary: Controller use in server side mode
|
||||
"""
|
||||
@@ -585,49 +591,50 @@ class ClientFactory(layer.RawLayerClientFactory):
|
||||
"""
|
||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "buildObserver", "ClientFactory"))
|
||||
|
||||
class ServerFactory(layer.RawLayerServerFactory):
|
||||
"""
|
||||
@summary: Factory of Server RDP protocol
|
||||
"""
|
||||
def __init__(self, colorDepth, privateKeyFileName = None, certificateFileName = None):
|
||||
"""
|
||||
@param colorDepth: color depth of session
|
||||
@param privateKeyFileName: file contain server private key (if none -> back to standard RDP security)
|
||||
@param certficiateFileName: file that contain public key (if none -> back to standard RDP security)
|
||||
"""
|
||||
self._colorDepth = colorDepth
|
||||
self._privateKeyFileName = privateKeyFileName
|
||||
self._certificateFileName = certificateFileName
|
||||
|
||||
def connectionLost(self, tpktLayer, reason):
|
||||
"""
|
||||
@param reason: twisted reason
|
||||
"""
|
||||
#retrieve controller
|
||||
x224Layer = tpktLayer._presentation
|
||||
mcsLayer = x224Layer._presentation
|
||||
secLayer = mcsLayer._channels[mcs.Channel.MCS_GLOBAL_CHANNEL]
|
||||
pduLayer = secLayer._presentation
|
||||
controller = pduLayer._listener
|
||||
controller.onClose()
|
||||
|
||||
def buildRawLayer(self, addr):
|
||||
"""
|
||||
@summary: Function call from twisted and build rdp protocol stack
|
||||
@param addr: destination address
|
||||
"""
|
||||
controller = RDPServerController(self._colorDepth, self._privateKeyFileName, self._certificateFileName)
|
||||
self.buildObserver(controller, addr)
|
||||
return controller.getProtocol()
|
||||
|
||||
def buildObserver(self, controller, addr):
|
||||
"""
|
||||
@summary: Build observer use for connection
|
||||
@param controller: RDP stack controller
|
||||
@param addr: destination address
|
||||
"""
|
||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "buildObserver", "ServerFactory"))
|
||||
|
||||
# class ServerFactory(RawLayerServerFactory):
|
||||
# """
|
||||
# @summary: Factory of Server RDP protocol
|
||||
# """
|
||||
# def __init__(self, colorDepth, privateKeyFileName = None, certificateFileName = None):
|
||||
# """
|
||||
# @param colorDepth: color depth of session
|
||||
# @param privateKeyFileName: file contain server private key (if none -> back to standard RDP security)
|
||||
# @param certficiateFileName: file that contain public key (if none -> back to standard RDP security)
|
||||
# """
|
||||
# self._colorDepth = colorDepth
|
||||
# self._privateKeyFileName = privateKeyFileName
|
||||
# self._certificateFileName = certificateFileName
|
||||
#
|
||||
# def connectionLost(self, tpktLayer, reason):
|
||||
# """
|
||||
# @param reason: twisted reason
|
||||
# """
|
||||
# #retrieve controller
|
||||
# x224Layer = tpktLayer._presentation
|
||||
# mcsLayer = x224Layer._presentation
|
||||
# secLayer = mcsLayer._channels[mcs.Channel.MCS_GLOBAL_CHANNEL]
|
||||
# pduLayer = secLayer._presentation
|
||||
# controller = pduLayer._listener
|
||||
# controller.onClose()
|
||||
#
|
||||
# def buildRawLayer(self, addr):
|
||||
# """
|
||||
# @summary: Function call from twisted and build rdp protocol stack
|
||||
# @param addr: destination address
|
||||
# """
|
||||
# controller = RDPServerController(self._colorDepth, self._privateKeyFileName, self._certificateFileName)
|
||||
# self.buildObserver(controller, addr)
|
||||
# return controller.getProtocol()
|
||||
#
|
||||
# def buildObserver(self, controller, addr):
|
||||
# """
|
||||
# @summary: Build observer use for connection
|
||||
# @param controller: RDP stack controller
|
||||
# @param addr: destination address
|
||||
# """
|
||||
# raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "buildObserver", "ServerFactory"))
|
||||
#
|
||||
class RDPClientObserver(object):
|
||||
"""
|
||||
@summary: Class use to inform all RDP event handle by RDPY
|
||||
@@ -21,13 +21,14 @@
|
||||
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.layer import LayerAutomata, IStreamSender
|
||||
from rdpy.core.error import InvalidExpectedDataException
|
||||
from rdpy.core import log
|
||||
from hashlib import sha1 as sha
|
||||
from hashlib import md5
|
||||
from rdpy.core import tpkt, lic
|
||||
from rdpy.core.t125 import gcc, mcs
|
||||
from rdpy.model.type import CompositeType, CallableValue, Stream, UInt32Le, UInt16Le, String, sizeof, UInt8
|
||||
from rdpy.model.layer import LayerAutomata, IStreamSender
|
||||
from rdpy.model.error import InvalidExpectedDataException
|
||||
from rdpy.model import log
|
||||
from rdpy.security import rc4
|
||||
import rdpy.security.rsa_wrapper as rsa
|
||||
|
||||
@@ -22,8 +22,8 @@ Basic Encoding Rules use in RDP.
|
||||
ASN.1 standard
|
||||
"""
|
||||
|
||||
from rdpy.core.type import UInt8, UInt16Be, UInt32Be, String
|
||||
from rdpy.core.error import InvalidExpectedDataException, InvalidSize
|
||||
from rdpy.model.type import UInt8, UInt16Be, UInt32Be, String
|
||||
from rdpy.model.error import InvalidExpectedDataException, InvalidSize
|
||||
|
||||
class BerPc(object):
|
||||
BER_PC_MASK = 0x20
|
||||
@@ -22,11 +22,11 @@ Implement GCC structure use in RDP protocol
|
||||
http://msdn.microsoft.com/en-us/library/cc240508.aspx
|
||||
"""
|
||||
|
||||
import md5
|
||||
from rdpy.core.type import UInt8, UInt16Le, UInt32Le, CompositeType, CallableValue, String, Stream, sizeof, FactoryType, ArrayType
|
||||
import per, mcs
|
||||
from rdpy.core.error import InvalidExpectedDataException
|
||||
from rdpy.core import log
|
||||
from hashlib import md5
|
||||
from rdpy.model.type import UInt8, UInt16Le, UInt32Le, CompositeType, CallableValue, String, Stream, sizeof, FactoryType, ArrayType
|
||||
from rdpy.core.t125 import per, mcs
|
||||
from rdpy.model.error import InvalidExpectedDataException
|
||||
from rdpy.model import log
|
||||
from rdpy.security import x509
|
||||
import rdpy.security.rsa_wrapper as rsa
|
||||
|
||||
@@ -24,13 +24,13 @@ Each channel have a particular role.
|
||||
The main channel is the graphical channel.
|
||||
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
|
||||
from rdpy.model.layer import LayerAutomata, IStreamSender, Layer
|
||||
from rdpy.model.type import sizeof, Stream, UInt8, UInt16Le, String
|
||||
from rdpy.model.error import InvalidExpectedDataException, InvalidValue, InvalidSize, CallPureVirtualFuntion
|
||||
from rdpy.core.t125.ber import writeLength
|
||||
import rdpy.model.log as log
|
||||
|
||||
import ber, gcc, per
|
||||
from rdpy.core.t125 import ber, gcc, per
|
||||
import rdpy.security.rsa_wrapper as rsa
|
||||
|
||||
class Message(object):
|
||||
@@ -21,8 +21,8 @@
|
||||
Per encoded function
|
||||
"""
|
||||
|
||||
from rdpy.core.type import UInt8, UInt16Be, UInt32Be, String
|
||||
from rdpy.core.error import InvalidValue, InvalidExpectedDataException
|
||||
from rdpy.model.type import UInt8, UInt16Be, UInt32Be, String
|
||||
from rdpy.model.error import InvalidValue, InvalidExpectedDataException
|
||||
|
||||
def readLength(s):
|
||||
"""
|
||||
@@ -22,9 +22,10 @@ Transport packet layer implementation
|
||||
|
||||
Use to build correct size packet and handle slow path and fast path mode
|
||||
"""
|
||||
from rdpy.core.layer import RawLayer
|
||||
from rdpy.core.type import UInt8, UInt16Be, sizeof
|
||||
from rdpy.core.error import CallPureVirtualFuntion
|
||||
from rdpy.model.layer import RawLayer
|
||||
from rdpy.model.type import UInt8, UInt16Be, sizeof
|
||||
from rdpy.model.error import CallPureVirtualFuntion
|
||||
|
||||
|
||||
class Action(object):
|
||||
"""
|
||||
@@ -23,11 +23,11 @@ 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 log
|
||||
from rdpy.model import log
|
||||
|
||||
from rdpy.core.layer import LayerAutomata, IStreamSender
|
||||
from rdpy.core.type import UInt8, UInt16Le, UInt16Be, UInt32Le, CompositeType, sizeof, String
|
||||
from rdpy.core.error import InvalidExpectedDataException, RDPSecurityNegoFail
|
||||
from rdpy.model.layer import LayerAutomata, IStreamSender
|
||||
from rdpy.model.type import UInt8, UInt16Le, UInt16Be, UInt32Le, CompositeType, sizeof, String
|
||||
from rdpy.model.error import InvalidExpectedDataException, RDPSecurityNegoFail
|
||||
|
||||
class MessageType(object):
|
||||
"""
|
||||
@@ -303,38 +303,8 @@ class Server(X224Layer):
|
||||
if self._selectedProtocol == Protocols.PROTOCOL_SSL:
|
||||
log.debug("*" * 10 + " select SSL layer " + "*" * 10)
|
||||
#_transport is TPKT and transport is TCP layer of twisted
|
||||
self._transport.startTLS(ServerTLSContext(self._serverPrivateKeyFileName, self._serverCertificateFileName))
|
||||
#self._transport.startTLS(ServerTLSContext(self._serverPrivateKeyFileName, self._serverCertificateFileName))
|
||||
|
||||
#connection is done send to presentation
|
||||
self.setNextState(self.recvData)
|
||||
self._presentation.connect()
|
||||
|
||||
#open ssl needed
|
||||
from twisted.internet import ssl
|
||||
from OpenSSL import SSL
|
||||
|
||||
class ClientTLSContext(ssl.ClientContextFactory):
|
||||
"""
|
||||
@summary: client context factory for open ssl
|
||||
"""
|
||||
def getContext(self):
|
||||
context = SSL.Context(SSL.TLSv1_METHOD)
|
||||
context.set_options(SSL.OP_DONT_INSERT_EMPTY_FRAGMENTS)
|
||||
context.set_options(SSL.OP_TLS_BLOCK_PADDING_BUG)
|
||||
return context
|
||||
|
||||
class ServerTLSContext(ssl.DefaultOpenSSLContextFactory):
|
||||
"""
|
||||
@summary: Server context factory for open ssl
|
||||
@param privateKeyFileName: Name of a file containing a private key
|
||||
@param certificateFileName: Name of a file containing a certificate
|
||||
"""
|
||||
def __init__(self, privateKeyFileName, certificateFileName):
|
||||
class TPDUSSLContext(SSL.Context):
|
||||
def __init__(self, method):
|
||||
SSL.Context.__init__(self, method)
|
||||
self.set_options(SSL.OP_DONT_INSERT_EMPTY_FRAGMENTS)
|
||||
self.set_options(SSL.OP_TLS_BLOCK_PADDING_BUG)
|
||||
|
||||
ssl.DefaultOpenSSLContextFactory.__init__(self, privateKeyFileName, certificateFileName, SSL.SSLv23_METHOD, TPDUSSLContext)
|
||||
|
||||
@@ -22,8 +22,9 @@ Join RDPY design with twisted design
|
||||
|
||||
RDPY use Layer Protocol design (like twisted)
|
||||
"""
|
||||
import asyncio
|
||||
from rdpy.model.error import CallPureVirtualFuntion
|
||||
|
||||
from rdpy.core.error import CallPureVirtualFuntion
|
||||
|
||||
class IStreamListener(object):
|
||||
"""
|
||||
@@ -36,6 +37,7 @@ class IStreamListener(object):
|
||||
"""
|
||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "recv", "IStreamListener"))
|
||||
|
||||
|
||||
class IStreamSender(object):
|
||||
"""
|
||||
@summary: Interface use to inform stream sender capability
|
||||
@@ -47,6 +49,7 @@ class IStreamSender(object):
|
||||
"""
|
||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "send", "IStreamSender"))
|
||||
|
||||
|
||||
class Layer(object):
|
||||
"""
|
||||
@summary: A simple double linked list with presentation and transport layer
|
||||
@@ -80,6 +83,7 @@ class Layer(object):
|
||||
if not self._transport is None:
|
||||
self._transport.close()
|
||||
|
||||
|
||||
class LayerAutomata(Layer, IStreamListener):
|
||||
"""
|
||||
@summary: Layer with automata callback
|
||||
@@ -103,13 +107,8 @@ class LayerAutomata(Layer, IStreamListener):
|
||||
|
||||
self.recv = callback
|
||||
|
||||
#twisted layer concept
|
||||
from twisted.internet import protocol
|
||||
from twisted.internet.abstract import FileDescriptor
|
||||
#first that handle stream
|
||||
from type import Stream
|
||||
|
||||
class RawLayerClientFactory(protocol.ClientFactory):
|
||||
class RawLayerClientFactory(asyncio.Protocol):
|
||||
"""
|
||||
@summary: Abstract class for Raw layer client factory
|
||||
"""
|
||||
@@ -137,36 +136,37 @@ class RawLayerClientFactory(protocol.ClientFactory):
|
||||
"""
|
||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "connectionLost", "RawLayerClientFactory"))
|
||||
|
||||
class RawLayerServerFactory(protocol.ServerFactory):
|
||||
"""
|
||||
@summary: Abstract class for Raw layer server factory
|
||||
"""
|
||||
def buildProtocol(self, addr):
|
||||
"""
|
||||
@summary: Function call from twisted
|
||||
@param addr: destination address
|
||||
"""
|
||||
rawLayer = self.buildRawLayer(addr)
|
||||
rawLayer.setFactory(self)
|
||||
return rawLayer
|
||||
|
||||
def buildRawLayer(self, addr):
|
||||
"""
|
||||
@summary: Override this function to build raw layer
|
||||
@param addr: destination address
|
||||
"""
|
||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "recv", "IStreamListener"))
|
||||
|
||||
def connectionLost(self, rawlayer, reason):
|
||||
"""
|
||||
@summary: Override this method to handle connection lost
|
||||
@param rawlayer: rawLayer that cause connectionLost event
|
||||
@param reason: twisted reason
|
||||
"""
|
||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "recv", "IStreamListener"))
|
||||
|
||||
|
||||
class RawLayer(protocol.Protocol, LayerAutomata, IStreamSender):
|
||||
# class RawLayerServerFactory(protocol.ServerFactory):
|
||||
# """
|
||||
# @summary: Abstract class for Raw layer server factory
|
||||
# """
|
||||
# def buildProtocol(self, addr):
|
||||
# """
|
||||
# @summary: Function call from twisted
|
||||
# @param addr: destination address
|
||||
# """
|
||||
# rawLayer = self.buildRawLayer(addr)
|
||||
# rawLayer.setFactory(self)
|
||||
# return rawLayer
|
||||
#
|
||||
# def buildRawLayer(self, addr):
|
||||
# """
|
||||
# @summary: Override this function to build raw layer
|
||||
# @param addr: destination address
|
||||
# """
|
||||
# raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "recv", "IStreamListener"))
|
||||
#
|
||||
# def connectionLost(self, rawlayer, reason):
|
||||
# """
|
||||
# @summary: Override this method to handle connection lost
|
||||
# @param rawlayer: rawLayer that cause connectionLost event
|
||||
# @param reason: twisted reason
|
||||
# """
|
||||
# raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "recv", "IStreamListener"))
|
||||
#
|
||||
#
|
||||
class RawLayer(asyncio.Protocol, LayerAutomata, IStreamSender):
|
||||
"""
|
||||
@summary: Wait event from twisted engine
|
||||
And format correct size packet
|
||||
@@ -44,7 +44,7 @@ def log(message):
|
||||
f = open(_LOG_FILE, "a+")
|
||||
f.write("%s\n"%message)
|
||||
f.close()
|
||||
print "[*] %s"%message
|
||||
print("[*] %s"%message)
|
||||
|
||||
def error(message):
|
||||
"""
|
||||
@@ -22,8 +22,8 @@ Remote Session Scenario File format
|
||||
Private protocol format to save events
|
||||
"""
|
||||
|
||||
from rdpy.core.type import CompositeType, FactoryType, UInt8, UInt16Le, UInt32Le, String, sizeof, Stream
|
||||
from rdpy.core import log, error
|
||||
from rdpy.model.type import CompositeType, FactoryType, UInt8, UInt16Le, UInt32Le, String, sizeof, Stream
|
||||
from rdpy.model import log, error
|
||||
import time
|
||||
|
||||
class EventType(object):
|
||||
@@ -26,9 +26,10 @@ We are in python!
|
||||
|
||||
import struct
|
||||
from copy import deepcopy
|
||||
from StringIO import StringIO
|
||||
from rdpy.core.error import InvalidExpectedDataException, InvalidSize, CallPureVirtualFuntion, InvalidValue
|
||||
import rdpy.core.log as log
|
||||
from io import BytesIO
|
||||
from rdpy.model.error import InvalidExpectedDataException, InvalidSize, CallPureVirtualFuntion, InvalidValue
|
||||
import rdpy.model.log as log
|
||||
|
||||
|
||||
def sizeof(element):
|
||||
"""
|
||||
@@ -852,7 +853,8 @@ def decodeUnicode(s):
|
||||
i += 1
|
||||
return r
|
||||
|
||||
class Stream(StringIO):
|
||||
|
||||
class Stream(BytesIO):
|
||||
"""
|
||||
@summary: Stream use to read all types
|
||||
"""
|
||||
@@ -1,765 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2014-2015 Sylvain Peyrefitte
|
||||
#
|
||||
# This file is part of rdpy.
|
||||
#
|
||||
# rdpy is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
"""
|
||||
Implement Remote FrameBuffer protocol use in VNC client and server
|
||||
@see: http://www.realvnc.com/docs/rfbproto.pdf
|
||||
|
||||
@todo: server side of protocol
|
||||
@todo: more encoding rectangle
|
||||
"""
|
||||
|
||||
from rdpy.core.layer import RawLayer, RawLayerClientFactory
|
||||
from rdpy.core.type import UInt8, UInt16Be, UInt32Be, SInt32Be, String, CompositeType
|
||||
from rdpy.core.error import InvalidValue, CallPureVirtualFuntion
|
||||
from rdpy.security.pyDes import des
|
||||
import rdpy.core.log as log
|
||||
|
||||
class ProtocolVersion(object):
|
||||
"""
|
||||
@summary: Different protocol version
|
||||
"""
|
||||
UNKNOWN = ""
|
||||
RFB003003 = "RFB 003.003\n"
|
||||
RFB003007 = "RFB 003.007\n"
|
||||
RFB003008 = "RFB 003.008\n"
|
||||
|
||||
class SecurityType(object):
|
||||
"""
|
||||
@summary: Security type supported
|
||||
"""
|
||||
INVALID = 0
|
||||
NONE = 1
|
||||
VNC = 2
|
||||
|
||||
class Pointer(object):
|
||||
"""
|
||||
@summary: Mouse event code (which button)
|
||||
actually in RFB specification only
|
||||
three buttons are supported
|
||||
"""
|
||||
BUTTON1 = 0x1
|
||||
BUTTON2 = 0x2
|
||||
BUTTON3 = 0x4
|
||||
|
||||
class Encoding(object):
|
||||
"""
|
||||
@summary: Encoding types of FrameBuffer update
|
||||
"""
|
||||
RAW = 0
|
||||
|
||||
class ClientToServerMessages(object):
|
||||
"""
|
||||
@summary: Client to server messages types
|
||||
"""
|
||||
PIXEL_FORMAT = 0
|
||||
ENCODING = 2
|
||||
FRAME_BUFFER_UPDATE_REQUEST = 3
|
||||
KEY_EVENT = 4
|
||||
POINTER_EVENT = 5
|
||||
CUT_TEXT = 6
|
||||
|
||||
class PixelFormat(CompositeType):
|
||||
"""
|
||||
@summary: Pixel format structure
|
||||
"""
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
self.BitsPerPixel = UInt8(32)
|
||||
self.Depth = UInt8(24)
|
||||
self.BigEndianFlag = UInt8(False)
|
||||
self.TrueColorFlag = UInt8(True)
|
||||
self.RedMax = UInt16Be(255)
|
||||
self.GreenMax = UInt16Be(255)
|
||||
self.BlueMax = UInt16Be(255)
|
||||
self.RedShift = UInt8(16)
|
||||
self.GreenShift = UInt8(8)
|
||||
self.BlueShift = UInt8(0)
|
||||
self.padding = (UInt16Be(), UInt8())
|
||||
|
||||
class ServerInit(CompositeType):
|
||||
"""
|
||||
@summary: Server init structure
|
||||
FrameBuffer configuration
|
||||
"""
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
self.width = UInt16Be()
|
||||
self.height = UInt16Be()
|
||||
self.pixelFormat = PixelFormat()
|
||||
|
||||
class FrameBufferUpdateRequest(CompositeType):
|
||||
"""
|
||||
@summary: FrameBuffer update request send from client to server
|
||||
Incremental means that server send update with a specific
|
||||
order, and client must draw orders in same order
|
||||
"""
|
||||
def __init__(self, incremental = False, x = 0, y = 0, width = 0, height = 0):
|
||||
CompositeType.__init__(self)
|
||||
self.incremental = UInt8(incremental)
|
||||
self.x = UInt16Be(x)
|
||||
self.y = UInt16Be(y)
|
||||
self.width = UInt16Be(width)
|
||||
self.height = UInt16Be(height)
|
||||
|
||||
|
||||
class Rectangle(CompositeType):
|
||||
"""
|
||||
@summary: Header message of update rectangle
|
||||
"""
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
self.x = UInt16Be()
|
||||
self.y = UInt16Be()
|
||||
self.width = UInt16Be()
|
||||
self.height = UInt16Be()
|
||||
self.encoding = SInt32Be()
|
||||
|
||||
class KeyEvent(CompositeType):
|
||||
"""
|
||||
@summary: Key event structure message
|
||||
Use to send a keyboard event
|
||||
"""
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
self.downFlag = UInt8(False)
|
||||
self.padding = UInt16Be()
|
||||
self.key = UInt32Be()
|
||||
|
||||
class PointerEvent(CompositeType):
|
||||
"""
|
||||
@summary: Pointer event structure message
|
||||
Use to send mouse event
|
||||
"""
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
self.mask = UInt8()
|
||||
self.x = UInt16Be()
|
||||
self.y = UInt16Be()
|
||||
|
||||
class ClientCutText(CompositeType):
|
||||
"""
|
||||
@summary: Client cut text message message
|
||||
Use to simulate copy paste (ctrl-c ctrl-v) only for text
|
||||
"""
|
||||
def __init__(self, text = ""):
|
||||
CompositeType.__init__(self)
|
||||
self.padding = (UInt16Be(), UInt8())
|
||||
self.size = UInt32Be(len(text))
|
||||
self.message = String(text)
|
||||
|
||||
class ServerCutTextHeader(CompositeType):
|
||||
"""
|
||||
@summary: Cut text header send from server to client
|
||||
"""
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
self.padding = (UInt16Be(), UInt8())
|
||||
self.size = UInt32Be()
|
||||
|
||||
class RFB(RawLayer):
|
||||
"""
|
||||
@summary: Implement RFB protocol
|
||||
"""
|
||||
def __init__(self, listener):
|
||||
"""
|
||||
@param listener: listener use to inform new orders
|
||||
"""
|
||||
RawLayer.__init__(self)
|
||||
#set client listener
|
||||
self._clientListener = listener
|
||||
#useful for RFB protocol
|
||||
self._callbackBody = None
|
||||
#protocol version negotiated
|
||||
self._version = String(ProtocolVersion.RFB003008)
|
||||
#number security launch by server
|
||||
self._securityLevel = UInt8(SecurityType.INVALID)
|
||||
#shared FrameBuffer client init message
|
||||
self._sharedFlag = UInt8(False)
|
||||
#server init message
|
||||
#which contain FrameBuffer dim and pixel format
|
||||
self._serverInit = ServerInit()
|
||||
#client pixel format
|
||||
self._pixelFormat = PixelFormat()
|
||||
#server name
|
||||
self._serverName = String()
|
||||
#nb rectangle
|
||||
self._nbRect = 0
|
||||
#current rectangle header
|
||||
self._currentRect = Rectangle()
|
||||
#for vnc security type
|
||||
self._password = '\0' * 8
|
||||
|
||||
def expectWithHeader(self, expectedHeaderLen, callbackBody):
|
||||
"""
|
||||
2nd level of waiting event
|
||||
read expectedHeaderLen that contain body size
|
||||
@param expectedHeaderLen: contains the number of bytes, which body length needs to be encoded
|
||||
@param callbackBody: next state use when expected date from expectedHeaderLen
|
||||
are received
|
||||
"""
|
||||
self._callbackBody = callbackBody
|
||||
self.expect(expectedHeaderLen, self.expectedBody)
|
||||
|
||||
def expectedBody(self, data):
|
||||
"""
|
||||
Read header and wait header value to call next state
|
||||
@param data: Stream that length are to header length (1|2|4 bytes)
|
||||
set next state to callBack body when length read from header
|
||||
are received
|
||||
"""
|
||||
bodyLen = None
|
||||
if data.len == 1:
|
||||
bodyLen = UInt8()
|
||||
elif data.len == 2:
|
||||
bodyLen = UInt16Be()
|
||||
elif data.len == 4:
|
||||
bodyLen = UInt32Be()
|
||||
else:
|
||||
log.error("invalid header length")
|
||||
return
|
||||
data.readType(bodyLen)
|
||||
self.expect(bodyLen.value, self._callbackBody)
|
||||
|
||||
def connect(self):
|
||||
"""
|
||||
Call when transport layer connection is made
|
||||
in Client mode -> wait protocol version
|
||||
"""
|
||||
self.expect(12, self.recvProtocolVersion)
|
||||
|
||||
def readProtocolVersion(self, data):
|
||||
"""
|
||||
Read protocol version
|
||||
@param data: Stream may contain protocol version string (ProtocolVersion)
|
||||
"""
|
||||
data.readType(self._version)
|
||||
if not self._version.value in [ProtocolVersion.RFB003003, ProtocolVersion.RFB003007, ProtocolVersion.RFB003008]:
|
||||
self._version.value = ProtocolVersion.UNKNOWN
|
||||
|
||||
def recvProtocolVersion(self, data):
|
||||
"""
|
||||
Read handshake packet
|
||||
If protocol receive from client is unknown
|
||||
try best version of protocol version (ProtocolVersion.RFB003008)
|
||||
@param data: Stream
|
||||
"""
|
||||
self.readProtocolVersion(data)
|
||||
if self._version.value == ProtocolVersion.UNKNOWN:
|
||||
log.info("Unknown protocol version %s send 003.008"%data.getvalue())
|
||||
#protocol version is unknown try best version we can handle
|
||||
self._version.value = ProtocolVersion.RFB003008
|
||||
#send same version of
|
||||
self.send(self._version)
|
||||
|
||||
#next state read security
|
||||
if self._version.value == ProtocolVersion.RFB003003:
|
||||
self.expect(4, self.recvSecurityServer)
|
||||
else:
|
||||
self.expectWithHeader(1, self.recvSecurityList)
|
||||
|
||||
def recvSecurityServer(self, data):
|
||||
"""
|
||||
Security handshake for 33 RFB version
|
||||
Server imposed security level
|
||||
@param data: well formed packet
|
||||
"""
|
||||
#TODO!!!
|
||||
pass
|
||||
|
||||
def recvSecurityList(self, data):
|
||||
"""
|
||||
Read security list packet send from server to client
|
||||
@param data: Stream that contains well formed packet
|
||||
"""
|
||||
securityList = []
|
||||
while data.dataLen() > 0:
|
||||
securityElement = UInt8()
|
||||
data.readType(securityElement)
|
||||
securityList.append(securityElement)
|
||||
#select high security level
|
||||
for s in securityList:
|
||||
if s.value in [SecurityType.NONE, SecurityType.VNC] and s > self._securityLevel:
|
||||
self._securityLevel = s
|
||||
break
|
||||
#send back security level choosen
|
||||
self.send(self._securityLevel)
|
||||
if self._securityLevel.value == SecurityType.VNC:
|
||||
self.expect(16, self.recvVNCChallenge)
|
||||
else:
|
||||
self.expect(4, self.recvSecurityResult)
|
||||
|
||||
def recvVNCChallenge(self, data):
|
||||
"""
|
||||
@summary: receive challenge in VNC authentication case
|
||||
@param data: Stream that contain well formed packet
|
||||
"""
|
||||
key = (self._password + '\0' * 8)[:8]
|
||||
newkey = []
|
||||
for ki in range(len(key)):
|
||||
bsrc = ord(key[ki])
|
||||
btgt = 0
|
||||
for i in range(8):
|
||||
if bsrc & (1 << i):
|
||||
btgt = btgt | (1 << 7-i)
|
||||
newkey.append(chr(btgt))
|
||||
|
||||
algo = des(newkey)
|
||||
self.send(String(algo.encrypt(data.getvalue())))
|
||||
self.expect(4, self.recvSecurityResult)
|
||||
|
||||
def recvSecurityResult(self, data):
|
||||
"""
|
||||
Read security result packet
|
||||
Use by server to inform connection status of client
|
||||
@param data: Stream that contain well formed packet
|
||||
"""
|
||||
result = UInt32Be()
|
||||
data.readType(result)
|
||||
if result == UInt32Be(1):
|
||||
log.info("Authentification failed")
|
||||
if self._version.value == ProtocolVersion.RFB003008:
|
||||
self.expectWithHeader(4, self.recvSecurityFailed)
|
||||
else:
|
||||
log.debug("Authentification OK")
|
||||
self.sendClientInit()
|
||||
|
||||
def recvSecurityFailed(self, data):
|
||||
"""
|
||||
Send by server to inform reason of why it's refused client
|
||||
@param data: Stream that contains well formed packet
|
||||
"""
|
||||
log.info("Security failed cause to %s"%data.getvalue())
|
||||
|
||||
def recvServerInit(self, data):
|
||||
"""
|
||||
Read server init packet
|
||||
@param data: Stream that contains well formed packet
|
||||
"""
|
||||
data.readType(self._serverInit)
|
||||
self.expectWithHeader(4, self.recvServerName)
|
||||
|
||||
def recvServerName(self, data):
|
||||
"""
|
||||
@summary: Read server name
|
||||
@param data: Stream that contains well formed packet
|
||||
"""
|
||||
data.readType(self._serverName)
|
||||
log.info("Server name %s"%str(self._serverName))
|
||||
#end of handshake
|
||||
#send pixel format
|
||||
self.sendPixelFormat(self._pixelFormat)
|
||||
#write encoding
|
||||
self.sendSetEncoding()
|
||||
#request entire zone
|
||||
self.sendFramebufferUpdateRequest(False, 0, 0, self._serverInit.width.value, self._serverInit.height.value)
|
||||
#now i'm ready to send event
|
||||
self._clientListener.onReady()
|
||||
self.expect(1, self.recvServerOrder)
|
||||
|
||||
def recvServerOrder(self, data):
|
||||
"""
|
||||
@summary: Read order receive from server
|
||||
Main function for bitmap update from server to client
|
||||
@param data: Stream that contains well formed packet
|
||||
"""
|
||||
packetType = UInt8()
|
||||
data.readType(packetType)
|
||||
if packetType.value == 0:
|
||||
self.expect(3, self.recvFrameBufferUpdateHeader)
|
||||
elif packetType.value == 2:
|
||||
self._clientListener.onBell()
|
||||
elif packetType.value == 3:
|
||||
self.expect(7, self.recvServerCutTextHeader)
|
||||
else:
|
||||
log.error("Unknown message type %s"%packetType.value)
|
||||
|
||||
def recvFrameBufferUpdateHeader(self, data):
|
||||
"""
|
||||
@summary: Read frame buffer update packet header
|
||||
@param data: Stream that contains well formed packet
|
||||
"""
|
||||
#padding
|
||||
nbRect = UInt16Be()
|
||||
self._nbRect = data.readType((UInt8(), nbRect))
|
||||
self._nbRect = nbRect.value
|
||||
self.expect(12, self.recvRectHeader)
|
||||
|
||||
def recvRectHeader(self, data):
|
||||
"""
|
||||
@summary: Read rectangle header
|
||||
@param data: Stream that contains well formed packet
|
||||
"""
|
||||
data.readType(self._currentRect)
|
||||
if self._currentRect.encoding.value == Encoding.RAW:
|
||||
self.expect(self._currentRect.width.value * self._currentRect.height.value * (self._pixelFormat.BitsPerPixel.value / 8), self.recvRectBody)
|
||||
|
||||
def recvRectBody(self, data):
|
||||
"""
|
||||
@summary: Read body of rectangle update
|
||||
@param data: Stream that contains well formed packet
|
||||
"""
|
||||
self._clientListener.recvRectangle(self._currentRect, self._pixelFormat, data.getvalue())
|
||||
|
||||
self._nbRect -= 1
|
||||
#if there is another rect to read
|
||||
if self._nbRect == 0:
|
||||
#job is finish send a request
|
||||
self.sendFramebufferUpdateRequest(True, 0, 0, self._serverInit.width.value, self._serverInit.height.value)
|
||||
self.expect(1, self.recvServerOrder)
|
||||
else:
|
||||
self.expect(12, self.recvRectHeader)
|
||||
|
||||
def recvServerCutTextHeader(self, data):
|
||||
"""
|
||||
@summary: callback when expect server cut text message
|
||||
@param data: Stream that contains well formed packet
|
||||
"""
|
||||
header = ServerCutTextHeader()
|
||||
data.readType(header)
|
||||
self.expect(header.size.value, self.recvServerCutTextBody)
|
||||
|
||||
def recvServerCutTextBody(self, data):
|
||||
"""
|
||||
@summary: Receive server cut text body
|
||||
@param data: Stream that contains well formed packet
|
||||
"""
|
||||
self._clientListener.onCutText(data.getvalue())
|
||||
self.expect(1, self.recvServerOrder)
|
||||
|
||||
def sendClientInit(self):
|
||||
"""
|
||||
@summary: Send client init packet
|
||||
"""
|
||||
self.send(self._sharedFlag)
|
||||
self.expect(20, self.recvServerInit)
|
||||
|
||||
def sendPixelFormat(self, pixelFormat):
|
||||
"""
|
||||
@summary: Send pixel format structure
|
||||
Very important packet that inform the image struct supported by the client
|
||||
@param pixelFormat: PixelFormat struct
|
||||
"""
|
||||
self.send((UInt8(ClientToServerMessages.PIXEL_FORMAT), UInt16Be(), UInt8(), pixelFormat))
|
||||
|
||||
def sendSetEncoding(self):
|
||||
"""
|
||||
@summary: Send set encoding packet
|
||||
Actually only RAW bitmap encoding are used
|
||||
"""
|
||||
self.send((UInt8(ClientToServerMessages.ENCODING), UInt8(), UInt16Be(1), SInt32Be(Encoding.RAW)))
|
||||
|
||||
def sendFramebufferUpdateRequest(self, incremental, x, y, width, height):
|
||||
"""
|
||||
@summary: Request server the specified zone
|
||||
incremental means request only change before last update
|
||||
"""
|
||||
self.send((UInt8(ClientToServerMessages.FRAME_BUFFER_UPDATE_REQUEST), FrameBufferUpdateRequest(incremental, x, y, width, height)))
|
||||
|
||||
def sendKeyEvent(self, keyEvent):
|
||||
"""
|
||||
@summary: Write key event packet
|
||||
@param keyEvent: KeyEvent struct to send
|
||||
"""
|
||||
self.send((UInt8(ClientToServerMessages.KEY_EVENT), keyEvent))
|
||||
|
||||
def sendPointerEvent(self, pointerEvent):
|
||||
"""
|
||||
@summary: Write pointer event packet
|
||||
@param pointerEvent: PointerEvent struct use
|
||||
"""
|
||||
self.send((UInt8(ClientToServerMessages.POINTER_EVENT), pointerEvent))
|
||||
|
||||
def sendClientCutText(self, text):
|
||||
"""
|
||||
@summary: write client cut text event packet
|
||||
"""
|
||||
self.send((UInt8(ClientToServerMessages.CUT_TEXT), ClientCutText(text)))
|
||||
|
||||
class RFBClientListener(object):
|
||||
"""
|
||||
@summary: Interface use to expose event receive from RFB layer
|
||||
"""
|
||||
def recvRectangle(self, rectangle, pixelFormat, data):
|
||||
"""
|
||||
@summary: Receive rectangle order
|
||||
Main update order type
|
||||
@param rectangle: Rectangle type header of packet
|
||||
@param pixelFormat: pixelFormat struct of current session
|
||||
@param data: image data
|
||||
"""
|
||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "recvRectangle", "RFBClientListener"))
|
||||
|
||||
def onBell(self):
|
||||
"""
|
||||
@summary: receive bip from server
|
||||
"""
|
||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onBell", "RFBClientListener"))
|
||||
|
||||
def onCutText(self, text):
|
||||
"""
|
||||
@summary: Receive cut text from server
|
||||
@param text: text inner cut text event
|
||||
"""
|
||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onCutText", "RFBClientListener"))
|
||||
|
||||
|
||||
class RFBClientController(RFBClientListener):
|
||||
"""
|
||||
@summary: Class use to manage RFB order and dispatch throw observers for client side
|
||||
"""
|
||||
def __init__(self):
|
||||
self._clientObservers = []
|
||||
#rfb layer to send client orders
|
||||
self._rfbLayer = RFB(self)
|
||||
self._isReady = False
|
||||
|
||||
def getProtocol(self):
|
||||
"""
|
||||
@return: RFB layer build by controller
|
||||
"""
|
||||
return self._rfbLayer
|
||||
|
||||
def addClientObserver(self, observer):
|
||||
"""
|
||||
@summary: Add new observer for this protocol
|
||||
@param observer: new observer
|
||||
"""
|
||||
self._clientObservers.append(observer)
|
||||
observer._clientListener = self
|
||||
|
||||
def getWidth(self):
|
||||
"""
|
||||
@return: width of framebuffer
|
||||
"""
|
||||
return self._rfbLayer._serverInit.width.value
|
||||
|
||||
def getHeight(self):
|
||||
"""
|
||||
@return: height of framebuffer
|
||||
"""
|
||||
return self._rfbLayer._serverInit.height.value
|
||||
|
||||
def getScreen(self):
|
||||
"""
|
||||
@return: (width, height) of screen
|
||||
"""
|
||||
return (self.getWidth(), self.getHeight())
|
||||
|
||||
def setPassword(self, password):
|
||||
"""
|
||||
@summary: set password for vnc authentication type
|
||||
@param password: password for session
|
||||
"""
|
||||
self._rfbLayer._password = password
|
||||
|
||||
def onReady(self):
|
||||
"""
|
||||
@summary: rfb stack is reday to send or receive event
|
||||
"""
|
||||
self._isReady = True
|
||||
for observer in self._clientObservers:
|
||||
observer.onReady()
|
||||
|
||||
def recvRectangle(self, rectangle, pixelFormat, data):
|
||||
"""
|
||||
@summary: Receive rectangle order
|
||||
Main update order type
|
||||
@param rectangle: Rectangle type header of packet
|
||||
@param pixelFormat: pixelFormat struct of current session
|
||||
@param data: image data
|
||||
"""
|
||||
for observer in self._clientObservers:
|
||||
observer.onUpdate(rectangle.width.value, rectangle.height.value, rectangle.x.value, rectangle.y.value, pixelFormat, rectangle.encoding, data)
|
||||
|
||||
def onBell(self):
|
||||
"""
|
||||
@summary: biiiip event
|
||||
"""
|
||||
for observer in self._clientObservers:
|
||||
observer.onBell()
|
||||
|
||||
def onCutText(self, text):
|
||||
"""
|
||||
@summary: receive cut text event
|
||||
@param text: text in cut text event
|
||||
"""
|
||||
for observer in self._clientObservers:
|
||||
observer.onCutText(text)
|
||||
|
||||
def onClose(self):
|
||||
"""
|
||||
@summary: handle on close events
|
||||
"""
|
||||
if not self._isReady:
|
||||
log.debug("Close on non ready layer means authentication error")
|
||||
return
|
||||
for observer in self._clientObservers:
|
||||
observer.onClose()
|
||||
|
||||
def sendKeyEvent(self, isDown, key):
|
||||
"""
|
||||
@summary: Send a key event throw RFB protocol
|
||||
@param isDown: boolean notify if key is pressed or not (True if key is pressed)
|
||||
@param key: ASCII code of key
|
||||
"""
|
||||
if not self._isReady:
|
||||
log.info("Try to send key event on non ready layer")
|
||||
return
|
||||
try:
|
||||
event = KeyEvent()
|
||||
event.downFlag.value = isDown
|
||||
event.key.value = key
|
||||
|
||||
self._rfbLayer.sendKeyEvent(event)
|
||||
except InvalidValue:
|
||||
log.debug("Try to send an invalid key event")
|
||||
|
||||
def sendPointerEvent(self, mask, x, y):
|
||||
"""
|
||||
@summary: Send a pointer event throw RFB protocol
|
||||
@param mask: mask of button if button 1 and 3 are pressed then mask is 00000101
|
||||
@param x: x coordinate of mouse pointer
|
||||
@param y: y pointer of mouse pointer
|
||||
"""
|
||||
if not self._isReady:
|
||||
log.info("Try to send pointer event on non ready layer")
|
||||
return
|
||||
try:
|
||||
event = PointerEvent()
|
||||
event.mask.value = mask
|
||||
event.x.value = x
|
||||
event.y.value = y
|
||||
|
||||
self._rfbLayer.sendPointerEvent(event)
|
||||
except InvalidValue:
|
||||
log.debug("Try to send an invalid pointer event")
|
||||
|
||||
def close(self):
|
||||
"""
|
||||
@summary: close rfb stack
|
||||
"""
|
||||
self._rfbLayer.close()
|
||||
|
||||
|
||||
class ClientFactory(RawLayerClientFactory):
|
||||
"""
|
||||
@summary: Twisted Factory of RFB protocol
|
||||
"""
|
||||
def buildRawLayer(self, addr):
|
||||
"""
|
||||
@summary: Function call by twisted on connection
|
||||
@param addr: address where client try to connect
|
||||
"""
|
||||
controller = RFBClientController()
|
||||
self.buildObserver(controller, addr)
|
||||
return controller.getProtocol()
|
||||
|
||||
def connectionLost(self, rfblayer, reason):
|
||||
"""
|
||||
@summary: Override this method to handle connection lost
|
||||
@param rfblayer: rfblayer that cause connectionLost event
|
||||
@param reason: twisted reason
|
||||
"""
|
||||
#call controller
|
||||
rfblayer._clientListener.onClose()
|
||||
|
||||
def buildObserver(self, controller, addr):
|
||||
"""
|
||||
@summary: Build an RFB observer object
|
||||
@param controller: controller use for rfb session
|
||||
@param addr: destination
|
||||
"""
|
||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "buildObserver", "ClientFactory"))
|
||||
|
||||
|
||||
class RFBClientObserver(object):
|
||||
"""
|
||||
@summary: RFB client protocol observer
|
||||
"""
|
||||
def __init__(self, controller):
|
||||
self._controller = controller
|
||||
self._controller.addClientObserver(self)
|
||||
|
||||
def getController(self):
|
||||
"""
|
||||
@return: RFB controller use by observer
|
||||
"""
|
||||
return self._controller
|
||||
|
||||
def keyEvent(self, isPressed, key):
|
||||
"""
|
||||
@summary: Send a key event
|
||||
@param isPressed: state of key
|
||||
@param key: ASCII code of key
|
||||
"""
|
||||
self._controller.sendKeyEvent(isPressed, key)
|
||||
|
||||
def mouseEvent(self, button, x, y):
|
||||
"""
|
||||
@summary: Send a mouse event to RFB Layer
|
||||
@param button: button number which is pressed (0,1,2,3,4,5,6,7)
|
||||
@param x: x coordinate of mouse pointer
|
||||
@param y: y coordinate of mouse pointer
|
||||
"""
|
||||
mask = 0
|
||||
if button == 1:
|
||||
mask = 1
|
||||
elif button > 1:
|
||||
mask = 1 << button - 1
|
||||
|
||||
self._controller.sendPointerEvent(mask, x, y)
|
||||
|
||||
def onReady(self):
|
||||
"""
|
||||
@summary: Event when network stack is ready to receive or send event
|
||||
"""
|
||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onReady", "RFBClientObserver"))
|
||||
|
||||
def onClose(self):
|
||||
"""
|
||||
@summary: On close event
|
||||
"""
|
||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onClose", "RFBClientObserver"))
|
||||
|
||||
def onUpdate(self, width, height, x, y, pixelFormat, encoding, data):
|
||||
"""
|
||||
@summary: Receive FrameBuffer update
|
||||
@param width : width of image
|
||||
@param height : height of image
|
||||
@param x : x position
|
||||
@param y : y position
|
||||
@param pixelFormat : pixel format struct from rfb.types
|
||||
@param encoding : encoding struct from rfb.types
|
||||
@param data : in respect of dataFormat and pixelFormat
|
||||
"""
|
||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onUpdate", "RFBClientObserver"))
|
||||
|
||||
def onCutText(self, text):
|
||||
"""
|
||||
@summary: event when server send cut text event
|
||||
@param text: text received
|
||||
"""
|
||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onCutText", "RFBClientObserver"))
|
||||
|
||||
def onBell(self):
|
||||
"""
|
||||
@summary: event when server send biiip
|
||||
"""
|
||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onBell", "RFBClientObserver"))
|
||||
145
rdpy/ui/qt4.py
145
rdpy/ui/qt4.py
@@ -23,13 +23,12 @@ Qt specific code
|
||||
QRemoteDesktop is a widget use for render in rdpy
|
||||
"""
|
||||
|
||||
from PyQt4 import QtGui, QtCore
|
||||
from rdpy.protocol.rfb.rfb import RFBClientObserver
|
||||
from rdpy.protocol.rdp.rdp import RDPClientObserver
|
||||
from rdpy.core.error import CallPureVirtualFuntion
|
||||
from PyQt5 import QtWidgets
|
||||
from rdpy.core.rdp import RDPClientObserver
|
||||
from rdpy.model.error import CallPureVirtualFuntion
|
||||
import sys
|
||||
|
||||
import rdpy.core.log as log
|
||||
import rdpy.model.log as log
|
||||
import rle
|
||||
|
||||
class QAdaptor(object):
|
||||
@@ -72,112 +71,10 @@ def qtImageFormatFromRFBPixelFormat(pixelFormat):
|
||||
@summary: convert RFB pixel format to QtGui.QImage format
|
||||
"""
|
||||
if pixelFormat.BitsPerPixel.value == 32:
|
||||
return QtGui.QImage.Format_RGB32
|
||||
return QtWidgets.QImage.Format_RGB32
|
||||
elif pixelFormat.BitsPerPixel.value == 16:
|
||||
return QtGui.QImage.Format_RGB16
|
||||
return QtWidgets.QImage.Format_RGB16
|
||||
|
||||
class RFBClientQt(RFBClientObserver, QAdaptor):
|
||||
"""
|
||||
@summary: QAdaptor for specific RFB protocol stack
|
||||
is to an RFB observer
|
||||
"""
|
||||
def __init__(self, controller):
|
||||
"""
|
||||
@param controller: controller for observer
|
||||
@param width: width of widget
|
||||
@param height: height of widget
|
||||
"""
|
||||
RFBClientObserver.__init__(self, controller)
|
||||
self._widget = QRemoteDesktop(1024, 800, self)
|
||||
|
||||
def getWidget(self):
|
||||
"""
|
||||
@return: widget use for render
|
||||
"""
|
||||
return self._widget
|
||||
|
||||
def onUpdate(self, width, height, x, y, pixelFormat, encoding, data):
|
||||
"""
|
||||
@summary: Implement RFBClientObserver interface
|
||||
@param width: width of new image
|
||||
@param height: height of new image
|
||||
@param x: x position of new image
|
||||
@param y: y position of new image
|
||||
@param pixelFormat: pixefFormat structure in rfb.message.PixelFormat
|
||||
@param encoding: encoding type rfb.message.Encoding
|
||||
@param data: image data in accordance with pixel format and encoding
|
||||
"""
|
||||
imageFormat = qtImageFormatFromRFBPixelFormat(pixelFormat)
|
||||
if imageFormat is None:
|
||||
log.error("Receive image in bad format")
|
||||
return
|
||||
|
||||
image = QtGui.QImage(data, width, height, imageFormat)
|
||||
self._widget.notifyImage(x, y, image, width, height)
|
||||
|
||||
def onCutText(self, text):
|
||||
"""
|
||||
@summary: event when server send cut text event
|
||||
@param text: text received
|
||||
"""
|
||||
|
||||
def onBell(self):
|
||||
"""
|
||||
@summary: event when server send biiip
|
||||
"""
|
||||
|
||||
def onReady(self):
|
||||
"""
|
||||
@summary: Event when network stack is ready to receive or send event
|
||||
"""
|
||||
(width, height) = self._controller.getScreen()
|
||||
self._widget.resize(width, height)
|
||||
|
||||
def sendMouseEvent(self, e, isPressed):
|
||||
"""
|
||||
@summary: Convert Qt mouse event to RFB mouse event
|
||||
@param e: qMouseEvent
|
||||
@param isPressed: event come from press or release action
|
||||
"""
|
||||
button = e.button()
|
||||
buttonNumber = 0
|
||||
if button == QtCore.Qt.LeftButton:
|
||||
buttonNumber = 1
|
||||
elif button == QtCore.Qt.MidButton:
|
||||
buttonNumber = 2
|
||||
elif button == QtCore.Qt.RightButton:
|
||||
buttonNumber = 3
|
||||
self.mouseEvent(buttonNumber, e.pos().x(), e.pos().y())
|
||||
|
||||
def sendKeyEvent(self, e, isPressed):
|
||||
"""
|
||||
@summary: Convert Qt key press event to RFB press event
|
||||
@param e: qKeyEvent
|
||||
@param isPressed: event come from press or release action
|
||||
"""
|
||||
self.keyEvent(isPressed, e.nativeVirtualKey())
|
||||
|
||||
def sendWheelEvent(self, e):
|
||||
"""
|
||||
@summary: Convert Qt wheel event to RFB Wheel event
|
||||
@param e: QKeyEvent
|
||||
@param isPressed: event come from press or release action
|
||||
"""
|
||||
pass
|
||||
|
||||
def closeEvent(self, e):
|
||||
"""
|
||||
@summary: Call when you want to close connection
|
||||
@param: QCloseEvent
|
||||
"""
|
||||
self._controller.close()
|
||||
|
||||
def onClose(self):
|
||||
"""
|
||||
@summary: Call when stack is close
|
||||
"""
|
||||
#do something maybe a message
|
||||
pass
|
||||
|
||||
def RDPBitmapToQtImage(width, height, bitsPerPixel, isCompress, data):
|
||||
"""
|
||||
@@ -195,36 +92,36 @@ def RDPBitmapToQtImage(width, height, bitsPerPixel, isCompress, data):
|
||||
if isCompress:
|
||||
buf = bytearray(width * height * 2)
|
||||
rle.bitmap_decompress(buf, width, height, data, 2)
|
||||
image = QtGui.QImage(buf, width, height, QtGui.QImage.Format_RGB555)
|
||||
image = QtWidgets.QImage(buf, width, height, QtWidgets.QImage.Format_RGB555)
|
||||
else:
|
||||
image = QtGui.QImage(data, width, height, QtGui.QImage.Format_RGB555).transformed(QtGui.QMatrix(1.0, 0.0, 0.0, -1.0, 0.0, 0.0))
|
||||
image = QtWidgets.QImage(data, width, height, QtWidgets.QImage.Format_RGB555).transformed(QtWidgets.QMatrix(1.0, 0.0, 0.0, -1.0, 0.0, 0.0))
|
||||
|
||||
elif bitsPerPixel == 16:
|
||||
if isCompress:
|
||||
buf = bytearray(width * height * 2)
|
||||
rle.bitmap_decompress(buf, width, height, data, 2)
|
||||
image = QtGui.QImage(buf, width, height, QtGui.QImage.Format_RGB16)
|
||||
image = QtWidgets.QImage(buf, width, height, QtWidgets.QImage.Format_RGB16)
|
||||
else:
|
||||
image = QtGui.QImage(data, width, height, QtGui.QImage.Format_RGB16).transformed(QtGui.QMatrix(1.0, 0.0, 0.0, -1.0, 0.0, 0.0))
|
||||
image = QtWidgets.QImage(data, width, height, QtWidgets.QImage.Format_RGB16).transformed(QtWidgets.QMatrix(1.0, 0.0, 0.0, -1.0, 0.0, 0.0))
|
||||
|
||||
elif bitsPerPixel == 24:
|
||||
if isCompress:
|
||||
buf = bytearray(width * height * 3)
|
||||
rle.bitmap_decompress(buf, width, height, data, 3)
|
||||
image = QtGui.QImage(buf, width, height, QtGui.QImage.Format_RGB888)
|
||||
image = QtWidgets.QImage(buf, width, height, QtWidgets.QImage.Format_RGB888)
|
||||
else:
|
||||
image = QtGui.QImage(data, width, height, QtGui.QImage.Format_RGB888).transformed(QtGui.QMatrix(1.0, 0.0, 0.0, -1.0, 0.0, 0.0))
|
||||
image = QtWidgets.QImage(data, width, height, QtWidgets.QImage.Format_RGB888).transformed(QtWidgets.QMatrix(1.0, 0.0, 0.0, -1.0, 0.0, 0.0))
|
||||
|
||||
elif bitsPerPixel == 32:
|
||||
if isCompress:
|
||||
buf = bytearray(width * height * 4)
|
||||
rle.bitmap_decompress(buf, width, height, data, 4)
|
||||
image = QtGui.QImage(buf, width, height, QtGui.QImage.Format_RGB32)
|
||||
image = QtWidgets.QImage(buf, width, height, QtWidgets.QImage.Format_RGB32)
|
||||
else:
|
||||
image = QtGui.QImage(data, width, height, QtGui.QImage.Format_RGB32).transformed(QtGui.QMatrix(1.0, 0.0, 0.0, -1.0, 0.0, 0.0))
|
||||
image = QtWidgets.QImage(data, width, height, QtWidgets.QImage.Format_RGB32).transformed(QtWidgets.QMatrix(1.0, 0.0, 0.0, -1.0, 0.0, 0.0))
|
||||
else:
|
||||
log.error("Receive image in bad format")
|
||||
image = QtGui.QImage(width, height, QtGui.QImage.Format_RGB32)
|
||||
image = QtWidgets.QImage(width, height, QtWidgets.QImage.Format_RGB32)
|
||||
return image
|
||||
|
||||
class RDPClientQt(RDPClientObserver, QAdaptor):
|
||||
@@ -330,7 +227,7 @@ class RDPClientQt(RDPClientObserver, QAdaptor):
|
||||
#do something maybe a message
|
||||
|
||||
|
||||
class QRemoteDesktop(QtGui.QWidget):
|
||||
class QRemoteDesktop(QtWidgets.QWidget):
|
||||
"""
|
||||
@summary: Qt display widget
|
||||
"""
|
||||
@@ -348,7 +245,7 @@ class QRemoteDesktop(QtGui.QWidget):
|
||||
#bind mouse event
|
||||
self.setMouseTracking(True)
|
||||
#buffer image
|
||||
self._buffer = QtGui.QImage(width, height, QtGui.QImage.Format_RGB32)
|
||||
self._buffer = QtWidgets.QImage(width, height, QtWidgets.QImage.Format_RGB32)
|
||||
|
||||
def notifyImage(self, x, y, qimage, width, height):
|
||||
"""
|
||||
@@ -358,7 +255,7 @@ class QRemoteDesktop(QtGui.QWidget):
|
||||
@param qimage: new QImage
|
||||
"""
|
||||
#fill buffer image
|
||||
with QtGui.QPainter(self._buffer) as qp:
|
||||
with QtWidgets.QPainter(self._buffer) as qp:
|
||||
qp.drawImage(x, y, qimage, 0, 0, width, height)
|
||||
#force update
|
||||
self.update()
|
||||
@@ -369,8 +266,8 @@ class QRemoteDesktop(QtGui.QWidget):
|
||||
@param width: {int} width of widget
|
||||
@param height: {int} height of widget
|
||||
"""
|
||||
self._buffer = QtGui.QImage(width, height, QtGui.QImage.Format_RGB32)
|
||||
QtGui.QWidget.resize(self, width, height)
|
||||
self._buffer = QtWidgets.QImage(width, height, QtWidgets.QImage.Format_RGB32)
|
||||
QtWidgets.QWidget.resize(self, width, height)
|
||||
|
||||
def paintEvent(self, e):
|
||||
"""
|
||||
@@ -378,7 +275,7 @@ class QRemoteDesktop(QtGui.QWidget):
|
||||
@param e: QEvent
|
||||
"""
|
||||
#draw in widget
|
||||
with QtGui.QPainter(self) as qp:
|
||||
with QtWidgets.QPainter(self) as qp:
|
||||
qp.drawImage(0, 0, self._buffer)
|
||||
|
||||
def mouseMoveEvent(self, event):
|
||||
|
||||
18
setup.py
18
setup.py
@@ -4,7 +4,7 @@ import setuptools
|
||||
from distutils.core import setup, Extension
|
||||
|
||||
setup(name='rdpy',
|
||||
version='1.3.2',
|
||||
version='2.0.0',
|
||||
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.
|
||||
@@ -16,14 +16,11 @@ setup(name='rdpy',
|
||||
url='https://github.com/citronneur/rdpy',
|
||||
packages=[
|
||||
'rdpy',
|
||||
'rdpy.core',
|
||||
'rdpy.model',
|
||||
'rdpy.security',
|
||||
'rdpy.protocol',
|
||||
'rdpy.protocol.rdp',
|
||||
'rdpy.protocol.rdp.pdu',
|
||||
'rdpy.protocol.rdp.nla',
|
||||
'rdpy.protocol.rdp.t125',
|
||||
'rdpy.protocol.rfb',
|
||||
'rdpy.core.pdu',
|
||||
'rdpy.core.nla',
|
||||
'rdpy.core.t125',
|
||||
'rdpy.ui'
|
||||
],
|
||||
ext_modules=[Extension('rle', ['ext/rle.c'])],
|
||||
@@ -37,10 +34,9 @@ setup(name='rdpy',
|
||||
'bin/rdpy-vncscreenshot.py'
|
||||
],
|
||||
install_requires=[
|
||||
'twisted',
|
||||
'pyopenssl',
|
||||
'PyQt5',
|
||||
'PyQt5-sip',
|
||||
'service_identity',
|
||||
'qt4reactor',
|
||||
'rsa',
|
||||
'pyasn1'
|
||||
],
|
||||
|
||||
@@ -26,9 +26,9 @@ import os, sys
|
||||
sys.path.insert(1, os.path.join(sys.path[0], '..'))
|
||||
|
||||
import unittest
|
||||
import rdpy.protocol.rdp.t125.ber as ber
|
||||
import rdpy.core.t125.ber as ber
|
||||
import rdpy.core.type as type
|
||||
import rdpy.core.error as error
|
||||
|
||||
|
||||
class BERTest(unittest.TestCase):
|
||||
"""
|
||||
|
||||
@@ -25,7 +25,7 @@ import os, sys
|
||||
# Change path so we find rdpy
|
||||
sys.path.insert(1, os.path.join(sys.path[0], '..'))
|
||||
|
||||
from rdpy.protocol.rdp.nla import cssp, ntlm
|
||||
from rdpy.core.nla import ntlm, cssp
|
||||
from rdpy.security import rc4
|
||||
|
||||
pubKeyHex = """
|
||||
|
||||
@@ -26,7 +26,7 @@ import os, sys
|
||||
sys.path.insert(1, os.path.join(sys.path[0], '..'))
|
||||
|
||||
import unittest
|
||||
from rdpy.protocol.rdp import lic, sec
|
||||
from rdpy.core import lic, sec
|
||||
import rdpy.core.type as type
|
||||
|
||||
#dump of server request
|
||||
|
||||
@@ -26,7 +26,7 @@ import os, sys
|
||||
sys.path.insert(1, os.path.join(sys.path[0], '..'))
|
||||
|
||||
import unittest
|
||||
import rdpy.protocol.rdp.t125.per as per
|
||||
import rdpy.core.t125.per as per
|
||||
import rdpy.core.type as type
|
||||
import rdpy.core.error as error
|
||||
|
||||
@@ -81,7 +81,7 @@ class PERTest(unittest.TestCase):
|
||||
s.writeType((per.writeLength(type.sizeof(v)), v))
|
||||
s.pos = 0
|
||||
|
||||
self.assertTrue(per.readInteger(s) == 3, "invalid readLength for type %s"%t)
|
||||
self.assertTrue(per.readInteger(s) == 3, "invalid readLength for type %s" % t)
|
||||
|
||||
#error case
|
||||
for l in [0, 3, 5]:
|
||||
|
||||
@@ -26,9 +26,9 @@ import os, sys
|
||||
sys.path.insert(1, os.path.join(sys.path[0], '..'))
|
||||
|
||||
import unittest
|
||||
import rdpy.protocol.rdp.tpkt as tpkt
|
||||
import rdpy.core.tpkt as tpkt
|
||||
import rdpy.core.type as type
|
||||
import rdpy.core.error as error
|
||||
|
||||
|
||||
class TPKTTest(unittest.TestCase):
|
||||
"""
|
||||
|
||||
@@ -26,7 +26,7 @@ import os, sys
|
||||
sys.path.insert(1, os.path.join(sys.path[0], '..'))
|
||||
|
||||
import unittest
|
||||
import rdpy.protocol.rdp.x224 as x224
|
||||
import rdpy.core.x224 as x224
|
||||
import rdpy.core.type as type
|
||||
import rdpy.core.error as error
|
||||
|
||||
|
||||
Reference in New Issue
Block a user