diff --git a/client/full/src/UDSClient.py b/client/full/src/UDSClient.py index a8186ed70..df0df10be 100755 --- a/client/full/src/UDSClient.py +++ b/client/full/src/UDSClient.py @@ -219,7 +219,7 @@ class UDSClient(QtGui.QMainWindow): QtCore.QTimer.singleShot(10000, self.getTransportData) except Exception as e: - logger.exception('Got exception executing script:') + #logger.exception('Got exception executing script:') self.showError(e) def endScript(self): diff --git a/client/full/src/uds/log.py b/client/full/src/uds/log.py index 417172423..8d015e5bd 100644 --- a/client/full/src/uds/log.py +++ b/client/full/src/uds/log.py @@ -46,7 +46,7 @@ logging.basicConfig( filename=logFile, filemode='a', format='%(levelname)s %(asctime)s %(message)s', - level=logging.DEBUG + level=logging.INFO ) logger = logging.getLogger('udsclient') diff --git a/server/src/uds/REST/methods/tickets.py b/server/src/uds/REST/methods/tickets.py index 42cfc0fb2..d58b64841 100644 --- a/server/src/uds/REST/methods/tickets.py +++ b/server/src/uds/REST/methods/tickets.py @@ -38,6 +38,7 @@ from uds.models import Authenticator from uds.models import DeployedService from uds.models import Transport from uds.models import TicketStore +from uds.core.managers import cryptoManager from uds.core.util.model import processUuid from uds.core.util import tools @@ -207,7 +208,7 @@ class Tickets(Handler): data = { 'username': username, - 'password': password, + 'password': cryptoManager().encrypt(password), 'realname': realname, 'groups': groups, 'auth': auth.uuid, diff --git a/server/src/uds/core/workers/SystemCleaners.py b/server/src/uds/core/workers/SystemCleaners.py index ad1003602..67973a14f 100644 --- a/server/src/uds/core/workers/SystemCleaners.py +++ b/server/src/uds/core/workers/SystemCleaners.py @@ -59,7 +59,7 @@ class CacheCleaner(Job): class TicketStoreCleaner(Job): - frecuency = 3600 * 12 # every twelve hours + frecuency = 60 # every minute (60 seconds) friendly_name = 'Ticket Storage Cleaner' def __init__(self, environment): diff --git a/server/src/uds/dispatchers/guacamole/views.py b/server/src/uds/dispatchers/guacamole/views.py index 04148c2dc..94fb39277 100644 --- a/server/src/uds/dispatchers/guacamole/views.py +++ b/server/src/uds/dispatchers/guacamole/views.py @@ -35,6 +35,7 @@ from __future__ import unicode_literals from django.http import HttpResponse from uds.models import TicketStore from uds.core.auths import auth +from uds.core.managers import cryptoManager import six import logging @@ -55,8 +56,11 @@ def dict2resp(dct): def guacamole(request, tunnelId): logger.debug('Received credentials request for tunnel id {0}'.format(tunnelId)) + tunnelId, scrambler = tunnelId.split('.') + try: val = TicketStore.get(tunnelId, invalidate=False) + val['password'] = cryptoManager().xor(val['password'], scrambler) response = dict2resp(val) except Exception: diff --git a/server/src/uds/models/TicketStore.py b/server/src/uds/models/TicketStore.py index a90b53a4a..c64845cd2 100644 --- a/server/src/uds/models/TicketStore.py +++ b/server/src/uds/models/TicketStore.py @@ -25,9 +25,9 @@ # 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 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -""" +''' .. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com -""" +''' from __future__ import unicode_literals @@ -45,7 +45,7 @@ import logging logger = logging.getLogger(__name__) -__updated__ = '2016-09-16' +__updated__ = '2018-07-19' class TicketStore(UUIDModel): @@ -78,7 +78,7 @@ class TicketStore(UUIDModel): @staticmethod def generateUuid(): - # more owner is this: + # more secure is this: # ''.join(random.SystemRandom().choice(string.ascii_lowercase + string.digits) for _ in range(40)) return cryptoManager().randomString(40) @@ -91,7 +91,7 @@ class TicketStore(UUIDModel): validator = pickle.dumps(validator) data = pickle.dumps(data) if secure: - data = cryptoManager().encrypt(data) + pass 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) if secure: - data = cryptoManager().encrypt() + pass try: - t = TicketStore.objects.get(uuid=uuid, owner=owner) - t.data = data + t = TicketStore.objects.get(uuid=uuid) + t.data = pickle.dumps(data) t.stamp = getSqlDatetime() t.validity = validity t.save() 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 def get(uuid, invalidate=True, owner=None, secure=False): @@ -128,10 +128,8 @@ class TicketStore(UUIDModel): if t.stamp + validity < now: raise TicketStore.InvalidTicket('Not valid anymore') - if secure is True: - data = pickle.loads(cryptoManager().decrypt(t.data)) - else: - data = pickle.loads(t.data) + # if secure: TODO + data = pickle.loads(t.data) # If has validator, execute it if t.validator is not None: @@ -161,10 +159,13 @@ class TicketStore(UUIDModel): @staticmethod def cleanup(): + from datetime import timedelta now = getSqlDatetime() - cleanSince = now - datetime.timedelta(seconds=TicketStore.MAX_VALIDITY) + for v in TicketStore.objects.all(): + if now > v.stamp + timedelta(seconds=v.validity): + v.delete() + cleanSince = now - datetime.timedelta(seconds=TicketStore.MAX_VALIDITY) number = TicketStore.objects.filter(stamp__lt=cleanSince).delete() - logger.debug('Cleaned {} tickets'.format(number)) def __unicode__(self): if self.validator is not None: diff --git a/server/src/uds/transports/HTML5RDP/HTML5RDP.py b/server/src/uds/transports/HTML5RDP/HTML5RDP.py index 56f93f9cc..f527eac85 100644 --- a/server/src/uds/transports/HTML5RDP/HTML5RDP.py +++ b/server/src/uds/transports/HTML5RDP/HTML5RDP.py @@ -44,6 +44,7 @@ from uds.core.transports.BaseTransport import TUNNELED_GROUP from uds.core.transports import protocols from uds.core.util import connection from uds.core.util import OsDetector +from uds.core.managers import cryptoManager from uds.models import TicketStore import logging @@ -192,12 +193,15 @@ class HTML5RDPTransport(Transport): if domain != '': username = domain + '\\' + username + scrambler = cryptoManager().randomString(32) + passwordCrypted = cryptoManager().xor(password, scrambler) + # Build params dict params = { 'protocol': 'rdp', 'hostname': ip, 'username': username, - 'password': password, + 'password': passwordCrypted, 'ignore-cert': 'true', 'security': self.security.value, 'drive-path': '/share/{}'.format(user.uuid), @@ -229,4 +233,5 @@ class HTML5RDPTransport(Transport): 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')))) + diff --git a/server/src/uds/transports/RDP/RDPTransport.py b/server/src/uds/transports/RDP/RDPTransport.py index 4df878e02..dbda8abdb 100644 --- a/server/src/uds/transports/RDP/RDPTransport.py +++ b/server/src/uds/transports/RDP/RDPTransport.py @@ -27,9 +27,9 @@ # 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. -""" +''' @author: Adolfo Gómez, dkmaster at dkmon dot com -""" +''' from __future__ import unicode_literals from django.utils.translation import ugettext_noop as _ from uds.core.managers.UserPrefsManager import CommonPrefs @@ -44,14 +44,14 @@ logger = logging.getLogger(__name__) READY_CACHE_TIMEOUT = 30 -__updated__ = '2018-05-18' +__updated__ = '2018-07-19' class RDPTransport(BaseRDPTransport): - """ + ''' 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 - """ + ''' typeName = _('RDP') typeType = 'RDPTransport' typeDescription = _('RDP Protocol. Direct connection.') @@ -104,7 +104,7 @@ class RDPTransport(BaseRDPTransport): r.domain = domain r.redirectPrinters = self.allowPrinters.isTrue() r.redirectSmartcards = self.allowSmartcards.isTrue() - r.redirectDrives = self.allowDrives.isTrue() + r.redirectDrives = self.allowDrives.value r.redirectHome = self.redirectHome.isTrue() r.redirectSerials = self.allowSerials.isTrue() r.enableClipboard = self.allowClipboard.isTrue() diff --git a/server/src/uds/transports/RDP/TRDPTransport.py b/server/src/uds/transports/RDP/TRDPTransport.py index 23ca9aae0..853b97f58 100644 --- a/server/src/uds/transports/RDP/TRDPTransport.py +++ b/server/src/uds/transports/RDP/TRDPTransport.py @@ -27,9 +27,9 @@ # 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. -""" +''' @author: Adolfo Gómez, dkmaster at dkmon dot com -""" +''' from __future__ import unicode_literals from django.utils.translation import ugettext_noop as _ from uds.core.managers.UserPrefsManager import CommonPrefs @@ -48,7 +48,7 @@ import logging import random import string -__updated__ = '2018-05-18' +__updated__ = '2018-07-19' logger = logging.getLogger(__name__) @@ -56,10 +56,10 @@ READY_CACHE_TIMEOUT = 30 class TRDPTransport(BaseRDPTransport): - """ + ''' 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 - """ + ''' typeName = _('RDP') typeType = 'TSRDPTransport' typeDescription = _('RDP Protocol. Tunneled connection.') @@ -132,7 +132,7 @@ class TRDPTransport(BaseRDPTransport): r.domain = domain r.redirectPrinters = self.allowPrinters.isTrue() r.redirectSmartcards = self.allowSmartcards.isTrue() - r.redirectDrives = self.allowDrives.isTrue() + r.redirectDrives = self.allowDrives.value r.redirectHome = self.redirectHome.isTrue() r.redirectSerials = self.allowSerials.isTrue() r.enableClipboard = self.allowClipboard.isTrue() diff --git a/server/src/uds/transports/RDP/scripts/windows/direct.py b/server/src/uds/transports/RDP/scripts/windows/direct.py index ce62b56d0..4f97403ce 100644 --- a/server/src/uds/transports/RDP/scripts/windows/direct.py +++ b/server/src/uds/transports/RDP/scripts/windows/direct.py @@ -10,8 +10,8 @@ from uds import tools # @UnresolvedImport import six -thePass = six.binary_type('{m.password}'.encode('UTF-16LE')) try: + thePass = six.binary_type("""{m.password}""".encode('UTF-16LE')) password = win32crypt.CryptProtectData(thePass, None, None, None, None, 0x01).encode('hex') except Exception: # Cannot encrypt for user, trying for machine diff --git a/server/src/uds/transports/RDP/scripts/windows/tunnel.py b/server/src/uds/transports/RDP/scripts/windows/tunnel.py index ff12de43c..ffedd52b2 100644 --- a/server/src/uds/transports/RDP/scripts/windows/tunnel.py +++ b/server/src/uds/transports/RDP/scripts/windows/tunnel.py @@ -21,8 +21,8 @@ if forwardThread.status == 2: tools.addTaskToWait(forwardThread) -thePass = six.binary_type('{m.password}'.encode('UTF-16LE')) try: + thePass = six.binary_type(sp['password'].encode('UTF-16LE')) password = win32crypt.CryptProtectData(thePass, None, None, None, None, 0x01).encode('hex') except Exception: # Cannot encrypt for user, trying for machine diff --git a/server/src/uds/web/views/auth.py b/server/src/uds/web/views/auth.py index 9389381f9..e262e86d0 100644 --- a/server/src/uds/web/views/auth.py +++ b/server/src/uds/web/views/auth.py @@ -152,7 +152,7 @@ def ticketAuth(request, ticketId): auth = data['auth'] realname = data['realname'] servicePool = data['servicePool'] - password = data['password'] + password = cryptoManager().decrypt(data['password']) transport = data['transport'] except Exception: logger.error('Ticket stored is not valid')