1
0
mirror of https://github.com/dkmstr/openuds.git synced 2024-12-21 09:34:08 +03:00

Merge remote-tracking branch 'origin/v3.6'

This commit is contained in:
Adolfo Gómez García 2023-04-10 18:07:32 +02:00
commit d55c0e9593
No known key found for this signature in database
GPG Key ID: DD1ABF20724CDA23
6 changed files with 84 additions and 13 deletions

View File

@ -51,6 +51,19 @@ from .log import logger
# Server before this version uses "unsigned" scripts
OLD_METHOD_VERSION = '2.4.0'
SECURE_CIPHERS = (
'TLS_AES_256_GCM_SHA384'
':TLS_CHACHA20_POLY1305_SHA256'
':TLS_AES_128_GCM_SHA256'
':ECDHE-RSA-AES256-GCM-SHA384'
':ECDHE-RSA-AES128-GCM-SHA256'
':ECDHE-RSA-CHACHA20-POLY1305'
':ECDHE-ECDSA-AES128-GCM-SHA256'
':ECDHE-ECDSA-AES256-GCM-SHA384'
':ECDHE-ECDSA-AES128-SHA256'
':ECDHE-ECDSA-CHACHA20-POLY1305'
)
# Callback for error on cert
# parameters are hostname, serial
# If returns True, ignores error
@ -72,7 +85,6 @@ class InvalidVersion(UDSException):
super().__init__(downloadUrl)
self.downloadUrl = downloadUrl
class RestApi:
_restApiUrl: str # base Rest API URL
@ -186,6 +198,7 @@ class RestApi:
ctx.verify_mode = ssl.CERT_NONE
# Disable SSLv2, SSLv3, TLSv1, TLSv1.1
ctx.minimum_version = ssl.TLSVersion.TLSv1_2
ctx.set_ciphers(SECURE_CIPHERS)
# If we have the certificates file, we use it
if tools.getCaCertsFile() is not None:

View File

@ -163,6 +163,23 @@ SECRET_KEY = 's5ky!7b5f#s35!e38xv%e-+iey6yi-#630x)kk3kk5_j8rie2*'
# This is a very long string, an RSA KEY (this can be changed, but if u loose it, all encription will be lost)
RSA_KEY = '-----BEGIN RSA PRIVATE KEY-----\nMIICXgIBAAKBgQC0qe1GlriQbHFYdKYRPBFDSS8Ne/TEKI2mtPKJf36XZTy6rIyH\nvUpT1gMScVjHjOISLNJQqktyv0G+ZGzLDmfkCUBev6JBlFwNeX3Dv/97Q0BsEzJX\noYHiDANUkuB30ukmGvG0sg1v4ccl+xs2Su6pFSc5bGINBcQ5tO0ZI6Q1nQIDAQAB\nAoGBAKA7Octqb+T/mQOX6ZXNjY38wXOXJb44LXHWeGnEnvUNf/Aci0L0epCidfUM\nfG33oKX4BMwwTVxHDrsa/HaXn0FZtbQeBVywZqMqWpkfL/Ho8XJ8Rsq8OfElrwek\nOCPXgxMzQYxoNHw8V97k5qhfupQ+h878BseN367xSyQ8plahAkEAuPgAi6aobwZ5\nFZhx/+6rmQ8sM8FOuzzm6bclrvfuRAUFa9+kMM2K48NAneAtLPphofqI8wDPCYgQ\nTl7O96GXVQJBAPoKtWIMuBHJXKCdUNOISmeEvEzJMPKduvyqnUYv17tM0JTV0uzO\nuDpJoNIwVPq5c3LJaORKeCZnt3dBrdH1FSkCQQC3DK+1hIvhvB0uUvxWlIL7aTmM\nSny47Y9zsc04N6JzbCiuVdeueGs/9eXHl6f9gBgI7eCD48QAocfJVygphqA1AkEA\nrvzZjcIK+9+pJHqUO0XxlFrPkQloaRK77uHUaW9IEjui6dZu4+2T/q7SjubmQgWR\nZy7Pap03UuFZA2wCoqJbaQJAUG0FVrnyUORUnMQvdDjAWps2sXoPvA8sbQY1W8dh\nR2k4TCFl2wD7LutvsdgdkiH0gWdh5tc1c4dRmSX1eQ27nA==\n-----END RSA PRIVATE KEY-----'
# Trusted cyphers
SECURE_CIPHERS = (
'TLS_AES_256_GCM_SHA384'
':TLS_CHACHA20_POLY1305_SHA256'
':TLS_AES_128_GCM_SHA256'
':ECDHE-RSA-AES256-GCM-SHA384'
':ECDHE-RSA-AES128-GCM-SHA256'
':ECDHE-RSA-CHACHA20-POLY1305'
':ECDHE-ECDSA-AES128-GCM-SHA256'
':ECDHE-ECDSA-AES256-GCM-SHA384'
':ECDHE-ECDSA-AES128-SHA256'
':ECDHE-ECDSA-CHACHA20-POLY1305'
)
# Min TLS version
SECURE_MIN_TLS_VERSION = '1.2'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',

View File

