1
0
mirror of https://github.com/dkmstr/openuds.git synced 2025-01-10 01:17:59 +03:00

chore: Generate random key for tunnel

This commit is contained in:
Adolfo Gómez García 2024-08-03 02:09:12 +02:00
parent cdb0f110cf
commit c04a40a468
No known key found for this signature in database
GPG Key ID: DD1ABF20724CDA23
6 changed files with 34 additions and 16 deletions

View File

@ -45,9 +45,8 @@ from .servers import ServerRegisterBase
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
MAX_SESSION_LENGTH = ( MAX_SESSION_LENGTH = 60 * 60 * 24 * 7 * 2 # Two weeks is max session length for a tunneled connection
60 * 60 * 24 * 7 * 2
) # Two weeks is max session length for a tunneled connection
# Enclosed methods under /tunnel path # Enclosed methods under /tunnel path
class TunnelTicket(Handler): class TunnelTicket(Handler):
@ -70,11 +69,7 @@ class TunnelTicket(Handler):
self._request.ip, self._request.ip,
) )
if ( if not is_trusted_source(self._request.ip) or len(self._args) != 3 or len(self._args[0]) != 48:
not is_trusted_source(self._request.ip)
or len(self._args) != 3
or len(self._args[0]) != 48
):
# Invalid requests # Invalid requests
raise exceptions.rest.AccessDenied() raise exceptions.rest.AccessDenied()
@ -92,11 +87,9 @@ class TunnelTicket(Handler):
# Try to get ticket from DB # Try to get ticket from DB
try: try:
user, user_service, host, port, extra = models.TicketStore.get_for_tunnel( user, user_service, host, port, extra, key = models.TicketStore.get_for_tunnel(self._args[0])
self._args[0]
)
host = host or '' host = host or ''
data = {} data: dict[str, typing.Any] = {}
if self._args[1][:4] == 'stop': if self._args[1][:4] == 'stop':
sent, recv = self._params['sent'], self._params['recv'] sent, recv = self._params['sent'], self._params['recv']
# Ensures extra exists... # Ensures extra exists...
@ -146,7 +139,7 @@ class TunnelTicket(Handler):
}, },
validity=MAX_SESSION_LENGTH, validity=MAX_SESSION_LENGTH,
) )
data = {'host': host, 'port': port, 'notify': notifyTicket} data = {'host': host, 'port': port, 'notify': notifyTicket, 'key': key}
return data return data
except Exception as e: except Exception as e:
@ -162,7 +155,11 @@ class TunnelRegister(ServerRegisterBase):
# Just a compatibility method for old tunnel servers # Just a compatibility method for old tunnel servers
def post(self) -> collections.abc.MutableMapping[str, typing.Any]: def post(self) -> collections.abc.MutableMapping[str, typing.Any]:
self._params['type'] = types.servers.ServerType.TUNNEL self._params['type'] = types.servers.ServerType.TUNNEL
self._params['os'] = self._params.get('os', types.os.KnownOS.LINUX.os_name()) # Legacy tunnels are always linux self._params['os'] = self._params.get(
'os', types.os.KnownOS.LINUX.os_name()
) # Legacy tunnels are always linux
self._params['version'] = '' # No version for legacy tunnels, does not respond to API requests from UDS self._params['version'] = '' # No version for legacy tunnels, does not respond to API requests from UDS
self._params['certificate'] = '' # No certificate for legacy tunnels, does not respond to API requests from UDS self._params['certificate'] = (
'' # No certificate for legacy tunnels, does not respond to API requests from UDS
)
return super().post() return super().post()

View File

@ -40,6 +40,7 @@ from django.utils.translation import gettext_noop as _
from uds import models from uds import models
from uds.core import consts, types from uds.core import consts, types
from uds.core.managers.crypto import CryptoManager
from uds.core.module import Module from uds.core.module import Module
from uds.core.util import net from uds.core.util import net
@ -213,6 +214,13 @@ class Transport(Module):
@return: transformed username @return: transformed username
""" """
return user.name return user.name
def generate_key(self, length: int = 32) -> str:
"""
Returns a random key of the requested length
Used for generate keys for the tunnel mainly, but can be used for other purposes
"""
return CryptoManager.manager().random_string(length)
def get_transport_script( def get_transport_script(
self, self,

View File

@ -220,6 +220,7 @@ class TicketStore(UUIDModel):
port: int, port: int,
host: typing.Optional[str] = None, host: typing.Optional[str] = None,
extra: typing.Optional[collections.abc.Mapping[str, typing.Any]] = None, extra: typing.Optional[collections.abc.Mapping[str, typing.Any]] = None,
key: typing.Optional[str] = None,
validity: int = 60 * 60 * 24, # 24 Hours default validity for tunnel tickets validity: int = 60 * 60 * 24, # 24 Hours default validity for tunnel tickets
) -> str: ) -> str:
owner = CryptoManager().random_string(length=8) owner = CryptoManager().random_string(length=8)
@ -231,6 +232,7 @@ class TicketStore(UUIDModel):
'h': host, 'h': host,
'p': port, 'p': port,
'e': extra, 'e': extra,
'k': key or '',
} }
return ( return (
# Note that the ticket is the uuid + owner, so we can encrypt data without keeping the key # Note that the ticket is the uuid + owner, so we can encrypt data without keeping the key
@ -254,6 +256,7 @@ class TicketStore(UUIDModel):
typing.Optional[str], typing.Optional[str],
int, int,
typing.Optional[collections.abc.Mapping[str, typing.Any]], typing.Optional[collections.abc.Mapping[str, typing.Any]],
str,
]: ]:
""" """
Returns the ticket for a tunneled connection Returns the ticket for a tunneled connection
@ -277,7 +280,7 @@ class TicketStore(UUIDModel):
if not host: if not host:
host = userservice.get_instance().get_ip() host = userservice.get_instance().get_ip()
return (user, userservice, host, data['p'], data['e']) return (user, userservice, host, data['p'], data['e'], data.get('k', ''))
except Exception as e: except Exception as e:
raise TicketStore.InvalidTicket(str(e)) raise TicketStore.InvalidTicket(str(e))

