forked from shaba/openuds
Started client part
This commit is contained in:
parent
dc006e7cbc
commit
c70d94e866
@ -37,6 +37,7 @@ from PyQt4 import QtCore, QtGui
|
|||||||
import six
|
import six
|
||||||
|
|
||||||
from uds.rest import RestRequest
|
from uds.rest import RestRequest
|
||||||
|
from uds.forward import forward
|
||||||
|
|
||||||
|
|
||||||
def done(data):
|
def done(data):
|
||||||
@ -46,6 +47,10 @@ def done(data):
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app = QtGui.QApplication(sys.argv)
|
app = QtGui.QApplication(sys.argv)
|
||||||
|
|
||||||
|
if six.PY3 is False:
|
||||||
|
import threading
|
||||||
|
threading._DummyThread._Thread__stop = lambda x: 42
|
||||||
|
|
||||||
# First parameter must be url
|
# First parameter must be url
|
||||||
try:
|
try:
|
||||||
uri = sys.argv[1]
|
uri = sys.argv[1]
|
||||||
|
6
client/src/UDSResources.qrc
Normal file
6
client/src/UDSResources.qrc
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<RCC>
|
||||||
|
<qresource prefix="images">
|
||||||
|
<file alias="logo-uds-small">images/logo-uds-small.png</file>
|
||||||
|
<file alias="logo-uds-big">images/logo-uds.png</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
49
client/src/UDSWindow.py
Normal file
49
client/src/UDSWindow.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Form implementation generated from reading ui file 'UDSWindow.ui'
|
||||||
|
#
|
||||||
|
# Created: Fri Mar 27 15:03:01 2015
|
||||||
|
# by: PyQt4 UI code generator 4.11.2
|
||||||
|
#
|
||||||
|
# WARNING! All changes made in this file will be lost!
|
||||||
|
|
||||||
|
from PyQt4 import QtCore, QtGui
|
||||||
|
|
||||||
|
try:
|
||||||
|
_fromUtf8 = QtCore.QString.fromUtf8
|
||||||
|
except AttributeError:
|
||||||
|
def _fromUtf8(s):
|
||||||
|
return s
|
||||||
|
|
||||||
|
try:
|
||||||
|
_encoding = QtGui.QApplication.UnicodeUTF8
|
||||||
|
def _translate(context, text, disambig):
|
||||||
|
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
||||||
|
except AttributeError:
|
||||||
|
def _translate(context, text, disambig):
|
||||||
|
return QtGui.QApplication.translate(context, text, disambig)
|
||||||
|
|
||||||
|
class Ui_MainWindow(object):
|
||||||
|
def setupUi(self, MainWindow):
|
||||||
|
MainWindow.setObjectName(_fromUtf8("MainWindow"))
|
||||||
|
MainWindow.resize(282, 185)
|
||||||
|
self.centralwidget = QtGui.QWidget(MainWindow)
|
||||||
|
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
|
||||||
|
MainWindow.setCentralWidget(self.centralwidget)
|
||||||
|
|
||||||
|
self.retranslateUi(MainWindow)
|
||||||
|
QtCore.QMetaObject.connectSlotsByName(MainWindow)
|
||||||
|
|
||||||
|
def retranslateUi(self, MainWindow):
|
||||||
|
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import sys
|
||||||
|
app = QtGui.QApplication(sys.argv)
|
||||||
|
MainWindow = QtGui.QMainWindow()
|
||||||
|
ui = Ui_MainWindow()
|
||||||
|
ui.setupUi(MainWindow)
|
||||||
|
MainWindow.show()
|
||||||
|
sys.exit(app.exec_())
|
||||||
|
|
54
client/src/UDSWindow.ui
Normal file
54
client/src/UDSWindow.ui
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>MainWindow</class>
|
||||||
|
<widget class="QMainWindow" name="MainWindow">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>282</width>
|
||||||
|
<height>185</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>MainWindow</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="centralwidget">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="autoFillBackground">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="pixmap">
|
||||||
|
<pixmap resource="UDSResources.qrc">:/images/logo-uds-small</pixmap>
|
||||||
|
</property>
|
||||||
|
<property name="scaledContents">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QProgressBar" name="progressBar">
|
||||||
|
<property name="value">
|
||||||
|
<number>24</number>
|
||||||
|
</property>
|
||||||
|
<property name="textVisible">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<resources>
|
||||||
|
<include location="UDSResources.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
BIN
client/src/images/logo-uds-small.png
Normal file
BIN
client/src/images/logo-uds-small.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
BIN
client/src/images/logo-uds.png
Normal file
BIN
client/src/images/logo-uds.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 36 KiB |
123
client/src/uds/forward.py
Normal file
123
client/src/uds/forward.py
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
# Based on forward.py from paramiko
|
||||||
|
# Copyright (C) 2003-2007 Robey Pointer <robeypointer@gmail.com>
|
||||||
|
# https://github.com/paramiko/paramiko/blob/master/demos/forward.py
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import select
|
||||||
|
import SocketServer
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import paramiko
|
||||||
|
import threading
|
||||||
|
|
||||||
|
g_verbose = True
|
||||||
|
|
||||||
|
|
||||||
|
class ForwardServer (SocketServer.ThreadingTCPServer):
|
||||||
|
daemon_threads = True
|
||||||
|
allow_reuse_address = True
|
||||||
|
|
||||||
|
|
||||||
|
class Handler (SocketServer.BaseRequestHandler):
|
||||||
|
|
||||||
|
def handle(self):
|
||||||
|
try:
|
||||||
|
chan = self.ssh_transport.open_channel('direct-tcpip',
|
||||||
|
(self.chain_host, self.chain_port),
|
||||||
|
self.request.getpeername())
|
||||||
|
except Exception as e:
|
||||||
|
verbose('Incoming request to %s:%d failed: %s' % (self.chain_host,
|
||||||
|
self.chain_port,
|
||||||
|
repr(e)))
|
||||||
|
return
|
||||||
|
if chan is None:
|
||||||
|
verbose('Incoming request to %s:%d was rejected by the SSH server.' %
|
||||||
|
(self.chain_host, self.chain_port))
|
||||||
|
return
|
||||||
|
|
||||||
|
verbose('Connected! Tunnel open %r -> %r -> %r' % (self.request.getpeername(),
|
||||||
|
chan.getpeername(), (self.chain_host, self.chain_port)))
|
||||||
|
while self.event.is_set() is False:
|
||||||
|
r, w, x = select.select([self.request, chan], [], [], 1)
|
||||||
|
|
||||||
|
if self.request in r:
|
||||||
|
data = self.request.recv(1024)
|
||||||
|
if len(data) == 0:
|
||||||
|
break
|
||||||
|
chan.send(data)
|
||||||
|
if chan in r:
|
||||||
|
data = chan.recv(1024)
|
||||||
|
if len(data) == 0:
|
||||||
|
break
|
||||||
|
self.request.send(data)
|
||||||
|
|
||||||
|
peername = self.request.getpeername()
|
||||||
|
chan.close()
|
||||||
|
self.request.close()
|
||||||
|
verbose('Tunnel closed from %r' % (peername,))
|
||||||
|
|
||||||
|
|
||||||
|
def verbose(s):
|
||||||
|
if g_verbose:
|
||||||
|
print(s)
|
||||||
|
|
||||||
|
|
||||||
|
class ForwardThread(threading.Thread):
|
||||||
|
def __init__(self, server, port, username, password, localPort, redirectHost, redirectPort):
|
||||||
|
threading.Thread.__init__(self)
|
||||||
|
self.client = None
|
||||||
|
self.fs = None
|
||||||
|
|
||||||
|
self.server = server
|
||||||
|
self.port = int(port)
|
||||||
|
self.username = username
|
||||||
|
self.password = password
|
||||||
|
|
||||||
|
self.localPort = int(localPort)
|
||||||
|
self.redirectHost = redirectHost
|
||||||
|
self.redirectPort = redirectPort
|
||||||
|
|
||||||
|
self.stopEvent = threading.Event()
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self.client = paramiko.SSHClient()
|
||||||
|
self.client.load_system_host_keys()
|
||||||
|
self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||||
|
|
||||||
|
verbose('Connecting to ssh host %s:%d ...' % (self.server, self.port))
|
||||||
|
|
||||||
|
self.client.connect(self.server, self.port, username=self.username, password=self.password)
|
||||||
|
|
||||||
|
class SubHander (Handler):
|
||||||
|
chain_host = self.redirectHost
|
||||||
|
chain_port = self.redirectPort
|
||||||
|
ssh_transport = self.client.get_transport()
|
||||||
|
event = self.stopEvent
|
||||||
|
|
||||||
|
self.fs = ForwardServer(('', self.redirectPort), SubHander)
|
||||||
|
self.fs.serve_forever()
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
try:
|
||||||
|
self.stopEvent.set()
|
||||||
|
self.fs.shutdown()
|
||||||
|
|
||||||
|
if self.client is not None:
|
||||||
|
self.client.close()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def forward(server, port, username, password, localPort, redirectHost, redirectPort):
|
||||||
|
port, redirectPort = int(port), int(redirectPort)
|
||||||
|
|
||||||
|
|
||||||
|
verbose('Connected')
|
||||||
|
|
||||||
|
ft = ForwardThread(server, port, username, password, localPort, redirectHost, redirectPort)
|
||||||
|
|
||||||
|
ft.start()
|
||||||
|
|
||||||
|
return ft
|
15
client/src/update.sh
Executable file
15
client/src/update.sh
Executable file
@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
|
||||||
|
function process {
|
||||||
|
for a in *.ui; do
|
||||||
|
pyuic4 $a -o `basename $a .ui`.py -x
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
pyrcc4 -py3 UDSResources.qrc -o UDSResources_rc.py
|
||||||
|
|
||||||
|
|
||||||
|
# process current directory ui's
|
||||||
|
process
|
||||||
|
|
@ -57,6 +57,7 @@ logger = logging.getLogger(__name__)
|
|||||||
CLIENT_VERSION = '1.7.0'
|
CLIENT_VERSION = '1.7.0'
|
||||||
REQUIRED_CLIENT_VERSION = '1.7.0'
|
REQUIRED_CLIENT_VERSION = '1.7.0'
|
||||||
|
|
||||||
|
|
||||||
# Enclosed methods under /actor path
|
# Enclosed methods under /actor path
|
||||||
class Client(Handler):
|
class Client(Handler):
|
||||||
'''
|
'''
|
||||||
@ -106,44 +107,18 @@ class Client(Handler):
|
|||||||
except Exception:
|
except Exception:
|
||||||
return Client.result(error=errors.ACCESS_DENIED)
|
return Client.result(error=errors.ACCESS_DENIED)
|
||||||
|
|
||||||
password = cryptoManager().xor(self._args[1], data['password']).decode('utf-8')
|
self._request.user = User.objects.get(uuid=data['user'])
|
||||||
user = User.objects.get(uuid=data['user'])
|
|
||||||
userService = UserService.objects.get(uuid=data['service'])
|
|
||||||
transport = Transport.objects.get(uuid=data['transport'])
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
logger.debug('idService: {}, idTransport: {}, user: {}'.format(data['service'], data['transport'], data['user']))
|
res = getService(self._request, data['service'], data['transport'])
|
||||||
|
if res is not None:
|
||||||
|
ip, userService, userServiceInstance, transport, transportInstance = res
|
||||||
|
password = cryptoManager().xor(self._args[1], data['password']).decode('utf-8')
|
||||||
|
|
||||||
if userService.isInMaintenance():
|
transportInfo = transportInstance.getUDSTransportData(userService, transport, ip, self.request.os, self._request.user, password, self._request)
|
||||||
return Client.result(error=errors.SERVICE_IN_MAINTENANCE)
|
return Client.result(transportInfo)
|
||||||
|
except Exception as e:
|
||||||
logger.debug('Found service: {0}'.format(userService))
|
|
||||||
|
|
||||||
# Test if the service is ready
|
|
||||||
if userService.isReady():
|
|
||||||
log.doLog(userService, log.INFO, "User {0} from {1} has initiated access".format(user.name, self._request.ip), log.WEB)
|
|
||||||
# If ready, show transport for this service, if also ready ofc
|
|
||||||
userServiceIntance = userService.getInstance()
|
|
||||||
ip = userServiceIntance.getIp()
|
|
||||||
events.addEvent(userService.deployed_service, events.ET_ACCESS, username=user.name, srcip=self._request.ip, dstip=ip, uniqueid=userService.unique_id)
|
|
||||||
if ip is not None:
|
|
||||||
transportInstance = transport.getInstance()
|
|
||||||
if transportInstance.isAvailableFor(ip):
|
|
||||||
userService.setConnectionSource(self._request.ip, 'unknown')
|
|
||||||
log.doLog(userService, log.INFO, "User service ready, rendering transport", log.WEB)
|
|
||||||
UserServiceManager.manager().notifyPreconnect(userService, transportInstance.processedUser(userService, user), transportInstance.protocol)
|
|
||||||
transportInfo = transportInstance.getUDSTransportData(userService, transport, ip, self.request.os, user, password, self._request)
|
|
||||||
return Client.result(transportInfo)
|
|
||||||
else:
|
|
||||||
log.doLog(userService, log.WARN, "User service is not accessible (ip {0})".format(ip), log.TRANSPORT)
|
|
||||||
logger.debug('Transport is not ready for user service {0}'.format(userService))
|
|
||||||
else:
|
|
||||||
logger.debug('Ip not available from user service {0}'.format(userService))
|
|
||||||
else:
|
|
||||||
log.doLog(userService, log.WARN, "User {0} from {1} tried to access, but machine was not ready".format(user.name, self._request.ip), log.WEB)
|
|
||||||
# Not ready, show message and return to this page in a while
|
|
||||||
return Client.result(error=errors.SERVICE_NOT_READY)
|
|
||||||
except Exception:
|
|
||||||
logger.exception("Exception")
|
logger.exception("Exception")
|
||||||
|
return Client.result(error=six.text_type(e))
|
||||||
|
|
||||||
raise RequestError('Request error')
|
return Client.result(error=errors.SERVICE_NOT_READY)
|
||||||
|
Loading…
Reference in New Issue
Block a user