@ -90,7 +90,7 @@ def _requestActor(
r = proxy.doProxyRequest(url=url, data=data, timeout=TIMEOUT)
else:
verify: typing.Union[bool, str]
cert = userService.getProperty('cert')
cert = userService.getProperty('cert') or ''
# cert = '' # Uncomment to test without cert
if cert:
# Generate temp file, and delete it after
@ -99,7 +99,7 @@ def _requestActor(
f.write(cert.encode()) # Save cert
else:
verify = False
session = secureRequestsSession(verify=bool(cert))
session = secureRequestsSession(verify=cert)
if data is None:
r = session.get(url, verify=verify, timeout=TIMEOUT)
else:

View File

@ -3,8 +3,10 @@ import random
from datetime import datetime, timedelta
import ipaddress
import typing
import logging
import ssl
from django.conf import settings
from cryptography import x509
from cryptography.x509.oid import NameOID
@ -16,9 +18,13 @@ import certifi
import requests
import requests.adapters
logger = logging.getLogger(__name__)
KEY_SIZE = 4096
SECRET_SIZE = 32
try:
# Ensure that we do not get warnings about self signed certificates and so
import requests.packages.urllib3 # type: ignore
@ -85,13 +91,21 @@ def createClientSslContext(verify: bool = True) -> ssl.SSLContext:
sslContext = ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH, cafile=certifi.where())
if not verify:
sslContext.check_hostname = False
sslContext.verify_mode = ssl.CERT_NONE
sslContext.verify_mode = ssl.VerifyMode.CERT_NONE
# Disable TLS1.0 and TLS1.1, SSLv2 and SSLv3 are disabled by default
# Next line is deprecated in Python 3.7
# sslContext.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3
sslContext.minimum_version = ssl.TLSVersion.TLSv1_2
if hasattr(settings, 'SECURE_MIN_TLS_VERSION') and settings.SECURE_MIN_TLS_VERSION:
# format is "1.0, 1.1, 1.2 or 1.3", convert to ssl.TLSVersion.TLSv1_0, ssl.TLSVersion.TLSv1_1, ssl.TLSVersion.TLSv1_2 or ssl.TLSVersion.TLSv1_3
sslContext.minimum_version = getattr(ssl.TLSVersion, 'TLSv' + settings.SECURE_MIN_TLS_VERSION.replace('.', '_'))
else:
sslContext.minimum_version = ssl.TLSVersion.TLSv1_2
sslContext.maximum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED
if hasattr(settings, 'SECURE_CIPHERS') and settings.SECURE_CIPHERS:
sslContext.set_ciphers(settings.SECURE_CIPHERS)
return sslContext
@ -126,7 +140,7 @@ def checkCertificateMatchPrivateKey(*, cert: str, key: str) -> bool:
# Even if the key or certificate is not valid, we only want a True if they match, False otherwise
return False
def secureRequestsSession(*, verify: bool = True) -> 'requests.Session':
def secureRequestsSession(*, verify: typing.Union[str, bool] = True) -> 'requests.Session':
'''
Generates a requests.Session object with a custom adapter that uses a custom SSLContext.
This is intended to be used for requests that need to be secure, but not necessarily verified.
@ -140,16 +154,36 @@ def secureRequestsSession(*, verify: bool = True) -> 'requests.Session':
'''
class UDSHTTPAdapter(requests.adapters.HTTPAdapter):
def init_poolmanager(self, *args, **kwargs) -> None:
sslContext = createClientSslContext(verify=verify)
# See urllib3.poolmanager.SSL_KEYWORDS for all available keys.
kwargs["ssl_context"] = sslContext
kwargs["ssl_context"] = createClientSslContext(verify=verify is True)
# See urllib3.poolmanager.SSL_KEYWORDS for all available keys.
return super().init_poolmanager(*args, **kwargs)
def cert_verify(self, conn, url, _, cert):
# Overridden to disable cert verification if verify is False
return super().cert_verify(conn, url, verify, cert)
def cert_verify(self, conn, url, lverify, cert) -> None:
"""Verify a SSL certificate. This method should not be called from user
code, and is only exposed for use when subclassing the
:class:`HTTPAdapter <requests.adapters.HTTPAdapter>`.
:param conn: The urllib3 connection object associated with the cert.
:param url: The requested URL.
:param verify: Either a boolean, in which case it controls whether we verify
the server's TLS certificate, or a string, in which case it must be a path
to a CA bundle to use
:param cert: The SSL certificate to verify.
"""
# If lverify is an string, use it even if verify is False
# if not, use verify value
if not isinstance(lverify, str):
lverify = verify
# logger.info('Connection info: %s', conn)
# for k, v in conn.__dict__.items():
# logger.info('Connection info: %s = %s', k, v)
super().cert_verify(conn, url, lverify, cert)
session = requests.Session()
session.mount("https://", UDSHTTPAdapter())

View File

@ -55,6 +55,7 @@ class ConfigurationType(typing.NamedTuple):
workers: int
ssl_min_tls_version: str # Valid values are 1.2, 1.3 (1.0 and 1.1 are not supported)
ssl_certificate: str
ssl_certificate_key: str
ssl_password: str
@ -131,6 +132,7 @@ def read(
listen_port=int(uds.get('port', '443')),
ipv6=uds.get('ipv6', 'false').lower() == 'true',
workers=int(uds.get('workers', '0')) or multiprocessing.cpu_count(),
ssl_min_tls_version=uds.get('ssl_min_tls_version', '1.2'),
ssl_certificate=uds['ssl_certificate'],
ssl_certificate_key=uds.get('ssl_certificate_key', ''),
ssl_password=uds.get('ssl_password', ''),

View File

@ -150,6 +150,11 @@ async def tunnel_proc_async(
context.load_cert_chain(**args)
# Set min version from string (1.2 or 1.3) as ssl.TLSVersion.TLSv1_2 or ssl.TLSVersion.TLSv1_3
if cfg.ssl_min_tls_version in ('1.2', '1.3'):
context.minimum_version = getattr(ssl.TLSVersion, f'TLSv1_{cfg.ssl_min_tls_version.split(".")[1]}')
# Any other value will be ignored
if cfg.ssl_ciphers:
context.set_ciphers(cfg.ssl_ciphers)