From e3cbc7ff286c3b5a362a310a028a7eb3badcc14e Mon Sep 17 00:00:00 2001 From: Ahmed TAHRI Date: Sun, 26 May 2024 07:58:18 +0200 Subject: [PATCH] improve support --ssl=[...] setting --- extras/man/http.1 | 3 ++- extras/man/https.1 | 3 ++- extras/profiling/benchmarks.py | 4 ++-- httpie/cli/definition.py | 5 +++-- httpie/ssl_.py | 27 ++++++++++++++++++++++++++- 5 files changed, 35 insertions(+), 7 deletions(-) diff --git a/extras/man/http.1 b/extras/man/http.1 index fd5a674828..ed69895f8a 100644 --- a/extras/man/http.1 +++ b/extras/man/http.1 @@ -570,9 +570,10 @@ installation (only the supported ones are shown here). A string in the OpenSSL cipher list format. +tls1.3 ciphers are always present regardless of your cipher list. -See `http \fB\,--help\/\fR` for the default ciphers list on you system. +See `http \fB\,--help\/\fR` for the default ciphers list. diff --git a/extras/man/https.1 b/extras/man/https.1 index ba3399d718..bdb0ef82a6 100644 --- a/extras/man/https.1 +++ b/extras/man/https.1 @@ -570,9 +570,10 @@ installation (only the supported ones are shown here). A string in the OpenSSL cipher list format. +tls1.3 ciphers are always present regardless of your cipher list. -See `http \fB\,--help\/\fR` for the default ciphers list on you system. +See `http \fB\,--help\/\fR` for the default ciphers list. diff --git a/extras/profiling/benchmarks.py b/extras/profiling/benchmarks.py index 04ea37a203..c262d46977 100644 --- a/extras/profiling/benchmarks.py +++ b/extras/profiling/benchmarks.py @@ -175,11 +175,11 @@ def run(self, context: Context) -> pyperf.Benchmark: for pretty in ['all', 'none']: CommandRunner( 'startup', - f'`http --pretty={pretty} httpbin.local:8888/stream/1000`', + f'`http --pretty={pretty} pie.dev/stream/1000`', [ '--print=HBhb', f'--pretty={pretty}', - 'httpbin.local:8888/stream/1000' + 'pie.dev/stream/1000' ] ) DownloadRunner('download', '`http --download :/big_file.txt` (3GB)', '3G') diff --git a/httpie/cli/definition.py b/httpie/cli/definition.py index 2a1a6c7072..7287eca6bb 100644 --- a/httpie/cli/definition.py +++ b/httpie/cli/definition.py @@ -906,12 +906,12 @@ def format_auth_help(auth_plugins_mapping, *, isolation_mode: bool = False): CIPHERS_CURRENT_DEFAULTS = ( """ - See `http --help` for the default ciphers list on you system. + See `http --help` for the default ciphers list. """ if IS_MAN_PAGE else f""" - By default, the following ciphers are used on your system: + By default, the following ciphers are used: {DEFAULT_SSL_CIPHERS_STRING} @@ -923,6 +923,7 @@ def format_auth_help(auth_plugins_mapping, *, isolation_mode: bool = False): help=f""" A string in the OpenSSL cipher list format. + tls1.3 ciphers are always present regardless of your cipher list. {CIPHERS_CURRENT_DEFAULTS} diff --git a/httpie/ssl_.py b/httpie/ssl_.py index 888be5540d..9dbd27005f 100644 --- a/httpie/ssl_.py +++ b/httpie/ssl_.py @@ -14,7 +14,7 @@ 'tls1': 'PROTOCOL_TLSv1', 'tls1.1': 'PROTOCOL_TLSv1_1', 'tls1.2': 'PROTOCOL_TLSv1_2', - 'tls1.3': 'PROTOCOL_TLSv1_3', + 'tls1.3': 'PROTOCOL_TLS_CLIENT', # CPython does not have a "PROTOCOL_TLSv1_3" constant, so, we'll improvise. } # todo: we'll need to update this in preparation for Python 3.13+ # could be a removal (after a long deprecation about constants @@ -104,6 +104,18 @@ def __init__( self._verify = None if ssl_version or ciphers: + # By default, almost all installed CPython have modern OpenSSL backends + # This actively prevent folks to negotiate "almost" dead TLS protocols + # HTTPie wants to help users when they explicitly expect "old" TLS support + # Common errors for user if not set: + # >- [SSL: NO_CIPHERS_AVAILABLE] no ciphers available + # >- [SSL: LEGACY_SIGALG_DISALLOWED_OR_UNSUPPORTED] legacy sigalg disallowed or unsupported + if ssl_version in {ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1} and ciphers is None: + # Please do not raise a "security" concern for that line. + # If the interpreter reach that line, it means that the user willingly set + # an unsafe TLS protocol. + ciphers = "DEFAULT:@SECLEVEL=0" + # Only set the custom context if user supplied one. # Because urllib3-future set his own secure ctx with a set of # ciphers (moz recommended list). thus avoiding excluding QUIC @@ -142,6 +154,19 @@ def _create_ssl_context( ssl_version: str = None, ciphers: str = None, ) -> 'ssl.SSLContext': + # HTTPie will take `ssl.PROTOCOL_TLS_CLIENT` as TLS 1.3 enforced! + # This piece of code is only triggered if user supplied --ssl=tls1.3 + if ssl_version is ssl.PROTOCOL_TLS_CLIENT: + return create_urllib3_context( + ciphers=ciphers, + ssl_minimum_version=ssl.TLSVersion.TLSv1_3, + ssl_maximum_version=ssl.TLSVersion.TLSv1_3, + # Since we are using a custom SSL context, we need to pass this + # here manually, even though it’s also passed to the connection + # in `super().cert_verify()`. + cert_reqs=ssl.CERT_REQUIRED if verify else ssl.CERT_NONE + ) + return create_urllib3_context( ciphers=ciphers, ssl_version=resolve_ssl_version(ssl_version),