View File

@ -141,10 +141,12 @@ class TRDPTransport(BaseRDPTransport):
width, height = self.screen_size.value.split('x') width, height = self.screen_size.value.split('x')
depth = self.color_depth.value depth = self.color_depth.value
key = self.generate_key()
ticket = TicketStore.create_for_tunnel( ticket = TicketStore.create_for_tunnel(
userService=userservice, userService=userservice,
port=self.rdp_port.as_int(), port=self.rdp_port.as_int(),
validity=self.tunnel_wait.as_int() + 60, # Ticket overtime validity=self.tunnel_wait.as_int() + 60, # Ticket overtime
key=key,
) )
tunnelFields = fields.get_tunnel_from_field(self.tunnel) tunnelFields = fields.get_tunnel_from_field(self.tunnel)
@ -187,6 +189,7 @@ class TRDPTransport(BaseRDPTransport):
'ticket': ticket, 'ticket': ticket,
'password': ci.password, 'password': ci.password,
'this_server': request.build_absolute_uri('/'), 'this_server': request.build_absolute_uri('/'),
'tunnel_key': key,
} }
if os.os == types.os.KnownOS.WINDOWS: if os.os == types.os.KnownOS.WINDOWS:

View File

@ -122,11 +122,13 @@ class TSPICETransport(BaseSpiceTransport):
userservice, transport, ip, os, user, password, request userservice, transport, ip, os, user, password, request
) )
key = self.generate_key()
if con.port: if con.port:
ticket = TicketStore.create_for_tunnel( ticket = TicketStore.create_for_tunnel(
userService=userservice, userService=userservice,
port=int(con.port), port=int(con.port),
validity=self.tunnel_wait.as_int() + 60, # Ticket overtime validity=self.tunnel_wait.as_int() + 60, # Ticket overtime
key=key,
) )
if con.secure_port: if con.secure_port:
@ -135,6 +137,7 @@ class TSPICETransport(BaseSpiceTransport):
port=int(con.secure_port), port=int(con.secure_port),
host=con.address, host=con.address,
validity=self.tunnel_wait.as_int() + 60, # Ticket overtime validity=self.tunnel_wait.as_int() + 60, # Ticket overtime
key=key,
) )
r = RemoteViewerFile( r = RemoteViewerFile(
@ -164,6 +167,7 @@ class TSPICETransport(BaseSpiceTransport):
'tunChk': self.verify_certificate.as_bool(), 'tunChk': self.verify_certificate.as_bool(),
'ticket': ticket, 'ticket': ticket,
'ticket_secure': ticket_secure, 'ticket_secure': ticket_secure,
'tunnel_key': key,
} }
try: try:

View File

@ -129,10 +129,12 @@ class TX2GOTransport(BaseX2GOTransport):
user=ci.username, user=ci.username,
) )
key = self.generate_key()
ticket = TicketStore.create_for_tunnel( ticket = TicketStore.create_for_tunnel(
userService=userservice, userService=userservice,
port=22, port=22,
validity=self.tunnel_wait.as_int() + 60, # Ticket overtime validity=self.tunnel_wait.as_int() + 60, # Ticket overtime
key=key,
) )
tunnelFields = fields.get_tunnel_from_field(self.tunnel) tunnelFields = fields.get_tunnel_from_field(self.tunnel)
@ -145,6 +147,7 @@ class TX2GOTransport(BaseX2GOTransport):
'tunChk': self.verify_certificate.as_bool(), 'tunChk': self.verify_certificate.as_bool(),
'ticket': ticket, 'ticket': ticket,
'key': private_key, 'key': private_key,
'tunnel_key': key,
'xf': xf, 'xf': xf,
} }