mirror of
https://github.com/dkmstr/openuds.git
synced 2024-12-22 13:34:04 +03:00
merged from 2.2
This commit is contained in:
commit
e37b929adc
@ -219,7 +219,7 @@ class UDSClient(QtGui.QMainWindow):
|
|||||||
QtCore.QTimer.singleShot(10000, self.getTransportData)
|
QtCore.QTimer.singleShot(10000, self.getTransportData)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception('Got exception executing script:')
|
#logger.exception('Got exception executing script:')
|
||||||
self.showError(e)
|
self.showError(e)
|
||||||
|
|
||||||
def endScript(self):
|
def endScript(self):
|
||||||
|
@ -46,7 +46,7 @@ logging.basicConfig(
|
|||||||
filename=logFile,
|
filename=logFile,
|
||||||
filemode='a',
|
filemode='a',
|
||||||
format='%(levelname)s %(asctime)s %(message)s',
|
format='%(levelname)s %(asctime)s %(message)s',
|
||||||
level=logging.DEBUG
|
level=logging.INFO
|
||||||
)
|
)
|
||||||
|
|
||||||
logger = logging.getLogger('udsclient')
|
logger = logging.getLogger('udsclient')
|
||||||
|
@ -38,6 +38,7 @@ from uds.models import Authenticator
|
|||||||
from uds.models import DeployedService
|
from uds.models import DeployedService
|
||||||
from uds.models import Transport
|
from uds.models import Transport
|
||||||
from uds.models import TicketStore
|
from uds.models import TicketStore
|
||||||
|
from uds.core.managers import cryptoManager
|
||||||
from uds.core.util.model import processUuid
|
from uds.core.util.model import processUuid
|
||||||
from uds.core.util import tools
|
from uds.core.util import tools
|
||||||
|
|
||||||
@ -207,7 +208,7 @@ class Tickets(Handler):
|
|||||||
|
|
||||||
data = {
|
data = {
|
||||||
'username': username,
|
'username': username,
|
||||||
'password': password,
|
'password': cryptoManager().encrypt(password),
|
||||||
'realname': realname,
|
'realname': realname,
|
||||||
'groups': groups,
|
'groups': groups,
|
||||||
'auth': auth.uuid,
|
'auth': auth.uuid,
|
||||||
|
@ -59,7 +59,7 @@ class CacheCleaner(Job):
|
|||||||
|
|
||||||
class TicketStoreCleaner(Job):
|
class TicketStoreCleaner(Job):
|
||||||
|
|
||||||
frecuency = 3600 * 12 # every twelve hours
|
frecuency = 60 # every minute (60 seconds)
|
||||||
friendly_name = 'Ticket Storage Cleaner'
|
friendly_name = 'Ticket Storage Cleaner'
|
||||||
|
|
||||||
def __init__(self, environment):
|
def __init__(self, environment):
|
||||||
|
@ -35,6 +35,7 @@ from __future__ import unicode_literals
|
|||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from uds.models import TicketStore
|
from uds.models import TicketStore
|
||||||
from uds.core.auths import auth
|
from uds.core.auths import auth
|
||||||
|
from uds.core.managers import cryptoManager
|
||||||
|
|
||||||
import six
|
import six
|
||||||
import logging
|
import logging
|
||||||
@ -55,8 +56,11 @@ def dict2resp(dct):
|
|||||||
def guacamole(request, tunnelId):
|
def guacamole(request, tunnelId):
|
||||||
logger.debug('Received credentials request for tunnel id {0}'.format(tunnelId))
|
logger.debug('Received credentials request for tunnel id {0}'.format(tunnelId))
|
||||||
|
|
||||||
|
tunnelId, scrambler = tunnelId.split('.')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
val = TicketStore.get(tunnelId, invalidate=False)
|
val = TicketStore.get(tunnelId, invalidate=False)
|
||||||
|
val['password'] = cryptoManager().xor(val['password'], scrambler)
|
||||||
|
|
||||||
response = dict2resp(val)
|
response = dict2resp(val)
|
||||||
except Exception:
|
except Exception:
|
||||||
|
@ -25,9 +25,9 @@
|
|||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
"""
|
'''
|
||||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
"""
|
'''
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ import logging
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
__updated__ = '2016-09-16'
|
__updated__ = '2018-07-19'
|
||||||
|
|
||||||
|
|
||||||
class TicketStore(UUIDModel):
|
class TicketStore(UUIDModel):
|
||||||
@ -78,7 +78,7 @@ class TicketStore(UUIDModel):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def generateUuid():
|
def generateUuid():
|
||||||
# more owner is this:
|
# more secure is this:
|
||||||
# ''.join(random.SystemRandom().choice(string.ascii_lowercase + string.digits) for _ in range(40))
|
# ''.join(random.SystemRandom().choice(string.ascii_lowercase + string.digits) for _ in range(40))
|
||||||
return cryptoManager().randomString(40)
|
return cryptoManager().randomString(40)
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ class TicketStore(UUIDModel):
|
|||||||
validator = pickle.dumps(validator)
|
validator = pickle.dumps(validator)
|
||||||
data = pickle.dumps(data)
|
data = pickle.dumps(data)
|
||||||
if secure:
|
if secure:
|
||||||
data = cryptoManager().encrypt(data)
|
pass
|
||||||
|
|
||||||
return TicketStore.objects.create(stamp=getSqlDatetime(), data=data, validator=validator, validity=validity, owner=owner).uuid
|
return TicketStore.objects.create(stamp=getSqlDatetime(), data=data, validator=validator, validity=validity, owner=owner).uuid
|
||||||
|
|
||||||
@ -106,16 +106,16 @@ class TicketStore(UUIDModel):
|
|||||||
|
|
||||||
data = pickle.dumps(data)
|
data = pickle.dumps(data)
|
||||||
if secure:
|
if secure:
|
||||||
data = cryptoManager().encrypt()
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
t = TicketStore.objects.get(uuid=uuid, owner=owner)
|
t = TicketStore.objects.get(uuid=uuid)
|
||||||
t.data = data
|
t.data = pickle.dumps(data)
|
||||||
t.stamp = getSqlDatetime()
|
t.stamp = getSqlDatetime()
|
||||||
t.validity = validity
|
t.validity = validity
|
||||||
t.save()
|
t.save()
|
||||||
except TicketStore.DoesNotExist:
|
except TicketStore.DoesNotExist:
|
||||||
t = TicketStore.objects.create(uuid=uuid, stamp=getSqlDatetime(), data=data, validator=validator, validity=validity, owner=owner)
|
t = TicketStore.objects.create(uuid=uuid, stamp=getSqlDatetime(), data=pickle.dumps(data), validator=validator, validity=validity)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get(uuid, invalidate=True, owner=None, secure=False):
|
def get(uuid, invalidate=True, owner=None, secure=False):
|
||||||
@ -128,9 +128,7 @@ class TicketStore(UUIDModel):
|
|||||||
if t.stamp + validity < now:
|
if t.stamp + validity < now:
|
||||||
raise TicketStore.InvalidTicket('Not valid anymore')
|
raise TicketStore.InvalidTicket('Not valid anymore')
|
||||||
|
|
||||||
if secure is True:
|
# if secure: TODO
|
||||||
data = pickle.loads(cryptoManager().decrypt(t.data))
|
|
||||||
else:
|
|
||||||
data = pickle.loads(t.data)
|
data = pickle.loads(t.data)
|
||||||
|
|
||||||
# If has validator, execute it
|
# If has validator, execute it
|
||||||
@ -161,10 +159,13 @@ class TicketStore(UUIDModel):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def cleanup():
|
def cleanup():
|
||||||
|
from datetime import timedelta
|
||||||
now = getSqlDatetime()
|
now = getSqlDatetime()
|
||||||
|
for v in TicketStore.objects.all():
|
||||||
|
if now > v.stamp + timedelta(seconds=v.validity):
|
||||||
|
v.delete()
|
||||||
cleanSince = now - datetime.timedelta(seconds=TicketStore.MAX_VALIDITY)
|
cleanSince = now - datetime.timedelta(seconds=TicketStore.MAX_VALIDITY)
|
||||||
number = TicketStore.objects.filter(stamp__lt=cleanSince).delete()
|
number = TicketStore.objects.filter(stamp__lt=cleanSince).delete()
|
||||||
logger.debug('Cleaned {} tickets'.format(number))
|
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
if self.validator is not None:
|
if self.validator is not None:
|
||||||
|
@ -44,6 +44,7 @@ from uds.core.transports.BaseTransport import TUNNELED_GROUP
|
|||||||
from uds.core.transports import protocols
|
from uds.core.transports import protocols
|
||||||
from uds.core.util import connection
|
from uds.core.util import connection
|
||||||
from uds.core.util import OsDetector
|
from uds.core.util import OsDetector
|
||||||
|
from uds.core.managers import cryptoManager
|
||||||
from uds.models import TicketStore
|
from uds.models import TicketStore
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
@ -192,12 +193,15 @@ class HTML5RDPTransport(Transport):
|
|||||||
if domain != '':
|
if domain != '':
|
||||||
username = domain + '\\' + username
|
username = domain + '\\' + username
|
||||||
|
|
||||||
|
scrambler = cryptoManager().randomString(32)
|
||||||
|
passwordCrypted = cryptoManager().xor(password, scrambler)
|
||||||
|
|
||||||
# Build params dict
|
# Build params dict
|
||||||
params = {
|
params = {
|
||||||
'protocol': 'rdp',
|
'protocol': 'rdp',
|
||||||
'hostname': ip,
|
'hostname': ip,
|
||||||
'username': username,
|
'username': username,
|
||||||
'password': password,
|
'password': passwordCrypted,
|
||||||
'ignore-cert': 'true',
|
'ignore-cert': 'true',
|
||||||
'security': self.security.value,
|
'security': self.security.value,
|
||||||
'drive-path': '/share/{}'.format(user.uuid),
|
'drive-path': '/share/{}'.format(user.uuid),
|
||||||
@ -229,4 +233,5 @@ class HTML5RDPTransport(Transport):
|
|||||||
|
|
||||||
ticket = TicketStore.create(params, validity=self.ticketValidity.num())
|
ticket = TicketStore.create(params, validity=self.ticketValidity.num())
|
||||||
|
|
||||||
return HttpResponseRedirect("{}/transport/?{}&{}".format(self.guacamoleServer.value, ticket, request.build_absolute_uri(reverse('Index'))))
|
return HttpResponseRedirect("{}/transport/?{}.{}&{}".format(self.guacamoleServer.value, ticket, scrambler, request.build_absolute_uri(reverse('Index'))))
|
||||||
|
|
||||||
|
@ -27,9 +27,9 @@
|
|||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
"""
|
'''
|
||||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
"""
|
'''
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from django.utils.translation import ugettext_noop as _
|
from django.utils.translation import ugettext_noop as _
|
||||||
from uds.core.managers.UserPrefsManager import CommonPrefs
|
from uds.core.managers.UserPrefsManager import CommonPrefs
|
||||||
@ -44,14 +44,14 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
READY_CACHE_TIMEOUT = 30
|
READY_CACHE_TIMEOUT = 30
|
||||||
|
|
||||||
__updated__ = '2018-05-18'
|
__updated__ = '2018-07-19'
|
||||||
|
|
||||||
|
|
||||||
class RDPTransport(BaseRDPTransport):
|
class RDPTransport(BaseRDPTransport):
|
||||||
"""
|
'''
|
||||||
Provides access via RDP to service.
|
Provides access via RDP to service.
|
||||||
This transport can use an domain. If username processed by authenticator contains '@', it will split it and left-@-part will be username, and right password
|
This transport can use an domain. If username processed by authenticator contains '@', it will split it and left-@-part will be username, and right password
|
||||||
"""
|
'''
|
||||||
typeName = _('RDP')
|
typeName = _('RDP')
|
||||||
typeType = 'RDPTransport'
|
typeType = 'RDPTransport'
|
||||||
typeDescription = _('RDP Protocol. Direct connection.')
|
typeDescription = _('RDP Protocol. Direct connection.')
|
||||||
@ -104,7 +104,7 @@ class RDPTransport(BaseRDPTransport):
|
|||||||
r.domain = domain
|
r.domain = domain
|
||||||
r.redirectPrinters = self.allowPrinters.isTrue()
|
r.redirectPrinters = self.allowPrinters.isTrue()
|
||||||
r.redirectSmartcards = self.allowSmartcards.isTrue()
|
r.redirectSmartcards = self.allowSmartcards.isTrue()
|
||||||
r.redirectDrives = self.allowDrives.isTrue()
|
r.redirectDrives = self.allowDrives.value
|
||||||
r.redirectHome = self.redirectHome.isTrue()
|
r.redirectHome = self.redirectHome.isTrue()
|
||||||
r.redirectSerials = self.allowSerials.isTrue()
|
r.redirectSerials = self.allowSerials.isTrue()
|
||||||
r.enableClipboard = self.allowClipboard.isTrue()
|
r.enableClipboard = self.allowClipboard.isTrue()
|
||||||
|
@ -27,9 +27,9 @@
|
|||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
"""
|
'''
|
||||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
"""
|
'''
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from django.utils.translation import ugettext_noop as _
|
from django.utils.translation import ugettext_noop as _
|
||||||
from uds.core.managers.UserPrefsManager import CommonPrefs
|
from uds.core.managers.UserPrefsManager import CommonPrefs
|
||||||
@ -48,7 +48,7 @@ import logging
|
|||||||
import random
|
import random
|
||||||
import string
|
import string
|
||||||
|
|
||||||
__updated__ = '2018-05-18'
|
__updated__ = '2018-07-19'
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -56,10 +56,10 @@ READY_CACHE_TIMEOUT = 30
|
|||||||
|
|
||||||
|
|
||||||
class TRDPTransport(BaseRDPTransport):
|
class TRDPTransport(BaseRDPTransport):
|
||||||
"""
|
'''
|
||||||
Provides access via RDP to service.
|
Provides access via RDP to service.
|
||||||
This transport can use an domain. If username processed by authenticator contains '@', it will split it and left-@-part will be username, and right password
|
This transport can use an domain. If username processed by authenticator contains '@', it will split it and left-@-part will be username, and right password
|
||||||
"""
|
'''
|
||||||
typeName = _('RDP')
|
typeName = _('RDP')
|
||||||
typeType = 'TSRDPTransport'
|
typeType = 'TSRDPTransport'
|
||||||
typeDescription = _('RDP Protocol. Tunneled connection.')
|
typeDescription = _('RDP Protocol. Tunneled connection.')
|
||||||
@ -132,7 +132,7 @@ class TRDPTransport(BaseRDPTransport):
|
|||||||
r.domain = domain
|
r.domain = domain
|
||||||
r.redirectPrinters = self.allowPrinters.isTrue()
|
r.redirectPrinters = self.allowPrinters.isTrue()
|
||||||
r.redirectSmartcards = self.allowSmartcards.isTrue()
|
r.redirectSmartcards = self.allowSmartcards.isTrue()
|
||||||
r.redirectDrives = self.allowDrives.isTrue()
|
r.redirectDrives = self.allowDrives.value
|
||||||
r.redirectHome = self.redirectHome.isTrue()
|
r.redirectHome = self.redirectHome.isTrue()
|
||||||
r.redirectSerials = self.allowSerials.isTrue()
|
r.redirectSerials = self.allowSerials.isTrue()
|
||||||
r.enableClipboard = self.allowClipboard.isTrue()
|
r.enableClipboard = self.allowClipboard.isTrue()
|
||||||
|
@ -10,8 +10,8 @@ from uds import tools # @UnresolvedImport
|
|||||||
|
|
||||||
import six
|
import six
|
||||||
|
|
||||||
thePass = six.binary_type('{m.password}'.encode('UTF-16LE'))
|
|
||||||
try:
|
try:
|
||||||
|
thePass = six.binary_type("""{m.password}""".encode('UTF-16LE'))
|
||||||
password = win32crypt.CryptProtectData(thePass, None, None, None, None, 0x01).encode('hex')
|
password = win32crypt.CryptProtectData(thePass, None, None, None, None, 0x01).encode('hex')
|
||||||
except Exception:
|
except Exception:
|
||||||
# Cannot encrypt for user, trying for machine
|
# Cannot encrypt for user, trying for machine
|
||||||
|
@ -21,8 +21,8 @@ if forwardThread.status == 2:
|
|||||||
|
|
||||||
tools.addTaskToWait(forwardThread)
|
tools.addTaskToWait(forwardThread)
|
||||||
|
|
||||||
thePass = six.binary_type('{m.password}'.encode('UTF-16LE'))
|
|
||||||
try:
|
try:
|
||||||
|
thePass = six.binary_type(sp['password'].encode('UTF-16LE'))
|
||||||
password = win32crypt.CryptProtectData(thePass, None, None, None, None, 0x01).encode('hex')
|
password = win32crypt.CryptProtectData(thePass, None, None, None, None, 0x01).encode('hex')
|
||||||
except Exception:
|
except Exception:
|
||||||
# Cannot encrypt for user, trying for machine
|
# Cannot encrypt for user, trying for machine
|
||||||
|
@ -152,7 +152,7 @@ def ticketAuth(request, ticketId):
|
|||||||
auth = data['auth']
|
auth = data['auth']
|
||||||
realname = data['realname']
|
realname = data['realname']
|
||||||
servicePool = data['servicePool']
|
servicePool = data['servicePool']
|
||||||
password = data['password']
|
password = cryptoManager().decrypt(data['password'])
|
||||||
transport = data['transport']
|
transport = data['transport']
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.error('Ticket stored is not valid')
|
logger.error('Ticket stored is not valid')
|
||||||
|
Loading…
Reference in New Issue
Block a user